diff --git a/src/dlls/cmbase.h b/src/dlls/cmbase.h index cf750bc..6f5d1f0 100644 --- a/src/dlls/cmbase.h +++ b/src/dlls/cmbase.h @@ -601,7 +601,6 @@ template T * CreateClassPtr( T *a ) // store the class pointer in the array here!!! monsters[monster_index].monster_index = edict_index; monsters[monster_index].monster_pent = temp_edict; - monsters[monster_index].respawn_index = -1; monsters[monster_index].pMonster = (CMBaseMonster *)a; // get the private data diff --git a/src/dlls/cmbaseextra.h b/src/dlls/cmbaseextra.h new file mode 100644 index 0000000..cb8e9c7 --- /dev/null +++ b/src/dlls/cmbaseextra.h @@ -0,0 +1,35 @@ +#ifndef BASEEXTRA_H +#define BASEEXTRA_H + +// any extra entities created in this project that aren't +// monsters will go here + +//========================================================= +// MonsterMaker - this ent creates monsters during the game. +//========================================================= +class CMMonsterMaker : public CMBaseMonster +{ +public: + void Spawn( void ); + void Precache( void ); + void KeyValue( KeyValueData* pkvd); + void EXPORT ToggleUse ( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value ); + void EXPORT CyclicUse ( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value ); + void EXPORT MakerThink ( void ); + void DeathNotice ( entvars_t *pevChild );// monster maker children use this to tell the monster maker that they have died. + void MakeMonster( void ); + + int m_iMonsterIndex;// index of the monster(s) that will be created. + + int m_cNumMonsters;// max number of monsters this ent can create + int m_iMaxLiveChildren;// max number of monsters that this maker may have out at one time. + + int m_cLiveChildren;// how many monsters made by this monster maker that are currently alive + + float m_flGround; // z coord of the ground under me, used to make sure no monsters are under the maker when it drops a new child + + BOOL m_fActive; + BOOL m_fFadeChildren;// should we make the children fadeout? +}; + +#endif // BASEEXTRA_H diff --git a/src/dlls/combat.cpp b/src/dlls/combat.cpp index cec3f03..0c6080e 100644 --- a/src/dlls/combat.cpp +++ b/src/dlls/combat.cpp @@ -580,7 +580,7 @@ void CMBaseMonster::CallGibMonster( void ) if (pev->health < -99) { pev->health = 0; - pev->fuser4 = pev->health; + pev->fuser4 = pev->health; } if ( ShouldFadeOnDeath() && !fade ) @@ -618,14 +618,11 @@ void CMBaseMonster :: Killed( entvars_t *pevAttacker, int iGib ) SetConditions( bits_COND_LIGHT_DAMAGE ); // tell owner ( if any ) that we're dead.This is mostly for MonsterMaker functionality. -/*jlb monstermaker CMBaseEntity *pOwner = CMBaseEntity::Instance(pev->owner); if ( pOwner ) { -//jlb it crashes here sometimes!!! pOwner->DeathNotice( pev ); } -jlb*/ if ( ShouldGibMonster( iGib ) ) { @@ -642,7 +639,7 @@ jlb*/ if (pev->health < -99) { pev->health = 0; - pev->fuser4 = pev->health; + pev->fuser4 = pev->health; } //pev->enemy = ENT( pevAttacker );//why? (sjb) @@ -894,8 +891,8 @@ int CMBaseMonster :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker // do the damage pev->health -= flTake; - if (pev->flags & FL_MONSTER) - pev->fuser4 = pev->health; + if (pev->flags & FL_MONSTER) + pev->fuser4 = pev->health; // HACKHACK Don't kill monsters in a script. Let them break their scripts first if ( m_MonsterState == MONSTERSTATE_SCRIPT ) @@ -1005,13 +1002,13 @@ int CMBaseMonster :: DeadTakeDamage( entvars_t *pevInflictor, entvars_t *pevAtta if ( pev->health <= flDamage ) { pev->health = -50; - pev->fuser4 = pev->health; + pev->fuser4 = pev->health; Killed( pevAttacker, GIB_ALWAYS ); return 0; } // Accumulate corpse gibbing damage, so you can gib with multiple hits pev->health -= flDamage * 0.1; - pev->fuser4 = pev->health; + pev->fuser4 = pev->health; } return 1; diff --git a/src/dlls/dllapi.cpp b/src/dlls/dllapi.cpp index 4bfb70c..f8b75ea 100644 --- a/src/dlls/dllapi.cpp +++ b/src/dlls/dllapi.cpp @@ -42,6 +42,7 @@ #include "cmbase.h" #include "cmbasemonster.h" +#include "cmbaseextra.h" #include "monsters.h" #include "weapons.h" #include "hornet.h" @@ -158,14 +159,15 @@ monster_type_t monster_types[]= "monster_pitdrone", FALSE, "monster_shockroach", FALSE, "monster_shocktrooper", FALSE, - "monster_voltigore", FALSE, - "monster_baby_voltigore", FALSE, + "monster_alien_voltigore", FALSE, + "monster_alien_babyvoltigore", FALSE, "monster_babygarg", FALSE, // Sven Co-op Monsters "monster_hwgrunt", FALSE, "monster_robogrunt", FALSE, "monster_stukabat", FALSE, "info_node", FALSE, // Nodes "info_node_air", FALSE, + "monstermaker", FALSE, // Extra entities "", FALSE }; @@ -209,15 +211,6 @@ int GetMonsterIndex(void) void FreeMonsterIndex(int index) { - int idx = monsters[index].respawn_index; - - if (idx != -1) - { - monster_spawnpoint[idx].need_to_respawn = TRUE; - monster_spawnpoint[idx].respawn_time = gpGlobals->time + - monster_spawnpoint[idx].delay; - } - delete monsters[index].pMonster; monsters[index].monster_index = 0; @@ -557,7 +550,7 @@ void check_monster_info( edict_t *pPlayer ) } } -bool spawn_monster(int monster_type, Vector origin, Vector angles, int respawn_index, int spawnflags, pKVD *keyvalue) +edict_t* spawn_monster(int monster_type, Vector origin, Vector angles, int spawnflags, pKVD *keyvalue) { int monster_index; edict_t *monster_pent; @@ -567,7 +560,7 @@ bool spawn_monster(int monster_type, Vector origin, Vector angles, int respawn_i { //META_CONS("[MONSTER] ERROR: No FREE Monster edicts!"); LOG_MESSAGE(PLID, "ERROR: No FREE Monster edicts!"); - return TRUE; + return NULL; } // was this monster NOT precached? @@ -601,11 +594,12 @@ bool spawn_monster(int monster_type, Vector origin, Vector angles, int respawn_i LOG_MESSAGE(PLID, "%s", msg); } - return TRUE; + return NULL; } switch (monster_type) { + // Monsters case 0: monsters[monster_index].pMonster = CreateClassPtr((CMAGrunt *)NULL); break; case 1: monsters[monster_index].pMonster = CreateClassPtr((CMApache *)NULL); break; case 2: monsters[monster_index].pMonster = CreateClassPtr((CMBarney *)NULL); break; @@ -636,17 +630,17 @@ bool spawn_monster(int monster_type, Vector origin, Vector angles, int respawn_i case 27: monsters[monster_index].pMonster = CreateClassPtr((CMHWGrunt *)NULL); break; case 28: monsters[monster_index].pMonster = CreateClassPtr((CMRGrunt *)NULL); break; case 29: monsters[monster_index].pMonster = CreateClassPtr((CMStukabat *)NULL); break; + // Extra entities + case 32: monsters[monster_index].pMonster = CreateClassPtr((CMMonsterMaker *)NULL); break; } if (monsters[monster_index].pMonster == NULL) { //META_CONS("[MONSTER] ERROR: Error Creating Monster!" ); LOG_MESSAGE(PLID, "ERROR: Error Creating Monster!"); - return TRUE; + return NULL; } - monsters[monster_index].respawn_index = respawn_index; - monster_pent = ENT(monsters[monster_index].pMonster->pev); monsters[monster_index].monster_pent = monster_pent; @@ -673,15 +667,19 @@ bool spawn_monster(int monster_type, Vector origin, Vector angles, int respawn_i monsters[monster_index].pMonster->Spawn(); - // Reverse fadecorpse behaviour - if ( ( spawnflags & SF_MONSTER_FADECORPSE ) ) - monster_pent->v.spawnflags &= ~SF_MONSTER_FADECORPSE; - else - monster_pent->v.spawnflags |= SF_MONSTER_FADECORPSE; - + // Only modify starting spawnflags for monsters, not for entities! + if ( monster_index <= 29 ) + { + // Reverse fadecorpse behaviour + if ( ( spawnflags & SF_MONSTER_FADECORPSE ) ) + monster_pent->v.spawnflags &= ~SF_MONSTER_FADECORPSE; + else + monster_pent->v.spawnflags |= SF_MONSTER_FADECORPSE; + } + monster_pent->v.fuser4 = monster_pent->v.health; // save the original health - return FALSE; + return monster_pent; } @@ -698,8 +696,7 @@ void check_respawn(void) for (int index=0; index < monster_spawn_count; index++) { - if (monster_spawnpoint[index].need_to_respawn && - (monster_spawnpoint[index].respawn_time <= gpGlobals->time)) + if (monster_spawnpoint[index].need_to_respawn) { monster_spawnpoint[index].need_to_respawn = FALSE; @@ -713,12 +710,10 @@ void check_respawn(void) keyvalue = monster_spawnpoint[index].keyvalue; - if (spawn_monster(monster_type, origin, angles, index, spawnflags, keyvalue)) + if (spawn_monster(monster_type, origin, angles, spawnflags, keyvalue) == NULL) { - // spawn_monster failed, retry again after delay... - monster_spawnpoint[index].need_to_respawn = TRUE; - monster_spawnpoint[index].respawn_time = gpGlobals->time + - monster_spawnpoint[index].delay; + // spawn_monster failed + ALERT( at_error, "Failed to spawn %s at origin %f %f %f\n", monster_types[monster_type].name, origin.x, origin.y, origin.z ); } } } @@ -886,7 +881,7 @@ void MonsterCommand(void) if (monster_angle.y < 0) monster_angle.y += 360; - spawn_monster(monster_type, v_src, monster_angle, -1, spawnflags, NULL); + spawn_monster(monster_type, v_src, monster_angle, spawnflags, NULL); return; } @@ -914,9 +909,9 @@ void MonsterCommand(void) if (monster_angle.y < 0) monster_angle.y += 360; - spawn_monster(monster_type, v_src, monster_angle, -1, spawnflags, NULL); + spawn_monster(monster_type, v_src, monster_angle, spawnflags, NULL); - return; + return; } } @@ -942,7 +937,7 @@ void MonsterCommand(void) if (monster_angle.y < 0) monster_angle.y += 360; - spawn_monster(monster_type, v_src, monster_angle, -1, spawnflags, NULL); + spawn_monster(monster_type, v_src, monster_angle, spawnflags, NULL); return; } @@ -969,7 +964,7 @@ void MonsterCommand(void) if (monster_angle.y < 0) monster_angle.y += 360; - spawn_monster(monster_type, v_src, monster_angle, -1, spawnflags, NULL); + spawn_monster(monster_type, v_src, monster_angle, spawnflags, NULL); return; } @@ -996,7 +991,7 @@ void MonsterCommand(void) if (monster_angle.y < 0) monster_angle.y += 360; - spawn_monster(monster_type, v_src, monster_angle, -1, spawnflags, NULL); + spawn_monster(monster_type, v_src, monster_angle, spawnflags, NULL); return; } @@ -1023,7 +1018,7 @@ void MonsterCommand(void) if (monster_angle.y < 0) monster_angle.y += 360; - spawn_monster(monster_type, v_src, monster_angle, -1, spawnflags, NULL); + spawn_monster(monster_type, v_src, monster_angle, spawnflags, NULL); return; } @@ -1294,8 +1289,9 @@ void mmDispatchTouch( edict_t *pentTouched, edict_t *pentOther ) void mmServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) { int index; - - CMAGrunt agrunt; + + // Monsters + CMAGrunt agrunt; // 0 CMApache apache; CMBarney barney; CMBigMomma bigmomma; @@ -1324,7 +1320,10 @@ void mmServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) CMBabyGargantua babygargantua; CMHWGrunt hwgrunt; CMRGrunt rgrunt; - CMStukabat stukabat; + CMStukabat stukabat; // 29 + + // Extra entities + CMMonsterMaker monstermaker; // 32 g_psv_gravity = CVAR_GET_POINTER( "sv_gravity" ); @@ -1372,6 +1371,7 @@ void mmServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) case 27: hwgrunt.Precache(); break; case 28: rgrunt.Precache(); break; case 29: stukabat.Precache(); break; + case 32: monstermaker.Precache(); break; } } } diff --git a/src/dlls/monster_config.cpp b/src/dlls/monster_config.cpp index c890049..21875af 100644 --- a/src/dlls/monster_config.cpp +++ b/src/dlls/monster_config.cpp @@ -94,7 +94,7 @@ void scan_monster_cfg(FILE *fp) // Now that I think about it this looks slow and bad code >.> // A match is found. What is this? - if (strncmp(monster_types[mIndex].name, "monster", 7) == 0) + if (strncmp(monster_types[mIndex].name, "monster_", 8) == 0) { // It's a monster, add it to the list if (monster_spawn_count == MAX_MONSTERS) @@ -110,6 +110,22 @@ void scan_monster_cfg(FILE *fp) monster = TRUE; } } + else if (strcmp(monster_types[mIndex].name, "monstermaker") == 0) + { + // A monster spawner, add it to the list + if (monster_spawn_count == MAX_MONSTERS) + { + // error.exe + LOG_MESSAGE(PLID, "ERROR: can't add monstermaker, reached MAX_MONSTERS!"); + badent = TRUE; + } + else + { + monster_spawnpoint[monster_spawn_count].monster = mIndex; + monster_types[mIndex].need_to_precache = TRUE; + monster = TRUE; + } + } else if (strcmp(monster_types[mIndex].name, "info_node") == 0) { // Normal node @@ -142,7 +158,7 @@ void scan_monster_cfg(FILE *fp) } if (monster_types[mIndex].name[0] == 0) { - LOG_MESSAGE(PLID, "ERROR: unknown classname: %s", input); // print conflictive line + LOG_MESSAGE(PLID, "ERROR: unknown classname: %s", data[kvd_index-1].value); // print conflictive line LOG_MESSAGE(PLID, "ERROR: nothing will spawn here!"); badent = TRUE; } @@ -150,8 +166,8 @@ void scan_monster_cfg(FILE *fp) else { // What are you doing?! - LOG_MESSAGE(PLID, "ERROR: BAD ENTITY STRUCTURE! Last line was %s", input); // print conflictive line - LOG_MESSAGE(PLID, "ERROR: nothing will spawn here!"); + LOG_MESSAGE(PLID, "ERROR: BAD ENTITY STRUCTURE! Last line was %s", data[kvd_index-1].key); // print conflictive line + LOG_MESSAGE(PLID, "ERROR: classname MUST be the last entry of the entity!" ); badent = TRUE; } @@ -192,23 +208,6 @@ void scan_monster_cfg(FILE *fp) node_spawnpoint[node_spawn_count].origin[2] = z; } } - else if (strcmp(data[i].key, "delay") == 0) - { - // ToDo: Remove this keyvalue. - // Monsters spawned directly should not respawn. - if (monster) - { - if (sscanf(data[i].value, "%f", &x) != 1) - { - LOG_MESSAGE(PLID, "ERROR: invalid delay: %s", input); // print conflictive line - - // default to 30 seconds - LOG_MESSAGE(PLID, "ERROR: entity respawn frequency will be set to 30 seconds"); - x = 30; - } - monster_spawnpoint[monster_spawn_count].delay = x; - } - } else if (strcmp(data[i].key, "angles") == 0) { if (monster) @@ -241,6 +240,30 @@ void scan_monster_cfg(FILE *fp) monster_spawnpoint[monster_spawn_count].spawnflags = x; } } + else if (strcmp(data[i].key, "monstertype") == 0) + { + if (monster) + { + // this keyvalue is only valid for monstermaker entity + if (strcmp(data[kvd_index-1].value, "monstermaker") == 0) + { + // process the entity precache here + int mIndex; + for (mIndex = 0; monster_types[mIndex].name[0]; mIndex++) + { + if (strcmp(data[i].value, monster_types[mIndex].name) == 0) + { + monster_types[mIndex].need_to_precache = TRUE; + break; // only one monster at a time + } + } + + // pass the keyvalue to the entity + strcpy(monster_spawnpoint[monster_spawn_count].keyvalue[i].key, data[i].key); + strcpy(monster_spawnpoint[monster_spawn_count].keyvalue[i].value, data[i].value); + } + } + } else { // We do not know this keyvalue, but an specific entity might use it. @@ -255,8 +278,7 @@ void scan_monster_cfg(FILE *fp) if (monster) { - // Init monster - monster_spawnpoint[monster_spawn_count].respawn_time = gpGlobals->time + 0.1; // spawn (nearly) right away + // Spawn right away monster_spawnpoint[monster_spawn_count].need_to_respawn = TRUE; monster_spawn_count++; } diff --git a/src/dlls/monster_mm.dsp b/src/dlls/monster_mm.dsp index 9c3462e..1432f8f 100644 --- a/src/dlls/monster_mm.dsp +++ b/src/dlls/monster_mm.dsp @@ -218,6 +218,10 @@ SOURCE=.\monster_config.cpp # End Source File # Begin Source File +SOURCE=.\monstermaker.cpp +# End Source File +# Begin Source File + SOURCE=.\monsters.cpp # End Source File # Begin Source File @@ -330,6 +334,10 @@ SOURCE=.\cmbase.h # End Source File # Begin Source File +SOURCE=.\cmbaseextra.h +# End Source File +# Begin Source File + SOURCE=.\cmbasemonster.h # End Source File # Begin Source File diff --git a/src/dlls/monster_plugin.h b/src/dlls/monster_plugin.h index 030cbfa..0162f02 100644 --- a/src/dlls/monster_plugin.h +++ b/src/dlls/monster_plugin.h @@ -27,7 +27,6 @@ typedef struct int monster_index; edict_t *monster_pent; bool killed; - int respawn_index; CMBaseMonster *pMonster; } monster_t; @@ -38,11 +37,9 @@ extern monster_t monsters[MAX_MONSTER_ENTS]; typedef struct { Vector origin; Vector angles; - float delay; unsigned char monster; int spawnflags; pKVD *keyvalue; - float respawn_time; bool need_to_respawn; } monster_spawnpoint_t; diff --git a/src/dlls/monstermaker.cpp b/src/dlls/monstermaker.cpp new file mode 100644 index 0000000..1d707c5 --- /dev/null +++ b/src/dlls/monstermaker.cpp @@ -0,0 +1,241 @@ +/*** +* +* Copyright (c) 1996-2001, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +//========================================================= +// Monster Maker - this is an entity that creates monsters +// in the game. +//========================================================= + +#include "extdll.h" +#include "util.h" +#include "cmbase.h" +#include "cmbasemonster.h" +#include "cmbaseextra.h" +#include "monsters.h" + +// Monstermaker spawnflags +#define SF_MONSTERMAKER_START_ON 1 // start active ( if has targetname ) +#define SF_MONSTERMAKER_CYCLIC 4 // drop one monster every time fired. +#define SF_MONSTERMAKER_MONSTERCLIP 8 // Children are blocked by monsterclip + +extern monster_type_t monster_types[]; +extern edict_t* spawn_monster(int monster_type, Vector origin, Vector angles, int spawnflags, pKVD *keyvalue); + + +// ======================================================== +void CMMonsterMaker :: KeyValue( KeyValueData *pkvd ) +{ + if ( FStrEq(pkvd->szKeyName, "monstercount") ) + { + m_cNumMonsters = atoi(pkvd->szValue); + pkvd->fHandled = TRUE; + } + else if ( FStrEq(pkvd->szKeyName, "m_imaxlivechildren") ) + { + m_iMaxLiveChildren = atoi(pkvd->szValue); + pkvd->fHandled = TRUE; + } + else if ( FStrEq(pkvd->szKeyName, "monstertype") ) + { + // Process monster_index + int mIndex; + for (mIndex = 0; monster_types[mIndex].name[0]; mIndex++) + { + if (strcmp(pkvd->szValue, monster_types[mIndex].name) == 0) + { + m_iMonsterIndex = mIndex; + break; // grab the first entry we find + } + } + pkvd->fHandled = TRUE; + } + else + CMBaseMonster::KeyValue( pkvd ); +} + + +void CMMonsterMaker :: Spawn( ) +{ + pev->solid = SOLID_NOT; + + m_cLiveChildren = 0; + Precache(); + if ( !FStringNull ( pev->targetname ) ) + { + if ( pev->spawnflags & SF_MONSTERMAKER_CYCLIC ) + { + SetUse ( &CMMonsterMaker::CyclicUse );// drop one monster each time we fire + } + else + { + SetUse ( &CMMonsterMaker::ToggleUse );// so can be turned on/off + } + + if ( FBitSet ( pev->spawnflags, SF_MONSTERMAKER_START_ON ) ) + {// start making monsters as soon as monstermaker spawns + m_fActive = TRUE; + SetThink ( &CMMonsterMaker::MakerThink ); + } + else + {// wait to be activated. + m_fActive = FALSE; + SetThink ( &CMMonsterMaker::SUB_DoNothing ); + } + } + else + {// no targetname, just start. + pev->nextthink = gpGlobals->time + m_flDelay; + m_fActive = TRUE; + SetThink ( &CMMonsterMaker::MakerThink ); + } + + // always fade + m_fFadeChildren = TRUE; + + m_flGround = 0; +} + +void CMMonsterMaker :: Precache( void ) +{ + CMBaseMonster::Precache(); + // choosen monster is auto-precached +} + +//========================================================= +// MakeMonster- this is the code that drops the monster +//========================================================= +void CMMonsterMaker::MakeMonster( void ) +{ + edict_t *pent; + int createSF = SF_MONSTER_FALL_TO_GROUND; + + if ( m_iMaxLiveChildren > 0 && m_cLiveChildren >= m_iMaxLiveChildren ) + {// not allowed to make a new one yet. Too many live ones out right now. + return; + } + + if ( !m_flGround ) + { + // set altitude. Now that I'm activated, any breakables, etc should be out from under me. + TraceResult tr; + + UTIL_TraceLine ( pev->origin, pev->origin - Vector ( 0, 0, 2048 ), ignore_monsters, ENT(pev), &tr ); + m_flGround = tr.vecEndPos.z; + } + + Vector mins = pev->origin - Vector( 34, 34, 0 ); + Vector maxs = pev->origin + Vector( 34, 34, 0 ); + maxs.z = pev->origin.z; + mins.z = m_flGround; + + edict_t *pList[2]; + int count = UTIL_EntitiesInBox( pList, 2, mins, maxs, FL_CLIENT|FL_MONSTER ); + if ( count ) + { + // don't build a stack of monsters! + return; + } + + // Should children hit monsterclip brushes? + if ( pev->spawnflags & SF_MONSTERMAKER_MONSTERCLIP ) + createSF |= SF_MONSTER_HITMONSTERCLIP; + + // Attempt to spawn monster + pent = spawn_monster(m_iMonsterIndex, pev->origin, pev->angles, createSF, NULL); + if ( pent == NULL ) + { + ALERT ( at_console, "NULL Ent in MonsterMaker!\n" ); + return; + } + + // If I have a target, fire! + if ( !FStringNull ( pev->target ) ) + { + // delay already overloaded for this entity, so can't call SUB_UseTargets() + FireTargets( STRING(pev->target), this->edict(), this->edict(), USE_TOGGLE, 0 ); + } + + pent->v.owner = edict(); + + if ( !FStringNull( pev->netname ) ) + { + // if I have a netname (overloaded), give the child monster that name as a targetname + pent->v.targetname = pev->netname; + } + + m_cLiveChildren++;// count this monster + m_cNumMonsters--; + + if ( m_cNumMonsters == 0 ) + { + // Disable this forever. Don't kill it because it still gets death notices + SetThink( NULL ); + SetUse( NULL ); + } +} + +//========================================================= +// CyclicUse - drops one monster from the monstermaker +// each time we call this. +//========================================================= +void CMMonsterMaker::CyclicUse ( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value ) +{ + MakeMonster(); +} + +//========================================================= +// ToggleUse - activates/deactivates the monster maker +//========================================================= +void CMMonsterMaker :: ToggleUse ( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value ) +{ + if ( !ShouldToggle( useType, m_fActive ) ) + return; + + if ( m_fActive ) + { + m_fActive = FALSE; + SetThink ( NULL ); + } + else + { + m_fActive = TRUE; + SetThink ( &CMMonsterMaker::MakerThink ); + } + + pev->nextthink = gpGlobals->time; +} + +//========================================================= +// MakerThink - creates a new monster every so often +//========================================================= +void CMMonsterMaker :: MakerThink ( void ) +{ + pev->nextthink = gpGlobals->time + m_flDelay; + + MakeMonster(); +} + + +//========================================================= +//========================================================= +void CMMonsterMaker :: DeathNotice ( entvars_t *pevChild ) +{ + // ok, we've gotten the deathnotice from our child, now clear out its owner if we don't want it to fade. + m_cLiveChildren--; + + if ( !m_fFadeChildren ) + { + pevChild->owner = NULL; + } +} diff --git a/src/dlls/voltigore.cpp b/src/dlls/voltigore.cpp index c7459c9..cf8ed6c 100644 --- a/src/dlls/voltigore.cpp +++ b/src/dlls/voltigore.cpp @@ -33,9 +33,6 @@ #define VOLTIGORE_MAX_BEAMS 8 -#define VOLTIGORE_CLASSNAME "monster_alien_voltigore" -#define VOLTIGORE_BABY_CLASSNAME "monster_alien_babyvoltigore" - #define VOLTIGORE_ZAP_RED 180 #define VOLTIGORE_ZAP_GREEN 16 #define VOLTIGORE_ZAP_BLUE 255