17 Commits

Author SHA1 Message Date
Giegue
0f2bd95275 Merge pull request #1 from JulianR0/tier2
Tier 2 milestone reached!
2020-06-03 14:38:21 -03:00
Giegue
be8df87e82 Merge branch 'master' into tier2 2020-06-03 14:37:16 -03:00
Julian
aa99d801c7 Merge branch 'tier2' of github.com:JulianR0/monstermod-redo into tier2 2020-06-03 14:32:37 -03:00
Julian
aa57599c3c Tier 2 milestone reached! 2020-06-03 14:31:55 -03:00
Julian
b2beda8f68 Tier 2 milestone reached! 2020-06-03 14:28:58 -03:00
Julian
6d4a608793 Add "classify" keyvalue to override monster classification. 2020-06-03 13:57:06 -03:00
Giegue
612ce63050 Update README.md 2020-06-03 01:42:33 -03:00
Julian
1e68434df5 Add "displayname" keyvalue for custom monster names. 2020-06-03 01:36:04 -03:00
Julian
4d61695e6b Merge branch 'tier2' of github.com:JulianR0/monstermod-redo into tier2 2020-06-02 01:56:04 -03:00
Julian
4912f6d23d Display basic monster info on aiment. 2020-06-02 01:54:48 -03:00
Giegue
50fd9aa13a Update README.md 2020-06-01 17:20:23 -03:00
Giegue
d72aba3b6f Update README.md 2020-06-01 17:18:06 -03:00
Julian
d39bc85ab6 Use monster classname for player deaths. 2020-06-01 17:10:52 -03:00
Julian
5c275e5b62 Added death messages. 2020-06-01 03:53:42 -03:00
Julian
b4ec347170 Fixed TextMsg message crashes. 2020-06-01 03:53:12 -03:00
Julian
8f899d2c6d Add install instructions. 2020-03-17 22:48:56 -03:00
Giegue
d63e0af548 Tier 1 milestone reached! 2020-03-17 22:41:10 -03:00
29 changed files with 1126 additions and 89 deletions

View File

@@ -53,13 +53,13 @@ Current milestones are separated by "Tiers", which are as follows:
- Rework config processing to use a "key --> value" format. **[DONE]** - Rework config processing to use a "key --> value" format. **[DONE]**
- Add info_node and info_node_air support for AI navigation. **[DONE]** - Add info_node and info_node_air support for AI navigation. **[DONE]**
- Add node_viewer to debug node graph generation. **[DONE]** - Add node_viewer to debug node graph generation. **[DONE]**
- Implement Gargantua and all Turrets from Half-Life. - Implement Gargantua and all Turrets from Half-Life. **[DONE]**
### Tier 2 ### Tier 2
- Add *-at least minimal-* death messages. *-Example: "\<player\> was killed by a \<monster\>".-* - Add *-at least minimal-* death messages. *-Example: "\<player\> was killed by a \<monster\>".-* **[DONE]**
- Implement HUD info about the monsters, along with the "displayname" keyvalue. - Implement HUD info about the monsters, along with the "displayname" keyvalue. **[DONE]**
- Implement custom monster classification, the "classify" keyvalue. - Implement custom monster classification, the "classify" keyvalue. **[DONE]**
### Tier 3 ### Tier 3

View File

@@ -5,10 +5,31 @@
// To add entries to this file, just pretend it's ripent. // To add entries to this file, just pretend it's ripent.
// //
// "delay" means monster respawndelay. // "delay" means monster respawndelay.
//
// You may also be interesed in these other 2 keyvalues:
//
// "displayname" to change the monster's name, shown in HUD when you point at it.
// "classify" to change the monster's default classification, use one of these values:
//
// CLASS_NONE 0
// CLASS_MACHINE 1
// CLASS_PLAYER 2
// CLASS_HUMAN_PASSIVE 3
// CLASS_HUMAN_MILITARY 4
// CLASS_ALIEN_MILITARY 5
// CLASS_ALIEN_PASSIVE 6
// CLASS_ALIEN_MONSTER 7
// CLASS_ALIEN_PREY 8
// CLASS_ALIEN_PREDATOR 9
// CLASS_INSECT 10
// CLASS_PLAYER_ALLY 11
// CLASS_PLAYER_BIOWEAPON 12
// CLASS_ALIEN_BIOWEAPON 13
{ {
"origin" "90 -180 150" "origin" "90 -180 150"
"delay" "30" "delay" "30"
"displayname" "Example Custom Name"
"orientation" "1" "orientation" "1"
"spawnflags" "32" "spawnflags" "32"
"classname" "monster_miniturret" "classname" "monster_miniturret"
@@ -16,6 +37,7 @@
{ {
"origin" "123 456 789" "origin" "123 456 789"
"delay" "5" "delay" "5"
"classify" "7"
"angles" "0 45 0" "angles" "0 45 0"
"classname" "monster_houndeye" "classname" "monster_houndeye"
} }

View File

@@ -1,6 +1,8 @@
// //
// MONSTERS - monsters that you always want to precache (for dynamic spawning) // MONSTERS - monsters that you always want to precache (for dynamic spawning)
// //
// Install this file to your mod's base directory.
//
// (just remove the comment characters at the beginning of the line for the // (just remove the comment characters at the beginning of the line for the
// monsters that you always want to precache.) // monsters that you always want to precache.)
@@ -10,12 +12,11 @@
//monster_bigmomma //monster_bigmomma
//monster_bullsquid //monster_bullsquid
//monster_gargantua //monster_gargantua
//monster_hassassin //monster_human_assassin
//monster_headcrab //monster_headcrab
//monster_human_grunt //monster_human_grunt
//monster_houndeye //monster_houndeye
//monster_alien_slave //monster_alien_slave
//monster_icthyosaur
//monster_alien_controller //monster_alien_controller
//monster_scientist //monster_scientist
//monster_snark //monster_snark

View File

@@ -1,6 +1,6 @@
// MONSTERS health and damage amounts // MONSTERS health and damage amounts
// //
// (Note: Some of these aren't currently used. They're in here for future use.) // Install this file to your mod's base directory.
// Alien Grunt // Alien Grunt
sk_agrunt_health 90 sk_agrunt_health 90

View File

@@ -125,11 +125,14 @@ const char *CMAGrunt::pAlertSounds[] =
//========================================================= //=========================================================
int CMAGrunt::IRelationship ( CMBaseEntity *pTarget ) int CMAGrunt::IRelationship ( CMBaseEntity *pTarget )
{ {
// ditto hgrunt.cpp
/*
if ( strcmp(STRING(pTarget->pev->model), "models/hgrunt.mdl") == 0 ) if ( strcmp(STRING(pTarget->pev->model), "models/hgrunt.mdl") == 0 )
{ {
return R_NM; return R_NM;
} }
*/
return CMBaseMonster :: IRelationship( pTarget ); return CMBaseMonster :: IRelationship( pTarget );
} }
@@ -313,6 +316,11 @@ void CMAGrunt :: PainSound ( void )
//========================================================= //=========================================================
int CMAGrunt :: Classify ( void ) int CMAGrunt :: Classify ( void )
{ {
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MILITARY; return CLASS_ALIEN_MILITARY;
} }
@@ -541,6 +549,13 @@ void CMAGrunt :: Spawn()
m_flNextSpeakTime = m_flNextWordTime = gpGlobals->time + 10 + RANDOM_LONG(0, 10); m_flNextSpeakTime = m_flNextWordTime = gpGlobals->time + 10 + RANDOM_LONG(0, 10);
MonsterInit(); MonsterInit();
pev->classname = MAKE_STRING( "monster_alien_grunt" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Alien Grunt" );
}
} }
//========================================================= //=========================================================

View File

@@ -84,6 +84,13 @@ void CMApache :: Spawn( void )
m_flPrevSeen = 0.0f; m_flPrevSeen = 0.0f;
m_iSoundState = 0; m_iSoundState = 0;
pev->classname = MAKE_STRING( "monster_apache" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Apache" );
}
} }
@@ -111,7 +118,15 @@ void CMApache::Precache( void )
apache_rocket.Precache(); apache_rocket.Precache();
} }
int CMApache :: Classify ( void )
{
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_HUMAN_MILITARY;
}
void CMApache::NullThink( void ) void CMApache::NullThink( void )
{ {
@@ -974,4 +989,4 @@ void CMApacheHVR :: AccelerateThink( void )
} }
#endif #endif

View File

