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.
442 lines
17 KiB
442 lines
17 KiB
local Tinkr, Bastion = ...
|
|
|
|
local ShadowModule = Bastion.Module:New('shadow')
|
|
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('shadow_priest') -- for saving variables
|
|
|
|
local ArcaneTorrent = Bastion.SpellBook:GetSpell(232633)
|
|
local AutoAttack = Bastion.SpellBook:GetSpell(6603)
|
|
local AngelicFeather = Bastion.SpellBook:GetSpell(121536)
|
|
local DesperatePrayer = Bastion.SpellBook:GetSpell(19236)
|
|
local DispelMagic = Bastion.SpellBook:GetSpell(528)
|
|
local DominateMind = Bastion.SpellBook:GetSpell(205364)
|
|
local Fade = Bastion.SpellBook:GetSpell(586)
|
|
local FlashHeal = Bastion.SpellBook:GetSpell(2061)
|
|
local LeapofFaith = Bastion.SpellBook:GetSpell(73325)
|
|
local Levitate = Bastion.SpellBook:GetSpell(1706)
|
|
local MassDispel = Bastion.SpellBook:GetSpell(32375)
|
|
local MindBlast = Bastion.SpellBook:GetSpell(8092)
|
|
local MindSoothe = Bastion.SpellBook:GetSpell(453)
|
|
local MindVision = Bastion.SpellBook:GetSpell(2096)
|
|
local Mindgames = Bastion.SpellBook:GetSpell(375901)
|
|
local PowerInfusion = Bastion.SpellBook:GetSpell(10060)
|
|
local PowerWordFortitude = Bastion.SpellBook:GetSpell(21562)
|
|
local PowerWordShield = Bastion.SpellBook:GetSpell(17)
|
|
local PsychicScream = Bastion.SpellBook:GetSpell(8122)
|
|
local Resurrection = Bastion.SpellBook:GetSpell(2006)
|
|
local ShadowWordDeath = Bastion.SpellBook:GetSpell(32379)
|
|
local ShadowWordPain = Bastion.SpellBook:GetSpell(589)
|
|
local VampiricEmbrace = Bastion.SpellBook:GetSpell(15286)
|
|
local DarkAscension = Bastion.SpellBook:GetSpell(391109)
|
|
local DevouringPlague = Bastion.SpellBook:GetSpell(335467)
|
|
local Dispersion = Bastion.SpellBook:GetSpell(47585)
|
|
local Halo = Bastion.SpellBook:GetSpell(120644)
|
|
local MindFlay = Bastion.SpellBook:GetSpell(15407)
|
|
local MindFlayInsanity = Bastion.SpellBook:GetSpell(391399)
|
|
local MindSear = Bastion.SpellBook:GetSpell(48045)
|
|
local MindSpike = Bastion.SpellBook:GetSpell(73510)
|
|
local Mindbender = Bastion.SpellBook:GetSpell(200174)
|
|
local ShadowCrash = Bastion.SpellBook:GetSpell(205385)
|
|
local Shadowform = Bastion.SpellBook:GetSpell(232698)
|
|
local Silence = Bastion.SpellBook:GetSpell(15487)
|
|
local SurgeofDarkness = Bastion.SpellBook:GetSpell(87160)
|
|
local VampiricTouch = Bastion.SpellBook:GetSpell(34914)
|
|
local VoidTorrent = Bastion.SpellBook:GetSpell(263165)
|
|
|
|
local function checktotem(totemname)
|
|
for index = 1, MAX_TOTEMS do
|
|
local haveTotem, totemName, startTime, duration, icon = GetTotemInfo(index)
|
|
if not totemName then return false end
|
|
if string.find(totemName, totemname) then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local InterruptTarget = Bastion.UnitManager:CreateCustomUnit('silence', 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)
|
|
|
|
local RestingAPL = Bastion.APL:New('resting')
|
|
local OpenerAPL = Bastion.APL:New('opener')
|
|
local STAPL = Bastion.APL:New('st')
|
|
local AOEAPL = Bastion.APL:New('aoe')
|
|
local DefensivesAPL = Bastion.APL:New('defensives')
|
|
local UtilityAPL = Bastion.APL:New('utility')
|
|
|
|
-- Resting - Out of Combat Actions
|
|
local usepwf = myconf:Read('pwf')
|
|
local useshadowform = myconf:Read('shadowform')
|
|
RestingAPL:AddSpell(
|
|
PowerWordFortitude:CastableIf(function(self)
|
|
return usepwf and self:IsKnownAndUsable() and
|
|
not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(PowerWordFortitude):IsUp() and not IsMounted()
|
|
end):SetTarget(Player)
|
|
)
|
|
RestingAPL:AddSpell(
|
|
Shadowform:CastableIf(function(self)
|
|
return useshadowform and self:IsKnownAndUsable() and
|
|
not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(Shadowform):IsUp() and not IsMounted()
|
|
end):SetTarget(Player)
|
|
)
|
|
|
|
-- Opener spells
|
|
local opener = myconf:Read('opener')
|
|
OpenerAPL:AddSpell(
|
|
ShadowCrash:CastableIf(function(self)
|
|
return opener == 'crash' and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
end):SetTarget(None):OnCast(function(self)
|
|
local loc = Target:GetPosition()
|
|
self:Click(loc)
|
|
end)
|
|
)
|
|
OpenerAPL:AddSpell(
|
|
ShadowWordPain:CastableIf(function(self)
|
|
return opener == 'swp' and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Target:GetAuras():FindMy(ShadowWordPain):IsUp()
|
|
end):SetTarget(Target)
|
|
)
|
|
|
|
-- Defensive spells
|
|
-- Power Word: Shield
|
|
local pws = myconf:Read('pws')
|
|
local pwspercent = myconf:Read('pwspercent')
|
|
DefensivesAPL:AddSpell(
|
|
PowerWordShield:CastableIf(function(self)
|
|
return pws and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(PowerWordShield):IsUp()
|
|
and Player:GetHP() <= pwspercent
|
|
end):SetTarget(Player)
|
|
)
|
|
-- Dispersion
|
|
local dispersion = myconf:Read('dispersion')
|
|
local dispersionpercent = myconf:Read('dispersionpercent')
|
|
DefensivesAPL:AddSpell(
|
|
Dispersion:CastableIf(function(self)
|
|
return dispersion and self:IsKnownAndUsable() and Player:GetHP() <= dispersionpercent
|
|
end):SetTarget(Player)
|
|
)
|
|
|
|
-- Utility spells
|
|
-- Interrupt with Silence
|
|
local silence = myconf:Read('silence')
|
|
UtilityAPL:AddSpell(
|
|
Silence:CastableIf(function(self)
|
|
return silence and InterruptTarget:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
end):SetTarget(InterruptTarget)
|
|
)
|
|
|
|
-- Single Target Action Priority List
|
|
-- Make sure your target has both Shadow Word: Pain and Vampiric Touch active. Prioritise Shadow Crash over Vampiric Touch for this.
|
|
STAPL:AddSpell(
|
|
ShadowWordPain:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Target:GetAuras():FindMy(ShadowWordPain):IsUp()
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Mindbender on cooldown
|
|
STAPL:AddSpell(
|
|
Mindbender:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Dark Ascension on cooldown
|
|
STAPL:AddSpell(
|
|
DarkAscension:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
end):SetTarget(Player)
|
|
)
|
|
-- Cast Power Infusion if Dark Ascension is active
|
|
STAPL:AddSpell(
|
|
PowerInfusion:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:GetAuras():FindMy(DarkAscension):IsUp()
|
|
end):SetTarget(Player)
|
|
)
|
|
-- Use offensive trinkets and potions.
|
|
-- Cast Mind Blast if you have two charges
|
|
STAPL:AddSpell(
|
|
MindBlast:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and MindBlast:GetCharges() == 2
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Shadow Word: Death if Mindbender is active
|
|
STAPL:AddSpell(
|
|
ShadowWordDeath:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and checktotem("Mindbender")
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Mind Sear to avoid over capping Insanity, consider holding it small amounts of time for mobs to group up. 3+ targets
|
|
STAPL:AddSpell(
|
|
MindSear:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Target:GetEnemies(10) >= 3
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Devouring Plague if you're close to capping Insanity or the debuff will expire
|
|
STAPL:AddSpell(
|
|
DevouringPlague:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:GetPower(Enum.PowerType.Insanity) >= 80
|
|
and Target:GetEnemies(10) <= 2
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Vampiric Touch if you are within pandemic range to maintain uptime
|
|
STAPL:AddSpell(
|
|
VampiricTouch:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
and (not Target:GetAuras():FindMy(VampiricTouch):IsUp() or Target:GetAuras():FindMy(VampiricTouch):GetRemainingTime() <= 6.3)
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Shadow Word: Death if the target is below 20% hp
|
|
STAPL:AddSpell(
|
|
ShadowWordDeath:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Target:GetHealthPercent() <= 20
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Mind Blast
|
|
STAPL:AddSpell(
|
|
MindBlast:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Mindgames
|
|
STAPL:AddSpell(
|
|
Mindgames:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Shadow Crash, even if your DoTs are not close to expiring
|
|
STAPL:AddSpell(
|
|
ShadowCrash:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
end):SetTarget(None):OnCast(function(self)
|
|
local loc = Target:GetPosition()
|
|
self:Click(loc)
|
|
end)
|
|
)
|
|
-- Cast Void Torrent
|
|
STAPL:AddSpell(
|
|
VoidTorrent:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Halo
|
|
STAPL:AddSpell(
|
|
Halo:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Target:GetEnemies(10) >= 2
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Mind Spike if you have a Surge of Darkness proc
|
|
STAPL:AddSpell(
|
|
MindSpike:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:GetAuras():FindMy(SurgeofDarkness):IsUp()
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Mind Flay: Insanity
|
|
STAPL:AddSpell(
|
|
MindFlayInsanity:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Mind Spike
|
|
STAPL:AddSpell(
|
|
MindSpike:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Target:GetEnemies(10) == 1
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Mind Flay
|
|
STAPL:AddSpell(
|
|
MindFlay:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
|
|
end):SetTarget(Target)
|
|
)
|
|
-- Cast Shadow Word: Pain if you're moving and nothing else is available
|
|
STAPL:AddSpell(
|
|
ShadowWordPain:CastableIf(function(self)
|
|
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:IsMoving()
|
|
end):SetTarget(Target)
|
|
)
|
|
|
|
-- Module that dictates APL flow
|
|
ShadowModule:Sync(function()
|
|
if not Player:IsAffectingCombat() then
|
|
RestingAPL:Execute()
|
|
end
|
|
if not Player:IsAffectingCombat() and Target:Exists() and Target:IsHostile() and not Target:IsDead() then
|
|
OpenerAPL:Execute()
|
|
end
|
|
if Player:IsAffectingCombat() and Target:Exists() and Target:IsHostile() and not Target:IsDead() then
|
|
UtilityAPL:Execute()
|
|
DefensivesAPL:Execute()
|
|
STAPL:Execute()
|
|
end
|
|
end)
|
|
Bastion:Register(ShadowModule)
|
|
|
|
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 = 'Shadow Word: Pain', value = 'swp'},
|
|
{ text = 'Shadow Crash', value = 'crash'},
|
|
{ text = 'None', value = 'none'},
|
|
},
|
|
initialValue = myconf:Read('opener', 'shield'),
|
|
onValueChanged = function(_, value) myconf:Write('opener', value) end }, },
|
|
|
|
[3] = { shadpr = { type = 'label', label = 'Buffs' } },
|
|
|
|
[4] = { pwf = { type = 'checkbox', label = 'Power Word: Fortitude', column = 6, order = 1,
|
|
initialValue = myconf:Read('pwf', false),
|
|
onValueChanged = function(_, flag) myconf:Write('pwf', flag) end },
|
|
|
|
shadform = { type = 'checkbox', label = 'Shadowform', column = 6, order = 2,
|
|
initialValue = myconf:Read('shadowform', false),
|
|
onValueChanged = function(_, flag) myconf:Write('shadowform', flag) end }, },
|
|
|
|
[5] = { shadpr = { type = 'label', label = 'Defensives' } },
|
|
|
|
[6] = { shield1 = { type = 'checkbox', label = 'Power Word: Shield', column = 6, order = 1,
|
|
initialValue = myconf:Read('pws', false),
|
|
onValueChanged = function(_, flag) myconf:Write('pws', flag) end },
|
|
|
|
shield2 = { type = 'slider', label = 'Player Health', column = 6, order = 2,
|
|
min = 1, max = 100, precision = 0,
|
|
initialValue = myconf:Read('pwspercent', 35),
|
|
onValueChanged = function(_, value) myconf:Write('pwspercent', value) end }, },
|
|
|
|
[7] = { dispersion1 = { type = 'checkbox', label = 'Dispersion', column = 6, order = 1,
|
|
initialValue = myconf:Read('dispersion', false),
|
|
onValueChanged = function(_, flag) myconf:Write('dispersion', flag) end },
|
|
|
|
dispersion2 = { type = 'slider', label = 'Player Health', column = 6, order = 2,
|
|
min = 1, max = 100, precision = 0,
|
|
initialValue = myconf:Read('dispersionpercent', 35),
|
|
onValueChanged = function(_, value) myconf:Write('dispersionpercent', value) end }, },
|
|
|
|
[8] = { shadpr = { type = 'label', label = 'Interrupts' } },
|
|
|
|
[9] = { silence = { type = 'checkbox', label = 'Silence on CD', column = 12, order = 1,
|
|
initialValue = myconf:Read('silence', false),
|
|
onValueChanged = function(_, flag) myconf:Write('silence', flag) end }, },
|
|
|
|
},
|
|
}
|
|
|
|
local tab2 =
|
|
{
|
|
layoutConfig = { padding = { top = 40 } },
|
|
rows = {
|
|
[1] = { shadpr = { type = 'label', 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 shadpriestconfig = {
|
|
layoutConfig = { padding = { top = 30 } },
|
|
rows = {
|
|
[1] = {
|
|
container = {
|
|
type = 'tab',
|
|
fullSize = true,
|
|
tabs = {
|
|
{
|
|
name = 'player',
|
|
title = 'Player Settings',
|
|
layout = tab1
|
|
},
|
|
{
|
|
name = 'placeholder',
|
|
title = 'Placeholder',
|
|
layout = tab2
|
|
}
|
|
},
|
|
}
|
|
},
|
|
},
|
|
}
|
|
Bastion.settingstemplate(shadpriestconfig, 'Shadow Priest', 400, 500, 1.00, 1.00, 1.00) --, 0.00, 0.44, 0.87, 'enhsha') --Title of Settings Frame, Width, Height, ClassRGB, Rotation Name
|
|
|
|
-- 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 |