void CEnvHeadcrabCanister::TestForCollisionsAgainstWorld( const Vector &vecEndPosition ) { // Splash damage! // Iterate on all entities in the vicinity. float flDamageRadius = m_flDamageRadius; float flDamage = m_flDamage; CEntity *pEntity; for ( CEntitySphereQuery sphere( vecEndPosition, flDamageRadius ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) { if ( pEntity == this ) continue; if ( !pEntity->IsSolid() ) continue; // Get distance to object and use it as a scale value. Vector vecSegment; VectorSubtract( pEntity->GetAbsOrigin(), vecEndPosition, vecSegment ); float flDistance = VectorNormalize( vecSegment ); float flFactor = 1.0f / ( flDamageRadius * (INNER_RADIUS_FRACTION - 1) ); flFactor *= flFactor; float flScale = flDistance - flDamageRadius; flScale *= flScale * flFactor; if ( flScale > 1.0f ) { flScale = 1.0f; } // Check for a physics object and apply force! Vector vecForceDir = vecSegment; IPhysicsObject *pPhysObject = pEntity->VPhysicsGetObject(); if ( pPhysObject ) { // Send it flying!!! float flMass = PhysGetEntityMass( pEntity ); vecForceDir *= flMass * 750 * flScale; pPhysObject->ApplyForceCenter( vecForceDir ); } if ( pEntity->m_takedamage && ( m_flDamage != 0.0f ) ) { CTakeDamageInfo info( BaseEntity(), BaseEntity(), flDamage * flScale, DMG_BLAST ); CalculateExplosiveDamageForce( &info, vecSegment, pEntity->GetAbsOrigin() ); pEntity->TakeDamage( info ); } if ( pEntity->IsPlayer() && !(static_cast<CPlayer*>(pEntity)->IsInAVehicle()) ) { if (vecSegment.z < 0.1f) { vecSegment.z = 0.1f; VectorNormalize( vecSegment ); } float flAmount = SimpleSplineRemapVal( flScale, 0.0f, 1.0f, 250.0f, 1000.0f ); pEntity->ApplyAbsVelocityImpulse( vecSegment * flAmount ); } } }
const Vector &CE_CBeam::GetAbsStartPos( void ) { CEntity *ent = GetStartEntity(); if ( GetType() == BEAM_ENTS && ent ) { return ent->GetAbsOrigin(); } return GetAbsOrigin(); }
//----------------------------------------------------------------------------- // Purpose: // Input : *pTarget - // &chasePosition - //----------------------------------------------------------------------------- void CAI_BasePhysicsFlyingBot::TranslateNavGoal( CBaseEntity *pTarget, Vector &chasePosition ) { Assert( pTarget != NULL ); CEntity *cent = CEntity::Instance(pTarget); if ( cent == NULL ) { chasePosition = vec3_origin; return; } // Chase their eyes chasePosition = cent->GetAbsOrigin() + cent->GetViewOffset(); }
const Vector &CE_CBeam::GetAbsEndPos( void ) { CEntity *ent = GetEndEntity(); if ( GetType() != BEAM_POINTS && GetType() != BEAM_HOSE && ent ) { return ent->GetAbsOrigin(); } if (!const_cast<CE_CBeam*>(this)->GetMoveParent()) return m_vecEndPos; // FIXME: Cache this off? static Vector vecAbsPos; VectorTransform( m_vecEndPos, EntityToWorldTransform(), vecAbsPos ); return vecAbsPos; }
void CE_CEnvLaser::StrikeThink( void ) { CEntity *pEnd = RandomTargetname( STRING( *m_iszLaserTarget ) ); Vector vecFireAt = GetAbsEndPos(); if ( pEnd ) { vecFireAt = pEnd->GetAbsOrigin(); } trace_t tr; UTIL_TraceLine( GetAbsOrigin(), vecFireAt, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr ); FireAtPoint( tr ); SetNextThink( gpGlobals->curtime ); }
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 ) { m_TimeLastLookMisc = gpGlobals->curtime; BeginGather(); float distSq = ( iDistance * iDistance ); const Vector &origin = GetAbsOrigin(); int iter; CEntity *pEnt = CEntity::Instance(g_AI_SensedObjectsManager->GetFirst( &iter )); while ( pEnt ) { if ( pEnt->GetFlags() & BOX_QUERY_MASK ) { if ( origin.DistToSqr(pEnt->GetAbsOrigin()) < distSq && Look( pEnt->BaseEntity()) ) { nSeen++; } } pEnt = CEntity::Instance(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; }
//----------------------------------------------------------------------------- // Test for impact! //----------------------------------------------------------------------------- void CEnvHeadcrabCanister::TestForCollisionsAgainstEntities( const Vector &vecEndPosition ) { // Debugging!! // NDebugOverlay::Box( GetAbsOrigin(), m_vecMin * 0.5f, m_vecMax * 0.5f, 255, 255, 0, 0, 5 ); // NDebugOverlay::Box( vecEndPosition, m_vecMin, m_vecMax, 255, 0, 0, 0, 5 ); float flRadius = CollisionProp()->BoundingRadius(); Vector vecMins( -flRadius, -flRadius, -flRadius ); Vector vecMaxs( flRadius, flRadius, flRadius ); Ray_t ray; ray.Init( GetAbsOrigin(), vecEndPosition, vecMins, vecMaxs ); CCollideList collideList( &ray, BaseEntity(), MASK_SOLID ); enginetrace->EnumerateEntities( ray, false, &collideList ); float flDamage = m_flDamage; // Now get each entity and react accordinly! for( int iEntity = collideList.m_Entities.Count(); --iEntity >= 0; ) { CEntity *pEntity = collideList.m_Entities[iEntity]; Vector vecForceDir = m_Shared.m_vecDirection; // Check for a physics object and apply force! IPhysicsObject *pPhysObject = pEntity->VPhysicsGetObject(); if ( pPhysObject ) { float flMass = PhysGetEntityMass( pEntity ); vecForceDir *= flMass * 750; pPhysObject->ApplyForceCenter( vecForceDir ); } if ( pEntity->m_takedamage && ( m_flDamage != 0.0f ) ) { CTakeDamageInfo info( BaseEntity(), BaseEntity(), flDamage, DMG_BLAST ); CalculateExplosiveDamageForce( &info, vecForceDir, pEntity->GetAbsOrigin() ); pEntity->TakeDamage( info ); } } }
int CE_Cycler_Fix::OnTakeDamage_Alive(const CTakeDamageInfo& info) { #if 0 return BaseClass::OnTakeDamage_Alive(info); #endif Forget( bits_MEMORY_INCOVER ); if ( !CCombatCharacter::FAKE_OnTakeDamage_Alive( info ) ) return 0; if ( GetSleepState() == AISS_WAITING_FOR_THREAT ) Wake(); CEntity *attacker = CEntity::Instance(info.GetAttacker()); // NOTE: This must happen after the base class is called; we need to reduce // health before the pain sound, since some NPCs use the final health // level as a modifier to determine which pain sound to use. // REVISIT: Combine soldiers shoot each other a lot and then talk about it // this improves that case a bunch, but it seems kind of harsh. if ( !GetSquad() || !GetSquad()->SquadIsMember( attacker ) ) { PainSound( info );// "Ouch!" } // See if we're running a dynamic interaction that should break when I am damaged. if ( IsActiveDynamicInteraction() ) { ScriptedNPCInteraction_t *pInteraction = GetRunningDynamicInteraction(); if ( pInteraction->iLoopBreakTriggerMethod & SNPCINT_LOOPBREAK_ON_DAMAGE ) { CEAI_ScriptedSequence *_m_hCine = Get_m_hCine(); // Can only break when we're in the action anim if ( _m_hCine->IsPlayingAction() ) { _m_hCine->StopActionLoop( true ); } } } // If we're not allowed to die, refuse to die // Allow my interaction partner to kill me though if ( m_iHealth <= 0 && HasInteractionCantDie() && attacker != m_hInteractionPartner ) { m_iHealth = 1; } // ----------------------------------- // Fire outputs // ----------------------------------- if ( m_flLastDamageTime != gpGlobals->curtime ) { // only fire once per frame m_OnDamaged->FireOutput( attacker, this); if( attacker && attacker->IsPlayer() ) { m_OnDamagedByPlayer->FireOutput( attacker, this ); // This also counts as being harmed by player's squad. m_OnDamagedByPlayerSquad->FireOutput( attacker, this ); } else { // See if the person that injured me is an NPC. CAI_NPC *pAttacker = dynamic_cast<CAI_NPC *>( attacker ); if( pAttacker && pAttacker->IsAlive() ) { if( pAttacker->GetSquad() != NULL && pAttacker->IsInPlayerSquad() ) { m_OnDamagedByPlayerSquad->FireOutput( attacker, this ); } } } } if( (info.GetDamageType() & DMG_CRUSH) && !(info.GetDamageType() & DMG_PHYSGUN) && info.GetDamage() >= MIN_PHYSICS_FLINCH_DAMAGE ) { SetCondition( COND_PHYSICS_DAMAGE ); } if ( m_iHealth <= ( m_iMaxHealth / 2 ) ) { m_OnHalfHealth->FireOutput( attacker, this ); } // react to the damage (get mad) if ( ( (GetFlags() & FL_NPC) == 0 ) || !attacker ) return 1; // If the attacker was an NPC or client update my position memory if ( attacker->GetFlags() & (FL_NPC | FL_CLIENT) ) { // ------------------------------------------------------------------ // DO NOT CHANGE THIS CODE W/O CONSULTING // Only update information about my attacker I don't see my attacker // ------------------------------------------------------------------ if ( !FInViewCone_Entity( info.GetAttacker() ) || !FVisible_Entity( info.GetAttacker() ) ) { // ------------------------------------------------------------- // If I have an inflictor (enemy / grenade) update memory with // position of inflictor, otherwise update with an position // estimate for where the attack came from // ------------------------------------------------------ Vector vAttackPos; CEntity *inflictor = CEntity::Instance(info.GetInflictor()); if (inflictor) { vAttackPos = inflictor->GetAbsOrigin(); } else { vAttackPos = (GetAbsOrigin() + ( *g_vecAttackDir * 64 )); } // ---------------------------------------------------------------- // If I already have an enemy, assume that the attack // came from the enemy and update my enemy's position // unless I already know about the attacker or I can see my enemy // ---------------------------------------------------------------- if ( GetEnemy() != NULL && !GetEnemies()->HasMemory( info.GetAttacker() ) && !HasCondition(COND_SEE_ENEMY) ) { UpdateEnemyMemory(GetEnemy_CBase(), vAttackPos, GetEnemy_CBase()); } // ---------------------------------------------------------------- // If I already know about this enemy, update his position // ---------------------------------------------------------------- else if (GetEnemies()->HasMemory( info.GetAttacker() )) { UpdateEnemyMemory(info.GetAttacker(), vAttackPos); } // ----------------------------------------------------------------- // Otherwise just note the position, but don't add enemy to my list // ----------------------------------------------------------------- else { UpdateEnemyMemory(NULL, vAttackPos); } } // add pain to the conditions if ( IsLightDamage( info ) ) { SetCondition( COND_LIGHT_DAMAGE ); } if ( IsHeavyDamage( info ) ) { SetCondition( COND_HEAVY_DAMAGE ); } ForceGatherConditions(); // Keep track of how much consecutive damage I have recieved if ((gpGlobals->curtime - m_flLastDamageTime) < 1.0) { m_flSumDamage += info.GetDamage(); } else { m_flSumDamage = info.GetDamage(); } m_flLastDamageTime = gpGlobals->curtime; if ( attacker && attacker->IsPlayer() ) m_flLastPlayerDamageTime = gpGlobals->curtime; GetEnemies()->OnTookDamageFrom( info.GetAttacker() ); if (m_flSumDamage > m_iMaxHealth*0.3) { SetCondition(COND_REPEATED_DAMAGE); } NotifyFriendsOfDamage( info.GetAttacker() ); } // --------------------------------------------------------------- // Insert a combat sound so that nearby NPCs know I've been hit // --------------------------------------------------------------- g_helpfunc.CSoundEnt_InsertSound(SOUND_COMBAT, GetAbsOrigin(), 1024, 0.5, BaseEntity(), SOUNDENT_CHANNEL_INJURY ); return 1; }
//----------------------------------------------------------------------------- // Place the canister in the world //----------------------------------------------------------------------------- CE_CSkyCamera *CEnvHeadcrabCanister::PlaceCanisterInWorld() { CE_CSkyCamera *pCamera = NULL; // Are we launching from a point? If so, use that point. if ( m_iszLaunchPositionName != NULL_STRING ) { // Get the launch position entity CEntity *pLaunchPos = g_helpfunc.FindEntityByName( (CBaseEntity *)NULL, m_iszLaunchPositionName ); if ( !pLaunchPos ) { Warning("%s (%s) could not find an entity matching LaunchPositionName of '%s'\n", GetEntityName(), GetDebugName(), STRING(m_iszLaunchPositionName) ); SUB_Remove(); } else { SetupWorldModel(); Vector vecForward, vecImpactDirection; GetVectors( &vecForward, NULL, NULL ); VectorMultiply( vecForward, -1.0f, vecImpactDirection ); m_Shared.InitInWorld( gpGlobals->curtime, pLaunchPos->GetAbsOrigin(), GetAbsAngles(), vecImpactDirection, m_vecImpactPosition, true ); SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterWorldThink ); SetNextThink( gpGlobals->curtime ); } } else if ( DetectInSkybox() ) { pCamera = GetEntitySkybox(); SetModel( ENV_HEADCRABCANISTER_SKYBOX_MODEL ); SetSolid( SOLID_NONE ); Vector vecForward; GetVectors( &vecForward, NULL, NULL ); vecForward *= -1.0f; m_Shared.InitInSkybox( gpGlobals->curtime, m_vecImpactPosition, GetAbsAngles(), vecForward, m_vecImpactPosition, pCamera->m_skyboxData->origin, pCamera->m_skyboxData->scale ); AddEFlags( EFL_IN_SKYBOX ); SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterSkyboxOnlyThink ); SetNextThink( gpGlobals->curtime + m_Shared.GetEnterWorldTime() + TICK_INTERVAL ); } else { Vector vecStartPosition, vecDirection; QAngle vecStartAngles; ComputeWorldEntryPoint( &vecStartPosition, &vecStartAngles, &vecDirection ); // Figure out which skybox to place the entity in. pCamera = GetCurrentSkyCamera(); if ( pCamera ) { m_Shared.InitInSkybox( gpGlobals->curtime, vecStartPosition, vecStartAngles, vecDirection, m_vecImpactPosition, pCamera->m_skyboxData->origin, pCamera->m_skyboxData->scale ); if ( m_Shared.IsInSkybox() ) { SetModel( ENV_HEADCRABCANISTER_SKYBOX_MODEL ); SetSolid( SOLID_NONE ); AddEFlags( EFL_IN_SKYBOX ); SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterSkyboxThink ); SetNextThink( gpGlobals->curtime + m_Shared.GetEnterWorldTime() ); } else { SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterWorldThink ); SetNextThink( gpGlobals->curtime ); } } else { m_Shared.InitInWorld( gpGlobals->curtime, vecStartPosition, vecStartAngles, vecDirection, m_vecImpactPosition ); SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterWorldThink ); SetNextThink( gpGlobals->curtime ); } } Vector vecEndPosition; QAngle vecEndAngles; m_Shared.GetPositionAtTime( gpGlobals->curtime, vecEndPosition, vecEndAngles ); SetAbsOrigin( vecEndPosition ); SetAbsAngles( vecEndAngles ); return pCamera; }