Beispiel #1
0
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;
}
Beispiel #6
0
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;
}