From 6a87afca613e6aa3e7ecd637f2033cfe202aca4b Mon Sep 17 00:00:00 2001 From: jeffi Date: Tue, 27 Aug 2024 09:38:38 -0500 Subject: [PATCH] Updates --- .editorconfig | 17 ++--- src/Aura/Aura.lua | 20 +----- src/Bastion/Bastion.lua | 39 +++++++++-- src/Item/Item.lua | 4 ++ src/Object/Object.lua | 127 ++++++++++++++++++++++++++++++++++++ src/Spell/Spell.lua | 4 +- src/TimeToDie/TimeToDie.lua | 31 +++++++-- src/Unit/Unit.lua | 22 ++++--- src/_bastion.lua | 61 +++++++++++++++++ 9 files changed, 276 insertions(+), 49 deletions(-) diff --git a/.editorconfig b/.editorconfig index c98f997..a6c8c49 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,14 +4,15 @@ root = true [*.lua] +call_parentheses = Always +charset = utf-8 +collapse_simple_statement = Never +end_of_line = lf +indent_size = 4 +indent_style = space indent_type = Spaces -column_width = 180 indent_width = 4 +insert_final_newline = true +max_line_length = 1000 quote_style = AutoPreferDouble -call_parentheses = Always -indent_style = space -indent_size = 4 -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true \ No newline at end of file +trim_trailing_whitespace = true \ No newline at end of file diff --git a/src/Aura/Aura.lua b/src/Aura/Aura.lua index 980dd96..4f8c110 100644 --- a/src/Aura/Aura.lua +++ b/src/Aura/Aura.lua @@ -45,7 +45,6 @@ end -- Equals ---@param other Bastion.Aura | Bastion.Spell ----@return boolean function Aura:__eq(other) if getmetatable(other) == Aura then return self:GetSpell():GetID() == other:GetSpell():GetID() @@ -59,7 +58,6 @@ function Aura:__eq(other) end -- tostring ----@return string function Aura:__tostring() return "Bastion.__Aura(" .. self:GetSpell():GetID() .. ")" .. " - " .. (self:GetName() or "''") end @@ -105,8 +103,8 @@ function Aura:New(unit, index, type) return Aura:CreateFromUnitAuraInfo(unitAuraInfo, index, type) end - local name, icon, count, dispelType, duration, expirationTime, source, isStealable, nameplateShowPersonal, spellId, canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod, v1, v2, v3, v4 = - UnitAura(unit:GetOMToken(), index, type) + ---@diagnostic disable-next-line: deprecated + local name, icon, count, dispelType, duration, expirationTime, source, isStealable, nameplateShowPersonal, spellId, canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod, v1, v2, v3, v4 = UnitAura(unit:GetOMToken(), index, type) ---@class Bastion.Aura local self = setmetatable({}, Aura) self.aura = { @@ -174,7 +172,6 @@ end ---@param unitAuraInfo? AuraData ---@param index? number ---@param type? "HELPFUL"|"HARMFUL" ----@return Bastion.Aura function Aura:CreateFromUnitAuraInfo(unitAuraInfo, index, type) if unitAuraInfo then ---@class Bastion.Aura @@ -208,67 +205,56 @@ function Aura:CreateFromUnitAuraInfo(unitAuraInfo, index, type) end -- Check if the aura is valid ----@return boolean function Aura:IsValid() return self.aura.name ~= nil end -- Check if the aura is up ----@return boolean function Aura:IsUp() return self:IsValid() and (self:GetDuration() == 0 or self:GetRemainingTime() > 0) end -- Check if the aura is down ----@return boolean function Aura:IsDown() return not self:IsUp() end -- Get the auras index ----@return number function Aura:GetIndex() return self.aura.index end -- Get the auras type ----@return string function Aura:GetType() return self.aura.type end -- Get the auras name ----@return string function Aura:GetName() return self.aura.name end -- Get the auras icon ----@return number function Aura:GetIcon() return self.aura.icon end -- Get the auras count ----@return number function Aura:GetCount() return self.aura.count end -- Get the auras dispel type ----@return string function Aura:GetDispelType() return self.aura.dispelType end -- Get the auras duration ----@return number function Aura:GetDuration() return self.aura.duration end -- Get the auras refresh status ----@return boolean function Aura:Refreshable() if not self:IsUp() then return true @@ -277,7 +263,6 @@ function Aura:Refreshable() end -- Get the auras remaining time ----@return number function Aura:GetRemainingTime() local remainingTime = self:GetExpirationTime() - GetTime() @@ -293,7 +278,6 @@ function Aura:GetElapsedPercent() end -- Get the auras expiration time ----@return number function Aura:GetExpirationTime() return self.aura.expirationTime end diff --git a/src/Bastion/Bastion.lua b/src/Bastion/Bastion.lua index b8fd9a4..6399694 100644 --- a/src/Bastion/Bastion.lua +++ b/src/Bastion/Bastion.lua @@ -119,7 +119,7 @@ local function CheckFileExtensions(path, extensions) newPath = AppendExtension(newPath, extension) end if FileExists(newPath) then - return newPath:sub(1, (extension:len() + 2) * -1), true + return newPath:sub(1, (extension:len() + 2) * -1), true, extension end end return path, false @@ -136,6 +136,7 @@ function Bastion:Require(filePath, ...) loadedPath = filePath.filePath or filePath, reloadable = not filePath.reloadable and false or false, order = #Bastion.LoadedFiles + 1, + ext = false, } local pathResolutionShortcut = loadedFile.originalPath:sub(1, 1) == "@" and Bastion.Paths.BastionScripts or @@ -158,27 +159,51 @@ function Bastion:Require(filePath, ...) end return 1, loadResults end - --Log(string.format("Bastion:Require - No files found in directory: %s", loadedFile.newPath)) return 0, SafePack(nil) end local found = false -- Check if file path has a .lua or .luac extension. If not, try to add one and check if the file exists - loadedFile.loadedPath, found = CheckFileExtensions(loadedFile.newPath, { "lua", "luac" }) + loadedFile.loadedPath, found, loadedFile.ext = CheckFileExtensions(loadedFile.newPath, { "lua", "luac" }) if not found then - --Log(string.format("Bastion:Require - Not Found: %s (%s)", loadedFile.newPath, loadedFile.originalPath)) return 0, SafePack(nil) end if not loadedFile.reloadable then if Bastion:CheckIfLoaded(loadedFile.loadedPath) then - --Log(string.format("Bastion:Require - Already loaded: %s (%s)", loadedFile.newPath, loadedFile.originalPath)) return 2, SafePack(nil) end end table.insert(Bastion.LoadedFiles, loadedFile) + --[[ local fileToRead = loadedFile.loadedPath .. (loadedFile.ext and "." .. loadedFile.ext or "") + local luaText = ReadFile(fileToRead) + if luaText then + local func, err = loadstringsecure(luaText, loadedFile.loadedPath) + if type(func) ~= "function" then + Bastion.Util:Print("Error loading file", loadedFile.loadedPath, err) + return 0, SafePack(nil) + end + setfenv(func, setmetatable({ ["_T"] = _T }, { + __index = function(t, v) + if v == "require" then + print("require") + end + return Tinkr.__ENV(t, v) + end + })) + + local call = { pcall(func, Tinkr, Bastion, ...) } + if not call[1] then + Bastion.Util:Print("Error executing file", loadedFile.loadedPath, call[2]) + return 0, SafePack(nil) + end + table.remove(call, 1) + return 1, unpack(call) + else + return 0, SafePack(nil) + end ]] return 1, SafePack(require(loadedFile.loadedPath, Bastion, ...)) end @@ -414,13 +439,13 @@ function Bastion:Load() end local sourceUnit = Bastion.Globals.UnitManager:GetObject(sourceGUID) - if sourceUnit and sourceUnit:Exists() then + if sourceUnit and sourceUnit:Exists() and sourceUnit:IsAffectingCombat() then sourceUnit:SetLastCombatTime(currTime) end local destUnit = Bastion.Globals.UnitManager:GetObject(destGUID) - if destUnit and destUnit:Exists() then + if destUnit and destUnit:Exists() and (destUnit:IsAffectingCombat() or (sourceUnit and sourceUnit:IsAffectingCombat())) then destUnit:SetLastCombatTime(currTime) end diff --git a/src/Item/Item.lua b/src/Item/Item.lua index 76f2d78..3b60054 100644 --- a/src/Item/Item.lua +++ b/src/Item/Item.lua @@ -180,6 +180,7 @@ function Item:GetItemSpell() if C_Item.GetItemSpell then return C_Item.GetItemSpell(self:GetID()) end + ---@diagnostic disable-next-line: deprecated return GetItemSpell(self:GetID()) end @@ -200,6 +201,7 @@ function Item:GetItemInfo() if C_Item.GetItemInfo then return C_Item.GetItemInfo(self:GetID()) end + ---@diagnostic disable-next-line: deprecated return GetItemInfo(self:GetID()) end @@ -385,6 +387,7 @@ function Item:IsUsable() local usable, noMana = C_Item.IsUsableItem(self:GetID()) return usable or usableExcludes[self:GetID()] end + ---@diagnostic disable-next-line: deprecated local usable, noMana = IsUsableItem(self:GetID()) return usable or usableExcludes[self:GetID()] end @@ -400,6 +403,7 @@ function Item:IsEquippable() if C_Item.IsEquippableItem then return C_Item.IsEquippableItem(self:GetID()) end + ---@diagnostic disable-next-line: deprecated return IsEquippableItem(self:GetID()) end diff --git a/src/Object/Object.lua b/src/Object/Object.lua index e69de29..f065877 100644 --- a/src/Object/Object.lua +++ b/src/Object/Object.lua @@ -0,0 +1,127 @@ +---@type Tinkr +local Tinkr, +---@class Bastion +Bastion = ... + +local Class = Tinkr.Util.Class + +---@class Bastion.Object +---@field unit WowGameObject +local Object = {} + +function Object:__index(k) + if k == "unit" then + return rawget(self, k) + end + + local response = Bastion.ClassMagic:Resolve(Object, k) + + if response == nil then + response = rawget(self, k) + end + + if response == nil then + error("Object:__index: " .. k .. " does not exist") + end + + return response +end + +---@param unit WowGameObject +function Object:New(unit) + ---@class Bastion.Object + local self = setmetatable({ unit = unit }, Object) + return self +end + +function Object:Creator() + return self.unit:creator() +end + +function Object:Distance(target) + return self.unit:distance(target) +end + +function Object:Flags() + return self.unit:flags() +end + +function Object:GameObjectType() + return self.unit:gameObjectType() +end + +function Object:Guid() + return self.unit:guid() +end + +function Object:Hash() + return self.unit:hash() +end + +function Object:Height() + return self.unit:height() +end + +function Object:Id() + return self.unit:id() +end + +function Object:IsOutdoors() + return self.unit:isOutdoors() +end + +function Object:IsSubmerged() + return self.unit:isSubmerged() +end + +function Object:Lootable() + return self.unit:lootable() +end + +function Object:ModelID() + return self.unit:modelID() +end + +function Object:MovementFlag() + return self.unit:movementFlag() +end + +function Object:Mover() + return self.unit:mover() +end + +function Object:Name() + return self.unit:name() +end + +function Object:RawPosition() + return self.unit:rawPosition() +end + +function Object:Position() + return self.unit:position() +end + +function Object:WorldPosition() + return self.unit:worldPosition() +end + +function Object:RawRotation() + return self.unit:rawRotation() +end + +function Object:Rotation() + return self.unit:rotation() +end + +function Object:RightClick() + return self.unit:rightClick() +end + +function Object:Sparkling() + return self.unit:sparkling() +end + +function Object:Type() + return self.unit:type() +end diff --git a/src/Spell/Spell.lua b/src/Spell/Spell.lua index 149ea37..d16d666 100644 --- a/src/Spell/Spell.lua +++ b/src/Spell/Spell.lua @@ -121,6 +121,8 @@ function Spell:New(id) local spellInfo = C_Spell.GetSpellInfo(id) local maxRange = spellInfo and spellInfo.maxRange or 0 local minRange = spellInfo and spellInfo.minRange or 0 + self.harmful = C_Spell.IsSpellHarmful(id) + self.helpful = C_Spell.IsSpellHelpful(id) self.auras = {} self.overrides = {} self.conditions = {} @@ -479,7 +481,7 @@ function Spell:EvaluateTraits(target) if self.traits.target.exists then if (self.traits.target.player and not player:Exists()) then return false - elseif (target and (target == Bastion.Globals.UnitManager:Get("none") or not target:Exists())) or (not target and not self:TargetExists()) then + elseif type(target) ~= "nil" and not target:Exists() or not self:TargetExists() then return false end end diff --git a/src/TimeToDie/TimeToDie.lua b/src/TimeToDie/TimeToDie.lua index e39ad5b..6ff9ec4 100644 --- a/src/TimeToDie/TimeToDie.lua +++ b/src/TimeToDie/TimeToDie.lua @@ -10,7 +10,7 @@ local TimeToDie = { Refreshing = false, Settings = { -- Refresh time (seconds) : min=0.1, max=2, default = 0.1 - Refresh = 0.2, + Refresh = 0.1, -- History time (seconds) : min=5, max=120, default = 10+0.4 HistoryTime = 10 + 0.4, -- Max history count : min=20, max=500, default = 100 @@ -65,7 +65,7 @@ function TimeToDie:Init() if not Bastion.Globals.UnitInfo then Bastion.Globals.UnitInfo = Bastion.Cache:New() Bastion.Globals.EventManager:RegisterWoWEvent("UNIT_HEALTH", function(unitId) - self:UNIT_HEALTH(unitId) + --self:UNIT_HEALTH(unitId) end) end end @@ -74,6 +74,22 @@ function TimeToDie:IterableUnits2() return Bastion.ObjectManager.activeEnemies end +function TimeToDie:Update() + local currentTime = GetTime() + for key, _ in pairs(self.Units) do + local unit = self.Units[key] + local obj = Bastion.Globals.UnitManager:Get(key) + if not obj:Exists() or (unit.history and unit.history[1] and (currentTime - (unit.history[1].time + unit.time) > self.Settings.InactiveTime and obj:InCombatOdds() < 80)) or (obj:IsDead() or not UnitCanAttack("player", obj:GetOMToken()) or (obj:GetHealth() <= 1 and obj:GetMaxHealth() > 1)) then + self:UNIT_DIED(key) + end + end + ---@param unit Bastion.Unit + Bastion.ObjectManager.enemies:each(function(unit) + self:UNIT_HEALTH(unit:GetOMToken()) + return false + end) +end + ---@param force? boolean function TimeToDie:Refresh(force) if self:IsRefreshing() or (self.NextUpdate > GetTime() and not force) or (not Bastion.Enabled and not force) then @@ -83,18 +99,19 @@ function TimeToDie:Refresh(force) self.Refreshing = true self.LastStart = currentTime - self.NextUpdate = self.LastStart + 2 + self.NextUpdate = self.LastStart + .5 - local units = TimeToDie.Units + --[[ local units = TimeToDie.Units for key, _ in pairs(units) do local unit = units[key] if unit.history and unit.history[1] then local lastTime = unit.history[1].time + unit.time if currentTime - lastTime > self.Settings.InactiveTime and Bastion.Globals.UnitManager:Get(key):InCombatOdds() < 80 then - units[key] = nil + self:UNIT_DIED(key) end end - end + end ]] + self:Update() self.Refreshing = false end @@ -108,7 +125,7 @@ end ---@param unitId UnitId function TimeToDie:UNIT_HEALTH(unitId) local currentTime = GetTime() - if UnitExists(unitId) and UnitCanAttack("player", unitId) then + if UnitExists(unitId) and UnitCanAttack("player", unitId) and not UnitIsDeadOrGhost(unitId) then local unitGUID = UnitGUID(unitId) if unitGUID then local unitTable = self.Units[unitGUID] diff --git a/src/Unit/Unit.lua b/src/Unit/Unit.lua index 8e63031..09576b1 100644 --- a/src/Unit/Unit.lua +++ b/src/Unit/Unit.lua @@ -7,7 +7,7 @@ Bastion = ... ---@class Bastion.Unit ---@field cache Bastion.Cache ---@field id false | number ----@field ttd_ticker false | cbObject +---@field ttd_ticker false | FunctionContainer ---@field unit? WowGameObject ---@field aura_table Bastion.AuraTable | nil local Unit = { @@ -41,12 +41,12 @@ function Unit:UpdateHealth() end function Unit:__index(k) - local response = Bastion.ClassMagic:Resolve(Unit, k) - if k == "unit" then return rawget(self, k) end + local response = Bastion.ClassMagic:Resolve(Unit, k) + if response == nil then response = rawget(self, k) end @@ -523,8 +523,6 @@ function Unit:GetRawUnit() return self:GetOMToken() end -local isClassicWow = select(4, GetBuildInfo()) < 40000 - -- Check if two units are in melee -- function Unit:InMelee(unit) -- return UnitInMelee(self:GetOMToken(), unit:GetOMToken()) @@ -542,8 +540,6 @@ local flags = { Unknown = 0x200000, } -local losFlag = bit.bor(flags.M2Collision, flags.WMOCollision, flags.Terrain) - ---@param attachmentId number function Unit:GetAttachmentPosition(attachmentId) local x, y, z = GetUnitAttachmentPosition(self:GetOMToken(), attachmentId) @@ -629,11 +625,21 @@ local attachmentId = { Unknown17 = 75, } -local losFlag = bit.bor(0x1, 0x10, 0x100000) +local losFlag = bit.bor(flags.M2Collision, flags.WMOCollision, flags.EnityCollision) + +local ignoreLoS = { + [91005] = true, -- Naraxas +} -- Check if the unit can see another unit ---@param unit Bastion.Unit ---@return boolean function Unit:CanSee(unit) + local npcId = unit:GetID() + + if npcId and ignoreLoS[npcId] then + return true + end + local ax, ay, az = ObjectPosition(self:GetOMToken()) local ah = ObjectHeight(self:GetOMToken()) local attx, atty, attz = GetUnitAttachmentPosition(unit:GetOMToken(), attachmentId.Chest) diff --git a/src/_bastion.lua b/src/_bastion.lua index df01db3..2207e5f 100644 --- a/src/_bastion.lua +++ b/src/_bastion.lua @@ -1,4 +1,65 @@ ---@type Tinkr local Tinkr = ... +---@param path string +---@param ...? any +local function require(path, ...) + local func = nil + local newPath = path + local loader = nil + if newPath:sub(-4) ~= ".lua" and newPath:sub(-5) ~= ".luac" then + if FileExists(newPath .. ".lua") then + newPath = newPath .. ".lua" + elseif FileExists(newPath .. ".luac") then + newPath = newPath .. ".luac" + else + Tinkr:OnError(string.format("File not found: path(%s) newPath(%s)", path, newPath), -1) + return + end + end + + if newPath:sub(-4) == ".lua" then + func = loadstringsecure(ReadFile(newPath) or "", newPath) + elseif newPath:sub(-5) == ".luac" then + func = RunEncrypted(newPath) + else + Tinkr:OnError(string.format("Loader not found: path(%s) newPath(%s)", path, newPath), -1) + return + end + if type(func) == "string" then + if type(func) == "string" then + Tinkr:OnError(string.format("Loader did not return function: path(%s) newPath(%s) error(%s)", path, newPath, func or ""), -1) + return + end + end + setfenv(func, setmetatable({ ["_T"] = _T }, { + __index = function(t, v) + if v == "require" then + --print(v, t.__file) + return function(...) + return require(...) + end + end + if v == '__file' then + --print(v, newPath) + return path + end + if v == 'TINKR_SECURE' then + --print(v, t.__file, issecure(), Tinkr:GetSecure()) + return Tinkr:GetSecure() + end + return Tinkr.__ENV(t, v) + end + })) + + local call = { pcall(func, Tinkr, ...) } + -- print('call', call[1], call[2]) + if not call[1] then + -- print(self:OnLoadingScreen()) + Tinkr:OnError(call[2], -1) + end + table.remove(call, 1) + + return unpack(call) +end require("scripts/bastion/src/Bastion/Bastion"):Load()