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.
295 lines
7.7 KiB
295 lines
7.7 KiB
5 years ago
|
//========= 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--;
|
||
|
}
|