bool CASW_BaseAI_Senses::WaitingUntilSeen( CBaseEntity *pSightEnt ) { if ( GetOuter()->GetSpawnFlags() & SF_NPC_WAIT_TILL_SEEN ) { // asw, wake up if marines see us (not players) if ( pSightEnt && pSightEnt->Classify() == CLASS_ASW_MARINE ) { CBaseCombatCharacter *pBCC = dynamic_cast<CBaseCombatCharacter*>( pSightEnt ); Vector zero = Vector(0,0,0); // don't link this client in the list if the npc is wait till seen and the player isn't facing the npc if (// && pPlayer->FVisible( GetOuter() ) pBCC->FInViewCone( GetOuter() ) && FBoxVisible( pSightEnt, static_cast<CBaseEntity*>(GetOuter()), zero ) ) { // marine sees us, become normal now. GetOuter()->RemoveSpawnFlags( SF_NPC_WAIT_TILL_SEEN ); return false; } } return true; } return false; }
bool CAI_Senses::WaitingUntilSeen( CBaseEntity *pSightEnt ) { CEntity *cent = CEntity::Instance(pSightEnt); if ( GetOuter()->m_spawnflags & SF_NPC_WAIT_TILL_SEEN ) { if ( cent->IsPlayer() ) { CPlayer *pPlayer = ToBasePlayer( cent ); Vector zero = Vector(0,0,0); // don't link this client in the list if the npc is wait till seen and the player isn't facing the npc if ( pPlayer // && pPlayer->FVisible( GetOuter() ) && pPlayer->FInViewCone_Entity( GetOuter()->BaseEntity() ) && FBoxVisible( cent, static_cast<CEntity*>(GetOuter()), zero ) ) { // player sees us, become normal now. GetOuter()->m_spawnflags &= ~SF_NPC_WAIT_TILL_SEEN; return false; } } return true; } return false; }
void CBaseTurret::ActiveThink(void) { int fAttack = 0; Vector vecDirToEnemy; pev->nextthink = gpGlobals->time + 0.1; StudioFrameAdvance( ); if ((!m_iOn) || (m_hEnemy == NULL)) { m_hEnemy = NULL; m_flLastSight = gpGlobals->time + m_flMaxWait; SetThink(&CBaseTurret::SearchThink); return; } // if it's dead, look for something new if ( !m_hEnemy->IsAlive() ) { if (!m_flLastSight) { m_flLastSight = gpGlobals->time + 0.5; // continue-shooting timeout } else { if (gpGlobals->time > m_flLastSight) { m_hEnemy = NULL; m_flLastSight = gpGlobals->time + m_flMaxWait; SetThink(&CBaseTurret::SearchThink); return; } } } Vector vecMid = pev->origin + pev->view_ofs; Vector vecMidEnemy = m_hEnemy->BodyTarget( vecMid ); // Look for our current enemy int fEnemyVisible = FBoxVisible(pev, m_hEnemy->pev, vecMidEnemy ); vecDirToEnemy = vecMidEnemy - vecMid; // calculate dir and dist to enemy float flDistToEnemy = vecDirToEnemy.Length(); Vector vec = UTIL_VecToAngles(vecMidEnemy - vecMid); // Current enmey is not visible. if (!fEnemyVisible || (flDistToEnemy > TURRET_RANGE)) { if (!m_flLastSight) m_flLastSight = gpGlobals->time + 0.5; else { // Should we look for a new target? if (gpGlobals->time > m_flLastSight) { m_hEnemy = NULL; m_flLastSight = gpGlobals->time + m_flMaxWait; SetThink(&CBaseTurret::SearchThink); return; } } fEnemyVisible = 0; } else { m_vecLastSight = vecMidEnemy; } UTIL_MakeAimVectors(m_vecCurAngles); /* ALERT( at_console, "%.0f %.0f : %.2f %.2f %.2f\n", m_vecCurAngles.x, m_vecCurAngles.y, gpGlobals->v_forward.x, gpGlobals->v_forward.y, gpGlobals->v_forward.z ); */ Vector vecLOS = vecDirToEnemy; //vecMid - m_vecLastSight; vecLOS = vecLOS.Normalize(); // Is the Gun looking at the target if (DotProduct(vecLOS, gpGlobals->v_forward) <= 0.866) // 30 degree slop fAttack = FALSE; else fAttack = TRUE; // fire the gun if (m_iSpin && ((fAttack) || (m_fBeserk))) { Vector vecSrc, vecAng; GetAttachment( 0, vecSrc, vecAng ); SetTurretAnim(TURRET_ANIM_FIRE); Shoot(vecSrc, gpGlobals->v_forward ); } else { SetTurretAnim(TURRET_ANIM_SPIN); } //move the gun if (m_fBeserk) { if (RANDOM_LONG(0,9) == 0) { m_vecGoalAngles.y = RANDOM_FLOAT(0,360); m_vecGoalAngles.x = RANDOM_FLOAT(0,90) - 90 * m_iOrientation; TakeDamage(pev,pev,1, DMG_GENERIC); // don't beserk forever return; } } else if (fEnemyVisible) { if (vec.y > 360) vec.y -= 360; if (vec.y < 0) vec.y += 360; //ALERT(at_console, "[%.2f]", vec.x); if (vec.x < -180) vec.x += 360; if (vec.x > 180) vec.x -= 360; // now all numbers should be in [1...360] // pin to turret limitations to [-90...15] if (m_iOrientation == 0) { if (vec.x > 90) vec.x = 90; else if (vec.x < m_iMinPitch) vec.x = m_iMinPitch; } else { if (vec.x < -90) vec.x = -90; else if (vec.x > -m_iMinPitch) vec.x = -m_iMinPitch; } // ALERT(at_console, "->[%.2f]\n", vec.x); m_vecGoalAngles.y = vec.y; m_vecGoalAngles.x = vec.x; } SpinUpCall(); MoveTurret(); }
void AvHTurret::ActiveThink(void) { PROFILE_START() // Advance model frame StudioFrameAdvance(); // Find enemy, or reacquire dead enemy this->UpdateEnemy(); // If we have a valid enemy if(!FNullEnt(this->m_hEnemy)) { // If enemy is in FOV Vector theVecMid = this->pev->origin + this->pev->view_ofs; //AvHSUPlayParticleEvent("JetpackEffect", this->edict(), theVecMid); CBaseEntity* theEnemyEntity = this->m_hEnemy; Vector theVecMidEnemy = theEnemyEntity->BodyTarget(theVecMid); //AvHSUPlayParticleEvent("JetpackEffect", theEnemyEntity->edict(), theVecMidEnemy); // calculate dir and dist to enemy Vector theVecDirToEnemy = theVecMidEnemy - theVecMid; Vector theAddition = theVecMid + theVecDirToEnemy; Vector theVecLOS = theVecDirToEnemy.Normalize(); // Update our goal angles to direction to enemy Vector theVecDirToEnemyAngles; VectorAngles(theVecDirToEnemy, theVecDirToEnemyAngles); // Set goal quaternion this->mGoalQuat = Quat(theVecDirToEnemyAngles); // Is the turret looking at the target yet? float theRadians = (this->GetVerticalFOV()/180.0f)*3.1415f; float theCosVerticalFOV = cos(theRadians); Vector theCurrentAngles; this->mCurQuat.GetAngles(theCurrentAngles); UTIL_MakeAimVectors(theCurrentAngles); if(DotProduct(theVecLOS, gpGlobals->v_forward) > theCosVerticalFOV) { // If enemy is visible bool theEnemyVisible = FBoxVisible(this->pev, this->m_hEnemy->pev, theVecMidEnemy) || !this->GetRequiresLOS(); if(theEnemyVisible && this->m_hEnemy->IsAlive()) { // If it's time to attack if((this->mTimeOfNextAttack == -1) || (gpGlobals->time >= this->mTimeOfNextAttack)) { // Shoot and play shoot animation Shoot(theVecMid, theVecDirToEnemy, theEnemyEntity->pev->velocity); this->PlayAnimationAtIndex(this->GetActiveAnimation()); // Set time for next attack this->SetNextAttack(); } // spin the barrel when acquired but not firing else if(this->GetBaseClassAnimatesTurret()) { this->pev->sequence = 2; ResetSequenceInfo(); } } } // Set next active think this->pev->nextthink = gpGlobals->time + kTurretThinkInterval; } // else we have no enemy, go back to search think else { SetThink(&AvHTurret::SearchThink); this->pev->nextthink = gpGlobals->time + kTurretThinkInterval; } this->TurretUpdate(); PROFILE_END(kAvHTurretActiveThink) }
//========================================================= // ActiveThink - //========================================================= void CNPC_BaseTurret::ActiveThink(void) { int fAttack = 0; SetNextThink( gpGlobals->curtime + 0.1 ); StudioFrameAdvance( ); if ( (!m_iOn) || (GetEnemy() == NULL) ) { SetEnemy( NULL ); m_flLastSight = gpGlobals->curtime + m_flMaxWait; SetThink(&CNPC_BaseTurret::SearchThink); return; } // if it's dead, look for something new if ( !GetEnemy()->IsAlive() ) { if (!m_flLastSight) { m_flLastSight = gpGlobals->curtime + 0.5; // continue-shooting timeout } else { if (gpGlobals->curtime > m_flLastSight) { SetEnemy( NULL ); m_flLastSight = gpGlobals->curtime + m_flMaxWait; SetThink(&CNPC_BaseTurret::SearchThink); return; } } } Vector vecMid = GetAbsOrigin() + GetViewOffset(); Vector vecMidEnemy = GetEnemy()->BodyTarget( vecMid, false ); // Look for our current enemy int fEnemyVisible = FBoxVisible(this, GetEnemy(), vecMidEnemy ); //We want to look at the enemy's eyes so we don't jitter Vector vecDirToEnemyEyes = vecMidEnemy - vecMid; float flDistToEnemy = vecDirToEnemyEyes.Length(); VectorNormalize( vecDirToEnemyEyes ); QAngle vecAnglesToEnemy; VectorAngles( vecDirToEnemyEyes, vecAnglesToEnemy ); // Current enmey is not visible. if (!fEnemyVisible || (flDistToEnemy > TURRET_RANGE)) { if (!m_flLastSight) m_flLastSight = gpGlobals->curtime + 0.5; else { // Should we look for a new target? if (gpGlobals->curtime > m_flLastSight) { SetEnemy( NULL ); m_flLastSight = gpGlobals->curtime + m_flMaxWait; SetThink(&CNPC_BaseTurret::SearchThink); return; } } fEnemyVisible = 0; } else { m_vecLastSight = vecMidEnemy; } //ALERT( at_console, "%.0f %.0f : %.2f %.2f %.2f\n", // m_vecCurAngles.x, m_vecCurAngles.y, // gpGlobals->v_forward.x, gpGlobals->v_forward.y, gpGlobals->v_forward.z ); Vector vecLOS = vecDirToEnemyEyes; //vecMid - m_vecLastSight; VectorNormalize( vecLOS ); Vector vecMuzzle, vecMuzzleDir; QAngle vecMuzzleAng; GetAttachment( 1, vecMuzzle, vecMuzzleAng ); AngleVectors( vecMuzzleAng, &vecMuzzleDir ); // Is the Gun looking at the target if (DotProduct(vecLOS, vecMuzzleDir) <= 0.866) // 30 degree slop fAttack = FALSE; else fAttack = TRUE; //forward // NDebugOverlay::Line(vecMuzzle, vecMid + ( vecMuzzleDir * 200 ), 255,0,0, false, 0.1); //LOS // NDebugOverlay::Line(vecMuzzle, vecMid + ( vecLOS * 200 ), 0,0,255, false, 0.1); // fire the gun if (m_iSpin && ((fAttack) || (m_fBeserk))) { Vector vecOrigin; QAngle vecAngles; GetAttachment( 1, vecOrigin, vecAngles ); Shoot(vecOrigin, vecMuzzleDir ); SetTurretAnim(TURRET_ANIM_FIRE); } else { SetTurretAnim(TURRET_ANIM_SPIN); } //move the gun if (m_fBeserk) { if (random->RandomInt(0,9) == 0) { m_vecGoalAngles.y = random->RandomFloat(0,360); m_vecGoalAngles.x = random->RandomFloat(0,90) - 90 * m_iOrientation; CTakeDamageInfo info; info.SetAttacker(this); info.SetInflictor(this); info.SetDamage( 1 ); info.SetDamageType( DMG_GENERIC ); TakeDamage( info ); // don't beserk forever return; } } else if (fEnemyVisible) { if (vecAnglesToEnemy.y > 360) vecAnglesToEnemy.y -= 360; if (vecAnglesToEnemy.y < 0) vecAnglesToEnemy.y += 360; //ALERT(at_console, "[%.2f]", vec.x); if (vecAnglesToEnemy.x < -180) vecAnglesToEnemy.x += 360; if (vecAnglesToEnemy.x > 180) vecAnglesToEnemy.x -= 360; // now all numbers should be in [1...360] // pin to turret limitations to [-90...14] if (m_iOrientation == TURRET_ORIENTATION_FLOOR) { if (vecAnglesToEnemy.x > 90) vecAnglesToEnemy.x = 90; else if (vecAnglesToEnemy.x < m_iMinPitch) vecAnglesToEnemy.x = m_iMinPitch; } else { if (vecAnglesToEnemy.x < -90) vecAnglesToEnemy.x = -90; else if (vecAnglesToEnemy.x > -m_iMinPitch) vecAnglesToEnemy.x = -m_iMinPitch; } //DevMsg( 1, "->[%.2f]\n", vec.x); m_vecGoalAngles.y = vecAnglesToEnemy.y; m_vecGoalAngles.x = vecAnglesToEnemy.x; } SpinUpCall(); MoveTurret(); }
bool CBaseBot::FindEnemy() { // check if the health is decreased bool fHealthDecreased = m_iPrevHealth > GetHealth(); m_iPrevHealth = GetHealth(); // store away the current health value float cur_dist; if (m_pEnemy && (!m_pEnemy->IsValid() || !m_pEnemy->IsAlive())) m_pEnemy = NULL; // null out the enemy pointer as it's no longer valid Vector vecHisPos; unsigned char cHit; // see if we can still see the current enemy... if (m_pEnemy) { if (FBoxVisible(m_pEnemy, &vecHisPos, &cHit)) { m_vecEnemy = vecHisPos; m_ucVisibility = cHit; } else { m_pEnemy = NULL; // we can no longer see this enemy } } // if we already have an enemy... if (m_pEnemy) { // don't discard important enemies (bomb/flag/hostage carrier, VIP, etc) if (g_pServer->ClientIsImportant(EnemyClient())) return false; // calculate the distance to the enemy cur_dist = (m_pEnemy->GetOrigin() - GetOrigin()).Length(); } else { cur_dist = FLT_MAX; // just some crazy value } // loop through all the clients... for (int i = 0; i < g_pServer->GetMaxClients(); i++) { if (i == entindex() - 1 || (m_pEnemy && i == m_pEnemy->entindex() - 1)) continue; // skip myself and the current enemy CClient *pClient = g_pServer->m_rgpClients[i]; if (!pClient || !pClient->IsValid() || !pClient->IsAlive()) continue; float dist = (pClient->GetOrigin() - GetOrigin()).Length(); // if this enemy is further away than the current one... if (dist > cur_dist && !g_pServer->ClientIsImportant(pClient)) continue; // skip it if (dist > 900 + 4000 * ((GetDifficulty() - 1) / 4.0)) continue; // enemy is too far if (g_pServer->IsTeamplay() && GetTeam() == g_pServer->GetTeam(pClient)) continue; // skip our teammates float fov; // if the bot's health decreased or the enemy is shooting if (!m_pEnemy && (fHealthDecreased || pClient->IsShooting())) fov = 360; else fov = GetFov() * 2 - (GetFov() - (dist > GetFov() * 9 ? GetFov() * 9 : dist) / 9); // check if enemy is in the view cone if (!FInViewCone(pClient, fov)) continue; // enemy isn't in bot's view cone // check if enemy is visible if (!FBoxVisible(pClient, &vecHisPos, &cHit)) { continue; // skip this enemy } // if the enemy is quite far away, not shooting and the bot is not damaged if (!m_pEnemy && dist > 200 && !fHealthDecreased && !pClient->IsShooting()) { // if the bot isn't in the fov of the enemy and the bot doesn't really want to fight if (!pClient->FInViewCone(this, 120) /*&& BotWantsToRetreat()*/) continue; // skip this enemy } m_pEnemy = pClient; // found a new enemy m_vecEnemy = vecHisPos; m_ucVisibility = cHit; DebugMsg(DEBUG_BOTCOMBAT, "Found new enemy: %s", m_pEnemy->GetNetName()); return true; } return false; // no new enemy is found }