int CWeaponCrowbar::WeaponMeleeAttack1Condition( float flDot, float flDist ) { // Attempt to lead the target (needed because citizens can't hit manhacks with the crowbar!) CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); CBaseEntity *pEnemy = pNPC->GetEnemy(); if (!pEnemy) return COND_NONE; Vector vecVelocity; vecVelocity = pEnemy->GetSmoothedVelocity( ); // Project where the enemy will be in a little while float dt = sk_crowbar_lead_time.GetFloat(); dt += SharedRandomFloat( "crowbarmelee1", -0.3f, 0.2f ); if ( dt < 0.0f ) dt = 0.0f; Vector vecExtrapolatedPos; VectorMA( pEnemy->WorldSpaceCenter(), dt, vecVelocity, vecExtrapolatedPos ); Vector vecDelta; VectorSubtract( vecExtrapolatedPos, pNPC->WorldSpaceCenter(), vecDelta ); if ( fabs( vecDelta.z ) > 70 ) { return COND_TOO_FAR_TO_ATTACK; } Vector vecForward = pNPC->BodyDirection2D( ); vecDelta.z = 0.0f; float flExtrapolatedDist = Vector2DNormalize( vecDelta.AsVector2D() ); if ((flDist > 64) && (flExtrapolatedDist > 64)) { return COND_TOO_FAR_TO_ATTACK; } float flExtrapolatedDot = DotProduct2D( vecDelta.AsVector2D(), vecForward.AsVector2D() ); if ((flDot < 0.7) && (flExtrapolatedDot < 0.7)) { return COND_NOT_FACING_ATTACK; } return COND_CAN_MELEE_ATTACK1; }
void InputSetAggressiveness( inputdata_t &inputdata ) { int newVal = inputdata.value.Int(); m_aggressiveness = (Aggressiveness_t)newVal; ValidateAggression(); UpdateActors(); const CUtlVector<AIHANDLE> &actors = AccessActors(); for ( int i = 0; i < actors.Count(); i++ ) { CAI_BaseNPC *pAI = actors[i]; CAI_StandoffBehavior *pBehavior; if ( !pAI->GetBehavior( &pBehavior ) ) continue; SetBehaviorParams( pBehavior); } }
void CAI_PlayerAlly::AlertFriends( CBaseEntity *pKiller ) { CBaseEntity *pFriend = NULL; int i; // for each friend in this bsp... for ( i = 0; i < TLK_CFRIENDS; i++ ) { while (pFriend = EnumFriends( pFriend, i, true )) { CAI_BaseNPC *pNPC = pFriend->MyNPCPointer(); if ( pNPC->IsAlive() ) { // If a client killed me, make everyone else mad/afraid of him if ( pKiller->GetFlags() & FL_CLIENT ) { pNPC->SetSchedule( SCHED_TALKER_BETRAYED ); #ifdef ALLIES_CAN_BE_PROVOKED pNPC->Remember( bits_MEMORY_PROVOKED ); if( IsSelected() ) { PlayerSelect( false ); } #endif } else { if( IRelationType(pKiller) == D_HT) { // Killed by an enemy!!! CAI_PlayerAlly *pAlly = (CAI_PlayerAlly *)pNPC; if( pAlly && pAlly->GetExpresser()->CanSpeakConcept( TLK_ALLY_KILLED ) ) { pAlly->Speak( TLK_ALLY_KILLED ); } } } } } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeapon357::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) { switch( pEvent->event ) { case EVENT_WEAPON_PISTOL_FIRE: { Vector vecShootOrigin, vecShootDir; vecShootOrigin = pOperator->Weapon_ShootPosition(); CAI_BaseNPC *npc = pOperator->MyNPCPointer(); ASSERT(npc != NULL); vecShootDir = npc->GetActualShootTrajectory(vecShootOrigin); CSoundEnt::InsertSound(SOUND_COMBAT | SOUND_CONTEXT_GUNFIRE, pOperator->GetAbsOrigin(), SOUNDENT_VOLUME_PISTOL, 0.2, pOperator, SOUNDENT_CHANNEL_WEAPON, pOperator->GetEnemy()); WeaponSound(SINGLE_NPC); pOperator->FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2); pOperator->DoMuzzleFlash(); m_iClip1 = m_iClip1 - 1; } case EVENT_WEAPON_RELOAD: { CBasePlayer *pOwner = ToBasePlayer(GetOwner()); CEffectData data; // Emit six spent shells for (int i = 0; i < 6; i++) { data.m_vOrigin = pOwner->WorldSpaceCenter() + RandomVector(-4, 4); data.m_vAngles = QAngle(90, random->RandomInt(0, 360), 0); data.m_nEntIndex = entindex(); DispatchEffect("ShellEject", data); } } break; default: BaseClass::Operator_HandleAnimEvent(pEvent, pOperator); break; } }
void CNPC_Vortigaunt::CallForHelp( char *szClassname, float flDist, CBaseEntity * pEnemy, Vector &vecLocation ) { // ALERT( at_aiconsole, "help " ); // skip ones not on my netname if ( !m_pSquad ) return; AISquadIter_t iter; for (CAI_BaseNPC *pSquadMember = m_pSquad->GetFirstMember( &iter ); pSquadMember; pSquadMember = m_pSquad->GetNextMember( &iter ) ) { float d = ( GetAbsOrigin() - pSquadMember->GetAbsOrigin() ).Length(); if ( d < flDist ) { pSquadMember->Remember( bits_MEMORY_PROVOKED ); pSquadMember->UpdateEnemyMemory( pEnemy, vecLocation ); } } }
//----------------------------------------------------------------------------- // Purpose: // Input : *pKiller - //----------------------------------------------------------------------------- void CNPCSimpleTalker::AlertFriends( CBaseEntity *pKiller ) { CBaseEntity *pFriend = NULL; int i; // for each friend in this bsp... for ( i = 0; i < TLK_CFRIENDS; i++ ) { while ((pFriend = EnumFriends( pFriend, i, true )) != NULL ) { CAI_BaseNPC *pNPC = pFriend->MyNPCPointer(); if ( pNPC->IsAlive() ) { // If a client killed me, make everyone else mad/afraid of him if ( pKiller->GetFlags() & FL_CLIENT ) { CNPCSimpleTalker*pTalkNPC = (CNPCSimpleTalker *)pFriend; if (pTalkNPC && pTalkNPC->IsOkToCombatSpeak()) { // FIXME: need to check CanSpeakConcept? pTalkNPC->Speak( TLK_BETRAYED ); } } else { if( IRelationType(pKiller) == D_HT) { // Killed by an enemy!!! CNPCSimpleTalker *pAlly = (CNPCSimpleTalker *)pNPC; if( pAlly && pAlly->GetExpresser()->CanSpeakConcept( TLK_ALLY_KILLED ) ) { pAlly->Speak( TLK_ALLY_KILLED ); } } } } } } }
int CAI_Squad::BroadcastInteraction( int interactionType, void *data, CBaseCombatCharacter *sender ) { //Must have a squad if ( m_SquadMembers.Count() == 0 ) return false; //Broadcast to all members of the squad for ( int i = 0; i < m_SquadMembers.Count(); i++ ) { CAI_BaseNPC *pMember = m_SquadMembers[i]->MyNPCPointer(); //Validate and don't send again to the sender if ( ( pMember != NULL) && ( pMember != sender ) ) { //Send it pMember->DispatchInteraction( interactionType, data, sender ); } } return true; }
//----------------------------------------------------------------------------- // Purpose: ENTITY I/O method for telling the assault behavior to cue assault // Input : &inputdata - //----------------------------------------------------------------------------- void CAI_AssaultGoal::InputBeginAssault( inputdata_t &inputdata ) { int i; for( i = 0 ; i < NumActors() ; i++ ) { CAI_BaseNPC *pActor = GetActor( i ); if( pActor ) { // Now use this actor to lookup the Behavior CAI_AssaultBehavior *pBehavior; if( pActor->GetBehavior( &pBehavior ) ) { // GOT IT! Now tell the behavior that entity i/o wants to cue the assault. pBehavior->ReceiveAssaultCue( CUE_ENTITY_INPUT ); } } } }
//========================================================= // Revela la posición de los jugadores. //========================================================= void CDirector_Manager::Disclose() { CAI_BaseNPC *pNPC = NULL; do { // Buscamos a todos los hijos en el mapa. pNPC = (CAI_BaseNPC *)gEntList.FindEntityByName(pNPC, CHILD_NAME); // No existe o esta muerto. if ( !pNPC || !pNPC->IsAlive() ) continue; // Ya tiene a un jugador como enemigo. if ( pNPC->GetEnemy() && pNPC->GetEnemy()->IsPlayer() ) continue; // Seleccionamos al jugador más cercano. float flDistance = 0.0f; CIN_Player *pPlayer = UTIL_GetNearestInPlayer(pPlayer->GetAbsOrigin(), flDistance); if ( !pPlayer ) continue; // Le decimos que su nuevo enemigo es el jugador y le damos la ubicación de este. pNPC->SetEnemy(pPlayer); pNPC->UpdateEnemyMemory(pPlayer, pPlayer->GetAbsOrigin()); } while ( pNPC ); }
//----------------------------------------------------------------------------- // Purpose: // Input : pInflictor - // pAttacker - // flDamage - // bitsDamageType - //----------------------------------------------------------------------------- void CNPC_Stalker::Event_Killed( const CTakeDamageInfo &info ) { if( IsInSquad() && info.GetAttacker()->IsPlayer() ) { AISquadIter_t iter; for ( CAI_BaseNPC *pSquadMember = GetSquad()->GetFirstMember( &iter ); pSquadMember; pSquadMember = GetSquad()->GetNextMember( &iter ) ) { if ( pSquadMember->IsAlive() && pSquadMember != this ) { CNPC_Stalker *pStalker = dynamic_cast <CNPC_Stalker*>(pSquadMember); if( pStalker && pStalker->FVisible(info.GetAttacker()) ) { pStalker->m_iPlayerAggression++; } } } } KillAttackBeam(); BaseClass::Event_Killed( info ); }
bool CAI_OperatorBehavior::CanSeePositionEntity() { CAI_BaseNPC *pOuter = GetOuter(); Assert( m_hPositionEnt.Get() != NULL ); // early out here. if( !pOuter->QuerySeeEntity(m_hPositionEnt) ) { m_WatchSeeEntity.Stop(); return false; } bool bSpotted = (pOuter->EyePosition().DistToSqr(m_hPositionEnt->GetAbsOrigin()) <= POSITION_ENT_ALWAYS_SEE_DIST); if ( !bSpotted ) { bSpotted = ( pOuter->FInViewCone(m_hPositionEnt) && pOuter->FVisible(m_hPositionEnt) ); } if (bSpotted ) { // If we haven't seen it up until now, start a timer. If we have seen it, wait for the // timer to finish. This prevents edge cases where turning on the flashlight makes // NPC spot the position entity a frame before she spots an enemy. if ( !m_WatchSeeEntity.IsRunning() ) { m_WatchSeeEntity.Start( 0.3,0.31 ); return false; } if ( !m_WatchSeeEntity.Expired() ) return false; return true; } m_WatchSeeEntity.Stop(); return false; }
//----------------------------------------------------------------------------- // Purpose: // Input : *pAttacker - // flDamage - // &vecDir - // *ptr - // bitsDamageType - //----------------------------------------------------------------------------- void CNPC_Bullseye::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) { //If specified, we must be the enemy of the target if ( m_spawnflags & SF_BULLSEYE_ENEMYDAMAGEONLY ) { CAI_BaseNPC *pInstigator = info.GetAttacker()->MyNPCPointer(); if ( pInstigator == NULL ) return; if ( pInstigator->GetEnemy() != this ) return; } //We can bleed if we want to, we can leave decals behind... if ( ( m_spawnflags & SF_BULLSEYE_BLEED ) && ( m_takedamage == DAMAGE_NO ) ) { TraceBleed( info.GetDamage(), vecDir, ptr, info.GetDamageType() ); } BaseClass::TraceAttack( info, vecDir, ptr ); }
//------------------------------------- // Purpose: Addes the given NPC to the squad //------------------------------------- void CAI_Squad::AddToSquad(CAI_BaseNPC *pNPC) { if ( !pNPC || !pNPC->IsAlive() ) { Assert(0); return; } if ( pNPC->GetSquad() == this ) return; if ( pNPC->GetSquad() ) { pNPC->GetSquad()->RemoveFromSquad(pNPC); } if (m_SquadMembers.Count() == MAX_SQUAD_MEMBERS) { DevMsg("Error!! Squad %s is too big!!! Replacing last member\n",this->m_Name); m_SquadMembers.Remove(m_SquadMembers.Count()-1); } m_SquadMembers.AddToTail(pNPC); pNPC->SetSquad( this ); pNPC->SetSquadName( m_Name ); if ( m_SquadMembers.Count() > 1 ) { CAI_BaseNPC *pCopyFrom = m_SquadMembers[0]; CAI_Enemies *pEnemies = pCopyFrom->GetEnemies(); AIEnemiesIter_t iter; AI_EnemyInfo_t *pInfo = pEnemies->GetFirst( &iter ); while ( pInfo ) { pNPC->UpdateEnemyMemory( pInfo->hEnemy, pInfo->vLastKnownLocation, pCopyFrom ); pInfo = pEnemies->GetNext( &iter ); } } }
//========================================================= // Crea un NPC Grunt. //========================================================= CAI_BaseNPC *CSurvivalZombieSpawn::MakeGrunt() { // Desactivado if ( Disabled || !sv_spawn_zombies.GetBool() ) return NULL; CAI_BaseNPC *pGrunt = (CAI_BaseNPC *)CreateEntityByName("npc_grunt"); // Ocurrio algún problema. if ( !pGrunt ) { Warning("[SURVIVAL ZOMBIE MAKER] Ha ocurrido un problema al intentar crear un grunt. \r\n"); return NULL; } Vector origin; if ( !CanMakeNPC(pGrunt, &origin) ) return NULL; // Lugar de creación. pGrunt->SetAbsOrigin(origin); // Nombre del Grunt. // [¡NO CAMBIAR!] Es utilizado por otras entidades para referirse a los zombis creados por esta entidad. pGrunt->SetName(MAKE_STRING("survival_grunt")); QAngle angles = GetAbsAngles(); angles.x = 0.0; angles.z = 0.0; pGrunt->SetAbsAngles(angles); // Tiene que caer al suelo. pGrunt->AddSpawnFlags(SF_NPC_FALL_TO_GROUND); // Creamos al grunt, le decimos quien es su dios (creador) y lo activamos. DispatchSpawn(pGrunt); pGrunt->SetOwnerEntity(this); DispatchActivate(pGrunt); // Ahora creamos la música. pGruntMusic = (CEnvSound *)CreateEntityByName("env_sound"); pGruntMusic->SetSourceEntityName(MAKE_STRING("survival_grunt")); pGruntMusic->SetSoundName(MAKE_STRING("NPC_Grunt.BackgroundMusic")); pGruntMusic->SetRadius(8000.0); pGruntMusic->SetAbsOrigin(origin); DispatchSpawn(pGruntMusic); pGruntMusic->SetOwnerEntity(this); DispatchActivate(pGruntMusic); pGruntMusic->SetPitch(100); pGruntMusic->SetVolume(1); pGruntMusic->PlayManual(1, 100); return pGrunt; }
void CWeaponOICW::Operator_HandleAnimEvent(animevent_t *pEvent, CBaseCombatCharacter *pOperator) { switch (pEvent->event) { case EVENT_WEAPON_AR2: { Vector vecShootOrigin, vecShootDir; vecShootOrigin = pOperator->Weapon_ShootPosition(); CAI_BaseNPC *npc = pOperator->MyNPCPointer(); ASSERT(npc != NULL); vecShootDir = npc->GetActualShootTrajectory(vecShootOrigin); WeaponSound(SINGLE_NPC); pOperator->FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2); pOperator->DoMuzzleFlash(); m_iClip1 = m_iClip1 - 1; } break; default: CBaseCombatWeapon::Operator_HandleAnimEvent(pEvent, pOperator); break; } }
//----------------------------------------------------------------------------- // Purpose: // Input : *pOperator - //----------------------------------------------------------------------------- void CWeaponShotgun::FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ) { Vector vecShootOrigin, vecShootDir; CAI_BaseNPC *npc = pOperator->MyNPCPointer(); ASSERT( npc != NULL ); WeaponSound( SINGLE_NPC ); pOperator->DoMuzzleFlash(); m_iClip1 = m_iClip1 - 1; if ( bUseWeaponAngles ) { QAngle angShootDir; GetAttachment( LookupAttachment( "muzzle" ), vecShootOrigin, angShootDir ); AngleVectors( angShootDir, &vecShootDir ); } else { vecShootOrigin = pOperator->Weapon_ShootPosition(); vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); } pOperator->FireBullets( 8, vecShootOrigin, vecShootDir, GetBulletSpread(), MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0 ); }
//========================================================= // Crea un Zombi sin colisiones. //========================================================= CAI_BaseNPC *CDirectorSpawn::MakeNoCollisionNPC(bool Horde, bool disclosePlayer) { // Desactivado if ( Disabled ) return NULL; // Creamos el NPC normalmente. CAI_BaseNPC *pNPC = MakeNPC(Horde, disclosePlayer, false); // Emm... ¿puso todas las clases en "no crear"? :genius: if ( !pNPC ) { Warning("[DIRECTOR NPC] Ha ocurrido un problema al intentar crear un zombie. \r\n"); return NULL; } // Lugar de creación. pNPC->SetAbsOrigin(GetAbsOrigin()); // No colisiona con otros NPC's. pNPC->SetCollisionGroup(COLLISION_GROUP_SPECIAL_NPC); return pNPC; }
void CAI_GoalEntity::ResolveNames() { m_actors.SetCount( 0 ); CBaseEntity *pEntity = NULL; for (;;) { switch ( m_SearchType ) { case ST_ENTNAME: { pEntity = gEntList.FindEntityByName( pEntity, m_iszActor, NULL ); break; } case ST_CLASSNAME: { pEntity = gEntList.FindEntityByClassname( pEntity, STRING( m_iszActor ) ); break; } } if ( !pEntity ) break; CAI_BaseNPC *pActor = pEntity->MyNPCPointer(); if ( pActor && pActor->GetState() != NPC_STATE_DEAD ) { AIHANDLE temp; temp = pActor; m_actors.AddToTail( temp ); } } m_hGoalEntity = gEntList.FindEntityByName( NULL, m_iszGoal, NULL ); }
bool CAI_Enemies::ShouldDiscardMemory( AI_EnemyInfo_t *pMemory ) { CBaseEntity *pEnemy = pMemory->hEnemy; if ( pEnemy ) { CAI_BaseNPC *pEnemyNPC = pEnemy->MyNPCPointer(); if ( pEnemyNPC && pEnemyNPC->GetState() == NPC_STATE_DEAD ) return true; } else { if ( !pMemory->bDangerMemory ) return true; } if ( !pMemory->bUnforgettable && gpGlobals->curtime > pMemory->timeLastSeen + m_flEnemyDiscardTime ) { return true; } return false; }
void CWeaponShotgun::FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ) { Vector vecShootOrigin, vecShootDir; CAI_BaseNPC *npc = pOperator->MyNPCPointer(); ASSERT( npc != NULL ); WeaponSound( SINGLE_NPC ); pOperator->DoMuzzleFlash(); m_iClip1 -= 1; if ( bUseWeaponAngles ) { QAngle angShootDir; GetAttachment( LookupAttachment( "muzzle" ), vecShootOrigin, angShootDir ); AngleVectors( angShootDir, &vecShootDir ); } else { vecShootOrigin = pOperator->Weapon_ShootPosition(); vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); } PrepareFireBullets(5, pOperator, vecShootOrigin, vecShootDir, false); }
bool CDirector_Manager::AddBoss(const Vector &vecPosition) { // No se ha podido acceder al Director. if ( !Director() ) return false; // No es posible crear un jefe aquí. if ( !CanMake(vecPosition) ) return false; // Creamos un jefe de la lista. const char *pBossName = GetBossClass(); CAI_BaseNPC *pBoss = (CAI_BaseNPC *)CreateEntityByName(pBossName); QAngle angles = RandomAngle(0, 360); angles.x = 0.0; angles.z = 0.0; pBoss->SetAbsAngles(angles); // Establecemos la ubicación de creación. pBoss->SetAbsOrigin(vecPosition); // Debe caer al suelo y desaparecer. pBoss->AddSpawnFlags(SF_NPC_FALL_TO_GROUND); UTIL_DropToFloor(pBoss, MASK_SOLID); ConVarRef director_debug("director_debug"); // Marcamos al nodo afortunado. if ( director_debug.GetBool() ) NDebugOverlay::Box(vecPosition, -Vector(15, 15, 15), Vector(15, 15, 15), 223, 1, 1, 10, 3.0f); DispatchSpawn(pBoss); pBoss->SetOwnerEntity(Director()); DispatchActivate(pBoss); // ¡¡NO CAMBIAR!! pBoss->SetName(MAKE_STRING(BOSS_NAME)); // Al parecer se atoro en una pared. if ( !PostSpawn(pBoss) ) return false; DevMsg("[MANAGER] Se ha creado un JEFE. \r\n"); ++Director()->BossSpawned; Director()->BossPendient = false; Director()->ChildsKilled = 0; return true; }
//----------------------------------------------------------------------------- // Purpose: Gets event from anim stream and throws the object // Input : // Output : //----------------------------------------------------------------------------- void CWeaponBrickbat::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) { switch( pEvent->event ) { case EVENT_WEAPON_THROW: { CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); if (!pNPC) { return; } Vector vec_target = pNPC->GetEnemyLKP(); // ----------------------------------------------------- // Get position of throw // ----------------------------------------------------- // If owner has a hand, set position to the hand bone position Vector launchPos; int iBIndex = pNPC->LookupBone("Bip01 R Hand"); if (iBIndex != -1) { Vector origin; QAngle angles; pNPC->GetBonePosition( iBIndex, launchPos, angles); } // Otherwise just set to in front of the owner else { Vector vFacingDir = pNPC->BodyDirection2D( ); vFacingDir = vFacingDir * 60.0; launchPos = pNPC->GetLocalOrigin()+vFacingDir; } ThrowBrickbat( launchPos, m_vecTossVelocity, sk_npc_dmg_brickbat.GetFloat()); // Drop the weapon and remove as no more ammo pNPC->Weapon_Drop( this ); UTIL_Remove( this ); } break; default: BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); break; } }
void asw_drone_cycle_f() { CBaseEntity* pEntity = NULL; while ((pEntity = gEntList.FindEntityByClassname( pEntity, "asw_drone" )) != NULL) { CAI_BaseNPC* pAI = dynamic_cast<CAI_BaseNPC*>(pEntity); if (pAI) { Msg("[%d:%s] Cycle=%f", pAI->entindex(), pAI->GetClassname(), pAI->GetCycle()); int iLayers = pAI->GetNumAnimOverlays(); for (int i=0;i<iLayers;i++) { Msg(" L%d: Cycle=%f Weight=%f\n", i, pAI->GetLayerCycle(i), pAI->GetLayerWeight(i)); } } } }
CAI_BaseNPC* CASW_Harvester::SpawnAlien() { if (asw_harverter_suppress_children.GetBool()) return NULL; CBaseEntity *pEntity = CreateEntityByName( "asw_parasite_defanged" ); CAI_BaseNPC *pNPC = dynamic_cast<CAI_BaseNPC*>(pEntity); if ( !pNPC ) { Warning("NULL Ent in CASW_Harvester!\n"); return NULL; } pNPC->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); pNPC->SetAbsOrigin( GetAbsOrigin() + Vector( 0, 0, asw_harvester_spawn_height.GetFloat() ) ); // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. QAngle angles = GetAbsAngles(); angles.x = 0.0; angles.z = 0.0; pNPC->SetAbsAngles( angles ); IASW_Spawnable_NPC* pSpawnable = dynamic_cast<IASW_Spawnable_NPC*>(pNPC); ASSERT(pSpawnable); if ( !pSpawnable ) { Warning("NULL Spawnable Ent in CASW_Harvester!\n"); UTIL_Remove(pNPC); return NULL; } DispatchSpawn( pNPC ); pNPC->SetOwnerEntity( this ); pNPC->Activate(); CASW_Parasite *pParasite = dynamic_cast<CASW_Parasite*>(pNPC); if (pParasite) { m_iCrittersAlive++; pParasite->SetMother(this); } return pNPC; }
void CLagCompensationManager::UpdateAIIndexes() { CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); int nAIs = g_AI_Manager.NumAIs(); for ( int i = 0; i < nAIs; i++ ) { CAI_BaseNPC *pNPC = ppAIs[i]; if ( pNPC && pNPC->GetAIIndex() != i ) // index of NPC has changed {// move their data to their new index, probably wanting to delete the old track record int oldIndex = pNPC->GetAIIndex(); int newIndex = i; //Msg("Lag compensation record adjusting, moving from index %i to %i\n",oldIndex,newIndex); CUtlFixedLinkedList< LagRecord > *track = &m_EntityTrack[ oldIndex ]; CUtlFixedLinkedList< LagRecord > *oldTrack = &m_EntityTrack[ newIndex ]; m_EntityTrack[oldIndex] = *oldTrack; m_EntityTrack[newIndex] = *track; if ( oldTrack->Count() > 0 ) // there's data in the auld yin, probably from someone newly dead, {// but if not we'll swap them round so that the old one can then fix their AI index //Msg("Index %i already contains data!\n",newIndex); for ( int j=0; j<nAIs; j++ ) { CAI_BaseNPC *pConflictingNPC = ppAIs[j]; if ( pConflictingNPC && pConflictingNPC->GetAIIndex() == newIndex ) {// found the conflicting NPC, swap them into the old index pConflictingNPC->SetAIIndex(oldIndex); // presumably they'll fix themselves further down the loop Warning("Lag compensation adjusting entity index, swapping with an existing entity! (%i & %i)\n",oldIndex,newIndex); break; } } } pNPC->SetAIIndex(newIndex); } } //========= End Of AI Patch ======= }
bool CPhysicsNPCSolver::IsIntersecting() { CAI_BaseNPC *pNPC = m_hNPC.Get(); CBaseEntity *pPhysics = m_hEntity.Get(); if ( pNPC && pPhysics ) { Ray_t ray; // bloated bounds to force slight separation Vector mins = pNPC->WorldAlignMins() - Vector(1,1,1); Vector maxs = pNPC->WorldAlignMaxs() + Vector(1,1,1); ray.Init( pNPC->GetAbsOrigin(), pNPC->GetAbsOrigin(), mins, maxs ); trace_t tr; enginetrace->ClipRayToEntity( ray, pNPC->PhysicsSolidMaskForEntity(), pPhysics, &tr ); if ( tr.startsolid ) return true; } return false; }
//----------------------------------------------------------------------------- // Purpose: Check the weapon LOS for an owner at an arbitrary position // If bSetConditions is true, LOS related conditions will also be set //----------------------------------------------------------------------------- bool CASW_Weapon::WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ) { bool bHasLOS = BaseClass::WeaponLOSCondition(ownerPos, targetPos, bSetConditions); // if the weapon has LOS, then do another wider trace to check we don't hit any friendlies // this is to stop the AI marines shooting way too close to other marines, which stops the player thinking about positioning so much if (bHasLOS && GetOwner() && asw_weapon_safety_hull.GetFloat() > 0) { CAI_BaseNPC* npcOwner = GetOwner()->MyNPCPointer(); Vector vecRelativeShootPosition; VectorSubtract( npcOwner->Weapon_ShootPosition(), npcOwner->GetAbsOrigin(), vecRelativeShootPosition ); // Find its relative shoot position Vector barrelPos = ownerPos + vecRelativeShootPosition; CASWWeaponLOSFilter traceFilter( GetOwner(), npcOwner->GetEnemy(), COLLISION_GROUP_BREAKABLE_GLASS ); // Use the custom LOS trace filter trace_t tr; UTIL_TraceHull( barrelPos, targetPos, Vector(-asw_weapon_safety_hull.GetFloat(), -asw_weapon_safety_hull.GetFloat(), -asw_weapon_safety_hull.GetFloat()), Vector(asw_weapon_safety_hull.GetFloat(), asw_weapon_safety_hull.GetFloat(), asw_weapon_safety_hull.GetFloat()), MASK_SHOT, &traceFilter, &tr ); if ( tr.fraction == 1.0 || tr.m_pEnt == npcOwner->GetEnemy() ) return true; // if a friendly is in the way, then we report failure CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( tr.m_pEnt ); if ( pBCC ) { if ( npcOwner->IRelationType( pBCC ) == D_HT ) return true; if ( bSetConditions ) { npcOwner->SetCondition( COND_WEAPON_BLOCKED_BY_FRIEND ); } return false; } } return bHasLOS; }
bool CAI_MoveAndShootOverlay::CanAimAtEnemy() { CAI_BaseNPC *pOuter = GetOuter(); bool result = false; bool resetConditions = false; CAI_ScheduleBits savedConditions; if ( !GetOuter()->ConditionsGathered() ) { savedConditions = GetOuter()->AccessConditionBits(); GetOuter()->GatherEnemyConditions( GetOuter()->GetEnemy() ); } if ( pOuter->HasCondition( COND_CAN_RANGE_ATTACK1 ) ) { result = true; } else if ( !pOuter->HasCondition( COND_ENEMY_DEAD ) && !pOuter->HasCondition( COND_TOO_FAR_TO_ATTACK ) && !pOuter->HasCondition( COND_ENEMY_TOO_FAR ) && !pOuter->HasCondition( COND_ENEMY_OCCLUDED ) ) { result = true; } // If we don't have a weapon, stop // This catches NPCs who holster their weapons while running if ( !HasAvailableRangeAttack() ) { result = false; } if ( resetConditions ) { GetOuter()->AccessConditionBits() = savedConditions; } return result; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTemplateNPCMaker::MakeNPC( void ) { // If we should be using the radius spawn method instead, do so if ( m_flRadius && HasSpawnFlags(SF_NPCMAKER_ALWAYSUSERADIUS) ) { MakeNPCInRadius(); return; } if (!CanMakeNPC( ( m_iszDestinationGroup != NULL_STRING ) )) return; CNPCSpawnDestination *pDestination = NULL; if ( m_iszDestinationGroup != NULL_STRING ) { pDestination = FindSpawnDestination(); if ( !pDestination ) { DevMsg( 2, "%s '%s' failed to find a valid spawnpoint in destination group: '%s'\n", GetClassname(), STRING(GetEntityName()), STRING(m_iszDestinationGroup) ); return; } } CAI_BaseNPC *pent = NULL; CBaseEntity *pEntity = NULL; MapEntity_ParseEntity( pEntity, STRING(m_iszTemplateData), NULL ); if ( pEntity != NULL ) { pent = (CAI_BaseNPC *)pEntity; } if ( !pent ) { Warning("NULL Ent in NPCMaker!\n" ); return; } if ( pDestination ) { pent->SetAbsOrigin( pDestination->GetAbsOrigin() ); // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. QAngle angles = pDestination->GetAbsAngles(); angles.x = 0.0; angles.z = 0.0; pent->SetAbsAngles( angles ); pDestination->OnSpawnedNPC( pent ); } else { pent->SetAbsOrigin( GetAbsOrigin() ); // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. QAngle angles = GetAbsAngles(); angles.x = 0.0; angles.z = 0.0; pent->SetAbsAngles( angles ); } m_OnSpawnNPC.Set( pEntity, pEntity, this ); if ( m_spawnflags & SF_NPCMAKER_FADE ) { pent->AddSpawnFlags( SF_NPC_FADE_CORPSE ); } pent->RemoveSpawnFlags( SF_NPC_TEMPLATE ); if ( ( m_spawnflags & SF_NPCMAKER_NO_DROP ) == false ) { pent->RemoveSpawnFlags( SF_NPC_FALL_TO_GROUND ); // don't fall, slam } ChildPreSpawn( pent ); DispatchSpawn( pent ); pent->SetOwnerEntity( this ); DispatchActivate( pent ); ChildPostSpawn( pent ); m_nLiveChildren++;// count this NPC if (!(m_spawnflags & SF_NPCMAKER_INF_CHILD)) { m_nMaxNumNPCs--; if ( IsDepleted() ) { m_OnAllSpawned.FireOutput( this, this ); // Disable this forever. Don't kill it because it still gets death notices SetThink( NULL ); SetUse( NULL ); } } }
//----------------------------------------------------------------------------- // Purpose: Creates the NPC. //----------------------------------------------------------------------------- void CNPCMaker::MakeNPC( void ) { if (!CanMakeNPC()) return; CAI_BaseNPC *pent = (CAI_BaseNPC*)CreateEntityByName( STRING(m_iszNPCClassname) ); if ( !pent ) { Warning("NULL Ent in NPCMaker!\n" ); return; } // ------------------------------------------------ // Intialize spawned NPC's relationships // ------------------------------------------------ pent->SetRelationshipString( m_RelationshipString ); m_OnSpawnNPC.Set( pent, pent, this ); pent->SetAbsOrigin( GetAbsOrigin() ); // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. QAngle angles = GetAbsAngles(); angles.x = 0.0; angles.z = 0.0; pent->SetAbsAngles( angles ); pent->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); if ( m_spawnflags & SF_NPCMAKER_FADE ) { pent->AddSpawnFlags( SF_NPC_FADE_CORPSE ); } pent->m_spawnEquipment = m_spawnEquipment; pent->SetSquadName( m_SquadName ); pent->SetHintGroup( m_strHintGroup ); ChildPreSpawn( pent ); DispatchSpawn( pent ); pent->SetOwnerEntity( this ); DispatchActivate( pent ); if ( m_ChildTargetName != NULL_STRING ) { // if I have a netname (overloaded), give the child NPC that name as a targetname pent->SetName( m_ChildTargetName ); } ChildPostSpawn( pent ); m_nLiveChildren++;// count this NPC if (!(m_spawnflags & SF_NPCMAKER_INF_CHILD)) { m_nMaxNumNPCs--; if ( IsDepleted() ) { m_OnAllSpawned.FireOutput( this, this ); // Disable this forever. Don't kill it because it still gets death notices SetThink( NULL ); SetUse( NULL ); } } }