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]**
- Add info_node and info_node_air support for AI navigation. **[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
- Add *-at least minimal-* death messages. *-Example: "\<player\> was killed by a \<monster\>".-*
- Implement HUD info about the monsters, along with the "displayname" keyvalue.
- Implement custom monster classification, the "classify" keyvalue.
- 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. **[DONE]**
- Implement custom monster classification, the "classify" keyvalue. **[DONE]**
### Tier 3

View File

@@ -5,10 +5,31 @@
// To add entries to this file, just pretend it's ripent.
//
// "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"
"delay" "30"
"displayname" "Example Custom Name"
"orientation" "1"
"spawnflags" "32"
"classname" "monster_miniturret"
@@ -16,6 +37,7 @@
{
"origin" "123 456 789"
"delay" "5"
"classify" "7"
"angles" "0 45 0"
"classname" "monster_houndeye"
}

View File

@@ -1,6 +1,8 @@
//
// 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
// monsters that you always want to precache.)
@@ -10,12 +12,11 @@
//monster_bigmomma
//monster_bullsquid
//monster_gargantua
//monster_hassassin
//monster_human_assassin
//monster_headcrab
//monster_human_grunt
//monster_houndeye
//monster_alien_slave
//monster_icthyosaur
//monster_alien_controller
//monster_scientist
//monster_snark

View File

@@ -1,6 +1,6 @@
// 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
sk_agrunt_health 90

View File

@@ -125,10 +125,13 @@ const char *CMAGrunt::pAlertSounds[] =
//=========================================================
int CMAGrunt::IRelationship ( CMBaseEntity *pTarget )
{
// ditto hgrunt.cpp
/*
if ( strcmp(STRING(pTarget->pev->model), "models/hgrunt.mdl") == 0 )
{
return R_NM;
}
*/
return CMBaseMonster :: IRelationship( pTarget );
}
@@ -313,6 +316,11 @@ void CMAGrunt :: PainSound ( 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;
}
@@ -541,6 +549,13 @@ void CMAGrunt :: Spawn()
m_flNextSpeakTime = m_flNextWordTime = gpGlobals->time + 10 + RANDOM_LONG(0, 10);
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_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();
}
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 )
{

View File

@@ -186,6 +186,11 @@ int CMBarney :: ISoundMask ( 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;
}
@@ -357,6 +362,13 @@ void CMBarney :: Spawn()
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
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 )
{
pev->classname = MAKE_STRING( "info_bigmomma" );
}
void CMInfoBM::KeyValue( KeyValueData* pkvd )
@@ -298,6 +299,11 @@ void CMBigMomma :: KeyValue( KeyValueData *pkvd )
//=========================================================
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;
}
@@ -610,6 +616,13 @@ void CMBigMomma :: Spawn()
m_MonsterState = MONSTERSTATE_NONE;
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 )
{
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MONSTER;
}
@@ -617,6 +622,13 @@ void CMBullsquid :: Spawn()
m_flNextSpitTime = gpGlobals->time;
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;
extern int GetMonsterIndex(void);
//

View File

@@ -102,6 +102,9 @@ public:
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 );
// monster use function
@@ -792,7 +795,7 @@ class CMApache : public CMBaseMonster
public:
void Spawn( void );
void Precache( void );
int Classify( void ) { return CLASS_HUMAN_MILITARY; };
int Classify( void );
int BloodColor( void ) { return DONT_BLEED; }
void Killed( entvars_t *pevAttacker, int iGib );
void GibMonster( void );

View File

@@ -590,6 +590,10 @@ void CMBaseMonster :: Killed( entvars_t *pevAttacker, int iGib )
unsigned int cCount = 0;
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 ( ShouldGibMonster( iGib ) )

View File

