From d01389faa4a0b60eb9cebba2fea17848e97a58ae Mon Sep 17 00:00:00 2001 From: BrewingCoder Date: Tue, 7 May 2024 19:48:30 -0400 Subject: [PATCH 1/2] Initial Affliction --- .../Warlock/Affliction/BrewAffliction.lua | 334 ++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 Rotations/Warlock/Affliction/BrewAffliction.lua diff --git a/Rotations/Warlock/Affliction/BrewAffliction.lua b/Rotations/Warlock/Affliction/BrewAffliction.lua new file mode 100644 index 000000000..88edc5d9d --- /dev/null +++ b/Rotations/Warlock/Affliction/BrewAffliction.lua @@ -0,0 +1,334 @@ +------------------------------------------------------- +-- Author = BrewingCoder +-- Patch = 10.2.6 +-- Coverage = 50% +-- Status = Development +-- Readiness = Development +------------------------------------------------------- +local rotationName = "BrewAffliction" + +local colors = { + blue = "|cff4285F4", + red = "|cffDB4437", + yellow = "|cffF4B400", + green = "|cff0F9D58", + white = "|cffFFFFFF", + purple = "|cff9B30FF", + aqua = "|cff89E2C7", + blue2 = "|cffb8d0ff", + green2 = "|cff469a81", + blue3 = "|cff6c84ef", + orange = "|cffff8000" +} + +local function createToggles() + local RotationModes = { + [1] = { mode = "On", value = 1 , overlay = "Rotation Enabled", tip = "Enable Rotation", highlight = 1, icon = br.player.spell.unendingResolve }, + [2] = { mode = "Off", value = 4 , overlay = "Rotation Disabled", tip = "Disable Rotation", highlight = 0, icon = br.player.spell.unendingResolve } + }; + br.ui:createToggle(RotationModes,"Rotation",1,0) + + local AOEMode + + local DefensiveModes = { + [1] = { mode = "On", value = 1 , overlay = "Defensive Enabled", tip = "Includes Defensive Cooldowns.", highlight = 1, icon = br.player.spell.unendingResolve}, + [2] = { mode = "Off", value = 2 , overlay = "Defensive Disabled", tip = "No Defensives will be used.", highlight = 0, icon = br.player.spell.unendingResolve} + }; + br.ui:createToggle(DefensiveModes,"Defensive",2,0) + local PetSummonModes = { + [1] = { mode = "1", value = 1 , overlay = "Imp", tip = "Summon Imp", highlight = 1, icon = br.player.spell.summonImp }, + [2] = { mode = "2", value = 2 ,overlay = "Voidwalker", tip = "Summon Voidwalker", highlight = 1, icon = br.player.spell.summonVoidwalker }, + [3] = { mode = "3", value = 3 , overlay = "Felhunter", tip = "Summon Felhunter", highlight = 1, icon = br.player.spell.summonFelhunter }, + [4] = { mode = "4", value = 4 , overlay = "Sayaad", tip = "Summon Sayaad", highlight = 1, icon = br.player.spell.summonSuccubus }, + [5] = { mode = "5", value = 5 , overlay = "Felguard", tip = "Summon Felguard", highlight = 1, icon = br.player.spell.summonFelguard}, + [6] = { mode = "6", value = 6 , overlay = "None", tip = "Do Not Summon", highlight = 0, icon = br.player.spell.fear} + } + br.ui:createToggle(PetSummonModes,"PetSummon",3,0) +end + +local function PetId() + if br._G.UnitExists("pet") then + return tonumber(br._G.UnitGUID("pet"):match("-(%d+)-%x+$",10)) + else + return nil + end +end + +local pets = { + imp = 416, + voidwalker = 1860, + felhunter = 417, + succubus = 1863, + felguard = 17252 +} + + +local function createOptions() + local optionTable + + local function rotationOptions() + local section + ----------------------- + --- GENERAL OPTIONS --- + ----------------------- + section = br.ui:createSection(br.ui.window.profile, "General") + -- Corruption + br.ui:createCheckbox(section, "Use Corruption") + -- Curse of Weakness + br.ui:createCheckbox(section, "Use Curse of Weakness") + br.ui:checkSectionState(section) + ------------------------- + --- DEFENSIVE OPTIONS --- + ------------------------- + section = br.ui:createSection(br.ui.window.profile, "Defensive") + -- Drain Life + br.ui:createSpinner(section, "Drain Life", 40, 0, 100, 5, "|cffFFFFFFPet Health Percent to Cast At") + -- Health Funnel + br.ui:createSpinner(section, "Health Funnel", 30, 0, 95, 5, "|cffFFFFFFPet Health Percent to Cast At") + br.ui:createSpinnerWithout(section, "Player Limit", 70, 0, 100, 5, "|cffFFFFFFHealth Percent to not use below.") + -- Healthstone + br.ui:createSpinner(section, "Healthstone", 60, 0, 95, 5, "|cffFFFFFFHealth Percent to Cast At") + -- Unending Resolve + br.ui:createSpinner(section, "Unending Resolve", 50, 0, 100, 5, "|cffFFFFFFHealth Percent to Cast At") + + br.ui:checkSectionState(section) + ---------------------- + --- TOGGLE OPTIONS --- + ---------------------- + section = br.ui:createSection(br.ui.window.profile, "Toggle Keys") + -- Single/Multi Toggle + br.ui:createDropdownWithout(section, "Rotation Mode", br.dropOptions.Toggle, 4) + --Defensive Key Toggle + br.ui:createDropdownWithout(section, "Defensive Mode", br.dropOptions.Toggle, 6) + -- Pause Toggle + br.ui:createDropdown(section, "Pause Mode", br.dropOptions.Toggle, 6) + br.ui:checkSectionState(section) + end + optionTable = {{ + [1] = "Rotation Options", + [2] = rotationOptions, + }} + return optionTable +end + +local cast +local cd +local debuff +local has +local mode +local ui +local pet +local spell +local unit +local units +local use +local power +local buff +local var +local equiped +local enemies +local talent +local actionList = {} +local activePet + + +local function round(number, digit_position) + local precision = math.pow(10, digit_position) + number = number + (precision / 2); -- this causes value #.5 and up to round up + return math.floor(number / precision) * precision +end + +local function boolNumeric(value) + if value then return 1 end + return 0 +end + +actionList.Defensive = function() + if cast.able.drainLife(units.dyn40) and unit.hp() <= ui.value("Drain Life") and unit.inCombat() then + if cast.drainLife() then ui.debug("Channeling Drain Life") return true end + end + -- Health Funnel + if cast.able.healthFunnel() and unit.hp("pet") <= ui.value("Health Funnel") and unit.hp("player") > ui.value("Player Limit") then + if cast.healthFunnel("pet") then ui.debug("Channeling Health Funnel") return true end + end + -- Healthstone + if ui.checked("Healthstone") then + if use.able.healthstone() and unit.inCombat() and has.healthstone() and unit.hp() <= ui.value("Healthstone") then + if use.healthstone() then ui.debug("Using Healthstone") return true end + end + if cast.able.createHealthstone() and not has.healthstone() and not ui.fullBags() then + if cast.createHealthstone() then ui.debug("Casting Create Healthstone") return true end + end + end + -- Unending Resolve + if ui.checked("Unending Resolve") and unit.hp() <= ui.value("Unending Resolve") and unit.inCombat() then + if cast.unendingResolve() then ui.debug("Casting Unending Resolve") return true end + end + +end + +actionList.Extra = function() + if cast.able.createHealthstone() and not has.healthstone() and not ui.fullBags() then + if cast.createHealthstone() then ui.debug("Casting Create Healthstone") return true end + end +end + +actionList.Interrupt = function() + -- if cast.able.fear("target") and unit.interrupt(40, "target", false) then + -- if cast.fear("target") then ui.debug("Casting Fear") return true end + -- end +end + +actionList.PreCombat = function() + if not unit.moving() and unit.level() >= 3 + and br._G.GetTime() - br.pauseTime > 0.5 + and br.timer:useTimer("summonPet", 1) then + if mode.petSummon == 1 and activePet ~= pets.imp and cast.able.summonImp() and not cast.last.summonImp() then + if cast.summonImp("player") then return true end + end + if mode.petSummon == 2 and activePet ~= pets.voidwalker and cast.able.summonVoidwalker() and not cast.last.summonVoidwalker(1) then + if cast.summonVoidwalker("player") then return true end + end + if mode.petSummon == 3 and activePet ~= pets.felhunter and cast.able.summonFelhunter() and not cast.last.summonFelguard(1) then + if cast.summonFelhunter("player") then return true end + end + if mode.petSummon == 4 and activePet ~= pets.succubus and cast.able.summonSuccubus() and not cast.last.summonSuccubus(1) then + if cast.summonSuccubus("player") then return true end + end + if mode.petSummon == 5 and activePet ~= pets.felguard and cast.able.summonFelguard() and not cast.last.summonFelguard(1) then + if cast.summonFelguard("player") then return true end + end + end + + -- if unit.inCombat() and unit.valid("target") and not var.profileStop then + if not unit.inCombat() and unit.valid("target") and unit.distance("target") <= 40 then + if cast.able.agony("target") and not debuff.agony.exists("target") then + if cast.agony("target") then ui.debug("[PreCombat] Agony") return true end + end + end +end + +actionList.CoolDown = function() + + + +end + +local function runRotation() + cast = br.player.cast + cd = br.player.cd + debuff = br.player.debuff + buff = br.player.buff + has = br.player.has + mode = br.player.ui.mode + talent = br.player.talent + ui = br.player.ui + pet = br.player.pet + spell = br.player.spell + ui = br.player.ui + unit = br.player.unit + units = br.player.units + use = br.player.use + power = br.player.power.soulShards() + var = br.player.variables + equiped = br.player.equiped + enemies = br.player.enemies + var.inRaid = br.player.instance=="raid" + var.inInstance = br.player.instance=="party" + activePet = PetId() + + var.demonicTyrant = false + var.demonicTyrantRemains = 0 + + -- Units + units.get(5) + units.get(40) + enemies.get(5) + enemies.get(8) + enemies.get(10) + enemies.get(15) + enemies.get(20) + enemies.get(25) + enemies.get(30) + enemies.get(35) + enemies.get(40) + enemies.get(5,"player",false,true) + enemies.get(10,"player",false, true) + enemies.get(20,"player",false,true) + enemies.get(30,"player",false,true) + enemies.get(40,"player",false,true) + + var.UnitNeedsAgony = nil + var.AgonyCount = 0 + for i=1,#enemies.yards40f do + if not debuff.agony.exists(enemies.yards40f[i]) and br._G.UnitAffectingCombat(enemies.yards40f[i]) then + var.UnitNeedsAgony = enemies.yards40f[i] + else + var.AgonyCount = var.AgonyCount + 1 + end + end + var.UnitsNeedCorruption = nil + var.CorruptionCount = 0 + for i=1,#enemies.yards40f do + if not debuff.corruption.exists(enemies.yards40f[i]) and br._G.UnitAffectingCombat(enemies.yards40f[i]) then + var.UnitsNeedCorruption = enemies.yards40f[i] + else + var.CorruptionCount = var.CorruptionCount + 1 + end + end + + + -- Pause Timer + if br.pauseTime == nil then br.pauseTime = br._G.GetTime() end + + if not unit.inCombat() and not unit.exists("target") and var.profileStop then + var.profileStop = false + elseif (unit.inCombat() and var.profileStop) or ui.pause() or unit.mounted() or unit.flying() or ui.mode.rotation == 4 then + return true + else + if actionList.Extra() then return true end + if actionList.Defensive() then return true end + if actionList.PreCombat() then return true end + if unit.inCombat() and unit.valid("target") and not var.profileStop then + if actionList.Interrupt() then return true end + if actionList.CoolDown() then return true end + + if cast.able.agony("target") and not debuff.agony.exists("target") then + if cast.agony("target") then ui.debug("Casting Agony") return true end + end + + if var.UnitNeedsAgony ~= nil and cast.able.agony(var.UnitNeedsAgony) then + if cast.agony(var.UnitNeedsAgony) then ui.debug("Casting Agony") return true end + end + + if cast.able.corruption("target") and not debuff.corruption.exists("target") then + if cast.corruption("target") then ui.debug("Casting Corruption") return true end + end + if var.UnitsNeedCorruption ~= nil and cast.able.corruption(var.UnitsNeedCorruption) then + if cast.corruption(var.UnitsNeedCorruption) then ui.debug("Casting Corruption") return true end + end + + if cast.able.maleficRapture() then + print("Corruption Count: "..var.CorruptionCount) + print("Agony Count: "..var.AgonyCount) + print("Enemies in 40 yards: "..#enemies.yards40f) + end + + if cast.able.maleficRapture() and var.CorruptionCount == #enemies.yards40f and var.AgonyCount == #enemies.yards40f and not cast.last.maleficRapture() then + if cast.maleficRapture() then ui.debug("Casting Malefic Rapture") return true end + end + + + + end + end +end +local id = 265 -- Affliction Warlock + +if br.rotations[id] == nil then br.rotations[id] = {} end +tinsert(br.rotations[id],{ + name = rotationName, + toggles = createToggles, + options = createOptions, + run = runRotation, +}) \ No newline at end of file From 52a4f091c728f17dfe81de9c8f58c941a468ced1 Mon Sep 17 00:00:00 2001 From: README Bot Date: Tue, 7 May 2024 23:52:16 +0000 Subject: [PATCH 2/2] Updated README.md from rotation metadata --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 3a5368646..8ff3cae70 100644 --- a/README.md +++ b/README.md @@ -166,6 +166,12 @@ Raidable means if its good to raid with. ### Warlock +- Affliction + +| rotation | author |patch |coverage| status | readiness |last updated| +|--------------|------------|:----:|:------:|:---------:|:-----------:|-----------:| +|BrewAffliction|BrewingCoder|10.2.6| 50% |Development|:interrobang:| 05/07/2024| + - Demonology |rotation | author |patch |coverage| status | readiness |last updated|