From bd0d7c63d21b061ee4eab3a5b722e2ea2836bd5a Mon Sep 17 00:00:00 2001 From: Tristan Cormier Date: Tue, 6 Jan 2026 17:32:10 -0500 Subject: [PATCH 001/269] feat(connection): implement character deletion message handlers --- src/net/connection/ClientConnection.cpp | 4 ++++ src/net/connection/ClientConnection.hpp | 1 + src/net/connection/RealmConnection.cpp | 11 ++++++++++- src/net/connection/RealmConnection.hpp | 2 ++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/net/connection/ClientConnection.cpp b/src/net/connection/ClientConnection.cpp index 28b9a96..66434c0 100644 --- a/src/net/connection/ClientConnection.cpp +++ b/src/net/connection/ClientConnection.cpp @@ -104,6 +104,10 @@ void ClientConnection::GetRealmList() { } } +void ClientConnection::HandleCharacterDelete(uint8_t result) { + this->Complete(result == 71, result); +} + int32_t ClientConnection::HandleConnect() { this->Complete(1, 5); diff --git a/src/net/connection/ClientConnection.hpp b/src/net/connection/ClientConnection.hpp index f96a16f..c24fa3a 100644 --- a/src/net/connection/ClientConnection.hpp +++ b/src/net/connection/ClientConnection.hpp @@ -22,6 +22,7 @@ class ClientConnection : public RealmConnection { // Virtual member functions virtual int32_t HandleConnect(); + virtual void HandleCharacterDelete(uint8_t result); // Member functions ClientConnection(RealmResponse* realmResponse) diff --git a/src/net/connection/RealmConnection.cpp b/src/net/connection/RealmConnection.cpp index e743658..a60549e 100644 --- a/src/net/connection/RealmConnection.cpp +++ b/src/net/connection/RealmConnection.cpp @@ -30,7 +30,7 @@ int32_t RealmConnection::MessageHandler(void* param, NETMESSAGE msgId, uint32_t } case SMSG_DELETE_CHAR: { - // TODO + result = connection->DeleteCharHandler(msgId, time, msg); break; } @@ -294,6 +294,15 @@ int32_t RealmConnection::HandleCharEnum(uint32_t msgId, uint32_t time, CDataStor return 1; } +int32_t RealmConnection::DeleteCharHandler(uint32_t msgId, uint32_t time, CDataStore* msg) { + uint8_t result; + msg->Get(result); + + this->HandleCharacterDelete(result); + + return 1; +} + void RealmConnection::RequestCharacterEnum() { CDataStore msg; diff --git a/src/net/connection/RealmConnection.hpp b/src/net/connection/RealmConnection.hpp index b4eaa10..332401b 100644 --- a/src/net/connection/RealmConnection.hpp +++ b/src/net/connection/RealmConnection.hpp @@ -46,11 +46,13 @@ class RealmConnection : public NetClient { // Virtual member functions virtual int32_t HandleAuthChallenge(AuthenticationChallenge* challenge); + virtual void HandleCharacterDelete(uint8_t result) = 0; // Member functions RealmConnection(RealmResponse* realmResponse); int32_t HandleAuthResponse(uint32_t msgId, uint32_t time, CDataStore* msg); int32_t HandleCharEnum(uint32_t msgId, uint32_t time, CDataStore* msg); + int32_t DeleteCharHandler(uint32_t msgId, uint32_t time, CDataStore* msg); void RequestCharacterEnum(); void RequestCharacterLogin(uint64_t guid, int32_t a2); void SetSelectedRealm(uint32_t a2, uint32_t a3, uint32_t a4); From 860d6978fdde066322b70ad65030b0e36f6f3d17 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 11 Jan 2026 16:01:28 -0600 Subject: [PATCH 002/269] feat(object): add GetNumDwordBlocks --- src/object/client/Utils.cpp | 44 +++++++++++++++++++++++++++++++++++++ src/object/client/Utils.hpp | 6 ++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/object/client/Utils.cpp b/src/object/client/Utils.cpp index 7da5a29..3baa96d 100644 --- a/src/object/client/Utils.cpp +++ b/src/object/client/Utils.cpp @@ -1,4 +1,48 @@ #include "object/client/Utils.hpp" +#include "object/client/CGContainer.hpp" +#include "object/client/CGCorpse.hpp" +#include "object/client/CGDynamicObject.hpp" +#include "object/client/CGGameObject.hpp" +#include "object/client/CGItem.hpp" +#include "object/client/CGObject_C.hpp" +#include "object/client/CGPlayer.hpp" +#include "object/client/CGUnit.hpp" +#include "object/client/ObjMgr.hpp" + +/** + * Given an object type hierarchy and GUID, return the number of DWORD blocks backing the object's + * data storage. + */ +uint32_t GetNumDwordBlocks(OBJECT_TYPE type, uint64_t guid) { + switch (type) { + case HIER_TYPE_OBJECT: + return CGObject::TotalFields(); + + case HIER_TYPE_ITEM: + return CGItem::TotalFields(); + + case HIER_TYPE_CONTAINER: + return CGContainer::TotalFields(); + + case HIER_TYPE_UNIT: + return CGUnit::TotalFields(); + + case HIER_TYPE_PLAYER: + return guid == ClntObjMgrGetActivePlayer() ? CGPlayer::TotalFields() : CGPlayer::TotalRemoteFields(); + + case HIER_TYPE_GAMEOBJECT: + return CGGameObject::TotalFields(); + + case HIER_TYPE_DYNAMICOBJECT: + return CGDynamicObject::TotalFields(); + + case HIER_TYPE_CORPSE: + return CGCorpse::TotalFields(); + + default: + return 0; + } +} /** * Accounting for the full hierarchy of the given object, return the next inherited type ID after diff --git a/src/object/client/Utils.hpp b/src/object/client/Utils.hpp index d3fa93b..b8d69e8 100644 --- a/src/object/client/Utils.hpp +++ b/src/object/client/Utils.hpp @@ -1,8 +1,12 @@ #ifndef OBJECT_CLIENT_UTILS_HPP #define OBJECT_CLIENT_UTILS_HPP -#include "object/client/CGObject_C.hpp" #include "object/Types.hpp" +#include + +class CGObject_C; + +uint32_t GetNumDwordBlocks(OBJECT_TYPE type, uint64_t guid); OBJECT_TYPE_ID IncTypeID(CGObject_C* object, OBJECT_TYPE_ID curTypeID); From 8ab88329bb546376ed06fdc5df76b89136efa509 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 11 Jan 2026 20:00:44 -0600 Subject: [PATCH 003/269] chore(object): restructure mirror-oriented util functions --- src/object/client/{Utils.cpp => Mirror.cpp} | 2 +- src/object/client/Mirror.hpp | 7 +++++++ src/object/client/Utils.hpp | 13 ------------- 3 files changed, 8 insertions(+), 14 deletions(-) rename src/object/client/{Utils.cpp => Mirror.cpp} (98%) create mode 100644 src/object/client/Mirror.hpp delete mode 100644 src/object/client/Utils.hpp diff --git a/src/object/client/Utils.cpp b/src/object/client/Mirror.cpp similarity index 98% rename from src/object/client/Utils.cpp rename to src/object/client/Mirror.cpp index 3baa96d..c7e90cf 100644 --- a/src/object/client/Utils.cpp +++ b/src/object/client/Mirror.cpp @@ -1,4 +1,4 @@ -#include "object/client/Utils.hpp" +#include "object/client/Mirror.hpp" #include "object/client/CGContainer.hpp" #include "object/client/CGCorpse.hpp" #include "object/client/CGDynamicObject.hpp" diff --git a/src/object/client/Mirror.hpp b/src/object/client/Mirror.hpp new file mode 100644 index 0000000..5c2c5fb --- /dev/null +++ b/src/object/client/Mirror.hpp @@ -0,0 +1,7 @@ +#ifndef OBJECT_CLIENT_MIRROR_HPP +#define OBJECT_CLIENT_MIRROR_HPP + +#include "object/Types.hpp" +#include + +#endif diff --git a/src/object/client/Utils.hpp b/src/object/client/Utils.hpp deleted file mode 100644 index b8d69e8..0000000 --- a/src/object/client/Utils.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef OBJECT_CLIENT_UTILS_HPP -#define OBJECT_CLIENT_UTILS_HPP - -#include "object/Types.hpp" -#include - -class CGObject_C; - -uint32_t GetNumDwordBlocks(OBJECT_TYPE type, uint64_t guid); - -OBJECT_TYPE_ID IncTypeID(CGObject_C* object, OBJECT_TYPE_ID curTypeID); - -#endif From d1b764903c129571484a50c87c5cd4e5b9c1959b Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 11 Jan 2026 20:26:59 -0600 Subject: [PATCH 004/269] feat(object): add ExtractDirtyMasks --- src/object/client/Mirror.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/object/client/Mirror.cpp b/src/object/client/Mirror.cpp index c7e90cf..eac065d 100644 --- a/src/object/client/Mirror.cpp +++ b/src/object/client/Mirror.cpp @@ -8,6 +8,34 @@ #include "object/client/CGPlayer.hpp" #include "object/client/CGUnit.hpp" #include "object/client/ObjMgr.hpp" +#include + +#define MAX_DIRTY_MASKS 42 + +/** + * Given a message data store, extract the dirty masks contained inside. Any masks not present are + * zeroed out. This function assumes the provided masks pointer has enough space for + * MAX_DIRTY_MASKS. + */ +int32_t ExtractDirtyMasks(CDataStore* msg, uint8_t* maskCount, uint32_t* masks) { + uint8_t count; + msg->Get(count); + + *maskCount = count; + + if (count > MAX_DIRTY_MASKS) { + return 0; + } + + for (int32_t i = 0; i < count; i++) { + msg->Get(masks[i]); + } + + // Zero out unused masks + memset(&masks[count], 0, (MAX_DIRTY_MASKS - count) * sizeof(uint32_t)); + + return 1; +} /** * Given an object type hierarchy and GUID, return the number of DWORD blocks backing the object's From 47e0dbb02869909b451fba3dac49eae449706c3f Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 11 Jan 2026 20:38:20 -0600 Subject: [PATCH 005/269] chore(object): tidy up ExtractDirtyMasks --- src/object/client/Mirror.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/object/client/Mirror.cpp b/src/object/client/Mirror.cpp index eac065d..1168d88 100644 --- a/src/object/client/Mirror.cpp +++ b/src/object/client/Mirror.cpp @@ -8,14 +8,15 @@ #include "object/client/CGPlayer.hpp" #include "object/client/CGUnit.hpp" #include "object/client/ObjMgr.hpp" +#include "object/Types.hpp" #include -#define MAX_DIRTY_MASKS 42 +#define MAX_CHANGE_MASKS 42 /** - * Given a message data store, extract the dirty masks contained inside. Any masks not present are - * zeroed out. This function assumes the provided masks pointer has enough space for - * MAX_DIRTY_MASKS. + * Given a message data store, extract the dirty change masks contained inside. Any masks not + * present are zeroed out. This function assumes the provided masks pointer has enough space for + * MAX_CHANGE_MASKS. */ int32_t ExtractDirtyMasks(CDataStore* msg, uint8_t* maskCount, uint32_t* masks) { uint8_t count; @@ -23,7 +24,7 @@ int32_t ExtractDirtyMasks(CDataStore* msg, uint8_t* maskCount, uint32_t* masks) *maskCount = count; - if (count > MAX_DIRTY_MASKS) { + if (count > MAX_CHANGE_MASKS) { return 0; } @@ -31,8 +32,8 @@ int32_t ExtractDirtyMasks(CDataStore* msg, uint8_t* maskCount, uint32_t* masks) msg->Get(masks[i]); } - // Zero out unused masks - memset(&masks[count], 0, (MAX_DIRTY_MASKS - count) * sizeof(uint32_t)); + // Zero out masks that aren't present + memset(&masks[count], 0, (MAX_CHANGE_MASKS - count) * sizeof(uint32_t)); return 1; } From abdb5c364c38a973fb6d49406d3447056e73cefd Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 11 Jan 2026 22:08:20 -0600 Subject: [PATCH 006/269] chore(build): update common --- lib/common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common b/lib/common index 48a7802..997c0b1 160000 --- a/lib/common +++ b/lib/common @@ -1 +1 @@ -Subproject commit 48a78025ef77faac80faa30c116f3ced4bbd9251 +Subproject commit 997c0b100c7da97c58bc30f85de525d590b631f1 From 8066b4c053ba5d84e24b5ec3abb98be9de40082c Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 11 Jan 2026 22:18:26 -0600 Subject: [PATCH 007/269] chore(build): update common --- lib/common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common b/lib/common index 997c0b1..39cf797 160000 --- a/lib/common +++ b/lib/common @@ -1 +1 @@ -Subproject commit 997c0b100c7da97c58bc30f85de525d590b631f1 +Subproject commit 39cf7976a899b4f9a1290d0afdbd5011e4af9ac1 From 9162978b4faab6e181bb223562fe3dd3eaa161a0 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 11 Jan 2026 22:36:12 -0600 Subject: [PATCH 008/269] feat(object): add CGObject_C::SetBlock --- src/object/client/CGObject_C.cpp | 5 +++++ src/object/client/CGObject_C.hpp | 1 + 2 files changed, 6 insertions(+) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index c311673..2533e35 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -1,5 +1,10 @@ #include "object/client/CGObject_C.hpp" +void CGObject_C::SetBlock(uint32_t block, uint32_t value) { + auto storage = reinterpret_cast(this->m_obj); + storage[block] = value; +} + void CGObject_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->m_obj = reinterpret_cast(&storage[CGObject::GetBaseOffset()]); this->m_objSaved = &saved[CGObject::GetBaseOffsetSaved()]; diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index 54ed069..ea1b64b 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -9,6 +9,7 @@ class CGObject_C : public CGObject, public TSHashObject { public: // Public member functions + void SetBlock(uint32_t block, uint32_t value); void SetStorage(uint32_t* storage, uint32_t* saved); void SetTypeID(OBJECT_TYPE_ID typeID); }; From 6d8510b4a75c9ae42c59b520a033ff341806193c Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 11 Jan 2026 23:48:16 -0600 Subject: [PATCH 009/269] feat(util): add SmartGUID --- src/util/SmartGUID.cpp | 29 +++++++++++++++++++++++++++++ src/util/SmartGUID.hpp | 17 +++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/util/SmartGUID.cpp create mode 100644 src/util/SmartGUID.hpp diff --git a/src/util/SmartGUID.cpp b/src/util/SmartGUID.cpp new file mode 100644 index 0000000..b165e35 --- /dev/null +++ b/src/util/SmartGUID.cpp @@ -0,0 +1,29 @@ +#include "util/SmartGUID.hpp" +#include + +SmartGUID::operator uint64_t() const { + return this->guid; +} + +SmartGUID& SmartGUID::operator=(uint64_t guid) { + this->guid = guid; + return *this; +} + +CDataStore& operator>>(CDataStore& msg, SmartGUID& guid) { + guid = 0; + + uint8_t mask; + msg.Get(mask); + + for (int32_t i = 0; i < 8; i++) { + if (mask & (1 << i)) { + uint8_t byte; + msg.Get(byte); + + guid.guid |= static_cast(byte) << (i * 8); + } + } + + return msg; +} diff --git a/src/util/SmartGUID.hpp b/src/util/SmartGUID.hpp new file mode 100644 index 0000000..fef46c8 --- /dev/null +++ b/src/util/SmartGUID.hpp @@ -0,0 +1,17 @@ +#ifndef UTIL_SMART_GUID_HPP +#define UTIL_SMART_GUID_HPP + +#include + +class CDataStore; + +struct SmartGUID { + uint64_t guid; + + operator uint64_t() const; + SmartGUID& operator=(uint64_t value); +}; + +CDataStore& operator>>(CDataStore& msg, SmartGUID& guid); + +#endif From 5e4ca1980d68c3acff154f7266f324a13ee92daf Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 11 Jan 2026 23:49:49 -0600 Subject: [PATCH 010/269] feat(object): add FillInPartialObjectData --- src/object/client/Mirror.cpp | 51 ++++++++++++++++++++++++++++++++++++ src/object/client/Mirror.hpp | 6 ++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/object/client/Mirror.cpp b/src/object/client/Mirror.cpp index 1168d88..0bb60f6 100644 --- a/src/object/client/Mirror.cpp +++ b/src/object/client/Mirror.cpp @@ -13,6 +13,17 @@ #define MAX_CHANGE_MASKS 42 +static uint32_t s_objMirrorBlocks[] = { + CGObject::TotalFields(), + CGItem::TotalFields(), + CGContainer::TotalFields(), + CGUnit::TotalFields(), + CGPlayer::TotalFields(), + CGGameObject::TotalFields(), + CGDynamicObject::TotalFields(), + CGCorpse::TotalFields(), +}; + /** * Given a message data store, extract the dirty change masks contained inside. Any masks not * present are zeroed out. This function assumes the provided masks pointer has enough space for @@ -134,3 +145,43 @@ OBJECT_TYPE_ID IncTypeID(CGObject_C* object, OBJECT_TYPE_ID curTypeID) { return NUM_CLIENT_OBJECT_TYPES; } } + +int32_t IsMaskBitSet(uint32_t* masks, uint32_t block) { + return masks[block / 32] & (1 << (block % 32)); +} + +int32_t FillInPartialObjectData(CGObject_C* object, uint64_t guid, CDataStore* msg, bool forFullUpdate, bool zeroZeroBits) { + uint8_t changeMaskCount; + uint32_t changeMasks[MAX_CHANGE_MASKS]; + if (!ExtractDirtyMasks(msg, &changeMaskCount, changeMasks)) { + return 0; + } + + OBJECT_TYPE_ID typeID = ID_OBJECT; + uint32_t blockOffset = 0; + uint32_t numBlocks = GetNumDwordBlocks(object->m_obj->m_type, guid); + + for (int32_t block = 0; block < numBlocks; block++) { + if (block >= s_objMirrorBlocks[typeID]) { + blockOffset = s_objMirrorBlocks[typeID]; + typeID = IncTypeID(object, typeID); + } + + if (!forFullUpdate) { + // TODO + } + + if (IsMaskBitSet(changeMasks, block)) { + uint32_t blockValue; + msg->GetArray(reinterpret_cast(&blockValue), sizeof(blockValue)); + + object->SetBlock(block, blockValue); + } else if (zeroZeroBits) { + object->SetBlock(block, 0); + } + } + + // TODO + + return 1; +} diff --git a/src/object/client/Mirror.hpp b/src/object/client/Mirror.hpp index 5c2c5fb..b582039 100644 --- a/src/object/client/Mirror.hpp +++ b/src/object/client/Mirror.hpp @@ -1,7 +1,11 @@ #ifndef OBJECT_CLIENT_MIRROR_HPP #define OBJECT_CLIENT_MIRROR_HPP -#include "object/Types.hpp" #include +class CDataStore; +class CGObject_C; + +int32_t FillInPartialObjectData(CGObject_C* object, uint64_t guid, CDataStore* msg, bool forFullUpdate, bool zeroZeroBits); + #endif From 364fba9f34e99650502e61f1286053568873b59b Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 12 Jan 2026 09:00:56 -0600 Subject: [PATCH 011/269] chore(util): restructure guid code and add WOWGUID typedef --- src/object/client/CGContainer.hpp | 3 ++- src/object/client/CGItem.hpp | 9 +++++---- src/object/client/CGObject.hpp | 3 ++- src/object/client/CGObject_C.hpp | 4 ++-- src/object/client/CGPlayer.hpp | 27 ++++++++++++++------------- src/object/client/CGUnit.hpp | 17 +++++++++-------- src/object/client/ClntObjMgr.hpp | 2 +- src/object/client/Mirror.cpp | 4 ++-- src/object/client/Mirror.hpp | 3 ++- src/object/client/ObjMgr.cpp | 6 +++--- src/object/client/ObjMgr.hpp | 6 +++--- src/util/CMakeLists.txt | 1 + src/util/GUID.hpp | 8 ++++++++ src/util/SmartGUID.hpp | 17 ----------------- src/util/{ => guid}/CHashKeyGUID.cpp | 4 ++-- src/util/{ => guid}/CHashKeyGUID.hpp | 9 +++++---- src/util/{ => guid}/SmartGUID.cpp | 6 +++--- src/util/guid/SmartGUID.hpp | 18 ++++++++++++++++++ src/util/guid/Types.hpp | 8 ++++++++ 19 files changed, 90 insertions(+), 65 deletions(-) create mode 100644 src/util/GUID.hpp delete mode 100644 src/util/SmartGUID.hpp rename src/util/{ => guid}/CHashKeyGUID.cpp (50%) rename src/util/{ => guid}/CHashKeyGUID.hpp (51%) rename src/util/{ => guid}/SmartGUID.cpp (78%) create mode 100644 src/util/guid/SmartGUID.hpp create mode 100644 src/util/guid/Types.hpp diff --git a/src/object/client/CGContainer.hpp b/src/object/client/CGContainer.hpp index e8fe574..2134814 100644 --- a/src/object/client/CGContainer.hpp +++ b/src/object/client/CGContainer.hpp @@ -1,12 +1,13 @@ #ifndef OBJECT_CLIENT_CG_CONTAINER_HPP #define OBJECT_CLIENT_CG_CONTAINER_HPP +#include "util/GUID.hpp" #include struct CGContainerData { uint32_t numSlots; uint32_t pad; - uint64_t slots[36]; + WOWGUID slots[36]; }; class CGContainer { diff --git a/src/object/client/CGItem.hpp b/src/object/client/CGItem.hpp index 7c9b52b..2fda058 100644 --- a/src/object/client/CGItem.hpp +++ b/src/object/client/CGItem.hpp @@ -1,6 +1,7 @@ #ifndef OBJECT_CLIENT_CG_ITEM_HPP #define OBJECT_CLIENT_CG_ITEM_HPP +#include "util/GUID.hpp" #include struct ItemEnchantment { @@ -10,10 +11,10 @@ struct ItemEnchantment { }; struct CGItemData { - uint64_t owner; - uint64_t containedIn; - uint64_t creator; - uint64_t giftCreator; + WOWGUID owner; + WOWGUID containedIn; + WOWGUID creator; + WOWGUID giftCreator; uint32_t stackCount; int32_t expiration; int32_t spellCharges[5]; diff --git a/src/object/client/CGObject.hpp b/src/object/client/CGObject.hpp index bcbde33..91b868e 100644 --- a/src/object/client/CGObject.hpp +++ b/src/object/client/CGObject.hpp @@ -2,10 +2,11 @@ #define OBJECT_CLIENT_CG_OBJECT_HPP #include "object/Types.hpp" +#include "util/GUID.hpp" #include struct CGObjectData { - uint64_t m_guid; + WOWGUID m_guid; OBJECT_TYPE m_type; int32_t m_entryID; float m_scale; diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index ea1b64b..8526a5e 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -1,9 +1,9 @@ #ifndef OBJECT_CLIENT_CG_OBJECT_C_HPP #define OBJECT_CLIENT_CG_OBJECT_C_HPP -#include "object/client/CGObject.hpp" #include "object/Types.hpp" -#include "util/CHashKeyGUID.hpp" +#include "object/client/CGObject.hpp" +#include "util/GUID.hpp" #include class CGObject_C : public CGObject, public TSHashObject { diff --git a/src/object/client/CGPlayer.hpp b/src/object/client/CGPlayer.hpp index f8dbb25..7ef380b 100644 --- a/src/object/client/CGPlayer.hpp +++ b/src/object/client/CGPlayer.hpp @@ -2,6 +2,7 @@ #define OBJECT_CLIENT_CG_PLAYER_HPP #include "object/Types.hpp" +#include "util/GUID.hpp" #include struct CQuestLogData { @@ -19,7 +20,7 @@ struct CVisibleItemData { }; struct CGPlayerData { - uint64_t duelArbiter; + WOWGUID duelArbiter; uint32_t flags; uint32_t guildID; uint32_t guildRank; @@ -33,18 +34,18 @@ struct CGPlayerData { int32_t chosenTitle; int32_t fakeInebriation; int32_t pad4; - uint64_t invSlots[NUM_INVENTORY_SLOTS]; - uint64_t packSlots[16]; - uint64_t bankSlots[28]; - uint64_t bankBagSlots[7]; - uint64_t vendorBuybackSlots[12]; - uint64_t keyringSlots[32]; - uint64_t currencyTokenSlots[32]; - uint64_t farsightObject; - uint64_t knownTitles; - uint64_t knownTitles2; - uint64_t knownTitles3; - uint64_t knownCurrencies; + WOWGUID invSlots[NUM_INVENTORY_SLOTS]; + WOWGUID packSlots[16]; + WOWGUID bankSlots[28]; + WOWGUID bankBagSlots[7]; + WOWGUID vendorBuybackSlots[12]; + WOWGUID keyringSlots[32]; + WOWGUID currencyTokenSlots[32]; + WOWGUID farsightObject; + WOWGUID knownTitles; + WOWGUID knownTitles2; + WOWGUID knownTitles3; + WOWGUID knownCurrencies; uint32_t xp; uint32_t nextLevelXP; // TODO diff --git a/src/object/client/CGUnit.hpp b/src/object/client/CGUnit.hpp index 55bba2d..6ca29fa 100644 --- a/src/object/client/CGUnit.hpp +++ b/src/object/client/CGUnit.hpp @@ -1,17 +1,18 @@ #ifndef OBJECT_CLIENT_CG_UNIT_HPP #define OBJECT_CLIENT_CG_UNIT_HPP +#include "util/GUID.hpp" #include struct CGUnitData { - uint64_t charm; - uint64_t summon; - uint64_t critter; - uint64_t charmedBy; - uint64_t summonedBy; - uint64_t createdBy; - uint64_t target; - uint64_t channelObject; + WOWGUID charm; + WOWGUID summon; + WOWGUID critter; + WOWGUID charmedBy; + WOWGUID summonedBy; + WOWGUID createdBy; + WOWGUID target; + WOWGUID channelObject; int32_t channelSpell; int32_t pad1; int32_t health; diff --git a/src/object/client/ClntObjMgr.hpp b/src/object/client/ClntObjMgr.hpp index 781345e..80793be 100644 --- a/src/object/client/ClntObjMgr.hpp +++ b/src/object/client/ClntObjMgr.hpp @@ -8,7 +8,7 @@ class ClientConnection; class ClntObjMgr { public: // Member variables - uint64_t m_activePlayer = 0; + WOWGUID m_activePlayer = 0; uint32_t m_mapID = 0; ClientConnection* m_net = nullptr; }; diff --git a/src/object/client/Mirror.cpp b/src/object/client/Mirror.cpp index 0bb60f6..c4f25da 100644 --- a/src/object/client/Mirror.cpp +++ b/src/object/client/Mirror.cpp @@ -53,7 +53,7 @@ int32_t ExtractDirtyMasks(CDataStore* msg, uint8_t* maskCount, uint32_t* masks) * Given an object type hierarchy and GUID, return the number of DWORD blocks backing the object's * data storage. */ -uint32_t GetNumDwordBlocks(OBJECT_TYPE type, uint64_t guid) { +uint32_t GetNumDwordBlocks(OBJECT_TYPE type, WOWGUID guid) { switch (type) { case HIER_TYPE_OBJECT: return CGObject::TotalFields(); @@ -150,7 +150,7 @@ int32_t IsMaskBitSet(uint32_t* masks, uint32_t block) { return masks[block / 32] & (1 << (block % 32)); } -int32_t FillInPartialObjectData(CGObject_C* object, uint64_t guid, CDataStore* msg, bool forFullUpdate, bool zeroZeroBits) { +int32_t FillInPartialObjectData(CGObject_C* object, WOWGUID guid, CDataStore* msg, bool forFullUpdate, bool zeroZeroBits) { uint8_t changeMaskCount; uint32_t changeMasks[MAX_CHANGE_MASKS]; if (!ExtractDirtyMasks(msg, &changeMaskCount, changeMasks)) { diff --git a/src/object/client/Mirror.hpp b/src/object/client/Mirror.hpp index b582039..899db97 100644 --- a/src/object/client/Mirror.hpp +++ b/src/object/client/Mirror.hpp @@ -1,11 +1,12 @@ #ifndef OBJECT_CLIENT_MIRROR_HPP #define OBJECT_CLIENT_MIRROR_HPP +#include "util/GUID.hpp" #include class CDataStore; class CGObject_C; -int32_t FillInPartialObjectData(CGObject_C* object, uint64_t guid, CDataStore* msg, bool forFullUpdate, bool zeroZeroBits); +int32_t FillInPartialObjectData(CGObject_C* object, WOWGUID guid, CDataStore* msg, bool forFullUpdate, bool zeroZeroBits); #endif diff --git a/src/object/client/ObjMgr.cpp b/src/object/client/ObjMgr.cpp index cb8452f..440366c 100644 --- a/src/object/client/ObjMgr.cpp +++ b/src/object/client/ObjMgr.cpp @@ -66,7 +66,7 @@ void MirrorInitialize() { // TODO } -void* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, uint64_t guid) { +void* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, WOWGUID guid) { auto playerGUID = ClntObjMgrGetActivePlayer(); // Heap allocate player object for current player @@ -89,7 +89,7 @@ void* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, uint64_t guid) { return mem; } -uint64_t ClntObjMgrGetActivePlayer() { +WOWGUID ClntObjMgrGetActivePlayer() { if (!s_curMgr) { return 0; } @@ -156,7 +156,7 @@ void ClntObjMgrPush(ClntObjMgr* mgr) { s_curMgr = mgr; } -void ClntObjMgrSetActivePlayer(uint64_t guid) { +void ClntObjMgrSetActivePlayer(WOWGUID guid) { s_curMgr->m_activePlayer = guid; } diff --git a/src/object/client/ObjMgr.hpp b/src/object/client/ObjMgr.hpp index 6d3b6ca..295f5e6 100644 --- a/src/object/client/ObjMgr.hpp +++ b/src/object/client/ObjMgr.hpp @@ -6,9 +6,9 @@ #include "object/Types.hpp" #include -void* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, uint64_t guid); +void* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, WOWGUID guid); -uint64_t ClntObjMgrGetActivePlayer(); +WOWGUID ClntObjMgrGetActivePlayer(); ClntObjMgr* ClntObjMgrGetCurrent(); @@ -22,7 +22,7 @@ void ClntObjMgrPop(); void ClntObjMgrPush(ClntObjMgr* mgr); -void ClntObjMgrSetActivePlayer(uint64_t guid); +void ClntObjMgrSetActivePlayer(WOWGUID guid); void ClntObjMgrSetHandlers(); diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 07e3a2f..a0696b6 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -1,5 +1,6 @@ file(GLOB PRIVATE_SOURCES "*.cpp" + "guid/*.cpp" ) if(WHOA_SYSTEM_MAC) diff --git a/src/util/GUID.hpp b/src/util/GUID.hpp new file mode 100644 index 0000000..06967f8 --- /dev/null +++ b/src/util/GUID.hpp @@ -0,0 +1,8 @@ +#ifndef UTIL_GUID_HPP +#define UTIL_GUID_HPP + +#include "util/guid/CHashKeyGUID.hpp" +#include "util/guid/SmartGUID.hpp" +#include "util/guid/Types.hpp" + +#endif diff --git a/src/util/SmartGUID.hpp b/src/util/SmartGUID.hpp deleted file mode 100644 index fef46c8..0000000 --- a/src/util/SmartGUID.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef UTIL_SMART_GUID_HPP -#define UTIL_SMART_GUID_HPP - -#include - -class CDataStore; - -struct SmartGUID { - uint64_t guid; - - operator uint64_t() const; - SmartGUID& operator=(uint64_t value); -}; - -CDataStore& operator>>(CDataStore& msg, SmartGUID& guid); - -#endif diff --git a/src/util/CHashKeyGUID.cpp b/src/util/guid/CHashKeyGUID.cpp similarity index 50% rename from src/util/CHashKeyGUID.cpp rename to src/util/guid/CHashKeyGUID.cpp index efcaef2..7418c57 100644 --- a/src/util/CHashKeyGUID.cpp +++ b/src/util/guid/CHashKeyGUID.cpp @@ -1,9 +1,9 @@ -#include "util/CHashKeyGUID.hpp" +#include "util/guid/CHashKeyGUID.hpp" CHashKeyGUID::CHashKeyGUID() { this->m_guid = 0; } -CHashKeyGUID::CHashKeyGUID(uint64_t guid) { +CHashKeyGUID::CHashKeyGUID(WOWGUID guid) { this->m_guid = guid; } diff --git a/src/util/CHashKeyGUID.hpp b/src/util/guid/CHashKeyGUID.hpp similarity index 51% rename from src/util/CHashKeyGUID.hpp rename to src/util/guid/CHashKeyGUID.hpp index be0a8cb..5ba0e4a 100644 --- a/src/util/CHashKeyGUID.hpp +++ b/src/util/guid/CHashKeyGUID.hpp @@ -1,17 +1,18 @@ -#ifndef UTIL_C_HASH_KEY_GUID_HPP -#define UTIL_C_HASH_KEY_GUID_HPP +#ifndef UTIL_GUID_C_HASH_KEY_GUID_HPP +#define UTIL_GUID_C_HASH_KEY_GUID_HPP +#include "util/guid/Types.hpp" #include class CHashKeyGUID { public: // Public member functions CHashKeyGUID(); - CHashKeyGUID(uint64_t guid); + CHashKeyGUID(WOWGUID guid); private: // Private member variables - uint64_t m_guid; + WOWGUID m_guid; }; #endif diff --git a/src/util/SmartGUID.cpp b/src/util/guid/SmartGUID.cpp similarity index 78% rename from src/util/SmartGUID.cpp rename to src/util/guid/SmartGUID.cpp index b165e35..038d2f5 100644 --- a/src/util/SmartGUID.cpp +++ b/src/util/guid/SmartGUID.cpp @@ -1,11 +1,11 @@ -#include "util/SmartGUID.hpp" +#include "util/guid/SmartGUID.hpp" #include -SmartGUID::operator uint64_t() const { +SmartGUID::operator WOWGUID() const { return this->guid; } -SmartGUID& SmartGUID::operator=(uint64_t guid) { +SmartGUID& SmartGUID::operator=(WOWGUID guid) { this->guid = guid; return *this; } diff --git a/src/util/guid/SmartGUID.hpp b/src/util/guid/SmartGUID.hpp new file mode 100644 index 0000000..99427ac --- /dev/null +++ b/src/util/guid/SmartGUID.hpp @@ -0,0 +1,18 @@ +#ifndef UTIL_GUID_SMART_GUID_HPP +#define UTIL_GUID_SMART_GUID_HPP + +#include "util/guid/Types.hpp" +#include + +class CDataStore; + +struct SmartGUID { + WOWGUID guid; + + operator WOWGUID() const; + SmartGUID& operator=(WOWGUID value); +}; + +CDataStore& operator>>(CDataStore& msg, SmartGUID& guid); + +#endif diff --git a/src/util/guid/Types.hpp b/src/util/guid/Types.hpp new file mode 100644 index 0000000..4824aa9 --- /dev/null +++ b/src/util/guid/Types.hpp @@ -0,0 +1,8 @@ +#ifndef UTIL_GUID_TYPES_HPP +#define UTIL_GUID_TYPES_HPP + +#include + +typedef uint64_t WOWGUID; + +#endif From c59d0de8b58780b863885aeca0375fd438277bd7 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 12 Jan 2026 19:45:31 -0600 Subject: [PATCH 012/269] feat(util): add wip C3Spline class to util --- src/util/C3Spline.cpp | 20 ++++++++++++++++++++ src/util/C3Spline.hpp | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/util/C3Spline.cpp create mode 100644 src/util/C3Spline.hpp diff --git a/src/util/C3Spline.cpp b/src/util/C3Spline.cpp new file mode 100644 index 0000000..e9c8e48 --- /dev/null +++ b/src/util/C3Spline.cpp @@ -0,0 +1,20 @@ +#include "util/C3Spline.hpp" +#include + +CDataStore& operator>>(CDataStore& msg, C3Spline_CatmullRom& spline) { + uint32_t pointCount = 0; + msg.Get(pointCount); + + void* points; + msg.GetDataInSitu(points, sizeof(C3Vector) * pointCount); + + uint8_t splineMode; + msg.Get(splineMode); + // TODO spline.splineMode = splineMode; + + if (pointCount && msg.IsValid()) { + // TODO spline.SetPoints() + } + + return msg; +} diff --git a/src/util/C3Spline.hpp b/src/util/C3Spline.hpp new file mode 100644 index 0000000..8a1c170 --- /dev/null +++ b/src/util/C3Spline.hpp @@ -0,0 +1,20 @@ +#ifndef UTIL_C3_SPLINE_HPP +#define UTIL_C3_SPLINE_HPP + +#include + +// TODO move these classes to typhoon +class C3Spline { + public: + // TODO +}; + +class C3Spline_CatmullRom : public C3Spline { + public: + // TODO +}; + +// TODO move this operator>> to util/DataStore.hpp +CDataStore& operator>>(CDataStore& msg, C3Spline_CatmullRom& spline); + +#endif From 1cc8c3ce400aa30ce6966fcaadb99ce8d96adad7 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 12 Jan 2026 19:59:53 -0600 Subject: [PATCH 013/269] feat(object): add CMoveSpline --- src/object/CMakeLists.txt | 1 + src/object/movement/CMoveSpline.cpp | 32 +++++++++++++++++++++++++++++ src/object/movement/CMoveSpline.hpp | 32 +++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 src/object/movement/CMoveSpline.cpp create mode 100644 src/object/movement/CMoveSpline.hpp diff --git a/src/object/CMakeLists.txt b/src/object/CMakeLists.txt index 7da1fdd..a77c62e 100644 --- a/src/object/CMakeLists.txt +++ b/src/object/CMakeLists.txt @@ -1,6 +1,7 @@ file(GLOB PRIVATE_SOURCES "*.cpp" "client/*.cpp" + "movement/*.cpp" ) add_library(object STATIC diff --git a/src/object/movement/CMoveSpline.cpp b/src/object/movement/CMoveSpline.cpp new file mode 100644 index 0000000..71d3f4e --- /dev/null +++ b/src/object/movement/CMoveSpline.cpp @@ -0,0 +1,32 @@ +#include "object/movement/CMoveSpline.hpp" +#include "util/DataStore.hpp" +#include + +CDataStore& operator>>(CDataStore& msg, CMoveSpline& spline) { + msg.Get(spline.flags); + + if (spline.flags & 0x20000) { + msg.Get(spline.face.facing); + } else if (spline.flags & 0x10000) { + msg.Get(spline.face.guid); + } else { + msg >> spline.face.spot; + } + + uint32_t val; + msg.Get(val); + spline.start = OsGetAsyncTimeMsPrecise() - val; + + msg.Get(spline.uint2C); + msg.Get(spline.uint30); + msg.Get(spline.float204); + msg.Get(spline.float208); + msg.Get(spline.float20C); + msg.Get(spline.uint210); + + msg >> spline.spline; + + msg >> spline.vector1F8; + + return msg; +} diff --git a/src/object/movement/CMoveSpline.hpp b/src/object/movement/CMoveSpline.hpp new file mode 100644 index 0000000..0f8ff90 --- /dev/null +++ b/src/object/movement/CMoveSpline.hpp @@ -0,0 +1,32 @@ +#ifndef OBJECT_MOVEMENT_C_MOVE_SPLINE_HPP +#define OBJECT_MOVEMENT_C_MOVE_SPLINE_HPP + +#include "util/C3Spline.hpp" +#include "util/GUID.hpp" +#include +#include + +struct CMoveSpline { + // TODO + union { + C3Vector spot = {}; + WOWGUID guid; + float facing; + } face; + uint32_t flags; + uint32_t start; + // TODO + uint32_t uint2C; + uint32_t uint30; + C3Spline_CatmullRom spline; + C3Vector vector1F8; + float float204; + float float208; + float float20C; + uint32_t uint210; + // TODO +}; + +CDataStore& operator>>(CDataStore& msg, CMoveSpline& spline); + +#endif From 4114f1ee169f3d77d51c5261a607d3ef36a1045e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 12 Jan 2026 20:27:55 -0600 Subject: [PATCH 014/269] feat(object): add CMovementStatus --- src/object/movement/CMovementStatus.cpp | 39 +++++++++++++++++++++++++ src/object/movement/CMovementStatus.hpp | 32 ++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 src/object/movement/CMovementStatus.cpp create mode 100644 src/object/movement/CMovementStatus.hpp diff --git a/src/object/movement/CMovementStatus.cpp b/src/object/movement/CMovementStatus.cpp new file mode 100644 index 0000000..1131615 --- /dev/null +++ b/src/object/movement/CMovementStatus.cpp @@ -0,0 +1,39 @@ +#include "object/movement/CMovementStatus.hpp" +#include "util/DataStore.hpp" + +CDataStore& operator>>(CDataStore& msg, CMovementStatus& move) { + msg.Get(move.moveFlags); + msg.Get(move.uint14); + msg.Get(move.uint0); + + msg >> move.position18; + msg.Get(move.facing34); + + if (move.moveFlags & 0x200) { + // TODO + } else { + move.transport = 0; + // TODO + } + + if ((move.moveFlags & (0x200000 | 0x2000000)) || (move.uint14 & 0x20)) { + msg.Get(move.float38); + } else { + move.float38 = 0.0f; + } + + msg.Get(move.uint3C); + + if (move.moveFlags & 0x1000) { + msg.Get(move.float40); + msg.Get(move.float44); + msg.Get(move.float48); + msg.Get(move.float4C); + } + + if (move.moveFlags & 0x4000000) { + msg.Get(move.float50); + } + + return msg; +} diff --git a/src/object/movement/CMovementStatus.hpp b/src/object/movement/CMovementStatus.hpp new file mode 100644 index 0000000..42993da --- /dev/null +++ b/src/object/movement/CMovementStatus.hpp @@ -0,0 +1,32 @@ +#ifndef OBJECT_MOVEMENT_C_MOVEMENT_STATUS_HPP +#define OBJECT_MOVEMENT_C_MOVEMENT_STATUS_HPP + +#include "util/GUID.hpp" +#include +#include +#include + +struct CMovementStatus { + uint32_t uint0 = 0; + // TODO + WOWGUID transport = 0; + uint32_t moveFlags = 0x0; + uint16_t uint14 = 0; + // TODO + C3Vector position18; + float facing24 = 0.0f; + C3Vector position28; + float facing34 = 0.0f; + float float38 = 0.0f; + uint32_t uint3C = 0; + float float40 = 0.0f; + float float44 = 0.0f; + float float48 = 0.0f; + float float4C = 0.0f; + float float50 = 0.0f; + // TODO +}; + +CDataStore& operator>>(CDataStore& msg, CMovementStatus& move); + +#endif From 8333530d6595ba54938f2cd749d5a1be44b08054 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 12 Jan 2026 20:32:49 -0600 Subject: [PATCH 015/269] fix(object): correct flag check in spline reader --- src/object/movement/CMoveSpline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/object/movement/CMoveSpline.cpp b/src/object/movement/CMoveSpline.cpp index 71d3f4e..dab5c66 100644 --- a/src/object/movement/CMoveSpline.cpp +++ b/src/object/movement/CMoveSpline.cpp @@ -9,7 +9,7 @@ CDataStore& operator>>(CDataStore& msg, CMoveSpline& spline) { msg.Get(spline.face.facing); } else if (spline.flags & 0x10000) { msg.Get(spline.face.guid); - } else { + } else if (spline.flags & 0x8000) { msg >> spline.face.spot; } From 775320a7fc4d73a37fa1e7c30e32106a8d2c30f7 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 12 Jan 2026 20:34:21 -0600 Subject: [PATCH 016/269] feat(object): add CClientMoveUpdate --- src/object/client/CClientMoveUpdate.cpp | 21 +++++++++++++++++++++ src/object/client/CClientMoveUpdate.hpp | 25 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/object/client/CClientMoveUpdate.cpp create mode 100644 src/object/client/CClientMoveUpdate.hpp diff --git a/src/object/client/CClientMoveUpdate.cpp b/src/object/client/CClientMoveUpdate.cpp new file mode 100644 index 0000000..1ca03be --- /dev/null +++ b/src/object/client/CClientMoveUpdate.cpp @@ -0,0 +1,21 @@ +#include "object/client/CClientMoveUpdate.hpp" + +CDataStore& operator>>(CDataStore& msg, CClientMoveUpdate& move) { + msg >> move.status; + + msg.Get(move.float60); + msg.Get(move.float64); + msg.Get(move.float68); + msg.Get(move.float6C); + msg.Get(move.float70); + msg.Get(move.float74); + msg.Get(move.float78); + msg.Get(move.float7C); + msg.Get(move.float80); + + if (move.status.moveFlags & 0x8000000) { + msg >> move.spline; + } + + return msg; +} diff --git a/src/object/client/CClientMoveUpdate.hpp b/src/object/client/CClientMoveUpdate.hpp new file mode 100644 index 0000000..2cde73e --- /dev/null +++ b/src/object/client/CClientMoveUpdate.hpp @@ -0,0 +1,25 @@ +#ifndef OBJECT_CLIENT_C_CLIENT_MOVE_UPDATE_HPP +#define OBJECT_CLIENT_C_CLIENT_MOVE_UPDATE_HPP + +#include "object/movement/CMovementStatus.hpp" +#include "object/movement/CMoveSpline.hpp" +#include + +struct CClientMoveUpdate { + CMovementStatus status; + float float60; + float float64; + float float68; + float float6C; + float float70; + float float74; + float float78; + float float7C; + float float80; + // TODO + CMoveSpline spline; +}; + +CDataStore& operator>>(CDataStore& msg, CClientMoveUpdate& move); + +#endif From be264e22bf6f578566da352657f7fa6cabeef9f4 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 12 Jan 2026 21:17:23 -0600 Subject: [PATCH 017/269] feat(object): add CClientObjCreate --- src/object/client/CClientObjCreate.cpp | 72 ++++++++++++++++++++++++++ src/object/client/CClientObjCreate.hpp | 26 ++++++++++ 2 files changed, 98 insertions(+) create mode 100644 src/object/client/CClientObjCreate.cpp create mode 100644 src/object/client/CClientObjCreate.hpp diff --git a/src/object/client/CClientObjCreate.cpp b/src/object/client/CClientObjCreate.cpp new file mode 100644 index 0000000..ed99e1a --- /dev/null +++ b/src/object/client/CClientObjCreate.cpp @@ -0,0 +1,72 @@ +#include "object/client/CClientObjCreate.hpp" +#include "util/DataStore.hpp" +#include "util/GUID.hpp" +#include "util/Unimplemented.hpp" +#include + +int32_t CClientObjCreate::Get(CDataStore* msg) { + uint16_t flags; + msg->Get(flags); + + this->flags = flags; + + if (this->flags & 0x20) { + *msg >> this->move; + } else if (this->flags & 0x100) { + SmartGUID guid; + *msg >> guid; + this->move.status.transport = guid; + + *msg >> this->move.status.position28; + *msg >> this->move.status.position18; + + msg->Get(this->move.status.facing34); + msg->Get(this->move.status.facing24); + } else if (this->flags & 0x40) { + this->move.status.transport = 0; + + *msg >> this->move.status.position28; + this->move.status.position18 = this->move.status.position28; + + msg->Get(this->move.status.facing34); + } + + if (this->flags & 0x8) { + msg->Get(this->uint2AC); + } else { + this->uint2AC = 0; + } + + if (this->flags & 0x10) { + msg->Get(this->uint2B0); + } else { + this->uint2B0 = 0; + } + + if (this->flags & 0x4) { + SmartGUID guid; + *msg >> guid; + this->guid2B8 = guid; + } else { + this->guid2B8 = 0; + } + + if (this->flags & 0x2) { + msg->Get(this->uint2C0); + } + + if (this->flags & 0x80) { + msg->Get(this->uint2C4); + msg->Get(this->float2C8); + } + + if (this->flags & 0x200) { + SmartGUID guid; + *msg >> guid; + this->guid2D4 = guid; + } else { + this->guid2D4 = 0; + } + + return msg->Size() >= msg->Tell(); +} diff --git a/src/object/client/CClientObjCreate.hpp b/src/object/client/CClientObjCreate.hpp new file mode 100644 index 0000000..5d8baf8 --- /dev/null +++ b/src/object/client/CClientObjCreate.hpp @@ -0,0 +1,26 @@ +#ifndef OBJECT_CLIENT_C_CLIENT_OBJ_CREATE_HPP +#define OBJECT_CLIENT_C_CLIENT_OBJ_CREATE_HPP + +#include "object/client/CClientMoveUpdate.hpp" +#include "util/GUID.hpp" +#include + +class CDataStore; + +struct CClientObjCreate { + CClientMoveUpdate move; + uint32_t flags = 0x0; + uint32_t uint2AC; + uint32_t uint2B0; + // TODO + WOWGUID guid2B8 = 0; + uint32_t uint2C0; + uint32_t uint2C4; + float float2C8; + // TODO + WOWGUID guid2D4 = 0; + + int32_t Get(CDataStore* msg); +}; + +#endif From 43ad9fc8a65f1735cd6f4e14a5e8dc5ade48882d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 12 Jan 2026 21:42:13 -0600 Subject: [PATCH 018/269] feat(object): add ctors to base object classes --- src/object/client/CGContainer_C.cpp | 4 ++++ src/object/client/CGContainer_C.hpp | 2 ++ src/object/client/CGCorpse_C.cpp | 4 ++++ src/object/client/CGCorpse_C.hpp | 2 ++ src/object/client/CGDynamicObject_C.cpp | 4 ++++ src/object/client/CGDynamicObject_C.hpp | 2 ++ src/object/client/CGGameObject_C.cpp | 4 ++++ src/object/client/CGGameObject_C.hpp | 2 ++ src/object/client/CGItem_C.cpp | 4 ++++ src/object/client/CGItem_C.hpp | 2 ++ src/object/client/CGObject_C.cpp | 8 ++++++++ src/object/client/CGObject_C.hpp | 3 +++ src/object/client/CGPlayer_C.cpp | 4 ++++ src/object/client/CGPlayer_C.hpp | 2 ++ src/object/client/CGUnit_C.cpp | 4 ++++ src/object/client/CGUnit_C.hpp | 2 ++ 16 files changed, 53 insertions(+) diff --git a/src/object/client/CGContainer_C.cpp b/src/object/client/CGContainer_C.cpp index 48b36cc..b6e5fcf 100644 --- a/src/object/client/CGContainer_C.cpp +++ b/src/object/client/CGContainer_C.cpp @@ -1,5 +1,9 @@ #include "object/client/CGContainer_C.hpp" +CGContainer_C::CGContainer_C(uint32_t time, CClientObjCreate& objCreate) : CGItem_C(time, objCreate) { + // TODO +} + void CGContainer_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGItem_C::SetStorage(storage, saved); diff --git a/src/object/client/CGContainer_C.hpp b/src/object/client/CGContainer_C.hpp index 2b06c97..7ca1cd1 100644 --- a/src/object/client/CGContainer_C.hpp +++ b/src/object/client/CGContainer_C.hpp @@ -1,12 +1,14 @@ #ifndef OBJECT_CLIENT_CG_CONTAINER_C_HPP #define OBJECT_CLIENT_CG_CONTAINER_C_HPP +#include "object/client/CClientObjCreate.hpp" #include "object/client/CGContainer.hpp" #include "object/client/CGItem_C.hpp" class CGContainer_C : public CGItem_C, public CGContainer { public: // Public member functions + CGContainer_C(uint32_t time, CClientObjCreate& objCreate); void SetStorage(uint32_t* storage, uint32_t* saved); }; diff --git a/src/object/client/CGCorpse_C.cpp b/src/object/client/CGCorpse_C.cpp index 1cab4e4..e62e4fb 100644 --- a/src/object/client/CGCorpse_C.cpp +++ b/src/object/client/CGCorpse_C.cpp @@ -1,5 +1,9 @@ #include "object/client/CGCorpse_C.hpp" +CGCorpse_C::CGCorpse_C(uint32_t time, CClientObjCreate& objCreate) : CGObject_C(time, objCreate) { + // TODO +} + void CGCorpse_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGCorpse_C.hpp b/src/object/client/CGCorpse_C.hpp index ab5c856..b5d0914 100644 --- a/src/object/client/CGCorpse_C.hpp +++ b/src/object/client/CGCorpse_C.hpp @@ -1,12 +1,14 @@ #ifndef OBJECT_CLIENT_CG_CORPSE_C_HPP #define OBJECT_CLIENT_CG_CORPSE_C_HPP +#include "object/client/CClientObjCreate.hpp" #include "object/client/CGCorpse.hpp" #include "object/client/CGObject_C.hpp" class CGCorpse_C : public CGObject_C, public CGCorpse { public: // Public member functions + CGCorpse_C(uint32_t time, CClientObjCreate& objCreate); void SetStorage(uint32_t* storage, uint32_t* saved); }; diff --git a/src/object/client/CGDynamicObject_C.cpp b/src/object/client/CGDynamicObject_C.cpp index 4d3f5cf..b3787f3 100644 --- a/src/object/client/CGDynamicObject_C.cpp +++ b/src/object/client/CGDynamicObject_C.cpp @@ -1,5 +1,9 @@ #include "object/client/CGDynamicObject_C.hpp" +CGDynamicObject_C::CGDynamicObject_C(uint32_t time, CClientObjCreate& objCreate) : CGObject_C(time, objCreate) { + // TODO +} + void CGDynamicObject_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGDynamicObject_C.hpp b/src/object/client/CGDynamicObject_C.hpp index 59fd38e..6905e28 100644 --- a/src/object/client/CGDynamicObject_C.hpp +++ b/src/object/client/CGDynamicObject_C.hpp @@ -1,12 +1,14 @@ #ifndef OBJECT_CLIENT_CG_DYNAMIC_OBJECT_C_HPP #define OBJECT_CLIENT_CG_DYNAMIC_OBJECT_C_HPP +#include "object/client/CClientObjCreate.hpp" #include "object/client/CGDynamicObject.hpp" #include "object/client/CGObject_C.hpp" class CGDynamicObject_C : public CGObject_C, public CGDynamicObject { public: // Public member functions + CGDynamicObject_C(uint32_t time, CClientObjCreate& objCreate); void SetStorage(uint32_t* storage, uint32_t* saved); }; diff --git a/src/object/client/CGGameObject_C.cpp b/src/object/client/CGGameObject_C.cpp index 82bd71b..c97445c 100644 --- a/src/object/client/CGGameObject_C.cpp +++ b/src/object/client/CGGameObject_C.cpp @@ -1,5 +1,9 @@ #include "object/client/CGGameObject_C.hpp" +CGGameObject_C::CGGameObject_C(uint32_t time, CClientObjCreate& objCreate) : CGObject_C(time, objCreate) { + // TODO +} + void CGGameObject_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGGameObject_C.hpp b/src/object/client/CGGameObject_C.hpp index d57e89f..36b3dce 100644 --- a/src/object/client/CGGameObject_C.hpp +++ b/src/object/client/CGGameObject_C.hpp @@ -1,12 +1,14 @@ #ifndef OBJECT_CLIENT_CG_GAME_OBJECT_C_HPP #define OBJECT_CLIENT_CG_GAME_OBJECT_C_HPP +#include "object/client/CClientObjCreate.hpp" #include "object/client/CGGameObject.hpp" #include "object/client/CGObject_C.hpp" class CGGameObject_C : public CGObject_C, public CGGameObject { public: // Public member functions + CGGameObject_C(uint32_t time, CClientObjCreate& objCreate); void SetStorage(uint32_t* storage, uint32_t* saved); }; diff --git a/src/object/client/CGItem_C.cpp b/src/object/client/CGItem_C.cpp index 7756f76..ba092ec 100644 --- a/src/object/client/CGItem_C.cpp +++ b/src/object/client/CGItem_C.cpp @@ -1,5 +1,9 @@ #include "object/client/CGItem_C.hpp" +CGItem_C::CGItem_C(uint32_t time, CClientObjCreate& objCreate) : CGObject_C(time, objCreate) { + // TODO +} + void CGItem_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGItem_C.hpp b/src/object/client/CGItem_C.hpp index 0656562..079d0bd 100644 --- a/src/object/client/CGItem_C.hpp +++ b/src/object/client/CGItem_C.hpp @@ -1,12 +1,14 @@ #ifndef OBJECT_CLIENT_CG_ITEM_C_HPP #define OBJECT_CLIENT_CG_ITEM_C_HPP +#include "object/client/CClientObjCreate.hpp" #include "object/client/CGObject_C.hpp" #include "object/client/CGItem.hpp" class CGItem_C : public CGObject_C, public CGItem { public: // Public member functions + CGItem_C(uint32_t time, CClientObjCreate& objCreate); void SetStorage(uint32_t* storage, uint32_t* saved); }; diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 2533e35..f9be5e9 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -1,5 +1,13 @@ #include "object/client/CGObject_C.hpp" +CGObject_C::CGObject_C(uint32_t time, CClientObjCreate& objCreate) { + // TODO +} + +void CGObject_C::AddWorldObject() { + // TODO +} + void CGObject_C::SetBlock(uint32_t block, uint32_t value) { auto storage = reinterpret_cast(this->m_obj); storage[block] = value; diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index 8526a5e..b63cc38 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -2,6 +2,7 @@ #define OBJECT_CLIENT_CG_OBJECT_C_HPP #include "object/Types.hpp" +#include "object/client/CClientObjCreate.hpp" #include "object/client/CGObject.hpp" #include "util/GUID.hpp" #include @@ -9,6 +10,8 @@ class CGObject_C : public CGObject, public TSHashObject { public: // Public member functions + CGObject_C(uint32_t time, CClientObjCreate& objCreate); + void AddWorldObject(); void SetBlock(uint32_t block, uint32_t value); void SetStorage(uint32_t* storage, uint32_t* saved); void SetTypeID(OBJECT_TYPE_ID typeID); diff --git a/src/object/client/CGPlayer_C.cpp b/src/object/client/CGPlayer_C.cpp index a838567..5ac5eaa 100644 --- a/src/object/client/CGPlayer_C.cpp +++ b/src/object/client/CGPlayer_C.cpp @@ -3,6 +3,10 @@ #include "object/Types.hpp" #include +CGPlayer_C::CGPlayer_C(uint32_t time, CClientObjCreate& objCreate) : CGUnit_C(time, objCreate) { + // TODO +} + void CGPlayer_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGUnit_C::SetStorage(storage, saved); diff --git a/src/object/client/CGPlayer_C.hpp b/src/object/client/CGPlayer_C.hpp index 88fa230..d94b8e8 100644 --- a/src/object/client/CGPlayer_C.hpp +++ b/src/object/client/CGPlayer_C.hpp @@ -1,6 +1,7 @@ #ifndef OBJECT_CLIENT_CG_PLAYER_C_HPP #define OBJECT_CLIENT_CG_PLAYER_C_HPP +#include "object/client/CClientObjCreate.hpp" #include "object/client/CGPlayer.hpp" #include "object/client/CGUnit_C.hpp" #include @@ -10,6 +11,7 @@ class CreatureModelDataRec; class CGPlayer_C : public CGUnit_C, public CGPlayer { public: // Public member functions + CGPlayer_C(uint32_t time, CClientObjCreate& objCreate); void SetStorage(uint32_t* storage, uint32_t* saved); }; diff --git a/src/object/client/CGUnit_C.cpp b/src/object/client/CGUnit_C.cpp index 8bff572..5a6ead7 100644 --- a/src/object/client/CGUnit_C.cpp +++ b/src/object/client/CGUnit_C.cpp @@ -89,6 +89,10 @@ const char* CGUnit_C::GetDisplayRaceNameFromRecord(const ChrRacesRec* raceRec, U return raceRec->m_name; } +CGUnit_C::CGUnit_C(uint32_t time, CClientObjCreate& objCreate) : CGObject_C(time, objCreate) { + // TODO +} + void CGUnit_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGUnit_C.hpp b/src/object/client/CGUnit_C.hpp index f025b5b..5b651ff 100644 --- a/src/object/client/CGUnit_C.hpp +++ b/src/object/client/CGUnit_C.hpp @@ -1,6 +1,7 @@ #ifndef OBJECT_CLIENT_CG_UNIT_C_HPP #define OBJECT_CLIENT_CG_UNIT_C_HPP +#include "object/client/CClientObjCreate.hpp" #include "object/client/CGObject_C.hpp" #include "object/client/CGUnit.hpp" #include "object/Types.hpp" @@ -15,6 +16,7 @@ class CGUnit_C : public CGObject_C, public CGUnit { static const char* GetDisplayRaceNameFromRecord(const ChrRacesRec* raceRec, UNIT_SEX sex, UNIT_SEX* displaySex); // Public member functions + CGUnit_C(uint32_t time, CClientObjCreate& objCreate); void SetStorage(uint32_t* storage, uint32_t* saved); }; From 2fc113d5b06af64d5b817c709f32776b16f7b42f Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 12 Jan 2026 21:43:35 -0600 Subject: [PATCH 019/269] feat(object): partially implement ObjectUpdateHandler --- src/object/client/MessageHandlers.cpp | 316 +++++++++++++++++++++++++- 1 file changed, 315 insertions(+), 1 deletion(-) diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index 9deef23..ad842bd 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -1,9 +1,297 @@ #include "object/client/MessageHandlers.hpp" +#include "object/client/CClientObjCreate.hpp" +#include "object/client/CGContainer_C.hpp" +#include "object/client/CGCorpse_C.hpp" +#include "object/client/CGDynamicObject_C.hpp" +#include "object/client/CGGameObject_C.hpp" +#include "object/client/CGItem_C.hpp" +#include "object/client/CGObject_C.hpp" +#include "object/client/CGPlayer_C.hpp" +#include "object/client/CGUnit_C.hpp" +#include "object/client/Mirror.hpp" +#include "object/client/ObjMgr.hpp" +#include "util/GUID.hpp" #include "util/Unimplemented.hpp" #include "util/Zlib.hpp" #include #include #include +#include + +enum UPDATE_TYPE { + UPDATE_PARTIAL = 0, + UPDATE_MOVEMENT = 1, + UPDATE_FULL = 2, + UPDATE_3 = 3, + UPDATE_OUT_OF_RANGE = 4, + UPDATE_IN_RANGE = 5, +}; + +CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenabled) { + WHOA_UNIMPLEMENTED(nullptr); +} + +void UpdateOutOfRangeObjects(CDataStore* msg) { + WHOA_UNIMPLEMENTED(); +} + +int32_t UpdateObject(CDataStore* msg) { + WHOA_UNIMPLEMENTED(0); +} + +void UpdateObjectMovement(CDataStore* msg) { + WHOA_UNIMPLEMENTED(); +} + +void SetupObjectStorage(OBJECT_TYPE_ID typeID, CGObject_C* object, WOWGUID guid) { + auto ptr = reinterpret_cast(object); + + switch (typeID) { + case ID_OBJECT: { + auto storage = reinterpret_cast(ptr + sizeof(CGObject_C)); + auto saved = storage + CGObject::TotalFields(); + + object->SetStorage(storage, saved); + memset(storage, 0, CGObject::GetDataSize()); + + break; + } + + case ID_ITEM: { + auto storage = reinterpret_cast(ptr + sizeof(CGItem_C)); + auto saved = storage + CGItem::TotalFields(); + + static_cast(object)->SetStorage(storage, saved); + memset(storage, 0, CGItem::GetDataSize()); + + break; + } + + case ID_CONTAINER: { + auto storage = reinterpret_cast(ptr + sizeof(CGContainer_C)); + auto saved = storage + CGContainer::TotalFields(); + + static_cast(object)->SetStorage(storage, saved); + memset(storage, 0, CGContainer::GetDataSize()); + + break; + } + + case ID_UNIT: { + auto storage = reinterpret_cast(ptr + sizeof(CGUnit_C)); + auto saved = storage + CGUnit::TotalFields(); + + static_cast(object)->SetStorage(storage, saved); + memset(storage, 0, CGUnit::GetDataSize()); + + break; + } + + case ID_PLAYER: { + // TODO something at ptr + 0x614 (within CGPlayer_C) + + if (guid == ClntObjMgrGetActivePlayer()) { + auto storage = reinterpret_cast(ptr + sizeof(CGPlayer_C)); + auto saved = storage + CGPlayer::TotalFields(); + + static_cast(object)->SetStorage(storage, saved); + memset(storage, 0, CGPlayer::GetDataSize()); + } else { + auto storage = reinterpret_cast(ptr + sizeof(CGPlayer_C)); + auto saved = storage + CGPlayer::TotalRemoteFields(); + + static_cast(object)->SetStorage(storage, saved); + memset(storage, 0, CGPlayer::GetRemoteDataSize()); + } + + break; + } + + case ID_GAMEOBJECT: { + auto storage = reinterpret_cast(ptr + sizeof(CGGameObject_C)); + auto saved = storage + CGGameObject::TotalFields(); + + static_cast(object)->SetStorage(storage, saved); + memset(storage, 0, CGGameObject::GetDataSize()); + + break; + } + + case ID_DYNAMICOBJECT: { + auto storage = reinterpret_cast(ptr + sizeof(CGDynamicObject_C)); + auto saved = storage + CGDynamicObject::TotalFields(); + + static_cast(object)->SetStorage(storage, saved); + memset(storage, 0, CGDynamicObject::GetDataSize()); + + break; + } + + case ID_CORPSE: { + auto storage = reinterpret_cast(ptr + sizeof(CGCorpse_C)); + auto saved = storage + CGCorpse::TotalFields(); + + static_cast(object)->SetStorage(storage, saved); + memset(storage, 0, CGCorpse::GetDataSize()); + + break; + } + } +} + +void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate) { + switch (object->m_typeID) { + case ID_ITEM: { + new (object) CGItem_C(time, objCreate); + + break; + } + + case ID_CONTAINER: { + new (object) CGContainer_C(time, objCreate); + + break; + } + + case ID_UNIT: { + new (object) CGUnit_C(time, objCreate); + object->AddWorldObject(); + + break; + } + + case ID_PLAYER: { + new (object) CGPlayer_C(time, objCreate); + object->AddWorldObject(); + + break; + } + + case ID_GAMEOBJECT: { + new (object) CGGameObject_C(time, objCreate); + object->AddWorldObject(); + + break; + } + + case ID_DYNAMICOBJECT: { + new (object) CGDynamicObject_C(time, objCreate); + object->AddWorldObject(); + + break; + } + + case ID_CORPSE: { + new (object) CGCorpse_C(time, objCreate); + object->AddWorldObject(); + + break; + } + + default: { + break; + } + } +} + +int32_t CreateObject(CDataStore* msg, uint32_t time) { + SmartGUID guid; + *msg >> guid; + + uint8_t _typeID; + msg->Get(_typeID); + auto typeID = static_cast(_typeID); + + int32_t reenabled; + auto existingObject = GetUpdateObject(guid, &reenabled); + + if (existingObject) { + // TODO + return 0; + } + + CClientObjCreate objCreate; + if (!objCreate.Get(msg)) { + return 0; + } + + if (objCreate.flags & 0x1) { + ClntObjMgrSetActivePlayer(guid); + } + + auto newObject = static_cast(ClntObjMgrAllocObject(typeID, guid)); + + SetupObjectStorage(typeID, newObject, guid); + + newObject->SetTypeID(typeID); + + if (!FillInPartialObjectData(newObject, guid, msg, true, false)) { + return 0; + } + + InitObject(newObject, time, objCreate); + + // TODO link to one of the ClntObjMgr lists + + return 1; +} + +void UpdateInRangeObjects(CDataStore* msg) { + WHOA_UNIMPLEMENTED(); +} + +int32_t ObjectUpdateFirstPass(CDataStore* msg, uint32_t time, uint32_t updateIdx, uint32_t updateCount) { + for (uint32_t i = updateIdx; i < updateCount; i++) { + uint8_t updateType; + msg->Get(updateType); + + switch (updateType) { + case UPDATE_PARTIAL: { + if (!UpdateObject(msg)) { + return 0; + } + + break; + } + + case UPDATE_MOVEMENT: { + // Read but ignored in first pass + SmartGUID guid; + *msg >> guid; + + UpdateObjectMovement(msg); + + break; + } + + case UPDATE_FULL: + case UPDATE_3: { + if (!CreateObject(msg, time)) { + return 0; + } + + break; + } + + case UPDATE_IN_RANGE: { + UpdateInRangeObjects(msg); + + break; + } + + default: { + STORM_APP_FATAL("Unknown client update packet type (%d)!", updateType); + } + } + } + + return 1; +} + +int32_t ObjectUpdateSecondPass(CDataStore* msg, uint32_t time, uint32_t updateCount) { + // TODO + return 0; +} int32_t ObjectCompressedUpdateHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) { uint32_t origSize; @@ -60,7 +348,33 @@ int32_t ObjectCompressedUpdateHandler(void* param, NETMESSAGE msgId, uint32_t ti } int32_t ObjectUpdateHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) { - WHOA_UNIMPLEMENTED(0); + uint32_t updateCount; + msg->Get(updateCount); + + auto startPos = msg->Tell(); + + uint8_t firstUpdateType; + msg->Get(firstUpdateType); + + uint32_t updateIdx = 0; + + if (firstUpdateType == UPDATE_OUT_OF_RANGE) { + UpdateOutOfRangeObjects(msg); + updateIdx = 1; + } else { + msg->Seek(startPos); + } + + int32_t result = 0; + + if (ObjectUpdateFirstPass(msg, time, updateIdx, updateCount)) { + msg->Seek(startPos); + result = ObjectUpdateSecondPass(msg, time, updateCount); + } + + // TODO + + return result; } int32_t OnObjectDestroy(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) { From 4dd9921a4f140ae6d4298d25ac2a779980456a98 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 15:52:50 -0600 Subject: [PATCH 020/269] feat(object): add ClntObjMgrLinkInNewObject --- src/object/client/CGObject_C.cpp | 5 +++++ src/object/client/CGObject_C.hpp | 1 + src/object/client/ClntObjMgr.hpp | 4 ++++ src/object/client/ObjMgr.cpp | 5 +++++ src/object/client/ObjMgr.hpp | 2 ++ 5 files changed, 17 insertions(+) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index f9be5e9..d9b11b8 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -1,7 +1,12 @@ #include "object/client/CGObject_C.hpp" +#include "object/client/ObjMgr.hpp" CGObject_C::CGObject_C(uint32_t time, CClientObjCreate& objCreate) { // TODO + + ClntObjMgrLinkInNewObject(this); + + // TODO } void CGObject_C::AddWorldObject() { diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index b63cc38..e0b8520 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -10,6 +10,7 @@ class CGObject_C : public CGObject, public TSHashObject { public: // Public member functions + CGObject_C() = default; CGObject_C(uint32_t time, CClientObjCreate& objCreate); void AddWorldObject(); void SetBlock(uint32_t block, uint32_t value); diff --git a/src/object/client/ClntObjMgr.hpp b/src/object/client/ClntObjMgr.hpp index 80793be..51cd561 100644 --- a/src/object/client/ClntObjMgr.hpp +++ b/src/object/client/ClntObjMgr.hpp @@ -1,6 +1,8 @@ #ifndef OBJECT_CLIENT_CLNT_OBJ_MGR_HPP #define OBJECT_CLIENT_CLNT_OBJ_MGR_HPP +#include "object/client/CGObject_C.hpp" +#include #include class ClientConnection; @@ -8,6 +10,8 @@ class ClientConnection; class ClntObjMgr { public: // Member variables + TSHashTable m_objects; + // TODO WOWGUID m_activePlayer = 0; uint32_t m_mapID = 0; ClientConnection* m_net = nullptr; diff --git a/src/object/client/ObjMgr.cpp b/src/object/client/ObjMgr.cpp index 440366c..d20711a 100644 --- a/src/object/client/ObjMgr.cpp +++ b/src/object/client/ObjMgr.cpp @@ -138,6 +138,11 @@ void ClntObjMgrInitializeStd(uint32_t mapID) { mgr->m_mapID = mapID; } +void ClntObjMgrLinkInNewObject(CGObject_C* object) { + CHashKeyGUID key(object->m_obj->m_guid); + s_curMgr->m_objects.Insert(object, object->m_obj->m_guid, key); +} + void ClntObjMgrPop() { if (!s_savMgr) { return; diff --git a/src/object/client/ObjMgr.hpp b/src/object/client/ObjMgr.hpp index 295f5e6..5d5b0a1 100644 --- a/src/object/client/ObjMgr.hpp +++ b/src/object/client/ObjMgr.hpp @@ -18,6 +18,8 @@ void ClntObjMgrInitializeShared(); void ClntObjMgrInitializeStd(uint32_t mapID); +void ClntObjMgrLinkInNewObject(CGObject_C* object); + void ClntObjMgrPop(); void ClntObjMgrPush(ClntObjMgr* mgr); From a90933f6353e924213cc09512ef3338ca88925eb Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 15:53:39 -0600 Subject: [PATCH 021/269] feat(util): add operator== overloads to CHashKeyGUID --- src/util/guid/CHashKeyGUID.cpp | 8 ++++++++ src/util/guid/CHashKeyGUID.hpp | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/util/guid/CHashKeyGUID.cpp b/src/util/guid/CHashKeyGUID.cpp index 7418c57..1e1f7a4 100644 --- a/src/util/guid/CHashKeyGUID.cpp +++ b/src/util/guid/CHashKeyGUID.cpp @@ -7,3 +7,11 @@ CHashKeyGUID::CHashKeyGUID() { CHashKeyGUID::CHashKeyGUID(WOWGUID guid) { this->m_guid = guid; } + +bool CHashKeyGUID::operator==(WOWGUID guid) const { + return this->m_guid == guid; +} + +bool CHashKeyGUID::operator==(const CHashKeyGUID& key) const { + return this->m_guid == key.m_guid; +} diff --git a/src/util/guid/CHashKeyGUID.hpp b/src/util/guid/CHashKeyGUID.hpp index 5ba0e4a..95399d1 100644 --- a/src/util/guid/CHashKeyGUID.hpp +++ b/src/util/guid/CHashKeyGUID.hpp @@ -9,6 +9,8 @@ class CHashKeyGUID { // Public member functions CHashKeyGUID(); CHashKeyGUID(WOWGUID guid); + bool operator==(WOWGUID guid) const; + bool operator==(const CHashKeyGUID& key) const; private: // Private member variables From 4f9cceda79da3082950e59e64d935a4d56cb6519 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 17:44:48 -0600 Subject: [PATCH 022/269] feat(object): add FindActiveObject --- src/object/client/Util.cpp | 6 ++++++ src/object/client/Util.hpp | 10 ++++++++++ 2 files changed, 16 insertions(+) create mode 100644 src/object/client/Util.cpp create mode 100644 src/object/client/Util.hpp diff --git a/src/object/client/Util.cpp b/src/object/client/Util.cpp new file mode 100644 index 0000000..b243c21 --- /dev/null +++ b/src/object/client/Util.cpp @@ -0,0 +1,6 @@ +#include "object/client/Util.hpp" +#include "object/client/ObjMgr.hpp" + +CGObject_C* FindActiveObject(WOWGUID guid) { + return ClntObjMgrGetCurrent()->m_objects.Ptr(guid, CHashKeyGUID(guid)); +} diff --git a/src/object/client/Util.hpp b/src/object/client/Util.hpp new file mode 100644 index 0000000..8903851 --- /dev/null +++ b/src/object/client/Util.hpp @@ -0,0 +1,10 @@ +#ifndef OBJECT_CLIENT_UTIL_HPP +#define OBJECT_CLIENT_UTIL_HPP + +#include "util/GUID.hpp" + +class CGObject_C; + +CGObject_C* FindActiveObject(WOWGUID guid); + +#endif From f722040986a95a687182aa0fd9a943f6f799e592 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 17:45:37 -0600 Subject: [PATCH 023/269] feat(object): stub CGObject_C::SetDisablePending --- src/object/client/CGObject_C.cpp | 4 ++++ src/object/client/CGObject_C.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index d9b11b8..7667ad8 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -18,6 +18,10 @@ void CGObject_C::SetBlock(uint32_t block, uint32_t value) { storage[block] = value; } +void CGObject_C::SetDisablePending(int32_t pending) { + // TODO +} + void CGObject_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->m_obj = reinterpret_cast(&storage[CGObject::GetBaseOffset()]); this->m_objSaved = &saved[CGObject::GetBaseOffsetSaved()]; diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index e0b8520..cd5b442 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -14,6 +14,7 @@ class CGObject_C : public CGObject, public TSHashObject Date: Tue, 13 Jan 2026 17:45:59 -0600 Subject: [PATCH 024/269] feat(object): partially implement GetUpdateObject --- src/object/client/MessageHandlers.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index ad842bd..5d9ef36 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -10,6 +10,7 @@ #include "object/client/CGUnit_C.hpp" #include "object/client/Mirror.hpp" #include "object/client/ObjMgr.hpp" +#include "object/client/Util.hpp" #include "util/GUID.hpp" #include "util/Unimplemented.hpp" #include "util/Zlib.hpp" @@ -28,7 +29,18 @@ enum UPDATE_TYPE { }; CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenabled) { - WHOA_UNIMPLEMENTED(nullptr); + *reenabled = false; + + auto activeObject = FindActiveObject(guid); + + if (activeObject) { + activeObject->SetDisablePending(false); + + return activeObject; + } + + // TODO handle reenabling object + return nullptr; } void UpdateOutOfRangeObjects(CDataStore* msg) { From b26db429948722e1b57702a2d89469fb5791c27e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 19:21:19 -0600 Subject: [PATCH 025/269] feat(object): stub CGObject_C::Reenable --- src/object/client/CGObject_C.cpp | 4 ++++ src/object/client/CGObject_C.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 7667ad8..07257a0 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -13,6 +13,10 @@ void CGObject_C::AddWorldObject() { // TODO } +void CGObject_C::Reenable() { + // TODO +} + void CGObject_C::SetBlock(uint32_t block, uint32_t value) { auto storage = reinterpret_cast(this->m_obj); storage[block] = value; diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index cd5b442..8ca0416 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -13,6 +13,7 @@ class CGObject_C : public CGObject, public TSHashObject Date: Tue, 13 Jan 2026 19:21:56 -0600 Subject: [PATCH 026/269] feat(object): add CClientObjCreate::Skip --- src/object/client/CClientObjCreate.cpp | 63 ++++++++++++++++++++++++++ src/object/client/CClientObjCreate.hpp | 1 + 2 files changed, 64 insertions(+) diff --git a/src/object/client/CClientObjCreate.cpp b/src/object/client/CClientObjCreate.cpp index ed99e1a..49d8249 100644 --- a/src/object/client/CClientObjCreate.cpp +++ b/src/object/client/CClientObjCreate.cpp @@ -4,6 +4,69 @@ #include "util/Unimplemented.hpp" #include +void CClientObjCreate::Skip(CDataStore* msg) { + uint16_t flags; + msg->Get(flags); + + if (flags & 0x20) { + CClientMoveUpdate::Skip(msg); + } else if (flags & 0x100) { + SmartGUID guid; + *msg >> guid; + + C3Vector position28; + *msg >> position28; + + C3Vector position18; + *msg >> position18; + + float facing34; + msg->Get(facing34); + + float facing24; + msg->Get(facing24); + } else if (flags & 0x40) { + C3Vector position28; + *msg >> position28; + + float facing34; + msg->Get(facing34); + } + + if (flags & 0x8) { + uint32_t uint2AC; + msg->Get(uint2AC); + } + + if (flags & 0x10) { + uint32_t uint2B0; + msg->Get(uint2B0); + } + + if (flags & 0x4) { + SmartGUID guid2B8; + *msg >> guid2B8; + } + + if (flags & 0x2) { + uint32_t uint2C0; + msg->Get(uint2C0); + } + + if (flags & 0x80) { + uint32_t uint2C4; + msg->Get(uint2C4); + + float float2C8; + msg->Get(float2C8); + } + + if (flags & 0x200) { + uint64_t uint2D4; + msg->Get(uint2D4); + } +} + int32_t CClientObjCreate::Get(CDataStore* msg) { uint16_t flags; msg->Get(flags); diff --git a/src/object/client/CClientObjCreate.hpp b/src/object/client/CClientObjCreate.hpp index 5d8baf8..ef41077 100644 --- a/src/object/client/CClientObjCreate.hpp +++ b/src/object/client/CClientObjCreate.hpp @@ -20,6 +20,7 @@ struct CClientObjCreate { // TODO WOWGUID guid2D4 = 0; + static void Skip(CDataStore* msg); int32_t Get(CDataStore* msg); }; From 31fca1706441071128af5aac214b00612d5ab94a Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 19:24:35 -0600 Subject: [PATCH 027/269] fix(object): correct read in CClientObjCreate::Get --- src/object/client/CClientObjCreate.cpp | 6 ++---- src/object/client/CClientObjCreate.hpp | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/object/client/CClientObjCreate.cpp b/src/object/client/CClientObjCreate.cpp index 49d8249..2122aa8 100644 --- a/src/object/client/CClientObjCreate.cpp +++ b/src/object/client/CClientObjCreate.cpp @@ -124,11 +124,9 @@ int32_t CClientObjCreate::Get(CDataStore* msg) { } if (this->flags & 0x200) { - SmartGUID guid; - *msg >> guid; - this->guid2D4 = guid; + msg->Get(this->uint2D4); } else { - this->guid2D4 = 0; + this->uint2D4 = 0; } return msg->Size() >= msg->Tell(); diff --git a/src/object/client/CClientObjCreate.hpp b/src/object/client/CClientObjCreate.hpp index ef41077..7480f8c 100644 --- a/src/object/client/CClientObjCreate.hpp +++ b/src/object/client/CClientObjCreate.hpp @@ -18,7 +18,7 @@ struct CClientObjCreate { uint32_t uint2C4; float float2C8; // TODO - WOWGUID guid2D4 = 0; + uint64_t uint2D4 = 0; // TODO guid? static void Skip(CDataStore* msg); int32_t Get(CDataStore* msg); From 1e13e33f2a41ccdd6f55d70b729eb44184c892e6 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 19:50:39 -0600 Subject: [PATCH 028/269] feat(object): add CClientMoveUpdate::Skip --- src/object/client/CClientMoveUpdate.cpp | 11 +++++++ src/object/client/CClientMoveUpdate.hpp | 2 ++ src/object/movement/CMoveSpline.cpp | 23 ++++++++++++++ src/object/movement/CMoveSpline.hpp | 2 ++ src/object/movement/CMovementStatus.cpp | 42 +++++++++++++++++++++++++ src/object/movement/CMovementStatus.hpp | 2 ++ 6 files changed, 82 insertions(+) diff --git a/src/object/client/CClientMoveUpdate.cpp b/src/object/client/CClientMoveUpdate.cpp index 1ca03be..8544098 100644 --- a/src/object/client/CClientMoveUpdate.cpp +++ b/src/object/client/CClientMoveUpdate.cpp @@ -1,5 +1,16 @@ #include "object/client/CClientMoveUpdate.hpp" +void CClientMoveUpdate::Skip(CDataStore* msg) { + uint32_t moveFlags = CMovementStatus::Skip(msg); + + void* data; + msg->GetDataInSitu(data, 9 * sizeof(float)); + + if (moveFlags & 0x8000000) { + CMoveSpline::Skip(msg); + } +} + CDataStore& operator>>(CDataStore& msg, CClientMoveUpdate& move) { msg >> move.status; diff --git a/src/object/client/CClientMoveUpdate.hpp b/src/object/client/CClientMoveUpdate.hpp index 2cde73e..7a05e65 100644 --- a/src/object/client/CClientMoveUpdate.hpp +++ b/src/object/client/CClientMoveUpdate.hpp @@ -18,6 +18,8 @@ struct CClientMoveUpdate { float float80; // TODO CMoveSpline spline; + + static void Skip(CDataStore* msg); }; CDataStore& operator>>(CDataStore& msg, CClientMoveUpdate& move); diff --git a/src/object/movement/CMoveSpline.cpp b/src/object/movement/CMoveSpline.cpp index dab5c66..1c76dea 100644 --- a/src/object/movement/CMoveSpline.cpp +++ b/src/object/movement/CMoveSpline.cpp @@ -2,6 +2,29 @@ #include "util/DataStore.hpp" #include +void CMoveSpline::Skip(CDataStore* msg) { + uint32_t flags; + msg->Get(flags); + + uint32_t faceBytes = 0; + + if (flags & 0x20000) { + faceBytes = 4; + } else if (flags & 0x10000) { + faceBytes = 8; + } else if (flags & 0x8000) { + faceBytes = 12; + } + + void* data; + msg->GetDataInSitu(data, faceBytes + 28); + + uint32_t splinePoints = 0; + msg->Get(splinePoints); + + msg->GetDataInSitu(data, (splinePoints * sizeof(C3Vector)) + 13); +} + CDataStore& operator>>(CDataStore& msg, CMoveSpline& spline) { msg.Get(spline.flags); diff --git a/src/object/movement/CMoveSpline.hpp b/src/object/movement/CMoveSpline.hpp index 0f8ff90..6d361af 100644 --- a/src/object/movement/CMoveSpline.hpp +++ b/src/object/movement/CMoveSpline.hpp @@ -25,6 +25,8 @@ struct CMoveSpline { float float20C; uint32_t uint210; // TODO + + static void Skip(CDataStore* msg); }; CDataStore& operator>>(CDataStore& msg, CMoveSpline& spline); diff --git a/src/object/movement/CMovementStatus.cpp b/src/object/movement/CMovementStatus.cpp index 1131615..844b65f 100644 --- a/src/object/movement/CMovementStatus.cpp +++ b/src/object/movement/CMovementStatus.cpp @@ -1,6 +1,48 @@ #include "object/movement/CMovementStatus.hpp" #include "util/DataStore.hpp" +uint32_t CMovementStatus::Skip(CDataStore* msg) { + uint32_t moveFlags = 0; + msg->Get(moveFlags); + + uint16_t uint14; + msg->Get(uint14); + + void* data; + msg->GetDataInSitu(data, 20); + + uint32_t skipBytes = 0; + + if (moveFlags & 0x200) { + SmartGUID guid; + *msg >> guid; + + skipBytes += 21; + + if (uint14 & 0x400) { + skipBytes += 4; + } + } + + if ((moveFlags & (0x200000 | 0x2000000)) || (uint14 & 0x20)) { + skipBytes += 4; + } + + skipBytes += 4; + + if (moveFlags & 0x1000) { + skipBytes += 16; + } + + if (moveFlags & 0x4000000) { + skipBytes += 4; + } + + msg->GetDataInSitu(data, skipBytes); + + return moveFlags; +} + CDataStore& operator>>(CDataStore& msg, CMovementStatus& move) { msg.Get(move.moveFlags); msg.Get(move.uint14); diff --git a/src/object/movement/CMovementStatus.hpp b/src/object/movement/CMovementStatus.hpp index 42993da..517c24c 100644 --- a/src/object/movement/CMovementStatus.hpp +++ b/src/object/movement/CMovementStatus.hpp @@ -25,6 +25,8 @@ struct CMovementStatus { float float4C = 0.0f; float float50 = 0.0f; // TODO + + static uint32_t Skip(CDataStore* msg); }; CDataStore& operator>>(CDataStore& msg, CMovementStatus& move); From 082bc06c69120769b8d41fe58c704e0dfa48b6c3 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 19:54:04 -0600 Subject: [PATCH 029/269] feat(object): handle existing objects in CreateObject --- src/object/client/MessageHandlers.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index 5d9ef36..f60025d 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -218,8 +218,17 @@ int32_t CreateObject(CDataStore* msg, uint32_t time) { auto existingObject = GetUpdateObject(guid, &reenabled); if (existingObject) { - // TODO - return 0; + CClientObjCreate::Skip(msg); + + if (!FillInPartialObjectData(existingObject, existingObject->m_obj->m_guid, msg, false, true)) { + return 0; + } + + if (reenabled) { + existingObject->Reenable(); + } + + return 1; } CClientObjCreate objCreate; From f44ba4bf63e4492529a1c881e490bf9f3d9c1f0d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 19:54:53 -0600 Subject: [PATCH 030/269] fix(object): properly skip move updates in ObjectUpdateFirstPass --- src/object/client/MessageHandlers.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index f60025d..af8621b 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -276,11 +276,12 @@ int32_t ObjectUpdateFirstPass(CDataStore* msg, uint32_t time, uint32_t updateIdx } case UPDATE_MOVEMENT: { - // Read but ignored in first pass + // Skipped in first pass + SmartGUID guid; *msg >> guid; - UpdateObjectMovement(msg); + CClientMoveUpdate::Skip(msg); break; } From b7c3735e7f1e7d382f2ad7f0b8bbe8dfd5c162eb Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 20:41:59 -0600 Subject: [PATCH 031/269] fix(object): correct types for various members of CGUnitData --- src/object/client/CGUnit.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/object/client/CGUnit.hpp b/src/object/client/CGUnit.hpp index 6ca29fa..0577be0 100644 --- a/src/object/client/CGUnit.hpp +++ b/src/object/client/CGUnit.hpp @@ -19,7 +19,7 @@ struct CGUnitData { int32_t power[7]; int32_t maxHealth; int32_t maxPower[7]; - int32_t powerRegenFlatModifier[7]; + float powerRegenFlatModifier[7]; int32_t powerRegenInterruptedFlatModifier[7]; int32_t level; int32_t factionTemplate; @@ -34,8 +34,8 @@ struct CGUnitData { int32_t displayID; int32_t nativeDisplayID; int32_t mountDisplayID; - uint32_t minDamage; - uint32_t maxDamage; + float minDamage; + float maxDamage; uint32_t minOffhandDamage; uint32_t maxOffhandDamage; int32_t pad2; @@ -44,7 +44,7 @@ struct CGUnitData { uint32_t petExperience; uint32_t petNextLevelExperience; uint32_t dynamicFlags; - int32_t modCastingSpeed; + float modCastingSpeed; int32_t createdBySpell; uint32_t npcFlags; uint32_t emoteState; @@ -63,12 +63,12 @@ struct CGUnitData { int32_t rangedAttackPower; int32_t rangedAttackPowerMods; int32_t rangedAttackPowerMultiplier; - int32_t minRangedDamage; - int32_t maxRangedDamage; + float minRangedDamage; + float maxRangedDamage; int32_t powerCostModifier[7]; int32_t powerCostMultiplier[7]; int32_t maxHealthModifier; - int32_t hoverHeight; + float hoverHeight; int32_t pad4; }; From 8615757d54e66237e22ff3e9a800cc62352e2f26 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 21:03:07 -0600 Subject: [PATCH 032/269] feat(object): implement UpdateObject --- src/object/client/MessageHandlers.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index af8621b..a909e77 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -43,12 +43,35 @@ CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenabled) { return nullptr; } +int32_t SkipPartialObjectUpdate(CDataStore* msg) { + // TODO + return 0; +} + void UpdateOutOfRangeObjects(CDataStore* msg) { WHOA_UNIMPLEMENTED(); } int32_t UpdateObject(CDataStore* msg) { - WHOA_UNIMPLEMENTED(0); + SmartGUID guid; + *msg >> guid; + + int32_t reenabled; + auto object = GetUpdateObject(guid, &reenabled); + + if (object) { + if (!FillInPartialObjectData(object, object->m_obj->m_guid, msg, false, false)) { + return 0; + } + + if (reenabled) { + object->Reenable(); + } + + return 1; + } + + return SkipPartialObjectUpdate(msg); } void UpdateObjectMovement(CDataStore* msg) { From d18a479bfb92b4d848ff6441f2f21bc9a26c844f Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 21:05:29 -0600 Subject: [PATCH 033/269] chore(object): move GetUpdateObject to util --- src/object/client/MessageHandlers.cpp | 15 --------------- src/object/client/Util.cpp | 15 +++++++++++++++ src/object/client/Util.hpp | 3 +++ 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index a909e77..71bb508 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -28,21 +28,6 @@ enum UPDATE_TYPE { UPDATE_IN_RANGE = 5, }; -CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenabled) { - *reenabled = false; - - auto activeObject = FindActiveObject(guid); - - if (activeObject) { - activeObject->SetDisablePending(false); - - return activeObject; - } - - // TODO handle reenabling object - return nullptr; -} - int32_t SkipPartialObjectUpdate(CDataStore* msg) { // TODO return 0; diff --git a/src/object/client/Util.cpp b/src/object/client/Util.cpp index b243c21..743346d 100644 --- a/src/object/client/Util.cpp +++ b/src/object/client/Util.cpp @@ -4,3 +4,18 @@ CGObject_C* FindActiveObject(WOWGUID guid) { return ClntObjMgrGetCurrent()->m_objects.Ptr(guid, CHashKeyGUID(guid)); } + +CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenabled) { + *reenabled = false; + + auto activeObject = FindActiveObject(guid); + + if (activeObject) { + activeObject->SetDisablePending(false); + + return activeObject; + } + + // TODO handle reenabling object + return nullptr; +} diff --git a/src/object/client/Util.hpp b/src/object/client/Util.hpp index 8903851..7cb677a 100644 --- a/src/object/client/Util.hpp +++ b/src/object/client/Util.hpp @@ -2,9 +2,12 @@ #define OBJECT_CLIENT_UTIL_HPP #include "util/GUID.hpp" +#include class CGObject_C; CGObject_C* FindActiveObject(WOWGUID guid); +CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenabled); + #endif From ae911d94ad04086a5951be9a6c4870038791d689 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 21:18:34 -0600 Subject: [PATCH 034/269] chore(object): move InitObject to util --- src/object/client/MessageHandlers.cpp | 55 ----------------------- src/object/client/Util.cpp | 64 +++++++++++++++++++++++++++ src/object/client/Util.hpp | 3 ++ 3 files changed, 67 insertions(+), 55 deletions(-) diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index 71bb508..ef353e2 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -159,61 +159,6 @@ void SetupObjectStorage(OBJECT_TYPE_ID typeID, CGObject_C* object, WOWGUID guid) } } -void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate) { - switch (object->m_typeID) { - case ID_ITEM: { - new (object) CGItem_C(time, objCreate); - - break; - } - - case ID_CONTAINER: { - new (object) CGContainer_C(time, objCreate); - - break; - } - - case ID_UNIT: { - new (object) CGUnit_C(time, objCreate); - object->AddWorldObject(); - - break; - } - - case ID_PLAYER: { - new (object) CGPlayer_C(time, objCreate); - object->AddWorldObject(); - - break; - } - - case ID_GAMEOBJECT: { - new (object) CGGameObject_C(time, objCreate); - object->AddWorldObject(); - - break; - } - - case ID_DYNAMICOBJECT: { - new (object) CGDynamicObject_C(time, objCreate); - object->AddWorldObject(); - - break; - } - - case ID_CORPSE: { - new (object) CGCorpse_C(time, objCreate); - object->AddWorldObject(); - - break; - } - - default: { - break; - } - } -} - int32_t CreateObject(CDataStore* msg, uint32_t time) { SmartGUID guid; *msg >> guid; diff --git a/src/object/client/Util.cpp b/src/object/client/Util.cpp index 743346d..4690487 100644 --- a/src/object/client/Util.cpp +++ b/src/object/client/Util.cpp @@ -1,4 +1,13 @@ #include "object/client/Util.hpp" +#include "object/client/CClientObjCreate.hpp" +#include "object/client/CGContainer_C.hpp" +#include "object/client/CGCorpse_C.hpp" +#include "object/client/CGDynamicObject_C.hpp" +#include "object/client/CGGameObject_C.hpp" +#include "object/client/CGItem_C.hpp" +#include "object/client/CGObject_C.hpp" +#include "object/client/CGPlayer_C.hpp" +#include "object/client/CGUnit_C.hpp" #include "object/client/ObjMgr.hpp" CGObject_C* FindActiveObject(WOWGUID guid) { @@ -19,3 +28,58 @@ CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenabled) { // TODO handle reenabling object return nullptr; } + +void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate) { + switch (object->m_typeID) { + case ID_ITEM: { + new (object) CGItem_C(time, objCreate); + + break; + } + + case ID_CONTAINER: { + new (object) CGContainer_C(time, objCreate); + + break; + } + + case ID_UNIT: { + new (object) CGUnit_C(time, objCreate); + object->AddWorldObject(); + + break; + } + + case ID_PLAYER: { + new (object) CGPlayer_C(time, objCreate); + object->AddWorldObject(); + + break; + } + + case ID_GAMEOBJECT: { + new (object) CGGameObject_C(time, objCreate); + object->AddWorldObject(); + + break; + } + + case ID_DYNAMICOBJECT: { + new (object) CGDynamicObject_C(time, objCreate); + object->AddWorldObject(); + + break; + } + + case ID_CORPSE: { + new (object) CGCorpse_C(time, objCreate); + object->AddWorldObject(); + + break; + } + + default: { + break; + } + } +} diff --git a/src/object/client/Util.hpp b/src/object/client/Util.hpp index 7cb677a..08cc115 100644 --- a/src/object/client/Util.hpp +++ b/src/object/client/Util.hpp @@ -4,10 +4,13 @@ #include "util/GUID.hpp" #include +class CClientObjCreate; class CGObject_C; CGObject_C* FindActiveObject(WOWGUID guid); CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenabled); +void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate); + #endif From 72d52475633310a1741857fd11d88fc44d1d7927 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 21:36:53 -0600 Subject: [PATCH 035/269] feat(object): implement UpdateInRangeObjects --- src/object/client/MessageHandlers.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index ef353e2..13b6fca 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -211,7 +211,22 @@ int32_t CreateObject(CDataStore* msg, uint32_t time) { } void UpdateInRangeObjects(CDataStore* msg) { - WHOA_UNIMPLEMENTED(); + uint32_t count; + msg->Get(count); + + for (int32_t i = 0; i < count; i++) { + SmartGUID guid; + *msg >> guid; + + if (guid != ClntObjMgrGetActivePlayer()) { + int32_t reenabled; + auto object = GetUpdateObject(guid, &reenabled); + + if (object && reenabled) { + object->Reenable(); + } + } + } } int32_t ObjectUpdateFirstPass(CDataStore* msg, uint32_t time, uint32_t updateIdx, uint32_t updateCount) { From 56f645fe3b693c214730ddeedec7d3b7384443e5 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 22:34:44 -0600 Subject: [PATCH 036/269] feat(object): link newly created objects to visible list --- src/object/client/CGObject_C.hpp | 4 ++++ src/object/client/ClntObjMgr.hpp | 3 +++ src/object/client/MessageHandlers.cpp | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index 8ca0416..cb0a3a0 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -6,9 +6,13 @@ #include "object/client/CGObject.hpp" #include "util/GUID.hpp" #include +#include class CGObject_C : public CGObject, public TSHashObject { public: + // Public member variables + TSLink m_link; + // Public member functions CGObject_C() = default; CGObject_C(uint32_t time, CClientObjCreate& objCreate); diff --git a/src/object/client/ClntObjMgr.hpp b/src/object/client/ClntObjMgr.hpp index 51cd561..baf848d 100644 --- a/src/object/client/ClntObjMgr.hpp +++ b/src/object/client/ClntObjMgr.hpp @@ -3,6 +3,7 @@ #include "object/client/CGObject_C.hpp" #include +#include #include class ClientConnection; @@ -12,6 +13,8 @@ class ClntObjMgr { // Member variables TSHashTable m_objects; // TODO + STORM_EXPLICIT_LIST(CGObject_C, m_link) m_visibleObjects; + // TODO WOWGUID m_activePlayer = 0; uint32_t m_mapID = 0; ClientConnection* m_net = nullptr; diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index 13b6fca..b50a672 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -205,7 +205,7 @@ int32_t CreateObject(CDataStore* msg, uint32_t time) { InitObject(newObject, time, objCreate); - // TODO link to one of the ClntObjMgr lists + ClntObjMgrGetCurrent()->m_visibleObjects.LinkToTail(newObject); return 1; } From 3332062f86707ea251a1fdbeace55adb12caae67 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 13 Jan 2026 23:04:21 -0600 Subject: [PATCH 037/269] feat(object): handle disabled objects in GetUpdateObject --- src/object/client/ClntObjMgr.hpp | 2 ++ src/object/client/Util.cpp | 29 ++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/object/client/ClntObjMgr.hpp b/src/object/client/ClntObjMgr.hpp index baf848d..7cd4fe3 100644 --- a/src/object/client/ClntObjMgr.hpp +++ b/src/object/client/ClntObjMgr.hpp @@ -12,8 +12,10 @@ class ClntObjMgr { public: // Member variables TSHashTable m_objects; + TSHashTable m_lazyCleanupObjects; // TODO STORM_EXPLICIT_LIST(CGObject_C, m_link) m_visibleObjects; + STORM_EXPLICIT_LIST(CGObject_C, m_link) m_reenabledObjects; // TODO WOWGUID m_activePlayer = 0; uint32_t m_mapID = 0; diff --git a/src/object/client/Util.cpp b/src/object/client/Util.cpp index 4690487..b4142ca 100644 --- a/src/object/client/Util.cpp +++ b/src/object/client/Util.cpp @@ -17,6 +17,8 @@ CGObject_C* FindActiveObject(WOWGUID guid) { CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenabled) { *reenabled = false; + // Active object + auto activeObject = FindActiveObject(guid); if (activeObject) { @@ -25,7 +27,32 @@ CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenabled) { return activeObject; } - // TODO handle reenabling object + // Disabled object + + auto disabledObject = ClntObjMgrGetCurrent()->m_lazyCleanupObjects.Ptr(guid, CHashKeyGUID(guid)); + + if (disabledObject) { + ClntObjMgrGetCurrent()->m_lazyCleanupObjects.Unlink(disabledObject); + disabledObject->m_link.Unlink(); + + ClntObjMgrGetCurrent()->m_objects.Insert(disabledObject, guid, CHashKeyGUID(guid)); + + // These link checks are guaranteed to pass because of the unlink above (both lists share + // the same link). This check is either from an inlined function or is cruft left behind + // after a refactor. + if ( + !ClntObjMgrGetCurrent()->m_visibleObjects.IsLinked(disabledObject) + && !ClntObjMgrGetCurrent()->m_reenabledObjects.IsLinked(disabledObject) + ) { + *reenabled = true; + ClntObjMgrGetCurrent()->m_reenabledObjects.LinkToTail(disabledObject); + } + + return disabledObject; + } + + // Object not found + return nullptr; } From 7e994ff19592b5ffe7f41d6a494f087479ae3d7a Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 14 Jan 2026 16:42:07 -0600 Subject: [PATCH 038/269] feat(object): add remaining members to CGPlayerData --- src/object/client/CGPlayer.hpp | 93 ++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 5 deletions(-) diff --git a/src/object/client/CGPlayer.hpp b/src/object/client/CGPlayer.hpp index 7ef380b..c20fd0c 100644 --- a/src/object/client/CGPlayer.hpp +++ b/src/object/client/CGPlayer.hpp @@ -19,21 +19,49 @@ struct CVisibleItemData { uint32_t enchantment; }; +struct CSkillInfo { + uint16_t skillLineID; + uint16_t skillStep; + uint16_t skillRank; + uint16_t skillMaxRank; + int16_t skillTempModifier; + int16_t skillPermModifier; +}; + +struct CArenaTeamInfo { + uint32_t field1; + uint32_t field2; + uint32_t field3; + uint32_t field4; + uint32_t field5; + uint32_t field6; + uint32_t field7; +}; + struct CGPlayerData { WOWGUID duelArbiter; uint32_t flags; uint32_t guildID; uint32_t guildRank; - int32_t pad1; - int32_t pad2; - int32_t pad3; + uint8_t skinID; + uint8_t faceID; + uint8_t hairStyleID; + uint8_t hairColorID; + uint8_t facialHairStyleID; + uint8_t bytes_2_2; // TODO + uint8_t bytes_2_3; // TODO + uint8_t restState; + uint8_t bytes_3_1; // TODO + uint8_t bytes_3_2; // TODO + uint8_t bytes_3_3; // TODO + uint8_t bytes_3_4; // TODO uint32_t duelTeam; int32_t guildTimestamp; CQuestLogData questLog[25]; CVisibleItemData visibleItems[19]; int32_t chosenTitle; int32_t fakeInebriation; - int32_t pad4; + int32_t pad1; WOWGUID invSlots[NUM_INVENTORY_SLOTS]; WOWGUID packSlots[16]; WOWGUID bankSlots[28]; @@ -48,7 +76,62 @@ struct CGPlayerData { WOWGUID knownCurrencies; uint32_t xp; uint32_t nextLevelXP; - // TODO + CSkillInfo skillInfo[128]; + int32_t characterPoints[2]; + uint32_t trackCreatureMask; + uint32_t trackResourceMask; + float blockPercentage; + float dodgePercentage; + float parryPercentage; + int32_t expertise; + int32_t offhandExpertise; + float critPercentage; + float rangedCritPercentage; + float offhandCritPercentage; + float spellCritPercentage[7]; + int32_t shieldBlock; + float shieldBlockCritPercentage; + uint8_t exploredZones[512]; + uint32_t restStateXP; + uint32_t coinage; + int32_t modDamageDonePos[7]; + int32_t modDamageDoneNeg[7]; + float modDamageDonePct[7]; + uint32_t modHealingDonePos; + float modHealingPct; + float modHealingDonePct; + int32_t modTargetResistance; + int32_t modTargetPhysicalResistance; + uint8_t field_bytes_1; // TODO + uint8_t field_bytes_2; // TODO + uint8_t field_bytes_3; // TODO + uint8_t field_bytes_4; // TODO + int32_t ammoID; + int32_t selfResSpell; + uint32_t pvpMedals; + uint32_t buybackPrice[12]; + uint32_t buybackTimestamp[12]; + uint16_t kills[2]; + uint32_t todayContribution; + uint32_t yesterdayContribution; + uint32_t lifetimeHonorableKills; + uint8_t field_bytes_2_1; // TODO + uint8_t field_bytes_2_2; // TODO + uint8_t field_bytes_2_3; // TODO + uint8_t field_bytes_2_4; // TODO + int32_t watchedFactionIndex; + uint32_t combatRating[25]; + CArenaTeamInfo arenaTeamInfo[3]; + uint32_t honorCurrency; + uint32_t arenaCurrency; + uint32_t maxLevel; + uint32_t dailyQuests[25]; + float runeRegen[4]; + uint32_t noReagentCost[3]; + uint32_t glyphSlots[6]; + uint32_t glyphs[6]; + int32_t glyphsEnabled; + uint32_t petSpellPower; }; class CGPlayer { From 2bb8da6971833818528c8579837a07b66f997ca7 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 14 Jan 2026 23:37:40 -0600 Subject: [PATCH 039/269] feat(object): add ClntObjMgrObjectPtr --- src/object/client/ObjMgr.cpp | 19 +++++++++++++++++++ src/object/client/ObjMgr.hpp | 2 ++ 2 files changed, 21 insertions(+) diff --git a/src/object/client/ObjMgr.cpp b/src/object/client/ObjMgr.cpp index d20711a..cd9d5ac 100644 --- a/src/object/client/ObjMgr.cpp +++ b/src/object/client/ObjMgr.cpp @@ -11,6 +11,7 @@ #include "object/client/CGPlayer_C.hpp" #include "object/client/CGUnit_C.hpp" #include "object/client/MessageHandlers.hpp" +#include "object/client/Util.hpp" #include "util/Unimplemented.hpp" #include #include @@ -143,6 +144,24 @@ void ClntObjMgrLinkInNewObject(CGObject_C* object) { s_curMgr->m_objects.Insert(object, object->m_obj->m_guid, key); } +CGObject_C* ClntObjMgrObjectPtr(WOWGUID guid, OBJECT_TYPE type) { + if (!s_curMgr || !guid) { + return nullptr; + } + + auto object = FindActiveObject(guid); + + if (!object) { + return nullptr; + } + + if (!(object->m_obj->m_type & type)) { + return nullptr; + } + + return object; +} + void ClntObjMgrPop() { if (!s_savMgr) { return; diff --git a/src/object/client/ObjMgr.hpp b/src/object/client/ObjMgr.hpp index 5d5b0a1..0610b7c 100644 --- a/src/object/client/ObjMgr.hpp +++ b/src/object/client/ObjMgr.hpp @@ -20,6 +20,8 @@ void ClntObjMgrInitializeStd(uint32_t mapID); void ClntObjMgrLinkInNewObject(CGObject_C* object); +CGObject_C* ClntObjMgrObjectPtr(WOWGUID guid, OBJECT_TYPE type); + void ClntObjMgrPop(); void ClntObjMgrPush(ClntObjMgr* mgr); From 8a062e56316bdc3027520d8736c3c2a900c474dc Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 14 Jan 2026 23:43:56 -0600 Subject: [PATCH 040/269] chore(object): correct params for ClntObjMgrObjectPtr --- src/object/client/ObjMgr.cpp | 2 +- src/object/client/ObjMgr.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/object/client/ObjMgr.cpp b/src/object/client/ObjMgr.cpp index cd9d5ac..d65b186 100644 --- a/src/object/client/ObjMgr.cpp +++ b/src/object/client/ObjMgr.cpp @@ -144,7 +144,7 @@ void ClntObjMgrLinkInNewObject(CGObject_C* object) { s_curMgr->m_objects.Insert(object, object->m_obj->m_guid, key); } -CGObject_C* ClntObjMgrObjectPtr(WOWGUID guid, OBJECT_TYPE type) { +CGObject_C* ClntObjMgrObjectPtr(WOWGUID guid, OBJECT_TYPE type, const char* fileName, int32_t lineNumber) { if (!s_curMgr || !guid) { return nullptr; } diff --git a/src/object/client/ObjMgr.hpp b/src/object/client/ObjMgr.hpp index 0610b7c..c5ea706 100644 --- a/src/object/client/ObjMgr.hpp +++ b/src/object/client/ObjMgr.hpp @@ -20,7 +20,7 @@ void ClntObjMgrInitializeStd(uint32_t mapID); void ClntObjMgrLinkInNewObject(CGObject_C* object); -CGObject_C* ClntObjMgrObjectPtr(WOWGUID guid, OBJECT_TYPE type); +CGObject_C* ClntObjMgrObjectPtr(WOWGUID guid, OBJECT_TYPE type, const char* fileName, int32_t lineNumber); void ClntObjMgrPop(); From 361d327f3061f9a40d620e43a650fe10f1c40a1d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 15 Jan 2026 15:57:17 -0600 Subject: [PATCH 041/269] feat(object): implement CGObject_C::SetDisablePending --- src/object/client/CGObject_C.cpp | 15 ++++++++++++++- src/object/client/CGObject_C.hpp | 7 +++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 07257a0..589cc60 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -4,6 +4,15 @@ CGObject_C::CGObject_C(uint32_t time, CClientObjCreate& objCreate) { // TODO + this->m_lockCount = 0; + this->m_disabled = 0; + this->m_inReenable = 0; + this->m_postInited = 0; + this->m_flag19 = 0; + this->m_disablePending = 0; + + // TODO + ClntObjMgrLinkInNewObject(this); // TODO @@ -23,7 +32,11 @@ void CGObject_C::SetBlock(uint32_t block, uint32_t value) { } void CGObject_C::SetDisablePending(int32_t pending) { - // TODO + if (pending) { + this->m_disablePending = true; + } else { + this->m_disablePending = false; + } } void CGObject_C::SetStorage(uint32_t* storage, uint32_t* saved) { diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index cb0a3a0..0633ec2 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -12,6 +12,13 @@ class CGObject_C : public CGObject, public TSHashObject m_link; + // TODO + uint32_t m_lockCount : 16; + uint32_t m_disabled : 1; + uint32_t m_inReenable : 1; + uint32_t m_postInited : 1; + uint32_t m_flag19 : 1; + uint32_t m_disablePending : 1; // Public member functions CGObject_C() = default; From e2bfef907a3d9204f80d33dc31c21d850c3453fc Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 15 Jan 2026 16:00:30 -0600 Subject: [PATCH 042/269] chore(object): rename parameter for clarity --- src/object/client/MessageHandlers.cpp | 18 +++++++++--------- src/object/client/Util.cpp | 6 +++--- src/object/client/Util.hpp | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index b50a672..9d38647 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -41,15 +41,15 @@ int32_t UpdateObject(CDataStore* msg) { SmartGUID guid; *msg >> guid; - int32_t reenabled; - auto object = GetUpdateObject(guid, &reenabled); + int32_t reenable; + auto object = GetUpdateObject(guid, &reenable); if (object) { if (!FillInPartialObjectData(object, object->m_obj->m_guid, msg, false, false)) { return 0; } - if (reenabled) { + if (reenable) { object->Reenable(); } @@ -167,8 +167,8 @@ int32_t CreateObject(CDataStore* msg, uint32_t time) { msg->Get(_typeID); auto typeID = static_cast(_typeID); - int32_t reenabled; - auto existingObject = GetUpdateObject(guid, &reenabled); + int32_t reenable; + auto existingObject = GetUpdateObject(guid, &reenable); if (existingObject) { CClientObjCreate::Skip(msg); @@ -177,7 +177,7 @@ int32_t CreateObject(CDataStore* msg, uint32_t time) { return 0; } - if (reenabled) { + if (reenable) { existingObject->Reenable(); } @@ -219,10 +219,10 @@ void UpdateInRangeObjects(CDataStore* msg) { *msg >> guid; if (guid != ClntObjMgrGetActivePlayer()) { - int32_t reenabled; - auto object = GetUpdateObject(guid, &reenabled); + int32_t reenable; + auto object = GetUpdateObject(guid, &reenable); - if (object && reenabled) { + if (object && reenable) { object->Reenable(); } } diff --git a/src/object/client/Util.cpp b/src/object/client/Util.cpp index b4142ca..b1209d1 100644 --- a/src/object/client/Util.cpp +++ b/src/object/client/Util.cpp @@ -14,8 +14,8 @@ CGObject_C* FindActiveObject(WOWGUID guid) { return ClntObjMgrGetCurrent()->m_objects.Ptr(guid, CHashKeyGUID(guid)); } -CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenabled) { - *reenabled = false; +CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenable) { + *reenable = false; // Active object @@ -44,7 +44,7 @@ CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenabled) { !ClntObjMgrGetCurrent()->m_visibleObjects.IsLinked(disabledObject) && !ClntObjMgrGetCurrent()->m_reenabledObjects.IsLinked(disabledObject) ) { - *reenabled = true; + *reenable = true; ClntObjMgrGetCurrent()->m_reenabledObjects.LinkToTail(disabledObject); } diff --git a/src/object/client/Util.hpp b/src/object/client/Util.hpp index 08cc115..49ea67b 100644 --- a/src/object/client/Util.hpp +++ b/src/object/client/Util.hpp @@ -9,7 +9,7 @@ class CGObject_C; CGObject_C* FindActiveObject(WOWGUID guid); -CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenabled); +CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenable); void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate); From a43ab566444abb55ba91918842d23256c77d33a1 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 15 Jan 2026 16:21:41 -0600 Subject: [PATCH 043/269] feat(object): partially implement CGObject_C::Reenable --- src/object/client/CGObject_C.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 589cc60..6261902 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -5,11 +5,11 @@ CGObject_C::CGObject_C(uint32_t time, CClientObjCreate& objCreate) { // TODO this->m_lockCount = 0; - this->m_disabled = 0; - this->m_inReenable = 0; - this->m_postInited = 0; - this->m_flag19 = 0; - this->m_disablePending = 0; + this->m_disabled = false; + this->m_inReenable = false; + this->m_postInited = false; + this->m_flag19 = false; + this->m_disablePending = false; // TODO @@ -23,6 +23,9 @@ void CGObject_C::AddWorldObject() { } void CGObject_C::Reenable() { + this->m_disabled = false; + this->m_inReenable = true; + // TODO } From ba0baf16887572efe5f54ce6f6f3de3410c6e54e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 15 Jan 2026 16:24:45 -0600 Subject: [PATCH 044/269] feat(object): add CGObject_C::IsInReenable --- src/object/client/CGObject_C.cpp | 4 ++++ src/object/client/CGObject_C.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 6261902..99896c9 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -22,6 +22,10 @@ void CGObject_C::AddWorldObject() { // TODO } +int32_t CGObject_C::IsInReenable() { + return this->m_inReenable; +} + void CGObject_C::Reenable() { this->m_disabled = false; this->m_inReenable = true; diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index 0633ec2..d857eb9 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -24,6 +24,7 @@ class CGObject_C : public CGObject, public TSHashObject Date: Thu, 15 Jan 2026 16:27:40 -0600 Subject: [PATCH 045/269] feat(object): add CGObject_C::IsObjectLocked --- src/object/client/CGObject_C.cpp | 4 ++++ src/object/client/CGObject_C.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 99896c9..ca48222 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -26,6 +26,10 @@ int32_t CGObject_C::IsInReenable() { return this->m_inReenable; } +int32_t CGObject_C::IsObjectLocked() { + return this->m_lockCount != 0; +} + void CGObject_C::Reenable() { this->m_disabled = false; this->m_inReenable = true; diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index d857eb9..2a2cc61 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -25,6 +25,7 @@ class CGObject_C : public CGObject, public TSHashObject Date: Thu, 15 Jan 2026 16:31:42 -0600 Subject: [PATCH 046/269] feat(object): add CGObject_C::SetObjectLocked --- src/object/client/CGObject_C.cpp | 12 ++++++++++++ src/object/client/CGObject_C.hpp | 1 + 2 files changed, 13 insertions(+) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index ca48222..31ca0ac 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -50,6 +50,18 @@ void CGObject_C::SetDisablePending(int32_t pending) { } } +void CGObject_C::SetObjectLocked(int32_t locked) { + if (locked) { + if (this->m_lockCount != 0xFFFF) { + this->m_lockCount++; + } + } else { + if (this->m_lockCount != 0) { + this->m_lockCount--; + } + } +} + void CGObject_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->m_obj = reinterpret_cast(&storage[CGObject::GetBaseOffset()]); this->m_objSaved = &saved[CGObject::GetBaseOffsetSaved()]; diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index 2a2cc61..e139ef8 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -29,6 +29,7 @@ class CGObject_C : public CGObject, public TSHashObject Date: Thu, 15 Jan 2026 20:15:29 -0600 Subject: [PATCH 047/269] feat(object): add OUT_OF_RANGE_TYPE --- src/object/Types.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/object/Types.hpp b/src/object/Types.hpp index 9168c91..952e619 100644 --- a/src/object/Types.hpp +++ b/src/object/Types.hpp @@ -72,6 +72,12 @@ enum OBJECT_TYPE_ID { // TODO }; +enum OUT_OF_RANGE_TYPE { + OUT_OF_RANGE_0 = 0, + OUT_OF_RANGE_1 = 1, + OUT_OF_RANGE_2 = 2, +}; + enum SHEATHE_TYPE { SHEATHE_0 = 0, SHEATHE_1 = 1, From 13ec1d7eef3c8321f3bb4939e173363f0f9a4cab Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 15 Jan 2026 21:04:43 -0600 Subject: [PATCH 048/269] feat(object): add HandleObjectOutOfRangePass1 --- src/object/client/CGObject_C.cpp | 4 ++++ src/object/client/CGObject_C.hpp | 8 ++++++++ src/object/client/Util.cpp | 17 +++++++++++++++++ src/object/client/Util.hpp | 3 +++ 4 files changed, 32 insertions(+) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 31ca0ac..2417717 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -22,6 +22,10 @@ void CGObject_C::AddWorldObject() { // TODO } +void CGObject_C::Disable() { + // TODO +} + int32_t CGObject_C::IsInReenable() { return this->m_inReenable; } diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index e139ef8..9caa2ba 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -19,6 +19,14 @@ class CGObject_C : public CGObject, public TSHashObjectHandleOutOfRange(type); + + if (object->IsObjectLocked()) { + object->SetDisablePending(true); + + return false; + } + + object->SetDisablePending(false); + object->Disable(); + + return true; +} + void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate) { switch (object->m_typeID) { case ID_ITEM: { diff --git a/src/object/client/Util.hpp b/src/object/client/Util.hpp index 49ea67b..0657692 100644 --- a/src/object/client/Util.hpp +++ b/src/object/client/Util.hpp @@ -1,6 +1,7 @@ #ifndef OBJECT_CLIENT_UTIL_HPP #define OBJECT_CLIENT_UTIL_HPP +#include "object/Types.hpp" #include "util/GUID.hpp" #include @@ -11,6 +12,8 @@ CGObject_C* FindActiveObject(WOWGUID guid); CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenable); +int32_t HandleObjectOutOfRangePass1(CGObject_C* object, OUT_OF_RANGE_TYPE type); + void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate); #endif From cd3585ca420161d1ba2bfcfb5199ed22409e4504 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 15 Jan 2026 21:24:45 -0600 Subject: [PATCH 049/269] feat(object): add HandleObjectOutOfRangePass2 --- src/object/client/Util.cpp | 14 ++++++++++++++ src/object/client/Util.hpp | 2 ++ 2 files changed, 16 insertions(+) diff --git a/src/object/client/Util.cpp b/src/object/client/Util.cpp index 02e4e40..619b298 100644 --- a/src/object/client/Util.cpp +++ b/src/object/client/Util.cpp @@ -73,6 +73,20 @@ int32_t HandleObjectOutOfRangePass1(CGObject_C* object, OUT_OF_RANGE_TYPE type) return true; } +void HandleObjectOutOfRangePass2(CGObject_C* object) { + // TODO ClearObjectMirrorHandlers(object); + + ClntObjMgrGetCurrent()->m_objects.Unlink(object); + + if (ClntObjMgrGetCurrent()->m_visibleObjects.IsLinked(object)) { + ClntObjMgrGetCurrent()->m_visibleObjects.UnlinkNode(object); + } + + ClntObjMgrGetCurrent()->m_lazyCleanupObjects.Insert(object, object->m_hashval, CHashKeyGUID(object->m_key)); + + // TODO link to type specific (disabled?) list in ClntObjMgrGetCurrent() +} + void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate) { switch (object->m_typeID) { case ID_ITEM: { diff --git a/src/object/client/Util.hpp b/src/object/client/Util.hpp index 0657692..e425f83 100644 --- a/src/object/client/Util.hpp +++ b/src/object/client/Util.hpp @@ -14,6 +14,8 @@ CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenable); int32_t HandleObjectOutOfRangePass1(CGObject_C* object, OUT_OF_RANGE_TYPE type); +void HandleObjectOutOfRangePass2(CGObject_C* object); + void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate); #endif From ccca191048dfb4df169dd0b422f7a63c43a8b5f0 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 15 Jan 2026 21:41:06 -0600 Subject: [PATCH 050/269] feat(object): implement OnObjectDestroy --- src/object/client/MessageHandlers.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index 9d38647..ec8b950 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -368,5 +368,21 @@ int32_t ObjectUpdateHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataS } int32_t OnObjectDestroy(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) { - WHOA_UNIMPLEMENTED(0); + WOWGUID guid; + msg->Get(guid); + + uint8_t dead; + msg->Get(dead); + + auto object = FindActiveObject(guid); + + if (object) { + // TODO handle unit death + + if (HandleObjectOutOfRangePass1(object, OUT_OF_RANGE_1)) { + HandleObjectOutOfRangePass2(object); + } + } + + return 1; } From de2bea7129a527f8ce4681cfdd11882d5fe56d31 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 15 Jan 2026 22:49:24 -0600 Subject: [PATCH 051/269] feat(object): implement UpdateOutOfRangeObjects --- src/object/client/MessageHandlers.cpp | 45 ++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index ec8b950..1d64e77 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -34,7 +34,50 @@ int32_t SkipPartialObjectUpdate(CDataStore* msg) { } void UpdateOutOfRangeObjects(CDataStore* msg) { - WHOA_UNIMPLEMENTED(); + uint32_t count; + msg->Get(count); + + // TODO CVehiclePassenger_C::StartAddingPendingRescueTransitions(); + + auto startPos = msg->Tell(); + + // Pass 1 + + for (int32_t i = 0; i < count; i++) { + SmartGUID guid; + *msg >> guid; + + if (guid == ClntObjMgrGetActivePlayer()) { + continue; + } + + auto object = FindActiveObject(guid); + + if (object) { + HandleObjectOutOfRangePass1(object, OUT_OF_RANGE_0); + } + } + + msg->Seek(startPos); + + // Pass 2 + + for (int32_t i = 0; i < count; i++) { + SmartGUID guid; + *msg >> guid; + + if (guid == ClntObjMgrGetActivePlayer()) { + continue; + } + + auto object = FindActiveObject(guid); + + if (object && !object->IsObjectLocked()) { + HandleObjectOutOfRangePass2(object); + } + } + + // TODO CVehiclePassenger_C::ExecutePendingRescueTransitions(); } int32_t UpdateObject(CDataStore* msg) { From 0b0b7927aad345f1147012fccc2929b1df610386 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 16 Jan 2026 08:41:50 -0600 Subject: [PATCH 052/269] feat(object): set disabled flag in CGObject_C::Disable --- src/object/client/CGObject_C.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 2417717..20b0b15 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -23,6 +23,9 @@ void CGObject_C::AddWorldObject() { } void CGObject_C::Disable() { + this->m_disabled = true; + // TODO other flag manipulation + // TODO } From 43dcfae6b0225d838cc3f45fcb8df68bffed168f Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 16 Jan 2026 16:56:27 -0600 Subject: [PATCH 053/269] feat(object): add type-specific cleanup queues to ClntObjMgr --- src/object/client/ClntObjMgr.hpp | 2 +- src/object/client/Util.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/object/client/ClntObjMgr.hpp b/src/object/client/ClntObjMgr.hpp index 7cd4fe3..30f8c97 100644 --- a/src/object/client/ClntObjMgr.hpp +++ b/src/object/client/ClntObjMgr.hpp @@ -13,7 +13,7 @@ class ClntObjMgr { // Member variables TSHashTable m_objects; TSHashTable m_lazyCleanupObjects; - // TODO + STORM_EXPLICIT_LIST(CGObject_C, m_link) m_lazyCleanupFifo[NUM_CLIENT_OBJECT_TYPES - 1]; STORM_EXPLICIT_LIST(CGObject_C, m_link) m_visibleObjects; STORM_EXPLICIT_LIST(CGObject_C, m_link) m_reenabledObjects; // TODO diff --git a/src/object/client/Util.cpp b/src/object/client/Util.cpp index 619b298..574960c 100644 --- a/src/object/client/Util.cpp +++ b/src/object/client/Util.cpp @@ -83,8 +83,7 @@ void HandleObjectOutOfRangePass2(CGObject_C* object) { } ClntObjMgrGetCurrent()->m_lazyCleanupObjects.Insert(object, object->m_hashval, CHashKeyGUID(object->m_key)); - - // TODO link to type specific (disabled?) list in ClntObjMgrGetCurrent() + ClntObjMgrGetCurrent()->m_lazyCleanupFifo[object->m_typeID - 1].LinkToTail(object); } void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate) { From c9aaa245c9e53b5fad8387a9cdec9a703ef066b2 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 16 Jan 2026 19:33:17 -0600 Subject: [PATCH 054/269] feat(event): dispatch tick events in main processing loop --- src/event/Scheduler.cpp | 6 ++---- src/event/Synthesize.cpp | 14 ++++++++++++++ src/event/Synthesize.hpp | 2 ++ src/event/Types.hpp | 7 ++++++- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/event/Scheduler.cpp b/src/event/Scheduler.cpp index 3f3f4f0..808b34c 100644 --- a/src/event/Scheduler.cpp +++ b/src/event/Scheduler.cpp @@ -286,12 +286,10 @@ int32_t SchedulerThreadProcProcess(uint32_t a1) { } } - uint32_t v9 = (currTime - context->m_schedLastIdle); + float elapsedSec = (currTime - context->m_schedLastIdle) * 0.001; context->m_schedLastIdle = currTime; - double elapsedSec = v9 * 0.001; - // TODO - // FrameTime::Update(currTime, elapsedSec); + SynthesizeTick(context, currTime, elapsedSec); IEvtTimerDispatch(context); diff --git a/src/event/Synthesize.cpp b/src/event/Synthesize.cpp index c42b51a..807291d 100644 --- a/src/event/Synthesize.cpp +++ b/src/event/Synthesize.cpp @@ -91,3 +91,17 @@ void SynthesizePoll(EvtContext* context) { IEvtQueueDispatch(context, EVENT_ID_POLL, nullptr); } + +void SynthesizeTick(EvtContext* context, uint32_t currTime, float elapsedSec) { + context->m_critsect.Enter(); + bool closed = context->m_schedState == EvtContext::SCHEDSTATE_CLOSED; + context->m_critsect.Leave(); + + if (closed) { + return; + } + + EVENT_DATA_TICK data = { elapsedSec, currTime }; + + IEvtQueueDispatch(context, EVENT_ID_TICK, &data); +} diff --git a/src/event/Synthesize.hpp b/src/event/Synthesize.hpp index 3b6f1ba..d4d9f4b 100644 --- a/src/event/Synthesize.hpp +++ b/src/event/Synthesize.hpp @@ -15,4 +15,6 @@ void SynthesizePaint(EvtContext* context); void SynthesizePoll(EvtContext* context); +void SynthesizeTick(EvtContext* context, uint32_t currTime, float elapsedSec); + #endif diff --git a/src/event/Types.hpp b/src/event/Types.hpp index a673839..ba13443 100644 --- a/src/event/Types.hpp +++ b/src/event/Types.hpp @@ -12,7 +12,7 @@ enum EVENTID { EVENT_ID_FOCUS = 2, EVENT_ID_CLOSE = 3, EVENT_ID_DESTROY = 4, - EVENT_ID_5 = 5, + EVENT_ID_TICK = 5, EVENT_ID_IDLE = 6, EVENT_ID_POLL = 7, EVENT_ID_INITIALIZE = 8, @@ -259,4 +259,9 @@ struct EVENT_DATA_SIZE { int32_t h; }; +struct EVENT_DATA_TICK { + float tickTimeSec; + uint32_t curTimeMs; +}; + #endif From c92f1b8de85a8ddb6e1a15d6daee3830d1e01cbf Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 17 Jan 2026 19:20:30 -0600 Subject: [PATCH 055/269] feat(world): add time handling functions to CWorld --- src/client/Client.cpp | 3 ++- src/world/CWorld.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++ src/world/CWorld.hpp | 29 +++++++++++++++++--- 3 files changed, 90 insertions(+), 4 deletions(-) diff --git a/src/client/Client.cpp b/src/client/Client.cpp index 6d1874c..4e2722f 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -520,8 +520,9 @@ void WowClientDestroy() { } void WowClientInit() { + EventRegister(EVENT_ID_TICK, reinterpret_cast(&CWorld::OnTick)); + // TODO - // EventRegister(EVENT_ID_5, (int)sub_4020E0); // _cfltcvt_init_0(); ClientRegisterConsoleCommands(); diff --git a/src/world/CWorld.cpp b/src/world/CWorld.cpp index 6863847..5f0fc45 100644 --- a/src/world/CWorld.cpp +++ b/src/world/CWorld.cpp @@ -6,10 +6,49 @@ #include "world/Weather.hpp" #include +uint32_t CWorld::s_curTimeMs; +float CWorld::s_curTimeSec; uint32_t CWorld::s_enables; uint32_t CWorld::s_enables2; +uint32_t CWorld::s_gameTimeFixed; +float CWorld::s_gameTimeSec; +uint32_t CWorld::s_tickTimeFixed; +uint32_t CWorld::s_tickTimeMs; +float CWorld::s_tickTimeSec; Weather* CWorld::s_weather; +uint32_t CWorld::GetCurTimeMs() { + return CWorld::s_curTimeMs; +} + +float CWorld::GetCurTimeSec() { + return CWorld::s_curTimeSec; +} + +uint32_t CWorld::GetFixedPrecisionTime(float timeSec) { + return static_cast(timeSec * 1024.0f); +} + +uint32_t CWorld::GetGameTimeFixed() { + return CWorld::s_gameTimeFixed; +} + +float CWorld::GetGameTimeSec() { + return CWorld::s_gameTimeSec; +} + +uint32_t CWorld::GetTickTimeFixed() { + return CWorld::s_tickTimeFixed; +} + +uint32_t CWorld::GetTickTimeMs() { + return CWorld::s_tickTimeMs; +} + +float CWorld::GetTickTimeSec() { + return CWorld::s_tickTimeSec; +} + void CWorld::Initialize() { CWorld::s_enables |= Enables::Enable_1 @@ -26,6 +65,9 @@ void CWorld::Initialize() { | Enables::Enable_Particulates | Enables::Enable_LowDetail; + CWorld::s_gameTimeFixed = 0; + CWorld::s_gameTimeSec = 0.0f; + // TODO if (GxCaps().m_shaderTargets[GxSh_Pixel] > GxShPS_none) { @@ -58,3 +100,23 @@ void CWorld::LoadMap(const char* mapName, const C3Vector& position, int32_t zone // TODO } + +int32_t CWorld::OnTick(const EVENT_DATA_TICK* data, void* param) { + CWorld::SetUpdateTime(data->tickTimeSec, data->curTimeMs); + + return 1; +} + +void CWorld::SetUpdateTime(float tickTimeSec, uint32_t curTimeMs) { + auto tickTimeFixed = CWorld::GetFixedPrecisionTime(tickTimeSec); + + CWorld::s_curTimeMs = curTimeMs; + CWorld::s_curTimeSec = static_cast(curTimeMs) * 0.001f; + + CWorld::s_gameTimeFixed += tickTimeFixed; + CWorld::s_gameTimeSec += tickTimeSec; + + CWorld::s_tickTimeFixed = tickTimeFixed; + CWorld::s_tickTimeMs = static_cast(tickTimeSec * 1000.0f); + CWorld::s_tickTimeSec = tickTimeSec; +} diff --git a/src/world/CWorld.hpp b/src/world/CWorld.hpp index a79831e..c3be35d 100644 --- a/src/world/CWorld.hpp +++ b/src/world/CWorld.hpp @@ -1,6 +1,7 @@ #ifndef WORLD_C_WORLD_HPP #define WORLD_C_WORLD_HPP +#include "event/Event.hpp" #include #include @@ -44,14 +45,36 @@ class CWorld { Enable_HwPcf = 0x2 }; - // Static variables + // Public static variables static uint32_t s_enables; static uint32_t s_enables2; static Weather* s_weather; - // Static functions - static void Initialize(void); + // Public static functions + static uint32_t GetCurTimeMs(); + static float GetCurTimeSec(); + static uint32_t GetGameTimeFixed(); + static float GetGameTimeSec(); + static uint32_t GetTickTimeFixed(); + static uint32_t GetTickTimeMs(); + static float GetTickTimeSec(); + static void Initialize(); static void LoadMap(const char* mapName, const C3Vector& position, int32_t zoneID); + static int32_t OnTick(const EVENT_DATA_TICK* data, void* param); + static void SetUpdateTime(float tickTimeSec, uint32_t curTimeMs); + + private: + // Private static variables + static uint32_t s_curTimeMs; + static float s_curTimeSec; + static uint32_t s_gameTimeFixed; + static float s_gameTimeSec; + static uint32_t s_tickTimeFixed; + static uint32_t s_tickTimeMs; + static float s_tickTimeSec; + + // Private static functions + static uint32_t GetFixedPrecisionTime(float timeSec); }; #endif From 2efef87898f71723e74184ff53bdb2d9a44b2f8f Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 17 Jan 2026 20:29:40 -0600 Subject: [PATCH 056/269] feat(object): set disable time in CGObject_C::Disable --- src/object/client/CGObject_C.cpp | 5 ++++- src/object/client/CGObject_C.hpp | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 20b0b15..39c9388 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -1,5 +1,6 @@ #include "object/client/CGObject_C.hpp" #include "object/client/ObjMgr.hpp" +#include "world/World.hpp" CGObject_C::CGObject_C(uint32_t time, CClientObjCreate& objCreate) { // TODO @@ -23,10 +24,12 @@ void CGObject_C::AddWorldObject() { } void CGObject_C::Disable() { + // TODO + this->m_disabled = true; // TODO other flag manipulation - // TODO + this->m_disableTimeMs = CWorld::GetCurTimeMs(); } int32_t CGObject_C::IsInReenable() { diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index 9caa2ba..61ddd4b 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -12,6 +12,7 @@ class CGObject_C : public CGObject, public TSHashObject m_link; + uint32_t m_disableTimeMs; // TODO uint32_t m_lockCount : 16; uint32_t m_disabled : 1; From 553a59c8083c1ecc1df4533ee0e8fe977bad9a7d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 17 Jan 2026 20:34:46 -0600 Subject: [PATCH 057/269] chore(object): tidy up return type for ClntObjMgrAllocObject --- src/object/client/MessageHandlers.cpp | 2 +- src/object/client/ObjMgr.cpp | 9 +++++---- src/object/client/ObjMgr.hpp | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index 1d64e77..cac7254 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -236,7 +236,7 @@ int32_t CreateObject(CDataStore* msg, uint32_t time) { ClntObjMgrSetActivePlayer(guid); } - auto newObject = static_cast(ClntObjMgrAllocObject(typeID, guid)); + auto newObject = ClntObjMgrAllocObject(typeID, guid); SetupObjectStorage(typeID, newObject, guid); diff --git a/src/object/client/ObjMgr.cpp b/src/object/client/ObjMgr.cpp index d65b186..a159c4f 100644 --- a/src/object/client/ObjMgr.cpp +++ b/src/object/client/ObjMgr.cpp @@ -67,12 +67,12 @@ void MirrorInitialize() { // TODO } -void* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, WOWGUID guid) { +CGObject_C* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, WOWGUID guid) { auto playerGUID = ClntObjMgrGetActivePlayer(); // Heap allocate player object for current player if (guid == playerGUID) { - return STORM_ALLOC(sizeof(CGPlayer_C) + CGPlayer::GetDataSize() + CGPlayer::GetDataSizeSaved()); + return static_cast(STORM_ALLOC(sizeof(CGPlayer_C) + CGPlayer::GetDataSize() + CGPlayer::GetDataSizeSaved())); } // TODO GarbageCollect(typeID, 10000); @@ -85,9 +85,10 @@ void* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, WOWGUID guid) { } // TODO pointer should be fetched via ObjectPtr - static_cast(mem)->m_memHandle = memHandle; + auto object = static_cast(mem); + object->m_memHandle = memHandle; - return mem; + return object; } WOWGUID ClntObjMgrGetActivePlayer() { diff --git a/src/object/client/ObjMgr.hpp b/src/object/client/ObjMgr.hpp index c5ea706..6d5fd09 100644 --- a/src/object/client/ObjMgr.hpp +++ b/src/object/client/ObjMgr.hpp @@ -6,7 +6,7 @@ #include "object/Types.hpp" #include -void* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, WOWGUID guid); +CGObject_C* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, WOWGUID guid); WOWGUID ClntObjMgrGetActivePlayer(); From 012e97f41056de79dfadbdae4a8d149dcf49d093 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 18 Jan 2026 19:50:07 -0600 Subject: [PATCH 058/269] feat(object): add GarbageCollect --- src/object/client/MessageHandlers.cpp | 10 +++++++++- src/object/client/ObjMgr.cpp | 6 +++++- src/object/client/ObjMgr.hpp | 2 ++ src/object/client/Util.cpp | 24 ++++++++++++++++++++++++ src/object/client/Util.hpp | 2 ++ 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index cac7254..ab77288 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -384,6 +384,8 @@ int32_t ObjectUpdateHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataS uint32_t updateCount; msg->Get(updateCount); + // If first update type is out of range, handle it before continuing with normal processing + auto startPos = msg->Tell(); uint8_t firstUpdateType; @@ -398,6 +400,8 @@ int32_t ObjectUpdateHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataS msg->Seek(startPos); } + // Process all updates in two passes (creates, updates and disables objects as appropriate) + int32_t result = 0; if (ObjectUpdateFirstPass(msg, time, updateIdx, updateCount)) { @@ -405,7 +409,11 @@ int32_t ObjectUpdateHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataS result = ObjectUpdateSecondPass(msg, time, updateCount); } - // TODO + // Garbage collect objects disabled more than 2 minutes ago (catch all) + + for (int32_t typeID = ID_OBJECT; typeID < NUM_CLIENT_OBJECT_TYPES; typeID++) { + GarbageCollect(static_cast(typeID), 120000); + } return result; } diff --git a/src/object/client/ObjMgr.cpp b/src/object/client/ObjMgr.cpp index a159c4f..b0b582a 100644 --- a/src/object/client/ObjMgr.cpp +++ b/src/object/client/ObjMgr.cpp @@ -75,7 +75,7 @@ CGObject_C* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, WOWGUID guid) { return static_cast(STORM_ALLOC(sizeof(CGPlayer_C) + CGPlayer::GetDataSize() + CGPlayer::GetDataSizeSaved())); } - // TODO GarbageCollect(typeID, 10000); + GarbageCollect(typeID, 10000); uint32_t memHandle; void* mem; @@ -91,6 +91,10 @@ CGObject_C* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, WOWGUID guid) { return object; } +void ClntObjMgrFreeObject(CGObject_C* object) { + // TODO +} + WOWGUID ClntObjMgrGetActivePlayer() { if (!s_curMgr) { return 0; diff --git a/src/object/client/ObjMgr.hpp b/src/object/client/ObjMgr.hpp index 6d5fd09..f467d9d 100644 --- a/src/object/client/ObjMgr.hpp +++ b/src/object/client/ObjMgr.hpp @@ -10,6 +10,8 @@ CGObject_C* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, WOWGUID guid); WOWGUID ClntObjMgrGetActivePlayer(); +void ClntObjMgrFreeObject(CGObject_C* object); + ClntObjMgr* ClntObjMgrGetCurrent(); uint32_t ClntObjMgrGetMapID(); diff --git a/src/object/client/Util.cpp b/src/object/client/Util.cpp index 574960c..6dd3e82 100644 --- a/src/object/client/Util.cpp +++ b/src/object/client/Util.cpp @@ -9,11 +9,35 @@ #include "object/client/CGPlayer_C.hpp" #include "object/client/CGUnit_C.hpp" #include "object/client/ObjMgr.hpp" +#include CGObject_C* FindActiveObject(WOWGUID guid) { return ClntObjMgrGetCurrent()->m_objects.Ptr(guid, CHashKeyGUID(guid)); } +/** + * Given an object type and collection age, free the object at the head of that type's FIFO queue + * if it was disabled longer ago than the collection age. Only frees at most one object per call. + */ +void GarbageCollect(OBJECT_TYPE_ID typeID, uint32_t collectAgeMs) { + auto object = ClntObjMgrGetCurrent()->m_lazyCleanupFifo[typeID - 1].Head(); + + if (!object) { + return; + } + + uint32_t disableAgeMs = OsGetAsyncTimeMsPrecise() - object->m_disableTimeMs; + + if (disableAgeMs < collectAgeMs) { + return; + } + + ClntObjMgrGetCurrent()->m_lazyCleanupObjects.Unlink(object); + object->m_link.Unlink(); + + ClntObjMgrFreeObject(object); +} + CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenable) { *reenable = false; diff --git a/src/object/client/Util.hpp b/src/object/client/Util.hpp index e425f83..b39c6db 100644 --- a/src/object/client/Util.hpp +++ b/src/object/client/Util.hpp @@ -10,6 +10,8 @@ class CGObject_C; CGObject_C* FindActiveObject(WOWGUID guid); +void GarbageCollect(OBJECT_TYPE_ID typeID, uint32_t collectAgeMs); + CGObject_C* GetUpdateObject(WOWGUID guid, int32_t* reenable); int32_t HandleObjectOutOfRangePass1(CGObject_C* object, OUT_OF_RANGE_TYPE type); From 305849b16481c4840f93824f7d61d614d3b6f278 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 18 Jan 2026 23:00:34 -0600 Subject: [PATCH 059/269] feat(object): add virtual dtors to base object classes --- src/object/client/CGContainer_C.cpp | 4 ++++ src/object/client/CGContainer_C.hpp | 3 +++ src/object/client/CGCorpse_C.cpp | 4 ++++ src/object/client/CGCorpse_C.hpp | 3 +++ src/object/client/CGDynamicObject_C.cpp | 4 ++++ src/object/client/CGDynamicObject_C.hpp | 3 +++ src/object/client/CGGameObject_C.cpp | 4 ++++ src/object/client/CGGameObject_C.hpp | 3 +++ src/object/client/CGItem_C.cpp | 4 ++++ src/object/client/CGItem_C.hpp | 3 +++ src/object/client/CGObject_C.cpp | 4 ++++ src/object/client/CGObject_C.hpp | 2 +- src/object/client/CGPlayer_C.cpp | 4 ++++ src/object/client/CGPlayer_C.hpp | 3 +++ src/object/client/CGUnit_C.cpp | 4 ++++ src/object/client/CGUnit_C.hpp | 3 +++ 16 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/object/client/CGContainer_C.cpp b/src/object/client/CGContainer_C.cpp index b6e5fcf..eb95404 100644 --- a/src/object/client/CGContainer_C.cpp +++ b/src/object/client/CGContainer_C.cpp @@ -4,6 +4,10 @@ CGContainer_C::CGContainer_C(uint32_t time, CClientObjCreate& objCreate) : CGIte // TODO } +CGContainer_C::~CGContainer_C() { + // TODO +} + void CGContainer_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGItem_C::SetStorage(storage, saved); diff --git a/src/object/client/CGContainer_C.hpp b/src/object/client/CGContainer_C.hpp index 7ca1cd1..ce6a665 100644 --- a/src/object/client/CGContainer_C.hpp +++ b/src/object/client/CGContainer_C.hpp @@ -7,6 +7,9 @@ class CGContainer_C : public CGItem_C, public CGContainer { public: + // Virtual public member functions + virtual ~CGContainer_C(); + // Public member functions CGContainer_C(uint32_t time, CClientObjCreate& objCreate); void SetStorage(uint32_t* storage, uint32_t* saved); diff --git a/src/object/client/CGCorpse_C.cpp b/src/object/client/CGCorpse_C.cpp index e62e4fb..37318bf 100644 --- a/src/object/client/CGCorpse_C.cpp +++ b/src/object/client/CGCorpse_C.cpp @@ -4,6 +4,10 @@ CGCorpse_C::CGCorpse_C(uint32_t time, CClientObjCreate& objCreate) : CGObject_C( // TODO } +CGCorpse_C::~CGCorpse_C() { + // TODO +} + void CGCorpse_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGCorpse_C.hpp b/src/object/client/CGCorpse_C.hpp index b5d0914..122a9d8 100644 --- a/src/object/client/CGCorpse_C.hpp +++ b/src/object/client/CGCorpse_C.hpp @@ -7,6 +7,9 @@ class CGCorpse_C : public CGObject_C, public CGCorpse { public: + // Virtual public member functions + virtual ~CGCorpse_C(); + // Public member functions CGCorpse_C(uint32_t time, CClientObjCreate& objCreate); void SetStorage(uint32_t* storage, uint32_t* saved); diff --git a/src/object/client/CGDynamicObject_C.cpp b/src/object/client/CGDynamicObject_C.cpp index b3787f3..96708ba 100644 --- a/src/object/client/CGDynamicObject_C.cpp +++ b/src/object/client/CGDynamicObject_C.cpp @@ -4,6 +4,10 @@ CGDynamicObject_C::CGDynamicObject_C(uint32_t time, CClientObjCreate& objCreate) // TODO } +CGDynamicObject_C::~CGDynamicObject_C() { + // TODO +} + void CGDynamicObject_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGDynamicObject_C.hpp b/src/object/client/CGDynamicObject_C.hpp index 6905e28..90fcd40 100644 --- a/src/object/client/CGDynamicObject_C.hpp +++ b/src/object/client/CGDynamicObject_C.hpp @@ -7,6 +7,9 @@ class CGDynamicObject_C : public CGObject_C, public CGDynamicObject { public: + // Virtual public member functions + virtual ~CGDynamicObject_C(); + // Public member functions CGDynamicObject_C(uint32_t time, CClientObjCreate& objCreate); void SetStorage(uint32_t* storage, uint32_t* saved); diff --git a/src/object/client/CGGameObject_C.cpp b/src/object/client/CGGameObject_C.cpp index c97445c..eef5f6e 100644 --- a/src/object/client/CGGameObject_C.cpp +++ b/src/object/client/CGGameObject_C.cpp @@ -4,6 +4,10 @@ CGGameObject_C::CGGameObject_C(uint32_t time, CClientObjCreate& objCreate) : CGO // TODO } +CGGameObject_C::~CGGameObject_C() { + // TODO +} + void CGGameObject_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGGameObject_C.hpp b/src/object/client/CGGameObject_C.hpp index 36b3dce..eec6134 100644 --- a/src/object/client/CGGameObject_C.hpp +++ b/src/object/client/CGGameObject_C.hpp @@ -7,6 +7,9 @@ class CGGameObject_C : public CGObject_C, public CGGameObject { public: + // Virtual public member functions + virtual ~CGGameObject_C(); + // Public member functions CGGameObject_C(uint32_t time, CClientObjCreate& objCreate); void SetStorage(uint32_t* storage, uint32_t* saved); diff --git a/src/object/client/CGItem_C.cpp b/src/object/client/CGItem_C.cpp index ba092ec..da6ac42 100644 --- a/src/object/client/CGItem_C.cpp +++ b/src/object/client/CGItem_C.cpp @@ -4,6 +4,10 @@ CGItem_C::CGItem_C(uint32_t time, CClientObjCreate& objCreate) : CGObject_C(time // TODO } +CGItem_C::~CGItem_C() { + // TODO +} + void CGItem_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGItem_C.hpp b/src/object/client/CGItem_C.hpp index 079d0bd..cb756ae 100644 --- a/src/object/client/CGItem_C.hpp +++ b/src/object/client/CGItem_C.hpp @@ -7,6 +7,9 @@ class CGItem_C : public CGObject_C, public CGItem { public: + // Virtual public member functions + virtual ~CGItem_C(); + // Public member functions CGItem_C(uint32_t time, CClientObjCreate& objCreate); void SetStorage(uint32_t* storage, uint32_t* saved); diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 39c9388..a32f9c5 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -19,6 +19,10 @@ CGObject_C::CGObject_C(uint32_t time, CClientObjCreate& objCreate) { // TODO } +CGObject_C::~CGObject_C() { + // TODO +} + void CGObject_C::AddWorldObject() { // TODO } diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index 61ddd4b..2819a1e 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -23,7 +23,7 @@ class CGObject_C : public CGObject, public TSHashObjectCGUnit_C::SetStorage(storage, saved); diff --git a/src/object/client/CGPlayer_C.hpp b/src/object/client/CGPlayer_C.hpp index d94b8e8..cd383ce 100644 --- a/src/object/client/CGPlayer_C.hpp +++ b/src/object/client/CGPlayer_C.hpp @@ -10,6 +10,9 @@ class CreatureModelDataRec; class CGPlayer_C : public CGUnit_C, public CGPlayer { public: + // Virtual public member functions + virtual ~CGPlayer_C(); + // Public member functions CGPlayer_C(uint32_t time, CClientObjCreate& objCreate); void SetStorage(uint32_t* storage, uint32_t* saved); diff --git a/src/object/client/CGUnit_C.cpp b/src/object/client/CGUnit_C.cpp index 5a6ead7..a8165bd 100644 --- a/src/object/client/CGUnit_C.cpp +++ b/src/object/client/CGUnit_C.cpp @@ -93,6 +93,10 @@ CGUnit_C::CGUnit_C(uint32_t time, CClientObjCreate& objCreate) : CGObject_C(time // TODO } +CGUnit_C::~CGUnit_C() { + // TODO +} + void CGUnit_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGUnit_C.hpp b/src/object/client/CGUnit_C.hpp index 5b651ff..632a8c6 100644 --- a/src/object/client/CGUnit_C.hpp +++ b/src/object/client/CGUnit_C.hpp @@ -15,6 +15,9 @@ class CGUnit_C : public CGObject_C, public CGUnit { static const char* GetDisplayClassNameFromRecord(const ChrClassesRec* classRec, UNIT_SEX sex, UNIT_SEX* displaySex); static const char* GetDisplayRaceNameFromRecord(const ChrRacesRec* raceRec, UNIT_SEX sex, UNIT_SEX* displaySex); + // Virtual public member functions + virtual ~CGUnit_C(); + // Public member functions CGUnit_C(uint32_t time, CClientObjCreate& objCreate); void SetStorage(uint32_t* storage, uint32_t* saved); From 5a8fb5e2d3535d983f105212c98cdd822b5690db Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 18 Jan 2026 23:00:59 -0600 Subject: [PATCH 060/269] feat(object): implement ClntObjMgrFreeObject --- src/object/client/ObjMgr.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/object/client/ObjMgr.cpp b/src/object/client/ObjMgr.cpp index b0b582a..bcdb488 100644 --- a/src/object/client/ObjMgr.cpp +++ b/src/object/client/ObjMgr.cpp @@ -92,7 +92,33 @@ CGObject_C* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, WOWGUID guid) { } void ClntObjMgrFreeObject(CGObject_C* object) { - // TODO + auto playerGUID = ClntObjMgrGetActivePlayer(); + auto isActivePlayer = object->m_obj->m_guid == playerGUID; + + switch (object->m_obj->m_type) { + case TYPE_OBJECT: + case HIER_TYPE_ITEM: + case HIER_TYPE_CONTAINER: + case HIER_TYPE_UNIT: + case HIER_TYPE_PLAYER: + case HIER_TYPE_GAMEOBJECT: + case HIER_TYPE_DYNAMICOBJECT: + case HIER_TYPE_CORPSE: { + object->~CGObject_C(); + + break; + } + + default: { + break; + } + } + + if (isActivePlayer) { + STORM_FREE(object); + } else { + ObjectFree(s_objHeapId[object->m_typeID], object->m_memHandle); + } } WOWGUID ClntObjMgrGetActivePlayer() { From 1de58d83e5e49bf06345399373c969f2a6c2f86f Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 19 Jan 2026 11:23:18 -0600 Subject: [PATCH 061/269] feat(object): finish reenabling objects in object update handler --- src/object/client/CGObject_C.cpp | 8 ++++++++ src/object/client/CGObject_C.hpp | 4 ++-- src/object/client/MessageHandlers.cpp | 10 +++++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index a32f9c5..0d70a8d 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -44,6 +44,14 @@ int32_t CGObject_C::IsObjectLocked() { return this->m_lockCount != 0; } +void CGObject_C::PostReenable() { + // TODO + + this->m_inReenable = false; + + // TODO +} + void CGObject_C::Reenable() { this->m_disabled = false; this->m_inReenable = true; diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index 2819a1e..aeb361b 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -25,7 +25,8 @@ class CGObject_C : public CGObject, public TSHashObjectm_reenabledObjects.Head()) { + ClntObjMgrGetCurrent()->m_visibleObjects.LinkToTail(reenabledObject); + reenabledObject->PostReenable(); + } + + return 1; } int32_t ObjectCompressedUpdateHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) { From 3d02539112d405a32e6e2836df1601aa2d88b6f1 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 19 Jan 2026 16:11:09 -0600 Subject: [PATCH 062/269] feat(object): add post update handling to ObjectUpdateSecondPass --- src/object/client/CGCorpse_C.cpp | 4 + src/object/client/CGCorpse_C.hpp | 1 + src/object/client/CGDynamicObject_C.cpp | 4 + src/object/client/CGDynamicObject_C.hpp | 1 + src/object/client/CGGameObject_C.cpp | 4 + src/object/client/CGGameObject_C.hpp | 1 + src/object/client/CGItem_C.cpp | 4 + src/object/client/CGItem_C.hpp | 1 + src/object/client/CGObject_C.cpp | 4 + src/object/client/CGObject_C.hpp | 1 + src/object/client/CGPlayer_C.cpp | 4 + src/object/client/CGPlayer_C.hpp | 1 + src/object/client/CGUnit_C.cpp | 10 ++ src/object/client/CGUnit_C.hpp | 6 + src/object/client/MessageHandlers.cpp | 163 +++++++++++++++++++++++- src/object/client/Mirror.cpp | 44 +++++++ src/object/client/Mirror.hpp | 2 + src/object/client/Util.cpp | 5 + src/object/client/Util.hpp | 2 + 19 files changed, 258 insertions(+), 4 deletions(-) diff --git a/src/object/client/CGCorpse_C.cpp b/src/object/client/CGCorpse_C.cpp index 37318bf..72b6c29 100644 --- a/src/object/client/CGCorpse_C.cpp +++ b/src/object/client/CGCorpse_C.cpp @@ -8,6 +8,10 @@ CGCorpse_C::~CGCorpse_C() { // TODO } +void CGCorpse_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { + // TODO +} + void CGCorpse_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGCorpse_C.hpp b/src/object/client/CGCorpse_C.hpp index 122a9d8..ef323f4 100644 --- a/src/object/client/CGCorpse_C.hpp +++ b/src/object/client/CGCorpse_C.hpp @@ -12,6 +12,7 @@ class CGCorpse_C : public CGObject_C, public CGCorpse { // Public member functions CGCorpse_C(uint32_t time, CClientObjCreate& objCreate); + void PostInit(uint32_t time, const CClientObjCreate& init, bool a4); void SetStorage(uint32_t* storage, uint32_t* saved); }; diff --git a/src/object/client/CGDynamicObject_C.cpp b/src/object/client/CGDynamicObject_C.cpp index 96708ba..9acc13d 100644 --- a/src/object/client/CGDynamicObject_C.cpp +++ b/src/object/client/CGDynamicObject_C.cpp @@ -8,6 +8,10 @@ CGDynamicObject_C::~CGDynamicObject_C() { // TODO } +void CGDynamicObject_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { + // TODO +} + void CGDynamicObject_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGDynamicObject_C.hpp b/src/object/client/CGDynamicObject_C.hpp index 90fcd40..22a66bc 100644 --- a/src/object/client/CGDynamicObject_C.hpp +++ b/src/object/client/CGDynamicObject_C.hpp @@ -12,6 +12,7 @@ class CGDynamicObject_C : public CGObject_C, public CGDynamicObject { // Public member functions CGDynamicObject_C(uint32_t time, CClientObjCreate& objCreate); + void PostInit(uint32_t time, const CClientObjCreate& init, bool a4); void SetStorage(uint32_t* storage, uint32_t* saved); }; diff --git a/src/object/client/CGGameObject_C.cpp b/src/object/client/CGGameObject_C.cpp index eef5f6e..399b477 100644 --- a/src/object/client/CGGameObject_C.cpp +++ b/src/object/client/CGGameObject_C.cpp @@ -8,6 +8,10 @@ CGGameObject_C::~CGGameObject_C() { // TODO } +void CGGameObject_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { + // TODO +} + void CGGameObject_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGGameObject_C.hpp b/src/object/client/CGGameObject_C.hpp index eec6134..808222b 100644 --- a/src/object/client/CGGameObject_C.hpp +++ b/src/object/client/CGGameObject_C.hpp @@ -12,6 +12,7 @@ class CGGameObject_C : public CGObject_C, public CGGameObject { // Public member functions CGGameObject_C(uint32_t time, CClientObjCreate& objCreate); + void PostInit(uint32_t time, const CClientObjCreate& init, bool a4); void SetStorage(uint32_t* storage, uint32_t* saved); }; diff --git a/src/object/client/CGItem_C.cpp b/src/object/client/CGItem_C.cpp index da6ac42..e9e4455 100644 --- a/src/object/client/CGItem_C.cpp +++ b/src/object/client/CGItem_C.cpp @@ -8,6 +8,10 @@ CGItem_C::~CGItem_C() { // TODO } +void CGItem_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { + // TODO +} + void CGItem_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGItem_C.hpp b/src/object/client/CGItem_C.hpp index cb756ae..3d1c65b 100644 --- a/src/object/client/CGItem_C.hpp +++ b/src/object/client/CGItem_C.hpp @@ -12,6 +12,7 @@ class CGItem_C : public CGObject_C, public CGItem { // Public member functions CGItem_C(uint32_t time, CClientObjCreate& objCreate); + void PostInit(uint32_t time, const CClientObjCreate& init, bool a4); void SetStorage(uint32_t* storage, uint32_t* saved); }; diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 0d70a8d..7b68b57 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -59,6 +59,10 @@ void CGObject_C::Reenable() { // TODO } +void CGObject_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { + // TODO +} + void CGObject_C::SetBlock(uint32_t block, uint32_t value) { auto storage = reinterpret_cast(this->m_obj); storage[block] = value; diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index aeb361b..d6b9436 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -36,6 +36,7 @@ class CGObject_C : public CGObject, public TSHashObjectCGUnit_C::SetStorage(storage, saved); diff --git a/src/object/client/CGPlayer_C.hpp b/src/object/client/CGPlayer_C.hpp index cd383ce..e224be4 100644 --- a/src/object/client/CGPlayer_C.hpp +++ b/src/object/client/CGPlayer_C.hpp @@ -15,6 +15,7 @@ class CGPlayer_C : public CGUnit_C, public CGPlayer { // Public member functions CGPlayer_C(uint32_t time, CClientObjCreate& objCreate); + void PostInit(uint32_t time, const CClientObjCreate& init, bool a4); void SetStorage(uint32_t* storage, uint32_t* saved); }; diff --git a/src/object/client/CGUnit_C.cpp b/src/object/client/CGUnit_C.cpp index a8165bd..2ac5147 100644 --- a/src/object/client/CGUnit_C.cpp +++ b/src/object/client/CGUnit_C.cpp @@ -1,6 +1,8 @@ #include "object/client/CGUnit_C.hpp" #include "db/Db.hpp" +WOWGUID CGUnit_C::s_activeMover; + const char* CGUnit_C::GetDisplayClassNameFromRecord(const ChrClassesRec* classRec, UNIT_SEX sex, UNIT_SEX* displaySex) { if (displaySex) { *displaySex = sex; @@ -97,6 +99,14 @@ CGUnit_C::~CGUnit_C() { // TODO } +void CGUnit_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { + // TODO +} + +void CGUnit_C::PostMovementUpdate(const CClientMoveUpdate& move, int32_t activeMover) { + // TODO +} + void CGUnit_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGUnit_C.hpp b/src/object/client/CGUnit_C.hpp index 632a8c6..f42fec0 100644 --- a/src/object/client/CGUnit_C.hpp +++ b/src/object/client/CGUnit_C.hpp @@ -5,12 +5,16 @@ #include "object/client/CGObject_C.hpp" #include "object/client/CGUnit.hpp" #include "object/Types.hpp" +#include "util/GUID.hpp" class ChrClassesRec; class ChrRacesRec; class CGUnit_C : public CGObject_C, public CGUnit { public: + // Public static variables + static WOWGUID s_activeMover; + // Public static functions static const char* GetDisplayClassNameFromRecord(const ChrClassesRec* classRec, UNIT_SEX sex, UNIT_SEX* displaySex); static const char* GetDisplayRaceNameFromRecord(const ChrRacesRec* raceRec, UNIT_SEX sex, UNIT_SEX* displaySex); @@ -20,6 +24,8 @@ class CGUnit_C : public CGObject_C, public CGUnit { // Public member functions CGUnit_C(uint32_t time, CClientObjCreate& objCreate); + void PostInit(uint32_t time, const CClientObjCreate& init, bool a4); + void PostMovementUpdate(const CClientMoveUpdate& move, int32_t activeMover); void SetStorage(uint32_t* storage, uint32_t* saved); }; diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index c5ee5da..9aa05d5 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -28,9 +28,123 @@ enum UPDATE_TYPE { UPDATE_IN_RANGE = 5, }; -int32_t SkipPartialObjectUpdate(CDataStore* msg) { - // TODO - return 0; +void SkipSetOfObjects(CDataStore* msg) { + uint32_t count; + msg->Get(count); + + for (int32_t i = 0; i < count; i++) { + SmartGUID guid; + *msg >> guid; + } +} + +int32_t PostInitObject(CDataStore* msg, uint32_t time, bool a3) { + SmartGUID guid; + *msg >> guid; + + uint8_t _typeID; + msg->Get(_typeID); + auto typeID = static_cast(_typeID); + + if (guid == 0) { + return 0; + } + + auto object = FindActiveObject(guid); + + if (!object) { + return 0; + } + + CClientObjCreate init; + if (!init.Get(msg)) { + return 0; + } + + if (object->m_inReenable && object->m_obj->m_type & TYPE_UNIT) { + // TODO + } + + if (object->m_postInited) { + // TODO + return 1; + } + + switch (typeID) { + case ID_OBJECT: { + object->PostInit(time, init, a3); + + break; + } + + case ID_ITEM: + case ID_CONTAINER: { + static_cast(object)->PostInit(time, init, a3); + + break; + } + + case ID_UNIT: { + static_cast(object)->PostInit(time, init, a3); + + break; + } + + case ID_PLAYER: { + static_cast(object)->PostInit(time, init, a3); + + break; + } + + case ID_GAMEOBJECT: { + static_cast(object)->PostInit(time, init, a3); + + break; + } + + case ID_DYNAMICOBJECT: { + static_cast(object)->PostInit(time, init, a3); + + break; + } + + case ID_CORPSE: { + static_cast(object)->PostInit(time, init, a3); + + break; + } + + default: { + STORM_APP_FATAL("PostInitObject: unknown object type %d", typeID); + } + } + + return SkipPartialObjectUpdate(msg); +} + +void PostMovementUpdate(CDataStore* msg) { + SmartGUID guid; + *msg >> guid; + + CClientMoveUpdate move; + *msg >> move; + + if (guid == CGUnit_C::s_activeMover) { + return; + } + + int32_t reenable; + auto unit = static_cast(GetUpdateObject(guid, &reenable)); + + if (!unit) { + return; + } + + unit->PostMovementUpdate(move, unit->m_obj->m_guid == CGUnit_C::s_activeMover); + + if (reenable) { + unit->Reenable(); + } } void UpdateOutOfRangeObjects(CDataStore* msg) { @@ -322,7 +436,48 @@ int32_t ObjectUpdateFirstPass(CDataStore* msg, uint32_t time, uint32_t updateIdx } int32_t ObjectUpdateSecondPass(CDataStore* msg, uint32_t time, uint32_t updateCount) { - // TODO + // Handle post updates + + for (int32_t i = 0; i < updateCount; i++) { + uint8_t updateType; + msg->Get(updateType); + + switch (updateType) { + case UPDATE_PARTIAL: { + if (!CallMirrorHandlers(msg, false, 0)) { + return 0; + } + + break; + } + + case UPDATE_MOVEMENT: { + PostMovementUpdate(msg); + + break; + } + + case UPDATE_FULL: + case UPDATE_3: { + if (!PostInitObject(msg, time, updateType == UPDATE_3)) { + return 0; + } + + break; + } + + case UPDATE_IN_RANGE: + case UPDATE_OUT_OF_RANGE: { + SkipSetOfObjects(msg); + + break; + } + + default: { + break; + } + } + } // Finish reenabling objects diff --git a/src/object/client/Mirror.cpp b/src/object/client/Mirror.cpp index c4f25da..762cefa 100644 --- a/src/object/client/Mirror.cpp +++ b/src/object/client/Mirror.cpp @@ -8,6 +8,7 @@ #include "object/client/CGPlayer.hpp" #include "object/client/CGUnit.hpp" #include "object/client/ObjMgr.hpp" +#include "object/client/Util.hpp" #include "object/Types.hpp" #include @@ -150,6 +151,49 @@ int32_t IsMaskBitSet(uint32_t* masks, uint32_t block) { return masks[block / 32] & (1 << (block % 32)); } +int32_t CallMirrorHandlers(CDataStore* msg, bool a2, WOWGUID guid) { + if (!a2) { + SmartGUID _guid; + *msg >> _guid; + + guid = _guid; + } + + auto object = FindActiveObject(guid); + + if (!object) { + return SkipPartialObjectUpdate(msg); + } + + uint8_t changeMaskCount; + uint32_t changeMasks[MAX_CHANGE_MASKS]; + if (!ExtractDirtyMasks(msg, &changeMaskCount, changeMasks)) { + return 0; + } + + OBJECT_TYPE_ID typeID = ID_OBJECT; + uint32_t blockOffset = 0; + uint32_t numBlocks = GetNumDwordBlocks(object->m_obj->m_type, guid); + + for (int32_t block = 0; block < numBlocks; block++) { + if (block >= s_objMirrorBlocks[typeID]) { + blockOffset = s_objMirrorBlocks[typeID]; + typeID = IncTypeID(object, typeID); + } + + // TODO + + if (IsMaskBitSet(changeMasks, block)) { + uint32_t blockValue = 0; + msg->Get(blockValue); + } + + // TODO + } + + return 1; +} + int32_t FillInPartialObjectData(CGObject_C* object, WOWGUID guid, CDataStore* msg, bool forFullUpdate, bool zeroZeroBits) { uint8_t changeMaskCount; uint32_t changeMasks[MAX_CHANGE_MASKS]; diff --git a/src/object/client/Mirror.hpp b/src/object/client/Mirror.hpp index 899db97..c094dae 100644 --- a/src/object/client/Mirror.hpp +++ b/src/object/client/Mirror.hpp @@ -7,6 +7,8 @@ class CDataStore; class CGObject_C; +int32_t CallMirrorHandlers(CDataStore* msg, bool a2, WOWGUID guid); + int32_t FillInPartialObjectData(CGObject_C* object, WOWGUID guid, CDataStore* msg, bool forFullUpdate, bool zeroZeroBits); #endif diff --git a/src/object/client/Util.cpp b/src/object/client/Util.cpp index 6dd3e82..5ac8c52 100644 --- a/src/object/client/Util.cpp +++ b/src/object/client/Util.cpp @@ -164,3 +164,8 @@ void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate) } } } + +int32_t SkipPartialObjectUpdate(CDataStore* msg) { + // TODO + return 0; +} diff --git a/src/object/client/Util.hpp b/src/object/client/Util.hpp index b39c6db..9a833ec 100644 --- a/src/object/client/Util.hpp +++ b/src/object/client/Util.hpp @@ -20,4 +20,6 @@ void HandleObjectOutOfRangePass2(CGObject_C* object); void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate); +int32_t SkipPartialObjectUpdate(CDataStore* msg); + #endif From 8cf0abb1b1e48cb63ea053a8ceb4db9c3086e372 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 19 Jan 2026 20:04:17 -0600 Subject: [PATCH 063/269] feat(object): manage post init flag across base object classes --- src/object/client/CGCorpse_C.cpp | 4 ++++ src/object/client/CGDynamicObject_C.cpp | 4 ++++ src/object/client/CGGameObject_C.cpp | 4 ++++ src/object/client/CGItem_C.cpp | 2 ++ src/object/client/CGObject_C.cpp | 2 ++ src/object/client/CGPlayer_C.cpp | 4 ++++ src/object/client/CGUnit_C.cpp | 4 ++++ src/object/client/MessageHandlers.cpp | 3 +-- 8 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/object/client/CGCorpse_C.cpp b/src/object/client/CGCorpse_C.cpp index 72b6c29..fe52b34 100644 --- a/src/object/client/CGCorpse_C.cpp +++ b/src/object/client/CGCorpse_C.cpp @@ -10,6 +10,10 @@ CGCorpse_C::~CGCorpse_C() { void CGCorpse_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { // TODO + + this->CGObject_C::PostInit(time, init, a4); + + // TODO } void CGCorpse_C::SetStorage(uint32_t* storage, uint32_t* saved) { diff --git a/src/object/client/CGDynamicObject_C.cpp b/src/object/client/CGDynamicObject_C.cpp index 9acc13d..bfe149a 100644 --- a/src/object/client/CGDynamicObject_C.cpp +++ b/src/object/client/CGDynamicObject_C.cpp @@ -10,6 +10,10 @@ CGDynamicObject_C::~CGDynamicObject_C() { void CGDynamicObject_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { // TODO + + this->CGObject_C::PostInit(time, init, a4); + + // TODO } void CGDynamicObject_C::SetStorage(uint32_t* storage, uint32_t* saved) { diff --git a/src/object/client/CGGameObject_C.cpp b/src/object/client/CGGameObject_C.cpp index 399b477..a782615 100644 --- a/src/object/client/CGGameObject_C.cpp +++ b/src/object/client/CGGameObject_C.cpp @@ -10,6 +10,10 @@ CGGameObject_C::~CGGameObject_C() { void CGGameObject_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { // TODO + + this->CGObject_C::PostInit(time, init, a4); + + // TODO } void CGGameObject_C::SetStorage(uint32_t* storage, uint32_t* saved) { diff --git a/src/object/client/CGItem_C.cpp b/src/object/client/CGItem_C.cpp index e9e4455..2862c00 100644 --- a/src/object/client/CGItem_C.cpp +++ b/src/object/client/CGItem_C.cpp @@ -9,6 +9,8 @@ CGItem_C::~CGItem_C() { } void CGItem_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { + this->CGObject_C::PostInit(time, init, a4); + // TODO } diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 7b68b57..f78ad1a 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -60,6 +60,8 @@ void CGObject_C::Reenable() { } void CGObject_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { + this->m_postInited = true; + // TODO } diff --git a/src/object/client/CGPlayer_C.cpp b/src/object/client/CGPlayer_C.cpp index fae956c..e34f048 100644 --- a/src/object/client/CGPlayer_C.cpp +++ b/src/object/client/CGPlayer_C.cpp @@ -13,6 +13,10 @@ CGPlayer_C::~CGPlayer_C() { void CGPlayer_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { // TODO + + this->CGUnit_C::PostInit(time, init, a4); + + // TODO } void CGPlayer_C::SetStorage(uint32_t* storage, uint32_t* saved) { diff --git a/src/object/client/CGUnit_C.cpp b/src/object/client/CGUnit_C.cpp index 2ac5147..d182d2d 100644 --- a/src/object/client/CGUnit_C.cpp +++ b/src/object/client/CGUnit_C.cpp @@ -101,6 +101,10 @@ CGUnit_C::~CGUnit_C() { void CGUnit_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { // TODO + + this->CGObject_C::PostInit(time, init, a4); + + // TODO } void CGUnit_C::PostMovementUpdate(const CClientMoveUpdate& move, int32_t activeMover) { diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index 9aa05d5..72124ae 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -66,8 +66,7 @@ int32_t PostInitObject(CDataStore* msg, uint32_t time, bool a3) { } if (object->m_postInited) { - // TODO - return 1; + return CallMirrorHandlers(msg, true, guid); } switch (typeID) { From 88ea9325bec8779120a8be27b6402842819a66ea Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 20 Jan 2026 20:56:04 -0600 Subject: [PATCH 064/269] feat(world): stub core map entity classes --- src/world/map/CMapBaseObj.hpp | 9 +++++++++ src/world/map/CMapEntity.hpp | 11 +++++++++++ src/world/map/CMapStaticEntity.hpp | 11 +++++++++++ 3 files changed, 31 insertions(+) create mode 100644 src/world/map/CMapBaseObj.hpp create mode 100644 src/world/map/CMapEntity.hpp create mode 100644 src/world/map/CMapStaticEntity.hpp diff --git a/src/world/map/CMapBaseObj.hpp b/src/world/map/CMapBaseObj.hpp new file mode 100644 index 0000000..c3f43e3 --- /dev/null +++ b/src/world/map/CMapBaseObj.hpp @@ -0,0 +1,9 @@ +#ifndef WORLD_MAP_C_MAP_BASE_OBJ_HPP +#define WORLD_MAP_C_MAP_BASE_OBJ_HPP + +class CMapBaseObj { + public: + // TODO +}; + +#endif diff --git a/src/world/map/CMapEntity.hpp b/src/world/map/CMapEntity.hpp new file mode 100644 index 0000000..156c4fd --- /dev/null +++ b/src/world/map/CMapEntity.hpp @@ -0,0 +1,11 @@ +#ifndef WORLD_MAP_C_MAP_ENTITY_HPP +#define WORLD_MAP_C_MAP_ENTITY_HPP + +#include "world/map/CMapStaticEntity.hpp" + +class CMapEntity : public CMapStaticEntity { + public: + // TODO +}; + +#endif diff --git a/src/world/map/CMapStaticEntity.hpp b/src/world/map/CMapStaticEntity.hpp new file mode 100644 index 0000000..917ea7f --- /dev/null +++ b/src/world/map/CMapStaticEntity.hpp @@ -0,0 +1,11 @@ +#ifndef WORLD_MAP_C_MAP_STATIC_ENTITY_HPP +#define WORLD_MAP_C_MAP_STATIC_ENTITY_HPP + +#include "world/map/CMapBaseObj.hpp" + +class CMapStaticEntity : public CMapBaseObj { + public: + // TODO +}; + +#endif From 536c94a7b71c6e98324a9641a68a148993d0d2ac Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 20 Jan 2026 20:56:21 -0600 Subject: [PATCH 065/269] feat(world): add HWORLDOBJECT --- src/world/Types.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/world/Types.hpp diff --git a/src/world/Types.hpp b/src/world/Types.hpp new file mode 100644 index 0000000..529e5fb --- /dev/null +++ b/src/world/Types.hpp @@ -0,0 +1,8 @@ +#ifndef WORLD_TYPES_HPP +#define WORLD_TYPES_HPP + +#include + +typedef uintptr_t HWORLDOBJECT; + +#endif From aa62781560a0bbeeacb94c54abd10e95c931b127 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 21 Jan 2026 16:06:21 -0600 Subject: [PATCH 066/269] feat(world): populate CMapBaseObj --- src/world/map/CMap.cpp | 1 + src/world/map/CMap.hpp | 3 +++ src/world/map/CMapBaseObj.cpp | 5 ++++ src/world/map/CMapBaseObj.hpp | 45 +++++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+) create mode 100644 src/world/map/CMapBaseObj.cpp diff --git a/src/world/map/CMap.cpp b/src/world/map/CMap.cpp index 32b9dd4..32c0234 100644 --- a/src/world/map/CMap.cpp +++ b/src/world/map/CMap.cpp @@ -1,6 +1,7 @@ #include "world/map/CMap.hpp" #include +STORM_EXPLICIT_LIST(CMapBaseObj, m_lameAssLink) CMap::s_entityList; char CMap::s_mapName[256]; char CMap::s_mapPath[256]; char CMap::s_wdtFilename[256]; diff --git a/src/world/map/CMap.hpp b/src/world/map/CMap.hpp index a1a14a0..3407f37 100644 --- a/src/world/map/CMap.hpp +++ b/src/world/map/CMap.hpp @@ -1,11 +1,14 @@ #ifndef WORLD_MAP_C_MAP_HPP #define WORLD_MAP_C_MAP_HPP +#include "world/map/CMapBaseObj.hpp" +#include #include class CMap { public: // Static variables + static STORM_EXPLICIT_LIST(CMapBaseObj, m_lameAssLink) s_entityList; static char s_mapName[]; static char s_mapPath[]; static char s_wdtFilename[]; diff --git a/src/world/map/CMapBaseObj.cpp b/src/world/map/CMapBaseObj.cpp new file mode 100644 index 0000000..620f598 --- /dev/null +++ b/src/world/map/CMapBaseObj.cpp @@ -0,0 +1,5 @@ +#include "world/map/CMapBaseObj.hpp" + +uint32_t CMapBaseObj::GetType() { + return this->m_type; +} diff --git a/src/world/map/CMapBaseObj.hpp b/src/world/map/CMapBaseObj.hpp index c3f43e3..d9693c8 100644 --- a/src/world/map/CMapBaseObj.hpp +++ b/src/world/map/CMapBaseObj.hpp @@ -1,9 +1,54 @@ #ifndef WORLD_MAP_C_MAP_BASE_OBJ_HPP #define WORLD_MAP_C_MAP_BASE_OBJ_HPP +#include +#include + +class CM2Lighting; +class CMapBaseObj; + +class CMapBaseObjLink { + public: + // Member variables + uint32_t memHandle; + CMapBaseObj* owner; + CMapBaseObj* ref; + TSLink refLink; + TSLink ownerLink; +}; + class CMapBaseObj { public: + // Enums + enum { + Type_BaseObj = 0x1, + Type_Area = 0x2, + Type_Chunk = 0x4, + Type_MapObjDef = 0x8, + Type_MapObjDefGroup = 0x10, + Type_Entity = 0x20, + Type_DoodadDef = 0x40, + Type_Light = 0x80, + }; + + // Public member variables + uint32_t m_memHandle; + TSLink m_lameAssLink; + STORM_EXPLICIT_LIST(CMapBaseObjLink, ownerLink) m_parentLinkList; + // TODO + + // Public virtual member functions + virtual ~CMapBaseObj() = default; + virtual void SelectLights(CM2Lighting* lighting) {}; + virtual void SelectUnderwater(CM2Lighting* lighting) {}; + + // Public member functions + uint32_t GetType(); + + protected: + // Protected member variables + uint16_t m_type = Type_BaseObj; }; #endif From ba6f00d96c61ea9c2d61dae8a9d0f450be1e8fc6 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 22 Jan 2026 15:46:17 -0600 Subject: [PATCH 067/269] feat(world): initialize map allocation heaps --- src/world/CWorld.cpp | 4 +++ src/world/map/CChunkLiquid.hpp | 9 ++++++ src/world/map/CMap.cpp | 51 +++++++++++++++++++++++++++++++ src/world/map/CMap.hpp | 15 +++++++++ src/world/map/CMapArea.hpp | 11 +++++++ src/world/map/CMapAreaLow.hpp | 9 ++++++ src/world/map/CMapCacheLight.hpp | 9 ++++++ src/world/map/CMapChunk.hpp | 11 +++++++ src/world/map/CMapDoodadDef.hpp | 11 +++++++ src/world/map/CMapLight.hpp | 11 +++++++ src/world/map/CMapObj.hpp | 9 ++++++ src/world/map/CMapObjDef.hpp | 11 +++++++ src/world/map/CMapObjDefGroup.hpp | 9 ++++++ src/world/map/CMapObjGroup.hpp | 9 ++++++ 14 files changed, 179 insertions(+) create mode 100644 src/world/map/CChunkLiquid.hpp create mode 100644 src/world/map/CMapArea.hpp create mode 100644 src/world/map/CMapAreaLow.hpp create mode 100644 src/world/map/CMapCacheLight.hpp create mode 100644 src/world/map/CMapChunk.hpp create mode 100644 src/world/map/CMapDoodadDef.hpp create mode 100644 src/world/map/CMapLight.hpp create mode 100644 src/world/map/CMapObj.hpp create mode 100644 src/world/map/CMapObjDef.hpp create mode 100644 src/world/map/CMapObjDefGroup.hpp create mode 100644 src/world/map/CMapObjGroup.hpp diff --git a/src/world/CWorld.cpp b/src/world/CWorld.cpp index 5f0fc45..fbe55a3 100644 --- a/src/world/CWorld.cpp +++ b/src/world/CWorld.cpp @@ -88,6 +88,10 @@ void CWorld::Initialize() { // TODO + CMap::Initialize(); + + // TODO + CWorld::s_weather = STORM_NEW(Weather); // TODO diff --git a/src/world/map/CChunkLiquid.hpp b/src/world/map/CChunkLiquid.hpp new file mode 100644 index 0000000..099266d --- /dev/null +++ b/src/world/map/CChunkLiquid.hpp @@ -0,0 +1,9 @@ +#ifndef WORLD_MAP_C_CHUNK_LIQUID_HPP +#define WORLD_MAP_C_CHUNK_LIQUID_HPP + +class CChunkLiquid { + public: + // TODO +}; + +#endif diff --git a/src/world/map/CMap.cpp b/src/world/map/CMap.cpp index 32c0234..3eb3e71 100644 --- a/src/world/map/CMap.cpp +++ b/src/world/map/CMap.cpp @@ -1,11 +1,45 @@ #include "world/map/CMap.hpp" +#include "world/map/CChunkLiquid.hpp" +#include "world/map/CMapArea.hpp" +#include "world/map/CMapAreaLow.hpp" +#include "world/map/CMapCacheLight.hpp" +#include "world/map/CMapChunk.hpp" +#include "world/map/CMapDoodadDef.hpp" +#include "world/map/CMapEntity.hpp" +#include "world/map/CMapLight.hpp" +#include "world/map/CMapObj.hpp" +#include "world/map/CMapObjDef.hpp" +#include "world/map/CMapObjDefGroup.hpp" +#include "world/map/CMapObjGroup.hpp" +#include #include +uint32_t* CMap::s_areaHeap; +uint32_t* CMap::s_areaLowHeap; +uint32_t* CMap::s_baseObjLinkHeap; +uint32_t* CMap::s_cacheLightHeap; +uint32_t* CMap::s_chunkHeap; +uint32_t* CMap::s_chunkLiquidHeap; +uint32_t* CMap::s_doodadDefHeap; +uint32_t* CMap::s_entityHeap; STORM_EXPLICIT_LIST(CMapBaseObj, m_lameAssLink) CMap::s_entityList; +uint32_t* CMap::s_lightHeap; +uint32_t* CMap::s_mapObjDefGroupHeap; +uint32_t* CMap::s_mapObjDefHeap; +uint32_t* CMap::s_mapObjGroupHeap; +uint32_t* CMap::s_mapObjHeap; char CMap::s_mapName[256]; char CMap::s_mapPath[256]; char CMap::s_wdtFilename[256]; +void CMap::Initialize() { + // TODO + + CMap::MapMemInitialize(); + + // TODO +} + void CMap::Load(const char* mapName, int32_t zoneID) { // TODO @@ -18,3 +52,20 @@ void CMap::Load(const char* mapName, int32_t zoneID) { // TODO } + +void CMap::MapMemInitialize() { + CMap::s_lightHeap = STORM_NEW(uint32_t)(ObjectAllocAddHeap(sizeof(CMapLight), 128, "WLIGHT", true)); + CMap::s_cacheLightHeap = STORM_NEW(uint32_t)(ObjectAllocAddHeap(sizeof(CMapCacheLight), 256, "WCACHELIGHT", true)); + CMap::s_mapObjGroupHeap = STORM_NEW(uint32_t)(ObjectAllocAddHeap(sizeof(CMapObjGroup), 128, "WMAPOBJGROUP", true)); + CMap::s_mapObjHeap = STORM_NEW(uint32_t)(ObjectAllocAddHeap(sizeof(CMapObj), 32, "WMAPOBJ", true)); + CMap::s_baseObjLinkHeap = STORM_NEW(uint32_t)(ObjectAllocAddHeap(sizeof(CMapBaseObjLink), 10000, "WBASEOBJLINK", true)); + CMap::s_areaHeap = STORM_NEW(uint32_t)(ObjectAllocAddHeap(sizeof(CMapArea), 16, "WAREA", true)); + // CMap::s_areaMedHeap = STORM_NEW(uint32_t)(ObjectAllocAddHeap(sizeof(CMapAreaMed), 16, "WAREAMED", true)); ?? + CMap::s_areaLowHeap = STORM_NEW(uint32_t)(ObjectAllocAddHeap(sizeof(CMapAreaLow), 16, "WAREALOW", true)); + CMap::s_chunkHeap = STORM_NEW(uint32_t)(ObjectAllocAddHeap(sizeof(CMapChunk), 256, "WCHUNK", true)); + CMap::s_doodadDefHeap = STORM_NEW(uint32_t)(ObjectAllocAddHeap(sizeof(CMapDoodadDef), 5000, "WDOODADDEF", true)); + CMap::s_entityHeap = STORM_NEW(uint32_t)(ObjectAllocAddHeap(sizeof(CMapEntity), 128, "WENTITY", true)); + CMap::s_mapObjDefGroupHeap = STORM_NEW(uint32_t)(ObjectAllocAddHeap(sizeof(CMapObjDefGroup), 128, "WMAPOBJDEFGROUP", true)); + CMap::s_mapObjDefHeap = STORM_NEW(uint32_t)(ObjectAllocAddHeap(sizeof(CMapObjDef), 64, "WMAPOBJDEF", true)); + CMap::s_chunkLiquidHeap = STORM_NEW(uint32_t)(ObjectAllocAddHeap(sizeof(CChunkLiquid), 64, "WCHUNKLIQUID", true)); +} diff --git a/src/world/map/CMap.hpp b/src/world/map/CMap.hpp index 3407f37..27e7c39 100644 --- a/src/world/map/CMap.hpp +++ b/src/world/map/CMap.hpp @@ -8,13 +8,28 @@ class CMap { public: // Static variables + static uint32_t* s_areaHeap; + static uint32_t* s_areaLowHeap; + static uint32_t* s_baseObjLinkHeap; + static uint32_t* s_cacheLightHeap; + static uint32_t* s_chunkHeap; + static uint32_t* s_chunkLiquidHeap; + static uint32_t* s_doodadDefHeap; + static uint32_t* s_entityHeap; static STORM_EXPLICIT_LIST(CMapBaseObj, m_lameAssLink) s_entityList; + static uint32_t* s_lightHeap; + static uint32_t* s_mapObjDefGroupHeap; + static uint32_t* s_mapObjDefHeap; + static uint32_t* s_mapObjGroupHeap; + static uint32_t* s_mapObjHeap; static char s_mapName[]; static char s_mapPath[]; static char s_wdtFilename[]; // Static functions + static void Initialize(); static void Load(const char* mapName, int32_t zoneID); + static void MapMemInitialize(); }; #endif diff --git a/src/world/map/CMapArea.hpp b/src/world/map/CMapArea.hpp new file mode 100644 index 0000000..95d87ba --- /dev/null +++ b/src/world/map/CMapArea.hpp @@ -0,0 +1,11 @@ +#ifndef WORLD_MAP_C_MAP_AREA_HPP +#define WORLD_MAP_C_MAP_AREA_HPP + +#include "world/map/CMapBaseObj.hpp" + +class CMapArea : public CMapBaseObj { + public: + // TODO +}; + +#endif diff --git a/src/world/map/CMapAreaLow.hpp b/src/world/map/CMapAreaLow.hpp new file mode 100644 index 0000000..0eb3802 --- /dev/null +++ b/src/world/map/CMapAreaLow.hpp @@ -0,0 +1,9 @@ +#ifndef WORLD_MAP_C_MAP_AREA_LOW_HPP +#define WORLD_MAP_C_MAP_AREA_LOW_HPP + +class CMapAreaLow { + public: + // TODO +}; + +#endif diff --git a/src/world/map/CMapCacheLight.hpp b/src/world/map/CMapCacheLight.hpp new file mode 100644 index 0000000..e2d82ac --- /dev/null +++ b/src/world/map/CMapCacheLight.hpp @@ -0,0 +1,9 @@ +#ifndef WORLD_MAP_C_MAP_CACHE_LIGHT_HPP +#define WORLD_MAP_C_MAP_CACHE_LIGHT_HPP + +class CMapCacheLight { + public: + // TODO +}; + +#endif diff --git a/src/world/map/CMapChunk.hpp b/src/world/map/CMapChunk.hpp new file mode 100644 index 0000000..15ed5ca --- /dev/null +++ b/src/world/map/CMapChunk.hpp @@ -0,0 +1,11 @@ +#ifndef WORLD_MAP_C_MAP_CHUNK_HPP +#define WORLD_MAP_C_MAP_CHUNK_HPP + +#include "world/map/CMapBaseObj.hpp" + +class CMapChunk : public CMapBaseObj { + public: + // TODO +}; + +#endif diff --git a/src/world/map/CMapDoodadDef.hpp b/src/world/map/CMapDoodadDef.hpp new file mode 100644 index 0000000..aa3d321 --- /dev/null +++ b/src/world/map/CMapDoodadDef.hpp @@ -0,0 +1,11 @@ +#ifndef WORLD_MAP_C_MAP_DOODAD_DEF_HPP +#define WORLD_MAP_C_MAP_DOODAD_DEF_HPP + +#include "world/map/CMapStaticEntity.hpp" + +class CMapDoodadDef : public CMapStaticEntity { + public: + // TODO +}; + +#endif diff --git a/src/world/map/CMapLight.hpp b/src/world/map/CMapLight.hpp new file mode 100644 index 0000000..577d866 --- /dev/null +++ b/src/world/map/CMapLight.hpp @@ -0,0 +1,11 @@ +#ifndef WORLD_MAP_C_MAP_LIGHT_HPP +#define WORLD_MAP_C_MAP_LIGHT_HPP + +#include "world/map/CMapBaseObj.hpp" + +class CMapLight : public CMapBaseObj { + public: + // TODO +}; + +#endif diff --git a/src/world/map/CMapObj.hpp b/src/world/map/CMapObj.hpp new file mode 100644 index 0000000..f962679 --- /dev/null +++ b/src/world/map/CMapObj.hpp @@ -0,0 +1,9 @@ +#ifndef WORLD_MAP_C_MAP_OBJ_HPP +#define WORLD_MAP_C_MAP_OBJ_HPP + +class CMapObj { + public: + // TODO +}; + +#endif diff --git a/src/world/map/CMapObjDef.hpp b/src/world/map/CMapObjDef.hpp new file mode 100644 index 0000000..1ce902b --- /dev/null +++ b/src/world/map/CMapObjDef.hpp @@ -0,0 +1,11 @@ +#ifndef WORLD_MAP_C_MAP_OBJ_DEF_HPP +#define WORLD_MAP_C_MAP_OBJ_DEF_HPP + +#include "world/map/CMapBaseObj.hpp" + +class CMapObjDef : public CMapBaseObj { + public: + // TODO +}; + +#endif diff --git a/src/world/map/CMapObjDefGroup.hpp b/src/world/map/CMapObjDefGroup.hpp new file mode 100644 index 0000000..b12f00a --- /dev/null +++ b/src/world/map/CMapObjDefGroup.hpp @@ -0,0 +1,9 @@ +#ifndef WORLD_MAP_C_MAP_OBJ_DEF_GROUP_HPP +#define WORLD_MAP_C_MAP_OBJ_DEF_GROUP_HPP + +class CMapObjDefGroup : public CMapBaseObj { + public: + // TODO +}; + +#endif diff --git a/src/world/map/CMapObjGroup.hpp b/src/world/map/CMapObjGroup.hpp new file mode 100644 index 0000000..7c4ee01 --- /dev/null +++ b/src/world/map/CMapObjGroup.hpp @@ -0,0 +1,9 @@ +#ifndef WORLD_MAP_C_MAP_OBJ_GROUP_HPP +#define WORLD_MAP_C_MAP_OBJ_GROUP_HPP + +class CMapObjGroup { + public: + // TODO +}; + +#endif From fe06d5e820162a28113cde62899cc66c488cb058 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 22 Jan 2026 16:06:48 -0600 Subject: [PATCH 068/269] feat(world): add CMap::AllocEntity --- src/world/map/CMap.cpp | 20 ++++++++++++++++++++ src/world/map/CMap.hpp | 3 +++ 2 files changed, 23 insertions(+) diff --git a/src/world/map/CMap.cpp b/src/world/map/CMap.cpp index 3eb3e71..d58ef54 100644 --- a/src/world/map/CMap.cpp +++ b/src/world/map/CMap.cpp @@ -32,6 +32,26 @@ char CMap::s_mapName[256]; char CMap::s_mapPath[256]; char CMap::s_wdtFilename[256]; +CMapEntity* CMap::AllocEntity(int32_t a1) { + CMapEntity* entity; + uint32_t memHandle; + void* mem = nullptr; + + if (ObjectAlloc(*CMap::s_entityHeap, &memHandle, &mem, false)) { + entity = new (mem) CMapEntity(); + } else { + entity = nullptr; + } + + if (a1) { + CMap::s_entityList.LinkToHead(entity); + } else { + CMap::s_entityList.LinkToTail(entity); + } + + return entity; +} + void CMap::Initialize() { // TODO diff --git a/src/world/map/CMap.hpp b/src/world/map/CMap.hpp index 27e7c39..902d24f 100644 --- a/src/world/map/CMap.hpp +++ b/src/world/map/CMap.hpp @@ -5,6 +5,8 @@ #include #include +class CMapEntity; + class CMap { public: // Static variables @@ -27,6 +29,7 @@ class CMap { static char s_wdtFilename[]; // Static functions + static CMapEntity* AllocEntity(int32_t a1); static void Initialize(); static void Load(const char* mapName, int32_t zoneID); static void MapMemInitialize(); From 948da084b003c729fce39dfe1a353f860c28d53a Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 22 Jan 2026 16:42:59 -0600 Subject: [PATCH 069/269] feat(world): set mem handle when allocating entities --- src/world/map/CMap.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/world/map/CMap.cpp b/src/world/map/CMap.cpp index d58ef54..f86ce96 100644 --- a/src/world/map/CMap.cpp +++ b/src/world/map/CMap.cpp @@ -39,6 +39,7 @@ CMapEntity* CMap::AllocEntity(int32_t a1) { if (ObjectAlloc(*CMap::s_entityHeap, &memHandle, &mem, false)) { entity = new (mem) CMapEntity(); + entity->m_memHandle = memHandle; } else { entity = nullptr; } From c5c2998efcafc68551eee462c907823029a8f3b2 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 23 Jan 2026 08:04:10 -0600 Subject: [PATCH 070/269] feat(world): add CWorld::AddObject --- src/world/CWorld.cpp | 29 +++++++++++++++++++++++++++++ src/world/CWorld.hpp | 3 +++ src/world/map/CMap.hpp | 3 +-- src/world/map/CMapBaseObj.hpp | 6 ++++++ src/world/map/CMapEntity.cpp | 5 +++++ src/world/map/CMapEntity.hpp | 12 ++++++++++++ src/world/map/CMapStaticEntity.hpp | 9 +++++++++ 7 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 src/world/map/CMapEntity.cpp diff --git a/src/world/CWorld.cpp b/src/world/CWorld.cpp index fbe55a3..6163b42 100644 --- a/src/world/CWorld.cpp +++ b/src/world/CWorld.cpp @@ -17,6 +17,35 @@ uint32_t CWorld::s_tickTimeMs; float CWorld::s_tickTimeSec; Weather* CWorld::s_weather; +HWORLDOBJECT CWorld::AddObject(CM2Model* model, void* handler, void* handlerParam, uint64_t param64, uint32_t param32, uint32_t objFlags) { + auto entity = CMap::AllocEntity(objFlags & 0x8 ? true : false); + + entity->m_model = model; + entity->m_param64 = param64; + entity->m_param32 = param32; + + // TODO + + entity->m_dirLightScale = 1.0f; + entity->m_dirLightScaleTarget = 1.0f; + + // TODO + + entity->m_type |= CMapBaseObj::Type_200; + + // TODO + + entity->m_flags = 0x0; + + if (objFlags & 0x20) { + entity->m_flags = 0x20000; + } + + // TODO + + return reinterpret_cast(entity); +} + uint32_t CWorld::GetCurTimeMs() { return CWorld::s_curTimeMs; } diff --git a/src/world/CWorld.hpp b/src/world/CWorld.hpp index c3be35d..93cf9fc 100644 --- a/src/world/CWorld.hpp +++ b/src/world/CWorld.hpp @@ -2,9 +2,11 @@ #define WORLD_C_WORLD_HPP #include "event/Event.hpp" +#include "world/Types.hpp" #include #include +class CM2Model; class Weather; class CWorld { @@ -51,6 +53,7 @@ class CWorld { static Weather* s_weather; // Public static functions + static HWORLDOBJECT AddObject(CM2Model* model, void* handler, void* handlerParam, uint64_t param64, uint32_t param32, uint32_t objFlags); static uint32_t GetCurTimeMs(); static float GetCurTimeSec(); static uint32_t GetGameTimeFixed(); diff --git a/src/world/map/CMap.hpp b/src/world/map/CMap.hpp index 902d24f..c70177b 100644 --- a/src/world/map/CMap.hpp +++ b/src/world/map/CMap.hpp @@ -2,11 +2,10 @@ #define WORLD_MAP_C_MAP_HPP #include "world/map/CMapBaseObj.hpp" +#include "world/map/CMapEntity.hpp" #include #include -class CMapEntity; - class CMap { public: // Static variables diff --git a/src/world/map/CMapBaseObj.hpp b/src/world/map/CMapBaseObj.hpp index d9693c8..ca77666 100644 --- a/src/world/map/CMapBaseObj.hpp +++ b/src/world/map/CMapBaseObj.hpp @@ -18,6 +18,9 @@ class CMapBaseObjLink { }; class CMapBaseObj { + friend class CMap; + friend class CWorld; + public: // Enums enum { @@ -29,10 +32,13 @@ class CMapBaseObj { Type_Entity = 0x20, Type_DoodadDef = 0x40, Type_Light = 0x80, + Type_100 = 0x100, + Type_200 = 0x200, }; // Public member variables uint32_t m_memHandle; + uint32_t m_flags = 0x0; TSLink m_lameAssLink; STORM_EXPLICIT_LIST(CMapBaseObjLink, ownerLink) m_parentLinkList; diff --git a/src/world/map/CMapEntity.cpp b/src/world/map/CMapEntity.cpp new file mode 100644 index 0000000..90fb8a3 --- /dev/null +++ b/src/world/map/CMapEntity.cpp @@ -0,0 +1,5 @@ +#include "world/map/CMapEntity.hpp" + +CMapEntity::CMapEntity() { + this->m_type |= CMapBaseObj::Type_Entity; +} diff --git a/src/world/map/CMapEntity.hpp b/src/world/map/CMapEntity.hpp index 156c4fd..82a080e 100644 --- a/src/world/map/CMapEntity.hpp +++ b/src/world/map/CMapEntity.hpp @@ -2,10 +2,22 @@ #define WORLD_MAP_C_MAP_ENTITY_HPP #include "world/map/CMapStaticEntity.hpp" +#include class CMapEntity : public CMapStaticEntity { public: + // Member variables + void* m_handler = nullptr; + void* m_handlerParam = nullptr; + uint64_t m_param64 = 0; + uint32_t m_param32 = 0; // TODO + CImVector m_ambientTarget = { 0xFF, 0x00, 0x00, 0x00 }; + float m_dirLightScaleTarget = 0.0f; + // TODO + + // Member functions + CMapEntity(); }; #endif diff --git a/src/world/map/CMapStaticEntity.hpp b/src/world/map/CMapStaticEntity.hpp index 917ea7f..efb8bcb 100644 --- a/src/world/map/CMapStaticEntity.hpp +++ b/src/world/map/CMapStaticEntity.hpp @@ -2,10 +2,19 @@ #define WORLD_MAP_C_MAP_STATIC_ENTITY_HPP #include "world/map/CMapBaseObj.hpp" +#include + +class CM2Model; class CMapStaticEntity : public CMapBaseObj { public: + // Member variables // TODO + CM2Model* m_model = nullptr; + // TODO + CImVector m_ambient = {}; + CImVector m_interiorDirColor = {}; + float m_dirLightScale = 0.0f; }; #endif From 1f7aa984b02db3f8c3104b1e21ed6a598b306746 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 23 Jan 2026 15:23:55 -0600 Subject: [PATCH 071/269] chore(ui): move interface key to ui --- src/glue/CGlueMgr.cpp | 22 ++-------------------- src/ui/Key.cpp | 20 ++++++++++++++++++++ src/ui/Key.hpp | 8 ++++++++ 3 files changed, 30 insertions(+), 20 deletions(-) create mode 100644 src/ui/Key.cpp create mode 100644 src/ui/Key.hpp diff --git a/src/glue/CGlueMgr.cpp b/src/glue/CGlueMgr.cpp index 6591a9e..27049df 100644 --- a/src/glue/CGlueMgr.cpp +++ b/src/glue/CGlueMgr.cpp @@ -25,6 +25,7 @@ #include "ui/FrameScript.hpp" #include "ui/FrameXML.hpp" #include "ui/Interface.hpp" +#include "ui/Key.hpp" #include "ui/ScriptFunctions.hpp" #include "ui/game/CGVideoOptions.hpp" #include "ui/simple/CSimpleModelFFX.hpp" @@ -36,25 +37,6 @@ #include #include -unsigned char InterfaceKey[256] = { - 0xC3, 0x5B, 0x50, 0x84, 0xB9, 0x3E, 0x32, 0x42, 0x8C, 0xD0, 0xC7, 0x48, 0xFA, 0x0E, 0x5D, 0x54, - 0x5A, 0xA3, 0x0E, 0x14, 0xBA, 0x9E, 0x0D, 0xB9, 0x5D, 0x8B, 0xEE, 0xB6, 0x84, 0x93, 0x45, 0x75, - 0xFF, 0x31, 0xFE, 0x2F, 0x64, 0x3F, 0x3D, 0x6D, 0x07, 0xD9, 0x44, 0x9B, 0x40, 0x85, 0x59, 0x34, - 0x4E, 0x10, 0xE1, 0xE7, 0x43, 0x69, 0xEF, 0x7C, 0x16, 0xFC, 0xB4, 0xED, 0x1B, 0x95, 0x28, 0xA8, - 0x23, 0x76, 0x51, 0x31, 0x57, 0x30, 0x2B, 0x79, 0x08, 0x50, 0x10, 0x1C, 0x4A, 0x1A, 0x2C, 0xC8, - 0x8B, 0x8F, 0x05, 0x2D, 0x22, 0x3D, 0xDB, 0x5A, 0x24, 0x7A, 0x0F, 0x13, 0x50, 0x37, 0x8F, 0x5A, - 0xCC, 0x9E, 0x04, 0x44, 0x0E, 0x87, 0x01, 0xD4, 0xA3, 0x15, 0x94, 0x16, 0x34, 0xC6, 0xC2, 0xC3, - 0xFB, 0x49, 0xFE, 0xE1, 0xF9, 0xDA, 0x8C, 0x50, 0x3C, 0xBE, 0x2C, 0xBB, 0x57, 0xED, 0x46, 0xB9, - 0xAD, 0x8B, 0xC6, 0xDF, 0x0E, 0xD6, 0x0F, 0xBE, 0x80, 0xB3, 0x8B, 0x1E, 0x77, 0xCF, 0xAD, 0x22, - 0xCF, 0xB7, 0x4B, 0xCF, 0xFB, 0xF0, 0x6B, 0x11, 0x45, 0x2D, 0x7A, 0x81, 0x18, 0xF2, 0x92, 0x7E, - 0x98, 0x56, 0x5D, 0x5E, 0x69, 0x72, 0x0A, 0x0D, 0x03, 0x0A, 0x85, 0xA2, 0x85, 0x9C, 0xCB, 0xFB, - 0x56, 0x6E, 0x8F, 0x44, 0xBB, 0x8F, 0x02, 0x22, 0x68, 0x63, 0x97, 0xBC, 0x85, 0xBA, 0xA8, 0xF7, - 0xB5, 0x40, 0x68, 0x3C, 0x77, 0x86, 0x6F, 0x4B, 0xD7, 0x88, 0xCA, 0x8A, 0xD7, 0xCE, 0x36, 0xF0, - 0x45, 0x6E, 0xD5, 0x64, 0x79, 0x0F, 0x17, 0xFC, 0x64, 0xDD, 0x10, 0x6F, 0xF3, 0xF5, 0xE0, 0xA6, - 0xC3, 0xFB, 0x1B, 0x8C, 0x29, 0xEF, 0x8E, 0xE5, 0x34, 0xCB, 0xD1, 0x2A, 0xCE, 0x79, 0xC3, 0x9A, - 0x0D, 0x36, 0xEA, 0x01, 0xE0, 0xAA, 0x91, 0x20, 0x54, 0xF0, 0x72, 0xD8, 0x1E, 0xC7, 0x89, 0xD2 -}; - int32_t CGlueMgr::m_acceptedEULA = 1; // TODO int32_t CGlueMgr::m_acceptedTerminationWithoutNotice; int32_t CGlueMgr::m_acceptedTOS = 1; // TODO @@ -1015,7 +997,7 @@ void CGlueMgr::Resume() { MD5Init(&md5); - switch (FrameXML_CheckSignature("Interface\\GlueXML\\GlueXML.toc", 0, InterfaceKey, digest1)) { + switch (FrameXML_CheckSignature("Interface\\GlueXML\\GlueXML.toc", nullptr, InterfaceKey, digest1)) { case 0: status.Add(STATUS_WARNING, "GlueXML missing signature"); ClientPostClose(9); diff --git a/src/ui/Key.cpp b/src/ui/Key.cpp new file mode 100644 index 0000000..738ba04 --- /dev/null +++ b/src/ui/Key.cpp @@ -0,0 +1,20 @@ +#include "ui/Key.hpp" + +uint8_t InterfaceKey[256] = { + 0xC3, 0x5B, 0x50, 0x84, 0xB9, 0x3E, 0x32, 0x42, 0x8C, 0xD0, 0xC7, 0x48, 0xFA, 0x0E, 0x5D, 0x54, + 0x5A, 0xA3, 0x0E, 0x14, 0xBA, 0x9E, 0x0D, 0xB9, 0x5D, 0x8B, 0xEE, 0xB6, 0x84, 0x93, 0x45, 0x75, + 0xFF, 0x31, 0xFE, 0x2F, 0x64, 0x3F, 0x3D, 0x6D, 0x07, 0xD9, 0x44, 0x9B, 0x40, 0x85, 0x59, 0x34, + 0x4E, 0x10, 0xE1, 0xE7, 0x43, 0x69, 0xEF, 0x7C, 0x16, 0xFC, 0xB4, 0xED, 0x1B, 0x95, 0x28, 0xA8, + 0x23, 0x76, 0x51, 0x31, 0x57, 0x30, 0x2B, 0x79, 0x08, 0x50, 0x10, 0x1C, 0x4A, 0x1A, 0x2C, 0xC8, + 0x8B, 0x8F, 0x05, 0x2D, 0x22, 0x3D, 0xDB, 0x5A, 0x24, 0x7A, 0x0F, 0x13, 0x50, 0x37, 0x8F, 0x5A, + 0xCC, 0x9E, 0x04, 0x44, 0x0E, 0x87, 0x01, 0xD4, 0xA3, 0x15, 0x94, 0x16, 0x34, 0xC6, 0xC2, 0xC3, + 0xFB, 0x49, 0xFE, 0xE1, 0xF9, 0xDA, 0x8C, 0x50, 0x3C, 0xBE, 0x2C, 0xBB, 0x57, 0xED, 0x46, 0xB9, + 0xAD, 0x8B, 0xC6, 0xDF, 0x0E, 0xD6, 0x0F, 0xBE, 0x80, 0xB3, 0x8B, 0x1E, 0x77, 0xCF, 0xAD, 0x22, + 0xCF, 0xB7, 0x4B, 0xCF, 0xFB, 0xF0, 0x6B, 0x11, 0x45, 0x2D, 0x7A, 0x81, 0x18, 0xF2, 0x92, 0x7E, + 0x98, 0x56, 0x5D, 0x5E, 0x69, 0x72, 0x0A, 0x0D, 0x03, 0x0A, 0x85, 0xA2, 0x85, 0x9C, 0xCB, 0xFB, + 0x56, 0x6E, 0x8F, 0x44, 0xBB, 0x8F, 0x02, 0x22, 0x68, 0x63, 0x97, 0xBC, 0x85, 0xBA, 0xA8, 0xF7, + 0xB5, 0x40, 0x68, 0x3C, 0x77, 0x86, 0x6F, 0x4B, 0xD7, 0x88, 0xCA, 0x8A, 0xD7, 0xCE, 0x36, 0xF0, + 0x45, 0x6E, 0xD5, 0x64, 0x79, 0x0F, 0x17, 0xFC, 0x64, 0xDD, 0x10, 0x6F, 0xF3, 0xF5, 0xE0, 0xA6, + 0xC3, 0xFB, 0x1B, 0x8C, 0x29, 0xEF, 0x8E, 0xE5, 0x34, 0xCB, 0xD1, 0x2A, 0xCE, 0x79, 0xC3, 0x9A, + 0x0D, 0x36, 0xEA, 0x01, 0xE0, 0xAA, 0x91, 0x20, 0x54, 0xF0, 0x72, 0xD8, 0x1E, 0xC7, 0x89, 0xD2 +}; diff --git a/src/ui/Key.hpp b/src/ui/Key.hpp new file mode 100644 index 0000000..7aef2bc --- /dev/null +++ b/src/ui/Key.hpp @@ -0,0 +1,8 @@ +#ifndef UI_KEY_HPP +#define UI_KEY_HPP + +#include + +extern uint8_t InterfaceKey[256]; + +#endif From bdf0bd27a119693e752872aab6c112e6b88d218b Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 23 Jan 2026 21:17:43 -0600 Subject: [PATCH 072/269] feat(ui): initialize game UI in ClientInitializeGame --- src/client/Client.cpp | 5 ++ src/ui/Game.hpp | 6 +++ src/ui/game/CGGameUI.cpp | 94 ++++++++++++++++++++++++++++++++++++ src/ui/game/CGGameUI.hpp | 17 +++++++ src/ui/game/CGWorldFrame.cpp | 22 +++++++++ src/ui/game/CGWorldFrame.hpp | 19 ++++++++ 6 files changed, 163 insertions(+) create mode 100644 src/ui/Game.hpp create mode 100644 src/ui/game/CGGameUI.cpp create mode 100644 src/ui/game/CGGameUI.hpp create mode 100644 src/ui/game/CGWorldFrame.cpp create mode 100644 src/ui/game/CGWorldFrame.hpp diff --git a/src/client/Client.cpp b/src/client/Client.cpp index 4e2722f..a193f64 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -18,6 +18,7 @@ #include "sound/Interface.hpp" #include "ui/FrameScript.hpp" #include "ui/FrameXML.hpp" +#include "ui/Game.hpp" #include "util/Random.hpp" #include "world/World.hpp" #include @@ -85,6 +86,10 @@ void ClientInitializeGame(uint32_t mapId, C3Vector position) { // TODO + CGGameUI::InitializeGame(); + + // TODO + EventRegister(EVENT_ID_IDLE, ClientIdle); // TODO diff --git a/src/ui/Game.hpp b/src/ui/Game.hpp new file mode 100644 index 0000000..6f5e712 --- /dev/null +++ b/src/ui/Game.hpp @@ -0,0 +1,6 @@ +#ifndef UI_GAME_HPP +#define UI_GAME_HPP + +#include "ui/game/CGGameUI.hpp" + +#endif diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp new file mode 100644 index 0000000..0f1ff34 --- /dev/null +++ b/src/ui/game/CGGameUI.cpp @@ -0,0 +1,94 @@ +#include "ui/game/CGGameUI.hpp" +#include "client/Client.hpp" +#include "ui/FrameXML.hpp" +#include "ui/Key.hpp" +#include "ui/game/CGWorldFrame.hpp" +#include "ui/simple/CSimpleTop.hpp" +#include "util/CStatus.hpp" +#include + +CSimpleTop* CGGameUI::s_simpleTop; + +void CGGameUI::Initialize() { + // TODO + + CGGameUI::s_simpleTop = STORM_NEW(CSimpleTop); + + // TODO + + CGGameUI::RegisterFrameFactories(); + + // TODO + + CStatus status; + + // TODO + + MD5_CTX md5; + uint8_t digest1[16]; + uint8_t digest2[16]; + + MD5Init(&md5); + + switch (FrameXML_CheckSignature("Interface\\FrameXML\\FrameXML.toc", "Interface\\FrameXML\\Bindings.xml", InterfaceKey, digest1)) { + case 0: { + status.Add(STATUS_WARNING, "FrameXML missing signature"); + ClientPostClose(10); + + return; + } + + case 1: { + status.Add(STATUS_WARNING, "FrameXML has corrupt signature"); + ClientPostClose(10); + + return; + } + + case 2: { + status.Add(STATUS_WARNING, "FrameXML is modified or corrupt"); + ClientPostClose(10); + + return; + } + + case 3: { + // Success + break; + } + + default: { + ClientPostClose(10); + + return; + } + } + + // TODO file count and progress bar logic + + FrameXML_FreeHashNodes(); + + FrameXML_CreateFrames("Interface\\FrameXML\\FrameXML.toc", nullptr, &md5, &status); + + // TODO CGUIBindings::s_bindings->Load("Interface\\FrameXML\\Bindings.xml", &md5, &status); + + MD5Final(digest2, &md5); + + // TODO digest validation + + // TODO +} + +void CGGameUI::InitializeGame() { + // TODO + + CGGameUI::Initialize(); + + // TODO +} + +void CGGameUI::RegisterFrameFactories() { + FrameXML_RegisterFactory("WorldFrame", &CGWorldFrame::Create, true); + + // TODO register remaining factories +} diff --git a/src/ui/game/CGGameUI.hpp b/src/ui/game/CGGameUI.hpp new file mode 100644 index 0000000..17b86f1 --- /dev/null +++ b/src/ui/game/CGGameUI.hpp @@ -0,0 +1,17 @@ +#ifndef UI_GAME_C_G_GAME_UI_HPP +#define UI_GAME_C_G_GAME_UI_HPP + +class CSimpleTop; + +class CGGameUI { + public: + // Static variables + static CSimpleTop* s_simpleTop; + + // Static functions + static void Initialize(); + static void InitializeGame(); + static void RegisterFrameFactories(); +}; + +#endif diff --git a/src/ui/game/CGWorldFrame.cpp b/src/ui/game/CGWorldFrame.cpp new file mode 100644 index 0000000..db9a49e --- /dev/null +++ b/src/ui/game/CGWorldFrame.cpp @@ -0,0 +1,22 @@ +#include "ui/game/CGWorldFrame.hpp" +#include + +CSimpleFrame* CGWorldFrame::Create(CSimpleFrame* parent) { + // TODO use CDataAllocator + + return STORM_NEW(CGWorldFrame)(parent); +} + +CGWorldFrame::CGWorldFrame(CSimpleFrame* parent) : CSimpleFrame(parent) { + // TODO + + CGWorldFrame::s_currentWorldFrame = this; + + // TODO + + this->EnableEvent(SIMPLE_EVENT_KEY, -1); + this->EnableEvent(SIMPLE_EVENT_MOUSE, -1); + this->EnableEvent(SIMPLE_EVENT_MOUSEWHEEL, -1); + + // TODO +} diff --git a/src/ui/game/CGWorldFrame.hpp b/src/ui/game/CGWorldFrame.hpp new file mode 100644 index 0000000..ce95231 --- /dev/null +++ b/src/ui/game/CGWorldFrame.hpp @@ -0,0 +1,19 @@ +#ifndef UI_GAME_C_G_WORLD_FRAME_HPP +#define UI_GAME_C_G_WORLD_FRAME_HPP + +#include "ui/simple/CSimpleFrame.hpp" +#include + +class CGWorldFrame : public CSimpleFrame { + public: + // Static variables + CGWorldFrame* s_currentWorldFrame; + + // Static functions + static CSimpleFrame* Create(CSimpleFrame* parent); + + // Member functions + CGWorldFrame(CSimpleFrame* parent); +}; + +#endif From 8d1316b163d28f9476d87b32bdf3dbd472ef4d32 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 24 Jan 2026 20:58:04 -0600 Subject: [PATCH 073/269] chore: normalize signature checking logic between GlueXML and FrameXML --- src/glue/CGlueMgr.cpp | 56 +++++++++++++++++++++------------------- src/ui/game/CGGameUI.cpp | 16 ++++++------ 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/glue/CGlueMgr.cpp b/src/glue/CGlueMgr.cpp index 27049df..90fae26 100644 --- a/src/glue/CGlueMgr.cpp +++ b/src/glue/CGlueMgr.cpp @@ -987,51 +987,53 @@ void CGlueMgr::Resume() { DeleteInterfaceFiles(); - MD5_CTX md5; - unsigned char digest1[16]; - unsigned char digest2[16]; - - int32_t v8; - unsigned char* v9; - unsigned char* v10; - - MD5Init(&md5); + uint8_t digest1[16]; switch (FrameXML_CheckSignature("Interface\\GlueXML\\GlueXML.toc", nullptr, InterfaceKey, digest1)) { - case 0: + case 0: { status.Add(STATUS_WARNING, "GlueXML missing signature"); ClientPostClose(9); - return; - case 1: + return; + } + + case 1: { status.Add(STATUS_WARNING, "GlueXML has corrupt signature"); ClientPostClose(9); - return; - case 2: + return; + } + + case 2: { status.Add(STATUS_WARNING, "GlueXML is modified or corrupt"); ClientPostClose(9); + return; + } - case 3: - FrameXML_FreeHashNodes(); - FrameXML_CreateFrames("Interface\\GlueXML\\GlueXML.toc", 0, &md5, &status); - - MD5Final(digest2, &md5); - - v8 = 16; - v9 = digest2; - v10 = digest1; - + case 3: { + // Success break; + } - default: + default: { ClientPostClose(9); + return; + } } - // TODO - // - some kind of digest validation? + MD5_CTX md5; + MD5Init(&md5); + + FrameXML_FreeHashNodes(); + + FrameXML_CreateFrames("Interface\\GlueXML\\GlueXML.toc", nullptr, &md5, &status); + + uint8_t digest2[16]; + MD5Final(digest2, &md5); + + // TODO digest validation FrameScript_SignalEvent(22, nullptr); diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 0f1ff34..2411bc7 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -24,32 +24,28 @@ void CGGameUI::Initialize() { // TODO - MD5_CTX md5; uint8_t digest1[16]; - uint8_t digest2[16]; - - MD5Init(&md5); switch (FrameXML_CheckSignature("Interface\\FrameXML\\FrameXML.toc", "Interface\\FrameXML\\Bindings.xml", InterfaceKey, digest1)) { case 0: { status.Add(STATUS_WARNING, "FrameXML missing signature"); ClientPostClose(10); - return; + break; } case 1: { status.Add(STATUS_WARNING, "FrameXML has corrupt signature"); ClientPostClose(10); - return; + break; } case 2: { status.Add(STATUS_WARNING, "FrameXML is modified or corrupt"); ClientPostClose(10); - return; + break; } case 3: { @@ -60,10 +56,13 @@ void CGGameUI::Initialize() { default: { ClientPostClose(10); - return; + break; } } + MD5_CTX md5; + MD5Init(&md5); + // TODO file count and progress bar logic FrameXML_FreeHashNodes(); @@ -72,6 +71,7 @@ void CGGameUI::Initialize() { // TODO CGUIBindings::s_bindings->Load("Interface\\FrameXML\\Bindings.xml", &md5, &status); + uint8_t digest2[16]; MD5Final(digest2, &md5); // TODO digest validation From 1589466076e9b579764f3c20babc75979a9ed54c Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 24 Jan 2026 22:48:09 -0600 Subject: [PATCH 074/269] feat(ui): add proper ScriptIx dtor --- src/ui/FrameScript_Object.cpp | 12 ++++++------ src/ui/FrameScript_Object.hpp | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/ui/FrameScript_Object.cpp b/src/ui/FrameScript_Object.cpp index d63daae..15b19a6 100644 --- a/src/ui/FrameScript_Object.cpp +++ b/src/ui/FrameScript_Object.cpp @@ -5,6 +5,12 @@ int32_t FrameScript_Object::s_objectTypes = 0; +FrameScript_Object::ScriptIx::~ScriptIx() { + if (this->luaRef) { + luaL_unref(FrameScript_GetContext(), LUA_REGISTRYINDEX, this->luaRef); + } +} + int32_t FrameScript_Object::CreateScriptMetaTable(lua_State* L, void (*a2)(lua_State* L)) { lua_createtable(L, 0, 0); lua_pushstring(L, "__index"); @@ -24,12 +30,6 @@ void FrameScript_Object::FillScriptMethodTable(lua_State *L, FrameScript_Method } } -FrameScript_Object::~FrameScript_Object() { - if (this->m_onEvent.luaRef) { - luaL_unref(FrameScript_GetContext(), LUA_REGISTRYINDEX, this->m_onEvent.luaRef); - } -} - const char* FrameScript_Object::GetDisplayName() { const char* name = this->GetName(); return name ? name : ""; diff --git a/src/ui/FrameScript_Object.hpp b/src/ui/FrameScript_Object.hpp index c8edad2..e80049e 100644 --- a/src/ui/FrameScript_Object.hpp +++ b/src/ui/FrameScript_Object.hpp @@ -14,6 +14,7 @@ class FrameScript_Object { struct ScriptIx { int32_t luaRef = 0; const char* unk = nullptr; + ~ScriptIx(); }; class ScriptFunction { @@ -34,7 +35,7 @@ class FrameScript_Object { ScriptIx m_onEvent; // Virtual member functions - virtual ~FrameScript_Object(); + virtual ~FrameScript_Object() = default; virtual char* GetName() = 0; virtual int32_t GetScriptMetaTable() = 0; virtual ScriptIx* GetScriptByName(const char* name, ScriptData& data); From 23be35bed231f78be5239a6b998e281f86b6e19e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 25 Jan 2026 12:45:10 -0600 Subject: [PATCH 075/269] feat(ui): delete strata in CSimpleTop dtor --- src/ui/simple/CSimpleTop.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ui/simple/CSimpleTop.cpp b/src/ui/simple/CSimpleTop.cpp index fa9903c..61a4a8f 100644 --- a/src/ui/simple/CSimpleTop.cpp +++ b/src/ui/simple/CSimpleTop.cpp @@ -400,6 +400,13 @@ CSimpleTop::CSimpleTop() : CLayoutFrame() { CSimpleTop::~CSimpleTop() { // TODO + for (auto& strata : this->m_strata) { + delete strata; + strata = nullptr; + } + + // TODO + this->DisableEvents(); HandleClose(this->m_screenLayer); From 4e9ea8f5a1be43260c913bdbc6c156b3765ae93b Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 25 Jan 2026 13:40:19 -0600 Subject: [PATCH 076/269] feat(ui): delete frames in CSimpleTop dtor --- src/ui/simple/CSimpleTop.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ui/simple/CSimpleTop.cpp b/src/ui/simple/CSimpleTop.cpp index 61a4a8f..4283997 100644 --- a/src/ui/simple/CSimpleTop.cpp +++ b/src/ui/simple/CSimpleTop.cpp @@ -400,6 +400,11 @@ CSimpleTop::CSimpleTop() : CLayoutFrame() { CSimpleTop::~CSimpleTop() { // TODO + while (auto frame = this->m_frames.Head()) { + this->m_frames.UnlinkNode(frame); + delete frame; + } + for (auto& strata : this->m_strata) { delete strata; strata = nullptr; From cded0d86e7b97ba80937cb6c71ca744141e3821c Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 25 Jan 2026 14:37:15 -0600 Subject: [PATCH 077/269] feat(ui): clear top pointer in CSimpleFrame dtor --- src/ui/simple/CSimpleFrame.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/simple/CSimpleFrame.cpp b/src/ui/simple/CSimpleFrame.cpp index 500772a..7630899 100644 --- a/src/ui/simple/CSimpleFrame.cpp +++ b/src/ui/simple/CSimpleFrame.cpp @@ -69,6 +69,7 @@ CSimpleFrame::~CSimpleFrame() { this->m_intAC = 3; this->m_top->UnregisterFrame(this); + this->m_top = nullptr; // TODO } From daba2a1ffd899f480fbf0f0b771ad840efb8f1a3 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 25 Jan 2026 14:40:28 -0600 Subject: [PATCH 078/269] feat(ui): delete title region in CSimpleFrame dtor --- src/ui/simple/CSimpleFrame.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ui/simple/CSimpleFrame.cpp b/src/ui/simple/CSimpleFrame.cpp index 7630899..9cf321d 100644 --- a/src/ui/simple/CSimpleFrame.cpp +++ b/src/ui/simple/CSimpleFrame.cpp @@ -64,13 +64,15 @@ CSimpleFrame::CSimpleFrame(CSimpleFrame* parent) : CScriptRegion() { } CSimpleFrame::~CSimpleFrame() { - // TODO - this->m_intAC = 3; this->m_top->UnregisterFrame(this); this->m_top = nullptr; + if (this->m_titleRegion) { + delete this->m_titleRegion; + } + // TODO } From c2eedc1d473de6acfea9f9544cc278023dc2d990 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 25 Jan 2026 14:50:16 -0600 Subject: [PATCH 079/269] feat(ui): clean up draw layers and batches in CSimpleFrame dtor --- src/ui/simple/CSimpleFrame.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ui/simple/CSimpleFrame.cpp b/src/ui/simple/CSimpleFrame.cpp index 9cf321d..83bbd59 100644 --- a/src/ui/simple/CSimpleFrame.cpp +++ b/src/ui/simple/CSimpleFrame.cpp @@ -73,6 +73,14 @@ CSimpleFrame::~CSimpleFrame() { delete this->m_titleRegion; } + for (int32_t layer = 0; layer < NUM_SIMPLEFRAME_DRAWLAYERS; layer++) { + this->m_drawlayers[layer].UnlinkAll(); + + if (this->m_batch[layer]) { + delete this->m_batch[layer]; + } + } + // TODO } From f1b8f495b668cffddbf5739bb19490f554f893ba Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 25 Jan 2026 15:05:10 -0600 Subject: [PATCH 080/269] feat(ui): delete regions in CSimpleFrame dtor --- src/ui/simple/CSimpleFrame.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ui/simple/CSimpleFrame.cpp b/src/ui/simple/CSimpleFrame.cpp index 83bbd59..cc176e7 100644 --- a/src/ui/simple/CSimpleFrame.cpp +++ b/src/ui/simple/CSimpleFrame.cpp @@ -81,6 +81,11 @@ CSimpleFrame::~CSimpleFrame() { } } + while (auto region = this->m_regions.Head()) { + this->m_regions.UnlinkNode(region); + delete region; + } + // TODO } From caf628145db7311baef3d599a19f14abbdf33581 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 25 Jan 2026 22:37:37 -0600 Subject: [PATCH 081/269] feat(ui): add ScriptEventsRegisterFunctions --- src/ui/game/CGGameUI.cpp | 13 + src/ui/game/ScriptEvents.cpp | 861 +++++++++++++++++++++++++++++++++++ src/ui/game/ScriptEvents.hpp | 6 + 3 files changed, 880 insertions(+) create mode 100644 src/ui/game/ScriptEvents.cpp create mode 100644 src/ui/game/ScriptEvents.hpp diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 2411bc7..4e6277a 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -3,12 +3,21 @@ #include "ui/FrameXML.hpp" #include "ui/Key.hpp" #include "ui/game/CGWorldFrame.hpp" +#include "ui/game/ScriptEvents.hpp" #include "ui/simple/CSimpleTop.hpp" #include "util/CStatus.hpp" #include CSimpleTop* CGGameUI::s_simpleTop; +void LoadScriptFunctions() { + // TODO + + ScriptEventsRegisterFunctions(); + + // TODO +} + void CGGameUI::Initialize() { // TODO @@ -16,6 +25,10 @@ void CGGameUI::Initialize() { // TODO + LoadScriptFunctions(); + + // TODO + CGGameUI::RegisterFrameFactories(); // TODO diff --git a/src/ui/game/ScriptEvents.cpp b/src/ui/game/ScriptEvents.cpp new file mode 100644 index 0000000..33419f3 --- /dev/null +++ b/src/ui/game/ScriptEvents.cpp @@ -0,0 +1,861 @@ +#include "ui/game/ScriptEvents.hpp" +#include "ui/FrameScript.hpp" +#include "ui/ScriptFunctions.hpp" +#include "ui/ScriptFunctionsShared.hpp" +#include "util/Unimplemented.hpp" + +int32_t Script_UnitExists(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsVisible(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsUnit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsPlayer(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsInMyGuild(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsCorpse(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsPartyLeader(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitGroupRolesAssigned(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsRaidOfficer(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitInParty(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitPlayerOrPetInParty(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitInRaid(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitPlayerOrPetInRaid(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitPlayerControlled(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsAFK(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsDND(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsPVP(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsPVPSanctuary(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsPVPFreeForAll(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitFactionGroup(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitReaction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsEnemy(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsFriend(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitCanCooperate(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitCanAssist(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitCanAttack(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsCharmed(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsPossessed(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_PlayerCanTeleport(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitClassification(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitSelectionColor(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitGUID(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitPVPName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitXP(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitXPMax(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitHealth(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitHealthMax(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitMana(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitManaMax(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitPower(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitPowerMax(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitPowerType(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitOnTaxi(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsFeignDeath(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsDead(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsGhost(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsDeadOrGhost(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsConnected(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitAffectingCombat(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitSex(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitLevel(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetMoney(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetHonorCurrency(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetArenaCurrency(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitRace(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitClass(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitClassBase(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitResistance(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitStat(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitAttackBothHands(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitDamage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitRangedDamage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitRangedAttack(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitAttackSpeed(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitAttackPower(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitRangedAttackPower(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitDefense(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitArmor(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitCharacterPoints(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitBuff(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitDebuff(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitAura(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsTapped(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsTappedByPlayer(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsTappedByAllThreatList(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsTrivial(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitHasRelicSlot(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetPortraitTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_HasFullControl(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetComboPoints(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsInGuild(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsGuildLeader(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsArenaTeamCaptain(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsInArenaTeam(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsResting(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCombatRating(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCombatRatingBonus(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetMaxCombatRatingBonus(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetDodgeChance(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBlockChance(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetShieldBlock(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetParryChance(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCritChanceFromAgility(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetSpellCritChanceFromIntellect(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCritChance(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetRangedCritChance(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetSpellCritChance(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetSpellBonusDamage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetSpellBonusHealing(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPetSpellBonusDamage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetSpellPenetration(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetArmorPenetration(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetAttackPowerForStat(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitCreatureType(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitCreatureFamily(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetResSicknessDuration(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPVPSessionStats(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPVPYesterdayStats(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPVPLifetimeStats(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitPVPRank(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPVPRankInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPVPRankProgress(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitCastingInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitChannelInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsLoggedIn(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsFlyableArea(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsIndoors(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsOutdoors(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsOutOfBounds(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsFalling(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsSwimming(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsFlying(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsMounted(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsStealthed(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsSameServer(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetUnitHealthModifier(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetUnitMaxHealthModifier(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetUnitPowerModifier(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetUnitHealthRegenRateFromSpirit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetUnitManaRegenRateFromSpirit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetManaRegen(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPowerRegen(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetRuneCooldown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetRuneCount(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetRuneType(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ReportPlayerIsPVPAFK(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_PlayerIsPVPInactive(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetExpertise(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetExpertisePercent(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitInBattleground(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitInRange(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetUnitSpeed(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetUnitPitch(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitInVehicle(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitUsingVehicle(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitControllingVehicle(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitInVehicleControlSeat(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitHasVehicleUI(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitTargetsVehicleInRaidUI(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitVehicleSkin(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitVehicleSeatCount(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitVehicleSeatInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitSwitchToVehicleSeat(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CanSwitchVehicleSeat(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetVehicleUIIndicator(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetVehicleUIIndicatorSeat(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitThreatSituation(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitDetailedThreatSituation(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnitIsControlling(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_EjectPassengerFromSeat(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CanEjectPassengerFromSeat(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RespondInstanceLock(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPlayerFacing(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPlayerInfoByGUID(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetItemStats(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetItemStatDelta(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsXPUserDisabled(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_FillLocalizedClassList(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +static FrameScript_Method s_UnitFunctions[] = { + { "UnitExists", &Script_UnitExists }, + { "UnitIsVisible", &Script_UnitIsVisible }, + { "UnitIsUnit", &Script_UnitIsUnit }, + { "UnitIsPlayer", &Script_UnitIsPlayer }, + { "UnitIsInMyGuild", &Script_UnitIsInMyGuild }, + { "UnitIsCorpse", &Script_UnitIsCorpse }, + { "UnitIsPartyLeader", &Script_UnitIsPartyLeader }, + { "UnitGroupRolesAssigned", &Script_UnitGroupRolesAssigned }, + { "UnitIsRaidOfficer", &Script_UnitIsRaidOfficer }, + { "UnitInParty", &Script_UnitInParty }, + { "UnitPlayerOrPetInParty", &Script_UnitPlayerOrPetInParty }, + { "UnitInRaid", &Script_UnitInRaid }, + { "UnitPlayerOrPetInRaid", &Script_UnitPlayerOrPetInRaid }, + { "UnitPlayerControlled", &Script_UnitPlayerControlled }, + { "UnitIsAFK", &Script_UnitIsAFK }, + { "UnitIsDND", &Script_UnitIsDND }, + { "UnitIsPVP", &Script_UnitIsPVP }, + { "UnitIsPVPSanctuary", &Script_UnitIsPVPSanctuary }, + { "UnitIsPVPFreeForAll", &Script_UnitIsPVPFreeForAll }, + { "UnitFactionGroup", &Script_UnitFactionGroup }, + { "UnitReaction", &Script_UnitReaction }, + { "UnitIsEnemy", &Script_UnitIsEnemy }, + { "UnitIsFriend", &Script_UnitIsFriend }, + { "UnitCanCooperate", &Script_UnitCanCooperate }, + { "UnitCanAssist", &Script_UnitCanAssist }, + { "UnitCanAttack", &Script_UnitCanAttack }, + { "UnitIsCharmed", &Script_UnitIsCharmed }, + { "UnitIsPossessed", &Script_UnitIsPossessed }, + { "PlayerCanTeleport", &Script_PlayerCanTeleport }, + { "UnitClassification", &Script_UnitClassification }, + { "UnitSelectionColor", &Script_UnitSelectionColor }, + { "UnitGUID", &Script_UnitGUID }, + { "UnitName", &Script_UnitName }, + { "UnitPVPName", &Script_UnitPVPName }, + { "UnitXP", &Script_UnitXP }, + { "UnitXPMax", &Script_UnitXPMax }, + { "UnitHealth", &Script_UnitHealth }, + { "UnitHealthMax", &Script_UnitHealthMax }, + { "UnitMana", &Script_UnitMana }, + { "UnitManaMax", &Script_UnitManaMax }, + { "UnitPower", &Script_UnitPower }, + { "UnitPowerMax", &Script_UnitPowerMax }, + { "UnitPowerType", &Script_UnitPowerType }, + { "UnitOnTaxi", &Script_UnitOnTaxi }, + { "UnitIsFeignDeath", &Script_UnitIsFeignDeath }, + { "UnitIsDead", &Script_UnitIsDead }, + { "UnitIsGhost", &Script_UnitIsGhost }, + { "UnitIsDeadOrGhost", &Script_UnitIsDeadOrGhost }, + { "UnitIsConnected", &Script_UnitIsConnected }, + { "UnitAffectingCombat", &Script_UnitAffectingCombat }, + { "UnitSex", &Script_UnitSex }, + { "UnitLevel", &Script_UnitLevel }, + { "GetMoney", &Script_GetMoney }, + { "GetHonorCurrency", &Script_GetHonorCurrency }, + { "GetArenaCurrency", &Script_GetArenaCurrency }, + { "UnitRace", &Script_UnitRace }, + { "UnitClass", &Script_UnitClass }, + { "UnitClassBase", &Script_UnitClassBase }, + { "UnitResistance", &Script_UnitResistance }, + { "UnitStat", &Script_UnitStat }, + { "UnitAttackBothHands", &Script_UnitAttackBothHands }, + { "UnitDamage", &Script_UnitDamage }, + { "UnitRangedDamage", &Script_UnitRangedDamage }, + { "UnitRangedAttack", &Script_UnitRangedAttack }, + { "UnitAttackSpeed", &Script_UnitAttackSpeed }, + { "UnitAttackPower", &Script_UnitAttackPower }, + { "UnitRangedAttackPower", &Script_UnitRangedAttackPower }, + { "UnitDefense", &Script_UnitDefense }, + { "UnitArmor", &Script_UnitArmor }, + { "UnitCharacterPoints", &Script_UnitCharacterPoints }, + { "UnitBuff", &Script_UnitBuff }, + { "UnitDebuff", &Script_UnitDebuff }, + { "UnitAura", &Script_UnitAura }, + { "UnitIsTapped", &Script_UnitIsTapped }, + { "UnitIsTappedByPlayer", &Script_UnitIsTappedByPlayer }, + { "UnitIsTappedByAllThreatList", &Script_UnitIsTappedByAllThreatList }, + { "UnitIsTrivial", &Script_UnitIsTrivial }, + { "UnitHasRelicSlot", &Script_UnitHasRelicSlot }, + { "SetPortraitTexture", &Script_SetPortraitTexture }, + { "HasFullControl", &Script_HasFullControl }, + { "GetComboPoints", &Script_GetComboPoints }, + { "IsInGuild", &Script_IsInGuild }, + { "IsGuildLeader", &Script_IsGuildLeader }, + { "IsArenaTeamCaptain", &Script_IsArenaTeamCaptain }, + { "IsInArenaTeam", &Script_IsInArenaTeam }, + { "IsResting", &Script_IsResting }, + { "GetCombatRating", &Script_GetCombatRating }, + { "GetCombatRatingBonus", &Script_GetCombatRatingBonus }, + { "GetMaxCombatRatingBonus", &Script_GetMaxCombatRatingBonus }, + { "GetDodgeChance", &Script_GetDodgeChance }, + { "GetBlockChance", &Script_GetBlockChance }, + { "GetShieldBlock", &Script_GetShieldBlock }, + { "GetParryChance", &Script_GetParryChance }, + { "GetCritChanceFromAgility", &Script_GetCritChanceFromAgility }, + { "GetSpellCritChanceFromIntellect", &Script_GetSpellCritChanceFromIntellect }, + { "GetCritChance", &Script_GetCritChance }, + { "GetRangedCritChance", &Script_GetRangedCritChance }, + { "GetSpellCritChance", &Script_GetSpellCritChance }, + { "GetSpellBonusDamage", &Script_GetSpellBonusDamage }, + { "GetSpellBonusHealing", &Script_GetSpellBonusHealing }, + { "GetPetSpellBonusDamage", &Script_GetPetSpellBonusDamage }, + { "GetSpellPenetration", &Script_GetSpellPenetration }, + { "GetArmorPenetration", &Script_GetArmorPenetration }, + { "GetAttackPowerForStat", &Script_GetAttackPowerForStat }, + { "UnitCreatureType", &Script_UnitCreatureType }, + { "UnitCreatureFamily", &Script_UnitCreatureFamily }, + { "GetResSicknessDuration", &Script_GetResSicknessDuration }, + { "GetPVPSessionStats", &Script_GetPVPSessionStats }, + { "GetPVPYesterdayStats", &Script_GetPVPYesterdayStats }, + { "GetPVPLifetimeStats", &Script_GetPVPLifetimeStats }, + { "UnitPVPRank", &Script_UnitPVPRank }, + { "GetPVPRankInfo", &Script_GetPVPRankInfo }, + { "GetPVPRankProgress", &Script_GetPVPRankProgress }, + { "UnitCastingInfo", &Script_UnitCastingInfo }, + { "UnitChannelInfo", &Script_UnitChannelInfo }, + { "IsLoggedIn", &Script_IsLoggedIn }, + { "IsFlyableArea", &Script_IsFlyableArea }, + { "IsIndoors", &Script_IsIndoors }, + { "IsOutdoors", &Script_IsOutdoors }, + { "IsOutOfBounds", &Script_IsOutOfBounds }, + { "IsFalling", &Script_IsFalling }, + { "IsSwimming", &Script_IsSwimming }, + { "IsFlying", &Script_IsFlying }, + { "IsMounted", &Script_IsMounted }, + { "IsStealthed", &Script_IsStealthed }, + { "UnitIsSameServer", &Script_UnitIsSameServer }, + { "GetUnitHealthModifier", &Script_GetUnitHealthModifier }, + { "GetUnitMaxHealthModifier", &Script_GetUnitMaxHealthModifier }, + { "GetUnitPowerModifier", &Script_GetUnitPowerModifier }, + { "GetUnitHealthRegenRateFromSpirit", &Script_GetUnitHealthRegenRateFromSpirit }, + { "GetUnitManaRegenRateFromSpirit", &Script_GetUnitManaRegenRateFromSpirit }, + { "GetManaRegen", &Script_GetManaRegen }, + { "GetPowerRegen", &Script_GetPowerRegen }, + { "GetRuneCooldown", &Script_GetRuneCooldown }, + { "GetRuneCount", &Script_GetRuneCount }, + { "GetRuneType", &Script_GetRuneType }, + { "ReportPlayerIsPVPAFK", &Script_ReportPlayerIsPVPAFK }, + { "PlayerIsPVPInactive", &Script_PlayerIsPVPInactive }, + { "GetExpertise", &Script_GetExpertise }, + { "GetExpertisePercent", &Script_GetExpertisePercent }, + { "UnitInBattleground", &Script_UnitInBattleground }, + { "UnitInRange", &Script_UnitInRange }, + { "GetUnitSpeed", &Script_GetUnitSpeed }, + { "GetUnitPitch", &Script_GetUnitPitch }, + { "UnitInVehicle", &Script_UnitInVehicle }, + { "UnitUsingVehicle", &Script_UnitUsingVehicle }, + { "UnitControllingVehicle", &Script_UnitControllingVehicle }, + { "UnitInVehicleControlSeat", &Script_UnitInVehicleControlSeat }, + { "UnitHasVehicleUI", &Script_UnitHasVehicleUI }, + { "UnitTargetsVehicleInRaidUI", &Script_UnitTargetsVehicleInRaidUI }, + { "UnitVehicleSkin", &Script_UnitVehicleSkin }, + { "UnitVehicleSeatCount", &Script_UnitVehicleSeatCount }, + { "UnitVehicleSeatInfo", &Script_UnitVehicleSeatInfo }, + { "UnitSwitchToVehicleSeat", &Script_UnitSwitchToVehicleSeat }, + { "CanSwitchVehicleSeat", &Script_CanSwitchVehicleSeat }, + { "GetVehicleUIIndicator", &Script_GetVehicleUIIndicator }, + { "GetVehicleUIIndicatorSeat", &Script_GetVehicleUIIndicatorSeat }, + { "UnitThreatSituation", &Script_UnitThreatSituation }, + { "UnitDetailedThreatSituation", &Script_UnitDetailedThreatSituation }, + { "UnitIsControlling", &Script_UnitIsControlling }, + { "EjectPassengerFromSeat", &Script_EjectPassengerFromSeat }, + { "CanEjectPassengerFromSeat", &Script_CanEjectPassengerFromSeat }, + { "RespondInstanceLock", &Script_RespondInstanceLock }, + { "GetPlayerFacing", &Script_GetPlayerFacing }, + { "GetPlayerInfoByGUID", &Script_GetPlayerInfoByGUID }, + { "GetItemStats", &Script_GetItemStats }, + { "GetItemStatDelta", &Script_GetItemStatDelta }, + { "IsXPUserDisabled", &Script_IsXPUserDisabled }, + { "FillLocalizedClassList", &Script_FillLocalizedClassList }, +}; + +void ScriptEventsRegisterFunctions() { + SystemRegisterFunctions(); + + for (auto& func : s_UnitFunctions) { + FrameScript_RegisterFunction(func.name, func.method); + } +} diff --git a/src/ui/game/ScriptEvents.hpp b/src/ui/game/ScriptEvents.hpp new file mode 100644 index 0000000..8240bc3 --- /dev/null +++ b/src/ui/game/ScriptEvents.hpp @@ -0,0 +1,6 @@ +#ifndef UI_GAME_SCRIPT_EVENTS_HPP +#define UI_GAME_SCRIPT_EVENTS_HPP + +void ScriptEventsRegisterFunctions(); + +#endif From cbbf491620b52954eecfd13b5b438ad5b092598d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 26 Jan 2026 12:24:17 -0600 Subject: [PATCH 082/269] chore(ui): clean up SystemRegisterFunctions --- src/glue/CGlueMgr.cpp | 1 + src/ui/ScriptFunctions.cpp | 9 --------- src/ui/ScriptFunctions.hpp | 4 ---- src/ui/ScriptFunctionsSystem.cpp | 14 +++++++++++--- src/ui/ScriptFunctionsSystem.hpp | 6 ++++++ src/ui/game/ScriptEvents.cpp | 3 +-- 6 files changed, 19 insertions(+), 18 deletions(-) create mode 100644 src/ui/ScriptFunctionsSystem.hpp diff --git a/src/glue/CGlueMgr.cpp b/src/glue/CGlueMgr.cpp index 90fae26..fa46eed 100644 --- a/src/glue/CGlueMgr.cpp +++ b/src/glue/CGlueMgr.cpp @@ -27,6 +27,7 @@ #include "ui/Interface.hpp" #include "ui/Key.hpp" #include "ui/ScriptFunctions.hpp" +#include "ui/ScriptFunctionsSystem.hpp" #include "ui/game/CGVideoOptions.hpp" #include "ui/simple/CSimpleModelFFX.hpp" #include "ui/simple/CSimpleTop.hpp" diff --git a/src/ui/ScriptFunctions.cpp b/src/ui/ScriptFunctions.cpp index 977956f..e1a7943 100644 --- a/src/ui/ScriptFunctions.cpp +++ b/src/ui/ScriptFunctions.cpp @@ -54,12 +54,3 @@ void RegisterSimpleFrameScriptMethods() { // CSimpleColorSelect::CreateScriptMetaTable(); // CSimpleMovieFrame::CreateScriptMetaTable(); } - -void SystemRegisterFunctions() { - for (int32_t i = 0; i < NUM_SCRIPT_FUNCTIONS_SYSTEM; ++i) { - FrameScript_RegisterFunction( - FrameScript::s_ScriptFunctions_System[i].name, - FrameScript::s_ScriptFunctions_System[i].method - ); - } -} diff --git a/src/ui/ScriptFunctions.hpp b/src/ui/ScriptFunctions.hpp index bfbce2b..fc0853e 100644 --- a/src/ui/ScriptFunctions.hpp +++ b/src/ui/ScriptFunctions.hpp @@ -7,15 +7,11 @@ struct lua_State; #define NUM_SCRIPT_FUNCTIONS_SIMPLE_FRAME 7 -#define NUM_SCRIPT_FUNCTIONS_SYSTEM 7 namespace FrameScript { extern FrameScript_Method s_ScriptFunctions_SimpleFrame[NUM_SCRIPT_FUNCTIONS_SIMPLE_FRAME]; - extern FrameScript_Method s_ScriptFunctions_System[NUM_SCRIPT_FUNCTIONS_SYSTEM]; } void RegisterSimpleFrameScriptMethods(); -void SystemRegisterFunctions(); - #endif diff --git a/src/ui/ScriptFunctionsSystem.cpp b/src/ui/ScriptFunctionsSystem.cpp index f0fa93e..a1f04e4 100644 --- a/src/ui/ScriptFunctionsSystem.cpp +++ b/src/ui/ScriptFunctionsSystem.cpp @@ -1,4 +1,4 @@ -#include "ui/ScriptFunctions.hpp" +#include "ui/FrameScript.hpp" #include "ui/ScriptFunctionsShared.hpp" #include "ui/Types.hpp" #include "util/Lua.hpp" @@ -22,10 +22,12 @@ int32_t Script_ConsoleExec(lua_State* L) { } int32_t Script_AccessDenied(lua_State* L) { - return luaL_error(L, "Access Denied"); + luaL_error(L, "Access Denied"); + + return 0; } -FrameScript_Method FrameScript::s_ScriptFunctions_System[NUM_SCRIPT_FUNCTIONS_SYSTEM] = { +static FrameScript_Method s_SystemFunctions[] = { { "GetTime", &Script_GetTime }, { "GetGameTime", &Script_GetGameTime }, { "ConsoleExec", &Script_ConsoleExec }, @@ -34,3 +36,9 @@ FrameScript_Method FrameScript::s_ScriptFunctions_System[NUM_SCRIPT_FUNCTIONS_SY { "AppendToFile", &Script_AccessDenied }, { "GetAccountExpansionLevel", &Script_GetAccountExpansionLevel } }; + +void SystemRegisterFunctions() { + for (auto& func : s_SystemFunctions) { + FrameScript_RegisterFunction(func.name, func.method); + } +} diff --git a/src/ui/ScriptFunctionsSystem.hpp b/src/ui/ScriptFunctionsSystem.hpp new file mode 100644 index 0000000..15fd17d --- /dev/null +++ b/src/ui/ScriptFunctionsSystem.hpp @@ -0,0 +1,6 @@ +#ifndef UI_SCRIPT_FUNCTIONS_SYSTEM_HPP +#define UI_SCRIPT_FUNCTIONS_SYSTEM_HPP + +void SystemRegisterFunctions(); + +#endif diff --git a/src/ui/game/ScriptEvents.cpp b/src/ui/game/ScriptEvents.cpp index 33419f3..258413b 100644 --- a/src/ui/game/ScriptEvents.cpp +++ b/src/ui/game/ScriptEvents.cpp @@ -1,7 +1,6 @@ #include "ui/game/ScriptEvents.hpp" #include "ui/FrameScript.hpp" -#include "ui/ScriptFunctions.hpp" -#include "ui/ScriptFunctionsShared.hpp" +#include "ui/ScriptFunctionsSystem.hpp" #include "util/Unimplemented.hpp" int32_t Script_UnitExists(lua_State* L) { From dc071210cabf494c8ae22583a0cc298ae79e07e4 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 26 Jan 2026 15:54:06 -0600 Subject: [PATCH 083/269] chore(ui): clean up RegisterSimpleFrameScriptMethods --- src/glue/CGlueMgr.cpp | 2 +- src/ui/ScriptFunctions.cpp | 56 ------------------- src/ui/ScriptFunctions.hpp | 17 ------ src/ui/ScriptFunctionsShared.cpp | 2 +- .../ScriptMethods.cpp} | 56 ++++++++++++++++++- src/ui/simple/ScriptMethods.hpp | 6 ++ 6 files changed, 61 insertions(+), 78 deletions(-) delete mode 100644 src/ui/ScriptFunctions.cpp delete mode 100644 src/ui/ScriptFunctions.hpp rename src/ui/{ScriptFunctionsSimpleFrame.cpp => simple/ScriptMethods.cpp} (68%) create mode 100644 src/ui/simple/ScriptMethods.hpp diff --git a/src/glue/CGlueMgr.cpp b/src/glue/CGlueMgr.cpp index fa46eed..e19ad25 100644 --- a/src/glue/CGlueMgr.cpp +++ b/src/glue/CGlueMgr.cpp @@ -26,11 +26,11 @@ #include "ui/FrameXML.hpp" #include "ui/Interface.hpp" #include "ui/Key.hpp" -#include "ui/ScriptFunctions.hpp" #include "ui/ScriptFunctionsSystem.hpp" #include "ui/game/CGVideoOptions.hpp" #include "ui/simple/CSimpleModelFFX.hpp" #include "ui/simple/CSimpleTop.hpp" +#include "ui/simple/ScriptMethods.hpp" #include "util/Filesystem.hpp" #include "util/Locale.hpp" #include "util/Log.hpp" diff --git a/src/ui/ScriptFunctions.cpp b/src/ui/ScriptFunctions.cpp deleted file mode 100644 index e1a7943..0000000 --- a/src/ui/ScriptFunctions.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "ui/ScriptFunctions.hpp" -#include "ui/FrameScript.hpp" -#include "ui/simple/CSimpleButton.hpp" -#include "ui/simple/CSimpleCheckbox.hpp" -#include "ui/simple/CSimpleEditBox.hpp" -#include "ui/simple/CSimpleFont.hpp" -#include "ui/simple/CSimpleFontString.hpp" -#include "ui/simple/CSimpleFrame.hpp" -#include "ui/simple/CSimpleHTML.hpp" -#include "ui/simple/CSimpleModel.hpp" -#include "ui/simple/CSimpleModelFFX.hpp" -#include "ui/simple/CSimpleScrollFrame.hpp" -#include "ui/simple/CSimpleSlider.hpp" -#include "ui/simple/CSimpleTexture.hpp" - -void RegisterSimpleFrameScriptMethods() { - for (int32_t i = 0; i < NUM_SCRIPT_FUNCTIONS_SIMPLE_FRAME; ++i) { - FrameScript_RegisterFunction( - FrameScript::s_ScriptFunctions_SimpleFrame[i].name, - FrameScript::s_ScriptFunctions_SimpleFrame[i].method - ); - } - - // TODO - // CSimpleAnim::CreateScriptMetaTable(); - // CSimpleTranslationAnim::CreateScriptMetaTable(); - // CSimpleRotationAnim::CreateScriptMetaTable(); - // CSimpleScaleAnim::CreateScriptMetaTable(); - // CSimpleControlPoint::CreateScriptMetaTable(); - // CSimplePathAnim::CreateScriptMetaTable(); - // CSimpleAlphaAnim::CreateScriptMetaTable(); - // CSimpleAnimGroup::CreateScriptMetaTable(); - - CSimpleFont::CreateScriptMetaTable(); - CSimpleTexture::CreateScriptMetaTable(); - CSimpleFontString::CreateScriptMetaTable(); - CSimpleFrame::CreateScriptMetaTable(); - CSimpleButton::CreateScriptMetaTable(); - CSimpleCheckbox::CreateScriptMetaTable(); - CSimpleEditBox::CreateScriptMetaTable(); - CSimpleHTML::CreateScriptMetaTable(); - - // TODO - // CSimpleMessageFrame::CreateScriptMetaTable(); - // CSimpleMessageScrollFrame::CreateScriptMetaTable(); - - CSimpleModel::CreateScriptMetaTable(); - CSimpleModelFFX::CreateScriptMetaTable(); - CSimpleScrollFrame::CreateScriptMetaTable(); - CSimpleSlider::CreateScriptMetaTable(); - - // TODO - // CSimpleStatusBar::CreateScriptMetaTable(); - // CSimpleColorSelect::CreateScriptMetaTable(); - // CSimpleMovieFrame::CreateScriptMetaTable(); -} diff --git a/src/ui/ScriptFunctions.hpp b/src/ui/ScriptFunctions.hpp deleted file mode 100644 index fc0853e..0000000 --- a/src/ui/ScriptFunctions.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef UI_SCRIPT_FUNCTIONS_HPP -#define UI_SCRIPT_FUNCTIONS_HPP - -#include "ui/Types.hpp" -#include - -struct lua_State; - -#define NUM_SCRIPT_FUNCTIONS_SIMPLE_FRAME 7 - -namespace FrameScript { - extern FrameScript_Method s_ScriptFunctions_SimpleFrame[NUM_SCRIPT_FUNCTIONS_SIMPLE_FRAME]; -} - -void RegisterSimpleFrameScriptMethods(); - -#endif diff --git a/src/ui/ScriptFunctionsShared.cpp b/src/ui/ScriptFunctionsShared.cpp index 96a9700..5ffb059 100644 --- a/src/ui/ScriptFunctionsShared.cpp +++ b/src/ui/ScriptFunctionsShared.cpp @@ -1,4 +1,4 @@ -#include "ui/ScriptFunctions.hpp" +#include "ui/ScriptFunctionsShared.hpp" #include "util/Lua.hpp" #include "util/Unimplemented.hpp" #include diff --git a/src/ui/ScriptFunctionsSimpleFrame.cpp b/src/ui/simple/ScriptMethods.cpp similarity index 68% rename from src/ui/ScriptFunctionsSimpleFrame.cpp rename to src/ui/simple/ScriptMethods.cpp index cf2e6c4..c27b5d7 100644 --- a/src/ui/ScriptFunctionsSimpleFrame.cpp +++ b/src/ui/simple/ScriptMethods.cpp @@ -1,13 +1,24 @@ +#include "ui/simple/ScriptMethods.hpp" #include "ui/FrameXML.hpp" -#include "ui/ScriptFunctions.hpp" #include "ui/Types.hpp" +#include "ui/simple/CSimpleButton.hpp" +#include "ui/simple/CSimpleCheckbox.hpp" +#include "ui/simple/CSimpleEditBox.hpp" +#include "ui/simple/CSimpleFont.hpp" +#include "ui/simple/CSimpleFontString.hpp" #include "ui/simple/CSimpleFrame.hpp" +#include "ui/simple/CSimpleHTML.hpp" +#include "ui/simple/CSimpleModel.hpp" +#include "ui/simple/CSimpleModelFFX.hpp" +#include "ui/simple/CSimpleScrollFrame.hpp" +#include "ui/simple/CSimpleSlider.hpp" +#include "ui/simple/CSimpleTexture.hpp" #include "util/CStatus.hpp" #include "util/Lua.hpp" #include "util/Unimplemented.hpp" #include -#include #include +#include int32_t Script_GetText(lua_State* L) { WHOA_UNIMPLEMENTED(0); @@ -137,7 +148,7 @@ int32_t Script_GetCurrentKeyBoardFocus(lua_State* L) { WHOA_UNIMPLEMENTED(0); } -FrameScript_Method FrameScript::s_ScriptFunctions_SimpleFrame[NUM_SCRIPT_FUNCTIONS_SIMPLE_FRAME] = { +static FrameScript_Method s_ScriptFunctions[] = { { "GetText", &Script_GetText }, { "GetNumFrames", &Script_GetNumFrames }, { "EnumerateFrames", &Script_EnumerateFrames }, @@ -146,3 +157,42 @@ FrameScript_Method FrameScript::s_ScriptFunctions_SimpleFrame[NUM_SCRIPT_FUNCTIO { "GetFramesRegisteredForEvent", &Script_GetFramesRegisteredForEvent }, { "GetCurrentKeyBoardFocus", &Script_GetCurrentKeyBoardFocus }, }; + +void RegisterSimpleFrameScriptMethods() { + for (auto& func : s_ScriptFunctions) { + FrameScript_RegisterFunction(func.name, func.method); + } + + // TODO + // CSimpleAnim::CreateScriptMetaTable(); + // CSimpleTranslationAnim::CreateScriptMetaTable(); + // CSimpleRotationAnim::CreateScriptMetaTable(); + // CSimpleScaleAnim::CreateScriptMetaTable(); + // CSimpleControlPoint::CreateScriptMetaTable(); + // CSimplePathAnim::CreateScriptMetaTable(); + // CSimpleAlphaAnim::CreateScriptMetaTable(); + // CSimpleAnimGroup::CreateScriptMetaTable(); + + CSimpleFont::CreateScriptMetaTable(); + CSimpleTexture::CreateScriptMetaTable(); + CSimpleFontString::CreateScriptMetaTable(); + CSimpleFrame::CreateScriptMetaTable(); + CSimpleButton::CreateScriptMetaTable(); + CSimpleCheckbox::CreateScriptMetaTable(); + CSimpleEditBox::CreateScriptMetaTable(); + CSimpleHTML::CreateScriptMetaTable(); + + // TODO + // CSimpleMessageFrame::CreateScriptMetaTable(); + // CSimpleMessageScrollFrame::CreateScriptMetaTable(); + + CSimpleModel::CreateScriptMetaTable(); + CSimpleModelFFX::CreateScriptMetaTable(); + CSimpleScrollFrame::CreateScriptMetaTable(); + CSimpleSlider::CreateScriptMetaTable(); + + // TODO + // CSimpleStatusBar::CreateScriptMetaTable(); + // CSimpleColorSelect::CreateScriptMetaTable(); + // CSimpleMovieFrame::CreateScriptMetaTable(); +} diff --git a/src/ui/simple/ScriptMethods.hpp b/src/ui/simple/ScriptMethods.hpp new file mode 100644 index 0000000..5d1e0e5 --- /dev/null +++ b/src/ui/simple/ScriptMethods.hpp @@ -0,0 +1,6 @@ +#ifndef UI_SIMPLE_SCRIPT_METHODS_HPP +#define UI_SIMPLE_SCRIPT_METHODS_HPP + +void RegisterSimpleFrameScriptMethods(); + +#endif From 6dd15ed2cf39162db052430f030ed191a441909c Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 26 Jan 2026 16:35:15 -0600 Subject: [PATCH 084/269] feat(ui): add FrameScript_UnregisterFunction --- src/ui/FrameScript.cpp | 9 +++++++++ src/ui/FrameScript.hpp | 2 ++ 2 files changed, 11 insertions(+) diff --git a/src/ui/FrameScript.cpp b/src/ui/FrameScript.cpp index 0bdc56d..2945dcc 100644 --- a/src/ui/FrameScript.cpp +++ b/src/ui/FrameScript.cpp @@ -1047,6 +1047,15 @@ const char* FrameScript_Sprintf(lua_State* L, int32_t idx, char buffer[], uint32 return buffer; } +void FrameScript_UnregisterFunction(char const* name) { + auto L = FrameScript::s_context; + + lua_pushnil(L); + lua_pushstring(L, name); + lua_insert(L, -2); + lua_rawset(L, LUA_GLOBALSINDEX); +} + void FrameScript_UnregisterScriptEvent(FrameScript_Object* object, FrameScript_EventObject* event) { if (event->pendingSignalCount) { auto node = event->unregisterListeners.Head(); diff --git a/src/ui/FrameScript.hpp b/src/ui/FrameScript.hpp index 8685e26..c84f30a 100644 --- a/src/ui/FrameScript.hpp +++ b/src/ui/FrameScript.hpp @@ -99,6 +99,8 @@ void FrameScript_SignalEvent(uint32_t index, const char* format, ...); const char* FrameScript_Sprintf(lua_State* L, int32_t idx, char buffer[], uint32_t bufferLen); +void FrameScript_UnregisterFunction(char const* name); + void FrameScript_UnregisterScriptEvent(FrameScript_Object* object, FrameScript_EventObject* event); void ScriptEventsInitialize(); From c0ec4aed44f9fa64be607bcb039b36313ef33391 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 26 Jan 2026 16:36:15 -0600 Subject: [PATCH 085/269] chore(ui): tweak style --- src/ui/FrameScript.cpp | 2 +- src/ui/FrameScript.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/FrameScript.cpp b/src/ui/FrameScript.cpp index 2945dcc..4ab2053 100644 --- a/src/ui/FrameScript.cpp +++ b/src/ui/FrameScript.cpp @@ -1047,7 +1047,7 @@ const char* FrameScript_Sprintf(lua_State* L, int32_t idx, char buffer[], uint32 return buffer; } -void FrameScript_UnregisterFunction(char const* name) { +void FrameScript_UnregisterFunction(const char* name) { auto L = FrameScript::s_context; lua_pushnil(L); diff --git a/src/ui/FrameScript.hpp b/src/ui/FrameScript.hpp index c84f30a..e2e4c83 100644 --- a/src/ui/FrameScript.hpp +++ b/src/ui/FrameScript.hpp @@ -99,7 +99,7 @@ void FrameScript_SignalEvent(uint32_t index, const char* format, ...); const char* FrameScript_Sprintf(lua_State* L, int32_t idx, char buffer[], uint32_t bufferLen); -void FrameScript_UnregisterFunction(char const* name); +void FrameScript_UnregisterFunction(const char* name); void FrameScript_UnregisterScriptEvent(FrameScript_Object* object, FrameScript_EventObject* event); From 95a8f4287f4576069303459ed195638a3616e419 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 26 Jan 2026 16:37:50 -0600 Subject: [PATCH 086/269] feat(ui): add SystemUnregisterFunctions --- src/ui/ScriptFunctionsSystem.cpp | 6 ++++++ src/ui/ScriptFunctionsSystem.hpp | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/ui/ScriptFunctionsSystem.cpp b/src/ui/ScriptFunctionsSystem.cpp index a1f04e4..72c13dd 100644 --- a/src/ui/ScriptFunctionsSystem.cpp +++ b/src/ui/ScriptFunctionsSystem.cpp @@ -42,3 +42,9 @@ void SystemRegisterFunctions() { FrameScript_RegisterFunction(func.name, func.method); } } + +void SystemUnregisterFunctions() { + for (auto& func : s_SystemFunctions) { + FrameScript_UnregisterFunction(func.name); + } +} diff --git a/src/ui/ScriptFunctionsSystem.hpp b/src/ui/ScriptFunctionsSystem.hpp index 15fd17d..67581e6 100644 --- a/src/ui/ScriptFunctionsSystem.hpp +++ b/src/ui/ScriptFunctionsSystem.hpp @@ -3,4 +3,6 @@ void SystemRegisterFunctions(); +void SystemUnregisterFunctions(); + #endif From a168c6fd41a06a6b80e3788f478fc20e7c4847cc Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 26 Jan 2026 16:41:13 -0600 Subject: [PATCH 087/269] feat(glue): unregister system functions in CGlueMgr::Suspend --- src/glue/CGlueMgr.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/glue/CGlueMgr.cpp b/src/glue/CGlueMgr.cpp index e19ad25..6a21ac4 100644 --- a/src/glue/CGlueMgr.cpp +++ b/src/glue/CGlueMgr.cpp @@ -1187,6 +1187,10 @@ void CGlueMgr::Suspend() { // TODO + SystemUnregisterFunctions(); + + // TODO + FrameXML_FreeHashNodes(); // TODO From 61b05eb3664b1c8427aba8f1f05b3dabf987c08d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 26 Jan 2026 21:11:36 -0600 Subject: [PATCH 088/269] feat(ui): add GMTicketInfoRegisterScriptFunctions --- src/ui/game/CGGameUI.cpp | 5 ++ src/ui/game/GMTicketInfoScript.cpp | 87 ++++++++++++++++++++++++++++++ src/ui/game/GMTicketInfoScript.hpp | 6 +++ 3 files changed, 98 insertions(+) create mode 100644 src/ui/game/GMTicketInfoScript.cpp create mode 100644 src/ui/game/GMTicketInfoScript.hpp diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 4e6277a..852e9e4 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -3,6 +3,7 @@ #include "ui/FrameXML.hpp" #include "ui/Key.hpp" #include "ui/game/CGWorldFrame.hpp" +#include "ui/game/GMTicketInfoScript.hpp" #include "ui/game/ScriptEvents.hpp" #include "ui/simple/CSimpleTop.hpp" #include "util/CStatus.hpp" @@ -16,6 +17,10 @@ void LoadScriptFunctions() { ScriptEventsRegisterFunctions(); // TODO + + GMTicketInfoRegisterScriptFunctions(); + + // TODO } void CGGameUI::Initialize() { diff --git a/src/ui/game/GMTicketInfoScript.cpp b/src/ui/game/GMTicketInfoScript.cpp new file mode 100644 index 0000000..302a150 --- /dev/null +++ b/src/ui/game/GMTicketInfoScript.cpp @@ -0,0 +1,87 @@ +#include "ui/game/GMTicketInfoScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Unimplemented.hpp" + +int32_t Script_GetGMTicket(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_NewGMTicket(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UpdateGMTicket(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DeleteGMTicket(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GMResponseNeedMoreHelp(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GMResponseResolve(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetGMStatus(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GMSurveyQuestion(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GMSurveyNumAnswers(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GMSurveyAnswer(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GMSurveyAnswerSubmit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GMSurveyCommentSubmit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GMSurveySubmit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GMReportLag(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RegisterStaticConstants(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +static FrameScript_Method s_ScriptFunctions[] = { + { "GetGMTicket", &Script_GetGMTicket }, + { "NewGMTicket", &Script_NewGMTicket }, + { "UpdateGMTicket", &Script_UpdateGMTicket }, + { "DeleteGMTicket", &Script_DeleteGMTicket }, + { "GMResponseNeedMoreHelp", &Script_GMResponseNeedMoreHelp }, + { "GMResponseResolve", &Script_GMResponseResolve }, + { "GetGMStatus", &Script_GetGMStatus }, + { "GMSurveyQuestion", &Script_GMSurveyQuestion }, + { "GMSurveyNumAnswers", &Script_GMSurveyNumAnswers }, + { "GMSurveyAnswer", &Script_GMSurveyAnswer }, + { "GMSurveyAnswerSubmit", &Script_GMSurveyAnswerSubmit }, + { "GMSurveyCommentSubmit", &Script_GMSurveyCommentSubmit }, + { "GMSurveySubmit", &Script_GMSurveySubmit }, + { "GMReportLag", &Script_GMReportLag }, + { "RegisterStaticConstants", &Script_RegisterStaticConstants }, +}; + +void GMTicketInfoRegisterScriptFunctions() { + for (auto& func : s_ScriptFunctions) { + FrameScript_RegisterFunction(func.name, func.method); + } +} diff --git a/src/ui/game/GMTicketInfoScript.hpp b/src/ui/game/GMTicketInfoScript.hpp new file mode 100644 index 0000000..1a0c64f --- /dev/null +++ b/src/ui/game/GMTicketInfoScript.hpp @@ -0,0 +1,6 @@ +#ifndef UI_GAME_GM_TICKET_INFO_SCRIPT_HPP +#define UI_GAME_GM_TICKET_INFO_SCRIPT_HPP + +void GMTicketInfoRegisterScriptFunctions(); + +#endif From bc1d7cbd663ff628703b306fb67a296999015fe2 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 05:28:39 -0600 Subject: [PATCH 089/269] feat(ui): add GameScriptRegisterFunctions --- src/glue/GlueScript.cpp | 30 - src/ui/ScriptFunctionsShared.cpp | 30 + src/ui/ScriptFunctionsShared.hpp | 6 + src/ui/game/CGGameUI.cpp | 5 + src/ui/game/GameScript.cpp | 1554 ++++++++++++++++++++++++++++++ src/ui/game/GameScript.hpp | 6 + 6 files changed, 1601 insertions(+), 30 deletions(-) create mode 100644 src/ui/game/GameScript.cpp create mode 100644 src/ui/game/GameScript.hpp diff --git a/src/glue/GlueScript.cpp b/src/glue/GlueScript.cpp index 1730888..1e8cd23 100644 --- a/src/glue/GlueScript.cpp +++ b/src/glue/GlueScript.cpp @@ -522,36 +522,6 @@ int32_t Script_IsScanDLLFinished(lua_State* L) { return 1; } -int32_t Script_IsWindowsClient(lua_State* L) { -#if defined(WHOA_SYSTEM_WIN) - lua_pushnumber(L, 1.0); -#else - lua_pushnil(L); -#endif - - return 1; -} - -int32_t Script_IsMacClient(lua_State* L) { -#if defined(WHOA_SYSTEM_MAC) - lua_pushnumber(L, 1.0); -#else - lua_pushnil(L); -#endif - - return 1; -} - -int32_t Script_IsLinuxClient(lua_State* L) { -#if defined(WHOA_SYSTEM_LINUX) - lua_pushnumber(L, 1.0); -#else - lua_pushnil(L); -#endif - - return 1; -} - int32_t Script_SetRealmSplitState(lua_State* L) { WHOA_UNIMPLEMENTED(0); } diff --git a/src/ui/ScriptFunctionsShared.cpp b/src/ui/ScriptFunctionsShared.cpp index 5ffb059..c6e1289 100644 --- a/src/ui/ScriptFunctionsShared.cpp +++ b/src/ui/ScriptFunctionsShared.cpp @@ -6,3 +6,33 @@ int32_t Script_GetAccountExpansionLevel(lua_State* L) { WHOA_UNIMPLEMENTED(0); } + +int32_t Script_IsLinuxClient(lua_State* L) { +#if defined(WHOA_SYSTEM_LINUX) + lua_pushnumber(L, 1.0); +#else + lua_pushnil(L); +#endif + + return 1; +} + +int32_t Script_IsMacClient(lua_State* L) { +#if defined(WHOA_SYSTEM_MAC) + lua_pushnumber(L, 1.0); +#else + lua_pushnil(L); +#endif + + return 1; +} + +int32_t Script_IsWindowsClient(lua_State* L) { +#if defined(WHOA_SYSTEM_WIN) + lua_pushnumber(L, 1.0); +#else + lua_pushnil(L); +#endif + + return 1; +} diff --git a/src/ui/ScriptFunctionsShared.hpp b/src/ui/ScriptFunctionsShared.hpp index 04e196b..1c80788 100644 --- a/src/ui/ScriptFunctionsShared.hpp +++ b/src/ui/ScriptFunctionsShared.hpp @@ -6,4 +6,10 @@ int32_t Script_GetAccountExpansionLevel(lua_State* L); +int32_t Script_IsLinuxClient(lua_State* L); + +int32_t Script_IsMacClient(lua_State* L); + +int32_t Script_IsWindowsClient(lua_State* L); + #endif diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 852e9e4..0f527fd 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -4,6 +4,7 @@ #include "ui/Key.hpp" #include "ui/game/CGWorldFrame.hpp" #include "ui/game/GMTicketInfoScript.hpp" +#include "ui/game/GameScript.hpp" #include "ui/game/ScriptEvents.hpp" #include "ui/simple/CSimpleTop.hpp" #include "util/CStatus.hpp" @@ -14,6 +15,10 @@ CSimpleTop* CGGameUI::s_simpleTop; void LoadScriptFunctions() { // TODO + GameScriptRegisterFunctions(); + + // TODO + ScriptEventsRegisterFunctions(); // TODO diff --git a/src/ui/game/GameScript.cpp b/src/ui/game/GameScript.cpp new file mode 100644 index 0000000..bc194d8 --- /dev/null +++ b/src/ui/game/GameScript.cpp @@ -0,0 +1,1554 @@ +#include "ui/game/GameScript.hpp" +#include "ui/FrameScript.hpp" +#include "ui/ScriptFunctionsShared.hpp" +#include "util/Unimplemented.hpp" + +namespace { +int32_t Script_FrameXML_Debug(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBuildInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ReloadUI(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RegisterForSave(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RegisterForSavePerCharacter(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetLayoutMode(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsModifierKeyDown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsLeftShiftKeyDown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsRightShiftKeyDown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsShiftKeyDown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsLeftControlKeyDown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsRightControlKeyDown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsControlKeyDown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsLeftAltKeyDown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsRightAltKeyDown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsAltKeyDown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsMouseButtonDown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetMouseButtonName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetMouseButtonClicked(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetConsoleKey(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_Screenshot(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetFramerate(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TogglePerformanceDisplay(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TogglePerformancePause(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TogglePerformanceValues(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ResetPerformanceValues(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetDebugStats(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsDebugBuild(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RegisterCVar(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCVarInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetCVar(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCVar(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCVarBool(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCVarDefault(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCVarMin(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCVarMax(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCVarAbsoluteMin(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCVarAbsoluteMax(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetWaterDetail(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetWaterDetail(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetFarclip(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetFarclip(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetTexLodBias(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetTexLodBias(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetBaseMip(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBaseMip(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ToggleTris(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TogglePortals(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ToggleCollision(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ToggleCollisionDisplay(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TogglePlayerBounds(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_Stuck(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_Logout(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_Quit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetCursor(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ResetCursor(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ClearCursor(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CursorHasItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CursorHasSpell(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CursorHasMacro(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CursorHasMoney(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCursorInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_EquipCursorItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DeleteCursorItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_EquipPendingItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CancelPendingEquip(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetUnit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetNearest(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetNearestEnemy(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetNearestEnemyPlayer(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetNearestFriend(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetNearestFriendPlayer(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetNearestPartyMember(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetNearestRaidMember(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetDirectionEnemy(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetDirectionFriend(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetDirectionFinished(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetLastTarget(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetLastEnemy(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetLastFriend(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_AttackTarget(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_AssistUnit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_FocusUnit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_FollowUnit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_InteractUnit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ClearTarget(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ClearFocus(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_AutoEquipCursorItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ToggleSheath(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetZoneText(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetRealZoneText(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetSubZoneText(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetMinimapZoneText(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_InitiateTrade(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CanInspect(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_NotifyInspect(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_InviteUnit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UninviteUnit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RequestTimePlayed(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RepopMe(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_AcceptResurrect(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DeclineResurrect(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ResurrectGetOfferer(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ResurrectHasSickness(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ResurrectHasTimer(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BeginTrade(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CancelTrade(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_AcceptGroup(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DeclineGroup(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_AcceptGuild(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DeclineGuild(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_AcceptArenaTeam(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DeclineArenaTeam(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CancelLogout(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ForceLogout(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ForceQuit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCursorMoney(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DropCursorMoney(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_PickupPlayerMoney(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_HasSoulstone(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UseSoulstone(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_HasKey(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GuildInvite(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GuildUninvite(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GuildPromote(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GuildDemote(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GuildSetLeader(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GuildSetMOTD(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GuildLeave(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GuildDisband(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GuildInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ArenaTeamInviteByName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ArenaTeamLeave(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ArenaTeamUninviteByName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ArenaTeamSetLeaderByName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ArenaTeamDisband(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetScreenWidth(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetScreenHeight(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetDamageBonusStat(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetReleaseTimeRemaining(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCorpseRecoveryDelay(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInstanceBootTimeRemaining(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInstanceLockTimeRemaining(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInstanceLockTimeRemainingEncounter(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetSummonConfirmTimeLeft(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetSummonConfirmSummoner(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetSummonConfirmAreaName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ConfirmSummon(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CancelSummon(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCursorPosition(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetNetStats(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SitStandOrDescendStart(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_StopCinematic(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RunScript(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CheckInteractDistance(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RandomRoll(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_OpeningCinematic(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_InCinematic(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_AcceptXPLoss(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CheckSpiritHealerDist(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CheckTalentMasterDist(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CheckBinderDist(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RetrieveCorpse(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BindEnchant(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ReplaceEnchant(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ReplaceTradeEnchant(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_NotWhileDeadError(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetRestState(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetXPExhaustion(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetTimeToWellRested(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GMRequestPlayerInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCoinIcon(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCoinText(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCoinTextureString(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsSubZonePVPPOI(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetZonePVPInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TogglePVP(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetPVP(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPVPDesired(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPVPTimer(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsPVPTimerRunning(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ConfirmBindOnUse(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetPortraitToTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetLocale(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetGMTicketCategories(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DropItemOnUnit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RestartGx(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RestoreVideoResolutionDefaults(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RestoreVideoEffectsDefaults(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RestoreVideoStereoDefaults(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBindLocation(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ConfirmTalentWipe(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ConfirmBinder(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ShowingHelm(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ShowingCloak(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ShowHelm(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ShowCloak(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetEuropeanNumbers(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetAreaSpiritHealerTime(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_AcceptAreaSpiritHeal(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CancelAreaSpiritHeal(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetMouseFocus(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetRealmName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetItemQualityColor(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetItemInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetItemGem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetExtendedItemInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetItemIcon(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetItemFamily(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetItemCount(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetItemSpell(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetItemCooldown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_PickupItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsCurrentItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsUsableItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsHelpfulItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsHarmfulItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsConsumableItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsEquippableItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsEquippedItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsEquippedItemType(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsDressableItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ItemHasRange(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsItemInRange(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetNumAddOns(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetAddOnInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetAddOnMetadata(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UpdateAddOnMemoryUsage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetAddOnMemoryUsage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetScriptCPUUsage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UpdateAddOnCPUUsage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetAddOnCPUUsage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetFunctionCPUUsage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetFrameCPUUsage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetEventCPUUsage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ResetCPUUsage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetAddOnDependencies(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_EnableAddOn(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_EnableAllAddOns(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DisableAddOn(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DisableAllAddOns(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ResetDisabledAddOns(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsAddOnLoadOnDemand(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsAddOnLoaded(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_LoadAddOn(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_PartialPlayTime(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_NoPlayTime(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBillingTimeRested(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CanShowResetInstances(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ResetInstances(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsInInstance(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInstanceDifficulty(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInstanceInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetDungeonDifficulty(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetDungeonDifficulty(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetRaidDifficulty(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetRaidDifficulty(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ReportBug(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ReportSuggestion(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetMirrorTimerInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetMirrorTimerProgress(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetNumTitles(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCurrentTitle(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetCurrentTitle(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsTitleKnown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetTitleName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UseItemByName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_EquipItemByName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetExistingLocales(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_InCombatLockdown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_StartAttack(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_StopAttack(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetTaxiBenchmarkMode(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetTaxiBenchmarkMode(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_Dismount(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_VoicePushToTalkStart(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_VoicePushToTalkStop(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetUIVisibility(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsReferAFriendLinked(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CanGrantLevel(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GrantLevel(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CanSummonFriend(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SummonFriend(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetSummonFriendCooldown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetTotemInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetTotemTimeLeft(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TargetTotem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DestroyTotem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetNumDeclensionSets(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DeclineName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_AcceptLevelGrant(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DeclineLevelGrant(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UploadSettings(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DownloadSettings(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetMovieResolution(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GameMovieFinished(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsDesaturateSupported(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetThreatStatusColor(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsThreatWarningEnabled(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ConsoleAddMessage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetItemUniqueness(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_EndRefund(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_EndBoundTradeable(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CanMapChangeDifficulty(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetExpansionLevel(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetAllowLowLevelRaid(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetAllowLowLevelRaid(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +static FrameScript_Method s_ScriptFunctions[] = { + { "FrameXML_Debug", &Script_FrameXML_Debug }, + { "GetBuildInfo", &Script_GetBuildInfo }, + { "ReloadUI", &Script_ReloadUI }, + { "RegisterForSave", &Script_RegisterForSave }, + { "RegisterForSavePerCharacter", &Script_RegisterForSavePerCharacter }, + { "SetLayoutMode", &Script_SetLayoutMode }, + { "IsModifierKeyDown", &Script_IsModifierKeyDown }, + { "IsLeftShiftKeyDown", &Script_IsLeftShiftKeyDown }, + { "IsRightShiftKeyDown", &Script_IsRightShiftKeyDown }, + { "IsShiftKeyDown", &Script_IsShiftKeyDown }, + { "IsLeftControlKeyDown", &Script_IsLeftControlKeyDown }, + { "IsRightControlKeyDown", &Script_IsRightControlKeyDown }, + { "IsControlKeyDown", &Script_IsControlKeyDown }, + { "IsLeftAltKeyDown", &Script_IsLeftAltKeyDown }, + { "IsRightAltKeyDown", &Script_IsRightAltKeyDown }, + { "IsAltKeyDown", &Script_IsAltKeyDown }, + { "IsMouseButtonDown", &Script_IsMouseButtonDown }, + { "GetMouseButtonName", &Script_GetMouseButtonName }, + { "GetMouseButtonClicked", &Script_GetMouseButtonClicked }, + { "SetConsoleKey", &Script_SetConsoleKey }, + { "Screenshot", &Script_Screenshot }, + { "GetFramerate", &Script_GetFramerate }, + { "TogglePerformanceDisplay", &Script_TogglePerformanceDisplay }, + { "TogglePerformancePause", &Script_TogglePerformancePause }, + { "TogglePerformanceValues", &Script_TogglePerformanceValues }, + { "ResetPerformanceValues", &Script_ResetPerformanceValues }, + { "GetDebugStats", &Script_GetDebugStats }, + { "IsDebugBuild", &Script_IsDebugBuild }, + { "RegisterCVar", &Script_RegisterCVar }, + { "GetCVarInfo", &Script_GetCVarInfo }, + { "SetCVar", &Script_SetCVar }, + { "GetCVar", &Script_GetCVar }, + { "GetCVarBool", &Script_GetCVarBool }, + { "GetCVarDefault", &Script_GetCVarDefault }, + { "GetCVarMin", &Script_GetCVarMin }, + { "GetCVarMax", &Script_GetCVarMax }, + { "GetCVarAbsoluteMin", &Script_GetCVarAbsoluteMin }, + { "GetCVarAbsoluteMax", &Script_GetCVarAbsoluteMax }, + { "GetWaterDetail", &Script_GetWaterDetail }, + { "SetWaterDetail", &Script_SetWaterDetail }, + { "GetFarclip", &Script_GetFarclip }, + { "SetFarclip", &Script_SetFarclip }, + { "GetTexLodBias", &Script_GetTexLodBias }, + { "SetTexLodBias", &Script_SetTexLodBias }, + { "SetBaseMip", &Script_SetBaseMip }, + { "GetBaseMip", &Script_GetBaseMip }, + { "ToggleTris", &Script_ToggleTris }, + { "TogglePortals", &Script_TogglePortals }, + { "ToggleCollision", &Script_ToggleCollision }, + { "ToggleCollisionDisplay", &Script_ToggleCollisionDisplay }, + { "TogglePlayerBounds", &Script_TogglePlayerBounds }, + { "Stuck", &Script_Stuck }, + { "Logout", &Script_Logout }, + { "Quit", &Script_Quit }, + { "SetCursor", &Script_SetCursor }, + { "ResetCursor", &Script_ResetCursor }, + { "ClearCursor", &Script_ClearCursor }, + { "CursorHasItem", &Script_CursorHasItem }, + { "CursorHasSpell", &Script_CursorHasSpell }, + { "CursorHasMacro", &Script_CursorHasMacro }, + { "CursorHasMoney", &Script_CursorHasMoney }, + { "GetCursorInfo", &Script_GetCursorInfo }, + { "EquipCursorItem", &Script_EquipCursorItem }, + { "DeleteCursorItem", &Script_DeleteCursorItem }, + { "EquipPendingItem", &Script_EquipPendingItem }, + { "CancelPendingEquip", &Script_CancelPendingEquip }, + { "TargetUnit", &Script_TargetUnit }, + { "TargetNearest", &Script_TargetNearest }, + { "TargetNearestEnemy", &Script_TargetNearestEnemy }, + { "TargetNearestEnemyPlayer", &Script_TargetNearestEnemyPlayer }, + { "TargetNearestFriend", &Script_TargetNearestFriend }, + { "TargetNearestFriendPlayer", &Script_TargetNearestFriendPlayer }, + { "TargetNearestPartyMember", &Script_TargetNearestPartyMember }, + { "TargetNearestRaidMember", &Script_TargetNearestRaidMember }, + { "TargetDirectionEnemy", &Script_TargetDirectionEnemy }, + { "TargetDirectionFriend", &Script_TargetDirectionFriend }, + { "TargetDirectionFinished", &Script_TargetDirectionFinished }, + { "TargetLastTarget", &Script_TargetLastTarget }, + { "TargetLastEnemy", &Script_TargetLastEnemy }, + { "TargetLastFriend", &Script_TargetLastFriend }, + { "AttackTarget", &Script_AttackTarget }, + { "AssistUnit", &Script_AssistUnit }, + { "FocusUnit", &Script_FocusUnit }, + { "FollowUnit", &Script_FollowUnit }, + { "InteractUnit", &Script_InteractUnit }, + { "ClearTarget", &Script_ClearTarget }, + { "ClearFocus", &Script_ClearFocus }, + { "AutoEquipCursorItem", &Script_AutoEquipCursorItem }, + { "ToggleSheath", &Script_ToggleSheath }, + { "GetZoneText", &Script_GetZoneText }, + { "GetRealZoneText", &Script_GetRealZoneText }, + { "GetSubZoneText", &Script_GetSubZoneText }, + { "GetMinimapZoneText", &Script_GetMinimapZoneText }, + { "InitiateTrade", &Script_InitiateTrade }, + { "CanInspect", &Script_CanInspect }, + { "NotifyInspect", &Script_NotifyInspect }, + { "InviteUnit", &Script_InviteUnit }, + { "UninviteUnit", &Script_UninviteUnit }, + { "RequestTimePlayed", &Script_RequestTimePlayed }, + { "RepopMe", &Script_RepopMe }, + { "AcceptResurrect", &Script_AcceptResurrect }, + { "DeclineResurrect", &Script_DeclineResurrect }, + { "ResurrectGetOfferer", &Script_ResurrectGetOfferer }, + { "ResurrectHasSickness", &Script_ResurrectHasSickness }, + { "ResurrectHasTimer", &Script_ResurrectHasTimer }, + { "BeginTrade", &Script_BeginTrade }, + { "CancelTrade", &Script_CancelTrade }, + { "AcceptGroup", &Script_AcceptGroup }, + { "DeclineGroup", &Script_DeclineGroup }, + { "AcceptGuild", &Script_AcceptGuild }, + { "DeclineGuild", &Script_DeclineGuild }, + { "AcceptArenaTeam", &Script_AcceptArenaTeam }, + { "DeclineArenaTeam", &Script_DeclineArenaTeam }, + { "CancelLogout", &Script_CancelLogout }, + { "ForceLogout", &Script_ForceLogout }, + { "ForceQuit", &Script_ForceQuit }, + { "GetCursorMoney", &Script_GetCursorMoney }, + { "DropCursorMoney", &Script_DropCursorMoney }, + { "PickupPlayerMoney", &Script_PickupPlayerMoney }, + { "HasSoulstone", &Script_HasSoulstone }, + { "UseSoulstone", &Script_UseSoulstone }, + { "HasKey", &Script_HasKey }, + { "GuildInvite", &Script_GuildInvite }, + { "GuildUninvite", &Script_GuildUninvite }, + { "GuildPromote", &Script_GuildPromote }, + { "GuildDemote", &Script_GuildDemote }, + { "GuildSetLeader", &Script_GuildSetLeader }, + { "GuildSetMOTD", &Script_GuildSetMOTD }, + { "GuildLeave", &Script_GuildLeave }, + { "GuildDisband", &Script_GuildDisband }, + { "GuildInfo", &Script_GuildInfo }, + { "ArenaTeamInviteByName", &Script_ArenaTeamInviteByName }, + { "ArenaTeamLeave", &Script_ArenaTeamLeave }, + { "ArenaTeamUninviteByName", &Script_ArenaTeamUninviteByName }, + { "ArenaTeamSetLeaderByName", &Script_ArenaTeamSetLeaderByName }, + { "ArenaTeamDisband", &Script_ArenaTeamDisband }, + { "GetScreenWidth", &Script_GetScreenWidth }, + { "GetScreenHeight", &Script_GetScreenHeight }, + { "GetDamageBonusStat", &Script_GetDamageBonusStat }, + { "GetReleaseTimeRemaining", &Script_GetReleaseTimeRemaining }, + { "GetCorpseRecoveryDelay", &Script_GetCorpseRecoveryDelay }, + { "GetInstanceBootTimeRemaining", &Script_GetInstanceBootTimeRemaining }, + { "GetInstanceLockTimeRemaining", &Script_GetInstanceLockTimeRemaining }, + { "GetInstanceLockTimeRemainingEncounter", &Script_GetInstanceLockTimeRemainingEncounter }, + { "GetSummonConfirmTimeLeft", &Script_GetSummonConfirmTimeLeft }, + { "GetSummonConfirmSummoner", &Script_GetSummonConfirmSummoner }, + { "GetSummonConfirmAreaName", &Script_GetSummonConfirmAreaName }, + { "ConfirmSummon", &Script_ConfirmSummon }, + { "CancelSummon", &Script_CancelSummon }, + { "GetCursorPosition", &Script_GetCursorPosition }, + { "GetNetStats", &Script_GetNetStats }, + { "SitStandOrDescendStart", &Script_SitStandOrDescendStart }, + { "StopCinematic", &Script_StopCinematic }, + { "RunScript", &Script_RunScript }, + { "CheckInteractDistance", &Script_CheckInteractDistance }, + { "RandomRoll", &Script_RandomRoll }, + { "OpeningCinematic", &Script_OpeningCinematic }, + { "InCinematic", &Script_InCinematic }, + { "IsWindowsClient", &Script_IsWindowsClient }, + { "IsMacClient", &Script_IsMacClient }, + { "IsLinuxClient", &Script_IsLinuxClient }, + { "AcceptXPLoss", &Script_AcceptXPLoss }, + { "CheckSpiritHealerDist", &Script_CheckSpiritHealerDist }, + { "CheckTalentMasterDist", &Script_CheckTalentMasterDist }, + { "CheckBinderDist", &Script_CheckBinderDist }, + { "RetrieveCorpse", &Script_RetrieveCorpse }, + { "BindEnchant", &Script_BindEnchant }, + { "ReplaceEnchant", &Script_ReplaceEnchant }, + { "ReplaceTradeEnchant", &Script_ReplaceTradeEnchant }, + { "NotWhileDeadError", &Script_NotWhileDeadError }, + { "GetRestState", &Script_GetRestState }, + { "GetXPExhaustion", &Script_GetXPExhaustion }, + { "GetTimeToWellRested", &Script_GetTimeToWellRested }, + { "GMRequestPlayerInfo", &Script_GMRequestPlayerInfo }, + { "GetCoinIcon", &Script_GetCoinIcon }, + { "GetCoinText", &Script_GetCoinText }, + { "GetCoinTextureString", &Script_GetCoinTextureString }, + { "IsSubZonePVPPOI", &Script_IsSubZonePVPPOI }, + { "GetZonePVPInfo", &Script_GetZonePVPInfo }, + { "TogglePVP", &Script_TogglePVP }, + { "SetPVP", &Script_SetPVP }, + { "GetPVPDesired", &Script_GetPVPDesired }, + { "GetPVPTimer", &Script_GetPVPTimer }, + { "IsPVPTimerRunning", &Script_IsPVPTimerRunning }, + { "ConfirmBindOnUse", &Script_ConfirmBindOnUse }, + { "SetPortraitToTexture", &Script_SetPortraitToTexture }, + { "GetLocale", &Script_GetLocale }, + { "GetGMTicketCategories", &Script_GetGMTicketCategories }, + { "DropItemOnUnit", &Script_DropItemOnUnit }, + { "RestartGx", &Script_RestartGx }, + { "RestoreVideoResolutionDefaults", &Script_RestoreVideoResolutionDefaults }, + { "RestoreVideoEffectsDefaults", &Script_RestoreVideoEffectsDefaults }, + { "RestoreVideoStereoDefaults", &Script_RestoreVideoStereoDefaults }, + { "GetBindLocation", &Script_GetBindLocation }, + { "ConfirmTalentWipe", &Script_ConfirmTalentWipe }, + { "ConfirmBinder", &Script_ConfirmBinder }, + { "ShowingHelm", &Script_ShowingHelm }, + { "ShowingCloak", &Script_ShowingCloak }, + { "ShowHelm", &Script_ShowHelm }, + { "ShowCloak", &Script_ShowCloak }, + { "SetEuropeanNumbers", &Script_SetEuropeanNumbers }, + { "GetAreaSpiritHealerTime", &Script_GetAreaSpiritHealerTime }, + { "AcceptAreaSpiritHeal", &Script_AcceptAreaSpiritHeal }, + { "CancelAreaSpiritHeal", &Script_CancelAreaSpiritHeal }, + { "GetMouseFocus", &Script_GetMouseFocus }, + { "GetRealmName", &Script_GetRealmName }, + { "GetItemQualityColor", &Script_GetItemQualityColor }, + { "GetItemInfo", &Script_GetItemInfo }, + { "GetItemGem", &Script_GetItemGem }, + { "GetExtendedItemInfo", &Script_GetExtendedItemInfo }, + { "GetItemIcon", &Script_GetItemIcon }, + { "GetItemFamily", &Script_GetItemFamily }, + { "GetItemCount", &Script_GetItemCount }, + { "GetItemSpell", &Script_GetItemSpell }, + { "GetItemCooldown", &Script_GetItemCooldown }, + { "PickupItem", &Script_PickupItem }, + { "IsCurrentItem", &Script_IsCurrentItem }, + { "IsUsableItem", &Script_IsUsableItem }, + { "IsHelpfulItem", &Script_IsHelpfulItem }, + { "IsHarmfulItem", &Script_IsHarmfulItem }, + { "IsConsumableItem", &Script_IsConsumableItem }, + { "IsEquippableItem", &Script_IsEquippableItem }, + { "IsEquippedItem", &Script_IsEquippedItem }, + { "IsEquippedItemType", &Script_IsEquippedItemType }, + { "IsDressableItem", &Script_IsDressableItem }, + { "ItemHasRange", &Script_ItemHasRange }, + { "IsItemInRange", &Script_IsItemInRange }, + { "GetNumAddOns", &Script_GetNumAddOns }, + { "GetAddOnInfo", &Script_GetAddOnInfo }, + { "GetAddOnMetadata", &Script_GetAddOnMetadata }, + { "UpdateAddOnMemoryUsage", &Script_UpdateAddOnMemoryUsage }, + { "GetAddOnMemoryUsage", &Script_GetAddOnMemoryUsage }, + { "GetScriptCPUUsage", &Script_GetScriptCPUUsage }, + { "UpdateAddOnCPUUsage", &Script_UpdateAddOnCPUUsage }, + { "GetAddOnCPUUsage", &Script_GetAddOnCPUUsage }, + { "GetFunctionCPUUsage", &Script_GetFunctionCPUUsage }, + { "GetFrameCPUUsage", &Script_GetFrameCPUUsage }, + { "GetEventCPUUsage", &Script_GetEventCPUUsage }, + { "ResetCPUUsage", &Script_ResetCPUUsage }, + { "GetAddOnDependencies", &Script_GetAddOnDependencies }, + { "EnableAddOn", &Script_EnableAddOn }, + { "EnableAllAddOns", &Script_EnableAllAddOns }, + { "DisableAddOn", &Script_DisableAddOn }, + { "DisableAllAddOns", &Script_DisableAllAddOns }, + { "ResetDisabledAddOns", &Script_ResetDisabledAddOns }, + { "IsAddOnLoadOnDemand", &Script_IsAddOnLoadOnDemand }, + { "IsAddOnLoaded", &Script_IsAddOnLoaded }, + { "LoadAddOn", &Script_LoadAddOn }, + { "PartialPlayTime", &Script_PartialPlayTime }, + { "NoPlayTime", &Script_NoPlayTime }, + { "GetBillingTimeRested", &Script_GetBillingTimeRested }, + { "CanShowResetInstances", &Script_CanShowResetInstances }, + { "ResetInstances", &Script_ResetInstances }, + { "IsInInstance", &Script_IsInInstance }, + { "GetInstanceDifficulty", &Script_GetInstanceDifficulty }, + { "GetInstanceInfo", &Script_GetInstanceInfo }, + { "GetDungeonDifficulty", &Script_GetDungeonDifficulty }, + { "SetDungeonDifficulty", &Script_SetDungeonDifficulty }, + { "GetRaidDifficulty", &Script_GetRaidDifficulty }, + { "SetRaidDifficulty", &Script_SetRaidDifficulty }, + { "ReportBug", &Script_ReportBug }, + { "ReportSuggestion", &Script_ReportSuggestion }, + { "GetMirrorTimerInfo", &Script_GetMirrorTimerInfo }, + { "GetMirrorTimerProgress", &Script_GetMirrorTimerProgress }, + { "GetNumTitles", &Script_GetNumTitles }, + { "GetCurrentTitle", &Script_GetCurrentTitle }, + { "SetCurrentTitle", &Script_SetCurrentTitle }, + { "IsTitleKnown", &Script_IsTitleKnown }, + { "GetTitleName", &Script_GetTitleName }, + { "UseItemByName", &Script_UseItemByName }, + { "EquipItemByName", &Script_EquipItemByName }, + { "GetExistingLocales", &Script_GetExistingLocales }, + { "InCombatLockdown", &Script_InCombatLockdown }, + { "StartAttack", &Script_StartAttack }, + { "StopAttack", &Script_StopAttack }, + { "SetTaxiBenchmarkMode", &Script_SetTaxiBenchmarkMode }, + { "GetTaxiBenchmarkMode", &Script_GetTaxiBenchmarkMode }, + { "Dismount", &Script_Dismount }, + { "VoicePushToTalkStart", &Script_VoicePushToTalkStart }, + { "VoicePushToTalkStop", &Script_VoicePushToTalkStop }, + { "SetUIVisibility", &Script_SetUIVisibility }, + { "IsReferAFriendLinked", &Script_IsReferAFriendLinked }, + { "CanGrantLevel", &Script_CanGrantLevel }, + { "GrantLevel", &Script_GrantLevel }, + { "CanSummonFriend", &Script_CanSummonFriend }, + { "SummonFriend", &Script_SummonFriend }, + { "GetSummonFriendCooldown", &Script_GetSummonFriendCooldown }, + { "GetTotemInfo", &Script_GetTotemInfo }, + { "GetTotemTimeLeft", &Script_GetTotemTimeLeft }, + { "TargetTotem", &Script_TargetTotem }, + { "DestroyTotem", &Script_DestroyTotem }, + { "GetNumDeclensionSets", &Script_GetNumDeclensionSets }, + { "DeclineName", &Script_DeclineName }, + { "AcceptLevelGrant", &Script_AcceptLevelGrant }, + { "DeclineLevelGrant", &Script_DeclineLevelGrant }, + { "UploadSettings", &Script_UploadSettings }, + { "DownloadSettings", &Script_DownloadSettings }, + { "GetMovieResolution", &Script_GetMovieResolution }, + { "GameMovieFinished", &Script_GameMovieFinished }, + { "IsDesaturateSupported", &Script_IsDesaturateSupported }, + { "GetThreatStatusColor", &Script_GetThreatStatusColor }, + { "IsThreatWarningEnabled", &Script_IsThreatWarningEnabled }, + { "ConsoleAddMessage", &Script_ConsoleAddMessage }, + { "GetItemUniqueness", &Script_GetItemUniqueness }, + { "EndRefund", &Script_EndRefund }, + { "EndBoundTradeable", &Script_EndBoundTradeable }, + { "CanMapChangeDifficulty", &Script_CanMapChangeDifficulty }, + { "GetExpansionLevel", &Script_GetExpansionLevel }, + { "GetAllowLowLevelRaid", &Script_GetAllowLowLevelRaid }, + { "SetAllowLowLevelRaid", &Script_SetAllowLowLevelRaid }, +}; + +void GameScriptRegisterFunctions() { + for (auto& func : s_ScriptFunctions) { + FrameScript_RegisterFunction(func.name, func.method); + } +} diff --git a/src/ui/game/GameScript.hpp b/src/ui/game/GameScript.hpp new file mode 100644 index 0000000..ffab4a3 --- /dev/null +++ b/src/ui/game/GameScript.hpp @@ -0,0 +1,6 @@ +#ifndef UI_GAME_GAME_SCRIPT_HPP +#define UI_GAME_GAME_SCRIPT_HPP + +void GameScriptRegisterFunctions(); + +#endif From e8724502024c50ca2055100fd807c4c284cead7a Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 07:56:30 -0600 Subject: [PATCH 090/269] fix(ui): fix infinite loop in CSimpleFrame::SetBeingScrolled --- src/ui/simple/CSimpleFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleFrame.cpp b/src/ui/simple/CSimpleFrame.cpp index cc176e7..4832f4f 100644 --- a/src/ui/simple/CSimpleFrame.cpp +++ b/src/ui/simple/CSimpleFrame.cpp @@ -1342,7 +1342,7 @@ void CSimpleFrame::SetBeingScrolled(int32_t a2, int32_t a3) { this->m_batchDirty |= 0x1F; } - for (auto child = this->m_children.Head(); child; this->m_children.Link(child)->Next()) { + for (auto child = this->m_children.Head(); child; child = this->m_children.Link(child)->Next()) { if (!(child->frame->m_flags & 0x4000)) { child->frame->SetBeingScrolled(a2, -1); } From ba5006a4d8e69547ac80b9a0b5955c5185a328d9 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 08:20:56 -0600 Subject: [PATCH 091/269] feat(ui): implement CSimpleFontString_IsVisible --- src/ui/simple/CSimpleFontStringScript.cpp | 11 ++++++++++- src/ui/simple/CSimpleRegion.cpp | 4 ++++ src/ui/simple/CSimpleRegion.hpp | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleFontStringScript.cpp b/src/ui/simple/CSimpleFontStringScript.cpp index 57893eb..62f2415 100644 --- a/src/ui/simple/CSimpleFontStringScript.cpp +++ b/src/ui/simple/CSimpleFontStringScript.cpp @@ -73,7 +73,16 @@ int32_t CSimpleFontString_Hide(lua_State* L) { } int32_t CSimpleFontString_IsVisible(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleFontString::GetObjectType(); + auto string = static_cast(FrameScript_GetObjectThis(L, type)); + + if (string->IsVisible()) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + + return 1; } int32_t CSimpleFontString_IsShown(lua_State* L) { diff --git a/src/ui/simple/CSimpleRegion.cpp b/src/ui/simple/CSimpleRegion.cpp index aa82007..c33c754 100644 --- a/src/ui/simple/CSimpleRegion.cpp +++ b/src/ui/simple/CSimpleRegion.cpp @@ -49,6 +49,10 @@ bool CSimpleRegion::IsShown() { return this->m_shown == 1; } +bool CSimpleRegion::IsVisible() { + return this->m_visible == 1; +} + void CSimpleRegion::OnColorChanged(bool a2) { if (this->m_parent) { uint8_t effectiveAlpha = this->m_parent->m_alpha * this->m_parent->alphaBD / 255; diff --git a/src/ui/simple/CSimpleRegion.hpp b/src/ui/simple/CSimpleRegion.hpp index 6c56534..733834a 100644 --- a/src/ui/simple/CSimpleRegion.hpp +++ b/src/ui/simple/CSimpleRegion.hpp @@ -32,6 +32,7 @@ class CSimpleRegion : public CScriptRegion { void Hide(); void HideThis(); bool IsShown(); + bool IsVisible(); void OnRegionChanged(); void SetVertexColor(const CImVector& color); void SetVertexGradient(ORIENTATION orientation, const CImVector& minColor, const CImVector& maxColor); From 98ea3099855e87e5a1424ef4d2cfc1aae8c8cae5 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 08:24:29 -0600 Subject: [PATCH 092/269] feat(ui): implement CSimpleTexture_IsVisible --- src/ui/simple/CSimpleTextureScript.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleTextureScript.cpp b/src/ui/simple/CSimpleTextureScript.cpp index a6ea6ac..473204f 100644 --- a/src/ui/simple/CSimpleTextureScript.cpp +++ b/src/ui/simple/CSimpleTextureScript.cpp @@ -97,7 +97,16 @@ int32_t CSimpleTexture_Hide(lua_State* L) { } int32_t CSimpleTexture_IsVisible(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleTexture::GetObjectType(); + auto texture = static_cast(FrameScript_GetObjectThis(L, type)); + + if (texture->IsVisible()) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + + return 1; } int32_t CSimpleTexture_IsShown(lua_State* L) { From 7d9173b880707c6750be95e665b7d167d89861a6 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 08:26:08 -0600 Subject: [PATCH 093/269] feat(ui): implement CSimpleTexture_IsShown --- src/ui/simple/CSimpleTextureScript.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleTextureScript.cpp b/src/ui/simple/CSimpleTextureScript.cpp index 473204f..2dbe992 100644 --- a/src/ui/simple/CSimpleTextureScript.cpp +++ b/src/ui/simple/CSimpleTextureScript.cpp @@ -110,7 +110,16 @@ int32_t CSimpleTexture_IsVisible(lua_State* L) { } int32_t CSimpleTexture_IsShown(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleTexture::GetObjectType(); + auto texture = static_cast(FrameScript_GetObjectThis(L, type)); + + if (texture->IsShown()) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + + return 1; } int32_t CSimpleTexture_GetTexture(lua_State* L) { From 5f7bf8c95c84e8f7d0500ed254a4ebd8183f8149 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 08:44:58 -0600 Subject: [PATCH 094/269] feat(ui): implement Script_GetCVarBool --- src/ui/game/GameScript.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/ui/game/GameScript.cpp b/src/ui/game/GameScript.cpp index bc194d8..0def051 100644 --- a/src/ui/game/GameScript.cpp +++ b/src/ui/game/GameScript.cpp @@ -1,6 +1,8 @@ #include "ui/game/GameScript.hpp" +#include "console/CVar.hpp" #include "ui/FrameScript.hpp" #include "ui/ScriptFunctionsShared.hpp" +#include "util/StringTo.hpp" #include "util/Unimplemented.hpp" namespace { @@ -133,7 +135,21 @@ int32_t Script_GetCVar(lua_State* L) { } int32_t Script_GetCVarBool(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isstring(L, 1)) { + luaL_error(L, "Usage: GetCVarBool(\"cvar\")"); + return 0; + } + + auto varName = lua_tostring(L, 1); + auto var = CVar::LookupRegistered(varName); + + if (var && !(var->m_flags & 0x40) && StringToBOOL(var->GetString())) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + + return 1; } int32_t Script_GetCVarDefault(lua_State* L) { From b9f2c609667a5a2c383d7569d54f01f0c45fe507 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 09:01:17 -0600 Subject: [PATCH 095/269] feat(ui): implement Script_GetCursorPosition --- src/ui/game/GameScript.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/ui/game/GameScript.cpp b/src/ui/game/GameScript.cpp index 0def051..111b13a 100644 --- a/src/ui/game/GameScript.cpp +++ b/src/ui/game/GameScript.cpp @@ -1,7 +1,9 @@ #include "ui/game/GameScript.hpp" #include "console/CVar.hpp" +#include "gx/Coordinate.hpp" #include "ui/FrameScript.hpp" #include "ui/ScriptFunctionsShared.hpp" +#include "ui/simple/CSimpleTop.hpp" #include "util/StringTo.hpp" #include "util/Unimplemented.hpp" @@ -617,7 +619,25 @@ int32_t Script_CancelSummon(lua_State* L) { } int32_t Script_GetCursorPosition(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + STORM_ASSERT(CSimpleTop::s_instance); + + float ddcX = 0.0f; + float ddcY = 0.0f; + + NDCToDDC( + CSimpleTop::s_instance->m_mousePosition.x, + CSimpleTop::s_instance->m_mousePosition.y, + &ddcX, + &ddcY + ); + + float ndcX = DDCToNDCWidth(CoordinateGetAspectCompensation() * 1024.0f * ddcX); + lua_pushnumber(L, ndcX); + + float ndcY = DDCToNDCWidth(CoordinateGetAspectCompensation() * 1024.0f * ddcY); + lua_pushnumber(L, ndcY); + + return 2; } int32_t Script_GetNetStats(lua_State* L) { From c4077daa3f7eab3d7c9f0667b348f7424c39222e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 10:39:50 -0600 Subject: [PATCH 096/269] feat(ui): implement CSimpleFrame_EnableMouse --- src/ui/simple/CSimpleFrame.cpp | 12 ++++++++++++ src/ui/simple/CSimpleFrame.hpp | 1 + src/ui/simple/CSimpleFrameScript.cpp | 18 +++++++++++++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleFrame.cpp b/src/ui/simple/CSimpleFrame.cpp index 4832f4f..1257cd1 100644 --- a/src/ui/simple/CSimpleFrame.cpp +++ b/src/ui/simple/CSimpleFrame.cpp @@ -100,6 +100,18 @@ void CSimpleFrame::DisableDrawLayer(uint32_t drawlayer) { this->NotifyDrawLayerChanged(drawlayer); } +void CSimpleFrame::DisableEvent(CSimpleEventType eventType) { + if (!(this->m_eventmask & (1 << eventType))) { + return; + } + + if (this->m_visible) { + this->m_top->UnregisterForEvent(this, eventType, 0); + } + + this->m_eventmask &= ~(1 << eventType); +} + void CSimpleFrame::EnableDrawLayer(uint32_t drawlayer) { this->m_drawenabled[drawlayer] = 1; this->NotifyDrawLayerChanged(drawlayer); diff --git a/src/ui/simple/CSimpleFrame.hpp b/src/ui/simple/CSimpleFrame.hpp index 2807794..2f08b23 100644 --- a/src/ui/simple/CSimpleFrame.hpp +++ b/src/ui/simple/CSimpleFrame.hpp @@ -123,6 +123,7 @@ class CSimpleFrame : public CScriptRegion { CSimpleFrame(CSimpleFrame* parent); void AddFrameRegion(CSimpleRegion* region, uint32_t drawlayer); void DisableDrawLayer(uint32_t drawlayer); + void DisableEvent(CSimpleEventType eventType); void EnableDrawLayer(uint32_t drawlayer); void EnableEvent(CSimpleEventType eventType, int32_t priority); int32_t GetHitRect(CRect& rect); diff --git a/src/ui/simple/CSimpleFrameScript.cpp b/src/ui/simple/CSimpleFrameScript.cpp index 2b63fb0..ca9d743 100644 --- a/src/ui/simple/CSimpleFrameScript.cpp +++ b/src/ui/simple/CSimpleFrameScript.cpp @@ -4,6 +4,7 @@ #include "ui/FrameScript.hpp" #include "ui/simple/CSimpleFrame.hpp" #include "util/Lua.hpp" +#include "util/StringTo.hpp" #include "util/Unimplemented.hpp" #include #include @@ -459,7 +460,22 @@ int32_t CSimpleFrame_IsKeyboardEnabled(lua_State* L) { } int32_t CSimpleFrame_EnableMouse(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleFrame::GetObjectType(); + auto frame = static_cast(FrameScript_GetObjectThis(L, type)); + + if (!frame->ProtectedFunctionsAllowed()) { + // TODO disallowed logic + + return 0; + } + + if (StringToBOOL(L, 2, 1)) { + frame->EnableEvent(SIMPLE_EVENT_MOUSE, -1); + } else { + frame->DisableEvent(SIMPLE_EVENT_MOUSE); + } + + return 0; } int32_t CSimpleFrame_IsMouseEnabled(lua_State* L) { From 1c1e4f587536e83002d6189c60744fec25709adf Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 12:25:49 -0600 Subject: [PATCH 097/269] feat(ui): register GameTooltip factory --- src/ui/game/CGGameUI.cpp | 2 ++ src/ui/game/CGTooltip.cpp | 11 +++++++++++ src/ui/game/CGTooltip.hpp | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 src/ui/game/CGTooltip.cpp create mode 100644 src/ui/game/CGTooltip.hpp diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 0f527fd..35a392f 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -2,6 +2,7 @@ #include "client/Client.hpp" #include "ui/FrameXML.hpp" #include "ui/Key.hpp" +#include "ui/game/CGTooltip.hpp" #include "ui/game/CGWorldFrame.hpp" #include "ui/game/GMTicketInfoScript.hpp" #include "ui/game/GameScript.hpp" @@ -112,6 +113,7 @@ void CGGameUI::InitializeGame() { void CGGameUI::RegisterFrameFactories() { FrameXML_RegisterFactory("WorldFrame", &CGWorldFrame::Create, true); + FrameXML_RegisterFactory("GameTooltip", &CGTooltip::Create, false); // TODO register remaining factories } diff --git a/src/ui/game/CGTooltip.cpp b/src/ui/game/CGTooltip.cpp new file mode 100644 index 0000000..57e78a7 --- /dev/null +++ b/src/ui/game/CGTooltip.cpp @@ -0,0 +1,11 @@ +#include "ui/game/CGTooltip.hpp" + +CSimpleFrame* CGTooltip::Create(CSimpleFrame* parent) { + // TODO use CDataAllocator + + return STORM_NEW(CGTooltip)(parent); +} + +CGTooltip::CGTooltip(CSimpleFrame* parent) : CSimpleFrame(parent) { + // TODO +} diff --git a/src/ui/game/CGTooltip.hpp b/src/ui/game/CGTooltip.hpp new file mode 100644 index 0000000..f59c5a6 --- /dev/null +++ b/src/ui/game/CGTooltip.hpp @@ -0,0 +1,18 @@ +#ifndef UI_GAME_C_G_TOOLTIP_HPP +#define UI_GAME_C_G_TOOLTIP_HPP + +#include "ui/simple/CSimpleFrame.hpp" + +class CGTooltip : public CSimpleFrame { + public: + // Static functions + static CSimpleFrame* Create(CSimpleFrame* parent); + + // Member variables + // TODO + + // Member functions + CGTooltip(CSimpleFrame* parent); +}; + +#endif From 8ee1586a142e5166c7122266c67e562d2def5cb9 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 16:17:40 -0600 Subject: [PATCH 098/269] feat(ui): add CharacterInfoRegisterScriptFunctions --- src/ui/game/CGGameUI.cpp | 7 +- src/ui/game/CharacterInfoScript.cpp | 181 ++++++++++++++++++++++++++++ src/ui/game/CharacterInfoScript.hpp | 6 + 3 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 src/ui/game/CharacterInfoScript.cpp create mode 100644 src/ui/game/CharacterInfoScript.hpp diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 35a392f..91f1e80 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -4,8 +4,9 @@ #include "ui/Key.hpp" #include "ui/game/CGTooltip.hpp" #include "ui/game/CGWorldFrame.hpp" -#include "ui/game/GMTicketInfoScript.hpp" +#include "ui/game/CharacterInfoScript.hpp" #include "ui/game/GameScript.hpp" +#include "ui/game/GMTicketInfoScript.hpp" #include "ui/game/ScriptEvents.hpp" #include "ui/simple/CSimpleTop.hpp" #include "util/CStatus.hpp" @@ -24,6 +25,10 @@ void LoadScriptFunctions() { // TODO + CharacterInfoRegisterScriptFunctions(); + + // TODO + GMTicketInfoRegisterScriptFunctions(); // TODO diff --git a/src/ui/game/CharacterInfoScript.cpp b/src/ui/game/CharacterInfoScript.cpp new file mode 100644 index 0000000..1b70462 --- /dev/null +++ b/src/ui/game/CharacterInfoScript.cpp @@ -0,0 +1,181 @@ +#include "ui/game/CharacterInfoScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t Script_GetInventorySlotInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInventoryItemsForSlot(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInventoryItemTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInventoryItemBroken(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInventoryItemCount(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInventoryItemQuality(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInventoryItemCooldown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInventoryItemDurability(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInventoryItemLink(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInventoryItemID(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInventoryItemGems(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_KeyRingButtonIDToInvSlotID(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_PickupInventoryItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UseInventoryItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SocketInventoryItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsInventoryItemLocked(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_PutItemInBag(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_PutItemInBackpack(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_PickupBagFromSlot(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CursorCanGoInSlot(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ShowInventorySellCursor(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetInventoryPortraitTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetGuildInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInventoryAlertStatus(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UpdateInventoryAlertStatus(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_OffhandHasWeapon(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_HasInspectHonorData(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RequestInspectHonorData(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInspectHonorData(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetInspectArenaTeamData(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ClearInspectPlayer(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetWeaponEnchantInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_HasWandEquipped(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +static FrameScript_Method s_ScriptFunctions[] = { + { "GetInventorySlotInfo", &Script_GetInventorySlotInfo }, + { "GetInventoryItemsForSlot", &Script_GetInventoryItemsForSlot }, + { "GetInventoryItemTexture", &Script_GetInventoryItemTexture }, + { "GetInventoryItemBroken", &Script_GetInventoryItemBroken }, + { "GetInventoryItemCount", &Script_GetInventoryItemCount }, + { "GetInventoryItemQuality", &Script_GetInventoryItemQuality }, + { "GetInventoryItemCooldown", &Script_GetInventoryItemCooldown }, + { "GetInventoryItemDurability", &Script_GetInventoryItemDurability }, + { "GetInventoryItemLink", &Script_GetInventoryItemLink }, + { "GetInventoryItemID", &Script_GetInventoryItemID }, + { "GetInventoryItemGems", &Script_GetInventoryItemGems }, + { "KeyRingButtonIDToInvSlotID", &Script_KeyRingButtonIDToInvSlotID }, + { "PickupInventoryItem", &Script_PickupInventoryItem }, + { "UseInventoryItem", &Script_UseInventoryItem }, + { "SocketInventoryItem", &Script_SocketInventoryItem }, + { "IsInventoryItemLocked", &Script_IsInventoryItemLocked }, + { "PutItemInBag", &Script_PutItemInBag }, + { "PutItemInBackpack", &Script_PutItemInBackpack }, + { "PickupBagFromSlot", &Script_PickupBagFromSlot }, + { "CursorCanGoInSlot", &Script_CursorCanGoInSlot }, + { "ShowInventorySellCursor", &Script_ShowInventorySellCursor }, + { "SetInventoryPortraitTexture", &Script_SetInventoryPortraitTexture }, + { "GetGuildInfo", &Script_GetGuildInfo }, + { "GetInventoryAlertStatus", &Script_GetInventoryAlertStatus }, + { "UpdateInventoryAlertStatus", &Script_UpdateInventoryAlertStatus }, + { "OffhandHasWeapon", &Script_OffhandHasWeapon }, + { "HasInspectHonorData", &Script_HasInspectHonorData }, + { "RequestInspectHonorData", &Script_RequestInspectHonorData }, + { "GetInspectHonorData", &Script_GetInspectHonorData }, + { "GetInspectArenaTeamData", &Script_GetInspectArenaTeamData }, + { "ClearInspectPlayer", &Script_ClearInspectPlayer }, + { "GetWeaponEnchantInfo", &Script_GetWeaponEnchantInfo }, + { "HasWandEquipped", &Script_HasWandEquipped }, +}; + +void CharacterInfoRegisterScriptFunctions() { + for (auto& func : s_ScriptFunctions) { + FrameScript_RegisterFunction(func.name, func.method); + } +} diff --git a/src/ui/game/CharacterInfoScript.hpp b/src/ui/game/CharacterInfoScript.hpp new file mode 100644 index 0000000..96ebefc --- /dev/null +++ b/src/ui/game/CharacterInfoScript.hpp @@ -0,0 +1,6 @@ +#ifndef UI_GAME_CHARACTER_INFO_SCRIPT_HPP +#define UI_GAME_CHARACTER_INFO_SCRIPT_HPP + +void CharacterInfoRegisterScriptFunctions(); + +#endif From 94731f53c35fd93fc2d978fac791a51d5ecab125 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 17:46:48 -0600 Subject: [PATCH 099/269] feat(ui): add BattlefieldInfoRegisterScriptFunctions --- src/ui/game/BattlefieldInfoScript.cpp | 271 ++++++++++++++++++++++++++ src/ui/game/BattlefieldInfoScript.hpp | 6 + src/ui/game/CGGameUI.cpp | 7 +- 3 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 src/ui/game/BattlefieldInfoScript.cpp create mode 100644 src/ui/game/BattlefieldInfoScript.hpp diff --git a/src/ui/game/BattlefieldInfoScript.cpp b/src/ui/game/BattlefieldInfoScript.cpp new file mode 100644 index 0000000..11c22c8 --- /dev/null +++ b/src/ui/game/BattlefieldInfoScript.cpp @@ -0,0 +1,271 @@ +#include "ui/game/BattlefieldInfoScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t Script_GetNumBattlefields(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldInstanceInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsBattlefieldArena(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsActiveBattlefieldArena(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_JoinBattlefield(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetSelectedBattlefield(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetSelectedBattlefield(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_AcceptBattlefieldPort(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldStatus(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldPortExpiration(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldInstanceExpiration(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldInstanceRunTime(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldEstimatedWaitTime(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldTimeWaited(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CloseBattlefield(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RequestBattlefieldScoreData(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetNumBattlefieldScores(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldScore(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldWinner(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetBattlefieldScoreFaction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_LeaveBattlefield(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetNumBattlefieldStats(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldStatInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldStatData(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RequestBattlefieldPositions(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetNumBattlefieldPositions(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldPosition(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetNumBattlefieldFlagPositions(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldFlagPosition(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetNumBattlefieldVehicles(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldVehicleInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CanJoinBattlefieldAsGroup(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldMapIconScale(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldTeamInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlefieldArenaFaction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SortBattlefieldScoreData(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_HearthAndResurrectFromArea(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CanHearthAndResurrectFromArea(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetNumBattlegroundTypes(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBattlegroundInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RequestBattlegroundInstanceInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetNumArenaOpponents(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BattlefieldMgrEntryInviteResponse(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BattlefieldMgrQueueRequest(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BattlefieldMgrQueueInviteResponse(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BattlefieldMgrExitRequest(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetWorldPVPQueueStatus(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetHolidayBGHonorCurrencyBonuses(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetRandomBGHonorCurrencyBonuses(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SortBGList(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +static FrameScript_Method s_ScriptFunctions[] = { + { "GetNumBattlefields", &Script_GetNumBattlefields }, + { "GetBattlefieldInfo", &Script_GetBattlefieldInfo }, + { "GetBattlefieldInstanceInfo", &Script_GetBattlefieldInstanceInfo }, + { "IsBattlefieldArena", &Script_IsBattlefieldArena }, + { "IsActiveBattlefieldArena", &Script_IsActiveBattlefieldArena }, + { "JoinBattlefield", &Script_JoinBattlefield }, + { "SetSelectedBattlefield", &Script_SetSelectedBattlefield }, + { "GetSelectedBattlefield", &Script_GetSelectedBattlefield }, + { "AcceptBattlefieldPort", &Script_AcceptBattlefieldPort }, + { "GetBattlefieldStatus", &Script_GetBattlefieldStatus }, + { "GetBattlefieldPortExpiration", &Script_GetBattlefieldPortExpiration }, + { "GetBattlefieldInstanceExpiration", &Script_GetBattlefieldInstanceExpiration }, + { "GetBattlefieldInstanceRunTime", &Script_GetBattlefieldInstanceRunTime }, + { "GetBattlefieldEstimatedWaitTime", &Script_GetBattlefieldEstimatedWaitTime }, + { "GetBattlefieldTimeWaited", &Script_GetBattlefieldTimeWaited }, + { "CloseBattlefield", &Script_CloseBattlefield }, + { "RequestBattlefieldScoreData", &Script_RequestBattlefieldScoreData }, + { "GetNumBattlefieldScores", &Script_GetNumBattlefieldScores }, + { "GetBattlefieldScore", &Script_GetBattlefieldScore }, + { "GetBattlefieldWinner", &Script_GetBattlefieldWinner }, + { "SetBattlefieldScoreFaction", &Script_SetBattlefieldScoreFaction }, + { "LeaveBattlefield", &Script_LeaveBattlefield }, + { "GetNumBattlefieldStats", &Script_GetNumBattlefieldStats }, + { "GetBattlefieldStatInfo", &Script_GetBattlefieldStatInfo }, + { "GetBattlefieldStatData", &Script_GetBattlefieldStatData }, + { "RequestBattlefieldPositions", &Script_RequestBattlefieldPositions }, + { "GetNumBattlefieldPositions", &Script_GetNumBattlefieldPositions }, + { "GetBattlefieldPosition", &Script_GetBattlefieldPosition }, + { "GetNumBattlefieldFlagPositions", &Script_GetNumBattlefieldFlagPositions }, + { "GetBattlefieldFlagPosition", &Script_GetBattlefieldFlagPosition }, + { "GetNumBattlefieldVehicles", &Script_GetNumBattlefieldVehicles }, + { "GetBattlefieldVehicleInfo", &Script_GetBattlefieldVehicleInfo }, + { "CanJoinBattlefieldAsGroup", &Script_CanJoinBattlefieldAsGroup }, + { "GetBattlefieldMapIconScale", &Script_GetBattlefieldMapIconScale }, + { "GetBattlefieldTeamInfo", &Script_GetBattlefieldTeamInfo }, + { "GetBattlefieldArenaFaction", &Script_GetBattlefieldArenaFaction }, + { "SortBattlefieldScoreData", &Script_SortBattlefieldScoreData }, + { "HearthAndResurrectFromArea", &Script_HearthAndResurrectFromArea }, + { "CanHearthAndResurrectFromArea", &Script_CanHearthAndResurrectFromArea }, + { "GetNumBattlegroundTypes", &Script_GetNumBattlegroundTypes }, + { "GetBattlegroundInfo", &Script_GetBattlegroundInfo }, + { "RequestBattlegroundInstanceInfo", &Script_RequestBattlegroundInstanceInfo }, + { "GetNumArenaOpponents", &Script_GetNumArenaOpponents }, + { "BattlefieldMgrEntryInviteResponse", &Script_BattlefieldMgrEntryInviteResponse }, + { "BattlefieldMgrQueueRequest", &Script_BattlefieldMgrQueueRequest }, + { "BattlefieldMgrQueueInviteResponse", &Script_BattlefieldMgrQueueInviteResponse }, + { "BattlefieldMgrExitRequest", &Script_BattlefieldMgrExitRequest }, + { "GetWorldPVPQueueStatus", &Script_GetWorldPVPQueueStatus }, + { "GetHolidayBGHonorCurrencyBonuses", &Script_GetHolidayBGHonorCurrencyBonuses }, + { "GetRandomBGHonorCurrencyBonuses", &Script_GetRandomBGHonorCurrencyBonuses }, + { "SortBGList", &Script_SortBGList }, +}; + +void BattlefieldInfoRegisterScriptFunctions() { + for (auto& func : s_ScriptFunctions) { + FrameScript_RegisterFunction(func.name, func.method); + } +} diff --git a/src/ui/game/BattlefieldInfoScript.hpp b/src/ui/game/BattlefieldInfoScript.hpp new file mode 100644 index 0000000..7eb21aa --- /dev/null +++ b/src/ui/game/BattlefieldInfoScript.hpp @@ -0,0 +1,6 @@ +#ifndef UI_GAME_BATTLEFIELD_INFO_SCRIPT_HPP +#define UI_GAME_BATTLEFIELD_INFO_SCRIPT_HPP + +void BattlefieldInfoRegisterScriptFunctions(); + +#endif diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 91f1e80..6a4e49e 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -2,11 +2,12 @@ #include "client/Client.hpp" #include "ui/FrameXML.hpp" #include "ui/Key.hpp" +#include "ui/game/BattlefieldInfoScript.hpp" #include "ui/game/CGTooltip.hpp" #include "ui/game/CGWorldFrame.hpp" #include "ui/game/CharacterInfoScript.hpp" -#include "ui/game/GameScript.hpp" #include "ui/game/GMTicketInfoScript.hpp" +#include "ui/game/GameScript.hpp" #include "ui/game/ScriptEvents.hpp" #include "ui/simple/CSimpleTop.hpp" #include "util/CStatus.hpp" @@ -29,6 +30,10 @@ void LoadScriptFunctions() { // TODO + BattlefieldInfoRegisterScriptFunctions(); + + // TODO + GMTicketInfoRegisterScriptFunctions(); // TODO From 501935ffc2717390c836100e1a061813929a481d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 17:49:22 -0600 Subject: [PATCH 100/269] feat(ui): stub Script_GetGameTime --- src/ui/ScriptFunctionsSystem.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/ScriptFunctionsSystem.cpp b/src/ui/ScriptFunctionsSystem.cpp index 72c13dd..bc484aa 100644 --- a/src/ui/ScriptFunctionsSystem.cpp +++ b/src/ui/ScriptFunctionsSystem.cpp @@ -14,7 +14,10 @@ int32_t Script_GetTime(lua_State* L) { } int32_t Script_GetGameTime(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + // TODO real implementation + lua_pushnumber(L, 1.0); + lua_pushnumber(L, 15.0); + WHOA_UNIMPLEMENTED(2); } int32_t Script_ConsoleExec(lua_State* L) { From ac0930497c4e2db8bc7d3fe0dad640cf13e0020e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 17:54:56 -0600 Subject: [PATCH 101/269] feat(ui): add CGTooltip::GetObjectType --- src/ui/game/CGTooltip.cpp | 10 ++++++++++ src/ui/game/CGTooltip.hpp | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/src/ui/game/CGTooltip.cpp b/src/ui/game/CGTooltip.cpp index 57e78a7..e319dd4 100644 --- a/src/ui/game/CGTooltip.cpp +++ b/src/ui/game/CGTooltip.cpp @@ -1,11 +1,21 @@ #include "ui/game/CGTooltip.hpp" +int32_t CGTooltip::s_objectType; + CSimpleFrame* CGTooltip::Create(CSimpleFrame* parent) { // TODO use CDataAllocator return STORM_NEW(CGTooltip)(parent); } +int32_t CGTooltip::GetObjectType() { + if (!CGTooltip::s_objectType) { + CGTooltip::s_objectType = ++FrameScript_Object::s_objectTypes; + } + + return CGTooltip::s_objectType; +} + CGTooltip::CGTooltip(CSimpleFrame* parent) : CSimpleFrame(parent) { // TODO } diff --git a/src/ui/game/CGTooltip.hpp b/src/ui/game/CGTooltip.hpp index f59c5a6..8bcfa62 100644 --- a/src/ui/game/CGTooltip.hpp +++ b/src/ui/game/CGTooltip.hpp @@ -5,8 +5,12 @@ class CGTooltip : public CSimpleFrame { public: + // Static variables + static int32_t s_objectType; + // Static functions static CSimpleFrame* Create(CSimpleFrame* parent); + static int32_t GetObjectType(); // Member variables // TODO From 1334d1407c2dac6a8115b6c862252e27044cab7a Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 18:45:52 -0600 Subject: [PATCH 102/269] feat(ui): add CGTooltip::CreateScriptMetaTable --- src/ui/game/CGGameUI.cpp | 4 + src/ui/game/CGTooltip.cpp | 12 ++ src/ui/game/CGTooltip.hpp | 3 + src/ui/game/CGTooltipScript.cpp | 355 ++++++++++++++++++++++++++++++++ src/ui/game/CGTooltipScript.hpp | 10 + 5 files changed, 384 insertions(+) create mode 100644 src/ui/game/CGTooltipScript.cpp create mode 100644 src/ui/game/CGTooltipScript.hpp diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 6a4e49e..5af07f7 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -18,6 +18,10 @@ CSimpleTop* CGGameUI::s_simpleTop; void LoadScriptFunctions() { // TODO + CGTooltip::CreateScriptMetaTable(); + + // TODO + GameScriptRegisterFunctions(); // TODO diff --git a/src/ui/game/CGTooltip.cpp b/src/ui/game/CGTooltip.cpp index e319dd4..ceb5bfa 100644 --- a/src/ui/game/CGTooltip.cpp +++ b/src/ui/game/CGTooltip.cpp @@ -1,5 +1,7 @@ #include "ui/game/CGTooltip.hpp" +#include "ui/game/CGTooltipScript.hpp" +int32_t CGTooltip::s_metatable; int32_t CGTooltip::s_objectType; CSimpleFrame* CGTooltip::Create(CSimpleFrame* parent) { @@ -8,6 +10,11 @@ CSimpleFrame* CGTooltip::Create(CSimpleFrame* parent) { return STORM_NEW(CGTooltip)(parent); } +void CGTooltip::CreateScriptMetaTable() { + auto L = FrameScript_GetContext(); + CGTooltip::s_metatable = FrameScript_Object::CreateScriptMetaTable(L, &CGTooltip::RegisterScriptMethods); +} + int32_t CGTooltip::GetObjectType() { if (!CGTooltip::s_objectType) { CGTooltip::s_objectType = ++FrameScript_Object::s_objectTypes; @@ -16,6 +23,11 @@ int32_t CGTooltip::GetObjectType() { return CGTooltip::s_objectType; } +void CGTooltip::RegisterScriptMethods(lua_State* L) { + CSimpleFrame::RegisterScriptMethods(L); + FrameScript_Object::FillScriptMethodTable(L, CGTooltipMethods, NUM_CG_TOOLTIP_SCRIPT_METHODS); +} + CGTooltip::CGTooltip(CSimpleFrame* parent) : CSimpleFrame(parent) { // TODO } diff --git a/src/ui/game/CGTooltip.hpp b/src/ui/game/CGTooltip.hpp index 8bcfa62..5b32efa 100644 --- a/src/ui/game/CGTooltip.hpp +++ b/src/ui/game/CGTooltip.hpp @@ -6,11 +6,14 @@ class CGTooltip : public CSimpleFrame { public: // Static variables + static int32_t s_metatable; static int32_t s_objectType; // Static functions static CSimpleFrame* Create(CSimpleFrame* parent); + static void CreateScriptMetaTable(); static int32_t GetObjectType(); + static void RegisterScriptMethods(lua_State* L); // Member variables // TODO diff --git a/src/ui/game/CGTooltipScript.cpp b/src/ui/game/CGTooltipScript.cpp new file mode 100644 index 0000000..91b296d --- /dev/null +++ b/src/ui/game/CGTooltipScript.cpp @@ -0,0 +1,355 @@ +#include "ui/game/CGTooltipScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t CGTooltip_AddFontStrings(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetMinimumWidth(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_GetMinimumWidth(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetPadding(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_GetPadding(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_IsOwned(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_GetOwner(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetOwner(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_GetAnchorType(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetAnchorType(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_ClearLines(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_AddLine(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_AddDoubleLine(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_AddTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetText(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_AppendText(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_FadeOut(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetHyperlink(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetPetAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetShapeshift(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetPossession(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetTracking(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetSpell(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetSpellByID(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetGlyph(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetInventoryItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetLootItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetQuestItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetQuestLogItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetTrainerService(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetTradeSkillItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetMerchantItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetMerchantCostItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetTradePlayerItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetTradeTargetItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetBagItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetUnit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetUnitBuff(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetUnitDebuff(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetUnitAura(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetTalent(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetSendMailItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetInboxItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetAuctionSellItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetAuctionItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_NumLines(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetQuestRewardSpell(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetQuestLogRewardSpell(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetHyperlinkCompareItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetBuybackItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetLootRollItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetSocketedItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetSocketGem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetExistingSocketGem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetGuildBankItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_IsUnit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_GetUnit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_GetItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_GetSpell(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetTotem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetCurrencyToken(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetBackpackToken(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_IsEquippedItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetQuestLogSpecialItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetEquipmentSet(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetFrameStack(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetLFGDungeonReward(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTooltip_SetLFGCompletionReward(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +FrameScript_Method CGTooltipMethods[] = { + { "AddFontStrings", &CGTooltip_AddFontStrings }, + { "SetMinimumWidth", &CGTooltip_SetMinimumWidth }, + { "GetMinimumWidth", &CGTooltip_GetMinimumWidth }, + { "SetPadding", &CGTooltip_SetPadding }, + { "GetPadding", &CGTooltip_GetPadding }, + { "IsOwned", &CGTooltip_IsOwned }, + { "GetOwner", &CGTooltip_GetOwner }, + { "SetOwner", &CGTooltip_SetOwner }, + { "GetAnchorType", &CGTooltip_GetAnchorType }, + { "SetAnchorType", &CGTooltip_SetAnchorType }, + { "ClearLines", &CGTooltip_ClearLines }, + { "AddLine", &CGTooltip_AddLine }, + { "AddDoubleLine", &CGTooltip_AddDoubleLine }, + { "AddTexture", &CGTooltip_AddTexture }, + { "SetText", &CGTooltip_SetText }, + { "AppendText", &CGTooltip_AppendText }, + { "FadeOut", &CGTooltip_FadeOut }, + { "SetHyperlink", &CGTooltip_SetHyperlink }, + { "SetAction", &CGTooltip_SetAction }, + { "SetPetAction", &CGTooltip_SetPetAction }, + { "SetShapeshift", &CGTooltip_SetShapeshift }, + { "SetPossession", &CGTooltip_SetPossession }, + { "SetTracking", &CGTooltip_SetTracking }, + { "SetSpell", &CGTooltip_SetSpell }, + { "SetSpellByID", &CGTooltip_SetSpellByID }, + { "SetGlyph", &CGTooltip_SetGlyph }, + { "SetInventoryItem", &CGTooltip_SetInventoryItem }, + { "SetLootItem", &CGTooltip_SetLootItem }, + { "SetQuestItem", &CGTooltip_SetQuestItem }, + { "SetQuestLogItem", &CGTooltip_SetQuestLogItem }, + { "SetTrainerService", &CGTooltip_SetTrainerService }, + { "SetTradeSkillItem", &CGTooltip_SetTradeSkillItem }, + { "SetMerchantItem", &CGTooltip_SetMerchantItem }, + { "SetMerchantCostItem", &CGTooltip_SetMerchantCostItem }, + { "SetTradePlayerItem", &CGTooltip_SetTradePlayerItem }, + { "SetTradeTargetItem", &CGTooltip_SetTradeTargetItem }, + { "SetBagItem", &CGTooltip_SetBagItem }, + { "SetUnit", &CGTooltip_SetUnit }, + { "SetUnitBuff", &CGTooltip_SetUnitBuff }, + { "SetUnitDebuff", &CGTooltip_SetUnitDebuff }, + { "SetUnitAura", &CGTooltip_SetUnitAura }, + { "SetTalent", &CGTooltip_SetTalent }, + { "SetSendMailItem", &CGTooltip_SetSendMailItem }, + { "SetInboxItem", &CGTooltip_SetInboxItem }, + { "SetAuctionSellItem", &CGTooltip_SetAuctionSellItem }, + { "SetAuctionItem", &CGTooltip_SetAuctionItem }, + { "NumLines", &CGTooltip_NumLines }, + { "SetQuestRewardSpell", &CGTooltip_SetQuestRewardSpell }, + { "SetQuestLogRewardSpell", &CGTooltip_SetQuestLogRewardSpell }, + { "SetHyperlinkCompareItem", &CGTooltip_SetHyperlinkCompareItem }, + { "SetBuybackItem", &CGTooltip_SetBuybackItem }, + { "SetLootRollItem", &CGTooltip_SetLootRollItem }, + { "SetSocketedItem", &CGTooltip_SetSocketedItem }, + { "SetSocketGem", &CGTooltip_SetSocketGem }, + { "SetExistingSocketGem", &CGTooltip_SetExistingSocketGem }, + { "SetGuildBankItem", &CGTooltip_SetGuildBankItem }, + { "IsUnit", &CGTooltip_IsUnit }, + { "GetUnit", &CGTooltip_GetUnit }, + { "GetItem", &CGTooltip_GetItem }, + { "GetSpell", &CGTooltip_GetSpell }, + { "SetTotem", &CGTooltip_SetTotem }, + { "SetCurrencyToken", &CGTooltip_SetCurrencyToken }, + { "SetBackpackToken", &CGTooltip_SetBackpackToken }, + { "IsEquippedItem", &CGTooltip_IsEquippedItem }, + { "SetQuestLogSpecialItem", &CGTooltip_SetQuestLogSpecialItem }, + { "SetEquipmentSet", &CGTooltip_SetEquipmentSet }, + { "SetFrameStack", &CGTooltip_SetFrameStack }, + { "SetLFGDungeonReward", &CGTooltip_SetLFGDungeonReward }, + { "SetLFGCompletionReward", &CGTooltip_SetLFGCompletionReward }, +}; diff --git a/src/ui/game/CGTooltipScript.hpp b/src/ui/game/CGTooltipScript.hpp new file mode 100644 index 0000000..635099f --- /dev/null +++ b/src/ui/game/CGTooltipScript.hpp @@ -0,0 +1,10 @@ +#ifndef UI_GAME_C_G_TOOLTIP_SCRIPT_HPP +#define UI_GAME_C_G_TOOLTIP_SCRIPT_HPP + +#include "ui/Types.hpp" + +#define NUM_CG_TOOLTIP_SCRIPT_METHODS 69 + +extern FrameScript_Method CGTooltipMethods[NUM_CG_TOOLTIP_SCRIPT_METHODS]; + +#endif From 6b916d56d1d13fc6151f5abf2d55a1ccfce038fe Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 19:12:52 -0600 Subject: [PATCH 103/269] feat(ui): add CGTooltip::GetScriptMetaTable --- src/ui/game/CGTooltip.cpp | 4 ++++ src/ui/game/CGTooltip.hpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/ui/game/CGTooltip.cpp b/src/ui/game/CGTooltip.cpp index ceb5bfa..328dd4b 100644 --- a/src/ui/game/CGTooltip.cpp +++ b/src/ui/game/CGTooltip.cpp @@ -31,3 +31,7 @@ void CGTooltip::RegisterScriptMethods(lua_State* L) { CGTooltip::CGTooltip(CSimpleFrame* parent) : CSimpleFrame(parent) { // TODO } + +int32_t CGTooltip::GetScriptMetaTable() { + return CGTooltip::s_metatable; +} diff --git a/src/ui/game/CGTooltip.hpp b/src/ui/game/CGTooltip.hpp index 5b32efa..f6a5961 100644 --- a/src/ui/game/CGTooltip.hpp +++ b/src/ui/game/CGTooltip.hpp @@ -18,6 +18,9 @@ class CGTooltip : public CSimpleFrame { // Member variables // TODO + // Virtual member functions + virtual int32_t GetScriptMetaTable(); + // Member functions CGTooltip(CSimpleFrame* parent); }; From 379cbf7e6170461194158702e38d3acc2acd3623 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 19:28:48 -0600 Subject: [PATCH 104/269] feat(ui): add UIBindingsRegisterScriptFunctions --- src/ui/game/CGGameUI.cpp | 2 + src/ui/game/UIBindingsScript.cpp | 146 +++++++++++++++++++++++++++++++ src/ui/game/UIBindingsScript.hpp | 6 ++ 3 files changed, 154 insertions(+) create mode 100644 src/ui/game/UIBindingsScript.cpp create mode 100644 src/ui/game/UIBindingsScript.hpp diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 5af07f7..3c88c85 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -9,6 +9,7 @@ #include "ui/game/GMTicketInfoScript.hpp" #include "ui/game/GameScript.hpp" #include "ui/game/ScriptEvents.hpp" +#include "ui/game/UIBindingsScript.hpp" #include "ui/simple/CSimpleTop.hpp" #include "util/CStatus.hpp" #include @@ -23,6 +24,7 @@ void LoadScriptFunctions() { // TODO GameScriptRegisterFunctions(); + UIBindingsRegisterScriptFunctions(); // TODO diff --git a/src/ui/game/UIBindingsScript.cpp b/src/ui/game/UIBindingsScript.cpp new file mode 100644 index 0000000..8d488a1 --- /dev/null +++ b/src/ui/game/UIBindingsScript.cpp @@ -0,0 +1,146 @@ +#include "ui/game/UIBindingsScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t Script_GetNumBindings(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBinding(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetBinding(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetBindingSpell(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetBindingItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetBindingMacro(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetBindingClick(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetOverrideBinding(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetOverrideBindingSpell(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetOverrideBindingItem(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetOverrideBindingMacro(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetOverrideBindingClick(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ClearOverrideBindings(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBindingKey(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBindingAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBindingByKey(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RunBinding(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetCurrentBindingSet(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_LoadBindings(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SaveBindings(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetNumModifiedClickActions(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetModifiedClickAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetModifiedClick(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetModifiedClick(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsModifiedClick(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetClickFrame(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +static FrameScript_Method s_ScriptFunctions[] = { + { "GetNumBindings", &Script_GetNumBindings }, + { "GetBinding", &Script_GetBinding }, + { "SetBinding", &Script_SetBinding }, + { "SetBindingSpell", &Script_SetBindingSpell }, + { "SetBindingItem", &Script_SetBindingItem }, + { "SetBindingMacro", &Script_SetBindingMacro }, + { "SetBindingClick", &Script_SetBindingClick }, + { "SetOverrideBinding", &Script_SetOverrideBinding }, + { "SetOverrideBindingSpell", &Script_SetOverrideBindingSpell }, + { "SetOverrideBindingItem", &Script_SetOverrideBindingItem }, + { "SetOverrideBindingMacro", &Script_SetOverrideBindingMacro }, + { "SetOverrideBindingClick", &Script_SetOverrideBindingClick }, + { "ClearOverrideBindings", &Script_ClearOverrideBindings }, + { "GetBindingKey", &Script_GetBindingKey }, + { "GetBindingAction", &Script_GetBindingAction }, + { "GetBindingByKey", &Script_GetBindingByKey }, + { "RunBinding", &Script_RunBinding }, + { "GetCurrentBindingSet", &Script_GetCurrentBindingSet }, + { "LoadBindings", &Script_LoadBindings }, + { "SaveBindings", &Script_SaveBindings }, + { "GetNumModifiedClickActions", &Script_GetNumModifiedClickActions }, + { "GetModifiedClickAction", &Script_GetModifiedClickAction }, + { "SetModifiedClick", &Script_SetModifiedClick }, + { "GetModifiedClick", &Script_GetModifiedClick }, + { "IsModifiedClick", &Script_IsModifiedClick }, + { "GetClickFrame", &Script_GetClickFrame }, +}; + +void UIBindingsRegisterScriptFunctions() { + for (auto& func : s_ScriptFunctions) { + FrameScript_RegisterFunction(func.name, func.method); + } +} diff --git a/src/ui/game/UIBindingsScript.hpp b/src/ui/game/UIBindingsScript.hpp new file mode 100644 index 0000000..a74a0b9 --- /dev/null +++ b/src/ui/game/UIBindingsScript.hpp @@ -0,0 +1,6 @@ +#ifndef UI_GAME_UI_BINDINGS_SCRIPT_HPP +#define UI_GAME_UI_BINDINGS_SCRIPT_HPP + +void UIBindingsRegisterScriptFunctions(); + +#endif From cd167c54a32b6622882fa15755b83b5a9c0e038c Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 27 Jan 2026 19:31:19 -0600 Subject: [PATCH 105/269] feat(ui): store tooltip pointer in CGGameUI::Initialize --- src/ui/game/CGGameUI.cpp | 7 +++++++ src/ui/game/CGGameUI.hpp | 2 ++ 2 files changed, 9 insertions(+) diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 3c88c85..2729222 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -1,5 +1,6 @@ #include "ui/game/CGGameUI.hpp" #include "client/Client.hpp" +#include "ui/CScriptObject.hpp" #include "ui/FrameXML.hpp" #include "ui/Key.hpp" #include "ui/game/BattlefieldInfoScript.hpp" @@ -14,6 +15,7 @@ #include "util/CStatus.hpp" #include +CScriptObject* CGGameUI::s_gameTooltip; CSimpleTop* CGGameUI::s_simpleTop; void LoadScriptFunctions() { @@ -117,6 +119,11 @@ void CGGameUI::Initialize() { // TODO digest validation // TODO + + CGGameUI::s_gameTooltip = CScriptObject::GetScriptObjectByName("GameTooltip", CGTooltip::GetObjectType()); + // TODO STORM_ASSERT(CGGameUI::s_gameTooltip); + + // TODO } void CGGameUI::InitializeGame() { diff --git a/src/ui/game/CGGameUI.hpp b/src/ui/game/CGGameUI.hpp index 17b86f1..567ab2f 100644 --- a/src/ui/game/CGGameUI.hpp +++ b/src/ui/game/CGGameUI.hpp @@ -1,11 +1,13 @@ #ifndef UI_GAME_C_G_GAME_UI_HPP #define UI_GAME_C_G_GAME_UI_HPP +class CScriptObject; class CSimpleTop; class CGGameUI { public: // Static variables + static CScriptObject* s_gameTooltip; static CSimpleTop* s_simpleTop; // Static functions From bfcceed8fda9a4cbbe09e91162024b7866814dcf Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 28 Jan 2026 15:44:42 -0600 Subject: [PATCH 106/269] feat(util): add initial implementation of WowTime --- src/util/CMakeLists.txt | 1 + src/util/Time.hpp | 6 ++ src/util/time/WowTime.cpp | 166 +++++++++++++++++++++++++++++++++++++ src/util/time/WowTime.hpp | 29 +++++++ test/CMakeLists.txt | 1 + test/util/time/WowTime.cpp | 146 ++++++++++++++++++++++++++++++++ 6 files changed, 349 insertions(+) create mode 100644 src/util/Time.hpp create mode 100644 src/util/time/WowTime.cpp create mode 100644 src/util/time/WowTime.hpp create mode 100644 test/util/time/WowTime.cpp diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index a0696b6..3c2f020 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -1,6 +1,7 @@ file(GLOB PRIVATE_SOURCES "*.cpp" "guid/*.cpp" + "time/*.cpp" ) if(WHOA_SYSTEM_MAC) diff --git a/src/util/Time.hpp b/src/util/Time.hpp new file mode 100644 index 0000000..8edb391 --- /dev/null +++ b/src/util/Time.hpp @@ -0,0 +1,6 @@ +#ifndef UTIL_TIME_HPP +#define UTIL_TIME_HPP + +#include "util/time/WowTime.hpp" + +#endif diff --git a/src/util/time/WowTime.cpp b/src/util/time/WowTime.cpp new file mode 100644 index 0000000..3005a3c --- /dev/null +++ b/src/util/time/WowTime.cpp @@ -0,0 +1,166 @@ +#include "util/time/WowTime.hpp" +#include +#include + +static const char* s_weekdays[] = { + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", +}; + +void WowTime::WowDecodeTime(uint32_t value, int32_t* minute, int32_t* hour, int32_t* weekday, int32_t* monthday, int32_t* month, int32_t* year, int32_t* flags) { + // Minute: bits 0-5 (6 bits, max 63) + if (minute) { + auto m = static_cast(value & 63); + *minute = (m == 63) ? -1 : m; + } + + // Hour: bits 6-10 (5 bits, max 31) + if (hour) { + auto h = static_cast((value >> 6) & 31); + *hour = (h == 31) ? -1 : h; + } + + // Weekday: bits 11-13 (3 bits, max 7) + if (weekday) { + auto wd = static_cast((value >> 11) & 7); + *weekday = (wd == 7) ? -1 : wd; + } + + // Month day: bits 14-19 (6 bits, max 63) + if (monthday) { + auto md = static_cast((value >> 14) & 63); + *monthday = (md == 63) ? -1 : md; + } + + // Month: bits 20-23 (4 bits, max 15) + if (month) { + auto mo = static_cast((value >> 20) & 15); + *month = (mo == 15) ? -1 : mo; + } + + // Year: bits 24-28 (5 bits, max 31) + if (year) { + auto y = static_cast((value >> 24) & 31); + *year = (y == 31) ? -1 : y; + } + + // Flags: bits 29-30 (2 bits, max 3) + if (flags) { + auto f = static_cast((value >> 29) & 3); + *flags = (f == 3) ? -1 : f; + } +} + +void WowTime::WowDecodeTime(uint32_t value, WowTime* time) { + WowTime::WowDecodeTime( + value, + &time->m_minute, + &time->m_hour, + &time->m_weekday, + &time->m_monthday, + &time->m_month, + &time->m_year, + &time->m_flags + ); +} + +void WowTime::WowEncodeTime(uint32_t& value, int32_t minute, int32_t hour, int32_t weekday, int32_t monthday, int32_t month, int32_t year, int32_t flags) { + STORM_ASSERT(minute == -1 || (minute >= 0 && minute < 60)); + STORM_ASSERT(hour == -1 || (hour >= 0 && hour < 24)); + STORM_ASSERT(weekday == -1 || (weekday >= 0 && weekday < 7)); + STORM_ASSERT(monthday == -1 || (monthday >= 0 && monthday < 32)); + STORM_ASSERT(month == -1 || (month >= 0 && month < 12)); + STORM_ASSERT(year == -1 || year >= 0 && year <= ((1 << 5) - 1)); + STORM_ASSERT(flags >= 0 && flags <= ((1 << 2) - 1)); + + value = ((flags & 3) << 29) // Flags: bits 29-30 (2 bits, max 3) + | ((year & 31) << 24) // Year: bits 24-28 (5 bits, max 31) + | ((month & 15) << 20) // Month: bits 20-23 (4 bits, max 15) + | ((monthday & 63) << 14) // Month day: bits 14-19 (6 bits, max 63) + | ((weekday & 7) << 11) // Weekday: bits 11-13 (3 bits, max 7) + | ((hour & 31) << 6) // Hour: bits 6-10 (5 bits, max 31) + | (minute & 63); // Minute: bits 0-5 (6 bits, max 63) +} + +void WowTime::WowEncodeTime(uint32_t& value, const WowTime* time) { + WowTime::WowEncodeTime( + value, + time->m_minute, + time->m_hour, + time->m_weekday, + time->m_monthday, + time->m_month, + time->m_year, + time->m_flags + ); +} + +char* WowTime::WowGetTimeString(WowTime* time, char* str, int32_t len) { + uint32_t encoded; + WowTime::WowEncodeTime(encoded, time); + + if (encoded == 0) { + SStrPrintf(str, len, "Not Set"); + return str; + } + + char yearStr[8]; + char monthStr[8]; + char monthdayStr[8]; + char weekdayStr[8]; + char hourStr[8]; + char minuteStr[8]; + + if (time->m_year >= 0) { + SStrPrintf(yearStr, sizeof(yearStr), "%i", time->m_year + 2000); + } else { + SStrPrintf(yearStr, sizeof(yearStr), "A"); + } + + if (time->m_month >= 0) { + SStrPrintf(monthStr, sizeof(monthStr), "%i", time->m_month + 1); + } else { + SStrPrintf(monthStr, sizeof(monthStr), "A"); + } + + if (time->m_monthday >= 0) { + SStrPrintf(monthdayStr, sizeof(monthdayStr), "%i", time->m_monthday + 1); + } else { + SStrPrintf(monthdayStr, sizeof(monthdayStr), "A"); + } + + if (time->m_weekday >= 0) { + SStrPrintf(weekdayStr, sizeof(weekdayStr), s_weekdays[time->m_weekday]); + } else { + SStrPrintf(weekdayStr, sizeof(weekdayStr), "Any"); + } + + if (time->m_hour >= 0) { + SStrPrintf(hourStr, sizeof(hourStr), "%i", time->m_hour); + } else { + SStrPrintf(hourStr, sizeof(hourStr), "A"); + } + + if (time->m_minute >= 0) { + SStrPrintf(minuteStr, sizeof(minuteStr), "%2.2i", time->m_minute); + } else { + SStrPrintf(minuteStr, sizeof(minuteStr), "A"); + } + + SStrPrintf(str, len, "%s/%s/%s (%s) %s:%s", monthStr, monthdayStr, yearStr, weekdayStr, hourStr, minuteStr); + + return str; +} + +int32_t WowTime::GetHourAndMinutes() { + if (this->m_hour < 0 || this->m_minute < 0) { + return 0; + } + + return this->m_hour * 60 + this->m_minute; +} diff --git a/src/util/time/WowTime.hpp b/src/util/time/WowTime.hpp new file mode 100644 index 0000000..b4931c6 --- /dev/null +++ b/src/util/time/WowTime.hpp @@ -0,0 +1,29 @@ +#ifndef UTIL_TIME_WOW_TIME_HPP +#define UTIL_TIME_WOW_TIME_HPP + +#include + +class WowTime { + public: + // Static functions + static void WowDecodeTime(uint32_t value, int32_t* minute, int32_t* hour, int32_t* weekday, int32_t* monthday, int32_t* month, int32_t* year, int32_t* flags); + static void WowDecodeTime(uint32_t value, WowTime* time); + static void WowEncodeTime(uint32_t& value, int32_t minute, int32_t hour, int32_t weekday, int32_t monthday, int32_t month, int32_t year, int32_t flags); + static void WowEncodeTime(uint32_t& value, const WowTime* time); + static char* WowGetTimeString(WowTime* time, char* str, int32_t len); + + // Member variables + int32_t m_minute = -1; + int32_t m_hour = -1; + int32_t m_weekday = -1; + int32_t m_monthday = -1; + int32_t m_month = -1; + int32_t m_year = -1; + int32_t m_flags = 0x0; + int32_t m_holidayOffset = 0; + + // Member functions + int32_t GetHourAndMinutes(); +}; + +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a2292d6..519fe25 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,6 +5,7 @@ if(WHOA_SYSTEM_MAC) "gx/*.cpp" "gx/font/*.cpp" "util/*.cpp" + "util/time/*.cpp" ) set_source_files_properties(${PRIVATE_SOURCES} diff --git a/test/util/time/WowTime.cpp b/test/util/time/WowTime.cpp new file mode 100644 index 0000000..b76a5ed --- /dev/null +++ b/test/util/time/WowTime.cpp @@ -0,0 +1,146 @@ +#include "util/time/WowTime.hpp" +#include "catch.hpp" +#include "storm/String.hpp" + +TEST_CASE("WowTime::WowTime", "[util]") { + SECTION("constructs correctly") { + WowTime time; + + CHECK(time.m_minute == -1); + CHECK(time.m_hour == -1); + CHECK(time.m_weekday == -1); + CHECK(time.m_monthday == -1); + CHECK(time.m_month == -1); + CHECK(time.m_year == -1); + CHECK(time.m_flags == 0x0); + CHECK(time.m_holidayOffset == 0); + } +} + +TEST_CASE("WowTime::WowDecodeTime", "[util]") { + SECTION("decodes 1234567890 as expected") { + uint32_t value = 1234567890; + WowTime time; + + WowTime::WowDecodeTime(value, &time.m_minute, &time.m_hour, &time.m_weekday, &time.m_monthday, &time.m_month, &time.m_year, &time.m_flags); + + CHECK(time.m_minute == 18); + CHECK(time.m_hour == 11); + CHECK(time.m_weekday == 0); + CHECK(time.m_monthday == 24); + CHECK(time.m_month == 9); + CHECK(time.m_year == 9); + CHECK(time.m_flags == 0x2); + } + + SECTION("decodes 0xFFFFFFFF as expected") { + uint32_t value = 0xFFFFFFFF; + WowTime time; + + WowTime::WowDecodeTime(value, &time.m_minute, &time.m_hour, &time.m_weekday, &time.m_monthday, &time.m_month, &time.m_year, &time.m_flags); + + CHECK(time.m_minute == -1); + CHECK(time.m_hour == -1); + CHECK(time.m_weekday == -1); + CHECK(time.m_monthday == -1); + CHECK(time.m_month == -1); + CHECK(time.m_year == -1); + CHECK(time.m_flags == -1); + } +} + +TEST_CASE("WowTime::WowEncodeTime", "[util]") { + SECTION("encodes 10/25/2009 (Sun) 11:18 with flag 0x2 set as expected") { + uint32_t value = 0; + + WowTime time; + time.m_minute = 18; + time.m_hour = 11; + time.m_weekday = 0; + time.m_monthday = 24; + time.m_month = 9; + time.m_year = 9; + time.m_flags = 0x2; + + WowTime::WowEncodeTime(value, &time); + + REQUIRE(value == 1234567890); + } + + SECTION("encodes empty time as expected") { + uint32_t value = 0; + WowTime time; + + WowTime::WowEncodeTime(value, &time); + + REQUIRE(value == 0x1FFFFFFF); + } + + SECTION("encodes, decodes, and reencodes as expected") { + uint32_t value = 0; + + WowTime time1; + time1.m_minute = 18; + time1.m_hour = 11; + time1.m_weekday = 0; + time1.m_monthday = 24; + time1.m_month = 9; + time1.m_year = 9; + time1.m_flags = 0x2; + + WowTime time2; + + CHECK(time2.m_minute != time1.m_minute); + CHECK(time2.m_hour != time1.m_hour); + CHECK(time2.m_weekday != time1.m_weekday); + CHECK(time2.m_monthday != time1.m_monthday); + CHECK(time2.m_month != time1.m_month); + CHECK(time2.m_year != time1.m_year); + CHECK(time2.m_flags != time1.m_flags); + + WowTime::WowEncodeTime(value, &time1); + WowTime::WowDecodeTime(value, &time2); + + CHECK(time2.m_minute == time1.m_minute); + CHECK(time2.m_hour == time1.m_hour); + CHECK(time2.m_weekday == time1.m_weekday); + CHECK(time2.m_monthday == time1.m_monthday); + CHECK(time2.m_month == time1.m_month); + CHECK(time2.m_year == time1.m_year); + CHECK(time2.m_flags == time1.m_flags); + } +} + +TEST_CASE("WowTime::WowGetTimeString", "[util]") { + SECTION("gets expected string") { + WowTime time; + time.m_minute = 18; + time.m_hour = 11; + time.m_weekday = 0; + time.m_monthday = 24; + time.m_month = 9; + time.m_year = 9; + time.m_flags = 0x2; + + char buf[128]; + auto timeStr = WowTime::WowGetTimeString(&time, buf, sizeof(buf)); + + REQUIRE(!SStrCmp(timeStr, "10/25/2009 (Sun) 11:18")); + } +} + +TEST_CASE("WowTime::GetHourAndMinutes", "[util]") { + SECTION("gets expected hour and minutes for default constructed time") { + WowTime time; + + REQUIRE(time.GetHourAndMinutes() == 0); + } + + SECTION("gets expected hour and minutes for 11:18") { + WowTime time; + time.m_minute = 18; + time.m_hour = 11; + + REQUIRE(time.GetHourAndMinutes() == 11 * 60 + 18); + } +} From 335bd21a26ae5ee6d40302ecd30c439bb02512a1 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 28 Jan 2026 18:50:12 -0600 Subject: [PATCH 107/269] feat(util): add WowTime::SetHourAndMinutes --- src/util/time/WowTime.cpp | 5 +++++ src/util/time/WowTime.hpp | 1 + test/util/time/WowTime.cpp | 10 ++++++++++ 3 files changed, 16 insertions(+) diff --git a/src/util/time/WowTime.cpp b/src/util/time/WowTime.cpp index 3005a3c..7abdd9d 100644 --- a/src/util/time/WowTime.cpp +++ b/src/util/time/WowTime.cpp @@ -164,3 +164,8 @@ int32_t WowTime::GetHourAndMinutes() { return this->m_hour * 60 + this->m_minute; } + +void WowTime::SetHourAndMinutes(int32_t minutes) { + this->m_hour = minutes / 60; + this->m_minute = minutes % 60; +} diff --git a/src/util/time/WowTime.hpp b/src/util/time/WowTime.hpp index b4931c6..f363ebe 100644 --- a/src/util/time/WowTime.hpp +++ b/src/util/time/WowTime.hpp @@ -24,6 +24,7 @@ class WowTime { // Member functions int32_t GetHourAndMinutes(); + void SetHourAndMinutes(int32_t minutes); }; #endif diff --git a/test/util/time/WowTime.cpp b/test/util/time/WowTime.cpp index b76a5ed..d6cb15b 100644 --- a/test/util/time/WowTime.cpp +++ b/test/util/time/WowTime.cpp @@ -144,3 +144,13 @@ TEST_CASE("WowTime::GetHourAndMinutes", "[util]") { REQUIRE(time.GetHourAndMinutes() == 11 * 60 + 18); } } + +TEST_CASE("WowTime::SetHourAndMinutes", "[util]") { + SECTION("sets expected hour and minutes for 11:18") { + WowTime time; + time.SetHourAndMinutes(11 * 60 + 18); + + CHECK(time.m_hour == 11); + CHECK(time.m_minute == 18); + } +} From 661b77091fca49f1c2e1d57741bc06ad817e1081 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 28 Jan 2026 18:56:12 -0600 Subject: [PATCH 108/269] feat(util): add WowTime::SetHourAndMinute overload --- src/util/time/WowTime.cpp | 11 +++++++++++ src/util/time/WowTime.hpp | 1 + test/util/time/WowTime.cpp | 13 +++++++++++++ 3 files changed, 25 insertions(+) diff --git a/src/util/time/WowTime.cpp b/src/util/time/WowTime.cpp index 7abdd9d..65534ea 100644 --- a/src/util/time/WowTime.cpp +++ b/src/util/time/WowTime.cpp @@ -169,3 +169,14 @@ void WowTime::SetHourAndMinutes(int32_t minutes) { this->m_hour = minutes / 60; this->m_minute = minutes % 60; } + +int32_t WowTime::SetHourAndMinutes(uint32_t hour, uint32_t minutes) { + if (hour >= 24 || minutes >= 60) { + return 0; + } + + this->m_hour = hour; + this->m_minute = minutes; + + return 1; +} diff --git a/src/util/time/WowTime.hpp b/src/util/time/WowTime.hpp index f363ebe..125c48b 100644 --- a/src/util/time/WowTime.hpp +++ b/src/util/time/WowTime.hpp @@ -25,6 +25,7 @@ class WowTime { // Member functions int32_t GetHourAndMinutes(); void SetHourAndMinutes(int32_t minutes); + int32_t SetHourAndMinutes(uint32_t hour, uint32_t minutes); }; #endif diff --git a/test/util/time/WowTime.cpp b/test/util/time/WowTime.cpp index d6cb15b..640bdf1 100644 --- a/test/util/time/WowTime.cpp +++ b/test/util/time/WowTime.cpp @@ -152,5 +152,18 @@ TEST_CASE("WowTime::SetHourAndMinutes", "[util]") { CHECK(time.m_hour == 11); CHECK(time.m_minute == 18); + + time.SetHourAndMinutes(11, 18); + + CHECK(time.m_hour == 11); + CHECK(time.m_minute == 18); + } + + SECTION("does not set invalid hour and minutes") { + WowTime time; + + CHECK(time.SetHourAndMinutes(25, 61) == 0); + CHECK(time.m_hour == -1); + CHECK(time.m_minute == -1); } } From aed2aebb66b025862d0805c4961568f6b3faa8bd Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 28 Jan 2026 20:13:11 -0600 Subject: [PATCH 109/269] feat(util): add WowTime::AddDays --- src/util/time/WowTime.cpp | 54 ++++++++++++++++++++++++++++++++++++++ src/util/time/WowTime.hpp | 1 + test/util/time/WowTime.cpp | 21 +++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/src/util/time/WowTime.cpp b/src/util/time/WowTime.cpp index 65534ea..55ae2e4 100644 --- a/src/util/time/WowTime.cpp +++ b/src/util/time/WowTime.cpp @@ -1,6 +1,7 @@ #include "util/time/WowTime.hpp" #include #include +#include static const char* s_weekdays[] = { "Sun", @@ -157,6 +158,59 @@ char* WowTime::WowGetTimeString(WowTime* time, char* str, int32_t len) { return str; } +void WowTime::AddDays(int32_t days, bool includeTime) { + // Validate date + + if (this->m_year < 0 || this->m_month < 0 || this->m_monthday < 0) { + return; + } + + // Convert WowTime to tm + + tm t = {}; + + t.tm_year = this->m_year + 100; // WowTime year is years since 2000; tm_year is years since 1900 + t.tm_mon = this->m_month; // WowTime month and tm_mon are both 0-based + t.tm_mday = this->m_monthday + 1; // WowTime monthday is 0-based; tm_mday is 1-based + t.tm_isdst = -1; // Let mktime determine DST + + if (includeTime) { + t.tm_hour = this->m_hour; + t.tm_min = this->m_minute; + } + + // Convert tm to time_t and add the specified days + + auto time = mktime(&t); + time += days * 86400; + + + if (!includeTime) { + time += 3600; // Tack on hour to ensure DST boundaries don't muck with days added + } + + // Convert adjusted time back to tm + + auto t_ = localtime(&time); + if (t_) { + t = *t_; + } else { + t = {}; + } + + // Convert adjusted tm back to WowTime + + this->m_year = t.tm_year - 100; + this->m_month = t.tm_mon; + this->m_monthday = t.tm_mday - 1; + this->m_weekday = t.tm_wday; + + if (includeTime) { + this->m_hour = t.tm_hour; + this->m_minute = t.tm_min; + } +} + int32_t WowTime::GetHourAndMinutes() { if (this->m_hour < 0 || this->m_minute < 0) { return 0; diff --git a/src/util/time/WowTime.hpp b/src/util/time/WowTime.hpp index 125c48b..f931e07 100644 --- a/src/util/time/WowTime.hpp +++ b/src/util/time/WowTime.hpp @@ -23,6 +23,7 @@ class WowTime { int32_t m_holidayOffset = 0; // Member functions + void AddDays(int32_t days, bool includeTime); int32_t GetHourAndMinutes(); void SetHourAndMinutes(int32_t minutes); int32_t SetHourAndMinutes(uint32_t hour, uint32_t minutes); diff --git a/test/util/time/WowTime.cpp b/test/util/time/WowTime.cpp index 640bdf1..f30b7f5 100644 --- a/test/util/time/WowTime.cpp +++ b/test/util/time/WowTime.cpp @@ -129,6 +129,27 @@ TEST_CASE("WowTime::WowGetTimeString", "[util]") { } } +TEST_CASE("WowTime::AddDays", "[util]") { + SECTION("adds 1 day to 1/28/2026") { + WowTime time; + time.m_minute = 18; + time.m_hour = 11; + time.m_weekday = 3; + time.m_monthday = 27; + time.m_month = 0; + time.m_year = 26; + + time.AddDays(1, false); + + CHECK(time.m_minute == 18); + CHECK(time.m_hour == 11); + CHECK(time.m_weekday == 4); + CHECK(time.m_monthday == 28); + CHECK(time.m_month == 0); + CHECK(time.m_year == 26); + } +} + TEST_CASE("WowTime::GetHourAndMinutes", "[util]") { SECTION("gets expected hour and minutes for default constructed time") { WowTime time; From 1d91a4946287d49d815a4071182683e2889aa8c0 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 28 Jan 2026 20:39:49 -0600 Subject: [PATCH 110/269] feat(util): add initial implementation of CGameTime --- src/util/Time.hpp | 1 + src/util/time/CGameTime.cpp | 29 +++++++++++++++++++++++++++++ src/util/time/CGameTime.hpp | 29 +++++++++++++++++++++++++++++ test/util/time/CGameTime.cpp | 28 ++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+) create mode 100644 src/util/time/CGameTime.cpp create mode 100644 src/util/time/CGameTime.hpp create mode 100644 test/util/time/CGameTime.cpp diff --git a/src/util/Time.hpp b/src/util/Time.hpp index 8edb391..db18ed3 100644 --- a/src/util/Time.hpp +++ b/src/util/Time.hpp @@ -1,6 +1,7 @@ #ifndef UTIL_TIME_HPP #define UTIL_TIME_HPP +#include "util/time/CGameTime.hpp" #include "util/time/WowTime.hpp" #endif diff --git a/src/util/time/CGameTime.cpp b/src/util/time/CGameTime.cpp new file mode 100644 index 0000000..94810ab --- /dev/null +++ b/src/util/time/CGameTime.cpp @@ -0,0 +1,29 @@ +#include "util/time/CGameTime.hpp" +#include "common/Time.hpp" + +void CGameTime::PerformCallbacks(int32_t minutes) { + // TODO +} + +void CGameTime::TickMinute() { + // Increment minute + int32_t minutes = (this->GetHourAndMinutes() + 1) % 1440; + + // Update hours and minutes + this->SetHourAndMinutes(minutes); + + // Increment day if minute crossed day boundary + if (minutes == 0) { + this->AddDays(1, false); + } + + this->m_gameMinutesElapsed++; + + this->PerformCallbacks(minutes); + + this->m_lastTickMinute = OsGetAsyncTimeMsPrecise(); + + this->uint40 = 1; + + this->m_dayProgression = this->m_gameMinutesThisTick + static_cast(minutes); +} diff --git a/src/util/time/CGameTime.hpp b/src/util/time/CGameTime.hpp new file mode 100644 index 0000000..d8f53c0 --- /dev/null +++ b/src/util/time/CGameTime.hpp @@ -0,0 +1,29 @@ +#ifndef UTIL_TIME_C_GAME_TIME_HPP +#define UTIL_TIME_C_GAME_TIME_HPP + +#include "util/time/WowTime.hpp" + +class CGameTime : public WowTime { + public: + // Public member functions + void PerformCallbacks(int32_t minutes); + void TickMinute(); + + private: + // Private member variables + uint32_t m_lastTick = 0; + int32_t m_timeBias = 0; + int32_t m_dateBias = 0; + uint32_t m_gameMinutesElapsed = 0; + float m_gameMinutesPerRealSecond = 1.0f / 60.0f; + float m_gameMinutesThisTick = 0.0f; + uint32_t m_timeDifferential = 0; + uint32_t m_lastTickMinute = 0; + uint8_t uint40 = 0; + float m_dayProgression = 0.0f; + float float48 = 0.0f; + float float4C = 0.0f; + // TODO m_callbackLists +}; + +#endif diff --git a/test/util/time/CGameTime.cpp b/test/util/time/CGameTime.cpp new file mode 100644 index 0000000..825da49 --- /dev/null +++ b/test/util/time/CGameTime.cpp @@ -0,0 +1,28 @@ +#include "util/time/CGameTime.hpp" +#include "catch.hpp" + +TEST_CASE("CGameTime::CGameTime", "[util]") { + SECTION("constructs correctly") { + CGameTime time; + + CHECK(time.m_minute == -1); + CHECK(time.m_hour == -1); + CHECK(time.m_weekday == -1); + CHECK(time.m_monthday == -1); + CHECK(time.m_month == -1); + CHECK(time.m_year == -1); + CHECK(time.m_flags == 0x0); + CHECK(time.m_holidayOffset == 0); + } +} + +TEST_CASE("CGameTime::TickMinute", "[util]") { + SECTION("ticks minute correctly") { + CGameTime time; + time.SetHourAndMinutes(0, 0); + time.TickMinute(); + + CHECK(time.m_hour == 0); + CHECK(time.m_minute == 1); + } +} From 886ababae9e7757117aa15536ac41d30e5d4e001 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 28 Jan 2026 21:31:24 -0600 Subject: [PATCH 111/269] feat(util): add CGameTime::GameTimeSetTime --- src/util/time/CGameTime.cpp | 41 ++++++++++++++++++++++++++++++++++++ src/util/time/CGameTime.hpp | 7 ++++-- test/util/time/CGameTime.cpp | 25 ++++++++++++++++------ 3 files changed, 64 insertions(+), 9 deletions(-) diff --git a/src/util/time/CGameTime.cpp b/src/util/time/CGameTime.cpp index 94810ab..6cf165c 100644 --- a/src/util/time/CGameTime.cpp +++ b/src/util/time/CGameTime.cpp @@ -1,6 +1,47 @@ #include "util/time/CGameTime.hpp" #include "common/Time.hpp" +void CGameTime::GameTimeSetTime(const WowTime& time, bool shouldTick) { + WowTime biasTime = time; + + if (this->m_timeBias) { + auto minutes = biasTime.GetHourAndMinutes() + this->m_timeBias; + + if (minutes < 0) { + minutes += 1440; + } else { + minutes %= 1440; + } + + biasTime.SetHourAndMinutes(minutes); + } + + if (this->m_dateBias) { + biasTime.AddDays(this->m_dateBias, false); + } + + static_cast(*this) = biasTime; + + if (shouldTick) { + // Rewind time by exactly one minute + if (this->m_minute != 0) { + this->m_minute--; + } else { + this->m_minute = 59; + + if (this->m_hour != 0) { + this->m_hour--; + } else { + this->m_hour = 23; + this->AddDays(-1, false); + } + } + + // Tick ahead exactly one minute (ensures callbacks fire and various counters update) + this->TickMinute(); + } +} + void CGameTime::PerformCallbacks(int32_t minutes) { // TODO } diff --git a/src/util/time/CGameTime.hpp b/src/util/time/CGameTime.hpp index d8f53c0..445dbf9 100644 --- a/src/util/time/CGameTime.hpp +++ b/src/util/time/CGameTime.hpp @@ -6,8 +6,7 @@ class CGameTime : public WowTime { public: // Public member functions - void PerformCallbacks(int32_t minutes); - void TickMinute(); + void GameTimeSetTime(const WowTime& time, bool shouldTick); private: // Private member variables @@ -24,6 +23,10 @@ class CGameTime : public WowTime { float float48 = 0.0f; float float4C = 0.0f; // TODO m_callbackLists + + // Private member functions + void PerformCallbacks(int32_t minutes); + void TickMinute(); }; #endif diff --git a/test/util/time/CGameTime.cpp b/test/util/time/CGameTime.cpp index 825da49..88dfd6d 100644 --- a/test/util/time/CGameTime.cpp +++ b/test/util/time/CGameTime.cpp @@ -16,13 +16,24 @@ TEST_CASE("CGameTime::CGameTime", "[util]") { } } -TEST_CASE("CGameTime::TickMinute", "[util]") { - SECTION("ticks minute correctly") { - CGameTime time; - time.SetHourAndMinutes(0, 0); - time.TickMinute(); +TEST_CASE("CGameTime::GameTimeSetTime", "[util]") { + SECTION("sets game time correctly") { + WowTime time; + time.m_minute = 18; + time.m_hour = 11; + time.m_weekday = 3; + time.m_monthday = 27; + time.m_month = 0; + time.m_year = 26; - CHECK(time.m_hour == 0); - CHECK(time.m_minute == 1); + CGameTime gameTime; + gameTime.GameTimeSetTime(time, true); + + CHECK(gameTime.m_minute == 18); + CHECK(gameTime.m_hour == 11); + CHECK(gameTime.m_weekday == 3); + CHECK(gameTime.m_monthday == 27); + CHECK(gameTime.m_month == 0); + CHECK(gameTime.m_year == 26); } } From 721ee527eb3291867784228827880bea86093d2f Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 28 Jan 2026 22:01:23 -0600 Subject: [PATCH 112/269] feat(util): add CGameTime::GameTimeUpdate --- src/util/time/CGameTime.cpp | 22 ++++++++++++++++++++++ src/util/time/CGameTime.hpp | 1 + test/util/time/CGameTime.cpp | 20 ++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/src/util/time/CGameTime.cpp b/src/util/time/CGameTime.cpp index 6cf165c..f0ecf39 100644 --- a/src/util/time/CGameTime.cpp +++ b/src/util/time/CGameTime.cpp @@ -42,6 +42,28 @@ void CGameTime::GameTimeSetTime(const WowTime& time, bool shouldTick) { } } +void CGameTime::GameTimeUpdate(float elapsedSec) { + this->m_gameMinutesThisTick += this->m_gameMinutesPerRealSecond * elapsedSec; + + // Skip minute ticks for time differential + if (this->m_timeDifferential != 0 && this->m_gameMinutesThisTick >= 1.0f) { + auto minutesToConsume = static_cast(this->m_gameMinutesThisTick); + + // Clamp to differential + if (this->m_timeDifferential < minutesToConsume) { + minutesToConsume = this->m_timeDifferential; + } + + this->m_timeDifferential -= minutesToConsume; + this->m_gameMinutesThisTick -= static_cast(minutesToConsume); + } + + while (this->m_gameMinutesThisTick >= 1.0f) { + this->m_gameMinutesThisTick -= 1.0f; + this->TickMinute(); + } +} + void CGameTime::PerformCallbacks(int32_t minutes) { // TODO } diff --git a/src/util/time/CGameTime.hpp b/src/util/time/CGameTime.hpp index 445dbf9..ed02236 100644 --- a/src/util/time/CGameTime.hpp +++ b/src/util/time/CGameTime.hpp @@ -7,6 +7,7 @@ class CGameTime : public WowTime { public: // Public member functions void GameTimeSetTime(const WowTime& time, bool shouldTick); + void GameTimeUpdate(float elapsedSec); private: // Private member variables diff --git a/test/util/time/CGameTime.cpp b/test/util/time/CGameTime.cpp index 88dfd6d..4f1d20c 100644 --- a/test/util/time/CGameTime.cpp +++ b/test/util/time/CGameTime.cpp @@ -37,3 +37,23 @@ TEST_CASE("CGameTime::GameTimeSetTime", "[util]") { CHECK(gameTime.m_year == 26); } } + +TEST_CASE("CGameTime::GameTimeUpdate", "[util]") { + SECTION("updates game time correctly") { + WowTime time; + time.m_minute = 18; + time.m_hour = 11; + time.m_weekday = 3; + time.m_monthday = 27; + time.m_month = 0; + time.m_year = 26; + + CGameTime gameTime; + gameTime.GameTimeSetTime(time, true); + + gameTime.GameTimeUpdate(60.0f); + + CHECK(gameTime.m_hour == 11); + CHECK(gameTime.m_minute == 19); + } +} From efd3f8e8f4b0f6c3898631a18e9d29bf8b0ee0fa Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 29 Jan 2026 07:33:50 -0600 Subject: [PATCH 113/269] feat(client): add ClientGameTimeTickHandler --- src/client/Client.cpp | 17 ++++++++++++++--- src/client/Client.hpp | 3 +++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/client/Client.cpp b/src/client/Client.cpp index a193f64..98a7dca 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -20,6 +20,7 @@ #include "ui/FrameXML.hpp" #include "ui/Game.hpp" #include "util/Random.hpp" +#include "util/Time.hpp" #include "world/World.hpp" #include #include @@ -30,6 +31,8 @@ CVar* Client::g_accountNameVar; CVar* Client::g_accountListVar; HEVENTCONTEXT Client::g_clientEventContext; +CGameTime g_clientGameTime; + static CVar* s_desktopGammaCvar; static CVar* s_gammaCvar; static CVar* s_textureCacheSizeCvar; @@ -70,10 +73,18 @@ void BaseInitializeGlobal() { PropInitialize(); } +int32_t ClientGameTimeTickHandler(const void* data, void* param) { + STORM_ASSERT(data); + + g_clientGameTime.GameTimeUpdate(static_cast(data)->elapsedSec); + + return 1; +} + int32_t ClientIdle(const void* data, void* param) { - // TODO - // ClientGameTimeTickHandler(data, param); - // Player_C_ZoneUpdateHandler(data, param); + ClientGameTimeTickHandler(data, nullptr); + + // TODO Player_C_ZoneUpdateHandler(data, nullptr); return 1; } diff --git a/src/client/Client.hpp b/src/client/Client.hpp index fba112d..92365b8 100644 --- a/src/client/Client.hpp +++ b/src/client/Client.hpp @@ -5,6 +5,7 @@ #include class CVar; +class CGameTime; namespace Client { extern CVar* g_accountNameVar; @@ -12,6 +13,8 @@ namespace Client { extern HEVENTCONTEXT g_clientEventContext; } +extern CGameTime g_clientGameTime; + void ClientInitializeGame(uint32_t mapId, C3Vector position); void ClientPostClose(int32_t a1); From 50a24e8564f84bacaf6f0cea9c66672853abdf1d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 29 Jan 2026 07:37:43 -0600 Subject: [PATCH 114/269] feat(ui): implement Script_GetGameTime --- src/client/Client.cpp | 1 - src/client/Client.hpp | 2 +- src/ui/ScriptFunctionsSystem.cpp | 9 +++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/client/Client.cpp b/src/client/Client.cpp index 98a7dca..af9a2dd 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -20,7 +20,6 @@ #include "ui/FrameXML.hpp" #include "ui/Game.hpp" #include "util/Random.hpp" -#include "util/Time.hpp" #include "world/World.hpp" #include #include diff --git a/src/client/Client.hpp b/src/client/Client.hpp index 92365b8..49dac65 100644 --- a/src/client/Client.hpp +++ b/src/client/Client.hpp @@ -2,10 +2,10 @@ #define CLIENT_CLIENT_HPP #include "event/Event.hpp" +#include "util/Time.hpp" #include class CVar; -class CGameTime; namespace Client { extern CVar* g_accountNameVar; diff --git a/src/ui/ScriptFunctionsSystem.cpp b/src/ui/ScriptFunctionsSystem.cpp index bc484aa..0b4c225 100644 --- a/src/ui/ScriptFunctionsSystem.cpp +++ b/src/ui/ScriptFunctionsSystem.cpp @@ -1,4 +1,5 @@ #include "ui/FrameScript.hpp" +#include "client/Client.hpp" #include "ui/ScriptFunctionsShared.hpp" #include "ui/Types.hpp" #include "util/Lua.hpp" @@ -14,10 +15,10 @@ int32_t Script_GetTime(lua_State* L) { } int32_t Script_GetGameTime(lua_State* L) { - // TODO real implementation - lua_pushnumber(L, 1.0); - lua_pushnumber(L, 15.0); - WHOA_UNIMPLEMENTED(2); + lua_pushnumber(L, g_clientGameTime.m_hour); + lua_pushnumber(L, g_clientGameTime.m_minute); + + return 2; } int32_t Script_ConsoleExec(lua_State* L) { From 6e7c267d3e8462a12e047a1c9be3972fa12b77c7 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 29 Jan 2026 07:52:43 -0600 Subject: [PATCH 115/269] feat(client): add ClientInitializeGameTime --- src/client/Client.cpp | 11 +++++++++++ src/client/ClientHandlers.cpp | 21 +++++++++++++++++++++ src/client/ClientHandlers.hpp | 10 ++++++++++ 3 files changed, 42 insertions(+) diff --git a/src/client/Client.cpp b/src/client/Client.cpp index af9a2dd..069bd3f 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -80,6 +80,16 @@ int32_t ClientGameTimeTickHandler(const void* data, void* param) { return 1; } +void ClientInitializeGameTime() { + ClientServices::SetMessageHandler(SMSG_GAME_SPEED_SET, &ReceiveNewGameSpeed, nullptr); + ClientServices::SetMessageHandler(SMSG_LOGIN_SET_TIME_SPEED, &ReceiveNewTimeSpeed, nullptr); + ClientServices::SetMessageHandler(SMSG_GAME_TIME_UPDATE, &ReceiveGameTimeUpdate, nullptr); + ClientServices::SetMessageHandler(SMSG_SERVERTIME, &ReceiveServerTime, nullptr); + ClientServices::SetMessageHandler(SMSG_GAME_TIME_SET, &ReceiveNewGameTime, nullptr); + + // TODO initialize s_forcedChangeCallbacks +} + int32_t ClientIdle(const void* data, void* param) { ClientGameTimeTickHandler(data, nullptr); @@ -101,6 +111,7 @@ void ClientInitializeGame(uint32_t mapId, C3Vector position) { // TODO EventRegister(EVENT_ID_IDLE, ClientIdle); + ClientInitializeGameTime(); // TODO diff --git a/src/client/ClientHandlers.cpp b/src/client/ClientHandlers.cpp index 1eeab84..ecd90c1 100644 --- a/src/client/ClientHandlers.cpp +++ b/src/client/ClientHandlers.cpp @@ -2,6 +2,7 @@ #include "console/Console.hpp" #include "db/Db.hpp" #include "object/Client.hpp" +#include "util/Unimplemented.hpp" #include "world/World.hpp" #include #include @@ -77,6 +78,26 @@ int32_t PlayedTimeHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataSto return 0; } +int32_t ReceiveGameTimeUpdate(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t ReceiveNewGameSpeed(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t ReceiveNewGameTime(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t ReceiveNewTimeSpeed(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t ReceiveServerTime(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) { + WHOA_UNIMPLEMENTED(0); +} + int32_t TransferAbortedHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) { // TODO diff --git a/src/client/ClientHandlers.hpp b/src/client/ClientHandlers.hpp index 4cb756c..47bc1f8 100644 --- a/src/client/ClientHandlers.hpp +++ b/src/client/ClientHandlers.hpp @@ -14,6 +14,16 @@ int32_t NotifyHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* int32_t PlayedTimeHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg); +int32_t ReceiveGameTimeUpdate(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg); + +int32_t ReceiveNewGameSpeed(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg); + +int32_t ReceiveNewGameTime(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg); + +int32_t ReceiveNewTimeSpeed(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg); + +int32_t ReceiveServerTime(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg); + int32_t TransferAbortedHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg); int32_t TransferPendingHandler(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg); From 53b26169f3dbeedfbe84d35eb9d42b82b6558dbc Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 29 Jan 2026 08:46:57 -0600 Subject: [PATCH 116/269] feat(util): add CGameTime::GameTimeSetMinutesPerSecond --- src/util/time/CGameTime.cpp | 14 ++++++++++++++ src/util/time/CGameTime.hpp | 7 ++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/util/time/CGameTime.cpp b/src/util/time/CGameTime.cpp index f0ecf39..e91a35d 100644 --- a/src/util/time/CGameTime.cpp +++ b/src/util/time/CGameTime.cpp @@ -1,6 +1,20 @@ #include "util/time/CGameTime.hpp" #include "common/Time.hpp" +float CGameTime::GameTimeSetMinutesPerSecond(float minutesPerSec) { + float oldMinutesPerSec = this->m_gameMinutesPerRealSecond; + + if (minutesPerSec > CGameTime::MAX_SPEED) { + minutesPerSec = CGameTime::MAX_SPEED; + } else if (minutesPerSec < CGameTime::MIN_SPEED) { + minutesPerSec = CGameTime::MIN_SPEED; + } + + this->m_gameMinutesPerRealSecond = minutesPerSec; + + return oldMinutesPerSec; +} + void CGameTime::GameTimeSetTime(const WowTime& time, bool shouldTick) { WowTime biasTime = time; diff --git a/src/util/time/CGameTime.hpp b/src/util/time/CGameTime.hpp index ed02236..8d18b5d 100644 --- a/src/util/time/CGameTime.hpp +++ b/src/util/time/CGameTime.hpp @@ -5,7 +5,12 @@ class CGameTime : public WowTime { public: + // Public static variables + static constexpr float MIN_SPEED = 1.0f / 60.0f; + static constexpr float MAX_SPEED = 60.0f; + // Public member functions + float GameTimeSetMinutesPerSecond(float minutesPerSec); void GameTimeSetTime(const WowTime& time, bool shouldTick); void GameTimeUpdate(float elapsedSec); @@ -15,7 +20,7 @@ class CGameTime : public WowTime { int32_t m_timeBias = 0; int32_t m_dateBias = 0; uint32_t m_gameMinutesElapsed = 0; - float m_gameMinutesPerRealSecond = 1.0f / 60.0f; + float m_gameMinutesPerRealSecond = MIN_SPEED; float m_gameMinutesThisTick = 0.0f; uint32_t m_timeDifferential = 0; uint32_t m_lastTickMinute = 0; From 0bb3ac157fa00303d211a5b4e9d5f44009b6f1a5 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 29 Jan 2026 08:47:19 -0600 Subject: [PATCH 117/269] feat(client): implement ReceiveNewTimeSpeed --- src/client/ClientHandlers.cpp | 36 +++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/client/ClientHandlers.cpp b/src/client/ClientHandlers.cpp index ecd90c1..70c4adb 100644 --- a/src/client/ClientHandlers.cpp +++ b/src/client/ClientHandlers.cpp @@ -1,12 +1,14 @@ #include "client/ClientHandlers.hpp" +#include "Client.hpp" #include "console/Console.hpp" #include "db/Db.hpp" #include "object/Client.hpp" +#include "util/Time.hpp" #include "util/Unimplemented.hpp" #include "world/World.hpp" #include -#include #include +#include static float s_newFacing; static C3Vector s_newPosition; @@ -91,7 +93,37 @@ int32_t ReceiveNewGameTime(void* param, NETMESSAGE msgId, uint32_t time, CDataSt } int32_t ReceiveNewTimeSpeed(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) { - WHOA_UNIMPLEMENTED(0); + uint32_t encodedTime; + msg->Get(encodedTime); + + float newSpeed; + msg->Get(newSpeed); + + uint32_t holidayOffset; + msg->Get(holidayOffset); + + if (!msg->IsRead()) { + STORM_ASSERT(msg->IsFinal()); + // TODO ConsoleWriteA("Malformed message received: Id = %d, Len = %d, Read = %d\n", DEFAULT_COLOR, msgId, msg->Size(), msg->Tell()); + + return 0; + } + + WowTime newTime; + WowTime::WowDecodeTime(encodedTime, &newTime); + newTime.m_holidayOffset = holidayOffset; + + g_clientGameTime.GameTimeSetTime(newTime, true); + + // TODO UpdateTime(); + + auto oldSpeed = g_clientGameTime.GameTimeSetMinutesPerSecond(newSpeed); + + char logStr[256]; + SStrPrintf(logStr, sizeof(logStr), "Gamespeed set from %.03f to %.03f", oldSpeed, newSpeed); + ConsoleWrite(logStr, DEFAULT_COLOR); + + return 1; } int32_t ReceiveServerTime(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg) { From 26522016e06053fa88b0c27b2a455f135bfe03e2 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 29 Jan 2026 12:46:31 -0600 Subject: [PATCH 118/269] feat(ui): implement Script_GetCVar --- src/ui/game/GameScript.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/ui/game/GameScript.cpp b/src/ui/game/GameScript.cpp index 111b13a..236b5b9 100644 --- a/src/ui/game/GameScript.cpp +++ b/src/ui/game/GameScript.cpp @@ -133,7 +133,21 @@ int32_t Script_SetCVar(lua_State* L) { } int32_t Script_GetCVar(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isstring(L, 1)) { + luaL_error(L, "Usage: GetCVar(\"cvar\")"); + return 0; + } + + auto varName = lua_tostring(L, 1); + auto var = CVar::LookupRegistered(varName); + + if (var && !(var->m_flags & 0x40)) { + lua_pushstring(L, var->GetString()); + } else { + lua_pushnil(L); + } + + return 1; } int32_t Script_GetCVarBool(lua_State* L) { From f19894ef126436ed648ab6776d8e6f8b12c01da3 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 29 Jan 2026 21:33:04 -0600 Subject: [PATCH 119/269] feat(ui): add stub implementations of remaining game frame classes --- src/ui/game/CGCharacterModelBase.cpp | 37 ++++++++++ src/ui/game/CGCharacterModelBase.hpp | 28 +++++++ src/ui/game/CGCharacterModelBaseScript.cpp | 30 ++++++++ src/ui/game/CGCharacterModelBaseScript.hpp | 10 +++ src/ui/game/CGCooldown.cpp | 37 ++++++++++ src/ui/game/CGCooldown.hpp | 28 +++++++ src/ui/game/CGCooldownScript.cpp | 35 +++++++++ src/ui/game/CGCooldownScript.hpp | 10 +++ src/ui/game/CGDressUpModelFrame.cpp | 37 ++++++++++ src/ui/game/CGDressUpModelFrame.hpp | 28 +++++++ src/ui/game/CGDressUpModelFrameScript.cpp | 25 +++++++ src/ui/game/CGDressUpModelFrameScript.hpp | 10 +++ src/ui/game/CGGameUI.cpp | 22 +++++- src/ui/game/CGMinimapFrame.cpp | 37 ++++++++++ src/ui/game/CGMinimapFrame.hpp | 28 +++++++ src/ui/game/CGMinimapFrameScript.cpp | 85 ++++++++++++++++++++++ src/ui/game/CGMinimapFrameScript.hpp | 10 +++ src/ui/game/CGQuestPOIFrame.cpp | 38 ++++++++++ src/ui/game/CGQuestPOIFrame.hpp | 28 +++++++ src/ui/game/CGQuestPOIFrameScript.cpp | 80 ++++++++++++++++++++ src/ui/game/CGQuestPOIFrameScript.hpp | 10 +++ src/ui/game/CGTabardModelFrame.cpp | 37 ++++++++++ src/ui/game/CGTabardModelFrame.hpp | 28 +++++++ src/ui/game/CGTabardModelFrameScript.cpp | 60 +++++++++++++++ src/ui/game/CGTabardModelFrameScript.hpp | 10 +++ 25 files changed, 784 insertions(+), 4 deletions(-) create mode 100644 src/ui/game/CGCharacterModelBase.cpp create mode 100644 src/ui/game/CGCharacterModelBase.hpp create mode 100644 src/ui/game/CGCharacterModelBaseScript.cpp create mode 100644 src/ui/game/CGCharacterModelBaseScript.hpp create mode 100644 src/ui/game/CGCooldown.cpp create mode 100644 src/ui/game/CGCooldown.hpp create mode 100644 src/ui/game/CGCooldownScript.cpp create mode 100644 src/ui/game/CGCooldownScript.hpp create mode 100644 src/ui/game/CGDressUpModelFrame.cpp create mode 100644 src/ui/game/CGDressUpModelFrame.hpp create mode 100644 src/ui/game/CGDressUpModelFrameScript.cpp create mode 100644 src/ui/game/CGDressUpModelFrameScript.hpp create mode 100644 src/ui/game/CGMinimapFrame.cpp create mode 100644 src/ui/game/CGMinimapFrame.hpp create mode 100644 src/ui/game/CGMinimapFrameScript.cpp create mode 100644 src/ui/game/CGMinimapFrameScript.hpp create mode 100644 src/ui/game/CGQuestPOIFrame.cpp create mode 100644 src/ui/game/CGQuestPOIFrame.hpp create mode 100644 src/ui/game/CGQuestPOIFrameScript.cpp create mode 100644 src/ui/game/CGQuestPOIFrameScript.hpp create mode 100644 src/ui/game/CGTabardModelFrame.cpp create mode 100644 src/ui/game/CGTabardModelFrame.hpp create mode 100644 src/ui/game/CGTabardModelFrameScript.cpp create mode 100644 src/ui/game/CGTabardModelFrameScript.hpp diff --git a/src/ui/game/CGCharacterModelBase.cpp b/src/ui/game/CGCharacterModelBase.cpp new file mode 100644 index 0000000..089afbe --- /dev/null +++ b/src/ui/game/CGCharacterModelBase.cpp @@ -0,0 +1,37 @@ +#include "ui/game/CGCharacterModelBase.hpp" +#include "ui/game/CGCharacterModelBaseScript.hpp" + +int32_t CGCharacterModelBase::s_metatable; +int32_t CGCharacterModelBase::s_objectType; + +CSimpleFrame* CGCharacterModelBase::Create(CSimpleFrame* parent) { + // TODO use CDataAllocator + + return STORM_NEW(CGCharacterModelBase)(parent); +} + +void CGCharacterModelBase::CreateScriptMetaTable() { + auto L = FrameScript_GetContext(); + CGCharacterModelBase::s_metatable = FrameScript_Object::CreateScriptMetaTable(L, &CGCharacterModelBase::RegisterScriptMethods); +} + +int32_t CGCharacterModelBase::GetObjectType() { + if (!CGCharacterModelBase::s_objectType) { + CGCharacterModelBase::s_objectType = ++FrameScript_Object::s_objectTypes; + } + + return CGCharacterModelBase::s_objectType; +} + +void CGCharacterModelBase::RegisterScriptMethods(lua_State* L) { + CSimpleModel::RegisterScriptMethods(L); + FrameScript_Object::FillScriptMethodTable(L, CGCharacterModelBaseMethods, NUM_CG_CHARACTER_MODEL_BASE_SCRIPT_METHODS); +} + +CGCharacterModelBase::CGCharacterModelBase(CSimpleFrame* parent) : CSimpleModel(parent) { + // TODO +} + +int32_t CGCharacterModelBase::GetScriptMetaTable() { + return CGCharacterModelBase::s_metatable; +} diff --git a/src/ui/game/CGCharacterModelBase.hpp b/src/ui/game/CGCharacterModelBase.hpp new file mode 100644 index 0000000..b67b3e2 --- /dev/null +++ b/src/ui/game/CGCharacterModelBase.hpp @@ -0,0 +1,28 @@ +#ifndef UI_GAME_C_G_CHARACTER_MODEL_BASE_HPP +#define UI_GAME_C_G_CHARACTER_MODEL_BASE_HPP + +#include "ui/simple/CSimpleModel.hpp" + +class CGCharacterModelBase : public CSimpleModel { + public: + // Static variables + static int32_t s_metatable; + static int32_t s_objectType; + + // Static functions + static CSimpleFrame* Create(CSimpleFrame* parent); + static void CreateScriptMetaTable(); + static int32_t GetObjectType(); + static void RegisterScriptMethods(lua_State* L); + + // Member variables + // TODO + + // Virtual member functions + virtual int32_t GetScriptMetaTable(); + + // Member functions + CGCharacterModelBase(CSimpleFrame* parent); +}; + +#endif diff --git a/src/ui/game/CGCharacterModelBaseScript.cpp b/src/ui/game/CGCharacterModelBaseScript.cpp new file mode 100644 index 0000000..b4d92a9 --- /dev/null +++ b/src/ui/game/CGCharacterModelBaseScript.cpp @@ -0,0 +1,30 @@ +#include "ui/game/CGCharacterModelBaseScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t Script_SetUnit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetCreature(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_RefreshUnit(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetRotation(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +FrameScript_Method CGCharacterModelBaseMethods[] = { + { "SetUnit", &Script_SetUnit }, + { "SetCreature", &Script_SetCreature }, + { "RefreshUnit", &Script_RefreshUnit }, + { "SetRotation", &Script_SetRotation }, +}; diff --git a/src/ui/game/CGCharacterModelBaseScript.hpp b/src/ui/game/CGCharacterModelBaseScript.hpp new file mode 100644 index 0000000..7c9deb5 --- /dev/null +++ b/src/ui/game/CGCharacterModelBaseScript.hpp @@ -0,0 +1,10 @@ +#ifndef UI_GAME_C_G_CHARACTER_MODEL_BASE_SCRIPT_HPP +#define UI_GAME_C_G_CHARACTER_MODEL_BASE_SCRIPT_HPP + +#include "ui/Types.hpp" + +#define NUM_CG_CHARACTER_MODEL_BASE_SCRIPT_METHODS 4 + +extern FrameScript_Method CGCharacterModelBaseMethods[NUM_CG_CHARACTER_MODEL_BASE_SCRIPT_METHODS]; + +#endif diff --git a/src/ui/game/CGCooldown.cpp b/src/ui/game/CGCooldown.cpp new file mode 100644 index 0000000..fb6aef8 --- /dev/null +++ b/src/ui/game/CGCooldown.cpp @@ -0,0 +1,37 @@ +#include "ui/game/CGCooldown.hpp" +#include "ui/game/CGCooldownScript.hpp" + +int32_t CGCooldown::s_metatable; +int32_t CGCooldown::s_objectType; + +CSimpleFrame* CGCooldown::Create(CSimpleFrame* parent) { + // TODO use CDataAllocator + + return STORM_NEW(CGCooldown)(parent); +} + +void CGCooldown::CreateScriptMetaTable() { + auto L = FrameScript_GetContext(); + CGCooldown::s_metatable = FrameScript_Object::CreateScriptMetaTable(L, &CGCooldown::RegisterScriptMethods); +} + +int32_t CGCooldown::GetObjectType() { + if (!CGCooldown::s_objectType) { + CGCooldown::s_objectType = ++FrameScript_Object::s_objectTypes; + } + + return CGCooldown::s_objectType; +} + +void CGCooldown::RegisterScriptMethods(lua_State* L) { + CSimpleFrame::RegisterScriptMethods(L); + FrameScript_Object::FillScriptMethodTable(L, CGCooldownMethods, NUM_CG_COOLDOWN_SCRIPT_METHODS); +} + +CGCooldown::CGCooldown(CSimpleFrame* parent) : CSimpleFrame(parent) { + // TODO +} + +int32_t CGCooldown::GetScriptMetaTable() { + return CGCooldown::s_metatable; +} diff --git a/src/ui/game/CGCooldown.hpp b/src/ui/game/CGCooldown.hpp new file mode 100644 index 0000000..8522fb1 --- /dev/null +++ b/src/ui/game/CGCooldown.hpp @@ -0,0 +1,28 @@ +#ifndef UI_GAME_C_G_COOLDOWN_HPP +#define UI_GAME_C_G_COOLDOWN_HPP + +#include "ui/simple/CSimpleFrame.hpp" + +class CGCooldown : public CSimpleFrame { + public: + // Static variables + static int32_t s_metatable; + static int32_t s_objectType; + + // Static functions + static CSimpleFrame* Create(CSimpleFrame* parent); + static void CreateScriptMetaTable(); + static int32_t GetObjectType(); + static void RegisterScriptMethods(lua_State* L); + + // Member variables + // TODO + + // Virtual member functions + virtual int32_t GetScriptMetaTable(); + + // Member functions + CGCooldown(CSimpleFrame* parent); +}; + +#endif diff --git a/src/ui/game/CGCooldownScript.cpp b/src/ui/game/CGCooldownScript.cpp new file mode 100644 index 0000000..5e7f145 --- /dev/null +++ b/src/ui/game/CGCooldownScript.cpp @@ -0,0 +1,35 @@ +#include "ui/game/CGCooldownScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t CGCooldown_SetCooldown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGCooldown_SetReverse(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGCooldown_GetReverse(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGCooldown_SetDrawEdge(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGCooldown_GetDrawEdge(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +FrameScript_Method CGCooldownMethods[] = { + { "SetCooldown", &CGCooldown_SetCooldown }, + { "SetReverse", &CGCooldown_SetReverse }, + { "GetReverse", &CGCooldown_GetReverse }, + { "SetDrawEdge", &CGCooldown_SetDrawEdge }, + { "GetDrawEdge", &CGCooldown_GetDrawEdge }, +}; diff --git a/src/ui/game/CGCooldownScript.hpp b/src/ui/game/CGCooldownScript.hpp new file mode 100644 index 0000000..34aecc7 --- /dev/null +++ b/src/ui/game/CGCooldownScript.hpp @@ -0,0 +1,10 @@ +#ifndef UI_GAME_C_G_COOLDOWN_SCRIPT_HPP +#define UI_GAME_C_G_COOLDOWN_SCRIPT_HPP + +#include "ui/Types.hpp" + +#define NUM_CG_COOLDOWN_SCRIPT_METHODS 5 + +extern FrameScript_Method CGCooldownMethods[NUM_CG_COOLDOWN_SCRIPT_METHODS]; + +#endif diff --git a/src/ui/game/CGDressUpModelFrame.cpp b/src/ui/game/CGDressUpModelFrame.cpp new file mode 100644 index 0000000..8ead82d --- /dev/null +++ b/src/ui/game/CGDressUpModelFrame.cpp @@ -0,0 +1,37 @@ +#include "ui/game/CGDressUpModelFrame.hpp" +#include "ui/game/CGDressUpModelFrameScript.hpp" + +int32_t CGDressUpModelFrame::s_metatable; +int32_t CGDressUpModelFrame::s_objectType; + +CSimpleFrame* CGDressUpModelFrame::Create(CSimpleFrame* parent) { + // TODO use CDataAllocator + + return STORM_NEW(CGDressUpModelFrame)(parent); +} + +void CGDressUpModelFrame::CreateScriptMetaTable() { + auto L = FrameScript_GetContext(); + CGDressUpModelFrame::s_metatable = FrameScript_Object::CreateScriptMetaTable(L, &CGDressUpModelFrame::RegisterScriptMethods); +} + +int32_t CGDressUpModelFrame::GetObjectType() { + if (!CGDressUpModelFrame::s_objectType) { + CGDressUpModelFrame::s_objectType = ++FrameScript_Object::s_objectTypes; + } + + return CGDressUpModelFrame::s_objectType; +} + +void CGDressUpModelFrame::RegisterScriptMethods(lua_State* L) { + CGCharacterModelBase::RegisterScriptMethods(L); + FrameScript_Object::FillScriptMethodTable(L, CGDressUpModelFrameMethods, NUM_CG_DRESS_UP_MODEL_FRAME_SCRIPT_METHODS); +} + +CGDressUpModelFrame::CGDressUpModelFrame(CSimpleFrame* parent) : CGCharacterModelBase(parent) { + // TODO +} + +int32_t CGDressUpModelFrame::GetScriptMetaTable() { + return CGDressUpModelFrame::s_metatable; +} diff --git a/src/ui/game/CGDressUpModelFrame.hpp b/src/ui/game/CGDressUpModelFrame.hpp new file mode 100644 index 0000000..a74f6d3 --- /dev/null +++ b/src/ui/game/CGDressUpModelFrame.hpp @@ -0,0 +1,28 @@ +#ifndef UI_GAME_C_G_DRESS_UP_MODEL_FRAME_HPP +#define UI_GAME_C_G_DRESS_UP_MODEL_FRAME_HPP + +#include "ui/game/CGCharacterModelBase.hpp" + +class CGDressUpModelFrame : public CGCharacterModelBase { + public: + // Static variables + static int32_t s_metatable; + static int32_t s_objectType; + + // Static functions + static CSimpleFrame* Create(CSimpleFrame* parent); + static void CreateScriptMetaTable(); + static int32_t GetObjectType(); + static void RegisterScriptMethods(lua_State* L); + + // Member variables + // TODO + + // Virtual member functions + virtual int32_t GetScriptMetaTable(); + + // Member functions + CGDressUpModelFrame(CSimpleFrame* parent); +}; + +#endif diff --git a/src/ui/game/CGDressUpModelFrameScript.cpp b/src/ui/game/CGDressUpModelFrameScript.cpp new file mode 100644 index 0000000..14e948b --- /dev/null +++ b/src/ui/game/CGDressUpModelFrameScript.cpp @@ -0,0 +1,25 @@ +#include "ui/game/CGDressUpModelFrameScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t Script_Undress(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_Dress(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_TryOn(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +FrameScript_Method CGDressUpModelFrameMethods[] = { + { "Undress", &Script_Undress }, + { "Dress", &Script_Dress }, + { "TryOn", &Script_TryOn }, +}; diff --git a/src/ui/game/CGDressUpModelFrameScript.hpp b/src/ui/game/CGDressUpModelFrameScript.hpp new file mode 100644 index 0000000..fe4aad5 --- /dev/null +++ b/src/ui/game/CGDressUpModelFrameScript.hpp @@ -0,0 +1,10 @@ +#ifndef UI_GAME_C_G_DRESS_UP_MODEL_FRAME_SCRIPT_HPP +#define UI_GAME_C_G_DRESS_UP_MODEL_FRAME_SCRIPT_HPP + +#include "ui/Types.hpp" + +#define NUM_CG_DRESS_UP_MODEL_FRAME_SCRIPT_METHODS 3 + +extern FrameScript_Method CGDressUpModelFrameMethods[NUM_CG_DRESS_UP_MODEL_FRAME_SCRIPT_METHODS]; + +#endif diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 2729222..21bd423 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -4,6 +4,12 @@ #include "ui/FrameXML.hpp" #include "ui/Key.hpp" #include "ui/game/BattlefieldInfoScript.hpp" +#include "ui/game/CGCharacterModelBase.hpp" +#include "ui/game/CGCooldown.hpp" +#include "ui/game/CGDressUpModelFrame.hpp" +#include "ui/game/CGMinimapFrame.hpp" +#include "ui/game/CGQuestPOIFrame.hpp" +#include "ui/game/CGTabardModelFrame.hpp" #include "ui/game/CGTooltip.hpp" #include "ui/game/CGWorldFrame.hpp" #include "ui/game/CharacterInfoScript.hpp" @@ -22,8 +28,12 @@ void LoadScriptFunctions() { // TODO CGTooltip::CreateScriptMetaTable(); - - // TODO + CGCooldown::CreateScriptMetaTable(); + CGMinimapFrame::CreateScriptMetaTable(); + CGCharacterModelBase::CreateScriptMetaTable(); + CGDressUpModelFrame::CreateScriptMetaTable(); + CGTabardModelFrame::CreateScriptMetaTable(); + CGQuestPOIFrame::CreateScriptMetaTable(); GameScriptRegisterFunctions(); UIBindingsRegisterScriptFunctions(); @@ -137,6 +147,10 @@ void CGGameUI::InitializeGame() { void CGGameUI::RegisterFrameFactories() { FrameXML_RegisterFactory("WorldFrame", &CGWorldFrame::Create, true); FrameXML_RegisterFactory("GameTooltip", &CGTooltip::Create, false); - - // TODO register remaining factories + FrameXML_RegisterFactory("Cooldown", &CGCooldown::Create, false); + FrameXML_RegisterFactory("Minimap", &CGMinimapFrame::Create, false); + FrameXML_RegisterFactory("PlayerModel", &CGCharacterModelBase::Create, false); + FrameXML_RegisterFactory("DressUpModel", &CGDressUpModelFrame::Create, false); + FrameXML_RegisterFactory("TabardModel", &CGTabardModelFrame::Create, false); + FrameXML_RegisterFactory("QuestPOIFrame", &CGQuestPOIFrame::Create, false); } diff --git a/src/ui/game/CGMinimapFrame.cpp b/src/ui/game/CGMinimapFrame.cpp new file mode 100644 index 0000000..40494d3 --- /dev/null +++ b/src/ui/game/CGMinimapFrame.cpp @@ -0,0 +1,37 @@ +#include "ui/game/CGMinimapFrame.hpp" +#include "ui/game/CGMinimapFrameScript.hpp" + +int32_t CGMinimapFrame::s_metatable; +int32_t CGMinimapFrame::s_objectType; + +CSimpleFrame* CGMinimapFrame::Create(CSimpleFrame* parent) { + // TODO use CDataAllocator + + return STORM_NEW(CGMinimapFrame)(parent); +} + +void CGMinimapFrame::CreateScriptMetaTable() { + auto L = FrameScript_GetContext(); + CGMinimapFrame::s_metatable = FrameScript_Object::CreateScriptMetaTable(L, &CGMinimapFrame::RegisterScriptMethods); +} + +int32_t CGMinimapFrame::GetObjectType() { + if (!CGMinimapFrame::s_objectType) { + CGMinimapFrame::s_objectType = ++FrameScript_Object::s_objectTypes; + } + + return CGMinimapFrame::s_objectType; +} + +void CGMinimapFrame::RegisterScriptMethods(lua_State* L) { + CSimpleFrame::RegisterScriptMethods(L); + FrameScript_Object::FillScriptMethodTable(L, CGMinimapFrameMethods, NUM_CG_MINIMAP_FRAME_SCRIPT_METHODS); +} + +CGMinimapFrame::CGMinimapFrame(CSimpleFrame* parent) : CSimpleFrame(parent) { + // TODO +} + +int32_t CGMinimapFrame::GetScriptMetaTable() { + return CGMinimapFrame::s_metatable; +} diff --git a/src/ui/game/CGMinimapFrame.hpp b/src/ui/game/CGMinimapFrame.hpp new file mode 100644 index 0000000..d83d199 --- /dev/null +++ b/src/ui/game/CGMinimapFrame.hpp @@ -0,0 +1,28 @@ +#ifndef UI_GAME_C_G_MINIMAP_FRAME_HPP +#define UI_GAME_C_G_MINIMAP_FRAME_HPP + +#include "ui/simple/CSimpleFrame.hpp" + +class CGMinimapFrame : public CSimpleFrame { + public: + // Static variables + static int32_t s_metatable; + static int32_t s_objectType; + + // Static functions + static CSimpleFrame* Create(CSimpleFrame* parent); + static void CreateScriptMetaTable(); + static int32_t GetObjectType(); + static void RegisterScriptMethods(lua_State* L); + + // Member variables + // TODO + + // Virtual member functions + virtual int32_t GetScriptMetaTable(); + + // Member functions + CGMinimapFrame(CSimpleFrame* parent); +}; + +#endif diff --git a/src/ui/game/CGMinimapFrameScript.cpp b/src/ui/game/CGMinimapFrameScript.cpp new file mode 100644 index 0000000..dc914b0 --- /dev/null +++ b/src/ui/game/CGMinimapFrameScript.cpp @@ -0,0 +1,85 @@ +#include "ui/game/CGMinimapFrameScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t CGMinimapFrame_SetMaskTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGMinimapFrame_SetIconTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGMinimapFrame_SetBlipTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGMinimapFrame_SetClassBlipTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGMinimapFrame_SetPOIArrowTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGMinimapFrame_SetStaticPOIArrowTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGMinimapFrame_SetCorpsePOIArrowTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGMinimapFrame_SetPlayerTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGMinimapFrame_SetPlayerTextureHeight(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGMinimapFrame_SetPlayerTextureWidth(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGMinimapFrame_GetZoomLevels(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGMinimapFrame_GetZoom(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGMinimapFrame_SetZoom(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGMinimapFrame_PingLocation(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGMinimapFrame_GetPingPosition(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +FrameScript_Method CGMinimapFrameMethods[] = { + { "SetMaskTexture", &CGMinimapFrame_SetMaskTexture }, + { "SetIconTexture", &CGMinimapFrame_SetIconTexture }, + { "SetBlipTexture", &CGMinimapFrame_SetBlipTexture }, + { "SetClassBlipTexture", &CGMinimapFrame_SetClassBlipTexture }, + { "SetPOIArrowTexture", &CGMinimapFrame_SetPOIArrowTexture }, + { "SetStaticPOIArrowTexture", &CGMinimapFrame_SetStaticPOIArrowTexture }, + { "SetCorpsePOIArrowTexture", &CGMinimapFrame_SetCorpsePOIArrowTexture }, + { "SetPlayerTexture", &CGMinimapFrame_SetPlayerTexture }, + { "SetPlayerTextureHeight", &CGMinimapFrame_SetPlayerTextureHeight }, + { "SetPlayerTextureWidth", &CGMinimapFrame_SetPlayerTextureWidth }, + { "GetZoomLevels", &CGMinimapFrame_GetZoomLevels }, + { "GetZoom", &CGMinimapFrame_GetZoom }, + { "SetZoom", &CGMinimapFrame_SetZoom }, + { "PingLocation", &CGMinimapFrame_PingLocation }, + { "GetPingPosition", &CGMinimapFrame_GetPingPosition }, +}; diff --git a/src/ui/game/CGMinimapFrameScript.hpp b/src/ui/game/CGMinimapFrameScript.hpp new file mode 100644 index 0000000..2095602 --- /dev/null +++ b/src/ui/game/CGMinimapFrameScript.hpp @@ -0,0 +1,10 @@ +#ifndef UI_GAME_C_G_MINIMAP_FRAME_SCRIPT_HPP +#define UI_GAME_C_G_MINIMAP_FRAME_SCRIPT_HPP + +#include "ui/Types.hpp" + +#define NUM_CG_MINIMAP_FRAME_SCRIPT_METHODS 15 + +extern FrameScript_Method CGMinimapFrameMethods[NUM_CG_MINIMAP_FRAME_SCRIPT_METHODS]; + +#endif diff --git a/src/ui/game/CGQuestPOIFrame.cpp b/src/ui/game/CGQuestPOIFrame.cpp new file mode 100644 index 0000000..577692d --- /dev/null +++ b/src/ui/game/CGQuestPOIFrame.cpp @@ -0,0 +1,38 @@ +#include "ui/game/CGQuestPOIFrame.hpp" +#include "ui/game/CGQuestPOIFrameScript.hpp" + +int32_t CGQuestPOIFrame::s_metatable; +int32_t CGQuestPOIFrame::s_objectType; + +CSimpleFrame* CGQuestPOIFrame::Create(CSimpleFrame* parent) { + // TODO use CDataAllocator + + return STORM_NEW(CGQuestPOIFrame)(parent); +} + +void CGQuestPOIFrame::CreateScriptMetaTable() { + auto L = FrameScript_GetContext(); + CGQuestPOIFrame::s_metatable = FrameScript_Object::CreateScriptMetaTable(L, &CGQuestPOIFrame::RegisterScriptMethods); +} + +int32_t CGQuestPOIFrame::GetObjectType() { + if (!CGQuestPOIFrame::s_objectType) { + CGQuestPOIFrame::s_objectType = ++FrameScript_Object::s_objectTypes; + } + + return CGQuestPOIFrame::s_objectType; +} + +void CGQuestPOIFrame::RegisterScriptMethods(lua_State* L) { + CSimpleFrame::RegisterScriptMethods(L); + FrameScript_Object::FillScriptMethodTable(L, CGQuestPOIFrameMethods, NUM_CG_QUEST_POI_FRAME_SCRIPT_METHODS); +} + +CGQuestPOIFrame::CGQuestPOIFrame(CSimpleFrame* parent) : CSimpleFrame(parent) { + // TODO +} + +int32_t CGQuestPOIFrame::GetScriptMetaTable() { + return CGQuestPOIFrame::s_metatable; +} + diff --git a/src/ui/game/CGQuestPOIFrame.hpp b/src/ui/game/CGQuestPOIFrame.hpp new file mode 100644 index 0000000..ceb3be9 --- /dev/null +++ b/src/ui/game/CGQuestPOIFrame.hpp @@ -0,0 +1,28 @@ +#ifndef UI_GAME_C_G_QUEST_POI_FRAME_HPP +#define UI_GAME_C_G_QUEST_POI_FRAME_HPP + +#include "ui/simple/CSimpleFrame.hpp" + +class CGQuestPOIFrame : public CSimpleFrame { + public: + // Static variables + static int32_t s_metatable; + static int32_t s_objectType; + + // Static functions + static CSimpleFrame* Create(CSimpleFrame* parent); + static void CreateScriptMetaTable(); + static int32_t GetObjectType(); + static void RegisterScriptMethods(lua_State* L); + + // Member variables + // TODO + + // Virtual member functions + virtual int32_t GetScriptMetaTable(); + + // Member functions + CGQuestPOIFrame(CSimpleFrame* parent); +}; + +#endif diff --git a/src/ui/game/CGQuestPOIFrameScript.cpp b/src/ui/game/CGQuestPOIFrameScript.cpp new file mode 100644 index 0000000..8ab1b01 --- /dev/null +++ b/src/ui/game/CGQuestPOIFrameScript.cpp @@ -0,0 +1,80 @@ +#include "ui/game/CGQuestPOIFrameScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t CGQuestPOIFrame_SetFillTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGQuestPOIFrame_SetFillAlpha(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGQuestPOIFrame_SetBorderTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGQuestPOIFrame_SetBorderAlpha(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGQuestPOIFrame_SetBorderScalar(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGQuestPOIFrame_DrawQuestBlob(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGQuestPOIFrame_EnableSmoothing(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGQuestPOIFrame_EnableMerging(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGQuestPOIFrame_SetMergeThreshold(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGQuestPOIFrame_SetNumSplinePoints(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGQuestPOIFrame_UpdateQuestPOI(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGQuestPOIFrame_UpdateMouseOverTooltip(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGQuestPOIFrame_GetTooltipIndex(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGQuestPOIFrame_GetNumTooltips(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +FrameScript_Method CGQuestPOIFrameMethods[] = { + { "SetFillTexture", &CGQuestPOIFrame_SetFillTexture }, + { "SetFillAlpha", &CGQuestPOIFrame_SetFillAlpha }, + { "SetBorderTexture", &CGQuestPOIFrame_SetBorderTexture }, + { "SetBorderAlpha", &CGQuestPOIFrame_SetBorderAlpha }, + { "SetBorderScalar", &CGQuestPOIFrame_SetBorderScalar }, + { "DrawQuestBlob", &CGQuestPOIFrame_DrawQuestBlob }, + { "EnableSmoothing", &CGQuestPOIFrame_EnableSmoothing }, + { "EnableMerging", &CGQuestPOIFrame_EnableMerging }, + { "SetMergeThreshold", &CGQuestPOIFrame_SetMergeThreshold }, + { "SetNumSplinePoints", &CGQuestPOIFrame_SetNumSplinePoints }, + { "UpdateQuestPOI", &CGQuestPOIFrame_UpdateQuestPOI }, + { "UpdateMouseOverTooltip", &CGQuestPOIFrame_UpdateMouseOverTooltip }, + { "GetTooltipIndex", &CGQuestPOIFrame_GetTooltipIndex }, + { "GetNumTooltips", &CGQuestPOIFrame_GetNumTooltips }, +}; diff --git a/src/ui/game/CGQuestPOIFrameScript.hpp b/src/ui/game/CGQuestPOIFrameScript.hpp new file mode 100644 index 0000000..0e105f7 --- /dev/null +++ b/src/ui/game/CGQuestPOIFrameScript.hpp @@ -0,0 +1,10 @@ +#ifndef UI_GAME_C_G_QUEST_POI_FRAME_SCRIPT_HPP +#define UI_GAME_C_G_QUEST_POI_FRAME_SCRIPT_HPP + +#include "ui/Types.hpp" + +#define NUM_CG_QUEST_POI_FRAME_SCRIPT_METHODS 14 + +extern FrameScript_Method CGQuestPOIFrameMethods[NUM_CG_QUEST_POI_FRAME_SCRIPT_METHODS]; + +#endif diff --git a/src/ui/game/CGTabardModelFrame.cpp b/src/ui/game/CGTabardModelFrame.cpp new file mode 100644 index 0000000..29f3600 --- /dev/null +++ b/src/ui/game/CGTabardModelFrame.cpp @@ -0,0 +1,37 @@ +#include "ui/game/CGTabardModelFrame.hpp" +#include "ui/game/CGTabardModelFrameScript.hpp" + +int32_t CGTabardModelFrame::s_metatable; +int32_t CGTabardModelFrame::s_objectType; + +CSimpleFrame* CGTabardModelFrame::Create(CSimpleFrame* parent) { + // TODO use CDataAllocator + + return STORM_NEW(CGTabardModelFrame)(parent); +} + +void CGTabardModelFrame::CreateScriptMetaTable() { + auto L = FrameScript_GetContext(); + CGTabardModelFrame::s_metatable = FrameScript_Object::CreateScriptMetaTable(L, &CGTabardModelFrame::RegisterScriptMethods); +} + +int32_t CGTabardModelFrame::GetObjectType() { + if (!CGTabardModelFrame::s_objectType) { + CGTabardModelFrame::s_objectType = ++FrameScript_Object::s_objectTypes; + } + + return CGTabardModelFrame::s_objectType; +} + +void CGTabardModelFrame::RegisterScriptMethods(lua_State* L) { + CGCharacterModelBase::RegisterScriptMethods(L); + FrameScript_Object::FillScriptMethodTable(L, CGTabardModelFrameMethods, NUM_CG_TABARD_MODEL_FRAME_SCRIPT_METHODS); +} + +CGTabardModelFrame::CGTabardModelFrame(CSimpleFrame* parent) : CGCharacterModelBase(parent) { + // TODO +} + +int32_t CGTabardModelFrame::GetScriptMetaTable() { + return CGTabardModelFrame::s_metatable; +} diff --git a/src/ui/game/CGTabardModelFrame.hpp b/src/ui/game/CGTabardModelFrame.hpp new file mode 100644 index 0000000..b6e3d72 --- /dev/null +++ b/src/ui/game/CGTabardModelFrame.hpp @@ -0,0 +1,28 @@ +#ifndef UI_GAME_C_G_TABARD_MODEL_FRAME_HPP +#define UI_GAME_C_G_TABARD_MODEL_FRAME_HPP + +#include "ui/game/CGCharacterModelBase.hpp" + +class CGTabardModelFrame : public CGCharacterModelBase { + public: + // Static variables + static int32_t s_metatable; + static int32_t s_objectType; + + // Static functions + static CSimpleFrame* Create(CSimpleFrame* parent); + static void CreateScriptMetaTable(); + static int32_t GetObjectType(); + static void RegisterScriptMethods(lua_State* L); + + // Member variables + // TODO + + // Virtual member functions + virtual int32_t GetScriptMetaTable(); + + // Member functions + CGTabardModelFrame(CSimpleFrame* parent); +}; + +#endif diff --git a/src/ui/game/CGTabardModelFrameScript.cpp b/src/ui/game/CGTabardModelFrameScript.cpp new file mode 100644 index 0000000..405d727 --- /dev/null +++ b/src/ui/game/CGTabardModelFrameScript.cpp @@ -0,0 +1,60 @@ +#include "ui/game/CGTabardModelFrameScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t CGTabardModelFrame_InitializeTabardColors(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTabardModelFrame_Save(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTabardModelFrame_CycleVariation(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTabardModelFrame_GetUpperBackgroundFileName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTabardModelFrame_GetLowerBackgroundFileName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTabardModelFrame_GetUpperEmblemFileName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTabardModelFrame_GetLowerEmblemFileName(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTabardModelFrame_GetUpperEmblemTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTabardModelFrame_GetLowerEmblemTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CGTabardModelFrame_CanSaveTabardNow(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +FrameScript_Method CGTabardModelFrameMethods[] = { + { "InitializeTabardColors", &CGTabardModelFrame_InitializeTabardColors }, + { "Save", &CGTabardModelFrame_Save }, + { "CycleVariation", &CGTabardModelFrame_CycleVariation }, + { "GetUpperBackgroundFileName", &CGTabardModelFrame_GetUpperBackgroundFileName }, + { "GetLowerBackgroundFileName", &CGTabardModelFrame_GetLowerBackgroundFileName }, + { "GetUpperEmblemFileName", &CGTabardModelFrame_GetUpperEmblemFileName }, + { "GetLowerEmblemFileName", &CGTabardModelFrame_GetLowerEmblemFileName }, + { "GetUpperEmblemTexture", &CGTabardModelFrame_GetUpperEmblemTexture }, + { "GetLowerEmblemTexture", &CGTabardModelFrame_GetLowerEmblemTexture }, + { "CanSaveTabardNow", &CGTabardModelFrame_CanSaveTabardNow }, +}; diff --git a/src/ui/game/CGTabardModelFrameScript.hpp b/src/ui/game/CGTabardModelFrameScript.hpp new file mode 100644 index 0000000..4d68cae --- /dev/null +++ b/src/ui/game/CGTabardModelFrameScript.hpp @@ -0,0 +1,10 @@ +#ifndef UI_GAME_C_G_TABARD_MODEL_FRAME_SCRIPT_HPP +#define UI_GAME_C_G_TABARD_MODEL_FRAME_SCRIPT_HPP + +#include "ui/Types.hpp" + +#define NUM_CG_TABARD_MODEL_FRAME_SCRIPT_METHODS 10 + +extern FrameScript_Method CGTabardModelFrameMethods[NUM_CG_TABARD_MODEL_FRAME_SCRIPT_METHODS]; + +#endif From df177a40b062e219bfbc8c402c5ea0c08422b00a Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 29 Jan 2026 22:16:25 -0600 Subject: [PATCH 120/269] chore(ui): use anonymous namespace consistently for script bindings --- src/ui/game/GMTicketInfoScript.cpp | 4 ++++ src/ui/game/GameScript.cpp | 1 + src/ui/game/ScriptEvents.cpp | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/src/ui/game/GMTicketInfoScript.cpp b/src/ui/game/GMTicketInfoScript.cpp index 302a150..0264338 100644 --- a/src/ui/game/GMTicketInfoScript.cpp +++ b/src/ui/game/GMTicketInfoScript.cpp @@ -2,6 +2,8 @@ #include "ui/FrameScript.hpp" #include "util/Unimplemented.hpp" +namespace { + int32_t Script_GetGMTicket(lua_State* L) { WHOA_UNIMPLEMENTED(0); } @@ -62,6 +64,8 @@ int32_t Script_RegisterStaticConstants(lua_State* L) { WHOA_UNIMPLEMENTED(0); } +} + static FrameScript_Method s_ScriptFunctions[] = { { "GetGMTicket", &Script_GetGMTicket }, { "NewGMTicket", &Script_NewGMTicket }, diff --git a/src/ui/game/GameScript.cpp b/src/ui/game/GameScript.cpp index 236b5b9..0652fba 100644 --- a/src/ui/game/GameScript.cpp +++ b/src/ui/game/GameScript.cpp @@ -8,6 +8,7 @@ #include "util/Unimplemented.hpp" namespace { + int32_t Script_FrameXML_Debug(lua_State* L) { WHOA_UNIMPLEMENTED(0); } diff --git a/src/ui/game/ScriptEvents.cpp b/src/ui/game/ScriptEvents.cpp index 258413b..0367bee 100644 --- a/src/ui/game/ScriptEvents.cpp +++ b/src/ui/game/ScriptEvents.cpp @@ -3,6 +3,8 @@ #include "ui/ScriptFunctionsSystem.hpp" #include "util/Unimplemented.hpp" +namespace { + int32_t Script_UnitExists(lua_State* L) { WHOA_UNIMPLEMENTED(0); } @@ -679,6 +681,8 @@ int32_t Script_FillLocalizedClassList(lua_State* L) { WHOA_UNIMPLEMENTED(0); } +} + static FrameScript_Method s_UnitFunctions[] = { { "UnitExists", &Script_UnitExists }, { "UnitIsVisible", &Script_UnitIsVisible }, From 1cddac296c82c8d40020cd86ed5df6835b4fa1e5 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 29 Jan 2026 22:19:08 -0600 Subject: [PATCH 121/269] chore(ui): use boolean for unique flag in FrameXML_RegisterFactory calls --- src/ui/FrameXML.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/ui/FrameXML.cpp b/src/ui/FrameXML.cpp index 2f99571..720702e 100644 --- a/src/ui/FrameXML.cpp +++ b/src/ui/FrameXML.cpp @@ -541,19 +541,19 @@ int32_t FrameXML_RegisterFactory(const char* type, CSimpleFrame* (*factory)(CSim } void FrameXML_RegisterDefault() { - FrameXML_RegisterFactory("Button", &Create_SimpleButton, 0); - FrameXML_RegisterFactory("CheckButton", &Create_SimpleCheckButton, 0); - FrameXML_RegisterFactory("EditBox", &Create_SimpleEditBox, 0); - FrameXML_RegisterFactory("Frame", &Create_SimpleFrame, 0); - FrameXML_RegisterFactory("MessageFrame", &Create_SimpleMessageFrame, 0); - FrameXML_RegisterFactory("Model", &Create_SimpleModel, 0); - FrameXML_RegisterFactory("ScrollFrame", &Create_SimpleScrollFrame, 0); - FrameXML_RegisterFactory("ScrollingMessageFrame", &Create_SimpleScrollingMessageFrame, 0); - FrameXML_RegisterFactory("Slider", &Create_SimpleSlider, 0); - FrameXML_RegisterFactory("SimpleHTML", &Create_SimpleHTML, 0); - FrameXML_RegisterFactory("StatusBar", &Create_SimpleStatusBar, 0); - FrameXML_RegisterFactory("ColorSelect", &Create_SimpleColorSelect, 0); - FrameXML_RegisterFactory("MovieFrame", &Create_SimpleMovieFrame, 0); + FrameXML_RegisterFactory("Button", &Create_SimpleButton, false); + FrameXML_RegisterFactory("CheckButton", &Create_SimpleCheckButton, false); + FrameXML_RegisterFactory("EditBox", &Create_SimpleEditBox, false); + FrameXML_RegisterFactory("Frame", &Create_SimpleFrame, false); + FrameXML_RegisterFactory("MessageFrame", &Create_SimpleMessageFrame, false); + FrameXML_RegisterFactory("Model", &Create_SimpleModel, false); + FrameXML_RegisterFactory("ScrollFrame", &Create_SimpleScrollFrame, false); + FrameXML_RegisterFactory("ScrollingMessageFrame", &Create_SimpleScrollingMessageFrame, false); + FrameXML_RegisterFactory("Slider", &Create_SimpleSlider, false); + FrameXML_RegisterFactory("SimpleHTML", &Create_SimpleHTML, false); + FrameXML_RegisterFactory("StatusBar", &Create_SimpleStatusBar, false); + FrameXML_RegisterFactory("ColorSelect", &Create_SimpleColorSelect, false); + FrameXML_RegisterFactory("MovieFrame", &Create_SimpleMovieFrame, false); } void FrameXML_ReleaseHashNode(const char* name) { From 91a4afd976e41a8f707db5fdc7f0f7604095a9b1 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 29 Jan 2026 22:41:29 -0600 Subject: [PATCH 122/269] feat(ui): add stubbed implementation of CSimpleStatusBar --- src/ui/FrameXML.cpp | 5 +- src/ui/simple/CSimpleStatusBar.cpp | 31 +++++++++++ src/ui/simple/CSimpleStatusBar.hpp | 27 +++++++++ src/ui/simple/CSimpleStatusBarScript.cpp | 70 ++++++++++++++++++++++++ src/ui/simple/CSimpleStatusBarScript.hpp | 10 ++++ src/ui/simple/ScriptMethods.cpp | 3 +- 6 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 src/ui/simple/CSimpleStatusBar.cpp create mode 100644 src/ui/simple/CSimpleStatusBar.hpp create mode 100644 src/ui/simple/CSimpleStatusBarScript.cpp create mode 100644 src/ui/simple/CSimpleStatusBarScript.hpp diff --git a/src/ui/FrameXML.cpp b/src/ui/FrameXML.cpp index 720702e..6c342ca 100644 --- a/src/ui/FrameXML.cpp +++ b/src/ui/FrameXML.cpp @@ -8,6 +8,7 @@ #include "ui/simple/CSimpleModel.hpp" #include "ui/simple/CSimpleScrollFrame.hpp" #include "ui/simple/CSimpleSlider.hpp" +#include "ui/simple/CSimpleStatusBar.hpp" #include "util/CStatus.hpp" #include "util/SFile.hpp" #include @@ -96,9 +97,9 @@ CSimpleFrame* Create_SimpleHTML(CSimpleFrame* parent) { } CSimpleFrame* Create_SimpleStatusBar(CSimpleFrame* parent) { - // TODO + // TODO CDataAllocator - return nullptr; + return STORM_NEW(CSimpleStatusBar(parent)); } CSimpleFrame* Create_SimpleColorSelect(CSimpleFrame* parent) { diff --git a/src/ui/simple/CSimpleStatusBar.cpp b/src/ui/simple/CSimpleStatusBar.cpp new file mode 100644 index 0000000..471c842 --- /dev/null +++ b/src/ui/simple/CSimpleStatusBar.cpp @@ -0,0 +1,31 @@ +#include "ui/simple/CSimpleStatusBar.hpp" +#include "ui/simple/CSimpleStatusBarScript.hpp" + +int32_t CSimpleStatusBar::s_metatable; +int32_t CSimpleStatusBar::s_objectType; + +void CSimpleStatusBar::CreateScriptMetaTable() { + auto L = FrameScript_GetContext(); + CSimpleStatusBar::s_metatable = FrameScript_Object::CreateScriptMetaTable(L, &CSimpleStatusBar::RegisterScriptMethods); +} + +int32_t CSimpleStatusBar::GetObjectType() { + if (!CSimpleStatusBar::s_objectType) { + CSimpleStatusBar::s_objectType = ++FrameScript_Object::s_objectTypes; + } + + return CSimpleStatusBar::s_objectType; +} + +void CSimpleStatusBar::RegisterScriptMethods(lua_State* L) { + CSimpleFrame::RegisterScriptMethods(L); + FrameScript_Object::FillScriptMethodTable(L, SimpleStatusBarMethods, NUM_SIMPLE_STATUS_BAR_SCRIPT_METHODS); +} + +CSimpleStatusBar::CSimpleStatusBar(CSimpleFrame* parent) : CSimpleFrame(parent) { + // TODO +} + +int32_t CSimpleStatusBar::GetScriptMetaTable() { + return CSimpleStatusBar::s_metatable; +} diff --git a/src/ui/simple/CSimpleStatusBar.hpp b/src/ui/simple/CSimpleStatusBar.hpp new file mode 100644 index 0000000..812439e --- /dev/null +++ b/src/ui/simple/CSimpleStatusBar.hpp @@ -0,0 +1,27 @@ +#ifndef UI_SIMPLE_C_SIMPLE_STATUS_BAR_HPP +#define UI_SIMPLE_C_SIMPLE_STATUS_BAR_HPP + +#include "ui/simple/CSimpleFrame.hpp" + +class CSimpleStatusBar : public CSimpleFrame { + public: + // Static variables + static int32_t s_metatable; + static int32_t s_objectType; + + // Static functions + static void CreateScriptMetaTable(); + static int32_t GetObjectType(); + static void RegisterScriptMethods(lua_State* L); + + // Member variables + // TODO + + // Virtual member functions + virtual int32_t GetScriptMetaTable(); + + // Member functions + CSimpleStatusBar(CSimpleFrame* parent); +}; + +#endif diff --git a/src/ui/simple/CSimpleStatusBarScript.cpp b/src/ui/simple/CSimpleStatusBarScript.cpp new file mode 100644 index 0000000..88dcc40 --- /dev/null +++ b/src/ui/simple/CSimpleStatusBarScript.cpp @@ -0,0 +1,70 @@ +#include "ui/simple/CSimpleStatusBarScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t CSimpleStatusBar_GetOrientation(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CSimpleStatusBar_SetOrientation(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CSimpleStatusBar_GetMinMaxValues(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CSimpleStatusBar_SetMinMaxValues(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CSimpleStatusBar_GetValue(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CSimpleStatusBar_SetValue(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CSimpleStatusBar_GetStatusBarTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CSimpleStatusBar_SetStatusBarTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CSimpleStatusBar_GetStatusBarColor(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CSimpleStatusBar_SetStatusBarColor(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CSimpleStatusBar_GetRotatesTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t CSimpleStatusBar_SetRotatesTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +FrameScript_Method SimpleStatusBarMethods[] = { + { "GetOrientation", &CSimpleStatusBar_GetOrientation }, + { "SetOrientation", &CSimpleStatusBar_SetOrientation }, + { "GetMinMaxValues", &CSimpleStatusBar_GetMinMaxValues }, + { "SetMinMaxValues", &CSimpleStatusBar_SetMinMaxValues }, + { "GetValue", &CSimpleStatusBar_GetValue }, + { "SetValue", &CSimpleStatusBar_SetValue }, + { "GetStatusBarTexture", &CSimpleStatusBar_GetStatusBarTexture }, + { "SetStatusBarTexture", &CSimpleStatusBar_SetStatusBarTexture }, + { "GetStatusBarColor", &CSimpleStatusBar_GetStatusBarColor }, + { "SetStatusBarColor", &CSimpleStatusBar_SetStatusBarColor }, + { "GetRotatesTexture", &CSimpleStatusBar_GetRotatesTexture }, + { "SetRotatesTexture", &CSimpleStatusBar_SetRotatesTexture }, +}; diff --git a/src/ui/simple/CSimpleStatusBarScript.hpp b/src/ui/simple/CSimpleStatusBarScript.hpp new file mode 100644 index 0000000..928dfa5 --- /dev/null +++ b/src/ui/simple/CSimpleStatusBarScript.hpp @@ -0,0 +1,10 @@ +#ifndef UI_SIMPLE_C_SIMPLE_STATUS_BAR_SCRIPT_HPP +#define UI_SIMPLE_C_SIMPLE_STATUS_BAR_SCRIPT_HPP + +#include "ui/Types.hpp" + +#define NUM_SIMPLE_STATUS_BAR_SCRIPT_METHODS 12 + +extern FrameScript_Method SimpleStatusBarMethods[NUM_SIMPLE_STATUS_BAR_SCRIPT_METHODS]; + +#endif diff --git a/src/ui/simple/ScriptMethods.cpp b/src/ui/simple/ScriptMethods.cpp index c27b5d7..fe10793 100644 --- a/src/ui/simple/ScriptMethods.cpp +++ b/src/ui/simple/ScriptMethods.cpp @@ -12,6 +12,7 @@ #include "ui/simple/CSimpleModelFFX.hpp" #include "ui/simple/CSimpleScrollFrame.hpp" #include "ui/simple/CSimpleSlider.hpp" +#include "ui/simple/CSimpleStatusBar.hpp" #include "ui/simple/CSimpleTexture.hpp" #include "util/CStatus.hpp" #include "util/Lua.hpp" @@ -190,9 +191,9 @@ void RegisterSimpleFrameScriptMethods() { CSimpleModelFFX::CreateScriptMetaTable(); CSimpleScrollFrame::CreateScriptMetaTable(); CSimpleSlider::CreateScriptMetaTable(); + CSimpleStatusBar::CreateScriptMetaTable(); // TODO - // CSimpleStatusBar::CreateScriptMetaTable(); // CSimpleColorSelect::CreateScriptMetaTable(); // CSimpleMovieFrame::CreateScriptMetaTable(); } From 85b7537faa76889d8fde5a9f96c9525bab6220bd Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 30 Jan 2026 19:39:49 -0600 Subject: [PATCH 123/269] feat(ui): add TOOLTIP_ANCHORPOINT --- src/ui/Types.hpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/ui/Types.hpp b/src/ui/Types.hpp index 23cf83e..dbfccea 100644 --- a/src/ui/Types.hpp +++ b/src/ui/Types.hpp @@ -98,6 +98,21 @@ enum TextureImageMode { ImageMode_Desaturate = 1 }; +enum TOOLTIP_ANCHORPOINT { + TOOLTIP_ANCHOR_LEFT = 0, + TOOLTIP_ANCHOR_RIGHT = 1, + TOOLTIP_ANCHOR_BOTTOMLEFT = 2, + TOOLTIP_ANCHOR_BOTTOM = 3, + TOOLTIP_ANCHOR_BOTTOMRIGHT = 4, + TOOLTIP_ANCHOR_TOPLEFT = 5, + TOOLTIP_ANCHOR_TOP = 6, + TOOLTIP_ANCHOR_TOPRIGHT = 7, + TOOLTIP_ANCHOR_CURSOR = 8, + TOOLTIP_ANCHOR_NONE = 9, + TOOLTIP_ANCHOR_PRESERVE = 10, + TOOLTIP_ANCHOR_CURSOR_RIGHT = 11, +}; + struct FRAMEPRIORITY { CSimpleFrame* frame; uint32_t priority; From bdef61479d9f4688c72bbe883823a90c1614745e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 30 Jan 2026 19:53:03 -0600 Subject: [PATCH 124/269] feat(ui): implement CGTooltip_IsOwned --- src/ui/game/CGTooltip.hpp | 4 ++++ src/ui/game/CGTooltipScript.cpp | 32 +++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/ui/game/CGTooltip.hpp b/src/ui/game/CGTooltip.hpp index f6a5961..5914f0e 100644 --- a/src/ui/game/CGTooltip.hpp +++ b/src/ui/game/CGTooltip.hpp @@ -16,6 +16,10 @@ class CGTooltip : public CSimpleFrame { static void RegisterScriptMethods(lua_State* L); // Member variables + CSimpleFrame* m_owner = nullptr; + TOOLTIP_ANCHORPOINT m_anchorPoint; + // TODO + C2Vector m_offset; // TODO // Virtual member functions diff --git a/src/ui/game/CGTooltipScript.cpp b/src/ui/game/CGTooltipScript.cpp index 91b296d..cd4c1bd 100644 --- a/src/ui/game/CGTooltipScript.cpp +++ b/src/ui/game/CGTooltipScript.cpp @@ -1,5 +1,7 @@ #include "ui/game/CGTooltipScript.hpp" +#include "ui/game/CGTooltip.hpp" #include "ui/FrameScript.hpp" +#include "util/Lua.hpp" #include "util/Unimplemented.hpp" namespace { @@ -25,7 +27,35 @@ int32_t CGTooltip_GetPadding(lua_State* L) { } int32_t CGTooltip_IsOwned(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CGTooltip::GetObjectType(); + auto tooltip = static_cast(FrameScript_GetObjectThis(L, type)); + + if (lua_type(L, 2) != LUA_TTABLE) { + luaL_error(L, "Usage: %s:IsOwned(frame)", tooltip->GetDisplayName()); + return 0; + } + + lua_rawgeti(L, 2, 0); + auto frame = static_cast(lua_touserdata(L, -1)); + lua_settop(L, -2); + + if (!frame) { + luaL_error(L, "%s:IsOwned(): Couldn't find 'this' in frame object", tooltip->GetDisplayName()); + return 0; + } + + if (!frame->IsA(CSimpleFrame::GetObjectType())) { + luaL_error(L, "%s:IsOwned(): Wrong object type, expected frame", tooltip->GetDisplayName()); + return 0; + } + + if (tooltip->m_owner == frame) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + + return 1; } int32_t CGTooltip_GetOwner(lua_State* L) { From 3d7d000190460936d10e548cd2ffc4ea634a4256 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 30 Jan 2026 20:45:05 -0600 Subject: [PATCH 125/269] feat(ui): implement Script_RequestBattlefieldPositions --- src/ui/game/BattlefieldInfoScript.cpp | 5 ++++- src/ui/game/CGBattlefieldInfo.cpp | 5 +++++ src/ui/game/CGBattlefieldInfo.hpp | 10 ++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/ui/game/CGBattlefieldInfo.cpp create mode 100644 src/ui/game/CGBattlefieldInfo.hpp diff --git a/src/ui/game/BattlefieldInfoScript.cpp b/src/ui/game/BattlefieldInfoScript.cpp index 11c22c8..5c0929a 100644 --- a/src/ui/game/BattlefieldInfoScript.cpp +++ b/src/ui/game/BattlefieldInfoScript.cpp @@ -1,4 +1,5 @@ #include "ui/game/BattlefieldInfoScript.hpp" +#include "ui/game/CGBattlefieldInfo.hpp" #include "ui/FrameScript.hpp" #include "util/Unimplemented.hpp" @@ -105,7 +106,9 @@ int32_t Script_GetBattlefieldStatData(lua_State* L) { } int32_t Script_RequestBattlefieldPositions(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + CGBattlefieldInfo::RequestPlayerPositions(); + + return 0; } int32_t Script_GetNumBattlefieldPositions(lua_State* L) { diff --git a/src/ui/game/CGBattlefieldInfo.cpp b/src/ui/game/CGBattlefieldInfo.cpp new file mode 100644 index 0000000..7f9eef1 --- /dev/null +++ b/src/ui/game/CGBattlefieldInfo.cpp @@ -0,0 +1,5 @@ +#include "ui/game/CGBattlefieldInfo.hpp" + +void CGBattlefieldInfo::RequestPlayerPositions() { + // TODO +} diff --git a/src/ui/game/CGBattlefieldInfo.hpp b/src/ui/game/CGBattlefieldInfo.hpp new file mode 100644 index 0000000..ccf2bac --- /dev/null +++ b/src/ui/game/CGBattlefieldInfo.hpp @@ -0,0 +1,10 @@ +#ifndef UI_GAME_C_G_BATTLEFIELD_INFO_HPP +#define UI_GAME_C_G_BATTLEFIELD_INFO_HPP + +class CGBattlefieldInfo { + public: + // Static functions + static void RequestPlayerPositions(); +}; + +#endif From 2c181e436c5ad71215cc2cda3611086176a5a737 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 30 Jan 2026 20:57:48 -0600 Subject: [PATCH 126/269] feat(ui): add CGTooltip::IsA --- src/ui/game/CGTooltip.cpp | 7 +++++++ src/ui/game/CGTooltip.hpp | 1 + 2 files changed, 8 insertions(+) diff --git a/src/ui/game/CGTooltip.cpp b/src/ui/game/CGTooltip.cpp index 328dd4b..d45687c 100644 --- a/src/ui/game/CGTooltip.cpp +++ b/src/ui/game/CGTooltip.cpp @@ -35,3 +35,10 @@ CGTooltip::CGTooltip(CSimpleFrame* parent) : CSimpleFrame(parent) { int32_t CGTooltip::GetScriptMetaTable() { return CGTooltip::s_metatable; } + +bool CGTooltip::IsA(int32_t type) { + return type == CGTooltip::s_objectType + || type == CSimpleFrame::s_objectType + || type == CScriptRegion::s_objectType + || type == CScriptObject::s_objectType; +} diff --git a/src/ui/game/CGTooltip.hpp b/src/ui/game/CGTooltip.hpp index 5914f0e..1410350 100644 --- a/src/ui/game/CGTooltip.hpp +++ b/src/ui/game/CGTooltip.hpp @@ -23,6 +23,7 @@ class CGTooltip : public CSimpleFrame { // TODO // Virtual member functions + virtual bool IsA(int32_t type); virtual int32_t GetScriptMetaTable(); // Member functions From 22eb04e495693941750903b2681dbe8bfeb7d62d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 30 Jan 2026 21:41:01 -0600 Subject: [PATCH 127/269] feat(ui): implement CSimpleButton_GetFontString --- src/ui/simple/CSimpleButtonScript.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleButtonScript.cpp b/src/ui/simple/CSimpleButtonScript.cpp index e5bc4df..f820b9d 100644 --- a/src/ui/simple/CSimpleButtonScript.cpp +++ b/src/ui/simple/CSimpleButtonScript.cpp @@ -218,7 +218,22 @@ int32_t CSimpleButton_SetFontString(lua_State* L) { } int32_t CSimpleButton_GetFontString(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleButton::GetObjectType(); + auto button = static_cast(FrameScript_GetObjectThis(L, type)); + auto text = button->m_text; + + if (!text) { + lua_pushnil(L); + return 1; + } + + if (!text->lua_registered) { + text->RegisterScriptObject(nullptr); + } + + lua_rawgeti(L, LUA_REGISTRYINDEX, text->lua_objectRef); + + return 1; } int32_t CSimpleButton_SetText(lua_State* L) { From 0cf12c9c9040f435f6a10c9bb4cb937a95eee6ad Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 31 Jan 2026 23:47:29 -0600 Subject: [PATCH 128/269] feat(ui): add CGGameUI::GetLockedTarget --- src/ui/game/CGGameUI.cpp | 7 ++++++- src/ui/game/CGGameUI.hpp | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 21bd423..0187f65 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -23,6 +23,7 @@ CScriptObject* CGGameUI::s_gameTooltip; CSimpleTop* CGGameUI::s_simpleTop; +WOWGUID CGGameUI::s_lockedTarget; void LoadScriptFunctions() { // TODO @@ -57,6 +58,10 @@ void LoadScriptFunctions() { // TODO } +WOWGUID& CGGameUI::GetLockedTarget() { + return CGGameUI::s_lockedTarget; +} + void CGGameUI::Initialize() { // TODO @@ -131,7 +136,7 @@ void CGGameUI::Initialize() { // TODO CGGameUI::s_gameTooltip = CScriptObject::GetScriptObjectByName("GameTooltip", CGTooltip::GetObjectType()); - // TODO STORM_ASSERT(CGGameUI::s_gameTooltip); + STORM_ASSERT(CGGameUI::s_gameTooltip); // TODO } diff --git a/src/ui/game/CGGameUI.hpp b/src/ui/game/CGGameUI.hpp index 567ab2f..062d8b9 100644 --- a/src/ui/game/CGGameUI.hpp +++ b/src/ui/game/CGGameUI.hpp @@ -1,6 +1,8 @@ #ifndef UI_GAME_C_G_GAME_UI_HPP #define UI_GAME_C_G_GAME_UI_HPP +#include "util/guid/Types.hpp" + class CScriptObject; class CSimpleTop; @@ -11,9 +13,13 @@ class CGGameUI { static CSimpleTop* s_simpleTop; // Static functions + static WOWGUID& GetLockedTarget(); static void Initialize(); static void InitializeGame(); static void RegisterFrameFactories(); + + private: + static WOWGUID s_lockedTarget; }; #endif From e7abae11022cde6d13deae07b46417d318a71c9a Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 1 Feb 2026 13:03:52 -0600 Subject: [PATCH 129/269] feat(object): add CGObject::GetGUID --- src/object/client/CGObject.cpp | 4 ++++ src/object/client/CGObject.hpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/object/client/CGObject.cpp b/src/object/client/CGObject.cpp index d292eec..97bf379 100644 --- a/src/object/client/CGObject.cpp +++ b/src/object/client/CGObject.cpp @@ -23,3 +23,7 @@ uint32_t CGObject::TotalFields() { uint32_t CGObject::TotalFieldsSaved() { return CGObject::GetBaseOffsetSaved() + 3; } + +WOWGUID CGObject::GetGUID() const { + return this->m_obj->m_guid; +} diff --git a/src/object/client/CGObject.hpp b/src/object/client/CGObject.hpp index 91b868e..1d1bfd7 100644 --- a/src/object/client/CGObject.hpp +++ b/src/object/client/CGObject.hpp @@ -29,6 +29,9 @@ class CGObject { uint32_t* m_objSaved; uint32_t m_memHandle; OBJECT_TYPE_ID m_typeID; + + // Public member functions + WOWGUID GetGUID() const; }; #endif From 1891bdc5eaa19882dc07242459e84d7688c8add4 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 1 Feb 2026 13:04:16 -0600 Subject: [PATCH 130/269] feat(object): add player class to object client header --- src/object/Client.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/object/Client.hpp b/src/object/Client.hpp index 24a5c2b..3675649 100644 --- a/src/object/Client.hpp +++ b/src/object/Client.hpp @@ -1,6 +1,7 @@ #ifndef OBJECT_CLIENT_HPP #define OBJECT_CLIENT_HPP +#include "client/CGPlayer_C.hpp" #include "client/ObjMgr.hpp" #include "object/Types.hpp" From f5171c0c6caff1a6656cce729c14723ac074b088 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 1 Feb 2026 13:04:37 -0600 Subject: [PATCH 131/269] feat(ui): add CGGameUI::IsRaidMember --- src/ui/game/CGGameUI.cpp | 6 ++++++ src/ui/game/CGGameUI.hpp | 1 + 2 files changed, 7 insertions(+) diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 0187f65..ea8a3fb 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -149,6 +149,12 @@ void CGGameUI::InitializeGame() { // TODO } +int32_t CGGameUI::IsRaidMember(const WOWGUID& guid) { + // TODO + + return false; +} + void CGGameUI::RegisterFrameFactories() { FrameXML_RegisterFactory("WorldFrame", &CGWorldFrame::Create, true); FrameXML_RegisterFactory("GameTooltip", &CGTooltip::Create, false); diff --git a/src/ui/game/CGGameUI.hpp b/src/ui/game/CGGameUI.hpp index 062d8b9..2cf3c8b 100644 --- a/src/ui/game/CGGameUI.hpp +++ b/src/ui/game/CGGameUI.hpp @@ -16,6 +16,7 @@ class CGGameUI { static WOWGUID& GetLockedTarget(); static void Initialize(); static void InitializeGame(); + static int32_t IsRaidMember(const WOWGUID& guid); static void RegisterFrameFactories(); private: From bc3b469266df3c2f747098d758159eaa111b9c2d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 1 Feb 2026 13:05:32 -0600 Subject: [PATCH 132/269] feat(ui): add Script_GetGUIDFromToken --- src/ui/game/ScriptUtil.cpp | 157 +++++++++++++++++++++++++++++++++++++ src/ui/game/ScriptUtil.hpp | 8 ++ 2 files changed, 165 insertions(+) create mode 100644 src/ui/game/ScriptUtil.cpp create mode 100644 src/ui/game/ScriptUtil.hpp diff --git a/src/ui/game/ScriptUtil.cpp b/src/ui/game/ScriptUtil.cpp new file mode 100644 index 0000000..9ac1fed --- /dev/null +++ b/src/ui/game/ScriptUtil.cpp @@ -0,0 +1,157 @@ +#include "ui/game/ScriptUtil.hpp" +#include "object/Client.hpp" +#include "ui/game/CGGameUI.hpp" +#include + +bool Script_GetGUIDFromToken(const char* token, WOWGUID& guid, bool defaultToTarget) { + auto activePlayer = static_cast(ClntObjMgrObjectPtr(ClntObjMgrGetActivePlayer(), TYPE_PLAYER, __FILE__, __LINE__)); + + // Null or empty token + if (token == nullptr || *token == '\0') { + if (defaultToTarget) { + guid = CGGameUI::GetLockedTarget(); + + return true; + } + + return false; + } + + guid = 0; + auto parseToken = token; + + // player - active player + if (!SStrCmpI(parseToken, "player", 6)) { + parseToken += 6; + + if (activePlayer) { + guid = activePlayer->GetGUID(); + } + } + + // vehicle - active player's vehicle + else if (!SStrCmpI(parseToken, "vehicle", 7)) { + parseToken += 7; + + // TODO + } + + // pet - active player's pet + else if (!SStrCmpI(parseToken, "pet", 3)) { + parseToken += 3; + + // TODO + } + + // target - current locked target + else if (!SStrCmpI(parseToken, "target", 6)) { + parseToken += 6; + + guid = CGGameUI::GetLockedTarget(); + } + + // partypet1-4 - party member's pet + else if (!SStrCmpI(parseToken, "partypet", 8)) { + parseToken += 8; + + auto index = SStrToUnsigned(parseToken); + // TODO + } + + // party1-4 - party member + else if (!SStrCmpI(parseToken, "party", 5)) { + parseToken += 5; + + auto index = SStrToUnsigned(parseToken); + // TODO + } + + // raidpet1-40 - raid member's pet + else if (!SStrCmpI(parseToken, "raidpet", 7)) { + parseToken += 7; + + auto index = SStrToUnsigned(parseToken); + // TODO + } + + // raid1-40 - raid member + else if (!SStrCmpI(parseToken, "raid", 4)) { + parseToken += 4; + + auto index = SStrToUnsigned(parseToken); + // TODO + } + + // boss1-5 - boss unit + else if (!SStrCmpI(parseToken, "boss", 4)) { + parseToken += 4; + + auto index = SStrToUnsigned(parseToken); + // TODO + } + + // arenapet1-5 - arena opponent's pet + else if (!SStrCmpI(parseToken, "arenapet", 8)) { + parseToken += 8; + + auto index = SStrToUnsigned(parseToken); + // TODO + } + + // arena1-5 - arena opponent + else if (!SStrCmpI(parseToken, "arena", 5)) { + parseToken += 5; + + auto index = SStrToUnsigned(parseToken); + // TODO + } + + // commentator1-N - commentator arena member + else if (!SStrCmpI(parseToken, "commentator", 11)) { + parseToken += 11; + + auto index = SStrToUnsigned(parseToken); + // TODO + } + + // mouseover - object under cursor + else if (!SStrCmpI(parseToken, "mouseover", 9)) { + parseToken += 9; + + // TODO + } + + // focus - focus target + else if (!SStrCmpI(parseToken, "focus", 5)) { + parseToken += 5; + + // TODO + } + + // npc - NPC interaction target + else if (!SStrCmpI(parseToken, "npc")) { + parseToken += 3; + + // TODO + } + + // questnpc - quest giver NPC + else if (!SStrCmpI(parseToken, "questnpc")) { + parseToken += 8; + + // TODO + } + + // none + else if (!SStrCmpI(parseToken, "none")) { + parseToken += 4; + + guid = -1; + } + + // TODO ParseTrailingTokens + // TODO Script_GetGUIDFromString + // TODO guid -2 + + return false; +} diff --git a/src/ui/game/ScriptUtil.hpp b/src/ui/game/ScriptUtil.hpp new file mode 100644 index 0000000..9cdf7ea --- /dev/null +++ b/src/ui/game/ScriptUtil.hpp @@ -0,0 +1,8 @@ +#ifndef UI_GAME_SCRIPT_UTIL_HPP +#define UI_GAME_SCRIPT_UTIL_HPP + +#include "util/GUID.hpp" + +bool Script_GetGUIDFromToken(const char* token, WOWGUID& guid, bool defaultToTarget); + +#endif From 184d3b041f73f21657c4077f4df3ed3253cb7222 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 1 Feb 2026 13:05:52 -0600 Subject: [PATCH 133/269] feat(ui): implement Script_UnitIsPlayer --- src/ui/game/ScriptEvents.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/ui/game/ScriptEvents.cpp b/src/ui/game/ScriptEvents.cpp index 0367bee..ca4b472 100644 --- a/src/ui/game/ScriptEvents.cpp +++ b/src/ui/game/ScriptEvents.cpp @@ -1,6 +1,11 @@ #include "ui/game/ScriptEvents.hpp" +#include "object/client/ObjMgr.hpp" #include "ui/FrameScript.hpp" #include "ui/ScriptFunctionsSystem.hpp" +#include "ui/game/CGGameUI.hpp" +#include "ui/game/ScriptUtil.hpp" +#include "util/GUID.hpp" +#include "util/Lua.hpp" #include "util/Unimplemented.hpp" namespace { @@ -18,7 +23,19 @@ int32_t Script_UnitIsUnit(lua_State* L) { } int32_t Script_UnitIsPlayer(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto token = lua_tostring(L, 1); + WOWGUID guid = 0; + Script_GetGUIDFromToken(token, guid, false); + + auto object = ClntObjMgrObjectPtr(guid, TYPE_PLAYER, __FILE__, __LINE__); + + if (object || CGGameUI::IsRaidMember(guid)) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + + return 1; } int32_t Script_UnitIsInMyGuild(lua_State* L) { From 99c00ade9be54019c783658f6631e55ad7453041 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 1 Feb 2026 20:16:33 -0600 Subject: [PATCH 134/269] feat(ui): add CGGameUI::GetCurrentObjectTrack --- src/ui/game/CGGameUI.cpp | 7 ++++++- src/ui/game/CGGameUI.hpp | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index ea8a3fb..8a5f8bd 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -21,9 +21,10 @@ #include "util/CStatus.hpp" #include +WOWGUID CGGameUI::s_currentObjectTrack; CScriptObject* CGGameUI::s_gameTooltip; -CSimpleTop* CGGameUI::s_simpleTop; WOWGUID CGGameUI::s_lockedTarget; +CSimpleTop* CGGameUI::s_simpleTop; void LoadScriptFunctions() { // TODO @@ -58,6 +59,10 @@ void LoadScriptFunctions() { // TODO } +WOWGUID& CGGameUI::GetCurrentObjectTrack() { + return CGGameUI::s_currentObjectTrack; +} + WOWGUID& CGGameUI::GetLockedTarget() { return CGGameUI::s_lockedTarget; } diff --git a/src/ui/game/CGGameUI.hpp b/src/ui/game/CGGameUI.hpp index 2cf3c8b..0044be8 100644 --- a/src/ui/game/CGGameUI.hpp +++ b/src/ui/game/CGGameUI.hpp @@ -13,6 +13,7 @@ class CGGameUI { static CSimpleTop* s_simpleTop; // Static functions + static WOWGUID& GetCurrentObjectTrack(); static WOWGUID& GetLockedTarget(); static void Initialize(); static void InitializeGame(); @@ -20,6 +21,7 @@ class CGGameUI { static void RegisterFrameFactories(); private: + static WOWGUID s_currentObjectTrack; static WOWGUID s_lockedTarget; }; From 43cb20cd0fae14ce0932253eaa63632f12de89d7 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 1 Feb 2026 20:22:17 -0600 Subject: [PATCH 135/269] feat(ui): add CGGameUI::IsRaidMemberOrPet --- src/ui/game/CGGameUI.cpp | 6 ++++++ src/ui/game/CGGameUI.hpp | 1 + 2 files changed, 7 insertions(+) diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 8a5f8bd..f0f40a9 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -160,6 +160,12 @@ int32_t CGGameUI::IsRaidMember(const WOWGUID& guid) { return false; } +int32_t CGGameUI::IsRaidMemberOrPet(const WOWGUID& guid) { + // TODO + + return false; +} + void CGGameUI::RegisterFrameFactories() { FrameXML_RegisterFactory("WorldFrame", &CGWorldFrame::Create, true); FrameXML_RegisterFactory("GameTooltip", &CGTooltip::Create, false); diff --git a/src/ui/game/CGGameUI.hpp b/src/ui/game/CGGameUI.hpp index 0044be8..2fc782b 100644 --- a/src/ui/game/CGGameUI.hpp +++ b/src/ui/game/CGGameUI.hpp @@ -18,6 +18,7 @@ class CGGameUI { static void Initialize(); static void InitializeGame(); static int32_t IsRaidMember(const WOWGUID& guid); + static int32_t IsRaidMemberOrPet(const WOWGUID& guid); static void RegisterFrameFactories(); private: From 6e1eb93ff9b65494ed09d30698c03a0bbbb1c967 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 1 Feb 2026 20:22:56 -0600 Subject: [PATCH 136/269] feat(ui): implement post-token-parsing logic in Script_GetGUIDFromToken --- src/ui/game/ScriptUtil.cpp | 42 ++++++++++++++++++++++++++++++++++---- src/ui/game/ScriptUtil.hpp | 2 ++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/ui/game/ScriptUtil.cpp b/src/ui/game/ScriptUtil.cpp index 9ac1fed..0f5a809 100644 --- a/src/ui/game/ScriptUtil.cpp +++ b/src/ui/game/ScriptUtil.cpp @@ -3,6 +3,20 @@ #include "ui/game/CGGameUI.hpp" #include +namespace { + +bool ParseTrailingTokens(const char* token, WOWGUID& guid, CGPlayer_C* player) { + // TODO + return true; +} + +} + +bool Script_GetGUIDFromString(const char*& token, WOWGUID& guid) { + // TODO + return true; +} + bool Script_GetGUIDFromToken(const char* token, WOWGUID& guid, bool defaultToTarget) { auto activePlayer = static_cast(ClntObjMgrObjectPtr(ClntObjMgrGetActivePlayer(), TYPE_PLAYER, __FILE__, __LINE__)); @@ -118,7 +132,11 @@ bool Script_GetGUIDFromToken(const char* token, WOWGUID& guid, bool defaultToTar else if (!SStrCmpI(parseToken, "mouseover", 9)) { parseToken += 9; - // TODO + auto trackedObjectGuid = CGGameUI::GetCurrentObjectTrack(); + + if (ClntObjMgrObjectPtr(trackedObjectGuid, TYPE_UNIT, __FILE__, __LINE__) || CGGameUI::IsRaidMemberOrPet(trackedObjectGuid)) { + guid = trackedObjectGuid; + } } // focus - focus target @@ -149,9 +167,25 @@ bool Script_GetGUIDFromToken(const char* token, WOWGUID& guid, bool defaultToTar guid = -1; } - // TODO ParseTrailingTokens - // TODO Script_GetGUIDFromString - // TODO guid -2 + // Token string was fully parsed or GUID was determined and token string potentially includes + // trailing tokens + if ((*parseToken == '\0' || guid) && ParseTrailingTokens(parseToken, guid, activePlayer)) { + if (!guid) { + guid = -2; + } + return true; + } + + // Token string was either not parsed or only partially parsed and GUID was not determined + if (!guid && Script_GetGUIDFromString(token, guid) && ParseTrailingTokens(token, guid, activePlayer)) { + if (!guid) { + guid = -2; + } + + return true; + } + + // GUID was not successfully determined return false; } diff --git a/src/ui/game/ScriptUtil.hpp b/src/ui/game/ScriptUtil.hpp index 9cdf7ea..c06aa58 100644 --- a/src/ui/game/ScriptUtil.hpp +++ b/src/ui/game/ScriptUtil.hpp @@ -3,6 +3,8 @@ #include "util/GUID.hpp" +bool Script_GetGUIDFromString(const char*& token, WOWGUID& guid); + bool Script_GetGUIDFromToken(const char* token, WOWGUID& guid, bool defaultToTarget); #endif From 4d0c48be5260eeb577a7af1d368792024fc57681 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 2 Feb 2026 08:20:49 -0600 Subject: [PATCH 137/269] feat(object): add model member to CGObject_C --- src/object/client/CGObject_C.cpp | 4 ++++ src/object/client/CGObject_C.hpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index f78ad1a..dea307c 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -5,6 +5,10 @@ CGObject_C::CGObject_C(uint32_t time, CClientObjCreate& objCreate) { // TODO + this->m_model = nullptr; + + // TODO + this->m_lockCount = 0; this->m_disabled = false; this->m_inReenable = false; diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index d6b9436..5904559 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -8,12 +8,16 @@ #include #include +class CM2Model; + class CGObject_C : public CGObject, public TSHashObject { public: // Public member variables TSLink m_link; uint32_t m_disableTimeMs; // TODO + CM2Model* m_model; + // TODO uint32_t m_lockCount : 16; uint32_t m_disabled : 1; uint32_t m_inReenable : 1; From 87ae3b512b19bd65cfb9f9835ad9be0019a15bdf Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 2 Feb 2026 08:47:50 -0600 Subject: [PATCH 138/269] feat(object): clean up data struct visibility --- src/object/client/CGContainer.cpp | 4 ++++ src/object/client/CGContainer.hpp | 6 +++++- src/object/client/CGCorpse.cpp | 4 ++++ src/object/client/CGCorpse.hpp | 6 +++++- src/object/client/CGDynamicObject.cpp | 4 ++++ src/object/client/CGDynamicObject.hpp | 6 +++++- src/object/client/CGGameObject.cpp | 4 ++++ src/object/client/CGGameObject.hpp | 6 +++++- src/object/client/CGItem.cpp | 4 ++++ src/object/client/CGItem.hpp | 6 +++++- src/object/client/CGObject.cpp | 12 ++++++++++++ src/object/client/CGObject.hpp | 14 +++++++++++--- src/object/client/CGPlayer.cpp | 4 ++++ src/object/client/CGPlayer.hpp | 6 +++++- src/object/client/CGUnit.cpp | 4 ++++ src/object/client/CGUnit.hpp | 6 +++++- src/object/client/MessageHandlers.cpp | 8 ++++---- src/object/client/Mirror.cpp | 6 +++--- src/object/client/ObjMgr.cpp | 12 ++++++------ src/object/client/Util.cpp | 4 ++-- 20 files changed, 101 insertions(+), 25 deletions(-) diff --git a/src/object/client/CGContainer.cpp b/src/object/client/CGContainer.cpp index 0c9b943..b6080fa 100644 --- a/src/object/client/CGContainer.cpp +++ b/src/object/client/CGContainer.cpp @@ -24,3 +24,7 @@ uint32_t CGContainer::TotalFields() { uint32_t CGContainer::TotalFieldsSaved() { return CGContainer::GetBaseOffsetSaved() + 72; } + +CGContainerData* CGContainer::Container() const { + return this->m_cont; +} diff --git a/src/object/client/CGContainer.hpp b/src/object/client/CGContainer.hpp index 2134814..d0bd262 100644 --- a/src/object/client/CGContainer.hpp +++ b/src/object/client/CGContainer.hpp @@ -20,9 +20,13 @@ class CGContainer { static uint32_t TotalFields(); static uint32_t TotalFieldsSaved(); - // Public member variables + protected: + // Protected member variables CGContainerData* m_cont; uint32_t* m_contSaved; + + // Protected member functions + CGContainerData* Container() const; }; #endif diff --git a/src/object/client/CGCorpse.cpp b/src/object/client/CGCorpse.cpp index 3dd6ec2..2838f94 100644 --- a/src/object/client/CGCorpse.cpp +++ b/src/object/client/CGCorpse.cpp @@ -24,3 +24,7 @@ uint32_t CGCorpse::TotalFields() { uint32_t CGCorpse::TotalFieldsSaved() { return CGCorpse::GetBaseOffsetSaved() + 3; } + +CGCorpseData* CGCorpse::Corpse() const { + return this->m_corpse; +} diff --git a/src/object/client/CGCorpse.hpp b/src/object/client/CGCorpse.hpp index be7add3..93d19e7 100644 --- a/src/object/client/CGCorpse.hpp +++ b/src/object/client/CGCorpse.hpp @@ -17,9 +17,13 @@ class CGCorpse { static uint32_t TotalFields(); static uint32_t TotalFieldsSaved(); - // Public member variables + protected: + // Protected member variables CGCorpseData* m_corpse; uint32_t* m_corpseSaved; + + // Protected member functions + CGCorpseData* Corpse() const; }; #endif diff --git a/src/object/client/CGDynamicObject.cpp b/src/object/client/CGDynamicObject.cpp index f55ca10..bec80ac 100644 --- a/src/object/client/CGDynamicObject.cpp +++ b/src/object/client/CGDynamicObject.cpp @@ -24,3 +24,7 @@ uint32_t CGDynamicObject::TotalFields() { uint32_t CGDynamicObject::TotalFieldsSaved() { return CGDynamicObject::GetBaseOffsetSaved() + 0; } + +CGDynamicObjectData* CGDynamicObject::DynamicObject() const { + return this->m_dynamicObj; +} diff --git a/src/object/client/CGDynamicObject.hpp b/src/object/client/CGDynamicObject.hpp index 8f68718..1292973 100644 --- a/src/object/client/CGDynamicObject.hpp +++ b/src/object/client/CGDynamicObject.hpp @@ -17,9 +17,13 @@ class CGDynamicObject { static uint32_t TotalFields(); static uint32_t TotalFieldsSaved(); - // Public member variables + protected: + // Protected member variables CGDynamicObjectData* m_dynamicObj; uint32_t* m_dynamicObjSaved; + + // Protected member functions + CGDynamicObjectData* DynamicObject() const; }; #endif diff --git a/src/object/client/CGGameObject.cpp b/src/object/client/CGGameObject.cpp index 5a498f5..76b81c6 100644 --- a/src/object/client/CGGameObject.cpp +++ b/src/object/client/CGGameObject.cpp @@ -24,3 +24,7 @@ uint32_t CGGameObject::TotalFields() { uint32_t CGGameObject::TotalFieldsSaved() { return CGGameObject::GetBaseOffsetSaved() + 4; } + +CGGameObjectData* CGGameObject::GameObject() const { + return this->m_gameObj; +} diff --git a/src/object/client/CGGameObject.hpp b/src/object/client/CGGameObject.hpp index 5469f1f..1f19c12 100644 --- a/src/object/client/CGGameObject.hpp +++ b/src/object/client/CGGameObject.hpp @@ -17,9 +17,13 @@ class CGGameObject { static uint32_t TotalFields(); static uint32_t TotalFieldsSaved(); - // Public member variables + protected: + // Protected member variables CGGameObjectData* m_gameObj; uint32_t* m_gameObjSaved; + + // Protected member functions + CGGameObjectData* GameObject() const; }; #endif diff --git a/src/object/client/CGItem.cpp b/src/object/client/CGItem.cpp index 5c849cb..7a012c0 100644 --- a/src/object/client/CGItem.cpp +++ b/src/object/client/CGItem.cpp @@ -24,3 +24,7 @@ uint32_t CGItem::TotalFields() { uint32_t CGItem::TotalFieldsSaved() { return CGItem::GetBaseOffsetSaved() + 47; } + +CGItemData* CGItem::Item() const { + return this->m_item; +} diff --git a/src/object/client/CGItem.hpp b/src/object/client/CGItem.hpp index 2fda058..ec22654 100644 --- a/src/object/client/CGItem.hpp +++ b/src/object/client/CGItem.hpp @@ -38,9 +38,13 @@ class CGItem { static uint32_t TotalFields(); static uint32_t TotalFieldsSaved(); - // Public member variables + protected: + // Protected member variables CGItemData* m_item; uint32_t* m_itemSaved; + + // Protected member functions + CGItemData* Item() const; }; #endif diff --git a/src/object/client/CGObject.cpp b/src/object/client/CGObject.cpp index 97bf379..41236cf 100644 --- a/src/object/client/CGObject.cpp +++ b/src/object/client/CGObject.cpp @@ -27,3 +27,15 @@ uint32_t CGObject::TotalFieldsSaved() { WOWGUID CGObject::GetGUID() const { return this->m_obj->m_guid; } + +OBJECT_TYPE CGObject::GetType() const { + return this->m_obj->m_type; +} + +OBJECT_TYPE_ID CGObject::GetTypeID() const { + return this->m_typeID; +} + +CGObjectData* CGObject::Obj() const { + return this->m_obj; +} diff --git a/src/object/client/CGObject.hpp b/src/object/client/CGObject.hpp index 1d1bfd7..55f4514 100644 --- a/src/object/client/CGObject.hpp +++ b/src/object/client/CGObject.hpp @@ -25,13 +25,21 @@ class CGObject { // Public member variables uint32_t uint0; // TODO what is this? - CGObjectData* m_obj; - uint32_t* m_objSaved; uint32_t m_memHandle; - OBJECT_TYPE_ID m_typeID; // Public member functions WOWGUID GetGUID() const; + OBJECT_TYPE GetType() const; + OBJECT_TYPE_ID GetTypeID() const; + + protected: + // Protected member variables + CGObjectData* m_obj; + uint32_t* m_objSaved; + OBJECT_TYPE_ID m_typeID; + + // Protected member functions + CGObjectData* Obj() const; }; #endif diff --git a/src/object/client/CGPlayer.cpp b/src/object/client/CGPlayer.cpp index 5f30bcb..1e44711 100644 --- a/src/object/client/CGPlayer.cpp +++ b/src/object/client/CGPlayer.cpp @@ -40,3 +40,7 @@ uint32_t CGPlayer::TotalFieldsSaved() { uint32_t CGPlayer::TotalRemoteFieldsSaved() { return CGPlayer::GetBaseOffsetSaved() + 173; } + +CGPlayerData* CGPlayer::Player() const { + return this->m_player; +} diff --git a/src/object/client/CGPlayer.hpp b/src/object/client/CGPlayer.hpp index c20fd0c..707f39f 100644 --- a/src/object/client/CGPlayer.hpp +++ b/src/object/client/CGPlayer.hpp @@ -148,9 +148,13 @@ class CGPlayer { static uint32_t TotalFieldsSaved(); static uint32_t TotalRemoteFieldsSaved(); - // Public member variables + protected: + // Protected member variables CGPlayerData* m_player; uint32_t* m_playerSaved; + + // Protected member functions + CGPlayerData* Player() const; }; #endif diff --git a/src/object/client/CGUnit.cpp b/src/object/client/CGUnit.cpp index 05b42e2..4f525c8 100644 --- a/src/object/client/CGUnit.cpp +++ b/src/object/client/CGUnit.cpp @@ -24,3 +24,7 @@ uint32_t CGUnit::TotalFields() { uint32_t CGUnit::TotalFieldsSaved() { return CGUnit::GetBaseOffsetSaved() + 123; } + +CGUnitData* CGUnit::Unit() const { + return this->m_unit; +} diff --git a/src/object/client/CGUnit.hpp b/src/object/client/CGUnit.hpp index 0577be0..3fb6ddb 100644 --- a/src/object/client/CGUnit.hpp +++ b/src/object/client/CGUnit.hpp @@ -82,9 +82,13 @@ class CGUnit { static uint32_t TotalFields(); static uint32_t TotalFieldsSaved(); - // Public member variables + protected: + // Protected member variables CGUnitData* m_unit; uint32_t* m_unitSaved; + + // Protected member functions + CGUnitData* Unit() const; }; #endif diff --git a/src/object/client/MessageHandlers.cpp b/src/object/client/MessageHandlers.cpp index 72124ae..86679e6 100644 --- a/src/object/client/MessageHandlers.cpp +++ b/src/object/client/MessageHandlers.cpp @@ -61,7 +61,7 @@ int32_t PostInitObject(CDataStore* msg, uint32_t time, bool a3) { return 0; } - if (object->m_inReenable && object->m_obj->m_type & TYPE_UNIT) { + if (object->m_inReenable && object->GetType() & TYPE_UNIT) { // TODO } @@ -139,7 +139,7 @@ void PostMovementUpdate(CDataStore* msg) { return; } - unit->PostMovementUpdate(move, unit->m_obj->m_guid == CGUnit_C::s_activeMover); + unit->PostMovementUpdate(move, unit->GetGUID() == CGUnit_C::s_activeMover); if (reenable) { unit->Reenable(); @@ -201,7 +201,7 @@ int32_t UpdateObject(CDataStore* msg) { auto object = GetUpdateObject(guid, &reenable); if (object) { - if (!FillInPartialObjectData(object, object->m_obj->m_guid, msg, false, false)) { + if (!FillInPartialObjectData(object, object->GetGUID(), msg, false, false)) { return 0; } @@ -329,7 +329,7 @@ int32_t CreateObject(CDataStore* msg, uint32_t time) { if (existingObject) { CClientObjCreate::Skip(msg); - if (!FillInPartialObjectData(existingObject, existingObject->m_obj->m_guid, msg, false, true)) { + if (!FillInPartialObjectData(existingObject, existingObject->GetGUID(), msg, false, true)) { return 0; } diff --git a/src/object/client/Mirror.cpp b/src/object/client/Mirror.cpp index 762cefa..75554a5 100644 --- a/src/object/client/Mirror.cpp +++ b/src/object/client/Mirror.cpp @@ -91,7 +91,7 @@ uint32_t GetNumDwordBlocks(OBJECT_TYPE type, WOWGUID guid) { * to indicate the end of the hierarchy. */ OBJECT_TYPE_ID IncTypeID(CGObject_C* object, OBJECT_TYPE_ID curTypeID) { - switch (object->m_obj->m_type) { + switch (object->GetType()) { // ID_OBJECT -> ID_ITEM -> ID_CONTAINER case HIER_TYPE_ITEM: case HIER_TYPE_CONTAINER: @@ -173,7 +173,7 @@ int32_t CallMirrorHandlers(CDataStore* msg, bool a2, WOWGUID guid) { OBJECT_TYPE_ID typeID = ID_OBJECT; uint32_t blockOffset = 0; - uint32_t numBlocks = GetNumDwordBlocks(object->m_obj->m_type, guid); + uint32_t numBlocks = GetNumDwordBlocks(object->GetType(), guid); for (int32_t block = 0; block < numBlocks; block++) { if (block >= s_objMirrorBlocks[typeID]) { @@ -203,7 +203,7 @@ int32_t FillInPartialObjectData(CGObject_C* object, WOWGUID guid, CDataStore* ms OBJECT_TYPE_ID typeID = ID_OBJECT; uint32_t blockOffset = 0; - uint32_t numBlocks = GetNumDwordBlocks(object->m_obj->m_type, guid); + uint32_t numBlocks = GetNumDwordBlocks(object->GetType(), guid); for (int32_t block = 0; block < numBlocks; block++) { if (block >= s_objMirrorBlocks[typeID]) { diff --git a/src/object/client/ObjMgr.cpp b/src/object/client/ObjMgr.cpp index bcdb488..c817841 100644 --- a/src/object/client/ObjMgr.cpp +++ b/src/object/client/ObjMgr.cpp @@ -93,9 +93,9 @@ CGObject_C* ClntObjMgrAllocObject(OBJECT_TYPE_ID typeID, WOWGUID guid) { void ClntObjMgrFreeObject(CGObject_C* object) { auto playerGUID = ClntObjMgrGetActivePlayer(); - auto isActivePlayer = object->m_obj->m_guid == playerGUID; + auto isActivePlayer = object->GetGUID() == playerGUID; - switch (object->m_obj->m_type) { + switch (object->GetType()) { case TYPE_OBJECT: case HIER_TYPE_ITEM: case HIER_TYPE_CONTAINER: @@ -117,7 +117,7 @@ void ClntObjMgrFreeObject(CGObject_C* object) { if (isActivePlayer) { STORM_FREE(object); } else { - ObjectFree(s_objHeapId[object->m_typeID], object->m_memHandle); + ObjectFree(s_objHeapId[object->GetTypeID()], object->m_memHandle); } } @@ -171,8 +171,8 @@ void ClntObjMgrInitializeStd(uint32_t mapID) { } void ClntObjMgrLinkInNewObject(CGObject_C* object) { - CHashKeyGUID key(object->m_obj->m_guid); - s_curMgr->m_objects.Insert(object, object->m_obj->m_guid, key); + CHashKeyGUID key(object->GetGUID()); + s_curMgr->m_objects.Insert(object, object->GetGUID(), key); } CGObject_C* ClntObjMgrObjectPtr(WOWGUID guid, OBJECT_TYPE type, const char* fileName, int32_t lineNumber) { @@ -186,7 +186,7 @@ CGObject_C* ClntObjMgrObjectPtr(WOWGUID guid, OBJECT_TYPE type, const char* file return nullptr; } - if (!(object->m_obj->m_type & type)) { + if (!(object->GetType() & type)) { return nullptr; } diff --git a/src/object/client/Util.cpp b/src/object/client/Util.cpp index 5ac8c52..1d6f076 100644 --- a/src/object/client/Util.cpp +++ b/src/object/client/Util.cpp @@ -107,11 +107,11 @@ void HandleObjectOutOfRangePass2(CGObject_C* object) { } ClntObjMgrGetCurrent()->m_lazyCleanupObjects.Insert(object, object->m_hashval, CHashKeyGUID(object->m_key)); - ClntObjMgrGetCurrent()->m_lazyCleanupFifo[object->m_typeID - 1].LinkToTail(object); + ClntObjMgrGetCurrent()->m_lazyCleanupFifo[object->GetTypeID() - 1].LinkToTail(object); } void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate) { - switch (object->m_typeID) { + switch (object->GetTypeID()) { case ID_ITEM: { new (object) CGItem_C(time, objCreate); From 1c85269d1c3c270e16f07e340a397e6ba28494f3 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 2 Feb 2026 11:37:30 -0600 Subject: [PATCH 139/269] feat(object): add CGObject_C::CanHighlight --- src/object/client/CGObject_C.cpp | 4 ++++ src/object/client/CGObject_C.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index dea307c..98a4c0b 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -31,6 +31,10 @@ void CGObject_C::AddWorldObject() { // TODO } +int32_t CGObject_C::CanHighlight() { + return false; +} + void CGObject_C::Disable() { // TODO diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index 5904559..5bfd3f7 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -33,6 +33,7 @@ class CGObject_C : public CGObject, public TSHashObject Date: Mon, 2 Feb 2026 11:39:02 -0600 Subject: [PATCH 140/269] feat(object): add CGObject_C::CanBeTargetted --- src/object/client/CGObject_C.cpp | 4 ++++ src/object/client/CGObject_C.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 98a4c0b..284cac3 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -31,6 +31,10 @@ void CGObject_C::AddWorldObject() { // TODO } +int32_t CGObject_C::CanBeTargetted() { + return false; +} + int32_t CGObject_C::CanHighlight() { return false; } diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index 5bfd3f7..a0d9770 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -34,6 +34,7 @@ class CGObject_C : public CGObject, public TSHashObject Date: Mon, 2 Feb 2026 11:41:15 -0600 Subject: [PATCH 141/269] feat(object): add CGUnit_C::CanBeTargetted --- src/object/client/CGUnit_C.cpp | 4 ++++ src/object/client/CGUnit_C.hpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/object/client/CGUnit_C.cpp b/src/object/client/CGUnit_C.cpp index d182d2d..4b2320a 100644 --- a/src/object/client/CGUnit_C.cpp +++ b/src/object/client/CGUnit_C.cpp @@ -99,6 +99,10 @@ CGUnit_C::~CGUnit_C() { // TODO } +int32_t CGUnit_C::CanBeTargetted() { + return this->CanHighlight(); +} + void CGUnit_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { // TODO diff --git a/src/object/client/CGUnit_C.hpp b/src/object/client/CGUnit_C.hpp index f42fec0..a22e889 100644 --- a/src/object/client/CGUnit_C.hpp +++ b/src/object/client/CGUnit_C.hpp @@ -21,6 +21,9 @@ class CGUnit_C : public CGObject_C, public CGUnit { // Virtual public member functions virtual ~CGUnit_C(); + // TODO + virtual int32_t CanBeTargetted(); + // TODO // Public member functions CGUnit_C(uint32_t time, CClientObjCreate& objCreate); From 71b7b159dec5a829be1d7cbab1186da0eb5d4dc7 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 2 Feb 2026 16:45:58 -0600 Subject: [PATCH 142/269] feat(ui): add CGPetInfo --- src/ui/Game.hpp | 1 + src/ui/game/CGPetInfo.cpp | 6 ++++++ src/ui/game/CGPetInfo.hpp | 13 +++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 src/ui/game/CGPetInfo.cpp create mode 100644 src/ui/game/CGPetInfo.hpp diff --git a/src/ui/Game.hpp b/src/ui/Game.hpp index 6f5e712..e4431b0 100644 --- a/src/ui/Game.hpp +++ b/src/ui/Game.hpp @@ -2,5 +2,6 @@ #define UI_GAME_HPP #include "ui/game/CGGameUI.hpp" +#include "ui/game/CGPetInfo.hpp" #endif diff --git a/src/ui/game/CGPetInfo.cpp b/src/ui/game/CGPetInfo.cpp new file mode 100644 index 0000000..90c337d --- /dev/null +++ b/src/ui/game/CGPetInfo.cpp @@ -0,0 +1,6 @@ +#include "ui/game/CGPetInfo.hpp" + +WOWGUID CGPetInfo::GetPet(uint32_t index) { + // TODO + return 0; +} diff --git a/src/ui/game/CGPetInfo.hpp b/src/ui/game/CGPetInfo.hpp new file mode 100644 index 0000000..036ca81 --- /dev/null +++ b/src/ui/game/CGPetInfo.hpp @@ -0,0 +1,13 @@ +#ifndef UI_GAME_C_G_PET_INFO_HPP +#define UI_GAME_C_G_PET_INFO_HPP + +#include "util/GUID.hpp" +#include + +class CGPetInfo { + public: + // Static functions + static WOWGUID GetPet(uint32_t index); +}; + +#endif From 55e37fd7791394909b9651e568e0b3633e4e2f7c Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 2 Feb 2026 16:46:23 -0600 Subject: [PATCH 143/269] feat(object): add CGUnit_C::CanHighlight --- src/object/client/CGUnit_C.cpp | 12 ++++++++++++ src/object/client/CGUnit_C.hpp | 1 + 2 files changed, 13 insertions(+) diff --git a/src/object/client/CGUnit_C.cpp b/src/object/client/CGUnit_C.cpp index 4b2320a..11f32d2 100644 --- a/src/object/client/CGUnit_C.cpp +++ b/src/object/client/CGUnit_C.cpp @@ -1,5 +1,7 @@ #include "object/client/CGUnit_C.hpp" +#include "object/client/ObjMgr.hpp" #include "db/Db.hpp" +#include "ui/Game.hpp" WOWGUID CGUnit_C::s_activeMover; @@ -99,6 +101,16 @@ CGUnit_C::~CGUnit_C() { // TODO } +int32_t CGUnit_C::CanHighlight() { + if (this->m_unit->flags & 0x2000000) { + if (this->m_unit->createdBy != ClntObjMgrGetActivePlayer() || this->GetGUID() != CGPetInfo::GetPet(0)) { + return false; + } + } + + return true; +} + int32_t CGUnit_C::CanBeTargetted() { return this->CanHighlight(); } diff --git a/src/object/client/CGUnit_C.hpp b/src/object/client/CGUnit_C.hpp index a22e889..b3103ff 100644 --- a/src/object/client/CGUnit_C.hpp +++ b/src/object/client/CGUnit_C.hpp @@ -22,6 +22,7 @@ class CGUnit_C : public CGObject_C, public CGUnit { // Virtual public member functions virtual ~CGUnit_C(); // TODO + virtual int32_t CanHighlight(); virtual int32_t CanBeTargetted(); // TODO From e51df96e8d888352a2ebc06ed349d66902942f21 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 2 Feb 2026 16:46:42 -0600 Subject: [PATCH 144/269] feat(ui): implement Script_UnitExists --- src/ui/game/ScriptEvents.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/ui/game/ScriptEvents.cpp b/src/ui/game/ScriptEvents.cpp index ca4b472..25d33a3 100644 --- a/src/ui/game/ScriptEvents.cpp +++ b/src/ui/game/ScriptEvents.cpp @@ -11,7 +11,19 @@ namespace { int32_t Script_UnitExists(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto token = lua_tostring(L, 1); + WOWGUID guid = 0; + Script_GetGUIDFromToken(token, guid, false); + + auto object = ClntObjMgrObjectPtr(guid, TYPE_OBJECT, __FILE__, __LINE__); + + if ((object && object->CanBeTargetted()) || CGGameUI::IsRaidMemberOrPet(guid)) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + + return 1; } int32_t Script_UnitIsVisible(lua_State* L) { From 0962e5952e14ffda0836e05a914acf4c41c70a23 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 2 Feb 2026 20:30:52 -0600 Subject: [PATCH 145/269] feat(ui): implement Script_FillLocalizedClassList --- src/ui/game/ScriptEvents.cpp | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/ui/game/ScriptEvents.cpp b/src/ui/game/ScriptEvents.cpp index 25d33a3..f58cce5 100644 --- a/src/ui/game/ScriptEvents.cpp +++ b/src/ui/game/ScriptEvents.cpp @@ -1,11 +1,13 @@ #include "ui/game/ScriptEvents.hpp" -#include "object/client/ObjMgr.hpp" +#include "db/Db.hpp" +#include "object/Client.hpp" #include "ui/FrameScript.hpp" #include "ui/ScriptFunctionsSystem.hpp" #include "ui/game/CGGameUI.hpp" #include "ui/game/ScriptUtil.hpp" #include "util/GUID.hpp" #include "util/Lua.hpp" +#include "util/StringTo.hpp" #include "util/Unimplemented.hpp" namespace { @@ -707,7 +709,29 @@ int32_t Script_IsXPUserDisabled(lua_State* L) { } int32_t Script_FillLocalizedClassList(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (lua_type(L, 1) != LUA_TTABLE) { + luaL_error(L, "Usage: FillLocalizedClassList(classTable[, isFemale])"); + return 0; + } + + auto isFemale = StringToBOOL(L, 2, 0); + auto sex = isFemale ? UNITSEX_FEMALE : UNITSEX_MALE; + + lua_settop(L, 1); + + for (int32_t i = 0; i < g_chrClassesDB.GetNumRecords(); ++i) { + auto classRec = g_chrClassesDB.GetRecordByIndex(i); + if (classRec) { + auto displayName = CGUnit_C::GetDisplayClassNameFromRecord(classRec, sex, 0); + + lua_pushstring(L, classRec->m_filename); + lua_pushstring(L, displayName); + + lua_settable(L, -3); + } + } + + return 1; } } From b076c2c57380db49e3b1f4ca45abb29166a7fb39 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 2 Feb 2026 21:02:29 -0600 Subject: [PATCH 146/269] feat(ui): implement CSimpleFontString_GetText --- src/ui/simple/CSimpleFontStringScript.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleFontStringScript.cpp b/src/ui/simple/CSimpleFontStringScript.cpp index 62f2415..bffae37 100644 --- a/src/ui/simple/CSimpleFontStringScript.cpp +++ b/src/ui/simple/CSimpleFontStringScript.cpp @@ -162,7 +162,17 @@ int32_t CSimpleFontString_SetFont(lua_State* L) { } int32_t CSimpleFontString_GetText(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleFontString::GetObjectType(); + auto string = static_cast(FrameScript_GetObjectThis(L, type)); + + auto text = string->GetText(); + if (!text || !*text) { + text = nullptr; + } + + lua_pushstring(L, text); + + return 1; } int32_t CSimpleFontString_GetFieldSize(lua_State* L) { From f42416bd0b049a54d0467c53738a6683f57981a1 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 2 Feb 2026 21:09:56 -0600 Subject: [PATCH 147/269] feat(ui): implement CSimpleButton_GetTextHeight --- src/ui/simple/CSimpleButtonScript.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleButtonScript.cpp b/src/ui/simple/CSimpleButtonScript.cpp index f820b9d..bb38c57 100644 --- a/src/ui/simple/CSimpleButtonScript.cpp +++ b/src/ui/simple/CSimpleButtonScript.cpp @@ -372,7 +372,18 @@ int32_t CSimpleButton_GetTextWidth(lua_State* L) { } int32_t CSimpleButton_GetTextHeight(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleButton::GetObjectType(); + auto button = static_cast(FrameScript_GetObjectThis(L, type)); + + auto text = button->m_text; + + float height = text ? text->GetHeight() : 0.0f; + float ddcHeight = CoordinateGetAspectCompensation() * 1024.0f * height; + float ndcHeight = DDCToNDCWidth(ddcHeight); + + lua_pushnumber(L, ndcHeight); + + return 1; } int32_t CSimpleButton_RegisterForClicks(lua_State* L) { From 728d13b216a895cbf4be155ef5b4bb5d0e75b680 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 2 Feb 2026 22:13:40 -0600 Subject: [PATCH 148/269] fix(object): link to ui lib --- src/object/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/object/CMakeLists.txt b/src/object/CMakeLists.txt index a77c62e..e6cd5c6 100644 --- a/src/object/CMakeLists.txt +++ b/src/object/CMakeLists.txt @@ -16,4 +16,5 @@ target_include_directories(object target_link_libraries(object PRIVATE db + ui ) From ae64833a5c9f9cc637834928f1c6a2f123b23cab Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 2 Feb 2026 22:19:15 -0600 Subject: [PATCH 149/269] feat(ui): add CSimpleFrame::m_attributes --- src/ui/simple/CSimpleFrame.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ui/simple/CSimpleFrame.hpp b/src/ui/simple/CSimpleFrame.hpp index 2f08b23..39e8d19 100644 --- a/src/ui/simple/CSimpleFrame.hpp +++ b/src/ui/simple/CSimpleFrame.hpp @@ -6,6 +6,7 @@ #include "ui/CScriptRegion.hpp" #include "ui/Types.hpp" #include "ui/simple/CSimpleRegion.hpp" +#include #include #include @@ -17,6 +18,10 @@ class CSimpleTitleRegion; class CSimpleTop; struct lua_State; +struct FRAMEATTR : TSHashObject { + int32_t luaRef; +}; + class CSimpleFrame : public CScriptRegion { public: // Static members @@ -71,6 +76,7 @@ class CSimpleFrame : public CScriptRegion { ScriptIx m_onAttributeChange; ScriptIx m_onEnable; ScriptIx m_onDisable; + TSHashTable m_attributes; int32_t m_drawenabled[NUM_SIMPLEFRAME_DRAWLAYERS]; CBackdropGenerator* m_backdrop = nullptr; STORM_EXPLICIT_LIST(CSimpleRegion, m_regionLink) m_regions; From c099226cd271db97e995237f6a08c2f5c157de0e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 2 Feb 2026 22:29:26 -0600 Subject: [PATCH 150/269] feat(ui): add CSimpleFrame::GetAttribute --- src/ui/simple/CSimpleFrame.cpp | 12 ++++++++++++ src/ui/simple/CSimpleFrame.hpp | 1 + 2 files changed, 13 insertions(+) diff --git a/src/ui/simple/CSimpleFrame.cpp b/src/ui/simple/CSimpleFrame.cpp index 1257cd1..2588bcf 100644 --- a/src/ui/simple/CSimpleFrame.cpp +++ b/src/ui/simple/CSimpleFrame.cpp @@ -522,6 +522,18 @@ void CSimpleFrame::PreLoadXML(XMLNode* node, CStatus* status) { } } +bool CSimpleFrame::GetAttribute(const char* name, int32_t& luaRef) { + auto attr = this->m_attributes.Ptr(name); + + if (!attr || attr->luaRef == -1) { + return false; + } + + luaRef = attr->luaRef; + + return true; +} + int32_t CSimpleFrame::GetBoundsRect(CRect& bounds) { if (this->IsResizePending()) { this->Resize(1); diff --git a/src/ui/simple/CSimpleFrame.hpp b/src/ui/simple/CSimpleFrame.hpp index 39e8d19..d014462 100644 --- a/src/ui/simple/CSimpleFrame.hpp +++ b/src/ui/simple/CSimpleFrame.hpp @@ -132,6 +132,7 @@ class CSimpleFrame : public CScriptRegion { void DisableEvent(CSimpleEventType eventType); void EnableDrawLayer(uint32_t drawlayer); void EnableEvent(CSimpleEventType eventType, int32_t priority); + bool GetAttribute(const char* name, int32_t& luaRef); int32_t GetHitRect(CRect& rect); void Hide(); void LoadXML_Attributes(const XMLNode* node, CStatus* status); From bdce2662056af15077cf168691db4c49b80c2037 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 3 Feb 2026 08:36:04 -0600 Subject: [PATCH 151/269] feat(ui): add CSimpleFrame::SetAttribute --- src/ui/simple/CSimpleFrame.cpp | 35 ++++++++++++++++++++++++++++++++++ src/ui/simple/CSimpleFrame.hpp | 2 ++ 2 files changed, 37 insertions(+) diff --git a/src/ui/simple/CSimpleFrame.cpp b/src/ui/simple/CSimpleFrame.cpp index 2588bcf..67a1da0 100644 --- a/src/ui/simple/CSimpleFrame.cpp +++ b/src/ui/simple/CSimpleFrame.cpp @@ -376,6 +376,29 @@ void CSimpleFrame::RegisterForEvents(int32_t a2) { } } +void CSimpleFrame::RunOnAttributeChangedScript(const char* name, int32_t luaRef) { + if (!this->m_onAttributeChange.luaRef) { + return; + } + + auto L = FrameScript_GetContext(); + + // TODO taint management + + // Attribute name + auto nameLower = static_cast(alloca(SStrLen(name) + 1)); + SStrCopy(nameLower, name); + SStrLower(nameLower); + lua_pushstring(L, nameLower); + + // Attribute ref + lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef); + + this->RunScript(this->m_onAttributeChange, 2, nullptr); + + // TODO taint management +} + void CSimpleFrame::RunOnCharScript(const char* chr) { if (this->m_onChar.luaRef) { auto L = FrameScript_GetContext(); @@ -1329,6 +1352,18 @@ void CSimpleFrame::RemoveFrameRegion(CSimpleRegion* region, uint32_t drawlayer) this->NotifyDrawLayerChanged(drawlayer); } +void CSimpleFrame::SetAttribute(const char* name, int32_t luaRef) { + auto attr = this->m_attributes.Ptr(name); + + if (!attr) { + attr = this->m_attributes.New(name, 0, 0x0); + } + + attr->luaRef = luaRef; + + this->RunOnAttributeChangedScript(name, luaRef); +} + void CSimpleFrame::SetBackdrop(CBackdropGenerator* backdrop) { if (this->m_backdrop) { delete this->m_backdrop; diff --git a/src/ui/simple/CSimpleFrame.hpp b/src/ui/simple/CSimpleFrame.hpp index d014462..21ce7ea 100644 --- a/src/ui/simple/CSimpleFrame.hpp +++ b/src/ui/simple/CSimpleFrame.hpp @@ -146,6 +146,7 @@ class CSimpleFrame : public CScriptRegion { void RegisterForEvents(int32_t a2); void RegisterRegion(CSimpleRegion* region); void RemoveFrameRegion(CSimpleRegion* region, uint32_t drawlayer); + void RunOnAttributeChangedScript(const char* name, int32_t luaRef); void RunOnCharScript(const char* chr); void RunOnEnableScript(); void RunOnEnterScript(int32_t a2); @@ -159,6 +160,7 @@ class CSimpleFrame : public CScriptRegion { void RunOnShowScript(); void RunOnSizeChangedScript(float width, float height); void RunOnUpdateScript(float elapsedSec); + void SetAttribute(const char* name, int32_t luaRef); void SetBackdrop(CBackdropGenerator* backdrop); void SetBeingScrolled(int32_t a2, int32_t a3); void SetFrameAlpha(uint8_t alpha); From 3d8073cf75fdfa48b443a22435929b0c1c69b454 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 3 Feb 2026 09:00:27 -0600 Subject: [PATCH 152/269] feat(ui): implement CSimpleFrame::LoadXML_Attributes --- src/ui/simple/CSimpleFrame.cpp | 64 +++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleFrame.cpp b/src/ui/simple/CSimpleFrame.cpp index 67a1da0..6f95f38 100644 --- a/src/ui/simple/CSimpleFrame.cpp +++ b/src/ui/simple/CSimpleFrame.cpp @@ -772,7 +772,69 @@ int32_t CSimpleFrame::HideThis() { } void CSimpleFrame::LoadXML_Attributes(const XMLNode* node, CStatus* status) { - // TODO + auto L = FrameScript_GetContext(); + + auto child = node->GetChild(); + + while (child) { + // Unexpected child node + if (SStrCmpI(child->GetName(), "Attribute")) { + status->Add(STATUS_WARNING, "Frame %s: Unknown attributes element %s", this->GetDisplayName(), child->GetName()); + child = child->GetSibling(); + continue; + } + + auto attrName = child->GetAttributeByName("name"); + + // No attribute name + if (!attrName) { + status->Add(STATUS_WARNING, "Frame %s: unnamed attribute element", this->GetDisplayName()); + child = child->GetSibling(); + continue; + } + + auto attrType = child->GetAttributeByName("type"); + + if (!attrType) { + attrType = "string"; + } + + auto attrValue = child->GetAttributeByName("value"); + + // Missing attribute value for non-nil type + if (SStrCmpI(attrType, "nil") && !attrValue) { + status->Add(STATUS_WARNING, "Frame %s: attribute element named %s missing value", this->GetDisplayName(), attrName); + child = child->GetSibling(); + continue; + } + + // Push attribute value to stack + if (!SStrCmpI(attrType, "nil")) { + lua_pushnil(L); + } else if (!SStrCmpI(attrType, "boolean")) { + lua_pushboolean(L, StringToBOOL(attrValue)); + } else if (!SStrCmpI(attrType, "number")) { + lua_pushnumber(L, SStrToFloat(attrValue)); + } else { + lua_pushstring(L, attrValue); + } + + auto attr = this->m_attributes.Ptr(attrName); + + if (attr) { + luaL_unref(L, LUA_REGISTRYINDEX, attr->luaRef); + } else { + attr = this->m_attributes.New(attrName, 0, 0x0); + } + + // TODO taint management + + attr->luaRef = luaL_ref(L, LUA_REGISTRYINDEX); + + // TODO taint management + + child = child->GetSibling(); + } } void CSimpleFrame::LoadXML_Backdrop(const XMLNode* node, CStatus* status) { From c201da76cd7294eae60769568d3598604be0c12f Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 3 Feb 2026 09:40:46 -0600 Subject: [PATCH 153/269] feat(ui): partially implement CSimpleFrame_GetAttribute --- src/ui/simple/CSimpleFrameScript.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleFrameScript.cpp b/src/ui/simple/CSimpleFrameScript.cpp index ca9d743..cd2f78f 100644 --- a/src/ui/simple/CSimpleFrameScript.cpp +++ b/src/ui/simple/CSimpleFrameScript.cpp @@ -180,7 +180,32 @@ int32_t CSimpleFrame_CanChangeAttributes(lua_State* L) { } int32_t CSimpleFrame_GetAttribute(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleFrame::GetObjectType(); + auto frame = static_cast(FrameScript_GetObjectThis(L, type)); + + // 3 argument form + if (lua_gettop(L) == 4 && lua_isstring(L, 3)) { + // TODO 3 argument form isn't handled yet + WHOA_UNIMPLEMENTED(0); + } + + // 1 argument form + if (lua_isstring(L, 2)) { + auto attrName = lua_tostring(L, 2); + int32_t luaRef; + + if (frame->GetAttribute(attrName, luaRef)) { + lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef); + } else { + lua_pushnil(L); + } + + return 1; + } + + // Invalid call + luaL_error(L, "Usage: %s:GetAttribute(\"name\")", frame->GetDisplayName()); + return 0; } int32_t CSimpleFrame_SetAttribute(lua_State* L) { From 66fd4a65646cd4f3e6cb8a30bb005f7ee0b1ddc2 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 3 Feb 2026 10:13:08 -0600 Subject: [PATCH 154/269] feat(ui): implement CSimpleFrame_SetAttribute --- src/ui/simple/CSimpleFrame.cpp | 4 ++++ src/ui/simple/CSimpleFrame.hpp | 1 + src/ui/simple/CSimpleFrameScript.cpp | 33 +++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleFrame.cpp b/src/ui/simple/CSimpleFrame.cpp index 6f95f38..0e03001 100644 --- a/src/ui/simple/CSimpleFrame.cpp +++ b/src/ui/simple/CSimpleFrame.cpp @@ -95,6 +95,10 @@ void CSimpleFrame::AddFrameRegion(CSimpleRegion* region, uint32_t drawlayer) { this->NotifyDrawLayerChanged(drawlayer); } +int32_t CSimpleFrame::AttributeChangesAllowed() { + return true; +} + void CSimpleFrame::DisableDrawLayer(uint32_t drawlayer) { this->m_drawenabled[drawlayer] = 0; this->NotifyDrawLayerChanged(drawlayer); diff --git a/src/ui/simple/CSimpleFrame.hpp b/src/ui/simple/CSimpleFrame.hpp index 21ce7ea..f0641da 100644 --- a/src/ui/simple/CSimpleFrame.hpp +++ b/src/ui/simple/CSimpleFrame.hpp @@ -128,6 +128,7 @@ class CSimpleFrame : public CScriptRegion { // Member functions CSimpleFrame(CSimpleFrame* parent); void AddFrameRegion(CSimpleRegion* region, uint32_t drawlayer); + int32_t AttributeChangesAllowed(); void DisableDrawLayer(uint32_t drawlayer); void DisableEvent(CSimpleEventType eventType); void EnableDrawLayer(uint32_t drawlayer); diff --git a/src/ui/simple/CSimpleFrameScript.cpp b/src/ui/simple/CSimpleFrameScript.cpp index cd2f78f..118c11b 100644 --- a/src/ui/simple/CSimpleFrameScript.cpp +++ b/src/ui/simple/CSimpleFrameScript.cpp @@ -209,7 +209,38 @@ int32_t CSimpleFrame_GetAttribute(lua_State* L) { } int32_t CSimpleFrame_SetAttribute(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleFrame::GetObjectType(); + auto frame = static_cast(FrameScript_GetObjectThis(L, type)); + + if (!frame->ProtectedFunctionsAllowed() && !frame->AttributeChangesAllowed()) { + // TODO disallowed logic + + return 0; + } + + lua_settop(L, 3); + + if (!lua_isstring(L, 2) || lua_type(L, 3) == LUA_TNONE) { + luaL_error(L, "Usage: %s:SetAttribute(\"name\", value)", frame->GetDisplayName()); + return 0; + } + + auto attrName = lua_tostring(L, 2); + int32_t luaRef; + + if (frame->GetAttribute(attrName, luaRef)) { + luaL_unref(L, LUA_REGISTRYINDEX, luaRef); + } + + // TODO taint management + + luaRef = luaL_ref(L, LUA_REGISTRYINDEX); + + // TODO taint management + + frame->SetAttribute(attrName, luaRef); + + return 0; } int32_t CSimpleFrame_GetEffectiveScale(lua_State* L) { From 0681e432e21c7a06b1db24d96f7712f243f556c1 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 3 Feb 2026 14:57:22 -0600 Subject: [PATCH 155/269] feat(ui): handle 3 argument form in CSimpleFrame_GetAttribute --- src/ui/simple/CSimpleFrameScript.cpp | 138 ++++++++++++++++++++++++++- 1 file changed, 134 insertions(+), 4 deletions(-) diff --git a/src/ui/simple/CSimpleFrameScript.cpp b/src/ui/simple/CSimpleFrameScript.cpp index 118c11b..227a892 100644 --- a/src/ui/simple/CSimpleFrameScript.cpp +++ b/src/ui/simple/CSimpleFrameScript.cpp @@ -184,26 +184,156 @@ int32_t CSimpleFrame_GetAttribute(lua_State* L) { auto frame = static_cast(FrameScript_GetObjectThis(L, type)); // 3 argument form + if (lua_gettop(L) == 4 && lua_isstring(L, 3)) { - // TODO 3 argument form isn't handled yet - WHOA_UNIMPLEMENTED(0); + size_t prefixLen, nameLen, suffixLen; + auto prefix = lua_tolstring(L, 2, &prefixLen); + auto name = lua_tolstring(L, 3, &nameLen); + auto suffix = lua_tolstring(L, 4, &suffixLen); + + char buffer[256]; + char* write; + size_t remaining; + size_t copyLen; + + int32_t luaRef; + + // Attempt 1: prefix + name + suffix + + write = buffer; + remaining = 255; + + if (prefixLen > 0) { + copyLen = (prefixLen < remaining) ? prefixLen : remaining; + memcpy(write, prefix, copyLen); + write += copyLen; + remaining -= copyLen; + } + + if (nameLen > 0) { + copyLen = (nameLen < remaining) ? nameLen : remaining; + memcpy(write, name, copyLen); + write += copyLen; + remaining -= copyLen; + } + + if (suffixLen > 0) { + copyLen = (suffixLen < remaining) ? suffixLen : remaining; + memcpy(write, suffix, copyLen); + write += copyLen; + } + + *write = '\0'; + + if (frame->GetAttribute(buffer, luaRef)) { + lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef); + return 1; + } + + // Attempt 2: "*" + name + suffix + + write = buffer; + *write++ = '*'; + remaining = 254; + + if (nameLen > 0) { + copyLen = (nameLen < remaining) ? nameLen : remaining; + memcpy(write, name, copyLen); + write += copyLen; + remaining -= copyLen; + } + + if (suffixLen > 0) { + copyLen = (suffixLen < remaining) ? suffixLen : remaining; + memcpy(write, suffix, copyLen); + write += copyLen; + } + + *write = '\0'; + + if (frame->GetAttribute(buffer, luaRef)) { + lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef); + return 1; + } + + // Attempt 3: prefix + name + "*" + + write = buffer; + remaining = 254; + + if (prefixLen > 0) { + copyLen = (prefixLen < remaining) ? prefixLen : remaining; + memcpy(write, prefix, copyLen); + write += copyLen; + remaining -= copyLen; + } + + if (nameLen > 0) { + copyLen = (nameLen < remaining) ? nameLen : remaining; + memcpy(write, name, copyLen); + write += copyLen; + } + + *write++ = '*'; + *write = '\0'; + + if (frame->GetAttribute(buffer, luaRef)) { + lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef); + return 1; + } + + // Attempt 4: "*" + name + "*" + + write = buffer; + *write++ = '*'; + remaining = 253; + + if (nameLen > 0) { + copyLen = (nameLen < remaining) ? nameLen : remaining; + memcpy(write, name, copyLen); + write += copyLen; + } + + *write++ = '*'; + *write = '\0'; + + if (frame->GetAttribute(buffer, luaRef)) { + lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef); + return 1; + } + + // Attempt 5: name + + if (frame->GetAttribute(name, luaRef)) { + lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef); + return 1; + } + + // Not found + + lua_pushnil(L); + return 1; } // 1 argument form + if (lua_isstring(L, 2)) { auto attrName = lua_tostring(L, 2); int32_t luaRef; if (frame->GetAttribute(attrName, luaRef)) { lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef); - } else { - lua_pushnil(L); + return 1; } + // Not found + + lua_pushnil(L); return 1; } // Invalid call + luaL_error(L, "Usage: %s:GetAttribute(\"name\")", frame->GetDisplayName()); return 0; } From 3bf95af10c05c5f2d49c42d814aa9766d7fd7c1b Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 3 Feb 2026 16:24:09 -0600 Subject: [PATCH 156/269] feat(ui): implement CSimpleTexture_SetDrawLayer --- src/ui/simple/CSimpleTextureScript.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleTextureScript.cpp b/src/ui/simple/CSimpleTextureScript.cpp index 2dbe992..ada51de 100644 --- a/src/ui/simple/CSimpleTextureScript.cpp +++ b/src/ui/simple/CSimpleTextureScript.cpp @@ -19,7 +19,25 @@ int32_t CSimpleTexture_GetDrawLayer(lua_State* L) { } int32_t CSimpleTexture_SetDrawLayer(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleTexture::GetObjectType(); + auto texture = static_cast(FrameScript_GetObjectThis(L, type)); + + if (!lua_isstring(L, 2)) { + luaL_error(L, "Usage: %s:SetDrawLayer(\"layer\")", texture->GetDisplayName()); + return 0; + } + + auto drawlayerStr = lua_tostring(L, 2); + int32_t drawlayer = texture->m_drawlayer; + + if (!StringToDrawLayer(drawlayerStr, drawlayer)) { + luaL_error(L, "Usage: %s:SetDrawLayer(\"layer\")", texture->GetDisplayName()); + return 0; + } + + texture->SetFrame(texture->m_parent, drawlayer, texture->m_shown); + + return 0; } int32_t CSimpleTexture_GetBlendMode(lua_State* L) { From d34336cd7e8d037980b13171e47bab2fccbed629 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 3 Feb 2026 17:03:59 -0600 Subject: [PATCH 157/269] feat(ui): add ActionBarRegisterScriptFunctions --- src/ui/game/ActionBarScript.cpp | 156 ++++++++++++++++++++++++++++++++ src/ui/game/ActionBarScript.hpp | 6 ++ src/ui/game/CGGameUI.cpp | 5 + 3 files changed, 167 insertions(+) create mode 100644 src/ui/game/ActionBarScript.cpp create mode 100644 src/ui/game/ActionBarScript.hpp diff --git a/src/ui/game/ActionBarScript.cpp b/src/ui/game/ActionBarScript.cpp new file mode 100644 index 0000000..88457cc --- /dev/null +++ b/src/ui/game/ActionBarScript.cpp @@ -0,0 +1,156 @@ +#include "ui/game/ActionBarScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t Script_GetActionInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetActionTexture(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetActionCount(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetActionCooldown(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetActionAutocast(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetActionText(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_HasAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UseAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_PickupAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_PlaceAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsAttackAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsCurrentAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsAutoRepeatAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsUsableAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsConsumableAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsStackableAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsEquippedAction(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ActionHasRange(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsActionInRange(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetBonusBarOffset(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetMultiCastBarOffset(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ChangeActionBarPage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetActionBarPage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetActionBarToggles(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetActionBarToggles(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsPossessBarVisible(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetMultiCastTotemSpells(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetMultiCastSpell(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +static FrameScript_Method s_ScriptFunctions[] = { + { "GetActionInfo", &Script_GetActionInfo }, + { "GetActionTexture", &Script_GetActionTexture }, + { "GetActionCount", &Script_GetActionCount }, + { "GetActionCooldown", &Script_GetActionCooldown }, + { "GetActionAutocast", &Script_GetActionAutocast }, + { "GetActionText", &Script_GetActionText }, + { "HasAction", &Script_HasAction }, + { "UseAction", &Script_UseAction }, + { "PickupAction", &Script_PickupAction }, + { "PlaceAction", &Script_PlaceAction }, + { "IsAttackAction", &Script_IsAttackAction }, + { "IsCurrentAction", &Script_IsCurrentAction }, + { "IsAutoRepeatAction", &Script_IsAutoRepeatAction }, + { "IsUsableAction", &Script_IsUsableAction }, + { "IsConsumableAction", &Script_IsConsumableAction }, + { "IsStackableAction", &Script_IsStackableAction }, + { "IsEquippedAction", &Script_IsEquippedAction }, + { "ActionHasRange", &Script_ActionHasRange }, + { "IsActionInRange", &Script_IsActionInRange }, + { "GetBonusBarOffset", &Script_GetBonusBarOffset }, + { "GetMultiCastBarOffset", &Script_GetMultiCastBarOffset }, + { "ChangeActionBarPage", &Script_ChangeActionBarPage }, + { "GetActionBarPage", &Script_GetActionBarPage }, + { "GetActionBarToggles", &Script_GetActionBarToggles }, + { "SetActionBarToggles", &Script_SetActionBarToggles }, + { "IsPossessBarVisible", &Script_IsPossessBarVisible }, + { "GetMultiCastTotemSpells", &Script_GetMultiCastTotemSpells }, + { "SetMultiCastSpell", &Script_SetMultiCastSpell }, +}; + +void ActionBarRegisterScriptFunctions() { + for (auto& func : s_ScriptFunctions) { + FrameScript_RegisterFunction(func.name, func.method); + } +} diff --git a/src/ui/game/ActionBarScript.hpp b/src/ui/game/ActionBarScript.hpp new file mode 100644 index 0000000..a5c8ad8 --- /dev/null +++ b/src/ui/game/ActionBarScript.hpp @@ -0,0 +1,6 @@ +#ifndef UI_GAME_ACTION_BAR_SCRIPT_HPP +#define UI_GAME_ACTION_BAR_SCRIPT_HPP + +void ActionBarRegisterScriptFunctions(); + +#endif diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index f0f40a9..4591643 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -3,6 +3,7 @@ #include "ui/CScriptObject.hpp" #include "ui/FrameXML.hpp" #include "ui/Key.hpp" +#include "ui/game/ActionBarScript.hpp" #include "ui/game/BattlefieldInfoScript.hpp" #include "ui/game/CGCharacterModelBase.hpp" #include "ui/game/CGCooldown.hpp" @@ -46,6 +47,10 @@ void LoadScriptFunctions() { // TODO + ActionBarRegisterScriptFunctions(); + + // TODO + CharacterInfoRegisterScriptFunctions(); // TODO From 7d911e453d34c71d2d818008aa5469d248dc1670 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 3 Feb 2026 17:11:18 -0600 Subject: [PATCH 158/269] feat(ui): implement Script_GetActionBarPage --- src/ui/game/ActionBarScript.cpp | 10 +++++++++- src/ui/game/CGActionBar.cpp | 4 ++++ src/ui/game/CGActionBar.hpp | 13 +++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/ui/game/CGActionBar.cpp create mode 100644 src/ui/game/CGActionBar.hpp diff --git a/src/ui/game/ActionBarScript.cpp b/src/ui/game/ActionBarScript.cpp index 88457cc..14f9f95 100644 --- a/src/ui/game/ActionBarScript.cpp +++ b/src/ui/game/ActionBarScript.cpp @@ -1,5 +1,7 @@ #include "ui/game/ActionBarScript.hpp" #include "ui/FrameScript.hpp" +#include "ui/game/CGActionBar.hpp" +#include "util/Lua.hpp" #include "util/Unimplemented.hpp" namespace { @@ -93,7 +95,13 @@ int32_t Script_ChangeActionBarPage(lua_State* L) { } int32_t Script_GetActionBarPage(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (CGActionBar::s_tempPageActiveFlags) { + lua_pushinteger(L, 1); + } else { + lua_pushinteger(L, CGActionBar::s_currentPage + 1); + } + + return 1; } int32_t Script_GetActionBarToggles(lua_State* L) { diff --git a/src/ui/game/CGActionBar.cpp b/src/ui/game/CGActionBar.cpp new file mode 100644 index 0000000..6d652cc --- /dev/null +++ b/src/ui/game/CGActionBar.cpp @@ -0,0 +1,4 @@ +#include "ui/game/CGActionBar.hpp" + +uint32_t CGActionBar::s_currentPage; +uint32_t CGActionBar::s_tempPageActiveFlags; diff --git a/src/ui/game/CGActionBar.hpp b/src/ui/game/CGActionBar.hpp new file mode 100644 index 0000000..ddced5b --- /dev/null +++ b/src/ui/game/CGActionBar.hpp @@ -0,0 +1,13 @@ +#ifndef UI_GAME_C_G_ACTION_BAR_HPP +#define UI_GAME_C_G_ACTION_BAR_HPP + +#include + +class CGActionBar { + public: + // Static variables + static uint32_t s_currentPage; + static uint32_t s_tempPageActiveFlags; +}; + +#endif From 4857e817c5db2cfd23cb3282aa1ad6413256c4e1 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 09:45:37 -0600 Subject: [PATCH 159/269] feat(ui): implement CSimpleFrame_CreateTexture --- src/ui/simple/CSimpleFrameScript.cpp | 64 +++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleFrameScript.cpp b/src/ui/simple/CSimpleFrameScript.cpp index 227a892..bfb22f4 100644 --- a/src/ui/simple/CSimpleFrameScript.cpp +++ b/src/ui/simple/CSimpleFrameScript.cpp @@ -2,10 +2,13 @@ #include "gx/Coordinate.hpp" #include "ui/CBackdropGenerator.hpp" #include "ui/FrameScript.hpp" +#include "ui/FrameXML.hpp" #include "ui/simple/CSimpleFrame.hpp" +#include "ui/simple/CSimpleTexture.hpp" #include "util/Lua.hpp" #include "util/StringTo.hpp" #include "util/Unimplemented.hpp" +#include #include #include #include @@ -19,7 +22,66 @@ int32_t CSimpleFrame_CreateTitleRegion(lua_State* L) { } int32_t CSimpleFrame_CreateTexture(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleFrame::GetObjectType(); + auto frame = static_cast(FrameScript_GetObjectThis(L, type)); + + const char* name = nullptr; + if (lua_isstring(L, 2)) { + name = lua_tostring(L, 2); + } + + int32_t drawlayer = DRAWLAYER_ARTWORK; + if (lua_isstring(L, 3)) { + auto drawlayerStr = lua_tostring(L, 3); + StringToDrawLayer(drawlayerStr, drawlayer); + } + + XMLNode* inheritNode = nullptr; + + if (lua_type(L, 4) == LUA_TSTRING) { + auto inheritName = lua_tostring(L, 4); + const char* tainted; + bool locked; + + inheritNode = FrameXML_AcquireHashNode(inheritName, tainted, locked); + + if (!inheritNode) { + luaL_error(L, "%s:CreateTexture(): Couldn't find inherited node \"%s\"", frame->GetDisplayName(), inheritName); + return 0; + } + + if (locked) { + luaL_error(L, "%s:CreateTexture(): Recursively inherited node \"%s\"", frame->GetDisplayName(), inheritName); + return 0; + } + } + + // TODO CDataAllocator::GetData + auto texture = STORM_NEW(CSimpleTexture)(frame, drawlayer, true); + + if (name && *name) { + texture->SetName(name); + } + + if (inheritNode) { + CStatus status; + + texture->LoadXML(inheritNode, &status); + texture->PostLoadXML(inheritNode, &status); + + auto inheritName = lua_tostring(L, 4); + FrameXML_ReleaseHashNode(inheritName); + } + + // TODO anim related logic? + + if (!texture->lua_registered) { + texture->RegisterScriptObject(nullptr); + } + + lua_rawgeti(L, LUA_REGISTRYINDEX, texture->lua_objectRef); + + return 1; } int32_t CSimpleFrame_CreateFontString(lua_State* L) { From 6a4a2110f4a709f5f11a1577e8f2229b60bcf37e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 11:37:30 -0600 Subject: [PATCH 160/269] feat(ui): implement CSimpleFrame_GetScript --- src/ui/FrameScript_Object.cpp | 27 +++++++++++++++++++++++++++ src/ui/FrameScript_Object.hpp | 1 + src/ui/simple/CSimpleFrameScript.cpp | 5 ++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/ui/FrameScript_Object.cpp b/src/ui/FrameScript_Object.cpp index 15b19a6..17ff3db 100644 --- a/src/ui/FrameScript_Object.cpp +++ b/src/ui/FrameScript_Object.cpp @@ -35,6 +35,33 @@ const char* FrameScript_Object::GetDisplayName() { return name ? name : ""; } +int32_t FrameScript_Object::GetScript(lua_State* L) { + if (!lua_isstring(L, 2)) { + luaL_error(L, "Usage: %s:GetScript(\"type\")", this->GetDisplayName()); + return 0; + } + + auto name = lua_tostring(L, 2); + ScriptData data; + + auto script = this->GetScriptByName(name, data); + + if (!script) { + luaL_error(L, "%s doesn't have a \"%s\" script", this->GetDisplayName(), lua_tostring(L, 2)); + return 0; + } + + // TODO taint management + + if (script->luaRef > 0) { + lua_rawgeti(L, LUA_REGISTRYINDEX, script->luaRef); + } else { + lua_pushnil(L); + } + + return 1; +} + FrameScript_Object::ScriptIx* FrameScript_Object::GetScriptByName(const char* name, FrameScript_Object::ScriptData& data) { if (!SStrCmpI(name, "OnEvent", STORM_MAX_STR)) { data.wrapper = "return function(self,event,...) %s end"; diff --git a/src/ui/FrameScript_Object.hpp b/src/ui/FrameScript_Object.hpp index e80049e..db4528f 100644 --- a/src/ui/FrameScript_Object.hpp +++ b/src/ui/FrameScript_Object.hpp @@ -43,6 +43,7 @@ class FrameScript_Object { // Member functions const char* GetDisplayName(); + int32_t GetScript(lua_State* L); int32_t RegisterScriptEvent(const char* name); void RegisterScriptObject(const char* name); void RunScript(ScriptIx const& script, int32_t argCount, const char* a4); diff --git a/src/ui/simple/CSimpleFrameScript.cpp b/src/ui/simple/CSimpleFrameScript.cpp index bfb22f4..45b2679 100644 --- a/src/ui/simple/CSimpleFrameScript.cpp +++ b/src/ui/simple/CSimpleFrameScript.cpp @@ -188,7 +188,10 @@ int32_t CSimpleFrame_HasScript(lua_State* L) { } int32_t CSimpleFrame_GetScript(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleFrame::GetObjectType(); + auto frame = static_cast(FrameScript_GetObjectThis(L, type)); + + return frame->GetScript(L); } int32_t CSimpleFrame_SetScript(lua_State* L) { From bc2dabeea988da47013dfa04221223af702334a9 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 12:48:52 -0600 Subject: [PATCH 161/269] feat(ui): add CSimpleStatusBar::GetScriptByName --- src/ui/simple/CSimpleStatusBar.cpp | 18 ++++++++++++++++++ src/ui/simple/CSimpleStatusBar.hpp | 25 ++++++++++++++++++------- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/ui/simple/CSimpleStatusBar.cpp b/src/ui/simple/CSimpleStatusBar.cpp index 471c842..2787be3 100644 --- a/src/ui/simple/CSimpleStatusBar.cpp +++ b/src/ui/simple/CSimpleStatusBar.cpp @@ -26,6 +26,24 @@ CSimpleStatusBar::CSimpleStatusBar(CSimpleFrame* parent) : CSimpleFrame(parent) // TODO } +FrameScript_Object::ScriptIx* CSimpleStatusBar::GetScriptByName(const char* name, ScriptData& data) { + auto script = this->CSimpleFrame::GetScriptByName(name, data); + + if (script) { + return script; + } + + if (!SStrCmpI(name, "OnValueChanged")) { + script = &this->m_onValueChanged; + data.wrapper = "return function(self,value) %s end"; + } else if (!SStrCmpI(name, "OnMinMaxChanged")) { + script = &this->m_onMinMaxChanged; + data.wrapper = "return function(self,min,max) %s end"; + } + + return script; +} + int32_t CSimpleStatusBar::GetScriptMetaTable() { return CSimpleStatusBar::s_metatable; } diff --git a/src/ui/simple/CSimpleStatusBar.hpp b/src/ui/simple/CSimpleStatusBar.hpp index 812439e..f95d8e7 100644 --- a/src/ui/simple/CSimpleStatusBar.hpp +++ b/src/ui/simple/CSimpleStatusBar.hpp @@ -5,23 +5,34 @@ class CSimpleStatusBar : public CSimpleFrame { public: - // Static variables + // Public static variables static int32_t s_metatable; static int32_t s_objectType; - // Static functions + // Public static functions static void CreateScriptMetaTable(); static int32_t GetObjectType(); static void RegisterScriptMethods(lua_State* L); - // Member variables - // TODO - - // Virtual member functions + // Public virtual member functions virtual int32_t GetScriptMetaTable(); + virtual ScriptIx* GetScriptByName(const char* name, ScriptData& data); - // Member functions + // Public member functions CSimpleStatusBar(CSimpleFrame* parent); + + protected: + // Protected member variables + uint32_t m_changed : 1; + uint32_t m_rangeSet : 1; + uint32_t m_valueSet : 1; + float m_minValue = 0.0f; + float m_maxValue = 0.0f; + float m_value = 0.0f; + CSimpleTexture* m_barTexture = nullptr; + ORIENTATION m_orientation = ORIENTATION_HORIZONTAL; + ScriptIx m_onValueChanged; + ScriptIx m_onMinMaxChanged; }; #endif From 61484450b83e471fcb9025481045bc82660b2cf2 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 13:23:14 -0600 Subject: [PATCH 162/269] feat(ui): add CSimpleStatusBar::SetValue --- src/ui/simple/CSimpleStatusBar.cpp | 33 ++++++++++++++++++++++++++++++ src/ui/simple/CSimpleStatusBar.hpp | 3 +++ 2 files changed, 36 insertions(+) diff --git a/src/ui/simple/CSimpleStatusBar.cpp b/src/ui/simple/CSimpleStatusBar.cpp index 2787be3..cfa8baa 100644 --- a/src/ui/simple/CSimpleStatusBar.cpp +++ b/src/ui/simple/CSimpleStatusBar.cpp @@ -1,5 +1,6 @@ #include "ui/simple/CSimpleStatusBar.hpp" #include "ui/simple/CSimpleStatusBarScript.hpp" +#include "util/Lua.hpp" int32_t CSimpleStatusBar::s_metatable; int32_t CSimpleStatusBar::s_objectType; @@ -47,3 +48,35 @@ FrameScript_Object::ScriptIx* CSimpleStatusBar::GetScriptByName(const char* name int32_t CSimpleStatusBar::GetScriptMetaTable() { return CSimpleStatusBar::s_metatable; } + +void CSimpleStatusBar::RunOnValueChangedScript() { + if (!this->m_onValueChanged.luaRef) { + return; + } + + auto L = FrameScript_GetContext(); + + lua_pushnumber(L, this->m_value); + + this->RunScript(this->m_onValueChanged, 1, nullptr); +} + +void CSimpleStatusBar::SetValue(float value) { + if (!this->m_rangeSet) { + return; + } + + // Clamp value + value = std::min(std::max(value, this->m_minValue), this->m_maxValue); + + if (this->m_valueSet && this->m_value == value) { + return; + } + + this->m_value = value; + + this->m_changed = true; + this->m_valueSet = true; + + this->RunOnValueChangedScript(); +} diff --git a/src/ui/simple/CSimpleStatusBar.hpp b/src/ui/simple/CSimpleStatusBar.hpp index f95d8e7..2e4ca12 100644 --- a/src/ui/simple/CSimpleStatusBar.hpp +++ b/src/ui/simple/CSimpleStatusBar.hpp @@ -17,9 +17,12 @@ class CSimpleStatusBar : public CSimpleFrame { // Public virtual member functions virtual int32_t GetScriptMetaTable(); virtual ScriptIx* GetScriptByName(const char* name, ScriptData& data); + // TODO + virtual void SetValue(float value); // Public member functions CSimpleStatusBar(CSimpleFrame* parent); + void RunOnValueChangedScript(); protected: // Protected member variables From 35699af8d21465d3c0a1a22c513f6dc633e52dc2 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 14:28:55 -0600 Subject: [PATCH 163/269] feat(ui): add CSimpleStatusBar::SetMinMaxValues --- src/ui/simple/CSimpleStatusBar.cpp | 37 ++++++++++++++++++++++++++++++ src/ui/simple/CSimpleStatusBar.hpp | 2 ++ 2 files changed, 39 insertions(+) diff --git a/src/ui/simple/CSimpleStatusBar.cpp b/src/ui/simple/CSimpleStatusBar.cpp index cfa8baa..f743019 100644 --- a/src/ui/simple/CSimpleStatusBar.cpp +++ b/src/ui/simple/CSimpleStatusBar.cpp @@ -49,6 +49,19 @@ int32_t CSimpleStatusBar::GetScriptMetaTable() { return CSimpleStatusBar::s_metatable; } +void CSimpleStatusBar::RunOnMinMaxChangedScript() { + if (!this->m_onMinMaxChanged.luaRef) { + return; + } + + auto L = FrameScript_GetContext(); + + lua_pushnumber(L, this->m_minValue); + lua_pushnumber(L, this->m_maxValue); + + this->RunScript(this->m_onMinMaxChanged, 2, nullptr); +} + void CSimpleStatusBar::RunOnValueChangedScript() { if (!this->m_onValueChanged.luaRef) { return; @@ -61,6 +74,29 @@ void CSimpleStatusBar::RunOnValueChangedScript() { this->RunScript(this->m_onValueChanged, 1, nullptr); } +void CSimpleStatusBar::SetMinMaxValues(float min, float max) { + if (min > max) { + min = max; + } + + // No change + if (this->m_rangeSet && this->m_minValue == min && this->m_maxValue == max) { + return; + } + + this->m_minValue = min; + this->m_maxValue = max; + + this->m_changed = true; + this->m_rangeSet = true; + + this->RunOnMinMaxChangedScript(); + + if (this->m_valueSet) { + this->SetValue(this->m_value); + } +} + void CSimpleStatusBar::SetValue(float value) { if (!this->m_rangeSet) { return; @@ -69,6 +105,7 @@ void CSimpleStatusBar::SetValue(float value) { // Clamp value value = std::min(std::max(value, this->m_minValue), this->m_maxValue); + // No change if (this->m_valueSet && this->m_value == value) { return; } diff --git a/src/ui/simple/CSimpleStatusBar.hpp b/src/ui/simple/CSimpleStatusBar.hpp index 2e4ca12..a8bbe61 100644 --- a/src/ui/simple/CSimpleStatusBar.hpp +++ b/src/ui/simple/CSimpleStatusBar.hpp @@ -22,7 +22,9 @@ class CSimpleStatusBar : public CSimpleFrame { // Public member functions CSimpleStatusBar(CSimpleFrame* parent); + void RunOnMinMaxChangedScript(); void RunOnValueChangedScript(); + void SetMinMaxValues(float min, float max); protected: // Protected member variables From c54dda367b197861c250a97d0be4579745ef6f59 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 14:33:23 -0600 Subject: [PATCH 164/269] feat(ui): implement CSimpleStatusBar_SetValue --- src/ui/simple/CSimpleStatusBarScript.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleStatusBarScript.cpp b/src/ui/simple/CSimpleStatusBarScript.cpp index 88dcc40..7e7dbf7 100644 --- a/src/ui/simple/CSimpleStatusBarScript.cpp +++ b/src/ui/simple/CSimpleStatusBarScript.cpp @@ -1,5 +1,7 @@ #include "ui/simple/CSimpleStatusBarScript.hpp" +#include "ui/simple/CSimpleStatusBar.hpp" #include "ui/FrameScript.hpp" +#include "util/Lua.hpp" #include "util/Unimplemented.hpp" namespace { @@ -25,7 +27,19 @@ int32_t CSimpleStatusBar_GetValue(lua_State* L) { } int32_t CSimpleStatusBar_SetValue(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleStatusBar::GetObjectType(); + auto statusBar = static_cast(FrameScript_GetObjectThis(L, type)); + + if (!lua_isnumber(L, 2)) { + luaL_error(L, "Usage: %s:SetValue(value)", statusBar->GetDisplayName()); + return 0; + } + + auto value = static_cast(lua_tonumber(L, 2)); + + statusBar->SetValue(value); + + return 0; } int32_t CSimpleStatusBar_GetStatusBarTexture(lua_State* L) { From 977a3051db871c3c31555bfde682bcf65c9ce69b Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 15:08:45 -0600 Subject: [PATCH 165/269] feat(ui): implement CSimpleStatusBar_SetMinMaxValues --- src/ui/simple/CSimpleStatusBarScript.cpp | 25 +++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleStatusBarScript.cpp b/src/ui/simple/CSimpleStatusBarScript.cpp index 7e7dbf7..562f01f 100644 --- a/src/ui/simple/CSimpleStatusBarScript.cpp +++ b/src/ui/simple/CSimpleStatusBarScript.cpp @@ -19,7 +19,30 @@ int32_t CSimpleStatusBar_GetMinMaxValues(lua_State* L) { } int32_t CSimpleStatusBar_SetMinMaxValues(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleStatusBar::GetObjectType(); + auto statusBar = static_cast(FrameScript_GetObjectThis(L, type)); + + if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3)) { + luaL_error(L, "Usage: %s:SetMinMaxValues(min, max)", statusBar->GetDisplayName()); + return 0; + } + + auto min = lua_tonumber(L, 2); + auto max = lua_tonumber(L, 3); + + if (min < -1.0e12 || min > 1.0e12 || max < -1.0e12 || max > 1.0e12) { + luaL_error(L, "Min or Max out of range"); + return 0; + } + + if (max - min > 1.0e12) { + luaL_error(L, "Min and Max too far apart"); + return 0; + } + + statusBar->SetMinMaxValues(static_cast(min), static_cast(max)); + + return 0; } int32_t CSimpleStatusBar_GetValue(lua_State* L) { From dc22db2f1822fb071edf08ce3ea4914740b1a7e9 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 15:16:33 -0600 Subject: [PATCH 166/269] feat(ui): implement CSimpleStatusBar_GetValue --- src/ui/simple/CSimpleStatusBar.cpp | 4 ++++ src/ui/simple/CSimpleStatusBar.hpp | 1 + src/ui/simple/CSimpleStatusBarScript.cpp | 7 ++++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleStatusBar.cpp b/src/ui/simple/CSimpleStatusBar.cpp index f743019..ae0aec8 100644 --- a/src/ui/simple/CSimpleStatusBar.cpp +++ b/src/ui/simple/CSimpleStatusBar.cpp @@ -49,6 +49,10 @@ int32_t CSimpleStatusBar::GetScriptMetaTable() { return CSimpleStatusBar::s_metatable; } +float CSimpleStatusBar::GetValue() const { + return this->m_value; +} + void CSimpleStatusBar::RunOnMinMaxChangedScript() { if (!this->m_onMinMaxChanged.luaRef) { return; diff --git a/src/ui/simple/CSimpleStatusBar.hpp b/src/ui/simple/CSimpleStatusBar.hpp index a8bbe61..974309e 100644 --- a/src/ui/simple/CSimpleStatusBar.hpp +++ b/src/ui/simple/CSimpleStatusBar.hpp @@ -22,6 +22,7 @@ class CSimpleStatusBar : public CSimpleFrame { // Public member functions CSimpleStatusBar(CSimpleFrame* parent); + float GetValue() const; void RunOnMinMaxChangedScript(); void RunOnValueChangedScript(); void SetMinMaxValues(float min, float max); diff --git a/src/ui/simple/CSimpleStatusBarScript.cpp b/src/ui/simple/CSimpleStatusBarScript.cpp index 562f01f..2aae2b1 100644 --- a/src/ui/simple/CSimpleStatusBarScript.cpp +++ b/src/ui/simple/CSimpleStatusBarScript.cpp @@ -46,7 +46,12 @@ int32_t CSimpleStatusBar_SetMinMaxValues(lua_State* L) { } int32_t CSimpleStatusBar_GetValue(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleStatusBar::GetObjectType(); + auto statusBar = static_cast(FrameScript_GetObjectThis(L, type)); + + lua_pushnumber(L, statusBar->GetValue()); + + return 1; } int32_t CSimpleStatusBar_SetValue(lua_State* L) { From d9b6647c42e6715f60e4de9d1fa0dbc1666072a5 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 15:22:58 -0600 Subject: [PATCH 167/269] feat(ui): add CSimpleStatusBar::IsA --- src/ui/simple/CSimpleStatusBar.cpp | 7 +++++++ src/ui/simple/CSimpleStatusBar.hpp | 1 + 2 files changed, 8 insertions(+) diff --git a/src/ui/simple/CSimpleStatusBar.cpp b/src/ui/simple/CSimpleStatusBar.cpp index ae0aec8..f221801 100644 --- a/src/ui/simple/CSimpleStatusBar.cpp +++ b/src/ui/simple/CSimpleStatusBar.cpp @@ -53,6 +53,13 @@ float CSimpleStatusBar::GetValue() const { return this->m_value; } +bool CSimpleStatusBar::IsA(int32_t type) { + return type == CSimpleStatusBar::s_objectType + || type == CSimpleFrame::s_objectType + || type == CScriptRegion::s_objectType + || type == CScriptObject::s_objectType; +} + void CSimpleStatusBar::RunOnMinMaxChangedScript() { if (!this->m_onMinMaxChanged.luaRef) { return; diff --git a/src/ui/simple/CSimpleStatusBar.hpp b/src/ui/simple/CSimpleStatusBar.hpp index 974309e..7cca58d 100644 --- a/src/ui/simple/CSimpleStatusBar.hpp +++ b/src/ui/simple/CSimpleStatusBar.hpp @@ -17,6 +17,7 @@ class CSimpleStatusBar : public CSimpleFrame { // Public virtual member functions virtual int32_t GetScriptMetaTable(); virtual ScriptIx* GetScriptByName(const char* name, ScriptData& data); + virtual bool IsA(int32_t type); // TODO virtual void SetValue(float value); From 78f2afb8918541f1ec90bb6e39d9a9c9f56f0d58 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 17:08:31 -0600 Subject: [PATCH 168/269] feat(ui): add CSimpleStatusBar::LoadXML --- src/ui/simple/CSimpleStatusBar.cpp | 80 ++++++++++++++++++++++++++++++ src/ui/simple/CSimpleStatusBar.hpp | 5 ++ 2 files changed, 85 insertions(+) diff --git a/src/ui/simple/CSimpleStatusBar.cpp b/src/ui/simple/CSimpleStatusBar.cpp index f221801..1546869 100644 --- a/src/ui/simple/CSimpleStatusBar.cpp +++ b/src/ui/simple/CSimpleStatusBar.cpp @@ -1,6 +1,10 @@ #include "ui/simple/CSimpleStatusBar.hpp" +#include "ui/LoadXML.hpp" #include "ui/simple/CSimpleStatusBarScript.hpp" +#include "util/CStatus.hpp" #include "util/Lua.hpp" +#include "util/StringTo.hpp" +#include int32_t CSimpleStatusBar::s_metatable; int32_t CSimpleStatusBar::s_objectType; @@ -60,6 +64,66 @@ bool CSimpleStatusBar::IsA(int32_t type) { || type == CScriptObject::s_objectType; } +void CSimpleStatusBar::LoadXML(const XMLNode* node, CStatus* status) { + this->CSimpleFrame::LoadXML(node, status); + + int32_t drawlayer = DRAWLAYER_ARTWORK; + auto drawlayerAttr = node->GetAttributeByName("drawLayer"); + if (drawlayerAttr && *drawlayerAttr) { + StringToDrawLayer(drawlayerAttr, drawlayer); + } + + for (auto child = node->GetChild(); child; child = child->GetSibling()) { + if (!SStrCmpI(child->GetName(), "BarTexture")) { + auto texture = LoadXML_Texture(child, this, status); + this->SetBarTexture(texture, drawlayer); + } else if (!SStrCmpI(child->GetName(), "BarColor")) { + CImVector color = {}; + LoadXML_Color(child, color); + this->SetStatusBarColor(color); + } + } + + auto minValueAttr = node->GetAttributeByName("minValue"); + if (minValueAttr && *minValueAttr) { + auto maxValueAttr = node->GetAttributeByName("maxValue"); + if (maxValueAttr && *maxValueAttr) { + auto minValue = SStrToFloat(minValueAttr); + auto maxValue = SStrToFloat(maxValueAttr); + + if (minValue < -1.0e12 || minValue > 1.0e12 || maxValue < -1.0e12 || maxValue > 1.0e12) { + status->Add(STATUS_ERROR, "Frame %s: Min or Max out of range", this->GetDisplayName()); + } else if (maxValue - minValue > 1.0e12) { + status->Add(STATUS_ERROR, "Frame %s: Min and Max too far apart", this->GetDisplayName()); + } else { + this->SetMinMaxValues(minValue, maxValue); + } + + auto defaultValueAttr = node->GetAttributeByName("defaultValue"); + if (defaultValueAttr && *defaultValueAttr) { + auto defaultValue = SStrToFloat(defaultValueAttr); + this->SetValue(defaultValue); + } + } + } + + auto orientationAttr = node->GetAttributeByName("orientation"); + if (orientationAttr && *orientationAttr) { + ORIENTATION orientation; + if (StringToOrientation(orientationAttr, orientation)) { + this->SetOrientation(orientation); + } else { + status->Add(STATUS_WARNING, "Frame %s: Unknown orientation %s in element %s", this->GetDisplayName(), orientationAttr, node->GetName()); + } + } + + auto rotatesTextureAttr = node->GetAttributeByName("rotatesTexture"); + if (rotatesTextureAttr && *rotatesTextureAttr) { + auto rotatesTexture = StringToBOOL(rotatesTextureAttr); + this->SetRotatesTexture(rotatesTexture); + } +} + void CSimpleStatusBar::RunOnMinMaxChangedScript() { if (!this->m_onMinMaxChanged.luaRef) { return; @@ -85,6 +149,10 @@ void CSimpleStatusBar::RunOnValueChangedScript() { this->RunScript(this->m_onValueChanged, 1, nullptr); } +void CSimpleStatusBar::SetBarTexture(CSimpleTexture* texture, int32_t drawlayer) { + // TODO +} + void CSimpleStatusBar::SetMinMaxValues(float min, float max) { if (min > max) { min = max; @@ -108,6 +176,18 @@ void CSimpleStatusBar::SetMinMaxValues(float min, float max) { } } +void CSimpleStatusBar::SetOrientation(ORIENTATION orientation) { + // TODO +} + +void CSimpleStatusBar::SetRotatesTexture(int32_t enabled) { + // TODO +} + +void CSimpleStatusBar::SetStatusBarColor(const CImVector& color) { + // TODO +} + void CSimpleStatusBar::SetValue(float value) { if (!this->m_rangeSet) { return; diff --git a/src/ui/simple/CSimpleStatusBar.hpp b/src/ui/simple/CSimpleStatusBar.hpp index 7cca58d..1655a46 100644 --- a/src/ui/simple/CSimpleStatusBar.hpp +++ b/src/ui/simple/CSimpleStatusBar.hpp @@ -20,13 +20,18 @@ class CSimpleStatusBar : public CSimpleFrame { virtual bool IsA(int32_t type); // TODO virtual void SetValue(float value); + virtual void LoadXML(const XMLNode* node, CStatus* status); // Public member functions CSimpleStatusBar(CSimpleFrame* parent); float GetValue() const; void RunOnMinMaxChangedScript(); void RunOnValueChangedScript(); + void SetBarTexture(CSimpleTexture* texture, int32_t drawlayer); void SetMinMaxValues(float min, float max); + void SetOrientation(ORIENTATION orientation); + void SetRotatesTexture(int32_t enabled); + void SetStatusBarColor(const CImVector& color); protected: // Protected member variables From fd31a10eafbfa1d51eb3f38324c4e33da3b3099f Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 21:06:53 -0600 Subject: [PATCH 169/269] feat(ui): implement CSimpleStatusBar::SetBarTexture --- src/ui/simple/CSimpleStatusBar.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleStatusBar.cpp b/src/ui/simple/CSimpleStatusBar.cpp index 1546869..0e33201 100644 --- a/src/ui/simple/CSimpleStatusBar.cpp +++ b/src/ui/simple/CSimpleStatusBar.cpp @@ -1,6 +1,7 @@ #include "ui/simple/CSimpleStatusBar.hpp" #include "ui/LoadXML.hpp" #include "ui/simple/CSimpleStatusBarScript.hpp" +#include "ui/simple/CSimpleTexture.hpp" #include "util/CStatus.hpp" #include "util/Lua.hpp" #include "util/StringTo.hpp" @@ -150,7 +151,27 @@ void CSimpleStatusBar::RunOnValueChangedScript() { } void CSimpleStatusBar::SetBarTexture(CSimpleTexture* texture, int32_t drawlayer) { - // TODO + // No change + if (this->m_barTexture == texture) { + return; + } + + if (this->m_barTexture) { + delete this->m_barTexture; + } + + if (texture) { + texture->SetFrame(this, drawlayer, true); + + texture->SetPoint(FRAMEPOINT_BOTTOMLEFT, this, FRAMEPOINT_BOTTOMLEFT, 0.0f, 0.0f, true); + texture->SetPoint(FRAMEPOINT_BOTTOMRIGHT, this, FRAMEPOINT_BOTTOMRIGHT, 0.0f, 0.0f, true); + texture->SetPoint(FRAMEPOINT_TOPLEFT, this, FRAMEPOINT_TOPLEFT, 0.0f, 0.0f, true); + texture->SetPoint(FRAMEPOINT_TOPRIGHT, this, FRAMEPOINT_TOPRIGHT, 0.0f, 0.0f, true); + } + + this->m_barTexture = texture; + + this->m_changed = true; } void CSimpleStatusBar::SetMinMaxValues(float min, float max) { From d0621df975b6e440f74e95329fb91c4137f56578 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 21:10:42 -0600 Subject: [PATCH 170/269] feat(ui): implement CSimpleStatusBar::SetStatusBarColor --- src/ui/simple/CSimpleStatusBar.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleStatusBar.cpp b/src/ui/simple/CSimpleStatusBar.cpp index 0e33201..1190a48 100644 --- a/src/ui/simple/CSimpleStatusBar.cpp +++ b/src/ui/simple/CSimpleStatusBar.cpp @@ -206,7 +206,9 @@ void CSimpleStatusBar::SetRotatesTexture(int32_t enabled) { } void CSimpleStatusBar::SetStatusBarColor(const CImVector& color) { - // TODO + if (this->m_barTexture) { + this->m_barTexture->SetVertexColor(color); + } } void CSimpleStatusBar::SetValue(float value) { From 98103db5eea5772200f7e6be932893ac7dd2b39a Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 21:15:32 -0600 Subject: [PATCH 171/269] feat(ui): implement CSimpleStatusBar_SetStatusBarColor --- src/ui/simple/CSimpleStatusBarScript.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleStatusBarScript.cpp b/src/ui/simple/CSimpleStatusBarScript.cpp index 2aae2b1..56bc271 100644 --- a/src/ui/simple/CSimpleStatusBarScript.cpp +++ b/src/ui/simple/CSimpleStatusBarScript.cpp @@ -83,7 +83,15 @@ int32_t CSimpleStatusBar_GetStatusBarColor(lua_State* L) { } int32_t CSimpleStatusBar_SetStatusBarColor(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleStatusBar::GetObjectType(); + auto statusBar = static_cast(FrameScript_GetObjectThis(L, type)); + + CImVector color = {}; + FrameScript_GetColor(L, 2, color); + + statusBar->SetStatusBarColor(color); + + return 0; } int32_t CSimpleStatusBar_GetRotatesTexture(lua_State* L) { From 3713a7ee893ba56644672e9fbe2b507c665e15ac Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 21:40:42 -0600 Subject: [PATCH 172/269] feat(ui): implement CSimpleStatusBar_GetMinMaxValues --- src/ui/simple/CSimpleStatusBar.cpp | 8 ++++++++ src/ui/simple/CSimpleStatusBar.hpp | 2 ++ src/ui/simple/CSimpleStatusBarScript.cpp | 8 +++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleStatusBar.cpp b/src/ui/simple/CSimpleStatusBar.cpp index 1190a48..a2b1c8a 100644 --- a/src/ui/simple/CSimpleStatusBar.cpp +++ b/src/ui/simple/CSimpleStatusBar.cpp @@ -54,6 +54,14 @@ int32_t CSimpleStatusBar::GetScriptMetaTable() { return CSimpleStatusBar::s_metatable; } +float CSimpleStatusBar::GetMaxValue() const { + return this->m_maxValue; +} + +float CSimpleStatusBar::GetMinValue() const { + return this->m_minValue; +} + float CSimpleStatusBar::GetValue() const { return this->m_value; } diff --git a/src/ui/simple/CSimpleStatusBar.hpp b/src/ui/simple/CSimpleStatusBar.hpp index 1655a46..1bdb821 100644 --- a/src/ui/simple/CSimpleStatusBar.hpp +++ b/src/ui/simple/CSimpleStatusBar.hpp @@ -24,6 +24,8 @@ class CSimpleStatusBar : public CSimpleFrame { // Public member functions CSimpleStatusBar(CSimpleFrame* parent); + float GetMaxValue() const; + float GetMinValue() const; float GetValue() const; void RunOnMinMaxChangedScript(); void RunOnValueChangedScript(); diff --git a/src/ui/simple/CSimpleStatusBarScript.cpp b/src/ui/simple/CSimpleStatusBarScript.cpp index 56bc271..2701c2f 100644 --- a/src/ui/simple/CSimpleStatusBarScript.cpp +++ b/src/ui/simple/CSimpleStatusBarScript.cpp @@ -15,7 +15,13 @@ int32_t CSimpleStatusBar_SetOrientation(lua_State* L) { } int32_t CSimpleStatusBar_GetMinMaxValues(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleStatusBar::GetObjectType(); + auto statusBar = static_cast(FrameScript_GetObjectThis(L, type)); + + lua_pushnumber(L, statusBar->GetMinValue()); + lua_pushnumber(L, statusBar->GetMaxValue()); + + return 2; } int32_t CSimpleStatusBar_SetMinMaxValues(lua_State* L) { From 856bb72e1a0051599ab93dfcb4365769e9dab287 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 4 Feb 2026 21:53:51 -0600 Subject: [PATCH 173/269] chore(ui): improve CSimpleStatusBar ctor --- src/ui/simple/CSimpleStatusBar.cpp | 4 ---- src/ui/simple/CSimpleStatusBar.hpp | 6 +++++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ui/simple/CSimpleStatusBar.cpp b/src/ui/simple/CSimpleStatusBar.cpp index a2b1c8a..e5c3f20 100644 --- a/src/ui/simple/CSimpleStatusBar.cpp +++ b/src/ui/simple/CSimpleStatusBar.cpp @@ -28,10 +28,6 @@ void CSimpleStatusBar::RegisterScriptMethods(lua_State* L) { FrameScript_Object::FillScriptMethodTable(L, SimpleStatusBarMethods, NUM_SIMPLE_STATUS_BAR_SCRIPT_METHODS); } -CSimpleStatusBar::CSimpleStatusBar(CSimpleFrame* parent) : CSimpleFrame(parent) { - // TODO -} - FrameScript_Object::ScriptIx* CSimpleStatusBar::GetScriptByName(const char* name, ScriptData& data) { auto script = this->CSimpleFrame::GetScriptByName(name, data); diff --git a/src/ui/simple/CSimpleStatusBar.hpp b/src/ui/simple/CSimpleStatusBar.hpp index 1bdb821..203f6a4 100644 --- a/src/ui/simple/CSimpleStatusBar.hpp +++ b/src/ui/simple/CSimpleStatusBar.hpp @@ -23,7 +23,11 @@ class CSimpleStatusBar : public CSimpleFrame { virtual void LoadXML(const XMLNode* node, CStatus* status); // Public member functions - CSimpleStatusBar(CSimpleFrame* parent); + CSimpleStatusBar(CSimpleFrame* parent) + : CSimpleFrame(parent) + , m_changed(false) + , m_rangeSet(false) + , m_valueSet(false) {}; float GetMaxValue() const; float GetMinValue() const; float GetValue() const; From 534e05be93cacf4820ed3ab5c9d79531e14a31ff Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 07:01:30 -0600 Subject: [PATCH 174/269] feat(ui): add CLayoutFrame::GetSize --- src/ui/CLayoutFrame.cpp | 20 ++++++++++++++++++-- src/ui/CLayoutFrame.hpp | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/ui/CLayoutFrame.cpp b/src/ui/CLayoutFrame.cpp index 4df0f77..886d776 100644 --- a/src/ui/CLayoutFrame.cpp +++ b/src/ui/CLayoutFrame.cpp @@ -332,6 +332,10 @@ void CLayoutFrame::GetFirstPointY(const FRAMEPOINT* const pointarray, int32_t el } } +float CLayoutFrame::GetHeight() { + return this->m_height; +} + CLayoutFrame* CLayoutFrame::GetLayoutFrameByName(const char* name) { return nullptr; } @@ -353,8 +357,20 @@ int32_t CLayoutFrame::GetRect(CRect* rect) { return 1; } -float CLayoutFrame::GetHeight() { - return this->m_height; +void CLayoutFrame::GetSize(float& width, float& height, int32_t a4) { + width = this->GetWidth(); + height = this->GetHeight(); + + if (!a4 && (width == 0.0f || height == 0.0f)) { + if (this->m_flags & FLAG_RESIZE_PENDING) { + this->Resize(1); + } + + if (this->m_flags & 0x1) { + width = (this->m_rect.maxX - this->m_rect.minX) / this->m_layoutScale; + height = (this->m_rect.maxY - this->m_rect.minY) / this->m_layoutScale; + } + } } float CLayoutFrame::GetWidth() { diff --git a/src/ui/CLayoutFrame.hpp b/src/ui/CLayoutFrame.hpp index 7e0da91..53ab714 100644 --- a/src/ui/CLayoutFrame.hpp +++ b/src/ui/CLayoutFrame.hpp @@ -51,6 +51,7 @@ class CLayoutFrame { virtual void SetHeight(float height); virtual float GetWidth(); virtual float GetHeight(); + virtual void GetSize(float& width, float& height, int32_t a4); virtual void GetClampRectInsets(float& a1, float& a2, float& a3, float& a4); virtual int32_t IsAttachmentOrigin(); virtual CLayoutFrame* GetLayoutFrameByName(const char* name); From aa22dd952a86b03826bc960413133c42d3e18cd8 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 07:05:28 -0600 Subject: [PATCH 175/269] feat(ui): add CSimpleStatusBar::OnLayerUpdate --- src/ui/simple/CSimpleStatusBar.cpp | 50 ++++++++++++++++++++++++++++++ src/ui/simple/CSimpleStatusBar.hpp | 3 ++ 2 files changed, 53 insertions(+) diff --git a/src/ui/simple/CSimpleStatusBar.cpp b/src/ui/simple/CSimpleStatusBar.cpp index e5c3f20..c3c0d28 100644 --- a/src/ui/simple/CSimpleStatusBar.cpp +++ b/src/ui/simple/CSimpleStatusBar.cpp @@ -28,6 +28,16 @@ void CSimpleStatusBar::RegisterScriptMethods(lua_State* L) { FrameScript_Object::FillScriptMethodTable(L, SimpleStatusBarMethods, NUM_SIMPLE_STATUS_BAR_SCRIPT_METHODS); } +float CSimpleStatusBar::GetAnimValue() const { + auto range = this->m_maxValue - this->m_minValue; + + if (range <= 0.0f) { + return 0.0f; + } + + return (this->m_value - this->m_minValue) / range; +} + FrameScript_Object::ScriptIx* CSimpleStatusBar::GetScriptByName(const char* name, ScriptData& data) { auto script = this->CSimpleFrame::GetScriptByName(name, data); @@ -129,6 +139,46 @@ void CSimpleStatusBar::LoadXML(const XMLNode* node, CStatus* status) { } } +void CSimpleStatusBar::OnLayerUpdate(float elapsedSec) { + this->CSimpleFrame::OnLayerUpdate(elapsedSec); + + if (!this->m_changed || !this->m_rangeSet || !this->m_valueSet || !this->m_barTexture) { + return; + } + + auto animValue = this->GetAnimValue(); + + if (animValue <= 0.0f) { + this->m_barTexture->Hide(); + this->m_changed = false; + + return; + } + + float width, height; + this->GetSize(width, height, false); + + auto fill = 1.0f - animValue; + + this->m_barTexture->Show(); + + if (this->m_orientation == ORIENTATION_VERTICAL) { + this->m_barTexture->SetPoint(FRAMEPOINT_BOTTOMLEFT, this, FRAMEPOINT_BOTTOMLEFT, 0.0f, 0.0f, true); + this->m_barTexture->SetPoint(FRAMEPOINT_BOTTOMRIGHT, this, FRAMEPOINT_BOTTOMRIGHT, 0.0f, 0.0f, true); + + this->m_barTexture->SetPoint(FRAMEPOINT_TOPLEFT, this, FRAMEPOINT_TOPLEFT, 0.0f, -(fill * height), true); + this->m_barTexture->SetPoint(FRAMEPOINT_TOPRIGHT, this, FRAMEPOINT_TOPRIGHT, 0.0f, -(fill * height), true); + } else { + this->m_barTexture->SetPoint(FRAMEPOINT_TOPLEFT, this, FRAMEPOINT_TOPLEFT, 0.0f, 0.0f, true); + this->m_barTexture->SetPoint(FRAMEPOINT_BOTTOMLEFT, this, FRAMEPOINT_BOTTOMLEFT, 0.0f, 0.0f, true); + + this->m_barTexture->SetPoint(FRAMEPOINT_TOPRIGHT, this, FRAMEPOINT_TOPRIGHT, -(fill * width), 0.0f, true); + this->m_barTexture->SetPoint(FRAMEPOINT_BOTTOMRIGHT, this, FRAMEPOINT_BOTTOMRIGHT, -(fill * width), 0.0f, true); + } + + this->m_changed = false; +} + void CSimpleStatusBar::RunOnMinMaxChangedScript() { if (!this->m_onMinMaxChanged.luaRef) { return; diff --git a/src/ui/simple/CSimpleStatusBar.hpp b/src/ui/simple/CSimpleStatusBar.hpp index 203f6a4..0a81141 100644 --- a/src/ui/simple/CSimpleStatusBar.hpp +++ b/src/ui/simple/CSimpleStatusBar.hpp @@ -19,6 +19,8 @@ class CSimpleStatusBar : public CSimpleFrame { virtual ScriptIx* GetScriptByName(const char* name, ScriptData& data); virtual bool IsA(int32_t type); // TODO + virtual void OnLayerUpdate(float elapsedSec); + // TODO virtual void SetValue(float value); virtual void LoadXML(const XMLNode* node, CStatus* status); @@ -28,6 +30,7 @@ class CSimpleStatusBar : public CSimpleFrame { , m_changed(false) , m_rangeSet(false) , m_valueSet(false) {}; + float GetAnimValue() const; float GetMaxValue() const; float GetMinValue() const; float GetValue() const; From aac8cf0855322eedf049b62f1490c72ba51543f5 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 13:26:59 -0600 Subject: [PATCH 176/269] feat(object): add CGObject::IsA --- src/object/client/CGObject.cpp | 4 ++++ src/object/client/CGObject.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/object/client/CGObject.cpp b/src/object/client/CGObject.cpp index 41236cf..64d8359 100644 --- a/src/object/client/CGObject.cpp +++ b/src/object/client/CGObject.cpp @@ -36,6 +36,10 @@ OBJECT_TYPE_ID CGObject::GetTypeID() const { return this->m_typeID; } +int32_t CGObject::IsA(OBJECT_TYPE type) const { + return (this->GetType() & type) != 0; +} + CGObjectData* CGObject::Obj() const { return this->m_obj; } diff --git a/src/object/client/CGObject.hpp b/src/object/client/CGObject.hpp index 55f4514..4331157 100644 --- a/src/object/client/CGObject.hpp +++ b/src/object/client/CGObject.hpp @@ -31,6 +31,7 @@ class CGObject { WOWGUID GetGUID() const; OBJECT_TYPE GetType() const; OBJECT_TYPE_ID GetTypeID() const; + int32_t IsA(OBJECT_TYPE type) const; protected: // Protected member variables From f567a3a7c87c004c3903188fe9e421d77b7f9701 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 14:51:17 -0600 Subject: [PATCH 177/269] feat(object): add CGPlayer::GetXP --- src/object/client/CGPlayer.cpp | 4 ++++ src/object/client/CGPlayer.hpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/object/client/CGPlayer.cpp b/src/object/client/CGPlayer.cpp index 1e44711..422f8dd 100644 --- a/src/object/client/CGPlayer.cpp +++ b/src/object/client/CGPlayer.cpp @@ -41,6 +41,10 @@ uint32_t CGPlayer::TotalRemoteFieldsSaved() { return CGPlayer::GetBaseOffsetSaved() + 173; } +uint32_t CGPlayer::GetXP() const { + return this->Player()->xp; +} + CGPlayerData* CGPlayer::Player() const { return this->m_player; } diff --git a/src/object/client/CGPlayer.hpp b/src/object/client/CGPlayer.hpp index 707f39f..d6090e1 100644 --- a/src/object/client/CGPlayer.hpp +++ b/src/object/client/CGPlayer.hpp @@ -148,6 +148,9 @@ class CGPlayer { static uint32_t TotalFieldsSaved(); static uint32_t TotalRemoteFieldsSaved(); + // Public member functions + uint32_t GetXP() const; + protected: // Protected member variables CGPlayerData* m_player; From c9f26b6666f33e23504e231dcdf06e499a42b9a6 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 14:53:58 -0600 Subject: [PATCH 178/269] feat(object): add CGObject::IsExactlyA --- src/object/client/CGObject.cpp | 4 ++++ src/object/client/CGObject.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/object/client/CGObject.cpp b/src/object/client/CGObject.cpp index 64d8359..153cce1 100644 --- a/src/object/client/CGObject.cpp +++ b/src/object/client/CGObject.cpp @@ -40,6 +40,10 @@ int32_t CGObject::IsA(OBJECT_TYPE type) const { return (this->GetType() & type) != 0; } +int32_t CGObject::IsExactlyA(OBJECT_TYPE_ID typeID) const { + return this->m_typeID == typeID; +} + CGObjectData* CGObject::Obj() const { return this->m_obj; } diff --git a/src/object/client/CGObject.hpp b/src/object/client/CGObject.hpp index 4331157..506cddd 100644 --- a/src/object/client/CGObject.hpp +++ b/src/object/client/CGObject.hpp @@ -32,6 +32,7 @@ class CGObject { OBJECT_TYPE GetType() const; OBJECT_TYPE_ID GetTypeID() const; int32_t IsA(OBJECT_TYPE type) const; + int32_t IsExactlyA(OBJECT_TYPE_ID typeID) const; protected: // Protected member variables From 5d81022c749476adbb90d7b92c0da86b0871521e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 15:00:32 -0600 Subject: [PATCH 179/269] feat(object): add CGPlayer::GetNextLevelXP --- src/object/client/CGPlayer.cpp | 4 ++++ src/object/client/CGPlayer.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/object/client/CGPlayer.cpp b/src/object/client/CGPlayer.cpp index 422f8dd..568baf3 100644 --- a/src/object/client/CGPlayer.cpp +++ b/src/object/client/CGPlayer.cpp @@ -41,6 +41,10 @@ uint32_t CGPlayer::TotalRemoteFieldsSaved() { return CGPlayer::GetBaseOffsetSaved() + 173; } +uint32_t CGPlayer::GetNextLevelXP() const { + return this->Player()->nextLevelXP; +} + uint32_t CGPlayer::GetXP() const { return this->Player()->xp; } diff --git a/src/object/client/CGPlayer.hpp b/src/object/client/CGPlayer.hpp index d6090e1..3d18372 100644 --- a/src/object/client/CGPlayer.hpp +++ b/src/object/client/CGPlayer.hpp @@ -149,6 +149,7 @@ class CGPlayer { static uint32_t TotalRemoteFieldsSaved(); // Public member functions + uint32_t GetNextLevelXP() const; uint32_t GetXP() const; protected: From ee48e47992791de8af679b4146cac4ffdcb2aef6 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 15:58:48 -0600 Subject: [PATCH 180/269] feat(object): add CGPlayer_C::GetActiveXP --- src/object/client/CGPlayer_C.cpp | 9 +++++++++ src/object/client/CGPlayer_C.hpp | 1 + 2 files changed, 10 insertions(+) diff --git a/src/object/client/CGPlayer_C.cpp b/src/object/client/CGPlayer_C.cpp index e34f048..cb43f4c 100644 --- a/src/object/client/CGPlayer_C.cpp +++ b/src/object/client/CGPlayer_C.cpp @@ -1,5 +1,6 @@ #include "object/client/CGPlayer_C.hpp" #include "db/Db.hpp" +#include "object/client/ObjMgr.hpp" #include "object/Types.hpp" #include @@ -11,6 +12,14 @@ CGPlayer_C::~CGPlayer_C() { // TODO } +uint32_t CGPlayer_C::GetActiveXP() const { + if (this->GetGUID() != ClntObjMgrGetActivePlayer()) { + return 0; + } + + return this->GetXP(); +} + void CGPlayer_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { // TODO diff --git a/src/object/client/CGPlayer_C.hpp b/src/object/client/CGPlayer_C.hpp index e224be4..85db184 100644 --- a/src/object/client/CGPlayer_C.hpp +++ b/src/object/client/CGPlayer_C.hpp @@ -15,6 +15,7 @@ class CGPlayer_C : public CGUnit_C, public CGPlayer { // Public member functions CGPlayer_C(uint32_t time, CClientObjCreate& objCreate); + uint32_t GetActiveXP() const; void PostInit(uint32_t time, const CClientObjCreate& init, bool a4); void SetStorage(uint32_t* storage, uint32_t* saved); }; From ed9c68360242301276e48bd6bbe18e34ccaaae1e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 16:01:46 -0600 Subject: [PATCH 181/269] feat(object): add CGPlayer_C::GetActiveNextLevelXP --- src/object/client/CGPlayer_C.cpp | 8 ++++++++ src/object/client/CGPlayer_C.hpp | 1 + 2 files changed, 9 insertions(+) diff --git a/src/object/client/CGPlayer_C.cpp b/src/object/client/CGPlayer_C.cpp index cb43f4c..34ccb52 100644 --- a/src/object/client/CGPlayer_C.cpp +++ b/src/object/client/CGPlayer_C.cpp @@ -12,6 +12,14 @@ CGPlayer_C::~CGPlayer_C() { // TODO } +uint32_t CGPlayer_C::GetActiveNextLevelXP() const { + if (this->GetGUID() != ClntObjMgrGetActivePlayer()) { + return 0; + } + + return this->GetNextLevelXP(); +} + uint32_t CGPlayer_C::GetActiveXP() const { if (this->GetGUID() != ClntObjMgrGetActivePlayer()) { return 0; diff --git a/src/object/client/CGPlayer_C.hpp b/src/object/client/CGPlayer_C.hpp index 85db184..20813a8 100644 --- a/src/object/client/CGPlayer_C.hpp +++ b/src/object/client/CGPlayer_C.hpp @@ -15,6 +15,7 @@ class CGPlayer_C : public CGUnit_C, public CGPlayer { // Public member functions CGPlayer_C(uint32_t time, CClientObjCreate& objCreate); + uint32_t GetActiveNextLevelXP() const; uint32_t GetActiveXP() const; void PostInit(uint32_t time, const CClientObjCreate& init, bool a4); void SetStorage(uint32_t* storage, uint32_t* saved); From cfb8f2bae11eadbb00333028d3330a5b4351814e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 16:05:12 -0600 Subject: [PATCH 182/269] feat(ui): add Script_GetUnitFromName --- src/ui/game/ScriptUtil.cpp | 10 ++++++++++ src/ui/game/ScriptUtil.hpp | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/src/ui/game/ScriptUtil.cpp b/src/ui/game/ScriptUtil.cpp index 0f5a809..1822389 100644 --- a/src/ui/game/ScriptUtil.cpp +++ b/src/ui/game/ScriptUtil.cpp @@ -12,6 +12,16 @@ bool ParseTrailingTokens(const char* token, WOWGUID& guid, CGPlayer_C* player) { } +CGUnit_C* Script_GetUnitFromName(const char* name) { + WOWGUID guid; + + if (!Script_GetGUIDFromToken(name, guid, false)) { + return nullptr; + } + + return static_cast(ClntObjMgrObjectPtr(guid, TYPE_UNIT, __FILE__, __LINE__)); +} + bool Script_GetGUIDFromString(const char*& token, WOWGUID& guid) { // TODO return true; diff --git a/src/ui/game/ScriptUtil.hpp b/src/ui/game/ScriptUtil.hpp index c06aa58..3d3c1c8 100644 --- a/src/ui/game/ScriptUtil.hpp +++ b/src/ui/game/ScriptUtil.hpp @@ -3,6 +3,10 @@ #include "util/GUID.hpp" +class CGUnit_C; + +CGUnit_C* Script_GetUnitFromName(const char* name); + bool Script_GetGUIDFromString(const char*& token, WOWGUID& guid); bool Script_GetGUIDFromToken(const char* token, WOWGUID& guid, bool defaultToTarget); From a53e1360a4e5cc422fa2df6efa4e9d7445816a44 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 16:12:04 -0600 Subject: [PATCH 183/269] feat(ui): implement Script_UnitXP --- src/ui/game/ScriptEvents.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/ui/game/ScriptEvents.cpp b/src/ui/game/ScriptEvents.cpp index f58cce5..7139e84 100644 --- a/src/ui/game/ScriptEvents.cpp +++ b/src/ui/game/ScriptEvents.cpp @@ -173,7 +173,23 @@ int32_t Script_UnitPVPName(lua_State* L) { } int32_t Script_UnitXP(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isstring(L, 1)) { + luaL_error(L, "Usage: UnitXP(\"unit\")"); + return 0; + } + + auto name = lua_tostring(L, 1); + auto unit = Script_GetUnitFromName(name); + + float xp = 0.0f; + + if (unit && unit->IsA(TYPE_PLAYER)) { + xp = static_cast(unit)->GetActiveXP(); + } + + lua_pushnumber(L, xp); + + return 1; } int32_t Script_UnitXPMax(lua_State* L) { From 315ea05ba048cd4d43e332a797fddf34c882f5e8 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 16:56:44 -0600 Subject: [PATCH 184/269] feat(ui): implement Script_UnitXPMax --- src/ui/game/ScriptEvents.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/ui/game/ScriptEvents.cpp b/src/ui/game/ScriptEvents.cpp index 7139e84..7aa33f2 100644 --- a/src/ui/game/ScriptEvents.cpp +++ b/src/ui/game/ScriptEvents.cpp @@ -193,7 +193,23 @@ int32_t Script_UnitXP(lua_State* L) { } int32_t Script_UnitXPMax(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isstring(L, 1)) { + luaL_error(L, "Usage: UnitXPMax(\"unit\")"); + return 0; + } + + auto name = lua_tostring(L, 1); + auto unit = Script_GetUnitFromName(name); + + float xpMax = 0.0f; + + if (unit && unit->IsA(TYPE_PLAYER)) { + xpMax = static_cast(unit)->GetActiveNextLevelXP(); + } + + lua_pushnumber(L, xpMax); + + return 1; } int32_t Script_UnitHealth(lua_State* L) { From 19f51db2e2a4b0edd33008a14b843e9758746e50 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 20:13:32 -0600 Subject: [PATCH 185/269] chore(ui): move ScriptEventsInitialize into game ui dir --- src/ui/FrameScript.cpp | 653 ----------------------------------- src/ui/FrameScript.hpp | 2 - src/ui/Game.hpp | 1 + src/ui/game/ScriptEvents.cpp | 650 ++++++++++++++++++++++++++++++++++ src/ui/game/ScriptEvents.hpp | 2 + 5 files changed, 653 insertions(+), 655 deletions(-) diff --git a/src/ui/FrameScript.cpp b/src/ui/FrameScript.cpp index 4ab2053..95e2c57 100644 --- a/src/ui/FrameScript.cpp +++ b/src/ui/FrameScript.cpp @@ -1083,656 +1083,3 @@ void FrameScript_UnregisterScriptEvent(FrameScript_Object* object, FrameScript_E } } } - -void ScriptEventsInitialize() { - g_scriptEvents[0] = "UNIT_PET"; - g_scriptEvents[2] = "UNIT_PET"; - g_scriptEvents[12] = "UNIT_TARGET"; - g_scriptEvents[17] = "UNIT_DISPLAYPOWER"; - g_scriptEvents[18] = "UNIT_HEALTH"; - g_scriptEvents[19] = "UNIT_MANA"; - g_scriptEvents[20] = "UNIT_RAGE"; - g_scriptEvents[21] = "UNIT_FOCUS"; - g_scriptEvents[22] = "UNIT_ENERGY"; - g_scriptEvents[23] = "UNIT_HAPPINESS"; - g_scriptEvents[25] = "UNIT_RUNIC_POWER"; - g_scriptEvents[26] = "UNIT_MAXHEALTH"; - g_scriptEvents[27] = "UNIT_MAXMANA"; - g_scriptEvents[28] = "UNIT_MAXRAGE"; - g_scriptEvents[29] = "UNIT_MAXFOCUS"; - g_scriptEvents[30] = "UNIT_MAXENERGY"; - g_scriptEvents[31] = "UNIT_MAXHAPPINESS"; - g_scriptEvents[33] = "UNIT_MAXRUNIC_POWER"; - g_scriptEvents[48] = "UNIT_LEVEL"; - g_scriptEvents[49] = "UNIT_FACTION"; - g_scriptEvents[53] = "UNIT_FLAGS"; - g_scriptEvents[54] = "UNIT_FLAGS"; - g_scriptEvents[56] = "UNIT_ATTACK_SPEED"; - g_scriptEvents[57] = "UNIT_ATTACK_SPEED"; - g_scriptEvents[58] = "UNIT_RANGEDDAMAGE"; - g_scriptEvents[64] = "UNIT_DAMAGE"; - g_scriptEvents[65] = "UNIT_DAMAGE"; - g_scriptEvents[66] = "UNIT_DAMAGE"; - g_scriptEvents[67] = "UNIT_DAMAGE"; - g_scriptEvents[71] = "UNIT_PET_EXPERIENCE"; - g_scriptEvents[72] = "UNIT_PET_EXPERIENCE"; - g_scriptEvents[73] = "UNIT_DYNAMIC_FLAGS"; - g_scriptEvents[78] = "UNIT_STATS"; - g_scriptEvents[79] = "UNIT_STATS"; - g_scriptEvents[80] = "UNIT_STATS"; - g_scriptEvents[81] = "UNIT_STATS"; - g_scriptEvents[82] = "UNIT_STATS"; - g_scriptEvents[93] = "UNIT_RESISTANCES"; - g_scriptEvents[94] = "UNIT_RESISTANCES"; - g_scriptEvents[95] = "UNIT_RESISTANCES"; - g_scriptEvents[96] = "UNIT_RESISTANCES"; - g_scriptEvents[97] = "UNIT_RESISTANCES"; - g_scriptEvents[98] = "UNIT_RESISTANCES"; - g_scriptEvents[99] = "UNIT_RESISTANCES"; - g_scriptEvents[100] = "UNIT_RESISTANCES"; - g_scriptEvents[101] = "UNIT_RESISTANCES"; - g_scriptEvents[102] = "UNIT_RESISTANCES"; - g_scriptEvents[103] = "UNIT_RESISTANCES"; - g_scriptEvents[104] = "UNIT_RESISTANCES"; - g_scriptEvents[105] = "UNIT_RESISTANCES"; - g_scriptEvents[106] = "UNIT_RESISTANCES"; - g_scriptEvents[107] = "UNIT_RESISTANCES"; - g_scriptEvents[108] = "UNIT_RESISTANCES"; - g_scriptEvents[109] = "UNIT_RESISTANCES"; - g_scriptEvents[110] = "UNIT_RESISTANCES"; - g_scriptEvents[111] = "UNIT_RESISTANCES"; - g_scriptEvents[112] = "UNIT_RESISTANCES"; - g_scriptEvents[113] = "UNIT_RESISTANCES"; - g_scriptEvents[117] = "UNIT_ATTACK_POWER"; - g_scriptEvents[118] = "UNIT_ATTACK_POWER"; - g_scriptEvents[119] = "UNIT_ATTACK_POWER"; - g_scriptEvents[120] = "UNIT_RANGED_ATTACK_POWER"; - g_scriptEvents[121] = "UNIT_RANGED_ATTACK_POWER"; - g_scriptEvents[122] = "UNIT_RANGED_ATTACK_POWER"; - g_scriptEvents[123] = "UNIT_RANGEDDAMAGE"; - g_scriptEvents[124] = "UNIT_RANGEDDAMAGE"; - g_scriptEvents[125] = "UNIT_MANA"; - g_scriptEvents[132] = "UNIT_MANA"; - g_scriptEvents[139] = "UNIT_STATS"; - g_scriptEvents[142] = "UNIT_AURA"; - g_scriptEvents[143] = "UNIT_COMBAT"; - g_scriptEvents[144] = "UNIT_NAME_UPDATE"; - g_scriptEvents[145] = "UNIT_PORTRAIT_UPDATE"; - g_scriptEvents[146] = "UNIT_MODEL_CHANGED"; - g_scriptEvents[147] = "UNIT_INVENTORY_CHANGED"; - g_scriptEvents[148] = "UNIT_CLASSIFICATION_CHANGED"; - g_scriptEvents[149] = "UNIT_COMBO_POINTS"; - g_scriptEvents[150] = "ITEM_LOCK_CHANGED"; - g_scriptEvents[151] = "PLAYER_XP_UPDATE"; - g_scriptEvents[152] = "PLAYER_REGEN_DISABLED"; - g_scriptEvents[153] = "PLAYER_REGEN_ENABLED"; - g_scriptEvents[154] = "PLAYER_AURAS_CHANGED"; - g_scriptEvents[155] = "PLAYER_ENTER_COMBAT"; - g_scriptEvents[156] = "PLAYER_LEAVE_COMBAT"; - g_scriptEvents[157] = "PLAYER_TARGET_CHANGED"; - g_scriptEvents[158] = "PLAYER_FOCUS_CHANGED"; - g_scriptEvents[159] = "PLAYER_CONTROL_LOST"; - g_scriptEvents[160] = "PLAYER_CONTROL_GAINED"; - g_scriptEvents[161] = "PLAYER_FARSIGHT_FOCUS_CHANGED"; - g_scriptEvents[162] = "PLAYER_LEVEL_UP"; - g_scriptEvents[163] = "PLAYER_MONEY"; - g_scriptEvents[164] = "PLAYER_DAMAGE_DONE_MODS"; - g_scriptEvents[165] = "PLAYER_TOTEM_UPDATE"; - g_scriptEvents[166] = "ZONE_CHANGED"; - g_scriptEvents[167] = "ZONE_CHANGED_INDOORS"; - g_scriptEvents[168] = "ZONE_CHANGED_NEW_AREA"; - g_scriptEvents[169] = "MINIMAP_UPDATE_ZOOM"; - g_scriptEvents[170] = "MINIMAP_UPDATE_TRACKING"; - g_scriptEvents[171] = "SCREENSHOT_SUCCEEDED"; - g_scriptEvents[172] = "SCREENSHOT_FAILED"; - g_scriptEvents[173] = "ACTIONBAR_SHOWGRID"; - g_scriptEvents[174] = "ACTIONBAR_HIDEGRID"; - g_scriptEvents[175] = "ACTIONBAR_PAGE_CHANGED"; - g_scriptEvents[176] = "ACTIONBAR_SLOT_CHANGED"; - g_scriptEvents[177] = "ACTIONBAR_UPDATE_STATE"; - g_scriptEvents[178] = "ACTIONBAR_UPDATE_USABLE"; - g_scriptEvents[179] = "ACTIONBAR_UPDATE_COOLDOWN"; - g_scriptEvents[180] = "UPDATE_BONUS_ACTIONBAR"; - g_scriptEvents[181] = "PARTY_MEMBERS_CHANGED"; - g_scriptEvents[182] = "PARTY_LEADER_CHANGED"; - g_scriptEvents[183] = "PARTY_MEMBER_ENABLE"; - g_scriptEvents[184] = "PARTY_MEMBER_DISABLE"; - g_scriptEvents[185] = "PARTY_LOOT_METHOD_CHANGED"; - g_scriptEvents[186] = "SYSMSG"; - g_scriptEvents[187] = "UI_ERROR_MESSAGE"; - g_scriptEvents[188] = "UI_INFO_MESSAGE"; - g_scriptEvents[189] = "UPDATE_CHAT_COLOR"; - g_scriptEvents[190] = "CHAT_MSG_ADDON"; - g_scriptEvents[191] = "CHAT_MSG_SYSTEM"; - g_scriptEvents[192] = "CHAT_MSG_SAY"; - g_scriptEvents[193] = "CHAT_MSG_PARTY"; - g_scriptEvents[194] = "CHAT_MSG_RAID"; - g_scriptEvents[195] = "CHAT_MSG_GUILD"; - g_scriptEvents[196] = "CHAT_MSG_OFFICER"; - g_scriptEvents[197] = "CHAT_MSG_YELL"; - g_scriptEvents[198] = "CHAT_MSG_WHISPER"; - g_scriptEvents[199] = "CHAT_MSG_WHISPER_INFORM"; - g_scriptEvents[200] = "CHAT_MSG_EMOTE"; - g_scriptEvents[201] = "CHAT_MSG_TEXT_EMOTE"; - g_scriptEvents[202] = "CHAT_MSG_MONSTER_SAY"; - g_scriptEvents[203] = "CHAT_MSG_MONSTER_PARTY"; - g_scriptEvents[204] = "CHAT_MSG_MONSTER_YELL"; - g_scriptEvents[205] = "CHAT_MSG_MONSTER_WHISPER"; - g_scriptEvents[206] = "CHAT_MSG_MONSTER_EMOTE"; - g_scriptEvents[207] = "CHAT_MSG_CHANNEL"; - g_scriptEvents[208] = "CHAT_MSG_CHANNEL_JOIN"; - g_scriptEvents[209] = "CHAT_MSG_CHANNEL_LEAVE"; - g_scriptEvents[210] = "CHAT_MSG_CHANNEL_LIST"; - g_scriptEvents[211] = "CHAT_MSG_CHANNEL_NOTICE"; - g_scriptEvents[212] = "CHAT_MSG_CHANNEL_NOTICE_USER"; - g_scriptEvents[213] = "CHAT_MSG_AFK"; - g_scriptEvents[214] = "CHAT_MSG_DND"; - g_scriptEvents[215] = "CHAT_MSG_IGNORED"; - g_scriptEvents[216] = "CHAT_MSG_SKILL"; - g_scriptEvents[217] = "CHAT_MSG_LOOT"; - g_scriptEvents[218] = "CHAT_MSG_MONEY"; - g_scriptEvents[219] = "CHAT_MSG_OPENING"; - g_scriptEvents[220] = "CHAT_MSG_TRADESKILLS"; - g_scriptEvents[221] = "CHAT_MSG_PET_INFO"; - g_scriptEvents[222] = "CHAT_MSG_COMBAT_MISC_INFO"; - g_scriptEvents[223] = "CHAT_MSG_COMBAT_XP_GAIN"; - g_scriptEvents[224] = "CHAT_MSG_COMBAT_HONOR_GAIN"; - g_scriptEvents[225] = "CHAT_MSG_COMBAT_FACTION_CHANGE"; - g_scriptEvents[226] = "CHAT_MSG_BG_SYSTEM_NEUTRAL"; - g_scriptEvents[227] = "CHAT_MSG_BG_SYSTEM_ALLIANCE"; - g_scriptEvents[228] = "CHAT_MSG_BG_SYSTEM_HORDE"; - g_scriptEvents[229] = "CHAT_MSG_RAID_LEADER"; - g_scriptEvents[230] = "CHAT_MSG_RAID_WARNING"; - g_scriptEvents[231] = "CHAT_MSG_RAID_BOSS_WHISPER"; - g_scriptEvents[232] = "CHAT_MSG_RAID_BOSS_EMOTE"; - g_scriptEvents[233] = "CHAT_MSG_FILTERED"; - g_scriptEvents[234] = "CHAT_MSG_BATTLEGROUND"; - g_scriptEvents[235] = "CHAT_MSG_BATTLEGROUND_LEADER"; - g_scriptEvents[236] = "CHAT_MSG_RESTRICTED"; - - // TODO - // g_scriptEvents[237] = &byte_9E14FF; - - g_scriptEvents[238] = "CHAT_MSG_ACHIEVEMENT"; - g_scriptEvents[239] = "CHAT_MSG_GUILD_ACHIEVEMENT"; - g_scriptEvents[240] = "LANGUAGE_LIST_CHANGED"; - g_scriptEvents[241] = "TIME_PLAYED_MSG"; - g_scriptEvents[242] = "SPELLS_CHANGED"; - g_scriptEvents[243] = "CURRENT_SPELL_CAST_CHANGED"; - g_scriptEvents[244] = "SPELL_UPDATE_COOLDOWN"; - g_scriptEvents[245] = "SPELL_UPDATE_USABLE"; - g_scriptEvents[246] = "CHARACTER_POINTS_CHANGED"; - g_scriptEvents[247] = "SKILL_LINES_CHANGED"; - g_scriptEvents[248] = "ITEM_PUSH"; - g_scriptEvents[249] = "LOOT_OPENED"; - g_scriptEvents[250] = "LOOT_SLOT_CLEARED"; - g_scriptEvents[251] = "LOOT_SLOT_CHANGED"; - g_scriptEvents[252] = "LOOT_CLOSED"; - g_scriptEvents[253] = "PLAYER_LOGIN"; - g_scriptEvents[254] = "PLAYER_LOGOUT"; - g_scriptEvents[255] = "PLAYER_ENTERING_WORLD"; - g_scriptEvents[256] = "PLAYER_LEAVING_WORLD"; - g_scriptEvents[257] = "PLAYER_ALIVE"; - g_scriptEvents[258] = "PLAYER_DEAD"; - g_scriptEvents[259] = "PLAYER_CAMPING"; - g_scriptEvents[260] = "PLAYER_QUITING"; - g_scriptEvents[261] = "LOGOUT_CANCEL"; - g_scriptEvents[262] = "RESURRECT_REQUEST"; - g_scriptEvents[263] = "PARTY_INVITE_REQUEST"; - g_scriptEvents[264] = "PARTY_INVITE_CANCEL"; - g_scriptEvents[265] = "GUILD_INVITE_REQUEST"; - g_scriptEvents[266] = "GUILD_INVITE_CANCEL"; - g_scriptEvents[267] = "GUILD_MOTD"; - g_scriptEvents[268] = "TRADE_REQUEST"; - g_scriptEvents[269] = "TRADE_REQUEST_CANCEL"; - g_scriptEvents[270] = "LOOT_BIND_CONFIRM"; - g_scriptEvents[271] = "EQUIP_BIND_CONFIRM"; - g_scriptEvents[272] = "AUTOEQUIP_BIND_CONFIRM"; - g_scriptEvents[273] = "USE_BIND_CONFIRM"; - g_scriptEvents[274] = "DELETE_ITEM_CONFIRM"; - g_scriptEvents[275] = "CURSOR_UPDATE"; - g_scriptEvents[276] = "ITEM_TEXT_BEGIN"; - g_scriptEvents[277] = "ITEM_TEXT_TRANSLATION"; - g_scriptEvents[278] = "ITEM_TEXT_READY"; - g_scriptEvents[279] = "ITEM_TEXT_CLOSED"; - g_scriptEvents[280] = "GOSSIP_SHOW"; - g_scriptEvents[281] = "GOSSIP_CONFIRM"; - g_scriptEvents[282] = "GOSSIP_CONFIRM_CANCEL"; - g_scriptEvents[283] = "GOSSIP_ENTER_CODE"; - g_scriptEvents[284] = "GOSSIP_CLOSED"; - g_scriptEvents[285] = "QUEST_GREETING"; - g_scriptEvents[286] = "QUEST_DETAIL"; - g_scriptEvents[287] = "QUEST_PROGRESS"; - g_scriptEvents[288] = "QUEST_COMPLETE"; - g_scriptEvents[289] = "QUEST_FINISHED"; - g_scriptEvents[290] = "QUEST_ITEM_UPDATE"; - g_scriptEvents[291] = "TAXIMAP_OPENED"; - g_scriptEvents[292] = "TAXIMAP_CLOSED"; - g_scriptEvents[293] = "QUEST_LOG_UPDATE"; - g_scriptEvents[294] = "TRAINER_SHOW"; - g_scriptEvents[295] = "TRAINER_UPDATE"; - g_scriptEvents[296] = "TRAINER_DESCRIPTION_UPDATE"; - g_scriptEvents[297] = "TRAINER_CLOSED"; - g_scriptEvents[298] = "CVAR_UPDATE"; - g_scriptEvents[299] = "TRADE_SKILL_SHOW"; - g_scriptEvents[300] = "TRADE_SKILL_UPDATE"; - g_scriptEvents[301] = "TRADE_SKILL_CLOSE"; - g_scriptEvents[302] = "MERCHANT_SHOW"; - g_scriptEvents[303] = "MERCHANT_UPDATE"; - g_scriptEvents[304] = "MERCHANT_CLOSED"; - g_scriptEvents[305] = "TRADE_SHOW"; - g_scriptEvents[306] = "TRADE_CLOSED"; - g_scriptEvents[307] = "TRADE_UPDATE"; - g_scriptEvents[308] = "TRADE_ACCEPT_UPDATE"; - g_scriptEvents[309] = "TRADE_TARGET_ITEM_CHANGED"; - g_scriptEvents[310] = "TRADE_PLAYER_ITEM_CHANGED"; - g_scriptEvents[311] = "TRADE_MONEY_CHANGED"; - g_scriptEvents[312] = "PLAYER_TRADE_MONEY"; - g_scriptEvents[313] = "BAG_OPEN"; - g_scriptEvents[314] = "BAG_UPDATE"; - g_scriptEvents[315] = "BAG_CLOSED"; - g_scriptEvents[316] = "BAG_UPDATE_COOLDOWN"; - g_scriptEvents[317] = "LOCALPLAYER_PET_RENAMED"; - g_scriptEvents[318] = "UNIT_ATTACK"; - g_scriptEvents[319] = "UNIT_DEFENSE"; - g_scriptEvents[320] = "PET_ATTACK_START"; - g_scriptEvents[321] = "PET_ATTACK_STOP"; - g_scriptEvents[322] = "UPDATE_MOUSEOVER_UNIT"; - g_scriptEvents[323] = "UNIT_SPELLCAST_SENT"; - g_scriptEvents[324] = "UNIT_SPELLCAST_START"; - g_scriptEvents[325] = "UNIT_SPELLCAST_STOP"; - g_scriptEvents[326] = "UNIT_SPELLCAST_FAILED"; - g_scriptEvents[327] = "UNIT_SPELLCAST_FAILED_QUIET"; - g_scriptEvents[328] = "UNIT_SPELLCAST_INTERRUPTED"; - g_scriptEvents[329] = "UNIT_SPELLCAST_DELAYED"; - g_scriptEvents[330] = "UNIT_SPELLCAST_SUCCEEDED"; - g_scriptEvents[331] = "UNIT_SPELLCAST_CHANNEL_START"; - g_scriptEvents[332] = "UNIT_SPELLCAST_CHANNEL_UPDATE"; - g_scriptEvents[333] = "UNIT_SPELLCAST_CHANNEL_STOP"; - g_scriptEvents[334] = "UNIT_SPELLCAST_INTERRUPTIBLE"; - g_scriptEvents[335] = "UNIT_SPELLCAST_NOT_INTERRUPTIBLE"; - g_scriptEvents[336] = "PLAYER_GUILD_UPDATE"; - g_scriptEvents[337] = "QUEST_ACCEPT_CONFIRM"; - g_scriptEvents[338] = "PLAYERBANKSLOTS_CHANGED"; - g_scriptEvents[339] = "BANKFRAME_OPENED"; - g_scriptEvents[340] = "BANKFRAME_CLOSED"; - g_scriptEvents[341] = "PLAYERBANKBAGSLOTS_CHANGED"; - g_scriptEvents[342] = "FRIENDLIST_UPDATE"; - g_scriptEvents[343] = "IGNORELIST_UPDATE"; - g_scriptEvents[344] = "MUTELIST_UPDATE"; - g_scriptEvents[345] = "PET_BAR_UPDATE"; - g_scriptEvents[346] = "PET_BAR_UPDATE_COOLDOWN"; - g_scriptEvents[347] = "PET_BAR_SHOWGRID"; - g_scriptEvents[348] = "PET_BAR_HIDEGRID"; - g_scriptEvents[349] = "PET_BAR_HIDE"; - g_scriptEvents[350] = "PET_BAR_UPDATE_USABLE"; - g_scriptEvents[351] = "MINIMAP_PING"; - g_scriptEvents[352] = "MIRROR_TIMER_START"; - g_scriptEvents[353] = "MIRROR_TIMER_PAUSE"; - g_scriptEvents[354] = "MIRROR_TIMER_STOP"; - g_scriptEvents[355] = "WORLD_MAP_UPDATE"; - g_scriptEvents[356] = "WORLD_MAP_NAME_UPDATE"; - g_scriptEvents[357] = "AUTOFOLLOW_BEGIN"; - g_scriptEvents[358] = "AUTOFOLLOW_END"; - g_scriptEvents[360] = "CINEMATIC_START"; - g_scriptEvents[361] = "CINEMATIC_STOP"; - g_scriptEvents[362] = "UPDATE_FACTION"; - g_scriptEvents[363] = "CLOSE_WORLD_MAP"; - g_scriptEvents[364] = "OPEN_TABARD_FRAME"; - g_scriptEvents[365] = "CLOSE_TABARD_FRAME"; - g_scriptEvents[366] = "TABARD_CANSAVE_CHANGED"; - g_scriptEvents[367] = "GUILD_REGISTRAR_SHOW"; - g_scriptEvents[368] = "GUILD_REGISTRAR_CLOSED"; - g_scriptEvents[369] = "DUEL_REQUESTED"; - g_scriptEvents[370] = "DUEL_OUTOFBOUNDS"; - g_scriptEvents[371] = "DUEL_INBOUNDS"; - g_scriptEvents[372] = "DUEL_FINISHED"; - g_scriptEvents[373] = "TUTORIAL_TRIGGER"; - g_scriptEvents[374] = "PET_DISMISS_START"; - g_scriptEvents[375] = "UPDATE_BINDINGS"; - g_scriptEvents[376] = "UPDATE_SHAPESHIFT_FORMS"; - g_scriptEvents[377] = "UPDATE_SHAPESHIFT_FORM"; - g_scriptEvents[378] = "UPDATE_SHAPESHIFT_USABLE"; - g_scriptEvents[379] = "UPDATE_SHAPESHIFT_COOLDOWN"; - g_scriptEvents[380] = "WHO_LIST_UPDATE"; - g_scriptEvents[381] = "PETITION_SHOW"; - g_scriptEvents[382] = "PETITION_CLOSED"; - g_scriptEvents[383] = "EXECUTE_CHAT_LINE"; - g_scriptEvents[384] = "UPDATE_MACROS"; - g_scriptEvents[385] = "UPDATE_TICKET"; - g_scriptEvents[386] = "UPDATE_CHAT_WINDOWS"; - g_scriptEvents[387] = "CONFIRM_XP_LOSS"; - g_scriptEvents[388] = "CORPSE_IN_RANGE"; - g_scriptEvents[389] = "CORPSE_IN_INSTANCE"; - g_scriptEvents[390] = "CORPSE_OUT_OF_RANGE"; - g_scriptEvents[391] = "UPDATE_GM_STATUS"; - g_scriptEvents[392] = "PLAYER_UNGHOST"; - g_scriptEvents[393] = "BIND_ENCHANT"; - g_scriptEvents[394] = "REPLACE_ENCHANT"; - g_scriptEvents[395] = "TRADE_REPLACE_ENCHANT"; - g_scriptEvents[396] = "TRADE_POTENTIAL_BIND_ENCHANT"; - g_scriptEvents[397] = "PLAYER_UPDATE_RESTING"; - g_scriptEvents[398] = "UPDATE_EXHAUSTION"; - g_scriptEvents[399] = "PLAYER_FLAGS_CHANGED"; - g_scriptEvents[400] = "GUILD_ROSTER_UPDATE"; - g_scriptEvents[401] = "GM_PLAYER_INFO"; - g_scriptEvents[402] = "MAIL_SHOW"; - g_scriptEvents[403] = "MAIL_CLOSED"; - g_scriptEvents[404] = "SEND_MAIL_MONEY_CHANGED"; - g_scriptEvents[405] = "SEND_MAIL_COD_CHANGED"; - g_scriptEvents[406] = "MAIL_SEND_INFO_UPDATE"; - g_scriptEvents[407] = "MAIL_SEND_SUCCESS"; - g_scriptEvents[408] = "MAIL_INBOX_UPDATE"; - g_scriptEvents[409] = "MAIL_LOCK_SEND_ITEMS"; - g_scriptEvents[410] = "MAIL_UNLOCK_SEND_ITEMS"; - g_scriptEvents[411] = "BATTLEFIELDS_SHOW"; - g_scriptEvents[412] = "BATTLEFIELDS_CLOSED"; - g_scriptEvents[413] = "UPDATE_BATTLEFIELD_STATUS"; - g_scriptEvents[414] = "UPDATE_BATTLEFIELD_SCORE"; - g_scriptEvents[415] = "AUCTION_HOUSE_SHOW"; - g_scriptEvents[416] = "AUCTION_HOUSE_CLOSED"; - g_scriptEvents[417] = "NEW_AUCTION_UPDATE"; - g_scriptEvents[418] = "AUCTION_ITEM_LIST_UPDATE"; - g_scriptEvents[419] = "AUCTION_OWNED_LIST_UPDATE"; - g_scriptEvents[420] = "AUCTION_BIDDER_LIST_UPDATE"; - g_scriptEvents[421] = "PET_UI_UPDATE"; - g_scriptEvents[422] = "PET_UI_CLOSE"; - g_scriptEvents[423] = "ADDON_LOADED"; - g_scriptEvents[424] = "VARIABLES_LOADED"; - g_scriptEvents[425] = "MACRO_ACTION_FORBIDDEN"; - g_scriptEvents[426] = "ADDON_ACTION_FORBIDDEN"; - g_scriptEvents[427] = "MACRO_ACTION_BLOCKED"; - g_scriptEvents[428] = "ADDON_ACTION_BLOCKED"; - g_scriptEvents[429] = "START_AUTOREPEAT_SPELL"; - g_scriptEvents[430] = "STOP_AUTOREPEAT_SPELL"; - g_scriptEvents[431] = "PET_STABLE_SHOW"; - g_scriptEvents[432] = "PET_STABLE_UPDATE"; - g_scriptEvents[433] = "PET_STABLE_UPDATE_PAPERDOLL"; - g_scriptEvents[434] = "PET_STABLE_CLOSED"; - g_scriptEvents[435] = "RAID_ROSTER_UPDATE"; - g_scriptEvents[436] = "UPDATE_PENDING_MAIL"; - g_scriptEvents[437] = "UPDATE_INVENTORY_ALERTS"; - g_scriptEvents[438] = "UPDATE_INVENTORY_DURABILITY"; - g_scriptEvents[439] = "UPDATE_TRADESKILL_RECAST"; - g_scriptEvents[440] = "OPEN_MASTER_LOOT_LIST"; - g_scriptEvents[441] = "UPDATE_MASTER_LOOT_LIST"; - g_scriptEvents[442] = "START_LOOT_ROLL"; - g_scriptEvents[443] = "CANCEL_LOOT_ROLL"; - g_scriptEvents[444] = "CONFIRM_LOOT_ROLL"; - g_scriptEvents[445] = "CONFIRM_DISENCHANT_ROLL"; - g_scriptEvents[446] = "INSTANCE_BOOT_START"; - g_scriptEvents[447] = "INSTANCE_BOOT_STOP"; - g_scriptEvents[448] = "LEARNED_SPELL_IN_TAB"; - g_scriptEvents[449] = "DISPLAY_SIZE_CHANGED"; - g_scriptEvents[450] = "CONFIRM_TALENT_WIPE"; - g_scriptEvents[451] = "CONFIRM_BINDER"; - g_scriptEvents[452] = "MAIL_FAILED"; - g_scriptEvents[453] = "CLOSE_INBOX_ITEM"; - g_scriptEvents[454] = "CONFIRM_SUMMON"; - g_scriptEvents[455] = "CANCEL_SUMMON"; - g_scriptEvents[456] = "BILLING_NAG_DIALOG"; - g_scriptEvents[457] = "IGR_BILLING_NAG_DIALOG"; - g_scriptEvents[458] = "PLAYER_SKINNED"; - g_scriptEvents[459] = "TABARD_SAVE_PENDING"; - g_scriptEvents[460] = "UNIT_QUEST_LOG_CHANGED"; - g_scriptEvents[461] = "PLAYER_PVP_KILLS_CHANGED"; - g_scriptEvents[462] = "PLAYER_PVP_RANK_CHANGED"; - g_scriptEvents[463] = "INSPECT_HONOR_UPDATE"; - g_scriptEvents[464] = "UPDATE_WORLD_STATES"; - g_scriptEvents[465] = "AREA_SPIRIT_HEALER_IN_RANGE"; - g_scriptEvents[466] = "AREA_SPIRIT_HEALER_OUT_OF_RANGE"; - g_scriptEvents[467] = "PLAYTIME_CHANGED"; - g_scriptEvents[468] = "UPDATE_LFG_TYPES"; - g_scriptEvents[469] = "UPDATE_LFG_LIST"; - g_scriptEvents[470] = "UPDATE_LFG_LIST_INCREMENTAL"; - g_scriptEvents[471] = "START_MINIGAME"; - g_scriptEvents[472] = "MINIGAME_UPDATE"; - g_scriptEvents[473] = "READY_CHECK"; - g_scriptEvents[474] = "READY_CHECK_CONFIRM"; - g_scriptEvents[475] = "READY_CHECK_FINISHED"; - g_scriptEvents[476] = "RAID_TARGET_UPDATE"; - g_scriptEvents[477] = "GMSURVEY_DISPLAY"; - g_scriptEvents[478] = "UPDATE_INSTANCE_INFO"; - g_scriptEvents[479] = "SOCKET_INFO_UPDATE"; - g_scriptEvents[480] = "SOCKET_INFO_CLOSE"; - g_scriptEvents[481] = "PETITION_VENDOR_SHOW"; - g_scriptEvents[482] = "PETITION_VENDOR_CLOSED"; - g_scriptEvents[483] = "PETITION_VENDOR_UPDATE"; - g_scriptEvents[484] = "COMBAT_TEXT_UPDATE"; - g_scriptEvents[485] = "QUEST_WATCH_UPDATE"; - g_scriptEvents[486] = "KNOWLEDGE_BASE_SETUP_LOAD_SUCCESS"; - g_scriptEvents[487] = "KNOWLEDGE_BASE_SETUP_LOAD_FAILURE"; - g_scriptEvents[488] = "KNOWLEDGE_BASE_QUERY_LOAD_SUCCESS"; - g_scriptEvents[489] = "KNOWLEDGE_BASE_QUERY_LOAD_FAILURE"; - g_scriptEvents[490] = "KNOWLEDGE_BASE_ARTICLE_LOAD_SUCCESS"; - g_scriptEvents[491] = "KNOWLEDGE_BASE_ARTICLE_LOAD_FAILURE"; - g_scriptEvents[492] = "KNOWLEDGE_BASE_SYSTEM_MOTD_UPDATED"; - g_scriptEvents[493] = "KNOWLEDGE_BASE_SERVER_MESSAGE"; - g_scriptEvents[494] = "ARENA_TEAM_UPDATE"; - g_scriptEvents[495] = "ARENA_TEAM_ROSTER_UPDATE"; - g_scriptEvents[496] = "ARENA_TEAM_INVITE_REQUEST"; - g_scriptEvents[497] = "HONOR_CURRENCY_UPDATE"; - g_scriptEvents[498] = "KNOWN_TITLES_UPDATE"; - g_scriptEvents[499] = "NEW_TITLE_EARNED"; - g_scriptEvents[500] = "OLD_TITLE_LOST"; - g_scriptEvents[501] = "LFG_UPDATE"; - g_scriptEvents[502] = "LFG_PROPOSAL_UPDATE"; - g_scriptEvents[503] = "LFG_PROPOSAL_SHOW"; - g_scriptEvents[504] = "LFG_PROPOSAL_FAILED"; - g_scriptEvents[505] = "LFG_PROPOSAL_SUCCEEDED"; - g_scriptEvents[506] = "LFG_ROLE_UPDATE"; - g_scriptEvents[507] = "LFG_ROLE_CHECK_UPDATE"; - g_scriptEvents[508] = "LFG_ROLE_CHECK_SHOW"; - g_scriptEvents[509] = "LFG_ROLE_CHECK_HIDE"; - g_scriptEvents[510] = "LFG_ROLE_CHECK_ROLE_CHOSEN"; - g_scriptEvents[511] = "LFG_QUEUE_STATUS_UPDATE"; - g_scriptEvents[512] = "LFG_BOOT_PROPOSAL_UPDATE"; - g_scriptEvents[513] = "LFG_LOCK_INFO_RECEIVED"; - g_scriptEvents[514] = "LFG_UPDATE_RANDOM_INFO"; - g_scriptEvents[515] = "LFG_OFFER_CONTINUE"; - g_scriptEvents[516] = "LFG_OPEN_FROM_GOSSIP"; - g_scriptEvents[517] = "LFG_COMPLETION_REWARD"; - g_scriptEvents[518] = "PARTY_LFG_RESTRICTED"; - g_scriptEvents[519] = "PLAYER_ROLES_ASSIGNED"; - g_scriptEvents[520] = "COMBAT_RATING_UPDATE"; - g_scriptEvents[521] = "MODIFIER_STATE_CHANGED"; - g_scriptEvents[522] = "UPDATE_STEALTH"; - g_scriptEvents[523] = "ENABLE_TAXI_BENCHMARK"; - g_scriptEvents[524] = "DISABLE_TAXI_BENCHMARK"; - g_scriptEvents[525] = "VOICE_START"; - g_scriptEvents[526] = "VOICE_STOP"; - g_scriptEvents[527] = "VOICE_STATUS_UPDATE"; - g_scriptEvents[528] = "VOICE_CHANNEL_STATUS_UPDATE"; - g_scriptEvents[529] = "UPDATE_FLOATING_CHAT_WINDOWS"; - g_scriptEvents[530] = "RAID_INSTANCE_WELCOME"; - g_scriptEvents[531] = "MOVIE_RECORDING_PROGRESS"; - g_scriptEvents[532] = "MOVIE_COMPRESSING_PROGRESS"; - g_scriptEvents[533] = "MOVIE_UNCOMPRESSED_MOVIE"; - g_scriptEvents[534] = "VOICE_PUSH_TO_TALK_START"; - g_scriptEvents[535] = "VOICE_PUSH_TO_TALK_STOP"; - g_scriptEvents[536] = "GUILDBANKFRAME_OPENED"; - g_scriptEvents[537] = "GUILDBANKFRAME_CLOSED"; - g_scriptEvents[538] = "GUILDBANKBAGSLOTS_CHANGED"; - g_scriptEvents[539] = "GUILDBANK_ITEM_LOCK_CHANGED"; - g_scriptEvents[540] = "GUILDBANK_UPDATE_TABS"; - g_scriptEvents[541] = "GUILDBANK_UPDATE_MONEY"; - g_scriptEvents[542] = "GUILDBANKLOG_UPDATE"; - g_scriptEvents[543] = "GUILDBANK_UPDATE_WITHDRAWMONEY"; - g_scriptEvents[544] = "GUILDBANK_UPDATE_TEXT"; - g_scriptEvents[545] = "GUILDBANK_TEXT_CHANGED"; - g_scriptEvents[546] = "CHANNEL_UI_UPDATE"; - g_scriptEvents[547] = "CHANNEL_COUNT_UPDATE"; - g_scriptEvents[548] = "CHANNEL_ROSTER_UPDATE"; - g_scriptEvents[549] = "CHANNEL_VOICE_UPDATE"; - g_scriptEvents[550] = "CHANNEL_INVITE_REQUEST"; - g_scriptEvents[551] = "CHANNEL_PASSWORD_REQUEST"; - g_scriptEvents[552] = "CHANNEL_FLAGS_UPDATED"; - g_scriptEvents[553] = "VOICE_SESSIONS_UPDATE"; - g_scriptEvents[554] = "VOICE_CHAT_ENABLED_UPDATE"; - g_scriptEvents[555] = "VOICE_LEFT_SESSION"; - g_scriptEvents[556] = "INSPECT_TALENT_READY"; - g_scriptEvents[557] = "VOICE_SELF_MUTE"; - g_scriptEvents[558] = "VOICE_PLATE_START"; - g_scriptEvents[559] = "VOICE_PLATE_STOP"; - g_scriptEvents[560] = "ARENA_SEASON_WORLD_STATE"; - g_scriptEvents[561] = "GUILD_EVENT_LOG_UPDATE"; - g_scriptEvents[562] = "GUILDTABARD_UPDATE"; - g_scriptEvents[563] = "SOUND_DEVICE_UPDATE"; - g_scriptEvents[564] = "COMMENTATOR_MAP_UPDATE"; - g_scriptEvents[565] = "COMMENTATOR_ENTER_WORLD"; - g_scriptEvents[566] = "COMBAT_LOG_EVENT"; - g_scriptEvents[567] = "COMBAT_LOG_EVENT_UNFILTERED"; - g_scriptEvents[568] = "COMMENTATOR_PLAYER_UPDATE"; - g_scriptEvents[569] = "PLAYER_ENTERING_BATTLEGROUND"; - g_scriptEvents[570] = "BARBER_SHOP_OPEN"; - g_scriptEvents[571] = "BARBER_SHOP_CLOSE"; - g_scriptEvents[572] = "BARBER_SHOP_SUCCESS"; - g_scriptEvents[573] = "BARBER_SHOP_APPEARANCE_APPLIED"; - g_scriptEvents[574] = "CALENDAR_UPDATE_INVITE_LIST"; - g_scriptEvents[575] = "CALENDAR_UPDATE_EVENT_LIST"; - g_scriptEvents[576] = "CALENDAR_NEW_EVENT"; - g_scriptEvents[577] = "CALENDAR_OPEN_EVENT"; - g_scriptEvents[578] = "CALENDAR_CLOSE_EVENT"; - g_scriptEvents[579] = "CALENDAR_UPDATE_EVENT"; - g_scriptEvents[580] = "CALENDAR_UPDATE_PENDING_INVITES"; - g_scriptEvents[581] = "CALENDAR_EVENT_ALARM"; - g_scriptEvents[582] = "CALENDAR_UPDATE_ERROR"; - g_scriptEvents[583] = "CALENDAR_ACTION_PENDING"; - g_scriptEvents[584] = "VEHICLE_ANGLE_SHOW"; - g_scriptEvents[585] = "VEHICLE_ANGLE_UPDATE"; - g_scriptEvents[586] = "VEHICLE_POWER_SHOW"; - g_scriptEvents[587] = "UNIT_ENTERING_VEHICLE"; - g_scriptEvents[588] = "UNIT_ENTERED_VEHICLE"; - g_scriptEvents[589] = "UNIT_EXITING_VEHICLE"; - g_scriptEvents[590] = "UNIT_EXITED_VEHICLE"; - g_scriptEvents[591] = "VEHICLE_PASSENGERS_CHANGED"; - g_scriptEvents[592] = "PLAYER_GAINS_VEHICLE_DATA"; - g_scriptEvents[593] = "PLAYER_LOSES_VEHICLE_DATA"; - g_scriptEvents[594] = "PET_FORCE_NAME_DECLENSION"; - g_scriptEvents[595] = "LEVEL_GRANT_PROPOSED"; - g_scriptEvents[596] = "SYNCHRONIZE_SETTINGS"; - g_scriptEvents[597] = "PLAY_MOVIE"; - g_scriptEvents[598] = "RUNE_POWER_UPDATE"; - g_scriptEvents[599] = "RUNE_TYPE_UPDATE"; - g_scriptEvents[600] = "ACHIEVEMENT_EARNED"; - g_scriptEvents[601] = "CRITERIA_UPDATE"; - g_scriptEvents[602] = "RECEIVED_ACHIEVEMENT_LIST"; - g_scriptEvents[603] = "PET_RENAMEABLE"; - g_scriptEvents[604] = "KNOWN_CURRENCY_TYPES_UPDATE"; - g_scriptEvents[605] = "CURRENCY_DISPLAY_UPDATE"; - g_scriptEvents[606] = "COMPANION_LEARNED"; - g_scriptEvents[607] = "COMPANION_UNLEARNED"; - g_scriptEvents[608] = "COMPANION_UPDATE"; - g_scriptEvents[609] = "UNIT_THREAT_LIST_UPDATE"; - g_scriptEvents[610] = "UNIT_THREAT_SITUATION_UPDATE"; - g_scriptEvents[611] = "GLYPH_ADDED"; - g_scriptEvents[612] = "GLYPH_REMOVED"; - g_scriptEvents[613] = "GLYPH_UPDATED"; - g_scriptEvents[614] = "GLYPH_ENABLED"; - g_scriptEvents[615] = "GLYPH_DISABLED"; - g_scriptEvents[616] = "USE_GLYPH"; - g_scriptEvents[617] = "TRACKED_ACHIEVEMENT_UPDATE"; - g_scriptEvents[618] = "ARENA_OPPONENT_UPDATE"; - g_scriptEvents[619] = "INSPECT_ACHIEVEMENT_READY"; - g_scriptEvents[620] = "RAISED_AS_GHOUL"; - g_scriptEvents[621] = "PARTY_CONVERTED_TO_RAID"; - g_scriptEvents[622] = "PVPQUEUE_ANYWHERE_SHOW"; - g_scriptEvents[623] = "PVPQUEUE_ANYWHERE_UPDATE_AVAILABLE"; - g_scriptEvents[624] = "QUEST_ACCEPTED"; - g_scriptEvents[625] = "PLAYER_TALENT_UPDATE"; - g_scriptEvents[626] = "ACTIVE_TALENT_GROUP_CHANGED"; - g_scriptEvents[627] = "PET_TALENT_UPDATE"; - g_scriptEvents[628] = "PREVIEW_TALENT_POINTS_CHANGED"; - g_scriptEvents[629] = "PREVIEW_PET_TALENT_POINTS_CHANGED"; - g_scriptEvents[630] = "WEAR_EQUIPMENT_SET"; - g_scriptEvents[631] = "EQUIPMENT_SETS_CHANGED"; - g_scriptEvents[632] = "INSTANCE_LOCK_START"; - g_scriptEvents[633] = "INSTANCE_LOCK_STOP"; - g_scriptEvents[634] = "PLAYER_EQUIPMENT_CHANGED"; - g_scriptEvents[635] = "ITEM_LOCKED"; - g_scriptEvents[636] = "ITEM_UNLOCKED"; - g_scriptEvents[637] = "TRADE_SKILL_FILTER_UPDATE"; - g_scriptEvents[638] = "EQUIPMENT_SWAP_PENDING"; - g_scriptEvents[639] = "EQUIPMENT_SWAP_FINISHED"; - g_scriptEvents[640] = "NPC_PVPQUEUE_ANYWHERE"; - g_scriptEvents[641] = "UPDATE_MULTI_CAST_ACTIONBAR"; - g_scriptEvents[642] = "ENABLE_XP_GAIN"; - g_scriptEvents[643] = "DISABLE_XP_GAIN"; - g_scriptEvents[644] = "BATTLEFIELD_MGR_ENTRY_INVITE"; - g_scriptEvents[645] = "BATTLEFIELD_MGR_ENTERED"; - g_scriptEvents[646] = "BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE"; - g_scriptEvents[647] = "BATTLEFIELD_MGR_EJECT_PENDING"; - g_scriptEvents[648] = "BATTLEFIELD_MGR_EJECTED"; - g_scriptEvents[649] = "BATTLEFIELD_MGR_QUEUE_INVITE"; - g_scriptEvents[650] = "BATTLEFIELD_MGR_STATE_CHANGE"; - g_scriptEvents[651] = "WORLD_STATE_UI_TIMER_UPDATE"; - g_scriptEvents[652] = "END_REFUND"; - g_scriptEvents[653] = "END_BOUND_TRADEABLE"; - g_scriptEvents[654] = "UPDATE_CHAT_COLOR_NAME_BY_CLASS"; - g_scriptEvents[655] = "GMRESPONSE_RECEIVED"; - g_scriptEvents[656] = "VEHICLE_UPDATE"; - g_scriptEvents[657] = "WOW_MOUSE_NOT_FOUND"; - g_scriptEvents[659] = "MAIL_SUCCESS"; - g_scriptEvents[660] = "TALENTS_INVOLUNTARILY_RESET"; - g_scriptEvents[661] = "INSTANCE_ENCOUNTER_ENGAGE_UNIT"; - g_scriptEvents[662] = "QUEST_QUERY_COMPLETE"; - g_scriptEvents[663] = "QUEST_POI_UPDATE"; - g_scriptEvents[664] = "PLAYER_DIFFICULTY_CHANGED"; - g_scriptEvents[665] = "CHAT_MSG_PARTY_LEADER"; - g_scriptEvents[666] = "VOTE_KICK_REASON_NEEDED"; - g_scriptEvents[667] = "ENABLE_LOW_LEVEL_RAID"; - g_scriptEvents[668] = "DISABLE_LOW_LEVEL_RAID"; - g_scriptEvents[669] = "CHAT_MSG_TARGETICONS"; - g_scriptEvents[670] = "AUCTION_HOUSE_DISABLED"; - g_scriptEvents[671] = "AUCTION_MULTISELL_START"; - g_scriptEvents[672] = "AUCTION_MULTISELL_UPDATE"; - g_scriptEvents[673] = "AUCTION_MULTISELL_FAILURE"; - g_scriptEvents[674] = "PET_SPELL_POWER_UPDATE"; - g_scriptEvents[675] = "BN_CONNECTED"; - g_scriptEvents[676] = "BN_DISCONNECTED"; - g_scriptEvents[677] = "BN_SELF_ONLINE"; - g_scriptEvents[678] = "BN_SELF_OFFLINE"; - g_scriptEvents[679] = "BN_FRIEND_LIST_SIZE_CHANGED"; - g_scriptEvents[680] = "BN_FRIEND_INVITE_LIST_INITIALIZED"; - g_scriptEvents[681] = "BN_FRIEND_INVITE_SEND_RESULT"; - g_scriptEvents[682] = "BN_FRIEND_INVITE_ADDED"; - g_scriptEvents[683] = "BN_FRIEND_INVITE_REMOVED"; - g_scriptEvents[684] = "BN_FRIEND_INFO_CHANGED"; - g_scriptEvents[685] = "BN_CUSTOM_MESSAGE_CHANGED"; - g_scriptEvents[686] = "BN_CUSTOM_MESSAGE_LOADED"; - g_scriptEvents[687] = "CHAT_MSG_BN_WHISPER"; - g_scriptEvents[688] = "CHAT_MSG_BN_WHISPER_INFORM"; - g_scriptEvents[689] = "BN_CHAT_WHISPER_UNDELIVERABLE"; - g_scriptEvents[690] = "BN_CHAT_CHANNEL_JOINED"; - g_scriptEvents[691] = "BN_CHAT_CHANNEL_LEFT"; - g_scriptEvents[692] = "BN_CHAT_CHANNEL_CLOSED"; - g_scriptEvents[693] = "CHAT_MSG_BN_CONVERSATION"; - g_scriptEvents[694] = "CHAT_MSG_BN_CONVERSATION_NOTICE"; - g_scriptEvents[695] = "CHAT_MSG_BN_CONVERSATION_LIST"; - g_scriptEvents[696] = "BN_CHAT_CHANNEL_MESSAGE_UNDELIVERABLE"; - g_scriptEvents[697] = "BN_CHAT_CHANNEL_MESSAGE_BLOCKED"; - g_scriptEvents[698] = "BN_CHAT_CHANNEL_MEMBER_JOINED"; - g_scriptEvents[699] = "BN_CHAT_CHANNEL_MEMBER_LEFT"; - g_scriptEvents[700] = "BN_CHAT_CHANNEL_MEMBER_UPDATED"; - g_scriptEvents[701] = "BN_CHAT_CHANNEL_CREATE_SUCCEEDED"; - g_scriptEvents[702] = "BN_CHAT_CHANNEL_CREATE_FAILED"; - g_scriptEvents[703] = "BN_CHAT_CHANNEL_INVITE_SUCCEEDED"; - g_scriptEvents[704] = "BN_CHAT_CHANNEL_INVITE_FAILED"; - g_scriptEvents[705] = "BN_BLOCK_LIST_UPDATED"; - g_scriptEvents[706] = "BN_SYSTEM_MESSAGE"; - g_scriptEvents[707] = "BN_REQUEST_FOF_SUCCEEDED"; - g_scriptEvents[708] = "BN_REQUEST_FOF_FAILED"; - g_scriptEvents[709] = "BN_NEW_PRESENCE"; - g_scriptEvents[710] = "BN_TOON_NAME_UPDATED"; - g_scriptEvents[711] = "BN_FRIEND_ACCOUNT_ONLINE"; - g_scriptEvents[712] = "BN_FRIEND_ACCOUNT_OFFLINE"; - g_scriptEvents[713] = "BN_FRIEND_TOON_ONLINE"; - g_scriptEvents[714] = "BN_FRIEND_TOON_OFFLINE"; - g_scriptEvents[715] = "BN_MATURE_LANGUAGE_FILTER"; - g_scriptEvents[716] = "COMMENTATOR_SKIRMISH_QUEUE_REQUEST"; - g_scriptEvents[717] = "COMMENTATOR_SKIRMISH_MODE_REQUEST"; - g_scriptEvents[718] = "CHAT_MSG_BN_INLINE_TOAST_ALERT"; - g_scriptEvents[719] = "CHAT_MSG_BN_INLINE_TOAST_BROADCAST"; - g_scriptEvents[720] = "CHAT_MSG_BN_INLINE_TOAST_BROADCAST_INFORM"; - g_scriptEvents[721] = "CHAT_MSG_BN_INLINE_TOAST_CONVERSATION"; -} diff --git a/src/ui/FrameScript.hpp b/src/ui/FrameScript.hpp index e2e4c83..3eff364 100644 --- a/src/ui/FrameScript.hpp +++ b/src/ui/FrameScript.hpp @@ -103,6 +103,4 @@ void FrameScript_UnregisterFunction(const char* name); void FrameScript_UnregisterScriptEvent(FrameScript_Object* object, FrameScript_EventObject* event); -void ScriptEventsInitialize(); - #endif diff --git a/src/ui/Game.hpp b/src/ui/Game.hpp index e4431b0..82eb4a9 100644 --- a/src/ui/Game.hpp +++ b/src/ui/Game.hpp @@ -3,5 +3,6 @@ #include "ui/game/CGGameUI.hpp" #include "ui/game/CGPetInfo.hpp" +#include "ui/game/ScriptEvents.hpp" #endif diff --git a/src/ui/game/ScriptEvents.cpp b/src/ui/game/ScriptEvents.cpp index 7aa33f2..50a62fb 100644 --- a/src/ui/game/ScriptEvents.cpp +++ b/src/ui/game/ScriptEvents.cpp @@ -947,3 +947,653 @@ void ScriptEventsRegisterFunctions() { FrameScript_RegisterFunction(func.name, func.method); } } + +void ScriptEventsInitialize() { + g_scriptEvents[0] = "UNIT_PET"; + g_scriptEvents[2] = "UNIT_PET"; + g_scriptEvents[12] = "UNIT_TARGET"; + g_scriptEvents[17] = "UNIT_DISPLAYPOWER"; + g_scriptEvents[18] = "UNIT_HEALTH"; + g_scriptEvents[19] = "UNIT_MANA"; + g_scriptEvents[20] = "UNIT_RAGE"; + g_scriptEvents[21] = "UNIT_FOCUS"; + g_scriptEvents[22] = "UNIT_ENERGY"; + g_scriptEvents[23] = "UNIT_HAPPINESS"; + g_scriptEvents[25] = "UNIT_RUNIC_POWER"; + g_scriptEvents[26] = "UNIT_MAXHEALTH"; + g_scriptEvents[27] = "UNIT_MAXMANA"; + g_scriptEvents[28] = "UNIT_MAXRAGE"; + g_scriptEvents[29] = "UNIT_MAXFOCUS"; + g_scriptEvents[30] = "UNIT_MAXENERGY"; + g_scriptEvents[31] = "UNIT_MAXHAPPINESS"; + g_scriptEvents[33] = "UNIT_MAXRUNIC_POWER"; + g_scriptEvents[48] = "UNIT_LEVEL"; + g_scriptEvents[49] = "UNIT_FACTION"; + g_scriptEvents[53] = "UNIT_FLAGS"; + g_scriptEvents[54] = "UNIT_FLAGS"; + g_scriptEvents[56] = "UNIT_ATTACK_SPEED"; + g_scriptEvents[57] = "UNIT_ATTACK_SPEED"; + g_scriptEvents[58] = "UNIT_RANGEDDAMAGE"; + g_scriptEvents[64] = "UNIT_DAMAGE"; + g_scriptEvents[65] = "UNIT_DAMAGE"; + g_scriptEvents[66] = "UNIT_DAMAGE"; + g_scriptEvents[67] = "UNIT_DAMAGE"; + g_scriptEvents[71] = "UNIT_PET_EXPERIENCE"; + g_scriptEvents[72] = "UNIT_PET_EXPERIENCE"; + g_scriptEvents[73] = "UNIT_DYNAMIC_FLAGS"; + g_scriptEvents[78] = "UNIT_STATS"; + g_scriptEvents[79] = "UNIT_STATS"; + g_scriptEvents[80] = "UNIT_STATS"; + g_scriptEvents[81] = "UNIT_STATS"; + g_scriptEvents[82] = "UNIT_STATS"; + g_scriptEvents[93] = "UNIT_RESISTANCES"; + g_scriptEvents[94] = "UNIT_RESISTANCES"; + g_scriptEvents[95] = "UNIT_RESISTANCES"; + g_scriptEvents[96] = "UNIT_RESISTANCES"; + g_scriptEvents[97] = "UNIT_RESISTANCES"; + g_scriptEvents[98] = "UNIT_RESISTANCES"; + g_scriptEvents[99] = "UNIT_RESISTANCES"; + g_scriptEvents[100] = "UNIT_RESISTANCES"; + g_scriptEvents[101] = "UNIT_RESISTANCES"; + g_scriptEvents[102] = "UNIT_RESISTANCES"; + g_scriptEvents[103] = "UNIT_RESISTANCES"; + g_scriptEvents[104] = "UNIT_RESISTANCES"; + g_scriptEvents[105] = "UNIT_RESISTANCES"; + g_scriptEvents[106] = "UNIT_RESISTANCES"; + g_scriptEvents[107] = "UNIT_RESISTANCES"; + g_scriptEvents[108] = "UNIT_RESISTANCES"; + g_scriptEvents[109] = "UNIT_RESISTANCES"; + g_scriptEvents[110] = "UNIT_RESISTANCES"; + g_scriptEvents[111] = "UNIT_RESISTANCES"; + g_scriptEvents[112] = "UNIT_RESISTANCES"; + g_scriptEvents[113] = "UNIT_RESISTANCES"; + g_scriptEvents[117] = "UNIT_ATTACK_POWER"; + g_scriptEvents[118] = "UNIT_ATTACK_POWER"; + g_scriptEvents[119] = "UNIT_ATTACK_POWER"; + g_scriptEvents[120] = "UNIT_RANGED_ATTACK_POWER"; + g_scriptEvents[121] = "UNIT_RANGED_ATTACK_POWER"; + g_scriptEvents[122] = "UNIT_RANGED_ATTACK_POWER"; + g_scriptEvents[123] = "UNIT_RANGEDDAMAGE"; + g_scriptEvents[124] = "UNIT_RANGEDDAMAGE"; + g_scriptEvents[125] = "UNIT_MANA"; + g_scriptEvents[132] = "UNIT_MANA"; + g_scriptEvents[139] = "UNIT_STATS"; + g_scriptEvents[142] = "UNIT_AURA"; + g_scriptEvents[143] = "UNIT_COMBAT"; + g_scriptEvents[144] = "UNIT_NAME_UPDATE"; + g_scriptEvents[145] = "UNIT_PORTRAIT_UPDATE"; + g_scriptEvents[146] = "UNIT_MODEL_CHANGED"; + g_scriptEvents[147] = "UNIT_INVENTORY_CHANGED"; + g_scriptEvents[148] = "UNIT_CLASSIFICATION_CHANGED"; + g_scriptEvents[149] = "UNIT_COMBO_POINTS"; + g_scriptEvents[150] = "ITEM_LOCK_CHANGED"; + g_scriptEvents[151] = "PLAYER_XP_UPDATE"; + g_scriptEvents[152] = "PLAYER_REGEN_DISABLED"; + g_scriptEvents[153] = "PLAYER_REGEN_ENABLED"; + g_scriptEvents[154] = "PLAYER_AURAS_CHANGED"; + g_scriptEvents[155] = "PLAYER_ENTER_COMBAT"; + g_scriptEvents[156] = "PLAYER_LEAVE_COMBAT"; + g_scriptEvents[157] = "PLAYER_TARGET_CHANGED"; + g_scriptEvents[158] = "PLAYER_FOCUS_CHANGED"; + g_scriptEvents[159] = "PLAYER_CONTROL_LOST"; + g_scriptEvents[160] = "PLAYER_CONTROL_GAINED"; + g_scriptEvents[161] = "PLAYER_FARSIGHT_FOCUS_CHANGED"; + g_scriptEvents[162] = "PLAYER_LEVEL_UP"; + g_scriptEvents[163] = "PLAYER_MONEY"; + g_scriptEvents[164] = "PLAYER_DAMAGE_DONE_MODS"; + g_scriptEvents[165] = "PLAYER_TOTEM_UPDATE"; + g_scriptEvents[166] = "ZONE_CHANGED"; + g_scriptEvents[167] = "ZONE_CHANGED_INDOORS"; + g_scriptEvents[168] = "ZONE_CHANGED_NEW_AREA"; + g_scriptEvents[169] = "MINIMAP_UPDATE_ZOOM"; + g_scriptEvents[170] = "MINIMAP_UPDATE_TRACKING"; + g_scriptEvents[171] = "SCREENSHOT_SUCCEEDED"; + g_scriptEvents[172] = "SCREENSHOT_FAILED"; + g_scriptEvents[173] = "ACTIONBAR_SHOWGRID"; + g_scriptEvents[174] = "ACTIONBAR_HIDEGRID"; + g_scriptEvents[175] = "ACTIONBAR_PAGE_CHANGED"; + g_scriptEvents[176] = "ACTIONBAR_SLOT_CHANGED"; + g_scriptEvents[177] = "ACTIONBAR_UPDATE_STATE"; + g_scriptEvents[178] = "ACTIONBAR_UPDATE_USABLE"; + g_scriptEvents[179] = "ACTIONBAR_UPDATE_COOLDOWN"; + g_scriptEvents[180] = "UPDATE_BONUS_ACTIONBAR"; + g_scriptEvents[181] = "PARTY_MEMBERS_CHANGED"; + g_scriptEvents[182] = "PARTY_LEADER_CHANGED"; + g_scriptEvents[183] = "PARTY_MEMBER_ENABLE"; + g_scriptEvents[184] = "PARTY_MEMBER_DISABLE"; + g_scriptEvents[185] = "PARTY_LOOT_METHOD_CHANGED"; + g_scriptEvents[186] = "SYSMSG"; + g_scriptEvents[187] = "UI_ERROR_MESSAGE"; + g_scriptEvents[188] = "UI_INFO_MESSAGE"; + g_scriptEvents[189] = "UPDATE_CHAT_COLOR"; + g_scriptEvents[190] = "CHAT_MSG_ADDON"; + g_scriptEvents[191] = "CHAT_MSG_SYSTEM"; + g_scriptEvents[192] = "CHAT_MSG_SAY"; + g_scriptEvents[193] = "CHAT_MSG_PARTY"; + g_scriptEvents[194] = "CHAT_MSG_RAID"; + g_scriptEvents[195] = "CHAT_MSG_GUILD"; + g_scriptEvents[196] = "CHAT_MSG_OFFICER"; + g_scriptEvents[197] = "CHAT_MSG_YELL"; + g_scriptEvents[198] = "CHAT_MSG_WHISPER"; + g_scriptEvents[199] = "CHAT_MSG_WHISPER_INFORM"; + g_scriptEvents[200] = "CHAT_MSG_EMOTE"; + g_scriptEvents[201] = "CHAT_MSG_TEXT_EMOTE"; + g_scriptEvents[202] = "CHAT_MSG_MONSTER_SAY"; + g_scriptEvents[203] = "CHAT_MSG_MONSTER_PARTY"; + g_scriptEvents[204] = "CHAT_MSG_MONSTER_YELL"; + g_scriptEvents[205] = "CHAT_MSG_MONSTER_WHISPER"; + g_scriptEvents[206] = "CHAT_MSG_MONSTER_EMOTE"; + g_scriptEvents[207] = "CHAT_MSG_CHANNEL"; + g_scriptEvents[208] = "CHAT_MSG_CHANNEL_JOIN"; + g_scriptEvents[209] = "CHAT_MSG_CHANNEL_LEAVE"; + g_scriptEvents[210] = "CHAT_MSG_CHANNEL_LIST"; + g_scriptEvents[211] = "CHAT_MSG_CHANNEL_NOTICE"; + g_scriptEvents[212] = "CHAT_MSG_CHANNEL_NOTICE_USER"; + g_scriptEvents[213] = "CHAT_MSG_AFK"; + g_scriptEvents[214] = "CHAT_MSG_DND"; + g_scriptEvents[215] = "CHAT_MSG_IGNORED"; + g_scriptEvents[216] = "CHAT_MSG_SKILL"; + g_scriptEvents[217] = "CHAT_MSG_LOOT"; + g_scriptEvents[218] = "CHAT_MSG_MONEY"; + g_scriptEvents[219] = "CHAT_MSG_OPENING"; + g_scriptEvents[220] = "CHAT_MSG_TRADESKILLS"; + g_scriptEvents[221] = "CHAT_MSG_PET_INFO"; + g_scriptEvents[222] = "CHAT_MSG_COMBAT_MISC_INFO"; + g_scriptEvents[223] = "CHAT_MSG_COMBAT_XP_GAIN"; + g_scriptEvents[224] = "CHAT_MSG_COMBAT_HONOR_GAIN"; + g_scriptEvents[225] = "CHAT_MSG_COMBAT_FACTION_CHANGE"; + g_scriptEvents[226] = "CHAT_MSG_BG_SYSTEM_NEUTRAL"; + g_scriptEvents[227] = "CHAT_MSG_BG_SYSTEM_ALLIANCE"; + g_scriptEvents[228] = "CHAT_MSG_BG_SYSTEM_HORDE"; + g_scriptEvents[229] = "CHAT_MSG_RAID_LEADER"; + g_scriptEvents[230] = "CHAT_MSG_RAID_WARNING"; + g_scriptEvents[231] = "CHAT_MSG_RAID_BOSS_WHISPER"; + g_scriptEvents[232] = "CHAT_MSG_RAID_BOSS_EMOTE"; + g_scriptEvents[233] = "CHAT_MSG_FILTERED"; + g_scriptEvents[234] = "CHAT_MSG_BATTLEGROUND"; + g_scriptEvents[235] = "CHAT_MSG_BATTLEGROUND_LEADER"; + g_scriptEvents[236] = "CHAT_MSG_RESTRICTED"; + g_scriptEvents[237] = ""; + g_scriptEvents[238] = "CHAT_MSG_ACHIEVEMENT"; + g_scriptEvents[239] = "CHAT_MSG_GUILD_ACHIEVEMENT"; + g_scriptEvents[240] = "LANGUAGE_LIST_CHANGED"; + g_scriptEvents[241] = "TIME_PLAYED_MSG"; + g_scriptEvents[242] = "SPELLS_CHANGED"; + g_scriptEvents[243] = "CURRENT_SPELL_CAST_CHANGED"; + g_scriptEvents[244] = "SPELL_UPDATE_COOLDOWN"; + g_scriptEvents[245] = "SPELL_UPDATE_USABLE"; + g_scriptEvents[246] = "CHARACTER_POINTS_CHANGED"; + g_scriptEvents[247] = "SKILL_LINES_CHANGED"; + g_scriptEvents[248] = "ITEM_PUSH"; + g_scriptEvents[249] = "LOOT_OPENED"; + g_scriptEvents[250] = "LOOT_SLOT_CLEARED"; + g_scriptEvents[251] = "LOOT_SLOT_CHANGED"; + g_scriptEvents[252] = "LOOT_CLOSED"; + g_scriptEvents[253] = "PLAYER_LOGIN"; + g_scriptEvents[254] = "PLAYER_LOGOUT"; + g_scriptEvents[255] = "PLAYER_ENTERING_WORLD"; + g_scriptEvents[256] = "PLAYER_LEAVING_WORLD"; + g_scriptEvents[257] = "PLAYER_ALIVE"; + g_scriptEvents[258] = "PLAYER_DEAD"; + g_scriptEvents[259] = "PLAYER_CAMPING"; + g_scriptEvents[260] = "PLAYER_QUITING"; + g_scriptEvents[261] = "LOGOUT_CANCEL"; + g_scriptEvents[262] = "RESURRECT_REQUEST"; + g_scriptEvents[263] = "PARTY_INVITE_REQUEST"; + g_scriptEvents[264] = "PARTY_INVITE_CANCEL"; + g_scriptEvents[265] = "GUILD_INVITE_REQUEST"; + g_scriptEvents[266] = "GUILD_INVITE_CANCEL"; + g_scriptEvents[267] = "GUILD_MOTD"; + g_scriptEvents[268] = "TRADE_REQUEST"; + g_scriptEvents[269] = "TRADE_REQUEST_CANCEL"; + g_scriptEvents[270] = "LOOT_BIND_CONFIRM"; + g_scriptEvents[271] = "EQUIP_BIND_CONFIRM"; + g_scriptEvents[272] = "AUTOEQUIP_BIND_CONFIRM"; + g_scriptEvents[273] = "USE_BIND_CONFIRM"; + g_scriptEvents[274] = "DELETE_ITEM_CONFIRM"; + g_scriptEvents[275] = "CURSOR_UPDATE"; + g_scriptEvents[276] = "ITEM_TEXT_BEGIN"; + g_scriptEvents[277] = "ITEM_TEXT_TRANSLATION"; + g_scriptEvents[278] = "ITEM_TEXT_READY"; + g_scriptEvents[279] = "ITEM_TEXT_CLOSED"; + g_scriptEvents[280] = "GOSSIP_SHOW"; + g_scriptEvents[281] = "GOSSIP_CONFIRM"; + g_scriptEvents[282] = "GOSSIP_CONFIRM_CANCEL"; + g_scriptEvents[283] = "GOSSIP_ENTER_CODE"; + g_scriptEvents[284] = "GOSSIP_CLOSED"; + g_scriptEvents[285] = "QUEST_GREETING"; + g_scriptEvents[286] = "QUEST_DETAIL"; + g_scriptEvents[287] = "QUEST_PROGRESS"; + g_scriptEvents[288] = "QUEST_COMPLETE"; + g_scriptEvents[289] = "QUEST_FINISHED"; + g_scriptEvents[290] = "QUEST_ITEM_UPDATE"; + g_scriptEvents[291] = "TAXIMAP_OPENED"; + g_scriptEvents[292] = "TAXIMAP_CLOSED"; + g_scriptEvents[293] = "QUEST_LOG_UPDATE"; + g_scriptEvents[294] = "TRAINER_SHOW"; + g_scriptEvents[295] = "TRAINER_UPDATE"; + g_scriptEvents[296] = "TRAINER_DESCRIPTION_UPDATE"; + g_scriptEvents[297] = "TRAINER_CLOSED"; + g_scriptEvents[298] = "CVAR_UPDATE"; + g_scriptEvents[299] = "TRADE_SKILL_SHOW"; + g_scriptEvents[300] = "TRADE_SKILL_UPDATE"; + g_scriptEvents[301] = "TRADE_SKILL_CLOSE"; + g_scriptEvents[302] = "MERCHANT_SHOW"; + g_scriptEvents[303] = "MERCHANT_UPDATE"; + g_scriptEvents[304] = "MERCHANT_CLOSED"; + g_scriptEvents[305] = "TRADE_SHOW"; + g_scriptEvents[306] = "TRADE_CLOSED"; + g_scriptEvents[307] = "TRADE_UPDATE"; + g_scriptEvents[308] = "TRADE_ACCEPT_UPDATE"; + g_scriptEvents[309] = "TRADE_TARGET_ITEM_CHANGED"; + g_scriptEvents[310] = "TRADE_PLAYER_ITEM_CHANGED"; + g_scriptEvents[311] = "TRADE_MONEY_CHANGED"; + g_scriptEvents[312] = "PLAYER_TRADE_MONEY"; + g_scriptEvents[313] = "BAG_OPEN"; + g_scriptEvents[314] = "BAG_UPDATE"; + g_scriptEvents[315] = "BAG_CLOSED"; + g_scriptEvents[316] = "BAG_UPDATE_COOLDOWN"; + g_scriptEvents[317] = "LOCALPLAYER_PET_RENAMED"; + g_scriptEvents[318] = "UNIT_ATTACK"; + g_scriptEvents[319] = "UNIT_DEFENSE"; + g_scriptEvents[320] = "PET_ATTACK_START"; + g_scriptEvents[321] = "PET_ATTACK_STOP"; + g_scriptEvents[322] = "UPDATE_MOUSEOVER_UNIT"; + g_scriptEvents[323] = "UNIT_SPELLCAST_SENT"; + g_scriptEvents[324] = "UNIT_SPELLCAST_START"; + g_scriptEvents[325] = "UNIT_SPELLCAST_STOP"; + g_scriptEvents[326] = "UNIT_SPELLCAST_FAILED"; + g_scriptEvents[327] = "UNIT_SPELLCAST_FAILED_QUIET"; + g_scriptEvents[328] = "UNIT_SPELLCAST_INTERRUPTED"; + g_scriptEvents[329] = "UNIT_SPELLCAST_DELAYED"; + g_scriptEvents[330] = "UNIT_SPELLCAST_SUCCEEDED"; + g_scriptEvents[331] = "UNIT_SPELLCAST_CHANNEL_START"; + g_scriptEvents[332] = "UNIT_SPELLCAST_CHANNEL_UPDATE"; + g_scriptEvents[333] = "UNIT_SPELLCAST_CHANNEL_STOP"; + g_scriptEvents[334] = "UNIT_SPELLCAST_INTERRUPTIBLE"; + g_scriptEvents[335] = "UNIT_SPELLCAST_NOT_INTERRUPTIBLE"; + g_scriptEvents[336] = "PLAYER_GUILD_UPDATE"; + g_scriptEvents[337] = "QUEST_ACCEPT_CONFIRM"; + g_scriptEvents[338] = "PLAYERBANKSLOTS_CHANGED"; + g_scriptEvents[339] = "BANKFRAME_OPENED"; + g_scriptEvents[340] = "BANKFRAME_CLOSED"; + g_scriptEvents[341] = "PLAYERBANKBAGSLOTS_CHANGED"; + g_scriptEvents[342] = "FRIENDLIST_UPDATE"; + g_scriptEvents[343] = "IGNORELIST_UPDATE"; + g_scriptEvents[344] = "MUTELIST_UPDATE"; + g_scriptEvents[345] = "PET_BAR_UPDATE"; + g_scriptEvents[346] = "PET_BAR_UPDATE_COOLDOWN"; + g_scriptEvents[347] = "PET_BAR_SHOWGRID"; + g_scriptEvents[348] = "PET_BAR_HIDEGRID"; + g_scriptEvents[349] = "PET_BAR_HIDE"; + g_scriptEvents[350] = "PET_BAR_UPDATE_USABLE"; + g_scriptEvents[351] = "MINIMAP_PING"; + g_scriptEvents[352] = "MIRROR_TIMER_START"; + g_scriptEvents[353] = "MIRROR_TIMER_PAUSE"; + g_scriptEvents[354] = "MIRROR_TIMER_STOP"; + g_scriptEvents[355] = "WORLD_MAP_UPDATE"; + g_scriptEvents[356] = "WORLD_MAP_NAME_UPDATE"; + g_scriptEvents[357] = "AUTOFOLLOW_BEGIN"; + g_scriptEvents[358] = "AUTOFOLLOW_END"; + g_scriptEvents[360] = "CINEMATIC_START"; + g_scriptEvents[361] = "CINEMATIC_STOP"; + g_scriptEvents[362] = "UPDATE_FACTION"; + g_scriptEvents[363] = "CLOSE_WORLD_MAP"; + g_scriptEvents[364] = "OPEN_TABARD_FRAME"; + g_scriptEvents[365] = "CLOSE_TABARD_FRAME"; + g_scriptEvents[366] = "TABARD_CANSAVE_CHANGED"; + g_scriptEvents[367] = "GUILD_REGISTRAR_SHOW"; + g_scriptEvents[368] = "GUILD_REGISTRAR_CLOSED"; + g_scriptEvents[369] = "DUEL_REQUESTED"; + g_scriptEvents[370] = "DUEL_OUTOFBOUNDS"; + g_scriptEvents[371] = "DUEL_INBOUNDS"; + g_scriptEvents[372] = "DUEL_FINISHED"; + g_scriptEvents[373] = "TUTORIAL_TRIGGER"; + g_scriptEvents[374] = "PET_DISMISS_START"; + g_scriptEvents[375] = "UPDATE_BINDINGS"; + g_scriptEvents[376] = "UPDATE_SHAPESHIFT_FORMS"; + g_scriptEvents[377] = "UPDATE_SHAPESHIFT_FORM"; + g_scriptEvents[378] = "UPDATE_SHAPESHIFT_USABLE"; + g_scriptEvents[379] = "UPDATE_SHAPESHIFT_COOLDOWN"; + g_scriptEvents[380] = "WHO_LIST_UPDATE"; + g_scriptEvents[381] = "PETITION_SHOW"; + g_scriptEvents[382] = "PETITION_CLOSED"; + g_scriptEvents[383] = "EXECUTE_CHAT_LINE"; + g_scriptEvents[384] = "UPDATE_MACROS"; + g_scriptEvents[385] = "UPDATE_TICKET"; + g_scriptEvents[386] = "UPDATE_CHAT_WINDOWS"; + g_scriptEvents[387] = "CONFIRM_XP_LOSS"; + g_scriptEvents[388] = "CORPSE_IN_RANGE"; + g_scriptEvents[389] = "CORPSE_IN_INSTANCE"; + g_scriptEvents[390] = "CORPSE_OUT_OF_RANGE"; + g_scriptEvents[391] = "UPDATE_GM_STATUS"; + g_scriptEvents[392] = "PLAYER_UNGHOST"; + g_scriptEvents[393] = "BIND_ENCHANT"; + g_scriptEvents[394] = "REPLACE_ENCHANT"; + g_scriptEvents[395] = "TRADE_REPLACE_ENCHANT"; + g_scriptEvents[396] = "TRADE_POTENTIAL_BIND_ENCHANT"; + g_scriptEvents[397] = "PLAYER_UPDATE_RESTING"; + g_scriptEvents[398] = "UPDATE_EXHAUSTION"; + g_scriptEvents[399] = "PLAYER_FLAGS_CHANGED"; + g_scriptEvents[400] = "GUILD_ROSTER_UPDATE"; + g_scriptEvents[401] = "GM_PLAYER_INFO"; + g_scriptEvents[402] = "MAIL_SHOW"; + g_scriptEvents[403] = "MAIL_CLOSED"; + g_scriptEvents[404] = "SEND_MAIL_MONEY_CHANGED"; + g_scriptEvents[405] = "SEND_MAIL_COD_CHANGED"; + g_scriptEvents[406] = "MAIL_SEND_INFO_UPDATE"; + g_scriptEvents[407] = "MAIL_SEND_SUCCESS"; + g_scriptEvents[408] = "MAIL_INBOX_UPDATE"; + g_scriptEvents[409] = "MAIL_LOCK_SEND_ITEMS"; + g_scriptEvents[410] = "MAIL_UNLOCK_SEND_ITEMS"; + g_scriptEvents[411] = "BATTLEFIELDS_SHOW"; + g_scriptEvents[412] = "BATTLEFIELDS_CLOSED"; + g_scriptEvents[413] = "UPDATE_BATTLEFIELD_STATUS"; + g_scriptEvents[414] = "UPDATE_BATTLEFIELD_SCORE"; + g_scriptEvents[415] = "AUCTION_HOUSE_SHOW"; + g_scriptEvents[416] = "AUCTION_HOUSE_CLOSED"; + g_scriptEvents[417] = "NEW_AUCTION_UPDATE"; + g_scriptEvents[418] = "AUCTION_ITEM_LIST_UPDATE"; + g_scriptEvents[419] = "AUCTION_OWNED_LIST_UPDATE"; + g_scriptEvents[420] = "AUCTION_BIDDER_LIST_UPDATE"; + g_scriptEvents[421] = "PET_UI_UPDATE"; + g_scriptEvents[422] = "PET_UI_CLOSE"; + g_scriptEvents[423] = "ADDON_LOADED"; + g_scriptEvents[424] = "VARIABLES_LOADED"; + g_scriptEvents[425] = "MACRO_ACTION_FORBIDDEN"; + g_scriptEvents[426] = "ADDON_ACTION_FORBIDDEN"; + g_scriptEvents[427] = "MACRO_ACTION_BLOCKED"; + g_scriptEvents[428] = "ADDON_ACTION_BLOCKED"; + g_scriptEvents[429] = "START_AUTOREPEAT_SPELL"; + g_scriptEvents[430] = "STOP_AUTOREPEAT_SPELL"; + g_scriptEvents[431] = "PET_STABLE_SHOW"; + g_scriptEvents[432] = "PET_STABLE_UPDATE"; + g_scriptEvents[433] = "PET_STABLE_UPDATE_PAPERDOLL"; + g_scriptEvents[434] = "PET_STABLE_CLOSED"; + g_scriptEvents[435] = "RAID_ROSTER_UPDATE"; + g_scriptEvents[436] = "UPDATE_PENDING_MAIL"; + g_scriptEvents[437] = "UPDATE_INVENTORY_ALERTS"; + g_scriptEvents[438] = "UPDATE_INVENTORY_DURABILITY"; + g_scriptEvents[439] = "UPDATE_TRADESKILL_RECAST"; + g_scriptEvents[440] = "OPEN_MASTER_LOOT_LIST"; + g_scriptEvents[441] = "UPDATE_MASTER_LOOT_LIST"; + g_scriptEvents[442] = "START_LOOT_ROLL"; + g_scriptEvents[443] = "CANCEL_LOOT_ROLL"; + g_scriptEvents[444] = "CONFIRM_LOOT_ROLL"; + g_scriptEvents[445] = "CONFIRM_DISENCHANT_ROLL"; + g_scriptEvents[446] = "INSTANCE_BOOT_START"; + g_scriptEvents[447] = "INSTANCE_BOOT_STOP"; + g_scriptEvents[448] = "LEARNED_SPELL_IN_TAB"; + g_scriptEvents[449] = "DISPLAY_SIZE_CHANGED"; + g_scriptEvents[450] = "CONFIRM_TALENT_WIPE"; + g_scriptEvents[451] = "CONFIRM_BINDER"; + g_scriptEvents[452] = "MAIL_FAILED"; + g_scriptEvents[453] = "CLOSE_INBOX_ITEM"; + g_scriptEvents[454] = "CONFIRM_SUMMON"; + g_scriptEvents[455] = "CANCEL_SUMMON"; + g_scriptEvents[456] = "BILLING_NAG_DIALOG"; + g_scriptEvents[457] = "IGR_BILLING_NAG_DIALOG"; + g_scriptEvents[458] = "PLAYER_SKINNED"; + g_scriptEvents[459] = "TABARD_SAVE_PENDING"; + g_scriptEvents[460] = "UNIT_QUEST_LOG_CHANGED"; + g_scriptEvents[461] = "PLAYER_PVP_KILLS_CHANGED"; + g_scriptEvents[462] = "PLAYER_PVP_RANK_CHANGED"; + g_scriptEvents[463] = "INSPECT_HONOR_UPDATE"; + g_scriptEvents[464] = "UPDATE_WORLD_STATES"; + g_scriptEvents[465] = "AREA_SPIRIT_HEALER_IN_RANGE"; + g_scriptEvents[466] = "AREA_SPIRIT_HEALER_OUT_OF_RANGE"; + g_scriptEvents[467] = "PLAYTIME_CHANGED"; + g_scriptEvents[468] = "UPDATE_LFG_TYPES"; + g_scriptEvents[469] = "UPDATE_LFG_LIST"; + g_scriptEvents[470] = "UPDATE_LFG_LIST_INCREMENTAL"; + g_scriptEvents[471] = "START_MINIGAME"; + g_scriptEvents[472] = "MINIGAME_UPDATE"; + g_scriptEvents[473] = "READY_CHECK"; + g_scriptEvents[474] = "READY_CHECK_CONFIRM"; + g_scriptEvents[475] = "READY_CHECK_FINISHED"; + g_scriptEvents[476] = "RAID_TARGET_UPDATE"; + g_scriptEvents[477] = "GMSURVEY_DISPLAY"; + g_scriptEvents[478] = "UPDATE_INSTANCE_INFO"; + g_scriptEvents[479] = "SOCKET_INFO_UPDATE"; + g_scriptEvents[480] = "SOCKET_INFO_CLOSE"; + g_scriptEvents[481] = "PETITION_VENDOR_SHOW"; + g_scriptEvents[482] = "PETITION_VENDOR_CLOSED"; + g_scriptEvents[483] = "PETITION_VENDOR_UPDATE"; + g_scriptEvents[484] = "COMBAT_TEXT_UPDATE"; + g_scriptEvents[485] = "QUEST_WATCH_UPDATE"; + g_scriptEvents[486] = "KNOWLEDGE_BASE_SETUP_LOAD_SUCCESS"; + g_scriptEvents[487] = "KNOWLEDGE_BASE_SETUP_LOAD_FAILURE"; + g_scriptEvents[488] = "KNOWLEDGE_BASE_QUERY_LOAD_SUCCESS"; + g_scriptEvents[489] = "KNOWLEDGE_BASE_QUERY_LOAD_FAILURE"; + g_scriptEvents[490] = "KNOWLEDGE_BASE_ARTICLE_LOAD_SUCCESS"; + g_scriptEvents[491] = "KNOWLEDGE_BASE_ARTICLE_LOAD_FAILURE"; + g_scriptEvents[492] = "KNOWLEDGE_BASE_SYSTEM_MOTD_UPDATED"; + g_scriptEvents[493] = "KNOWLEDGE_BASE_SERVER_MESSAGE"; + g_scriptEvents[494] = "ARENA_TEAM_UPDATE"; + g_scriptEvents[495] = "ARENA_TEAM_ROSTER_UPDATE"; + g_scriptEvents[496] = "ARENA_TEAM_INVITE_REQUEST"; + g_scriptEvents[497] = "HONOR_CURRENCY_UPDATE"; + g_scriptEvents[498] = "KNOWN_TITLES_UPDATE"; + g_scriptEvents[499] = "NEW_TITLE_EARNED"; + g_scriptEvents[500] = "OLD_TITLE_LOST"; + g_scriptEvents[501] = "LFG_UPDATE"; + g_scriptEvents[502] = "LFG_PROPOSAL_UPDATE"; + g_scriptEvents[503] = "LFG_PROPOSAL_SHOW"; + g_scriptEvents[504] = "LFG_PROPOSAL_FAILED"; + g_scriptEvents[505] = "LFG_PROPOSAL_SUCCEEDED"; + g_scriptEvents[506] = "LFG_ROLE_UPDATE"; + g_scriptEvents[507] = "LFG_ROLE_CHECK_UPDATE"; + g_scriptEvents[508] = "LFG_ROLE_CHECK_SHOW"; + g_scriptEvents[509] = "LFG_ROLE_CHECK_HIDE"; + g_scriptEvents[510] = "LFG_ROLE_CHECK_ROLE_CHOSEN"; + g_scriptEvents[511] = "LFG_QUEUE_STATUS_UPDATE"; + g_scriptEvents[512] = "LFG_BOOT_PROPOSAL_UPDATE"; + g_scriptEvents[513] = "LFG_LOCK_INFO_RECEIVED"; + g_scriptEvents[514] = "LFG_UPDATE_RANDOM_INFO"; + g_scriptEvents[515] = "LFG_OFFER_CONTINUE"; + g_scriptEvents[516] = "LFG_OPEN_FROM_GOSSIP"; + g_scriptEvents[517] = "LFG_COMPLETION_REWARD"; + g_scriptEvents[518] = "PARTY_LFG_RESTRICTED"; + g_scriptEvents[519] = "PLAYER_ROLES_ASSIGNED"; + g_scriptEvents[520] = "COMBAT_RATING_UPDATE"; + g_scriptEvents[521] = "MODIFIER_STATE_CHANGED"; + g_scriptEvents[522] = "UPDATE_STEALTH"; + g_scriptEvents[523] = "ENABLE_TAXI_BENCHMARK"; + g_scriptEvents[524] = "DISABLE_TAXI_BENCHMARK"; + g_scriptEvents[525] = "VOICE_START"; + g_scriptEvents[526] = "VOICE_STOP"; + g_scriptEvents[527] = "VOICE_STATUS_UPDATE"; + g_scriptEvents[528] = "VOICE_CHANNEL_STATUS_UPDATE"; + g_scriptEvents[529] = "UPDATE_FLOATING_CHAT_WINDOWS"; + g_scriptEvents[530] = "RAID_INSTANCE_WELCOME"; + g_scriptEvents[531] = "MOVIE_RECORDING_PROGRESS"; + g_scriptEvents[532] = "MOVIE_COMPRESSING_PROGRESS"; + g_scriptEvents[533] = "MOVIE_UNCOMPRESSED_MOVIE"; + g_scriptEvents[534] = "VOICE_PUSH_TO_TALK_START"; + g_scriptEvents[535] = "VOICE_PUSH_TO_TALK_STOP"; + g_scriptEvents[536] = "GUILDBANKFRAME_OPENED"; + g_scriptEvents[537] = "GUILDBANKFRAME_CLOSED"; + g_scriptEvents[538] = "GUILDBANKBAGSLOTS_CHANGED"; + g_scriptEvents[539] = "GUILDBANK_ITEM_LOCK_CHANGED"; + g_scriptEvents[540] = "GUILDBANK_UPDATE_TABS"; + g_scriptEvents[541] = "GUILDBANK_UPDATE_MONEY"; + g_scriptEvents[542] = "GUILDBANKLOG_UPDATE"; + g_scriptEvents[543] = "GUILDBANK_UPDATE_WITHDRAWMONEY"; + g_scriptEvents[544] = "GUILDBANK_UPDATE_TEXT"; + g_scriptEvents[545] = "GUILDBANK_TEXT_CHANGED"; + g_scriptEvents[546] = "CHANNEL_UI_UPDATE"; + g_scriptEvents[547] = "CHANNEL_COUNT_UPDATE"; + g_scriptEvents[548] = "CHANNEL_ROSTER_UPDATE"; + g_scriptEvents[549] = "CHANNEL_VOICE_UPDATE"; + g_scriptEvents[550] = "CHANNEL_INVITE_REQUEST"; + g_scriptEvents[551] = "CHANNEL_PASSWORD_REQUEST"; + g_scriptEvents[552] = "CHANNEL_FLAGS_UPDATED"; + g_scriptEvents[553] = "VOICE_SESSIONS_UPDATE"; + g_scriptEvents[554] = "VOICE_CHAT_ENABLED_UPDATE"; + g_scriptEvents[555] = "VOICE_LEFT_SESSION"; + g_scriptEvents[556] = "INSPECT_TALENT_READY"; + g_scriptEvents[557] = "VOICE_SELF_MUTE"; + g_scriptEvents[558] = "VOICE_PLATE_START"; + g_scriptEvents[559] = "VOICE_PLATE_STOP"; + g_scriptEvents[560] = "ARENA_SEASON_WORLD_STATE"; + g_scriptEvents[561] = "GUILD_EVENT_LOG_UPDATE"; + g_scriptEvents[562] = "GUILDTABARD_UPDATE"; + g_scriptEvents[563] = "SOUND_DEVICE_UPDATE"; + g_scriptEvents[564] = "COMMENTATOR_MAP_UPDATE"; + g_scriptEvents[565] = "COMMENTATOR_ENTER_WORLD"; + g_scriptEvents[566] = "COMBAT_LOG_EVENT"; + g_scriptEvents[567] = "COMBAT_LOG_EVENT_UNFILTERED"; + g_scriptEvents[568] = "COMMENTATOR_PLAYER_UPDATE"; + g_scriptEvents[569] = "PLAYER_ENTERING_BATTLEGROUND"; + g_scriptEvents[570] = "BARBER_SHOP_OPEN"; + g_scriptEvents[571] = "BARBER_SHOP_CLOSE"; + g_scriptEvents[572] = "BARBER_SHOP_SUCCESS"; + g_scriptEvents[573] = "BARBER_SHOP_APPEARANCE_APPLIED"; + g_scriptEvents[574] = "CALENDAR_UPDATE_INVITE_LIST"; + g_scriptEvents[575] = "CALENDAR_UPDATE_EVENT_LIST"; + g_scriptEvents[576] = "CALENDAR_NEW_EVENT"; + g_scriptEvents[577] = "CALENDAR_OPEN_EVENT"; + g_scriptEvents[578] = "CALENDAR_CLOSE_EVENT"; + g_scriptEvents[579] = "CALENDAR_UPDATE_EVENT"; + g_scriptEvents[580] = "CALENDAR_UPDATE_PENDING_INVITES"; + g_scriptEvents[581] = "CALENDAR_EVENT_ALARM"; + g_scriptEvents[582] = "CALENDAR_UPDATE_ERROR"; + g_scriptEvents[583] = "CALENDAR_ACTION_PENDING"; + g_scriptEvents[584] = "VEHICLE_ANGLE_SHOW"; + g_scriptEvents[585] = "VEHICLE_ANGLE_UPDATE"; + g_scriptEvents[586] = "VEHICLE_POWER_SHOW"; + g_scriptEvents[587] = "UNIT_ENTERING_VEHICLE"; + g_scriptEvents[588] = "UNIT_ENTERED_VEHICLE"; + g_scriptEvents[589] = "UNIT_EXITING_VEHICLE"; + g_scriptEvents[590] = "UNIT_EXITED_VEHICLE"; + g_scriptEvents[591] = "VEHICLE_PASSENGERS_CHANGED"; + g_scriptEvents[592] = "PLAYER_GAINS_VEHICLE_DATA"; + g_scriptEvents[593] = "PLAYER_LOSES_VEHICLE_DATA"; + g_scriptEvents[594] = "PET_FORCE_NAME_DECLENSION"; + g_scriptEvents[595] = "LEVEL_GRANT_PROPOSED"; + g_scriptEvents[596] = "SYNCHRONIZE_SETTINGS"; + g_scriptEvents[597] = "PLAY_MOVIE"; + g_scriptEvents[598] = "RUNE_POWER_UPDATE"; + g_scriptEvents[599] = "RUNE_TYPE_UPDATE"; + g_scriptEvents[600] = "ACHIEVEMENT_EARNED"; + g_scriptEvents[601] = "CRITERIA_UPDATE"; + g_scriptEvents[602] = "RECEIVED_ACHIEVEMENT_LIST"; + g_scriptEvents[603] = "PET_RENAMEABLE"; + g_scriptEvents[604] = "KNOWN_CURRENCY_TYPES_UPDATE"; + g_scriptEvents[605] = "CURRENCY_DISPLAY_UPDATE"; + g_scriptEvents[606] = "COMPANION_LEARNED"; + g_scriptEvents[607] = "COMPANION_UNLEARNED"; + g_scriptEvents[608] = "COMPANION_UPDATE"; + g_scriptEvents[609] = "UNIT_THREAT_LIST_UPDATE"; + g_scriptEvents[610] = "UNIT_THREAT_SITUATION_UPDATE"; + g_scriptEvents[611] = "GLYPH_ADDED"; + g_scriptEvents[612] = "GLYPH_REMOVED"; + g_scriptEvents[613] = "GLYPH_UPDATED"; + g_scriptEvents[614] = "GLYPH_ENABLED"; + g_scriptEvents[615] = "GLYPH_DISABLED"; + g_scriptEvents[616] = "USE_GLYPH"; + g_scriptEvents[617] = "TRACKED_ACHIEVEMENT_UPDATE"; + g_scriptEvents[618] = "ARENA_OPPONENT_UPDATE"; + g_scriptEvents[619] = "INSPECT_ACHIEVEMENT_READY"; + g_scriptEvents[620] = "RAISED_AS_GHOUL"; + g_scriptEvents[621] = "PARTY_CONVERTED_TO_RAID"; + g_scriptEvents[622] = "PVPQUEUE_ANYWHERE_SHOW"; + g_scriptEvents[623] = "PVPQUEUE_ANYWHERE_UPDATE_AVAILABLE"; + g_scriptEvents[624] = "QUEST_ACCEPTED"; + g_scriptEvents[625] = "PLAYER_TALENT_UPDATE"; + g_scriptEvents[626] = "ACTIVE_TALENT_GROUP_CHANGED"; + g_scriptEvents[627] = "PET_TALENT_UPDATE"; + g_scriptEvents[628] = "PREVIEW_TALENT_POINTS_CHANGED"; + g_scriptEvents[629] = "PREVIEW_PET_TALENT_POINTS_CHANGED"; + g_scriptEvents[630] = "WEAR_EQUIPMENT_SET"; + g_scriptEvents[631] = "EQUIPMENT_SETS_CHANGED"; + g_scriptEvents[632] = "INSTANCE_LOCK_START"; + g_scriptEvents[633] = "INSTANCE_LOCK_STOP"; + g_scriptEvents[634] = "PLAYER_EQUIPMENT_CHANGED"; + g_scriptEvents[635] = "ITEM_LOCKED"; + g_scriptEvents[636] = "ITEM_UNLOCKED"; + g_scriptEvents[637] = "TRADE_SKILL_FILTER_UPDATE"; + g_scriptEvents[638] = "EQUIPMENT_SWAP_PENDING"; + g_scriptEvents[639] = "EQUIPMENT_SWAP_FINISHED"; + g_scriptEvents[640] = "NPC_PVPQUEUE_ANYWHERE"; + g_scriptEvents[641] = "UPDATE_MULTI_CAST_ACTIONBAR"; + g_scriptEvents[642] = "ENABLE_XP_GAIN"; + g_scriptEvents[643] = "DISABLE_XP_GAIN"; + g_scriptEvents[644] = "BATTLEFIELD_MGR_ENTRY_INVITE"; + g_scriptEvents[645] = "BATTLEFIELD_MGR_ENTERED"; + g_scriptEvents[646] = "BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE"; + g_scriptEvents[647] = "BATTLEFIELD_MGR_EJECT_PENDING"; + g_scriptEvents[648] = "BATTLEFIELD_MGR_EJECTED"; + g_scriptEvents[649] = "BATTLEFIELD_MGR_QUEUE_INVITE"; + g_scriptEvents[650] = "BATTLEFIELD_MGR_STATE_CHANGE"; + g_scriptEvents[651] = "WORLD_STATE_UI_TIMER_UPDATE"; + g_scriptEvents[652] = "END_REFUND"; + g_scriptEvents[653] = "END_BOUND_TRADEABLE"; + g_scriptEvents[654] = "UPDATE_CHAT_COLOR_NAME_BY_CLASS"; + g_scriptEvents[655] = "GMRESPONSE_RECEIVED"; + g_scriptEvents[656] = "VEHICLE_UPDATE"; + g_scriptEvents[657] = "WOW_MOUSE_NOT_FOUND"; + g_scriptEvents[659] = "MAIL_SUCCESS"; + g_scriptEvents[660] = "TALENTS_INVOLUNTARILY_RESET"; + g_scriptEvents[661] = "INSTANCE_ENCOUNTER_ENGAGE_UNIT"; + g_scriptEvents[662] = "QUEST_QUERY_COMPLETE"; + g_scriptEvents[663] = "QUEST_POI_UPDATE"; + g_scriptEvents[664] = "PLAYER_DIFFICULTY_CHANGED"; + g_scriptEvents[665] = "CHAT_MSG_PARTY_LEADER"; + g_scriptEvents[666] = "VOTE_KICK_REASON_NEEDED"; + g_scriptEvents[667] = "ENABLE_LOW_LEVEL_RAID"; + g_scriptEvents[668] = "DISABLE_LOW_LEVEL_RAID"; + g_scriptEvents[669] = "CHAT_MSG_TARGETICONS"; + g_scriptEvents[670] = "AUCTION_HOUSE_DISABLED"; + g_scriptEvents[671] = "AUCTION_MULTISELL_START"; + g_scriptEvents[672] = "AUCTION_MULTISELL_UPDATE"; + g_scriptEvents[673] = "AUCTION_MULTISELL_FAILURE"; + g_scriptEvents[674] = "PET_SPELL_POWER_UPDATE"; + g_scriptEvents[675] = "BN_CONNECTED"; + g_scriptEvents[676] = "BN_DISCONNECTED"; + g_scriptEvents[677] = "BN_SELF_ONLINE"; + g_scriptEvents[678] = "BN_SELF_OFFLINE"; + g_scriptEvents[679] = "BN_FRIEND_LIST_SIZE_CHANGED"; + g_scriptEvents[680] = "BN_FRIEND_INVITE_LIST_INITIALIZED"; + g_scriptEvents[681] = "BN_FRIEND_INVITE_SEND_RESULT"; + g_scriptEvents[682] = "BN_FRIEND_INVITE_ADDED"; + g_scriptEvents[683] = "BN_FRIEND_INVITE_REMOVED"; + g_scriptEvents[684] = "BN_FRIEND_INFO_CHANGED"; + g_scriptEvents[685] = "BN_CUSTOM_MESSAGE_CHANGED"; + g_scriptEvents[686] = "BN_CUSTOM_MESSAGE_LOADED"; + g_scriptEvents[687] = "CHAT_MSG_BN_WHISPER"; + g_scriptEvents[688] = "CHAT_MSG_BN_WHISPER_INFORM"; + g_scriptEvents[689] = "BN_CHAT_WHISPER_UNDELIVERABLE"; + g_scriptEvents[690] = "BN_CHAT_CHANNEL_JOINED"; + g_scriptEvents[691] = "BN_CHAT_CHANNEL_LEFT"; + g_scriptEvents[692] = "BN_CHAT_CHANNEL_CLOSED"; + g_scriptEvents[693] = "CHAT_MSG_BN_CONVERSATION"; + g_scriptEvents[694] = "CHAT_MSG_BN_CONVERSATION_NOTICE"; + g_scriptEvents[695] = "CHAT_MSG_BN_CONVERSATION_LIST"; + g_scriptEvents[696] = "BN_CHAT_CHANNEL_MESSAGE_UNDELIVERABLE"; + g_scriptEvents[697] = "BN_CHAT_CHANNEL_MESSAGE_BLOCKED"; + g_scriptEvents[698] = "BN_CHAT_CHANNEL_MEMBER_JOINED"; + g_scriptEvents[699] = "BN_CHAT_CHANNEL_MEMBER_LEFT"; + g_scriptEvents[700] = "BN_CHAT_CHANNEL_MEMBER_UPDATED"; + g_scriptEvents[701] = "BN_CHAT_CHANNEL_CREATE_SUCCEEDED"; + g_scriptEvents[702] = "BN_CHAT_CHANNEL_CREATE_FAILED"; + g_scriptEvents[703] = "BN_CHAT_CHANNEL_INVITE_SUCCEEDED"; + g_scriptEvents[704] = "BN_CHAT_CHANNEL_INVITE_FAILED"; + g_scriptEvents[705] = "BN_BLOCK_LIST_UPDATED"; + g_scriptEvents[706] = "BN_SYSTEM_MESSAGE"; + g_scriptEvents[707] = "BN_REQUEST_FOF_SUCCEEDED"; + g_scriptEvents[708] = "BN_REQUEST_FOF_FAILED"; + g_scriptEvents[709] = "BN_NEW_PRESENCE"; + g_scriptEvents[710] = "BN_TOON_NAME_UPDATED"; + g_scriptEvents[711] = "BN_FRIEND_ACCOUNT_ONLINE"; + g_scriptEvents[712] = "BN_FRIEND_ACCOUNT_OFFLINE"; + g_scriptEvents[713] = "BN_FRIEND_TOON_ONLINE"; + g_scriptEvents[714] = "BN_FRIEND_TOON_OFFLINE"; + g_scriptEvents[715] = "BN_MATURE_LANGUAGE_FILTER"; + g_scriptEvents[716] = "COMMENTATOR_SKIRMISH_QUEUE_REQUEST"; + g_scriptEvents[717] = "COMMENTATOR_SKIRMISH_MODE_REQUEST"; + g_scriptEvents[718] = "CHAT_MSG_BN_INLINE_TOAST_ALERT"; + g_scriptEvents[719] = "CHAT_MSG_BN_INLINE_TOAST_BROADCAST"; + g_scriptEvents[720] = "CHAT_MSG_BN_INLINE_TOAST_BROADCAST_INFORM"; + g_scriptEvents[721] = "CHAT_MSG_BN_INLINE_TOAST_CONVERSATION"; +} diff --git a/src/ui/game/ScriptEvents.hpp b/src/ui/game/ScriptEvents.hpp index 8240bc3..5e72007 100644 --- a/src/ui/game/ScriptEvents.hpp +++ b/src/ui/game/ScriptEvents.hpp @@ -1,6 +1,8 @@ #ifndef UI_GAME_SCRIPT_EVENTS_HPP #define UI_GAME_SCRIPT_EVENTS_HPP +void ScriptEventsInitialize(); + void ScriptEventsRegisterFunctions(); #endif From f08cbc079511f9bd69413ba553fcd3b61d9bfae6 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 20:33:53 -0600 Subject: [PATCH 186/269] feat(ui): add ScriptEventsRegisterEvents --- src/ui/FrameScript.cpp | 8 ++++---- src/ui/FrameScript.hpp | 1 - src/ui/game/CGGameUI.cpp | 1 + src/ui/game/ScriptEvents.cpp | 8 ++++++++ src/ui/game/ScriptEvents.hpp | 4 ++++ 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/ui/FrameScript.cpp b/src/ui/FrameScript.cpp index 95e2c57..9ab1430 100644 --- a/src/ui/FrameScript.cpp +++ b/src/ui/FrameScript.cpp @@ -11,8 +11,6 @@ #include #include -const char* g_scriptEvents[722]; - int32_t g_glueFrameScriptGenders[] = { 2, // UNIT_SEX_MALE 3, // UNIT_SEX_FEMALE @@ -154,8 +152,10 @@ void FrameScript_CreateEvents(const char* names[], uint32_t count) { FrameScript::s_scriptEvents.SetCount(count); for (int32_t i = 0; i < count; i++) { - auto event = FrameScript::s_scriptEventsHash.New(names[i], 0, 0); - FrameScript::s_scriptEvents[i] = event; + if (names[i]) { + auto event = FrameScript::s_scriptEventsHash.New(names[i], 0, 0); + FrameScript::s_scriptEvents[i] = event; + } } } diff --git a/src/ui/FrameScript.hpp b/src/ui/FrameScript.hpp index 3eff364..da63f47 100644 --- a/src/ui/FrameScript.hpp +++ b/src/ui/FrameScript.hpp @@ -40,7 +40,6 @@ class FrameScript_EventObject : public TSHashObject Date: Thu, 5 Feb 2026 20:51:46 -0600 Subject: [PATCH 187/269] feat(ui): add CGGameUI::IsLoggingIn --- src/ui/game/CGGameUI.cpp | 9 +++++++++ src/ui/game/CGGameUI.hpp | 2 ++ 2 files changed, 11 insertions(+) diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 26db2a5..5999a82 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -25,6 +25,7 @@ WOWGUID CGGameUI::s_currentObjectTrack; CScriptObject* CGGameUI::s_gameTooltip; WOWGUID CGGameUI::s_lockedTarget; +bool CGGameUI::s_loggingIn; CSimpleTop* CGGameUI::s_simpleTop; void LoadScriptFunctions() { @@ -75,6 +76,10 @@ WOWGUID& CGGameUI::GetLockedTarget() { void CGGameUI::Initialize() { // TODO + CGGameUI::s_loggingIn = true; + + // TODO + CGGameUI::s_simpleTop = STORM_NEW(CSimpleTop); // TODO @@ -160,6 +165,10 @@ void CGGameUI::InitializeGame() { // TODO } +bool CGGameUI::IsLoggingIn() { + return CGGameUI::s_loggingIn; +} + int32_t CGGameUI::IsRaidMember(const WOWGUID& guid) { // TODO diff --git a/src/ui/game/CGGameUI.hpp b/src/ui/game/CGGameUI.hpp index 2fc782b..4415bc5 100644 --- a/src/ui/game/CGGameUI.hpp +++ b/src/ui/game/CGGameUI.hpp @@ -17,6 +17,7 @@ class CGGameUI { static WOWGUID& GetLockedTarget(); static void Initialize(); static void InitializeGame(); + static bool IsLoggingIn(); static int32_t IsRaidMember(const WOWGUID& guid); static int32_t IsRaidMemberOrPet(const WOWGUID& guid); static void RegisterFrameFactories(); @@ -24,6 +25,7 @@ class CGGameUI { private: static WOWGUID s_currentObjectTrack; static WOWGUID s_lockedTarget; + static bool s_loggingIn; }; #endif From e5aab736b741a0a7764d561ba4b500a1f93ebe04 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 21:04:31 -0600 Subject: [PATCH 188/269] feat(ui): add CGGameUI::EnterWorld --- src/ui/Game.hpp | 1 + src/ui/game/CGGameUI.cpp | 31 +++++++++++++++++++++++++++++++ src/ui/game/CGGameUI.hpp | 2 ++ src/ui/game/ScriptEvents.cpp | 7 ++++--- src/ui/game/Types.hpp | 12 ++++++++++++ 5 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/ui/game/Types.hpp diff --git a/src/ui/Game.hpp b/src/ui/Game.hpp index 82eb4a9..41f63d9 100644 --- a/src/ui/Game.hpp +++ b/src/ui/Game.hpp @@ -4,5 +4,6 @@ #include "ui/game/CGGameUI.hpp" #include "ui/game/CGPetInfo.hpp" #include "ui/game/ScriptEvents.hpp" +#include "ui/game/Types.hpp" #endif diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 5999a82..8107419 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -1,5 +1,6 @@ #include "ui/game/CGGameUI.hpp" #include "client/Client.hpp" +#include "object/Client.hpp" #include "ui/CScriptObject.hpp" #include "ui/FrameXML.hpp" #include "ui/Key.hpp" @@ -17,6 +18,7 @@ #include "ui/game/GMTicketInfoScript.hpp" #include "ui/game/GameScript.hpp" #include "ui/game/ScriptEvents.hpp" +#include "ui/game/Types.hpp" #include "ui/game/UIBindingsScript.hpp" #include "ui/simple/CSimpleTop.hpp" #include "util/CStatus.hpp" @@ -24,6 +26,7 @@ WOWGUID CGGameUI::s_currentObjectTrack; CScriptObject* CGGameUI::s_gameTooltip; +bool CGGameUI::s_inWorld; WOWGUID CGGameUI::s_lockedTarget; bool CGGameUI::s_loggingIn; CSimpleTop* CGGameUI::s_simpleTop; @@ -65,6 +68,28 @@ void LoadScriptFunctions() { // TODO } +void CGGameUI::EnterWorld() { + if (CGGameUI::s_inWorld) { + return; + } + + CGGameUI::s_inWorld = true; + + // TODO + + if (CGGameUI::s_loggingIn) { + CGGameUI::s_loggingIn = false; + + FrameScript_SignalEvent(SCRIPT_PLAYER_LOGIN, nullptr); + + // TODO CGLCD::Login(); + } + + FrameScript_SignalEvent(SCRIPT_PLAYER_ENTERING_WORLD, nullptr); + + // TODO +} + WOWGUID& CGGameUI::GetCurrentObjectTrack() { return CGGameUI::s_currentObjectTrack; } @@ -155,6 +180,12 @@ void CGGameUI::Initialize() { STORM_ASSERT(CGGameUI::s_gameTooltip); // TODO + + if (ClntObjMgrGetActivePlayer()) { + CGGameUI::EnterWorld(); + } + + // TODO } void CGGameUI::InitializeGame() { diff --git a/src/ui/game/CGGameUI.hpp b/src/ui/game/CGGameUI.hpp index 4415bc5..6b7aaab 100644 --- a/src/ui/game/CGGameUI.hpp +++ b/src/ui/game/CGGameUI.hpp @@ -13,6 +13,7 @@ class CGGameUI { static CSimpleTop* s_simpleTop; // Static functions + static void EnterWorld(); static WOWGUID& GetCurrentObjectTrack(); static WOWGUID& GetLockedTarget(); static void Initialize(); @@ -24,6 +25,7 @@ class CGGameUI { private: static WOWGUID s_currentObjectTrack; + static bool s_inWorld; static WOWGUID s_lockedTarget; static bool s_loggingIn; }; diff --git a/src/ui/game/ScriptEvents.cpp b/src/ui/game/ScriptEvents.cpp index 941e8b2..b3aa7d4 100644 --- a/src/ui/game/ScriptEvents.cpp +++ b/src/ui/game/ScriptEvents.cpp @@ -5,6 +5,7 @@ #include "ui/ScriptFunctionsSystem.hpp" #include "ui/game/CGGameUI.hpp" #include "ui/game/ScriptUtil.hpp" +#include "ui/game/Types.hpp" #include "util/GUID.hpp" #include "util/Lua.hpp" #include "util/StringTo.hpp" @@ -1133,9 +1134,9 @@ void ScriptEventsInitialize() { g_scriptEvents[250] = "LOOT_SLOT_CLEARED"; g_scriptEvents[251] = "LOOT_SLOT_CHANGED"; g_scriptEvents[252] = "LOOT_CLOSED"; - g_scriptEvents[253] = "PLAYER_LOGIN"; - g_scriptEvents[254] = "PLAYER_LOGOUT"; - g_scriptEvents[255] = "PLAYER_ENTERING_WORLD"; + g_scriptEvents[SCRIPT_PLAYER_LOGIN] = "PLAYER_LOGIN"; + g_scriptEvents[SCRIPT_PLAYER_LOGOUT] = "PLAYER_LOGOUT"; + g_scriptEvents[SCRIPT_PLAYER_ENTERING_WORLD] = "PLAYER_ENTERING_WORLD"; g_scriptEvents[256] = "PLAYER_LEAVING_WORLD"; g_scriptEvents[257] = "PLAYER_ALIVE"; g_scriptEvents[258] = "PLAYER_DEAD"; diff --git a/src/ui/game/Types.hpp b/src/ui/game/Types.hpp new file mode 100644 index 0000000..9609829 --- /dev/null +++ b/src/ui/game/Types.hpp @@ -0,0 +1,12 @@ +#ifndef UI_GAME_TYPES_HPP +#define UI_GAME_TYPES_HPP + +enum SCRIPTEVENT { + // TODO + SCRIPT_PLAYER_LOGIN = 253, + SCRIPT_PLAYER_LOGOUT = 254, + SCRIPT_PLAYER_ENTERING_WORLD = 255, + // TODO +}; + +#endif From c7179026fc7b8932a58abf5907dabf41b6e97727 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 22:09:25 -0600 Subject: [PATCH 189/269] feat(object): implement SkipPartialObjectUpdate --- src/object/client/Mirror.cpp | 17 +++++++++++++++++ src/object/client/Mirror.hpp | 2 ++ src/object/client/Util.cpp | 5 ----- src/object/client/Util.hpp | 2 -- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/object/client/Mirror.cpp b/src/object/client/Mirror.cpp index 75554a5..f07937a 100644 --- a/src/object/client/Mirror.cpp +++ b/src/object/client/Mirror.cpp @@ -229,3 +229,20 @@ int32_t FillInPartialObjectData(CGObject_C* object, WOWGUID guid, CDataStore* ms return 1; } + +int32_t SkipPartialObjectUpdate(CDataStore* msg) { + uint8_t changeMaskCount; + uint32_t changeMasks[MAX_CHANGE_MASKS]; + if (!ExtractDirtyMasks(msg, &changeMaskCount, changeMasks)) { + return 0; + } + + for (int32_t block = 0; block < changeMaskCount * 32; block++) { + if (IsMaskBitSet(changeMasks, block)) { + uint32_t blockValue; + msg->Get(blockValue); + } + } + + return 1; +} diff --git a/src/object/client/Mirror.hpp b/src/object/client/Mirror.hpp index c094dae..7af7b38 100644 --- a/src/object/client/Mirror.hpp +++ b/src/object/client/Mirror.hpp @@ -11,4 +11,6 @@ int32_t CallMirrorHandlers(CDataStore* msg, bool a2, WOWGUID guid); int32_t FillInPartialObjectData(CGObject_C* object, WOWGUID guid, CDataStore* msg, bool forFullUpdate, bool zeroZeroBits); +int32_t SkipPartialObjectUpdate(CDataStore* msg); + #endif diff --git a/src/object/client/Util.cpp b/src/object/client/Util.cpp index 1d6f076..e560a15 100644 --- a/src/object/client/Util.cpp +++ b/src/object/client/Util.cpp @@ -164,8 +164,3 @@ void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate) } } } - -int32_t SkipPartialObjectUpdate(CDataStore* msg) { - // TODO - return 0; -} diff --git a/src/object/client/Util.hpp b/src/object/client/Util.hpp index 9a833ec..b39c6db 100644 --- a/src/object/client/Util.hpp +++ b/src/object/client/Util.hpp @@ -20,6 +20,4 @@ void HandleObjectOutOfRangePass2(CGObject_C* object); void InitObject(CGObject_C* object, uint32_t time, CClientObjCreate& objCreate); -int32_t SkipPartialObjectUpdate(CDataStore* msg); - #endif From 61303b51a23074044c133f333f7d9157e27c36a8 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 22:09:52 -0600 Subject: [PATCH 190/269] feat(object): stub CGPlayer_C::PostInitActivePlayer --- src/object/client/CGPlayer_C.cpp | 16 ++++++++++++++++ src/object/client/CGPlayer_C.hpp | 2 ++ 2 files changed, 18 insertions(+) diff --git a/src/object/client/CGPlayer_C.cpp b/src/object/client/CGPlayer_C.cpp index 34ccb52..8e39a18 100644 --- a/src/object/client/CGPlayer_C.cpp +++ b/src/object/client/CGPlayer_C.cpp @@ -34,6 +34,18 @@ void CGPlayer_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) this->CGUnit_C::PostInit(time, init, a4); // TODO + + if (this->GetGUID() == ClntObjMgrGetActivePlayer()) { + this->PostInitActivePlayer(); + } else { + this->UpdatePartyMemberState(); + } + + // TODO +} + +void CGPlayer_C::PostInitActivePlayer() { + // TODO } void CGPlayer_C::SetStorage(uint32_t* storage, uint32_t* saved) { @@ -43,6 +55,10 @@ void CGPlayer_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->m_playerSaved = &saved[CGPlayer::GetBaseOffsetSaved()]; } +void CGPlayer_C::UpdatePartyMemberState() { + // TODO +} + uint32_t Player_C_GetDisplayId(uint32_t race, uint32_t sex) { STORM_ASSERT(sex < UNITSEX_LAST); diff --git a/src/object/client/CGPlayer_C.hpp b/src/object/client/CGPlayer_C.hpp index 20813a8..2af9cef 100644 --- a/src/object/client/CGPlayer_C.hpp +++ b/src/object/client/CGPlayer_C.hpp @@ -18,7 +18,9 @@ class CGPlayer_C : public CGUnit_C, public CGPlayer { uint32_t GetActiveNextLevelXP() const; uint32_t GetActiveXP() const; void PostInit(uint32_t time, const CClientObjCreate& init, bool a4); + void PostInitActivePlayer(); void SetStorage(uint32_t* storage, uint32_t* saved); + void UpdatePartyMemberState(); }; uint32_t Player_C_GetDisplayId(uint32_t race, uint32_t sex); From 5b88141acb57ff96dbd6c9dd76a449d0cd3e113d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 22:22:01 -0600 Subject: [PATCH 191/269] feat(object): add ClntObjMgrGetPlayerType --- src/object/Types.hpp | 5 +++++ src/object/client/ClntObjMgr.hpp | 4 ++++ src/object/client/ObjMgr.cpp | 6 +++++- src/object/client/ObjMgr.hpp | 2 ++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/object/Types.hpp b/src/object/Types.hpp index 952e619..9ce56c2 100644 --- a/src/object/Types.hpp +++ b/src/object/Types.hpp @@ -78,6 +78,11 @@ enum OUT_OF_RANGE_TYPE { OUT_OF_RANGE_2 = 2, }; +enum PLAYER_TYPE { + PLAYER_NORMAL = 0, + PLAYER_BOT = 1, +}; + enum SHEATHE_TYPE { SHEATHE_0 = 0, SHEATHE_1 = 1, diff --git a/src/object/client/ClntObjMgr.hpp b/src/object/client/ClntObjMgr.hpp index 30f8c97..6415fbd 100644 --- a/src/object/client/ClntObjMgr.hpp +++ b/src/object/client/ClntObjMgr.hpp @@ -18,8 +18,12 @@ class ClntObjMgr { STORM_EXPLICIT_LIST(CGObject_C, m_link) m_reenabledObjects; // TODO WOWGUID m_activePlayer = 0; + PLAYER_TYPE m_type; uint32_t m_mapID = 0; ClientConnection* m_net = nullptr; + + // Member functions + ClntObjMgr(PLAYER_TYPE type) : m_type(type) {}; }; #endif diff --git a/src/object/client/ObjMgr.cpp b/src/object/client/ObjMgr.cpp index c817841..bd1c860 100644 --- a/src/object/client/ObjMgr.cpp +++ b/src/object/client/ObjMgr.cpp @@ -141,6 +141,10 @@ uint32_t ClntObjMgrGetMapID() { return s_curMgr->m_mapID; } +PLAYER_TYPE ClntObjMgrGetPlayerType() { + return s_curMgr->m_type; +} + void ClntObjMgrInitializeShared() { if (!s_heapsAllocated) { for (int32_t i = ID_ITEM; i < NUM_CLIENT_OBJECT_TYPES; i++) { @@ -158,7 +162,7 @@ void ClntObjMgrInitializeShared() { void ClntObjMgrInitializeStd(uint32_t mapID) { // TODO last instance time - auto mgr = STORM_NEW(ClntObjMgr); + auto mgr = STORM_NEW(ClntObjMgr)(PLAYER_NORMAL); g_clientConnection->SetObjMgr(mgr); mgr->m_net = g_clientConnection; diff --git a/src/object/client/ObjMgr.hpp b/src/object/client/ObjMgr.hpp index f467d9d..d50f0a1 100644 --- a/src/object/client/ObjMgr.hpp +++ b/src/object/client/ObjMgr.hpp @@ -16,6 +16,8 @@ ClntObjMgr* ClntObjMgrGetCurrent(); uint32_t ClntObjMgrGetMapID(); +PLAYER_TYPE ClntObjMgrGetPlayerType(); + void ClntObjMgrInitializeShared(); void ClntObjMgrInitializeStd(uint32_t mapID); From 7dcc33bcb42194029925c09e4faf6852ad2d6e09 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 5 Feb 2026 22:22:33 -0600 Subject: [PATCH 192/269] feat(object): partially implement CGPlayer_C::PostInitActivePlayer --- src/object/client/CGPlayer_C.cpp | 20 +++++++++++++++++++- src/ui/game/ScriptEvents.cpp | 2 +- src/ui/game/Types.hpp | 2 ++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/object/client/CGPlayer_C.cpp b/src/object/client/CGPlayer_C.cpp index 8e39a18..26b5aa3 100644 --- a/src/object/client/CGPlayer_C.cpp +++ b/src/object/client/CGPlayer_C.cpp @@ -1,7 +1,9 @@ #include "object/client/CGPlayer_C.hpp" #include "db/Db.hpp" -#include "object/client/ObjMgr.hpp" #include "object/Types.hpp" +#include "object/client/ObjMgr.hpp" +#include "ui/FrameScript.hpp" +#include "ui/Game.hpp" #include CGPlayer_C::CGPlayer_C(uint32_t time, CClientObjCreate& objCreate) : CGUnit_C(time, objCreate) { @@ -46,6 +48,22 @@ void CGPlayer_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) void CGPlayer_C::PostInitActivePlayer() { // TODO + + if (ClntObjMgrGetPlayerType() == PLAYER_NORMAL) { + // TODO + + FrameScript_SignalEvent(SCRIPT_ACTIONBAR_SLOT_CHANGED, "%d", 0); + } + + // TODO + + if (ClntObjMgrGetPlayerType() == PLAYER_NORMAL) { + // TODO + + CGGameUI::EnterWorld(); + } + + // TODO } void CGPlayer_C::SetStorage(uint32_t* storage, uint32_t* saved) { diff --git a/src/ui/game/ScriptEvents.cpp b/src/ui/game/ScriptEvents.cpp index b3aa7d4..c3846a3 100644 --- a/src/ui/game/ScriptEvents.cpp +++ b/src/ui/game/ScriptEvents.cpp @@ -1057,7 +1057,7 @@ void ScriptEventsInitialize() { g_scriptEvents[173] = "ACTIONBAR_SHOWGRID"; g_scriptEvents[174] = "ACTIONBAR_HIDEGRID"; g_scriptEvents[175] = "ACTIONBAR_PAGE_CHANGED"; - g_scriptEvents[176] = "ACTIONBAR_SLOT_CHANGED"; + g_scriptEvents[SCRIPT_ACTIONBAR_SLOT_CHANGED] = "ACTIONBAR_SLOT_CHANGED"; g_scriptEvents[177] = "ACTIONBAR_UPDATE_STATE"; g_scriptEvents[178] = "ACTIONBAR_UPDATE_USABLE"; g_scriptEvents[179] = "ACTIONBAR_UPDATE_COOLDOWN"; diff --git a/src/ui/game/Types.hpp b/src/ui/game/Types.hpp index 9609829..be7891f 100644 --- a/src/ui/game/Types.hpp +++ b/src/ui/game/Types.hpp @@ -2,6 +2,8 @@ #define UI_GAME_TYPES_HPP enum SCRIPTEVENT { + // TODO + SCRIPT_ACTIONBAR_SLOT_CHANGED = 176, // TODO SCRIPT_PLAYER_LOGIN = 253, SCRIPT_PLAYER_LOGOUT = 254, From 8c850c0bd5935a6ad81c2a8423f3984085351a98 Mon Sep 17 00:00:00 2001 From: Tristan Cormier Date: Thu, 5 Feb 2026 11:32:16 -0500 Subject: [PATCH 193/269] feat(glue): implement Script_IsShiftKeyDown --- src/glue/GlueScript.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/glue/GlueScript.cpp b/src/glue/GlueScript.cpp index 1e8cd23..3c76156 100644 --- a/src/glue/GlueScript.cpp +++ b/src/glue/GlueScript.cpp @@ -17,7 +17,13 @@ #include int32_t Script_IsShiftKeyDown(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (EventIsKeyDown(KEY_LSHIFT) || EventIsKeyDown(KEY_RSHIFT)) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + + return 1; } int32_t Script_GetBuildInfo(lua_State* L) { From c133d37705799b201ab7437edaa487c5cd1f1b3b Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 6 Feb 2026 06:23:28 -0600 Subject: [PATCH 194/269] feat(db): add PaperDollItemFrameRec --- src/db/Db.cpp | 2 ++ src/db/Db.hpp | 2 ++ src/db/rec/PaperDollItemFrameRec.cpp | 51 ++++++++++++++++++++++++++++ src/db/rec/PaperDollItemFrameRec.hpp | 25 ++++++++++++++ 4 files changed, 80 insertions(+) create mode 100644 src/db/rec/PaperDollItemFrameRec.cpp create mode 100644 src/db/rec/PaperDollItemFrameRec.hpp diff --git a/src/db/Db.cpp b/src/db/Db.cpp index ea8a8d1..5d08340 100644 --- a/src/db/Db.cpp +++ b/src/db/Db.cpp @@ -18,6 +18,7 @@ WowClientDB g_factionTemplateDB; WowClientDB g_itemDisplayInfoDB; WowClientDB g_itemVisualsDB; WowClientDB g_mapDB; +WowClientDB g_paperDollItemFrameDB; WowClientDB g_soundEntriesDB; WowClientDB g_soundEntriesAdvancedDB; @@ -43,6 +44,7 @@ void StaticDBLoadAll(void (*loadFn)(WowClientDB_Base*, const char*, int32_t)) { loadFn(&g_itemDisplayInfoDB, __FILE__, __LINE__); loadFn(&g_itemVisualsDB, __FILE__, __LINE__); loadFn(&g_mapDB, __FILE__, __LINE__); + loadFn(&g_paperDollItemFrameDB, __FILE__, __LINE__); loadFn(&g_soundEntriesDB, __FILE__, __LINE__); loadFn(&g_soundEntriesAdvancedDB, __FILE__, __LINE__); }; diff --git a/src/db/Db.hpp b/src/db/Db.hpp index 75421d9..2eddf58 100644 --- a/src/db/Db.hpp +++ b/src/db/Db.hpp @@ -19,6 +19,7 @@ #include "db/rec/ItemDisplayInfoRec.hpp" #include "db/rec/ItemVisualsRec.hpp" #include "db/rec/MapRec.hpp" +#include "db/rec/PaperDollItemFrameRec.hpp" #include "db/rec/SoundEntriesRec.hpp" #include "db/rec/SoundEntriesAdvancedRec.hpp" @@ -39,6 +40,7 @@ extern WowClientDB g_factionTemplateDB; extern WowClientDB g_itemDisplayInfoDB; extern WowClientDB g_itemVisualsDB; extern WowClientDB g_mapDB; +extern WowClientDB g_paperDollItemFrameDB; extern WowClientDB g_soundEntriesDB; extern WowClientDB g_soundEntriesAdvancedDB; diff --git a/src/db/rec/PaperDollItemFrameRec.cpp b/src/db/rec/PaperDollItemFrameRec.cpp new file mode 100644 index 0000000..87a0d5b --- /dev/null +++ b/src/db/rec/PaperDollItemFrameRec.cpp @@ -0,0 +1,51 @@ +// DO NOT EDIT: generated by whoa-autocode +#include "db/rec/PaperDollItemFrameRec.hpp" +#include "util/Locale.hpp" +#include "util/SFile.hpp" + +const char* PaperDollItemFrameRec::GetFilename() { + return "DBFilesClient\\PaperDollItemFrame.dbc"; +} + +uint32_t PaperDollItemFrameRec::GetNumColumns() { + return 3; +} + +uint32_t PaperDollItemFrameRec::GetRowSize() { + return 12; +} + +bool PaperDollItemFrameRec::NeedIDAssigned() { + return true; +} + +int32_t PaperDollItemFrameRec::GetID() { + return this->m_generatedID; +} + +void PaperDollItemFrameRec::SetID(int32_t id) { + this->m_generatedID = id; +} + +bool PaperDollItemFrameRec::Read(SFile* f, const char* stringBuffer) { + uint32_t itemButtonNameOfs; + uint32_t slotIconOfs; + + if ( + !SFile::Read(f, &itemButtonNameOfs, sizeof(uint32_t), nullptr, nullptr, nullptr) + || !SFile::Read(f, &slotIconOfs, sizeof(uint32_t), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_slotNumber, sizeof(this->m_slotNumber), nullptr, nullptr, nullptr) + ) { + return false; + } + + if (stringBuffer) { + this->m_itemButtonName = &stringBuffer[itemButtonNameOfs]; + this->m_slotIcon = &stringBuffer[slotIconOfs]; + } else { + this->m_itemButtonName = ""; + this->m_slotIcon = ""; + } + + return true; +} diff --git a/src/db/rec/PaperDollItemFrameRec.hpp b/src/db/rec/PaperDollItemFrameRec.hpp new file mode 100644 index 0000000..7ecc87d --- /dev/null +++ b/src/db/rec/PaperDollItemFrameRec.hpp @@ -0,0 +1,25 @@ +// DO NOT EDIT: generated by whoa-autocode +#ifndef DB_REC_PAPER_DOLL_ITEM_FRAME_REC_HPP +#define DB_REC_PAPER_DOLL_ITEM_FRAME_REC_HPP + +#include + +class SFile; + +class PaperDollItemFrameRec { + public: + const char* m_itemButtonName; + const char* m_slotIcon; + int32_t m_slotNumber; + int32_t m_generatedID; + + static const char* GetFilename(); + static uint32_t GetNumColumns(); + static uint32_t GetRowSize(); + static bool NeedIDAssigned(); + int32_t GetID(); + void SetID(int32_t id); + bool Read(SFile* f, const char* stringBuffer); +}; + +#endif From 4bf88801ed3a44842224c9061630db9c9ae504e7 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 6 Feb 2026 06:43:00 -0600 Subject: [PATCH 195/269] feat(ui): implement Script_GetInventorySlotInfo --- src/ui/game/CharacterInfoScript.cpp | 39 ++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/ui/game/CharacterInfoScript.cpp b/src/ui/game/CharacterInfoScript.cpp index 1b70462..295bbd7 100644 --- a/src/ui/game/CharacterInfoScript.cpp +++ b/src/ui/game/CharacterInfoScript.cpp @@ -1,11 +1,48 @@ #include "ui/game/CharacterInfoScript.hpp" +#include "db/Db.hpp" #include "ui/FrameScript.hpp" +#include "util/Lua.hpp" #include "util/Unimplemented.hpp" namespace { int32_t Script_GetInventorySlotInfo(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isstring(L, 1)) { + luaL_error(L, "Invalid inventory slot in GetInventorySlotInfo"); + return 0; + } + + auto slotName = lua_tostring(L, 1); + + PaperDollItemFrameRec* slotRec = nullptr; + for (int32_t i = 0; i < g_paperDollItemFrameDB.GetNumRecords(); i++) { + auto paperDollItemFrameRec = g_paperDollItemFrameDB.GetRecordByIndex(i); + + if (paperDollItemFrameRec && !SStrCmpI(slotName, paperDollItemFrameRec->m_itemButtonName)) { + slotRec = paperDollItemFrameRec; + break; + } + } + + if (!slotRec) { + luaL_error(L, "Invalid inventory slot in GetInventorySlotInfo"); + return 0; + } + + // id + lua_pushnumber(L, slotRec->m_slotNumber); + + // textureName + lua_pushstring(L, slotRec->m_slotIcon); + + // checkRelic + if (slotRec->m_slotNumber == EQUIPPED_LAST) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + + return 3; } int32_t Script_GetInventoryItemsForSlot(lua_State* L) { From 68ad71090e51a3331bdcf9b26e282b2ea8d6d798 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 6 Feb 2026 10:36:54 -0600 Subject: [PATCH 196/269] feat(object): simplify getters in CGPlayer_C --- src/object/client/CGPlayer_C.cpp | 8 ++++---- src/object/client/CGPlayer_C.hpp | 4 ++-- src/ui/game/ScriptEvents.cpp | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/object/client/CGPlayer_C.cpp b/src/object/client/CGPlayer_C.cpp index 26b5aa3..87d6b1a 100644 --- a/src/object/client/CGPlayer_C.cpp +++ b/src/object/client/CGPlayer_C.cpp @@ -14,20 +14,20 @@ CGPlayer_C::~CGPlayer_C() { // TODO } -uint32_t CGPlayer_C::GetActiveNextLevelXP() const { +uint32_t CGPlayer_C::GetNextLevelXP() const { if (this->GetGUID() != ClntObjMgrGetActivePlayer()) { return 0; } - return this->GetNextLevelXP(); + return this->CGPlayer::GetNextLevelXP(); } -uint32_t CGPlayer_C::GetActiveXP() const { +uint32_t CGPlayer_C::GetXP() const { if (this->GetGUID() != ClntObjMgrGetActivePlayer()) { return 0; } - return this->GetXP(); + return this->CGPlayer::GetXP(); } void CGPlayer_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { diff --git a/src/object/client/CGPlayer_C.hpp b/src/object/client/CGPlayer_C.hpp index 2af9cef..d58b7a0 100644 --- a/src/object/client/CGPlayer_C.hpp +++ b/src/object/client/CGPlayer_C.hpp @@ -15,8 +15,8 @@ class CGPlayer_C : public CGUnit_C, public CGPlayer { // Public member functions CGPlayer_C(uint32_t time, CClientObjCreate& objCreate); - uint32_t GetActiveNextLevelXP() const; - uint32_t GetActiveXP() const; + uint32_t GetNextLevelXP() const; + uint32_t GetXP() const; void PostInit(uint32_t time, const CClientObjCreate& init, bool a4); void PostInitActivePlayer(); void SetStorage(uint32_t* storage, uint32_t* saved); diff --git a/src/ui/game/ScriptEvents.cpp b/src/ui/game/ScriptEvents.cpp index c3846a3..89d08bf 100644 --- a/src/ui/game/ScriptEvents.cpp +++ b/src/ui/game/ScriptEvents.cpp @@ -189,7 +189,7 @@ int32_t Script_UnitXP(lua_State* L) { float xp = 0.0f; if (unit && unit->IsA(TYPE_PLAYER)) { - xp = static_cast(unit)->GetActiveXP(); + xp = static_cast(unit)->GetXP(); } lua_pushnumber(L, xp); @@ -209,7 +209,7 @@ int32_t Script_UnitXPMax(lua_State* L) { float xpMax = 0.0f; if (unit && unit->IsA(TYPE_PLAYER)) { - xpMax = static_cast(unit)->GetActiveNextLevelXP(); + xpMax = static_cast(unit)->GetNextLevelXP(); } lua_pushnumber(L, xpMax); From 5ee4c54827832f3bc825c7a8055b4e6f9d5b25c0 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 6 Feb 2026 14:04:52 -0600 Subject: [PATCH 197/269] feat(ui): implement Script_GetMoney --- src/object/client/CGPlayer.cpp | 4 ++++ src/object/client/CGPlayer.hpp | 1 + src/object/client/CGPlayer_C.cpp | 14 ++++++++++++++ src/object/client/CGPlayer_C.hpp | 4 ++++ src/ui/game/ScriptEvents.cpp | 10 +++++++++- 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/object/client/CGPlayer.cpp b/src/object/client/CGPlayer.cpp index 568baf3..6306a01 100644 --- a/src/object/client/CGPlayer.cpp +++ b/src/object/client/CGPlayer.cpp @@ -41,6 +41,10 @@ uint32_t CGPlayer::TotalRemoteFieldsSaved() { return CGPlayer::GetBaseOffsetSaved() + 173; } +uint32_t CGPlayer::GetMoney() const { + return this->Player()->coinage; +} + uint32_t CGPlayer::GetNextLevelXP() const { return this->Player()->nextLevelXP; } diff --git a/src/object/client/CGPlayer.hpp b/src/object/client/CGPlayer.hpp index 3d18372..8f2c274 100644 --- a/src/object/client/CGPlayer.hpp +++ b/src/object/client/CGPlayer.hpp @@ -149,6 +149,7 @@ class CGPlayer { static uint32_t TotalRemoteFieldsSaved(); // Public member functions + uint32_t GetMoney() const; uint32_t GetNextLevelXP() const; uint32_t GetXP() const; diff --git a/src/object/client/CGPlayer_C.cpp b/src/object/client/CGPlayer_C.cpp index 87d6b1a..805936a 100644 --- a/src/object/client/CGPlayer_C.cpp +++ b/src/object/client/CGPlayer_C.cpp @@ -6,6 +6,12 @@ #include "ui/Game.hpp" #include +CGPlayer_C* CGPlayer_C::GetActivePtr() { + return static_cast( + ClntObjMgrObjectPtr(ClntObjMgrGetActivePlayer(), TYPE_PLAYER, __FILE__, __LINE__) + ); +} + CGPlayer_C::CGPlayer_C(uint32_t time, CClientObjCreate& objCreate) : CGUnit_C(time, objCreate) { // TODO } @@ -14,6 +20,14 @@ CGPlayer_C::~CGPlayer_C() { // TODO } +uint32_t CGPlayer_C::GetMoney() const { + if (this->GetGUID() != ClntObjMgrGetActivePlayer()) { + return 0; + } + + return this->CGPlayer::GetMoney(); +} + uint32_t CGPlayer_C::GetNextLevelXP() const { if (this->GetGUID() != ClntObjMgrGetActivePlayer()) { return 0; diff --git a/src/object/client/CGPlayer_C.hpp b/src/object/client/CGPlayer_C.hpp index d58b7a0..6e6a0eb 100644 --- a/src/object/client/CGPlayer_C.hpp +++ b/src/object/client/CGPlayer_C.hpp @@ -10,11 +10,15 @@ class CreatureModelDataRec; class CGPlayer_C : public CGUnit_C, public CGPlayer { public: + // Public static functions + static CGPlayer_C* GetActivePtr(); + // Virtual public member functions virtual ~CGPlayer_C(); // Public member functions CGPlayer_C(uint32_t time, CClientObjCreate& objCreate); + uint32_t GetMoney() const; uint32_t GetNextLevelXP() const; uint32_t GetXP() const; void PostInit(uint32_t time, const CClientObjCreate& init, bool a4); diff --git a/src/ui/game/ScriptEvents.cpp b/src/ui/game/ScriptEvents.cpp index 89d08bf..a607076 100644 --- a/src/ui/game/ScriptEvents.cpp +++ b/src/ui/game/ScriptEvents.cpp @@ -282,7 +282,15 @@ int32_t Script_UnitLevel(lua_State* L) { } int32_t Script_GetMoney(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto player = CGPlayer_C::GetActivePtr(); + + if (player) { + lua_pushnumber(L, player->GetMoney()); + } else { + lua_pushnumber(L, 0.0f); + } + + return 1; } int32_t Script_GetHonorCurrency(lua_State* L) { From cda8fff0963d74a546b50085a31702ac1f4cbcb1 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 6 Feb 2026 15:35:17 -0600 Subject: [PATCH 198/269] feat(ui): implement Script_GetCursorMoney --- src/ui/game/CGGameUI.cpp | 5 +++++ src/ui/game/CGGameUI.hpp | 2 ++ src/ui/game/GameScript.cpp | 5 ++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 8107419..91e0b16 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -25,6 +25,7 @@ #include WOWGUID CGGameUI::s_currentObjectTrack; +uint32_t CGGameUI::s_cursorMoney; CScriptObject* CGGameUI::s_gameTooltip; bool CGGameUI::s_inWorld; WOWGUID CGGameUI::s_lockedTarget; @@ -94,6 +95,10 @@ WOWGUID& CGGameUI::GetCurrentObjectTrack() { return CGGameUI::s_currentObjectTrack; } +uint32_t CGGameUI::GetCursorMoney() { + return CGGameUI::s_cursorMoney; +} + WOWGUID& CGGameUI::GetLockedTarget() { return CGGameUI::s_lockedTarget; } diff --git a/src/ui/game/CGGameUI.hpp b/src/ui/game/CGGameUI.hpp index 6b7aaab..7546629 100644 --- a/src/ui/game/CGGameUI.hpp +++ b/src/ui/game/CGGameUI.hpp @@ -15,6 +15,7 @@ class CGGameUI { // Static functions static void EnterWorld(); static WOWGUID& GetCurrentObjectTrack(); + static uint32_t GetCursorMoney(); static WOWGUID& GetLockedTarget(); static void Initialize(); static void InitializeGame(); @@ -25,6 +26,7 @@ class CGGameUI { private: static WOWGUID s_currentObjectTrack; + static uint32_t s_cursorMoney; static bool s_inWorld; static WOWGUID s_lockedTarget; static bool s_loggingIn; diff --git a/src/ui/game/GameScript.cpp b/src/ui/game/GameScript.cpp index 0652fba..8132635 100644 --- a/src/ui/game/GameScript.cpp +++ b/src/ui/game/GameScript.cpp @@ -3,6 +3,7 @@ #include "gx/Coordinate.hpp" #include "ui/FrameScript.hpp" #include "ui/ScriptFunctionsShared.hpp" +#include "ui/game/CGGameUI.hpp" #include "ui/simple/CSimpleTop.hpp" #include "util/StringTo.hpp" #include "util/Unimplemented.hpp" @@ -502,7 +503,9 @@ int32_t Script_ForceQuit(lua_State* L) { } int32_t Script_GetCursorMoney(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + lua_pushnumber(L, CGGameUI::GetCursorMoney()); + + return 1; } int32_t Script_DropCursorMoney(lua_State* L) { From 3366ea2c8935a21881f26b93622fd01065a7fc7e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 6 Feb 2026 22:23:27 -0600 Subject: [PATCH 199/269] feat(ui): add TradeInfoRegisterScriptFunctions --- src/ui/game/CGGameUI.cpp | 5 ++ src/ui/game/TradeInfoScript.cpp | 86 +++++++++++++++++++++++++++++++++ src/ui/game/TradeInfoScript.hpp | 6 +++ 3 files changed, 97 insertions(+) create mode 100644 src/ui/game/TradeInfoScript.cpp create mode 100644 src/ui/game/TradeInfoScript.hpp diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 91e0b16..da68b74 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -18,6 +18,7 @@ #include "ui/game/GMTicketInfoScript.hpp" #include "ui/game/GameScript.hpp" #include "ui/game/ScriptEvents.hpp" +#include "ui/game/TradeInfoScript.hpp" #include "ui/game/Types.hpp" #include "ui/game/UIBindingsScript.hpp" #include "ui/simple/CSimpleTop.hpp" @@ -60,6 +61,10 @@ void LoadScriptFunctions() { // TODO + TradeInfoRegisterScriptFunctions(); + + // TODO + BattlefieldInfoRegisterScriptFunctions(); // TODO diff --git a/src/ui/game/TradeInfoScript.cpp b/src/ui/game/TradeInfoScript.cpp new file mode 100644 index 0000000..6de2d43 --- /dev/null +++ b/src/ui/game/TradeInfoScript.cpp @@ -0,0 +1,86 @@ +#include "ui/game/TradeInfoScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t Script_CloseTrade(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ClickTradeButton(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ClickTargetTradeButton(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetTradeTargetItemInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetTradeTargetItemLink(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetTradePlayerItemInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetTradePlayerItemLink(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_AcceptTrade(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CancelTradeAccept(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPlayerTradeMoney(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetTargetTradeMoney(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_PickupTradeMoney(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_AddTradeMoney(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetTradeMoney(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +static FrameScript_Method s_ScriptFunctions[] = { + { "CloseTrade", &Script_CloseTrade }, + { "ClickTradeButton", &Script_ClickTradeButton }, + { "ClickTargetTradeButton", &Script_ClickTargetTradeButton }, + { "GetTradeTargetItemInfo", &Script_GetTradeTargetItemInfo }, + { "GetTradeTargetItemLink", &Script_GetTradeTargetItemLink }, + { "GetTradePlayerItemInfo", &Script_GetTradePlayerItemInfo }, + { "GetTradePlayerItemLink", &Script_GetTradePlayerItemLink }, + { "AcceptTrade", &Script_AcceptTrade }, + { "CancelTradeAccept", &Script_CancelTradeAccept }, + { "GetPlayerTradeMoney", &Script_GetPlayerTradeMoney }, + { "GetTargetTradeMoney", &Script_GetTargetTradeMoney }, + { "PickupTradeMoney", &Script_PickupTradeMoney }, + { "AddTradeMoney", &Script_AddTradeMoney }, + { "SetTradeMoney", &Script_SetTradeMoney }, +}; + +void TradeInfoRegisterScriptFunctions() { + for (auto& func : s_ScriptFunctions) { + FrameScript_RegisterFunction(func.name, func.method); + } +} diff --git a/src/ui/game/TradeInfoScript.hpp b/src/ui/game/TradeInfoScript.hpp new file mode 100644 index 0000000..fbc95d9 --- /dev/null +++ b/src/ui/game/TradeInfoScript.hpp @@ -0,0 +1,6 @@ +#ifndef UI_GAME_TRADE_INFO_SCRIPT_HPP +#define UI_GAME_TRADE_INFO_SCRIPT_HPP + +void TradeInfoRegisterScriptFunctions(); + +#endif From 72d2c3b1a23f4ea46bbfd447c37c853eff156765 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 6 Feb 2026 22:29:43 -0600 Subject: [PATCH 200/269] feat(ui): implement Script_GetPlayerTradeMoney --- src/ui/game/CGTradeInfo.cpp | 12 ++++++++++++ src/ui/game/CGTradeInfo.hpp | 19 +++++++++++++++++++ src/ui/game/TradeInfoScript.cpp | 10 +++++++++- 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/ui/game/CGTradeInfo.cpp create mode 100644 src/ui/game/CGTradeInfo.hpp diff --git a/src/ui/game/CGTradeInfo.cpp b/src/ui/game/CGTradeInfo.cpp new file mode 100644 index 0000000..6eb5e49 --- /dev/null +++ b/src/ui/game/CGTradeInfo.cpp @@ -0,0 +1,12 @@ +#include "ui/game/CGTradeInfo.hpp" + +uint32_t CGTradeInfo::s_playerMoney; +WOWGUID CGTradeInfo::s_tradingPlayer; + +uint32_t CGTradeInfo::GetPlayerTradeMoney() { + return CGTradeInfo::s_playerMoney; +} + +WOWGUID CGTradeInfo::GetTradePartner() { + return CGTradeInfo::s_tradingPlayer; +} diff --git a/src/ui/game/CGTradeInfo.hpp b/src/ui/game/CGTradeInfo.hpp new file mode 100644 index 0000000..5ae17b5 --- /dev/null +++ b/src/ui/game/CGTradeInfo.hpp @@ -0,0 +1,19 @@ +#ifndef UI_GAME_C_G_TRADE_INFO_HPP +#define UI_GAME_C_G_TRADE_INFO_HPP + +#include "util/GUID.hpp" +#include + +class CGTradeInfo { + public: + // Public static functions + static uint32_t GetPlayerTradeMoney(); + static WOWGUID GetTradePartner(); + + private: + // Private static variables + static uint32_t s_playerMoney; + static WOWGUID s_tradingPlayer; +}; + +#endif diff --git a/src/ui/game/TradeInfoScript.cpp b/src/ui/game/TradeInfoScript.cpp index 6de2d43..185c95d 100644 --- a/src/ui/game/TradeInfoScript.cpp +++ b/src/ui/game/TradeInfoScript.cpp @@ -1,5 +1,7 @@ #include "ui/game/TradeInfoScript.hpp" #include "ui/FrameScript.hpp" +#include "ui/game/CGTradeInfo.hpp" +#include "util/Lua.hpp" #include "util/Unimplemented.hpp" namespace { @@ -41,7 +43,13 @@ int32_t Script_CancelTradeAccept(lua_State* L) { } int32_t Script_GetPlayerTradeMoney(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (CGTradeInfo::GetTradePartner()) { + lua_pushnumber(L, CGTradeInfo::GetPlayerTradeMoney()); + } else { + lua_pushnumber(L, 0); + } + + return 1; } int32_t Script_GetTargetTradeMoney(lua_State* L) { From 43895197af5dbc3c3f90209a5bba8056ba74478b Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 8 Feb 2026 06:58:15 -0600 Subject: [PATCH 201/269] feat(ui): implement Script_SetCVar --- src/ui/game/GameScript.cpp | 37 +++++++++++++++++++++++++++++++++++- src/ui/game/ScriptEvents.cpp | 2 +- src/ui/game/Types.hpp | 2 ++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/ui/game/GameScript.cpp b/src/ui/game/GameScript.cpp index 8132635..9fe3ce3 100644 --- a/src/ui/game/GameScript.cpp +++ b/src/ui/game/GameScript.cpp @@ -4,6 +4,7 @@ #include "ui/FrameScript.hpp" #include "ui/ScriptFunctionsShared.hpp" #include "ui/game/CGGameUI.hpp" +#include "ui/game/Types.hpp" #include "ui/simple/CSimpleTop.hpp" #include "util/StringTo.hpp" #include "util/Unimplemented.hpp" @@ -131,7 +132,41 @@ int32_t Script_GetCVarInfo(lua_State* L) { } int32_t Script_SetCVar(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isstring(L, 1)) { + luaL_error(L, "Usage: SetCVar(\"cvar\", value [, \"scriptCvar\")"); + return 0; + } + + auto varName = lua_tostring(L, 1); + auto var = CVar::LookupRegistered(varName); + + if (!var || (var->m_flags & 0x40)) { + luaL_error(L, "Couldn't find CVar named '%s'", varName); + return 0; + } + + if (var->m_flags & 0x4 || var->m_flags & 0x100) { + luaL_error(L, "\"%s\" is read-only", varName); + return 0; + } + + if (!(var->m_flags & 0x8)/* TODO || CSimpleTop::GetInstance()->dword124C */) { + auto value = lua_tostring(L, 2); + if (!value) { + value = "0"; + } + + var->Set(value, true, false, false, true); + + if (lua_isstring(L, 3)) { + auto scriptVarName = lua_tostring(L, 3); + FrameScript_SignalEvent(SCRIPT_CVAR_UPDATE, "%s%s", scriptVarName, value); + } + } else { + // TODO CGGameUI::ShowBlockedActionFeedback(nullptr, 2); + } + + return 0; } int32_t Script_GetCVar(lua_State* L) { diff --git a/src/ui/game/ScriptEvents.cpp b/src/ui/game/ScriptEvents.cpp index a607076..dc30c00 100644 --- a/src/ui/game/ScriptEvents.cpp +++ b/src/ui/game/ScriptEvents.cpp @@ -1187,7 +1187,7 @@ void ScriptEventsInitialize() { g_scriptEvents[295] = "TRAINER_UPDATE"; g_scriptEvents[296] = "TRAINER_DESCRIPTION_UPDATE"; g_scriptEvents[297] = "TRAINER_CLOSED"; - g_scriptEvents[298] = "CVAR_UPDATE"; + g_scriptEvents[SCRIPT_CVAR_UPDATE] = "CVAR_UPDATE"; g_scriptEvents[299] = "TRADE_SKILL_SHOW"; g_scriptEvents[300] = "TRADE_SKILL_UPDATE"; g_scriptEvents[301] = "TRADE_SKILL_CLOSE"; diff --git a/src/ui/game/Types.hpp b/src/ui/game/Types.hpp index be7891f..a54dce4 100644 --- a/src/ui/game/Types.hpp +++ b/src/ui/game/Types.hpp @@ -9,6 +9,8 @@ enum SCRIPTEVENT { SCRIPT_PLAYER_LOGOUT = 254, SCRIPT_PLAYER_ENTERING_WORLD = 255, // TODO + SCRIPT_CVAR_UPDATE = 298, + // TODO }; #endif From 7ec9a35b4bd3de400a9b512f652060c8004d7cbe Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 8 Feb 2026 07:16:58 -0600 Subject: [PATCH 202/269] feat(ui): implement Script_GetBonusBarOffset --- src/ui/game/ActionBarScript.cpp | 4 +++- src/ui/game/CGActionBar.cpp | 5 +++++ src/ui/game/CGActionBar.hpp | 9 ++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/ui/game/ActionBarScript.cpp b/src/ui/game/ActionBarScript.cpp index 14f9f95..14bd210 100644 --- a/src/ui/game/ActionBarScript.cpp +++ b/src/ui/game/ActionBarScript.cpp @@ -83,7 +83,9 @@ int32_t Script_IsActionInRange(lua_State* L) { } int32_t Script_GetBonusBarOffset(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + lua_pushnumber(L, CGActionBar::GetBonusBarOffset()); + + return 1; } int32_t Script_GetMultiCastBarOffset(lua_State* L) { diff --git a/src/ui/game/CGActionBar.cpp b/src/ui/game/CGActionBar.cpp index 6d652cc..b85f587 100644 --- a/src/ui/game/CGActionBar.cpp +++ b/src/ui/game/CGActionBar.cpp @@ -1,4 +1,9 @@ #include "ui/game/CGActionBar.hpp" +uint32_t CGActionBar::s_bonusBarOffset; uint32_t CGActionBar::s_currentPage; uint32_t CGActionBar::s_tempPageActiveFlags; + +uint32_t CGActionBar::GetBonusBarOffset() { + return CGActionBar::s_bonusBarOffset; +} diff --git a/src/ui/game/CGActionBar.hpp b/src/ui/game/CGActionBar.hpp index ddced5b..7e33fde 100644 --- a/src/ui/game/CGActionBar.hpp +++ b/src/ui/game/CGActionBar.hpp @@ -5,9 +5,16 @@ class CGActionBar { public: - // Static variables + // Public static variables static uint32_t s_currentPage; static uint32_t s_tempPageActiveFlags; + + // Public static functions + static uint32_t GetBonusBarOffset(); + + private: + // Private static variables + static uint32_t s_bonusBarOffset; }; #endif From 99a95e9db44e152c07ce6059ef71c64c301df6f3 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 8 Feb 2026 13:01:55 -0600 Subject: [PATCH 203/269] feat(ui): add BattlenetUI_RegisterScriptFunctions --- src/ui/game/BattlenetUI.cpp | 302 ++++++++++++++++++++++++++++++++++++ src/ui/game/BattlenetUI.hpp | 6 + src/ui/game/CGGameUI.cpp | 4 +- 3 files changed, 310 insertions(+), 2 deletions(-) create mode 100644 src/ui/game/BattlenetUI.cpp create mode 100644 src/ui/game/BattlenetUI.hpp diff --git a/src/ui/game/BattlenetUI.cpp b/src/ui/game/BattlenetUI.cpp new file mode 100644 index 0000000..933ac76 --- /dev/null +++ b/src/ui/game/BattlenetUI.cpp @@ -0,0 +1,302 @@ +#include "ui/game/BattlenetUI.hpp" +#include "ui/FrameScript.hpp" +#include "util/Lua.hpp" +#include "util/Unimplemented.hpp" + +namespace BattlenetUI { + +int32_t Script_BNGetInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetNumFriends(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetFriendInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetFriendInfoByID(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetNumFriendToons(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetFriendToonInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetToonInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNRemoveFriend(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSetFriendNote(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSetSelectedFriend(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetSelectedFriend(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetNumFriendInvites(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetFriendInviteInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSendFriendInvite(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSendFriendInviteByID(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNAcceptFriendInvite(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNDeclineFriendInvite(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNReportFriendInvite(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSetAFK(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSetDND(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSetCustomMessage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetCustomMessageTable(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSetFocus(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSendWhisper(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNCreateConversation(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNInviteToConversation(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNLeaveConversation(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSendConversationMessage(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetNumConversationMembers(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetConversationMemberInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetConversationInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNListConversation(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetNumBlocked(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetBlockedInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNIsBlocked(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSetBlocked(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSetSelectedBlock(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetSelectedBlock(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetNumBlockedToons(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetBlockedToonInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNIsToonBlocked(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSetToonBlocked(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSetSelectedToonBlock(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetSelectedToonBlock(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNReportPlayer(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNConnected(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNFeaturesEnabledAndConnected(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsBNLogin(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNFeaturesEnabled(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNRequestFOFInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetNumFOF(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetFOFInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNSetMatureLanguageFilter(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetMatureLanguageFilter(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNIsSelf(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNIsFriend(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_BNGetMaxPlayersInConversation(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +static FrameScript_Method s_ScriptFunctions[] = { + { "BNGetInfo", &Script_BNGetInfo }, + { "BNGetNumFriends", &Script_BNGetNumFriends }, + { "BNGetFriendInfo", &Script_BNGetFriendInfo }, + { "BNGetFriendInfoByID", &Script_BNGetFriendInfoByID }, + { "BNGetNumFriendToons", &Script_BNGetNumFriendToons }, + { "BNGetFriendToonInfo", &Script_BNGetFriendToonInfo }, + { "BNGetToonInfo", &Script_BNGetToonInfo }, + { "BNRemoveFriend", &Script_BNRemoveFriend }, + { "BNSetFriendNote", &Script_BNSetFriendNote }, + { "BNSetSelectedFriend", &Script_BNSetSelectedFriend }, + { "BNGetSelectedFriend", &Script_BNGetSelectedFriend }, + { "BNGetNumFriendInvites", &Script_BNGetNumFriendInvites }, + { "BNGetFriendInviteInfo", &Script_BNGetFriendInviteInfo }, + { "BNSendFriendInvite", &Script_BNSendFriendInvite }, + { "BNSendFriendInviteByID", &Script_BNSendFriendInviteByID }, + { "BNAcceptFriendInvite", &Script_BNAcceptFriendInvite }, + { "BNDeclineFriendInvite", &Script_BNDeclineFriendInvite }, + { "BNReportFriendInvite", &Script_BNReportFriendInvite }, + { "BNSetAFK", &Script_BNSetAFK }, + { "BNSetDND", &Script_BNSetDND }, + { "BNSetCustomMessage", &Script_BNSetCustomMessage }, + { "BNGetCustomMessageTable", &Script_BNGetCustomMessageTable }, + { "BNSetFocus", &Script_BNSetFocus }, + { "BNSendWhisper", &Script_BNSendWhisper }, + { "BNCreateConversation", &Script_BNCreateConversation }, + { "BNInviteToConversation", &Script_BNInviteToConversation }, + { "BNLeaveConversation", &Script_BNLeaveConversation }, + { "BNSendConversationMessage", &Script_BNSendConversationMessage }, + { "BNGetNumConversationMembers", &Script_BNGetNumConversationMembers }, + { "BNGetConversationMemberInfo", &Script_BNGetConversationMemberInfo }, + { "BNGetConversationInfo", &Script_BNGetConversationInfo }, + { "BNListConversation", &Script_BNListConversation }, + { "BNGetNumBlocked", &Script_BNGetNumBlocked }, + { "BNGetBlockedInfo", &Script_BNGetBlockedInfo }, + { "BNIsBlocked", &Script_BNIsBlocked }, + { "BNSetBlocked", &Script_BNSetBlocked }, + { "BNSetSelectedBlock", &Script_BNSetSelectedBlock }, + { "BNGetSelectedBlock", &Script_BNGetSelectedBlock }, + { "BNGetNumBlockedToons", &Script_BNGetNumBlockedToons }, + { "BNGetBlockedToonInfo", &Script_BNGetBlockedToonInfo }, + { "BNIsToonBlocked", &Script_BNIsToonBlocked }, + { "BNSetToonBlocked", &Script_BNSetToonBlocked }, + { "BNSetSelectedToonBlock", &Script_BNSetSelectedToonBlock }, + { "BNGetSelectedToonBlock", &Script_BNGetSelectedToonBlock }, + { "BNReportPlayer", &Script_BNReportPlayer }, + { "BNConnected", &Script_BNConnected }, + { "BNFeaturesEnabledAndConnected", &Script_BNFeaturesEnabledAndConnected }, + { "IsBNLogin", &Script_IsBNLogin }, + { "BNFeaturesEnabled", &Script_BNFeaturesEnabled }, + { "BNRequestFOFInfo", &Script_BNRequestFOFInfo }, + { "BNGetNumFOF", &Script_BNGetNumFOF }, + { "BNGetFOFInfo", &Script_BNGetFOFInfo }, + { "BNSetMatureLanguageFilter", &Script_BNSetMatureLanguageFilter }, + { "BNGetMatureLanguageFilter", &Script_BNGetMatureLanguageFilter }, + { "BNIsSelf", &Script_BNIsSelf }, + { "BNIsFriend", &Script_BNIsFriend }, + { "BNGetMaxPlayersInConversation", &Script_BNGetMaxPlayersInConversation }, +}; + +} + +void BattlenetUI_RegisterScriptFunctions() { + for (auto& func : BattlenetUI::s_ScriptFunctions) { + FrameScript_RegisterFunction(func.name, func.method); + } +} diff --git a/src/ui/game/BattlenetUI.hpp b/src/ui/game/BattlenetUI.hpp new file mode 100644 index 0000000..3772f55 --- /dev/null +++ b/src/ui/game/BattlenetUI.hpp @@ -0,0 +1,6 @@ +#ifndef UI_GAME_BATTLENET_UI_HPP +#define UI_GAME_BATTLENET_UI_HPP + +void BattlenetUI_RegisterScriptFunctions(); + +#endif diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index da68b74..3c5db2a 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -6,6 +6,7 @@ #include "ui/Key.hpp" #include "ui/game/ActionBarScript.hpp" #include "ui/game/BattlefieldInfoScript.hpp" +#include "ui/game/BattlenetUI.hpp" #include "ui/game/CGCharacterModelBase.hpp" #include "ui/game/CGCooldown.hpp" #include "ui/game/CGDressUpModelFrame.hpp" @@ -70,8 +71,7 @@ void LoadScriptFunctions() { // TODO GMTicketInfoRegisterScriptFunctions(); - - // TODO + BattlenetUI_RegisterScriptFunctions(); } void CGGameUI::EnterWorld() { From c6ddfc0d8707223cb04486696cae6add1552444d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 8 Feb 2026 13:07:40 -0600 Subject: [PATCH 204/269] feat(ui): implement Script_IsBNLogin --- src/ui/game/BattlenetUI.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ui/game/BattlenetUI.cpp b/src/ui/game/BattlenetUI.cpp index 933ac76..20fd9c4 100644 --- a/src/ui/game/BattlenetUI.cpp +++ b/src/ui/game/BattlenetUI.cpp @@ -1,4 +1,6 @@ #include "ui/game/BattlenetUI.hpp" +#include "client/ClientServices.hpp" +#include "net/Login.hpp" #include "ui/FrameScript.hpp" #include "util/Lua.hpp" #include "util/Unimplemented.hpp" @@ -194,7 +196,13 @@ int32_t Script_BNFeaturesEnabledAndConnected(lua_State* L) { } int32_t Script_IsBNLogin(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (ClientServices::LoginConnection() && ClientServices::LoginConnection()->GetLoginServerType() == 1) { + lua_pushboolean(L, true); + } else { + lua_pushboolean(L, false); + } + + return 1; } int32_t Script_BNFeaturesEnabled(lua_State* L) { From 14d14dacb05e3887cc43964460143272db672adc Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 8 Feb 2026 13:11:45 -0600 Subject: [PATCH 205/269] feat(ui): stub Script_BNFeaturesEnabled --- src/ui/game/BattlenetUI.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/game/BattlenetUI.cpp b/src/ui/game/BattlenetUI.cpp index 20fd9c4..3a63a10 100644 --- a/src/ui/game/BattlenetUI.cpp +++ b/src/ui/game/BattlenetUI.cpp @@ -206,7 +206,10 @@ int32_t Script_IsBNLogin(lua_State* L) { } int32_t Script_BNFeaturesEnabled(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + // TODO real implementation + lua_pushboolean(L, false); + + return 1; } int32_t Script_BNRequestFOFInfo(lua_State* L) { From 4f26eeb05cc2e21945eb00f32841f2f80fb2dcf3 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 8 Feb 2026 13:18:40 -0600 Subject: [PATCH 206/269] feat(ui): stub Script_BNConnected --- src/ui/game/BattlenetUI.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/game/BattlenetUI.cpp b/src/ui/game/BattlenetUI.cpp index 3a63a10..65d430d 100644 --- a/src/ui/game/BattlenetUI.cpp +++ b/src/ui/game/BattlenetUI.cpp @@ -188,7 +188,10 @@ int32_t Script_BNReportPlayer(lua_State* L) { } int32_t Script_BNConnected(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + // TODO real implementation + lua_pushboolean(L, false); + + return 1; } int32_t Script_BNFeaturesEnabledAndConnected(lua_State* L) { From 1fd5c5c944af5209007e36912f9033ab020a9c6e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 8 Feb 2026 13:22:15 -0600 Subject: [PATCH 207/269] feat(ui): stub Script_BNFeaturesEnabledAndConnected --- src/ui/game/BattlenetUI.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/game/BattlenetUI.cpp b/src/ui/game/BattlenetUI.cpp index 65d430d..fbdad55 100644 --- a/src/ui/game/BattlenetUI.cpp +++ b/src/ui/game/BattlenetUI.cpp @@ -195,7 +195,10 @@ int32_t Script_BNConnected(lua_State* L) { } int32_t Script_BNFeaturesEnabledAndConnected(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + // TODO real implementation + lua_pushboolean(L, false); + + return 1; } int32_t Script_IsBNLogin(lua_State* L) { From fabd5888a9afe2589550ee1e4b590544488390f7 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 8 Feb 2026 20:37:45 -0600 Subject: [PATCH 208/269] feat(ui): add CGGameUI::RegisterGameCVars --- src/ui/game/CGGameUI.cpp | 46 ++++++++++++++++++++++++++++++++++++++++ src/ui/game/CGGameUI.hpp | 1 + 2 files changed, 47 insertions(+) diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 3c5db2a..08e40c7 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -1,5 +1,6 @@ #include "ui/game/CGGameUI.hpp" #include "client/Client.hpp" +#include "console/CVar.hpp" #include "object/Client.hpp" #include "ui/CScriptObject.hpp" #include "ui/FrameXML.hpp" @@ -121,6 +122,7 @@ void CGGameUI::Initialize() { LoadScriptFunctions(); ScriptEventsRegisterEvents(); + CGGameUI::RegisterGameCVars(); // TODO @@ -232,3 +234,47 @@ void CGGameUI::RegisterFrameFactories() { FrameXML_RegisterFactory("TabardModel", &CGTabardModelFrame::Create, false); FrameXML_RegisterFactory("QuestPOIFrame", &CGQuestPOIFrame::Create, false); } + +void CGGameUI::RegisterGameCVars() { + // TODO + + CVar::Register("enableCombatText", "Whether to show floating combat text", 0x10, "1", nullptr, GAME); + CVar::Register("combatTextFloatMode", "The combat text float mode", 0x10, "1", nullptr, GAME); + CVar::Register("fctCombatState", nullptr, 0x10, "0", nullptr, GAME); + CVar::Register("fctDodgeParryMiss", nullptr, 0x10, "0", nullptr, GAME); + CVar::Register("fctDamageReduction", nullptr, 0x10, "0", nullptr, GAME); + CVar::Register("fctRepChanges", nullptr, 0x10, "0", nullptr, GAME); + CVar::Register("fctReactives", nullptr, 0x10, "0", nullptr, GAME); + CVar::Register("fctFriendlyHealers", nullptr, 0x10, "0", nullptr, GAME); + CVar::Register("fctComboPoints", nullptr, 0x10, "0", nullptr, GAME); + CVar::Register("fctLowManaHealth", nullptr, 0x10, "1", nullptr, GAME); + CVar::Register("fctEnergyGains", nullptr, 0x10, "0", nullptr, GAME); + CVar::Register("fctPeriodicEnergyGains", nullptr, 0x10, "0", nullptr, GAME); + CVar::Register("fctHonorGains", nullptr, 0x10, "0", nullptr, GAME); + CVar::Register("fctAuras", nullptr, 0x10, "0", nullptr, GAME); + CVar::Register("fctAllSpellMechanics", nullptr, 0x10, "0", nullptr, GAME); + CVar::Register("fctSpellMechanics", nullptr, 0x10, "0", nullptr, GAME); + CVar::Register("fctSpellMechanicsOther", nullptr, 0x10, "0", nullptr, GAME); + + CVar::Register("xpBarText", "Whether the XP bar shows the numeric experience value", 0x10, "0", nullptr, GAME); + + CVar::Register("playerStatusText", "Whether the player portrait shows numeric health/mana values", 0x10, "0", nullptr, GAME); + CVar::Register("petStatusText", "Whether the pet portrait shows numeric health/mana values", 0x10, "0", nullptr, GAME); + CVar::Register("partyStatusText", "Whether the party portraits shows numeric health/mana values", 0x10, "0", nullptr, GAME); + CVar::Register("targetStatusText", "Whether the target portrait shows numeric health/mana values", 0x10, "0", nullptr, GAME); + CVar::Register("statusTextPercentage", "Whether numeric health/mana values are shown as raw values or percentages", 0x10, "0", nullptr, GAME); + + CVar::Register("showPartyBackground", "Show a background behind party members", 0x10, "0", nullptr, GAME); + CVar::Register("partyBackgroundOpacity", "The opacity of the party background", 0x10, "0.5", nullptr, GAME); + CVar::Register("hidePartyInRaid", "Whether to hide the party UI while in a raid", 0x10, "0", nullptr, GAME); + CVar::Register("showPartyPets", "Whether to show pets in the party UI", 0x20, "1", nullptr, GAME); + CVar::Register("showRaidRange", "Show range indicator in raid UI", 0x20, "0", nullptr, GAME); + + CVar::Register("showArenaEnemyFrames", "Show arena enemy frames while in an Arena", 0x20, "1", nullptr, GAME); + CVar::Register("showArenaEnemyCastbar", "Show the spell enemies are casting on the Arena Enemy frames", 0x20, "1", nullptr, GAME); + CVar::Register("showArenaEnemyPets", "Show the enemy team's pets on the ArenaEnemy frames", 0x20, "1", nullptr, GAME); + + CVar::Register("fullSizeFocusFrame", "Increases the size of the focus frame to that of the target frame", 0x20, "0", nullptr, GAME); + + // TODO +} diff --git a/src/ui/game/CGGameUI.hpp b/src/ui/game/CGGameUI.hpp index 7546629..74de9af 100644 --- a/src/ui/game/CGGameUI.hpp +++ b/src/ui/game/CGGameUI.hpp @@ -23,6 +23,7 @@ class CGGameUI { static int32_t IsRaidMember(const WOWGUID& guid); static int32_t IsRaidMemberOrPet(const WOWGUID& guid); static void RegisterFrameFactories(); + static void RegisterGameCVars(); private: static WOWGUID s_currentObjectTrack; From 91da4e96809743670522e59197faae6951dc0f3a Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 8 Feb 2026 21:45:31 -0600 Subject: [PATCH 209/269] feat(ui): add CLayoutFrame::SetSize --- src/ui/CLayoutFrame.cpp | 7 +++++++ src/ui/CLayoutFrame.hpp | 1 + 2 files changed, 8 insertions(+) diff --git a/src/ui/CLayoutFrame.cpp b/src/ui/CLayoutFrame.cpp index 886d776..9e7cac4 100644 --- a/src/ui/CLayoutFrame.cpp +++ b/src/ui/CLayoutFrame.cpp @@ -862,6 +862,13 @@ void CLayoutFrame::SetProtectFlag(uint32_t flag) { this->m_flags &= ~0x800; } +void CLayoutFrame::SetSize(float width, float height) { + this->m_flags &= ~0x8; + this->m_width = width; + this->m_height = height; + this->Resize(0); +} + void CLayoutFrame::SetWidth(float width) { this->m_flags &= ~0x8; this->m_width = width; diff --git a/src/ui/CLayoutFrame.hpp b/src/ui/CLayoutFrame.hpp index 53ab714..26c36d8 100644 --- a/src/ui/CLayoutFrame.hpp +++ b/src/ui/CLayoutFrame.hpp @@ -49,6 +49,7 @@ class CLayoutFrame { virtual bool SetLayoutScale(float scale, bool force); virtual void SetWidth(float width); virtual void SetHeight(float height); + virtual void SetSize(float width, float height); virtual float GetWidth(); virtual float GetHeight(); virtual void GetSize(float& width, float& height, int32_t a4); From 66df4c55dace3407e510cb7a1d2a0a3c7f82a7d8 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 8 Feb 2026 21:45:58 -0600 Subject: [PATCH 210/269] feat(ui): implement CScriptRegion_SetSize --- src/ui/CScriptRegionScript.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/ui/CScriptRegionScript.cpp b/src/ui/CScriptRegionScript.cpp index 4c9b489..aa7c783 100644 --- a/src/ui/CScriptRegionScript.cpp +++ b/src/ui/CScriptRegionScript.cpp @@ -219,7 +219,28 @@ int32_t CScriptRegion_SetHeight(lua_State* L) { } int32_t CScriptRegion_SetSize(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CScriptRegion::GetObjectType(); + auto region = static_cast(FrameScript_GetObjectThis(L, type)); + + if (!region->ProtectedFunctionsAllowed()) { + // TODO disallowed logic + return 0; + } + + if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3)) { + luaL_error(L, "Usage: %s:SetSize(width, height)", region->GetDisplayName()); + return 0; + } + + auto ndcWidth = static_cast(lua_tonumber(L, 2)) / (CoordinateGetAspectCompensation() * 1024.0f); + auto ddcWidth = NDCToDDCWidth(ndcWidth); + + auto ndcHeight = static_cast(lua_tonumber(L, 3)) / (CoordinateGetAspectCompensation() * 1024.0f); + auto ddcHeight = NDCToDDCWidth(ndcHeight); + + region->SetSize(ddcWidth, ddcHeight); + + return 0; } int32_t CScriptRegion_GetSize(lua_State* L) { From d210df2f430ad3c83e65e1a1622ad596febff2a4 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 9 Feb 2026 04:56:46 -0600 Subject: [PATCH 211/269] feat(ui): add CGPartyInfo::NumMembers --- src/ui/game/CGPartyInfo.cpp | 15 +++++++++++++++ src/ui/game/CGPartyInfo.hpp | 16 ++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/ui/game/CGPartyInfo.cpp create mode 100644 src/ui/game/CGPartyInfo.hpp diff --git a/src/ui/game/CGPartyInfo.cpp b/src/ui/game/CGPartyInfo.cpp new file mode 100644 index 0000000..36f4ed3 --- /dev/null +++ b/src/ui/game/CGPartyInfo.cpp @@ -0,0 +1,15 @@ +#include "ui/game/CGPartyInfo.hpp" + +WOWGUID CGPartyInfo::m_members[4]; + +uint32_t CGPartyInfo::NumMembers() { + uint32_t count = 0; + + for (auto& member : CGPartyInfo::m_members) { + if (member != 0) { + count++; + } + } + + return count; +} diff --git a/src/ui/game/CGPartyInfo.hpp b/src/ui/game/CGPartyInfo.hpp new file mode 100644 index 0000000..5a9ffe5 --- /dev/null +++ b/src/ui/game/CGPartyInfo.hpp @@ -0,0 +1,16 @@ +#ifndef UI_GAME_C_G_PARTY_INFO_HPP +#define UI_GAME_C_G_PARTY_INFO_HPP + +#include "util/GUID.hpp" + +class CGPartyInfo { + public: + // Public static functions + static uint32_t NumMembers(); + + private: + // Private static variables + static WOWGUID m_members[]; +}; + +#endif From 4d003129beab4b6ed4cd731533b938938e963f70 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 9 Feb 2026 05:07:34 -0600 Subject: [PATCH 212/269] feat(ui): add PartyInfoRegisterScriptFunctions --- src/ui/game/CGGameUI.cpp | 2 + src/ui/game/PartyInfoScript.cpp | 127 ++++++++++++++++++++++++++++++++ src/ui/game/PartyInfoScript.hpp | 6 ++ 3 files changed, 135 insertions(+) create mode 100644 src/ui/game/PartyInfoScript.cpp create mode 100644 src/ui/game/PartyInfoScript.hpp diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index 08e40c7..a33db78 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -19,6 +19,7 @@ #include "ui/game/CharacterInfoScript.hpp" #include "ui/game/GMTicketInfoScript.hpp" #include "ui/game/GameScript.hpp" +#include "ui/game/PartyInfoScript.hpp" #include "ui/game/ScriptEvents.hpp" #include "ui/game/TradeInfoScript.hpp" #include "ui/game/Types.hpp" @@ -56,6 +57,7 @@ void LoadScriptFunctions() { // TODO ActionBarRegisterScriptFunctions(); + PartyInfoRegisterScriptFunctions(); // TODO diff --git a/src/ui/game/PartyInfoScript.cpp b/src/ui/game/PartyInfoScript.cpp new file mode 100644 index 0000000..0ea14ae --- /dev/null +++ b/src/ui/game/PartyInfoScript.cpp @@ -0,0 +1,127 @@ +#include "ui/game/PartyInfoScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Lua.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t Script_GetNumPartyMembers(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetRealNumPartyMembers(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPartyMember(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPartyLeaderIndex(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsPartyLeader(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsRealPartyLeader(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_LeaveParty(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetLootMethod(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetLootMethod(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetLootThreshold(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetLootThreshold(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetPartyAssignment(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ClearPartyAssignment(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetPartyAssignment(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SilenceMember(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_UnSilenceMember(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetOptOutOfLoot(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetOptOutOfLoot(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_CanChangePlayerDifficulty(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ChangePlayerDifficulty(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsPartyLFG(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_HasLFGRestrictions(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +static FrameScript_Method s_ScriptFunctions[] = { + { "GetNumPartyMembers", &Script_GetNumPartyMembers }, + { "GetRealNumPartyMembers", &Script_GetRealNumPartyMembers }, + { "GetPartyMember", &Script_GetPartyMember }, + { "GetPartyLeaderIndex", &Script_GetPartyLeaderIndex }, + { "IsPartyLeader", &Script_IsPartyLeader }, + { "IsRealPartyLeader", &Script_IsRealPartyLeader }, + { "LeaveParty", &Script_LeaveParty }, + { "GetLootMethod", &Script_GetLootMethod }, + { "SetLootMethod", &Script_SetLootMethod }, + { "GetLootThreshold", &Script_GetLootThreshold }, + { "SetLootThreshold", &Script_SetLootThreshold }, + { "SetPartyAssignment", &Script_SetPartyAssignment }, + { "ClearPartyAssignment", &Script_ClearPartyAssignment }, + { "GetPartyAssignment", &Script_GetPartyAssignment }, + { "SilenceMember", &Script_SilenceMember }, + { "UnSilenceMember", &Script_UnSilenceMember }, + { "SetOptOutOfLoot", &Script_SetOptOutOfLoot }, + { "GetOptOutOfLoot", &Script_GetOptOutOfLoot }, + { "CanChangePlayerDifficulty", &Script_CanChangePlayerDifficulty }, + { "ChangePlayerDifficulty", &Script_ChangePlayerDifficulty }, + { "IsPartyLFG", &Script_IsPartyLFG }, + { "HasLFGRestrictions", &Script_HasLFGRestrictions }, +}; + +void PartyInfoRegisterScriptFunctions() { + for (auto& func : s_ScriptFunctions) { + FrameScript_RegisterFunction(func.name, func.method); + } +} diff --git a/src/ui/game/PartyInfoScript.hpp b/src/ui/game/PartyInfoScript.hpp new file mode 100644 index 0000000..99ad273 --- /dev/null +++ b/src/ui/game/PartyInfoScript.hpp @@ -0,0 +1,6 @@ +#ifndef UI_GAME_PARTY_INFO_SCRIPT_HPP +#define UI_GAME_PARTY_INFO_SCRIPT_HPP + +void PartyInfoRegisterScriptFunctions(); + +#endif From 8da307593d7ce8837a7d9db9bfd066c1f40c66c1 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 9 Feb 2026 05:13:02 -0600 Subject: [PATCH 213/269] feat(ui): implement Script_GetNumPartyMembers --- src/ui/game/PartyInfoScript.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/game/PartyInfoScript.cpp b/src/ui/game/PartyInfoScript.cpp index 0ea14ae..408ce1e 100644 --- a/src/ui/game/PartyInfoScript.cpp +++ b/src/ui/game/PartyInfoScript.cpp @@ -1,12 +1,15 @@ #include "ui/game/PartyInfoScript.hpp" #include "ui/FrameScript.hpp" +#include "ui/game/CGPartyInfo.hpp" #include "util/Lua.hpp" #include "util/Unimplemented.hpp" namespace { int32_t Script_GetNumPartyMembers(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + lua_pushnumber(L, CGPartyInfo::NumMembers()); + + return 1; } int32_t Script_GetRealNumPartyMembers(lua_State* L) { From 8e67adc15f79bf61e590eb45415bf1a2222aa48d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 9 Feb 2026 05:55:20 -0600 Subject: [PATCH 214/269] feat(ui): add CGRaidInfo::NumMembers --- src/ui/game/CGRaidInfo.cpp | 7 +++++++ src/ui/game/CGRaidInfo.hpp | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/ui/game/CGRaidInfo.cpp create mode 100644 src/ui/game/CGRaidInfo.hpp diff --git a/src/ui/game/CGRaidInfo.cpp b/src/ui/game/CGRaidInfo.cpp new file mode 100644 index 0000000..4289a7c --- /dev/null +++ b/src/ui/game/CGRaidInfo.cpp @@ -0,0 +1,7 @@ +#include "ui/game/CGRaidInfo.hpp" + +uint32_t CGRaidInfo::s_numMembers; + +uint32_t CGRaidInfo::NumMembers() { + return CGRaidInfo::s_numMembers; +} diff --git a/src/ui/game/CGRaidInfo.hpp b/src/ui/game/CGRaidInfo.hpp new file mode 100644 index 0000000..a303502 --- /dev/null +++ b/src/ui/game/CGRaidInfo.hpp @@ -0,0 +1,16 @@ +#ifndef UI_GAME_C_G_RAID_INFO_HPP +#define UI_GAME_C_G_RAID_INFO_HPP + +#include + +class CGRaidInfo { + public: + // Public static functions + static uint32_t NumMembers(); + + private: + // Private static variables + static uint32_t s_numMembers; +}; + +#endif From 39bf2f5ad48134412d8f8856284c44a691878bdc Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 9 Feb 2026 06:04:57 -0600 Subject: [PATCH 215/269] feat(ui): add RaidInfoRegisterScriptFunctions --- src/ui/game/CGGameUI.cpp | 5 ++ src/ui/game/RaidInfoScript.cpp | 117 +++++++++++++++++++++++++++++++++ src/ui/game/RaidInfoScript.hpp | 6 ++ 3 files changed, 128 insertions(+) create mode 100644 src/ui/game/RaidInfoScript.cpp create mode 100644 src/ui/game/RaidInfoScript.hpp diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index a33db78..a92b41f 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -20,6 +20,7 @@ #include "ui/game/GMTicketInfoScript.hpp" #include "ui/game/GameScript.hpp" #include "ui/game/PartyInfoScript.hpp" +#include "ui/game/RaidInfoScript.hpp" #include "ui/game/ScriptEvents.hpp" #include "ui/game/TradeInfoScript.hpp" #include "ui/game/Types.hpp" @@ -73,6 +74,10 @@ void LoadScriptFunctions() { // TODO + RaidInfoRegisterScriptFunctions(); + + // TODO + GMTicketInfoRegisterScriptFunctions(); BattlenetUI_RegisterScriptFunctions(); } diff --git a/src/ui/game/RaidInfoScript.cpp b/src/ui/game/RaidInfoScript.cpp new file mode 100644 index 0000000..bf33235 --- /dev/null +++ b/src/ui/game/RaidInfoScript.cpp @@ -0,0 +1,117 @@ +#include "ui/game/RaidInfoScript.hpp" +#include "ui/FrameScript.hpp" +#include "util/Lua.hpp" +#include "util/Unimplemented.hpp" + +namespace { + +int32_t Script_GetNumRaidMembers(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetRealNumRaidMembers(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetRaidRosterInfo(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetRaidRosterSelection(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetRaidRosterSelection(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsRaidLeader(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsRealRaidLeader(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_IsRaidOfficer(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetRaidSubgroup(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SwapRaidSubgroup(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ConvertToRaid(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_PromoteToLeader(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_PromoteToAssistant(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DemoteAssistant(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_SetRaidTarget(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetRaidTargetIndex(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_DoReadyCheck(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_ConfirmReadyCheck(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetReadyCheckTimeLeft(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +int32_t Script_GetReadyCheckStatus(lua_State* L) { + WHOA_UNIMPLEMENTED(0); +} + +} + +static FrameScript_Method s_ScriptFunctions[] = { + { "GetNumRaidMembers", &Script_GetNumRaidMembers }, + { "GetRealNumRaidMembers", &Script_GetRealNumRaidMembers }, + { "GetRaidRosterInfo", &Script_GetRaidRosterInfo }, + { "SetRaidRosterSelection", &Script_SetRaidRosterSelection }, + { "GetRaidRosterSelection", &Script_GetRaidRosterSelection }, + { "IsRaidLeader", &Script_IsRaidLeader }, + { "IsRealRaidLeader", &Script_IsRealRaidLeader }, + { "IsRaidOfficer", &Script_IsRaidOfficer }, + { "SetRaidSubgroup", &Script_SetRaidSubgroup }, + { "SwapRaidSubgroup", &Script_SwapRaidSubgroup }, + { "ConvertToRaid", &Script_ConvertToRaid }, + { "PromoteToLeader", &Script_PromoteToLeader }, + { "PromoteToAssistant", &Script_PromoteToAssistant }, + { "DemoteAssistant", &Script_DemoteAssistant }, + { "SetRaidTarget", &Script_SetRaidTarget }, + { "GetRaidTargetIndex", &Script_GetRaidTargetIndex }, + { "DoReadyCheck", &Script_DoReadyCheck }, + { "ConfirmReadyCheck", &Script_ConfirmReadyCheck }, + { "GetReadyCheckTimeLeft", &Script_GetReadyCheckTimeLeft }, + { "GetReadyCheckStatus", &Script_GetReadyCheckStatus }, +}; + +void RaidInfoRegisterScriptFunctions() { + for (auto& func : s_ScriptFunctions) { + FrameScript_RegisterFunction(func.name, func.method); + } +} diff --git a/src/ui/game/RaidInfoScript.hpp b/src/ui/game/RaidInfoScript.hpp new file mode 100644 index 0000000..1ef711c --- /dev/null +++ b/src/ui/game/RaidInfoScript.hpp @@ -0,0 +1,6 @@ +#ifndef UI_GAME_RAID_INFO_SCRIPT_HPP +#define UI_GAME_RAID_INFO_SCRIPT_HPP + +void RaidInfoRegisterScriptFunctions(); + +#endif From e1758940993188c947f97dd5ae92141e1837fedf Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 9 Feb 2026 06:09:41 -0600 Subject: [PATCH 216/269] feat(ui): implement Script_GetNumRaidMembers --- src/ui/game/RaidInfoScript.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/game/RaidInfoScript.cpp b/src/ui/game/RaidInfoScript.cpp index bf33235..aaccaa4 100644 --- a/src/ui/game/RaidInfoScript.cpp +++ b/src/ui/game/RaidInfoScript.cpp @@ -1,12 +1,15 @@ #include "ui/game/RaidInfoScript.hpp" #include "ui/FrameScript.hpp" +#include "ui/game/CGRaidInfo.hpp" #include "util/Lua.hpp" #include "util/Unimplemented.hpp" namespace { int32_t Script_GetNumRaidMembers(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + lua_pushnumber(L, CGRaidInfo::NumMembers()); + + return 1; } int32_t Script_GetRealNumRaidMembers(lua_State* L) { From 0d001d4b3f6a43ee037940c244dd8d7070cf2666 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 9 Feb 2026 08:01:56 -0600 Subject: [PATCH 217/269] feat(ui): implement Script_GetCVarDefault --- src/ui/game/GameScript.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ui/game/GameScript.cpp b/src/ui/game/GameScript.cpp index 9fe3ce3..0268775 100644 --- a/src/ui/game/GameScript.cpp +++ b/src/ui/game/GameScript.cpp @@ -206,7 +206,22 @@ int32_t Script_GetCVarBool(lua_State* L) { } int32_t Script_GetCVarDefault(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isstring(L, 1)) { + luaL_error(L, "Usage: GetCVarDefault(\"cvar\")"); + return 0; + } + + auto varName = lua_tostring(L, 1); + auto var = CVar::LookupRegistered(varName); + + if (!var || (var->m_flags & 0x40)) { + luaL_error(L, "Couldn't find CVar named '%s'", varName); + return 0; + } + + lua_pushstring(L, var->GetDefaultValue()); + + return 1; } int32_t Script_GetCVarMin(lua_State* L) { From 121f41d6b8c2f28eb102532bb374813a2df07ff9 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 9 Feb 2026 08:33:24 -0600 Subject: [PATCH 218/269] feat(ui): implement CSimpleFrame_CreateFontString --- src/ui/simple/CSimpleFrameScript.cpp | 70 +++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleFrameScript.cpp b/src/ui/simple/CSimpleFrameScript.cpp index 45b2679..aa5ff6b 100644 --- a/src/ui/simple/CSimpleFrameScript.cpp +++ b/src/ui/simple/CSimpleFrameScript.cpp @@ -3,6 +3,8 @@ #include "ui/CBackdropGenerator.hpp" #include "ui/FrameScript.hpp" #include "ui/FrameXML.hpp" +#include "ui/simple/CSimpleFont.hpp" +#include "ui/simple/CSimpleFontString.hpp" #include "ui/simple/CSimpleFrame.hpp" #include "ui/simple/CSimpleTexture.hpp" #include "util/Lua.hpp" @@ -85,7 +87,73 @@ int32_t CSimpleFrame_CreateTexture(lua_State* L) { } int32_t CSimpleFrame_CreateFontString(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleFrame::GetObjectType(); + auto frame = static_cast(FrameScript_GetObjectThis(L, type)); + + const char* name = nullptr; + if (lua_isstring(L, 2)) { + name = lua_tostring(L, 2); + } + + int32_t drawlayer = DRAWLAYER_ARTWORK; + if (lua_isstring(L, 3)) { + auto drawlayerStr = lua_tostring(L, 3); + StringToDrawLayer(drawlayerStr, drawlayer); + } + + CSimpleFont* inheritFont = nullptr; + XMLNode* inheritNode = nullptr; + + if (lua_type(L, 4) == LUA_TSTRING) { + auto inheritName = lua_tostring(L, 4); + + inheritFont = CSimpleFont::GetFont(inheritName, 0); + + if (!inheritFont) { + const char* tainted; + bool locked; + inheritNode = FrameXML_AcquireHashNode(inheritName, tainted, locked); + + if (!inheritNode) { + luaL_error(L, "%s:CreateFontString(): Couldn't find inherited node \"%s\"", frame->GetDisplayName(), inheritName); + return 0; + } + + if (locked) { + luaL_error(L, "%s:CreateFontString(): Recursively inherited node \"%s\"", frame->GetDisplayName(), inheritName); + return 0; + } + } + } + + // TODO CDataAllocator::GetData + auto string = STORM_NEW(CSimpleFontString)(frame, drawlayer, true); + + if (name && *name) { + string->SetName(name); + } + + if (inheritFont) { + string->SetFontObject(inheritFont); + } else if (inheritNode) { + CStatus status; + + string->LoadXML(inheritNode, &status); + string->PostLoadXML(inheritNode, &status); + + auto inheritName = lua_tostring(L, 4); + FrameXML_ReleaseHashNode(inheritName); + } + + // TODO anim related logic? + + if (!string->lua_registered) { + string->RegisterScriptObject(nullptr); + } + + lua_rawgeti(L, LUA_REGISTRYINDEX, string->lua_objectRef); + + return 1; } int32_t CSimpleFrame_GetBoundsRect(lua_State* L) { From 17198939da3eb203bae57a6a612cf3eef81178cc Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 9 Feb 2026 10:48:58 -0600 Subject: [PATCH 219/269] feat(ui): add FrameScript_Object::UnregisterScriptEvent --- src/ui/FrameScript_Object.cpp | 19 +++++++++++++++++++ src/ui/FrameScript_Object.hpp | 1 + 2 files changed, 20 insertions(+) diff --git a/src/ui/FrameScript_Object.cpp b/src/ui/FrameScript_Object.cpp index 17ff3db..6a8397e 100644 --- a/src/ui/FrameScript_Object.cpp +++ b/src/ui/FrameScript_Object.cpp @@ -193,6 +193,25 @@ int32_t FrameScript_Object::SetScript(lua_State* L) { return 0; } +void FrameScript_Object::UnregisterScriptEvent(const char* name) { + auto event = FrameScript::s_scriptEventsHash.Ptr(name); + + if (!event) { + return; + } + + if (event->pendingSignalCount) { + for (auto node = event->registerListeners.Head(); node; node = event->registerListeners.Next(node)) { + if (node->listener == this) { + event->registerListeners.DeleteNode(node); + break; + } + } + } + + FrameScript_UnregisterScriptEvent(this, event); +} + void FrameScript_Object::UnregisterScriptObject(const char* name) { auto L = FrameScript_GetContext(); diff --git a/src/ui/FrameScript_Object.hpp b/src/ui/FrameScript_Object.hpp index db4528f..3884042 100644 --- a/src/ui/FrameScript_Object.hpp +++ b/src/ui/FrameScript_Object.hpp @@ -48,6 +48,7 @@ class FrameScript_Object { void RegisterScriptObject(const char* name); void RunScript(ScriptIx const& script, int32_t argCount, const char* a4); int32_t SetScript(lua_State* L); + void UnregisterScriptEvent(const char* name); void UnregisterScriptObject(const char* name); }; From c604ae6d197e429d3e912d070a58658a464f832d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 9 Feb 2026 10:49:18 -0600 Subject: [PATCH 220/269] feat(ui): implement CSimpleFrame_UnregisterEvent --- src/ui/simple/CSimpleFrameScript.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleFrameScript.cpp b/src/ui/simple/CSimpleFrameScript.cpp index aa5ff6b..ba842ca 100644 --- a/src/ui/simple/CSimpleFrameScript.cpp +++ b/src/ui/simple/CSimpleFrameScript.cpp @@ -289,7 +289,19 @@ int32_t CSimpleFrame_RegisterEvent(lua_State* L) { } int32_t CSimpleFrame_UnregisterEvent(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleFrame::GetObjectType(); + auto frame = static_cast(FrameScript_GetObjectThis(L, type)); + + if (!lua_isstring(L, 2)) { + luaL_error(L, "Usage: %s:UnregisterEvent(\"event\")", frame->GetDisplayName()); + return 0; + } + + auto eventName = lua_tostring(L, 2); + + frame->UnregisterScriptEvent(eventName); + + return 0; } int32_t CSimpleFrame_RegisterAllEvents(lua_State* L) { From 9f3160b1d2adf5078a357679a3abedd57438ce02 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 9 Feb 2026 15:38:48 -0600 Subject: [PATCH 221/269] feat(world): add CWorld::GetM2Scene --- src/world/CWorld.cpp | 11 +++++++++-- src/world/CWorld.hpp | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/world/CWorld.cpp b/src/world/CWorld.cpp index 6163b42..1027380 100644 --- a/src/world/CWorld.cpp +++ b/src/world/CWorld.cpp @@ -12,6 +12,7 @@ uint32_t CWorld::s_enables; uint32_t CWorld::s_enables2; uint32_t CWorld::s_gameTimeFixed; float CWorld::s_gameTimeSec; +CM2Scene* CWorld::s_m2Scene; uint32_t CWorld::s_tickTimeFixed; uint32_t CWorld::s_tickTimeMs; float CWorld::s_tickTimeSec; @@ -66,6 +67,10 @@ float CWorld::GetGameTimeSec() { return CWorld::s_gameTimeSec; } +CM2Scene* CWorld::GetM2Scene() { + return CWorld::s_m2Scene; +} + uint32_t CWorld::GetTickTimeFixed() { return CWorld::s_tickTimeFixed; } @@ -97,8 +102,6 @@ void CWorld::Initialize() { CWorld::s_gameTimeFixed = 0; CWorld::s_gameTimeSec = 0.0f; - // TODO - if (GxCaps().m_shaderTargets[GxSh_Pixel] > GxShPS_none) { CWorld::s_enables |= Enables::Enable_PixelShader; } @@ -109,6 +112,10 @@ void CWorld::Initialize() { // TODO + CWorld::s_m2Scene = M2CreateScene(); + + // TODO + uint32_t m2Flags = M2GetCacheFlags(); CShaderEffect::InitShaderSystem( (m2Flags & 0x8) != 0, diff --git a/src/world/CWorld.hpp b/src/world/CWorld.hpp index 93cf9fc..0ea3682 100644 --- a/src/world/CWorld.hpp +++ b/src/world/CWorld.hpp @@ -7,6 +7,7 @@ #include class CM2Model; +class CM2Scene; class Weather; class CWorld { @@ -58,6 +59,7 @@ class CWorld { static float GetCurTimeSec(); static uint32_t GetGameTimeFixed(); static float GetGameTimeSec(); + static CM2Scene* GetM2Scene(); static uint32_t GetTickTimeFixed(); static uint32_t GetTickTimeMs(); static float GetTickTimeSec(); @@ -72,6 +74,7 @@ class CWorld { static float s_curTimeSec; static uint32_t s_gameTimeFixed; static float s_gameTimeSec; + static CM2Scene* s_m2Scene; static uint32_t s_tickTimeFixed; static uint32_t s_tickTimeMs; static float s_tickTimeSec; From b4751725a6a679e37f6733b50c0a5582bb43fc0c Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 9 Feb 2026 15:40:23 -0600 Subject: [PATCH 222/269] feat(object): implement CGObject_C::AddWorldObject --- src/object/client/CGObject_C.cpp | 80 +++++++++++++++++++++++++++++++- src/object/client/CGObject_C.hpp | 9 ++++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 284cac3..3a7b0a6 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -1,4 +1,5 @@ #include "object/client/CGObject_C.hpp" +#include "model/Model2.hpp" #include "object/client/ObjMgr.hpp" #include "world/World.hpp" @@ -6,6 +7,7 @@ CGObject_C::CGObject_C(uint32_t time, CClientObjCreate& objCreate) { // TODO this->m_model = nullptr; + this->m_worldObject = 0; // TODO @@ -28,7 +30,52 @@ CGObject_C::~CGObject_C() { } void CGObject_C::AddWorldObject() { - // TODO + if (!this->m_model) { + const char* fileName; + if (this->GetModelFileName(fileName)) { + auto model = CWorld::GetM2Scene()->CreateModel(fileName, 0); + this->SetModel(model); + model->Release(); + } + } + + if (!this->m_model) { + return; + } + + if (ClntObjMgrGetPlayerType() != PLAYER_NORMAL) { + return; + } + + if (this->m_worldObject) { + // TODO SysMsgPrintf(1, 2, "OBJECTALREADYACTIVE|0x%016I64X", this->GetGUID()); + + return; + } + + uint32_t objFlags = 0x0; + + if (this->IsA(TYPE_GAMEOBJECT)) { + objFlags |= 0x8 | 0x2 | 0x1; + } else if (this->IsA(TYPE_DYNAMICOBJECT)) { + objFlags |= 0x8 | 0x2; + } else if (this->IsA(TYPE_CORPSE)) { + // TODO + } else if (this->IsA(TYPE_UNIT)) { + // TODO + + objFlags |= 0x10; + + if (this->IsA(TYPE_PLAYER)) { + objFlags |= 0x20; + } + } + + this->m_worldObject = CWorld::AddObject(this->GetObjectModel(), nullptr, nullptr, this->GetGUID(), 0, objFlags); + + if (!this->m_inReenable && this->m_postInited) { + this->UpdateWorldObject(false); + } } int32_t CGObject_C::CanBeTargetted() { @@ -48,6 +95,14 @@ void CGObject_C::Disable() { this->m_disableTimeMs = CWorld::GetCurTimeMs(); } +int32_t CGObject_C::GetModelFileName(const char*& name) { + return false; +} + +CM2Model* CGObject_C::GetObjectModel() { + return this->m_model; +} + int32_t CGObject_C::IsInReenable() { return this->m_inReenable; } @@ -90,6 +145,25 @@ void CGObject_C::SetDisablePending(int32_t pending) { } } +void CGObject_C::SetModel(CM2Model* model) { + // No change + if (this->m_model == model) { + return; + } + + if (model) { + model->AddRef(); + } + + this->m_model = model; + + this->SetModelFinish(model); +} + +void CGObject_C::SetModelFinish(CM2Model* model) { + // TODO +} + void CGObject_C::SetObjectLocked(int32_t locked) { if (locked) { if (this->m_lockCount != 0xFFFF) { @@ -147,3 +221,7 @@ void CGObject_C::SetTypeID(OBJECT_TYPE_ID typeID) { break; } } + +void CGObject_C::UpdateWorldObject(int32_t a2) { + // TODO +} diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index a0d9770..46f150b 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -5,6 +5,7 @@ #include "object/client/CClientObjCreate.hpp" #include "object/client/CGObject.hpp" #include "util/GUID.hpp" +#include "world/Types.hpp" #include #include @@ -18,6 +19,7 @@ class CGObject_C : public CGObject, public TSHashObject Date: Tue, 10 Feb 2026 16:00:15 -0600 Subject: [PATCH 223/269] feat(object): add CGUnit_C::GetModelFileName --- src/object/client/CGObject_C.cpp | 2 +- src/object/client/CGObject_C.hpp | 2 +- src/object/client/CGUnit_C.cpp | 20 ++++++++++++++++++++ src/object/client/CGUnit_C.hpp | 4 ++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index 3a7b0a6..e9cd9a2 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -95,7 +95,7 @@ void CGObject_C::Disable() { this->m_disableTimeMs = CWorld::GetCurTimeMs(); } -int32_t CGObject_C::GetModelFileName(const char*& name) { +int32_t CGObject_C::GetModelFileName(const char*& name) const { return false; } diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index 46f150b..fdb5813 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -36,7 +36,7 @@ class CGObject_C : public CGObject, public TSHashObjectCanHighlight(); } +CreatureModelDataRec* CGUnit_C::GetModelData() const { + // TODO + return nullptr; +} + +int32_t CGUnit_C::GetModelFileName(const char*& name) const { + auto modelDataRec = this->GetModelData(); + + // Model data not found + if (!modelDataRec) { + name = "Spells\\ErrorCube.mdx"; + + return true; + } + + name = modelDataRec->m_modelName; + + return modelDataRec->m_modelName ? true : false; +} + void CGUnit_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { // TODO diff --git a/src/object/client/CGUnit_C.hpp b/src/object/client/CGUnit_C.hpp index b3103ff..8df4b75 100644 --- a/src/object/client/CGUnit_C.hpp +++ b/src/object/client/CGUnit_C.hpp @@ -9,6 +9,7 @@ class ChrClassesRec; class ChrRacesRec; +class CreatureModelDataRec; class CGUnit_C : public CGObject_C, public CGUnit { public: @@ -22,12 +23,15 @@ class CGUnit_C : public CGObject_C, public CGUnit { // Virtual public member functions virtual ~CGUnit_C(); // TODO + virtual int32_t GetModelFileName(const char*& name) const; + // TODO virtual int32_t CanHighlight(); virtual int32_t CanBeTargetted(); // TODO // Public member functions CGUnit_C(uint32_t time, CClientObjCreate& objCreate); + CreatureModelDataRec* GetModelData() const; void PostInit(uint32_t time, const CClientObjCreate& init, bool a4); void PostMovementUpdate(const CClientMoveUpdate& move, int32_t activeMover); void SetStorage(uint32_t* storage, uint32_t* saved); From 0f7f0207eecceff97654113b430b4496ced01769 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 11 Feb 2026 22:21:17 -0600 Subject: [PATCH 224/269] feat(object): add CGUnit::GetDisplayID --- src/object/client/CGUnit.cpp | 4 ++++ src/object/client/CGUnit.hpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/object/client/CGUnit.cpp b/src/object/client/CGUnit.cpp index 4f525c8..3474606 100644 --- a/src/object/client/CGUnit.cpp +++ b/src/object/client/CGUnit.cpp @@ -25,6 +25,10 @@ uint32_t CGUnit::TotalFieldsSaved() { return CGUnit::GetBaseOffsetSaved() + 123; } +int32_t CGUnit::GetDisplayID() const { + return this->Unit()->displayID; +} + CGUnitData* CGUnit::Unit() const { return this->m_unit; } diff --git a/src/object/client/CGUnit.hpp b/src/object/client/CGUnit.hpp index 3fb6ddb..631f7ca 100644 --- a/src/object/client/CGUnit.hpp +++ b/src/object/client/CGUnit.hpp @@ -82,6 +82,9 @@ class CGUnit { static uint32_t TotalFields(); static uint32_t TotalFieldsSaved(); + // Public member functions + int32_t GetDisplayID() const; + protected: // Protected member variables CGUnitData* m_unit; From d2534172336076053997833c24830e90b97da91e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 11 Feb 2026 22:33:39 -0600 Subject: [PATCH 225/269] feat(object): add CGUnit::GetNativeDisplayID --- src/object/client/CGUnit.cpp | 4 ++++ src/object/client/CGUnit.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/object/client/CGUnit.cpp b/src/object/client/CGUnit.cpp index 3474606..223407b 100644 --- a/src/object/client/CGUnit.cpp +++ b/src/object/client/CGUnit.cpp @@ -29,6 +29,10 @@ int32_t CGUnit::GetDisplayID() const { return this->Unit()->displayID; } +int32_t CGUnit::GetNativeDisplayID() const { + return this->Unit()->nativeDisplayID; +} + CGUnitData* CGUnit::Unit() const { return this->m_unit; } diff --git a/src/object/client/CGUnit.hpp b/src/object/client/CGUnit.hpp index 631f7ca..f34c268 100644 --- a/src/object/client/CGUnit.hpp +++ b/src/object/client/CGUnit.hpp @@ -84,6 +84,7 @@ class CGUnit { // Public member functions int32_t GetDisplayID() const; + int32_t GetNativeDisplayID() const; protected: // Protected member variables From afb329c42d6907b4860df8507025bf82b09919a8 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 11 Feb 2026 22:39:24 -0600 Subject: [PATCH 226/269] feat(object): add CGUnit_C::GetLocalDisplayID --- src/object/client/CGUnit_C.cpp | 4 ++++ src/object/client/CGUnit_C.hpp | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/src/object/client/CGUnit_C.cpp b/src/object/client/CGUnit_C.cpp index 52ad0b8..531b408 100644 --- a/src/object/client/CGUnit_C.cpp +++ b/src/object/client/CGUnit_C.cpp @@ -115,6 +115,10 @@ int32_t CGUnit_C::CanBeTargetted() { return this->CanHighlight(); } +int32_t CGUnit_C::GetLocalDisplayID() const { + return this->m_localDisplayID; +} + CreatureModelDataRec* CGUnit_C::GetModelData() const { // TODO return nullptr; diff --git a/src/object/client/CGUnit_C.hpp b/src/object/client/CGUnit_C.hpp index 8df4b75..2d5e67f 100644 --- a/src/object/client/CGUnit_C.hpp +++ b/src/object/client/CGUnit_C.hpp @@ -31,10 +31,17 @@ class CGUnit_C : public CGObject_C, public CGUnit { // Public member functions CGUnit_C(uint32_t time, CClientObjCreate& objCreate); + int32_t GetLocalDisplayID() const; CreatureModelDataRec* GetModelData() const; void PostInit(uint32_t time, const CClientObjCreate& init, bool a4); void PostMovementUpdate(const CClientMoveUpdate& move, int32_t activeMover); void SetStorage(uint32_t* storage, uint32_t* saved); + + private: + // Private member variables + // TODO + int32_t m_localDisplayID = 0; + // TODO }; #endif From b69a99214174ea82aa19cef29b2169a5645ae430 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 11 Feb 2026 22:54:36 -0600 Subject: [PATCH 227/269] feat(object): implement CGUnit_C::GetModelData --- src/object/client/CGUnit_C.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/object/client/CGUnit_C.cpp b/src/object/client/CGUnit_C.cpp index 531b408..493f890 100644 --- a/src/object/client/CGUnit_C.cpp +++ b/src/object/client/CGUnit_C.cpp @@ -120,8 +120,27 @@ int32_t CGUnit_C::GetLocalDisplayID() const { } CreatureModelDataRec* CGUnit_C::GetModelData() const { - // TODO - return nullptr; + // Prefer local display ID if set and unit's display ID hasn't been overridden from unit's + // native display ID; otherwise prefer overridden display ID. + auto displayID = this->GetLocalDisplayID() && this->GetDisplayID() == this->GetNativeDisplayID() + ? this->GetLocalDisplayID() + : this->GetDisplayID(); + + auto creatureDisplayInfoRec = g_creatureDisplayInfoDB.GetRecord(displayID); + + if (!creatureDisplayInfoRec) { + // TODO SysMsgPrintf(1, 2, "NOCREATUREDISPLAYIDFOUND|%d", displayID); + return nullptr; + } + + auto creatureModelDataRec = g_creatureModelDataDB.GetRecord(creatureDisplayInfoRec->m_modelID); + + if (!creatureModelDataRec) { + // TODO SysMsgPrintf(1, 16, "INVALIDDISPLAYMODELRECORD|%d|%d", creatureDisplayInfoRec->m_modelID, creatureDisplayInfoRec->m_ID); + return nullptr; + } + + return creatureModelDataRec; } int32_t CGUnit_C::GetModelFileName(const char*& name) const { From 79b6a47b9a4bf98ce95648ad788c069c49470db4 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 13 Feb 2026 07:18:41 -0600 Subject: [PATCH 228/269] feat(db): add CreatureDisplayInfoExtraRec --- src/db/Db.cpp | 2 + src/db/Db.hpp | 2 + src/db/rec/CreatureDisplayInfoExtraRec.cpp | 66 ++++++++++++++++++++++ src/db/rec/CreatureDisplayInfoExtraRec.hpp | 32 +++++++++++ 4 files changed, 102 insertions(+) create mode 100644 src/db/rec/CreatureDisplayInfoExtraRec.cpp create mode 100644 src/db/rec/CreatureDisplayInfoExtraRec.hpp diff --git a/src/db/Db.cpp b/src/db/Db.cpp index 5d08340..7dff303 100644 --- a/src/db/Db.cpp +++ b/src/db/Db.cpp @@ -12,6 +12,7 @@ WowClientDB g_characterFacialHairStylesDB; WowClientDB g_chrClassesDB; WowClientDB g_chrRacesDB; WowClientDB g_creatureDisplayInfoDB; +WowClientDB g_creatureDisplayInfoExtraDB; WowClientDB g_creatureModelDataDB; WowClientDB g_factionGroupDB; WowClientDB g_factionTemplateDB; @@ -38,6 +39,7 @@ void StaticDBLoadAll(void (*loadFn)(WowClientDB_Base*, const char*, int32_t)) { loadFn(&g_chrClassesDB, __FILE__, __LINE__); loadFn(&g_chrRacesDB, __FILE__, __LINE__); loadFn(&g_creatureDisplayInfoDB, __FILE__, __LINE__); + loadFn(&g_creatureDisplayInfoExtraDB, __FILE__, __LINE__); loadFn(&g_creatureModelDataDB, __FILE__, __LINE__); loadFn(&g_factionGroupDB, __FILE__, __LINE__); loadFn(&g_factionTemplateDB, __FILE__, __LINE__); diff --git a/src/db/Db.hpp b/src/db/Db.hpp index 2eddf58..2efa912 100644 --- a/src/db/Db.hpp +++ b/src/db/Db.hpp @@ -13,6 +13,7 @@ #include "db/rec/ChrClassesRec.hpp" #include "db/rec/ChrRacesRec.hpp" #include "db/rec/CreatureDisplayInfoRec.hpp" +#include "db/rec/CreatureDisplayInfoExtraRec.hpp" #include "db/rec/CreatureModelDataRec.hpp" #include "db/rec/FactionGroupRec.hpp" #include "db/rec/FactionTemplateRec.hpp" @@ -34,6 +35,7 @@ extern WowClientDB g_characterFacialHairStylesDB; extern WowClientDB g_chrClassesDB; extern WowClientDB g_chrRacesDB; extern WowClientDB g_creatureDisplayInfoDB; +extern WowClientDB g_creatureDisplayInfoExtraDB; extern WowClientDB g_creatureModelDataDB; extern WowClientDB g_factionGroupDB; extern WowClientDB g_factionTemplateDB; diff --git a/src/db/rec/CreatureDisplayInfoExtraRec.cpp b/src/db/rec/CreatureDisplayInfoExtraRec.cpp new file mode 100644 index 0000000..4e2f85d --- /dev/null +++ b/src/db/rec/CreatureDisplayInfoExtraRec.cpp @@ -0,0 +1,66 @@ +// DO NOT EDIT: generated by whoa-autocode +#include "db/rec/CreatureDisplayInfoExtraRec.hpp" +#include "util/Locale.hpp" +#include "util/SFile.hpp" + +const char* CreatureDisplayInfoExtraRec::GetFilename() { + return "DBFilesClient\\CreatureDisplayInfoExtra.dbc"; +} + +uint32_t CreatureDisplayInfoExtraRec::GetNumColumns() { + return 21; +} + +uint32_t CreatureDisplayInfoExtraRec::GetRowSize() { + return 84; +} + +bool CreatureDisplayInfoExtraRec::NeedIDAssigned() { + return false; +} + +int32_t CreatureDisplayInfoExtraRec::GetID() { + return this->m_ID; +} + +void CreatureDisplayInfoExtraRec::SetID(int32_t id) { + this->m_ID = id; +} + +bool CreatureDisplayInfoExtraRec::Read(SFile* f, const char* stringBuffer) { + uint32_t bakeNameOfs; + + if ( + !SFile::Read(f, &this->m_ID, sizeof(this->m_ID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_displayRaceID, sizeof(this->m_displayRaceID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_displaySexID, sizeof(this->m_displaySexID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_skinID, sizeof(this->m_skinID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_faceID, sizeof(this->m_faceID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_hairStyleID, sizeof(this->m_hairStyleID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_hairColorID, sizeof(this->m_hairColorID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_facialHairID, sizeof(this->m_facialHairID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_npcitemDisplay[0], sizeof(m_npcitemDisplay[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_npcitemDisplay[1], sizeof(m_npcitemDisplay[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_npcitemDisplay[2], sizeof(m_npcitemDisplay[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_npcitemDisplay[3], sizeof(m_npcitemDisplay[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_npcitemDisplay[4], sizeof(m_npcitemDisplay[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_npcitemDisplay[5], sizeof(m_npcitemDisplay[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_npcitemDisplay[6], sizeof(m_npcitemDisplay[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_npcitemDisplay[7], sizeof(m_npcitemDisplay[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_npcitemDisplay[8], sizeof(m_npcitemDisplay[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_npcitemDisplay[9], sizeof(m_npcitemDisplay[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_npcitemDisplay[10], sizeof(m_npcitemDisplay[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_flags, sizeof(this->m_flags), nullptr, nullptr, nullptr) + || !SFile::Read(f, &bakeNameOfs, sizeof(uint32_t), nullptr, nullptr, nullptr) + ) { + return false; + } + + if (stringBuffer) { + this->m_bakeName = &stringBuffer[bakeNameOfs]; + } else { + this->m_bakeName = ""; + } + + return true; +} diff --git a/src/db/rec/CreatureDisplayInfoExtraRec.hpp b/src/db/rec/CreatureDisplayInfoExtraRec.hpp new file mode 100644 index 0000000..977d9c0 --- /dev/null +++ b/src/db/rec/CreatureDisplayInfoExtraRec.hpp @@ -0,0 +1,32 @@ +// DO NOT EDIT: generated by whoa-autocode +#ifndef DB_REC_CREATURE_DISPLAY_INFO_EXTRA_REC_HPP +#define DB_REC_CREATURE_DISPLAY_INFO_EXTRA_REC_HPP + +#include + +class SFile; + +class CreatureDisplayInfoExtraRec { + public: + int32_t m_ID; + int32_t m_displayRaceID; + int32_t m_displaySexID; + int32_t m_skinID; + int32_t m_faceID; + int32_t m_hairStyleID; + int32_t m_hairColorID; + int32_t m_facialHairID; + int32_t m_npcitemDisplay[11]; + int32_t m_flags; + const char* m_bakeName; + + static const char* GetFilename(); + static uint32_t GetNumColumns(); + static uint32_t GetRowSize(); + static bool NeedIDAssigned(); + int32_t GetID(); + void SetID(int32_t id); + bool Read(SFile* f, const char* stringBuffer); +}; + +#endif From c6a89b5ef8c1a2f65e4efe887d47ab15082e6320 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 13 Feb 2026 13:51:48 -0600 Subject: [PATCH 229/269] feat(db): add CreatureSoundDataRec --- src/db/Db.cpp | 2 + src/db/Db.hpp | 2 + src/db/rec/CreatureSoundDataRec.cpp | 75 +++++++++++++++++++++++++++++ src/db/rec/CreatureSoundDataRec.hpp | 52 ++++++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 src/db/rec/CreatureSoundDataRec.cpp create mode 100644 src/db/rec/CreatureSoundDataRec.hpp diff --git a/src/db/Db.cpp b/src/db/Db.cpp index 7dff303..9644480 100644 --- a/src/db/Db.cpp +++ b/src/db/Db.cpp @@ -14,6 +14,7 @@ WowClientDB g_chrRacesDB; WowClientDB g_creatureDisplayInfoDB; WowClientDB g_creatureDisplayInfoExtraDB; WowClientDB g_creatureModelDataDB; +WowClientDB g_creatureSoundDataDB; WowClientDB g_factionGroupDB; WowClientDB g_factionTemplateDB; WowClientDB g_itemDisplayInfoDB; @@ -41,6 +42,7 @@ void StaticDBLoadAll(void (*loadFn)(WowClientDB_Base*, const char*, int32_t)) { loadFn(&g_creatureDisplayInfoDB, __FILE__, __LINE__); loadFn(&g_creatureDisplayInfoExtraDB, __FILE__, __LINE__); loadFn(&g_creatureModelDataDB, __FILE__, __LINE__); + loadFn(&g_creatureSoundDataDB, __FILE__, __LINE__); loadFn(&g_factionGroupDB, __FILE__, __LINE__); loadFn(&g_factionTemplateDB, __FILE__, __LINE__); loadFn(&g_itemDisplayInfoDB, __FILE__, __LINE__); diff --git a/src/db/Db.hpp b/src/db/Db.hpp index 2efa912..c80eb0f 100644 --- a/src/db/Db.hpp +++ b/src/db/Db.hpp @@ -15,6 +15,7 @@ #include "db/rec/CreatureDisplayInfoRec.hpp" #include "db/rec/CreatureDisplayInfoExtraRec.hpp" #include "db/rec/CreatureModelDataRec.hpp" +#include "db/rec/CreatureSoundDataRec.hpp" #include "db/rec/FactionGroupRec.hpp" #include "db/rec/FactionTemplateRec.hpp" #include "db/rec/ItemDisplayInfoRec.hpp" @@ -37,6 +38,7 @@ extern WowClientDB g_chrRacesDB; extern WowClientDB g_creatureDisplayInfoDB; extern WowClientDB g_creatureDisplayInfoExtraDB; extern WowClientDB g_creatureModelDataDB; +extern WowClientDB g_creatureSoundDataDB; extern WowClientDB g_factionGroupDB; extern WowClientDB g_factionTemplateDB; extern WowClientDB g_itemDisplayInfoDB; diff --git a/src/db/rec/CreatureSoundDataRec.cpp b/src/db/rec/CreatureSoundDataRec.cpp new file mode 100644 index 0000000..0a3db1e --- /dev/null +++ b/src/db/rec/CreatureSoundDataRec.cpp @@ -0,0 +1,75 @@ +// DO NOT EDIT: generated by whoa-autocode +#include "db/rec/CreatureSoundDataRec.hpp" +#include "util/Locale.hpp" +#include "util/SFile.hpp" + +const char* CreatureSoundDataRec::GetFilename() { + return "DBFilesClient\\CreatureSoundData.dbc"; +} + +uint32_t CreatureSoundDataRec::GetNumColumns() { + return 38; +} + +uint32_t CreatureSoundDataRec::GetRowSize() { + return 152; +} + +bool CreatureSoundDataRec::NeedIDAssigned() { + return false; +} + +int32_t CreatureSoundDataRec::GetID() { + return this->m_ID; +} + +void CreatureSoundDataRec::SetID(int32_t id) { + this->m_ID = id; +} + +bool CreatureSoundDataRec::Read(SFile* f, const char* stringBuffer) { + if ( + !SFile::Read(f, &this->m_ID, sizeof(this->m_ID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundExertionID, sizeof(this->m_soundExertionID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundExertionCriticalID, sizeof(this->m_soundExertionCriticalID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundInjuryID, sizeof(this->m_soundInjuryID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundInjuryCriticalID, sizeof(this->m_soundInjuryCriticalID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundInjuryCrushingBlowID, sizeof(this->m_soundInjuryCrushingBlowID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundDeathID, sizeof(this->m_soundDeathID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundStunID, sizeof(this->m_soundStunID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundStandID, sizeof(this->m_soundStandID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundFootstepID, sizeof(this->m_soundFootstepID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundAggroID, sizeof(this->m_soundAggroID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundWingFlapID, sizeof(this->m_soundWingFlapID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundWingGlideID, sizeof(this->m_soundWingGlideID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundAlertID, sizeof(this->m_soundAlertID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundFidget[0], sizeof(m_soundFidget[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundFidget[1], sizeof(m_soundFidget[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundFidget[2], sizeof(m_soundFidget[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundFidget[3], sizeof(m_soundFidget[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundFidget[4], sizeof(m_soundFidget[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_customAttack[0], sizeof(m_customAttack[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_customAttack[1], sizeof(m_customAttack[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_customAttack[2], sizeof(m_customAttack[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_customAttack[3], sizeof(m_customAttack[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_npcsoundID, sizeof(this->m_npcsoundID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_loopSoundID, sizeof(this->m_loopSoundID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_creatureImpactType, sizeof(this->m_creatureImpactType), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundJumpStartID, sizeof(this->m_soundJumpStartID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundJumpEndID, sizeof(this->m_soundJumpEndID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundPetAttackID, sizeof(this->m_soundPetAttackID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundPetOrderID, sizeof(this->m_soundPetOrderID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_soundPetDismissID, sizeof(this->m_soundPetDismissID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_fidgetDelaySecondsMin, sizeof(this->m_fidgetDelaySecondsMin), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_fidgetDelaySecondsMax, sizeof(this->m_fidgetDelaySecondsMax), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_birthSoundID, sizeof(this->m_birthSoundID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_spellCastDirectedSoundID, sizeof(this->m_spellCastDirectedSoundID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_submergeSoundID, sizeof(this->m_submergeSoundID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_submergedSoundID, sizeof(this->m_submergedSoundID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_creatureSoundDataIdpet, sizeof(this->m_creatureSoundDataIdpet), nullptr, nullptr, nullptr) + ) { + return false; + } + + return true; +} diff --git a/src/db/rec/CreatureSoundDataRec.hpp b/src/db/rec/CreatureSoundDataRec.hpp new file mode 100644 index 0000000..d97564b --- /dev/null +++ b/src/db/rec/CreatureSoundDataRec.hpp @@ -0,0 +1,52 @@ +// DO NOT EDIT: generated by whoa-autocode +#ifndef DB_REC_CREATURE_SOUND_DATA_REC_HPP +#define DB_REC_CREATURE_SOUND_DATA_REC_HPP + +#include + +class SFile; + +class CreatureSoundDataRec { + public: + int32_t m_ID; + int32_t m_soundExertionID; + int32_t m_soundExertionCriticalID; + int32_t m_soundInjuryID; + int32_t m_soundInjuryCriticalID; + int32_t m_soundInjuryCrushingBlowID; + int32_t m_soundDeathID; + int32_t m_soundStunID; + int32_t m_soundStandID; + int32_t m_soundFootstepID; + int32_t m_soundAggroID; + int32_t m_soundWingFlapID; + int32_t m_soundWingGlideID; + int32_t m_soundAlertID; + int32_t m_soundFidget[5]; + int32_t m_customAttack[4]; + int32_t m_npcsoundID; + int32_t m_loopSoundID; + int32_t m_creatureImpactType; + int32_t m_soundJumpStartID; + int32_t m_soundJumpEndID; + int32_t m_soundPetAttackID; + int32_t m_soundPetOrderID; + int32_t m_soundPetDismissID; + float m_fidgetDelaySecondsMin; + float m_fidgetDelaySecondsMax; + int32_t m_birthSoundID; + int32_t m_spellCastDirectedSoundID; + int32_t m_submergeSoundID; + int32_t m_submergedSoundID; + int32_t m_creatureSoundDataIdpet; + + static const char* GetFilename(); + static uint32_t GetNumColumns(); + static uint32_t GetRowSize(); + static bool NeedIDAssigned(); + int32_t GetID(); + void SetID(int32_t id); + bool Read(SFile* f, const char* stringBuffer); +}; + +#endif From e56bde0ddee58e1527a2d495f5c3c2ff58710a33 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 13 Feb 2026 14:16:07 -0600 Subject: [PATCH 230/269] feat(db): add UnitBloodLevelsRec --- src/db/Db.cpp | 2 ++ src/db/Db.hpp | 2 ++ src/db/rec/UnitBloodLevelsRec.cpp | 41 +++++++++++++++++++++++++++++++ src/db/rec/UnitBloodLevelsRec.hpp | 23 +++++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 src/db/rec/UnitBloodLevelsRec.cpp create mode 100644 src/db/rec/UnitBloodLevelsRec.hpp diff --git a/src/db/Db.cpp b/src/db/Db.cpp index 9644480..4d8ae4d 100644 --- a/src/db/Db.cpp +++ b/src/db/Db.cpp @@ -23,6 +23,7 @@ WowClientDB g_mapDB; WowClientDB g_paperDollItemFrameDB; WowClientDB g_soundEntriesDB; WowClientDB g_soundEntriesAdvancedDB; +WowClientDB g_unitBloodLevelsDB; void LoadDB(WowClientDB_Base* db, const char* filename, int32_t linenumber) { db->Load(filename, linenumber); @@ -51,6 +52,7 @@ void StaticDBLoadAll(void (*loadFn)(WowClientDB_Base*, const char*, int32_t)) { loadFn(&g_paperDollItemFrameDB, __FILE__, __LINE__); loadFn(&g_soundEntriesDB, __FILE__, __LINE__); loadFn(&g_soundEntriesAdvancedDB, __FILE__, __LINE__); + loadFn(&g_unitBloodLevelsDB, __FILE__, __LINE__); }; void ClientDBInitialize() { diff --git a/src/db/Db.hpp b/src/db/Db.hpp index c80eb0f..a985f4d 100644 --- a/src/db/Db.hpp +++ b/src/db/Db.hpp @@ -24,6 +24,7 @@ #include "db/rec/PaperDollItemFrameRec.hpp" #include "db/rec/SoundEntriesRec.hpp" #include "db/rec/SoundEntriesAdvancedRec.hpp" +#include "db/rec/UnitBloodLevelsRec.hpp" extern WowClientDB g_achievementDB; extern WowClientDB g_areaTableDB; @@ -47,6 +48,7 @@ extern WowClientDB g_mapDB; extern WowClientDB g_paperDollItemFrameDB; extern WowClientDB g_soundEntriesDB; extern WowClientDB g_soundEntriesAdvancedDB; +extern WowClientDB g_unitBloodLevelsDB; void ClientDBInitialize(); diff --git a/src/db/rec/UnitBloodLevelsRec.cpp b/src/db/rec/UnitBloodLevelsRec.cpp new file mode 100644 index 0000000..3d037ca --- /dev/null +++ b/src/db/rec/UnitBloodLevelsRec.cpp @@ -0,0 +1,41 @@ +// DO NOT EDIT: generated by whoa-autocode +#include "db/rec/UnitBloodLevelsRec.hpp" +#include "util/Locale.hpp" +#include "util/SFile.hpp" + +const char* UnitBloodLevelsRec::GetFilename() { + return "DBFilesClient\\UnitBloodLevels.dbc"; +} + +uint32_t UnitBloodLevelsRec::GetNumColumns() { + return 4; +} + +uint32_t UnitBloodLevelsRec::GetRowSize() { + return 16; +} + +bool UnitBloodLevelsRec::NeedIDAssigned() { + return false; +} + +int32_t UnitBloodLevelsRec::GetID() { + return this->m_ID; +} + +void UnitBloodLevelsRec::SetID(int32_t id) { + this->m_ID = id; +} + +bool UnitBloodLevelsRec::Read(SFile* f, const char* stringBuffer) { + if ( + !SFile::Read(f, &this->m_ID, sizeof(this->m_ID), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_violencelevel[0], sizeof(m_violencelevel[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_violencelevel[1], sizeof(m_violencelevel[0]), nullptr, nullptr, nullptr) + || !SFile::Read(f, &this->m_violencelevel[2], sizeof(m_violencelevel[0]), nullptr, nullptr, nullptr) + ) { + return false; + } + + return true; +} diff --git a/src/db/rec/UnitBloodLevelsRec.hpp b/src/db/rec/UnitBloodLevelsRec.hpp new file mode 100644 index 0000000..9b10ede --- /dev/null +++ b/src/db/rec/UnitBloodLevelsRec.hpp @@ -0,0 +1,23 @@ +// DO NOT EDIT: generated by whoa-autocode +#ifndef DB_REC_UNIT_BLOOD_LEVELS_REC_HPP +#define DB_REC_UNIT_BLOOD_LEVELS_REC_HPP + +#include + +class SFile; + +class UnitBloodLevelsRec { + public: + int32_t m_ID; + int32_t m_violencelevel[3]; + + static const char* GetFilename(); + static uint32_t GetNumColumns(); + static uint32_t GetRowSize(); + static bool NeedIDAssigned(); + int32_t GetID(); + void SetID(int32_t id); + bool Read(SFile* f, const char* stringBuffer); +}; + +#endif From 6860d86369c998e888e4d212817d891f95cff2b0 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 13 Feb 2026 14:32:55 -0600 Subject: [PATCH 231/269] feat(object): add CGUnit_C::RefreshDataPointers --- src/object/client/CGUnit_C.cpp | 78 +++++++++++++++++++++++++++++++--- src/object/client/CGUnit_C.hpp | 18 +++++++- 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/object/client/CGUnit_C.cpp b/src/object/client/CGUnit_C.cpp index 493f890..d167e26 100644 --- a/src/object/client/CGUnit_C.cpp +++ b/src/object/client/CGUnit_C.cpp @@ -2,6 +2,7 @@ #include "object/client/ObjMgr.hpp" #include "db/Db.hpp" #include "ui/Game.hpp" +#include WOWGUID CGUnit_C::s_activeMover; @@ -95,6 +96,10 @@ const char* CGUnit_C::GetDisplayRaceNameFromRecord(const ChrRacesRec* raceRec, U CGUnit_C::CGUnit_C(uint32_t time, CClientObjCreate& objCreate) : CGObject_C(time, objCreate) { // TODO + + this->RefreshDataPointers(); + + // TODO } CGUnit_C::~CGUnit_C() { @@ -115,16 +120,22 @@ int32_t CGUnit_C::CanBeTargetted() { return this->CanHighlight(); } +int32_t CGUnit_C::GetDisplayID() const { + // Prefer local display ID if set and unit's display ID hasn't been overridden from unit's + // native display ID. + if (this->GetLocalDisplayID() && this->GetDisplayID() == this->GetNativeDisplayID()) { + return this->GetLocalDisplayID(); + } + + return this->CGUnit::GetDisplayID(); +} + int32_t CGUnit_C::GetLocalDisplayID() const { return this->m_localDisplayID; } CreatureModelDataRec* CGUnit_C::GetModelData() const { - // Prefer local display ID if set and unit's display ID hasn't been overridden from unit's - // native display ID; otherwise prefer overridden display ID. - auto displayID = this->GetLocalDisplayID() && this->GetDisplayID() == this->GetNativeDisplayID() - ? this->GetLocalDisplayID() - : this->GetDisplayID(); + auto displayID = this->GetDisplayID(); auto creatureDisplayInfoRec = g_creatureDisplayInfoDB.GetRecord(displayID); @@ -170,6 +181,63 @@ void CGUnit_C::PostMovementUpdate(const CClientMoveUpdate& move, int32_t activeM // TODO } +void CGUnit_C::RefreshDataPointers() { + auto displayID = this->GetDisplayID(); + + // Display info + + this->m_displayInfo = g_creatureDisplayInfoDB.GetRecord(displayID); + + if (!this->m_displayInfo) { + // TODO auto name = this->GetUnitName(0, 1); + // TODO SysMsgPrintf(2, 2, "NOUNITDISPLAYID|%d|%s", displayID, name); + + this->m_displayInfo = g_creatureDisplayInfoDB.GetRecordByIndex(0); + + if (!this->m_displayInfo) { + STORM_APP_FATAL("Error, NO creature display records found"); + } + } + + // Display info extra + + this->m_displayInfoExtra = g_creatureDisplayInfoExtraDB.GetRecord(this->m_displayInfo->m_extendedDisplayInfoID); + + // Model data + + this->m_modelData = g_creatureModelDataDB.GetRecord(this->m_displayInfo->m_modelID); + + // Sound data + + this->m_soundData = g_creatureSoundDataDB.GetRecord(this->m_displayInfo->m_soundID); + + if (!this->m_soundData) { + this->m_soundData = g_creatureSoundDataDB.GetRecord(this->m_modelData->m_soundID); + } + + // Blood levels + + this->m_bloodRec = g_unitBloodLevelsDB.GetRecord(this->m_displayInfo->m_bloodID); + + if (!this->m_bloodRec) { + this->m_bloodRec = g_unitBloodLevelsDB.GetRecord(this->m_modelData->m_bloodID); + + if (!this->m_bloodRec) { + this->m_bloodRec = g_unitBloodLevelsDB.GetRecordByIndex(0); + } + } + + // Creature stats + + if (this->GetType() == HIER_TYPE_UNIT) { + // TODO load creature stats + } + + // Flags + + // TODO set flags +} + void CGUnit_C::SetStorage(uint32_t* storage, uint32_t* saved) { this->CGObject_C::SetStorage(storage, saved); diff --git a/src/object/client/CGUnit_C.hpp b/src/object/client/CGUnit_C.hpp index 2d5e67f..5f4a1e2 100644 --- a/src/object/client/CGUnit_C.hpp +++ b/src/object/client/CGUnit_C.hpp @@ -9,7 +9,11 @@ class ChrClassesRec; class ChrRacesRec; +class CreatureDisplayInfoRec; +class CreatureDisplayInfoExtraRec; class CreatureModelDataRec; +class CreatureSoundDataRec; +class UnitBloodLevelsRec; class CGUnit_C : public CGObject_C, public CGUnit { public: @@ -31,15 +35,27 @@ class CGUnit_C : public CGObject_C, public CGUnit { // Public member functions CGUnit_C(uint32_t time, CClientObjCreate& objCreate); - int32_t GetLocalDisplayID() const; + int32_t GetDisplayID() const; CreatureModelDataRec* GetModelData() const; void PostInit(uint32_t time, const CClientObjCreate& init, bool a4); void PostMovementUpdate(const CClientMoveUpdate& move, int32_t activeMover); void SetStorage(uint32_t* storage, uint32_t* saved); + protected: + // Protected member functions + int32_t GetLocalDisplayID() const; + void RefreshDataPointers(); + private: // Private member variables // TODO + CreatureDisplayInfoRec* m_displayInfo; + CreatureDisplayInfoExtraRec* m_displayInfoExtra; + CreatureModelDataRec* m_modelData; + CreatureSoundDataRec* m_soundData; + // TODO + UnitBloodLevelsRec* m_bloodRec; + // TODO int32_t m_localDisplayID = 0; // TODO }; From 04c3dac38250c1bea8a0f49ede28efa53d3924e7 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 13 Feb 2026 21:10:02 -0600 Subject: [PATCH 232/269] feat(object): handle creature geosets and skins in CGUnit_C::PostInit --- src/component/CCharacterComponent.cpp | 72 +++++++++++++++++++++++++++ src/component/CCharacterComponent.hpp | 4 ++ src/model/CM2Model.cpp | 4 ++ src/model/CM2Model.hpp | 1 + src/object/client/CGUnit_C.cpp | 13 +++++ 5 files changed, 94 insertions(+) diff --git a/src/component/CCharacterComponent.cpp b/src/component/CCharacterComponent.cpp index 63e2a06..db3b5fe 100644 --- a/src/component/CCharacterComponent.cpp +++ b/src/component/CCharacterComponent.cpp @@ -121,6 +121,10 @@ bool ComponentCompressCallback(CVar* var, const char* oldValue, const char* valu return true; } +void ReplaceParticleColor(CM2Model* model, int32_t particleColorID) { + // TODO +} + int32_t CCharacterComponent::AddHandItem(CM2Model* model, const ItemDisplayInfoRec* displayRec, INVENTORY_SLOTS invSlot, SHEATHE_TYPE sheatheType, bool sheathed, bool shield, bool a7, int32_t visualID) { if (!model || !displayRec || invSlot > INVSLOT_TABARD) { return -1; @@ -247,6 +251,26 @@ CCharacterComponent* CCharacterComponent::AllocComponent() { return component; } +void CCharacterComponent::ApplyMonsterGeosets(CM2Model* model, const CreatureDisplayInfoRec* displayInfoRec) { + if (!model || !displayInfoRec || !displayInfoRec->m_creatureGeosetData) { + return; + } + + for (int32_t group = 100, dataOfs = 0; group < 900; group += 100, dataOfs += 4) { + auto section = (displayInfoRec->m_creatureGeosetData >> dataOfs) & 0xF; + + if (section) { + // Hide all sections in group + model->SetGeometryVisible(group, group + 99, false); + + // Show matching section + model->SetGeometryVisible(group + section, group + section, true); + } + } + + model->OptimizeVisibleGeometry(); +} + void CCharacterComponent::ComponentCloseFingers(CM2Model* model, COMP_HAND_SLOT handSlot) { uint32_t firstBone; uint32_t lastBone; @@ -789,6 +813,54 @@ void CCharacterComponent::RemoveLinkpt(CM2Model* model, GEOCOMPONENTLINKS link) } } +void CCharacterComponent::ReplaceMonsterSkin(CM2Model* model, const CreatureDisplayInfoRec* displayInfoRec, const CreatureModelDataRec* modelDataRec) { + if (!model || !displayInfoRec || !modelDataRec) { + return; + } + + CStatus status; + char texturePath[STORM_MAX_PATH]; + + // Copy model path to use as base path for texture + auto src = modelDataRec->m_modelName; + auto dst = texturePath; + while (*src) { + *dst++ = *src++; + } + *dst = '\0'; + + // Locate start of model file name + auto lastSlash = strrchr(texturePath, '\\'); + auto modelFileName = lastSlash ? lastSlash + 1 : texturePath; + + auto textureFlags = CGxTexFlags(GxTex_LinearMipLinear, 1, 1, 0, 0, 0, 1); + + for (uint32_t i = 0; i < 3; i++) { + auto textureName = displayInfoRec->m_textureVariation[i]; + + if (textureName[0] == '\0') { + continue; + } + + // Replace model file name with texture name + src = textureName; + dst = modelFileName; + while (*src) { + *dst++ = *src++; + } + *dst = '\0'; + + auto texture = TextureCreate(texturePath, textureFlags, &status, 0); + + if (texture) { + model->ReplaceTexture(11 + i, texture); + HandleClose(texture); + } + } + + ReplaceParticleColor(model, displayInfoRec->m_particleColorID); +} + void CCharacterComponent::UpdateBaseTexture(EGxTexCommand cmd, uint32_t width, uint32_t height, uint32_t depth, uint32_t mipLevel, void* userArg, uint32_t& texelStrideInBytes, const void*& texels) { auto component = static_cast(userArg); diff --git a/src/component/CCharacterComponent.hpp b/src/component/CCharacterComponent.hpp index 04e12f7..6b6637c 100644 --- a/src/component/CCharacterComponent.hpp +++ b/src/component/CCharacterComponent.hpp @@ -10,6 +10,8 @@ class CACHEENTRY; class CCharacterComponent; class CharSectionsRec; +class CreatureDisplayInfoRec; +class CreatureModelDataRec; class ItemDisplayInfoRec; struct BlpPalPixel; @@ -51,6 +53,7 @@ class CCharacterComponent { static int32_t AddHandItem(CM2Model* model, const ItemDisplayInfoRec* displayRec, INVENTORY_SLOTS invSlot, SHEATHE_TYPE sheatheType, bool sheathed, bool shield, bool a7, int32_t a8); static void AddLink(CM2Model* parent, GEOCOMPONENTLINKS link, char const* modelPath, char const* texturePath, int32_t visualID, const ItemDisplayInfoRec* displayRec); static CCharacterComponent* AllocComponent(); + static void ApplyMonsterGeosets(CM2Model* model, const CreatureDisplayInfoRec* displayInfoRec); static void ComponentCloseFingers(CM2Model* model, COMP_HAND_SLOT handSlot); static void ComponentOpenFingers(CM2Model* model, COMP_HAND_SLOT handSlot); static HTEXTURE CreateTexture(const char* fileName, CStatus* status); @@ -68,6 +71,7 @@ class CCharacterComponent { static void PasteTransparent4Bit(void* srcTexture, const BlpPalPixel* srcPal, MipBits* dstMips, const C2iVector& dstPos, uint32_t dstWidth, const C2iVector& srcPos, const C2iVector& srcSize, TCTEXTUREINFO& srcInfo, int32_t srcMipLevel, int32_t dstMipLevelOfs); static void PasteTransparent8Bit(void* srcTexture, const BlpPalPixel* srcPal, MipBits* dstMips, const C2iVector& dstPos, uint32_t dstWidth, const C2iVector& srcPos, const C2iVector& srcSize, TCTEXTUREINFO& srcInfo, int32_t srcMipLevel, int32_t dstMipLevelOfs); static void RemoveLinkpt(CM2Model* model, GEOCOMPONENTLINKS link); + static void ReplaceMonsterSkin(CM2Model* model, const CreatureDisplayInfoRec* displayInfoRec, const CreatureModelDataRec* modelDataRec); static void UpdateBaseTexture(EGxTexCommand cmd, uint32_t width, uint32_t height, uint32_t depth, uint32_t mipLevel, void* userArg, uint32_t& texelStrideInBytes, const void*& texels); // Member variables diff --git a/src/model/CM2Model.cpp b/src/model/CM2Model.cpp index 6f081f8..49ace78 100644 --- a/src/model/CM2Model.cpp +++ b/src/model/CM2Model.cpp @@ -1604,6 +1604,10 @@ void CM2Model::LinkToCallbackListTail() { this->m_shared->m_callbackListTail = &this->m_callbackNext; } +void CM2Model::OptimizeVisibleGeometry() { + // TODO +} + int32_t CM2Model::ProcessCallbacks() { // TODO return 1; diff --git a/src/model/CM2Model.hpp b/src/model/CM2Model.hpp index 821b498..9ca72cb 100644 --- a/src/model/CM2Model.hpp +++ b/src/model/CM2Model.hpp @@ -178,6 +178,7 @@ class CM2Model { int32_t IsDrawable(int32_t a2, int32_t a3); int32_t IsLoaded(int32_t a2, int32_t attachments); void LinkToCallbackListTail(); + void OptimizeVisibleGeometry(); int32_t ProcessCallbacks(); void ProcessCallbacksRecursive(); uint32_t Release(); diff --git a/src/object/client/CGUnit_C.cpp b/src/object/client/CGUnit_C.cpp index d167e26..d040676 100644 --- a/src/object/client/CGUnit_C.cpp +++ b/src/object/client/CGUnit_C.cpp @@ -1,4 +1,6 @@ #include "object/client/CGUnit_C.hpp" +#include "component/CCharacterComponent.hpp" +#include "model/Model2.hpp" #include "object/client/ObjMgr.hpp" #include "db/Db.hpp" #include "ui/Game.hpp" @@ -175,6 +177,17 @@ void CGUnit_C::PostInit(uint32_t time, const CClientObjCreate& init, bool a4) { this->CGObject_C::PostInit(time, init, a4); // TODO + + if (this->m_displayInfo) { + CCharacterComponent::ApplyMonsterGeosets(this->m_model, this->m_displayInfo); + CCharacterComponent::ReplaceMonsterSkin(this->m_model, this->m_displayInfo, this->m_modelData); + + if (this->m_modelData) { + this->m_model->m_flag4 = (this->m_modelData->m_flags & 0x200) ? true : false; + } + } + + // TODO } void CGUnit_C::PostMovementUpdate(const CClientMoveUpdate& move, int32_t activeMover) { From 05d949523cc2ef7fe165f8c9f8657ea871274cd3 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 14 Feb 2026 05:05:38 -0600 Subject: [PATCH 233/269] feat(ui): add CGWorldFrame::OnFrameRender --- src/ui/game/CGWorldFrame.cpp | 41 ++++++++++++++++++++++++++++++++++++ src/ui/game/CGWorldFrame.hpp | 6 ++++++ src/ui/game/PlayerName.cpp | 9 ++++++++ src/ui/game/PlayerName.hpp | 8 +++++++ 4 files changed, 64 insertions(+) create mode 100644 src/ui/game/PlayerName.cpp create mode 100644 src/ui/game/PlayerName.hpp diff --git a/src/ui/game/CGWorldFrame.cpp b/src/ui/game/CGWorldFrame.cpp index db9a49e..1300565 100644 --- a/src/ui/game/CGWorldFrame.cpp +++ b/src/ui/game/CGWorldFrame.cpp @@ -1,5 +1,9 @@ #include "ui/game/CGWorldFrame.hpp" +#include "gx/Shader.hpp" +#include "gx/Transform.hpp" +#include "ui/game/PlayerName.hpp" #include +#include CSimpleFrame* CGWorldFrame::Create(CSimpleFrame* parent) { // TODO use CDataAllocator @@ -7,6 +11,27 @@ CSimpleFrame* CGWorldFrame::Create(CSimpleFrame* parent) { return STORM_NEW(CGWorldFrame)(parent); } +void CGWorldFrame::RenderWorld(void* param) { + auto frame = reinterpret_cast(param); + + C44Matrix savedProj; + GxXformProjection(savedProj); + + C44Matrix savedView; + GxXformView(savedView); + + frame->OnWorldUpdate(); + PlayerNameUpdateWorldText(); + + frame->OnWorldRender(); + PlayerNameRenderWorldText(); + + GxXformSetProjection(savedProj); + GxXformSetView(savedView); + + CShaderEffect::UpdateProjMatrix(); +} + CGWorldFrame::CGWorldFrame(CSimpleFrame* parent) : CSimpleFrame(parent) { // TODO @@ -20,3 +45,19 @@ CGWorldFrame::CGWorldFrame(CSimpleFrame* parent) : CSimpleFrame(parent) { // TODO } + +void CGWorldFrame::OnFrameRender(CRenderBatch* batch, uint32_t layer) { + this->CSimpleFrame::OnFrameRender(batch, layer); + + if (layer == DRAWLAYER_BACKGROUND) { + batch->QueueCallback(&CGWorldFrame::RenderWorld, this); + } +} + +void CGWorldFrame::OnWorldRender() { + // TODO +} + +void CGWorldFrame::OnWorldUpdate() { + // TODO +} diff --git a/src/ui/game/CGWorldFrame.hpp b/src/ui/game/CGWorldFrame.hpp index ce95231..6cec83a 100644 --- a/src/ui/game/CGWorldFrame.hpp +++ b/src/ui/game/CGWorldFrame.hpp @@ -11,9 +11,15 @@ class CGWorldFrame : public CSimpleFrame { // Static functions static CSimpleFrame* Create(CSimpleFrame* parent); + static void RenderWorld(void* param); + + // Virtual member functions + virtual void OnFrameRender(CRenderBatch* batch, uint32_t layer); // Member functions CGWorldFrame(CSimpleFrame* parent); + void OnWorldRender(); + void OnWorldUpdate(); }; #endif diff --git a/src/ui/game/PlayerName.cpp b/src/ui/game/PlayerName.cpp new file mode 100644 index 0000000..a871c8c --- /dev/null +++ b/src/ui/game/PlayerName.cpp @@ -0,0 +1,9 @@ +#include "ui/game/PlayerName.hpp" + +void PlayerNameRenderWorldText() { + // TODO +} + +void PlayerNameUpdateWorldText() { + // TODO +} diff --git a/src/ui/game/PlayerName.hpp b/src/ui/game/PlayerName.hpp new file mode 100644 index 0000000..a4e320e --- /dev/null +++ b/src/ui/game/PlayerName.hpp @@ -0,0 +1,8 @@ +#ifndef UI_GAME_PLAYER_NAME_HPP +#define UI_GAME_PLAYER_NAME_HPP + +void PlayerNameRenderWorldText(); + +void PlayerNameUpdateWorldText(); + +#endif From d859670f7ba96e90b54b51d6ee34c46f9aa5bd35 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 14 Feb 2026 08:23:58 -0600 Subject: [PATCH 234/269] feat(ui): set frame strata in CGWorldFrame ctor --- src/ui/game/CGWorldFrame.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ui/game/CGWorldFrame.cpp b/src/ui/game/CGWorldFrame.cpp index 1300565..3446f1b 100644 --- a/src/ui/game/CGWorldFrame.cpp +++ b/src/ui/game/CGWorldFrame.cpp @@ -39,6 +39,8 @@ CGWorldFrame::CGWorldFrame(CSimpleFrame* parent) : CSimpleFrame(parent) { // TODO + this->SetFrameStrata(FRAME_STRATA_WORLD); + this->EnableEvent(SIMPLE_EVENT_KEY, -1); this->EnableEvent(SIMPLE_EVENT_MOUSE, -1); this->EnableEvent(SIMPLE_EVENT_MOUSEWHEEL, -1); From d77b1dfd67eefe3fcfb780d99bdd0f0e7ea07187 Mon Sep 17 00:00:00 2001 From: Tristan Cormier Date: Sat, 14 Feb 2026 20:27:36 -0500 Subject: [PATCH 235/269] chore(net): rename character creation NETMESSAGE enum members --- src/net/Types.hpp | 4 ++-- src/net/connection/RealmConnection.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/net/Types.hpp b/src/net/Types.hpp index 3515db6..7db2ddb 100644 --- a/src/net/Types.hpp +++ b/src/net/Types.hpp @@ -60,11 +60,11 @@ enum NETMESSAGE { CMSG_AUTH_SRP6_BEGIN = 0x0033, CMSG_AUTH_SRP6_PROOF = 0x0034, CMSG_AUTH_SRP6_RECODE = 0x0035, - CMSG_CREATE_CHARACTER = 0x0036, + CMSG_CHAR_CREATE = 0x0036, CMSG_ENUM_CHARACTERS = 0x0037, CMSG_CHAR_DELETE = 0x0038, SMSG_AUTH_SRP6_RESPONSE = 0x0039, - SMSG_CREATE_CHAR = 0x003A, + SMSG_CHAR_CREATE = 0x003A, SMSG_ENUM_CHARACTERS_RESULT = 0x003B, SMSG_DELETE_CHAR = 0x003C, CMSG_PLAYER_LOGIN = 0x003D, diff --git a/src/net/connection/RealmConnection.cpp b/src/net/connection/RealmConnection.cpp index a60549e..9bc0a6a 100644 --- a/src/net/connection/RealmConnection.cpp +++ b/src/net/connection/RealmConnection.cpp @@ -19,7 +19,7 @@ int32_t RealmConnection::MessageHandler(void* param, NETMESSAGE msgId, uint32_t break; } - case SMSG_CREATE_CHAR: { + case SMSG_CHAR_CREATE: { // TODO break; } @@ -91,7 +91,7 @@ RealmConnection::RealmConnection(RealmResponse* realmResponse) { this->SetMessageHandler(SMSG_AUTH_RESPONSE, &RealmConnection::MessageHandler, this); this->SetMessageHandler(SMSG_ADDON_INFO, &RealmConnection::MessageHandler, this); this->SetMessageHandler(SMSG_ENUM_CHARACTERS_RESULT, &RealmConnection::MessageHandler, this); - this->SetMessageHandler(SMSG_CREATE_CHAR, &RealmConnection::MessageHandler, this); + this->SetMessageHandler(SMSG_CHAR_CREATE, &RealmConnection::MessageHandler, this); this->SetMessageHandler(SMSG_CHARACTER_LOGIN_FAILED, &RealmConnection::MessageHandler, this); this->SetMessageHandler(SMSG_LOGOUT_COMPLETE, &RealmConnection::MessageHandler, this); this->SetMessageHandler(SMSG_LOGOUT_CANCEL_ACK, &RealmConnection::MessageHandler, this); From 71a31e19bd355021e416d9d882f6117841930fe9 Mon Sep 17 00:00:00 2001 From: Tristan Cormier Date: Sat, 14 Feb 2026 20:36:19 -0500 Subject: [PATCH 236/269] chore(glue): rename IDLE_5 to IDLE_CREATE_CHARACTER --- src/glue/CGlueMgr.cpp | 2 +- src/glue/CGlueMgr.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/glue/CGlueMgr.cpp b/src/glue/CGlueMgr.cpp index 6a21ac4..6528583 100644 --- a/src/glue/CGlueMgr.cpp +++ b/src/glue/CGlueMgr.cpp @@ -1129,7 +1129,7 @@ void CGlueMgr::StatusDialogClick() { } case IDLE_REALM_LIST: - case IDLE_5: + case IDLE_CREATE_CHARACTER: case IDLE_DELETE_CHARACTER: case IDLE_ENTER_WORLD: { ClientServices::Connection()->Cancel(2); diff --git a/src/glue/CGlueMgr.hpp b/src/glue/CGlueMgr.hpp index 258fbee..38e369b 100644 --- a/src/glue/CGlueMgr.hpp +++ b/src/glue/CGlueMgr.hpp @@ -20,7 +20,7 @@ class CGlueMgr { IDLE_ACCOUNT_LOGIN = 2, IDLE_CHARACTER_LIST = 3, IDLE_REALM_LIST = 4, - IDLE_5 = 5, + IDLE_CREATE_CHARACTER = 5, IDLE_DELETE_CHARACTER = 6, IDLE_7 = 7, IDLE_8 = 8, From 86084516cdf47b46f2b5a3a048e66ea25ebce485 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 15 Feb 2026 12:42:14 -0600 Subject: [PATCH 237/269] feat(ui): add CSimpleCamera --- lib/typhoon | 2 +- src/ui/simple/CSimpleCamera.cpp | 52 +++++++++++++++++++++++++++++++++ src/ui/simple/CSimpleCamera.hpp | 35 ++++++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/ui/simple/CSimpleCamera.cpp create mode 100644 src/ui/simple/CSimpleCamera.hpp diff --git a/lib/typhoon b/lib/typhoon index 1c9e783..a7733b6 160000 --- a/lib/typhoon +++ b/lib/typhoon @@ -1 +1 @@ -Subproject commit 1c9e7831c874068e7c939a7dea8790eef6513d78 +Subproject commit a7733b6a8c2d52f081fbd74ca40d7ca8f94e1209 diff --git a/src/ui/simple/CSimpleCamera.cpp b/src/ui/simple/CSimpleCamera.cpp new file mode 100644 index 0000000..db439c1 --- /dev/null +++ b/src/ui/simple/CSimpleCamera.cpp @@ -0,0 +1,52 @@ +#include "ui/simple/CSimpleCamera.hpp" + +CSimpleCamera::CSimpleCamera(float nearZ, float farZ, float fov) { + this->float10 = 0.0f; + + this->m_nearZ = nearZ; + this->m_farZ = farZ; + this->m_fov = fov; + this->m_aspect = 1.0f; + + this->SetFacing(0.0f, 0.0f, 0.0f); +} + +float CSimpleCamera::FOV() { + return this->m_fov; +} + +C3Vector CSimpleCamera::Forward() const { + return { this->m_facing.a0, this->m_facing.a1, this->m_facing.a2 }; +} + +C3Vector CSimpleCamera::Right() const { + return { this->m_facing.b0, this->m_facing.b1, this->m_facing.b2 }; +} + +void CSimpleCamera::SetFacing(const C3Vector& forward) { + // TODO +} + +void CSimpleCamera::SetFacing(const C3Vector& forward, const C3Vector& up) { + // TODO +} + +void CSimpleCamera::SetFacing(float yaw, float pitch, float roll) { + this->m_facing.FromEulerAnglesZYX(yaw, pitch, roll); +} + +void CSimpleCamera::SetFarZ(float farZ) { + this->m_farZ = farZ; +} + +void CSimpleCamera::SetFieldOfView(float fov) { + this->m_fov = fov; +} + +void CSimpleCamera::SetNearZ(float nearZ) { + this->m_nearZ = nearZ; +} + +C3Vector CSimpleCamera::Up() const { + return { this->m_facing.c0, this->m_facing.c1, this->m_facing.c2 }; +} diff --git a/src/ui/simple/CSimpleCamera.hpp b/src/ui/simple/CSimpleCamera.hpp new file mode 100644 index 0000000..5f8c943 --- /dev/null +++ b/src/ui/simple/CSimpleCamera.hpp @@ -0,0 +1,35 @@ +#ifndef UI_SIMPLE_C_SIMPLE_CAMERA_HPP +#define UI_SIMPLE_C_SIMPLE_CAMERA_HPP + +#include +#include + +class CSimpleCamera { + public: + // Virtual public member functions + virtual float FOV(); + virtual C3Vector Forward() const; + virtual C3Vector Right() const; + virtual C3Vector Up() const; + + // Public member functions + CSimpleCamera(float nearZ, float farZ, float fov); + void SetFacing(const C3Vector& forward); + void SetFacing(const C3Vector& forward, const C3Vector& up); + void SetFacing(float yaw, float pitch, float roll); + void SetFarZ(float farZ); + void SetFieldOfView(float fov); + void SetNearZ(float nearZ); + + protected: + // Protected member variables + C3Vector m_position; + float float10; + C33Matrix m_facing; + float m_nearZ; + float m_farZ; + float m_fov; + float m_aspect; +}; + +#endif From 0e6f65f32e98cc98b65b29fee430db0f7f40161c Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 15 Feb 2026 20:12:01 -0600 Subject: [PATCH 238/269] feat(ui): implement CSimpleCamera::SetFacing with forward vector --- src/ui/simple/CSimpleCamera.cpp | 53 ++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleCamera.cpp b/src/ui/simple/CSimpleCamera.cpp index db439c1..11f2ff5 100644 --- a/src/ui/simple/CSimpleCamera.cpp +++ b/src/ui/simple/CSimpleCamera.cpp @@ -1,4 +1,55 @@ #include "ui/simple/CSimpleCamera.hpp" +#include + +namespace { + +void FaceDirection(const C3Vector& direction, C3Vector& xPrime, C3Vector& yPrime, C3Vector& zPrime) { + STORM_ASSERT(CMath::fnotequal(direction.SquaredMag(), 0.0f)); + + // Forward + xPrime = direction; + + // Right + if (CMath::fequal(xPrime.SquaredMag(), 0.0f)) { + yPrime.x = 1.0f; + yPrime.y = 0.0f; + yPrime.z = 0.0f; + } else { + yPrime.x = -xPrime.y; + yPrime.y = xPrime.x; + yPrime.z = 0.0f; + + CMath::normalize(yPrime.x, yPrime.y); + } + + // Up (Forward cross Right) + zPrime = C3Vector::Cross(xPrime, yPrime); +} + +void BuildBillboardMatrix(const C3Vector& direction, C33Matrix& rotation) { + C3Vector xPrime = {}; + C3Vector yPrime = {}; + C3Vector zPrime = {}; + + FaceDirection(direction, xPrime, yPrime, zPrime); + + // Forward + rotation.a0 = xPrime.x; + rotation.a1 = xPrime.y; + rotation.a2 = xPrime.z; + + // Right + rotation.b0 = yPrime.x; + rotation.b1 = yPrime.y; + rotation.b2 = yPrime.z; + + // Up + rotation.c0 = zPrime.x; + rotation.c1 = zPrime.y; + rotation.c2 = zPrime.z; +} + +} CSimpleCamera::CSimpleCamera(float nearZ, float farZ, float fov) { this->float10 = 0.0f; @@ -24,7 +75,7 @@ C3Vector CSimpleCamera::Right() const { } void CSimpleCamera::SetFacing(const C3Vector& forward) { - // TODO + BuildBillboardMatrix(forward, this->m_facing); } void CSimpleCamera::SetFacing(const C3Vector& forward, const C3Vector& up) { From 2711c752ba3897f50c9b00e9365c561b7b9fc537 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 15 Feb 2026 20:28:56 -0600 Subject: [PATCH 239/269] chore(build): update typhoon --- lib/typhoon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/typhoon b/lib/typhoon index a7733b6..dc8f10e 160000 --- a/lib/typhoon +++ b/lib/typhoon @@ -1 +1 @@ -Subproject commit a7733b6a8c2d52f081fbd74ca40d7ca8f94e1209 +Subproject commit dc8f10e407daa8bdf7e90d9438b55d5883780825 From 7d491570e486900cb8fbf752f4e4b58ca3fea74e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 15 Feb 2026 21:02:06 -0600 Subject: [PATCH 240/269] feat(ui): add CSimpleCamera::GetScene --- src/ui/simple/CSimpleCamera.cpp | 11 ++++++++++- src/ui/simple/CSimpleCamera.hpp | 5 ++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/ui/simple/CSimpleCamera.cpp b/src/ui/simple/CSimpleCamera.cpp index 11f2ff5..0164145 100644 --- a/src/ui/simple/CSimpleCamera.cpp +++ b/src/ui/simple/CSimpleCamera.cpp @@ -1,4 +1,5 @@ #include "ui/simple/CSimpleCamera.hpp" +#include "model/Model2.hpp" #include namespace { @@ -52,7 +53,7 @@ void BuildBillboardMatrix(const C3Vector& direction, C33Matrix& rotation) { } CSimpleCamera::CSimpleCamera(float nearZ, float farZ, float fov) { - this->float10 = 0.0f; + this->m_scene = nullptr; this->m_nearZ = nearZ; this->m_farZ = farZ; @@ -70,6 +71,14 @@ C3Vector CSimpleCamera::Forward() const { return { this->m_facing.a0, this->m_facing.a1, this->m_facing.a2 }; } +CM2Scene* CSimpleCamera::GetScene() { + if (!this->m_scene) { + this->m_scene = M2CreateScene(); + } + + return this->m_scene; +} + C3Vector CSimpleCamera::Right() const { return { this->m_facing.b0, this->m_facing.b1, this->m_facing.b2 }; } diff --git a/src/ui/simple/CSimpleCamera.hpp b/src/ui/simple/CSimpleCamera.hpp index 5f8c943..2f2fdda 100644 --- a/src/ui/simple/CSimpleCamera.hpp +++ b/src/ui/simple/CSimpleCamera.hpp @@ -4,6 +4,8 @@ #include #include +class CM2Scene; + class CSimpleCamera { public: // Virtual public member functions @@ -14,6 +16,7 @@ class CSimpleCamera { // Public member functions CSimpleCamera(float nearZ, float farZ, float fov); + CM2Scene* GetScene(); void SetFacing(const C3Vector& forward); void SetFacing(const C3Vector& forward, const C3Vector& up); void SetFacing(float yaw, float pitch, float roll); @@ -23,8 +26,8 @@ class CSimpleCamera { protected: // Protected member variables + CM2Scene* m_scene; C3Vector m_position; - float float10; C33Matrix m_facing; float m_nearZ; float m_farZ; From 4628b7d831b694d8fedf9673f0c58c5795a120bd Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 17 Feb 2026 07:02:15 -0600 Subject: [PATCH 241/269] feat(ui): add CSimpleCamera::SetGxProjectionAndView --- src/ui/simple/CSimpleCamera.cpp | 20 ++++++++++++++++++++ src/ui/simple/CSimpleCamera.hpp | 2 ++ 2 files changed, 22 insertions(+) diff --git a/src/ui/simple/CSimpleCamera.cpp b/src/ui/simple/CSimpleCamera.cpp index 0164145..8a35c2f 100644 --- a/src/ui/simple/CSimpleCamera.cpp +++ b/src/ui/simple/CSimpleCamera.cpp @@ -1,4 +1,5 @@ #include "ui/simple/CSimpleCamera.hpp" +#include "gx/Transform.hpp" #include "model/Model2.hpp" #include @@ -107,6 +108,25 @@ void CSimpleCamera::SetNearZ(float nearZ) { this->m_nearZ = nearZ; } +void CSimpleCamera::SetGxProjectionAndView(const CRect& projRect) { + // Projection + + this->m_aspect = (projRect.maxX - projRect.minX) / (projRect.maxY - projRect.minY); + + C44Matrix projMat; + GxuXformCreateProjection_Exact(this->m_fov * 0.6f, this->m_aspect, this->m_nearZ, this->m_farZ, projMat); + + GxXformSetProjection(projMat); + + // View + + C3Vector eye; + C44Matrix viewMat; + GxuXformCreateLookAtSgCompat(eye, this->Forward(), this->Up(), viewMat); + + GxXformSetView(viewMat); +} + C3Vector CSimpleCamera::Up() const { return { this->m_facing.c0, this->m_facing.c1, this->m_facing.c2 }; } diff --git a/src/ui/simple/CSimpleCamera.hpp b/src/ui/simple/CSimpleCamera.hpp index 2f2fdda..e39cea6 100644 --- a/src/ui/simple/CSimpleCamera.hpp +++ b/src/ui/simple/CSimpleCamera.hpp @@ -2,6 +2,7 @@ #define UI_SIMPLE_C_SIMPLE_CAMERA_HPP #include +#include #include class CM2Scene; @@ -22,6 +23,7 @@ class CSimpleCamera { void SetFacing(float yaw, float pitch, float roll); void SetFarZ(float farZ); void SetFieldOfView(float fov); + void SetGxProjectionAndView(const CRect& projRect); void SetNearZ(float nearZ); protected: From 6bcaec1fe7dc47d156afe57903c85cd741ac0218 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 17 Feb 2026 07:06:31 -0600 Subject: [PATCH 242/269] fix(ui): use FOV getter in CSimpleCamera::SetGxProjectionAndView --- src/ui/simple/CSimpleCamera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/simple/CSimpleCamera.cpp b/src/ui/simple/CSimpleCamera.cpp index 8a35c2f..e03757a 100644 --- a/src/ui/simple/CSimpleCamera.cpp +++ b/src/ui/simple/CSimpleCamera.cpp @@ -114,7 +114,7 @@ void CSimpleCamera::SetGxProjectionAndView(const CRect& projRect) { this->m_aspect = (projRect.maxX - projRect.minX) / (projRect.maxY - projRect.minY); C44Matrix projMat; - GxuXformCreateProjection_Exact(this->m_fov * 0.6f, this->m_aspect, this->m_nearZ, this->m_farZ, projMat); + GxuXformCreateProjection_Exact(this->FOV() * 0.6f, this->m_aspect, this->m_nearZ, this->m_farZ, projMat); GxXformSetProjection(projMat); From b3c07f06076755ba1de85b4b23e9dccc0ede24f8 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 17 Feb 2026 07:15:14 -0600 Subject: [PATCH 243/269] fix(ui): const correctness for CSimpleCamera::FOV --- src/ui/simple/CSimpleCamera.cpp | 2 +- src/ui/simple/CSimpleCamera.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/simple/CSimpleCamera.cpp b/src/ui/simple/CSimpleCamera.cpp index e03757a..990c982 100644 --- a/src/ui/simple/CSimpleCamera.cpp +++ b/src/ui/simple/CSimpleCamera.cpp @@ -64,7 +64,7 @@ CSimpleCamera::CSimpleCamera(float nearZ, float farZ, float fov) { this->SetFacing(0.0f, 0.0f, 0.0f); } -float CSimpleCamera::FOV() { +float CSimpleCamera::FOV() const { return this->m_fov; } diff --git a/src/ui/simple/CSimpleCamera.hpp b/src/ui/simple/CSimpleCamera.hpp index e39cea6..407cdb6 100644 --- a/src/ui/simple/CSimpleCamera.hpp +++ b/src/ui/simple/CSimpleCamera.hpp @@ -10,7 +10,7 @@ class CM2Scene; class CSimpleCamera { public: // Virtual public member functions - virtual float FOV(); + virtual float FOV() const; virtual C3Vector Forward() const; virtual C3Vector Right() const; virtual C3Vector Up() const; From 50685c7cc04d2e231679a6aa76c2119eea48464e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 17 Feb 2026 12:43:01 -0600 Subject: [PATCH 244/269] chore(build): update typhoon --- lib/typhoon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/typhoon b/lib/typhoon index dc8f10e..4ba7e0a 160000 --- a/lib/typhoon +++ b/lib/typhoon @@ -1 +1 @@ -Subproject commit dc8f10e407daa8bdf7e90d9438b55d5883780825 +Subproject commit 4ba7e0a6c3836254daf97bab159807fae6cab039 From 214534893577b2dfde907233c22f7d0d5e232ac4 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 17 Feb 2026 12:43:28 -0600 Subject: [PATCH 245/269] feat(world): add CWorld::GetFarClip and CWorld::GetNearClip --- src/world/CWorld.cpp | 10 ++++++++++ src/world/CWorld.hpp | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/src/world/CWorld.cpp b/src/world/CWorld.cpp index 1027380..a49ceaf 100644 --- a/src/world/CWorld.cpp +++ b/src/world/CWorld.cpp @@ -10,9 +10,11 @@ uint32_t CWorld::s_curTimeMs; float CWorld::s_curTimeSec; uint32_t CWorld::s_enables; uint32_t CWorld::s_enables2; +float CWorld::s_farClip; uint32_t CWorld::s_gameTimeFixed; float CWorld::s_gameTimeSec; CM2Scene* CWorld::s_m2Scene; +float CWorld::s_nearClip = 0.1f; uint32_t CWorld::s_tickTimeFixed; uint32_t CWorld::s_tickTimeMs; float CWorld::s_tickTimeSec; @@ -55,6 +57,10 @@ float CWorld::GetCurTimeSec() { return CWorld::s_curTimeSec; } +float CWorld::GetFarClip() { + return CWorld::s_farClip; +} + uint32_t CWorld::GetFixedPrecisionTime(float timeSec) { return static_cast(timeSec * 1024.0f); } @@ -71,6 +77,10 @@ CM2Scene* CWorld::GetM2Scene() { return CWorld::s_m2Scene; } +float CWorld::GetNearClip() { + return CWorld::s_nearClip; +} + uint32_t CWorld::GetTickTimeFixed() { return CWorld::s_tickTimeFixed; } diff --git a/src/world/CWorld.hpp b/src/world/CWorld.hpp index 0ea3682..f181a0e 100644 --- a/src/world/CWorld.hpp +++ b/src/world/CWorld.hpp @@ -57,9 +57,11 @@ class CWorld { static HWORLDOBJECT AddObject(CM2Model* model, void* handler, void* handlerParam, uint64_t param64, uint32_t param32, uint32_t objFlags); static uint32_t GetCurTimeMs(); static float GetCurTimeSec(); + static float GetFarClip(); static uint32_t GetGameTimeFixed(); static float GetGameTimeSec(); static CM2Scene* GetM2Scene(); + static float GetNearClip(); static uint32_t GetTickTimeFixed(); static uint32_t GetTickTimeMs(); static float GetTickTimeSec(); @@ -72,9 +74,11 @@ class CWorld { // Private static variables static uint32_t s_curTimeMs; static float s_curTimeSec; + static float s_farClip; static uint32_t s_gameTimeFixed; static float s_gameTimeSec; static CM2Scene* s_m2Scene; + static float s_nearClip; static uint32_t s_tickTimeFixed; static uint32_t s_tickTimeMs; static float s_tickTimeSec; From 09c016c9359bcd1c594f5c290acd495193a4eb12 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 17 Feb 2026 19:35:22 -0600 Subject: [PATCH 246/269] feat(world): set CMap::s_mapID in CMap::Load --- src/world/map/CMap.cpp | 7 ++++++- src/world/map/CMap.hpp | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/world/map/CMap.cpp b/src/world/map/CMap.cpp index f86ce96..9839f45 100644 --- a/src/world/map/CMap.cpp +++ b/src/world/map/CMap.cpp @@ -28,6 +28,7 @@ uint32_t* CMap::s_mapObjDefGroupHeap; uint32_t* CMap::s_mapObjDefHeap; uint32_t* CMap::s_mapObjGroupHeap; uint32_t* CMap::s_mapObjHeap; +int32_t CMap::s_mapID = -1; char CMap::s_mapName[256]; char CMap::s_mapPath[256]; char CMap::s_wdtFilename[256]; @@ -61,7 +62,7 @@ void CMap::Initialize() { // TODO } -void CMap::Load(const char* mapName, int32_t zoneID) { +void CMap::Load(const char* mapName, int32_t mapID) { // TODO auto nameOfs = SStrCopy(CMap::s_mapPath, "World\\Maps\\"); @@ -72,6 +73,10 @@ void CMap::Load(const char* mapName, int32_t zoneID) { SStrPrintf(CMap::s_wdtFilename, sizeof(CMap::s_wdtFilename), "%s\\%s.wdt", CMap::s_mapPath, CMap::s_mapName); // TODO + + CMap::s_mapID = mapID; + + // TODO } void CMap::MapMemInitialize() { diff --git a/src/world/map/CMap.hpp b/src/world/map/CMap.hpp index c70177b..372c6bb 100644 --- a/src/world/map/CMap.hpp +++ b/src/world/map/CMap.hpp @@ -23,6 +23,7 @@ class CMap { static uint32_t* s_mapObjDefHeap; static uint32_t* s_mapObjGroupHeap; static uint32_t* s_mapObjHeap; + static int32_t s_mapID; static char s_mapName[]; static char s_mapPath[]; static char s_wdtFilename[]; @@ -30,7 +31,7 @@ class CMap { // Static functions static CMapEntity* AllocEntity(int32_t a1); static void Initialize(); - static void Load(const char* mapName, int32_t zoneID); + static void Load(const char* mapName, int32_t mapID); static void MapMemInitialize(); }; From 703dc26df720a2969b024f20e45a16b63a891ccf Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 17 Feb 2026 19:37:19 -0600 Subject: [PATCH 247/269] feat(world): implement CWorldParam::FarClipCallback --- src/world/CWorld.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/world/CWorld.hpp | 2 ++ src/world/CWorldParam.cpp | 4 +++- src/world/CWorldParam.hpp | 2 +- 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/world/CWorld.cpp b/src/world/CWorld.cpp index a49ceaf..bb8726a 100644 --- a/src/world/CWorld.cpp +++ b/src/world/CWorld.cpp @@ -2,6 +2,7 @@ #include "gx/Gx.hpp" #include "gx/Shader.hpp" #include "model/Model2.hpp" +#include "world/CWorldParam.hpp" #include "world/Map.hpp" #include "world/Weather.hpp" #include @@ -15,11 +16,31 @@ uint32_t CWorld::s_gameTimeFixed; float CWorld::s_gameTimeSec; CM2Scene* CWorld::s_m2Scene; float CWorld::s_nearClip = 0.1f; +float CWorld::s_prevFarClip; uint32_t CWorld::s_tickTimeFixed; uint32_t CWorld::s_tickTimeMs; float CWorld::s_tickTimeSec; Weather* CWorld::s_weather; +namespace { + +float AdjustFarClip(float farClip, int32_t mapID) { + float minFarClip = 183.33333f; + float maxFarClip = 1583.3334f; + + if (mapID < 530 || mapID == 575 || mapID == 543) { + if (!CWorldParam::cvar_farClipOverride || CWorldParam::cvar_farClipOverride->GetInt() < 1) { + maxFarClip = 791.66669f; + } + } else if (false /* TODO OsGetPhysicalMemory() <= 1073741824 */) { + maxFarClip = 791.66669f; + } + + return std::min(std::max(farClip, minFarClip), maxFarClip); +} + +} + HWORLDOBJECT CWorld::AddObject(CM2Model* model, void* handler, void* handlerParam, uint64_t param64, uint32_t param32, uint32_t objFlags) { auto entity = CMap::AllocEntity(objFlags & 0x8 ? true : false); @@ -157,6 +178,24 @@ int32_t CWorld::OnTick(const EVENT_DATA_TICK* data, void* param) { return 1; } +void CWorld::SetFarClip(float farClip) { + farClip = AdjustFarClip(farClip, CMap::s_mapID); + + if (CWorld::s_farClip == farClip) { + return; + } + + CWorld::s_prevFarClip = CWorld::s_farClip; + CWorld::s_farClip = farClip; + + // TODO CMapRenderChunk::DirtyPools(); + + CWorld::s_nearClip = 0.2f; + + // TODO dword_D1C410 = 1; + // TODO dword_ADEEE0 = 1; +} + void CWorld::SetUpdateTime(float tickTimeSec, uint32_t curTimeMs) { auto tickTimeFixed = CWorld::GetFixedPrecisionTime(tickTimeSec); diff --git a/src/world/CWorld.hpp b/src/world/CWorld.hpp index f181a0e..94a3cdd 100644 --- a/src/world/CWorld.hpp +++ b/src/world/CWorld.hpp @@ -68,6 +68,7 @@ class CWorld { static void Initialize(); static void LoadMap(const char* mapName, const C3Vector& position, int32_t zoneID); static int32_t OnTick(const EVENT_DATA_TICK* data, void* param); + static void SetFarClip(float farClip); static void SetUpdateTime(float tickTimeSec, uint32_t curTimeMs); private: @@ -79,6 +80,7 @@ class CWorld { static float s_gameTimeSec; static CM2Scene* s_m2Scene; static float s_nearClip; + static float s_prevFarClip; static uint32_t s_tickTimeFixed; static uint32_t s_tickTimeMs; static float s_tickTimeSec; diff --git a/src/world/CWorldParam.cpp b/src/world/CWorldParam.cpp index 4b5d68a..6d4dda4 100644 --- a/src/world/CWorldParam.cpp +++ b/src/world/CWorldParam.cpp @@ -1,4 +1,5 @@ #include "world/CWorldParam.hpp" +#include "world/CWorld.hpp" #include "console/CVar.hpp" CVar* CWorldParam::cvar_baseMip; @@ -53,7 +54,8 @@ bool CWorldParam::ExtShadowQualityCallback(CVar* var, const char* oldValue, cons } bool CWorldParam::FarClipCallback(CVar* var, const char* oldValue, const char* value, void* arg) { - // TODO + CWorld::SetFarClip(SStrToFloat(value)); + return true; } diff --git a/src/world/CWorldParam.hpp b/src/world/CWorldParam.hpp index 6e94460..a078072 100644 --- a/src/world/CWorldParam.hpp +++ b/src/world/CWorldParam.hpp @@ -1,7 +1,7 @@ #ifndef WORLD_C_WORLD_PARAM_HPP #define WORLD_C_WORLD_PARAM_HPP -class CVar; +#include "console/CVar.hpp" class CWorldParam { public: From f8f00b599e93938d0d051ab93208b9f5fc7faf79 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Tue, 17 Feb 2026 21:46:18 -0600 Subject: [PATCH 248/269] feat(world): set near clip and far clip in CWorld::LoadMap --- src/world/CWorld.cpp | 8 ++++++-- src/world/CWorld.hpp | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/world/CWorld.cpp b/src/world/CWorld.cpp index bb8726a..8a14a42 100644 --- a/src/world/CWorld.cpp +++ b/src/world/CWorld.cpp @@ -164,10 +164,14 @@ void CWorld::Initialize() { // TODO } -void CWorld::LoadMap(const char* mapName, const C3Vector& position, int32_t zoneID) { +void CWorld::LoadMap(const char* mapName, const C3Vector& position, int32_t mapID) { + CWorld::s_farClip = AdjustFarClip(CWorldParam::cvar_farClip->GetFloat(), mapID); + CWorld::s_nearClip = 0.2f; + CWorld::s_prevFarClip = CWorld::s_farClip; + // TODO - CMap::Load(mapName, zoneID); + CMap::Load(mapName, mapID); // TODO } diff --git a/src/world/CWorld.hpp b/src/world/CWorld.hpp index 94a3cdd..124e370 100644 --- a/src/world/CWorld.hpp +++ b/src/world/CWorld.hpp @@ -66,7 +66,7 @@ class CWorld { static uint32_t GetTickTimeMs(); static float GetTickTimeSec(); static void Initialize(); - static void LoadMap(const char* mapName, const C3Vector& position, int32_t zoneID); + static void LoadMap(const char* mapName, const C3Vector& position, int32_t mapID); static int32_t OnTick(const EVENT_DATA_TICK* data, void* param); static void SetFarClip(float farClip); static void SetUpdateTime(float tickTimeSec, uint32_t curTimeMs); From 8c518f7e6dcb0a80efcbb0fd8e9adef60eac4a0e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 18 Feb 2026 06:14:31 -0600 Subject: [PATCH 249/269] feat(gx): add EGxBuffer --- src/gx/Types.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gx/Types.hpp b/src/gx/Types.hpp index 9ceaf2d..481e112 100644 --- a/src/gx/Types.hpp +++ b/src/gx/Types.hpp @@ -54,6 +54,12 @@ enum EGxBlend { GxBlends_Last = 12 }; +enum EGxBuffer { + GxBuffers_Color = 0, + GxBuffers_Depth = 1, + GxBuffers_Last, +}; + enum EGxColorFormat { GxCF_argb = 0, GxCF_rgba = 1, From 4782c554fc3b6c988442d265c4f9b9111d3f584e Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 18 Feb 2026 06:15:53 -0600 Subject: [PATCH 250/269] feat(gx): add CGxDevice::TextureTarget --- src/gx/CGxDevice.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/gx/CGxDevice.hpp b/src/gx/CGxDevice.hpp index de72727..b4c719d 100644 --- a/src/gx/CGxDevice.hpp +++ b/src/gx/CGxDevice.hpp @@ -38,6 +38,13 @@ struct ShaderConstants { class CGxDevice { public: + // Structs + struct TextureTarget { + CGxTex* m_texture; + uint32_t m_plane; + void* m_apiSpecific; + }; + // Static variables static uint32_t s_alphaRef[]; static C3Vector s_pointScaleIdentity; From 619bcca7781251d163bfb90c965223e5032470dc Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 18 Feb 2026 06:19:28 -0600 Subject: [PATCH 251/269] feat(gx): add CGxDevice::m_textureTarget --- src/gx/CGxDevice.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gx/CGxDevice.hpp b/src/gx/CGxDevice.hpp index b4c719d..250be28 100644 --- a/src/gx/CGxDevice.hpp +++ b/src/gx/CGxDevice.hpp @@ -123,6 +123,9 @@ class CGxDevice { int32_t m_primIndexDirty = 0; TSFixedArray m_appRenderStates; TSFixedArray m_hwRenderStates; + // TODO + TextureTarget m_textureTarget[GxBuffers_Last]; + // TODO uint32_t m_baseMipLevel = 0; // TODO placeholder // Virtual member functions From a51e9ba0828fb05285f43c538f85210e5a54565c Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 18 Feb 2026 08:24:53 -0600 Subject: [PATCH 252/269] feat(gx): add missing initializers to CGxDevice --- src/gx/CGxDevice.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gx/CGxDevice.hpp b/src/gx/CGxDevice.hpp index 250be28..0c7ed1e 100644 --- a/src/gx/CGxDevice.hpp +++ b/src/gx/CGxDevice.hpp @@ -108,12 +108,12 @@ class CGxDevice { uint32_t m_appMasterEnables = 0; uint32_t m_hwMasterEnables = 0; TSList> m_poolList; - CGxBuf* m_bufLocked[GxPoolTargets_Last]; + CGxBuf* m_bufLocked[GxPoolTargets_Last] = {}; CGxPool* m_vertexPool = nullptr; CGxPool* m_indexPool = nullptr; - CGxBuf* m_streamBufs[GxPoolTargets_Last]; + CGxBuf* m_streamBufs[GxPoolTargets_Last] = {}; CGxVertexAttrib m_primVertexFormatAttrib[GxVertexBufferFormats_Last]; - CGxBuf* m_primVertexFormatBuf[GxVertexBufferFormats_Last]; + CGxBuf* m_primVertexFormatBuf[GxVertexBufferFormats_Last] = {}; uint32_t m_primVertexMask = 0; uint32_t m_primVertexDirty = 0; EGxVertexBufferFormat m_primVertexFormat = GxVertexBufferFormats_Last; @@ -124,7 +124,7 @@ class CGxDevice { TSFixedArray m_appRenderStates; TSFixedArray m_hwRenderStates; // TODO - TextureTarget m_textureTarget[GxBuffers_Last]; + TextureTarget m_textureTarget[GxBuffers_Last] = {}; // TODO uint32_t m_baseMipLevel = 0; // TODO placeholder From e7bd5968cf4003df446c4090428ac35930731f68 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 18 Feb 2026 08:43:11 -0600 Subject: [PATCH 253/269] feat(gx): add GxRenderTargetGet --- src/gx/CGxDevice.cpp | 4 ++++ src/gx/CGxDevice.hpp | 1 + src/gx/RenderTarget.cpp | 6 ++++++ src/gx/RenderTarget.hpp | 10 ++++++++++ 4 files changed, 21 insertions(+) create mode 100644 src/gx/RenderTarget.cpp create mode 100644 src/gx/RenderTarget.hpp diff --git a/src/gx/CGxDevice.cpp b/src/gx/CGxDevice.cpp index 880a107..b3eac61 100644 --- a/src/gx/CGxDevice.cpp +++ b/src/gx/CGxDevice.cpp @@ -924,6 +924,10 @@ CGxPool* CGxDevice::PoolCreate(EGxPoolTarget target, EGxPoolUsage usage, uint32_ return pool; } +void CGxDevice::RenderTargetGet(EGxBuffer buffer, CGxTex*& gxTex) { + gxTex = this->m_textureTarget[buffer].m_texture; +} + void CGxDevice::RsGet(EGxRenderState which, int32_t& value) { value = static_cast(this->m_appRenderStates[which].m_value); } diff --git a/src/gx/CGxDevice.hpp b/src/gx/CGxDevice.hpp index 0c7ed1e..edf9f99 100644 --- a/src/gx/CGxDevice.hpp +++ b/src/gx/CGxDevice.hpp @@ -183,6 +183,7 @@ class CGxDevice { void PrimVertexFormat(CGxBuf*, CGxVertexAttrib*, uint32_t); void PrimVertexMask(uint32_t); void PrimVertexPtr(CGxBuf*, EGxVertexBufferFormat); + void RenderTargetGet(EGxBuffer buffer, CGxTex*& gxTex); void RsGet(EGxRenderState, int32_t&); void RsSet(EGxRenderState, int32_t); void RsSet(EGxRenderState, void*); diff --git a/src/gx/RenderTarget.cpp b/src/gx/RenderTarget.cpp new file mode 100644 index 0000000..d847708 --- /dev/null +++ b/src/gx/RenderTarget.cpp @@ -0,0 +1,6 @@ +#include "gx/RenderTarget.hpp" +#include "gx/Device.hpp" + +void GxRenderTargetGet(EGxBuffer buffer, CGxTex*& gxTex) { + g_theGxDevicePtr->RenderTargetGet(buffer, gxTex); +} diff --git a/src/gx/RenderTarget.hpp b/src/gx/RenderTarget.hpp new file mode 100644 index 0000000..c95cad2 --- /dev/null +++ b/src/gx/RenderTarget.hpp @@ -0,0 +1,10 @@ +#ifndef GX_RENDER_TARGET_HPP +#define GX_RENDER_TARGET_HPP + +#include "gx/Types.hpp" + +class CGxTex; + +void GxRenderTargetGet(EGxBuffer buffer, CGxTex*& gxTex); + +#endif From c6e18336de336c573868b30d6a05b59d9efd9492 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 18 Feb 2026 16:28:19 -0600 Subject: [PATCH 254/269] chore(build): update typhoon --- lib/typhoon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/typhoon b/lib/typhoon index 4ba7e0a..1f8bf13 160000 --- a/lib/typhoon +++ b/lib/typhoon @@ -1 +1 @@ -Subproject commit 4ba7e0a6c3836254daf97bab159807fae6cab039 +Subproject commit 1f8bf1370dc1cf13da5965be99803633d82a524f From 7682dba2c91198acf4f56525d317366be182d938 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 18 Feb 2026 17:00:56 -0600 Subject: [PATCH 255/269] feat(ui): add CGCamera --- lib/typhoon | 2 +- src/ui/game/CGCamera.cpp | 97 +++++++++++++++++++++++++++++++++ src/ui/game/CGCamera.hpp | 48 ++++++++++++++++ src/ui/game/CGGameUI.cpp | 5 ++ src/ui/game/Types.hpp | 12 ++++ src/ui/simple/CSimpleCamera.cpp | 12 ++-- src/ui/simple/CSimpleCamera.hpp | 1 + 7 files changed, 172 insertions(+), 5 deletions(-) create mode 100644 src/ui/game/CGCamera.cpp create mode 100644 src/ui/game/CGCamera.hpp diff --git a/lib/typhoon b/lib/typhoon index 1f8bf13..1e5366b 160000 --- a/lib/typhoon +++ b/lib/typhoon @@ -1 +1 @@ -Subproject commit 1f8bf1370dc1cf13da5965be99803633d82a524f +Subproject commit 1e5366bbc6935e3363abf5921f0be12f902e790a diff --git a/src/ui/game/CGCamera.cpp b/src/ui/game/CGCamera.cpp new file mode 100644 index 0000000..f278f6e --- /dev/null +++ b/src/ui/game/CGCamera.cpp @@ -0,0 +1,97 @@ +#include "ui/game/CGCamera.hpp" +#include "ui/game/Types.hpp" +#include "console/CVar.hpp" +#include "world/World.hpp" +#include +#include +#include + +static CVar* s_cameraView; + +CGCamera::CameraViewData CGCamera::s_cameraViewDataDefault[MAX_CAMERA_VIEWS] = { + { "0.0", "0.0", "0.0" }, // VIEW_FIRST_PERSON + { "0.0", "0.0", "0.0" }, // VIEW_THIRD_PERSON_A + { "5.55", "10.0", "0.0" }, // VIEW_THIRD_PERSON_B + { "5.55", "20.0", "0.0" }, // VIEW_THIRD_PERSON_C + { "13.88", "30.0", "0.0" }, // VIEW_THIRD_PERSON_D + { "13.88", "10.0", "0.0" }, // VIEW_THIRD_PERSON_E + { "0.0", "0.0", "0.0" }, // VIEW_COMMENTATOR + { "5.0", "10.0", "0.0" }, // VIEW_BARBER_SHOP +}; + +namespace { + +bool ValidateCameraView(CVar* var, const char* oldValue, const char* value, void* arg) { + auto view = SStrToFloat(value); + auto min = static_cast(VIEW_FIRST_PERSON); + auto max = static_cast(VIEW_BARBER_SHOP); + + if (view >= min && view <= max) { + return true; + } + + // TODO ConsoleWriteA("Value out of range (%f - %f)\n", DEFAULT_COLOR, min, max); + + return false; +} + +} + +CGCamera::CGCamera() : CSimpleCamera(CWorld::GetNearClip(), CWorld::GetFarClip(), 90.0f * CMath::DEG2RAD) { + this->m_relativeTo = 0; + + this->m_view = s_cameraView->GetInt(); + + this->m_distance = SStrToFloat(CGCamera::s_cameraViewDataDefault[this->m_view].m_distance); + this->m_yaw = 0.0f; + this->m_pitch = SStrToFloat(CGCamera::s_cameraViewDataDefault[this->m_view].m_pitch); + this->m_roll = 0.0f; + + this->m_fovOffset = 0.0f; +} + +float CGCamera::FOV() const { + // Clamp offset-adjusted FOV between 0pi and 1pi + return std::min(std::max(this->m_fov + this->m_fovOffset, 0.0f), CMath::PI); +} + +C3Vector CGCamera::Forward() const { + if (this->m_relativeTo) { + return this->CSimpleCamera::Forward() * this->ParentToWorld(); + } + + return this->CSimpleCamera::Forward(); +} + +C33Matrix CGCamera::ParentToWorld() const { + // TODO + return {}; +} + +C3Vector CGCamera::Right() const { + if (this->m_relativeTo) { + return this->CSimpleCamera::Right() * this->ParentToWorld(); + } + + return this->CSimpleCamera::Right(); +} + +void CGCamera::SetupWorldProjection(const CRect& projRect) { + this->SetGxProjectionAndView(projRect); +} + +C3Vector CGCamera::Up() const { + if (this->m_relativeTo) { + return this->CSimpleCamera::Up() * this->ParentToWorld(); + } + + return this->CSimpleCamera::Up(); +} + +void CameraRegisterCVars() { + // TODO + + s_cameraView = CVar::Register("cameraView", nullptr, 0x10, "2", &ValidateCameraView, DEFAULT); + + // TODO +} diff --git a/src/ui/game/CGCamera.hpp b/src/ui/game/CGCamera.hpp new file mode 100644 index 0000000..b0aafb7 --- /dev/null +++ b/src/ui/game/CGCamera.hpp @@ -0,0 +1,48 @@ +#ifndef UI_GAME_C_G_CAMERA_HPP +#define UI_GAME_C_G_CAMERA_HPP + +#include "ui/simple/CSimpleCamera.hpp" +#include "util/GUID.hpp" + +class CGCamera : public CSimpleCamera { + public: + // Public structs + struct CameraViewData { + const char* m_distance; + const char* m_pitch; + const char* m_yaw; + }; + + // Public static variables + static CameraViewData s_cameraViewDataDefault[]; + + // Virtual public member functions + virtual ~CGCamera() = default; + virtual float FOV() const; + virtual C3Vector Forward() const; + virtual C3Vector Right() const; + virtual C3Vector Up() const; + + // Public member functions + CGCamera(); + C33Matrix ParentToWorld() const; + void SetupWorldProjection(const CRect& projRect); + + private: + // Private member variables + // TODO + WOWGUID m_relativeTo; + // TODO + int32_t m_view; + // TODO + float m_distance; + float m_yaw; + float m_pitch; + float m_roll; + // TODO + float m_fovOffset; +}; + +void CameraRegisterCVars(); + +#endif diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index a92b41f..791b850 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -8,6 +8,7 @@ #include "ui/game/ActionBarScript.hpp" #include "ui/game/BattlefieldInfoScript.hpp" #include "ui/game/BattlenetUI.hpp" +#include "ui/game/CGCamera.hpp" #include "ui/game/CGCharacterModelBase.hpp" #include "ui/game/CGCooldown.hpp" #include "ui/game/CGDressUpModelFrame.hpp" @@ -284,4 +285,8 @@ void CGGameUI::RegisterGameCVars() { CVar::Register("fullSizeFocusFrame", "Increases the size of the focus frame to that of the target frame", 0x20, "0", nullptr, GAME); // TODO + + CameraRegisterCVars(); + + // TODO } diff --git a/src/ui/game/Types.hpp b/src/ui/game/Types.hpp index a54dce4..78d1696 100644 --- a/src/ui/game/Types.hpp +++ b/src/ui/game/Types.hpp @@ -13,4 +13,16 @@ enum SCRIPTEVENT { // TODO }; +enum CAMERA_VIEW { + VIEW_FIRST_PERSON = 0, + VIEW_THIRD_PERSON_A = 1, + VIEW_THIRD_PERSON_B = 2, + VIEW_THIRD_PERSON_C = 3, + VIEW_THIRD_PERSON_D = 4, + VIEW_THIRD_PERSON_E = 5, + VIEW_COMMENTATOR = 6, + VIEW_BARBER_SHOP = 7, + MAX_CAMERA_VIEWS, +}; + #endif diff --git a/src/ui/simple/CSimpleCamera.cpp b/src/ui/simple/CSimpleCamera.cpp index 990c982..15a0dc6 100644 --- a/src/ui/simple/CSimpleCamera.cpp +++ b/src/ui/simple/CSimpleCamera.cpp @@ -104,10 +104,6 @@ void CSimpleCamera::SetFieldOfView(float fov) { this->m_fov = fov; } -void CSimpleCamera::SetNearZ(float nearZ) { - this->m_nearZ = nearZ; -} - void CSimpleCamera::SetGxProjectionAndView(const CRect& projRect) { // Projection @@ -127,6 +123,14 @@ void CSimpleCamera::SetGxProjectionAndView(const CRect& projRect) { GxXformSetView(viewMat); } +void CSimpleCamera::SetNearZ(float nearZ) { + this->m_nearZ = nearZ; +} + +void CSimpleCamera::SetScreenAspect(const CRect& screenRect) { + this->m_aspect = (screenRect.maxX - screenRect.minX) / (screenRect.maxY - screenRect.minY); +} + C3Vector CSimpleCamera::Up() const { return { this->m_facing.c0, this->m_facing.c1, this->m_facing.c2 }; } diff --git a/src/ui/simple/CSimpleCamera.hpp b/src/ui/simple/CSimpleCamera.hpp index 407cdb6..3387a35 100644 --- a/src/ui/simple/CSimpleCamera.hpp +++ b/src/ui/simple/CSimpleCamera.hpp @@ -25,6 +25,7 @@ class CSimpleCamera { void SetFieldOfView(float fov); void SetGxProjectionAndView(const CRect& projRect); void SetNearZ(float nearZ); + void SetScreenAspect(const CRect& screenRect); protected: // Protected member variables From e5cc9de4866e6d96a8395a8a0d3d5c9e7a6cd223 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 18 Feb 2026 19:34:52 -0600 Subject: [PATCH 256/269] feat(ui): add CGWorldFrame::OnFrameSizeChanged --- src/ui/game/CGWorldFrame.cpp | 29 +++++++++++++++++++++++++++++ src/ui/game/CGWorldFrame.hpp | 13 +++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/ui/game/CGWorldFrame.cpp b/src/ui/game/CGWorldFrame.cpp index 3446f1b..fab12fd 100644 --- a/src/ui/game/CGWorldFrame.cpp +++ b/src/ui/game/CGWorldFrame.cpp @@ -1,6 +1,8 @@ #include "ui/game/CGWorldFrame.hpp" +#include "gx/Coordinate.hpp" #include "gx/Shader.hpp" #include "gx/Transform.hpp" +#include "ui/game/CGCamera.hpp" #include "ui/game/PlayerName.hpp" #include #include @@ -46,6 +48,10 @@ CGWorldFrame::CGWorldFrame(CSimpleFrame* parent) : CSimpleFrame(parent) { this->EnableEvent(SIMPLE_EVENT_MOUSEWHEEL, -1); // TODO + + this->m_camera = STORM_NEW(CGCamera); + + // TODO } void CGWorldFrame::OnFrameRender(CRenderBatch* batch, uint32_t layer) { @@ -56,6 +62,29 @@ void CGWorldFrame::OnFrameRender(CRenderBatch* batch, uint32_t layer) { } } +void CGWorldFrame::OnFrameSizeChanged(const CRect& rect) { + this->CSimpleFrame::OnFrameSizeChanged(rect); + + // Screen rect (DDC) + this->m_screenRect.minX = std::max(this->m_rect.minX, 0.0f); + this->m_screenRect.minY = std::max(this->m_rect.minY, 0.0f); + this->m_screenRect.maxX = std::min(this->m_rect.maxX, NDCToDDCWidth(1.0f)); + this->m_screenRect.maxY = std::min(this->m_rect.maxY, NDCToDDCHeight(1.0f)); + + // Camera aspect ratio + if (this->m_camera) { + this->m_camera->SetScreenAspect(this->m_screenRect); + } + + // Viewport (NDC) + DDCToNDC(this->m_rect.minX, this->m_rect.minY, &this->m_viewport.minX, &this->m_viewport.minY); + DDCToNDC(this->m_rect.maxX, this->m_rect.maxY, &this->m_viewport.maxX, &this->m_viewport.maxY); + this->m_viewport.minX = std::max(this->m_viewport.minX, 0.0f); + this->m_viewport.minY = std::max(this->m_viewport.minY, 0.0f); + this->m_viewport.maxX = std::min(this->m_viewport.maxX, 1.0f); + this->m_viewport.maxY = std::min(this->m_viewport.maxY, 1.0f); +} + void CGWorldFrame::OnWorldRender() { // TODO } diff --git a/src/ui/game/CGWorldFrame.hpp b/src/ui/game/CGWorldFrame.hpp index 6cec83a..169940c 100644 --- a/src/ui/game/CGWorldFrame.hpp +++ b/src/ui/game/CGWorldFrame.hpp @@ -4,6 +4,8 @@ #include "ui/simple/CSimpleFrame.hpp" #include +class CGCamera; + class CGWorldFrame : public CSimpleFrame { public: // Static variables @@ -15,11 +17,22 @@ class CGWorldFrame : public CSimpleFrame { // Virtual member functions virtual void OnFrameRender(CRenderBatch* batch, uint32_t layer); + // TODO + virtual void OnFrameSizeChanged(const CRect& rect); // Member functions CGWorldFrame(CSimpleFrame* parent); void OnWorldRender(); void OnWorldUpdate(); + + private: + // Private member variables + // TODO + CRect m_screenRect; + CRect m_viewport; + // TODO + CGCamera* m_camera; + // TODO }; #endif From 06186d12515b3140803e66f0192e25bd2b1c98c6 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Thu, 19 Feb 2026 06:56:43 -0600 Subject: [PATCH 257/269] feat(ui): call CGCamera::SetupWorldProjection from CGWorldFrame::OnWorldUpdate --- src/ui/game/CGWorldFrame.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ui/game/CGWorldFrame.cpp b/src/ui/game/CGWorldFrame.cpp index fab12fd..1b0c823 100644 --- a/src/ui/game/CGWorldFrame.cpp +++ b/src/ui/game/CGWorldFrame.cpp @@ -91,4 +91,8 @@ void CGWorldFrame::OnWorldRender() { void CGWorldFrame::OnWorldUpdate() { // TODO + + this->m_camera->SetupWorldProjection(this->m_screenRect); + + // TODO } From 6675586a2900fd814de087d166f7f0ff0de0d100 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 21 Feb 2026 14:07:33 -0600 Subject: [PATCH 258/269] feat(ui): add CSimpleCamera::Position --- src/ui/simple/CSimpleCamera.cpp | 4 ++++ src/ui/simple/CSimpleCamera.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/ui/simple/CSimpleCamera.cpp b/src/ui/simple/CSimpleCamera.cpp index 15a0dc6..a4e67c2 100644 --- a/src/ui/simple/CSimpleCamera.cpp +++ b/src/ui/simple/CSimpleCamera.cpp @@ -84,6 +84,10 @@ C3Vector CSimpleCamera::Right() const { return { this->m_facing.b0, this->m_facing.b1, this->m_facing.b2 }; } +const C3Vector& CSimpleCamera::Position() const { + return this->m_position; +} + void CSimpleCamera::SetFacing(const C3Vector& forward) { BuildBillboardMatrix(forward, this->m_facing); } diff --git a/src/ui/simple/CSimpleCamera.hpp b/src/ui/simple/CSimpleCamera.hpp index 3387a35..e5a166d 100644 --- a/src/ui/simple/CSimpleCamera.hpp +++ b/src/ui/simple/CSimpleCamera.hpp @@ -18,6 +18,7 @@ class CSimpleCamera { // Public member functions CSimpleCamera(float nearZ, float farZ, float fov); CM2Scene* GetScene(); + const C3Vector& Position() const; void SetFacing(const C3Vector& forward); void SetFacing(const C3Vector& forward, const C3Vector& up); void SetFacing(float yaw, float pitch, float roll); From 817cec99feebb0b6e7e629e7fd92a0d54173e60f Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 21 Feb 2026 14:11:22 -0600 Subject: [PATCH 259/269] feat(ui): add CGCamera::Target --- src/ui/game/CGCamera.cpp | 4 ++++ src/ui/game/CGCamera.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/ui/game/CGCamera.cpp b/src/ui/game/CGCamera.cpp index f278f6e..bb9a454 100644 --- a/src/ui/game/CGCamera.cpp +++ b/src/ui/game/CGCamera.cpp @@ -80,6 +80,10 @@ void CGCamera::SetupWorldProjection(const CRect& projRect) { this->SetGxProjectionAndView(projRect); } +C3Vector CGCamera::Target() const { + return this->m_position + this->Forward(); +} + C3Vector CGCamera::Up() const { if (this->m_relativeTo) { return this->CSimpleCamera::Up() * this->ParentToWorld(); diff --git a/src/ui/game/CGCamera.hpp b/src/ui/game/CGCamera.hpp index b0aafb7..a23d789 100644 --- a/src/ui/game/CGCamera.hpp +++ b/src/ui/game/CGCamera.hpp @@ -27,6 +27,7 @@ class CGCamera : public CSimpleCamera { CGCamera(); C33Matrix ParentToWorld() const; void SetupWorldProjection(const CRect& projRect); + C3Vector Target() const; private: // Private member variables From 58c897576981e6c03448ae3d5731c374b5da0d21 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 21 Feb 2026 21:15:01 -0600 Subject: [PATCH 260/269] feat(ui): add CGCamera::GetTarget --- src/ui/game/CGCamera.cpp | 4 ++++ src/ui/game/CGCamera.hpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/ui/game/CGCamera.cpp b/src/ui/game/CGCamera.cpp index bb9a454..1fd1098 100644 --- a/src/ui/game/CGCamera.cpp +++ b/src/ui/game/CGCamera.cpp @@ -63,6 +63,10 @@ C3Vector CGCamera::Forward() const { return this->CSimpleCamera::Forward(); } +const WOWGUID& CGCamera::GetTarget() const { + return this->m_target; +} + C33Matrix CGCamera::ParentToWorld() const { // TODO return {}; diff --git a/src/ui/game/CGCamera.hpp b/src/ui/game/CGCamera.hpp index a23d789..13d18ad 100644 --- a/src/ui/game/CGCamera.hpp +++ b/src/ui/game/CGCamera.hpp @@ -25,6 +25,7 @@ class CGCamera : public CSimpleCamera { // Public member functions CGCamera(); + const WOWGUID& GetTarget() const; C33Matrix ParentToWorld() const; void SetupWorldProjection(const CRect& projRect); C3Vector Target() const; @@ -32,6 +33,8 @@ class CGCamera : public CSimpleCamera { private: // Private member variables // TODO + WOWGUID m_target; + // TODO WOWGUID m_relativeTo; // TODO int32_t m_view; From cb8291af1acd3c01ceb53ecce5b9e6b2435cf2d8 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 21 Feb 2026 21:41:08 -0600 Subject: [PATCH 261/269] feat(ui): add CGCamera::HasModel --- src/ui/game/CGCamera.cpp | 7 +++++++ src/ui/game/CGCamera.hpp | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/src/ui/game/CGCamera.cpp b/src/ui/game/CGCamera.cpp index 1fd1098..60b736c 100644 --- a/src/ui/game/CGCamera.cpp +++ b/src/ui/game/CGCamera.cpp @@ -38,6 +38,9 @@ bool ValidateCameraView(CVar* var, const char* oldValue, const char* value, void } CGCamera::CGCamera() : CSimpleCamera(CWorld::GetNearClip(), CWorld::GetFarClip(), 90.0f * CMath::DEG2RAD) { + this->m_model = nullptr; + + this->m_target = 0; this->m_relativeTo = 0; this->m_view = s_cameraView->GetInt(); @@ -67,6 +70,10 @@ const WOWGUID& CGCamera::GetTarget() const { return this->m_target; } +int32_t CGCamera::HasModel() const { + return this->m_model != nullptr; +} + C33Matrix CGCamera::ParentToWorld() const { // TODO return {}; diff --git a/src/ui/game/CGCamera.hpp b/src/ui/game/CGCamera.hpp index 13d18ad..5a3a5b2 100644 --- a/src/ui/game/CGCamera.hpp +++ b/src/ui/game/CGCamera.hpp @@ -4,6 +4,8 @@ #include "ui/simple/CSimpleCamera.hpp" #include "util/GUID.hpp" +class CM2Model; + class CGCamera : public CSimpleCamera { public: // Public structs @@ -26,12 +28,14 @@ class CGCamera : public CSimpleCamera { // Public member functions CGCamera(); const WOWGUID& GetTarget() const; + int32_t HasModel() const; C33Matrix ParentToWorld() const; void SetupWorldProjection(const CRect& projRect); C3Vector Target() const; private: // Private member variables + CM2Model* m_model; // TODO WOWGUID m_target; // TODO From 6cb53104301aa9ec1da80689f2d12c26f7aa5ecf Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 21 Feb 2026 21:41:37 -0600 Subject: [PATCH 262/269] feat(object): add CGObject_C::GetPosition --- src/object/client/CGObject_C.cpp | 4 ++++ src/object/client/CGObject_C.hpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index e9cd9a2..f8b1451 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -103,6 +103,10 @@ CM2Model* CGObject_C::GetObjectModel() { return this->m_model; } +C3Vector CGObject_C::GetPosition() const { + return { 0.0f, 0.0f, 0.0f }; +} + int32_t CGObject_C::IsInReenable() { return this->m_inReenable; } diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index fdb5813..788bbb5 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -36,6 +36,8 @@ class CGObject_C : public CGObject, public TSHashObject Date: Sat, 21 Feb 2026 21:42:02 -0600 Subject: [PATCH 263/269] feat(world): stub CWorld::Update --- src/world/CWorld.cpp | 4 ++++ src/world/CWorld.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/world/CWorld.cpp b/src/world/CWorld.cpp index 8a14a42..1ebc1c1 100644 --- a/src/world/CWorld.cpp +++ b/src/world/CWorld.cpp @@ -213,3 +213,7 @@ void CWorld::SetUpdateTime(float tickTimeSec, uint32_t curTimeMs) { CWorld::s_tickTimeMs = static_cast(tickTimeSec * 1000.0f); CWorld::s_tickTimeSec = tickTimeSec; } + +void CWorld::Update(const C3Vector& cameraPos, const C3Vector& cameraTarget, const C3Vector& targetPos) { + // TODO +} diff --git a/src/world/CWorld.hpp b/src/world/CWorld.hpp index 124e370..63c19ec 100644 --- a/src/world/CWorld.hpp +++ b/src/world/CWorld.hpp @@ -70,6 +70,7 @@ class CWorld { static int32_t OnTick(const EVENT_DATA_TICK* data, void* param); static void SetFarClip(float farClip); static void SetUpdateTime(float tickTimeSec, uint32_t curTimeMs); + static void Update(const C3Vector& cameraPos, const C3Vector& cameraTarget, const C3Vector& targetPos); private: // Private static variables From af4b798942e3c44875d8fd2c81d1cd85ad7fd58b Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 21 Feb 2026 21:42:41 -0600 Subject: [PATCH 264/269] feat(ui): call CWorld::Update from CGWorldFrame::OnWorldUpdate --- src/ui/game/CGWorldFrame.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/ui/game/CGWorldFrame.cpp b/src/ui/game/CGWorldFrame.cpp index 1b0c823..ccea161 100644 --- a/src/ui/game/CGWorldFrame.cpp +++ b/src/ui/game/CGWorldFrame.cpp @@ -2,8 +2,10 @@ #include "gx/Coordinate.hpp" #include "gx/Shader.hpp" #include "gx/Transform.hpp" +#include "object/Client.hpp" #include "ui/game/CGCamera.hpp" #include "ui/game/PlayerName.hpp" +#include "world/World.hpp" #include #include @@ -92,7 +94,19 @@ void CGWorldFrame::OnWorldRender() { void CGWorldFrame::OnWorldUpdate() { // TODO + auto target = ClntObjMgrObjectPtr(this->m_camera->GetTarget(), TYPE_OBJECT, __FILE__, __LINE__); + + // TODO + this->m_camera->SetupWorldProjection(this->m_screenRect); // TODO + + auto targetPos = target && !this->m_camera->HasModel() + ? target->GetPosition() + : this->m_camera->Position(); + + CWorld::Update(this->m_camera->Position(), this->m_camera->Target(), targetPos); + + // TODO } From fa98bbc1f05266b4e00b976a5af00d67bfaca3e0 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 22 Feb 2026 21:57:26 -0600 Subject: [PATCH 265/269] feat(object): add CGObject_C::GetFacing --- src/object/client/CGObject_C.cpp | 4 ++++ src/object/client/CGObject_C.hpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/object/client/CGObject_C.cpp b/src/object/client/CGObject_C.cpp index f8b1451..3ae73a7 100644 --- a/src/object/client/CGObject_C.cpp +++ b/src/object/client/CGObject_C.cpp @@ -95,6 +95,10 @@ void CGObject_C::Disable() { this->m_disableTimeMs = CWorld::GetCurTimeMs(); } +float CGObject_C::GetFacing() const { + return 0.0f; +} + int32_t CGObject_C::GetModelFileName(const char*& name) const { return false; } diff --git a/src/object/client/CGObject_C.hpp b/src/object/client/CGObject_C.hpp index 788bbb5..f7d9400 100644 --- a/src/object/client/CGObject_C.hpp +++ b/src/object/client/CGObject_C.hpp @@ -38,6 +38,8 @@ class CGObject_C : public CGObject, public TSHashObject Date: Mon, 23 Feb 2026 22:31:12 -0500 Subject: [PATCH 266/269] feat(connection): implement character creation message handlers (#166) Co-authored-by: fallenoak --- src/net/connection/ClientConnection.cpp | 4 ++++ src/net/connection/ClientConnection.hpp | 1 + src/net/connection/RealmConnection.cpp | 11 ++++++++++- src/net/connection/RealmConnection.hpp | 2 ++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/net/connection/ClientConnection.cpp b/src/net/connection/ClientConnection.cpp index 66434c0..8dba0a9 100644 --- a/src/net/connection/ClientConnection.cpp +++ b/src/net/connection/ClientConnection.cpp @@ -104,6 +104,10 @@ void ClientConnection::GetRealmList() { } } +void ClientConnection::HandleCharacterCreate(uint8_t result) { + this->Complete(result == 47, result); +} + void ClientConnection::HandleCharacterDelete(uint8_t result) { this->Complete(result == 71, result); } diff --git a/src/net/connection/ClientConnection.hpp b/src/net/connection/ClientConnection.hpp index c24fa3a..3e30b88 100644 --- a/src/net/connection/ClientConnection.hpp +++ b/src/net/connection/ClientConnection.hpp @@ -22,6 +22,7 @@ class ClientConnection : public RealmConnection { // Virtual member functions virtual int32_t HandleConnect(); + virtual void HandleCharacterCreate(uint8_t result); virtual void HandleCharacterDelete(uint8_t result); // Member functions diff --git a/src/net/connection/RealmConnection.cpp b/src/net/connection/RealmConnection.cpp index 9bc0a6a..0ede2da 100644 --- a/src/net/connection/RealmConnection.cpp +++ b/src/net/connection/RealmConnection.cpp @@ -20,7 +20,7 @@ int32_t RealmConnection::MessageHandler(void* param, NETMESSAGE msgId, uint32_t } case SMSG_CHAR_CREATE: { - // TODO + result = connection->CreateCharHandler(msgId, time, msg); break; } @@ -294,6 +294,15 @@ int32_t RealmConnection::HandleCharEnum(uint32_t msgId, uint32_t time, CDataStor return 1; } +int32_t RealmConnection::CreateCharHandler(uint32_t msgId, uint32_t time, CDataStore* msg) { + uint8_t result; + msg->Get(result); + + this->HandleCharacterCreate(result); + + return 1; +} + int32_t RealmConnection::DeleteCharHandler(uint32_t msgId, uint32_t time, CDataStore* msg) { uint8_t result; msg->Get(result); diff --git a/src/net/connection/RealmConnection.hpp b/src/net/connection/RealmConnection.hpp index 332401b..b7a9556 100644 --- a/src/net/connection/RealmConnection.hpp +++ b/src/net/connection/RealmConnection.hpp @@ -46,12 +46,14 @@ class RealmConnection : public NetClient { // Virtual member functions virtual int32_t HandleAuthChallenge(AuthenticationChallenge* challenge); + virtual void HandleCharacterCreate(uint8_t result) = 0; virtual void HandleCharacterDelete(uint8_t result) = 0; // Member functions RealmConnection(RealmResponse* realmResponse); int32_t HandleAuthResponse(uint32_t msgId, uint32_t time, CDataStore* msg); int32_t HandleCharEnum(uint32_t msgId, uint32_t time, CDataStore* msg); + int32_t CreateCharHandler(uint32_t msgId, uint32_t time, CDataStore* msg); int32_t DeleteCharHandler(uint32_t msgId, uint32_t time, CDataStore* msg); void RequestCharacterEnum(); void RequestCharacterLogin(uint64_t guid, int32_t a2); From abf2e2cde3cc6a021498cb2c1137449e584e09d6 Mon Sep 17 00:00:00 2001 From: Tristan 'Natrist' Cormier Date: Mon, 23 Feb 2026 23:30:49 -0500 Subject: [PATCH 267/269] feat(glue): add CGlueMgr::PollCreateCharacter (#167) Co-authored-by: fallenoak --- src/glue/CGlueMgr.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/glue/CGlueMgr.hpp | 1 + 2 files changed, 37 insertions(+) diff --git a/src/glue/CGlueMgr.cpp b/src/glue/CGlueMgr.cpp index 6528583..8ffed61 100644 --- a/src/glue/CGlueMgr.cpp +++ b/src/glue/CGlueMgr.cpp @@ -393,6 +393,11 @@ int32_t CGlueMgr::Idle(const void* a1, void* a2) { break; } + case IDLE_CREATE_CHARACTER: { + CGlueMgr::PollCreateCharacter(msg, complete, result); + break; + } + case IDLE_DELETE_CHARACTER: { CGlueMgr::PollDeleteCharacter(msg, complete, result); break; @@ -763,6 +768,37 @@ void CGlueMgr::PollCharacterList(const char* msg, int32_t complete, int32_t resu } } +void CGlueMgr::PollCreateCharacter(const char* msg, int32_t complete, int32_t result) { + FrameScript_SignalEvent(UPDATE_STATUS_DIALOG, "%s", msg); + + if (CGlueMgr::HandleBattlenetDisconnect()) { + CGlueMgr::SetIdleState(IDLE_NONE); + } + + if (!complete) { + return; + } + + // Error + + if (result == 0) { + FrameScript_SignalEvent(OPEN_STATUS_DIALOG, "%s%s", "OKAY", msg); + + CGlueMgr::SetIdleState(IDLE_NONE); + + return; + } + + // Success + + CGlueMgr::SetIdleState(IDLE_NONE); + + FrameScript_SignalEvent(CLOSE_STATUS_DIALOG, nullptr); + FrameScript_SignalEvent(SELECT_LAST_CHARACTER, nullptr); + + CGlueMgr::SetScreen("charselect"); +} + void CGlueMgr::PollDeleteCharacter(const char* msg, int32_t complete, int32_t result) { FrameScript_SignalEvent(UPDATE_STATUS_DIALOG, "%s", msg); diff --git a/src/glue/CGlueMgr.hpp b/src/glue/CGlueMgr.hpp index 38e369b..e608366 100644 --- a/src/glue/CGlueMgr.hpp +++ b/src/glue/CGlueMgr.hpp @@ -80,6 +80,7 @@ class CGlueMgr { static int32_t OnKickReasonMsg(void* param, NETMESSAGE msgId, uint32_t time, CDataStore* msg); static void PollAccountLogin(int32_t errorCode, const char* msg, int32_t complete, int32_t result, WOWCS_OPS op); static void PollCharacterList(const char* msg, int32_t complete, int32_t result, int32_t errorCode); + static void PollCreateCharacter(const char* msg, int32_t complete, int32_t result); static void PollDeleteCharacter(const char* msg, int32_t complete, int32_t result); static void PollEnterWorld(); static void PollLoginServerLogin(); From d19658185a1c0eaa5d36d159f2a5a5c8f72e8bd3 Mon Sep 17 00:00:00 2001 From: Tristan 'Natrist' Cormier Date: Tue, 24 Feb 2026 22:00:27 -0500 Subject: [PATCH 268/269] feat(glue): implement Script_TerminationWithoutNoticeAccepted (#159) Co-authored-by: fallenoak --- src/glue/GlueScript.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/glue/GlueScript.cpp b/src/glue/GlueScript.cpp index 3c76156..8cc472d 100644 --- a/src/glue/GlueScript.cpp +++ b/src/glue/GlueScript.cpp @@ -204,7 +204,13 @@ int32_t Script_ShowTerminationWithoutNoticeNotice(lua_State* L) { } int32_t Script_TerminationWithoutNoticeAccepted(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (CGlueMgr::m_acceptedTerminationWithoutNotice) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + + return 1; } int32_t Script_AcceptTerminationWithoutNotice(lua_State* L) { From 0a91d4460032b74fb3b1fae3a991ee57cacece0d Mon Sep 17 00:00:00 2001 From: Tristan 'Natrist' Cormier Date: Wed, 25 Feb 2026 21:36:05 -0500 Subject: [PATCH 269/269] feat(glue): implement Script_ContestAccepted (#161) Co-authored-by: fallenoak --- src/glue/CGlueMgr.cpp | 1 + src/glue/CGlueMgr.hpp | 1 + src/glue/GlueScript.cpp | 8 +++++++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/glue/CGlueMgr.cpp b/src/glue/CGlueMgr.cpp index 8ffed61..1fabdde 100644 --- a/src/glue/CGlueMgr.cpp +++ b/src/glue/CGlueMgr.cpp @@ -38,6 +38,7 @@ #include #include +int32_t CGlueMgr::m_acceptedContest = 1; // TODO int32_t CGlueMgr::m_acceptedEULA = 1; // TODO int32_t CGlueMgr::m_acceptedTerminationWithoutNotice; int32_t CGlueMgr::m_acceptedTOS = 1; // TODO diff --git a/src/glue/CGlueMgr.hpp b/src/glue/CGlueMgr.hpp index e608366..3210186 100644 --- a/src/glue/CGlueMgr.hpp +++ b/src/glue/CGlueMgr.hpp @@ -32,6 +32,7 @@ class CGlueMgr { }; // Static variables + static int32_t m_acceptedContest; static int32_t m_acceptedEULA; static int32_t m_acceptedTerminationWithoutNotice; static int32_t m_acceptedTOS; diff --git a/src/glue/GlueScript.cpp b/src/glue/GlueScript.cpp index 8cc472d..3dee47a 100644 --- a/src/glue/GlueScript.cpp +++ b/src/glue/GlueScript.cpp @@ -234,7 +234,13 @@ int32_t Script_ShowContestNotice(lua_State* L) { } int32_t Script_ContestAccepted(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (CGlueMgr::m_acceptedContest) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + + return 1; } int32_t Script_AcceptContest(lua_State* L) {