diff --git a/.github/workflows/create-zips.yml b/.github/workflows/create-zips.yml new file mode 100644 index 0000000..d422320 --- /dev/null +++ b/.github/workflows/create-zips.yml @@ -0,0 +1,72 @@ +# This is a basic workflow to help you get started with Actions + +name: Zip Mod Folders + +# Controls when the workflow will run +on: + # Triggers the workflow on push event but only for the "main" branch + push: + branches: [ "main" ] + paths: + - 'HeartAttack/**' + - 'HumorousDeath/**' + - 'InterruptReminder/**' + - 'LibFramePool-1.0/**' + - 'TalkingHeadShut/**' + - 'ThreatTrack/**' + - 'ZoomerWoW/**' + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v4 + + - name: Create ZIPs folder + run: mkdir -p _zips + + - name: Delete contents of _zips + run: | + rm -rf "_zips/"* + + # Runs a set of commands using the runners shell + - name: Run a multi-line script + run: | + folders=("HeartAttack" "HumorousDeath" "InterruptReminder" "LibFramePool-1.0" "TalkingHeadShut" "ThreatTrack" "ZoomerWoW") + for folder in "${folders[@]}"; do + files=() + cd "${folder}" + version=$(head -n2 *.toc | tail -n1 | awk '{print $3}') + zip_name="${folder}_v${version}.zip" + for item in "."/*; do + if [[ "$item" != "./_misc" && "$item" != "./*.zip" ]]; then + files+=("$item") + fi + done + zip -r "$zip_name" "${files[@]}" + echo "Created zip file $zip_name" + mv "$zip_name" ../_zips + cd .. + done + - name: Push ZIPs to repo + run: | + branch_name=$(date +"%d-%b-%Y-%H-%M-%S") + git config user.name "GitHub Actions Bot" + git config user.email "<>" + git checkout -b "zips_$branch_name" + git add _zips/* + git commit -m "Committed ZIP folders" + git push -u origin "zips_$branch_name" + gh pr create -B main -H "zips_$branch_name" --title "Merge zips_$branch_name into main" --body 'Created by Github action' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + diff --git a/.gitignore b/.gitignore index 4c4201d..c4e00c7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ luac.out # luarocks build files *.src.rock -*.zip *.tar.gz # Object files diff --git a/HeartAttack/HeartAttack.lua b/HeartAttack/HeartAttack.lua index aa3cf11..e89bfba 100644 --- a/HeartAttack/HeartAttack.lua +++ b/HeartAttack/HeartAttack.lua @@ -1,6 +1,7 @@ local HA_Table = { panel = CreateFrame("Frame", "HeartAttackSettings") } +local category --[[READ FIRST If you would like to change the parameters of the mod (either by lowering the total possible playtime, or increasing @@ -138,11 +139,13 @@ local function create_interface() " roles, open the file HeartAttack/HeartAttack.lua in your text editor of choice and read line 3 that says".. " READ FIRST for instructions.") userNote:SetWordWrap(true) - InterfaceOptions_AddCategory(HA_Table.panel, true) + category = Settings.RegisterCanvasLayoutCategory(HA_Table.panel, HA_Table.panel.name, HA_Table.panel.name); + category.ID = HA_Table.panel.name + Settings.RegisterAddOnCategory(category); end function HeartAttack_OnAddonCompartmentClick() - InterfaceOptionsFrame_OpenToCategory(HA_Table.panel) + Settings.OpenToCategory(category.ID) end --Game Over frame diff --git a/HeartAttack/HeartAttack.toc b/HeartAttack/HeartAttack.toc index 2c0beb9..834d4a5 100644 --- a/HeartAttack/HeartAttack.toc +++ b/HeartAttack/HeartAttack.toc @@ -1,5 +1,5 @@ -## Interface: 100206 -## Version: 1.0.4 +## Interface: 110005 +## Version: 1.1.1 ## Title: Heart Attack ## Author: AgentRG ## SavedVariablesPerCharacter: HeartAttack_FirstTimeDone, HeartAttack_GlobalTable diff --git a/HeartAttack/Heart_Attack_Orc_KG.png b/HeartAttack/_misc/Heart_Attack_Orc_KG.png similarity index 100% rename from HeartAttack/Heart_Attack_Orc_KG.png rename to HeartAttack/_misc/Heart_Attack_Orc_KG.png diff --git a/HumorousDeath/HumorousDeath.toc b/HumorousDeath/HumorousDeath.toc index 17daee7..a6ab7e4 100644 --- a/HumorousDeath/HumorousDeath.toc +++ b/HumorousDeath/HumorousDeath.toc @@ -1,5 +1,5 @@ -## Interface: 100206 -## Version: 1.0.5 +## Interface: 110005 +## Version: 1.0.7 ## Title: Humorous Death ## Author: AgentRG ## SavedVariablesPerCharacter: HumorousDeath_IterateInt, HumorousDeath_Setting, HumorousDeath_FirstTimeDone diff --git a/HumorousDeath/OrcFinalKG.jpg b/HumorousDeath/_misc/OrcFinalKG.jpg similarity index 100% rename from HumorousDeath/OrcFinalKG.jpg rename to HumorousDeath/_misc/OrcFinalKG.jpg diff --git a/HumorousDeath/OrcFinalKG.png b/HumorousDeath/_misc/OrcFinalKG.png similarity index 100% rename from HumorousDeath/OrcFinalKG.png rename to HumorousDeath/_misc/OrcFinalKG.png diff --git a/HumorousDeath/hd-icon.jpg b/HumorousDeath/_misc/hd-icon.jpg similarity index 100% rename from HumorousDeath/hd-icon.jpg rename to HumorousDeath/_misc/hd-icon.jpg diff --git a/InterruptReminder/CHANGELOG.md b/InterruptReminder/CHANGELOG.md index 7d73f3e..15a28d9 100644 --- a/InterruptReminder/CHANGELOG.md +++ b/InterruptReminder/CHANGELOG.md @@ -1,3 +1,74 @@ +## v2.4.5 +General Changes: + + Supporting latest TOC version + +## v2.4.4 +General Changes: + + Revamped logic that would find the spells in the action bar. + Moved around when the mods global table is being generated. + Added localization for Portuguese, Chinese, French, German, Italian, Spanish, Korea and Russian (Created using AI, hopefully no spellling mistakes). + +Bug Fixes: + + Removed a talent from Demon Hunter that was mistaken for a spell. + Added missing RaceIDs to the mod table when pulling race spells. + Fixed duplicate spells appearing in the list of spells due to other addons requesting spell data. + + +## v2.4.3 +Bug Fixes: + + Further fixed localization other than English by moving to ClassIds and RaceIds + Added a localization to translate mod text into other languages in the future + +## v2.4.2 +Bug Fixes: + + Fixed the settings UI being stuck in a loop of generation. + + +## v2.4.1 +Bug Fixes: + + Fixed not all spells loading on UI load. + + +## v2.4.0 +New Addition: + + Migrated from smart spell lookup based on keywords to hardcoded spell IDs based on character class/race. + The reasoning being that support for multiple languages would be impossibly difficult to support. + + Plus due to frequent updates, I often had to exclude specific spells that got picked up by the mod because they + matched the lookup, but did not meet the correct criteria. + + Cataclysm version of the mod is still using the old lookup logic. I do not plan to update that version of the mod + as I do not play classic enough (or at all) to see myself spending time supporting it, but I am looking for volunteers! + +General Changes: + + Removed all code related to smart lookup of spells. + Added add-on version number to bottom left of config window. + Rewrote some parts in the about-mod section. + + +## v2.3.1 +Bug Fixes: + + Fixed null exception for spells that the player character does not have unlocked. + +## v2.3.0 +General Changes: + + Migrated old functions used to gather information about spells to be gathered from C classes. + +Bug Fixes: + + Fixed settings menu initialization. + Fixed extraneous spell showing up for Evokers. + ## v2.2.0 New Addition: diff --git a/InterruptReminder/InterruptReminder.lua b/InterruptReminder/InterruptReminder.lua index 6d24b60..6e2c3f6 100644 --- a/InterruptReminder/InterruptReminder.lua +++ b/InterruptReminder/InterruptReminder.lua @@ -1,5 +1,10 @@ +local L + -- Table from which the add-on retrieves and stores all runtime data about the target, player, and more. local IR_Table = { + Mod_Version = function() + return "Interrupt Reminder ".. L["VERSION"] ..": 2.4.5" + end, -- WoW default action bar names ActionBars = { 'ActionButton', 'MultiBarBottomLeftButton', 'MultiBarBottomRightButton', 'MultiBarRightButton', 'MultiBarLeftButton', 'MultiBar7Button', 'MultiBar6Button', 'MultiBar5Button' }, @@ -7,80 +12,80 @@ local IR_Table = { 'ElvUI_Bar5Button', 'ElvUI_Bar6Button', 'ElvUI_Bar7Button', 'ElvUI_Bar8Button', 'ElvUI_Bar9Button', 'ElvUI_Bar10Button', 'ElvUI_Bar13Button', 'ElvUI_Bar14Button', 'ElvUI_Bar15Button' }, - -- All keywords that are found in varying Crowd Control spells - CrownControlTypes = { 'knock', 'control', 'confuse', 'fear', 'flee', 'stun', 'interrupt', 'incapacit', - 'intimidat', 'sleep', 'disorient', 'horr', 'silenc', 'counter' }, - -- Spells that will get picked up by IR_Table:get_all_crowd_control_spells because they contain a keyword from - -- CrownControlTypes that we do not want to be added to the list - ExtraneousCCSpells = { - ['Evoker'] = { 'Deep Breath', 'Dream Flight', 'Emerald Communion', 'Breath of Eons' }, - ['Warlock'] = { 'Dark Pact', 'Unending Resolve', 'Grimoire: Felguard', 'Nightmare', 'Horrify' }, - ['Warrior'] = { 'Enraged Regeneration', 'Concussive Blows', 'Endurance Training', 'Berserker Shout', - 'Berserker Rage', 'Cacophonous Roar', 'Menace', 'Bladestorm', 'Berserker Stance' }, - ['Mage'] = { 'Blink', 'Frost Nova', 'Volatile Detonation', 'Quick Witted', 'Time Manipulation', 'Glacial Spike' }, - ['Demon Hunter'] = { 'Isolated Prey', 'Chaos Fragments', 'Disrupting Fury' }, - ['Druid'] = { 'Barkskin', 'Light of the Sun', 'Pouncing Strikes', 'Inner Peace' }, - ['Hunter'] = { 'Eyes of the Beast', 'Binding Shackles', 'Bestial Wrath' }, - ['Death Knight'] = { "Death's Advance", 'Lichborne', 'Coldthirst', 'Icebound Fortitude' }, - ['Priest'] = { 'Pain Suppression', 'Guardian Spirit', 'Dispersion', 'Ultimate Penitence', 'Petrifying Scream', - 'Censure', 'Last Word', "Idol of Y'Shaarj" }, - ['Paladin'] = { 'Divine Shield', 'Divine Protection', "Justicar's Vengeance", 'Concentration Aura', - 'Auras of the Resolute', 'Punishment' }, - ['Rogue'] = { 'Sap', 'Iron Wire' }, - ['Monk'] = { 'Restoral', 'Storm, Earth, and Fire', "Shaohao's Lessons" }, - ['Shaman'] = { 'Tumultuous Fissures', 'Primal Elementalist', 'Mountains Will Fall', "Spiritwalker's Aegis", - 'Tremor Totem', 'Static Charge', 'Tranquil Air Totem', 'Thundershock' }, - ['Human'] = { 'Will to Survive' }, - ['Dwarf'] = {}, - ['Night Elf'] = {}, - ['Gnome'] = {}, - ['Draenei'] = {}, - ['Pandaren'] = {}, - ['Dracthyr'] = {}, - ['Void Elf'] = {}, - ['Lightforged Draenei'] = {}, - ['Dark Iron Dwarf'] = {}, - ['Kul Tiran'] = {}, - ['Mechagnome'] = {}, - ['Tauren'] = {}, - ['Troll'] = {}, - ['Blood Elf'] = {}, - ['Goblin'] = {}, - ['Nightborne'] = {}, - ['Highmountain Tauren'] = {}, - ["Mag'har Orc"] = {}, - ['Vulpera'] = {}, - ['Worgen'] = { 'Calm the Wolf' }, - ['Orc'] = { 'Hardiness' }, - ['Undead'] = { 'Will of the Forsaken' }, - ['Zandalari Troll'] = { "Regeneratin'" } - }, -- Default interrupts for all classes. These spell's primarily goal is to interrupt (with sometimes a secondary --effect) InterruptSpells = { - ['Death Knight'] = { 'Mind Freeze', 'Asphyxiate', 'Strangulate' }, - ['Demon Hunter'] = { 'Disrupt' }, - ['Druid'] = { 'Skull Bash', 'Solar Beam' }, - ['Evoker'] = { 'Quell' }, - ['Hunter'] = { 'Counter Shot', 'Muzzle' }, - ['Mage'] = { 'Counterspell' }, - ['Monk'] = { 'Spear Hand Strike' }, - ['Paladin'] = { 'Rebuke', "Avenger's Shield" }, - ['Priest'] = { 'Silence' }, - ['Rogue'] = { 'Kick' }, - ['Shaman'] = { 'Wind Shear' }, - ['Warlock'] = { 'Spell Lock', 'Optical Blast', 'Axe Toss' }, - ['Warrior'] = { 'Pummel' } + [6] = { 47528 }, --Death Knight + [12] = { 183752 }, --Demon Hunter + [11] = { 78675 }, --Druid + [13] = { 351338 }, --Evoker + [3] = { 147362, 187707 }, --Hunter + [8] = { 2139 }, --Mage + [10] = { 116705 }, --Monk + [2] = { 96231 }, --Paladin + [5] = { 15487 }, --Priest + [4] = { 1766 }, --Rogue + [7] = { 57994 }, --Shaman + [9] = { 19647, 115781, 89766 }, --Warlock + [1] = { 6552 } --Warrior + }, + CCSpells = { + [6] = { 47528 --[[Mind freeze]], 221562 --[[Asphyxiate]], 108194 --[[Asphyxiate]], 444010 --[[Death Charge]], + 207167 --[[Blinding Sleet]], 374049 --[[Suppression]], 206970 --[[Tightening Grasp]] }, + [12] = { 183752 --[[Disrupt]], 217832 --[[Imprison]], 191427 --[[Metamorphosis]], 211881 --[[Fel Eruption]], + 202137 --[[Sigil of Silence]], 207684 --[[Sigil of Misery]], 179057 --[[Chaos Nova]] }, + [11] = { 78675 --[[Solar Beam]], 106839 --[[Skull Bash]], 132469 --[[Typhoon]], 2637 --[[Hibernate]], + 33786 --[[Cyclone]], 22570 --[[Maim]], 99 --[[Incapacitating Roar]], 5211 --[[Mighty Bash]], + 102359 --[[Mass Entanglement]] }, + [13] = { 351338 --[[Quell]], 360806 --[[Sleep Walk]] }, + [3] = { 147362 --[[Counter Shot]], 187707 --[[Muzzle]], 187650 --[[Freezing Trap]], 1513 --[[Scare Beast]], + 109248 --[[Binding Shot]], 19577 --[[Intimidation]], 186387 --[[Bursting Shot]], + 213691 --[[Scatter Shot]], 236776 --[[High Explosive Trap]], 462031 --[[Implosive Trap]], + 355589 --[[Wailing Arrow]]}, + [8] = { 2139 --[[Counterspell]], 118 --[[Polymorph (Sheep)]], 113724 --[[Ring of Frost]], + 157981 --[[Blast Wave]], 383121 --[[Mass Polymorph]], 31661 --[[Dragon's Breath]], + 157980 --[[Supernova]]}, + [10] = { 117952 --[[Crackling Jade Lightning]], 119381 --[[Leg Sweep]], 115078 --[[Paralysis]], + 198898 --[[Song of Chi-Ji]], 116705 --[[Spear Hand Strike]]}, + [2] = { 853 --[[Hammer of Justice]], 31935 --[[Avenger's Shield]], 255937 --[[Wake of Ashes]], + 20066 --[[Repentance]], 115750 --[[Blinding Light]], 96231 --[[Rebuke]], 10326 --[[Turn Evil]]}, + [5] = { 64044 --[[Psychic Horror]], 8122 --[[Psychic Scream]], 88625 --[[Holy Word: Chastise]], + 34914 --[[Vampiric Touch]], 15487 --[[Silence]], 605 --[[Mind Control]], + 205364 --[[Dominate Mind]]}, + [4] = { 1833 --[[Cheap Shot]], 1766 --[[Kick]], 408 --[[Kidney Shot]], 2094 --[[Blind]], 1776 --[[Gouge]]}, + [7] = { 188389 --[[Flame Shock]], 197214 --[[Sundering]], 462620 --[[Earthquake (At target)]], + 61882 --[[Earthquake (Selected location]], 192058 --[[Capacitor Totem]], 305483 --[[Lightning Lasso]], + 51490 --[[Thunderstorm]], 57994 --[[Wind Shear]], 51514 --[[Hex]]}, + [9] = { 5782 --[[Fear]], 316099 --[[Unstable Affliction]], 1122 --[[Summon Infernal]], 30283 --[[Shadowfury]], + 5484 --[[Howl of Terror]], 6789 --[[Mortal Coil]], 19647 --[[Spell Lock]], + 115781 --[[Optical Blast]], 89766 --[[Axe Toss]]}, + [1] = { 6552 --[[Pummel]], 386071 --[[Disrupting Shout]], 385952 --[[Shield Charge]], 107570 --[[Storm Bolt]], + 46968 --[[Shockwave]], 5246 --[[Intimidating Shout]] } }, + RaceSpells = { + [52] = { 368970 --[[Tail Swipe]], 357214 --[[Wing Buffet]] }, --Dracthyr (Alliance) + [70] = { 368970 --[[Tail Swipe]], 357214 --[[Wing Buffet]] }, --Dracthyr (Horde) + [32] = { 287712 --[[Haymaker]] }, --Kul Tiran + [6] = { 20549 --[[War Stomp]] }, --Tauren + [28] = { 255654 --[[Bull Rush]] }, --Highmountain Tauren + [24] = { 107079 --[[Quaking Palm]] }, --Pandaren (Neutral) + [25] = { 107079 --[[Quaking Palm]] }, --Pandaren (Alliance) + [26] = { 107079 --[[Quaking Palm]] }, --Pandaren (Horde) + [84] = {}, [1] = {}, [3] = {}, [29] = {}, [35] = {}, [4] = {}, [34] = {}, [10] = {}, [33] = {}, [31] = {}, + [2] = {}, [27] = {}, [22] = {}, [11] = {}, [36] = {}, [9] = {}, [37] = {}, [30] = {}, [5] = {}, [8] = {}, + [7] = {}, [12] = {}, [13] = {}, [14] = {}, [15] = {}, [16] = {}, [17] = {}, [18] = {}, [19] = {}, [20] = {}, + [21] = {}, [23] = {}, [85] = {} + }, + SpellCache = {}, SaveHidden = true, - bossInserts = 0, + BossInserts = 0, EndTime = nil, StartTime = nil, IsInterruptible = false, TargetCanBeStunned = false, CurrentTargetCanBeAttacked = false, SpecializationChanged = false, - panel = CreateFrame("Frame", "InterruptReminderSettings"), + Panel = CreateFrame("Frame", "InterruptReminderSettings"), ButtonCache = {}, GlowCache = nil, HideCache = nil, @@ -89,41 +94,37 @@ local IR_Table = { } local f = CreateFrame('Frame', 'InterruptReminder') -local PlayerClass = UnitClass('player') -local PlayerRace = UnitRace('player') +local PlayerClass = select(3, UnitClass('player')) +local PlayerRace = select(3, UnitRace('player')) local CheckButtonFramePool - -- Library used to highlight spells. Without the library, the addon will encounter protected action access error local LibCustomGlow = LibStub("LibCustomGlow-1.0") local LibFramePool = LibStub("LibFramePool-1.0") -- Local version of WoW global functions for slightly faster runtime access local GetActionInfo = GetActionInfo -local GetSpellCooldown = GetSpellCooldown +local C_Spell_GetSpellCooldown = C_Spell.GetSpellCooldown local UnitCastingInfo = UnitCastingInfo local UnitChannelInfo = UnitChannelInfo -local GetNumSpellTabs = GetNumSpellTabs -local GetSpellTabInfo = GetSpellTabInfo -local GetSpellBookItemName = GetSpellBookItemName local tContains = tContains -local Spell = Spell local GetUnitName = GetUnitName local UnitClassification = UnitClassification -local HasAction = HasAction -local GetSpellInfo = GetSpellInfo +local C_Spell_GetSpellInfo = C_Spell.GetSpellInfo +local C_Spell_GetSpellName = C_Spell.GetSpellName +local C_Spell_GetSpellDescription = C_Spell.GetSpellDescription +local C_Spell_RequestLoadSpellData = C_Spell.RequestLoadSpellData local GetTime = GetTime local C_Timer = C_Timer +local C_ActionBar = C_ActionBar local C_EncounterJournal = C_EncounterJournal local EJ_GetCreatureInfo = EJ_GetCreatureInfo local UnitCanAttack = UnitCanAttack local C_Map = C_Map -local C_ClassTalents = C_ClassTalents -local C_Traits = C_Traits local GetInstanceInfo = GetInstanceInfo local PlaySoundFile = PlaySoundFile local IsPlayerSpell = IsPlayerSpell -local IsAddOnLoaded = IsAddOnLoaded +local C_AddOns_IsAddOnLoaded = C_AddOns.IsAddOnLoaded local CreateFrame = CreateFrame local StopSound = StopSound @@ -134,6 +135,11 @@ local ipairs = ipairs local pairs = pairs local select = select +-- Patch 11.0 new settings initialization +IR_Table.Panel.name = "Interrupt Reminder" +local category = Settings.RegisterCanvasLayoutCategory(IR_Table.Panel, IR_Table.Panel.name, IR_Table.Panel.name); +category.ID = IR_Table.Panel.name + local function printInfo(text) print("|cff00ffffInfo (InterruptReminder): |cffffffff" .. text) end @@ -159,16 +165,15 @@ end SLASH_INTERRUPT_REMINDER_OPTIONS1 = "/irconfig" --- Slash command to open the options menu. SlashCmdList['INTERRUPT_REMINDER_OPTIONS'] = function() - InterfaceOptionsFrame_OpenToCategory(IR_Table.panel) + Settings.OpenToCategory(category.ID) end --- Remove duplicates in a table and return the table local function remove_duplicates_from_array(input_table) - local currentCopy = input_table local hash = {} local res = {} - for _, v in pairs(currentCopy) do + for _, v in pairs(input_table) do if (not hash[v]) then res[#res + 1] = v hash[v] = true @@ -201,97 +206,46 @@ local function merge_two_tables(table_one, table_two) return table_one end ---- Get all spells from the specialization tree that is currently active for the player and save them into a table. -local function get_specialization_spells() - local spellIDs = {} - local list = {} - local extraneousSpells = merge_two_tables(IR_Table.ExtraneousCCSpells[PlayerClass], - IR_Table.ExtraneousCCSpells[PlayerRace]) - - local configID = C_ClassTalents.GetActiveConfigID() - if configID == nil then - return +local function create_global_table() + if InterruptReminder_Table == nil then + InterruptReminder_Table = {} end - - local configInfo = C_Traits.GetConfigInfo(configID) - if configInfo == nil then - return + if InterruptReminder_Table['Spells'] == nil then + InterruptReminder_Table['Spells'] = {} end - - for _, treeID in ipairs(configInfo.treeIDs) do - local nodes = C_Traits.GetTreeNodes(treeID) - - for _, nodeID in ipairs(nodes) do - local nodeInfo = C_Traits.GetNodeInfo(configID, nodeID) - - for _, entryID in ipairs(nodeInfo.entryIDs) do - local entryInfo = C_Traits.GetEntryInfo(configID, entryID) - - if entryInfo and entryInfo.definitionID then - local definitionInfo = C_Traits.GetDefinitionInfo(entryInfo.definitionID) - - if definitionInfo.spellID then - table.insert(spellIDs, definitionInfo.spellID) - end - end - end - end + if InterruptReminder_Table['SelectedSpells'] == nil then + InterruptReminder_Table['SelectedSpells'] = IR_Table.InterruptSpells[PlayerClass] end - for _, spellId in ipairs(spellIDs) do - local spell = Spell:CreateFromSpellID(spellId) - local spellName = spell:GetSpellName() - - if spellName and not tContains(extraneousSpells, spellName) then - if spell:IsSpellEmpty() == false then - spell:ContinueOnSpellLoad(function() - local desc = spell:GetSpellDescription() - local descLower = string.lower(desc) - - for _, cc in pairs(IR_Table.CrownControlTypes) do - if string.find(descLower, cc, 1, true) then - printDebug("get_specialization_spells: Inserted spell " .. spellName .. ".") - table.insert(list, { spellName = spellName, description = desc }) - break - end - end - end) - end - end + if InterruptReminder_Table['CurrentBossList'] == nil then + InterruptReminder_Table['CurrentBossList'] = {} + end + if InterruptReminder_Table['Debug'] == nil then + InterruptReminder_Table['Debug'] = false + end + if InterruptReminder_Table['PlaySound'] == nil then + InterruptReminder_Table['PlaySound'] = false + end + if InterruptReminder_Table['Styles'] == nil then + InterruptReminder_Table['Styles'] = { + ['Pixel'] = { name = 'Pixel', color = { 0.95, 0.95, 0.32, 1 }, N = 8, thickness = 2, border = true }, + ['Cast'] = { name = 'Cast', color = { 0.95, 0.95, 0.32, 1 }, N = 4, frequency = 0.125, scale = 1 }, + ['Glow'] = { name = 'Glow', color = { 0.95, 0.98, 0.65, 1 }, frequency = 0.125 }, + ['Proc'] = { name = 'Proc' } + } + end + if InterruptReminder_Table['SelectedStyle'] == nil then + InterruptReminder_Table['SelectedStyle'] = InterruptReminder_Table.Styles['Proc'] end - return list end ---- Get all spells from the player's current spell book except for the professions. +--- Read the cached spells table and get the name/description for each spell inside of it local function get_spellbook_spells() + local spells = IR_Table.SpellCache local list = {} - local numSpellTabs = GetNumSpellTabs() - local extraneousSpells = merge_two_tables(IR_Table.ExtraneousCCSpells[PlayerClass], - IR_Table.ExtraneousCCSpells[PlayerRace]) - - for tabIndex = 1, numSpellTabs do - local _, _, offset, numSpells = GetSpellTabInfo(tabIndex) - - for spellIndex = offset + 1, offset + numSpells do - local spellName, _, spellId = GetSpellBookItemName(spellIndex, BOOKTYPE_SPELL) - if spellName and not tContains(extraneousSpells, spellName) then - local spell = Spell:CreateFromSpellID(spellId) - - if spell:IsSpellEmpty() == false then - spell:ContinueOnSpellLoad(function() - local desc = spell:GetSpellDescription() - local descLower = string.lower(desc) - - for _, cc in pairs(IR_Table.CrownControlTypes) do - if string.find(descLower, cc, 1, true) then - printDebug("get_spellbook_spells: Inserted spell " .. spellName .. ".") - table.insert(list, { spellName = spellName, description = desc }) - break - end - end - end) - end - end - end + for _ = 1, #spells do + local name = C_Spell_GetSpellName(spells[_]) + local desc = C_Spell_GetSpellDescription(spells[_]) + table.insert(list, { spellID = spells[_], spellName = name, description = desc }) end return list end @@ -380,13 +334,13 @@ local function get_bosses() if bestMapForPlayer ~= nil then local encounters = C_EncounterJournal.GetEncountersOnMap(bestMapForPlayer) or {} - IR_Table.bossInserts = 0 + IR_Table.BossInserts = 0 for _, encounter in pairs(encounters) do for i = 1, 9 do local name = select(2, EJ_GetCreatureInfo(i, encounter.encounterID)) if name then InterruptReminder_Table.CurrentBossList[#InterruptReminder_Table.CurrentBossList + 1] = name - IR_Table.bossInserts = IR_Table.bossInserts + 1 + IR_Table.BossInserts = IR_Table.BossInserts + 1 else break end @@ -398,7 +352,7 @@ end ---Keep the boss list at the capacity of 30 local function truncate_boss_list() - local inserts = IR_Table.bossInserts + local inserts = IR_Table.BossInserts if #InterruptReminder_Table.CurrentBossList >= 30 then for _ = 1, inserts do @@ -411,36 +365,41 @@ end ---Options frame function IR_Table:CreateInterface(self) - IR_Table.panel.name = "Interrupt Reminder" - local about_mod_hover = CreateFrame("Frame", nil, IR_Table.panel) - local about_mod_frame = CreateFrame("Frame", nil, IR_Table.panel, 'BackdropTemplate') - local save_button = CreateFrame("Button", nil, IR_Table.panel, "UIPanelButtonTemplate") - local cancel_button = CreateFrame("Button", nil, IR_Table.panel, "UIPanelButtonTemplate") - local refresh_button = CreateFrame("Button", nil, IR_Table.panel, "UIPanelButtonTemplate") - local advanced_spell_mode = CreateFrame("CheckButton", nil, IR_Table.panel, "ChatConfigCheckButtonTemplate") - local debug_mode = CreateFrame("CheckButton", nil, IR_Table.panel, "ChatConfigCheckButtonTemplate") - local play_sound = CreateFrame("CheckButton", nil, IR_Table.panel, "ChatConfigCheckButtonTemplate") - local glow_texture_test = CreateFrame("Frame", nil, IR_Table.panel) - local proc_glow_checkbox = CreateFrame("CheckButton", nil, IR_Table.panel, "ChatConfigCheckButtonTemplate") - local glow_glow_checkbox = CreateFrame("CheckButton", nil, IR_Table.panel, "ChatConfigCheckButtonTemplate") - local pixel_glow_checkbox = CreateFrame("CheckButton", nil, IR_Table.panel, "ChatConfigCheckButtonTemplate") - local cast_glow_checkbox = CreateFrame("CheckButton", nil, IR_Table.panel, "ChatConfigCheckButtonTemplate") - local save_warning_text = IR_Table.panel:CreateFontString(nil, "OVERLAY", "GameTooltipText") - local r_slider = CreateFrame("Slider", "RSlider", IR_Table.panel, "OptionsSliderTemplate") - local g_slider = CreateFrame("Slider", "GSlider", IR_Table.panel, "OptionsSliderTemplate") - local b_slider = CreateFrame("Slider", "BSlider", IR_Table.panel, "OptionsSliderTemplate") - local a_slider = CreateFrame("Slider", "ASlider", IR_Table.panel, "OptionsSliderTemplate") - local n_slider = CreateFrame("Slider", "NSlider", IR_Table.panel, "OptionsSliderTemplate") - local t_slider = CreateFrame("Slider", "TSlider", IR_Table.panel, "OptionsSliderTemplate") - local f_slider = CreateFrame("Slider", "FSlider", IR_Table.panel, "OptionsSliderTemplate") - local s_slider = CreateFrame("Slider", "SSlider", IR_Table.panel, "OptionsSliderTemplate") + L = InterruptReminder_Localization + + local about_mod_hover = CreateFrame("Frame", nil, IR_Table.Panel) + local about_mod_frame = CreateFrame("Frame", nil, IR_Table.Panel, 'BackdropTemplate') + local save_button = CreateFrame("Button", nil, IR_Table.Panel, "UIPanelButtonTemplate") + local cancel_button = CreateFrame("Button", nil, IR_Table.Panel, "UIPanelButtonTemplate") + local refresh_button = CreateFrame("Button", nil, IR_Table.Panel, "UIPanelButtonTemplate") + local debug_mode = CreateFrame("CheckButton", nil, IR_Table.Panel, "ChatConfigCheckButtonTemplate") + local play_sound = CreateFrame("CheckButton", nil, IR_Table.Panel, "ChatConfigCheckButtonTemplate") + local glow_texture_test = CreateFrame("Frame", nil, IR_Table.Panel) + local proc_glow_checkbox = CreateFrame("CheckButton", nil, IR_Table.Panel, "ChatConfigCheckButtonTemplate") + local glow_glow_checkbox = CreateFrame("CheckButton", nil, IR_Table.Panel, "ChatConfigCheckButtonTemplate") + local pixel_glow_checkbox = CreateFrame("CheckButton", nil, IR_Table.Panel, "ChatConfigCheckButtonTemplate") + local cast_glow_checkbox = CreateFrame("CheckButton", nil, IR_Table.Panel, "ChatConfigCheckButtonTemplate") + local save_warning_text = IR_Table.Panel:CreateFontString(nil, "OVERLAY", "GameTooltipText") + local version_text = IR_Table.Panel:CreateFontString(nil, "OVERLAY", "GameTooltipText") + local r_slider = CreateFrame("Slider", "RSlider", IR_Table.Panel, "OptionsSliderTemplate") + local g_slider = CreateFrame("Slider", "GSlider", IR_Table.Panel, "OptionsSliderTemplate") + local b_slider = CreateFrame("Slider", "BSlider", IR_Table.Panel, "OptionsSliderTemplate") + local a_slider = CreateFrame("Slider", "ASlider", IR_Table.Panel, "OptionsSliderTemplate") + local n_slider = CreateFrame("Slider", "NSlider", IR_Table.Panel, "OptionsSliderTemplate") + local t_slider = CreateFrame("Slider", "TSlider", IR_Table.Panel, "OptionsSliderTemplate") + local f_slider = CreateFrame("Slider", "FSlider", IR_Table.Panel, "OptionsSliderTemplate") + local s_slider = CreateFrame("Slider", "SSlider", IR_Table.Panel, "OptionsSliderTemplate") local about_mod_text = about_mod_frame:CreateFontString(nil, "OVERLAY", "GameTooltipText") - local horizontal_line_top = IR_Table.panel:CreateLine() - local horizontal_line_bottom = IR_Table.panel:CreateLine() + local horizontal_line_top = IR_Table.Panel:CreateLine() + local horizontal_line_bottom = IR_Table.Panel:CreateLine() + + version_text:SetText(IR_Table.Mod_Version()) + version_text:SetPoint("BOTTOMLEFT", 8, 0) + version_text:Show() --- Create 30 checkboxes to be used local function create_checkboxes(frame) - CheckButtonFramePool = LibFramePool:CreateFramePool(30, "CheckButton", {nil, frame, "ChatConfigCheckButtonTemplate"}) + CheckButtonFramePool = LibFramePool:CreateFramePool(30, "CheckButton", { nil, frame, "ChatConfigCheckButtonTemplate" }) LibFramePool:SetOnClickScript(CheckButtonFramePool, function() if IR_Table.SaveHidden == true then save_warning_text:Show() @@ -492,7 +451,7 @@ function IR_Table:CreateInterface(self) local function generate_spell_glow_checkboxes() local checkboxes = { proc_glow_checkbox, glow_glow_checkbox, pixel_glow_checkbox, cast_glow_checkbox } local sliders = { r_slider, g_slider, b_slider, a_slider, n_slider, t_slider, f_slider, s_slider } - local names = { 'Proc', 'Glow', 'Pixel', 'Cast' } + local names = { L["PROC"], L["GLOW"], L["PIXEL"], L["CAST"] } local load_data = { 'glow', 'pixel', 'cast' } local x = 8 @@ -555,7 +514,7 @@ function IR_Table:CreateInterface(self) --- Create all sliders and fill in the relevant data for the them where appropriate, as well as the OnMouseUp script local function generate_sliders() local sliders = { r_slider, g_slider, b_slider, a_slider, n_slider, t_slider, f_slider, s_slider } - local text = { "Red", "Green", "Blue", "Alpha", "Lines", "Thickness", "Frequency", "Scale" } + local text = { L["RED"], L["GREEN"], L["BLUE"], L["ALPHA"], L["LINES"], L["THICKNESS"], L["FREQUENCY"], L["SCALE"] } local global_text = { "RSlider", "GSlider", "BSlider", "ASlider", "NSlider", "TSlider", "FSlider", "SSlider" } local y = -367 local scripts = { function() @@ -691,26 +650,26 @@ function IR_Table:CreateInterface(self) end end - --- If advanced options are enabled, set the name/description of checkbox at position i to that of that spell. If - --- the spell is present in SelectedSpells, set the checkbox to checked status. Hide all other checkboxes. + --- Set the name/description of checkbox at position i to that of that spell. If the spell is present in + --- SelectedSpells, set the checkbox to checked status. Hide all other checkboxes. local function pre_fill_checkboxes() - if self.IsInit == true then - local spells = self.Spells - local checkedSpells = self.SelectedSpells - - for i = 1, #spells do - local spell_name = spells[i].spellName - local spell_description = spells[i].description - local checkbox = CheckButtonFramePool[i].frame - checkbox.Text:SetText(spell_name) - checkbox.tooltip = spell_description - if tContains(checkedSpells, spell_name) then - checkbox:SetChecked(true) - else - checkbox:SetChecked(false) - end - checkbox:Show() + local spells = self.Spells + local checkedSpells = self.SelectedSpells + + for i = 1, #spells do + local spellID = spells[i].spellID + local spell_name = spells[i].spellName + local spell_description = spells[i].description + local checkbox = CheckButtonFramePool[i].frame + checkbox.Text:SetText(spell_name) + checkbox.tooltip = spell_description + checkbox:SetAttribute('SpellID', spellID) + if tContains(checkedSpells, spell_name) then + checkbox:SetChecked(true) + else + checkbox:SetChecked(false) end + checkbox:Show() end end @@ -742,39 +701,14 @@ function IR_Table:CreateInterface(self) end end - --- Set SelectedSpells to default interrupt spells. Hide all checkboxes and set them to unchecked. - local function remove_spell_checkboxes() - self.SelectedSpells = IR_Table.InterruptSpells[PlayerClass] - IR_Table.SelectedSpells = self.selectedSpells - for i = 1, 30 do - local checkbox = CheckButtonFramePool[i].frame - - checkbox:Hide() - checkbox:SetChecked(false) - end - IR_Table.TargetCanBeStunned = false - end - --- Create all header checkboxes and fill in the relevant data for the them where appropriate, as well as the --- OnClick script local function generate_header_checkboxes() - local checkboxes = { advanced_spell_mode, debug_mode , play_sound} - local text = { 'Enable Advanced Spell Selection', 'Enable Debugger', 'Enable Audio Cue' } - local tooltip = { 'Brings up a list of checkboxes for the user to select from for individual spells that the' .. - ' user would like to see highlighted.', 'Enable the debugger for event handling and' .. - ' other functions.', 'Play a sound when the target is casting an interruptible spell.' } + local checkboxes = { debug_mode, play_sound } + local text = { L['ENABLE_DEBUGGER'], L['ENABLE_AUDIO_CUE'] } + local tooltip = { 'Enable the debugger for event handling and other functions.', 'Play a sound when the target is casting an interruptible spell.' } local x = 8 local scripts = { function(checkbox) - if checkbox:GetChecked() == true then - self.IsInit = true - generate_spell_checkboxes(IR_Table.panel) - hide_and_show_frames(nil, { save_button, cancel_button, refresh_button }) - else - self.IsInit = false - remove_spell_checkboxes() - hide_and_show_frames({ save_button, cancel_button, refresh_button, save_warning_text }, nil) - end - end, function(checkbox) if checkbox:GetChecked() == true then self.Debug = true printInfo("Debugger has been enabled.") @@ -795,24 +729,15 @@ function IR_Table:CreateInterface(self) checkboxes[i].tooltip = tooltip[i] checkboxes[i]:SetPoint("TOPLEFT", x, -10) if i == 1 then - if self.IsInit == true then - checkboxes[i]:SetChecked(true) - generate_spell_glow_checkboxes(IR_Table.panel) - else - checkboxes[i]:SetChecked(false) - end - elseif i == 2 then if self.Debug == true then checkboxes[i]:SetChecked(true) else checkboxes[i]:SetChecked(false) end + elseif i == 2 then + checkboxes[i]:SetChecked(true) else - if self.PlaySound == true then - checkboxes[i]:SetChecked(true) - else - checkboxes[i]:SetChecked(false) - end + checkboxes[i]:SetChecked(false) end checkboxes[i]:SetScript("OnClick", scripts[i]) x = x + 240 @@ -838,12 +763,11 @@ function IR_Table:CreateInterface(self) IR_Table.SelectedSpells = copy end - --- Create all spell-related buttons and fill in the relevant data for the them where appropriate, as well as the - --- OnClick script + --- Create all spell-related buttons and fill in the relevant data for the them where appropriate, as well as the OnClick script local function generate_buttons() - local buttons = { save_button, refresh_button, cancel_button } - local text = { 'Save Spells', 'Refresh Spells', 'Cancel' } - local x = -100 + local buttons = { save_button, cancel_button } + local text = { L['SAVE_SPELLS'], L['CANCEL'] } + local x = -50 local scripts = { function() enable_and_disable_mouse_frames(buttons, nil) PlaySoundFile(567407, "SFX") @@ -853,20 +777,6 @@ function IR_Table:CreateInterface(self) IR_Table.SaveHidden = true end enable_and_disable_mouse_frames(nil, buttons) - end, function() - enable_and_disable_mouse_frames(buttons, nil) - PlaySoundFile(567407, "SFX") - self.SelectedSpells = IR_Table.InterruptSpells[PlayerClass] - IR_Table.SelectedSpells = self.selectedSpells - pre_fill_checkboxes() - IR_Table:GetAllCrowdControlSpells(self) - generate_spell_checkboxes(IR_Table.panel) - if IR_Table.SaveHidden == false then - save_warning_text:Hide() - IR_Table.SaveHidden = true - end - IR_Table:Hide_Glow(refresh_button) - enable_and_disable_mouse_frames(nil, buttons) end, function() enable_and_disable_mouse_frames(buttons, nil) PlaySoundFile(567407, "SFX") @@ -879,32 +789,18 @@ function IR_Table:CreateInterface(self) end } for i = 1, #buttons do - if self.IsInit == false then - buttons[i]:Hide() - else - buttons[i]:Show() - end + buttons[i]:Show() buttons[i]:SetText(text[i]) buttons[i]:SetWidth(100) buttons[i]:SetPoint("BOTTOM", x, 300) buttons[i]:SetScript("OnClick", scripts[i]) - if i == 2 then - buttons[i]:SetScript("OnEvent", function(_, event) - if event == 'ACTIVE_PLAYER_SPECIALIZATION_CHANGED' then - printInfo('Specialization changed! Please go to the mod settings to update your spell' .. - ' highlighting.') - IR_Table:Show_Glow(refresh_button) - end - end) - buttons[i]:RegisterEvent('ACTIVE_PLAYER_SPECIALIZATION_CHANGED') - end x = x + 100 end end --- If one of the checkboxes were checked but changes were not saved, this warning will appear. save_warning_text:Hide() - save_warning_text:SetText("You have unsaved changes!") + save_warning_text:SetText(L["UNSAVED_CHANGES"]) save_warning_text:SetTextColor(1.0, 0, 0, 1) save_warning_text:SetPoint("BOTTOM", 0, 325) @@ -952,28 +848,13 @@ function IR_Table:CreateInterface(self) about_mod_text:SetSize(650, 290) about_mod_text:SetJustifyH("LEFT") about_mod_text:SetJustifyV("TOP"); - about_mod_text:SetText("About the mod:\n\n" .. - "• If \"Enable Advanced Spell Selection\" is disabled, the default interrupt spells will be highlighted." .. - " In the case of your player class, it will be the spell(s): " - .. table.concat(IR_Table.InterruptSpells[PlayerClass], ',') .. ".\n\n" .. - "• If \"Enable Advanced Spell Selection\" is enabled, a list of checkboxes will appear for selection. A " .. - "special algorithm runs in the background to determine which spells are eligible to be considered Crowd " .. - "Control spells. If you noticed that a spell that should not be in the list is there, or one that should " .. - "be there is missing, please let the developer know as he plays only one class.\n\n" .. - "• If you notice that the list of available spells seems too short, or that only the spells that you previously" .. - " selected appear on the list of checkboxes, please click on the \"Refresh Spells\" button. World of" .. - " Warcraft does not always load all objects by the time this options menu is generated, so at the time the" .. - " algorithm ran, it's possible that some parts of the game were not available for the addon.\n\n" .. - "• If you have changed your specialization, you will get a notification in chat to remind you to refresh " .. - "your spells, as each specialization has their own unique Crowd Control spells.\n\n" .. - "• The debugger is mainly for developer use. Enabling it will cause a lot of chat noise.\n\n" .. - "• Please let the developer of any bugs you come across at either the GitHub repository, CurseForge or" .. - " WoWInterface.") + about_mod_text:SetText(L["ABOUT_MOD"]) about_mod_text:SetWordWrap(true) --- Pre-run certain scripts IR_Table:GetAllCrowdControlSpells(self) - create_checkboxes(IR_Table.panel) + create_checkboxes(IR_Table.Panel) + generate_spell_checkboxes() pre_fill_checkboxes() --- Horizontal line at the top @@ -1015,24 +896,16 @@ function IR_Table:CreateInterface(self) glow_glow_checkbox:EnableMouse(false) end - InterfaceOptions_AddCategory(IR_Table.panel, true) + Settings.RegisterAddOnCategory(category); end function InterruptReminder_OnAddonCompartmentClick() - InterfaceOptionsFrame_OpenToCategory(IR_Table.panel) + Settings.OpenToCategory(category.ID) end function IR_Table:GetAllCrowdControlSpells(self) self.Spells = {} - local copy = {} - - copy = get_spellbook_spells() - local specialization_spells = get_specialization_spells() - if specialization_spells ~= nil then - copy = merge_two_tables(copy, specialization_spells) - end - copy = remove_duplicates_from_nested_table(copy, 'spellName') - self.Spells = copy + self.Spells = get_spellbook_spells() end ---Algorithm that determines whether the currently selected target is a boss and reassigns IR_Table.TargetCanBeStunned @@ -1048,37 +921,35 @@ function IR_Table:IsTargetABoss(self) pull the target information from the previous target, even though GetUnitName should return nil at that point. Luckily, thin air cannot cast spells, so the rest of the addon will still function as intended. ]] - if self.IsInit then - local targetName = GetUnitName('target', false) + local targetName = GetUnitName('target', false) - -- Check to see if the user is currently in an instance - if is_in_instance() == true then + -- Check to see if the user is currently in an instance + if is_in_instance() == true then - -- Safety measure in case the dungeon boss names has not been defined as either list of bosses or empty - if bosses == nil then - IR_Table:Handle_ZoneChanged(self) - bosses = self.CurrentBossList - end + -- Safety measure in case the dungeon boss names has not been defined as either list of bosses or empty + if bosses == nil then + IR_Table:Handle_ZoneChanged(self) + bosses = self.CurrentBossList + end - -- Otherwise, check whether the target is a boss. If he's a boss, he's not stunnable. - if tContains(bosses, targetName) then - IR_Table.TargetCanBeStunned = false - printDebug("IsTargetABoss: Target is in boss list.") - else - IR_Table.TargetCanBeStunned = true - printDebug("IsTargetABoss: Target is not in boss list.") - end + -- Otherwise, check whether the target is a boss. If he's a boss, he's not stunnable. + if tContains(bosses, targetName) then + IR_Table.TargetCanBeStunned = false + printDebug("IsTargetABoss: Target is in boss list.") else - -- Otherwise, assume we're in the open world - local enemyRarity = UnitClassification('target') - -- In WoW, units that are world bosses, elites and rare elites are more likely than not stun immune. - if enemyRarity == 'worldboss' or enemyRarity == 'elite' or enemyRarity == 'rareelite' then - IR_Table.TargetCanBeStunned = false - printDebug("IsTargetABoss: Target has a frame, therefore cannot be stunned.") - else - printDebug("IsTargetABoss: Target has no frame, therefore can be stunned.") - IR_Table.TargetCanBeStunned = true - end + IR_Table.TargetCanBeStunned = true + printDebug("IsTargetABoss: Target is not in boss list.") + end + else + -- Otherwise, assume we're in the open world + local enemyRarity = UnitClassification('target') + -- In WoW, units that are world bosses, elites and rare elites are more likely than not stun immune. + if enemyRarity == 'worldboss' or enemyRarity == 'elite' or enemyRarity == 'rareelite' then + IR_Table.TargetCanBeStunned = false + printDebug("IsTargetABoss: Target has a frame, therefore cannot be stunned.") + else + printDebug("IsTargetABoss: Target has no frame, therefore can be stunned.") + IR_Table.TargetCanBeStunned = true end end end @@ -1086,31 +957,42 @@ end ---Return the button location of the spell from the cached ButtonCache. If there is no cache for the button or the --- slot has been updated, then find the location of the button and save it to ButtonCache. function IR_Table:FindSpellLocation(spell) - spell = string.lower(spell) local function find_button() local actionBars + local uiType - if IsAddOnLoaded("ElvUI") == true then + if C_AddOns_IsAddOnLoaded("ElvUI") == true then actionBars = IR_Table.ElvUIActionBars + uiType = 'ElvUI' else actionBars = IR_Table.ActionBars + uiType = 'Default' end for _, barName in ipairs(actionBars) do for i = 1, 12 do + local spellID + local actionSlot local button = _G[barName .. i] - local slot = button:GetAttribute('action') or button:GetPagedID() - - if HasAction(slot) then - local actionType, id, _, actionName = GetActionInfo(slot) - - if actionType == 'spell' then - actionName = GetSpellInfo(id) - end - - if actionName then - if string.lower(actionName) == spell then - IR_Table.ButtonCache[spell] = { button = button, slot = slot } + if button then + if uiType == 'Default' then + actionSlot = button['action'] + spellID = C_ActionBar.GetSpell(actionSlot) + if spellID then + local spellName = C_Spell_GetSpellName(spellID) + if spellName == spell then + IR_Table.ButtonCache[spell] = { button = button, slot = actionSlot } + end + end + elseif uiType == 'ElvUI' then + spellID = button['abilityID'] + actionSlot = button + if spellID then + local spellName = C_Spell_GetSpellName(spellID) + if spellName == spell then + actionSlot = button:GetAttribute('action') + IR_Table.ButtonCache[spell] = { button = button, slot = actionSlot } + end end end end @@ -1154,21 +1036,26 @@ function IR_Table:GetSpellCooldowns(spells_table, interrupt_only) if spells_table ~= nil then for i = 1, #spells_table do local spell = spells_table[i] - local _, _, _, _, _, _, spellID = GetSpellInfo(spell) - if type(spellID) == 'number' then - local isInSpellbook = IsPlayerSpell(spellID) - if isInSpellbook then - local start, duration = GetSpellCooldown(spellID) - if duration == 0 or duration <= 1.5 --[[Global Cooldown]] then - table.insert(readyToCast, { ['location'] = IR_Table:FindSpellLocation(spell) }) - else - -- Add a 0.01 overhead to ensure the spell gets highlighted after it is off cooldown - local calculatedTimeRemaining = (start + duration - GetTime()) + 0.01 - -- Safety check to ensure we don't save a negative number by mistake - if calculatedTimeRemaining > 0 then - -- Check that the spell will be ready before the spellcast from the target ends - if IR_Table.EndTime ~= nil and IR_Table.EndTime < ((start + duration) * 1000) then - table.insert(stillOnCooldown, { ['cooldown'] = calculatedTimeRemaining, ['location'] = IR_Table:FindSpellLocation(spell) }) + local spellInfo = C_Spell_GetSpellInfo(spell) + if spellInfo ~= nil then + local spellID = spellInfo.spellID + if type(spellID) == 'number' then + local isInSpellbook = IsPlayerSpell(spellID) + if isInSpellbook then + local spellCooldownInfo = C_Spell_GetSpellCooldown(spellID) + local duration = spellCooldownInfo.duration + local start = spellCooldownInfo.startTime + if duration == 0 or duration <= 1.5 --[[Global Cooldown]] then + table.insert(readyToCast, { ['location'] = IR_Table:FindSpellLocation(spell) }) + else + -- Add a 0.01 overhead to ensure the spell gets highlighted after it is off cooldown + local calculatedTimeRemaining = (start + duration - GetTime()) + 0.01 + -- Safety check to ensure we don't save a negative number by mistake + if calculatedTimeRemaining > 0 then + -- Check that the spell will be ready before the spellcast from the target ends + if IR_Table.EndTime ~= nil and IR_Table.EndTime < ((start + duration) * 1000) then + table.insert(stillOnCooldown, { ['cooldown'] = calculatedTimeRemaining, ['location'] = IR_Table:FindSpellLocation(spell) }) + end end end end @@ -1176,7 +1063,7 @@ function IR_Table:GetSpellCooldowns(spells_table, interrupt_only) end end end - printDebug("GetSpellCooldowns: " .. #readyToCast .. " spells ready to cast. " .. #stillOnCooldown .. + printDebug("C_Spell_GetSpellCooldown: " .. #readyToCast .. " spells ready to cast. " .. #stillOnCooldown .. " spells are still on cooldown.") return readyToCast, stillOnCooldown end @@ -1381,51 +1268,17 @@ end ---Handles the logic for when the player initially logs in or does a /reload function IR_Table:Handle_PlayerLogin() + + local spells = merge_two_tables(IR_Table.CCSpells[PlayerClass], IR_Table.RaceSpells[PlayerRace]) + for _ = 1, #spells do + C_Spell_RequestLoadSpellData(spells[_]) + end + if InterruptReminder_FirstLaunch == nil then InterruptReminder_FirstLaunch = true printInfo('First time loading the add-on? Type /irhelp for more information.') end - if InterruptReminder_Table == nil then - InterruptReminder_Table = {} - end - if InterruptReminder_Table.IsInit == nil then - InterruptReminder_Table.IsInit = false - end - if InterruptReminder_Table.Spells == nil then - InterruptReminder_Table.Spells = {} - end - if InterruptReminder_Table.SelectedSpells == nil then - InterruptReminder_Table.SelectedSpells = IR_Table.InterruptSpells[PlayerClass] - end - if InterruptReminder_Table.CurrentBossList == nil then - InterruptReminder_Table.CurrentBossList = {} - end - if InterruptReminder_Table.Debug == nil then - InterruptReminder_Table.Debug = false - end - if InterruptReminder_Table.PlaySound == nil then - InterruptReminder_Table.PlaySound = false - end - if InterruptReminder_Table.Styles == nil then - InterruptReminder_Table.Styles = { - ['Pixel'] = { name = 'Pixel', color = { 0.95, 0.95, 0.32, 1 }, N = 8, thickness = 2, border = true }, - ['Cast'] = { name = 'Cast', color = { 0.95, 0.95, 0.32, 1 }, N = 4, frequency = 0.125, scale = 1 }, - ['Glow'] = { name = 'Glow', color = { 0.95, 0.98, 0.65, 1 }, frequency = 0.125 }, - ['Proc'] = { name = 'Proc' } - } - end - if InterruptReminder_Table.SelectedStyle == nil then - InterruptReminder_Table.SelectedStyle = InterruptReminder_Table.Styles['Proc'] - end - - C_Timer.After(1, function() - IR_Table:CreateInterface(InterruptReminder_Table) - printDebug("Handle_PlayerLogin: Options interface created.") - end) - - -- Initial values for IR_Table - IR_Table.SelectedSpells = InterruptReminder_Table.SelectedSpells - IR_Table.SelectedGlow = InterruptReminder_Table.SelectedStyle + create_global_table() end function f:OnEvent(event, ...) @@ -1442,10 +1295,29 @@ function f:OnEvent(event, ...) if event == 'PLAYER_TARGET_CHANGED' then IR_Table:Handle_PlayerSwitchingTargets(IR_Table) end - if (event == 'ZONE_CHANGED_NEW_AREA' or event == 'ZONE_CHANGED_INDOORS' or event == 'ZONE_CHANGED') - and InterruptReminder_Table.IsInit == true then + if (event == 'ZONE_CHANGED_NEW_AREA' or event == 'ZONE_CHANGED_INDOORS' or event == 'ZONE_CHANGED') then IR_Table:Handle_ZoneChanged(InterruptReminder_Table) end + if event == 'SPELL_DATA_LOAD_RESULT' then + create_global_table() + local spellID, success = ... + local spells = merge_two_tables(IR_Table.CCSpells[PlayerClass], IR_Table.RaceSpells[PlayerRace]) + if success and tContains(spells, spellID) then + table.insert(IR_Table.SpellCache, spellID) + end + + IR_Table.SpellCache = remove_duplicates_from_array(IR_Table.SpellCache) -- Needed in case another mod requests same spell data + + if #IR_Table.SpellCache == #spells then + IR_Table.SelectedSpells = InterruptReminder_Table.SelectedSpells + IR_Table.SelectedGlow = InterruptReminder_Table.SelectedStyle + + + IR_Table:CreateInterface(InterruptReminder_Table) + f:UnregisterEvent('SPELL_DATA_LOAD_RESULT') + printDebug("Handle_PlayerLogin: Options interface created.") + end + end end f:RegisterEvent('PLAYER_LOGIN') @@ -1459,4 +1331,5 @@ f:RegisterEvent('PLAYER_TARGET_CHANGED') f:RegisterEvent('ZONE_CHANGED') f:RegisterEvent('ZONE_CHANGED_NEW_AREA') f:RegisterEvent('ZONE_CHANGED_INDOORS') +f:RegisterEvent('SPELL_DATA_LOAD_RESULT') f:SetScript('OnEvent', f.OnEvent) \ No newline at end of file diff --git a/InterruptReminder/InterruptReminder.toc b/InterruptReminder/InterruptReminder.toc index 4a5d15f..e591ec0 100644 --- a/InterruptReminder/InterruptReminder.toc +++ b/InterruptReminder/InterruptReminder.toc @@ -1,5 +1,5 @@ -## Interface: 100207 -## Version: 2.2.0 +## Interface: 110005 +## Version: 2.4.5 ## Title: Interrupt Reminder ## Author: AgentRG ## OptionalDeps: LibCustomGlow-1.0 @@ -10,4 +10,5 @@ Libs\LibCustomGlow-1.0\LibStub\LibStub.lua Libs\LibCustomGlow-1.0\LibCustomGlow-1.0.lua Libs\LibFramePool-1.0\LibFramePool-1.0.lua +Localization.lua InterruptReminder.lua \ No newline at end of file diff --git a/InterruptReminder/InterruptReminder_Cata.toc b/InterruptReminder/InterruptReminder_Cata.toc index 4ce900d..9017021 100644 --- a/InterruptReminder/InterruptReminder_Cata.toc +++ b/InterruptReminder/InterruptReminder_Cata.toc @@ -1,5 +1,5 @@ ## Interface: 40400 -## Version: 2.2.0 +## Version: 2.4.4 ## Title: Interrupt Reminder ## Author: AgentRG ## OptionalDeps: LibCustomGlow-1.0 diff --git a/InterruptReminder/Libs/LibCustomGlow-1.0/CHANGES.txt b/InterruptReminder/Libs/LibCustomGlow-1.0/CHANGES.txt index 4c3a621..6b0b4b6 100644 --- a/InterruptReminder/Libs/LibCustomGlow-1.0/CHANGES.txt +++ b/InterruptReminder/Libs/LibCustomGlow-1.0/CHANGES.txt @@ -1,12 +1,86 @@ -tag 648b01168be33c5ee2cebb19f893c13ed149f4d3 1.0.3 +tag e3d97d426caa6916c25fc3d2e605e440fe9eb1ae 1.0.4 Author: Benjamin Staneck -Date: Sat Aug 10 23:00:24 2019 +0200 +Date: Tue Jul 23 21:06:04 2024 +0200 -Tag as 1.0.3 +commit aa437b0d49632d878bb45828d2cf20207b90b207 +Author: Benjamin Staneck +Date: Tue Jul 23 21:05:48 2024 +0200 + + Update TOC and metadata + +commit 78aa5cd180ae4162e9e4eeba8b1d59e2d8fec1d9 +Author: Buds +Date: Thu May 30 13:24:36 2024 +0200 + + Replace ObjectPoolBaseMixin with a minimal implementation of pools + + TWW build 54935 stopped exposing ObjectPoolBaseMixin + +commit 5bc2b61a4342f1423fe45868987ea3716530e2fa +Author: enderneko +Date: Wed May 29 14:25:42 2024 +0800 + + Fix ProcGlow animation order + +commit 4cb491a9105aba01e97b8d2b7f2b258130c58437 +Author: Buds +Date: Sat Apr 13 02:55:42 2024 +0200 + + Fix division per zero error when alpha is set to zero + +commit a478475554b6b4e0ac12f48a1bc43b24754cb51d +Author: Buds +Date: Sat Jul 8 21:55:29 2023 +0200 + + Add "Proc Glow" support (#19) + +commit 25f4c8e5c25a5c2e8e670de1202686114b4caa22 +Author: Buds +Date: Sat Jun 17 10:20:12 2023 +0200 + + Fix rounding error leading to alpha value to be slightly over 1 + + Message: ...akAuras/Libs/LibCustomGlow-1.0/LibCustomGlow-1.0.lua:641: bad argument #1 to 'SetAlpha' (Usage: self:SetAlpha(alpha)) + +commit d830e939610a899cbc2d809d07a04c4aee9b2bc5 +Author: Benjamin Staneck +Date: Mon Nov 28 12:53:41 2022 +0100 + + Delete LICENSE.md -commit 6efc82df449dea8a78f7ab647c252afafc45c381 +commit 3b983444f80376002041f72b2c14849b769e174e Author: Benjamin Staneck -Date: Sat Aug 10 23:00:12 2019 +0200 +Date: Mon Nov 28 12:48:48 2022 +0100 + + Create LICENSE + +commit e685cd9babf607df8214d405dad59de878687b65 +Author: Benjamin Staneck +Date: Fri Nov 11 02:24:50 2022 +0100 + + Create LICENSE.md + +commit 357b94474886151e07572cc705c260c6c40302c3 +Author: Buds +Date: Wed Sep 7 18:19:38 2022 +0200 + + Fix Lua error in TexPoolResetter (#18) + +commit f15e6de03f59acff163c5d5f7d66fed5dbcbc897 +Author: Simpy +Date: Thu Feb 17 23:49:25 2022 -0500 + + fix AutoCastGlow on non-retail + +commit d0ac18a80d153399caf25bcc79278d6d6e83c78e +Author: d87 +Date: Mon Aug 10 16:00:02 2020 +0700 + + Fix division by zero + +commit 62612955401de40bd23698302be9e1843e793b65 +Author: Infus +Date: Fri May 1 16:30:35 2020 +0200 - bump minor version + Fix PixelGlow being in the wrong place for one frame diff --git a/InterruptReminder/Libs/LibCustomGlow-1.0/LICENSE b/InterruptReminder/Libs/LibCustomGlow-1.0/LICENSE new file mode 100644 index 0000000..aab9999 --- /dev/null +++ b/InterruptReminder/Libs/LibCustomGlow-1.0/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Benjamin Staneck + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/InterruptReminder/Libs/LibCustomGlow-1.0/LibCustomGlow-1.0.lua b/InterruptReminder/Libs/LibCustomGlow-1.0/LibCustomGlow-1.0.lua index fc88e97..d62bcbb 100644 --- a/InterruptReminder/Libs/LibCustomGlow-1.0/LibCustomGlow-1.0.lua +++ b/InterruptReminder/Libs/LibCustomGlow-1.0/LibCustomGlow-1.0.lua @@ -6,7 +6,7 @@ https://www.wowace.com/projects/libbuttonglow-1-0 -- luacheck: globals CreateFromMixins ObjectPoolMixin CreateTexturePool CreateFramePool local MAJOR_VERSION = "LibCustomGlow-1.0" -local MINOR_VERSION = 17 +local MINOR_VERSION = 19 if not LibStub then error(MAJOR_VERSION .. " requires LibStub.") end local lib, oldversion = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION) if not lib then return end @@ -34,20 +34,50 @@ lib.startList = {} lib.stopList = {} local GlowParent = UIParent - -local GlowMaskPool = CreateFromMixins(ObjectPoolMixin) -lib.GlowMaskPool = GlowMaskPool -local function MaskPoolFactory(maskPool) - return maskPool.parent:CreateMaskTexture() -end - -local MaskPoolResetter = function(maskPool,mask) - mask:Hide() - mask:ClearAllPoints() -end - -ObjectPoolMixin.OnLoad(GlowMaskPool,MaskPoolFactory,MaskPoolResetter) -GlowMaskPool.parent = GlowParent +local GlowMaskPool = { + createFunc = function(self) + return self.parent:CreateMaskTexture() + end, + resetFunc = function(self, mask) + mask:Hide() + mask:ClearAllPoints() + end, + AddObject = function(self, object) + local dummy = true + self.activeObjects[object] = dummy + self.activeObjectCount = self.activeObjectCount + 1 + end, + ReclaimObject = function(self, object) + tinsert(self.inactiveObjects, object) + self.activeObjects[object] = nil + self.activeObjectCount = self.activeObjectCount - 1 + end, + Release = function(self, object) + local active = self.activeObjects[object] ~= nil + if active then + self:resetFunc(object) + self:ReclaimObject(object) + end + return active + end, + Acquire = function(self) + local object = tremove(self.inactiveObjects) + local new = object == nil + if new then + object = self:createFunc() + self:resetFunc(object, new) + end + self:AddObject(object) + return object, new + end, + Init = function(self, parent) + self.activeObjects = {} + self.inactiveObjects = {} + self.activeObjectCount = 0 + self.parent = parent + end +} +GlowMaskPool:Init(GlowParent) local TexPoolResetter = function(pool,tex) local maskNum = tex:GetNumMaskTextures() @@ -93,14 +123,14 @@ lib.GlowFramePool = GlowFramePool local function addFrameAndTex(r,color,name,key,N,xOffset,yOffset,texture,texCoord,desaturated,frameLevel) key = key or "" - frameLevel = frameLevel or 8 + frameLevel = frameLevel or 8 if not r[name..key] then r[name..key] = GlowFramePool:Acquire() r[name..key]:SetParent(r) r[name..key].name = name..key end local f = r[name..key] - f:SetFrameLevel(r:GetFrameLevel()+frameLevel) + f:SetFrameLevel(r:GetFrameLevel()+frameLevel) f:SetPoint("TOPLEFT",r,"TOPLEFT",-xOffset+0.05,yOffset+0.05) f:SetPoint("BOTTOMRIGHT",r,"BOTTOMRIGHT",xOffset,-yOffset+0.05) f:Show() @@ -326,7 +356,7 @@ lib.startList["Pixel Glow"] = lib.PixelGlow_Start lib.stopList["Pixel Glow"] = lib.PixelGlow_Stop ---Autocast Glow Funcitons-- +--Autocast Glow Functions-- local function acUpdate(self,elapsed) local width,height = self:GetSize() if width ~= self.info.width or height ~= self.info.height then @@ -609,11 +639,19 @@ end local ButtonGlowTextures = {["spark"] = true,["innerGlow"] = true,["innerGlowOver"] = true,["outerGlow"] = true,["outerGlowOver"] = true,["ants"] = true} +local function noZero(num) + if num == 0 then + return 0.001 + else + return num + end +end + function lib.ButtonGlow_Start(r,color,frequency,frameLevel) if not r then return end - frameLevel = frameLevel or 8; + frameLevel = frameLevel or 8; local throttle if frequency and frequency > 0 then throttle = 0.25/frequency*0.01 @@ -628,8 +666,8 @@ function lib.ButtonGlow_Start(r,color,frequency,frameLevel) f:SetPoint("TOPLEFT", r, "TOPLEFT", -width * 0.2, height * 0.2) f:SetPoint("BOTTOMRIGHT", r, "BOTTOMRIGHT", width * 0.2, -height * 0.2) f.ants:SetSize(width*1.4*0.85, height*1.4*0.85) - AnimIn_OnFinished(f.animIn) - if f.animOut:IsPlaying() then + AnimIn_OnFinished(f.animIn) + if f.animOut:IsPlaying() then f.animOut:Stop() f.animIn:Play() end @@ -638,7 +676,7 @@ function lib.ButtonGlow_Start(r,color,frequency,frameLevel) for texture in pairs(ButtonGlowTextures) do f[texture]:SetDesaturated(nil) f[texture]:SetVertexColor(1,1,1) - local alpha = math.min(f[texture]:GetAlpha()/(f.color and f.color[4] or 1), 1) + local alpha = math.min(f[texture]:GetAlpha()/noZero(f.color and f.color[4] or 1), 1) f[texture]:SetAlpha(alpha) updateAlphaAnim(f, 1) end @@ -647,7 +685,7 @@ function lib.ButtonGlow_Start(r,color,frequency,frameLevel) for texture in pairs(ButtonGlowTextures) do f[texture]:SetDesaturated(1) f[texture]:SetVertexColor(color[1],color[2],color[3]) - local alpha = math.min(f[texture]:GetAlpha()/(f.color and f.color[4] or 1)*color[4], 1) + local alpha = math.min(f[texture]:GetAlpha()/noZero(f.color and f.color[4] or 1)*color[4], 1) f[texture]:SetAlpha(alpha) updateAlphaAnim(f,color and color[4] or 1) end @@ -757,7 +795,7 @@ local function InitProcGlow(f) local flipbookRepeat = f.ProcLoopAnim:CreateAnimation("FlipBook") flipbookRepeat:SetChildKey("ProcLoop") flipbookRepeat:SetDuration(1) - flipbookRepeat:SetOrder(1) + flipbookRepeat:SetOrder(0) flipbookRepeat:SetFlipBookRows(6) flipbookRepeat:SetFlipBookColumns(5) flipbookRepeat:SetFlipBookFrames(30) diff --git a/InterruptReminder/Libs/LibCustomGlow-1.0/LibCustomGlow-1.0.toc b/InterruptReminder/Libs/LibCustomGlow-1.0/LibCustomGlow-1.0.toc index 44e4f84..1e79c55 100644 --- a/InterruptReminder/Libs/LibCustomGlow-1.0/LibCustomGlow-1.0.toc +++ b/InterruptReminder/Libs/LibCustomGlow-1.0/LibCustomGlow-1.0.toc @@ -1,10 +1,10 @@ -## Interface: 80200 +## Interface: 110000, 110002 ## Title: Lib: CustomGlow ## Notes: Creates custom glow functions ## Author: deezo ## X-Category: Library ## X-License: BSD -## Version: 1.0.3 +## Version: 1.0.4 ## OptionalDeps: Masque LibStub\LibStub.lua diff --git a/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/LibStub.toc b/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/LibStub.toc index 036915c..6e4cca9 100644 --- a/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/LibStub.toc +++ b/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/LibStub.toc @@ -1,4 +1,4 @@ -## Interface: 80000 +## Interface: 90005 ## Title: Lib: LibStub ## Notes: Universal Library Stub ## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel diff --git a/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/tests/test.lua b/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/tests/test.lua new file mode 100644 index 0000000..276ddab --- /dev/null +++ b/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/tests/test.lua @@ -0,0 +1,41 @@ +debugstack = debug.traceback +strmatch = string.match + +loadfile("../LibStub.lua")() + +local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy +assert(lib) -- should return the library table +assert(not oldMinor) -- should not return the old minor, since it didn't exist + +-- the following is to create data and then be able to check if the same data exists after the fact +function lib:MyMethod() +end +local MyMethod = lib.MyMethod +lib.MyTable = {} +local MyTable = lib.MyTable + +local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail +assert(not newLib) -- should not return since out of date + +local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail +assert(not newLib) -- should not return since out of date + +local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version +assert(newLib) -- library table +assert(rawequal(newLib, lib)) -- should be the same reference as the previous +assert(newOldMinor == 1) -- should return the minor version of the previous version + +assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved +assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved + +local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number) +assert(newLib) -- library table +assert(newOldMinor == 2) -- previous version was 2 + +local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number) +assert(newLib) +assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string) + +local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string +assert(newLib) +assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string) \ No newline at end of file diff --git a/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/tests/test2.lua b/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/tests/test2.lua new file mode 100644 index 0000000..eae7172 --- /dev/null +++ b/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/tests/test2.lua @@ -0,0 +1,27 @@ +debugstack = debug.traceback +strmatch = string.match + +loadfile("../LibStub.lua")() + +for major, library in LibStub:IterateLibraries() do + -- check that MyLib doesn't exist yet, by iterating through all the libraries + assert(major ~= "MyLib") +end + +assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking +assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error. +local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib +assert(lib) -- check it exists +assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference + +assert(LibStub:NewLibrary("MyLib", 2)) -- create a new version + +local count=0 +for major, library in LibStub:IterateLibraries() do + -- check that MyLib exists somewhere in the libraries, by iterating through all the libraries + if major == "MyLib" then -- we found it! + count = count +1 + assert(rawequal(library, lib)) -- verify that the references are equal + end +end +assert(count == 1) -- verify that we actually found it, and only once diff --git a/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/tests/test3.lua b/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/tests/test3.lua new file mode 100644 index 0000000..30f7b94 --- /dev/null +++ b/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/tests/test3.lua @@ -0,0 +1,14 @@ +debugstack = debug.traceback +strmatch = string.match + +loadfile("../LibStub.lua")() + +local proxy = newproxy() -- non-string + +assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata +local success, ret = pcall(LibStub.GetLibrary, proxy, true) +assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered. + +assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it. + +assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement \ No newline at end of file diff --git a/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/tests/test4.lua b/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/tests/test4.lua new file mode 100644 index 0000000..43eb338 --- /dev/null +++ b/InterruptReminder/Libs/LibCustomGlow-1.0/LibStub/tests/test4.lua @@ -0,0 +1,41 @@ +debugstack = debug.traceback +strmatch = string.match + +loadfile("../LibStub.lua")() + + +-- Pretend like loaded libstub is old and doesn't have :IterateLibraries +assert(LibStub.minor) +LibStub.minor = LibStub.minor - 0.0001 +LibStub.IterateLibraries = nil + +loadfile("../LibStub.lua")() + +assert(type(LibStub.IterateLibraries)=="function") + + +-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created +LibStub.IterateLibraries = 123 + +loadfile("../LibStub.lua")() + +assert(LibStub.IterateLibraries == 123) + + +-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created +LibStub.minor = LibStub.minor + 0.0001 + +loadfile("../LibStub.lua")() + +assert(LibStub.IterateLibraries == 123) + + +-- Again with a huge number +LibStub.minor = LibStub.minor + 1234567890 + +loadfile("../LibStub.lua")() + +assert(LibStub.IterateLibraries == 123) + + +print("OK") \ No newline at end of file diff --git a/InterruptReminder/Libs/LibCustomGlow-1.0/README.md b/InterruptReminder/Libs/LibCustomGlow-1.0/README.md index 1d506b8..0e1f960 100644 --- a/InterruptReminder/Libs/LibCustomGlow-1.0/README.md +++ b/InterruptReminder/Libs/LibCustomGlow-1.0/README.md @@ -1,52 +1,63 @@ +# LibCustomGlow + Adds functions: -PixelGlow_Start(frame[, color[, N[, frequency[, length[, th[, xOffset[, yOffset[, border[ ,key]]]]]]]]) +## Pixel Glow + +- `PixelGlow_Start(frame[, color[, N[, frequency[, length[, th[, xOffset[, yOffset[, border[ ,key]]]]]]]])` Starts glow over target frame with set parameters: -frame - target frame to set glowing; -color - {r,g,b,a}, color of lines and opacity, from 0 to 1. Defaul value is {0.95, 0.95, 0.32, 1}; -N - number of lines. Defaul value is 8; -frequency - frequency, set to negative to inverse direction of rotation. Default value is 0.25; -length - length of lines. Default value depends on region size and number of lines; -th - thickness of lines. Default value is 2; -xOffset,yOffset - offset of glow relative to region border; -border - set to true to create border under lines; -key - key of glow, allows for multiple glows on one frame; -PixelGlow_Stop(frame[, key]) +- `frame` - target frame to set glowing; +- `color` - {r,g,b,a}, color of lines and opacity, from 0 to 1. Default value is {0.95, 0.95, 0.32, 1}; +- `N` - number of lines. Default value is 8; +- `frequency` - frequency, set to negative to inverse direction of rotation. Default value is 0.25; +- `length` - length of lines. Default value depends on region size and number of lines; +- `th` - thickness of lines. Default value is 2; +- `xOffset`,`yOffset` - offset of glow relative to region border; +- `border` - set to true to create border under lines; +- `key` - key of glow, allows for multiple glows on one frame; + +--- + +- `PixelGlow_Stop(frame[, key])` Stops glow with set key over target frame -  +## AutoCast Glow -AutoCastGlow_Start(frame[, color[, N[, frequency[, scale[, xOffset[, yOffset[, key]]]]]]]) +- `AutoCastGlow_Start(frame[, color[, N[, frequency[, scale[, xOffset[, yOffset[, key]]]]]]])` Starts glow over target frame with set parameters: -frame - target frame to set glowing; -color - {r,g,b,a}, color of particles and opacity, from 0 to 1. Defaul value is {0.95, 0.95, 0.32, 1}; -N - number of particle groups. Each group contains 4 particles. Defaul value is 4; -frequency - frequency, set to negative to inverse direction of rotation. Default value is 0.125; -scale - scale of particles; -xOffset,yOffset - offset of glow relative to region border; -key - key of glow, allows for multiple glows on one frame; -AutoCastGlow_Stop(frame[, key]) +- `frame` - target frame to set glowing; +- `color` - {r,g,b,a}, color of particles and opacity, from 0 to 1. Default value is {0.95, 0.95, 0.32, 1}; +- `N` - number of particle groups. Each group contains 4 particles. Default value is 4; +- `frequency` - frequency, set to negative to inverse direction of rotation. Default value is 0.125; +- `scale` - scale of particles; +- `xOffset`,`yOffset` - offset of glow relative to region border; +- `key` - key of glow, allows for multiple glows on one frame; - Stops glow with set key over target frame +--- -  +- `AutoCastGlow_Stop(frame[, key])` -Blizzard glow is based heavily on https://www.wowace.com/projects/libbuttonglow-1-0 +Stops glow with set key over target frame -ButtonGlow_Start(frame[, color[, frequency]]]) +## ButtonGlow + +Blizzard glow is based heavily on  + +- `ButtonGlow_Start(frame[, color[, frequency]]])` + +Starts glow over target frame with set parameters: - Starts glow over target frame with set parameters: +- `frame` - target frame to set glowing; +- `color` - {r,g,b,a}, color of particles and opacity, from 0 to 1. Default value is {0.95, 0.95, 0.32, 1}; +- `frequency` - frequency. Default value is 0.125; -frame - target frame to set glowing; -color - {r,g,b,a}, color of particles and opacity, from 0 to 1. Defaul value is {0.95, 0.95, 0.32, 1}; -frequency - frequency. Default value is 0.125; -ButtonGlow_Stop(frame) +--- -Stops glow over target frame +- `ButtonGlow_Stop(frame)` -  + Stops glow over target frame diff --git a/InterruptReminder/Libs/LibCustomGlow-1.0/cspell.json b/InterruptReminder/Libs/LibCustomGlow-1.0/cspell.json new file mode 100644 index 0000000..23171ff --- /dev/null +++ b/InterruptReminder/Libs/LibCustomGlow-1.0/cspell.json @@ -0,0 +1,12 @@ +{ + "version": "0.2", + "language": "en-US", + "ignorePaths": ["LICENSE"], + "words": [ + "Desaturated", + "issecurevariable", + "Leppkes", + "luacheck", + "tremove" + ] +} diff --git a/InterruptReminder/Localization.lua b/InterruptReminder/Localization.lua new file mode 100644 index 0000000..ef47575 --- /dev/null +++ b/InterruptReminder/Localization.lua @@ -0,0 +1,330 @@ +local L = {} + +local locale = GetLocale() + +if (locale == "enUS" or locale == 'enGB') then + L["VERSION"] = "Version" + L["SAVE_SPELLS"] = "Save Spells" + L["CANCEL"] = "Cancel" + L["ENABLE_DEBUGGER"] = "Enable Debugger" + L["ENABLE_AUDIO_CUE"] = "Enable Audio Cue" + L["PROC"] = "Proc" + L["GLOW"] = "Glow" + L["PIXEL"] = "Pixel" + L["CAST"] = "Cast" + L["RED"] = "Red" + L["GREEN"] = "Green" + L["BLUE"] = "Blue" + L["ALPHA"] = "Alpha" + L["LINES"] = "Lines" + L["SCALE"] = "Scale" + L["FREQUENCY"] = "Frequency" + L["THICKNESS"] = "Thickness" + L["UNSAVED_CHANGES"] = "You have unsaved changes!" + L["ABOUT_MOD"] = "About the mod:\n\n" .. + "• If the current mob is a boss, class interrupt spells will be highlighted instead of user selections.\n\n" .. + "• The debugger is mainly for developer use. Enabling it will cause a lot of chat noise.\n\n" .. + "• Please let the developer of any bugs you come across at either the GitHub repository, CurseForge or" .. + " WoWInterface.\n\n" .. + "• Please let the developer know if any spells are missing from the list of spells available for selection." +elseif locale == "deDE" then + L["VERSION"] = "Version" + L["SAVE_SPELLS"] = "Zauber speichern" + L["CANCEL"] = "Abbrechen" + L["ENABLE_DEBUGGER"] = "Debugger aktivieren" + L["ENABLE_AUDIO_CUE"] = "Audio-Hinweis aktivieren" + L["PROC"] = "Proc" + L["GLOW"] = "Leuchten" + L["PIXEL"] = "Pixel" + L["CAST"] = "Wirken" + L["RED"] = "Rot" + L["GREEN"] = "Grün" + L["BLUE"] = "Blau" + L["ALPHA"] = "Alpha" + L["LINES"] = "Linien" + L["SCALE"] = "Skalierung" + L["FREQUENCY"] = "Frequenz" + L["THICKNESS"] = "Dicke" + L["UNSAVED_CHANGES"] = "Sie haben ungespeicherte Änderungen!" + L["ABOUT_MOD"] = "Über das Mod:\n\n" .. + "• Wenn der aktuelle Gegner ein Boss ist, werden Klassenunterbrechungszauber hervorgehoben anstelle der vom Benutzer ausgewählten.\n\n" .. + "• Der Debugger ist hauptsächlich für Entwickler gedacht. Wenn er aktiviert ist, wird er viele Chatnachrichten erzeugen.\n\n" .. + "• Bitte melden Sie dem Entwickler alle Fehler, die Sie entweder im GitHub-Repository, auf CurseForge oder" .. + " WoWInterface finden.\n\n" .. + "• Bitte informieren Sie den Entwickler, wenn Zauber in der Liste der zur Auswahl stehenden Zauber fehlen." +elseif locale == "esMX" then + L["VERSION"] = "Versión" + L["SAVE_SPELLS"] = "Guardar hechizos" + L["CANCEL"] = "Cancelar" + L["ENABLE_DEBUGGER"] = "Habilitar depurador" + L["ENABLE_AUDIO_CUE"] = "Habilitar señal de audio" + L["PROC"] = "Proc" + L["GLOW"] = "Brillo" + L["PIXEL"] = "Píxel" + L["CAST"] = "Lanzar" + L["RED"] = "Rojo" + L["GREEN"] = "Verde" + L["BLUE"] = "Azul" + L["ALPHA"] = "Alfa" + L["LINES"] = "Líneas" + L["SCALE"] = "Escala" + L["FREQUENCY"] = "Frecuencia" + L["THICKNESS"] = "Grosor" + L["UNSAVED_CHANGES"] = "¡Tienes cambios no guardados!" + L["ABOUT_MOD"] = "Acerca del mod:\n\n" .. + "• Si el enemigo actual es un jefe, los hechizos de interrupción de clase se resaltarán en lugar de las selecciones del usuario.\n\n" .. + "• El depurador es principalmente para uso de desarrolladores. Activarlo generará mucho ruido en el chat.\n\n" .. + "• Por favor, informe al desarrollador de cualquier error que encuentre en el repositorio de GitHub, CurseForge o" .. + " WoWInterface.\n\n" .. + "• Por favor, informe al desarrollador si faltan hechizos en la lista de hechizos disponibles para selección." +elseif locale == 'ptBR' then + L["VERSION"] = "Versão" + L["SAVE_SPELLS"] = "Salvar Feitiços" + L["CANCEL"] = "Cancelar" + L["ENABLE_DEBUGGER"] = "Ativar Depurador" + L["ENABLE_AUDIO_CUE"] = "Ativar Sinal de Áudio" + L["PROC"] = "Proc" + L["GLOW"] = "Brilho" + L["PIXEL"] = "Pixel" + L["CAST"] = "Lançar" + L["RED"] = "Vermelho" + L["GREEN"] = "Verde" + L["BLUE"] = "Azul" + L["ALPHA"] = "Alfa" + L["LINES"] = "Linhas" + L["SCALE"] = "Escala" + L["FREQUENCY"] = "Frequência" + L["THICKNESS"] = "Espessura" + L["UNSAVED_CHANGES"] = "Você tem alterações não salvas!" + L["ABOUT_MOD"] = "Sobre o mod:\n\n" .. + "• Se o inimigo atual for um chefe, feitiços de interrupção de classe serão destacados em vez das seleções do usuário.\n\n" .. + "• O depurador é principalmente para uso dos desenvolvedores. Ativá-lo gerará muito ruído no chat.\n\n" .. + "• Informe ao desenvolvedor sobre qualquer erro que você encontrar, seja no repositório do GitHub, no CurseForge ou" .. + " no WoWInterface.\n\n" .. + "• Por favor, informe ao desenvolvedor se algum feitiço estiver faltando na lista de feitiços disponíveis para seleção." +elseif (locale == 'zhCN' or locale == 'enCN') then + L["VERSION"] = "版本" + L["SAVE_SPELLS"] = "保存法术" + L["CANCEL"] = "取消" + L["ENABLE_DEBUGGER"] = "启用调试器" + L["ENABLE_AUDIO_CUE"] = "启用音频提示" + L["PROC"] = "触发" + L["GLOW"] = "发光" + L["PIXEL"] = "像素" + L["CAST"] = "施法" + L["RED"] = "红色" + L["GREEN"] = "绿色" + L["BLUE"] = "蓝色" + L["ALPHA"] = "透明度" + L["LINES"] = "线条" + L["SCALE"] = "缩放" + L["FREQUENCY"] = "频率" + L["THICKNESS"] = "粗细" + L["UNSAVED_CHANGES"] = "你有未保存的更改!" + L["ABOUT_MOD"] = "关于此模组:\n\n" .. + "• 如果当前敌人是首领,类技能打断法术将被高亮显示,而不是用户选择的法术。\n\n" .. + "• 调试器主要用于开发者。启用后会在聊天中生成大量信息。\n\n" .. + "• 请将您发现的任何错误报告给开发者,可以通过 GitHub 仓库、CurseForge 或 WoWInterface。\n\n" .. + "• 如果有任何法术缺失,请通知开发者,将其加入可选法术列表。" +elseif locale == 'frFR' then + L["VERSION"] = "Version" + L["SAVE_SPELLS"] = "Sauvegarder les sorts" + L["CANCEL"] = "Annuler" + L["ENABLE_DEBUGGER"] = "Activer le débogueur" + L["ENABLE_AUDIO_CUE"] = "Activer le signal audio" + L["PROC"] = "Proc" + L["GLOW"] = "Lueur" + L["PIXEL"] = "Pixel" + L["CAST"] = "Incantation" + L["RED"] = "Rouge" + L["GREEN"] = "Vert" + L["BLUE"] = "Bleu" + L["ALPHA"] = "Alpha" + L["LINES"] = "Lignes" + L["SCALE"] = "Échelle" + L["FREQUENCY"] = "Fréquence" + L["THICKNESS"] = "Épaisseur" + L["UNSAVED_CHANGES"] = "Vous avez des modifications non sauvegardées !" + L["ABOUT_MOD"] = "À propos du mod :\n\n" .. + "• Si l'ennemi actuel est un boss, les sorts d'interruption de classe seront mis en évidence au lieu des sélections de l'utilisateur.\n\n" .. + "• Le débogueur est principalement destiné à l'usage des développeurs. L'activer génèrera beaucoup de messages dans le chat.\n\n" .. + "• Merci d'informer le développeur de tout bug rencontré via le dépôt GitHub, CurseForge ou" .. + " WoWInterface.\n\n" .. + "• Merci d'informer le développeur si des sorts sont manquants dans la liste des sorts disponibles." +elseif locale == 'itIT' then + L["VERSION"] = "Versione" + L["SAVE_SPELLS"] = "Salva incantesimi" + L["CANCEL"] = "Annulla" + L["ENABLE_DEBUGGER"] = "Abilita debugger" + L["ENABLE_AUDIO_CUE"] = "Abilita segnale audio" + L["PROC"] = "Proc" + L["GLOW"] = "Bagliore" + L["PIXEL"] = "Pixel" + L["CAST"] = "Lancio" + L["RED"] = "Rosso" + L["GREEN"] = "Verde" + L["BLUE"] = "Blu" + L["ALPHA"] = "Alpha" + L["LINES"] = "Linee" + L["SCALE"] = "Scala" + L["FREQUENCY"] = "Frequenza" + L["THICKNESS"] = "Spessore" + L["UNSAVED_CHANGES"] = "Hai modifiche non salvate!" + L["ABOUT_MOD"] = "Informazioni sul mod:\n\n" .. + "• Se il nemico attuale è un boss, gli incantesimi di interruzione della classe verranno evidenziati al posto delle selezioni dell'utente.\n\n" .. + "• Il debugger è principalmente per uso degli sviluppatori. Abilitarlo genererà molti messaggi in chat.\n\n" .. + "• Si prega di segnalare eventuali bug allo sviluppatore su GitHub, CurseForge o" .. + " WoWInterface.\n\n" .. + "• Si prega di informare lo sviluppatore se mancano incantesimi nell'elenco degli incantesimi disponibili." +elseif locale == 'ruRU' then + L["VERSION"] = "Версия" + L["SAVE_SPELLS"] = "Сохранить заклинания" + L["CANCEL"] = "Отмена" + L["ENABLE_DEBUGGER"] = "Включить отладчик" + L["ENABLE_AUDIO_CUE"] = "Включить аудиосигнал" + L["PROC"] = "Прок" + L["GLOW"] = "Свечение" + L["PIXEL"] = "Пиксель" + L["CAST"] = "Применить" + L["RED"] = "Красный" + L["GREEN"] = "Зелёный" + L["BLUE"] = "Синий" + L["ALPHA"] = "Альфа" + L["LINES"] = "Линии" + L["SCALE"] = "Масштаб" + L["FREQUENCY"] = "Частота" + L["THICKNESS"] = "Толщина" + L["UNSAVED_CHANGES"] = "У вас есть несохранённые изменения!" + L["ABOUT_MOD"] = "О моде:\n\n" .. + "• Если текущий противник является боссом, заклинания прерывания классов будут выделены вместо пользовательских выборов.\n\n" .. + "• Отладчик предназначен в основном для разработчиков. Включение его создаст много сообщений в чате.\n\n" .. + "• Пожалуйста, сообщайте разработчику о любых ошибках, найденных в репозитории GitHub, на CurseForge или" .. + " WoWInterface.\n\n" .. + "• Пожалуйста, сообщайте разработчику, если какие-либо заклинания отсутствуют в списке доступных для выбора." +elseif locale == 'ptPT' then + L["VERSION"] = "Versão" + L["SAVE_SPELLS"] = "Guardar Feitiços" + L["CANCEL"] = "Cancelar" + L["ENABLE_DEBUGGER"] = "Ativar Depurador" + L["ENABLE_AUDIO_CUE"] = "Ativar Sinal Áudio" + L["PROC"] = "Proc" + L["GLOW"] = "Brilho" + L["PIXEL"] = "Pixel" + L["CAST"] = "Lançar" + L["RED"] = "Vermelho" + L["GREEN"] = "Verde" + L["BLUE"] = "Azul" + L["ALPHA"] = "Alfa" + L["LINES"] = "Linhas" + L["SCALE"] = "Escala" + L["FREQUENCY"] = "Frequência" + L["THICKNESS"] = "Espessura" + L["UNSAVED_CHANGES"] = "Tens alterações não guardadas!" + L["ABOUT_MOD"] = "Sobre o mod:\n\n" .. + "• Se o inimigo atual for um chefe, os feitiços de interrupção de classe serão destacados em vez das seleções do utilizador.\n\n" .. + "• O depurador é principalmente para uso dos programadores. Ativá-lo gerará muito ruído no chat.\n\n" .. + "• Por favor, reporte qualquer erro que encontrar ao programador através do repositório GitHub, CurseForge ou" .. + " WoWInterface.\n\n" .. + "• Informe o programador se algum feitiço estiver em falta na lista de feitiços disponíveis para seleção." +elseif locale == 'koKR' then + L["VERSION"] = "버전" + L["SAVE_SPELLS"] = "주문 저장" + L["CANCEL"] = "취소" + L["ENABLE_DEBUGGER"] = "디버거 활성화" + L["ENABLE_AUDIO_CUE"] = "오디오 신호 활성화" + L["PROC"] = "발동" + L["GLOW"] = "광채" + L["PIXEL"] = "픽셀" + L["CAST"] = "시전" + L["RED"] = "빨강" + L["GREEN"] = "초록" + L["BLUE"] = "파랑" + L["ALPHA"] = "투명도" + L["LINES"] = "라인" + L["SCALE"] = "크기" + L["FREQUENCY"] = "빈도" + L["THICKNESS"] = "굵기" + L["UNSAVED_CHANGES"] = "저장되지 않은 변경 사항이 있습니다!" + L["ABOUT_MOD"] = "모드에 대하여:\n\n" .. + "• 현재 적이 보스라면, 사용자가 선택한 주문 대신 클래스의 차단 주문이 강조됩니다.\n\n" .. + "• 디버거는 주로 개발자용입니다. 활성화하면 채팅에 많은 메시지가 표시됩니다.\n\n" .. + "• GitHub 저장소, CurseForge 또는 WoWInterface에서 발견한 버그를 개발자에게 알려주십시오.\n\n" .. + "• 선택 가능한 주문 목록에 누락된 주문이 있으면 개발자에게 알려주십시오." +elseif locale == 'esES' then + L["VERSION"] = "Versión" + L["SAVE_SPELLS"] = "Guardar hechizos" + L["CANCEL"] = "Cancelar" + L["ENABLE_DEBUGGER"] = "Habilitar depurador" + L["ENABLE_AUDIO_CUE"] = "Habilitar señal de audio" + L["PROC"] = "Proc" + L["GLOW"] = "Brillo" + L["PIXEL"] = "Píxel" + L["CAST"] = "Lanzar" + L["RED"] = "Rojo" + L["GREEN"] = "Verde" + L["BLUE"] = "Azul" + L["ALPHA"] = "Alfa" + L["LINES"] = "Líneas" + L["SCALE"] = "Escala" + L["FREQUENCY"] = "Frecuencia" + L["THICKNESS"] = "Grosor" + L["UNSAVED_CHANGES"] = "¡Tienes cambios sin guardar!" + L["ABOUT_MOD"] = "Acerca del mod:\n\n" .. + "• Si el enemigo actual es un jefe, los hechizos de interrupción de clase se resaltarán en lugar de las selecciones del usuario.\n\n" .. + "• El depurador es principalmente para uso de desarrolladores. Activarlo generará mucho ruido en el chat.\n\n" .. + "• Por favor, informa de cualquier error que encuentres al desarrollador en el repositorio de GitHub, CurseForge o" .. + " WoWInterface.\n\n" .. + "• Por favor, informa al desarrollador si faltan hechizos en la lista de hechizos disponibles para selección." +elseif (locale == 'zhTW' or locale == 'enTW') then + L["VERSION"] = "版本" + L["SAVE_SPELLS"] = "保存法術" + L["CANCEL"] = "取消" + L["ENABLE_DEBUGGER"] = "啟用除錯器" + L["ENABLE_AUDIO_CUE"] = "啟用音效提示" + L["PROC"] = "觸發" + L["GLOW"] = "光暈" + L["PIXEL"] = "像素" + L["CAST"] = "施法" + L["RED"] = "紅色" + L["GREEN"] = "綠色" + L["BLUE"] = "藍色" + L["ALPHA"] = "透明度" + L["LINES"] = "線條" + L["SCALE"] = "比例" + L["FREQUENCY"] = "頻率" + L["THICKNESS"] = "粗細" + L["UNSAVED_CHANGES"] = "您有未保存的更改!" + L["ABOUT_MOD"] = "關於此模組:\n\n" .. + "• 如果當前敵人是首領,將會高亮顯示職業的打斷法術,而不是玩家選擇的法術。\n\n" .. + "• 除錯器主要供開發者使用。啟用後會在聊天中產生大量訊息。\n\n" .. + "• 請向開發者報告您發現的任何錯誤,您可以透過 GitHub 倉庫、CurseForge 或 WoWInterface。\n\n" .. + "• 如果法術列表中缺少任何可選法術,請通知開發者。" +else + L["VERSION"] = "Version" + L["SAVE_SPELLS"] = "Save Spells" + L["CANCEL"] = "Cancel" + L["ENABLE_DEBUGGER"] = "Enable Debugger" + L["ENABLE_AUDIO_CUE"] = "Enable Audio Cue" + L["PROC"] = "Proc" + L["GLOW"] = "Glow" + L["PIXEL"] = "Pixel" + L["CAST"] = "Cast" + L["RED"] = "Red" + L["GREEN"] = "Green" + L["BLUE"] = "Blue" + L["ALPHA"] = "Alpha" + L["LINES"] = "Lines" + L["SCALE"] = "Scale" + L["FREQUENCY"] = "Frequency" + L["THICKNESS"] = "Thickness" + L["UNSAVED_CHANGES"] = "You have unsaved changes!" + L["ABOUT_MOD"] = "About the mod:\n\n" .. + "• If the current mob is a boss, class interrupt spells will be highlighted instead of user selections.\n\n" .. + "• The debugger is mainly for developer use. Enabling it will cause a lot of chat noise.\n\n" .. + "• Please let the developer of any bugs you come across at either the GitHub repository, CurseForge or" .. + " WoWInterface.\n\n" .. + "• Please let the developer know if any spells are missing from the list of spells available for selection." +end + + +InterruptReminder_Localization = L \ No newline at end of file diff --git a/InterruptReminder/InterruptOrc.png b/InterruptReminder/_misc/InterruptOrc.png similarity index 100% rename from InterruptReminder/InterruptOrc.png rename to InterruptReminder/_misc/InterruptOrc.png diff --git a/InterruptReminder/description-image.png b/InterruptReminder/_misc/description-image.png similarity index 100% rename from InterruptReminder/description-image.png rename to InterruptReminder/_misc/description-image.png diff --git a/InterruptReminder/options.png b/InterruptReminder/_misc/options.png similarity index 100% rename from InterruptReminder/options.png rename to InterruptReminder/_misc/options.png diff --git a/LibFramePool-1.0/LibFramePool-1.0.toc b/LibFramePool-1.0/LibFramePool-1.0.toc index ef3ef97..134e8c7 100644 --- a/LibFramePool-1.0/LibFramePool-1.0.toc +++ b/LibFramePool-1.0/LibFramePool-1.0.toc @@ -1,10 +1,10 @@ -## Interface: 100206 +## Interface: 110005 +## Version: 1.0.3 ## Title: Lib: FramePool ## Notes: Library for handling pools of frames using table data type ## Author: AgentRG ## X-Category: Library ## X-License: BSD -## Version: 1.0.1 LibStub\LibStub.lua diff --git a/README.md b/README.md index 3da8b82..4105cd1 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # WoW-Addons -Repo for WoW addons that I have developed. +Repo for WoW addons that I have developed. This repo uses GitHub Actions to automatically create the ZIP files under `_zips` when changes are merged to main branch. * [Interrupt Reminder](InterruptReminder) - Highlight the class' interrupt abilities when the target is casting or channeling a spell that can diff --git a/TalkingHeadShut/TalkingHeadShut.toc b/TalkingHeadShut/TalkingHeadShut.toc index 576cc1f..dfbd9c7 100644 --- a/TalkingHeadShut/TalkingHeadShut.toc +++ b/TalkingHeadShut/TalkingHeadShut.toc @@ -1,5 +1,5 @@ -## Interface: 100206 -## Version: 1.0.2 +## Interface: 110005 +## Version: 1.0.4 ## Title: Talking Head - Shut! ## Author: AgentRG ## IconTexture: Interface\AddOns\TalkingHeadShut\icon.png diff --git a/ThreatTrack/ThreatTrack.toc b/ThreatTrack/ThreatTrack.toc index f595cd9..e225762 100644 --- a/ThreatTrack/ThreatTrack.toc +++ b/ThreatTrack/ThreatTrack.toc @@ -1,5 +1,5 @@ -## Interface: 100207 -## Version: 1.1.0 +## Interface: 110005 +## Version: 1.2.1 ## Title: Threat Track ## Author: AgentRG ## SavedVariablesPerCharacter: ThreatTrack_currentBossList, ThreatTrack_seconds diff --git a/ThreatTrack/Example.PNG b/ThreatTrack/_misc/Example.PNG similarity index 100% rename from ThreatTrack/Example.PNG rename to ThreatTrack/_misc/Example.PNG diff --git a/ThreatTrack/Explanation.png b/ThreatTrack/_misc/Explanation.png similarity index 100% rename from ThreatTrack/Explanation.png rename to ThreatTrack/_misc/Explanation.png diff --git a/ZoomerWoW/ZoomerWoW.lua b/ZoomerWoW/ZoomerWoW.lua index 739df06..38f924b 100644 --- a/ZoomerWoW/ZoomerWoW.lua +++ b/ZoomerWoW/ZoomerWoW.lua @@ -10,18 +10,45 @@ local mapping_table = { ['for real'] = 'fr', ['show off'] = 'flex', ['are the'] = 'be', + ['over with'] = 'ratioed', ['really use'] = 'crazy use', + ['looking for you'] = 'malding', + ['best friend'] = 'bestie', + ['step forward'] = 'pull up', ['i understand'] = 'say less', ['call out'] = 'clapback', - ['trying to'] = 'tryna' + ["don't know"] = 'dunno', + ['trying to'] = 'tryna', + ['shut up'] = "quit yappin'", + ['wrong with him'] = 'got bro down' }, single_words = { ['i'] = 'ya boi', + ['cross'] = 'hop', ['specialist'] = 'spesh', ['skills'] = 'skillz', ['skill'] = 'skillz', ["you'll"] = 'u', + ['home'] = 'Ohio', + ['place'] = 'Ohio', + ['she'] = 'step-sister', + ['places'] = 'Ohios', + ['city'] = 'Ohio', + ['village'] = 'gooncave', + ['heaven'] = 'Kai Cenant', ['about'] = 'bout', + ['stole'] = 'copped', + ['stop'] = 'edge', + ['archer'] = 'pogger', + ['archers'] = 'poggers', + ['stopping'] = 'edging', + ['line'] = 'grind', + ['courage'] = 'aura', + ['mistake'] = 'cap', + ['step'] = 'griddy', + ['call'] = 'shill', + ['honor'] = 'GOATED fr', + ['horse'] = 'whip', ["he's"] = 'he be', ['family'] = 'fam', ['transform'] = 'glow up', @@ -29,7 +56,13 @@ local mapping_table = { ['master'] = 'CEO', ['professor'] = 'CEO', ['boss'] = 'CEO', + ['soldier'] = 'simp', + ['soldiers'] = 'simps', + ['brothers'] = 'gooners', + ['brother'] = 'gooner', + ['trying'] = "tryin'", ['fan'] = 'stan', + ['father'] = 'Alpha', ['please'] = 'plz', ['stalker'] = 'stan', ['observer'] = 'stan', @@ -47,6 +80,7 @@ local mapping_table = { ['evil'] = 'big yikes', ['embarrassed'] = 'big yikes', ['fancy'] = 'boujee', + ['awake'] = 'woke', ['extravagant'] = 'boujee', ['lie'] = 'cap', ['attractive'] = 'snack', @@ -55,12 +89,18 @@ local mapping_table = { ['losing'] = "L'ing", ["i'm"] = "i'ma", ['looking'] = "lookin'", - ['good'] = 'bop', + ['king'] = 'short king', + ['good'] = 'based', ['stylish'] = 'drip', ['*sigh*'] = 'sheesh', ['sigh'] = 'sheesh', + ['rebels'] = 'rizzlers', + ['rebellion'] = 'rizz-bellion', + ['captured'] = 'copped', + ['capture'] = 'cop', ['mad'] = 'living rent free in my head', ['yes'] = 'bet', + ['offensive'] = 'big yikes', ['agree'] = 'bet', ['agreed'] = 'bet', ['okay'] = 'bet', @@ -73,8 +113,7 @@ local mapping_table = { ['charismatic'] = 'main character', ['charm'] = 'rizz', ['charisma'] = 'main character syndrome', - ['sister'] = 'sis', - ['brother'] = 'bro', + ['sister'] = 'step-sister', ['funny'] = 'sending me', ['amazing'] = 'slaps', ['amaze'] = 'slap', @@ -82,6 +121,7 @@ local mapping_table = { ['delicious'] = "bussin'", ['suspicious'] = 'sus', ['suspect'] = 'sus', + ['speaking'] = 'yapping', ['untrustworthy'] = 'sus', ['shady'] = 'sus', ['outfit'] = 'snatched', @@ -91,6 +131,7 @@ local mapping_table = { ['tiny'] = 'smol', ['greatest'] = 'G.O.A.T', ['hey'] = 'suh', + ['impressive'] = 'banger', ['hello'] = 'suh', ['family'] = 'fam', ['embarrassing '] = 'big yikes', @@ -112,26 +153,44 @@ local mapping_table = { ['acceptable'] = 'valid', ['throw'] = 'yeet', ['uncool'] = 'cheugy', + ['nice'] = 'chill', ['fierce'] = 'snatched', ['quite'] = 'low-key', + ['go'] = 'goon', ['moderate'] = 'low-key', ['there'] = 'thar', ['my'] = 'ma', ['opinion'] = 'take', + ['taking'] = 'thug-shaking', ['ouch'] = 'big yikes', ['dramatic'] = 'extra', ['positive'] = 'green flag', ['desire'] = 'goal', ['woman'] = 'girlboss', + ['girl'] = 'gyatt', + ['run'] = 'edge', + ['running'] = 'edging', ['very'] = 'highkey', ['warning'] = 'red flag', ['kill'] = 'slay', + ['ambush'] = 'mog', + ['boy'] = 'femboy', + ['mixed'] = 'maxxed', + ['walked'] = 'griddied', ['friend'] = 'fam', ['have'] = 'haz', + ['came'] = 'rizzed', ['welcome'] = 'yoooooo', - ['you'] = 'ya', + ['allies'] = 'rizzlers', + ['ally'] = 'rizzler', + ['you'] = 'mew', + ['the'] = 'thar', ['and'] = 'n', + ['dad'] = 'daddy', + ['damn'] = 'fanum', + ['thief'] = 'beta', ['your'] = 'ur', + ['safe'] = 'locked-in', ['are'] = 'be', ['sad'] = 'salty', ['grieve'] = 'salty' @@ -196,29 +255,34 @@ end local function get_process_set_text() local text local frame - if GreetingText:IsVisible() then - text = GreetingText:GetText() - frame = GreetingText - elseif GossipFrame.GreetingPanel:IsVisible() then - text = C_GossipInfo.GetText() - local parentFrame = GossipFrame.GreetingPanel.ScrollBox.ScrollTarget - for _, region in ipairs({parentFrame:GetChildren()}) do - if region:GetObjectType() == 'Frame' then - for _, region_2 in ipairs({region:GetRegions()}) do - if region_2:GetObjectType() == "FontString" and region_2:GetText() then - frame = region_2 - break + if C_AddOns.IsAddOnLoaded("Immersion") == true then + text = ImmersionFrame.TalkBox.TextFrame.Text:GetLine() + frame = ImmersionFrame.TalkBox.TextFrame.Text + else + if GreetingText:IsVisible() then + text = GreetingText:GetText() + frame = GreetingText + elseif GossipFrame.GreetingPanel:IsVisible() then + text = C_GossipInfo.GetText() + local parentFrame = GossipFrame.GreetingPanel.ScrollBox.ScrollTarget + for _, region in ipairs({parentFrame:GetChildren()}) do + if region:GetObjectType() == 'Frame' then + for _, region_2 in ipairs({region:GetRegions()}) do + if region_2:GetObjectType() == "FontString" and region_2:GetText() then + frame = region_2 + break + end end end end + elseif QuestInfoDescriptionText:IsVisible() then + text = QuestInfoDescriptionText:GetText() + frame = QuestInfoDescriptionText end - elseif QuestInfoDescriptionText:IsVisible() then - text = QuestInfoDescriptionText:GetText() - frame = QuestInfoDescriptionText end if text ~= nil and frame ~= nil then text = process_text(text) - frame:SetText(text) + frame:DisplayLine(text) end end diff --git a/ZoomerWoW/ZoomerWoW.toc b/ZoomerWoW/ZoomerWoW.toc index e488ae9..349503e 100644 --- a/ZoomerWoW/ZoomerWoW.toc +++ b/ZoomerWoW/ZoomerWoW.toc @@ -1,5 +1,5 @@ -## Interface: 100207 -## Version: 1.0.0 +## Interface: 110005 +## Version: 1.0.2 ## Title: Zoomer WoW ## Author: AgentRG diff --git a/ZoomerWoW/1.PNG b/ZoomerWoW/_misc/1.PNG similarity index 100% rename from ZoomerWoW/1.PNG rename to ZoomerWoW/_misc/1.PNG diff --git a/ZoomerWoW/2.PNG b/ZoomerWoW/_misc/2.PNG similarity index 100% rename from ZoomerWoW/2.PNG rename to ZoomerWoW/_misc/2.PNG