From 29e19b931f84e1e0543ab64ef11aab17c5a60847 Mon Sep 17 00:00:00 2001 From: 4n0n <4n0n@tinkr.site> Date: Thu, 19 Jan 2023 01:24:33 -0600 Subject: [PATCH] Tons of changes, probably broke stuff --- scripts/outlaw.lua | 6 +- scripts/restodruid.lua | 2 +- scripts/subtlety.lua | 18 ++-- src/List/List.lua | 153 ++++++++++++++++++++++++++++ src/ObjectManager/ObjectManager.lua | 50 +++++++++ src/Spell/Spell.lua | 11 -- src/SpellBook/SpellBook.lua | 4 + src/Unit/Unit.lua | 22 ++-- src/UnitManager/UnitManager.lua | 77 +++----------- src/_bastion.lua | 17 ++++ 10 files changed, 265 insertions(+), 95 deletions(-) create mode 100644 src/List/List.lua create mode 100644 src/ObjectManager/ObjectManager.lua diff --git a/scripts/outlaw.lua b/scripts/outlaw.lua index 2943c91..959ecb5 100644 --- a/scripts/outlaw.lua +++ b/scripts/outlaw.lua @@ -50,7 +50,7 @@ local WindscarWhetstone = Bastion.ItemBook:GetItem(137486) local PurgeTarget = Bastion.UnitManager:CreateCustomUnit('purge', function(unit) local purge = nil - Bastion.UnitManager:EnumNameplates(function(unit) + Bastion.UnitManager:EnumEnemies(function(unit) if unit:IsDead() then return false end @@ -79,7 +79,7 @@ end) local KickTarget = Bastion.UnitManager:CreateCustomUnit('kick', function(unit) local purge = nil - Bastion.UnitManager:EnumNameplates(function(unit) + Bastion.UnitManager:EnumEnemies(function(unit) if unit:IsDead() then return false end @@ -139,7 +139,7 @@ end) local Explosive = Bastion.UnitManager:CreateCustomUnit('explosive', function(unit) local explosive = nil - Bastion.UnitManager:EnumNameplates(function(unit) + Bastion.UnitManager:EnumEnemies(function(unit) if unit:IsDead() then return false end diff --git a/scripts/restodruid.lua b/scripts/restodruid.lua index 29aa90d..20a7591 100644 --- a/scripts/restodruid.lua +++ b/scripts/restodruid.lua @@ -177,7 +177,7 @@ end) local PurgeTarget = Bastion.UnitManager:CreateCustomUnit('purge', function(unit) local purge = nil - Bastion.UnitManager:EnumNameplates(function(unit) + Bastion.UnitManager:EnumEnemies(function(unit) if unit:IsDead() then return false end diff --git a/scripts/subtlety.lua b/scripts/subtlety.lua index 95efc48..554d20e 100644 --- a/scripts/subtlety.lua +++ b/scripts/subtlety.lua @@ -66,7 +66,7 @@ local WindscarWhetstone = Bastion.ItemBook:GetItem(137486) local PurgeTarget = Bastion.UnitManager:CreateCustomUnit('purge', function(unit) local purge = nil - Bastion.UnitManager:EnumNameplates(function(unit) + Bastion.UnitManager:EnumEnemies(function(unit) if unit:IsDead() then return false end @@ -95,7 +95,7 @@ end) local KickTarget = Bastion.UnitManager:CreateCustomUnit('kick', function(unit) local purge = nil - Bastion.UnitManager:EnumNameplates(function(unit) + Bastion.UnitManager:EnumEnemies(function(unit) if unit:IsDead() then return false end @@ -155,7 +155,7 @@ end) local RuptureTarget = Bastion.UnitManager:CreateCustomUnit('rupture', function() local target = nil - Bastion.UnitManager:EnumNameplates(function(unit) + Bastion.UnitManager:EnumEnemies(function(unit) if unit:IsDead() then return false end @@ -642,12 +642,12 @@ AOEAPL:AddSpell( -- Use Shuriken Storm on 2 targets outside of Shadow Dance. AOEAPL:AddSpell( ShurikenStorm:CastableIf(function(self) - return Target:Exists() and Player:InMelee(Target) and + return Target:Exists() and Player:GetDistance(Target) <= 10 and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and - Player:GetMeleeAttackers() == 2 and + Player:GetEnemies(10) == 2 and not Player:GetAuras():FindMy(ShadowDanceAura):IsUp() - end):SetTarget(Target) + end):SetTarget(Player) ) -- Use Shadowstrike on 2 and 3 targets during Shadow Dance or to proc Premeditation. @@ -656,7 +656,7 @@ AOEAPL:AddSpell( return Target:Exists() and Player:InMelee(Target) and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and - Player:GetMeleeAttackers() >= 2 and Player:GetMeleeAttackers() <= 3 and + Player:GetEnemies(10) >= 2 and Player:GetEnemies(10) <= 3 and Player:GetAuras():FindMy(ShadowDanceAura):IsUp() end):SetTarget(Target) ) @@ -664,10 +664,10 @@ AOEAPL:AddSpell( -- Use Shuriken Storm AOEAPL:AddSpell( ShurikenStorm:CastableIf(function(self) - return Target:Exists() and Player:InMelee(Target) and + return Target:Exists() and Player:GetDistance(Target) <= 10 and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() - end):SetTarget(Target) + end):SetTarget(Player) ) diff --git a/src/List/List.lua b/src/List/List.lua new file mode 100644 index 0000000..7b583a6 --- /dev/null +++ b/src/List/List.lua @@ -0,0 +1,153 @@ +local Tinkr, Bastion = ... + +local List = {} +List.__index = List + +function List:New() + local self = setmetatable({}, List) + self._list = {} + return self +end + +function List:push(value) + table.insert(self._list, value) +end + +function List:pop() + return table.remove(self._list) +end + +function List:peek() + return self._list[#self._list] +end + +function List:count() + return #self._list +end + +function List:clear() + self._list = {} +end + +function List:contains(value) + for _, v in ipairs(self._list) do + if v == value then + return true + end + end + return false +end + +function List:remove(value) + for i, v in ipairs(self._list) do + if v == value then + table.remove(self._list, i) + return true + end + end + return false +end + +function List:each(callback) + for _, v in ipairs(self._list) do + if callback(v) then + break + end + end +end + +function List:map(callback) + local newList = List.new() + for _, v in ipairs(self._list) do + newList:push(callback(v)) + end + return newList +end + +function List:filter(callback) + local newList = List.new() + for _, v in ipairs(self._list) do + if callback(v) then + newList:push(v) + end + end + return newList +end + +function List:reduce(callback, initialValue) + local result = initialValue + for _, v in ipairs(self._list) do + result = callback(result, v) + end + return result +end + +function List:find(callback) + for _, v in ipairs(self._list) do + if callback(v) then + return v + end + end + return nil +end + +function List:findIndex(callback) + for i, v in ipairs(self._list) do + if callback(v) then + return i + end + end + return nil +end + +function List:sort(callback) + table.sort(self._list, callback) +end + +function List:reverse() + local newList = List.new() + for i = #self._list, 1, -1 do + newList:push(self._list[i]) + end + return newList +end + +function List:clone() + local newList = List.new() + for _, v in ipairs(self._list) do + newList:push(v) + end + return newList +end + +function List:concat(list) + local newList = List.new() + for _, v in ipairs(self._list) do + newList:push(v) + end + for _, v in ipairs(list._list) do + newList:push(v) + end + return newList +end + +function List:join(separator) + local result = "" + for i, v in ipairs(self._list) do + result = result .. v + if i < #self._list then + result = result .. separator + end + end + return result +end + +function List:toString() + return self:join(", ") +end + +function List:__tostring() + return self:toString() +end + +return List diff --git a/src/ObjectManager/ObjectManager.lua b/src/ObjectManager/ObjectManager.lua new file mode 100644 index 0000000..d90b561 --- /dev/null +++ b/src/ObjectManager/ObjectManager.lua @@ -0,0 +1,50 @@ +local Tinkr, Bastion = ... + +local ObjectManager = {} +ObjectManager.__index = ObjectManager + +function ObjectManager:New() + local self = setmetatable({}, ObjectManager) + + self._objects = {} + + self.enemies = Bastion.List:New() + self.friends = Bastion.List:New() + self.activeEnemies = Bastion.List:New() + self.explosives = Bastion.List:New() + + return self +end + +function ObjectManager:Refresh() + self.enemies:clear() + self.friends:clear() + self.activeEnemies:clear() + self.explosives:clear() + + local objects = Objects() + + for _, object in pairs(objects) do + if ObjectType(object) == 5 or ObjectType(object) == 6 then + local unit = Bastion.UnitManager:GetObject(ObjectGUID(object)) + if not unit then + unit = Bastion.Unit:New(object) + Bastion.UnitManager:SetObject(unit) + end + + if unit:GetID() == 120651 then + self.explosives:push(unit) + elseif unit:IsPlayer() and unit:IsInParty() then + self.friends:push(unit) + elseif unit:IsEnemy() then + self.enemies:push(unit) + + if unit:IsAffectingCombat() then + self.activeEnemies:push(unit) + end + end + end + end +end + +return ObjectManager diff --git a/src/Spell/Spell.lua b/src/Spell/Spell.lua index 609fff7..b97a781 100644 --- a/src/Spell/Spell.lua +++ b/src/Spell/Spell.lua @@ -41,17 +41,6 @@ function Spell:New(id) self.spellID = id - Bastion.EventManager:RegisterWoWEvent("UNIT_SPELLCAST_SUCCEEDED", function(...) - local unit, castGUID, spellID = ... - if unit == "player" and spellID == self:GetID() then - self.lastCastAt = GetTime() - - if self:GetPostCastFunction() then - self:GetPostCastFunction()(self) - end - end - end) - return self end diff --git a/src/SpellBook/SpellBook.lua b/src/SpellBook/SpellBook.lua index 9519e0a..b06f69f 100644 --- a/src/SpellBook/SpellBook.lua +++ b/src/SpellBook/SpellBook.lua @@ -20,4 +20,8 @@ function SpellBook:GetSpell(id) return self.spells[id] end +function SpellBook:GetIfRegistered(id) + return self.spells[id] +end + return SpellBook diff --git a/src/Unit/Unit.lua b/src/Unit/Unit.lua index 5441b0c..ffae779 100644 --- a/src/Unit/Unit.lua +++ b/src/Unit/Unit.lua @@ -211,7 +211,7 @@ end -- Get if the unit is affecting combat function Unit:IsAffectingCombat() - return UnitAffectingCombat(self.unit) + return UnitAffectingCombat('player', self.unit) end -- Get the units class id @@ -319,7 +319,6 @@ end -- Get the number of enemies in a given range of the unit and cache the result for .5 seconds function Unit:GetEnemies(range) - local enemies = self.cache:Get("enemies_" .. range) if enemies then return enemies @@ -327,9 +326,9 @@ function Unit:GetEnemies(range) local count = 0 - Bastion.UnitManager:EnumNameplates(function(unit) + Bastion.UnitManager:EnumEnemies(function(unit) if not self:IsUnit(unit) and unit:GetDistance(self) <= range and unit:IsAlive() and self:CanSee(unit) and - unit:IsEnemy() then + unit:IsEnemy() and unit:IsAffectingCombat() then count = count + 1 end end) @@ -340,15 +339,21 @@ end -- Get the number of melee attackers function Unit:GetMeleeAttackers() + local enemies = self.cache:Get("melee_attackers") + if enemies then + return enemies + end + local count = 0 - Bastion.UnitManager:EnumNameplates(function(unit) + Bastion.UnitManager:EnumEnemies(function(unit) if not self:IsUnit(unit) and unit:IsAlive() and self:CanSee(unit) and - self:InMelee(unit) and unit:IsEnemy() then + self:InMelee(unit) and unit:IsEnemy() and unit:IsAffectingCombat() then count = count + 1 end end) + self.cache:Set("melee_attackers", count, .5) return count end @@ -460,4 +465,9 @@ function Unit:GetID() return ObjectID(self.unit) end +-- In party +function Unit:IsInParty() + return UnitInParty(self.unit) +end + return Unit diff --git a/src/UnitManager/UnitManager.lua b/src/UnitManager/UnitManager.lua index df19ace..53a6b54 100644 --- a/src/UnitManager/UnitManager.lua +++ b/src/UnitManager/UnitManager.lua @@ -167,82 +167,29 @@ end -- Enum Friends (party/raid members) function UnitManager:EnumFriends(cb) - local isRaid = IsInRaid() - local n = GetNumGroupMembers() - - if cb(self:Get('player')) then - return - end - - if isRaid then - for i = 1, n do - local unit = self:Get('raid' .. i) - if unit:IsValid() then - if cb(unit) then - break - end - end - end - else - for i = 1, n do - local unit = self:Get('party' .. i) - if unit:IsValid() then - if cb(unit) then - break - end - end + Bastion.ObjectManager.friends:each(function(unit) + if cb(unit) then + return true end - end + end) end -- Enum Enemies (object manager) function UnitManager:EnumEnemies(cb) - for obj in ObjectManager:Objects() do - if ObjectType(obj) == 5 or ObjectType(obj) == 6 then - local unit = UnitManager:GetObject(ObjectGUID(obj)) - if not unit then - unit = Unit:New(obj) - UnitManager:SetObject(unit) - end - if unit:IsHostile() and unit:IsAffectingCombat() and unit:IsAlive() - then - if cb(unit) then - break - end - end + Bastion.ObjectManager.activeEnemies:each(function(unit) + if cb(unit) then + return true end - end + end) end -- Enum Units (object manager) function UnitManager:EnumUnits(cb) - local objs = Objects() - for i = 1, #objs do - local obj = objs[i] - if ObjectType(obj) == 5 or ObjectType(obj) == 6 then - local unit = UnitManager:GetObject(ObjectGUID(obj)) - if not unit then - unit = Unit:New(obj) - UnitManager:SetObject(unit) - end - if cb(unit) then - break - end - end - end -end - --- Enum enemies (nameplates) -function UnitManager:EnumNameplates(cb) - local n = 30 - for i = 1, n do - local unit = self:Get('nameplate' .. i) - if unit:IsValid() then - if cb(unit) then - break - end + Bastion.ObjectManager.enemies:each(function(unit) + if cb(unit) then + return true end - end + end) end -- Get the number of friends with a buff (party/raid members) diff --git a/src/_bastion.lua b/src/_bastion.lua index 4c42318..57e49b5 100644 --- a/src/_bastion.lua +++ b/src/_bastion.lua @@ -15,6 +15,7 @@ function Bastion.require(class) end Bastion.ClassMagic = Bastion.require("ClassMagic") +Bastion.List = Bastion.require("List") Bastion.NotificationsList, Bastion.Notification = Bastion.require("NotificationsList") Bastion.Vector3 = Bastion.require("Vector3") Bastion.Commmand = Bastion.require("Command") @@ -26,6 +27,7 @@ Bastion.Aura = Bastion.require("Aura") Bastion.APL = Bastion.require("APL") Bastion.Module = Bastion.require("Module") Bastion.UnitManager = Bastion.require("UnitManager"):New() +Bastion.ObjectManager = Bastion.require("ObjectManager"):New() Bastion.EventManager = Bastion.require("EventManager"):New() Bastion.Spell = Bastion.require("Spell") Bastion.SpellBook = Bastion.require("SpellBook"):New() @@ -47,6 +49,20 @@ Bastion.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras) u:GetAuras():OnUpdate(auras) end) +Bastion.EventManager:RegisterWoWEvent("UNIT_SPELLCAST_SUCCEEDED", function(...) + local unit, castGUID, spellID = ... + + local spell = Bastion.SpellBook:GetIfRegistered(spellID) + + if unit == "player" and spell then + spell.lastCastAt = GetTime() + + if spell:GetPostCastFunction() then + spell:GetPostCastFunction()(spell) + end + end +end) + Bastion.Ticker = C_Timer.NewTicker(0.1, function() if not Bastion.CombatTimer:IsRunning() and UnitAffectingCombat("player") then Bastion.CombatTimer:Start() @@ -55,6 +71,7 @@ Bastion.Ticker = C_Timer.NewTicker(0.1, function() end if Bastion.Enabled then + Bastion.ObjectManager:Refresh() for i = 1, #Bastion.modules do Bastion.modules[i]:Tick() end