void CASW_Arena::UpdateArena() { // has arena mode just been turned on? if ( !m_bStartedArenaMode ) { for ( int i=0; i< m_ArenaAliens.Count(); i++ ) { UTIL_PrecacheOther( m_ArenaAliens[i]->m_szAlienClass ); } m_bStartedArenaMode = true; m_ArenaRestTimer.Start( 3.0f ); } if ( m_ArenaShuffleWallsTimer.HasStarted() && m_ArenaShuffleWallsTimer.IsElapsed() ) { TeleportPlayersToSpawn(); ShuffleArenaWalls(); m_ArenaShuffleWallsTimer.Invalidate(); m_ArenaRestTimer.Start( 2.5f ); } if ( m_ArenaRestTimer.HasStarted() && m_ArenaRestTimer.IsElapsed() ) { SpawnArenaWave(); m_ArenaRestTimer.Invalidate(); } if ( m_ArenaCheckTimer.HasStarted() && m_ArenaCheckTimer.IsElapsed() ) { // count live aliens CBaseEntity* pEntity = NULL; int iAliens = 0; while ((pEntity = gEntList.NextEnt( pEntity )) != NULL) { if ( pEntity && pEntity->IsNPC() && pEntity->Classify() != CLASS_ASW_MARINE && pEntity->GetHealth() > 0 ) iAliens++; } if ( iAliens <= 0 && !m_ArenaRestTimer.HasStarted() && !m_ArenaShuffleWallsTimer.HasStarted() ) { RefillMarineAmmo(); if ( asw_arena_shuffle_walls.GetInt() > 0 && ( m_iArenaWave % asw_arena_shuffle_walls.GetInt() ) == 0 && ( m_iArenaWave != 0 ) ) { UTIL_CenterPrintAll( UTIL_VarArgs("Wave %d clear!\nThe arena is changing...", m_iArenaWave ) ); m_ArenaShuffleWallsTimer.Start( 5.0f ); } else { UTIL_CenterPrintAll( UTIL_VarArgs("Wave %d clear!", m_iArenaWave ) ); m_ArenaRestTimer.Start( RandomFloat( 8, 12 ) ); } m_ArenaCheckTimer.Invalidate(); } } }
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) { CBaseEntity *pEntity = (CBaseEntity *)pServerEntity; if ( pEntity->GetCollisionGroup() == COLLISION_GROUP_WEAPON ) return false; // Don't collide with the tracing entity's vehicle (if it exists) if ( pServerEntity == m_pVehicle ) return false; if ( pEntity->GetHealth() > 0 ) { CBreakable *pBreakable = dynamic_cast<CBreakable *>(pEntity); if ( pBreakable && pBreakable->IsBreakable() && pBreakable->GetMaterialType() == matGlass) { return false; } } return BaseClass::ShouldHitEntity( pServerEntity, contentsMask ); }
//------------------------------------------------------------------------------ // Purpose: general purpose routine to collect conditions used both during active // and non-active states of the behavior. //------------------------------------------------------------------------------ void CAI_ASW_HealOtherBehavior::GatherCommonConditions( ) { BaseClass::GatherCommonConditions(); // ClearCondition( COND_HEAL_OTHER_HAS_TARGET ); SetCondition( COND_HEAL_OTHER_NOT_HAS_TARGET ); ClearCondition( COND_HEAL_OTHER_TARGET_CHANGED ); ClearCondition( COND_HEAL_OTHER_TARGET_IN_RANGE ); ClearCondition( COND_HEAL_OTHER_NOT_TARGET_IN_RANGE ); CBaseEntity *pBestObject = NULL; int nPotentialHealthBenefit = 0; for( int i = 0; i < GetOuter()->GetNumFactions(); i++ ) { if ( GetOuter()->GetFactionRelationshipDisposition( i ) == D_LIKE ) { CUtlVector< EHANDLE > *pEntityList = GetOuter()->GetEntitiesInFaction( i ); for( int j = 0; j < pEntityList->Count(); j++ ) { CBaseEntity *pEntity = pEntityList->Element( j ); if ( pEntity->GetHealth() <= 0 ) continue; Class_T entClass = pEntity->Classify(); if ( entClass == CLASS_ASW_SHAMAN || entClass == CLASS_ASW_BOOMER || entClass == CLASS_ASW_BOOMERMINI || entClass == CLASS_ASW_PARASITE || entClass == CLASS_ASW_BLOB || entClass == CLASS_ASW_BUZZER || entClass == CLASS_ASW_RUNNER ) { continue; } if ( GetOuter() != pEntity ) { Vector vDiff = pEntity->GetAbsOrigin() - GetAbsOrigin(); float flLengthSquared = vDiff.LengthSqr(); if ( flLengthSquared <= m_flHealConsiderationDistanceSquared ) //&& ( !asw_shaman_only_heal_hurt_pEntity->m_iHealth < pEntity->m_iMaxHealth ) { if ( nPotentialHealthBenefit == 0 || ( pEntity->m_iMaxHealth - pEntity->m_iHealth ) > nPotentialHealthBenefit ) { nPotentialHealthBenefit = ( pEntity->m_iMaxHealth - pEntity->m_iHealth ); pBestObject = pEntity; } } } } } } if ( pBestObject ) { if ( m_hHealTargetEnt != NULL && m_hHealTargetEnt != pBestObject ) { SetCondition( COND_HEAL_OTHER_TARGET_CHANGED ); } // SetCondition( COND_HEAL_OTHER_HAS_TARGET ); ClearCondition( COND_HEAL_OTHER_NOT_HAS_TARGET ); m_hHealTargetEnt = pBestObject; if ( m_hHealTargetEnt.Get() ) { Vector vPredictedPos = m_hHealTargetEnt->GetAbsOrigin() + m_hHealTargetEnt->GetAbsVelocity() * asw_shaman_aim_ahead_time.GetFloat(); Vector vDiff = vPredictedPos - GetAbsOrigin(); if ( vDiff.Length() < m_flHealDistance ) { SetCondition( COND_HEAL_OTHER_TARGET_IN_RANGE ); } else { SetCondition( COND_HEAL_OTHER_NOT_TARGET_IN_RANGE ); } } } else { if ( m_hHealTargetEnt != NULL && m_hHealTargetEnt != pBestObject ) { SetCondition( COND_HEAL_OTHER_TARGET_CHANGED ); } m_hHealTargetEnt = NULL; } }
//----------------------------------------------------------------------------- // 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 ); }
//----------------------------------------------------------------------------- // Purpose: Returns a pointer to a healable target //----------------------------------------------------------------------------- bool CWeaponMedigun::FindAndHealTargets( void ) { CTFPlayer *pOwner = ToTFPlayer( GetOwnerEntity() ); if ( !pOwner ) return false; bool bFound = false; // Maintaining beam to existing target? CBaseEntity *pTarget = m_hHealingTarget; if ( pTarget && pTarget->IsAlive() ) { MaintainTargetInSlot(); } else { FindNewTargetForSlot(); } CBaseEntity *pNewTarget = m_hHealingTarget; if ( pNewTarget && pNewTarget->IsAlive() ) { CTFPlayer *pTFPlayer = ToTFPlayer( pNewTarget ); #ifdef GAME_DLL // HACK: For now, just deal with players if ( pTFPlayer ) { if ( pTarget != pNewTarget && pNewTarget->IsPlayer() ) { pTFPlayer->m_Shared.Heal( pOwner, GetHealRate() ); } pTFPlayer->m_Shared.RecalculateChargeEffects( false ); } if ( m_flReleaseStartedAt && m_flReleaseStartedAt < (gpGlobals->curtime + 0.2) ) { // When we start the release, everyone we heal rockets to full health pNewTarget->TakeHealth( pNewTarget->GetMaxHealth(), DMG_GENERIC ); } #endif bFound = true; // Charge up our power if we're not releasing it, and our target // isn't receiving any benefit from our healing. if ( !m_bChargeRelease ) { if ( pTFPlayer ) { int iBoostMax = floor( pTFPlayer->m_Shared.GetMaxBuffedHealth() * 0.95); if ( weapon_medigun_charge_rate.GetFloat() ) { float flChargeAmount = gpGlobals->frametime / weapon_medigun_charge_rate.GetFloat(); // Reduced charge for healing fully healed guys if ( pNewTarget->GetHealth() >= iBoostMax && ( TFGameRules() && !TFGameRules()->InSetup() ) ) { flChargeAmount *= 0.5; } int iTotalHealers = pTFPlayer->m_Shared.GetNumHealers(); if ( iTotalHealers > 1 ) { flChargeAmount /= (float)iTotalHealers; } float flNewLevel = min( m_flChargeLevel + flChargeAmount, 1.0 ); #ifdef GAME_DLL if ( flNewLevel >= 1.0 && m_flChargeLevel < 1.0 ) { pOwner->SpeakConceptIfAllowed( MP_CONCEPT_MEDIC_CHARGEREADY ); if ( pTFPlayer ) { pTFPlayer->SpeakConceptIfAllowed( MP_CONCEPT_HEALTARGET_CHARGEREADY ); } } #endif m_flChargeLevel = flNewLevel; } } } } return bFound; }
CBaseEntity * CASW_Rocket::FindPotentialTarget( void ) const { float bestdist = 0; CBaseEntity *bestent = NULL; Vector v_forward, v_right, v_up; AngleVectors( GetAbsAngles(), &v_forward, &v_right, &v_up ); // find the aimtarget nearest us int count = AimTarget_ListCount(); if ( count ) { CBaseEntity **pList = (CBaseEntity **)stackalloc( sizeof(CBaseEntity *) * count ); AimTarget_ListCopy( pList, count ); CTraceFilterSkipTwoEntities filter(this, GetOwnerEntity(), COLLISION_GROUP_NONE); for ( int i = 0; i < count; i++ ) { CBaseEntity *pEntity = pList[i]; if (!pEntity || !pEntity->IsAlive() || !pEntity->edict() || !pEntity->IsNPC() ) { //Msg("not alive or not an edict, skipping\n"); continue; } if (!pEntity || !pEntity->IsAlive() || !pEntity->edict() || !pEntity->IsNPC() ) { //Msg("not alive or not an edict, skipping\n"); continue; } // don't autoaim onto marines if (pEntity->Classify() == CLASS_ASW_MARINE || pEntity->Classify() == CLASS_ASW_COLONIST) continue; if ( pEntity->Classify() == CLASS_ASW_PARASITE ) { CASW_Parasite *pParasite = static_cast< CASW_Parasite* >( pEntity ); if ( pParasite->m_bInfesting ) { continue; } } Vector center = pEntity->BodyTarget( GetAbsOrigin() ); Vector center_flat = center; center_flat.z = GetAbsOrigin().z; Vector dir = (center - GetAbsOrigin()); VectorNormalize( dir ); Vector dir_flat = (center_flat - GetAbsOrigin()); VectorNormalize( dir_flat ); // make sure it's in front of the rocket float dot = DotProduct (dir, v_forward ); //if (dot < 0) //{ //continue; //} float dist = (pEntity->GetAbsOrigin() - GetAbsOrigin()).LengthSqr(); if (dist > ASW_ROCKET_MAX_HOMING_RANGE) continue; // check another marine isn't between us and the target to reduce FF trace_t tr; UTIL_TraceLine(GetAbsOrigin(), pEntity->WorldSpaceCenter(), MASK_SHOT, &filter, &tr); if (tr.fraction < 1.0f && tr.m_pEnt != pEntity && tr.m_pEnt && tr.m_pEnt->Classify() == CLASS_ASW_MARINE) continue; // does this critter already have enough rockets to kill it? { CASW_DamageAllocationMgr::IndexType_t assignmentIndex = m_RocketAssigner.Find( pEntity ); if ( m_RocketAssigner.IsValid(assignmentIndex) ) { if ( m_RocketAssigner[assignmentIndex].m_flAccumulatedDamage > pEntity->GetHealth() ) { continue; } } } // check another marine isn't between us and the target to reduce FF UTIL_TraceLine(GetAbsOrigin(), pEntity->WorldSpaceCenter(), MASK_SHOT, &filter, &tr); if (tr.fraction < 1.0f && tr.m_pEnt != pEntity && tr.m_pEnt && tr.m_pEnt->Classify() == CLASS_ASW_MARINE) continue; // increase distance if dot isn't towards us dist += (1.0f - dot) * 150; // bias of x units when object is 90 degrees to the side if (bestdist == 0 || dist < bestdist) { bestdist = dist; bestent = pEntity; } } if ( bestent && asw_rocket_debug.GetBool() ) { Vector center = bestent->BodyTarget( GetAbsOrigin() ); Vector center_flat = center; center_flat.z = GetAbsOrigin().z; Vector dir = (center - GetAbsOrigin()); VectorNormalize( dir ); Msg( "Rocket[%d] starting homing in on %s(%d) dir = %f %f %f\n", entindex(), bestent->GetClassname(), bestent->entindex(), VectorExpand( dir ) ); } } return bestent; }