@@ -186,6 +186,11 @@ int CMBarney :: ISoundMask ( void)
//========================================================= //=========================================================
int CMBarney :: Classify ( void ) int CMBarney :: Classify ( void )
{ {
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_PLAYER_ALLY; return CLASS_PLAYER_ALLY;
} }
@@ -357,6 +362,13 @@ void CMBarney :: Spawn()
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP; m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
MonsterInit(); MonsterInit();
pev->classname = MAKE_STRING( "monster_barney" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Barney" );
}
} }
//========================================================= //=========================================================

View File

@@ -48,6 +48,7 @@ public:
void CMInfoBM::Spawn( void ) void CMInfoBM::Spawn( void )
{ {
pev->classname = MAKE_STRING( "info_bigmomma" );
} }
void CMInfoBM::KeyValue( KeyValueData* pkvd ) void CMInfoBM::KeyValue( KeyValueData* pkvd )
@@ -298,6 +299,11 @@ void CMBigMomma :: KeyValue( KeyValueData *pkvd )
//========================================================= //=========================================================
int CMBigMomma :: Classify ( void ) int CMBigMomma :: Classify ( void )
{ {
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MONSTER; return CLASS_ALIEN_MONSTER;
} }
@@ -610,6 +616,13 @@ void CMBigMomma :: Spawn()
m_MonsterState = MONSTERSTATE_NONE; m_MonsterState = MONSTERSTATE_NONE;
MonsterInit(); MonsterInit();
pev->classname = MAKE_STRING( "monster_bigmomma" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Big Momma" );
}
} }
//========================================================= //=========================================================

View File

@@ -357,6 +357,11 @@ BOOL CMBullsquid :: FValidateHintType ( short sHint )
//========================================================= //=========================================================
int CMBullsquid :: Classify ( void ) int CMBullsquid :: Classify ( void )
{ {
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MONSTER; return CLASS_ALIEN_MONSTER;
} }
@@ -617,6 +622,13 @@ void CMBullsquid :: Spawn()
m_flNextSpitTime = gpGlobals->time; m_flNextSpitTime = gpGlobals->time;
MonsterInit(); MonsterInit();
pev->classname = MAKE_STRING( "monster_bullchicken" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Bullsquid" );
}
} }
//========================================================= //=========================================================

View File

@@ -540,7 +540,6 @@ public:
class CMBaseMonster; class CMBaseMonster;
extern int GetMonsterIndex(void); extern int GetMonsterIndex(void);
// //

View File

@@ -101,7 +101,10 @@ public:
string_t m_iszTriggerTarget;// name of target that should be fired. string_t m_iszTriggerTarget;// name of target that should be fired.
Vector m_HackedGunPos; // HACK until we can query end of gun Vector m_HackedGunPos; // HACK until we can query end of gun
string_t m_szMonsterName; // Monster name to display on HUD
int m_iClassifyOverride; // Overriden classification for this monster
void KeyValue( KeyValueData *pkvd ); void KeyValue( KeyValueData *pkvd );
// monster use function // monster use function
@@ -792,7 +795,7 @@ class CMApache : public CMBaseMonster
public: public:
void Spawn( void ); void Spawn( void );
void Precache( void ); void Precache( void );
int Classify( void ) { return CLASS_HUMAN_MILITARY; }; int Classify( void );
int BloodColor( void ) { return DONT_BLEED; } int BloodColor( void ) { return DONT_BLEED; }
void Killed( entvars_t *pevAttacker, int iGib ); void Killed( entvars_t *pevAttacker, int iGib );
void GibMonster( void ); void GibMonster( void );

View File

