bool CAI_LeadBehavior::CanSelectSchedule() { if ( !AI_GetSinglePlayer() || AI_GetSinglePlayer()->IsDead() ) return false; bool fAttacked = ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) ); bool fNonCombat = ( GetNpcState() == NPC_STATE_IDLE || GetNpcState() == NPC_STATE_ALERT ); return ( !fAttacked && (fNonCombat || m_args.bLeadDuringCombat) && HasGoal() ); }
void CParticleSystemQuery::GetLocalPlayerEyeVectors( Vector *pForward, Vector *pRight, Vector *pUp ) { #ifdef CLIENT_DLL // HACK_GETLOCALPLAYER_GUARD( "CParticleSystemQuery::GetLocalPlayerPos" ); int slot = GET_ACTIVE_SPLITSCREEN_SLOT(); ACTIVE_SPLITSCREEN_PLAYER_GUARD( slot ); C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if ( !pPlayer ) { *pForward = vec3_origin; *pRight = vec3_origin; *pUp = vec3_origin; return; } pPlayer->EyeVectors( pForward, pRight, pUp ); #else CBasePlayer *pPlayer = AI_GetSinglePlayer(); if ( !pPlayer ) { *pForward = vec3_origin; *pRight = vec3_origin; *pUp = vec3_origin; return; } pPlayer->EyeVectors( pForward, pRight, pUp ); #endif }
CBaseEntity *CAI_StandoffBehavior::GetPlayerLeader() { CBaseEntity *pPlayer = AI_GetSinglePlayer(); if ( pPlayer && GetOuter()->IRelationType( pPlayer ) == D_LI ) return pPlayer; return NULL; }
//------------------------------------------------------------------------ // Purpose: // Input : &inputdata - //----------------------------------------------------------------------------- void CScriptIntro::InputSetFOVBlendTime( inputdata_t &inputdata ) { // Cache our FOV starting point before we update our data here if ( m_flNextFOVBlendTime >= gpGlobals->curtime ) { // We're already in a blend, so capture where we are at this point in time m_iStartFOV = ScriptInfo_CalculateFOV( m_flFOVBlendStartTime, m_flNextFOVBlendTime, m_iStartFOV, m_iNextFOV, m_bAlternateFOV ); } else { // If we weren't blending, then we need to construct a proper starting point from scratch CBasePlayer *pPlayer = AI_GetSinglePlayer(); if ( pPlayer ) { m_iStartFOV = ( m_iFOV ) ? m_iFOV : pPlayer->GetFOV(); } else { m_iStartFOV = m_iFOV; } } m_flNextFOVBlendTime = gpGlobals->curtime + inputdata.value.Float(); m_flFOVBlendStartTime = gpGlobals->curtime; }
//----------------------------------------------------------------------------- // Purpose: // Input : &inputdata - //----------------------------------------------------------------------------- void CPropVehicleChoreoGeneric::InputEnterVehicleImmediate( inputdata_t &inputdata ) { if ( m_bEnterAnimOn ) return; // Try the activator first & use them if they are a player. CBasePlayer *pPlayer = ToBasePlayer( inputdata.pActivator ); if ( pPlayer == NULL ) { // Activator was not a player, just grab the singleplayer player. pPlayer = AI_GetSinglePlayer(); if ( pPlayer == NULL ) return; } if ( pPlayer->IsInAVehicle() ) { // Force the player out of whatever vehicle they are in. pPlayer->LeaveVehicle(); } // Force us to drop anything we're holding pPlayer->ForceDropOfCarriedPhysObjects(); pPlayer->GetInVehicle( GetServerVehicle(), VEHICLE_ROLE_DRIVER ); }
//----------------------------------------------------------------------------- // Purpose: Force the player to enter the vehicle. //----------------------------------------------------------------------------- void CPropVehicleChoreoGeneric::InputEnterVehicle( inputdata_t &inputdata ) { if ( m_bEnterAnimOn ) return; // Try the activator first & use them if they are a player. CBasePlayer *pPlayer = ToBasePlayer( inputdata.pActivator ); if ( pPlayer == NULL ) { // Activator was not a player, just grab the single-player player. pPlayer = AI_GetSinglePlayer(); if ( pPlayer == NULL ) return; } // Force us to drop anything we're holding pPlayer->ForceDropOfCarriedPhysObjects(); // FIXME: I hate code like this. I should really add a parameter to HandlePassengerEntry // to allow entry into locked vehicles bool bWasLocked = m_bLocked; m_bLocked = false; GetServerVehicle()->HandlePassengerEntry( pPlayer, true ); m_bLocked = bWasLocked; }
void CAI_LeadBehavior::BeginScheduleSelection() { SetTarget( AI_GetSinglePlayer() ); CAI_Expresser *pExpresser = GetOuter()->GetExpresser(); if ( pExpresser ) pExpresser->ClearSpokeConcept( TLK_LEAD_ARRIVAL ); }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- CAI_Hint *CAI_FearBehavior::FindFearWithdrawalDest() { CAI_Hint *pHint; CHintCriteria hintCriteria; CAI_BaseNPC *pOuter = GetOuter(); Assert(pOuter != NULL); hintCriteria.AddHintType( HINT_PLAYER_ALLY_FEAR_DEST ); hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE_TO_PLAYER | bits_HINT_NOT_CLOSE_TO_ENEMY /*| bits_HINT_NODE_IN_VIEWCONE | bits_HINT_NPC_IN_NODE_FOV*/ ); hintCriteria.AddIncludePosition( AI_GetSinglePlayer()->GetAbsOrigin(), ( ai_fear_player_dist.GetFloat() ) ); pHint = CAI_HintManager::FindHint( pOuter, hintCriteria ); if( pHint ) { // Reserve this node while I try to get to it. When I get there I will lock it. // Otherwise, if I fail to get there, the node will come available again soon. pHint->DisableForSeconds( 4.0f ); } #if 0 else { Msg("DID NOT FIND HINT\n"); NDebugOverlay::Cross3D( GetOuter()->WorldSpaceCenter(), 32, 255, 255, 0, false, 10.0f ); } #endif return pHint; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponStriderBuster::Detonate( void ) { CBaseEntity *pVictim = GetOwnerEntity(); if ( !m_bDud && pVictim ) { // Kill the strider (with magic effect) CBasePlayer *pPlayer = AI_GetSinglePlayer(); CTakeDamageInfo info( pPlayer, this, RandomVector( -100.0f, 100.0f ), GetAbsOrigin(), pVictim->GetHealth(), DMG_GENERIC ); pVictim->TakeDamage( info ); gamestats->Event_WeaponHit( ToBasePlayer( pPlayer ), true, GetClassname(), info ); // Tracker 62293: There's a bug where the inflictor/attacker are reversed when calling TakeDamage above so the player never gets // credit for the strider buster kills. The code has a bunch of assumptions lower level, so it's safer to just fix it here by // crediting a kill to the player directly. gamestats->Event_PlayerKilledOther( pPlayer, pVictim, info ); } m_OnDetonate.FireOutput( this, this ); // Explode if ( !m_bDud ) { CreateDestroyedEffect(); EmitSound( "Weapon_StriderBuster.Detonate" ); } else { DispatchParticleEffect( "striderbuster_explode_dummy_core", GetAbsOrigin(), GetAbsAngles() ); EmitSound( "Weapon_StriderBuster.Dud_Detonate" ); } // Go to bits! Shatter( pVictim ); }
void CNPC_Zombine::GatherGrenadeConditions( void ) { if ( m_iGrenadeCount <= 0 ) return; if ( g_flZombineGrenadeTimes > gpGlobals->curtime ) return; if ( m_flGrenadePullTime > gpGlobals->curtime ) return; if ( m_flSuperFastAttackTime >= gpGlobals->curtime ) return; if ( HasGrenade() ) return; if ( GetEnemy() == NULL ) return; if ( FVisible( GetEnemy() ) == false ) return; if ( IsSprinting() ) return; if ( IsOnFire() ) return; if ( IsRunningDynamicInteraction() == true ) return; if ( m_ActBusyBehavior.IsActive() ) return; CBasePlayer *pPlayer = AI_GetSinglePlayer(); if ( pPlayer && pPlayer->FVisible( this ) ) { float flLengthToPlayer = (pPlayer->GetAbsOrigin() - GetAbsOrigin()).Length(); float flLengthToEnemy = flLengthToPlayer; if ( pPlayer != GetEnemy() ) { flLengthToEnemy = ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin()).Length(); } if ( flLengthToPlayer <= GRENADE_PULL_MAX_DISTANCE && flLengthToEnemy <= GRENADE_PULL_MAX_DISTANCE ) { float flPullChance = 1.0f - ( flLengthToEnemy / GRENADE_PULL_MAX_DISTANCE ); m_flGrenadePullTime = gpGlobals->curtime + 0.5f; if ( flPullChance >= random->RandomFloat( 0.0f, 1.0f ) ) { g_flZombineGrenadeTimes = gpGlobals->curtime + 10.0f; SetCondition( COND_ZOMBINE_GRENADE ); } } } }
bool CNPC_Zombine::AllowedToSprint( void ) { if ( IsOnFire() ) return false; //If you're sprinting then there's no reason to sprint again. if ( IsSprinting() ) return false; int iChance = SPRINT_CHANCE_VALUE; CHL2_Player *pPlayer = dynamic_cast <CHL2_Player*> ( AI_GetSinglePlayer() ); if ( pPlayer ) { if ( HL2GameRules()->IsAlyxInDarknessMode() && pPlayer->FlashlightIsOn() == false ) { iChance = SPRINT_CHANCE_VALUE_DARKNESS; } //Bigger chance of this happening if the player is not looking at the zombie if ( pPlayer->FInViewCone( this ) == false ) { iChance *= 2; } } if ( HasGrenade() ) { iChance *= 4; } //Below 25% health they'll always sprint if ( ( GetHealth() > GetMaxHealth() * 0.5f ) ) { if ( IsStrategySlotRangeOccupied( SQUAD_SLOT_ZOMBINE_SPRINT1, SQUAD_SLOT_ZOMBINE_SPRINT2 ) == true ) return false; if ( random->RandomInt( 0, 100 ) > iChance ) return false; if ( m_flSprintRestTime > gpGlobals->curtime ) return false; } float flLength = ( GetEnemy()->WorldSpaceCenter() - WorldSpaceCenter() ).Length(); if ( flLength > MAX_SPRINT_DISTANCE ) return false; return true; }
//----------------------------------------------------------------------------- // Purpose: Blend the parameters to the specified value //----------------------------------------------------------------------------- void CEnvDOFController::UpdateParamBlend( void ) { // Update our focal target if we have one if ( m_hFocusTarget ) { CBasePlayer *pPlayer = AI_GetSinglePlayer(); float flDistToFocus = ( m_hFocusTarget->GetAbsOrigin() - pPlayer->GetAbsOrigin() ).Length(); m_flFarFocusDepth.GetForModify() = flDistToFocus + m_flFocusTargetRange; m_flFarBlurDepth.GetForModify() = m_flFarFocusDepth + BLUR_DEPTH; } SetThink( &CEnvDOFController::UpdateParamBlend ); SetNextThink( gpGlobals->curtime + 0.1f ); }
void CNPC_Dog::SetupThrowTarget( void ) { if ( m_hThrowTarget == NULL ) { #ifdef SecobMod__Enable_Fixed_Multiplayer_AI m_hThrowTarget = UTIL_GetNearestVisiblePlayer(this); #else m_hThrowTarget = AI_GetSinglePlayer(); #endif //SecobMod__Enable_Fixed_Multiplayer_AI } SetTarget( m_hThrowTarget ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CAI_PassengerBehaviorZombie::GatherConditions( void ) { BaseClass::GatherConditions(); // Always clear the base conditions ClearCondition( COND_CAN_MELEE_ATTACK1 ); // Behavior when outside the vehicle if ( GetPassengerState() == PASSENGER_STATE_OUTSIDE ) { if ( CanBeOnEnemyVehicle() && CanJumpToAttachToVehicle() ) { SetCondition( COND_CAN_RANGE_ATTACK1 ); } // Determine if we can latch on to the vehicle (out of sight) ClearCondition( COND_PASSENGER_ZOMBIE_CAN_ATTACH_TO_VEHICLE ); CBasePlayer *pPlayer = AI_GetSinglePlayer(); if ( pPlayer != NULL && GetOuter()->GetEnemy() == pPlayer && pPlayer->GetVehicleEntity() == m_hVehicle ) { // Can't be visible to the player and must be close enough bool bNotVisibleToPlayer = ( pPlayer->FInViewCone( GetOuter() ) == false ); float flDistSqr = ( pPlayer->GetAbsOrigin() - GetOuter()->GetAbsOrigin() ).LengthSqr(); bool bInRange = ( flDistSqr < Square(250.0f) ); if ( bNotVisibleToPlayer && bInRange ) { // We can latch on and "enter" the vehicle SetCondition( COND_PASSENGER_ZOMBIE_CAN_ATTACH_TO_VEHICLE ); } else if ( bNotVisibleToPlayer == false && flDistSqr < Square(128.0f) ) { // Otherwise just hit the vehicle in anger SetCondition( COND_CAN_MELEE_ATTACK1 ); } } } // Behavior when on the car if ( GetPassengerState() == PASSENGER_STATE_INSIDE ) { // Check for melee attack if ( GetOuter()->GetNextAttack() < gpGlobals->curtime ) { SetCondition( COND_CAN_MELEE_ATTACK1 ); } } }
Vector CParticleSystemQuery::GetLocalPlayerPos( void ) { #ifdef CLIENT_DLL C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if ( !pPlayer ) return vec3_origin; return pPlayer->WorldSpaceCenter(); #else CBasePlayer *pPlayer = AI_GetSinglePlayer(); if ( !pPlayer ) return vec3_origin; return pPlayer->WorldSpaceCenter(); #endif }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CAntlionGrub::SetNextThinkByDistance( void ) { CBasePlayer *pPlayer = AI_GetSinglePlayer(); if ( pPlayer == NULL ) { SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.5f, 3.0f ) ); return; } float flDistToPlayerSqr = ( GetAbsOrigin() - pPlayer->GetAbsOrigin() ).LengthSqr(); float scale = RemapValClamped( flDistToPlayerSqr, Square( 400 ), Square( 5000 ), 1.0f, 5.0f ); float time = random->RandomFloat( 1.0f, 3.0f ); SetNextThink( gpGlobals->curtime + ( time * scale ) ); }
Vector CParticleSystemQuery::GetLocalPlayerPos( void ) { #ifdef CLIENT_DLL // HACK_GETLOCALPLAYER_GUARD( "CParticleSystemQuery::GetLocalPlayerPos" ); int slot = GET_ACTIVE_SPLITSCREEN_SLOT(); ACTIVE_SPLITSCREEN_PLAYER_GUARD( slot ); C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if ( !pPlayer ) return vec3_origin; return pPlayer->WorldSpaceCenter(); #else CBasePlayer *pPlayer = AI_GetSinglePlayer(); if ( !pPlayer ) return vec3_origin; return pPlayer->WorldSpaceCenter(); #endif }
//----------------------------------------------------------------------------- // Purpose: Find what size of nugget to spawn //----------------------------------------------------------------------------- int CAntlionGrub::GetNuggetDenomination( void ) { // Find the desired health perc we want to be at float flDesiredHealthPerc = DynamicResupply_GetDesiredHealthPercentage(); CBasePlayer *pPlayer = AI_GetSinglePlayer(); if ( pPlayer == NULL ) return -1; // Get the player's current health percentage float flPlayerHealthPerc = (float) pPlayer->GetHealth() / (float) pPlayer->GetMaxHealth(); // If we're already maxed out, return the small nugget if ( flPlayerHealthPerc >= flDesiredHealthPerc ) { return NUGGET_SMALL; } // Find where we fall in the desired health's range float flPercDelta = flPlayerHealthPerc / flDesiredHealthPerc; // The larger to discrepancy, the higher the chance to move quickly to close it float flSeed = random->RandomFloat( 0.0f, 1.0f ); float flRandomPerc = Bias( flSeed, (1.0f-flPercDelta) ); int nDenomination; if ( flRandomPerc < 0.25f ) { nDenomination = NUGGET_SMALL; } else if ( flRandomPerc < 0.625f ) { nDenomination = NUGGET_MEDIUM; } else { nDenomination = NUGGET_LARGE; } // Msg("Player: %.02f, Desired: %.02f, Seed: %.02f, Perc: %.02f, Result: %d\n", flPlayerHealthPerc, flDesiredHealthPerc, flSeed, flRandomPerc, nDenomination ); return nDenomination; }
void CGrenadeSpit::Think( void ) { InitHissSound(); if ( m_pHissSound == NULL ) return; // Add a doppler effect to the balls as they travel #ifdef HL2SB CBaseEntity *pPlayer = AI_GetNearestPlayer( GetAbsOrigin() ); #else CBaseEntity *pPlayer = AI_GetSinglePlayer(); #endif if ( pPlayer != NULL ) { Vector dir; VectorSubtract( pPlayer->GetAbsOrigin(), GetAbsOrigin(), dir ); VectorNormalize(dir); float velReceiver = DotProduct( pPlayer->GetAbsVelocity(), dir ); float velTransmitter = -DotProduct( GetAbsVelocity(), dir ); // speed of sound == 13049in/s int iPitch = 100 * ((1 - velReceiver / 13049) / (1 + velTransmitter / 13049)); // clamp pitch shifts if ( iPitch > 250 ) { iPitch = 250; } if ( iPitch < 50 ) { iPitch = 50; } // Set the pitch we've calculated CSoundEnvelopeController::GetController().SoundChangePitch( m_pHissSound, iPitch, 0.1f ); } // Set us up to think again shortly SetNextThink( gpGlobals->curtime + 0.05f ); }
//------------------------------------------------------------------------------ bool CNPC_EnemyFinder::ShouldAlwaysThink() { if ( BaseClass::ShouldAlwaysThink() ) return true; CBasePlayer *pPlayer = AI_GetSinglePlayer(); if ( pPlayer && IRelationType( pPlayer ) == D_HT ) { float playerDistSqr = GetAbsOrigin().DistToSqr( pPlayer->GetAbsOrigin() ); if ( !m_flMaxSearchDist || playerDistSqr <= Square(m_flMaxSearchDist) ) { if ( !FBitSet( m_spawnflags, SF_ENEMY_FINDER_CHECK_VIS) ) return true; if ( playerDistSqr <= Square( 50 * 12 ) ) return true; } } return false; }
//----------------------------------------------------------------------------- // Purpose: Return true if the player is further ahead on the lead route than I am //----------------------------------------------------------------------------- bool CAI_LeadBehavior::PlayerIsAheadOfMe( bool bForce ) { // Find the nearest point on our route to the player, and see if that's further // ahead of us than our nearest point. // If we're not leading, our route doesn't lead to the goal, so we can't use it. // If we just started leading, go ahead and test, and we'll build a temp route. if ( !m_bInitialAheadTest && !IsCurSchedule( SCHED_LEAD_PLAYER, false ) && !bForce ) return false; m_bInitialAheadTest = false; Vector vecClosestPoint; if ( GetClosestPointOnRoute( AI_GetSinglePlayer()->GetAbsOrigin(), &vecClosestPoint ) ) { // If the closest point is not right next to me, then // the player is somewhere ahead of me on the route. if ( (vecClosestPoint - GetOuter()->GetAbsOrigin()).LengthSqr() > (32*32) ) return true; } return false; }
void CParticleSystemQuery::GetLocalPlayerEyeVectors( Vector *pForward, Vector *pRight, Vector *pUp ) { #ifdef CLIENT_DLL C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if ( !pPlayer ) { *pForward = vec3_origin; *pRight = vec3_origin; *pUp = vec3_origin; return; } pPlayer->EyeVectors( pForward, pRight, pUp ); #else CBasePlayer *pPlayer = AI_GetSinglePlayer(); if ( !pPlayer ) { *pForward = vec3_origin; *pRight = vec3_origin; *pUp = vec3_origin; return; } pPlayer->EyeVectors( pForward, pRight, pUp ); #endif }
void CNPC_Dog::SetPlayerAvoidState( void ) { bool bIntersectingBoneFollowers = false; bool bIntersectingNPCBox = false; Vector vNothing; GetSequenceLinearMotion( GetSequence(), &vNothing ); bool bIsMoving = ( IsMoving() || ( vNothing != vec3_origin ) ); //If we are coming out of a script, check if we are stuck inside the player. if ( m_bPerformAvoidance || ( ShouldPlayerAvoid() && bIsMoving ) ) { trace_t trace; Vector vMins, vMaxs; Vector vWorldMins, vWorldMaxs; Vector vPlayerMins, vPlayerMaxs; physfollower_t *pBone; int i; #ifdef SecobMod__Enable_Fixed_Multiplayer_AI CBasePlayer *pLocalPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); #else CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pLocalPlayer ) { vWorldMins = WorldAlignMins(); vWorldMaxs = WorldAlignMaxs(); vPlayerMins = pLocalPlayer->GetAbsOrigin() + pLocalPlayer->WorldAlignMins(); vPlayerMaxs = pLocalPlayer->GetAbsOrigin() + pLocalPlayer->WorldAlignMaxs(); // check if the player intersects the bounds of any of the bone followers for ( i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) { pBone = m_BoneFollowerManager.GetBoneFollower( i ); if ( pBone && pBone->hFollower ) { pBone->hFollower->CollisionProp()->WorldSpaceSurroundingBounds( &vMins, &vMaxs ); if ( IsBoxIntersectingBox( vMins, vMaxs, vPlayerMins, vPlayerMaxs ) ) { bIntersectingBoneFollowers = true; break; } } } bIntersectingNPCBox = IsBoxIntersectingBox( GetAbsOrigin() + vWorldMins, GetAbsOrigin() + vWorldMaxs, vPlayerMins, vPlayerMaxs ); if ( ai_debug_avoidancebounds.GetBool() ) { int iRed = ( bIntersectingNPCBox == true ) ? 255 : 0; NDebugOverlay::Box( GetAbsOrigin(), vWorldMins, vWorldMaxs, iRed, 0, 255, 64, 0.1 ); // draw the bounds of the bone followers for ( i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) { pBone = m_BoneFollowerManager.GetBoneFollower( i ); if ( pBone && pBone->hFollower ) { pBone->hFollower->CollisionProp()->WorldSpaceSurroundingBounds( &vMins, &vMaxs ); iRed = ( IsBoxIntersectingBox( vMins, vMaxs, vPlayerMins, vPlayerMaxs ) ) ? 255 : 0; NDebugOverlay::Box( vec3_origin, vMins, vMaxs, iRed, 0, 255, 64, 0.1 ); } } } } } m_bPlayerAvoidState = ShouldPlayerAvoid(); m_bPerformAvoidance = bIntersectingNPCBox || bIntersectingBoneFollowers; if ( GetCollisionGroup() == COLLISION_GROUP_NPC || GetCollisionGroup() == COLLISION_GROUP_NPC_ACTOR ) { if ( bIntersectingNPCBox == true ) { SetCollisionGroup( COLLISION_GROUP_NPC_ACTOR ); } else { SetCollisionGroup( COLLISION_GROUP_NPC ); } if ( bIntersectingBoneFollowers == true ) { MantainBoneFollowerCollisionGroups( COLLISION_GROUP_NPC_ACTOR ); } else { MantainBoneFollowerCollisionGroups( COLLISION_GROUP_NPC ); } } }
//--------------------------------------------------------- //--------------------------------------------------------- void CNPC_Dog::StartTask( const Task_t *pTask ) { switch( pTask->iTask ) { case TASK_DOG_SETUP_THROW_TARGET: { SetupThrowTarget(); TaskComplete(); } break; case TASK_DOG_GET_PATH_TO_PHYSOBJ: { FindPhysicsObject( STRING( m_sObjectName ) ); if ( m_hPhysicsEnt == NULL ) { FindPhysicsObject( NULL ); return; } IPhysicsObject *pPhysicsObject = m_hPhysicsEnt->VPhysicsGetObject(); Vector vecGoalPos; Vector vecDir; vecDir = GetLocalOrigin() - m_hPhysicsEnt->WorldSpaceCenter(); VectorNormalize(vecDir); vecDir.z = 0; if ( m_hPhysicsEnt->GetOwnerEntity() == NULL ) m_hPhysicsEnt->SetOwnerEntity( this ); if ( pPhysicsObject ) pPhysicsObject->RecheckCollisionFilter(); vecGoalPos = m_hPhysicsEnt->WorldSpaceCenter() + (vecDir * DOG_PHYSOBJ_MOVE_TO_DIST ); //If I'm near my goal, then just walk to it. Activity aActivity = ACT_RUN; if ( ( vecGoalPos - GetLocalOrigin() ).Length() <= 128 ) aActivity = ACT_WALK; if ( GetNavigator()->SetGoal( AI_NavGoal_t( vecGoalPos, aActivity ), AIN_NO_PATH_TASK_FAIL ) == false ) { if ( m_hUnreachableObjects.Find( m_hPhysicsEnt ) == -1 ) m_hUnreachableObjects.AddToTail( m_hPhysicsEnt ); FindPhysicsObject( NULL, m_hPhysicsEnt ); m_flTimeToCatch = gpGlobals->curtime + 0.1; m_flNextRouteTime = gpGlobals->curtime + 0.3; m_flNextSwat = gpGlobals->curtime + 0.1; GetNavigator()->ClearGoal(); } else { TaskComplete(); } } break; case TASK_DOG_FACE_OBJECT: { if( m_hPhysicsEnt == NULL ) { // Physics Object is gone! Probably was an explosive // or something else broke it. TaskFail("Physics ent NULL"); return; } Vector vecDir; vecDir = m_hPhysicsEnt->WorldSpaceCenter() - GetLocalOrigin(); VectorNormalize(vecDir); GetMotor()->SetIdealYaw( UTIL_VecToYaw( vecDir ) ); TaskComplete(); } break; case TASK_DOG_PICKUP_ITEM: { if( m_hPhysicsEnt == NULL ) { // Physics Object is gone! Probably was an explosive // or something else broke it. TaskFail("Physics ent NULL"); return; } else { SetIdealActivity( (Activity)ACT_DOG_PICKUP ); } } break; case TASK_DOG_LAUNCH_ITEM: { if( m_hPhysicsEnt == NULL ) { // Physics Object is gone! Probably was an explosive // or something else broke it. TaskFail("Physics ent NULL"); return; } else { if ( m_hPhysicsEnt == NULL || m_bHasObject == false ) { TaskFail( "Don't have the item!" ); return; } SetIdealActivity( (Activity)ACT_DOG_THROW ); } } break; case TASK_DOG_WAIT_FOR_TARGET_TO_FACE: { if ( CanTargetSeeMe() ) TaskComplete(); } break; case TASK_DOG_WAIT_FOR_OBJECT: { SetIdealActivity( (Activity)ACT_DOG_WAITING ); } break; case TASK_DOG_CATCH_OBJECT: { SetIdealActivity( (Activity)ACT_DOG_CATCH ); } break; case TASK_DOG_DELAY_SWAT: m_flNextSwat = gpGlobals->curtime + pTask->flTaskData; if ( m_hThrowTarget == NULL ) #ifdef SecobMod__Enable_Fixed_Multiplayer_AI m_hThrowTarget = UTIL_GetNearestVisiblePlayer(this); #else m_hThrowTarget = AI_GetSinglePlayer(); #endif //SecobMod__Enable_Fixed_Multiplayer_AI TaskComplete(); break; default: BaseClass::StartTask( pTask ); } }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CAI_FearBehavior::GatherConditions() { BaseClass::GatherConditions(); ClearCondition( COND_FEAR_ENEMY_CLOSE ); ClearCondition( COND_FEAR_ENEMY_TOO_CLOSE ); if( GetEnemy() ) { float flEnemyDistSqr = GetAbsOrigin().DistToSqr(GetEnemy()->GetAbsOrigin()); if( flEnemyDistSqr < FEAR_ENEMY_TOLERANCE_TOO_CLOSE_DIST_SQR ) { SetCondition( COND_FEAR_ENEMY_TOO_CLOSE ); if( IsInASafePlace() ) { SpoilSafePlace(); } } else if( flEnemyDistSqr < FEAR_ENEMY_TOLERANCE_CLOSE_DIST_SQR && GetEnemy()->GetEnemy() == GetOuter() ) { // Only become scared of an enemy at this range if they're my enemy, too SetCondition( COND_FEAR_ENEMY_CLOSE ); if( IsInASafePlace() ) { SpoilSafePlace(); } } } ClearCondition(COND_FEAR_SEPARATED_FROM_PLAYER); // Check for separation from the player // -The player is farther away than 60 feet // -I haven't seen the player in 2 seconds // // Here's the distance check: CBasePlayer *pPlayer = AI_GetSinglePlayer(); if( pPlayer != NULL && GetAbsOrigin().DistToSqr(pPlayer->GetAbsOrigin()) >= Square( ai_fear_player_dist.GetFloat() * 1.5f ) ) { SetCondition(COND_FEAR_SEPARATED_FROM_PLAYER); } // Here's the visibility check. We can't skip this because it's time-sensitive if( GetOuter()->FVisible(pPlayer) ) { m_flTimePlayerLastVisible = gpGlobals->curtime; } else { if( gpGlobals->curtime - m_flTimePlayerLastVisible >= 2.0f ) { SetCondition(COND_FEAR_SEPARATED_FROM_PLAYER); } } if( HasCondition(COND_FEAR_SEPARATED_FROM_PLAYER) ) { //Msg("I am separated from player\n"); if( IsInASafePlace() ) { SpoilSafePlace(); } } }
int CAI_LeadBehavior::SelectSchedule() { if ( HasGoal() ) { if( HasCondition(COND_LEAD_SUCCESS) ) { return SCHED_LEAD_SUCCEED; } // Player's here, but does he have the weapon we want him to have? if ( m_weaponname != NULL_STRING ) { CBasePlayer *pFollower = AI_GetSinglePlayer(); if ( pFollower && !pFollower->Weapon_OwnsThisType( STRING(m_weaponname) ) ) { // If the safety timeout has run out, just give the player the weapon if ( !m_flWeaponSafetyTimeOut || (m_flWeaponSafetyTimeOut > gpGlobals->curtime) ) return SCHED_LEAD_PLAYERNEEDSWEAPON; string_t iszItem = AllocPooledString( "weapon_bugbait" ); pFollower->GiveNamedItem( STRING(iszItem) ); } } // If we have a waitpoint, we want to wait at it for the player. if( HasWaitPoint() && !PlayerIsAheadOfMe( true ) ) { bool bKeepWaiting = true; // If we have no wait distance, trigger as soon as the player comes in view if ( !m_waitdistance ) { if ( HasCondition( COND_SEE_PLAYER ) ) { // We've spotted the player, so stop waiting bKeepWaiting = false; } } else { // We have to collect data about the person we're leading around. CBaseEntity *pFollower = AI_GetSinglePlayer(); if( pFollower ) { float flFollowerDist = ( WorldSpaceCenter() - pFollower->WorldSpaceCenter() ).Length(); if ( flFollowerDist < m_waitdistance ) { bKeepWaiting = false; } } } // Player still not here? if ( bKeepWaiting ) return SCHED_LEAD_WAITFORPLAYER; // We're finished waiting m_waitpoint = vec3_origin; Speak( TLK_LEAD_WAITOVER ); // Don't speak the start line, because we've said m_hasspokenstart = true; return SCHED_WAIT_FOR_SPEAK_FINISH; } // If we haven't spoken our start speech, do that first if ( !m_hasspokenstart ) { if ( HasCondition(COND_LEAD_HAVE_FOLLOWER_LOS) && HasCondition(COND_LEAD_FOLLOWER_VERY_CLOSE) ) return SCHED_LEAD_SPEAK_START; // We haven't spoken to him, and we still need to. Go get him. return SCHED_LEAD_RETRIEVE; } if( HasCondition( COND_LEAD_FOLLOWER_LOST ) ) { if( m_args.iRetrievePlayer ) { // If not, we want to go get the player. DevMsg( GetOuter(), "Follower lost. Spoke COMING_BACK.\n"); Speak( TLK_LEAD_COMINGBACK ); m_MoveMonitor.ClearMark(); // If we spoke something, wait for it to finish if ( m_args.iComingBackWaitForSpeak && IsSpeaking() ) return SCHED_LEAD_SPEAK_THEN_RETRIEVE_PLAYER; return SCHED_LEAD_RETRIEVE; } else { // Just stay right here and wait. return SCHED_LEAD_WAITFORPLAYERIDLE; } } if( HasCondition( COND_LEAD_FOLLOWER_LAGGING ) ) { DevMsg( GetOuter(), "Follower lagging. Spoke CATCHUP.\n"); Speak( TLK_LEAD_CATCHUP ); return SCHED_LEAD_PAUSE; } else { // If we're at the goal, wait for the player to get here if ( ( WorldSpaceCenter() - m_goal ).LengthSqr() < (64*64) ) return SCHED_LEAD_AWAIT_SUCCESS; // If we were retrieving the player, speak the resume if ( IsCurSchedule( SCHED_LEAD_RETRIEVE, false ) || IsCurSchedule( SCHED_LEAD_WAITFORPLAYERIDLE, false ) ) { Speak( TLK_LEAD_RETRIEVE ); // If we spoke something, wait for it to finish, if the mapmakers wants us to if ( m_args.iRetrieveWaitForSpeak && IsSpeaking() ) return SCHED_LEAD_SPEAK_THEN_LEAD_PLAYER; } DevMsg( GetOuter(), "Leading Follower.\n"); return SCHED_LEAD_PLAYER; } } return BaseClass::SelectSchedule(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CAI_LeadBehavior::GatherConditions( void ) { BaseClass::GatherConditions(); if ( HasGoal() ) { // Fix for bad transition case (to investigate) if ( ( WorldSpaceCenter() - m_goal ).LengthSqr() > (64*64) && IsCurSchedule( SCHED_LEAD_AWAIT_SUCCESS, false) ) { GetOuter()->ClearSchedule( "Lead behavior - bad transition?" ); } // We have to collect data about the person we're leading around. CBaseEntity *pFollower = AI_GetSinglePlayer(); if( pFollower ) { ClearCondition( COND_LEAD_FOLLOWER_VERY_CLOSE ); ClearCondition( COND_LEAD_FOLLOWER_MOVING_TOWARDS_ME ); // Check distance to the follower float flFollowerDist = ( WorldSpaceCenter() - pFollower->WorldSpaceCenter() ).Length(); bool bLagging = flFollowerDist > (m_leaddistance*4); if ( bLagging ) { if ( PlayerIsAheadOfMe() ) { bLagging = false; } } // Player heading towards me? // Only factor this in if you're not too far from them if ( flFollowerDist < (m_leaddistance*4) ) { Vector vecVelocity = pFollower->GetSmoothedVelocity(); if ( VectorNormalize(vecVelocity) > 50 ) { Vector vecToPlayer = (GetAbsOrigin() - pFollower->GetAbsOrigin()); VectorNormalize( vecToPlayer ); if ( DotProduct( vecVelocity, vecToPlayer ) > 0.5 ) { SetCondition( COND_LEAD_FOLLOWER_MOVING_TOWARDS_ME ); bLagging = false; } } } // If he's outside our lag range, consider him lagging if ( bLagging ) { SetCondition( COND_LEAD_FOLLOWER_LAGGING ); ClearCondition( COND_LEAD_FOLLOWER_NOT_LAGGING ); } else { ClearCondition( COND_LEAD_FOLLOWER_LAGGING ); SetCondition( COND_LEAD_FOLLOWER_NOT_LAGGING ); // If he's really close, note that if ( flFollowerDist < m_leaddistance ) { SetCondition( COND_LEAD_FOLLOWER_VERY_CLOSE ); } } // To be considered not lagging, the follower must be visible, and within the lead distance if ( GetOuter()->FVisible( pFollower ) && GetOuter()->GetSenses()->ShouldSeeEntity( pFollower ) ) { SetCondition( COND_LEAD_HAVE_FOLLOWER_LOS ); m_LostLOSTimer.Stop(); } else { ClearCondition( COND_LEAD_HAVE_FOLLOWER_LOS ); // We don't have a LOS. But if we did have LOS, don't clear it until the timer is up. if ( m_LostLOSTimer.IsRunning() ) { if ( m_LostLOSTimer.Expired() ) { SetCondition( COND_LEAD_FOLLOWER_LAGGING ); ClearCondition( COND_LEAD_FOLLOWER_NOT_LAGGING ); } } else { m_LostLOSTimer.Start(); } } // Now we want to see if the follower is lost. Being lost means being (far away || out of LOS ) // && some time has passed. Also, lagging players are considered lost if the NPC's never delivered // the start speech, because it means the NPC should run to the player to start the lead. if( HasCondition( COND_LEAD_FOLLOWER_LAGGING ) ) { if ( !m_hasspokenstart ) { SetCondition( COND_LEAD_FOLLOWER_LOST ); } else { if ( m_args.bStopScenesWhenPlayerLost ) { // Try and stop me speaking my monolog, if I am if ( !m_hasPausedScenes && IsRunningScriptedScene( GetOuter() ) ) { //Msg("Stopping scenes.\n"); PauseActorsScriptedScenes( GetOuter(), false ); m_hasPausedScenes = true; } } if( m_LostTimer.IsRunning() ) { if( m_LostTimer.Expired() ) { SetCondition( COND_LEAD_FOLLOWER_LOST ); } } else { m_LostTimer.Start(); } } } else { // If I was speaking a monolog, resume it if ( m_args.bStopScenesWhenPlayerLost && m_hasPausedScenes ) { if ( IsRunningScriptedScene( GetOuter() ) ) { //Msg("Resuming scenes.\n"); ResumeActorsScriptedScenes( GetOuter(), false ); } m_hasPausedScenes = false; } m_LostTimer.Stop(); ClearCondition( COND_LEAD_FOLLOWER_LOST ); } // Evaluate for success // Success right now means being stationary, close to the goal, and having the player close by if ( !( m_args.flags & AILF_NO_DEF_SUCCESS ) ) { ClearCondition( COND_LEAD_SUCCESS ); // Check Z first, and only check 2d if we're within that bool bWithinZ = fabs(GetLocalOrigin().z - m_goal.z) < 64; if ( bWithinZ && (GetLocalOrigin() - m_goal).Length2D() <= 64 ) { if ( HasCondition( COND_LEAD_FOLLOWER_VERY_CLOSE ) ) { SetCondition( COND_LEAD_SUCCESS ); } else if ( m_successdistance ) { float flDistSqr = (pFollower->GetAbsOrigin() - GetLocalOrigin()).Length2DSqr(); if ( flDistSqr < (m_successdistance*m_successdistance) ) { SetCondition( COND_LEAD_SUCCESS ); } } } } if ( m_MoveMonitor.IsMarkSet() && m_MoveMonitor.TargetMoved( pFollower ) ) SetCondition( COND_LEAD_FOLLOWER_MOVED_FROM_MARK ); else ClearCondition( COND_LEAD_FOLLOWER_MOVED_FROM_MARK ); } } if( m_args.bLeadDuringCombat ) { ClearCondition( COND_LIGHT_DAMAGE ); ClearCondition( COND_HEAVY_DAMAGE ); } }
void CNPC_Dog::ThrowObject( const char *pAttachmentName ) { if ( m_hPhysicsEnt ) { m_bHasObject = false; IPhysicsObject *pPhysObj = m_hPhysicsEnt->VPhysicsGetObject(); if ( pPhysObj ) { Vector vGunPos; QAngle angGunAngles; AngularImpulse angVelocity = RandomAngularImpulse( -250 , -250 ) / pPhysObj->GetMass(); InvalidateBoneCache(); int iAttachment = LookupAttachment( pAttachmentName ); if ( iAttachment == 0 ) iAttachment = m_iPhysGunAttachment; GetAttachment( iAttachment, vGunPos, angGunAngles ); pPhysObj->Wake(); if ( pPhysObj->GetShadowController() ) { m_hPhysicsEnt->SetParent( NULL ); m_hPhysicsEnt->SetMoveType( (MoveType_t)m_iContainerMoveType ); m_hPhysicsEnt->SetOwnerEntity( this ); pPhysObj->RemoveShadowController(); pPhysObj->SetPosition( m_hPhysicsEnt->GetLocalOrigin(), m_hPhysicsEnt->GetLocalAngles(), true ); pPhysObj->RecheckCollisionFilter(); pPhysObj->RecheckContactPoints(); } if ( m_hThrowTarget == NULL ) #ifdef SecobMod__Enable_Fixed_Multiplayer_AI m_hThrowTarget = UTIL_GetNearestVisiblePlayer(this); #else m_hThrowTarget = AI_GetSinglePlayer(); #endif //SecobMod__Enable_Fixed_Multiplayer_AI Vector vThrowDirection; if ( m_hThrowTarget ) { Vector vThrowOrigin = m_hThrowTarget->GetAbsOrigin(); if ( m_hThrowTarget->IsPlayer() ) vThrowOrigin = vThrowOrigin + Vector( random->RandomFloat( -128, 128 ), random->RandomFloat( -128, 128 ), 0 ); Vector vecToss = VecCheckToss( this, vGunPos, vThrowOrigin, m_flThrowArcModifier, 1.0f, true ); if( vecToss == vec3_origin ) { // Fix up an impossible throw so dog will at least toss the box in the target's general direction instead of dropping it. // Also toss it up in the air so it will fall down and break. (Just throw the box up at a 45 degree angle) Vector forward, up; GetVectors( &forward, NULL, &up ); vecToss = forward + up; VectorNormalize( vecToss ); vecToss *= pPhysObj->GetMass() * 30.0f; } vThrowDirection = vecToss + ( m_hThrowTarget->GetSmoothedVelocity() / 2 ); Vector vLinearDrag; Vector unitVel = vThrowDirection; VectorNormalize( unitVel ); float flTest = 1000 / vThrowDirection.Length(); float flDrag = pPhysObj->CalculateLinearDrag( vThrowDirection ); vThrowDirection = vThrowDirection + ( unitVel * ( flDrag * flDrag ) ) / flTest; pPhysObj->SetVelocity( &vThrowDirection, &angVelocity ); m_flTimeToCatch = gpGlobals->curtime + dog_max_wait_time.GetFloat(); //Don't start pulling until the object is away from me. //We base the time on the throw velocity. m_flTimeToPull = gpGlobals->curtime + ( 1000 / vThrowDirection.Length() ); } //Fire Output! m_OnThrow.FireOutput( this, this ); ClearBeams(); if ( m_bBeamEffects == true ) { EmitSound( "Weapon_PhysCannon.Launch" ); CBeam *pBeam = CBeam::BeamCreate( "sprites/orangelight1.vmt", 1.8 ); if ( pBeam != NULL ) { pBeam->PointEntInit( m_hPhysicsEnt->WorldSpaceCenter(), this ); pBeam->SetEndAttachment( m_iPhysGunAttachment ); pBeam->SetWidth( 6.4 ); pBeam->SetEndWidth( 12.8 ); pBeam->SetBrightness( 255 ); pBeam->SetColor( 255, 255, 255 ); pBeam->LiveForTime( 0.2f ); pBeam->RelinkBeam(); pBeam->SetNoise( 2 ); } Vector shotDir = ( m_hPhysicsEnt->WorldSpaceCenter() - vGunPos ); VectorNormalize( shotDir ); CPVSFilter filter( m_hPhysicsEnt->WorldSpaceCenter() ); te->GaussExplosion( filter, 0.0f, m_hPhysicsEnt->WorldSpaceCenter() - ( shotDir * 4.0f ), RandomVector(-1.0f, 1.0f), 0 ); } } } }
void CAI_LeadBehavior::StartTask( const Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_LEAD_FACE_GOAL: { if ( m_goalyaw != -1 ) { GetMotor()->SetIdealYaw( m_goalyaw ); } TaskComplete(); break; } case TASK_LEAD_SUCCEED: { Speak( TLK_LEAD_SUCCESS ); NotifyEvent( LBE_SUCCESS ); break; } case TASK_LEAD_ARRIVE: { // Only speak the first time we arrive if ( !m_hasspokenarrival ) { Speak( TLK_LEAD_ARRIVAL ); NotifyEvent( LBE_ARRIVAL ); m_hasspokenarrival = true; } else { TaskComplete(); } break; } case TASK_STOP_LEADING: { ClearGoal(); TaskComplete(); break; } case TASK_GET_PATH_TO_LEAD_GOAL: { if ( GetNavigator()->SetGoal( m_goal ) ) { TaskComplete(); } else { TaskFail("NO PATH"); } break; } case TASK_LEAD_GET_PATH_TO_WAITPOINT: { if ( GetNavigator()->SetGoal( m_waitpoint ) ) { TaskComplete(); } else { TaskFail("NO PATH"); } break; } case TASK_LEAD_WALK_PATH: { // If we're leading, and we're supposed to run, run instead of walking if ( m_run && ( IsCurSchedule( SCHED_LEAD_WAITFORPLAYER, false ) || IsCurSchedule( SCHED_LEAD_PLAYER, false ) || IsCurSchedule( SCHED_LEAD_SPEAK_THEN_LEAD_PLAYER, false )|| IsCurSchedule( SCHED_LEAD_RETRIEVE, false ) ) ) { ChainStartTask( TASK_RUN_PATH ); } else { ChainStartTask( TASK_WALK_PATH ); } break; } case TASK_LEAD_WAVE_TO_PLAYER: { // Wave to the player if we can see him. Otherwise, just idle. if ( HasCondition( COND_SEE_PLAYER ) ) { Speak( TLK_LEAD_ATTRACTPLAYER ); if ( HaveSequenceForActivity(ACT_SIGNAL1) ) { SetActivity(ACT_SIGNAL1); } } else { SetActivity(ACT_IDLE); } TaskComplete(); break; } case TASK_LEAD_PLAYER_NEEDS_WEAPON: { float flAvailableTime = GetOuter()->GetExpresser()->GetSemaphoreAvailableTime( GetOuter() ); // if someone else is talking, don't speak if ( flAvailableTime <= gpGlobals->curtime ) { Speak( TLK_LEAD_MISSINGWEAPON ); } SetActivity(ACT_IDLE); TaskComplete(); break; } case TASK_LEAD_SPEAK_START: { m_hasspokenstart = true; Speak( TLK_LEAD_START ); SetActivity(ACT_IDLE); TaskComplete(); break; } case TASK_LEAD_MOVE_TO_RANGE: { // If we haven't spoken our start speech, move closer if ( !m_hasspokenstart) { ChainStartTask( TASK_MOVE_TO_GOAL_RANGE, m_leaddistance - 24 ); } else { ChainStartTask( TASK_MOVE_TO_GOAL_RANGE, m_retrievedistance ); } break; } case TASK_LEAD_RETRIEVE_WAIT: { m_MoveMonitor.SetMark( AI_GetSinglePlayer(), 24 ); ChainStartTask( TASK_WAIT_INDEFINITE ); break; } case TASK_STOP_MOVING: { BaseClass::StartTask( pTask); if ( IsCurSchedule( SCHED_LEAD_PAUSE, false ) && pTask->flTaskData == 1 ) { GetNavigator()->SetArrivalDirection( GetTarget() ); } break; } case TASK_WAIT_FOR_SPEAK_FINISH: { BaseClass::StartTask( pTask); if( GetOuter()->GetState() == NPC_STATE_COMBAT ) { // Don't stand around jabbering in combat. TaskComplete(); } // If we're not supposed to wait for the player, don't wait for speech to finish. // Instead, just wait a wee tad, and then start moving. NPC will speak on the go. if ( TaskIsRunning() && !m_args.iRetrievePlayer ) { if ( gpGlobals->curtime - GetOuter()->GetTimeTaskStarted() > 0.3 ) { TaskComplete(); } } break; } default: BaseClass::StartTask( pTask); } }
void CAI_ScriptConditions::EvaluationThink() { if ( m_fDisabled == true ) return; int iActorsDone = 0; #ifdef HL2_DLL if( AI_GetSinglePlayer()->GetFlags() & FL_NOTARGET ) { ScrCondDbgMsg( ("%s WARNING: Player is NOTARGET. This will affect all LOS conditiosn involving the player!\n", GetDebugName()) ); } #endif for ( int i = 0; i < m_ElementList.Count(); ) { CAI_ScriptConditionsElement *pConditionElement = &m_ElementList[i]; if ( pConditionElement == NULL ) { i++; continue; } CBaseEntity *pActor = pConditionElement->GetActor(); CBaseEntity *pActivator = this; #ifdef HL2_EPISODIC if ( pActor && HasSpawnFlags( SF_ACTOR_AS_ACTIVATOR ) ) { pActivator = pActor; } #endif AssertMsg( !m_fDisabled, ("Violated invariant between CAI_ScriptConditions disabled state and think func setting") ); if ( m_Actor != NULL_STRING && !pActor ) { if ( m_ElementList.Count() == 1 ) { DevMsg( "Warning: Active AI script conditions associated with an non-existant or destroyed NPC\n" ); m_NoValidActors.FireOutput( this, this, 0 ); } iActorsDone++; m_ElementList.Remove( i ); continue; } i++; if( m_flMinTimeout > 0 && pConditionElement->GetTimeOut()->Expired() ) { ScrCondDbgMsg( ( "%s firing output OnConditionsTimeout (%f seconds)\n", STRING( GetEntityName() ), pConditionElement->GetTimeOut()->GetInterval() ) ); iActorsDone++; m_OnConditionsTimeout.FireOutput( pActivator, this ); continue; } bool result = true; const int nEvaluators = sizeof( gm_Evaluators ) / sizeof( gm_Evaluators[0] ); EvalArgs_t args = { pActor, GetPlayer(), m_hTarget.Get() }; for ( int i = 0; i < nEvaluators; ++i ) { if ( !(this->*gm_Evaluators[i].pfnEvaluator)( args ) ) { pConditionElement->GetTimer()->Reset(); result = false; ScrCondDbgMsg( ( "%s failed on: %s\n", GetDebugName(), gm_Evaluators[ i ].pszName ) ); break; } } if ( result ) { ScrCondDbgMsg( ( "%s waiting... %f\n", GetDebugName(), pConditionElement->GetTimer()->GetRemaining() ) ); } if ( result && pConditionElement->GetTimer()->Expired() ) { ScrCondDbgMsg( ( "%s firing output OnConditionsSatisfied\n", GetDebugName() ) ); // Default behavior for now, provide worldcraft option later. iActorsDone++; m_OnConditionsSatisfied.FireOutput( pActivator, this ); } } //All done! if ( iActorsDone == m_ElementList.Count() ) { Disable(); m_ElementList.Purge(); } SetThinkTime(); }