Ejemplo n.º 1
0
//--------------------------------------------------------------------------------------------------------
bool CFuncNavBlocker::CalculateBlocked( bool *pResultByTeam, const Vector &vecMins, const Vector &vecMaxs )
{
	int nTeamsBlocked = 0;
	int i;
	bool bBlocked = false;
	for ( i=0; i<MAX_NAV_TEAMS; ++i )
	{
		pResultByTeam[i] = false;
	}

	FOR_EACH_LL( gm_NavBlockers, iBlocker )
	{
		CFuncNavBlocker *pBlocker = gm_NavBlockers[iBlocker];
		bool bIsIntersecting = false;

		for ( i=0; i<MAX_NAV_TEAMS; ++i )
		{
			if ( pBlocker->m_isBlockingNav[i] )
			{
				if ( !pResultByTeam[i] )
				{
					if ( bIsIntersecting || ( bIsIntersecting = IsBoxIntersectingBox( pBlocker->m_CachedMins, pBlocker->m_CachedMaxs, vecMins, vecMaxs ) ) != false )
					{
						bBlocked = true;
						pResultByTeam[i] = true;
						nTeamsBlocked++;
					}
					else
					{
						continue;
					}
				}
			}
		}

		if ( nTeamsBlocked == MAX_NAV_TEAMS )
		{
			break;
		}
 	}
Ejemplo n.º 2
0
//-----------------------------------------------------------------------------
// Purpose: Finds the first entity within an extent by class name.
// Input  : pStartEntity - The entity to start from when doing the search.
//			szName - Entity class name, ie "info_target".
//			vecMins - Search mins.
//			vecMaxs - Search maxs.
// Output : Returns a pointer to the found entity, NULL if none.
//-----------------------------------------------------------------------------
CBaseEntity *CGlobalEntityList::FindEntityByClassnameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecMins, const Vector &vecMaxs )
{
	//
	// Check for matching class names within the search radius.
	//
	CBaseEntity *pEntity = pStartEntity;

	while ((pEntity = gEntList.FindEntityByClassname( pEntity, szName )) != NULL)
	{
		if ( !pEntity->edict() && !pEntity->IsEFlagSet( EFL_SERVER_ONLY ) )
			continue;

		// check if the aabb intersects the search aabb.
		Vector entMins, entMaxs;
		pEntity->CollisionProp()->WorldSpaceAABB( &entMins, &entMaxs );
		if ( IsBoxIntersectingBox( vecMins, vecMaxs, entMins, entMaxs ) )
		{
			return pEntity;
		}
	}

	return NULL;
}
Ejemplo n.º 3
0
void C_HL2MP_Player::AvoidPlayers( CUserCmd *pCmd )
{
	// This is only used in team play.
	if ( !HL2MPRules()->IsTeamplay() )
		return;

	// Don't test if the player doesn't exist or is dead.
	if ( IsAlive() == false )
		return;

	C_Team *pTeam = ( C_Team * )GetTeam();
	if ( !pTeam )
		return;

	// Up vector.
	static Vector vecUp( 0.0f, 0.0f, 1.0f );

	Vector vecHL2MPPlayerCenter = GetAbsOrigin();
	Vector vecHL2MPPlayerMin = GetPlayerMins();
	Vector vecHL2MPPlayerMax = GetPlayerMaxs();
	float flZHeight = vecHL2MPPlayerMax.z - vecHL2MPPlayerMin.z;
	vecHL2MPPlayerCenter.z += 0.5f * flZHeight;
	VectorAdd( vecHL2MPPlayerMin, vecHL2MPPlayerCenter, vecHL2MPPlayerMin );
	VectorAdd( vecHL2MPPlayerMax, vecHL2MPPlayerCenter, vecHL2MPPlayerMax );

	// Find an intersecting player or object.
	int nAvoidPlayerCount = 0;
	C_HL2MP_Player *pAvoidPlayerList[MAX_PLAYERS];

	C_HL2MP_Player *pIntersectPlayer = NULL;
	float flAvoidRadius = 0.0f;

	Vector vecAvoidCenter, vecAvoidMin, vecAvoidMax;
	for ( int i = 0; i < pTeam->GetNumPlayers(); ++i )
	{
		C_HL2MP_Player *pAvoidPlayer = static_cast< C_HL2MP_Player * >( pTeam->GetPlayer( i ) );
		if ( pAvoidPlayer == NULL )
			continue;
		// Is the avoid player me?
		if ( pAvoidPlayer == this )
			continue;

		// Save as list to check against for objects.
		pAvoidPlayerList[nAvoidPlayerCount] = pAvoidPlayer;
		++nAvoidPlayerCount;

		// Check to see if the avoid player is dormant.
		if ( pAvoidPlayer->IsDormant() )
			continue;

		// Is the avoid player solid?
		if ( pAvoidPlayer->IsSolidFlagSet( FSOLID_NOT_SOLID ) )
			continue;

		Vector t1, t2;

		vecAvoidCenter = pAvoidPlayer->GetAbsOrigin();
		vecAvoidMin = pAvoidPlayer->GetPlayerMins();
		vecAvoidMax = pAvoidPlayer->GetPlayerMaxs();
		flZHeight = vecAvoidMax.z - vecAvoidMin.z;
		vecAvoidCenter.z += 0.5f * flZHeight;
		VectorAdd( vecAvoidMin, vecAvoidCenter, vecAvoidMin );
		VectorAdd( vecAvoidMax, vecAvoidCenter, vecAvoidMax );

		if ( IsBoxIntersectingBox( vecHL2MPPlayerMin, vecHL2MPPlayerMax, vecAvoidMin, vecAvoidMax ) )
		{
			// Need to avoid this player.
			if ( !pIntersectPlayer )
			{
				pIntersectPlayer = pAvoidPlayer;
				break;
			}
		}
	}

	// Anything to avoid?
	if ( !pIntersectPlayer )
		return;

	// Calculate the push strength and direction.
	Vector vecDelta;

	// Avoid a player - they have precedence.
	if ( pIntersectPlayer )
	{
		VectorSubtract( pIntersectPlayer->WorldSpaceCenter(), vecHL2MPPlayerCenter, vecDelta );

		Vector vRad = pIntersectPlayer->WorldAlignMaxs() - pIntersectPlayer->WorldAlignMins();
		vRad.z = 0;

		flAvoidRadius = vRad.Length();
	}

	float flPushStrength = RemapValClamped( vecDelta.Length(), flAvoidRadius, 0, 0, hl2mp_max_separation_force.GetInt() ); //flPushScale;

	//Msg( "PushScale = %f\n", flPushStrength );

	// Check to see if we have enough push strength to make a difference.
	if ( flPushStrength < 0.01f )
		return;

	Vector vecPush;
	if ( GetAbsVelocity().Length2DSqr() > 0.1f )
	{
		Vector vecVelocity = GetAbsVelocity();
		vecVelocity.z = 0.0f;
		CrossProduct( vecUp, vecVelocity, vecPush );
		VectorNormalize( vecPush );
	}
	else
	{
		// We are not moving, but we're still intersecting.
		QAngle angView = pCmd->viewangles;
		angView.x = 0.0f;
		AngleVectors( angView, NULL, &vecPush, NULL );
	}

	// Move away from the other player/object.
	Vector vecSeparationVelocity;
	if ( vecDelta.Dot( vecPush ) < 0 )
	{
		vecSeparationVelocity = vecPush * flPushStrength;
	}
	else
	{
		vecSeparationVelocity = vecPush * -flPushStrength;
	}

	// Don't allow the max push speed to be greater than the max player speed.
	float flMaxPlayerSpeed = MaxSpeed();
	float flCropFraction = 1.33333333f;

	if ( ( GetFlags() & FL_DUCKING ) && ( GetGroundEntity() != NULL ) )
	{	
		flMaxPlayerSpeed *= flCropFraction;
	}	

	float flMaxPlayerSpeedSqr = flMaxPlayerSpeed * flMaxPlayerSpeed;

	if ( vecSeparationVelocity.LengthSqr() > flMaxPlayerSpeedSqr )
	{
		vecSeparationVelocity.NormalizeInPlace();
		VectorScale( vecSeparationVelocity, flMaxPlayerSpeed, vecSeparationVelocity );
	}

	QAngle vAngles = pCmd->viewangles;
	vAngles.x = 0;
	Vector currentdir;
	Vector rightdir;

	AngleVectors( vAngles, &currentdir, &rightdir, NULL );

	Vector vDirection = vecSeparationVelocity;

	VectorNormalize( vDirection );

	float fwd = currentdir.Dot( vDirection );
	float rt = rightdir.Dot( vDirection );

	float forward = fwd * flPushStrength;
	float side = rt * flPushStrength;

	//Msg( "fwd: %f - rt: %f - forward: %f - side: %f\n", fwd, rt, forward, side );

	pCmd->forwardmove	+= forward;
	pCmd->sidemove		+= side;

	// Clamp the move to within legal limits, preserving direction. This is a little
	// complicated because we have different limits for forward, back, and side

	//Msg( "PRECLAMP: forwardmove=%f, sidemove=%f\n", pCmd->forwardmove, pCmd->sidemove );

	float flForwardScale = 1.0f;
	if ( pCmd->forwardmove > fabs( cl_forwardspeed.GetFloat() ) )
	{
		flForwardScale = fabs( cl_forwardspeed.GetFloat() ) / pCmd->forwardmove;
	}
	else if ( pCmd->forwardmove < -fabs( cl_backspeed.GetFloat() ) )
	{
		flForwardScale = fabs( cl_backspeed.GetFloat() ) / fabs( pCmd->forwardmove );
	}

	float flSideScale = 1.0f;
	if ( fabs( pCmd->sidemove ) > fabs( cl_sidespeed.GetFloat() ) )
	{
		flSideScale = fabs( cl_sidespeed.GetFloat() ) / fabs( pCmd->sidemove );
	}

	float flScale = min( flForwardScale, flSideScale );
	pCmd->forwardmove *= flScale;
	pCmd->sidemove *= flScale;

	//Msg( "Pforwardmove=%f, sidemove=%f\n", pCmd->forwardmove, pCmd->sidemove );
}
Ejemplo n.º 4
0
//-----------------------------------------------------------------------------
// Purpose: Update the fire and its children
//-----------------------------------------------------------------------------
void CFire::Update( float simTime )
{
	VPROF_FIRE( "CFire::Update" );

	if ( m_flFuel != 0 )
	{
		m_flFuel -= simTime;
		if ( m_flFuel <= 0 )
		{
			GoOutInSeconds( 1 );
			return;
		}
	}

	float strength = m_flHeatLevel / FIRE_MAX_HEAT_LEVEL;
	if ( m_flHeatLevel != m_flLastHeatLevel )
	{
		m_flLastHeatLevel = m_flHeatLevel;
		// Make the effect the appropriate size given the heat level
		m_hEffect->Scale( strength, 0.5f );		
	}
	// add heat to myself (grow)
	float addedHeat = (m_flAttackTime > 0) ? m_flMaxHeat / m_flAttackTime : m_flMaxHeat;
	addedHeat *= simTime * fire_growthrate.GetFloat();
	AddHeat( addedHeat, true );

	// add heat to nearby fires
	float outputHeat = strength * m_flHeatLevel;

	Vector fireMins;
	Vector fireMaxs;
	Vector fireEntityDamageMins;
	Vector fireEntityDamageMaxs;

	GetFireDimensions( &fireMins, &fireMaxs );

	if ( FIRE_SPREAD_DAMAGE_MULTIPLIER != 1.0 ) // if set to 1.0, optimizer will remove this code
	{
		fireEntityDamageMins = fireMins / FIRE_SPREAD_DAMAGE_MULTIPLIER;
		fireEntityDamageMaxs = fireMaxs / FIRE_SPREAD_DAMAGE_MULTIPLIER;
	}

	//NDebugOverlay::Box( GetAbsOrigin(), fireMins, fireMaxs, 255, 255, 255, 0, fire_dmginterval.GetFloat() );
	fireMins += GetAbsOrigin();
	fireMaxs += GetAbsOrigin();

	if ( FIRE_SPREAD_DAMAGE_MULTIPLIER != 1.0 )
	{
		fireEntityDamageMins += GetAbsOrigin();
		fireEntityDamageMaxs += GetAbsOrigin();
	}

	CBaseEntity *pNearby[256];
	CFire *pFires[16];
	int nearbyCount = UTIL_EntitiesInBox( pNearby, ARRAYSIZE(pNearby), fireMins, fireMaxs, 0 );
	int fireCount = 0;
	int i;

	// is it time to do damage?
	bool damage = false;
	int outputDamage = 0;
	if ( m_flDamageTime <= gpGlobals->curtime )
	{
		m_flDamageTime = gpGlobals->curtime + fire_dmginterval.GetFloat();
		outputDamage = (fire_dmgbase.GetFloat() + outputHeat * fire_dmgscale.GetFloat() * m_flDamageScale) * fire_dmginterval.GetFloat();
		if ( outputDamage )
		{
			damage = true;
		}
	}
	int damageFlags = (m_nFireType == FIRE_NATURAL) ? DMG_BURN : DMG_PLASMA;
	for ( i = 0; i < nearbyCount; i++ )
	{
		CBaseEntity *pOther = pNearby[i];

		if ( pOther == this )
		{
			continue;
		}
		else if ( FClassnameIs( pOther, "env_fire" ) )
		{
			if ( fireCount < ARRAYSIZE(pFires) )
			{
				pFires[fireCount] = (CFire *)pOther;
				fireCount++;
			}
			continue;
		}
		else if ( pOther->m_takedamage == DAMAGE_NO )
		{
			pNearby[i] = NULL;
		}
		else if ( damage )
		{
			bool bDoDamage;

			if ( FIRE_SPREAD_DAMAGE_MULTIPLIER != 1.0 && !pOther->IsPlayer() ) // if set to 1.0, optimizer will remove this code
			{
				Vector otherMins, otherMaxs;
				pOther->CollisionProp()->WorldSpaceAABB( &otherMins, &otherMaxs );
				bDoDamage = IsBoxIntersectingBox( otherMins, otherMaxs, 
												  fireEntityDamageMins, fireEntityDamageMaxs );

			}
			else
				bDoDamage = true;

			if ( bDoDamage )
			{
				// Make sure can actually see entity (don't damage through walls)
				trace_t tr;
				UTIL_TraceLine( this->WorldSpaceCenter(), pOther->WorldSpaceCenter(), MASK_FIRE_SOLID, pOther, COLLISION_GROUP_NONE, &tr );

				if (tr.fraction == 1.0 && !tr.startsolid)
				{
					pOther->TakeDamage( CTakeDamageInfo( this, this, outputDamage, damageFlags ) );
				}
			}
		}
	}

	outputHeat *= fire_heatscale.GetFloat() * simTime;

	if ( fireCount > 0 )
	{
		outputHeat /= fireCount;
		for ( i = 0; i < fireCount; i++ )
		{
			pFires[i]->AddHeat( outputHeat, false );
		}
	}
}
Ejemplo n.º 5
0
void CNPC_Dog::SetPlayerAvoidState( void )
{
	bool bIntersectingBoneFollowers = false;
	bool bIntersectingNPCBox = false;

	Vector vNothing;

	GetSequenceLinearMotion( GetSequence(), &vNothing );
	bool bIsMoving = ( IsMoving() || ( vNothing != vec3_origin ) );

	//If we are coming out of a script, check if we are stuck inside the player.
	if ( m_bPerformAvoidance || ( ShouldPlayerAvoid() && bIsMoving ) )
	{
		trace_t trace;
		Vector vMins, vMaxs;
		Vector vWorldMins, vWorldMaxs;
		Vector vPlayerMins, vPlayerMaxs;
		physfollower_t *pBone;
		int i;
		
		#ifdef SecobMod__Enable_Fixed_Multiplayer_AI
			CBasePlayer *pLocalPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); 
		#else
			CBasePlayer *pLocalPlayer = AI_GetSinglePlayer();
		#endif //SecobMod__Enable_Fixed_Multiplayer_AI

		if ( pLocalPlayer )
		{
			vWorldMins = WorldAlignMins();
			vWorldMaxs = WorldAlignMaxs();

			vPlayerMins = pLocalPlayer->GetAbsOrigin() + pLocalPlayer->WorldAlignMins();
			vPlayerMaxs = pLocalPlayer->GetAbsOrigin() + pLocalPlayer->WorldAlignMaxs();

			// check if the player intersects the bounds of any of the bone followers
			for ( i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ )
			{
				pBone = m_BoneFollowerManager.GetBoneFollower( i );
				if ( pBone && pBone->hFollower )
				{
					pBone->hFollower->CollisionProp()->WorldSpaceSurroundingBounds( &vMins, &vMaxs );
					if ( IsBoxIntersectingBox( vMins, vMaxs, vPlayerMins, vPlayerMaxs ) )
					{
						bIntersectingBoneFollowers = true;
						break;
					}
				}
			}

			bIntersectingNPCBox = IsBoxIntersectingBox( GetAbsOrigin() + vWorldMins, GetAbsOrigin() + vWorldMaxs, vPlayerMins, vPlayerMaxs );

			if ( ai_debug_avoidancebounds.GetBool() )
			{
				int iRed = ( bIntersectingNPCBox == true ) ? 255 : 0;

				NDebugOverlay::Box( GetAbsOrigin(), vWorldMins, vWorldMaxs, iRed, 0, 255, 64, 0.1 );

				// draw the bounds of the bone followers
				for ( i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ )
				{
					pBone = m_BoneFollowerManager.GetBoneFollower( i );
					if ( pBone && pBone->hFollower )
					{
						pBone->hFollower->CollisionProp()->WorldSpaceSurroundingBounds( &vMins, &vMaxs );
						iRed = ( IsBoxIntersectingBox( vMins, vMaxs, vPlayerMins, vPlayerMaxs ) ) ? 255 : 0;

						NDebugOverlay::Box( vec3_origin, vMins, vMaxs, iRed, 0, 255, 64, 0.1 );
					}
				}
			}
		}
	}

	m_bPlayerAvoidState = ShouldPlayerAvoid();
	m_bPerformAvoidance = bIntersectingNPCBox || bIntersectingBoneFollowers;

	if ( GetCollisionGroup() == COLLISION_GROUP_NPC || GetCollisionGroup() == COLLISION_GROUP_NPC_ACTOR )
	{
		if ( bIntersectingNPCBox == true )
		{
			SetCollisionGroup( COLLISION_GROUP_NPC_ACTOR );
		}
		else
		{
			SetCollisionGroup( COLLISION_GROUP_NPC );
		}

		if ( bIntersectingBoneFollowers == true )
		{
			MantainBoneFollowerCollisionGroups( COLLISION_GROUP_NPC_ACTOR );
		}
		else
		{
			MantainBoneFollowerCollisionGroups( COLLISION_GROUP_NPC );
		}
	}
}
//--------------------------------------------------------------------------------------------------------
bool AvoidActors::operator()( CBaseCombatCharacter *obj )
{
	if ( !obj || ( obj == m_owner ) || ( obj->GetTeamNumber() != m_owner->GetTeamNumber() ) )
		return true;

#ifdef CLIENT_DLL
	if ( obj->IsDormant() )
		return true;
#endif

	if ( obj->IsSolidFlagSet( FSOLID_NOT_SOLID ) )
		return true;

	CTerrorPlayer *player = ToTerrorPlayer( obj );
	if ( !player )
		return true;

	if ( player->IsIncapacitatedRevivable() )
		return true;

	if ( player->IsGhost() )
		return true;

	Vector objOrigin = obj->GetAbsOrigin();
	Vector vObjMins = objOrigin + obj->WorldAlignMins();
	Vector vObjMaxs = objOrigin + obj->WorldAlignMaxs();
	Vector vOwnerMins = *m_dest + m_owner->WorldAlignMins();
	Vector vOwnerMaxs = *m_dest + m_owner->WorldAlignMaxs();
	if ( !IsBoxIntersectingBox( vOwnerMins, vOwnerMaxs, vObjMins, vObjMaxs ) )
		return true;

	float objWidth = vObjMaxs.x - vObjMins.x;
	float ownerWidth = vOwnerMaxs.x - vOwnerMins.x;
	float idealDistance = (objWidth + ownerWidth) * 0.5f * m_scale;

	Vector vDelta = objOrigin - *m_dest;
	vDelta.z = 0;
	float fDist = vDelta.NormalizeInPlace();
	if ( fDist > idealDistance )
		return true;

	Vector rayOrigin = m_origin;
	Vector rayDelta = *m_dest - m_origin;
	Vector sphereCenter = objOrigin;
	float sphereRadius = idealDistance;
	rayOrigin.z = rayDelta.z = sphereCenter.z = 0.0f;
	float t1, t2;
	if ( IntersectRayWithSphere( rayOrigin, rayDelta, sphereCenter, sphereRadius, &t1, &t2 ) )
	{
		Vector sphereToDest = *m_dest - sphereCenter;
		sphereToDest.z = 0.0f;
		if ( !sphereToDest.IsZero() )
		{
			float radius = sphereToDest.NormalizeInPlace();
			sphereToDest *= (idealDistance - radius);
			*m_dest += sphereToDest;
			m_avoidedActors.AddToTail( obj );
		}
	}

	return true;
}