@@ -81,6 +81,11 @@ const char *CMController::pDeathSounds[] =
//=========================================================
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;
}
@@ -310,6 +315,13 @@ void CMController :: Spawn()
m_MonsterState = MONSTERSTATE_NONE;
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;
pev->dmgtime = gpGlobals->time;
pev->classname = MAKE_STRING( "controller_head_ball" );
}
@@ -1297,8 +1311,9 @@ void CMControllerZapBall :: Spawn( void )
m_hOwner = pev->owner;
pev->dmgtime = gpGlobals->time; // keep track of when ball spawned
pev->nextthink = gpGlobals->time + 0.1;
}
pev->classname = MAKE_STRING( "controller_energy_ball" );
}
void CMControllerZapBall :: Precache( void )
{

View File

@@ -58,6 +58,24 @@ extern gamedll_funcs_t *gpGamedllFuncs;
extern cvar_t *dllapi_log;
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;
@@ -122,7 +140,7 @@ monster_type_t monster_types[]=
"monster_bigmomma", FALSE,
"monster_bullsquid", FALSE,
"monster_alien_controller", FALSE,
"monster_hassassin", FALSE,
"monster_human_assassin", FALSE,
"monster_headcrab", FALSE,
"monster_human_grunt", 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++)
{
@@ -325,7 +343,8 @@ void check_monster_dead(void)
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;
}
}
@@ -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)
{
int monster_index;
@@ -1032,7 +1240,7 @@ void mmDispatchThink( edict_t *pent )
{
monsters[index].pMonster->Think();
check_monster_dead();
check_monster_dead(pent);
RETURN_META(MRES_SUPERCEDE);
}
@@ -1054,7 +1262,7 @@ void mmDispatchTouch( edict_t *pentTouched, edict_t *pentOther )
{
monsters[index].pMonster->Touch(pentOther);
check_monster_dead();
check_monster_dead(pentOther);
RETURN_META(MRES_SUPERCEDE);
}
@@ -1174,6 +1382,13 @@ void mmStartFrame( void )
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 =
{
mmGameDLLInit, //! pfnGameInit() Initialize the game (one-time call after loading of game .dll)
@@ -1196,7 +1411,7 @@ static DLL_FUNCTIONS gFunctionTable =
NULL, // pfnClientConnect
NULL, // pfnClientDisconnect
NULL, // pfnClientKill
mmClientKill, //! pfnClientKill
NULL, // pfnClientPutInServer
NULL, // pfnClientCommand
NULL, // pfnClientUserInfoChanged
@@ -1259,8 +1474,7 @@ C_DLLEXPORT int GetEntityAPI2( DLL_FUNCTIONS *pFunctionTable, int *interfaceVers
void mmDispatchThink_Post( edict_t *pent )
{
check_monster_hurt(pent);
check_monster_dead();
check_monster_dead(pent);
RETURN_META(MRES_IGNORED);
}
@@ -1268,8 +1482,9 @@ void mmDispatchThink_Post( edict_t *pent )
void mmPlayerPostThink_Post( edict_t *pEntity )
{
check_monster_hurt(pEntity);
check_monster_dead();
check_monster_dead(pEntity);
check_player_dead(pEntity);
check_monster_info(pEntity);
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 ) );
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 )
{
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MONSTER;
}
@@ -684,6 +689,13 @@ void CMGargantua :: Spawn()
EyeOff();
m_seeTime = gpGlobals->time + 5;
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 )
{
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_HUMAN_MILITARY;
}
@@ -230,6 +235,13 @@ void CMHAssassin :: Spawn()
pev->rendermode = kRenderTransTexture;
MonsterInit();
pev->classname = MAKE_STRING( "monster_human_assassin" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Female Assassin" );
}
}
//=========================================================

View File

