sqwarmed/sdk_src/game/server/swarm/asw_jump_trigger.cpp

159 lines
4.9 KiB
C++

#include "cbase.h"
#include "asw_shareddefs.h"
#include "asw_jump_trigger.h"
#include "asw_drone_advanced.h"
#include "asw_util_shared.h"
#include "asw_marine.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
LINK_ENTITY_TO_CLASS( trigger_asw_jump, CASW_Jump_Trigger );
BEGIN_DATADESC( CASW_Jump_Trigger )
DEFINE_FUNCTION( VolumeTouch ),
DEFINE_KEYFIELD( m_JumpDestName, FIELD_STRING, "JumpDestName" ),
DEFINE_KEYFIELD( m_fMinMarineDistance, FIELD_STRING, "MinMarineDist" ),
DEFINE_KEYFIELD( m_bClearOrders, FIELD_BOOLEAN, "ClearOrders" ),
DEFINE_KEYFIELD( m_bCheckEnemyDirection, FIELD_BOOLEAN, "CheckEnemyDirection" ),
DEFINE_KEYFIELD( m_bOneJumpPerAlien, FIELD_BOOLEAN, "CheckTriggerJumped" ),
DEFINE_KEYFIELD( m_bRetryFailedJumps, FIELD_BOOLEAN, "RetryFailedJumps" ),
DEFINE_KEYFIELD( m_bForceJump, FIELD_BOOLEAN, "ForceJump" ),
DEFINE_KEYFIELD( m_ForceAngle, FIELD_VECTOR, "ForceAngle" ),
DEFINE_KEYFIELD( m_fForceSpeed, FIELD_FLOAT, "ForceSpeed" ),
DEFINE_ARRAY( m_vecJumpDestination, FIELD_FLOAT, ASW_MAX_JUMP_DESTS ), // NOTE: MUST BE IN LOCAL SPACE, NOT POSITION_VECTOR!!! (see CBaseEntity::Restore)
END_DATADESC()
CASW_Jump_Trigger::CASW_Jump_Trigger()
{
}
//-----------------------------------------------------------------------------
// Purpose: Touch function. Activates the trigger.
// Input : pOther - The thing that touched us.
//-----------------------------------------------------------------------------
void CASW_Jump_Trigger::VolumeTouch(CBaseEntity *pOther)
{
CASW_Alien_Jumper *pJumper = dynamic_cast<CASW_Alien_Jumper*>(pOther);
if (pJumper && ( pJumper->CapabilitiesGet() & bits_CAP_MOVE_JUMP )
&& !pJumper->IsJumping() && ( pJumper->GetFlags() & FL_ONGROUND ) )
{
bool bJumped = false;
if ( m_bForceJump && m_fForceSpeed != 0 )
{
Vector vecVelocity;
AngleVectors( m_ForceAngle, &vecVelocity );
vecVelocity *= m_fForceSpeed;
bJumped = pJumper->DoForcedJump( vecVelocity );
}
else
{
// pick a jump dest
int iChosen = random->RandomInt(0, m_iNumJumpDests-1);
if (!ReasonableJump(pJumper, iChosen))
{
// the dest was blocked, so we're going to just go and try all our dests
iChosen = -1;
for (int i=0;i<m_iNumJumpDests;i++)
{
if (ReasonableJump(pJumper, i))
{
iChosen = i;
break;
}
}
if (iChosen == -1) // all dests blocked
return;
}
// don't jump if a marine is too near us
float marine_distance = 0;
CASW_Marine *pMarine = UTIL_ASW_NearestMarine(pJumper->GetAbsOrigin(), marine_distance);
if (pMarine && marine_distance < m_fMinMarineDistance)
{
return;
}
bJumped = pJumper->DoJumpTo(m_vecJumpDestination[iChosen]);
if ( !bJumped )
{
bool bHasOrders = ( pJumper->m_AlienOrders != AOT_None );
if ( m_bRetryFailedJumps && !bHasOrders ) // don't stop and wait for retry if we're still moving somewhere
pJumper->WaitAndRetryJump( m_vecJumpDestination[iChosen] );
}
}
// start to jump
pJumper->m_bTriggerJumped = true;
// clear the jumpers previous orders
if ( bJumped && m_bClearOrders )
{
pJumper->SetAlienOrders(AOT_None, vec3_origin, NULL);
}
}
}
bool CASW_Jump_Trigger::ReasonableJump(CASW_Alien_Jumper *pJumper, int iJumpNum)
{
if (!pJumper)
return false;
if (m_bOneJumpPerAlien && pJumper->m_bTriggerJumped)
return false;
if (!pJumper->GetEnemy()) // let him jump if he has no enemy
return true;
if (!m_bCheckEnemyDirection) // let him jump if he doesn't care about the direction of his enemy
return true;
// if he does have an enemy, check it's in the direction of the jump
float fEnemyYaw = UTIL_VecToYaw(pJumper->GetEnemy()->GetAbsOrigin() - pJumper->GetAbsOrigin());
float fJumpYaw = UTIL_VecToYaw(m_vecJumpDestination[iJumpNum] - pJumper->GetAbsOrigin());
return fabs(UTIL_AngleDiff(fEnemyYaw, fJumpYaw)) < 90;
}
//-----------------------------------------------------------------------------
// Purpose: Called when spawning, after keyvalues have been handled.
//-----------------------------------------------------------------------------
void CASW_Jump_Trigger::Spawn( void )
{
BaseClass::Spawn();
InitTrigger();
if ( m_flWait == 0 )
{
m_flWait = 0.2;
}
ASSERTSZ( m_iHealth == 0, "trigger_asw_jump with health" );
// find the target this use area is attached to
m_iNumJumpDests = 0;
CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, m_JumpDestName, NULL );
while ( pEnt )
{
m_vecJumpDestination[m_iNumJumpDests] = pEnt->GetAbsOrigin();
m_iNumJumpDests++;
pEnt = gEntList.FindEntityByName(pEnt, m_JumpDestName, NULL);
}
if ( m_iNumJumpDests > 0 || m_bForceJump )
{
SetTouch( &CASW_Jump_Trigger::VolumeTouch );
}
else
{
Msg("Error: trigger_asw_jump has no valid destinations.\n");
}
//Assert(!m_hUseTarget);
}