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.
bastion/scripts/shadowpriest.lua

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