@@ -119,6 +119,11 @@ const char *CMHeadCrab::pBiteSounds[] =
//=========================================================
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;
}
@@ -256,6 +261,13 @@ void CMHeadCrab :: Spawn()
m_MonsterState = MONSTERSTATE_NONE;
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 )
{
// 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 ))
{
return R_NM;
}
*/
return CMBaseMonster::IRelationship( pTarget );
}
@@ -596,6 +599,11 @@ void CMHGrunt :: CheckAmmo ( 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;
}
@@ -886,6 +894,13 @@ void CMHGrunt :: Spawn()
CMTalkMonster::g_talkWaitTime = 0;
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->solid = SOLID_BBOX;
pev->takedamage = DAMAGE_YES;
pev->flags |= FL_MONSTER;
pev->flags |= FL_MONSTER; // I have a bad feeling about this
pev->health = 1;// weak!
// hornets don't live as long in multiplayer
@@ -83,6 +83,8 @@ void CMHornet :: Spawn( void )
pev->nextthink = gpGlobals->time + 0.1;
ResetSequenceInfo( );
pev->classname = MAKE_STRING( "hornet" );
}
@@ -124,13 +126,23 @@ int CMHornet::IRelationship ( CMBaseEntity *pTarget )
//=========================================================
int CMHornet::Classify ( void )
{
/*
if ( pev->owner && pev->owner->v.flags & FL_CLIENT)
{
return CLASS_PLAYER_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 )
{
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MONSTER;
}
@@ -277,6 +282,13 @@ void CMHoundeye :: Spawn()
m_fDontBlink = FALSE;
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 )
{
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MILITARY;
}
@@ -433,6 +438,12 @@ void CMISlave :: Spawn()
m_flNextAttack = 0.0f;
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
// 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
GetEntityAPI2, // pfnGetEntityAPI2 HL SDK2; called before game DLL
GetEntityAPI2_Post, // pfnGetEntityAPI2_Post META; called after game DLL
NULL, // pfnGetNewDLLFunctions HL SDK2; called before game DLL
NULL, // pfnGetNewDLLFunctions_Post META; called after game DLL
NULL, // pfnGetEngineFunctions META; called before HL engine
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
plugin_info_t Plugin_info = {
META_INTERFACE_VERSION, // interface version
"MonsterMod", // name
"1.0", // version
"17/03/2020", // date in DD/MM/YYYY format
"2.0", // version
"03/06/2020", // date in DD/MM/YYYY format
"botman, Rick90, Giegue", // original authors + recreation by...
"https://github.com/JulianR0/monstermod-redo", // url
"MONSTER", // logtag
@@ -77,10 +78,15 @@ meta_globals_t *gpMetaGlobals; // metamod globals
gamedll_funcs_t *gpGamedllFuncs; // gameDLL function tables
mutil_funcs_t *gpMetaUtilFuncs; // metamod utility functions
// CVars
cvar_t init_dllapi_log = {"monster_log", "0", FCVAR_EXTDLL, 0, NULL};
cvar_t *dllapi_log = NULL;
cvar_t init_monster_spawn = {"monster_spawn", "1", FCVAR_EXTDLL, 0, 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:
@@ -103,16 +109,17 @@ C_DLLEXPORT int Meta_Query(char *ifvers, plugin_info_t **pPlugInfo,
// pFunctionTable (requested) table of function tables this plugin catches
// pMGlobals (given) global vars from metamod
// pGamedllFuncs (given) copy of function tables from game dll
C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable,
meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs)
C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs)
{
if(now); // to satisfy gcc -Wunused
if(!pMGlobals) {
if(!pMGlobals)
{
LOG_ERROR(PLID, "Meta_Attach called with null pMGlobals");
return(FALSE);
}
gpMetaGlobals=pMGlobals;
if(!pFunctionTable) {
if(!pFunctionTable)
{
LOG_ERROR(PLID, "Meta_Attach called with null pFunctionTable");
return(FALSE);
}
@@ -133,6 +140,12 @@ C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable,
CVAR_REGISTER(&init_monster_spawn);
monster_spawn = CVAR_GET_POINTER("monster_spawn");
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

@@ -2509,6 +2509,16 @@ void CMBaseMonster :: KeyValue( KeyValueData *pkvd )
m_iTriggerCondition = atoi( pkvd->szValue );
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
{
CMBaseToggle::KeyValue( pkvd );

View File

@@ -1485,8 +1485,6 @@ void CTestHull :: Spawn( entvars_t *pevMasterNode )
//=========================================================
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_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 )
{
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_HUMAN_PASSIVE;
}
@@ -616,6 +621,13 @@ void CMScientist :: Spawn( void )
pev->skin = 1;
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 )
{
// E
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MONSTER;
}
@@ -84,6 +90,13 @@ void CMSqueakGrenade :: Spawn( void )
ResetSequenceInfo( );
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 )

View File

@@ -142,6 +142,13 @@ void CMTurret::Spawn()
m_eyeBrightness = 0;
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()
@@ -168,6 +175,13 @@ void CMMiniTurret::Spawn()
SetThink(&CMMiniTurret::Initialize);
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 )
{
if (m_iOn || m_iAutoStart)
{
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_MACHINE;
}
return CLASS_NONE;
}
@@ -1008,6 +1030,13 @@ void CMSentry::Spawn()
SetTouch(&CMSentry::SentryTouch);
SetThink(&CMSentry::Initialize);
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)

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 )
{
if (gmsgTextMsg)
if (gmsgTextMsg == 0)
gmsgTextMsg = REG_USER_MSG( "TextMsg", -1 );
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 )
{
if (gmsgTextMsg)
if (gmsgTextMsg == 0)
gmsgTextMsg = REG_USER_MSG( "TextMsg", -1 );
MESSAGE_BEGIN( MSG_ONE, gmsgTextMsg, NULL, client );
@@ -1755,10 +1755,17 @@ int UTIL_TakeDamage( edict_t *pEdict, entvars_t *pevInflictor, entvars_t *pevAtt
// do the damage
pEdict->v.health -= flTake;
// store entity that hurt this player
pEdict->v.dmg_inflictor = ENT(pevAttacker);
if ( pEdict->v.health <= 0 )
{
pEdict->v.health = 1; // can't suicide if already dead!
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

View File

@@ -82,6 +82,11 @@ const char *CMZombie::pPainSounds[] =
//=========================================================
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;
}
@@ -254,6 +259,13 @@ void CMZombie :: Spawn()
m_afCapability = bits_CAP_DOORS_GROUP;
MonsterInit();
pev->classname = MAKE_STRING( "monster_zombie" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Zombie" );
}
}
//=========================================================