Handle entvar keyvalues.

This commit is contained in:
Giegue
2023-03-06 20:02:04 -03:00
parent 73f240ddb1
commit bd9fe1f487
9 changed files with 274 additions and 6 deletions

View File

@@ -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 )
{

View File

@@ -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 ) {}

View File

@@ -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

View File

@@ -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 );