//------------------------------------------------------------------------------ // Purpose: //------------------------------------------------------------------------------ CBaseEntity* CScriptedTarget::FindEntity( void ) { // --------------------------------------------------- // First try to find the entity by name // --------------------------------------------------- CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, m_iszEntity ); if (pEntity && pEntity->GetFlags() & FL_NPC) { CAI_BaseNPC* pNPC = pEntity->MyNPCPointer(); if (pNPC->DispatchInteraction( g_interactionScriptedTarget, NULL, this )) { return pEntity; } } // --------------------------------------------------- // If that fails, assume we were given a classname // and find nearest entity in radius of that class // --------------------------------------------------- float flNearestDist = MAX_COORD_RANGE; CBaseEntity* pNearestEnt = NULL; CBaseEntity* pTestEnt = NULL; for ( CEntitySphereQuery sphere( GetAbsOrigin(), m_flRadius ); ( pTestEnt = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) { if (pTestEnt->GetFlags() & FL_NPC) { if (FClassnameIs( pTestEnt, STRING(m_iszEntity))) { float flTestDist = (pTestEnt->GetAbsOrigin() - GetAbsOrigin()).Length(); if (flTestDist < flNearestDist) { flNearestDist = flTestDist; pNearestEnt = pTestEnt; } } } } // UNDONE: If nearest fails, try next nearest if (pNearestEnt) { CAI_BaseNPC* pNPC = pNearestEnt->MyNPCPointer(); if (pNPC->DispatchInteraction( g_interactionScriptedTarget, NULL, this )) { return pNearestEnt; } } return NULL; }
CBaseMonster *CScriptedSentence::FindEntity( void ) { CBaseEntity* pTargetEnt = nullptr; CBaseMonster* pMonster = nullptr; while( (pTargetEnt = UTIL_FindEntityByTargetname( pTargetEnt, STRING( m_iszEntity ) )) ) { if( (pMonster = pTargetEnt->MyMonsterPointer()) ) { if( AcceptableSpeaker( pMonster ) ) return pMonster; //ALERT( at_console, "%s (%s), not acceptable\n", pMonster->GetClassname(), pMonster->GetTargetname() ); } } pTargetEnt = nullptr; while( (pTargetEnt = UTIL_FindEntityInSphere( pTargetEnt, GetAbsOrigin(), m_flRadius )) ) { if( pTargetEnt->ClassnameIs( m_iszEntity ) ) { if( pTargetEnt->GetFlags().Any( FL_MONSTER ) ) { pMonster = pTargetEnt->MyMonsterPointer(); if( AcceptableSpeaker( pMonster ) ) return pMonster; } } } return nullptr; }
//========================================================= // MeleeAttack1() // Ataque cuerpo a cuerpo #1 // En este caso: //========================================================= void CNPC_Scient::MeleeAttack1() { /* Ataque cuerpo a cuerpo ¡Ejemplo! En este código el NPC aventará y empujara al usuario con un golpe. Esto es solo un ejemplo, modifique o elimine. */ // Atacar CBaseEntity *pHurt = CheckTraceHullAttack(70, Vector(-16,-16,-16), Vector(16,16,16), sk_grunt_dmg_high.GetFloat(), DMG_SLASH | DMG_ALWAYSGIB); // ¿Le hice daño? if (pHurt) { Vector forward, up; AngleVectors(GetAbsAngles(), &forward, NULL, &up); // Aturdirlo if (pHurt->GetFlags() & (FL_NPC | FL_CLIENT)) pHurt->ViewPunch(QAngle(70, 0, -70)); // Aventarlo por los aires. pHurt->ApplyAbsVelocityImpulse(400 * (up + 1*forward)); } AttackSound(); }
//----------------------------------------------------------------------------- // Purpose: Checks if the player is standing on a moving entity and adjusts velocity and // basevelocity appropriately // Input : *player - // frametime - //----------------------------------------------------------------------------- void CPlayerMove::CheckMovingGround( CBasePlayer *player, double frametime ) { VPROF( "CPlayerMove::CheckMovingGround()" ); CBaseEntity *groundentity; if ( player->GetFlags() & FL_ONGROUND ) { groundentity = player->GetGroundEntity(); if ( groundentity && ( groundentity->GetFlags() & FL_CONVEYOR) ) { Vector vecNewVelocity; groundentity->GetGroundVelocityToApply( vecNewVelocity ); if ( player->GetFlags() & FL_BASEVELOCITY ) { vecNewVelocity += player->GetBaseVelocity(); } player->SetBaseVelocity( vecNewVelocity ); player->AddFlag( FL_BASEVELOCITY ); } } if ( !( player->GetFlags() & FL_BASEVELOCITY ) ) { // Apply momentum (add in half of the previous frame of velocity first) player->ApplyAbsVelocityImpulse( (1.0 + ( frametime * 0.5 )) * player->GetBaseVelocity() ); player->SetBaseVelocity( vec3_origin ); } player->RemoveFlag( FL_BASEVELOCITY ); }
//Pose la mine sur son support une fois l'animation terminée void CWeaponMine::FinishAttach( void ){ CHL2MP_Player *pOwner = ToHL2MPPlayer( GetOwner() ); if (!pOwner) return; Vector vecSrc, vecAiming; vecSrc = pOwner->EyePosition(); QAngle angles = pOwner->GetLocalAngles(); AngleVectors( angles, &vecAiming ); trace_t tr; UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 60), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); if (tr.fraction < 1.0) { if (tr.m_pEnt) { //On attache pas la mine sur une entité vivante CBaseEntity *pEntity = tr.m_pEnt; CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity ); if (pBCC){ m_bAttachMine = false; m_bNeedReload = true; return; } #ifndef CLIENT_DLL //On vérifie qu'il n 'y a pas déjà une mine sur le support visé CBaseEntity* pResult = gEntList.FindEntityByClassname(NULL,"npc_mine"); while (pResult) { if((pResult->GetAbsOrigin() - tr.endpos).Length() < MINE_DISTANCE){ m_bAttachMine = false; m_bNeedReload = true; return; } pResult = gEntList.FindEntityByClassname(pResult,"npc_mine"); } if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) { QAngle angles; VectorAngles(tr.plane.normal, angles); angles.x += 90; CBaseEntity *pEnt = CBaseEntity::Create( "npc_mine", tr.endpos + tr.plane.normal * 3, angles, NULL ); CNPCMine *pMine = (CNPCMine *)pEnt; pMine->m_hOwner = GetOwner(); ChooseMineColor(pMine); pMine->AttachToEntity( pEntity ); pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); } #endif } } m_bAttachMine = false; m_bNeedReload = true; }
//========================================================= // Deathnotice. //========================================================= void CTeamplayRules::DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info ) { if ( m_DisableDeathMessages ) return; CBaseEntity *pKiller = info.GetAttacker(); if ( pVictim && pKiller && pKiller->GetFlags() & FL_CLIENT ) { CBasePlayer *pk = (CBasePlayer*)pKiller; if ( pk ) { if ( (pk != pVictim) && (PlayerRelationship( pVictim, pk ) == GR_TEAMMATE) ) { CRelieableBroadcastRecipientFilter filter; // TODO we are sending this message twice ?? in BaseClass::DeathNotice too. UserMessageBegin( filter, "DeathMsg" ); WRITE_BYTE( pKiller->entindex() ); // the killer WRITE_BYTE( pVictim->entindex() ); // the victim WRITE_STRING( "teammate" ); // flag this as a teammate kill MessageEnd(); return; } } } BaseClass::DeathNotice( pVictim, info ); }
/* cmove hook function */ bool __stdcall HookedCreateMove( float SampleTime, CUserCmd* UserCmd ) { if ( !UserCmd->CommandNumber ) return true; /* code goes here */ CBaseEntity * Local = ( CBaseEntity* ) ClientEntityList->GetClientEntity( EngineClient->GetLocalPlayer( ) ); if ( !Local ) return true; /* example bhop */ if ( UserCmd->Buttons & IN_JUMP ) { if ( !( Local->GetFlags( ) & FL_ONGROUND ) ) { UserCmd->Buttons &= ~IN_JUMP; } } // not accurate and does not look legit, todo; save angles cmd->ViewAngles -= Local->GetPunch() * 2; return false; }
// find a viable entity bool CCineMonster::FindEntity() { m_hTargetEnt = nullptr; CBaseEntity* pTargetEnt = nullptr; CBaseMonster* pTarget = nullptr; while( ( pTargetEnt = UTIL_FindEntityByTargetname( pTargetEnt, STRING( m_iszEntity ) ) ) != nullptr ) { if( pTargetEnt->GetFlags().Any( FL_MONSTER ) ) { pTarget = pTargetEnt->MyMonsterPointer(); if( pTarget && pTarget->CanPlaySequence( FCanOverrideState(), SS_INTERRUPT_BY_NAME ) ) { m_hTargetEnt = pTarget; return true; } ALERT( at_console, "Found %s, but can't play!\n", STRING( m_iszEntity ) ); } pTarget = nullptr; } if( !pTarget ) { pTargetEnt = nullptr; while( ( pTargetEnt = UTIL_FindEntityInSphere( pTargetEnt, GetAbsOrigin(), m_flRadius ) ) != nullptr ) { if( pTargetEnt->ClassnameIs( STRING( m_iszEntity ) ) ) { if( pTargetEnt->GetFlags().Any( FL_MONSTER ) ) { pTarget = pTargetEnt->MyMonsterPointer(); if( pTarget && pTarget->CanPlaySequence( FCanOverrideState(), SS_INTERRUPT_IDLE ) ) { m_hTargetEnt = pTarget; return true; } } } } } m_hTargetEnt = nullptr; return false; }
//----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- void CWeapon_SLAM::StartTripmineAttach( void ) { // Only the player fires this way so we can cast CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); if (!pPlayer) { return; } Vector vecSrc, vecAiming; // Take the eye position and direction vecSrc = pPlayer->EyePosition(); QAngle angles = pPlayer->GetLocalAngles(); AngleVectors( angles, &vecAiming ); trace_t tr; UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); if (tr.fraction < 1.0) { // ALERT( at_console, "hit %f\n", tr.flFraction ); CBaseEntity *pEntity = tr.m_pEnt; if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) { // player "shoot" animation pPlayer->SetAnimation( PLAYER_ATTACK1 ); // ----------------------------------------- // Play attach animation // ----------------------------------------- if (m_bDetonatorArmed) { SendWeaponAnim(ACT_SLAM_STICKWALL_ATTACH); } else { SendWeaponAnim(ACT_SLAM_TRIPMINE_ATTACH); } m_bNeedReload = true; m_bAttachTripmine = true; m_bNeedDetonatorDraw = m_bDetonatorArmed; } else { // ALERT( at_console, "no deploy\n" ); } } m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); // SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() ); }
//----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- void CWeapon_SLAM::StartSatchelAttach( void ) { #ifndef CLIENT_DLL CBaseCombatCharacter *pOwner = GetOwner(); if (!pOwner) { return; } Vector vecSrc = pOwner->Weapon_ShootPosition( ); Vector vecAiming = pOwner->BodyDirection2D( ); trace_t tr; UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); if (tr.fraction < 1.0) { CBaseEntity *pEntity = tr.m_pEnt; if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) { // Only the player fires this way so we can cast CBasePlayer *pPlayer = ToBasePlayer( pOwner ); // player "shoot" animation pPlayer->SetAnimation( PLAYER_ATTACK1 ); //Tony; need to check the player models ! ToHL2MPPlayer(pPlayer)->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_PRIMARY ); // ----------------------------------------- // Play attach animation // ----------------------------------------- if (m_bDetonatorArmed) { SendWeaponAnim(ACT_SLAM_STICKWALL_ATTACH); } else { SendWeaponAnim(ACT_SLAM_STICKWALL_ND_ATTACH); if (!m_bDetonatorArmed) { m_bDetonatorArmed = true; m_bNeedDetonatorDraw = true; } } m_bNeedReload = true; m_bAttachSatchel = true; m_flNextPrimaryAttack = m_flNextSecondaryAttack = SLAM_REFIRE_DELAY + gpGlobals->curtime + SequenceDuration(); } } #endif }
void CNPC_Gargantua::HandleAnimEvent( animevent_t *pEvent ) { CPASAttenuationFilter filter( this ); switch( pEvent->event ) { case GARG_AE_SLASH_LEFT: { // HACKHACK!!! CBaseEntity *pHurt = GargantuaCheckTraceHullAttack( GARG_ATTACKDIST + 10.0, sk_gargantua_dmg_slash.GetFloat(), DMG_SLASH ); if (pHurt) { if ( pHurt->GetFlags() & ( FL_NPC | FL_CLIENT ) ) { pHurt->ViewPunch( QAngle( -30, -30, 30 ) ); Vector vRight; AngleVectors( GetAbsAngles(), NULL, &vRight, NULL ); pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() - vRight * 100 ); } EmitSound( filter, entindex(), "Garg.AttackHit" ); } else // Play a random attack miss sound { EmitSound( filter, entindex(),"Garg.AttackMiss" ); } } break; case GARG_AE_RIGHT_FOOT: case GARG_AE_LEFT_FOOT: UTIL_ScreenShake( GetAbsOrigin(), 4.0, 3.0, 1.0, 1500, SHAKE_START ); EmitSound( filter, entindex(), "Garg.Footstep" ); break; case GARG_AE_STOMP: StompAttack(); m_seeTime = gpGlobals->curtime + 12; break; case GARG_AE_BREATHE: EmitSound( filter, entindex(), "Garg.Breath" ); break; default: BaseClass::HandleAnimEvent(pEvent); break; } }
void CHL2MPRules::ManageObjectRelocation( void ) { int iTotal = m_hRespawnableItemsAndWeapons.Count(); if ( iTotal > 0 ) { for ( int i = 0; i < iTotal; i++ ) { CBaseEntity *pObject = m_hRespawnableItemsAndWeapons[i].Get(); if ( pObject ) { Vector vSpawOrigin; QAngle vSpawnAngles; if ( GetObjectsOriginalParameters( pObject, vSpawOrigin, vSpawnAngles ) == true ) { float flDistanceFromSpawn = (pObject->GetAbsOrigin() - vSpawOrigin ).Length(); if ( flDistanceFromSpawn > WEAPON_MAX_DISTANCE_FROM_SPAWN ) { bool shouldReset = false; IPhysicsObject *pPhysics = pObject->VPhysicsGetObject(); if ( pPhysics ) { shouldReset = pPhysics->IsAsleep(); } else { shouldReset = (pObject->GetFlags() & FL_ONGROUND) ? true : false; } if ( shouldReset ) { pObject->Teleport( &vSpawOrigin, &vSpawnAngles, NULL ); pObject->EmitSound( "AlyxEmp.Charge" ); IPhysicsObject *pPhys = pObject->VPhysicsGetObject(); if ( pPhys ) { pPhys->Wake(); } } } } } } } }
void CGargantua::HandleAnimEvent(AnimEvent_t& event) { switch( event.event ) { case GARG_AE_SLASH_LEFT: { // HACKHACK!!! CBaseEntity *pHurt = GargantuaCheckTraceHullAttack( GARG_ATTACKDIST + 10.0, gSkillData.GetGargantuaDmgSlash(), DMG_SLASH ); if (pHurt) { if ( pHurt->GetFlags().Any( FL_MONSTER | FL_CLIENT ) ) { pHurt->SetPunchAngle( Vector( -30, // pitch -30, // yaw 30 //roll ) ); //UTIL_MakeVectors( GetAbsAngles() ); // called by CheckTraceHullAttack pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() - gpGlobals->v_right * 100 ); } EMIT_SOUND_DYN ( this, CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, 50 + RANDOM_LONG(0,15) ); } else // Play a random attack miss sound EMIT_SOUND_DYN ( this, CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, 50 + RANDOM_LONG(0,15) ); Vector forward; UTIL_MakeVectorsPrivate( GetAbsAngles(), &forward, nullptr, nullptr ); } break; case GARG_AE_RIGHT_FOOT: case GARG_AE_LEFT_FOOT: UTIL_ScreenShake( GetAbsOrigin(), 4.0, 3.0, 1.0, 750 ); EMIT_SOUND_DYN ( this, CHAN_BODY, pFootSounds[ RANDOM_LONG(0,ARRAYSIZE(pFootSounds)-1) ], 1.0, ATTN_GARG, 0, PITCH_NORM + RANDOM_LONG(-10,10) ); break; case GARG_AE_STOMP: StompAttack(); m_seeTime = gpGlobals->time + 12; break; case GARG_AE_BREATHE: EMIT_SOUND_DYN ( this, CHAN_VOICE, pBreatheSounds[ RANDOM_LONG(0,ARRAYSIZE(pBreatheSounds)-1) ], 1.0, ATTN_GARG, 0, PITCH_NORM + RANDOM_LONG(-10,10) ); break; default: CBaseMonster::HandleAnimEvent( event ); break; } }
void CNPC_Gargantua::HandleAnimEvent( animevent_t *pEvent ) { CPASAttenuationFilter filter( this ); switch( pEvent->event ) { case GARG_AE_SLASH_LEFT: { // HACKHACK!!! CBaseEntity *pHurt = GargantuaCheckTraceHullAttack( GARG_ATTACKDIST + 10.0, sk_gargantua_dmg_slash.GetFloat(), DMG_SLASH ); if (pHurt) { if ( pHurt->GetFlags() & ( FL_NPC | FL_CLIENT ) ) { pHurt->ViewPunch( QAngle( -30, -30, 30 ) ); Vector vRight; AngleVectors( GetAbsAngles(), NULL, &vRight, NULL ); pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() - vRight * 100 ); } enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, pAttackHitSounds[ random->RandomInt(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, 50 + random->RandomInt(0,15) ); } else // Play a random attack miss sound enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, pAttackMissSounds[ random->RandomInt(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, 50 + random->RandomInt(0,15) ); } break; case GARG_AE_RIGHT_FOOT: case GARG_AE_LEFT_FOOT: UTIL_ScreenShake( GetAbsOrigin(), 4.0, 3.0, 1.0, 1500, SHAKE_START ); enginesound->EmitSound( filter, entindex(), CHAN_BODY, pFootSounds[ random->RandomInt(0,ARRAYSIZE(pFootSounds)-1) ], 1.0, ATTN_GARG, 0, PITCH_NORM + random->RandomInt(-10,10) ); break; case GARG_AE_STOMP: StompAttack(); m_seeTime = gpGlobals->curtime + 12; break; case GARG_AE_BREATHE: enginesound->EmitSound( filter, entindex(), CHAN_VOICE, pBreatheSounds[ random->RandomInt(0,ARRAYSIZE(pBreatheSounds)-1) ], 1.0, ATTN_GARG, 0, PITCH_NORM + random->RandomInt(-10,10) ); break; default: BaseClass::HandleAnimEvent(pEvent); break; } }
//----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- void CWeapon_SLAM::TripmineAttach( void ) { CHL2MP_Player *pOwner = ToHL2MPPlayer( GetOwner() ); if (!pOwner) { return; } m_bAttachTripmine = false; Vector vecSrc, vecAiming; // Take the eye position and direction vecSrc = pOwner->EyePosition(); QAngle angles = pOwner->GetLocalAngles(); AngleVectors( angles, &vecAiming ); trace_t tr; UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); if (tr.fraction < 1.0) { CBaseEntity *pEntity = tr.m_pEnt; if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) { #ifndef CLIENT_DLL QAngle angles; VectorAngles(tr.plane.normal, angles); angles.x += 90; CBaseEntity *pEnt = CBaseEntity::Create( "npc_tripmine", tr.endpos + tr.plane.normal * 3, angles, NULL ); CTripmineGrenade *pMine = (CTripmineGrenade *)pEnt; pMine->m_hOwner = GetOwner(); // Attempt to attach to entity, or just sit still in place. pMine->AttachToEntity( pEntity ); #endif pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); } } }
//----------------------------------------------------------------------------- // Purpose: Catch stalker specific messages // Input : // Output : //----------------------------------------------------------------------------- void CNPC_Stalker::HandleAnimEvent( animevent_t *pEvent ) { switch( pEvent->Event() ) { case NPC_EVENT_LEFTFOOT: { EmitSound( "NPC_Stalker.FootstepLeft", pEvent->eventtime ); } break; case NPC_EVENT_RIGHTFOOT: { EmitSound( "NPC_Stalker.FootstepRight", pEvent->eventtime ); } break; case STALKER_AE_MELEE_HIT: { CBaseEntity *pHurt; pHurt = CheckTraceHullAttack( 32, Vector(-16,-16,-16), Vector(16,16,16), sk_stalker_melee_dmg.GetFloat(), DMG_SLASH ); if ( pHurt ) { if ( pHurt->GetFlags() & (FL_NPC|FL_CLIENT) ) { pHurt->ViewPunch( QAngle( 5, 0, random->RandomInt(-10,10)) ); } // Spawn some extra blood if we hit a BCC CBaseCombatCharacter* pBCC = ToBaseCombatCharacter( pHurt ); if (pBCC) { SpawnBlood(pBCC->EyePosition(), g_vecAttackDir, pBCC->BloodColor(), sk_stalker_melee_dmg.GetFloat()); } // Play a attack hit sound EmitSound( "NPC_Stalker.Hit" ); } break; } default: BaseClass::HandleAnimEvent( pEvent ); break; } }
//----------------------------------------------------------------------------- // Purpose: Counts all the players in the zone. Fires one output per player // in the zone, one output per player out of the zone, and outputs // with the total counts of players in and out of the zone. //----------------------------------------------------------------------------- void CGamePlayerZone::InputCountPlayersInZone( inputdata_t &inputdata ) { int playersInCount = 0; int playersOutCount = 0; if ( !CanFireForActivator( inputdata.pActivator ) ) return; CBaseEntity *pPlayer = NULL; for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { pPlayer = UTIL_PlayerByIndex( i ); if ( pPlayer ) { trace_t trace; Hull_t hullType; hullType = HULL_HUMAN; if ( pPlayer->GetFlags() & FL_DUCKING ) { hullType = HULL_SMALL_CENTERED; } UTIL_TraceModel( pPlayer->GetAbsOrigin(), pPlayer->GetAbsOrigin(), NAI_Hull::Mins(hullType), NAI_Hull::Maxs(hullType), this, COLLISION_GROUP_NONE, &trace ); if ( trace.startsolid ) { playersInCount++; m_OnPlayerInZone.FireOutput(pPlayer, this); } else { playersOutCount++; m_OnPlayerOutZone.FireOutput(pPlayer, this); } } } m_PlayersInCount.Set(playersInCount, inputdata.pActivator, this); m_PlayersOutCount.Set(playersOutCount, inputdata.pActivator, this); }
//----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- void CWeapon_Tripwire::StartTripwireAttach( void ) { // Only the player fires this way so we can cast CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); if (!pPlayer) { return; } Vector vecSrc = pPlayer->Weapon_ShootPosition(); Vector vecAiming = pPlayer->BodyDirection3D( ); trace_t tr; UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); if (tr.fraction < 1.0) { // ALERT( at_console, "hit %f\n", tr.flFraction ); CBaseEntity *pEntity = tr.m_pEnt; if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) { // player "shoot" animation pPlayer->SetAnimation( PLAYER_ATTACK1 ); // ----------------------------------------- // Play attach animation // ----------------------------------------- SendWeaponAnim(ACT_SLAM_TRIPMINE_ATTACH); m_bNeedReload = true; m_bAttachTripwire = true; } else { // ALERT( at_console, "no deploy\n" ); } } m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); // SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() ); }
int CAI_Senses::LookForObjects( int iDistance ) { const int BOX_QUERY_MASK = FL_OBJECT; int nSeen = 0; if ( gpGlobals->curtime - m_TimeLastLookMisc > AI_MISC_SEARCH_TIME ) { AI_PROFILE_SENSES(CAI_Senses_LookForObjects); m_TimeLastLookMisc = gpGlobals->curtime; BeginGather(); float distSq = ( iDistance * iDistance ); const Vector &origin = GetAbsOrigin(); int iter; CBaseEntity *pEnt = g_AI_SensedObjectsManager.GetFirst( &iter ); while ( pEnt ) { if ( pEnt->GetFlags() & BOX_QUERY_MASK ) { if ( origin.DistToSqr(pEnt->GetAbsOrigin()) < distSq && Look( pEnt) ) { nSeen++; } } pEnt = g_AI_SensedObjectsManager.GetNext( &iter ); } EndGather( nSeen, &m_SeenMisc ); } else { for ( int i = m_SeenMisc.Count() - 1; i >= 0; --i ) { if ( m_SeenMisc[i].Get() == NULL ) m_SeenMisc.FastRemove( i ); } nSeen = m_SeenMisc.Count(); } return nSeen; }
//----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- void CWeapon_SLAM::SatchelAttach( void ) { CBaseCombatCharacter *pOwner = GetOwner(); if (!pOwner) { return; } m_bAttachSatchel = false; Vector vecSrc = pOwner->Weapon_ShootPosition( ); Vector vecAiming = pOwner->BodyDirection2D( ); trace_t tr; UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); if (tr.fraction < 1.0) { CBaseEntity *pEntity = tr.m_pEnt; if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) { QAngle angles; VectorAngles(tr.plane.normal, angles); angles.y -= 90; angles.z -= 90; tr.endpos.z -= 6.0f; EmitSound( "Weapon_SLAM.SatchelAttach" ); CSatchelCharge *pSatchel = (CSatchelCharge*)CBaseEntity::Create( "npc_satchel", tr.endpos + tr.plane.normal * 3, angles, NULL ); pSatchel->SetMoveType( MOVETYPE_FLY ); // no gravity pSatchel->m_bIsAttached = true; pSatchel->m_bIsLive = true; pSatchel->SetThrower( GetOwner() ); pSatchel->SetOwnerEntity( ((CBaseEntity*)GetOwner()) ); pSatchel->m_pMyWeaponSLAM = this; pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); } } }
//---------------------------------------------------------------------------------- // Purpose: Returns z value of floor below given point (up to fMaxDrop inches below) // Input : // Output : //---------------------------------------------------------------------------------- float GetFloorZ(const Vector &origin, float fMaxDrop) { // trace to the ground, then pop up 8 units and place node there to make it // easier for them to connect (think stairs, chairs, and bumps in the floor). // After the routing is done, push them back down. // trace_t tr; AI_TraceLine ( origin, origin - Vector ( 0, 0, fMaxDrop ), MASK_NPCSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); // This trace is ONLY used if we hit an entity flagged with FL_WORLDBRUSH trace_t trEnt; AI_TraceLine ( origin, origin - Vector ( 0, 0, fMaxDrop ), MASK_NPCSOLID, NULL, COLLISION_GROUP_NONE, &trEnt ); // Did we hit something closer than the floor? if ( trEnt.fraction < tr.fraction ) { // If it was a world brush entity, copy the node location if ( trEnt.m_pEnt ) { CBaseEntity *e = trEnt.m_pEnt; if ( e && ( e->GetFlags() & FL_WORLDBRUSH ) ) { tr.endpos = trEnt.endpos; } } } return tr.endpos.z; }
//----------------------------------------------------------------------------- // Purpose: Give the harpoon a yank //----------------------------------------------------------------------------- void CWeaponHarpoon::YankHarpoon( void ) { CBasePlayer *pPlayer = dynamic_cast<CBasePlayer*>( GetOwner() ); if ( !pPlayer ) return; #if !defined( CLIENT_DLL ) if ( m_bActiveHarpoon && m_hHarpoon.Get() ) { // If the harpoon's impaled something, pull it towards me CBaseEntity *pTarget = m_hHarpoon->GetImpaledTarget(); if ( pTarget ) { if ( !pTarget->IsBSPModel() && pTarget->GetMoveType() != MOVETYPE_NONE ) { // Bring him to me! EmitSound( "Harpoon.Yank" ); // Get a yank vector, and raise it a little to get them off the ground if they're on it Vector vecOverHere = ( pPlayer->GetAbsOrigin() - pTarget->GetAbsOrigin() ); VectorNormalize( vecOverHere ); if ( pTarget->GetFlags() & FL_ONGROUND ) { pTarget->SetGroundEntity( NULL ); vecOverHere.z = 0.5; } pTarget->ApplyAbsVelocityImpulse( vecOverHere * 500 ); PlayAttackAnimation( ACT_VM_HAULBACK ); } } m_hHarpoon->SetThink( SUB_Remove ); m_hHarpoon->SetNextThink( gpGlobals->curtime + 5.0 ); m_hHarpoon = NULL; m_bActiveHarpoon = false; } DetachRope(); #endif }
// Find an entity that I'm interested in and precache the sounds he'll need in the sequence. void CCineMonster::Activate( void ) { CBaseMonster* pTarget = nullptr; CBaseEntity* pNextTarget = nullptr; // The entity name could be a target name or a classname // Check the targetname while( !pTarget && ( pNextTarget = UTIL_FindEntityByTargetname( pNextTarget, STRING( m_iszEntity ) ) ) != nullptr ) { if( pNextTarget->GetFlags().Any( FL_MONSTER ) ) { pTarget = pNextTarget->MyMonsterPointer(); } } // If no entity with that targetname, check the classname if( !pTarget ) { pNextTarget = nullptr; while( !pTarget && ( pNextTarget = UTIL_FindEntityByClassname( pNextTarget, STRING( m_iszEntity ) ) ) != nullptr ) { pTarget = pNextTarget->MyMonsterPointer(); } } // Found a compatible entity if( pTarget ) { void *pmodel; pmodel = GET_MODEL_PTR( pTarget->edict() ); if( pmodel ) { // Look through the event list for stuff to precache SequencePrecache( pmodel, STRING( m_iszIdle ) ); SequencePrecache( pmodel, STRING( m_iszPlay ) ); } } }
//----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- void CWeapon_SLAM::TripmineAttach( void ) { CBaseCombatCharacter *pOwner = GetOwner(); if (!pOwner) { return; } m_bAttachTripmine = false; Vector vecSrc = pOwner->Weapon_ShootPosition(); Vector vecAiming = pOwner->EyeDirection3D(); trace_t tr; UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); if (tr.fraction < 1.0) { CBaseEntity *pEntity = tr.m_pEnt; if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) { QAngle angles; VectorAngles(tr.plane.normal, angles); angles.x += 90; CBaseEntity *pEnt = CBaseEntity::Create( "npc_tripmine", tr.endpos + tr.plane.normal * 3, angles, NULL ); CTripmineGrenade *pMine = (CTripmineGrenade *)pEnt; pMine->m_hOwner = GetOwner(); pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); EmitSound( "Weapon_SLAM.TripMineAttach" ); } } }
//----------------------------------------------------------------------------- // Purpose: // Input : flDot - // flDist - // Output : int //----------------------------------------------------------------------------- int CWeaponSMG1::WeaponRangeAttack2Condition( float flDot, float flDist ) { CAI_BaseNPC *npcOwner = GetOwner()->MyNPCPointer(); return COND_NONE; /* // -------------------------------------------------------- // Assume things haven't changed too much since last time // -------------------------------------------------------- if (gpGlobals->curtime < m_flNextGrenadeCheck ) return m_lastGrenadeCondition; */ // ----------------------- // If moving, don't check. // ----------------------- if ( npcOwner->IsMoving()) return COND_NONE; CBaseEntity *pEnemy = npcOwner->GetEnemy(); if (!pEnemy) return COND_NONE; Vector vecEnemyLKP = npcOwner->GetEnemyLKP(); if ( !( pEnemy->GetFlags() & FL_ONGROUND ) && pEnemy->GetWaterLevel() == 0 && vecEnemyLKP.z > (GetAbsOrigin().z + WorldAlignMaxs().z) ) { //!!!BUGBUG - we should make this check movetype and make sure it isn't FLY? Players who jump a lot are unlikely to // be grenaded. // don't throw grenades at anything that isn't on the ground! return COND_NONE; } // -------------------------------------- // Get target vector // -------------------------------------- Vector vecTarget; if (random->RandomInt(0,1)) { // magically know where they are vecTarget = pEnemy->WorldSpaceCenter(); } else { // toss it to where you last saw them vecTarget = vecEnemyLKP; } // vecTarget = m_vecEnemyLKP + (pEnemy->BodyTarget( GetLocalOrigin() ) - pEnemy->GetLocalOrigin()); // estimate position // vecTarget = vecTarget + pEnemy->m_vecVelocity * 2; if ( ( vecTarget - npcOwner->GetLocalOrigin() ).Length2D() <= COMBINE_MIN_GRENADE_CLEAR_DIST ) { // crap, I don't want to blow myself up m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full second. return (COND_NONE); } // --------------------------------------------------------------------- // Are any friendlies near the intended grenade impact area? // --------------------------------------------------------------------- CBaseEntity *pTarget = NULL; while ( ( pTarget = gEntList.FindEntityInSphere( pTarget, vecTarget, COMBINE_MIN_GRENADE_CLEAR_DIST ) ) != NULL ) { //Check to see if the default relationship is hatred, and if so intensify that if ( npcOwner->IRelationType( pTarget ) == D_LI ) { // crap, I might blow my own guy up. Don't throw a grenade and don't check again for a while. m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full second. return (COND_WEAPON_BLOCKED_BY_FRIEND); } } // --------------------------------------------------------------------- // Check that throw is legal and clear // --------------------------------------------------------------------- // FIXME: speed is based on difficulty... Vector vecToss = VecCheckThrow( this, npcOwner->GetLocalOrigin() + Vector(0,0,60), vecTarget, 600.0, 0.5 ); if ( vecToss != vec3_origin ) { m_vecTossVelocity = vecToss; // don't check again for a while. // JAY: HL1 keeps checking - test? //m_flNextGrenadeCheck = gpGlobals->curtime; m_flNextGrenadeCheck = gpGlobals->curtime + 0.3; // 1/3 second. return COND_CAN_RANGE_ATTACK2; } else { // don't check again for a while. m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full second. return COND_WEAPON_SIGHT_OCCLUDED; } }
//========================================================= // SonicAttack //========================================================= void CNPC_Houndeye::SonicAttack ( void ) { EmitSound( "NPC_Houndeye.SonicAttack" ); if (m_pEnergyWave) { UTIL_Remove(m_pEnergyWave); } Vector vFacingDir = EyeDirection3D( ); m_pEnergyWave = (CEnergyWave*)Create( "energy_wave", EyePosition(), GetLocalAngles() ); m_flEndEnergyWaveTime = gpGlobals->curtime + 1; //<<TEMP>> magic m_pEnergyWave->SetAbsVelocity( 100*vFacingDir ); CBaseEntity *pEntity = NULL; // iterate on all entities in the vicinity. for ( CEntitySphereQuery sphere( GetAbsOrigin(), HOUNDEYE_MAX_ATTACK_RADIUS ); pEntity = sphere.GetCurrentEntity(); sphere.NextEntity() ) { if (pEntity->Classify() == CLASS_HOUNDEYE) { continue; } if (pEntity->GetFlags() & FL_NOTARGET) { continue; } IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); if ( pEntity->m_takedamage != DAMAGE_NO || pPhysicsObject) { // -------------------------- // Adjust damage by distance // -------------------------- float flDist = (pEntity->WorldSpaceCenter() - GetAbsOrigin()).Length(); float flDamageAdjuster = 1-( flDist / HOUNDEYE_MAX_ATTACK_RADIUS ); // -------------------------- // Adjust damage by direction // -------------------------- Vector forward; AngleVectors( GetAbsAngles(), &forward ); Vector vEntDir = (pEntity->GetAbsOrigin() - GetAbsOrigin()); VectorNormalize(vEntDir); float flDotPr = DotProduct(forward,vEntDir); flDamageAdjuster *= flDotPr; if (flDamageAdjuster < 0) { continue; } // -------------------------- // Adjust damage by visibility // -------------------------- if ( !FVisible( pEntity ) ) { if ( pEntity->IsPlayer() ) { // if this entity is a client, and is not in full view, inflict half damage. We do this so that players still // take the residual damage if they don't totally leave the houndeye's effective radius. We restrict it to clients // so that monsters in other parts of the level don't take the damage and get pissed. flDamageAdjuster *= 0.5; } else if ( !FClassnameIs( pEntity, "func_breakable" ) && !FClassnameIs( pEntity, "func_pushable" ) ) { // do not hurt nonclients through walls, but allow damage to be done to breakables continue; } } // ------------------------------ // Apply the damage // ------------------------------ if (pEntity->m_takedamage != DAMAGE_NO) { CTakeDamageInfo info( this, this, flDamageAdjuster * sk_Houndeye_dmg_blast.GetFloat(), DMG_SONIC | DMG_ALWAYSGIB ); CalculateExplosiveDamageForce( &info, (pEntity->GetAbsOrigin() - GetAbsOrigin()), pEntity->GetAbsOrigin() ); pEntity->TakeDamage( info ); // Throw the player if ( pEntity->IsPlayer() ) { Vector forward; AngleVectors( GetLocalAngles(), &forward ); Vector vecVelocity = pEntity->GetAbsVelocity(); vecVelocity += forward * 250 * flDamageAdjuster; vecVelocity.z = 300 * flDamageAdjuster; pEntity->SetAbsVelocity( vecVelocity ); pEntity->ViewPunch( QAngle(random->RandomInt(-20,20), 0, random->RandomInt(-20,20)) ); } } // ------------------------------ // Apply physics foces // ------------------------------ IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); if (pPhysicsObject) { float flForce = flDamageAdjuster * 8000; pPhysicsObject->ApplyForceCenter( (vEntDir+Vector(0,0,0.2)) * flForce ); pPhysicsObject->ApplyTorqueCenter( vEntDir * flForce ); } } } }
void CFuncTank::TrackTarget( void ) { trace_t tr; bool updateTime = FALSE, lineOfSight; QAngle angles; Vector barrelEnd; CBaseEntity *pTarget = NULL; barrelEnd.Init(); // Get a position to aim for if (m_pController) { // Tanks attempt to mirror the player's angles angles = m_pController->EyeAngles(); SetNextThink( gpGlobals->curtime + 0.05 ); } else { if ( IsActive() ) { SetNextThink( gpGlobals->curtime + 0.1f ); } else { return; } // ----------------------------------- // Get world target position // ----------------------------------- barrelEnd = WorldBarrelPosition(); Vector worldTargetPosition; if (m_spawnflags & SF_TANK_AIM_AT_POS) { worldTargetPosition = m_vTargetPosition; } else { CBaseEntity *pEntity = (CBaseEntity *)m_hTarget; if ( !pEntity || ( pEntity->GetFlags() & FL_NOTARGET ) ) { if ( m_targetEntityName != NULL_STRING ) // New HL2 behavior { m_hTarget = FindTarget( m_targetEntityName, NULL ); } else // HL1 style { m_hTarget = ToBasePlayer( GetContainingEntity( UTIL_FindClientInPVS( edict() ) ) ); } if ( m_hTarget != NULL ) { SetNextThink( gpGlobals->curtime ); // Think again immediately } else { if ( IsActive() ) { SetNextThink( gpGlobals->curtime + 2 ); // Wait 2 secs } if ( m_fireLast !=0 ) { m_OnLoseTarget.FireOutput(this, this); m_fireLast = 0; } } return; } pTarget = pEntity; // Calculate angle needed to aim at target worldTargetPosition = pEntity->EyePosition(); } float range = (worldTargetPosition - barrelEnd).Length(); if ( !InRange( range ) ) { m_fireLast = 0; return; } UTIL_TraceLine( barrelEnd, worldTargetPosition, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); if (m_spawnflags & SF_TANK_AIM_AT_POS) { updateTime = TRUE; m_sightOrigin = m_vTargetPosition; } else { lineOfSight = FALSE; // No line of sight, don't track if ( tr.fraction == 1.0 || tr.m_pEnt == pTarget ) { lineOfSight = TRUE; CBaseEntity *pInstance = pTarget; if ( InRange( range ) && pInstance && pInstance->IsAlive() ) { updateTime = TRUE; // Sight position is BodyTarget with no noise (so gun doesn't bob up and down) m_sightOrigin = pInstance->BodyTarget( GetLocalOrigin(), false ); } } } // Convert targetPosition to parent angles = AimBarrelAt( m_parentMatrix.WorldToLocal( m_sightOrigin ) ); } // Force the angles to be relative to the center position float offsetY = UTIL_AngleDistance( angles.y, m_yawCenter ); float offsetX = UTIL_AngleDistance( angles.x, m_pitchCenter ); angles.y = m_yawCenter + offsetY; angles.x = m_pitchCenter + offsetX; // Limit against range in y // MDB - don't check pitch! If two func_tanks are meant to align, // and one can pitch and the other cannot, this can lead to them getting // different values for angles.y. Nothing is lost by not updating yaw // because the target is not in pitch range. bool bOutsideYawRange = ( fabs( offsetY ) > m_yawRange + m_yawTolerance ); bool bOutsidePitchRange = ( fabs( offsetX ) > m_pitchRange + m_pitchTolerance ); Vector vecToTarget = m_sightOrigin - GetLocalOrigin(); // if target is outside yaw range if ( bOutsideYawRange ) { if ( angles.y > m_yawCenter + m_yawRange ) { angles.y = m_yawCenter + m_yawRange; } else if ( angles.y < (m_yawCenter - m_yawRange) ) { angles.y = (m_yawCenter - m_yawRange); } } if ( bOutsidePitchRange || bOutsideYawRange || ( vecToTarget.Length() < ( barrelEnd - GetAbsOrigin() ).Length() ) ) { // Don't update if you saw the player, but out of range updateTime = false; } if ( updateTime ) { m_lastSightTime = gpGlobals->curtime; m_persist2burst = 0; } // Move toward target at rate or less float distY = UTIL_AngleDistance( angles.y, GetLocalAngles().y ); QAngle vecAngVel = GetLocalAngularVelocity(); vecAngVel.y = distY * 10; vecAngVel.y = clamp( vecAngVel.y, -m_yawRate, m_yawRate ); // Limit against range in x angles.x = clamp( angles.x, m_pitchCenter - m_pitchRange, m_pitchCenter + m_pitchRange ); // Move toward target at rate or less float distX = UTIL_AngleDistance( angles.x, GetLocalAngles().x ); vecAngVel.x = distX * 10; vecAngVel.x = clamp( vecAngVel.x, -m_pitchRate, m_pitchRate ); SetLocalAngularVelocity( vecAngVel ); SetMoveDoneTime( 0.1 ); if ( m_pController ) return; if ( CanFire() && ( (fabs(distX) < m_pitchTolerance && fabs(distY) < m_yawTolerance) || (m_spawnflags & SF_TANK_LINEOFSIGHT) ) ) { bool fire = FALSE; Vector forward; AngleVectors( GetLocalAngles(), &forward ); forward = m_parentMatrix.ApplyRotation( forward ); if ( m_spawnflags & SF_TANK_LINEOFSIGHT ) { float length = (m_maxRange > 0) ? m_maxRange : MAX_TRACE_LENGTH; UTIL_TraceLine( barrelEnd, barrelEnd + forward * length, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); if ( tr.m_pEnt == pTarget ) fire = TRUE; } else fire = TRUE; if ( fire ) { if (m_fireLast == 0) { m_OnAquireTarget.FireOutput(this, this); } FiringSequence( barrelEnd, forward, this ); } else { if (m_fireLast !=0) { m_OnLoseTarget.FireOutput(this, this); } m_fireLast = 0; } } else { if (m_fireLast !=0) { m_OnLoseTarget.FireOutput(this, this); } m_fireLast = 0; } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CBaseEntity *CAI_FuncTankBehavior::BestEnemy( void ) { // Only use this BestEnemy call when we are on the manned gun. if ( !m_hFuncTank ||!IsMounted() ) return BaseClass::BestEnemy(); CBaseEntity *pBestEnemy = NULL; int iBestDistSq = MAX_COORD_RANGE * MAX_COORD_RANGE; // so first visible entity will become the closest. int iBestPriority = -1000; bool bBestUnreachable = false; // Forces initial check bool bBestSeen = false; bool bUnreachable = false; int iDistSq; AIEnemiesIter_t iter; // Get the current npc for checking from. CAI_BaseNPC *pNPC = GetOuter(); if ( !pNPC ) return NULL; for( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst( &iter ); pEMemory != NULL; pEMemory = GetEnemies()->GetNext( &iter ) ) { CBaseEntity *pEnemy = pEMemory->hEnemy; if ( !pEnemy || !pEnemy->IsAlive() ) continue; // UNDONE: Move relationship checks into IsValidEnemy? if ( ( pEnemy->GetFlags() & FL_NOTARGET ) || ( pNPC->IRelationType( pEnemy ) != D_HT && pNPC->IRelationType( pEnemy ) != D_FR ) || !IsValidEnemy( pEnemy ) ) continue; if ( pEMemory->timeLastSeen < pNPC->GetAcceptableTimeSeenEnemy() ) continue; if ( pEMemory->timeValidEnemy > gpGlobals->curtime ) continue; // Skip enemies that have eluded me to prevent infinite loops if ( GetEnemies()->HasEludedMe( pEnemy ) ) continue; // Establish the reachability of this enemy bUnreachable = pNPC->IsUnreachable( pEnemy ); // Check view cone of the view tank here. bUnreachable = !m_hFuncTank->IsEntityInViewCone( pEnemy ); if ( !bUnreachable ) { // It's in the viewcone. Now make sure we have LOS to it. bUnreachable = !m_hFuncTank->HasLOSTo( pEnemy ); } // If best is reachable and current is unreachable, skip the unreachable enemy regardless of priority if ( !bBestUnreachable && bUnreachable ) continue; // If best is unreachable and current is reachable, always pick the current regardless of priority if ( bBestUnreachable && !bUnreachable ) { bBestSeen = ( pNPC->GetSenses()->DidSeeEntity( pEnemy ) || pNPC->FVisible( pEnemy ) ); // @TODO (toml 04-02-03): Need to optimize CanSeeEntity() so multiple calls in frame do not recalculate, rather cache iBestPriority = pNPC->IRelationPriority( pEnemy ); iBestDistSq = static_cast<int>((pEnemy->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr()); pBestEnemy = pEnemy; bBestUnreachable = bUnreachable; } // If both are unreachable or both are reachable, chose enemy based on priority and distance else if ( pNPC->IRelationPriority( pEnemy ) > iBestPriority ) { // this entity is disliked MORE than the entity that we // currently think is the best visible enemy. No need to do // a distance check, just get mad at this one for now. iBestPriority = pNPC->IRelationPriority ( pEnemy ); iBestDistSq = static_cast<int>(( pEnemy->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr()); pBestEnemy = pEnemy; bBestUnreachable = bUnreachable; } else if ( pNPC->IRelationPriority( pEnemy ) == iBestPriority ) { // this entity is disliked just as much as the entity that // we currently think is the best visible enemy, so we only // get mad at it if it is closer. iDistSq = static_cast<int>(( pEnemy->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr()); bool bCloser = ( iDistSq < iBestDistSq ) ; if ( bCloser || !bBestSeen ) { // @TODO (toml 04-02-03): Need to optimize FVisible() so multiple calls in frame do not recalculate, rather cache bool fSeen = ( pNPC->GetSenses()->DidSeeEntity( pEnemy ) || pNPC->FVisible( pEnemy ) ); if ( ( bCloser && ( fSeen || !bBestSeen ) ) || ( !bCloser && !bBestSeen && fSeen ) ) { bBestSeen = fSeen; iBestDistSq = iDistSq; iBestPriority = pNPC->IRelationPriority( pEnemy ); pBestEnemy = pEnemy; bBestUnreachable = bUnreachable; } } } } return pBestEnemy; }
//------------------------------------------------------------------------------ // Purpose : // Input : // Output : //------------------------------------------------------------------------------ void CGrenade_Brickbat::BrickbatThink( void ) { // ----------------------------------------------------------- // Might be physically simulated so get my velocity manually // ----------------------------------------------------------- Vector vVelocity; AngularImpulse vAngVel; GetVelocity(&vVelocity,&vAngVel); // See if I can lose my owner (has dropper moved out of way?) // Want do this so owner can throw the brickbat if (GetOwnerEntity()) { trace_t tr; Vector vUpABit = GetAbsOrigin(); vUpABit.z += 5.0; CBaseEntity* saveOwner = GetOwnerEntity(); SetOwnerEntity( NULL ); UTIL_TraceEntity( this, GetAbsOrigin(), vUpABit, MASK_SOLID, &tr ); if ( tr.startsolid || tr.fraction != 1.0 ) { SetOwnerEntity( saveOwner ); } } // --------------------------------------------------------------- // Make sure we're not resting on a living thing's bounding box // --------------------------------------------------------------- if (vVelocity.Length() < 0.01) { trace_t tr; UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,10), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction < 1.0 && tr.m_pEnt) { CBaseEntity *pEntity = tr.m_pEnt; if (pEntity->GetFlags() & (FL_CLIENT | FL_NPC)) { // -------------------- // Bounce me off // -------------------- Vector vNewVel; vNewVel.y = 100; vNewVel.x = random->RandomInt(-100,100); vNewVel.z = random->RandomInt(-100,100); // If physically simulated IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); if ( pPhysicsObject ) { pPhysicsObject->AddVelocity( &vNewVel, &vAngVel ); } // Otherwise else { SetAbsVelocity( vNewVel ); } } } } if (vVelocity.Length() < 0.01) { SpawnBrickbatWeapon(); } SetNextThink( gpGlobals->curtime + 0.1f ); }
void CAPCController::TrackTarget( void ) { trace_t tr; bool updateTime = FALSE, lineOfSight; QAngle angles; Vector barrelEnd; CBaseEntity *pTarget = NULL; barrelEnd.Init(); if ( IsActive() ) { SetNextThink( gpGlobals->curtime + 0.1f ); } else { return; } // ----------------------------------- // Get world target position // ----------------------------------- barrelEnd = WorldBarrelPosition(); Vector worldTargetPosition; CBaseEntity *pEntity = (CBaseEntity *)m_hTarget; if ( !pEntity || ( pEntity->GetFlags() & FL_NOTARGET ) ) { m_hTarget = FindTarget( m_targetEntityName, NULL ); if ( IsActive() ) { SetNextThink( gpGlobals->curtime + 2 ); // Wait 2 sec s } return; } pTarget = pEntity; // Calculate angle needed to aim at target worldTargetPosition = pEntity->EyePosition(); float range = (worldTargetPosition - barrelEnd).Length(); if ( !InRange( range ) ) { m_bFireDelayed = false; return; } UTIL_TraceLine( barrelEnd, worldTargetPosition, MASK_BLOCKLOS, this, COLLISION_GROUP_NONE, &tr ); lineOfSight = FALSE; // No line of sight, don't track if ( tr.fraction == 1.0 || tr.m_pEnt == pTarget ) { lineOfSight = TRUE; CBaseEntity *pInstance = pTarget; if ( InRange( range ) && pInstance && pInstance->IsAlive() ) { updateTime = TRUE; // Sight position is BodyTarget with no noise (so gun doesn't bob up and down) m_sightOrigin = pInstance->BodyTarget( GetLocalOrigin(), false ); } } // Convert targetPosition to parent angles = AimBarrelAt( m_parentMatrix.WorldToLocal( m_sightOrigin ) ); // Force the angles to be relative to the center position float offsetY = UTIL_AngleDistance( angles.y, m_yawCenter ); float offsetX = UTIL_AngleDistance( angles.x, m_pitchCenter ); angles.y = m_yawCenter + offsetY; angles.x = m_pitchCenter + offsetX; // Move toward target at rate or less float distY = UTIL_AngleDistance( angles.y, GetLocalAngles().y ); QAngle vecAngVel = GetLocalAngularVelocity(); vecAngVel.y = distY * 10; vecAngVel.y = clamp( vecAngVel.y, -m_yawRate, m_yawRate ); // Move toward target at rate or less float distX = UTIL_AngleDistance( angles.x, GetLocalAngles().x ); vecAngVel.x = distX * 10; vecAngVel.x = clamp( vecAngVel.x, -m_pitchRate, m_pitchRate ); SetLocalAngularVelocity( vecAngVel ); SetMoveDoneTime( 0.1 ); Vector forward; AngleVectors( GetLocalAngles(), &forward ); forward = m_parentMatrix.ApplyRotation( forward ); AngleVectors(angles, &forward); if ( lineOfSight == TRUE ) { // FIXME: This will ultimately have to deal with NPCs being in the vehicle as well // See if the target is in a vehicle. If so, check its relationship CBasePlayer *pPlayer = ToBasePlayer( pTarget ); if ( pPlayer && pPlayer->IsInAVehicle() ) { IServerVehicle *pVehicle = pPlayer->GetVehicle(); if ( pVehicle->ClassifyPassenger( pPlayer, CLASS_PLAYER ) == CLASS_PLAYER) { if ( !m_bFireDelayed ) { m_bFireDelayed = true; m_flFiringDelay = gpGlobals->curtime + 1.5; // setup delay time before we start firing return; } if ( gpGlobals->curtime > m_flFiringDelay ) { m_OnFireAtTarget.Set(forward, this, this); // tell apc to fire rockets, and what direction } } } } else { m_bFireDelayed = false; // reset flag since we can no longer see target } }