local AddonName, AddonTable = ...
local AceAddon = LibStub("AceAddon-3.0")
local AceConfig = LibStub("AceConfig-3.0")
local AceConfigDialog = LibStub("AceConfigDialog-3.0")
local AceDB = LibStub("AceDB-3.0")
local AceEvent = LibStub("AceEvent-3.0")
local addon = AceAddon:NewAddon(AddonName, "AceEvent-3.0", "AceConsole-3.0")
RaidHelper = addon
function RaidHelper:Initialize()
self.version = "1.2.3"
self.author = "PlayerName"
local addon = LibStub("AceAddon-3.0"):NewAddon("RaidHelper")
addon:SetDefaultModuleState(true)
addon:SetDefaultModuleLibraries("AceEvent-3.0")
self:RegisterEvents()
self:PrintMessage("RaidHelper initialized successfully")
if not RaidHelperDB then
RaidHelperDB = {}
end
RaidHelperDB:Load()
self:SetupSlashCommands()
self:CreateRaidFrame()
self:PrintMessage(string.format("RaidHelper v%s loaded", self.version))
end
function RaidHelper:OnEnable()
self:RegisterEvents()
self:RefreshRaidRoster()
self:ShowRaidFrame()
self:PrintMessage("RaidHelper enabled")
RaidHelperDB:Save()
LibStub("AceConfigDialog-3.0"):Open("RaidHelper")
end
function RaidHelper:OnDisable()
self:UnregisterEvents()
self:HideRaidFrame()
RaidHelperDB:Save()
self:PrintMessage("RaidHelper disabled")
end
function RaidHelper:RegisterEvents()
if not self.frame then
self.frame = CreateFrame("Frame", "RaidHelperEventFrame")
end
self.frame:RegisterEvent("PLAYER_ENTERING_WORLD")
self.frame:RegisterEvent("GROUP_ROSTER_UPDATE")
self.frame:RegisterEvent("UNIT_HEALTH")
self.frame:RegisterEvent("UNIT_AURA")
self.frame:RegisterEvent("PLAYER_REGEN_DISABLED")
self.frame:SetScript("OnEvent", function(frame, event, ...) self:HandleEvent(event, ...) end)
self:PrintMessage("Events registered")
end
function RaidHelper:UnregisterEvents()
if self.frame then
self.frame:UnregisterAllEvents()
self.frame:SetScript("OnEvent", nil)
end
self:PrintMessage("Events unregistered")
end
function RaidHelper:HandleEvent(event, ...)
local handlers = {
PLAYER_ENTERING_WORLD = function()
self:RefreshRaidRoster()
end,
GROUP_ROSTER_UPDATE = function()
self:RefreshRaidRoster()
self:UpdateMemberHealth(...)
end,
UNIT_HEALTH = function(unit)
self:UpdateMemberHealth(unit)
end,
UNIT_AURA = function(unit)
self:CheckBuffs(unit)
end,
UNIT_POWER = function(unit, powerType)
self:CheckBuffs(unit)
end,
PLAYER_REGEN_DISABLED = function()
self:PrintMessage("Entering combat!")
RaidHelperDB:Save()
end,
PLAYER_REGEN_ENABLED = function()
self:HideRaidFrame()
self:PrintMessage("Leaving combat!")
end,
UNKNOWN_EVENT = function()
self:PrintMessage("Unknown event received")
end,
}
local handler = handlers[event] or handlers.UNKNOWN_EVENT
handler()
end
function RaidHelper:RefreshRaidRoster()
self.raidMembers = {}
local numMembers = GetNumGroupMembers()
if not IsInRaid() then
return
end
for i = 1, numMembers do
local unit = "raid" .. i
local name = UnitName(unit)
local class = UnitClass(unit)
local maxHealth = UnitHealthMax(unit)
local currentHealth = UnitHealth(unit)
table.insert(self.raidMembers, {
unit = unit,
name = name,
class = class,
maxHealth = maxHealth,
currentHealth = currentHealth,
})
end
self:UpdateRaidFrame()
self:PrintMessage(string.format("Raid roster updated: %d members", numMembers))
end
function RaidHelper:UpdateMemberHealth(unit)
if not unit then
return
end
if not UnitExists(unit) then
return
end
local maxHealth = UnitHealthMax(unit)
local currentHealth = UnitHealth(unit)
for _, member in ipairs(self.raidMembers) do
if member.unit == unit then
member.maxHealth = maxHealth
member.currentHealth = currentHealth
table.insert(self.healthHistory, {
unit = unit,
time = GetTime(),
health = currentHealth,
})
end
end
end
function RaidHelper:CheckBuffs(unit)
if not unit then
return
end
local requiredBuffs = {
"Power Word: Fortitude",
"Arcane Intellect",
"Mark of the Wild",
"Blessing of Kings",
}
for _, buffName in ipairs(requiredBuffs) do
local hasBuffFound = false
for i = 1, 40 do
local name = UnitBuff(unit, i)
if name == buffName then
hasBuffFound = true
break
end
end
if not hasBuffFound then
self:ApplyBuff(unit, buffName)
end
end
self:PrintMessage(string.format("Checked buffs for %s", UnitName(unit)))
end
function RaidHelper:ApplyBuff(unit, buffName)
if not unit then
return
end
if not UnitExists(unit) then
return
end
local hasSpell = UnitBuff(unit, buffName)
if not hasSpell then
CastSpellByName(buffName, unit)
self:PrintMessage(string.format("Applied %s to %s", buffName, UnitName(unit)))
end
end
function RaidHelper:ShowRaidFrame()
if not self.raidFrame then
local frame = CreateFrame("Frame", "RaidHelperMainFrame", UIParent, "BasicFrameTemplateWithInset")
frame:SetTitle("Raid Helper")
frame:SetSize(400, 600)
frame:SetPoint("CENTER")
frame:SetBackdrop({
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
})
frame:SetBackdropColor(0, 0, 0, 0.8)
frame:SetMovable(true)
frame:EnableMouse(true)
frame:RegisterForDrag("LeftButton")
frame:SetScript("OnDragStart", frame.StartMoving)
frame:SetScript("OnDragStop", frame.StopMovingOrSizing)
self.raidFrame = frame
end
self.raidFrame:Show()
end
function RaidHelper:HideRaidFrame()
if self.raidFrame then
self.raidFrame:Hide()
end
end
function RaidHelper:UpdateRaidFrame()
if not self.raidFrame then
return
end
if self.raidFrame.members then
for _, memberFrame in ipairs(self.raidFrame.members) do
memberFrame:Hide()
memberFrame:SetParent(nil)
end
end
self.raidFrame.members = {}
for i, member in ipairs(self.raidMembers) do
local memberFrame = CreateFrame("Frame", nil, self.raidFrame)
memberFrame:SetSize(380, 40)
memberFrame:SetPoint("TOPLEFT", 10, -30 - (i - 1) * 45)
local nameText = memberFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
nameText:SetPoint("LEFT", 5, 0)
nameText:SetText(member.name)
local healthBar = CreateFrame("StatusBar", nil, memberFrame)
healthBar:SetSize(200, 20)
healthBar:SetPoint("LEFT", 120, 0)
healthBar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
healthBar:SetMinMaxValues(0, member.maxHealth)
healthBar:SetValue(member.currentHealth)
table.insert(self.raidFrame.members, memberFrame)
end
end
function RaidHelper:PrintMessage(message)
if not message then
return
end
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00[RaidHelper]|r " .. message)
end
function RaidHelper:GetOptions()
local options = {
type = "group",
name = "Raid Helper",
args = {
enable = {
type = "toggle",
name = "Enable Addon",
get = function() return self:IsEnabled() end,
set = function(_, value)
if value then
self:OnEnable()
else
self:OnDisable()
end
end,
},
showFrame = {
type = "toggle",
name = "Show Raid Frame",
get = function() return self.raidFrame and self.raidFrame:IsShown() end,
set = function(_, value)
if value then
self:ShowRaidFrame()
else
self:HideRaidFrame()
end
end,
},
},
}
return options
end
RaidHelperDB = RaidHelperDB or {}
function RaidHelperDB:Reset()
RaidHelperSavedVariables = {
version = "1.2.3",
enabled = true,
showFrame = true,
raidMembers = {},
settings = {
autoHeal = false,
autoBuff = true,
announceBuffs = true,
},
}
end
function RaidHelperDB:Save()
if not RaidHelperSavedVariables then
self:Reset()
end
RaidHelperSavedVariables.raidMembers = RaidHelper.raidMembers or {}
RaidHelperSavedVariables.lastUpdate = time()
RaidHelper:PrintMessage("Database saved")
end
function RaidHelperDB:Load()
if not RaidHelperSavedVariables then
self:Reset()
end
if RaidHelperSavedVariables.raidMembers then
RaidHelper.raidMembers = RaidHelperSavedVariables.raidMembers
end
RaidHelper:PrintMessage("Database loaded")
end
function RaidHelperDB:Get(key)
if not RaidHelperSavedVariables then
return nil
end
return RaidHelperSavedVariables[key]
end
function RaidHelperDB:Set(key, value)
if not RaidHelperSavedVariables then
self:Reset()
end
RaidHelperSavedVariables[key] = value
self:Save()
end
function RaidHelper:SetupSlashCommands()
SLASH_RAIDHELPER1 = "/rh"
SLASH_RAIDHELPER2 = "/raidhelper"
end
SlashCmdList["RAIDHELPER"] = function(msg)
local command, args = msg:match("^(%S*)%s*(.-)$")
local commands = {
show = function()
RaidHelper:ShowRaidFrame()
end,
hide = function()
RaidHelper:HideRaidFrame()
end,
refresh = function()
RaidHelper:RefreshRaidRoster()
end,
enable = function()
RaidHelper:OnEnable()
end,
disable = function()
RaidHelper:OnDisable()
end,
reset = function()
RaidHelperDB:Reset()
RaidHelper:PrintMessage("Database reset")
end,
config = function()
LibStub("AceConfigDialog-3.0"):Open("RaidHelper")
end,
help = function()
RaidHelper:PrintMessage("Available commands:")
RaidHelper:PrintMessage("/rh show - Show raid frame")
RaidHelper:PrintMessage("/rh hide - Hide raid frame")
RaidHelper:PrintMessage("/rh refresh - Refresh raid roster")
RaidHelper:PrintMessage("/rh enable - Enable addon")
RaidHelper:PrintMessage("/rh disable - Disable addon")
RaidHelper:PrintMessage("/rh reset - Reset database")
RaidHelper:PrintMessage("/rh config - Open config")
end,
}
local handler = commands[command] or commands.help
handler()
end
local function GetClassColor(class)
local colors = {
WARRIOR = { r = 0.78, g = 0.61, b = 0.43 },
PALADIN = { r = 0.96, g = 0.55, b = 0.73 },
HUNTER = { r = 0.67, g = 0.83, b = 0.45 },
ROGUE = { r = 1.00, g = 0.96, b = 0.41 },
PRIEST = { r = 1.00, g = 1.00, b = 1.00 },
DEATHKNIGHT = { r = 0.77, g = 0.12, b = 0.23 },
SHAMAN = { r = 0.00, g = 0.44, b = 0.87 },
MAGE = { r = 0.25, g = 0.78, b = 0.92 },
WARLOCK = { r = 0.53, g = 0.53, b = 0.93 },
MONK = { r = 0.00, g = 1.00, b = 0.59 },
DRUID = { r = 1.00, g = 0.49, b = 0.04 },
DEMONHUNTER = { r = 0.64, g = 0.19, b = 0.79 },
}
return colors[class] or { r = 1, g = 1, b = 1 }
end
local function FormatHealthPercent(current, max)
if max == 0 then
return "0%"
end
local percent = (current / max) * 100
return string.format("%.1f%%", percent)
end
local function IsPlayerInRange(unit)
if not UnitExists(unit) then
return false
end
return CheckInteractDistance(unit, 4)
end
local function GetUnitRole(unit)
local role = UnitGroupRolesAssigned(unit)
if role == "TANK" then
return "Tank"
elseif role == "HEALER" then
return "Healer"
elseif role == "DAMAGER" then
return "DPS"
else
return "Unknown"
end
end
local function OnAddonLoaded(self, event, addonName)
if addonName == "RaidHelper" then
RaidHelper:Initialize()
end
end
local function OnPlayerLogin(self)
RaidHelper:OnEnable()
end
local function OnPlayerLogout(self)
RaidHelper:OnDisable()
RaidHelperDB:Save()
end
local loaderFrame = CreateFrame("Frame")
loaderFrame:RegisterEvent("ADDON_LOADED")
loaderFrame:RegisterEvent("PLAYER_LOGIN")
loaderFrame:RegisterEvent("PLAYER_LOGOUT")
loaderFrame:SetScript("OnEvent", function(self, event, ...)
if event == "ADDON_LOADED" then
OnAddonLoaded(self, event, ...)
elseif event == "PLAYER_LOGIN" then
OnPlayerLogin(self)
elseif event == "PLAYER_LOGOUT" then
OnPlayerLogout(self)
end
end)
local function ParseCombatLog()
local timestamp, eventType, _, sourceGUID, sourceName, _, _, destGUID, destName = CombatLogGetCurrentEventInfo()
if eventType == "SPELL_CAST_SUCCESS" then
RaidHelper:PrintMessage(string.format("%s cast a spell", sourceName))
elseif eventType == "SPELL_DAMAGE" then
RaidHelper:PrintMessage(string.format("%s took damage", destName))
elseif eventType == "SPELL_HEAL" then
RaidHelper:PrintMessage(string.format("%s was healed", destName))
end
end
local combatFrame = CreateFrame("Frame")
combatFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
combatFrame:SetScript("OnEvent", ParseCombatLog)
local MinimapButton = {
icon = "Interface\\Icons\\Ability_Warrior_RallyingCry",
}
function MinimapButton:Initialize()
local LDB = LibStub("LibDataBroker-1.1")
local icon = LibStub("LibDBIcon-1.0")
local dataObject = LDB:NewDataObject("RaidHelper", {
type = "launcher",
icon = self.icon,
OnClick = function(_, button)
if button == "LeftButton" then
RaidHelper:ShowRaidFrame()
elseif button == "RightButton" then
LibStub("AceConfigDialog-3.0"):Open("RaidHelper")
end
end,
OnTooltipShow = function(tooltip)
tooltip:AddLine("Raid Helper")
tooltip:AddLine("Left-click: Show raid frame")
tooltip:AddLine("Right-click: Open config")
end,
})
icon:Register("RaidHelper", dataObject, RaidHelperDB:Get("minimap"))
end
MinimapButton:Initialize()
local function CreateGroupFinderListing()
local activityID = C_LFGList.GetActivityInfoTable(1)
C_LFGList.CreateListing({
activityID = activityID,
name = "Raid Helper Group",
comment = "Looking for more!",
voiceChat = "",
itemLevel = 0,
honorLevel = 0,
})
RaidHelper:PrintMessage("Group listing created")
end
hooksecurefunc("LFGListInviteDialog_Show", function()
RaidHelper:PrintMessage("Group finder opened")
end)
return RaidHelper