diff --git a/src/component/test.cpp b/src/component/test.cpp index a3db37b..55949f2 100644 --- a/src/component/test.cpp +++ b/src/component/test.cpp @@ -2,6 +2,7 @@ #include "loader/component_loader.hpp" #include "scheduler.hpp" +#include "gsc.hpp" #include #include @@ -186,6 +187,23 @@ namespace test //printf("Biggie Spam McCheese\n"); }); + gsc::function::add("getarraytest", []() + { + auto parent_id = game::Scr_GetObject(0, game::SCRIPTINSTANCE_SERVER).pointerValue; + + auto script_array_size = GetArraySize(game::SCRIPTINSTANCE_SERVER, parent_id); + for (auto i = 0u; i < script_array_size; ++i) + { + auto id = game::GetArrayVariable(game::SCRIPTINSTANCE_SERVER, parent_id, i); + auto entry_value = &game::gScrVarGlob[0].childVariables[id]; + if ((entry_value->w.type & 0x1F) != game::VAR_STRING) + { + game::Scr_Error(utils::string::va("index %d in array is not a string", i), game::SCRIPTINSTANCE_SERVER, false); + } + printf("%s\n", game::SL_ConvertToString(game::SCRIPTINSTANCE_SERVER, entry_value->u.u.stringValue)); + } + }); + gscr_spawn_hook.create(0x517630, gscr_spawn_stub); //Disable AI print spam diff --git a/src/game/game.cpp b/src/game/game.cpp index 55c641f..13770ce 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -3,6 +3,7 @@ #include #include +#include namespace game { @@ -460,6 +461,23 @@ namespace game } } + unsigned int GetArrayVariableIndex(unsigned int unsignedValue, scriptInstance_t inst, unsigned int parentId, void* call_addr) + { + unsigned int answer; + + __asm + { + push parentId; + push inst; + mov eax, unsignedValue; + call call_addr; + mov answer, eax; + add esp, 0x8; + } + + return answer; + } + unsigned int Scr_GetNumParam(scriptInstance_t inst) { return gScrVmPub[inst].outparamcount; @@ -786,6 +804,39 @@ namespace game return dist; } + VariableUnion Scr_GetObject(unsigned int index, scriptInstance_t inst) + { + const char* v3; // eax + const char* v4; // eax + VariableValue* value; // [esp+0h] [ebp-4h] + + if (index < gScrVmPub[inst].outparamcount) + { + value = &gScrVmPub[inst].top[-index]; + if (value->type == VAR_BEGIN_REF) + return value->u; + gScrVarPub[inst].error_index = index + 1; + v3 = utils::string::va("type %s is not an object", var_typename[value->type]); + Scr_Error(v3, inst, 0); + } + v4 = utils::string::va("parameter %d does not exist", index + 1); + Scr_Error(v4, inst, 0); + return value->u; + } + + unsigned int GetArraySize(scriptInstance_t inst, unsigned int id) + { + VariableValueInternal* entryValue; // [esp+0h] [ebp-4h] + + entryValue = &gScrVarGlob[inst].parentVariables[id + 1]; + return entryValue->u.o.u.size; + } + + unsigned int GetArrayVariable(scriptInstance_t inst, unsigned int parentId, unsigned int unsignedValue) + { + return gScrVarGlob[inst].childVariables[GetArrayVariableIndex(unsignedValue, inst, parentId)].hash.id; + } + void Sentient_GetVelocity(sentient_s* self, float* vVelOut) { static const auto call_addr = SELECT(0x0, 0x5662A0); diff --git a/src/game/game.hpp b/src/game/game.hpp index b5b994e..44d59a9 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -68,6 +68,9 @@ namespace game __inline void* Scr_NotifyNum() { return CALL_ADDR(0x0, 0x698CC0); } void Scr_NotifyNum(scriptInstance_t inst, int entNum, int entClass, unsigned int notifStr, int numParams, void* call_addr = Scr_NotifyNum()); + __inline void* GetArrayVariableIndex() { return CALL_ADDR(0x0, 0x6902A0); } + unsigned int GetArrayVariableIndex(unsigned int unsignedValue, scriptInstance_t inst, unsigned int parentId, void* call_addr = GetArrayVariableIndex()); + unsigned int Scr_GetNumParam(scriptInstance_t inst); VariableType Scr_GetType(scriptInstance_t inst, unsigned int index); void Scr_Error(const char* err, scriptInstance_t inst, bool is_terminal); @@ -93,6 +96,9 @@ namespace game float Path_GetPathDir(float* delta, const float* vFrom, const float* vTo); float Vec3DistanceSq(const float* p1, const float* p2); float EvaluateHeuristic(CustomSearchInfo_FindPath* searchInfo, pathnode_t* pSuccessor, const float* vGoalPos); + VariableUnion Scr_GetObject(unsigned int index, scriptInstance_t inst); + unsigned int GetArraySize(scriptInstance_t inst, unsigned int id); + unsigned int GetArrayVariable(scriptInstance_t inst, unsigned int parentId, unsigned int unsignedValue); void Sentient_GetVelocity(sentient_s* self, float* vVelOut); diff --git a/src/game/structs.hpp b/src/game/structs.hpp index 1f69aec..b97648a 100644 --- a/src/game/structs.hpp +++ b/src/game/structs.hpp @@ -2122,6 +2122,18 @@ namespace game VAR_TOTAL_COUNT = 0x1B, }; + /* 977 */ + struct VariableStackBuffer + { + char* pos; + unsigned __int16 size; + unsigned __int16 bufLen; + unsigned __int16 localId; + unsigned __int8 time; + char buf[1]; + }; + + /* 234 */ union VariableUnion { int intValue; @@ -2130,7 +2142,7 @@ namespace game const float* vectorValue; const char* codePosValue; unsigned int pointerValue; - char* stackValue; + VariableStackBuffer* stackValue; unsigned int entityOffset; }; @@ -2172,6 +2184,129 @@ namespace game VariableValue stack[2048]; }; + /* 1143 */ + union Variable_u + { + unsigned __int16 prev; + unsigned __int16 prevSibling; + }; + + /* 1144 */ + struct Variable + { + unsigned __int16 id; + Variable_u u; + }; + + /* 1145 */ + union ObjectInfo_u + { + unsigned __int16 entnum; + unsigned __int16 size; + unsigned __int16 nextEntId; + unsigned __int16 self; + }; + + /* 1146 */ + struct ObjectInfo + { + unsigned __int16 refCount; + ObjectInfo_u u; + }; + + /* 1147 */ + union VariableValueInternal_u + { + unsigned int next; + VariableUnion u; + ObjectInfo o; + }; + + /* 1148 */ + union VariableValueInternal_w + { + unsigned int status; + unsigned int type; + unsigned int name; + unsigned int classnum; + unsigned int notifyName; + unsigned int waitTime; + unsigned int parentLocalId; + }; + + /* 1149 */ + union VariableValueInternal_v + { + unsigned __int16 next; + unsigned __int16 index; + }; + + /* 240 */ + struct VariableValueInternal + { + Variable hash; + VariableValueInternal_u u; + VariableValueInternal_w w; + VariableValueInternal_v v; + unsigned __int16 nextSibling; + }; + + /* 241 */ + struct __declspec(align(4)) scrVarGlob_t + { + VariableValueInternal parentVariables[24576]; + VariableValueInternal childVariables[65536]; + }; + + /* 986 */ + struct __declspec(align(4)) HunkUser + { + HunkUser* current; + HunkUser* next; + int maxSize; + int end; + int pos; + int locked; + char* name; + bool fixed; + bool tempMem; + bool debugMem; + int type; + unsigned __int8 buf[1]; + }; + + /* 222 */ + struct __declspec(align(4)) scrVarPub_t + { + char* fieldBuffer; + unsigned __int16 canonicalStrCount; + bool developer; + bool developer_script; + bool evaluate; + char* error_message; + int error_index; + unsigned int time; + unsigned int timeArrayId; + unsigned int pauseArrayId; + unsigned int levelId; + unsigned int gameId; + unsigned int animId; + unsigned int freeEntList; + unsigned int tempVariable; + bool bInited; + unsigned __int16 savecount; + unsigned int checksum; + unsigned int entId; + unsigned int entFieldName; + HunkUser* programHunkUser; + char* programBuffer; + char* endScriptBuffer; + __int16 saveIdMap; + __int16 saveIdMapRev; + char field_54[98291]; + char field_18047; + }; + struct __declspec(align(2)) scr_const_t { unsigned __int16 _; diff --git a/src/game/symbols.hpp b/src/game/symbols.hpp index 1deabd2..c7c75f5 100644 --- a/src/game/symbols.hpp +++ b/src/game/symbols.hpp @@ -22,15 +22,16 @@ namespace game WEAK symbol g_path{ 0x0, 0x1F2F700 }; WEAK symbol g_entities{ 0x0, 0x176C6F0 }; WEAK symbol g_hudelems{ 0x0, 0x173C6F0 }; - //WEAK symbol scrVarPub{ 0x0, 0x3882B70 }; + WEAK symbol gScrVarPub{ 0x0, 0x3882B70 }; WEAK symbol gScrVmPub{ 0x0, 0x3BD4700 }; WEAK symbol level{ 0x0, 0x18F5D88 }; WEAK symbol g_pathAttemptGoalPos{ 0x0, 0x16CFD6C }; //WEAK symbol scrParserPub{ 0x0, 0x3882B00 }; - //WEAK symbol gScrVarGlob{ 0x0, 0x3914700 }; + WEAK symbol gScrVarGlob{ 0x0, 0x3914700 }; WEAK symbol function_stack{ 0x0, 0x3BDDDD0 }; WEAK symbol scr_const{0x0, 0x1F33B90}; + WEAK symbol var_typename{ 0x0, 0x8CF4B0 }; WEAK symbol BG_WeaponNames{ 0x0, 0x8F6770 };