commit 07b87b2c127dec75a5536ebec8f6dacf341a1a05 Author: Sumsebrum Date: Mon May 17 16:49:54 2021 +0200 init v1.0.3-Beta diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f00ad52 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.idea +Gladdy +BuffLib +*.zip +*.psd +Ace-Libs +Images_Raw +Gladdy_old \ No newline at end of file diff --git a/Bindings.xml b/Bindings.xml new file mode 100644 index 0000000..2bd08d7 --- /dev/null +++ b/Bindings.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Constants.lua b/Constants.lua new file mode 100644 index 0000000..b6ad45c --- /dev/null +++ b/Constants.lua @@ -0,0 +1,610 @@ +local GetSpellInfo = GetSpellInfo + +local Gladdy = LibStub("Gladdy") +local L = Gladdy.L +local AURA_TYPE_DEBUFF, AURA_TYPE_BUFF = AURA_TYPE_DEBUFF, AURA_TYPE_BUFF + +function Gladdy:GetSpecBuffs() + return { + -- DRUID + [GetSpellInfo(45283)] = L["Restoration"], -- Natural Perfection + [GetSpellInfo(16880)] = L["Restoration"], -- Nature's Grace; Dreamstate spec in TBC equals Restoration + [GetSpellInfo(24858)] = L["Restoration"], -- Moonkin Form; Dreamstate spec in TBC equals Restoration + [GetSpellInfo(17007)] = L["Feral"], -- Leader of the Pack + [GetSpellInfo(16188)] = L["Restoration"], -- Nature's Swiftness + + -- HUNTER + [GetSpellInfo(34692)] = L["Beast Mastery"], -- The Beast Within + [GetSpellInfo(20895)] = L["Beast Mastery"], -- Spirit Bond + [GetSpellInfo(34455)] = L["Beast Mastery"], -- Ferocious Inspiration + [GetSpellInfo(27066)] = L["Marksmanship"], -- Trueshot Aura + + -- MAGE + [GetSpellInfo(33405)] = L["Frost"], -- Ice Barrier + [GetSpellInfo(11129)] = L["Fire"], -- Combustion + [GetSpellInfo(12042)] = L["Arcane"], -- Arcane Power + [GetSpellInfo(12043)] = L["Arcane"], -- Presence of Mind + [GetSpellInfo(12472)] = L["Frost"], -- Icy Veins + + -- PALADIN + [GetSpellInfo(31836)] = L["Holy"], -- Light's Grace + [GetSpellInfo(31842)] = L["Holy"], -- Divine Illumination + [GetSpellInfo(20216)] = L["Holy"], -- Divine Favor + [GetSpellInfo(20375)] = L["Retribution"], -- Seal of Command + [GetSpellInfo(20049)] = L["Retribution"], -- Vengeance + [GetSpellInfo(20218)] = L["Retribution"], -- Sanctity Aura + + -- PRIEST + [GetSpellInfo(15473)] = L["Shadow"], -- Shadowform + [GetSpellInfo(45234)] = L["Discipline"], -- Focused Will + [GetSpellInfo(27811)] = L["Discipline"], -- Blessed Recovery + [GetSpellInfo(33142)] = L["Holy"], -- Blessed Resilience + [GetSpellInfo(14752)] = L["Discipline"], -- Divine Spirit + [GetSpellInfo(27681)] = L["Discipline"], -- Prayer of Spirit + [GetSpellInfo(10060)] = L["Discipline"], -- Power Infusion + [GetSpellInfo(33206)] = L["Discipline"], -- Pain Suppression + [GetSpellInfo(14893)] = L["Discipline"], -- Inspiration + + -- ROGUE + [GetSpellInfo(36554)] = L["Subtlety"], -- Shadowstep + [GetSpellInfo(44373)] = L["Subtlety"], -- Shadowstep Speed + [GetSpellInfo(36563)] = L["Subtlety"], -- Shadowstep DMG + [GetSpellInfo(14278)] = L["Subtlety"], -- Ghostly Strike + [GetSpellInfo(31233)] = L["Assassination"], -- Find Weakness + + --Shaman + [GetSpellInfo(16190)] = L["Restoration"], -- Mana Tide Totem + [GetSpellInfo(32594)] = L["Restoration"], -- Earth Shield + [GetSpellInfo(30823)] = L["Enhancement"], -- Shamanistic Rage + + -- WARLOCK + [GetSpellInfo(19028)] = L["Demonology"], -- Soul Link + [GetSpellInfo(23759)] = L["Demonology"], -- Master Demonologist + [GetSpellInfo(30302)] = L["Destruction"], -- Nether Protection + [GetSpellInfo(34935)] = L["Destruction"], -- Backlash + + -- WARRIOR + [GetSpellInfo(29838)] = L["Arms"], -- Second Wind + [GetSpellInfo(12292)] = L["Arms"], -- Death Wish + + } +end + +function Gladdy:GetSpecSpells() + return { + -- DRUID + [GetSpellInfo(33831)] = L["Balance"], -- Force of Nature + [GetSpellInfo(33983)] = L["Feral"], -- Mangle (Cat) + [GetSpellInfo(33987)] = L["Feral"], -- Mangle (Bear) + [GetSpellInfo(18562)] = L["Restoration"], -- Swiftmend + [GetSpellInfo(16188)] = L["Restoration"], -- Nature's Swiftness + + -- HUNTER + [GetSpellInfo(19577)] = L["Beast Mastery"], -- Intimidation + [GetSpellInfo(34490)] = L["Marksmanship"], -- Silencing Shot + [GetSpellInfo(27068)] = L["Survival"], -- Wyvern Sting + [GetSpellInfo(19306)] = L["Survival"], -- Counterattack + [GetSpellInfo(27066)] = L["Marksmanship"], -- Trueshot Aura + + -- MAGE + [GetSpellInfo(12042)] = L["Arcane"], -- Arcane Power + [GetSpellInfo(33043)] = L["Fire"], -- Dragon's Breath + [GetSpellInfo(33933)] = L["Fire"], -- Blast Wave + [GetSpellInfo(33405)] = L["Frost"], -- Ice Barrier + [GetSpellInfo(31687)] = L["Frost"], -- Summon Water Elemental + [GetSpellInfo(12472)] = L["Frost"], -- Icy Veins + [GetSpellInfo(11958)] = L["Frost"], -- Cold Snap + + -- PALADIN + [GetSpellInfo(33072)] = L["Holy"], -- Holy Shock + [GetSpellInfo(20216)] = L["Holy"], -- Divine Favor + [GetSpellInfo(31842)] = L["Holy"], -- Divine Illumination + [GetSpellInfo(32700)] = L["Protection"], -- Avenger's Shield + [GetSpellInfo(27170)] = L["Retribution"], -- Seal of Command + [GetSpellInfo(35395)] = L["Retribution"], -- Crusader Strike + [GetSpellInfo(20066)] = L["Retribution"], -- Repentance + [GetSpellInfo(20218)] = L["Retribution"], -- Sanctity Aura + + -- PRIEST + [GetSpellInfo(10060)] = L["Discipline"], -- Power Infusion + [GetSpellInfo(33206)] = L["Discipline"], -- Pain Suppression + [GetSpellInfo(14752)] = L["Discipline"], -- Divine Spirit + [GetSpellInfo(33143)] = L["Holy"], -- Blessed Resilience + [GetSpellInfo(34861)] = L["Holy"], -- Circle of Healing + [GetSpellInfo(15473)] = L["Shadow"], -- Shadowform + [GetSpellInfo(34917)] = L["Shadow"], -- Vampiric Touch + + -- ROGUE + [GetSpellInfo(34413)] = L["Assassination"], -- Mutilate + [GetSpellInfo(14177)] = L["Assassination"], -- Cold Blood + [GetSpellInfo(13750)] = L["Combat"], -- Adrenaline Rush + [GetSpellInfo(14185)] = L["Subtlety"], -- Preparation + [GetSpellInfo(16511)] = L["Subtlety"], -- Hemorrhage + [GetSpellInfo(36554)] = L["Subtlety"], -- Shadowstep + [GetSpellInfo(14278)] = L["Subtlety"], -- Ghostly Strike + [GetSpellInfo(14183)] = L["Subtlety"], -- Premeditation + + -- SHAMAN + [GetSpellInfo(16166)] = L["Elemental"], -- Elemental Mastery + [GetSpellInfo(30823)] = L["Enhancement"], -- Shamanistic Rage + [GetSpellInfo(17364)] = L["Enhancement"], -- Stormstrike + [GetSpellInfo(16190)] = L["Restoration"], -- Mana Tide Totem + [GetSpellInfo(32594)] = L["Restoration"], -- Earth Shield + --[GetSpellInfo(16188)] = L["Restoration"], -- Nature's Swiftness + + -- WARLOCK + [GetSpellInfo(30405)] = L["Affliction"], -- Unstable Affliction + --[GetSpellInfo(30911)] = L["Affliction"], -- Siphon Life + [GetSpellInfo(30414)] = L["Destruction"], -- Shadowfury + + -- WARRIOR + [GetSpellInfo(30330)] = L["Arms"], -- Mortal Strike + [GetSpellInfo(12292)] = L["Arms"], -- Death Wish + [GetSpellInfo(30335)] = L["Fury"], -- Bloodthirst + [GetSpellInfo(12809)] = L["Protection"], -- Concussion Blow + [GetSpellInfo(30022)] = L["Protection"], -- Devastation + } +end + +function Gladdy:GetImportantAuras() + return { + -- Cyclone + [GetSpellInfo(33786)] = { + track = AURA_TYPE_DEBUFF, + duration = 6, + priority = 40, + spellID = 33786, + }, + -- Hibername + [GetSpellInfo(18658)] = { + track = AURA_TYPE_DEBUFF, + duration = 10, + priority = 40, + magic = true, + spellID = 18658, + }, + -- Entangling Roots + [GetSpellInfo(26989)] = { + track = AURA_TYPE_DEBUFF, + duration = 10, + priority = 30, + onDamage = true, + magic = true, + root = true, + spellID = 26989, + }, + -- Feral Charge + [GetSpellInfo(16979)] = { + track = AURA_TYPE_DEBUFF, + duration = 4, + priority = 30, + root = true, + spellID = 16979, + }, + -- Bash + [GetSpellInfo(8983)] = { + track = AURA_TYPE_DEBUFF, + duration = 4, + priority = 30, + spellID = 8983, + }, + -- Pounce + [GetSpellInfo(9005)] = { + track = AURA_TYPE_DEBUFF, + duration = 3, + priority = 40, + spellID = 9005, + }, + -- Maim + [GetSpellInfo(22570)] = { + track = AURA_TYPE_DEBUFF, + duration = 6, + priority = 40, + incapacite = true, + spellID = 22570, + }, + -- Innervate + [GetSpellInfo(29166)] = { + track = AURA_TYPE_BUFF, + duration = 20, + priority = 10, + spellID = 29166, + }, + -- Imp Starfire Stun + [GetSpellInfo(16922)] = { + track = AURA_TYPE_DEBUFF, + duration = 3, + priority = 40, + spellSchool = "physical", + spellID = 16922, + }, + + + -- Freezing Trap Effect + [GetSpellInfo(14309)] = { + track = AURA_TYPE_DEBUFF, + duration = 10, + priority = 40, + onDamage = true, + magic = true, + spellID = 14309, + }, + -- Wyvern Sting + [GetSpellInfo(19386)] = { + track = AURA_TYPE_DEBUFF, + duration = 10, + priority = 40, + onDamage = true, + poison = true, + sleep = true, + spellID = 19386, + }, + -- Scatter Shot + [GetSpellInfo(19503)] = { + track = AURA_TYPE_DEBUFF, + duration = 4, + priority = 40, + onDamage = true, + spellID = 19503, + }, + -- Silencing Shot + [GetSpellInfo(34490)] = { + track = AURA_TYPE_DEBUFF, + duration = 3, + priority = 15, + magic = true, + spellID = 34490, + }, + -- Intimidation + [GetSpellInfo(19577)] = { + track = AURA_TYPE_DEBUFF, + duration = 2, + priority = 40, + spellID = 19577, + }, + -- The Beast Within + [GetSpellInfo(34692)] = { + track = AURA_TYPE_BUFF, + duration = 18, + priority = 20, + spellID = 34692, + }, + + + -- Polymorph + [GetSpellInfo(12826)] = { + track = AURA_TYPE_DEBUFF, + duration = 10, + priority = 40, + onDamage = true, + magic = true, + spellID = 12826, + }, + -- Dragon's Breath + [GetSpellInfo(31661)] = { + track = AURA_TYPE_DEBUFF, + duration = 3, + priority = 40, + onDamage = true, + magic = true, + spellID = 31661, + }, + -- Frost Nova + [GetSpellInfo(27088)] = { + track = AURA_TYPE_DEBUFF, + duration = 8, + priority = 30, + onDamage = true, + magic = true, + root = true, + spellID = 27088, + }, + -- Freeze (Water Elemental) + [GetSpellInfo(33395)] = { + track = AURA_TYPE_DEBUFF, + duration = 8, + priority = 30, + onDamage = true, + magic = true, + root = true, + spellID = 33395, + }, + -- Counterspell - Silence + [GetSpellInfo(18469)] = { + track = AURA_TYPE_DEBUFF, + duration = 4, + priority = 15, + magic = true, + spellID = 18469, + }, + -- Ice Block + [GetSpellInfo(45438)] = { + track = AURA_TYPE_BUFF, + duration = 10, + priority = 20, + spellID = 45438, + }, + -- Impact + [GetSpellInfo(12355)] = { + track = AURA_TYPE_DEBUFF, + duration = 2, + priority = 40, + spellID = 12355, + }, + + -- Hammer of Justice + [GetSpellInfo(10308)] = { + track = AURA_TYPE_DEBUFF, + duration = 6, + priority = 40, + magic = true, + spellID = 10308, + }, + -- Repentance + [GetSpellInfo(20066)] = { + track = AURA_TYPE_DEBUFF, + duration = 6, + priority = 40, + onDamage = true, + magic = true, + incapacite = true, + spellID = 20066, + }, + -- Blessing of Protection + [GetSpellInfo(10278)] = { + track = AURA_TYPE_BUFF, + duration = 10, + priority = 10, + spellID = 10278, + }, + -- Blessing of Freedom + [GetSpellInfo(1044)] = { + track = AURA_TYPE_BUFF, + duration = 14, + priority = 10, + spellID = 1044, + }, + -- Divine Shield + [GetSpellInfo(642)] = { + track = AURA_TYPE_BUFF, + duration = 12, + priority = 20, + spellID = 642, + }, + + + -- Psychic Scream + [GetSpellInfo(8122)] = { + track = AURA_TYPE_DEBUFF, + duration = 8, + priority = 40, + onDamage = true, + fear = true, + magic = true, + spellID = 8122, + }, + -- Chastise + [GetSpellInfo(44047)] = { + track = AURA_TYPE_DEBUFF, + duration = 8, + priority = 30, + root = true, + spellID = 44047, + }, + -- Mind Control + [GetSpellInfo(605)] = { + track = AURA_TYPE_DEBUFF, + duration = 10, + priority = 40, + magic = true, + spellID = 605, + }, + -- Silence + [GetSpellInfo(15487)] = { + track = AURA_TYPE_DEBUFF, + duration = 5, + priority = 15, + magic = true, + spellID = 15487, + }, + -- Pain Suppression + [GetSpellInfo(33206)] = { + track = AURA_TYPE_BUFF, + duration = 8, + priority = 10, + spellID = 33206, + }, + + + -- Sap + [GetSpellInfo(6770)] = { + track = AURA_TYPE_DEBUFF, + duration = 10, + priority = 40, + onDamage = true, + incapacite = true, + spellID = 6770, + }, + -- Blind + [GetSpellInfo(2094)] = { + track = AURA_TYPE_DEBUFF, + duration = 10, + priority = 40, + onDamage = true, + spellID = 2094, + }, + -- Cheap Shot + [GetSpellInfo(1833)] = { + track = AURA_TYPE_DEBUFF, + duration = 4, + priority = 40, + spellID = 1833, + }, + -- Kidney Shot + [GetSpellInfo(8643)] = { + track = AURA_TYPE_DEBUFF, + duration = 6, + priority = 40, + spellID = 8643, + }, + -- Gouge + [GetSpellInfo(1776)] = { + track = AURA_TYPE_DEBUFF, + duration = 4, + priority = 40, + onDamage = true, + incapacite = true, + spellID = 1776, + }, + -- Kick - Silence + [GetSpellInfo(18425)] = { + track = AURA_TYPE_DEBUFF, + duration = 2, + priority = 15, + spellID = 18425, + }, + -- Garrote - Silence + [GetSpellInfo(1330)] = { + track = AURA_TYPE_DEBUFF, + duration = 3, + priority = 15, + spellID = 1330, + }, + -- Cloak of Shadows + [GetSpellInfo(31224)] = { + track = AURA_TYPE_BUFF, + duration = 5, + priority = 20, + spellID = 31224, + }, + + + -- Fear + [GetSpellInfo(5782)] = { + track = AURA_TYPE_DEBUFF, + duration = 10, + priority = 40, + onDamage = true, + fear = true, + magic = true, + spellID = 5782, + }, + -- Death Coil + [GetSpellInfo(27223)] = { + track = AURA_TYPE_DEBUFF, + duration = 3, + priority = 40, + spellID = 27223, + }, + -- Shadowfury + [GetSpellInfo(30283)] = { + track = AURA_TYPE_DEBUFF, + duration = 2, + priority = 40, + magic = true, + spellID = 30283, + }, + -- Seduction (Succubus) + [GetSpellInfo(6358)] = { + track = AURA_TYPE_DEBUFF, + duration = 10, + priority = 40, + onDamage = true, + fear = true, + magic = true, + spellID = 6358, + }, + -- Howl of Terror + [GetSpellInfo(5484)] = { + track = AURA_TYPE_DEBUFF, + duration = 8, + priority = 40, + onDamage = true, + fear = true, + magic = true, + spellID = 5484, + texture = select(3, GetSpellInfo(5484)) + }, + -- Spell Lock (Felhunter) + [GetSpellInfo(24259)] = { + track = AURA_TYPE_DEBUFF, + duration = 3, + priority = 15, + magic = true, + spellID = 24259, + }, + -- Unstable Affliction Silence + ["Unstable Affliction Silence"] = { -- GetSpellInfo returns "Unstable Affliction" + track = AURA_TYPE_DEBUFF, + duration = 5, + priority = 15, + magic = true, + spellID = 31117, + }, + + + -- Intimidating Shout + [GetSpellInfo(5246)] = { + track = AURA_TYPE_DEBUFF, + duration = 8, + priority = 15, + onDamage = true, + fear = true, + spellID = 5246, + }, + -- Concussion Blow + [GetSpellInfo(12809)] = { + track = AURA_TYPE_DEBUFF, + duration = 5, + priority = 40, + spellID = 12809, + }, + -- Intercept Stun + [GetSpellInfo(25274)] = { + track = AURA_TYPE_DEBUFF, + duration = 3, + priority = 40, + spellID = 25274, + }, + -- Spell Reflection + [GetSpellInfo(23920)] = { + track = AURA_TYPE_BUFF, + duration = 5, + priority = 50, + spellID = 23920, + }, + -- Shield Bash - Silenced + [GetSpellInfo(18498)] = { + track = AURA_TYPE_DEBUFF, + duration = 3, + priority = 15, + spellSchool = "magic", + spellID = 18498, + }, + + -- Grounding Totem Effect + [GetSpellInfo(8178)] = { + track = AURA_TYPE_BUFF, + duration = 0, + priority = 20, + spellID = 8178 + }, + + + -- War Stomp + [GetSpellInfo(20549)] = { + track = AURA_TYPE_DEBUFF, + duration = 2, + priority = 40, + spellID = 20549, + }, + -- Arcane Torrent + [GetSpellInfo(28730)] = { + track = AURA_TYPE_DEBUFF, + duration = 2, + priority = 15, + magic = true, + spellID = 28730, + }, + } +end \ No newline at end of file diff --git a/EventListener.lua b/EventListener.lua new file mode 100644 index 0000000..b16a00f --- /dev/null +++ b/EventListener.lua @@ -0,0 +1,251 @@ +local select, string_gsub = select, string.gsub + +local CombatLogGetCurrentEventInfo = CombatLogGetCurrentEventInfo +local RAID_CLASS_COLORS = RAID_CLASS_COLORS +local AURA_TYPE_DEBUFF = AURA_TYPE_DEBUFF +local AURA_TYPE_BUFF = AURA_TYPE_BUFF + +local UnitName, UnitAura, UnitRace, UnitClass, UnitGUID, UnitIsUnit = UnitName, UnitAura, UnitRace, UnitClass, UnitGUID, UnitIsUnit +local UnitCastingInfo, UnitChannelInfo = UnitCastingInfo, UnitChannelInfo +local GetSpellInfo = GetSpellInfo +local FindAuraByName = AuraUtil.FindAuraByName + +local Gladdy = LibStub("Gladdy") +local Cooldowns = Gladdy.modules["Cooldowns"] +local Diminishings = Gladdy.modules["Diminishings"] + +local EventListener = Gladdy:NewModule("EventListener", nil, { + test = true, +}) + +function EventListener:Initialize() + self:RegisterMessage("JOINED_ARENA") +end + +function EventListener.OnEvent(self, event, ...) + EventListener[event](self, ...) +end + +function EventListener:JOINED_ARENA() + self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") + self:RegisterEvent("ARENA_OPPONENT_UPDATE") + self:RegisterEvent("UNIT_AURA") + self:RegisterEvent("UNIT_SPELLCAST_START") + self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START") + self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED") + self:SetScript("OnEvent", EventListener.OnEvent) + Gladdy:SendCommMessage("GladdyVCheck", Gladdy.version, "RAID", UnitName("player")) +end + +function EventListener:Reset() + self:UnregisterAllEvents() + self:SetScript("OnEvent", nil) +end + +function Gladdy:DetectSpec(unit, specSpell) + if specSpell then + self.modules["Cooldowns"]:DetectSpec(unit, specSpell) + end +end + +function Gladdy:SpotEnemy(unit, auraScan) + local button = self.buttons[unit] + button.raceLoc = UnitRace(unit) + button.race = select(2, UnitRace(unit)) + button.classLoc = select(1, UnitClass(unit)) + button.class = select(2, UnitClass(unit)) + button.name = UnitName(unit) + button.stealthed = false + Gladdy.guids[UnitGUID(unit)] = unit + Gladdy:SendMessage("ENEMY_SPOTTED", unit) + if auraScan and not button.spec then + for n = 1, 30 do + local spellName,_,_,_,_,_,unitCaster = UnitAura(unit, n, "HELPFUL") + if ( not spellName ) then + break + end + if Gladdy.specBuffs[spellName] then + local unitPet = string_gsub(unit, "%d$", "pet%1") + if UnitIsUnit(unit, unitCaster) or UnitIsUnit(unitPet, unitCaster) then + Gladdy:DetectSpec(unit, Gladdy.specBuffs[spellName]) + end + end + end + end +end + +function EventListener:COMBAT_LOG_EVENT_UNFILTERED() + -- timestamp,eventType,hideCaster,sourceGUID,sourceName,sourceFlags,sourceRaidFlags,destGUID,destName,destFlags,destRaidFlags,spellId,spellName,spellSchool + local _,eventType,_,sourceGUID,_,_,_,destGUID,_,_,_,spellID,spellName = CombatLogGetCurrentEventInfo() + local srcUnit = Gladdy.guids[sourceGUID] + local destUnit = Gladdy.guids[destGUID] + + if Gladdy.specSpells[spellName] and srcUnit then + --Gladdy:Print(eventType, spellName, Gladdy.specSpells[spellName], srcUnit) + end + if (eventType == "UNIT_DIED" or eventType == "PARTY_KILL" or eventType == "SPELL_INSTAKILL") then + if destUnit then + --Gladdy:Print(eventType, "destUnit", destUnit) + elseif srcUnit then + --Gladdy:Print(eventType, "srcUnit", srcUnit) + end + end + + if destUnit then + -- diminish tracker + if (Gladdy.db.drEnabled and (eventType == "SPELL_AURA_REMOVED" or eventType == "SPELL_AURA_REFRESH")) then + Diminishings:AuraFade(destUnit, spellID) + end + -- death detection + if (eventType == "UNIT_DIED" or eventType == "PARTY_KILL" or eventType == "SPELL_INSTAKILL") then + Gladdy:SendMessage("UNIT_DEATH", destUnit) + end + -- spec detection + if not Gladdy.buttons[destUnit].class then + Gladdy:SpotEnemy(destUnit, true) + end + end + if srcUnit then + -- cooldown tracker + if Gladdy.db.cooldown and Cooldowns.cooldownSpellIds[spellName] then + local unitClass + local spellId = Cooldowns.cooldownSpellIds[spellName] -- don't use spellId from combatlog, in case of different spellrank + if (Cooldowns.cooldownSpells[Gladdy.buttons[srcUnit].class][spellId]) then + unitClass = Gladdy.buttons[srcUnit].class + else + unitClass = Gladdy.buttons[srcUnit].race + end + Cooldowns:CooldownUsed(srcUnit, unitClass, spellId, spellName) + Gladdy:DetectSpec(srcUnit, Gladdy.specSpells[spellName]) + end + + if not Gladdy.buttons[srcUnit].class then + Gladdy:SpotEnemy(srcUnit, true) + end + if not Gladdy.buttons[srcUnit].spec then + Gladdy:DetectSpec(srcUnit, Gladdy.specSpells[spellName]) + end + end +end + +function EventListener:ARENA_OPPONENT_UPDATE(unit, updateReason) + --[[ updateReason: seen, unseen, destroyed, cleared ]] + + local button = Gladdy.buttons[unit] + local pet = Gladdy.modules["Pets"].frames[unit] + if button or pet then + if updateReason == "seen" then + -- ENEMY_SPOTTED + if button and not button.class then + Gladdy:SpotEnemy(unit, true) + end + if button and button.stealthed then + local class = Gladdy.buttons[unit].class + button.healthBar.hp:SetStatusBarColor(RAID_CLASS_COLORS[class].r, RAID_CLASS_COLORS[class].g, RAID_CLASS_COLORS[class].b, 1) + end + if pet then + Gladdy:SendMessage("PET_SPOTTED", unit) + end + elseif updateReason == "unseen" then + -- STEALTH + if button then + Gladdy:SendMessage("ENEMY_STEALTH", unit) + button.healthBar.hp:SetStatusBarColor(0.66, 0.66, 0.66, 1) + button.stealthed = true + end + if pet then + Gladdy:SendMessage("PET_STEALTH", unit) + end + elseif updateReason == "destroyed" then + -- LEAVE + if button then + Gladdy:SendMessage("UNIT_DESTROYED", unit) + end + if pet then + Gladdy:SendMessage("PET_DESTROYED", unit) + end + elseif updateReason == "cleared" then + --Gladdy:Print("ARENA_OPPONENT_UPDATE", updateReason, unit) + end + end +end + +local exceptionNames = { + [31117] = GetSpellInfo(30405) .. " Silence", -- Unstable Affliction Silence + [43523] = GetSpellInfo(30405) .. " Silence", + [24131] = select(1, GetSpellInfo(19386)) .. " Dot", -- Wyvern Sting Dot + [24134] = select(1, GetSpellInfo(19386)) .. " Dot", + [24135] = select(1, GetSpellInfo(19386)) .. " Dot", + [27069] = select(1, GetSpellInfo(19386)) .. " Dot", + [19975] = select(1, GetSpellInfo(27010)) .. " " .. select(1, GetSpellInfo(16689)), -- Entangling Roots Nature's Grasp + [19974] = select(1, GetSpellInfo(27010)) .. " " .. select(1, GetSpellInfo(16689)), + [19973] = select(1, GetSpellInfo(27010)) .. " " .. select(1, GetSpellInfo(16689)), + [19972] = select(1, GetSpellInfo(27010)) .. " " .. select(1, GetSpellInfo(16689)), + [19971] = select(1, GetSpellInfo(27010)) .. " " .. select(1, GetSpellInfo(16689)), + [19971] = select(1, GetSpellInfo(27010)) .. " " .. select(1, GetSpellInfo(16689)), + [27010] = select(1, GetSpellInfo(27010)) .. " " .. select(1, GetSpellInfo(16689)), +} + +function EventListener:UNIT_AURA(unit) + local button = Gladdy.buttons[unit] + if not button then + return + end + for i = 1, 2 do + if not Gladdy.buttons[unit].class then + Gladdy:SpotEnemy(unit, false) + end + local filter = (i == 1 and "HELPFUL" or "HARMFUL") + local auraType = i == 1 and AURA_TYPE_BUFF or AURA_TYPE_DEBUFF + Gladdy:SendMessage("AURA_FADE", unit, auraType) + for n = 1, 30 do + local spellName, texture, count, debuffType, duration, expirationTime, unitCaster, _, shouldConsolidate, spellID = UnitAura(unit, n, filter) + if ( not spellID ) then + Gladdy:SendMessage("AURA_GAIN_LIMIT", unit, auraType, n - 1) + break + end + if not button.spec and Gladdy.specBuffs[spellName] then + local unitPet = string_gsub(unit, "%d$", "pet%1") + if UnitIsUnit(unit, unitCaster) or UnitIsUnit(unitPet, unitCaster) then + Gladdy:DetectSpec(unit, Gladdy.specBuffs[spellName]) + end + end + if exceptionNames[spellID] then + spellName = exceptionNames[spellID] + end + Gladdy:SendMessage("AURA_GAIN", unit, auraType, spellID, spellName, texture, duration, expirationTime, count, debuffType, i) + Gladdy:Call("Announcements", "CheckDrink", unit, spellName) + end + end +end + +function EventListener:UNIT_SPELLCAST_START(unit) + if Gladdy.buttons[unit] then + local spellName = UnitCastingInfo(unit) + if Gladdy.specSpells[spellName] and not Gladdy.buttons[unit].spec then + Gladdy:DetectSpec(unit, Gladdy.specSpells[spellName]) + end + end +end + +function EventListener:UNIT_SPELLCAST_CHANNEL_START(unit) + if Gladdy.buttons[unit] then + local spellName = UnitChannelInfo(unit) + if Gladdy.specSpells[spellName] and not Gladdy.buttons[unit].spec then + Gladdy:DetectSpec(unit, Gladdy.specSpells[spellName]) + end + end +end + +function EventListener:UNIT_SPELLCAST_SUCCEEDED(unit) + if Gladdy.buttons[unit] then + local spellName = UnitCastingInfo(unit) + if Gladdy.specSpells[spellName] and not Gladdy.buttons[unit].spec then + Gladdy:DetectSpec(unit, Gladdy.specSpells[spellName]) + end + end +end + +function EventListener:GetOptions() + return nil +end diff --git a/Frame.lua b/Frame.lua new file mode 100644 index 0000000..bd1cb9a --- /dev/null +++ b/Frame.lua @@ -0,0 +1,287 @@ +local CreateFrame = CreateFrame +local UIParent = UIParent +local InCombatLockdown = InCombatLockdown + +local Gladdy = LibStub("Gladdy") +local L = Gladdy.L + +Gladdy.BUTTON_DEFAULTS = { + name = "", + guid = "", + raceLoc = "", + classLoc = "", + class = "", + health = "", + healthMax = 0, + power = 0, + powerMax = 0, + powerType = 0, + spec = "", + testSpec = "", + spells = {}, + ns = false, + nf = false, + pom = false, + fd = false, + damaged = 0, + click = false, + stealthed = false, +} + +function Gladdy:CreateFrame() + self.frame = CreateFrame("Frame", "GladdyFrame", UIParent) + + self.frame:SetClampedToScreen(true) + self.frame:EnableMouse(true) + self.frame:SetMovable(true) + self.frame:RegisterForDrag("LeftButton") + + self.frame:SetScript("OnDragStart", function(f) + if (not InCombatLockdown() and not self.db.locked) then + f:StartMoving() + end + end) + self.frame:SetScript("OnDragStop", function(f) + if (not InCombatLockdown()) then + f:StopMovingOrSizing() + + local scale = f:GetEffectiveScale() + self.db.x = f:GetLeft() * scale + self.db.y = (self.db.growUp and f:GetBottom() or f:GetTop()) * scale + end + end) + + self.anchor = CreateFrame("Button", "GladdyAnchor", self.frame, BackdropTemplateMixin and "BackdropTemplate") + self.anchor:SetHeight(20) + self.anchor:SetBackdrop({ bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16 }) + self.anchor:SetBackdropColor(0, 0, 0, 1) + self.anchor:SetClampedToScreen(true) + self.anchor:EnableMouse(true) + self.anchor:SetMovable(true) + self.anchor:RegisterForDrag("LeftButton") + self.anchor:RegisterForClicks("RightButtonUp") + self.anchor:SetScript("OnDragStart", function() + if (not InCombatLockdown() and not self.db.locked) then + self.frame:StartMoving() + end + end) + self.anchor:SetScript("OnDragStop", function() + if (not InCombatLockdown()) then + self.frame:StopMovingOrSizing() + + local scale = self.frame:GetEffectiveScale() + self.db.x = self.frame:GetLeft() * scale + self.db.y = (self.db.growUp and self.frame:GetBottom() or self.frame:GetTop()) * scale + end + end) + self.anchor:SetScript("OnClick", function() + if (not InCombatLockdown()) then + self:ShowOptions() + end + end) + + self.anchor.text = self.anchor:CreateFontString("GladdyAnchorText", "ARTWORK", "GameFontHighlightSmall") + self.anchor.text:SetText(L["Gladdy - drag to move"]) + self.anchor.text:SetPoint("CENTER") + + self.anchor.button = CreateFrame("Button", "GladdyAnchorButton", self.anchor, "UIPanelCloseButton") + self.anchor.button:SetWidth(20) + self.anchor.button:SetHeight(20) + self.anchor.button:SetPoint("RIGHT", self.anchor, "RIGHT", 2, 0) + self.anchor.button:SetScript("OnClick", function(_, _, down) + if (not down) then + self.db.locked = true + self:UpdateFrame() + end + end) + + if (self.db.locked) then + self.anchor:Hide() + end + + self.frame:Hide() +end + +function Gladdy:UpdateFrame() + + if (not self.frame) then + self:CreateFrame() + end + local teamSize = self.curBracket or 0 + + local iconSize = self.db.healthBarHeight + local margin = 0 + local width = self.db.barWidth + self.db.padding * 2 + 5 + local height = self.db.healthBarHeight * teamSize + margin * (teamSize - 1) + self.db.padding * 2 + 5 + local extraBarWidth = 0 + local extraBarHeight = 0 + + -- Powerbar + iconSize = iconSize + self.db.powerBarHeight + margin = margin + self.db.powerBarHeight + height = height + self.db.powerBarHeight * teamSize + extraBarHeight = extraBarHeight + self.db.powerBarHeight + + -- Cooldown + margin = margin + 1 + self.db.highlightBorderSize * 2 + 1 -- + 1 space between health and power bar + height = height + self.db.highlightBorderSize * teamSize + + if (self.db.cooldownYPos == "TOP" or self.db.cooldownYPos == "BOTTOM") and self.db.cooldown then + margin = margin + self.db.cooldownSize + height = height + self.db.cooldownSize * teamSize + end + if (self.db.buffsCooldownPos == "TOP" or self.db.buffsCooldownPos == "BOTTOM") and self.db.buffsEnabled then + margin = margin + self.db.buffsIconSize + height = height + self.db.buffsIconSize * teamSize + end + if (self.db.buffsBuffsCooldownPos == "TOP" or self.db.buffsBuffsCooldownPos == "BOTTOM") and self.db.buffsEnabled then + margin = margin + self.db.buffsBuffsIconSize + height = height + self.db.buffsBuffsIconSize * teamSize + end + if self.db.buffsCooldownPos == "TOP" and self.db.cooldownYPos == "TOP" and self.db.cooldown and self.db.buffsEnabled then + margin = margin + 1 + end + if self.db.buffsCooldownPos == "BOTTOM" and self.db.cooldownYPos == "BOTTOM" and self.db.cooldown and self.db.buffsEnabled then + margin = margin + 1 + end + + -- Classicon + width = width + iconSize + extraBarWidth = extraBarWidth + iconSize + + -- Trinket + width = width + iconSize + + self.frame:SetScale(self.db.frameScale) + self.frame:SetWidth(width) + self.frame:SetHeight(height) + --self.frame:SetBackdropColor(self.db.frameColor.r, self.db.frameColor.g, self.db.frameColor.b, self.db.frameColor.a) + self.frame:ClearAllPoints() + if (self.db.x == 0 and self.db.y == 0) then + self.frame:SetPoint("CENTER") + else + local scale = self.frame:GetEffectiveScale() + if (self.db.growUp) then + self.frame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", self.db.x / scale, self.db.y / scale) + else + self.frame:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", self.db.x / scale, self.db.y / scale) + end + end + + self.anchor:SetWidth(width) + self.anchor:ClearAllPoints() + if (self.db.growUp) then + self.anchor:SetPoint("TOPLEFT", self.frame, "BOTTOMLEFT") + else + self.anchor:SetPoint("BOTTOMLEFT", self.frame, "TOPLEFT") + end + + if (self.db.locked) then + self.anchor:Hide() + self.anchor:Hide() + else + self.anchor:Show() + end + + for i = 1, teamSize do + local button = self.buttons["arena" .. i] + button:SetWidth(self.db.barWidth + extraBarWidth) + button:SetHeight(self.db.healthBarHeight) + button.secure:SetWidth(self.db.barWidth + extraBarWidth) + button.secure:SetHeight(self.db.healthBarHeight + extraBarHeight) + + button:ClearAllPoints() + button.secure:ClearAllPoints() + if (self.db.growUp) then + if (i == 1) then + button:SetPoint("BOTTOMLEFT", self.frame, "BOTTOMLEFT", self.db.padding + 2, 0) + button.secure:SetPoint("BOTTOMLEFT", self.frame, "BOTTOMLEFT", self.db.padding + 2, 0) + else + button:SetPoint("BOTTOMLEFT", self.buttons["arena" .. (i - 1)], "TOPLEFT", 0, margin + self.db.bottomMargin) + button.secure:SetPoint("BOTTOMLEFT", self.buttons["arena" .. (i - 1)], "TOPLEFT", 0, margin + self.db.bottomMargin) + end + else + if (i == 1) then + button:SetPoint("TOPLEFT", self.frame, "TOPLEFT", self.db.padding + 2, 0) + button.secure:SetPoint("TOPLEFT", self.frame, "TOPLEFT", self.db.padding + 2, 0) + else + button:SetPoint("TOPLEFT", self.buttons["arena" .. (i - 1)], "BOTTOMLEFT", 0, -margin - self.db.bottomMargin) + button.secure:SetPoint("TOPLEFT", self.buttons["arena" .. (i - 1)], "BOTTOMLEFT", 0, -margin - self.db.bottomMargin) + end + end + + + for k, v in self:IterModules() do + self:Call(v, "UpdateFrame", button.unit) + end + end + for k, v in self:IterModules() do + self:Call(v, "UpdateFrameOnce") + end +end + +function Gladdy:HideFrame() + if (self.frame) then + self.frame:Hide() + self.frame.testing = nil + end +end + +function Gladdy:ToggleFrame(i) + self:Reset() + + if (self.frame and self.frame:IsShown() and i == self.curBracket) then + self:HideFrame() + else + self.curBracket = i + + if (not self.frame) then + self:CreateFrame() + end + + for o = 1, self.curBracket do + local unit = "arena" .. o + if (not self.buttons[unit]) then + self:CreateButton(o) + end + end + self:UpdateFrame() + self:Test() + self.frame:Show() + end +end + +function Gladdy:CreateButton(i) + if (not self.frame) then + self:CreateFrame() + end + + local button = CreateFrame("Frame", "GladdyButtonFrame" .. i, self.frame) + button:SetAlpha(0) + + local secure = CreateFrame("Button", "GladdyButton" .. i, button, "SecureActionButtonTemplate") + secure:RegisterForClicks("AnyUp") + secure:RegisterForClicks("AnyUp") + secure:SetAttribute("*type1", "target") + secure:SetAttribute("*type2", "focus") + secure:SetAttribute("unit", "arena" .. i) + + button:RegisterEvent("UNIT_NAME_UPDATE") + button:RegisterEvent("ARENA_OPPONENT_UPDATE") + button:RegisterEvent("ARENA_COOLDOWNS_UPDATE") + button:RegisterEvent("ARENA_CROWD_CONTROL_SPELL_UPDATE") + button:RegisterUnitEvent("UNIT_CONNECTION", "arena" .. i) + + button.id = i + button.unit = "arena" .. i + button.secure = secure + + + self:ResetButton(button.unit) + + self.buttons[button.unit] = button + + for k, v in self:IterModules() do + self:Call(v, "CreateFrame", button.unit) + end +end \ No newline at end of file diff --git a/Gladdy.lua b/Gladdy.lua new file mode 100644 index 0000000..f4d39cc --- /dev/null +++ b/Gladdy.lua @@ -0,0 +1,388 @@ +local setmetatable = setmetatable +local type = type +local tostring = tostring +local select = select +local pairs = pairs +local tinsert = table.insert +local tsort = table.sort +local CreateFrame = CreateFrame +local DEFAULT_CHAT_FRAME = DEFAULT_CHAT_FRAME +local IsAddOnLoaded = IsAddOnLoaded +local IsInInstance = IsInInstance +local GetBattlefieldStatus = GetBattlefieldStatus +local IsActiveBattlefieldArena = IsActiveBattlefieldArena + +--------------------------- + +-- CORE + +--------------------------- + +local MAJOR, MINOR = "Gladdy", 4 +local Gladdy = LibStub:NewLibrary(MAJOR, MINOR) +local L +Gladdy.version_major = "TBC-Classic_v1" +Gladdy.version_minor = "0.3-Beta" +Gladdy.version = Gladdy.version_major .. "." .. Gladdy.version_minor + +LibStub("AceTimer-3.0"):Embed(Gladdy) +LibStub("AceComm-3.0"):Embed(Gladdy) +Gladdy.modules = {} +setmetatable(Gladdy, { + __tostring = function() + return MAJOR + end +}) + +function Gladdy:Print(...) + local text = "|cff0384fcGladdy|r:" + local val + for i = 1, select("#", ...) do + val = select(i, ...) + if (type(val) == 'boolean') then val = val and "true" or false end + text = text .. " " .. tostring(val) + end + DEFAULT_CHAT_FRAME:AddMessage(text) +end + +function Gladdy:Warn(...) + local text = "|cfffc0303Gladdy|r:" + local val + for i = 1, select("#", ...) do + val = select(i, ...) + if (type(val) == 'boolean') then val = val and "true" or false end + text = text .. " " .. tostring(val) + end + DEFAULT_CHAT_FRAME:AddMessage(text) +end + +Gladdy.events = CreateFrame("Frame") +Gladdy.events.registered = {} +Gladdy.events:RegisterEvent("PLAYER_LOGIN") +Gladdy.events:SetScript("OnEvent", function(self, event, ...) + if (event == "PLAYER_LOGIN") then + Gladdy:OnInitialize() + Gladdy:OnEnable() + else + local func = self.registered[event] + + if (type(Gladdy[func]) == "function") then + Gladdy[func](Gladdy, event, ...) + end + end +end) + +function Gladdy:RegisterEvent(event, func) + self.events.registered[event] = func or event + self.events:RegisterEvent(event) +end +function Gladdy:UnregisterEvent(event) + self.events.registered[event] = nil + self.events:UnregisterEvent(event) +end +function Gladdy:UnregisterAllEvents() + self.events.registered = {} + self.events:UnregisterAllEvents() +end + +--------------------------- + +-- MODULE FUNCTIONS + +--------------------------- + +local function pairsByPrio(t) + local a = {} + for k, v in pairs(t) do + tinsert(a, { k, v.priority }) + end + tsort(a, function(x, y) + return x[2] > y[2] + end) + + local i = 0 + return function() + i = i + 1 + + if (a[i] ~= nil) then + return a[i][1], t[a[i][1]] + else + return nil + end + end +end +function Gladdy:IterModules() + return pairsByPrio(self.modules) +end + +function Gladdy:Call(module, func, ...) + if (type(module) == "string") then + module = self.modules[module] + end + + if (type(module[func]) == "function") then + module[func](module, ...) + end +end +function Gladdy:SendMessage(message, ...) + for k, v in self:IterModules() do + self:Call(v, v.messages[message], ...) + end +end + +function Gladdy:NewModule(name, priority, defaults) + local module = CreateFrame("Frame") + module.name = name + module.priority = priority or 0 + module.defaults = defaults or {} + module.messages = {} + + module.RegisterMessage = function(self, message, func) + self.messages[message] = func or message + end + + module.GetOptions = function() + return nil + end + + for k, v in pairs(module.defaults) do + self.defaults.profile[k] = v + end + + self.modules[name] = module + + return module +end + +--------------------------- + +-- INIT + +--------------------------- + +function Gladdy:OnInitialize() + self.dbi = LibStub("AceDB-3.0"):New("GladdyXZ", self.defaults) + self.dbi.RegisterCallback(self, "OnProfileChanged", "OnProfileChanged") + self.dbi.RegisterCallback(self, "OnProfileCopied", "OnProfileChanged") + self.dbi.RegisterCallback(self, "OnProfileReset", "OnProfileChanged") + self.db = self.dbi.profile + + self.LSM = LibStub("LibSharedMedia-3.0") + self.LSM:Register("statusbar", "Gloss", "Interface\\AddOns\\Gladdy\\Images\\Gloss") + self.LSM:Register("statusbar", "Smooth", "Interface\\AddOns\\Gladdy\\Images\\Smooth") + self.LSM:Register("statusbar", "Minimalist", "Interface\\AddOns\\Gladdy\\Images\\Minimalist") + self.LSM:Register("statusbar", "LiteStep", "Interface\\AddOns\\Gladdy\\Images\\LiteStep.tga") + self.LSM:Register("border", "Gladdy Tooltip round", "Interface\\AddOns\\Gladdy\\Images\\UI-Tooltip-Border_round_selfmade") + self.LSM:Register("border", "Gladdy Tooltip squared", "Interface\\AddOns\\Gladdy\\Images\\UI-Tooltip-Border_square_selfmade") + self.LSM:Register("font", "DorisPP", "Interface\\AddOns\\Gladdy\\Images\\DorisPP.TTF") + + L = self.L + + self.testData = { + ["arena1"] = { name = "Swift", raceLoc = L["Tauren"], classLoc = L["Warrior"], class = "WARRIOR", health = 9635, healthMax = 14207, power = 76, powerMax = 100, powerType = 1, testSpec = L["Arms"], race = "Tauren" }, + ["arena2"] = { name = "Vilden", raceLoc = L["Undead"], classLoc = L["Mage"], class = "MAGE", health = 10969, healthMax = 11023, power = 7833, powerMax = 10460, powerType = 0, testSpec = L["Frost"], race = "Scourge" }, + ["arena3"] = { name = "Krymu", raceLoc = L["Human"], classLoc = L["Rogue"], class = "ROGUE", health = 1592, healthMax = 11740, power = 45, powerMax = 110, powerType = 3, testSpec = L["Subtlety"], race = "Human" }, + ["arena4"] = { name = "Talmon", raceLoc = L["Human"], classLoc = L["Warlock"], class = "WARLOCK", health = 10221, healthMax = 14960, power = 9855, powerMax = 9855, powerType = 0, testSpec = L["Demonology"], race = "Human" }, + ["arena5"] = { name = "Hydra", raceLoc = L["Undead"], classLoc = L["Priest"], class = "PRIEST", health = 11960, healthMax = 11960, power = 2515, powerMax = 10240, powerType = 0, testSpec = L["Discipline"], race = "Human" }, + } + + self.cooldownSpellIds = {} + self.spellTextures = {} + self.specBuffs = self:GetSpecBuffs() + self.specSpells = self:GetSpecSpells() + self.buttons = {} + self.guids = {} + self.curBracket = nil + self.curUnit = 1 + self.lastInstance = nil + + self:SetupOptions() + + for k, v in self:IterModules() do + self:Call(v, "Initialize") -- B.E > A.E :D + end +end + +function Gladdy:OnProfileChanged() + self.db = self.dbi.profile + + self:HideFrame() + self:ToggleFrame(3) +end + +function Gladdy:OnEnable() + self:RegisterEvent("UPDATE_BATTLEFIELD_STATUS") + self:RegisterEvent("PLAYER_ENTERING_WORLD") + + if (IsAddOnLoaded("Clique")) then + for i = 1, 5 do + self:CreateButton(i) + end + + ClickCastFrames = ClickCastFrames or {} + ClickCastFrames[self.buttons.arena1.secure] = true + ClickCastFrames[self.buttons.arena2.secure] = true + ClickCastFrames[self.buttons.arena3.secure] = true + ClickCastFrames[self.buttons.arena4.secure] = true + ClickCastFrames[self.buttons.arena5.secure] = true + end + + if (not self.db.locked and self.db.x == 0 and self.db.y == 0) then + self:Print(L["Welcome to Gladdy!"]) + self:Print(L["First run has been detected, displaying test frame."]) + self:Print(L["Valid slash commands are:"]) + self:Print(L["/gladdy ui"]) + self:Print(L["/gladdy test2-5"]) + self:Print(L["/gladdy hide"]) + self:Print(L["/gladdy reset"]) + self:Print(L["If this is not your first run please lock or move the frame to prevent this from happening."]) + + self:HideFrame() + self:ToggleFrame(3) + end +end + +function Gladdy:GetIconStyles() + return + { + ["Interface\\AddOns\\Gladdy\\Images\\Border_rounded_blp"] = L["Gladdy Tooltip round"], + ["Interface\\AddOns\\Gladdy\\Images\\Border_squared_blp"] = L["Gladdy Tooltip squared"], + ["Interface\\AddOns\\Gladdy\\Images\\Border_Gloss"] = L["Gloss (black border)"], + } +end + +--------------------------- + +-- TEST + +--------------------------- + +function Gladdy:Test() + Gladdy.frame.testing = true + for i = 1, self.curBracket do + local unit = "arena" .. i + if (not self.buttons[unit]) then + self:CreateButton(i) + end + local button = self.buttons[unit] + + for k, v in pairs(self.testData[unit]) do + button[k] = v + end + + for k, v in self:IterModules() do + self:Call(v, "Test", unit) + end + + button:SetAlpha(1) + end +end + +--------------------------- + +-- EVENT HANDLING + +--------------------------- + +function Gladdy:PLAYER_ENTERING_WORLD() + local instance = select(2, IsInInstance()) + if (instance ~= "arena" and self.frame and self.frame:IsVisible() and not self.frame.testing) then + self:Reset() + self:HideFrame() + end + if (instance == "arena") then + self:Reset() + self:HideFrame() + end + self.lastInstance = instance +end + +function Gladdy:UPDATE_BATTLEFIELD_STATUS(_, index) + local status, mapName, instanceID, levelRangeMin, levelRangeMax, teamSize, isRankedArena, suspendedQueue, bool, queueType = GetBattlefieldStatus(index) + if (status == "active" and teamSize > 0 and IsActiveBattlefieldArena()) then + self.curBracket = teamSize + self:JoinedArena() + end +end + +--------------------------- + +-- RESET FUNCTIONS (ARENA LEAVE) + +--------------------------- + +function Gladdy:Reset() + if type(self.guids) == "table" then + for k, v in pairs(self.guids) do + self.guids[k] = nil + end + end + self.guids = {} + self.curBracket = nil + self.curUnit = 1 + + for k1, v1 in self:IterModules() do + self:Call(v1, "Reset") + end + + for unit in pairs(self.buttons) do + self:ResetUnit(unit) + end +end + +function Gladdy:ResetUnit(unit) + local button = self.buttons[unit] + if (not button) then + return + end + + button:SetAlpha(0) + self:ResetButton(unit) + + for k2, v2 in self:IterModules() do + self:Call(v2, "ResetUnit", unit) + end +end + +function Gladdy:ResetButton(unit) + local button = self.buttons[unit] + if (not button) then + return + end + for k1, v1 in pairs(self.BUTTON_DEFAULTS) do + if (type(v1) == "string") then + button[k1] = nil + elseif (type(v1) == "number") then + button[k1] = 0 + elseif (type(v1) == "array") then + button[k1] = {} + elseif (type(v1) == "boolean") then + button[k1] = false + end + end +end + +--------------------------- + +-- ARENA JOINED + +--------------------------- + +function Gladdy:JoinedArena() + if not self.curBracket then + self.curBracket = 2 + end + + for i = 1, self.curBracket do + if (not self.buttons["arena" .. i]) then + self:CreateButton(i) + end + end + + self:SendMessage("JOINED_ARENA") + self:UpdateFrame() + self.frame:Show() + for i=1, self.curBracket do + self.buttons["arena" .. i]:SetAlpha(1) + end +end diff --git a/Gladdy.toc b/Gladdy.toc new file mode 100644 index 0000000..ca10f3f --- /dev/null +++ b/Gladdy.toc @@ -0,0 +1,35 @@ +## Interface: 20501 +## Title: Gladdy - Macumba/XiCoN Edit +## Version: 1.0.3-Beta +## Notes: The most powerful arena AddOn for WoW 2.5.1 +## Author: XiconQoo +## X-Email: +## SavedVariables: GladdyXZ +## OptionalDeps: SharedMedia, Blizzard_CombatLog, Blizzard_ArenaUI, Blizzard_CombatText + +embeds.xml + +Gladdy.lua +Lang.lua +Frame.lua +Options.lua +Constants.lua + +Modules\Announcements.lua +Modules\Healthbar.lua +Modules\Powerbar.lua +Modules\Auras.lua +Modules\Castbar.lua +Modules\Classicon.lua +Modules\Diminishings.lua +Modules\Highlight.lua +Modules\TotemPlates.lua +Modules\Trinket.lua +Modules\Cooldowns.lua +Modules\ArenaCountDown.lua +Modules\BuffsDebuffs.lua +Modules\VersionCheck.lua +Modules\XiconProfiles.lua +Modules\Pets.lua +Modules\ExportImport.lua +EventListener.lua diff --git a/Images/BasicProfiles/Classic1.blp b/Images/BasicProfiles/Classic1.blp new file mode 100644 index 0000000..6b85095 Binary files /dev/null and b/Images/BasicProfiles/Classic1.blp differ diff --git a/Images/BasicProfiles/Klimp1.blp b/Images/BasicProfiles/Klimp1.blp new file mode 100644 index 0000000..041524b Binary files /dev/null and b/Images/BasicProfiles/Klimp1.blp differ diff --git a/Images/BasicProfiles/Knall1.blp b/Images/BasicProfiles/Knall1.blp new file mode 100644 index 0000000..de381f1 Binary files /dev/null and b/Images/BasicProfiles/Knall1.blp differ diff --git a/Images/Border_Gloss.tga b/Images/Border_Gloss.tga new file mode 100644 index 0000000..292e9f0 Binary files /dev/null and b/Images/Border_Gloss.tga differ diff --git a/Images/Border_rounded_blp.blp b/Images/Border_rounded_blp.blp new file mode 100644 index 0000000..fb5aebb Binary files /dev/null and b/Images/Border_rounded_blp.blp differ diff --git a/Images/Border_squared_blp.blp b/Images/Border_squared_blp.blp new file mode 100644 index 0000000..035061f Binary files /dev/null and b/Images/Border_squared_blp.blp differ diff --git a/Images/Classes/INV_Hammer_01.blp b/Images/Classes/INV_Hammer_01.blp new file mode 100644 index 0000000..3f73ae7 Binary files /dev/null and b/Images/Classes/INV_Hammer_01.blp differ diff --git a/Images/Classes/INV_Jewelry_Talisman_04.blp b/Images/Classes/INV_Jewelry_Talisman_04.blp new file mode 100644 index 0000000..a0dd70e Binary files /dev/null and b/Images/Classes/INV_Jewelry_Talisman_04.blp differ diff --git a/Images/Classes/INV_Misc_MonsterClaw_04.blp b/Images/Classes/INV_Misc_MonsterClaw_04.blp new file mode 100644 index 0000000..45257da Binary files /dev/null and b/Images/Classes/INV_Misc_MonsterClaw_04.blp differ diff --git a/Images/Classes/INV_Staff_13.blp b/Images/Classes/INV_Staff_13.blp new file mode 100644 index 0000000..e1ea422 Binary files /dev/null and b/Images/Classes/INV_Staff_13.blp differ diff --git a/Images/Classes/INV_Staff_30.blp b/Images/Classes/INV_Staff_30.blp new file mode 100644 index 0000000..d3591b3 Binary files /dev/null and b/Images/Classes/INV_Staff_30.blp differ diff --git a/Images/Classes/INV_Sword_27.blp b/Images/Classes/INV_Sword_27.blp new file mode 100644 index 0000000..7305323 Binary files /dev/null and b/Images/Classes/INV_Sword_27.blp differ diff --git a/Images/Classes/INV_ThrowingKnife_04.blp b/Images/Classes/INV_ThrowingKnife_04.blp new file mode 100644 index 0000000..51ba123 Binary files /dev/null and b/Images/Classes/INV_ThrowingKnife_04.blp differ diff --git a/Images/Classes/INV_Weapon_Bow_07.blp b/Images/Classes/INV_Weapon_Bow_07.blp new file mode 100644 index 0000000..283aead Binary files /dev/null and b/Images/Classes/INV_Weapon_Bow_07.blp differ diff --git a/Images/Classes/Spell_Nature_Drowsy.blp b/Images/Classes/Spell_Nature_Drowsy.blp new file mode 100644 index 0000000..355c6dd Binary files /dev/null and b/Images/Classes/Spell_Nature_Drowsy.blp differ diff --git a/Images/Countdown/0.blp b/Images/Countdown/0.blp new file mode 100644 index 0000000..d8ad777 Binary files /dev/null and b/Images/Countdown/0.blp differ diff --git a/Images/Countdown/1.blp b/Images/Countdown/1.blp new file mode 100644 index 0000000..849c799 Binary files /dev/null and b/Images/Countdown/1.blp differ diff --git a/Images/Countdown/2.blp b/Images/Countdown/2.blp new file mode 100644 index 0000000..b74cce1 Binary files /dev/null and b/Images/Countdown/2.blp differ diff --git a/Images/Countdown/3.blp b/Images/Countdown/3.blp new file mode 100644 index 0000000..c4157cb Binary files /dev/null and b/Images/Countdown/3.blp differ diff --git a/Images/Countdown/4.blp b/Images/Countdown/4.blp new file mode 100644 index 0000000..6480f0d Binary files /dev/null and b/Images/Countdown/4.blp differ diff --git a/Images/Countdown/5.blp b/Images/Countdown/5.blp new file mode 100644 index 0000000..4cfac61 Binary files /dev/null and b/Images/Countdown/5.blp differ diff --git a/Images/Countdown/6.blp b/Images/Countdown/6.blp new file mode 100644 index 0000000..4d34be0 Binary files /dev/null and b/Images/Countdown/6.blp differ diff --git a/Images/Countdown/7.blp b/Images/Countdown/7.blp new file mode 100644 index 0000000..4293f83 Binary files /dev/null and b/Images/Countdown/7.blp differ diff --git a/Images/Countdown/8.blp b/Images/Countdown/8.blp new file mode 100644 index 0000000..fb4c555 Binary files /dev/null and b/Images/Countdown/8.blp differ diff --git a/Images/Countdown/9.blp b/Images/Countdown/9.blp new file mode 100644 index 0000000..7a4bbb9 Binary files /dev/null and b/Images/Countdown/9.blp differ diff --git a/Images/DorisPP.TTF b/Images/DorisPP.TTF new file mode 100644 index 0000000..060f1d6 Binary files /dev/null and b/Images/DorisPP.TTF differ diff --git a/Images/Gloss.tga b/Images/Gloss.tga new file mode 100644 index 0000000..8a1dd5b Binary files /dev/null and b/Images/Gloss.tga differ diff --git a/Images/LiteStep.tga b/Images/LiteStep.tga new file mode 100644 index 0000000..488c265 Binary files /dev/null and b/Images/LiteStep.tga differ diff --git a/Images/Minimalist.tga b/Images/Minimalist.tga new file mode 100644 index 0000000..030bc83 Binary files /dev/null and b/Images/Minimalist.tga differ diff --git a/Images/Smooth.tga b/Images/Smooth.tga new file mode 100644 index 0000000..9ad81ad Binary files /dev/null and b/Images/Smooth.tga differ diff --git a/Images/Totems/Spell_Nature_InvisibilityTotem_edit.blp b/Images/Totems/Spell_Nature_InvisibilityTotem_edit.blp new file mode 100644 index 0000000..673a1b4 Binary files /dev/null and b/Images/Totems/Spell_Nature_InvisibilityTotem_edit.blp differ diff --git a/Images/Totems/Spell_Nature_ManaRegenTotem_edit.blp b/Images/Totems/Spell_Nature_ManaRegenTotem_edit.blp new file mode 100644 index 0000000..abc5a39 Binary files /dev/null and b/Images/Totems/Spell_Nature_ManaRegenTotem_edit.blp differ diff --git a/Images/Totems/Spell_Nature_RemoveCurse_edit.blp b/Images/Totems/Spell_Nature_RemoveCurse_edit.blp new file mode 100644 index 0000000..c1eaa3f Binary files /dev/null and b/Images/Totems/Spell_Nature_RemoveCurse_edit.blp differ diff --git a/Images/Totems/Spell_Nature_SlowingTotem_edit.blp b/Images/Totems/Spell_Nature_SlowingTotem_edit.blp new file mode 100644 index 0000000..4b9b8b1 Binary files /dev/null and b/Images/Totems/Spell_Nature_SlowingTotem_edit.blp differ diff --git a/Images/Totems/Spell_Nature_Windfury_edit.blp b/Images/Totems/Spell_Nature_Windfury_edit.blp new file mode 100644 index 0000000..5fc8a05 Binary files /dev/null and b/Images/Totems/Spell_Nature_Windfury_edit.blp differ diff --git a/Images/UI-Tooltip-Border_round_selfmade.blp b/Images/UI-Tooltip-Border_round_selfmade.blp new file mode 100644 index 0000000..cc5a7ad Binary files /dev/null and b/Images/UI-Tooltip-Border_round_selfmade.blp differ diff --git a/Images/UI-Tooltip-Border_square_selfmade.blp b/Images/UI-Tooltip-Border_square_selfmade.blp new file mode 100644 index 0000000..ce034e5 Binary files /dev/null and b/Images/UI-Tooltip-Border_square_selfmade.blp differ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1b8a5cd --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + This program 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 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. \ No newline at end of file diff --git a/Lang.lua b/Lang.lua new file mode 100644 index 0000000..887083b --- /dev/null +++ b/Lang.lua @@ -0,0 +1,480 @@ +local setmetatable = setmetatable + +local GetLocale = GetLocale + +local L = {} + +if (GetLocale() == "ruRU") then + -- Races + L["Human"] = "Человек" + L["Dwarf"] = "Дворф" + L["Night Elf"] = "Ночной эльф" + L["Gnome"] = "Гном" + L["Draenei"] = "Дреней" + L["Orc"] = "Орк" + L["Undead"] = "Нежить" + L["Tauren"] = "Таурен" + L["Troll"] = "Тролль" + L["Blood Elf"] = "Эльф крови" + + -- Classes + L["Druid"] = "Друид" + L["Hunter"] = "Охотник" + L["Mage"] = "Маг" + L["Paladin"] = "Паладин" + L["Priest"] = "Жрец" + L["Rogue"] = "Разбойник" + L["Shaman"] = "Шаман" + L["Warlock"] = "Чернокнижник" + L["Warrior"] = "Воин" + + -- Specs + L["Balance"] = "Баланс" + L["Feral"] = "Сила зверя" + L["Restoration"] = "Исцеление" + L["Beast Mastery"] = "Повелитель зверей" + L["Marksmanship"] = "Стрельба" + L["Survival"] = "Выживание" + L["Arcane"] = "Тайная магия" + L["Fire"] = "Огонь" + L["Frost"] = "Лед" + L["Holy"] = "Свет" + L["Protection"] = "Защита" + L["Retribution"] = "Возмездие" + L["Discipline"] = "Послушание" + L["Shadow"] = "Тьма" + L["Assassination"] = "Ликвидация" + L["Combat"] = "Бой" + L["Subtlety"] = "Скрытность" + L["Elemental"] = "Cтихии" + L["Enhancement"] = "Совершенствование" + L["Affliction"] = "Колдовство" + L["Demonology"] = "Демонология" + L["Destruction"] = "Разрушение" + L["Arms"] = "Оружие" + L["Fury"] = "Неистовство" + + -- Gladdy.lua + L["Welcome to Gladdy!"] = "Вас приветствует Gladdy!" + L["First run has been detected, displaying test frame."] = "Обнаружен первый запуск, показываем тестовое окно." + L["Valid slash commands are:"] = "Валидные команды:" + L["If this is not your first run please lock or move the frame to prevent this from happening."] = "Если это не первый запуск, переместите, либо закрепите окно во избежание показа окна." + + -- Frame.lua + L["Gladdy - drag to move"] = "Gladdy - тащите для перемещения" + + -- Options.lua + L["Announcements"] = "Оповещения" + L["Announcement settings"] = "Настройки оповещения" + L["Auras"] = "Ауры" + L["Auras settings"] = "Настройки аур" + L["Castbar"] = "Полоса применения" + L["Castbar settings"] = "Настройки полосы применения" + L["Classicon"] = "Иконка класса" + L["Classicon settings"] = "Настройки иконки класса" + L["Clicks"] = "Клики" + L["Clicks settings"] = "Настройки кликов" + L["Diminishings"] = "Диминишинги" + L["Diminishings settings"] = "Настройки диминишингов" + L["Healthbar"] = "Полоса жизней" + L["Healthbar settings"] = "Настройки полосы жизней" + L["Highlight"] = "Подсветка" + L["Highlight settings"] = "Настройки подсветки" + L["Nameplates"] = "Индикаторы здоровья" + L["Nameplates settings"] = "Настройки индикаторов здоровья " + L["Powerbar"] = "Полоса маны" + L["Powerbar settings"] = "Настройки полосы маны" + L["Score"] = "Счет" + L["Score settings"] = "Настройки счета" + L["Trinket"] = "Тринкет" + L["Trinket settings"] = "Настройки тринкета" + L["Reset module"] = "Сбросить настройки" + L["Reset module to defaults"] = "Сбросить настройки модуля к начальным" + L["No settings"] = "Нет настроек" + L["Module has no settings"] = "Модуль не имеет настроек" + L["General"] = "Основные" + L["General settings"] = "Основные настройки" + L["Lock frame"] = "Закрепить фрейм" + L["Toggle if frame can be moved"] = "Включите, если фрейм можно двигать" + L["Grow frame upwards"] = "Расти вверх" + L["If enabled the frame will grow upwards instead of downwards"] = "Если включено, то фрейм будет расти вверх, а не вниз" + L["Frame scale"] = "Масштаб фрейма" + L["Scale of the frame"] = "Масштаб фрейма" + L["Frame padding"] = "Отступы фрейма" + L["Padding of the frame"] = "Отступы фрейма" + L["Frame color"] = "Цвет фрейма" + L["Color of the frame"] = "Цвет фрейма" + L["Bar width"] = "Ширина полос" + L["Width of the bars"] = "Ширина полос" + L["Bottom margin"] = "Нижняя граница полосы" + L["Margin between each button"] = "Отступ до следующей полосы" + + -- Announcements.lua + L["RESURRECTING: %s (%s)"] = "ВОСКРЕШАЕТ: %s (%s)" + L["SPEC DETECTED: %s - %s (%s)"] = "СПЕЦИАЛИЗАЦИЯ ОПРЕДЕЛЕНА: %s - %s (%s)" + L["LOW HEALTH: %s (%s)"] = "МАЛО ЗДОРОВЬЯ: %s (%s)" + L["TRINKET USED: %s (%s)"] = "ТРИНКЕТ ИСПОЛЬЗОВАН: %s (%s)" + L["TRINKET READY: %s (%s)"] = "ТРИНКЕТ ГОТОВ: %s (%s)" + L["DRINKING: %s (%s)"] = "ПЬЁТ: %s (%s)" + L["Self"] = "Сам" + L["Party"] = "Группа" + L["Raid Warning"] = "Объявление рейду" + L["Blizzard's Floating Combat Text"] = "Стандартный текст боя" + L["MikScrollingBattleText"] = "MikScrollingBattleText" + L["Scrolling Combat Text"] = "Scrolling Combat Text" + L["Parrot"] = "Parrot" + L["Drinking"] = "Питьё" + L["Announces when enemies sit down to drink"] = "Оповещать, когда вражеский игрок начинает пить" + L["Resurrection"] = "Воскрешение" + L["Announces when an enemy tries to resurrect a teammate"] = "Оповещать, когда вражеский игрок начинает воскрешать союзника" + L["New enemies"] = "Новые враги" + L["Announces when new enemies are discovered"] = "Оповещать о найденных вражеских игроках" + L["Spec Detection"] = "Обнаружение специализации" + L["Announces when the spec of an enemy was detected"] = "Оповещать, когда обнаружена специализация вражеского игрока" + L["Low health"] = "Мало жизней" + L["Announces when an enemy drops below a certain health threshold"] = "Оповещать, когда уровень здоровья вражеского игрока падает ниже определенного количества" + L["Low health threshold"] = "Процент малого количества здоровья" + L["Choose how low an enemy must be before low health is announced"] = "Укажите процент здоровья вражеского игрока, когда нужно показать оповещение" + L["Trinket used"] = "Использование пвп-тринкета" + L["Announce when an enemy's trinket is used"] = "Оповещать об использовании пвп-тринкета вражеским игроком" + L["Trinket ready"] = "Готовность пвп-тринкета" + L["Announce when an enemy's trinket is ready again"] = "Оповещать, когда пвп-тринкет вражеского игрока готов" + L["Destination"] = "Вариант оповещений" + L["Choose how your announcements are displayed"] = "Выберать, как показывать оповещения" + + -- Auras.lua + L["Font color"] = "Цвет текста" + L["Color of the text"] = "Цвет текста" + L["Font size"] = "Размер текста" + L["Size of the text"] = "Размер текста" + + -- Castbar.lua + L["Bar height"] = "Высота полосы" + L["Height of the bar"] = "Высота полосы" + L["Bar texture"] = "Текстура полосы" + L["Texture of the bar"] = "Текстура полосы" + L["Bar color"] = "Цвет полосы" + L["Color of the cast bar"] = "Цвет полосы применений" + L["Background color"] = "Цвет фона полосы" + L["Color of the cast bar background"] = "Цвет фона полосы применений" + L["Icon position"] "Расположение значка трансляции" + + -- Clicks.lua + L["Action #%d"] = "Действие #%d" + L["Left Click Enemy 1"] = "Левый клик по цели 1" + L["Left Click Enemy 2"] = "Левый клик по цели 2" + L["Left Click Enemy 3"] = "Левый клик по цели 3" + L["Left Click Enemy 4"] = "Левый клик по цели 4" + L["Left Click Enemy 5"] = "Левый клик по цели 5" + L["Right Click Enemy 1"] = "Правый клик по цели 1" + L["Right Click Enemy 2"] = "Правый клик по цели 2" + L["Right Click Enemy 3"] = "Правый клик по цели 3" + L["Right Click Enemy 4"] = "Правый клик по цели 4" + L["Right Click Enemy 5"] = "Правый клик по цели 5" + L["Left button"] = "Левая кнопка" + L["Right button"] = "Правая кнопка" + L["Middle button"] = "Средняя кнопка" + L["Button 4"] = "Кнопка 4" + L["Button 5"] = "Кнопка 5" + L["None"] = "Не назначено" + L["CTRL"] = "CTRL" + L["SHIFT"] = "SHIFT" + L["ALT"] = "ALT" + L["Cast Spell"] = "Применить заклинание" + L["Name"] = "Название" + L["Select the name of the click option"] = "Выбрать название опции клика" + L["Button"] = "Кнопка" + L["Select which mouse button to use"] = "Выбрать кнопку мыши для использования" + L["Modifier"] = "Модификатор" + L["Select which modifier to use"] = "Выбрать модификатор для использования" + L["Action"] = "Действите" + L["Select what action this mouse button does"] = "Выбрать действие, производимое данной кнопкой мыши" + L["Spell name / Macro text"] = "Название заклинания / Текст макроса" + L["Use *name* as unit's name. Like a '/rofl *name*'"] = "Используйте *name* в качестве имени игрока. Например, '/rofl *name*'" + + -- Diminishings.lua + L["DR Cooldown position"] = "Позиция ДР таймеров" + L["Position of the cooldown icons"] = "Позиция ДР таймеров" + L["Left"] = "Слева" + L["Right"] = "Справа" + L["Icon Size"] = "Размер иконок" + L["Size of the DR Icons"] = "Размер ДР иконок" + + -- Healthbar.lua + L["Show the actual health"] = "Показывать текущее здоровье" + L["Show the actual health on the health bar"] = "Показывать текущее здоровье на полосе жизней" + L["Show max health"] = "Показывать максимальное здоровье" + L["Show max health on the health bar"] = "Показывать максимальное здоровье на полосе жизней" + L["Show health percentage"] = "Показывать здоровье в процентах" + L["Show health percentage on the health bar"] = "Показывать здоровье в процентах на полосе жизней" + + -- Highlight.lua + L["Border size"] = "Размер границы" + L["Target border color"] = "Цвет контура цели" + L["Color of the selected targets border"] = "Цвет контура цели" + L["Focus border color"] = "Цвет контура фокуса" + L["Color of the focus border"] = "Цвет контура фокуса" + L["Raid leader border color"] = "Цвет контура цели рейд лидера" + L["Color of the raid leader border"] = "Цвет контура цели рейд лидера" + L["Highlight target"] = "Подсвечивать цель" + L["Toggle if the selected target should be highlighted"] = "Включите, если необходима подсветка цели" + L["Show border around target"] = "Показывать контур вокруг цели" + L["Toggle if a border should be shown around the selected target"] = "Включите, если необходимо показывать контур вокруг цели" + L["Show border around focus"] = "Показывать контур вокруг фокуса" + L["Toggle of a border should be shown around the current focus"] = "Включите, если необходимо показывать контур вокруг фокуса" + L["Show border around raid leader"] = "Показывать контур вокруг цели рейд лидера" + L["Toggle if a border should be shown around the raid leader"] = "Включите, если необходимо показывать контур вокруг цели рейд лидера" + + -- Powerbar.lua + L["Show the actual power"] = "Показывать текущую ману" + L["Show the actual power on the power bar"] = "Показывать текущую ману на полосе маны" + L["Show max power"] = "Показывать максимальную ману" + L["Show max power on the power bar"] = "Показывать максимальную ману на полосе маны" + L["Show power percentage"] = "Показывать ману в процентах" + L["Show power percentage on the power bar"] = "Показывать ману в процентах на полосе маны" + L["Color of the status bar background"] = "Цвет фона строки состояния" + + -- Trinket.lua + L["No cooldown count (OmniCC)"] = "Не показывать кулдаун (OmniCC)" + L["Disable cooldown timers by addons (reload UI to take effect)"] = "Отключить таймер кулдаунов для аддонов (необходима перезагрузка интерфейса)" +elseif (GetLocale() == "deDE") then + -- Races + L["Human"] = "Mensch" + L["Dwarf"] = "Zwerg" + L["Night Elf"] = "Nachtelf" + L["Gnome"] = "Gnom" + L["Draenei"] = "Draenei" + L["Orc"] = "Ork" + L["Undead"] = "Untoter" + L["Tauren"] = "Taure" + L["Troll"] = "Тroll" + L["Blood Elf"] = "Blutelf" + + -- Classes + L["Druid"] = "Druide" + L["Hunter"] = "Jäger" + L["Mage"] = "Magier" + L["Paladin"] = "Paladin" + L["Priest"] = "Priester" + L["Rogue"] = "Schurke" + L["Shaman"] = "Schamane" + L["Warlock"] = "Hexenmeister" + L["Warrior"] = "Krieger" + + -- Specs + L["Balance"] = "Gleichgewicht" + L["Feral"] = "Wilder Kampf" + L["Restoration"] = "Wiederherstellung" + L["Beast Mastery"] = "Tierherrschaft" + L["Marksmanship"] = "Treffsicherheit" + L["Survival"] = "Überleben" + L["Arcane"] = "Arkan" + L["Fire"] = "Feuer" + L["Frost"] = "Frost" + L["Holy"] = "Heilig" + L["Protection"] = "Schutz" + L["Retribution"] = "Vergeltung" + L["Discipline"] = "Disziplin" + L["Shadow"] = "Schatten" + L["Assassination"] = "Meucheln" + L["Combat"] = "Kampf" + L["Subtlety"] = "Täuschung" + L["Elemental"] = "Elemental" + L["Enhancement"] = "Verstärkung" + L["Affliction"] = "Gebrechen" + L["Demonology"] = "Demonologie" + L["Destruction"] = "Zerstörung" + L["Arms"] = "Waffen" + L["Fury"] = "Furor" + + -- Gladdy.lua + L["Welcome to Gladdy!"] = "Willkommen bei Gladdy!" + L["First run has been detected, displaying test frame."] = "Erster Start wurde entdeckt, zeige Testbild an." + L["Valid slash commands are:"] = "Gültige slash Befehle sind:" + L["If this is not your first run please lock or move the frame to prevent this from happening."] = "Wenn dies nicht dein erster Start ist, sperre oder bewege das Bild um diese Meldung zu verhindern." + + -- Frame.lua + L["Gladdy - drag to move"] = "Gladdy - ziehe um zu bewegen" + + -- Options.lua + L["Announcements"] = "Meldungen" + L["Announcement settings"] = "Meldungseinstellungen" + L["Auras"] = "Auren" + L["Auras settings"] = "Aureneinstellungen" + L["Castbar"] = "Zauberleiste" + L["Castbar settings"] = "Zauberleisteneinstellungen" + L["Classicon"] = "Klassensymbol" + L["Classicon settings"] = "Klassensymboleinstellungen" + L["Clicks"] = "Klicks" + L["Clicks settings"] = "Klickeinstellungen" + L["Diminishings"] = "DR" + L["Diminishings settings"] = "DR Einstellungen" + L["Healthbar"] = "Lebensleiste" + L["Healthbar settings"] = "Lebensleisteneinstellungen" + L["Highlight"] = "warnung" + L["Highlight settings"] = "Warnungseinstellungen" + L["Nameplates"] = "Namensplaketten" + L["Nameplates settings"] = "Namensplaketteneinstellungen" + L["Powerbar"] = "Powerleiste" + L["Powerbar settings"] = "Powerleisteneinstellungen" + L["Score"] = "Score" + L["Score settings"] = "Scoreeinstellungen" + L["Trinket"] = "Insignie" + L["Trinket settings"] = "Insignieneinstellungen" + L["Reset module"] = "Model zurücksetzen" + L["Reset module to defaults"] = "Modul auf Standardeinstellungen zurücksetzen" + L["No settings"] = "Keine Einstellungen" + L["Module has no settings"] = "Modul hat keine Einstellungen" + L["General"] = "ОAllgemein" + L["General settings"] = "Allgemeine Einstellungen" + L["Lock frame"] = "Sperre Bild" + L["Toggle if frame can be moved"] = "Aktivieren falls das Bild bewegt werden kann" + L["Grow frame upwards"] = "Bild von unten nach oben aufbauen" + L["If enabled the frame will grow upwards instead of downwards"] = "Falls aktiviert, wird das Bild von unten nach oben aufgebaut" + L["Frame scale"] = "Bildskalierung" + L["Scale of the frame"] = "Skalierung des Bildes" + L["Frame padding"] = "Bild Unterlage" + L["Padding of the frame"] = "Unterlage des Bildes" + L["Frame color"] = "Bildfarbe" + L["Color of the frame"] = "Farbe des Bildes" + L["Bar width"] = "Leistenbreite" + L["Width of the bars"] = "Breite der Leisten" + L["Bottom margin"] = "Unterer Abstand" + L["Margin between each button"] = "Abstand zwischen jedem Buttom" + + -- Announcements.lua + L["RESURRECTING: %s (%s)"] = "Wiederbeleben: %s (%s) " + L["SPEC DETECTED: %s - %s (%s)"] = "Talenspezalisierung entdeckt: %s - %s (%s)" + L["LOW HEALTH: %s (%s)"] = "Niedriges Leben: %s (%s)" + L["TRINKET USED: %s (%s)"] = "Insiginie benutzt: %s (%s)" + L["TRINKET READY: %s (%s)"] = "Insignie bereit: %s (%s)" + L["DRINKING: %s (%s)"] = "Trinken: %s (%s)" + L["Self"] = "Selbst" + L["Party"] = "Gruppe" + L["Raid Warning"] = "Schlachtzugwarnung" + L["Blizzard's Floating Combat Text"] = "Blizzard Kampftext" + L["MikScrollingBattleText"] = "MikScrollingBattleText" + L["Scrolling Combat Text"] = "Scrolling Combat Text" + L["Parrot"] = "Parrot" + L["Drinking"] = "Trinken" + L["Announces when enemies sit down to drink"] = "Warnt wenn Gegner sich zum Trinken hinsetzen" + L["Resurrection"] = "Wiederbelebung" + L["Announces when an enemy tries to resurrect a teammate"] = "Warnt wenn Gegner versuchen Teammitglieder wiederzubeleben" + L["New enemies"] = "Neue Gegner" + L["Announces when new enemies are discovered"] = "Gibt an, wenn neue Gegner entdeckt wurden" + L["Spec Detection"] = "Talent Entdeckung" + L["Announces when the spec of an enemy was detected"] = "Gibt an, wenn Talente eines Gegners entdeckt wurden" + L["Low health"] = "Wenig Leben" + L["Announces when an enemy drops below a certain health threshold"] = "Warnt, wenn das Leben eines Gegners unter einen bestimmten Prozentwert fällt" + L["Low health threshold"] = "Prozentwert: Wenig Leben" + L["Choose how low an enemy must be before low health is announced"] = "Bestimme wie wenig Leben ein Gegner haben muss, damit vor wenig Leben gewarnt wird" + L["Trinket used"] = "Insignie benutzt" + L["Announce when an enemy's trinket is used"] = "Warnt, wenn ein Gegner seine Insignie benutzt" + L["Trinket ready"] = "Insignie bereit" + L["Announce when an enemy's trinket is ready again"] = "Warnt wenn die Insignie eines Gegner wieder bereit ist" + L["Destination"] = "Ziel" + L["Choose how your announcements are displayed"] = "Bestimme wo Warnungen dargestellt werden" + + -- Auras.lua + L["Font color"] = "Schriftfarbe" + L["Color of the text"] = "Farbe der Schrift" + L["Font size"] = "Schriftgröße" + L["Size of the text"] = "Größe der Schrift" + + -- Castbar.lua + L["Bar height"] = "Leistenhöhe" + L["Height of the bar"] = "Höhe der Leiste" + L["Bar texture"] = "Leistentextur" + L["Texture of the bar"] = "Textur der Leiste" + L["Bar color"] = "Leistenfarbe" + L["Color of the cast bar"] = "Farbe der Zauberleiste" + L["Background color"] = "Hintergrundfarbe" + L["Color of the cast bar background"] = "Hintergrundfarbe der Zauberleiste" + L["Icon position"] "Position des Zauberleistensymbols" + + -- Clicks.lua + L["Action #%d"] = "Aktion #%d" + L["Left Click Enemy 1"] = "Linksklick Gegner 1" + L["Left Click Enemy 2"] = "Linksklick Gegner 2" + L["Left Click Enemy 3"] = "Linksklick Gegner 3" + L["Left Click Enemy 4"] = "Linksklick Gegner 4" + L["Left Click Enemy 5"] = "Linksklick Gegner 5" + L["Right Click Enemy 1"] = "Rechtsklick Gegner 1" + L["Right Click Enemy 2"] = "Rechtsklick Gegner 2" + L["Right Click Enemy 3"] = "Rechtsklick Gegner 3" + L["Right Click Enemy 4"] = "Rechtsklick Gegner 4" + L["Right Click Enemy 5"] = "Rechtsklick Gegner 5" + L["Left button"] = "Linke Taste" + L["Right button"] = "Rechte Taste" + L["Middle button"] = "Mittlere Taste" + L["Button 4"] = "Maus 4" + L["Button 5"] = "Maus 5" + L["None"] = "Keine" + L["CTRL"] = "STRG" + L["SHIFT"] = "SHIFT" + L["ALT"] = "ALT" + L["Cast Spell"] = "Wirke Zauber" + L["Name"] = "Name" + L["Select the name of the click option"] = "Wähle einen Namen für die Klickoption" + L["Button"] = "Taste" + L["Select which mouse button to use"] = "Wähle welche Maustaste genutzt werden soll" + L["Modifier"] = "Modifier" + L["Select which modifier to use"] = "Wähle welcher Modifier benutzt werdne soll" + L["Action"] = "Aktion" + L["Select what action this mouse button does"] = "Wähle welche Aktion die Maustaste durchführt" + L["Spell name / Macro text"] = "Zaubername / Makrotext" + L["Use *name* as unit's name. Like a '/rofl *name*'"] = "Benutzt *name* als Gegnername. Zum Beispiel '/rofl *name*'" + + -- Diminishings.lua + L["DR Cooldown position"] = "Position des DR Cooldowns" + L["Position of the cooldown icons"] = "Position des DR Cooldowns" + L["Left"] = "Links" + L["Right"] = "Rechts" + L["Icon Size"] = "Symbolgröße" + L["Size of the DR Icons"] = "Größe des DR Symbols" + + -- Healthbar.lua + L["Show the actual health"] = "Zeige das Leben an" + L["Show the actual health on the health bar"] = "Zeige das Leben auf der Lebensanzeige an" + L["Show max health"] = "Zeige Maximalleben an" + L["Show max health on the health bar"] = "Zeige Maximalleben auf der Lebensanzeige an" + L["Show health percentage"] = "Zeige prozentuales Leben" + L["Show health percentage on the health bar"] = "Zeige prozentuales Leben auf der Lebensanzeige an" + + -- Highlight.lua + L["Border size"] = "Rahmengröße" + L["Target border color"] = "Zielrahmenfarbe" + L["Color of the selected targets border"] = "Farbe des Rahmens des gewählten Ziels" + L["Focus border color"] = "Focusrahmenfarbe" + L["Color of the focus border"] = "Farbe des Focusrahmens" + L["Raid leader border color"] = "Schlachtzugleiterrahmenfarbe" + L["Color of the raid leader border"] = "Farbe des Rahmens für den Schlachtzugleiter" + L["Highlight target"] = "Highlight Ziel" + L["Toggle if the selected target should be highlighted"] = "Включите, если необходима подсветка цели" + L["Show border around target"] = "Zeige Rahmen um das Ziel an" + L["Toggle if a border should be shown around the selected target"] = "Auswählen wenn ein Ramhen um das ausgewählte Ziel angezeigt werden soll" + L["Show border around focus"] = "Zeige Rahmen um Focus" + L["Toggle of a border should be shown around the current focus"] = "Auswählen wenn ein Ramhen um das ausgewählte Focusziel angezeigt werden soll" + L["Show border around raid leader"] = "Zeige Rahmen um Schlachtzugleiter" + L["Toggle if a border should be shown around the raid leader"] = "Auswählen wenn ein Ramhen um den ausgewählten SChlachtzugleiter angezeigt werden soll" + + -- Powerbar.lua + L["Show the actual power"] = "Zeige genaue Power" + L["Show the actual power on the power bar"] = "Zeige die genaue Power in der Powerleiste " + L["Show max power"] = "Zeige Maximalpower" + L["Show max power on the power bar"] = "Zeige Maximalpower in der Powerbau" + L["Show power percentage"] = "Zeige prozentuale Power" + L["Show power percentage on the power bar"] = "Zeige prozentuale Power in der Powerbau" + L["Color of the status bar background"] = "Hintergrundfarbe der Statusleiste" + + -- Trinket.lua + L["No cooldown count (OmniCC)"] = "Keine Cooldownanzeige (OmniCC)" + L["Disable cooldown timers by addons (reload UI to take effect)"] = "Deaktiviere Cooldownanzeige durch Addons (UI neu laden um zu wirken)" +end + +-- Superhack allowing use key as value if not present in table +LibStub("Gladdy").L = setmetatable(L, { + __index = function(t, k) + return k + end +}) \ No newline at end of file diff --git a/Libs/AceComm-3.0/AceComm-3.0.lua b/Libs/AceComm-3.0/AceComm-3.0.lua new file mode 100644 index 0000000..242d92c --- /dev/null +++ b/Libs/AceComm-3.0/AceComm-3.0.lua @@ -0,0 +1,305 @@ +--- **AceComm-3.0** allows you to send messages of unlimited length over the addon comm channels. +-- It'll automatically split the messages into multiple parts and rebuild them on the receiving end.\\ +-- **ChatThrottleLib** is of course being used to avoid being disconnected by the server. +-- +-- **AceComm-3.0** can be embeded into your addon, either explicitly by calling AceComm:Embed(MyAddon) or by +-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object +-- and can be accessed directly, without having to explicitly call AceComm itself.\\ +-- It is recommended to embed AceComm, otherwise you'll have to specify a custom `self` on all calls you +-- make into AceComm. +-- @class file +-- @name AceComm-3.0 +-- @release $Id: AceComm-3.0.lua 1202 2019-05-15 23:11:22Z nevcairiel $ + +--[[ AceComm-3.0 + +TODO: Time out old data rotting around from dead senders? Not a HUGE deal since the number of possible sender names is somewhat limited. + +]] + +local CallbackHandler = LibStub("CallbackHandler-1.0") +local CTL = assert(ChatThrottleLib, "AceComm-3.0 requires ChatThrottleLib") + +local MAJOR, MINOR = "AceComm-3.0", 12 +local AceComm,oldminor = LibStub:NewLibrary(MAJOR, MINOR) + +if not AceComm then return end + +-- Lua APIs +local type, next, pairs, tostring = type, next, pairs, tostring +local strsub, strfind = string.sub, string.find +local match = string.match +local tinsert, tconcat = table.insert, table.concat +local error, assert = error, assert + +-- WoW APIs +local Ambiguate = Ambiguate + +-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded +-- List them here for Mikk's FindGlobals script +-- GLOBALS: LibStub, DEFAULT_CHAT_FRAME, geterrorhandler, RegisterAddonMessagePrefix + +AceComm.embeds = AceComm.embeds or {} + +-- for my sanity and yours, let's give the message type bytes some names +local MSG_MULTI_FIRST = "\001" +local MSG_MULTI_NEXT = "\002" +local MSG_MULTI_LAST = "\003" +local MSG_ESCAPE = "\004" + +-- remove old structures (pre WoW 4.0) +AceComm.multipart_origprefixes = nil +AceComm.multipart_reassemblers = nil + +-- the multipart message spool: indexed by a combination of sender+distribution+ +AceComm.multipart_spool = AceComm.multipart_spool or {} + +--- Register for Addon Traffic on a specified prefix +-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent), max 16 characters +-- @param method Callback to call on message reception: Function reference, or method name (string) to call on self. Defaults to "OnCommReceived" +function AceComm:RegisterComm(prefix, method) + if method == nil then + method = "OnCommReceived" + end + + if #prefix > 16 then -- TODO: 15? + error("AceComm:RegisterComm(prefix,method): prefix length is limited to 16 characters") + end + if C_ChatInfo then + C_ChatInfo.RegisterAddonMessagePrefix(prefix) + else + RegisterAddonMessagePrefix(prefix) + end + + return AceComm._RegisterComm(self, prefix, method) -- created by CallbackHandler +end + +local warnedPrefix=false + +--- Send a message over the Addon Channel +-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent) +-- @param text Data to send, nils (\000) not allowed. Any length. +-- @param distribution Addon channel, e.g. "RAID", "GUILD", etc; see SendAddonMessage API +-- @param target Destination for some distributions; see SendAddonMessage API +-- @param prio OPTIONAL: ChatThrottleLib priority, "BULK", "NORMAL" or "ALERT". Defaults to "NORMAL". +-- @param callbackFn OPTIONAL: callback function to be called as each chunk is sent. receives 3 args: the user supplied arg (see next), the number of bytes sent so far, and the number of bytes total to send. +-- @param callbackArg: OPTIONAL: first arg to the callback function. nil will be passed if not specified. +function AceComm:SendCommMessage(prefix, text, distribution, target, prio, callbackFn, callbackArg) + prio = prio or "NORMAL" -- pasta's reference implementation had different prio for singlepart and multipart, but that's a very bad idea since that can easily lead to out-of-sequence delivery! + if not( type(prefix)=="string" and + type(text)=="string" and + type(distribution)=="string" and + (target==nil or type(target)=="string" or type(target)=="number") and + (prio=="BULK" or prio=="NORMAL" or prio=="ALERT") + ) then + error('Usage: SendCommMessage(addon, "prefix", "text", "distribution"[, "target"[, "prio"[, callbackFn, callbackarg]]])', 2) + end + + local textlen = #text + local maxtextlen = 255 -- Yes, the max is 255 even if the dev post said 256. I tested. Char 256+ get silently truncated. /Mikk, 20110327 + local queueName = prefix..distribution..(target or "") + + local ctlCallback = nil + if callbackFn then + ctlCallback = function(sent) + return callbackFn(callbackArg, sent, textlen) + end + end + + local forceMultipart + if match(text, "^[\001-\009]") then -- 4.1+: see if the first character is a control character + -- we need to escape the first character with a \004 + if textlen+1 > maxtextlen then -- would we go over the size limit? + forceMultipart = true -- just make it multipart, no escape problems then + else + text = "\004" .. text + end + end + + if not forceMultipart and textlen <= maxtextlen then + -- fits all in one message + CTL:SendAddonMessage(prio, prefix, text, distribution, target, queueName, ctlCallback, textlen) + else + maxtextlen = maxtextlen - 1 -- 1 extra byte for part indicator in prefix(4.0)/start of message(4.1) + + -- first part + local chunk = strsub(text, 1, maxtextlen) + CTL:SendAddonMessage(prio, prefix, MSG_MULTI_FIRST..chunk, distribution, target, queueName, ctlCallback, maxtextlen) + + -- continuation + local pos = 1+maxtextlen + + while pos+maxtextlen <= textlen do + chunk = strsub(text, pos, pos+maxtextlen-1) + CTL:SendAddonMessage(prio, prefix, MSG_MULTI_NEXT..chunk, distribution, target, queueName, ctlCallback, pos+maxtextlen-1) + pos = pos + maxtextlen + end + + -- final part + chunk = strsub(text, pos) + CTL:SendAddonMessage(prio, prefix, MSG_MULTI_LAST..chunk, distribution, target, queueName, ctlCallback, textlen) + end +end + + +---------------------------------------- +-- Message receiving +---------------------------------------- + +do + local compost = setmetatable({}, {__mode = "k"}) + local function new() + local t = next(compost) + if t then + compost[t]=nil + for i=#t,3,-1 do -- faster than pairs loop. don't even nil out 1/2 since they'll be overwritten + t[i]=nil + end + return t + end + + return {} + end + + local function lostdatawarning(prefix,sender,where) + DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: lost network data regarding '"..tostring(prefix).."' from '"..tostring(sender).."' (in "..where..")") + end + + function AceComm:OnReceiveMultipartFirst(prefix, message, distribution, sender) + local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender + local spool = AceComm.multipart_spool + + --[[ + if spool[key] then + lostdatawarning(prefix,sender,"First") + -- continue and overwrite + end + --]] + + spool[key] = message -- plain string for now + end + + function AceComm:OnReceiveMultipartNext(prefix, message, distribution, sender) + local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender + local spool = AceComm.multipart_spool + local olddata = spool[key] + + if not olddata then + --lostdatawarning(prefix,sender,"Next") + return + end + + if type(olddata)~="table" then + -- ... but what we have is not a table. So make it one. (Pull a composted one if available) + local t = new() + t[1] = olddata -- add old data as first string + t[2] = message -- and new message as second string + spool[key] = t -- and put the table in the spool instead of the old string + else + tinsert(olddata, message) + end + end + + function AceComm:OnReceiveMultipartLast(prefix, message, distribution, sender) + local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender + local spool = AceComm.multipart_spool + local olddata = spool[key] + + if not olddata then + --lostdatawarning(prefix,sender,"End") + return + end + + spool[key] = nil + + if type(olddata) == "table" then + -- if we've received a "next", the spooled data will be a table for rapid & garbage-free tconcat + tinsert(olddata, message) + AceComm.callbacks:Fire(prefix, tconcat(olddata, ""), distribution, sender) + compost[olddata] = true + else + -- if we've only received a "first", the spooled data will still only be a string + AceComm.callbacks:Fire(prefix, olddata..message, distribution, sender) + end + end +end + + + + + + +---------------------------------------- +-- Embed CallbackHandler +---------------------------------------- + +if not AceComm.callbacks then + AceComm.callbacks = CallbackHandler:New(AceComm, + "_RegisterComm", + "UnregisterComm", + "UnregisterAllComm") +end + +AceComm.callbacks.OnUsed = nil +AceComm.callbacks.OnUnused = nil + +local function OnEvent(self, event, prefix, message, distribution, sender) + if event == "CHAT_MSG_ADDON" then + sender = Ambiguate(sender, "none") + local control, rest = match(message, "^([\001-\009])(.*)") + if control then + if control==MSG_MULTI_FIRST then + AceComm:OnReceiveMultipartFirst(prefix, rest, distribution, sender) + elseif control==MSG_MULTI_NEXT then + AceComm:OnReceiveMultipartNext(prefix, rest, distribution, sender) + elseif control==MSG_MULTI_LAST then + AceComm:OnReceiveMultipartLast(prefix, rest, distribution, sender) + elseif control==MSG_ESCAPE then + AceComm.callbacks:Fire(prefix, rest, distribution, sender) + else + -- unknown control character, ignore SILENTLY (dont warn unnecessarily about future extensions!) + end + else + -- single part: fire it off immediately and let CallbackHandler decide if it's registered or not + AceComm.callbacks:Fire(prefix, message, distribution, sender) + end + else + assert(false, "Received "..tostring(event).." event?!") + end +end + +AceComm.frame = AceComm.frame or CreateFrame("Frame", "AceComm30Frame") +AceComm.frame:SetScript("OnEvent", OnEvent) +AceComm.frame:UnregisterAllEvents() +AceComm.frame:RegisterEvent("CHAT_MSG_ADDON") + + +---------------------------------------- +-- Base library stuff +---------------------------------------- + +local mixins = { + "RegisterComm", + "UnregisterComm", + "UnregisterAllComm", + "SendCommMessage", +} + +-- Embeds AceComm-3.0 into the target object making the functions from the mixins list available on target:.. +-- @param target target object to embed AceComm-3.0 in +function AceComm:Embed(target) + for k, v in pairs(mixins) do + target[v] = self[v] + end + self.embeds[target] = true + return target +end + +function AceComm:OnEmbedDisable(target) + target:UnregisterAllComm() +end + +-- Update embeds +for target, v in pairs(AceComm.embeds) do + AceComm:Embed(target) +end diff --git a/Libs/AceComm-3.0/AceComm-3.0.xml b/Libs/AceComm-3.0/AceComm-3.0.xml new file mode 100644 index 0000000..24fb43b --- /dev/null +++ b/Libs/AceComm-3.0/AceComm-3.0.xml @@ -0,0 +1,5 @@ + +