From c15a86b45472c4cb31956100353406ad2649eb0f Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 20 Mar 2006 18:08:51 +0000 Subject: [PATCH] added new TR/KVD stuffs --- dlls/fakemeta/CString.h | 413 +++++++++++++++++++++++++++++ dlls/fakemeta/fakemeta.vcproj | 3 + dlls/fakemeta/fakemeta_amxx.cpp | 6 + dlls/fakemeta/fm_tr.cpp | 88 +----- dlls/fakemeta/fm_tr.h | 24 +- dlls/fakemeta/fm_tr2.cpp | 308 +++++++++++++++++++++ dlls/fakemeta/forward.cpp | 16 +- plugins/include/fakemeta.inc | 15 ++ plugins/include/fakemeta_const.inc | 13 +- 9 files changed, 789 insertions(+), 97 deletions(-) create mode 100755 dlls/fakemeta/CString.h create mode 100644 dlls/fakemeta/fm_tr2.cpp diff --git a/dlls/fakemeta/CString.h b/dlls/fakemeta/CString.h new file mode 100755 index 00000000..3f9d6531 --- /dev/null +++ b/dlls/fakemeta/CString.h @@ -0,0 +1,413 @@ +/* AMX Mod X +* +* by the AMX Mod X Development Team +* originally developed by OLO +* +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at +* your option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +* In addition, as a special exception, the author gives permission to +* link the code of this program with the Half-Life Game Engine ("HL +* Engine") and Modified Game Libraries ("MODs") developed by Valve, +* L.L.C ("Valve"). You must obey the GNU General Public License in all +* respects for all of the code used other than the HL Engine and MODs +* from Valve. If you modify this file, you may extend this exception +* to your version of the file, but you are not obligated to do so. If +* you do not wish to do so, delete this exception statement from your +* version. +*/ + +#ifndef _INCLUDE_CSTRING_H +#define _INCLUDE_CSTRING_H + +#include +#include + +//by David "BAILOPAN" Anderson +class String +{ +public: + String() + { + v = NULL; + a_size = 0; + //assign(""); + } + + ~String() + { + if (v) + delete [] v; + } + + String(const char *src) + { + v = NULL; + a_size = 0; + assign(src); + } + + const char * _fread(FILE *fp) + { + Grow(512, false); + char *ret = fgets(v, 511, fp); + return ret; + } + + String(const String &src) + { + v = NULL; + a_size = 0; + assign(src.c_str()); + } + + const char *c_str() { return v?v:""; } + + const char *c_str() const { return v?v:""; } + + void append(const char *t) + { + Grow(size() + strlen(t) + 1); + strcat(v, t); + } + + void append(const char c) + { + size_t len = size(); + Grow(len + 2); + v[len] = c; + v[len + 1] = '\0'; + } + + void append(String &d) + { + append(d.c_str()); + } + + void assign(const String &src) + { + assign(src.c_str()); + } + + void assign(const char *d) + { + if (!d) + { + clear(); + } else { + size_t len = strlen(d); + Grow(len + 1, false); + memcpy(v, d, len); + v[len] = '\0'; + } + } + + void clear() + { + if (v) + v[0] = '\0'; + } + + int compare (const char *d) const + { + if (!v) + return strcmp("", d); + else + return strcmp(v, d); + } + + //Added this for amxx inclusion + bool empty() + { + if (!v) + return true; + + if (v[0] == '\0') + return true; + + return false; + } + + size_t size() + { + if (v) + return strlen(v); + else + return 0; + } + + int find(const char c, int index = 0) + { + int len = static_cast(size()); + if (len < 1) + return npos; + if (index >= len || index < 0) + return npos; + int i = 0; + for (i=index; i=0; i--) + { + if (!is_space(v[i]) + || (is_space(v[i]) && i==0)) + { + erase(i+1, j); + break; + } + j++; + } + } + + if (len == 1) + { + if (is_space(v[0])) + { + clear(); + return; + } + } + } + + void erase(unsigned int start, int num = npos) + { + if (!v) + return; + unsigned int i = 0; + size_t len = size(); + //check for bounds + if (num == npos || start+num > len-start) + num = len - start; + //do the erasing + bool copyflag = false; + for (i=0; i=start && i= len || !v) + return ns; + + if (num == npos) + { + num = len - index; + } else if (index+num >= len) { + num = len - index; + } + + unsigned int i = 0; + unsigned int nslen = num + 2; + + ns.Grow(nslen); + + for (i=index; i= 65 && v[i] <= 90) + v[i] &= ~(1<<5); + } + } + + String & operator = (const String &src) + { + assign(src); + return *this; + } + + String & operator = (const char *src) + { + assign(src); + return *this; + + } + + char operator [] (unsigned int index) + { + if (index > size() || !v) + { + return -1; + } else { + return v[index]; + } + } + + int at(int a) + { + if (a < 0 || a >= (int)size() || !v) + return -1; + + return v[a]; + } + + bool at(int at, char c) + { + if (at < 0 || at >= (int)size() || !v) + return false; + + v[at] = c; + + return true; + } + +private: + void Grow(unsigned int d, bool copy=true) + { + if (d <= a_size) + return; + char *n = new char[d + 1]; + if (copy && v) + strcpy(n, v); + if (v) + delete [] v; + else + strcpy(n, ""); + v = n; + a_size = d + 1; + } + + char *v; + unsigned int a_size; +public: + static const int npos = -1; +}; + +#endif //_INCLUDE_CSTRING_H diff --git a/dlls/fakemeta/fakemeta.vcproj b/dlls/fakemeta/fakemeta.vcproj index ebc71216..3f382a3b 100755 --- a/dlls/fakemeta/fakemeta.vcproj +++ b/dlls/fakemeta/fakemeta.vcproj @@ -129,6 +129,9 @@ + + diff --git a/dlls/fakemeta/fakemeta_amxx.cpp b/dlls/fakemeta/fakemeta_amxx.cpp index 4097c4cf..a82def60 100755 --- a/dlls/fakemeta/fakemeta_amxx.cpp +++ b/dlls/fakemeta/fakemeta_amxx.cpp @@ -13,7 +13,13 @@ void OnAmxxAttach() MF_AddNatives(pdata_natives); MF_AddNatives(tr_Natives); MF_AddNatives(glb_natives); + MF_AddNatives(ext2_natives); + g_kvd_2.szClassName = ""; + g_kvd_2.szKeyName = ""; + g_kvd_2.szValue = ""; + g_kvd_glb.kvd = &g_kvd_2; } + int GetHullBounds(int hullnumber, float *mins, float *maxs); // sawce: Do not null out the forward for ServerActivate. It's required for the INDEXENT() fix. (I don't think ServerActivate is planned on being forwarded anyway) void ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) diff --git a/dlls/fakemeta/fm_tr.cpp b/dlls/fakemeta/fm_tr.cpp index 69a8c46a..96607fc6 100755 --- a/dlls/fakemeta/fm_tr.cpp +++ b/dlls/fakemeta/fm_tr.cpp @@ -159,94 +159,12 @@ static cell AMX_NATIVE_CALL get_tr(AMX *amx, cell *params) } } -// native set_kv(TraceResult:tr_member, {Float,_}:...); -static cell AMX_NATIVE_CALL set_kv(AMX *amx, cell *params) +AMX_NATIVE_INFO tr_Natives[] = { - - - //if (*params / sizeof(cell) < 2) - //return 0; //TODO: Error - - //cell *ptr = MF_GetAmxAddr(amx, params[2]); - //edict_t *e = 0; - - switch (params[1]) - { - case KV_ClassName: - { - int len; - g_fm_keyValueData->szClassName = MF_GetAmxString(amx, params[2], 0, &len); - return 1; - } - case KV_KeyName: - { - int len; - g_fm_keyValueData->szKeyName = MF_GetAmxString(amx, params[2], 0, &len); - return 1; - } - case KV_Value: - { - int len; - g_fm_keyValueData->szValue = MF_GetAmxString(amx, params[2], 0, &len); - return 1; - } - case KV_fHandled: - { - g_fm_keyValueData->fHandled = params[2]; - return 1; - } - default: - { - //TODO: error - return 0; - } - } -} - -static cell AMX_NATIVE_CALL get_kv(AMX *amx, cell *params) -{ - int type = params[1]; - cell *ptr = 0; - const char *szRet = ""; - - switch (type) - { - case KV_ClassName: - { - if (g_fm_keyValueData->szClassName) - szRet = g_fm_keyValueData->szClassName; - break; - } - case KV_KeyName: - { - if (g_fm_keyValueData->szKeyName) - szRet = g_fm_keyValueData->szKeyName; - break; - } - case KV_Value: - { - if (g_fm_keyValueData->szValue) - szRet = g_fm_keyValueData->szValue; - break; - } - case KV_fHandled: { - return g_fm_keyValueData->fHandled; - } - default: - { - //TODO: error - return 0; - } - } - - return MF_SetAmxString(amx, params[2], szRet, params[3]); -} - -AMX_NATIVE_INFO tr_Natives[] = { {"get_tr", get_tr}, {"set_tr", set_tr}, - {"get_kv", get_kv}, - {"set_kv", set_kv}, {NULL, NULL}, }; + + diff --git a/dlls/fakemeta/fm_tr.h b/dlls/fakemeta/fm_tr.h index 7e19767e..ed6a8492 100755 --- a/dlls/fakemeta/fm_tr.h +++ b/dlls/fakemeta/fm_tr.h @@ -1,12 +1,29 @@ #ifndef _INCLUDE_TR_H #define _INCLUDE_TR_H +#include "CString.h" + extern TraceResult *gfm_tr; -extern KeyValueData *g_fm_keyValueData; // JGHG: Yeah yeah I know this doesn't fit in here. Then again, neither does gaben. + +//these also don't fit in here but gaben does not care. GABEN DOES NOT CARE!!! +extern TraceResult g_tr_2; +extern KeyValueData g_kvd_2; + +struct KVD_Wrapper +{ + KeyValueData *kvd; + String cls; + String key; + String val; +}; + +extern KVD_Wrapper g_kvd_glb; +extern KVD_Wrapper g_kvd_hook; + enum { TR_AllSolid, - TR_StartSolid, + TR_StartSolid, TR_InOpen, TR_InWater, TR_flFraction, @@ -20,12 +37,13 @@ enum enum KeyValue { KV_ClassName, - KV_KeyName, + KV_KeyName, KV_Value, KV_fHandled }; extern AMX_NATIVE_INFO tr_Natives[]; +extern AMX_NATIVE_INFO ext2_natives[]; #endif //_INCLUDE_TR_H diff --git a/dlls/fakemeta/fm_tr2.cpp b/dlls/fakemeta/fm_tr2.cpp new file mode 100644 index 00000000..03eaf853 --- /dev/null +++ b/dlls/fakemeta/fm_tr2.cpp @@ -0,0 +1,308 @@ +#include "fakemeta_amxx.h" + +TraceResult g_tr_2; +KeyValueData g_kvd_2; + +KVD_Wrapper g_kvd_glb; + +static cell AMX_NATIVE_CALL set_tr2(AMX *amx, cell *params) +{ + TraceResult *tr; + if (params[1] == 0) + tr = &g_tr_2; + else + tr = reinterpret_cast(params[1]); + + if (*params / sizeof(cell) < 3) + { + MF_LogError(amx, AMX_ERR_NATIVE, "No data passed"); + return 0; + } + + cell *ptr = MF_GetAmxAddr(amx, params[3]); + + switch (params[2]) + { + case TR_AllSolid: + { + tr->fAllSolid = *ptr; + return 1; + break; + } + case TR_InOpen: + { + tr->fInOpen = *ptr; + return 1; + break; + } + case TR_StartSolid: + { + tr->fStartSolid = *ptr; + return 1; + break; + } + case TR_InWater: + { + tr->fInWater = *ptr; + return 1; + break; + } + case TR_flFraction: + { + tr->flFraction = amx_ctof(*ptr); + return 1; + break; + } + case TR_vecEndPos: + { + tr->vecEndPos.x = amx_ctof(ptr[0]); + tr->vecEndPos.y = amx_ctof(ptr[1]); + tr->vecEndPos.z = amx_ctof(ptr[2]); + return 1; + break; + } + case TR_flPlaneDist: + { + tr->flPlaneDist = amx_ctof(*ptr); + return 1; + break; + } + case TR_vecPlaneNormal: + { + tr->vecPlaneNormal.x = amx_ctof(ptr[0]); + tr->vecPlaneNormal.y = amx_ctof(ptr[1]); + tr->vecPlaneNormal.z = amx_ctof(ptr[2]); + return 1; + break; + } + case TR_pHit: + { + edict_t *e = INDEXENT(*ptr); + if (!e || FNullEnt(e)) + return 0; //TODO: return error + tr->pHit = e; + return 1; + break; + } + case TR_iHitgroup: + { + tr->iHitgroup = *ptr; + return 1; + break; + } + default: + { + MF_LogError(amx, AMX_ERR_NATIVE, "Unknown traceresult member %d", params[2]); + return 0; + } + } + + return 0; +} + +static cell AMX_NATIVE_CALL get_tr2(AMX *amx, cell *params) +{ + TraceResult *tr; + if (params[1] == 0) + tr = &g_tr_2; + else + tr = reinterpret_cast(params[1]); + + cell *ptr; + + switch (params[2]) + { + case TR_AllSolid: + { + return tr->fAllSolid; + break; + } + case TR_InOpen: + { + return tr->fInOpen; + break; + } + case TR_StartSolid: + { + return tr->fStartSolid; + break; + } + case TR_InWater: + { + return tr->fInWater; + break; + } + case TR_flFraction: + { + ptr = MF_GetAmxAddr(amx, params[3]); + *ptr = amx_ftoc(tr->flFraction); + return 1; + break; + } + case TR_vecEndPos: + { + ptr = MF_GetAmxAddr(amx, params[3]); + ptr[0] = amx_ftoc(tr->vecEndPos.x); + ptr[1] = amx_ftoc(tr->vecEndPos.y); + ptr[2] = amx_ftoc(tr->vecEndPos.z); + return 1; + break; + } + case TR_flPlaneDist: + { + ptr = MF_GetAmxAddr(amx, params[3]); + *ptr = amx_ftoc(tr->flPlaneDist); + return 1; + break; + } + case TR_vecPlaneNormal: + { + ptr = MF_GetAmxAddr(amx, params[3]); + ptr[0] = amx_ftoc(tr->vecPlaneNormal.x); + ptr[1] = amx_ftoc(tr->vecPlaneNormal.y); + ptr[2] = amx_ftoc(tr->vecPlaneNormal.z); + return 1; + break; + } + case TR_pHit: + { + if (gfm_tr->pHit == NULL || FNullEnt(gfm_tr->pHit)) + return -1; + return ENTINDEX(tr->pHit); + break; + } + case TR_iHitgroup: + { + return tr->iHitgroup; + break; + } + default: + { + MF_LogError(amx, AMX_ERR_NATIVE, "Unknown traceresult member %d", params[2]); + return 0; + } + } + + return 0; +} + +static cell AMX_NATIVE_CALL get_kvd(AMX *amx, cell *params) +{ + KVD_Wrapper *kvdw; + KeyValueData *kvd; + if (params[1] == 0) + kvdw = &g_kvd_glb; + else + kvdw = reinterpret_cast(params[1]); + kvd = kvdw->kvd; + + switch (params[2]) + { + case KV_fHandled: + { + return kvd->fHandled; + break; + } + case KV_ClassName: + { + if (params[0] / sizeof(cell) != 4) + { + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid number of parameters passed"); + return 0; + } + cell *ptr = MF_GetAmxAddr(amx, params[4]); + return MF_SetAmxString(amx, params[3], kvd->szClassName, (int)*ptr); + break; + } + case KV_KeyName: + { + if (params[0] / sizeof(cell) != 4) + { + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid number of parameters passed"); + return 0; + } + cell *ptr = MF_GetAmxAddr(amx, params[4]); + return MF_SetAmxString(amx, params[3], kvd->szKeyName, (int)*ptr); + break; + } + case KV_Value: + { + if (params[0] / sizeof(cell) != 4) + { + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid number of parameters passed"); + return 0; + } + cell *ptr = MF_GetAmxAddr(amx, params[4]); + return MF_SetAmxString(amx, params[3], kvd->szValue, (int)*ptr); + break; + } + } + + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid KeyValueData member: %d", params[2]); + + return 0; +} + +static cell AMX_NATIVE_CALL set_kvd(AMX *amx, cell *params) +{ + KVD_Wrapper *kvdw; + KeyValueData *kvd; + if (params[1] == 0) + kvdw = &g_kvd_glb; + else + kvdw = reinterpret_cast(params[1]); + kvd = kvdw->kvd; + + if (*params / sizeof(cell) < 3) + { + MF_LogError(amx, AMX_ERR_NATIVE, "No data passed"); + return 0; + } + + cell *ptr = MF_GetAmxAddr(amx, params[3]); + int len; + + switch (params[2]) + { + case KV_fHandled: + { + kvd->fHandled = (int)*ptr; + return 1; + break; + } + case KV_ClassName: + { + kvdw->cls.assign(MF_GetAmxString(amx, params[1], 0, &len)); + kvd->szClassName = const_cast(kvdw->cls.c_str()); + return 1; + break; + } + case KV_KeyName: + { + kvdw->key.assign(MF_GetAmxString(amx, params[1], 0, &len)); + kvd->szKeyName = const_cast(kvdw->key.c_str()); + return 1; + break; + } + case KV_Value: + { + kvdw->val.assign(MF_GetAmxString(amx, params[1], 0, &len)); + kvd->szValue = const_cast(kvdw->val.c_str()); + return 1; + break; + } + } + + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid KeyValueData member: %d", params[2]); + + return 0; +} + +AMX_NATIVE_INFO ext2_natives[] = +{ + {"get_tr2", get_tr2}, + {"set_tr2", set_tr2}, + {"get_kvd", get_kvd}, + {NULL, NULL}, +}; + diff --git a/dlls/fakemeta/forward.cpp b/dlls/fakemeta/forward.cpp index 7f913651..4d4cfc57 100755 --- a/dlls/fakemeta/forward.cpp +++ b/dlls/fakemeta/forward.cpp @@ -11,6 +11,7 @@ const char *mStringResult; const char *mlStringResult; int retType = 0; int lastFmRes = FMRES_IGNORED; +KVD_Wrapper g_kvd_hook; #include "forwardmacros.h" @@ -98,7 +99,7 @@ void TraceLine(const float *v1, const float *v2, int fNoMonsters, edict_t *pentT gfm_tr=ptr; PREPARE_VECTOR(v1); PREPARE_VECTOR(v2); - FM_ENG_HANDLE(FM_TraceLine, (Engine[FM_TraceLine].at(i), p_v1, p_v2, fNoMonsters, ENTINDEX(pentToSkip) /*, (cell)ptr*/)); + FM_ENG_HANDLE(FM_TraceLine, (Engine[FM_TraceLine].at(i), p_v1, p_v2, fNoMonsters, ENTINDEX(pentToSkip) , (cell)ptr)); RETURN_META(mswi(lastFmRes)); } @@ -107,7 +108,7 @@ void TraceLine_post(const float *v1, const float *v2, int fNoMonsters, edict_t * gfm_tr=ptr; PREPARE_VECTOR(v1); PREPARE_VECTOR(v2); - FM_ENG_HANDLE_POST(FM_TraceLine, (EnginePost[FM_TraceLine].at(i), p_v1, p_v2, fNoMonsters, ENTINDEX(pentToSkip)/*, (cell)ptr*/)); + FM_ENG_HANDLE_POST(FM_TraceLine, (EnginePost[FM_TraceLine].at(i), p_v1, p_v2, fNoMonsters, ENTINDEX(pentToSkip), (cell)ptr)); RETURN_META(MRES_IGNORED); } @@ -124,14 +125,15 @@ typedef struct KeyValueData_s */ void KeyValue(edict_t* entity, KeyValueData* data) { - g_fm_keyValueData = data; - FM_ENG_HANDLE(FM_KeyValue, (Engine[FM_KeyValue].at(i), ENTINDEX(entity))); + g_kvd_hook.kvd = data; + FM_ENG_HANDLE(FM_KeyValue, (Engine[FM_KeyValue].at(i), ENTINDEX(entity), (cell)(&g_kvd_hook))); RETURN_META(mswi(lastFmRes)); } void KeyValue_post(edict_t* entity, KeyValueData* data) { - FM_ENG_HANDLE_POST(FM_KeyValue, (EnginePost[FM_KeyValue].at(i), ENTINDEX(entity))); + g_kvd_hook.kvd = data; + FM_ENG_HANDLE_POST(FM_KeyValue, (EnginePost[FM_KeyValue].at(i), ENTINDEX(entity), (cell)(&g_kvd_hook))); RETURN_META(MRES_IGNORED); } @@ -684,7 +686,7 @@ static cell AMX_NATIVE_CALL register_forward(AMX *amx, cell *params) ENGHOOK(EmitAmbientSound); break; case FM_TraceLine: - fId = MF_RegisterSPForwardByName(amx, funcname, FP_ARRAY, FP_ARRAY, FP_CELL, FP_CELL, FP_DONE); + fId = MF_RegisterSPForwardByName(amx, funcname, FP_ARRAY, FP_ARRAY, FP_CELL, FP_CELL, FP_CELL, FP_DONE); ENGHOOK(TraceLine); break; case FM_TraceToss: @@ -1004,7 +1006,7 @@ static cell AMX_NATIVE_CALL register_forward(AMX *amx, cell *params) //DLLFunc_KeyValue, // void ) ( edict_t *pentKeyvalue, KeyValueData *pkvd ); case FM_KeyValue: //fId = MF_RegisterSPForwardByName(amx, funcname, FP_CELL, FP_STRING, FP_STRING, FP_STRING, FP_CELL, FP_DONE); - fId = MF_RegisterSPForwardByName(amx, funcname, FP_CELL, FP_DONE); + fId = MF_RegisterSPForwardByName(amx, funcname, FP_CELL, FP_CELL, FP_DONE); DLLHOOK(KeyValue); break; //DLLFunc_SetAbsBox, // void ) ( edict_t *pent ); diff --git a/plugins/include/fakemeta.inc b/plugins/include/fakemeta.inc index dce96487..a0f7b84e 100755 --- a/plugins/include/fakemeta.inc +++ b/plugins/include/fakemeta.inc @@ -61,6 +61,21 @@ native dllfunc(type,{Float,Sql,Result,_}:...); native get_tr(TraceResult:tr_member, {Float,_}:...); native set_tr(TraceResult:tr_member, {Float,_}:...); +//Upgraded version takes in a TraceResult handle, optionally passed in as the last parameter to the +//TraceResult forward. Use 0 to specify the global traceresult handle set from calling +// some of the Engfucs. +native get_tr2(tr_handle, TraceResult:tr_member, {Float,_}:...); +native set_tr2(tr_handle, TraceResult:tr_member, {Float,_}:...); + +//Same as above, use either a kvd_handle or 0 for global reserved kvd data +//kvd_handle is passed by the kvd hook, last param +native get_kvd(kvd_handle, KeyValueData:member, {Float,_}:...); + +//Using set_kvd with the handle from the hook for anything under KV_fHandled +// is considered an undefined operation (it could crash). You should fire a new +// keyvalues structure rather than changing the internal engine strings. +native set_kvd(kvd_handle, KeyValueData:member, {Float,_}:...); + //NOTE that for the string offsets below, on AMD64, a byref (char **) offset is NOT the same as an int offset //In fact it's QWORD aligned rather than DWORD aligned, so the offset will be exactly half. //Gets a string from a private offset. If byref is false, the string is treated as static rather than dynamic. diff --git a/plugins/include/fakemeta_const.inc b/plugins/include/fakemeta_const.inc index 77a55257..836b72a6 100755 --- a/plugins/include/fakemeta_const.inc +++ b/plugins/include/fakemeta_const.inc @@ -496,7 +496,7 @@ enum { enum TraceResult { TR_AllSolid, - TR_StartSolid, + TR_StartSolid, TR_InOpen, TR_InWater, TR_flFraction, @@ -505,4 +505,13 @@ enum TraceResult TR_vecPlaneNormal, TR_pHit, TR_iHitgroup, -}; \ No newline at end of file +}; + +enum KeyValueData +{ + KV_ClassName, + KV_KeyName, + KV_Value, + KV_fHandled +}; +