void CACBot::Spawn() { // Init all bot variabeles m_pMyEnt->nextprimary = 2 + rnd(5); // 2011jan18:ft: 2 == GUN_CARBINE, GUN_SHOTGUN, GUN_SUBGUN, GUN_SNIPER, GUN_ASSAULT - if CPISTOL is activated this needs a FIXME to rnd(6) m_pMyEnt->targetyaw = m_pMyEnt->targetpitch = 0.0f; m_pMyEnt->pBot = this; spawnplayer(m_pMyEnt); m_eCurrentBotState = STATE_NORMAL; m_iShootDelay = m_iChangeWeaponDelay = 0; m_iCheckEnvDelay = 0; m_vPrevOrigin = g_vecZero; m_iStuckCheckDelay = lastmillis + 250; m_bStuck = false; m_iStuckTime = 0; m_iStrafeTime = m_iStrafeCheckDelay = 0; m_iMoveDir = DIR_NONE; m_pPrevEnemy = NULL; m_iCombatNavTime = 0; m_iSPMoveTime = 0; m_iEnemySearchDelay = 0; m_bCombatJump = false; m_iCombatJumpDelay = 0; m_iHuntDelay = 0; m_vHuntLocation = m_vPrevHuntLocation = g_vecZero; m_pHuntTarget = NULL; m_fPrevHuntDist = 0.0f; m_iHuntLastTurnLessTime = m_iHuntPlayerUpdateTime = m_iHuntPauseTime = 0; m_iLastJumpPad = 0; m_pTargetEnt = NULL; m_iCheckTeleporterDelay = m_iCheckJumppadsDelay = 0; m_iCheckEntsDelay = 0; m_iCheckTriggersDelay = 0; m_iLookForWaypointTime = 0; m_iAimDelay = 0; m_fYawToTurn = m_fPitchToTurn = 0.0f; m_vGoal = m_vWaterGoal = g_vecZero; ResetWaypointVars(); }
entity *CACBot::SearchForFlags(bool bUseWPs, float flRange, float flMaxHeight) { /* Flags are scored on the following: - Distance */ float flDist; entity *pNewTargetFlag = NULL; waypoint_s *pWptNearBot = NULL, *pBestWpt = NULL; short sScore, sHighestScore = 0; vec vNewGoal = g_vecZero; if ((WaypointClass.m_iWaypointCount >= 1) && bUseWPs) pWptNearBot = GetNearestWaypoint(200.0f); #ifdef WP_FLOOD if (!pWptNearBot && bUseWPs) pWptNearBot = GetNearestFloodWP(64.0f); #endif loopv(ents) { sScore = 0; entity &e = ents[i]; if(!CanTakeFlag(e)) continue; //vec o = g_vecZero; vec o = vec(e.x, e.y, S(e.x, e.y)->floor + PLAYERHEIGHT + PLAYERABOVEEYE); if(!m_secure(gamemode) && e.attr2 >= 0 && e.attr2 < 2) { flaginfo &f = flaginfos[e.attr2]; // flaginfo &of = flaginfos[team_opposite(i)]; if(f.state == CTFF_DROPPED) { o = f.pos; o.z += PLAYERHEIGHT + PLAYERABOVEEYE; } } if(OUTBORD((int)o.x, (int)o.y)) continue; flDist = GetDistance(o); if (flDist > flRange) continue; // Score on distance float ff = flDist; if (ff > 100.0f) ff = 100.0f; sScore += ((100 - short(ff)) / 2); waypoint_s *pWptNearEnt = NULL; // If this flag entity isn't visible check if there is a nearby waypoint if (!IsReachable(o, flMaxHeight))//(!IsVisible(o)) { if (!pWptNearBot) continue; #ifdef WP_FLOOD if (pWptNearBot->pNode->iFlags & W_FL_FLOOD) pWptNearEnt = GetNearestFloodWP(o, 100.0f); else #endif pWptNearEnt = GetNearestWaypoint(o, 200.f); if (!pWptNearEnt) continue; } // Score on visibility if (pWptNearEnt == NULL) // Ent is visible sScore += 6; else sScore += 3; if(sScore > sHighestScore) { if (pWptNearEnt) pBestWpt = pWptNearEnt; else pBestWpt = NULL; // best flag doesn't need any waypoints vNewGoal = o; pNewTargetFlag = &e; } } if (pNewTargetFlag) { // Need waypoints to reach it? if (pBestWpt) { ResetWaypointVars(); SetCurrentWaypoint(pWptNearBot); SetCurrentGoalWaypoint(pBestWpt); } m_vGoal = vNewGoal; } return pNewTargetFlag; }
bool CACBot::HeadToTargetFlag() { if(m_pTargetFlag) { const vec o = m_vGoal; if(CanTakeFlag(*m_pTargetFlag) && (!UnderWater(m_pMyEnt->o) || !UnderWater(o))) { bool bIsVisible = false; if (m_pCurrentGoalWaypoint) { if ((GetDistance(o) <= 20.0f) && IsReachable(o, 1.0f)) bIsVisible = true; else if (HeadToGoal()) { //debugbeam(m_pMyEnt->o, m_pCurrentWaypoint->pNode->v_origin); //debugbeam(m_pMyEnt->o, // m_pCurrentGoalWaypoint->pNode->v_origin); AddDebugText("Using WPs for flag"); return true; } } else bIsVisible = IsVisible(o); if (bIsVisible) { if (m_pCurrentWaypoint || m_pCurrentGoalWaypoint) { condebug("flag is now visible"); ResetWaypointVars(); } float flHeightDiff = o.z - m_pMyEnt->o.z; bool bToHigh = false; if (Get2DDistance(o) <= 2.0f) { if (flHeightDiff >= 1.5f) { if (flHeightDiff <= JUMP_HEIGHT) { #ifndef RELEASE_BUILD char sz[64]; sprintf(sz, "Flag z diff: %f", o.z-m_pMyEnt->o.z); condebug(sz); #endif // Jump if close to ent and the ent is high m_pMyEnt->jumpnext = true; } else bToHigh = true; } } if (!bToHigh) { AimToVec(o); return true; } } } } return false; }
entity *CACBot::SearchForEnts(bool bUseWPs, float flRange, float flMaxHeight) { /* Entities are scored on the following things: - Visibility - For ammo: Need(ie has this bot much of this type or not) - distance */ float flDist; entity *pNewTargetEnt = NULL; waypoint_s *pWptNearBot = NULL, *pBestWpt = NULL; short sScore, sHighestScore = 0; if ((WaypointClass.m_iWaypointCount >= 1) && bUseWPs) pWptNearBot = GetNearestWaypoint(15.0f); #ifdef WP_FLOOD if (!pWptNearBot && bUseWPs) pWptNearBot = GetNearestFloodWP(5.0f); #endif loopv(ents) { sScore = 0; entity &e = ents[i]; vec o(e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight); if (!ents[i].spawned) continue; if (OUTBORD(e.x, e.y)) continue; bool bInteresting = false; short sAmmo = 0, sMaxAmmo = 0; switch(e.type) { case I_CLIPS: sMaxAmmo = ammostats[m_pMyEnt->secondary].max; bInteresting = (m_pMyEnt->ammo[m_pMyEnt->secondary]<sMaxAmmo); sAmmo = m_pMyEnt->ammo[m_pMyEnt->secondary]; break; case I_AMMO: sMaxAmmo = ammostats[m_pMyEnt->primary].max; bInteresting = (m_pMyEnt->ammo[m_pMyEnt->primary]<sMaxAmmo); sAmmo = m_pMyEnt->ammo[m_pMyEnt->primary]; break; case I_GRENADE: sMaxAmmo = ammostats[GUN_GRENADE].max; bInteresting = (m_pMyEnt->mag[GUN_GRENADE]<sMaxAmmo); sAmmo = -1; break; case I_HEALTH: sMaxAmmo = MAXHEALTH; bInteresting = (m_pMyEnt->health < sMaxAmmo); sAmmo = m_pMyEnt->health; break; case I_HELMET: case I_ARMOUR: sMaxAmmo = MAXARMOUR; bInteresting = (m_pMyEnt->armour < sMaxAmmo); sAmmo = m_pMyEnt->armour; break; case I_AKIMBO: bInteresting = !m_pMyEnt->akimbo; sAmmo = -1; break; }; if (!bInteresting) continue; // Not an interesting item, skip // Score on ammo and need // Akimbo & nade if (sAmmo == -1) { sScore += 75; // Bonus } else { // Calculate current percentage of max ammo float percent = ((float)sAmmo / (float)sMaxAmmo) * 100.0f; if (percent > 100.0f) percent = 100.0f; sScore += ((100 - short(percent))/2); } flDist = GetDistance(o); if (flDist > flRange) continue; // Score on distance float f = flDist; if (f > 100.0f) f = 100.0f; sScore += ((100 - short(f)) / 2); waypoint_s *pWptNearEnt = NULL; // If this entity isn't visible check if there is a nearby waypoint if (!IsReachable(o, flMaxHeight))//(!IsVisible(o)) { if (!pWptNearBot) continue; #ifdef WP_FLOOD if (pWptNearBot->pNode->iFlags & W_FL_FLOOD) pWptNearEnt = GetNearestFloodWP(o, 8.0f); else #endif pWptNearEnt = GetNearestWaypoint(o, 15.0f); if (!pWptNearEnt) continue; } // Score on visibility if (pWptNearEnt == NULL) // Ent is visible sScore += 30; else sScore += 15; if (sScore > sHighestScore) { // Found a valid wp near the bot and the ent,so...lets store it :) if (pWptNearEnt) pBestWpt = pWptNearEnt; else pBestWpt = NULL; // Best ent so far doesn't need any waypoints sHighestScore = sScore; pNewTargetEnt = &ents[i]; } } if (pNewTargetEnt) { // Need waypoints to reach it? if (pBestWpt) { ResetWaypointVars(); SetCurrentWaypoint(pWptNearBot); SetCurrentGoalWaypoint(pBestWpt); } m_vGoal.x = pNewTargetEnt->x; m_vGoal.y = pNewTargetEnt->y; m_vGoal.z = S(pNewTargetEnt->x, pNewTargetEnt->y)->floor+player1->eyeheight; } return pNewTargetEnt; }