@@ -589,7 +589,11 @@ void CMBaseMonster :: Killed( entvars_t *pevAttacker, int iGib )
{ {
unsigned int cCount = 0; unsigned int cCount = 0;
BOOL fDone = FALSE; BOOL fDone = FALSE;
// If a player killed this monster, add score
if ( UTIL_IsPlayer( ENT( pevAttacker ) ) )
pevAttacker->frags += 1.0;
if ( HasMemory( bits_MEMORY_KILLED ) ) if ( HasMemory( bits_MEMORY_KILLED ) )
{ {
if ( ShouldGibMonster( iGib ) ) if ( ShouldGibMonster( iGib ) )
@@ -822,7 +826,7 @@ int CMBaseMonster :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker
{ {
float flTake; float flTake;
Vector vecDir; Vector vecDir;
if (!pev->takedamage) if (!pev->takedamage)
return 0; return 0;

View File

@@ -81,6 +81,11 @@ const char *CMController::pDeathSounds[] =
//========================================================= //=========================================================
int CMController :: Classify ( void ) int CMController :: Classify ( void )
{ {
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MILITARY; return CLASS_ALIEN_MILITARY;
} }
@@ -310,6 +315,13 @@ void CMController :: Spawn()
m_MonsterState = MONSTERSTATE_NONE; m_MonsterState = MONSTERSTATE_NONE;
MonsterInit(); MonsterInit();
pev->classname = MAKE_STRING( "monster_alien_controller" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Alien Controller" );
}
} }
//========================================================= //=========================================================
@@ -1113,6 +1125,8 @@ void CMControllerHeadBall :: Spawn( void )
m_hOwner = pev->owner; m_hOwner = pev->owner;
pev->dmgtime = gpGlobals->time; pev->dmgtime = gpGlobals->time;
pev->classname = MAKE_STRING( "controller_head_ball" );
} }
@@ -1297,9 +1311,10 @@ void CMControllerZapBall :: Spawn( void )
m_hOwner = pev->owner; m_hOwner = pev->owner;
pev->dmgtime = gpGlobals->time; // keep track of when ball spawned pev->dmgtime = gpGlobals->time; // keep track of when ball spawned
pev->nextthink = gpGlobals->time + 0.1; pev->nextthink = gpGlobals->time + 0.1;
pev->classname = MAKE_STRING( "controller_energy_ball" );
} }
void CMControllerZapBall :: Precache( void ) void CMControllerZapBall :: Precache( void )
{ {
PRECACHE_MODEL("sprites/xspark4.spr"); PRECACHE_MODEL("sprites/xspark4.spr");

View File

@@ -58,6 +58,24 @@ extern gamedll_funcs_t *gpGamedllFuncs;
extern cvar_t *dllapi_log; extern cvar_t *dllapi_log;
extern cvar_t *monster_spawn; extern cvar_t *monster_spawn;
extern cvar_t *monster_show_deaths;
extern cvar_t *monster_show_info;
// Player TakeDamage and Killed
int g_DamageMsg;
bool g_DamageActive;
int g_DamageVictim;
edict_t *g_DamageAttacker[33];
int g_DamageBits[33];
bool g_PlayerKilled[33];
float g_flWaitTillMessage[33];
// DeathMsg
int g_DeathMsg;
bool g_DeathActive;
// TE_TEXTMESSAGE
float g_NextMessage[33];
cvar_t *g_psv_gravity = NULL; cvar_t *g_psv_gravity = NULL;
@@ -122,7 +140,7 @@ monster_type_t monster_types[]=
"monster_bigmomma", FALSE, "monster_bigmomma", FALSE,
"monster_bullsquid", FALSE, "monster_bullsquid", FALSE,
"monster_alien_controller", FALSE, "monster_alien_controller", FALSE,
"monster_hassassin", FALSE, "monster_human_assassin", FALSE,
"monster_headcrab", FALSE, "monster_headcrab", FALSE,
"monster_human_grunt", FALSE, "monster_human_grunt", FALSE,
"monster_houndeye", FALSE, "monster_houndeye", FALSE,
@@ -305,7 +323,7 @@ void check_monster_hurt(edict_t *pAttacker)
} }
void check_monster_dead(void) void check_monster_dead(edict_t *pAttacker)
{ {
for (int index = 0; index < monster_ents_used; index++) for (int index = 0; index < monster_ents_used; index++)
{ {
@@ -324,8 +342,9 @@ void check_monster_dead(void)
pent->v.flags &= ~FL_KILLME; // clear FL_KILLME bit pent->v.flags &= ~FL_KILLME; // clear FL_KILLME bit
pent->v.deadflag = DEAD_NO; // bring back to life pent->v.deadflag = DEAD_NO; // bring back to life
monsters[index].pMonster->Killed(VARS(pent), 0); monsters[index].pMonster->Killed(VARS(pAttacker), 0);
monsters[index].killed = TRUE; monsters[index].killed = TRUE;
} }
} }
@@ -344,6 +363,195 @@ void check_monster_dead(void)
} }
void check_player_dead( edict_t *pPlayer )
{
// Death messages are disabled
if (!monster_show_deaths->value)
return;
int iPlayerIndex = ENTINDEX( pPlayer );
// Player died?
if ( !UTIL_IsAlive( pPlayer ) )
{
edict_t *pAttacker = pPlayer->v.dmg_inflictor;
char szMessage[129]; // To allow exactly 128 characters
// Attacker is NULL or message already shown, don't care
if ( pAttacker == NULL || g_PlayerKilled[ iPlayerIndex ] )
return;
// Get player's name
char szPlayerName[33];
sprintf( szPlayerName, "%s", STRING( pPlayer->v.netname ) );
// Killed by a monster?
if ( pAttacker->v.flags & FL_MONSTER )
{
// Check the first character for 'aeiou'.
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pAttacker));
char szCheck[2];
strncpy( szCheck, STRING( pMonster->m_szMonsterName ), 1 );
// Make the first character lowercase
szCheck[0] = tolower( szCheck[ 0 ] );
if ( strncmp( szCheck, "a", 1 ) == 0 || strncmp( szCheck, "e", 1 ) == 0 || strncmp( szCheck, "i", 1 ) == 0 || strncmp( szCheck, "o", 1 ) == 0 || strncmp( szCheck, "u", 1 ) == 0 )
sprintf( szMessage, "* %s was killed by an %s.\n", szPlayerName, STRING( pMonster->m_szMonsterName ) );
else
sprintf( szMessage, "* %s was killed by a %s.\n", szPlayerName, STRING( pMonster->m_szMonsterName ) );
}
else
{
// Any messages from here should only be shown if allowed.
// Level 0 = Disabled
// Level 1 = All messages
// Level 2 = Only monster deaths
if (monster_show_deaths->value == 1)
{
// Suicide?
if ( pAttacker == pPlayer )
sprintf( szMessage, "* %s commited suicide.\n", szPlayerName );
// An entity killed this player.
else if ( ENTINDEX( pAttacker ) > 0 )
{
// Gather damage type and format death message
if ( g_DamageBits[ iPlayerIndex ] == DMG_GENERIC )
sprintf( szMessage, "* %s died mysteriously.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_CRUSH )
sprintf( szMessage, "* %s was smashed.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_BULLET )
sprintf( szMessage, "* %s was shot.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_SLASH )
sprintf( szMessage, "* %s lost it's jelly.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_BURN )
sprintf( szMessage, "* %s burned to death.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_FREEZE )
sprintf( szMessage, "* %s froze to death.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_FALL )
sprintf( szMessage, "* %s broke it's bones.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_BLAST )
sprintf( szMessage, "* %s blew up.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_CLUB )
sprintf( szMessage, "* %s was crowbared.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_SHOCK )
sprintf( szMessage, "* %s was electrocuted.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_SONIC )
sprintf( szMessage, "* %s ears popped.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_ENERGYBEAM )
sprintf( szMessage, "* %s saw the pretty lights.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] == DMG_NEVERGIB )
sprintf( szMessage, "* %s had a painful death.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] == DMG_ALWAYSGIB )
sprintf( szMessage, "* %s was gibbed.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_DROWN )
sprintf( szMessage, "* %s became too drunk.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_PARALYZE )
sprintf( szMessage, "* %s was paralyzed.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_NERVEGAS )
sprintf( szMessage, "* %s lost it's brain.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_POISON )
sprintf( szMessage, "* %s had a slow death.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_RADIATION )
sprintf( szMessage, "* %s went nuclear.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_DROWNRECOVER )
sprintf( szMessage, "* %s used too much flex tape.\n", szPlayerName ); // is this type of death even possible?
else if ( g_DamageBits[ iPlayerIndex ] & DMG_ACID )
sprintf( szMessage, "* %s was melted.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_SLOWBURN )
sprintf( szMessage, "* %s became a cake.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_SLOWFREEZE )
sprintf( szMessage, "* %s died of hypothermia.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] & DMG_MORTAR )
sprintf( szMessage, "* %s blew his missile pet.\n", szPlayerName );
else if ( g_DamageBits[ iPlayerIndex ] == (1 << 30) ) // (1 << 30) = 1073741824. For custom death messages
sprintf( szMessage, "* %s %s.\n", szPlayerName, STRING( pAttacker->v.noise ) );
else // other mods could have more DMG_ variants that aren't registered here.
sprintf( szMessage, "* %s deadly died.\n", szPlayerName );
}
// the "world" killed this player
else
sprintf( szMessage, "* %s fell or drowned or something.\n", szPlayerName );
}
}
// Print the message
if ( strlen( szMessage ) > 0 )
UTIL_ClientPrintAll( HUD_PRINTTALK, szMessage );
g_PlayerKilled[ iPlayerIndex ] = true;
}
else
g_PlayerKilled[ iPlayerIndex ] = false;
}
void check_monster_info( edict_t *pPlayer )
{
// Monster Info is disabled
if (!monster_show_info->value)
return;
// Player must be alive
if ( UTIL_IsAlive( pPlayer ) )
{
// Don't overdo it!
if ( g_NextMessage[ ENTINDEX( pPlayer ) ] > gpGlobals->time )
return;
// Get player position and view angle
Vector origin = pPlayer->v.origin;
Vector view_angle = pPlayer->v.v_angle;
Vector view_offset = pPlayer->v.view_ofs;
// Prepare Trace
TraceResult tr;
Vector v_src, v_dest;
UTIL_MakeVectors(view_angle);
v_src = origin + view_offset; // Player aiment
v_dest = v_src + gpGlobals->v_forward * 4096; // Should cover enough distance
UTIL_TraceLine(v_src, v_dest, dont_ignore_monsters, pPlayer, &tr);
// Hit an entity?
if (tr.pHit != NULL)
{
// Must be a monster
if (tr.pHit->v.flags & FL_MONSTER)
{
// Get monster info
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(tr.pHit));
char szInfo[512];
sprintf(szInfo, "Enemy: %s\nHealth: %.0f\nFrags: %.0f\n", STRING( pMonster->m_szMonsterName ), pMonster->pev->health, pMonster->pev->frags );
// Create a TE_TEXTMESSAGE and show the monster information
MESSAGE_BEGIN( MSG_ONE, SVC_TEMPENTITY, NULL, pPlayer );
WRITE_BYTE( TE_TEXTMESSAGE );
WRITE_BYTE( 3 ); // Channel
WRITE_SHORT( 327 ); // X
WRITE_SHORT( 4771 ); // Y
WRITE_BYTE( 0 ); // Effect
WRITE_BYTE( 171 ); // R1
WRITE_BYTE( 23 ); // G1
WRITE_BYTE( 7 ); // B1
WRITE_BYTE( 0 ); // A1
WRITE_BYTE( 207 ); // R2
WRITE_BYTE( 23 ); // G2
WRITE_BYTE( 7 ); // B2
WRITE_BYTE( 255 ); // A2
WRITE_SHORT( 0 ); // Fade-in Time
WRITE_SHORT( 15 ); // Fade-out Time
WRITE_SHORT( 448 ); // Hold time
WRITE_STRING( szInfo ); // Message
MESSAGE_END();
// Delay till next scan
g_NextMessage[ ENTINDEX( pPlayer ) ] = gpGlobals->time + 0.875;
}
}
}
}
bool spawn_monster(int monster_type, Vector origin, Vector angles, int respawn_index, int spawnflags, pKVD *keyvalue) bool spawn_monster(int monster_type, Vector origin, Vector angles, int respawn_index, int spawnflags, pKVD *keyvalue)
{ {
int monster_index; int monster_index;
@@ -1032,7 +1240,7 @@ void mmDispatchThink( edict_t *pent )
{ {
monsters[index].pMonster->Think(); monsters[index].pMonster->Think();
check_monster_dead(); check_monster_dead(pent);
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
@@ -1054,7 +1262,7 @@ void mmDispatchTouch( edict_t *pentTouched, edict_t *pentOther )
{ {
monsters[index].pMonster->Touch(pentOther); monsters[index].pMonster->Touch(pentOther);
check_monster_dead(); check_monster_dead(pentOther);
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
@@ -1174,6 +1382,13 @@ void mmStartFrame( void )
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
void mmClientKill( edict_t *pPlayer )
{
// Just to let the system know the player commited suicide
pPlayer->v.dmg_inflictor = pPlayer;
RETURN_META(MRES_IGNORED);
}
static DLL_FUNCTIONS gFunctionTable = static DLL_FUNCTIONS gFunctionTable =
{ {
mmGameDLLInit, //! pfnGameInit() Initialize the game (one-time call after loading of game .dll) mmGameDLLInit, //! pfnGameInit() Initialize the game (one-time call after loading of game .dll)
@@ -1196,7 +1411,7 @@ static DLL_FUNCTIONS gFunctionTable =
NULL, // pfnClientConnect NULL, // pfnClientConnect
NULL, // pfnClientDisconnect NULL, // pfnClientDisconnect
NULL, // pfnClientKill mmClientKill, //! pfnClientKill
NULL, // pfnClientPutInServer NULL, // pfnClientPutInServer
NULL, // pfnClientCommand NULL, // pfnClientCommand
NULL, // pfnClientUserInfoChanged NULL, // pfnClientUserInfoChanged
@@ -1259,18 +1474,18 @@ C_DLLEXPORT int GetEntityAPI2( DLL_FUNCTIONS *pFunctionTable, int *interfaceVers
void mmDispatchThink_Post( edict_t *pent ) void mmDispatchThink_Post( edict_t *pent )
{ {
check_monster_hurt(pent); check_monster_hurt(pent);
check_monster_dead(); check_monster_dead(pent);
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
void mmPlayerPostThink_Post( edict_t *pEntity ) void mmPlayerPostThink_Post( edict_t *pEntity )
{ {
check_monster_hurt(pEntity); check_monster_hurt(pEntity);
check_monster_dead(); check_monster_dead(pEntity);
check_player_dead(pEntity);
check_monster_info(pEntity);
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
@@ -1353,3 +1568,534 @@ C_DLLEXPORT int GetEntityAPI2_Post( DLL_FUNCTIONS *pFunctionTable, int *interfac
memcpy( pFunctionTable, &gFunctionTable_Post, sizeof( DLL_FUNCTIONS ) ); memcpy( pFunctionTable, &gFunctionTable_Post, sizeof( DLL_FUNCTIONS ) );
return(TRUE); return(TRUE);
} }
// Some messages seems to be offset by 1. Linux specific? CStrike specific?
int IsCSServer( void )
{
char mod[16];
sprintf( mod, "%s", GET_GAME_INFO( PLID, GINFO_NAME ) );
if ( strcmp( mod, "cstrike" ) == 0 || strcmp( mod, "czero" ) == 0 )
return 1;
return 0;
}
int mmRegUserMsg_Post( const char *pName, int iSize )
{
int cs_server = IsCSServer();
if ( strcmp( pName, "Damage" ) == 0 )
g_DamageMsg = META_RESULT_ORIG_RET( int ) - cs_server;
else if ( strcmp( pName, "DeathMsg" ) == 0 )
g_DeathMsg = META_RESULT_ORIG_RET( int );// - cs_server;
RETURN_META_VALUE( MRES_IGNORED, 0 );
}
void mmMessageBegin_Post( int msg_dest, int msg_type, const float *pOrigin, edict_t *ed )
{
if ( msg_type == g_DamageMsg )
{
// Whatever hurting us must be a valid entity
if (ed->v.dmg_inflictor != NULL )
{
g_DamageActive = true;
g_DamageVictim = ENTINDEX( ed );
g_DamageAttacker[ g_DamageVictim ] = ed->v.dmg_inflictor;
}
}
else if ( msg_type == g_DeathMsg )
{
// Prepare to update deathmsg
g_DeathActive = true;
}
RETURN_META( MRES_IGNORED );
}
void mmWriteLong_Post( int iValue )
{
if ( g_DamageActive )
g_DamageBits[ g_DamageVictim ] = iValue;
RETURN_META( MRES_IGNORED );
}
// This cannot be done on post!
void mmWriteString( const char *szValue )
{
if ( g_DeathActive )
{
// Prevent recursion
g_DeathActive = false;
// Ensure whatever killed the player is a valid entity
if (g_DamageAttacker[ g_DamageVictim ] != NULL)
{
// Send a new WriteString with the killer's classname
WRITE_STRING( STRING( g_DamageAttacker[ g_DamageVictim ]->v.classname ) );
// Supercede the old message
RETURN_META( MRES_SUPERCEDE );
}
}
RETURN_META( MRES_IGNORED );
}
void mmMessageEnd_Post( void )
{
g_DamageActive = false;
RETURN_META( MRES_IGNORED );
}
enginefuncs_t meta_engfuncs =
{
NULL, // pfnPrecacheModel()
NULL, // pfnPrecacheSound()
NULL, // pfnSetModel()
NULL, // pfnModelIndex()
NULL, // pfnModelFrames()
NULL, // pfnSetSize()
NULL, // pfnChangeLevel()
NULL, // pfnGetSpawnParms()
NULL, // pfnSaveSpawnParms()
NULL, // pfnVecToYaw()
NULL, // pfnVecToAngles()
NULL, // pfnMoveToOrigin()
NULL, // pfnChangeYaw()
NULL, // pfnChangePitch()
NULL, // pfnFindEntityByString()
NULL, // pfnGetEntityIllum()
NULL, // pfnFindEntityInSphere()
NULL, // pfnFindClientInPVS()
NULL, // pfnEntitiesInPVS()
NULL, // pfnMakeVectors()
NULL, // pfnAngleVectors()
NULL, // pfnCreateEntity()
NULL, // pfnRemoveEntity()
NULL, // pfnCreateNamedEntity()
NULL, // pfnMakeStatic()
NULL, // pfnEntIsOnFloor()
NULL, // pfnDropToFloor()
NULL, // pfnWalkMove()
NULL, // pfnSetOrigin()
NULL, // pfnEmitSound()
NULL, // pfnEmitAmbientSound()
NULL, // pfnTraceLine()
NULL, // pfnTraceToss()
NULL, // pfnTraceMonsterHull()
NULL, // pfnTraceHull()
NULL, // pfnTraceModel()
NULL, // pfnTraceTexture()
NULL, // pfnTraceSphere()
NULL, // pfnGetAimVector()
NULL, // pfnServerCommand()
NULL, // pfnServerExecute()
NULL, // pfnClientCommand()
NULL, // pfnParticleEffect()
NULL, // pfnLightStyle()
NULL, // pfnDecalIndex()
NULL, // pfnPointContents()
NULL, // pfnMessageBegin()
NULL, // pfnMessageEnd()
NULL, // pfnWriteByte()
NULL, // pfnWriteChar()
NULL, // pfnWriteShort()
NULL, // pfnWriteLong()
NULL, // pfnWriteAngle()
NULL, // pfnWriteCoord()
mmWriteString, //! pfnWriteString()
NULL, // pfnWriteEntity()
NULL, // pfnCVarRegister()
NULL, // pfnCVarGetFloat()
NULL, // pfnCVarGetString()
NULL, // pfnCVarSetFloat()
NULL, // pfnCVarSetString()
NULL, // pfnAlertMessage()
NULL, // pfnEngineFprintf()
NULL, // pfnPvAllocEntPrivateData()
NULL, // pfnPvEntPrivateData()
NULL, // pfnFreeEntPrivateData()
NULL, // pfnSzFromIndex()
NULL, // pfnAllocString()
NULL, // pfnGetVarsOfEnt()
NULL, // pfnPEntityOfEntOffset()
NULL, // pfnEntOffsetOfPEntity()
NULL, // pfnIndexOfEdict()
NULL, // pfnPEntityOfEntIndex()
NULL, // pfnFindEntityByVars()
NULL, // pfnGetModelPtr()
NULL, // pfnRegUserMsg()
NULL, // pfnAnimationAutomove()
NULL, // pfnGetBonePosition()
NULL, // pfnFunctionFromName()
NULL, // pfnNameForFunction()
NULL, // pfnClientPrintf()
NULL, // pfnServerPrint()
NULL, // pfnCmd_Args()
NULL, // pfnCmd_Argv()
NULL, // pfnCmd_Argc()
NULL, // pfnGetAttachment()
NULL, // pfnCRC32_Init()
NULL, // pfnCRC32_ProcessBuffer()
NULL, // pfnCRC32_ProcessByte()
NULL, // pfnCRC32_Final()
NULL, // pfnRandomLong()
NULL, // pfnRandomFloat()
NULL, // pfnSetView()
NULL, // pfnTime()
NULL, // pfnCrosshairAngle()
NULL, // pfnLoadFileForMe()
NULL, // pfnFreeFile()
NULL, // pfnEndSection()
NULL, // pfnCompareFileTime()
NULL, // pfnGetGameDir()
NULL, // pfnCvar_RegisterVariable()
NULL, // pfnFadeClientVolume()
NULL, // pfnSetClientMaxspeed()
NULL, // pfnCreateFakeClient()
NULL, // pfnRunPlayerMove()
NULL, // pfnNumberOfEntities()
NULL, // pfnGetInfoKeyBuffer()
NULL, // pfnInfoKeyValue()
NULL, // pfnSetKeyValue()
NULL, // pfnSetClientKeyValue()
NULL, // pfnIsMapValid()
NULL, // pfnStaticDecal()
NULL, // pfnPrecacheGeneric()
NULL, // pfnGetPlayerUserId()
NULL, // pfnBuildSoundMsg()
NULL, // pfnIsDedicatedServer()
NULL, // pfnCVarGetPointer()
NULL, // pfnGetPlayerWONId()
NULL, // pfnInfo_RemoveKey()
NULL, // pfnGetPhysicsKeyValue()
NULL, // pfnSetPhysicsKeyValue()
NULL, // pfnGetPhysicsInfoString()
NULL, // pfnPrecacheEvent()
NULL, // pfnPlaybackEvent()
NULL, // pfnSetFatPVS()
NULL, // pfnSetFatPAS()
NULL, // pfnCheckVisibility()
NULL, // pfnDeltaSetField()
NULL, // pfnDeltaUnsetField()
NULL, // pfnDeltaAddEncoder()
NULL, // pfnGetCurrentPlayer()
NULL, // pfnCanSkipPlayer()
NULL, // pfnDeltaFindField()
NULL, // pfnDeltaSetFieldByIndex()
NULL, // pfnDeltaUnsetFieldByIndex()
NULL, // pfnSetGroupMask()
NULL, // pfnCreateInstancedBaseline()
NULL, // pfnCvar_DirectSet()
NULL, // pfnForceUnmodified()
NULL, // pfnGetPlayerStats()
NULL, // pfnAddServerCommand()
NULL, // pfnVoice_GetClientListening()
NULL, // pfnVoice_SetClientListening()
NULL, // pfnGetPlayerAuthId()
NULL, // pfnSequenceGet()
NULL, // pfnSequencePickSentence()
NULL, // pfnGetFileSize()
NULL, // pfnGetApproxWavePlayLen()
NULL, // pfnIsCareerMatch()
NULL, // pfnGetLocalizedStringLength()
NULL, // pfnRegisterTutorMessageShown()
NULL, // pfnGetTimesTutorMessageShown()
NULL, // pfnProcessTutorMessageDecayBuffer()
NULL, // pfnConstructTutorMessageDecayBuffer()
NULL, // pfnResetTutorMessageDecayData()
NULL, // pfnQueryClientCvarValue()
NULL, // pfnQueryClientCvarValue2()
NULL, // pfnEngCheckParm()
};
C_DLLEXPORT int GetEngineFunctions(enginefuncs_t *pengfuncsFromEngine, int *interfaceVersion)
{
if(!pengfuncsFromEngine)
{
LOG_ERROR(PLID, "GetEngineFunctions called with null pengfuncsFromEngine");
return(FALSE);
}
else if(*interfaceVersion != ENGINE_INTERFACE_VERSION)
{
LOG_ERROR(PLID, "GetEngineFunctions version mismatch; requested=%d ours=%d", *interfaceVersion, ENGINE_INTERFACE_VERSION);
// Tell metamod what version we had, so it can figure out who is
// out of date.
*interfaceVersion = ENGINE_INTERFACE_VERSION;
return(FALSE);
}
memcpy(pengfuncsFromEngine, &meta_engfuncs, sizeof(enginefuncs_t));
return TRUE;
}
enginefuncs_t meta_engfuncs_post =
{
NULL, // pfnPrecacheModel()
NULL, // pfnPrecacheSound()
NULL, // pfnSetModel()
NULL, // pfnModelIndex()
NULL, // pfnModelFrames()
NULL, // pfnSetSize()
NULL, // pfnChangeLevel()
NULL, // pfnGetSpawnParms()
NULL, // pfnSaveSpawnParms()
NULL, // pfnVecToYaw()
NULL, // pfnVecToAngles()
NULL, // pfnMoveToOrigin()
NULL, // pfnChangeYaw()
NULL, // pfnChangePitch()
NULL, // pfnFindEntityByString()
NULL, // pfnGetEntityIllum()
NULL, // pfnFindEntityInSphere()
NULL, // pfnFindClientInPVS()
NULL, // pfnEntitiesInPVS()
NULL, // pfnMakeVectors()
NULL, // pfnAngleVectors()
NULL, // pfnCreateEntity()
NULL, // pfnRemoveEntity()
NULL, // pfnCreateNamedEntity()
NULL, // pfnMakeStatic()
NULL, // pfnEntIsOnFloor()
NULL, // pfnDropToFloor()
NULL, // pfnWalkMove()
NULL, // pfnSetOrigin()
NULL, // pfnEmitSound()
NULL, // pfnEmitAmbientSound()
NULL, // pfnTraceLine()
NULL, // pfnTraceToss()
NULL, // pfnTraceMonsterHull()
NULL, // pfnTraceHull()
NULL, // pfnTraceModel()
NULL, // pfnTraceTexture()
NULL, // pfnTraceSphere()
NULL, // pfnGetAimVector()
NULL, // pfnServerCommand()
NULL, // pfnServerExecute()
NULL, // pfnClientCommand()
NULL, // pfnParticleEffect()
NULL, // pfnLightStyle()
NULL, // pfnDecalIndex()
NULL, // pfnPointContents()
mmMessageBegin_Post, //! pfnMessageBegin()
mmMessageEnd_Post, //! pfnMessageEnd()
NULL, // pfnWriteByte()
NULL, // pfnWriteChar()
NULL, // pfnWriteShort()
mmWriteLong_Post, //! pfnWriteLong()
NULL, // pfnWriteAngle()
NULL, // pfnWriteCoord()
NULL, // pfnWriteString()
NULL, // pfnWriteEntity()
NULL, // pfnCVarRegister()
NULL, // pfnCVarGetFloat()
NULL, // pfnCVarGetString()
NULL, // pfnCVarSetFloat()
NULL, // pfnCVarSetString()
NULL, // pfnAlertMessage()
NULL, // pfnEngineFprintf()
NULL, // pfnPvAllocEntPrivateData()
NULL, // pfnPvEntPrivateData()
NULL, // pfnFreeEntPrivateData()
NULL, // pfnSzFromIndex()
NULL, // pfnAllocString()
NULL, // pfnGetVarsOfEnt()
NULL, // pfnPEntityOfEntOffset()
NULL, // pfnEntOffsetOfPEntity()
NULL, // pfnIndexOfEdict()
NULL, // pfnPEntityOfEntIndex()
NULL, // pfnFindEntityByVars()
NULL, // pfnGetModelPtr()
mmRegUserMsg_Post, //! pfnRegUserMsg()
NULL, // pfnAnimationAutomove()
NULL, // pfnGetBonePosition()
NULL, // pfnFunctionFromName()
NULL, // pfnNameForFunction()
NULL, // pfnClientPrintf()
NULL, // pfnServerPrint()
NULL, // pfnCmd_Args()
NULL, // pfnCmd_Argv()
NULL, // pfnCmd_Argc()
NULL, // pfnGetAttachment()
NULL, // pfnCRC32_Init()
NULL, // pfnCRC32_ProcessBuffer()
NULL, // pfnCRC32_ProcessByte()
NULL, // pfnCRC32_Final()
NULL, // pfnRandomLong()
NULL, // pfnRandomFloat()
NULL, // pfnSetView()
NULL, // pfnTime()
NULL, // pfnCrosshairAngle()
NULL, // pfnLoadFileForMe()
NULL, // pfnFreeFile()
NULL, // pfnEndSection()
NULL, // pfnCompareFileTime()
NULL, // pfnGetGameDir()
NULL, // pfnCvar_RegisterVariable()
NULL, // pfnFadeClientVolume()
NULL, // pfnSetClientMaxspeed()
NULL, // pfnCreateFakeClient()
NULL, // pfnRunPlayerMove()
NULL, // pfnNumberOfEntities()
NULL, // pfnGetInfoKeyBuffer()
NULL, // pfnInfoKeyValue()
NULL, // pfnSetKeyValue()
NULL, // pfnSetClientKeyValue()
NULL, // pfnIsMapValid()
NULL, // pfnStaticDecal()
NULL, // pfnPrecacheGeneric()
NULL, // pfnGetPlayerUserId()
NULL, // pfnBuildSoundMsg()
NULL, // pfnIsDedicatedServer()
NULL, // pfnCVarGetPointer()
NULL, // pfnGetPlayerWONId()
NULL, // pfnInfo_RemoveKey()
NULL, // pfnGetPhysicsKeyValue()
NULL, // pfnSetPhysicsKeyValue()
NULL, // pfnGetPhysicsInfoString()
NULL, // pfnPrecacheEvent()
NULL, // pfnPlaybackEvent()
NULL, // pfnSetFatPVS()
NULL, // pfnSetFatPAS()
NULL, // pfnCheckVisibility()
NULL, // pfnDeltaSetField()
NULL, // pfnDeltaUnsetField()
NULL, // pfnDeltaAddEncoder()
NULL, // pfnGetCurrentPlayer()
NULL, // pfnCanSkipPlayer()
NULL, // pfnDeltaFindField()
NULL, // pfnDeltaSetFieldByIndex()
NULL, // pfnDeltaUnsetFieldByIndex()
NULL, // pfnSetGroupMask()
NULL, // pfnCreateInstancedBaseline()
NULL, // pfnCvar_DirectSet()
NULL, // pfnForceUnmodified()
NULL, // pfnGetPlayerStats()
NULL, // pfnAddServerCommand()
NULL, // pfnVoice_GetClientListening()
NULL, // pfnVoice_SetClientListening()
NULL, // pfnGetPlayerAuthId()
NULL, // pfnSequenceGet()
NULL, // pfnSequencePickSentence()
NULL, // pfnGetFileSize()
NULL, // pfnGetApproxWavePlayLen()
NULL, // pfnIsCareerMatch()
NULL, // pfnGetLocalizedStringLength()
NULL, // pfnRegisterTutorMessageShown()
NULL, // pfnGetTimesTutorMessageShown()
NULL, // pfnProcessTutorMessageDecayBuffer()
NULL, // pfnConstructTutorMessageDecayBuffer()
NULL, // pfnResetTutorMessageDecayData()
NULL, // pfnQueryClientCvarValue()
NULL, // pfnQueryClientCvarValue2()
NULL, // pfnEngCheckParm()
};
C_DLLEXPORT int GetEngineFunctions_Post(enginefuncs_t *pengfuncsFromEngine, int *interfaceVersion)
{
if(!pengfuncsFromEngine)
{
LOG_ERROR(PLID, "GetEngineFunctions_Post called with null pengfuncsFromEngine");
return(FALSE);
}
else if(*interfaceVersion != ENGINE_INTERFACE_VERSION)
{
LOG_ERROR(PLID, "GetEngineFunctions_Post version mismatch; requested=%d ours=%d", *interfaceVersion, ENGINE_INTERFACE_VERSION);
// Tell metamod what version we had, so it can figure out who is
// out of date.
*interfaceVersion = ENGINE_INTERFACE_VERSION;
return(FALSE);
}
memcpy(pengfuncsFromEngine, &meta_engfuncs_post, sizeof(enginefuncs_t));
return TRUE;
}

View File

@@ -624,6 +624,11 @@ void CMGargantua :: PrescheduleThink( void )
//========================================================= //=========================================================
int CMGargantua :: Classify ( void ) int CMGargantua :: Classify ( void )
{ {
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MONSTER; return CLASS_ALIEN_MONSTER;
} }
@@ -684,6 +689,13 @@ void CMGargantua :: Spawn()
EyeOff(); EyeOff();
m_seeTime = gpGlobals->time + 5; m_seeTime = gpGlobals->time + 5;
m_flameTime = gpGlobals->time + 2; m_flameTime = gpGlobals->time + 2;
pev->classname = MAKE_STRING( "monster_gargantua" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Gargantua" );
}
} }

View File

@@ -88,6 +88,11 @@ int CMHAssassin :: ISoundMask ( void)
//========================================================= //=========================================================
int CMHAssassin :: Classify ( void ) int CMHAssassin :: Classify ( void )
{ {
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_HUMAN_MILITARY; return CLASS_HUMAN_MILITARY;
} }
@@ -228,8 +233,15 @@ void CMHAssassin :: Spawn()
m_iTargetRanderamt = 20; m_iTargetRanderamt = 20;
pev->renderamt = 20; pev->renderamt = 20;
pev->rendermode = kRenderTransTexture; pev->rendermode = kRenderTransTexture;
MonsterInit(); MonsterInit();
pev->classname = MAKE_STRING( "monster_human_assassin" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Female Assassin" );
}
} }
//========================================================= //=========================================================
@@ -906,4 +918,4 @@ Schedule_t* CMHAssassin :: GetScheduleOfType ( int Type )
return CMBaseMonster :: GetScheduleOfType( Type ); return CMBaseMonster :: GetScheduleOfType( Type );
} }
#endif #endif

View File

@@ -119,6 +119,11 @@ const char *CMHeadCrab::pBiteSounds[] =
//========================================================= //=========================================================
int CMHeadCrab :: Classify ( void ) int CMHeadCrab :: Classify ( void )
{ {
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_PREY; return CLASS_ALIEN_PREY;
} }
@@ -256,6 +261,13 @@ void CMHeadCrab :: Spawn()
m_MonsterState = MONSTERSTATE_NONE; m_MonsterState = MONSTERSTATE_NONE;
MonsterInit(); MonsterInit();
pev->classname = MAKE_STRING( "monster_headcrab" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Head Crab" );
}
} }
//========================================================= //=========================================================

View File

@@ -174,12 +174,15 @@ void CMHGrunt :: SpeakSentence( void )
//========================================================= //=========================================================
int CMHGrunt::IRelationship ( CMBaseEntity *pTarget ) int CMHGrunt::IRelationship ( CMBaseEntity *pTarget )
{ {
if (( strcmp(STRING(pTarget->pev->model), "models/agrunt.mdl") == 0 ) || // on single player, forcing R_NM makes sense.
// on multiplayer, a custom classification will cause misbehaviour.
/*
if (( strcmp(STRING(pTarget->pev->model), "models/agrunt.mdl") == 0 ) ||
( strcmp(STRING(pTarget->pev->model), "models/garg.mdl") == 0 )) ( strcmp(STRING(pTarget->pev->model), "models/garg.mdl") == 0 ))
{ {
return R_NM; return R_NM;
} }
*/
return CMBaseMonster::IRelationship( pTarget ); return CMBaseMonster::IRelationship( pTarget );
} }
@@ -596,6 +599,11 @@ void CMHGrunt :: CheckAmmo ( void )
//========================================================= //=========================================================
int CMHGrunt :: Classify ( void ) int CMHGrunt :: Classify ( void )
{ {
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_HUMAN_MILITARY; return CLASS_HUMAN_MILITARY;
} }
@@ -886,6 +894,13 @@ void CMHGrunt :: Spawn()
CMTalkMonster::g_talkWaitTime = 0; CMTalkMonster::g_talkWaitTime = 0;
MonsterInit(); MonsterInit();
pev->classname = MAKE_STRING( "monster_human_grunt" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Human Grunt" );
}
} }
//========================================================= //=========================================================

View File

@@ -49,7 +49,7 @@ void CMHornet :: Spawn( void )
pev->movetype = MOVETYPE_FLY; pev->movetype = MOVETYPE_FLY;
pev->solid = SOLID_BBOX; pev->solid = SOLID_BBOX;
pev->takedamage = DAMAGE_YES; pev->takedamage = DAMAGE_YES;
pev->flags |= FL_MONSTER; pev->flags |= FL_MONSTER; // I have a bad feeling about this
pev->health = 1;// weak! pev->health = 1;// weak!
// hornets don't live as long in multiplayer // hornets don't live as long in multiplayer
@@ -83,6 +83,8 @@ void CMHornet :: Spawn( void )
pev->nextthink = gpGlobals->time + 0.1; pev->nextthink = gpGlobals->time + 0.1;
ResetSequenceInfo( ); ResetSequenceInfo( );
pev->classname = MAKE_STRING( "hornet" );
} }
@@ -124,13 +126,23 @@ int CMHornet::IRelationship ( CMBaseEntity *pTarget )
//========================================================= //=========================================================
int CMHornet::Classify ( void ) int CMHornet::Classify ( void )
{ {
/*
if ( pev->owner && pev->owner->v.flags & FL_CLIENT) if ( pev->owner && pev->owner->v.flags & FL_CLIENT)
{ {
return CLASS_PLAYER_BIOWEAPON; return CLASS_PLAYER_BIOWEAPON;
} }
return CLASS_ALIEN_BIOWEAPON; return CLASS_ALIEN_BIOWEAPON;
*/
// Ensure classify is consistent with the owner, in the event
// it's classification was overriden.
if ( pev->owner == NULL )
return CLASS_ALIEN_BIOWEAPON;
// Ain't this going to make the hornets code "slow"?
CMBaseMonster *pOwner = GetClassPtr((CMBaseMonster *)VARS(pev->owner));
return pOwner->Classify();
} }
//========================================================= //=========================================================

View File

@@ -78,6 +78,11 @@ enum
//========================================================= //=========================================================
int CMHoundeye :: Classify ( void ) int CMHoundeye :: Classify ( void )
{ {
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MONSTER; return CLASS_ALIEN_MONSTER;
} }
@@ -277,6 +282,13 @@ void CMHoundeye :: Spawn()
m_fDontBlink = FALSE; m_fDontBlink = FALSE;
MonsterInit(); MonsterInit();
pev->classname = MAKE_STRING( "monster_houndeye" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Houndeye" );
}
} }
//========================================================= //=========================================================

View File

@@ -67,6 +67,11 @@ const char *CMISlave::pDeathSounds[] =
//========================================================= //=========================================================
int CMISlave :: Classify ( void ) int CMISlave :: Classify ( void )
{ {
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MILITARY; return CLASS_ALIEN_MILITARY;
} }
@@ -429,10 +434,16 @@ void CMISlave :: Spawn()
for (int i = 0; i < ISLAVE_MAX_BEAMS; i++) for (int i = 0; i < ISLAVE_MAX_BEAMS; i++)
m_pBeam[i] = NULL; m_pBeam[i] = NULL;
m_iBravery = 0; m_iBravery = 0;
m_flNextAttack = 0.0f; m_flNextAttack = 0.0f;
MonsterInit(); MonsterInit();
pev->classname = MAKE_STRING( "monster_alien_slave" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Alien Slave" );
}
} }
//========================================================= //=========================================================

View File

@@ -40,23 +40,24 @@
#include "sdk_util.h" // UTIL_LogPrintf, etc #include "sdk_util.h" // UTIL_LogPrintf, etc
// Must provide at least one of these.. // Must provide at least one of these..
static META_FUNCTIONS gMetaFunctionTable = { static META_FUNCTIONS gMetaFunctionTable =
NULL, // pfnGetEntityAPI HL SDK; called before game DLL {
NULL, // pfnGetEntityAPI_Post META; called after game DLL NULL, // pfnGetEntityAPI HL SDK; called before game DLL
GetEntityAPI2, // pfnGetEntityAPI2 HL SDK2; called before game DLL NULL, // pfnGetEntityAPI_Post META; called after game DLL
GetEntityAPI2_Post, // pfnGetEntityAPI2_Post META; called after game DLL GetEntityAPI2, // pfnGetEntityAPI2 HL SDK2; called before game DLL
NULL, // pfnGetNewDLLFunctions HL SDK2; called before game DLL GetEntityAPI2_Post, // pfnGetEntityAPI2_Post META; called after game DLL
NULL, // pfnGetNewDLLFunctions_Post META; called after game DLL NULL, // pfnGetNewDLLFunctions HL SDK2; called before game DLL
NULL, // pfnGetEngineFunctions META; called before HL engine NULL, // pfnGetNewDLLFunctions_Post META; called after game DLL
NULL, // pfnGetEngineFunctions_Post META; called after HL engine GetEngineFunctions, // pfnGetEngineFunctions META; called before HL engine
GetEngineFunctions_Post, // pfnGetEngineFunctions_Post META; called after HL engine
}; };
// Description of plugin // Description of plugin
plugin_info_t Plugin_info = { plugin_info_t Plugin_info = {
META_INTERFACE_VERSION, // interface version META_INTERFACE_VERSION, // interface version
"MonsterMod", // name "MonsterMod", // name
"1.0", // version "2.0", // version
"17/03/2020", // date in DD/MM/YYYY format "03/06/2020", // date in DD/MM/YYYY format
"botman, Rick90, Giegue", // original authors + recreation by... "botman, Rick90, Giegue", // original authors + recreation by...
"https://github.com/JulianR0/monstermod-redo", // url "https://github.com/JulianR0/monstermod-redo", // url
"MONSTER", // logtag "MONSTER", // logtag
@@ -77,10 +78,15 @@ meta_globals_t *gpMetaGlobals; // metamod globals
gamedll_funcs_t *gpGamedllFuncs; // gameDLL function tables gamedll_funcs_t *gpGamedllFuncs; // gameDLL function tables
mutil_funcs_t *gpMetaUtilFuncs; // metamod utility functions mutil_funcs_t *gpMetaUtilFuncs; // metamod utility functions
// CVars
cvar_t init_dllapi_log = {"monster_log", "0", FCVAR_EXTDLL, 0, NULL}; cvar_t init_dllapi_log = {"monster_log", "0", FCVAR_EXTDLL, 0, NULL};
cvar_t *dllapi_log = NULL; cvar_t *dllapi_log = NULL;
cvar_t init_monster_spawn = {"monster_spawn", "1", FCVAR_EXTDLL, 0, NULL}; cvar_t init_monster_spawn = {"monster_spawn", "1", FCVAR_EXTDLL, 0, NULL};
cvar_t *monster_spawn = NULL; cvar_t *monster_spawn = NULL;
cvar_t init_monster_show_deaths = {"monster_show_deaths", "1", FCVAR_EXTDLL, 0, NULL};
cvar_t *monster_show_deaths = NULL;
cvar_t init_monster_show_info = {"monster_show_info", "1", FCVAR_EXTDLL, 0, NULL};
cvar_t *monster_show_info = NULL;
// Metamod requesting info about this plugin: // Metamod requesting info about this plugin:
@@ -103,37 +109,44 @@ C_DLLEXPORT int Meta_Query(char *ifvers, plugin_info_t **pPlugInfo,
// pFunctionTable (requested) table of function tables this plugin catches // pFunctionTable (requested) table of function tables this plugin catches
// pMGlobals (given) global vars from metamod // pMGlobals (given) global vars from metamod
// pGamedllFuncs (given) copy of function tables from game dll // pGamedllFuncs (given) copy of function tables from game dll
C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs)
meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs)
{ {
if(now); // to satisfy gcc -Wunused if(now); // to satisfy gcc -Wunused
if(!pMGlobals) { if(!pMGlobals)
LOG_ERROR(PLID, "Meta_Attach called with null pMGlobals"); {
return(FALSE); LOG_ERROR(PLID, "Meta_Attach called with null pMGlobals");
} return(FALSE);
gpMetaGlobals=pMGlobals; }
if(!pFunctionTable) { gpMetaGlobals=pMGlobals;
LOG_ERROR(PLID, "Meta_Attach called with null pFunctionTable"); if(!pFunctionTable)
return(FALSE); {
} LOG_ERROR(PLID, "Meta_Attach called with null pFunctionTable");
memcpy(pFunctionTable, &gMetaFunctionTable, sizeof(META_FUNCTIONS)); return(FALSE);
gpGamedllFuncs=pGamedllFuncs; }
memcpy(pFunctionTable, &gMetaFunctionTable, sizeof(META_FUNCTIONS));
gpGamedllFuncs=pGamedllFuncs;
LOG_MESSAGE(PLID, "%s %s, %s", VNAME, VVERSION, VDATE); LOG_MESSAGE(PLID, "%s %s, %s", VNAME, VVERSION, VDATE);
LOG_MESSAGE(PLID, "by %s", VAUTHOR); LOG_MESSAGE(PLID, "by %s", VAUTHOR);
LOG_MESSAGE(PLID, "%s", VURL); LOG_MESSAGE(PLID, "%s", VURL);
LOG_MESSAGE(PLID, "compiled: %s CDT", COMPILE_TIME); LOG_MESSAGE(PLID, "compiled: %s CDT", COMPILE_TIME);
LOG_CONSOLE(PLID, "[%s] %s v%s, %s", VLOGTAG, VNAME, VVERSION, VDATE); LOG_CONSOLE(PLID, "[%s] %s v%s, %s", VLOGTAG, VNAME, VVERSION, VDATE);
LOG_CONSOLE(PLID, "[%s] by %s", VLOGTAG, VAUTHOR); LOG_CONSOLE(PLID, "[%s] by %s", VLOGTAG, VAUTHOR);
CVAR_REGISTER(&init_dllapi_log); CVAR_REGISTER(&init_dllapi_log);
dllapi_log = CVAR_GET_POINTER("monster_log"); dllapi_log = CVAR_GET_POINTER("monster_log");
CVAR_REGISTER(&init_monster_spawn); CVAR_REGISTER(&init_monster_spawn);
monster_spawn = CVAR_GET_POINTER("monster_spawn"); monster_spawn = CVAR_GET_POINTER("monster_spawn");
return(TRUE); CVAR_REGISTER(&init_monster_show_deaths);
monster_show_deaths = CVAR_GET_POINTER("monster_show_deaths");
CVAR_REGISTER(&init_monster_show_info);
monster_show_info = CVAR_GET_POINTER("monster_show_info");
return(TRUE);
} }

View File

@@ -2504,11 +2504,21 @@ void CMBaseMonster :: KeyValue( KeyValueData *pkvd )
m_iszTriggerTarget = ALLOC_STRING( pkvd->szValue ); m_iszTriggerTarget = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE; pkvd->fHandled = TRUE;
} }
else if (FStrEq(pkvd->szKeyName, "TriggerCondition") ) else if (FStrEq(pkvd->szKeyName, "TriggerCondition"))
{ {
m_iTriggerCondition = atoi( pkvd->szValue ); m_iTriggerCondition = atoi( pkvd->szValue );
pkvd->fHandled = TRUE; pkvd->fHandled = TRUE;
} }
else if (FStrEq(pkvd->szKeyName, "displayname"))
{
m_szMonsterName = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "classify"))
{
m_iClassifyOverride = atoi( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else else
{ {
CMBaseToggle::KeyValue( pkvd ); CMBaseToggle::KeyValue( pkvd );

View File

@@ -1485,8 +1485,6 @@ void CTestHull :: Spawn( entvars_t *pevMasterNode )
//========================================================= //=========================================================
void CTestHull::DropDelay ( void ) void CTestHull::DropDelay ( void )
{ {
// Do NOT uncomment or you'll get a "Tried to create a message with a bogus message type ( 0 )" crash!
// Left here only because it's on the original HLSDK, and for comedy purposes. -Giegue
//UTIL_CenterPrintAll( "Node Graph out of Date. Rebuilding..." ); //UTIL_CenterPrintAll( "Node Graph out of Date. Rebuilding..." );
UTIL_SetOrigin ( VARS(pev), WorldGraph.m_pNodes[ 0 ].m_vecOrigin ); UTIL_SetOrigin ( VARS(pev), WorldGraph.m_pNodes[ 0 ].m_vecOrigin );

View File

@@ -517,6 +517,11 @@ void CMScientist :: RunTask( Task_t *pTask )
//========================================================= //=========================================================
int CMScientist :: Classify ( void ) int CMScientist :: Classify ( void )
{ {
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_HUMAN_PASSIVE; return CLASS_HUMAN_PASSIVE;
} }
@@ -616,6 +621,13 @@ void CMScientist :: Spawn( void )
pev->skin = 1; pev->skin = 1;
MonsterInit(); MonsterInit();
pev->classname = MAKE_STRING( "monster_scientist" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Scientist" );
}
} }
//========================================================= //=========================================================

View File

@@ -47,6 +47,12 @@ float CMSqueakGrenade::m_flNextBounceSoundTime = 0;
int CMSqueakGrenade :: Classify ( void ) int CMSqueakGrenade :: Classify ( void )
{ {
// E
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MONSTER; return CLASS_ALIEN_MONSTER;
} }
@@ -84,6 +90,13 @@ void CMSqueakGrenade :: Spawn( void )
ResetSequenceInfo( ); ResetSequenceInfo( );
m_hEnemy = NULL; m_hEnemy = NULL;
pev->classname = MAKE_STRING( "monster_snark" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// hi :3
m_szMonsterName = MAKE_STRING( "Snark" );
}
} }
void CMSqueakGrenade::Precache( void ) void CMSqueakGrenade::Precache( void )
@@ -334,4 +347,4 @@ void CMSqueakGrenade::SuperBounceTouch( edict_t *pOther )
#endif #endif
#endif #endif

View File

@@ -142,6 +142,13 @@ void CMTurret::Spawn()
m_eyeBrightness = 0; m_eyeBrightness = 0;
pev->nextthink = gpGlobals->time + 0.3; pev->nextthink = gpGlobals->time + 0.3;
pev->classname = MAKE_STRING( "monster_turret" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Turret" );
}
} }
void CMTurret::Precache() void CMTurret::Precache()
@@ -166,8 +173,15 @@ void CMMiniTurret::Spawn()
m_iMinPitch = -15; m_iMinPitch = -15;
UTIL_SetSize(pev, Vector(-16, -16, -m_iRetractHeight), Vector(16, 16, m_iRetractHeight)); UTIL_SetSize(pev, Vector(-16, -16, -m_iRetractHeight), Vector(16, 16, m_iRetractHeight));
SetThink(&CMMiniTurret::Initialize); SetThink(&CMMiniTurret::Initialize);
pev->nextthink = gpGlobals->time + 0.3; pev->nextthink = gpGlobals->time + 0.3;
pev->classname = MAKE_STRING( "monster_miniturret" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Mini-Turret" );
}
} }
@@ -978,7 +992,15 @@ int CMBaseTurret::MoveTurret(void)
int CMBaseTurret::Classify ( void ) int CMBaseTurret::Classify ( void )
{ {
if (m_iOn || m_iAutoStart) if (m_iOn || m_iAutoStart)
return CLASS_MACHINE; {
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_MACHINE;
}
return CLASS_NONE; return CLASS_NONE;
} }
@@ -1006,8 +1028,15 @@ void CMSentry::Spawn()
UTIL_SetSize(pev, Vector(-16, -16, -m_iRetractHeight), Vector(16, 16, m_iRetractHeight)); UTIL_SetSize(pev, Vector(-16, -16, -m_iRetractHeight), Vector(16, 16, m_iRetractHeight));
SetTouch(&CMSentry::SentryTouch); SetTouch(&CMSentry::SentryTouch);
SetThink(&CMSentry::Initialize); SetThink(&CMSentry::Initialize);
pev->nextthink = gpGlobals->time + 0.3; pev->nextthink = gpGlobals->time + 0.3;
pev->classname = MAKE_STRING( "monster_sentry" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Sentry Turret" );
}
} }
void CMSentry::Shoot(Vector &vecSrc, Vector &vecDirToEnemy) void CMSentry::Shoot(Vector &vecSrc, Vector &vecDirToEnemy)

View File

@@ -757,7 +757,7 @@ int gmsgSayText = 0;
void UTIL_ClientPrintAll( int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 ) void UTIL_ClientPrintAll( int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 )
{ {
if (gmsgTextMsg) if (gmsgTextMsg == 0)
gmsgTextMsg = REG_USER_MSG( "TextMsg", -1 ); gmsgTextMsg = REG_USER_MSG( "TextMsg", -1 );
MESSAGE_BEGIN( MSG_ALL, gmsgTextMsg ); MESSAGE_BEGIN( MSG_ALL, gmsgTextMsg );
@@ -778,7 +778,7 @@ void UTIL_ClientPrintAll( int msg_dest, const char *msg_name, const char *param1
void ClientPrint( entvars_t *client, int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 ) void ClientPrint( entvars_t *client, int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 )
{ {
if (gmsgTextMsg) if (gmsgTextMsg == 0)
gmsgTextMsg = REG_USER_MSG( "TextMsg", -1 ); gmsgTextMsg = REG_USER_MSG( "TextMsg", -1 );
MESSAGE_BEGIN( MSG_ONE, gmsgTextMsg, NULL, client ); MESSAGE_BEGIN( MSG_ONE, gmsgTextMsg, NULL, client );
@@ -1754,11 +1754,18 @@ int UTIL_TakeDamage( edict_t *pEdict, entvars_t *pevInflictor, entvars_t *pevAtt
// do the damage // do the damage
pEdict->v.health -= flTake; pEdict->v.health -= flTake;
// store entity that hurt this player
pEdict->v.dmg_inflictor = ENT(pevAttacker);
if ( pEdict->v.health <= 0 ) if ( pEdict->v.health <= 0 )
{ {
pEdict->v.health = 1; // can't suicide if already dead! pEdict->v.health = 1; // can't suicide if already dead!
gpGamedllFuncs->dllapi_table->pfnClientKill(pEdict); gpGamedllFuncs->dllapi_table->pfnClientKill(pEdict);
// Add 1 score to the monster that killed this player
if ( pevAttacker->flags & FL_MONSTER )
pevAttacker->frags += 1.0;
} }
// tell director about it // tell director about it
@@ -1800,7 +1807,7 @@ int UTIL_TakeDamage( edict_t *pEdict, entvars_t *pevInflictor, entvars_t *pevAtt
WRITE_COORD( pevInflictor->origin.z ); WRITE_COORD( pevInflictor->origin.z );
MESSAGE_END(); MESSAGE_END();
} }
return fTookDamage; return fTookDamage;
} }

View File

@@ -82,6 +82,11 @@ const char *CMZombie::pPainSounds[] =
//========================================================= //=========================================================
int CMZombie :: Classify ( void ) int CMZombie :: Classify ( void )
{ {
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MONSTER; return CLASS_ALIEN_MONSTER;
} }
@@ -254,6 +259,13 @@ void CMZombie :: Spawn()
m_afCapability = bits_CAP_DOORS_GROUP; m_afCapability = bits_CAP_DOORS_GROUP;
MonsterInit(); MonsterInit();
pev->classname = MAKE_STRING( "monster_zombie" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Zombie" );
}
} }
//========================================================= //=========================================================
@@ -313,4 +325,4 @@ int CMZombie::IgnoreConditions ( void )
return iIgnore; return iIgnore;
} }