diff --git a/APIDocs.md b/APIDocs.md index 75b1672c..f7fa1257 100644 --- a/APIDocs.md +++ b/APIDocs.md @@ -202,6 +202,11 @@ If the stat entry does not exist, the stat entry doesn't have an attribute named Returns the type of the specified stat entry. If the stat entry does not exist, the query fails. Possible return values: `Character`, `Potion`, `Armor`, `Object`, `Shield`, `Weapon`, `SkillData`, `StatusData`. +### StatGetExtraData +`query NRD_StatGetExtraData([in](STRING)_Key, [out](REAL)_Value)` + +Returns the specified key from `Data.txt`. If the key does not exist, the query fails. + # Status functions diff --git a/OsiInterface/Functions/StatFunctions.cpp b/OsiInterface/Functions/StatFunctions.cpp index 13f3801a..d8d8adb1 100644 --- a/OsiInterface/Functions/StatFunctions.cpp +++ b/OsiInterface/Functions/StatFunctions.cpp @@ -114,6 +114,26 @@ namespace osidbg args[1].String = typeInfo->Name.Str; return true; } + + bool StatGetExtraData(OsiArgumentDesc & args) + { + auto key = args[0].String; + auto & value = args[1].Float; + + auto stats = gOsirisProxy->GetLibraryManager().GetStats(); + if (stats == nullptr || stats->ExtraData == nullptr) { + OsiError("RPGStats not available"); + return false; + } + + auto extraData = stats->ExtraData->Properties.Find(key); + if (extraData != nullptr) { + value = *extraData; + return true; + } else { + return false; + } + } } void CustomFunctionLibrary::RegisterStatFunctions() @@ -170,6 +190,16 @@ namespace osidbg &func::StatGetType ); functionMgr.Register(std::move(getStatType)); + + auto getExtraData = std::make_unique( + "NRD_StatGetExtraData", + std::vector{ + { "Key", ValueType::String, FunctionArgumentDirection::In }, + { "Value", ValueType::Real, FunctionArgumentDirection::Out }, + }, + &func::StatGetExtraData + ); + functionMgr.Register(std::move(getExtraData)); } } diff --git a/OsiInterface/GameDefinitions/Stats.h b/OsiInterface/GameDefinitions/Stats.h index 9f427103..f3b12ce0 100644 --- a/OsiInterface/GameDefinitions/Stats.h +++ b/OsiInterface/GameDefinitions/Stats.h @@ -475,6 +475,51 @@ namespace osidbg CRPGStats_Modifier * GetAttributeInfo(const char * name, int * attributeIndex) const; }; + struct CRPGStats_ExtraData + { + FixedStringMapBase Properties; + }; + + struct CRPGStats_Object_Property + { + void * VMT; + FixedString SomeHashedText; + }; + + struct CDivinityStats_Object_Property_Data : public CRPGStats_Object_Property + { + uint32_t Unkn; + uint8_t PropertyContext; + uint8_t _Pad1[3]; + void * ConditionBlockPtr; + }; + + struct CRPGStats_Object_Property_List + { + CNamedElementManager Properties; + FixedString FS1; + uint8_t Unknown; + uint8_t _Pad[7]; + }; + + struct CDivinityStats_Condition + { + void * ScriptCheckBlock; + FixedString Id; + }; + + struct CRPGStats_Conditions_Manager + { + FixedStringMapBase Conditions; + uint8_t _Pad1[4]; + ObjectSet Strs; + }; + + struct CRPGStats_ItemType_Manager : public CNamedElementManager + { + uint64_t Unknown; + }; + struct CRPGStatsManager { CNamedElementManager modifierValueList; @@ -484,11 +529,42 @@ namespace osidbg CNamedElementManager deltaMods; CNamedElementManager treasureSubtables; CNamedElementManager treasureTables; - CNamedElementManager itemTypes; - uint64_t unknown[46]; + CRPGStats_ItemType_Manager itemTypes; + FixedStringMapBase PropertyLists; + uint8_t _Pad1[4]; + CRPGStats_Conditions_Manager ConditionsManager; + STDWString WStr1; + uint64_t Unkn1[5]; + CRPGStats_ExtraData * ExtraData; + FixedStringRefMap RefMap1; + FixedStringRefMap RefMap2; + FixedStringMapBase FSMap1; + uint8_t _Pad2[4]; + FixedStringMapBase FSMapInt1; + uint8_t _Pad3[4]; + FixedStringMapBase FSMapInt2; + uint8_t _Pad4[4]; + FixedStringMapBase FSMapInt3; + uint8_t _Pad5[4]; + FixedStringMapBase FSMap2; + uint64_t Unkn2[7]; ObjectSet ModifierFSSet; ObjectSet AttributeFlags; - uint64_t unknown2[165]; + uint64_t unknown2[140]; + void * EquipmentSetManager; + void * SkillSetManager; + uint64_t Unkn3; + void * ItemCombinationManager; + uint64_t Unkn4; + FixedString FS1; + FixedStringMapBase FSMapUInt64; + uint8_t _Pad6[4]; + uint64_t Unkn5; + PrimitiveSet DataBufferSet; + uint64_t Unkn6; + void * DivinityStats; + void * CritSection; + uint64_t Unkn7[5]; ModifierList * GetTypeInfo(CRPGStats_Object * object); RPGEnumeration * GetAttributeInfo(CRPGStats_Object * object, const char * attributeName, int & attributeIndex); diff --git a/OsiInterface/Lua/LuaBinding.cpp b/OsiInterface/Lua/LuaBinding.cpp index a30306ce..db701504 100644 --- a/OsiInterface/Lua/LuaBinding.cpp +++ b/OsiInterface/Lua/LuaBinding.cpp @@ -237,6 +237,25 @@ namespace osidbg } + + char const * const LuaStatsExtraDataProxy::MetatableName = "LuaStatsExtraDataProxy"; + + int LuaStatsExtraDataProxy::LuaIndex(lua_State * L) + { + auto stats = gOsirisProxy->GetLibraryManager().GetStats(); + if (stats == nullptr || stats->ExtraData == nullptr) return luaL_error(L, "Stats not available"); + + auto key = luaL_checkstring(L, 2); + auto extraData = stats->ExtraData->Properties.Find(key); + if (extraData != nullptr) { + lua_pushnumber(L, *extraData); + return 1; + } else { + return 0; + } + } + + LuaExtensionLibrary::LuaExtensionLibrary() { } @@ -252,6 +271,7 @@ namespace osidbg LuaHandleProxy::RegisterMetatable(L); LuaStatusHandleProxy::RegisterMetatable(L); LuaHandleProxy::RegisterMetatable(L); + LuaStatsExtraDataProxy::RegisterMetatable(L); RegisterNameResolverMetatable(L); CreateNameResolver(L); } @@ -412,6 +432,13 @@ math.randomseed = function () end )"; LoadScript(sandbox, "sandbox"); + + auto L = state_; + lua_getglobal(L, "Ext"); // stack: Ext + lua_pushstring(L, "ExtraData"); // stack: Ext, "ExtraData" + LuaStatsExtraDataProxy::New(L); // stack: Ext, "ExtraData", ExtraDataProxy + lua_settable(L, -3); // stack: Ext + lua_pop(L, 1); // stack: - } LuaState::~LuaState() diff --git a/OsiInterface/Lua/LuaBinding.h b/OsiInterface/Lua/LuaBinding.h index 75a69856..08ac2025 100644 --- a/OsiInterface/Lua/LuaBinding.h +++ b/OsiInterface/Lua/LuaBinding.h @@ -266,6 +266,14 @@ namespace osidbg ObjectHandle status_; }; + class LuaStatsExtraDataProxy : public LuaUserdata, public LuaIndexable + { + public: + static char const * const MetatableName; + + int LuaIndex(lua_State * L); + }; + class LuaExtensionLibrary {