diff --git a/src/Classes/BuildListControl.lua b/src/Classes/BuildListControl.lua index 8a46e7bb95..65e2083c7d 100644 --- a/src/Classes/BuildListControl.lua +++ b/src/Classes/BuildListControl.lua @@ -9,6 +9,9 @@ local s_format = string.format ---@class BuildListControl: ListControl local BuildListClass = newClass("BuildListControl", "ListControl") +---@param anchor Anchor? +---@param rect Rect? +---@param listMode any function BuildListClass:BuildListControl(anchor, rect, listMode) self:ListControl(anchor, rect, 20, "VERTICAL", false, listMode.list) self.listMode = listMode diff --git a/src/Classes/CalcBreakdownControl.lua b/src/Classes/CalcBreakdownControl.lua index 1154bcad02..3668cce32b 100644 --- a/src/Classes/CalcBreakdownControl.lua +++ b/src/Classes/CalcBreakdownControl.lua @@ -16,6 +16,7 @@ local band = AND64 -- bit.band ---@class CalcBreakdownControl: Control, ControlHost local CalcBreakdownClass = newClass("CalcBreakdownControl", "Control", "ControlHost") +---@param calcsTab CalcsTab function CalcBreakdownClass:CalcBreakdownControl(calcsTab) self:Control() self:ControlHost() diff --git a/src/Classes/CalcSectionControl.lua b/src/Classes/CalcSectionControl.lua index 1f796ee92c..66dea3cb87 100644 --- a/src/Classes/CalcSectionControl.lua +++ b/src/Classes/CalcSectionControl.lua @@ -8,8 +8,15 @@ local t_insert = table.insert ---@class CalcSectionControl: Control, ControlHost local CalcSectionClass = newClass("CalcSectionControl", "Control", "ControlHost") +---@param calcsTab CalcsTab +---@param width any +---@param id any +---@param group any +---@param colour any +---@param subSection any +---@param updateFunc any function CalcSectionClass:CalcSectionControl(calcsTab, width, id, group, colour, subSection, updateFunc) - self:Control(calcsTab, {0, 0, width, 0}) + self:Control(nil, {0, 0, width, 0}) self:ControlHost() self.calcsTab = calcsTab self.id = id diff --git a/src/Classes/CalcsTab.lua b/src/Classes/CalcsTab.lua index 16aa139e03..4c06f2cd8c 100644 --- a/src/Classes/CalcsTab.lua +++ b/src/Classes/CalcsTab.lua @@ -498,8 +498,8 @@ function CalcsTabClass:BuildOutput() end -- Retrieve calculator functions - self.nodeCalculator = { self.calcs.getNodeCalculator(self.build) } - self.miscCalculator = { self.calcs.getMiscCalculator(self.build) } + local miscCalcFunc, miscCalcBase = self.calcs.getMiscCalculator(self.build) + self.miscCalculator = { miscCalcFunc, miscCalcBase } end -- Controls the coroutine that calculates node power @@ -702,12 +702,8 @@ function CalcsTabClass:CalculateCombinedOffDefStat(original, modified) return dpsIncr / modifiedDps, defence end -function CalcsTabClass:GetNodeCalculator() - return unpack(self.nodeCalculator) -end - function CalcsTabClass:GetMiscCalculator() - return unpack(self.miscCalculator) + return self.miscCalculator[1], self.miscCalculator[2] end function CalcsTabClass:CreateUndoState() diff --git a/src/Classes/CompareCalcsHelpers.lua b/src/Classes/CompareCalcsHelpers.lua index 455c7b3a23..1a5254e8d0 100644 --- a/src/Classes/CompareCalcsHelpers.lua +++ b/src/Classes/CompareCalcsHelpers.lua @@ -40,6 +40,8 @@ function M.FormatCalcModName(modName) end -- Resolve a modifier's source to a human-readable name +---@param mod Mod +---@param build Build function M.ResolveSourceName(mod, build) if not mod.source then return "" end local sourceType = mod.source:match("[^:]+") or "" @@ -138,6 +140,8 @@ function M.FormatModRow(row, sectionData, build) end -- Get breakdown text lines for a build's actor +---@param sectionData any +---@param build Build function M.GetBreakdownLines(sectionData, build) if not sectionData.breakdown then return nil end local calcsActor = build.calcsTab and build.calcsTab.calcsEnv and build.calcsTab.calcsEnv.player @@ -164,6 +168,8 @@ end -- Draw the calcs hover tooltip showing breakdown for both builds with common/unique grouping -- tooltip, primaryBuild, primaryLabel passed as args instead of self +---@param tooltip Tooltip +---@param primaryBuild Build function M.DrawCalcsTooltip(tooltip, primaryBuild, primaryLabel, colData, rowLabel, rowX, rowY, rowW, rowH, vp, compareEntry) if tooltip:CheckForUpdate(colData, rowLabel) then -- Get calcsEnv actors (these have breakdown data populated) @@ -318,6 +324,8 @@ function M.DrawCalcsTooltip(tooltip, primaryBuild, primaryLabel, colData, rowLab end -- Resolve a modifier's source name for breakdown panel display +---@param mod Mod +---@param build Build local function resolveModSource(mod, build) local sourceType = mod.source and mod.source:match("[^:]+") or "?" local sourceName = "" @@ -352,6 +360,7 @@ local function resolveModSource(mod, build) end -- Draw a breakdown panel for a single build's SkillBuffs or SkillDebuffs, +---@param build Build function M.DrawSkillBreakdownPanel(build, breakdownKey, label, cellX, cellY, cellW, cellH, vp) local player = build.calcsTab and build.calcsTab.calcsEnv and build.calcsTab.calcsEnv.player diff --git a/src/Classes/ConfigTab.lua b/src/Classes/ConfigTab.lua index 3e8e7155d1..3d6a27badf 100644 --- a/src/Classes/ConfigTab.lua +++ b/src/Classes/ConfigTab.lua @@ -13,13 +13,13 @@ local s_upper = string.upper local varList = require("Modules.ConfigOptions") local configModBrowser = require("Modules.ConfigModBrowser") ----@class CustomModBlockControl : Control, ControlHost -local CustomModBlockClass = newClass("CustomModBlockControl", "Control", "ControlHost") +---@class CustomModBlockControl: ControlHost, Control +local CustomModBlockClass = newClass("CustomModBlockControl", "ControlHost", "Control") ----@param anchor Anchor ----@param rect Rect +---@param anchor Anchor? +---@param rect Rect? ---@param configTab ConfigTab ----@param blockIndex any +---@param blockIndex integer ---@param blockData any function CustomModBlockClass:CustomModBlockControl(anchor, rect, configTab, blockIndex, blockData) self:Control(anchor, rect) diff --git a/src/Classes/Control.lua b/src/Classes/Control.lua index a63a5a830a..9e59aab634 100644 --- a/src/Classes/Control.lua +++ b/src/Classes/Control.lua @@ -6,6 +6,7 @@ local t_insert = table.insert local m_floor = math.floor +---@enum (key) AnchorPoint local anchorPos = { ["TOPLEFT"] = { 0 , 0 }, ["TOP"] = { 0.5, 0 }, @@ -39,10 +40,19 @@ local rect = { ---@field shown Prop ---@field x Prop? ---@field y Prop? +---@field width Prop? +---@field height Prop? ---@field collapseY number? An additional offset which is applied when this control uses a collapsed anchor. ---@field collapseX number? An additional offset which is applied when this control uses a collapsed anchor. local ControlClass = newClass("Control") +---@generic T +---@alias Prop (fun(self: self): T) | T +---@alias Anchor [AnchorPoint, Control|ControlHost|nil, AnchorPoint, boolean|nil] +---@alias Rect [Prop?,Prop?, Prop?, Prop?] + +---@param anchor? Anchor +---@param rect? Rect function ControlClass:Control(anchor, rect) self.rectStart = rect or {0, 0, 0, 0} self.x, self.y, self.width, self.height = unpack(self.rectStart) @@ -160,4 +170,4 @@ function ControlClass:TabAdvance(step) end end return self -end \ No newline at end of file +end diff --git a/src/Classes/GemSelectControl.lua b/src/Classes/GemSelectControl.lua index f5a434c530..6700cbc7ca 100644 --- a/src/Classes/GemSelectControl.lua +++ b/src/Classes/GemSelectControl.lua @@ -18,6 +18,12 @@ local toolTipText = "Prefix tag searches with a colon and exclude tags with a da ---@class GemSelectControl: EditControl local GemSelectClass = newClass("GemSelectControl", "EditControl") +---@param anchor Anchor? +---@param rect Rect? +---@param skillsTab SkillsTab +---@param index integer +---@param changeFunc fun(...) +---@param forceTooltip boolean function GemSelectClass:GemSelectControl(anchor, rect, skillsTab, index, changeFunc, forceTooltip) self:EditControl(anchor, rect, nil, nil, "^ %a':-") self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({ "TOPRIGHT", self, "TOPRIGHT" }, { -1, 0, 18, 0 }, (self.height - 4) * 4) diff --git a/src/Classes/ItemDBControl.lua b/src/Classes/ItemDBControl.lua index 1691558d42..fbb004f766 100644 --- a/src/Classes/ItemDBControl.lua +++ b/src/Classes/ItemDBControl.lua @@ -13,6 +13,15 @@ local m_floor = math.floor ---@class ItemDBControl: ListControl local ItemDBClass = newClass("ItemDBControl", "ListControl") +---@class ItemDBData +---@field list table +---@field loading boolean? + +---@param anchor Anchor? +---@param rect Rect? +---@param itemsTab ItemsTab +---@param db ItemDBData +---@param dbType "RARE"|"UNIQUE" function ItemDBClass:ItemDBControl(anchor, rect, itemsTab, db, dbType) self:ListControl(anchor, rect, 16, "VERTICAL", false) self.itemsTab = itemsTab diff --git a/src/Classes/ItemListControl.lua b/src/Classes/ItemListControl.lua index f2a4d61ced..b1cef41e05 100644 --- a/src/Classes/ItemListControl.lua +++ b/src/Classes/ItemListControl.lua @@ -9,6 +9,10 @@ local t_insert = table.insert ---@class ItemListControl: ListControl local ItemListClass = newClass("ItemListControl", "ListControl") +---@param anchor Anchor? +---@param rect Rect? +---@param itemsTab ItemsTab +---@param forceTooltip boolean? function ItemListClass:ItemListControl(anchor, rect, itemsTab, forceTooltip) self:ListControl(anchor, rect, 16, "VERTICAL", true, itemsTab.itemOrderList, forceTooltip) self.itemsTab = itemsTab diff --git a/src/Classes/ItemSlotControl.lua b/src/Classes/ItemSlotControl.lua index 95ee0b76f2..640b2c9277 100644 --- a/src/Classes/ItemSlotControl.lua +++ b/src/Classes/ItemSlotControl.lua @@ -12,6 +12,13 @@ local BuildExportPoE2 = LoadModule("Modules/BuildExportPoE2") ---@class ItemSlotControl: DropDownControl local ItemSlotClass = newClass("ItemSlotControl", "DropDownControl") +---@param anchor Anchor? +---@param x Prop +---@param y Prop +---@param itemsTab ItemsTab +---@param slotName string +---@param slotLabel? string +---@param nodeId integer? function ItemSlotClass:ItemSlotControl(anchor, x, y, itemsTab, slotName, slotLabel, nodeId) self:DropDownControl(anchor, {x, y, 310, 20}, { }, function(index, value) if self.items[index] ~= self.selItemId then diff --git a/src/Classes/LabelControl.lua b/src/Classes/LabelControl.lua index 04d084ced7..194f4d7ded 100644 --- a/src/Classes/LabelControl.lua +++ b/src/Classes/LabelControl.lua @@ -6,6 +6,9 @@ ---@class LabelControl: Control local LabelClass = newClass("LabelControl", "Control") +---@param anchor? Anchor +---@param rect? Rect +---@param label? Prop function LabelClass:LabelControl(anchor, rect, label) self:Control(anchor, rect) self.label = label @@ -18,4 +21,4 @@ end function LabelClass:Draw() local x, y = self:GetPos() DrawString(x, y, "LEFT", self:GetProperty("height"), "VAR", self:GetProperty("label")) -end \ No newline at end of file +end diff --git a/src/Classes/ListControl.lua b/src/Classes/ListControl.lua index 3d56711104..1ffc492acb 100644 --- a/src/Classes/ListControl.lua +++ b/src/Classes/ListControl.lua @@ -30,9 +30,17 @@ local m_min = math.min local m_max = math.max local m_floor = math.floor ----@class ListControl: Control, ControlHost +---@class ListControl: Control, ControlHost +---@field list T[] local ListClass = newClass("ListControl", "Control", "ControlHost") +---@param anchor Anchor? +---@param rect Rect? +---@param rowHeight number +---@param scroll "HORIZONTAL"|"VERTICAL"|boolean|nil +---@param isMutable boolean? +---@param list any[]? +---@param forceTooltip? any function ListClass:ListControl(anchor, rect, rowHeight, scroll, isMutable, list, forceTooltip) self:Control(anchor, rect) self:ControlHost() diff --git a/src/Classes/ModStore.lua b/src/Classes/ModStore.lua index c31acde6c8..12d29f1f7d 100644 --- a/src/Classes/ModStore.lua +++ b/src/Classes/ModStore.lua @@ -27,6 +27,12 @@ local conditionName = setmetatable({ }, { __index = function(t, var) return t[var] end }) +-- TODO: very incomplete +---@class ModCfg +---@field flags number? bit mask +---@field keywordFlags number? +---@field skillName string? +---@field source string? ---@class ModStore local ModStoreClass = newClass("ModStore") @@ -154,6 +160,10 @@ function ModStoreClass:Combine(modType, cfg, ...) end end +---@param modType string +---@param cfg? ModCfg +---@param ... string +---@return number function ModStoreClass:Sum(modType, cfg, ...) local flags, keywordFlags = 0, 0 local source @@ -200,6 +210,9 @@ function ModStoreClass:SumNegativeValues(modType, cfg, modName, ...) return total end +---@param cfg? ModCfg +---@param ... string +---@return number function ModStoreClass:More(cfg, ...) local flags, keywordFlags = 0, 0 local source @@ -222,6 +235,9 @@ function ModStoreClass:Flag(cfg, ...) return self:FlagInternal(self, cfg, flags, keywordFlags, source, ...) end +---@param cfg? ModCfg +---@param ... string +---@return any function ModStoreClass:Override(cfg, ...) local flags, keywordFlags = 0, 0 local source @@ -233,6 +249,9 @@ function ModStoreClass:Override(cfg, ...) return self:OverrideInternal(self, cfg, flags, keywordFlags, source, ...) end +---@param cfg? ModCfg +---@param ... string +---@return any[] function ModStoreClass:List(cfg, ...) local flags, keywordFlags = 0, 0 local source @@ -246,6 +265,10 @@ function ModStoreClass:List(cfg, ...) return result end +---@param modType string +---@param cfg? ModCfg +---@param ... string +---@return table[] function ModStoreClass:Tabulate(modType, cfg, ...) local flags, keywordFlags = 0, 0 local source @@ -289,6 +312,10 @@ function ModStoreClass:HasMod(modType, cfg, ...) return self:HasModInternal(modType, flags, keywordFlags, source, ...) end +---@param var string +---@param cfg? ModCfg +---@param noMod? boolean +---@return boolean function ModStoreClass:GetCondition(var, cfg, noMod) if (cfg and cfg.overrideCond and cfg.overrideCond[var] ~= nil) then return cfg.overrideCond[var] @@ -297,10 +324,17 @@ function ModStoreClass:GetCondition(var, cfg, noMod) end end +---@param var string +---@param cfg? ModCfg +---@param noMod? boolean +---@return number function ModStoreClass:GetMultiplier(var, cfg, noMod) return (not noMod and self:Override(cfg, multiplierName[var])) or (self.multipliers[var] or 0) + (self.parent and self.parent:GetMultiplier(var, cfg, true) or 0) + (not noMod and self:Sum("BASE", cfg, multiplierName[var]) or 0) end +---@param stat string +---@param cfg? ModCfg +---@return number function ModStoreClass:GetStat(stat, cfg) if stat == "ManaReservedPercent" then local reservedPercentMana = 0 @@ -346,6 +380,10 @@ function ModStoreClass:GetStat(stat, cfg) end end +---@param mod Mod +---@param cfg? ModCfg +---@param globalLimits? table +---@return any function ModStoreClass:EvalMod(mod, cfg, globalLimits) local value = mod.value local GetStat = self.GetStat diff --git a/src/Classes/NotableDBControl.lua b/src/Classes/NotableDBControl.lua index 5c574db0ec..ac6ab00971 100644 --- a/src/Classes/NotableDBControl.lua +++ b/src/Classes/NotableDBControl.lua @@ -24,6 +24,7 @@ end ---@class NotableDBControl: ListControl local NotableDBClass = newClass("NotableDBControl", "ListControl") +---@param itemsTab ItemsTab function NotableDBClass:NotableDBControl(anchor, rect, itemsTab, db, dbType) local headerHeight = 96 local innerRect = {rect[1], rect[2]+headerHeight, rect[3], rect[4]-headerHeight} diff --git a/src/Classes/PassiveMasteryControl.lua b/src/Classes/PassiveMasteryControl.lua index 1b924f806b..09a8ff1019 100644 --- a/src/Classes/PassiveMasteryControl.lua +++ b/src/Classes/PassiveMasteryControl.lua @@ -13,13 +13,23 @@ local m_floor = math.floor ---@class PassiveMasteryControl: ListControl local PassiveMasteryControlClass = newClass("PassiveMasteryControl", "ListControl") +---@class MasterListElem +---@field label string +---@field id number + +---@param anchor Anchor? +---@param rect Rect +---@param list MasterListElem[] +---@param treeTab TreeTab +---@param node Node +---@param saveButton ButtonControl function PassiveMasteryControlClass:PassiveMasteryControl(anchor, rect, list, treeTab, node, saveButton) self.list = list or { } -- automagical width for j=1,#list do rect[3] = m_max(rect[3], DrawStringWidth(16, "VAR", list[j].label) + 5) end - self:ListControl(anchor, rect, 16, false, false, self.list) + self:ListControl(anchor, rect, 16, nil, false, self.list) self.treeTab = treeTab self.treeView = treeTab.viewer self.node = node diff --git a/src/Classes/PassiveSpec.lua b/src/Classes/PassiveSpec.lua index 7b6da9ca25..636204787e 100644 --- a/src/Classes/PassiveSpec.lua +++ b/src/Classes/PassiveSpec.lua @@ -23,8 +23,13 @@ local legacyClassIdMap = { } ---@class PassiveSpec: UndoHandler +---@field nodes table +---@field allocNodes table local PassiveSpecClass = newClass("PassiveSpec", "UndoHandler") +---@param build Build +---@param treeVersion any +---@param convert? any function PassiveSpecClass:PassiveSpec(build, treeVersion, convert) self:UndoHandler() @@ -56,6 +61,7 @@ function PassiveSpecClass:Init(treeVersion, convert) for _, treeNode in pairs(self.tree.nodes) do -- Exclude proxy or groupless nodes, as well as expansion sockets if treeNode.group and not treeNode.isProxy and not treeNode.group.isProxy and (not treeNode.expansionJewel or not treeNode.expansionJewel.parent) then + ---@class Node self.nodes[treeNode.id] = setmetatable({ linked = { }, power = { } diff --git a/src/Classes/PassiveTree.lua b/src/Classes/PassiveTree.lua index f052c4d4b0..9b08e54b7e 100644 --- a/src/Classes/PassiveTree.lua +++ b/src/Classes/PassiveTree.lua @@ -35,7 +35,25 @@ local function getFile(URL) return #page > 0 and page end +---@class PassiveTreeGroup +---@field x number +---@field y number +---@field orbits integer[] +---@field nodes integer[] +---@field background any? +---@field isProxy boolean? ---@class PassiveTree +---@field classes any[] A list of classes on the tree +---@field alternate_ascendancies any[]? +---@field tree "Default"|"DefaultAltAscendancies" +---@field groups PassiveTreeGroup[] +---@field nodes table<"root"|integer, Node> +---@field jewelSlots integer[] +---@field min_x integer +---@field min_y integer +---@field max_x integer +---@field max_y integer +---@field constants table local PassiveTreeClass = newClass("PassiveTree") function PassiveTreeClass:PassiveTree(treeVersion) @@ -191,7 +209,9 @@ function PassiveTreeClass:PassiveTree(treeVersion) self.sockets = { } self.masteryEffects = { } local nodeMap = { } - for _, node in pairs(self.nodes) do + for _, n in pairs(self.nodes) do + ---@class Node + local node = n node.id = node.skill node.iname = node.stringId node.g = node.group diff --git a/src/Classes/PassiveTreeView.lua b/src/Classes/PassiveTreeView.lua index 8a854c6c45..86ffcd4659 100644 --- a/src/Classes/PassiveTreeView.lua +++ b/src/Classes/PassiveTreeView.lua @@ -139,6 +139,11 @@ end -- Returns the draw color for a node when compare overlay is active. -- Handles diff coloring for allocated/unallocated, mastery changes, and jewel socket differences. +---@param node Node +---@param compareNode Node? +---@param spec PassiveSpec +---@param build Build +---@param nodeDefaultColor any function PassiveTreeViewClass:GetCompareNodeColor(node, compareNode, spec, build, nodeDefaultColor) if not compareNode then return nodeDefaultColor @@ -1444,6 +1449,7 @@ function PassiveTreeViewClass:Zoom(level, viewPort) self.zoomY = relY + (self.zoomY - relY) * factor end +---@param build Build function PassiveTreeViewClass:Focus(x, y, viewPort, build) self.zoomLevel = 20 self.zoom = 1.2 ^ self.zoomLevel @@ -1547,6 +1553,9 @@ function PassiveTreeViewClass:DoesNodeMatchSearchParams(build, node) end end +---@param tooltip Tooltip +---@param node Node +---@param build Build function PassiveTreeViewClass:AddNodeName(tooltip, node, build) local fontSizeBig = main.showFlavourText and 18 or 16 tooltip:SetRecipe(node.infoRecipe) @@ -1606,6 +1615,10 @@ function PassiveTreeViewClass:AddNodeName(tooltip, node, build) end end +---@param tooltip Tooltip +---@param node Node +---@param build Build +---@param incSmallPassiveSkillEffect number? Whether the function should stop after writing the mod info, before any allocation-specific info function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build, incSmallPassiveSkillEffect) local fontSizeBig = main.showFlavourText and 18 or 16 tooltip.center = true diff --git a/src/Classes/SharedItemListControl.lua b/src/Classes/SharedItemListControl.lua index 7d0583722f..b578a390cb 100644 --- a/src/Classes/SharedItemListControl.lua +++ b/src/Classes/SharedItemListControl.lua @@ -10,6 +10,10 @@ local t_remove = table.remove ---@class SharedItemListControl: ListControl local SharedItemListClass = newClass("SharedItemListControl", "ListControl") +---@param anchor Anchor? +---@param rect Rect? +---@param itemsTab ItemsTab +---@param forceTooltip boolean? function SharedItemListClass:SharedItemListControl(anchor, rect, itemsTab, forceTooltip) self:ListControl(anchor, rect, 16, "VERTICAL", true, main.sharedItemList, forceTooltip) self.itemsTab = itemsTab diff --git a/src/Classes/SkillListControl.lua b/src/Classes/SkillListControl.lua index 954b14cae4..95e5966630 100644 --- a/src/Classes/SkillListControl.lua +++ b/src/Classes/SkillListControl.lua @@ -29,6 +29,9 @@ local slot_map = { ---@class SkillListControl: ListControl local SkillListClass = newClass("SkillListControl", "ListControl") +---@param anchor Anchor? +---@param rect Rect? +---@param skillsTab SkillsTab function SkillListClass:SkillListControl(anchor, rect, skillsTab) self:ListControl(anchor, rect, 16, "VERTICAL", true, skillsTab.socketGroupList) self.skillsTab = skillsTab diff --git a/src/Classes/SkillSetListControl.lua b/src/Classes/SkillSetListControl.lua index 415f7581cc..35cecbe2d3 100644 --- a/src/Classes/SkillSetListControl.lua +++ b/src/Classes/SkillSetListControl.lua @@ -12,6 +12,9 @@ local s_format = string.format ---@class SkillSetListControl: ListControl local SkillSetListClass = newClass("SkillSetListControl", "ListControl") +---@param anchor Anchor? +---@param rect Rect? +---@param skillsTab SkillsTab function SkillSetListClass:SkillSetListControl(anchor, rect, skillsTab) self:ListControl(anchor, rect, 16, "VERTICAL", true, skillsTab.skillSetOrderList) self.skillsTab = skillsTab diff --git a/src/Classes/TimelessJewelSocketControl.lua b/src/Classes/TimelessJewelSocketControl.lua index 3e841231df..5328e73976 100644 --- a/src/Classes/TimelessJewelSocketControl.lua +++ b/src/Classes/TimelessJewelSocketControl.lua @@ -9,6 +9,12 @@ local m_min = math.min ---@class TimelessJewelSocketControl: DropDownControl local TimelessJewelSocketClass = newClass("TimelessJewelSocketControl", "DropDownControl") +---@param anchor Anchor? +---@param rect Rect? +---@param list any[] +---@param selFunc any +---@param build Build +---@param socketViewer any function TimelessJewelSocketClass:TimelessJewelSocketControl(anchor, rect, list, selFunc, build, socketViewer) self:DropDownControl(anchor, rect, list, selFunc) self.build = build diff --git a/src/Classes/TradeQuery.lua b/src/Classes/TradeQuery.lua index 69c8d6d26c..cdff5eedb2 100644 --- a/src/Classes/TradeQuery.lua +++ b/src/Classes/TradeQuery.lua @@ -22,6 +22,7 @@ local baseSlots = { "Weapon 1", "Weapon 2", "Weapon 1 Swap", "Weapon 2 Swap", "H ---@class TradeQuery local TradeQueryClass = newClass("TradeQuery") +---@param itemsTab ItemsTab function TradeQueryClass:TradeQuery(itemsTab) self.itemsTab = itemsTab self.itemsTab.leagueDropList = { } diff --git a/src/Modules/Build.lua b/src/Modules/Build.lua index 6287f7a485..aec7c05ded 100644 --- a/src/Modules/Build.lua +++ b/src/Modules/Build.lua @@ -17,6 +17,10 @@ local function firstToUpper(str) return (str:gsub("^%l", string.upper)) end +---@class Build: ControlHost +---@field spec PassiveSpec added by TreeTab +---@field powerBuilderProgressCallback fun(progress: number)? +---@field powerBuilderCallback fun()? local buildMode = new("ControlHost"):ControlHost() local function InsertIfNew(t, val) @@ -1351,7 +1355,7 @@ function buildMode:OnFrame(inputEvents) self.controls.breakdown:SetBreakdownData(unpack(self.breakdownInputs)) end self:RefreshStatList() - self.configTab.calcFunc, self.configTab.calcBase = self.calcsTab:GetMiscCalculator(self) + self.configTab.calcFunc, self.configTab.calcBase = self.calcsTab:GetMiscCalculator() end if main.showThousandsSeparators ~= self.lastShowThousandsSeparators then self:RefreshStatList() diff --git a/src/Modules/CalcActiveSkill.lua b/src/Modules/CalcActiveSkill.lua index 8e821a387d..e8365205a4 100644 --- a/src/Modules/CalcActiveSkill.lua +++ b/src/Modules/CalcActiveSkill.lua @@ -143,6 +143,7 @@ end -- Create an active skill using the given active gem and list of support gems -- It will determine the base flag set, and check which of the support gems can support this skill function calcs.createActiveSkill(activeEffect, supportList, env, actor, socketGroup, summonSkill) + ---@class ActiveSkill local activeSkill = { activeEffect = activeEffect, supportList = supportList, @@ -162,7 +163,9 @@ function calcs.createActiveSkill(activeEffect, supportList, env, actor, socketGr end -- Initialise skill flag set ('attack', 'projectile', etc) - local statSet, skillFlags + ---@class SkillFlags + local skillFlags + local statSet if env.mode == "CALCS" then statSet = activeEffect.grantedEffect.statSets[activeEffect.statSetCalcs.index] skillFlags = statSet and copyTable(statSet.baseFlags) or { } @@ -672,6 +675,7 @@ function calcs.buildActiveSkillModList(env, activeSkill) effectiveRange = env.configInput.enemyDistance or env.configPlaceholder.enemyDistance -- Build config structure for modifier searches + ---@class ModCfg activeSkill.skillCfg = { flags = bor(skillModFlags, activeSkill.weapon1Flags or activeSkill.weapon2Flags or 0), keywordFlags = skillKeywordFlags, diff --git a/src/Modules/CalcBase.lua b/src/Modules/CalcBase.lua index cf23cec318..939ec803bd 100644 --- a/src/Modules/CalcBase.lua +++ b/src/Modules/CalcBase.lua @@ -2,3 +2,92 @@ ---@class Calcs local calcs = {} return calcs + +---@class Output +---@field MainHand Output? +---@field OffHand Output? +---@field Minion Output? +---@field ActivePhantasmLimit number? +---@field ActiveSpectreLimit number? +---@field BattleCryExertsCount number? +---@field BattleMageCryCastTime number? +---@field BattleMageCryCooldown number? +---@field BattleMageCryDuration number? +---@field BattlemageUpTimeRatio number? +---@field BleedDamage number? +---@field ChaosHitAverage number? +---@field ChaosResist number? +---@field ColdHitAverage number? +---@field ColdResistOverCap number? +---@field ColdResistTotal number? +---@field CullMultiplier number? +---@field Dex number? +---@field EffectiveBlockChance number? +---@field EffectiveProjectileBlockChance number? +---@field EffectiveSpellBlockChance number? +---@field EffectiveSpellProjectileBlockChance number? +---@field EnergyShieldLeechDuration number? +---@field EnergyShieldRecoupRecoveryAvg number? +---@field EnergyShieldRegenRecovery number? +---@field ESCost number? +---@field FireHitAverage number? +---@field FireResistOverCap number? +---@field FireResistTotal number? +---@field FreezeChanceOnCrit number? +---@field FreezeChanceOnHit number? +---@field GlobalWarcryUptimeRatio number? +---@field IgniteAvoidChance number? +---@field IgniteChanceOnCrit number? +---@field IgniteChanceOnHit number? +---@field InfernalCryCastTime number? +---@field InfernalCryCooldown number? +---@field InfernalCryDuration number? +---@field InfernalExertsCount number? +---@field InfernalUpTimeRatio number? +---@field Int number? +---@field LifeCancellableReservation number? +---@field LifeCost number? +---@field LifeLeechDuration number? +---@field LifeRecoupRecoveryAvg number? +---@field LifeRegenRecovery number? +---@field LifeReservedPercent number? +---@field LifeUnreserved number? +---@field LightningHitAverage number? +---@field LightningResist number? +---@field LightningResistOverCap number? +---@field LightningResistTotal number? +---@field ManaCost number? +---@field ManaCostRaw number? +---@field ManaHasCost boolean? +---@field ManaLeechDuration number? +---@field ManaRecoupRecoveryAvg number? +---@field ManaRegenRecovery number? +---@field ManaUnreserved number? +---@field PhysicalTakenDamage number? +---@field PhysicalTakenHit number? +---@field PoisonAvoidChance number? +---@field RageCost number? +---@field ReservationDpsMultiplier number? +---@field ReturnChance number? +---@field SelfIgniteDuration number? +---@field SelfIgniteEffect number? +---@field SelfPoisonDuration number? +---@field SelfPoisonEffect number? +---@field Str number? +---@field TotalVaalRejuvenationTotemLife number? +---@field TotemChaosResist number? +---@field TotemLife number? + +---@class Breakdown +---@field MainHand Breakdown? +---@field OffHand Breakdown? + +---@class Actor +---@field output Output +---@field modDB ModDB +---@field enemy Actor? +---@field breakdown? Breakdown? + +---@class ActiveSkill +---@field skillModList ModList +---@field skillCfg ModCfg diff --git a/src/Modules/CalcBreakdown.lua b/src/Modules/CalcBreakdown.lua index 63c38bb120..eabb0d2bc6 100644 --- a/src/Modules/CalcBreakdown.lua +++ b/src/Modules/CalcBreakdown.lua @@ -14,7 +14,8 @@ local m_max = math.max local s_format = string.format return function(modDB, output, actor) - local breakdown = { } + ---@class Breakdown + local breakdown = {} function breakdown.multiChain(out, chain) local base = (chain.base and chain.base[2]) or nil diff --git a/src/Modules/CalcDefence.lua b/src/Modules/CalcDefence.lua index 3efeeab9f0..4e7e4b44a6 100644 --- a/src/Modules/CalcDefence.lua +++ b/src/Modules/CalcDefence.lua @@ -430,6 +430,7 @@ end ---@param actor table actor (with output and modDB) for which to calculate the damage ---@return number, table sum of damages and a table of taken damage parts function calcs.takenHitFromDamage(rawDamage, damageType, actor) + ---@class Output local output = actor.output local modDB = actor.modDB local function damageMitigationMultiplierForType(damage, type) @@ -469,6 +470,7 @@ end ---@param actor table actor (with output and modDB) for which to calculate the pools ---@return table pools reduced by damage function calcs.reducePoolsByDamage(poolTable, damageTable, actor) + ---@class Output local output = actor.output local modDB = actor.modDB local poolTbl = poolTable or { } @@ -766,7 +768,9 @@ end function calcs.defence(env, actor) local modDB = actor.modDB local enemyDB = actor.enemy.modDB + ---@class Output local output = actor.output + ---@class Breakdown local breakdown = actor.breakdown local condList = modDB.conditions @@ -829,6 +833,7 @@ function calcs.defence(env, actor) end end + ---@alias MinMaxTotalBreakdownResist [string, string, string] -- Resistances output["PhysicalResist"] = 0 @@ -2032,7 +2037,9 @@ end function calcs.buildDefenceEstimations(env, actor) local modDB = actor.modDB local enemyDB = actor.enemy.modDB + ---@class Output local output = actor.output + ---@class Breakdown local breakdown = actor.breakdown local condList = modDB.conditions diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 0c1f70b40e..bcb2940da3 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -64,6 +64,7 @@ local damageStatsForTypes = setmetatable({ }, { __index = function(t, k) end }) local globalOutput = nil +---@type Breakdown? local globalBreakdown = nil local function calcConvertedDamage(activeSkill, output, cfg, damageType) @@ -380,10 +381,15 @@ function calcSkillDuration(skillModList, skillCfg, skillData, env, enemyDB) end -- Performs all offensive calculations +---@param env Env +---@param actor Actor +---@param activeSkill ActiveSkill function calcs.offence(env, actor, activeSkill) local modDB = actor.modDB local enemyDB = actor.enemy.modDB + ---@class Output local output = actor.output + ---@class Breakdown local breakdown = actor.breakdown local skillModList = activeSkill.skillModList @@ -2557,7 +2563,11 @@ function calcs.offence(env, actor, activeSkill) -- Calculate how often you hit (speed, accuracy, block, etc) for _, pass in ipairs(passList) do globalOutput, globalBreakdown = output, breakdown - local source, output, cfg, breakdown = pass.source, pass.output, pass.cfg, pass.breakdown + local source = pass.source + ---@class Output + local output = pass.output + local cfg = pass.cfg + local breakdown = pass.breakdown if skillData.averageBurstHits then output.AverageBurstHits = skillData.averageBurstHits @@ -3201,7 +3211,12 @@ function calcs.offence(env, actor, activeSkill) --Calculate damage (exerts, crits, ruthless, DPS, etc) for _, pass in ipairs(passList) do globalOutput, globalBreakdown = output, breakdown - local source, output, cfg, breakdown = pass.source, pass.output, pass.cfg, pass.breakdown + local source = pass.source + ---@class Output + local output = pass.output + local cfg = pass.cfg + ---@class Breakdown + local breakdown = pass.breakdown -- Exerted Attack members local exertedDoubleDamage = env.modDB:Sum("BASE", cfg, "ExertDoubleDamageChance") @@ -4860,7 +4875,12 @@ function calcs.offence(env, actor, activeSkill) -- Calculate ailments and debuffs (poison, bleed, ignite, impale, exposure, etc) for _, pass in ipairs(passList) do globalOutput, globalBreakdown = output, breakdown - local source, output, cfg, breakdown = pass.source, pass.output, pass.cfg, pass.breakdown + local source = pass.source + ---@class Output + local output = pass.output + local cfg = pass.cfg + ---@class Breakdown + local breakdown = pass.breakdown -- Legacy PoE1 ailments (to be removed later): Scorched, Brittle, Sapped, Impale output.ImpaleChance = 0 diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index ac1c64b710..f40a1c719c 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -216,7 +216,9 @@ end ---@param actor table local function doActorAttribsConditions(env, actor) local modDB = actor.modDB + ---@class Output local output = actor.output + ---@class Breakdown local breakdown = actor.breakdown local condList = modDB.conditions @@ -579,6 +581,7 @@ end local function doActorMisc(env, actor) local modDB = actor.modDB local enemyDB = actor.enemy.modDB + ---@class Output local output = actor.output local condList = modDB.conditions @@ -853,6 +856,7 @@ end -- Process charges local function doActorCharges(env, actor) local modDB = actor.modDB + ---@class Output local output = actor.output -- Calculate current and maximum charges @@ -1179,7 +1183,8 @@ function calcs.perform(env, skipEHP) end env.player.output = { } - env.enemy.output = { } + env.enemy.output = {} + ---@class Output local output = env.player.output env.partyMembers = env.build.partyTab.actor diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index 7f0f8a2fde..0d1188d628 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -622,6 +622,7 @@ local function addBestSupport(supportEffect, appliedSupportList, mode) end end +---@alias CalcEnvMode "MAIN"|"CALCS"|"CALCULATOR" -- Initialise environment: -- 1. Initialises the player and enemy modifier databases -- 2. Merges modifiers for all items @@ -629,6 +630,14 @@ end -- 4. Merges modifiers for all allocated passive nodes -- 5. Builds a list of active skills and their supports (calcs.createActiveSkill) -- 6. Builds modifier lists for all active skills (calcs.buildActiveSkillModList) +---@param build Build +---@param mode CalcEnvMode +---@param override CalcOverride? +---@param specEnv any? +---@return Env +---@return ModDB? cachedPlayerDB +---@return ModDB? cachedEnemyDB +---@return ModDB? cachedMinionDB function calcs.initEnv(build, mode, override, specEnv) ClearMatchKeywordFlagsCache() -- accelerator variables @@ -645,6 +654,8 @@ function calcs.initEnv(build, mode, override, specEnv) local classStats = nil if not env then + ---@class Env + ---@field minion Actor? env = { } env.build = build env.data = build.data diff --git a/src/Modules/CalcTriggers.lua b/src/Modules/CalcTriggers.lua index 79800b5e5f..91a1a75534 100644 --- a/src/Modules/CalcTriggers.lua +++ b/src/Modules/CalcTriggers.lua @@ -138,7 +138,9 @@ local function helmetFocusHandler(env) if not env.player.mainSkill.skillFlags.minion and not env.player.mainSkill.skillFlags.disable and env.player.mainSkill.triggeredBy then local triggerName = "Focus" env.player.mainSkill.skillData.triggered = true + ---@class Output local output = env.player.output + ---@class Breakdown local breakdown = env.player.breakdown local triggerCD = env.player.mainSkill.triggeredBy.grantedEffect.levels[env.player.mainSkill.triggeredBy.level].cooldown local triggeredCD = env.player.mainSkill.skillData.cooldown @@ -225,6 +227,7 @@ local function CWCHandler(env) local source = nil local triggerName = "Cast While Channeling" local output = env.player.output + ---@class Breakdown local breakdown = env.player.breakdown for _, skill in ipairs(env.player.activeSkillList) do local match1 = env.player.mainSkill.activeEffect.grantedEffect.fromItem and skill.socketGroup and skill.socketGroup.slot == env.player.mainSkill.socketGroup.slot @@ -386,6 +389,7 @@ end local function defaultTriggerHandler(env, config) local actor = config.actor local output = config.actor.output + ---@class Breakdown local breakdown = config.actor.breakdown local source = config.source local triggeredSkills = config.triggeredSkills or {} diff --git a/src/Modules/Calcs.lua b/src/Modules/Calcs.lua index d6142af6c8..69378e3f51 100644 --- a/src/Modules/Calcs.lua +++ b/src/Modules/Calcs.lua @@ -70,57 +70,22 @@ local function infoDump(env) prettyPrintTable(env.player.output) end --- Generate a function for calculating the effect of some modification to the environment -local function getCalculator(build, fullInit, modFunc) - -- Initialise environment - local env, cachedPlayerDB, cachedEnemyDB, cachedMinionDB = calcs.initEnv(build, "CALCULATOR") - - -- Run base calculation pass - calcs.perform(env) - local fullDPS = calcs.calcFullDPS(build, "CALCULATOR", {}, { cachedPlayerDB = cachedPlayerDB, cachedEnemyDB = cachedEnemyDB, cachedMinionDB = cachedMinionDB, env = nil }) - env.player.output.SkillDPS = fullDPS.skills - env.player.output.FullDPS = fullDPS.combinedDPS - env.player.output.FullDotDPS = fullDPS.TotalDotDPS - local baseOutput = env.player.output - - env.modDB.parent = cachedPlayerDB - env.enemyDB.parent = cachedEnemyDB - if cachedMinionDB then - env.minion.modDB.parent = cachedMinionDB - end - return function(...) - -- Remove mods added during the last pass - wipeTable(env.modDB.mods) - wipeTable(env.modDB.conditions) - wipeTable(env.modDB.multipliers) - wipeTable(env.enemyDB.mods) - wipeTable(env.enemyDB.conditions) - wipeTable(env.enemyDB.multipliers) - - -- Call function to make modifications to the environment - modFunc(env, ...) - - -- Run calculation pass - calcs.perform(env) - fullDPS = calcs.calcFullDPS(build, "CALCULATOR", {}, { cachedPlayerDB = cachedPlayerDB, cachedEnemyDB = cachedEnemyDB, cachedMinionDB = cachedMinionDB, env = nil}) - env.player.output.SkillDPS = fullDPS.skills - env.player.output.FullDPS = fullDPS.combinedDPS - env.player.output.FullDotDPS = fullDPS.TotalDotDPS - - return env.player.output - end, baseOutput -end - --- Get fast calculator for adding tree node modifiers -function calcs.getNodeCalculator(build) - return getCalculator(build, true, function(env, nodeList) - -- Build and merge modifiers for these nodes - env.modDB:AddList(calcs.buildModListForNodeList(env, nodeList)) - end) -end +---@class CalcOverride +---@field spec PassiveSpec? +---@field addNodes table? A set of passive nodes. Only keyed by node id for anointed nodes. +---@field removeNodes table? A set of passive nodes. Only keyed by node id for anointed nodes. +---@field repSlotName string? The name of the replaced item slot +---@field repItem Item? +---@field toggleFlask Item? Item object used as a table key. +---@field toggleCharm Item? Item object used as a table key. +---@field conditions string[]? +---@field extraJewelFuncs ModList? -- Get calculator for other changes (adding/removing nodes, items, gems, etc) +---@param build Build +---@return fun(override?: CalcOverride, useFullDPS?: boolean, fastCalcOptions?: table): Output calcFunc +---@return Output output function calcs.getMiscCalculator(build) -- Run base calculation pass local env, cachedPlayerDB, cachedEnemyDB, cachedMinionDB = calcs.initEnv(build, "CALCULATOR") diff --git a/src/Modules/Data.lua b/src/Modules/Data.lua index 781832d686..a5f6bdb379 100644 --- a/src/Modules/Data.lua +++ b/src/Modules/Data.lua @@ -117,16 +117,17 @@ for k, v in pairs(miscData) do data[k] = v end ----@class StatTable +---@class PowerStat ---@field stat? string stat ID ---@field label string A short description of the stat ----@field transform fun(in: number|string): number|string A function to e.g. invert the value, if the stat represents something where lower is better +---@field transform? fun(in: number|string): number|string A function to e.g. invert the value, if the stat represents something where lower is better ---@field combinedOffDef? boolean ---@field ignoreForNodes? boolean ---@field ignoreForItems? boolean ---@field reverseSort? boolean +---@field itemField string? ----@type StatTable[] +---@type PowerStat[] data.powerStatList = { { stat=nil, label="Offence/Defence", combinedOffDef=true, ignoreForItems=true }, { stat=nil, label="Name", itemField="Name", ignoreForNodes=true, reverseSort=true, transform=function(value) return value:gsub("^The ","") end}, @@ -182,7 +183,7 @@ data.powerStatList = { } ---@param output any Calc output ----@param statTable StatTable Table with stats as in data.powerStatList +---@param statTable PowerStat Table with stats as in data.powerStatList ---@param skipTransform? boolean Whether the stat transform should be skipped. This is useful if you want to e.g. divide two less is better stats ---@return number function data.powerStatList.GetFromOutput(output, statTable, skipTransform) diff --git a/src/Modules/Main.lua b/src/Modules/Main.lua index 7cd2b2a3c1..d4cbb8e2cc 100644 --- a/src/Modules/Main.lua +++ b/src/Modules/Main.lua @@ -147,8 +147,10 @@ function main:Init() self:ChangeUserPath(self.userPath, ignoreBuild) end - self.uniqueDB = { list = { }, loading = true } - self.rareDB = { list = { }, loading = true } + ---@type ItemDBData + self.uniqueDB = { list = {}, loading = true } + ---@type ItemDBData + self.rareDB = { list = {}, loading = true } local function loadItemDBs() for type, typeList in pairsYield(data.uniques) do diff --git a/src/Modules/ModTools.lua b/src/Modules/ModTools.lua index b71a2e1ca9..b115fe8f4e 100644 --- a/src/Modules/ModTools.lua +++ b/src/Modules/ModTools.lua @@ -17,6 +17,17 @@ local bor = OR64 -- bit.bor modLib = { } +--- "Flag" is only used with CanNotUseItem +---@alias NumericModTypes "INC"|"MORE"|"BASE"|"OVERRIDE"|"MAX"|"CHANCE"|"DUMMY"|"Flag"|"MIN" + +-- Massive discriminated union. Todo: probably has to be built with an LLM for a start +---@class ModTag +---@field type string + +---@overload fun(modName: string, modType: NumericModTypes, modVal?: number, sourceOrTag: string|ModTag?, flagsOrModTag: number|ModTag?, keywordFlagsOrModTag: number|ModTag?, ...: ModTag) +---@overload fun(modName: string, modType: "FLAG", modVal: boolean, sourceOrModTag: string|ModTag?, flagsOrModTag: number|ModTag?, keywordFlagsOrModTag: number|ModTag?, ...: ModTag) +---@overload fun(modName: string, modType: "LIST", modVal: any[]|any, sourceOrModTag: string|ModTag?, flagsOrModTag: number|ModTag?, keywordFlagsOrModTag: number|ModTag?, ...: ModTag) +---@return Mod function modLib.createMod(modName, modType, modVal, ...) local flags = 0 local keywordFlags = 0 @@ -34,6 +45,14 @@ function modLib.createMod(modName, modType, modVal, ...) keywordFlags = select(3, ...) tagStart = 4 end + ---@class Mod + ---@field name string + ---@field type NumericModTypes|"FLAG"|"LIST" + ---@field value number|boolean|any Number for numeric mod types, boolean for FLAG, any for LIST + ---@field flags number + ---@field keywordFlags number + ---@field source? string + ---@field [integer] ModTag return { name = modName, type = modType,