mirror of
https://github.com/brues-code/ClassicAPI.git
synced 2026-11-14 15:10:39 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be6dc200fe | ||
|
|
7f52afeef4 |
@@ -1,3 +1,5 @@
|
||||
function MouseIsOver(region, topOffset, bottomOffset, leftOffset, rightOffset)
|
||||
return region:IsMouseOver(topOffset, bottomOffset, leftOffset, rightOffset);
|
||||
if region:IsMouseOver(topOffset, bottomOffset, leftOffset, rightOffset) then
|
||||
return 1;
|
||||
end
|
||||
end
|
||||
|
||||
@@ -68,12 +68,9 @@ namespace AuctionHouse::PostItem {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const char *kEvtStart = "AUCTION_MULTISELL_START";
|
||||
constexpr const char *kEvtUpdate = "AUCTION_MULTISELL_UPDATE";
|
||||
constexpr const char *kEvtFailure = "AUCTION_MULTISELL_FAILURE";
|
||||
const Event::Custom::AutoReserve _r1{kEvtStart};
|
||||
const Event::Custom::AutoReserve _r2{kEvtUpdate};
|
||||
const Event::Custom::AutoReserve _r3{kEvtFailure};
|
||||
const Event::Custom::AutoReserve _evtStart{"AUCTION_MULTISELL_START"};
|
||||
const Event::Custom::AutoReserve _evtUpdate{"AUCTION_MULTISELL_UPDATE"};
|
||||
const Event::Custom::AutoReserve _evtFailure{"AUCTION_MULTISELL_FAILURE"};
|
||||
|
||||
// Generous per-step abort bound. A split or a post is one server round-trip
|
||||
// (~tens of frames); 600 frames (~10s at 60fps) means "something's wrong"
|
||||
@@ -206,7 +203,7 @@ bool FindFreeGeneralSlot(void *L, int *outBag, int *outSlot) {
|
||||
void Finish(bool success) {
|
||||
g_job.active = false;
|
||||
if (!success)
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kEvtFailure), "");
|
||||
Event::Custom::Fire(_evtFailure.Slot(), "");
|
||||
// success needs no event: the last PostWait already fired
|
||||
// AUCTION_MULTISELL_UPDATE(total, total).
|
||||
}
|
||||
@@ -279,7 +276,7 @@ void Tick() {
|
||||
// Post confirmed once the server pulls the item out of the slot.
|
||||
if (w.item == nullptr || w.guid != g_job.postGuid) {
|
||||
++g_job.postedStacks;
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kEvtUpdate), "%d%d",
|
||||
Event::Custom::Fire(_evtUpdate.Slot(), "%d%d",
|
||||
g_job.postedStacks, g_job.totalStacks);
|
||||
g_job.phase = Phase::Idle;
|
||||
g_job.waitTicks = 0;
|
||||
@@ -400,7 +397,7 @@ int __fastcall Script_C_AuctionHouse_PostItem(void *L) {
|
||||
g_job.runTime = runTime;
|
||||
g_job.phase = Phase::Idle;
|
||||
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kEvtStart), "");
|
||||
Event::Custom::Fire(_evtStart.Slot(), "");
|
||||
Game::Lua::PushBool(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ void OnWorldTick() {
|
||||
static_cast<uintptr_t>(Offsets::VAR_IN_WORLD)) == 0)
|
||||
return;
|
||||
g_pending = false;
|
||||
const int slot = Event::Custom::Lookup(kEventName);
|
||||
const int slot = _reserve.Slot();
|
||||
if (slot >= 0)
|
||||
Event::Custom::Fire(slot, "");
|
||||
// Notify C++ subscribers of the bag-change frame (see UpdateDelayed.h).
|
||||
|
||||
Vendored
+7
-7
@@ -61,8 +61,8 @@ constexpr int kMaxWaitTicks = 1200; // give up and fire failure after this many
|
||||
|
||||
struct Registered {
|
||||
void *cache;
|
||||
const char *eventName;
|
||||
uintptr_t getRecord; // this cache class's _GetRecord
|
||||
const Event::Custom::AutoReserve *reserve; // completion event's reservation
|
||||
uintptr_t getRecord; // this cache class's _GetRecord
|
||||
Pending pending[kMaxPending];
|
||||
int pendingCount;
|
||||
};
|
||||
@@ -79,8 +79,7 @@ Registered *Find(void *cache) {
|
||||
}
|
||||
|
||||
void Fire(const Registered *r, uint32_t id, bool success) {
|
||||
Event::Custom::FireIdSuccess(Event::Custom::Lookup(r->eventName),
|
||||
static_cast<int>(id), success);
|
||||
Event::Custom::FireIdSuccess(r->reserve->Slot(), static_cast<int>(id), success);
|
||||
}
|
||||
|
||||
int FindPending(const Registered *r, uint32_t id) {
|
||||
@@ -176,15 +175,16 @@ const Tick::WorldTick::AutoSubscribe _tickSub{&OnWorldTick};
|
||||
|
||||
} // namespace
|
||||
|
||||
void Register(void *cacheInstance, const char *eventName, uintptr_t getRecordAddr) {
|
||||
if (cacheInstance == nullptr || eventName == nullptr || getRecordAddr == 0)
|
||||
void Register(void *cacheInstance, const Event::Custom::AutoReserve *reserve,
|
||||
uintptr_t getRecordAddr) {
|
||||
if (cacheInstance == nullptr || reserve == nullptr || getRecordAddr == 0)
|
||||
return;
|
||||
if (Find(cacheInstance) != nullptr) // idempotent (safe across /reload)
|
||||
return;
|
||||
if (g_cacheCount >= kMaxCaches)
|
||||
return;
|
||||
g_caches[g_cacheCount].cache = cacheInstance;
|
||||
g_caches[g_cacheCount].eventName = eventName;
|
||||
g_caches[g_cacheCount].reserve = reserve;
|
||||
g_caches[g_cacheCount].getRecord = getRecordAddr;
|
||||
g_caches[g_cacheCount].pendingCount = 0;
|
||||
++g_cacheCount;
|
||||
|
||||
Vendored
+14
-10
@@ -15,6 +15,10 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Event::Custom {
|
||||
struct AutoReserve;
|
||||
}
|
||||
|
||||
// Shared async-load machinery for the client query caches that aren't
|
||||
// item/quest — creature, gameobject, and (potentially) the other
|
||||
// SMSG_*_QUERY caches. Modeled on `Item::Data`'s pending/timeout/event
|
||||
@@ -30,10 +34,9 @@
|
||||
// functions, so hooking creature's and gameobject's separately is fine);
|
||||
// item/quest have their own parsers and aren't touched.
|
||||
//
|
||||
// static const char *kEvent = "CREATURE_DATA_LOAD_RESULT";
|
||||
// static const Event::Custom::AutoReserve _r{kEvent}; // reserve the event
|
||||
// static const Event::Custom::AutoReserve _r{"CREATURE_DATA_LOAD_RESULT"};
|
||||
// ...
|
||||
// Cache::QueryLoad::Register(cacheInstance, kEvent,
|
||||
// Cache::QueryLoad::Register(cacheInstance, &_r,
|
||||
// Offsets::FUN_CREATURE_GET_RECORD); // at init
|
||||
// Cache::QueryLoad::RequestLoad(cacheInstance, id); // fire a load
|
||||
//
|
||||
@@ -44,13 +47,14 @@ namespace Cache::QueryLoad {
|
||||
|
||||
// Register a query cache for async-load tracking. `cacheInstance` is the
|
||||
// cache global (e.g. `Offsets::VAR_CREATURE_CACHE` cast to void*);
|
||||
// `eventName` is a Custom event the caller has reserved via
|
||||
// `Event::Custom::AutoReserve`, fired `(id, success)` on completion;
|
||||
// `getRecordAddr` is the cache class's `_GetRecord` (e.g.
|
||||
// `Offsets::FUN_CREATURE_GET_RECORD`). `cacheInstance`/`eventName` must
|
||||
// outlive the process (pass static values). Idempotent — calling again
|
||||
// for the same cache is a no-op (safe across /reload).
|
||||
void Register(void *cacheInstance, const char *eventName, uintptr_t getRecordAddr);
|
||||
// `reserve` is the caller's `Event::Custom::AutoReserve` for the
|
||||
// completion event, fired `(id, success)`; `getRecordAddr` is the cache
|
||||
// class's `_GetRecord` (e.g. `Offsets::FUN_CREATURE_GET_RECORD`).
|
||||
// `cacheInstance`/`reserve` must outlive the process (pass statics).
|
||||
// Idempotent — calling again for the same cache is a no-op (safe across
|
||||
// /reload).
|
||||
void Register(void *cacheInstance, const Event::Custom::AutoReserve *reserve,
|
||||
uintptr_t getRecordAddr);
|
||||
|
||||
// True if `id` is already in the cache (pure peek, no network query).
|
||||
bool IsCached(void *cacheInstance, uint32_t id);
|
||||
|
||||
@@ -361,7 +361,7 @@ void RegisterLuaFunctions() {
|
||||
Game::Lua::RegisterTableFunction("C_CreatureInfo", "GetCreatureTypeIDs",
|
||||
&Script_GetCreatureTypeIDs);
|
||||
Cache::QueryLoad::Register(reinterpret_cast<void *>(Offsets::VAR_CREATURE_CACHE),
|
||||
kCreatureDataLoadResult, Offsets::FUN_CREATURE_GET_RECORD);
|
||||
&_reserveLoadResult, Offsets::FUN_CREATURE_GET_RECORD);
|
||||
}
|
||||
|
||||
const Game::ModuleAutoRegister _autoreg{&RegisterLuaFunctions};
|
||||
|
||||
@@ -386,7 +386,7 @@ int __fastcall Script_UseEquipmentSet(void *L) {
|
||||
const uint32_t setID = ArgSetID(L, 1);
|
||||
const Set *s = Data::FindByID(setID);
|
||||
if (s == nullptr) {
|
||||
const int evt = Event::Custom::Lookup(kSwapFinishedEvent);
|
||||
const int evt = kEvtSwapFinished.Slot();
|
||||
if (evt >= 0)
|
||||
Event::Custom::Fire(evt, "%d%d", 0, static_cast<int>(setID));
|
||||
Game::Lua::PushBoolean(L, 0);
|
||||
@@ -396,7 +396,7 @@ int __fastcall Script_UseEquipmentSet(void *L) {
|
||||
// Fire PENDING right after the set-exists check, before any of
|
||||
// the swap work. Addon UI can use this to gate swap-in-progress
|
||||
// visuals.
|
||||
const int pendingEvt = Event::Custom::Lookup(kSwapPendingEvent);
|
||||
const int pendingEvt = kEvtSwapPending.Slot();
|
||||
if (pendingEvt >= 0)
|
||||
Event::Custom::Fire(pendingEvt, "%d", static_cast<int>(setID));
|
||||
|
||||
@@ -569,7 +569,7 @@ int __fastcall Script_UseEquipmentSet(void *L) {
|
||||
virtualPaperdoll[targetSlot - 1] = 0;
|
||||
}
|
||||
|
||||
const int evt = Event::Custom::Lookup(kSwapFinishedEvent);
|
||||
const int evt = kEvtSwapFinished.Slot();
|
||||
if (evt >= 0)
|
||||
Event::Custom::Fire(evt, "%d%d", 1, static_cast<int>(setID));
|
||||
|
||||
@@ -620,8 +620,5 @@ static void RegisterLuaFunctions() {
|
||||
}
|
||||
|
||||
static const Game::ModuleAutoRegister _autoreg{&RegisterLuaFunctions};
|
||||
static const Event::Custom::AutoReserve _reserve{kEventName};
|
||||
static const Event::Custom::AutoReserve _reservePending{kSwapPendingEvent};
|
||||
static const Event::Custom::AutoReserve _reserveFinished{kSwapFinishedEvent};
|
||||
|
||||
} // namespace EquipmentSet::Api
|
||||
|
||||
@@ -75,7 +75,7 @@ uint32_t NextAvailableID() {
|
||||
}
|
||||
|
||||
void FireChanged() {
|
||||
const int slot = Event::Custom::Lookup(kEventName);
|
||||
const int slot = kEvtSetsChanged.Slot();
|
||||
if (slot >= 0)
|
||||
Event::Custom::Fire(slot, "");
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "event/Custom.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
@@ -109,8 +111,9 @@ constexpr int LOC_MISSING = -1;
|
||||
// coincidence, not load-bearing).
|
||||
constexpr int LOC_IGNORED = 1;
|
||||
|
||||
// Custom event names. All three are reserved at module-init time
|
||||
// via `Event::Custom::AutoReserve` in `Api.cpp`.
|
||||
// Custom event reservations, shared by the Data and Api TUs (C++17 inline
|
||||
// variables — one instance each; the AutoReserve ctor dedups by name anyway).
|
||||
// Fire via `kEvt*.Slot()`.
|
||||
//
|
||||
// EQUIPMENT_SETS_CHANGED — no payload; fires on any mutation
|
||||
// (create / save / modify / delete /
|
||||
@@ -130,8 +133,8 @@ constexpr int LOC_IGNORED = 1;
|
||||
// pickup→equip pair actually completed,
|
||||
// matching modern's "we dispatched"
|
||||
// definition of success).
|
||||
constexpr const char *kEventName = "EQUIPMENT_SETS_CHANGED";
|
||||
constexpr const char *kSwapPendingEvent = "EQUIPMENT_SWAP_PENDING";
|
||||
constexpr const char *kSwapFinishedEvent = "EQUIPMENT_SWAP_FINISHED";
|
||||
inline const Event::Custom::AutoReserve kEvtSetsChanged{"EQUIPMENT_SETS_CHANGED"};
|
||||
inline const Event::Custom::AutoReserve kEvtSwapPending{"EQUIPMENT_SWAP_PENDING"};
|
||||
inline const Event::Custom::AutoReserve kEvtSwapFinished{"EQUIPMENT_SWAP_FINISHED"};
|
||||
|
||||
} // namespace EquipmentSet
|
||||
|
||||
+10
-10
@@ -244,25 +244,25 @@ void Grow() {
|
||||
} // namespace
|
||||
|
||||
AutoReserve::AutoReserve(const char *name) {
|
||||
if (name == nullptr || g_reservedCount >= MAX_RESERVED)
|
||||
if (name == nullptr)
|
||||
return;
|
||||
// Dedup: a name reserved twice resolves both instances to the one entry.
|
||||
for (int i = 0; i < g_reservedCount; ++i) {
|
||||
if (std::strcmp(g_reserved[i].name, name) == 0)
|
||||
if (std::strcmp(g_reserved[i].name, name) == 0) {
|
||||
index_ = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (g_reservedCount >= MAX_RESERVED)
|
||||
return; // overflow — index_ stays -1, Slot() reports unclaimed
|
||||
g_reserved[g_reservedCount].name = name;
|
||||
g_reserved[g_reservedCount].slot = -1;
|
||||
index_ = g_reservedCount;
|
||||
++g_reservedCount;
|
||||
}
|
||||
|
||||
int Lookup(const char *name) {
|
||||
if (name == nullptr)
|
||||
return -1;
|
||||
for (int i = 0; i < g_reservedCount; ++i) {
|
||||
if (std::strcmp(g_reserved[i].name, name) == 0)
|
||||
return g_reserved[i].slot;
|
||||
}
|
||||
return -1;
|
||||
int AutoReserve::Slot() const {
|
||||
return index_ >= 0 ? g_reserved[index_].slot : -1;
|
||||
}
|
||||
|
||||
int LookupByName(const char *name) {
|
||||
|
||||
+22
-17
@@ -37,31 +37,36 @@ namespace Event::Custom {
|
||||
// DLL operate on the table independently of the others.
|
||||
//
|
||||
// The name pointer must outlive the engine (a string literal does).
|
||||
// Same name reserved twice is deduped; reserving more than `MAX_RESERVED`
|
||||
// names total (see Custom.cpp) silently drops the overflow — keep that cap
|
||||
// above the codebase-wide `AutoReserve` count.
|
||||
// Same name reserved twice is deduped (both instances resolve to the same
|
||||
// reservation); reserving more than `MAX_RESERVED` names total (see
|
||||
// Custom.cpp) silently drops the overflow — keep that cap above the
|
||||
// codebase-wide `AutoReserve` count.
|
||||
//
|
||||
// Fire through the instance: `Fire(_r.Slot(), …)`. `Slot()` is the O(1)
|
||||
// read of the reservation's current slot id — it resolves through the
|
||||
// shared reservation table, so reload invalidation (`PrepareForReload`)
|
||||
// and re-claiming (`RetryClaims`) stay centralized and the value is never
|
||||
// stale. Returns -1 while unclaimed (before the first Lua-side
|
||||
// `RegisterEvent` triggers `RetryClaims`), which `Fire` treats as a no-op.
|
||||
// Do NOT cache the return across frames — read it at fire time (the read
|
||||
// is two loads; there is nothing to save).
|
||||
struct AutoReserve {
|
||||
explicit AutoReserve(const char *name);
|
||||
};
|
||||
int Slot() const;
|
||||
|
||||
// Returns the slot id currently assigned to `name`, or -1 if not yet
|
||||
// claimed (e.g. before the first Lua-side `RegisterEvent` has
|
||||
// triggered `RetryClaims`). Slot indices may change across `/reload`,
|
||||
// so call this at fire time rather than caching the value.
|
||||
//
|
||||
// Only consults our reservation cache — for engine-defined events
|
||||
// (UNIT_FACTION, BAG_UPDATE, etc.) use `LookupByName`.
|
||||
int Lookup(const char *name);
|
||||
private:
|
||||
int index_ = -1; // into the reservation table; -1 = dropped (overflow)
|
||||
};
|
||||
|
||||
// Walks the live engine event table at `[VAR_EVENT_TABLE_BASE_PTR]`
|
||||
// looking for an entry whose name strcmps equal to `name`. Returns
|
||||
// the slot index, or -1 if no entry matches.
|
||||
//
|
||||
// Works for both engine-defined events AND our `AutoReserve`-claimed
|
||||
// custom events (both populate the same table). Slightly slower than
|
||||
// `Lookup` (O(table size) vs O(reservations)) — prefer `Lookup` for
|
||||
// names we've reserved. Use this for engine-defined events we want to
|
||||
// fire ourselves (e.g., polyfilling missing event dispatches).
|
||||
// custom events (both populate the same table). O(table size) — for
|
||||
// names we've reserved, prefer the O(1) `AutoReserve::Slot()`. Use this
|
||||
// for engine-defined events we want to fire ourselves (e.g., polyfilling
|
||||
// missing event dispatches).
|
||||
int LookupByName(const char *name);
|
||||
|
||||
// True iff at least one frame is currently registered for the event in
|
||||
@@ -88,7 +93,7 @@ bool HasListeners(int slot);
|
||||
// Fire(slot, "%s%d", keyName, down); // MODIFIER_STATE_CHANGED(key, down)
|
||||
//
|
||||
// No-op for `eventID < 0`, which lets callers cheaply guard on the
|
||||
// `Lookup()` result without an explicit if.
|
||||
// `Slot()` result without an explicit if.
|
||||
template <typename... Args>
|
||||
inline void Fire(int eventID, const char *format, Args... args) {
|
||||
if (eventID < 0)
|
||||
|
||||
@@ -98,7 +98,7 @@ void __fastcall FireNotify_h(int factionID, int delta) {
|
||||
// any addon relying on the chat event firing first would expect.
|
||||
FireNotify_o(factionID, delta);
|
||||
|
||||
const int slot = Event::Custom::Lookup(kEventName);
|
||||
const int slot = _reserve.Slot();
|
||||
if (slot >= 0)
|
||||
Event::Custom::Fire(slot, "%d%d%d", factionID, newStanding, delta);
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ void RegisterLuaFunctions() {
|
||||
Game::Lua::RegisterTableFunction("C_GameObjectInfo", "RequestLoadGameObjectByID",
|
||||
&Script_RequestLoadGameObjectByID);
|
||||
Cache::QueryLoad::Register(reinterpret_cast<void *>(Offsets::VAR_GAMEOBJECT_CACHE),
|
||||
kGameObjectDataLoadResult, Offsets::FUN_GAMEOBJECT_GET_RECORD);
|
||||
&_reserveLoadResult, Offsets::FUN_GAMEOBJECT_GET_RECORD);
|
||||
}
|
||||
|
||||
const Game::ModuleAutoRegister _autoreg{&RegisterLuaFunctions};
|
||||
|
||||
@@ -64,8 +64,8 @@ namespace Input::GlobalMouse {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const char *kDownEvent = "GLOBAL_MOUSE_DOWN";
|
||||
constexpr const char *kUpEvent = "GLOBAL_MOUSE_UP";
|
||||
const Event::Custom::AutoReserve _reserveDown{"GLOBAL_MOUSE_DOWN"};
|
||||
const Event::Custom::AutoReserve _reserveUp{"GLOBAL_MOUSE_UP"};
|
||||
|
||||
// Held-state bitmap — bit `i` set means the button with 1-based
|
||||
// `IsMouseButtonDown` ID `i+1` is currently held. Modern API IDs:
|
||||
@@ -154,7 +154,7 @@ void ProcessMouseMessage(UINT msg, WPARAM wParam) {
|
||||
else g_mouseButtonMask &= ~bit;
|
||||
}
|
||||
|
||||
const int slot = Event::Custom::Lookup(down ? kDownEvent : kUpEvent);
|
||||
const int slot = (down ? _reserveDown : _reserveUp).Slot();
|
||||
if (slot >= 0)
|
||||
Event::Custom::Fire(slot, "%s", name);
|
||||
}
|
||||
@@ -241,8 +241,6 @@ void RegisterLuaFunctions() {
|
||||
InstallHook();
|
||||
}
|
||||
|
||||
const Event::Custom::AutoReserve _reserveDown{kDownEvent};
|
||||
const Event::Custom::AutoReserve _reserveUp{kUpEvent};
|
||||
const Tick::WorldTick::AutoSubscribe _evict{&EvictTick};
|
||||
const Game::ModuleAutoRegister _autoreg{&RegisterLuaFunctions};
|
||||
|
||||
|
||||
@@ -102,11 +102,9 @@ void SetBit(int bitIdx, bool down) {
|
||||
if (down) g_modifierMask |= bit;
|
||||
else g_modifierMask &= ~bit;
|
||||
|
||||
// Slot was assigned when the engine populated its event table; our
|
||||
// hook on `RebuildEventTable` recorded the index. Lookup at fire
|
||||
// time rather than caching because `/reload` re-runs the rebuild
|
||||
// and the index may shift.
|
||||
const int slot = Event::Custom::Lookup(kModifierStateChanged);
|
||||
// Read the slot at fire time (never cache it) — `/reload` rebuilds the
|
||||
// event table and the reservation re-claims, which may shift the index.
|
||||
const int slot = _reserveModifierStateChanged.Slot();
|
||||
if (slot >= 0)
|
||||
Event::Custom::Fire(slot, "%s%d", kKeyName[bitIdx], static_cast<int>(down));
|
||||
}
|
||||
|
||||
+4
-4
@@ -58,13 +58,13 @@ static const Event::Custom::AutoReserve _reserveItemDataLoadResult{kItemDataLoad
|
||||
static const Event::Custom::AutoReserve _reserveGetItemInfoReceived{kGetItemInfoReceived};
|
||||
|
||||
static void FireGetItemInfoReceived(int itemID, bool success) {
|
||||
Event::Custom::FireIdSuccess(Event::Custom::Lookup(kGetItemInfoReceived),
|
||||
itemID, success);
|
||||
Event::Custom::FireIdSuccess(_reserveGetItemInfoReceived.Slot(), itemID,
|
||||
success);
|
||||
}
|
||||
|
||||
static void FireItemDataLoadResult(int itemID, bool success) {
|
||||
Event::Custom::FireIdSuccess(Event::Custom::Lookup(kItemDataLoadResult),
|
||||
itemID, success);
|
||||
Event::Custom::FireIdSuccess(_reserveItemDataLoadResult.Slot(), itemID,
|
||||
success);
|
||||
}
|
||||
|
||||
// Item-load callbacks are __stdcall, 2 args / 8 bytes — matching the
|
||||
|
||||
@@ -318,7 +318,7 @@ void AppendNonBagOwned(uint64_t *out, int *count) {
|
||||
}
|
||||
|
||||
void FireChanged() {
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kEvtNewItems), "");
|
||||
Event::Custom::Fire(_r.Slot(), "");
|
||||
}
|
||||
|
||||
// Login-baseline handler. Runs every frame but does no work once the
|
||||
|
||||
@@ -344,7 +344,7 @@ StartFn_t g_origStart = nullptr;
|
||||
// structurally: a new item appears or the ring evicts an old one (shifting
|
||||
// every index).
|
||||
void FireFullUpdate() {
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kFullUpdate), "");
|
||||
Event::Custom::Fire(_evFullUpdate.Slot(), "");
|
||||
}
|
||||
|
||||
// START_ROLL: let the original build the store node, then read the item's
|
||||
@@ -373,8 +373,7 @@ void __fastcall Roll_h(void *msg, void *ctx, int a3) {
|
||||
if (structural)
|
||||
FireFullUpdate();
|
||||
if (itemIdx > 0)
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kRollChanged), "%d%d", itemIdx,
|
||||
playerIdx);
|
||||
Event::Custom::Fire(_evRollChanged.Slot(), "%d%d", itemIdx, playerIdx);
|
||||
}
|
||||
|
||||
void __fastcall Won_h(void *ctx, void *msg, int a3) {
|
||||
@@ -388,7 +387,7 @@ void __fastcall Won_h(void *ctx, void *msg, int a3) {
|
||||
if (structural)
|
||||
FireFullUpdate();
|
||||
if (itemIdx > 0)
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kRollComplete), "%d", itemIdx);
|
||||
Event::Custom::Fire(_evRollComplete.Slot(), "%d", itemIdx);
|
||||
}
|
||||
|
||||
void __fastcall Passed_h(void *ctx, void *msg) {
|
||||
@@ -402,7 +401,7 @@ void __fastcall Passed_h(void *ctx, void *msg) {
|
||||
if (structural)
|
||||
FireFullUpdate();
|
||||
if (itemIdx > 0)
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kRollComplete), "%d", itemIdx);
|
||||
Event::Custom::Fire(_evRollComplete.Slot(), "%d", itemIdx);
|
||||
}
|
||||
|
||||
const Game::HookAutoRegister _hookRoll{
|
||||
|
||||
+1
-1
@@ -267,7 +267,7 @@ void Complete() {
|
||||
s_scan.currentGuid = 0;
|
||||
s_scan.suppressEvents = false;
|
||||
s_scan.lootMode = false;
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kEventCompleted), "");
|
||||
Event::Custom::Fire(_reserve.Slot(), "");
|
||||
}
|
||||
|
||||
void TryStartNext() {
|
||||
|
||||
@@ -223,8 +223,8 @@ int BuildList(LocEntry *out, int maxOut) {
|
||||
// lesson). The scan is bounded (16 debuff slots) and early-outs when idle, so
|
||||
// the per-frame cost is negligible.
|
||||
|
||||
constexpr const char *kEventAdded = "LOSS_OF_CONTROL_ADDED";
|
||||
constexpr const char *kEventUpdate = "LOSS_OF_CONTROL_UPDATE";
|
||||
const Event::Custom::AutoReserve _reserveAdded{"LOSS_OF_CONTROL_ADDED"};
|
||||
const Event::Custom::AutoReserve _reserveUpdate{"LOSS_OF_CONTROL_UPDATE"};
|
||||
|
||||
// Identity of an active effect for frame-to-frame diffing: a CC is keyed by
|
||||
// spellID, a school interrupt by its school mask (spellID 0).
|
||||
@@ -255,7 +255,7 @@ void OnWorldTick() {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (!ContainsKey(g_prev, g_prevCount, cur[i])) {
|
||||
// A newly-applied effect -> LOSS_OF_CONTROL_ADDED(eventIndex).
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kEventAdded), "%d", i + 1);
|
||||
Event::Custom::Fire(_reserveAdded.Slot(), "%d", i + 1);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
@@ -269,15 +269,13 @@ void OnWorldTick() {
|
||||
// forward-compatible with per-unit tracking and matches modern WoW, whose
|
||||
// LOSS_OF_CONTROL_UPDATE carries the unit token.
|
||||
if (changed)
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kEventUpdate), "%s", "player");
|
||||
Event::Custom::Fire(_reserveUpdate.Slot(), "%s", "player");
|
||||
|
||||
for (int i = 0; i < n; ++i)
|
||||
g_prev[i] = cur[i];
|
||||
g_prevCount = n;
|
||||
}
|
||||
|
||||
static const Event::Custom::AutoReserve _reserveAdded{kEventAdded};
|
||||
static const Event::Custom::AutoReserve _reserveUpdate{kEventUpdate};
|
||||
static const Tick::WorldTick::AutoSubscribe _tick{&OnWorldTick};
|
||||
|
||||
// `C_LossOfControl.GetActiveLossOfControlDataCount()` -> number.
|
||||
|
||||
+11
-15
@@ -59,13 +59,9 @@ namespace NamePlate::Events {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const char *kEventCreated = "NAME_PLATE_CREATED";
|
||||
constexpr const char *kEventUnitAdded = "NAME_PLATE_UNIT_ADDED";
|
||||
constexpr const char *kEventUnitRemoved = "NAME_PLATE_UNIT_REMOVED";
|
||||
|
||||
const Event::Custom::AutoReserve _r1{kEventCreated};
|
||||
const Event::Custom::AutoReserve _r2{kEventUnitAdded};
|
||||
const Event::Custom::AutoReserve _r3{kEventUnitRemoved};
|
||||
const Event::Custom::AutoReserve _evtCreated{"NAME_PLATE_CREATED"};
|
||||
const Event::Custom::AutoReserve _evtUnitAdded{"NAME_PLATE_UNIT_ADDED"};
|
||||
const Event::Custom::AutoReserve _evtUnitRemoved{"NAME_PLATE_UNIT_REMOVED"};
|
||||
|
||||
// Previous tick's snapshot — GUID → nameplate-frame pointer for each
|
||||
// nameplated unit. Compared against the next tick's walk to compute
|
||||
@@ -112,14 +108,14 @@ int AssignSlot(uint64_t guid) {
|
||||
return static_cast<int>(g_slots.size() - 1);
|
||||
}
|
||||
|
||||
// Fire `eventName` with a pre-formatted string as `arg1`. The engine
|
||||
// Fire `event` with a pre-formatted string as `arg1`. The engine
|
||||
// dispatcher's `%s` format code pushes the C string into `_G.arg1`
|
||||
// as a Lua string — no escaping concerns for our own input
|
||||
// (`"nameplateN"`).
|
||||
void FireWithString(const char *eventName, const char *value) {
|
||||
void FireWithString(const Event::Custom::AutoReserve &event, const char *value) {
|
||||
if (value == nullptr)
|
||||
return;
|
||||
const int slot = Event::Custom::Lookup(eventName);
|
||||
const int slot = event.Slot();
|
||||
if (slot < 0)
|
||||
return;
|
||||
Event::Custom::Fire(slot, "%s", value);
|
||||
@@ -172,10 +168,10 @@ using LuaRefRef_t = int(__fastcall *)(void *L, int t);
|
||||
using LuaRefUnref_t = void(__fastcall *)(void *L, int t, int ref);
|
||||
using LuaRawGetI_t = void(__fastcall *)(void *L, int t, int n);
|
||||
|
||||
void FireWithFrame(const char *eventName, void *frame) {
|
||||
void FireWithFrame(const Event::Custom::AutoReserve &event, void *frame) {
|
||||
if (frame == nullptr)
|
||||
return;
|
||||
const int slot = Event::Custom::Lookup(eventName);
|
||||
const int slot = event.Slot();
|
||||
if (slot < 0)
|
||||
return;
|
||||
|
||||
@@ -229,7 +225,7 @@ void OnWorldTick() {
|
||||
// event handler.
|
||||
for (const auto &kv : g_currentTickPlates) {
|
||||
if (g_seenPlates.insert(kv.second).second)
|
||||
FireWithFrame(kEventCreated, const_cast<void *>(kv.second));
|
||||
FireWithFrame(_evtCreated, const_cast<void *>(kv.second));
|
||||
if (g_lastTickPlates.find(kv.first) == g_lastTickPlates.end()) {
|
||||
const int slot = AssignSlot(kv.first);
|
||||
// Watch this unit's fields so UNIT_HEALTH/UNIT_AURA/… fire with
|
||||
@@ -237,7 +233,7 @@ void OnWorldTick() {
|
||||
// target/party/raid tokens, not nameplates).
|
||||
Unit::TokenObserver::Register(kv.first, &NamePlateFieldCb);
|
||||
char tokenBuf[24];
|
||||
FireWithString(kEventUnitAdded,
|
||||
FireWithString(_evtUnitAdded,
|
||||
FormatNamePlateToken(tokenBuf, sizeof tokenBuf, slot + 1));
|
||||
}
|
||||
}
|
||||
@@ -254,7 +250,7 @@ void OnWorldTick() {
|
||||
continue;
|
||||
const int oneBased = static_cast<int>(it - g_slots.begin()) + 1;
|
||||
char tokenBuf[24];
|
||||
FireWithString(kEventUnitRemoved,
|
||||
FireWithString(_evtUnitRemoved,
|
||||
FormatNamePlateToken(tokenBuf, sizeof tokenBuf, oneBased));
|
||||
Unit::TokenObserver::Unregister(kv.first, &NamePlateFieldCb);
|
||||
*it = 0; // free the slot (no shift of survivors)
|
||||
|
||||
@@ -109,8 +109,7 @@ int __fastcall EquipSlotChanged_cb(uint32_t fieldOffset, uint32_t /*size*/,
|
||||
const int slot0 =
|
||||
static_cast<int>(fieldOffset - Offsets::OFF_DESC_PLAYER_EQUIP_FIRST) >> 3;
|
||||
if (slot0 >= 0 && slot0 < Offsets::DESC_PLAYER_EQUIP_SLOTS) {
|
||||
Event::Custom::FireIdSuccess(Event::Custom::Lookup(kEvtEquipmentChanged),
|
||||
slot0 + 1,
|
||||
Event::Custom::FireIdSuccess(_r.Slot(), slot0 + 1,
|
||||
SlotHasItem(guidLo, guidHi, slot0));
|
||||
// Gear swap changes item +healing and Spirit/Armor — invalidate the
|
||||
// GetSpellBonusHealing cache.
|
||||
@@ -225,7 +224,7 @@ void __fastcall AlertsRecompute_h() {
|
||||
return;
|
||||
}
|
||||
if (changed)
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kEvtDurability), "");
|
||||
Event::Custom::Fire(_r2.Slot(), "");
|
||||
}
|
||||
|
||||
static const Game::HookAutoRegister _alertsHook{
|
||||
|
||||
@@ -68,8 +68,7 @@ void __fastcall BindPointUpdateHandler_h(void *packetBuffer) {
|
||||
static_cast<uintptr_t>(Offsets::VAR_IN_WORLD)) == 0)
|
||||
return;
|
||||
|
||||
const int slot = Event::Custom::Lookup(kEventName);
|
||||
Event::Custom::Fire(slot, "");
|
||||
Event::Custom::Fire(_reserve.Slot(), "");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
+12
-18
@@ -43,12 +43,12 @@ namespace Player::InputEvents {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const char *kStartedMovingEvent = "PLAYER_STARTED_MOVING";
|
||||
constexpr const char *kStoppedMovingEvent = "PLAYER_STOPPED_MOVING";
|
||||
constexpr const char *kStartedLookingEvent = "PLAYER_STARTED_LOOKING";
|
||||
constexpr const char *kStoppedLookingEvent = "PLAYER_STOPPED_LOOKING";
|
||||
constexpr const char *kStartedTurningEvent = "PLAYER_STARTED_TURNING";
|
||||
constexpr const char *kStoppedTurningEvent = "PLAYER_STOPPED_TURNING";
|
||||
const Event::Custom::AutoReserve _reserveStartedMoving{"PLAYER_STARTED_MOVING"};
|
||||
const Event::Custom::AutoReserve _reserveStoppedMoving{"PLAYER_STOPPED_MOVING"};
|
||||
const Event::Custom::AutoReserve _reserveStartedLooking{"PLAYER_STARTED_LOOKING"};
|
||||
const Event::Custom::AutoReserve _reserveStoppedLooking{"PLAYER_STOPPED_LOOKING"};
|
||||
const Event::Custom::AutoReserve _reserveStartedTurning{"PLAYER_STARTED_TURNING"};
|
||||
const Event::Custom::AutoReserve _reserveStoppedTurning{"PLAYER_STOPPED_TURNING"};
|
||||
|
||||
// Below this per-frame delta, treat the yaw as stable. Picks up
|
||||
// real rotation (smallest user-perceptible RMB-drag is ~0.5°/frame
|
||||
@@ -85,12 +85,12 @@ const uint8_t *Camera() {
|
||||
gameState, Offsets::OFF_GAME_STATE_CAMERA_PTR);
|
||||
}
|
||||
|
||||
void FireTransition(bool now, bool &prev, const char *startedName,
|
||||
const char *stoppedName) {
|
||||
void FireTransition(bool now, bool &prev, const Event::Custom::AutoReserve &started,
|
||||
const Event::Custom::AutoReserve &stopped) {
|
||||
if (now == prev)
|
||||
return;
|
||||
prev = now;
|
||||
const int slot = Event::Custom::Lookup(now ? startedName : stoppedName);
|
||||
const int slot = (now ? started : stopped).Slot();
|
||||
if (slot >= 0)
|
||||
Event::Custom::Fire(slot, "");
|
||||
}
|
||||
@@ -172,19 +172,13 @@ void OnWorldTick() {
|
||||
g_havePrevCameraYaw = true;
|
||||
}
|
||||
|
||||
FireTransition(moving, g_wasMoving, kStartedMovingEvent, kStoppedMovingEvent);
|
||||
FireTransition(turning, g_wasTurning, kStartedTurningEvent, kStoppedTurningEvent);
|
||||
FireTransition(looking, g_wasLooking, kStartedLookingEvent, kStoppedLookingEvent);
|
||||
FireTransition(moving, g_wasMoving, _reserveStartedMoving, _reserveStoppedMoving);
|
||||
FireTransition(turning, g_wasTurning, _reserveStartedTurning, _reserveStoppedTurning);
|
||||
FireTransition(looking, g_wasLooking, _reserveStartedLooking, _reserveStoppedLooking);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
static const Event::Custom::AutoReserve _reserveStartedMoving{kStartedMovingEvent};
|
||||
static const Event::Custom::AutoReserve _reserveStoppedMoving{kStoppedMovingEvent};
|
||||
static const Event::Custom::AutoReserve _reserveStartedLooking{kStartedLookingEvent};
|
||||
static const Event::Custom::AutoReserve _reserveStoppedLooking{kStoppedLookingEvent};
|
||||
static const Event::Custom::AutoReserve _reserveStartedTurning{kStartedTurningEvent};
|
||||
static const Event::Custom::AutoReserve _reserveStoppedTurning{kStoppedTurningEvent};
|
||||
static const Tick::WorldTick::AutoSubscribe _tickSub{&OnWorldTick};
|
||||
|
||||
} // namespace Player::InputEvents
|
||||
|
||||
+3
-3
@@ -33,8 +33,8 @@ static const Event::Custom::AutoReserve _reserveQuestDataLoadResult{kQuestDataLo
|
||||
static void __stdcall QuestLoadCallback(void *userData, int success) {
|
||||
const auto questID =
|
||||
static_cast<int>(reinterpret_cast<uintptr_t>(userData));
|
||||
Event::Custom::FireIdSuccess(Event::Custom::Lookup(kQuestDataLoadResult),
|
||||
questID, success != 0);
|
||||
Event::Custom::FireIdSuccess(_reserveQuestDataLoadResult.Slot(), questID,
|
||||
success != 0);
|
||||
}
|
||||
|
||||
static void RequestAndMaybeNotify(uint32_t questID) {
|
||||
@@ -45,7 +45,7 @@ static void RequestAndMaybeNotify(uint32_t questID) {
|
||||
// invoking our callback. Fire the event ourselves so addons get the
|
||||
// notification regardless of cache state, matching modern semantics.
|
||||
if (wasCached) {
|
||||
Event::Custom::FireIdSuccess(Event::Custom::Lookup(kQuestDataLoadResult),
|
||||
Event::Custom::FireIdSuccess(_reserveQuestDataLoadResult.Slot(),
|
||||
static_cast<int>(questID), true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ void __fastcall QuestLogRebuild_h(int param_1) {
|
||||
// (login or post-reload). Modern WoW's QUEST_ACCEPTED doesn't
|
||||
// fire on initial sync either; we match that.
|
||||
if (newCount == 1) {
|
||||
const int slot = Event::Custom::Lookup(kAcceptedEventName);
|
||||
const int slot = _reserveAccepted.Slot();
|
||||
if (slot >= 0)
|
||||
Event::Custom::Fire(slot, "%d%d", firstNewIdx, firstNewID);
|
||||
}
|
||||
@@ -168,7 +168,7 @@ void __fastcall QuestLogRebuild_h(int param_1) {
|
||||
// all but one of the previous character's quests (1 removal, N
|
||||
// additions in the same rebuild).
|
||||
if (removedCount == 1 && newCount <= 1) {
|
||||
const int slot = Event::Custom::Lookup(kRemovedEventName);
|
||||
const int slot = _reserveRemoved.Slot();
|
||||
if (slot >= 0)
|
||||
Event::Custom::Fire(slot, "%d", firstRemovedID);
|
||||
}
|
||||
|
||||
@@ -77,8 +77,7 @@ int __fastcall Handler_h(void *thisPlayer, void *edx, void *packetStream) {
|
||||
const int result = Handler_o(thisPlayer, edx, packetStream);
|
||||
|
||||
if (questID > 0) {
|
||||
const int slot = Event::Custom::Lookup(kEventName);
|
||||
Event::Custom::Fire(slot, "%u%u%u",
|
||||
Event::Custom::Fire(_reserve.Slot(), "%u%u%u",
|
||||
questID, xpReward, moneyReward);
|
||||
}
|
||||
|
||||
|
||||
+23
-35
@@ -31,33 +31,20 @@ namespace Spell::CastEvents {
|
||||
namespace {
|
||||
|
||||
|
||||
constexpr const char *kStart = "UNIT_SPELLCAST_START";
|
||||
constexpr const char *kStop = "UNIT_SPELLCAST_STOP";
|
||||
constexpr const char *kDelayed = "UNIT_SPELLCAST_DELAYED";
|
||||
constexpr const char *kChannelStart = "UNIT_SPELLCAST_CHANNEL_START";
|
||||
constexpr const char *kChannelStop = "UNIT_SPELLCAST_CHANNEL_STOP";
|
||||
constexpr const char *kChannelUpdate = "UNIT_SPELLCAST_CHANNEL_UPDATE";
|
||||
constexpr const char *kSucceeded = "UNIT_SPELLCAST_SUCCEEDED";
|
||||
constexpr const char *kInterrupted = "UNIT_SPELLCAST_INTERRUPTED";
|
||||
constexpr const char *kFailed = "UNIT_SPELLCAST_FAILED";
|
||||
constexpr const char *kFailedQuiet = "UNIT_SPELLCAST_FAILED_QUIET";
|
||||
constexpr const char *kSent = "UNIT_SPELLCAST_SENT";
|
||||
constexpr const char *kReticleTarget = "UNIT_SPELLCAST_RETICLE_TARGET";
|
||||
constexpr const char *kReticleClear = "UNIT_SPELLCAST_RETICLE_CLEAR";
|
||||
|
||||
const Event::Custom::AutoReserve _rStart{kStart};
|
||||
const Event::Custom::AutoReserve _rStop{kStop};
|
||||
const Event::Custom::AutoReserve _rDelayed{kDelayed};
|
||||
const Event::Custom::AutoReserve _rChannelStart{kChannelStart};
|
||||
const Event::Custom::AutoReserve _rChannelStop{kChannelStop};
|
||||
const Event::Custom::AutoReserve _rChannelUpdate{kChannelUpdate};
|
||||
const Event::Custom::AutoReserve _rSucceeded{kSucceeded};
|
||||
const Event::Custom::AutoReserve _rInterrupted{kInterrupted};
|
||||
const Event::Custom::AutoReserve _rFailed{kFailed};
|
||||
const Event::Custom::AutoReserve _rFailedQuiet{kFailedQuiet};
|
||||
const Event::Custom::AutoReserve _rSent{kSent};
|
||||
const Event::Custom::AutoReserve _rReticleTarget{kReticleTarget};
|
||||
const Event::Custom::AutoReserve _rReticleClear{kReticleClear};
|
||||
// The reservations double as the fire handles (`k*.Slot()` — O(1)).
|
||||
const Event::Custom::AutoReserve kStart{"UNIT_SPELLCAST_START"};
|
||||
const Event::Custom::AutoReserve kStop{"UNIT_SPELLCAST_STOP"};
|
||||
const Event::Custom::AutoReserve kDelayed{"UNIT_SPELLCAST_DELAYED"};
|
||||
const Event::Custom::AutoReserve kChannelStart{"UNIT_SPELLCAST_CHANNEL_START"};
|
||||
const Event::Custom::AutoReserve kChannelStop{"UNIT_SPELLCAST_CHANNEL_STOP"};
|
||||
const Event::Custom::AutoReserve kChannelUpdate{"UNIT_SPELLCAST_CHANNEL_UPDATE"};
|
||||
const Event::Custom::AutoReserve kSucceeded{"UNIT_SPELLCAST_SUCCEEDED"};
|
||||
const Event::Custom::AutoReserve kInterrupted{"UNIT_SPELLCAST_INTERRUPTED"};
|
||||
const Event::Custom::AutoReserve kFailed{"UNIT_SPELLCAST_FAILED"};
|
||||
const Event::Custom::AutoReserve kFailedQuiet{"UNIT_SPELLCAST_FAILED_QUIET"};
|
||||
const Event::Custom::AutoReserve kSent{"UNIT_SPELLCAST_SENT"};
|
||||
const Event::Custom::AutoReserve kReticleTarget{"UNIT_SPELLCAST_RETICLE_TARGET"};
|
||||
const Event::Custom::AutoReserve kReticleClear{"UNIT_SPELLCAST_RETICLE_CLEAR"};
|
||||
|
||||
// Autoshot spams client-side failures while ramping — nampower filters it
|
||||
// out of its failure event, so do we.
|
||||
@@ -108,8 +95,9 @@ void BuildCastGuid(char *out, size_t n, int type, int spellID, int castUID) {
|
||||
// rank)`. Gated on a listener so an unwatched event does no DBC lookups or
|
||||
// string formatting. A null name/rank pushes `nil` through the dispatcher's
|
||||
// `lua_pushstring(NULL) → pushnil` tail-jump, which is fine.
|
||||
void Fire(const char *eventName, int spellID, int guidNum, int type = 3) {
|
||||
const int slot = Event::Custom::Lookup(eventName);
|
||||
void Fire(const Event::Custom::AutoReserve &event, int spellID, int guidNum,
|
||||
int type = 3) {
|
||||
const int slot = event.Slot();
|
||||
if (!Event::Custom::HasListeners(slot))
|
||||
return;
|
||||
const uint8_t *rec = Spell::Lookup::RecordForID(spellID);
|
||||
@@ -127,7 +115,7 @@ void Fire(const char *eventName, int spellID, int guidNum, int type = 3) {
|
||||
// inserted at arg2. `target` is a unit token (e.g. "target") resolved from
|
||||
// the cast packet, or "" for self / no-target casts.
|
||||
void FireSent(int spellID, int guidNum, const char *target) {
|
||||
const int slot = Event::Custom::Lookup(kSent);
|
||||
const int slot = kSent.Slot();
|
||||
if (!Event::Custom::HasListeners(slot))
|
||||
return;
|
||||
const uint8_t *rec = Spell::Lookup::RecordForID(spellID);
|
||||
@@ -148,8 +136,8 @@ void FireSent(int spellID, int guidNum, const char *target) {
|
||||
// the load-bearing fields — are exact; only arg2 differs (`""` vs `nil`),
|
||||
// which is inconsequential for a reticle (no cast to identify). spellName /
|
||||
// rank are our usual extension tail.
|
||||
void FireReticle(const char *eventName, int spellID) {
|
||||
const int slot = Event::Custom::Lookup(eventName);
|
||||
void FireReticle(const Event::Custom::AutoReserve &event, int spellID) {
|
||||
const int slot = event.Slot();
|
||||
if (!Event::Custom::HasListeners(slot))
|
||||
return;
|
||||
const uint8_t *rec = Spell::Lookup::RecordForID(spellID);
|
||||
@@ -382,9 +370,9 @@ const Net::SendObserver::AutoSubscribe _sendSub{&OnSend};
|
||||
// the payload is fanned out per token (`target` / `focus` / `nameplateN` /
|
||||
// `party` / `raid` / `mouseover`). Same `(unit, castGUID, spellID, spellName,
|
||||
// rank)` shape as the player events, just with a non-"player" unit.
|
||||
void FireRemote(const char *eventName, uint64_t casterGuid, int spellID,
|
||||
int guidNum) {
|
||||
const int slot = Event::Custom::Lookup(eventName);
|
||||
void FireRemote(const Event::Custom::AutoReserve &event, uint64_t casterGuid,
|
||||
int spellID, int guidNum) {
|
||||
const int slot = event.Slot();
|
||||
if (!Event::Custom::HasListeners(slot))
|
||||
return;
|
||||
const uint8_t *rec = Spell::Lookup::RecordForID(spellID);
|
||||
|
||||
+1
-1
@@ -284,7 +284,7 @@ void Set(uint64_t guid) {
|
||||
TokenObserver::Register(guid, &FocusFieldCb);
|
||||
g_focusObserved = true;
|
||||
}
|
||||
const int slot = Event::Custom::Lookup(kEventName);
|
||||
const int slot = _reserve.Slot();
|
||||
if (slot >= 0)
|
||||
Event::Custom::Fire(slot, "");
|
||||
}
|
||||
|
||||
@@ -173,8 +173,7 @@ void __fastcall BonusActionBarUpdate_h() {
|
||||
if (current < 0 || current == s_lastForm)
|
||||
return;
|
||||
s_lastForm = current;
|
||||
const int slot = Event::Custom::Lookup(kEventName);
|
||||
Event::Custom::Fire(slot, "");
|
||||
Event::Custom::Fire(_reserve.Slot(), "");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
+21
-4
@@ -108,6 +108,19 @@ constexpr const char *kEvtPlaybackStarted = "VOICE_CHAT_TTS_PLAYBACK_STARTED";
|
||||
constexpr const char *kEvtSpeakTextUpdate = "VOICE_CHAT_TTS_SPEAK_TEXT_UPDATE";
|
||||
constexpr const char *kEvtVoicesUpdate = "VOICE_CHAT_TTS_VOICES_UPDATE";
|
||||
|
||||
// The lazily-created reservations, set by RegisterLuaFunctions. Null while
|
||||
// standing down for VanillaTTS — but the fire helpers only run from our own
|
||||
// registered surface, so they never see null in that mode; SlotOf's guard is
|
||||
// belt-and-suspenders (`Fire(-1)` no-ops).
|
||||
const Event::Custom::AutoReserve *g_evtPlaybackFailed = nullptr;
|
||||
const Event::Custom::AutoReserve *g_evtPlaybackFinished = nullptr;
|
||||
const Event::Custom::AutoReserve *g_evtPlaybackStarted = nullptr;
|
||||
const Event::Custom::AutoReserve *g_evtVoicesUpdate = nullptr;
|
||||
|
||||
int SlotOf(const Event::Custom::AutoReserve *r) {
|
||||
return r != nullptr ? r->Slot() : -1;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// CVar names + handles (registered in RegisterLuaFunctions)
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -186,18 +199,18 @@ std::wstring Utf8ToWide(const char *s) {
|
||||
// Event fire helpers (engine dispatcher via Event::Custom)
|
||||
// ---------------------------------------------------------------------------
|
||||
void FireVoicesUpdate() {
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kEvtVoicesUpdate), "");
|
||||
Event::Custom::Fire(SlotOf(g_evtVoicesUpdate), "");
|
||||
}
|
||||
void FirePlaybackStarted(int numConsumers, int utteranceID, int durationMS, int dest) {
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kEvtPlaybackStarted), "%d%d%d%d",
|
||||
Event::Custom::Fire(SlotOf(g_evtPlaybackStarted), "%d%d%d%d",
|
||||
numConsumers, utteranceID, durationMS, dest);
|
||||
}
|
||||
void FirePlaybackFinished(int numConsumers, int utteranceID, int dest) {
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kEvtPlaybackFinished), "%d%d%d",
|
||||
Event::Custom::Fire(SlotOf(g_evtPlaybackFinished), "%d%d%d",
|
||||
numConsumers, utteranceID, dest);
|
||||
}
|
||||
void FirePlaybackFailed(const char *status, int utteranceID, int dest) {
|
||||
Event::Custom::Fire(Event::Custom::Lookup(kEvtPlaybackFailed), "%s%d%d",
|
||||
Event::Custom::Fire(SlotOf(g_evtPlaybackFailed), "%s%d%d",
|
||||
status, utteranceID, dest);
|
||||
}
|
||||
|
||||
@@ -565,6 +578,10 @@ void RegisterLuaFunctions() {
|
||||
static const Event::Custom::AutoReserve _r3{kEvtPlaybackStarted};
|
||||
static const Event::Custom::AutoReserve _r4{kEvtSpeakTextUpdate};
|
||||
static const Event::Custom::AutoReserve _r5{kEvtVoicesUpdate};
|
||||
g_evtPlaybackFailed = &_r1;
|
||||
g_evtPlaybackFinished = &_r2;
|
||||
g_evtPlaybackStarted = &_r3;
|
||||
g_evtVoicesUpdate = &_r5;
|
||||
|
||||
g_cvarVoice = CVar::Factory::Register(kCVarVoice, "0", 0, &OnVoiceChanged);
|
||||
g_cvarSpeed = CVar::Factory::Register(kCVarSpeed, "0", 0, &OnSpeedChanged);
|
||||
|
||||
Reference in New Issue
Block a user