diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..dfe0770
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/Bindings.xml b/Bindings.xml
new file mode 100644
index 0000000..11ed7a1
--- /dev/null
+++ b/Bindings.xml
@@ -0,0 +1,11 @@
+
+
+ SMARTBUFF_Check(0);
+
+
+ SMARTBUFF_OptionsFrame_Toggle();
+
+
+ SMARTBUFF_ResetBuffTimers(0);
+
+
diff --git a/Icons/Deathknight.tga b/Icons/Deathknight.tga
new file mode 100644
index 0000000..6a337ff
Binary files /dev/null and b/Icons/Deathknight.tga differ
diff --git a/Icons/DeathknightPet.tga b/Icons/DeathknightPet.tga
new file mode 100644
index 0000000..d9512e0
Binary files /dev/null and b/Icons/DeathknightPet.tga differ
diff --git a/Icons/Demonhunter.tga b/Icons/Demonhunter.tga
new file mode 100644
index 0000000..9470d01
Binary files /dev/null and b/Icons/Demonhunter.tga differ
diff --git a/Icons/Druid.tga b/Icons/Druid.tga
new file mode 100644
index 0000000..c95ff25
Binary files /dev/null and b/Icons/Druid.tga differ
diff --git a/Icons/Hunter.tga b/Icons/Hunter.tga
new file mode 100644
index 0000000..537eedb
Binary files /dev/null and b/Icons/Hunter.tga differ
diff --git a/Icons/HunterPet.tga b/Icons/HunterPet.tga
new file mode 100644
index 0000000..4264c6e
Binary files /dev/null and b/Icons/HunterPet.tga differ
diff --git a/Icons/IconDisabled.tga b/Icons/IconDisabled.tga
new file mode 100644
index 0000000..978e877
Binary files /dev/null and b/Icons/IconDisabled.tga differ
diff --git a/Icons/IconEnabled.tga b/Icons/IconEnabled.tga
new file mode 100644
index 0000000..7098842
Binary files /dev/null and b/Icons/IconEnabled.tga differ
diff --git a/Icons/Mage.tga b/Icons/Mage.tga
new file mode 100644
index 0000000..847858b
Binary files /dev/null and b/Icons/Mage.tga differ
diff --git a/Icons/MiniMapButtonDisabled.tga b/Icons/MiniMapButtonDisabled.tga
new file mode 100644
index 0000000..67ccf66
Binary files /dev/null and b/Icons/MiniMapButtonDisabled.tga differ
diff --git a/Icons/MiniMapButtonEnabled.tga b/Icons/MiniMapButtonEnabled.tga
new file mode 100644
index 0000000..8ca07c4
Binary files /dev/null and b/Icons/MiniMapButtonEnabled.tga differ
diff --git a/Icons/Monk.tga b/Icons/Monk.tga
new file mode 100644
index 0000000..a67ae1a
Binary files /dev/null and b/Icons/Monk.tga differ
diff --git a/Icons/Paladin.tga b/Icons/Paladin.tga
new file mode 100644
index 0000000..5f71bb8
Binary files /dev/null and b/Icons/Paladin.tga differ
diff --git a/Icons/Priest.tga b/Icons/Priest.tga
new file mode 100644
index 0000000..d9b3d86
Binary files /dev/null and b/Icons/Priest.tga differ
diff --git a/Icons/Rogue.tga b/Icons/Rogue.tga
new file mode 100644
index 0000000..6338be6
Binary files /dev/null and b/Icons/Rogue.tga differ
diff --git a/Icons/Shaman.tga b/Icons/Shaman.tga
new file mode 100644
index 0000000..6aac4d4
Binary files /dev/null and b/Icons/Shaman.tga differ
diff --git a/Icons/Warlock.tga b/Icons/Warlock.tga
new file mode 100644
index 0000000..f187dcc
Binary files /dev/null and b/Icons/Warlock.tga differ
diff --git a/Icons/WarlockPet.tga b/Icons/WarlockPet.tga
new file mode 100644
index 0000000..bebaaed
Binary files /dev/null and b/Icons/WarlockPet.tga differ
diff --git a/Icons/Warrior.tga b/Icons/Warrior.tga
new file mode 100644
index 0000000..daef21a
Binary files /dev/null and b/Icons/Warrior.tga differ
diff --git a/Icons/empty.tga b/Icons/empty.tga
new file mode 100644
index 0000000..c21e7e1
Binary files /dev/null and b/Icons/empty.tga differ
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8e53607
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# SmartBuff Classic
+ Classic, SoM, TBC Classic and WOTLK
diff --git a/ReadMe.txt b/ReadMe.txt
new file mode 100644
index 0000000..3be805b
--- /dev/null
+++ b/ReadMe.txt
@@ -0,0 +1,60 @@
+***********************************************************************
+
+SmartBuff - Retail / Classic TBC / Seasons of Mastery / WOTLK versions by Codermik
+
+You will find me on:
+ Classic Server: Mik/Castanova/Amarantine/Paramedic on EU-Mirage Raceway
+ Retail: Challenger, Castanova, Paramedic and many others on EU-Aszune
+
+Join me on discord to offer feedback, report bugs and much more: https://discord.gg/R6EkZ94TKK
+
+If you would like to help support the addon development please see the addon options screen.
+
+***********************************************************************
+
+SmartBuff is a buff addon to cast buffs easily and quickly. All classes are supported.
+Bind a key and it checks if you, a party/raid member, also hunter and warlock pets, needs your buff and cast it.
+Use the options menu to configure it you like, as example: buffs, raid subgroups, pets, etc.
+Run the mod when ever you wish, if nothing is buffed, there is no penalty or cool down.
+
+Features:
+- Supports all classes
+- Supports EN/DE/FR clients
+- Checks buffs and rebuff you, raid/party members, raid/party pets
+- Setup your own buff templates (Solo, Party, Raid, Battleground, MC, Onyxia, BWL, AQ, ZG, Custom 1-5)
+- Auto switch templates
+- Individual setup for each buff
+- Supports group buffs: 'Gift of the Wild'/'Arcane Brilliance'/'Prayer of Fortitude'/'Prayer of Spirit', incl. group size and reagence check
+- Supports class buffs: all greater blessings of the Paladin
+- Supports self buffs
+- Supports weapon buffs (individual for main and off hand): Shaman, all poisons (Rogue), all stones and oils, incl. reagence check
+- Supports character level based buffs
+- Supports tracking abilities
+- Reminder if a buff is missing (Splash/chat/sound)
+- ReBuff Timer
+- Scrollwhell or only one key is needed
+- Fast and easy to use
+- FuBar support
+- Titan Panel support
+
+
+Usage:
+Minimap button:
+Left click: opens SmartBuff options frame
+Right click: enables/disables SmartBuff
+Alt-Left click: SmartDebuff
+Shift-Left click: move minimap button
+
+Chat:
+Type /sbm for options menu in game
+Type /sb [command] or /smartbuff [command] in game
+- cast buff
+toggle - Toggles SmartBuff On/Off
+menu - Show/hide options menu
+rbt - reset buff timers
+sdb - SmartDebuff
+rafp - reset all frame positions
+
+Options frame:
+Right click on buff checkbox: opens buff setup frame
+
diff --git a/SmartBuff-Classic.toc b/SmartBuff-Classic.toc
new file mode 100644
index 0000000..65110ac
--- /dev/null
+++ b/SmartBuff-Classic.toc
@@ -0,0 +1,20 @@
+## Interface: 11403
+## Title: SmartBuff |cffffffff(Classic)|r by |cff00ff00Codermik & Aeldra|r
+## Version: 21.11403
+## Author: |cff20d2ffCodermik (Mik / Castanova on EU-Mirage Raceway) & Aeldra|r (EU-Proudmoore)
+## Notes: Cast the most important buffs on you or party/raid members/pets. Use /sbm for options menu.
+## DefaultState: Enabled
+## LoadOnDemand: 0
+## Notes-deDE: Castet die wichtigsten Buffs auf dich selbst, Gruppe/Raid Mitglieder/Pets. Benutze /sbm um das Men� zu �ffnen
+## Notes-frFR: Cast the most important buffs on you or party/raid members/pets. Use /sbm for options menu.
+## SavedVariables: SMARTBUFF_OptionsGlobal
+## SavedVariablesPerCharacter: SMARTBUFF_Options, SMARTBUFF_Buffs
+
+lib\LibStub\LibStub.lua
+lib\CallbackHandler-1.0\CallbackHandler-1.0.lua
+lib\LibClassicDurations\LibClassicDurations.xml
+SmartBuff.globals.lua
+SmartBuff.xml
+
+lib\Broker_SmartBuff\LibDataBroker-1.1.lua
+lib\Broker_SmartBuff\Broker_SmartBuff.lua
diff --git a/SmartBuff-Wrath.toc b/SmartBuff-Wrath.toc
new file mode 100644
index 0000000..785fceb
--- /dev/null
+++ b/SmartBuff-Wrath.toc
@@ -0,0 +1,20 @@
+## Interface: 30400
+## Title: SmartBuff |cffffffff(Classic WOTLK)|r by |cff00ff00Codermik & Aeldra|r
+## Version: 21.30400
+## Author: |cff20d2ffCodermik (Mik / Castanova on EU-Mirage Raceway) & Aeldra|r (EU-Proudmoore)
+## Notes: Cast the most important buffs on you or party/raid members/pets. Use /sbm for options menu.
+## DefaultState: Enabled
+## LoadOnDemand: 0
+## Notes-deDE: Castet die wichtigsten Buffs auf dich selbst, Gruppe/Raid Mitglieder/Pets. Benutze /sbm um das Men� zu �ffnen
+## Notes-frFR: Cast the most important buffs on you or party/raid members/pets. Use /sbm for options menu.
+## SavedVariables: SMARTBUFF_OptionsGlobal
+## SavedVariablesPerCharacter: SMARTBUFF_Options, SMARTBUFF_Buffs
+
+lib\LibStub\LibStub.lua
+lib\CallbackHandler-1.0\CallbackHandler-1.0.lua
+lib\LibClassicDurations\LibClassicDurations.xml
+SmartBuff.globals.lua
+SmartBuff.xml
+
+lib\Broker_SmartBuff\LibDataBroker-1.1.lua
+lib\Broker_SmartBuff\Broker_SmartBuff.lua
diff --git a/SmartBuff.buffs.lua b/SmartBuff.buffs.lua
new file mode 100644
index 0000000..921e910
--- /dev/null
+++ b/SmartBuff.buffs.lua
@@ -0,0 +1,995 @@
+-------------------------------------------------------------------------------
+-- SmartBuff
+-- Originally created by Aeldra (EU-Proudmoore)
+-- Classic versions by Codermik (Mik/Castanova/Amarantine EU-Mirage Raceway)
+-- Discord: https://discord.gg/R6EkZ94TKK
+-- Cast the most important buffs on you, tanks or party/raid members/pets.
+-------------------------------------------------------------------------------
+
+local _;
+local S = SMARTBUFF_GLOBALS;
+
+SMARTBUFF_PLAYERCLASS = nil;
+SMARTBUFF_BUFFLIST = nil;
+
+-- Buff types
+SMARTBUFF_CONST_ALL = "ALL";
+SMARTBUFF_CONST_GROUP = "GROUP";
+SMARTBUFF_CONST_GROUPALL = "GROUPALL";
+SMARTBUFF_CONST_SELF = "SELF";
+SMARTBUFF_CONST_FORCESELF = "FORCESELF";
+SMARTBUFF_CONST_TRACK = "TRACK";
+SMARTBUFF_CONST_WEAPON = "WEAPON";
+SMARTBUFF_CONST_INV = "INVENTORY";
+SMARTBUFF_CONST_FOOD = "FOOD";
+SMARTBUFF_CONST_SCROLL = "SCROLL";
+SMARTBUFF_CONST_POTION = "POTION";
+SMARTBUFF_CONST_STANCE = "STANCE";
+SMARTBUFF_CONST_ITEM = "ITEM";
+SMARTBUFF_CONST_ITEMGROUP = "ITEMGROUP";
+SMARTBUFF_CONST_TOY = "TOY";
+
+S.CheckPet = "CHECKPET";
+S.CheckPetNeeded = "CHECKPETNEEDED";
+S.CheckFishingPole = "CHECKFISHINGPOLE";
+S.NIL = "x";
+S.Toybox = { };
+
+local function GetItems(items)
+ local t = { };
+ for _, id in pairs(items) do
+ local name = GetItemInfo(id);
+ if (name) then
+ --print("Item found: "..id..", "..name);
+ tinsert(t, name);
+ end
+ end
+ return t;
+end
+
+local function InsertItem(t, type, itemId, spellId, duration, link)
+ local item = GetItemInfo(itemId);
+ local spell = GetSpellInfo(spellId);
+ if (item and spell) then
+ --print("Item found: "..item..", "..spell);
+ tinsert(t, {item, duration, type, nil, spell, link});
+ end
+end
+
+local function AddItem(itemId, spellId, duration, link)
+ InsertItem(SMARTBUFF_SCROLL, SMARTBUFF_CONST_SCROLL, itemId, spellId, duration, link);
+end
+
+
+----------------------------------------------------------------------------------------------------------------------------------
+---
+--- Initialise Item List
+---
+----------------------------------------------------------------------------------------------------------------------------------
+function SMARTBUFF_InitItemList()
+
+ -- Reagents
+ SMARTBUFF_WILDBERRIES = GetItemInfo(17021); -- Wild Berries
+ SMARTBUFF_WILDTHORNROOT = GetItemInfo(17026); -- Wild Thornroot
+ SMARTBUFF_WILDQUILLVINE = GetItemInfo(22148); -- Wild Quillvine
+ SMARTBUFF_ARCANEPOWDER = GetItemInfo(17020); -- Arcane Powder
+ SMARTBUFF_HOLYCANDLE = GetItemInfo(17028); -- Holy Candle
+ SMARTBUFF_SACREDCANDLE = GetItemInfo(17029); -- Sacred Candle
+ SMARTBUFF_SYMBOLOFKINGS = GetItemInfo(21177); -- Symbol of Kings
+
+ -- Stones and oils etc.
+ SMARTBUFF_LESSERMANAOIL = GetItemInfo(20747); -- Lesser Mana Oil
+ SMARTBUFF_BRILLIANTMANAOIL = GetItemInfo(20748); -- Brilliant Mana Oil
+ SMARTBUFF_BRILLIANTWIZARDOIL = GetItemInfo(20749); -- Brilliant Wizard Oil
+ SMARTBUFF_SUPERIORMANAOIL = GetItemInfo(22521); -- Brilliant Mana Oil
+ SMARTBUFF_SUPERIORWIZARDOIL = GetItemInfo(22522); -- Superior Wizard Oil
+ SMARTBUFF_OILOFIMMOLATION = GetItemInfo(8956); -- Oil of Immolation
+ SMARTBUFF_SOLIDWSTONE = GetItemInfo(7965); -- Solid Weighstone
+ SMARTBUFF_SOLIDSSTONE = GetItemInfo(7964); -- Solid Sharpening Stone
+ SMARTBUFF_ELEMENTALSSTONE = GetItemInfo(18262); -- Solid Weightstone
+ SMARTBUFF_ADAMANTITEWSTONE = GetItemInfo(28421); -- Adamantite Weightstone
+ SMARTBUFF_ADAMANTITESSTONE = GetItemInfo(23529); -- Adamantite Sharpening Stone
+ SMARTBUFF_HEAVYWSTONE = GetItemInfo(3241); -- Heavy Weighstone
+ SMARTBUFF_HEAVYSSTONE = GetItemInfo(2871); -- Heavy Sharpening Stone
+ SMARTBUFF_WEIGHSTONE = GetItemInfo(28420); -- Fel Weighstone
+ SMARTBUFF_FELSHARPENINGSTONE = GetItemInfo(23528); -- Greater Rune of Warding
+
+ -- Poisons (some
+ SMARTBUFF_INSTANTPOISON1 = GetItemInfo(6947); -- Instant Poison
+ SMARTBUFF_INSTANTPOISON2 = GetItemInfo(6949); -- Instant Poison II
+ SMARTBUFF_INSTANTPOISON3 = GetItemInfo(6950); -- Instant Poison III
+ SMARTBUFF_INSTANTPOISON4 = GetItemInfo(8926); -- Instant Poison IV
+ SMARTBUFF_INSTANTPOISON5 = GetItemInfo(8927); -- Instant Poison V
+ SMARTBUFF_INSTANTPOISON6 = GetItemInfo(8928); -- Instant Poison VI
+ SMARTBUFF_INSTANTPOISON7 = GetItemInfo(21927); -- Instant Poison VII
+ SMARTBUFF_WOUNDPOISON1 = GetItemInfo(10918); -- Wound Poison
+ SMARTBUFF_WOUNDPOISON2 = GetItemInfo(10920); -- Wound Poison II
+ SMARTBUFF_WOUNDPOISON3 = GetItemInfo(10921); -- Wound Poison III
+ SMARTBUFF_WOUNDPOISON4 = GetItemInfo(10922); -- Wound Poison IV
+ SMARTBUFF_WOUNDPOISON5 = GetItemInfo(22055); -- Wound Poison V
+ SMARTBUFF_MINDPOISON1 = GetItemInfo(5237); -- Mind-numbing Poison
+ SMARTBUFF_MINDPOISON2 = GetItemInfo(6951); -- Mind-numbing Poison II
+ SMARTBUFF_MINDPOISON3 = GetItemInfo(9186); -- Mind-numbing Poison III
+ SMARTBUFF_DEADLYPOISON1 = GetItemInfo(2892); -- Deadly Poison
+ SMARTBUFF_DEADLYPOISON2 = GetItemInfo(2893); -- Deadly Poison II
+ SMARTBUFF_DEADLYPOISON3 = GetItemInfo(8984); -- Deadly Poison III
+ SMARTBUFF_DEADLYPOISON4 = GetItemInfo(8985); -- Deadly Poison IV
+ SMARTBUFF_DEADLYPOISON5 = GetItemInfo(20844); -- Deadly Poison V
+ SMARTBUFF_DEADLYPOISON6 = GetItemInfo(22053); -- Deadly Poison VI
+ SMARTBUFF_DEADLYPOISON7 = GetItemInfo(22054); -- Deadly Poison VII
+ SMARTBUFF_CRIPPLINGPOISON1 = GetItemInfo(3775); -- Crippling Poison
+ SMARTBUFF_CRIPPLINGPOISON2 = GetItemInfo(3776); -- Crippling Poison II
+ SMARTBUFF_ANESTHETICPOISON1 = GetItemInfo(21835); -- Anesthetic Poison
+
+ -- Food
+ SMARTBUFF_GOLDENFISHSTICKS_ITEM = GetItemInfo(27666); -- Golden Fish Sticks
+ SMARTBUFF_FISHERMANSFEAST_ITEM = GetItemInfo(33052); -- Fisherman's Feast
+ SMARTBUFF_SKULLFISHSOUP_ITEM = GetItemInfo(33825); -- Skullfish Soup
+ SMARTBUFF_SPICYHOTTALBUK_ITEM = GetItemInfo(33872); -- Spicy Hot Talbuk
+ SMARTBUFF_BLACKENEDBASILISK_ITEM = GetItemInfo(27657); -- Blackened Basilisk
+ SMARTBUFF_BLACKENEDSPOREFISH_ITEM = GetItemInfo(27663); -- Blackened Sporefish
+ SMARTBUFF_BUZZARDBITES_ITEM = GetItemInfo(27651); -- Buzzard Bites
+ SMARTBUFF_CLAMBAR_ITEM = GetItemInfo(30155); -- Clam Bar
+ SMARTBUFF_CRUNCHYSERPENT_ITEM = GetItemInfo(31673); -- Crunchy Serpent
+ SMARTBUFF_FELTAILDELIGHT_ITEM = GetItemInfo(27662); -- Feltail Delight
+ SMARTBUFF_GRILLEDMUDFISH_ITEM = GetItemInfo(27664); -- Grilled Mudfish
+ SMARTBUFF_HELBOARBACON_ITEM = GetItemInfo(29292); -- Hellboar Bacon
+ SMARTBUFF_MOKNATHAKSHORTRIBS_ITEM = GetItemInfo(31672); -- Mok'Nathal Shortribs
+ SMARTBUFF_POACHEDBLUEFISH_ITEM = GetItemInfo(27665); -- Poached Bluefish
+ SMARTBUFF_RAVAGERDOG_ITEM = GetItemInfo(27655); -- Ravager Dog
+ SMARTBUFF_ROASTEDCLEFTHOOF_ITEM = GetItemInfo(27658); -- Roasted Clefthoof
+ SMARTBUFF_SPICYCRAWDAD_ITEM = GetItemInfo(27667); -- Spicy Crawdad
+ SMARTBUFF_TALBUKSTEAK_ITEM = GetItemInfo(27660); -- Talbuk Steak
+ SMARTBUFF_WARPBURGER_ITEM = GetItemInfo(27659); -- Warp Burger
+ SMARTBUFF_CHARREDBEARKABOBS_ITEM = GetItemInfo(35563); -- Charred Bear Kabobs
+ SMARTBUFF_ORONOKSTUBERSPELL_ITEM = GetItemInfo(30361); -- Oronok's Tuber of Spell Power
+ SMARTBUFF_ORONOKSTUBERAGILITY_ITEM = GetItemInfo(30358); -- Oronok's Tuber of Agility
+ SMARTBUFF_ORONOKSTUBERHEALS_ITEM = GetItemInfo(30357); -- Oronok's Tuber of Healing
+ SMARTBUFF_ORONOKSTUBERSTRENGTH_ITEM = GetItemInfo(30359); -- Oronok's Tuber of Strength
+ SMARTBUFF_HOTAPPLECIDER_ITEM = GetItemInfo(34411); -- Hot Apple Cider
+ SMARTBUFF_SKYGUARDRATIONS_ITEM = GetItemInfo(32721); -- Skyguard Rations
+ SMARTBUFF_DIRGESKICKINCHOPS_ITEM = GetItemInfo(21023); -- Dirge's Kickin' Chimaerok Chops
+ SMARTBUFF_JUICYBEARBURGER_ITEM = GetItemInfo(35565); -- Juicy Bear Burger
+ SMARTBUFF_NIGHTFINSOUP_ITEM = GetItemInfo(13931); -- Nightfin Soup
+
+
+ -- Conjured mage food / Water IDs
+ S.FoodMage = GetItems({587, 597, 990, 6129, 10144, 10145, 28612, 33717 });
+ S.WaterMage = GetItems({5504, 5505, 5506, 6127, 10138, 10139, 10140, 37420, 27090});
+ S.MageManaBuscuit = ({34062});
+
+ -- Scrolls
+ SMARTBUFF_SOAGILITY1 = GetItemInfo(3012); -- Scroll of Agility I
+ SMARTBUFF_SOAGILITY2 = GetItemInfo(1477); -- Scroll of Agility II
+ SMARTBUFF_SOAGILITY3 = GetItemInfo(4425); -- Scroll of Agility III
+ SMARTBUFF_SOAGILITY4 = GetItemInfo(10309); -- Scroll of Agility IV
+ SMARTBUFF_SOAGILITY5 = GetItemInfo(27498); -- Scroll of Agility V
+ SMARTBUFF_SOINTELLECT1 = GetItemInfo(955); -- Scroll of Intellect I
+ SMARTBUFF_SOINTELLECT2 = GetItemInfo(2290); -- Scroll of Intellect II
+ SMARTBUFF_SOINTELLECT3 = GetItemInfo(4419); -- Scroll of Intellect III
+ SMARTBUFF_SOINTELLECT4 = GetItemInfo(10308); -- Scroll of Intellect IV
+ SMARTBUFF_SOINTELLECT5 = GetItemInfo(27499); -- Scroll of Intellect V
+ SMARTBUFF_SOSTAMINA1 = GetItemInfo(1180); -- Scroll of Stamina I
+ SMARTBUFF_SOSTAMINA2 = GetItemInfo(1711); -- Scroll of Stamina II
+ SMARTBUFF_SOSTAMINA3 = GetItemInfo(4422); -- Scroll of Stamina III
+ SMARTBUFF_SOSTAMINA4 = GetItemInfo(10307); -- Scroll of Stamina IV
+ SMARTBUFF_SOSTAMINA5 = GetItemInfo(27502); -- Scroll of Stamina V
+ SMARTBUFF_SOSPIRIT1 = GetItemInfo(1181); -- Scroll of Spirit I
+ SMARTBUFF_SOSPIRIT2 = GetItemInfo(1712); -- Scroll of Spirit II
+ SMARTBUFF_SOSPIRIT3 = GetItemInfo(4424); -- Scroll of Spirit III
+ SMARTBUFF_SOSPIRIT4 = GetItemInfo(10306); -- Scroll of Spirit IV
+ SMARTBUFF_SOSPIRIT5 = GetItemInfo(27501); -- Scroll of Spirit V
+ SMARTBUFF_SOSTRENGHT1 = GetItemInfo(954); -- Scroll of Strength I
+ SMARTBUFF_SOSTRENGHT2 = GetItemInfo(2289); -- Scroll of Strength II
+ SMARTBUFF_SOSTRENGHT3 = GetItemInfo(4426); -- Scroll of Strength III
+ SMARTBUFF_SOSTRENGHT4 = GetItemInfo(10310); -- Scroll of Strength IV
+ SMARTBUFF_SOSTRENGHT5 = GetItemInfo(27503); -- Scroll of Strength V
+ SMARTBUFF_SOPROTECTION1 = GetItemInfo(3013); -- Scroll of Protection I
+ SMARTBUFF_SOPROTECTION2 = GetItemInfo(1478); -- Scroll of Protection II
+ SMARTBUFF_SOPROTECTION3 = GetItemInfo(4421); -- Scroll of Protection III
+ SMARTBUFF_SOPROTECTION4 = GetItemInfo(10305); -- Scroll of Protection IV
+ SMARTBUFF_SOPROTECTION5 = GetItemInfo(27500); -- Scroll of Protection IV
+
+ -- Potions / Elixirs / Flasks Items
+ SMARTBUFF_ADEPTELIXIR_ITEM = GetItemInfo(28103); -- Adept's Elixir
+ SMARTBUFF_MAJORDEFENSE_ITEM = GetItemInfo(22834); -- Major Defense
+ SMARTBUFF_MAJORAGILITY_ITEM = GetItemInfo(22831); -- Major Agility
+ SMARTBUFF_DRAENICWISDOM_ITEM = GetItemInfo(32067); -- Draenic Wisdom
+ SMARTBUFF_MAJORFROSTPOWER_ITEM = GetItemInfo(22827); -- Major Frost Power
+ SMARTBUFF_EARTHEN_ITEM = GetItemInfo(32063); -- Earthen Elixir
+ SMARTBUFF_MASTERY_ITEM = GetItemInfo(28104); -- Elixir of Mastery
+ SMARTBUFF_CAMOUFLAGE_ITEM = GetItemInfo(22823); -- Elixir of Camouflage
+ SMARTBUFF_HEALINGPOWER_ITEM = GetItemInfo(22825); -- Elixir of Healing Power
+ SMARTBUFF_MAJORFORTITUDE_ITEM = GetItemInfo(32062); -- Elixir of Major Fortitude
+ SMARTBUFF_MAJORSTRENGTH_ITEM = GetItemInfo(22824); -- Elixir of Major Strength
+ SMARTBUFF_ONSLAUGHTELIXIR_ITEM = GetItemInfo(28102); -- Onslaught Elixir
+ SMARTBUFF_GREATERARCANE_ITEM = GetItemInfo(13454); -- Greater Arcane
+ SMARTBUFF_MONGOOSEELIXIR_ITEM = GetItemInfo(13452); -- Elixir of Mongoose
+ SMARTBUFF_BRUTEFORCE_ITEM = GetItemInfo(13453); -- Elixir of Brute Force
+ SMARTBUFF_SAGESELIXIR_ITEM = GetItemInfo(13447); -- Elixir of Sages
+ SMARTBUFF_SUPERIORDEFENSE_ITEM = GetItemInfo(13445); -- Elixir of Superior Defense
+ SMARTBUFF_DEMONSLAYING_ITEM = GetItemInfo(9224); -- Elixir of Demon Slaying
+ SMARTBUFF_MAJORFIREPOWER_ITEM = GetItemInfo(22833); -- Elixir of Major Fire Power
+ SMARTBUFF_GREATERFIREPOWER_ITEM = GetItemInfo(21546); -- Elixir of Greater Fire Power
+ SMARTBUFF_SHADOWPOWER_ITEM = GetItemInfo(9264); -- Elixir of Shadow Power
+ SMARTBUFF_GIANTSELIXIR_ITEM = GetItemInfo(9206); -- Elixir of Giants
+ SMARTBUFF_GREATERAGILITY_ITEM = GetItemInfo(9187); -- Elixir of Greater Agility
+ SMARTBUFF_GIFTOFARTHAS_ITEM = GetItemInfo(9088); -- Gift of Arthas
+ SMARTBUFF_ARANCEELIXIR_ITEM = GetItemInfo(9155); -- Arcane Elixir
+ SMARTBUFF_GREATERINTELLECT_ITEM = GetItemInfo(9179); -- Elixir of Greater Intellect
+ SMARTBUFF_MAJORNATUREPROT_ITEM = GetItemInfo(22844); -- Major Natur Protection Potion
+ SMARTBUFF_MAJORMAGEBLOOD_ITEM = GetItemInfo(22840); -- Major Mageblood
+ SMARTBUFF_MAJORSHADOWPWR_ITEM = GetItemInfo(22835); -- Major Shadow Power
+ SMARTBUFF_MAJORIRONSKIN_ITEM = GetItemInfo(32068); -- Major Ironskin
+ SMARTBUFF_BLINDINGLIGHTFLASK_ITEM = GetItemInfo(22861); -- Flask of Blinding Light
+ SMARTBUFF_FORTIFICATIONFLASK_ITEM = GetItemInfo(22851); -- Flask of Fortification
+ SMARTBUFF_RESTORATIONFLASK_ITEM = GetItemInfo(22853); -- Flask of Restoration
+ SMARTBUFF_PUREDEATHFLASK_ITEM = GetItemInfo(22866); -- Flask of Pure Death
+ SMARTBUFF_RELENTLESSFLASK_ITEM = GetItemInfo(22854); -- Flask of Relentless Assault
+ SMARTBUFF_CHROMATICFLASK_ITEM = GetItemInfo(13513); -- Flask of Chromatic Resistance
+ SMARTBUFF_DISTILLEDFLASK_ITEM = GetItemInfo(13511); -- Flask of Distilled Wisdom
+ SMARTBUFF_SUPREMEPWRFLASK_ITEM = GetItemInfo(13512); -- Flask of Supreme Power
+
+ -- Misc Items
+ _, _, _, _, _, _, S.FishingPole = GetItemInfo(6256); --"Fishing Pole"
+
+ SMARTBUFF_AddMsgD(">>>> Item list's have been initialised.");
+
+end
+
+
+----------------------------------------------------------------------------------------------------------------------------------
+---
+--- Initialise Spell Id
+---
+----------------------------------------------------------------------------------------------------------------------------------
+function SMARTBUFF_InitSpellIDs()
+
+ -- Druid
+ SMARTBUFF_DRUID_CAT = GetSpellInfo(768); --"Cat Form"
+ SMARTBUFF_DRUID_TREE = GetSpellInfo(33891); --"Tree of Life"
+ SMARTBUFF_DRUID_MOONKIN = GetSpellInfo(24858); --"Moonkin Form"
+ SMARTBUFF_DRUID_TRACK = GetSpellInfo(5225); --"Track Humanoids"
+ SMARTBUFF_MOTW = GetSpellInfo(1126); --"Mark of the Wild"
+ SMARTBUFF_GOTWRB1 = GetSpellInfo(21849); --"Gift of the Wild"
+ SMARTBUFF_THORNS = GetSpellInfo(467); --"Thorns"
+ SMARTBUFF_IMPTHORNS = GetSpellInfo(16836); --"Improved Thorns"
+ SMARTBUFF_BARKSKIN = GetSpellInfo(22812); --"Barkskin"
+ SMARTBUFF_NATURESGRASP = GetSpellInfo(16689); --"Nature's Grasp"
+ SMARTBUFF_TIGERSFURY = GetSpellInfo(5217); --"Tiger's Fury"
+ SMARTBUFF_SAVAGEROAR = GetSpellInfo(52610); --"Savage Roar"
+ SMARTBUFF_OMENOFCLARITY = GetSpellInfo(16864); --"Omen of Clarity"
+
+ -- Druid linked
+ S.LinkDruidThorns = { SMARTBUFF_THORNS, SMARTBUFF_IMPTHORNS };
+ S.LinkDruidGOTW = { SMARTBUFF_MOTW, SMARTBUFF_GOTWRB1}
+
+ -- Priest
+ SMARTBUFF_PWF = GetSpellInfo(1243); --"Power Word: Fortitude"
+ SMARTBUFF_POFRB1 = GetSpellInfo(21562); --"Prayer of Fortitude"
+ SMARTBUFF_SP = GetSpellInfo(976); --"Shadow Protection"
+ SMARTBUFF_POSPRB1 = GetSpellInfo(27683); --"Prayer of Shadow Protection"
+ SMARTBUFF_INNERFIRE = GetSpellInfo(588); --"Inner Fire"
+ SMARTBUFF_DS = GetSpellInfo(14752); --"Divine Spirit"
+ SMARTBUFF_POSRB1 = GetSpellInfo(27681); --"Prayer of Spirit"
+ SMARTBUFF_PWS = GetSpellInfo(17); --"Power Word: Shield"
+ SMARTBUFF_SHADOWFORM = GetSpellInfo(15473); --"Shadowform"
+ SMARTBUFF_FEARWARD = GetSpellInfo(6346); --"Fear Ward"
+ SMARTBUFF_ELUNESGRACE = GetSpellInfo(2651); --"Elune's Grace"
+ SMARTBUFF_FEEDBACK = GetSpellInfo(13896); --"Feedback"
+ SMARTBUFF_SHADOWGUARD = GetSpellInfo(18137); --"Shadowguard"
+ SMARTBUFF_TOUCHOFWEAKNESS = GetSpellInfo(2652); --"Touch of Weakness"
+ SMARTBUFF_INNERFOCUS = GetSpellInfo(14751); --"Inner Focus"
+ SMARTBUFF_RENEW = GetSpellInfo(139); --"Renew"
+
+
+ S.ChainPriestFortBuffs = { SMARTBUFF_PWF, SMARTBUFF_POFRB1};
+ S.ChainPriestSpiritBuffs = { SMARTBUFF_DS, SMARTBUFF_POSRB1};
+ S.ChainPriestShadowBuffs = { SMARTBUFF_SP, SMARTBUFF_POSPRB1};
+
+
+ -- Mage
+ SMARTBUFF_AI = GetSpellInfo(1459); --"Arcane Intellect"
+ SMARTBUFF_ABRB1 = GetSpellInfo(23028); --"Arcane Brilliance"
+ SMARTBUFF_ICEARMOR = GetSpellInfo(7302); --"Ice Armor"
+ SMARTBUFF_FROSTARMOR = GetSpellInfo(168); --"Frost Armor"
+ SMARTBUFF_MAGEARMOR = GetSpellInfo(6117); --"Mage Armor"
+ SMARTBUFF_MOLTENARMOR = GetSpellInfo(30482); --"Molten Armor"
+ SMARTBUFF_DAMPENMAGIC = GetSpellInfo(604); --"Dampen Magic"
+ SMARTBUFF_AMPLIFYMAGIC = GetSpellInfo(1008); --"Amplify Magic"
+ SMARTBUFF_MANASHIELD = GetSpellInfo(1463); --"Mana Shield"
+ SMARTBUFF_FIREWARD = GetSpellInfo(543); --"Fire Ward"
+ SMARTBUFF_FROSTWARD = GetSpellInfo(6143); --"Frost Ward"
+ SMARTBUFF_ICEBARRIER = GetSpellInfo(11426); --"Ice Barrier"
+ SMARTBUFF_COMBUSTION = GetSpellInfo(11129); --"Combustion"
+ SMARTBUFF_ARCANEPOWER = GetSpellInfo(12042); --"Arcane Power"
+ SMARTBUFF_PRESENCEOFMIND = GetSpellInfo(12043); --"Presence of Mind"
+ SMARTBUFF_ICYVEINS = GetSpellInfo(12472); --"Icy Veins"
+ SMARTBUFF_SUMMONWATERELE = GetSpellInfo(31687); --"Summon Water Elemental"
+ SMARTBUFF_FOCUSMAGIC = GetSpellInfo(54646); --"Focus Magic"
+
+ -- Mage chained
+ S.ChainMageArmor = { SMARTBUFF_ICEARMOR, SMARTBUFF_FROSTARMOR, SMARTBUFF_MAGEARMOR, SMARTBUFF_MOLTENARMOR };
+ S.ChainMageBuffs = { SMARTBUFF_AI, SMARTBUFF_ABRB1};
+
+ -- Warlock
+ SMARTBUFF_FELARMOR = GetSpellInfo(28176); --"Fel Armor"
+ SMARTBUFF_DEMONARMOR = GetSpellInfo(706); --"Demon Armor"
+ SMARTBUFF_DEMONSKIN = GetSpellInfo(687); --"Demon Skin"
+ SMARTBUFF_UNENDINGBREATH = GetSpellInfo(5697); --"Unending Breath"
+ SMARTBUFF_DINVISIBILITY = GetSpellInfo(132); --"Detect Invisibility"
+ SMARTBUFF_SOULLINK = GetSpellInfo(19028); --"Soul Link"
+ SMARTBUFF_SHADOWWARD = GetSpellInfo(6229); --"Shadow Ward"
+ SMARTBUFF_DARKPACT = GetSpellInfo(18220); --"Dark Pact"
+ SMARTBUFF_LIFETAP = GetSpellInfo(1454); --"Life Tap"
+ SMARTBUFF_CREATEHSMIN = GetSpellInfo(6201); --"Create Healthstone (Minor)"
+ SMARTBUFF_CREATEHSLES = GetSpellInfo(6202); --"Create Healthstone (Lesser)"
+ SMARTBUFF_CREATEHS = GetSpellInfo(5699); --"Create Healthstone"
+ SMARTBUFF_CREATEHSGRE = GetSpellInfo(11729); --"Create Healthstone (Greater)"
+ SMARTBUFF_CREATEHSMAJ = GetSpellInfo(11730); --"Create Healthstone (Major)"
+ SMARTBUFF_SOULSTONE = GetSpellInfo(20707); --"Soulstone"
+ SMARTBUFF_CREATESSMIN = GetSpellInfo(693); --"Create Soulstone (Minor)"
+ SMARTBUFF_CREATESSLES = GetSpellInfo(20752); --"Create Soulstone (Lesser)"
+ SMARTBUFF_CREATESS = GetSpellInfo(20755); --"Create Soulstone"
+ SMARTBUFF_CREATESSGRE = GetSpellInfo(20756); --"Create Soulstone (Greater)"
+ SMARTBUFF_CREATESSMAJ = GetSpellInfo(20757); --"Create Soulstone (Major)"
+
+ -- Warlock chained
+ S.ChainWarlockArmor = { SMARTBUFF_DEMONSKIN, SMARTBUFF_DEMONARMOR, SMARTBUFF_FELARMOR };
+
+
+ -- Hunter
+ SMARTBUFF_TRUESHOTAURA = GetSpellInfo(19506); --"Trueshot Aura"
+ SMARTBUFF_RAPIDFIRE = GetSpellInfo(3045); --"Rapid Fire"
+ SMARTBUFF_AOTH = GetSpellInfo(13165); --"Aspect of the Hawk"
+ SMARTBUFF_AOTM = GetSpellInfo(13163); --"Aspect of the Monkey"
+ SMARTBUFF_AOTW = GetSpellInfo(20043); --"Aspect of the Wild"
+ SMARTBUFF_AOTB = GetSpellInfo(13161); --"Aspect of the Beast"
+ SMARTBUFF_AOTC = GetSpellInfo(5118); --"Aspect of the Cheetah"
+ SMARTBUFF_AOTP = GetSpellInfo(13159); --"Aspect of the Pack"
+ SMARTBUFF_AOTV = GetSpellInfo(34074); --"Aspect of the Viper"
+ SMARTBUFF_AOTDH = GetSpellInfo(61846); --"Aspect of the Dragonhawk"
+
+ -- Hunter chained
+ S.ChainAspects = { SMARTBUFF_AOTH,SMARTBUFF_AOTM,SMARTBUFF_AOTW,SMARTBUFF_AOTB,SMARTBUFF_AOTC,SMARTBUFF_AOTP,SMARTBUFF_AOTV,SMARTBUFF_AOTDH };
+
+
+ -- Shaman
+ SMARTBUFF_LIGHTNINGSHIELD = GetSpellInfo(324); --"Lightning Shield"
+ SMARTBUFF_WATERSHIELD = GetSpellInfo(24398); --"Water Shield"
+ SMARTBUFF_EARTHSHIELD = GetSpellInfo(974); --"Earth Shield"
+ SMARTBUFF_ROCKBITERW = GetSpellInfo(8017); --"Rockbiter Weapon"
+ SMARTBUFF_FROSTBRANDW = GetSpellInfo(8033); --"Frostbrand Weapon"
+ SMARTBUFF_FLAMETONGUEW = GetSpellInfo(8024); --"Flametongue Weapon"
+ SMARTBUFF_WINDFURYW = GetSpellInfo(8232); --"Windfury Weapon"
+ SMARTBUFF_EARTHLIVINGW = GetSpellInfo(51730); --"Earthliving Weapon"
+ SMARTBUFF_WATERBREATHING = GetSpellInfo(131); --"Water Breathing"
+ SMARTBUFF_WATERWALKING = GetSpellInfo(546); --"Water Walking"
+
+ -- Shaman chained
+ S.ChainShamanShield = { SMARTBUFF_LIGHTNINGSHIELD, SMARTBUFF_WATERSHIELD, SMARTBUFF_EARTHSHIELD };
+
+
+ -- Warrior
+ SMARTBUFF_BATTLESHOUT = GetSpellInfo(6673); --"Battle Shout"
+ SMARTBUFF_COMMANDINGSHOUT = GetSpellInfo(469); --"Commanding Shout"
+ SMARTBUFF_BERSERKERRAGE = GetSpellInfo(18499); --"Berserker Rage"
+ SMARTBUFF_BLOODRAGE = GetSpellInfo(2687); --"Bloodrage"
+ SMARTBUFF_RAMPAGE = GetSpellInfo(29801); --"Rampage"
+ SMARTBUFF_VIGILANCE = GetSpellInfo(50720); --"Vigilance"
+ SMARTBUFF_SHIELDBLOCK = GetSpellInfo(2565); --"Shield Block"
+
+ -- Warrior chained
+ S.ChainWarriorShout = { SMARTBUFF_BATTLESHOUT, SMARTBUFF_COMMANDINGSHOUT };
+
+
+ -- Rogue
+ SMARTBUFF_BLADEFLURRY = GetSpellInfo(13877); --"Blade Flurry"
+ SMARTBUFF_SAD = GetSpellInfo(5171); --"Slice and Dice"
+ SMARTBUFF_EVASION = GetSpellInfo(5277); --"Evasion"
+ SMARTBUFF_HUNGERFORBLOOD = GetSpellInfo(51662); --"Hunger For Blood"
+ SMARTBUFF_STEALTH = GetSpellInfo(1784); --"Stealth"
+
+
+ -- Paladin
+ SMARTBUFF_RIGHTEOUSFURY = GetSpellInfo(25780); --"Righteous Fury"
+ SMARTBUFF_HOLYSHIELD = GetSpellInfo(20925); --"Holy Shield"
+ SMARTBUFF_BOM = GetSpellInfo(19740); --"Blessing of Might"
+ SMARTBUFF_GBOM = GetSpellInfo(25782); --"Greater Blessing of Might"
+ SMARTBUFF_BOW = GetSpellInfo(19742); --"Blessing of Wisdom"
+ SMARTBUFF_GBOW = GetSpellInfo(25894); --"Greater Blessing of Wisdom"
+ SMARTBUFF_BOSAL = GetSpellInfo(1038); --"Blessing of Salvation"
+ SMARTBUFF_GBOSAL = GetSpellInfo(25895); --"Greater Blessing of Salvation"
+ SMARTBUFF_BOK = GetSpellInfo(20217); --"Blessing of Kings"
+ SMARTBUFF_GBOK = GetSpellInfo(25898); --"Greater Blessing of Kings"
+ SMARTBUFF_BOSAN = GetSpellInfo(20911); --"Blessing of Sanctuary"
+ SMARTBUFF_GBOSAN = GetSpellInfo(25899); --"Greater Blessing of Sanctuary"
+-- SMARTBUFF_BOF = GetSpellInfo(1044); --"Blessing of Freedom"
+-- SMARTBUFF_BOP = GetSpellInfo(1022); --"Blessing of Protection"
+ SMARTBUFF_SOCOMMAND = GetSpellInfo(20375); --"Seal of Command"
+ SMARTBUFF_SOJUSTICE = GetSpellInfo(20164); --"Seal of Justice"
+ SMARTBUFF_SOLIGHT = GetSpellInfo(20165); --"Seal of Light"
+ SMARTBUFF_SORIGHTEOUSNESS = GetSpellInfo(21084); --"Seal of Righteousness"
+ SMARTBUFF_SOWISDOM = GetSpellInfo(20166); --"Seal of Wisdom"
+ SMARTBUFF_SOTCRUSADER = GetSpellInfo(21082); --"Seal of the Crusader"
+ SMARTBUFF_SOVENGEANCE = GetSpellInfo(31801); --"Seal of Vengeance"
+ SMARTBUFF_SOBLOOD = GetSpellInfo(31892); --"Seal of Blood"
+ SMARTBUFF_SOCORRUPTION = GetSpellInfo(53736); --"Seal of Corruption"
+ SMARTBUFF_SOMARTYR = GetSpellInfo(53720); --"Seal of the Martyr"
+ SMARTBUFF_DEVOTIONAURA = GetSpellInfo(465); --"Devotion Aura"
+ SMARTBUFF_RETRIBUTIONAURA = GetSpellInfo(7294); --"Retribution Aura"
+ SMARTBUFF_CONCENTRATIONAURA = GetSpellInfo(19746); --"Concentration Aura"
+ SMARTBUFF_SHADOWRESISTANCEAURA = GetSpellInfo(19876); --"Shadow Resistance Aura"
+ SMARTBUFF_FROSTRESISTANCEAURA = GetSpellInfo(19888); --"Frost Resistance Aura"
+ SMARTBUFF_FIRERESISTANCEAURA = GetSpellInfo(19891); --"Fire Resistance Aura"
+ SMARTBUFF_SANCTITYAURA = GetSpellInfo(20218); --"Sanctity Aura"
+ SMARTBUFF_CRUSADERAURA = GetSpellInfo(32223); --"Crusader Aura"
+
+ -- Paladin chained
+ S.ChainPaladinBOM = { SMARTBUFF_BOM, SMARTBUFF_GBOM };
+ S.ChainPaladinBOW = { SMARTBUFF_BOW, SMARTBUFF_GBOW };
+ S.ChainPaladinSAL = { SMARTBUFF_BOSAL, SMARTBUFF_GBOSAL };
+ S.ChainPaladinBOK = { SMARTBUFF_BOK, SMARTBUFF_GBOK };
+ S.ChainPaladinSAN = { SMARTBUFF_BOSAN, SMARTBUFF_GBOSAN };
+ S.ChainPaladinSeal = { SMARTBUFF_SOCOMMAND, SMARTBUFF_SOJUSTICE, SMARTBUFF_SOLIGHT, SMARTBUFF_SORIGHTEOUSNESS, SMARTBUFF_SOWISDOM, SMARTBUFF_SOTCRUSADER, SMARTBUFF_SOVENGEANCE, SMARTBUFF_SOBLOOD, SMARTBUFF_SOCORRUPTION, SMARTBUFF_SOMARTYR };
+ S.ChainPaladinAura = { SMARTBUFF_DEVOTIONAURA, SMARTBUFF_RETRIBUTIONAURA, SMARTBUFF_CONCENTRATIONAURA, SMARTBUFF_SHADOWRESISTANCEAURA, SMARTBUFF_FROSTRESISTANCEAURA, SMARTBUFF_FIRERESISTANCEAURA, SMARTBUFF_SANCTITYAURA, SMARTBUFF_CRUSADERAURA };
+
+ -- Death Knight
+ SMARTBUFF_DANCINGRW = GetSpellInfo(49028); --"Dancing Rune Weapon"
+-- SMARTBUFF_BLOODPRESENCE = GetSpellInfo(48263); --"Blood Presence"
+-- SMARTBUFF_FROSTPRESENCE = GetSpellInfo(48266); --"Frost Presence"
+-- SMARTBUFF_UNHOLYPRESENCE = GetSpellInfo(48265); --"Unholy Presence"
+ SMARTBUFF_PATHOFFROST = GetSpellInfo(3714); --"Path of Frost"
+-- SMARTBUFF_BONESHIELD = GetSpellInfo(49222); --"Bone Shield"
+ SMARTBUFF_HORNOFWINTER = GetSpellInfo(57330); --"Horn of Winter"
+ SMARTBUFF_RAISEDEAD = GetSpellInfo(46584); --"Raise Dead"
+-- SMARTBUFF_POTGRAVE = GetSpellInfo(155522); --"Power of the Grave" (P)
+
+ -- Death Knight buff links
+ S.ChainDKPresence = { SMARTBUFF_BLOODPRESENCE, SMARTBUFF_FROSTPRESENCE, SMARTBUFF_UNHOLYPRESENCE };
+
+
+ -- Tracking
+ SMARTBUFF_FINDMINERALS = GetSpellInfo(2580); --"Find Minerals"
+ SMARTBUFF_FINDHERBS = GetSpellInfo(2383); --"Find Herbs"
+ SMARTBUFF_FINDTREASURE = GetSpellInfo(2481); --"Find Treasure"
+ SMARTBUFF_TRACKHUMANOIDS = GetSpellInfo(19883); --"Track Humanoids"
+ SMARTBUFF_TRACKBEASTS = GetSpellInfo(1494); --"Track Beasts"
+ SMARTBUFF_TRACKUNDEAD = GetSpellInfo(19884); --"Track Undead"
+ SMARTBUFF_TRACKHIDDEN = GetSpellInfo(19885); --"Track Hidden"
+ SMARTBUFF_TRACKELEMENTALS = GetSpellInfo(19880); --"Track Elementals"
+ SMARTBUFF_TRACKDEMONS = GetSpellInfo(19878); --"Track Demons"
+ SMARTBUFF_TRACKGIANTS = GetSpellInfo(19882); --"Track Giants"
+ SMARTBUFF_TRACKDRAGONKIN = GetSpellInfo(19879); --"Track Dragonkin"
+ SMARTBUFF_SENSEDEMONS = GetSpellInfo(5500); --"Sense Demons"
+ SMARTBUFF_SENSEUNDEAD = GetSpellInfo(5502); --"Sense Undead"
+
+ -- Racial
+ SMARTBUFF_STONEFORM = GetSpellInfo(20594); --"Stoneform"
+ SMARTBUFF_BLOODFURY = GetSpellInfo(20572); --"Blood Fury" 33697, 33702
+ SMARTBUFF_BERSERKING = GetSpellInfo(26297); --"Berserking"
+ SMARTBUFF_WOTFORSAKEN = GetSpellInfo(7744); --"Will of the Forsaken"
+ SMARTBUFF_WarStomp = GetSpellInfo(20549); --"War Stomp"
+
+ -- Food
+ SMARTBUFF_FOOD_AURA = GetSpellInfo(19705); --"Well Fed"
+ SMARTBUFF_FOOD_SPELL = GetSpellInfo(433); --"Food"
+ SMARTBUFF_DRINK_SPELL = GetSpellInfo(430); --"Drink"
+
+ -- Misc
+ SMARTBUFF_KIRUSSOV = GetSpellInfo(46302); --"K'iru's Song of Victory"
+ SMARTBUFF_FISHING = GetSpellInfo(7620) or GetSpellInfo(111541); --"Fishing"
+
+
+ -- Scroll
+ SMARTBUFF_SBAGILITY = GetSpellInfo(8115); -- Scroll buff: Agility
+ SMARTBUFF_SBINTELLECT = GetSpellInfo(8096); -- Scroll buff: Intellect
+ SMARTBUFF_SBSTAMINA = GetSpellInfo(8099); -- Scroll buff: Stamina
+ SMARTBUFF_SBSPIRIT = GetSpellInfo(8112); -- Scroll buff: Spirit
+ SMARTBUFF_SBSTRENGHT = GetSpellInfo(8118); -- Scroll buff: Strength
+ SMARTBUFF_SBPROTECTION = GetSpellInfo(89344); -- Scroll buff: Armor
+
+ --- Burning Crusade Classic - Potions / Flasks / Elixirs
+ SMARTBUFF_ADEPTELIXIR_BUFF = GetSpellInfo(33740); -- Adept's Elixir
+ SMARTBUFF_MAJORDEFENSE_BUFF = GetSpellInfo(28557); -- Major Defense
+ SMARTBUFF_MAJORAGILITY_BUFF = GetSpellInfo(28497); -- Major Agility
+ SMARTBUFF_DRAENICWISDOM_BUFF = GetSpellInfo(39638); -- Draenic Wisdom
+ SMARTBUFF_MAJORFROSTPOWER_BUFF = GetSpellInfo(28549); -- Major Frost Power
+ SMARTBUFF_EARTHEN_BUFF = GetSpellInfo(39637); -- Earthen Elixir
+ SMARTBUFF_MASTERY_BUFF = GetSpellInfo(33741); -- Elixir of Mastery
+ SMARTBUFF_CAMOUFLAGE_BUFF = GetSpellInfo(28543); -- Elixir of Camouflage
+ SMARTBUFF_HEALINGPOWER_BUFF = GetSpellInfo(28545); -- Elixir of Healing Power
+ SMARTBUFF_MAJORFORTITUDE_BUFF = GetSpellInfo(39636); -- Elixir of Major Fortitude
+ SMARTBUFF_MAJORSTRENGTH_BUFF = GetSpellInfo(28544); -- Elixir of Major Strength
+ SMARTBUFF_ONSLAUGHTELIXIR_BUFF = GetSpellInfo(33738); -- Onslaught Elixir
+ SMARTBUFF_GREATERARCANE_BUFF = GetSpellInfo(17573); -- Greater Arcane
+ SMARTBUFF_MONGOOSEELIXIR_BUFF = GetSpellInfo(17571); -- Elixir of Mongoose
+ SMARTBUFF_BRUTEFORCE_BUFF = GetSpellInfo(17557); -- Elixir of Brute Force
+ SMARTBUFF_SAGESELIXIR_BUFF = GetSpellInfo(17555); -- Elixir of Sages
+ SMARTBUFF_SUPERIORDEFENSE_BUFF = GetSpellInfo(17554); -- Elixir of Superior Defense
+ SMARTBUFF_DEMONSLAYING_BUFF = GetSpellInfo(11477); -- Elixir of Demon Slaying
+ SMARTBUFF_MAJORFIREPOWER_BUFF = GetSpellInfo(28556); -- Elixir of Major Fire Power
+ SMARTBUFF_GREATERFIREPOWER_BUFF = GetSpellInfo(26277); -- Elixir of Greater Fire Power
+ SMARTBUFF_SHADOWPOWER_BUFF = GetSpellInfo(11476); -- Elixir of Shadow Power
+ SMARTBUFF_GIANTSELIXIR_BUFF = GetSpellInfo(11472); -- Elixir of Giants
+ SMARTBUFF_GREATERAGILITY_BUFF = GetSpellInfo(11467); -- Elixir of Greater Agility
+ SMARTBUFF_GIFTOFARTHAS_BUFF = GetSpellInfo(11466); -- Gift of Arthas
+ SMARTBUFF_ARANCEELIXIR_BUFF = GetSpellInfo(11461); -- Arcane Elixir
+ SMARTBUFF_GREATERINTELLECT_BUFF = GetSpellInfo(11465); -- Elixir of Greater Intellect
+ SMARTBUFF_MAJORNATUREPROT_BUFF = GetSpellInfo(28573); -- Major Natur Protection Potion
+ SMARTBUFF_MAJORMAGEBLOOD_BUFF = GetSpellInfo(28570); -- Major Mageblood
+ SMARTBUFF_MAJORSHADOWPWR_BUFF = GetSpellInfo(28558); -- Major Shadow Power
+ SMARTBUFF_MAJORIRONSKIN_BUFF = GetSpellInfo(39639); -- Major Ironskin
+ SMARTBUFF_BLINDINGLIGHTFLASK_BUFF = GetSpellInfo(28590); -- Flask of Blinding Light
+ SMARTBUFF_FORTIFICATIONFLASK_BUFF = GetSpellInfo(28587); -- Flask of Fortification
+ SMARTBUFF_RESTORATIONFLASK_BUFF = GetSpellInfo(28588); -- Flask of Restoration
+ SMARTBUFF_PUREDEATHFLASK_BUFF = GetSpellInfo(28591); -- Flask of Pure Death
+ SMARTBUFF_RELENTLESSFLASK_BUFF = GetSpellInfo(28589); -- Flask of Relentless Assault
+ SMARTBUFF_CHROMATICFLASK_BUFF = GetSpellInfo(17638); -- Flask of Chromatic Resistance
+ SMARTBUFF_DISTILLEDFLASK_BUFF = GetSpellInfo(17636); -- Flask of Distilled Wisdom
+ SMARTBUFF_SUPREMEPWRFLASK_BUFF = GetSpellInfo(17637); -- Flask of Supreme Power
+
+
+ -- Buff map
+ S.LinkStats = { SMARTBUFF_BOK, SMARTBUFF_MOTW, SMARTBUFF_LOTE, SMARTBUFF_LOTWT, SMARTBUFF_MOTWR1, SMARTBUFF_MOTWR2, SMARTBUFF_MOTWR3,
+ SMARTBUFF_MOTWR4, SMARTBUFF_MOTWR5, SMARTBUFF_MOTWR6, SMARTBUFF_MOTWR7, SMARTBUFF_GOTWR1, SMARTBUFF_GOTWR2,
+ GetSpellInfo(159988), -- Bark of the Wild
+ GetSpellInfo(203538), -- Greater Blessing of Kings
+ GetSpellInfo(90363), -- Embrace of the Shale Spider
+ GetSpellInfo(160077), -- Strength of the Earth
+ SMARTBUFF_DSR1, SMARTBUFF_DSR2, SMARTBUFF_DSR3, SMARTBUFF_DSR4, SMARTBUFF_SWPR1, SMARTBUFF_SWPR2, SMARTBUFF_SWPR3,
+ SMARTBUFF_PSWPR1, SMARTBUFF_POSR1,
+ };
+
+ S.LinkFlaskTBC = { SMARTBUFF_BLINDINGLIGHTFLASK_BUFF, SMARTBUFF_FORTIFICATIONFLASK_BUFF, SMARTBUFF_RESTORATIONFLASK_BUFF, SMARTBUFF_PUREDEATHFLASK_BUFF,
+ SMARTBUFF_RELENTLESSFLASK_BUFF, SMARTBUFF_CHROMATICFLASK_BUFF, SMARTBUFF_DISTILLEDFLASK_BUFF, SMARTBUFF_SUPREMEPWRFLASK_BUFF};
+
+
+ S.LinkSp = { SMARTBUFF_POSPRB1, SMARTBUFF_POSPRB2 }
+ S.LinkAp = { SMARTBUFF_HORNOFWINTER, SMARTBUFF_BATTLESHOUT, SMARTBUFF_TRUESHOTAURA };
+
+ S.LinkMa = { SMARTBUFF_BOM, SMARTBUFF_DRUID_MKAURA, SMARTBUFF_GRACEOFAIR, SMARTBUFF_POTGRAVE,
+ GetSpellInfo(93435), -- Roar of Courage
+ GetSpellInfo(160039), -- Keen Senses
+ GetSpellInfo(128997), -- Spirit Beast Blessing
+ GetSpellInfo(160073) -- Plainswalking
+ };
+
+ S.LinkInt = { SMARTBUFF_BOW, SMARTBUFF_ABRB1, SMARTBUFF_ABRB2, SMARTBUFF_ABR1, SMARTBUFF_AIR1, SMARTBUFF_AIR2, SMARTBUFF_AIR3, SMARTBUFF_AIR4, SMARTBUFF_AIR5, SMARTBUFF_DALARANB };
+
+ SMARTBUFF_AddMsgD(">>>> Spell ID's have been initialised.");
+
+end
+
+
+----------------------------------------------------------------------------------------------------------------------------------
+---
+--- Initialise Spell List
+---
+----------------------------------------------------------------------------------------------------------------------------------
+function SMARTBUFF_InitSpellList()
+ if (SMARTBUFF_PLAYERCLASS == nil) then return; end
+
+ -- Druid
+ if (SMARTBUFF_PLAYERCLASS == "DRUID") then
+ SMARTBUFF_BUFFLIST = {
+ -- mark of the wild
+ {SMARTBUFF_MOTW, 30, SMARTBUFF_CONST_GROUP, {1,10,20,30,40,50,60,70,80}, "HPET;WPET", S.LinkDruidGOTW},
+ -- gift of the wild
+ {SMARTBUFF_GOTWRB1, 60, SMARTBUFF_CONST_GROUP, {50,60,70,80}, "HPET;WPET", S.LinkDruidGOTW, {SMARTBUFF_WILDBERRIES,SMARTBUFF_WILDTHORNROOT}},
+ {SMARTBUFF_IMPTHORNS, 10, SMARTBUFF_CONST_GROUP, {6,14}, "HUNTER;ROGUE;MAGE;PRIEST;PALADIN;WARLOCK;WPET;DKPET", S.LinkDruidThorns},
+ {SMARTBUFF_THORNS, 10, SMARTBUFF_CONST_GROUP, {6,14,24,34,44,54, 64, 74}, "HUNTER;ROGUE;MAGE;PRIEST;PALADIN;WARLOCK;WPET;DKPET", S.LinkDruidThorns},
+ {SMARTBUFF_OMENOFCLARITY, 10, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_BARKSKIN, 0.25, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_NATURESGRASP, 0.75, SMARTBUFF_CONST_FORCESELF},
+ {SMARTBUFF_TIGERSFURY, 0.1, SMARTBUFF_CONST_SELF, nil, SMARTBUFF_DRUID_CAT},
+ {SMARTBUFF_SAVAGEROAR, 0.15, SMARTBUFF_CONST_SELF, nil, SMARTBUFF_DRUID_CAT},
+ {SMARTBUFF_DRUID_MOONKIN, -1, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_DRUID_TREE, -1, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_CENARIONWARD, 0.5, SMARTBUFF_CONST_GROUP, {1}, "WARRIOR;DRUID;SHAMAN;HUNTER;ROGUE;MAGE;PRIEST;PALADIN;WARLOCK;DEATHKNIGHT;MONK;DEMONHUNTER"},
+ };
+ end
+
+
+ -- Priest
+ if (SMARTBUFF_PLAYERCLASS == "PRIEST") then
+ SMARTBUFF_BUFFLIST = {
+
+ -- fortitude / prayer of fortitude
+ {SMARTBUFF_PWF, 30, SMARTBUFF_CONST_GROUP, {1,12,24,36,48,60,70,80}, "HPET;WPET", S.ChainPriestFortBuffs},
+ {SMARTBUFF_POFRB1, 60, SMARTBUFF_CONST_GROUP, {48,60,70,80}, "HPET;WPET", S.ChainPriestFortBuffs, {SMARTBUFF_SACREDCANDLE}},
+ -- shadow protection / prayer of shadow protection
+ {SMARTBUFF_SP, 30, SMARTBUFF_CONST_GROUP, {30,42,56,68,76}, "HPET;WPET", S.ChainPriestShadowBuffs},
+ {SMARTBUFF_POSPRB1, 60, SMARTBUFF_CONST_GROUP, {48,60,70,80}, "HPET;WPET", S.ChainPriestShadowBuffs, {SMARTBUFF_SACREDCANDLE}},
+ -- spirit / divine spirit
+ {SMARTBUFF_DS, 30, SMARTBUFF_CONST_GROUP, {30,40,50,60,70,80}, "HPET;WPET", S.ChainPriestSpiritBuffs},
+ {SMARTBUFF_POSRB1, 60, SMARTBUFF_CONST_GROUP, {48,60,70,80}, "HPET;WPET", S.ChainPriestSpiritBuffs, {SMARTBUFF_SACREDCANDLE}},
+
+ {SMARTBUFF_INNERFIRE, 10, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_DS, 30, SMARTBUFF_CONST_GROUP, {40,42,54,60,70,80}, "ROGUE;WARRIOR;HPET;WPET", nil, nil, SMARTBUFF_POSRB1, 60, {60}, {SMARTBUFF_SACREDCANDLE}},
+-- {SMARTBUFF_POSRB1, 60, SMARTBUFF_CONST_GROUP, {60}, "ROGUE;WARRIOR;HPET;WPET", nil, nil, SMARTBUFF_POSRB2, 60, {70}, {SMARTBUFF_SACREDCANDLE}},
+ {SMARTBUFF_PWS, 0.5, SMARTBUFF_CONST_GROUP, {6,12,18,24,30,36,42,48,54,60,65,70,75,80}, "MAGE;WARLOCK;DEATHKNIGHT;ROGUE;PALADIN;WARRIOR;DRUID;HUNTER;SHAMAN;HPET;WPET"},
+ {SMARTBUFF_SHADOWFORM, -1, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_FEARWARD, 10, SMARTBUFF_CONST_GROUP, {20}},
+ {SMARTBUFF_ELUNESGRACE, 0.25, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_FEEDBACK, 0.25, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_SHADOWGUARD, 10, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_TOUCHOFWEAKNESS, 10, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_INNERFOCUS, -1, SMARTBUFF_CONST_SELF}
+ };
+ end
+
+ -- Mage
+ if (SMARTBUFF_PLAYERCLASS == "MAGE") then
+ SMARTBUFF_BUFFLIST = {
+ -- arcane intellect
+ {SMARTBUFF_AI, 30, SMARTBUFF_CONST_GROUP, {1,14,28,42,56,70,80}, "ROGUE;WARRIOR;HPET;WPET", S.ChainMageBuffs},
+ -- arcane brilliance
+ {SMARTBUFF_ABRB1, 60, SMARTBUFF_CONST_GROUP, {56, 70, 80}, "ROGUE;WARRIOR;HPET;WPET", {SMARTBUFF_ARCANEPOWDER}, S.ChainMageBuffs},
+ {SMARTBUFF_FOCUSMAGIC, 30, SMARTBUFF_CONST_GROUP, {20}, "WARRIOR;DRUID;SHAMAN;HUNTER;ROGUE;MAGE;PRIEST;PALADIN;WARLOCK;DEATHKNIGHT;HPET;WPET"},
+ {SMARTBUFF_ICEARMOR, 30, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainMageArmor},
+ {SMARTBUFF_FROSTARMOR, 30, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainMageArmor},
+ {SMARTBUFF_MAGEARMOR, 30, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainMageArmor},
+ {SMARTBUFF_MOLTENARMOR, 30, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainMageArmor},
+ {SMARTBUFF_DAMPENMAGIC, 10, SMARTBUFF_CONST_GROUP, {12,24,36,48,60}, "HPET;WPET"},
+ {SMARTBUFF_AMPLIFYMAGIC, 10, SMARTBUFF_CONST_GROUP, {18,30,42,54}, "HPET;WPET"},
+ {SMARTBUFF_MANASHIELD, 1, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_FIREWARD, 0.5, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_FROSTWARD, 0.5, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_ICEBARRIER, 1, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_COMBUSTION, -1, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_ICYVEINS, 0.33, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_ARCANEPOWER, 0.25, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_PRESENCEOFMIND, 0.165, SMARTBUFF_CONST_SELF}
+ };
+ end
+
+ -- Warlock
+ if (SMARTBUFF_PLAYERCLASS == "WARLOCK") then
+ SMARTBUFF_BUFFLIST = {
+ {SMARTBUFF_FELARMOR, 30, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainWarlockArmor},
+ {SMARTBUFF_DEMONARMOR, 30, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainWarlockArmor},
+ {SMARTBUFF_DEMONSKIN, 30, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainWarlockArmor},
+ {SMARTBUFF_SOULLINK, 0, SMARTBUFF_CONST_SELF, nil, S.CheckPetNeeded},
+ {SMARTBUFF_DINVISIBILITY, 10, SMARTBUFF_CONST_GROUP, {26}, "HPET;WPET"},
+ {SMARTBUFF_UNENDINGBREATH, 10, SMARTBUFF_CONST_GROUP, {16}, "HPET;WPET"},
+ {SMARTBUFF_LIFETAP, 0.025, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_SHADOWWARD, 0.5, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_DARKPACT, 0.5, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_SOULSTONE, 15, SMARTBUFF_CONST_GROUP, {18}, "WARRIOR;DRUID;SHAMAN;HUNTER;ROGUE;MAGE;PRIEST;PALADIN;WARLOCK;DEATHKNIGHT;MONK;DEMONHUNTER;HPET;WPET;DKPET"},
+ {SMARTBUFF_CREATEHSMAJ, 0.03, SMARTBUFF_CONST_ITEM, nil, SMARTBUFF_HEALTHSTONEGEM},
+ {SMARTBUFF_CREATEHSGRE, 0.03, SMARTBUFF_CONST_ITEM, nil, SMARTBUFF_HEALTHSTONEGEM},
+ {SMARTBUFF_CREATEHS, 0.03, SMARTBUFF_CONST_ITEM, nil, SMARTBUFF_HEALTHSTONEGEM},
+ {SMARTBUFF_CREATEHSLES, 0.03, SMARTBUFF_CONST_ITEM, nil, SMARTBUFF_HEALTHSTONEGEM},
+ {SMARTBUFF_CREATEHSMIN, 0.03, SMARTBUFF_CONST_ITEM, nil, SMARTBUFF_HEALTHSTONEGEM},
+ {SMARTBUFF_CREATESSMAJ, 0.03, SMARTBUFF_CONST_ITEM, nil, SMARTBUFF_SOULSTONEGEM},
+ {SMARTBUFF_CREATESSGRE, 0.03, SMARTBUFF_CONST_ITEM, nil, SMARTBUFF_SOULSTONEGEM},
+ {SMARTBUFF_CREATESS, 0.03, SMARTBUFF_CONST_ITEM, nil, SMARTBUFF_SOULSTONEGEM},
+ {SMARTBUFF_CREATESSLES, 0.03, SMARTBUFF_CONST_ITEM, nil, SMARTBUFF_SOULSTONEGEM},
+ {SMARTBUFF_CREATESSMIN, 0.03, SMARTBUFF_CONST_ITEM, nil, SMARTBUFF_SOULSTONEGEM},
+ {SMARTBUFF_SPELLSTONE6, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_SPELLSTONE5, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_SPELLSTONE4, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_SPELLSTONE3, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_SPELLSTONE2, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_SPELLSTONE1, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_FIRESTONE7, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_FIRESTONE6, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_FIRESTONE5, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_FIRESTONE4, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_FIRESTONE3, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_FIRESTONE2, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_FIRESTONE1, 60, SMARTBUFF_CONST_INV}
+ };
+ end
+
+ -- Hunter
+ if (SMARTBUFF_PLAYERCLASS == "HUNTER") then
+ SMARTBUFF_BUFFLIST = {
+ {SMARTBUFF_TRUESHOTAURA, -1, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_RAPIDFIRE, 0.2, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_AOTDH, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainAspects},
+ {SMARTBUFF_AOTH, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainAspects},
+ {SMARTBUFF_AOTM, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainAspects},
+ {SMARTBUFF_AOTV, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainAspects},
+ {SMARTBUFF_AOTW, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainAspects},
+ {SMARTBUFF_AOTB, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainAspects},
+ {SMARTBUFF_AOTC, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainAspects},
+ {SMARTBUFF_AOTP, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainAspects}
+ };
+ end
+
+ -- Shaman
+ if (SMARTBUFF_PLAYERCLASS == "SHAMAN") then
+ SMARTBUFF_BUFFLIST = {
+ {SMARTBUFF_LIGHTNINGSHIELD, 10, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainShamanShield},
+ {SMARTBUFF_WATERSHIELD, 10, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainShamanShield},
+ {SMARTBUFF_EARTHSHIELD, 10, SMARTBUFF_CONST_GROUP, {50,60}, "WARRIOR;DEATHKNIGHT;DRUID;SHAMAN;HUNTER;ROGUE;MAGE;PRIEST;PALADIN;WARLOCK;HPET;WPET", nil, S.ChainShamanShield},
+ {SMARTBUFF_WINDFURYW, 30, SMARTBUFF_CONST_WEAPON},
+ {SMARTBUFF_FLAMETONGUEW, 30, SMARTBUFF_CONST_WEAPON},
+ {SMARTBUFF_FROSTBRANDW, 30, SMARTBUFF_CONST_WEAPON},
+ {SMARTBUFF_ROCKBITERW, 30, SMARTBUFF_CONST_WEAPON},
+ {SMARTBUFF_EARTHLIVINGW, 30, SMARTBUFF_CONST_WEAPON},
+ {SMARTBUFF_WATERBREATHING, 10, SMARTBUFF_CONST_GROUP, {22}},
+ {SMARTBUFF_WATERWALKING, 10, SMARTBUFF_CONST_GROUP, {28}}
+ };
+ end
+
+ -- Warrior
+ if (SMARTBUFF_PLAYERCLASS == "WARRIOR") then
+ SMARTBUFF_BUFFLIST = {
+ {SMARTBUFF_BATTLESHOUT, 2, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainWarriorShout},
+ {SMARTBUFF_COMMANDINGSHOUT, 2, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainWarriorShout},
+ {SMARTBUFF_BERSERKERRAGE, 0.165, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_SHIELDBLOCK, 0.1666, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_BLOODRAGE, 0.165, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_RAMPAGE, 0.5, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_VIGILANCE, 30, SMARTBUFF_CONST_GROUP, {40}, "WARRIOR;DRUID;SHAMAN;HUNTER;ROGUE;MAGE;PRIEST;PALADIN;WARLOCK;DEATHKNIGHT;HPET;WPET"}
+ };
+ end
+
+ -- Rogue
+ if (SMARTBUFF_PLAYERCLASS == "ROGUE") then
+ SMARTBUFF_BUFFLIST = {
+ {SMARTBUFF_STEALTH, -1, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_BLADEFLURRY, 0.165, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_SAD, 0.2, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_HUNGERFORBLOOD, 0.5, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_EVASION, 0.2, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_INSTANTPOISON9, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_INSTANTPOISON8, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_INSTANTPOISON7, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_INSTANTPOISON6, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_INSTANTPOISON5, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_INSTANTPOISON4, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_INSTANTPOISON3, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_INSTANTPOISON2, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_INSTANTPOISON1, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_WOUNDPOISON7, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_WOUNDPOISON6, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_WOUNDPOISON5, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_WOUNDPOISON4, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_WOUNDPOISON3, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_WOUNDPOISON2, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_WOUNDPOISON1, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_MINDPOISON1, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_DEADLYPOISON9, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_DEADLYPOISON8, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_DEADLYPOISON7, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_DEADLYPOISON6, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_DEADLYPOISON5, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_DEADLYPOISON4, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_DEADLYPOISON3, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_DEADLYPOISON2, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_DEADLYPOISON1, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_CRIPPLINGPOISON1, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_ANESTHETICPOISON2, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_ANESTHETICPOISON1, 60, SMARTBUFF_CONST_INV}
+ };
+ end
+
+ -- Paladin
+ if (SMARTBUFF_PLAYERCLASS == "PALADIN") then
+ SMARTBUFF_BUFFLIST = {
+
+ {SMARTBUFF_RIGHTEOUSFURY, 30, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_HOLYSHIELD, 0.165, SMARTBUFF_CONST_SELF},
+
+ {SMARTBUFF_BOW, 5, SMARTBUFF_CONST_GROUP, {14,24,34,44,54,60,65,71,77}, "ROGUE;WARRIOR;HPET;WPET", S.ChainPaladinBOW},
+ {SMARTBUFF_GBOW, 15, SMARTBUFF_CONST_GROUP, {54,60,65,71,77}, "ROGUE;WARRIOR;HPET;WPET", S.ChainPaladinBOW, {SMARTBUFF_SYMBOLOFKINGS}},
+ {SMARTBUFF_BOM, 5, SMARTBUFF_CONST_GROUP, {4,12,22,32,42,52,60,70,73,79}, "MAGE;PRIEST;WARLOCK;HPET;WPET", S.ChainPaladinBOM},
+ {SMARTBUFF_GBOM, 15, SMARTBUFF_CONST_GROUP, {52,60,70,73,79}, "MAGE;PRIEST;WARLOCK;HPET;WPET", S.ChainPaladinBOM, {SMARTBUFF_SYMBOLOFKINGS}},
+ {SMARTBUFF_BOK, 5, SMARTBUFF_CONST_GROUP, {20}, "HPET;WPET", S.ChainPaladinBOK},
+ {SMARTBUFF_GBOK, 15, SMARTBUFF_CONST_GROUP, {60}, "HPET;WPET", S.ChainPaladinBOK, {SMARTBUFF_SYMBOLOFKINGS}},
+ {SMARTBUFF_BOSAL, 5, SMARTBUFF_CONST_GROUP, {26}, "TANK;HPET;WPET", S.ChainPaladinSAL},
+ {SMARTBUFF_GBOSAL, 15, SMARTBUFF_CONST_GROUP, {60}, "TANK;HPET;WPET", S.ChainPaladinSAL, {SMARTBUFF_SYMBOLOFKINGS}},
+ {SMARTBUFF_BOSAN, 5, SMARTBUFF_CONST_GROUP, {26,40,50,60}, "HPET;WPET", S.ChainPaladinSAN},
+ {SMARTBUFF_GBOSAN, 15, SMARTBUFF_CONST_GROUP, {60}, "HPET;WPET", S.ChainPaladinSAN, {SMARTBUFF_SYMBOLOFKINGS}},
+
+ {SMARTBUFF_SOCOMMAND, 2, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinSeal},
+ {SMARTBUFF_SOFURY, 2, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinSeal},
+ {SMARTBUFF_SOJUSTICE, 2, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinSeal},
+ {SMARTBUFF_SOLIGHT, 2, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinSeal},
+ {SMARTBUFF_SORIGHTEOUSNESS, 2, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinSeal},
+ {SMARTBUFF_SOWISDOM, 2, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinSeal},
+ {SMARTBUFF_SOTCRUSADER, 2, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinSeal},
+ {SMARTBUFF_SOVENGEANCE, 2, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinSeal},
+ {SMARTBUFF_SOBLOOD, 2, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinSeal},
+ {SMARTBUFF_SOCORRUPTION, 2, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinSeal},
+ {SMARTBUFF_SOMARTYR, 2, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinSeal},
+ {SMARTBUFF_DEVOTIONAURA, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinAura},
+ {SMARTBUFF_RETRIBUTIONAURA, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinAura},
+ {SMARTBUFF_CONCENTRATIONAURA, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinAura},
+ {SMARTBUFF_SHADOWRESISTANCEAURA, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinAura},
+ {SMARTBUFF_FROSTRESISTANCEAURA, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinAura},
+ {SMARTBUFF_FIRERESISTANCEAURA, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinAura},
+ {SMARTBUFF_SANCTITYAURA, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinAura},
+ {SMARTBUFF_CRUSADERAURA, -1, SMARTBUFF_CONST_SELF, nil, nil, nil, S.ChainPaladinAura}
+
+ };
+ end
+
+ -- Deathknight
+ if (SMARTBUFF_PLAYERCLASS == "DEATHKNIGHT") then
+ SMARTBUFF_BUFFLIST = {
+ {SMARTBUFF_DANCINGRW, 0.2, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_BLOODPRESENCE, -1, SMARTBUFF_CONST_STANCE, nil, nil, nil, S.ChainDKPresence},
+ {SMARTBUFF_FROSTPRESENCE, -1, SMARTBUFF_CONST_STANCE, nil, nil, nil, S.ChainDKPresence},
+ {SMARTBUFF_UNHOLYPRESENCE, -1, SMARTBUFF_CONST_STANCE, nil, nil, nil, S.ChainDKPresence},
+ {SMARTBUFF_HORNOFWINTER, 60, SMARTBUFF_CONST_SELF, nil, nil, S.LinkAp},
+ {SMARTBUFF_BONESHIELD, 5, SMARTBUFF_CONST_SELF},
+ {SMARTBUFF_RAISEDEAD, 1, SMARTBUFF_CONST_SELF, nil, S.CheckPet},
+ {SMARTBUFF_PATHOFFROST, -1, SMARTBUFF_CONST_SELF}
+ };
+ end
+
+
+ -- Stones and oils
+ SMARTBUFF_WEAPON = {
+ {SMARTBUFF_LESSERMANAOIL, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_BRILLIANTMANAOIL, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_BRILLIANTWIZARDOIL, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_SUPERIORMANAOIL, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_SUPERIORWIZARDOIL, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_OILOFIMMOLATION, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_SOLIDWSTONE, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_SOLIDSSTONE, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_ELEMENTALSSTONE, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_ADAMANTITEWSTONE, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_ADAMANTITESSTONE, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_HEAVYWSTONE, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_HEAVYSSTONE, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_WEIGHSTONE, 60, SMARTBUFF_CONST_INV},
+ {SMARTBUFF_FELSHARPENINGSTONE, 60, SMARTBUFF_CONST_INV},
+ };
+
+ -- Tracking
+ SMARTBUFF_TRACKING = {
+ {SMARTBUFF_FINDMINERALS, -1, SMARTBUFF_CONST_TRACK},
+ {SMARTBUFF_FINDHERBS, -1, SMARTBUFF_CONST_TRACK},
+ {SMARTBUFF_FINDTREASURE, -1, SMARTBUFF_CONST_TRACK},
+ {SMARTBUFF_TRACKHUMANOIDS, -1, SMARTBUFF_CONST_TRACK},
+ {SMARTBUFF_TRACKBEASTS, -1, SMARTBUFF_CONST_TRACK},
+ {SMARTBUFF_TRACKUNDEAD, -1, SMARTBUFF_CONST_TRACK},
+ {SMARTBUFF_TRACKHIDDEN, -1, SMARTBUFF_CONST_TRACK},
+ {SMARTBUFF_TRACKELEMENTALS, -1, SMARTBUFF_CONST_TRACK},
+ {SMARTBUFF_TRACKDEMONS, -1, SMARTBUFF_CONST_TRACK},
+ {SMARTBUFF_TRACKGIANTS, -1, SMARTBUFF_CONST_TRACK},
+ {SMARTBUFF_TRACKDRAGONKIN, -1, SMARTBUFF_CONST_TRACK},
+ {SMARTBUFF_SENSEDEMONS, -1, SMARTBUFF_CONST_TRACK},
+ {SMARTBUFF_SENSEUNDEAD, -1, SMARTBUFF_CONST_TRACK}
+ };
+
+ -- Racial
+ SMARTBUFF_RACIAL = {
+ {SMARTBUFF_STONEFORM, 0.133, SMARTBUFF_CONST_SELF}, -- Dwarv
+ --{SMARTBUFF_PRECEPTION, 0.333, SMARTBUFF_CONST_SELF}, -- Human
+ {SMARTBUFF_BLOODFURY, 0.416, SMARTBUFF_CONST_SELF}, -- Orc
+ {SMARTBUFF_BERSERKING, 0.166, SMARTBUFF_CONST_SELF}, -- Troll
+ {SMARTBUFF_WOTFORSAKEN, 0.083, SMARTBUFF_CONST_SELF}, -- Undead
+ {SMARTBUFF_WarStomp, 0.033, SMARTBUFF_CONST_SELF} -- Tauer
+ };
+
+ -- FOOD
+ SMARTBUFF_FOOD = {
+ {SMARTBUFF_GOLDENFISHSTICKS_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_FISHERMANSFEAST_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_SKULLFISHSOUP_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_SPICYHOTTALBUK_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_BLACKENEDBASILISK_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_BLACKENEDSPOREFISH_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_BUZZARDBITES_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_CLAMBAR_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_CRUNCHYSERPENT_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_FELTAILDELIGHT_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_GRILLEDMUDFISH_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_HELBOARBACON_ITEM, 15, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_MOKNATHAKSHORTRIBS_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_POACHEDBLUEFISH_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_RAVAGERDOG_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_ROASTEDCLEFTHOOF_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_SPICYCRAWDAD_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_TALBUKSTEAK_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_WARPBURGER_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_CHARREDBEARKABOBS_ITEM, 15, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_ORONOKSTUBERSPELL_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_ORONOKSTUBERAGILITY_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_ORONOKSTUBERHEALS_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_ORONOKSTUBERSTRENGTH_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_HOTAPPLECIDER_ITEM, 30, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_SKYGUARDRATIONS_ITEM, 15, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_DIRGESKICKINCHOPS_ITEM, 15, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_JUICYBEARBURGER_ITEM, 15, SMARTBUFF_CONST_FOOD},
+ {SMARTBUFF_NIGHTFINSOUP_ITEM, 10, SMARTBUFF_CONST_FOOD},
+ };
+
+
+ -- Scrolls
+ SMARTBUFF_SCROLL = {
+ {SMARTBUFF_SOAGILITY5, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBAGILITY},
+ {SMARTBUFF_SOAGILITY4, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBAGILITY},
+ {SMARTBUFF_SOAGILITY3, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBAGILITY},
+ {SMARTBUFF_SOAGILITY2, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBAGILITY},
+ {SMARTBUFF_SOAGILITY1, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBAGILITY},
+
+ {SMARTBUFF_SOINTELLECT5, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBINTELLECT},
+ {SMARTBUFF_SOINTELLECT4, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBINTELLECT},
+ {SMARTBUFF_SOINTELLECT3, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBINTELLECT},
+ {SMARTBUFF_SOINTELLECT2, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBINTELLECT},
+ {SMARTBUFF_SOINTELLECT1, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBINTELLECT},
+
+ {SMARTBUFF_SOSTAMINA5, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSTAMINA},
+ {SMARTBUFF_SOSTAMINA4, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSTAMINA},
+ {SMARTBUFF_SOSTAMINA3, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSTAMINA},
+ {SMARTBUFF_SOSTAMINA2, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSTAMINA},
+ {SMARTBUFF_SOSTAMINA1, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSTAMINA},
+
+ {SMARTBUFF_SOSPIRIT5, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSPIRIT},
+ {SMARTBUFF_SOSPIRIT4, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSPIRIT},
+ {SMARTBUFF_SOSPIRIT3, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSPIRIT},
+ {SMARTBUFF_SOSPIRIT2, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSPIRIT},
+ {SMARTBUFF_SOSPIRIT1, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSPIRIT},
+
+ {SMARTBUFF_SOSTRENGHT5, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSTRENGHT},
+ {SMARTBUFF_SOSTRENGHT4, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSTRENGHT},
+ {SMARTBUFF_SOSTRENGHT3, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSTRENGHT},
+ {SMARTBUFF_SOSTRENGHT2, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSTRENGHT},
+ {SMARTBUFF_SOSTRENGHT1, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBSTRENGHT},
+
+ {SMARTBUFF_SOPROTECTION5, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBPROTECTION},
+ {SMARTBUFF_SOPROTECTION4, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBPROTECTION},
+ {SMARTBUFF_SOPROTECTION3, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBPROTECTION},
+ {SMARTBUFF_SOPROTECTION2, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBPROTECTION},
+ {SMARTBUFF_SOPROTECTION1, 30, SMARTBUFF_CONST_SCROLL, nil, SMARTBUFF_SBPROTECTION},
+ };
+
+
+ --- Burning Crusade Classic Potions / Elixirs / Flasks
+
+ SMARTBUFF_POTION = {
+
+ {SMARTBUFF_ADEPTELIXIR_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_ADEPTELIXIR_BUFF},
+ {SMARTBUFF_MAJORDEFENSE_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_MAJORDEFENSE_BUFF},
+ {SMARTBUFF_MAJORAGILITY_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_MAJORAGILITY_BUFF},
+ {SMARTBUFF_DRAENICWISDOM_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_DRAENICWISDOM_BUFF},
+ {SMARTBUFF_MAJORFROSTPOWER_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_MAJORFROSTPOWER_BUFF},
+ {SMARTBUFF_EARTHEN_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_EARTHEN_BUFF},
+ {SMARTBUFF_MASTERY_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_MASTERY_BUFF},
+ {SMARTBUFF_CAMOUFLAGE_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_CAMOUFLAGE_BUFF},
+ {SMARTBUFF_HEALINGPOWER_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_HEALINGPOWER_BUFF},
+ {SMARTBUFF_MAJORFORTITUDE_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_MAJORFORTITUDE_BUFF},
+ {SMARTBUFF_MAJORSTRENGTH_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_MAJORSTRENGTH_BUFF},
+ {SMARTBUFF_ONSLAUGHTELIXIR_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_ONSLAUGHTELIXIR_BUFF},
+ {SMARTBUFF_GREATERARCANE_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_GREATERARCANE_BUFF},
+ {SMARTBUFF_MONGOOSEELIXIR_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_MONGOOSEELIXIR_BUFF},
+ {SMARTBUFF_BRUTEFORCE_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_BRUTEFORCE_BUFF},
+ {SMARTBUFF_SAGESELIXIR_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_SAGESELIXIR_BUFF},
+ {SMARTBUFF_SUPERIORDEFENSE_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_SUPERIORDEFENSE_BUFF},
+ {SMARTBUFF_DEMONSLAYING_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_DEMONSLAYING_BUFF},
+ {SMARTBUFF_MAJORFIREPOWER_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_MAJORFIREPOWER_BUFF},
+ {SMARTBUFF_GREATERFIREPOWER_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_GREATERFIREPOWER_BUFF},
+ {SMARTBUFF_SHADOWPOWER_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_SHADOWPOWER_BUFF},
+ {SMARTBUFF_GIANTSELIXIR_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_GIANTSELIXIR_BUFF},
+ {SMARTBUFF_GREATERAGILITY_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_GREATERAGILITY_BUFF},
+ {SMARTBUFF_GIFTOFARTHAS_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_GIFTOFARTHAS_BUFF},
+ {SMARTBUFF_ARANCEELIXIR_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_ARANCEELIXIR_BUFF},
+ {SMARTBUFF_GREATERINTELLECT_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_GREATERINTELLECT_BUFF},
+ {SMARTBUFF_MAJORNATUREPROT_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_MAJORNATUREPROT_BUFF},
+ {SMARTBUFF_MAJORMAGEBLOOD_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_MAJORMAGEBLOOD_BUFF},
+ {SMARTBUFF_MAJORSHADOWPWR_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_MAJORSHADOWPWR_BUFF},
+ {SMARTBUFF_MAJORIRONSKIN_ITEM, 60, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_MAJORIRONSKIN_BUFF},
+ {SMARTBUFF_BLINDINGLIGHTFLASK_ITEM, 120, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_BLINDINGLIGHTFLASK_BUFF, S.LinkFlaskTBC},
+ {SMARTBUFF_FORTIFICATIONFLASK_ITEM, 120, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_FORTIFICATIONFLASK_BUFF, S.LinkFlaskTBC},
+ {SMARTBUFF_RESTORATIONFLASK_ITEM, 120, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_RESTORATIONFLASK_BUFF, S.LinkFlaskTBC},
+ {SMARTBUFF_PUREDEATHFLASK_ITEM, 120, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_PUREDEATHFLASK_BUFF, S.LinkFlaskTBC},
+ {SMARTBUFF_RELENTLESSFLASK_ITEM, 120, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_RELENTLESSFLASK_BUFF, S.LinkFlaskTBC},
+ {SMARTBUFF_CHROMATICFLASK_ITEM, 120, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_CHROMATICFLASK_BUFF, S.LinkFlaskTBC},
+ {SMARTBUFF_DISTILLEDFLASK_ITEM, 120, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_DISTILLEDFLASK_BUFF, S.LinkFlaskTBC},
+ {SMARTBUFF_HEALINGPOWER_ITEM, 120, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_HEALINGPOWER_BUFF, S.LinkFlaskTBC},
+ {SMARTBUFF_SUPREMEPWRFLASK_ITEM, 120, SMARTBUFF_CONST_POTION, nil, SMARTBUFF_SUPREMEPWRFLASK_BUFF, S.LinkFlaskTBC},
+
+ }
+
+ SMARTBUFF_AddMsgD(">>>> Spell lists have been initialised.");
+
+end
diff --git a/SmartBuff.globals.lua b/SmartBuff.globals.lua
new file mode 100644
index 0000000..2b97256
--- /dev/null
+++ b/SmartBuff.globals.lua
@@ -0,0 +1,61 @@
+-------------------------------------------------------------------------------
+-- SmartBuff
+-- Originally created by Aeldra (EU-Proudmoore)
+-- Classic versions by Codermik (Mik/Castanova/Amarantine EU-Mirage Raceway)
+-- Discord: https://discord.gg/R6EkZ94TKK
+-- Cast the most important buffs on you, tanks or party/raid members/pets.
+-------------------------------------------------------------------------------
+
+-- Globals
+
+
+SMARTBUFF_GLOBALS = { };
+local SG = SMARTBUFF_GLOBALS;
+
+SMARTBUFF_TTC_R = 1;
+SMARTBUFF_TTC_G = 1;
+SMARTBUFF_TTC_B = 1;
+SMARTBUFF_TTC_A = 1;
+
+SMARTBUFF_OPTIONSFRAME_HEIGHT = 630;
+SMARTBUFF_OPTIONSFRAME_WIDTH = 500;
+
+SMARTBUFF_ACTION_ITEM = "item";
+SMARTBUFF_ACTION_SPELL = "spell";
+
+SMARTBUFF_CONST_AUTOSOUND = "Deathbind Sound";
+--SMARTBUFF_CONST_AUTOSOUND = "TaxiNodeDiscovered";
+--SMARTBUFF_CONST_AUTOSOUND = "GLUECREATECHARACTERBUTTON";
+
+--[[
+SystemFont
+GameFontNormal
+GameFontNormalSmall
+GameFontNormalLarge
+GameFontHighlight
+GameFontHighlightSmall
+GameFontHighlightSmallOutline
+GameFontHighlightLarge
+GameFontDisable
+GameFontDisableSmall
+GameFontDisableLarge
+GameFontGreen
+GameFontGreenSmall
+GameFontGreenLarge
+GameFontRed
+GameFontRedSmall
+GameFontRedLarge
+GameFontWhite
+GameFontDarkGraySmall
+NumberFontNormalYellow
+NumberFontNormalSmallGray
+QuestFontNormalSmall
+DialogButtonHighlightText
+ErrorFont
+TextStatusBarText
+CombatLogFont
+NumberFontNormalLarge
+NumberFontNormalHuge
+]]--
+
+
diff --git a/SmartBuff.lua b/SmartBuff.lua
new file mode 100644
index 0000000..d96b00b
--- /dev/null
+++ b/SmartBuff.lua
@@ -0,0 +1,5043 @@
+-------------------------------------------------------------------------------
+-- SmartBuff
+-- Originally created by Aeldra (EU-Proudmoore)
+-- Classic/Retail versions by Codermik (Mik/Castanova/Amarantine EU-Mirage Raceway or Castanova on EU-Aszune)
+-- Discord: https://discord.gg/R6EkZ94TKK
+-- Cast the most important buffs on you, tanks or party/raid members/pets.
+-------------------------------------------------------------------------------
+
+SMARTBUFF_DATE = "190722 Dev";
+SMARTBUFF_VERSION = "r21."..SMARTBUFF_DATE;
+SMARTBUFF_VERSIONMIN = 11403; -- min version
+SMARTBUFF_VERSIONNR = 30400; -- max version
+SMARTBUFF_TITLE = "SmartBuff";
+SMARTBUFF_SUBTITLE = "Supports casting buffs on tanks, selected classes in party or raids.";
+SMARTBUFF_DESC = "Cast the most important buffs on you, tanks, party or raid members/pets";
+SMARTBUFF_VERS_TITLE = SMARTBUFF_TITLE .. " " .. SMARTBUFF_VERSION;
+SMARTBUFF_OPTIONS_TITLE = SMARTBUFF_VERS_TITLE;
+
+-- addon name
+local addonName = ...
+local SmartbuffPrefix = "Smartbuff";
+local SmartbuffSession = true;
+local SmartbuffVerCheck = false; -- for my use when checking guild users/testers versions :)
+local buildInfo = select(4, GetBuildInfo())
+local SmartbuffRevision = 21;
+local SmartbuffVerNotifyList = {}
+
+local LCD = LibStub and LibStub("LibClassicDurations", true)
+if LCD then LCD:Register(SMARTBUFF_TITLE) end
+
+local UnitAuraFull = UnitAura
+if LCD and LCD.UnitAura then UnitAuraFull = function(a, b, c) return LCD:UnitAura(a, b, c) end end
+
+
+local SG = SMARTBUFF_GLOBALS;
+local OG = nil; -- Options global
+local O = nil; -- Options local
+local B = nil; -- Buff settings local
+local _;
+
+BINDING_HEADER_SMARTBUFF = "SmartBuff";
+SMARTBUFF_BOOK_TYPE_SPELL = "spell";
+
+
+local GlobalCd = 1.5;
+local maxSkipCoolDown = 3;
+local maxRaid = 40;
+local maxBuffs = 40;
+local maxScrollButtons = 50;
+local numBuffs = 0;
+
+local isLoaded = false;
+local isPlayer = false;
+local isInit = false;
+local isCombat = false;
+local isSetBuffs = false;
+local isSetZone = false;
+local isFirstError = false;
+local isMounted = false;
+local isCTRA = true;
+local isSetUnits = false;
+local isKeyUpChanged = false;
+local isKeyDownChanged = false;
+local isAuraChanged = false;
+local isClearSplash = false;
+local isRebinding = false;
+local isParrot = false;
+local isSync = false;
+local isSyncReq = false;
+local isInitBtn = false;
+
+local isShapeshifted = false;
+local sShapename = "";
+
+local tStartZone = 0;
+local tTicker = 0;
+local tSync = 0;
+
+local sRealmName = nil;
+local sPlayerName = nil;
+local sID = nil;
+local sPlayerClass = nil;
+local iLastSubgroup = 0;
+local tLastCheck = 0;
+local iGroupSetup = -1;
+local iLastBuffSetup = -1;
+local sLastTexture = "";
+local iLastGroupSetup = -99;
+local sLastZone = "";
+local tAutoBuff = 0;
+local tDebuff = 0;
+local sMsgWarning = "";
+local iCurrentFont = 1;
+local iCurrentList = -1;
+local iLastPlayer = -1;
+
+local isPlayerMoving = false;
+
+local cGroups = { };
+local cClassGroups = { };
+local cBuffs = { };
+local cBuffIndex = { };
+local cBuffTimer = { };
+local cBlacklist = { };
+local cUnits = { };
+local cBuffsCombat = { };
+
+local cScrBtnBO = nil;
+
+local cAddUnitList = { };
+local cIgnoreUnitList = { };
+
+local cClasses = {"DRUID", "HUNTER", "MAGE", "PALADIN", "PRIEST", "ROGUE", "SHAMAN", "WARLOCK", "WARRIOR", "DEATHKNIGHT", "MONK", "DEMONHUNTER", "HPET", "WPET", "DKPET", "TANK", "HEALER", "DAMAGER"};
+local cIgnoreClasses = { 11, 12, 15, 17, 18 };
+local cOrderGrp = {0, 1, 2, 3, 4, 5, 6, 7, 8};
+local cOrderClass = {0, "WARRIOR", "PRIEST", "DRUID", "PALADIN", "SHAMAN", "MAGE", "WARLOCK", "HUNTER", "ROGUE", "TANK", "HPET", "WPET", "DKPET"};
+local cFonts = {"NumberFontNormal", "NumberFontNormalLarge", "NumberFontNormalHuge", "GameFontNormal", "GameFontNormalLarge", "GameFontNormalHuge", "ChatFontNormal", "QuestFont", "MailTextFontNormal", "QuestTitleFont"};
+
+local currentUnit = nil;
+local currentSpell = nil;
+local currentRank = nil;
+local currentTemplate = nil;
+local currentSpec = nil;
+
+local imgSB = "Interface\\Icons\\Spell_Nature_Purge";
+local imgIconOn = "Interface\\AddOns\\SmartBuff\\Icons\\MiniMapButtonEnabled";
+local imgIconOff = "Interface\\AddOns\\SmartBuff\\Icons\\MiniMapButtonDisabled";
+
+local IconPaths = {
+ ["Pet"] = "Interface\\Icons\\spell_nature_spiritwolf",
+ ["Roles"] = "Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES",
+ ["Classes"] = "Interface\\WorldStateFrame\\Icons-Classes",
+};
+
+local Icons = {
+ ["WARRIOR"] = { IconPaths.Classes, 0.00, 0.25, 0.00, 0.25 },
+ ["MAGE"] = { IconPaths.Classes, 0.25, 0.50, 0.00, 0.25 },
+ ["ROGUE"] = { IconPaths.Classes, 0.50, 0.75, 0.00, 0.25 },
+ ["DRUID"] = { IconPaths.Classes, 0.75, 1.00, 0.00, 0.25 },
+ ["HUNTER"] = { IconPaths.Classes, 0.00, 0.25, 0.25, 0.50 },
+ ["SHAMAN"] = { IconPaths.Classes, 0.25, 0.50, 0.25, 0.50 },
+ ["PRIEST"] = { IconPaths.Classes, 0.50, 0.75, 0.25, 0.50 },
+ ["WARLOCK"] = { IconPaths.Classes, 0.75, 1.00, 0.25, 0.50 },
+ ["PALADIN"] = { IconPaths.Classes, 0.00, 0.25, 0.50, 0.75 },
+ ["DEATHKNIGHT"] = { IconPaths.Classes, 0.25, 0.50, 0.50, 0.75 },
+ ["MONK"] = { IconPaths.Classes, 0.50, 0.75, 0.50, 0.75 },
+ ["DEMONHUNTER"] = { IconPaths.Classes, 0.75, 1.00, 0.50, 0.75 },
+ ["PET"] = { IconPaths.Pet, 0.08, 0.92, 0.08, 0.92},
+ ["TANK"] = { IconPaths.Roles, 0.0, 19/64, 22/64, 41/64 },
+ ["HEALER"] = { IconPaths.Roles, 20/64, 39/64, 1/64, 20/64 },
+ ["DAMAGER"] = { IconPaths.Roles, 20/64, 39/64, 22/64, 41/64 },
+ ["NONE"] = { IconPaths.Roles, 20/64, 39/64, 22/64, 41/64 },
+};
+
+local DebugChatFrame = DEFAULT_CHAT_FRAME;
+
+-- upvalues
+local UnitCastingInfo = _G.UnitCastingInfo or _G.CastingInfo
+local UnitChannelInfo = _G.UnitChannelInfo or _G.ChannelInfo
+local GetNumSpecGroups = _G.GetNumSpecGroups or function(...) return 1 end
+local IsActiveBattlefieldArena = _G.IsActiveBattlefieldArena or function(...) return false end
+
+-- Popup
+StaticPopupDialogs["SMARTBUFF_DATA_PURGE"] = {
+ text = SMARTBUFF_OFT_PURGE_DATA,
+ button1 = SMARTBUFF_OFT_YES,
+ button2 = SMARTBUFF_OFT_NO,
+ OnAccept = function() SMARTBUFF_ResetAll() end,
+ timeout = 0,
+ whileDead = 1,
+ hideOnEscape = 1
+}
+
+-- Rounds a number to the given number of decimal places.
+local r_mult;
+local function Round(num, idp)
+ r_mult = 10^(idp or 0);
+ return math.floor(num * r_mult + 0.5) / r_mult;
+end
+
+-- Returns a chat color code string
+local function BCC(r, g, b)
+ return string.format("|cff%02x%02x%02x", (r*255), (g*255), (b*255));
+end
+
+local BL = BCC(0, 0, 1);
+local BLD = BCC(0, 0, 0.7);
+local BLL = BCC(0.5, 0.8, 1);
+local GR = BCC(0, 1, 0);
+local GRD = BCC(0, 0.7, 0);
+local GRL = BCC(0.6, 1, 0.6);
+local RD = BCC(1, 0, 0);
+local RDD = BCC(0.7, 0, 0);
+local RDL = BCC(1, 0.3, 0.3);
+local YL = BCC(1, 1, 0);
+local YLD = BCC(0.7, 0.7, 0);
+local YLL = BCC(1, 1, 0.5);
+local OR = BCC(1, 0.7, 0);
+local ORD = BCC(0.7, 0.5, 0);
+local ORL = BCC(1, 0.6, 0.3);
+local WH = BCC(1, 1, 1);
+local CY = BCC(0.5, 1, 1);
+
+-- Reorders values in the table
+local function treorder(t, i, n)
+ if (t and type(t) == "table" and t[i]) then
+ local s = t[i];
+ tremove(t, i);
+ if (i + n < 1) then
+ tinsert(t, 1, s);
+ elseif (i + n > #t) then
+ tinsert(t, s);
+ else
+ tinsert(t, i + n, s);
+ end
+ end
+end
+
+-- Finds a value in the table and returns the index
+local function tfind(t, s)
+ if (t and type(t) == "table" and s) then
+ for k, v in pairs(t) do
+ if (v and v == s) then
+ return k;
+ end
+ end
+ end
+ return false;
+end
+
+local function tcontains(t, s)
+ if (t and type(t) == "table" and s) then
+ for _, v in ipairs(t) do
+ if (v == s) then
+ return true;
+ end
+ end
+ end
+ return false;
+end
+
+function strim(s)
+ return (s:gsub("^%s*(.-)%s*$", "%1"))
+end
+
+local function ChkS(text)
+ if (text == nil) then
+ text = "";
+ end
+ return text;
+end
+
+local function IsFlying()
+ local result = GetShapeshiftForm(false)
+ -- bugfix 6/7/2022, frost/shadow/sanct aura on paladin was causing the
+ -- GetShapeshiftForm to return 5 faking the addon into thinking the
+ -- player was actually flying on a druid. CM
+ if (result == 5 or result == 6) and sPlayerClass == "DRUID" then
+ return true
+ end
+ return false
+end
+
+local function UnitInVehicle(unit)
+ return false
+end
+
+local function UnitHasVehicleUI(unit)
+ return false
+end
+
+local function UnitGroupRolesAssigned(unit)
+ -- dont bother if we dont have assigned tanks
+ if cClassGroups then
+ if cClassGroups["TANK"] then
+ for n = 1, maxRaid, 1 do
+ local u = cClassGroups["TANK"][n]
+ if u and u == unit then
+ name, rank, subgroup, level, class, classeng, zone, online, isDead, role = GetRaidRosterInfo(n)
+ if role and role == "MAINTANK" then
+ return "TANK"
+ end
+ end
+ end
+ end
+ end
+ return "NONE"
+end
+
+local function IsVisibleToPlayer(self)
+ if (not self) then return false; end
+
+ local w, h = UIParent:GetWidth(), UIParent:GetHeight();
+ local x, y = self:GetLeft(), UIParent:GetHeight() - self:GetTop();
+
+ --print(format("w = %.0f, h = %.0f, x = %.0f, y = %.0f", w, h, x, y));
+ if (x >= 0 and x < (w - self:GetWidth()) and y >= 0 and y < (h - self:GetHeight())) then
+ return true;
+ end
+ return false;
+end
+
+
+local function CS()
+ if (currentSpec == nil) then
+ currentSpec = GetSpecialization();
+ end
+ if (currentSpec == nil) then
+ currentSpec = 1;
+ end
+ return currentSpec;
+end
+
+local function CT()
+ return currentTemplate;
+end
+
+local function GetBuffSettings(buff)
+ if (B and buff) then
+ return B[CS()][CT()][buff];
+ end
+ return nil;
+end
+
+local function InitBuffSettings(cBI, reset)
+ local buff = cBI.BuffS;
+ local cBuff = GetBuffSettings(buff);
+ if (cBuff == nil) then
+ B[CS()][CT()][buff] = { };
+ cBuff = B[CS()][CT()][buff];
+ reset = true;
+ end
+
+ if (reset) then
+ wipe(cBuff);
+ cBuff.EnableS = false;
+ cBuff.EnableG = false;
+ cBuff.SelfOnly = false;
+ cBuff.SelfNot = false;
+ cBuff.CIn = false;
+ cBuff.COut = true;
+ cBuff.MH = false;
+ cBuff.OH = false;
+ cBuff.RH = false;
+ cBuff.Reminder = true;
+ cBuff.RBTime = 0;
+ cBuff.ManaLimit = 0;
+ if (cBI.Type == SMARTBUFF_CONST_GROUP or cBI.Type == SMARTBUFF_CONST_ITEMGROUP) then
+ for n in pairs(cClasses) do
+ if (cBI.Type == SMARTBUFF_CONST_GROUP and not tcontains(cIgnoreClasses, n) and not string.find(cBI.Params, cClasses[n])) then
+ cBuff[cClasses[n]] = true;
+ else
+ cBuff[cClasses[n]] = false;
+ end
+ end
+ end
+ end
+
+ -- Upgrades
+ if (cBuff.RBTime == nil) then cBuff.Reminder = true; cBuff.RBTime = 0; end -- to 1.10g
+ if (cBuff.ManaLimit == nil) then cBuff.ManaLimit = 0; end -- to 1.12b
+ if (cBuff.SelfNot == nil) then cBuff.SelfNot = false; end -- to 2.0i
+ if (cBuff.AddList == nil) then cBuff.AddList = { }; end -- to 2.1a
+ if (cBuff.IgnoreList == nil) then cBuff.IgnoreList = { }; end -- to 2.1a
+ if (cBuff.RH == nil) then cBuff.RH = false; end -- to 4.0b
+
+end
+
+local function InitBuffOrder(reset)
+ if (B[CS()].Order == nil) then
+ B[CS()].Order = { };
+ end
+
+ local b;
+ local i;
+ local ord = B[CS()].Order;
+ if (reset) then
+ wipe(ord);
+ SMARTBUFF_AddMsgD("Reset buff order");
+ end
+
+ -- Remove not longer existing buffs in the order list
+ for k, v in pairs(ord) do
+ if (v and cBuffIndex[v] == nil) then
+ SMARTBUFF_AddMsgD("Remove from buff order: "..v);
+ tremove(ord, k);
+ end
+ end
+
+ i = 1;
+ while (cBuffs[i] and cBuffs[i].BuffS) do
+ b = false;
+ for _, v in pairs(ord) do
+ if (v and v == cBuffs[i].BuffS) then
+ b = true;
+ break;
+ end
+ end
+ -- buff not found add it to order list
+ if (not b) then
+ tinsert(ord, cBuffs[i].BuffS);
+ SMARTBUFF_AddMsgD("Add to buff order: "..cBuffs[i].BuffS);
+ end
+ i = i + 1;
+ end
+end
+
+local function IsMinLevel(minLevel)
+ if (not minLevel) then
+ return true;
+ end
+ if (minLevel > UnitLevel("player")) then
+ return false;
+ end
+ return true;
+end
+
+local function IsPowerLimitOk(bs)
+ -- Check for power threshold
+ if (bs.ManaLimit and bs.ManaLimit > 0) then
+ local powerType, powerToken = UnitPowerType("player");
+ -- if bs.ManaLimit <= 100 and powertype is mana then the ManaLimit is %
+ if (bs.ManaLimit <= 100 and powerType == 0) then
+ if (((UnitPower("player", powerType) / UnitPowerMax("player", powerType))) * 100 < bs.ManaLimit) then
+ --print(powerToken.." is below % threshold!");
+ return false;
+ end
+ elseif (UnitPower("player", powerType) < bs.ManaLimit) then
+ --print(powerToken.." is below threshold!");
+ return false;
+ end
+ end
+ return true;
+end
+
+local function IsPlayerInGuild()
+ return IsInGuild() -- and GetGuildInfo("player")
+end
+
+local function SendSmartbuffVersion(player, unit)
+ -- if ive announced to this player / the player is me then just return.
+ if player == UnitName("player") then return end
+ for count,value in ipairs(SmartbuffVerNotifyList) do
+ if value[1] == player then return end
+ end
+ -- not announced, add the player and announce.
+ tinsert(SmartbuffVerNotifyList, {player, unit, GetTime()})
+ C_ChatInfo.SendAddonMessage(SmartbuffPrefix, SmartbuffRevision, "WHISPER", player)
+ SMARTBUFF_AddMsgD(string.format("%s was sent version information.",player))
+end
+
+-- SMARTBUFF_OnLoad
+function SMARTBUFF_OnLoad(self)
+
+ self:RegisterEvent("ADDON_LOADED");
+ self:RegisterEvent("PLAYER_LOGIN");
+ self:RegisterEvent("PLAYER_ENTERING_WORLD");
+ self:RegisterEvent("UNIT_NAME_UPDATE");
+ self:RegisterEvent("GROUP_ROSTER_UPDATE");
+ self:RegisterEvent("PLAYER_REGEN_ENABLED");
+ self:RegisterEvent("PLAYER_REGEN_DISABLED");
+ self:RegisterEvent("PLAYER_STARTED_MOVING");
+ self:RegisterEvent("PLAYER_STOPPED_MOVING");
+ self:RegisterEvent("SPELLS_CHANGED");
+ self:RegisterEvent("ACTIONBAR_HIDEGRID");
+ self:RegisterEvent("UNIT_AURA");
+ self:RegisterEvent("CHAT_MSG_ADDON");
+ self:RegisterEvent("CHAT_MSG_CHANNEL");
+ self:RegisterEvent("UPDATE_MOUSEOVER_UNIT");
+ self:RegisterEvent("UNIT_SPELLCAST_FAILED");
+ self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED");
+
+ --One of them allows SmartBuff to be closed with the Escape key
+ tinsert(UISpecialFrames, "SmartBuffOptionsFrame");
+ UIPanelWindows["SmartBuffOptionsFrame"] = nil;
+
+ -- setup command line.
+ SlashCmdList["SMARTBUFF"] = SMARTBUFF_command;
+ SLASH_SMARTBUFF1 = "/sbo";
+ SLASH_SMARTBUFF2 = "/sbuff";
+ SLASH_SMARTBUFF3 = "/smartbuff";
+ SlashCmdList["SMARTBUFFMENU"] = SMARTBUFF_OptionsFrame_Toggle;
+ SLASH_SMARTBUFFMENU1 = "/sbm";
+ SlashCmdList["SmartReloadUI"] = function(msg) ReloadUI(); end;
+ SLASH_SmartReloadUI1 = "/rui";
+
+ SMARTBUFF_InitSpellIDs();
+ --DEFAULT_CHAT_FRAME:AddMessage("SB OnLoad");
+end
+-- END SMARTBUFF_OnLoad
+
+
+-------------------------------------------------------------------------------------------------------------------------------------
+-- SmartBuff Event Handler ---------------------------------------------------------------------------------------------------------
+-------------------------------------------------------------------------------------------------------------------------------------
+function SMARTBUFF_OnEvent(self, event, ...)
+ local arg1, arg2, arg3, arg4, arg5 = ...;
+
+ -- UNIT_NAME_UPDATE / PLAYER_ENTERING_WORLD
+ if ((event == "UNIT_NAME_UPDATE" and arg1 == "player") or event == "PLAYER_ENTERING_WORLD") then
+ if IsPlayerInGuild() and event == "PLAYER_ENTERING_WORLD" then
+ C_ChatInfo.SendAddonMessage(SmartbuffPrefix, SmartbuffRevision, "GUILD")
+ end
+ isPlayer = true;
+ if (event == "PLAYER_ENTERING_WORLD" and isInit and O.Toggle) then
+ isSetZone = true;
+ tStartZone = GetTime();
+ end
+
+ -- ADDON_LOADED
+ elseif(event == "ADDON_LOADED" and arg1 == SMARTBUFF_TITLE) then
+ isLoaded = true;
+ end
+
+ -- PLAYER_LOGIN
+ if event == "PLAYER_LOGIN" then
+ local prefixResult = C_ChatInfo.RegisterAddonMessagePrefix(SmartbuffPrefix)
+ end
+
+ -- CHAT_MSG_ADDON
+ if event == "CHAT_MSG_ADDON" then
+ if arg1 == SmartbuffPrefix then
+ -- its us.
+ if arg2 then
+ arg2 = tonumber(arg2)
+ if arg2 > SmartbuffRevision and SmartbuffSession then
+ -- detected a newer version of the addon, lets let the player know.
+ DEFAULT_CHAT_FRAME:AddMessage(SMARTBUFF_MSG_NEWVER1..SMARTBUFF_VERSION..SMARTBUFF_MSG_NEWVER2..arg2..SMARTBUFF_MSG_NEWVER3)
+ SmartbuffSession = false
+ end
+ -- guild version check - for my use testing the addon with the guild testers. --
+ if arg5 and arg5 ~= UnitName("player") and SmartbuffVerCheck then
+ DEFAULT_CHAT_FRAME:AddMessage("|cff00e0ffSmartbuff : |cffFFFF00"..arg5.." ("..arg3..")|cffffffff has revision |cffFFFF00r"..arg2.."|cffffffff installed.")
+ end
+ end
+ end
+ end
+
+ -- SMARTBUFF_UPDATE
+ if (event == "SMARTBUFF_UPDATE" and isLoaded and isPlayer and not isInit and not InCombatLockdown()) then
+ SMARTBUFF_Options_Init(self);
+ end
+
+ if (not isInit or O == nil) then
+ return;
+ end;
+
+ -- GROUP_ROSTER_UPDATE
+ if (event == "GROUP_ROSTER_UPDATE") then
+ isSetUnits = true;
+
+ -- PLAYER_REGEN_DISABLED
+ elseif (event == "PLAYER_REGEN_DISABLED") then
+ SMARTBUFF_Ticker(true);
+
+ if (O.Toggle) then
+ if (O.InCombat) then
+ for spell, data in pairs(cBuffsCombat) do
+ if (data and data.Unit and data.ActionType) then
+ if (data.Type == SMARTBUFF_CONST_SELF or data.Type == SMARTBUFF_CONST_FORCESELF or data.Type == SMARTBUFF_CONST_STANCE or data.Type == SMARTBUFF_CONST_ITEM) then
+ SmartBuff_KeyButton:SetAttribute("unit", nil);
+ else
+ SmartBuff_KeyButton:SetAttribute("unit", data.Unit);
+ end
+ SmartBuff_KeyButton:SetAttribute("type", data.ActionType);
+ SmartBuff_KeyButton:SetAttribute("spell", spell);
+ SmartBuff_KeyButton:SetAttribute("item", nil);
+ SmartBuff_KeyButton:SetAttribute("target-slot", nil);
+ SmartBuff_KeyButton:SetAttribute("target-item", nil);
+ SmartBuff_KeyButton:SetAttribute("macrotext", nil);
+ SmartBuff_KeyButton:SetAttribute("action", nil);
+ SMARTBUFF_AddMsgD("Enter Combat, set button: " .. spell .. " on " .. data.Unit .. ", " .. data.ActionType);
+ break;
+ end
+ end
+ end
+ SMARTBUFF_SyncBuffTimers();
+ SMARTBUFF_Check(1, true);
+ end
+
+ -- PLAYER_REGEN_ENABLED
+ elseif (event == "PLAYER_REGEN_ENABLED") then
+ SMARTBUFF_Ticker(true);
+ if (O.Toggle) then
+ if (O.InCombat) then
+ SmartBuff_KeyButton:SetAttribute("type", nil);
+ SmartBuff_KeyButton:SetAttribute("unit", nil);
+ SmartBuff_KeyButton:SetAttribute("spell", nil);
+ end
+ SMARTBUFF_SyncBuffTimers();
+ SMARTBUFF_Check(1, true);
+ end
+
+ -- PLAYER_STARTED_MOVING / PLAYER_STOPPED_MOVING
+ elseif (event == "PLAYER_STARTED_MOVING") then
+ isPlayerMoving = true;
+
+ elseif (event == "PLAYER_STOPPED_MOVING") then
+ isPlayerMoving = false;
+
+ -- SPELLS_CHANGED / ACTIONBAR_HIDEGRID
+ elseif (event == "SPELLS_CHANGED" or event == "ACTIONBAR_HIDEGRID") then
+ isSetBuffs = true;
+ end
+
+ if (not O.Toggle) then
+ return;
+ end;
+
+ -- UNIT_AURA
+ if (event == "UNIT_AURA") then
+ if (UnitAffectingCombat("player") and (arg1 == "player" or string.find(arg1, "^party") or string.find(arg1, "^raid"))) then
+ isSyncReq = true;
+ end
+ -- checks if aspect of cheetah or pack is active and cancel it if someone gets dazed
+ if (sPlayerClass == "HUNTER" and O.AntiDaze and (arg1 == "player" or string.find(arg1, "^party") or string.find(arg1, "^raid") or string.find(arg1, "pet"))) then
+ local _, _, stuntex = GetSpellInfo(1604); --get Dazed icon
+ if (SMARTBUFF_IsDebuffTexture(arg1, stuntex)) then
+ buff = nil;
+ if (arg1 == "player" and SMARTBUFF_CheckBuff(arg1, SMARTBUFF_AOTC)) then
+ buff = SMARTBUFF_AOTC;
+ elseif (SMARTBUFF_CheckBuff(arg1, SMARTBUFF_AOTP, true)) then
+ buff = SMARTBUFF_AOTP;
+ end
+ if (buff) then
+ if (O.ToggleAutoSplash and not SmartBuffOptionsFrame:IsVisible()) then
+ SmartBuffSplashFrame:Clear();
+ SmartBuffSplashFrame:SetTimeVisible(1);
+ SmartBuffSplashFrame:AddMessage("!!! CANCEL "..buff.." !!!", O.ColSplashFont.r, O.ColSplashFont.g, O.ColSplashFont.b, 1.0);
+ end
+ if (O.ToggleAutoChat) then
+ SMARTBUFF_AddMsgWarn("!!! CANCEL "..buff.." !!!", true);
+ end
+ end
+ end
+ end
+ end
+
+ -- UI_ERROR_MESSAGE
+ if (event == "UI_ERROR_MESSAGE") then
+ SMARTBUFF_AddMsgD(string.format("Error message: %s",arg1));
+ end
+
+ -- UNIT_SPELLCAST_FAILED
+ if (event == "UNIT_SPELLCAST_FAILED") then
+ currentUnit = arg1;
+ SMARTBUFF_AddMsgD(string.format("Spell failed: %s",arg1));
+ if (currentUnit and (string.find(currentUnit, "party") or string.find(currentUnit, "raid") or (currentUnit == "target" and O.Debug))) then
+ if (UnitName(currentUnit) ~= sPlayerName and O.BlacklistTimer > 0) then
+ cBlacklist[currentUnit] = GetTime();
+ if (currentUnit and UnitName(currentUnit)) then
+ SMARTBUFF_AddMsgWarn(UnitName(currentUnit).." ("..currentUnit..") blacklisted ("..O.BlacklistTimer.."sec)");
+ end
+ end
+ end
+ currentUnit = nil;
+
+ -- UNIT_SPELLCAST_SUCCEEDED
+ elseif (event == "UNIT_SPELLCAST_SUCCEEDED") then
+ if (arg1 and arg1 == "player") then
+ local unit = nil;
+ local spell = nil;
+ local target = nil;
+
+ if (arg1 and arg2) then
+ if (not arg3) then arg3 = ""; end
+ if (not arg4) then arg4 = ""; end
+ SMARTBUFF_AddMsgD("Spellcast succeeded: " .. arg1 .. ", " .. arg2 .. ", " .. arg3 .. ", " .. arg4)
+ if (string.find(arg1, "party") or string.find(arg1, "raid")) then
+ spell = arg2;
+ end
+ --SMARTBUFF_SetButtonTexture(SmartBuff_KeyButton, imgSB);
+ end
+ if (currentUnit and currentSpell and currentUnit ~= "target") then
+ unit = currentUnit;
+ spell = currentSpell;
+ end
+ if (unit) then
+ local name = UnitName(unit);
+ if (cBuffTimer[unit] == nil) then
+ cBuffTimer[unit] = { };
+ end
+ --if (not SMARTBUFF_IsPlayer(unit)) then
+ cBuffTimer[unit][spell] = GetTime();
+ --end
+ if (name ~= nil) then
+ SMARTBUFF_AddMsg(name .. ": " .. spell .. " " .. SMARTBUFF_MSG_BUFFED);
+ currentUnit = nil;
+ currentSpell = nil;
+ currentRank = nil;
+ end
+ end
+ if (isClearSplash) then
+ isClearSplash = false;
+ SMARTBUFF_Splash_Clear();
+ end
+ end
+ end
+
+end
+
+-------------------------------------------------------------------------------------------------------------------------------------
+-- SMARTBUFF_OnUpdate --------------------------------------------------------------------------------------------------------------
+-------------------------------------------------------------------------------------------------------------------------------------
+function SMARTBUFF_OnUpdate(self, elapsed)
+ if not self.Elapsed then
+ self.Elapsed = 0.2
+ end
+ self.Elapsed = self.Elapsed - elapsed
+ if self.Elapsed > 0 then
+ return
+ end
+ self.Elapsed = 0.2
+
+ if (not isInit) then
+ if (isLoaded and GetTime() > tAutoBuff + 0.5) then
+ tAutoBuff = GetTime();
+ _, tName = GetTalentInfo(1, 1, 1);
+ if (tName) then
+ SMARTBUFF_OnEvent(self, "SMARTBUFF_UPDATE");
+ end
+ end
+ else
+ if (isSetZone and GetTime() > (tStartZone + 4)) then
+ SMARTBUFF_CheckLocation();
+ end
+ SMARTBUFF_Ticker();
+ SMARTBUFF_Check(1);
+ end
+end
+
+-------------------------------------------------------------------------------------------------------------------------------------
+-- SMARTBUFF_Ticker ----------------------------------------------------------------------------------------------------------------
+-------------------------------------------------------------------------------------------------------------------------------------
+function SMARTBUFF_Ticker(force)
+ if (force or GetTime() > tTicker + 1) then
+ tTicker = GetTime();
+
+ if (isSetUnits) then
+ isSetUnits = false;
+ SMARTBUFF_SetUnits();
+ isSyncReq = true;
+ end
+
+ if (isSyncReq or tTicker > tSync + 10) then
+ SMARTBUFF_SyncBuffTimers();
+ end
+
+ if (isAuraChanged) then
+ isAuraChanged = false;
+ --SMARTBUFF_AddMsgD("Force check");
+ SMARTBUFF_Check(1, true);
+ end
+
+ end
+end
+
+-------------------------------------------------------------------------------------------------------------------------------------
+--
+-- SMARTBUFF_AddMsg
+-- SMARTBUFF_AddMsgErr
+-- SMARTBUFF_AddMsgWarn
+-- SMARTBUFF_AddMsgD
+--
+-------------------------------------------------------------------------------------------------------------------------------------
+function SMARTBUFF_AddMsg(msg, force)
+ if (DEFAULT_CHAT_FRAME and (force or not O.ToggleMsgNormal)) then
+ DEFAULT_CHAT_FRAME:AddMessage(YLL .. msg .. "|r");
+ end
+end
+
+function SMARTBUFF_AddMsgErr(msg, force)
+ if (DEFAULT_CHAT_FRAME and (force or not O.ToggleMsgError)) then
+ DEFAULT_CHAT_FRAME:AddMessage(RDL .. SMARTBUFF_TITLE .. ": " .. msg .. "|r");
+ end
+end
+
+function SMARTBUFF_AddMsgWarn(msg, force)
+ if (DEFAULT_CHAT_FRAME and (force or not O.ToggleMsgWarning)) then
+ if (isParrot) then
+ Parrot:ShowMessage(CY .. msg .. "|r");
+ else
+ DEFAULT_CHAT_FRAME:AddMessage(CY .. msg .. "|r");
+ end
+ end
+end
+
+function SMARTBUFF_AddMsgD(msg, r, g, b)
+ if (r == nil) then r = 0.5; end
+ if (g == nil) then g = 0.8; end
+ if (b == nil) then b = 1; end
+ if (DebugChatFrame and O and O.Debug) then
+ DebugChatFrame:AddMessage(msg, r, g, b);
+ end
+end
+
+
+-------------------------------------------------------------------------------------------------------------------------------------
+-- SMARTBUFF_SetUnits()
+-- Creates a array of units in a party or raid.
+-------------------------------------------------------------------------------------------------------------------------------------
+
+function SMARTBUFF_SetUnits()
+ --if (not isInit or not O.Toggle) then return; end
+ if (InCombatLockdown()) then
+ isSetUnits = true;
+ return;
+ end
+ if (SmartBuffOptionsFrame:IsVisible()) then return; end
+
+ local i = 0;
+ local n = 0;
+ local j = 0;
+ local s = nil;
+ local psg = 0;
+ local b = false;
+ local iBFA = SMARTBUFF_IsActiveBattlefield();
+
+ if (iBFA > 0) then
+ SMARTBUFF_CheckLocation();
+ end
+
+ -- player
+ -- pet
+ -- party1-4
+ -- partypet1-4
+ -- raid1-40
+ -- raidpet1-40
+
+ iGroupSetup = -1;
+ if (IsInRaid()) then
+ iGroupSetup = 3;
+ elseif (GetNumSubgroupMembers() ~= 0) then
+ iGroupSetup = 2;
+ else
+ iGroupSetup = 1;
+ end
+
+ if (iGroupSetup ~= iLastGroupSetup) then
+ iLastGroupSetup = iGroupSetup;
+ wipe(cBlacklist);
+ wipe(cBuffTimer);
+ if (SMARTBUFF_TEMPLATES[iGroupSetup] == nil) then
+ SMARTBUFF_SetBuffs();
+ end
+ local tmp = SMARTBUFF_TEMPLATES[iGroupSetup];
+ if (O.AutoSwitchTemplate and currentTemplate ~= tmp and iBFA == 0) then
+ SMARTBUFF_AddMsg(SMARTBUFF_OFT_AUTOSWITCHTMP .. ": " .. currentTemplate .. " -> " .. tmp);
+ currentTemplate = tmp;
+ SMARTBUFF_SetBuffs();
+ end
+ SMARTBUFF_MiniGroup_Show();
+ --SMARTBUFF_AddMsgD("Group type changed");
+ end
+
+ wipe(cUnits);
+ wipe(cGroups);
+ cClassGroups = nil;
+ wipe(cAddUnitList);
+ wipe(cIgnoreUnitList);
+
+ -- Raid Setup
+ if (iGroupSetup == 3) then
+ cClassGroups = { };
+ local name, server, rank, subgroup, level, class, classeng, zone, online, isDead, role;
+ local sRUnit = nil;
+
+ j = 1;
+ for n = 1, maxRaid, 1 do
+ -- GetRaidRosterInfo role returns "MAINTANK" or "MAINASSIST"
+ name, rank, subgroup, level, class, classeng, zone, online, isDead, role = GetRaidRosterInfo(n);
+ if (name) then
+ server = nil;
+ i = string.find(name, "-", 1, true);
+ if (i and i > 0) then
+ server = string.sub(name, i + 1);
+ name = string.sub(name, 1, i - 1);
+ SMARTBUFF_AddMsgD(name .. ", " .. server);
+ end
+ sRUnit = "raid"..n;
+
+ -- Debug ----------------------------------------------------------------------------------------
+-- if role then print("Player: ".. name .. ", " .. sRUnit .. ", " .. role); end
+
+ SMARTBUFF_AddUnitToClass("raid", n, role);
+ SmartBuff_AddToUnitList(1, sRUnit, subgroup);
+ SmartBuff_AddToUnitList(2, sRUnit, subgroup);
+
+ if (name == sPlayerName and not server) then
+ psg = subgroup;
+ end
+
+ if (O.ToggleGrp[subgroup]) then
+ s = "";
+ if (name == UnitName(sRUnit)) then
+ if (cGroups[subgroup] == nil) then
+ cGroups[subgroup] = { };
+ end
+ if (name == sPlayerName and not server) then b = true; end
+ cGroups[subgroup][j] = sRUnit;
+ j = j + 1;
+ end
+ end
+ -- attempt to announce the addon version (if they have it)
+ if online then SendSmartbuffVersion(name, sRUnit) end
+ end
+ end --end for
+
+ if (not b or B[CS()][currentTemplate].SelfFirst) then
+ SMARTBUFF_AddSoloSetup();
+ iLastSubgroup = psg;
+ --SMARTBUFF_AddMsgD("Player not in selected groups or buff self first");
+ end
+
+ if (iLastSubgroup ~= psg) then
+ SMARTBUFF_AddMsgWarn(SMARTBUFF_TITLE .. ": " .. SMARTBUFF_MSG_SUBGROUP);
+ if (O.ToggleSubGrpChanged) then
+ O.ToggleGrp[psg] = true;
+ if (SmartBuffOptionsFrame:IsVisible()) then
+ SMARTBUFF_ShowSubGroupsOptions();
+ else
+ SMARTBUFF_OptionsFrame_Open();
+ end
+ end
+ iLastSubgroup = psg;
+ end
+
+ SMARTBUFF_AddMsgD("Raid Unit-Setup finished");
+
+ -- Party Setup
+ elseif (iGroupSetup == 2) then
+
+ cClassGroups = { };
+ if (B[CS()][currentTemplate].SelfFirst) then
+ SMARTBUFF_AddSoloSetup();
+ end
+ cGroups[1] = { };
+ cGroups[1][0] = "player";
+ SMARTBUFF_AddUnitToClass("player", 0, nil);
+ for j = 1, 4, 1 do
+ cGroups[1][j] = "party"..j;
+ SMARTBUFF_AddUnitToClass("party", j, nil);
+ SmartBuff_AddToUnitList(1, "party"..j, 1);
+ SmartBuff_AddToUnitList(2, "party"..j, 1);
+ name, _, _, _, _, _, _, online, _, _ = GetRaidRosterInfo(j);
+ if name and online then SendSmartbuffVersion(name, "party") end
+
+ -- debug
+-- if name then print("Player: ".. name .. ", " .. "party"..j .. "."); end
+
+
+ end
+ SMARTBUFF_AddMsgD("Party Unit-Setup finished");
+
+ -- Solo Setup
+ else
+ SMARTBUFF_AddSoloSetup();
+ SMARTBUFF_AddMsgD("Solo Unit-Setup finished");
+ end
+
+ collectgarbage();
+end
+
+
+-------------------------------------------------------------------------------------------------------------------------------------
+-- SMARTBUFF_AddUnitToClass --------------------------------------------------------------------------------------------------------
+-------------------------------------------------------------------------------------------------------------------------------------
+function SMARTBUFF_AddUnitToClass(unit, i, proll)
+ local u = unit;
+ local up = "pet";
+ if (unit ~= "player") then
+ u = unit..i;
+ up = unit.."pet"..i;
+ end
+ if (UnitExists(u)) then
+ if (not cUnits[1]) then
+ cUnits[1] = { };
+ end
+ cUnits[1][i] = u;
+ SMARTBUFF_AddMsgD("Unit added: " .. UnitName(u) .. ", " .. u);
+
+ local _, uc = UnitClass(u);
+ if (uc and not cClassGroups[uc]) then
+ cClassGroups[uc] = { };
+ else
+ if u and uc then
+ cClassGroups[uc][i] = u;
+ end
+ end
+
+ if uc and proll == "MAINTANK" then
+ if (not cClassGroups["TANK"]) then
+ cClassGroups["TANK"] = { };
+ end
+ cClassGroups["TANK"][i] = u;
+ end;
+
+ if (uc and uc == "HUNTER") then
+ if (not cClassGroups["HPET"]) then
+ cClassGroups["HPET"] = { };
+ end
+ cClassGroups["HPET"][i] = up;
+
+ elseif (uc and uc == "DEATHKNIGHT") then
+ if (not cClassGroups["DKPET"]) then
+ cClassGroups["DKPET"] = { };
+ end
+ cClassGroups["DKPET"][i] = up;
+
+ elseif (uc and (uc == "WARLOCK" or uc == "MAGE")) then
+ if (not cClassGroups["WPET"]) then
+ cClassGroups["WPET"] = { };
+ end
+ cClassGroups["WPET"][i] = up;
+ end
+
+ end
+end
+
+function SMARTBUFF_AddSoloSetup()
+ cGroups[0] = { };
+ cGroups[0][0] = "player";
+ cUnits[0] = { };
+ cUnits[0][0] = "player";
+ if (sPlayerClass == "HUNTER" or sPlayerClass == "WARLOCK" or sPlayerClass == "MAGE") then cGroups[0][1] = "pet"; end
+ if (B[CS()][currentTemplate]) then
+ if (not cClassGroups) then
+ cClassGroups = { };
+ end
+ cClassGroups[0] = { };
+ cClassGroups[0][0] = "player";
+ end
+end
+-- END SMARTBUFF_SetUnits
+
+
+
+
+
+
+
+
+
+-------------------------------------------------------------------------------------------------------------------------------------
+-- SMARTBUFF_GetSpellID
+-- Read available spells / abilities from spell book including spellid's
+-------------------------------------------------------------------------------------------------------------------------------------
+function SMARTBUFF_GetSpellID(spellname)
+
+ if (spellname) then spellname = string.lower(spellname); else return nil; end
+
+ local i = 0;
+ local nSpells = 0;
+ local id = nil;
+ local spellN, spellId, skillType;
+
+ -- Get number of spells
+ for i = 1, GetNumSpellTabs() do
+ local _, _, _, n = GetSpellTabInfo(i);
+ nSpells = nSpells + n;
+ end
+
+ i = 0;
+ while (i < nSpells) do
+ i = i + 1;
+ spellN = GetSpellBookItemName(i, BOOKTYPE_SPELL);
+ skillType, spellId = GetSpellBookItemInfo(i, BOOKTYPE_SPELL);
+ --print(spellN.." "..spellId);
+
+ if (skillType == "FLYOUT") then
+ for j = 1, GetNumFlyouts() do
+ local fid = GetFlyoutID(j);
+ local name, description, numSlots, isKnown = GetFlyoutInfo(fid)
+ if (isKnown) then
+ for s = 1, numSlots do
+ local flySpellID, overrideSpellID, isKnown, spellN, slotSpecID = GetFlyoutSlotInfo(fid, s);
+ if (isKnown and string.lower(spellN) == spellname) then
+ --print(spellname.." "..spellN.." "..flySpellID);
+ return flySpellID;
+ end
+ end
+ end
+ end
+ end
+
+ if (spellN ~= nil and string.lower(spellN) == spellname) then
+ id = spellId;
+ break;
+ end
+ end
+
+ if (id) then
+ if (IsPassiveSpell(id) or skillType == "FUTURESPELL" or not IsSpellKnown(id)) then
+ id = nil;
+ i = nil;
+ end
+ end
+
+-- if i and id then print("Spell Name: "..spellname..", id: "..id..", i: " .. i); end;
+
+ return id, i;
+end
+
+
+-------------------------------------------------------------------------------------------------------------------------------------
+-- SMARTBUFF_SetBuffs()
+-- Setup the buff array
+-------------------------------------------------------------------------------------------------------------------------------------
+function SMARTBUFF_SetBuffs()
+
+ if (B == nil) then return; end
+
+ local n = 1;
+ local buff = nil;
+ local ct = currentTemplate;
+
+ if (B[CS()] == nil) then
+ B[CS()] = { };
+ end
+
+ SMARTBUFF_InitItemList();
+ SMARTBUFF_InitSpellList();
+
+ if (B[CS()][ct] == nil) then
+ B[CS()][ct] = { };
+ B[CS()][ct].SelfFirst = false;
+ end
+
+ if (B[CS()][ct].GrpBuffSize == nil) then
+ B[CS()][ct].GrpBuffSize = 3;
+ end
+
+ wipe(cBuffs);
+ wipe(cBuffIndex);
+ numBuffs = 0;
+
+ for _, buff in pairs(SMARTBUFF_BUFFLIST) do
+ n = SMARTBUFF_SetBuff(buff, n, true);
+ end
+
+ for _, buff in pairs(SMARTBUFF_WEAPON) do
+ n = SMARTBUFF_SetBuff(buff, n);
+ end
+
+ for _, buff in pairs(SMARTBUFF_RACIAL) do
+ n = SMARTBUFF_SetBuff(buff, n);
+ end
+
+ for _, buff in pairs(SMARTBUFF_TRACKING) do
+ n = SMARTBUFF_SetBuff(buff, n);
+ end
+
+ for _, buff in pairs(SMARTBUFF_POTION) do
+ n = SMARTBUFF_SetBuff(buff, n);
+ end
+
+ for _, buff in pairs(SMARTBUFF_SCROLL) do
+ n = SMARTBUFF_SetBuff(buff, n);
+ end
+
+ for _, buff in pairs(SMARTBUFF_FOOD) do
+ n = SMARTBUFF_SetBuff(buff, n);
+ end
+
+ wipe(cBuffsCombat);
+ SMARTBUFF_SetInCombatBuffs();
+
+ InitBuffOrder();
+
+ numBuffs = n - 1;
+ isSetBuffs = false;
+end
+
+
+-------------------------------------------------------------------------------------------------------------------------------------
+-- SMARTBUFF_SetBuff
+-------------------------------------------------------------------------------------------------------------------------------------
+function SMARTBUFF_SetBuff(buff, i, ia)
+
+ if (buff == nil or buff[1] == nil or i > maxScrollButtons) then return i; end
+
+ cBuffs[i] = nil;
+ cBuffs[i] = { };
+ cBuffs[i].BuffS = buff[1];
+ cBuffs[i].DurationS = ceil(buff[2] * 60);
+ cBuffs[i].Type = buff[3];
+ cBuffs[i].CanCharge = false;
+
+ if (SMARTBUFF_IsSpell(cBuffs[i].Type) or cBuffs[i].Type == SMARTBUFF_CONST_TRACK) then
+ cBuffs[i].IDS, cBuffs[i].BookID = SMARTBUFF_GetSpellID(cBuffs[i].BuffS);
+-- if cBuffs[i].IDS then print("Id: "..cBuffs[i].IDS.." BookId:"..cBuffs[i].BookID); end
+ end
+
+ if (cBuffs[i].IDS == nil and not(SMARTBUFF_IsItem(cBuffs[i].Type))) then
+ cBuffs[i] = nil;
+ return i;
+ end
+
+ if (buff[4] ~= nil) then cBuffs[i].LevelsS = buff[4] else cBuffs[i].LevelsS = nil end
+ if (buff[5] ~= nil) then cBuffs[i].Params = buff[5] else cBuffs[i].Params = SG.NIL end
+
+ if (cBuffs[i].IDS ~= nil) then
+ cBuffs[i].IconS = GetSpellTexture(cBuffs[i].BuffS);
+ else
+ if (cBuffs[i].Type == SMARTBUFF_CONST_TRACK) then
+
+
+ elseif (cBuffs[i].Type == SMARTBUFF_CONST_ITEMGROUP) then
+ local _, _, _, _, minLevel, _, _, _, _, texture = GetItemInfo(cBuffs[i].BuffS);
+ if (not IsMinLevel(minLevel)) then
+ cBuffs[i] = nil;
+ return i;
+ end
+ cBuffs[i].IconS = texture;
+
+ else
+ local _, _, _, _, minLevel = GetItemInfo(cBuffs[i].BuffS);
+ if (not IsMinLevel(minLevel)) then
+ cBuffs[i] = nil;
+ return i;
+ end
+
+ local _, _, count, texture = SMARTBUFF_FindItem(cBuffs[i].BuffS, cBuffs[i].Chain);
+ if (count <= 0) then
+ cBuffs[i] = nil;
+ return i;
+ end
+ cBuffs[i].IconS = texture;
+ end
+ end
+
+ -- debug
+-- print("Add "..buff[1]);
+
+ cBuffs[i].Links = buff[6];
+ cBuffs[i].Chain = buff[7];
+ cBuffs[i].BuffG = buff[8];
+
+ cBuffs[i].IDG = SMARTBUFF_GetSpellID(cBuffs[i].BuffG);
+ if (cBuffs[i].IDG ~= nil) then
+ cBuffs[i].IconG = GetSpellTexture(cBuffs[i].BuffG);
+ else
+ cBuffs[i].IconG = nil;
+ end
+ if (buff[9] ~= nil) then cBuffs[i].DurationG = ceil(buff[9] * 60); else cBuffs[i].DurationG = nil; end
+ if (buff[10] ~= nil) then cBuffs[i].LevelsG = buff[10]; else cBuffs[i].LevelsG = nil; end
+ if (buff[11] ~= nil) then cBuffs[i].ReagentG = buff[11]; else cBuffs[i].ReagentG = nil; end
+
+ cBuffIndex[cBuffs[i].BuffS] = i;
+ if (cBuffs[i].IDG ~= nil) then
+ cBuffIndex[cBuffs[i].BuffG] = i;
+ end
+
+ InitBuffSettings(cBuffs[i]);
+
+ return i + 1;
+end
+
+
+function SMARTBUFF_SetInCombatBuffs()
+ local ct = currentTemplate;
+ if (ct == nil or B[CS()] == nil or B[CS()][ct] == nil) then
+ return;
+ end
+ for name, data in pairs(B[CS()][ct]) do
+ --SMARTBUFF_AddMsgD(name .. ", type = " .. type(data));
+ if (type(data) == "table" and cBuffIndex[name] and (B[CS()][ct][name].EnableS or B[CS()][ct][name].EnableG) and B[CS()][ct][name].CIn) then
+ if (cBuffsCombat[name]) then
+ wipe(cBuffsCombat[name]);
+ else
+ cBuffsCombat[name] = { };
+ end
+ cBuffsCombat[name].Unit = "player";
+ cBuffsCombat[name].Type = cBuffs[cBuffIndex[name]].Type;
+ cBuffsCombat[name].ActionType = "spell";
+ SMARTBUFF_AddMsgD("Set combat spell: " .. name);
+ --break;
+ end
+ end
+end
+-- END SMARTBUFF_SetBuffs
+
+
+function SMARTBUFF_IsTalentFrameVisible()
+ return PlayerTalentFrame and PlayerTalentFrame:IsVisible();
+end
+
+
+-- Main Check functions
+function SMARTBUFF_PreCheck(mode, force)
+ if (not isInit) then return false end
+
+ if (not isInitBtn) then
+ SMARTBUFF_InitActionButtonPos();
+ end
+
+ if (not O.Toggle) then
+ if (mode == 0) then
+ SMARTBUFF_AddMsg(SMARTBUFF_MSG_DISABLED);
+ end
+ return false;
+ end
+
+ if (mode == 1 and not force) then
+ if ((GetTime() - tLastCheck) < O.AutoTimer) then
+ return false;
+ end
+ end
+
+ tLastCheck = GetTime();
+ SMARTBUFF_ShowSAButton();
+ --end
+
+ SMARTBUFF_SetButtonTexture(SmartBuff_KeyButton, imgSB);
+ if (SmartBuffOptionsFrame:IsVisible()) then return false; end
+
+ -- check for mount-spells
+ if (sPlayerClass == "PALADIN" and (IsMounted() or IsFlying()) and not SMARTBUFF_CheckBuff("player", SMARTBUFF_CRUSADERAURA)) then
+ return true;
+ end
+
+ if ((mode == 1 and not O.ToggleAuto) or IsMounted() or IsFlying() or LootFrame:IsVisible()
+ or UnitOnTaxi("player") or UnitIsDeadOrGhost("player") or UnitIsCorpse("player")
+ or (mode ~= 1 and (SMARTBUFF_IsPicnic("player") or SMARTBUFF_IsFishing("player")))
+ or (UnitInVehicle("player") or UnitHasVehicleUI("player"))
+ --or (mode == 1 and (O.ToggleAutoRest and IsResting()) and not UnitIsPVP("player"))
+ or (not O.BuffInCities and IsResting() and not UnitIsPVP("player"))) then
+
+ if (UnitIsDeadOrGhost("player")) then
+ SMARTBUFF_CheckBuffTimers();
+ end
+
+ return false;
+ end
+
+ if (UnitAffectingCombat("player")) then
+ isCombat = true;
+ --SMARTBUFF_AddMsgD("In combat");
+ else
+ isCombat = false;
+ --SMARTBUFF_AddMsgD("Out of combat");
+ end
+
+ if (not isCombat and isSetBuffs) then
+ SMARTBUFF_SetBuffs();
+ isSyncReq = true;
+ end
+
+ sMsgWarning = "";
+ isFirstError = true;
+
+ return true;
+end
+
+
+-- Bufftimer check functions
+function SMARTBUFF_CheckBuffTimers()
+ local n = 0;
+ local ct = currentTemplate;
+ local cGrp = cUnits;
+ for subgroup in pairs(cGrp) do
+ n = 0;
+ if (cGrp[subgroup] ~= nil) then
+ for _, unit in pairs(cGrp[subgroup]) do
+ if (unit) then
+ if (SMARTBUFF_CheckUnitBuffTimers(unit)) then
+ n = n + 1;
+ end
+ end
+ end
+ if (cBuffTimer[subgroup]) then
+ cBuffTimer[subgroup] = nil;
+ SMARTBUFF_AddMsgD("Group " .. subgroup .. ": group timer reseted");
+ end
+ end
+ end
+end
+-- END SMARTBUFF_CheckBuffTimers
+
+-- if unit is dead, remove all timers
+function SMARTBUFF_CheckUnitBuffTimers(unit)
+ if (UnitExists(unit) and UnitIsConnected(unit) and UnitIsFriend("player", unit) and UnitIsPlayer(unit) and UnitIsDeadOrGhost(unit)) then
+ local _, uc = UnitClass(unit);
+ local fd = nil;
+ if (uc == "HUNTER") then
+ fd = SMARTBUFF_IsFeignDeath(unit);
+ end
+ if (not fd) then
+ if (cBuffTimer[unit]) then
+ cBuffTimer[unit] = nil;
+ SMARTBUFF_AddMsgD(UnitName(unit) .. ": unit timer reset");
+ end
+ if (cBuffTimer[uc]) then
+ cBuffTimer[uc] = nil;
+ SMARTBUFF_AddMsgD(uc .. ": class timer reset");
+ end
+ return true;
+ end
+ end
+end
+-- END SMARTBUFF_CheckUnitBuffTimers
+
+
+-- Reset the buff timers and set them to running out soon
+function SMARTBUFF_ResetBuffTimers()
+ if (not isInit) then return; end
+
+ local ct = currentTemplate;
+ local t = GetTime();
+ local rbTime = 0;
+ local i = 0;
+ local d = 0;
+ local tl = 0;
+ local buffS = nil;
+ local buff = nil;
+ local unit = nil;
+ local obj = nil;
+ local uc = nil;
+
+ local cGrp = cGroups;
+ for subgroup in pairs(cGrp) do
+ n = 0;
+ if (cGrp[subgroup] ~= nil) then
+
+ for _, unit in pairs(cGrp[subgroup]) do
+ if (unit and UnitExists(unit) and UnitIsConnected(unit) and UnitIsFriend("player", unit) and UnitIsPlayer(unit) and not UnitIsDeadOrGhost(unit)) then
+ _, uc = UnitClass(unit);
+ i = 1;
+ while (cBuffs[i] and cBuffs[i].BuffS) do
+ d = -1;
+ buff = nil;
+ rbTime = 0;
+ buffS = cBuffs[i].BuffS;
+
+ rbTime = B[CS()][ct][buffS].RBTime;
+ if (rbTime <= 0) then
+ rbTime = O.RebuffTimer;
+ end
+
+ if (cBuffs[i].BuffG and B[CS()][ct][buffS].EnableG and cBuffs[i].IDG ~= nil and cBuffs[i].DurationG > 0) then
+ d = cBuffs[i].DurationG;
+ buff = cBuffs[i].BuffG;
+ obj = subgroup;
+ end
+
+ if (d > 0 and buff) then
+ if (not cBuffTimer[obj]) then
+ cBuffTimer[obj] = { };
+ end
+ cBuffTimer[obj][buff] = t - d + rbTime - 1;
+ end
+
+ buff = nil;
+ if (buffS and B[CS()][ct][buffS].EnableS and cBuffs[i].IDS ~= nil and cBuffs[i].DurationS > 0
+ and uc and B[CS()][ct][buffS][uc]) then
+ d = cBuffs[i].DurationS;
+ buff = buffS;
+ obj = unit;
+ end
+
+ if (d > 0 and buff) then
+ if (not cBuffTimer[obj]) then
+ cBuffTimer[obj] = { };
+ end
+ cBuffTimer[obj][buff] = t - d + rbTime - 1;
+ end
+
+ i = i + 1;
+ end
+ end
+ end
+ end
+ end
+ --isAuraChanged = true;
+ SMARTBUFF_Check(1, true);
+end
+
+function SMARTBUFF_ShowBuffTimers()
+ if (not isInit) then return; end
+
+ local ct = currentTemplate;
+ local t = GetTime();
+ local rbTime = 0;
+ local i = 0;
+ local d = 0;
+ local tl = 0;
+ local buffS = nil;
+
+ for unit in pairs(cBuffTimer) do
+ for buff in pairs(cBuffTimer[unit]) do
+ if (unit and buff and cBuffTimer[unit][buff]) then
+
+ d = -1;
+ buffS = nil;
+ if (cBuffIndex[buff]) then
+ i = cBuffIndex[buff];
+ if (cBuffs[i].BuffS == buff and cBuffs[i].DurationS > 0) then
+ d = cBuffs[i].DurationS;
+ buffS = cBuffs[i].BuffS;
+ elseif (cBuffs[i].BuffG == buff and cBuffs[i].DurationG > 0) then
+ d = cBuffs[i].DurationG;
+ buffS = cBuffs[i].BuffS;
+ end
+ i = i + 1;
+ end
+
+ if (buffS and B[CS()][ct][buffS] ~= nil) then
+ if (d > 0) then
+ rbTime = B[CS()][ct][buffS].RBTime;
+ if (rbTime <= 0) then
+ rbTime = O.RebuffTimer;
+ end
+ tl = cBuffTimer[unit][buff] + d - t;
+ if (tl >= 0) then
+ local s = "";
+ if (string.find(unit, "^party") or string.find(unit, "^raid") or string.find(unit, "^player") or string.find(unit, "^pet")) then
+ local un = UnitName(unit);
+ if (un) then
+ un = " (" .. un .. ")";
+ else
+ un = "";
+ end
+ s = "Unit " .. unit .. un;
+ elseif (string.find(unit, "^%d$")) then
+ s = "Grp " .. unit;
+ else
+ s = "Class " .. unit;
+ end
+ -- SMARTBUFF_AddMsg(string.format("%s: %s, time left: %.0f, rebuff time: %.0f", s, buff, tl, rbTime));
+ else
+ cBuffTimer[unit][buff] = nil;
+ end
+ else
+ --SMARTBUFF_AddMsgD("Removed: " .. buff);
+ cBuffTimer[unit][buff] = nil;
+ end
+ end
+
+ end
+ end
+ end
+
+end
+-- END SMARTBUFF_ResetBuffTimers
+
+
+-- Synchronize the internal buff timers with the UI timers
+function SMARTBUFF_SyncBuffTimers()
+ if (not isInit or isSync or isSetBuffs or SMARTBUFF_IsTalentFrameVisible()) then return; end
+ isSync = true;
+ tSync = GetTime();
+
+ local ct = currentTemplate;
+ local rbTime = 0;
+ local i = 0;
+ local buffS = nil;
+ local unit = nil;
+ local uc = nil;
+
+ local cGrp = nil;
+ if (sPlayerClass == "PALADIN" and cClassGroups) then
+ cGrp = cClassGroups;
+ else
+ cGrp = cGroups;
+ end
+
+ for subgroup in pairs(cGrp) do
+ n = 0;
+ if (cGrp[subgroup] ~= nil) then
+ for _, unit in pairs(cGrp[subgroup]) do
+ if (unit and UnitExists(unit) and UnitIsConnected(unit) and UnitIsFriend("player", unit) and UnitIsPlayer(unit) and not UnitIsDeadOrGhost(unit)) then
+ _, uc = UnitClass(unit);
+ i = 1;
+ while (cBuffs[i] and cBuffs[i].BuffS) do
+ rbTime = 0;
+ buffS = cBuffs[i].BuffS;
+
+ rbTime = B[CS()][ct][buffS].RBTime;
+ if (rbTime <= 0) then
+ rbTime = O.RebuffTimer;
+ end
+
+ if (cBuffs[i].BuffG and B[CS()][ct][buffS].EnableG and cBuffs[i].IDG ~= nil and cBuffs[i].DurationG > 0) then
+ SMARTBUFF_SyncBuffTimer(unit, subgroup, cBuffs[i], true);
+ end
+
+ if (buffS and B[CS()][ct][buffS].EnableS and cBuffs[i].IDS ~= nil and cBuffs[i].DurationS > 0) then
+ if (cBuffs[i].Type ~= SMARTBUFF_CONST_SELF or (cBuffs[i].Type == SMARTBUFF_CONST_SELF and SMARTBUFF_IsPlayer(unit))) then
+ --and uc and B[CS()][ct][buffS][uc]) then
+ --SMARTBUFF_AddMsgD("Buff timer sync check: " .. buffS);
+ SMARTBUFF_SyncBuffTimer(unit, unit, cBuffs[i], false);
+ end
+ end
+
+ i = i + 1;
+ end -- END while
+ end
+ end -- END for
+ end
+ end -- END for
+
+ isSync = false;
+ isSyncReq = false;
+end
+
+
+function SMARTBUFF_SyncBuffTimer(unit, grp, cBuff, isGrpBuff)
+ if (not unit or not grp or not cBuff) then return end
+
+ local buff, d;
+ if (isGrpBuff) then
+ d = cBuff.DurationG;
+ buff = cBuff.BuffG;
+ else
+ d = cBuff.DurationS;
+ buff = cBuff.BuffS;
+ end
+
+ if (d and d > 0 and buff) then
+ local t = GetTime();
+ local ret, _, _, timeleft = SMARTBUFF_CheckUnitBuffs(unit, buff, cBuff.Type, cBuff.Links, cBuff.Chain);
+ if (ret == nil and timeleft ~= nil) then
+ if (not cBuffTimer[grp]) then cBuffTimer[grp] = { } end
+ st = Round(t - d + timeleft, 2);
+ if (not cBuffTimer[grp][buff] or (cBuffTimer[grp][buff] and cBuffTimer[grp][buff] ~= st)) then
+ cBuffTimer[grp][buff] = st;
+ if (timeleft > 60) then
+ SMARTBUFF_AddMsgD("Buff timer sync: " .. grp .. ", " .. buff .. ", " .. string.format("%.1f", timeleft/60) .. "min");
+ else
+ SMARTBUFF_AddMsgD("Buff timer sync: " .. grp .. ", " .. buff .. ", " .. string.format("%.1f", timeleft) .. "sec");
+ end
+ end
+ end
+ end
+end
+
+
+-- check if the player is shapeshifted
+function SMARTBUFF_IsShapeshifted()
+ if (sPlayerClass == "SHAMAN") then
+ if (GetShapeshiftForm(true) > 0) then
+ return true, "Ghost Wolf";
+ end
+ elseif (sPlayerClass == "DRUID") then
+ local i;
+ for i = 1, GetNumShapeshiftForms(), 1 do
+ local icon, active, castable, spellId = GetShapeshiftFormInfo(i);
+ local name = GetSpellInfo(spellId);
+ if (active and castable and name ~= SMARTBUFF_DRUID_TREANT) then
+ return true, name;
+ end
+ end
+ end
+ return false, nil;
+end
+-- END SMARTBUFF_IsShapeshifted
+
+
+local IsChecking = false;
+function SMARTBUFF_Check(mode, force)
+ if (IsChecking or not SMARTBUFF_PreCheck(mode, force)) then return; end
+
+ IsChecking = true;
+
+ local ct = currentTemplate;
+ local unit = nil;
+ local units = nil;
+ local unitsGrp = nil;
+ local unitB = nil;
+ local unitL = nil;
+ local unitU = nil;
+ local uLevel = nil;
+ local uLevelL = nil;
+ local uLevelU = nil;
+ local idL = nil;
+ local idU = nil;
+ local subgroup = 0;
+ local i;
+ local j;
+ local n;
+ local m;
+ local rc;
+ local rank;
+ local reagent;
+ local nGlobal = 0;
+ local tmpDisabled = { };
+
+ local buffs = nil;
+ if (SMARTBUFF_Buffs[CS()]) then
+ buffs = SMARTBUFF_Buffs[CS()][ct];
+ end
+
+ SMARTBUFF_checkBlacklist();
+
+ -- 1. check in combat buffs
+ if (InCombatLockdown()) then -- and O.InCombat
+ for spell in pairs(cBuffsCombat) do
+ if (spell) then
+ local ret, actionType, spellName, slot, unit, buffType = SMARTBUFF_BuffUnit("player", 0, mode, spell)
+ --SMARTBUFF_AddMsgD("Check combat spell: " .. spell .. ", ret = " .. ret);
+ if (ret and ret == 0) then
+ IsChecking = false;
+ return;
+ end
+ end
+ end
+ end
+
+ -- 2. buff target, if enabled
+ if ((mode == 0 or mode == 5) and O.BuffTarget) then
+ local actionType, spellName, slot, buffType, rankText;
+ i, actionType, spellName, slot, _, buffType, rankText = SMARTBUFF_BuffUnit("target", 0, mode);
+ if (i <= 1) then
+ if (i == 0) then
+ --tLastCheck = GetTime() - O.AutoTimer + GlobalCd;
+ end
+ IsChecking = false;
+ return i, actionType, spellName, slot, "target", buffType, rankText;
+ end
+ end
+
+ -- 3. check groups
+ local cGrp = nil;
+ local cOrd = nil;
+ cGrp = cGroups;
+ cOrd = cOrderGrp;
+
+ isMounted = IsMounted() or IsFlying();
+
+ for _, subgroup in pairs(cOrd) do
+ --SMARTBUFF_AddMsgD("Checking subgroup " .. subgroup .. ", " .. GetTime());
+ if (cGrp[subgroup] ~= nil or (type(subgroup) == "number" and subgroup == 1)) then
+
+ if (cGrp[subgroup] ~= nil) then
+ units = cGrp[subgroup];
+ else
+ units = nil;
+ end
+
+ if (cUnits and type(subgroup) == "number" and subgroup == 1) then
+ unitsGrp = cUnits[1];
+ else
+ unitsGrp = units;
+ end
+
+ -- check group buff
+ if (buffs and unitsGrp and not isMounted) then
+
+ i = 1;
+ local rbTime = 0;
+ while (cBuffs[i] and cBuffs[i].BuffS) do
+ local cBuff = cBuffs[i];
+ local buffnS = cBuff.BuffS;
+ local buffnG = cBuff.BuffG;
+ local bs = buffs[buffnS];
+
+ if (buffnG and tmpDisabled[buffnG] == nil and bs and bs.EnableG and cBuff.IDG ~= nil
+ and ((isCombat and bs.CIn) or (not isCombat and bs.COut)) and IsPowerLimitOk(bs)
+ --and UnitMana("player") >= bs.ManaLimit
+ and (sPlayerClass ~= "PALADIN" or not cClassGroups or (sPlayerClass == "PALADIN" and (bs[subgroup] or (type(subgroup) == "number" and subgroup == 0))))) then
+
+ local tmpUnits = { };
+ local btl = 9999;
+ local bExp = false;
+ local target = "";
+
+ if (sPlayerClass == "PALADIN" and cClassGroups) then
+ for _, unit in pairs(units) do
+ local u = UnitClass(unit);
+ if (u) then
+ target = SMARTBUFF_MSG_CLASS .. " " .. u;
+ SMARTBUFF_AddMsgD(target);
+ break;
+ end
+ end
+ else
+ --target = SMARTBUFF_MSG_GROUP .. " " .. subgroup;
+ target = SMARTBUFF_MSG_GROUP;
+ end
+
+ if (type(subgroup) == "number" and subgroup == 0) then
+ target = sPlayerName;
+ end
+
+ rbTime = bs.RBTime;
+ if (rbTime <= 0) then
+ rbTime = SMARTBUFF_Options.RebuffTimer;
+ end
+
+ if (cBuffTimer[subgroup] ~= nil and cBuffTimer[subgroup][buffnG] ~= nil) then
+ btl = cBuff.DurationG - (GetTime() - cBuffTimer[subgroup][buffnG]);
+ if (rbTime > 0 and rbTime >= btl) then
+ bExp = true;
+ if (mode == 1) then
+ -- clean up buff timer, if expired
+ if (btl < 0) then
+ cBuffTimer[subgroup][buffnG] = nil;
+ --SMARTBUFF_AddMsgD("Group " .. subgroup .. ": " .. buffnS .. " timer reset");
+ tLastCheck = GetTime() - SMARTBUFF_Options.AutoTimer + 0.5;
+ return;
+ end
+ end
+ end
+ end
+
+ SMARTBUFF_AddMsgD("Checking0 " .. buffnG);
+ n = 0;
+ m = 0;
+ j = 0;
+ uLevelL = 100;
+ uLevelU = 0;
+ unitL = nil;
+ unitU = nil;
+ unitB = nil;
+ for _, unit in pairs(unitsGrp) do
+ j = j + 1;
+ SMARTBUFF_AddMsgD("Checking1 " .. buffnG .. " " .. unit);
+
+ --if (unit and (UnitIsPlayer(unit) or (sPlayerClass == "PALADIN" and (UnitPlayerOrPetInParty(unit) or UnitPlayerOrPetInRaid(unit)))) and not SMARTBUFF_IsInList(unit, UnitName(unit), SMARTBUFF_Buffs[CS()][ct][buffnS].IgnoreList)) then
+ if (unit and UnitIsPlayer(unit) and not SMARTBUFF_IsInList(unit, UnitName(unit), bs.IgnoreList)) then
+
+ SMARTBUFF_AddMsgD("Checking2 " .. buffnG .. " " .. unit);
+ n = n + 1;
+ --if (UnitExists(unit) and not UnitIsDeadOrGhost(unit) and not UnitIsCorpse(unit) and UnitIsConnected(unit) and UnitIsVisible(unit) and not UnitOnTaxi(unit) and (SMARTBUFF_IsPlayer(unit) or not SMARTBUFF_Options.AdvGrpBuffRange or not SpellHasRange(cBuff.BuffG) or (IsSpellInRange(cBuff.BuffG, unit) == 1))) then
+
+ if (UnitExists(unit) and not UnitIsDeadOrGhost(unit) and not UnitIsCorpse(unit) and UnitIsConnected(unit) and UnitIsVisible(unit) and not UnitOnTaxi(unit) and UnitInRange(unit) == 1) then
+ --if (sPlayerClass ~= "PALADIN")
+ tmpUnits[n] = unit;
+ uLevel = UnitLevel(unit);
+ if (uLevel < uLevelL) then
+ uLevelL = uLevel;
+ unitL = unit;
+ end
+ if (uLevel > uLevelU) then
+ uLevelU = uLevel;
+ unitU = unit;
+ unitB = unit;
+ end
+ local ret, idx, buffname;
+ ret, idx, buffname = SMARTBUFF_CheckUnitBuffs(unit, nil, buffnG);
+ if (ret ~= nil or bExp) then
+ m = m + 1;
+ end
+ end
+ end
+
+ end -- end for units
+
+ if (mode == 1 and m >= buffs.GrpBuffSize and n >= buffs.GrpBuffSize) then
+ SMARTBUFF_SetMissingBuffMessage(target, buffnG, false, 1, btl, bExp, false);
+ SMARTBUFF_SetButtonTexture(SmartBuff_KeyButton, cBuff.IconG);
+ return;
+ end
+
+ if (unitL ~= nil and unitU ~=nil and unitB ~= nil and cBuff.IDG ~= nil) then
+ idU, rank = SMARTBUFF_CheckUnitLevel(unitU, cBuff.IDG, cBuff.LevelsG);
+ idL, rank = SMARTBUFF_CheckUnitLevel(unitL, cBuff.IDG, cBuff.LevelsG);
+
+ if (idL ~= nil and idU ~= nil and idL == idU and rank > 0 and m >= buffs.GrpBuffSize and n >= buffs.GrpBuffSize) then
+
+ reagent = cBuff.ReagentG[rank];
+ if (reagent and mode ~= 1) then
+ rc = SMARTBUFF_CountReagent(reagent);
+ if (rc > 0) then
+ currentUnit = nil;
+ currentSpell = nil;
+
+ SMARTBUFF_AddMsgD("Buffing group (" .. unitB .. ") " .. subgroup .. ", " .. idU .. ", " .. j .. ", ");
+ j = SMARTBUFF_doCast(unitB, idU, buffnG, nil, SMARTBUFF_CONST_ALL)
+
+ if (j == 0) then
+ SMARTBUFF_AddMsg(target .. ": " .. buffnG .. " " .. SMARTBUFF_MSG_BUFFED);
+ SMARTBUFF_AddMsg(SMARTBUFF_MSG_STOCK .. " " .. reagent .. " = " .. (rc - 1));
+
+ if (sPlayerClass == "PALADIN") then
+ local _, uc = UnitClass(unitB);
+ if (cBuffTimer[uc] == nil) then
+ cBuffTimer[uc] = { };
+ end
+ cBuffTimer[uc][buffnG] = GetTime();
+ else
+ if (cBuffTimer[subgroup] == nil) then
+ cBuffTimer[subgroup] = { };
+ end
+ cBuffTimer[subgroup][buffnG] = GetTime();
+ end
+
+ -- cleanup single buff timer
+ for _, unit in pairs(tmpUnits) do
+ if (cBuffTimer[unit] and cBuffTimer[unit][buffnS]) then
+ cBuffTimer[unit][buffnS] = nil;
+ end
+ end
+
+ --tLastCheck = GetTime() - SMARTBUFF_Options.AutoTimer + GlobalCd;
+ return 0, SMARTBUFF_ACTION_SPELL, buffnG, -1, unitB, cBuff.Type;
+ end
+ else
+ SMARTBUFF_AddMsgWarn(SMARTBUFF_MSG_NOREAGENT .. " " .. reagent .. "! " .. buffnG .. " " .. SMARTBUFF_MSG_DEACTIVATED);
+ tmpDisabled[buffnG] = true;
+ --tinsert(tmpDisabled, buffnG);
+ --bs.EnableG = false;
+ end
+ elseif (reagent and mode == 1) then
+ SMARTBUFF_SetMissingBuffMessage(target, buffnG, false, 1, btl, bExp, false);
+ SMARTBUFF_SetButtonTexture(SmartBuff_KeyButton, cBuff.IconG);
+ return;
+ else
+ --SMARTBUFF_AddMsgD("Reagent = nil");
+ end
+ end
+ end
+ end
+
+ i = i + 1;
+ end -- END while buffs
+ end
+
+ -- check buffs
+ if (units) then
+ for _, unit in pairs(units) do
+ if (isSetBuffs) then break; end
+
+ local spellName, actionType, slot, buffType, rankText;
+ i, actionType, spellName, slot, _, buffType, rankText = SMARTBUFF_BuffUnit(unit, subgroup, mode);
+
+ if (i <= 1) then
+ if (i == 0 and mode ~= 1) then
+ --tLastCheck = GetTime() - O.AutoTimer + GlobalCd;
+ if (actionType == SMARTBUFF_ACTION_ITEM) then
+ --tLastCheck = tLastCheck + 2;
+ end
+ end
+ IsChecking = false;
+ return i, actionType, spellName, slot, unit, buffType, rankText;
+ end
+ end
+ end
+
+ end
+ end -- for groups
+
+ if (mode == 0) then
+ if (sMsgWarning == "" or sMsgWarning == " ") then
+ SMARTBUFF_AddMsg(SMARTBUFF_MSG_NOTHINGTODO);
+ else
+ SMARTBUFF_AddMsgWarn(sMsgWarning);
+ sMsgWarning = "";
+ end
+ end
+ --tLastCheck = GetTime();
+ IsChecking = false;
+end
+-- END SMARTBUFF_Check
+
+
+-- Buffs a unit
+function SMARTBUFF_BuffUnit(unit, subgroup, mode, spell)
+ local bs = nil;
+ local buff = nil;
+ local buffname = nil;
+ local buffnS = nil;
+ local uc = nil;
+ local ur = "NONE";
+ local un = nil;
+ local uct = nil;
+ local ucf = nil;
+ local r;
+ local rankText;
+ local i;
+ local bt = 0;
+ local cd = 0;
+ local cds = 0;
+ local charges = 0;
+ local handtype = "";
+ local bExpire = false;
+ local isPvP = false;
+ local bufftarget = nil;
+ local rbTime = 0;
+ local bUsable = false;
+ local time = GetTime();
+ local cBuff = nil;
+ local iId = nil;
+ local iSlot = -1;
+
+ if (UnitIsPVP("player")) then isPvP = true end
+
+ SMARTBUFF_CheckUnitBuffTimers(unit);
+
+ --SMARTBUFF_AddMsgD("Checking " .. unit);
+
+ if (UnitExists(unit) and UnitIsFriend("player", unit) and not UnitIsDeadOrGhost(unit) and not UnitIsCorpse(unit)
+ and UnitIsConnected(unit) and UnitIsVisible(unit) and not UnitOnTaxi(unit) and not cBlacklist[unit]
+ and ((not UnitIsPVP(unit) and (not isPvP or O.BuffPvP)) or (UnitIsPVP(unit) and (isPvP or O.BuffPvP)))) then
+ --and not SmartBuff_UnitIsIgnored(unit)
+
+ _, uc = UnitClass(unit);
+ un = UnitName(unit);
+ ur = UnitGroupRolesAssigned(unit);
+ uct = UnitCreatureType(unit);
+ ucf = UnitCreatureFamily(unit);
+ if (uct == nil) then uct = ""; end
+ if (ucf == nil) then ucf = ""; end
+
+-- if (un) then SMARTBUFF_AddMsgD("Grp "..subgroup.." checking "..un.." ("..unit.."/"..uc.."/"..ur.."/"..uct.."/"..ucf..")", 0, 1, 0.5); end
+
+ isShapeshifted, sShapename = SMARTBUFF_IsShapeshifted();
+ --while (cBuffs[i] and cBuffs[i].BuffS) do
+ for i, buffnS in pairs(B[CS()].Order) do
+ if (isSetBuffs or SmartBuffOptionsFrame:IsVisible()) then break; end
+ cBuff = cBuffs[cBuffIndex[buffnS]];
+ --buffnS = cBuff.BuffS;
+ bs = GetBuffSettings(buffnS);
+ bExpire = false;
+ handtype = "";
+ charges = -1;
+ bufftarget = nil;
+ bUsable = false;
+ iId = nil;
+ iSlot = -1;
+
+ if (not cBuff or not bs) then bUsable = false end
+ if (cBuff and bs) then bUsable = bs.EnableS end
+
+ if (bUsable and spell and spell ~= buffnS) then
+ bUsable = false;
+ --SMARTBUFF_AddMsgD("Exclusive check on " .. spell .. ", current spell = " .. buffnS);
+ end
+
+ if (bUsable and cBuff.Type == SMARTBUFF_CONST_SELF and not SMARTBUFF_IsPlayer(unit)) then bUsable = false end
+ if (bUsable and not cBuff.Type == SMARTBUFF_CONST_TRACK and not SMARTBUFF_IsItem(cBuff.Type) and not IsUsableSpell(buffnS)) then bUsable = false end
+ if (bUsable and bs.SelfNot and SMARTBUFF_IsPlayer(unit)) then bUsable = false end
+ if (bUsable and cBuff.Params == SG.CheckFishingPole and SMARTBUFF_IsFishingPoleEquiped()) then bUsable = false end
+
+ -- Check for power threshold
+ if (bUsable) then
+ bUsable = IsPowerLimitOk(bs);
+ end
+
+ -- Check for buffs which depends on a pet
+ if (bUsable and cBuff.Params == SG.CheckPet and UnitExists("pet")) then bUsable = false end
+ if (bUsable and cBuff.Params == SG.CheckPetNeeded and not UnitExists("pet")) then bUsable = false end
+
+ -- Check for mount auras
+ isMounted = false;
+ if (bUsable and sPlayerClass == "PALADIN") then
+ isMounted = IsMounted() or IsFlying();
+ if ((buffnS ~= SMARTBUFF_CRUSADERAURA and isMounted) or (buffnS == SMARTBUFF_CRUSADERAURA and not isMounted)) then
+ bUsable = false;
+ end
+ end
+
+
+ if (bUsable and not (cBuff.Type == SMARTBUFF_CONST_TRACK or SMARTBUFF_IsItem(cBuff.Type))) then
+ -- check if you have enough mana/rage/energy to cast
+ local isUsable, notEnoughMana = IsUsableSpell(buffnS);
+ if (notEnoughMana) then
+ bUsable = false;
+ --SMARTBUFF_AddMsgD("Buff " .. cBuff.BuffS .. ", not enough mana!");
+ elseif (mode ~= 1 and isUsable == nil and buffnS ~= SMARTBUFF_PWS) then
+ bUsable = false;
+ --SMARTBUFF_AddMsgD("Buff " .. cBuff.BuffS .. " is not usable!");
+ end
+ end
+
+ if (bUsable and bs.EnableS and (cBuff.IDS ~= nil or SMARTBUFF_IsItem(cBuff.Type) or cBuff.Type == SMARTBUFF_CONST_TRACK)
+ and ((mode ~= 1 and ((isCombat and bs.CIn) or (not isCombat and bs.COut)))
+ or (mode == 1 and bs.Reminder and ((not isCombat and bs.COut)
+ or (isCombat and (bs.CIn or O.ToggleAutoCombat)))))) then
+
+ --print("Check: "..buffnS)
+
+ if (not bs.SelfOnly or (bs.SelfOnly and SMARTBUFF_IsPlayer(unit))) then
+ -- get current spell cooldown
+ cd = 0;
+ cds = 0;
+ if (cBuff.IDS) then
+ cds, cd = GetSpellCooldown(buffnS);
+ cd = (cds + cd) - time;
+ if (cd < 0) then
+ cd = 0;
+ end
+ --SMARTBUFF_AddMsgD(buffnS.." cd = "..cd);
+ end
+
+ -- check if spell has cooldown
+ if (cd <= 0 or (mode == 1 and cd <= 1.5)) then
+ if (cBuff.IDS and sMsgWarning == SMARTBUFF_MSG_CD) then
+ sMsgWarning = " ";
+ end
+
+ rbTime = bs.RBTime;
+ if (rbTime <= 0) then
+ rbTime = O.RebuffTimer;
+ end
+
+ --SMARTBUFF_AddMsgD(uc.." "..CT());
+ if (not SMARTBUFF_IsInList(unit, un, bs.IgnoreList) and (((cBuff.Type == SMARTBUFF_CONST_GROUP or cBuff.Type == SMARTBUFF_CONST_ITEMGROUP)
+ and (bs[ur]
+ or (bs.SelfOnly and SMARTBUFF_IsPlayer(unit))
+ or (bs[uc] and (UnitIsPlayer(unit) or uct == SMARTBUFF_HUMANOID or (uc == "DRUID" and (uct == SMARTBUFF_BEAST or uct == SMARTBUFF_ELEMENTAL))))
+ or (bs["HPET"] and uct == SMARTBUFF_BEAST and uc ~= "DRUID")
+ or (bs["DKPET"] and utc == SMARTBUFF_UNDEAD)
+ or (bs["WPET"] and (uct == SMARTBUFF_DEMON or (uc ~= "DRUID" and uct == SMARTBUFF_ELEMENTAL)) and ucf ~= SMARTBUFF_DEMONTYPE)))
+ or (cBuff.Type ~= SMARTBUFF_CONST_GROUP and SMARTBUFF_IsPlayer(unit))
+ or SMARTBUFF_IsInList(unit, un, bs.AddList))) then
+ buff = nil;
+
+ --Tracking ability ------------------------------------------------------------------------
+
+ if (cBuff.Type == SMARTBUFF_CONST_TRACK) then
+ if buildInfo >= 20502 then
+ -- assume we are TBC Classic
+ local count = (GetNumTrackingTypes())+1; -- GetNumTrackingTypes doesnt count "none" so add one to include it.
+ local trackingFound;
+ for n = 1, count do
+ local trackN, trackT, trackA, trackC = GetTrackingInfo(n);
+ if trackN == buffnS and trackA then
+ trackingFound = true;
+ break;
+ else
+ trackingFound = false;
+ end
+ end
+ if not trackingFound then
+ if (sPlayerClass ~= "DRUID" or ((not isShapeshifted and buffnS ~= SMARTBUFF_DRUID_TRACK) or (isShapeshifted and buffnS ~= SMARTBUFF_DRUID_TRACK) or (isShapeshifted and buffnS == SMARTBUFF_DRUID_TRACK and sShapename == SMARTBUFF_DRUID_CAT))) then
+ buff = buffnS;
+ end
+ end
+ else
+ -- we are below the minimal tbc build, assume its classic era / season of mastery.
+ local iconTrack = GetTrackingTexture();
+ if (iconTrack ~= nil) then
+ SMARTBUFF_AddMsgD("Track already enabled: " .. iconTrack);
+ else
+ if (sPlayerClass ~= "DRUID" or ((not isShapeshifted and buffnS ~= SMARTBUFF_DRUID_TRACK) or (isShapeshifted and buffnS ~= SMARTBUFF_DRUID_TRACK) or (isShapeshifted and buffnS == SMARTBUFF_DRUID_TRACK and sShapename == SMARTBUFF_DRUID_CAT))) then
+ buff = buffnS;
+ SMARTBUFF_AddMsgD("Missing tracking: "..buffnS);
+ end
+ end
+ end
+
+ -- Food, Scroll, Potion or conjured items ------------------------------------------------------------------------
+
+ elseif (cBuff.Type == SMARTBUFF_CONST_FOOD or cBuff.Type == SMARTBUFF_CONST_SCROLL or cBuff.Type == SMARTBUFF_CONST_POTION or
+ cBuff.Type == SMARTBUFF_CONST_ITEM or cBuff.Type == SMARTBUFF_CONST_ITEMGROUP) then
+
+ if (cBuff.Type == SMARTBUFF_CONST_ITEM) then
+ bt = nil;
+ buff = nil;
+ if (cBuff.Params ~= SG.NIL) then
+ local cr = SMARTBUFF_CountReagent(cBuff.Params, cBuff.Chain);
+ --SMARTBUFF_AddMsgD(cr.." "..cBuff.Params.." found");
+ if (cr == 0) then
+ buff = cBuff.Params;
+ end
+ end
+
+ -- only prompt / apply food when I am not moving - this would constantly use food
+ -- in your bags if you were moving - bugfix 03/12/2021.
+
+ elseif (cBuff.Type == SMARTBUFF_CONST_FOOD and isPlayerMoving == false) then
+ if (not SMARTBUFF_IsPicnic(unit)) then
+ buff, index, buffname, bt, charges = SMARTBUFF_CheckUnitBuffs(unit, SMARTBUFF_FOOD_AURA, cBuff.Type, cBuff.Links, cBuff.Chain);
+ end
+
+ else
+ if (cBuff.Params ~= SG.NIL) then
+ if (cBuff.Links and cBuff.Links == SG.CheckFishingPole) then
+ if (SMARTBUFF_IsFishingPoleEquiped()) then
+ buff, index, buffname, bt, charges = SMARTBUFF_CheckUnitBuffs(unit, cBuff.Params, cBuff.Type);
+ else
+ buff = nil;
+ end
+ else
+ buff, index, buffname, bt, charges = SMARTBUFF_CheckUnitBuffs(unit, cBuff.Params, cBuff.Type, cBuff.Links, cBuff.Chain);
+ end
+ --SMARTBUFF_AddMsgD("Buff time ("..cBuff.Params..") = "..tostring(bt));
+ else
+ buff = nil;
+ end
+ end
+
+ if (buff == nil and cBuff.DurationS >= 1 and rbTime > 0) then
+ if (charges == nil) then charges = -1; end
+ if (charges > 1) then cBuff.CanCharge = true; end
+ bufftarget = nil;
+ end
+
+ if (bt and bt <= rbTime) then
+ buff = buffnS;
+ bExpire = true;
+ end
+
+ if (buff) then
+ if (cBuff.Type ~= SMARTBUFF_CONST_ITEM) then
+ local cr, iid = SMARTBUFF_CountReagent(buffnS, cBuff.Chain);
+ if (cr > 0) then
+ buff = buffnS;
+ if (cBuff.Type == SMARTBUFF_CONST_ITEMGROUP or cBuff.Type == SMARTBUFF_CONST_SCROLL) then
+ cds, cd = GetItemCooldown(iid);
+ cd = (cds + cd) - time;
+ --SMARTBUFF_AddMsgD(cr.." "..buffnS.." found, cd = "..cd);
+ if (cd > 0) then
+ buff = nil;
+ end
+ end
+ --SMARTBUFF_AddMsgD(cr .. " " .. buffnS .. " found");
+ else
+ --SMARTBUFF_AddMsgD("No " .. buffnS .. " found");
+ buff = nil;
+ bExpire = false;
+ end
+ end
+ end
+
+ -- Weapon buff ------------------------------------------------------------------------
+
+ elseif (cBuff.Type == SMARTBUFF_CONST_WEAPON or cBuff.Type == SMARTBUFF_CONST_INV) then
+ --SMARTBUFF_AddMsgD("Check weapon Buff");
+ local bMh, tMh, cMh, idMh, bOh, tOh, cOh, idOh = GetWeaponEnchantInfo();
+
+ if (bs.MH) then
+ iSlot = 16;
+ iId = GetInventoryItemID("player", iSlot);
+ if (iId and SMARTBUFF_CanApplyWeaponBuff(buffnS, iSlot)) then
+ if (bMh) then
+ if (rbTime > 0 and cBuff.DurationS >= 1) then
+ --if (tMh == nil) then tMh = 0; end
+ tMh = floor(tMh/1000);
+ charges = cMh;
+ if (charges == nil) then charges = -1; end
+ if (charges > 1) then cBuff.CanCharge = true; end
+ --SMARTBUFF_AddMsgD(un .. " (WMH): " .. buffnS .. string.format(" %.0f sec left", tMh) .. ", " .. charges .. " charges left");
+ if (tMh <= rbTime or (O.CheckCharges and cBuff.CanCharge and charges > 0 and charges <= O.MinCharges)) then
+ buff = buffnS;
+ bt = tMh;
+ bExpire = true;
+ end
+ end
+ else
+ handtype = "main";
+ buff = buffnS;
+ end
+ else
+ --SMARTBUFF_AddMsgD("Weapon Buff cannot be cast, no mainhand weapon equipped or wrong weapon/stone type");
+ end
+ end
+
+ if (bs.OH and not bExpire and handtype == "") then
+ iSlot = 17;
+ iId = GetInventoryItemID("player", iSlot);
+ if (iId and SMARTBUFF_CanApplyWeaponBuff(buffnS, iSlot)) then
+ if (bOh) then
+ if (rbTime > 0 and cBuff.DurationS >= 1) then
+ --if (tOh == nil) then tOh = 0; end
+ tOh = floor(tOh/1000);
+ charges = cOh;
+ if (charges == nil) then charges = -1; end
+ if (charges > 1) then cBuff.CanCharge = true; end
+ --SMARTBUFF_AddMsgD(un .. " (WOH): " .. buffnS .. string.format(" %.0f sec left", tOh) .. ", " .. charges .. " charges left");
+ if (tOh <= rbTime or (O.CheckCharges and cBuff.CanCharge and charges > 0 and charges <= O.MinCharges)) then
+ buff = buffnS;
+ bt = tOh;
+ bExpire = true;
+ end
+ end
+ else
+ handtype = "off";
+ buff = buffnS;
+ end
+ else
+ --SMARTBUFF_AddMsgD("Weapon Buff cannot be cast, no offhand weapon equipped or wrong weapon/stone type");
+ end
+ end
+
+ if (buff and cBuff.Type == SMARTBUFF_CONST_INV) then
+ local cr = SMARTBUFF_CountReagent(buffnS, cBuff.Chain);
+ if (cr > 0) then
+ --SMARTBUFF_AddMsgD(cr .. " " .. buffnS .. " found");
+ else
+ --SMARTBUFF_AddMsgD("No " .. buffnS .. " found");
+ buff = nil;
+ end
+ end
+
+ -- Normal buff ------------------------------------------------------------------------
+
+ else
+ local index = nil;
+
+ -- check timer object
+ buff, index, buffname, bt, charges = SMARTBUFF_CheckUnitBuffs(unit, buffnS, cBuff.Type, cBuff.Links, cBuff.Chain);
+ if (charges == nil) then charges = -1; end
+ if (charges > 1) then cBuff.CanCharge = true; end
+
+ if (unit ~= "target" and buff == nil and cBuff.DurationS >= 1 and rbTime > 0) then
+ if (SMARTBUFF_IsPlayer(unit)) then
+ if (cBuffTimer[unit] ~= nil and cBuffTimer[unit][buffnS] ~= nil) then
+ local tbt = cBuff.DurationS - (time - cBuffTimer[unit][buffnS]);
+ if (not bt or bt - tbt > rbTime) then
+ bt = tbt;
+ end
+ end
+ bufftarget = nil;
+ --SMARTBUFF_AddMsgD(un .. " (P): " .. index .. ". " .. GetPlayerBuffTexture(index) .. "(" .. charges .. ") - " .. buffnS .. string.format(" %.0f sec left", bt));
+ elseif (cBuffTimer[unit] ~= nil and cBuffTimer[unit][buffnS] ~= nil) then
+ bt = cBuff.DurationS - (time - cBuffTimer[unit][buffnS]);
+ bufftarget = nil;
+ --SMARTBUFF_AddMsgD(un .. " (S): " .. buffnS .. string.format(" %.0f sec left", bt));
+ elseif (cBuff.BuffG ~= nil and cBuffTimer[subgroup] ~= nil and cBuffTimer[subgroup][cBuff.BuffG] ~= nil) then
+ bt = cBuff.DurationG - (time - cBuffTimer[subgroup][cBuff.BuffG]);
+ if (type(subgroup) == "number") then
+ bufftarget = SMARTBUFF_MSG_GROUP .. " " .. subgroup;
+ else
+ bufftarget = SMARTBUFF_MSG_CLASS .. " " .. UnitClass(unit);
+ end
+ --SMARTBUFF_AddMsgD(bufftarget .. ": " .. cBuff.BuffG .. string.format(" %.0f sec left", bt));
+ elseif (cBuff.BuffG ~= nil and cBuffTimer[uc] ~= nil and cBuffTimer[uc][cBuff.BuffG] ~= nil) then
+ bt = cBuff.DurationG - (time - cBuffTimer[uc][cBuff.BuffG]);
+ bufftarget = SMARTBUFF_MSG_CLASS .. " " .. UnitClass(unit);
+ --SMARTBUFF_AddMsgD(bufftarget .. ": " .. cBuff.BuffG .. string.format(" %.0f sec left", bt));
+ else
+ bt = nil;
+ end
+
+ if ((bt and bt <= rbTime) or (O.CheckCharges and cBuff.CanCharge and charges > 0 and charges <= O.MinCharges)) then
+ if (buffname) then
+ buff = buffname;
+ else
+ buff = buffnS;
+ end
+ bExpire = true;
+ end
+ end
+
+ -- check if the group buff is active, in this case it is not possible to cast the single buff
+ if (buffname and mode ~= 1 and buffname ~= buffnS) then
+ buff = nil;
+ --SMARTBUFF_AddMsgD("Group buff is active, single buff canceled!");
+ --print("Group buff is active, single buff canceled!");
+ end
+
+ end -- END normal buff
+
+ -- check if shapeshifted and cancel buff if it is not possible to cast it
+ if (buff and cBuff.Type ~= SMARTBUFF_CONST_TRACK and cBuff.Type ~= SMARTBUFF_CONST_FORCESELF) then
+ --isShapeshifted = true;
+ --sShapename = "Moonkingestalt";
+ if (isShapeshifted) then
+ if (string.find(cBuff.Params, sShapename)) then
+ --SMARTBUFF_AddMsgD("Cast " .. buff .. " while shapeshifted");
+ else
+ if(cBuff.Params == SMARTBUFF_DRUID_CAT) then
+ buff = nil;
+ end
+ if (buff and mode ~= 1 and not O.InShapeshift and (sShapename ~= SMARTBUFF_DRUID_MOONKIN and sShapename ~= SMARTBUFF_DRUID_TREANT)) then
+ --sMsgWarning = SMARTBUFF_MSG_SHAPESHIFT .. ": " .. sShapename;
+ buff = nil;
+ end
+ end
+ else
+ if(cBuff.Params == SMARTBUFF_DRUID_CAT) then
+ buff = nil;
+ end
+ end
+ end
+
+ if (buff) then
+
+ -- Cast mode ---------------------------------------------------------------------------------------
+ if (mode == 0 or mode == 5) then
+ currentUnit = nil;
+ currentSpell = nil;
+
+ --try to apply weapon buffs on main/off hand
+ if (cBuff.Type == SMARTBUFF_CONST_INV) then
+ if (iSlot and (handtype ~= "" or bExpire)) then
+ local bag, slot, count = SMARTBUFF_FindItem(buffnS, cBuff.Chain);
+ if (count > 0) then
+ sMsgWarning = "";
+ return 0, SMARTBUFF_ACTION_ITEM, buffnS, iSlot, "player", cBuff.Type;
+ end
+ end
+ r = 50;
+ elseif (cBuff.Type == SMARTBUFF_CONST_WEAPON) then
+ if (iId and (handtype ~= "" or bExpire)) then
+ sMsgWarning = "";
+ return 0, SMARTBUFF_ACTION_SPELL, buffnS, iSlot, "player", cBuff.Type;
+ --return 0, SMARTBUFF_ACTION_SPELL, buffnS, iId, "player", cBuff.Type;
+ end
+ r = 50;
+
+ -- eat food or use scroll or potion
+ elseif (cBuff.Type == SMARTBUFF_CONST_FOOD or cBuff.Type == SMARTBUFF_CONST_SCROLL or cBuff.Type == SMARTBUFF_CONST_POTION) then
+ local bag, slot, count = SMARTBUFF_FindItem(buffnS, cBuff.Chain);
+ if (count > 0 or bExpire) then
+ sMsgWarning = "";
+ return 0, SMARTBUFF_ACTION_ITEM, buffnS, 0, "player", cBuff.Type;
+ end
+ r = 20;
+
+ -- use item on a unit
+ elseif (cBuff.Type == SMARTBUFF_CONST_ITEMGROUP) then
+ local bag, slot, count = SMARTBUFF_FindItem(buffnS, cBuff.Chain);
+ if (count > 0) then
+ sMsgWarning = "";
+ return 0, SMARTBUFF_ACTION_ITEM, buffnS, 0, unit, cBuff.Type;
+ end
+ r = 20;
+
+ -- create item
+ elseif (cBuff.Type == SMARTBUFF_CONST_ITEM) then
+ r = 20;
+ local bag, slot, count = SMARTBUFF_FindItem(buff, cBuff.Chain);
+ if (count == 0) then
+ r = SMARTBUFF_doCast(unit, cBuff.IDS, buffnS, cBuff.LevelsS, cBuff.Type);
+ if (r == 0) then
+ currentUnit = unit;
+ currentSpell = buffnS;
+ end
+ end
+
+ -- cast spell
+ else
+ r, _, rankText = SMARTBUFF_doCast(unit, cBuff.IDS, buffnS, cBuff.LevelsS, cBuff.Type);
+ if (r == 0) then
+ currentUnit = unit;
+ currentSpell = buffnS;
+ end
+ end
+
+ -- Check mode ---------------------------------------------------------------------------------------
+ elseif (mode == 1) then
+ currentUnit = nil;
+ currentSpell = nil;
+ if (bufftarget == nil) then bufftarget = un; end
+
+ if (SMARTBUFF_CheckUnitLevel(unit, cBuff.IDS, cBuff.LevelsS) ~= nil or cBuff.IDS ~= nil or SMARTBUFF_IsItem(cBuff.Type) or cBuff.Type == SMARTBUFF_CONST_TRACK) then
+ -- clean up buff timer, if expired
+ if (bt and bt < 0 and bExpire) then
+ bt = 0;
+ if (cBuffTimer[unit] ~= nil and cBuffTimer[unit][buffnS] ~= nil) then
+ cBuffTimer[unit][buffnS] = nil;
+ --SMARTBUFF_AddMsgD(un .. " (S): " .. buffnS .. " timer reset");
+ end
+ if (cBuff.IDG ~= nil) then
+ if (cBuffTimer[subgroup] ~= nil and cBuffTimer[subgroup][cBuff.BuffG] ~= nil) then
+ cBuffTimer[subgroup][cBuff.BuffG] = nil;
+ --SMARTBUFF_AddMsgD("Group " .. subgroup .. ": " .. buffnS .. " timer reset");
+ end
+ if (cBuffTimer[uc] ~= nil and cBuffTimer[uc][cBuff.BuffG] ~= nil) then
+ cBuffTimer[uc][cBuff.BuffG] = nil;
+ --SMARTBUFF_AddMsgD("Class " .. uc .. ": " .. cBuff.BuffG .. " timer reset");
+ end
+ end
+ tLastCheck = time - O.AutoTimer + 0.5;
+ return 0;
+ end
+
+ SMARTBUFF_SetMissingBuffMessage(bufftarget, buff, cBuff.IconS, cBuff.CanCharge, charges, bt, bExpire);
+ SMARTBUFF_SetButtonTexture(SmartBuff_KeyButton, cBuff.IconS);
+ return 0;
+ end
+ end
+
+ if (r == 0) then
+ -- target buffed
+ -- Message will printed in the "SPELLCAST_STOP" event
+ sMsgWarning = "";
+ return 0, SMARTBUFF_ACTION_SPELL, buffnS, -1, unit, cBuff.Type, rankText;
+ elseif (r == 1) then
+ -- spell cooldown
+ if (mode == 0) then SMARTBUFF_AddMsgWarn(buffnS .. " " .. SMARTBUFF_MSG_CD); end
+ return 1;
+ elseif (r == 2) then
+ -- can not target
+ if (mode == 0 and ucf ~= SMARTBUFF_DEMONTYPE) then SMARTBUFF_AddMsgD("Can not target " .. un); end
+ elseif (r == 3) then
+ -- target oor
+ if (mode == 0) then SMARTBUFF_AddMsgWarn(un .. " " .. SMARTBUFF_MSG_OOR); end
+ break;
+ elseif (r == 4) then
+ -- spell cooldown > maxSkipCoolDown
+ if (mode == 0) then SMARTBUFF_AddMsgD(buffnS .. " " .. SMARTBUFF_MSG_CD .. " > " .. maxSkipCoolDown); end
+ elseif (r == 5) then
+ -- target to low
+ if (mode == 0) then SMARTBUFF_AddMsgD(un .. " is to low to get buffed with " .. buffnS); end
+ elseif (r == 6) then
+ -- not enough mana/rage/energy
+ sMsgWarning = SMARTBUFF_MSG_OOM;
+ elseif (r == 7) then
+ -- tracking ability is already active
+ if (mode == 0) then SMARTBUFF_AddMsgD(buffnS .. " not used, other ability already active"); end
+ elseif (r == 8) then
+ -- actionslot is not defined
+ if (mode == 0) then SMARTBUFF_AddMsgD(buffnS .. " has no actionslot"); end
+ elseif (r == 9) then
+ -- spell ID not found
+ if (mode == 0) then SMARTBUFF_AddMsgD(buffnS .. " spellID not found"); end
+ elseif (r == 10) then
+ -- target could not buffed
+ if (mode == 0) then SMARTBUFF_AddMsgD(buffnS .. " could not buffed on " .. un); end
+ elseif (r == 20) then
+ -- item not found
+ if (mode == 0) then SMARTBUFF_AddMsgD(buffnS .. " could not used"); end
+ elseif (r == 50) then
+ -- weapon buff could not applied
+ if (mode == 0) then SMARTBUFF_AddMsgD(buffnS .. " could not applied"); end
+ else
+ -- no spell selected
+ if (mode == 0) then SMARTBUFF_AddMsgD(SMARTBUFF_MSG_CHAT); end
+ end
+ else
+ -- finished
+ if (mode == 0) then SMARTBUFF_AddMsgD(un .. " nothing to buff"); end
+ end
+ else
+ -- target does not need this buff
+ if (mode == 0) then SMARTBUFF_AddMsgD(un .. " does not need " .. buffnS); end
+ end
+ else
+ -- cooldown
+ if (sMsgWarning == "") then
+ sMsgWarning = SMARTBUFF_MSG_CD;
+ end
+ --SMARTBUFF_AddMsgD("Spell on cd: "..buffnS);
+ end
+ end -- group or self
+ end
+ --i = i + 1;
+ end -- for buff
+
+ end
+ return 3;
+end
+-- END SMARTBUFF_BuffUnit
+
+
+function SMARTBUFF_IsInList(unit, unitname, list)
+ if (list ~= nil) then
+ for un in pairs(list) do
+ if (un ~= nil and UnitIsPlayer(unit) and un == unitname) then
+ return true;
+ end
+ end
+ end
+ return false;
+end
+
+
+function SMARTBUFF_SetMissingBuffMessage(target, buff, icon, bCanCharge, nCharges, tBuffTimeLeft, bExpire)
+ local f = SmartBuffSplashFrame;
+ -- show splash buff message
+ if (f and O.ToggleAutoSplash and not SmartBuffOptionsFrame:IsVisible()) then
+ local s;
+ local sd = O.SplashDuration;
+ local si = "";
+
+ if (OG.SplashIcon and icon) then
+ local n = O.SplashIconSize;
+ if (n == nil or n <= 0) then
+ n = O.CurrentFontSize;
+ end
+ si = string.format("\124T%s:%d:%d:1:0\124t ", icon, n, n) or "";
+ end
+ if (OG.SplashMsgShort and si == "") then si = buff end
+ if (O.AutoTimer < 4) then
+ sd = 1;
+ f:Clear();
+ end
+
+ f:SetTimeVisible(sd);
+ if (not nCharges) then nCharges = 0; end
+ if (O.CheckCharges and bCanCharge and nCharges > 0 and nCharges <= O.MinCharges and bExpire) then
+ if (OG.SplashMsgShort) then
+ s = target.." > "..si.." < "..format(SMARTBUFF_ABBR_CHARGES_OL, nCharges);
+ else
+ s = target.."\n"..SMARTBUFF_MSG_REBUFF.." "..si..buff..": "..format(ITEM_SPELL_CHARGES, nCharges).." "..SMARTBUFF_MSG_LEFT;
+ end
+ elseif (bExpire) then
+ if (OG.SplashMsgShort) then
+ s = target.." > "..si.." < "..format(SECOND_ONELETTER_ABBR, tBuffTimeLeft);
+ else
+ s = target.."\n"..SMARTBUFF_MSG_REBUFF.." "..si..buff..": "..format(SECONDS_ABBR, tBuffTimeLeft).." "..SMARTBUFF_MSG_LEFT;
+ end
+ else
+ if (OG.SplashMsgShort) then
+ s = target.." > "..si;
+ else
+ s = target.." "..SMARTBUFF_MSG_NEEDS.." "..si..buff;
+ end
+ end
+ f:AddMessage(s, O.ColSplashFont.r, O.ColSplashFont.g, O.ColSplashFont.b, 1.0);
+ end
+
+ -- show chat buff message
+ if (O.ToggleAutoChat) then
+ if (O.CheckCharges and bCanCharge and nCharges > 0 and nCharges <= O.MinCharges and bExpire) then
+ SMARTBUFF_AddMsgWarn(target..": "..SMARTBUFF_MSG_REBUFF.." "..buff..", "..format(ITEM_SPELL_CHARGES, nCharges).." ".. SMARTBUFF_MSG_LEFT, true);
+ elseif (bExpire) then
+ SMARTBUFF_AddMsgWarn(target..": "..SMARTBUFF_MSG_REBUFF.." "..buff..format(SECONDS_ABBR, tBuffTimeLeft).." "..SMARTBUFF_MSG_LEFT, true);
+ else
+ SMARTBUFF_AddMsgWarn(target.." "..SMARTBUFF_MSG_NEEDS.." "..buff, true);
+ end
+ end
+
+ -- play sound
+ if (O.ToggleAutoSound) then
+ PlaySound(1141);
+ end
+end
+
+
+local cWeaponStandard = {0, 1, 4, 5, 6, 7, 8, 10, 13, 15, 16}; -- "Daggers", "Axes", "Swords", "Maces", "Staves", "Fist Weapons", "Polearms", "Thrown"
+local cWeaponBlunt = {4, 5, 10, 13}; -- "Maces", "Staves", "Fist Weapons"
+local cWeaponSharp = {0, 1, 6, 7, 8, 15}; -- "Daggers", "Axes", "Swords", "Polearms"
+
+-- check if a spell/reagent could applied on a weapon
+function SMARTBUFF_CanApplyWeaponBuff(buff, slot)
+ local cWeaponTypes = nil;
+ if (string.find(buff, SMARTBUFF_WEAPON_SHARP_PATTERN)) then
+ cWeaponTypes = cWeaponSharp;
+ elseif (string.find(buff, SMARTBUFF_WEAPON_BLUNT_PATTERN)) then
+ cWeaponTypes = cWeaponBlunt;
+ else
+ cWeaponTypes = cWeaponStandard;
+ end
+
+ local itemLink = GetInventoryItemLink("player", slot);
+ if (itemLink == nil) then return false end
+
+ local itemType, itemSubType, _, _, _, _, classId, subclassId = select(6, GetItemInfo(itemLink));
+ --if (itemType and itemSubType) then
+ -- SMARTBUFF_AddMsgD("Type: "..itemType..", Subtype: "..itemSubType);
+ --end
+
+ if (tcontains(cWeaponTypes, subclassId)) then
+ return true, itemSubType;
+ end
+
+ return false;
+end
+-- END SMARTBUFF_CanApplyWeaponBuff
+
+
+-- Check the unit blacklist
+function SMARTBUFF_checkBlacklist()
+ local t = GetTime();
+ for unit in pairs(cBlacklist) do
+ if (t > (cBlacklist[unit] + O.BlacklistTimer)) then
+ cBlacklist[unit] = nil;
+ end
+ end
+end
+-- END SMARTBUFF_checkBlacklist
+
+
+-- Casts a spell
+function SMARTBUFF_doCast(unit, id, spellName, levels, type)
+ if (id == nil) then return 9; end
+
+ if (type == SMARTBUFF_CONST_TRACK) then
+ local iconTrack = GetTrackingTexture();
+ if (iconTrack ~= nil and iconTrack ~= "Interface\\Minimap\\Tracking\\None") then
+ SMARTBUFF_AddMsgD("Track already enabled: "..iconTrack);
+ return 7;
+ end
+ end
+
+ -- check if spell has cooldown
+ local _, cd = GetSpellCooldown(spellName)
+ if (not cd) then
+ -- move on
+ elseif (cd > maxSkipCoolDown) then
+ return 4;
+ elseif (cd > 0) then
+ return 1;
+ end
+
+ -- Rangecheck
+ if (type == SMARTBUFF_CONST_GROUP or type == SMARTBUFF_CONST_ITEMGROUP) then
+
+ if (SpellHasRange(spellName)) then
+ if (IsSpellInRange(spellName, unit) ~= 1) then
+ return 3;
+ end
+ else
+ if (UnitInRange(unit) ~= 1) then
+ return 3;
+ end
+ end
+
+ end
+
+ -- check if target is to low for this spell
+ local newId, rank, rankText = SMARTBUFF_CheckUnitLevel(unit, id, levels);
+ if (newId == nil) then
+ return 5;
+ end
+
+ -- check if you have enough mana/energy/rage to cast
+ local isUsable, notEnoughMana = IsUsableSpell(spellName);
+ if (notEnoughMana) then
+ return 6;
+ end
+
+ return 0, rank, rankText;
+end
+-- END SMARTBUFF_doCast
+
+
+-- checks if the unit is the player
+function SMARTBUFF_IsPlayer(unit)
+ if (unit and UnitIsUnit("player", unit)) then
+ return true;
+ end
+ return false;
+end
+-- END SMARTBUFF_IsPlayer
+
+
+function UnitBuffByBuffName(target,buffname,filter)
+ for i = 1,40 do
+ name = UnitBuff(target, i, filter);
+ if not name then return end
+ if name == buffname then
+ return UnitBuff(target, i, filter);
+ end
+ end
+end
+
+--
+-- SMARTBUFF_CheckUnitBuffs
+-- Function to return the name of the buff to cast.
+--
+function SMARTBUFF_CheckUnitBuffs(unit, buffN, buffT, buffL, buffC)
+ if (not unit or (not buffN and not buffL)) then return end
+
+ local i, n, v;
+ local buff = nil;
+ local defBuff = nil;
+ local timeleft = nil;
+ local duration = nil;
+ local caster = nil;
+ local count = nil;
+ local icon = nil;
+ local time = GetTime();
+ local uname = UnitName(unit) or "?";
+
+ if (buffN) then
+ defBuff = buffN;
+ else
+ defBuff = buffL[1];
+ end
+
+ -- Stance/Presence/Seal check, these are not in the aura list
+ n = cBuffIndex[defBuff];
+ if (cBuffs[n] and cBuffs[n].Type == SMARTBUFF_CONST_STANCE) then
+ if (defBuff and buffC and #buffC >= 1) then
+ local t = B[CS()].Order;
+ if (t and #t >= 1) then
+ for i = 1, #t, 1 do
+ if (t[i] and tfind(buffC, t[i])) then
+ v = GetBuffSettings(t[i]);
+ if (v and v.EnableS) then
+ for n = 1, GetNumShapeshiftForms(), 1 do
+ local _, name, active, castable = GetShapeshiftFormInfo(n);
+ if (name and not active and castable and name == t[i]) then
+ return defBuff, nil, nil, nil, nil;
+ elseif (name and active and castable and name == t[i]) then
+ return nil, i, defBuff, 1800, -1;
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ return defBuff, nil, nil, nil, nil;
+ end
+
+ -- Check linked buffs
+ if (buffL) then
+ if (not O.LinkSelfBuffCheck and buffT == SMARTBUFF_CONST_SELF) then
+ -- Do not check linked self buffs
+ elseif (not O.LinkGrpBuffCheck and buffT == SMARTBUFF_CONST_GROUP) then
+ -- Do not check linked group buffs
+ else
+ for n, v in pairs(buffL) do
+ if (v and v ~= defBuff) then
+ SMARTBUFF_AddMsgD("Check linked buff ("..uname.."): "..v);
+ buff, icon, count, _, duration, timeleft, caster = UnitBuffByBuffName(unit, v);
+ if (buff) then
+ timeleft = timeleft - time;
+ SMARTBUFF_AddMsgD("Linked buff found: "..buff..", "..timeleft..", "..icon);
+ return nil, n, defBuff, timeleft, count;
+ end
+ end
+ end
+ end
+ end
+
+ -- Check chained buffs
+ if (defBuff and buffC and #buffC > 1) then
+ local t = B[CS()].Order;
+ if (t and #t > 1) then
+ for i = 1, #t, 1 do
+ if (t[i] and tfind(buffC, t[i])) then
+ v = GetBuffSettings(t[i]);
+ if (v and v.EnableS) then
+ local b, tl, im = SMARTBUFF_CheckBuff(unit, t[i]);
+ if (b and im) then
+ if (SMARTBUFF_CheckBuffLink(unit, t[i], v.Type, v.Links)) then
+ return nil, i, defBuff, tl, -1;
+ end
+ elseif (not b and t[i] == defBuff) then
+ return defBuff, nil, nil, nil, nil;
+ end
+ end
+ end
+ end
+ end
+ end
+
+ -- Check default buff
+ if (defBuff) then
+ buff, icon, count, _, duration, timeleft, caster = UnitBuffByBuffName(unit, defBuff);
+ if (buff) then
+-- print("Found buff: "..buff.. " on unit: "..unit)
+ timeleft = timeleft - time;
+ if (SMARTBUFF_IsPlayer(caster)) then
+ SMARTBUFF_UpdateBuffDuration(defBuff, duration);
+ end
+ SMARTBUFF_AddMsgD("Default buff found: "..buff..", "..timeleft..", "..icon);
+ return nil, 0, defBuff, timeleft, count;
+ else
+-- print("Not Found Buff: "..defBuff.. " on unit: "..unit)
+ end
+ end
+
+ -- Buff not found, return default buff
+ return defBuff, nil, nil, nil, nil;
+
+end
+
+
+-- Will return the lower Id of the spell, if the unit level is lower
+function SMARTBUFF_CheckUnitLevel(unit, spellId, spellLevels)
+ if (spellLevels == nil or spellId == nil) then
+ return spellId;
+ end
+
+ local Id = spellId;
+ local uLevel = UnitLevel(unit);
+ local spellName, _, icon, castTime, minRange, maxRange = GetSpellInfo(Id);
+ local sRank = GetSpellSubtext(Id);
+ if (sRank == nil or sRank == "") then
+ return Id;
+ end
+
+ local _, _, spellRank = string.find(sRank, "(%d+)");
+ if (spellRank == nil) then
+ return Id;
+ end
+
+ spellRank = tonumber(spellRank);
+ local i = spellRank;
+
+ --SMARTBUFF_AddMsgD(spellName .. sRank .. ":" .. spellRank .. ", " .. spellLevels[i]);
+
+ while (i >= 1) do
+ if (uLevel >= (spellLevels[i] - 10)) then
+ break;
+ end
+ i = i - 1;
+ end
+
+ if (i == spellRank) then
+ return Id;
+ end
+
+ local rankText;
+ if (i > 0) then
+ local n = spellRank - i;
+ Id = Id - n;
+ rankText = "("..string.gsub(sRank, "(%d+)", n)..")";
+ --SMARTBUFF_AddMsgD(uLevel .. " " .. spellName .. " Rank " .. i .. " - ID = " .. Id);
+ else
+ Id = nil;
+ --SMARTBUFF_AddMsgD(spellName .. ": no rank available for this level");
+ end;
+
+ return Id, i, rankText;
+end
+-- END SMARTBUFF_CheckUnitLevel
+
+
+
+function SMARTBUFF_CheckBuffLink(unit, defBuff, buffT, buffL)
+ -- Check linked buffs
+ if (buffL) then
+ if (not O.LinkSelfBuffCheck and buffT == SMARTBUFF_CONST_SELF) then
+ -- Do not check linked self buffs
+ elseif (not O.LinkGrpBuffCheck and buffT == SMARTBUFF_CONST_GROUP) then
+ -- Do not check linked group buffs
+ else
+ for n, v in pairs(buffL) do
+ if (v and v ~= defBuff) then
+ SMARTBUFF_AddMsgD("Check linked buff ("..uname.."): "..v);
+ buff, icon, count, _, duration, timeleft, caster = UnitBuffByBuffName(unit, v);
+ if (buff) then
+ timeleft = timeleft - time;
+ SMARTBUFF_AddMsgD("Linked buff found: "..buff..", "..timeleft..", "..icon);
+ return nil, n, defBuff, timeleft, count;
+ end
+ end
+ end
+ end
+ end
+ return defBuff;
+end
+
+function SMARTBUFF_CheckBuffChain(unit, buff, chain)
+ local i;
+ if (buff and chain and #chain > 1) then
+ local t = B[CS()].Order;
+ if (t and #t > 1) then
+ SMARTBUFF_AddMsgD("Check chained buff: "..buff);
+ for i = 1, #t, 1 do
+ if (t[i] and t[i] ~= buff and tfind(chain, t[i])) then
+ local b, tl, im = SMARTBUFF_CheckBuff(unit, t[i], true);
+ if (b and im) then
+ SMARTBUFF_AddMsgD("Chained buff found: "..t[i]);
+ return nil, i, buff, tl, -1;
+ end
+ end
+ end
+ end
+ end
+ return buff;
+end
+
+
+function SMARTBUFF_UpdateBuffDuration(buff, duration)
+ local i = cBuffIndex[buff];
+ if (i ~= nil and cBuffs[i] ~= nil and buff == cBuffs[i].BuffS) then
+ if (cBuffs[i].DurationS ~= nil and cBuffs[i].DurationS > 0 and cBuffs[i].DurationS ~= duration) then
+ SMARTBUFF_AddMsgD("Updated buff duration: "..buff.." = "..duration.."sec, old = "..cBuffs[i].DurationS);
+ cBuffs[i].DurationS = duration;
+ end
+ end
+end
+
+
+function UnitAuraBySpellName(target, spellname, filter)
+ for i = 1,40 do
+ name = UnitAura(target, i, filter);
+ if not name then return end
+ if name == spellname then
+ return UnitAuraFull(target, i, filter);
+ end
+ end
+end
+
+function SMARTBUFF_CheckBuff(unit, buffName, isMine)
+ if (not unit or not buffName) then
+ return false, 0;
+ end
+ local buff, _, _, _, _, timeleft, caster = UnitAuraBySpellName(unit, buffName, "HELPFUL");
+ if (buff) then
+ SMARTBUFF_AddMsgD(UnitName(unit).." buff found: "..buff, 0, 1, 0.5);
+ if (buff == buffName) then
+ timeleft = timeleft - GetTime();
+ if (isMine and caster) then
+ if (SMARTBUFF_IsPlayer(caster)) then
+ return true, timeleft, caster;
+ end
+ return false, 0, nil;
+ end
+ return true, timeleft, SMARTBUFF_IsPlayer(caster);
+ end
+ end
+ return false, 0;
+end
+-- END SMARTBUFF_CheckUnitBuffs
+
+
+-- Will return the name/description of the buff
+function SMARTBUFF_GetBuffName(unit, buffIndex, line)
+ local i = buffIndex;
+ local name = nil;
+ if (i < 0 or i > maxBuffs) then
+ return nil;
+ end
+ --SmartBuffTooltip:SetOwner(SmartBuffFrame, "ANCHOR_NONE");
+ SmartBuffTooltip:ClearLines();
+ SmartBuffTooltip:SetUnitBuff(unit, i);
+ local obj = _G["SmartBuffTooltipTextLeft" .. line];
+ if (obj) then
+ name = obj:GetText();
+ end
+ return name;
+end
+-- END SMARTBUFF_GetBuffName
+
+
+-- IsFeignDeath(unit)
+function SMARTBUFF_IsFeignDeath(unit)
+ return UnitIsFeignDeath(unit);
+end
+-- END SMARTBUFF_IsFeignDeath
+
+
+-- IsPicnic(unit)
+function SMARTBUFF_IsPicnic(unit)
+ if (not SMARTBUFF_CheckUnitBuffs(unit, SMARTBUFF_FOOD_SPELL, SMARTBUFF_CONST_FOOD, {SMARTBUFF_FOOD_SPELL, SMARTBUFF_DRINK_SPELL})) then
+ return true;
+ end
+ return false;
+end
+-- END SMARTBUFF_IsPicnic
+
+
+-- IsFishing(unit)
+function SMARTBUFF_IsFishing(unit)
+ -- spell, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitChannelInfo("unit")
+ local spell = UnitChannelInfo(unit);
+ if (spell ~= nil and SMARTBUFF_FISHING ~= nil and spell == SMARTBUFF_FISHING) then
+ --SMARTBUFF_AddMsgD("Channeling "..SMARTBUFF_FISHING);
+ return true;
+ end
+ return false;
+end
+
+function SMARTBUFF_IsFishingPoleEquiped()
+ if (not SG or not SG.FishingPole) then return false end
+
+ local link = GetInventoryItemLink("player", GetInventorySlotInfo("MainHandSlot"));
+ if (not link) then return false end
+
+ local _, _, _, _, _, _, subType = GetItemInfo(link);
+ if (not subType) then return false end
+
+ --print(SG.FishingPole.." - "..subType);
+ if (SG.FishingPole == subType) then return true end
+
+ return false;
+end
+-- END SMARTBUFF_IsFishing
+
+-- SMARTBUFF_IsSpell(sType)
+function SMARTBUFF_IsSpell(sType)
+ return sType == SMARTBUFF_CONST_GROUP or sType == SMARTBUFF_CONST_GROUPALL or sType == SMARTBUFF_CONST_SELF or sType == SMARTBUFF_CONST_FORCESELF or sType == SMARTBUFF_CONST_WEAPON or sType == SMARTBUFF_CONST_STANCE or sType == SMARTBUFF_CONST_ITEM;
+end
+-- END SMARTBUFF_IsSpell
+
+-- SMARTBUFF_IsItem(sType)
+function SMARTBUFF_IsItem(sType)
+ return sType == SMARTBUFF_CONST_INV or sType == SMARTBUFF_CONST_FOOD or sType == SMARTBUFF_CONST_SCROLL or sType == SMARTBUFF_CONST_POTION or sType == SMARTBUFF_CONST_ITEMGROUP;
+end
+-- END SMARTBUFF_IsItem
+
+
+-- Loops through all of the debuffs currently active looking for a texture string match
+function SMARTBUFF_IsDebuffTexture(unit, debufftex)
+ local active = false;
+ local i = 1;
+ local name, icon;
+ -- name,rank,icon,count,type = UnitDebuff("unit", id or "name"[,"rank"])
+ while (UnitDebuff(unit, i)) do
+ name, icon, _, _ = UnitDebuff(unit, i);
+ --SMARTBUFF_AddMsgD(i .. ". " .. name .. ", " .. icon);
+ if (string.find(icon, debufftex)) then
+ active = true;
+ break
+ end
+ i = i + 1;
+ end
+ return active;
+end
+-- END SMARTASPECT_IsDebuffTex
+
+
+-- Returns the number of a reagent currently in player's bag
+function SMARTBUFF_CountReagent(reagent, chain)
+ if (reagent == nil) then
+ return -1, nil;
+ end
+
+ local toy = SG.Toybox[reagent];
+ if (toy) then
+ return 1, toy[1];
+ end
+
+ local n = 0;
+ local id = nil;
+ local bag = 0;
+ local slot = 0;
+ local itemLink, itemName, count;
+ if (chain == nil) then chain = { reagent }; end
+ for bag = 0, NUM_BAG_FRAMES do
+ for slot = 1, GetContainerNumSlots(bag) do
+ itemLink = GetContainerItemLink(bag, slot);
+ if (itemLink ~= nil) then
+ itemName = string.match(itemLink, "%[.-%]");
+ --print(bag, slot, itemName);
+ for i = 1, #chain, 1 do
+ --print(chain[i]);
+ if (chain[i] and string.find(itemName, chain[i], 1, true)) then
+ --if (chain[i] and string.find(itemLink, "["..chain[i].."]", 1, true)) then
+ --print("Item found: "..chain[i]);
+ _, count = GetContainerItemInfo(bag, slot);
+ id = GetContainerItemID(bag, slot);
+ n = n + count;
+ end
+ end
+ end
+ end
+ end
+ return n, id;
+end
+
+function SMARTBUFF_FindItem(reagent, chain)
+ if (reagent == nil) then
+ return nil, nil, -1, nil;
+ end
+
+ --local toy = SG.Toybox[reagent];
+ --if (toy) then
+ -- return 999, toy[1], 1, toy[2];
+ --end
+
+ local n = 0;
+ local bag = 0;
+ local slot = 0;
+ local itemLink, itemName, texture, count;
+ if (chain == nil) then chain = { reagent }; end
+ for bag = 0, NUM_BAG_FRAMES do
+ for slot = 1, GetContainerNumSlots(bag) do
+ itemLink = GetContainerItemLink(bag, slot);
+ if (itemLink ~= nil) then
+ --itemName = string.match(itemLink, "item[%-?%d:]+");
+ --itemName = string.match(itemLink, "|h%[.*%]|h");
+ itemName = string.match(itemLink, "%[.-%]");
+ --print(bag, slot, itemName);
+ --SMARTBUFF_AddMsgD("Reagent found: " .. itemLink);
+ for i = 1, #chain, 1 do
+ --print(chain[i]);
+ if (chain[i] and string.find(itemName, chain[i], 1, true)) then
+ --if (chain[i] and string.find(itemLink, "["..chain[i].."]", 1, true)) then
+ --print("Item found: "..chain[i]);
+ texture, count = GetContainerItemInfo(bag, slot);
+ return bag, slot, count, texture;
+ end
+ end
+ end
+ end
+ end
+ return nil, nil, 0, nil;
+end
+-- END Reagent functions
+
+
+---------------------------------------------------------------------------------------------------
+-- check the current zone and set buff template
+---------------------------------------------------------------------------------------------------
+function SMARTBUFF_CheckLocation()
+ if (not O.AutoSwitchTemplate and not O.AutoSwitchTemplateInst) then return; end
+
+ local zone = GetRealZoneText();
+ if (zone == nil) then
+ SMARTBUFF_AddMsgD("No zone found, try again...");
+ tStartZone = GetTime();
+ isSetZone = true;
+ return;
+ end
+
+ isSetZone = false;
+ local tmp = nil;
+ local b = false;
+
+ SMARTBUFF_AddMsgD("Current zone: "..zone..", last zone: "..sLastZone);
+ if (zone ~= sLastZone) then
+ sLastZone = zone;
+ if (IsActiveBattlefieldArena()) then
+ tmp = SMARTBUFF_TEMPLATES[5];
+ elseif (SMARTBUFF_IsActiveBattlefield(zone) == 1) then
+ tmp = SMARTBUFF_TEMPLATES[4];
+ else
+ if (O.AutoSwitchTemplateInst) then
+ local i = 1;
+ for _ in pairs(SMARTBUFF_INSTANCES) do
+ if (string.find(string.lower(zone), string.lower(SMARTBUFF_INSTANCES[i]))) then
+ b = true;
+ break;
+ end
+ i = i + 1;
+ end
+ tmp = nil;
+ if (b) then
+ if (SMARTBUFF_TEMPLATES[i + 5] ~= nil) then
+ tmp = SMARTBUFF_TEMPLATES[i + 5]
+ end
+ end
+ end
+ end
+ --SMARTBUFF_AddMsgD("Current tmpl: " .. currentTemplate .. " - new tmpl: " .. tmp);
+ if (tmp and currentTemplate ~= tmp) then
+ SMARTBUFF_AddMsg(SMARTBUFF_OFT_AUTOSWITCHTMP .. ": " .. currentTemplate .. " -> " .. tmp);
+ currentTemplate = tmp;
+ SMARTBUFF_SetBuffs();
+ end
+ end
+end
+
+
+
+-- checks if the player is inside a battlefield
+function SMARTBUFF_IsActiveBattlefield(zone)
+ local i, status, map, instanceId, teamSize;
+ for i = 1, GetMaxBattlefieldID() do
+ status, map, instanceId, _, _, teamSize = GetBattlefieldStatus(i);
+ if (status and status ~= "none") then
+ SMARTBUFF_AddMsgD("Battlefield status = "..ChkS(status)..", Id = "..ChkS(instanceId)..", TS = "..ChkS(teamSize)..", Map = "..ChkS(map)..", Zone = "..ChkS(zone));
+ else
+ SMARTBUFF_AddMsgD("Battlefield status = none");
+ end
+ if (status and status == "active" and map) then
+ if (teamSize and type(teamSize) == "number" and teamSize > 0) then
+ return 2;
+ end
+ return 1;
+ end
+ end
+ return 0;
+end
+-- END IsActiveBattlefield
+
+
+-- Helper functions ---------------------------------------------------------------------------------------
+function SMARTBUFF_toggleBool(b, msg)
+ if (not b or b == nil) then
+ b = true;
+ SMARTBUFF_AddMsg(SMARTBUFF_TITLE .. ": " .. msg .. GR .. "On", true);
+ else
+ b = false
+ SMARTBUFF_AddMsg(SMARTBUFF_TITLE .. ": " .. msg .. RD .."Off", true);
+ end
+ return b;
+end
+
+function SMARTBUFF_BoolState(b, msg)
+ if (b) then
+ SMARTBUFF_AddMsg(SMARTBUFF_TITLE .. ": " .. msg .. GR .. "On", true);
+ else
+ SMARTBUFF_AddMsg(SMARTBUFF_TITLE .. ": " .. msg .. RD .."Off", true);
+ end
+end
+
+function SMARTBUFF_Split(msg, char)
+ local arr = { };
+ while (string.find(msg, char)) do
+ local iStart, iEnd = string.find(msg, char);
+ tinsert(arr, strsub(msg, 1, iStart - 1));
+ msg = strsub(msg, iEnd + 1, strlen(msg));
+ end
+ if (strlen(msg) > 0) then
+ tinsert(arr, msg);
+ end
+ return arr;
+end
+-- END Bool helper functions
+
+
+-- Init the SmartBuff variables ---------------------------------------------------------------------------------------
+function SMARTBUFF_Options_Init(self)
+ if (isInit) then return; end
+
+ self:UnregisterEvent("CHAT_MSG_CHANNEL");
+ self:UnregisterEvent("UPDATE_MOUSEOVER_UNIT");
+
+ --DebugChatFrame:AddMessage("Starting init SB");
+
+ _, sPlayerClass = UnitClass("player");
+ sRealmName = GetRealmName();
+ sPlayerName = UnitName("player");
+ sID = sRealmName .. ":" .. sPlayerName;
+ --AutoSelfCast = GetCVar("autoSelfCast");
+
+ SMARTBUFF_PLAYERCLASS = sPlayerClass;
+
+
+ if (not SMARTBUFF_Buffs) then SMARTBUFF_Buffs = { }; end
+ B = SMARTBUFF_Buffs;
+ if (not SMARTBUFF_Options) then SMARTBUFF_Options = { }; end
+ O = SMARTBUFF_Options;
+
+ SMARTBUFF_BROKER_SetIcon(); -- bug fix, credit: SunNova
+
+ if (O.Toggle == nil) then O.Toggle = true; end
+ if (O.ToggleAuto == nil) then O.ToggleAuto = true; end
+ if (O.AutoTimer == nil) then O.AutoTimer = 5; end
+ if (O.BlacklistTimer == nil) then O.BlacklistTimer = 5; end
+ if (O.ToggleAutoCombat == nil) then O.ToggleAutoCombat = false; end
+ if (O.ToggleAutoChat == nil) then O.ToggleAutoChat = false; end
+ if (O.ToggleAutoSplash == nil) then O.ToggleAutoSplash = true; end
+ if (O.ToggleAutoSound == nil) then O.ToggleAutoSound = true; end
+ if (O.CheckCharges == nil) then O.CheckCharges = true; end
+ --if (O.ToggleAutoRest == nil) then O.ToggleAutoRest = true; end
+ if (O.RebuffTimer == nil) then O.RebuffTimer = 20; end
+ if (O.SplashDuration == nil) then O.SplashDuration = 2; end
+ if (O.SplashIconSize == nil) then O.SplashIconSize = 12; end
+
+ if (O.BuffTarget == nil) then O.BuffTarget = false; end
+ if (O.BuffPvP == nil) then O.BuffPvP = false; end
+ if (O.BuffInCities == nil) then O.BuffInCities = true; end
+ if (O.LinkSelfBuffCheck == nil) then O.LinkSelfBuffCheck = true; end
+ if (O.LinkGrpBuffCheck == nil) then O.LinkGrpBuffCheck = true; end
+ if (O.AntiDaze == nil) then O.AntiDaze = true; end
+
+ if (O.ScrollWheel ~= nil and O.ScrollWheelUp == nil) then O.ScrollWheelUp = O.ScrollWheel; end
+ if (O.ScrollWheel ~= nil and O.ScrollWheelDown == nil) then O.ScrollWheelDown = O.ScrollWheel; end
+ if (O.ScrollWheelUp == nil) then O.ScrollWheelUp = true; end
+ if (O.ScrollWheelDown == nil) then O.ScrollWheelDown = true; end
+
+ if (O.InCombat == nil) then O.InCombat = true; end
+ if (O.AutoSwitchTemplate == nil) then O.AutoSwitchTemplate = true; end
+ if (O.AutoSwitchTemplateInst == nil) then O.AutoSwitchTemplateInst = true; end
+ if (O.InShapeshift == nil) then O.InShapeshift = true; end
+
+ if (O.ToggleGrp == nil) then O.ToggleGrp = {true, false, false, false, false, false, false, false}; end
+ if (O.ToggleSubGrpChanged == nil) then O.ToggleSubGrpChanged = false; end
+
+ if (O.ToggleMsgNormal == nil) then O.ToggleMsgNormal = true; end
+ if (O.ToggleMsgWarning == nil) then O.ToggleMsgWarning = false; end
+ if (O.ToggleMsgError == nil) then O.ToggleMsgError = false; end
+
+ if (O.HideMmButton == nil) then O.HideMmButton = false; end
+ if (O.HideSAButton == nil) then O.HideSAButton = false; end
+
+ if (O.MinCharges == nil) then
+ if (sPlayerClass == "SHAMAN" or sPlayerClass == "PRIEST") then
+ O.MinCharges = 1;
+ else
+ O.MinCharges = 3;
+ end
+ end
+
+ if (O.ShowMiniGrp == nil) then
+ if (sPlayerClass == "DRUID" or sPlayerClass == "MAGE" or sPlayerClass == "PRIEST") then
+ O.ShowMiniGrp = true;
+ else
+ O.ShowMiniGrp = false;
+ end
+ end
+
+ if (not O.AddList) then O.AddList = { }; end
+ if (not O.IgnoreList) then O.IgnoreList = { }; end
+
+ if (O.LastTemplate == nil) then O.LastTemplate = SMARTBUFF_TEMPLATES[1]; end
+ local b = false;
+ while (SMARTBUFF_TEMPLATES[i] ~= nil) do
+ if (SMARTBUFF_TEMPLATES[i] == O.LastTemplate) then
+ b = true;
+ break;
+ end
+ i = i + 1;
+ end
+ if (not b) then
+ O.LastTemplate = SMARTBUFF_TEMPLATES[1];
+ end
+
+ currentTemplate = O.LastTemplate;
+ --currentSpec = GetSpecialization();
+ currentSpec = 1;
+
+ if (O.OldWheelUp == nil) then O.OldWheelUp = ""; end
+ if (O.OldWheelDown == nil) then O.OldWheelDown = ""; end
+
+ SMARTBUFF_InitActionButtonPos();
+
+ if (O.SplashX == nil) then O.SplashX = 100; end
+ if (O.SplashY == nil) then O.SplashY = -100; end
+ if (O.CurrentFont == nil) then O.CurrentFont = 9; end
+ if (O.ColSplashFont == nil) then
+ O.ColSplashFont = { };
+ O.ColSplashFont.r = 1.0;
+ O.ColSplashFont.g = 1.0;
+ O.ColSplashFont.b = 1.0;
+ end
+ iCurrentFont = O.CurrentFont;
+
+ if (O.Debug == nil) then O.Debug = false; end
+
+ -- Cosmos support
+ if(EarthFeature_AddButton) then
+ EarthFeature_AddButton(
+ { id = SMARTBUFF_TITLE;
+ name = SMARTBUFF_TITLE;
+ subtext = SMARTBUFF_TITLE;
+ tooltip = "";
+ icon = imgSB;
+ callback = SMARTBUFF_OptionsFrame_Toggle;
+ test = nil;
+ } )
+ elseif (Cosmos_RegisterButton) then
+ Cosmos_RegisterButton(SMARTBUFF_TITLE, SMARTBUFF_TITLE, SMARTBUFF_TITLE, imgSB, SMARTBUFF_OptionsFrame_Toggle);
+ end
+
+ if (IsAddOnLoaded("Parrot")) then
+ isParrot = true;
+ end
+
+ SMARTBUFF_FindItem("ScanBagsForSBInit");
+
+ SMARTBUFF_AddMsg(SMARTBUFF_VERS_TITLE .. " " .. SMARTBUFF_MSG_LOADED, true);
+ SMARTBUFF_AddMsg("/sbm - " .. SMARTBUFF_OFT_MENU, true);
+ isInit = true;
+
+ SMARTBUFF_CheckMiniMapButton();
+ SMARTBUFF_MinimapButton_OnUpdate(SmartBuff_MiniMapButton);
+ SMARTBUFF_ShowSAButton();
+ SMARTBUFF_Splash_Hide();
+
+ if (O.UpgradeToDualSpec == nil) then
+ for n = 1, GetNumSpecGroups(), 1 do
+ if (B[n] == nil) then
+ B[n] = { };
+ end
+ for k, v in pairs(SMARTBUFF_TEMPLATES) do
+ SMARTBUFF_AddMsgD(v);
+ if (B[v] ~= nil) then
+ B[n][v] = B[v];
+ end
+ end
+ end
+ for k, v in pairs(SMARTBUFF_TEMPLATES) do
+ if (B[v] ~= nil) then
+ wipe(B[v]);
+ B[v] = nil;
+ end
+ end
+ O.UpgradeToDualSpec = true;
+ SMARTBUFF_AddMsg("Upgraded to dual spec", true);
+ end
+
+ for k, v in pairs(cClasses) do
+ if (SMARTBUFF_CLASSES[k] == nil) then
+ SMARTBUFF_CLASSES[k] = v;
+ end
+ end
+
+ if (O.VersionNr == nil or O.VersionNr < SMARTBUFF_VERSIONNR) then
+ O.VersionNr = SMARTBUFF_VERSIONNR;
+ SMARTBUFF_SetBuffs();
+ InitBuffOrder(true);
+ --print("Upgrade SmartBuff to "..SMARTBUFF_VERSION);
+ end
+
+ if (SMARTBUFF_OptionsGlobal == nil) then SMARTBUFF_OptionsGlobal = { }; end
+ OG = SMARTBUFF_OptionsGlobal;
+ if (OG.SplashIcon == nil) then OG.SplashIcon = true; end
+ if (OG.SplashMsgShort == nil) then OG.SplashMsgShort = false; end
+ if (OG.FirstStart == nil) then OG.FirstStart = "V0"; end
+
+ SMARTBUFF_Splash_ChangeFont(0);
+ if (OG.FirstStart ~= SMARTBUFF_VERSION) then
+ OG.FirstStart = SMARTBUFF_VERSION;
+ SMARTBUFF_OptionsFrame_Open(true);
+
+ if (OG.Tutorial == nil) then
+ OG.Tutorial = SMARTBUFF_VERSIONNR;
+ SMARTBUFF_ToggleTutorial();
+ end
+
+ SmartBuffWNF_lblText:SetText(SMARTBUFF_WHATSNEW);
+ SmartBuffWNF:Show();
+ else
+ SMARTBUFF_SetBuffs();
+ end
+
+ if (not IsVisibleToPlayer(SmartBuff_KeyButton)) then
+ SmartBuff_KeyButton:ClearAllPoints();
+ SmartBuff_KeyButton:SetPoint("CENTER", UIParent, "CENTER", 0, 100);
+ end
+
+ SMARTBUFF_SetUnits();
+ SMARTBUFF_RebindKeys();
+ isSyncReq = true;
+
+ -- finally, client version check
+ if buildInfo > SMARTBUFF_VERSIONNR or buildInfo < SMARTBUFF_VERSIONMIN then
+ DEFAULT_CHAT_FRAME:AddMessage("|cff00e0ffSmartbuff : |cffff6060This version was NOT intended for client version ("..buildInfo..") - you may encounter lua errors or other issues so please check for an update! - Join Discord for all the latest information at |cffFFFF00https://discord.gg/R6EkZ94TKK.")
+ end
+
+end
+-- END SMARTBUFF_Options_Init
+
+function SMARTBUFF_InitActionButtonPos()
+ if (InCombatLockdown()) then return end
+
+ isInitBtn = true;
+ if (O.ActionBtnX == nil) then
+ SMARTBUFF_SetButtonPos(SmartBuff_KeyButton);
+ else
+ SmartBuff_KeyButton:ClearAllPoints();
+ SmartBuff_KeyButton:SetPoint("TOPLEFT", UIParent, "TOPLEFT", O.ActionBtnX, O.ActionBtnY);
+ end
+ --print(format("x = %.0f, y = %.0f", O.ActionBtnX, O.ActionBtnY));
+end
+
+function SMARTBUFF_ResetAll()
+ wipe(SMARTBUFF_Buffs);
+ wipe(SMARTBUFF_Options);
+ ReloadUI();
+end
+
+function SMARTBUFF_SetButtonPos(self)
+ local x, y = self:GetLeft(), self:GetTop() - UIParent:GetHeight();
+ O.ActionBtnX = x;
+ O.ActionBtnY = y;
+ --print(format("x = %.0f, y = %.0f", x, y));
+end
+
+function SMARTBUFF_RebindKeys()
+ local i;
+ isRebinding = true;
+ for i = 1, GetNumBindings(), 1 do
+ local s = "";
+ local command, key1, key2 = GetBinding(i);
+
+ --if (command and key1) then
+ -- SMARTBUFF_AddMsgD(i .. " = " .. command .. " - " .. key1;
+ --end
+
+ if (key1 and key1 == "MOUSEWHEELUP" and command ~= "SmartBuff_KeyButton") then
+ O.OldWheelUp = command;
+ --SMARTBUFF_AddMsgD("Old wheel up: " .. command);
+ elseif (key1 and key1 == "MOUSEWHEELDOWN" and command ~= "SmartBuff_KeyButton") then
+ O.OldWheelDown = command;
+ --SMARTBUFF_AddMsgD("Old wheel down: " .. command);
+ end
+
+ if (command and command == "SMARTBUFF_BIND_TRIGGER") then
+ --s = i .. " = " .. command;
+ if (key1) then
+ --s = s .. ", key1 = " .. key1 .. " rebound";
+ SetBindingClick(key1, "SmartBuff_KeyButton");
+ end
+ if (key2) then
+ --s = s .. ", key2 = " .. key2 .. " rebound";
+ SetBindingClick(key2, "SmartBuff_KeyButton");
+ end
+ --SMARTBUFF_AddMsgD(s);
+ break;
+ end
+ end
+
+ if (O.ScrollWheelUp) then
+ isKeyUpChanged = true;
+ SetOverrideBindingClick(SmartBuffFrame, false, "MOUSEWHEELUP", "SmartBuff_KeyButton", "MOUSEWHEELUP");
+ --SMARTBUFF_AddMsgD("Set wheel up");
+ else
+ if (isKeyUpChanged) then
+ isKeyUpChanged = false;
+ SetOverrideBinding(SmartBuffFrame, false, "MOUSEWHEELUP");
+ --SMARTBUFF_AddMsgD("Set old wheel up: " .. O.OldWheelUp);
+ end
+ end
+
+ if (O.ScrollWheelDown) then
+ isKeyDownChanged = true;
+ SetOverrideBindingClick(SmartBuffFrame, false, "MOUSEWHEELDOWN", "SmartBuff_KeyButton", "MOUSEWHEELDOWN");
+ --SMARTBUFF_AddMsgD("Set wheel down");
+ else
+ if (isKeyDownChanged) then
+ isKeyDownChanged = false;
+ SetOverrideBinding(SmartBuffFrame, false, "MOUSEWHEELDOWN");
+ --SMARTBUFF_AddMsgD("Set old wheel down: " .. O.OldWheelDown);
+ end
+ end
+ isRebinding = false;
+end
+
+function SMARTBUFF_ResetBindings()
+ if (not isRebinding) then
+ isRebinding = true;
+ if (O.OldWheelUp == "SmartBuff_KeyButton") then
+ SetBinding("MOUSEWHEELUP", "CAMERAZOOMIN");
+ else
+ SetBinding("MOUSEWHEELUP", O.OldWheelUp);
+ end
+ if (O.OldWheelDown == "SmartBuff_KeyButton") then
+ SetBinding("MOUSEWHEELDOWN", "CAMERAZOOMOUT");
+ else
+ SetBinding("MOUSEWHEELDOWN", O.OldWheelDown);
+ end
+ SaveBindings(GetCurrentBindingSet());
+ SMARTBUFF_RebindKeys();
+ end
+end
+
+
+-- SmartBuff commandline menu ---------------------------------------------------------------------------------------
+function SMARTBUFF_command(msg)
+ if (not isInit) then
+ SMARTBUFF_AddMsgWarn(SMARTBUFF_VERS_TITLE.." not initialized correctly!", true);
+ return;
+ end
+
+ if(msg == "toggle" or msg == "t") then
+ SMARTBUFF_OToggle();
+ SMARTBUFF_SetUnits();
+ elseif (msg == "menu") then
+ SMARTBUFF_OptionsFrame_Toggle();
+ elseif (msg == "rbt") then
+ SMARTBUFF_ResetBuffTimers();
+ elseif (msg == "sbt") then
+ SMARTBUFF_ShowBuffTimers();
+ elseif (msg == "target") then
+ if (SMARTBUFF_PreCheck(0)) then
+ SMARTBUFF_checkBlacklist();
+ SMARTBUFF_BuffUnit("target", 0, 0);
+ end
+ elseif (msg == "debug") then
+ O.Debug = SMARTBUFF_toggleBool(O.Debug, "Debug active = ");
+ elseif (msg == "open") then
+ SMARTBUFF_OptionsFrame_Open(true);
+ elseif (msg == "sync") then
+ SMARTBUFF_SyncBuffTimers();
+ elseif (msg == "rb") then
+ SMARTBUFF_ResetBindings();
+ SMARTBUFF_AddMsg("SmartBuff key and mouse bindings reset.", true);
+ elseif (msg == "rafp") then
+ SmartBuffSplashFrame:ClearAllPoints();
+ SmartBuffSplashFrame:SetPoint("CENTER", UIParent, "CENTER");
+ SmartBuff_MiniMapButton:ClearAllPoints();
+ SmartBuff_MiniMapButton:SetPoint("TOPLEFT", Minimap, "TOPLEFT");
+ SmartBuff_KeyButton:ClearAllPoints();
+ SmartBuff_KeyButton:SetPoint("CENTER", UIParent, "CENTER");
+ SmartBuffOptionsFrame:ClearAllPoints();
+ SmartBuffOptionsFrame:SetPoint("CENTER", UIParent, "CENTER");
+ SmartBuff_MiniGroup:ClearAllPoints();
+ SmartBuff_MiniGroup:SetPoint("CENTER", UIParent, "CENTER");
+ elseif (msg == "tmg") then
+ --SMARTBUFF_OToggleMiniGrp();
+ O.ShowMiniGrp = SMARTBUFF_toggleBool(O.ShowMiniGrp, "MiniGrp active = ");
+ SMARTBUFF_MiniGroup_Show();
+
+ elseif (msg == "test") then
+
+ -- Test Code ******************************************
+ -- ****************************************************
+
+ --SMARTBUFF_WEAPON_SHARP_PATTERN
+ --Schwerer Gewichtsstein
+ --Schwerer Wetzstein
+ --local a, b = SMARTBUFF_CanApplyWeaponBuff("Schwerer Wetzstein", 16);
+ --print(a);
+ --print(b);
+
+ --local spellname = "Mind--numbing Poison";
+ --SMARTBUFF_AddMsg("Original: " .. spellname, true);
+ --if (string.find(spellname, "%-%-") ~= nil) then
+ -- spellname = string.gsub(spellname, "%-%-", "%-");
+ --end
+ --SMARTBUFF_AddMsg("Modified: " .. spellname, true);
+ -- ****************************************************
+ -- ****************************************************
+
+ else
+ --SMARTBUFF_Check(0);
+ SMARTBUFF_AddMsg(SMARTBUFF_VERS_TITLE, true);
+ SMARTBUFF_AddMsg("Syntax: /sbo [command] or /sbuff [command] or /smartbuff [command]", true);
+ SMARTBUFF_AddMsg("toggle - " .. SMARTBUFF_OFT, true);
+ SMARTBUFF_AddMsg("menu - " .. SMARTBUFF_OFT_MENU, true);
+ SMARTBUFF_AddMsg("target - " .. SMARTBUFF_OFT_TARGET, true);
+ SMARTBUFF_AddMsg("rbt - " .. "Reset buff timers", true);
+ SMARTBUFF_AddMsg("sbt - " .. "Show buff timers", true);
+ SMARTBUFF_AddMsg("rafp - " .. "Reset all frame positions", true);
+ SMARTBUFF_AddMsg("sync - " .. "Sync buff timers with UI", true);
+ SMARTBUFF_AddMsg("rb - " .. "Reset key/mouse bindings", true);
+ end
+end
+-- END SMARTBUFF_command
+
+
+-- SmartBuff options toggle ---------------------------------------------------------------------------------------
+function SMARTBUFF_OToggle()
+ if (not isInit) then return; end
+ O.Toggle = SMARTBUFF_toggleBool(O.Toggle, "Active = ");
+ SMARTBUFF_CheckMiniMapButton();
+ if (O.Toggle) then
+ SMARTBUFF_MiniGroup_Show();
+ SMARTBUFF_SetUnits();
+ else
+ if (SmartBuff_MiniGroup:IsVisible()) then
+ SmartBuff_MiniGroup:Hide();
+ end
+ end
+end
+
+function SMARTBUFF_OToggleAuto()
+ O.ToggleAuto = not O.ToggleAuto;
+end
+function SMARTBUFF_OToggleAutoCombat()
+ O.ToggleAutoCombat = not O.ToggleAutoCombat;
+end
+function SMARTBUFF_OToggleAutoChat()
+ O.ToggleAutoChat = not O.ToggleAutoChat;
+end
+function SMARTBUFF_OToggleAutoSplash()
+ O.ToggleAutoSplash = not O.ToggleAutoSplash;
+end
+function SMARTBUFF_OToggleAutoSound()
+ O.ToggleAutoSound = not O.ToggleAutoSound;
+end
+
+--function SMARTBUFF_OToggleCheckCharges()
+-- O.ToggleCheckCharges = not O.ToggleCheckCharges;
+--end
+--function SMARTBUFF_OToggleAutoRest()
+-- O.ToggleAutoRest = not O.ToggleAutoRest;
+--end
+
+function SMARTBUFF_OAutoSwitchTmp()
+ O.AutoSwitchTemplate = not O.AutoSwitchTemplate;
+end
+function SMARTBUFF_OAutoSwitchTmpInst()
+ O.AutoSwitchTemplateInst = not O.AutoSwitchTemplateInst;
+end
+
+function SMARTBUFF_OBuffTarget()
+ O.BuffTarget = not O.BuffTarget;
+end
+
+function SMARTBUFF_OBuffPvP()
+ O.BuffPvP = not O.BuffPvP;
+end
+
+function SMARTBUFF_OBuffInCities()
+ O.BuffInCities = not O.BuffInCities;
+end
+
+function SMARTBUFF_OLinkSelfBuffCheck()
+ O.LinkSelfBuffCheck = not O.LinkSelfBuffCheck;
+end
+function SMARTBUFF_OLinkGrpBuffCheck()
+ O.LinkGrpBuffCheck = not O.LinkGrpBuffCheck;
+end
+function SMARTBUFF_OAntiDaze()
+ O.AntiDaze = not O.AntiDaze;
+end
+
+function SMARTBUFF_OScrollWheelUp()
+ O.ScrollWheelUp = not O.ScrollWheelUp;
+ isKeyUpChanged = true;
+end
+function SMARTBUFF_OScrollWheelDown()
+ O.ScrollWheelDown = not O.ScrollWheelDown;
+ isKeyDownChanged = true;
+end
+function SMARTBUFF_OInShapeshift()
+ O.InShapeshift = not O.InShapeshift;
+end
+function SMARTBUFF_OInCombat()
+ O.InCombat = not O.InCombat;
+end
+
+function SMARTBUFF_OToggleGrp(i)
+ O.ToggleGrp[i] = not O.ToggleGrp[i];
+ if (SmartBuff_MiniGroup:IsVisible()) then
+ SMARTBUFF_SetUnits();
+ end
+end
+function SMARTBUFF_OToggleMiniGrp()
+ O.ShowMiniGrp = not O.ShowMiniGrp;
+end
+function SMARTBUFF_OToggleSubGrpChanged()
+ O.ToggleSubGrpChanged = not O.ToggleSubGrpChanged;
+end
+
+function SMARTBUFF_OToggleMsgNormal()
+ O.ToggleMsgNormal = not O.ToggleMsgNormal;
+end
+function SMARTBUFF_OToggleMsgWarning()
+ O.ToggleMsgWarning = not O.ToggleMsgWarning;
+end
+function SMARTBUFF_OToggleMsgError()
+ O.ToggleMsgError = not O.ToggleMsgError;
+end
+
+function SMARTBUFF_OHideMmButton()
+ O.HideMmButton = not O.HideMmButton;
+ SMARTBUFF_CheckMiniMapButton();
+end
+function SMARTBUFF_OHideSAButton()
+ O.HideSAButton = not O.HideSAButton;
+ SMARTBUFF_ShowSAButton();
+end
+
+function SMARTBUFF_OToggleBuff(s, i)
+ local bs = GetBuffSettings(cBuffs[i].BuffS);
+ if (bs == nil) then
+ return;
+ end
+
+ if (s == "S") then
+ bs.EnableS = not bs.EnableS;
+ if (bs.IDG ~= nil) then
+ bs.EnableG = bs.EnableS;
+ else
+ bs.EnableG = false;
+ end
+ SMARTBUFF_AddMsgD("OToggleBuff = "..cBuffs[i].BuffS..", "..tostring(bs.EnableS)..", "..tostring(bs.EnableG));
+
+ if (bs.EnableS) then
+ SmartBuff_BuffSetup_Show(i);
+ else
+ SmartBuff_BuffSetup:Hide();
+ iLastBuffSetup = -1;
+ SmartBuff_PlayerSetup:Hide();
+ end
+ elseif (s == "G") then
+ bs.EnableG = not bs.EnableG;
+ end
+
+end
+
+function SMARTBUFF_OToggleDebug()
+ O.Debug = not O.Debug;
+end
+
+function SMARTBUFF_OptionsFrame_Toggle()
+ if (not isInit) then return; end
+
+ if(SmartBuffOptionsFrame:IsVisible()) then
+ if(iLastBuffSetup > 0) then
+ SmartBuff_BuffSetup:Hide();
+ iLastBuffSetup = -1;
+ SmartBuff_PlayerSetup:Hide();
+ end
+ SmartBuffOptionsFrame:Hide();
+ else
+ SmartBuffOptionsCredits_lblText:SetText(SMARTBUFF_CREDITS);
+ SmartBuffOptionsFrame:Show();
+ SmartBuff_PlayerSetup:Hide();
+ end
+
+ SMARTBUFF_MinimapButton_CheckPos();
+end
+
+function SMARTBUFF_OptionsFrame_Open(force)
+ if (not isInit) then return; end
+ if(not SmartBuffOptionsFrame:IsVisible() or force) then
+ SmartBuffOptionsCredits_lblText:SetText(SMARTBUFF_CREDITS);
+ SmartBuffOptionsFrame:Show();
+ end
+end
+
+function SmartBuff_BuffSetup_Show(i)
+ local icon1 = cBuffs[i].IconS;
+ local icon2 = cBuffs[i].IconG;
+ local name = cBuffs[i].BuffS;
+ local btype = cBuffs[i].Type;
+ local hidden = true;
+ local n = 0;
+ local bs = GetBuffSettings(name);
+
+ if (name == nil or btype == SMARTBUFF_CONST_TRACK) then
+ SmartBuff_BuffSetup:Hide();
+ iLastBuffSetup = -1;
+ SmartBuff_PlayerSetup:Hide();
+ return;
+ end
+
+ if(SmartBuff_BuffSetup:IsVisible() and i == iLastBuffSetup) then
+ SmartBuff_BuffSetup:Hide();
+ iLastBuffSetup = -1;
+ SmartBuff_PlayerSetup:Hide();
+ return;
+ else
+ if (btype == SMARTBUFF_CONST_GROUP or btype == SMARTBUFF_CONST_ITEMGROUP) then
+ hidden = false;
+ end
+
+ if (icon2 and bs.EnableG) then
+ SmartBuff_BuffSetup_BuffIcon2:SetNormalTexture(icon2);
+ SmartBuff_BuffSetup_BuffIcon2:Show();
+ else
+ SmartBuff_BuffSetup_BuffIcon2:Hide();
+ end
+ if (icon1) then
+ SmartBuff_BuffSetup_BuffIcon1:SetNormalTexture(icon1);
+ if (icon2 and bs.EnableG) then
+ SmartBuff_BuffSetup_BuffIcon1:SetPoint("TOPLEFT", 44, -30);
+ else
+ SmartBuff_BuffSetup_BuffIcon1:SetPoint("TOPLEFT", 64, -30);
+ end
+ SmartBuff_BuffSetup_BuffIcon1:Show();
+ else
+ SmartBuff_BuffSetup_BuffIcon1:SetPoint("TOPLEFT", 24, -30);
+ SmartBuff_BuffSetup_BuffIcon1:Hide();
+ end
+
+ local obj = SmartBuff_BuffSetup_BuffText;
+ if (name) then
+ obj:SetText(name);
+ --SMARTBUFF_AddMsgD(name);
+ else
+ obj:SetText("");
+ end
+
+ SmartBuff_BuffSetup_cbSelf:SetChecked(bs.SelfOnly);
+ SmartBuff_BuffSetup_cbSelfNot:SetChecked(bs.SelfNot);
+ SmartBuff_BuffSetup_cbCombatIn:SetChecked(bs.CIn);
+ SmartBuff_BuffSetup_cbCombatOut:SetChecked(bs.COut);
+ SmartBuff_BuffSetup_cbMH:SetChecked(bs.MH);
+ SmartBuff_BuffSetup_cbOH:SetChecked(bs.OH);
+ SmartBuff_BuffSetup_cbRH:SetChecked(bs.RH);
+ SmartBuff_BuffSetup_cbReminder:SetChecked(bs.Reminder);
+ SmartBuff_BuffSetup_txtManaLimit:SetNumber(bs.ManaLimit);
+
+ --SMARTBUFF_AddMsgD("Test Buff setup show 1");
+ if (cBuffs[i].DurationS > 0) then
+ SmartBuff_BuffSetup_RBTime:SetMinMaxValues(0, cBuffs[i].DurationS);
+ _G[SmartBuff_BuffSetup_RBTime:GetName().."High"]:SetText(cBuffs[i].DurationS);
+ if (cBuffs[i].DurationS <= 60) then
+ SmartBuff_BuffSetup_RBTime:SetValueStep(1);
+ elseif (cBuffs[i].DurationS <= 180) then
+ SmartBuff_BuffSetup_RBTime:SetValueStep(5);
+ elseif (cBuffs[i].DurationS <= 600) then
+ SmartBuff_BuffSetup_RBTime:SetValueStep(10);
+ else
+ SmartBuff_BuffSetup_RBTime:SetValueStep(30);
+ end
+ SmartBuff_BuffSetup_RBTime:SetValue(bs.RBTime);
+ _G[SmartBuff_BuffSetup_RBTime:GetName().."Text"]:SetText(bs.RBTime .. "\nsec");
+ SmartBuff_BuffSetup_RBTime:Show();
+ else
+ SmartBuff_BuffSetup_RBTime:Hide();
+ end
+ --SMARTBUFF_AddMsgD("Test Buff setup show 2");
+
+ SmartBuff_BuffSetup_txtManaLimit:Hide();
+ if (cBuffs[i].Type == SMARTBUFF_CONST_INV or cBuffs[i].Type == SMARTBUFF_CONST_WEAPON) then
+ SmartBuff_BuffSetup_cbMH:Show();
+ SmartBuff_BuffSetup_cbOH:Show();
+ SmartBuff_BuffSetup_cbRH:Hide();
+ else
+ SmartBuff_BuffSetup_cbMH:Hide();
+ SmartBuff_BuffSetup_cbOH:Hide();
+ SmartBuff_BuffSetup_cbRH:Hide();
+ if (cBuffs[i].Type ~= SMARTBUFF_CONST_FOOD and cBuffs[i].Type ~= SMARTBUFF_CONST_SCROLL and cBuffs[i].Type ~= SMARTBUFF_CONST_POTION) then
+ SmartBuff_BuffSetup_txtManaLimit:Show();
+ --SMARTBUFF_AddMsgD("Show ManaLimit");
+ end
+ end
+
+ if (cBuffs[i].Type == SMARTBUFF_CONST_GROUP or cBuffs[i].Type == SMARTBUFF_CONST_ITEMGROUP) then
+ SmartBuff_BuffSetup_cbSelf:Show();
+ SmartBuff_BuffSetup_cbSelfNot:Show();
+ SmartBuff_BuffSetup_btnPriorityList:Show();
+ SmartBuff_BuffSetup_btnIgnoreList:Show();
+ else
+ SmartBuff_BuffSetup_cbSelf:Hide();
+ SmartBuff_BuffSetup_cbSelfNot:Hide();
+ SmartBuff_BuffSetup_btnPriorityList:Hide();
+ SmartBuff_BuffSetup_btnIgnoreList:Hide();
+ SmartBuff_PlayerSetup:Hide();
+ end
+
+ local cb = nil;
+ local btn = nil;
+ n = 0;
+ --SMARTBUFF_AddMsgD("Test Buff setup show 3");
+ for _ in pairs(cClasses) do
+ n = n + 1;
+ cb = _G["SmartBuff_BuffSetup_cbClass"..n];
+ btn = _G["SmartBuff_BuffSetup_ClassIcon"..n];
+ if (hidden or tcontains(cIgnoreClasses, n)) then
+ cb:Hide();
+ btn:Hide();
+ else
+ cb:SetChecked(bs[cClasses[n]]);
+ cb:Show();
+ btn:Show();
+ end
+ end
+ iLastBuffSetup = i;
+ --SMARTBUFF_AddMsgD("Test Buff setup show 4");
+ SmartBuff_BuffSetup:Show();
+
+ if (SmartBuff_PlayerSetup:IsVisible()) then
+ SmartBuff_PS_Show(iCurrentList);
+ end
+ end
+end
+
+function SmartBuff_BuffSetup_ManaLimitChanged(self)
+ local i = iLastBuffSetup;
+ if (i <= 0) then
+ return;
+ end
+ local ct = currentTemplate;
+ local name = cBuffs[i].BuffS;
+ B[CS()][ct][name].ManaLimit = self:GetNumber();
+end
+
+function SmartBuff_BuffSetup_OnClick()
+ local i = iLastBuffSetup;
+ local ct = currentTemplate;
+ if (i <= 0) then
+ return;
+ end
+ local name = cBuffs[i].BuffS;
+ local cBuff = GetBuffSettings(name);
+
+ cBuff.SelfOnly = SmartBuff_BuffSetup_cbSelf:GetChecked();
+ cBuff.SelfNot = SmartBuff_BuffSetup_cbSelfNot:GetChecked();
+ cBuff.CIn = SmartBuff_BuffSetup_cbCombatIn:GetChecked();
+ cBuff.COut = SmartBuff_BuffSetup_cbCombatOut:GetChecked();
+ cBuff.MH = SmartBuff_BuffSetup_cbMH:GetChecked();
+ cBuff.OH = SmartBuff_BuffSetup_cbOH:GetChecked();
+ cBuff.RH = SmartBuff_BuffSetup_cbRH:GetChecked();
+ cBuff.Reminder = SmartBuff_BuffSetup_cbReminder:GetChecked();
+
+ cBuff.RBTime = SmartBuff_BuffSetup_RBTime:GetValue();
+ _G[SmartBuff_BuffSetup_RBTime:GetName().."Text"]:SetText(cBuff.RBTime .. "\nsec");
+
+ if (cBuffs[i].Type == SMARTBUFF_CONST_GROUP or cBuffs[i].Type == SMARTBUFF_CONST_ITEMGROUP) then
+ local n = 0;
+ local cb = nil;
+ for _ in pairs(cClasses) do
+ n = n + 1;
+ cb = _G["SmartBuff_BuffSetup_cbClass"..n];
+ if (tcontains(cIgnoreClasses, n)) then
+ cBuff[cClasses[n]] = false;
+ else
+ cBuff[cClasses[n]] = cb:GetChecked();
+ end
+ end
+ end
+ --SMARTBUFF_AddMsgD("Buff setup saved");
+end
+
+function SmartBuff_BuffSetup_ToolTip(mode)
+ local i = iLastBuffSetup;
+ if (i <= 0) then
+ return;
+ end
+ local ids = cBuffs[i].IDS;
+ local idg = cBuffs[i].IDG;
+ local btype = cBuffs[i].Type
+
+ GameTooltip:ClearLines();
+ if (SMARTBUFF_IsItem(btype)) then
+ local bag, slot, count, texture = SMARTBUFF_FindItem(cBuffs[i].BuffS, cBuffs[i].Chain);
+ if (bag and slot) then
+ if (bag == 999) then -- Toy
+ GameTooltip:SetToyByItemID(slot);
+ else
+ GameTooltip:SetBagItem(bag, slot);
+ end
+ end
+ else
+ if (mode == 1 and ids) then
+ GameTooltip:SetHyperlink("spell:" .. ids);
+ elseif (mode == 2 and idg) then
+ GameTooltip:SetHyperlink("spell:" .. idg);
+ end
+ end
+ GameTooltip:Show();
+end
+-- END SmartBuff options toggle
+
+
+-- Options frame functions ---------------------------------------------------------------------------------------
+function SMARTBUFF_Options_OnLoad(self)
+end
+
+function SMARTBUFF_Options_OnShow()
+ -- Check if the options frame is out of screen area
+ local top = GetScreenHeight() - math.abs(SmartBuffOptionsFrame:GetTop());
+ local bottom = GetScreenHeight() - math.abs(SmartBuffOptionsFrame:GetBottom());
+ local left = SmartBuffOptionsFrame:GetLeft();
+ local right = SmartBuffOptionsFrame:GetRight();
+
+ --SMARTBUFF_AddMsgD("X: " .. GetScreenWidth() .. ", " .. left .. ", " .. right);
+ --SMARTBUFF_AddMsgD("Y: " .. GetScreenHeight() .. ", " .. top .. ", " .. bottom);
+
+ if (GetScreenWidth() < left + 20 or GetScreenHeight() < top + 20 or right < 20 or bottom < 20) then
+ SmartBuffOptionsFrame:SetPoint("TOPLEFT", UIParent, "CENTER", -SmartBuffOptionsFrame:GetWidth() / 2, SmartBuffOptionsFrame:GetHeight() / 2);
+ end
+
+ SmartBuff_ShowControls("SmartBuffOptionsFrame", true);
+
+ SmartBuffOptionsFrame_cbSB:SetChecked(O.Toggle);
+ SmartBuffOptionsFrame_cbAuto:SetChecked(O.ToggleAuto);
+ SmartBuffOptionsFrameAutoTimer:SetValue(O.AutoTimer);
+ SmartBuff_SetSliderText(SmartBuffOptionsFrameAutoTimer, SMARTBUFF_OFT_AUTOTIMER, O.AutoTimer, INT_SPELL_DURATION_SEC);
+ SmartBuffOptionsFrame_cbAutoCombat:SetChecked(O.ToggleAutoCombat);
+ SmartBuffOptionsFrame_cbAutoChat:SetChecked(O.ToggleAutoChat);
+ SmartBuffOptionsFrame_cbAutoSplash:SetChecked(O.ToggleAutoSplash);
+ SmartBuffOptionsFrame_cbAutoSound:SetChecked(O.ToggleAutoSound);
+ --SmartBuffOptionsFrame_cbCheckCharges:SetChecked(O.ToggleCheckCharges);
+ --SmartBuffOptionsFrame_cbAutoRest:SetChecked(O.ToggleAutoRest);
+ SmartBuffOptionsFrame_cbAutoSwitchTmp:SetChecked(O.AutoSwitchTemplate);
+ SmartBuffOptionsFrame_cbAutoSwitchTmpInst:SetChecked(O.AutoSwitchTemplateInst);
+ SmartBuffOptionsFrame_cbBuffPvP:SetChecked(O.BuffPvP);
+ SmartBuffOptionsFrame_cbBuffTarget:SetChecked(O.BuffTarget);
+ SmartBuffOptionsFrame_cbBuffInCities:SetChecked(O.BuffInCities);
+ SmartBuffOptionsFrame_cbInShapeshift:SetChecked(O.InShapeshift);
+
+ SmartBuffOptionsFrame_cbAntiDaze:SetChecked(O.AntiDaze);
+ SmartBuffOptionsFrame_cbLinkGrpBuffCheck:SetChecked(O.LinkGrpBuffCheck);
+ SmartBuffOptionsFrame_cbLinkSelfBuffCheck:SetChecked(O.LinkSelfBuffCheck);
+
+ SmartBuffOptionsFrame_cbScrollWheelUp:SetChecked(O.ScrollWheelUp);
+ SmartBuffOptionsFrame_cbScrollWheelDown:SetChecked(O.ScrollWheelDown);
+ SmartBuffOptionsFrame_cbInCombat:SetChecked(O.InCombat);
+ SmartBuffOptionsFrame_cbMsgNormal:SetChecked(O.ToggleMsgNormal);
+ SmartBuffOptionsFrame_cbMsgWarning:SetChecked(O.ToggleMsgWarning);
+ SmartBuffOptionsFrame_cbMsgError:SetChecked(O.ToggleMsgError);
+ SmartBuffOptionsFrame_cbHideMmButton:SetChecked(O.HideMmButton);
+ SmartBuffOptionsFrame_cbHideSAButton:SetChecked(O.HideSAButton);
+
+ SmartBuffOptionsFrameRebuffTimer:SetValue(O.RebuffTimer);
+ SmartBuff_SetSliderText(SmartBuffOptionsFrameRebuffTimer, SMARTBUFF_OFT_REBUFFTIMER, O.RebuffTimer, INT_SPELL_DURATION_SEC);
+ SmartBuffOptionsFrameBLDuration:SetValue(O.BlacklistTimer);
+ SmartBuff_SetSliderText(SmartBuffOptionsFrameBLDuration, SMARTBUFF_OFT_BLDURATION, O.BlacklistTimer, INT_SPELL_DURATION_SEC);
+
+ SMARTBUFF_ShowSubGroupsOptions();
+ SMARTBUFF_SetCheckButtonBuffs(0);
+
+ SMARTBUFF_Splash_Show();
+
+ SMARTBUFF_AddMsgD("Option frame updated: " .. currentTemplate);
+end
+
+function SMARTBUFF_ShowSubGroupsMini()
+ SMARTBUFF_ShowSubGroups("SmartBuff_MiniGroup", O.ToggleGrp);
+end
+
+function SMARTBUFF_ShowSubGroupsOptions()
+ SMARTBUFF_ShowSubGroups("SmartBuffOptionsFrame", O.ToggleGrp);
+end
+
+function SMARTBUFF_ShowSubGroups(frame, grpTable)
+ local i;
+ for i = 1, 8, 1 do
+ obj = _G[frame.."_cbGrp"..i];
+ if (obj) then
+ obj:SetChecked(grpTable[i]);
+ end
+ end
+end
+
+function SMARTBUFF_Options_OnHide()
+ if (SmartBuffWNF:IsVisible()) then
+ SmartBuffWNF:Hide();
+ end
+ SMARTBUFF_ToggleTutorial(true);
+ SmartBuffOptionsFrame:SetHeight(SMARTBUFF_OPTIONSFRAME_HEIGHT);
+ --SmartBuff_BuffSetup:SetHeight(SMARTBUFF_OPTIONSFRAME_HEIGHT);
+ wipe(cBuffsCombat);
+ SMARTBUFF_SetInCombatBuffs();
+ SmartBuff_BuffSetup:Hide();
+ SmartBuff_PlayerSetup:Hide();
+ SMARTBUFF_SetUnits();
+ SMARTBUFF_Splash_Hide();
+ SMARTBUFF_RebindKeys();
+ --collectgarbage();
+end
+
+function SmartBuff_ShowControls(sName, bShow)
+ local children = {_G[sName]:GetChildren()};
+ for i, child in pairs(children) do
+ --SMARTBUFF_AddMsgD(i .. ": " .. child:GetName());
+ if (i > 1 and string.find(child:GetName(), "^"..sName..".+")) then
+ if (bShow) then
+ child:Show();
+ else
+ child:Hide();
+ end
+ end
+ end
+end
+
+function SmartBuffOptionsFrameSlider_OnLoad(self, low, high, step, labels)
+ _G[self:GetName().."Text"]:SetFontObject(GameFontNormalSmall);
+ if (labels) then
+ if (self:GetOrientation() ~= "VERTICAL") then
+ _G[self:GetName().."Low"]:SetText(low);
+ else
+ _G[self:GetName().."Low"]:SetText("");
+ end
+ _G[self:GetName().."High"]:SetText(high);
+ else
+ _G[self:GetName().."Low"]:SetText("");
+ _G[self:GetName().."High"]:SetText("");
+ end
+ self:SetMinMaxValues(low, high);
+ self:SetValueStep(step);
+ self:SetStepsPerPage(step);
+
+ if (step < 1) then return; end
+
+ self.GetValueBase = self.GetValue;
+ self.GetValue = function()
+ local n = self:GetValueBase();
+ if (n) then
+ local r = Round(n);
+ if (r ~= n) then
+ self:SetValue(n);
+ end
+ return r;
+ end
+ return low;
+ end;
+end
+
+function SmartBuff_SetSliderText(self, text, value, valformat, setval)
+ if (not self or not value) then return end
+ local s;
+ if (setval) then self:SetValue(value) end
+ if (valformat) then
+ s = string.format(valformat, value);
+ else
+ s = tostring(value);
+ end
+ getglobal(self:GetName().."Text"):SetText(text.." "..WH..s.."|r");
+end
+
+function SmartBuff_BuffSetup_RBTime_OnValueChanged(self)
+ _G[SmartBuff_BuffSetup_RBTime:GetName().."Text"]:SetText(WH..format("%.0f", self:GetValue()).."\nsec|r");
+end
+
+function SMARTBUFF_SetCheckButtonBuffs(mode)
+ local objS;
+ local objG;
+ local i = 1;
+ local ct = currentTemplate;
+
+ if (mode == 0) then
+ SMARTBUFF_SetBuffs();
+ end
+
+ SmartBuffOptionsFrame_cbAntiDaze:Hide();
+
+ if (sPlayerClass == "HUNTER" or sPlayerClass == "ROGUE" or sPlayerClass == "WARRIOR") then
+ SmartBuffOptionsFrameBLDuration:Hide();
+ if (sPlayerClass == "HUNTER") then
+ SmartBuffOptionsFrame_cbLinkGrpBuffCheck:Hide();
+ SmartBuffOptionsFrame_cbAntiDaze:Show();
+ end
+ end
+
+ if (sPlayerClass == "DRUID" or sPlayerClass == "SHAMAN") then
+ SmartBuffOptionsFrame_cbInShapeshift:Show();
+ else
+ SmartBuffOptionsFrame_cbInShapeshift:Hide();
+ end
+
+ SMARTBUFF_BuffOrderOnScroll();
+end
+
+
+function SMARTBUFF_DropDownTemplate_OnShow(self)
+ local i = 0;
+ for _, tmp in pairs(SMARTBUFF_TEMPLATES) do
+ i = i + 1;
+ --SMARTBUFF_AddMsgD(i .. "." .. tmp);
+ if (tmp == currentTemplate) then
+ break;
+ end
+ end
+ UIDropDownMenu_Initialize(self, SMARTBUFF_DropDownTemplate_Initialize);
+ UIDropDownMenu_SetSelectedValue(SmartBuffOptionsFrame_ddTemplates, i);
+ UIDropDownMenu_SetWidth(SmartBuffOptionsFrame_ddTemplates, 135);
+end
+
+function SMARTBUFF_DropDownTemplate_Initialize()
+ local info = UIDropDownMenu_CreateInfo();
+ info.text = ALL;
+ info.value = -1;
+ info.func = SMARTBUFF_DropDownTemplate_OnClick;
+ for k, v in pairs(SMARTBUFF_TEMPLATES) do
+ info.text = SMARTBUFF_TEMPLATES[k];
+ info.value = k;
+ info.func = SMARTBUFF_DropDownTemplate_OnClick;
+ info.checked = nil;
+ UIDropDownMenu_AddButton(info);
+ end
+end
+
+function SMARTBUFF_DropDownTemplate_OnClick(self)
+ local i = self.value;
+ local tmp = nil;
+ UIDropDownMenu_SetSelectedValue(SmartBuffOptionsFrame_ddTemplates, i);
+ tmp = SMARTBUFF_TEMPLATES[i];
+ --SMARTBUFF_AddMsgD("Selected/Current Buff-Template: " .. tmp .. "/" .. currentTemplate);
+ if (currentTemplate ~= tmp) then
+ SmartBuff_BuffSetup:Hide();
+ iLastBuffSetup = -1;
+ SmartBuff_PlayerSetup:Hide();
+
+ currentTemplate = tmp;
+ SMARTBUFF_Options_OnShow();
+ O.LastTemplate = currentTemplate;
+ end
+end
+-- END Options frame functions
+
+
+-- Splash screen functions ---------------------------------------------------------------------------------------
+function SMARTBUFF_Splash_Show()
+ if (not isInit) then return; end
+ SMARTBUFF_Splash_ChangeFont(1);
+ SmartBuffSplashFrame:EnableMouse(true);
+ SmartBuffSplashFrame:Show();
+ SmartBuffSplashFrame:SetTimeVisible(60);
+ SmartBuffSplashFrameOptions:Show();
+end
+
+function SMARTBUFF_Splash_Hide()
+ if (not isInit) then return; end
+ SMARTBUFF_Splash_Clear();
+ SMARTBUFF_Splash_ChangePos();
+ SmartBuffSplashFrame:EnableMouse(false);
+ SmartBuffSplashFrame:SetFadeDuration(O.SplashDuration);
+ SmartBuffSplashFrame:SetTimeVisible(O.SplashDuration);
+ SmartBuffSplashFrameOptions:Hide();
+end
+
+function SMARTBUFF_Splash_Clear()
+ SmartBuffSplashFrame:Clear();
+end
+
+function SMARTBUFF_Splash_ChangePos()
+ local x, y = SmartBuffSplashFrame:GetLeft(), SmartBuffSplashFrame:GetTop() - UIParent:GetHeight();
+ if (O) then
+ O.SplashX = x;
+ O.SplashY = y;
+ end
+end
+
+function SMARTBUFF_Splash_ChangeFont(mode)
+ local f = SmartBuffSplashFrame;
+
+ if (mode > 1) then
+ SMARTBUFF_Splash_ChangePos();
+ iCurrentFont = iCurrentFont + 1;
+ end
+ if (not cFonts[iCurrentFont]) then
+ iCurrentFont = 1;
+ end
+ O.CurrentFont = iCurrentFont;
+ f:ClearAllPoints();
+ f:SetPoint("TOPLEFT", O.SplashX, O.SplashY);
+
+ local fo = f:GetFontObject();
+ local fName, fHeight, fFlags = _G[cFonts[iCurrentFont]]:GetFont();
+ if (mode > 1 or O.CurrentFontSize == nil) then
+ O.CurrentFontSize = fHeight;
+ end
+ fo:SetFont(fName, O.CurrentFontSize, fFlags);
+ SmartBuffSplashFrameOptions.size:SetValue(O.CurrentFontSize);
+
+ f:SetInsertMode("TOP");
+ f:SetJustifyV("MIDDLE");
+ if (mode > 0) then
+ local si = "";
+ if (OG.SplashIcon) then
+ local n = O.SplashIconSize;
+ if (n == nil or n <= 0) then
+ n = O.CurrentFontSize;
+ end
+ si = string.format(" \124T%s:%d:%d:1:0\124t", "Interface\\Icons\\INV_Misc_QuestionMark", n, n) or "";
+ else
+ si = " BuffXYZ";
+ end
+ SMARTBUFF_Splash_Clear();
+ if (OG.SplashMsgShort) then
+ f:AddMessage(cFonts[iCurrentFont].." >"..si.."\ndrag'n'drop to move", O.ColSplashFont.r, O.ColSplashFont.g, O.ColSplashFont.b, 1.0);
+ else
+ f:AddMessage(cFonts[iCurrentFont].." "..SMARTBUFF_MSG_NEEDS..si.."\ndrag'n'drop to move", O.ColSplashFont.r, O.ColSplashFont.g, O.ColSplashFont.b, 1.0);
+ end
+ end
+end
+-- END Splash screen events
+
+
+-- Playerlist functions ---------------------------------------------------------------------------------------
+function SmartBuff_PlayerSetup_OnShow()
+end
+
+function SmartBuff_PlayerSetup_OnHide()
+end
+
+function SmartBuff_PS_GetList()
+ if (iLastBuffSetup <= 0) then return { } end
+
+ local name = cBuffs[iLastBuffSetup].BuffS;
+ if (name) then
+ if (iCurrentList == 1) then
+ return B[CS()][currentTemplate][name].AddList;
+ else
+ return B[CS()][currentTemplate][name].IgnoreList;
+ end
+ end
+end
+
+function SmartBuff_PS_GetUnitList()
+ if (iCurrentList == 1) then
+ return cAddUnitList;
+ else
+ return cIgnoreUnitList;
+ end
+end
+
+function SmartBuff_UnitIsAdd(unit)
+ if (unit and cAddUnitList[unit]) then return true end
+ return false;
+end
+
+function SmartBuff_UnitIsIgnored(unit)
+ if (unit and cIgnoreUnitList[unit]) then return true end
+ return false;
+end
+
+function SmartBuff_PS_Show(i)
+ iCurrentList = i;
+ iLastPlayer = -1;
+ local obj = SmartBuff_PlayerSetup_Title;
+ if (iCurrentList == 1) then
+ obj:SetText("Additional list");
+ else
+ obj:SetText("Ignore list");
+ end
+ obj:ClearFocus();
+ SmartBuff_PlayerSetup_EditBox:ClearFocus();
+ SmartBuff_PlayerSetup:Show();
+ SmartBuff_PS_SelectPlayer(0);
+end
+
+function SmartBuff_PS_AddPlayer()
+ local cList = SmartBuff_PS_GetList();
+ local un = UnitName("target");
+ if (un and UnitIsPlayer("target") and (UnitInRaid("target") or UnitInParty("target") or O.Debug)) then
+ if (not cList[un]) then
+ cList[un] = true;
+ SmartBuff_PS_SelectPlayer(0);
+ end
+ end
+end
+
+function SmartBuff_PS_RemovePlayer()
+ local n = 0;
+ local cList = SmartBuff_PS_GetList();
+ for player in pairs(cList) do
+ n = n + 1;
+ if (n == iLastPlayer) then
+ cList[player] = nil;
+ break;
+ end
+ end
+ SmartBuff_PS_SelectPlayer(0);
+end
+
+function SmartBuff_AddToUnitList(idx, unit, subgroup)
+ iCurrentList = idx;
+ local cList = SmartBuff_PS_GetList();
+ local cUnitList = SmartBuff_PS_GetUnitList();
+ if (unit and subgroup) then
+ local un = UnitName(unit);
+ if (un and cList[un]) then
+ cUnitList[unit] = subgroup;
+ --print("Added to UnitList:" .. un .. "(" .. unit .. ")");
+ end
+ end
+end
+
+function SmartBuff_PS_SelectPlayer(iOp)
+ local idx = iLastPlayer + iOp;
+ local cList = SmartBuff_PS_GetList();
+ local s = "";
+
+ local tn = 0;
+ for player in pairs(cList) do
+ tn = tn + 1;
+ s = s .. player .. "\n";
+ end
+
+ -- update list in textbox
+ if (iOp == 0) then
+ SmartBuff_PlayerSetup_EditBox:SetText(s);
+ --SmartBuff_PlayerSetup_EditBox:ClearFocus();
+ end
+
+ -- highlight selected player
+ if (tn > 0) then
+ if (idx > tn) then idx = tn; end
+ if (idx < 1) then idx = 1; end
+ iLastPlayer = idx;
+ --SmartBuff_PlayerSetup_EditBox:ClearFocus();
+ local n = 0;
+ local i = 0;
+ local w = 0;
+ for player in pairs(cList) do
+ n = n + 1;
+ w = string.len(player);
+ if (n == idx) then
+ SmartBuff_PlayerSetup_EditBox:HighlightText(i + n - 1, i + n + w);
+ break;
+ end
+ i = i + w;
+ end
+ end
+end
+
+function SmartBuff_PS_Resize()
+ local h = SmartBuffOptionsFrame:GetHeight();
+ local b = true;
+
+ if (h < 200) then
+ SmartBuffOptionsFrame:SetHeight(SMARTBUFF_OPTIONSFRAME_HEIGHT);
+ --SmartBuff_BuffSetup:SetHeight(SMARTBUFF_OPTIONSFRAME_HEIGHT);
+ b = true;
+ else
+ SmartBuffOptionsFrame:SetHeight(40);
+ --SmartBuff_BuffSetup:SetHeight(40);
+ b = false;
+ end
+ SmartBuff_ShowControls("SmartBuffOptionsFrame", b);
+ if (b) then
+ SMARTBUFF_SetCheckButtonBuffs(1);
+ end
+end
+-- END Playerlist functions
+
+
+-- Mini group functions ---------------------------------------------------------------------------------------
+function SMARTBUFF_MiniGroup_OnShow()
+ SmartBuff_MiniGroup_Title:SetText(SMARTBUFF_TITLE.." - "..currentTemplate);
+ SMARTBUFF_ShowSubGroupsMini();
+end
+
+function SMARTBUFF_MiniGroup_OnHide()
+end
+
+function SMARTBUFF_MiniGroup_Show()
+ --if (O.ShowMiniGrp) then
+ if (O.ShowMiniGrp and iGroupSetup == 3) then
+ SmartBuff_MiniGroup:Show();
+ else
+ if (SmartBuff_MiniGroup:IsVisible()) then
+ SmartBuff_MiniGroup:Hide();
+ end
+ end
+end
+-- END Mini group functions
+
+
+-- Secure button functions, NEW TBC ---------------------------------------------------------------------------------------
+function SMARTBUFF_ShowSAButton()
+ if (not InCombatLockdown()) then
+ if (O.HideSAButton) then
+ SmartBuff_KeyButton:Hide();
+ else
+ SmartBuff_KeyButton:Show();
+ end
+ end
+end
+
+local sScript;
+function SMARTBUFF_OnClick(obj)
+ SMARTBUFF_AddMsgD("OnClick");
+end
+
+
+local lastBuffType = "";
+function SMARTBUFF_OnPreClick(self, button, down)
+ if (not isInit) then return end
+
+ local mode = 0;
+ if (button) then
+ if (button == "MOUSEWHEELUP" or button == "MOUSEWHEELDOWN") then
+ mode = 5;
+ end
+ end
+
+ if (not InCombatLockdown()) then
+ self:SetAttribute("type", nil);
+ self:SetAttribute("unit", nil);
+ self:SetAttribute("spell", nil);
+ self:SetAttribute("item", nil);
+ self:SetAttribute("macrotext", nil);
+ self:SetAttribute("target-slot", nil);
+ self:SetAttribute("target-item", nil);
+ self:SetAttribute("action", nil);
+ end
+
+ --sScript = self:GetScript("OnClick");
+ --self:SetScript("OnClick", SMARTBUFF_OnClick);
+
+ local td;
+ if (lastBuffType == "") then
+ td = 0.8;
+ else
+ td = GlobalCd;
+ end
+ --SMARTBUFF_AddMsgD("Last buff type: " .. lastBuffType .. ", set cd: " .. td);
+
+
+ -- *** TODO: Check for classic **********************************************************************************
+ local casting = UnitCastingInfo("player") or UnitChannelInfo("player");
+ --print(casting);
+ if (casting ~= nil) then
+ --print("Casting", casting, "-> Reset AutoBuff timer");
+ tAutoBuff = GetTime() + 0.7;
+ return;
+ end
+
+ if (GetTime() < (tAutoBuff + td)) then return end
+
+ --SMARTBUFF_AddMsgD("next buff check");
+ tAutoBuff = GetTime();
+ lastBuffType = "";
+ currentUnit = nil;
+ currentSpell = nil;
+ currentRank = nil;
+
+ if (not InCombatLockdown()) then
+ local ret, actionType, spellName, slot, unit, buffType, rankText = SMARTBUFF_Check(mode);
+ if (ret and ret == 0 and actionType and spellName and unit) then
+ lastBuffType = buffType;
+ self:SetAttribute("type", actionType);
+ self:SetAttribute("unit", unit);
+ if (actionType == SMARTBUFF_ACTION_SPELL) then
+ if (slot and slot > 0 and unit == "player") then
+ self:SetAttribute("type", "macro");
+ self:SetAttribute("macrotext", string.format("/use %s\n/use %i\n/click StaticPopup1Button1", spellName, slot));
+ --self:SetAttribute("target-item", slot);
+ SMARTBUFF_AddMsgD("Weapon buff "..spellName..", "..slot);
+ else
+ --rankText = "(Rang 1)";
+ local name = spellName;
+ if (rankText ~= nil) then
+ name = spellName..rankText;
+ end
+ SMARTBUFF_AddMsgD("SetAttribute 'spell' = "..name);
+ self:SetAttribute("spell", name);
+ end
+
+ if (cBuffIndex[spellName]) then
+ currentUnit = unit;
+ currentSpell = spellName;
+ end
+
+ elseif (actionType == SMARTBUFF_ACTION_ITEM and slot) then
+ --if (spellname ~= nil and string.find(spellname, "%-%-") ~= nil) then
+ -- spellname = string.gsub(spellname, "%-%-", "%-");
+ --end
+ self:SetAttribute("item", spellName);
+ if (slot > 0) then
+ --self:SetAttribute("target-slot", slot);
+
+ self:SetAttribute("type", "macro");
+ self:SetAttribute("macrotext", string.format("/use %s\n/use %i\n/click StaticPopup1Button1", spellName, slot));
+ end
+ elseif (actionType == "action" and slot) then
+ self:SetAttribute("action", slot);
+ else
+ SMARTBUFF_AddMsgD("Preclick: not supported actiontype -> " .. actionType);
+ end
+
+ --isClearSplash = true;
+ tLastCheck = GetTime() - O.AutoTimer + GlobalCd;
+ end
+ end
+end
+
+function SMARTBUFF_OnPostClick(self, button, down)
+ if (not isInit) then return end
+
+ if (button) then
+ if (button == "MOUSEWHEELUP") then
+ CameraZoomIn(1);
+ elseif (button == "MOUSEWHEELDOWN") then
+ CameraZoomOut(1);
+ end
+ end
+
+ if (InCombatLockdown()) then return end
+
+ --[[
+ if (O.Toggle) then
+ if (O.InCombat) then
+ for spell, data in pairs(cBuffsCombat) do
+ if (data and data.Unit and data.ActionType) then
+ SmartBuff_KeyButton:SetAttribute("unit", data.Unit);
+ SmartBuff_KeyButton:SetAttribute("type", data.ActionType);
+ SmartBuff_KeyButton:SetAttribute("spell", spell);
+ SmartBuff_KeyButton:SetAttribute("item", nil);
+ SmartBuff_KeyButton:SetAttribute("target-slot", nil);
+ SmartBuff_KeyButton:SetAttribute("action", nil);
+ SMARTBUFF_AddMsgD("Enter Combat, set button: " .. spell .. " on " .. data.Unit .. ", " .. data.ActionType);
+ break;
+ end
+ end
+ end
+ end
+ ]]--
+
+ --local posX, posY = GetPlayerMapPosition("player");
+ --SMARTBUFF_AddMsgD("X = " .. posX .. ", Y = " .. posY);
+ --if (UnitCreatureType("target")) then
+ -- SMARTBUFF_AddMsgD(UnitCreatureType("target"));
+ --end
+
+ --[[
+ local r = IsSpellInRange("Nachwachsen", "target")
+ if(r and r == 1) then
+ SMARTBUFF_AddMsgD("Spell in range");
+ elseif(r and r == 0) then
+ SMARTBUFF_AddMsgD("OOR");
+ end
+ ]]--
+
+ --[[
+ local s = "";
+ local button = SecureStateChild_GetEffectiveButton(self);
+ local type = SecureButton_GetModifiedAttribute(self, "type", button, "");
+ local unit = SecureButton_GetModifiedAttribute(self, "unit", button, "");
+ local spell = SecureButton_GetModifiedAttribute(self, "spell", button, "");
+ if (type and unit and spell) then
+ s = s .. type .. ", " .. unit .. ", " .. spell;
+ end
+ ]]--
+
+ self:SetAttribute("type", nil);
+ self:SetAttribute("unit", nil);
+ self:SetAttribute("spell", nil);
+ self:SetAttribute("item", nil);
+ self:SetAttribute("target-slot", nil);
+ self:SetAttribute("target-item", nil);
+ self:SetAttribute("macrotext", nil);
+ self:SetAttribute("action", nil);
+
+ SMARTBUFF_SetButtonTexture(SmartBuff_KeyButton, imgSB);
+ --SMARTBUFF_AddMsgD("Button reseted, " .. button);
+ --self:SetScript("OnClick", sScript);
+end
+
+function SMARTBUFF_SetButtonTexture(button, texture, text)
+ --if (InCombatLockdown()) then return; end
+
+ if (button and texture and texture ~= sLastTexture) then
+ sLastTexture = texture;
+ button:SetNormalTexture(texture);
+ --SMARTBUFF_AddMsgD("Button slot texture set -> " .. texture);
+ if (text) then
+ --button.title:SetText(spell);
+ end
+ end
+end
+-- END secure button functions
+
+
+-- Minimap button functions ---------------------------------------------------------------------------------------
+-- Sets the correct icon on the minimap button
+function SMARTBUFF_CheckMiniMapButton()
+ if (O.Toggle) then
+ SmartBuff_MiniMapButton:SetNormalTexture(imgIconOn);
+ else
+ SmartBuff_MiniMapButton:SetNormalTexture(imgIconOff);
+ end
+
+ if (O.HideMmButton) then
+ SmartBuff_MiniMapButton:Hide();
+ else
+ SmartBuff_MiniMapButton:Show();
+ end
+
+ -- Update the Titan Panel icon
+ if (TitanPanelBarButton and TitanPanelSmartBuffButton_SetIcon ~= nil) then
+ TitanPanelSmartBuffButton_SetIcon();
+ end
+
+ -- Update the FuBar icon
+ if (IsAddOnLoaded("FuBar") and IsAddOnLoaded("FuBar_SmartBuffFu") and SMARTBUFF_Fu_SetIcon ~= nil) then
+ SMARTBUFF_Fu_SetIcon();
+ end
+
+ -- Update the Broker icon
+ if (IsAddOnLoaded("Broker_SmartBuff") and SMARTBUFF_BROKER_SetIcon ~= nil) then
+ SMARTBUFF_BROKER_SetIcon();
+ end
+
+end
+
+function SMARTBUFF_MinimapButton_CheckPos()
+ if (not isInit or not SmartBuff_MiniMapButton) then return; end
+ local x = SmartBuff_MiniMapButton:GetLeft();
+ local y = SmartBuff_MiniMapButton:GetTop();
+ if (x == nil or y == nil) then return; end
+ x = x - Minimap:GetLeft();
+ y = y - Minimap:GetTop();
+ if (math.abs(x) < 180 and math.abs(y) < 180) then
+ O.MMCPosX = x;
+ O.MMCPosY = y;
+ --SMARTBUFF_AddMsgD("x = " .. O.MMCPosX .. ", y = " .. O.MMCPosY);
+ end
+end
+
+-- Function to move the minimap button arround the minimap
+function SMARTBUFF_MinimapButton_OnUpdate(self, move)
+ if (not isInit or self == nil or not self:IsVisible()) then
+ return;
+ end
+
+ local xpos, ypos;
+ self:ClearAllPoints();
+ if (move or O.MMCPosX == nil) then
+ local pos, r
+ local xmin, ymin = Minimap:GetLeft(), Minimap:GetBottom();
+ xpos, ypos = GetCursorPosition();
+ xpos = xmin-xpos/Minimap:GetEffectiveScale()+70;
+ ypos = ypos/Minimap:GetEffectiveScale()-ymin-70;
+ pos = math.deg(math.atan2(ypos,xpos));
+ r = math.sqrt(xpos*xpos + ypos*ypos);
+ --SMARTBUFF_AddMsgD("x = " .. xpos .. ", y = " .. ypos .. ", r = " .. r .. ", pos = " .. pos);
+
+ if (r < 75) then
+ r = 75;
+ elseif(r > 105) then
+ r = 105;
+ end
+
+ xpos = 52-r*cos(pos);
+ ypos = r*sin(pos)-52;
+ O.MMCPosX = xpos;
+ O.MMCPosY = ypos;
+ --SMARTBUFF_AddMsgD("Update minimap button position");
+ else
+ xpos = O.MMCPosX;
+ ypos = O.MMCPosY;
+ --SMARTBUFF_AddMsgD("Load minimap button position");
+ end
+ self:ClearAllPoints();
+ self:SetPoint("TOPLEFT", "Minimap", "TOPLEFT", xpos, ypos);
+ --SMARTBUFF_AddMsgD("x = " .. O.MMCPosX .. ", y = " .. O.MMCPosY);
+ --SmartBuff_MiniMapButton:SetUserPlaced(true);
+ --SMARTBUFF_AddMsgD("Update minimap button");
+end
+-- END Minimap button functions
+
+
+
+-- Scroll frame functions ---------------------------------------------------------------------------------------
+local ScrBtnSize = 20;
+local ScrLineHeight = 18;
+local function SetPosScrollButtons(parent, cBtn)
+ local btn;
+ local name;
+ for i = 1, #cBtn, 1 do
+ btn = cBtn[i];
+ btn:ClearAllPoints();
+ btn:SetPoint("TOPLEFT", parent, "TOPLEFT", 2, -2 - ScrLineHeight*(i-1));
+ end
+end
+
+local StartY, EndY;
+local function CreateScrollButton(name, parent, cBtn, onClick, onDragStop)
+ local btn = CreateFrame("CheckButton", name, parent, "OptionsCheckButtonTemplate");
+ btn:SetWidth(ScrBtnSize);
+ btn:SetHeight(ScrBtnSize);
+ --btn:RegisterForClicks("LeftButtonUp");
+ btn:RegisterForClicks("AnyUp");
+ btn:SetScript("OnClick", onClick);
+ --btn:SetScript("OnMouseUp", onClick);
+
+ if (onDragStop ~= nil) then
+ btn:SetMovable(true);
+ btn:RegisterForDrag("LeftButton");
+ btn:SetScript("OnDragStart", function(self, b)
+ StartY = self:GetTop();
+ self:StartMoving();
+ end
+ );
+ btn:SetScript("OnDragStop", function(self, b)
+ EndY = self:GetTop();
+ local i = tonumber(self:GetID()) + FauxScrollFrame_GetOffset(parent);
+ local n = math.floor((StartY-EndY) / ScrLineHeight);
+ self:StopMovingOrSizing();
+ SetPosScrollButtons(parent, cBtn);
+ onDragStop(i, n);
+ end
+ );
+ end
+
+ local text = btn:CreateFontString(nil, nil, "GameFontNormal");
+ text:SetJustifyH("LEFT");
+ --text:SetAllPoints(btn);
+ text:SetPoint("TOPLEFT", btn, "TOPLEFT", ScrBtnSize, 0);
+ text:SetWidth(parent:GetWidth()-ScrBtnSize);
+ text:SetHeight(ScrBtnSize);
+ btn:SetFontString(text);
+ btn:SetHighlightFontObject("GameFontHighlight");
+
+ local highlight = btn:CreateTexture();
+ --highlight:SetAllPoints(btn);
+ highlight:SetPoint("TOPLEFT", btn, "TOPLEFT", 0, -2);
+ highlight:SetWidth(parent:GetWidth());
+ highlight:SetHeight(ScrLineHeight-3);
+
+ highlight:SetTexture("Interface/QuestFrame/UI-QuestTitleHighlight");
+ btn:SetHighlightTexture(highlight);
+
+ return btn;
+end
+
+
+local function CreateScrollButtons(self, cBtn, sBtnName, onClick, onDragStop)
+ local btn, i;
+ for i = 1, maxScrollButtons, 1 do
+ btn = CreateScrollButton(sBtnName..i, self, cBtn, onClick, onDragStop);
+ btn:SetID(i);
+ cBtn[i] = btn;
+ end
+ SetPosScrollButtons(self, cBtn);
+end
+
+
+local function OnScroll(self, cData, sBtnName)
+ local num = #cData;
+ local n, numToDisplay;
+
+ if (num <= maxScrollButtons) then
+ numToDisplay = num-1;
+ else
+ numToDisplay = maxScrollButtons;
+ end
+
+ FauxScrollFrame_Update(self, num, numToDisplay, ScrLineHeight);
+ local t = B[CS()][CT()];
+ for i = 1, maxScrollButtons, 1 do
+ n = i + FauxScrollFrame_GetOffset(self);
+ btn = _G[sBtnName..i];
+ if (btn) then
+ if (n <= num) then
+ btn:SetNormalFontObject("GameFontNormalSmall");
+ btn:SetHighlightFontObject("GameFontHighlightSmall");
+ btn:SetText(cData[n]);
+ btn:SetChecked(t[cData[n]].EnableS);
+ btn:Show();
+ else
+ btn:Hide();
+ end
+ end
+ end
+end
+
+
+function SMARTBUFF_BuffOrderOnScroll(self, arg1)
+ if (not self) then
+ self = SmartBuffOptionsFrame_ScrollFrameBuffs;
+ end
+
+ local name = "SMARTBUFF_BtnScrollBO";
+ if (not cScrBtnBO and self) then
+ cScrBtnBO = { };
+ CreateScrollButtons(self, cScrBtnBO, name, SMARTBUFF_BuffOrderBtnOnClick, SMARTBUFF_BuffOrderBtnOnDragStop);
+ end
+
+ if (B[CS()].Order == nil) then
+ B[CS()].Order = { };
+ end
+
+ local t = { };
+ for _, v in pairs(B[CS()].Order) do
+ if (v) then
+ tinsert(t, v);
+ end
+ end
+ OnScroll(self, t, name);
+end
+
+function SMARTBUFF_BuffOrderBtnOnClick(self, button)
+ local n = self:GetID() + FauxScrollFrame_GetOffset(self:GetParent());
+ local i = cBuffIndex[B[CS()].Order[n]];
+ --SMARTBUFF_AddMsgD("Buff OnClick = "..n..", "..button);
+ if (button == "LeftButton") then
+ SMARTBUFF_OToggleBuff("S", i);
+ else
+ local b = not self:GetChecked();
+ self:SetChecked(b);
+ SmartBuff_BuffSetup_Show(i);
+ end
+end
+
+function SMARTBUFF_BuffOrderBtnOnDragStop(i, n)
+ treorder(B[CS()].Order, i, n);
+ SMARTBUFF_BuffOrderOnScroll();
+end
+
+function SMARTBUFF_BuffOrderReset()
+ InitBuffOrder(true);
+ SMARTBUFF_BuffOrderOnScroll();
+end
+
+
+-- Help plate functions ---------------------------------------------------------------------------------------
+
+local HelpPlateList = {
+ FramePos = { x = 20, y = -20 },
+ FrameSize = { width = 480, height = 500 },
+ [1] = { ButtonPos = { x = 344, y = -80 }, HighLightBox = { x = 260, y = -50, width = 204, height = 410 }, ToolTipDir = "DOWN", ToolTipText = "Spell list\nDrag'n'Drop to change the priority order" },
+ [2] = { ButtonPos = { x = 105, y = -110 }, HighLightBox = { x = 10, y = -30, width = 230, height = 125 }, ToolTipDir = "DOWN", ToolTipText = "Buff reminder options" },
+ [3] = { ButtonPos = { x = 105, y = -250 }, HighLightBox = { x = 10, y = -165, width = 230, height = 135 }, ToolTipDir = "DOWN", ToolTipText = "Character based options" },
+ [4] = { ButtonPos = { x = 200, y = -320 }, HighLightBox = { x = 10, y = -300, width = 230, height = 90 }, ToolTipDir = "RIGHT", ToolTipText = "Additional UI options" },
+}
+
+function SMARTBUFF_ToggleTutorial(close)
+end
+--[[function SMARTBUFF_ToggleTutorial(close)
+ local helpPlate = HelpPlateList;
+ if (not helpPlate) then return end;
+
+ local b = HelpPlate_IsShowing(helpPlate);
+ if (close) then
+ HelpPlate_Hide(false);
+ return;
+ end
+
+ if (not b) then
+ HelpPlate_Show(helpPlate, SmartBuffOptionsFrame, SmartBuffOptionsFrame_TutorialButton, true);
+ else
+ HelpPlate_Hide(true);
+ end
+end--]]
diff --git a/SmartBuff.toc b/SmartBuff.toc
new file mode 100644
index 0000000..dc42e7d
--- /dev/null
+++ b/SmartBuff.toc
@@ -0,0 +1,20 @@
+## Interface: 20504
+## Title: SmartBuff |cffffffff(Classic TBC)|r by |cff00ff00Codermik & Aeldra|r
+## Version: 21.20504
+## Author: |cff20d2ffCodermik (Mik / Castanova on EU-Mirage Raceway) & Aeldra|r (EU-Proudmoore)
+## Notes: Cast the most important buffs on you or party/raid members/pets. Use /sbm for options menu.
+## DefaultState: Enabled
+## LoadOnDemand: 0
+## Notes-deDE: Castet die wichtigsten Buffs auf dich selbst, Gruppe/Raid Mitglieder/Pets. Benutze /sbm um das Men� zu �ffnen
+## Notes-frFR: Cast the most important buffs on you or party/raid members/pets. Use /sbm for options menu.
+## SavedVariables: SMARTBUFF_OptionsGlobal
+## SavedVariablesPerCharacter: SMARTBUFF_Options, SMARTBUFF_Buffs
+
+lib\LibStub\LibStub.lua
+lib\CallbackHandler-1.0\CallbackHandler-1.0.lua
+lib\LibClassicDurations\LibClassicDurations.xml
+SmartBuff.globals.lua
+SmartBuff.xml
+
+lib\Broker_SmartBuff\LibDataBroker-1.1.lua
+lib\Broker_SmartBuff\Broker_SmartBuff.lua
diff --git a/SmartBuff.xml b/SmartBuff.xml
new file mode 100644
index 0000000..adcabeb
--- /dev/null
+++ b/SmartBuff.xml
@@ -0,0 +1,3299 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Mixin(self, BackdropTemplateMixin);
+ self:SetBackdrop({
+ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+ });
+ SMARTBUFF_OnLoad(self);
+
+
+ SMARTBUFF_OnEvent(self, event, ...);
+
+
+ SMARTBUFF_OnUpdate(self, elapsed);
+
+
+
+
+
+
+ self:SetOwner(SmartBuffFrame, "ANCHOR_NONE");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Mixin(self, BackdropTemplateMixin);
+ self:SetBackdrop(nil);
+ self:RegisterForDrag("LeftButton");
+ self:EnableMouse(false);
+ self:EnableKeyboard(false);
+ self:EnableMouseWheel(false);
+ SMARTBUFF_Splash_Hide();
+
+
+ if(SmartBuffOptionsFrame:IsVisible()) then
+ self:StopMovingOrSizing();
+ end
+
+
+ if(SmartBuffOptionsFrame:IsVisible()) then
+ SMARTBUFF_Splash_ChangeFont(1);
+ self:StartMoving();
+ end
+
+
+ if(SmartBuffOptionsFrame:IsVisible()) then
+ SMARTBUFF_Splash_ChangePos();
+ SMARTBUFF_Splash_ChangeFont(1);
+ self:StopMovingOrSizing();
+ end
+
+
+ if(SmartBuffOptionsFrame:IsVisible()) then
+ SMARTBUFF_Splash_ChangeFont(1);
+ end
+
+
+ if(SmartBuffOptionsFrame:IsVisible()) then
+ SMARTBUFF_Splash_ChangeFont(1);
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuffOptionsFrameSlider_OnLoad(self, 4, 48, 1);
+ BackdropTemplateMixin.OnBackdropLoaded(self);
+
+
+ local o = SMARTBUFF_Options;
+ if (o and o.CurrentFontSize) then
+ SmartBuff_SetSliderText(self, SMARTBUFF_OFT_FONTSIZE, o.CurrentFontSize, "%d", true);
+ end
+
+
+ local p = SmartBuffSplashFrame;
+ if (not p) then return end
+
+ local o = SMARTBUFF_Options;
+ local f = p:GetFontObject();
+ local fName, fHeight, fFlags = f:GetFont();
+ local n = self:GetValue();
+
+ if (o and n ~= o.CurrentFontSize) then
+ SmartBuff_SetSliderText(self, SMARTBUFF_OFT_FONTSIZE, n, "%d");
+ f:SetFont(fName, n, fFlags)
+ o.CurrentFontSize = n;
+ SMARTBUFF_Splash_ChangeFont(1);
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuffOptionsFrameSlider_OnLoad(self, 0, 64, 4);
+ BackdropTemplateMixin.OnBackdropLoaded(self);
+
+
+ local o = SMARTBUFF_Options;
+ if (o and o.SplashIconSize) then
+ SmartBuff_SetSliderText(self, SMARTBUFF_OFT_ICONSIZE, o.SplashIconSize, "%d", true);
+ end
+
+
+ local o = SMARTBUFF_Options;
+ local n = self:GetValue();
+ if (o and o.SplashIconSize ~= n) then
+ SmartBuff_SetSliderText(self, SMARTBUFF_OFT_ICONSIZE, n, "%d");
+ o.SplashIconSize = n;
+ SMARTBUFF_Splash_ChangeFont(1);
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_SPLASHICON);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ local o = SMARTBUFF_OptionsGlobal;
+ if (o) then self:SetChecked(o.SplashIcon or false) end
+
+
+ local o = SMARTBUFF_OptionsGlobal;
+ if (o) then
+ o.SplashIcon = not o.SplashIcon;
+ SMARTBUFF_Splash_ChangeFont(1);
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_SPLASHMSGSHORT);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ local o = SMARTBUFF_OptionsGlobal;
+ if (o) then self:SetChecked(o.SplashMsgShort or false) end
+
+
+ local o = SMARTBUFF_OptionsGlobal;
+ if (o) then
+ o.SplashMsgShort = not o.SplashMsgShort;
+ SMARTBUFF_Splash_ChangeFont(1);
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if(SMARTBUFF_Options) then
+ self:SetColorRGB(SMARTBUFF_Options.ColSplashFont.r, SMARTBUFF_Options.ColSplashFont.g, SMARTBUFF_Options.ColSplashFont.b);
+ end;
+
+
+ local o = SMARTBUFF_Options;
+ local r, g, b = self:GetColorRGB();
+ if (o and (r ~= o.ColSplashFont.r or g ~= o.ColSplashFont.g or b ~= o.ColSplashFont.r)) then
+ o.ColSplashFont.r = r;
+ o.ColSplashFont.g = g;
+ o.ColSplashFont.b = b;
+ end;
+
+
+ SMARTBUFF_Splash_ChangeFont(1);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:EnableKeyboard(false);
+ self:EnableMouseWheel(false);
+
+
+ Mixin(self, BackdropTemplateMixin);
+ self:SetBackdrop({
+ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+ insets = {left = 12, right = 12, top = 12, bottom = 11},
+ });
+ SmartBuffSplashFrame:SetBackdrop({
+ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
+ edgeFile = nil,
+ });
+ SmartBuffSplashFrame:SetBackdropColor(0, 0, 0, 1)
+ self:ClearAllPoints();
+ self:SetPoint("TOPLEFT", self:GetParent(), "BOTTOMLEFT", 0, -2);
+
+
+ SmartBuffSplashFrame:SetBackdrop({
+ bgFile = nil,
+ edgeFile = nil,
+ })
+
+
+ if(self:IsVisible()) then
+ SMARTBUFF_Splash_ChangeFont(1);
+ end
+
+
+ if(self:IsVisible()) then
+ SMARTBUFF_Splash_ChangeFont(1);
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggle();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_AUTO);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleAuto();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_AUTO, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuffOptionsFrameSlider_OnLoad(self, 1, 60, 1);
+ BackdropTemplateMixin.OnBackdropLoaded(self);
+
+
+ local o = SMARTBUFF_Options;
+ if (o and o.AutoTimer) then
+ SmartBuff_SetSliderText(self, SMARTBUFF_OFT_AUTOTIMER, o.AutoTimer, INT_SPELL_DURATION_SEC, true);
+ end
+
+
+ local o = SMARTBUFF_Options;
+ local n = self:GetValue();
+ if (o and o.AutoTimer ~= n) then
+ SmartBuff_SetSliderText(self, SMARTBUFF_OFT_AUTOTIMER, n, INT_SPELL_DURATION_SEC);
+ o.AutoTimer = n;
+ end
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_AUTOTIMER, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_AUTOCOMBAT);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleAutoCombat();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_AUTOCOMBAT, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_AUTOCHAT);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleAutoChat();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_AUTOCHAT, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_AUTOSPLASH);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleAutoSplash();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_AUTOSPLASH, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_AUTOSOUND);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleAutoSound();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_AUTOSOUND, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuffOptionsFrameSlider_OnLoad(self, 0, 10, 1);
+ BackdropTemplateMixin.OnBackdropLoaded(self);
+
+
+ local o = SMARTBUFF_Options;
+ if (o and o.MinCharges) then
+ SmartBuff_SetSliderText(self, SMARTBUFF_MSG_CHARGES, o.MinCharges, "%d", true);
+ end
+
+
+ local o = SMARTBUFF_Options;
+ local n = self:GetValue();
+ if (o and o.MinCharges ~= n) then
+ SmartBuff_SetSliderText(self, SMARTBUFF_MSG_CHARGES, n, "%d");
+ o.MinCharges = n;
+ if (n == 0) then
+ o.CheckCharges = false;
+ else
+ o.CheckCharges = true;
+ end
+ end
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_CHECKCHARGES, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuffOptionsFrameSlider_OnLoad(self, 0, 5, 0.2);
+ BackdropTemplateMixin.OnBackdropLoaded(self);
+
+
+ local o = SMARTBUFF_Options;
+ if (o and o.SplashDuration) then
+ SmartBuff_SetSliderText(self, "Splash", o.SplashDuration, SPELL_DURATION_SEC, true);
+ end
+
+
+ local o = SMARTBUFF_Options;
+ local n = self:GetValue();
+ if (o and o.SplashDuration ~= n) then
+ SmartBuff_SetSliderText(self, "Splash", n, SPELL_DURATION_SEC);
+ o.SplashDuration = n;
+ end
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_SPLASHDURATION, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuffOptionsFrameSlider_OnLoad(self, 0, 600, 10);
+ BackdropTemplateMixin.OnBackdropLoaded(self);
+
+
+ local o = SMARTBUFF_Options;
+ if (o and o.RebuffTimer) then
+ SmartBuff_SetSliderText(self, SMARTBUFF_OFT_REBUFFTIMER, o.RebuffTimer, INT_SPELL_DURATION_SEC, true);
+ end
+
+
+ local o = SMARTBUFF_Options;
+ local n = self:GetValue();
+ if (o and o.RebuffTimer ~= n) then
+ SmartBuff_SetSliderText(self, SMARTBUFF_OFT_REBUFFTIMER, n, INT_SPELL_DURATION_SEC);
+ o.RebuffTimer = n;
+ end
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_REBUFFTIMER, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_AUTOSWITCHTMP);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OAutoSwitchTmp();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_AUTOSWITCHTMP, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_AUTOSWITCHTMPINST);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OAutoSwitchTmpInst();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_AUTOSWITCHTMPINST, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_LINKGRPBUFFCHECK);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OLinkGrpBuffCheck();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_LINKGRPBUFFCHECK, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_ANTIDAZE);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OAntiDaze();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_ANTIDAZE, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_LINKSELFBUFFCHECK);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OLinkSelfBuffCheck();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_LINKSELFBUFFCHECK, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_BUFFPVP);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OBuffPvP();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_BUFFPVP, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_BUFFTARGET);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OBuffTarget();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_BUFFTARGET, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_SCROLLWHEELUP);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OScrollWheelUp();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_SCROLLWHEELUP, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_SCROLLWHEELDOWN);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OScrollWheelDown();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_SCROLLWHEELDOWN, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_BUFFINCITIES);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OBuffInCities();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_BUFFINCITIES, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_INSHAPESHIFT);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OInShapeshift();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_INSHAPESHIFT, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_INCOMBAT);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OInCombat();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_INCOMBAT, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuffOptionsFrameSlider_OnLoad(self, 0, 40, 1);
+ BackdropTemplateMixin.OnBackdropLoaded(self);
+
+
+ local o = SMARTBUFF_Options;
+ local n = self:GetValue();
+ if (o and o.BlacklistTimer ~= n) then
+ SmartBuff_SetSliderText(self, SMARTBUFF_OFT_BLDURATION, n, INT_SPELL_DURATION_SEC);
+ o.BlacklistTimer = n;
+ end
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_BLDURATION, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_MSGNORMAL);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleMsgNormal();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_MSGERROR);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleMsgError();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_MSGWARNING);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleMsgWarning();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_HIDEMMBUTTON);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OHideMmButton();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_HIDEMMBUTTON, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_OFT_HIDESABUTTON);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OHideSAButton();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_OFTT_HIDESABUTTON, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FauxScrollFrame_OnVerticalScroll(self, offset, 18, SMARTBUFF_BuffOrderOnScroll);
+
+
+ SMARTBUFF_BuffOrderOnScroll(self);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Mixin(self, BackdropTemplateMixin)
+ self:SetBackdrop({
+ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+ insets = {left = 12, right = 12, top = 12, bottom = 11},
+ });
+ SMARTBUFF_Options_OnLoad(self);
+
+
+ SMARTBUFF_Options_OnShow();
+ --SmartBuff_MiniGroup:Hide();
+
+
+ self:StopMovingOrSizing();
+ SMARTBUFF_Options_OnHide();
+ --SMARTBUFF_MiniGroup_Show();
+
+
+ if (button == "LeftButton") then
+ self:StartMoving();
+ end
+
+
+ if (button == "LeftButton") then
+ self:StopMovingOrSizing();
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:EnableMouse(false);
+ self:EnableKeyboard(false);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_BST_SELFONLY);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_BSTT_SELFONLY, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_BST_SELFNOT);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_BSTT_SELFNOT, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_BST_COMBATIN);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_BSTT_COMBATIN, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_BST_COMBATOUT);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_BSTT_COMBATOUT, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:SetFontObject(GameFontHighlightSmall);
+ self:SetJustifyH("LEFT");
+ self:SetJustifyV("MIDDLE");
+
+
+ SmartBuff_BuffSetup_txtManaLimit:SetFocus();
+
+
+ self:ClearFocus();
+
+
+ SmartBuff_BuffSetup_ManaLimitChanged(self);
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_BSTT_MANALIMIT, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_BST_MAINHAND);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_BSTT_MAINHAND, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_BST_OFFHAND);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_BSTT_OFFHAND, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_BST_RANGED);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_BSTT_RANGED, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText(SMARTBUFF_BST_REMINDER);
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_BSTT_REMINDER, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ BackdropTemplateMixin.OnBackdropLoaded(self);
+ SmartBuffOptionsFrameSlider_OnLoad(self, 0, 3600, 10, true);
+
+
+ SmartBuff_BuffSetup_RBTime_OnValueChanged(self);
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+ GameTooltip:SetText(SMARTBUFF_BSTT_REBUFFTIMER, SMARTBUFF_TTC_R, SMARTBUFF_TTC_G, SMARTBUFF_TTC_B, SMARTBUFF_TTC_A);
+
+
+ GameTooltip:Hide();
+ SmartBuff_BuffSetup_OnClick();
+
+
+
+
+
+
+ Mixin(self, BackdropTemplateMixin);
+ self:SetBackdrop({
+ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+ insets = {left = 12, right = 12, top = 12, bottom = 11},
+ });
+ SMARTBUFF_Options_OnLoad(self);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:EnableMouse(false);
+ self:EnableKeyboard(false);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:EnableMouse(false);
+ self:EnableKeyboard(false);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Mixin(self, BackdropTemplateMixin);
+ self:SetBackdrop({
+ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+ insets = {left = 12, right = 12, top = 12, bottom = 11},
+ });
+ SmartBuffSplashFrame:SetBackdrop({
+ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
+ edgeFile = nil,
+ });
+ SmartBuff_PlayerSetup_OnShow();
+
+
+ SmartBuff_PlayerSetup_OnHide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:SetText("SmartBuff subgroups");
+ self:EnableMouse(false);
+ self:EnableKeyboard(false);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("1");
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleGrp(1);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("2");
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleGrp(2);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("3");
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleGrp(3);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("4");
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleGrp(4);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("5");
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleGrp(5);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("6");
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleGrp(6);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("7");
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleGrp(7);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(self:GetName().."Text"):SetText("8");
+ getglobal(self:GetName().."Text"):SetFontObject(GameFontNormalSmall);
+
+
+ SMARTBUFF_OToggleGrp(8);
+
+
+
+
+
+
+ self:RegisterForDrag("LeftButton");
+
+
+ Mixin(self, BackdropTemplateMixin);
+ SmartBuff_MiniGroup:SetBackdrop({
+ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
+ edgeFile = nil,
+ });
+ SMARTBUFF_MiniGroup_OnShow();
+
+
+ self:StopMovingOrSizing();
+ SMARTBUFF_MiniGroup_OnHide();
+
+
+ if (button == "LeftButton" and IsShiftKeyDown()) then
+ self:StartMoving();
+ end
+
+
+ if (button == "LeftButton") then
+ self:StopMovingOrSizing();
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:SetAutoFocus(false);
+ self:SetText("");
+ self:EnableMouse(false);
+ self:EnableKeyboard(false);
+ self:SetHeight(SmartBuffOptionsFrame:GetHeight()-16);
+
+
+
+
+
+
+
+ self:SetHeight(SmartBuffOptionsFrame:GetHeight());
+ Mixin(self, BackdropTemplateMixin)
+ self:SetBackdrop({bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", insets = {left = 12, right = 12, top = 12, bottom = 11},})
+
+
+
+
+
+ self:StopMovingOrSizing();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/Broker_SmartBuff/Broker_SmartBuff.lua b/lib/Broker_SmartBuff/Broker_SmartBuff.lua
new file mode 100644
index 0000000..ae1b766
--- /dev/null
+++ b/lib/Broker_SmartBuff/Broker_SmartBuff.lua
@@ -0,0 +1,45 @@
+-------------------------------------------------------------------------------
+-- Broker: SmartBuff
+-- Created by Aeldra (EU-Proudmoore)
+--
+-- Data Broker support
+-------------------------------------------------------------------------------
+
+if (not SMARTBUFF_TITLE) then return end
+
+local F = CreateFrame("Frame", "Broker_SmartBuff");
+
+function SMARTBUFF_BROKER_SetIcon()
+ if (not F.LS) then return end
+ if (SMARTBUFF_Options and SMARTBUFF_Options.Toggle) then
+ F.LS.icon = "Interface\\AddOns\\SmartBuff\\Icons\\IconEnabled";
+ else
+ F.LS.icon = "Interface\\AddOns\\SmartBuff\\Icons\\IconDisabled";
+ end
+end
+
+F.LS = LibStub:GetLibrary("LibDataBroker-1.1"):NewDataObject("SmartBuff", {
+ type = "launcher",
+ label = SMARTBUFF_TITLE,
+ OnClick = function(_, msg)
+ if (msg == "RightButton") then
+ SMARTBUFF_OToggle();
+ SMARTBUFF_BROKER_SetIcon(); -- bug fix, credit: SunNova
+ elseif (msg == "LeftButton" and IsAltKeyDown()) then
+ if (IsAddOnLoaded("SmartDebuff")) then
+ SMARTDEBUFF_ToggleSF();
+ end
+ elseif (msg == "LeftButton") then
+ SMARTBUFF_OptionsFrame_Toggle();
+ end
+ end,
+ icon = "Interface\\AddOns\\SmartBuff\\Icons\\IconDisabled",
+ OnTooltipShow = function(tooltip)
+ if (not tooltip or not tooltip.AddLine) then return end
+ tooltip:AddLine("|cffffffff"..SMARTBUFF_TITLE.."|r");
+ tooltip:AddLine(SMARTBUFF_TITAN_TT);
+ end,
+});
+
+F:Hide();
+--print("Borker - SmartBuff loaded");
diff --git a/lib/Broker_SmartBuff/LibDataBroker-1.1.lua b/lib/Broker_SmartBuff/LibDataBroker-1.1.lua
new file mode 100644
index 0000000..f47c0cd
--- /dev/null
+++ b/lib/Broker_SmartBuff/LibDataBroker-1.1.lua
@@ -0,0 +1,90 @@
+
+assert(LibStub, "LibDataBroker-1.1 requires LibStub")
+assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
+
+local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
+if not lib then return end
+oldminor = oldminor or 0
+
+
+lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
+lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
+local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
+
+if oldminor < 2 then
+ lib.domt = {
+ __metatable = "access denied",
+ __index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
+ }
+end
+
+if oldminor < 3 then
+ lib.domt.__newindex = function(self, key, value)
+ if not attributestorage[self] then attributestorage[self] = {} end
+ if attributestorage[self][key] == value then return end
+ attributestorage[self][key] = value
+ local name = namestorage[self]
+ if not name then return end
+ callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
+ callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
+ callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
+ callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
+ end
+end
+
+if oldminor < 2 then
+ function lib:NewDataObject(name, dataobj)
+ if self.proxystorage[name] then return end
+
+ if dataobj then
+ assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
+ self.attributestorage[dataobj] = {}
+ for i,v in pairs(dataobj) do
+ self.attributestorage[dataobj][i] = v
+ dataobj[i] = nil
+ end
+ end
+ dataobj = setmetatable(dataobj or {}, self.domt)
+ self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
+ self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
+ return dataobj
+ end
+end
+
+if oldminor < 1 then
+ function lib:DataObjectIterator()
+ return pairs(self.proxystorage)
+ end
+
+ function lib:GetDataObjectByName(dataobjectname)
+ return self.proxystorage[dataobjectname]
+ end
+
+ function lib:GetNameByDataObject(dataobject)
+ return self.namestorage[dataobject]
+ end
+end
+
+if oldminor < 4 then
+ local next = pairs(attributestorage)
+ function lib:pairs(dataobject_or_name)
+ local t = type(dataobject_or_name)
+ assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
+
+ local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
+ assert(attributestorage[dataobj], "Data object not found")
+
+ return next, attributestorage[dataobj], nil
+ end
+
+ local ipairs_iter = ipairs(attributestorage)
+ function lib:ipairs(dataobject_or_name)
+ local t = type(dataobject_or_name)
+ assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
+
+ local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
+ assert(attributestorage[dataobj], "Data object not found")
+
+ return ipairs_iter, attributestorage[dataobj], 0
+ end
+end
diff --git a/lib/CallbackHandler-1.0/CallbackHandler-1.0.lua b/lib/CallbackHandler-1.0/CallbackHandler-1.0.lua
new file mode 100644
index 0000000..a8377fe
--- /dev/null
+++ b/lib/CallbackHandler-1.0/CallbackHandler-1.0.lua
@@ -0,0 +1,212 @@
+--[[ $Id: CallbackHandler-1.0.lua 1186 2018-07-21 14:19:18Z nevcairiel $ ]]
+local MAJOR, MINOR = "CallbackHandler-1.0", 7
+local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not CallbackHandler then return end -- No upgrade needed
+
+local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
+
+-- Lua APIs
+local tconcat = table.concat
+local assert, error, loadstring = assert, error, loadstring
+local setmetatable, rawset, rawget = setmetatable, rawset, rawget
+local next, select, pairs, type, tostring = next, select, pairs, type, tostring
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: geterrorhandler
+
+local xpcall = xpcall
+
+local function errorhandler(err)
+ return geterrorhandler()(err)
+end
+
+local function Dispatch(handlers, ...)
+ local index, method = next(handlers)
+ if not method then return end
+ repeat
+ xpcall(method, errorhandler, ...)
+ index, method = next(handlers, index)
+ until not method
+end
+
+--------------------------------------------------------------------------
+-- CallbackHandler:New
+--
+-- target - target object to embed public APIs in
+-- RegisterName - name of the callback registration API, default "RegisterCallback"
+-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback"
+-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
+
+function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName)
+
+ RegisterName = RegisterName or "RegisterCallback"
+ UnregisterName = UnregisterName or "UnregisterCallback"
+ if UnregisterAllName==nil then -- false is used to indicate "don't want this method"
+ UnregisterAllName = "UnregisterAllCallbacks"
+ end
+
+ -- we declare all objects and exported APIs inside this closure to quickly gain access
+ -- to e.g. function names, the "target" parameter, etc
+
+
+ -- Create the registry object
+ local events = setmetatable({}, meta)
+ local registry = { recurse=0, events=events }
+
+ -- registry:Fire() - fires the given event/message into the registry
+ function registry:Fire(eventname, ...)
+ if not rawget(events, eventname) or not next(events[eventname]) then return end
+ local oldrecurse = registry.recurse
+ registry.recurse = oldrecurse + 1
+
+ Dispatch(events[eventname], eventname, ...)
+
+ registry.recurse = oldrecurse
+
+ if registry.insertQueue and oldrecurse==0 then
+ -- Something in one of our callbacks wanted to register more callbacks; they got queued
+ for eventname,callbacks in pairs(registry.insertQueue) do
+ local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
+ for self,func in pairs(callbacks) do
+ events[eventname][self] = func
+ -- fire OnUsed callback?
+ if first and registry.OnUsed then
+ registry.OnUsed(registry, target, eventname)
+ first = nil
+ end
+ end
+ end
+ registry.insertQueue = nil
+ end
+ end
+
+ -- Registration of a callback, handles:
+ -- self["method"], leads to self["method"](self, ...)
+ -- self with function ref, leads to functionref(...)
+ -- "addonId" (instead of self) with function ref, leads to functionref(...)
+ -- all with an optional arg, which, if present, gets passed as first argument (after self if present)
+ target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
+ if type(eventname) ~= "string" then
+ error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
+ end
+
+ method = method or eventname
+
+ local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
+
+ if type(method) ~= "string" and type(method) ~= "function" then
+ error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
+ end
+
+ local regfunc
+
+ if type(method) == "string" then
+ -- self["method"] calling style
+ if type(self) ~= "table" then
+ error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
+ elseif self==target then
+ error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
+ elseif type(self[method]) ~= "function" then
+ error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
+ end
+
+ if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
+ local arg=select(1,...)
+ regfunc = function(...) self[method](self,arg,...) end
+ else
+ regfunc = function(...) self[method](self,...) end
+ end
+ else
+ -- function ref with self=object or self="addonId" or self=thread
+ if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
+ error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
+ end
+
+ if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
+ local arg=select(1,...)
+ regfunc = function(...) method(arg,...) end
+ else
+ regfunc = method
+ end
+ end
+
+
+ if events[eventname][self] or registry.recurse<1 then
+ -- if registry.recurse<1 then
+ -- we're overwriting an existing entry, or not currently recursing. just set it.
+ events[eventname][self] = regfunc
+ -- fire OnUsed callback?
+ if registry.OnUsed and first then
+ registry.OnUsed(registry, target, eventname)
+ end
+ else
+ -- we're currently processing a callback in this registry, so delay the registration of this new entry!
+ -- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
+ registry.insertQueue = registry.insertQueue or setmetatable({},meta)
+ registry.insertQueue[eventname][self] = regfunc
+ end
+ end
+
+ -- Unregister a callback
+ target[UnregisterName] = function(self, eventname)
+ if not self or self==target then
+ error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
+ end
+ if type(eventname) ~= "string" then
+ error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
+ end
+ if rawget(events, eventname) and events[eventname][self] then
+ events[eventname][self] = nil
+ -- Fire OnUnused callback?
+ if registry.OnUnused and not next(events[eventname]) then
+ registry.OnUnused(registry, target, eventname)
+ end
+ end
+ if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
+ registry.insertQueue[eventname][self] = nil
+ end
+ end
+
+ -- OPTIONAL: Unregister all callbacks for given selfs/addonIds
+ if UnregisterAllName then
+ target[UnregisterAllName] = function(...)
+ if select("#",...)<1 then
+ error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
+ end
+ if select("#",...)==1 and ...==target then
+ error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
+ end
+
+
+ for i=1,select("#",...) do
+ local self = select(i,...)
+ if registry.insertQueue then
+ for eventname, callbacks in pairs(registry.insertQueue) do
+ if callbacks[self] then
+ callbacks[self] = nil
+ end
+ end
+ end
+ for eventname, callbacks in pairs(events) do
+ if callbacks[self] then
+ callbacks[self] = nil
+ -- Fire OnUnused callback?
+ if registry.OnUnused and not next(callbacks) then
+ registry.OnUnused(registry, target, eventname)
+ end
+ end
+ end
+ end
+ end
+ end
+
+ return registry
+end
+
+
+-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
+-- try to upgrade old implicit embeds since the system is selfcontained and
+-- relies on closures to work.
+
diff --git a/lib/LibClassicDurations/LibClassicDurations.xml b/lib/LibClassicDurations/LibClassicDurations.xml
new file mode 100644
index 0000000..4934790
--- /dev/null
+++ b/lib/LibClassicDurations/LibClassicDurations.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/LibClassicDurations/classAbilities.lua b/lib/LibClassicDurations/classAbilities.lua
new file mode 100644
index 0000000..cdd8001
--- /dev/null
+++ b/lib/LibClassicDurations/classAbilities.lua
@@ -0,0 +1,1145 @@
+local lib = LibStub and LibStub("LibClassicDurations", true)
+if not lib then return end
+
+local Type, Version = "SpellTable", 71
+if lib:GetDataVersion(Type) >= Version then return end -- older versions didn't have that function
+
+local Spell = lib.AddAura
+local Talent = lib.Talent
+local INFINITY = math.huge
+
+local _, class = UnitClass("player")
+local locale = GetLocale()
+
+-- Temporary
+-- Erases Fire Vulnerability from the name to id table in case older version of the lib written it there
+if locale == "zhCN" then
+ lib.spellNameToID[GetSpellInfo(980)] = nil
+end
+if locale == "ruRU" then
+ lib.spellNameToID[GetSpellInfo(12721)] = nil -- Deep Wounds conflict with Rake on ruRU
+end
+
+-- https://github.com/rgd87/LibClassicDurations/issues/11
+lib.indirectRefreshSpells = {
+ [GetSpellInfo(11597)] = { -- Sunder Armor
+ [11597] = {
+ events = {
+ ["SPELL_CAST_SUCCESS"] = true
+ },
+ -- targetSpellID = 11597,
+ rollbackMisses = true,
+ }
+ },
+
+ [GetSpellInfo(25357)] = { -- Healing Wave
+ [29203] = {
+ events = {
+ ["SPELL_CAST_SUCCESS"] = true
+ },
+ -- targetSpellID = 29203, -- Healing Way
+ }
+ },
+}
+
+if class == "MAGE" then
+
+
+ lib.indirectRefreshSpells[GetSpellInfo(25304)] = { -- Frostbolt
+ [12579] = {
+ events = {
+ ["SPELL_DAMAGE"] = true
+ },
+ targetSpellID = 12579, -- Winter's Chill
+ rollbackMisses = true,
+ condition = function(isMine) return isMine end,
+ }
+ }
+
+ lib.indirectRefreshSpells[GetSpellInfo(10161)] = { -- Cone of Cold
+ [12579] = {
+ events = {
+ ["SPELL_DAMAGE"] = true
+ },
+ targetSpellID = 12579, -- Winter's Chill
+ rollbackMisses = true,
+ condition = function(isMine) return isMine end,
+ }
+ }
+
+ lib.indirectRefreshSpells[GetSpellInfo(10230)] = { -- Frost Nova
+ [12579] = {
+ events = {
+ ["SPELL_DAMAGE"] = true
+ },
+ targetSpellID = 12579, -- Winter's Chill
+ rollbackMisses = true,
+ condition = function(isMine) return isMine end,
+ }
+ }
+
+ -- Winter's Chill = Frostbolt
+ lib.indirectRefreshSpells[GetSpellInfo(12579)] = lib.indirectRefreshSpells[GetSpellInfo(25304)]
+
+ lib.indirectRefreshSpells[GetSpellInfo(10)] = { -- Blizzard
+ [12486] = {
+ events = {
+ ["SPELL_PERIODIC_DAMAGE"] = true
+ },
+ applyAura = true,
+ targetSpellID = 12486, -- Imp Blizzard
+ }
+ }
+
+ -- Ignite
+
+ lib.indirectRefreshSpells[GetSpellInfo(10207)] = { -- Scorch
+ [22959] = {
+ events = {
+ ["SPELL_DAMAGE"] = true
+ },
+ -- targetSpellID = 22959, -- Fire Vulnerability
+ rollbackMisses = true,
+ -- condition = function(isMine) return isMine end,
+ -- it'll refresg only from mages personal casts which is fine
+ -- because if mage doesn't have imp scorch then he won't even see a Fire Vulnerability timer
+ },
+ }
+
+ local fire_spells = {133, 10207, 2136, 2120, 11113} -- Fireball, Scorch, Fireblast, Flamestrike, Blast Wave
+
+ for _, spellId in ipairs(fire_spells) do
+ local spellName = GetSpellInfo(spellId)
+ if not lib.indirectRefreshSpells[spellName] then
+ lib.indirectRefreshSpells[spellName] = {}
+ end
+ lib.indirectRefreshSpells[spellName][12654] = {
+ events = {
+ ["SPELL_DAMAGE"] = true
+ },
+ -- targetSpellID = 12654, -- Ignite
+ rollbackMisses = true,
+ condition = function(isMine, isCrit) return isCrit end,
+ customAction = function(srcGUID, dstGUID, spellID)
+ local lib = LibStub("LibClassicDurations")
+ local spellTable = lib:GetSpellTable(srcGUID, dstGUID, spellID)
+ if spellTable and not spellTable.tickExtended then
+ local igniteStartTime = spellTable[2]
+ spellTable[2] = igniteStartTime + 2
+ spellTable.tickExtended = true
+ if lib.DEBUG_IGNITE then
+ print(GetTime(), "[Ignite] Extended", dstGUID, "New start time:", spellTable[2])
+ end
+ end
+ end,
+ }
+ end
+
+
+
+ lib.indirectRefreshSpells[GetSpellInfo(12654)] = CopyTable(lib.indirectRefreshSpells[GetSpellInfo(133)]) -- Just adding Ignite to indirectRefreshSpells table
+ lib.indirectRefreshSpells[GetSpellInfo(12654)][12654].events = {}
+end
+
+if class == "PRIEST" then
+ -- Shadow Weaving
+ lib.indirectRefreshSpells[GetSpellInfo(10894)] = { -- SW:Pain
+ [15258] = {
+ events = {
+ ["SPELL_AURA_APPLIED"] = true,
+ ["SPELL_AURA_REFRESH"] = true,
+ },
+ -- targetSpellID = 15258, -- Shadow Weaving
+ -- targetResistCheck = true,
+ rollbackMisses = true,
+ condition = function(isMine) return isMine end,
+ }
+ }
+ lib.indirectRefreshSpells[GetSpellInfo(10947)] = { -- Mind Blast
+ [15258] = {
+ events = {
+ ["SPELL_DAMAGE"] = true,
+ },
+ -- targetResistCheck = true,
+ rollbackMisses = true,
+ condition = function(isMine) return isMine end,
+ }
+ }
+ lib.indirectRefreshSpells[GetSpellInfo(18807)] = { -- Mind Flay
+ [15258] = {
+ events = {
+ ["SPELL_AURA_APPLIED"] = true,
+ ["SPELL_AURA_REFRESH"] = true,
+ },
+ rollbackMisses = true,
+ condition = function(isMine) return isMine end,
+ }
+ }
+
+ -- Shadow Weaving = SW: Pain
+ lib.indirectRefreshSpells[GetSpellInfo(15258)] = CopyTable(lib.indirectRefreshSpells[GetSpellInfo(10894)])
+ lib.indirectRefreshSpells[GetSpellInfo(15258)][15258].events = {}
+end
+
+------------------
+-- GLOBAL
+------------------
+
+-- World Buffs incl. Chronoboon IDs
+Spell(349981, { duration = INFINITY }) -- World effect suspended
+Spell({ 355363, 22888 }, { duration = 7200 }) -- Rallying Cry of the Dragonslayer
+Spell({ 355365, 24425 }, { duration = 7200 }) -- Spirit of Zandalar
+Spell({ 355366, 16609 }, { duration = 3600 }) -- Warchief's Blessing
+
+-- Atiesh Buffs
+Spell( 28142, { duration = INFINITY, type = "BUFF" }) -- Power of the Guardian
+Spell( 28143, { duration = INFINITY, type = "BUFF" }) -- Power of the Guardian
+Spell( 28144, { duration = INFINITY, type = "BUFF" }) -- Power of the Guardian
+Spell( 28145, { duration = INFINITY, type = "BUFF" }) -- Power of the Guardian
+
+Spell( 2479, { duration = 30 }) -- Honorless Target
+Spell(1604, { duration = 4 }) -- Common Daze
+Spell( 23605, { duration = 5 }) -- Nightfall (Axe) Proc
+Spell( 835, { duration = 3 }) -- Tidal Charm
+Spell( 11196, { duration = 60 }) -- Recently Bandaged
+Spell( 16928, { duration = 45 }) -- Armor Shatter, procced by Annihilator, axe weapon
+
+Spell({ 13099, 13138, 16566 }, {
+ duration = function(spellID)
+ if spellID == 13138 then return 20 -- backfire
+ elseif spellID == 16566 then return 30 -- backfire
+ else return 10 end
+ end
+}) -- Net-o-Matic
+
+Spell( 23451, { duration = 10 }) -- Battleground speed buff
+Spell( 23493, { duration = 10 }) -- Battleground heal buff
+Spell( 23505, { duration = 60 }) -- Battleground damage buff
+Spell({ 4068 }, { duration = 3 }) -- Iron Grenade
+Spell({ 19769 }, { duration = 3 }) -- Thorium Grenade
+Spell( 6615, { duration = 30, type = "BUFF", buffType = "Magic" }) -- Free Action Potion
+Spell( 24364, { duration = 5, type = "BUFF", buffType = "Magic" }) -- Living Action Potion
+Spell( 3169, { duration = 6, type = "BUFF", buffType = "Magic" }) -- Limited Invulnerability Potion
+Spell( 16621, { duration = 3, type = "BUFF" }) -- Invulnerable Mail
+Spell( 1090, { duration = 30 }) -- Magic Dust
+Spell( 13327, { duration = 30 }) -- Reckless Charge
+Spell({ 26740, 13181 }, { duration = 20 }) -- Mind Control Cap + Backfire
+Spell( 11359, { duration = 30, type = "BUFF" }) -- Restorative Potion
+Spell( 6727, { duration = 30 }) -- Violet Tragan
+Spell( 5024, { duration = 10, type = "BUFF" }) -- Skull of Impending Doom
+Spell( 2379, { duration = 15, type = "BUFF", buffType = "Magic" }) -- Swiftness Potion
+Spell( 5134, { duration = 10 }) -- Flash Bomb
+Spell( 23097, { duration = 5, type = "BUFF" }) -- Fire Reflector
+Spell( 23131, { duration = 5, type = "BUFF" }) -- Frost Reflector
+Spell( 23132, { duration = 5, type = "BUFF" }) -- Shadow Reflector
+Spell({ 25750, 25747, 25746, 23991 }, { duration = 15, type = "BUFF" }) -- AB Trinkets
+Spell( 23506, { duration = 20, type = "BUFF" }) -- Arena Grand Master trinket
+Spell( 29506, { duration = 20, type = "BUFF" }) -- Burrower's Shell trinket
+Spell( 12733, { duration = 30, type = "BUFF" }) -- Blacksmith trinket
+-- Spell( 15753, { duration = 2 }) -- Linken's Boomerang stun
+-- Spell( 15752, { duration = 10 }) -- Linken's Boomerang disarm
+Spell( 14530, { duration = 10, type = "BUFF" }) -- Nifty Stopwatch
+Spell( 13237, { duration = 3 }) -- Goblin Mortar trinket
+Spell( 21152, { duration = 3 }) -- Earthshaker, weapon proc
+Spell( 14253, { duration = 8, type = "BUFF" }) -- Black Husk Shield
+Spell( 9175, { duration = 15, type = "BUFF" }) -- Swift Boots
+Spell( 13141, { duration = 20, type = "BUFF" }) -- Gnomish Rocket Boots
+Spell( 8892, { duration = 20, type = "BUFF" }) -- Goblin Rocket Boots
+Spell( 9774, { duration = 5, type = "BUFF" }) -- Spider Belt & Ornate Mithril Boots
+Spell({ 746, 1159, 3267, 3268, 7926, 7927, 10838, 10839, 18608, 18610, 23567, 23568, 23569, 23696, 24412, 24413, 24414}, { duration = 8, type = "BUFF" }) -- First Aid
+Spell({ 21992, 27648 }, { duration = 12 }) -- Thunderfury, -Nature Resist, -Atk Spd
+
+
+-------------
+-- RACIALS
+-------------
+
+Spell( 26635 ,{ duration = 10, type = "BUFF" }) -- Berserking
+Spell( 20600 ,{ duration = 20, type = "BUFF" }) -- Perception
+Spell( 23234 ,{ duration = 15, type = "BUFF" }) -- Blood Fury
+Spell( 23230 ,{ duration = 25 }) -- Blood Fury debuff
+Spell( 20594 ,{ duration = 8, type = "BUFF" }) -- Stoneform
+Spell( 20549 ,{ duration = 2 }) -- War Stomp
+Spell( 7744, { duration = 5, type = "BUFF" }) -- Will of the Forsaken
+
+-------------
+-- PRIEST
+-------------
+
+Spell( 15473, { duration = INFINITY, type = "BUFF" }) -- Shadowform
+Spell( 14751, { duration = INFINITY, type = "BUFF", buffType = "Magic" }) -- Inner focus
+
+-- Why long auras are disabled
+-- When you first get in combat log range with a player,
+-- you'll get AURA_APPLIED event as if it was just applied, when it actually wasn't.
+-- That's extremely common for these long self-buffs
+-- Long raid buffs now have cast filter, that is only if you directly casted a spell it'll register
+-- Cast Filter is ignored for enemies, so some personal buffs have it to still show enemy buffs
+
+Spell({ 1243, 1244, 1245, 2791, 10937, 10938 }, { duration = 1800, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Power Word: Fortitude
+Spell({ 21562, 21564 }, { duration = 3600, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Prayer of Fortitude
+Spell({ 976, 10957, 10958 }, { duration = 600, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Shadow Protection
+Spell( 27683, { duration = 1200, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Prayer of Shadow Protection
+Spell({ 14752, 14818, 14819, 27841 }, { duration = 1800, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Divine Spirit
+Spell( 27681, { duration = 3600, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Prayer of Spirit
+
+Spell({ 588, 602, 1006, 7128, 10951, 10952 }, { duration = 600, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Inner Fire
+
+Spell({ 14743, 27828 }, { duration = 6, type = "BUFF", buffType = "Magic" }) -- Focused Casting (Martyrdom)
+Spell( 27827, { duration = 10, type = "BUFF" }) -- Spirit of Redemption
+Spell( 15271, { duration = 15, type = "BUFF" }) -- Spirit Tap
+
+Spell({ 2943, 19249, 19251, 19252, 19253, 19254 }, { duration = 120 }) -- Touch of Weakness Effect
+Spell({ 13896, 19271, 19273, 19274, 19275 }, { duration = 15, type = "BUFF" }) -- Feedback
+Spell({ 2651, 19289, 19291, 19292, 19293 }, { duration = 15, type = "BUFF" }) -- Elune's Grace
+Spell({ 9035, 19281, 19282, 19283, 19284, 19285 }, { duration = 120 }) -- Hex of Weakness
+
+Spell( 6346, { duration = 600, type = "BUFF", buffType = "Magic" }) -- Fear Ward
+Spell({ 14893, 15357 ,15359 }, { duration = 15, type = "BUFF", buffType = "Magic" }) -- Inspiration
+Spell({ 7001, 27873, 27874 }, { duration = 10, type = "BUFF", buffType = "Magic" }) -- Lightwell Renew
+Spell( 552, { duration = 20, type = "BUFF", buffType = "Magic" }) -- Abolish Disease
+Spell({ 17, 592, 600, 3747, 6065, 6066, 10898, 10899, 10900, 10901 }, {duration = 30, type = "BUFF", buffType = "Magic" }) -- PWS
+Spell( 6788, { duration = 15 }) -- Weakened Soul
+if class == "PRIEST" then
+ lib:TrackItemSet("Garments of the Oracle", { 21349, 21350, 21348, 21352, 21351 })
+ lib:RegisterSetBonusCallback("Garments of the Oracle", 5)
+end
+Spell({ 139, 6074, 6075, 6076, 6077, 6078, 10927, 10928, 10929, 25315 }, {
+ duration = function(spellID, isSrcPlayer)
+ if isSrcPlayer and lib:IsSetBonusActive("Garments of the Oracle", 5) then
+ return 18
+ else
+ return 15
+ end
+ end,
+ type = "BUFF", buffType = "Magic" }) -- Renew
+
+Spell( 15487, { duration = 5 }) -- Silence
+Spell({ 10797, 19296, 19299, 19302, 19303, 19304, 19305 }, { duration = 6, stacking = true }) -- starshards
+Spell({ 2944, 19276, 19277, 19278, 19279, 19280 }, { duration = 24, stacking = true }) --devouring plague
+Spell({ 453, 8192, 10953 }, { duration = 15 }) -- mind soothe
+
+Spell({ 9484, 9485, 10955 }, {
+ duration = function(spellID)
+ if spellID == 9484 then return 30
+ elseif spellID == 9485 then return 40
+ else return 50 end
+ end
+}) -- Shackle Undead
+
+Spell( 10060, { duration = 15, type = "BUFF", buffType = "Magic" }) --Power Infusion
+Spell({ 14914, 15261, 15262, 15263, 15264, 15265, 15266, 15267 }, { duration = 10, stacking = true }) -- Holy Fire, stacking?
+Spell({ 586, 9578, 9579, 9592, 10941, 10942 }, { duration = 10, type = "BUFF" }) -- Fade
+if class == "PRIEST" then
+ lib:TrackItemSet("PriestPvPSet", {
+ 17604, 17603, 17605, 17608, 17607, 17602,
+ 17623, 17625, 17622, 17624, 17618, 17620,
+ 22869, 22859, 22882, 22885, 23261, 23262,
+ 23302, 23303, 23288, 23289, 23316, 23317,
+ })
+ lib:RegisterSetBonusCallback("PriestPvPSet", 3)
+end
+Spell({ 8122, 8124, 10888, 10890 }, {
+ duration = function(spellID, isSrcPlayer)
+ if isSrcPlayer then
+ local pvpSetBonus = lib:IsSetBonusActive("PriestPvPSet", 3) and 1 or 0
+ return 8 + pvpSetBonus
+ else
+ return 8
+ end
+ end
+}) -- Psychic Scream
+Spell({ 589, 594, 970, 992, 2767, 10892, 10893, 10894 }, { stacking = true,
+ duration = function(spellID, isSrcPlayer)
+ -- Improved SWP, 2 ranks: Increases the duration of your Shadow Word: Pain spell by 3 sec.
+ local talents = isSrcPlayer and 3*Talent(15275, 15317) or 0
+ return 18 + talents
+ end
+}) -- SW:P
+Spell( 15269 ,{ duration = 3 }) -- Blackout
+
+if class == "PRIEST" then
+Spell( 15258 ,{
+ duration = function(spellID, isSrcPlayer)
+ -- Only SP himself can see the timer
+ if Talent(15257, 15331, 15332, 15333, 15334) > 0 then
+ return 15
+ else
+ return nil
+ end
+ end
+}) -- Shadow Weaving
+end
+
+Spell( 15286 ,{ duration = 60 }) -- Vampiric Embrace
+Spell({ 15407, 17311, 17312, 17313, 17314, 18807 }, { duration = 3 }) -- Mind Flay
+Spell({ 605, 10911, 10912 }, { duration = 60 }) -- Mind Control
+
+---------------
+-- DRUID
+---------------
+
+Spell( 768, { duration = INFINITY, type = "BUFF" }) -- Cat Form
+Spell( 783, { duration = INFINITY, type = "BUFF" }) -- Travel Form
+Spell( 5487, { duration = INFINITY, type = "BUFF" }) -- Bear Form
+Spell( 9634, { duration = INFINITY, type = "BUFF" }) -- Dire Bear Form
+Spell( 1066, { duration = INFINITY, type = "BUFF" }) -- Aquatic Form
+Spell( 24858, { duration = INFINITY, type = "BUFF" }) -- Moonkin Form
+Spell( 24932, { duration = INFINITY, type = "BUFF" }) -- Leader of the Pack
+Spell( 17116, { duration = INFINITY, type = "BUFF", buffType = "Magic" }) -- Nature's Swiftness
+
+Spell({ 1126, 5232, 5234, 6756, 8907, 9884, 9885 }, { duration = 1800, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Mark of the Wild
+Spell({ 21849, 21850 }, { duration = 3600, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Gift of the Wild
+Spell( 19975, { duration = 12, buffType = "Magic" }) -- Nature's Grasp root
+Spell({ 16689, 16810, 16811, 16812, 16813, 17329 }, { duration = 45, type = "BUFF", buffType = "Magic" }) -- Nature's Grasp
+Spell( 16864, { duration = 600, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Omen of Clarity
+Spell( 16870, { duration = 15, type = "BUFF", buffType = "Magic" }) -- Clearcasting from OoC
+
+
+
+Spell( 19675, { duration = 4 }) -- Feral Charge
+Spell({ 467, 782, 1075, 8914, 9756, 9910 }, { duration = 600, type = "BUFF", buffType = "Magic" }) -- Thorns
+Spell( 22812 ,{ duration = 15, type = "BUFF", buffType = "Magic" }) -- Barkskin
+--SKIPPING: Hurricane (Channeled)
+Spell({ 339, 1062, 5195, 5196, 9852, 9853 }, {
+ pvpduration = 20,
+ buffType = "Magic",
+ duration = function(spellID)
+ if spellID == 339 then return 12
+ elseif spellID == 1062 then return 15
+ elseif spellID == 5195 then return 18
+ elseif spellID == 5196 then return 21
+ elseif spellID == 9852 then return 24
+ else return 27 end
+ end
+}) -- Entangling Roots
+Spell({ 2908, 8955, 9901 }, { duration = 15 }) -- Soothe Animal
+Spell({ 770, 778, 9749, 9907 }, { duration = 40 }) -- Faerie Fire
+Spell({ 16857, 17390, 17391, 17392 }, { duration = 40 }) -- Faerie Fire (Feral)
+Spell({ 2637, 18657, 18658 }, {
+ pvpduration = 20,
+ duration = function(spellID)
+ if spellID == 2637 then return 20
+ elseif spellID == 18657 then return 30
+ else return 40 end
+ end
+}) -- Hibernate
+Spell({ 99, 1735, 9490, 9747, 9898 }, { duration = 30 }) -- Demoralizing Roar
+Spell({ 5211, 6798, 8983 }, { stacking = true, -- stacking?
+ duration = function(spellID)
+ local brutal_impact = Talent(16940, 16941)*0.5
+ if spellID == 5211 then return 2+brutal_impact
+ elseif spellID == 6798 then return 3+brutal_impact
+ else return 4+brutal_impact end
+ end
+}) -- Bash
+Spell( 5209, { duration = 6 }) -- Challenging Roar
+Spell( 6795, { duration = 3, stacking = true }) -- Taunt
+
+Spell({ 1850, 9821 }, { duration = 15, type = "BUFF" }) -- Dash
+Spell( 5229, { duration = 10, type = "BUFF" }) -- Enrage
+Spell({ 22842, 22895, 22896 }, { duration = 10, type = "BUFF" }) -- Frenzied Regeneration
+Spell( 16922, { duration = 3 }) -- Imp Starfire Stun
+
+Spell({ 9005, 9823, 9827 }, { -- Pounce stun doesn't create a debuff icon, so this is not going to be used
+ duration = function(spellID)
+ local brutal_impact = Talent(16940, 16941)*0.5
+ return 2+brutal_impact
+ end
+}) -- Pounce
+Spell({ 9007, 9824, 9826 }, { duration = 18, stacking = true, }) -- Pounce Bleed
+Spell({ 8921, 8924, 8925, 8926, 8927, 8928, 8929, 9833, 9834, 9835 }, { stacking = true,
+ duration = function(spellID)
+ if spellID == 8921 then return 9
+ else return 12 end
+ end
+}) -- Moonfire
+Spell({ 1822, 1823, 1824, 9904 }, { duration = 9, stacking = true }) -- Rake
+Spell({ 1079, 9492, 9493, 9752, 9894, 9896 }, { duration = 12, stacking = true }) -- Rip
+Spell({ 5217, 6793, 9845, 9846 }, { name = "Tiger's Fury", duration = 6 })
+
+Spell( 2893 ,{ duration = 8, type = "BUFF", buffType = "Magic" }) -- Abolish Poison
+Spell( 29166 , { duration = 20, type = "BUFF", buffType = "Magic" }) -- Innervate
+
+Spell({ 8936, 8938, 8939, 8940, 8941, 9750, 9856, 9857, 9858 }, { duration = 21, type = "BUFF", buffType = "Magic" }) -- Regrowth
+
+if class == "DRUID" then
+ lib:TrackItemSet("StormrageRaiment", { 16899, 16900, 16901, 16902, 16903, 16904, 16897, 16898, })
+ lib:RegisterSetBonusCallback("StormrageRaiment", 8)
+end
+Spell({ 774, 1058, 1430, 2090, 2091, 3627, 8910, 9839, 9840, 9841, 25299 }, {
+ duration = function(spellID, isSrcPlayer)
+ if isSrcPlayer and lib:IsSetBonusActive("StormrageRaiment", 8) then
+ return 15
+ else
+ return 12
+ end
+ end,
+ stacking = false, type = "BUFF", buffType = "Magic" }) -- Rejuv
+Spell({ 5570, 24974, 24975, 24976, 24977 }, { duration = 12, stacking = true }) -- Insect Swarm
+
+-------------
+-- WARRIOR
+-------------
+
+Spell( 2457 , { duration = INFINITY, type = "BUFF" }) -- Battle Stance
+Spell( 2458 , { duration = INFINITY, type = "BUFF" }) -- Berserker Stance
+Spell( 71 , { duration = INFINITY, type = "BUFF" }) -- Def Stance
+
+Spell({ 12294, 21551, 21552, 21553 }, { duration = 10 }) -- Mortal Strike Healing Reduction
+
+Spell({72, 1671, 1672}, { duration = 6 }) -- Shield Bash
+Spell( 18498, { duration = 3 }) -- Improved Shield Bash
+
+Spell( 20230, { duration = 15, type = "BUFF" }) -- Retaliation
+Spell( 1719, { duration = 15, type = "BUFF" }) -- Recklessness
+Spell( 871, { type = "BUFF", duration = 10 }) -- Shield wall, varies
+Spell( 12976, { duration = 20, type = "BUFF" }) -- Last Stand
+Spell( 12328, { duration = 30 }) -- Death Wish
+Spell({ 772, 6546, 6547, 6548, 11572, 11573, 11574 }, { stacking = true,
+ duration = function(spellID)
+ if spellID == 772 then return 9
+ elseif spellID == 6546 then return 12
+ elseif spellID == 6547 then return 15
+ elseif spellID == 6548 then return 18
+ else return 21 end
+ end
+}) -- Rend
+if locale ~= "ruRU" or class ~= "DRUID" then
+Spell( 12721, { duration = 12, stacking = true }) -- Deep Wounds
+end
+
+Spell({ 1715, 7372, 7373 }, { duration = 15 }) -- Hamstring
+Spell( 23694 , { duration = 5 }) -- Improved Hamstring
+Spell({ 6343, 8198, 8204, 8205, 11580, 11581 }, {
+ duration = function(spellID)
+ if spellID == 6343 then return 10
+ elseif spellID == 8198 then return 14
+ elseif spellID == 8204 then return 18
+ elseif spellID == 8205 then return 22
+ elseif spellID == 11580 then return 26
+ else return 30 end
+ end
+}) -- Thunder Clap
+Spell({ 694, 7400, 7402, 20559, 20560 }, { duration = 6 }) -- Mocking Blow
+Spell( 1161 ,{ duration = 6 }) -- Challenging Shout
+Spell( 355 ,{ duration = 3, stacking = true }) -- Taunt
+Spell({ 5242, 6192, 6673, 11549, 11550, 11551, 25289 }, { type = "BUFF",
+ duration = function(spellID, isSrcPlayer)
+ local talents = isSrcPlayer and Talent(12321, 12835, 12836, 12837, 12838) or 0
+ return 120 * (1 + 0.1 * talents)
+ end
+}) -- Battle Shout
+Spell({ 1160, 6190, 11554, 11555, 11556 }, {
+ duration = function(spellID, isSrcPlayer)
+ local talents = isSrcPlayer and Talent(12321, 12835, 12836, 12837, 12838) or 0
+ return 30 * (1 + 0.1 * talents)
+ end
+}) -- Demoralizing Shout, varies
+Spell( 18499, { duration = 10, type = "BUFF" }) -- Berserker Rage
+Spell({ 20253, 20614, 20615 }, { duration = 3 }) -- Intercept
+Spell( 12323, { duration = 6 }) -- Piercing Howl
+Spell( 5246, { duration = 8 }) -- Intimidating Shout Fear
+Spell( 20511, { duration = 8 }) -- Intimidating Shout Main Target Cower Effect
+
+Spell( 676 ,{
+ duration = function(spellID, isSrcPlayer)
+ local talents = isSrcPlayer and Talent(12313, 12804, 12807) or 0
+ return 10 + talents
+ end,
+}) -- Disarm, varies
+Spell( 29131 ,{ duration = 10, type = "BUFF" }) -- Bloodrage
+Spell( 12798 , { duration = 3 }) -- Imp Revenge Stun
+Spell( 2565 ,{ duration = 5, type = "BUFF" }) -- Shield Block, varies BUFF
+
+Spell({ 7386, 7405, 8380, 11596, 11597 }, { duration = 30 }) -- Sunder Armor
+Spell( 12809 ,{ duration = 5 }) -- Concussion Blow
+Spell( 12292 ,{ duration = 20, type = "BUFF" }) -- Sweeping Strikes
+Spell({ 12880, 14201, 14202, 14203, 14204 }, { duration = 12, type = "BUFF" }) -- Enrage
+Spell({ 12966, 12967, 12968, 12969, 12970 }, { duration = 15, type = "BUFF" }) -- Flurry
+Spell({ 16488, 16490, 16491 }, { duration = 6, type = "BUFF" }) -- Blood Craze
+Spell({ 23885, 23886, 23887, 23888 }, { duration = 6, type = "BUFF" }) -- Bloodthirst
+Spell(7922, { duration = 1 }) -- Charge
+Spell(5530, { duration = 3 }) -- Mace Specialization
+
+--------------
+-- ROGUE
+--------------
+
+Spell( 14177 , { duration = INFINITY, type = "BUFF" }) -- Cold Blood
+Spell({ 1784, 1785, 1786, 1787 } , { duration = INFINITY, type = "BUFF" }) -- Stealth
+
+Spell( 14278 , { duration = 7, type = "BUFF" }) -- Ghostly Strike
+Spell({ 16511, 17347, 17348 }, { duration = 15 }) -- Hemorrhage
+Spell({ 11327, 11329 }, { duration = 10 }) -- Vanish
+Spell({ 3409, 11201 }, { duration = 12 }) -- Crippling Poison
+-- Spell({ 13218, 13222, 13223, 13224 }, { duration = 15 }) -- Wound Poison
+-- Spell({ 2818, 2819, 11353, 11354, 25349 }, { duration = 12, stacking = true }) -- Deadly Poison
+Spell({ 5760, 8692, 11398 }, {
+ duration = function(spellID)
+ if spellID == 5760 then return 10
+ elseif spellID == 8692 then return 12
+ else return 14 end
+ end
+}) -- Mind-numbing Poison
+
+Spell( 18425, { duration = 2 }) -- Improved Kick Silence
+Spell( 13750, { duration = 15, type = "BUFF" }) -- Adrenaline Rush
+Spell( 13877, { duration = 15, type = "BUFF" }) -- Blade Flurry
+Spell( 1833, { duration = 4 }) -- Cheap Shot
+Spell({ 2070, 6770, 11297 }, {
+ pvpduration = 20,
+ duration = function(spellID)
+ if spellID == 6770 then return 25 -- yes, Rank 1 spell id is 6770 actually
+ elseif spellID == 2070 then return 35
+ else return 45 end
+ end
+}) -- Sap
+Spell( 2094 , { duration = 10 }) -- Blind
+
+Spell({ 8647, 8649, 8650, 11197, 11198 }, { duration = 30 }) -- Expose Armor
+Spell({ 703, 8631, 8632, 8633, 11289, 11290 }, { duration = 18 }) -- Garrote
+
+Spell({ 408, 8643 }, {
+ duration = function(spellID, isSrcPlayer, comboPoints)
+ local duration = spellID == 8643 and 1 or 0 -- if Rank 2, add 1s
+ if isSrcPlayer then
+ return duration + comboPoints
+ else
+ return duration + 5 -- just assume 5cp i guess
+ end
+ end
+}) -- Kidney Shot
+
+Spell({ 1943, 8639, 8640, 11273, 11274, 11275 }, { stacking = true,
+ duration = function(spellID, isSrcPlayer, comboPoints)
+ if isSrcPlayer then
+ return (6 + comboPoints*2)
+ else
+ return 16
+ end
+ end
+}) -- Rupture
+
+Spell({ 5171, 6774 }, { duration = nil, type = "BUFF" }) -- SnD, to prevent fallback to incorrect db values
+
+Spell({ 2983, 8696, 11305 }, { duration = 15, type = "BUFF" }) -- Sprint
+Spell( 5277 ,{ duration = 15, type = "BUFF" }) -- Evasion
+Spell({ 1776, 1777, 8629, 11285, 11286 }, {
+ duration = function(spellID, isSrcPlayer)
+ if isSrcPlayer then
+ return 4 + 0.5*Talent(13741, 13793, 13792)
+ else
+ return 5.5
+ end
+ end
+}) -- Gouge
+
+Spell( 14251 , { duration = 6 }) -- Riposte (disarm)
+
+------------
+-- WARLOCK
+------------
+
+Spell({ 20707, 20762, 20763, 20764, 20765 }, { duration = 1800, type = "BUFF" }) -- Soulstone Resurrection
+Spell({ 687, 696 }, { duration = 1800, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Demon SKin
+Spell({ 706, 1086, 11733, 11734, 11735 }, { duration = 1800, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Demon Armor
+Spell({ 18791 }, { duration = 1800, type = "BUFF", castFilter = true }) -- Touch of Shadow
+Spell({ 18789 }, { duration = 1800, type = "BUFF", castFilter = true }) -- Burning Wish
+Spell({ 18792 }, { duration = 1800, type = "BUFF", castFilter = true }) -- Fel Energy
+Spell({ 18790 }, { duration = 1800, type = "BUFF", castFilter = true }) -- Fel Stamina
+
+--SKIPPING: Drain Life, Mana, Soul, Enslave, Health funnel, kilrog
+Spell( 24259 ,{ duration = 3 }) -- Spell Lock Silence
+Spell({ 17767, 17850, 17851, 17852, 17853, 17854 }, { duration = 10 }) -- Consume Shadows (Voidwalker)
+Spell( 18118, { duration = 5 }) -- Aftermath Proc
+Spell({ 132, 2970, 11743 }, { duration = 600 }) -- Detect Invisibility
+Spell( 5697, { duration = 600 }) -- Unending Breath
+if class == "WARLOCK" then
+ Spell({ 17794, 17798, 17797, 17799, 17800 }, { duration = 12 }) -- Shadow Vulnerability (Imp Shadow Bolt)
+end
+Spell({ 18288 }, { duration = 1800, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Amplify Curse
+Spell({ 1714, 11719 }, { duration = 30 }) -- Curse of Tongues
+Spell({ 702, 1108, 6205, 7646, 11707, 11708 },{ duration = 120 }) -- Curse of Weakness
+Spell({ 17862, 17937 }, { duration = 300 }) -- Curse of Shadows
+Spell({ 1490, 11721, 11722 }, { duration = 300 }) -- Curse of Elements
+Spell({ 704, 7658, 7659, 11717 }, { duration = 120 }) -- Curse of Recklessness
+Spell( 603 ,{ duration = 60, stacking = true }) -- Curse of Doom
+Spell( 18223 ,{ duration = 12 }) -- Curse of Exhaustion
+Spell( 6358, {
+ duration = function(spellID, isSrcPlayer)
+ if isSrcPlayer then
+ local mul = 1 + Talent(18754, 18755, 18756)*0.1
+ return 15*mul
+ else
+ return 15
+ end
+ end
+}) -- Seduction, varies, Improved Succubus
+Spell({ 5484, 17928 }, {
+ duration = function(spellID)
+ return spellID == 5484 and 10 or 15
+ end
+}) -- Howl of Terror
+Spell({ 5782, 6213, 6215 }, {
+ pvpduration = 20,
+ duration = function(spellID)
+ if spellID == 5782 then return 10
+ elseif spellID == 6213 then return 15
+ else return 20 end
+ end
+}) -- Fear
+
+Spell({ 710, 18647 }, {
+ duration = function(spellID)
+ return spellID == 710 and 20 or 30
+ end
+}) -- Banish
+Spell({ 6789, 17925, 17926 }, { duration = 3 }) -- Death Coil
+Spell({ 6307, 7804, 7805, 11766, 11767 }, { duration = INFINITY }) -- Blood Pact
+Spell({ 18708 }, { duration = 15, type = "BUFF", buffType = "Magic" }) -- Fel Domination
+Spell({ 19480 }, { duration = INFINITY }) -- Paranoia
+Spell({ 25228 }, { duration = INFINITY, type = "BUFF", buffType = "Magic" }) -- Soul Link
+Spell({ 23829 }, { duration = INFINITY, type = "BUFF" }) -- Master Demonologist
+Spell({ 18265, 18879, 18880, 18881}, { duration = 30, stacking = true }) -- Siphon Life
+
+if locale ~= "zhCN" or class ~= "MAGE" then
+Spell({ 980, 1014, 6217, 11711, 11712, 11713 }, { duration = 24, stacking = true }) -- Curse of Agony
+end
+
+Spell({ 172, 6222, 6223, 7648, 11671, 11672, 25311 }, { stacking = true,
+ duration = function(spellID)
+ if spellID == 172 then
+ return 12
+ elseif spellID == 6222 then
+ return 15
+ else
+ return 18
+ end
+ end
+})
+Spell({ 348, 707, 1094, 2941, 11665, 11667, 11668, 25309 },{ duration = 15, stacking = true }) -- Immolate
+
+Spell({ 6229, 11739, 11740, 28610 } ,{ duration = 30, type = "BUFF", buffType = "Magic" }) -- Shadow Ward
+Spell({ 7812, 19438, 19440, 19441, 19442, 19443 }, { duration = 30, type = "BUFF", buffType = "Magic" }) -- Sacrifice
+Spell({ 17877, 18867, 18868, 18869, 18870, 18871 }, { duration = 5 }) -- Shadowburn Debuff
+Spell( 18093 ,{ duration = 3 }) -- Pyroclasm
+
+---------------
+-- SHAMAN
+---------------
+
+Spell({ 8185, 10534, 10535 }, { duration = INFINITY, type = "BUFF" }) -- Fire Resistance Totem
+Spell({ 8182, 10476, 10477 }, { duration = INFINITY, type = "BUFF" }) -- Frost Resistance Totem
+Spell({ 10596, 10598, 10599 }, { duration = INFINITY, type = "BUFF" }) -- Nature Resistance Totem
+Spell( 25909, { duration = INFINITY, type = "BUFF" }) -- Tranquil Air Totem
+Spell({ 5672, 6371, 6372, 10460, 10461 }, { duration = INFINITY, type = "BUFF" }) -- Healing Stream Totem
+Spell({ 5677, 10491, 10493, 10494 }, { duration = INFINITY, type = "BUFF" }) -- Mana Spring Totem
+Spell({ 8076, 8162, 8163, 10441, 25362 }, { duration = INFINITY, type = "BUFF" }) -- Strength of Earth Totem
+Spell({ 8836, 10626, 25360 }, { duration = INFINITY, type = "BUFF" }) -- Grace of Air Totem
+Spell({ 8072, 8156, 8157, 10403, 10404, 10405 }, { duration = INFINITY, type = "BUFF" }) -- Stoneskin Totem
+Spell({ 16191, 17355, 17360 }, { duration = 12, type = "BUFF" }) -- Mana Tide Totem
+Spell( 16166, { duration = INFINITY, type = "BUFF" }) -- Elemental Mastery
+
+Spell( 8178 ,{ duration = 45, type = "BUFF" }) -- Grounding Totem Effect, no duration, but lasts 45s. Keeping for enemy buffs
+
+-- Using Druid's NS
+-- Spell( 16188, { duration = INFINITY, type = "BUFF" }) -- Nature's Swiftness
+
+Spell({ 324, 325, 905, 945, 8134, 10431, 10432 }, { duration = 600, type = "BUFF", buffType = "Magic" }) -- Lightning Shield
+Spell( 546 ,{ duration = 600, type = "BUFF", buffType = "Magic" }) -- Water Walking
+Spell( 131 ,{ duration = 600, type = "BUFF", buffType = "Magic" }) -- Water Breahing
+Spell({ 16257, 16277, 16278, 16279, 16280 }, { duration = 15, type = "BUFF" }) -- Flurry
+
+Spell( 17364 ,{ duration = 12 }) -- Stormstrike
+Spell({ 16177, 16236, 16237 }, { duration = 15, type = "BUFF", buffType = "Magic" }) -- Ancestral Fortitude from Ancestral Healing
+Spell({ 8056, 8058, 10472, 10473 }, { duration = 8 }) -- Frost Shock
+Spell({ 8050, 8052, 8053, 10447, 10448, 29228 }, { duration = 12, stacking = true }) -- Flame Shock
+Spell( 29203 ,{ duration = 15, type = "BUFF", buffType = "Magic" }) -- Healing Way
+Spell({ 8034, 8037, 10458, 16352, 16353 }, { duration = 8 }) -- Frostbrand Attack
+Spell( 3600 ,{ duration = 5 }) -- Earthbind Totem
+
+--------------
+-- PALADIN
+--------------
+
+Spell( 19746, { duration = INFINITY, type = "BUFF" }) -- Concentration Aura
+Spell({ 465, 643, 1032, 10290, 10291, 10292, 10293 }, { duration = INFINITY, type = "BUFF" }) -- Devotion Aura
+Spell({ 19891, 19899, 19900 }, { duration = INFINITY, type = "BUFF" }) -- Fire Resistance Aura
+Spell({ 19888, 19897, 19898 }, { duration = INFINITY, type = "BUFF" }) -- Frost Resistance Aura
+Spell({ 19876, 19895, 19896 }, { duration = INFINITY, type = "BUFF" }) -- Shadow Resistance Aura
+Spell({ 7294, 10298, 10299, 10300, 10301 }, { duration = INFINITY, type = "BUFF" }) -- Retribution Aura
+Spell({ 20218 }, { duration = INFINITY, type = "BUFF" }) -- Sanctity Aura
+
+
+Spell( 25780, { duration = 1800, type = "BUFF", buffType = "Magic" }) -- Righteous Fury
+
+Spell({ 19740, 19834, 19835, 19836, 19837, 19838, 25291 }, { duration = 300, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Blessing of Might
+Spell({ 25782, 25916 }, { duration = 900, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Greater Blessing of Might
+
+Spell({ 19742, 19850, 19852, 19853, 19854, 25290 }, { duration = 300, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Blessing of Wisdom
+Spell({ 25894, 25918 }, { duration = 900, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Greater Blessing of Might
+
+Spell(20217, { duration = 300, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Blessing of Kings
+Spell(25898, { duration = 900, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Greater Blessing of Kings
+
+Spell({ 20911, 20912, 20913 }, { duration = 300, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Blessing of Sanctuary
+Spell(25899, { duration = 900, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Greater Blessing of Sanctuary
+
+Spell(1038, { duration = 300, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Blessing of Salvation
+Spell(25895, { duration = 900, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Greater Blessing of Salvation
+
+Spell({ 19977, 19978, 19979 }, { duration = 300, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Blessing of Light
+Spell(25890, { duration = 900, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Greater Blessing of Light
+
+Spell( 20066, { duration = 6 }) -- Repentance
+Spell({ 2878, 5627, 5627 }, {
+ duration = function(spellID)
+ if spellID == 2878 then return 10
+ elseif spellID == 5627 then return 15
+ else return 20 end
+ end
+}) -- Turn Undead
+
+Spell( 1044, {
+ duration = function(spellID, isSrcPlayer)
+ local talents = 0
+ if isSrcPlayer then talents = 3*Talent(20174, 20175) end
+ return 10 + talents
+ end, type = "BUFF", buffType = "Magic" }) -- Blessing of Freedom
+Spell({ 6940, 20729 }, { duration = 30, type = "BUFF", buffType = "Magic" }) -- Blessing of Sacrifice
+Spell({ 1022, 5599, 10278 }, { type = "BUFF",
+ buffType = "Magic",
+ duration = function(spellID)
+ if spellID == 1022 then return 6
+ elseif spellID == 5599 then return 8
+ else return 10 end
+ end
+}) -- Blessing of Protection
+Spell(25771, { duration = 60 }) -- Forbearance
+Spell({ 498, 5573 }, { type = "BUFF",
+ duration = function(spellID)
+ return spellID == 498 and 6 or 8
+ end
+}) -- Divine Protection
+Spell({ 642, 1020 }, { type = "BUFF",
+ duration = function(spellID)
+ return spellID == 642 and 10 or 12
+ end
+}) -- Divine Shield
+Spell({ 20375, 20915, 20918, 20919, 20920 }, { duration = 30, type = "BUFF", buffType = "Magic" }) -- Seal of Command
+Spell({ 21084, 20287, 20288, 20289, 20290, 20291, 20292, 20293 }, { duration = 30, type = "BUFF", buffType = "Magic" }) -- Seal of Righteousness
+Spell({ 20162, 20305, 20306, 20307, 20308, 21082 }, { duration = 30, type = "BUFF", buffType = "Magic" }) -- Seal of the Crusader
+Spell({ 20165, 20347, 20348, 20349 }, { duration = 30, type = "BUFF", buffType = "Magic" }) -- Seal of Light
+Spell({ 20166, 20356, 20357 }, { duration = 30, type = "BUFF", buffType = "Magic" }) -- Seal of Wisdom
+Spell( 20164 , { duration = 30, type = "BUFF", buffType = "Magic" }) -- Seal of Justice
+
+Spell({ 21183, 20188, 20300, 20301, 20302, 20303 }, { duration = 10 }) -- Judgement of the Crusader
+Spell({ 20185, 20344, 20345, 20346 }, {
+ duration = function(spellID, isSrcPlayer)
+ if isSrcPlayer then
+ local talents = 10*Talent(20359, 20360, 20361)
+ return 10+talents
+ else
+ return 10
+ end
+ end
+}) -- Judgement of Light
+Spell({ 20186, 20354, 20355 }, {
+ duration = function(spellID, isSrcPlayer)
+ if isSrcPlayer then
+ local talents = 10*Talent(20359, 20360, 20361)
+ return 10+talents
+ else
+ return 10
+ end
+ end
+}) -- Judgement of Wisdom
+Spell(20184, { duration = 10 }) -- Judgement of Justice
+
+Spell({ 853, 5588, 5589, 10308 }, {
+ duration = function(spellID)
+ if spellID == 853 then return 3
+ elseif spellID == 5588 then return 4
+ elseif spellID == 5589 then return 5
+ else return 6 end
+ end
+}) -- Hammer of Justice
+
+Spell({ 20925, 20927, 20928 }, { duration = 10, type = "BUFF", buffType = "Magic" }) -- Holy Shield
+Spell({ 20128, 20131, 20132, 20133, 20134 }, { duration = 10, type = "BUFF" }) -- Redoubt
+Spell({ 67, 26017, 26018 }, { duration = 10, type = "BUFF", buffType = "Magic" }) -- Vindication
+Spell({ 20050, 20052, 20053, 20054, 20055 }, { duration = 8, type = "BUFF", buffType = "Magic" }) -- Vengeance
+Spell( 20170 ,{ duration = 2 }) -- Seal of Justice stun
+
+-------------
+-- HUNTER
+-------------
+
+Spell( 13161, { duration = INFINITY, type = "BUFF" }) -- Aspect of the Beast
+Spell( 5118, { duration = INFINITY, type = "BUFF" }) -- Aspect of the Cheetah
+Spell( 13159, { duration = INFINITY, type = "BUFF" }) -- Aspect of the Pack
+Spell( 13163, { duration = INFINITY, type = "BUFF" }) -- Aspect of the Monkey
+Spell({ 20043, 20190 }, { duration = INFINITY, type = "BUFF" }) -- Aspect of the Wild
+Spell({ 13165, 14318, 14319, 14320, 14321, 14322, 25296 }, { duration = INFINITY, type = "BUFF" }) -- Aspect of the Hawk
+Spell( 5384, { duration = INFINITY, type = "BUFF" }) -- Feign Death (Will it work?)
+Spell({ 19579, 24529 }, { duration = INFINITY, type = "BUFF" }) -- Spirit Bond
+
+Spell({ 19506, 20905, 20906 }, { duration = 1800, type = "BUFF", castFilter = true }) -- Trueshot Aura
+Spell(19615, { duration = 8, type = "BUFF" }) -- Frenzy
+Spell({ 1130, 14323, 14324, 14325 }, { duration = 120 }) -- Hunter's Mark
+Spell(19263, { duration = 10, type = "BUFF" }) -- Deterrence
+Spell(3045, { duration = 15, type = "BUFF" }) -- Rapid Fire
+Spell(19574, { duration = 18, type = "BUFF" }) -- Bestial Wrath
+Spell({ 1978, 13549, 13550, 13551, 13552, 13553, 13554, 13555, 25295 }, { duration = 15, stacking = true }) -- Serpent Sting
+Spell({ 3043, 14275, 14276, 14277 }, { duration = 20 }) -- Scorpid Sting
+Spell({ 3034, 14279, 14280 }, { duration = 8 }) -- Viper Sting
+Spell({ 19386, 24132, 24133 }, { duration = 12 }) -- Wyvern Sting
+Spell({ 24131, 24134, 24135 }, { duration = 12 }) -- Wyvern Sting Dot
+Spell({ 1513, 14326, 14327 }, {
+ pvpduration = 20,
+ duration = function(spellID)
+ if spellID == 1513 then return 10
+ elseif spellID == 14326 then return 15
+ else return 20 end
+ end
+}) -- Scare Beast
+
+Spell(19229, { duration = 5 }) -- Wing Clip Root
+Spell({ 19306, 20909, 20910 }, { duration = 5 }) -- Counterattack
+-- Spell({ 13812, 14314, 14315 }, { duration = 20, stacking = true }) -- Explosive Trap
+Spell({ 13797, 14298, 14299, 14300, 14301 }, { duration = 15, stacking = true }) -- Immolation Trap
+Spell({ 3355, 14308, 14309 }, {
+ pvpduration = 20,
+ duration = function(spellID, isSrcPlayer)
+ local mul = 1
+ if isSrcPlayer then
+ mul = mul + 0.15*Talent(19239, 19245) -- Clever Traps
+ end
+ if spellID == 3355 then return 10*mul
+ elseif spellID == 14308 then return 15*mul
+ else return 20*mul end
+ end
+}) -- Freezing Trap
+Spell(19503, { duration = 4 }) -- Scatter Shot
+Spell({ 2974, 14267, 14268 }, { duration = 10 }) -- Wing Clip
+Spell(5116, { duration = 4 }) -- Concussive Shot
+Spell(19410, { duration = 3 }) -- Conc Stun
+Spell(24394, { duration = 3 }) -- Intimidation
+-- Spell(15571, { duration = 4 }) -- Daze from Aspect
+Spell(19185, { duration = 5 }) -- Entrapment
+Spell(25999, { duration = 1 }) -- Boar Charge
+Spell({ 23099, 23109, 23110 } , { duration = 15 }) -- Dash
+Spell(1002, { duration = 60 }) -- Eye of the Beast
+Spell(1539, { duration = 20 }) -- Feed Pet Effect
+Spell({ 136, 3111, 3661, 3662, 13542, 13543, 13544 }, { duration = 5, type = "BUFF" }) -- Mend Pet
+
+-------------
+-- MAGE
+-------------
+
+Spell( 12043, { duration = INFINITY, type = "BUFF", buffType = "Magic" }) -- Presence of Mind
+
+Spell({ 1459, 1460, 1461, 10156, 10157 }, { duration = 1800, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Arcane Intellect
+Spell( 23028, { duration = 3600, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Arcane Brilliance
+Spell({ 6117, 22782, 22783 }, { duration = 1800, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Mage Armor
+Spell({ 168, 7300, 7301 }, { duration = 1800, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Frost Armor
+Spell({ 7302, 7320, 10219, 10220 }, { duration = 1800, type = "BUFF", castFilter = true, buffType = "Magic" }) -- Ice Armor
+
+Spell( 2855, { duration = 120, type = "BUFF", buffType = "Magic" }) -- Detect Magic
+Spell( 130, { duration = 1800, type = "BUFF", buffType = "Magic" }) -- Slow Fall
+
+Spell({ 133, 143, 145, 3140, 8400, 8401, 8402, 10148, 10149, 10150, 10151, 25306 }, {
+ stacking = true,
+ duration = function(spellID)
+ if spellID == 133 then return 4
+ elseif spellID == 143 then return 6
+ elseif spellID == 145 then return 6
+ else return 8 end
+ end
+}) -- Fireball
+Spell({ 11366, 12505, 12522, 12523, 12524, 12525, 12526, 18809 }, { duration = 12, stacking = true }) -- Pyroblast
+
+Spell({ 604, 8450, 8451, 10173, 10174 }, { duration = 600, type = "BUFF", buffType = "Magic" }) -- Dampen Magic
+Spell({ 1008, 8455, 10169, 10170 }, { duration = 600, type = "BUFF", buffType = "Magic" }) -- Amplify Magic
+
+Spell(18469, { duration = 4 }) -- Imp CS Silence
+Spell({ 118, 12824, 12825, 12826, 28270, 28271, 28272 }, {
+ pvpduration = 20,
+ duration = function(spellID)
+ if spellID == 118 then return 20
+ elseif spellID == 12824 then return 30
+ elseif spellID == 12825 then return 40
+ else return 50 end
+ end
+}) -- Polymorph
+Spell(11958, { duration = 10, type = "BUFF" }) -- Ice Block
+Spell({ 1463, 8494, 8495, 10191, 10192, 10193 }, { duration = 60, type = "BUFF", buffType = "Magic" }) -- Mana Shield
+Spell({ 11426, 13031, 13032, 13033 }, { duration = 60, type = "BUFF", buffType = "Magic" }) -- Ice Barrier
+Spell({ 543, 8457, 8458, 10223, 10225 }, { duration = 30, type = "BUFF", buffType = "Magic" }) -- Fire Ward
+Spell({ 6143, 8461, 8462, 10177, 28609 }, { duration = 30, type = "BUFF", buffType = "Magic" }) -- Frost Ward
+
+Spell(12355, { duration = 2 }) -- Impact
+lib.spellNameToID[GetSpellInfo(12654)] = 12654
+-- Spell(12654, { duration = 4 }) -- Ignite
+
+if class == "MAGE" then
+Spell(22959, {
+ duration = function(spellID, isSrcPlayer)
+ if Talent(11095, 12872, 12873) > 0 then
+ return 30
+ else
+ return nil
+ end
+ end }) -- Fire Vulnerability
+end
+
+if class == "MAGE" then
+Spell(12579, {
+ duration = function(spellID, isSrcPlayer)
+ if Talent(11180, 28592, 28593, 28594, 28595) > 0 then
+ return 15
+ else
+ return nil
+ end
+ end }) -- Winter's Chill
+end
+
+Spell({ 11113, 13018, 13019, 13020, 13021 }, { duration = 6 }) -- Blast Wave
+
+Spell({ 2120, 2121, 8422, 8423, 10215, 10216 }, { duration = 8, stacking = true }) -- Flamestrike
+
+Spell({ 120, 8492, 10159, 10160, 10161 }, {
+ duration = function(spellID, isSrcPlayer)
+ local permafrost = isSrcPlayer and Talent(11175, 12569, 12571) or 0
+ return 8 + permafrost
+ end
+}) -- Cone of Cold
+
+
+if class == "MAGE" then
+-- Chilled from Imp Blizzard
+Spell({ 12484, 12485, 12486 }, {
+ duration = function(spellID, isSrcPlayer)
+ if Talent(11185, 12487, 12488) > 0 then -- Don't show anything if mage doesn't have imp blizzard talent
+ local permafrost = Talent(11175, 12569, 12571) -- Always count player's permafost, even source isn't player.
+ return 1.5 + permafrost + 0.5
+ -- 0.5 compensates for delay between damage event and slow application
+ else
+ return nil
+ end
+ end
+}) -- Improved Blizzard (Chilled)
+
+-- Manually setting a custom spellname for ImpBlizzard's "Chilled" aura
+lib.spellNameToID["ImpBlizzard"] = 12486
+-- Frost Armor will overwrite Chilled to 7321 right after
+end
+
+Spell({6136, 7321}, {
+ duration = function(spellID, isSrcPlayer)
+ local permafrost = isSrcPlayer and Talent(11175, 12569, 12571) or 0
+ return 5 + permafrost
+ end
+}) -- Frost/Ice Armor (Chilled)
+
+Spell({ 116, 205, 837, 7322, 8406, 8407, 8408, 10179, 10180, 10181, 25304 }, {
+ duration = function(spellID, isSrcPlayer)
+ local permafrost = isSrcPlayer and Talent(11175, 12569, 12571) or 0
+ if spellID == 116 then return 5 + permafrost
+ elseif spellID == 205 then return 6 + permafrost
+ elseif spellID == 837 then return 6 + permafrost
+ elseif spellID == 7322 then return 7 + permafrost
+ elseif spellID == 8406 then return 7 + permafrost
+ elseif spellID == 8407 then return 8 + permafrost
+ elseif spellID == 8408 then return 8 + permafrost
+ else return 9 + permafrost end
+ end
+}) -- Frostbolt
+
+Spell(12494, { duration = 5 }) -- Frostbite
+Spell({ 122, 865, 6131, 10230 }, { duration = 8 }) -- Frost Nova
+-- Spell(12536, { duration = 15 }) -- Clearcasting
+Spell(12043, { duration = 15 }) -- Presence of Mind
+Spell(12042, { duration = 15 }) -- Arcane Power
+Spell(12051, { duration = 8, type = "BUFF" }) -- Evocation
+
+-------------
+-- MOUNTS
+-------------
+
+Spell(17481, { duration = INFINITY, type = "BUFF" }) -- Deathcharger's Reins
+Spell(24252, { duration = INFINITY, type = "BUFF" }) -- Swift Zulian Tiger
+Spell(23509, { duration = INFINITY, type = "BUFF" }) -- Horn of the Frostwolf Howler
+Spell(17229, { duration = INFINITY, type = "BUFF" }) -- Reins of the Winterspring Frostsaber
+Spell(26656, { duration = INFINITY, type = "BUFF" }) -- Black Qiraji Resonating Crystal
+Spell(24242, { duration = INFINITY, type = "BUFF" }) -- Swift Razzashi Raptor
+Spell(23510, { duration = INFINITY, type = "BUFF" }) -- Stormpike Battle Charger
+Spell(470, { duration = INFINITY, type = "BUFF" }) -- Black Stallion Bridle
+Spell(22723, { duration = INFINITY, type = "BUFF" }) -- Reins of the Black War Tiger
+Spell(472, { duration = INFINITY, type = "BUFF" }) -- Pinto Bridle
+Spell(23221, { duration = INFINITY, type = "BUFF" }) -- Reins of the Swift Frostsaber
+Spell(23227, { duration = INFINITY, type = "BUFF" }) -- Swift Palomino
+Spell(23228, { duration = INFINITY, type = "BUFF" }) -- Swift White Steed
+Spell(6648, { duration = INFINITY, type = "BUFF" }) -- Chestnut Mare Bridle
+Spell(458, { duration = INFINITY, type = "BUFF" }) -- Brown Horse Bridle
+Spell(23338, { duration = INFINITY, type = "BUFF" }) -- Reins of the Swift Stormsaber
+Spell(23219, { duration = INFINITY, type = "BUFF" }) -- Reins of the Swift Mistsaber
+Spell(22721, { duration = INFINITY, type = "BUFF" }) -- Whistle of the Black War Raptor
+Spell(23229, { duration = INFINITY, type = "BUFF" }) -- Swift Brown Steed
+Spell(22717, { duration = INFINITY, type = "BUFF" }) -- Black War Steed Bridle
+Spell(10793, { duration = INFINITY, type = "BUFF" }) -- Reins of the Striped Nightsaber
+Spell(22722, { duration = INFINITY, type = "BUFF" }) -- Red Skeletal Warhorse
+Spell(18791, { duration = INFINITY, type = "BUFF" }) -- Purple Skeletal Warhorse
+Spell(10789, { duration = INFINITY, type = "BUFF" }) -- Reins of the Spotted Frostsaber
+Spell(18245, { duration = INFINITY, type = "BUFF" }) -- Horn of the Black War Wolf
+Spell(6653, { duration = INFINITY, type = "BUFF" }) -- Horn of the Dire Wolf
+Spell(23241, { duration = INFINITY, type = "BUFF" }) -- Swift Blue Raptor
+Spell(8394, { duration = INFINITY, type = "BUFF" }) -- Reins of the Striped Frostsaber
+Spell(23250, { duration = INFINITY, type = "BUFF" }) -- Horn of the Swift Brown Wolf
+Spell(22718, { duration = INFINITY, type = "BUFF" }) -- Black War Kodo
+Spell(580, { duration = INFINITY, type = "BUFF" }) -- Horn of the Timber Wolf
+Spell(17463, { duration = INFINITY, type = "BUFF" }) -- Blue Skeletal Horse
+Spell(23251, { duration = INFINITY, type = "BUFF" }) -- Horn of the Swift Timber Wolf
+Spell(23243, { duration = INFINITY, type = "BUFF" }) -- Swift Orange Raptor
+Spell(17465, { duration = INFINITY, type = "BUFF" }) -- Green Skeletal Warhorse
+Spell(22720, { duration = INFINITY, type = "BUFF" }) -- Black War Ram
+Spell(8395, { duration = INFINITY, type = "BUFF" }) -- Whistle of the Emerald Raptor
+Spell(6654, { duration = INFINITY, type = "BUFF" }) -- Horn of the Brown Wolf
+Spell(17462, { duration = INFINITY, type = "BUFF" }) -- Red Skeletal Horse
+Spell(23240, { duration = INFINITY, type = "BUFF" }) -- Swift White Ram
+Spell(23252, { duration = INFINITY, type = "BUFF" }) -- Horn of the Swift Gray Wolf
+Spell(23247, { duration = INFINITY, type = "BUFF" }) -- Great White Kodo
+Spell(23242, { duration = INFINITY, type = "BUFF" }) -- Swift Olive Raptor
+Spell(23225, { duration = INFINITY, type = "BUFF" }) -- Swift Green Mechanostrider
+Spell(10969, { duration = INFINITY, type = "BUFF" }) -- Blue Mechanostrider
+Spell(10799, { duration = INFINITY, type = "BUFF" }) -- Whistle of the Violet Raptor
+Spell(22719, { duration = INFINITY, type = "BUFF" }) -- Black Battlestrider
+Spell(6898, { duration = INFINITY, type = "BUFF" }) -- White Ram
+Spell(17464, { duration = INFINITY, type = "BUFF" }) -- Brown Skeletal Horse
+Spell(17454, { duration = INFINITY, type = "BUFF" }) -- Unpainted Mechanostrider
+Spell(23223, { duration = INFINITY, type = "BUFF" }) -- Swift White Mechanostrider
+Spell(10796, { duration = INFINITY, type = "BUFF" }) -- Whistle of the Turquoise Raptor
+Spell(23238, { duration = INFINITY, type = "BUFF" }) -- Swift Brown Ram
+Spell(23239, { duration = INFINITY, type = "BUFF" }) -- Swift Gray Ram
+Spell(6899, { duration = INFINITY, type = "BUFF" }) -- Brown Ram
+Spell(6777, { duration = INFINITY, type = "BUFF" }) -- Gray Ram
+Spell(10873, { duration = INFINITY, type = "BUFF" }) -- Red Mechanostrider
+Spell(23249, { duration = INFINITY, type = "BUFF" }) -- Great Brown Kodo
+Spell(18989, { duration = INFINITY, type = "BUFF" }) -- Gray Kodo
+Spell(18990, { duration = INFINITY, type = "BUFF" }) -- Brown Kodo
+Spell(23248, { duration = INFINITY, type = "BUFF" }) -- Great Gray Kodo
+Spell(23222, { duration = INFINITY, type = "BUFF" }) -- Swift Yellow Mechanostrider
+Spell(17453, { duration = INFINITY, type = "BUFF" }) -- Green Mechanostrider
+Spell(23214, { duration = INFINITY, type = "BUFF" }) -- Summon Charger
+Spell(13819, { duration = INFINITY, type = "BUFF" }) -- Summon Warhorse
+Spell(23161, { duration = INFINITY, type = "BUFF" }) -- Summon Dreadsteed
+Spell(5784, { duration = INFINITY, type = "BUFF" }) -- Summon Felsteed
+
+-------------
+-- ITEMS
+-------------
+
+Spell(17670, { duration = INFINITY, type = "BUFF" }) -- Argent Dawn Commission
+
+lib:SetDataVersion(Type, Version)
diff --git a/lib/LibClassicDurations/core.lua b/lib/LibClassicDurations/core.lua
new file mode 100644
index 0000000..1be6e5a
--- /dev/null
+++ b/lib/LibClassicDurations/core.lua
@@ -0,0 +1,1161 @@
+--[================[
+LibClassicDurations
+Author: d87
+Description: Tracks all aura applications in combat log and provides duration, expiration time.
+And additionally enemy buffs info.
+
+Usage example 1:
+-----------------
+
+ -- Using UnitAura wrapper
+ local UnitAura = _G.UnitAura
+
+ local LibClassicDurations = LibStub("LibClassicDurations", true)
+ if LibClassicDurations then
+ LibClassicDurations:Register("YourAddon")
+ UnitAura = LibClassicDurations.UnitAuraWrapper
+ end
+
+--]================]
+if WOW_PROJECT_ID ~= WOW_PROJECT_CLASSIC then return end
+
+local MAJOR, MINOR = "LibClassicDurations", 69
+local lib = LibStub:NewLibrary(MAJOR, MINOR)
+if not lib then return end
+
+lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
+lib.frame = lib.frame or CreateFrame("Frame")
+
+lib.guids = lib.guids or {}
+lib.spells = lib.spells or {}
+lib.npc_spells = lib.npc_spells or {}
+
+lib.spellNameToID = lib.spellNameToID or {}
+local spellNameToID = lib.spellNameToID
+
+local NPCspellNameToID = {}
+if lib.NPCSpellTableTimer then
+ lib.NPCSpellTableTimer:Cancel()
+end
+
+lib.DRInfo = lib.DRInfo or {}
+local DRInfo = lib.DRInfo
+
+lib.buffCache = lib.buffCache or {}
+local buffCache = lib.buffCache
+
+local buffCacheValid = {}
+
+lib.nameplateUnitMap = lib.nameplateUnitMap or {}
+local nameplateUnitMap = lib.nameplateUnitMap
+
+lib.castLog = lib.castLog or {}
+local castLog = lib.castLog
+
+lib.guidAccessTimes = lib.guidAccessTimes or {}
+local guidAccessTimes = lib.guidAccessTimes
+
+local f = lib.frame
+local callbacks = lib.callbacks
+local guids = lib.guids
+local spells = lib.spells
+local npc_spells = lib.npc_spells
+local indirectRefreshSpells = lib.indirectRefreshSpells
+
+local INFINITY = math.huge
+local PURGE_INTERVAL = 900
+local PURGE_THRESHOLD = 1800
+local UNKNOWN_AURA_DURATION = 3600 -- 60m
+local BUFF_CACHE_EXPIRATION_TIME = 40
+
+local CombatLogGetCurrentEventInfo = CombatLogGetCurrentEventInfo
+local UnitGUID = UnitGUID
+local UnitAura = UnitAura
+local GetSpellInfo = GetSpellInfo
+local GetTime = GetTime
+local tinsert = table.insert
+local unpack = unpack
+local GetGUIDAuraTime
+local time = time
+
+if lib.enableEnemyBuffTracking == nil then lib.enableEnemyBuffTracking = false end
+local enableEnemyBuffTracking = lib.enableEnemyBuffTracking
+
+local COMBATLOG_OBJECT_CONTROL_PLAYER = COMBATLOG_OBJECT_CONTROL_PLAYER
+
+f:SetScript("OnEvent", function(self, event, ...)
+ return self[event](self, event, ...)
+end)
+
+lib.dataVersions = lib.dataVersions or {}
+local SpellDataVersions = lib.dataVersions
+
+function lib:SetDataVersion(dataType, version)
+ SpellDataVersions[dataType] = version
+ npc_spells = lib.npc_spells
+ indirectRefreshSpells = lib.indirectRefreshSpells
+end
+
+function lib:GetDataVersion(dataType)
+ return SpellDataVersions[dataType] or 0
+end
+
+lib.AddAura = function(id, opts)
+ if not opts then return end
+
+ local lastRankID
+ if type(id) == "table" then
+ local clones = id
+ lastRankID = clones[#clones]
+ else
+ lastRankID = id
+ end
+
+ local spellName = GetSpellInfo(lastRankID)
+ if not spellName then
+ -- print(MINOR, lastRankID, spellName)
+ return
+ end
+ spellNameToID[spellName] = lastRankID
+
+ if type(id) == "table" then
+ for _, spellID in ipairs(id) do
+ spells[spellID] = opts
+ end
+ else
+ spells[id] = opts
+ end
+end
+
+
+lib.Talent = function (...)
+ for i=1, 5 do
+ local spellID = select(i, ...)
+ if not spellID then break end
+ if IsPlayerSpell(spellID) then return i end
+ end
+ return 0
+end
+
+local prevID
+local counter = 0
+local function processNPCSpellTable()
+ local dataTable = lib.npc_spells
+ counter = 0
+ local id = next(dataTable, prevID)
+ while (id and counter < 300) do
+ local spellName = GetSpellInfo(id)
+ if spellName then
+ NPCspellNameToID[GetSpellInfo(id)] = id
+ end
+
+ counter = counter + 1
+ prevID = id
+ id = next(dataTable, prevID)
+ end
+ if (id) then
+ C_Timer.After(1, processNPCSpellTable)
+ end
+end
+lib.NPCSpellTableTimer = C_Timer.NewTimer(10, processNPCSpellTable)
+
+
+local function isHunterGUID(guid)
+ return select(2, GetPlayerInfoByGUID(guid)) == "HUNTER"
+end
+local function isFriendlyFeigning(guid)
+ if IsInRaid() then
+ for i = 1, MAX_RAID_MEMBERS do
+ local unitID = "raid"..i
+ if (UnitGUID(unitID) == guid) and UnitIsFeignDeath(unitID) then
+ return true
+ end
+ end
+ elseif IsInGroup() then
+ for i = 1, MAX_PARTY_MEMBERS do
+ local unitID = "party"..i
+ if (UnitGUID(unitID) == guid) and UnitIsFeignDeath(unitID) then
+ return true
+ end
+ end
+ end
+end
+--------------------------
+-- OLD GUIDs PURGE
+--------------------------
+
+local function purgeOldGUIDsArgs(dataTable, accessTimes)
+ local now = time()
+ local deleted = {}
+ for guid, lastAccessTime in pairs(accessTimes) do
+ if lastAccessTime + PURGE_THRESHOLD < now then
+ dataTable[guid] = nil
+ nameplateUnitMap[guid] = nil
+ buffCacheValid[guid] = nil
+ buffCache[guid] = nil
+ DRInfo[guid] = nil
+ castLog[guid] = nil
+ tinsert(deleted, guid)
+ end
+ end
+ for _, guid in ipairs(deleted) do
+ accessTimes[guid] = nil
+ end
+end
+
+local function purgeOldGUIDs()
+ purgeOldGUIDsArgs(guids, guidAccessTimes)
+end
+if lib.purgeTicker then
+ lib.purgeTicker:Cancel()
+end
+lib.purgeTicker = C_Timer.NewTicker( PURGE_INTERVAL, purgeOldGUIDs)
+
+------------------------------------
+-- Restore data if using standalone
+f:RegisterEvent("PLAYER_LOGIN")
+function f:PLAYER_LOGIN()
+ if LCD_Data and LCD_GUIDAccess then
+ purgeOldGUIDsArgs(LCD_Data, LCD_GUIDAccess)
+
+ local function MergeTableNoOverwrite(t1, t2)
+ if not t2 then return false end
+ for k,v in pairs(t2) do
+ if type(v) == "table" then
+ if t1[k] == nil then
+ t1[k] = CopyTable(v)
+ else
+ MergeTableNoOverwrite(t1[k], v)
+ end
+ elseif t1[k] == nil then
+ t1[k] = v
+ end
+ end
+ return t1
+ end
+
+ local curSessionData = lib.guids
+ local restoredSessionData = LCD_Data
+ MergeTableNoOverwrite(curSessionData, restoredSessionData)
+
+ local curSessionAccessTimes = lib.guidAccessTimes
+ local restoredSessionAccessTimes = LCD_GUIDAccess
+ MergeTableNoOverwrite(curSessionAccessTimes, restoredSessionAccessTimes)
+ end
+
+ f:RegisterEvent("PLAYER_LOGOUT")
+ function f:PLAYER_LOGOUT()
+ LCD_Data = guids
+ LCD_GUIDAccess = guidAccessTimes
+ end
+end
+
+
+--------------------------
+-- DIMINISHING RETURNS
+--------------------------
+local bit_band = bit.band
+local DRResetTime = 18.4
+local COMBATLOG_OBJECT_TYPE_PLAYER = COMBATLOG_OBJECT_TYPE_PLAYER
+local COMBATLOG_OBJECT_REACTION_FRIENDLY = COMBATLOG_OBJECT_REACTION_FRIENDLY
+
+local DRMultipliers = { 0.5, 0.25, 0}
+local function addDRLevel(dstGUID, category)
+ local guidTable = DRInfo[dstGUID]
+ if not guidTable then
+ DRInfo[dstGUID] = {}
+ guidTable = DRInfo[dstGUID]
+ end
+
+ local catTable = guidTable[category]
+ if not catTable then
+ guidTable[category] = { level = 0, expires = 0}
+ catTable = guidTable[category]
+ end
+
+ local now = GetTime()
+ local isExpired = (catTable.expires or 0) <= now
+ local oldDRLevel = catTable.level
+ if isExpired or oldDRLevel >= 3 then
+ catTable.level = 0
+ end
+ catTable.level = catTable.level + 1
+ catTable.expires = now + DRResetTime
+end
+local function clearDRs(dstGUID)
+ DRInfo[dstGUID] = nil
+end
+local function getDRMul(dstGUID, spellID)
+ local category = lib.DR_CategoryBySpellID[spellID]
+ if not category then return 1 end
+
+ local guidTable = DRInfo[dstGUID]
+ if guidTable then
+ local catTable = guidTable[category]
+ if catTable then
+ local now = GetTime()
+ local isExpired = (catTable.expires or 0) <= now
+ if isExpired then
+ return 1
+ else
+ local mul = DRMultipliers[catTable.level]
+ return mul or 1
+ end
+ end
+ end
+ return 1
+end
+
+local function CountDiminishingReturns(eventType, srcGUID, srcFlags, dstGUID, dstFlags, spellID, auraType)
+ if auraType == "DEBUFF" then
+ if eventType == "SPELL_AURA_REMOVED" or eventType == "SPELL_AURA_REFRESH" then
+ local category = lib.DR_CategoryBySpellID[spellID]
+ if not category then return end
+
+ local isDstPlayer = bit_band(dstFlags, COMBATLOG_OBJECT_TYPE_PLAYER) > 0
+ -- local isFriendly = bit_band(dstFlags, COMBATLOG_OBJECT_REACTION_FRIENDLY) > 0
+
+ if not isDstPlayer then
+ if not lib.DR_TypesPVE[category] then return end
+ end
+
+ addDRLevel(dstGUID, category)
+ end
+ if eventType == "UNIT_DIED" then
+ if not isHunterGUID(dstGUID) then
+ clearDRs(dstGUID)
+ end
+ end
+ end
+end
+
+------------------------
+-- COMBO POINTS
+------------------------
+
+local GetComboPoints = GetComboPoints
+local _, playerClass = UnitClass("player")
+local cpWas = 0
+local cpNow = 0
+local function GetCP()
+ if not cpNow then return GetComboPoints("player", "target") end
+ return cpWas > cpNow and cpWas or cpNow
+end
+
+function f:PLAYER_TARGET_CHANGED(event)
+ return self:UNIT_POWER_UPDATE(event, "player", "COMBO_POINTS")
+end
+function f:UNIT_POWER_UPDATE(event,unit, ptype)
+ if ptype == "COMBO_POINTS" then
+ cpWas = cpNow
+ cpNow = GetComboPoints(unit, "target")
+ end
+end
+
+---------------------------
+-- COMBAT LOG
+---------------------------
+
+local function cleanDuration(duration, spellID, srcGUID, comboPoints)
+ if type(duration) == "function" then
+ local isSrcPlayer = srcGUID == UnitGUID("player")
+ -- Passing startTime for the sole reason of identifying different Rupture/KS applications for Rogues
+ -- Then their duration func will cache one actual duration calculated at the moment of application
+ return duration(spellID, isSrcPlayer, comboPoints)
+ end
+ return duration
+end
+
+local function GetSpellTable(srcGUID, dstGUID, spellID)
+ local guidTable = guids[dstGUID]
+ if not guidTable then return end
+
+ local spellTable = guidTable[spellID]
+ if not spellTable then return end
+
+ local applicationTable
+ if spellTable.applications then
+ applicationTable = spellTable.applications[srcGUID]
+ else
+ applicationTable = spellTable
+ end
+ if not applicationTable then return end
+ return applicationTable
+end
+
+local function RefreshTimer(srcGUID, dstGUID, spellID, overrideTime)
+ local applicationTable = GetSpellTable(srcGUID, dstGUID, spellID)
+ if not applicationTable then return end
+
+ local oldStartTime = applicationTable[2]
+ applicationTable[2] = overrideTime or GetTime() -- set start time to now
+ return true, oldStartTime
+end
+
+local function SetTimer(srcGUID, dstGUID, dstName, dstFlags, spellID, spellName, opts, auraType, doRemove)
+ if not opts then return end
+
+ local guidTable = guids[dstGUID]
+ if not guidTable then
+ guids[dstGUID] = {}
+ guidTable = guids[dstGUID]
+ end
+
+ local isStacking = opts.stacking
+ -- local auraUID = MakeAuraUID(spellID, isStacking and srcGUID)
+
+ if doRemove then
+ if guidTable[spellID] then
+ if isStacking then
+ if guidTable[spellID].applications then
+ guidTable[spellID].applications[srcGUID] = nil
+ end
+ else
+ guidTable[spellID] = nil
+ end
+ end
+ return
+ end
+
+ local spellTable = guidTable[spellID]
+ if not spellTable then
+ guidTable[spellID] = {}
+ spellTable = guidTable[spellID]
+ if isStacking then
+ spellTable.applications = {}
+ end
+ end
+
+ local applicationTable
+ if isStacking then
+ applicationTable = spellTable.applications[srcGUID]
+ if not applicationTable then
+ spellTable.applications[srcGUID] = {}
+ applicationTable = spellTable.applications[srcGUID]
+ end
+ else
+ applicationTable = spellTable
+ end
+
+ local duration = opts.duration
+ local isDstPlayer = bit_band(dstFlags, COMBATLOG_OBJECT_CONTROL_PLAYER) > 0
+ if isDstPlayer and opts.pvpduration then
+ duration = opts.pvpduration
+ end
+
+ if not duration then
+ return SetTimer(srcGUID, dstGUID, dstName, dstFlags, spellID, spellName, opts, auraType, true)
+ end
+ -- local mul = getDRMul(dstGUID, spellID)
+ -- duration = duration * mul
+ local now = GetTime()
+ -- local expirationTime
+ -- if duration == 0 then
+ -- expirationTime = now + UNKNOWN_AURA_DURATION -- 60m
+ -- else
+ -- -- local temporaryDuration = cleanDuration(opts.duration, spellID, srcGUID)
+ -- expirationTime = now + duration
+ -- end
+
+ applicationTable[1] = duration
+ applicationTable[2] = now
+ -- applicationTable[2] = expirationTime
+ applicationTable[3] = auraType
+
+ local isSrcPlayer = srcGUID == UnitGUID("player")
+ local comboPoints
+ if isSrcPlayer and playerClass == "ROGUE" then
+ comboPoints = GetCP()
+ end
+ applicationTable[4] = comboPoints
+
+ guidAccessTimes[dstGUID] = time()
+end
+
+local function FireToUnits(event, dstGUID)
+ if dstGUID == UnitGUID("target") then
+ callbacks:Fire(event, "target")
+ end
+ local nameplateUnit = nameplateUnitMap[dstGUID]
+ if nameplateUnit then
+ callbacks:Fire(event, nameplateUnit)
+ end
+end
+
+local function GetLastRankSpellID(spellName)
+ local spellID = spellNameToID[spellName]
+ if not spellID then
+ spellID = NPCspellNameToID[spellName]
+ end
+ return spellID
+end
+
+local eventSnapshot
+castLog.SetLastCast = function(self, srcGUID, spellID, timestamp)
+ self[srcGUID] = { spellID, timestamp }
+ guidAccessTimes[srcGUID] = time()
+end
+castLog.IsCurrent = function(self, srcGUID, spellID, timestamp, timeWindow)
+ local entry = self[srcGUID]
+ if entry then
+ local lastSpellID, lastTimestamp = entry[1], entry[2]
+ return lastSpellID == spellID and (timestamp - lastTimestamp < timeWindow)
+ end
+end
+
+local lastResistSpellID
+local lastResistTime = 0
+---------------------------
+-- COMBAT LOG HANDLER
+---------------------------
+function f:COMBAT_LOG_EVENT_UNFILTERED(event)
+ return self:CombatLogHandler(CombatLogGetCurrentEventInfo())
+end
+
+local rollbackTable = setmetatable({}, { __mode="v" })
+local function ProcIndirectRefresh(eventType, spellName, srcGUID, srcFlags, dstGUID, dstFlags, dstName, isCrit)
+ if indirectRefreshSpells[spellName] then
+ local targetSpells = indirectRefreshSpells[spellName]
+
+ for targetSpellID, refreshTable in pairs(targetSpells) do
+ if refreshTable.events[eventType] then
+
+
+ local condition = refreshTable.condition
+ if condition then
+ local isMine = bit_band(srcFlags, COMBATLOG_OBJECT_AFFILIATION_MINE) == COMBATLOG_OBJECT_AFFILIATION_MINE
+ if not condition(isMine, isCrit) then return end
+ end
+
+ if refreshTable.targetResistCheck then
+ local now = GetTime()
+ if lastResistSpellID == targetSpellID and now - lastResistTime < 0.4 then
+ return
+ end
+ end
+
+ if refreshTable.applyAura then
+ local opts = spells[targetSpellID]
+ if opts then
+ local targetAuraType = "DEBUFF"
+ local targetSpellName = GetSpellInfo(targetSpellID)
+ SetTimer(srcGUID, dstGUID, dstName, dstFlags, targetSpellID, targetSpellName, opts, targetAuraType)
+ end
+ elseif refreshTable.customAction then
+ refreshTable.customAction(srcGUID, dstGUID, targetSpellID)
+ else
+ local _, oldStartTime = RefreshTimer(srcGUID, dstGUID, targetSpellID)
+
+ if refreshTable.rollbackMisses and oldStartTime then
+ rollbackTable[srcGUID] = rollbackTable[srcGUID] or {}
+ rollbackTable[srcGUID][dstGUID] = rollbackTable[srcGUID][dstGUID] or {}
+ local now = GetTime()
+ rollbackTable[srcGUID][dstGUID][targetSpellID] = {now, oldStartTime}
+ end
+ end
+ end
+ end
+ end
+end
+
+local igniteName = GetSpellInfo(12654)
+do
+ local igniteOpts = { duration = 4 }
+ function f:IgniteHandler(...)
+ local timestamp, eventType, hideCaster,
+ srcGUID, srcName, srcFlags, srcFlags2,
+ dstGUID, dstName, dstFlags, dstFlags2,
+ spellID, spellName, spellSchool, auraType, _, _, _, _, _, isCrit = ...
+
+ spellID = 12654
+ local opts = igniteOpts
+
+ if eventType == "SPELL_AURA_APPLIED" then
+ SetTimer(srcGUID, dstGUID, dstName, dstFlags, spellID, spellName, opts, auraType)
+ local spellTable = GetSpellTable(srcGUID, dstGUID, spellID)
+ spellTable.tickExtended = true -- skipping first tick by treating it as already extended
+ if lib.DEBUG_IGNITE then
+ print(GetTime(), "[Ignite] Applied", dstGUID, "StartTime:", spellTable[2])
+ end
+ elseif eventType == "SPELL_PERIODIC_DAMAGE" then
+ local spellTable = GetSpellTable(srcGUID, dstGUID, spellID)
+ if spellTable then
+ if lib.DEBUG_IGNITE then
+ print(GetTime(), "[Ignite] Tick", dstGUID)
+ end
+ spellTable.tickExtended = false -- unmark tick
+ end
+ elseif eventType == "SPELL_AURA_REMOVED" then
+ SetTimer(srcGUID, dstGUID, dstName, dstFlags, spellID, spellName, opts, auraType, true)
+ if lib.DEBUG_IGNITE then
+ print(GetTime(), "[Ignite] Removed", dstGUID)
+ end
+ end
+ end
+ -- if playerClass ~= "MAGE" then
+ -- f.IgniteHandler = function() end
+ -- end
+ function lib:GetSpellTable(...)
+ return GetSpellTable(...)
+ end
+end
+
+function f:CombatLogHandler(...)
+ local timestamp, eventType, hideCaster,
+ srcGUID, srcName, srcFlags, srcFlags2,
+ dstGUID, dstName, dstFlags, dstFlags2,
+ spellID, spellName, spellSchool, auraType, _, _, _, _, _, isCrit = ...
+
+ ProcIndirectRefresh(eventType, spellName, srcGUID, srcFlags, dstGUID, dstFlags, dstName, isCrit)
+
+ if spellName == igniteName then
+ self:IgniteHandler(...)
+ end
+
+ if eventType == "SPELL_MISSED" and
+ bit_band(srcFlags, COMBATLOG_OBJECT_AFFILIATION_MINE) == COMBATLOG_OBJECT_AFFILIATION_MINE
+ then
+ local missType = auraType
+ -- ABSORB BLOCK DEFLECT DODGE EVADE IMMUNE MISS PARRY REFLECT RESIST
+ if not (missType == "ABSORB" or missType == "BLOCK") then -- not sure about those two
+
+ local refreshTable = indirectRefreshSpells[spellName]
+ -- This is just for Sunder Armor misses
+ if refreshTable and refreshTable.rollbackMisses then
+ local rollbacksFromSource = rollbackTable[srcGUID]
+ if rollbacksFromSource then
+ local rollbacks = rollbacksFromSource[dstGUID]
+ if rollbacks then
+ local targetSpellID = refreshTable.targetSpellID
+ local snapshot = rollbacks[targetSpellID]
+ if snapshot then
+ local timestamp, oldStartTime = unpack(snapshot)
+ local now = GetTime()
+ if now - timestamp < 0.5 then
+ RefreshTimer(srcGUID, dstGUID, targetSpellID, oldStartTime)
+ end
+ end
+ end
+ end
+ end
+
+ spellID = GetLastRankSpellID(spellName)
+ if not spellID then
+ return
+ end
+
+ lastResistSpellID = spellID
+ lastResistTime = GetTime()
+ end
+ end
+
+ if auraType == "BUFF" or auraType == "DEBUFF" or eventType == "SPELL_CAST_SUCCESS" then
+ if spellID == 0 then
+ -- so not to rewrite the whole thing to spellnames after the combat log change
+ -- just treat everything as max rank id of that spell name
+ spellID = GetLastRankSpellID(spellName)
+ if not spellID then
+ return
+ end
+ end
+
+ CountDiminishingReturns(eventType, srcGUID, srcFlags, dstGUID, dstFlags, spellID, auraType)
+
+ local isDstFriendly = bit_band(dstFlags, COMBATLOG_OBJECT_REACTION_FRIENDLY) > 0
+
+ local opts = spells[spellID]
+
+ if not opts then
+ local npcDurationForSpellName = npc_spells[spellID]
+ if npcDurationForSpellName then
+ opts = { duration = npcDurationForSpellName }
+ -- elseif enableEnemyBuffTracking and not isDstFriendly and auraType == "BUFF" then
+ -- opts = { duration = 0 } -- it'll be accepted but as an indefinite aura
+ end
+ end
+
+ if opts then
+ local castEventPass
+ if opts.castFilter then
+ -- Buff and Raidwide Buff events arrive in the following order:
+ -- 1571716930.161 ID: 21562 SPELL_AURA_APPLIED/REFRESH to Caster himself (if selfcast or raidwide)
+ -- 1571716930.161 ID: 21562 SPELL_CAST_SUCCESS on Cast Target
+ -- 1571716930.161 ID: 21562 SPELL_AURA_APPLIED/REFRESH to everyone else
+
+ -- For spells that have cast filter enabled:
+ -- First APPLIED event gets snapshotted and otherwise ignored
+ -- CAST event effectively sets castEventPass to true
+ -- Snapshotted event now gets handled with cast pass
+ -- All the following APPLIED events are accepted while cast pass is valid
+ -- (Unconfirmed whether timestamp is the same even for a 40m raid)
+ local now = GetTime()
+ castEventPass = castLog:IsCurrent(srcGUID, spellID, now, 0.8)
+ if not castEventPass and (eventType == "SPELL_AURA_REFRESH" or eventType == "SPELL_AURA_APPLIED") then
+ eventSnapshot = { timestamp, eventType, hideCaster,
+ srcGUID, srcName, srcFlags, srcFlags2,
+ dstGUID, dstName, dstFlags, dstFlags2,
+ spellID, spellName, spellSchool, auraType }
+ return
+ end
+
+ if eventType == "SPELL_CAST_SUCCESS" then
+ -- Aura spell ID can be different from cast spell id
+ -- But all buffs are usually simple spells and it's the same for them
+ castLog:SetLastCast(srcGUID, spellID, now)
+ if eventSnapshot then
+ self:CombatLogHandler(unpack(eventSnapshot))
+ eventSnapshot = nil
+ end
+ end
+ end
+
+ local isEnemyBuff = not isDstFriendly and auraType == "BUFF"
+ -- print(eventType, srcGUID, "=>", dstName, spellID, spellName, auraType )
+ if eventType == "SPELL_AURA_REFRESH" or
+ eventType == "SPELL_AURA_APPLIED" or
+ eventType == "SPELL_AURA_APPLIED_DOSE"
+ then
+ if not opts.castFilter or
+ castEventPass or
+ isEnemyBuff
+ then
+ SetTimer(srcGUID, dstGUID, dstName, dstFlags, spellID, spellName, opts, auraType)
+ end
+ elseif eventType == "SPELL_AURA_REMOVED" then
+ SetTimer(srcGUID, dstGUID, dstName, dstFlags, spellID, spellName, opts, auraType, true)
+ -- elseif eventType == "SPELL_AURA_REMOVED_DOSE" then
+ -- self:RemoveDose(srcGUID, dstGUID, spellID, spellName, auraType, amount)
+ end
+ if enableEnemyBuffTracking and isEnemyBuff then
+ -- invalidate buff cache
+ buffCacheValid[dstGUID] = nil
+
+ FireToUnits("UNIT_BUFF", dstGUID)
+ if eventType == "SPELL_AURA_REFRESH" or
+ eventType == "SPELL_AURA_APPLIED" or
+ eventType == "SPELL_AURA_APPLIED_DOSE"
+ then
+ FireToUnits("UNIT_BUFF_GAINED", dstGUID, spellID)
+ end
+ end
+ end
+ end
+ if eventType == "UNIT_DIED" then
+ if isHunterGUID(dstGUID) then
+ local isDstFriendly = bit_band(dstFlags, COMBATLOG_OBJECT_REACTION_FRIENDLY) > 0
+ if not isDstFriendly or isFriendlyFeigning(dstGUID) then
+ return
+ end
+ end
+
+ guids[dstGUID] = nil
+ buffCache[dstGUID] = nil
+ buffCacheValid[dstGUID] = nil
+ guidAccessTimes[dstGUID] = nil
+ local isDstFriendly = bit_band(dstFlags, COMBATLOG_OBJECT_REACTION_FRIENDLY) > 0
+ if enableEnemyBuffTracking and not isDstFriendly then
+ FireToUnits("UNIT_BUFF", dstGUID)
+ end
+ nameplateUnitMap[dstGUID] = nil
+ end
+end
+
+---------------------------
+-- ENEMY BUFFS
+---------------------------
+local makeBuffInfo = function(spellID, applicationTable, dstGUID, srcGUID)
+ local name, rank, icon, castTime, minRange, maxRange, _spellId = GetSpellInfo(spellID)
+ local durationFunc, startTime, auraType, comboPoints = unpack(applicationTable)
+ local duration = cleanDuration(durationFunc, spellID, srcGUID, comboPoints) -- srcGUID isn't needed actually
+ -- no DRs on buffs
+ local expirationTime = startTime + duration
+ if duration == INFINITY then
+ duration = 0
+ expirationTime = 0
+ end
+ local now = GetTime()
+ if expirationTime > now then
+ local buffType = spells[spellID] and spells[spellID].buffType
+ return { name, icon, 0, buffType, duration, expirationTime, nil, nil, nil, spellID, false, false, false, false, 1 }
+ end
+end
+
+local shouldDisplayAura = function(auraTable)
+ if auraTable[3] == "BUFF" then
+ local now = GetTime()
+ local expirationTime = auraTable[2]
+ return expirationTime > now
+ end
+ return false
+end
+
+lib.scanTip = lib.scanTip or CreateFrame("GameTooltip", "LibClassicDurationsScanTip", nil, "GameTooltipTemplate")
+local scanTip = lib.scanTip
+scanTip:SetOwner(WorldFrame, "ANCHOR_NONE")
+local function RegenerateBuffList(unit, dstGUID)
+ local buffs = {}
+ local spellName
+ for i=1, 32 do
+ scanTip:ClearLines()
+ scanTip:SetUnitAura(unit, i, "HELPFUL")
+ spellName = LibClassicDurationsScanTipTextLeft1:GetText()
+ if spellName then
+ local spellID = GetLastRankSpellID(spellName)
+ if spellID then
+ local icon = GetSpellTexture(spellID)
+ local opts = spells[spellID]
+ local buffInfo = { spellName, icon, 0, (opts and opts.buffType), 0, 0, nil, nil, nil, spellID, false, false, false, false, 1 }
+ local isStacking = opts and opts.stacking
+ local srcGUID = nil
+ local duration, expirationTime = GetGUIDAuraTime(dstGUID, spellName, spellID, srcGUID, isStacking)
+ if duration then
+ buffInfo[5] = duration
+ buffInfo[6] = expirationTime
+ end
+
+ tinsert(buffs, buffInfo)
+ end
+ else
+ break
+ end
+ end
+
+ buffCache[dstGUID] = buffs
+ buffCacheValid[dstGUID] = GetTime() + BUFF_CACHE_EXPIRATION_TIME -- Expiration timestamp
+end
+
+local FillInDuration = function(unit, buffName, icon, count, debuffType, duration, expirationTime, caster, canStealOrPurge, nps, spellId, ...)
+ if buffName then
+ local durationNew, expirationTimeNew = lib.GetAuraDurationByUnitDirect(unit, spellId, caster, buffName)
+ if duration == 0 and durationNew then
+ duration = durationNew
+ expirationTime = expirationTimeNew
+ end
+ return buffName, icon, count, debuffType, duration, expirationTime, caster, canStealOrPurge, nps, spellId, ...
+ end
+end
+lib.FillInDuration = FillInDuration
+
+function lib.UnitAuraDirect(unit, index, filter)
+ if enableEnemyBuffTracking and filter == "HELPFUL" and not UnitIsFriend("player", unit) and not UnitAura(unit, 1, filter) then
+ local unitGUID = UnitGUID(unit)
+ if not unitGUID then return end
+ local isValid = buffCacheValid[unitGUID]
+ if not isValid or isValid < GetTime() then
+ RegenerateBuffList(unit, unitGUID)
+ end
+
+ local buffCacheHit = buffCache[unitGUID]
+ if buffCacheHit then
+ local buffReturns = buffCache[unitGUID][index]
+ if buffReturns then
+ return unpack(buffReturns)
+ end
+ end
+ else
+ return FillInDuration(unit, UnitAura(unit, index, filter))
+ end
+end
+
+function lib.UnitAuraWithBuffs(...)
+ return lib.UnitAuraDirect(...)
+end
+
+function lib.UnitAuraWrapper(unit, ...)
+ return lib.FillInDuration(unit, UnitAura(unit, ...))
+end
+
+function lib:UnitAura(...)
+ return self.UnitAuraDirect(...)
+end
+
+function f:NAME_PLATE_UNIT_ADDED(event, unit)
+ local unitGUID = UnitGUID(unit)
+ nameplateUnitMap[unitGUID] = unit
+end
+function f:NAME_PLATE_UNIT_REMOVED(event, unit)
+ local unitGUID = UnitGUID(unit)
+ if unitGUID then -- it returns correctly on death, but just in case
+ nameplateUnitMap[unitGUID] = nil
+ end
+end
+
+function callbacks.OnUsed()
+ lib.enableEnemyBuffTracking = true
+ enableEnemyBuffTracking = lib.enableEnemyBuffTracking
+ f:RegisterEvent("NAME_PLATE_UNIT_ADDED")
+ f:RegisterEvent("NAME_PLATE_UNIT_REMOVED")
+end
+function callbacks.OnUnused()
+ lib.enableEnemyBuffTracking = false
+ enableEnemyBuffTracking = lib.enableEnemyBuffTracking
+ f:UnregisterEvent("NAME_PLATE_UNIT_ADDED")
+ f:UnregisterEvent("NAME_PLATE_UNIT_REMOVED")
+end
+
+if next(callbacks.events) then
+ callbacks.OnUsed()
+end
+
+---------------------------
+-- PUBLIC FUNCTIONS
+---------------------------
+GetGUIDAuraTime = function(dstGUID, spellName, spellID, srcGUID, isStacking, forcedNPCDuration)
+ local guidTable = guids[dstGUID]
+ if guidTable then
+
+ local lastRankID = GetLastRankSpellID(spellName)
+
+ local spellTable = guidTable[lastRankID]
+ if spellTable then
+ local applicationTable
+
+ -- Return when player spell and npc spell have the same name and the player spell is stacking
+ -- NPC spells are always assumed to not stack, so it won't find startTime
+ if forcedNPCDuration and spellTable.applications then return nil end
+
+ if isStacking then
+ if srcGUID and spellTable.applications then
+ applicationTable = spellTable.applications[srcGUID]
+ elseif spellTable.applications then -- return some duration
+ applicationTable = select(2,next(spellTable.applications))
+ end
+ else
+ applicationTable = spellTable
+ end
+ if not applicationTable then return end
+ local durationFunc, startTime, auraType, comboPoints = unpack(applicationTable)
+ local duration = forcedNPCDuration or cleanDuration(durationFunc, spellID, srcGUID, comboPoints)
+ if duration == INFINITY then return nil end
+ if not duration then return nil end
+ if not startTime then return nil end
+ local mul = getDRMul(dstGUID, spellID)
+ -- local mul = getDRMul(dstGUID, lastRankID)
+ duration = duration * mul
+ local expirationTime = startTime + duration
+ if GetTime() <= expirationTime then
+ return duration, expirationTime
+ end
+ end
+ end
+end
+
+if playerClass == "MAGE" then
+ local NormalGetGUIDAuraTime = GetGUIDAuraTime
+ local Chilled = GetSpellInfo(12486)
+ GetGUIDAuraTime = function(dstGUID, spellName, spellID, ...)
+
+ -- Overriding spellName for Improved blizzard's spellIDs
+ if spellName == Chilled and
+ spellID == 12486 or spellID == 12484 or spellID == 12485
+ then
+ spellName = "ImpBlizzard"
+ end
+ return NormalGetGUIDAuraTime(dstGUID, spellName, spellID, ...)
+ end
+end
+
+function lib.GetAuraDurationByUnitDirect(unit, spellID, casterUnit, spellName)
+ assert(spellID, "spellID is nil")
+ local opts = spells[spellID]
+ local isStacking
+ local npcDurationById
+ if opts then
+ isStacking = opts.stacking
+ else
+ npcDurationById = npc_spells[spellID]
+ if not npcDurationById then return end
+ end
+ local dstGUID = UnitGUID(unit)
+ local srcGUID = casterUnit and UnitGUID(casterUnit)
+ if not spellName then spellName = GetSpellInfo(spellID) end
+ return GetGUIDAuraTime(dstGUID, spellName, spellID, srcGUID, isStacking, npcDurationById)
+end
+
+function lib:GetAuraDurationByUnit(...)
+ return self.GetAuraDurationByUnitDirect(...)
+
+end
+function lib:GetAuraDurationByGUID(dstGUID, spellID, srcGUID, spellName)
+ local opts = spells[spellID]
+ if not opts then return end
+ if not spellName then spellName = GetSpellInfo(spellID) end
+ return GetGUIDAuraTime(dstGUID, spellName, spellID, srcGUID, opts.stacking)
+end
+
+function lib:GetLastRankSpellIDByName(spellName)
+ return GetLastRankSpellID(spellName)
+end
+
+-- Will not work for cp-based durations, KS and Rupture
+function lib:GetDurationForRank(spellName, spellID, srcGUID)
+ local lastRankID = spellNameToID[spellName]
+ local opts = spells[lastRankID]
+ if opts then
+ return cleanDuration(opts.duration, spellID, srcGUID)
+ end
+end
+
+lib.activeFrames = lib.activeFrames or {}
+local activeFrames = lib.activeFrames
+function lib:RegisterFrame(frame)
+ activeFrames[frame] = true
+ if next(activeFrames) then
+ f:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
+ if playerClass == "ROGUE" then
+ f:RegisterEvent("PLAYER_TARGET_CHANGED")
+ f:RegisterUnitEvent("UNIT_POWER_UPDATE", "player")
+ end
+ end
+end
+lib.Register = lib.RegisterFrame
+
+function lib:UnregisterFrame(frame)
+ activeFrames[frame] = nil
+ if not next(activeFrames) then
+ f:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
+ if playerClass == "ROGUE" then
+ f:UnregisterEvent("PLAYER_TARGET_CHANGED")
+ f:UnregisterEvent("UNIT_POWER_UPDATE")
+ end
+ end
+end
+lib.Unregister = lib.UnregisterFrame
+
+
+function lib:ToggleDebug()
+ if not lib.debug then
+ lib.debug = CreateFrame("Frame")
+ lib.debug:SetScript("OnEvent",function( self, event )
+ local timestamp, eventType, hideCaster,
+ srcGUID, srcName, srcFlags, srcFlags2,
+ dstGUID, dstName, dstFlags, dstFlags2,
+ spellID, spellName, spellSchool, auraType, amount = CombatLogGetCurrentEventInfo()
+ local isSrcPlayer = (bit_band(srcFlags, COMBATLOG_OBJECT_AFFILIATION_MINE) == COMBATLOG_OBJECT_AFFILIATION_MINE)
+ if isSrcPlayer then
+ print (GetTime(), "ID:", spellID, spellName, eventType, srcFlags, srcGUID,"|cff00ff00==>|r", dstGUID, dstFlags, auraType, amount)
+ end
+ end)
+ end
+ if not lib.debug.enabled then
+ lib.debug:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
+ lib.debug.enabled = true
+ print("[LCD] Enabled combat log event display")
+ else
+ lib.debug:UnregisterAllEvents()
+ lib.debug.enabled = false
+ print("[LCD] Disabled combat log event display")
+ end
+end
+
+function lib:MonitorUnit(unit)
+ if not lib.debug then
+ lib.debug = CreateFrame("Frame")
+ local debugGUID = UnitGUID(unit)
+ lib.debug:SetScript("OnEvent",function( self, event )
+ local timestamp, eventType, hideCaster,
+ srcGUID, srcName, srcFlags, srcFlags2,
+ dstGUID, dstName, dstFlags, dstFlags2,
+ spellID, spellName, spellSchool, auraType, amount = CombatLogGetCurrentEventInfo()
+ if srcGUID == debugGUID or dstGUID == debugGUID then
+ print (GetTime(), "ID:", spellID, spellName, eventType, srcFlags, srcGUID,"|cff00ff00==>|r", dstGUID, dstFlags, auraType, amount)
+ end
+ end)
+ end
+ if not lib.debug.enabled then
+ lib.debug:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
+ lib.debug.enabled = true
+ print("[LCD] Enabled combat log event display")
+ else
+ lib.debug:UnregisterAllEvents()
+ lib.debug.enabled = false
+ print("[LCD] Disabled combat log event display")
+ end
+end
+
+------------------
+-- Set Tracking
+------------------
+
+
+local itemSets = {}
+
+function lib:TrackItemSet(setname, itemArray)
+ itemSets[setname] = itemSets[setname] or {}
+ if not itemSets[setname].items then
+ itemSets[setname].items = {}
+ itemSets[setname].callbacks = {}
+ local bitems = itemSets[setname].items
+ for _, itemID in ipairs(itemArray) do
+ bitems[itemID] = true
+ end
+ end
+end
+function lib:RegisterSetBonusCallback(setname, pieces, handle_on, handle_off)
+ local set = itemSets[setname]
+ if not set then error(string.format("Itemset '%s' is not registered", setname)) end
+ set.callbacks[pieces] = {}
+ set.callbacks[pieces].equipped = false
+ set.callbacks[pieces].on = handle_on
+ set.callbacks[pieces].off = handle_off
+end
+
+function lib:IsSetBonusActive(setname, bonusLevel)
+ local set = itemSets[setname]
+ if not set then return false end
+ local setCallbacks = set.callbacks
+ if setCallbacks[bonusLevel] and setCallbacks[bonusLevel].equipped then
+ return true
+ end
+ return false
+end
+
+
+function lib:IsSetBonusActiveFullCheck(setname, bonusLevel)
+ local set = itemSets[setname]
+ if not set then return false end
+ local set_items = set.items
+ local pieces_equipped = 0
+ for slot=1,17 do
+ local itemID = GetInventoryItemID("player", slot)
+ if set_items[itemID] then pieces_equipped = pieces_equipped + 1 end
+ end
+ return (pieces_equipped >= bonusLevel)
+end
+
+
+lib.setwatcher = lib.setwatcher or CreateFrame("Frame", nil, UIParent)
+local setwatcher = lib.setwatcher
+setwatcher:SetScript("OnEvent", function(self, event, ...)
+ return self[event](self, event, ...)
+end)
+setwatcher:RegisterEvent("PLAYER_LOGIN")
+function setwatcher:PLAYER_LOGIN()
+ if next(itemSets) then
+ self:RegisterUnitEvent("UNIT_INVENTORY_CHANGED", "player")
+ self:UNIT_INVENTORY_CHANGED(nil, "player")
+ end
+end
+function setwatcher:UNIT_INVENTORY_CHANGED(event, unit)
+ for setname, set in pairs(itemSets) do
+ local set_items = set.items
+ local pieces_equipped = 0
+ for slot=1,17 do -- That excludes ranged slot in classic
+ local itemID = GetInventoryItemID("player", slot)
+ if set_items[itemID] then pieces_equipped = pieces_equipped + 1 end
+ end
+ for bp, bonus in pairs(set.callbacks) do
+ if pieces_equipped >= bp then
+ if not bonus.equipped then
+ if bonus.on then bonus.on() end
+ bonus.equipped = true
+ end
+ else
+ if bonus.equipped then
+ if bonus.off then bonus.off() end
+ bonus.equipped = false
+ end
+ end
+ end
+ end
+end
diff --git a/lib/LibClassicDurations/diminishingReturns.lua b/lib/LibClassicDurations/diminishingReturns.lua
new file mode 100644
index 0000000..27cff17
--- /dev/null
+++ b/lib/LibClassicDurations/diminishingReturns.lua
@@ -0,0 +1,176 @@
+local lib = LibStub("LibClassicDurations", true)
+if not lib then return end
+
+local Type, Version = "DRTable", 7
+if lib:GetDataVersion(Type) >= Version then return end
+
+local FEAR = "FEAR"
+local SILENCE = "SILENCE"
+local INCAP = "INCAP"
+local STUN = "STUN"
+local HORROR = "HORROR"
+local ROOT = "ROOT"
+-- local OPENER_STUN = "OPENER_STUN"
+local RANDOM_STUN = "RANDOM_STUN"
+local RANDOM_ROOT = "RANDOM_ROOT"
+local FROST_SHOCK = "FROST_SHOCK"
+local KIDNEY_SHOT = "KIDNEY_SHOT"
+
+lib.DR_TypesPVE = {
+ [KIDNEY_SHOT] = true,
+ [STUN] = true,
+}
+
+lib.DR_CategoryBySpellID = {
+ -- Silences weren't on DR until 3.0.8
+ -- Are random stuns even diminished at all among themselves?
+ -- Random roots?
+
+ [835] = STUN, -- Tidal Charm
+ [20549] = STUN, -- War Stomp
+ [16566] = ROOT, -- Net-o-Matic
+ [1090] = INCAP, -- Magic Dust
+ [13327] = INCAP, -- Goblin Rocket Helm, Reckless Charge
+ [5134] = FEAR, -- Flash Bomb
+
+ [5782] = FEAR, -- Fear 3 ranks
+ [6213] = FEAR,
+ [6215] = FEAR,
+ [5484] = FEAR, -- Howl of Terror 2 ranks
+ [17928] = FEAR,
+ [6358] = FEAR, -- Seduction
+
+ -- [24259] = SILENCE, -- Spell Lock
+
+ -- Coil wasn't on DR in classic
+ -- [6789] = HORROR, -- Death Coil 3 ranks
+ -- [17925] = HORROR,
+ -- [17926] = HORROR,
+ [22703] = STUN, -- Infernal Summon Stun
+
+
+ [20066] = INCAP, -- Repentance
+
+ [853] = STUN, -- Hammer of Justice 4 ranks
+ [5588] = STUN,
+ [5589] = STUN,
+ [10308] = STUN,
+
+ [20170] = RANDOM_STUN, -- Seal of Justice Stun
+
+
+
+ [3355] = INCAP, -- Freezing Trap Effect 3 ranks
+ [14308] = INCAP,
+ [14309] = INCAP,
+
+ [19386] = INCAP, -- Wyvern Sting 3 ranks
+ [24132] = INCAP,
+ [24133] = INCAP,
+
+ [19503] = INCAP, -- Scatter Shot
+ -- [19229] = RANDOM_ROOT, -- Improved Wing Clip Root
+
+ [19306] = ROOT, -- Counterattack
+
+ [19410] = RANDOM_STUN, -- Conc stun
+ [24394] = STUN, -- Intimidation
+
+
+ [2637] = INCAP, -- Hibernate 3 ranks
+ [18657] = INCAP,
+ [18658] = INCAP,
+
+ [5211] = STUN, -- Bash 3 ranks
+ [6798] = STUN,
+ [8983] = STUN,
+
+ [339] = ROOT, -- Entangling Roots 6 ranks
+ [1062] = ROOT,
+ [5195] = ROOT,
+ [5196] = ROOT,
+ [9852] = ROOT,
+ [9853] = ROOT,
+ [16922] = RANDOM_STUN, -- Improved Starfire
+
+ [9005] = STUN, -- Pounce 3 ranks
+ [9823] = STUN,
+ [9827] = STUN,
+
+
+ -- [18469] = SILENCE, -- Silence (Improved Counterspell)
+
+ [118] = INCAP, -- Polymorph 7 variants
+ [12824] = INCAP,
+ [12825] = INCAP,
+ [12826] = INCAP,
+ [28270] = INCAP,
+ [28271] = INCAP,
+ [28272] = INCAP,
+
+ -- Frostbite wasn't on DR until 2.1.0
+ -- [12494] = RANDOM_ROOT, -- Frostbite
+ [12355] = RANDOM_STUN, -- Impact
+
+ [122] = ROOT, -- Frost Nova 4 rank
+ [865] = ROOT,
+ [6131] = ROOT,
+ [10230] = ROOT,
+
+ [8056] = FROST_SHOCK, -- Frost Shock 4 ranks
+ [8058] = FROST_SHOCK,
+ [10472] = FROST_SHOCK,
+ [10473] = FROST_SHOCK,
+
+
+ -- [15487] = SILENCE, -- Silence (Priest)
+ [15269] = RANDOM_STUN, -- Blackout
+
+ -- MIND CONTROL ???
+ -- No Undeads for Shackle in classic
+
+ [8122] = FEAR, -- Psychic Scream
+ [8124] = FEAR,
+ [10888] = FEAR,
+ [10890] = FEAR,
+
+
+ -- [18425] = SILENCE, -- Imp Kick
+ [1833] = STUN, -- Cheap Shot
+ -- Blind wasn't on Fear until some time in 3.0, and before that it was with Cyclone,
+ -- and in classic probably with itself
+ -- [2094] = FEAR, -- Blind
+
+ [2070] = INCAP, -- Sap 3 ranks
+ [6770] = INCAP,
+ [11297] = INCAP,
+
+ [1776] = INCAP, -- Gouge 5 ranks
+ [1777] = INCAP,
+ [8629] = INCAP,
+ [11285] = INCAP,
+ [11286] = INCAP,
+
+ [408] = KIDNEY_SHOT, -- Kidney Shot 2 ranks
+ [8643] = KIDNEY_SHOT,
+
+ [5530] = RANDOM_STUN, -- Mace Spec Stun, shared by both Rogue and Warrior
+
+
+ -- [18498] = SILENCE, -- Imp Shield Bash Silence
+ -- [23694] = RANDOM_ROOT, -- Improved Hamstring Root
+
+ -- Disarm wasn't on DR until 2.3.0
+ -- [676] = "DISARM", -- Disarm
+
+ [12809] = STUN, -- Concussion Blow
+ [12798] = RANDOM_STUN, -- Improved Revenge
+ [5246] = FEAR, -- Intimidating Shout
+ [7922] = STUN, -- Charge
+
+ [20253] = STUN, -- Intercept Stun 3 ranks
+ [20614] = STUN,
+ [20615] = STUN,
+}
+
+lib:SetDataVersion(Type, Version)
\ No newline at end of file
diff --git a/lib/LibClassicDurations/npcAbilities.lua b/lib/LibClassicDurations/npcAbilities.lua
new file mode 100644
index 0000000..0c50193
--- /dev/null
+++ b/lib/LibClassicDurations/npcAbilities.lua
@@ -0,0 +1,576 @@
+local lib = LibStub and LibStub("LibClassicDurations", true)
+if not lib then return end
+
+local Type, Version = "NPCSpellTable", 2
+if lib:GetDataVersion(Type) >= Version then return end
+
+lib.npc_spells = {
+ [11]=30,[12]=10,[13]=30,[16]=15,[17]=30,[22]=10,[25]=5,[43]=30,[47]=10,[56]=3,
+ [65]=30,[66]=120,[67]=10,[89]=20,[91]=30,[96]=10,[99]=30,[101]=3,[111]=10,
+ [112]=10,[113]=15,[116]=5,[118]=20,[120]=8,[122]=8,[126]=45,[128]=60,[130]=30,
+ [131]=600,[132]=600,[133]=4,[134]=60,[136]=5,[139]=15,[143]=6,[145]=6,[168]=1800,
+ [172]=12,[184]=60,[205]=6,[228]=10,[246]=10,[302]=30,[324]=600,[325]=600,
+ [339]=12,[348]=15,[355]=3,[379]=60,[409]=60,[410]=60,[411]=60,[430]=18,[431]=21,
+ [432]=24,[433]=18,[434]=21,[435]=24,[450]=5,[453]=15,[454]=10,[457]=30,[467]=600,
+ [474]=30,[498]=6,[507]=30,[509]=30,[512]=20,[543]=30,[546]=600,[550]=30,[552]=20,
+ [553]=30,[568]=8,[586]=10,[588]=600,[589]=18,[592]=30,[594]=18,[595]=30,[600]=30,
+ [602]=600,[603]=60,[604]=600,[605]=60,[606]=30,[642]=10,[673]=3600,[676]=10,
+ [687]=1800,[689]=5,[692]=10,[694]=6,[696]=1800,[699]=5,[700]=20,[702]=120,
+ [703]=18,[704]=120,[706]=1800,[707]=15,[709]=5,[710]=20,[720]=8,[731]=8,[742]=30,
+ [744]=30,[745]=10,[746]=6,[755]=10,[770]=40,[772]=9,[774]=12,[775]=8,[776]=5,
+ [778]=40,[782]=600,[785]=20,[800]=0.25,[802]=240,[804]=4,[806]=60,[822]=60,
+ [829]=30,[830]=30,[833]=10,[834]=3600,[835]=3,[837]=6,[839]=30,[849]=60,[851]=10,
+ [853]=3,[855]=30,[863]=60,[865]=8,[867]=30,[871]=10,[877]=30,[885]=120,[905]=600,
+ [945]=600,[970]=18,[976]=600,[980]=24,[992]=18,[994]=30,[1002]=60,[1006]=600,
+ [1008]=600,[1009]=5,[1010]=120,[1014]=24,[1020]=12,[1022]=6,[1038]=300,[1044]=10,
+ [1056]=30,[1058]=12,[1062]=15,[1075]=600,[1079]=12,[1086]=1800,[1090]=30,
+ [1094]=15,[1098]=300,[1108]=120,[1120]=15,[1121]=8,[1126]=1800,[1127]=27,
+ [1129]=30,[1130]=120,[1131]=30,[1132]=30,[1133]=27,[1135]=30,[1137]=30,[1138]=60,
+ [1139]=15,[1159]=6,[1160]=30,[1161]=6,[1179]=10,[1243]=1800,[1244]=1800,
+ [1245]=1800,[1302]=45,[1430]=12,[1450]=1800,[1451]=1800,[1452]=1800,[1453]=1800,
+ [1459]=1800,[1460]=1800,[1461]=1800,[1462]=30,[1463]=60,[1490]=300,[1513]=10,
+ [1515]=20,[1528]=1,[1539]=20,[1604]=4,[1663]=30,[1664]=30,[1665]=30,[1706]=120,
+ [1714]=30,[1715]=15,[1719]=15,[1731]=15,[1732]=15,[1735]=30,[1776]=4,[1777]=4,
+ [1822]=9,[1823]=9,[1824]=9,[1833]=4,[1834]=180,[1849]=30,[1850]=15,[1864]=300,
+ [1906]=8,[1943]=6,[1949]=15,[1953]=1,[1978]=15,[2070]=35,[2090]=12,[2091]=12,
+ [2094]=10,[2096]=60,[2140]=15,[2313]=20,[2351]=30,[2353]=30,[2354]=30,[2361]=300,
+ [2367]=3600,[2374]=3600,[2376]=3600,[2378]=3600,[2379]=15,[2380]=180,[2381]=600,
+ [2425]=5,[2479]=30,[2537]=30,[2564]=5,[2565]=5,[2601]=30,[2602]=15,[2637]=20,
+ [2639]=21,[2647]=5,[2651]=15,[2652]=600,[2691]=0.001,[2766]=30,[2767]=18,
+ [2791]=1800,[2818]=12,[2819]=12,[2855]=120,[2871]=30,[2878]=10,[2880]=10,
+ [2893]=8,[2908]=15,[2941]=15,[2943]=120,[2944]=24,[2947]=180,[2969]=15,
+ [2970]=600,[2974]=10,[2983]=15,[3019]=15,[3023]=30,[3034]=8,[3043]=20,[3045]=15,
+ [3105]=600,[3109]=10,[3111]=5,[3120]=5,[3130]=6,[3132]=12,[3133]=30,[3136]=10,
+ [3140]=8,[3143]=3,[3145]=5,[3146]=30,[3147]=12,[3148]=20,[3149]=15,[3150]=600,
+ [3151]=6,[3157]=3600,[3158]=3600,[3159]=3600,[3160]=3600,[3161]=3600,[3162]=3600,
+ [3163]=3600,[3164]=3600,[3165]=3600,[3166]=3600,[3167]=3600,[3168]=3600,[3169]=6,
+ [3219]=3600,[3220]=3600,[3221]=3600,[3222]=3600,[3223]=3600,[3229]=5,[3232]=60,
+ [3237]=240,[3238]=8,[3242]=2,[3247]=15,[3248]=6,[3252]=12,[3256]=240,[3258]=4,
+ [3260]=8,[3261]=20,[3263]=5,[3264]=15,[3267]=7,[3268]=7,[3269]=8,[3271]=2,
+ [3288]=10,[3329]=60,[3332]=30,[3335]=300,[3355]=10,[3356]=45,[3358]=40,
+ [3369]=120,[3385]=4,[3387]=120,[3388]=45,[3389]=6,[3396]=30,[3409]=12,[3416]=10,
+ [3419]=6,[3424]=120,[3427]=300,[3429]=600,[3436]=300,[3439]=300,[3442]=15,
+ [3443]=15,[3446]=6,[3485]=15,[3490]=5,[3510]=3,[3514]=3,[3542]=30,[3547]=8,
+ [3551]=2,[3574]=8,[3583]=120,[3584]=120,[3586]=180,[3589]=8,[3593]=3600,[3600]=5,
+ [3602]=30,[3603]=15,[3604]=8,[3609]=8,[3618]=300,[3627]=12,[3635]=6,[3636]=15,
+ [3639]=6,[3648]=45,[3650]=15,[3651]=10,[3661]=5,[3662]=5,[3671]=180,[3672]=180,
+ [3673]=180,[3674]=30,[3680]=15,[3698]=10,[3699]=10,[3700]=10,[3719]=30,[3742]=15,
+ [3747]=30,[3815]=45,[3826]=3,[4057]=60,[4058]=3,[4060]=12,[4063]=30,[4064]=1,
+ [4065]=1,[4066]=2,[4067]=2,[4068]=3,[4069]=3,[4077]=60,[4079]=10,[4083]=30,
+ [4092]=10,[4101]=6,[4102]=15,[4104]=15,[4105]=15,[4107]=10,[4108]=10,[4109]=12,
+ [4111]=12,[4134]=10,[4135]=10,[4137]=10,[4139]=10,[4146]=15,[4147]=30,[4148]=300,
+ [4149]=10,[4150]=12,[4153]=30,[4154]=8,[4159]=5,[4166]=3,[4167]=8,[4168]=10,
+ [4169]=12,[4238]=120,[4240]=8,[4242]=15,[4243]=3,[4244]=8,[4246]=15,[4282]=10,
+ [4285]=8,[4286]=15,[4316]=30,[4318]=1800,[4320]=12,[4321]=5,[4504]=30,[4505]=30,
+ [4507]=5,[4514]=12,[4524]=3,[4538]=12,[4539]=10,[4805]=15,[4932]=20,[4940]=30,
+ [4941]=90,[4948]=15,[4952]=5,[4955]=12,[4962]=6,[4970]=10,[4974]=120,[4979]=10,
+ [4980]=10,[5003]=90,[5004]=18,[5005]=21,[5006]=24,[5007]=27,[5020]=300,
+ [5021]=300,[5024]=10,[5101]=30,[5105]=60,[5106]=15,[5115]=6,[5116]=4,[5119]=180,
+ [5120]=60,[5121]=60,[5122]=60,[5123]=60,[5124]=60,[5134]=10,[5137]=60,[5138]=5,
+ [5143]=3,[5144]=4,[5145]=5,[5159]=20,[5164]=2,[5165]=8,[5171]=6,[5195]=18,
+ [5196]=21,[5202]=1800,[5208]=60,[5209]=6,[5211]=2,[5213]=15,[5217]=6,[5219]=8,
+ [5220]=15,[5229]=10,[5232]=1800,[5234]=1800,[5242]=120,[5246]=8,[5250]=30,
+ [5254]=30,[5256]=20,[5257]=300,[5259]=15,[5260]=15,[5262]=10,[5271]=20,[5276]=15,
+ [5277]=15,[5280]=45,[5302]=5,[5306]=120,[5320]=1800,[5321]=1800,[5322]=1800,
+ [5323]=1800,[5324]=1800,[5325]=1800,[5337]=8,[5363]=20,[5365]=20,[5366]=20,
+ [5367]=20,[5376]=8,[5384]=360,[5402]=300,[5403]=10,[5413]=120,[5416]=45,[5422]=8,
+ [5424]=4,[5426]=6,[5480]=15,[5484]=10,[5508]=15,[5514]=12,[5515]=8,[5530]=3,
+ [5543]=2,[5567]=5,[5570]=12,[5573]=8,[5579]=0.1,[5588]=4,[5589]=5,[5597]=10,
+ [5598]=10,[5599]=8,[5627]=15,[5628]=6,[5648]=3,[5649]=5,[5665]=600,[5697]=600,
+ [5703]=4,[5708]=2,[5726]=5,[5727]=8,[5759]=240,[5760]=10,[5781]=30,[5782]=10,
+ [5810]=6,[5858]=300,[5862]=1800,[5884]=12,[5909]=600,[5915]=60,[5917]=10,
+ [5918]=5,[5934]=6,[5951]=2,[5990]=8,[6016]=20,[6065]=30,[6066]=30,[6074]=15,
+ [6075]=15,[6076]=15,[6077]=15,[6078]=15,[6114]=300,[6115]=60,[6117]=1800,
+ [6131]=8,[6136]=5,[6143]=30,[6146]=15,[6150]=12,[6190]=30,[6192]=120,[6196]=60,
+ [6197]=60,[6205]=120,[6213]=15,[6215]=20,[6217]=24,[6222]=15,[6223]=18,[6226]=5,
+ [6229]=30,[6238]=20,[6240]=0.001,[6253]=2,[6257]=30,[6264]=8,[6266]=3,[6268]=3,
+ [6272]=60,[6277]=120,[6278]=60,[6298]=300,[6304]=3,[6306]=30,[6343]=10,
+ [6346]=600,[6355]=10,[6358]=15,[6405]=180,[6409]=5,[6410]=21,[6411]=21,[6422]=3,
+ [6431]=30,[6432]=10,[6434]=10,[6435]=3,[6466]=3,[6467]=180,[6468]=6,[6495]=300,
+ [6507]=60,[6512]=600,[6513]=60,[6524]=2,[6528]=0.001,[6530]=10,[6531]=60,
+ [6533]=10,[6538]=60,[6546]=12,[6547]=15,[6548]=18,[6576]=5,[6580]=3,[6581]=10,
+ [6584]=10,[6600]=5,[6601]=5,[6602]=5,[6605]=4,[6607]=2,[6608]=5,[6614]=30,
+ [6615]=30,[6634]=8,[6664]=2,[6669]=2,[6673]=120,[6685]=15,[6711]=360,[6713]=6,
+ [6714]=4,[6716]=3,[6724]=10,[6726]=6,[6727]=30,[6728]=10,[6730]=2,[6741]=20,
+ [6742]=30,[6749]=5,[6751]=12,[6754]=3,[6756]=1800,[6758]=120,[6767]=600,
+ [6770]=25,[6772]=3,[6774]=6,[6788]=15,[6789]=3,[6793]=6,[6795]=3,[6798]=3,
+ [6814]=45,[6816]=4,[6817]=4,[6818]=4,[6819]=4,[6844]=10,[6864]=8,[6866]=180,
+ [6869]=2,[6870]=180,[6873]=120,[6894]=10,[6902]=120,[6903]=10,[6907]=120,
+ [6909]=180,[6917]=10,[6921]=6,[6922]=300,[6927]=5,[6940]=30,[6942]=6,[6945]=5,
+ [6946]=180,[6950]=60,[6951]=300,[6955]=300,[6957]=180,[6960]=180,[6965]=4,
+ [6969]=1,[6974]=1,[6982]=4,[6984]=10,[6985]=10,[7001]=10,[7020]=15,[7022]=300,
+ [7023]=1,[7035]=5,[7036]=5,[7038]=60,[7039]=60,[7040]=60,[7041]=60,[7042]=60,
+ [7043]=60,[7044]=60,[7045]=60,[7046]=60,[7047]=60,[7048]=60,[7049]=60,[7050]=60,
+ [7051]=60,[7053]=60,[7054]=300,[7057]=300,[7068]=15,[7072]=60,[7074]=5,
+ [7081]=300,[7082]=3,[7090]=300,[7093]=4,[7098]=180,[7102]=240,[7103]=240,
+ [7104]=10,[7120]=1800,[7121]=10,[7124]=300,[7125]=120,[7127]=60,[7128]=600,
+ [7136]=10,[7137]=6,[7139]=3,[7140]=5,[7144]=15,[7164]=180,[7178]=1800,[7184]=300,
+ [7211]=10,[7230]=3600,[7231]=3600,[7232]=3600,[7233]=3600,[7234]=3600,
+ [7235]=3600,[7236]=3600,[7237]=3600,[7238]=3600,[7239]=3600,[7240]=3600,
+ [7241]=3600,[7242]=3600,[7243]=3600,[7244]=3600,[7245]=3600,[7246]=3600,
+ [7247]=3600,[7248]=3600,[7249]=3600,[7250]=3600,[7251]=3600,[7252]=3600,
+ [7253]=3600,[7254]=3600,[7267]=3,[7272]=12,[7279]=120,[7288]=20,[7289]=120,
+ [7290]=10,[7291]=30,[7295]=10,[7300]=1800,[7301]=1800,[7302]=1800,[7320]=1800,
+ [7321]=5,[7322]=7,[7336]=1,[7337]=1.5,[7338]=2,[7339]=2.5,[7353]=60,[7357]=15,
+ [7358]=60,[7365]=30,[7366]=240,[7367]=180,[7371]=4,[7372]=15,[7373]=15,[7383]=30,
+ [7386]=30,[7389]=15,[7396]=30,[7399]=4,[7400]=6,[7402]=6,[7405]=30,[7481]=300,
+ [7483]=300,[7484]=300,[7586]=10,[7587]=10,[7621]=10,[7638]=3,[7645]=10,
+ [7646]=120,[7648]=18,[7651]=5,[7656]=30,[7657]=30,[7658]=120,[7659]=120,
+ [7670]=2.5,[7713]=6,[7737]=15,[7739]=10,[7744]=5,[7750]=12,[7761]=4,[7764]=1800,
+ [7803]=5,[7806]=180,[7807]=180,[7808]=180,[7812]=30,[7840]=20,[7844]=1800,
+ [7870]=300,[7901]=300,[7914]=9,[7922]=1,[7926]=8,[7927]=8,[7947]=60,[7948]=20,
+ [7950]=3,[7961]=5,[7964]=4,[7965]=300,[7967]=15,[7992]=25,[7997]=300,[7998]=10,
+ [8014]=1200,[8016]=1200,[8034]=8,[8037]=8,[8040]=15,[8041]=10,[8050]=12,
+ [8052]=12,[8053]=12,[8056]=8,[8058]=8,[8064]=30,[8066]=120,[8067]=120,
+ [8068]=1800,[8070]=12,[8078]=10,[8091]=1800,[8094]=1800,[8095]=1800,[8096]=1800,
+ [8097]=1800,[8098]=1800,[8099]=1800,[8100]=1800,[8101]=1800,[8112]=1800,
+ [8113]=1800,[8114]=1800,[8115]=1800,[8116]=1800,[8117]=1800,[8118]=1800,
+ [8119]=1800,[8120]=1800,[8122]=8,[8124]=8,[8134]=600,[8137]=1800,[8138]=2700,
+ [8139]=1800,[8140]=15,[8142]=10,[8147]=10,[8150]=2.5,[8151]=2.5,[8191]=15,
+ [8192]=15,[8198]=14,[8202]=1200,[8204]=18,[8205]=22,[8208]=10,[8212]=120,
+ [8215]=120,[8219]=3600,[8220]=3600,[8221]=3600,[8222]=3600,[8223]=10,[8224]=600,
+ [8225]=5,[8226]=300,[8233]=1.5,[8236]=1.5,[8242]=2,[8245]=300,[8255]=10,
+ [8256]=180,[8257]=30,[8260]=4,[8267]=600,[8269]=120,[8272]=600,[8275]=75,
+ [8277]=120,[8281]=10,[8282]=600,[8285]=2.5,[8288]=15,[8289]=15,[8312]=10,
+ [8313]=20,[8314]=3600,[8316]=180,[8317]=180,[8338]=2,[8345]=60,[8346]=20,
+ [8348]=12,[8359]=300,[8361]=2,[8362]=20,[8363]=75,[8365]=60,[8377]=4,[8379]=10,
+ [8380]=30,[8382]=45,[8383]=3600,[8384]=3600,[8385]=3600,[8391]=3,[8392]=10,
+ [8398]=8,[8399]=10,[8400]=8,[8401]=8,[8402]=8,[8406]=7,[8407]=8,[8408]=8,
+ [8416]=5,[8417]=5,[8450]=600,[8451]=600,[8455]=600,[8457]=30,[8458]=30,[8461]=30,
+ [8462]=30,[8492]=8,[8494]=60,[8495]=60,[8510]=2,[8511]=2,[8516]=1.5,[8552]=120,
+ [8553]=600,[8554]=2,[8599]=120,[8600]=180,[8602]=10,[8609]=3,[8611]=6,[8629]=4,
+ [8631]=18,[8632]=18,[8633]=18,[8639]=6,[8640]=6,[8643]=1,[8646]=2,[8647]=30,
+ [8649]=30,[8650]=30,[8672]=30,[8692]=12,[8696]=15,[8699]=20,[8715]=3,[8716]=12,
+ [8733]=3600,[8788]=600,[8806]=60,[8817]=3,[8818]=18,[8822]=30,[8823]=30,
+ [8824]=30,[8892]=20,[8893]=2,[8898]=1200,[8899]=1200,[8900]=1200,[8901]=20,
+ [8902]=20,[8907]=1800,[8909]=600,[8910]=12,[8914]=600,[8921]=9,[8924]=12,
+ [8925]=12,[8926]=12,[8927]=12,[8928]=12,[8929]=12,[8936]=21,[8938]=21,[8939]=21,
+ [8940]=21,[8941]=21,[8955]=15,[8983]=4,[8988]=10,[8989]=10,[8994]=15,[9005]=2,
+ [9007]=18,[9032]=30,[9034]=21,[9035]=120,[9080]=10,[9095]=600,[9128]=120,
+ [9159]=10,[9175]=15,[9176]=60,[9177]=24,[9178]=120,[9179]=3,[9192]=120,
+ [9199]=300,[9220]=120,[9234]=1800,[9256]=10,[9275]=21,[9373]=12,[9438]=8,
+ [9458]=3,[9459]=60,[9462]=8,[9482]=30,[9484]=30,[9485]=40,[9490]=30,[9492]=12,
+ [9493]=12,[9552]=9,[9574]=45,[9576]=10,[9578]=10,[9579]=10,[9587]=180,[9592]=10,
+ [9612]=15,[9614]=60,[9616]=20,[9632]=9,[9657]=10,[9658]=45,[9672]=4,[9712]=5,
+ [9733]=4,[9735]=1200,[9736]=30,[9738]=120,[9741]=6,[9747]=30,[9749]=40,[9750]=21,
+ [9752]=12,[9756]=600,[9773]=8,[9774]=5,[9775]=60,[9779]=8,[9791]=20,[9796]=60,
+ [9800]=60,[9806]=20,[9810]=10,[9821]=15,[9823]=2,[9824]=18,[9826]=18,[9827]=2,
+ [9833]=12,[9834]=12,[9835]=12,[9839]=12,[9840]=12,[9841]=12,[9845]=6,[9846]=6,
+ [9852]=24,[9853]=27,[9856]=21,[9857]=21,[9858]=21,[9884]=1800,[9885]=1800,
+ [9894]=12,[9896]=12,[9898]=30,[9901]=15,[9904]=9,[9906]=5,[9907]=40,[9910]=600,
+ [9915]=10,[9930]=30,[9991]=604800,[9992]=10,[10017]=10,[10018]=10,[10060]=15,
+ [10072]=3600,[10093]=1,[10096]=120,[10134]=7,[10136]=1200,[10148]=8,[10149]=8,
+ [10150]=8,[10151]=8,[10156]=1800,[10157]=1800,[10159]=8,[10160]=8,[10161]=8,
+ [10169]=600,[10170]=600,[10173]=600,[10174]=600,[10177]=30,[10179]=9,[10180]=9,
+ [10181]=9,[10191]=60,[10192]=60,[10193]=60,[10211]=5,[10212]=5,[10219]=1800,
+ [10220]=1800,[10223]=30,[10225]=30,[10228]=120,[10230]=8,[10236]=180,[10238]=180,
+ [10240]=180,[10241]=180,[10242]=180,[10250]=30,[10251]=180,[10252]=5,[10253]=10,
+ [10256]=30,[10257]=30,[10259]=2,[10260]=20,[10263]=90,[10266]=2,[10268]=180,
+ [10278]=10,[10308]=6,[10326]=20,[10336]=30,[10337]=30,[10342]=15,[10345]=20,
+ [10348]=20,[10351]=5,[10368]=15,[10370]=60,[10371]=10,[10431]=600,[10432]=600,
+ [10447]=12,[10448]=12,[10452]=20,[10455]=0.001,[10458]=8,[10472]=8,[10473]=8,
+ [10484]=1.5,[10576]=6,[10578]=8,[10608]=1.5,[10610]=1.5,[10618]=120,[10651]=120,
+ [10653]=120,[10654]=10,[10667]=3600,[10668]=3600,[10669]=3600,[10670]=3600,
+ [10671]=3600,[10672]=3600,[10690]=3600,[10691]=3600,[10692]=3600,[10693]=3600,
+ [10730]=10,[10732]=10,[10734]=3,[10737]=10,[10767]=1800,[10794]=30,[10797]=6,
+ [10805]=3,[10831]=5,[10834]=3,[10835]=3,[10836]=3,[10838]=8,[10839]=8,
+ [10849]=300,[10851]=15,[10852]=10,[10855]=10,[10856]=8,[10857]=35,[10888]=8,
+ [10890]=8,[10892]=18,[10893]=18,[10894]=18,[10898]=30,[10899]=30,[10900]=30,
+ [10901]=30,[10909]=60,[10911]=60,[10912]=60,[10927]=15,[10928]=15,[10929]=15,
+ [10937]=1800,[10938]=1800,[10941]=10,[10942]=10,[10951]=600,[10952]=600,
+ [10953]=15,[10955]=50,[10957]=600,[10958]=600,[10967]=20,[10968]=30,[10987]=5,
+ [11013]=120,[11014]=15,[11020]=8,[11089]=30,[11113]=6,[11131]=10,[11196]=60,
+ [11197]=30,[11198]=30,[11201]=12,[11206]=600,[11264]=10,[11273]=6,[11274]=6,
+ [11275]=6,[11285]=4,[11286]=4,[11289]=18,[11290]=18,[11297]=45,[11305]=15,
+ [11319]=1800,[11327]=10,[11328]=3600,[11329]=10,[11330]=3600,[11331]=3600,
+ [11332]=3600,[11333]=3600,[11334]=3600,[11348]=3600,[11349]=3600,[11350]=15,
+ [11353]=12,[11354]=12,[11359]=30,[11363]=180,[11364]=180,[11366]=12,[11371]=1800,
+ [11374]=180,[11389]=3600,[11390]=1800,[11391]=30,[11392]=18,[11393]=3600,
+ [11394]=3600,[11395]=3600,[11396]=3600,[11397]=300,[11398]=14,[11403]=120,
+ [11404]=3600,[11405]=3600,[11406]=300,[11407]=3600,[11426]=60,[11428]=2,
+ [11430]=2,[11436]=10,[11442]=180,[11443]=15,[11444]=20,[11445]=60,[11446]=300,
+ [11469]=12,[11470]=12,[11471]=12,[11474]=1800,[11481]=11,[11534]=20,[11538]=4,
+ [11539]=12,[11549]=120,[11550]=120,[11551]=120,[11554]=30,[11555]=30,[11556]=30,
+ [11572]=21,[11573]=21,[11574]=21,[11580]=26,[11581]=30,[11596]=30,[11597]=30,
+ [11639]=18,[11640]=15,[11641]=10,[11647]=30,[11650]=3,[11657]=20,[11658]=15,
+ [11665]=15,[11667]=15,[11668]=15,[11671]=18,[11672]=18,[11675]=15,[11683]=15,
+ [11684]=15,[11693]=10,[11694]=10,[11695]=10,[11699]=5,[11700]=5,[11703]=5,
+ [11704]=5,[11707]=120,[11708]=120,[11711]=24,[11712]=24,[11713]=24,[11717]=120,
+ [11719]=30,[11721]=300,[11722]=300,[11725]=300,[11726]=300,[11733]=1800,
+ [11734]=1800,[11735]=1800,[11739]=30,[11740]=30,[11743]=600,[11770]=180,
+ [11771]=180,[11790]=15,[11791]=30,[11820]=10,[11826]=3,[11831]=8,[11835]=30,
+ [11836]=10,[11841]=600,[11876]=5,[11877]=5,[11879]=5,[11892]=120,[11918]=15,
+ [11920]=20,[11922]=15,[11958]=10,[11960]=60,[11962]=21,[11963]=120,[11971]=30,
+ [11974]=30,[11977]=15,[11980]=120,[11983]=10,[12001]=240,[12020]=60,[12021]=10,
+ [12023]=5,[12024]=5,[12040]=30,[12042]=15,[12051]=8,[12054]=15,[12096]=8,
+ [12097]=20,[12098]=20,[12134]=12,[12160]=12,[12166]=5,[12169]=5,[12174]=1800,
+ [12175]=1800,[12176]=1800,[12177]=1800,[12178]=1800,[12179]=1800,[12241]=4,
+ [12242]=3,[12245]=300,[12248]=10,[12251]=30,[12252]=10,[12255]=900,[12257]=5,
+ [12279]=600,[12280]=60,[12292]=20,[12294]=10,[12323]=6,[12328]=30,[12355]=2,
+ [12421]=2,[12438]=10,[12461]=2,[12479]=10,[12480]=15,[12483]=15,[12484]=1.5,
+ [12485]=1.5,[12486]=1.5,[12493]=120,[12494]=5,[12505]=12,[12509]=3,[12520]=4,
+ [12521]=3,[12522]=12,[12523]=12,[12524]=12,[12525]=12,[12526]=12,[12528]=10,
+ [12530]=60,[12531]=8,[12533]=45,[12536]=15,[12540]=4,[12541]=600,[12542]=4,
+ [12543]=3,[12544]=1800,[12545]=20,[12548]=8,[12550]=600,[12551]=10,[12557]=8,
+ [12561]=60,[12562]=5,[12579]=15,[12608]=600,[12611]=8,[12613]=6,[12654]=4,
+ [12655]=4,[12674]=8,[12675]=4,[12685]=10,[12686]=15,[12705]=6,[12721]=12,
+ [12731]=8,[12733]=30,[12734]=3,[12737]=4,[12738]=10,[12741]=120,[12742]=21,
+ [12747]=10,[12748]=5,[12766]=45,[12795]=120,[12798]=3,[12809]=5,[12824]=30,
+ [12825]=40,[12826]=50,[12843]=60,[12844]=0.001,[12845]=30,[12880]=12,[12884]=45,
+ [12888]=6,[12889]=15,[12890]=15,[12891]=45,[12941]=15,[12942]=10,[12943]=10,
+ [12946]=10,[12966]=15,[12967]=15,[12968]=15,[12969]=15,[12970]=15,[12976]=20,
+ [13003]=20,[13004]=30,[13005]=4,[13007]=8,[13010]=30,[13013]=20,[13018]=6,
+ [13019]=6,[13020]=6,[13021]=6,[13031]=60,[13032]=60,[13033]=60,[13099]=10,
+ [13119]=20,[13138]=20,[13141]=20,[13158]=5,[13168]=10,[13181]=20,[13183]=10,
+ [13218]=15,[13222]=15,[13223]=15,[13224]=15,[13234]=600,[13235]=20,[13237]=3,
+ [13238]=3,[13278]=4,[13298]=30,[13318]=30,[13322]=2,[13323]=20,[13326]=1800,
+ [13327]=30,[13338]=15,[13360]=2,[13424]=30,[13438]=6,[13439]=5,[13443]=15,
+ [13444]=30,[13445]=15,[13459]=30,[13466]=7,[13488]=50,[13490]=30,[13493]=4,
+ [13494]=30,[13496]=10,[13518]=15,[13524]=60,[13526]=30,[13528]=30,[13530]=3,
+ [13532]=10,[13533]=10,[13534]=10,[13542]=5,[13543]=5,[13544]=5,[13549]=15,
+ [13550]=15,[13551]=15,[13552]=15,[13553]=15,[13554]=15,[13555]=15,[13566]=8,
+ [13578]=8,[13579]=4,[13582]=120,[13583]=120,[13585]=600,[13608]=10,[13619]=180,
+ [13692]=15,[13704]=6,[13729]=12,[13730]=30,[13736]=2,[13737]=5,[13738]=15,
+ [13744]=15,[13747]=10,[13750]=15,[13752]=30,[13787]=1800,[13797]=15,[13808]=3,
+ [13835]=3,[13847]=15,[13864]=1800,[13874]=8,[13877]=15,[13880]=30,[13884]=180,
+ [13896]=15,[13902]=5,[13903]=30,[13907]=5,[13910]=0.001,[13951]=20,[14030]=10,
+ [14032]=18,[14087]=30,[14100]=5,[14102]=2,[14110]=30,[14118]=30,[14120]=30,
+ [14130]=600,[14143]=20,[14147]=30,[14149]=20,[14180]=4,[14183]=10,[14201]=12,
+ [14202]=12,[14203]=12,[14204]=12,[14207]=5,[14251]=6,[14253]=8,[14267]=10,
+ [14268]=10,[14275]=20,[14276]=20,[14277]=20,[14278]=7,[14279]=8,[14280]=8,
+ [14296]=30,[14298]=15,[14299]=15,[14300]=15,[14301]=15,[14308]=15,[14309]=20,
+ [14323]=120,[14324]=120,[14325]=120,[14326]=15,[14327]=20,[14331]=15,[14514]=1,
+ [14515]=15,[14517]=30,[14518]=30,[14530]=10,[14532]=300,[14533]=300,[14534]=300,
+ [14535]=300,[14538]=300,[14539]=300,[14621]=20,[14743]=6,[14744]=180,
+ [14752]=1800,[14792]=30,[14795]=12,[14797]=21,[14818]=1800,[14819]=1800,
+ [14821]=15,[14822]=15,[14823]=15,[14868]=30,[14870]=3,[14871]=1,[14872]=15,
+ [14874]=10,[14875]=30,[14888]=1800,[14890]=0.001,[14893]=15,[14897]=25,[14902]=4,
+ [14903]=2,[14907]=8,[14914]=10,[15039]=12,[15041]=60,[15042]=600,[15043]=4,
+ [15044]=60,[15056]=7,[15061]=5,[15062]=10,[15063]=8,[15087]=15,[15089]=8,
+ [15091]=6,[15096]=12,[15123]=3600,[15128]=120,[15229]=15,[15231]=1800,
+ [15233]=1800,[15235]=120,[15244]=8,[15258]=15,[15261]=10,[15262]=10,[15263]=10,
+ [15264]=10,[15265]=10,[15266]=10,[15267]=10,[15269]=3,[15271]=15,[15277]=30,
+ [15279]=600,[15280]=20,[15283]=8,[15286]=60,[15288]=1800,[15346]=30,[15357]=15,
+ [15359]=15,[15366]=3600,[15398]=8,[15407]=3,[15470]=15,[15471]=8,[15474]=10,
+ [15475]=120,[15487]=5,[15494]=10,[15497]=4,[15499]=8,[15502]=30,[15505]=21,
+ [15507]=600,[15529]=10,[15530]=4,[15531]=8,[15532]=8,[15534]=20,[15535]=10,
+ [15548]=10,[15570]=21,[15571]=4,[15572]=30,[15583]=10,[15588]=10,[15593]=8,
+ [15595]=10,[15602]=30,[15604]=10,[15609]=10,[15616]=12,[15618]=2,[15621]=2,
+ [15636]=10,[15642]=5,[15646]=10,[15652]=2,[15654]=18,[15655]=2,[15656]=15,
+ [15660]=10,[15661]=21,[15662]=6,[15664]=10,[15708]=5,[15716]=120,[15727]=30,
+ [15728]=240,[15730]=180,[15732]=21,[15735]=5,[15742]=3,[15744]=6,[15752]=10,
+ [15753]=2,[15784]=60,[15790]=5,[15798]=12,[15802]=120,[15822]=12,[15848]=1800,
+ [15850]=5,[15852]=600,[15859]=5,[15860]=9,[15878]=3,[15970]=10,[15971]=30,
+ [15976]=10,[15981]=12,[16001]=9,[16037]=2,[16045]=30,[16046]=6,[16048]=60,
+ [16049]=604800,[16050]=10,[16051]=2,[16053]=60,[16071]=300,[16075]=2,[16094]=10,
+ [16095]=15,[16096]=5,[16097]=10,[16098]=600,[16099]=10,[16104]=6,[16122]=4,
+ [16128]=180,[16143]=600,[16145]=30,[16147]=21,[16168]=20,[16170]=30,[16172]=20,
+ [16177]=15,[16186]=180,[16231]=120,[16236]=15,[16237]=15,[16244]=30,[16246]=15,
+ [16247]=180,[16249]=4,[16257]=15,[16277]=15,[16278]=15,[16279]=15,[16280]=15,
+ [16310]=3,[16321]=10,[16322]=20,[16323]=1800,[16325]=600,[16326]=600,
+ [16327]=1800,[16329]=600,[16333]=120,[16336]=300,[16337]=300,[16340]=10,
+ [16350]=10,[16352]=8,[16353]=8,[16359]=30,[16361]=1.5,[16366]=60,[16373]=30,
+ [16391]=30,[16392]=30,[16393]=30,[16400]=15,[16401]=30,[16402]=3,[16403]=30,
+ [16404]=10,[16406]=30,[16412]=6,[16413]=6,[16415]=8,[16420]=0.5,[16427]=30,
+ [16429]=1800,[16430]=12,[16431]=60,[16432]=8,[16448]=1800,[16449]=1800,
+ [16451]=10,[16452]=3,[16454]=30,[16458]=1800,[16460]=1800,[16461]=1800,
+ [16469]=10,[16470]=10,[16488]=6,[16490]=6,[16491]=6,[16497]=5,[16498]=60,
+ [16499]=1800,[16508]=8,[16509]=15,[16511]=15,[16528]=10,[16532]=600,[16536]=45,
+ [16551]=3,[16552]=10,[16555]=300,[16557]=10,[16560]=15,[16561]=21,[16566]=30,
+ [16567]=600,[16568]=3,[16569]=10,[16573]=45,[16587]=600,[16591]=600,[16593]=120,
+ [16595]=600,[16597]=10,[16598]=20,[16599]=20,[16600]=5,[16601]=8,[16603]=25,
+ [16608]=4,[16609]=3600,[16610]=600,[16612]=1800,[16617]=600,[16618]=300,
+ [16621]=3,[16627]=9,[16628]=9,[16629]=30,[16637]=20,[16689]=45,[16707]=20,
+ [16708]=20,[16709]=20,[16711]=300,[16712]=300,[16713]=60,[16714]=60,[16716]=5,
+ [16717]=5,[16727]=5,[16739]=300,[16789]=15,[16790]=2,[16791]=60,[16798]=10,
+ [16799]=4,[16803]=5,[16804]=12,[16805]=10,[16810]=45,[16811]=45,[16812]=45,
+ [16813]=45,[16834]=6,[16835]=6,[16838]=5,[16843]=4,[16856]=5,[16857]=40,
+ [16864]=600,[16866]=10,[16867]=12,[16869]=10,[16870]=15,[16871]=60,[16873]=1800,
+ [16874]=600,[16875]=1800,[16876]=1800,[16877]=600,[16878]=1800,[16881]=600,
+ [16882]=600,[16883]=1200,[16884]=3600,[16885]=3600,[16886]=15,[16887]=3600,
+ [16888]=3600,[16889]=1800,[16890]=3600,[16891]=3600,[16892]=3600,[16893]=3600,
+ [16894]=3600,[16895]=3600,[16898]=30,[16916]=30,[16922]=3,[16927]=5,[16928]=45,
+ [16939]=20,[17008]=5,[17011]=5,[17013]=1800,[17014]=10,[17038]=1200,[17052]=300,
+ [17057]=3,[17105]=12,[17134]=60,[17139]=30,[17140]=8,[17141]=8,[17142]=8,
+ [17145]=6,[17146]=18,[17148]=30,[17150]=1800,[17151]=600,[17152]=10,[17153]=30,
+ [17154]=30,[17158]=10,[17165]=3,[17168]=10,[17170]=12,[17172]=5,[17173]=5,
+ [17174]=3,[17175]=3600,[17177]=8,[17179]=20,[17183]=15,[17189]=20,[17196]=30,
+ [17197]=6,[17205]=1200,[17207]=2,[17213]=900,[17227]=120,[17230]=300,[17238]=5,
+ [17243]=5,[17244]=120,[17246]=120,[17250]=120,[17252]=1800,[17272]=2,[17273]=12,
+ [17274]=12,[17275]=300,[17276]=4,[17277]=6,[17281]=30,[17286]=4,[17292]=30,
+ [17293]=8,[17307]=6,[17308]=2,[17311]=3,[17312]=3,[17313]=3,[17314]=3,[17315]=30,
+ [17329]=45,[17330]=20,[17331]=10,[17333]=10,[17347]=15,[17348]=15,[17351]=10,
+ [17352]=10,[17364]=12,[17368]=3,[17390]=40,[17391]=40,[17392]=40,[17398]=5,
+ [17405]=15,[17407]=25,[17445]=20,[17446]=10,[17447]=10,[17473]=12,[17483]=6,
+ [17484]=30,[17492]=5,[17494]=30,[17499]=30,[17500]=2,[17503]=4,[17504]=30,
+ [17505]=60,[17506]=30,[17510]=3,[17511]=20,[17528]=20,[17535]=3600,[17537]=3600,
+ [17538]=3600,[17539]=3600,[17540]=120,[17543]=3600,[17544]=3600,[17545]=3600,
+ [17546]=3600,[17547]=5,[17548]=3600,[17549]=3600,[17620]=5,[17624]=60,
+ [17626]=7200,[17627]=7200,[17628]=7200,[17629]=7200,[17633]=30,[17639]=12,
+ [17651]=6,[17668]=1,[17680]=60,[17682]=5,[17686]=10,[17687]=15,[17691]=300,
+ [17692]=5,[17697]=5,[17715]=15,[17716]=1.5,[17729]=60,[17730]=60,[17734]=3600,
+ [17738]=14,[17740]=60,[17741]=60,[17743]=120,[17745]=10,[17767]=10,[17771]=30,
+ [17772]=5,[17774]=8,[17794]=12,[17797]=12,[17798]=12,[17799]=12,[17800]=12,
+ [17820]=15,[17831]=60,[17850]=10,[17851]=10,[17852]=10,[17853]=10,[17854]=10,
+ [17862]=300,[17877]=5,[17883]=21,[17925]=3,[17926]=3,[17928]=15,[17937]=300,
+ [17941]=10,[17961]=1800,[17963]=30,[18070]=30,[18075]=30,[18077]=15,[18078]=30,
+ [18082]=6,[18088]=3,[18093]=3,[18097]=30,[18099]=10,[18100]=1800,[18101]=5,
+ [18103]=2,[18105]=8,[18106]=30,[18108]=8,[18118]=5,[18124]=27,[18125]=600,
+ [18137]=600,[18140]=30,[18141]=600,[18144]=2,[18149]=120,[18151]=120,[18159]=900,
+ [18163]=1800,[18165]=8,[18172]=300,[18173]=20,[18191]=600,[18192]=600,
+ [18193]=600,[18194]=600,[18197]=15,[18199]=6,[18200]=30,[18202]=30,[18203]=30,
+ [18208]=25,[18209]=604800,[18210]=604800,[18222]=600,[18223]=12,[18229]=27,
+ [18230]=27,[18231]=27,[18232]=27,[18233]=27,[18234]=27,[18265]=30,[18266]=15,
+ [18267]=30,[18270]=90,[18278]=6,[18288]=30,[18289]=15,[18327]=10,[18328]=60,
+ [18347]=600,[18364]=15,[18371]=10,[18376]=24,[18377]=300,[18381]=30,[18395]=2,
+ [18396]=0.001,[18425]=2,[18431]=3,[18461]=1,[18469]=4,[18498]=3,[18499]=10,
+ [18501]=5,[18502]=120,[18503]=10,[18520]=30,[18543]=21,[18545]=20,[18546]=6,
+ [18557]=5,[18608]=8,[18610]=8,[18633]=30,[18647]=30,[18652]=15,[18654]=15,
+ [18656]=3,[18657]=30,[18658]=40,[18671]=30,[18702]=60,[18708]=15,[18733]=5,
+ [18747]=300,[18763]=15,[18765]=20,[18787]=30,[18789]=1800,[18790]=1800,
+ [18791]=1800,[18792]=1800,[18796]=6,[18798]=5,[18802]=10,[18803]=4,[18807]=3,
+ [18809]=12,[18810]=3600,[18811]=2,[18812]=2,[18820]=10,[18826]=10,[18828]=20,
+ [18867]=5,[18868]=5,[18869]=5,[18870]=5,[18871]=5,[18874]=7,[18879]=30,
+ [18880]=30,[18881]=30,[18942]=3600,[18946]=30,[18948]=300,[18949]=30,[18956]=30,
+ [18957]=30,[18958]=45,[18968]=600,[18972]=20,[18977]=10,[19030]=300,[19128]=2,
+ [19133]=8,[19134]=8,[19135]=15,[19136]=5,[19137]=20,[19185]=5,[19229]=5,
+ [19231]=300,[19249]=120,[19251]=120,[19252]=120,[19253]=120,[19254]=120,
+ [19261]=600,[19262]=600,[19263]=10,[19264]=600,[19265]=600,[19266]=600,
+ [19271]=15,[19273]=15,[19274]=15,[19275]=15,[19276]=24,[19277]=24,[19278]=24,
+ [19279]=24,[19280]=24,[19281]=120,[19282]=120,[19283]=120,[19284]=120,
+ [19285]=120,[19289]=15,[19291]=15,[19292]=15,[19293]=15,[19296]=6,[19299]=6,
+ [19302]=6,[19303]=6,[19304]=6,[19305]=6,[19306]=5,[19308]=600,[19309]=600,
+ [19310]=600,[19311]=600,[19312]=600,[19364]=5,[19365]=900,[19366]=900,
+ [19367]=900,[19369]=5,[19372]=900,[19386]=12,[19393]=16,[19397]=60,[19408]=8,
+ [19410]=3,[19428]=8,[19438]=30,[19440]=30,[19441]=30,[19442]=30,[19443]=30,
+ [19448]=30,[19450]=30,[19451]=8,[19463]=10,[19469]=15,[19478]=60,[19479]=10,
+ [19482]=2,[19486]=20,[19496]=15,[19503]=4,[19514]=600,[19516]=1800,[19548]=20,
+ [19574]=18,[19577]=15,[19597]=900,[19615]=8,[19631]=60,[19634]=15,[19635]=60,
+ [19636]=6,[19638]=30,[19641]=6,[19643]=5,[19645]=10,[19652]=10,[19653]=10,
+ [19654]=10,[19655]=60,[19656]=60,[19659]=300,[19660]=60,[19674]=20,[19675]=4,
+ [19676]=900,[19677]=900,[19678]=900,[19679]=900,[19680]=900,[19681]=900,
+ [19682]=900,[19683]=900,[19684]=900,[19685]=900,[19686]=900,[19687]=20,
+ [19688]=20,[19689]=20,[19690]=900,[19692]=20,[19693]=20,[19694]=20,[19695]=8,
+ [19696]=20,[19697]=20,[19699]=20,[19700]=20,[19702]=10,[19703]=300,[19705]=900,
+ [19706]=900,[19708]=900,[19709]=900,[19710]=900,[19711]=900,[19713]=300,
+ [19714]=30,[19716]=300,[19725]=20,[19727]=3600,[19740]=300,[19742]=300,
+ [19753]=180,[19755]=60,[19769]=3,[19771]=30,[19776]=18,[19778]=30,[19779]=10,
+ [19780]=2,[19784]=4,[19812]=8,[19820]=20,[19821]=5,[19822]=10,[19832]=90,
+ [19834]=300,[19835]=300,[19836]=300,[19837]=300,[19838]=300,[19850]=300,
+ [19852]=300,[19853]=300,[19854]=300,[19872]=30,[19937]=900,[19952]=10,[19953]=10,
+ [19970]=27,[19971]=24,[19972]=21,[19973]=18,[19974]=15,[19975]=12,[19977]=300,
+ [19978]=300,[19979]=300,[20005]=5,[20006]=12,[20007]=15,[20019]=6,[20050]=8,
+ [20052]=8,[20053]=8,[20054]=8,[20055]=8,[20066]=6,[20128]=10,[20131]=10,
+ [20132]=10,[20133]=10,[20134]=10,[20154]=30,[20162]=30,[20164]=30,[20165]=30,
+ [20166]=30,[20170]=2,[20184]=10,[20185]=10,[20186]=10,[20188]=10,[20217]=300,
+ [20223]=10,[20228]=12,[20229]=8,[20230]=15,[20233]=120,[20236]=120,[20253]=3,
+ [20276]=2,[20277]=4,[20287]=30,[20288]=30,[20289]=30,[20290]=30,[20291]=30,
+ [20292]=30,[20293]=30,[20294]=21,[20297]=4,[20300]=10,[20301]=10,[20302]=10,
+ [20303]=10,[20305]=30,[20306]=30,[20307]=30,[20308]=30,[20310]=2,[20344]=10,
+ [20345]=10,[20346]=10,[20347]=30,[20348]=30,[20349]=30,[20354]=10,[20355]=10,
+ [20356]=30,[20357]=30,[20375]=30,[20436]=30,[20475]=8,[20478]=8,[20481]=1800,
+ [20507]=1,[20508]=0.001,[20510]=15,[20511]=8,[20512]=20,[20541]=0.1,[20542]=15,
+ [20544]=2,[20545]=600,[20547]=8,[20548]=3,[20549]=2,[20553]=2,[20559]=6,
+ [20560]=6,[20564]=8,[20570]=10,[20578]=10,[20586]=20,[20587]=600,[20590]=600,
+ [20594]=8,[20600]=20,[20604]=15,[20612]=8,[20614]=3,[20615]=3,[20619]=10,
+ [20620]=300,[20624]=3600,[20629]=10,[20631]=10,[20654]=15,[20655]=60,[20656]=60,
+ [20663]=10,[20664]=12,[20665]=21,[20667]=30,[20668]=10,[20669]=10,[20672]=3,
+ [20683]=5,[20685]=8,[20690]=12,[20697]=30,[20699]=15,[20701]=12,[20706]=30,
+ [20707]=1800,[20716]=10,[20717]=10,[20729]=30,[20733]=60,[20740]=15,[20743]=5,
+ [20753]=30,[20762]=1800,[20763]=1800,[20764]=1800,[20765]=1800,[20785]=1800,
+ [20786]=10,[20787]=21,[20792]=4,[20798]=1800,[20800]=21,[20806]=4,[20812]=15,
+ [20819]=4,[20822]=4,[20826]=21,[20828]=8,[20875]=900,[20882]=300,[20909]=5,
+ [20910]=5,[20911]=300,[20912]=300,[20913]=300,[20914]=300,[20915]=30,[20918]=30,
+ [20919]=30,[20920]=30,[20925]=10,[20927]=10,[20928]=10,[20988]=4,[20989]=10,
+ [21007]=120,[21008]=6,[21030]=8,[21047]=10,[21048]=1800,[21049]=30,[21055]=30,
+ [21056]=60,[21060]=10,[21062]=30,[21063]=45,[21066]=10,[21067]=10,[21068]=24,
+ [21069]=6,[21075]=10,[21081]=30,[21082]=30,[21084]=30,[21086]=1800,[21087]=1800,
+ [21090]=1800,[21091]=10,[21095]=5,[21098]=30,[21099]=5,[21141]=30,[21149]=18,
+ [21151]=30,[21152]=3,[21153]=10,[21159]=8,[21162]=10,[21163]=1800,[21165]=10,
+ [21167]=1,[21171]=120,[21172]=10,[21174]=10,[21183]=10,[21188]=2,[21307]=7200,
+ [21330]=2,[21331]=15,[21335]=600,[21337]=600,[21340]=600,[21354]=3,[21369]=4,
+ [21401]=8,[21403]=1800,[21425]=120,[21540]=10,[21546]=900,[21547]=5,[21551]=10,
+ [21552]=10,[21553]=10,[21556]=1800,[21562]=3600,[21564]=3600,[21566]=1800,
+ [21655]=1,[21669]=12,[21670]=60,[21687]=15,[21708]=15,[21736]=7200,[21740]=4,
+ [21748]=2,[21749]=2,[21787]=120,[21793]=10,[21794]=16,[21808]=8,[21827]=600,
+ [21833]=8,[21840]=6,[21847]=6,[21849]=3600,[21850]=3600,[21860]=5,[21863]=600,
+ [21866]=16,[21869]=8,[21878]=15,[21887]=10,[21892]=2,[21896]=5,[21898]=2,
+ [21909]=8,[21920]=1800,[21921]=4,[21925]=4,[21927]=4,[21929]=4,[21932]=4,
+ [21936]=60,[21949]=30,[21952]=20,[21955]=10,[21956]=10,[21961]=30,[21970]=60,
+ [21971]=10,[21976]=4,[21980]=60,[21990]=4,[21992]=12,[22008]=10,[22009]=15,
+ [22011]=30,[22067]=10,[22127]=10,[22128]=600,[22168]=20,[22187]=30,[22206]=12,
+ [22247]=6,[22272]=5,[22274]=20,[22284]=5,[22289]=6,[22290]=6,[22291]=5,
+ [22335]=30,[22356]=10,[22357]=2,[22371]=120,[22373]=21,[22412]=30,[22415]=10,
+ [22417]=30,[22418]=1800,[22419]=4,[22420]=60,[22423]=12,[22424]=6,[22426]=30,
+ [22427]=5,[22428]=8,[22433]=20,[22438]=30,[22440]=0.001,[22442]=6,[22478]=15,
+ [22479]=6,[22519]=2,[22558]=5,[22559]=6,[22561]=1,[22566]=8,[22570]=2,[22572]=5,
+ [22582]=8,[22592]=2,[22639]=30,[22640]=5,[22642]=6,[22643]=4,[22645]=8,
+ [22646]=0.001,[22651]=8,[22652]=10,[22660]=30,[22661]=10,[22662]=21,[22666]=6,
+ [22667]=15,[22678]=6,[22682]=10,[22685]=1800,[22686]=4,[22687]=6,[22688]=30,
+ [22689]=20,[22690]=4,[22691]=6,[22692]=8,[22693]=10,[22695]=21,[22703]=2,
+ [22707]=1.7,[22710]=30,[22713]=20,[22730]=600,[22731]=27,[22734]=30,[22735]=7200,
+ [22736]=600,[22739]=8,[22742]=20,[22744]=10,[22746]=8,[22751]=120,[22752]=900,
+ [22782]=1800,[22783]=1800,[22788]=604800,[22789]=900,[22790]=900,[22800]=8,
+ [22807]=3600,[22812]=15,[22817]=7200,[22818]=7200,[22820]=7200,[22822]=6,
+ [22823]=6,[22833]=10,[22835]=60,[22839]=15,[22842]=10,[22850]=10,[22857]=15,
+ [22859]=5,[22863]=10,[22884]=4,[22888]=7200,[22895]=10,[22896]=10,[22901]=30,
+ [22909]=4,[22911]=2,[22914]=3,[22915]=3,[22917]=240,[22919]=3,[22924]=10,
+ [22935]=3,[22937]=10,[22948]=5,[22959]=30,[22969]=5,[22992]=11,[22994]=10,
+ [22997]=40,[22998]=3,[23006]=3,[23009]=2,[23010]=1,[23015]=18,[23016]=18,
+ [23023]=10,[23028]=3600,[23038]=12,[23039]=6,[23055]=2,[23060]=240,[23097]=5,
+ [23099]=15,[23102]=4,[23103]=10,[23108]=10,[23109]=15,[23110]=15,[23113]=6,
+ [23115]=8,[23120]=6,[23126]=300,[23128]=8,[23131]=5,[23132]=5,[23145]=15,
+ [23147]=15,[23148]=15,[23153]=600,[23154]=600,[23155]=600,[23162]=10,[23164]=20,
+ [23165]=30,[23169]=600,[23170]=600,[23171]=4,[23174]=300,[23175]=300,[23177]=300,
+ [23179]=1200,[23182]=900,[23183]=12,[23186]=90,[23187]=15,[23189]=15,[23205]=45,
+ [23207]=10,[23224]=8,[23226]=6,[23230]=25,[23234]=15,[23244]=4,[23257]=30,
+ [23260]=20,[23262]=30,[23268]=18,[23269]=4,[23270]=20,[23271]=15,[23273]=0.1,
+ [23274]=0.1,[23275]=5,[23276]=0.1,[23277]=0.1,[23279]=30,[23298]=45,[23299]=18,
+ [23303]=5,[23310]=8,[23312]=8,[23313]=15,[23314]=15,[23315]=60,[23316]=60,
+ [23331]=8,[23340]=8,[23341]=20,[23342]=10,[23355]=20,[23364]=2,[23365]=8,
+ [23379]=30,[23380]=12,[23387]=1,[23388]=2,[23397]=30,[23398]=30,[23401]=30,
+ [23402]=30,[23410]=30,[23411]=8,[23412]=9,[23414]=30,[23415]=5,[23417]=6,
+ [23418]=30,[23425]=30,[23427]=0.001,[23444]=10,[23445]=7200,[23447]=5,[23449]=24,
+ [23451]=10,[23452]=90,[23454]=1,[23456]=10,[23457]=10,[23461]=15,[23492]=5,
+ [23493]=10,[23505]=60,[23506]=20,[23511]=30,[23513]=180,[23537]=600,[23552]=600,
+ [23567]=8,[23568]=8,[23569]=8,[23577]=7,[23580]=6,[23600]=6,[23601]=4,[23603]=20,
+ [23605]=5,[23618]=10,[23619]=15,[23620]=20,[23684]=15,[23693]=120,[23694]=5,
+ [23696]=8,[23697]=600,[23698]=30,[23719]=8,[23720]=30,[23721]=10,[23723]=20,
+ [23724]=20,[23726]=20,[23733]=20,[23734]=20,[23735]=7200,[23736]=7200,
+ [23737]=7200,[23738]=7200,[23766]=7200,[23767]=7200,[23768]=7200,[23769]=7200,
+ [23770]=14400,[23780]=20,[23782]=20,[23790]=3600,[23848]=10,[23850]=10,[23860]=8,
+ [23862]=10,[23865]=10,[23885]=8,[23886]=8,[23887]=8,[23888]=8,[23895]=15,
+ [23918]=10,[23919]=2,[23931]=10,[23947]=3600,[23948]=3600,[23951]=15,[23952]=18,
+ [23953]=10,[23958]=60,[23964]=600,[23978]=10,[23991]=15,[24002]=8,[24003]=8,
+ [24004]=10,[24005]=25,[24011]=10,[24018]=10,[24020]=2,[24021]=8,[24043]=6,
+ [24048]=2,[24049]=10,[24053]=5,[24054]=120,[24057]=2,[24065]=5,[24066]=4,
+ [24086]=604800,[24087]=20,[24097]=30,[24099]=10,[24109]=60,[24110]=8,[24111]=30,
+ [24131]=12,[24132]=12,[24133]=12,[24134]=12,[24135]=12,[24152]=15,[24170]=18,
+ [24178]=20,[24185]=30,[24192]=6,[24193]=2,[24203]=30,[24210]=120,[24212]=18,
+ [24213]=2,[24217]=30,[24221]=60,[24223]=10,[24225]=6,[24236]=2,[24238]=12,
+ [24244]=300,[24255]=12,[24259]=3,[24268]=30,[24300]=7,[24306]=20,[24312]=604800,
+ [24314]=6,[24317]=20,[24318]=90,[24321]=90,[24322]=8,[24323]=8,[24324]=8,
+ [24327]=10,[24328]=10,[24331]=9,[24332]=9,[24333]=2,[24335]=12,[24336]=12,
+ [24339]=180,[24345]=5,[24348]=4,[24352]=20,[24354]=20,[24355]=30,[24360]=12,
+ [24361]=3600,[24363]=3600,[24364]=5,[24375]=5,[24378]=60,[24379]=10,[24382]=7200,
+ [24383]=7200,[24388]=30,[24389]=60,[24390]=10,[24394]=3,[24395]=15,[24396]=15,
+ [24397]=15,[24408]=2,[24412]=8,[24413]=8,[24414]=8,[24415]=20,[24417]=7200,
+ [24423]=4,[24425]=7200,[24427]=60,[24435]=5,[24438]=20,[24498]=15,[24499]=20,
+ [24542]=15,[24543]=20,[24544]=20,[24546]=15,[24573]=5,[24574]=20,[24575]=20,
+ [24577]=4,[24578]=4,[24579]=4,[24583]=10,[24586]=10,[24587]=10,[24594]=7,
+ [24596]=120,[24597]=10,[24600]=7,[24603]=10,[24604]=10,[24605]=10,[24610]=15,
+ [24611]=9,[24614]=15,[24615]=1.5,[24617]=10,[24618]=5,[24619]=12,[24640]=10,
+ [24646]=15,[24647]=2,[24648]=10,[24658]=20,[24659]=20,[24661]=20,[24662]=20,
+ [24664]=6,[24671]=2,[24672]=20,[24673]=600,[24674]=10,[24686]=6,[24687]=5,
+ [24688]=10,[24689]=8,[24690]=2,[24692]=604800,[24698]=4,[24699]=20,[24700]=2,
+ [24701]=15,[24705]=7200,[24707]=25,[24708]=3600,[24709]=3600,[24710]=3600,
+ [24711]=3600,[24712]=3600,[24713]=3600,[24716]=3,[24723]=3600,[24725]=15,
+ [24732]=3600,[24734]=4,[24735]=3600,[24736]=3600,[24740]=3600,[24742]=18,
+ [24743]=5,[24744]=4,[24745]=1,[24747]=1,[24752]=1800,[24753]=45,[24754]=6,
+ [24755]=3600,[24756]=4,[24757]=1,[24758]=4,[24759]=1,[24760]=4,[24761]=1,
+ [24762]=1,[24763]=4,[24765]=4,[24766]=1,[24768]=4,[24769]=1,[24770]=4,[24771]=1,
+ [24772]=4,[24773]=1,[24776]=0.001,[24778]=5,[24783]=4,[24784]=4,[24785]=1,
+ [24786]=4,[24787]=1,[24788]=4,[24789]=4,[24790]=4,[24791]=1,[24792]=1,[24793]=1,
+ [24798]=900,[24799]=900,[24800]=30,[24803]=4,[24811]=5,[24818]=30,[24828]=3,
+ [24832]=5,[24833]=600,[24839]=45,[24865]=25,[24869]=24,[24870]=900,[24871]=5,
+ [24884]=10,[24893]=11,[24906]=10,[24910]=10,[24918]=120,[24919]=5,[24920]=2,
+ [24924]=1200,[24925]=1200,[24926]=1200,[24927]=1200,[24928]=120,[24935]=300,
+ [24937]=300,[24942]=4,[24948]=5,[24957]=12,[24974]=12,[24975]=12,[24976]=12,
+ [24977]=12,[24984]=15,[24991]=7200,[24992]=15,[24998]=15,[25006]=300,[25020]=600,
+ [25022]=6,[25023]=1800,[25029]=2,[25037]=900,[25040]=900,[25042]=12,[25043]=90,
+ [25049]=6,[25050]=120,[25051]=20,[25053]=30,[25056]=2,[25057]=10,[25058]=15,
+ [25098]=8,[25101]=900,[25102]=60,[25161]=1,[25164]=30,[25165]=15,[25174]=30,
+ [25177]=45,[25178]=45,[25180]=45,[25181]=45,[25183]=45,[25185]=8,[25187]=30,
+ [25189]=10,[25195]=15,[25199]=1800,[25260]=6,[25262]=10,[25282]=6,[25289]=120,
+ [25290]=300,[25291]=300,[25295]=15,[25299]=12,[25304]=9,[25306]=8,[25309]=15,
+ [25311]=18,[25315]=15,[25345]=5,[25348]=12,[25349]=12,[25371]=15,[25374]=15,
+ [25410]=15,[25424]=10,[25425]=2,[25462]=60,[25471]=10,[25473]=10,[25495]=8,
+ [25497]=8,[25503]=10,[25515]=5,[25516]=30,[25565]=0.1,[25605]=15,[25645]=30,
+ [25646]=15,[25651]=20,[25654]=2,[25655]=8,[25656]=20,[25660]=30,[25661]=900,
+ [25668]=20,[25678]=180,[25685]=604800,[25688]=1800,[25694]=900,[25695]=30,
+ [25696]=30,[25697]=30,[25698]=7,[25700]=21,[25701]=21,[25702]=21,[25703]=21,
+ [25722]=900,[25725]=10,[25746]=15,[25747]=15,[25748]=10,[25750]=15,[25751]=30,
+ [25752]=10,[25756]=2,[25757]=10,[25768]=8,[25771]=60,[25772]=120,[25773]=120,
+ [25774]=3,[25780]=1800,[25782]=900,[25790]=600,[25794]=3600,[25795]=3600,
+ [25796]=3600,[25797]=3600,[25798]=3600,[25799]=3600,[25804]=900,[25805]=15,
+ [25806]=30,[25809]=12,[25810]=12,[25811]=10,[25812]=16,[25815]=6,[25816]=120,
+ [25821]=2,[25824]=604800,[25838]=20,[25839]=12,[25851]=30,[25852]=2,[25864]=1,
+ [25886]=21,[25887]=21,[25888]=21,[25889]=21,[25890]=900,[25891]=20,
+ [25893]=604800,[25894]=900,[25895]=900,[25898]=900,[25899]=900,[25907]=10,
+ [25916]=900,[25918]=900,[25937]=15,[25941]=900,[25942]=10,[25945]=10,
+ [25947]=1800,[25990]=20,[25991]=10,[25999]=1,[26004]=1800,[26008]=1800,
+ [26009]=300,[26013]=900,[26015]=1,[26017]=10,[26018]=10,[26025]=8,[26030]=27,
+ [26035]=1800,[26038]=8,[26041]=10,[26042]=4,[26043]=30,[26044]=8,[26049]=8,
+ [26050]=30,[26051]=8,[26053]=8,[26064]=12,[26068]=3600,[26069]=10,[26070]=8,
+ [26071]=15,[26072]=12,[26077]=8,[26078]=30,[26079]=10,[26083]=15,[26099]=30,
+ [26102]=5,[26108]=3,[26121]=8,[26129]=20,[26132]=8,[26136]=300,[26141]=10,
+ [26143]=10,[26157]=1800,[26166]=30,[26168]=30,[26177]=4,[26178]=4,[26179]=4,
+ [26180]=12,[26195]=20,[26196]=15,[26197]=20,[26198]=30,[26199]=1800,[26201]=4,
+ [26211]=10,[26218]=3600,[26222]=1.5,[26226]=4,[26235]=45,[26258]=20,[26259]=12,
+ [26260]=30,[26261]=30,[26263]=25,[26272]=1800,[26273]=1800,[26274]=1800,
+ [26276]=1800,[26331]=20,[26332]=3.8,[26379]=6,[26381]=10,[26382]=3,[26386]=12,
+ [26387]=1200,[26390]=10,[26393]=3600,[26400]=20,[26401]=30,[26402]=30,[26419]=10,
+ [26462]=1800,[26463]=60,[26464]=60,[26467]=30,[26470]=8,[26472]=30,[26473]=30,
+ [26474]=30,[26475]=30,[26480]=30,[26522]=1800,[26525]=20,[26527]=120,[26542]=10,
+ [26548]=8,[26552]=8,[26556]=40,[26580]=8,[26592]=15,[26601]=10,[26613]=6,
+ [26615]=3600,[26619]=45,[26634]=604800,[26635]=10,[26637]=1.7,[26641]=3,
+ [26650]=0.1,[26651]=1,[26652]=10,[26662]=300,[26664]=3600,[26680]=3600,
+ [26681]=3600,[26682]=3600,[26740]=20,[26787]=0.001,[26802]=3600,[26898]=3600,
+ [26977]=60,[27039]=4,[27042]=4,[27177]=10,[27183]=300,[27192]=300,[27193]=300,
+ [27194]=300,[27195]=300,[27196]=300,[27197]=300,[27198]=300,[27199]=300,
+ [27200]=300,[27205]=4,[27208]=4,[27420]=3,[27499]=10,[27532]=12,[27533]=6,
+ [27534]=6,[27535]=6,[27536]=6,[27538]=6,[27540]=6,[27543]=10,[27545]=10,
+ [27551]=30,[27553]=2,[27555]=10,[27556]=15,[27559]=3,[27564]=5,[27565]=10,
+ [27568]=604800,[27569]=604800,[27571]=120,[27572]=3600,[27575]=600,[27578]=120,
+ [27579]=30,[27580]=10,[27581]=10,[27582]=30,[27584]=15,[27603]=8,[27605]=18,
+ [27606]=15,[27607]=30,[27610]=8,[27615]=5,[27616]=600,[27619]=10,[27620]=4,
+ [27633]=10,[27634]=3,[27636]=6,[27637]=21,[27638]=15,[27640]=3,[27641]=6,
+ [27648]=12,[27652]=1800,[27653]=1800,[27664]=3600,[27665]=3600,[27666]=3600,
+ [27669]=3600,[27670]=3600,[27671]=3600,[27672]=5,[27673]=30,[27675]=15,
+ [27680]=600,[27681]=3600,[27683]=1200,[27685]=4,[27688]=300,[27689]=30,
+ [27720]=3600,[27721]=3600,[27722]=3600,[27723]=3600,[27737]=12,[27758]=5,
+ [27759]=30,[27760]=15,[27775]=10,[27779]=30,[27807]=20,[27808]=5,[27813]=6,
+ [27814]=6,[27817]=6,[27818]=6,[27819]=5,[27825]=15,[27827]=10,[27828]=6,
+ [27841]=1800,[27852]=0.1,[27857]=300,[27861]=2700,[27863]=600,[27864]=300,
+ [27865]=60,[27868]=3,[27873]=10,[27874]=10,[27880]=3,[27891]=20,[27897]=600,
+ [27965]=1,[27990]=4,[27991]=30,[27993]=12,[27994]=5,[27995]=20,[28007]=230,
+ [28009]=180,[28011]=120,[28018]=7200,[28059]=60,[28084]=60,[28095]=3600,
+ [28127]=8,[28131]=300,[28134]=10,[28137]=3,[28158]=60,[28169]=10,[28190]=30,
+ [28200]=20,[28225]=300,[28270]=50,[28271]=50,[28272]=50,[28310]=8,[28311]=10,
+ [28314]=3,[28315]=2,[28316]=3,[28323]=2,[28333]=2,[28334]=6,[28335]=2,[28342]=90,
+ [28350]=7,[28362]=604800,[28371]=8,[28374]=3,[28391]=1,[28406]=8,[28409]=20,
+ [28410]=20,[28412]=3,[28413]=8,[28418]=120,[28419]=120,[28420]=120,[28431]=9,
+ [28434]=1,[28440]=6,[28445]=3,[28450]=0.1,[28456]=6,[28467]=15,[28478]=4,
+ [28479]=4,[28498]=300,[28522]=25,[28531]=5,[28542]=12,[28608]=24,[28609]=30,
+ [28610]=30,[28616]=30,[28618]=1,[28619]=2,[28620]=2,[28621]=2,[28622]=60,
+ [28627]=55,[28679]=60,[28681]=1800,[28701]=20,[28725]=5,[28727]=30,[28732]=30,
+ [28747]=600,[28750]=4,[28754]=15,[28757]=4,[28762]=8,[28765]=30,[28766]=30,
+ [28768]=30,[28769]=30,[28770]=30,[28772]=30,[28773]=20,[28776]=30,[28777]=20,
+ [28778]=20,[28779]=20,[28780]=30,[28785]=20,[28786]=6,[28790]=8,[28791]=8,
+ [28793]=8,[28795]=8,[28796]=8,[28798]=1800,[28804]=30,[28810]=30,[28824]=8,
+ [28825]=8,[28826]=8,[28827]=8,[28832]=75,[28833]=75,[28834]=75,[28835]=75,
+ [28846]=5,[28858]=15,[28862]=20,[28866]=15,[28882]=8,[28911]=18,[28913]=10,
+ [28969]=10,[28991]=10,[28995]=6,[29001]=3600,[29002]=3600,[29003]=3600,
+ [29006]=1800,[29007]=30,[29008]=30,[29035]=15,[29038]=21,[29039]=21,[29040]=900,
+ [29041]=30,[29042]=20,[29051]=60,[29055]=25,[29060]=20,[29061]=20,[29063]=6,
+ [29073]=30,[29104]=5,[29124]=20,[29131]=10,[29134]=5,[29163]=5,[29164]=5,
+ [29166]=20,[29168]=6,[29169]=10,[29175]=3600,[29177]=10,[29178]=10,[29183]=60,
+ [29184]=60,[29185]=120,[29194]=120,[29195]=60,[29196]=120,[29197]=60,[29198]=120,
+ [29199]=60,[29203]=15,[29204]=10,[29207]=1,[29208]=1,[29209]=1,[29210]=1,
+ [29211]=1,[29212]=15,[29213]=10,[29214]=10,[29220]=300,[29228]=12,[29232]=90,
+ [29233]=4,[29235]=3600,[29252]=5,[29261]=5,[29265]=5,[29270]=5,[29274]=1,
+ [29296]=2,[29306]=60,[29325]=25,[29330]=25,[29331]=3600,[29332]=3600,
+ [29333]=3600,[29334]=3600,[29335]=3600,[29338]=3600,[29350]=45,[29388]=12,
+ [29407]=10,[29419]=10,[29432]=3600,[29484]=10,[29506]=20,[29530]=1,[29534]=1800,
+ [29544]=8,[29602]=20,[29607]=0.001,[29685]=5,[29825]=30,[29846]=3600,[29848]=20,
+ [29849]=8,[29851]=2,[29865]=12,[29871]=5,[29910]=1,[29915]=10,[29943]=8,
+ [29998]=21,[30001]=8,[30002]=6,[30003]=7200,[30020]=10,[30080]=300,[30081]=300,
+ [30082]=3,[30088]=3600,[30089]=3600,[30090]=3600,[30092]=8,[30094]=8,[30095]=8,
+ [30109]=5,[30110]=604800,[30112]=2,[30113]=30,[30165]=10,[30167]=600,[30225]=8,
+ [30238]=1800,[30285]=15,[30297]=1800,[30331]=7200,[30336]=7200,[30338]=7200,
+ [30440]=30,[30441]=30,[30803]=10,[30804]=10,[30805]=10,[30806]=10,[30807]=10,
+ [30918]=1,[31248]=1,[31316]=0.1,[31362]=1,[31466]=1,[31562]=6,[31800]=27,
+ [301100]=3,[301101]=3,
+}
+
+lib:SetDataVersion(Type, Version)
\ No newline at end of file
diff --git a/lib/LibStub/LibStub.lua b/lib/LibStub/LibStub.lua
new file mode 100644
index 0000000..0a41ac0
--- /dev/null
+++ b/lib/LibStub/LibStub.lua
@@ -0,0 +1,30 @@
+-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+ LibStub = LibStub or {libs = {}, minors = {} }
+ _G[LIBSTUB_MAJOR] = LibStub
+ LibStub.minor = LIBSTUB_MINOR
+
+ function LibStub:NewLibrary(major, minor)
+ assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+ minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+ local oldminor = self.minors[major]
+ if oldminor and oldminor >= minor then return nil end
+ self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+ return self.libs[major], oldminor
+ end
+
+ function LibStub:GetLibrary(major, silent)
+ if not self.libs[major] and not silent then
+ error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+ end
+ return self.libs[major], self.minors[major]
+ end
+
+ function LibStub:IterateLibraries() return pairs(self.libs) end
+ setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
diff --git a/localization.cn.lua b/localization.cn.lua
new file mode 100644
index 0000000..39877bb
--- /dev/null
+++ b/localization.cn.lua
@@ -0,0 +1,427 @@
+-------------------------------------------------------------------------------
+-- Simplified Chinese localization
+-- By Kurax Kuang
+-------------------------------------------------------------------------------
+
+if (GetLocale() == "zhCN") then
+
+-- smartbuff credits
+SMARTBUFF_CREDITS = "|cffffffff"
+ .."Codermik 的 Classic 版本。 请在 CurseForge 或我的 discord 上报告任何问题:\n\n"
+ .."|cff00e0ffhttps://discord.gg/R6EkZ94TKK\n\n"
+ .."|cffffffff如果您感谢所涉及的工作量以及为您带来这些各种插件所花费的时间,请考虑通过以下方式支持我:\n\n"
+ .."|cffffffffPatreon: |cff00e0ffhttps://www.patreon.com/codermik\n"
+ .."|cffffffffTwitch: |cff00e0ffhttps://www.twitch.tv/codermik\n"
+ .."|cffffffffPayPal.Me: |cff00e0ffhttps://paypal.me/codermik\n\n"
+;
+
+-- 德鲁伊
+SMARTBUFF_DRUID_CAT = "猎豹形态";
+SMARTBUFF_DRUID_MOONKIN = "枭兽形态";
+SMARTBUFF_DRUID_TRACK = "追踪人型生物";
+
+SMARTBUFF_MOTW = "野性印记";
+SMARTBUFF_GOTW = "野性赐福";
+SMARTBUFF_THORNS = "荆棘术";
+SMARTBUFF_OMENOFCLARITY = "清晰预兆";
+SMARTBUFF_BARKSKIN = "树皮术";
+SMARTBUFF_NATURESGRASP = "自然之握";
+SMARTBUFF_TIGERSFURY = "猛虎之怒";
+SMARTBUFF_REJUVENATION = "回春术";
+SMARTBUFF_REGROWTH = "愈合";
+
+SMARTBUFF_REMOVECURSE = "解除诅咒";
+SMARTBUFF_ABOLISHPOISON = "驱毒术";
+
+-- 法师
+SMARTBUFF_AI = "奥术智慧";
+SMARTBUFF_AB = "奥术光辉";
+SMARTBUFF_ICEARMOR = "冰甲术";
+SMARTBUFF_FROSTARMOR = "霜甲术";
+SMARTBUFF_MAGEARMOR = "法师护甲";
+SMARTBUFF_MOLTENARMOR = "熔岩护甲";
+SMARTBUFF_DAMPENMAGIC = "魔法抑制";
+SMARTBUFF_AMPLIFYMAGIC = "魔法增效";
+SMARTBUFF_MANASHIELD = "法力护盾";
+SMARTBUFF_FIREWARD = "防护火焰结界";
+SMARTBUFF_FROSTWARD = "防护冰霜结界";
+SMARTBUFF_ICEBARRIER = "寒冰护体";
+SMARTBUFF_COMBUSTION = "燃烧";
+SMARTBUFF_ARCANEPOWER = "奥术强化";
+SMARTBUFF_PRESENCEOFMIND = "气定神闲";
+SMARTBUFF_ICYVEINS = "冰冷血脉";
+
+SMARTBUFF_MAGE_PATTERN = {"%a+护甲$"};
+
+-- 牧师
+SMARTBUFF_PWF = "真言术:韧";
+SMARTBUFF_POF = "坚韧祷言";
+SMARTBUFF_SP = "防护暗影";
+SMARTBUFF_POSP = "暗影防护祷言";
+SMARTBUFF_INNERFIRE = "心灵之火";
+SMARTBUFF_DS = "神圣之灵";
+SMARTBUFF_POS = "精神祷言";
+SMARTBUFF_PWS = "真言术:盾";
+SMARTBUFF_FEARWARD = "防护恐惧结界";
+SMARTBUFF_ELUNESGRACE = "艾露恩的赐福";
+SMARTBUFF_FEEDBACK = "回馈";
+SMARTBUFF_SHADOWGUARD = "暗影守卫";
+SMARTBUFF_TOUCHOFWEAKNESS = "虚弱之触";
+SMARTBUFF_INNERFOCUS = "心灵专注";
+SMARTBUFF_RENEW = "恢复";
+
+-- 术士
+SMARTBUFF_FELARMOR = "邪甲术";
+SMARTBUFF_DEMONARMOR = "魔甲术";
+SMARTBUFF_DEMONSKIN = "恶魔皮肤";
+SMARTBUFF_UNENDINGBREATH = "魔息术";
+SMARTBUFF_DGINVISIBILITY = "侦测强效隐形";
+SMARTBUFF_DINVISIBILITY = "侦测隐形";
+SMARTBUFF_DLINVISIBILITY = "侦测次级隐形";
+SMARTBUFF_SOULLINK = "灵魂链接";
+SMARTBUFF_SHADOWWARD = "暗影守卫";
+SMARTBUFF_DARKPACT = "黑暗契约";
+SMARTBUFF_SOULSTONE = "灵魂石复活";
+
+SMARTBUFF_WARLOCK_PATTERN = {"^恶魔%a+"};
+
+-- 猎人
+SMARTBUFF_TRUESHOTAURA = "强击光环";
+SMARTBUFF_RAPIDFIRE = "急速射击";
+SMARTBUFF_AOTH = "雄鹰守护";
+SMARTBUFF_AOTM = "灵猴守护";
+SMARTBUFF_AOTW = "野性守护";
+SMARTBUFF_AOTB = "野兽守护";
+SMARTBUFF_AOTC = "猎豹守护";
+SMARTBUFF_AOTP = "豹群守护";
+SMARTBUFF_AOTV = "蝰蛇守护";
+
+SMARTBUFF_HUNTER_PATTERN = {"守护$"};
+
+-- 萨满祭司
+SMARTBUFF_LIGHTNINGSHIELD = "闪电之盾";
+SMARTBUFF_WATERSHIELD = "水之护盾";
+SMARTBUFF_EARTHSHIELD = "大地之盾";
+SMARTBUFF_ROCKBITERW = "石化武器";
+SMARTBUFF_FROSTBRANDW = "冰封武器";
+SMARTBUFF_FLAMETONGUEW = "火舌武器";
+SMARTBUFF_WINDFURYW = "风怒武器";
+SMARTBUFF_WATERBREATHING = "水下呼吸";
+
+SMARTBUFF_SHAMAN_PATTERN = {"%a+之盾$"};
+
+-- 战士
+SMARTBUFF_BATTLESHOUT = "战斗怒吼";
+SMARTBUFF_COMMANDINGSHOUT = "命令怒吼";
+SMARTBUFF_BERSERKERRAGE = "狂暴之怒";
+SMARTBUFF_BLOODRAGE = "血性狂暴";
+SMARTBUFF_RAMPAGE = "暴怒";
+
+-- 盗贼
+SMARTBUFF_BLADEFLURRY = "剑刃乱舞";
+SMARTBUFF_SAD = "切割";
+SMARTBUFF_EVASION = "闪避";
+SMARTBUFF_INSTANTPOISON = "速效药膏";
+SMARTBUFF_WOUNDPOISON = "致伤药膏";
+--SMARTBUFF_MINDPOISON = "Mind\194\173numbing Poison";
+--SMARTBUFF_MINDPOISON = "Mind\45numbing Poison";
+SMARTBUFF_MINDPOISON = "麻痹药膏";
+SMARTBUFF_DEADLYPOISON = "致命药膏";
+SMARTBUFF_CRIPPLINGPOISON = "减速药膏";
+SMARTBUFF_ANESTHETICPOISON = "麻醉药膏";
+
+-- 圣骑士
+SMARTBUFF_RIGHTEOUSFURY = "正义之怒";
+SMARTBUFF_HOLYSHIELD = "神圣之盾";
+SMARTBUFF_BOM = "力量祝福";
+SMARTBUFF_GBOM = "强效力量祝福";
+SMARTBUFF_BOW = "智慧祝福";
+SMARTBUFF_GBOW = "强效智慧祝福";
+SMARTBUFF_BOSAL = "拯救祝福";
+SMARTBUFF_GBOSAL = "强效拯救祝福";
+SMARTBUFF_BOK = "王者祝福";
+SMARTBUFF_GBOK = "强效王者祝福";
+SMARTBUFF_BOSAN = "庇护祝福";
+SMARTBUFF_GBOSAN = "强效庇护祝福";
+SMARTBUFF_BOL = "光明祝福";
+SMARTBUFF_GBOL = "强效光明祝福";
+SMARTBUFF_BOF = "自由祝福";
+SMARTBUFF_BOP = "保护祝福";
+SMARTBUFF_SOCOMMAND = "命令圣印";
+SMARTBUFF_SOFURY = "愤怒圣印";
+SMARTBUFF_SOJUSTICE = "公正圣印";
+SMARTBUFF_SOLIGHT = "光明圣印";
+SMARTBUFF_SORIGHTEOUSNESS = "正义圣印";
+SMARTBUFF_SOWISDOM = "智慧圣印";
+SMARTBUFF_SOTCRUSADER = "十字军圣印";
+SMARTBUFF_SOVENGEANCE = "复仇圣印";
+SMARTBUFF_SOBLOOD = "鲜血圣印";
+SMARTBUFF_DEVOTIONAURA = "虔诚光环";
+SMARTBUFF_RETRIBUTIONAURA = "惩罚光环";
+SMARTBUFF_CONCENTRATIONAURA = "专注光环";
+SMARTBUFF_SHADOWRESISTANCEAURA = "暗影抗性光环";
+SMARTBUFF_FROSTRESISTANCEAURA = "冰霜抗性光环";
+SMARTBUFF_FIRERESISTANCEAURA = "火焰抗性光环";
+SMARTBUFF_SANCTITYAURA = "圣洁光环";
+SMARTBUFF_CRUSADERAURA = "十字军光环";
+
+SMARTBUFF_PALADIN_PATTERN = {"%a+圣印$"};
+
+-- 石头和油类
+SMARTBUFF_SSROUGH = "劣质磨刀石";
+SMARTBUFF_SSCOARSE = "粗制磨刀石";
+SMARTBUFF_SSHEAVY = "重磨刀石";
+SMARTBUFF_SSSOLID = "坚固的磨刀石";
+SMARTBUFF_SSDENSE = "致密磨刀石";
+SMARTBUFF_SSELEMENTAL = "元素磨刀石";
+SMARTBUFF_SSFEL = "魔能磨刀石";
+SMARTBUFF_SSADAMANTITE = "精金磨刀石";
+SMARTBUFF_WSROUGH = "劣质平衡石";
+SMARTBUFF_WSCOARSE = "粗制平衡石";
+SMARTBUFF_WSHEAVY = "重平衡石";
+SMARTBUFF_WSSOLID = "坚固的平衡石";
+SMARTBUFF_WSDENSE = "致密平衡石";
+SMARTBUFF_WSFEL = "魔能平衡石";
+SMARTBUFF_WSADAMANTITE = "精金平衡石";
+SMARTBUFF_SHADOWOIL = "暗影之油";
+SMARTBUFF_FROSTOIL = "冰霜之油";
+SMARTBUFF_MANAOILMINOR = "初级法力之油";
+SMARTBUFF_MANAOILLESSER = "次级法力之油";
+SMARTBUFF_MANAOILBRILLIANT = "卓越法力之油";
+SMARTBUFF_MANAOILSUPERIOR = "超级法力之油";
+SMARTBUFF_WIZARDOILMINOR = "初级巫师之油";
+SMARTBUFF_WIZARDOILLESSER = "次级巫师之油";
+SMARTBUFF_WIZARDOIL = "巫师之油";
+SMARTBUFF_WIZARDOILBRILLIANT = "卓越巫师之油";
+SMARTBUFF_WIZARDOILSUPERIOR = "超级巫师之油";
+
+SMARTBUFF_WEAPON_STANDARD = {"匕首", "斧", "剑", "锤", "法杖", "拳套", "长柄武器"};
+SMARTBUFF_WEAPON_BLUNT = {"魔杖", "法杖", "拳套"};
+SMARTBUFF_WEAPON_BLUNT_PATTERN = "平衡石$";
+SMARTBUFF_WEAPON_SHARP = {"匕首", "斧", "剑", "长柄武器"};
+SMARTBUFF_WEAPON_SHARP_PATTERN = "磨刀石$";
+
+-- 跟踪类
+SMARTBUFF_FINDMINERALS = "寻找矿物";
+SMARTBUFF_FINDHERBS = "寻找草药";
+SMARTBUFF_FINDTREASURE = "寻找财宝";
+SMARTBUFF_TRACKHUMANOIDS = "追踪人型生物";
+SMARTBUFF_TRACKBEASTS = "追踪野兽";
+SMARTBUFF_TRACKUNDEAD = "追踪亡灵";
+SMARTBUFF_TRACKHIDDEN = "追踪隐藏生物";
+SMARTBUFF_TRACKELEMENTALS = "追踪元素生物";
+SMARTBUFF_TRACKDEMONS = "追踪恶魔";
+SMARTBUFF_TRACKGIANTS = "追踪巨人";
+SMARTBUFF_TRACKDRAGONKIN = "追踪龙类";
+SMARTBUFF_SENSEDEMONS = "感知恶魔";
+SMARTBUFF_SENSEUNDEAD = "感知亡灵";
+
+-- 种族技能
+SMARTBUFF_STONEFORM = "石像形态";
+SMARTBUFF_PRECEPTION = "感知";
+SMARTBUFF_BLOODFURY = "血之狂怒";
+SMARTBUFF_BERSERKING = "狂暴";
+SMARTBUFF_WOTFORSAKEN = "亡灵意志";
+
+-- 材料
+SMARTBUFF_WILDBERRIES = "野生浆果";
+SMARTBUFF_WILDTHORNROOT = "野生棘根草";
+SMARTBUFF_WILDQUILLVINE = "野生刺藤";
+SMARTBUFF_ARCANEPOWDER = "魔粉";
+SMARTBUFF_HOLYCANDLE = "圣洁蜡烛";
+SMARTBUFF_SACREDCANDLE = "神圣蜡烛";
+SMARTBUFF_SYMBOLOFKINGS = "神圣符印";
+
+-- Food
+--SMARTBUFF_ = "";
+SMARTBUFF_SAGEFISHDELIGHT = "美味鼠尾鱼";
+SMARTBUFF_BUZZARDBITES = "美味秃鹫";
+SMARTBUFF_RAVAGERDOG = "掠食者热狗";
+SMARTBUFF_FELTAILDELIGHT = "美味魔尾鱼";
+SMARTBUFF_CLAMBAR = "蚌柳";
+SMARTBUFF_SPORELINGSNACK = "孢子小吃";
+SMARTBUFF_BLACKENEDSPOREFISH = "烟熏孢子鱼";
+SMARTBUFF_BLACKENEDBASILISK = "烟熏蜥蜴";
+SMARTBUFF_GRILLEDMUDFISH = "烤泥鱼";
+SMARTBUFF_POACHEDBLUEFISH = "水煮蓝鱼";
+SMARTBUFF_ROASTEDCLEFTHOOF = "烧烤裂蹄牛";
+SMARTBUFF_WARPBURGER = "迁跃兽汉堡";
+SMARTBUFF_TALBUKSTEAK = "塔布肉排";
+SMARTBUFF_GOLDENFISHSTICKS = "金色鱼柳";
+SMARTBUFF_CRUNCHYSERPENT = "香脆蛇";
+SMARTBUFF_MOKNATHALSHORTRIBS = "莫克纳萨肋排";
+SMARTBUFF_SPICYCRAWDAD = "香辣小龙虾";
+
+SMARTBUFF_FOOD_AURA = "进食充分";
+
+
+-- 生物类型
+SMARTBUFF_HUMANOID = "人型生物";
+SMARTBUFF_DEMON = "恶魔";
+SMARTBUFF_BEAST = "野兽";
+SMARTBUFF_ELEMENTAL = "元素生物";
+SMARTBUFF_DEMONTYPE = "小鬼";
+
+-- 职业
+SMARTBUFF_CLASSES = {"德鲁伊", "猎人", "法师", "圣骑士", "牧师", "潜行者", "萨满祭司", "术士", "战士", "死亡骑士", "武僧", "恶魔猎手", "猎人宠物", "术士宠物", "Death Knight Pet", "Tank", "Healer", "Damage Dealer"};
+
+-- 模板和地图
+SMARTBUFF_TEMPLATES = {"Solo", "组队", "团队", "战场", "卡拉赞", "祖阿曼", "地狱火堡垒", "盘牙水库", "奥金顿", "风暴要塞", "格鲁尔巢穴", "时光之穴", "黑暗神庙", "自定义 1", "自定义 2", "自定义 3"};
+SMARTBUFF_INSTANCES = {"卡拉赞", "祖阿曼", "玛瑟里顿的巢穴", "毒蛇神殿", "风暴之眼", "格鲁尔的巢穴", "海加尔", "黑暗神庙", "熔火之心", "奥妮克希亚的巢穴", "黑翼之巢", "纳克萨玛斯", "安其拉", "祖尔格拉布", "奥特兰克山谷", "阿拉希盆地", "战歌峡谷", "刀锋山", "纳格兰竞技场"};
+
+-- 骑乘
+SMARTBUFF_MOUNT = "速度提高(%d+)%%.";
+
+-- 快捷键设置
+BINDING_NAME_SMARTBUFF_BIND_TRIGGER = "触发";
+BINDING_NAME_SMARTBUFF_BIND_TARGET = "目标";
+BINDING_NAME_SMARTBUFF_BIND_OPTIONS = "设置窗口";
+BINDING_NAME_SMARTBUFF_BIND_RESETBUFFTIMERS = "重新设定BUFF定时器";
+
+-- 设置窗口
+SMARTBUFF_OFT = "启用SmartBuff";
+SMARTBUFF_OFT_MENU = "显示/隐藏配置菜单";
+SMARTBUFF_OFT_AUTO = "提醒";
+SMARTBUFF_OFT_AUTOTIMER = "检测间隔";
+SMARTBUFF_OFT_AUTOCOMBAT = "战斗";
+SMARTBUFF_OFT_AUTOCHAT = "聊天";
+SMARTBUFF_OFT_AUTOSPLASH = "闪烁";
+SMARTBUFF_OFT_AUTOSOUND = "声音";
+SMARTBUFF_OFT_AUTOREST = "城市内禁用";
+SMARTBUFF_OFT_HUNTERPETS = "BUFF猎人宠物";
+SMARTBUFF_OFT_WARLOCKPETS = "BUFF术士宠物";
+SMARTBUFF_OFT_ARULES = "高级规则";
+SMARTBUFF_OFT_GRP = "监视的组别";
+SMARTBUFF_OFT_SUBGRPCHANGED = "自动开启选项窗口";
+SMARTBUFF_OFT_BUFFS = "可施放项目";
+SMARTBUFF_OFT_TARGET = "BUFF选定目标";
+SMARTBUFF_OFT_DONE = "确定";
+SMARTBUFF_OFT_APPLY = "应用";
+SMARTBUFF_OFT_GRPBUFFSIZE = "触发人数";
+SMARTBUFF_OFT_CLASSBUFFSIZE = "职业人数";
+SMARTBUFF_OFT_MESSAGES = "禁用信息";
+SMARTBUFF_OFT_MSGNORMAL = "正常";
+SMARTBUFF_OFT_MSGWARNING = "警告";
+SMARTBUFF_OFT_MSGERROR = "错误";
+SMARTBUFF_OFT_HIDEMMBUTTON = "隐藏小地图按钮";
+SMARTBUFF_OFT_REBUFFTIMER = "提醒时间";
+SMARTBUFF_OFT_AUTOSWITCHTMP = "自动开启配置";
+SMARTBUFF_OFT_SELFFIRST = "首选自身";
+SMARTBUFF_OFT_SCROLLWHEEL = "鼠标滚轴触发";
+SMARTBUFF_OFT_SCROLLWHEELUP = "向上滚动时触发";
+SMARTBUFF_OFT_SCROLLWHEELDOWN= "向下时";
+SMARTBUFF_OFT_TARGETSWITCH = "目标改变触发";
+SMARTBUFF_OFT_BUFFTARGET = "目标 BUFF";
+SMARTBUFF_OFT_BUFFPVP = "PVP BUFF";
+SMARTBUFF_OFT_AUTOSWITCHTMPINST = "自动更换方案";
+SMARTBUFF_OFT_CHECKCHARGES = "检查次数";
+SMARTBUFF_OFT_RBT = "重置计时器";
+SMARTBUFF_OFT_BUFFINCITIES = "在主城内BUFF";
+SMARTBUFF_OFT_UISYNC = "UI同步";
+SMARTBUFF_OFT_ADVGRPBUFFCHECK = "队伍BUFF检查";
+SMARTBUFF_OFT_ADVGRPBUFFRANGE = "队伍范围检查";
+SMARTBUFF_OFT_BLDURATION = "忽略名单";
+SMARTBUFF_OFT_COMPMODE = "兼容模式";
+SMARTBUFF_OFT_MINIGRP = "迷你团队";
+SMARTBUFF_OFT_ANTIDAZE = "自动切换守护";
+SMARTBUFF_OFT_HIDESABUTTON = "隐藏动作按钮";
+SMARTBUFF_OFT_INCOMBAT = "战斗中触发";
+SMARTBUFF_OFT_SMARTDEBUFF = "SmartDebuff";
+
+-- 设置信息提示
+SMARTBUFF_OFTT = "启用智能施法";
+SMARTBUFF_OFTT_AUTO = "启用BUFF信息提示";
+SMARTBUFF_OFTT_AUTOTIMER = "BUFF监视时间的间隔";
+SMARTBUFF_OFTT_AUTOCOMBAT = "战斗时仍保持监视";
+SMARTBUFF_OFTT_AUTOCHAT = "在聊天窗口中显示施法有关信息";
+SMARTBUFF_OFTT_AUTOSPLASH = "在游戏屏幕的中央以闪烁方式显示施法失败的有关信息";
+SMARTBUFF_OFTT_AUTOSOUND = "声音提示施法失败事件";
+SMARTBUFF_OFTT_AUTOREST = "在主城内禁用信息提示";
+SMARTBUFF_OFTT_HUNTERPETS = "对猎人宠物施法";
+SMARTBUFF_OFTT_WARLOCKPETS = "对术士宠物施法," .. SMARTBUFF_DEMONTYPE .. "除外。";
+SMARTBUFF_OFTT_ARULES = "设定以下情况不施法:法师、牧师和术士不施放荆棘术,无魔法职业不施放奥术智慧、神圣之灵。";
+SMARTBUFF_OFTT_SUBGRPCHANGED = "当你所在队伍发生变动后,自动开启Smartbuff配置窗口。";
+SMARTBUFF_OFTT_GRPBUFFSIZE = "设定所在小队中玩家的BUFF消失的人数上限,来触发群体BUFF的施放。";
+SMARTBUFF_OFTT_HIDEMMBUTTON = "隐藏小地图按钮。";
+SMARTBUFF_OFTT_REBUFFTIMER = "设定当BUFF消失前多少秒,提示你重新施法。0 = 不提示";
+SMARTBUFF_OFTT_SELFFIRST = "优先给自己施放BUFF。";
+SMARTBUFF_OFTT_SCROLLWHEELUP = "当鼠标滚轴向上滚动时触发技能。";
+SMARTBUFF_OFTT_SCROLLWHEELDOWN = "当鼠标滚轴向下滚动时触发技能。";
+SMARTBUFF_OFTT_TARGETSWITCH = "当你改变目标时触发技能。";
+SMARTBUFF_OFTT_BUFFTARGET = "当目标为友好状态时,给予该目标施放BUFF。";
+SMARTBUFF_OFTT_BUFFPVP = "将给PVP开启的玩家施放BUFF。";
+SMARTBUFF_OFTT_AUTOSWITCHTMP = "当你所在队伍成员发生改变时,自动开启Smartbuff的配置窗口。";
+SMARTBUFF_OFTT_AUTOSWITCHTMPINST = "根据你是否处于组队、团队、副本的情况,自动更换预定的方案。";
+SMARTBUFF_OFTT_CHECKCHARGES = "当BUFF次数过低时报警。";
+SMARTBUFF_OFTT_BUFFINCITIES = "即使是在主城内仍然BUFF。\n如果你在PVP状态下,无论何种情况均会BUFF。";
+SMARTBUFF_OFTT_UISYNC = "开启同步选项,以从其他玩家那里获取你的BUFF的剩余时间。";
+SMARTBUFF_OFTT_ADVGRPBUFFCHECK = "在检查群体BUFF的同时\n也检查单个BUFF的补给情况。";
+SMARTBUFF_OFTT_ADVGRPBUFFRANGE = "在施放群体BUFF时\n检查所有队员是否在施法范围内。";
+SMARTBUFF_OFTT_BLDURATION = "剩余多少时间内的玩家将被忽略。\n0 = 停用";
+SMARTBUFF_OFTT_COMPMODE = "兼容性模式\n注意!!!\n如果你存在无法自我施法的问题,\n必须使用此模式。";
+SMARTBUFF_OFTT_MINIGRP = "用迷你团队模式显示合理化的团队框架。";
+SMARTBUFF_OFTT_ANTIDAZE = "当自己队伍中有成员晕眩时,自动取消猎豹守护/豹群守护。";
+SMARTBUFF_OFTT_SPLASHSTYLE = "改变BUFF提示信息的字体。";
+SMARTBUFF_OFTT_HIDESABUTTON = "隐藏SmartBuff动作按钮。";
+SMARTBUFF_OFTT_INCOMBAT = "目前只能用于你自己身上。\n你设定的第一个战斗中可释放的BUFF将在战斗前放置到动作按钮上,\n因此你可以在战斗中施放这个法术。\n警告:战斗中所有逻辑判断都将不可用!";
+SMARTBUFF_OFTT_SMARTDEBUFF = "显示SmartDebuff窗口。";
+SMARTBUFF_OFTT_SPLASHDURATION= "设定多少秒后提示信息消失。";
+
+-- BUFF设置内容
+SMARTBUFF_BST_SELFONLY = "仅对自身施法";
+SMARTBUFF_BST_SELFNOT = "不对自身施法";
+SMARTBUFF_BST_COMBATIN = "战斗状态触发";
+SMARTBUFF_BST_COMBATOUT = "非战斗状态触发";
+SMARTBUFF_BST_MAINHAND = "主手";
+SMARTBUFF_BST_OFFHAND = "副手";
+SMARTBUFF_BST_REMINDER = "通报";
+SMARTBUFF_BST_MANALIMIT = "最低值";
+
+-- BUFF设置提示信息内容
+SMARTBUFF_BSTT_SELFONLY = "仅BUFF自己,不给其他队友BUFF。";
+SMARTBUFF_BSTT_SELFNOT = "BUFF所有其他选择的职业,但是不BUFF自己。";
+SMARTBUFF_BSTT_COMBATIN = "在战斗状态时仍保持自动触发技能";
+SMARTBUFF_BSTT_COMBATOUT = "在非战斗状态时保持自动触发技能";
+SMARTBUFF_BSTT_MAINHAND = "给主手武器施放BUFF。";
+SMARTBUFF_BSTT_OFFHAND = "给副手武器施放BUFF。";
+SMARTBUFF_BSTT_REMINDER = "显示提醒信息。";
+SMARTBUFF_BSTT_REBUFFTIMER = "设定当BUFF消失前多少秒时发出警告信息。\n0 = 不提示";
+SMARTBUFF_BSTT_MANALIMIT = "当魔法值/怒气值/能量值低于你设置的值时将不会BUFF。";
+
+-- 玩家设置窗口信息提示
+SMARTBUFF_PSTT_RESIZE = "最小化/最大化\n主设置窗口";
+
+-- 命令行信息提示内容
+SMARTBUFF_MSG_LOADED = "已加载";
+SMARTBUFF_MSG_NEWVER1 = "|cff00e0ffSmartbuff : |cffffffff 有可用的新版本,您正在使用 |cffFFFF00";
+SMARTBUFF_MSG_NEWVER2 = "|cffffffff 和修订 |cffFFFF00r"
+SMARTBUFF_MSG_NEWVER3 = "|cffffffff 目前可供下载。 加入 Discord 以获取所有最新信息: https://discord.gg/R6EkZ94TKK.";
+SMARTBUFF_MSG_DISABLED = "SmartBuff已禁用!";
+SMARTBUFF_MSG_SUBGROUP = "你已经加入一个新的队伍,请检查你的设置。";
+SMARTBUFF_MSG_NOTHINGTODO = "没有指令可以执行。";
+SMARTBUFF_MSG_BUFFED = "已经施放";
+SMARTBUFF_MSG_OOR = "不在施法范围内。";
+--SMARTBUFF_MSG_CD = "技能CD时间已到。";
+SMARTBUFF_MSG_CD = "正处于公共CD时间!";
+SMARTBUFF_MSG_CHAT = "没有发现任何聊天窗口。";
+SMARTBUFF_MSG_SHAPESHIFT = "在变形状态下不能使用法术!";
+SMARTBUFF_MSG_NOACTIONSLOT = "动作条没有可用位置,需要一个空位置才能正常工作!";
+SMARTBUFF_MSG_GROUP = "队伍";
+SMARTBUFF_MSG_NEEDS = "需要加BUFF:";
+SMARTBUFF_MSG_OOM = "没有足够的魔法/怒气/能量!";
+SMARTBUFF_MSG_STOCK = "目前存放的";
+SMARTBUFF_MSG_NOREAGENT = "没有施法材料:";
+SMARTBUFF_MSG_DEACTIVATED = "禁用!";
+SMARTBUFF_MSG_REBUFF = "你的BUFF:";
+SMARTBUFF_MSG_LEFT = "以后消失!";
+SMARTBUFF_MSG_CLASS = "职业";
+SMARTBUFF_MSG_CHARGES = "次数";
+
+-- Support
+SMARTBUFF_MINIMAP_TT = "左键:选项菜单\n右键:开/关\nAlt+左键:SmartDebuff\n按Shift拖拽:移动按钮";
+SMARTBUFF_TITAN_TT = "左键:选项菜单\n右键:开/关\nAlt+左键:SmartDebuff";
+SMARTBUFF_FUBAR_TT = "左键:选项菜单\n右键:开/关\nAlt+左键:SmartDebuff";
+
+SMARTBUFF_DEBUFF_TT = "按Shift和左键拖拽:移动窗口\n|cff20d2ff- S按钮 -|r\n左键:按职业显示\nShift和左键:职业颜色\nAlt和左键:高亮左/右\n|cff20d2ff- P按钮 -|r\n左键:开/关隐藏宠物";
+
+end
diff --git a/localization.de.lua b/localization.de.lua
new file mode 100644
index 0000000..b119140
--- /dev/null
+++ b/localization.de.lua
@@ -0,0 +1,208 @@
+-------------------------------------------------------------------------------
+-- German localization
+-------------------------------------------------------------------------------
+
+if (GetLocale() == "deDE") then
+
+-- addon credits
+SMARTBUFF_CREDITS = "|cffffffff"
+ .."Classic-Version von Codermik. Bitte melde alle Probleme auf CurseForge oder meinem Discord unter:\n\n"
+ .."|cff00e0ffhttps://discord.gg/R6EkZ94TKK\n\n"
+ .."|cffffffffWenn Sie den Arbeitsaufwand und die Zeit zu schätzen wissen, die erforderlich ist, um Ihnen diese verschiedenen Add-Ons zur Verfügung zu stellen, erwägen Sie bitte, mich zu unterstützen, indem Sie:\n\n"
+ .."|cffffffffPatreon: |cff00e0ffhttps://www.patreon.com/codermik\n"
+ .."|cffffffffTwitch: |cff00e0ffhttps://www.twitch.tv/codermik\n"
+ .."|cffffffffPayPal.Me: |cff00e0ffhttps://paypal.me/codermik\n\n"
+;
+
+-- Weapon types
+SMARTBUFF_WEAPON_STANDARD = {"Dolche", "äxte", "schwerter", "streitkolben", "Stäbe", "Faustwaffen", "Stangenwaffen", "Wurfwaffe"};
+SMARTBUFF_WEAPON_BLUNT = {"streitkolben", "Faustwaffen", "Stäbe"};
+SMARTBUFF_WEAPON_BLUNT_PATTERN = "ewichtsstein$";
+SMARTBUFF_WEAPON_SHARP = {"Dolche", "äxte", "schwerter", "Stangenwaffen"};
+SMARTBUFF_WEAPON_SHARP_PATTERN = "etzstein$";
+
+-- Creature types
+SMARTBUFF_HUMANOID = "Humanoid";
+SMARTBUFF_DEMON = "Dämon";
+SMARTBUFF_BEAST = "Wildtier";
+SMARTBUFF_ELEMENTAL = "Elementar";
+SMARTBUFF_DEMONTYPE = "Wichtel";
+SMARTBUFF_UNDEAD = "Untot";
+
+-- Classes
+SMARTBUFF_CLASSES = {"Druide", "Jäger", "Magier", "Paladin", "Priester", "Schurke", "Schamane", "Hexenmeister", "Krieger", "Todesritter", "Mönch", "Dämonenjäger", "Jäger Pet", "Hexer Pet", "Todesritter Pet", "Tank", "Heiler", "Schadensverursacher"};
+
+-- Templates and Instances
+SMARTBUFF_TEMPLATES = {"Solo", "Gruppe", "Raid", "Schlachtfeld", "Arena", "ICC", "PDK", "Ulduar", "MC", "Ony", "BWL", "Naxx", "AQ", "ZG", "Custom 1", "Custom 2", "Custom 3", "Custom 4", "Custom 5"};
+SMARTBUFF_INSTANCES = {"Eiskronenzitadelle", "Prüfung des Kreuzfahrers", "Ulduar", "geschmolzene Kern", "Onyxias Hort", "Pechschwingenhort", "Naxxramas", "Ahn'Qiraj", "Zul'Gurub"};
+
+-- Mount
+SMARTBUFF_MOUNT = "Erhöht Tempo um (%d+)%%.";
+
+-- Abbreviations
+SMARTBUFF_ABBR_CHARGES_OL = "%d a";
+
+-- Bindings
+BINDING_NAME_SMARTBUFF_BIND_TRIGGER = "Trigger";
+BINDING_NAME_SMARTBUFF_BIND_TARGET = "Ziel";
+BINDING_NAME_SMARTBUFF_BIND_OPTIONS = "Optionen";
+BINDING_NAME_SMARTBUFF_BIND_RESETBUFFTIMERS = "Buff Timer löschen";
+
+-- Options Frame Text
+SMARTBUFF_OFT = "SmartBuff An/Aus";
+SMARTBUFF_OFT_MENU = "Zeige/verberge Optionen Menü";
+SMARTBUFF_OFT_AUTO = "Erinnerung";
+SMARTBUFF_OFT_AUTOTIMER = "Check Timer";
+SMARTBUFF_OFT_AUTOCOMBAT = "im Kampf";
+SMARTBUFF_OFT_AUTOCHAT = "Chat";
+SMARTBUFF_OFT_AUTOSPLASH = "Splash";
+SMARTBUFF_OFT_AUTOSOUND = "Ton";
+SMARTBUFF_OFT_AUTOREST = "Unterdrückt in Städten";
+SMARTBUFF_OFT_HUNTERPETS = "Jäger Pets buffen";
+SMARTBUFF_OFT_WARLOCKPETS = "Hexer Pets buffen";
+SMARTBUFF_OFT_ARULES = "Zusätzliche Regeln";
+SMARTBUFF_OFT_GRP = "Raid Sub-Gruppen zum Buffen";
+SMARTBUFF_OFT_SUBGRPCHANGED = "Öffne Menü";
+SMARTBUFF_OFT_BUFFS = "Buffs/Fähigkeiten";
+SMARTBUFF_OFT_TARGET = "Bufft das anvisierte Ziel";
+SMARTBUFF_OFT_DONE = "Fertig";
+SMARTBUFF_OFT_APPLY = "Übernehmen";
+SMARTBUFF_OFT_GRPBUFFSIZE = "Grp/Ra-Grösse";
+SMARTBUFF_OFT_CLASSBUFFSIZE = "Klassengrösse";
+SMARTBUFF_OFT_MESSAGES = "Unterdrücke Meldungen";
+SMARTBUFF_OFT_MSGNORMAL = "Normal";
+SMARTBUFF_OFT_MSGWARNING = "Warnung";
+SMARTBUFF_OFT_MSGERROR = "Fehler";
+SMARTBUFF_OFT_HIDEMMBUTTON = "Verberge Minimap-Knopf";
+SMARTBUFF_OFT_REBUFFTIMER = "Rebuff Timer";
+SMARTBUFF_OFT_AUTOSWITCHTMP = "Vorlagenwechsel";
+SMARTBUFF_OFT_SELFFIRST = "Mich zuerst";
+SMARTBUFF_OFT_SCROLLWHEELUP = "Bufft mit Mausrad hoch";
+SMARTBUFF_OFT_SCROLLWHEELDOWN = "runter";
+SMARTBUFF_OFT_TARGETSWITCH = "bei Zielwechsel";
+SMARTBUFF_OFT_BUFFTARGET = "Bufft das Ziel";
+SMARTBUFF_OFT_BUFFPVP = "Buff PvP";
+SMARTBUFF_OFT_AUTOSWITCHTMPINST = "Instanzen";
+SMARTBUFF_OFT_CHECKCHARGES = "Aufladungen";
+SMARTBUFF_OFT_RBT = "Reset BT";
+SMARTBUFF_OFT_BUFFINCITIES = "Bufft in Städten";
+SMARTBUFF_OFT_UISYNC = "UI Sync";
+SMARTBUFF_OFT_BLDURATION = "Blacklisted";
+SMARTBUFF_OFT_COMPMODE = "Komp. Modus";
+SMARTBUFF_OFT_MINIGRP = "Mini Gruppe";
+SMARTBUFF_OFT_ANTIDAZE = "Anti-Daze";
+SMARTBUFF_OFT_HIDESABUTTON = "Verberge Action-Knopf";
+SMARTBUFF_OFT_INCOMBAT = "Bufft im Kampf";
+SMARTBUFF_OFT_SMARTDEBUFF = "SmartDebuff";
+SMARTBUFF_OFT_INSHAPESHIFT = "Verwandelt";
+SMARTBUFF_OFT_LINKGRPBUFFCHECK = "Grp Link";
+SMARTBUFF_OFT_LINKSELFBUFFCHECK = "Selbst Link";
+SMARTBUFF_OFT_RESETALL = "Reset Alles";
+SMARTBUFF_OFT_RESETLIST = "Reset Liste";
+SMARTBUFF_OFT_YES = "Ja";
+SMARTBUFF_OFT_NO = "Nein";
+SMARTBUFF_OFT_PURGE_DATA = "Bist du sicher, dass du ALLE SmartBuff Daten zurücksetzen willst?\nDiese Aktion wird ein neu Laden des UI's durchführen!";
+SMARTBUFF_OFT_SPLASHICON = "Symbol anzeigen";
+SMARTBUFF_OFT_SPLASHMSGSHORT = "Kurze Meldung";
+
+-- Options Frame Tooltip Text
+SMARTBUFF_OFTT = "Schaltet SmartBuff An/Aus";
+SMARTBUFF_OFTT_AUTO = "Schaltet die Erinnerung an fehlende Buffs An/Aus";
+SMARTBUFF_OFTT_AUTOTIMER = "Verzögerung in Sekunden zwischen zwei Checks.";
+SMARTBUFF_OFTT_AUTOCOMBAT = "Check auch während dem Kampf durchführen.";
+SMARTBUFF_OFTT_AUTOCHAT = "Zeigt fehlende Buffs als Chat-Meldung an.";
+SMARTBUFF_OFTT_AUTOSPLASH = "Zeigt fehlende Buffs als Splash-Meldung\nin der mitte des Bildschirms an.";
+SMARTBUFF_OFTT_AUTOSOUND = "Bei fehlende Buffs erklingt ein Ton.";
+SMARTBUFF_OFTT_AUTOREST = "Erinnerung wird in den\nHauptstädten unterdrückt.";
+SMARTBUFF_OFTT_HUNTERPETS = "Bufft die Jäger Pets auch.";
+SMARTBUFF_OFTT_WARLOCKPETS = "Bufft die Hexer Pets auch,\nausser den " .. SMARTBUFF_DEMONTYPE .. ".";
+SMARTBUFF_OFTT_ARULES = "Bufft nicht:\n- Dornen auf Magier, Priester und Hexer\n- Arkane Intelligenz auf Klassen ohne Mana\n- Göttlicher Willen auf Klassen ohne Mana";
+SMARTBUFF_OFTT_SUBGRPCHANGED = "Öffnet automatisch das SmartBuff Menü,\nwenn du die Sub-Gruppe gewechselt hast.";
+SMARTBUFF_OFTT_GRPBUFFSIZE = "Anzahl Spieler die in der Gruppe/Raid sein\nmüssen und den Gruppen-Buff nicht haben,\ndamit der Gruppen-Buff verwendet wird.";
+SMARTBUFF_OFTT_HIDEMMBUTTON = "Verbirgt den SmartBuff Minimap-Knopf.";
+SMARTBUFF_OFTT_REBUFFTIMER = "Wieviele Sekunden vor Ablauf der Buffs,\nsoll daran erinnert werden.\n0 = Deaktivert";
+SMARTBUFF_OFTT_SELFFIRST = "Bufft den eigenen Charakter immer zuerst.";
+SMARTBUFF_OFTT_SCROLLWHEELUP = "Bufft beim Bewegen des Scrollrads nach vorne.";
+SMARTBUFF_OFTT_SCROLLWHEELDOWN = "Bufft beim Bewegen des Scrollrads zurück.";
+SMARTBUFF_OFTT_TARGETSWITCH = "Bufft beim Wechsel eines Ziels.";
+SMARTBUFF_OFTT_BUFFTARGET = "Bufft zuerst das aktuelle Ziel,\nfalls dies freundlich ist.";
+SMARTBUFF_OFTT_BUFFPVP = "Bufft auch Spieler im PvP Modus,\nwenn man selbst nicht im PvP ist.";
+SMARTBUFF_OFTT_AUTOSWITCHTMP = "Wechselt automatisch die Buff-Vorlage,\nwenn der Gruppentyp sich ändert.";
+SMARTBUFF_OFTT_AUTOSWITCHTMPINST = "Wechselt automatisch die Buff-Vorlage,\nwenn die Instanz sich ändert.";
+SMARTBUFF_OFTT_CHECKCHARGES = "Erinnerung wenn die Aufladungen\neines Buffs bald aufgebraucht sind.\n0 = Deaktivert";
+SMARTBUFF_OFTT_BUFFINCITIES = "Bufft auch in den Hauptstädten.\nWenn du PvP geflagged bist, bufft es immer.";
+SMARTBUFF_OFTT_UISYNC = "Aktiviert die Synchronisation mit dem UI,\num die Buff-Zeiten der anderen Spieler zu erhalten.";
+SMARTBUFF_OFTT_BLDURATION = "Wieviele Sekunden ein Spieler auf\ndie schwarze Liste gesetzt wird.\n0 = Deaktivert";
+SMARTBUFF_OFTT_COMPMODE = "Kompatibilitäts Modus\nWarnung!!!\nBenutzte diesen Modus nur, wenn Probleme auftreten\nBuffs auf sich selbst zu casten.";
+SMARTBUFF_OFTT_MINIGRP = "Zeigt die Raid-Subgruppen Einstellungen in einem\neigenen verschiebbaren Mini-Fenster an.";
+SMARTBUFF_OFTT_ANTIDAZE = "Bricht automatisch den\nAspekt des Geparden/Rudels ab,\nwenn jemand betäubt wird\n(Selbst oder Gruppe).";
+SMARTBUFF_OFTT_SPLASHSTYLE = "Wechselt die Schriftart\nder Buff-Meldungen.";
+SMARTBUFF_OFTT_HIDESABUTTON = "Verbirgt den SmartBuff Action-Knopf.";
+SMARTBUFF_OFTT_INCOMBAT = "Funktioniert nur auf dich selbst.\nDer erste Buff, welcher als 'im Kampf'\ngesetzt ist, wird verwendet\nund kann im Kampf benutzt werden.\n!!! Achtung !!!\nSämtliche Buff-Logik ist inaktiv im Kampf!";
+SMARTBUFF_OFTT_SMARTDEBUFF = "Zeigt das SmartDebuff Fenster.";
+SMARTBUFF_OFTT_SPLASHDURATION= "Wieviele Sekunden die Splash Meldung angezeigt wird,\nbevor sie ausgeblendet wird.";
+SMARTBUFF_OFTT_INSHAPESHIFT = "Bufft auch wenn du\nverwandelt bist.";
+SMARTBUFF_OFTT_LINKGRPBUFFCHECK = "Prüft ob schon ein Buff\nmit gleichem Effekt von einer\nanderen Klasse aktiv ist.";
+SMARTBUFF_OFTT_LINKSELFBUFFCHECK = "Prüft ob ein Eigen-Buff\naktiv ist, von welchen jeweils\nnur einer aktiv sein kann.";
+
+-- Buffsetup Frame Text
+SMARTBUFF_BST_SELFONLY = "Nur mich";
+SMARTBUFF_BST_SELFNOT = "Mich nicht";
+SMARTBUFF_BST_COMBATIN = "Im Kampf";
+SMARTBUFF_BST_COMBATOUT = "Aus dem Kampf";
+SMARTBUFF_BST_MAINHAND = "Waffenhand";
+SMARTBUFF_BST_OFFHAND = "Schildhand";
+SMARTBUFF_BST_RANGED = "Wurfwaffe";
+SMARTBUFF_BST_REMINDER = "Benachrichtigung";
+SMARTBUFF_BST_MANALIMIT = "Grenzwert";
+
+-- Buffsetup Frame Tooltip Text
+SMARTBUFF_BSTT_SELFONLY = "Bufft nur deinen eigenen Charakter.";
+SMARTBUFF_BSTT_SELFNOT = "Bufft alle anderen selektierte Klassen,\nausser deinen eigenen Charakter.";
+SMARTBUFF_BSTT_COMBATIN = "Bufft innerhalb des Kampfes.";
+SMARTBUFF_BSTT_COMBATOUT = "Bufft ausserhalb des Kampfes.";
+SMARTBUFF_BSTT_MAINHAND = "Bufft die Haupthand.";
+SMARTBUFF_BSTT_OFFHAND = "Bufft die Schildhand.";
+SMARTBUFF_BSTT_RANGED = "Bufft die Wurfwaffe.";
+SMARTBUFF_BSTT_REMINDER = "Erinnerungs-Nachricht ausgeben.";
+SMARTBUFF_BSTT_REBUFFTIMER = "Wieviele Sekunden vor Ablauf des Buffs,\nsoll daran erinnert werden.\n0 = Globaler Rebuff Timer";
+SMARTBUFF_BSTT_MANALIMIT = "Mana/Wut/Energie Grenzwert\nWenn du unter diesen Wert fällst\nwird der Buff nicht mehr verwendet.";
+
+-- Playersetup Frame Tooltip Text
+SMARTBUFF_PSTT_RESIZE = "Minimiert/Maximiert\ndas Optionenfenster";
+
+-- Messages
+SMARTBUFF_MSG_LOADED = "geladen. Classic von Codermik - bitte alle gefundenen Fehler melden.";
+SMARTBUFF_MSG_NEWVER1 = "|cff00e0ffSmartbuff : |cffffffff Es ist eine neue Version verfügbar, Sie verwenden |cffFFFF00";
+SMARTBUFF_MSG_NEWVER2 = "|cffffffff und Überarbeitung |cffFFFF00r"
+SMARTBUFF_MSG_NEWVER3 = "|cffffffff ist derzeit zum Download verfügbar. Treten Sie Discord bei, um alle aktuellen Informationen zu erhalten unter https://discord.gg/R6EkZ94TKK.";
+SMARTBUFF_MSG_DISABLED = "SmartBuff ist deaktiviert!";
+SMARTBUFF_MSG_SUBGROUP = "Du hast die Subgruppe gewechselt, bitte überprüfe die Einstellungen!";
+SMARTBUFF_MSG_NOTHINGTODO = "Nichts zu buffen";
+SMARTBUFF_MSG_BUFFED = "gebuffed";
+SMARTBUFF_MSG_OOR = "ist ausser Reichweite zum Buffen!";
+--SMARTBUFF_MSG_CD = "hat noch Cooldown";
+SMARTBUFF_MSG_CD = "Globaler Cooldown!";
+SMARTBUFF_MSG_CHAT = "nicht möglich über Chat-Befehl!";
+SMARTBUFF_MSG_SHAPESHIFT = "In Verwandlung kann nicht gebufft werden!";
+SMARTBUFF_MSG_NOACTIONSLOT = "muss in einem Slot auf der Aktionsleiste sein, dass es funktioniert!";
+SMARTBUFF_MSG_GROUP = "Gruppe";
+SMARTBUFF_MSG_NEEDS = "benötigt";
+SMARTBUFF_MSG_OOM = "Zuwenig Mana/Wut/Energie!";
+SMARTBUFF_MSG_STOCK = "Aktueller Bestand";
+SMARTBUFF_MSG_NOREAGENT = "Zuwenig";
+SMARTBUFF_MSG_DEACTIVATED = "deaktiviert!";
+SMARTBUFF_MSG_REBUFF = "ReBuff";
+SMARTBUFF_MSG_LEFT = "übrig";
+SMARTBUFF_MSG_CLASS = "Klasse";
+SMARTBUFF_MSG_CHARGES = "Aufladungen";
+SMARTBUFF_MSG_SPECCHANGED = "Spec gewechselt (%s), lade Buff-Vorlagen...";
+
+-- Support
+SMARTBUFF_MINIMAP_TT = "Links Klick: Optionen Menü\nRechts Klick: An/Aus\nAlt-Links Klick: SmartDebuff\nShift-Ziehen: Knopf verschieben";
+SMARTBUFF_TITAN_TT = "Links Klick: Optionen Menü\nRechts Klick: An/Aus\nAlt-Links Klick: SmartDebuff";
+SMARTBUFF_FUBAR_TT = "\nLinks Klick: Optionen Menü\nShift-Links Klick: An/Aus\nAlt-Links Klick: SmartDebuff";
+
+SMARTBUFF_DEBUFF_TT = "Shift-Links ziehen: Fenster verschieben\n|cff20d2ff- S Knopf -|r\nLinks Klick: Ordne nach Klassen\nShift-Links Klick: Klassen-Farben\nAlt-Links Klick: Zeige L/R\n|cff20d2ff- P Knopf -|r\nLinks Klick: Verberge Pets";
+
+end
diff --git a/localization.en.lua b/localization.en.lua
new file mode 100644
index 0000000..8136ed2
--- /dev/null
+++ b/localization.en.lua
@@ -0,0 +1,234 @@
+-------------------------------------------------------------------------------
+-- English localization (Default)
+-------------------------------------------------------------------------------
+
+-- Whats new info
+SMARTBUFF_WHATSNEW = "\n\n|cffffffff Whats new:|r\n\n"
+ .." |cffffffffClassic version by Codermik\n"
+ .." Please report any issues on Curse or Discord.|r\n\n\n"
+ .." Changes in r21:\n\n"
+ .." * Fixed missing Deathknight support in WOTLK\n"
+ .." as it was not shown in the list of classes. \n"
+ .."\n\n"
+ .." |cffffffffIf you appreciate my work on the various addons\n"
+ .." for wow then please consider supporting me, you\n"
+ .." can do this several ways which include:\n\n"
+ .." |cffffffffPatreon: |cff00e0ffhttps://www.patreon.com/codermik\n"
+ .." |cffffffffTwitch: |cff00e0ffhttps://www.twitch.tv/codermik\n"
+ .." |cffffffffPayPal.Me: |cff00e0ffhttps://paypal.me/codermik\n\n\n"
+ .." |cffffffffThanks to everyone providing feedback and\n"
+ .." |cffffffffbug reports - you have helped a lot!|r\n\n\n"
+
+ .." |cff00e0ffHuge thanks to Aeldra for creating the original\n"
+ .." addon and the framework for this release.\n\n"
+;
+
+-- addon credits
+SMARTBUFF_CREDITS = "|cffffffff"
+ .."Classic version by Codermik. Please report any issues on CurseForge or my discord at:\n\n"
+ .."|cff00e0ffhttps://discord.gg/R6EkZ94TKK\n\n"
+ .."|cffffffffIf you appreciate the amount of work involved and the time taken to bring you these various addons please consider supporting me by:\n\n"
+ .."|cffffffffPatreon: |cff00e0ffhttps://www.patreon.com/codermik\n"
+ .."|cffffffffTwitch: |cff00e0ffhttps://www.twitch.tv/codermik\n"
+ .."|cffffffffPayPal.Me: |cff00e0ffhttps://paypal.me/codermik\n\n"
+;
+
+-- Weapon types
+SMARTBUFF_WEAPON_STANDARD = {"Daggers", "Axes", "Swords", "Maces", "Staves", "Fist Weapons", "Polearms", "Thrown"};
+SMARTBUFF_WEAPON_BLUNT = {"Maces", "Staves", "Fist Weapons"};
+SMARTBUFF_WEAPON_BLUNT_PATTERN = "Weightstone$";
+SMARTBUFF_WEAPON_SHARP = {"Daggers", "Axes", "Swords", "Polearms"};
+SMARTBUFF_WEAPON_SHARP_PATTERN = "Sharpening Stone$";
+
+-- Creature types
+SMARTBUFF_HUMANOID = "Humanoid";
+SMARTBUFF_DEMON = "Demon";
+SMARTBUFF_BEAST = "Beast";
+SMARTBUFF_ELEMENTAL = "Elemental";
+SMARTBUFF_DEMONTYPE = "Imp";
+SMARTBUFF_UNDEAD = "Undead";
+
+-- Classes
+SMARTBUFF_CLASSES = {"Druid", "Hunter", "Mage", "Paladin", "Priest", "Rogue", "Shaman", "Warlock", "Warrior", "Death Knight", "Monk", "Demon Hunter", "Hunter Pet", "Warlock Pet", "Death Knight Pet", "Tank", "Healer", "Damage Dealer"};
+
+-- Templates and Instances
+SMARTBUFF_TEMPLATES = {"Solo", "Party", "Raid", "Battleground", "Arena", "ICC", "TOC", "Ulduar", "MC", "Ony", "BWL", "Naxx", "AQ", "ZG", "Custom 1", "Custom 2", "Custom 3", "Custom 4", "Custom 5"};
+SMARTBUFF_INSTANCES = {"Icecrown Citadel", "Trial of the Crusader", "Ulduar", "Molten Core", "Onyxia's Lair", "Blackwing Lair", "Naxxramas", "Ahn'Qiraj", "Zul'Gurub"};
+
+-- Mount
+SMARTBUFF_MOUNT = "Increases speed by (%d+)%%.";
+
+-- Abbreviations
+SMARTBUFF_ABBR_CHARGES_OL = "%d c";
+
+-- Bindings
+BINDING_NAME_SMARTBUFF_BIND_TRIGGER = "Trigger";
+BINDING_NAME_SMARTBUFF_BIND_TARGET = "Target";
+BINDING_NAME_SMARTBUFF_BIND_OPTIONS = "Option menu";
+BINDING_NAME_SMARTBUFF_BIND_RESETBUFFTIMERS = "Reset buff timers";
+
+-- Options Frame Text
+SMARTBUFF_OFT = "SmartBuff On/Off";
+SMARTBUFF_OFT_MENU = "Show/hide options menu";
+SMARTBUFF_OFT_AUTO = "Reminder";
+SMARTBUFF_OFT_AUTOTIMER = "Check timer";
+SMARTBUFF_OFT_AUTOCOMBAT = "in combat";
+SMARTBUFF_OFT_AUTOCHAT = "Chat";
+SMARTBUFF_OFT_AUTOSPLASH = "Splash";
+SMARTBUFF_OFT_AUTOSOUND = "Sound";
+SMARTBUFF_OFT_AUTOREST = "Disable in cities";
+SMARTBUFF_OFT_HUNTERPETS = "Buff Hunter pets";
+SMARTBUFF_OFT_WARLOCKPETS = "Buff Warlock pets";
+SMARTBUFF_OFT_ARULES = "Advance rules";
+SMARTBUFF_OFT_BUFFS = "Buffs/Abilities";
+SMARTBUFF_OFT_TARGET = "Buffs the selected target";
+SMARTBUFF_OFT_DONE = "Done";
+SMARTBUFF_OFT_APPLY = "Apply";
+SMARTBUFF_OFT_CLASSBUFFSIZE = "Class size";
+SMARTBUFF_OFT_MESSAGES = "Disable messages";
+SMARTBUFF_OFT_MSGNORMAL = "normal";
+SMARTBUFF_OFT_MSGWARNING = "warning";
+SMARTBUFF_OFT_MSGERROR = "error";
+SMARTBUFF_OFT_HIDEMMBUTTON = "Hide minimap button";
+SMARTBUFF_OFT_REBUFFTIMER = "Rebuff Timer";
+SMARTBUFF_OFT_AUTOSWITCHTMP = "Switch template";
+SMARTBUFF_OFT_SELFFIRST = "Self first";
+SMARTBUFF_OFT_SCROLLWHEELUP = "Buff on scrollwheel up";
+SMARTBUFF_OFT_SCROLLWHEELDOWN= "down";
+SMARTBUFF_OFT_TARGETSWITCH = "target change";
+SMARTBUFF_OFT_BUFFTARGET = "Buff target";
+SMARTBUFF_OFT_BUFFPVP = "Buff PvP";
+SMARTBUFF_OFT_AUTOSWITCHTMPINST = "Instances";
+SMARTBUFF_OFT_CHECKCHARGES = "Check charges";
+SMARTBUFF_OFT_RBT = "Reset BT";
+SMARTBUFF_OFT_BUFFINCITIES = "Buff in cities";
+SMARTBUFF_OFT_BLDURATION = "Blacklisted";
+SMARTBUFF_OFT_ANTIDAZE = "Anti daze";
+SMARTBUFF_OFT_HIDESABUTTON = "Hide action button";
+SMARTBUFF_OFT_INCOMBAT = "Buff in combat";
+SMARTBUFF_OFT_SMARTDEBUFF = "SmartDebuff";
+SMARTBUFF_OFT_INSHAPESHIFT = "Shapeshift";
+SMARTBUFF_OFT_LINKGRPBUFFCHECK = "Grp link";
+SMARTBUFF_OFT_LINKSELFBUFFCHECK = "Self link";
+SMARTBUFF_OFT_RESETALL = "Reset All";
+SMARTBUFF_OFT_RESETLIST = "Reset List";
+SMARTBUFF_OFT_YES = "Yes";
+SMARTBUFF_OFT_NO = "No";
+SMARTBUFF_OFT_PURGE_DATA = "Are you sure you want to reset ALL SmartBuff data?\nThis action will force a reload of the UI!";
+SMARTBUFF_OFT_SPLASHICON = "Show Icon";
+SMARTBUFF_OFT_SPLASHMSGSHORT = "Short Message";
+SMARTBUFF_OFT_FONTSTYLE = "Font";
+SMARTBUFF_OFT_FONTSIZE = "Font Size";
+SMARTBUFF_OFT_ICONSIZE = "Icon Size";
+
+
+-- Options Frame Tooltip Text
+SMARTBUFF_OFTT = "Toggles SmartBuff On/Off";
+SMARTBUFF_OFTT_AUTO = "Toggles the buff reminder On/Off";
+SMARTBUFF_OFTT_AUTOTIMER = "Delay in seconds between two checks.";
+SMARTBUFF_OFTT_AUTOCOMBAT = "Run the check also in combat.";
+SMARTBUFF_OFTT_AUTOCHAT = "Displays missing buffs as chat message.";
+SMARTBUFF_OFTT_AUTOSPLASH = "Displays missing buffs as splash message\nin the middle of the screen.";
+SMARTBUFF_OFTT_AUTOSOUND = "Plays a sound if buffs are missing.";
+SMARTBUFF_OFTT_AUTOREST = "Disable reminder in capital cities";
+SMARTBUFF_OFTT_HUNTERPETS = "Buff the Hunter pets as well.";
+SMARTBUFF_OFTT_WARLOCKPETS = "Buff the Warlock pets as well, except the " .. SMARTBUFF_DEMONTYPE .. ".";
+SMARTBUFF_OFTT_ARULES = "Does not cast:\n- Thorns on Mages, Priests and Warlocks\n- Arcane Intellect on units without Mana\n- Divine Spirit on units without Mana";
+SMARTBUFF_OFTT_HIDEMMBUTTON = "Hides the SmartBuff minimap button.";
+SMARTBUFF_OFTT_REBUFFTIMER = "How many seconds before a buff expires,\nthe reminder should alert you.\n0 = Deactivated";
+SMARTBUFF_OFTT_SELFFIRST = "Buffs your character first of all others.";
+SMARTBUFF_OFTT_SCROLLWHEELUP = "Cast buffs when you roll your\nscrollwheel forward.";
+SMARTBUFF_OFTT_SCROLLWHEELDOWN = "Cast buffs when you roll your\nscrollwheel backward.";
+SMARTBUFF_OFTT_TARGETSWITCH = "Cast buffs when you switch your target.";
+SMARTBUFF_OFTT_BUFFTARGET = "Buffs first the current target,\nif it is friendly.";
+SMARTBUFF_OFTT_BUFFPVP = "Buff PvP flagged players,\nalso if you are not PvP flagged.";
+SMARTBUFF_OFTT_AUTOSWITCHTMP = "Automatically switches the template,\nif the group type changes.";
+SMARTBUFF_OFTT_AUTOSWITCHTMPINST = "Automatically switches the template,\nif the instance changes.";
+SMARTBUFF_OFTT_CHECKCHARGES = "Displays low amount of\ncharges on a buff.\n0 = Deactivated";
+SMARTBUFF_OFTT_BUFFINCITIES = "Buffs also if you are in capital cities.\nIf you are PvP flagged, it buffs in any case.";
+SMARTBUFF_OFTT_BLDURATION = "How many seconds, players will be blacklisted.\n0 = Deactivated";
+SMARTBUFF_OFTT_ANTIDAZE = "Automatically cancels the\naspect of the cheetah/pack\nif someone gets dazed\n(self or group).";
+SMARTBUFF_OFTT_SPLASHSTYLE = "Changes the fontstyle of\nthe buff messages.";
+SMARTBUFF_OFTT_HIDESABUTTON = "Hides the SmartBuff action button.";
+SMARTBUFF_OFTT_INCOMBAT = "At the moment it only works on yourself.\nThe first buff you mark as in combat,\nwill set on the button before combat\nand you can use it in combat.\n!!! Warning !!!\nAll logic is disabled in combat!";
+SMARTBUFF_OFTT_SMARTDEBUFF = "Shows the SmartDebuff frame.";
+SMARTBUFF_OFTT_SPLASHDURATION= "How many seconds the splash\nmessage will displayed,\nbefore it fades.";
+SMARTBUFF_OFTT_INSHAPESHIFT = "Cast buffs also if you\nare shapeshifted.";
+SMARTBUFF_OFTT_LINKGRPBUFFCHECK = "Checks if a buff of an other\nclass with similar effect\nis already active.";
+SMARTBUFF_OFTT_LINKSELFBUFFCHECK = "Checks if a self buff is active,\nwhose only one can be\nactive at a time.";
+
+-- Buffsetup Frame Text
+SMARTBUFF_BST_SELFONLY = "Myself only";
+SMARTBUFF_BST_SELFNOT = "Myself not";
+SMARTBUFF_BST_COMBATIN = "In combat";
+SMARTBUFF_BST_COMBATOUT = "Out of combat";
+SMARTBUFF_BST_MAINHAND = "Main Hand";
+SMARTBUFF_BST_OFFHAND = "Off Hand";
+SMARTBUFF_BST_RANGED = "Thrown";
+SMARTBUFF_BST_REMINDER = "Notification";
+SMARTBUFF_BST_MANALIMIT = "Lower bound";
+
+-- Buffsetup Frame Tooltip Text
+SMARTBUFF_BSTT_SELFONLY = "Buffs only your character.";
+SMARTBUFF_BSTT_SELFNOT = "Buffs all other selected classes,\nexcept your character.";
+SMARTBUFF_BSTT_COMBATIN = "Buffs if you are in combat.";
+SMARTBUFF_BSTT_COMBATOUT = "Buffs if you are out of combat.";
+SMARTBUFF_BSTT_MAINHAND = "Buffs the Main Hand.";
+SMARTBUFF_BSTT_OFFHAND = "Buffs the Off Hand.";
+SMARTBUFF_BSTT_RANGED = "Buffs the ranged slot.";
+SMARTBUFF_BSTT_REMINDER = "Display reminder message.";
+SMARTBUFF_BSTT_REBUFFTIMER = "How many seconds before a buff expires,\nthe reminder should alert you.\n0 = global rebuff timer";
+SMARTBUFF_BSTT_MANALIMIT = "Mana/Rage/Energy threshold\nIf you are below this value\nit will not cast the buff.";
+
+-- Playersetup Frame Tooltip Text
+SMARTBUFF_PSTT_RESIZE = "Minimize/maximize\nthe main options frame";
+
+-- Messages
+SMARTBUFF_MSG_LOADED = "loaded. Classic version by Codermik - please report any errors found.";
+SMARTBUFF_MSG_NEWVER1 = "|cff00e0ffSmartbuff : |cffffffff There is a new version available, you are using |cffFFFF00";
+SMARTBUFF_MSG_NEWVER2 = "|cffffffff and revision |cffFFFF00r"
+SMARTBUFF_MSG_NEWVER3 = "|cffffffff is currently available for download. Join Discord for all the latest information at https://discord.gg/R6EkZ94TKK.";
+SMARTBUFF_MSG_DISABLED = "SmartBuff is disabled!";
+SMARTBUFF_MSG_SUBGROUP = "You've joined a new subgroup, please check the options!";
+SMARTBUFF_MSG_NOTHINGTODO = "Nothing to do";
+SMARTBUFF_MSG_BUFFED = "buffed";
+SMARTBUFF_MSG_OOR = "is out of range to buff!";
+--SMARTBUFF_MSG_CD = "has cooldown!";
+SMARTBUFF_MSG_CD = "Global cooldown!";
+SMARTBUFF_MSG_CHAT = "not possible in chat mode!";
+SMARTBUFF_MSG_SHAPESHIFT = "Casting is not allowed in shapeshift form!";
+SMARTBUFF_MSG_NOACTIONSLOT = "needs a slot in an actionbar to working properly!";
+SMARTBUFF_MSG_GROUP = "Group";
+SMARTBUFF_MSG_NEEDS = "needs";
+SMARTBUFF_MSG_OOM = "Not enough mana/rage/energy!";
+SMARTBUFF_MSG_STOCK = "Actual stock of";
+SMARTBUFF_MSG_NOREAGENT = "Out of reagent:";
+SMARTBUFF_MSG_DEACTIVATED = "deactivated!";
+SMARTBUFF_MSG_REBUFF = "Rebuff";
+SMARTBUFF_MSG_LEFT = "left";
+SMARTBUFF_MSG_CLASS = "Class";
+SMARTBUFF_MSG_CHARGES = "charges";
+SMARTBUFF_MSG_SPECCHANGED = "Spec changed (%s), loading buff templates...";
+
+-- Support
+SMARTBUFF_MINIMAP_TT = "Left click: options menu\nRight click: On/Off\nAlt-Left Click: SmartDebuff\nShift drag: Move button";
+SMARTBUFF_TITAN_TT = "Left Click: Open options\nRight Click: On/Off\nAlt-Left Click: SmartDebuff";
+SMARTBUFF_FUBAR_TT = "\nLeft Click: Open options\nShift-Left Click: On/Off\nAlt-Left Click: SmartDebuff";
+
+SMARTBUFF_DEBUFF_TT = "Shift-Left drag: Move frame\n|cff20d2ff- S button -|r\nLeft click: Show by classes\nShift-Left click: Class colors\nAlt-Left click: Highlight L/R\n|cff20d2ff- P button -|r\nLeft click: Hide pets on/off";
+
+
+-- Code table
+-- : \195\160 : \195\168 : \195\172 : \195\178 : \195\185
+-- : \195\161 : \195\169 : \195\173 : \195\179 : \195\186
+-- : \195\162 : \195\170 : \195\174 : \195\180 : \195\187
+-- : \195\163 : \195\171 : \195\175 : \195\181 : \195\188
+-- : \195\164 : \195\177 : \195\182
+-- : \195\166 : \195\184
+-- : \195\167 : \197\147
+--
+-- : \195\132
+-- : \195\150
+-- : \195\156
+-- : \195\159
+
diff --git a/localization.es.lua b/localization.es.lua
new file mode 100644
index 0000000..cb59d38
--- /dev/null
+++ b/localization.es.lua
@@ -0,0 +1,204 @@
+-------------------------------------------------------------------------------
+-- Spanish Localization
+-- Big thanks to Chusina
+-------------------------------------------------------------------------------
+
+if (GetLocale() == "esES") then
+
+-- addon credits
+SMARTBUFF_CREDITS = "|cffffffff"
+ .."Versin de Classic por Codermik. Informe cualquier problema en CurseForge o mi discordia en:\n\n"
+ .."|cff00e0ffhttps://discord.gg/R6EkZ94TKK\n\n"
+ .."|cffffffffSi aprecia la cantidad de trabajo involucrado y el tiempo que se tom para brindarle estos diversos complementos, considere apoyarme de la siguiente manera:\n\n"
+ .."|cffffffffPatreon: |cff00e0ffhttps://www.patreon.com/codermik\n"
+ .."|cffffffffTwitch: |cff00e0ffhttps://www.twitch.tv/codermik\n"
+ .."|cffffffffPayPal.Me: |cff00e0ffhttps://paypal.me/codermik\n\n"
+;
+
+-- Weapon types
+SMARTBUFF_WEAPON_STANDARD = {"Dagas", "Hachas", "Espadas", "Mazas", "Bastones", "Armas de pu\195\177o", "Lanzas", "Arma arrojadiza"};
+SMARTBUFF_WEAPON_BLUNT = {"Mazas", "Bastones", "Armas de pu\195\177o"};
+SMARTBUFF_WEAPON_BLUNT_PATTERN = "^Contrapeso %a+";
+SMARTBUFF_WEAPON_SHARP = {"Dagas", "Hachas", "Espadas", "Lanzas"};
+SMARTBUFF_WEAPON_SHARP_PATTERN = "^Piedra de afilar %a+";
+
+-- Creature types
+SMARTBUFF_HUMANOID = "Humanoide";
+SMARTBUFF_DEMON = "Demonio";
+SMARTBUFF_BEAST = "Bestia";
+SMARTBUFF_ELEMENTAL = "Elemental";
+SMARTBUFF_DEMONTYPE = "Diablillo";
+SMARTBUFF_UNDEAD = "No-muerto";
+
+-- Classes
+SMARTBUFF_CLASSES = {"Druida", "Cazador", "Mago", "Palad\195\173n", "Sacerdote", "P\195\173caro", "Cham\195\161n", "Brujo", "Guerrero", "Caballero de la Muerte", "Monje", "Cazador de demonios", "Mascota de cazador", "Mascota de brujo", "Mascota de caballero de la Muerte", "Tanque", "Sanador", "Infligir da\195\177o"};
+
+-- Templates and Instances
+SMARTBUFF_TEMPLATES = {"Solo", "Grupo", "Banda", "Campos de batalla", "Arena", "CCH", "PdC", "Ulduar", "MC", "Ony", "BWL", "Naxx", "AQ", "ZG", "Custom 1", "Custom 2", "Custom 3", "Custom 4", "Custom 5"};
+SMARTBUFF_INSTANCES = {"Ciudadela de la Corona de Hielo", "Prueba del Cruzado", "Ulduar", "N\195\186cleo de Magma", "Guarida de Onyxia", "Guarida alanegra", "Naxxramas", "Ahn'Qiraj", "Zul'Gurub"};
+
+-- Mount
+SMARTBUFF_MOUNT = "Aumenta la velocidad en un (%d+)%%.";
+
+-- Bindings
+BINDING_NAME_SMARTBUFF_BIND_TRIGGER = "Disparador";
+BINDING_NAME_SMARTBUFF_BIND_TARGET = "Objetivo";
+BINDING_NAME_SMARTBUFF_BIND_OPTIONS = "Men\195\186 de opciones";
+BINDING_NAME_SMARTBUFF_BIND_RESETBUFFTIMERS = "Restaurar temporizador de buffs";
+
+-- Options Frame Text
+SMARTBUFF_OFT = "SmartBuff On/Off";
+SMARTBUFF_OFT_MENU = "Mostrar/Ocultar men\195\186 de opciones";
+SMARTBUFF_OFT_AUTO = "Recordatorio";
+SMARTBUFF_OFT_AUTOTIMER = "Revisar temporizador";
+SMARTBUFF_OFT_AUTOCOMBAT = "en combate";
+SMARTBUFF_OFT_AUTOCHAT = "Chat";
+SMARTBUFF_OFT_AUTOSPLASH = "Splash";
+SMARTBUFF_OFT_AUTOSOUND = "Sonido";
+SMARTBUFF_OFT_AUTOREST = "Desactivar en ciudades";
+SMARTBUFF_OFT_HUNTERPETS = "Buffar mascotas de Cazador";
+SMARTBUFF_OFT_WARLOCKPETS = "Buffar mascotas de Brujo";
+SMARTBUFF_OFT_ARULES = "Reglas avanzadas";
+SMARTBUFF_OFT_GRP = "Subgrupos de Banda para buffar";
+SMARTBUFF_OFT_SUBGRPCHANGED = "Abrir men\195\186 de opciones";
+SMARTBUFF_OFT_BUFFS = "Buffs/Habilidades";
+SMARTBUFF_OFT_TARGET = "Buffar el objetivo seleccionado";
+SMARTBUFF_OFT_DONE = "Hecho";
+SMARTBUFF_OFT_APPLY = "Aplicar";
+SMARTBUFF_OFT_GRPBUFFSIZE = "Tama\195\177o del grupo";
+SMARTBUFF_OFT_CLASSBUFFSIZE = "Tama\195\177o de clase";
+SMARTBUFF_OFT_MESSAGES = "Desactivar im\195\161genes";
+SMARTBUFF_OFT_MSGNORMAL = "normal";
+SMARTBUFF_OFT_MSGWARNING = "aviso";
+SMARTBUFF_OFT_MSGERROR = "error";
+SMARTBUFF_OFT_HIDEMMBUTTON = "Ocultar bot\195\179n de minimapa";
+SMARTBUFF_OFT_REBUFFTIMER = "Temporizador de Rebuff";
+SMARTBUFF_OFT_AUTOSWITCHTMP = "Cambiar plantilla";
+SMARTBUFF_OFT_SELFFIRST = "Primero uno mismo";
+SMARTBUFF_OFT_SCROLLWHEELUP = "Buffar con scroll arriba";
+SMARTBUFF_OFT_SCROLLWHEELDOWN= "abajo";
+SMARTBUFF_OFT_TARGETSWITCH = "cambio de objetivo";
+SMARTBUFF_OFT_BUFFTARGET = "Buffar objetivo";
+SMARTBUFF_OFT_BUFFPVP = "Buffar en JcJ";
+SMARTBUFF_OFT_AUTOSWITCHTMPINST = "Instancias";
+SMARTBUFF_OFT_CHECKCHARGES = "Comprobar cargas";
+SMARTBUFF_OFT_RBT = "Restaurar BT";
+SMARTBUFF_OFT_BUFFINCITIES = "Buffar en ciudades";
+SMARTBUFF_OFT_UISYNC = "Sincronizar con UI";
+SMARTBUFF_OFT_BLDURATION = "Lista Negra";
+SMARTBUFF_OFT_COMPMODE = "Modo Comp.";
+SMARTBUFF_OFT_MINIGRP = "Mini grupo";
+SMARTBUFF_OFT_ANTIDAZE = "Anti aturdimiento";
+SMARTBUFF_OFT_HIDESABUTTON = "Ocultar bot\195\179n de acci\195\179n";
+SMARTBUFF_OFT_INCOMBAT = "en combate";
+SMARTBUFF_OFT_SMARTDEBUFF = "SmartDebuff";
+SMARTBUFF_OFT_INSHAPESHIFT = "Shapeshift";
+SMARTBUFF_OFT_LINKGRPBUFFCHECK = "Grp link";
+SMARTBUFF_OFT_LINKSELFBUFFCHECK = "Self link";
+SMARTBUFF_OFT_RESETALL = "Reset All";
+SMARTBUFF_OFT_RESETLIST = "Reset List";
+SMARTBUFF_OFT_YES = "Yes";
+SMARTBUFF_OFT_NO = "No";
+SMARTBUFF_OFT_PURGE_DATA = "Are you sure you want to reset ALL SmartBuff data?\nThis action will force a reload of the UI!";
+
+-- Options Frame Tooltip Text
+SMARTBUFF_OFTT = "Alterna SmartBuff On/Off";
+SMARTBUFF_OFTT_AUTO = "Alterna el recordatorio de buff On/Off";
+SMARTBUFF_OFTT_AUTOTIMER = "Retraso en segundos entre dos comprobaciones.";
+SMARTBUFF_OFTT_AUTOCOMBAT = "Ejecutar comprobaci\195\179n tambi\195\169n en combate.";
+SMARTBUFF_OFTT_AUTOCHAT = "Muestra los buffs perdidos como mensajes en el chat.";
+SMARTBUFF_OFTT_AUTOSPLASH = "Muestra los buffs perdidos como mensajes en medio de la pantalla.";
+SMARTBUFF_OFTT_AUTOSOUND = "Toca un sonido cuando se pierden los buffs.";
+SMARTBUFF_OFTT_AUTOREST = "Desactiva el recordatorio en las ciudades principales";
+SMARTBUFF_OFTT_HUNTERPETS = "Buffar la mascota del cazador tambi\195\169n.";
+SMARTBUFF_OFTT_WARLOCKPETS = "Buffar la mascota del brujo tambi\195\169n, excepto el " .. SMARTBUFF_DEMONTYPE .. ".";
+SMARTBUFF_OFTT_ARULES = "No lanzar:\n- Espinas en Magos, Sacerdotes y Brujos\n- Intelecto Arcano en unidades sin Man\195\161\n- Esp\195\173ritu divino en unidades sin Man\195\161";
+SMARTBUFF_OFTT_SUBGRPCHANGED = "Abrir autom\195\161ticamente el men\195\186 de opciones,\ncuando has cambiado de subgrupo.";
+SMARTBUFF_OFTT_GRPBUFFSIZE = "A cu\195\161ntos jugadores con el buff de grupo\nperdido y que deber\195\173an estar en el grupo,\n va a buffar el buff de grupo.";
+SMARTBUFF_OFTT_HIDEMMBUTTON = "Oculta el bot\195\179n de SmartBuff del minimapa.";
+SMARTBUFF_OFTT_REBUFFTIMER = "Cu\195\161ntos segundos antes de que el buff expire,\nte debe alertar el recordatorio.\n0 = Desactivado";
+SMARTBUFF_OFTT_SELFFIRST = "Buffar tu personaje antes que los dem\195\161s.";
+SMARTBUFF_OFTT_SCROLLWHEELUP = "Lanzar buffs cuando muevas tu\nrueda del rat\195\179n adelante.";
+SMARTBUFF_OFTT_SCROLLWHEELDOWN = "Lanzar buffs cuando muevas tu\nrueda del rat\195\179n atr\195\161s.";
+SMARTBUFF_OFTT_TARGETSWITCH = "Lanzar buffs cuando cambias de objetivo.";
+SMARTBUFF_OFTT_BUFFTARGET = "Buffar primero el objetivo actual,\nsi es amigable.";
+SMARTBUFF_OFTT_BUFFPVP = "Buffar jugadores con JcJ activo,\naunque t\195\186 no lo tengas activado.";
+SMARTBUFF_OFTT_AUTOSWITCHTMP = "Cambiar autom\195\161ticamente la plantilla,\nsi el tipo de grupo cambia.";
+SMARTBUFF_OFTT_AUTOSWITCHTMPINST = "Cambiar autom\195\161ticamente la plantilla,\nsi la instancia cambia.";
+SMARTBUFF_OFTT_CHECKCHARGES = "Muestra cantidad baja de \ncargas en un buff.\n0 = Desactivado";
+SMARTBUFF_OFTT_BUFFINCITIES = "Buffar tambi\195\169n si est\195\161s en una ciudad principal.\nSi tienes activado el JcJ, buffar igualmente.";
+SMARTBUFF_OFTT_UISYNC = "Activar sincronizaci\195\179n con la UI\npara recuperar el tiempo de buff restante de otros jugadores.";
+SMARTBUFF_OFTT_BLDURATION = "Cuantos segundos est\195\161n los jugadores en la lista negra.\n0 = Desactivado";
+SMARTBUFF_OFTT_COMPMODE = "Modo compatible\nAtenci\195\179n!!!\nUsar este modo s\195\179lo si est\195\161s\nteniendo problemas para lanzarte buffs a t\195\173 mismo.";
+SMARTBUFF_OFTT_MINIGRP = "Mostrar los ajustes del subgrupo de banda en un\nmarco propio movible";
+SMARTBUFF_OFTT_ANTIDAZE = "Autom\195\161ticamente cancela el\naspecto del mono/manada\nsi alguien est\195\161 aturdido\n(\195\169l mismo o el grupo).";
+SMARTBUFF_OFTT_SPLASHSTYLE = "Cambia la fuente de\nlos mensajes de buff.";
+SMARTBUFF_OFTT_HIDESABUTTON = "Oculta el bot\195\179n de acci\195\179n de SmartBuff.";
+SMARTBUFF_OFTT_INCOMBAT = "De momento s\195\179lo funciona sobre t\195\173 mismo.\nEl primer buff que marcas para combate,\nse establecer\195\161 en el bot\195\179n antes del combate\ny puede ser usado en combate.\nAviso! Toda l\195\179gica se inutiliza en combate";
+SMARTBUFF_OFTT_SMARTDEBUFF = "Muestra la pesta\195\177a de SmartDeBuff";
+SMARTBUFF_OFTT_SPLASHDURATION= "Cu\195\161ntos segundos estar\195\161 en pantalla el\nmensaje,\nantes de atenuarse.";
+SMARTBUFF_OFTT_INSHAPESHIFT = "Cast buffs also if you\nare shapeshifted.";
+SMARTBUFF_OFTT_LINKGRPBUFFCHECK = "Checks if a buff of an other\nclass with similar effect\nis already active.";
+SMARTBUFF_OFTT_LINKSELFBUFFCHECK = "Checks if a self buff is active,\nwhose only one can be\nactive at a time.";
+
+-- Buffsetup Frame Text
+SMARTBUFF_BST_SELFONLY = "Uno mismo s\195\179lo";
+SMARTBUFF_BST_SELFNOT = "No a uno mismo";
+SMARTBUFF_BST_COMBATIN = "En combate";
+SMARTBUFF_BST_COMBATOUT = "Fuera de combate";
+SMARTBUFF_BST_MAINHAND = "Mano principal";
+SMARTBUFF_BST_OFFHAND = "Una mano";
+SMARTBUFF_BST_RANGED = "Arma arrojadiza";
+SMARTBUFF_BST_REMINDER = "Notificaci\195\179n";
+SMARTBUFF_BST_MANALIMIT = "M\195\173nimo obligado";
+
+-- Buffsetup Frame Tooltip Text
+SMARTBUFF_BSTT_SELFONLY = "Buffar s\195\179lo tu personaje.";
+SMARTBUFF_BSTT_SELFNOT = "Buffar todas las clases seleccionadas excepto tu personaje.";
+SMARTBUFF_BSTT_COMBATIN = "Buffar si est\195\161s en combate.";
+SMARTBUFF_BSTT_COMBATOUT = "Buffar si est\195\161s fuera de combate.";
+SMARTBUFF_BSTT_MAINHAND = "Buffar Mano principal.";
+SMARTBUFF_BSTT_OFFHAND = "Buffar Una mano.";
+SMARTBUFF_BSTT_RANGED = "Buffs the ranged slot.";
+SMARTBUFF_BSTT_REMINDER = "Visualizar mensaje recordatorio.";
+SMARTBUFF_BSTT_REBUFFTIMER = "Cu\195\161ntos segundos antes de que el buff expire,\ndebe el recordatorio avisarte.\n0 = temporizador de rebuff global";
+SMARTBUFF_BSTT_MANALIMIT = "Umbral de Man\195\161/Ira/Energ\195\173a\nSi tienes menos de este valor\nno se lanzar\195\161 el buff";
+
+-- Playersetup Frame Tooltip Text
+SMARTBUFF_PSTT_RESIZE = "Minimiza/maximiza\nla ventana principal de opciones";
+
+-- Messages
+SMARTBUFF_MSG_LOADED = "cargado";
+SMARTBUFF_MSG_NEWVER1 = "|cff00e0ffSmartbuff : |cffffffff Una nueva versin est disponible para descargar, usted est usando la versin |cffFFFF00";
+SMARTBUFF_MSG_NEWVER2 = "|cffffffff y la versin |cffFFFF00r"
+SMARTBUFF_MSG_NEWVER3 = "|cffffffff ya est disponible para su descarga. nase a Discord para obtener toda la informacin ms reciente en https://discord.gg/R6EkZ94TKK.";
+SMARTBUFF_MSG_DISABLED = "SmartBuff est\195\161 deshabilitado!";
+SMARTBUFF_MSG_SUBGROUP = "Te has unido a un nuevo subgrupo, por favor comprueba las opciones!";
+SMARTBUFF_MSG_NOTHINGTODO = "Nada que hacer";
+SMARTBUFF_MSG_BUFFED = "buffado";
+SMARTBUFF_MSG_OOR = "est\195\161 fuera de rango para lanzar el buff!";
+--SMARTBUFF_MSG_CD = "est\195\161 recargando!";
+SMARTBUFF_MSG_CD = "Recarga global!";
+SMARTBUFF_MSG_CHAT = "no es posible en el modo chat!";
+SMARTBUFF_MSG_SHAPESHIFT = "No se puede lanzar con la forma cambiada!";
+SMARTBUFF_MSG_NOACTIONSLOT = "necesita un hueco en la barra de acci\195\179n para funcionar correctamente!";
+SMARTBUFF_MSG_GROUP = "Grupo";
+SMARTBUFF_MSG_NEEDS = "necesitas";
+SMARTBUFF_MSG_OOM = "No hay suficiente man\195\161/ira/energ\195\173a!";
+SMARTBUFF_MSG_STOCK = "No tienes stock";
+SMARTBUFF_MSG_NOREAGENT = "Sin reagente:";
+SMARTBUFF_MSG_DEACTIVATED = "desactivado!";
+SMARTBUFF_MSG_REBUFF = "Rebuff";
+SMARTBUFF_MSG_LEFT = "tiempo restante";
+SMARTBUFF_MSG_CLASS = "Clase";
+SMARTBUFF_MSG_CHARGES = "cargas";
+SMARTBUFF_MSG_SPECCHANGED = "Spec changed (%s), loading buff templates...";
+
+-- Support
+SMARTBUFF_MINIMAP_TT = "Click izquierdo: men\195\186 de opciones\nClick derecho: On/Off\nAlt-Click izquierdo: SmartDebuff\nMay\195\186scuals arrastrar: Mover bot\195\179n";
+SMARTBUFF_TITAN_TT = "Click izquierdo: Abrir opciones\nClick derecho: On/Off\nAlt-Click izquierdo: SmartDebuff";
+SMARTBUFF_FUBAR_TT = "\nClick izquierdo: Abrir opciones\nMay\195\186sulas-Click izquierdo: On/Off\nAlt-Click izquierdo: SmartDebuff";
+
+SMARTBUFF_DEBUFF_TT = "May\195\186sculas-arrastrar bot\195\179n izquierdo: Mover marco\n|cff20d2ff- S bot\195\179n -|r\nClick izquierdo: Mostrar por clases\nMay\195\186sculas-Click izquierdo: Clases por colores\nAlt-Click izquierdo: Destacar L/R\n|cff20d2ff- P bot\195\179n -|r\nLeft click: Hide pets on/off";
+
+end
diff --git a/localization.fr.lua b/localization.fr.lua
new file mode 100644
index 0000000..c3c1cca
--- /dev/null
+++ b/localization.fr.lua
@@ -0,0 +1,205 @@
+-------------------------------------------------------------------------------
+-- French localization
+-- Last update : 05/06/2006
+-- By ( Sasmira, Cosmos Team )
+-------------------------------------------------------------------------------
+
+if (GetLocale() == "frFR") then
+
+-- addon credits
+SMARTBUFF_CREDITS = "|cffffffff"
+ .."Version Classic par Codermik. Veuillez signaler tout problème sur CurseForge ou mon discord:\n\n"
+ .."|cff00e0ffhttps://discord.gg/R6EkZ94TKK\n\n"
+ .."|cffffffffSi vous appréciez la quantité de travail impliquée et le temps pris pour vous apporter ces différents addons, pensez à me soutenir en :\n\n"
+ .."|cffffffffPatreon: |cff00e0ffhttps://www.patreon.com/codermik\n"
+ .."|cffffffffTwitch: |cff00e0ffhttps://www.twitch.tv/codermik\n"
+ .."|cffffffffPayPal.Me: |cff00e0ffhttps://paypal.me/codermik\n\n"
+;
+
+-- Weapon types
+SMARTBUFF_WEAPON_STANDARD = {"Dagues", "Haches", "Ep\195\169es", "Masses", "B\195\162tons", "Armes de pugilat", "Armes d\'hast", "Armes de jet"};
+SMARTBUFF_WEAPON_BLUNT = {"Masses", "B\195\162tons", "Armes de pugilat"};
+SMARTBUFF_WEAPON_BLUNT_PATTERN = "^Pierre de lest ";
+SMARTBUFF_WEAPON_SHARP = {"Dagues", "Haches", "Ep\195\169es", "Armes d\'hast"};
+SMARTBUFF_WEAPON_SHARP_PATTERN = "^Pierre \195\160 aiguiser ";
+
+-- Creature types
+SMARTBUFF_HUMANOID = "Humano\195\175de";
+SMARTBUFF_DEMON = "D\195\169mon";
+SMARTBUFF_BEAST = "B\195\170te";
+SMARTBUFF_ELEMENTAL = "\195\137l\195\169mentaire";
+SMARTBUFF_DEMONTYPE = "Diablotin";
+SMARTBUFF_UNDEAD = "Mort-vivant";
+
+-- Classes
+SMARTBUFF_CLASSES = {"Druide", "Chasseur", "Mage", "Paladin", "Pr\195\170tre", "Voleur", "Chaman", "D\195\169moniste", "Guerrier", "Chevalier de la mort", "Moine", "Chasseur de démons", "Chasseur Pet", "D\195\169moniste Pet", "Chevalier de la mort Pet", "Tank", "Gu\195\169risseur", "Sp\195\169cialiste des d\195\169g\195\162ts"};
+
+-- Templates and Instances
+SMARTBUFF_TEMPLATES = {"Seul", "Groupe", "Raid", "Champs de Bataille", "Ar\195\168ne", "CCG", "EdC", "Ulduar", "MC", "Ony", "BWL", "Naxx", "AQ", "ZG", "Custom 1", "Custom 2", "Custom 3", "Custom 4", "Custom 5"};
+SMARTBUFF_INSTANCES = {"Citadelle de la Couronne de glace", "L\'\195\169preuve du crois\195\169", "Ulduar", "C\197\147ur du Magma", "Repaire d\'Onyxia", "Repaire de l\'Aile noire", "Naxxramas", "Ahn'Qiraj", "Zul'Gurub"};
+
+-- Mount
+SMARTBUFF_MOUNT = "Augmente la vitesse de (%d+)%%.";
+
+-- Bindings
+BINDING_NAME_SMARTBUFF_BIND_TRIGGER = "D\195\169clencheur";
+BINDING_NAME_SMARTBUFF_BIND_TARGET = "Cible";
+BINDING_NAME_SMARTBUFF_BIND_OPTIONS = "Menu d\'Options";
+BINDING_NAME_SMARTBUFF_BIND_RESETBUFFTIMERS = "Reset buff timers";
+
+-- Options Frame Text
+SMARTBUFF_OFT = "ON/OFF SmartBuff";
+SMARTBUFF_OFT_MENU = "Afficher/Cacher le menu d\'options";
+SMARTBUFF_OFT_AUTO = "Rappel";
+SMARTBUFF_OFT_AUTOTIMER = "V\195\169rifier";
+SMARTBUFF_OFT_AUTOCOMBAT = "En combat";
+SMARTBUFF_OFT_AUTOCHAT = "Chat";
+SMARTBUFF_OFT_AUTOSPLASH = "Splash";
+SMARTBUFF_OFT_AUTOSOUND = "Son";
+SMARTBUFF_OFT_AUTOREST = "D\195\169sactiver dans les Capitales";
+SMARTBUFF_OFT_HUNTERPETS = "Buff: Pets Chasseur";
+SMARTBUFF_OFT_WARLOCKPETS = "Buff: Pets D\195\169mo.";
+SMARTBUFF_OFT_ARULES = "R\195\168gles avanc\195\169es";
+SMARTBUFF_OFT_GRP = "Sous Groupe Raid \195\160 Buffer";
+SMARTBUFF_OFT_SUBGRPCHANGED = "Ouvrir le menu";
+SMARTBUFF_OFT_BUFFS = "Buffs/Capacit\195\169s";
+SMARTBUFF_OFT_TARGET = "Buffs la cible s\195\169lectionn\195\169e";
+SMARTBUFF_OFT_DONE = "Quitter";
+SMARTBUFF_OFT_APPLY = "Appliquer";
+SMARTBUFF_OFT_GRPBUFFSIZE = "Taille: Groupe";
+SMARTBUFF_OFT_CLASSBUFFSIZE = "Taille: Classe";
+SMARTBUFF_OFT_MESSAGES = "D\195\169sactiver: Message";
+SMARTBUFF_OFT_MSGNORMAL = "Normal";
+SMARTBUFF_OFT_MSGWARNING = "Avertissement";
+SMARTBUFF_OFT_MSGERROR = "Erreur";
+SMARTBUFF_OFT_HIDEMMBUTTON = "Cacher: Bouton Minimap";
+SMARTBUFF_OFT_REBUFFTIMER = "Timer: Rebuff";
+SMARTBUFF_OFT_AUTOSWITCHTMP = "Changer de config";
+SMARTBUFF_OFT_SELFFIRST = "Moi en premier";
+SMARTBUFF_OFT_SCROLLWHEELUP = "Buff avec la Souris en haut";
+SMARTBUFF_OFT_SCROLLWHEELDOWN= "en bas";
+SMARTBUFF_OFT_TARGETSWITCH = "Changer de Cible";
+SMARTBUFF_OFT_BUFFTARGET = "Buff sur Cible";
+SMARTBUFF_OFT_BUFFPVP = "JcJ Buff";
+SMARTBUFF_OFT_AUTOSWITCHTMPINST = "Instance";
+SMARTBUFF_OFT_CHECKCHARGES = "Charges";
+SMARTBUFF_OFT_RBT = "Reset BT";
+SMARTBUFF_OFT_BUFFINCITIES = "Buff dans les Cap.";
+SMARTBUFF_OFT_UISYNC = "UI sync";
+SMARTBUFF_OFT_BLDURATION = "Liste noire";
+SMARTBUFF_OFT_COMPMODE = "Comp. mode";
+SMARTBUFF_OFT_MINIGRP = "Mini groupe";
+SMARTBUFF_OFT_ANTIDAZE = "Anti daze"; -- NOT TRANSLATED
+SMARTBUFF_OFT_HIDESABUTTON = "Cacher: Bouton action";
+SMARTBUFF_OFT_INCOMBAT = "en combat";
+SMARTBUFF_OFT_SMARTDEBUFF = "SmartDebuff";
+SMARTBUFF_OFT_INSHAPESHIFT = "Shapeshift";
+SMARTBUFF_OFT_LINKGRPBUFFCHECK = "Grp link";
+SMARTBUFF_OFT_LINKSELFBUFFCHECK = "Self link";
+SMARTBUFF_OFT_RESETALL = "Reset All";
+SMARTBUFF_OFT_RESETLIST = "Reset List";
+SMARTBUFF_OFT_YES = "Oui";
+SMARTBUFF_OFT_NO = "No";
+SMARTBUFF_OFT_PURGE_DATA = "Are you sure you want to reset ALL SmartBuff data?\nThis action will force a reload of the UI!";
+
+-- Options Frame Tooltip Text
+SMARTBUFF_OFTT = "ON/OFF SmartBuff";
+SMARTBUFF_OFTT_AUTO = "ON/OFF Le rappel de buff";
+SMARTBUFF_OFTT_AUTOTIMER = "D\195\169lai en secondes entre deux v\195\169rifications.";
+SMARTBUFF_OFTT_AUTOCOMBAT = "Lance une v\195\169rification en combat.";
+SMARTBUFF_OFTT_AUTOCHAT = "Affiche dans le chat un message lorsque le buff est expir\195\169.";
+SMARTBUFF_OFTT_AUTOSPLASH = "Affiche un message au milieu de l\'\195\169cran \nlorsque le buff est expir\195\169.";
+SMARTBUFF_OFTT_AUTOSOUND = "Joue un son lorsque les buffs sont expir\195\169s.";
+SMARTBUFF_OFTT_AUTOREST = "D\195\169sactiver le rappel dans les Capitales.";
+SMARTBUFF_OFTT_HUNTERPETS = "Buff les pets de Chasseur.";
+SMARTBUFF_OFTT_WARLOCKPETS = "Buff les pets de D\195\169moniste, except\195\169 le " .. SMARTBUFF_DEMONTYPE .. ".";
+SMARTBUFF_OFTT_ARULES = "Ne peut \195\170tre lanc\195\169:\n- Epines sur Mages, Pr\195\170tres et D\195\169monistes\n- Intelligence des Arcanes sur des unit\195\169s sans Mana\n- Esprit Divin sur des unit\195\169s sans Mana";
+SMARTBUFF_OFTT_SUBGRPCHANGED = "Ouvre Automatiquement le menu d\'options de SmartBuff,\nlorsque vous changez de sous groupe.";
+SMARTBUFF_OFTT_GRPBUFFSIZE = "Le nombre de joueurs que vous avez \ndans le groupe pour utiliser le Buff de groupe.";
+SMARTBUFF_OFTT_HIDEMMBUTTON = "Cache le bouton SmartBuff de la Minimap.";
+SMARTBUFF_OFTT_REBUFFTIMER = "Indique le temps en secondes avant que le Buff expire,\nle rappel vous lancera une alerte.\n0 = D\195\169sactiv\195\169";
+SMARTBUFF_OFTT_SELFFIRST = "Buffs votre personnage en premier avant tous les autres.";
+SMARTBUFF_OFTT_SCROLLWHEELUP = "Applique les buffs \nlorsque vous utilisez la molette de la souris.";
+SMARTBUFF_OFTT_SCROLLWHEELDOWN = "Applique les buffs \nlorsque vous utilisez la molette de la souris.";
+SMARTBUFF_OFTT_TARGETSWITCH = "Lancer les buffs lorsque vous changez votre cible.";
+SMARTBUFF_OFTT_BUFFTARGET = "Buffs en premier la cible courante,\nde la m\195\170me faction.";
+SMARTBUFF_OFTT_BUFFPVP = "JcJ Buff sur les joueurs marqu\195\169s JcJ,\nm\195\170me si vous n\'\195\170tes pas vous aussi en JcJ.";
+SMARTBUFF_OFTT_AUTOSWITCHTMP = "Change automatiquement de configuration,\nsi le type de groupe change.";
+SMARTBUFF_OFTT_AUTOSWITCHTMPINST = "Change automatiquement de configuration,\nsi l\'instance change.";
+SMARTBUFF_OFTT_CHECKCHARGES = "Affiche un message au quantit\195\169 basse\nde charges que un Buff\n0 = D\195\169sactiv\195\169";
+SMARTBUFF_OFTT_BUFFINCITIES = "Buffs also if you are in capital cities.\nIf you are PvP flagged, it buffs in any case."; -- NOT TRANSLATED
+SMARTBUFF_OFTT_UISYNC = "Activate syncronisation with the UI\nto retrive the bufftime left from other players."; -- NOT TRANSLATED
+SMARTBUFF_OFTT_BLDURATION = "How many seconds, players will be blacklistet.\n0 = Deactivated"; -- NOT TRANSLATED
+SMARTBUFF_OFTT_COMPMODE = "Compatibility mode\nAttention!!!\nUses this mode only, if you are\nfacing problems to cast buffs on yourself.";
+SMARTBUFF_OFTT_MINIGRP = "Show raid subgoup settings in an\nown movable mini group frame."; -- NOT TRANSLATED
+SMARTBUFF_OFTT_ANTIDAZE = "Automatically cancels the\naspect of the cheetah/pack\nif someone gets dazed\n(self or group)."; -- NOT TRANSLATED
+SMARTBUFF_OFTT_SPLASHSTYLE = "Changes the fontstyle of\nthe buff messages."; -- NOT TRANSLATED
+SMARTBUFF_OFTT_HIDESABUTTON = "Cache le bouton SmartBuff de action."; -- NOT TRANSLATED
+SMARTBUFF_OFTT_INCOMBAT = "At the moment it only works on yourself.\nThe first buff you mark as in combat,\nwill set on the button before combat\nand you can use it in combat.\nWarning! All logic is disabled in combat!";
+SMARTBUFF_OFTT_SMARTDEBUFF = "Shows the SmartDebuff frame.";
+SMARTBUFF_OFTT_SPLASHDURATION= "How many seconds the splash\nmessage will displayed,\nbefore it fades.";
+SMARTBUFF_OFTT_INSHAPESHIFT = "Cast buffs also if you\nare shapeshifted.";
+SMARTBUFF_OFTT_LINKGRPBUFFCHECK = "Checks if a buff of an other\nclass with similar effect\nis already active.";
+SMARTBUFF_OFTT_LINKSELFBUFFCHECK = "Checks if a self buff is active,\nwhose only one can be\nactive at a time.";
+
+-- Buffsetup Frame Text
+SMARTBUFF_BST_SELFONLY = "Sur Soi";
+SMARTBUFF_BST_SELFNOT = "Sur Soi pas";
+SMARTBUFF_BST_COMBATIN = "En combat";
+SMARTBUFF_BST_COMBATOUT = "Hors combat";
+SMARTBUFF_BST_MAINHAND = "Main Principale";
+SMARTBUFF_BST_OFFHAND = "Main Gauche";
+SMARTBUFF_BST_RANGED = "Armes de jet";
+SMARTBUFF_BST_REMINDER = "Notification";
+SMARTBUFF_BST_MANALIMIT = "Lower bound";
+
+-- Buffsetup Frame Tooltip Text
+SMARTBUFF_BSTT_SELFONLY = "Buffs uniquement votre personnage.";
+SMARTBUFF_BSTT_SELFNOT = "Buffs all other selected classes,\nexcept your character."; -- NOT TRANSLATED
+SMARTBUFF_BSTT_COMBATIN = "Buffs si vous \195\170tes en combat.";
+SMARTBUFF_BSTT_COMBATOUT = "Buffs si vous \195\170tes hors combat.";
+SMARTBUFF_BSTT_MAINHAND = "Buffs La Main Principale.";
+SMARTBUFF_BSTT_OFFHAND = "Buffs La Main Gauche.";
+SMARTBUFF_BSTT_RANGED = "Buffs the ranged slot.";
+SMARTBUFF_BSTT_REMINDER = "Afficher le message de rappel.";
+SMARTBUFF_BSTT_REBUFFTIMER = "Indique le temps en secondes avant que le Buff expire,\nle rappel vous lancera une alerte.\n0 = Timer: Rebuff";
+SMARTBUFF_BSTT_MANALIMIT = "Mana/Rage/Energy threshold\nIf you are below this value\nit will not cast the buff.";
+
+-- Playersetup Frame Tooltip Text
+SMARTBUFF_PSTT_RESIZE = "Minimize/maximize\nthe main options frame";
+
+-- Messages
+SMARTBUFF_MSG_LOADED = "chargée. Classic de Codermik - veuillez signaler toute erreur trouvée.";
+SMARTBUFF_MSG_NEWVER1 = "|cff00e0ffSmartbuff : |cffffffff Il y a une nouvelle version disponible, vous utilisez |cffFFFF00";
+SMARTBUFF_MSG_NEWVER2 = "|cffffffff et révision |cffFFFF00r"
+SMARTBUFF_MSG_NEWVER3 = "|cffffffff est actuellement disponible en téléchargement. Rejoignez Discord pour toutes les dernières informations à https://discord.gg/R6EkZ94TKK.";
+SMARTBUFF_MSG_DISABLED = "SmartBuff est d\195\169sactiv\195\169 !";
+SMARTBUFF_MSG_SUBGROUP = "Vous venez de rejoindre un nouveau sous groupe, merci de v\195\169rifier les options !";
+SMARTBUFF_MSG_NOTHINGTODO = "STOP, IL N\'Y A PLUS RIEN A LANCER !!! Tous les Buffs sont deja lanc\195\169s ;-)";
+SMARTBUFF_MSG_BUFFED = "vient d\'\195\170tre appliqu\195\169(e)";
+SMARTBUFF_MSG_OOR = "est hors de port\195\169e pour \195\170tre buff\195\169 !"
+--SMARTBUFF_MSG_CD = "vient d\'expirer !";
+SMARTBUFF_MSG_CD = "Global d\'expirer !";
+SMARTBUFF_MSG_CHAT = "Impossible en mode chat!";
+SMARTBUFF_MSG_SHAPESHIFT = "Le lancement du sort ne peut pas se faire sous cette forme !";
+SMARTBUFF_MSG_NOACTIONSLOT = "a besoin d\'un emplacement dans une barre d\'action pour fonctionner correctement !";
+SMARTBUFF_MSG_GROUP = "Groupe";
+SMARTBUFF_MSG_NEEDS = "a besoin de";
+SMARTBUFF_MSG_OOM = "Vous n\'avez pas assez de mana/rage/\195\169nergie !";
+SMARTBUFF_MSG_STOCK = "Stock actuel de";
+SMARTBUFF_MSG_NOREAGENT = "Plus assez de r\195\169actif:";
+SMARTBUFF_MSG_DEACTIVATED = "d\195\169sactivat\195\169!";
+SMARTBUFF_MSG_REBUFF = "Rebuff";
+SMARTBUFF_MSG_LEFT = "temps restant";
+SMARTBUFF_MSG_CLASS = "Classe";
+SMARTBUFF_MSG_CHARGES = "charges";
+SMARTBUFF_MSG_SPECCHANGED = "Spec changed (%s), loading buff templates...";
+
+-- Support
+SMARTBUFF_MINIMAP_TT = "Left Click: Menu d\'options\nRight Click: ON/OFF\nAlt-Left Click: SmartDebuff\nShift drag: Move button"; -- NOT TRANSLATED
+SMARTBUFF_TITAN_TT = "Left Click: Menu d\'options\nRight Click: ON/OFF\nAlt-Left Click: SmartDebuff"; -- NOT TRANSLATED
+SMARTBUFF_FUBAR_TT = "\nLeft Click: Menu d\'options\nShift-Left Click: ON/OFF\nAlt-Left Click: SmartDebuff"; -- NOT TRANSLATED
+
+SMARTBUFF_DEBUFF_TT = "Shift-Left drag: Move frame\n|cff20d2ff- S button -|r\nLeft click: Show by classes\nShift-Left click: Class colors\nAlt-Left click: Highlight L/R\n|cff20d2ff- P button -|r\nLeft click: Hide pets on/off"; -- NOT TRANSLATED
+
+end
diff --git a/localization.ru.lua b/localization.ru.lua
new file mode 100644
index 0000000..571c15b
--- /dev/null
+++ b/localization.ru.lua
@@ -0,0 +1,202 @@
+-------------------------------------------------------------------------------
+-- Russian localization by Dr. Jet Cheshirsky (don't blame me for lame OFFICIAL translations though =~_^=)
+-------------------------------------------------------------------------------
+
+if (GetLocale() == "ruRU") then
+
+-- addon credits
+SMARTBUFF_CREDITS = "|cffffffff"
+ .."Версия Classic от Codermik. Пожалуйста, сообщайте о любых проблемах на CurseForge или в моем разногласии по адресу:\n\n"
+ .."|cff00e0ffhttps://discord.gg/R6EkZ94TKK\n\n"
+ .."|cffffffffЕсли вы цените объем проделанной работы и время, затраченное на создание этих различных дополнений, пожалуйста, поддержите меня:\n\n"
+ .."|cffffffffPatreon: |cff00e0ffhttps://www.patreon.com/codermik\n"
+ .."|cffffffffTwitch: |cff00e0ffhttps://www.twitch.tv/codermik\n"
+ .."|cffffffffPayPal.Me: |cff00e0ffhttps://paypal.me/codermik\n\n"
+;
+
+-- Weapon types
+SMARTBUFF_WEAPON_STANDARD = {"Кинжалы", "топоры", "мечи", "дробящее", "Посохи", "Кистевое", "Древковое", "Метательное"};
+SMARTBUFF_WEAPON_BLUNT = {"дробящее", "Посохи", "Кистевое"};
+SMARTBUFF_WEAPON_BLUNT_PATTERN = "грузик$";
+SMARTBUFF_WEAPON_SHARP = {"Кинжалы", "топоры", "мечи", "Древковое"};
+SMARTBUFF_WEAPON_SHARP_PATTERN = "точило$";
+
+-- Creature type
+SMARTBUFF_HUMANOID = "Гуманоид";
+SMARTBUFF_DEMON = "Демон";
+SMARTBUFF_BEAST = "Животное";
+SMARTBUFF_ELEMENTAL = "Дух стихии";
+SMARTBUFF_DEMONTYPE = "Бес";
+SMARTBUFF_UNDEAD = "Undead";
+
+-- Classes
+SMARTBUFF_CLASSES = {"Друид", "Охотник", "Маг", "Паладин", "Жрец", "Разбойник", "Шаман", "Чернокнижник", "Воин", "Монах", "Питомец Охотника", "Охотник на демонов", "Прислужник Чернокнижника", "DK Pet", "танка", "целителя", "Бойцы"};
+
+-- Templates and Instances
+SMARTBUFF_TEMPLATES = {"Соло", "Группа", "Рейд", "Поле битвы", "Арена", "ЦЛК", "Ик", "Ульдуар", "ОБ", "Оня", "ЛКТ", "Накс", "АК", "ЗГ", "Своё 1", "Своё 2", "Своё 3", "Своё 4", "Своё 5"};
+SMARTBUFF_INSTANCES = {"Цитадель Ледяной Короны", "Испытание крестоносца", "Ульдуар", "Огненная Бездна", "Логово Ониксии", "Логово Крыла Тьмы", "Наксрамас", "Ан'Кираж", "Зул'Гуруб"};
+
+-- Mount
+SMARTBUFF_MOUNT = "Увеличивает скорость на (%d+)%%.";
+
+-- Bindings
+BINDING_NAME_SMARTBUFF_BIND_TRIGGER = "Триггер";
+BINDING_NAME_SMARTBUFF_BIND_TARGET = "Цель";
+BINDING_NAME_SMARTBUFF_BIND_OPTIONS = "Меню опций";
+BINDING_NAME_SMARTBUFF_BIND_RESETBUFFTIMERS = "Сбросить таймеры баффов";
+
+-- Options Frame Text
+SMARTBUFF_OFT = "Вкл/Выкл";
+SMARTBUFF_OFT_MENU = "Меню опций";
+SMARTBUFF_OFT_AUTO = "Напоминалка";
+SMARTBUFF_OFT_AUTOTIMER = "Проверка таймера";
+SMARTBUFF_OFT_AUTOCOMBAT = "в бою";
+SMARTBUFF_OFT_AUTOCHAT = "Чат";
+SMARTBUFF_OFT_AUTOSPLASH = "Всплеск";
+SMARTBUFF_OFT_AUTOSOUND = "Звук";
+SMARTBUFF_OFT_AUTOREST = "Запретить в городе";
+SMARTBUFF_OFT_HUNTERPETS = "Баффать питомцев охотника";
+SMARTBUFF_OFT_WARLOCKPETS = "Баффать питомцев чернокнижника";
+SMARTBUFF_OFT_ARULES = "Расширенные правила";
+SMARTBUFF_OFT_GRP = "Баффать подгруппы рейда";
+SMARTBUFF_OFT_SUBGRPCHANGED = "Открыть меню опций";
+SMARTBUFF_OFT_BUFFS = "Баффы/Умения";
+SMARTBUFF_OFT_TARGET = "Баффать выбраную цель";
+SMARTBUFF_OFT_DONE = "Готово";
+SMARTBUFF_OFT_APPLY = "Применить";
+SMARTBUFF_OFT_GRPBUFFSIZE = "Без групбаффа";
+SMARTBUFF_OFT_CLASSBUFFSIZE = "Без групбаффа";
+SMARTBUFF_OFT_MESSAGES = "Запретить сообщения";
+SMARTBUFF_OFT_MSGNORMAL = "обычные";
+SMARTBUFF_OFT_MSGWARNING = "предупреждения";
+SMARTBUFF_OFT_MSGERROR = "ошибки";
+SMARTBUFF_OFT_HIDEMMBUTTON = "Спрятать кнопку у карты";
+SMARTBUFF_OFT_REBUFFTIMER = "Таймер ребаффа";
+SMARTBUFF_OFT_AUTOSWITCHTMP = "Менять настройки";
+SMARTBUFF_OFT_SELFFIRST = "Сначала себя";
+SMARTBUFF_OFT_SCROLLWHEELUP = "Баффать по колесу вверх";
+SMARTBUFF_OFT_SCROLLWHEELDOWN= "вниз";
+SMARTBUFF_OFT_TARGETSWITCH = "смена цели";
+SMARTBUFF_OFT_BUFFTARGET = "Баффать цель";
+SMARTBUFF_OFT_BUFFPVP = "Баффать в PvP";
+SMARTBUFF_OFT_AUTOSWITCHTMPINST = "Подземелья";
+SMARTBUFF_OFT_CHECKCHARGES = "Проверять заряды";
+SMARTBUFF_OFT_RBT = "Сброс БТ";
+SMARTBUFF_OFT_BUFFINCITIES = "Баффать в городе";
+SMARTBUFF_OFT_UISYNC = "Синхронизация UI";
+SMARTBUFF_OFT_BLDURATION = "Ч.список";
+SMARTBUFF_OFT_COMPMODE = "Комп.режим";
+SMARTBUFF_OFT_MINIGRP = "Мини-группа";
+SMARTBUFF_OFT_ANTIDAZE = "Анти-стоп";
+SMARTBUFF_OFT_HIDESABUTTON = "Спрятать кнопку действия";
+SMARTBUFF_OFT_INCOMBAT = "в бою";
+SMARTBUFF_OFT_SMARTDEBUFF = "SmartDebuff";
+SMARTBUFF_OFT_INSHAPESHIFT = "Shapeshift";
+SMARTBUFF_OFT_LINKGRPBUFFCHECK = "Grp link";
+SMARTBUFF_OFT_LINKSELFBUFFCHECK = "Self link";
+SMARTBUFF_OFT_RESETALL = "Reset All";
+SMARTBUFF_OFT_RESETLIST = "Reset List";
+SMARTBUFF_OFT_YES = "Yes";
+SMARTBUFF_OFT_NO = "No";
+SMARTBUFF_OFT_PURGE_DATA = "Are you sure you want to reset ALL SmartBuff data?\nThis action will force a reload of the UI!";
+
+-- Options Frame Tooltip Text
+SMARTBUFF_OFTT = "Включает-выключает SmartBuff.";
+SMARTBUFF_OFTT_AUTO = "Включает-выключает напоминалку.";
+SMARTBUFF_OFTT_AUTOTIMER = "Задержка в секундах между двумя проверками.";
+SMARTBUFF_OFTT_AUTOCOMBAT = "Запускать провеку во время боя.";
+SMARTBUFF_OFTT_AUTOCHAT = "Показывать недостающие баффы в чате.";
+SMARTBUFF_OFTT_AUTOSPLASH = "Показывать недостающие баффы всплывающим сообщением в центре экрана.";
+SMARTBUFF_OFTT_AUTOSOUND = "Проигрывать звук при отсутствии нужных баффов.";
+SMARTBUFF_OFTT_AUTOREST = "Запретить напоминалку при нахождении в городе.";
+SMARTBUFF_OFTT_HUNTERPETS = "Баффать питомцев Охотника наравне с прочими.";
+SMARTBUFF_OFTT_WARLOCKPETS = "Баффать питомцев Чернокнижника, за исключением " .. SMARTBUFF_DEMONTYPE .. ".";
+SMARTBUFF_OFTT_ARULES = "Не кастовать:\n- Шипы на Магов, Жрецов и Чернокнижников\n- Чародейский интеллект на тех, у кого нет маны\n- Божественный дух на тех, у кого нет маны";
+SMARTBUFF_OFTT_SUBGRPCHANGED = "Автоматически открывать меню опций SmartBuff,\nкогда вы меняете подгруппу.";
+SMARTBUFF_OFTT_GRPBUFFSIZE = "Сколько игроков без группового баффа должно\nбыть в группе, чтобы кастовать групповой бафф.";
+SMARTBUFF_OFTT_HIDEMMBUTTON = "Спрятать кнопку SmartBuff рядом с мини-картой.";
+SMARTBUFF_OFTT_REBUFFTIMER = "За сколько секунд до спадения баффа,\nнапоминака должна предупреждать.\n0 = Отключить";
+SMARTBUFF_OFTT_SELFFIRST = "Баффать сначала себя, потом других.";
+SMARTBUFF_OFTT_SCROLLWHEELUP = "Баффать, когда вы прокручиваете\nколесо мыши вперёд.";
+SMARTBUFF_OFTT_SCROLLWHEELDOWN = "Баффать, когда вы прокручиваете\nколесо мыши назад.";
+SMARTBUFF_OFTT_TARGETSWITCH = "Баффать при смене цели.";
+SMARTBUFF_OFTT_BUFFTARGET = "Сначала баффать цель,\nесли она дружественная.";
+SMARTBUFF_OFTT_BUFFPVP = "Баффать игроков с PvP флагом,\nдаже если на вас нет PvP флага.";
+SMARTBUFF_OFTT_AUTOSWITCHTMP = "Автоматически менять набор настроек,\nесли меняется тип группы.";
+SMARTBUFF_OFTT_AUTOSWITCHTMPINST = "Автоматически менять набор настроек,\nесли меняется подземелье.";
+SMARTBUFF_OFTT_CHECKCHARGES = "Показывать нехватку зарядов баффа\nпри падении ниже этого числа.\n0 = Отключить";
+SMARTBUFF_OFTT_BUFFINCITIES = "Баффать даже при нахождении в городе.\nЕсли на вас PvP флаг, баффает в любом случае.";
+SMARTBUFF_OFTT_UISYNC = "Активировать синхронизацию с UI\nчтобы получать оставшееся время баффов\nот других игроков.";
+SMARTBUFF_OFTT_BLDURATION = "Сколько секунд игрок держится в чёрном списке.\n0 = Отключить";
+SMARTBUFF_OFTT_COMPMODE = "Режим совместимости.\nВнимание!!!\nИспользуйте этот режим только если\nу вас проблемы с обкастом себя самого.";
+SMARTBUFF_OFTT_MINIGRP = "Показывать выбор подгрупп рейда\nв отдельной маленькой рамке.";
+SMARTBUFF_OFTT_ANTIDAZE = "Автоматически прерывать\nДух Гепарда/Стаи\nесли на ком-то из группы\nповисло замедление.";
+SMARTBUFF_OFTT_SPLASHSTYLE = "Изменить шрифт сообщений о баффах.";
+SMARTBUFF_OFTT_HIDESABUTTON = "Спрятать кнопку действия SmartBuff.";
+SMARTBUFF_OFTT_INCOMBAT = "At the moment it only works on yourself.\nThe first buff you mark as in combat,\nwill set on the button before combat\nand you can use it in combat.\nWarning! All logic is disabled in combat!";
+SMARTBUFF_OFTT_SMARTDEBUFF = "Shows the SmartDebuff frame.";
+SMARTBUFF_OFTT_SPLASHDURATION= "Сколько секунд будут отображаться\nвсплывающие сообщения.";
+SMARTBUFF_OFTT_INSHAPESHIFT = "Cast buffs also if you\nare shapeshifted.";
+SMARTBUFF_OFTT_LINKGRPBUFFCHECK = "Checks if a buff of an other\nclass with similar effect\nis already active.";
+SMARTBUFF_OFTT_LINKSELFBUFFCHECK = "Checks if a self buff is active,\nwhose only one can be\nactive at a time.";
+
+-- Buffsetup Frame Text
+SMARTBUFF_BST_SELFONLY = "Только себя";
+SMARTBUFF_BST_SELFNOT = "Кроме себя";
+SMARTBUFF_BST_COMBATIN = "В бою";
+SMARTBUFF_BST_COMBATOUT = "Вне боя";
+SMARTBUFF_BST_MAINHAND = "Правая рука";
+SMARTBUFF_BST_OFFHAND = "Левая рука";
+SMARTBUFF_BST_RANGED = "Метательное";
+SMARTBUFF_BST_REMINDER = "Напоминалка";
+SMARTBUFF_BST_MANALIMIT = "При уровне\nманы не ниже";
+
+-- Buffsetup Frame Tooltip Text
+SMARTBUFF_BSTT_SELFONLY = "Баффать только себя любимого.";
+SMARTBUFF_BSTT_SELFNOT = "Баффать все выбранные классы,\nкроме себя самого.";
+SMARTBUFF_BSTT_COMBATIN = "Баффать если вы в бою.";
+SMARTBUFF_BSTT_COMBATOUT = "Баффать если вы не в бою.";
+SMARTBUFF_BSTT_MAINHAND = "Бафф на оружие правой руки.";
+SMARTBUFF_BSTT_OFFHAND = "Бафф на оружие левой руки.";
+SMARTBUFF_BSTT_RANGED = "Buffs the ranged slot.";
+SMARTBUFF_BSTT_REMINDER = "Показывать окошко напоминалки.";
+SMARTBUFF_BSTT_REBUFFTIMER = "За сколько секунд до спадения баффа,\nнапоминалка должна предупредить.\n0 = общий таймер проверки";
+SMARTBUFF_BSTT_MANALIMIT = "Уровень Маны/Ярости/Энергии. \nЕсли он окажется ниже,\nто баффа не будет.";
+
+-- Playersetup Frame Tooltip Text
+SMARTBUFF_PSTT_RESIZE = "Свернуть/развернуть\nосновное окно опций";
+
+-- Messages
+SMARTBUFF_MSG_LOADED = "загружен. Версия Classic от Codermik - сообщайте обо всех обнаруженных ошибках.";
+SMARTBUFF_MSG_NEWVER1 = "|cff00e0ffSmartbuff : |cffffffff Доступна новая версия, вы используете |cffFFFF00";
+SMARTBUFF_MSG_NEWVER2 = "|cffffffff и версия |cffFFFF00r"
+SMARTBUFF_MSG_NEWVER3 = "|cffffffff в настоящее время доступна для загрузки. Присоединяйтесь к Discord для получения последней информации по адресу https://discord.gg/R6EkZ94TKK.";
+SMARTBUFF_MSG_DISABLED = "SmartBuff отключен!";
+SMARTBUFF_MSG_SUBGROUP = "Вы присоединились к новой группе, проверьте опции!";
+SMARTBUFF_MSG_NOTHINGTODO = "Нечего делать";
+SMARTBUFF_MSG_BUFFED = "- бафф наложен";
+SMARTBUFF_MSG_OOR = "вне зоны действия баффа!";
+SMARTBUFF_MSG_CD = "Глобальный кулдаун!";
+SMARTBUFF_MSG_CHAT = "невозможно в режиме чата!";
+SMARTBUFF_MSG_SHAPESHIFT = "Нельзя колдовать в звероформе!";
+SMARTBUFF_MSG_NOACTIONSLOT = "требуется слот в панели действий для правильной работы!";
+SMARTBUFF_MSG_GROUP = "Группа";
+SMARTBUFF_MSG_NEEDS = "нуждается в баффе:";
+SMARTBUFF_MSG_OOM = "Не хватает маны/ярости/энергии!";
+SMARTBUFF_MSG_STOCK = "Имеющийся запас";
+SMARTBUFF_MSG_NOREAGENT = "Нехватка реагента:";
+SMARTBUFF_MSG_DEACTIVATED = "деактивировано!";
+SMARTBUFF_MSG_REBUFF = "Реббафф";
+SMARTBUFF_MSG_LEFT = "осталось";
+SMARTBUFF_MSG_CLASS = "Класс";
+SMARTBUFF_MSG_CHARGES = "зарядов";
+SMARTBUFF_MSG_SPECCHANGED = "Spec changed (%s), loading buff templates...";
+
+-- Support
+SMARTBUFF_MINIMAP_TT = "Левой кнопкой: меню опций\nПравой кнопкой: Вкл/Выкл\nAlt+Левой Кнопкой: SmartDebuff\nТащить с Shift-ом: Двигать кнопку";
+SMARTBUFF_TITAN_TT = "Левой кнопкой: меню опций\nПравой кнопкой: Вкл/Выкл\nAlt+Левой Кнопкой: SmartDebuff";
+SMARTBUFF_FUBAR_TT = "Левой кнопкой: меню опций\nShift+Левой кнопкой: Вкл/Выкл\nAlt+Левой Кнопкой: SmartDebuff";
+
+SMARTBUFF_DEBUFF_TT = "Shift+тащить: Двигать рамку\n|cff20d2ff- S button -|r\nЛевой кнопкой: Показать по классам\nShift+левой кнопкой: Классовые цвета\nAlt+Левой кнопкой: Подсветить L/R\n|cff20d2ff- P button -|r\nЛевой кнопкой: Спрятать петов (да/нет)";
+
+end
diff --git a/localization.tw.lua b/localization.tw.lua
new file mode 100644
index 0000000..0549cf8
--- /dev/null
+++ b/localization.tw.lua
@@ -0,0 +1,210 @@
+-------------------------------------------------------------------------------
+-- Taiwan Localization
+-- Big thanks to:
+-- 血之谷-萬年卡奴
+-------------------------------------------------------------------------------
+if (GetLocale() == "zhTW") then
+
+-- smartbuff credits
+SMARTBUFF_CREDITS = "|cffffffff"
+ .."Classic 的 Shadowlands 版本。 请在 CurseForge 或我的 discord 上报告任何问题:\n\n"
+ .."|cff00e0ffhttps://discord.gg/R6EkZ94TKK\n\n"
+ .."|cffffffff如果您感谢所涉及的工作量以及为您带来这些各种插件所花费的时间,请考虑通过以下方式支持我:\n\n"
+ .."|cffffffffPatreon: |cff00e0ffhttps://www.patreon.com/codermik\n"
+ .."|cffffffffTwitch: |cff00e0ffhttps://www.twitch.tv/codermik\n"
+ .."|cffffffffPayPal.Me: |cff00e0ffhttps://paypal.me/codermik\n\n"
+;
+
+-- Weapon types
+SMARTBUFF_WEAPON_STANDARD = {"匕首", "斧", "劍", "錘", "法杖", "拳套", "長柄武器", "投擲武器"};
+SMARTBUFF_WEAPON_BLUNT = {"錘", "法杖", "拳套"};
+SMARTBUFF_WEAPON_BLUNT_PATTERN = "平衡石$";
+SMARTBUFF_WEAPON_SHARP = {"匕首", "斧", "劍", "長柄武器"};
+SMARTBUFF_WEAPON_SHARP_PATTERN = "磨刀石$";
+
+-- Creature types
+SMARTBUFF_HUMANOID = "人形生物";
+SMARTBUFF_DEMON = "惡魔";
+SMARTBUFF_BEAST = "野獸";
+SMARTBUFF_ELEMENTAL = "元素生物";
+SMARTBUFF_DEMONTYPE = "小鬼";
+SMARTBUFF_UNDEAD = "不死";
+
+-- Classes
+SMARTBUFF_CLASSES = {"德魯伊", "獵人", "法師", "聖騎士", "牧師", "盜賊", "薩滿", "術士", "戰士", "死亡騎士", "武僧", "恶魔猎手", "獵人寵物", "術士寵物", "死騎寵物", "坦克", "補師", "DD"};
+
+-- Templates and Instances
+SMARTBUFF_TEMPLATES = {"自我", "隊伍", "團隊", "戰場", "競技場", "ICC", "TOC", "Ulduar", "MC", "Ony", "BWL", "Naxx", "AQ", "ZG", "自定義 1", "自定義 2", "自定義 3", "自定義 4", "自定義 5"};
+SMARTBUFF_INSTANCES = {"冰冠城塞", "十字軍的試煉", "奧杜亞", "熔火之心", "奧妮克希亞的巢穴", "黑翼之巢", "納克薩瑪斯", "安其拉", "祖爾格拉布"};
+
+-- Mount
+SMARTBUFF_MOUNT = "速度提高(%d+)%%.";
+
+-- Abbreviations
+SMARTBUFF_ABBR_CHARGES_OL = "%d c";
+
+-- Bindings
+BINDING_NAME_SMARTBUFF_BIND_TRIGGER = "觸發";
+BINDING_NAME_SMARTBUFF_BIND_TARGET = "目標";
+BINDING_NAME_SMARTBUFF_BIND_OPTIONS = "選項視窗";
+BINDING_NAME_SMARTBUFF_BIND_RESETBUFFTIMERS = "重置 Buff 時間";
+
+-- Options Frame Text
+SMARTBUFF_OFT = "SmartBuff 開/關";
+SMARTBUFF_OFT_MENU = "選項視窗 顯示/隱藏";
+SMARTBUFF_OFT_AUTO = "啟用提示";
+SMARTBUFF_OFT_AUTOTIMER = "檢查週期";
+SMARTBUFF_OFT_AUTOCOMBAT = "戰鬥";
+SMARTBUFF_OFT_AUTOCHAT = "聊天";
+SMARTBUFF_OFT_AUTOSPLASH = "閃爍";
+SMARTBUFF_OFT_AUTOSOUND = "聲音";
+SMARTBUFF_OFT_AUTOREST = "城市內停用";
+SMARTBUFF_OFT_HUNTERPETS = "Buff獵人寵物";
+SMARTBUFF_OFT_WARLOCKPETS = "Buff術士寵物";
+SMARTBUFF_OFT_ARULES = "進階規則";
+SMARTBUFF_OFT_GRP = "監控團隊中小隊";
+SMARTBUFF_OFT_SUBGRPCHANGED = "開啟選項視窗";
+SMARTBUFF_OFT_BUFFS = "Buff項目";
+SMARTBUFF_OFT_TARGET = "Buff目標";
+SMARTBUFF_OFT_DONE = "確定";
+SMARTBUFF_OFT_APPLY = "套用";
+SMARTBUFF_OFT_GRPBUFFSIZE = "隊伍觸發人數";
+SMARTBUFF_OFT_CLASSBUFFSIZE = "職業觸發人數";
+SMARTBUFF_OFT_MESSAGES = "關閉訊息";
+SMARTBUFF_OFT_MSGNORMAL = "一般";
+SMARTBUFF_OFT_MSGWARNING = "警告";
+SMARTBUFF_OFT_MSGERROR = "錯誤";
+SMARTBUFF_OFT_HIDEMMBUTTON = "隱藏小地圖按鈕";
+SMARTBUFF_OFT_REBUFFTIMER = "重新buff計時器";
+SMARTBUFF_OFT_AUTOSWITCHTMP = "自動切換方案";
+SMARTBUFF_OFT_SELFFIRST = "自己優先";
+SMARTBUFF_OFT_SCROLLWHEELUP = "滑鼠滾輪向上";
+SMARTBUFF_OFT_SCROLLWHEELDOWN= "下";
+SMARTBUFF_OFT_TARGETSWITCH = "目標改變觸發";
+SMARTBUFF_OFT_BUFFTARGET = "Buff 目標";
+SMARTBUFF_OFT_BUFFPVP = "Buff PvP";
+SMARTBUFF_OFT_AUTOSWITCHTMPINST = "副本";
+SMARTBUFF_OFT_CHECKCHARGES = "次數檢查";
+SMARTBUFF_OFT_RBT = "重置計時器";
+SMARTBUFF_OFT_BUFFINCITIES = "在城市內buff";
+SMARTBUFF_OFT_UISYNC = "UI同步";
+SMARTBUFF_OFT_BLDURATION = "忽略";
+SMARTBUFF_OFT_COMPMODE = "相容模式";
+SMARTBUFF_OFT_MINIGRP = "小團隊";
+SMARTBUFF_OFT_ANTIDAZE = "防眩暈";
+SMARTBUFF_OFT_HIDESABUTTON = "隱藏動作按鈕";
+SMARTBUFF_OFT_INCOMBAT = "戰鬥中";
+SMARTBUFF_OFT_SMARTDEBUFF = "SmartDebuff";
+SMARTBUFF_OFT_INSHAPESHIFT = "變身型態下";
+SMARTBUFF_OFT_LINKGRPBUFFCHECK = "團隊buff檢查";
+SMARTBUFF_OFT_LINKSELFBUFFCHECK = "自我buff檢查";
+SMARTBUFF_OFT_RESETALL = "重置設定";
+SMARTBUFF_OFT_RESETLIST = "重置法術清單";
+SMARTBUFF_OFT_YES = "是";
+SMARTBUFF_OFT_NO = "否";
+SMARTBUFF_OFT_PURGE_DATA = "你確定要重置Smartbuff 所有的資料嗎? 這個動作將會重啟你的UI介面!";
+SMARTBUFF_OFT_SPLASHICON = "顯示圖示";
+SMARTBUFF_OFT_SPLASHMSGSHORT = "簡短訊息";
+
+
+-- Options Frame Tooltip Text
+SMARTBUFF_OFTT = "SmarBuff 開/關";
+SMARTBUFF_OFTT_AUTO = "Buff提示 開/關";
+SMARTBUFF_OFTT_AUTOTIMER = "Buff監視時間的間隔";
+SMARTBUFF_OFTT_AUTOCOMBAT = "戰鬥時保持監視";
+SMARTBUFF_OFTT_AUTOCHAT = "Buff消失訊息 - 聊天視窗訊息";
+SMARTBUFF_OFTT_AUTOSPLASH = "Buff消失訊息 - 螢幕中央閃爍訊息";
+SMARTBUFF_OFTT_AUTOSOUND = "Buff消失訊息 - 聲音提示";
+SMARTBUFF_OFTT_AUTOREST = "在主城內停用訊息提示";
+SMARTBUFF_OFTT_HUNTERPETS = "Buff獵人寵物";
+SMARTBUFF_OFTT_WARLOCKPETS = "Buff術士寵物,除了" .. SMARTBUFF_DEMONTYPE .. ".";
+SMARTBUFF_OFTT_ARULES = "設定以下情況不施法:\n法師、牧師和術士不施放荊棘術, \n無魔法職業不施放秘法智慧、神聖之靈.";
+SMARTBUFF_OFTT_SUBGRPCHANGED = "所在小隊變動後,自動開啟Smartbuff選項視窗.";
+SMARTBUFF_OFTT_GRPBUFFSIZE = "小隊補充群體buff的人數門檻.";
+SMARTBUFF_OFTT_HIDEMMBUTTON = "隱藏小地圖按鈕.";
+SMARTBUFF_OFTT_REBUFFTIMER = "Buff消失前多少秒,\n提示你重新施法.\n0 = 不提示";
+SMARTBUFF_OFTT_SELFFIRST = "優先對自己施放buff";
+SMARTBUFF_OFTT_SCROLLWHEELUP = "當滑鼠滾輪向前滾動時buff";
+SMARTBUFF_OFTT_SCROLLWHEELDOWN = "當滑鼠滾輪向後滾動時buff.";
+SMARTBUFF_OFTT_TARGETSWITCH = "當你改變目標時buff.";
+SMARTBUFF_OFTT_BUFFTARGET = "當目標為友好狀態時,優先buff該目標";
+SMARTBUFF_OFTT_BUFFPVP = "自身非PVP時,也buff PvP玩家";
+SMARTBUFF_OFTT_AUTOSWITCHTMP = "依團體狀態自動切換方案";
+SMARTBUFF_OFTT_AUTOSWITCHTMPINST = "切換副本時,自動切換方案";
+SMARTBUFF_OFTT_CHECKCHARGES = "當buff次數過低時警告.";
+SMARTBUFF_OFTT_BUFFINCITIES = "當你在城市內仍然buff.\n如果你在PvP狀態下,不論任何情況皆會buff";
+SMARTBUFF_OFTT_UISYNC = "啟動UI同步自身施放給其他玩家的buff剩餘時間.";
+SMARTBUFF_OFTT_BLDURATION = "忽略玩家秒數\n0 = 停用";
+SMARTBUFF_OFTT_COMPMODE = "相容模式\n警示!!!\n除非無法buff自己,否則不勾選";
+SMARTBUFF_OFTT_MINIGRP = "以獨立可移動小視窗顯示Raid各小隊設定.";
+SMARTBUFF_OFTT_ANTIDAZE = "若小隊中有人眩暈,\n自動取消獵豹/豹群守護";
+SMARTBUFF_OFTT_SPLASHSTYLE = "更換 buff 訊息字型.";
+SMARTBUFF_OFTT_HIDESABUTTON = "隱藏SmartBuff動作按鈕.";
+SMARTBUFF_OFTT_INCOMBAT = "只對自己作用.\n被勾選為'戰鬥中'的第一個buff會在戰鬥前被設定在按鈕上,\n並能在戰鬥中使用.\n注意: 戰鬥中禁用邏輯判斷.";
+SMARTBUFF_OFTT_SMARTDEBUFF = "顯示SmartDebuff視窗.";
+SMARTBUFF_OFTT_SPLASHDURATION= "閃爍訊息持續秒數.";
+SMARTBUFF_OFTT_INSHAPESHIFT = "在變身型態下是否也施放buff.";
+SMARTBUFF_OFTT_LINKGRPBUFFCHECK = "檢查其他職業\n是否已經施放\n相同類型的buff.";
+SMARTBUFF_OFTT_LINKSELFBUFFCHECK = "檢查自己身上\n是否有只能\n單一存在的Buff.";
+
+-- Buffsetup Frame Text
+SMARTBUFF_BST_SELFONLY = "僅對自己施法";
+SMARTBUFF_BST_SELFNOT = "不對自己施法";
+SMARTBUFF_BST_COMBATIN = "戰鬥狀態觸發";
+SMARTBUFF_BST_COMBATOUT = "非戰鬥狀態觸發";
+SMARTBUFF_BST_MAINHAND = "主手";
+SMARTBUFF_BST_OFFHAND = "副手";
+SMARTBUFF_BST_RANGED = "投擲";
+SMARTBUFF_BST_REMINDER = "通知";
+SMARTBUFF_BST_MANALIMIT = "力能底線";--力能是技能施放來源,如怒氣、能量、法力
+
+-- Buffsetup Frame Tooltip Text
+SMARTBUFF_BSTT_SELFONLY = "僅對自己施法,不對其他隊友施法.";
+SMARTBUFF_BSTT_SELFNOT = "除了自己,buff所有勾選職業.";
+SMARTBUFF_BSTT_COMBATIN = "在戰鬥狀態時保持自動觸發技能.";
+SMARTBUFF_BSTT_COMBATOUT = "在非戰鬥狀態時保持自動觸發技能.";
+SMARTBUFF_BSTT_MAINHAND = "Buff主手.";
+SMARTBUFF_BSTT_OFFHAND = "Buff副手.";
+SMARTBUFF_BSTT_RANGED = "Buff遠程武器";
+SMARTBUFF_BSTT_REMINDER = "顯示提示訊息.";
+SMARTBUFF_BSTT_REBUFFTIMER = "Buff消失前多少秒,\n發出警告訊息.0 = 不提示";
+SMARTBUFF_BSTT_MANALIMIT = "設定魔法/怒氣/能量保留門檻.";
+
+-- Playersetup Frame Tooltip Text
+SMARTBUFF_PSTT_RESIZE = "最小化/最大化 設定視窗";
+
+-- Messages
+SMARTBUFF_MSG_LOADED = "已載入";
+SMARTBUFF_MSG_NEWVER1 = "|cff00e0ffSmartbuff : |cffffffff 有一个新的版本可用,你目前使用的版本是 |cffFFFF00";
+SMARTBUFF_MSG_NEWVER2 = "|cffffffff 和修订 |cffFFFF00r"
+SMARTBUFF_MSG_NEWVER3 = "|cffffffff 目前可供下载。 加入Discord,了解所有最新信息 https://discord.gg/R6EkZ94TKK.";
+SMARTBUFF_MSG_DISABLED = "SmarBuff已停用!";
+SMARTBUFF_MSG_SUBGROUP = "你已經加入一個新的小隊,請檢查你的設定!";
+SMARTBUFF_MSG_NOTHINGTODO = "不需執行任何指令";
+SMARTBUFF_MSG_BUFFED = "已施放";
+SMARTBUFF_MSG_OOR = "不在施法範圍內!";
+--SMARTBUFF_MSG_CD = "冷卻中!";
+SMARTBUFF_MSG_CD = "公共CD時間已到!";
+SMARTBUFF_MSG_CHAT = "沒有發現任何聊天視窗!";
+SMARTBUFF_MSG_SHAPESHIFT = "變身形態不能施法!";
+SMARTBUFF_MSG_NOACTIONSLOT = "需要動作條按鈕才能正常運作!";
+SMARTBUFF_MSG_GROUP = "隊伍";
+SMARTBUFF_MSG_NEEDS = "需要加buff:";
+SMARTBUFF_MSG_OOM = "沒有足夠的魔法/怒氣/能量!";
+SMARTBUFF_MSG_STOCK = "目前庫存的";
+SMARTBUFF_MSG_NOREAGENT = "沒有施法材料:";
+SMARTBUFF_MSG_DEACTIVATED = "停用!";
+SMARTBUFF_MSG_REBUFF = "Rebuff:";
+SMARTBUFF_MSG_LEFT = "剩餘";
+SMARTBUFF_MSG_CLASS = "職業";
+SMARTBUFF_MSG_CHARGES = "次";
+SMARTBUFF_MSG_SPECCHANGED = "天賦已更改(%s), 重設buff模組...";
+
+-- Support
+SMARTBUFF_MINIMAP_TT = "左鍵: 選項視窗\n右鍵: 開/關\nAlt-左鍵: SmartDebuff\nShift拖曳: 移動按鈕";
+SMARTBUFF_TITAN_TT = "左鍵: 開啟選項\n右鍵: 開/關\nAlt-左鍵: SmartDebuff";
+SMARTBUFF_FUBAR_TT = "\n左鍵: 開啟選項\nShift-左鍵: 開/關\nAlt-左鍵: SmartDebuff";
+
+SMARTBUFF_DEBUFF_TT = "Shift-左鍵拖曳: 移動視窗\n|cff20d2ff- S 按鈕 -|r\n左鍵: 依職業顯示\nShift-左鍵: 職業顏色\nAlt-左鍵: 高亮度 L/R\n|cff20d2ff- P 按鈕 -|r\n左鍵: 隱藏寵物 開/關";
+
+end
\ No newline at end of file