-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCooldown.cpp
More file actions
77 lines (63 loc) · 3.15 KB
/
Cooldown.cpp
File metadata and controls
77 lines (63 loc) · 3.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// This file is part of ClassicAPI.
//
// ClassicAPI is free software: you can redistribute it and/or modify it under the terms
// of the GNU Lesser General Public License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// ClassicAPI is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more details.
// `C_Spell.GetSpellCooldown(spellIdentifier)` — modern table-shape
// cooldown query that accepts spellID, name, name(rank), or
// `|Hspell:N|h` hyperlink, and returns a `SpellCooldownInfo` table
// (or nil for unrecognized spells). Vanilla 1.12 only ships
// `GetSpellCooldown(slot, bookType)`, which forces callers to walk
// the spellbook first and rejects spellIDs not in it (talent
// passives, profession recipes, etc.).
//
// Same `FUN_SPELL_QUERY_COOLDOWN` helper `Spell::Usable` uses for
// the cooldown gate, just exposed through the modern table shape.
#include "Arg.h"
#include "Lookup.h"
#include "Game.h"
#include "Offsets.h"
#include <cstdint>
namespace Spell::Cooldown {
namespace {
using QueryCooldown_t = void(__fastcall *)(int spellID, int bookType,
int *outDuration,
int *outStart,
int *outEnable);
int __fastcall Script_C_Spell_GetSpellCooldown(void *L) {
const int spellID = Spell::Arg::ResolveSpellID(L, 1);
if (spellID <= 0 || Spell::Lookup::RecordForID(spellID) == nullptr)
return 0;
auto fn = reinterpret_cast<QueryCooldown_t>(
static_cast<uintptr_t>(Offsets::FUN_SPELL_QUERY_COOLDOWN));
int durationMs = 0, startMs = 0, enable = 0;
fn(spellID, 0 /* bookType=player */, &durationMs, &startMs, &enable);
Game::Lua::NewTable(L);
// Engine returns ms with the same epoch as `GetTime()` — multiply
// by 0.001 to match modern's seconds-from-`GetTime` shape, same
// conversion `Script_GetSpellCooldown` does at the Lua boundary.
Game::Lua::SetFieldNumber(L, "startTime",
static_cast<double>(startMs) * 0.001);
Game::Lua::SetFieldNumber(L, "duration",
static_cast<double>(durationMs) * 0.001);
Game::Lua::SetFieldBool(L, "isEnabled", enable != 0);
// Vanilla has no haste-on-cooldown mechanic. Hard-code 1.0 so
// modern code that divides remaining-time by `modRate` works.
Game::Lua::SetFieldNumber(L, "modRate", 1.0);
// `activeCategory` / `timeUntilEndOfStartRecovery` / `isOnGCD`
// are 11.1.5+ / 12.0+ fields with no vanilla source — leave
// unset so they read as nil, matching modern's "field present
// but inapplicable" semantics.
return 1;
}
} // namespace
static void RegisterLuaFunctions() {
Game::Lua::RegisterTableFunction("C_Spell", "GetSpellCooldown",
&Script_C_Spell_GetSpellCooldown);
}
static const Game::ModuleAutoRegister _autoreg{&RegisterLuaFunctions};
} // namespace Spell::Cooldown