Handle entvar keyvalues.
This commit is contained in:
@@ -158,8 +158,6 @@ I'm aware that the plugin is far from perfect, and there are a few things that n
|
||||
|
||||
- Rarely, Stukabats will become unable to fly towards their target, standing in air doing seemingly nothing. Cause of bug unknown.
|
||||
|
||||
- Entvars are not recognized, so anything that is a pevfield that is not used by monstermod is unusable.
|
||||
|
||||
There are probably more issues that aren't listed here, I'll attempt to fix them as I find them. Of course, any bug report is welcome. If reporting a bug, try to explain step by step how the bug ocurred. The easier it is to replicate a bug, the easier it is to locate it and fix it.
|
||||
|
||||
## Milestones
|
||||
|
||||
@@ -4,4 +4,6 @@ This folder contains auxiliary tools used to enhance the compatibility and/or in
|
||||
|
||||
As these are auxiliary, they aren't needed to enjoy MonsterMod. If you want an extra boost, feel free to install these.
|
||||
|
||||
Plugins from the `base` folder should come first, then the ones from the appropiate mod folder.
|
||||
|
||||
Once all milestones are completed, the possibility of removing the need for external plugins will be considered. Until then, this has to stay.
|
||||
|
||||
25
extra/base/README.md
Normal file
25
extra/base/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
## Base Plugins (All Mods)
|
||||
|
||||
Auxiliary Tools to use MonsterMod in any GoldSrc game.
|
||||
|
||||
These are base plugins that should be installed first before adding any mod-specific plugin.
|
||||
|
||||
### AMX Mod X Plugins
|
||||
|
||||
#### -A note about AMXX plugins-
|
||||
|
||||
All plugins in this section require AMXX 1.9.0 or greater, they will not work on 1.8.2 or older.
|
||||
|
||||
Compiled plugins are provided in the `bin` folder for your convenience. However, if you prefer to build the plugins yourself, the source code of all AMXX plugins are located in the `src` folder for compilation.
|
||||
|
||||
#### GoldSrc --> MonsterMod Use Dispatcher
|
||||
|
||||
Because MonsterMod entities are, -quite literally-, just a func_wall with its own logic, trying to trigger any MonsterMod entity from the outside will fail, as it will attempt to use the logic of game's "func_wall" instead of our own.
|
||||
|
||||
To add salt to injury, Metamod is incapable of hooking use functions, as the pfnUse/DispatchUse methods provided by the API has been deprecated, and no longer work. Leaving AMXX's HamSandwich as the only module that can hook an entity's Use() function.
|
||||
|
||||
In normal circunstances, you do not need this plugin. But let's say you have a turret monster, disabled by default, and you gave it a targetname. Even with a name, triggering this turret regardless of the method used will not activate it.
|
||||
|
||||
This plugin redirects the game's func_wall Use() function to MonsterMod, connecting the missing piece and allowing you to trigger MonsterMod entities with your shiny func_button.
|
||||
|
||||
I can't believe I've done this. *incomprehensible screams*
|
||||
BIN
extra/base/bin/glb_dispatchuse.amxx
Normal file
BIN
extra/base/bin/glb_dispatchuse.amxx
Normal file
Binary file not shown.
24
extra/base/src/glb_dispatchuse.sma
Normal file
24
extra/base/src/glb_dispatchuse.sma
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma semicolon 1
|
||||
|
||||
#include <amxmodx>
|
||||
#include <engine>
|
||||
#include <hamsandwich>
|
||||
|
||||
public plugin_init()
|
||||
{
|
||||
register_plugin( "GAME-MONSTER: Use Dispatcher", "1.0", "Giegue" );
|
||||
|
||||
RegisterHam( Ham_Use, "func_wall", "DispatchUse" );
|
||||
}
|
||||
|
||||
public DispatchUse( entity, caller, activator, useType, Float:value )
|
||||
{
|
||||
// all monstermod entities have this set
|
||||
if ( entity_get_edict( entity, EV_ENT_euser4 ) )
|
||||
{
|
||||
server_cmd( "_use %i %i %i %i %f", entity, caller, activator, useType, value );
|
||||
return HAM_SUPERCEDE;
|
||||
}
|
||||
|
||||
return HAM_IGNORED;
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "cmbase.h"
|
||||
#include "decals.h"
|
||||
|
||||
void EntvarsKeyvalue( entvars_t *pev, KeyValueData *pkvd );
|
||||
|
||||
extern Vector VecBModelOrigin( entvars_t* pevBModel );
|
||||
extern DLL_GLOBAL Vector g_vecAttackDir;
|
||||
|
||||
@@ -103,6 +105,19 @@ edict_t *CMBaseEntity::CreateEntity(char *classname)
|
||||
return pent;
|
||||
}
|
||||
|
||||
// process entvar keyvalue
|
||||
void CMBaseEntity :: KeyValue( KeyValueData* pkvd )
|
||||
{
|
||||
if ( !pev || !pkvd )
|
||||
return;
|
||||
|
||||
if ( pkvd->fHandled )
|
||||
{
|
||||
// only handled data contain readable strings
|
||||
EntvarsKeyvalue( pev, pkvd );
|
||||
}
|
||||
}
|
||||
|
||||
// give health
|
||||
int CMBaseEntity :: TakeHealth( float flHealth, int bitsDamageType )
|
||||
{
|
||||
|
||||
@@ -134,7 +134,7 @@ public:
|
||||
// initialization functions
|
||||
virtual void Spawn( void ) { return; }
|
||||
virtual void Precache( void ) { return; }
|
||||
virtual void KeyValue( KeyValueData* pkvd) { pkvd->fHandled = FALSE; }
|
||||
virtual void KeyValue( KeyValueData* pkvd );
|
||||
virtual int ObjectCaps( void ) { return FCAP_ACROSS_TRANSITION; }
|
||||
virtual void Activate( void ) {}
|
||||
|
||||
|
||||
@@ -1327,6 +1327,46 @@ void mmDispatchTouch( edict_t *pentTouched, edict_t *pentOther )
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
// pfnUse has been deprecated so the only way to trigger a monstermod
|
||||
// entity from the outside is to do it manually. ARRGHH! -Giegue
|
||||
void mmDispatchUse( void )
|
||||
{
|
||||
if ( CMD_ARGC() >= 6 ) // the command itself is an argument, we need 5. so argc == 6
|
||||
{
|
||||
edict_t *entity = INDEXENT( atoi( CMD_ARGV( 1 ) ) );
|
||||
edict_t *caller = INDEXENT( atoi( CMD_ARGV( 2 ) ) );
|
||||
edict_t *activator = INDEXENT( atoi( CMD_ARGV( 3 ) ) );
|
||||
USE_TYPE useType = USE_TYPE( atoi( CMD_ARGV( 4 ) ) );
|
||||
float flValue = atof( CMD_ARGV( 5 ) );
|
||||
|
||||
// nevermind the unoptimization that this brings... >C
|
||||
for (int index=0; index < monster_ents_used; index++)
|
||||
{
|
||||
if ((entity != NULL) && (entity == monsters[index].monster_pent))
|
||||
{
|
||||
if ( FNullEnt( caller ) ) caller = NULL;
|
||||
if ( FNullEnt( activator ) ) activator = NULL;
|
||||
|
||||
monsters[index].pMonster->Use( caller, activator, useType, flValue );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mmDispatchKeyValue( edict_t *pentKeyvalue, KeyValueData *pkvd )
|
||||
{
|
||||
for (int index=0; index < monster_ents_used; index++)
|
||||
{
|
||||
if ((pentKeyvalue != NULL) && (pentKeyvalue == monsters[index].monster_pent))
|
||||
{
|
||||
monsters[index].pMonster->KeyValue( pkvd );
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
void mmServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
|
||||
{
|
||||
@@ -1371,6 +1411,7 @@ void mmServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
|
||||
|
||||
(g_engfuncs.pfnAddServerCommand)("monster", MonsterCommand);
|
||||
(g_engfuncs.pfnAddServerCommand)("node_viewer", SpawnViewerCommand);
|
||||
(g_engfuncs.pfnAddServerCommand)("_use", mmDispatchUse);
|
||||
|
||||
for (index = 0; monster_types[index].name[0]; index++)
|
||||
{
|
||||
@@ -1531,10 +1572,10 @@ static DLL_FUNCTIONS gFunctionTable =
|
||||
mmGameDLLInit, //! pfnGameInit() Initialize the game (one-time call after loading of game .dll)
|
||||
mmDispatchSpawn, //! pfnSpawn()
|
||||
mmDispatchThink, //! pfnThink
|
||||
NULL, // pfnUse
|
||||
NULL, // pfnUse [DEPRECATED]
|
||||
mmDispatchTouch, //! pfnTouch
|
||||
NULL, // pfnBlocked
|
||||
NULL, // pfnKeyValue
|
||||
mmDispatchKeyValue, //! pfnKeyValue
|
||||
NULL, // pfnSave
|
||||
NULL, // pfnRestore
|
||||
NULL, // pfnSetAbsBox
|
||||
@@ -1631,7 +1672,7 @@ static DLL_FUNCTIONS gFunctionTable_Post =
|
||||
NULL, // pfnGameInit() Initialize the game (one-time call after loading of game .dll)
|
||||
NULL, // pfnSpawn()
|
||||
mmDispatchThink_Post, //! pfnThink
|
||||
NULL, // pfnUse
|
||||
NULL, // pfnUse [DEPRECATED]
|
||||
NULL, // pfnTouch
|
||||
NULL, // pfnBlocked
|
||||
NULL, // pfnKeyValue
|
||||
|
||||
@@ -226,6 +226,120 @@ UTIL_GroupTrace::~UTIL_GroupTrace( void )
|
||||
}
|
||||
|
||||
|
||||
TYPEDESCRIPTION gEntvarsDescription[] =
|
||||
{
|
||||
DEFINE_ENTITY_FIELD( classname, FIELD_STRING ),
|
||||
DEFINE_ENTITY_GLOBAL_FIELD( globalname, FIELD_STRING ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( origin, FIELD_POSITION_VECTOR ),
|
||||
DEFINE_ENTITY_FIELD( oldorigin, FIELD_POSITION_VECTOR ),
|
||||
DEFINE_ENTITY_FIELD( velocity, FIELD_VECTOR ),
|
||||
DEFINE_ENTITY_FIELD( basevelocity, FIELD_VECTOR ),
|
||||
DEFINE_ENTITY_FIELD( movedir, FIELD_VECTOR ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( angles, FIELD_VECTOR ),
|
||||
DEFINE_ENTITY_FIELD( avelocity, FIELD_VECTOR ),
|
||||
DEFINE_ENTITY_FIELD( punchangle, FIELD_VECTOR ),
|
||||
DEFINE_ENTITY_FIELD( v_angle, FIELD_VECTOR ),
|
||||
DEFINE_ENTITY_FIELD( fixangle, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( idealpitch, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( pitch_speed, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( ideal_yaw, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( yaw_speed, FIELD_FLOAT ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( modelindex, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_GLOBAL_FIELD( model, FIELD_MODELNAME ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( viewmodel, FIELD_MODELNAME ),
|
||||
DEFINE_ENTITY_FIELD( weaponmodel, FIELD_MODELNAME ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( absmin, FIELD_POSITION_VECTOR ),
|
||||
DEFINE_ENTITY_FIELD( absmax, FIELD_POSITION_VECTOR ),
|
||||
DEFINE_ENTITY_GLOBAL_FIELD( mins, FIELD_VECTOR ),
|
||||
DEFINE_ENTITY_GLOBAL_FIELD( maxs, FIELD_VECTOR ),
|
||||
DEFINE_ENTITY_GLOBAL_FIELD( size, FIELD_VECTOR ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( ltime, FIELD_TIME ),
|
||||
DEFINE_ENTITY_FIELD( nextthink, FIELD_TIME ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( solid, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_FIELD( movetype, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( skin, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_FIELD( body, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_FIELD( effects, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( gravity, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( friction, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( light_level, FIELD_FLOAT ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( frame, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( scale, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( sequence, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_FIELD( animtime, FIELD_TIME ),
|
||||
DEFINE_ENTITY_FIELD( framerate, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( controller, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_FIELD( blending, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( rendermode, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_FIELD( renderamt, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( rendercolor, FIELD_VECTOR ),
|
||||
DEFINE_ENTITY_FIELD( renderfx, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( health, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( frags, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( weapons, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_FIELD( takedamage, FIELD_FLOAT ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( deadflag, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( view_ofs, FIELD_VECTOR ),
|
||||
DEFINE_ENTITY_FIELD( button, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_FIELD( impulse, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( chain, FIELD_EDICT ),
|
||||
DEFINE_ENTITY_FIELD( dmg_inflictor, FIELD_EDICT ),
|
||||
DEFINE_ENTITY_FIELD( enemy, FIELD_EDICT ),
|
||||
DEFINE_ENTITY_FIELD( aiment, FIELD_EDICT ),
|
||||
DEFINE_ENTITY_FIELD( owner, FIELD_EDICT ),
|
||||
DEFINE_ENTITY_FIELD( groundentity, FIELD_EDICT ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( spawnflags, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_FIELD( flags, FIELD_FLOAT ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( colormap, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_FIELD( team, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( max_health, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( teleport_time, FIELD_TIME ),
|
||||
DEFINE_ENTITY_FIELD( armortype, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( armorvalue, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( waterlevel, FIELD_INTEGER ),
|
||||
DEFINE_ENTITY_FIELD( watertype, FIELD_INTEGER ),
|
||||
|
||||
// Having these fields be local to the individual levels makes it easier to test those levels individually.
|
||||
DEFINE_ENTITY_GLOBAL_FIELD( target, FIELD_STRING ),
|
||||
DEFINE_ENTITY_GLOBAL_FIELD( targetname, FIELD_STRING ),
|
||||
DEFINE_ENTITY_FIELD( netname, FIELD_STRING ),
|
||||
DEFINE_ENTITY_FIELD( message, FIELD_STRING ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( dmg_take, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( dmg_save, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( dmg, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( dmgtime, FIELD_TIME ),
|
||||
|
||||
DEFINE_ENTITY_FIELD( noise, FIELD_SOUNDNAME ),
|
||||
DEFINE_ENTITY_FIELD( noise1, FIELD_SOUNDNAME ),
|
||||
DEFINE_ENTITY_FIELD( noise2, FIELD_SOUNDNAME ),
|
||||
DEFINE_ENTITY_FIELD( noise3, FIELD_SOUNDNAME ),
|
||||
DEFINE_ENTITY_FIELD( speed, FIELD_FLOAT ),
|
||||
DEFINE_ENTITY_FIELD( air_finished, FIELD_TIME ),
|
||||
DEFINE_ENTITY_FIELD( pain_finished, FIELD_TIME ),
|
||||
DEFINE_ENTITY_FIELD( radsuit_finished, FIELD_TIME ),
|
||||
};
|
||||
|
||||
#define ENTVARS_COUNT (sizeof(gEntvarsDescription)/sizeof(gEntvarsDescription[0]))
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
edict_t *DBG_EntOfVars( const entvars_t *pev )
|
||||
{
|
||||
@@ -1512,6 +1626,55 @@ void UTIL_StripToken( const char *pKey, char *pDest )
|
||||
}
|
||||
|
||||
|
||||
void EntvarsKeyvalue( entvars_t *pev, KeyValueData *pkvd )
|
||||
{
|
||||
int i;
|
||||
TYPEDESCRIPTION *pField;
|
||||
|
||||
for ( i = 0; i < ENTVARS_COUNT; i++ )
|
||||
{
|
||||
pField = &gEntvarsDescription[i];
|
||||
|
||||
if ( !stricmp( pField->fieldName, pkvd->szKeyName ) )
|
||||
{
|
||||
switch( pField->fieldType )
|
||||
{
|
||||
case FIELD_MODELNAME:
|
||||
case FIELD_SOUNDNAME:
|
||||
case FIELD_STRING:
|
||||
(*(int *)((char *)pev + pField->fieldOffset)) = ALLOC_STRING( pkvd->szValue );
|
||||
break;
|
||||
|
||||
case FIELD_TIME:
|
||||
case FIELD_FLOAT:
|
||||
(*(float *)((char *)pev + pField->fieldOffset)) = atof( pkvd->szValue );
|
||||
break;
|
||||
|
||||
case FIELD_INTEGER:
|
||||
(*(int *)((char *)pev + pField->fieldOffset)) = atoi( pkvd->szValue );
|
||||
break;
|
||||
|
||||
case FIELD_POSITION_VECTOR:
|
||||
case FIELD_VECTOR:
|
||||
UTIL_StringToVector( (float *)((char *)pev + pField->fieldOffset), pkvd->szValue );
|
||||
break;
|
||||
|
||||
default:
|
||||
case FIELD_EVARS:
|
||||
case FIELD_CLASSPTR:
|
||||
case FIELD_EDICT:
|
||||
case FIELD_ENTITY:
|
||||
case FIELD_POINTER:
|
||||
ALERT( at_error, "Bad field in entity!!\n" );
|
||||
break;
|
||||
}
|
||||
pkvd->fHandled = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vector VecBModelOrigin( entvars_t* pevBModel )
|
||||
{
|
||||
return pevBModel->absmin + ( pevBModel->size * 0.5 );
|
||||
|
||||
Reference in New Issue
Block a user