forked from Bastion/Bastion
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
400 lines
17 KiB
400 lines
17 KiB
local Tinkr, Bastion = ...
|
|
|
|
local FeralModule = Bastion.Module:New('feral')
|
|
local Evaluator = Tinkr.Util.Evaluator
|
|
local Player = Bastion.UnitManager:Get('player')
|
|
local None = Bastion.UnitManager:Get('none')
|
|
local Target = Bastion.UnitManager:Get('target')
|
|
|
|
local myconf = Tinkr.Util.Config:New('feral_druid') -- for saving variables
|
|
|
|
-- Spellbook spells
|
|
local Shadowmeld = Bastion.SpellBook:GetSpell(58984)
|
|
local Barkskin = Bastion.SpellBook:GetSpell(22812)
|
|
local BearForm = Bastion.SpellBook:GetSpell(5487)
|
|
--local Berserk = Bastion.SpellBook:GetSpell(50334)
|
|
local CatForm = Bastion.SpellBook:GetSpell(768)
|
|
local Dash = Bastion.SpellBook:GetSpell(1850)
|
|
local EntanglingRoots = Bastion.SpellBook:GetSpell(339)
|
|
local FeralFrenzy = Bastion.SpellBook:GetSpell(274837)
|
|
local FerociousBite = Bastion.SpellBook:GetSpell(22568)
|
|
--local FrenziedRegeneration = Bastion.SpellBook:GetSpell(22842)
|
|
local Growl = Bastion.SpellBook:GetSpell(6795)
|
|
--local Ironfur = Bastion.SpellBook:GetSpell(192081)
|
|
local Mangle = Bastion.SpellBook:GetSpell(33917)
|
|
local MarkoftheWild = Bastion.SpellBook:GetSpell(1126)
|
|
local Moonfire = Bastion.SpellBook:GetSpell(8921)
|
|
local MoonfireDebuff = Bastion.SpellBook:GetSpell(164812)
|
|
local PredatorySwiftness = Bastion.SpellBook:GetSpell(69369)
|
|
local PrimalWrath = Bastion.SpellBook:GetSpell(285381)
|
|
local Prowl = Bastion.SpellBook:GetSpell(5215)
|
|
local Rake = Bastion.SpellBook:GetSpell(1822)
|
|
local RakeDebuff = Bastion.SpellBook:GetSpell(155722)
|
|
local Regrowth = Bastion.SpellBook:GetSpell(8936)
|
|
local Revive = Bastion.SpellBook:GetSpell(50769)
|
|
local Rip = Bastion.SpellBook:GetSpell(1079)
|
|
local Shred = Bastion.SpellBook:GetSpell(5221)
|
|
local SkullBash = Bastion.SpellBook:GetSpell(106839)
|
|
--local Thrash = Bastion.SpellBook:GetSpell(106830)
|
|
local Thrash = Bastion.SpellBook:GetSpell(106832)
|
|
local ThrashDebuff = Bastion.SpellBook:GetSpell(106830)
|
|
local TigersFury = Bastion.SpellBook:GetSpell(5217)
|
|
local TravelForm = Bastion.SpellBook:GetSpell(783)
|
|
local Wrath = Bastion.SpellBook:GetSpell(5176)
|
|
--local Maul = Bastion.SpellBook:GetSpell(6807)
|
|
--local SurvivalInstincts = Bastion.SpellBook:GetSpell(61336)
|
|
--local Swipe = Bastion.SpellBook:GetSpell(106785)
|
|
local Swipe = Bastion.SpellBook:GetSpell(213764)
|
|
local BrutalSlash = Bastion.SpellBook:GetSpell(202028)
|
|
local ApexPredator = Bastion.SpellBook:GetSpell(391882)
|
|
local Incarnation = Bastion.SpellBook:GetSpell(102543)
|
|
|
|
-- Define Units
|
|
local InterruptTarget = Bastion.UnitManager:CreateCustomUnit('skullbash', function(unit)
|
|
local interrupt = nil
|
|
Bastion.UnitManager:EnumEnemies(function(unit)
|
|
if unit:IsDead() then return false end
|
|
if not Player:CanSee(unit) then return false end
|
|
if Player:GetDistance(unit) > 40 then return false end
|
|
if Player:InMelee(unit) and unit:IsInterruptible(5) and Player:IsFacing(unit) then
|
|
interrupt = unit
|
|
return true
|
|
end
|
|
end)
|
|
if interrupt == nil then
|
|
interrupt = None
|
|
end
|
|
return interrupt
|
|
end)
|
|
|
|
local Tank = Bastion.UnitManager:CreateCustomUnit('tank', function(unit)
|
|
local tank = nil
|
|
Bastion.UnitManager:EnumFriends(function(unit)
|
|
if Player:GetDistance(unit) > 40 then return false end
|
|
if not Player:CanSee(unit) then return false end
|
|
if unit:IsDead() then return false end
|
|
if unit:IsTank() then
|
|
tank = unit
|
|
return true
|
|
end
|
|
return false
|
|
end)
|
|
if tank == nil then
|
|
tank = None
|
|
end
|
|
return tank
|
|
end)
|
|
|
|
local Explosive = Bastion.UnitManager:CreateCustomUnit('explosive', function(unit)
|
|
local explosive = nil
|
|
Bastion.UnitManager:EnumEnemies(function(unit)
|
|
if unit:IsDead() then return false end
|
|
if not Player:CanSee(unit) then return false end
|
|
if Player:GetDistance(unit) > 40 then return false end
|
|
if Player:InMelee(unit) and unit:GetID() == 120651 and Player:IsFacing(unit) then
|
|
explosive = unit
|
|
return true
|
|
end
|
|
end)
|
|
if explosive == nil then
|
|
explosive = None
|
|
end
|
|
return explosive
|
|
end)
|
|
|
|
-- Rotation code here
|
|
local function Buffs()
|
|
-- Mark of the Wild
|
|
local motw = myconf:Read('motw')
|
|
MarkoftheWild:Condition('Mark of the Wild', function()
|
|
return motw and MarkoftheWild:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(MarkoftheWild):IsUp()
|
|
and not Player:IsMounted()
|
|
end)
|
|
MarkoftheWild:Cast(Player, 'Mark of the Wild')
|
|
end
|
|
|
|
local function DruidProwl()
|
|
-- Prowl
|
|
Prowl:Condition('Prowl', function()
|
|
return Prowl:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(Prowl):IsUp()
|
|
and Player:GetDistance(Target) <= 25 and not Player:IsMounted() and Target:IsHostile() and not Target:IsDead()
|
|
end)
|
|
Prowl:Cast(Player, 'Prowl')
|
|
end
|
|
|
|
local function Opener()
|
|
-- Rake
|
|
Rake:Condition('Rake', function()
|
|
return Rake:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:InMelee(Target)
|
|
and not Target:GetAuras():FindMy(RakeDebuff):IsUp() and Target:Exists() and Target:IsHostile() and not Target:IsDead()
|
|
end)
|
|
Rake:Cast(Target, 'Rake')
|
|
end
|
|
|
|
local function Interrupt()
|
|
-- Skull Bash
|
|
SkullBash:Condition('SkullBash', function()
|
|
return SkullBash:IsKnownAndUsable() and InterruptTarget:Exists() and not Player:IsCastingOrChanneling()
|
|
end)
|
|
C_Timer.After(1.5, function()
|
|
SkullBash:Cast(Target, 'SkullBash')
|
|
end)
|
|
end
|
|
|
|
local function Damage()
|
|
-- Cat Form
|
|
CatForm:Condition('Cat Form', function()
|
|
return CatForm:IsKnownAndUsable() and not Player:GetAuras():FindMy(CatForm):IsUp()
|
|
end)
|
|
CatForm:Cast(Player, 'Cat Form')
|
|
-- Healing with Predatory Swiftness
|
|
Regrowth:Condition('Regrowth', function()
|
|
return Regrowth:IsKnownAndUsable() and Player:GetAuras():FindMy(PredatorySwiftness):IsUp()
|
|
end)
|
|
Regrowth:Cast(Player, 'Regrowth')
|
|
-- Cooldowns
|
|
-- Tiger's Fury
|
|
TigersFury:Condition('Tigers Fury', function()
|
|
return TigersFury:IsKnownAndUsable() and not Player:GetAuras():FindMy(TigersFury):IsUp()
|
|
end)
|
|
TigersFury:Cast(Player, 'Tigers Fury')
|
|
-- Feral Frenzy on cooldown and when combo points are zero
|
|
FeralFrenzy:Condition('Feral Frenzy', function()
|
|
return FeralFrenzy:IsKnownAndUsable() and Player:GetComboPoints(Target) == 0
|
|
end)
|
|
FeralFrenzy:Cast(Player, 'Feral Frenzy')
|
|
-- Incarnation: Avatar of Ashamane
|
|
Incarnation:Condition('Incarnation', function()
|
|
return Incarnation:IsKnownAndUsable()
|
|
end)
|
|
Incarnation:Cast(Player, 'Incarnation')
|
|
|
|
-- Multi Target Rotation
|
|
if Player:GetEnemies(8) >= 2 then
|
|
-- Primal Wrath at 5 combo points
|
|
PrimalWrath:Condition('Primal Wrath', function()
|
|
return PrimalWrath:IsKnownAndUsable() and Player:InMelee(Target) and Player:GetComboPoints(Target) >= 5
|
|
and (not Target:GetAuras():FindMy(Rip):IsUp() or Target:GetAuras():FindMy(Rip):GetRemainingTime() <= 7)
|
|
end)
|
|
PrimalWrath:Cast(Target, 'Primal Wrath')
|
|
-- Spend Apex Predator Procs on Ferocious Bite
|
|
FerociousBite:Condition('Ferocious Bite Apex Predator', function()
|
|
return FerociousBite:IsKnownAndUsable() and Player:InMelee(Target) and Player:GetAuras():FindMy(ApexPredator):IsUp()
|
|
end)
|
|
FerociousBite:Cast(Target, 'Ferocious Bite Apex Predator')
|
|
-- Maintain Rake
|
|
Rake:Condition('Maintain Rake', function()
|
|
return Rake:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:InMelee(Target)
|
|
and Target:GetAuras():FindMy(RakeDebuff):GetRemainingTime() <= 4
|
|
end)
|
|
Rake:Cast(Target, 'Maintain Rake')
|
|
-- Cast Thrash if its not up
|
|
Thrash:Condition('Thrash', function()
|
|
return Thrash:IsKnownAndUsable() and not Target:GetAuras():FindMy(ThrashDebuff):IsUp() and Player:InMelee(Target)
|
|
end)
|
|
Thrash:Cast(Target, 'Thrash')
|
|
-- Avoid capping Brutal Slash charges
|
|
BrutalSlash:Condition('Brutal Slash', function()
|
|
return BrutalSlash:IsKnownAndUsable() and Player:InMelee(Target)
|
|
end)
|
|
BrutalSlash:Cast(Target, 'Brutal Slash')
|
|
-- Shred to generate combo points
|
|
Shred:Condition('Shred', function()
|
|
return Shred:IsKnownAndUsable() and Player:InMelee(Target)
|
|
end)
|
|
Shred:Cast(Target, 'Shred')
|
|
end
|
|
|
|
-- Single Target Rotation
|
|
if Player:GetEnemies(8) == 1 then
|
|
-- Maintain Rip - you'll want to cast this at 5 combo points
|
|
Rip:Condition('Rip', function()
|
|
return Rip:IsKnownAndUsable() and Player:InMelee(Target) and Player:GetComboPoints(Target) >= 5
|
|
and (not Target:GetAuras():FindMy(Rip):IsUp() or Target:GetAuras():FindMy(Rip):GetRemainingTime() <= 7)
|
|
end)
|
|
Rip:Cast(Target, 'Rip')
|
|
-- Spend Apex Predator Procs on Ferocious Bite
|
|
FerociousBite:Condition('Ferocious Bite Apex Predator', function()
|
|
return FerociousBite:IsKnownAndUsable() and Player:InMelee(Target) and Player:GetAuras():FindMy(ApexPredator):IsUp()
|
|
end)
|
|
FerociousBite:Cast(Target, 'Ferocious Bite Apex Predator')
|
|
-- If you have 5 combo points and Rip is not in Pandemic then cast Ferocious Bite
|
|
FerociousBite:Condition('Ferocious Bite', function()
|
|
return FerociousBite:IsKnownAndUsable() and Player:InMelee(Target) and Player:GetComboPoints(Target) >= 5
|
|
end)
|
|
FerociousBite:Cast(Target, 'Ferocious Bite')
|
|
-- Maintain Rake
|
|
Rake:Condition('Maintain Rake', function()
|
|
return Rake:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:InMelee(Target)
|
|
and Target:GetAuras():FindMy(RakeDebuff):GetRemainingTime() <= 4
|
|
end)
|
|
Rake:Cast(Target, 'Maintain Rake')
|
|
-- Avoid capping Brutal Slash charges
|
|
BrutalSlash:Condition('Brutal Slash', function()
|
|
return BrutalSlash:IsKnownAndUsable() and Player:InMelee(Target)
|
|
end)
|
|
BrutalSlash:Cast(Target, 'Brutal Slash')
|
|
-- Cast Thrash if its not up
|
|
Thrash:Condition('Thrash', function()
|
|
return Thrash:IsKnownAndUsable() and not Target:GetAuras():FindMy(ThrashDebuff):IsUp() and Player:InMelee(Target)
|
|
end)
|
|
Thrash:Cast(Target, 'Thrash')
|
|
-- Shred to generate combo points
|
|
Shred:Condition('Shred', function()
|
|
return Shred:IsKnownAndUsable() and Player:InMelee(Target)
|
|
end)
|
|
Shred:Cast(Target, 'Shred')
|
|
end
|
|
end
|
|
|
|
-- Module that dictates workflow
|
|
FeralModule:Sync(function()
|
|
if not Player:IsAffectingCombat() then
|
|
if Buffs() then return end
|
|
if DruidProwl() then return end
|
|
if Opener() then return end
|
|
end
|
|
if Player:IsAffectingCombat() and Target:Exists() and Target:IsHostile() and not Target:IsDead() then
|
|
if Interrupt() then return end
|
|
if Damage() then return end
|
|
end
|
|
end)
|
|
Bastion:Register(FeralModule)
|
|
|
|
local tab1 =
|
|
{
|
|
layoutConfig = { padding = { top = 40 } },
|
|
rows = {
|
|
[1] = { shadpr = { type = 'label', label = 'Open Combat' } },
|
|
|
|
[2] = { opener = { type = 'dropdown', label = 'Opener', column = 6, order = 1,
|
|
options = {
|
|
{ text = 'Moonfire', value = 'moonfire'},
|
|
{ text = 'None', value = 'none'},
|
|
},
|
|
initialValue = myconf:Read('opener', 'moonfire'),
|
|
onValueChanged = function(_, value) myconf:Write('opener', value) end }, },
|
|
|
|
[3] = { shadpr = { type = 'label', label = 'Buffs' } },
|
|
|
|
[4] = { motw = { type = 'checkbox', label = 'Mark of the Wild', column = 12, order = 1,
|
|
initialValue = myconf:Read('motw', false),
|
|
onValueChanged = function(_, flag) myconf:Write('motw', flag) end }, },
|
|
|
|
[5] = { shadpr = { type = 'label', label = 'Defensives' } },
|
|
|
|
[6] = { shield1 = { type = 'checkbox', label = 'Ironfur', column = 6, order = 1,
|
|
initialValue = myconf:Read('ironfur', false),
|
|
onValueChanged = function(_, flag) myconf:Write('ironfur', flag) end },
|
|
|
|
shield2 = { type = 'slider', label = 'Player Health', column = 6, order = 2,
|
|
min = 1, max = 100, precision = 0,
|
|
initialValue = myconf:Read('ironfurpercent', 35),
|
|
onValueChanged = function(_, value) myconf:Write('ironfurpercent', value) end }, },
|
|
|
|
[7] = { dispersion1 = { type = 'checkbox', label = 'Frenzied Regeneration', column = 6, order = 1,
|
|
initialValue = myconf:Read('fregen', false),
|
|
onValueChanged = function(_, flag) myconf:Write('fregen', flag) end },
|
|
|
|
dispersion2 = { type = 'slider', label = 'Player Health', column = 6, order = 2,
|
|
min = 1, max = 100, precision = 0,
|
|
initialValue = myconf:Read('fregenpercent', 35),
|
|
onValueChanged = function(_, value) myconf:Write('fregenpercent', value) end }, },
|
|
|
|
[8] = { shadpr = { type = 'label', label = 'Interrupts' } },
|
|
|
|
[9] = { silence = { type = 'checkbox', label = 'Skull Bash on CD', column = 12, order = 1,
|
|
initialValue = myconf:Read('skullbash', false),
|
|
onValueChanged = function(_, flag) myconf:Write('skullbash', flag) end }, },
|
|
|
|
[10] = { shadpr = { type = 'header', label = 'Purify Disease' } },
|
|
|
|
[11] = { incombat = { type = 'checkbox', label = 'In Combat', column = 6, order = 1,
|
|
initialValue = myconf:Read('purifyic', false),
|
|
onValueChanged = function(_, flag) myconf:Write('purifyic', flag) end },
|
|
|
|
outcombat = { type = 'checkbox', label = 'Out of Combat', column = 6, order = 2,
|
|
initialValue = myconf:Read('purifyooc', false),
|
|
onValueChanged = function(_, flag) myconf:Write('purifyooc', flag) end }, },
|
|
|
|
[12] = { shadpr = { type = 'header', label = 'Dispel Magic' } },
|
|
|
|
[13] = { incombat = { type = 'checkbox', label = 'In Combat', column = 12, order = 1,
|
|
initialValue = myconf:Read('dispelic', false),
|
|
onValueChanged = function(_, flag) myconf:Write('dispelic', flag) end }, },
|
|
|
|
[14] = { shadpr = { type = 'header', label = 'Dispel Delay Time' } },
|
|
|
|
[15] = { delay = { type = 'slider', label = 'In seconds', column = 6, order = 1,
|
|
min = 0.5, max = 2, precision = 1,
|
|
initialValue = myconf:Read('dispeldelay', 1),
|
|
onValueChanged = function(_, value) myconf:Write('dispeldelay', value) end }, },
|
|
|
|
},
|
|
}
|
|
|
|
local tab2 =
|
|
{
|
|
layoutConfig = { padding = { top = 40 } },
|
|
rows = {
|
|
[1] = { shadpr = { type = 'header', label = 'Player Healing' } },
|
|
|
|
[2] = { incombat = { type = 'checkbox', label = 'In Combat Healing', column = 6, order = 1,
|
|
initialValue = myconf:Read('playericheal', false),
|
|
onValueChanged = function(_, flag) myconf:Write('playericheal', flag) end },
|
|
|
|
outcombat = { type = 'checkbox', label = 'Out of Combat Healing', column = 6, order = 2,
|
|
initialValue = myconf:Read('playeroocheal', false),
|
|
onValueChanged = function(_, flag) myconf:Write('playeroocheal', flag) end }, },
|
|
|
|
[3] = { shadowmend1 = { type = 'checkbox', label = 'Shadow Mend', column = 6, order = 1,
|
|
initialValue = myconf:Read('shadowmend', false),
|
|
onValueChanged = function(_, flag) myconf:Write('shadowmend', flag) end },
|
|
|
|
shadowmend2 = { type = 'slider', label = 'Player Health', column = 6, order = 2,
|
|
min = 1, max = 100, precision = 0,
|
|
initialValue = myconf:Read('shadowmendpercent', 35),
|
|
onValueChanged = function(_, value) myconf:Write('shadowmendpercent', value) end }, },
|
|
|
|
},
|
|
}
|
|
|
|
local feralconfig = {
|
|
layoutConfig = { padding = { top = 30 } },
|
|
rows = {
|
|
[1] = {
|
|
container = {
|
|
type = 'tab',
|
|
fullSize = true,
|
|
tabs = {
|
|
{
|
|
name = 'player',
|
|
title = 'Player Settings',
|
|
layout = tab1
|
|
},
|
|
{
|
|
name = 'group',
|
|
title = 'Placeholder',
|
|
layout = tab2
|
|
}
|
|
},
|
|
}
|
|
},
|
|
},
|
|
}
|
|
Bastion.settingstemplate(feralconfig, 'Feral Druid', 400, 600, 1.00, 0.49, 0.04) -- config, Title of Settings Frame, Width, Height, ClassRGB
|
|
|
|
-- Class colours
|
|
-- Death Knight 0.77 0.12 0.23 Red
|
|
-- Demon Hunter 0.64 0.19 0.79 Dark Magenta
|
|
-- Druid 1.00 0.49 0.04 Orange
|
|
-- Evoker 0.20 0.58 0.50 Dark Emerald
|
|
-- Hunter 0.67 0.83 0.45 Green
|
|
-- Mage 0.25 0.78 0.92 Light Blue
|
|
-- Monk 0.00 1.00 0.60 Spring Green
|
|
-- Paladin 0.96 0.55 0.73 Pink
|
|
-- Priest 1.00 1.00 1.00 White
|
|
-- Rogue 1.00 0.96 0.41 Yellow
|
|
-- Shaman 0.00 0.44 0.87 Blue
|
|
-- Warlock 0.53 0.53 0.93 Purple
|
|
-- Warrior 0.78 0.61 0.43 Tan |