Repository navigation
Expand file tree
/
Copy pathDescription.cpp
More file actions
110 lines (94 loc) · 4.75 KB
/
Copy pathDescription.cpp
File metadata and controls
110 lines (94 loc) · 4.75 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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// This file is part of ClassicAPI.
//
// ClassicAPI is free software: you can redistribute it and/or modify it under the terms
// of the GNU 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// ClassicAPI. If not, see <https://www.gnu.org/licenses/>.
#include "Description.h"
#include "Game.h"
#include "Offsets.h"
#include "item/Location.h"
#include "spell/Arg.h"
#include "spell/Lookup.h"
#include <cstdint>
namespace Spell::Description {
using FormatSpellDescription_t = void(__fastcall *)(const void *spellRecord, char *outBuf,
int bufLen, int contextFlag, int reserved3,
int useToolTipText, int reserved5,
int reserved6);
void Expand(const uint8_t *spellRecord, char *out, int outSize) {
out[0] = '\0';
auto fn = reinterpret_cast<FormatSpellDescription_t>(
Offsets::FUN_FORMAT_SPELL_DESCRIPTION);
fn(spellRecord, out, outSize,
/*contextFlag*/ 0,
/*reserved3*/ 0,
/*useToolTipText*/ 0, // 0 = read description (+0x228), non-zero = ToolTip (+0x24C)
/*reserved5*/ 1,
/*reserved6*/ 0);
}
static int __fastcall Script_GetSpellDescription(void *L) {
const int spellID = Spell::Arg::ResolveSpellID(L, 1);
const uint8_t *record = Spell::Lookup::RecordForID(spellID);
if (record == nullptr)
return 0; // nil for invalid / out-of-range spell IDs
// 1024 bytes is what every engine caller uses (`push 0x400`). Spell
// descriptions in vanilla don't exceed this in any locale; the helper
// null-terminates and stops writing on overflow, so the upper bound is
// self-enforced.
char buffer[0x400];
Expand(record, buffer, sizeof(buffer));
if (buffer[0] == '\0')
return 0; // empty / no description in current locale → nil
Game::Lua::PushString(L, buffer);
return 1;
}
// `C_Spell.GetSpellDescriptionForItemLocation(spell, itemLocation)` — the
// description as an item at `itemLocation` shows it. The item tooltip's
// spell lines (0x0052DA24) expand the spell's text with the same arguments
// `Expand` passes (pet 0, level 0, aura 0, stack 1, unmodified 0 —
// benilla-re ui/spelltokens), so the item contributes nothing to the text
// and the result is GetSpellDescription's. The location is still required,
// as the retail signature makes it.
static int __fastcall Script_GetSpellDescriptionForItemLocation(void *L) {
if (!Item::Location::IsLocationArg(L, 2)) {
Game::Lua::Error(L, "Usage: local description = "
"C_Spell.GetSpellDescriptionForItemLocation(spellIdentifier, itemLocation)");
return 0;
}
return Script_GetSpellDescription(L);
}
// --- Documentation ----------------------------------------------------------
static const Game::Doc::Field kGetSpellDescriptionArgs[] = {
Game::Doc::Req("spell", "SpellIdentifier", "A spell ID, spell link, or spell name."),
};
static const Game::Doc::Field kGetSpellDescriptionRets[] = {
Game::Doc::Opt("description", "string", nullptr,
"Nil for an unknown spell and for a spell with no description in "
"your language."),
};
static const Game::Doc::Function kGetSpellDescription{
"The spell's description text, with its placeholders filled in at the base rank.",
kGetSpellDescriptionArgs, kGetSpellDescriptionRets};
static const Game::Doc::Field kForItemLocationArgs[] = {
Game::Doc::Req("spell", "SpellIdentifier", "A spell ID, spell link, or spell name."),
Game::Doc::Req("itemLocation", "ItemLocation", "The item that shows the spell."),
};
static const Game::Doc::Function kGetSpellDescriptionForItemLocation{
"The spell's description text as an item's tooltip shows it.",
kForItemLocationArgs, kGetSpellDescriptionRets};
static void RegisterLuaFunctions() {
Game::Lua::RegisterTableFunction("C_Spell", "GetSpellDescription",
&Script_GetSpellDescription, &kGetSpellDescription);
Game::Lua::RegisterTableFunction("C_Spell", "GetSpellDescriptionForItemLocation",
&Script_GetSpellDescriptionForItemLocation,
&kGetSpellDescriptionForItemLocation);
}
static const Game::ModuleAutoRegister _autoreg{&RegisterLuaFunctions};
} // namespace Spell::Description