forked from Bastion/Bastion
parent
cb4c49b1b3
commit
6a48a2e7ac
@ -0,0 +1,114 @@ |
|||||||
|
---@type Tinkr |
||||||
|
local Tinkr, |
||||||
|
---@class Bastion |
||||||
|
Bastion = ... |
||||||
|
|
||||||
|
---@alias Bastion.APL.Action.Type "spell" | "item" | "apl" | "sequence" | "variable" | "function" |
||||||
|
---@alias Bastion.APL.Action.Object Bastion.Spell | Bastion.Item | Bastion.APL |
||||||
|
|
||||||
|
-- APL Action class |
||||||
|
---@class Bastion.APL.Action |
||||||
|
local APLAction = {} |
||||||
|
APLAction.__index = APLAction |
||||||
|
|
||||||
|
|
||||||
|
---@class Bastion.APL.Action.New.Params |
||||||
|
---@field parent Bastion.APL |
||||||
|
---@field type Bastion.APL.Action.Type |
||||||
|
---@field object Bastion.APL.Action.Object |
||||||
|
---@field condition? false | string | fun(self: Bastion.APL.Action, object: Bastion.APL.Action.Object, target?: Bastion.Unit): boolean |
||||||
|
---@field onActionFunc? false | fun(object: Bastion.APL.Action.Object, target?: Bastion.Unit): any |
||||||
|
---@field actionUsableFunc? false | fun(object: Bastion.APL.Action.Object, target?: Bastion.Unit): boolean |
||||||
|
---@field executor? fun(self: Bastion.APL.Action): boolean |
||||||
|
---@field target? Bastion.Unit | false |
||||||
|
---@field targetIf? false | fun(object: Bastion.APL.Action.Object): Bastion.Unit |
||||||
|
|
||||||
|
---@param params Bastion.APL.Action.New.Params |
||||||
|
function APLAction:New(params) |
||||||
|
---@class Bastion.APL.Action |
||||||
|
local self = setmetatable({}, APLAction) |
||||||
|
self.parent = params.parent |
||||||
|
self.index = #self.parent.actions + 1 |
||||||
|
self.type = params.type |
||||||
|
self.object = params.object |
||||||
|
self.condition = params.condition or false |
||||||
|
self.onActionFunc = params.onActionFunc or false |
||||||
|
self.actionUsableFunc = params.actionUsableFunc or false |
||||||
|
self.executor = params.executor or false |
||||||
|
self.target = params.target or false |
||||||
|
self.targetIf = params.targetIf or false |
||||||
|
return self |
||||||
|
end |
||||||
|
|
||||||
|
function APLAction:Execute() |
||||||
|
return self.executor and self.executor(self) or false |
||||||
|
end |
||||||
|
|
||||||
|
---@class Bastion.APL.Action.New.Spell.Params |
||||||
|
---@field parent Bastion.APL |
||||||
|
---@field spell Bastion.Spell |
||||||
|
---@field condition? false | string | fun(self: Bastion.APL.Action, object: Bastion.Spell, target?: Bastion.Unit): boolean |
||||||
|
---@field target? Bastion.Unit |
||||||
|
---@field targetIf? fun(self: Bastion.Spell): Bastion.Unit |
||||||
|
|
||||||
|
---@param params Bastion.APL.Action.New.Spell.Params |
||||||
|
function APLAction:NewSpell(params) |
||||||
|
return self:New({ |
||||||
|
parent = params.parent, |
||||||
|
type = "spell", |
||||||
|
object = params.spell, |
||||||
|
condition = params.condition or false, |
||||||
|
target = params.target or params.spell:GetTarget(), |
||||||
|
targetIf = params.targetIf or false, |
||||||
|
onActionFunc = params.spell.OnCastFunc or false, |
||||||
|
actionUsableFunc = params.spell.CastableIfFunc or false, |
||||||
|
executor = function(this) |
||||||
|
local target = this.targetIf and this.targetIf(this.object) or this.target or nil |
||||||
|
return this.object:CastableIf(this.actionUsableFunc):OnCast(this.onActionFunc):Cast(target, this.condition) |
||||||
|
end, |
||||||
|
}) |
||||||
|
end |
||||||
|
|
||||||
|
---@class Bastion.APL.Action.New.Item.Params |
||||||
|
---@field parent Bastion.APL |
||||||
|
---@field item Bastion.Item |
||||||
|
---@field condition? false | string | fun(self: Bastion.APL.Action, object: Bastion.Item, target?: Bastion.Unit): boolean |
||||||
|
---@field target? Bastion.Unit |
||||||
|
---@field targetIf? fun(self: Bastion.Item): Bastion.Unit |
||||||
|
|
||||||
|
---@param params Bastion.APL.Action.New.Item.Params |
||||||
|
function APLAction:NewItem(params) |
||||||
|
return self:New({ |
||||||
|
parent = params.parent, |
||||||
|
type = "item", |
||||||
|
object = params.item, |
||||||
|
condition = params.condition or false, |
||||||
|
target = params.target or params.item:GetTarget() or false, |
||||||
|
targetIf = params.targetIf or false, |
||||||
|
onActionFunc = params.item.OnUseFunc or false, |
||||||
|
actionUsableFunc = params.item.UsableIfFunc or false, |
||||||
|
executor = function(this) |
||||||
|
return this.object:UsableIf(this.actionUsableFunc):OnUse(this.onActionFunc):Use( |
||||||
|
this.targetIf and this.targetIf(this.object) or this.target or nil, this.condition) |
||||||
|
end, |
||||||
|
}) |
||||||
|
end |
||||||
|
|
||||||
|
---@class Bastion.APL.Action.New.APL.Params |
||||||
|
---@field parent Bastion.APL |
||||||
|
---@field apl Bastion.APL |
||||||
|
---@field condition? false | string | fun(self: Bastion.APL.Action, object: Bastion.APL): boolean |
||||||
|
|
||||||
|
function APLAction:NewAPL(params) |
||||||
|
return self:New({ |
||||||
|
parent = params.parent, |
||||||
|
type = "apl", |
||||||
|
object = params.apl, |
||||||
|
condition = params.condition or false, |
||||||
|
executor = function(this) |
||||||
|
return this.object:Execute() |
||||||
|
end, |
||||||
|
}) |
||||||
|
end |
||||||
|
|
||||||
|
Bastion.APLAction = APLAction |
@ -0,0 +1,22 @@ |
|||||||
|
---@type Tinkr |
||||||
|
local Tinkr, |
||||||
|
---@class Bastion |
||||||
|
Bastion = ... |
||||||
|
|
||||||
|
-- APL Manager |
||||||
|
---@class Bastion.APLManager |
||||||
|
local APLManager = {} |
||||||
|
|
||||||
|
APLManager.__index = APLManager |
||||||
|
APLManager.__metatable = false |
||||||
|
|
||||||
|
function APLManager:New() |
||||||
|
---@class Bastion.APLManager |
||||||
|
local self = setmetatable({ |
||||||
|
APLs = {}, |
||||||
|
}, APLManager) |
||||||
|
|
||||||
|
return self |
||||||
|
end |
||||||
|
|
||||||
|
Bastion.APLManager = APLManager |
@ -0,0 +1,127 @@ |
|||||||
|
---@type Tinkr |
||||||
|
local Tinkr, |
||||||
|
---@class Bastion |
||||||
|
Bastion = ... |
||||||
|
|
||||||
|
---@class Bastion.TimeToDieManager |
||||||
|
---@field units table<string, Bastion.TimeToDieUnit> |
||||||
|
---@field recycle Bastion.TimeToDieUnit[] |
||||||
|
local TimeToDieManager = {} |
||||||
|
|
||||||
|
local tokenPrefixes = { |
||||||
|
"^arena[1-5]", |
||||||
|
"^boss[1-5]", |
||||||
|
"^focus", |
||||||
|
"^mouseover", |
||||||
|
"^none", |
||||||
|
"^party[1-4]", |
||||||
|
"^partypet[1-4]", |
||||||
|
"^pet", |
||||||
|
"^player", |
||||||
|
"^raid[1-40]", |
||||||
|
"^raidpet[1-40]", |
||||||
|
"^target", |
||||||
|
"^vehicle", |
||||||
|
"^nameplate[1-40]", |
||||||
|
"^spectated", |
||||||
|
} |
||||||
|
|
||||||
|
---@param token string |
||||||
|
local validateToken = function(token) |
||||||
|
for i = 1, #tokenPrefixes do |
||||||
|
if string.match(token, tokenPrefixes[i]) then |
||||||
|
return true |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
function TimeToDieManager:__index(k) |
||||||
|
if type(TimeToDieManager[k]) ~= "nil" then |
||||||
|
return TimeToDieManager[k] |
||||||
|
end |
||||||
|
|
||||||
|
local kguid = type(k) == "string" and validateToken(k) and ObjectGUID(k) or k |
||||||
|
|
||||||
|
if kguid and self.units[kguid] then |
||||||
|
return self.units[kguid] |
||||||
|
end |
||||||
|
|
||||||
|
if self.units[kguid] == nil then |
||||||
|
if Object(k) then |
||||||
|
--return self:SetObject(Bastion.Unit:New(Object(k) or k)) |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
function TimeToDieManager:New() |
||||||
|
---@class Bastion.TimeToDieManager |
||||||
|
local self = setmetatable({}, TimeToDieManager) |
||||||
|
self.units = {} |
||||||
|
self.recycle = {} |
||||||
|
return self |
||||||
|
end |
||||||
|
|
||||||
|
---@param unitId UnitIds |
||||||
|
function TimeToDieManager:NAME_PLATE_UNIT_ADDED(unitId) |
||||||
|
print("NAME_PLATE_UNIT_ADDED", unitId) |
||||||
|
end |
||||||
|
|
||||||
|
---@param unitId UnitIds |
||||||
|
function TimeToDieManager:NAME_PLATE_UNIT_REMOVED(unitId) |
||||||
|
print("NAME_PLATE_UNIT_REMOVED", unitId) |
||||||
|
end |
||||||
|
|
||||||
|
---@param unitId UnitIds |
||||||
|
function TimeToDieManager:UNIT_FLAGS(unitId) |
||||||
|
print("UNIT_FLAGS", unitId) |
||||||
|
end |
||||||
|
|
||||||
|
function TimeToDieManager:RegisterEvents() |
||||||
|
Bastion.EventManager:RegisterWoWEvent("NAME_PLATE_UNIT_ADDED", function(...) |
||||||
|
self:NAME_PLATE_UNIT_ADDED(...) |
||||||
|
end) |
||||||
|
|
||||||
|
Bastion.EventManager:RegisterWoWEvent("NAME_PLATE_UNIT_REMOVED", function(...) |
||||||
|
self:NAME_PLATE_UNIT_REMOVED(...) |
||||||
|
end) |
||||||
|
|
||||||
|
Bastion.EventManager:RegisterWoWEvent("UNIT_FLAGS", function(...) |
||||||
|
self:UNIT_FLAGS(...) |
||||||
|
end) |
||||||
|
end |
||||||
|
|
||||||
|
---@param unitGuid string |
||||||
|
function TimeToDieManager:GetUnit(unitGuid) |
||||||
|
if unitGuid and self.units[unitGuid] then |
||||||
|
return self.units[unitGuid] |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
---@param unitGuid string |
||||||
|
function TimeToDieManager:RemoveUnit(unitGuid) |
||||||
|
if type(self.units[unitGuid]) ~= "nil" then |
||||||
|
local oldUnit = self.units[unitGuid] |
||||||
|
self.units[unitGuid] = nil |
||||||
|
table.insert(self.recycle, oldUnit:Recycle()) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
---@param when number |
||||||
|
---@param healthPct number |
||||||
|
---@param unit? WowGameObject |
||||||
|
function TimeToDieManager:RecycleUnit(when, healthPct, unit) |
||||||
|
return Bastion.TimeToDieUnit:New(table.remove(self.recycle) or false, when, healthPct, unit) |
||||||
|
end |
||||||
|
|
||||||
|
---@param unitGuid string |
||||||
|
---@param healthPct number |
||||||
|
---@param when? number |
||||||
|
function TimeToDieManager:UpdateUnit(unitGuid, healthPct, when) |
||||||
|
local unitObject = self.units[unitGuid] |
||||||
|
when = when or GetTime() |
||||||
|
if not unitObject then |
||||||
|
unitObject = self:GetUnit(unitGuid) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
Bastion.TimeToDieManager = TimeToDieManager:New() |
@ -0,0 +1,120 @@ |
|||||||
|
---@type Tinkr |
||||||
|
local Tinkr, |
||||||
|
---@class Bastion |
||||||
|
Bastion = ... |
||||||
|
|
||||||
|
---@class Bastion.TimeToDieUnit |
||||||
|
local TimeToDieUnit = { |
||||||
|
Enums = { |
||||||
|
Duration = { |
||||||
|
DEFAULT_TTD = 30, |
||||||
|
FOREVER = 300, |
||||||
|
TRIVIAL = 5, |
||||||
|
}, |
||||||
|
DeathPercent = { |
||||||
|
[162099] = 0.5, -- General Kaal; Sanguine Depths |
||||||
|
[166608] = 0.1, -- Mueh'zala; De Other Side |
||||||
|
[164929] = 0.2, -- Tirnenn Villager; Mists of Tirna Scythe |
||||||
|
[164804] = 0.2, -- Droman Oulfarran; Mists of Tirna Scythe |
||||||
|
}, |
||||||
|
Excluded = { |
||||||
|
[23775] = true, -- Head of the Horseman |
||||||
|
[120651] = true, -- Explosives |
||||||
|
[156227] = true, -- Neferset Denizen |
||||||
|
[160966] = true, -- Thing from Beyond? |
||||||
|
[161895] = true, -- Thing from Beyond? |
||||||
|
[157452] = true, -- Nightmare Antigen in Carapace |
||||||
|
[158041] = 310126, -- N'Zoth with Psychic Shell |
||||||
|
[164698] = true, -- Tor'ghast Junk |
||||||
|
[177117] = 355790, -- Ner'zhul: Orb of Torment (Protected by Eternal Torment) |
||||||
|
[176581] = true, -- Painsmith: Spiked Ball |
||||||
|
[186150] = true, -- Soul Fragment (Gavel of the First Arbiter) |
||||||
|
[185685] = true, -- Season 3 Relics |
||||||
|
[185680] = true, -- Season 3 Relics |
||||||
|
[185683] = true, -- Season 3 Relics |
||||||
|
[183501] = 367573, -- Xy'mox: Genesis Bulwark |
||||||
|
[166969] = true, -- Frieda |
||||||
|
[166970] = true, -- Stavros |
||||||
|
[166971] = true, -- Niklaus |
||||||
|
[168113] = 329606, -- Grashaal (when shielded) |
||||||
|
[168112] = 329636, -- Kaal (when shielded) |
||||||
|
[193760] = true, -- Surging Ruiner (Raszageth) -- gives bad range information. |
||||||
|
[204560] = true, -- Incorporeal Being |
||||||
|
} |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
TimeToDieUnit.__index = TimeToDieUnit |
||||||
|
|
||||||
|
---@param recycledUnit Bastion.TimeToDieUnit | false |
||||||
|
---@param when number |
||||||
|
---@param healthPct number |
||||||
|
---@param unit? WowGameObject |
||||||
|
function TimeToDieUnit:New(recycledUnit, when, healthPct, unit) |
||||||
|
---@class Bastion.TimeToDieUnit |
||||||
|
local self = recycledUnit and recycledUnit:Recycle() or setmetatable({}, TimeToDieUnit) |
||||||
|
self.firstSeen = when |
||||||
|
self.firstHealthPct = healthPct |
||||||
|
|
||||||
|
self.lastSeen = when |
||||||
|
self.lastHealthPct = healthPct |
||||||
|
|
||||||
|
self.unit = unit or false |
||||||
|
|
||||||
|
self.rate = 0 |
||||||
|
self.n = 0 |
||||||
|
|
||||||
|
self.npcid = unit and unit:id() or false |
||||||
|
|
||||||
|
self.deathPercent = self.npcid and TimeToDieUnit.Enums.DeathPercent[self.npcid] or 0 |
||||||
|
self.deathTime = self.unit and (UnitIsTrivial(self.unit:unit()) and UnitLevel(self.unit:unit()) > -1) and |
||||||
|
TimeToDieUnit.Enums.TRIVIAL or TimeToDieUnit.Enums.DEFAULT_TTD |
||||||
|
|
||||||
|
self.excluded = self.npcid and TimeToDieUnit.Enums.Excluded[self.npcid] or false |
||||||
|
return self:Update(when, healthPct) |
||||||
|
end |
||||||
|
|
||||||
|
function TimeToDieUnit:Recycle() |
||||||
|
self.firstSeen = 0 |
||||||
|
self.firstHealthPct = 0 |
||||||
|
self.lastSeen = 0 |
||||||
|
self.lastHealthPct = 0 |
||||||
|
self.unit = false |
||||||
|
self.rate = 0 |
||||||
|
self.n = 0 |
||||||
|
self.npcid = 0 |
||||||
|
self.deathPercent = 0 |
||||||
|
self.deathTime = 0 |
||||||
|
self.excluded = false |
||||||
|
return self |
||||||
|
end |
||||||
|
|
||||||
|
---@param when number |
||||||
|
---@param healthPct number |
||||||
|
function TimeToDieUnit:Update(when, healthPct) |
||||||
|
local difference = self.lastHealthPct - healthPct |
||||||
|
|
||||||
|
-- We don't recalculate the rate when enemies heal. |
||||||
|
if difference > 0 then |
||||||
|
local elapsed = when - self.lastSeen |
||||||
|
|
||||||
|
-- If this is our first health difference, just store it. |
||||||
|
if self.n == 0 then |
||||||
|
self.rate = difference / elapsed |
||||||
|
self.n = 1 |
||||||
|
else |
||||||
|
local samples = min(self.n, 9) |
||||||
|
local newRate = self.rate * samples + (difference / elapsed) |
||||||
|
self.n = samples + 1 |
||||||
|
self.rate = newRate / self.n |
||||||
|
end |
||||||
|
|
||||||
|
self.deathTime = (healthPct - self.deathPercent) / self.rate |
||||||
|
end |
||||||
|
|
||||||
|
self.lastHealth = healthPct |
||||||
|
self.lastSeen = when |
||||||
|
return self |
||||||
|
end |
||||||
|
|
||||||
|
Bastion.TimeToDieUnit = TimeToDieUnit |
Loading…
Reference in new issue