753 lines
22 KiB
C++
753 lines
22 KiB
C++
#include "cbase.h"
|
|
#include "asw_triggers.h"
|
|
#include "asw_marine.h"
|
|
#include "asw_game_resource.h"
|
|
#include "asw_marine_resource.h"
|
|
#include "asw_marine_speech.h"
|
|
#include "asw_gamerules.h"
|
|
#include "asw_weapon.h"
|
|
#include "asw_util_shared.h"
|
|
#include "asw_melee_system.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
ConVar asw_synup_chatter_chance("asw_synup_chatter_chance", "0.2", FCVAR_CHEAT, "Chance of the synup chatter happening");
|
|
|
|
// Chance trigger - has a random chance of actually firing
|
|
|
|
LINK_ENTITY_TO_CLASS( trigger_asw_chance, CASW_Chance_Trigger_Multiple );
|
|
|
|
BEGIN_DATADESC( CASW_Chance_Trigger_Multiple )
|
|
DEFINE_KEYFIELD( m_fTriggerChance, FIELD_FLOAT, "TriggerChance" ),
|
|
|
|
// Function Pointers
|
|
DEFINE_FUNCTION(ChanceMultiTouch),
|
|
DEFINE_FUNCTION(MultiWaitOver ),
|
|
|
|
// Outputs
|
|
DEFINE_OUTPUT(m_OnTrigger, "OnTrigger")
|
|
END_DATADESC()
|
|
|
|
void CASW_Chance_Trigger_Multiple::Spawn( void )
|
|
{
|
|
BaseClass::Spawn();
|
|
|
|
InitTrigger();
|
|
|
|
if (m_flWait == 0)
|
|
{
|
|
m_flWait = 0.2;
|
|
}
|
|
|
|
ASSERTSZ(m_iHealth == 0, "trigger_multiple with health");
|
|
SetTouch( &CASW_Chance_Trigger_Multiple::ChanceMultiTouch );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Touch function. Activates the trigger.
|
|
// Input : pOther - The thing that touched us.
|
|
//-----------------------------------------------------------------------------
|
|
void CASW_Chance_Trigger_Multiple::ChanceMultiTouch(CBaseEntity *pOther)
|
|
{
|
|
if (PassesTriggerFilters(pOther))
|
|
{
|
|
ActivateChanceMultiTrigger( pOther );
|
|
}
|
|
}
|
|
|
|
void CASW_Chance_Trigger_Multiple::ActivateChanceMultiTrigger(CBaseEntity *pActivator)
|
|
{
|
|
if (GetNextThink() > gpGlobals->curtime)
|
|
return; // still waiting for reset time
|
|
|
|
m_hActivator = pActivator;
|
|
|
|
if (RandomFloat() < m_fTriggerChance)
|
|
m_OnTrigger.FireOutput(m_hActivator, this);
|
|
|
|
if (m_flWait > 0)
|
|
{
|
|
SetThink( &CASW_Chance_Trigger_Multiple::MultiWaitOver );
|
|
SetNextThink( gpGlobals->curtime + m_flWait );
|
|
}
|
|
else
|
|
{
|
|
// we can't just remove (self) here, because this is a touch function
|
|
// called while C code is looping through area links...
|
|
SetTouch( NULL );
|
|
SetNextThink( gpGlobals->curtime + 0.1f );
|
|
SetThink( &CASW_Chance_Trigger_Multiple::SUB_Remove );
|
|
}
|
|
}
|
|
|
|
void CASW_Chance_Trigger_Multiple::MultiWaitOver( void )
|
|
{
|
|
SetThink( NULL );
|
|
}
|
|
|
|
|
|
|
|
LINK_ENTITY_TO_CLASS( trigger_asw_random_target, CASW_Random_Target_Trigger_Multiple );
|
|
|
|
BEGIN_DATADESC( CASW_Random_Target_Trigger_Multiple )
|
|
DEFINE_KEYFIELD( m_iNumOutputs, FIELD_INTEGER, "NumOutputs" ),
|
|
// Function Pointers
|
|
DEFINE_FUNCTION(RandomMultiTouch),
|
|
DEFINE_FUNCTION(MultiWaitOver),
|
|
|
|
// Outputs
|
|
DEFINE_OUTPUT(m_OnTrigger1, "OnTrigger1"),
|
|
DEFINE_OUTPUT(m_OnTrigger2, "OnTrigger2"),
|
|
DEFINE_OUTPUT(m_OnTrigger3, "OnTrigger3"),
|
|
DEFINE_OUTPUT(m_OnTrigger4, "OnTrigger4"),
|
|
DEFINE_OUTPUT(m_OnTrigger5, "OnTrigger5"),
|
|
DEFINE_OUTPUT(m_OnTrigger6, "OnTrigger6"),
|
|
END_DATADESC()
|
|
|
|
void CASW_Random_Target_Trigger_Multiple::Spawn( void )
|
|
{
|
|
BaseClass::Spawn();
|
|
|
|
InitTrigger();
|
|
|
|
if (m_flWait == 0)
|
|
{
|
|
m_flWait = 0.2;
|
|
}
|
|
|
|
ASSERTSZ(m_iHealth == 0, "trigger_multiple with health");
|
|
SetTouch( &CASW_Random_Target_Trigger_Multiple::RandomMultiTouch );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Touch function. Activates the trigger.
|
|
// Input : pOther - The thing that touched us.
|
|
//-----------------------------------------------------------------------------
|
|
void CASW_Random_Target_Trigger_Multiple::RandomMultiTouch(CBaseEntity *pOther)
|
|
{
|
|
if (PassesTriggerFilters(pOther))
|
|
{
|
|
ActivateRandomMultiTrigger( pOther );
|
|
}
|
|
}
|
|
|
|
void CASW_Random_Target_Trigger_Multiple::ActivateRandomMultiTrigger(CBaseEntity *pActivator)
|
|
{
|
|
if (GetNextThink() > gpGlobals->curtime)
|
|
return; // still waiting for reset time
|
|
|
|
m_hActivator = pActivator;
|
|
|
|
int i = RandomInt(1, m_iNumOutputs);
|
|
switch (i)
|
|
{
|
|
case 2: m_OnTrigger2.FireOutput(m_hActivator, this); break;
|
|
case 3: m_OnTrigger3.FireOutput(m_hActivator, this); break;
|
|
case 4: m_OnTrigger4.FireOutput(m_hActivator, this); break;
|
|
case 5: m_OnTrigger5.FireOutput(m_hActivator, this); break;
|
|
case 6: m_OnTrigger6.FireOutput(m_hActivator, this); break;
|
|
default: m_OnTrigger1.FireOutput(m_hActivator, this); break;
|
|
}
|
|
|
|
if (m_flWait > 0)
|
|
{
|
|
SetThink( &CASW_Random_Target_Trigger_Multiple::MultiWaitOver );
|
|
SetNextThink( gpGlobals->curtime + m_flWait );
|
|
}
|
|
else
|
|
{
|
|
// we can't just remove (self) here, because this is a touch function
|
|
// called while C code is looping through area links...
|
|
SetTouch( NULL );
|
|
SetNextThink( gpGlobals->curtime + 0.1f );
|
|
SetThink( &CASW_Random_Target_Trigger_Multiple::SUB_Remove );
|
|
}
|
|
}
|
|
|
|
void CASW_Random_Target_Trigger_Multiple::MultiWaitOver( void )
|
|
{
|
|
SetThink( NULL );
|
|
}
|
|
|
|
|
|
LINK_ENTITY_TO_CLASS( trigger_asw_supplies_chatter, CASW_Supplies_Chatter_Trigger );
|
|
|
|
BEGIN_DATADESC( CASW_Supplies_Chatter_Trigger )
|
|
// Function Pointers
|
|
DEFINE_FUNCTION(SuppliesChatterTouch),
|
|
DEFINE_FUNCTION(MultiWaitOver ),
|
|
|
|
DEFINE_KEYFIELD(m_bNoAmmo, FIELD_BOOLEAN, "NoAmmo"),
|
|
|
|
// Outputs
|
|
DEFINE_OUTPUT(m_OnTrigger, "OnTrigger")
|
|
END_DATADESC()
|
|
|
|
void CASW_Supplies_Chatter_Trigger::Spawn( void )
|
|
{
|
|
BaseClass::Spawn();
|
|
|
|
InitTrigger();
|
|
|
|
if (m_flWait == 0)
|
|
{
|
|
m_flWait = 0.2;
|
|
}
|
|
|
|
ASSERTSZ(m_iHealth == 0, "trigger_multiple with health");
|
|
SetTouch( &CASW_Supplies_Chatter_Trigger::SuppliesChatterTouch );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Touch function. Activates the trigger.
|
|
// Input : pOther - The thing that touched us.
|
|
//-----------------------------------------------------------------------------
|
|
void CASW_Supplies_Chatter_Trigger::SuppliesChatterTouch(CBaseEntity *pOther)
|
|
{
|
|
if (PassesTriggerFilters(pOther) && pOther->Classify() == CLASS_ASW_MARINE)
|
|
{
|
|
ActivateSuppliesChatterTrigger( pOther );
|
|
}
|
|
}
|
|
|
|
void CASW_Supplies_Chatter_Trigger::ActivateSuppliesChatterTrigger(CBaseEntity *pActivator)
|
|
{
|
|
if (GetNextThink() > gpGlobals->curtime)
|
|
return; // still waiting for reset time
|
|
|
|
m_hActivator = pActivator;
|
|
|
|
m_OnTrigger.FireOutput(m_hActivator, this);
|
|
|
|
// pick a nearby marine to say the chatter
|
|
if ( ASWGameResource() )
|
|
{
|
|
CASW_Game_Resource *pGameResource = ASWGameResource();
|
|
// count how many are nearby
|
|
int iNearby = 0;
|
|
for (int i=0;i<pGameResource->GetMaxMarineResources();i++)
|
|
{
|
|
CASW_Marine_Resource *pMR = pGameResource->GetMarineResource(i);
|
|
CASW_Marine *pMarine = pMR ? pMR->GetMarineEntity() : NULL;
|
|
if (pMarine && (pActivator->GetAbsOrigin().DistTo(pMarine->GetAbsOrigin()) < 600)
|
|
&& pMarine->GetHealth() > 0)
|
|
iNearby++;
|
|
}
|
|
if (iNearby >= 2) // only do the speech if there are at least 2 marines nearby
|
|
{
|
|
int iChatter = random->RandomInt(0, iNearby-1);
|
|
for (int i=0;i<pGameResource->GetMaxMarineResources();i++)
|
|
{
|
|
CASW_Marine_Resource *pMR = pGameResource->GetMarineResource(i);
|
|
CASW_Marine *pMarine = pMR ? pMR->GetMarineEntity() : NULL;
|
|
if (pMarine && (pActivator->GetAbsOrigin().DistTo(pMarine->GetAbsOrigin()) < 600)
|
|
&& pMarine->GetHealth() > 0)
|
|
{
|
|
if (iChatter <= 0)
|
|
{
|
|
if (m_bNoAmmo)
|
|
pMarine->GetMarineSpeech()->Chatter(CHATTER_SUPPLIES);
|
|
else
|
|
pMarine->GetMarineSpeech()->Chatter(CHATTER_SUPPLIES_AMMO);
|
|
break;
|
|
}
|
|
iChatter--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_flWait > 0)
|
|
{
|
|
SetThink( &CASW_Supplies_Chatter_Trigger::MultiWaitOver );
|
|
SetNextThink( gpGlobals->curtime + m_flWait );
|
|
}
|
|
else
|
|
{
|
|
// we can't just remove (self) here, because this is a touch function
|
|
// called while C code is looping through area links...
|
|
SetTouch( NULL );
|
|
SetNextThink( gpGlobals->curtime + 0.1f );
|
|
SetThink( &CASW_Supplies_Chatter_Trigger::SUB_Remove );
|
|
}
|
|
}
|
|
|
|
void CASW_Supplies_Chatter_Trigger::MultiWaitOver( void )
|
|
{
|
|
SetThink( NULL );
|
|
}
|
|
|
|
|
|
LINK_ENTITY_TO_CLASS( trigger_asw_synup_chatter, CASW_SynUp_Chatter_Trigger );
|
|
|
|
BEGIN_DATADESC( CASW_SynUp_Chatter_Trigger )
|
|
// Function Pointers
|
|
DEFINE_FUNCTION(ChatterTouch),
|
|
DEFINE_FUNCTION(MultiWaitOver ),
|
|
|
|
// Outputs
|
|
DEFINE_OUTPUT(m_OnTrigger, "OnTrigger")
|
|
END_DATADESC()
|
|
|
|
void CASW_SynUp_Chatter_Trigger::Spawn( void )
|
|
{
|
|
BaseClass::Spawn();
|
|
|
|
InitTrigger();
|
|
|
|
m_flWait = 1.0f; // always retry (trigger deletes itself when the conversation takes place or could take place)
|
|
|
|
ASSERTSZ(m_iHealth == 0, "trigger_multiple with health");
|
|
SetTouch( &CASW_SynUp_Chatter_Trigger::ChatterTouch );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Touch function. Activates the trigger.
|
|
// Input : pOther - The thing that touched us.
|
|
//-----------------------------------------------------------------------------
|
|
void CASW_SynUp_Chatter_Trigger::ChatterTouch(CBaseEntity *pOther)
|
|
{
|
|
if (PassesTriggerFilters(pOther) && pOther->Classify() == CLASS_ASW_MARINE)
|
|
{
|
|
ActivateChatterTrigger( pOther );
|
|
}
|
|
}
|
|
|
|
void CASW_SynUp_Chatter_Trigger::ActivateChatterTrigger(CBaseEntity *pActivator)
|
|
{
|
|
if (GetNextThink() > gpGlobals->curtime)
|
|
return; // still waiting for reset time
|
|
|
|
m_hActivator = pActivator;
|
|
|
|
|
|
m_OnTrigger.FireOutput(m_hActivator, this);
|
|
|
|
float f = random->RandomFloat();
|
|
|
|
|
|
// pick a nearby marine to say the chatter
|
|
if ( ASWGameResource() )
|
|
{
|
|
CASW_Game_Resource *pGameResource = ASWGameResource();
|
|
// count how many are nearby
|
|
int iNearby = 0;
|
|
for (int i=0;i<pGameResource->GetMaxMarineResources();i++)
|
|
{
|
|
CASW_Marine_Resource *pMR = pGameResource->GetMarineResource(i);
|
|
CASW_Marine *pMarine = pMR ? pMR->GetMarineEntity() : NULL;
|
|
if (pMarine && (pActivator->GetAbsOrigin().DistTo(pMarine->GetAbsOrigin()) < 600)
|
|
&& pMarine->GetHealth() > 0 && pMarine->GetMarineProfile()
|
|
&& (pMarine->GetMarineProfile()->m_VoiceType == ASW_VOICE_VEGAS || pMarine->GetMarineProfile()->m_VoiceType == ASW_VOICE_CRASH))
|
|
iNearby++;
|
|
}
|
|
int iChatter = random->RandomInt(0, iNearby-1);
|
|
if (iNearby > 0)
|
|
{
|
|
for (int i=0;i<pGameResource->GetMaxMarineResources();i++)
|
|
{
|
|
CASW_Marine_Resource *pMR = pGameResource->GetMarineResource(i);
|
|
CASW_Marine *pMarine = pMR ? pMR->GetMarineEntity() : NULL;
|
|
if (pMarine && (pActivator->GetAbsOrigin().DistTo(pMarine->GetAbsOrigin()) < 600)
|
|
&& pMarine->GetHealth() > 0 && pMarine->GetMarineProfile()
|
|
&& (pMarine->GetMarineProfile()->m_VoiceType == ASW_VOICE_VEGAS || pMarine->GetMarineProfile()->m_VoiceType == ASW_VOICE_CRASH))
|
|
{
|
|
if (iChatter <= 0)
|
|
{
|
|
if (f <= asw_synup_chatter_chance.GetFloat())
|
|
{
|
|
CASW_MarineSpeech::StartConversation(CONV_SYNUP, pMarine);
|
|
}
|
|
else
|
|
{
|
|
}
|
|
m_flWait = 0;
|
|
break;
|
|
}
|
|
iChatter--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_flWait > 0)
|
|
{
|
|
SetThink( &CASW_SynUp_Chatter_Trigger::MultiWaitOver );
|
|
SetNextThink( gpGlobals->curtime + m_flWait );
|
|
}
|
|
else
|
|
{
|
|
// we can't just remove (self) here, because this is a touch function
|
|
// called while C code is looping through area links...
|
|
SetTouch( NULL );
|
|
SetNextThink( gpGlobals->curtime + 0.1f );
|
|
SetThink( &CASW_SynUp_Chatter_Trigger::SUB_Remove );
|
|
}
|
|
}
|
|
|
|
void CASW_SynUp_Chatter_Trigger::MultiWaitOver( void )
|
|
{
|
|
SetThink( NULL );
|
|
}
|
|
|
|
|
|
LINK_ENTITY_TO_CLASS( trigger_asw_marine_position, CASW_Marine_Position_Trigger );
|
|
|
|
BEGIN_DATADESC( CASW_Marine_Position_Trigger )
|
|
DEFINE_KEYFIELD( m_fDesiredFacing, FIELD_FLOAT, "DesiredFacing" ),
|
|
DEFINE_KEYFIELD( m_fTolerance, FIELD_FLOAT, "Tolerance" ),
|
|
// Function Pointers
|
|
DEFINE_FUNCTION(PositionTouch),
|
|
DEFINE_FUNCTION(MultiWaitOver ),
|
|
|
|
// Outputs
|
|
DEFINE_OUTPUT(m_OnTrigger, "OnTrigger"),
|
|
DEFINE_OUTPUT(m_OnMarineInPosition, "MarineInPosition"),
|
|
DEFINE_OUTPUT(m_OnMarineOutOfPosition, "MarineOutOfPosition"),
|
|
|
|
END_DATADESC()
|
|
|
|
void CASW_Marine_Position_Trigger::Spawn( void )
|
|
{
|
|
BaseClass::Spawn();
|
|
|
|
InitTrigger();
|
|
|
|
if (m_flWait == 0)
|
|
{
|
|
m_flWait = 0.2;
|
|
}
|
|
|
|
m_hMarine = NULL;
|
|
|
|
ASSERTSZ(m_iHealth == 0, "trigger_multiple with health");
|
|
SetTouch( &CASW_Marine_Position_Trigger::PositionTouch );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Touch function. Activates the trigger.
|
|
// Input : pOther - The thing that touched us.
|
|
//-----------------------------------------------------------------------------
|
|
void CASW_Marine_Position_Trigger::PositionTouch(CBaseEntity *pOther)
|
|
{
|
|
if (PassesTriggerFilters(pOther) && pOther->Classify() == CLASS_ASW_MARINE)
|
|
{
|
|
ActivatePositionTrigger( pOther );
|
|
}
|
|
}
|
|
|
|
void CASW_Marine_Position_Trigger::ActivatePositionTrigger(CBaseEntity *pActivator)
|
|
{
|
|
if (GetNextThink() > gpGlobals->curtime)
|
|
return; // still waiting for reset time
|
|
|
|
m_hActivator = pActivator;
|
|
m_OnTrigger.FireOutput(m_hActivator, this);
|
|
|
|
SetThink( &CASW_Marine_Position_Trigger::MultiWaitOver );
|
|
SetNextThink( gpGlobals->curtime + 0.1f );
|
|
}
|
|
|
|
void CASW_Marine_Position_Trigger::MultiWaitOver( void )
|
|
{
|
|
int iMarines = 0;
|
|
for (int i=0;i<m_hTouchingEntities.Count();i++)
|
|
{
|
|
CBaseEntity *pOther = m_hTouchingEntities[i];
|
|
if (pOther && pOther->Classify() == CLASS_ASW_MARINE)
|
|
{
|
|
iMarines++;
|
|
if (!m_hMarine.Get() || m_hMarine.Get() == pOther)
|
|
{
|
|
float fYawDiff = UTIL_AngleDiff(m_fDesiredFacing, pOther->EyeAngles()[YAW]);
|
|
bool bInPosition = fabs(fYawDiff) < m_fTolerance;
|
|
if (bInPosition && !m_hMarine.Get())
|
|
{
|
|
m_OnMarineInPosition.FireOutput(pOther, this);
|
|
m_hMarine = pOther;
|
|
}
|
|
else if (m_hMarine.Get() && !bInPosition)
|
|
{
|
|
m_OnMarineOutOfPosition.FireOutput(pOther, this);
|
|
m_hMarine = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (iMarines <= 0)
|
|
{
|
|
SetThink( NULL ); // no more marines inside us, so clear think and allow retrigger
|
|
if (m_hMarine.Get())
|
|
{
|
|
m_OnMarineOutOfPosition.FireOutput(m_hMarine.Get(), this);
|
|
m_hMarine = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetNextThink( gpGlobals->curtime + 0.1f ); // constantly check up on the marines inside us, NOTE: no more OnTriggers will fire while doing this
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------
|
|
// entity that fires outputs when a marine is healed
|
|
// -------------------------------------------------------------
|
|
|
|
LINK_ENTITY_TO_CLASS( asw_info_heal, CASW_Info_Heal );
|
|
|
|
BEGIN_DATADESC( CASW_Info_Heal )
|
|
DEFINE_OUTPUT( m_MarineHealed, "MarineHealed" ),
|
|
END_DATADESC()
|
|
|
|
void CASW_Info_Heal::Spawn()
|
|
{
|
|
BaseClass::Spawn();
|
|
|
|
if ( ASWGameRules() )
|
|
{
|
|
ASWGameRules()->SetInfoHeal( this );
|
|
}
|
|
}
|
|
|
|
void CASW_Info_Heal::OnMarineHealed( CASW_Marine *pHealer, CASW_Marine *pHealed, CASW_Weapon *pHealEquip )
|
|
{
|
|
m_MarineHealed.FireOutput(pHealed, pHealer);
|
|
}
|
|
|
|
// -------------------------------------------------------------
|
|
// entity that hurts the nearest marine, but doesn't kill him
|
|
// -------------------------------------------------------------
|
|
|
|
LINK_ENTITY_TO_CLASS( asw_hurt_nearest_marine, CASW_Hurt_Nearest_Marine );
|
|
|
|
BEGIN_DATADESC( CASW_Hurt_Nearest_Marine )
|
|
DEFINE_INPUTFUNC( FIELD_VOID, "HurtMarine", InputHurtMarine ),
|
|
END_DATADESC()
|
|
|
|
void CASW_Hurt_Nearest_Marine::InputHurtMarine( inputdata_t &inputdata )
|
|
{
|
|
// find the nearest marine
|
|
float distance = 0;
|
|
CBaseEntity *pMarine = UTIL_ASW_NearestMarine( GetAbsOrigin(), distance );
|
|
if ( pMarine )
|
|
{
|
|
if ( pMarine->GetHealth() > 35 )
|
|
{
|
|
pMarine->SetHealth( 35 );
|
|
}
|
|
|
|
CTakeDamageInfo info( this, this, Vector(0,0,0), GetAbsOrigin(), MIN( 5, pMarine->GetHealth() - 1 ), DMG_INFEST );
|
|
pMarine->TakeDamage( info );
|
|
}
|
|
else
|
|
{
|
|
Msg("asw_hurt_nearest_marine failed to find a nearest marine\n");
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------
|
|
// entity that sends an output when X marines are past an area
|
|
// Requires two triggers, one that fires when a marine is behind us and one when the marine is past us.
|
|
// -------------------------------------------------------------
|
|
|
|
LINK_ENTITY_TO_CLASS( asw_marines_past_area, CASW_Marines_Past_Area );
|
|
|
|
BEGIN_DATADESC( CASW_Marines_Past_Area )
|
|
DEFINE_KEYFIELD( m_iNumMarines, FIELD_INTEGER, "NumMarines" ),
|
|
|
|
DEFINE_OUTPUT( m_OutputMarinesPast, "MarinesPast" ),
|
|
|
|
DEFINE_INPUTFUNC( FIELD_VOID, "MarineInFront", InputMarineInFront ),
|
|
DEFINE_INPUTFUNC( FIELD_VOID, "MarineBehind", InputMarineBehind ),
|
|
END_DATADESC()
|
|
|
|
IMPLEMENT_AUTO_LIST( IASW_Marines_Past_Area_List );
|
|
|
|
CASW_Marines_Past_Area::CASW_Marines_Past_Area()
|
|
{
|
|
m_MarinesPast.Purge();
|
|
}
|
|
|
|
void CASW_Marines_Past_Area::OnMarineKilled( CASW_Marine *pKilledMarine )
|
|
{
|
|
int nMarineCount = 0;
|
|
|
|
CASW_Game_Resource *pGameResource = ASWGameResource();
|
|
if ( pGameResource )
|
|
{
|
|
for ( int i = 0; i < pGameResource->GetMaxMarineResources(); i++ )
|
|
{
|
|
CASW_Marine_Resource* pMR = pGameResource->GetMarineResource( i );
|
|
if ( !pMR )
|
|
continue;
|
|
|
|
CASW_Marine *pMarine = pMR->GetMarineEntity();
|
|
if ( !pMarine )
|
|
continue;
|
|
|
|
if ( pMarine != pKilledMarine && pMarine->IsAlive() )
|
|
{
|
|
nMarineCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( pKilledMarine && m_MarinesPast.Find( pKilledMarine ) != m_MarinesPast.InvalidIndex() )
|
|
{
|
|
m_MarinesPast.FindAndRemove( pKilledMarine );
|
|
}
|
|
|
|
if ( ( m_iNumMarines != -1 && m_MarinesPast.Count() >= m_iNumMarines ) ||
|
|
( m_iNumMarines == -1 && nMarineCount > 0 && m_MarinesPast.Count() >= nMarineCount ) )
|
|
{
|
|
m_OutputMarinesPast.FireOutput( this, this );
|
|
}
|
|
}
|
|
|
|
void CASW_Marines_Past_Area::InputMarineInFront( inputdata_t &inputdata )
|
|
{
|
|
int nMarineCount = 0;
|
|
|
|
bool bAddedMarine = false;
|
|
CBaseTrigger *pTrigger = dynamic_cast<CBaseTrigger*>( inputdata.pCaller );
|
|
CASW_Game_Resource *pGameResource = ASWGameResource();
|
|
if ( pTrigger && pGameResource)
|
|
{
|
|
// go through all touching marines from the caller
|
|
for ( int i=0; i<pGameResource->GetMaxMarineResources(); i++ )
|
|
{
|
|
CASW_Marine_Resource* pMR = pGameResource->GetMarineResource( i );
|
|
if ( !pMR )
|
|
continue;
|
|
|
|
CASW_Marine *pMarine = pMR->GetMarineEntity();
|
|
if ( !pMarine )
|
|
continue;
|
|
|
|
if ( pMarine->IsAlive() )
|
|
{
|
|
nMarineCount++;
|
|
}
|
|
|
|
if ( pTrigger->IsTouching( pMarine ) )
|
|
{
|
|
if ( pMarine && m_MarinesPast.Find( pMarine ) == m_MarinesPast.InvalidIndex() )
|
|
{
|
|
m_MarinesPast.AddToTail( pMarine );
|
|
bAddedMarine = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CASW_Marine *pMarine = dynamic_cast<CASW_Marine*>( inputdata.pActivator );
|
|
if ( pMarine && m_MarinesPast.Find( pMarine ) == m_MarinesPast.InvalidIndex() )
|
|
{
|
|
m_MarinesPast.AddToTail( pMarine );
|
|
bAddedMarine = true;
|
|
|
|
if ( ( m_iNumMarines != -1 && m_MarinesPast.Count() >= m_iNumMarines ) ||
|
|
( m_iNumMarines == -1 && nMarineCount > 0 && m_MarinesPast.Count() >= nMarineCount ) )
|
|
{
|
|
m_OutputMarinesPast.FireOutput( pMarine, this );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( bAddedMarine &&
|
|
( m_iNumMarines != -1 && m_MarinesPast.Count() >= m_iNumMarines ) ||
|
|
( m_iNumMarines == -1 && nMarineCount > 0 && m_MarinesPast.Count() >= nMarineCount ) )
|
|
{
|
|
m_OutputMarinesPast.FireOutput( inputdata.pActivator, this );
|
|
}
|
|
}
|
|
|
|
void CASW_Marines_Past_Area::InputMarineBehind( inputdata_t &inputdata )
|
|
{
|
|
CBaseTrigger *pTrigger = dynamic_cast<CBaseTrigger*>( inputdata.pCaller );
|
|
CASW_Game_Resource *pGameResource = ASWGameResource();
|
|
if ( pTrigger && pGameResource)
|
|
{
|
|
// go through all touching marines from the caller
|
|
for ( int i=0; i<pGameResource->GetMaxMarineResources(); i++ )
|
|
{
|
|
CASW_Marine_Resource* pMR = pGameResource->GetMarineResource( i );
|
|
if ( !pMR )
|
|
continue;
|
|
|
|
CASW_Marine *pMarine = pMR->GetMarineEntity();
|
|
if ( !pMarine )
|
|
continue;
|
|
|
|
if ( pTrigger->IsTouching( pMarine ) )
|
|
{
|
|
if ( pMarine && m_MarinesPast.Find( pMarine ) != m_MarinesPast.InvalidIndex() )
|
|
{
|
|
m_MarinesPast.FindAndRemove( pMarine );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_MarinesPast.FindAndRemove( inputdata.pActivator );
|
|
}
|
|
}
|
|
|
|
// ===========================
|
|
|
|
LINK_ENTITY_TO_CLASS( trigger_asw_marine_knockback, CASW_Marine_Knockback_Trigger );
|
|
|
|
BEGIN_DATADESC( CASW_Marine_Knockback_Trigger )
|
|
DEFINE_KEYFIELD( m_vecKnockbackDir, FIELD_VECTOR, "knockdir" ),
|
|
|
|
// Function Pointers
|
|
DEFINE_FUNCTION( KnockbackTriggerTouch ),
|
|
|
|
// Outputs
|
|
DEFINE_OUTPUT(m_OnKnockedBack, "OnKnockedBack")
|
|
END_DATADESC()
|
|
|
|
void CASW_Marine_Knockback_Trigger::Spawn( void )
|
|
{
|
|
BaseClass::Spawn();
|
|
|
|
InitTrigger();
|
|
|
|
ASSERTSZ(m_iHealth == 0, "trigger_multiple with health");
|
|
SetTouch( &CASW_Marine_Knockback_Trigger::KnockbackTriggerTouch );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Touch function. Activates the trigger.
|
|
// Input : pOther - The thing that touched us.
|
|
//-----------------------------------------------------------------------------
|
|
void CASW_Marine_Knockback_Trigger::KnockbackTriggerTouch(CBaseEntity *pOther)
|
|
{
|
|
if ( PassesTriggerFilters(pOther) && pOther->Classify() == CLASS_ASW_MARINE )
|
|
{
|
|
CASW_Marine *pMarine = assert_cast<CASW_Marine*>( pOther );
|
|
if ( pMarine )
|
|
{
|
|
CASW_Melee_Attack *pAttack = pMarine->GetCurrentMeleeAttack();
|
|
if ( !pAttack || !( pAttack->m_nAttackID == CASW_Melee_System::s_nKnockdownBackwardAttackID || pAttack->m_nAttackID == CASW_Melee_System::s_nKnockdownForwardAttackID ) )
|
|
{
|
|
if ( pMarine->GetForcedActionRequest() == 0 )
|
|
{
|
|
pMarine->Knockdown( this, m_vecKnockbackDir, true );
|
|
m_hActivator = pOther;
|
|
m_OnKnockedBack.FireOutput(pOther, this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |