diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index bfecc7267..89a1a181f 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -292,6 +292,26 @@ char *PR_VarString (progfuncs_t *progfuncs, int first) return out; } +int PR_QueryField (progfuncs_t *progfuncs, unsigned int fieldoffset, etype_t *type, char **name, evalc_t *fieldcache) +{ + fdef_t *var; + var = ED_FieldAtOfs(progfuncs, fieldoffset); + if (!var) + return false; + + if (type) + *type = var->type & ~(DEF_SAVEGLOBAL|DEF_SHARED); + if (name) + *name = var->name; + if (fieldcache) + { + fieldcache->ofs32 = var; + fieldcache->varname = var->name; + } + + return true; +} + eval_t *GetEdictFieldValue(progfuncs_t *progfuncs, struct edict_s *ed, char *name, evalc_t *cache) { fdef_t *var; @@ -312,6 +332,9 @@ eval_t *GetEdictFieldValue(progfuncs_t *progfuncs, struct edict_s *ed, char *nam return NULL; } cache->ofs32 = var; + cache->varname = var->name; + if (!ed) + return (void*)~0; //something not null return (eval_t *) &(((int*)(((edictrun_t*)ed)->fields))[var->ofs]); } if (cache->ofs32 == NULL) @@ -545,7 +568,9 @@ progfuncs_t deffuncs = { PR_AllocTempString, PR_StringToProgs, - PR_StringToNative + PR_StringToNative, + 0, + PR_QueryField }; #undef printf diff --git a/engine/qclib/progsint.h b/engine/qclib/progsint.h index c54c88be2..5b230c50e 100644 --- a/engine/qclib/progsint.h +++ b/engine/qclib/progsint.h @@ -436,6 +436,7 @@ ddef32_t *ED_FindTypeGlobalFromProgs32 (progfuncs_t *progfuncs, char *name, prog ddef16_t *ED_FindGlobalFromProgs16 (progfuncs_t *progfuncs, char *name, progsnum_t prnum); ddef32_t *ED_FindGlobalFromProgs32 (progfuncs_t *progfuncs, char *name, progsnum_t prnum); fdef_t *ED_FindField (progfuncs_t *progfuncs, char *name); +fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs); dfunction_t *ED_FindFunction (progfuncs_t *progfuncs, char *name, progsnum_t *pnum, progsnum_t fromprogs); func_t PR_FindFunc(progfuncs_t *progfncs, char *funcname, progsnum_t pnum); void PR_Configure (progfuncs_t *progfncs, int addressable_size, int max_progs); diff --git a/engine/qclib/progslib.h b/engine/qclib/progslib.h index 6b5ec959c..132c7c623 100644 --- a/engine/qclib/progslib.h +++ b/engine/qclib/progslib.h @@ -133,6 +133,8 @@ struct progfuncs_s { string_t (*StringToProgs) (progfuncs_t *prinst, char *str); char *(*StringToNative) (progfuncs_t *prinst, string_t str); int stringtablesize; + + int (*QueryField) (progfuncs_t *prinst, unsigned int fieldoffset, etype_t *type, char **name, evalc_t *fieldcache); //find info on a field definition at an offset }; typedef struct progexterns_s { diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 7ceeed709..3104d9384 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -572,57 +572,57 @@ void PR_LoadGlabalStruct(void) if (progstype == PROG_H2) { - SV_QCStat(ev_float, "level", STAT_H2_LEVEL); - SV_QCStat(ev_float, "intelligence", STAT_H2_INTELLIGENCE); - SV_QCStat(ev_float, "wisdom", STAT_H2_WISDOM); - SV_QCStat(ev_float, "strength", STAT_H2_STRENGTH); - SV_QCStat(ev_float, "dexterity", STAT_H2_DEXTERITY); - SV_QCStat(ev_float, "bluemana", STAT_H2_BLUEMANA); - SV_QCStat(ev_float, "greenmana", STAT_H2_GREENMANA); - SV_QCStat(ev_float, "experience", STAT_H2_EXPERIENCE); - SV_QCStat(ev_float, "cnt_torch", STAT_H2_CNT_TORCH); - SV_QCStat(ev_float, "cnt_h_boost", STAT_H2_CNT_H_BOOST); - SV_QCStat(ev_float, "cnt_sh_boost", STAT_H2_CNT_SH_BOOST); - SV_QCStat(ev_float, "cnt_mana_boost", STAT_H2_CNT_MANA_BOOST); - SV_QCStat(ev_float, "cnt_teleport", STAT_H2_CNT_TELEPORT); - SV_QCStat(ev_float, "cnt_tome", STAT_H2_CNT_TOME); - SV_QCStat(ev_float, "cnt_summon", STAT_H2_CNT_SUMMON); - SV_QCStat(ev_float, "cnt_invisibility", STAT_H2_CNT_INVISIBILITY); - SV_QCStat(ev_float, "cnt_glyph", STAT_H2_CNT_GLYPH); - SV_QCStat(ev_float, "cnt_haste", STAT_H2_CNT_HASTE); - SV_QCStat(ev_float, "cnt_blast", STAT_H2_CNT_BLAST); - SV_QCStat(ev_float, "cnt_polymorph", STAT_H2_CNT_POLYMORPH); - SV_QCStat(ev_float, "cnt_flight", STAT_H2_CNT_FLIGHT); - SV_QCStat(ev_float, "cnt_cubeofforce", STAT_H2_CNT_CUBEOFFORCE); - SV_QCStat(ev_float, "cnt_invincibility", STAT_H2_CNT_INVINCIBILITY); - SV_QCStat(ev_float, "artifact_active", STAT_H2_ARTIFACT_ACTIVE); - SV_QCStat(ev_float, "artifact_low", STAT_H2_ARTIFACT_LOW); - SV_QCStat(ev_float, "movetype", STAT_H2_MOVETYPE); - SV_QCStat(ev_entity, "cameramode", STAT_H2_CAMERAMODE); - SV_QCStat(ev_float, "hasted", STAT_H2_HASTED); - SV_QCStat(ev_float, "inventory", STAT_H2_INVENTORY); - SV_QCStat(ev_float, "rings_active", STAT_H2_RINGS_ACTIVE); + SV_QCStatName(ev_float, "level", STAT_H2_LEVEL); + SV_QCStatName(ev_float, "intelligence", STAT_H2_INTELLIGENCE); + SV_QCStatName(ev_float, "wisdom", STAT_H2_WISDOM); + SV_QCStatName(ev_float, "strength", STAT_H2_STRENGTH); + SV_QCStatName(ev_float, "dexterity", STAT_H2_DEXTERITY); + SV_QCStatName(ev_float, "bluemana", STAT_H2_BLUEMANA); + SV_QCStatName(ev_float, "greenmana", STAT_H2_GREENMANA); + SV_QCStatName(ev_float, "experience", STAT_H2_EXPERIENCE); + SV_QCStatName(ev_float, "cnt_torch", STAT_H2_CNT_TORCH); + SV_QCStatName(ev_float, "cnt_h_boost", STAT_H2_CNT_H_BOOST); + SV_QCStatName(ev_float, "cnt_sh_boost", STAT_H2_CNT_SH_BOOST); + SV_QCStatName(ev_float, "cnt_mana_boost", STAT_H2_CNT_MANA_BOOST); + SV_QCStatName(ev_float, "cnt_teleport", STAT_H2_CNT_TELEPORT); + SV_QCStatName(ev_float, "cnt_tome", STAT_H2_CNT_TOME); + SV_QCStatName(ev_float, "cnt_summon", STAT_H2_CNT_SUMMON); + SV_QCStatName(ev_float, "cnt_invisibility", STAT_H2_CNT_INVISIBILITY); + SV_QCStatName(ev_float, "cnt_glyph", STAT_H2_CNT_GLYPH); + SV_QCStatName(ev_float, "cnt_haste", STAT_H2_CNT_HASTE); + SV_QCStatName(ev_float, "cnt_blast", STAT_H2_CNT_BLAST); + SV_QCStatName(ev_float, "cnt_polymorph", STAT_H2_CNT_POLYMORPH); + SV_QCStatName(ev_float, "cnt_flight", STAT_H2_CNT_FLIGHT); + SV_QCStatName(ev_float, "cnt_cubeofforce", STAT_H2_CNT_CUBEOFFORCE); + SV_QCStatName(ev_float, "cnt_invincibility", STAT_H2_CNT_INVINCIBILITY); + SV_QCStatName(ev_float, "artifact_active", STAT_H2_ARTIFACT_ACTIVE); + SV_QCStatName(ev_float, "artifact_low", STAT_H2_ARTIFACT_LOW); + SV_QCStatName(ev_float, "movetype", STAT_H2_MOVETYPE); + SV_QCStatName(ev_entity, "cameramode", STAT_H2_CAMERAMODE); + SV_QCStatName(ev_float, "hasted", STAT_H2_HASTED); + SV_QCStatName(ev_float, "inventory", STAT_H2_INVENTORY); + SV_QCStatName(ev_float, "rings_active", STAT_H2_RINGS_ACTIVE); - SV_QCStat(ev_float, "rings_low", STAT_H2_RINGS_LOW); - SV_QCStat(ev_float, "armor_amulet", STAT_H2_AMULET); - SV_QCStat(ev_float, "armor_bracer", STAT_H2_BRACER); - SV_QCStat(ev_float, "armor_breastplate", STAT_H2_BREASTPLATE); - SV_QCStat(ev_float, "armor_helmet", STAT_H2_HELMET); - SV_QCStat(ev_float, "ring_flight", STAT_H2_FLIGHT_T); - SV_QCStat(ev_float, "ring_water", STAT_H2_WATER_T); - SV_QCStat(ev_float, "ring_turning", STAT_H2_TURNING_T); - SV_QCStat(ev_float, "ring_regeneration", STAT_H2_REGEN_T); - SV_QCStat(ev_string, "puzzle_inv1", STAT_H2_PUZZLE1A); - SV_QCStat(ev_string, "puzzle_inv2", STAT_H2_PUZZLE2A); - SV_QCStat(ev_string, "puzzle_inv3", STAT_H2_PUZZLE3A); - SV_QCStat(ev_string, "puzzle_inv4", STAT_H2_PUZZLE4A); - SV_QCStat(ev_string, "puzzle_inv5", STAT_H2_PUZZLE5A); - SV_QCStat(ev_string, "puzzle_inv6", STAT_H2_PUZZLE6A); - SV_QCStat(ev_string, "puzzle_inv7", STAT_H2_PUZZLE7A); - SV_QCStat(ev_string, "puzzle_inv8", STAT_H2_PUZZLE8A); - SV_QCStat(ev_float, "max_health", STAT_H2_MAXHEALTH); - SV_QCStat(ev_float, "max_mana", STAT_H2_MAXMANA); - SV_QCStat(ev_float, "flags", STAT_H2_FLAGS); + SV_QCStatName(ev_float, "rings_low", STAT_H2_RINGS_LOW); + SV_QCStatName(ev_float, "armor_amulet", STAT_H2_AMULET); + SV_QCStatName(ev_float, "armor_bracer", STAT_H2_BRACER); + SV_QCStatName(ev_float, "armor_breastplate", STAT_H2_BREASTPLATE); + SV_QCStatName(ev_float, "armor_helmet", STAT_H2_HELMET); + SV_QCStatName(ev_float, "ring_flight", STAT_H2_FLIGHT_T); + SV_QCStatName(ev_float, "ring_water", STAT_H2_WATER_T); + SV_QCStatName(ev_float, "ring_turning", STAT_H2_TURNING_T); + SV_QCStatName(ev_float, "ring_regeneration", STAT_H2_REGEN_T); + SV_QCStatName(ev_string, "puzzle_inv1", STAT_H2_PUZZLE1A); + SV_QCStatName(ev_string, "puzzle_inv2", STAT_H2_PUZZLE2A); + SV_QCStatName(ev_string, "puzzle_inv3", STAT_H2_PUZZLE3A); + SV_QCStatName(ev_string, "puzzle_inv4", STAT_H2_PUZZLE4A); + SV_QCStatName(ev_string, "puzzle_inv5", STAT_H2_PUZZLE5A); + SV_QCStatName(ev_string, "puzzle_inv6", STAT_H2_PUZZLE6A); + SV_QCStatName(ev_string, "puzzle_inv7", STAT_H2_PUZZLE7A); + SV_QCStatName(ev_string, "puzzle_inv8", STAT_H2_PUZZLE8A); + SV_QCStatName(ev_float, "max_health", STAT_H2_MAXHEALTH); + SV_QCStatName(ev_float, "max_mana", STAT_H2_MAXMANA); + SV_QCStatName(ev_float, "flags", STAT_H2_FLAGS); } } @@ -9079,10 +9079,16 @@ void PF_gettaginfo(progfuncs_t *prinst, struct globalvars_s *pr_globals) VectorCopy((result+8), axis[2]); } +//the first implementation of this function was (float type, float num, string name) +//it is now float num, float type, .field void PF_clientstat(progfuncs_t *prinst, struct globalvars_s *pr_globals) { +#if 0 //this is the old code char *name = PF_VarString(prinst, 2, pr_globals); - SV_QCStat(G_FLOAT(OFS_PARM0), name, G_FLOAT(OFS_PARM1)); + SV_QCStatName(G_FLOAT(OFS_PARM0), name, G_FLOAT(OFS_PARM1)); +#else + SV_QCStatFieldIdx(G_FLOAT(OFS_PARM1), G_INT(OFS_PARM2)+prinst->fieldadjust, G_FLOAT(OFS_PARM0)); +#endif } void PF_runclientphys(progfuncs_t *prinst, struct globalvars_s *pr_globals) diff --git a/engine/server/server.h b/engine/server/server.h index e98cbaade..2b07d9ac9 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -997,7 +997,8 @@ void SV_SetMoveVars(void); // sv_send.c // qboolean SV_ChallengePasses(int challenge); -void SV_QCStat(int type, char *name, int statnum); +void SV_QCStatName(int type, char *name, int statnum); +void SV_QCStatFieldIdx(int type, unsigned int fieldindex, int statnum); void SV_ClearQCStats(void); void SV_SendClientMessages (void); diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 789685e24..98486e8d0 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -1179,7 +1179,7 @@ typedef struct { } qcstat_t; qcstat_t qcstats[MAX_CL_STATS-32]; int numqcstats; -void SV_QCStat(int type, char *name, int statnum) +void SV_QCStatEval(int type, char *name, evalc_t *cache, int statnum) { int i; if (numqcstats == sizeof(qcstats)/sizeof(qcstats[0])) @@ -1194,12 +1194,42 @@ void SV_QCStat(int type, char *name, int statnum) break; } if (i == numqcstats) + { + if (i == sizeof(qcstats)/sizeof(qcstats[0])) + { + Con_Printf("Too many stats specified for csqc\n"); + return; + } numqcstats++; + } qcstats[i].type = type; qcstats[i].statnum = statnum; Q_strncpyz(qcstats[i].name, name, sizeof(qcstats[i].name)); - memset(&qcstats[i].evalc, 0, sizeof(evalc_t)); + memcpy(&qcstats[i].evalc, cache, sizeof(evalc_t)); +} + +void SV_QCStatName(int type, char *name, int statnum) +{ + evalc_t cache; + if (!svprogfuncs->GetEdictFieldValue(svprogfuncs, NULL, name, &cache)) + return; + + SV_QCStatEval(type, name, &cache, statnum); +} + +void SV_QCStatFieldIdx(int type, unsigned int fieldindex, int statnum) +{ + evalc_t cache; + char *name; + etype_t ftype; + + if (!svprogfuncs->QueryField(svprogfuncs, fieldindex, &ftype, &name, &cache)) + { + Con_Printf("invalid field for csqc stat\n"); + return; + } + SV_QCStatEval(type, name, &cache, statnum); } void SV_ClearQCStats(void) @@ -1216,6 +1246,8 @@ void SV_UpdateQCStats(edict_t *ent, int *stats) { eval_t *eval; eval = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, qcstats[i].name, &qcstats[i].evalc); + if (!eval) + continue; switch(qcstats[i].type) {