From a454282f0e3781f6777ebd10f8c40914eb49045c Mon Sep 17 00:00:00 2001 From: Godlyh3ll Date: Wed, 16 Jul 2025 02:53:19 -0600 Subject: [PATCH 1/7] Add files via upload --- script.lua | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/script.lua b/script.lua index 3df5f47..fcc46fd 100644 --- a/script.lua +++ b/script.lua @@ -148,7 +148,11 @@ end local knownBattlerageSkillList = function() if #requestSkillDetails == 0 then - return battlerageSkills[1].name .. " " .. battlerageSkills[2].name .. " " .. battlerageSkills[3].name .. " ".. battlerageSkills[4].name .. " ".. battlerageSkills[5].name .. " ".. battlerageSkills[6].name + local names = {} + for i, skill in ipairs(battlerageSkills) do + names[#names+1] = skill.name + end + return table.concat(names, " ") end return("processing... try doing some things!") end @@ -163,8 +167,8 @@ local sortDepthswalkerBattlerage = function() debugMessage("sorting brage for walkers", {battlerageSkills = battlerageSkills}) - if class ~= "Depthswalker" or #battlerageSkills ~= 6 then return end - battlerageSkills[2], battlerageSkills[3], battlerageSkills[4] = battlerageSkills["curse"], battlerageSkills["nakail"], battlerageSkills["lash"] + if class ~= "Depthswalker" or #battlerageSkills ~= 7 then return end + battlerageSkills[3], battlerageSkills[4], battlerageSkills[5] = battlerageSkills["curse"], battlerageSkills["nakail"], battlerageSkills["lash"] battlerageSkills["curse"].affliction = "aeon" battlerageSkills["boinad"].affliction = "charm" @@ -181,8 +185,8 @@ local sortPariahBattlerage = function() debugMessage("sorting brage for pariah", {battlerageSkills = battlerageSkills}) - if class ~= "Pariah" or #battlerageSkills ~= 6 then return end - battlerageSkills[2], battlerageSkills[3], battlerageSkills[4] = battlerageSkills["symphony"], battlerageSkills["scour"], battlerageSkills["feast"] + if class ~= "Pariah" or #battlerageSkills ~= 7 then return end + battlerageSkills[3], battlerageSkills[4], battlerageSkills[5] = battlerageSkills["symphony"], battlerageSkills["scour"], battlerageSkills["feast"] battlerageSkills["symphony"].affliction = "fear" battlerageSkills["wail"].affliction = "clumsiness" @@ -202,8 +206,8 @@ local sortPsionBattlerage = function() debugMessage("sorting brage for psion", {battlerageSkills = battlerageSkills}) - if class ~= "Psion" or #battlerageSkills ~= 6 then return end - battlerageSkills[2], battlerageSkills[3], battlerageSkills[4] = battlerageSkills["regrowth"], battlerageSkills["pulverise"], battlerageSkills["devastate"] + if class ~= "Psion" or #battlerageSkills ~= 7 then return end + battlerageSkills[3], battlerageSkills[4], battlerageSkills[5] = battlerageSkills["regrowth"], battlerageSkills["pulverise"], battlerageSkills["devastate"] battlerageSkills["terror"].affliction = "fear" @@ -215,8 +219,8 @@ local sortUnnamableBattlerage = function() debugMessage("sorting brage for unnamable", {battlerageSkills = battlerageSkills}) - if class ~= "Unnamable" or #battlerageSkills ~= 6 then return end - battlerageSkills[2], battlerageSkills[3], battlerageSkills[4] = battlerageSkills["dread"], battlerageSkills["sunder"], battlerageSkills["destroy"] + if class ~= "Unnamable" or #battlerageSkills ~= 7 then return end + battlerageSkills[3], battlerageSkills[4], battlerageSkills[5] = battlerageSkills["dread"], battlerageSkills["sunder"], battlerageSkills["destroy"] battlerageSkills["dread"].affliction = "fear" battlerageSkills["entropy"].affliction = "aeon" @@ -557,8 +561,8 @@ end local function rageRazeFunction() if keneanung.bashing.shield then - if keneanung.bashing.configuration[class].autorageraze and keneanung.bashing.rageAvailable(3) then - send(battlerageSkills[3].command:format(keneanung.bashing.targetList[keneanung.bashing.attacking].id), false) + if keneanung.bashing.configuration[class].autorageraze and keneanung.bashing.rageAvailable(4) then + send(battlerageSkills[4].command:format(keneanung.bashing.targetList[keneanung.bashing.attacking].id), false) keneanung.bashing.shield = false local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] if system.brokeShield then @@ -587,14 +591,14 @@ keneanung.bashing.battlerage.simple = function(rage) ) if not rageRazeFunction() then - if keneanung.bashing.rageAvailable(4) then - sendRageAttack(battlerageSkills[4].command) + if keneanung.bashing.rageAvailable(5) then + sendRageAttack(battlerageSkills[5].command) elseif - keneanung.bashing.rageAvailable(1) and - ((not battlerageSkills[4].skillKnown) or - rage >= (battlerageSkills[1].rage + battlerageSkills[4].rage)) + keneanung.bashing.rageAvailable(2) and + ((not battlerageSkills[5].skillKnown) or + rage >= (battlerageSkills[2].rage + battlerageSkills[5].rage)) then - sendRageAttack(battlerageSkills[1].command) + sendRageAttack(battlerageSkills[2].command) end end end @@ -612,10 +616,10 @@ keneanung.bashing.battlerage.simplereverse = function(rage) ) if not rageRazeFunction() then - if keneanung.bashing.rageAvailable(1) then - sendRageAttack(battlerageSkills[1].command) - elseif keneanung.bashing.rageAvailable(4) then - sendRageAttack(battlerageSkills[4].command) + if keneanung.bashing.rageAvailable(2) then + sendRageAttack(battlerageSkills[2].command) + elseif keneanung.bashing.rageAvailable(5) then + sendRageAttack(battlerageSkills[5].command) end end end From 78d294d4c4a02f5579ab29bef3f312103212c7d0 Mon Sep 17 00:00:00 2001 From: Godlyh3ll Date: Wed, 16 Jul 2025 02:56:26 -0600 Subject: [PATCH 2/7] Fix: Support for 7 Battlerage Skills MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This update modifies the script to handle the recent Achaea update where all classes now have seven battlerage abilities instead of six. The original script assumed only six and failed to parse or use the abilities properly. Summary of Changes: Updated all index references to battlerageSkills (e.g. 1 → 2, 3 → 4, 4 → 5, etc.). Adjusted rageRazeFunction, simple, and simplereverse battlerage strategies to reflect new skill positions. Modified class-specific battlerage sorting functions (sortPariahBattlerage, etc.) to assign skills to the new correct indexes. Rewrote knownBattlerageSkillList() to dynamically list all available battlerage skills instead of hardcoding 6. This should restore correct battlerage execution and allow the system to scale if future battlerage abilities are added. From 2a55b21b670908a62a3b0bbe0bfba2b8be83ca42 Mon Sep 17 00:00:00 2001 From: Godlyh3ll Date: Wed, 16 Jul 2025 14:41:56 -0600 Subject: [PATCH 3/7] script.lua This update improves battlerage skill handling following the addition of a new skill (e.g., provoke) by Achaea. Instead of rewriting index logic, the update adjusts the skill ordering dynamically to preserve existing behavior. Summary: sortProvokeBattlerage() added Detects if provoke is the first battlerage skill (as currently sent by Achaea) and moves it to the end of the skill list, maintaining expected indexing for existing battlerage strategies. Called sortProvokeBattlerage() after all class-based sorters Ensures skill order is corrected regardless of class. Updated knownBattlerageSkillList() to use dynamic iteration Now lists all known battlerage skills by name, regardless of total count, avoiding hardcoded index errors. These changes preserve all original functionality while gracefully handling future battlerage expansions. --- script.lua | 4108 ++++++++++++++++++++++++++-------------------------- 1 file changed, 2059 insertions(+), 2049 deletions(-) diff --git a/script.lua b/script.lua index fcc46fd..7743a82 100644 --- a/script.lua +++ b/script.lua @@ -1,2049 +1,2059 @@ -local debugEnabled = false -local send = send -local directTargetAccess = {} -local afflictions = { - weakness = { - colour = "pale_green", - timer = 7 - }, - sensitivity = { - colour = "orange_red", - timer = 8 - }, - recklessness = { - colour = "yellow", - timer = 15 - }, - aeon = { - colour = "purple", - timer = 6 - }, - fear = { - colour = "orange", - timer = 8 - }, - clumsiness = { - colour = "forest_green", - timer = 7 - }, - inhibit = { - colour = "light_coral", - timer = 9 - }, - charm = { - colour = "magenta", - timer = 5 - }, - stun = { - colour = "black:yellow", - timer = 4 - }, - amnesia = { - colour = "LightGrey", - timer = 5 - }, -} - -local nonBattlerageAttainmentSkills = { - "Prevail", - "Portals", - "Battlerage", - "Market", - "Battle", - "Limitedportals", - "Independence", - "Embrace", - "Tradeskills", - "Theft", - "Craftsmanship", - "Multiclass", - "Sustenance", - "Dragonhood", - "Polymath", -} -local sessionGains = { } -local tripGains = { gold = 0, experience = 0 } - -local requestSkillDetails = {} -local battlerageSkills = {} -local rage = 0 - -local race = "" -local class = "" -local lastGoldChange -local lastGold -local lastXp - -local roomTargetStore = {} -local denizenCache = {} - -local waitingForManualTargetTimer -local waitingForManualTarget = false - -keneanung = keneanung or {} -keneanung.bashing = {} -keneanung.bashing.availableTargets = {} -keneanung.bashing.configuration = {} -keneanung.bashing.configuration.priorities = {} -keneanung.bashing.targetList = {} -keneanung.bashing.systems = {} -keneanung.bashing.battlerage = {} -keneanung.bashing.room = {} -keneanung.bashing.pausingAfflictions = {} -keneanung.bashing.trackih = false - -keneanung.bashing.attacking = 0 -keneanung.bashing.damage = 0 -keneanung.bashing.attacks = 0 -keneanung.bashing.healing = 0 -keneanung.bashing.lastHealth = 0 -keneanung.bashing.usedRageAttack = false -keneanung.bashing.usedBalanceAttack = false - -keneanung.bashing.configuration.enabled = false -keneanung.bashing.configuration.warning = 500 -keneanung.bashing.configuration.fleeing = 300 -keneanung.bashing.configuration.autoflee = true -keneanung.bashing.configuration.system = "auto" -keneanung.bashing.configuration.filesToLoad = {} -keneanung.bashing.configuration.targetLoyals = false -keneanung.bashing.configuration.lifetimeGains = { gold = 0, experience = 0 } -keneanung.bashing.configuration.manualTargetting = false -keneanung.bashing.configuration.waitForManualTarget = 2 - -local debugMessage = function(message, content) - if not debugEnabled then return end - echo(string.format("[%s]: %s", (debug.getinfo(2).name or "unknown"), message)) - if content then - display(content) - end -end - -local getTargetPrio = function(name) - local prios = keneanung.bashing.configuration.priorities[gmcp.Room.Info.area] - - debugMessage("prios for this area", prios) - - if not prios then - return - end - - debugMessage("target name", name) - - local prio = table.index_of(prios, name) - debugMessage("prio", prio) - return prio -end - -local kecho = function(what, command, popup) - - what = "\nkeneanung: " .. what - if command then - cechoLink(what, command, popup or "", true) - else - cecho(what) - end - -end - -local knownBattlerageSkillList = function() - if #requestSkillDetails == 0 then - local names = {} - for i, skill in ipairs(battlerageSkills) do - names[#names+1] = skill.name - end - return table.concat(names, " ") - end - return("processing... try doing some things!") -end - -keneanung.bashing.configuration.requestBattlerageSkills = function() - kecho("Requesting battlerage skills...\n") - sendGMCP([[Char.Skills.Get {"group":"attainment"}]]) - send(" ") -end - -local sortDepthswalkerBattlerage = function() - - debugMessage("sorting brage for walkers", {battlerageSkills = battlerageSkills}) - - if class ~= "Depthswalker" or #battlerageSkills ~= 7 then return end - battlerageSkills[3], battlerageSkills[4], battlerageSkills[5] = battlerageSkills["curse"], battlerageSkills["nakail"], battlerageSkills["lash"] - - battlerageSkills["curse"].affliction = "aeon" - battlerageSkills["boinad"].affliction = "charm" - - battlerageSkills["erasure"].affsUsed = { - "amnesia", - "weakness" - } - - debugMessage("sorted brage for walkers", {battlerageSkills = battlerageSkills}) -end - -local sortPariahBattlerage = function() - - debugMessage("sorting brage for pariah", {battlerageSkills = battlerageSkills}) - - if class ~= "Pariah" or #battlerageSkills ~= 7 then return end - battlerageSkills[3], battlerageSkills[4], battlerageSkills[5] = battlerageSkills["symphony"], battlerageSkills["scour"], battlerageSkills["feast"] - - battlerageSkills["symphony"].affliction = "fear" - battlerageSkills["wail"].affliction = "clumsiness" - - battlerageSkills["spider"].affsUsed = { - "inhibit", - "sensitivity" - } - - battlerageSkills["scour"].command = "ACCURSED SCOUR %s" - battlerageSkills["scour"].rage = 17 - - debugMessage("sorted brage for pariah", {battlerageSkills = battlerageSkills}) -end - -local sortPsionBattlerage = function() - - debugMessage("sorting brage for psion", {battlerageSkills = battlerageSkills}) - - if class ~= "Psion" or #battlerageSkills ~= 7 then return end - battlerageSkills[3], battlerageSkills[4], battlerageSkills[5] = battlerageSkills["regrowth"], battlerageSkills["pulverise"], battlerageSkills["devastate"] - - battlerageSkills["terror"].affliction = "fear" - - - debugMessage("sorted brage for psion", {battlerageSkills = battlerageSkills}) -end - -local sortUnnamableBattlerage = function() - - debugMessage("sorting brage for unnamable", {battlerageSkills = battlerageSkills}) - - if class ~= "Unnamable" or #battlerageSkills ~= 7 then return end - battlerageSkills[3], battlerageSkills[4], battlerageSkills[5] = battlerageSkills["dread"], battlerageSkills["sunder"], battlerageSkills["destroy"] - - battlerageSkills["dread"].affliction = "fear" - battlerageSkills["entropy"].affliction = "aeon" - - battlerageSkills["onslaught"].affsUsed = { - "stun", - "sensitivity" - } - - debugMessage("sorted brage for unnamable", {battlerageSkills = battlerageSkills}) -end - -local requestAllSkillDetails = function() - while #requestSkillDetails > 0 do - sendGMCP(string.format([[Char.Skills.Get {"group": "attainment", "name": "%s"}]], requestSkillDetails[1])) - table.remove(requestSkillDetails,1) - end - send(" ",false) -end - -local migrateTo1Point8 = function() - if keneanung.bashing.configuration.attackcommand then - local migratedConfig = {} - migratedConfig.attackcommand = keneanung.bashing.configuration.attackcommand - keneanung.bashing.configuration.attackcommand = nil - migratedConfig.autoraze = keneanung.bashing.configuration.autoraze - keneanung.bashing.configuration.autoraze = nil - migratedConfig.razecommand = keneanung.bashing.configuration.razecommand - keneanung.bashing.configuration.razecommand = nil - migratedConfig.rageStrat = keneanung.bashing.configuration.rageStrat - keneanung.bashing.configuration.rageStrat = nil - migratedConfig.autorageraze = keneanung.bashing.configuration.autorageraze - keneanung.bashing.configuration.autorageraze = nil - - raiseEvent("keneanung.bashing.settings.changed") - end -end - -local startAttack = function() - local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] - system.startAttack() - gmod.enableModule("keneanung.bashing", "IRE.Display") - sendGMCP([[Core.Supports.Add ["IRE.Display 3"] ]]) -- register the GMCP module independently from gmod. -end - -local stopAttack = function() - local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] - system.stopAttack() - gmod.disableModule("keneanung.bashing", "IRE.Display") - sendGMCP([[Core.Supports.Remove ["IRE.Display"] ]]) -- unregister the GMCP module independently from gmod. -end - -keneanung.bashing.systems.svo = { - - startAttack = function() - svo.addbalanceful("do next attack", keneanung.bashing.nextAttack) - svo.donext() - end, - - stopAttack = function() - svo.removebalanceful("do next attack") - end, - - flee = function() - raiseEvent("keneanung.bashing.fleeing") - keneanung.bashing.systems.svo.stopAttack() - svo.dofreefirst(keneanung.bashing.fleeDirection) - end, - - warnFlee = function(avg) - svo.boxDisplay("Better run or get ready to die!", "orange") - end, - - notifyFlee = function(avg) - svo.boxDisplay("Running as you have not enough health left.", "red") - end, - - handleShield = function() - keneanung.bashing.shield = true - end, - - setup = function() - send = function(command, echoback) - debugMessage("send got called", {command = command, echoback = echoback }) - local useAlias = false - if command == "keneanungki" then - command = keneanung.bashing.configuration[class].attackcommand - useAlias = true - elseif command == "keneanungra" then - command = keneanung.bashing.configuration[class].razecommand - useAlias = true - end - if keneanung.bashing.attacking > 0 and useAlias then - command = command:gsub("&tar", keneanung.bashing.targetList[keneanung.bashing.attacking].id) - end - - local commands = command:split("/") - for _, part in ipairs(commands) do - svo.sendc(part, echoback) - end - end - end, - - teardown = function() - send = _G.send - end, - - unpause = function() - svo.donext() - end - -} - -keneanung.bashing.systems.wundersys = { - - startAttack = function() - if keneanung.bashing.attacking > 0 then - enableTrigger(keneanung.bashing.systems.wundersys.queueTrigger) - local command - if keneanung.bashing.configuration[class].attackcommand:find("&tar") then - command = keneanung.bashing.configuration[class].attackcommand - else - command = keneanung.bashing.configuration[class].attackcommand .. " &tar" - end - wsys.doradd(command) - end - end, - - stopAttack = function() - disableTrigger(keneanung.bashing.systems.wundersys.queueTrigger) - wsys.dorclear() - end, - - flee = function() - raiseEvent("keneanung.bashing.fleeing") - keneanung.bashing.systems.wundersys.stopAttack() - wsys.dofreeadd(keneanung.bashing.fleeDirection) - end, - - warnFlee = function(avg) - wsys.boxDisplay("Better run or get ready to die!", "orange") - end, - - notifyFlee = function(avg) - wsys.boxDisplay("Running as you have not enough health left.", "red") - end, - - handleShield = function() - if keneanung.bashing.configuration[class].autoraze then - local command - if keneanung.bashing.configuration[class].razecommand:find("&tar") then - command = keneanung.bashing.configuration[class].razecommand - else - command = keneanung.bashing.configuration[class].razecommand .. " &tar" - end - wsys.dofirst(command, 1) - end - keneanung.bashing.shield = true - end, - - brokeShield = function() - wsys.undo(true, 1) - end, - - setup = function() - keneanung.bashing.systems.wundersys.queueTrigger = tempTrigger("[System]: Running queued eb command: DOR", - [[ - local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] - keneanung.bashing.attacks = keneanung.bashing.attacks + 1 - local avgDmg = keneanung.bashing.damage / keneanung.bashing.attacks - local avgHeal = keneanung.bashing.healing / keneanung.bashing.attacks - - local estimatedDmg = avgDmg * 2 - avgHeal - - local fleeat = keneanung.bashing.calcFleeValue(keneanung.bashing.configuration.fleeing) - - local warnat = keneanung.bashing.calcFleeValue(keneanung.bashing.configuration.warning) - - if estimatedDmg > gmcp.Char.Vitals.hp - fleeat and keneanung.bashing.configuration.autoflee then - - system.notifyFlee(estimatedDmg) - - system.flee() - - else - if estimatedDmg > gmcp.Char.Vitals.hp - warnat then - - system.warnFlee(estimatedDmg) - - end - end - ]]) - disableTrigger(keneanung.bashing.systems.wundersys.queueTrigger) - registerAnonymousEventHandler("do action run", "keneanung.bashing.systems.wundersys.doActionRun") - end, - - teardown = function() - if keneanung.bashing.systems.wundersys.queueTrigger then - killTrigger(keneanung.bashing.systems.wundersys.queueTrigger) - end - end, - - doActionRun = function(_, command) - local razecommand - if keneanung.bashing.configuration[class].razecommand:find("&tar") then - razecommand = keneanung.bashing.configuration[class].razecommand - else - razecommand = keneanung.bashing.configuration[class].razecommand .. " &tar" - end - if command == razecommand then - keneanung.bashing.shield = false - end - end, - - pause = function() - keneanung.bashing.systems.wundersys.stopAttack() - end, - - unpause = function() - keneanung.bashing.systems.wundersys.startAttack() - end -} - -keneanung.bashing.systems.none = { - - firstAttack = false, - - startAttack = function() - timeframe("keneanung.bashing.systems.none.firstAttack", {0, true}, {1, false}) - keneanung.bashing.systems.none.doAttack() - end, - - doAttack = function() - if keneanung.bashing.attacking > 0 then - - if keneanung.bashing.usedBalanceAttack and not keneanung.bashing.systems.none.firstAttack then - return true - end - - enableTrigger(keneanung.bashing.systems.none.queueTrigger) - send("queue add eqbal keneanungki", false) - - timeframe("keneanung.bashing.usedBalanceAttack", {0, true}, {0.5, false}) - end - end, - - stopAttack = function() - disableTrigger(keneanung.bashing.systems.none.queueTrigger) - send("cq all") - end, - - flee = function() - raiseEvent("keneanung.bashing.fleeing") - keneanung.bashing.systems.none.stopAttack() - send("queue prepend eqbal " .. keneanung.bashing.fleeDirection) - end, - - warnFlee = function(avg) - echo("Better run or get ready to die!") - end, - - notifyFlee = function(avg) - echo("Running as you have not enough health left.") - end, - - handleShield = function() - keneanung.bashing.shield = true - if keneanung.bashing.configuration[class].autoraze then - local command - send("queue prepend eqbal keneanungra", false) - end - end, - - brokeShield = function() - send("cq all") - send("queue add eqbal keneanungki", false) - end, - - setup = function() - keneanung.bashing.systems.none.queueTrigger = tempRegexTrigger("^\\[System\\]: Running queued eb command: (KENEANUNGKI|KENEANUNGRA)$", - [[ - local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] - keneanung.bashing.attacks = keneanung.bashing.attacks + 1 - local avgDmg = keneanung.bashing.damage / keneanung.bashing.attacks - local avgHeal = keneanung.bashing.healing / keneanung.bashing.attacks - - local estimatedDmg = avgDmg * 2 - avgHeal - - local fleeat = keneanung.bashing.calcFleeValue(keneanung.bashing.configuration.fleeing) - - local warnat = keneanung.bashing.calcFleeValue(keneanung.bashing.configuration.warning) - - if estimatedDmg > gmcp.Char.Vitals.hp - fleeat and keneanung.bashing.configuration.autoflee then - - system.notifyFlee(estimatedDmg) - - system.flee() - - else - if estimatedDmg > gmcp.Char.Vitals.hp - warnat then - - system.warnFlee(estimatedDmg) - - end - if matches[2] == "KENEANUNGKI" then - keneanung.bashing.systems.none.doAttack() - else - keneanung.bashing.shield = false - end - end - ]]) - disableTrigger(keneanung.bashing.systems.none.queueTrigger) - end, - - teardown = function() - if keneanung.bashing.systems.none.queueTrigger then - killTrigger(keneanung.bashing.systems.none.queueTrigger) - end - end, - - pause = function() - disableTrigger(keneanung.bashing.systems.none.queueTrigger) - end, - - unpause = function() - keneanung.bashing.systems.none.startAttack() - end - -} - -local function sendRageAttack(attack) - debugMessage("sending rage attack", attack) - send(attack:format(keneanung.bashing.targetList[keneanung.bashing.attacking].id), false) - keneanung.bashing.usedRageAttack = true - raiseEvent("keneanung.bashing.settings.changed") - tempTimer(1, "keneanung.bashing.usedRageAttack = false") -end - -local function rageRazeFunction() - if keneanung.bashing.shield then - if keneanung.bashing.configuration[class].autorageraze and keneanung.bashing.rageAvailable(4) then - send(battlerageSkills[4].command:format(keneanung.bashing.targetList[keneanung.bashing.attacking].id), false) - keneanung.bashing.shield = false - local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] - if system.brokeShield then - system.brokeShield() - end - return true - else - return false - end - end -end - -keneanung.bashing.battlerage.none = function(rage) -end - -keneanung.bashing.battlerage.simple = function(rage) - if keneanung.bashing.attacking == 0 then return end - - debugMessage("running 'simple' rage strategy", - { - rage = rage, - shield = keneanung.bashing.shield, - rageraze = keneanung.bashing.configuration[class].autorageraze, - rageSkills = battlerageSkills - } - ) - - if not rageRazeFunction() then - if keneanung.bashing.rageAvailable(5) then - sendRageAttack(battlerageSkills[5].command) - elseif - keneanung.bashing.rageAvailable(2) and - ((not battlerageSkills[5].skillKnown) or - rage >= (battlerageSkills[2].rage + battlerageSkills[5].rage)) - then - sendRageAttack(battlerageSkills[2].command) - end - end -end - -keneanung.bashing.battlerage.simplereverse = function(rage) - if keneanung.bashing.attacking == 0 then return end - - debugMessage("running 'simplereverse' rage strategy", - { - rage = rage, - shield = keneanung.bashing.shield, - rageraze = keneanung.bashing.configuration[class].autorageraze, - rageSkills = battlerageSkills - } - ) - - if not rageRazeFunction() then - if keneanung.bashing.rageAvailable(2) then - sendRageAttack(battlerageSkills[2].command) - elseif keneanung.bashing.rageAvailable(5) then - sendRageAttack(battlerageSkills[5].command) - end - end -end - -local aliases = { - ["razecommand"] = "keneanungra", - ["attackcommand"] = "keneanungki", -} - -local getSystem = function(tbl, index) - local systemName - if index == "auto" then - if svo then - return keneanung.bashing.systems.svo - elseif wsys and wsys.myVersion then - return keneanung.bashing.systems.wundersys - else - return keneanung.bashing.systems.none - end - end - kecho("Something went completely wrong: You are using an unknown system ('"..index.."'). Please use 'kconfig bashing system ' to correct this.") - return nil -end - -setmetatable(keneanung.bashing.systems, { __index = getSystem } ) - -keneanung.bashing.isPossibleTarget = function(targetName, area) - if not area then - area = gmcp.Room.Info.area - end - - local prios = keneanung.bashing.configuration.priorities[area] or {} - - return table.contains(prios, targetName) -end - -keneanung.bashing.addPossibleTarget = function(targetName) - - local prios = keneanung.bashing.configuration.priorities - local area = gmcp.Room.Info.area - - if prios[area] == nil then - prios[area] = {} - kecho("Added the new area " .. area .. " to the configuration.") - end - - if not table.contains(prios[area], targetName) then - - local before = keneanung.bashing.idOnly(keneanung.bashing.targetList) - - table.insert(prios[area], targetName) - kecho("Added the new possible target " .. targetName .. " to the end of the priority list.") - keneanung.bashing.configuration.priorities = prios - raiseEvent("keneanung.bashing.settings.changed") - keneanung.bashing.save() - - for _, item in ipairs(keneanung.bashing.room) do - keneanung.bashing.addTarget(item) - end - - local after = keneanung.bashing.idOnly(keneanung.bashing.targetList) - - keneanung.bashing.emitEventsIfChanged(before, after) - end -end - -keneanung.bashing.showAreas = function() - keneanung.bashing.showAreasFiltered(keneanung.bashing.configuration.priorities) -end - -keneanung.bashing.showAreasFiltered = function(filtered) - - kecho("Which area would you like to configure:\n") - for area, _ in pairs(filtered) do - cechoLink(" (" .. area .. ")\n",[[keneanung.bashing.managePrios("]]..area..[[")]],"Show priority list for '" .. area .."",true) - end -end - -keneanung.bashing.managePrios = function(area) - - local possibleMatches = {} - for areaName, _ in pairs(keneanung.bashing.configuration.priorities) do - if areaName:lower() == area:lower() then - possibleMatches[areaName] = true - break - end - if areaName:lower():find(area:lower()) then - possibleMatches[areaName] = true - end - end - - if table.is_empty(possibleMatches) then - kecho("No targets for " .. area .. " found yet!\n") - return - elseif table.size(possibleMatches) == 1 then - for areaName, _ in pairs(possibleMatches) do - area = areaName - end - else - keneanung.bashing.showAreasFiltered(possibleMatches) - return - end - - local prios = keneanung.bashing.configuration.priorities[area] - - kecho("Possible targets for " .. area .. ":\n") - for num, item in ipairs(prios) do - echo(" ") - cechoLink("(^^)", [[keneanung.bashing.shuffleUp("]]..area..[[", ]] .. num .. [[)]], "Shuffle " .. item .. " one step up.", true) - echo(" ") - cechoLink("(vv)", [[keneanung.bashing.shuffleDown("]]..area..[[", ]] .. num .. [[)]], "Shuffle " .. item .. " one step down.", true) - echo(" ") - cechoLink("(DD)", [[keneanung.bashing.delete("]]..area..[[", ]] .. num .. [[)]], "Delete " .. item .. " from list.", true) - resetFormat() - echo(" " .. item .. "\n") - end -end - -keneanung.bashing.shuffleDown = function(area, num) - - local prios = keneanung.bashing.configuration.priorities[area] - - if num < #prios then - prios[num], prios[num+1] = prios[num+1], prios[num] - end - keneanung.bashing.save() - - keneanung.bashing.managePrios(area) - - raiseEvent("keneanung.bashing.settings.changed") -end - -keneanung.bashing.shuffleUp = function(area, num) - - local prios = keneanung.bashing.configuration.priorities[area] - - if num > 1 then - prios[num], prios[num-1] = prios[num-1], prios[num] - end - keneanung.bashing.save() - - keneanung.bashing.managePrios(area) - - raiseEvent("keneanung.bashing.settings.changed") -end - -keneanung.bashing.delete = function(area, num) - - local prios = keneanung.bashing.configuration.priorities[area] - - table.remove(prios, num) - - keneanung.bashing.save() - - keneanung.bashing.managePrios(area) - - raiseEvent("keneanung.bashing.settings.changed") -end - -keneanung.bashing.deleteByName = function(area, name) - - local prios = keneanung.bashing.configuration.priorities[area] - - for num, prioName in ipairs(prios) do - if name == prioName then - keneanung.bashing.delete(area, num) - return - end - end -end - -keneanung.bashing.save = function() - if string.char(getMudletHomeDir():byte()) == "/" then - _sep = "/" - else - _sep = "\\" - end -- if - local savePath = getMudletHomeDir() .. _sep .. "keneanung_bashing.lua" - table.save(savePath, keneanung.bashing.configuration) - -end -- func - -keneanung.bashing.load = function() - if string.char(getMudletHomeDir():byte()) == "/" - then _sep = "/" - else _sep = "\\" - end -- if - local savePath = getMudletHomeDir() .. _sep .. "keneanung_bashing.lua" - if (io.exists(savePath)) then - table.load(savePath, keneanung.bashing.configuration) - end -- if - -end -- func - -keneanung.bashing.showConfig = function() - kecho( - string.format( - "Bashing is %s", - keneanung.bashing.configuration.enabled and "on" or "off" - ), - "keneanung.bashing.toggle('enabled', 'Bashing')", - string.format( - "Turn bashing %s", - keneanung.bashing.configuration.enabled and "off" or "on" - ) - ) - - kecho( - string.format( - "Automatic fleeing is %s", - keneanung.bashing.configuration.autoflee and "on" or "off" - ), - "keneanung.bashing.toggle('autoflee', 'Fleeing')", - string.format( - "Turn fleeing %s", - keneanung.bashing.configuration.autoflee and "off" or "on" - ) - ) - - kecho( - string.format( - "Warning at a security threshhold of %s health", - keneanung.bashing.configuration.warning - ), - "clearCmdLine() appendCmdLine('kconfig bashing warnat ')", - "Set warn threshold." - ) - - kecho( - string.format( - "Fleeing at a security threshhold of %s health", - keneanung.bashing.configuration.fleeing - ), - "clearCmdLine() appendCmdLine('kconfig bashing fleeat ')", - "Set flee threshold." - ) - - kecho( - string.format( - "Attack is set to %s", - keneanung.bashing.configuration[class].attackcommand - ), - "clearCmdLine() appendCmdLine('kconfig bashing attackcommand ')", - "Set attack." - ) - - kecho( - string.format( - "Autoraze is %s", - keneanung.bashing.configuration[class].autoraze and "on" or "off" - ), - "keneanung.bashing.toggle('autoraze', 'Autorazing')", - string.format( - "Turn autorazing %s", - keneanung.bashing.configuration[class].autoraze and "off" or "on" - ) - ) - - kecho( - string.format( - "Special attack on shielding is set to %s", - keneanung.bashing.configuration[class].razecommand - ), - "clearCmdLine() appendCmdLine('kconfig bashing razecommand ')", - "Set attack to raze shields." - ) - - kecho( - string.format( - "Razing shields with rage is %s", - keneanung.bashing.configuration[class].autorageraze and "on" or "off" - ), - "keneanung.bashing.toggle('autorageraze', 'Autorazing with rage')", - string.format( - "Turn autorazing with rage %s", - keneanung.bashing.configuration[class].autorageraze and "off" or "on" - ) - ) - - kecho( - string.format( - "Currently using this battlerage strategy: %s", - keneanung.bashing.configuration[class].rageStrat - ), - "clearCmdLine() appendCmdLine('kconfig bashing ragestrat ')", - "Set battlerage strategy to use." - ) - - kecho( - string.format( - "Currently using this system: %s", - keneanung.bashing.configuration.system - ), - "clearCmdLine() appendCmdLine('kconfig bashing system ')", - "Set system to use." - ) - - kecho( - string.format( - "Considering loyals for fallback targets is %s", - keneanung.bashing.configuration.targetLoyals and "on" or "off" - ), - "keneanung.bashing.toggle('targetLoyals', 'Falling back to loyal targets')", - string.format( - "Turn considering loyals for fallback targets %s", - keneanung.bashing.configuration.targetLoyals and "off" or "on" - ) - ) - - kecho( - string.format( - "Manual targetting is %s", - keneanung.bashing.configuration.manualTargetting and "on" or "off" - ), - "keneanung.bashing.toggle('manualTargetting', 'Manual targetting')", - string.format( - "Turn manual targetting %s", - keneanung.bashing.configuration.manualTargetting and "off" or "on" - ) - ) - - kecho( - string.format( - "Waiting for %s seconds for a new target before stopping, if attacking manually", - keneanung.bashing.configuration.waitForManualTarget - ), - "clearCmdLine() appendCmdLine('kconfig bashing waitfortarget ')", - "Set time to wait for a target." - ) - - kecho( - string.format( - "Battlerage skills identified (reset): " .. knownBattlerageSkillList() - ), - "keneanung.bashing.configuration.requestBattlerageSkills()", - "Request and parse battlerage skills again." - ) - - echo("\n") - - kecho("Loading these additional files on startup: ") - cechoLink("(Add new file)", "keneanung.bashing.addFile()", "Add a new file to load on startup", true) - for num, path in ipairs(keneanung.bashing.configuration.filesToLoad) do - echo("\n " .. path .. " (") - cechoLink("(Delete)", "keneanung.bashing.deleteFile(" .. num .. ")", "Don't load this file anymore", true) - end - echo("\n") - - kecho("Version: " .. keneanung.bashing.version .. "") -end - -keneanung.bashing.toggle = function(what, print) - local toPrint - if what == "autoraze" or what == "autorageraze" then - keneanung.bashing.configuration[class][what] = not keneanung.bashing.configuration[class][what] - toPrint = keneanung.bashing.configuration[class][what] and "enabled" or "disabled" - else - keneanung.bashing.configuration[what] = not keneanung.bashing.configuration[what] - toPrint = keneanung.bashing.configuration[what] and "enabled" or "disabled" - end - kecho(print .. " " .. toPrint .. "\n" ) - raiseEvent("keneanung.bashing.settings.changed") - keneanung.bashing.save() -end - -keneanung.bashing.shielded = function(what) - if keneanung.bashing.attacking > 0 and what == keneanung.bashing.targetList[keneanung.bashing.attacking].name then - local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] - system.handleShield() - end -end - -keneanung.bashing.flee = function() - local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] - system.flee() - keneanung.bashing.clearTarget() - kecho("New order. Tactical retreat.\n") -end - -keneanung.bashing.attackButton = function(toggle, echoback) - if echoback == nil then echoback = true end - if (keneanung.bashing.attacking == 0 and toggle ~= false) or toggle then - if keneanung.bashing.setTarget() then - startAttack() - if echoback then kecho("Nothing will stand in our way.\n") end - else - if echoback then kecho("Nothing to target, boss.\n") end - end - else - keneanung.bashing.clearTarget() - stopAttack() - if echoback then kecho("Lets save them for later.\n") end - end -end - -keneanung.bashing.setFlee = function(where) - keneanung.bashing.fleeDirection = where - raiseEvent("keneanung.bashing.settings.changed") - kecho("Fleeing to the " .. keneanung.bashing.fleeDirection .. "\n" ) -end - -keneanung.bashing.setThreshold = function(newValue, what) - keneanung.bashing.configuration[what] = matches[2] - raiseEvent("keneanung.bashing.settings.changed") - kecho(what:title().." with a security threshhold of " .. keneanung.bashing.configuration[what] .. " health\n" ) - keneanung.bashing.save() -end - -keneanung.bashing.setWaitForTarget = function(amount) - keneanung.bashing.configuration.waitForManualTarget = tonumber(amount) or 2 - raiseEvent("keneanung.bashing.settings.changed") - kecho("Waiting " .. keneanung.bashing.configuration.waitForManualTarget .. " seconds for a new target\n" ) - keneanung.bashing.save() -end - -keneanung.bashing.nextAttack = function() - if keneanung.bashing.configuration.enabled == false then - return false - end - - if keneanung.bashing.usedBalanceAttack then - return true - end - - if #keneanung.bashing.pausingAfflictions > 0 then - return false - end - - local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] - - keneanung.bashing.attacks = keneanung.bashing.attacks + 1 - - if #keneanung.bashing.targetList > 0 then - local avg = keneanung.bashing.damage / keneanung.bashing.attacks - - local fleeat = keneanung.bashing.calcFleeValue(keneanung.bashing.configuration.fleeing) - - local warnat = keneanung.bashing.calcFleeValue(keneanung.bashing.configuration.warning) - - if avg > keneanung.bashing.lastHealth - fleeat and keneanung.bashing.configuration.autoflee then - - system.notifyFlee(avg) - - system.flee() - - else - if avg > keneanung.bashing.lastHealth - warnat then - - system.warnFlee(avg) - - end - - local attack = (keneanung.bashing.shield and keneanung.bashing.configuration[class].autoraze) and "keneanungra" or "keneanungki" - send(attack, false) - keneanung.bashing.shield = false - keneanung.bashing.usedBalanceAttack = true - tempTimer( 0.5, "keneanung.bashing.usedBalanceAttack = false") - return true - - end - end - - keneanung.bashing.clearTarget() - stopAttack() - return false - -end - -local roomItemCallbackWorker = function(event) - - if gmcp.Char.Items[event:match("%w+$")].location ~= "room" or keneanung.bashing.configuration.enabled == false then - return - end - - debugMessage(event, { room=keneanung.bashing.room, targetList=keneanung.bashing.targetList }) - - local backup = keneanung.bashing.targetList - local directAccessBackup = directTargetAccess - local before = keneanung.bashing.idOnly(keneanung.bashing.targetList) - - if(event == "gmcp.Char.Items.Add") then - local item = gmcp.Char.Items.Add.item - keneanung.bashing.room[#keneanung.bashing.room + 1] = item - if item.attrib and item.attrib:find("m") and not item.attrib:find("d") then - keneanung.bashing.seenDenizen(item.id, item.name) - item = keneanung.bashing.getTargetObject(item.id) - if not keneanung.bashing.configuration.manualTargetting then - keneanung.bashing.addTarget(item) - end - end - end - - if(event == "gmcp.Char.Items.List") then - keneanung.bashing.availableTargets = {} - if not keneanung.bashing.configuration.manualTargetting then - --restore targets we had when we were in the room last - local storedTargets = roomTargetStore[gmcp.Room.Info.num] - - if storedTargets then - keneanung.bashing.targetList = storedTargets.targetList - end - - local targetList = {} - -- make sure our targets stay at the same place! - for index, targ in ipairs(keneanung.bashing.targetList) do - -- still considered a target? - if getTargetPrio(targ.name) then - -- search if that target possibly left the room - local found = false - for _, item in ipairs(gmcp.Char.Items.List.items) do - if item.id == targ.id then - found = true - break - end - end - -- still there? Add it in the old place - if found then - targetList[#targetList + 1] = targ - end - end - end - keneanung.bashing.targetList = targetList - end - - keneanung.bashing.room = {} - for _, item in ipairs(gmcp.Char.Items.List.items) do - keneanung.bashing.room[#keneanung.bashing.room + 1] = item - if item.attrib and item.attrib:find("m") and not item.attrib:find("d") then - keneanung.bashing.seenDenizen(item.id, item.name) - item = keneanung.bashing.getTargetObject(item.id) - if not keneanung.bashing.configuration.manualTargetting then - keneanung.bashing.addTarget(item) - end - end - end - end - - if(event == "gmcp.Char.Items.Remove") then - local item = gmcp.Char.Items.Remove.item - for num, itemRoom in ipairs(keneanung.bashing.room) do - if (itemRoom.id * 1) == (item.id * 1) then - table.remove(keneanung.bashing.room, num) - break - end - end - - keneanung.bashing.removeTarget(item) - end - - local after = keneanung.bashing.idOnly(keneanung.bashing.targetList) - - debugMessage("got before and after", {before=before, after=after, intersection=table.n_intersection(before, after)}) - - if #before == #after and #table.n_intersection(before, after) == #before then - keneanung.bashing.targetList = backup - directTargetAccess = directAccessBackup - return - end - - keneanung.bashing.emitEventsIfChanged(before, after) - - debugMessage("after", { room=keneanung.bashing.room, targetList=keneanung.bashing.targetList }) -end - -keneanung.bashing.roomItemCallback = function(event) - if event == "gmcp.Char.Items.Add" or event == "gmcp.Char.Items.Remove" then - roomItemCallbackWorker(event) - end -end - -keneanung.bashing.sysDataSendRequestCallback = function(_, data) - debugMessage("data gets sent", {data = data}) - local lowerData = data:lower() - if - lowerData:starts("class switch") or -- class switch - lowerData:starts("dragonform") or -- dragon - lowerData:starts("lesserform") or -- from dragon to normal - lowerData:starts("prevail") or -- elemental lord - lowerData:starts("forsake") -- from elemental to normal - then - sendGMCP('Core.Supports.Add ["IRE.Display 3"]') - end - - if (lowerData == "ih" or lowerData:starts("ih ")) and keneanung.bashing.configuration.enabled then - keneanung.bashing.trackih = true - end -end - -keneanung.bashing.emitEventsIfChanged = function( before, after) - if keneanung.bashing.difference(before, after) then - raiseEvent("keneanung.bashing.targetList.changed") - if before[1] ~= after[1] then - raiseEvent("keneanung.bashing.targetList.firstChanged", after[1]) - end - end -end - -keneanung.bashing.difference = function( list1, list2 ) - - if #list1 ~= #list2 then - return true - end - - for num, value in ipairs(list1) do - if value ~= list2[num] then return true end - end - - return false - -end - -keneanung.bashing.idOnly = function( list ) - - local ret = {} - - for _, value in ipairs(list) do - - table.insert(ret, value.id) - - end - - return ret - -end - -keneanung.bashing.addTarget = function(item) - - local targets = keneanung.bashing.targetList - local insertAt - - debugMessage("addTarget", item) - - local targetPrio = getTargetPrio(item.name) - - if not targetPrio then - return - end - - local targetObject = { id = item.id, name = item.name, affs = {} } - - if #targets == 0 then - table.insert(targets, targetObject) - else - - -- Small safeguard against adding something twice - for _, tar in ipairs(targets) do - if tar.id == item.id then - return - end - end - - local iStart,iEnd,iMid = 1,#targets,0 - local found = false - -- Binary Search - while iStart <= iEnd do - -- calculate middle - iMid = math.floor( (iStart+iEnd)/2 ) - -- get compare value - local existingPrio = getTargetPrio(targets[iMid].name) - -- get all values that match - if targetPrio == existingPrio then - insertAt = iMid - found = true - break - elseif existingPrio == nil or targetPrio < existingPrio then - iEnd = iMid - 1 - else - iStart = iMid + 1 - end - - end - - if not found then - insertAt = iStart - end - - if insertAt <= keneanung.bashing.attacking and #keneanung.bashing.targetList >= keneanung.bashing.attacking then - insertAt = keneanung.bashing.attacking + 1 - end - - table.insert(targets, insertAt, item) - - end - - if directTargetAccess[item.id] then - for aff, timer in pairs(directTargetAccess[item.id].affs) do - targetObject[aff] = timer - end - end - - directTargetAccess[item.id] = targetObject - - keneanung.bashing.targetList = targets - -end - -keneanung.bashing.removeTarget = function(item) - - local targets = keneanung.bashing.targetList - local number - - for num, itemTarget in ipairs(targets) do - if (itemTarget.id * 1) == (item.id * 1) then - number = num - break - end - end - - if number then - table.remove(targets, number) - if number <= keneanung.bashing.attacking then - keneanung.bashing.attacking = keneanung.bashing.attacking - 1 - keneanung.bashing.setTarget() - end - for _, timer in pairs(directTargetAccess[item.id].affs) do - killTimer(timer) - end - directTargetAccess[item.id] = nil - if keneanung.bashing.attacking == 0 and keneanung.bashing.configuration.manualTargetting then - waitingForManualTarget = true - waitingForManualTargetTimer = tempTimer(keneanung.bashing.configuration.waitForManualTarget, function() waitingForManualTarget = false end) - end - end - - keneanung.bashing.targetList = targets - -end - -keneanung.bashing.prioListChangedCallback = function() - kecho("Priority list changed to:\n") - for _, tar in ipairs(keneanung.bashing.targetList) do - cecho(" " .. tar.name .. "\n") - end -end - -keneanung.bashing.roomMessageCallback = function() - if keneanung.bashing.lastRoom == nil then - keneanung.bashing.lastRoom = gmcp.Room.Info.num - keneanung.bashing.fleeDirection = "north" - end - - if keneanung.bashing.lastRoom == gmcp.Room.Info.num then - return - end - - if not keneanung.bashing.configuration.manualTargetting then - roomTargetStore[keneanung.bashing.lastRoom] = { - targetList = keneanung.bashing.targetList, - } - end - - keneanung.bashing.damage = 0 - keneanung.bashing.healing = 0 - keneanung.bashing.attacks = 0 - - if gmcp.Char.Vitals.hp then - keneanung.bashing.lastHealth = gmcp.Char.Vitals.hp * 1 - end - - keneanung.bashing.shield = false - if keneanung.bashing.attacking > 0 then - keneanung.bashing.clearTarget() - stopAttack() - end - local exits = getRoomExits(gmcp.Room.Info.num) or gmcp.Room.Info.exits - local found = false - - if exits ~= {} then - for direction, num in pairs(exits) do - if num == keneanung.bashing.lastRoom then - keneanung.bashing.fleeDirection = direction - found = true - break - end - end - end - - if not found and not gmcp.Room.Info.ohmap then - kecho("WARNING: No exit to flee found, reusing " .. keneanung.bashing.fleeDirection .. ".\n") - end - - keneanung.bashing.lastRoom = gmcp.Room.Info.num - - roomItemCallbackWorker("gmcp.Char.Items.List") -- update the room item list now, because now we know if we changed the area. - -- also be optimistic that there is no other items list in between -end - -keneanung.bashing.vitalsChangeRecord = function() - - if keneanung.bashing.attacking == 0 then return end - - if gmcp.Char.Vitals.hp then - - local difference = keneanung.bashing.lastHealth - gmcp.Char.Vitals.hp - - if difference > 0 then - keneanung.bashing.damage = keneanung.bashing.damage + difference - elseif difference < 0 then - keneanung.bashing.healing = keneanung.bashing.healing + math.abs(difference) - end - - keneanung.bashing.lastHealth = gmcp.Char.Vitals.hp * 1 - end - - for _, stat in ipairs(gmcp.Char.Vitals.charstats) do - local rageAmount = stat:match("^Rage: (%d+)$") - if rageAmount then - rage = tonumber(rageAmount) - break - end - end - - keneanung.bashing.battlerage[keneanung.bashing.configuration[class].rageStrat](rage, battlerageSkills) - -end - -keneanung.bashing.buttonActionsCallback = function() - keneanung.bashing.battlerage[keneanung.bashing.configuration[class].rageStrat](rage, battlerageSkills) -end - -keneanung.bashing.charStatusCallback = function() - local somethingChanged = false - if race ~= gmcp.Char.Status.race then - debugMessage("Race changed") - somethingChanged = true - race = gmcp.Char.Status.race - end - - if class ~= gmcp.Char.Status.class then - debugMessage("Class changed") - somethingChanged = true - class = gmcp.Char.Status.class - end - - if somethingChanged then - keneanung.bashing.configuration.requestBattlerageSkills() -- rerequest attainment abilities - migrateTo1Point8() - if not keneanung.bashing.configuration[class] then - local newClassConfig = {} - newClassConfig.autoraze = false - newClassConfig.razecommand = "none" - newClassConfig.attackcommand = "kill" - newClassConfig.rageStrat = "simple" - keneanung.bashing.configuration[class] = newClassConfig - kecho("Seen new class " .. class .. ". Default config set.") - end - keneanung.bashing.setAlias("attackcommand") - keneanung.bashing.setAlias("razecommand") - sendGMCP([[Core.Supports.Remove ["IRE.Display"] ]]) - end - - debugMessage("Going to calculate gold gains", { lastGoldChange = lastGoldChange, lastGold = lastGold } ) - - local goldNumber = tonumber(gmcp.Char.Status.gold) - local goldChange = goldNumber - (lastGold or 0) - - debugMessage("Got new gold numbers", { goldChange = goldChange, goldNumber = goldNumber } ) - - local lifetimeGains = keneanung.bashing.configuration.lifetimeGains - - if lastGoldChange ~= nil then -- On login, skip this - - if goldChange + lastGoldChange ~= 0 and goldChange > 0 then -- We only want to count - -- real changes (not - sessionGains.gold = sessionGains.gold + goldChange -- taking from pack) and - tripGains.gold = tripGains.gold + goldChange -- gold gains. - lifetimeGains.gold = lifetimeGains.gold + goldChange - - end - - end - - lastGoldChange = goldChange - lastGold = goldNumber - - local newXp = gmcp.Char.Status.level:match("^(%d+)") * 100 + gmcp.Char.Status.xp:match("(.+)%%") - - debugMessage("Calculating experience gain", { lastXp = lastXp, newXp = newXp }) - - if lastXp ~= nil then - - sessionGains.experience = sessionGains.experience + newXp - lastXp - tripGains.experience = tripGains.experience + newXp - lastXp - lifetimeGains.experience = lifetimeGains.experience + newXp - lastXp - - end - - lastXp = newXp -end - -local proneAfflictions = { - "prone", - "stun", - "paralysis", - "entangled", - "webbed", - "transfixation", - "impaled", - "bound", - "aeon", -} - -keneanung.bashing.pauseOnAffliction = function(affliction) - affliction = affliction:lower() - if table.contains(proneAfflictions, affliction) then - local pAffs = keneanung.bashing.pausingAfflictions - if not table.contains(pAffs, affliction) then - pAffs[#pAffs + 1] = affliction - local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] - if system.pause then - system.pause() - end - end - end -end - -keneanung.bashing.unpauseOnHealing = function(affliction) - affliction = affliction:lower() - if table.contains(proneAfflictions, affliction) then - local pAffs = keneanung.bashing.pausingAfflictions - local index = 0 - for i, aff in ipairs(pAffs) do - if aff == affliction then - index = i - break - end - end - if index > 0 then - table.remove(pAffs, index) - end - if #pAffs == 0 then - local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] - if system.unpause and keneanung.bashing.attacking > 0 then - system.unpause() - end - end - end -end - -keneanung.bashing.afflictionCallback = function(_, origMessage) - if origMessage == "gmcp.Char.Afflictions.Add" then - keneanung.bashing.pauseOnAffliction(gmcp.Char.Afflictions.Add.name) - elseif origMessage == "gmcp.Char.Afflictions.Remove" then - keneanung.bashing.unpauseOnHealing(gmcp.Char.Afflictions.Remove[1]) - end -end - -keneanung.bashing.setCommand = function(command, what) - keneanung.bashing.configuration[class][command] = what - kecho(command .. " is now " .. keneanung.bashing.configuration[class][command] .. "\n" ) - keneanung.bashing.setAlias(command) - keneanung.bashing.save() - raiseEvent("keneanung.bashing.settings.changed") -end - -keneanung.bashing.setTarget = function() - if #keneanung.bashing.targetList == 0 then - local tar - local targetSet = false - - if target ~= nil and target ~='' and target:lower() ~= "none" then - tar = target - elseif gmcp.Char.Status.target ~= "None" then - tar = gmcp.Char.Status.target - end - - debugMessage("set tar", tar) - - if tar ~= nil then - - for _, item in ipairs(keneanung.bashing.room) do - if item.attrib and item.attrib:find("m") and not item.attrib:find("d") and item.name:lower():find(tar:lower()) then - if keneanung.bashing.configuration.targetLoyals or not item.attrib:find("x") then - keneanung.bashing.targetList[#keneanung.bashing.targetList + 1]= { - id = item.id, - name = item.name - } - targetSet = true - end - end - end - end - if not targetSet then - keneanung.bashing.clearTarget() - stopAttack() - return - end - end - if keneanung.bashing.attacking == 0 or keneanung.bashing.targetList[keneanung.bashing.attacking].id ~= gmcp.IRE.Target.Info.id then - keneanung.bashing.attacking = keneanung.bashing.attacking + 1 - end - debugMessage("setting target", keneanung.bashing.targetList[keneanung.bashing.attacking]) - sendGMCP('IRE.Target.Set "' .. keneanung.bashing.targetList[keneanung.bashing.attacking].id .. '"') - return keneanung.bashing.attacking ~= 0 -end - -keneanung.bashing.clearTarget = function() - if gmcp.IRE.Target and gmcp.IRE.Target.Set ~= "" then - debugMessage("clearing target") - sendGMCP('IRE.Target.Set "0"') - end - keneanung.bashing.attacking = 0 -end - -keneanung.bashing.login = function() - gmod.enableModule("keneanung.bashing", "IRE.Target") - sendGMCP([[Core.Supports.Add ["IRE.Target 1"] ]]) -- register the GMCP module independently from gmod. - sendGMCP([[Char.Skills.Get {"group":"attainment"}]]) - local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] - system.setup() - sessionGains.gold = 0 - sessionGains.experience = 0 - lastGoldChange = nil - lastXpChange = nil - lastGold = nil -end - -keneanung.bashing.setAlias = function(command) - local attackCommand - if keneanung.bashing.configuration[class][command]:find("&tar") then - attackCommand = keneanung.bashing.configuration[class][command] - else - attackCommand = keneanung.bashing.configuration[class][command] .. " &tar" - end - send(string.format("setalias %s %s", aliases[command], attackCommand), false) -end - -keneanung.bashing.setSystem = function(systemName) - - if not systemName then - kecho("The following systems are known:") - for name, _ in pairs(keneanung.bashing.systems) do - kecho(" " .. name, "keneanung.bashing.setSystem('" .. name .. "')", "Set '" .. name .. "' as queueing system") - end - kecho(" auto", "keneanung.bashing.setSystem('auto')", "Set 'auto' as queueing system") - echo("\n") - return - end - - if not rawget(keneanung.bashing.systems, systemName) and systemName ~= "auto" then - kecho("System not changed as '" .. systemName .. "' is unknown.") - return - end - local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] - if system then - system.teardown() - end - keneanung.bashing.configuration.system = systemName - kecho("Using " .. keneanung.bashing.configuration.system .. " as queuing system.\n" ) - raiseEvent("keneanung.bashing.settings.changed") - keneanung.bashing.save() - system = keneanung.bashing.systems[keneanung.bashing.configuration.system] - system.setup() -end - -keneanung.bashing.setRageStrat = function(strategyName) - - if not strategyName then - kecho("The following rage strategies are known:") - for name, _ in pairs(keneanung.bashing.battlerage) do - kecho(" " .. name, "keneanung.bashing.setRageStrat('" .. name .. "')", "Set '" .. name .. "' as battlerage strategy") - end - echo("\n") - return - end - - if not keneanung.bashing.battlerage[strategyName] then - kecho("Battlerage strategy not changed as '" .. strategyName .. "' is unknown.") - return - end - keneanung.bashing.configuration[class].rageStrat = strategyName - keneanung.bashing.save() - raiseEvent("keneanung.bashing.settings.changed") - kecho("Using " .. strategyName .. " as battlerage strategy.\n" ) -end - -keneanung.bashing.calcFleeValue = function(configValue) - local isString = type(configValue) == "string" - if isString and configValue:ends("%") then - return configValue:match("%d+") * gmcp.Char.Vitals.maxhp / 100 - elseif isString and configValue:ends("d") then - return configValue:match("(.-)d") * keneanung.bashing.damage / keneanung.bashing.attacks - else - return configValue * 1 - end -end - -keneanung.bashing.addFile = function() - local path = invokeFileDialog(true, "Which file do you want to add?") - if path ~= "" then - keneanung.bashing.configuration.filesToLoad[#keneanung.bashing.configuration.filesToLoad + 1] = path - raiseEvent("keneanung.bashing.settings.changed") - end - keneanung.bashing.save() -end - -keneanung.bashing.deleteFile = function(num) - table.remove(keneanung.bashing.configuration.filesToLoad, num) - keneanung.bashing.save() - - raiseEvent("keneanung.bashing.settings.changed") -end - -keneanung.bashing.toggleDebug = function() - debugEnabled = not debugEnabled - kecho("Debug " .. (debugEnabled and "enabled" or "disabled")) -end - -keneanung.bashing.addDenizenAffliction = function(denizen, affliction, own) - debugMessage("New denizen affliction.", { denizen = denizen, affliction = affliction, own = own }) - - local affObject = afflictions[affliction] - debugMessage("associated affliction object", affObject) - if not affObject then - kecho("Affliction '" .. affliction .. "' is not a known denizen affliction.") - return - end - - local denizenObject = keneanung.bashing.getTargetObject(denizen) - debugMessage("associated denizen object from direct access", denizenObject) - if not denizenObject then - kecho("Denizen '" .. denizen .. "' not in list of targets. Fallback is not yet implemented.") - return - end - - local isTarget = (keneanung.bashing.targetList[keneanung.bashing.attacking].id == denizenObject.id) - - denizenObject.affs[affliction] = tempTimer(affObject.timer, - string.format("keneanung.bashing.removeDenizenAffliction('%s', '%s', %s)", denizenObject.id, affliction, own and "true" or "false")) - - kecho(string.format("<%s>%s%s gained <%s>%s", isTarget and "OrangeRed" or "yellow", - denizenObject.name, isTarget and " (your target)" or "", affObject.colour, affliction)) - if own then - raiseEvent("keneanung.bashing.afflictionGained", denizenObject.id, affliction) - end -end - -keneanung.bashing.removeDenizenAffliction = function(denizen, affliction, own) - debugMessage("Remove denizen affliction.", { denizen = denizen, affliction = affliction, own = own }) - - local affObject = afflictions[affliction] - debugMessage("associated affliction object", affObject) - if not affObject then - kecho("Affliction '" .. affliction .. "' is not a known denizen affliction.") - return - end - - local denizenObject = directTargetAccess[denizen] - debugMessage("associated denizen object from direct access", denizenObject) - if not denizenObject then - return - end - - local isTarget = (keneanung.bashing.targetList[keneanung.bashing.attacking].id == denizenObject.id) - - killTimer(denizenObject.affs[affliction]) - kecho(string.format("<%s>%s%s lost <%s>%s", - isTarget and "OrangeRed" or "yellow", denizenObject.name, isTarget and " (your target)" or "", affObject.colour, affliction)) - if own then - raiseEvent("keneanung.bashing.afflictionLost", denizenObject.id, affliction) - end - denizenObject.affs[affliction] = nil -end - -keneanung.bashing.getAfflictions = function(denizen) - debugMessage("Returnung denizen affliction.", { denizen = denizen }) - - local denizenObject = directTargetAccess[denizen] - debugMessage("associated denizen object from direct access", denizenObject) - if not denizenObject then - return {} - end - - local ret = {} - for aff, _ in pairs(denizenObject.affs) do - ret[#ret + 1] = aff - end - - return ret -end - -keneanung.bashing.hasAffliction = function(denizen, affliction) - debugMessage("Checking for denizen affliction.", { denizen = denizen, affliction = affliction }) - - local denizenObject = directTargetAccess[denizen] - debugMessage("associated denizen object from direct access", denizenObject) - if not denizenObject then - return false - end - - return denizenObject.affs[affliction] ~= nil -end - -keneanung.bashing.handleSkillList = function() - local skillList = gmcp.Char.Skills.List - if skillList.group ~= "attainment" then return end - - for _, skill in ipairs(skillList.list) do - if not table.contains(nonBattlerageAttainmentSkills, skill) then - requestSkillDetails[#requestSkillDetails + 1] = skill - end - end - battlerageSkills = {} - requestAllSkillDetails() -end - -keneanung.bashing.handleSkillInfo = function() - local skillInfo = gmcp.Char.Skills.Info - if skillInfo.group ~= "attainment" then return end - - local cooldown = tonumber(skillInfo.info:match("(%d+%.%d+) seconds")) - local rage = tonumber(skillInfo.info:match("(%d+) rage")) - local command = skillInfo.info:match("Syntax:\n(.-)\n"):gsub("", "%%s") - local affliction = skillInfo.info:match("Gives denizen affliction: (%w+)") - local affsUsed = {skillInfo.info:match("Uses denizen afflictions: (%w+) or (%w+)")} - for ind, aff in ipairs(affsUsed) do - affsUsed[ind] = aff:lower() - end - local skillKnown = skillInfo.info:find("*** You have not yet learned this ability ***", 1, true) == nil - - local rageObject = { - cooldown = cooldown, - rage = rage, - command = command, - affliction = affliction and affliction:lower(), - affsUsed = affsUsed, - name = skillInfo.skill:lower(), - skillKnown = skillKnown - } - - if #battlerageSkills == 0 or skillInfo.skill:lower() ~= battlerageSkills[#battlerageSkills].name then - if battlerageSkills[skillInfo.skill] then - battlerageSkills[skillInfo.skill] = rageObject - for index, oldObject in ipairs(battlerageSkills) do - if oldObject.name == rageObject.name then - battlerageSkills[index] = rageObject - break - end - end - debugMessage("Updated skill " .. skillInfo.skill .. ", complete list is here ", battlerageSkills) - else - battlerageSkills[skillInfo.skill] = rageObject - battlerageSkills[#battlerageSkills + 1] = rageObject - debugMessage("added new battlerage skill complete list is here ", battlerageSkills) - if #battlerageSkills == 6 then - sortDepthswalkerBattlerage() - sortPariahBattlerage() - sortPsionBattlerage() - sortUnnamableBattlerage() - kecho("Finished parsing battlerage skills.\n") - end - end - else - debugMessage("got double battlerage skill") - end -end - -keneanung.bashing.rageAvailable = function(ability) - if keneanung.bashing.usedRageAttack then return false end - if type(ability) == "number" then - ability = battlerageSkills[ability].name - end - - if not gmcp.IRE.Display then - return false - end - - for _, button in pairs(gmcp.IRE.Display.ButtonActions) do - if button.text:lower() == ability:lower() then - return button.highlight == 1 - end - end - return false -end - -keneanung.bashing.printGains = function(which) - local gainsTable - if which == "lifetime" then - gainsTable = keneanung.bashing.configuration.lifetimeGains - elseif which == "session" then - gainsTable = sessionGains - elseif which == "trip" then - gainsTable = tripGains - else - kecho(string.format("Gains for the timespan '%s' are not tracked.", which)) - return - end - - local levels, percent = math.modf(gainsTable.experience / 100) - percent = percent * 100 - kecho(string.format("You gained %d levels, %.1f%% towards the next level and %d gold during the period '%s'.", levels, percent, gainsTable.gold, which)) - if gainsTable.stopwatch then - local time = getStopWatchTime(gainsTable.stopwatch) - kecho(string.format("The period was %dh %dmin and %.3f sec long.", math.floor(time / 3600), math.floor( math.mod(time, 3600) / 60), math.mod(time, 60))) - end -end - -keneanung.bashing.startHuntingTrip = function() - if not tripGains.stopwatch then - tripGains = { gold = 0, experience = 0, stopwatch = createStopWatch() } - startStopWatch(tripGains.stopwatch) - kecho("Started new hunting trip. Enjoy and be careful.") - else - kecho("Ugh- Finish the running trip before starting a new one?") - end -end - -keneanung.bashing.stopHuntingTrip = function() - if tripGains.stopwatch then - kecho("Stopped hunting trip. I hope you had fun.") - keneanung.bashing.printGains("trip") - stopStopWatch(tripGains.stopwatch) - tripGains.stopwatch = nil - else - kecho("You are not hunting or didn't tell me you did. Can't stop anything.") - end -end - -keneanung.bashing.seenDenizen = function(id, name) - keneanung.bashing.availableTargets[name] = true - if denizenCache[id] then - local timer = denizenCache[id].expireTimer - killTimer(timer) - timer = tempTimer(10 * 60, "keneanung.bashing.unseenDenizen('" .. id .. "')") - denizenCache[id].expireTimer = timer - else - local cacheObject = { name = name } - cacheObject.expireTimer = tempTimer(10 * 60, "keneanung.bashing.unseenDenizen('" .. id .. "')") - denizenCache[id] = cacheObject - end -end - -keneanung.bashing.unseenDenizen = function(id) - if denizenCache[id] then - killTimer(denizenCache[id].expireTimer) - denizenCache[id] = nil - end - if directTargetAccess[id] then - directTargetAccess[id] = nil - end -end - -keneanung.bashing.getDenizenName = function(id) - return denizenCache[id] and denizenCache[id].name or "unknown" -end - -keneanung.bashing.getTargetObject = function(id) - if not tonumber(id) then - kecho("You are trying to access the denizen with ID " .. id .. " which is not a numerical ID.") - return - end - local result = directTargetAccess[tostring(id)] - if not result then - result = { id = id, name = keneanung.bashing.getDenizenName(id), affs = {} } - directTargetAccess[tostring(id)] = result - end - return result -end - -local doImport = function(importTable) - --Allow us to strip a full config file down to just the priorities - importTable = importTable.priorities or importTable - - local somethingChanged = false - - - --do the import - for area,_ in pairs(importTable) do - if #importTable[area] > 0 then - keneanung.bashing.configuration.priorities[area] = keneanung.bashing.configuration.priorities[area] or {} - somethingChanged = true - end - for _, denizenString in pairs(importTable[area]) do - if not table.contains(keneanung.bashing.configuration.priorities[area],denizenString) then - table.insert(keneanung.bashing.configuration.priorities[area], denizenString) - somethingChanged = true - end - end - end - - if somethingChanged then - raiseEvent("keneanung.bashing.settings.changed") - end -end - -keneanung.bashing.guhemImport = function() - doImport(huntVar.userAreaList) -end - -keneanung.bashing.export = function() - local directory = invokeFileDialog(false, "Which file do you want to export your priorities to?") - if directory ~= "" then -- If a folder was provided - table.save(directory .. "/Bashing-Export.lua", keneanung.bashing.configuration.priorities) -- Exporting to folder specified - kecho("Have exported priorities to " .. path .. "/Bashing-Export.lua") -- Messaging user - end -end - -keneanung.bashing.import = function() - local path = invokeFileDialog(true, "Which file do you want to add?") -- Requesting the specific file to be imported - if path ~= "" then -- Making sure that the file was specified - local importTable = {} - table.load(path, importTable) - doImport(importTable) - kecho("Import Completed") - end --if -end - -keneanung.bashing.manuallyTarget = function(what) - if not keneanung.bashing.configuration.manualTargetting then return end - local item = keneanung.bashing.getTargetObject(what) - if not item then return end - keneanung.bashing.targetList = { item } - sendGMCP('IRE.Target.Set "' .. item.id .. '"') - raiseEvent("keneanung.bashing.targetList.changed") - raiseEvent("keneanung.bashing.targetList.firstChanged", keneanung.bashing.targetList[1].id) - if waitingForManualTargetTimer then killTimer(waitingForManualTargetTimer) end - if waitingForManualTarget then - keneanung.bashing.setTarget() - startAttack() - end -end - -keneanung.bashing.load() -for _, file in ipairs(keneanung.bashing.configuration.filesToLoad) do - dofile(file) -end -tempTimer(0, [[raiseEvent("keneanung.bashing.loaded")]]) +local debugEnabled = false +local send = send +local directTargetAccess = {} +local afflictions = { + weakness = { + colour = "pale_green", + timer = 7 + }, + sensitivity = { + colour = "orange_red", + timer = 8 + }, + recklessness = { + colour = "yellow", + timer = 15 + }, + aeon = { + colour = "purple", + timer = 6 + }, + fear = { + colour = "orange", + timer = 8 + }, + clumsiness = { + colour = "forest_green", + timer = 7 + }, + inhibit = { + colour = "light_coral", + timer = 9 + }, + charm = { + colour = "magenta", + timer = 5 + }, + stun = { + colour = "black:yellow", + timer = 4 + }, + amnesia = { + colour = "LightGrey", + timer = 5 + }, +} + +local nonBattlerageAttainmentSkills = { + "Prevail", + "Portals", + "Battlerage", + "Market", + "Battle", + "Limitedportals", + "Independence", + "Embrace", + "Tradeskills", + "Theft", + "Craftsmanship", + "Multiclass", + "Sustenance", + "Dragonhood", + "Polymath", +} +local sessionGains = { } +local tripGains = { gold = 0, experience = 0 } + +local requestSkillDetails = {} +local battlerageSkills = {} +local rage = 0 + +local race = "" +local class = "" +local lastGoldChange +local lastGold +local lastXp + +local roomTargetStore = {} +local denizenCache = {} + +local waitingForManualTargetTimer +local waitingForManualTarget = false + +keneanung = keneanung or {} +keneanung.bashing = {} +keneanung.bashing.availableTargets = {} +keneanung.bashing.configuration = {} +keneanung.bashing.configuration.priorities = {} +keneanung.bashing.targetList = {} +keneanung.bashing.systems = {} +keneanung.bashing.battlerage = {} +keneanung.bashing.room = {} +keneanung.bashing.pausingAfflictions = {} +keneanung.bashing.trackih = false + +keneanung.bashing.attacking = 0 +keneanung.bashing.damage = 0 +keneanung.bashing.attacks = 0 +keneanung.bashing.healing = 0 +keneanung.bashing.lastHealth = 0 +keneanung.bashing.usedRageAttack = false +keneanung.bashing.usedBalanceAttack = false + +keneanung.bashing.configuration.enabled = false +keneanung.bashing.configuration.warning = 500 +keneanung.bashing.configuration.fleeing = 300 +keneanung.bashing.configuration.autoflee = true +keneanung.bashing.configuration.system = "auto" +keneanung.bashing.configuration.filesToLoad = {} +keneanung.bashing.configuration.targetLoyals = false +keneanung.bashing.configuration.lifetimeGains = { gold = 0, experience = 0 } +keneanung.bashing.configuration.manualTargetting = false +keneanung.bashing.configuration.waitForManualTarget = 2 + +local debugMessage = function(message, content) + if not debugEnabled then return end + echo(string.format("[%s]: %s", (debug.getinfo(2).name or "unknown"), message)) + if content then + display(content) + end +end + +local getTargetPrio = function(name) + local prios = keneanung.bashing.configuration.priorities[gmcp.Room.Info.area] + + debugMessage("prios for this area", prios) + + if not prios then + return + end + + debugMessage("target name", name) + + local prio = table.index_of(prios, name) + debugMessage("prio", prio) + return prio +end + +local kecho = function(what, command, popup) + + what = "\nkeneanung: " .. what + if command then + cechoLink(what, command, popup or "", true) + else + cecho(what) + end + +end + +local knownBattlerageSkillList = function() + if #requestSkillDetails == 0 then + local names = {} + for i, skill in ipairs(battlerageSkills) do + names[#names+1] = skill.name + end + return table.concat(names, " ") + end + + return("processing... try doing some things!") +end + +keneanung.bashing.configuration.requestBattlerageSkills = function() + kecho("Requesting battlerage skills...\n") + sendGMCP([[Char.Skills.Get {"group":"attainment"}]]) + send(" ") +end + +local sortDepthswalkerBattlerage = function() + + debugMessage("sorting brage for walkers", {battlerageSkills = battlerageSkills}) + + if class ~= "Depthswalker" or #battlerageSkills ~= 6 then return end + battlerageSkills[2], battlerageSkills[3], battlerageSkills[4] = battlerageSkills["curse"], battlerageSkills["nakail"], battlerageSkills["lash"] + + battlerageSkills["curse"].affliction = "aeon" + battlerageSkills["boinad"].affliction = "charm" + + battlerageSkills["erasure"].affsUsed = { + "amnesia", + "weakness" + } + + debugMessage("sorted brage for walkers", {battlerageSkills = battlerageSkills}) +end + +local sortPariahBattlerage = function() + + debugMessage("sorting brage for pariah", {battlerageSkills = battlerageSkills}) + + if class ~= "Pariah" or #battlerageSkills ~= 6 then return end + battlerageSkills[2], battlerageSkills[3], battlerageSkills[4] = battlerageSkills["symphony"], battlerageSkills["scour"], battlerageSkills["feast"] + + battlerageSkills["symphony"].affliction = "fear" + battlerageSkills["wail"].affliction = "clumsiness" + + battlerageSkills["spider"].affsUsed = { + "inhibit", + "sensitivity" + } + + battlerageSkills["scour"].command = "ACCURSED SCOUR %s" + battlerageSkills["scour"].rage = 17 + + debugMessage("sorted brage for pariah", {battlerageSkills = battlerageSkills}) +end + +local sortPsionBattlerage = function() + + debugMessage("sorting brage for psion", {battlerageSkills = battlerageSkills}) + + if class ~= "Psion" or #battlerageSkills ~= 6 then return end + battlerageSkills[2], battlerageSkills[3], battlerageSkills[4] = battlerageSkills["regrowth"], battlerageSkills["pulverise"], battlerageSkills["devastate"] + + battlerageSkills["terror"].affliction = "fear" + + + debugMessage("sorted brage for psion", {battlerageSkills = battlerageSkills}) +end + +local sortUnnamableBattlerage = function() + + debugMessage("sorting brage for unnamable", {battlerageSkills = battlerageSkills}) + + if class ~= "Unnamable" or #battlerageSkills ~= 6 then return end + battlerageSkills[2], battlerageSkills[3], battlerageSkills[4] = battlerageSkills["dread"], battlerageSkills["sunder"], battlerageSkills["destroy"] + + battlerageSkills["dread"].affliction = "fear" + battlerageSkills["entropy"].affliction = "aeon" + + battlerageSkills["onslaught"].affsUsed = { + "stun", + "sensitivity" + } + + debugMessage("sorted brage for unnamable", {battlerageSkills = battlerageSkills}) +end + +local sortProvokeBattlerage = function() + if battlerageSkills[1] and battlerageSkills[1].name:lower() == "provoke" then + local provoke = table.remove(battlerageSkills, 1) + table.insert(battlerageSkills, provoke) + debugMessage("Moved provoke to end of battlerageSkills", battlerageSkills) + end +end + +local requestAllSkillDetails = function() + while #requestSkillDetails > 0 do + sendGMCP(string.format([[Char.Skills.Get {"group": "attainment", "name": "%s"}]], requestSkillDetails[1])) + table.remove(requestSkillDetails,1) + end + send(" ",false) +end + +local migrateTo1Point8 = function() + if keneanung.bashing.configuration.attackcommand then + local migratedConfig = {} + migratedConfig.attackcommand = keneanung.bashing.configuration.attackcommand + keneanung.bashing.configuration.attackcommand = nil + migratedConfig.autoraze = keneanung.bashing.configuration.autoraze + keneanung.bashing.configuration.autoraze = nil + migratedConfig.razecommand = keneanung.bashing.configuration.razecommand + keneanung.bashing.configuration.razecommand = nil + migratedConfig.rageStrat = keneanung.bashing.configuration.rageStrat + keneanung.bashing.configuration.rageStrat = nil + migratedConfig.autorageraze = keneanung.bashing.configuration.autorageraze + keneanung.bashing.configuration.autorageraze = nil + + raiseEvent("keneanung.bashing.settings.changed") + end +end + +local startAttack = function() + local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] + system.startAttack() + gmod.enableModule("keneanung.bashing", "IRE.Display") + sendGMCP([[Core.Supports.Add ["IRE.Display 3"] ]]) -- register the GMCP module independently from gmod. +end + +local stopAttack = function() + local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] + system.stopAttack() + gmod.disableModule("keneanung.bashing", "IRE.Display") + sendGMCP([[Core.Supports.Remove ["IRE.Display"] ]]) -- unregister the GMCP module independently from gmod. +end + +keneanung.bashing.systems.svo = { + + startAttack = function() + svo.addbalanceful("do next attack", keneanung.bashing.nextAttack) + svo.donext() + end, + + stopAttack = function() + svo.removebalanceful("do next attack") + end, + + flee = function() + raiseEvent("keneanung.bashing.fleeing") + keneanung.bashing.systems.svo.stopAttack() + svo.dofreefirst(keneanung.bashing.fleeDirection) + end, + + warnFlee = function(avg) + svo.boxDisplay("Better run or get ready to die!", "orange") + end, + + notifyFlee = function(avg) + svo.boxDisplay("Running as you have not enough health left.", "red") + end, + + handleShield = function() + keneanung.bashing.shield = true + end, + + setup = function() + send = function(command, echoback) + debugMessage("send got called", {command = command, echoback = echoback }) + local useAlias = false + if command == "keneanungki" then + command = keneanung.bashing.configuration[class].attackcommand + useAlias = true + elseif command == "keneanungra" then + command = keneanung.bashing.configuration[class].razecommand + useAlias = true + end + if keneanung.bashing.attacking > 0 and useAlias then + command = command:gsub("&tar", keneanung.bashing.targetList[keneanung.bashing.attacking].id) + end + + local commands = command:split("/") + for _, part in ipairs(commands) do + svo.sendc(part, echoback) + end + end + end, + + teardown = function() + send = _G.send + end, + + unpause = function() + svo.donext() + end + +} + +keneanung.bashing.systems.wundersys = { + + startAttack = function() + if keneanung.bashing.attacking > 0 then + enableTrigger(keneanung.bashing.systems.wundersys.queueTrigger) + local command + if keneanung.bashing.configuration[class].attackcommand:find("&tar") then + command = keneanung.bashing.configuration[class].attackcommand + else + command = keneanung.bashing.configuration[class].attackcommand .. " &tar" + end + wsys.doradd(command) + end + end, + + stopAttack = function() + disableTrigger(keneanung.bashing.systems.wundersys.queueTrigger) + wsys.dorclear() + end, + + flee = function() + raiseEvent("keneanung.bashing.fleeing") + keneanung.bashing.systems.wundersys.stopAttack() + wsys.dofreeadd(keneanung.bashing.fleeDirection) + end, + + warnFlee = function(avg) + wsys.boxDisplay("Better run or get ready to die!", "orange") + end, + + notifyFlee = function(avg) + wsys.boxDisplay("Running as you have not enough health left.", "red") + end, + + handleShield = function() + if keneanung.bashing.configuration[class].autoraze then + local command + if keneanung.bashing.configuration[class].razecommand:find("&tar") then + command = keneanung.bashing.configuration[class].razecommand + else + command = keneanung.bashing.configuration[class].razecommand .. " &tar" + end + wsys.dofirst(command, 1) + end + keneanung.bashing.shield = true + end, + + brokeShield = function() + wsys.undo(true, 1) + end, + + setup = function() + keneanung.bashing.systems.wundersys.queueTrigger = tempTrigger("[System]: Running queued eb command: DOR", + [[ + local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] + keneanung.bashing.attacks = keneanung.bashing.attacks + 1 + local avgDmg = keneanung.bashing.damage / keneanung.bashing.attacks + local avgHeal = keneanung.bashing.healing / keneanung.bashing.attacks + + local estimatedDmg = avgDmg * 2 - avgHeal + + local fleeat = keneanung.bashing.calcFleeValue(keneanung.bashing.configuration.fleeing) + + local warnat = keneanung.bashing.calcFleeValue(keneanung.bashing.configuration.warning) + + if estimatedDmg > gmcp.Char.Vitals.hp - fleeat and keneanung.bashing.configuration.autoflee then + + system.notifyFlee(estimatedDmg) + + system.flee() + + else + if estimatedDmg > gmcp.Char.Vitals.hp - warnat then + + system.warnFlee(estimatedDmg) + + end + end + ]]) + disableTrigger(keneanung.bashing.systems.wundersys.queueTrigger) + registerAnonymousEventHandler("do action run", "keneanung.bashing.systems.wundersys.doActionRun") + end, + + teardown = function() + if keneanung.bashing.systems.wundersys.queueTrigger then + killTrigger(keneanung.bashing.systems.wundersys.queueTrigger) + end + end, + + doActionRun = function(_, command) + local razecommand + if keneanung.bashing.configuration[class].razecommand:find("&tar") then + razecommand = keneanung.bashing.configuration[class].razecommand + else + razecommand = keneanung.bashing.configuration[class].razecommand .. " &tar" + end + if command == razecommand then + keneanung.bashing.shield = false + end + end, + + pause = function() + keneanung.bashing.systems.wundersys.stopAttack() + end, + + unpause = function() + keneanung.bashing.systems.wundersys.startAttack() + end +} + +keneanung.bashing.systems.none = { + + firstAttack = false, + + startAttack = function() + timeframe("keneanung.bashing.systems.none.firstAttack", {0, true}, {1, false}) + keneanung.bashing.systems.none.doAttack() + end, + + doAttack = function() + if keneanung.bashing.attacking > 0 then + + if keneanung.bashing.usedBalanceAttack and not keneanung.bashing.systems.none.firstAttack then + return true + end + + enableTrigger(keneanung.bashing.systems.none.queueTrigger) + send("queue add eqbal keneanungki", false) + + timeframe("keneanung.bashing.usedBalanceAttack", {0, true}, {0.5, false}) + end + end, + + stopAttack = function() + disableTrigger(keneanung.bashing.systems.none.queueTrigger) + send("cq all") + end, + + flee = function() + raiseEvent("keneanung.bashing.fleeing") + keneanung.bashing.systems.none.stopAttack() + send("queue prepend eqbal " .. keneanung.bashing.fleeDirection) + end, + + warnFlee = function(avg) + echo("Better run or get ready to die!") + end, + + notifyFlee = function(avg) + echo("Running as you have not enough health left.") + end, + + handleShield = function() + keneanung.bashing.shield = true + if keneanung.bashing.configuration[class].autoraze then + local command + send("queue prepend eqbal keneanungra", false) + end + end, + + brokeShield = function() + send("cq all") + send("queue add eqbal keneanungki", false) + end, + + setup = function() + keneanung.bashing.systems.none.queueTrigger = tempRegexTrigger("^\\[System\\]: Running queued eb command: (KENEANUNGKI|KENEANUNGRA)$", + [[ + local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] + keneanung.bashing.attacks = keneanung.bashing.attacks + 1 + local avgDmg = keneanung.bashing.damage / keneanung.bashing.attacks + local avgHeal = keneanung.bashing.healing / keneanung.bashing.attacks + + local estimatedDmg = avgDmg * 2 - avgHeal + + local fleeat = keneanung.bashing.calcFleeValue(keneanung.bashing.configuration.fleeing) + + local warnat = keneanung.bashing.calcFleeValue(keneanung.bashing.configuration.warning) + + if estimatedDmg > gmcp.Char.Vitals.hp - fleeat and keneanung.bashing.configuration.autoflee then + + system.notifyFlee(estimatedDmg) + + system.flee() + + else + if estimatedDmg > gmcp.Char.Vitals.hp - warnat then + + system.warnFlee(estimatedDmg) + + end + if matches[2] == "KENEANUNGKI" then + keneanung.bashing.systems.none.doAttack() + else + keneanung.bashing.shield = false + end + end + ]]) + disableTrigger(keneanung.bashing.systems.none.queueTrigger) + end, + + teardown = function() + if keneanung.bashing.systems.none.queueTrigger then + killTrigger(keneanung.bashing.systems.none.queueTrigger) + end + end, + + pause = function() + disableTrigger(keneanung.bashing.systems.none.queueTrigger) + end, + + unpause = function() + keneanung.bashing.systems.none.startAttack() + end + +} + +local function sendRageAttack(attack) + debugMessage("sending rage attack", attack) + send(attack:format(keneanung.bashing.targetList[keneanung.bashing.attacking].id), false) + keneanung.bashing.usedRageAttack = true + raiseEvent("keneanung.bashing.settings.changed") + tempTimer(1, "keneanung.bashing.usedRageAttack = false") +end + +local function rageRazeFunction() + if keneanung.bashing.shield then + if keneanung.bashing.configuration[class].autorageraze and keneanung.bashing.rageAvailable(3) then + send(battlerageSkills[3].command:format(keneanung.bashing.targetList[keneanung.bashing.attacking].id), false) + keneanung.bashing.shield = false + local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] + if system.brokeShield then + system.brokeShield() + end + return true + else + return false + end + end +end + +keneanung.bashing.battlerage.none = function(rage) +end + +keneanung.bashing.battlerage.simple = function(rage) + if keneanung.bashing.attacking == 0 then return end + + debugMessage("running 'simple' rage strategy", + { + rage = rage, + shield = keneanung.bashing.shield, + rageraze = keneanung.bashing.configuration[class].autorageraze, + rageSkills = battlerageSkills + } + ) + + if not rageRazeFunction() then + if keneanung.bashing.rageAvailable(4) then + sendRageAttack(battlerageSkills[4].command) + elseif + keneanung.bashing.rageAvailable(1) and + ((not battlerageSkills[4].skillKnown) or + rage >= (battlerageSkills[1].rage + battlerageSkills[4].rage)) + then + sendRageAttack(battlerageSkills[1].command) + end + end +end + +keneanung.bashing.battlerage.simplereverse = function(rage) + if keneanung.bashing.attacking == 0 then return end + + debugMessage("running 'simplereverse' rage strategy", + { + rage = rage, + shield = keneanung.bashing.shield, + rageraze = keneanung.bashing.configuration[class].autorageraze, + rageSkills = battlerageSkills + } + ) + + if not rageRazeFunction() then + if keneanung.bashing.rageAvailable(1) then + sendRageAttack(battlerageSkills[1].command) + elseif keneanung.bashing.rageAvailable(4) then + sendRageAttack(battlerageSkills[4].command) + end + end +end + +local aliases = { + ["razecommand"] = "keneanungra", + ["attackcommand"] = "keneanungki", +} + +local getSystem = function(tbl, index) + local systemName + if index == "auto" then + if svo then + return keneanung.bashing.systems.svo + elseif wsys and wsys.myVersion then + return keneanung.bashing.systems.wundersys + else + return keneanung.bashing.systems.none + end + end + kecho("Something went completely wrong: You are using an unknown system ('"..index.."'). Please use 'kconfig bashing system ' to correct this.") + return nil +end + +setmetatable(keneanung.bashing.systems, { __index = getSystem } ) + +keneanung.bashing.isPossibleTarget = function(targetName, area) + if not area then + area = gmcp.Room.Info.area + end + + local prios = keneanung.bashing.configuration.priorities[area] or {} + + return table.contains(prios, targetName) +end + +keneanung.bashing.addPossibleTarget = function(targetName) + + local prios = keneanung.bashing.configuration.priorities + local area = gmcp.Room.Info.area + + if prios[area] == nil then + prios[area] = {} + kecho("Added the new area " .. area .. " to the configuration.") + end + + if not table.contains(prios[area], targetName) then + + local before = keneanung.bashing.idOnly(keneanung.bashing.targetList) + + table.insert(prios[area], targetName) + kecho("Added the new possible target " .. targetName .. " to the end of the priority list.") + keneanung.bashing.configuration.priorities = prios + raiseEvent("keneanung.bashing.settings.changed") + keneanung.bashing.save() + + for _, item in ipairs(keneanung.bashing.room) do + keneanung.bashing.addTarget(item) + end + + local after = keneanung.bashing.idOnly(keneanung.bashing.targetList) + + keneanung.bashing.emitEventsIfChanged(before, after) + end +end + +keneanung.bashing.showAreas = function() + keneanung.bashing.showAreasFiltered(keneanung.bashing.configuration.priorities) +end + +keneanung.bashing.showAreasFiltered = function(filtered) + + kecho("Which area would you like to configure:\n") + for area, _ in pairs(filtered) do + cechoLink(" (" .. area .. ")\n",[[keneanung.bashing.managePrios("]]..area..[[")]],"Show priority list for '" .. area .."",true) + end +end + +keneanung.bashing.managePrios = function(area) + + local possibleMatches = {} + for areaName, _ in pairs(keneanung.bashing.configuration.priorities) do + if areaName:lower() == area:lower() then + possibleMatches[areaName] = true + break + end + if areaName:lower():find(area:lower()) then + possibleMatches[areaName] = true + end + end + + if table.is_empty(possibleMatches) then + kecho("No targets for " .. area .. " found yet!\n") + return + elseif table.size(possibleMatches) == 1 then + for areaName, _ in pairs(possibleMatches) do + area = areaName + end + else + keneanung.bashing.showAreasFiltered(possibleMatches) + return + end + + local prios = keneanung.bashing.configuration.priorities[area] + + kecho("Possible targets for " .. area .. ":\n") + for num, item in ipairs(prios) do + echo(" ") + cechoLink("(^^)", [[keneanung.bashing.shuffleUp("]]..area..[[", ]] .. num .. [[)]], "Shuffle " .. item .. " one step up.", true) + echo(" ") + cechoLink("(vv)", [[keneanung.bashing.shuffleDown("]]..area..[[", ]] .. num .. [[)]], "Shuffle " .. item .. " one step down.", true) + echo(" ") + cechoLink("(DD)", [[keneanung.bashing.delete("]]..area..[[", ]] .. num .. [[)]], "Delete " .. item .. " from list.", true) + resetFormat() + echo(" " .. item .. "\n") + end +end + +keneanung.bashing.shuffleDown = function(area, num) + + local prios = keneanung.bashing.configuration.priorities[area] + + if num < #prios then + prios[num], prios[num+1] = prios[num+1], prios[num] + end + keneanung.bashing.save() + + keneanung.bashing.managePrios(area) + + raiseEvent("keneanung.bashing.settings.changed") +end + +keneanung.bashing.shuffleUp = function(area, num) + + local prios = keneanung.bashing.configuration.priorities[area] + + if num > 1 then + prios[num], prios[num-1] = prios[num-1], prios[num] + end + keneanung.bashing.save() + + keneanung.bashing.managePrios(area) + + raiseEvent("keneanung.bashing.settings.changed") +end + +keneanung.bashing.delete = function(area, num) + + local prios = keneanung.bashing.configuration.priorities[area] + + table.remove(prios, num) + + keneanung.bashing.save() + + keneanung.bashing.managePrios(area) + + raiseEvent("keneanung.bashing.settings.changed") +end + +keneanung.bashing.deleteByName = function(area, name) + + local prios = keneanung.bashing.configuration.priorities[area] + + for num, prioName in ipairs(prios) do + if name == prioName then + keneanung.bashing.delete(area, num) + return + end + end +end + +keneanung.bashing.save = function() + if string.char(getMudletHomeDir():byte()) == "/" then + _sep = "/" + else + _sep = "\\" + end -- if + local savePath = getMudletHomeDir() .. _sep .. "keneanung_bashing.lua" + table.save(savePath, keneanung.bashing.configuration) + +end -- func + +keneanung.bashing.load = function() + if string.char(getMudletHomeDir():byte()) == "/" + then _sep = "/" + else _sep = "\\" + end -- if + local savePath = getMudletHomeDir() .. _sep .. "keneanung_bashing.lua" + if (io.exists(savePath)) then + table.load(savePath, keneanung.bashing.configuration) + end -- if + +end -- func + +keneanung.bashing.showConfig = function() + kecho( + string.format( + "Bashing is %s", + keneanung.bashing.configuration.enabled and "on" or "off" + ), + "keneanung.bashing.toggle('enabled', 'Bashing')", + string.format( + "Turn bashing %s", + keneanung.bashing.configuration.enabled and "off" or "on" + ) + ) + + kecho( + string.format( + "Automatic fleeing is %s", + keneanung.bashing.configuration.autoflee and "on" or "off" + ), + "keneanung.bashing.toggle('autoflee', 'Fleeing')", + string.format( + "Turn fleeing %s", + keneanung.bashing.configuration.autoflee and "off" or "on" + ) + ) + + kecho( + string.format( + "Warning at a security threshhold of %s health", + keneanung.bashing.configuration.warning + ), + "clearCmdLine() appendCmdLine('kconfig bashing warnat ')", + "Set warn threshold." + ) + + kecho( + string.format( + "Fleeing at a security threshhold of %s health", + keneanung.bashing.configuration.fleeing + ), + "clearCmdLine() appendCmdLine('kconfig bashing fleeat ')", + "Set flee threshold." + ) + + kecho( + string.format( + "Attack is set to %s", + keneanung.bashing.configuration[class].attackcommand + ), + "clearCmdLine() appendCmdLine('kconfig bashing attackcommand ')", + "Set attack." + ) + + kecho( + string.format( + "Autoraze is %s", + keneanung.bashing.configuration[class].autoraze and "on" or "off" + ), + "keneanung.bashing.toggle('autoraze', 'Autorazing')", + string.format( + "Turn autorazing %s", + keneanung.bashing.configuration[class].autoraze and "off" or "on" + ) + ) + + kecho( + string.format( + "Special attack on shielding is set to %s", + keneanung.bashing.configuration[class].razecommand + ), + "clearCmdLine() appendCmdLine('kconfig bashing razecommand ')", + "Set attack to raze shields." + ) + + kecho( + string.format( + "Razing shields with rage is %s", + keneanung.bashing.configuration[class].autorageraze and "on" or "off" + ), + "keneanung.bashing.toggle('autorageraze', 'Autorazing with rage')", + string.format( + "Turn autorazing with rage %s", + keneanung.bashing.configuration[class].autorageraze and "off" or "on" + ) + ) + + kecho( + string.format( + "Currently using this battlerage strategy: %s", + keneanung.bashing.configuration[class].rageStrat + ), + "clearCmdLine() appendCmdLine('kconfig bashing ragestrat ')", + "Set battlerage strategy to use." + ) + + kecho( + string.format( + "Currently using this system: %s", + keneanung.bashing.configuration.system + ), + "clearCmdLine() appendCmdLine('kconfig bashing system ')", + "Set system to use." + ) + + kecho( + string.format( + "Considering loyals for fallback targets is %s", + keneanung.bashing.configuration.targetLoyals and "on" or "off" + ), + "keneanung.bashing.toggle('targetLoyals', 'Falling back to loyal targets')", + string.format( + "Turn considering loyals for fallback targets %s", + keneanung.bashing.configuration.targetLoyals and "off" or "on" + ) + ) + + kecho( + string.format( + "Manual targetting is %s", + keneanung.bashing.configuration.manualTargetting and "on" or "off" + ), + "keneanung.bashing.toggle('manualTargetting', 'Manual targetting')", + string.format( + "Turn manual targetting %s", + keneanung.bashing.configuration.manualTargetting and "off" or "on" + ) + ) + + kecho( + string.format( + "Waiting for %s seconds for a new target before stopping, if attacking manually", + keneanung.bashing.configuration.waitForManualTarget + ), + "clearCmdLine() appendCmdLine('kconfig bashing waitfortarget ')", + "Set time to wait for a target." + ) + + kecho( + string.format( + "Battlerage skills identified (reset): " .. knownBattlerageSkillList() + ), + "keneanung.bashing.configuration.requestBattlerageSkills()", + "Request and parse battlerage skills again." + ) + + echo("\n") + + kecho("Loading these additional files on startup: ") + cechoLink("(Add new file)", "keneanung.bashing.addFile()", "Add a new file to load on startup", true) + for num, path in ipairs(keneanung.bashing.configuration.filesToLoad) do + echo("\n " .. path .. " (") + cechoLink("(Delete)", "keneanung.bashing.deleteFile(" .. num .. ")", "Don't load this file anymore", true) + end + echo("\n") + + kecho("Version: " .. keneanung.bashing.version .. "") +end + +keneanung.bashing.toggle = function(what, print) + local toPrint + if what == "autoraze" or what == "autorageraze" then + keneanung.bashing.configuration[class][what] = not keneanung.bashing.configuration[class][what] + toPrint = keneanung.bashing.configuration[class][what] and "enabled" or "disabled" + else + keneanung.bashing.configuration[what] = not keneanung.bashing.configuration[what] + toPrint = keneanung.bashing.configuration[what] and "enabled" or "disabled" + end + kecho(print .. " " .. toPrint .. "\n" ) + raiseEvent("keneanung.bashing.settings.changed") + keneanung.bashing.save() +end + +keneanung.bashing.shielded = function(what) + if keneanung.bashing.attacking > 0 and what == keneanung.bashing.targetList[keneanung.bashing.attacking].name then + local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] + system.handleShield() + end +end + +keneanung.bashing.flee = function() + local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] + system.flee() + keneanung.bashing.clearTarget() + kecho("New order. Tactical retreat.\n") +end + +keneanung.bashing.attackButton = function(toggle, echoback) + if echoback == nil then echoback = true end + if (keneanung.bashing.attacking == 0 and toggle ~= false) or toggle then + if keneanung.bashing.setTarget() then + startAttack() + if echoback then kecho("Nothing will stand in our way.\n") end + else + if echoback then kecho("Nothing to target, boss.\n") end + end + else + keneanung.bashing.clearTarget() + stopAttack() + if echoback then kecho("Lets save them for later.\n") end + end +end + +keneanung.bashing.setFlee = function(where) + keneanung.bashing.fleeDirection = where + raiseEvent("keneanung.bashing.settings.changed") + kecho("Fleeing to the " .. keneanung.bashing.fleeDirection .. "\n" ) +end + +keneanung.bashing.setThreshold = function(newValue, what) + keneanung.bashing.configuration[what] = matches[2] + raiseEvent("keneanung.bashing.settings.changed") + kecho(what:title().." with a security threshhold of " .. keneanung.bashing.configuration[what] .. " health\n" ) + keneanung.bashing.save() +end + +keneanung.bashing.setWaitForTarget = function(amount) + keneanung.bashing.configuration.waitForManualTarget = tonumber(amount) or 2 + raiseEvent("keneanung.bashing.settings.changed") + kecho("Waiting " .. keneanung.bashing.configuration.waitForManualTarget .. " seconds for a new target\n" ) + keneanung.bashing.save() +end + +keneanung.bashing.nextAttack = function() + if keneanung.bashing.configuration.enabled == false then + return false + end + + if keneanung.bashing.usedBalanceAttack then + return true + end + + if #keneanung.bashing.pausingAfflictions > 0 then + return false + end + + local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] + + keneanung.bashing.attacks = keneanung.bashing.attacks + 1 + + if #keneanung.bashing.targetList > 0 then + local avg = keneanung.bashing.damage / keneanung.bashing.attacks + + local fleeat = keneanung.bashing.calcFleeValue(keneanung.bashing.configuration.fleeing) + + local warnat = keneanung.bashing.calcFleeValue(keneanung.bashing.configuration.warning) + + if avg > keneanung.bashing.lastHealth - fleeat and keneanung.bashing.configuration.autoflee then + + system.notifyFlee(avg) + + system.flee() + + else + if avg > keneanung.bashing.lastHealth - warnat then + + system.warnFlee(avg) + + end + + local attack = (keneanung.bashing.shield and keneanung.bashing.configuration[class].autoraze) and "keneanungra" or "keneanungki" + send(attack, false) + keneanung.bashing.shield = false + keneanung.bashing.usedBalanceAttack = true + tempTimer( 0.5, "keneanung.bashing.usedBalanceAttack = false") + return true + + end + end + + keneanung.bashing.clearTarget() + stopAttack() + return false + +end + +local roomItemCallbackWorker = function(event) + + if gmcp.Char.Items[event:match("%w+$")].location ~= "room" or keneanung.bashing.configuration.enabled == false then + return + end + + debugMessage(event, { room=keneanung.bashing.room, targetList=keneanung.bashing.targetList }) + + local backup = keneanung.bashing.targetList + local directAccessBackup = directTargetAccess + local before = keneanung.bashing.idOnly(keneanung.bashing.targetList) + + if(event == "gmcp.Char.Items.Add") then + local item = gmcp.Char.Items.Add.item + keneanung.bashing.room[#keneanung.bashing.room + 1] = item + if item.attrib and item.attrib:find("m") and not item.attrib:find("d") then + keneanung.bashing.seenDenizen(item.id, item.name) + item = keneanung.bashing.getTargetObject(item.id) + if not keneanung.bashing.configuration.manualTargetting then + keneanung.bashing.addTarget(item) + end + end + end + + if(event == "gmcp.Char.Items.List") then + keneanung.bashing.availableTargets = {} + if not keneanung.bashing.configuration.manualTargetting then + --restore targets we had when we were in the room last + local storedTargets = roomTargetStore[gmcp.Room.Info.num] + + if storedTargets then + keneanung.bashing.targetList = storedTargets.targetList + end + + local targetList = {} + -- make sure our targets stay at the same place! + for index, targ in ipairs(keneanung.bashing.targetList) do + -- still considered a target? + if getTargetPrio(targ.name) then + -- search if that target possibly left the room + local found = false + for _, item in ipairs(gmcp.Char.Items.List.items) do + if item.id == targ.id then + found = true + break + end + end + -- still there? Add it in the old place + if found then + targetList[#targetList + 1] = targ + end + end + end + keneanung.bashing.targetList = targetList + end + + keneanung.bashing.room = {} + for _, item in ipairs(gmcp.Char.Items.List.items) do + keneanung.bashing.room[#keneanung.bashing.room + 1] = item + if item.attrib and item.attrib:find("m") and not item.attrib:find("d") then + keneanung.bashing.seenDenizen(item.id, item.name) + item = keneanung.bashing.getTargetObject(item.id) + if not keneanung.bashing.configuration.manualTargetting then + keneanung.bashing.addTarget(item) + end + end + end + end + + if(event == "gmcp.Char.Items.Remove") then + local item = gmcp.Char.Items.Remove.item + for num, itemRoom in ipairs(keneanung.bashing.room) do + if (itemRoom.id * 1) == (item.id * 1) then + table.remove(keneanung.bashing.room, num) + break + end + end + + keneanung.bashing.removeTarget(item) + end + + local after = keneanung.bashing.idOnly(keneanung.bashing.targetList) + + debugMessage("got before and after", {before=before, after=after, intersection=table.n_intersection(before, after)}) + + if #before == #after and #table.n_intersection(before, after) == #before then + keneanung.bashing.targetList = backup + directTargetAccess = directAccessBackup + return + end + + keneanung.bashing.emitEventsIfChanged(before, after) + + debugMessage("after", { room=keneanung.bashing.room, targetList=keneanung.bashing.targetList }) +end + +keneanung.bashing.roomItemCallback = function(event) + if event == "gmcp.Char.Items.Add" or event == "gmcp.Char.Items.Remove" then + roomItemCallbackWorker(event) + end +end + +keneanung.bashing.sysDataSendRequestCallback = function(_, data) + debugMessage("data gets sent", {data = data}) + local lowerData = data:lower() + if + lowerData:starts("class switch") or -- class switch + lowerData:starts("dragonform") or -- dragon + lowerData:starts("lesserform") or -- from dragon to normal + lowerData:starts("prevail") or -- elemental lord + lowerData:starts("forsake") -- from elemental to normal + then + sendGMCP('Core.Supports.Add ["IRE.Display 3"]') + end + + if (lowerData == "ih" or lowerData:starts("ih ")) and keneanung.bashing.configuration.enabled then + keneanung.bashing.trackih = true + end +end + +keneanung.bashing.emitEventsIfChanged = function( before, after) + if keneanung.bashing.difference(before, after) then + raiseEvent("keneanung.bashing.targetList.changed") + if before[1] ~= after[1] then + raiseEvent("keneanung.bashing.targetList.firstChanged", after[1]) + end + end +end + +keneanung.bashing.difference = function( list1, list2 ) + + if #list1 ~= #list2 then + return true + end + + for num, value in ipairs(list1) do + if value ~= list2[num] then return true end + end + + return false + +end + +keneanung.bashing.idOnly = function( list ) + + local ret = {} + + for _, value in ipairs(list) do + + table.insert(ret, value.id) + + end + + return ret + +end + +keneanung.bashing.addTarget = function(item) + + local targets = keneanung.bashing.targetList + local insertAt + + debugMessage("addTarget", item) + + local targetPrio = getTargetPrio(item.name) + + if not targetPrio then + return + end + + local targetObject = { id = item.id, name = item.name, affs = {} } + + if #targets == 0 then + table.insert(targets, targetObject) + else + + -- Small safeguard against adding something twice + for _, tar in ipairs(targets) do + if tar.id == item.id then + return + end + end + + local iStart,iEnd,iMid = 1,#targets,0 + local found = false + -- Binary Search + while iStart <= iEnd do + -- calculate middle + iMid = math.floor( (iStart+iEnd)/2 ) + -- get compare value + local existingPrio = getTargetPrio(targets[iMid].name) + -- get all values that match + if targetPrio == existingPrio then + insertAt = iMid + found = true + break + elseif existingPrio == nil or targetPrio < existingPrio then + iEnd = iMid - 1 + else + iStart = iMid + 1 + end + + end + + if not found then + insertAt = iStart + end + + if insertAt <= keneanung.bashing.attacking and #keneanung.bashing.targetList >= keneanung.bashing.attacking then + insertAt = keneanung.bashing.attacking + 1 + end + + table.insert(targets, insertAt, item) + + end + + if directTargetAccess[item.id] then + for aff, timer in pairs(directTargetAccess[item.id].affs) do + targetObject[aff] = timer + end + end + + directTargetAccess[item.id] = targetObject + + keneanung.bashing.targetList = targets + +end + +keneanung.bashing.removeTarget = function(item) + + local targets = keneanung.bashing.targetList + local number + + for num, itemTarget in ipairs(targets) do + if (itemTarget.id * 1) == (item.id * 1) then + number = num + break + end + end + + if number then + table.remove(targets, number) + if number <= keneanung.bashing.attacking then + keneanung.bashing.attacking = keneanung.bashing.attacking - 1 + keneanung.bashing.setTarget() + end + for _, timer in pairs(directTargetAccess[item.id].affs) do + killTimer(timer) + end + directTargetAccess[item.id] = nil + if keneanung.bashing.attacking == 0 and keneanung.bashing.configuration.manualTargetting then + waitingForManualTarget = true + waitingForManualTargetTimer = tempTimer(keneanung.bashing.configuration.waitForManualTarget, function() waitingForManualTarget = false end) + end + end + + keneanung.bashing.targetList = targets + +end + +keneanung.bashing.prioListChangedCallback = function() + kecho("Priority list changed to:\n") + for _, tar in ipairs(keneanung.bashing.targetList) do + cecho(" " .. tar.name .. "\n") + end +end + +keneanung.bashing.roomMessageCallback = function() + if keneanung.bashing.lastRoom == nil then + keneanung.bashing.lastRoom = gmcp.Room.Info.num + keneanung.bashing.fleeDirection = "north" + end + + if keneanung.bashing.lastRoom == gmcp.Room.Info.num then + return + end + + if not keneanung.bashing.configuration.manualTargetting then + roomTargetStore[keneanung.bashing.lastRoom] = { + targetList = keneanung.bashing.targetList, + } + end + + keneanung.bashing.damage = 0 + keneanung.bashing.healing = 0 + keneanung.bashing.attacks = 0 + + if gmcp.Char.Vitals.hp then + keneanung.bashing.lastHealth = gmcp.Char.Vitals.hp * 1 + end + + keneanung.bashing.shield = false + if keneanung.bashing.attacking > 0 then + keneanung.bashing.clearTarget() + stopAttack() + end + local exits = getRoomExits(gmcp.Room.Info.num) or gmcp.Room.Info.exits + local found = false + + if exits ~= {} then + for direction, num in pairs(exits) do + if num == keneanung.bashing.lastRoom then + keneanung.bashing.fleeDirection = direction + found = true + break + end + end + end + + if not found and not gmcp.Room.Info.ohmap then + kecho("WARNING: No exit to flee found, reusing " .. keneanung.bashing.fleeDirection .. ".\n") + end + + keneanung.bashing.lastRoom = gmcp.Room.Info.num + + roomItemCallbackWorker("gmcp.Char.Items.List") -- update the room item list now, because now we know if we changed the area. + -- also be optimistic that there is no other items list in between +end + +keneanung.bashing.vitalsChangeRecord = function() + + if keneanung.bashing.attacking == 0 then return end + + if gmcp.Char.Vitals.hp then + + local difference = keneanung.bashing.lastHealth - gmcp.Char.Vitals.hp + + if difference > 0 then + keneanung.bashing.damage = keneanung.bashing.damage + difference + elseif difference < 0 then + keneanung.bashing.healing = keneanung.bashing.healing + math.abs(difference) + end + + keneanung.bashing.lastHealth = gmcp.Char.Vitals.hp * 1 + end + + for _, stat in ipairs(gmcp.Char.Vitals.charstats) do + local rageAmount = stat:match("^Rage: (%d+)$") + if rageAmount then + rage = tonumber(rageAmount) + break + end + end + + keneanung.bashing.battlerage[keneanung.bashing.configuration[class].rageStrat](rage, battlerageSkills) + +end + +keneanung.bashing.buttonActionsCallback = function() + keneanung.bashing.battlerage[keneanung.bashing.configuration[class].rageStrat](rage, battlerageSkills) +end + +keneanung.bashing.charStatusCallback = function() + local somethingChanged = false + if race ~= gmcp.Char.Status.race then + debugMessage("Race changed") + somethingChanged = true + race = gmcp.Char.Status.race + end + + if class ~= gmcp.Char.Status.class then + debugMessage("Class changed") + somethingChanged = true + class = gmcp.Char.Status.class + end + + if somethingChanged then + keneanung.bashing.configuration.requestBattlerageSkills() -- rerequest attainment abilities + migrateTo1Point8() + if not keneanung.bashing.configuration[class] then + local newClassConfig = {} + newClassConfig.autoraze = false + newClassConfig.razecommand = "none" + newClassConfig.attackcommand = "kill" + newClassConfig.rageStrat = "simple" + keneanung.bashing.configuration[class] = newClassConfig + kecho("Seen new class " .. class .. ". Default config set.") + end + keneanung.bashing.setAlias("attackcommand") + keneanung.bashing.setAlias("razecommand") + sendGMCP([[Core.Supports.Remove ["IRE.Display"] ]]) + end + + debugMessage("Going to calculate gold gains", { lastGoldChange = lastGoldChange, lastGold = lastGold } ) + + local goldNumber = tonumber(gmcp.Char.Status.gold) + local goldChange = goldNumber - (lastGold or 0) + + debugMessage("Got new gold numbers", { goldChange = goldChange, goldNumber = goldNumber } ) + + local lifetimeGains = keneanung.bashing.configuration.lifetimeGains + + if lastGoldChange ~= nil then -- On login, skip this + + if goldChange + lastGoldChange ~= 0 and goldChange > 0 then -- We only want to count + -- real changes (not + sessionGains.gold = sessionGains.gold + goldChange -- taking from pack) and + tripGains.gold = tripGains.gold + goldChange -- gold gains. + lifetimeGains.gold = lifetimeGains.gold + goldChange + + end + + end + + lastGoldChange = goldChange + lastGold = goldNumber + + local newXp = gmcp.Char.Status.level:match("^(%d+)") * 100 + gmcp.Char.Status.xp:match("(.+)%%") + + debugMessage("Calculating experience gain", { lastXp = lastXp, newXp = newXp }) + + if lastXp ~= nil then + + sessionGains.experience = sessionGains.experience + newXp - lastXp + tripGains.experience = tripGains.experience + newXp - lastXp + lifetimeGains.experience = lifetimeGains.experience + newXp - lastXp + + end + + lastXp = newXp +end + +local proneAfflictions = { + "prone", + "stun", + "paralysis", + "entangled", + "webbed", + "transfixation", + "impaled", + "bound", + "aeon", +} + +keneanung.bashing.pauseOnAffliction = function(affliction) + affliction = affliction:lower() + if table.contains(proneAfflictions, affliction) then + local pAffs = keneanung.bashing.pausingAfflictions + if not table.contains(pAffs, affliction) then + pAffs[#pAffs + 1] = affliction + local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] + if system.pause then + system.pause() + end + end + end +end + +keneanung.bashing.unpauseOnHealing = function(affliction) + affliction = affliction:lower() + if table.contains(proneAfflictions, affliction) then + local pAffs = keneanung.bashing.pausingAfflictions + local index = 0 + for i, aff in ipairs(pAffs) do + if aff == affliction then + index = i + break + end + end + if index > 0 then + table.remove(pAffs, index) + end + if #pAffs == 0 then + local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] + if system.unpause and keneanung.bashing.attacking > 0 then + system.unpause() + end + end + end +end + +keneanung.bashing.afflictionCallback = function(_, origMessage) + if origMessage == "gmcp.Char.Afflictions.Add" then + keneanung.bashing.pauseOnAffliction(gmcp.Char.Afflictions.Add.name) + elseif origMessage == "gmcp.Char.Afflictions.Remove" then + keneanung.bashing.unpauseOnHealing(gmcp.Char.Afflictions.Remove[1]) + end +end + +keneanung.bashing.setCommand = function(command, what) + keneanung.bashing.configuration[class][command] = what + kecho(command .. " is now " .. keneanung.bashing.configuration[class][command] .. "\n" ) + keneanung.bashing.setAlias(command) + keneanung.bashing.save() + raiseEvent("keneanung.bashing.settings.changed") +end + +keneanung.bashing.setTarget = function() + if #keneanung.bashing.targetList == 0 then + local tar + local targetSet = false + + if target ~= nil and target ~='' and target:lower() ~= "none" then + tar = target + elseif gmcp.Char.Status.target ~= "None" then + tar = gmcp.Char.Status.target + end + + debugMessage("set tar", tar) + + if tar ~= nil then + + for _, item in ipairs(keneanung.bashing.room) do + if item.attrib and item.attrib:find("m") and not item.attrib:find("d") and item.name:lower():find(tar:lower()) then + if keneanung.bashing.configuration.targetLoyals or not item.attrib:find("x") then + keneanung.bashing.targetList[#keneanung.bashing.targetList + 1]= { + id = item.id, + name = item.name + } + targetSet = true + end + end + end + end + if not targetSet then + keneanung.bashing.clearTarget() + stopAttack() + return + end + end + if keneanung.bashing.attacking == 0 or keneanung.bashing.targetList[keneanung.bashing.attacking].id ~= gmcp.IRE.Target.Info.id then + keneanung.bashing.attacking = keneanung.bashing.attacking + 1 + end + debugMessage("setting target", keneanung.bashing.targetList[keneanung.bashing.attacking]) + sendGMCP('IRE.Target.Set "' .. keneanung.bashing.targetList[keneanung.bashing.attacking].id .. '"') + return keneanung.bashing.attacking ~= 0 +end + +keneanung.bashing.clearTarget = function() + if gmcp.IRE.Target and gmcp.IRE.Target.Set ~= "" then + debugMessage("clearing target") + sendGMCP('IRE.Target.Set "0"') + end + keneanung.bashing.attacking = 0 +end + +keneanung.bashing.login = function() + gmod.enableModule("keneanung.bashing", "IRE.Target") + sendGMCP([[Core.Supports.Add ["IRE.Target 1"] ]]) -- register the GMCP module independently from gmod. + sendGMCP([[Char.Skills.Get {"group":"attainment"}]]) + local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] + system.setup() + sessionGains.gold = 0 + sessionGains.experience = 0 + lastGoldChange = nil + lastXpChange = nil + lastGold = nil +end + +keneanung.bashing.setAlias = function(command) + local attackCommand + if keneanung.bashing.configuration[class][command]:find("&tar") then + attackCommand = keneanung.bashing.configuration[class][command] + else + attackCommand = keneanung.bashing.configuration[class][command] .. " &tar" + end + send(string.format("setalias %s %s", aliases[command], attackCommand), false) +end + +keneanung.bashing.setSystem = function(systemName) + + if not systemName then + kecho("The following systems are known:") + for name, _ in pairs(keneanung.bashing.systems) do + kecho(" " .. name, "keneanung.bashing.setSystem('" .. name .. "')", "Set '" .. name .. "' as queueing system") + end + kecho(" auto", "keneanung.bashing.setSystem('auto')", "Set 'auto' as queueing system") + echo("\n") + return + end + + if not rawget(keneanung.bashing.systems, systemName) and systemName ~= "auto" then + kecho("System not changed as '" .. systemName .. "' is unknown.") + return + end + local system = keneanung.bashing.systems[keneanung.bashing.configuration.system] + if system then + system.teardown() + end + keneanung.bashing.configuration.system = systemName + kecho("Using " .. keneanung.bashing.configuration.system .. " as queuing system.\n" ) + raiseEvent("keneanung.bashing.settings.changed") + keneanung.bashing.save() + system = keneanung.bashing.systems[keneanung.bashing.configuration.system] + system.setup() +end + +keneanung.bashing.setRageStrat = function(strategyName) + + if not strategyName then + kecho("The following rage strategies are known:") + for name, _ in pairs(keneanung.bashing.battlerage) do + kecho(" " .. name, "keneanung.bashing.setRageStrat('" .. name .. "')", "Set '" .. name .. "' as battlerage strategy") + end + echo("\n") + return + end + + if not keneanung.bashing.battlerage[strategyName] then + kecho("Battlerage strategy not changed as '" .. strategyName .. "' is unknown.") + return + end + keneanung.bashing.configuration[class].rageStrat = strategyName + keneanung.bashing.save() + raiseEvent("keneanung.bashing.settings.changed") + kecho("Using " .. strategyName .. " as battlerage strategy.\n" ) +end + +keneanung.bashing.calcFleeValue = function(configValue) + local isString = type(configValue) == "string" + if isString and configValue:ends("%") then + return configValue:match("%d+") * gmcp.Char.Vitals.maxhp / 100 + elseif isString and configValue:ends("d") then + return configValue:match("(.-)d") * keneanung.bashing.damage / keneanung.bashing.attacks + else + return configValue * 1 + end +end + +keneanung.bashing.addFile = function() + local path = invokeFileDialog(true, "Which file do you want to add?") + if path ~= "" then + keneanung.bashing.configuration.filesToLoad[#keneanung.bashing.configuration.filesToLoad + 1] = path + raiseEvent("keneanung.bashing.settings.changed") + end + keneanung.bashing.save() +end + +keneanung.bashing.deleteFile = function(num) + table.remove(keneanung.bashing.configuration.filesToLoad, num) + keneanung.bashing.save() + + raiseEvent("keneanung.bashing.settings.changed") +end + +keneanung.bashing.toggleDebug = function() + debugEnabled = not debugEnabled + kecho("Debug " .. (debugEnabled and "enabled" or "disabled")) +end + +keneanung.bashing.addDenizenAffliction = function(denizen, affliction, own) + debugMessage("New denizen affliction.", { denizen = denizen, affliction = affliction, own = own }) + + local affObject = afflictions[affliction] + debugMessage("associated affliction object", affObject) + if not affObject then + kecho("Affliction '" .. affliction .. "' is not a known denizen affliction.") + return + end + + local denizenObject = keneanung.bashing.getTargetObject(denizen) + debugMessage("associated denizen object from direct access", denizenObject) + if not denizenObject then + kecho("Denizen '" .. denizen .. "' not in list of targets. Fallback is not yet implemented.") + return + end + + local isTarget = (keneanung.bashing.targetList[keneanung.bashing.attacking].id == denizenObject.id) + + denizenObject.affs[affliction] = tempTimer(affObject.timer, + string.format("keneanung.bashing.removeDenizenAffliction('%s', '%s', %s)", denizenObject.id, affliction, own and "true" or "false")) + + kecho(string.format("<%s>%s%s gained <%s>%s", isTarget and "OrangeRed" or "yellow", + denizenObject.name, isTarget and " (your target)" or "", affObject.colour, affliction)) + if own then + raiseEvent("keneanung.bashing.afflictionGained", denizenObject.id, affliction) + end +end + +keneanung.bashing.removeDenizenAffliction = function(denizen, affliction, own) + debugMessage("Remove denizen affliction.", { denizen = denizen, affliction = affliction, own = own }) + + local affObject = afflictions[affliction] + debugMessage("associated affliction object", affObject) + if not affObject then + kecho("Affliction '" .. affliction .. "' is not a known denizen affliction.") + return + end + + local denizenObject = directTargetAccess[denizen] + debugMessage("associated denizen object from direct access", denizenObject) + if not denizenObject then + return + end + + local isTarget = (keneanung.bashing.targetList[keneanung.bashing.attacking].id == denizenObject.id) + + killTimer(denizenObject.affs[affliction]) + kecho(string.format("<%s>%s%s lost <%s>%s", + isTarget and "OrangeRed" or "yellow", denizenObject.name, isTarget and " (your target)" or "", affObject.colour, affliction)) + if own then + raiseEvent("keneanung.bashing.afflictionLost", denizenObject.id, affliction) + end + denizenObject.affs[affliction] = nil +end + +keneanung.bashing.getAfflictions = function(denizen) + debugMessage("Returnung denizen affliction.", { denizen = denizen }) + + local denizenObject = directTargetAccess[denizen] + debugMessage("associated denizen object from direct access", denizenObject) + if not denizenObject then + return {} + end + + local ret = {} + for aff, _ in pairs(denizenObject.affs) do + ret[#ret + 1] = aff + end + + return ret +end + +keneanung.bashing.hasAffliction = function(denizen, affliction) + debugMessage("Checking for denizen affliction.", { denizen = denizen, affliction = affliction }) + + local denizenObject = directTargetAccess[denizen] + debugMessage("associated denizen object from direct access", denizenObject) + if not denizenObject then + return false + end + + return denizenObject.affs[affliction] ~= nil +end + +keneanung.bashing.handleSkillList = function() + local skillList = gmcp.Char.Skills.List + if skillList.group ~= "attainment" then return end + + for _, skill in ipairs(skillList.list) do + if not table.contains(nonBattlerageAttainmentSkills, skill) then + requestSkillDetails[#requestSkillDetails + 1] = skill + end + end + battlerageSkills = {} + requestAllSkillDetails() +end + +keneanung.bashing.handleSkillInfo = function() + local skillInfo = gmcp.Char.Skills.Info + if skillInfo.group ~= "attainment" then return end + + local cooldown = tonumber(skillInfo.info:match("(%d+%.%d+) seconds")) + local rage = tonumber(skillInfo.info:match("(%d+) rage")) + local command = skillInfo.info:match("Syntax:\n(.-)\n"):gsub("", "%%s") + local affliction = skillInfo.info:match("Gives denizen affliction: (%w+)") + local affsUsed = {skillInfo.info:match("Uses denizen afflictions: (%w+) or (%w+)")} + for ind, aff in ipairs(affsUsed) do + affsUsed[ind] = aff:lower() + end + local skillKnown = skillInfo.info:find("*** You have not yet learned this ability ***", 1, true) == nil + + local rageObject = { + cooldown = cooldown, + rage = rage, + command = command, + affliction = affliction and affliction:lower(), + affsUsed = affsUsed, + name = skillInfo.skill:lower(), + skillKnown = skillKnown + } + + if #battlerageSkills == 0 or skillInfo.skill:lower() ~= battlerageSkills[#battlerageSkills].name then + if battlerageSkills[skillInfo.skill] then + battlerageSkills[skillInfo.skill] = rageObject + for index, oldObject in ipairs(battlerageSkills) do + if oldObject.name == rageObject.name then + battlerageSkills[index] = rageObject + break + end + end + debugMessage("Updated skill " .. skillInfo.skill .. ", complete list is here ", battlerageSkills) + else + battlerageSkills[skillInfo.skill] = rageObject + battlerageSkills[#battlerageSkills + 1] = rageObject + debugMessage("added new battlerage skill complete list is here ", battlerageSkills) + if #battlerageSkills == 6 then + sortDepthswalkerBattlerage() + sortPariahBattlerage() + sortPsionBattlerage() + sortUnnamableBattlerage() + sortProvokeBattlerage() + kecho("Finished parsing battlerage skills.\n") + end + end + else + debugMessage("got double battlerage skill") + end +end + +keneanung.bashing.rageAvailable = function(ability) + if keneanung.bashing.usedRageAttack then return false end + if type(ability) == "number" then + ability = battlerageSkills[ability].name + end + + if not gmcp.IRE.Display then + return false + end + + for _, button in pairs(gmcp.IRE.Display.ButtonActions) do + if button.text:lower() == ability:lower() then + return button.highlight == 1 + end + end + return false +end + +keneanung.bashing.printGains = function(which) + local gainsTable + if which == "lifetime" then + gainsTable = keneanung.bashing.configuration.lifetimeGains + elseif which == "session" then + gainsTable = sessionGains + elseif which == "trip" then + gainsTable = tripGains + else + kecho(string.format("Gains for the timespan '%s' are not tracked.", which)) + return + end + + local levels, percent = math.modf(gainsTable.experience / 100) + percent = percent * 100 + kecho(string.format("You gained %d levels, %.1f%% towards the next level and %d gold during the period '%s'.", levels, percent, gainsTable.gold, which)) + if gainsTable.stopwatch then + local time = getStopWatchTime(gainsTable.stopwatch) + kecho(string.format("The period was %dh %dmin and %.3f sec long.", math.floor(time / 3600), math.floor( math.mod(time, 3600) / 60), math.mod(time, 60))) + end +end + +keneanung.bashing.startHuntingTrip = function() + if not tripGains.stopwatch then + tripGains = { gold = 0, experience = 0, stopwatch = createStopWatch() } + startStopWatch(tripGains.stopwatch) + kecho("Started new hunting trip. Enjoy and be careful.") + else + kecho("Ugh- Finish the running trip before starting a new one?") + end +end + +keneanung.bashing.stopHuntingTrip = function() + if tripGains.stopwatch then + kecho("Stopped hunting trip. I hope you had fun.") + keneanung.bashing.printGains("trip") + stopStopWatch(tripGains.stopwatch) + tripGains.stopwatch = nil + else + kecho("You are not hunting or didn't tell me you did. Can't stop anything.") + end +end + +keneanung.bashing.seenDenizen = function(id, name) + keneanung.bashing.availableTargets[name] = true + if denizenCache[id] then + local timer = denizenCache[id].expireTimer + killTimer(timer) + timer = tempTimer(10 * 60, "keneanung.bashing.unseenDenizen('" .. id .. "')") + denizenCache[id].expireTimer = timer + else + local cacheObject = { name = name } + cacheObject.expireTimer = tempTimer(10 * 60, "keneanung.bashing.unseenDenizen('" .. id .. "')") + denizenCache[id] = cacheObject + end +end + +keneanung.bashing.unseenDenizen = function(id) + if denizenCache[id] then + killTimer(denizenCache[id].expireTimer) + denizenCache[id] = nil + end + if directTargetAccess[id] then + directTargetAccess[id] = nil + end +end + +keneanung.bashing.getDenizenName = function(id) + return denizenCache[id] and denizenCache[id].name or "unknown" +end + +keneanung.bashing.getTargetObject = function(id) + if not tonumber(id) then + kecho("You are trying to access the denizen with ID " .. id .. " which is not a numerical ID.") + return + end + local result = directTargetAccess[tostring(id)] + if not result then + result = { id = id, name = keneanung.bashing.getDenizenName(id), affs = {} } + directTargetAccess[tostring(id)] = result + end + return result +end + +local doImport = function(importTable) + --Allow us to strip a full config file down to just the priorities + importTable = importTable.priorities or importTable + + local somethingChanged = false + + + --do the import + for area,_ in pairs(importTable) do + if #importTable[area] > 0 then + keneanung.bashing.configuration.priorities[area] = keneanung.bashing.configuration.priorities[area] or {} + somethingChanged = true + end + for _, denizenString in pairs(importTable[area]) do + if not table.contains(keneanung.bashing.configuration.priorities[area],denizenString) then + table.insert(keneanung.bashing.configuration.priorities[area], denizenString) + somethingChanged = true + end + end + end + + if somethingChanged then + raiseEvent("keneanung.bashing.settings.changed") + end +end + +keneanung.bashing.guhemImport = function() + doImport(huntVar.userAreaList) +end + +keneanung.bashing.export = function() + local directory = invokeFileDialog(false, "Which file do you want to export your priorities to?") + if directory ~= "" then -- If a folder was provided + table.save(directory .. "/Bashing-Export.lua", keneanung.bashing.configuration.priorities) -- Exporting to folder specified + kecho("Have exported priorities to " .. path .. "/Bashing-Export.lua") -- Messaging user + end +end + +keneanung.bashing.import = function() + local path = invokeFileDialog(true, "Which file do you want to add?") -- Requesting the specific file to be imported + if path ~= "" then -- Making sure that the file was specified + local importTable = {} + table.load(path, importTable) + doImport(importTable) + kecho("Import Completed") + end --if +end + +keneanung.bashing.manuallyTarget = function(what) + if not keneanung.bashing.configuration.manualTargetting then return end + local item = keneanung.bashing.getTargetObject(what) + if not item then return end + keneanung.bashing.targetList = { item } + sendGMCP('IRE.Target.Set "' .. item.id .. '"') + raiseEvent("keneanung.bashing.targetList.changed") + raiseEvent("keneanung.bashing.targetList.firstChanged", keneanung.bashing.targetList[1].id) + if waitingForManualTargetTimer then killTimer(waitingForManualTargetTimer) end + if waitingForManualTarget then + keneanung.bashing.setTarget() + startAttack() + end +end + +keneanung.bashing.load() +for _, file in ipairs(keneanung.bashing.configuration.filesToLoad) do + dofile(file) +end +tempTimer(0, [[raiseEvent("keneanung.bashing.loaded")]]) From 6a453e8528df1b2d20bcca7b9ac9b8975c328a4a Mon Sep 17 00:00:00 2001 From: Godlyh3ll Date: Wed, 16 Jul 2025 14:48:52 -0600 Subject: [PATCH 4/7] script.lua This update improves battlerage skill handling following the addition of a new skill (e.g., provoke) by Achaea. Instead of rewriting index logic, the update adjusts the skill ordering dynamically to preserve existing behavior. Summary: sortProvokeBattlerage() added Detects if provoke is the first battlerage skill (as currently sent by Achaea) and moves it to the end of the skill list, maintaining expected indexing for existing battlerage strategies. Called sortProvokeBattlerage() after all class-based sorters Ensures skill order is corrected regardless of class. Updated knownBattlerageSkillList() to use dynamic iteration Now lists all known battlerage skills by name, regardless of total count, avoiding hardcoded index errors. These changes preserve all original functionality while gracefully handling future battlerage expansions. --- script.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script.lua b/script.lua index 7743a82..0d5e49c 100644 --- a/script.lua +++ b/script.lua @@ -1873,7 +1873,7 @@ keneanung.bashing.handleSkillInfo = function() battlerageSkills[skillInfo.skill] = rageObject battlerageSkills[#battlerageSkills + 1] = rageObject debugMessage("added new battlerage skill complete list is here ", battlerageSkills) - if #battlerageSkills == 6 then + if #battlerageSkills == 7 then sortDepthswalkerBattlerage() sortPariahBattlerage() sortPsionBattlerage() From c1a3d904b7cf0de5a54b9a2de51707f375c40373 Mon Sep 17 00:00:00 2001 From: Godlyh3ll Date: Wed, 16 Jul 2025 14:56:32 -0600 Subject: [PATCH 5/7] Update script.lua Added correct updated file From c181a2ee40f3e6df5280de160519905223721d1a Mon Sep 17 00:00:00 2001 From: Godlyh3ll Date: Wed, 16 Jul 2025 15:11:27 -0600 Subject: [PATCH 6/7] Update script.lua local variable for set battlerage skill value for easy changes if more are added later --- script.lua | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/script.lua b/script.lua index 0d5e49c..ad78357 100644 --- a/script.lua +++ b/script.lua @@ -79,6 +79,7 @@ local denizenCache = {} local waitingForManualTargetTimer local waitingForManualTarget = false +local EXPECTED_BATTLERAGE_COUNT = 7 keneanung = keneanung or {} keneanung.bashing = {} @@ -186,7 +187,7 @@ local sortPariahBattlerage = function() debugMessage("sorting brage for pariah", {battlerageSkills = battlerageSkills}) - if class ~= "Pariah" or #battlerageSkills ~= 6 then return end + if class ~= "Pariah" or #battlerageSkills ~= EXPECTED_BATTLERAGE_COUNT then return end battlerageSkills[2], battlerageSkills[3], battlerageSkills[4] = battlerageSkills["symphony"], battlerageSkills["scour"], battlerageSkills["feast"] battlerageSkills["symphony"].affliction = "fear" @@ -207,7 +208,7 @@ local sortPsionBattlerage = function() debugMessage("sorting brage for psion", {battlerageSkills = battlerageSkills}) - if class ~= "Psion" or #battlerageSkills ~= 6 then return end + if class ~= "Psion" or #battlerageSkills ~= EXPECTED_BATTLERAGE_COUNT then return end battlerageSkills[2], battlerageSkills[3], battlerageSkills[4] = battlerageSkills["regrowth"], battlerageSkills["pulverise"], battlerageSkills["devastate"] battlerageSkills["terror"].affliction = "fear" @@ -220,7 +221,7 @@ local sortUnnamableBattlerage = function() debugMessage("sorting brage for unnamable", {battlerageSkills = battlerageSkills}) - if class ~= "Unnamable" or #battlerageSkills ~= 6 then return end + if class ~= "Unnamable" or #battlerageSkills ~= EXPECTED_BATTLERAGE_COUNT then return end battlerageSkills[2], battlerageSkills[3], battlerageSkills[4] = battlerageSkills["dread"], battlerageSkills["sunder"], battlerageSkills["destroy"] battlerageSkills["dread"].affliction = "fear" @@ -1873,14 +1874,14 @@ keneanung.bashing.handleSkillInfo = function() battlerageSkills[skillInfo.skill] = rageObject battlerageSkills[#battlerageSkills + 1] = rageObject debugMessage("added new battlerage skill complete list is here ", battlerageSkills) - if #battlerageSkills == 7 then - sortDepthswalkerBattlerage() - sortPariahBattlerage() - sortPsionBattlerage() - sortUnnamableBattlerage() - sortProvokeBattlerage() - kecho("Finished parsing battlerage skills.\n") - end + if #battlerageSkills >= EXPECTED_BATTLERAGE_COUNT then + sortProvokeBattlerage() -- Must go first to fix ordering + sortDepthswalkerBattlerage() + sortPariahBattlerage() + sortPsionBattlerage() + sortUnnamableBattlerage() + kecho("Finished parsing battlerage skills.\n") + end end else debugMessage("got double battlerage skill") From 15a2211749fd7e0bbb2e3fa49e4213316b729c2d Mon Sep 17 00:00:00 2001 From: Godlyh3ll Date: Wed, 16 Jul 2025 15:32:31 -0600 Subject: [PATCH 7/7] Update script.lua Forgot Depthswalker change --- script.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script.lua b/script.lua index ad78357..fb9167d 100644 --- a/script.lua +++ b/script.lua @@ -169,7 +169,7 @@ local sortDepthswalkerBattlerage = function() debugMessage("sorting brage for walkers", {battlerageSkills = battlerageSkills}) - if class ~= "Depthswalker" or #battlerageSkills ~= 6 then return end + if class ~= "Depthswalker" or #battlerageSkills ~= EXPECTED_BATTLERAGE_COUNT then return end battlerageSkills[2], battlerageSkills[3], battlerageSkills[4] = battlerageSkills["curse"], battlerageSkills["nakail"], battlerageSkills["lash"] battlerageSkills["curse"].affliction = "aeon"