You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
650 lines
17 KiB
650 lines
17 KiB
#include "cbase.h" |
|
#include "props.h" |
|
#include "asw_egg.h" |
|
#include "asw_shareddefs.h" |
|
#include "asw_marine.h" |
|
#include "asw_marine_resource.h" |
|
#include "asw_fx_shared.h" |
|
#include "asw_parasite.h" |
|
#include "asw_gamerules.h" |
|
#include "asw_mission_manager.h" |
|
#include "asw_util_shared.h" |
|
#include "EntityFlame.h" |
|
#include "te_effect_dispatch.h" |
|
#include "asw_marine_speech.h" |
|
#include "asw_burning.h" |
|
#include "asw_game_resource.h" |
|
#include "asw_player.h" |
|
#include "asw_achievements.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
#define EGG_MODEL "models/aliens/egg/egg.mdl" |
|
#define EGG_OPEN_ANIM "open" |
|
#define EGG_CLOSED_ANIM "closed" |
|
#define EGG_JIGGLE_ANIM "closed" |
|
#define EGG_OPENING_ANIM "opening" |
|
#define EGG_ON_FIRE_ANIM "fire_open" |
|
#define EGG_HATCH_ANIM "egg_pop" |
|
|
|
#define ASW_EGG_HATCH_DELAY 3.0f |
|
#define ASW_EGG_ALWAYS_BURST_DISTANCE 120.0f |
|
#define ASW_EGG_BURST_DISTANCE_EASY 250.0f |
|
#define ASW_EGG_BURST_DISTANCE 450.0f |
|
#define ASW_EGG_RESET_DELAY 20.0f |
|
|
|
|
|
LINK_ENTITY_TO_CLASS( asw_egg, CASW_Egg ); |
|
|
|
|
|
IMPLEMENT_SERVERCLASS_ST(CASW_Egg, DT_ASW_Egg) |
|
SendPropBool( SENDINFO( m_bOnFire ) ), |
|
SendPropFloat( SENDINFO( m_fEggAwake ) ), |
|
END_SEND_TABLE() |
|
|
|
//--------------------------------------------------------- |
|
// Save/Restore |
|
//--------------------------------------------------------- |
|
BEGIN_DATADESC( CASW_Egg ) |
|
DEFINE_THINKFUNC( AnimThink ), |
|
DEFINE_THINKFUNC( SetupParasiteThink ), |
|
DEFINE_FUNCTION( EggTouch ), |
|
DEFINE_KEYFIELD( m_sParasiteClass, FIELD_STRING, "ParasiteClass" ), |
|
DEFINE_KEYFIELD( m_bFixedJumpDirection, FIELD_BOOLEAN, "FixedJumpDir" ), |
|
DEFINE_KEYFIELD( m_bSkipEggChatter, FIELD_BOOLEAN, "SkipEggChatter" ), |
|
DEFINE_KEYFIELD( m_bSmallOpenRadius, FIELD_BOOLEAN, "SmallOpenRadius" ), |
|
DEFINE_FIELD(m_fNextMarineCheckTime, FIELD_FLOAT), |
|
DEFINE_FIELD(m_bOpen, FIELD_BOOLEAN), |
|
DEFINE_FIELD(m_bOpening, FIELD_BOOLEAN), |
|
DEFINE_FIELD(m_bHatched, FIELD_BOOLEAN), |
|
DEFINE_FIELD(m_fHatchTime, FIELD_TIME), |
|
DEFINE_FIELD(m_bStoredEggSize, FIELD_BOOLEAN), |
|
DEFINE_FIELD(m_vecStartSurroundMins, FIELD_VECTOR), |
|
DEFINE_FIELD(m_vecStartSurroundMaxs, FIELD_VECTOR), |
|
DEFINE_FIELD(m_bMadeParasiteVisible, FIELD_BOOLEAN), |
|
DEFINE_FIELD(m_hParasite, FIELD_EHANDLE), |
|
DEFINE_FIELD( m_bOnFire, FIELD_BOOLEAN ), |
|
DEFINE_FIELD(m_hBurner, FIELD_EHANDLE), |
|
DEFINE_FIELD(m_hBurnerWeapon, FIELD_EHANDLE), |
|
DEFINE_FIELD(m_fEggAwake, FIELD_FLOAT), |
|
DEFINE_FIELD(m_fEggResetTime, FIELD_TIME), |
|
|
|
DEFINE_INPUTFUNC( FIELD_VOID, "EggOpen", InputOpen ), |
|
DEFINE_INPUTFUNC( FIELD_VOID, "EggHatch", InputHatch ), |
|
|
|
DEFINE_OUTPUT( m_OnOpened, "OnEggOpened" ), |
|
DEFINE_OUTPUT( m_OnHatched, "OnEggHatched" ), |
|
DEFINE_OUTPUT( m_OnDestroyed, "OnEggDestroyed" ), |
|
DEFINE_OUTPUT( m_OnEggReset, "OnEggReset" ), |
|
END_DATADESC() |
|
|
|
ConVar asw_egg_respawn( "asw_egg_respawn", "0", FCVAR_CHEAT, "If set, eggs will respawn the parasite inside" ); |
|
|
|
float CASW_Egg::s_fNextSpottedChatterTime = 0; |
|
|
|
CASW_Egg::CASW_Egg() |
|
{ |
|
m_bOpen = false; |
|
m_bOpening = false; |
|
m_bHatched = false; |
|
m_bMadeParasiteVisible = false; |
|
m_hParasite = NULL; |
|
m_bSmallOpenRadius = false; |
|
m_hBurner = NULL; |
|
m_fEggAwake = 0; |
|
m_fEggResetTime = 0; |
|
} |
|
|
|
|
|
CASW_Egg::~CASW_Egg() |
|
{ |
|
if (GetParasite()) |
|
GetParasite()->SetEgg(NULL); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CASW_Egg::Spawn( void ) |
|
{ |
|
SetMoveType( MOVETYPE_NONE ); |
|
//SetSolid( SOLID_BBOX ); |
|
SetSolid( SOLID_VPHYSICS ); |
|
CreateVPhysics(); |
|
SetCollisionGroup( ASW_COLLISION_GROUP_EGG ); |
|
|
|
Precache(); |
|
SetModel(EGG_MODEL); |
|
ResetSequence( LookupSequence( EGG_CLOSED_ANIM ) ); |
|
SetPlaybackRate( RandomFloat( 0.95, 1.05 ) ); // Slightly randomize the playback rate so they don't all match |
|
m_bStoredEggSize = false; |
|
|
|
BaseClass::Spawn(); |
|
|
|
AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); |
|
|
|
//SetCollisionBounds( Vector(-26,-26,0), Vector(26,26,60)); |
|
SetThink( &CASW_Egg::SetupParasiteThink ); |
|
SetNextThink( gpGlobals->curtime + 0.3f ); |
|
SetTouch( &CASW_Egg::EggTouch ); |
|
|
|
AddFlag( FL_AIMTARGET ); |
|
|
|
// create our parasite to sit inside and await a hapless marine |
|
QAngle angParasiteFacing = GetAbsAngles(); |
|
if (!m_bFixedJumpDirection) |
|
{ |
|
angParasiteFacing.y = random->RandomInt(0,360); |
|
} |
|
|
|
|
|
m_hParasite = dynamic_cast<CASW_Parasite*>(CreateNoSpawn("asw_parasite", GetAbsOrigin(), angParasiteFacing, this)); |
|
if (GetParasite()) |
|
{ |
|
//Msg("Telling parasite to idle in egg\n"); |
|
GetParasite()->IdleInEgg(true); |
|
//GetParasite()->AddSpawnFlags(SF_NPC_WAIT_FOR_SCRIPT); |
|
GetParasite()->Spawn(); |
|
GetParasite()->SetSleepState(AISS_WAITING_FOR_INPUT); |
|
GetParasite()->SetEgg(this); |
|
|
|
GetParasite()->SetParent( this ); |
|
} |
|
|
|
m_takedamage = DAMAGE_YES; |
|
m_iHealth = 50; |
|
m_iMaxHealth = m_iHealth; |
|
m_fNextMarineCheckTime = gpGlobals->curtime + random->RandomFloat(5.0f, 10.0f); |
|
|
|
if ( ASWGameResource() && ASWGameResource()->m_iStartingEggsInMap >= 0 ) |
|
{ |
|
ASWGameResource()->m_iStartingEggsInMap++; |
|
} |
|
} |
|
|
|
bool CASW_Egg::CreateVPhysics() |
|
{ |
|
VPhysicsInitStatic(); |
|
return true; |
|
} |
|
|
|
void CASW_Egg::Precache() |
|
{ |
|
PrecacheModel(EGG_MODEL); |
|
PrecacheParticleSystem( "egg_open" ); |
|
PrecacheParticleSystem( "egg_hatch" ); |
|
PrecacheParticleSystem( "egg_death" ); |
|
|
|
PrecacheModel ("models/aliens/egg/egggib_1.mdl"); |
|
PrecacheModel ("models/aliens/egg/egggib_2.mdl"); |
|
PrecacheModel ("models/aliens/egg/egggib_3.mdl"); |
|
|
|
PrecacheScriptSound("ASW_Egg.Open"); |
|
PrecacheScriptSound("ASW_Egg.Gib"); |
|
PrecacheScriptSound("ASW_Parasite.EggBurst"); |
|
BaseClass::Precache(); |
|
UTIL_PrecacheOther( "asw_parasite" ); |
|
} |
|
|
|
|
|
// int CASW_Egg::ShouldTransmit( const CCheckTransmitInfo *pInfo ) |
|
// { |
|
// return FL_EDICT_ALWAYS; |
|
// } |
|
// |
|
// int CASW_Egg::UpdateTransmitState() |
|
// { |
|
// return SetTransmitState( FL_EDICT_FULLCHECK ); |
|
// } |
|
|
|
void CASW_Egg::SetupParasiteThink() |
|
{ |
|
if (GetParasite() && GetParasite()->IsEffectActive(EF_NODRAW)) |
|
{ |
|
GetParasite()->RemoveEffects(EF_NODRAW); |
|
GetParasite()->SetActivity(ACT_IDLE); |
|
m_bMadeParasiteVisible = true; |
|
SetNextThink( gpGlobals->curtime + 0.5f ); |
|
return; |
|
} |
|
|
|
if (!m_bMadeParasiteVisible) |
|
{ |
|
SetNextThink( gpGlobals->curtime + 0.1f ); |
|
return; |
|
} |
|
|
|
// if we're done setting up the parasite, turn thinking over to the normal egg processing |
|
SetThink(&CASW_Egg::AnimThink); |
|
SetNextThink( gpGlobals->curtime + 0.1f ); |
|
} |
|
|
|
void CASW_Egg::ReachedEndOfSequence() |
|
{ |
|
if ( ( GetSequence() == LookupSequence( EGG_OPENING_ANIM ) ) ) |
|
{ |
|
ResetSequence( LookupSequence(EGG_OPEN_ANIM) ); |
|
m_bOpen = true; |
|
} |
|
if ( ( GetSequence() == LookupSequence( EGG_ON_FIRE_ANIM ) ) ) |
|
{ |
|
m_bOpen = true; |
|
} |
|
} |
|
|
|
void CASW_Egg::AnimThink( void ) |
|
{ |
|
if ( m_bOnFire ) |
|
{ |
|
ResetSequence( LookupSequence( EGG_ON_FIRE_ANIM ) ); |
|
} |
|
|
|
if (m_bOpen && !m_bHatched && gpGlobals->curtime >= m_fHatchTime) |
|
{ |
|
Hatch(NULL); |
|
} |
|
|
|
if (!m_bStoredEggSize) |
|
{ |
|
m_bStoredEggSize = true; |
|
m_vecStartSurroundMins = CollisionProp()->OBBMins(); |
|
m_vecStartSurroundMaxs = CollisionProp()->OBBMaxs(); |
|
//CollisionProp()->WorldSpaceSurroundingBounds( &m_vecStartSurroundMins, &m_vecStartSurroundMaxs ); |
|
//Msg("Storing %f and %f, %f\n", m_vecStartSurroundMaxs.x, m_vecStartSurroundMaxs.y, m_vecStartSurroundMaxs.z); |
|
} |
|
// periodically find the nearest marine and check if we should burst open |
|
if (!m_bOpen && gpGlobals->curtime >= m_fNextMarineCheckTime) |
|
{ |
|
float marine_distance = -1; |
|
CBaseEntity *pMarine = UTIL_ASW_NearestMarine(GetAbsOrigin(), marine_distance ); |
|
if (!m_bSkipEggChatter && pMarine && marine_distance < 500 && gpGlobals->curtime > s_fNextSpottedChatterTime) |
|
{ |
|
|
|
CASW_Marine *pSpottedMarine = UTIL_ASW_Marine_Can_Chatter_Spot(this, 500); |
|
if (pSpottedMarine) |
|
{ |
|
pSpottedMarine->GetMarineSpeech()->Chatter(CHATTER_EGGS); |
|
s_fNextSpottedChatterTime = gpGlobals->curtime + 30.0f; |
|
} |
|
else |
|
s_fNextSpottedChatterTime = gpGlobals->curtime + 1.0f; |
|
} |
|
float flOpenDist = ASW_EGG_BURST_DISTANCE; |
|
if ( ASWGameRules() && ASWGameRules()->GetSkillLevel() == 1 ) |
|
{ |
|
flOpenDist = ASW_EGG_BURST_DISTANCE_EASY; |
|
} |
|
if ( pMarine ) |
|
{ |
|
//Msg( "Egg %d check. Distance = %f\n", entindex(), marine_distance ); |
|
if ( marine_distance <= ASW_EGG_ALWAYS_BURST_DISTANCE ) |
|
{ |
|
Open(pMarine); |
|
} |
|
else if ( marine_distance <= ASW_EGG_BURST_DISTANCE && RandomFloat() < 0.1f ) |
|
{ |
|
Open(pMarine); |
|
} |
|
} |
|
|
|
if ( !m_bOpen ) |
|
{ |
|
// rethink interval based on how near the marines are |
|
if (marine_distance == -1 || marine_distance > 4096) |
|
{ |
|
m_fNextMarineCheckTime = gpGlobals->curtime + 5.0f; |
|
} |
|
else |
|
{ |
|
if (ASWGameRules() && ASWGameRules()->GetSkillLevel() >= 4 ) |
|
{ |
|
m_fNextMarineCheckTime = gpGlobals->curtime + 1.5f; |
|
} |
|
else if (ASWGameRules() && ASWGameRules()->GetSkillLevel() == 3 ) |
|
{ |
|
m_fNextMarineCheckTime = gpGlobals->curtime + 2.0f; |
|
} |
|
else |
|
{ |
|
m_fNextMarineCheckTime = gpGlobals->curtime + 2.4f; |
|
} |
|
} |
|
} |
|
} |
|
|
|
// fade in the green lines if we're about to wake up |
|
if ( m_bOpen && !m_bHatched ) |
|
{ |
|
m_fEggAwake = MIN( 1.0f, m_fEggAwake.Get() + gpGlobals->frametime * 3.0f ); |
|
} |
|
else |
|
{ |
|
m_fEggAwake = MAX( 0, m_fEggAwake.Get() - gpGlobals->frametime * 0.5f ); // slow power down |
|
|
|
if ( m_bHatched && gpGlobals->curtime > m_fEggResetTime && m_fEggResetTime > 0) |
|
{ |
|
ResetEgg(); |
|
} |
|
} |
|
|
|
SetNextThink( gpGlobals->curtime + 0.1f ); |
|
|
|
StudioFrameAdvance(); |
|
} |
|
|
|
void CASW_Egg::ResetEgg() |
|
{ |
|
if ( m_bOnFire ) |
|
{ |
|
return; |
|
} |
|
if ( m_bHatched ) |
|
{ |
|
// spawn a new parasite |
|
QAngle angParasiteFacing = GetAbsAngles(); |
|
if (!m_bFixedJumpDirection) |
|
{ |
|
angParasiteFacing.y = random->RandomInt(0,360); |
|
} |
|
|
|
m_hParasite = dynamic_cast<CASW_Parasite*>(CreateNoSpawn("asw_parasite", GetAbsOrigin(), angParasiteFacing, this)); |
|
if (GetParasite()) |
|
{ |
|
//Msg("Telling parasite to idle in egg\n"); |
|
|
|
GetParasite()->IdleInEgg(true); |
|
//GetParasite()->AddSpawnFlags(SF_NPC_WAIT_FOR_SCRIPT); |
|
GetParasite()->Spawn(); |
|
GetParasite()->SetSleepState(AISS_WAITING_FOR_INPUT); |
|
GetParasite()->SetEgg(this); |
|
|
|
GetParasite()->SetParent( this ); |
|
} |
|
} |
|
|
|
// reset the egg so it can open and hatch again |
|
m_bOpen = false; |
|
m_bHatched = false; |
|
ResetSequence( LookupSequence( EGG_CLOSED_ANIM ) ); |
|
SetBodygroup( 1,0 ); |
|
SetPlaybackRate( RandomFloat( 0.95, 1.05 ) ); // Slightly randomize the playback rate so they don't all match |
|
m_OnEggReset.FireOutput(this, this); |
|
} |
|
|
|
void CASW_Egg::Open(CBaseEntity* pOther) |
|
{ |
|
if ( !m_bOpen && !m_bHatched && !m_bOpening ) |
|
{ |
|
if ( m_bOnFire ) |
|
{ |
|
ResetSequence( LookupSequence ( EGG_ON_FIRE_ANIM ) ); |
|
} |
|
else |
|
{ |
|
ResetSequence( LookupSequence ( EGG_OPENING_ANIM ) ); |
|
SetCycle( 0 ); |
|
} |
|
|
|
SpawnEffects(EGG_FLAG_OPEN); |
|
CheckEggSize(); |
|
RemoveSolidFlags( FSOLID_NOT_SOLID ); |
|
//UTIL_ASW_BloodDrips( GetAbsOrigin()+Vector(0,0,50), Vector(0,0,1), BLOOD_COLOR_GREEN, 4 ); |
|
m_fHatchTime = gpGlobals->curtime + (ASW_EGG_HATCH_DELAY * random->RandomFloat(1.0f, 2.0f)); |
|
m_OnOpened.FireOutput(pOther, this); |
|
EmitSound("ASW_Egg.Open"); |
|
m_bOpening = true; |
|
} |
|
|
|
} |
|
|
|
void CASW_Egg::Hatch(CBaseEntity* pOther) |
|
{ |
|
if (!m_bHatched && m_bOpen) |
|
{ |
|
SpawnEffects(EGG_FLAG_HATCH); |
|
SetBodygroup( 1,1 ); |
|
ResetSequence( LookupSequence( EGG_HATCH_ANIM ) ); |
|
m_bHatched = true; |
|
CheckEggSize(); |
|
RemoveSolidFlags( FSOLID_NOT_SOLID ); |
|
// todo: make some green goo spurt out |
|
//UTIL_ASW_BloodDrips( GetAbsOrigin()+Vector(0,0,30), Vector(0,0,1), BLOOD_COLOR_GREEN, 4 ); |
|
// todo: spawn the parasite |
|
m_OnHatched.FireOutput(pOther, this); |
|
EmitSound("ASW_Parasite.EggBurst"); |
|
if (GetParasite()) |
|
{ |
|
if (IsOnFire()) |
|
{ |
|
CBaseEntity *pBurner = m_hBurner.Get(); |
|
if (!pBurner) |
|
pBurner = this; |
|
GetParasite()->ASW_Ignite( 30, 0, pBurner, m_hBurnerWeapon.Get() ); |
|
} |
|
else |
|
{ |
|
if ( ASWGameResource() ) |
|
{ |
|
ASWGameResource()->m_iEggsHatched++; |
|
} |
|
} |
|
|
|
GetParasite()->SetJumpFromEgg(true); |
|
GetParasite()->IdleInEgg(false); |
|
GetParasite()->Wake(); |
|
} |
|
|
|
if ( asw_egg_respawn.GetBool() ) |
|
{ |
|
m_fEggResetTime = gpGlobals->curtime + ASW_EGG_RESET_DELAY * random->RandomFloat(1.0f, 2.0f); |
|
} |
|
} |
|
} |
|
|
|
void CASW_Egg::EggTouch(CBaseEntity* pOther) |
|
{ |
|
// egg will open if touched by a marine |
|
CASW_Marine* pMarine = CASW_Marine::AsMarine( pOther ); |
|
if (pMarine) |
|
{ |
|
if (!m_bOpen) |
|
Open(pOther); |
|
} |
|
} |
|
|
|
// inputs |
|
|
|
void CASW_Egg::InputOpen( inputdata_t &inputdata ) |
|
{ |
|
if (!m_bOpen) |
|
Open(inputdata.pActivator); |
|
} |
|
|
|
void CASW_Egg::InputHatch( inputdata_t &inputdata ) |
|
{ |
|
if (!m_bHatched) |
|
{ |
|
m_bOpen = true; |
|
Hatch(inputdata.pActivator); |
|
} |
|
} |
|
|
|
// check the egg hasn't got any bigger in size, otherwise nearby creatures could get stuck in it |
|
void CASW_Egg::CheckEggSize() |
|
{ |
|
Vector vecSurroundMins, vecSurroundMaxs; |
|
vecSurroundMins = CollisionProp()->OBBMins(); |
|
vecSurroundMaxs = CollisionProp()->OBBMaxs(); |
|
|
|
if (vecSurroundMins.x < m_vecStartSurroundMins.x) |
|
vecSurroundMins.x = m_vecStartSurroundMins.x; |
|
if (vecSurroundMins.y < m_vecStartSurroundMins.y) |
|
vecSurroundMins.y = m_vecStartSurroundMins.y; |
|
if (vecSurroundMins.z < m_vecStartSurroundMins.z) |
|
vecSurroundMins.z = m_vecStartSurroundMins.z; |
|
|
|
if (vecSurroundMaxs.x > m_vecStartSurroundMaxs.x) |
|
vecSurroundMaxs.x = m_vecStartSurroundMaxs.x; |
|
if (vecSurroundMaxs.y > m_vecStartSurroundMaxs.y) |
|
vecSurroundMaxs.y = m_vecStartSurroundMaxs.y; |
|
if (vecSurroundMaxs.z > m_vecStartSurroundMaxs.z) |
|
vecSurroundMaxs.z = m_vecStartSurroundMaxs.z; |
|
|
|
SetCollisionBounds( vecSurroundMins, vecSurroundMaxs ); |
|
} |
|
|
|
void CASW_Egg::SpawnEffects(int flags) |
|
{ |
|
UTIL_ASW_EggGibs( WorldSpaceCenter(), flags, entindex() ); |
|
} |
|
|
|
int CASW_Egg::OnTakeDamage( const CTakeDamageInfo &info ) |
|
{ |
|
int result = BaseClass::OnTakeDamage(info); |
|
|
|
if (result > 0) |
|
{ |
|
CASW_Marine* pMarine = dynamic_cast<CASW_Marine*>(info.GetAttacker()); |
|
if (pMarine) |
|
pMarine->HurtAlien(this, info); |
|
|
|
if (info.GetDamageType() & DMG_BURN || |
|
info.GetDamageType() & DMG_BLAST) |
|
{ |
|
ASW_Ignite(30.0f, 0, info.GetAttacker(), info.GetWeapon() ); |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
void CASW_Egg::Event_Killed( const CTakeDamageInfo &info ) |
|
{ |
|
// make the egg shatter in however many stages are left |
|
//if (m_lifeState == LIFE_DEAD) // already dead? |
|
//return; |
|
if (!m_bHatched) |
|
{ |
|
SpawnEffects(EGG_FLAG_DIE); |
|
|
|
m_bOpen = true; |
|
CheckEggSize(); |
|
RemoveSolidFlags( FSOLID_NOT_SOLID ); |
|
} |
|
else |
|
{ |
|
SpawnEffects(EGG_FLAG_DIE); |
|
} |
|
|
|
// kill the parasite inside |
|
if (GetParasite() && !m_bHatched) |
|
{ |
|
CTakeDamageInfo killsite(info.GetInflictor(), info.GetAttacker(), info.GetDamageForce(), info.GetDamagePosition(), 150, |
|
info.GetDamageType()); |
|
killsite.SetWeapon( info.GetWeapon() ); |
|
GetParasite()->TakeDamage(killsite); |
|
} |
|
|
|
if (ASWGameRules() && ASWGameRules()->GetMissionManager()) |
|
ASWGameRules()->GetMissionManager()->EggKilled(this); |
|
|
|
CASW_Marine *pMarine = dynamic_cast<CASW_Marine*>(info.GetAttacker()); |
|
if (pMarine && pMarine->GetMarineResource()) |
|
{ |
|
pMarine->GetMarineResource()->m_iEggKills++; |
|
} |
|
if ( ASWGameResource() ) |
|
{ |
|
ASWGameResource()->m_iEggsKilled++; |
|
if ( ASWGameResource()->m_iStartingEggsInMap > 5 && ASWGameResource()->m_iEggsKilled >= ASWGameResource()->m_iStartingEggsInMap && ASWGameResource()->m_iEggsHatched <= 0 ) |
|
{ |
|
for ( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CASW_Player* pPlayer = dynamic_cast<CASW_Player*>( UTIL_PlayerByIndex( i ) ); |
|
if ( !pPlayer || !pPlayer->IsConnected() || !pPlayer->GetMarine() ) |
|
continue; |
|
|
|
pPlayer->AwardAchievement( ACHIEVEMENT_ASW_EGGS_BEFORE_HATCH ); |
|
} |
|
} |
|
} |
|
|
|
m_OnDestroyed.FireOutput(info.GetInflictor(), this); |
|
|
|
BaseClass::Event_Killed(info); |
|
|
|
SetThink(&CASW_Egg::SUB_Remove); |
|
SetNextThink(gpGlobals->curtime + 0.1f); |
|
|
|
// break the egg |
|
Vector velocity; |
|
velocity = Vector( RandomFloat( 50, 100 ), RandomFloat( 50, 100 ), RandomFloat( 100, 250 ) ); |
|
AngularImpulse angVelocity = RandomAngularImpulse( -500.0f, 500.0f ); |
|
breakablepropparams_t params( GetAbsOrigin(), GetAbsAngles(), velocity, angVelocity ); |
|
params.impactEnergyScale = 1.0f; |
|
params.defBurstScale = 100.0f; |
|
params.defCollisionGroup = COLLISION_GROUP_DEBRIS; |
|
PropBreakableCreateAll( GetModelIndex(), NULL, params, this, -1, true, true ); |
|
|
|
EmitSound("ASW_Egg.Gib"); |
|
} |
|
|
|
void CASW_Egg::ParasiteDied(CASW_Parasite* pParasite) |
|
{ |
|
m_hParasite = NULL; |
|
} |
|
|
|
void CASW_Egg::ASW_Ignite( float flFlameLifetime, float flSize, CBaseEntity *pAttacker, CBaseEntity *pDamagingWeapon /*= NULL */ ) |
|
{ |
|
if( IsOnFire() ) |
|
return; |
|
|
|
AddFlag( FL_ONFIRE ); |
|
m_bOnFire = true; |
|
if (ASWBurning()) |
|
ASWBurning()->BurnEntity(this, pAttacker, flFlameLifetime, 0.4f, 5.0f * 0.4f, pDamagingWeapon ); // 5 dps, applied every 0.4 seconds |
|
|
|
m_hBurner = pAttacker; |
|
m_hBurnerWeapon = pDamagingWeapon; |
|
|
|
m_OnIgnite.FireOutput( this, this ); |
|
} |
|
|
|
void CASW_Egg::Ignite( float flFlameLifetime, bool bNPCOnly, float flSize, bool bCalledByLevelDesigner ) |
|
{ |
|
return; // use ASW_Ignite instead |
|
} |
|
|
|
CASW_Parasite* CASW_Egg::GetParasite() |
|
{ |
|
return dynamic_cast<CASW_Parasite*>(m_hParasite.Get()); |
|
} |
|
|
|
void CASW_Egg::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) |
|
{ |
|
if ( m_takedamage == DAMAGE_NO ) |
|
return; |
|
|
|
CTakeDamageInfo subInfo = info; |
|
m_nForceBone = ptr->physicsbone; // save this bone for physics forces |
|
|
|
Assert( m_nForceBone > -255 && m_nForceBone < 256 ); |
|
|
|
if ( subInfo.GetDamage() >= 1.0 && !(subInfo.GetDamageType() & DMG_SHOCK ) |
|
&& !( subInfo.GetDamageType() & DMG_BURN ) ) |
|
{ |
|
Bleed( subInfo, ptr->endpos, vecDir, ptr ); |
|
} |
|
|
|
if( !info.GetInflictor() ) |
|
{ |
|
subInfo.SetInflictor( info.GetAttacker() ); |
|
} |
|
|
|
AddMultiDamage( subInfo, this ); |
|
} |
|
|
|
void CASW_Egg::Bleed( const CTakeDamageInfo &info, const Vector &vecPos, const Vector &vecDir, trace_t *ptr ) |
|
{ |
|
UTIL_ASW_DroneBleed( vecPos, -vecDir, 4 ); |
|
}
|
|
|