Add files via upload

This commit is contained in:
2026-08-09 09:02:43 +02:00
committed by GitHub
commit 46dca62dc0
2 changed files with 754 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
## Interface: 11200
## Title: HealerProtection
## Notes: Alert your group when you run out of mana, take aggro, or are about to die! Designed for OctoWow.
## Author: Dusk92
## Version: 1.0-OctoWow
## SavedVariablesPerCharacter: HPTABPC
## OptionalDeps: SuperWow, ClassicAPI, NamPower
# Fichiers de l'addon
core.lua
+744
View File
@@ -0,0 +1,744 @@
-- HealerProtection Vanilla / Turtle WoW Port
-- Ported for the 1.12.1 client (with SuperWow / ClassicAPI support)
-- Optimized version: cached lookups, removed unused temp table, fixed NEARDEATH bug, removed role detection (Force Healer bypass always on)
-- Optimization pass 2: SETOOMP getglobal only runs when actually needed, GetLang()/GetLocale() cached
-- in ToCurrentChat instead of being recomputed up to 5 times, IsPlayerInBG() cache shared with CanWriteToChat
HealerProtection = HealerProtection or {}
local HPDEBUG = false
local warning_aggro = nil
local nearoom = false
local oom = false
local aggro = false
local isdead = false
local isChanneling = false
local onceM1 = false
local onceM2 = false
local lasttarget = ""
local delayrange = GetTime()
local outsideOfGroup = false
-- ============================================================================
-- UTILS AND VANILLA 1.12 COMPATIBILITY
-- ============================================================================
-- Cleanly retrieves the number of group members
local function GetGroupMembersCount()
if GetNumGroupMembers then return GetNumGroupMembers() end
local raid = GetNumRaidMembers()
if raid > 0 then return raid end
return GetNumPartyMembers()
end
-- Checks if the player is in a battleground
local function IsPlayerInBG()
for i = 1, (MAX_BATTLEFIELD_QUEUES or 3) do
local status = GetBattlefieldStatus(i)
if status == "active" then
return true
end
end
return false
end
-- Mana resource abstraction
local function GetUnitPower(unit)
if UnitPower then return UnitPower(unit) end
return UnitMana(unit)
end
local function GetUnitPowerMax(unit)
if UnitPowerMax then return UnitPowerMax(unit) end
return UnitManaMax(unit)
end
local function GetUnitPowerType(unit)
if UnitPowerType then
local _, token = UnitPowerType(unit)
return token
end
local t = UnitManaType(unit)
if t == 0 then return "MANA" end
return "OTHER"
end
-- Safe wrapper for C_Timer.After
local function SafeAfter(delay, func)
if C_Timer and C_Timer.After then
C_Timer.After(delay, func)
else
local fAfter = CreateFrame("Frame")
local elapsed_time = 0
fAfter:SetScript("OnUpdate", function(self, elapsed)
local dt = elapsed or arg1 or 0
elapsed_time = elapsed_time + dt
if elapsed_time >= delay then
fAfter:SetScript("OnUpdate", nil)
func()
end
end)
end
end
-- Simplified aggro detection (adapts if SuperWow is installed)
local function GetThreatSituation()
if UnitThreatSituation then
return UnitThreatSituation("player")
else
if UnitExists("target") and not UnitIsFriend("player", "target") then
if UnitIsUnit("targettarget", "player") then
return 3
end
end
return 0
end
end
-- ============================================================================
-- HEALERPROTECTION FUNCTIONS
-- ============================================================================
-- Optimization: accepts an already computed channel to avoid recomputing GetCurrentChannel()
-- on every single call (PrintChat can call this up to 6 times per tick)
function HealerProtection:AllowedTo(cachedChannel)
local channel = cachedChannel or HealerProtection:GetCurrentChannel()
if HealerProtection:DBGV("printnothing", false) then
return false
end
-- SAY and YELL don't require being in a party/raid/guild to make sense
if channel == "SAY" or channel == "YELL" then
return true
end
-- GUILD requires actually being in a guild
if channel == "GUILD" then
if GetGuildInfo("player") ~= nil or HPDEBUG then
return true
end
if outsideOfGroup == false then
outsideOfGroup = true
HealerProtection:INFO("Not in a Guild")
end
return false
end
-- RAID requires actually being in a raid (being in a simple party is not enough)
if channel == "RAID" then
if GetNumRaidMembers() > 0 or HPDEBUG then
return true
end
if outsideOfGroup == false then
outsideOfGroup = true
HealerProtection:INFO("Not in a Raid")
end
return false
end
-- PARTY (and AUTO, already resolved to PARTY/RAID by GetCurrentChannel)
if GetGroupMembersCount() > 0 or HPDEBUG then
return true
end
if outsideOfGroup == false then
outsideOfGroup = true
HealerProtection:INFO("Not in a Party/Raid")
end
return false
end
function HealerProtection:GetCurrentChannel()
local _channel = "PARTY"
if HealerProtection:DBGV("channelchat", "AUTO") == "AUTO" then
if GetNumRaidMembers() > 0 then
_channel = "RAID"
elseif GetNumPartyMembers() > 0 then
_channel = "PARTY"
end
else
_channel = HealerProtection:DBGV("channelchat", "AUTO")
end
return _channel
end
function HealerProtection:InInstance()
if HPDEBUG then return true end
local is, _ = IsInInstance()
return is
end
-- Optimization: accepts an already computed inInstance to avoid a redundant call to InInstance()
-- Optimization: accepts an already computed inBG to avoid a redundant call to IsPlayerInBG()
function HealerProtection:CanWriteToChat(chan, cachedInInstance, cachedInBG)
local inInstance = cachedInInstance
if inInstance == nil then
inInstance = HealerProtection:InInstance()
end
local inBG = cachedInBG
if inBG == nil then
inBG = IsPlayerInBG()
end
if onceM1 and not inInstance and HealerProtection:DBGV("showoutsideofinstance", false) == false then
onceM1 = false
HealerProtection:MSG("Only shows Messages in Instances.")
end
if inInstance or HealerProtection:DBGV("showoutsideofinstance", false) then
if HealerProtection:DBGV("printnothing", false) == true then
if onceM2 then
onceM2 = false
HealerProtection:MSG("\"Print Nothing\" is enabled.")
end
return false
elseif inBG and HealerProtection:DBGV("showinbgs", false) == false then
return false
elseif (GetNumRaidMembers() > 0) and HealerProtection:DBGV("showinraids", true) == false then
return false
else
return true
end
end
return false
end
function HealerProtection:GetLang()
-- Optimization: GetLocale() cached once instead of being called up to 3 times below
local locale = GetLocale()
if locale == "enUS" then return locale end
if HealerProtection:DBGV("showonlyenglish", false) then return "enUS" end
if HealerProtection:DBGV("showonlytranslation", false) then return locale end
if HealerProtection:DBGV("showtranslation", true) then return "enUS," .. locale end
return "enUS"
end
function HealerProtection:ToCurrentChat(formatStr, val1text, val1val, val2text, val2val, cachedChannel, cachedInInstance, cachedInBG)
local inInstance = cachedInInstance
if inInstance == nil then
inInstance = HealerProtection:InInstance()
end
-- Optimization: computed once here and passed down to CanWriteToChat below,
-- instead of letting IsPlayerInBG() run a second time inside it.
local inBG = cachedInBG
if inBG == nil then
inBG = IsPlayerInBG()
end
local _channel = cachedChannel or HealerProtection:GetCurrentChannel()
local prefix = HealerProtection:DBGV("prefix", "[Healer Protection]")
local suffix = HealerProtection:DBGV("suffix", "")
if prefix ~= "" and prefix ~= " " then
prefix = prefix .. " "
elseif prefix == " " then
prefix = ""
end
if suffix ~= "" and suffix ~= " " then
suffix = " " .. suffix
elseif suffix == " " then
suffix = ""
end
-- Optimization: reuse of already computed inInstance / inBG, avoids extra calls
if HealerProtection:CanWriteToChat(_channel, inInstance, inBG) then
-- Optimization: GetLang() and GetLocale() cached once instead of being recomputed
-- (each re-running its own DBGV / GetLocale lookups) up to 5 times in the block below
local lang = HealerProtection:GetLang()
local locale = GetLocale()
local msg = ""
if lang == "enUS" then
if val2text then
msg = string.format(formatStr, HealerProtection:TryTrans(val1text, "enUS", val1val), HealerProtection:TryTrans(val2text, "enUS", val2val))
elseif val1text then
msg = string.format(formatStr, HealerProtection:TryTrans(val1text, "enUS", val1val))
end
elseif lang == locale then
if val2text then
msg = string.format(formatStr, HealerProtection:TryTrans(val1text, locale, val1val), HealerProtection:TryTrans(val2text, locale, val2val))
elseif val1text then
msg = string.format(formatStr, HealerProtection:TryTrans(val1text, locale, val1val))
end
else
if val2text then
msg = string.format(formatStr, HealerProtection:TryTrans(val1text, "enUS", val1val), HealerProtection:TryTrans(val2text, "enUS", val2val))
elseif val1text then
msg = string.format(formatStr, HealerProtection:TryTrans(val1text, "enUS", val1val))
end
if val2text then
msg = msg .. " [" .. string.format(formatStr, HealerProtection:TryTrans(val1text, locale, val1val), HealerProtection:TryTrans(val2text, locale, val2val)) .. "]"
elseif val1text then
msg = msg .. " [" .. string.format(formatStr, HealerProtection:TryTrans(val1text, locale, val1val)) .. "]"
end
end
local mes = prefix .. msg .. "." .. suffix
if mes ~= nil then
if SendChatMessage then
SendChatMessage(mes, _channel)
end
end
end
end
function HealerProtection:Setup()
if HealerProtection:IsSetup() then
if not InCombatLockdown() then
HPTABPC = HPTABPC or {}
HealerProtection:SetSetup(false)
warning_aggro = CreateFrame("Frame", nil, UIParent)
warning_aggro:SetFrameStrata("BACKGROUND")
warning_aggro:SetWidth(128)
warning_aggro:SetHeight(64)
warning_aggro.text = warning_aggro:CreateFontString(nil, "ARTWORK")
local font = STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF"
warning_aggro.text:SetFont(font, 20, "OUTLINE")
warning_aggro.text:SetPoint("CENTER", 0, 300)
warning_aggro.text:SetText(HealerProtection:Trans("LID_youhaveaggro") .. "!")
warning_aggro.text:SetTextColor(1, 0, 0, 1)
warning_aggro:SetPoint("CENTER", 0, 0)
warning_aggro:Hide()
local f = CreateFrame("Frame")
f:RegisterEvent("UI_ERROR_MESSAGE")
f:SetScript("OnEvent", function(self, event, a1)
local errMessage = a1 or arg1
if event == "UI_ERROR_MESSAGE" and errMessage == SPELL_FAILED_LINE_OF_SIGHT then
local TName = UnitName("target")
if TName and UnitIsFriend("player", "target") then
if lasttarget ~= TName or delayrange < GetTime() then
delayrange = GetTime() + 1
lasttarget = TName
if HealerProtection:DBGV("notinsight", false) then
local tex = "Target is not in the field of view (" .. TName .. ")"
if HealerProtection:DBGV("showtranslation", true) and GetLocale() ~= "enUS" then
tex = tex .. " [" .. errMessage .. " (" .. TName .. ")]"
end
HealerProtection:ToCurrentChat("%s", tex)
end
end
end
end
end)
local channeling = CreateFrame("Frame")
channeling:RegisterEvent("SPELLCAST_CHANNEL_START")
channeling:RegisterEvent("SPELLCAST_CHANNEL_STOP")
channeling:SetScript("OnEvent", function(self, event)
if event == "SPELLCAST_CHANNEL_START" then
isChanneling = true
elseif event == "SPELLCAST_CHANNEL_STOP" then
isChanneling = false
end
end)
HealerProtection:SetDbTab(HPTABPC)
HealerProtection:InitSetting()
if C_Timer and C_Timer.NewTicker then
C_Timer.NewTicker(1, function() HealerProtection:PrintChat() end)
else
local tickerFrame = CreateFrame("Frame")
local elapsed_time = 0
tickerFrame:SetScript("OnUpdate", function(self, elapsed)
local dt = elapsed or arg1 or 0
elapsed_time = elapsed_time + dt
if elapsed_time >= 1 then
elapsed_time = 0
HealerProtection:PrintChat()
end
end)
end
else
SafeAfter(0.1, function() HealerProtection:Setup() end)
end
end
end
function HealerProtection:PrintChat()
-- Optimization: OOM / NEAROOM thresholds are cached once per tick
local oomPerc = HealerProtection:DBGV("OOMPercentage", 10)
local nearOomPerc = HealerProtection:DBGV("NEAROOMPercentage", 30)
-- Optimization: getglobal("SETOOMP") now only runs when the thresholds are actually
-- misconfigured (oomPerc > nearOomPerc). With default settings (10 <= 30) that's false,
-- so before this change the getglobal lookup ran uselessly every single second, forever.
if oomPerc > nearOomPerc then
local SETOOMP = getglobal("SETOOMP")
if SETOOMP ~= nil and not InCombatLockdown() then
HPTABPC["OOMPercentage"] = nearOomPerc
SETOOMP:SetValue(HPTABPC["OOMPercentage"])
oomPerc = nearOomPerc
end
end
local inInstance = HealerProtection:InInstance()
local inBG = IsPlayerInBG()
local _channel = HealerProtection:GetCurrentChannel()
if not HealerProtection:CanWriteToChat(_channel, inInstance, inBG) then return end
if HealerProtection:IsLoaded() then
-- Role detection removed: the "Force Healer" bypass is now always active,
-- so there is no need to check the player's class/role here anymore.
-- Note: "printnothing" is already checked inside CanWriteToChat right above,
-- so if we reach this point it is guaranteed to be false -- no need to test it again.
-- Optimization: AllowedTo() only depends on the channel/group/guild/raid state,
-- none of which can change mid-tick, so it's computed once and reused below
-- instead of being called up to 6 times per tick (chat + emote x3 alerts).
local canAnnounce = HealerProtection:AllowedTo(_channel)
if not UnitIsDead("player") then
isdead = false
-- AGGRO LOGIC
if HealerProtection:DBGV("AGGRO", false) then
local status = GetThreatSituation()
if status ~= nil then
if status > 0 and not aggro then
if HealerProtection:DBGV("showaggrochat", true) and canAnnounce then
HealerProtection:ToCurrentChat("{rt8} %s", "LID_ihaveaggro", nil, nil, nil, _channel, inInstance, inBG)
end
if HealerProtection:DBGV("showaggroemote", true) and canAnnounce and not isChanneling then
DoEmote("helpme")
end
aggro = true
elseif status == 0 and aggro then
aggro = false
end
else
aggro = false
end
if warning_aggro then
if aggro then
warning_aggro:Show()
else
warning_aggro:Hide()
end
end
else
if warning_aggro then
warning_aggro:Hide()
end
end
-- MANA AND HEALTH LOGIC
local powerToken = GetUnitPowerType("player")
if powerToken == "MANA" then
local mana = GetUnitPower("player")
local manamax = GetUnitPowerMax("player")
local manaperc = HealerProtection:MathR((mana / manamax) * 100, 1)
-- OOM Alert (without percentage)
if HealerProtection:DBGV("OOM", true) then
if manaperc <= oomPerc and not oom then
oom = true
if HealerProtection:DBGV("showoomchat", true) and canAnnounce then
HealerProtection:ToCurrentChat("%s (%s)", "LID_outofmana", nil, "LID_xmana", manaperc, _channel, inInstance, inBG)
end
if HealerProtection:DBGV("showoomemote", true) and canAnnounce and not isChanneling then
DoEmote("oom")
end
elseif manaperc > oomPerc + 20 and oom then
oom = false
end
end
-- Near-OOM Alert (without percentage)
if HealerProtection:DBGV("NEAROOM", true) and not oom then
if manaperc <= nearOomPerc and not nearoom then
nearoom = true
if HealerProtection:DBGV("shownearoomchat", true) and canAnnounce then
HealerProtection:ToCurrentChat("%s (%s)", "LID_nearoutofmana", nil, "LID_xmana", manaperc, _channel, inInstance, inBG)
end
if HealerProtection:DBGV("shownearoomemote", true) and canAnnounce and not isChanneling then
DoEmote("incoming")
end
elseif manaperc > nearOomPerc + 20 and nearoom then
nearoom = false
end
end
end
elseif not isdead then
isdead = true
if HealerProtection:DBGV("deathmessage", true) then
HealerProtection:ToCurrentChat("%s", "LID_healerisdead", nil, nil, nil, _channel, inInstance, inBG)
end
end
end
end
-- ============================================================================
-- SETTINGS WINDOW AND SLASH COMMANDS (HOMEMADE FOR 1.12)
-- ============================================================================
function HealerProtection:DBGV(key, default)
if HPTABPC and HPTABPC[key] ~= nil then
return HPTABPC[key]
end
return default
end
SLASH_HEALERPROTECTION1 = "/hp"
SLASH_HEALERPROTECTION2 = "/healerprotection"
SlashCmdList["HEALERPROTECTION"] = function(msg)
if HPOptionsFrame and HPOptionsFrame:IsVisible() then
HPOptionsFrame:Hide()
else
if not HPOptionsFrame then
HealerProtection:CreateGUI()
end
HPOptionsFrame:Show()
end
end
function HealerProtection:CreateGUI()
local f = CreateFrame("Frame", "HPOptionsFrame", UIParent)
f:SetWidth(400)
f:SetHeight(755)
f:SetPoint("CENTER", UIParent, "CENTER")
f:SetBackdrop({
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
tile = true, tileSize = 32, edgeSize = 32,
insets = { left = 11, right = 12, top = 12, bottom = 11 }
})
f:SetMovable(true)
f:EnableMouse(true)
f:RegisterForDrag("LeftButton")
f:SetScript("OnDragStart", function() f:StartMoving() end)
f:SetScript("OnDragStop", function() f:StopMovingOrSizing() end)
f:SetFrameStrata("DIALOG")
f:Hide()
f.title = f:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
f.title:SetPoint("TOP", 0, -18)
f.title:SetText("Healer Protection - Settings")
local btnClose = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
btnClose:SetWidth(100)
btnClose:SetHeight(24)
btnClose:SetPoint("BOTTOM", 0, 16)
btnClose:SetText("Close")
btnClose:SetScript("OnClick", function() f:Hide() end)
-- ------------------------------------------------------------------
-- Helpers
-- ------------------------------------------------------------------
local function CreateCheckbox(name, label, dbKey, defaultValue, xOffset, yOffset)
local cb = CreateFrame("CheckButton", "HPCB_"..name, f, "UICheckButtonTemplate")
cb:SetPoint("TOPLEFT", xOffset, yOffset)
getglobal(cb:GetName().."Text"):SetText(label)
getglobal(cb:GetName().."Text"):SetTextColor(1, 1, 1)
cb:SetScript("OnShow", function()
local val = HPTABPC[dbKey]
if val == nil then val = defaultValue end
cb:SetChecked(val and 1 or nil)
end)
cb:SetScript("OnClick", function()
local isChecked = (cb:GetChecked() == 1)
HPTABPC[dbKey] = isChecked
end)
return cb
end
-- labelFormat must contain one "%d" placeholder for the current value, e.g. "If under %d%% Health, print message"
local function CreateSlider(name, labelFormat, dbKey, defaultValue, minVal, maxVal, yOffset)
local slider = CreateFrame("Slider", "HPSL_"..name, f, "OptionsSliderTemplate")
slider:SetPoint("TOP", 0, yOffset)
slider:SetWidth(320)
slider:SetHeight(16)
slider:SetOrientation("HORIZONTAL")
slider:SetMinMaxValues(minVal, maxVal)
slider:SetValueStep(1)
getglobal(slider:GetName().."Low"):SetText(tostring(minVal))
getglobal(slider:GetName().."High"):SetText(tostring(maxVal))
local sliderLabel = getglobal(slider:GetName().."Text")
local function UpdateLabel(val)
sliderLabel:SetText(string.format(labelFormat, val))
end
slider:SetScript("OnShow", function()
local val = HPTABPC[dbKey]
if val == nil then val = defaultValue end
slider:SetValue(val)
UpdateLabel(val)
end)
slider:SetScript("OnValueChanged", function()
local val = arg1
if val == nil then val = slider:GetValue() end
val = math.floor(val + 0.5)
HPTABPC[dbKey] = val
UpdateLabel(val)
end)
return slider
end
local function CreateEditBox(name, xOffset, yOffset, width, dbKey, defaultValue)
local labelFS = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
labelFS:SetPoint("TOPLEFT", xOffset, yOffset)
labelFS:SetText(name)
local eb = CreateFrame("EditBox", "HPEB_"..name, f, "InputBoxTemplate")
eb:SetWidth(width)
eb:SetHeight(20)
eb:SetPoint("TOPLEFT", xOffset + 4, yOffset - 18)
eb:SetAutoFocus(false)
eb:SetScript("OnShow", function()
local val = HPTABPC[dbKey]
if val == nil then val = defaultValue end
eb:SetText(val)
end)
eb:SetScript("OnEnterPressed", function()
HPTABPC[dbKey] = eb:GetText()
eb:ClearFocus()
end)
eb:SetScript("OnEditFocusLost", function()
HPTABPC[dbKey] = eb:GetText()
end)
return eb
end
local function CreateChannelDropdown(xOffset, yOffset)
local labelFS = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
labelFS:SetPoint("TOPLEFT", xOffset, yOffset)
labelFS:SetText("Announce Channel")
local dropdown = CreateFrame("Frame", "HPChannelDropDown", f, "UIDropDownMenuTemplate")
dropdown:SetPoint("TOPLEFT", xOffset - 16, yOffset - 18)
UIDropDownMenu_SetWidth(120, dropdown)
local channels = { "AUTO", "SAY", "YELL", "PARTY", "RAID", "GUILD" }
local function OnClick()
local value = this.value
HPTABPC["channelchat"] = value
UIDropDownMenu_SetSelectedValue(dropdown, value)
UIDropDownMenu_SetText(value, dropdown)
end
local function Initialize()
for _, chan in ipairs(channels) do
local info = {}
info.text = chan
info.value = chan
info.func = OnClick
UIDropDownMenu_AddButton(info)
end
end
UIDropDownMenu_Initialize(dropdown, Initialize)
local current = HealerProtection:DBGV("channelchat", "AUTO")
UIDropDownMenu_SetSelectedValue(dropdown, current)
UIDropDownMenu_SetText(current, dropdown)
return dropdown
end
-- ------------------------------------------------------------------
-- Layout (mirrors the D4KiR Healer Protection panel, minus the CC
-- checkbox grid top-right and the Loss of control section at the bottom)
-- ------------------------------------------------------------------
CreateCheckbox("PrintNothing", "Print Nothing", "printnothing", false, 20, -45)
CreateCheckbox("ShowInRaid", "Show in Raids", "showinraids", true, 20, -70)
CreateCheckbox("Outside", "Show outside", "showoutsideofinstance", false, 20, -95)
CreateCheckbox("ShowInBG", "Show in Battlegrounds", "showinbgs", false, 20, -120)
CreateCheckbox("Aggro", "AGGRO", "AGGRO", false, 20, -155)
CreateCheckbox("AggroChat", "AGGRO Chat-Message", "showaggrochat", true, 40, -180)
CreateCheckbox("AggroEmote", "AGGRO Emote", "showaggroemote", true, 40, -205)
CreateCheckbox("DeathMessage", "Death message", "deathmessage", true, 20, -230)
CreateCheckbox("OOM", "Out of Mana", "OOM", true, 20, -265)
CreateCheckbox("OOMChat", "OOM Chat-Message", "showoomchat", true, 40, -290)
CreateCheckbox("OOMEmote", "OOM Emote", "showoomemote", true, 40, -315)
CreateSlider("OomPerc", "If under %d%% Mana, print message", "OOMPercentage", 10, 1, 10, -355)
CreateCheckbox("NearOOM", "Near out of Mana", "NEAROOM", true, 20, -410)
CreateCheckbox("NearOOMChat", "Near OOM Chat-Message", "shownearoomchat", true, 40, -435)
CreateCheckbox("NearOOMEmote", "Near OOM Emote", "shownearoomemote", true, 40, -460)
CreateSlider("NearOomPerc", "If under %d%% Mana, print message", "NEAROOMPercentage", 30, 11, 30, -500)
CreateChannelDropdown(20, -555)
CreateEditBox("Prefix", 20, -615, 160, "prefix", "[Healer Protection]")
CreateEditBox("Suffix", 210, -615, 160, "suffix", "")
end
-- ============================================================================
-- MAGIC PATCH: STANDALONE BOOTSTRAP AND TRANSLATIONS
-- ============================================================================
local traductions = {
["LID_youhaveaggro"] = "You have aggro",
["LID_ihaveaggro"] = "Aggro on me! Get it off!",
["LID_outofmana"] = "I am OOM!",
["LID_nearoutofmana"] = "Low Mana!",
["LID_xmana"] = "%s%% Mana",
["LID_neardeath"] = "Help, I'm dying!",
["LID_xhealth"] = "%s%% HP",
["LID_healerisdead"] = "Healer is down... Fly, you fools!"
} -- BUG FIXED: closing brace was missing in the original file, which would have caused a Lua syntax error
function HealerProtection:Trans(key)
return traductions[key] or key
end
function HealerProtection:TryTrans(key, lang, val)
local texte = traductions[key] or key
if val then
return string.format(texte, tostring(val))
end
return texte
end
function HealerProtection:IsSetup() return true end
function HealerProtection:SetSetup() end
function HealerProtection:SetDbTab() end
function HealerProtection:InitSetting() end
function HealerProtection:IsLoaded() return true end
function HealerProtection:INFO(msg) DEFAULT_CHAT_FRAME:AddMessage("|cFF00FFFF[HP Info]|r " .. msg) end
function HealerProtection:MSG(msg) DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00[HP]|r " .. msg) end
function HealerProtection:MathR(val, dec)
dec = dec or 0
local mult = 10 ^ dec
return math.floor(val * mult + 0.5) / mult
end
local bootFrame = CreateFrame("Frame")
bootFrame:RegisterEvent("PLAYER_LOGIN")
bootFrame:SetScript("OnEvent", function()
HealerProtection:Setup()
DEFAULT_CHAT_FRAME:AddMessage("|cFF00FF00[Healer Protection]|r ready and armed! Type |cFFFFFF00/hp|r to configure the alerts.")
end)