Fixed wrong classname for Voltigore and Baby Voltigore.
Fixed unknown classnames showing as '}'. Remove monster respawn. Add 'monstermaker' entity.
This commit is contained in:
@@ -601,7 +601,6 @@ template <class T> 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
|
||||
|
||||
35
src/dlls/cmbaseextra.h
Normal file
35
src/dlls/cmbaseextra.h
Normal file
@@ -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
|
||||
@@ -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 ) )
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
// 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,7 +909,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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1295,7 +1290,8 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
241
src/dlls/monstermaker.cpp
Normal file
241
src/dlls/monstermaker.cpp
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user