Files
ScaledLifeTap/tests/mockwow.lua
T
2026-10-30 16:56:31 +00:00

184 lines
11 KiB
Lua

-- Minimal WoW 1.12 API mock for offline testing (Lua 5.0)
MOCK = { gear = {}, locale = "enUS", casts = {}, events = {}, frames = {} }
function GetLocale() return MOCK.locale end
function getglobal(n) return _G[n] end
function setglobal(n, v) _G[n] = v end
DEFAULT_CHAT_FRAME = { AddMessage = function(self, m) if MOCK.echo then print("[chat] " .. m) end end }
GREEN_FONT_COLOR_CODE, HIGHLIGHT_FONT_COLOR_CODE, LIGHTYELLOW_FONT_COLOR_CODE = "", "", ""
BOOKTYPE_SPELL = "spell"
SlashCmdList = {}
UIParent = {}
NORMAL_FONT_COLOR = { r = 1, g = 0.82, b = 0 }
GRAY_FONT_COLOR = { r = 0.5, g = 0.5, b = 0.5 }
UISpecialFrames = {}
GameTooltip = setmetatable({}, { __index = function() return function() end end })
-- UIDropDownMenu: record the menu built by the initializer so tests can click entries
MOCK.dropdownItems = {}
function UIDropDownMenu_SetWidth() end
function UIDropDownMenu_Initialize(frame, init) MOCK.dropdownItems = {}; frame.init = init; init() end
function UIDropDownMenu_AddButton(info) table.insert(MOCK.dropdownItems, info) end
function UIDropDownMenu_SetSelectedValue(frame, v) frame.selectedValue = v end
local SLOTIDS = { HeadSlot=1, NeckSlot=2, ShoulderSlot=3, ShirtSlot=4, ChestSlot=5, WaistSlot=6, LegsSlot=7,
FeetSlot=8, WristSlot=9, HandsSlot=10, Finger0Slot=11, Finger1Slot=12, Trinket0Slot=13, Trinket1Slot=14,
BackSlot=15, MainHandSlot=16, SecondaryHandSlot=17, RangedSlot=18, TabardSlot=19 }
function GetInventorySlotInfo(name) return SLOTIDS[name], "" end
MOCK.tooltipCalls = 0
local NOOP = function() end
-- unknown UI methods (Capitalized, as all WoW widget methods are) are no-ops; plain fields stay nil
local frameMeta = { __index = function(t, k)
if type(k) == "string" and string.find(k, "^%u") then return NOOP end
end }
local function newFontString()
local fs = { text = nil }
function fs:SetText(t) self.text = t end
function fs:GetText() return self.text end
function fs:SetTextColor(r, g, b) self.color = { r, g, b } end
return setmetatable(fs, frameMeta)
end
MOCK.newFontString = newFontString
local function newFrame(name, template)
local f = { events = {}, scripts = {}, shown = true, name = name, template = template, enabled = true }
function f:RegisterEvent(e) self.events[e] = true end
function f:UnregisterEvent(e) self.events[e] = nil end
function f:SetScript(s, fn) self.scripts[s] = fn end
function f:GetScript(s) return self.scripts[s] end
function f:Show()
local was = self.shown
self.shown = true
if not was and self.scripts.OnShow then local old = this; this = self; self.scripts.OnShow(); this = old end
end
function f:Hide() self.shown = false end
function f:IsShown() return self.shown end
function f:IsVisible() return self.shown end
function f:GetName() return self.name end
function f:SetParent(p) self.parentFrame = p end
function f:GetChecked() return self.checked end
function f:SetChecked(v) self.checked = v end
function f:Enable() self.enabled = true end
function f:Disable() self.enabled = false end
function f:SetMinMaxValues(a, b) self.min, self.max = a, b end
function f:SetValue(v)
self.value = v
if self.scripts.OnValueChanged then local old = this; this = self; self.scripts.OnValueChanged(); this = old end
end
function f:GetValue() return self.value end
function f:SetText(t) self.text = t end
function f:GetText() return self.text end
f.CreateFontString = function() return newFontString() end
if name then
_G[name] = f
if template == "OptionsCheckButtonTemplate" then _G[name .. "Text"] = newFontString() end
if template == "OptionsSliderTemplate" then
_G[name .. "Text"], _G[name .. "Low"], _G[name .. "High"] = newFontString(), newFontString(), newFontString()
end
end
table.insert(MOCK.frames, f)
return setmetatable(f, frameMeta)
end
MOCK.newFrame = newFrame
function CreateFrame(kind, name, parent, template)
local f = newFrame(name, template)
f.kind = kind
if kind == "GameTooltip" then
f.lines = {}
for i = 1, 30 do
local idx = i
local fs = { GetText = function() return f.lines[idx] end }
if name then _G[name .. "TextLeft" .. i] = fs; _G[name .. "TextRight" .. i] = { GetText = function() return nil end } end
end
function f:SetOwner() end
function f:ClearLines() self.lines = {} end
function f:NumLines() return table.getn(self.lines) end
function f:SetInventoryItem(unit, slot)
MOCK.tooltipCalls = MOCK.tooltipCalls + 1
local item = MOCK.gear[slot]
if not item then self.lines = {}; return nil end
self.lines = item
return 1
end
end
return f
end
-- emulate the XML-created objects BonusScanner expects
function MOCK.makeBonusScannerFrames()
CreateFrame("GameTooltip", "BonusScannerTooltip")
local f = newFrame("BonusScannerFrame")
this = f
BonusScanner:OnLoad()
f.scripts.OnEvent = function() BonusScanner:OnEvent() end
f.scripts.OnUpdate = function() BonusScanner:OnUpdate(arg1) end
return f
end
function MOCK.fire(ev, a1)
for _, f in ipairs(MOCK.frames) do
if f.events[ev] and f.scripts.OnEvent then
this, event, arg1 = f, ev, a1
f.scripts.OnEvent()
end
end
end
function MOCK.tick(elapsed)
for _, f in ipairs(MOCK.frames) do
if f.shown and f.scripts.OnUpdate then
this, arg1 = f, elapsed
f.scripts.OnUpdate()
end
end
end
-- player state
MOCK.hp, MOCK.hpmax, MOCK.mana, MOCK.manamax = 3500, 3500, 1000, 5000
function UnitHealth() return MOCK.hp end
function UnitHealthMax() return MOCK.hpmax end
function UnitMana() return MOCK.mana end
function UnitManaMax() return MOCK.manamax end
function UnitClass() return "Warlock", "WARLOCK" end
function UnitBuff() return nil end
function CastSpellByName(s) table.insert(MOCK.casts, s) end
function CastSpell(id, book) table.insert(MOCK.casts, "id:" .. id) end
MOCK.spellbook = { {"Shadow Bolt","Rank 9"} }
function GetSpellName(i, book)
local s = MOCK.spellbook[i]
if s then return s[1], s[2] end
return nil
end
MOCK.talents = { [1] = { {"Suppression"},{"Improved Corruption"},{"Improved Curse of Weakness"},{"Improved Drain Soul"},{"Improved Life Tap", 2} } }
function GetNumTalentTabs() return 3 end
function GetNumTalents(tab) return table.getn(MOCK.talents[tab] or {}) end
function GetTalentInfo(tab, i)
local t = MOCK.talents[tab] and MOCK.talents[tab][i]
if t then return t[1], "", 1, 1, t[2] or 0, 2 end
end
function IsAddOnLoaded(n) return MOCK.loaded and MOCK.loaded[n] end
-- realistic level-60 warlock gear (T2-ish / AQ40 / Naxx flavoured), tooltip lines incl. name line
MOCK.SAMPLE_GEAR = {
[1] = {"Nemesis Skullcap","Binds when picked up","Head","Cloth","124 Armor","+26 Stamina","+16 Intellect","+10 Shadow Resistance","Durability 60 / 60","Classes: Warlock","Requires Level 60","Equip: Improves your chance to get a critical strike with spells by 1%.","Equip: Increases damage and healing done by magical spells and effects by up to 32.","+8 Spell Damage and Healing","Nemesis Raiment (3/8)"," Nemesis Skullcap"," Nemesis Robes"," Nemesis Leggings","(3) Set: Reduces the threat generated by your Destruction spells by 20%.","(5) Set: Reduces the cooldown of your Shadow Ward by 4 sec.","(8) Set: Your Shadow Bolt has a chance to..."},
[2] = {"Choker of the Fire Lord","Binds when picked up","Neck","+7 Stamina","+7 Intellect","Requires Level 60","Equip: Increases damage and healing done by magical spells and effects by up to 34.","Equip: Decreases the magical resistances of your spell targets by 10."},
[3] = {"Nemesis Spaulders","Binds when picked up","Shoulder","Cloth","+20 Stamina","+13 Intellect","Equip: Increases damage and healing done by magical spells and effects by up to 23.","Zandalar Signet of Mojo","Nemesis Raiment (3/8)"},
[5] = {"Nemesis Robes","Binds when picked up","Chest","Cloth","+26 Stamina","+16 Intellect","+10 Fire Resistance","Equip: Increases damage and healing done by magical spells and effects by up to 32.","+4 All Stats","Nemesis Raiment (3/8)","(3) Set: Reduces the threat generated by your Destruction spells by 20%."},
[6] = {"Belt of the Fallen Emperor","Binds when picked up","Waist","Cloth","+17 Stamina","+18 Intellect","Equip: Improves your chance to hit with spells by 1%.","Equip: Increases damage and healing done by magical spells and effects by up to 22."},
[7] = {"Nemesis Leggings","Binds when picked up","Legs","Cloth","+23 Stamina","+16 Intellect","Equip: Increases damage and healing done by magical spells and effects by up to 39.","Equip: Improves your chance to get a critical strike with spells by 1%.","Nemesis Raiment (3/8)"},
[8] = {"Boots of Epiphany","Binds when picked up","Feet","Cloth","+15 Stamina","+19 Intellect","Equip: Increases damage and healing done by magical spells and effects by up to 34.","Run Speed Increased"},
[9] = {"Rejuvenating Bracers","Binds when picked up","Wrist","Cloth","+10 Intellect","Equip: Increases damage done by Shadow spells and effects by up to 21.","+9 Stamina"},
[10] = {"Gloves of Ebru","Binds when picked up","Hands","Cloth","+20 Stamina","+13 Intellect","Equip: Increases damage and healing done by magical spells and effects by up to 28.","+2% Threat"},
[11] = {"Ring of the Fallen God","Binds when picked up","Finger","+5 Stamina","+6 Intellect","Equip: Increases damage and healing done by magical spells and effects by up to 37.","Equip: Improves your chance to hit with spells by 1%."},
[12] = {"Band of Forced Concentration","Binds when picked up","Finger","+12 Stamina","+9 Intellect","Equip: Improves your chance to hit with spells by 1%.","Equip: Increases damage and healing done by magical spells and effects by up to 21."},
[13] = {"Talisman of Ephemeral Power","Binds when picked up","Trinket","Use: Increases damage and healing done by magical spells and effects by up to 175 for 15 sec."},
[14] = {"Briarwood Reed","Binds when picked up","Trinket","Equip: Increases damage and healing done by magical spells and effects by up to 29."},
[15] = {"Cloak of the Necropolis","Binds when picked up","Back","+11 Stamina","+12 Intellect","Equip: Improves your chance to hit with spells by 1%.","Equip: Increases damage and healing done by magical spells and effects by up to 26.","+3 Agility"},
[16] = {"Spinal Reaper","Binds when picked up","Two-Hand","Staff","163 - 246 Damage","Speed 3.20","(63.9 damage per second)","+16 Stamina","+21 Intellect","Equip: Increases damage done by Shadow spells and effects by up to 54.","+30 Spell Damage","Brilliant Wizard Oil (30 min)"},
[18] = {"Wand of Biting Cold","Binds when picked up","Ranged","Wand","Frost Damage","Equip: Increases damage and healing done by magical spells and effects by up to 12."},
}
-- expected SHADOWDMG + DMG (gear-only, no Use: or temporary oils since BonusScanner counts oils): computed in tests