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.
294 lines
7.7 KiB
294 lines
7.7 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: An entity that creates NPCs in the game. |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "entityapi.h" |
|
#include "entityoutput.h" |
|
#include "ai_basenpc.h" |
|
#include "hl1_monstermaker.h" |
|
#include "mapentities.h" |
|
|
|
|
|
BEGIN_DATADESC( CNPCMaker ) |
|
|
|
DEFINE_KEYFIELD( m_iMaxNumNPCs, FIELD_INTEGER, "monstercount" ), |
|
DEFINE_KEYFIELD( m_iMaxLiveChildren, FIELD_INTEGER, "MaxLiveChildren" ), |
|
DEFINE_KEYFIELD( m_flSpawnFrequency, FIELD_FLOAT, "delay" ), |
|
DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), |
|
DEFINE_KEYFIELD( m_iszNPCClassname, FIELD_STRING, "monstertype" ), |
|
|
|
DEFINE_FIELD( m_cLiveChildren, FIELD_INTEGER ), |
|
DEFINE_FIELD( m_flGround, FIELD_FLOAT ), |
|
|
|
// Inputs |
|
DEFINE_INPUTFUNC( FIELD_VOID, "Spawn", InputSpawnNPC ), |
|
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), |
|
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), |
|
DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), |
|
|
|
// Outputs |
|
DEFINE_OUTPUT( m_OnSpawnNPC, "OnSpawnNPC" ), |
|
|
|
// Function Pointers |
|
DEFINE_THINKFUNC( MakerThink ), |
|
|
|
END_DATADESC() |
|
|
|
|
|
LINK_ENTITY_TO_CLASS( monstermaker, CNPCMaker ); |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Spawn |
|
//----------------------------------------------------------------------------- |
|
void CNPCMaker::Spawn( void ) |
|
{ |
|
SetSolid( SOLID_NONE ); |
|
m_cLiveChildren = 0; |
|
Precache(); |
|
|
|
// If I can make an infinite number of NPC, force them to fade |
|
if ( m_spawnflags & SF_NPCMAKER_INF_CHILD ) |
|
{ |
|
m_spawnflags |= SF_NPCMAKER_FADE; |
|
} |
|
|
|
//Start on? |
|
if ( m_bDisabled == false ) |
|
{ |
|
SetThink ( &CNPCMaker::MakerThink ); |
|
SetNextThink( gpGlobals->curtime + m_flSpawnFrequency ); |
|
} |
|
else |
|
{ |
|
//wait to be activated. |
|
SetThink ( &CBaseEntity::SUB_DoNothing ); |
|
} |
|
m_flGround = 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns whether or not it is OK to make an NPC at this instant. |
|
//----------------------------------------------------------------------------- |
|
bool CNPCMaker::CanMakeNPC( void ) |
|
{ |
|
if ( m_iMaxLiveChildren > 0 && m_cLiveChildren >= m_iMaxLiveChildren ) |
|
{// not allowed to make a new one yet. Too many live ones out right now. |
|
return false; |
|
} |
|
|
|
if ( !m_flGround ) |
|
{ |
|
// set altitude. Now that I'm activated, any breakables, etc should be out from under me. |
|
trace_t tr; |
|
|
|
UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() - Vector ( 0, 0, 2048 ), MASK_NPCSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); |
|
m_flGround = tr.endpos.z; |
|
} |
|
|
|
Vector mins = GetAbsOrigin() - Vector( 34, 34, 0 ); |
|
Vector maxs = GetAbsOrigin() + Vector( 34, 34, 0 ); |
|
maxs.z = GetAbsOrigin().z; |
|
|
|
//Only adjust for the ground if we want it |
|
if ( ( m_spawnflags & SF_NPCMAKER_NO_DROP ) == false ) |
|
{ |
|
mins.z = m_flGround; |
|
} |
|
|
|
CBaseEntity *pList[128]; |
|
|
|
int count = UTIL_EntitiesInBox( pList, 128, mins, maxs, FL_CLIENT|FL_NPC ); |
|
if ( count ) |
|
{ |
|
//Iterate through the list and check the results |
|
for ( int i = 0; i < count; i++ ) |
|
{ |
|
//Don't build on top of another entity |
|
if ( pList[i] == NULL ) |
|
continue; |
|
|
|
//If one of the entities is solid, then we can't spawn now |
|
if ( ( pList[i]->GetSolidFlags() & FSOLID_NOT_SOLID ) == false ) |
|
return false; |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: If this had a finite number of children, return true if they've all |
|
// been created. |
|
//----------------------------------------------------------------------------- |
|
bool CNPCMaker::IsDepleted() |
|
{ |
|
if ( (m_spawnflags & SF_NPCMAKER_INF_CHILD) || m_iMaxNumNPCs > 0 ) |
|
return false; |
|
|
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Toggle the spawner's state |
|
//----------------------------------------------------------------------------- |
|
void CNPCMaker::Toggle( void ) |
|
{ |
|
if ( m_bDisabled ) |
|
{ |
|
Enable(); |
|
} |
|
else |
|
{ |
|
Disable(); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Start the spawner |
|
//----------------------------------------------------------------------------- |
|
void CNPCMaker::Enable( void ) |
|
{ |
|
// can't be enabled once depleted |
|
if ( IsDepleted() ) |
|
return; |
|
|
|
m_bDisabled = false; |
|
SetThink ( &CNPCMaker::MakerThink ); |
|
SetNextThink( gpGlobals->curtime ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Stop the spawner |
|
//----------------------------------------------------------------------------- |
|
void CNPCMaker::Disable( void ) |
|
{ |
|
m_bDisabled = true; |
|
SetThink ( NULL ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Input handler that spawns an NPC. |
|
//----------------------------------------------------------------------------- |
|
void CNPCMaker::InputSpawnNPC( inputdata_t &inputdata ) |
|
{ |
|
MakeNPC(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Input hander that starts the spawner |
|
//----------------------------------------------------------------------------- |
|
void CNPCMaker::InputEnable( inputdata_t &inputdata ) |
|
{ |
|
Enable(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Input hander that stops the spawner |
|
//----------------------------------------------------------------------------- |
|
void CNPCMaker::InputDisable( inputdata_t &inputdata ) |
|
{ |
|
Disable(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Input hander that toggles the spawner |
|
//----------------------------------------------------------------------------- |
|
void CNPCMaker::InputToggle( inputdata_t &inputdata ) |
|
{ |
|
Toggle(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Precache the target NPC |
|
//----------------------------------------------------------------------------- |
|
void CNPCMaker::Precache( void ) |
|
{ |
|
BaseClass::Precache(); |
|
UTIL_PrecacheOther( STRING( m_iszNPCClassname ) ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Creates the NPC. |
|
//----------------------------------------------------------------------------- |
|
void CNPCMaker::MakeNPC( void ) |
|
{ |
|
if (!CanMakeNPC()) |
|
{ |
|
return; |
|
} |
|
|
|
CBaseEntity *pent = (CBaseEntity*)CreateEntityByName( STRING(m_iszNPCClassname) ); |
|
|
|
if ( !pent ) |
|
{ |
|
Warning("NULL Ent in NPCMaker!\n" ); |
|
return; |
|
} |
|
|
|
m_OnSpawnNPC.FireOutput( this, this ); |
|
|
|
pent->SetLocalOrigin( GetAbsOrigin() ); |
|
pent->SetLocalAngles( GetAbsAngles() ); |
|
|
|
pent->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); |
|
|
|
if ( m_spawnflags & SF_NPCMAKER_FADE ) |
|
{ |
|
pent->AddSpawnFlags( SF_NPC_FADE_CORPSE ); |
|
} |
|
|
|
|
|
DispatchSpawn( pent ); |
|
pent->SetOwnerEntity( this ); |
|
|
|
m_cLiveChildren++;// count this NPC |
|
|
|
if (!(m_spawnflags & SF_NPCMAKER_INF_CHILD)) |
|
{ |
|
m_iMaxNumNPCs--; |
|
|
|
if ( IsDepleted() ) |
|
{ |
|
// Disable this forever. Don't kill it because it still gets death notices |
|
SetThink( NULL ); |
|
SetUse( NULL ); |
|
} |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Creates a new NPC every so often. |
|
//----------------------------------------------------------------------------- |
|
void CNPCMaker::MakerThink ( void ) |
|
{ |
|
SetNextThink( gpGlobals->curtime + m_flSpawnFrequency ); |
|
|
|
MakeNPC(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *pVictim - |
|
//----------------------------------------------------------------------------- |
|
void CNPCMaker::DeathNotice( CBaseEntity *pVictim ) |
|
{ |
|
// ok, we've gotten the deathnotice from our child, now clear out its owner if we don't want it to fade. |
|
m_cLiveChildren--; |
|
}
|
|
|