diff --git a/.gitignore b/.gitignore index e707d9bac5..0b875171d4 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ luajit/ spec/test_results.log spec/test_generation.log src/luacov.stats.out +runtime/lua/debugger.lua # Release manifest-updated.xml diff --git a/.gitignore.rej b/.gitignore.rej new file mode 100644 index 0000000000..cdc562c394 --- /dev/null +++ b/.gitignore.rej @@ -0,0 +1,12 @@ +diff a/.gitignore b/.gitignore (rejected hunks) +@@ -39,4 +40,8 @@ src/Data/TimelessJewelData/*.bin + runtime/imgui.ini + runtime/SimpleGraphic/SimpleGraphic.log + +-src/poe_api_response.json +\ No newline at end of file ++src/poe_api_response.json ++runtime/SimpleGraphic/Screenshots ++ ++.emmyrc.json ++.luarc.json diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5006e56841..7937115535 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -139,6 +139,14 @@ It is recommended to use it over the built-in Lua plugins. Please note that EmmyLua is not available for other editors based on Visual Studio Code, such as [VSCodium](https://vscodium.com) or [Eclipse Theia](https://theia-ide.org) but can be built from source if needed. +Another alternative on VSCode is to use [sumneko's Lua language server](https://marketplace.visualstudio.com/items?itemName=sumneko.lua) along with [actboy168's debugger](https://marketplace.visualstudio.com/items?itemName=actboy168.lua-debug). These can potentially offer more features than EmmyLua, such as conditional breakpoints. + +## Runtime environment + +It is recommended that you configure your IDE to include `src/_SimpleGraphic.def.lua` somehow. Path of Building runs inside a special Lua environment via SimpleGraphic which implements a small API. These are not defined inside the project, which means that the aforementioned meta/hint file is required for the IDE to know which functions exist. As the file is not included in code, it must be explicitly mentioned as a library in whichever language server you are using, or otherwise it will not be read. + +This file is normally not executed, but does contain basic implementations for parts of the API, which allows many parts of PoB to work without running inside SimpleGraphic. If you wish to test individual changes, it might be possible to do so through a script using Luajit directly. To do so, see HeadlessWrapper.lua for an example. It should be noted that some parts of the API (such as subscripts) are not implemented, which means some parts of PoB are unusable. + ### Visual Studio Code 1. Create a new Debug Configuration of type EmmyLua New Debug @@ -171,20 +179,60 @@ such as [VSCodium](https://vscodium.com) or [Eclipse Theia](https://theia-ide.or 1. In VSCode click Start Debugging (the green icon) or press F5 1. The debugger should connect +You might also want to use actboy168 debugger. This is possible by using for example the following launch.json configuration: + +```json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "πŸ„attach", + "type": "lua", + "request": "attach", + "stopOnEntry": false, + "address": "127.0.0.1:12306", + "luaVersion": "luajit", + }, + + ] +} +``` + +Then, similarly to the EmmyLua example: + +1. Find the sub-folder that looks like `actboy168.lua-debug-x.y.z-win32-x64` in `%USERPROFILE%/.vscode/extensions`. Navigate to it and find the `debugger.lua` script under the script folder. Copy this to `runtime/lua`. +2. Copy-paste the following code snippet into `launch:OnInit()`: + ```lua + local debugger = require("debugger"):start("127.0.0.1:12306") + -- debugger:event("wait") -- Uncomment this line if you want PoB to wait until the debugger is attached. + ``` + + Note that Linux developers using Wine might need to use the Windows debugger instead of using the VSCode debugger. This can be done by: + + 1. Downloading the .vsix from the VSCode extension page + 2. Copying `extension/{script,runtime}` to the `runtime` folder of the PoB directory (i.e., `runtime/runtime`). + 3. Copying `debugger.lua` from `runtime/scripts/debugger.lua` to `runtime/lua/debugger.lua`. + 4. Using `local debugger = loadfile(GetRuntimePath().."/lua/debugger.lua")():start("127.0.0.1:12306")` instead of the above code to avoid issues with Wine backwards slashes #### Excluding directories from EmmyLua Depending on the amount of system ram you have available and the amount that gets assigned to the jvm running the emmylua language server you might run into issues when trying to debug Path of building. -Files in `/Data` `/Export` and `/TreeData` can be massive and cause the EmmyLua language server to use a significant amount of memory. Sometimes causing the language server to crash. To avoid this and speed up initialization consider adding an `.emmyrc.json` file to the `.vscode` folder in the root of the Path of building folder with the following content: +Files in `/Data` `/Export` and `/TreeData` can be massive and cause the EmmyLua language server to use a significant amount of memory. Sometimes causing the language server to crash. To avoid this and speed up initialization consider adding an `.emmyrc.json` to the root of the Path of building folder with the following content: ```json { "$schema": "https://raw.githubusercontent.com/EmmyLuaLs/emmylua-analyzer-rust/refs/heads/main/crates/emmylua_code_analysis/resources/schema.json", "runtime": { - "version": "LuaJIT" + "version": "LuaJIT", + // this is not technically correct as LoadModule behaviour can + // differ from require, but it is useful for now + "requireLikeFunction": ["LoadModule"], }, "workspace": { "ignoreGlobs": [ + "**/*_spec.lua", + "spec/**/*.lua", + "runtime/lua/sha1/lua53_ops.lua", "**/src/Data/**/*.lua", "**/src/TreeData/**/*.lua", "**/src/Modules/ModParser.lua" @@ -193,6 +241,46 @@ Files in `/Data` `/Export` and `/TreeData` can be massive and cause the EmmyLua } ``` +This file can be customised according to what you want. It is a good idea to ignore test files as these tend to add things to the global namespace, which will look confusing, and they are designed to be run by Busted. `lua53_ops.lua` produces errors and doesn't actually get imported when using LuaJIT. It can be useful to keep the data and mod parser files, but generally this will increase the time the LSP takes to index the project on startup. + +### Excluding directories from Sumneko's language server + +If you prefer to not use EmmyLua, the following configuration works well for Sumneko's VS Code extension: + +```json +{ + "Lua.workspace.ignoreDir": [ + ".vscode", + // these files add things to global that aren't there in normal + // operation + "spec/*", + "src/Export/*", + "src/HeadlessWrapper.lua", + + // this has lua 5.3 code which produces errors, but doesn't actually run + "src/runtime/lua/sha1/*", + + // avoid overriding the below library setting + "src/_SimpleGraphic.def.lua", + ], + "Lua.diagnostics.disable": ["inject-field"], + // disables diagnostics even when you open one of the above + "Lua.diagnostics.ignoredFiles": "Disable", + "Lua.runtime.version": "LuaJIT", + "Lua.workspace.preloadFileSize": 1000, + // this is not technically correct as LoadModule behaviour can + // differ from require, but it is useful for now + "Lua.runtime.special": { + "LoadModule": "require" + }, + "Lua.workspace.library": [ + "src/_SimpleGraphic.def.lua" + ], +} +``` + +The extension will automatically skip large files from being preloaded (controlled by `Lua.workspace.preloadFileSize`), so they don't have to be excluded. The configuration file can be found by pressing Ctrl-Shift-P and selecting `Preferences: Open Workspace Settings (JSON)`. If you wish to check test files, you can remove the "ignoredFiles" option and install the busted, LuaFileSystem, and luassert LuaLS addons through `Lua: Open Addon Manager`. + ### PyCharm Community / IntelliJ Idea Community 1. Create a new "Debug Configuration" of type "Emmy Debugger(NEW)". @@ -226,6 +314,13 @@ More tests can be added to this folder to test specific functionality, or new te Please try to include tests for your new features in your pull request. Additionally, if your pr breaks a test that should be passing please update it accordingly. +It is a good idea to prefer Docker due to it having a very reliable Lua setup. But if you have performance problems with it, installing `busted` locally might help as it tends to be faster to execute: + +1. Install Luajit (due to PoB accessing the jit library, it non-Luajit versions might not work) +2. Install [Luarocks](https://luarocks.org/) (for example, through Scoop or your Linux package manager) +3. Run `luarocks install busted` +4. Run `busted --lua=luajit` to run the tests. You can also use e.g. `-p TestUtils_spec.lua` to run a specific file. + ### Debugging tests When running tests with a docker container it is possible to use EmmyLua for debugging. Paste in the following right under `function launch:OnInit()` in `./src/Launch.lua`: ```lua diff --git a/manifest.cfg.rej b/manifest.cfg.rej new file mode 100644 index 0000000000..610e1be6b7 --- /dev/null +++ b/manifest.cfg.rej @@ -0,0 +1,10 @@ +diff a/manifest.cfg b/manifest.cfg (rejected hunks) +@@ -10,7 +10,7 @@ exclude-directories = + + [program] + path = src +-exclude-files = HeadlessWrapper.lua,LaunchInstall.lua,Settings.xml ++exclude-files = HeadlessWrapper.lua,LaunchInstall.lua,Settings.xml,_SimpleGraphic.def.lua + exclude-directories = src/Export,src/TreeData,src/Builds,src/luacov.stats.out,src/Data/TimelessJewelData/BrutalRestraint.bin,src/Data/TimelessJewelData/ElegantHubris.bin,src/Data/TimelessJewelData/GloriousVanity.bin,src/Data/TimelessJewelData/LethalPride.bin,src/Data/TimelessJewelData/MilitantFaith.bin,src/Data/TimelessJewelData/HeroicTragedy.bin,src/Data/TimelessJewelData/AbyssAmanamu.bin,src/Data/TimelessJewelData/AbyssKurgal.bin,src/Data/TimelessJewelData/AbyssTecrod.bin,src/Data/TimelessJewelData/AbyssUlaman.bin,src/Data/TimelessJewelData/AbyssZorath.bin,src/poe_api_response.json + + [tree] diff --git a/spec/System/TestCommon_spec.lua b/spec/System/TestCommon_spec.lua new file mode 100644 index 0000000000..61a848e14e --- /dev/null +++ b/spec/System/TestCommon_spec.lua @@ -0,0 +1,96 @@ +describe("Common", function() + describe("Class creation and use", function() + it("produces error when parent constructors are not called", function() + local ParentClass = newClass("ConstructorTestParentClass") + function ParentClass:ConstructorTestParentClass() + return self + end + local ChildClass = newClass("ConstructorTestProblemChildClass", "ConstructorTestParentClass") + function ChildClass:ConstructorTestProblemChild() + -- Intentionally does not call self:ConstructorTestParentClass() + return self + end + common.classes.ConstructorTestParent = ParentClass + common.classes.ConstructorTestProblemChild = ChildClass + + assert.has_error(function() + new("ConstructorTestProblemChild"):ConstructorTestProblemChild() + end, "Parent class 'ConstructorTestParentClass' of class 'ConstructorTestProblemChild' must be initialised") + common.classes.ConstructorTestParent = nil + common.classes.ConstructorTestProblemChild = nil + end) + it("produces an error if additional arguments are passed", function() + local StupidClass = newClass("NewAbuse") + function StupidClass:NewAbuse(someParam) + return self + end + + common.classes.NewAbuse = StupidClass + + assert.has_no.errors(function() + local newObj = new("NewAbuse"):NewAbuse("fish") + end) + assert.has_error(function() + local newObj = new("NewAbuse", "look I'm using the old syntax") + end) + end) + it("produces an error if it calls a parent class without giving it self", function() + local ParentClass = newClass("ConstructorTestParentClass") + function ParentClass:ConstructorTestParentClass() + return self + end + + local ChildClass = newClass("ConstructorTestProblemChildClass", "ConstructorTestParentClass") + function ChildClass:ConstructorTestProblemChild() + self.ConstructorTestParentClass() + return self + end + + common.classes.ConstructorTestParent = ParentClass + common.classes.ConstructorTestProblemChild = ChildClass + + assert.has_error(function() + new("ConstructorTestProblemChild"):ConstructorTestProblemChild() + end) + common.classes.ConstructorTestParent = nil + common.classes.ConstructorTestProblemChild = nil + end) + it("produces an error if its constructor doesn't return the object", function() + local StupidClass = newClass("StupidClass") + function StupidClass:StupidClass() + end + + common.classes.StupidClass = StupidClass + + assert.has_error(function() + new("StupidClass"):StupidClass() + end, "Class StupidClass constructor did not return a value") + end) + it("produces an error if its constructor has not been called", function() + local StupidClass = newClass("StupidClass") + function StupidClass:StupidClass() + return self + end + + function StupidClass:Clear() + end + + common.classes.StupidClass = StupidClass + + assert.has_error(function() + local object = new("StupidClass") + return object.lines + end) + assert.has_error(function() + local object = new("StupidClass") + object:Clear() + end) + assert.has_no.errors(function() + local object = new("StupidClass"):StupidClass() + local x = object.lines + object:Clear() + end) + common.classes.StupidClass = nil + end) + end) +end) \ No newline at end of file diff --git a/spec/System/TestCompareBuySimilar_spec.lua b/spec/System/TestCompareBuySimilar_spec.lua index 1f32189d42..6d31922015 100644 --- a/spec/System/TestCompareBuySimilar_spec.lua +++ b/spec/System/TestCompareBuySimilar_spec.lua @@ -32,7 +32,7 @@ Corrupted]]) end) it("combines mods that are the same stat", function() - local lifeDiamond = new("Item", [[ + local lifeDiamond = new("Item"):Item([[ Test Subject Diamond Implicits: 0 @@ -47,7 +47,7 @@ Implicits: 0 assert.equal("+50 to Maximum Life", StripEscapes(entries[1].formattedLines[2])) assert.equal(150, entries[1].value) - local lifelessDiamond = new("Item", [[ + local lifelessDiamond = new("Item"):Item([[ Test Subject Diamond Implicits: 0 @@ -62,7 +62,7 @@ Implicits: 0 end) it("is not case-sensitive", function () - local funnyItem = new("Item", [[ + local funnyItem = new("Item"):Item([[ Test Subject Diamond Implicits: 1 @@ -73,7 +73,7 @@ Implicits: 1 end) it("does not combine implicit and explicit mods", function() - local lifelessDiamond = new("Item", [[ + local lifelessDiamond = new("Item"):Item([[ Test Subject Diamond Implicits: 1 diff --git a/spec/System/TestCompareBuySimilar_spec.lua.rej b/spec/System/TestCompareBuySimilar_spec.lua.rej new file mode 100644 index 0000000000..263c038d1f --- /dev/null +++ b/spec/System/TestCompareBuySimilar_spec.lua.rej @@ -0,0 +1,19 @@ +diff a/spec/System/TestCompareBuySimilar_spec.lua b/spec/System/TestCompareBuySimilar_spec.lua (rejected hunks) +@@ -155,7 +155,7 @@ Implicits: 1 + end + + local function getUniqueQuery(name, baseName) +- local item = new("Item", "Rarity: UNIQUE\n" .. name .. "\n" .. baseName .. "\nImplicits: 0") ++ local item = new("Item"):Item("Rarity: UNIQUE\n" .. name .. "\n" .. baseName .. "\nImplicits: 0") + local query = getQuery(openPopup(item, "Jewel")) + main:ClosePopup() + return query +@@ -179,7 +179,7 @@ Implicits: 1 + end) + + it("preserves apostrophes in unique names", function() +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Rarity: UNIQUE + Ralakesh's Impatience + Riveted Boots diff --git a/spec/System/TestItemMods_spec.lua.rej b/spec/System/TestItemMods_spec.lua.rej new file mode 100644 index 0000000000..b4b2e790e8 --- /dev/null +++ b/spec/System/TestItemMods_spec.lua.rej @@ -0,0 +1,55 @@ +diff a/spec/System/TestItemMods_spec.lua b/spec/System/TestItemMods_spec.lua (rejected hunks) +@@ -719,7 +719,7 @@ describe("TetsItemMods", function() + end) + + it("crafts modifiers from supported bases on rare-like uniques", function() +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Item Class: Helmets + Rarity: Unique + Subsume the Source +@@ -759,7 +759,7 @@ describe("TetsItemMods", function() + end) + + it("uses the item base for rare-like modifier eligibility by default", function() +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Item Class: Bows + Rarity: Unique + The Crimson Storm +@@ -778,7 +778,7 @@ describe("TetsItemMods", function() + end) + + it("keeps modifier metadata on duplicate variant tooltip lines", function() +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Rarity: Unique + Duplicate Variant Test + Plate Vest +@@ -791,7 +791,7 @@ describe("TetsItemMods", function() + Implicits: 0 + {variant:1}+10 to maximum Life + ]]) +- local tooltip = new("Tooltip") ++ local tooltip = new("Tooltip"):Tooltip() + build.itemsTab:AddItemTooltip(tooltip, item) + + local count = 0 +@@ -805,7 +805,7 @@ describe("TetsItemMods", function() + end) + + it("does not sort cluster jewel modifiers when the sorting control is hidden", function() +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Rarity: RARE + New Item + Large Cluster Jewel +@@ -880,7 +880,7 @@ describe("TetsItemMods", function() + end) + + it("sorts crafted modifier replacements without retaining the selected modifier", function() +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Rarity: RARE + New Item + Cobalt Jewel diff --git a/spec/System/TestItemParse_spec.lua b/spec/System/TestItemParse_spec.lua index 8034dc07b9..da4830c2e4 100644 --- a/spec/System/TestItemParse_spec.lua +++ b/spec/System/TestItemParse_spec.lua @@ -159,7 +159,7 @@ describe("TestItemParse", function() end) it("Prefix/Suffix", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ Prefix: {range:0.1}IncreasedLife1 Suffix: {range:0.2}ColdResist1 ]])) @@ -170,7 +170,7 @@ describe("TestItemParse", function() end) it("Implicits", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ Implicits: 2 +8 to Strength +10 to Intelligence @@ -1106,7 +1106,7 @@ describe("TestAdvancedItemParse #item", function() end) it("resets linePrefix", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ { Prefix Modifier "Warlock's" (Tier: 4) β€” Mana, Damage, Caster } 32(30-37)% increased Spell Damage +46(42-47) to maximum Mana @@ -1117,7 +1117,7 @@ describe("TestAdvancedItemParse #item", function() end) it("resets linePostfix", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ { Corruption Enhancement β€” Mana } 24(20-30)% increased Mana Regeneration Rate -------- @@ -1127,7 +1127,7 @@ describe("TestAdvancedItemParse #item", function() end) it("parses vaaled catalyst", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ Quality (Attribute Modifiers): +19% (augmented) { Unique Modifier β€” Attribute β€” 19% Increased } +120(80-100) to all Attributes @@ -1140,7 +1140,7 @@ describe("TestAdvancedItemParse #item", function() end) it("parses vaaled catalyst within range", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ Quality (Attribute Modifiers): +19% (augmented) { Unique Modifier β€” Attribute β€” 19% Increased } +95(80-100) to all Attributes @@ -1153,7 +1153,7 @@ describe("TestAdvancedItemParse #item", function() end) it("doesn't scale unscalable", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ Quality (Life and Mana Modifiers): +20% (augmented) { Unique Modifier β€” Life, Defences, Energy Shield, Minion, Gem } Socketed Golem Skills gain 20% of Maximum Life as Extra Maximum Energy Shield β€” Unscalable Value @@ -1162,7 +1162,7 @@ describe("TestAdvancedItemParse #item", function() end) it("correctly matches conqueror mod", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ { Suffix Modifier "of the Conquest" (Tier: 1) β€” Elemental, Cold } 10(8-10)% chance to Avoid Cold Damage from Hits (No chance to avoid damage can be higher than 75%) @@ -1173,7 +1173,7 @@ describe("TestAdvancedItemParse #item", function() end) it("parses enchant correctly #enchant", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ { Corrupted Enhancement } +8(6-10)% to Fire Resistance ]])) @@ -1181,7 +1181,7 @@ describe("TestAdvancedItemParse #item", function() end) it("parses enchant with tags correctly #enchant", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ { Corrupted Enhancement - Energy Shield } +8(6-10)% to Fire Resistance ]])) @@ -1190,7 +1190,7 @@ describe("TestAdvancedItemParse #item", function() end) it("parses junk", function() - local godTestItem = new("Item", [[ + local godTestItem = new("Item"):Item([[ Item Class: Sceptres Rarity: Unique Nebulis @@ -1208,7 +1208,7 @@ describe("TestAdvancedItemParse #item", function() Str: 104 Int: 122 -------- - Sockets: B R + Sockets: B R -------- Item Level: 87 -------- diff --git a/spec/System/TestItemParse_spec.lua.rej b/spec/System/TestItemParse_spec.lua.rej index 29cbba05d1..a5a7e4a9e7 100644 --- a/spec/System/TestItemParse_spec.lua.rej +++ b/spec/System/TestItemParse_spec.lua.rej @@ -1,42 +1,163 @@ diff a/spec/System/TestItemParse_spec.lua b/spec/System/TestItemParse_spec.lua (rejected hunks) -@@ -525,6 +525,16 @@ describe("TestAdvancedItemParse #item", function() - assert.are_not.equals("mana", item.explicitModLines[3].modTags[1]) - end) - -+ it("resets linePostfix", function() -+ local item = new("Item", raw([[ -+ { Corruption Enhancement β€” Mana } -+ 24(20-30)% increased Mana Regeneration Rate -+ -------- -+ +15 to maximum life -+ ]])) -+ assert.falsy(item.explicitModLines[1].enchant) -+ end) -+ - it("parses vaaled catalyst", function() - local item = new("Item", raw([[ - Quality (Attribute Modifiers): +19% (augmented) -@@ -571,6 +581,23 @@ describe("TestAdvancedItemParse #item", function() - -- assert.are.equals(1, item.explicitModLines[1].range) -- Not sure why this is returning 0.5 - end) - -+ it("parses enchant correctly #enchant", function() -+ local item = new("Item", raw([[ -+ { Corrupted Enhancement } -+ +8(6-10)% to Fire Resistance -+ ]])) -+ assert.are.equals(8, item.enchantModLines[1].modList[1].value) -+ end) -+ -+ it("parses enchant with tags correctly #enchant", function() -+ local item = new("Item", raw([[ -+ { Corrupted Enhancement - Energy Shield } -+ +8(6-10)% to Fire Resistance -+ ]])) -+ assert.are.equals(8, item.enchantModLines[1].modList[1].value) -+ assert.are.equals("energyshield", item.enchantModLines[1].modTags[1]) -+ end) -+ - it("parses junk", function() - local godTestItem = new("Item", [[ - Item Class: Sceptres +@@ -38,7 +38,7 @@ describe("TestItemParse", function() + cannotBeAnointed = true, + } + +- local item = new("Item", "Rarity: Normal\n" .. baseName) ++ local item = new("Item"):Item("Rarity: Normal\n" .. baseName) + + assert.are.equals(1, #item.enchantModLines) + assert.are.equals("+10 to Strength", item.enchantModLines[1].line) +@@ -147,7 +147,7 @@ describe("TestItemParse", function() + end) + + it("Versioned grouped variants", function() +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Rarity: UNIQUE + Versioned Grouped Test + Prismatic Ring +@@ -397,7 +397,7 @@ describe("TestItemParse", function() + end) + + it("ignores disabled modifiers in item conditions", function() +- local item = new("Item", raw("{disabled}+100 to maximum Life")) ++ local item = new("Item"):Item(raw("{disabled}+100 to maximum Life")) + assert.is_false(item:FindModifierSubstring("life", "body armour")) + end) + +@@ -763,7 +763,7 @@ describe("TestAdvancedItemParse #item", function() + end) + + it("parses allocated Crucible passive skills from advanced copy", function() +- local item = new("Item", raw([[ ++ local item = new("Item"):Item(raw([[ + { Allocated Crucible Passive Skill (Tier: 1) } + -3% to Critical Strike Chance + +100% to Global Critical Strike Multiplier +@@ -782,7 +782,7 @@ describe("TestAdvancedItemParse #item", function() + end) + + it("ignores attribute requirements from socketed gems", function() +- local item = new("Item", raw([[ ++ local item = new("Item"):Item(raw([[ + Requirements: + Str: 126 (unmet) + Dex: 185 (unmet) +@@ -801,7 +801,7 @@ describe("TestAdvancedItemParse #item", function() + end) + + it("orders fractured mods first and crafted mods last", function() +- local item = new("Item", raw([[ ++ local item = new("Item"):Item(raw([[ + Item Level: 83 + { Fractured Prefix Modifier "Cheetah's" (Tier: 2) β€” Speed } + 30% increased Movement Speed +@@ -826,7 +826,7 @@ describe("TestAdvancedItemParse #item", function() + end) + + it("matches same-name affixes using their advanced-copy ranges", function() +- local item = new("Item", raw([[ ++ local item = new("Item"):Item(raw([[ + Item Level: 85 + { Fractured Prefix Modifier "Essences" β€” Damage, Elemental, Fire, Attack } + Adds 100(80-109) to 179(162-189) Fire Damage +@@ -844,7 +844,7 @@ describe("TestAdvancedItemParse #item", function() + end) + + it("filters flask base properties and parses fixed-value advanced rolls", function() +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Rarity: Unique + Soul Catcher + Quartz Flask +@@ -870,7 +870,7 @@ describe("TestAdvancedItemParse #item", function() + end) + + it("preserves rolls from large advanced-copy ranges", function() +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Rarity: Unique + Elegant Hubris + Timeless Jewel +@@ -887,7 +887,7 @@ describe("TestAdvancedItemParse #item", function() + end) + + it("preserves independently rolled values on the same modifier line", function() +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Rarity: Unique + Prismweave + Rustic Sash +@@ -902,7 +902,7 @@ describe("TestAdvancedItemParse #item", function() + end) + + it("orders advanced-copy unique modifiers by their database stat order", function() +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Rarity: Unique + Geofri's Sanctuary + Elegant Ringmail +@@ -931,7 +931,7 @@ describe("TestAdvancedItemParse #item", function() + end) + + it("keeps the selected value from advanced-copy enum ranges", function() +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Rarity: Unique + The Dark Monarch + Lich's Circlet +@@ -946,7 +946,7 @@ describe("TestAdvancedItemParse #item", function() + end) + + it("parses punctuated enum and descending numeric ranges", function() +- local gemItem = new("Item", [[ ++ local gemItem = new("Item"):Item([[ + Rarity: Unique + Replica Dragonfang's Flight + Onyx Amulet +@@ -956,7 +956,7 @@ describe("TestAdvancedItemParse #item", function() + assert.are.equals("+3 to Level of all Lightning Tendrils Gems", gemItem.explicitModLines[1].line) + assert.is_true(#gemItem.explicitModLines[1].modList > 0) + +- local requirementItem = new("Item", [[ ++ local requirementItem = new("Item"):Item([[ + Rarity: Unique + Replica Dragonfang's Flight + Onyx Amulet +@@ -969,7 +969,7 @@ describe("TestAdvancedItemParse #item", function() + end) + + it("parses Memory Strands as an item property", function() +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Rarity: Magic + Imperial Maul of Revitalization + Weapon Range: 1.3 metres +@@ -1110,7 +1110,7 @@ describe("TestAdvancedItemParse #item", function() + end) + + it("does not apply disabled modifier magnitude", function() +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Rarity: UNIQUE + Magnitude Test + Plate Vest +@@ -1342,7 +1342,7 @@ describe("TestAdvancedItemParse #item", function() + ]] + it("scales only prefixes for increased effect of prefixes for advanced copy format", function() + assert.equal(0, spellCrit()) +- local item = new("Item", realJewel) ++ local item = new("Item"):Item(realJewel) + build.itemsTab:AddItem(item) + build.itemsTab:EquipItemInSet(item, build.itemsTab.activeItemSetId) + runCallback("OnFrame") +@@ -1351,7 +1351,7 @@ describe("TestAdvancedItemParse #item", function() + end) + + it("does not apply scaling twice when saving and loading", function() +- local item = new("Item", new("Item", realJewel):BuildRaw()) ++ local item = new("Item"):Item(new("Item"):Item(realJewel):BuildRaw()) + build.itemsTab:AddItem(item) + build.itemsTab:EquipItemInSet(item, build.itemsTab.activeItemSetId) + runCallback("OnFrame") diff --git a/spec/System/TestItemTools_spec.lua.rej b/spec/System/TestItemTools_spec.lua.rej new file mode 100644 index 0000000000..35d537f90d --- /dev/null +++ b/spec/System/TestItemTools_spec.lua.rej @@ -0,0 +1,10 @@ +diff a/spec/System/TestItemTools_spec.lua b/spec/System/TestItemTools_spec.lua (rejected hunks) +@@ -66,7 +66,7 @@ describe("TestItemTools", function() + if not common.classes.ItemsTab then + LoadModule("Classes/ItemsTab") + end +- local item = new("Item", [[ ++ local item = new("Item"):Item([[ + Rarity: Rare + Dire Thread + Cord Belt diff --git a/spec/System/TestPoEAPIAuth_spec.lua.rej b/spec/System/TestPoEAPIAuth_spec.lua.rej new file mode 100644 index 0000000000..79f742c578 --- /dev/null +++ b/spec/System/TestPoEAPIAuth_spec.lua.rej @@ -0,0 +1,28 @@ +diff a/spec/System/TestPoEAPIAuth_spec.lua b/spec/System/TestPoEAPIAuth_spec.lua (rejected hunks) +@@ -27,7 +27,7 @@ describe("PoEAPI auth", function() + callback(nil, "SSL connect error") + end + +- local api = new("PoEAPI") ++ local api = new("PoEAPI"):PoEAPI() + local callbackArgs + api:FetchAuthToken(function(errMsg) + callbackArgs = { +@@ -51,7 +51,7 @@ describe("PoEAPI auth", function() + error("token exchange should not run for mismatched OAuth state") + end + +- local api = new("PoEAPI") ++ local api = new("PoEAPI"):PoEAPI() + local callbackArgs + api:FetchAuthToken(function(errMsg) + callbackArgs = { +@@ -66,7 +66,7 @@ describe("PoEAPI auth", function() + assert.is_nil(api.authToken) + end) + it("stays usable after an error", function() +- local api = new("PoEAPI", "token", "refresh", os.time() + 3600) ++ local api = new("PoEAPI"):PoEAPI("token", "refresh", os.time() + 3600) + + -- Drive the network layer directly so we bypass ValidateAuth/token + -- refresh and exercise only DownloadWithRateLimit's limiter bookkeeping. diff --git a/spec/System/TestTradeQueryCurrency_spec.lua b/spec/System/TestTradeQueryCurrency_spec.lua index 2758a84363..fe6de69d40 100644 --- a/spec/System/TestTradeQueryCurrency_spec.lua +++ b/spec/System/TestTradeQueryCurrency_spec.lua @@ -2,7 +2,7 @@ describe("TradeQuery Currency Conversion", function() local mock_tradeQuery before_each(function() - mock_tradeQuery = new("TradeQuery", { itemsTab = {} }) + mock_tradeQuery = new("TradeQuery"):TradeQuery({ itemsTab = {} }) end) describe("ConvertCurrencyToDivs", function() diff --git a/spec/System/TestTradeQueryGenerator_spec.lua b/spec/System/TestTradeQueryGenerator_spec.lua index fab1af3cf8..97fb12934b 100644 --- a/spec/System/TestTradeQueryGenerator_spec.lua +++ b/spec/System/TestTradeQueryGenerator_spec.lua @@ -1,5 +1,5 @@ describe("TradeQueryGenerator", function() - local mock_queryGen = new("TradeQueryGenerator", { itemsTab = {} }) + local mock_queryGen = new("TradeQueryGenerator"):TradeQueryGenerator({ itemsTab = {} }) describe("ProcessMod", function() -- Pass: Mod line maps correctly to trade stat entry without error diff --git a/spec/System/TestTradeQueryGenerator_spec.lua.rej b/spec/System/TestTradeQueryGenerator_spec.lua.rej new file mode 100644 index 0000000000..b41bcaaf04 --- /dev/null +++ b/spec/System/TestTradeQueryGenerator_spec.lua.rej @@ -0,0 +1,28 @@ +diff a/spec/System/TestTradeQueryGenerator_spec.lua b/spec/System/TestTradeQueryGenerator_spec.lua (rejected hunks) +@@ -16,7 +16,7 @@ describe("TradeQueryGenerator", function() + + describe("Talisman mods", function() + it("only generates enchant weights when enabled", function() +- local queryGen = new("TradeQueryGenerator", { itemsTab = { } }) ++ local queryGen = new("TradeQueryGenerator"):TradeQueryGenerator({ itemsTab = {} }) + local enchantMods = queryGen.modData.Enchant + queryGen.modData = { Explicit = { }, Implicit = { }, Enchant = enchantMods, Corrupted = { }, Scourge = { } } + queryGen.calcContext = { special = { }, options = { } } +@@ -155,7 +155,7 @@ describe("TradeQueryGenerator", function() + + describe("Filter prioritization", function() + it("counts socket and link constraints against MAX_FILTERS", function() +- local queryGen = new("TradeQueryGenerator", { itemsTab = { items = { } } }) ++ local queryGen = new("TradeQueryGenerator"):TradeQueryGenerator({ itemsTab = { items = {} } }) + queryGen.modWeights = { } + for index = 1, 40 do + table.insert(queryGen.modWeights, { +@@ -165,7 +165,7 @@ describe("TradeQueryGenerator", function() + }) + end + queryGen.calcContext = { +- testItem = new("Item", "Rarity: RARE\nNew Item\nGold Ring\nImplicits: 0"), ++ testItem = new("Item"):Item("Rarity: RARE\nNew Item\nGold Ring\nImplicits: 0"), + baseOutput = { }, + baseStatValue = 0, + itemCategoryQueryStr = "accessory.ring", diff --git a/spec/System/TestTradeQueryRateLimiter_spec.lua b/spec/System/TestTradeQueryRateLimiter_spec.lua index 4542385fdf..c1457f2be0 100644 --- a/spec/System/TestTradeQueryRateLimiter_spec.lua +++ b/spec/System/TestTradeQueryRateLimiter_spec.lua @@ -3,7 +3,7 @@ describe("TradeQueryRateLimiter", function() -- Pass: Extracts keys/values correctly -- Fail: Nil/malformed values, indicating regex failure, breaking policy updates from API it("parses basic headers", function() - local limiter = new("TradeQueryRateLimiter") + local limiter = new("TradeQueryRateLimiter"):TradeQueryRateLimiter() local headers = limiter:ParseHeader("X-Rate-Limit-Policy: test\nRetry-After: 5\nContent-Type: json") assert.are.equal(headers["x-rate-limit-policy"], "test") assert.are.equal(headers["retry-after"], "5") @@ -15,7 +15,7 @@ describe("TradeQueryRateLimiter", function() -- Pass: Extracts rules/limits/states accurately -- Fail: Wrong buckets/windows, indicating parsing bug, enforcing incorrect rates it("parses full policy", function() - local limiter = new("TradeQueryRateLimiter") + local limiter = new("TradeQueryRateLimiter"):TradeQueryRateLimiter() local header = "X-Rate-Limit-Policy: trade-search-request-limit\nX-Rate-Limit-Rules: Ip,Account\nX-Rate-Limit-Ip: 8:10:60,15:60:120\nX-Rate-Limit-Ip-State: 7:10:60,14:60:120\nX-Rate-Limit-Account: 2:5:60\nX-Rate-Limit-Account-State: 1:5:60\nRetry-After: 10" local policies = limiter:ParsePolicy(header) local policy = policies["trade-search-request-limit"] @@ -30,7 +30,7 @@ describe("TradeQueryRateLimiter", function() -- Pass: Reduces limits (e.g., 5 -> 4) -- Fail: Unchanged limits, indicating margin ignored, risking user over-requests it("applies margin to limits", function() - local limiter = new("TradeQueryRateLimiter") + local limiter = new("TradeQueryRateLimiter"):TradeQueryRateLimiter() limiter.limitMargin = 1 local header = "X-Rate-Limit-Policy: test\nX-Rate-Limit-Rules: Ip\nX-Rate-Limit-Ip: 5:10:60\nX-Rate-Limit-Ip-State: 4:10:60" limiter:UpdateFromHeader(header) @@ -42,7 +42,7 @@ describe("TradeQueryRateLimiter", function() -- Pass: Delays past timestamp -- Fail: Allows immediate request, indicating ignored cooldowns, causing 429 errors it("blocks on retry-after", function() - local limiter = new("TradeQueryRateLimiter") + local limiter = new("TradeQueryRateLimiter"):TradeQueryRateLimiter() local now = os.time() limiter.policies["test"] = {} limiter.retryAfter["test"] = now + 10 @@ -53,7 +53,7 @@ describe("TradeQueryRateLimiter", function() -- Pass: Calculates delay from timestamps -- Fail: Allows request in limit, indicating state misread, over-throttling or bans it("blocks on window limit", function() - local limiter = new("TradeQueryRateLimiter") + local limiter = new("TradeQueryRateLimiter"):TradeQueryRateLimiter() local now = os.time() limiter.policies["test"] = { ["ip"] = { ["limits"] = { ["10"] = { ["request"] = 1, ["timeout"] = 60 } }, ["state"] = { ["10"] = { ["request"] = 1, ["timeout"] = 0 } } } } limiter.requestHistory["test"] = { timestamps = {now - 5} } @@ -67,7 +67,7 @@ describe("TradeQueryRateLimiter", function() -- Pass: Removes old stamps, decrements to 1 -- Fail: Stale data persists, indicating aging bug, perpetual blocking it("cleans up timestamps and decrements", function() - local limiter = new("TradeQueryRateLimiter") + local limiter = new("TradeQueryRateLimiter"):TradeQueryRateLimiter() limiter.policies["test"] = { ["ip"] = { ["state"] = { ["10"] = { ["request"] = 2, ["timeout"] = 0, ["decremented"] = nil } } } } limiter.requestHistory["test"] = { timestamps = {os.time() - 15, os.time() - 5}, maxWindow=10, lastCheck=os.time() - 10 } limiter:AgeOutRequests("test", os.time()) diff --git a/spec/System/TestTradeQueryRequests_spec.lua b/spec/System/TestTradeQueryRequests_spec.lua index 309521fdaa..8fb665e871 100644 --- a/spec/System/TestTradeQueryRequests_spec.lua +++ b/spec/System/TestTradeQueryRequests_spec.lua @@ -12,7 +12,7 @@ describe("TradeQueryRequests", function() return key end } - local requests = new("TradeQueryRequests", mock_limiter) + local requests = new("TradeQueryRequests"):TradeQueryRequests(mock_limiter) local function simulateRetry(requests, mock_limiter, policy, current_time) local now = current_time diff --git a/spec/System/TestTradeQuery_spec.lua.rej b/spec/System/TestTradeQuery_spec.lua.rej new file mode 100644 index 0000000000..2d58f6da83 --- /dev/null +++ b/spec/System/TestTradeQuery_spec.lua.rej @@ -0,0 +1,39 @@ +diff a/spec/System/TestTradeQuery_spec.lua b/spec/System/TestTradeQuery_spec.lua (rejected hunks) +@@ -3,8 +3,8 @@ describe("TradeQuery", function() + local mock_queryGen + + before_each(function() +- mock_tradeQuery = new("TradeQuery", { itemsTab = {} }) +- mock_queryGen = new("TradeQueryGenerator", { itemsTab = {} }) ++ mock_tradeQuery = new("TradeQuery"):TradeQuery({ itemsTab = {} }) ++ mock_queryGen = new("TradeQueryGenerator"):TradeQueryGenerator({ itemsTab = {} }) + end) + describe("result dropdown tooltipFunc", function() + -- Builds a TradeQuery with the strict minimum needed for +@@ -14,7 +14,7 @@ describe("TradeQuery", function() + -- lives behind a callback we never trigger, or is already initialized + -- by the TradeQuery constructor. + local function newTradeQuery(state) +- local tq = new("TradeQuery", { itemsTab = {} }) ++ local tq = new("TradeQuery"):TradeQuery({ itemsTab = {} }) + tq.itemsTab.activeItemSet = {} + tq.itemsTab.slots = {} + tq.slotTables[1] = { slotName = "Ring 1" } +@@ -34,7 +34,7 @@ describe("TradeQuery", function() + -- No sorted results at all -> first guard must short-circuit. + local tq = newTradeQuery({}) + local dropdown = buildRow1Dropdown(tq) +- local tooltip = new("Tooltip") ++ local tooltip = new("Tooltip"):Tooltip() + + assert.has_no.errors(function() + dropdown.tooltipFunc(tooltip, "DROP", 1, nil) +@@ -53,7 +53,7 @@ describe("TradeQuery", function() + }) + local dropdown = buildRow1Dropdown(tq) + tq.resultTbl[1] = {} +- local tooltip = new("Tooltip") ++ local tooltip = new("Tooltip"):Tooltip() + + assert.has_no.errors(function() + dropdown.tooltipFunc(tooltip, "DROP", 1, nil) diff --git a/src/Classes/BuildListControl.lua b/src/Classes/BuildListControl.lua index 3f42430ce9..415483e0f6 100644 --- a/src/Classes/BuildListControl.lua +++ b/src/Classes/BuildListControl.lua @@ -74,8 +74,8 @@ end function BuildListClass:RenameBuild(build, copyOnName) local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter the new name for this "..(build.folderName and "folder:" or "build:")) - controls.edit = new("EditControl", nil, {0, 40, 350, 20}, build.folderName or build.buildName, nil, "\\/:%*%?\"<>|%c", 100, function(buf) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter the new name for this "..(build.folderName and "folder:" or "build:")) + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, build.folderName or build.buildName, nil, "\\/:%*%?\"<>|%c", 100, function(buf) controls.save.enabled = false if build.folderName then if buf:match("%S") then @@ -97,7 +97,7 @@ function BuildListClass:RenameBuild(build, copyOnName) end end end) - controls.save = new("ButtonControl", nil, {-45, 70, 80, 20}, "Save", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Save", function() local newBuildName = controls.edit.buf if build.folderName then if copyOnName then @@ -132,7 +132,7 @@ function BuildListClass:RenameBuild(build, copyOnName) self.listMode:SelectControl(self) end) controls.save.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() main:ClosePopup() self.listMode:SelectControl(self) end) diff --git a/src/Classes/BuildListControl.lua.rej b/src/Classes/BuildListControl.lua.rej new file mode 100644 index 0000000000..c96c53de8b --- /dev/null +++ b/src/Classes/BuildListControl.lua.rej @@ -0,0 +1,39 @@ +diff a/src/Classes/BuildListControl.lua b/src/Classes/BuildListControl.lua (rejected hunks) +@@ -7,15 +7,18 @@ local ipairs = ipairs + local s_format = string.format + local buildListHelpers = LoadModule("Modules/BuildListHelpers") + +-local BuildListClass = newClass("BuildListControl", "ListControl", function(self, anchor, rect, listMode) +- self.ListControl(anchor, rect, 20, "VERTICAL", false, listMode.list) ++---@class BuildListControl: ListControl ++local BuildListClass = newClass("BuildListControl", "ListControl") ++ ++function BuildListClass:BuildListControl(anchor, rect, listMode) ++ self:ListControl(anchor, rect, 20, "VERTICAL", false, listMode.list) + self.listMode = listMode +- self.colList = { +- { width = function() return self:GetProperty("width") - 172 end }, ++ self.colList = { ++ { width = function() return self:GetProperty("width") - 172 end }, + { }, + } + self.showRowSeparators = true +- self.controls.path = new("PathControl", {"BOTTOM",self,"TOP"}, {0, -2, self.width, 24}, main.buildPath, listMode.subPath, function(subPath) ++ self.controls.path = new("PathControl"):PathControl({"BOTTOM",self,"TOP"}, {0, -2, self.width, 24}, main.buildPath, listMode.subPath, function(subPath) + listMode.subPath = subPath + listMode:BuildList() + self.selIndex = nil +@@ -50,10 +53,11 @@ local BuildListClass = newClass("BuildListControl", "ListControl", function(self + end + end + self.dragTargetList = { self.controls.path, self } +- self.controls.path.width = function () ++ self.controls.path.width = function() + return self.width() + end +-end) ++ return self ++end + + function BuildListClass:SelByFullFileName(fullFileName) + if fullFileName then diff --git a/src/Classes/ButtonControl.lua b/src/Classes/ButtonControl.lua index a37c6fc658..e231280f5e 100644 --- a/src/Classes/ButtonControl.lua +++ b/src/Classes/ButtonControl.lua @@ -3,14 +3,18 @@ -- Class: Button Control -- Basic button control. -- -local ButtonClass = newClass("ButtonControl", "Control", "TooltipHost", function(self, anchor, rect, label, onClick, onHover, forceTooltip) - self.Control(anchor, rect) - self.TooltipHost() +---@class ButtonControl: Control, TooltipHost +local ButtonClass = newClass("ButtonControl", "Control", "TooltipHost") + +function ButtonClass:ButtonControl(anchor, rect, label, onClick, onHover, forceTooltip) + self:Control(anchor, rect) + self:TooltipHost() self.label = label self.onClick = onClick self.onHover = onHover self.forceTooltip = forceTooltip -end) + return self +end function ButtonClass:Click() if self:IsShown() and self:IsEnabled() then diff --git a/src/Classes/CalcBreakdownControl.lua.rej b/src/Classes/CalcBreakdownControl.lua.rej new file mode 100644 index 0000000000..efee2389f1 --- /dev/null +++ b/src/Classes/CalcBreakdownControl.lua.rej @@ -0,0 +1,33 @@ +diff a/src/Classes/CalcBreakdownControl.lua b/src/Classes/CalcBreakdownControl.lua (rejected hunks) +@@ -13,19 +13,24 @@ local m_cos = math.cos + local m_pi = math.pi + local band = bit.band + +-local CalcBreakdownClass = newClass("CalcBreakdownControl", "Control", "ControlHost", function(self, calcsTab) +- self.Control() +- self.ControlHost() ++---@class CalcBreakdownControl: Control, ControlHost ++local CalcBreakdownClass = newClass("CalcBreakdownControl", "Control", "ControlHost") ++ ++function CalcBreakdownClass:CalcBreakdownControl(calcsTab) ++ self:Control() ++ self:ControlHost() + self.calcsTab = calcsTab + self.shown = false +- self.tooltip = new("Tooltip") +- self.nodeViewer = new("PassiveTreeView") ++ self.tooltip = new("Tooltip"):Tooltip() ++ self.nodeViewer = new("PassiveTreeView"):PassiveTreeView() + self.rangeGuide = NewImageHandle() + self.rangeGuide:Load("Assets/range_guide.png") + self.uiOverlay = NewImageHandle() + self.uiOverlay:Load("Assets/game_ui_small.png") +- self.controls.scrollBar = new("ScrollBarControl", {"RIGHT",self,"RIGHT"}, {-2, 0, 18, 0}, 80, "VERTICAL", true) +-end) ++ self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({ "RIGHT", self, "RIGHT" }, { -2, 0, 18, 0 }, 80, ++ "VERTICAL", true) ++ return self ++end + + function CalcBreakdownClass:IsMouseOver() + if not self:IsShown() then diff --git a/src/Classes/CalcSectionControl.lua b/src/Classes/CalcSectionControl.lua index ff7e557a43..ff3f5fa23b 100644 --- a/src/Classes/CalcSectionControl.lua +++ b/src/Classes/CalcSectionControl.lua @@ -33,7 +33,7 @@ local CalcSectionClass = newClass("CalcSectionControl", "Control", "ControlHost" end end subSec.collapsed = subSec.defaultCollapsed - self.controls["toggle"..i] = new("ButtonControl", {"TOPRIGHT",self,"TOPRIGHT"}, {-3, -13 + (16 * i), 16, 16}, function() + self.controls["toggle"..i] = new("ButtonControl"):ButtonControl({"TOPRIGHT",self,"TOPRIGHT"}, {-3, -13 + (16 * i), 16, 16}, function() return subSec.collapsed and "+" or "-" end, function() subSec.collapsed = not subSec.collapsed diff --git a/src/Classes/CalcSectionControl.lua.rej b/src/Classes/CalcSectionControl.lua.rej new file mode 100644 index 0000000000..fc904c54a9 --- /dev/null +++ b/src/Classes/CalcSectionControl.lua.rej @@ -0,0 +1,10 @@ +diff a/src/Classes/CalcSectionControl.lua b/src/Classes/CalcSectionControl.lua (rejected hunks) +@@ -56,7 +56,7 @@ function CalcSectionClass:CalcSectionControl(calcsTab, width, id, group, colour, + end + end + end +- self.controls.popOut = new("ButtonControl", {"TOPRIGHT",self,"TOPRIGHT"}, {-22, 3, 16, 16}, "^", function() ++ self.controls.popOut = new("ButtonControl"):ButtonControl({"TOPRIGHT",self,"TOPRIGHT"}, {-22, 3, 16, 16}, "^", function() + self:ToggleOverlay() + end) + self.controls.popOut.shown = function() diff --git a/src/Classes/CalcsTab.lua b/src/Classes/CalcsTab.lua index 1f7e758d4d..e41ce900de 100644 --- a/src/Classes/CalcsTab.lua +++ b/src/Classes/CalcsTab.lua @@ -16,10 +16,16 @@ local buffModeDropList = { { label = "Effective DPS", buffMode = "EFFECTIVE" } } -local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Control", function(self, build) - self.UndoHandler() - self.ControlHost() - self.Control() +---@class CalcsTab: UndoHandler, ControlHost, Control +---@field powerStat PowerStat? +---@field nodePowerMaxDepth integer? Maximum distance for power report +local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Control") + +---@param build Build +function CalcsTabClass:CalcsTab(build) + self:UndoHandler() + self:ControlHost() + self:Control() self.build = build @@ -32,13 +38,13 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro self.colWidth = 230 self.sectionList = { } - self.controls.search = new("EditControl", {"TOPLEFT",self,"TOPLEFT"}, {4, 5, 260, 20}, "", "Search", "%c", 100, nil, nil, nil, true) + self.controls.search = new("EditControl"):EditControl({"TOPLEFT",self,"TOPLEFT"}, {4, 5, 260, 20}, "", "Search", "%c", 100, nil, nil, nil, true) t_insert(self.controls, self.controls.search) -- Special section for skill/mode selection self:NewSection(3, "SkillSelect", 1, colorCodes.NORMAL, {{ defaultCollapsed = false, label = "View Skill Details", data = { { label = "Socket Group", { controlName = "mainSocketGroup", - control = new("DropDownControl", nil, {0, 0, 300, 16}, nil, function(index, value) + control = new("DropDownControl"):DropDownControl(nil, {0, 0, 300, 16}, nil, function(index, value) self.input.skill_number = index self:AddUndoState() self.build.buildFlag = true @@ -77,7 +83,7 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro self.build.buildFlag = true end) }, },{ label = "Skill Stages", playerFlag = "multiStage", { controlName = "mainSkillStageCount", - control = new("EditControl", nil, {0, 0, 52, 16}, nil, nil, "%D", nil, function(buf) + control = new("EditControl"):EditControl(nil, {0, 0, 52, 16}, nil, nil, "%D", nil, function(buf) local mainSocketGroup = self.build.skillsTab.socketGroupList[self.input.skill_number] local srcInstance = mainSocketGroup.displaySkillListCalcs[mainSocketGroup.mainActiveSkillCalcs].activeEffect.srcInstance srcInstance.skillStageCountCalcs = tonumber(buf) @@ -86,7 +92,7 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro end) }, }, { label = "Active Mines", playerFlag = "mine", { controlName = "mainSkillMineCount", - control = new("EditControl", nil, {0, 0, 52, 16}, nil, nil, "%D", nil, function(buf) + control = new("EditControl"):EditControl(nil, {0, 0, 52, 16}, nil, nil, "%D", nil, function(buf) local mainSocketGroup = self.build.skillsTab.socketGroupList[self.input.skill_number] local srcInstance = mainSocketGroup.displaySkillListCalcs[mainSocketGroup.mainActiveSkillCalcs].activeEffect.srcInstance srcInstance.skillMineCountCalcs = tonumber(buf) @@ -158,8 +164,8 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro } }, { label = "Calculation Mode", { controlName = "mode", - control = new("DropDownControl", nil, {0, 0, 100, 16}, buffModeDropList, function(index, value) - self.input.misc_buffMode = value.buffMode + control = new("DropDownControl"):DropDownControl(nil, {0, 0, 100, 16}, buffModeDropList, function(index, value) + self.input.misc_buffMode = value.buffMode self:AddUndoState() self.build.buildFlag = true end, [[ @@ -186,18 +192,19 @@ Effective DPS: Curses and enemy properties (such as resistances and status condi self:NewSection(unpack(section)) end - self.controls.breakdown = new("CalcBreakdownControl", self) + self.controls.breakdown = new("CalcBreakdownControl"):CalcBreakdownControl(self) - self.controls.scrollBar = new("ScrollBarControl", {"TOPRIGHT",self,"TOPRIGHT"}, {0, 0, 18, 0}, 50, "VERTICAL", true) + self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({"TOPRIGHT",self,"TOPRIGHT"}, {0, 0, 18, 0}, 50, "VERTICAL", true) self.powerBuilderInitialized = nil -end) + return self +end function CalcsTabClass:Load(xml, dbFileName) for _, node in ipairs(xml) do if type(node) == "table" then if node.elem == "Input" then if not node.attrib.name then - launch:ShowErrMsg("^1Error parsing '%s': 'Input' element missing name attribute", fileName) + launch:ShowErrMsg("^1Error parsing '%s': 'Input' element missing name attribute", dbFileName) return true end if node.attrib.number then @@ -207,12 +214,12 @@ function CalcsTabClass:Load(xml, dbFileName) elseif node.attrib.boolean then self.input[node.attrib.name] = node.attrib.boolean == "true" else - launch:ShowErrMsg("^1Error parsing '%s': 'Input' element missing number, string or boolean attribute", fileName) + launch:ShowErrMsg("^1Error parsing '%s': 'Input' element missing number, string or boolean attribute", dbFileName) return true end elseif node.elem == "Section" then if not node.attrib.id then - launch:ShowErrMsg("^1Error parsing '%s': 'Section' element missing id attribute", fileName) + launch:ShowErrMsg("^1Error parsing '%s': 'Section' element missing id attribute", dbFileName) return true end for _, section in ipairs(self.sectionList) do @@ -390,7 +397,7 @@ function CalcsTabClass:Draw(viewPort, inputEvents) end function CalcsTabClass:NewSection(width, ...) - local section = new("CalcSectionControl", self, width * self.colWidth + 8 * (width - 1), ...) + local section = new("CalcSectionControl"):CalcSectionControl(self, width * self.colWidth + 8 * (width - 1), ...) section.widthCols = width t_insert(self.controls, section) t_insert(self.sectionList, section) diff --git a/src/Classes/CalcsTab.lua.rej b/src/Classes/CalcsTab.lua.rej new file mode 100644 index 0000000000..e3006db3b4 --- /dev/null +++ b/src/Classes/CalcsTab.lua.rej @@ -0,0 +1,49 @@ +diff a/src/Classes/CalcsTab.lua b/src/Classes/CalcsTab.lua (rejected hunks) +@@ -52,14 +58,14 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro + } + }, }, + { label = "Active Skill", { controlName = "mainSkill", +- control = new("DropDownControl", nil, {0, 0, 300, 16}, nil, function(index, value) ++ control = new("DropDownControl"):DropDownControl(nil, {0, 0, 300, 16}, nil, function(index, value) + local mainSocketGroup = self.build.skillsTab.socketGroupList[self.input.skill_number] + mainSocketGroup.mainActiveSkillCalcs = index + self.build.buildFlag = true + end) + }, }, + { label = "Skill Part", playerFlag = "multiPart", { controlName = "mainSkillPart", +- control = new("DropDownControl", nil, {0, 0, 250, 16}, nil, function(index, value) ++ control = new("DropDownControl"):DropDownControl(nil, {0, 0, 250, 16}, nil, function(index, value) + local mainSocketGroup = self.build.skillsTab.socketGroupList[self.input.skill_number] + local srcInstance = mainSocketGroup.displaySkillListCalcs[mainSocketGroup.mainActiveSkillCalcs].activeEffect.srcInstance + srcInstance.skillPartCalcs = index +@@ -85,13 +91,13 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro + end) + }, }, + { label = "Show Minion Stats", flag = "haveMinion", { controlName = "showMinion", +- control = new("CheckBoxControl", nil, {0, 0, 18}, nil, function(state) ++ control = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, nil, function(state) + self.input.showMinion = state + self:AddUndoState() + end, "Show stats for the minion instead of the player.") + }, }, + { label = "Minion", flag = "minion", { controlName = "mainSkillMinion", +- control = new("DropDownControl", nil, {0, 0, 160, 16}, nil, function(index, value) ++ control = new("DropDownControl"):DropDownControl(nil, {0, 0, 160, 16}, nil, function(index, value) + local mainSocketGroup = self.build.skillsTab.socketGroupList[self.input.skill_number] + local srcInstance = mainSocketGroup.displaySkillListCalcs[mainSocketGroup.mainActiveSkillCalcs].activeEffect.srcInstance + if value.itemSetId then +@@ -104,12 +110,12 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro + end) + } }, + { label = "Spectre Library", flag = "spectre", { controlName = "mainSkillMinionLibrary", +- control = new("ButtonControl", nil, {0, 0, 100, 16}, "Manage Spectres...", function() ++ control = new("ButtonControl"):ButtonControl(nil, {0, 0, 100, 16}, "Manage Spectres...", function() + self.build:OpenSpectreLibrary() + end) + } }, + { label = "Minion Skill", flag = "haveMinion", { controlName = "mainSkillMinionSkill", +- control = new("DropDownControl", nil, {0, 0, 200, 16}, nil, function(index, value) ++ control = new("DropDownControl"):DropDownControl(nil, {0, 0, 200, 16}, nil, function(index, value) + local mainSocketGroup = self.build.skillsTab.socketGroupList[self.input.skill_number] + local srcInstance = mainSocketGroup.displaySkillListCalcs[mainSocketGroup.mainActiveSkillCalcs].activeEffect.srcInstance + srcInstance.skillMinionSkillCalcs = index diff --git a/src/Classes/CheckBoxControl.lua.rej b/src/Classes/CheckBoxControl.lua.rej new file mode 100644 index 0000000000..2498490bf0 --- /dev/null +++ b/src/Classes/CheckBoxControl.lua.rej @@ -0,0 +1,25 @@ +diff a/src/Classes/CheckBoxControl.lua b/src/Classes/CheckBoxControl.lua (rejected hunks) +@@ -3,15 +3,19 @@ + -- Class: Check Box Control + -- Basic check box control. + -- +-local CheckBoxClass = newClass("CheckBoxControl", "Control", "TooltipHost", function(self, anchor, rect, label, changeFunc, tooltipText, initialState) ++---@class CheckBoxControl: Control, TooltipHost ++local CheckBoxClass = newClass("CheckBoxControl", "Control", "TooltipHost") ++ ++function CheckBoxClass:CheckBoxControl(anchor, rect, label, changeFunc, tooltipText, initialState) + rect[4] = rect[3] or 0 +- self.Control(anchor, rect) +- self.TooltipHost(tooltipText) ++ self:Control(anchor, rect) ++ self:TooltipHost(tooltipText) + self.label = label + self.labelWidth = DrawStringWidth(self.width - 4, "VAR", label or "") + 5 + self.changeFunc = changeFunc + self.state = initialState +-end) ++ return self ++end + + function CheckBoxClass:IsMouseOver() + if not self:IsShown() then diff --git a/src/Classes/CompareBuySimilar.lua b/src/Classes/CompareBuySimilar.lua index 37abf6b6a6..6ad293397c 100644 --- a/src/Classes/CompareBuySimilar.lua +++ b/src/Classes/CompareBuySimilar.lua @@ -40,7 +40,6 @@ for i, entry in ipairs(LISTED_STATUS_OPTIONS) do end - -- Build the trade search URL based on popup selections local function buildURL(item, slotName, controls, modEntries, defenceEntries, isUnique) -- Determine realm and league from the popup's dropdowns @@ -413,22 +412,22 @@ function M.openPopup(item, slotName, primaryBuild) if isUnique then -- Unique item name label - controls.nameLabel = new("LabelControl", nil, {0, ctrlY, 0, 16}, "^x" .. (colorCodes[item.rarity] or "FFFFFF"):gsub("%^x","") .. item.name) + controls.nameLabel = new("LabelControl"):LabelControl(nil, {0, ctrlY, 0, 16}, "^x" .. (colorCodes[item.rarity] or "FFFFFF"):gsub("%^x","") .. item.name) ctrlY = ctrlY + rowHeight else -- Category label local categoryLabel = tradeHelpers.getTradeCategoryLabel(slotName, item) - controls.categoryLabel = new("LabelControl", {"TOPLEFT", nil, "TOPLEFT"}, {leftMargin, ctrlY, 0, 16}, "^7Category: " .. categoryLabel) + controls.categoryLabel = new("LabelControl"):LabelControl({"TOPLEFT", nil, "TOPLEFT"}, {leftMargin, ctrlY, 0, 16}, "^7Category: " .. categoryLabel) ctrlY = ctrlY + rowHeight -- Base type checkbox - controls.baseTypeCheck = new("CheckBoxControl", nil, {-popupWidth/2 + leftMargin + checkboxSize/2, ctrlY, checkboxSize}, "", rebuildUrl) - controls.baseTypeLabel = new("LabelControl", {"LEFT", controls.baseTypeCheck, "RIGHT"}, {4, 0, 0, 16}, "^7Use specific base: " .. (item.baseName or "Unknown")) + controls.baseTypeCheck = new("CheckBoxControl"):CheckBoxControl(nil, {-popupWidth/2 + leftMargin + checkboxSize/2, ctrlY, checkboxSize}, "", rebuildUrl) + controls.baseTypeLabel = new("LabelControl"):LabelControl({"LEFT", controls.baseTypeCheck, "RIGHT"}, {4, 0, 0, 16}, "^7Use specific base: " .. (item.baseName or "Unknown")) ctrlY = ctrlY + rowHeight -- Item level ctrlY = ctrlY + 4 - controls.ilvlLabel = new("LabelControl", {"TOPLEFT", nil, "TOPLEFT"}, {leftMargin, ctrlY, 0, 16}, "^7Item Level:") + controls.ilvlLabel = new("LabelControl"):LabelControl({"TOPLEFT", nil, "TOPLEFT"}, {leftMargin, ctrlY, 0, 16}, "^7Item Level:") controls.ilvlMin = tradeHelpers.newPlainNumericEdit(nil, { minFieldX - popupWidth / 2, ctrlY, fieldW, fieldH }, "", "Min", 4, true, rebuildUrl) controls.ilvlMax = tradeHelpers.newPlainNumericEdit(nil, { maxFieldX - popupWidth / 2, ctrlY, fieldW, fieldH }, "", "Max", 4, true, rebuildUrl) ctrlY = ctrlY + rowHeight @@ -436,8 +435,8 @@ function M.openPopup(item, slotName, primaryBuild) -- Defence stat rows for i, def in ipairs(defenceEntries) do local prefix = "def" .. i - controls[prefix .. "Check"] = new("CheckBoxControl", nil, {-popupWidth/2 + leftMargin + checkboxSize/2, ctrlY, checkboxSize}, "", rebuildUrl) - controls[prefix .. "Label"] = new("LabelControl", {"LEFT", controls[prefix .. "Check"], "RIGHT"}, {4, 0, 0, 16}, "^7" .. def.label) + controls[prefix .. "Check"] = new("CheckBoxControl"):CheckBoxControl(nil, {-popupWidth/2 + leftMargin + checkboxSize/2, ctrlY, checkboxSize}, "", rebuildUrl) + controls[prefix .. "Label"] = new("LabelControl"):LabelControl({"LEFT", controls[prefix .. "Check"], "RIGHT"}, {4, 0, 0, 16}, "^7" .. def.label) controls[prefix .. "Min"] = tradeHelpers.newPlainNumericEdit(nil, { minFieldX - popupWidth / 2, ctrlY, fieldW, fieldH }, tostring(m_floor(def.value)), "Min", 6, true, rebuildUrl) controls[prefix .. "Max"] = tradeHelpers.newPlainNumericEdit(nil, { maxFieldX - popupWidth / 2, ctrlY, fieldW, fieldH }, "", "Max", 6, true, rebuildUrl) ctrlY = ctrlY + rowHeight @@ -466,7 +465,7 @@ function M.openPopup(item, slotName, primaryBuild) -- adjust down by half a text row for each row over 1 local controlYPos = ctrlY + (rows - 1) * 8 local checkBoxXPos = -popupWidth/2 + leftMargin + checkboxSize/2 - controls[prefix .. "Check"] = new("CheckBoxControl", nil, {checkBoxXPos, controlYPos, checkboxSize}, "", rebuildUrl) + controls[prefix .. "Check"] = new("CheckBoxControl"):CheckBoxControl(nil, { checkBoxXPos, controlYPos, checkboxSize }, "", rebuildUrl) controls[prefix .. "Check"].enabled = function() return canSearch end @@ -493,7 +492,7 @@ function M.openPopup(item, slotName, primaryBuild) -- labels anchor based on the first row instead of the middle row, so adjust upwards local labelXOffset = (rows - 1) * -8 - controls[prefix .. "Label"] = new("LabelControl", {"LEFT", controls[prefix .. "Check"], "RIGHT"},{ 4, labelXOffset, 0, fontSize }, + controls[prefix .. "Label"] = new("LabelControl"):LabelControl({ "LEFT", controls[prefix .. "Check"], "RIGHT" }, { 4, labelXOffset, 0, fontSize }, displayText) -- when the trade site has a dropdown for the value, we opt to disable -- the inputs as they are numeric @@ -510,7 +509,7 @@ function M.openPopup(item, slotName, primaryBuild) -- Search button ctrlY = ctrlY + 8 - controls.search = new("ButtonControl", nil, {0, ctrlY, 110, 20}, "Open URL", function() + controls.search = new("ButtonControl"):ButtonControl(nil, { 0, ctrlY, 110, 20 }, "Open URL", function() Copy(uri) OpenURL(uri) end, nil) @@ -519,7 +518,7 @@ function M.openPopup(item, slotName, primaryBuild) return uri and uri ~= "" end - controls.close = new("ButtonControl", nil, {popupWidth/2 - 50, ctrlY, 60, 20}, "Close", function() + controls.close = new("ButtonControl"):ButtonControl(nil, { popupWidth / 2 - 50, ctrlY, 60, 20 }, "Close", function() main:ClosePopup() end) diff --git a/src/Classes/CompareBuySimilar.lua.rej b/src/Classes/CompareBuySimilar.lua.rej new file mode 100644 index 0000000000..43803f8ad8 --- /dev/null +++ b/src/Classes/CompareBuySimilar.lua.rej @@ -0,0 +1,49 @@ +diff a/src/Classes/CompareBuySimilar.lua b/src/Classes/CompareBuySimilar.lua (rejected hunks) +@@ -335,7 +334,7 @@ function M.openPopup(item, slotName, primaryBuild) + local tradeQuery = primaryBuild.itemsTab and primaryBuild.itemsTab.tradeQuery + local tradeQueryRequests = tradeQuery and tradeQuery.tradeQueryRequests + if not tradeQueryRequests then +- tradeQueryRequests = new("TradeQueryRequests") ++ tradeQueryRequests = new("TradeQueryRequests"):TradeQueryRequests() + end + + local function rebuildUrl() +@@ -374,8 +373,8 @@ function M.openPopup(item, slotName, primaryBuild) + end + + -- Realm dropdown +- controls.realmLabel = new("LabelControl", {"TOPLEFT", nil, "TOPLEFT"}, {leftMargin, ctrlY, 0, 16}, "^7Realm:") +- controls.realmDrop = new("DropDownControl", {"LEFT", controls.realmLabel, "RIGHT"}, {4, 0, 80, 20}, {"PC", "PS4", "Xbox"}, function(index, value) ++ controls.realmLabel = new("LabelControl"):LabelControl({"TOPLEFT", nil, "TOPLEFT"}, {leftMargin, ctrlY, 0, 16}, "^7Realm:") ++ controls.realmDrop = new("DropDownControl"):DropDownControl({"LEFT", controls.realmLabel, "RIGHT"}, {4, 0, 80, 20}, {"PC", "PS4", "Xbox"}, function(index, value) + local realmApiId = REALM_API_IDS[value] or "pc" + fetchLeaguesForRealm(realmApiId) + rebuildUrl() +@@ -386,8 +385,8 @@ function M.openPopup(item, slotName, primaryBuild) + end + + -- League dropdown +- controls.leagueLabel = new("LabelControl", {"LEFT", controls.realmDrop, "RIGHT"}, {12, 0, 0, 16}, "^7League:") +- controls.leagueDrop = new("DropDownControl", { "LEFT", controls.leagueLabel, "RIGHT" }, { 4, 0, 160, 20 }, ++ controls.leagueLabel = new("LabelControl"):LabelControl({"LEFT", controls.realmDrop, "RIGHT"}, {12, 0, 0, 16}, "^7League:") ++ controls.leagueDrop = new("DropDownControl"):DropDownControl({"LEFT", controls.leagueLabel, "RIGHT" }, { 4, 0, 160, 20 }, + { "Loading..." }, function(index, value) + local realmApiId = REALM_API_IDS[controls.realmDrop:GetSelValue()] or "pc" + M.lastLeagueByRealm = M.lastLeagueByRealm or {} +@@ -397,14 +396,14 @@ function M.openPopup(item, slotName, primaryBuild) + controls.leagueDrop.enabled = function() return #controls.leagueDrop.list > 0 and controls.leagueDrop.list[1] ~= "Loading..." end + + -- Listed status dropdown +- controls.listedDrop = new("DropDownControl", { "TOPRIGHT", nil, "TOPRIGHT" }, { -leftMargin, ctrlY, 242, 20 }, LISTED_STATUS_LABELS, function(index, value) ++ controls.listedDrop = new("DropDownControl"):DropDownControl({ "TOPRIGHT", nil, "TOPRIGHT" }, { -leftMargin, ctrlY, 242, 20 }, LISTED_STATUS_LABELS, function(index, value) + M.lastListedIndex = index + rebuildUrl() + end) + if M.lastListedIndex then + controls.listedDrop:SetSel(M.lastListedIndex, true) + end +- controls.listedLabel = new("LabelControl", {"RIGHT", controls.listedDrop, "LEFT"}, {-4, 0, 0, 16}, "^7Listed:") ++ controls.listedLabel = new("LabelControl"):LabelControl({"RIGHT", controls.listedDrop, "LEFT"}, {-4, 0, 0, 16}, "^7Listed:") + + -- Fetch initial leagues for the selected realm + fetchLeaguesForRealm(REALM_API_IDS[controls.realmDrop:GetSelValue()] or "pc") diff --git a/src/Classes/CompareEntry.lua b/src/Classes/CompareEntry.lua index b74b78c02f..8bf2776140 100644 --- a/src/Classes/CompareEntry.lua +++ b/src/Classes/CompareEntry.lua @@ -9,8 +9,11 @@ local s_format = string.format local m_min = math.min local m_max = math.max -local CompareEntryClass = newClass("CompareEntry", "ControlHost", function(self, xmlText, label) - self.ControlHost() +---@class CompareEntry: ControlHost +local CompareEntryClass = newClass("CompareEntry", "ControlHost") + +function CompareEntryClass:CompareEntry(xmlText, label) + self:ControlHost() self.label = label or "Comparison Build" self.buildName = label or "Comparison Build" @@ -46,13 +49,17 @@ local CompareEntryClass = newClass("CompareEntry", "ControlHost", function(self, self.outputRevision = 1 -- Display stats (same as primary build uses) - self.displayStats, self.minionDisplayStats, self.extraSaveStats = LoadModule("Modules/BuildDisplayStats") + local displayStatsModule = LoadModule("Modules/BuildDisplayStats") + self.displayStats = displayStatsModule.displayStats + self.minionDisplayStats = displayStatsModule.minionDisplayStats + self.extraSaveStats = displayStatsModule.extraSaveStats -- Load from XML if xmlText then self:LoadFromXML(xmlText) end -end) + return self +end function CompareEntryClass:LoadFromXML(xmlText) -- Parse the XML @@ -100,14 +107,14 @@ function CompareEntryClass:LoadFromXML(xmlText) -- Create tabs -- PartyTab is replaced with a stub providing an empty enemyModList and actor -- (CalcPerform.lua:1088 accesses build.partyTab.actor for party member buffs) - local partyActor = { Aura = {}, Curse = {}, Warcry = {}, Link = {}, modDB = new("ModDB"), output = {} } + local partyActor = { Aura = {}, Curse = {}, Warcry = {}, Link = {}, modDB = new("ModDB"):ModDB(), output = {} } partyActor.modDB.actor = partyActor - self.partyTab = { enemyModList = new("ModList"), actor = partyActor } - self.configTab = new("ConfigTab", self) - self.itemsTab = new("ItemsTab", self) - self.treeTab = new("TreeTab", self) - self.skillsTab = new("SkillsTab", self) - self.calcsTab = new("CalcsTab", self) + self.partyTab = { enemyModList = new("ModList"):ModList(), actor = partyActor } + self.configTab = new("ConfigTab"):ConfigTab(self) + self.itemsTab = new("ItemsTab"):ItemsTab(self) + self.treeTab = new("TreeTab"):TreeTab(self) + self.skillsTab = new("SkillsTab"):SkillsTab(self) + self.calcsTab = new("CalcsTab"):CalcsTab(self) -- Set up savers table self.savers = { diff --git a/src/Classes/ComparePowerReportListControl.lua b/src/Classes/ComparePowerReportListControl.lua index e57eb24993..59b94964fa 100644 --- a/src/Classes/ComparePowerReportListControl.lua +++ b/src/Classes/ComparePowerReportListControl.lua @@ -7,8 +7,11 @@ local t_insert = table.insert local t_sort = table.sort -local ComparePowerReportListClass = newClass("ComparePowerReportListControl", "ListControl", function(self, anchor, rect) - self.ListControl(anchor, rect, 18, "VERTICAL", false) +---@class ComparePowerReportListControl: ListControl +local ComparePowerReportListClass = newClass("ComparePowerReportListControl", "ListControl") + +function ComparePowerReportListClass:ComparePowerReportListControl(anchor, rect) + self:ListControl(anchor, rect, 18, "VERTICAL", false) local width = rect[3] self.impactColumn = { width = width * 0.22, label = "", sortable = true } @@ -22,7 +25,8 @@ local ComparePowerReportListClass = newClass("ComparePowerReportListControl", "L self.colLabels = true self.showRowSeparators = true self.statusText = "Select a metric above to generate the power report." -end) + return self +end function ComparePowerReportListClass:SetReport(stat, report) self.impactColumn.label = stat and stat.label or "" diff --git a/src/Classes/CompareTab.lua b/src/Classes/CompareTab.lua index c8f00063cb..18b14093c7 100644 --- a/src/Classes/CompareTab.lua +++ b/src/Classes/CompareTab.lua @@ -115,9 +115,13 @@ local function matchFlags(reqFlags, notFlags, flags) return true end -local CompareTabClass = newClass("CompareTab", "ControlHost", "Control", function(self, primaryBuild) - self.ControlHost() - self.Control() +---@class CompareTab: ControlHost, Control +local CompareTabClass = newClass("CompareTab", "ControlHost", "Control") + +---@param primaryBuild Build +function CompareTabClass:CompareTab(primaryBuild) + self:ControlHost() + self:Control() self.primaryBuild = primaryBuild @@ -141,13 +145,13 @@ local CompareTabClass = newClass("CompareTab", "ControlHost", "Control", functio self.treeOverlayMode = true -- Tooltip for item hover in Items view - self.itemTooltip = new("Tooltip") + self.itemTooltip = new("Tooltip"):Tooltip() -- Items expanded mode (false = compact names only, true = full item details inline) self.itemsExpandedMode = false -- Tooltip for calcs hover breakdown - self.calcsTooltip = new("Tooltip") + self.calcsTooltip = new("Tooltip"):Tooltip() self.calcsShowOnlyDifferences = true -- Interactive config controls state @@ -176,21 +180,22 @@ local CompareTabClass = newClass("CompareTab", "ControlHost", "Control", functio -- Controls for the comparison screen self:InitControls() -end) + return self +end function CompareTabClass:InitControls() -- Sub-tab buttons local subTabs = { "Summary", "Tree", "Skills", "Items", "Calcs", "Config" } local subTabModes = { "SUMMARY", "TREE", "SKILLS", "ITEMS", "CALCS", "CONFIG" } - self.controls.subTabAnchor = new("Control", nil, {0, 0, 0, 20}) + self.controls.subTabAnchor = new("Control"):Control(nil, {0, 0, 0, 20}) for i, tabName in ipairs(subTabs) do local mode = subTabModes[i] local prevName = i > 1 and ("subTab" .. subTabs[i-1]) or "subTabAnchor" local anchor = i == 1 and {"TOPLEFT", self.controls.subTabAnchor, "TOPLEFT"} or {"LEFT", self.controls[prevName], "RIGHT"} - self.controls["subTab" .. tabName] = new("ButtonControl", anchor, {i == 1 and 0 or 4, 0, 72, 20}, tabName, function() + self.controls["subTab" .. tabName] = new("ButtonControl"):ButtonControl(anchor, {i == 1 and 0 or 4, 0, 72, 20}, tabName, function() -- Clear tree overlay compareSpec when leaving TREE mode if self.compareViewMode == "TREE" and self.treeOverlayMode and self.primaryBuild.treeTab and self.primaryBuild.treeTab.viewer then @@ -211,8 +216,8 @@ function CompareTabClass:InitControls() end -- Build B selector dropdown - self.controls.compareBuildLabel = new("LabelControl", {"TOPLEFT", self.controls.subTabAnchor, "TOPLEFT"}, {0, -88, 0, 16}, "^7Compare with:") - self.controls.compareBuildSelect = new("DropDownControl", {"LEFT", self.controls.compareBuildLabel, "RIGHT"}, {4, 0, 250, 20}, {}, function(index, value) + self.controls.compareBuildLabel = new("LabelControl"):LabelControl({"TOPLEFT", self.controls.subTabAnchor, "TOPLEFT"}, {0, -88, 0, 16}, "^7Compare with:") + self.controls.compareBuildSelect = new("DropDownControl"):DropDownControl({"LEFT", self.controls.compareBuildLabel, "RIGHT"}, {4, 0, 250, 20}, {}, function(index, value) if index and index > 0 and index <= #self.compareEntries then self.activeCompareIndex = index self.treeSearchNeedsSync = true @@ -223,12 +228,12 @@ function CompareTabClass:InitControls() end -- Import button (opens import popup) - self.controls.importBtn = new("ButtonControl", {"LEFT", self.controls.compareBuildSelect, "RIGHT"}, {8, 0, 100, 20}, "Import...", function() + self.controls.importBtn = new("ButtonControl"):ButtonControl({"LEFT", self.controls.compareBuildSelect, "RIGHT"}, {8, 0, 100, 20}, "Import...", function() self:OpenImportPopup() end) -- Re-import current build button - self.controls.reimportBtn = new("ButtonControl", {"LEFT", self.controls.importBtn, "RIGHT"}, {4, 0, 140, 20}, "Re-import Current", function() + self.controls.reimportBtn = new("ButtonControl"):ButtonControl({"LEFT", self.controls.importBtn, "RIGHT"}, {4, 0, 140, 20}, "Re-import Current", function() self:ReimportPrimary() end) self.controls.reimportBtn.tooltipFunc = function(tooltip) @@ -255,7 +260,7 @@ function CompareTabClass:InitControls() end -- Remove comparison build button - self.controls.removeBtn = new("ButtonControl", {"LEFT", self.controls.reimportBtn, "RIGHT"}, {4, 0, 70, 20}, "Remove", function() + self.controls.removeBtn = new("ButtonControl"):ButtonControl({"LEFT", self.controls.reimportBtn, "RIGHT"}, {4, 0, 70, 20}, "Remove", function() if self.activeCompareIndex > 0 and self.activeCompareIndex <= #self.compareEntries then self:RemoveBuild(self.activeCompareIndex) end @@ -272,9 +277,9 @@ function CompareTabClass:InitControls() end -- Tree spec selector for comparison build - self.controls.compareSpecLabel = new("LabelControl", {"TOPLEFT", self.controls.subTabAnchor, "TOPLEFT"}, {0, -54, 0, 16}, "^7Tree set:") + self.controls.compareSpecLabel = new("LabelControl"):LabelControl({"TOPLEFT", self.controls.subTabAnchor, "TOPLEFT"}, {0, -54, 0, 16}, "^7Tree set:") self.controls.compareSpecLabel.shown = setsEnabled - self.controls.compareSpecSelect = new("DropDownControl", {"LEFT", self.controls.compareSpecLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) + self.controls.compareSpecSelect = new("DropDownControl"):DropDownControl({"LEFT", self.controls.compareSpecLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry and entry.treeTab and entry.treeTab.specList[index] then entry:SetActiveSpec(index) @@ -289,9 +294,9 @@ function CompareTabClass:InitControls() self.controls.compareSpecSelect.enableDroppedWidth = true -- Skill set selector for comparison build - self.controls.compareSkillSetLabel = new("LabelControl", {"LEFT", self.controls.compareSpecSelect, "RIGHT"}, {8, 0, 0, 16}, "^7Skill set:") + self.controls.compareSkillSetLabel = new("LabelControl"):LabelControl({"LEFT", self.controls.compareSpecSelect, "RIGHT"}, {8, 0, 0, 16}, "^7Skill set:") self.controls.compareSkillSetLabel.shown = setsEnabled - self.controls.compareSkillSetSelect = new("DropDownControl", {"LEFT", self.controls.compareSkillSetLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) + self.controls.compareSkillSetSelect = new("DropDownControl"):DropDownControl({"LEFT", self.controls.compareSkillSetLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry and entry.skillsTab and entry.skillsTab.skillSetOrderList[index] then entry:SetActiveSkillSet(entry.skillsTab.skillSetOrderList[index]) @@ -299,9 +304,9 @@ function CompareTabClass:InitControls() end) self.controls.compareSkillSetSelect.enabled = setsEnabled -- Item set selector for comparison build - self.controls.compareItemSetLabel = new("LabelControl", {"LEFT", self.controls.compareSkillSetSelect, "RIGHT"}, {8, 0, 0, 16}, "^7Item set:") + self.controls.compareItemSetLabel = new("LabelControl"):LabelControl({"LEFT", self.controls.compareSkillSetSelect, "RIGHT"}, {8, 0, 0, 16}, "^7Item set:") self.controls.compareItemSetLabel.shown = setsEnabled - self.controls.compareItemSetSelect = new("DropDownControl", {"LEFT", self.controls.compareItemSetLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) + self.controls.compareItemSetSelect = new("DropDownControl"):DropDownControl({"LEFT", self.controls.compareItemSetLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry and entry.itemsTab and entry.itemsTab.itemSetOrderList[index] then entry:SetActiveItemSet(entry.itemsTab.itemSetOrderList[index]) @@ -309,9 +314,9 @@ function CompareTabClass:InitControls() end) self.controls.compareItemSetSelect.enabled = setsEnabled -- Config set selector for comparison build - self.controls.compareConfigSetLabel = new("LabelControl", {"LEFT", self.controls.compareItemSetSelect, "RIGHT"}, {8, 0, 0, 16}, "^7Config set:") + self.controls.compareConfigSetLabel = new("LabelControl"):LabelControl({"LEFT", self.controls.compareItemSetSelect, "RIGHT"}, {8, 0, 0, 16}, "^7Config set:") self.controls.compareConfigSetLabel.shown = setsEnabled - self.controls.compareConfigSetSelect = new("DropDownControl", {"LEFT", self.controls.compareConfigSetLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) + self.controls.compareConfigSetSelect = new("DropDownControl"):DropDownControl({"LEFT", self.controls.compareConfigSetLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry and entry.configTab then local setId = entry.configTab.configSetOrderList[index] @@ -487,7 +492,7 @@ function CompareTabClass:InitControls() { label = "Effective DPS", buffMode = "EFFECTIVE" }, } -- Primary build calcs skill controls - self.controls.primCalcsSocketGroup = new("DropDownControl", nil, {0, 0, 200, 18}, {}, function(index, value) + self.controls.primCalcsSocketGroup = new("DropDownControl"):DropDownControl(nil, {0, 0, 200, 18}, {}, function(index, value) self.primaryBuild.calcsTab.input.skill_number = index self.primaryBuild.buildFlag = true end) @@ -495,7 +500,7 @@ function CompareTabClass:InitControls() self.controls.primCalcsSocketGroup.maxDroppedWidth = 400 self.controls.primCalcsSocketGroup.enableDroppedWidth = true - self.controls.primCalcsMainSkill = new("DropDownControl", nil, {0, 0, 200, 18}, {}, function(index, value) + self.controls.primCalcsMainSkill = new("DropDownControl"):DropDownControl(nil, {0, 0, 200, 18}, {}, function(index, value) local mainSocketGroup = self.primaryBuild.skillsTab.socketGroupList[self.primaryBuild.calcsTab.input.skill_number] if mainSocketGroup then mainSocketGroup.mainActiveSkillCalcs = index @@ -504,7 +509,7 @@ function CompareTabClass:InitControls() end) self.controls.primCalcsMainSkill.shown = false - self.controls.primCalcsSkillPart = new("DropDownControl", nil, {0, 0, 150, 18}, {}, function(index, value) + self.controls.primCalcsSkillPart = new("DropDownControl"):DropDownControl(nil, {0, 0, 150, 18}, {}, function(index, value) local mainSocketGroup = self.primaryBuild.skillsTab.socketGroupList[self.primaryBuild.calcsTab.input.skill_number] if mainSocketGroup then local displaySkillList = mainSocketGroup.displaySkillListCalcs @@ -517,7 +522,7 @@ function CompareTabClass:InitControls() end) self.controls.primCalcsSkillPart.shown = false - self.controls.primCalcsStageCount = new("EditControl", nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) + self.controls.primCalcsStageCount = new("EditControl"):EditControl(nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) local mainSocketGroup = self.primaryBuild.skillsTab.socketGroupList[self.primaryBuild.calcsTab.input.skill_number] if mainSocketGroup then local displaySkillList = mainSocketGroup.displaySkillListCalcs @@ -530,7 +535,7 @@ function CompareTabClass:InitControls() end) self.controls.primCalcsStageCount.shown = false - self.controls.primCalcsMineCount = new("EditControl", nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) + self.controls.primCalcsMineCount = new("EditControl"):EditControl(nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) local mainSocketGroup = self.primaryBuild.skillsTab.socketGroupList[self.primaryBuild.calcsTab.input.skill_number] if mainSocketGroup then local displaySkillList = mainSocketGroup.displaySkillListCalcs @@ -543,13 +548,13 @@ function CompareTabClass:InitControls() end) self.controls.primCalcsMineCount.shown = false - self.controls.primCalcsShowMinion = new("CheckBoxControl", nil, {0, 0, 18}, nil, function(state) + self.controls.primCalcsShowMinion = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, nil, function(state) self.primaryBuild.calcsTab.input.showMinion = state self.primaryBuild.buildFlag = true end, "Show stats for the minion instead of the player.") self.controls.primCalcsShowMinion.shown = false - self.controls.primCalcsMinion = new("DropDownControl", nil, {0, 0, 140, 18}, {}, function(index, value) + self.controls.primCalcsMinion = new("DropDownControl"):DropDownControl(nil, {0, 0, 140, 18}, {}, function(index, value) local mainSocketGroup = self.primaryBuild.skillsTab.socketGroupList[self.primaryBuild.calcsTab.input.skill_number] if mainSocketGroup then local displaySkillList = mainSocketGroup.displaySkillListCalcs @@ -569,7 +574,7 @@ function CompareTabClass:InitControls() end) self.controls.primCalcsMinion.shown = false - self.controls.primCalcsMinionSkill = new("DropDownControl", nil, {0, 0, 140, 18}, {}, function(index, value) + self.controls.primCalcsMinionSkill = new("DropDownControl"):DropDownControl(nil, {0, 0, 140, 18}, {}, function(index, value) local mainSocketGroup = self.primaryBuild.skillsTab.socketGroupList[self.primaryBuild.calcsTab.input.skill_number] if mainSocketGroup then local displaySkillList = mainSocketGroup.displaySkillListCalcs @@ -623,7 +628,7 @@ function CompareTabClass:InitControls() self.controls.cmpCalcsSocketGroup.maxDroppedWidth = 400 self.controls.cmpCalcsSocketGroup.enableDroppedWidth = true - self.controls.cmpCalcsMainSkill = new("DropDownControl", nil, {0, 0, 200, 18}, {}, function(index, value) + self.controls.cmpCalcsMainSkill = new("DropDownControl"):DropDownControl(nil, {0, 0, 200, 18}, {}, function(index, value) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.calcsTab.input.skill_number] @@ -635,7 +640,7 @@ function CompareTabClass:InitControls() end) self.controls.cmpCalcsMainSkill.shown = false - self.controls.cmpCalcsSkillPart = new("DropDownControl", nil, {0, 0, 150, 18}, {}, function(index, value) + self.controls.cmpCalcsSkillPart = new("DropDownControl"):DropDownControl(nil, {0, 0, 150, 18}, {}, function(index, value) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.calcsTab.input.skill_number] @@ -651,7 +656,7 @@ function CompareTabClass:InitControls() end) self.controls.cmpCalcsSkillPart.shown = false - self.controls.cmpCalcsStageCount = new("EditControl", nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) + self.controls.cmpCalcsStageCount = new("EditControl"):EditControl(nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.calcsTab.input.skill_number] @@ -667,7 +672,7 @@ function CompareTabClass:InitControls() end) self.controls.cmpCalcsStageCount.shown = false - self.controls.cmpCalcsMineCount = new("EditControl", nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) + self.controls.cmpCalcsMineCount = new("EditControl"):EditControl(nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.calcsTab.input.skill_number] @@ -683,7 +688,7 @@ function CompareTabClass:InitControls() end) self.controls.cmpCalcsMineCount.shown = false - self.controls.cmpCalcsShowMinion = new("CheckBoxControl", nil, {0, 0, 18}, nil, function(state) + self.controls.cmpCalcsShowMinion = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, nil, function(state) local entry = self:GetActiveCompare() if entry then entry.calcsTab.input.showMinion = state @@ -692,7 +697,7 @@ function CompareTabClass:InitControls() end, "Show stats for the minion instead of the player.") self.controls.cmpCalcsShowMinion.shown = false - self.controls.cmpCalcsMinion = new("DropDownControl", nil, {0, 0, 140, 18}, {}, function(index, value) + self.controls.cmpCalcsMinion = new("DropDownControl"):DropDownControl(nil, {0, 0, 140, 18}, {}, function(index, value) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.calcsTab.input.skill_number] @@ -715,7 +720,7 @@ function CompareTabClass:InitControls() end) self.controls.cmpCalcsMinion.shown = false - self.controls.cmpCalcsMinionSkill = new("DropDownControl", nil, {0, 0, 140, 18}, {}, function(index, value) + self.controls.cmpCalcsMinionSkill = new("DropDownControl"):DropDownControl(nil, {0, 0, 140, 18}, {}, function(index, value) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.calcsTab.input.skill_number] @@ -765,7 +770,7 @@ function CompareTabClass:InitControls() end) self.controls.cmpCalcsMode.shown = false - self.controls.calcsShowOnlyDifferencesCheck = new("CheckBoxControl", nil, {0, 0, 18}, "Show only differences", function(state) + self.controls.calcsShowOnlyDifferencesCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, "Show only differences", function(state) self.calcsShowOnlyDifferences = state end, "Show only rows that differ between both builds. Disable to include unchanged rows.") self.controls.calcsShowOnlyDifferencesCheck.shown = function() @@ -792,7 +797,7 @@ function CompareTabClass:InitControls() end -- Overlay toggle checkbox - self.controls.treeOverlayCheck = new("CheckBoxControl", nil, {0, 0, 20}, "Overlay comparison", function(state) + self.controls.treeOverlayCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 20}, "Overlay comparison", function(state) self.treeOverlayMode = state self.treeSearchNeedsSync = true if not state and self.primaryBuild.treeTab and self.primaryBuild.treeTab.viewer then @@ -802,7 +807,7 @@ function CompareTabClass:InitControls() self.controls.treeOverlayCheck.shown = treeFooterShown -- Overlay-mode search (single search for primary viewer) - self.controls.overlayTreeSearch = new("EditControl", nil, {0, 0, 300, 20}, "", "Search", "%c", 100, function(buf) + self.controls.overlayTreeSearch = new("EditControl"):EditControl(nil, {0, 0, 300, 20}, "", "Search", "%c", 100, function(buf) if self.primaryBuild.treeTab and self.primaryBuild.treeTab.viewer then self.primaryBuild.treeTab.viewer.searchStr = buf end @@ -812,7 +817,7 @@ function CompareTabClass:InitControls() end -- Items expanded mode toggle - self.controls.itemsExpandedCheck = new("CheckBoxControl", nil, {0, 0, 20}, "Expanded mode", function(state) + self.controls.itemsExpandedCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 20}, "Expanded mode", function(state) self.itemsExpandedMode = state self.scrollY = 0 end) @@ -824,9 +829,9 @@ function CompareTabClass:InitControls() local itemsShown = function() return self.compareViewMode == "ITEMS" and self:GetActiveCompare() ~= nil end - self.controls.primaryItemSetLabel = new("LabelControl", nil, {0, 0, 0, 16}, "^7Item set:") + self.controls.primaryItemSetLabel = new("LabelControl"):LabelControl(nil, {0, 0, 0, 16}, "^7Item set:") self.controls.primaryItemSetLabel.shown = itemsShown - self.controls.primaryItemSetSelect = new("DropDownControl", nil, {0, 0, 216, 20}, {}, function(index, value) + self.controls.primaryItemSetSelect = new("DropDownControl"):DropDownControl(nil, {0, 0, 216, 20}, {}, function(index, value) if self.primaryBuild.itemsTab and self.primaryBuild.itemsTab.itemSetOrderList[index] then self.primaryBuild.itemsTab:SetActiveItemSet(self.primaryBuild.itemsTab.itemSetOrderList[index]) self.primaryBuild.itemsTab:AddUndoState() @@ -836,9 +841,9 @@ function CompareTabClass:InitControls() self.controls.primaryItemSetSelect.shown = itemsShown -- Item set dropdown for compare build - self.controls.compareItemSetLabel2 = new("LabelControl", nil, {0, 0, 0, 16}, "^7Item set:") + self.controls.compareItemSetLabel2 = new("LabelControl"):LabelControl(nil, {0, 0, 0, 16}, "^7Item set:") self.controls.compareItemSetLabel2.shown = itemsShown - self.controls.compareItemSetSelect2 = new("DropDownControl", nil, {0, 0, 216, 20}, {}, function(index, value) + self.controls.compareItemSetSelect2 = new("DropDownControl"):DropDownControl(nil, {0, 0, 216, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry and entry.itemsTab and entry.itemsTab.itemSetOrderList[index] then entry:SetActiveItemSet(entry.itemsTab.itemSetOrderList[index]) @@ -848,9 +853,9 @@ function CompareTabClass:InitControls() self.controls.compareItemSetSelect2.shown = itemsShown -- Tree set dropdown for primary build - self.controls.primaryTreeSetLabel = new("LabelControl", nil, {0, 0, 0, 16}, "^7Tree set:") + self.controls.primaryTreeSetLabel = new("LabelControl"):LabelControl(nil, {0, 0, 0, 16}, "^7Tree set:") self.controls.primaryTreeSetLabel.shown = itemsShown - self.controls.primaryTreeSetSelect = new("DropDownControl", nil, {0, 0, 216, 20}, {}, function(index, value) + self.controls.primaryTreeSetSelect = new("DropDownControl"):DropDownControl(nil, {0, 0, 216, 20}, {}, function(index, value) if self.primaryBuild.treeTab and self.primaryBuild.treeTab.specList[index] then self.primaryBuild.modFlag = true self.primaryBuild.treeTab:SetActiveSpec(index) @@ -862,9 +867,9 @@ function CompareTabClass:InitControls() self.controls.primaryTreeSetSelect.enableDroppedWidth = true -- Tree set dropdown for compare build - self.controls.compareTreeSetLabel = new("LabelControl", nil, {0, 0, 0, 16}, "^7Tree set:") + self.controls.compareTreeSetLabel = new("LabelControl"):LabelControl(nil, {0, 0, 0, 16}, "^7Tree set:") self.controls.compareTreeSetLabel.shown = itemsShown - self.controls.compareTreeSetSelect = new("DropDownControl", nil, {0, 0, 216, 20}, {}, function(index, value) + self.controls.compareTreeSetSelect = new("DropDownControl"):DropDownControl(nil, {0, 0, 216, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry and entry.treeTab and entry.treeTab.specList[index] then entry:SetActiveSpec(index) @@ -879,13 +884,13 @@ function CompareTabClass:InitControls() self.controls.compareTreeSetSelect.enableDroppedWidth = true -- Footer anchor controls (side-by-side only) - self.controls.leftFooterAnchor = new("Control", nil, {0, 0, 0, 20}) + self.controls.leftFooterAnchor = new("Control"):Control(nil, {0, 0, 0, 20}) self.controls.leftFooterAnchor.shown = treeSideBySideShown - self.controls.rightFooterAnchor = new("Control", nil, {0, 0, 0, 20}) + self.controls.rightFooterAnchor = new("Control"):Control(nil, {0, 0, 0, 20}) self.controls.rightFooterAnchor.shown = treeSideBySideShown -- Left side (primary build) spec/version controls (header, both modes) - self.controls.leftSpecSelect = new("DropDownControl", nil, {0, 0, 180, 20}, {}, function(index, value) + self.controls.leftSpecSelect = new("DropDownControl"):DropDownControl(nil, {0, 0, 180, 20}, {}, function(index, value) if self.primaryBuild.treeTab and self.primaryBuild.treeTab.specList[index] then self.primaryBuild.modFlag = true self.primaryBuild.treeTab:SetActiveSpec(index) @@ -895,7 +900,7 @@ function CompareTabClass:InitControls() self.controls.leftSpecSelect.maxDroppedWidth = 500 self.controls.leftSpecSelect.enableDroppedWidth = true - self.controls.leftVersionSelect = new("DropDownControl", {"LEFT", self.controls.leftSpecSelect, "RIGHT"}, {4, 0, 100, 20}, self.treeVersionDropdownList, function(index, selected) + self.controls.leftVersionSelect = new("DropDownControl"):DropDownControl({"LEFT", self.controls.leftSpecSelect, "RIGHT"}, {4, 0, 100, 20}, self.treeVersionDropdownList, function(index, selected) if selected and selected.value and self.primaryBuild.spec and selected.value ~= self.primaryBuild.spec.treeVersion then self.primaryBuild.treeTab:OpenVersionConvertPopup(selected.value, true) end @@ -903,7 +908,7 @@ function CompareTabClass:InitControls() self.controls.leftVersionSelect.shown = treeFooterShown -- Left search (footer, side-by-side only) - self.controls.leftTreeSearch = new("EditControl", {"TOPLEFT", self.controls.leftFooterAnchor, "TOPLEFT"}, {0, 0, 200, 20}, "", "Search", "%c", 100, function(buf) + self.controls.leftTreeSearch = new("EditControl"):EditControl({"TOPLEFT", self.controls.leftFooterAnchor, "TOPLEFT"}, {0, 0, 200, 20}, "", "Search", "%c", 100, function(buf) if self.primaryBuild.treeTab and self.primaryBuild.treeTab.viewer then self.primaryBuild.treeTab.viewer.searchStr = buf end @@ -911,7 +916,7 @@ function CompareTabClass:InitControls() self.controls.leftTreeSearch.shown = treeSideBySideShown -- Right side (compare build) spec/version controls (header, both modes) - self.controls.rightSpecSelect = new("DropDownControl", nil, {0, 0, 180, 20}, {}, function(index, value) + self.controls.rightSpecSelect = new("DropDownControl"):DropDownControl(nil, {0, 0, 180, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry and entry.treeTab and entry.treeTab.specList[index] then entry:SetActiveSpec(index) @@ -925,7 +930,7 @@ function CompareTabClass:InitControls() self.controls.rightSpecSelect.maxDroppedWidth = 500 self.controls.rightSpecSelect.enableDroppedWidth = true - self.controls.rightVersionSelect = new("DropDownControl", {"LEFT", self.controls.rightSpecSelect, "RIGHT"}, {4, 0, 100, 20}, self.treeVersionDropdownList, function(index, selected) + self.controls.rightVersionSelect = new("DropDownControl"):DropDownControl({"LEFT", self.controls.rightSpecSelect, "RIGHT"}, {4, 0, 100, 20}, self.treeVersionDropdownList, function(index, selected) local entry = self:GetActiveCompare() if entry and selected and selected.value and entry.spec then if selected.value ~= entry.spec.treeVersion then @@ -936,7 +941,7 @@ function CompareTabClass:InitControls() self.controls.rightVersionSelect.shown = treeFooterShown -- Copy compared tree to primary build - self.controls.copySpecBtn = new("ButtonControl", {"LEFT", self.controls.rightVersionSelect, "RIGHT"}, {4, 0, 76, 20}, "Copy tree", function() + self.controls.copySpecBtn = new("ButtonControl"):ButtonControl({"LEFT", self.controls.rightVersionSelect, "RIGHT"}, {4, 0, 76, 20}, "Copy tree", function() self:CopyCompareSpecToPrimary(false) end) self.controls.copySpecBtn.shown = treeFooterShown @@ -945,14 +950,14 @@ function CompareTabClass:InitControls() return entry and entry.treeTab and entry.treeTab.specList[entry.treeTab.activeSpec] ~= nil end - self.controls.copySpecUseBtn = new("ButtonControl", {"LEFT", self.controls.copySpecBtn, "RIGHT"}, {2, 0, 100, 20}, "Copy and use", function() + self.controls.copySpecUseBtn = new("ButtonControl"):ButtonControl({"LEFT", self.controls.copySpecBtn, "RIGHT"}, {2, 0, 100, 20}, "Copy and use", function() self:CopyCompareSpecToPrimary(true) end) self.controls.copySpecUseBtn.shown = treeFooterShown self.controls.copySpecUseBtn.enabled = self.controls.copySpecBtn.enabled -- Right search (footer, side-by-side only) - self.controls.rightTreeSearch = new("EditControl", {"TOPLEFT", self.controls.rightFooterAnchor, "TOPLEFT"}, {0, 0, 200, 20}, "", "Search", "%c", 100, function(buf) + self.controls.rightTreeSearch = new("EditControl"):EditControl({"TOPLEFT", self.controls.rightFooterAnchor, "TOPLEFT"}, {0, 0, 200, 20}, "", "Search", "%c", 100, function(buf) local entry = self:GetActiveCompare() if entry and entry.treeTab and entry.treeTab.viewer then entry.treeTab.viewer.searchStr = buf @@ -961,7 +966,7 @@ function CompareTabClass:InitControls() self.controls.rightTreeSearch.shown = treeSideBySideShown -- Config view: "Copy Config from Compare Build" button - self.controls.copyConfigBtn = new("ButtonControl", nil, {0, 0, 240, 20}, + self.controls.copyConfigBtn = new("ButtonControl"):ButtonControl(nil, {0, 0, 240, 20}, "Copy Config from Compare Build", function() self:CopyCompareConfig() end) self.controls.copyConfigBtn.shown = function() @@ -969,7 +974,7 @@ function CompareTabClass:InitControls() end -- Config view: "Show All / Hide Ineligible" toggle button - self.controls.configToggleBtn = new("ButtonControl", nil, {0, 0, 240, 20}, + self.controls.configToggleBtn = new("ButtonControl"):ButtonControl(nil, {0, 0, 240, 20}, function() return self.configToggle and "Hide Ineligible Configurations" or "Show All Configurations" end, @@ -981,7 +986,7 @@ function CompareTabClass:InitControls() end -- Config view: search bar - self.controls.configSearchEdit = new("EditControl", nil, {0, 0, 240, 20}, "", "Search", "%c", 100, nil, nil, nil, true) + self.controls.configSearchEdit = new("EditControl"):EditControl(nil, {0, 0, 240, 20}, "", "Search", "%c", 100, nil, nil, nil, true) self.controls.configSearchEdit.shown = function() return self.compareViewMode == "CONFIG" and self:GetActiveCompare() ~= nil end @@ -990,9 +995,9 @@ function CompareTabClass:InitControls() local configShown = function() return self.compareViewMode == "CONFIG" and self:GetActiveCompare() ~= nil end - self.controls.configPrimarySetLabel = new("LabelControl", nil, {0, 0, 0, 16}, "^7Config set:") + self.controls.configPrimarySetLabel = new("LabelControl"):LabelControl(nil, {0, 0, 0, 16}, "^7Config set:") self.controls.configPrimarySetLabel.shown = configShown - self.controls.configPrimarySetSelect = new("DropDownControl", nil, {0, 0, 150, 20}, nil, function(index, value) + self.controls.configPrimarySetSelect = new("DropDownControl"):DropDownControl(nil, {0, 0, 150, 20}, nil, function(index, value) local configTab = self.primaryBuild.configTab local setId = configTab.configSetOrderList[index] if setId then @@ -1020,7 +1025,7 @@ function CompareTabClass:InitControls() t_insert(powerStatList, entry) end end - self.controls.comparePowerStatSelect = new("DropDownControl", nil, {0, 0, 200, 20}, powerStatList, function(index, value) + self.controls.comparePowerStatSelect = new("DropDownControl"):DropDownControl(nil, {0, 0, 200, 20}, powerStatList, function(index, value) if value and value.stat and value ~= self.comparePowerStat then self.comparePowerStat = value self.comparePowerDirty = true @@ -1041,35 +1046,35 @@ function CompareTabClass:InitControls() end -- Category checkboxes - self.controls.comparePowerTreeCheck = new("CheckBoxControl", nil, {0, 0, 18}, "Tree:", function(state) + self.controls.comparePowerTreeCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, "Tree:", function(state) self.comparePowerCategories.treeNodes = state self.comparePowerDirty = true end, "Include passive tree nodes from compared build") self.controls.comparePowerTreeCheck.shown = powerReportShown self.controls.comparePowerTreeCheck.state = true - self.controls.comparePowerItemsCheck = new("CheckBoxControl", nil, {0, 0, 18}, "Items:", function(state) + self.controls.comparePowerItemsCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, "Items:", function(state) self.comparePowerCategories.items = state self.comparePowerDirty = true end, "Include items from compared build") self.controls.comparePowerItemsCheck.shown = powerReportShown self.controls.comparePowerItemsCheck.state = true - self.controls.comparePowerGemsCheck = new("CheckBoxControl", nil, {0, 0, 18}, "Skill gems:", function(state) + self.controls.comparePowerGemsCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, "Skill gems:", function(state) self.comparePowerCategories.skillGems = state self.comparePowerDirty = true end, "Include skill gem groups unique to compared build") self.controls.comparePowerGemsCheck.shown = powerReportShown self.controls.comparePowerGemsCheck.state = true - self.controls.comparePowerSupportGemsCheck = new("CheckBoxControl", nil, {0, 0, 18}, "Support gems:", function(state) + self.controls.comparePowerSupportGemsCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, "Support gems:", function(state) self.comparePowerCategories.supportGems = state self.comparePowerDirty = true end, "Include support gems from compared build's active skill") self.controls.comparePowerSupportGemsCheck.shown = powerReportShown self.controls.comparePowerSupportGemsCheck.state = true - self.controls.comparePowerConfigCheck = new("CheckBoxControl", nil, {0, 0, 18}, "Config:", function(state) + self.controls.comparePowerConfigCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, "Config:", function(state) self.comparePowerCategories.config = state self.comparePowerDirty = true end, "Include config option differences from compared build") @@ -1077,19 +1082,19 @@ function CompareTabClass:InitControls() self.controls.comparePowerConfigCheck.state = true -- Power report list control (static height, own scrollbar) - self.controls.comparePowerReportList = new("ComparePowerReportListControl", nil, {0, 0, 750, 250}) + self.controls.comparePowerReportList = new("ComparePowerReportListControl"):ComparePowerReportListControl(nil, {0, 0, 750, 250}) self.controls.comparePowerReportList.compareTab = self self.controls.comparePowerReportList.shown = powerReportShown -- Scrollbar for Calcs sub-tab - self.controls.calcsScrollBar = new("ScrollBarControl", nil, {0, 0, 18, 0}, 50, "VERTICAL", true) + self.controls.calcsScrollBar = new("ScrollBarControl"):ScrollBarControl(nil, {0, 0, 18, 0}, 50, "VERTICAL", true) local calcsScrollBar = self.controls.calcsScrollBar self.controls.calcsScrollBar.shown = function() return self.compareViewMode == "CALCS" and self:GetActiveCompare() ~= nil and calcsScrollBar.enabled end -- Shared vertical scrollbar for Summary/Items/Skills/Config sub-tabs - self.controls.viewScrollBar = new("ScrollBarControl", nil, {0, 0, 18, 0}, 50, "VERTICAL", true) + self.controls.viewScrollBar = new("ScrollBarControl"):ScrollBarControl(nil, {0, 0, 18, 0}, 50, "VERTICAL", true) local viewScrollBar = self.controls.viewScrollBar self.controls.viewScrollBar.shown = function() return self:GetActiveCompare() ~= nil @@ -1099,14 +1104,14 @@ function CompareTabClass:InitControls() end -- Horizontal scrollbar for Items sub-tab - self.controls.itemsHScrollBar = new("ScrollBarControl", nil, {0, 0, 0, LAYOUT.itemsHScrollBarHeight}, 60, "HORIZONTAL", true) + self.controls.itemsHScrollBar = new("ScrollBarControl"):ScrollBarControl(nil, {0, 0, 0, LAYOUT.itemsHScrollBarHeight}, 60, "HORIZONTAL", true) local itemsHScrollBar = self.controls.itemsHScrollBar self.controls.itemsHScrollBar.shown = function() return self.compareViewMode == "ITEMS" and self:GetActiveCompare() ~= nil and itemsHScrollBar.enabled end -- Horizontal scrollbar for Skills sub-tab - self.controls.skillsHScrollBar = new("ScrollBarControl", nil, {0, 0, 0, LAYOUT.skillsHScrollBarHeight}, 60, "HORIZONTAL", true) + self.controls.skillsHScrollBar = new("ScrollBarControl"):ScrollBarControl(nil, {0, 0, 0, LAYOUT.skillsHScrollBarHeight}, 60, "HORIZONTAL", true) local skillsHScrollBar = self.controls.skillsHScrollBar self.controls.skillsHScrollBar.shown = function() return self.compareViewMode == "SKILLS" and self:GetActiveCompare() ~= nil and skillsHScrollBar.enabled @@ -1177,7 +1182,7 @@ local function makeConfigControl(varData, inputTable, configTab, buildObj, sourc local control local pVal = inputTable[varData.var] if varData.type == "check" then - control = new("CheckBoxControl", nil, {0, 0, 18}, nil, function(state) + control = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, nil, function(state) inputTable[varData.var] = state configTab:UpdateControls() configTab:BuildModList() @@ -1188,7 +1193,7 @@ local function makeConfigControl(varData, inputTable, configTab, buildObj, sourc or varData.type == "countAllowZero" or varData.type == "float" then local filter = (varData.type == "integer" and "^%-%d") or (varData.type == "float" and "^%d.") or "%D" - control = new("EditControl", nil, {0, 0, 90, 18}, + control = new("EditControl"):EditControl(nil, {0, 0, 90, 18}, tostring(pVal or ""), nil, filter, 7, function(buf) inputTable[varData.var] = tonumber(buf) @@ -1197,7 +1202,7 @@ local function makeConfigControl(varData, inputTable, configTab, buildObj, sourc buildObj.buildFlag = true end) elseif varData.type == "list" and varData.list then - control = new("DropDownControl", nil, {0, 0, 150, 18}, + control = new("DropDownControl"):DropDownControl(nil, {0, 0, 150, 18}, varData.list, function(index, value) inputTable[varData.var] = value.val configTab:UpdateControls() @@ -1306,7 +1311,7 @@ end -- Import a comparison build from XML text function CompareTabClass:ImportBuild(xmlText, label) - local entry = new("CompareEntry", xmlText, label) + local entry = new("CompareEntry"):CompareEntry(xmlText, label) if entry and entry.calcsTab and entry.calcsTab.mainOutput then t_insert(self.compareEntries, entry) self.activeCompareIndex = #self.compareEntries @@ -1390,7 +1395,7 @@ function CompareTabClass:CopyCompareSpecToPrimary(andUse) -- Create new spec from source (same pattern as PassiveSpecListControl Copy) -- Note: we don't copy jewels because they reference item IDs in the compared -- build's itemsTab which don't exist in the primary build - local newSpec = new("PassiveSpec", self.primaryBuild, sourceSpec.treeVersion) + local newSpec = new("PassiveSpec"):PassiveSpec(self.primaryBuild, sourceSpec.treeVersion) newSpec.title = (sourceSpec.title or "Default") .. " (Compared)" newSpec:RestoreUndoState(sourceSpec:CreateUndoState()) newSpec:BuildClusterJewelGraphs() @@ -1492,7 +1497,7 @@ function CompareTabClass:CopyCompareItemToPrimary(slotName, compareEntry, andUse local cItem = cSlot and compareEntry.itemsTab.items and compareEntry.itemsTab.items[cSlot.selItemId] if not cItem or not cItem.raw then return end - local newItem = new("Item", cItem.raw) + local newItem = new("Item"):Item(cItem.raw) newItem:NormaliseQuality() local pItemsTab = self.primaryBuild.itemsTab pItemsTab:AddItem(newItem, true) -- true = noAutoEquip @@ -1515,20 +1520,20 @@ function CompareTabClass:OpenImportPopup() -- Use a local variable for state text so it doesn't go into the controls table -- (PopupDialog iterates all controls table entries and expects them to be control objects) local stateText = "" - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Paste a build code or URL to import as comparison:") - controls.input = new("EditControl", nil, {0, 50, 450, 20}, "", nil, nil, nil, nil, nil, nil, true) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Paste a build code or URL to import as comparison:") + controls.input = new("EditControl"):EditControl(nil, {0, 50, 450, 20}, "", nil, nil, nil, nil, nil, nil, true) controls.input.enterFunc = function() if controls.input.buf and controls.input.buf ~= "" then controls.go.onClick() end end - controls.name = new("EditControl", nil, {0, 80, 450, 20}, "", "Name (optional)", nil, 100, nil) - controls.state = new("LabelControl", {"TOPLEFT", controls.name, "BOTTOMLEFT"}, {0, 4, 0, 16}) + controls.name = new("EditControl"):EditControl(nil, {0, 80, 450, 20}, "", "Name (optional)", nil, 100, nil) + controls.state = new("LabelControl"):LabelControl({"TOPLEFT", controls.name, "BOTTOMLEFT"}, {0, 4, 0, 16}) controls.state.label = function() return stateText or "" end - controls.go = new("ButtonControl", nil, {-118, 130, 80, 20}, "Import", function() + controls.go = new("ButtonControl"):ButtonControl(nil, {-118, 130, 80, 20}, "Import", function() local buf = controls.input.buf if not buf or buf == "" then return @@ -1565,11 +1570,11 @@ function CompareTabClass:OpenImportPopup() stateText = colorCodes.NEGATIVE .. "Invalid build code" end end) - controls.importFolder = new("ButtonControl", nil, {0, 130, 140, 20}, "Import from Folder", function() + controls.importFolder = new("ButtonControl"):ButtonControl(nil, {0, 130, 140, 20}, "Import from Folder", function() main:ClosePopup() self:OpenImportFolderPopup() end) - controls.cancel = new("ButtonControl", nil, {118, 130, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {118, 130, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(500, 160, "Import Comparison Build", controls, "go", "input", "cancel") @@ -1633,7 +1638,7 @@ function CompareTabClass:OpenImportFolderPopup() controls.sort:SelByValue(sortMode, "sortMode") -- Build list itself. Reuses BuildListControl (which provides the PathControl breadcrumbs) - controls.buildList = new("BuildListControl", {"TOPLEFT", nil, "TOPLEFT"}, {15, 75, 0, 0}, listHost) + controls.buildList = new("BuildListControl"):BuildListControl({"TOPLEFT", nil, "TOPLEFT"}, {15, 75, 0, 0}, listHost) controls.buildList.width = function() return 670 end controls.buildList.height = function() return 355 end @@ -1665,14 +1670,14 @@ function CompareTabClass:OpenImportFolderPopup() -- Populate the initial list now that the control (and its path control) exist. listHost:BuildList() - controls.open = new("ButtonControl", {"TOPLEFT", nil, "TOPLEFT"}, {255, 465, 80, 20}, "Open", function() + controls.open = new("ButtonControl"):ButtonControl({"TOPLEFT", nil, "TOPLEFT"}, {255, 465, 80, 20}, "Open", function() local sel = controls.buildList.selValue if sel then controls.buildList:LoadBuild(sel) end end) controls.open.enabled = function() return controls.buildList.selValue ~= nil end - controls.close = new("ButtonControl", {"TOPLEFT", nil, "TOPLEFT"}, {365, 465, 80, 20}, "Close", function() + controls.close = new("ButtonControl"):ButtonControl({"TOPLEFT", nil, "TOPLEFT"}, {365, 465, 80, 20}, "Close", function() main:ClosePopup() end) @@ -2823,7 +2828,7 @@ function CompareTabClass:ComparePowerBuilder(compareEntry, powerStat, categories local jewelSlots = self:GetJewelComparisonSlots(compareEntry) for _, jEntry in ipairs(jewelSlots) do if jEntry.cItem and jEntry.cItem.raw and not (jEntry.pItem and jEntry.pItem.name == jEntry.cItem.name) then - local newItem = new("Item", jEntry.cItem.raw) + local newItem = new("Item"):Item(jEntry.cItem.raw) newItem:NormaliseQuality() local bestImpactVal = nil @@ -3921,7 +3926,7 @@ function CompareTabClass:DrawItems(vp, compareEntry, inputEvents) local calcFunc, calcBase = self.calcs.getMiscCalculator(self.primaryBuild) if calcFunc then -- Create a fresh item to evaluate - local newItem = new("Item", hoverEquipItem.raw) + local newItem = new("Item"):Item(hoverEquipItem.raw) newItem:NormaliseQuality() -- Determine what's currently in the target slot diff --git a/src/Classes/CompareTab.lua.rej b/src/Classes/CompareTab.lua.rej new file mode 100644 index 0000000000..f5bbc36c8d --- /dev/null +++ b/src/Classes/CompareTab.lua.rej @@ -0,0 +1,137 @@ +diff a/src/Classes/CompareTab.lua b/src/Classes/CompareTab.lua (rejected hunks) +@@ -344,12 +349,12 @@ function CompareTabClass:InitControls() + -- ============================================================ + -- Comparison build main skill selector (row between sets and sub-tabs) + -- ============================================================ +- self.controls.cmpSkillLabel = new("LabelControl", {"TOPLEFT", self.controls.subTabAnchor, "TOPLEFT"}, {0, -32, 0, 16}, "^7Skill:") ++ self.controls.cmpSkillLabel = new("LabelControl"):LabelControl({"TOPLEFT", self.controls.subTabAnchor, "TOPLEFT"}, {0, -32, 0, 16}, "^7Skill:") + self.controls.cmpSkillLabel.shown = setsEnabled + self.controls.cmpSkillLabel.anchor.collapse = true + + -- Socket group dropdown +- self.controls.cmpSocketGroup = new("DropDownControl", {"LEFT", self.controls.cmpSkillLabel, "RIGHT"}, {4, 0, 200, 20}, {}, function(index, value) ++ self.controls.cmpSocketGroup = new("DropDownControl"):DropDownControl({"LEFT", self.controls.cmpSkillLabel, "RIGHT"}, {4, 0, 200, 20}, {}, function(index, value) + local entry = self:GetActiveCompare() + if entry then + entry:SetMainSocketGroup(index) +@@ -361,7 +366,7 @@ function CompareTabClass:InitControls() + self.controls.cmpSocketGroup.anchor.collapse = true + + -- Active skill within group +- self.controls.cmpMainSkill = new("DropDownControl", {"LEFT", self.controls.cmpSocketGroup, "RIGHT"}, {4, 0, 225, 20}, {}, function(index, value) ++ self.controls.cmpMainSkill = new("DropDownControl"):DropDownControl({"LEFT", self.controls.cmpSocketGroup, "RIGHT"}, {4, 0, 225, 20}, {}, function(index, value) + local entry = self:GetActiveCompare() + if entry then + local mainSocketGroup = entry.skillsTab.socketGroupList[entry.mainSocketGroup] +@@ -375,7 +380,7 @@ function CompareTabClass:InitControls() + self.controls.cmpMainSkill.anchor.collapse = true + + -- Skill part (multi-part skills) +- self.controls.cmpSkillPart = new("DropDownControl", {"LEFT", self.controls.cmpMainSkill, "RIGHT"}, {4, 0, 200, 20}, {}, function(index, value) ++ self.controls.cmpSkillPart = new("DropDownControl"):DropDownControl({"LEFT", self.controls.cmpMainSkill, "RIGHT"}, {4, 0, 200, 20}, {}, function(index, value) + local entry = self:GetActiveCompare() + if entry then + local mainSocketGroup = entry.skillsTab.socketGroupList[entry.mainSocketGroup] +@@ -393,10 +398,10 @@ function CompareTabClass:InitControls() + self.controls.cmpSkillPart.anchor.collapse = true + + -- Stage count +- self.controls.cmpStageCountLabel = new("LabelControl", {"LEFT", self.controls.cmpSkillPart, "RIGHT"}, {6, 0, 0, 16}, "^7Stages:") ++ self.controls.cmpStageCountLabel = new("LabelControl"):LabelControl({"LEFT", self.controls.cmpSkillPart, "RIGHT"}, {6, 0, 0, 16}, "^7Stages:") + self.controls.cmpStageCountLabel.shown = function() return self.controls.cmpStageCount.shown end + self.controls.cmpStageCountLabel.anchor.collapse = true +- self.controls.cmpStageCount = new("EditControl", {"LEFT", self.controls.cmpStageCountLabel, "RIGHT"}, {4, 0, 52, 20}, "", nil, "%D", 5, function(buf) ++ self.controls.cmpStageCount = new("EditControl"):EditControl({ "LEFT", self.controls.cmpStageCountLabel, "RIGHT" }, { 4, 0, 52, 20 }, "", nil, "%D", 5, function(buf) + local entry = self:GetActiveCompare() + if entry then + local mainSocketGroup = entry.skillsTab.socketGroupList[entry.mainSocketGroup] +@@ -414,10 +419,10 @@ function CompareTabClass:InitControls() + self.controls.cmpStageCount.anchor.collapse = true + + -- Mine count +- self.controls.cmpMineCountLabel = new("LabelControl", {"LEFT", self.controls.cmpStageCount, "RIGHT"}, {6, 0, 0, 16}, "^7Mines:") ++ self.controls.cmpMineCountLabel = new("LabelControl"):LabelControl({"LEFT", self.controls.cmpStageCount, "RIGHT"}, {6, 0, 0, 16}, "^7Mines:") + self.controls.cmpMineCountLabel.shown = function() return self.controls.cmpMineCount.shown end + self.controls.cmpMineCountLabel.anchor.collapse = true +- self.controls.cmpMineCount = new("EditControl", {"LEFT", self.controls.cmpMineCountLabel, "RIGHT"}, {4, 0, 52, 20}, "", nil, "%D", 5, function(buf) ++ self.controls.cmpMineCount = new("EditControl"):EditControl({ "LEFT", self.controls.cmpMineCountLabel, "RIGHT" }, { 4, 0, 52, 20 }, "", nil, "%D", 5, function(buf) + local entry = self:GetActiveCompare() + if entry then + local mainSocketGroup = entry.skillsTab.socketGroupList[entry.mainSocketGroup] +@@ -435,7 +440,7 @@ function CompareTabClass:InitControls() + self.controls.cmpMineCount.anchor.collapse = true + + -- Minion selector +- self.controls.cmpMinion = new("DropDownControl", {"LEFT", self.controls.cmpMineCount, "RIGHT"}, {6, 0, 140, 20}, {}, function(index, value) ++ self.controls.cmpMinion = new("DropDownControl"):DropDownControl({"LEFT", self.controls.cmpMineCount, "RIGHT"}, {6, 0, 140, 20}, {}, function(index, value) + local entry = self:GetActiveCompare() + if entry then + local mainSocketGroup = entry.skillsTab.socketGroupList[entry.mainSocketGroup] +@@ -460,7 +465,7 @@ function CompareTabClass:InitControls() + self.controls.cmpMinion.anchor.collapse = true + + -- Minion skill selector +- self.controls.cmpMinionSkill = new("DropDownControl", {"LEFT", self.controls.cmpMinion, "RIGHT"}, {4, 0, 140, 20}, {}, function(index, value) ++ self.controls.cmpMinionSkill = new("DropDownControl"):DropDownControl({"LEFT", self.controls.cmpMinion, "RIGHT"}, {4, 0, 140, 20}, {}, function(index, value) + local entry = self:GetActiveCompare() + if entry then + local mainSocketGroup = entry.skillsTab.socketGroupList[entry.mainSocketGroup] +@@ -582,14 +587,14 @@ function CompareTabClass:InitControls() + end) + self.controls.primCalcsMinionSkill.shown = false + +- self.controls.primCalcsMode = new("DropDownControl", nil, {0, 0, 120, 18}, calcsBuffModeDropList, function(index, value) ++ self.controls.primCalcsMode = new("DropDownControl"):DropDownControl(nil, {0, 0, 120, 18}, calcsBuffModeDropList, function(index, value) + self.primaryBuild.calcsTab.input.misc_buffMode = value.buffMode + self.primaryBuild.buildFlag = true + end) + self.controls.primCalcsMode.shown = false + + -- Compare build calcs skill controls +- self.controls.cmpCalcsSocketGroup = new("DropDownControl", nil, {0, 0, 200, 18}, {}, function(index, value) ++ self.controls.cmpCalcsSocketGroup = new("DropDownControl"):DropDownControl(nil, {0, 0, 200, 18}, {}, function(index, value) + local entry = self:GetActiveCompare() + if entry then + entry.calcsTab.input.skill_number = index +@@ -708,7 +713,7 @@ function CompareTabClass:InitControls() + end) + self.controls.cmpCalcsMinionSkill.shown = false + +- self.controls.cmpCalcsMode = new("DropDownControl", nil, {0, 0, 120, 18}, calcsBuffModeDropList, function(index, value) ++ self.controls.cmpCalcsMode = new("DropDownControl"):DropDownControl(nil, {0, 0, 120, 18}, calcsBuffModeDropList, function(index, value) + local entry = self:GetActiveCompare() + if entry then + entry.calcsTab.input.misc_buffMode = value.buffMode +@@ -1580,12 +1585,12 @@ function CompareTabClass:OpenImportFolderPopup() + end + + -- Search box and sort dropdown sit above the build list. +- controls.searchText = new("EditControl", {"TOPLEFT", nil, "TOPLEFT"}, {15, 25, 450, 20}, "", "Search", "%c%(%)", 100, function(buf) ++ controls.searchText = new("EditControl"):EditControl({"TOPLEFT", nil, "TOPLEFT"}, {15, 25, 450, 20}, "", "Search", "%c%(%)", 100, function(buf) + searchText = buf + listHost:FilterBuildList() + end, nil, nil, true) + controls.searchText:SetPlaceholder("(e.g. class:assassin myfilename)") +- controls.sort = new("DropDownControl", {"TOPLEFT", nil, "TOPLEFT"}, {475, 25, 210, 20}, buildListHelpers.buildSortDropList, function(index, value) ++ controls.sort = new("DropDownControl"):DropDownControl({"TOPLEFT", nil, "TOPLEFT"}, {475, 25, 210, 20}, buildListHelpers.buildSortDropList, function(index, value) + sortMode = value.sortMode + main.buildSortMode = value.sortMode + listHost:SortList() +@@ -2700,7 +2705,7 @@ function CompareTabClass:ComparePowerBuilder(compareEntry, powerStat, categories + local pSlot = self.primaryBuild.itemsTab and self.primaryBuild.itemsTab.slots[slotName] + local pItem = pSlot and self.primaryBuild.itemsTab.items[pSlot.selItemId] + if cItem and cItem.raw and not (pItem and pItem.name == cItem.name) then +- local newItem = new("Item", cItem.raw) ++ local newItem = new("Item"):Item(cItem.raw) + newItem:NormaliseQuality() + + -- if our comparison has abyssal jewels, but the primary build +@@ -2723,7 +2728,7 @@ function CompareTabClass:ComparePowerBuilder(compareEntry, powerStat, categories + -- might not exist + if cmpJewel then + -- copy item +- local itemCopy = new("Item", cmpJewel:BuildRaw()) ++ local itemCopy = new("Item"):Item(cmpJewel:BuildRaw()) + table.insert(cmpJewels, itemCopy) + self.primaryBuild.itemsTab:AddItem(itemCopy, false) + diff --git a/src/Classes/ConfigSetListControl.lua.rej b/src/Classes/ConfigSetListControl.lua.rej new file mode 100644 index 0000000000..a8b29b9be5 --- /dev/null +++ b/src/Classes/ConfigSetListControl.lua.rej @@ -0,0 +1,66 @@ +diff a/src/Classes/ConfigSetListControl.lua b/src/Classes/ConfigSetListControl.lua (rejected hunks) +@@ -7,10 +7,13 @@ local t_insert = table.insert + local t_remove = table.remove + local m_max = math.max + +-local ConfigSetListClass = newClass("ConfigSetListControl", "ListControl", function(self, anchor, rect, configTab) +- self.ListControl(anchor, rect, 16, "VERTICAL", true, configTab.configSetOrderList) ++---@class ConfigSetListControl: ListControl ++local ConfigSetListClass = newClass("ConfigSetListControl", "ListControl") ++ ++function ConfigSetListClass:ConfigSetListControl(anchor, rect, configTab) ++ self:ListControl(anchor, rect, 16, "VERTICAL", true, configTab.configSetOrderList) + self.configTab = configTab +- self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() ++ self.controls.copy = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() + local configSet = configTab.configSets[self.selValue] + local newConfigSet = copyTable(configSet) + newConfigSet.id = 1 +@@ -23,30 +26,31 @@ local ConfigSetListClass = newClass("ConfigSetListControl", "ListControl", funct + self.controls.copy.enabled = function() + return self.selValue ~= nil + end +- self.controls.delete = new("ButtonControl", {"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() ++ self.controls.delete = new("ButtonControl"):ButtonControl({"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() + self:OnSelDelete(self.selIndex, self.selValue) + end) + self.controls.delete.enabled = function() + return self.selValue ~= nil and #self.list > 1 + end +- self.controls.rename = new("ButtonControl", {"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() ++ self.controls.rename = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() + self:RenameSet(configTab.configSets[self.selValue]) + end) + self.controls.rename.enabled = function() + return self.selValue ~= nil + end +- self.controls.new = new("ButtonControl", {"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() ++ self.controls.new = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() + self:RenameSet(configTab:NewConfigSet(), true) + end) +-end) ++ return self ++end + + function ConfigSetListClass:RenameSet(configSet, addOnName) + local controls = { } +- controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter name for this config set:") +- controls.edit = new("EditControl", nil, {0, 40, 350, 20}, configSet.title, nil, nil, 100, function(buf) ++ controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter name for this config set:") ++ controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, configSet.title, nil, nil, 100, function(buf) + controls.save.enabled = buf:match("%S") + end) +- controls.save = new("ButtonControl", nil, {-45, 70, 80, 20}, "Save", function() ++ controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Save", function() + configSet.title = controls.edit.buf + self.configTab.modFlag = true + if addOnName then +@@ -59,7 +63,7 @@ function ConfigSetListClass:RenameSet(configSet, addOnName) + main:ClosePopup() + end) + controls.save.enabled = false +- controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() ++ controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() + if addOnName then + self.configTab.configSets[configSet.id] = nil + end diff --git a/src/Classes/ConfigTab.lua b/src/Classes/ConfigTab.lua index 83c649b476..87c8ec96c8 100644 --- a/src/Classes/ConfigTab.lua +++ b/src/Classes/ConfigTab.lua @@ -47,15 +47,15 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont self.controls.setSelect.enabled = function() return #self.configSetOrderList > 1 end - self.controls.setLabel = new("LabelControl", { "RIGHT", self.controls.setSelect, "LEFT" }, { -2, 0, 0, 16 }, "^7Config set:") - self.controls.setManage = new("ButtonControl", { "LEFT", self.controls.setSelect, "RIGHT" }, { 4, 0, 90, 20 }, "Manage...", function() + self.controls.setLabel = new("LabelControl"):LabelControl({ "RIGHT", self.controls.setSelect, "LEFT" }, { -2, 0, 0, 16 }, "^7Config set:") + self.controls.setManage = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.setSelect, "RIGHT" }, { 4, 0, 90, 20 }, "Manage...", function() self:OpenConfigSetManagePopup() end) - self.controls.search = new("EditControl", { "TOPLEFT", self.controls.sectionAnchor, "TOPLEFT" }, { 8, 15, 360, 20 }, "", "Search", "%c", 100, function() + self.controls.search = new("EditControl"):EditControl({ "TOPLEFT", self.controls.sectionAnchor, "TOPLEFT" }, { 8, 15, 360, 20 }, "", "Search", "%c", 100, function() self:UpdateControls() end, nil, nil, true) - self.controls.toggleConfigs = new("ButtonControl", { "LEFT", self.controls.search, "RIGHT" }, { 10, 0, 200, 20 }, function() + self.controls.toggleConfigs = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.search, "RIGHT" }, { 10, 0, 200, 20 }, function() -- dynamic text return self.toggleConfigs and "Hide Ineligible Configurations" or "Show All Configurations" end, function() @@ -141,7 +141,7 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont local lastSection for _, varData in ipairs(varList) do if varData.section then - lastSection = new("SectionControl", {"TOPLEFT",self.controls.search,"BOTTOMLEFT"}, {0, 0, 360, 0}, varData.section) + lastSection = new("SectionControl"):SectionControl({"TOPLEFT",self.controls.search,"BOTTOMLEFT"}, {0, 0, 360, 0}, varData.section) lastSection.varControlList = { } lastSection.col = varData.col lastSection.height = function(self) @@ -176,14 +176,14 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont self.build.buildFlag = true end) elseif varData.type == "list" then - control = new("DropDownControl", {"TOPLEFT",lastSection,"TOPLEFT"}, {234, 0, 118, 16}, varData.list, function(index, value) + control = new("DropDownControl"):DropDownControl({"TOPLEFT",lastSection,"TOPLEFT"}, {234, 0, 118, 16}, varData.list, function(index, value) self.configSets[self.activeConfigSetId].input[varData.var] = value.val self:AddUndoState() self:BuildModList() self.build.buildFlag = true end) elseif varData.type == "text" and not varData.resizable then - control = new("EditControl", {"TOPLEFT",lastSection,"TOPLEFT"}, {8, 0, 344, 118}, "", nil, "^%C\t\n", nil, function(buf, placeholder) + control = new("EditControl"):EditControl({"TOPLEFT",lastSection,"TOPLEFT"}, {8, 0, 344, 118}, "", nil, "^%C\t\n", nil, function(buf, placeholder) if placeholder then self.configSets[self.activeConfigSetId].placeholder[varData.var] = tostring(buf) else @@ -194,7 +194,7 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont self.build.buildFlag = true end, 16) elseif varData.type == "text" and varData.resizable then - control = new("ResizableEditControl", {"TOPLEFT",lastSection,"TOPLEFT"}, {8, 0, 344, 118, nil, nil, nil, 118 + 16 * 40}, "", nil, "^%C\t\n", nil, function(buf, placeholder) + control = new("ResizableEditControl"):ResizableEditControl({"TOPLEFT",lastSection,"TOPLEFT"}, {8, 0, 344, 118, nil, nil, nil, 118 + 16 * 40}, "", nil, "^%C\t\n", nil, function(buf, placeholder) if placeholder then self.configSets[self.activeConfigSetId].placeholder[varData.var] = tostring(buf) else @@ -205,7 +205,7 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont self.build.buildFlag = true end, 16) else - control = new("Control", {"TOPLEFT",lastSection,"TOPLEFT"}, {234, 0, 16, 16}) + control = new("Control"):Control({"TOPLEFT",lastSection,"TOPLEFT"}, {234, 0, 16, 16}) end if varData.inactiveText then @@ -549,7 +549,7 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont end local labelControl = control if varData.label and varData.type ~= "check" then - labelControl = new("LabelControl", {"RIGHT",control,"LEFT"}, {-4, 0, 0, DrawStringWidth(14, "VAR", varData.label) > 228 and 12 or 14}, "^7"..varData.label) + labelControl = new("LabelControl"):LabelControl({"RIGHT",control,"LEFT"}, {-4, 0, 0, DrawStringWidth(14, "VAR", varData.label) > 228 and 12 or 14}, "^7"..varData.label) t_insert(self.controls, labelControl) end if varData.var then @@ -880,9 +880,9 @@ function ConfigTabClass:UpdateLevel() end function ConfigTabClass:BuildModList() - local modList = new("ModList") + local modList = new("ModList"):ModList() self.modList = modList - local enemyModList = new("ModList") + local enemyModList = new("ModList"):ModList() self.enemyModList = enemyModList local input = self.configSets[self.activeConfigSetId].input local placeholder = self.configSets[self.activeConfigSetId].placeholder @@ -964,8 +964,8 @@ end function ConfigTabClass:OpenConfigSetManagePopup() main:OpenPopup(370, 290, "Manage Config Sets", { - new("ConfigSetListControl", nil, {0, 50, 350, 200}, self), - new("ButtonControl", nil, {0, 260, 90, 20}, "Done", function() + new("ConfigSetListControl"):ConfigSetListControl(nil, {0, 50, 350, 200}, self), + new("ButtonControl"):ButtonControl(nil, {0, 260, 90, 20}, "Done", function() main:ClosePopup() end), }) diff --git a/src/Classes/ConfigTab.lua.rej b/src/Classes/ConfigTab.lua.rej new file mode 100644 index 0000000000..c0a49e5894 --- /dev/null +++ b/src/Classes/ConfigTab.lua.rej @@ -0,0 +1,109 @@ +diff a/src/Classes/ConfigTab.lua b/src/Classes/ConfigTab.lua (rejected hunks) +@@ -15,15 +15,15 @@ local configVisibility = LoadModule("Modules/ConfigVisibility") + ---@class CustomModBlock: ControlHost, Control + local CustomModBlockClass = newClass("CustomModBlockControl", "ControlHost", "Control") + +-function CustomModBlockClass:CustomModBlockControl(self, anchor, rect, configTab, blockIndex, blockData) +- self.Control(anchor, rect) +- self.ControlHost() ++function CustomModBlockClass:CustomModBlockControl(anchor, rect, configTab, blockIndex, blockData) ++ self:Control(anchor, rect) ++ self:ControlHost() + + self.configTab = configTab + self.blockIndex = blockIndex + self.blockData = blockData + +- self.controls.deleteBtn = new("ButtonControl", {"TOPLEFT", self, "TOPLEFT"}, {0, 0, 20, 18}, "^1X", function() ++ self.controls.deleteBtn = new("ButtonControl"):ButtonControl({"TOPLEFT", self, "TOPLEFT"}, {0, 0, 20, 18}, "^1X", function() + local customModsList = configTab.configSets[configTab.activeConfigSetId].customModsList + table.remove(customModsList, blockIndex) + if #customModsList == 0 then +@@ -35,18 +35,18 @@ function CustomModBlockClass:CustomModBlockControl(self, anchor, rect, configTab + configTab.build.buildFlag = true + end) + +- self.controls.titleEdit = new("EditControl", {"LEFT", self.controls.deleteBtn, "RIGHT"}, {6, 0, 222, 18}, blockData.title or "", nil, nil, nil, function(buf) ++ self.controls.titleEdit = new("EditControl"):EditControl({"LEFT", self.controls.deleteBtn, "RIGHT"}, {6, 0, 222, 18}, blockData.title or "", nil, nil, nil, function(buf) + blockData.title = buf + configTab:AddUndoState() + configTab:BuildModList() + configTab.build.buildFlag = true + end) + +- self.controls.addModBtn = new("ButtonControl", {"LEFT", self.controls.titleEdit, "RIGHT"}, {6, 0, 58, 18}, "^7Add Mod", function() ++ self.controls.addModBtn = new("ButtonControl"):ButtonControl({"LEFT", self.controls.titleEdit, "RIGHT"}, {6, 0, 58, 18}, "^7Add Mod", function() + configTab:OpenAddModPopup(blockData) + end) + +- self.controls.enableCheck = new("CheckBoxControl", {"TOPRIGHT", self, "TOPRIGHT"}, {0, 0, 18}, "", function(state) ++ self.controls.enableCheck = new("CheckBoxControl"):CheckBoxControl({"TOPRIGHT", self, "TOPRIGHT"}, {0, 0, 18}, "", function(state) + blockData.enabled = state + configTab:AddUndoState() + configTab:BuildModList() +@@ -86,7 +86,8 @@ function CustomModBlockClass:CustomModBlockControl(self, anchor, rect, configTab + end + return inactiveText + end +-end) ++ return self ++end + + function CustomModBlockClass:GetSize() + local textHeight = self.controls.textEdit and self.controls.textEdit.height or 80 +@@ -779,7 +780,7 @@ function ConfigTabClass:ConfigTab(build) + end + self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({"TOPRIGHT",self,"TOPRIGHT"}, {0, 0, 18, 0}, 50, "VERTICAL", true) + if self.customSection then +- self.controls.customModsAddBlock = new("ButtonControl", {"TOPLEFT", self.customSection, "TOPLEFT"}, {8, 0, 120, 20}, "^7Add Mod Group", function() ++ self.controls.customModsAddBlock = new("ButtonControl"):ButtonControl({"TOPLEFT", self.customSection, "TOPLEFT"}, {8, 0, 120, 20}, "^7Add Mod Group", function() + local customModsList = self.configSets[self.activeConfigSetId].customModsList + t_insert(customModsList, { title = "Group " .. (#customModsList + 1), enabled = true, text = "" }) + self:UpdateCustomModsControls() +@@ -1276,7 +1277,7 @@ function ConfigTabClass:UpdateCustomModsControls() + self.customSection.varControlList = { self.controls.customModsAddBlock } + + for index, block in ipairs(configSet.customModsList) do +- local blockControl = new("CustomModBlockControl", {"TOPLEFT", self.customSection, "TOPLEFT"}, {8, 0, 344, 120}, self, index, block) ++ local blockControl = new("CustomModBlockControl"):CustomModBlockControl({"TOPLEFT", self.customSection, "TOPLEFT"}, {8, 0, 344, 120}, self, index, block) + t_insert(self.customModsBlockControls, blockControl) + t_insert(self.controls, blockControl) + t_insert(self.customSection.varControlList, blockControl) +@@ -1497,7 +1498,7 @@ function ConfigTabClass:OpenAddModPopup(blockData) + end + end + +- controls.listControl = new("ListControl", {"TOPLEFT", nil, "TOPLEFT"}, {10, 20, 700, 454}, 16, "VERTICAL", false, displayList) ++ controls.listControl = new("ListControl"):ListControl({"TOPLEFT", nil, "TOPLEFT"}, {10, 20, 700, 454}, 16, "VERTICAL", false, displayList) + controls.listControl.font = "VAR" + controls.listControl.GetRowValue = function(self, column, index, value) + return value or "" +@@ -1520,8 +1521,8 @@ function ConfigTabClass:OpenAddModPopup(blockData) + end + end + +- controls.searchLabel = new("LabelControl", {"TOPRIGHT", nil, "TOPLEFT"}, {65, 482, 0, 16}, "^7Search:") +- controls.search = new("EditControl", {"TOPLEFT", nil, "TOPLEFT"}, {70, 482, 640, 18}, "", nil, "%c", 100, function() ++ controls.searchLabel = new("LabelControl"):LabelControl({"TOPRIGHT", nil, "TOPLEFT"}, {65, 482, 0, 16}, "^7Search:") ++ controls.search = new("EditControl"):EditControl({"TOPLEFT", nil, "TOPLEFT"}, {70, 482, 640, 18}, "", nil, "%c", 100, function() + updateDisplayList() + end, nil, nil, true) + controls.search.controls.buttonClear.shown = function() +@@ -1530,7 +1531,7 @@ function ConfigTabClass:OpenAddModPopup(blockData) + + updateDisplayList() + +- controls.save = new("ButtonControl", nil, {-45, 512, 80, 20}, "Add", function() ++ controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 512, 80, 20}, "Add", function() + local selIndex = controls.listControl.selIndex or 1 + local selected = displayList[selIndex] + if selected and selected ~= "No matching modifiers found" then +@@ -1551,7 +1552,7 @@ function ConfigTabClass:OpenAddModPopup(blockData) + return selected ~= nil and selected ~= "No matching modifiers found" + end + +- controls.close = new("ButtonControl", nil, {45, 512, 80, 20}, "Cancel", function() ++ controls.close = new("ButtonControl"):ButtonControl(nil, {45, 512, 80, 20}, "Cancel", function() + main:ClosePopup() + end) + diff --git a/src/Classes/Control.lua b/src/Classes/Control.lua index 110eb6884e..d75ee730c5 100644 --- a/src/Classes/Control.lua +++ b/src/Classes/Control.lua @@ -6,6 +6,8 @@ local t_insert = table.insert local m_floor = math.floor + +---@enum (key) AnchorPoint local anchorPos = { ["TOPLEFT"] = { 0 , 0 }, ["TOP"] = { 0.5, 0 }, @@ -41,8 +43,14 @@ local ControlClass = newClass("Control", function(self, anchor, rect) if anchor then self:SetAnchor(anchor[1], anchor[2], anchor[3], nil, nil, anchor[4]) end -end) + return self +end + +---@generic T +---@alias Prop (fun(self: self): T) | T +---@param name string +---@return any value function ControlClass:GetProperty(name) if type(self[name]) == "function" then return self[name](self) diff --git a/src/Classes/Control.lua.rej b/src/Classes/Control.lua.rej new file mode 100644 index 0000000000..6ba4e94f9b --- /dev/null +++ b/src/Classes/Control.lua.rej @@ -0,0 +1,11 @@ +diff a/src/Classes/Control.lua b/src/Classes/Control.lua (rejected hunks) +@@ -38,6 +38,9 @@ local rect = { + ---@field enabled boolean | fun(...: any): boolean + ---@field onFocusGained? fun() + ---@field onFocusLost? fun() ++---@field shown Prop ++---@field x Prop? ++---@field y Prop? + local ControlClass = newClass("Control") + + ---@alias ControlAnchor [AnchorPoint, Control|ControlHost, AnchorPoint, boolean|nil] diff --git a/src/Classes/ControlHost.lua b/src/Classes/ControlHost.lua index 958447c512..592b71b016 100644 --- a/src/Classes/ControlHost.lua +++ b/src/Classes/ControlHost.lua @@ -4,9 +4,13 @@ -- Host for UI controls -- -local ControlHostClass = newClass("ControlHost", function(self) - self.controls = { } -end) +---@class ControlHost +local ControlHostClass = newClass("ControlHost") + +function ControlHostClass:ControlHost() + self.controls = {} + return self +end function ControlHostClass:SelectControl(newSelControl) if self.selControl == newSelControl then diff --git a/src/Classes/DraggerControl.lua b/src/Classes/DraggerControl.lua index de331cbb04..3aede08085 100644 --- a/src/Classes/DraggerControl.lua +++ b/src/Classes/DraggerControl.lua @@ -3,9 +3,12 @@ -- Class: Dragger Button Control -- Dragger button control. -- -local DraggerClass = newClass("DraggerControl", "Control", "TooltipHost", function(self, anchor, rect, label, onKeyDown, onKeyUp, onRightClick, onHover, forceTooltip) - self.Control(anchor, rect) - self.TooltipHost() +---@class DraggerControl: Control, TooltipHost +local DraggerClass = newClass("DraggerControl", "Control", "TooltipHost") + +function DraggerClass:DraggerControl(anchor, rect, label, onKeyDown, onKeyUp, onRightClick, onHover, forceTooltip) + self:Control(anchor, rect) + self:TooltipHost() self.label = label self.onKeyDown = onKeyDown self.onKeyUp = onKeyUp @@ -14,7 +17,8 @@ local DraggerClass = newClass("DraggerControl", "Control", "TooltipHost", functi self.forceTooltip = forceTooltip self.cursorX = 0 self.cursorY = 0 -end) + return self +end function DraggerClass:SetImage(path) if path then diff --git a/src/Classes/DropDownControl.lua b/src/Classes/DropDownControl.lua index cc7d47161f..9a38178e85 100644 --- a/src/Classes/DropDownControl.lua +++ b/src/Classes/DropDownControl.lua @@ -49,8 +49,9 @@ local DropDownClass = newClass("DropDownControl", "Control", "ControlHost", "Too self.enableDroppedWidth = false -- Set by the parent control. Activates the auto width of the box component. self.enableChangeBoxWidth = false - -- self.tag = "-" -end) + -- self.tag = "-" + return self +end -- maps the actual dropdown row index (after eventual filtering) to the original (unfiltered) list index function DropDownClass:DropIndexToListIndex(dropIndex) diff --git a/src/Classes/DropDownControl.lua.rej b/src/Classes/DropDownControl.lua.rej new file mode 100644 index 0000000000..01f02a4a4d --- /dev/null +++ b/src/Classes/DropDownControl.lua.rej @@ -0,0 +1,30 @@ +diff a/src/Classes/DropDownControl.lua b/src/Classes/DropDownControl.lua (rejected hunks) +@@ -8,11 +8,14 @@ local m_min = math.min + local m_max = math.max + local m_floor = math.floor + +-local DropDownClass = newClass("DropDownControl", "Control", "ControlHost", "TooltipHost", "SearchHost", function(self, anchor, rect, list, selFunc, tooltipText, ignoreSearchOrder) +- self.Control(anchor, rect) +- self.ControlHost() +- self.TooltipHost(tooltipText) +- self.SearchHost( ++---@class DropDownControl: Control, ControlHost, TooltipHost, SearchHost ++local DropDownClass = newClass("DropDownControl", "Control", "ControlHost", "TooltipHost", "SearchHost") ++ ++function DropDownClass:DropDownControl(anchor, rect, list, selFunc, tooltipText, ignoreSearchOrder) ++ self:Control(anchor, rect) ++ self:ControlHost() ++ self:TooltipHost(tooltipText) ++ self:SearchHost( + -- list to filter + function() + return self.list +@@ -31,7 +34,7 @@ local DropDownClass = newClass("DropDownControl", "Control", "ControlHost", "Too + end, + ignoreSearchOrder + ) +- self.controls.scrollBar = new("ScrollBarControl", {"TOPRIGHT",self,"TOPRIGHT"}, {-1, 0, 18, 0}, (self.height - 4) * 4) ++ self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({"TOPRIGHT",self,"TOPRIGHT"}, {-1, 0, 18, 0}, (self.height - 4) * 4) + self.controls.scrollBar.height = function() + return self.dropHeight + 2 + end diff --git a/src/Classes/EditControl.lua b/src/Classes/EditControl.lua index dd81738884..1024f53699 100644 --- a/src/Classes/EditControl.lua +++ b/src/Classes/EditControl.lua @@ -36,11 +36,15 @@ local function newlineCount(str) end end -local EditClass = newClass("EditControl", "ControlHost", "Control", "UndoHandler", "TooltipHost", function(self, anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) - self.ControlHost() - self.Control(anchor, rect) - self.UndoHandler() - self.TooltipHost() +---@class EditControl: ControlHost, Control, UndoHandler, TooltipHost +---@field inactiveText (fun(buf: string?): string)|string +local EditClass = newClass("EditControl", "ControlHost", "Control", "UndoHandler", "TooltipHost") + +function EditClass:EditControl(anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) + self:ControlHost() + self:Control(anchor, rect) + self:UndoHandler() + self:TooltipHost() self:SetText(init or "") self.prompt = prompt self.filter = filter or (main.unicode and "%c" or "^%w%p ") @@ -91,7 +95,8 @@ local EditClass = newClass("EditControl", "ControlHost", "Control", "UndoHandler self.controls.scrollBarV.shown = false end self.protected = false -end) + return self +end function EditClass:SetText(text, notify) self.buf = tostring(text) @@ -297,7 +302,8 @@ function EditClass:Draw(viewPort, noTooltip) else SetDrawColor(self.inactiveCol) if self.inactiveText then - local inactiveText = type(inactiveText) == "string" and self.inactiveText or self.inactiveText(self.buf) + local inactiveText = type(self.inactiveText) == "string" and self.inactiveText or self.inactiveText(self.buf) + ---@cast inactiveText string DrawString(-self.controls.scrollBarH.offset, -self.controls.scrollBarV.offset, "LEFT", textHeight, self.font, inactiveText) elseif self.protected then DrawString(-self.controls.scrollBarH.offset, -self.controls.scrollBarV.offset, "LEFT", textHeight, self.font, string.rep(protected_replace, #self.buf)) diff --git a/src/Classes/EditControl.lua.rej b/src/Classes/EditControl.lua.rej new file mode 100644 index 0000000000..d630cf5534 --- /dev/null +++ b/src/Classes/EditControl.lua.rej @@ -0,0 +1,31 @@ +diff a/src/Classes/EditControl.lua b/src/Classes/EditControl.lua (rejected hunks) +@@ -64,24 +68,24 @@ local EditClass = newClass("EditControl", "ControlHost", "Control", "UndoHandler + if self.filter == "%D" or self.filter == "^%-%d" then + -- Add +/- buttons for integer number edits + self.isNumeric = true +- self.controls.buttonDown = new("ButtonControl", {"RIGHT",self,"RIGHT"}, {-2, 0, buttonSize, buttonSize}, "-", function() ++ self.controls.buttonDown = new("ButtonControl"):ButtonControl({"RIGHT",self,"RIGHT"}, {-2, 0, buttonSize, buttonSize}, "-", function() + self:OnKeyUp("DOWN") + end) +- self.controls.buttonUp = new("ButtonControl", {"RIGHT",self.controls.buttonDown,"LEFT"}, {-1, 0, buttonSize, buttonSize}, "+", function() ++ self.controls.buttonUp = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.buttonDown,"LEFT"}, {-1, 0, buttonSize, buttonSize}, "+", function() + self:OnKeyUp("UP") + end) + elseif clearable then +- self.controls.buttonClear = new("ButtonControl", {"RIGHT",self,"RIGHT"}, {-2, 0, buttonSize, buttonSize}, "x", function() ++ self.controls.buttonClear = new("ButtonControl"):ButtonControl({"RIGHT",self,"RIGHT"}, {-2, 0, buttonSize, buttonSize}, "x", function() + self:SetText("", true) + end) + self.controls.buttonClear.shown = function() return #self.buf > 0 and self:IsMouseInBounds() end + end +- self.controls.scrollBarH = new("ScrollBarControl", {"BOTTOMLEFT",self,"BOTTOMLEFT"}, {1, -1, 0, 14}, 60, "HORIZONTAL", true) ++ self.controls.scrollBarH = new("ScrollBarControl"):ScrollBarControl({"BOTTOMLEFT",self,"BOTTOMLEFT"}, {1, -1, 0, 14}, 60, "HORIZONTAL", true) + self.controls.scrollBarH.width = function() + local width, height = self:GetSize() + return width - (self.controls.scrollBarV.enabled and 16 or 2) + end +- self.controls.scrollBarV = new("ScrollBarControl", {"TOPRIGHT",self,"TOPRIGHT"}, {-1, 1, 14, 0}, (lineHeight or 0) * 3, "VERTICAL", true) ++ self.controls.scrollBarV = new("ScrollBarControl"):ScrollBarControl({"TOPRIGHT",self,"TOPRIGHT"}, {-1, 1, 14, 0}, (lineHeight or 0) * 3, "VERTICAL", true) + self.controls.scrollBarV.height = function() + local width, height = self:GetSize() + return height - (self.controls.scrollBarH.enabled and 16 or 2) diff --git a/src/Classes/ExtBuildListControl.lua b/src/Classes/ExtBuildListControl.lua index fb6070ba69..c00323a3a2 100644 --- a/src/Classes/ExtBuildListControl.lua +++ b/src/Classes/ExtBuildListControl.lua @@ -10,36 +10,39 @@ local m_max = math.max local m_min = math.min local dkjson = require "dkjson" -local ExtBuildListControlClass = newClass("ExtBuildListControl", "ControlHost", "Control", - function(self, anchor, rect, providers) - self.Control(anchor, rect) - self.ControlHost() - self:SelectControl() - - self.rowHeight = 200 - self.scroll = "VERTICAL" - self.forceTooltip = false - self.font = "VAR" - self.importButtons = {} - self.previewButtons = {} - self.inTransition = false - self.contentHeight = 0 - self.tabs = {} - self.activeListProvider = nil - self.buildProviders = providers - self.buildProvidersList = {} - self.providerMaxLength = 150 - for _, provider in ipairs(self.buildProviders) do - self.providerMaxLength = m_max(self.providerMaxLength, DrawStringWidth(16, self.font, provider.name) + 30) - t_insert(self.buildProvidersList, provider.name) - end - end) +---@class ExtBuildListControl: ControlHost, Control +local ExtBuildListControlClass = newClass("ExtBuildListControl", "ControlHost", "Control") + +function ExtBuildListControlClass:ExtBuildListControl(anchor, rect, providers) + self:Control(anchor, rect) + self:ControlHost() + self:SelectControl() + + self.rowHeight = 200 + self.scroll = "VERTICAL" + self.forceTooltip = false + self.font = "VAR" + self.importButtons = {} + self.previewButtons = {} + self.inTransition = false + self.contentHeight = 0 + self.tabs = {} + self.activeListProvider = nil + self.buildProviders = providers + self.buildProvidersList = {} + self.providerMaxLength = 150 + for _, provider in ipairs(self.buildProviders) do + self.providerMaxLength = m_max(self.providerMaxLength, DrawStringWidth(16, self.font, provider.name) + 30) + t_insert(self.buildProvidersList, provider.name) + end + return self +end function ExtBuildListControlClass:Init(providerName) wipeTable(self.controls) wipeTable(self.tabs) - self.controls.sort = new("DropDownControl", { "TOP", self, "TOP" }, { 0, -20, self.providerMaxLength, 20 }, + self.controls.sort = new("DropDownControl"):DropDownControl({ "TOP", self, "TOP" }, { 0, -20, self.providerMaxLength, 20 }, self.buildProvidersList, function(index, value) self:Init(value) end) @@ -72,7 +75,7 @@ function ExtBuildListControlClass:Init(providerName) if lastControl then anchor = { "LEFT", lastControl, "RIGHT" } end - local button = new("ButtonControl", anchor, { 0, lastControl and 0 or -20, stringWidth + 10, 20 }, title, function() + local button = new("ButtonControl"):ButtonControl(anchor, { 0, lastControl and 0 or -20, stringWidth + 10, 20 }, title, function() if self.activeListProvider:GetActiveList() == title then return end @@ -105,7 +108,7 @@ function ExtBuildListControlClass:Init(providerName) return (self.width() - self.controls.sort.width()) / 2 end - self.controls.scrollBarV = new("ScrollBarControl", { "RIGHT", self, "RIGHT" }, { -1, 0, self.scroll and 16 or 0, 0 }, + self.controls.scrollBarV = new("ScrollBarControl"):ScrollBarControl({ "RIGHT", self, "RIGHT" }, { -1, 0, self.scroll and 16 or 0, 0 }, 80, "VERTICAL") { -- y = function() -- return (self.scrollH and -8 or 0) @@ -120,7 +123,7 @@ function ExtBuildListControlClass:Init(providerName) end if self.activeListProvider:GetPageUrl() then - self.controls.all = new("ButtonControl", { "BOTTOM", self, "BOTTOM" }, { 0, 1, self.width, 20 }, "See All", + self.controls.all = new("ButtonControl"):ButtonControl({ "BOTTOM", self, "BOTTOM" }, { 0, 1, self.width, 20 }, "See All", function() local url = self.activeListProvider:GetPageUrl() if url then @@ -407,14 +410,14 @@ function ExtBuildListControlClass:Draw(viewPort, noTooltip) local relativeHeight = currentHeight + 10 - self.controls.scrollBarV.offset if relativeHeight > y and relativeHeight < self.height() + y - 10 then if build.buildLink then - local importButton = new("ButtonControl", nil, { x, currentHeight - self.controls.scrollBarV.offset, 45, 20 }, "Import", function() + local importButton = new("ButtonControl"):ButtonControl(nil, { x, currentHeight - self.controls.scrollBarV.offset, 45, 20 }, "Import", function() self:importBuild(build) end) t_insert(self.controls, importButton) end if build.previewLink then - local previewButton = new("ButtonControl", nil, { x + 50, currentHeight - self.controls.scrollBarV.offset, 60, 20 }, "Preview", function() + local previewButton = new("ButtonControl"):ButtonControl(nil, { x + 50, currentHeight - self.controls.scrollBarV.offset, 60, 20 }, "Preview", function() OpenURL(build.previewLink) end) t_insert(self.controls, previewButton) diff --git a/src/Classes/ExtBuildListProvider.lua b/src/Classes/ExtBuildListProvider.lua index 2b0904ce86..546dc8b32c 100644 --- a/src/Classes/ExtBuildListProvider.lua +++ b/src/Classes/ExtBuildListProvider.lua @@ -10,14 +10,16 @@ -- .buildList [Needs to be filled in :GetBuilds with current list. buildName and buildLink fields are required.] -- .statusMsg [This can be used to print status message on the screen. Builds will not be listed if it has a value other than nil.] -local ExtBuildListProviderClass = newClass("ExtBuildListProvider", - function(self, listTitles) - self.listTitles = listTitles - self.buildList = {} - self.activeList = nil - self.statusMsg = nil - end -) +---@class ExtBuildListProvider +local ExtBuildListProviderClass = newClass("ExtBuildListProvider") + +function ExtBuildListProviderClass:ExtBuildListProvider(listTitles) + self.listTitles = listTitles + self.buildList = {} + self.activeList = nil + self.statusMsg = nil + return self +end function ExtBuildListProviderClass:GetPageUrl() return nil diff --git a/src/Classes/FolderListControl.lua b/src/Classes/FolderListControl.lua index ce4e6114b9..38d27a615e 100644 --- a/src/Classes/FolderListControl.lua +++ b/src/Classes/FolderListControl.lua @@ -21,7 +21,8 @@ local FolderListClass = newClass("FolderListControl", "ListControl", function(se end end) self:BuildList() -end) + return self +end function FolderListClass:SortList() if not self.list then return end diff --git a/src/Classes/FolderListControl.lua.rej b/src/Classes/FolderListControl.lua.rej new file mode 100644 index 0000000000..1950dd613b --- /dev/null +++ b/src/Classes/FolderListControl.lua.rej @@ -0,0 +1,21 @@ +diff a/src/Classes/FolderListControl.lua b/src/Classes/FolderListControl.lua (rejected hunks) +@@ -6,13 +6,16 @@ + local ipairs = ipairs + local t_insert = table.insert + +-local FolderListClass = newClass("FolderListControl", "ListControl", function(self, anchor, rect, subPath, onChange) +- self.ListControl(anchor, rect, 16, "VERTICAL", false, { }) ++---@class FolderListControl: ListControl ++local FolderListClass = newClass("FolderListControl", "ListControl") ++ ++function FolderListClass:FolderListControl(anchor, rect, subPath, onChange) ++ self:ListControl(anchor, rect, 16, "VERTICAL", false, { }) + self.subPath = subPath or "" + self.sortMode = "NAME" + self.onChangeCallback = onChange + +- self.controls.path = new("PathControl", {"BOTTOM",self,"TOP"}, {0, -2, self.width, 24}, main.buildPath, self.subPath, function(newSubPath) ++ self.controls.path = new("PathControl"):PathControl({"BOTTOM",self,"TOP"}, {0, -2, self.width, 24}, main.buildPath, self.subPath, function(newSubPath) + self.subPath = newSubPath + self:BuildList() + self.selIndex = nil diff --git a/src/Classes/GemSelectControl.lua.rej b/src/Classes/GemSelectControl.lua.rej new file mode 100644 index 0000000000..db31c90a24 --- /dev/null +++ b/src/Classes/GemSelectControl.lua.rej @@ -0,0 +1,34 @@ +diff a/src/Classes/GemSelectControl.lua b/src/Classes/GemSelectControl.lua (rejected hunks) +@@ -15,9 +15,19 @@ local gemTooltip = LoadModule("Classes/GemTooltip") + local toolTipText = "Prefix tag searches with a colon and exclude tags with a dash. e.g. :fire:lightning:-cold:area" + local imbuedTooltipText = "\"Socketed in\" item must be set in order to add an imbued support.\nOnly one imbued support is allowed per item." + +-local GemSelectClass = newClass("GemSelectControl", "EditControl", function(self, anchor, rect, skillsTab, index, changeFunc, forceTooltip, imbued) +- self.EditControl(anchor, rect, nil, nil, "^ %a':-") +- self.controls.scrollBar = new("ScrollBarControl", { "TOPRIGHT", self, "TOPRIGHT" }, {-1, 0, 18, 0}, (self.height - 4) * 4) ++---@class GemSelectControl: EditControl ++local GemSelectClass = newClass("GemSelectControl", "EditControl") ++ ++---@param anchor ControlAnchor ++---@param rect ControlRect ++---@param skillsTab SkillsTab ++---@param index integer ++---@param changeFunc fun(...) ++---@param forceTooltip boolean ++---@param imbued boolean ++function GemSelectClass:GemSelectControl(anchor, rect, skillsTab, index, changeFunc, forceTooltip, imbued) ++ self:EditControl(anchor, rect, nil, nil, "^ %a':-") ++ self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({ "TOPRIGHT", self, "TOPRIGHT" }, {-1, 0, 18, 0}, (self.height - 4) * 4) + self.controls.scrollBar.y = function() + local width, height = self:GetSize() + return height + 1 +@@ -54,7 +64,8 @@ local GemSelectClass = newClass("GemSelectControl", "EditControl", function(self + } + self.imbuedSelect = imbued + self.dpsBuildFlag = false +-end) ++ return self ++end + + function GemSelectClass:CalcOutputWithThisGem(calcFunc, gemData, useFullDPS) + local gemList = self.skillsTab.displayGroup.gemList diff --git a/src/Classes/ImportTab.lua b/src/Classes/ImportTab.lua index 0ca1eda976..1fd1a3dd74 100644 --- a/src/Classes/ImportTab.lua +++ b/src/Classes/ImportTab.lua @@ -160,12 +160,12 @@ local ImportTabClass = newClass("ImportTab", "ControlHost", "Control", function( end local exportWebsitesList = getExportSitesFromImportList() - self.controls.exportFrom = new("DropDownControl", { "LEFT", self.controls.generateCodeCopy,"RIGHT"}, {8, 0, 120, 20}, exportWebsitesList, function(_, selectedWebsite) + self.controls.exportFrom = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.generateCodeCopy, "RIGHT" }, { 8, 0, 120, 20 }, exportWebsitesList, function(_, selectedWebsite) main.lastExportWebsite = selectedWebsite.id self.exportWebsiteSelected = selectedWebsite.id end) self.controls.exportFrom:SelByValue(self.exportWebsiteSelected or main.lastExportWebsite or "Pastebin", "id") - self.controls.generateCodeByLink = new("ButtonControl", { "LEFT", self.controls.exportFrom, "RIGHT"}, {8, 0, 100, 20}, "Share", function() + self.controls.generateCodeByLink = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.exportFrom, "RIGHT" }, { 8, 0, 100, 20 }, "Share", function() local exportWebsite = exportWebsitesList[self.controls.exportFrom.selIndex] local subScriptId = buildSites.UploadBuild(self.controls.generateCodeOut.buf, exportWebsite) if subScriptId then @@ -197,8 +197,8 @@ local ImportTabClass = newClass("ImportTab", "ControlHost", "Control", function( end return #self.controls.generateCodeOut.buf > 0 end - self.controls.generateCodeNote = new("LabelControl", {"TOPLEFT",self.controls.generateCodeOut,"BOTTOMLEFT"}, {0, 4, 0, 14}, "^7Note: this code can be very long; you can use 'Share' to shrink it.") - self.controls.importCodeHeader = new("LabelControl", {"TOPLEFT",self.controls.generateCodeNote,"BOTTOMLEFT"}, {0, 26, 0, 16}, "^7To import a build, enter URL or code here:") + self.controls.generateCodeNote = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.generateCodeOut,"BOTTOMLEFT"}, {0, 4, 0, 14}, "^7Note: this code can be very long; you can use 'Share' to shrink it.") + self.controls.importCodeHeader = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.generateCodeNote,"BOTTOMLEFT"}, {0, 26, 0, 16}, "^7To import a build, enter URL or code here:") local importCodeHandle = function (buf) self.importCodeSite = nil @@ -296,21 +296,21 @@ local ImportTabClass = newClass("ImportTab", "ControlHost", "Control", function( end end - self.controls.importCodeIn = new("EditControl", {"TOPLEFT",self.controls.importCodeHeader,"BOTTOMLEFT"}, {0, 4, 328, 20}, "", nil, nil, nil, importCodeHandle, nil, nil, true) + self.controls.importCodeIn = new("EditControl"):EditControl({"TOPLEFT",self.controls.importCodeHeader,"BOTTOMLEFT"}, {0, 4, 328, 20}, "", nil, nil, nil, importCodeHandle, nil, nil, true) self.controls.importCodeIn.enterFunc = function() if self.importCodeValid then self.controls.importCodeGo.onClick() end end - self.controls.importCodeState = new("LabelControl", {"LEFT",self.controls.importCodeIn,"RIGHT"}, {8, 0, 0, 16}) + self.controls.importCodeState = new("LabelControl"):LabelControl({"LEFT",self.controls.importCodeIn,"RIGHT"}, {8, 0, 0, 16}) self.controls.importCodeState.label = function() return self.importCodeDetail or "" end - self.controls.importCodeMode = new("DropDownControl", {"TOPLEFT",self.controls.importCodeIn,"BOTTOMLEFT"}, {0, 4, 200, 20}, { "Import to this build", "Import to a new build", "Import as comparison" }) + self.controls.importCodeMode = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.importCodeIn,"BOTTOMLEFT"}, {0, 4, 200, 20}, { "Import to this build", "Import to a new build", "Import as comparison" }) self.controls.importCodeMode.enabled = function() return (self.build.dbFileName or self.controls.importCodeMode.selIndex == 3) and self.importCodeValid end - self.controls.importCodeGo = new("ButtonControl", {"LEFT",self.controls.importCodeMode,"RIGHT"}, {8, 0, 160, 20}, "Import", function() + self.controls.importCodeGo = new("ButtonControl"):ButtonControl({"LEFT",self.controls.importCodeMode,"RIGHT"}, {8, 0, 160, 20}, "Import", function() if self.importCodeSite and not self.importCodeXML then self.importCodeFetching = true local selectedWebsite = buildSites.websiteList[self.importCodeSite] @@ -1168,7 +1168,7 @@ function ImportTabClass:ImportItem(itemData, slotName) return end - local item = new("Item") + local item = new("Item"):Item() -- Determine rarity, display name and base type of the item item.rarity = rarityMap[itemData.frameType] diff --git a/src/Classes/ImportTab.lua.rej b/src/Classes/ImportTab.lua.rej new file mode 100644 index 0000000000..451f88a434 --- /dev/null +++ b/src/Classes/ImportTab.lua.rej @@ -0,0 +1,328 @@ +diff a/src/Classes/ImportTab.lua b/src/Classes/ImportTab.lua (rejected hunks) +@@ -76,19 +76,19 @@ local function addOAuthControls(self) + local rowSpacing = 6 + + +- self.controls.charImportStatusLabel = new("LabelControl", { "TOPLEFT", self.controls.sectionOauthCharImport, "TOPLEFT" }, ++ self.controls.charImportStatusLabel = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.sectionOauthCharImport, "TOPLEFT" }, + { labelSpacing, 14, 200, 16 }, function() + return "^7Character import status: " .. charImportStatus() + end) + +- self.controls.logoutApiButton = new("ButtonControl", { "TOPLEFT", self.controls.charImportStatusLabel, "TOPRIGHT" }, ++ self.controls.logoutApiButton = new("ButtonControl"):ButtonControl({ "TOPLEFT", self.controls.charImportStatusLabel, "TOPRIGHT" }, + { labelSpacing, 0, 170, 16 }, "^7Logout from Path of Exile API", function() + main.api:ResetDetails() + main:SaveSettings() + end) + self.controls.logoutApiButton.shown = function() return self.usingOauth and self.isAuthorized() end + +- self.controls.characterImportAnchor = new("Control", { "TOPLEFT", self.controls.sectionOauthCharImport, "TOPLEFT" }, ++ self.controls.characterImportAnchor = new("Control"):Control({ "TOPLEFT", self.controls.sectionOauthCharImport, "TOPLEFT" }, + { labelSpacing, 40, 200, 16 }) + self.controls.sectionOauthCharImport.height = function() + return self.isAuthorized() and 200 or 60 +@@ -160,7 +160,7 @@ local function addOAuthControls(self) + main.api:DownloadCharacterList(realm.realmCode, onResponse) + end + +- self.controls.authenticateButton = new("ButtonControl", { "TOPLEFT", self.controls.characterImportAnchor, "TOPLEFT" }, ++ self.controls.authenticateButton = new("ButtonControl"):ButtonControl({ "TOPLEFT", self.controls.characterImportAnchor, "TOPLEFT" }, + { 0, 0, 200, 16 }, "^7Authorize with Path of Exile", function() + main.api:FetchAuthToken(function(errCode) + if errCode then +@@ -182,20 +182,20 @@ local function addOAuthControls(self) + end + + -- Stage: select realm, league, character, and import data +- self.controls.charSelectHeader = new("LabelControl", { "TOPLEFT", self.controls.sectionOauthCharImport, "TOPLEFT" }, ++ self.controls.charSelectHeader = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.sectionOauthCharImport, "TOPLEFT" }, + { labelSpacing, 40, 200, 16 }, "^7Choose character to import data from:") + self.controls.charSelectHeader.shown = function() + return self.usingOauth and self.isAuthorized() + end + +- self.controls.oauthErrorLabel = new("LabelControl", { "TOPRIGHT", self.controls.sectionOauthCharImport, "TOPRIGHT" }, ++ self.controls.oauthErrorLabel = new("LabelControl"):LabelControl({ "TOPRIGHT", self.controls.sectionOauthCharImport, "TOPRIGHT" }, + { -8, 40, 0, 18 }) + self.controls.oauthErrorLabel.label = function() + local text = self.oauthErrCode and string.format("%sError: %s", colorCodes.NEGATIVE, self.oauthErrCode) or "" + return text + end + +- self.controls.accountRealm = new("DropDownControl", { "TOPLEFT", self.controls.charSelectHeader, "BOTTOMLEFT" }, ++ self.controls.accountRealm = new("DropDownControl"):DropDownControl({ "TOPLEFT", self.controls.charSelectHeader, "BOTTOMLEFT" }, + { 0, rowSpacing, 60, 20 }, realmList, function() + setLeaguesFromCharList() + end) +@@ -208,7 +208,7 @@ local function addOAuthControls(self) + end + return "Fetch Characters" + end +- self.controls.accountRealmFetchButton = new("ButtonControl", { "LEFT", self.controls.accountRealm, "RIGHT" }, ++ self.controls.accountRealmFetchButton = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.accountRealm, "RIGHT" }, + { labelSpacing, 0, 130, 20 }, fetchTextFunc, fetchCharacters) + self.controls.accountRealmFetchButton.enabled = fetchButtonEnabled + +@@ -223,12 +223,12 @@ local function addOAuthControls(self) + end + end + +- self.controls.charSelectLeagueLabel = new("LabelControl", { "TOPLEFT", self.controls.accountRealm, "BOTTOMLEFT" }, ++ self.controls.charSelectLeagueLabel = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.accountRealm, "BOTTOMLEFT" }, + { 0, rowSpacing, 0, 14 }, "^7League:") +- self.controls.charSelectLeague = new("DropDownControl", { "LEFT", self.controls.charSelectLeagueLabel, "RIGHT" }, ++ self.controls.charSelectLeague = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.charSelectLeagueLabel, "RIGHT" }, + { labelSpacing, 0, 150, 18 }, nil, onLeagueChange) + -- character select +- self.controls.charSelect = new("DropDownControl", { "TOPLEFT", self.controls.charSelectLeagueLabel, "BOTTOMLEFT" }, ++ self.controls.charSelect = new("DropDownControl"):DropDownControl({ "TOPLEFT", self.controls.charSelectLeagueLabel, "BOTTOMLEFT" }, + { 0, rowSpacing, 400, 18 }, nil) + self.controls.charSelect.enabled = function() + return self.usingOauth and self.isAuthorized() +@@ -243,9 +243,9 @@ local function addOAuthControls(self) + main.lastCharacterHash = common.sha1(charName) + self.lastCharacterHash = common.sha1(charName) + end +- self.controls.charImportHeader = new("LabelControl", { "TOPLEFT", self.controls.charSelect, "BOTTOMLEFT" }, ++ self.controls.charImportHeader = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.charSelect, "BOTTOMLEFT" }, + { 0, rowSpacing, 200, 16 }, "^7Import:") +- self.controls.charImportTree = new("ButtonControl", { "LEFT", self.controls.charImportHeader, "RIGHT" }, ++ self.controls.charImportTree = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.charImportHeader, "RIGHT" }, + { labelSpacing, 0, 170, 20 }, "Passive Tree and Jewels", function() + local realm = self.controls.accountRealm:GetSelValue() + local league = self.controls.charSelectLeague:GetSelValue() +@@ -280,9 +280,9 @@ local function addOAuthControls(self) + self.controls.charImportTree.enabled = function() + return self.usingOauth and self.isAuthorized() and self.controls.charSelect:GetSelValue() + end +- self.controls.charImportTreeClearJewels = new("CheckBoxControl", { "LEFT", self.controls.charImportTree, "RIGHT" }, ++ self.controls.charImportTreeClearJewels = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.charImportTree, "RIGHT" }, + { 90, 0, 18 }, "Delete jewels:", nil, "Delete all equipped jewels when importing.", true) +- self.controls.charImportItems = new("ButtonControl", { "TOPLEFT", self.controls.charImportTree, "BOTTOMLEFT" }, ++ self.controls.charImportItems = new("ButtonControl"):ButtonControl({ "TOPLEFT", self.controls.charImportTree, "BOTTOMLEFT" }, + { 0, rowSpacing, 110, 20 }, "Items and Skills", function() + local realm = self.controls.accountRealm:GetSelValue() + local league = self.controls.charSelectLeague:GetSelValue() +@@ -311,33 +311,32 @@ local function addOAuthControls(self) + self.controls.charImportItems.enabled = function() + return self.usingOauth and self.isAuthorized() and self.controls.charSelect:GetSelValue() + end +- self.controls.charImportItemsClearSkills = new("CheckBoxControl", { "LEFT", self.controls.charImportItems, "RIGHT" }, ++ self.controls.charImportItemsClearSkills = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.charImportItems, "RIGHT" }, + { 85, 0, 18 }, "Delete skills:", nil, "Delete all existing skills when importing.", true) +- self.controls.charImportItemsClearItems = new("CheckBoxControl", { "LEFT", self.controls.charImportItems, "RIGHT" }, ++ self.controls.charImportItemsClearItems = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.charImportItems, "RIGHT" }, + { 220, 0, 18 }, "Delete equipment:", nil, "Delete all equipped items when importing.", true) +- self.controls.charImportItemsIgnoreWeaponSwap = new("CheckBoxControl", { "LEFT", self.controls.charImportItems, ++ self.controls.charImportItemsIgnoreWeaponSwap = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.charImportItems, + "RIGHT" }, { 380, 0, 18 }, "Ignore weapon swap:", nil, "Ignore items and skills in weapon swap.", false) + end + local function addAccountNameControls(self) + self.charImportMode = "GETACCOUNTNAME" + self.charImportStatus = "Idle" +- self.controls.siteCharImportStatusLabel = new("LabelControl", { "TOPLEFT", self.controls.sectionCharSiteImport, "TOPLEFT" }, ++ self.controls.siteCharImportStatusLabel = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.sectionCharSiteImport, "TOPLEFT" }, + { 6, 14, 200, 16 }, function() + return "^7Character import status: " .. self.charImportStatus + end) + + -- Stage: input account name +- self.controls.siteAccountNameHeader = new("LabelControl", { "TOPLEFT", self.controls.sectionCharSiteImport, "TOPLEFT" }, ++ self.controls.siteAccountNameHeader = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.sectionCharSiteImport, "TOPLEFT" }, + { 6, 40, 250, 16 }, "^7To start importing a character, enter the character's account name:") + self.controls.siteAccountNameHeader.shown = function() + return self.charImportMode == "GETACCOUNTNAME" + end + +- self.controls.siteAccountRealm = new("DropDownControl", +- { "TOPLEFT", self.controls.siteAccountNameHeader, "BOTTOMLEFT" }, ++ self.controls.siteAccountRealm = new("DropDownControl"):DropDownControl({ "TOPLEFT", self.controls.siteAccountNameHeader, "BOTTOMLEFT" }, + { 0, 4, 60, 20 }, realmList) + self.controls.siteAccountRealm:SelByValue(main.lastRealm or "PC", "id") +- self.controls.siteAccountName = new("EditControl", { "LEFT", self.controls.siteAccountRealm, "RIGHT" }, { 8, 0, 200, 20 }, ++ self.controls.siteAccountName = new("EditControl"):EditControl({ "LEFT", self.controls.siteAccountRealm, "RIGHT" }, { 8, 0, 200, 20 }, + main.lastAccountName or "", nil, "%c", nil, nil, nil, nil, true) + self.controls.siteAccountName.pasteFilter = function(text) + return text:gsub(".", function(c) +@@ -360,7 +359,7 @@ local function addAccountNameControls(self) + return a:lower() < b:lower() + end) + end -- don't load the list many times +- self.controls.siteAccountNameGo = new("ButtonControl", { "LEFT", self.controls.siteAccountName, "RIGHT" }, { 8, 0, 60, 20 }, ++ self.controls.siteAccountNameGo = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.siteAccountName, "RIGHT" }, { 8, 0, 60, 20 }, + "Start", function() + local realm = self.controls.siteAccountRealm:GetSelValue() + self:DownloadSiteCharacterList(realm) +@@ -375,14 +374,14 @@ local function addAccountNameControls(self) + end + end + +- self.controls.siteAccountHistory = new("DropDownControl", { "LEFT", self.controls.siteAccountNameGo, "RIGHT" }, ++ self.controls.siteAccountHistory = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.siteAccountNameGo, "RIGHT" }, + { 8, 0, 200, 20 }, historyList, function() + self.controls.siteAccountName.buf = self.controls.siteAccountHistory.list[self.controls.siteAccountHistory.selIndex] + end) + self.controls.siteAccountHistory:SelByValue(main.lastAccountName) + self.controls.siteAccountHistory:CheckDroppedWidth(true) + +- self.controls.siteRemoveAccount = new("ButtonControl", { "LEFT", self.controls.siteAccountHistory, "RIGHT" }, { 8, 0, 20, 20 }, ++ self.controls.siteRemoveAccount = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.siteAccountHistory, "RIGHT" }, { 8, 0, 20, 20 }, + "X", function() + local accountName = self.controls.siteAccountHistory.list[self.controls.siteAccountHistory.selIndex] + if (accountName ~= nil) then +@@ -397,37 +396,36 @@ local function addAccountNameControls(self) + tooltip:AddLine(16, "^7Removes account from the dropdown list") + end + +- self.controls.siteAccountNameMissingDiscriminator = new("LabelControl", +- { "TOPLEFT", self.controls.siteAccountName, "BOTTOMLEFT" }, { 0, 8, 0, 16 }, "^1Missing discriminator e.g. #1234") ++ self.controls.siteAccountNameMissingDiscriminator = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.siteAccountName, "BOTTOMLEFT" }, { 0, 8, 0, 16 }, "^1Missing discriminator e.g. #1234") + self.controls.siteAccountNameMissingDiscriminator.shown = function() + return not self.controls.siteAccountName.buf:match("[#%-]%d%d%d%d$") and self.controls.siteAccountName.buf ~= "" + end + +- self.controls.siteAccountNameUnicode = new("LabelControl", { "TOPLEFT", self.controls.siteAccountRealm, "BOTTOMLEFT" }, ++ self.controls.siteAccountNameUnicode = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.siteAccountRealm, "BOTTOMLEFT" }, + { 0, 34, 0, 14 }, + "^7Note: if the account name contains non-ASCII characters it must be pasted into the textbox,\nnot typed manually.") + + -- Stage: select character and import data +- self.controls.siteCharSelectHeader = new("LabelControl", { "TOPLEFT", self.controls.sectionCharSiteImport, "TOPLEFT" }, ++ self.controls.siteCharSelectHeader = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.sectionCharSiteImport, "TOPLEFT" }, + { 6, 40, 200, 16 }, "^7Choose character to import data from:") + self.controls.siteCharSelectHeader.shown = function() + return self.charImportMode == "SELECTCHAR" or self.charImportMode == "IMPORTING" + end +- self.controls.siteCharSelectLeagueLabel = new("LabelControl", { "TOPLEFT", self.controls.siteCharSelectHeader, "BOTTOMLEFT" }, ++ self.controls.siteCharSelectLeagueLabel = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.siteCharSelectHeader, "BOTTOMLEFT" }, + { 0, 6, 0, 14 }, "^7League:") +- self.controls.siteCharSelectLeague = new("DropDownControl", { "LEFT", self.controls.siteCharSelectLeagueLabel, "RIGHT" }, ++ self.controls.siteCharSelectLeague = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.siteCharSelectLeagueLabel, "RIGHT" }, + { 4, 0, 150, 18 }, nil, function(index, value) + local realm = self.controls.siteAccountRealm:GetSelValue() + self:BuildCharacterList(realm.realmCode, value.league, self.lastCharList, self.controls.siteCharSelect) + end) +- self.controls.siteCharSelect = new("DropDownControl", { "TOPLEFT", self.controls.siteCharSelectHeader, "BOTTOMLEFT" }, ++ self.controls.siteCharSelect = new("DropDownControl"):DropDownControl({ "TOPLEFT", self.controls.siteCharSelectHeader, "BOTTOMLEFT" }, + { 0, 24, 400, 18 }) + self.controls.siteCharSelect.enabled = function() + return self.charImportMode == "SELECTCHAR" + end +- self.controls.siteCharImportHeader = new("LabelControl", { "TOPLEFT", self.controls.siteCharSelect, "BOTTOMLEFT" }, ++ self.controls.siteCharImportHeader = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.siteCharSelect, "BOTTOMLEFT" }, + { 0, 16, 200, 16 }, "^7Import:") +- self.controls.siteCharImportTree = new("ButtonControl", { "LEFT", self.controls.siteCharImportHeader, "RIGHT" }, ++ self.controls.siteCharImportTree = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.siteCharImportHeader, "RIGHT" }, + { 8, 0, 170, 20 }, "Passive Tree and Jewels", function() + local realm = self.controls.siteAccountRealm:GetSelValue() + if self.build.spec:CountAllocNodes() > 0 then +@@ -443,9 +441,9 @@ local function addAccountNameControls(self) + self.controls.siteCharImportTree.enabled = function() + return self.charImportMode == "SELECTCHAR" + end +- self.controls.siteCharImportTreeClearJewels = new("CheckBoxControl", { "LEFT", self.controls.siteCharImportTree, "RIGHT" }, ++ self.controls.siteCharImportTreeClearJewels = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.siteCharImportTree, "RIGHT" }, + { 90, 0, 18 }, "Delete jewels:", nil, "Delete all equipped jewels when importing.", true) +- self.controls.siteCharImportItems = new("ButtonControl", { "LEFT", self.controls.siteCharImportTree, "LEFT" }, ++ self.controls.siteCharImportItems = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.siteCharImportTree, "LEFT" }, + { 0, 36, 110, 20 }, "Items and Skills", function() + local realm = self.controls.siteAccountRealm:GetSelValue() + self:DownloadItems(realm) +@@ -454,64 +452,66 @@ local function addAccountNameControls(self) + self.controls.siteCharImportItems.enabled = function() + return self.charImportMode == "SELECTCHAR" + end +- self.controls.siteCharImportItemsClearSkills = new("CheckBoxControl", { "LEFT", self.controls.siteCharImportItems, "RIGHT" }, ++ self.controls.siteCharImportItemsClearSkills = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.siteCharImportItems, "RIGHT" }, + { 85, 0, 18 }, "Delete skills:", nil, "Delete all existing skills when importing.", true) +- self.controls.siteCharImportItemsClearItems = new("CheckBoxControl", { "LEFT", self.controls.siteCharImportItems, "RIGHT" }, ++ self.controls.siteCharImportItemsClearItems = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.siteCharImportItems, "RIGHT" }, + { 220, 0, 18 }, "Delete equipment:", nil, "Delete all equipped items when importing.", true) +- self.controls.siteCharImportItemsIgnoreWeaponSwap = new("CheckBoxControl", { "LEFT", self.controls.siteCharImportItems, ++ self.controls.siteCharImportItemsIgnoreWeaponSwap = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.siteCharImportItems, + "RIGHT" }, { 380, 0, 18 }, "Ignore weapon swap:", nil, "Ignore items and skills in weapon swap.", false) +- self.controls.siteCharBanditNote = new("LabelControl", { "TOPLEFT", self.controls.siteCharImportHeader, "BOTTOMLEFT" }, ++ self.controls.siteCharBanditNote = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.siteCharImportHeader, "BOTTOMLEFT" }, + { 0, 50, 200, 14 }, + "^7Tip: After you finish importing a character, make sure you update the bandit choice,\nas it can only be imported by logging in above.") + +- self.controls.siteCharClose = new("ButtonControl", { "TOPLEFT", self.controls.siteCharImportHeader, "BOTTOMLEFT" }, ++ self.controls.siteCharClose = new("ButtonControl"):ButtonControl({ "TOPLEFT", self.controls.siteCharImportHeader, "BOTTOMLEFT" }, + { 0, 90, 60, 20 }, "Close", function() + self.charImportMode = "GETACCOUNTNAME" + self.charImportStatus = "Idle" + end) + end + +-local ImportTabClass = newClass("ImportTab", "ControlHost", "Control", function(self, build) +- self.ControlHost() +- self.Control() ++---@class ImportTab: ControlHost, Control ++local ImportTabClass = newClass("ImportTab", "ControlHost", "Control") ++ ++---@param build Build ++function ImportTabClass:ImportTab(build) ++ self:ControlHost() ++ self:Control() + + self.build = build + + if not main.api then +- main.api = new("PoEAPI", main.lastToken, main.lastRefreshToken, main.tokenExpiry) ++ main.api = new("PoEAPI"):PoEAPI(main.lastToken, main.lastRefreshToken, main.tokenExpiry) + end + + +- self.controls.sectionOauthCharImport = new("SectionControl", { "TOPLEFT", self, "TOPLEFT" }, { 10, 18, 650, 200 }, ++ self.controls.sectionOauthCharImport = new("SectionControl"):SectionControl({ "TOPLEFT", self, "TOPLEFT" }, { 10, 18, 650, 200 }, + "Import From Your Account") + + addOAuthControls(self) + +- self.controls.sectionCharSiteImport = new("SectionControl", +- { "TOPLEFT", self.controls.sectionOauthCharImport, "BOTTOMLEFT" }, ++ self.controls.sectionCharSiteImport = new("SectionControl"):SectionControl({ "TOPLEFT", self.controls.sectionOauthCharImport, "BOTTOMLEFT" }, + { 0, 18, 650, 250 }, + "Import By Account Name") + addAccountNameControls(self) + + + -- Build import/export +- self.controls.sectionBuild = new("SectionControl", +- { "TOPLEFT", self.controls.sectionCharSiteImport, "BOTTOMLEFT", true }, ++ self.controls.sectionBuild = new("SectionControl"):SectionControl({ "TOPLEFT", self.controls.sectionCharSiteImport, "BOTTOMLEFT", true }, + { 0, 18, 650, 182 }, "Build Sharing") +- self.controls.generateCodeLabel = new("LabelControl", { "TOPLEFT", self.controls.sectionBuild, "TOPLEFT" }, ++ self.controls.generateCodeLabel = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.sectionBuild, "TOPLEFT" }, + { 6, 14, 0, 16 }, "^7Generate a code to share this build with other Path of Building users:") +- self.controls.generateCode = new("ButtonControl", {"LEFT",self.controls.generateCodeLabel,"RIGHT"}, {4, 0, 80, 20}, "Generate", function() ++ self.controls.generateCode = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.generateCodeLabel, "RIGHT" }, { 4, 0, 80, 20 }, "Generate", function() + self.controls.generateCodeOut:SetText(common.base64.encode(Deflate(self.build:SaveDB("code"))):gsub("+","-"):gsub("/","_")) + end) +- self.controls.enablePartyExportBuffs = new("CheckBoxControl", {"LEFT",self.controls.generateCode,"RIGHT"}, {100, 0, 18}, "Export Support", function(state) ++ self.controls.enablePartyExportBuffs = new("CheckBoxControl"):CheckBoxControl({"LEFT",self.controls.generateCode,"RIGHT"}, {100, 0, 18}, "Export Support", function(state) + self.build.partyTab.enableExportBuffs = state + self.build.buildFlag = true + end, "This is for party play, to export support character, it enables the exporting of auras, curses and modifiers to the enemy", false) +- self.controls.generateCodeOut = new("EditControl", {"TOPLEFT",self.controls.generateCodeLabel,"BOTTOMLEFT"}, {0, 8, 250, 20}, "", "Code", "%Z") ++ self.controls.generateCodeOut = new("EditControl"):EditControl({"TOPLEFT",self.controls.generateCodeLabel,"BOTTOMLEFT"}, {0, 8, 250, 20}, "", "Code", "%Z") + self.controls.generateCodeOut.enabled = function() + return #self.controls.generateCodeOut.buf > 0 + end +- self.controls.generateCodeCopy = new("ButtonControl", {"LEFT",self.controls.generateCodeOut,"RIGHT"}, {8, 0, 60, 20}, "Copy", function() ++ self.controls.generateCodeCopy = new("ButtonControl"):ButtonControl({"LEFT",self.controls.generateCodeOut,"RIGHT"}, {8, 0, 60, 20}, "Copy", function() + Copy(self.controls.generateCodeOut.buf) + self.controls.generateCodeOut:SetText("") + end) +@@ -726,8 +726,8 @@ local ImportTabClass = newClass("ImportTab", "ControlHost", "Control", function( + end + end) + end +- +-end) ++ return self ++end + + -- attempt to fetch the last realm's character list once per instance, if there + -- is a last realm saved diff --git a/src/Classes/Item.lua b/src/Classes/Item.lua index affafee709..708417861b 100644 --- a/src/Classes/Item.lua +++ b/src/Classes/Item.lua @@ -2117,7 +2117,7 @@ function ItemClass:BuildModList() if not self.base then return end - local baseList = new("ModList") + local baseList = new("ModList"):ModList() if self.base.weapon then self.weaponData = { } elseif self.base.armour then diff --git a/src/Classes/Item.lua.rej b/src/Classes/Item.lua.rej new file mode 100644 index 0000000000..57f8871ec2 --- /dev/null +++ b/src/Classes/Item.lua.rej @@ -0,0 +1,28 @@ +diff a/src/Classes/Item.lua b/src/Classes/Item.lua (rejected hunks) +@@ -88,11 +88,15 @@ end + + local influenceInfo = itemLib.influenceInfo.all + +-local ItemClass = newClass("Item", function(self, raw, rarity, highQuality) ++---@class Item ++local ItemClass = newClass("Item") ++ ++function ItemClass:Item(raw, rarity, highQuality) + if raw then + self:ParseRaw(sanitiseText(raw), rarity, highQuality) + end +-end) ++ return self ++end + + -- Reset all influence keys to false + function ItemClass:ResetInfluence() +@@ -2180,7 +2184,7 @@ function ItemClass:BuildModListForSlotNum(baseList, slotNum) + if slotNum ~= 1 then + slotName = slotName:gsub("1", tostring(slotNum)) + end +- local modList = new("ModList") ++ local modList = new("ModList"):ModList() + for _, baseMod in ipairs(baseList) do + local mod = copyTable(baseMod) + local add = true diff --git a/src/Classes/ItemDBControl.lua b/src/Classes/ItemDBControl.lua index 0e3c8231e9..72095c1fb8 100644 --- a/src/Classes/ItemDBControl.lua +++ b/src/Classes/ItemDBControl.lua @@ -10,8 +10,11 @@ local m_max = math.max local m_floor = math.floor -local ItemDBClass = newClass("ItemDBControl", "ListControl", function(self, anchor, rect, itemsTab, db, dbType) - self.ListControl(anchor, rect, 16, "VERTICAL", false) +---@class ItemDBControl: ListControl +local ItemDBClass = newClass("ItemDBControl", "ListControl") + +function ItemDBClass:ItemDBControl(anchor, rect, itemsTab, db, dbType) + self:ListControl(anchor, rect, 16, "VERTICAL", false) self.itemsTab = itemsTab self.db = db self.dbType = dbType @@ -333,7 +336,7 @@ end function ItemDBClass:OnSelClick(index, item, doubleClick) if IsKeyDown("CTRL") then -- Add item - local newItem = new("Item", item.raw) + local newItem = new("Item"):Item(item.raw) newItem:NormaliseQuality() self.itemsTab:AddItem(newItem, true) diff --git a/src/Classes/ItemDBControl.lua.rej b/src/Classes/ItemDBControl.lua.rej new file mode 100644 index 0000000000..d300657eb1 --- /dev/null +++ b/src/Classes/ItemDBControl.lua.rej @@ -0,0 +1,47 @@ +diff a/src/Classes/ItemDBControl.lua b/src/Classes/ItemDBControl.lua (rejected hunks) +@@ -28,35 +31,36 @@ local ItemDBClass = newClass("ItemDBControl", "ListControl", function(self, anch + self.typeList = { "Any type", "Armour", "Jewellery", "One Handed Melee", "Two Handed Melee" } + self.slotList = { "Any slot", "Weapon 1", "Weapon 2", "Helmet", "Body Armour", "Gloves", "Boots", "Amulet", "Ring", "Belt", "Jewel", "Flask", "Graft 1", "Graft 2" } + local baseY = dbType == "RARE" and -22 or -62 +- self.controls.slot = new("DropDownControl", {"BOTTOMLEFT",self,"TOPLEFT"}, {0, baseY, 179, 18}, self.slotList, function(index, value) ++ self.controls.slot = new("DropDownControl"):DropDownControl({"BOTTOMLEFT",self,"TOPLEFT"}, {0, baseY, 179, 18}, self.slotList, function(index, value) + self.listBuildFlag = true + end) +- self.controls.type = new("DropDownControl", {"LEFT",self.controls.slot,"RIGHT"}, {2, 0, 179, 18}, self.typeList, function(index, value) ++ self.controls.type = new("DropDownControl"):DropDownControl({"LEFT",self.controls.slot,"RIGHT"}, {2, 0, 179, 18}, self.typeList, function(index, value) + self.listBuildFlag = true + end) + if dbType == "UNIQUE" then +- self.controls.sort = new("DropDownControl", {"BOTTOMLEFT",self,"TOPLEFT"}, {0, baseY + 20, 179, 18}, self.sortDropList, function(index, value) ++ self.controls.sort = new("DropDownControl"):DropDownControl({"BOTTOMLEFT",self,"TOPLEFT"}, {0, baseY + 20, 179, 18}, self.sortDropList, function(index, value) + self:SetSortMode(value.sortMode) + end) +- self.controls.league = new("DropDownControl", {"LEFT",self.controls.sort,"RIGHT"}, {2, 0, 179, 18}, self.leagueList, function(index, value) ++ self.controls.league = new("DropDownControl"):DropDownControl({"LEFT",self.controls.sort,"RIGHT"}, {2, 0, 179, 18}, self.leagueList, function(index, value) + self.listBuildFlag = true + end) +- self.controls.requirement = new("DropDownControl", {"LEFT",self.controls.sort,"BOTTOMLEFT"}, {0, 11, 179, 18}, { "Any requirements", "Current level", "Current attributes", "Current useable" }, function(index, value) ++ self.controls.requirement = new("DropDownControl"):DropDownControl({"LEFT",self.controls.sort,"BOTTOMLEFT"}, {0, 11, 179, 18}, { "Any requirements", "Current level", "Current attributes", "Current useable" }, function(index, value) + self.listBuildFlag = true + end) +- self.controls.obtainable = new("DropDownControl", {"LEFT",self.controls.requirement,"RIGHT"}, {2, 0, 179, 18}, { "Obtainable", "Any source", "Unobtainable", "Vendor Recipe", "Upgraded", "Boss Item", "Corruption"}, function(index, value) ++ self.controls.obtainable = new("DropDownControl"):DropDownControl({"LEFT",self.controls.requirement,"RIGHT"}, {2, 0, 179, 18}, { "Obtainable", "Any source", "Unobtainable", "Vendor Recipe", "Upgraded", "Boss Item", "Corruption"}, function(index, value) + self.listBuildFlag = true + end) + end +- self.controls.search = new("EditControl", {"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 258, 18}, "", "Search", "%c", 100, function() ++ self.controls.search = new("EditControl"):EditControl({"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 258, 18}, "", "Search", "%c", 100, function() + self.listBuildFlag = true + end, nil, nil, true) +- self.controls.searchMode = new("DropDownControl", {"LEFT",self.controls.search,"RIGHT"}, {2, 0, 100, 18}, { "Anywhere", "Names", "Modifiers" }, function(index, value) ++ self.controls.searchMode = new("DropDownControl"):DropDownControl({"LEFT",self.controls.search,"RIGHT"}, {2, 0, 100, 18}, { "Anywhere", "Names", "Modifiers" }, function(index, value) + self.listBuildFlag = true + end) + self:BuildSortOrder() + self.listBuildFlag = true +-end) ++ return self ++end + + function ItemDBClass:LoadLeaguesAndTypes() + local leagueFlag = { } diff --git a/src/Classes/ItemListControl.lua b/src/Classes/ItemListControl.lua index ac03df2b1f..aaa03631da 100644 --- a/src/Classes/ItemListControl.lua +++ b/src/Classes/ItemListControl.lua @@ -146,7 +146,7 @@ end function ItemListClass:ReceiveDrag(type, value, source) if type == "Item" then - local newItem = new("Item", value.raw) + local newItem = new("Item"):Item(value.raw) newItem:NormaliseQuality() self.itemsTab:AddItem(newItem, true, self.selDragIndex) self.itemsTab:PopulateSlots() diff --git a/src/Classes/ItemListControl.lua.rej b/src/Classes/ItemListControl.lua.rej new file mode 100644 index 0000000000..e67ef7d28e --- /dev/null +++ b/src/Classes/ItemListControl.lua.rej @@ -0,0 +1,65 @@ +diff a/src/Classes/ItemListControl.lua b/src/Classes/ItemListControl.lua (rejected hunks) +@@ -7,20 +7,23 @@ local pairs = pairs + local ipairs = ipairs + local t_insert = table.insert + +-local ItemListClass = newClass("ItemListControl", "ListControl", function(self, anchor, rect, itemsTab, forceTooltip) +- self.ListControl(anchor, rect, 16, "VERTICAL", true, itemsTab.itemOrderList, forceTooltip) ++---@class ItemListControl: ListControl ++local ItemListClass = newClass("ItemListControl", "ListControl") ++ ++function ItemListClass:ItemListControl(anchor, rect, itemsTab, forceTooltip) ++ self:ListControl(anchor, rect, 16, "VERTICAL", true, itemsTab.itemOrderList, forceTooltip) + self.itemsTab = itemsTab + self.defaultText = "^x7F7F7FThis is the list of items that have been added to this build.\nYou can add items to this list by dragging them from\none of the other lists, or by clicking 'Add to build' when\nviewing an item." + self.dragTargetList = { } +- self.controls.loadoutFilter = new("DropDownControl", {"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 110, 18}, nil, function() ++ self.controls.loadoutFilter = new("DropDownControl"):DropDownControl({"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 110, 18}, nil, function() + self:UpdateList() + end) + self.controls.loadoutFilter.enableDroppedWidth = true +- self.controls.sort = new("ButtonControl", {"LEFT",self.controls.loadoutFilter,"RIGHT"}, {4, 0, 42, 18}, "Sort", function() ++ self.controls.sort = new("ButtonControl"):ButtonControl({"LEFT",self.controls.loadoutFilter,"RIGHT"}, {4, 0, 42, 18}, "Sort", function() + itemsTab:SortItemList() + self:UpdateList() + end) +- self.controls.deleteUnused = new("ButtonControl", {"LEFT",self.controls.sort,"RIGHT"}, {4, 0, 84, 18}, "Del Unused", function() ++ self.controls.deleteUnused = new("ButtonControl"):ButtonControl({"LEFT",self.controls.sort,"RIGHT"}, {4, 0, 84, 18}, "Del Unused", function() + local delList = {} + for _, itemId in pairs(itemsTab.itemOrderList) do + if not itemsTab:GetEquippedSlotForItem(itemsTab.items[itemId]) and not self:FindEquippedAbyssJewel(itemId, false) and not self:FindSocketedJewel(itemId, false) then +@@ -43,7 +46,7 @@ local ItemListClass = newClass("ItemListControl", "ListControl", function(self, + self.controls.deleteUnused.enabled = function() + return #self.list > 0 + end +- self.controls.deleteAll = new("ButtonControl", {"LEFT",self.controls.deleteUnused,"RIGHT"}, {4, 0, 58, 18}, "Del All", function() ++ self.controls.deleteAll = new("ButtonControl"):ButtonControl({"LEFT",self.controls.deleteUnused,"RIGHT"}, {4, 0, 58, 18}, "Del All", function() + main:OpenConfirmPopup("Delete All", "Are you sure you want to delete all items in this build?", "Delete", function() + for _, slot in pairs(itemsTab.slots) do + slot:SetSelItemId(0) +@@ -66,13 +69,14 @@ local ItemListClass = newClass("ItemListControl", "ListControl", function(self, + self.controls.deleteAll.enabled = function() + return #self.list > 0 + end +- self.controls.delete = new("ButtonControl", {"LEFT",self.controls.deleteAll,"RIGHT"}, {4, 0, 50, 18}, "Delete", function() ++ self.controls.delete = new("ButtonControl"):ButtonControl({"LEFT",self.controls.deleteAll,"RIGHT"}, {4, 0, 50, 18}, "Delete", function() + self:OnSelDelete(self.selIndex, self.selValue) + end) + self.controls.delete.enabled = function() + return self.selValue ~= nil + end +-end) ++ return self ++end + + function ItemListClass:UpdateLoadoutList() + local list = { "Any Loadout", "Current Loadout", "Unused Items" } +@@ -316,7 +320,7 @@ function ItemListClass:OnSelClick(index, itemId, doubleClick) + -- disallow dragging since if the cursor is outside the selection after + -- the second click, the item will be stuck onto the cursor + self.selDragging = false +- local newItem = new("Item", item:BuildRaw()) ++ local newItem = new("Item"):Item(item:BuildRaw()) + newItem.id = item.id + self.itemsTab:SetDisplayItem(newItem) + return false diff --git a/src/Classes/ItemSetListControl.lua.rej b/src/Classes/ItemSetListControl.lua.rej new file mode 100644 index 0000000000..105a44e247 --- /dev/null +++ b/src/Classes/ItemSetListControl.lua.rej @@ -0,0 +1,76 @@ +diff a/src/Classes/ItemSetListControl.lua b/src/Classes/ItemSetListControl.lua (rejected hunks) +@@ -8,10 +8,13 @@ local t_remove = table.remove + local m_max = math.max + local s_format = string.format + +-local ItemSetListClass = newClass("ItemSetListControl", "ListControl", function(self, anchor, rect, itemsTab) +- self.ListControl(anchor, rect, 16, "VERTICAL", true, itemsTab.itemSetOrderList) ++---@class ItemSetListControl: ListControl ++local ItemSetListClass = newClass("ItemSetListControl", "ListControl") ++ ++function ItemSetListClass:ItemSetListControl(anchor, rect, itemsTab) ++ self:ListControl(anchor, rect, 16, "VERTICAL", true, itemsTab.itemSetOrderList) + self.itemsTab = itemsTab +- self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() ++ self.controls.copy = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() + local newSet = copyTable(itemsTab.itemSets[self.selValue]) + newSet.id = 1 + while itemsTab.itemSets[newSet.id] do +@@ -23,31 +26,32 @@ local ItemSetListClass = newClass("ItemSetListControl", "ListControl", function( + self.controls.copy.enabled = function() + return self.selValue ~= nil + end +- self.controls.delete = new("ButtonControl", {"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() ++ self.controls.delete = new("ButtonControl"):ButtonControl({"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() + self:OnSelDelete(self.selIndex, self.selValue) + end) + self.controls.delete.enabled = function() + return self.selValue ~= nil and #self.list > 1 + end +- self.controls.rename = new("ButtonControl", {"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() ++ self.controls.rename = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() + self:RenameSet(itemsTab.itemSets[self.selValue]) + end) + self.controls.rename.enabled = function() + return self.selValue ~= nil + end +- self.controls.new = new("ButtonControl", {"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() ++ self.controls.new = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() + local newSet = itemsTab:NewItemSet() + self:RenameSet(newSet, true) + end) +-end) ++ return self ++end + + function ItemSetListClass:RenameSet(itemSet, addOnName) + local controls = { } +- controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter name for this item set:") +- controls.edit = new("EditControl", nil, {0, 40, 350, 20}, itemSet.title, nil, nil, 100, function(buf) ++ controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter name for this item set:") ++ controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, itemSet.title, nil, nil, 100, function(buf) + controls.save.enabled = buf:match("%S") + end) +- controls.save = new("ButtonControl", nil, {-45, 70, 80, 20}, "Save", function() ++ controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Save", function() + itemSet.title = controls.edit.buf + self.itemsTab.modFlag = true + if addOnName then +@@ -60,7 +64,7 @@ function ItemSetListClass:RenameSet(itemSet, addOnName) + main:ClosePopup() + end) + controls.save.enabled = false +- controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() ++ controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() + if addOnName then + self.itemsTab.itemSets[itemSet.id] = nil + end +@@ -95,7 +99,7 @@ function ItemSetListClass:ReceiveDrag(type, value, source) + local itemSet = self.itemsTab:NewItemSet() + itemSet.title = value.title + for slotName, item in pairs(value.slots) do +- local newItem = new("Item", item.raw) ++ local newItem = new("Item"):Item(item.raw) + newItem:NormaliseQuality() + self.itemsTab:AddItem(newItem, true) + itemSet[slotName].selItemId = newItem.id diff --git a/src/Classes/ItemSlotControl.lua b/src/Classes/ItemSlotControl.lua index c8ca3e3338..261f049bb1 100644 --- a/src/Classes/ItemSlotControl.lua +++ b/src/Classes/ItemSlotControl.lua @@ -8,8 +8,11 @@ local t_insert = table.insert local m_min = math.min local itemSlotHelper = LoadModule("Modules/ItemSlotHelper") -local ItemSlotClass = newClass("ItemSlotControl", "DropDownControl", function(self, anchor, x, y, itemsTab, slotName, slotLabel, nodeId) - self.DropDownControl(anchor, {x, y, 310, 20}, { }, function(index, value) +---@class ItemSlotControl +local ItemSlotClass = newClass("ItemSlotControl", "DropDownControl") + +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 self:SetSelItemId(self.items[index]) itemsTab:PopulateSlots() @@ -30,7 +33,7 @@ local ItemSlotClass = newClass("ItemSlotControl", "DropDownControl", function(se self.slotName = slotName self.slotNum = tonumber(slotName:match("%d+$") or slotName:match("%d+")) if slotName:match("Flask") then - self.controls.activate = new("CheckBoxControl", {"RIGHT",self,"LEFT"}, {-2, 0, 20}, nil, function(state) + self.controls.activate = new("CheckBoxControl"):CheckBoxControl({"RIGHT",self,"LEFT"}, {-2, 0, 20}, nil, function(state) self.active = state itemsTab.activeItemSet[self.slotName].active = state itemsTab:AddUndoState() @@ -69,7 +72,8 @@ local ItemSlotClass = newClass("ItemSlotControl", "DropDownControl", function(se end self.label = slotLabel or slotName self.nodeId = nodeId -end) + return self +end function ItemSlotClass:SetSelItemId(selItemId) if self.nodeId then @@ -123,7 +127,7 @@ function ItemSlotClass:ReceiveDrag(type, value, source) if value.id and self.itemsTab.items[value.id] then self:SetSelItemId(value.id) else - local newItem = new("Item", value.raw) + local newItem = new("Item"):Item(value.raw) newItem:NormaliseQuality() self.itemsTab:AddItem(newItem, true) self:SetSelItemId(newItem.id) diff --git a/src/Classes/ItemsTab.lua b/src/Classes/ItemsTab.lua index 797acf629c..179d13bdf6 100644 --- a/src/Classes/ItemsTab.lua +++ b/src/Classes/ItemsTab.lua @@ -161,10 +161,10 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro self.showStatDifferences = true -- PoB Trader class initialization - self.tradeQuery = new("TradeQuery", self) + self.tradeQuery = new("TradeQuery"):TradeQuery(self) -- Set selector - self.controls.setSelect = new("DropDownControl", {"TOPLEFT",self,"TOPLEFT"}, {96, 8, 216, 20}, nil, function(index, value) + self.controls.setSelect = new("DropDownControl"):DropDownControl({"TOPLEFT",self,"TOPLEFT"}, {96, 8, 216, 20}, nil, function(index, value) self:SetActiveItemSet(self.itemSetOrderList[index]) self:AddUndoState() end) @@ -178,13 +178,13 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro self:AddItemSetTooltip(tooltip, self.itemSets[self.itemSetOrderList[index]]) end end - self.controls.setLabel = new("LabelControl", {"RIGHT",self.controls.setSelect,"LEFT"}, {-2, 0, 0, 16}, "^7Item set:") - self.controls.setManage = new("ButtonControl", {"LEFT",self.controls.setSelect,"RIGHT"}, {4, 0, 90, 20}, "Manage...", function() + self.controls.setLabel = new("LabelControl"):LabelControl({"RIGHT",self.controls.setSelect,"LEFT"}, {-2, 0, 0, 16}, "^7Item set:") + self.controls.setManage = new("ButtonControl"):ButtonControl({"LEFT",self.controls.setSelect,"RIGHT"}, {4, 0, 90, 20}, "Manage...", function() self:OpenItemSetManagePopup() end) -- Price Items - self.controls.priceDisplayItem = new("ButtonControl", {"TOPLEFT",self,"TOPLEFT"}, {96, 32, 310, 20}, "Trade for these items", function() + self.controls.priceDisplayItem = new("ButtonControl"):ButtonControl({"TOPLEFT",self,"TOPLEFT"}, {96, 32, 310, 20}, "Trade for these items", function() self.tradeQuery:PriceItem() end) self.controls.priceDisplayItem.tooltipFunc = function(tooltip) @@ -258,7 +258,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro end -- Passive tree dropdown controls - self.controls.specSelect = new("DropDownControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, {0, 8, 216, 20}, nil, function(index, value) + self.controls.specSelect = new("DropDownControl"):DropDownControl({"TOPLEFT",prevSlot,"BOTTOMLEFT"}, {0, 8, 216, 20}, nil, function(index, value) if self.build.treeTab.specList[index] then self.build.modFlag = true self.build.treeTab:SetActiveSpec(index) @@ -268,10 +268,10 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro return #self.controls.specSelect.list > 1 end prevSlot = self.controls.specSelect - self.controls.specButton = new("ButtonControl", {"LEFT",prevSlot,"RIGHT"}, {4, 0, 90, 20}, "Manage...", function() + self.controls.specButton = new("ButtonControl"):ButtonControl({"LEFT",prevSlot,"RIGHT"}, {4, 0, 90, 20}, "Manage...", function() self.build.treeTab:OpenSpecManagePopup() end) - self.controls.specLabel = new("LabelControl", {"RIGHT",prevSlot,"LEFT"}, {-2, 0, 0, 16}, "^7Passive tree:") + self.controls.specLabel = new("LabelControl"):LabelControl({"RIGHT",prevSlot,"LEFT"}, {-2, 0, 0, 16}, "^7Passive tree:") self.sockets = { } local socketOrder = { } @@ -284,12 +284,12 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro return a.id < b.id end) for _, node in ipairs(socketOrder) do - local socketControl = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, "Jewel "..node.id, "Socket", node.id) + local socketControl = new("ItemSlotControl"):ItemSlotControl({"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, "Jewel "..node.id, "Socket", node.id) self.sockets[node.id] = socketControl addSlot(socketControl) end - self.controls.slotHeader = new("LabelControl", {"BOTTOMLEFT",self.slotAnchor,"TOPLEFT"}, {0, -4, 0, 16}, "^7Equipped items:") - self.controls.weaponSwap1 = new("ButtonControl", {"BOTTOMRIGHT",self.slotAnchor,"TOPRIGHT"}, {-20, -2, 18, 18}, "I", function() + self.controls.slotHeader = new("LabelControl"):LabelControl({"BOTTOMLEFT",self.slotAnchor,"TOPLEFT"}, {0, -4, 0, 16}, "^7Equipped items:") + self.controls.weaponSwap1 = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self.slotAnchor,"TOPRIGHT"}, {-20, -2, 18, 18}, "I", function() if self.activeItemSet.useSecondWeaponSet then self.activeItemSet.useSecondWeaponSet = false self:AddUndoState() @@ -309,7 +309,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro self.controls.weaponSwap1.locked = function() return not self.activeItemSet.useSecondWeaponSet end - self.controls.weaponSwap2 = new("ButtonControl", {"BOTTOMRIGHT",self.slotAnchor,"TOPRIGHT"}, {0, -2, 18, 18}, "II", function() + self.controls.weaponSwap2 = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self.slotAnchor,"TOPRIGHT"}, {0, -2, 18, 18}, "II", function() if not self.activeItemSet.useSecondWeaponSet then self.activeItemSet.useSecondWeaponSet = true self:AddUndoState() @@ -398,30 +398,29 @@ drag it onto the slot. This will also add it to your build if it's from the unique/template list. If there's 2 slots an item can go in, holding Shift will put it in the second.]]) - self.controls.sharedItemList = new("SharedItemListControl", {"TOPLEFT",self.controls.craftDisplayItem, "BOTTOMLEFT"}, {0, 232, 340, 308}, self, true) + self.controls.sharedItemList = new("SharedItemListControl"):SharedItemListControl({"TOPLEFT",self.controls.craftDisplayItem, "BOTTOMLEFT"}, {0, 232, 340, 308}, self, true) -- Display item - self.displayItemTooltip = new("Tooltip") + self.displayItemTooltip = new("Tooltip"):Tooltip() self.displayItemTooltip.maxWidth = 458 - self.anchorDisplayItem = new("Control", {"TOPLEFT",main.portraitMode and self.controls.setManage or self.controls.itemList,"TOPRIGHT"}, {20, main.portraitMode and 0 or -20, 0, 0}) + self.anchorDisplayItem = new("Control"):Control({"TOPLEFT",main.portraitMode and self.controls.setManage or self.controls.itemList,"TOPRIGHT"}, {20, main.portraitMode and 0 or -20, 0, 0}) self.anchorDisplayItem.shown = function() return self.displayItem ~= nil end - self.controls.addDisplayItem = new("ButtonControl", {"TOPLEFT",self.anchorDisplayItem,"TOPLEFT"}, {0, 0, 100, 20}, "", function() + self.controls.addDisplayItem = new("ButtonControl"):ButtonControl({"TOPLEFT",self.anchorDisplayItem,"TOPLEFT"}, {0, 0, 100, 20}, "", function() self:AddDisplayItem() end) self.controls.addDisplayItem.label = function() return self.items[self.displayItem.id] and "Save" or "Add to build" end - self.controls.editDisplayItem = new("ButtonControl", {"LEFT",self.controls.addDisplayItem,"RIGHT"}, {8, 0, 60, 20}, "Edit...", function() + self.controls.editDisplayItem = new("ButtonControl"):ButtonControl({"LEFT",self.controls.addDisplayItem,"RIGHT"}, {8, 0, 60, 20}, "Edit...", function() self:EditDisplayItemText() end) - self.controls.removeDisplayItem = new("ButtonControl", {"LEFT",self.controls.editDisplayItem,"RIGHT"}, {8, 0, 60, 20}, "Cancel", function() + self.controls.removeDisplayItem = new("ButtonControl"):ButtonControl({"LEFT",self.controls.editDisplayItem,"RIGHT"}, {8, 0, 60, 20}, "Cancel", function() self:SetDisplayItem() end) - self.controls.displayItemBuySimilar = new("ButtonControl", - { "LEFT", self.controls.removeDisplayItem, "RIGHT", true }, + self.controls.displayItemBuySimilar = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.removeDisplayItem, "RIGHT", true }, { 8, 0, 100, 20 }, "Buy similar", function() local itemSlot = self:GetComparisonSlotNameForItem(self.displayItem) buySimilar.openPopup(self.displayItem, itemSlot, self.build) @@ -660,10 +659,10 @@ holding Shift will put it in the second.]]) end -- Section: Cluster Jewel - self.controls.displayItemSectionClusterJewel = new("Control", {"TOPLEFT",self.controls.displayItemSectionCatalyst,"BOTTOMLEFT"}, {0, 0, 0, function() + self.controls.displayItemSectionClusterJewel = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionCatalyst,"BOTTOMLEFT"}, {0, 0, 0, function() return self.controls.displayItemClusterJewelSkill:IsShown() and 52 or 0 end}) - self.controls.displayItemClusterJewelSkill = new("DropDownControl", {"TOPLEFT",self.controls.displayItemSectionClusterJewel,"TOPLEFT"}, {0, 0, 300, 20}, { }, function(index, value) + self.controls.displayItemClusterJewelSkill = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemSectionClusterJewel,"TOPLEFT"}, {0, 0, 300, 20}, { }, function(index, value) self.displayItem.clusterJewelSkill = value.skillId self:CraftClusterJewel() end) { @@ -923,7 +922,7 @@ holding Shift will put it in the second.]]) drop.shown = function() return self.displayItem and self.displayItem.crafted and i <= self.displayItem.affixLimit end - slider = new("SliderControl", {"TOPLEFT",drop,"BOTTOMLEFT"}, {0, 2, 300, 16}, function(val) + slider = new("SliderControl"):SliderControl({"TOPLEFT",drop,"BOTTOMLEFT"}, {0, 2, 300, 16}, function(val) local affix = self.displayItem[drop.outputTable][drop.outputIndex] local index, range = slider:GetDivVal() affix.modId = drop.list[drop.selIndex].modList[index] @@ -1073,7 +1072,8 @@ holding Shift will put it in the second.]]) self:PopulateSlots() self.lastSlot = self.slots[baseSlots[#baseSlots]] -end) + return self +end function ItemsTabClass:Load(xml, dbFileName) self.activeItemSetId = 0 @@ -1082,7 +1082,7 @@ function ItemsTabClass:Load(xml, dbFileName) self.tradeQuery.statSortSelectionList = { } for _, node in ipairs(xml) do if node.elem == "Item" then - local item = new("Item", "") + local item = new("Item"):Item("") item.id = tonumber(node.attrib.id) item.variant = tonumber(node.attrib.variant) if node.attrib.variantAlt then @@ -1515,7 +1515,7 @@ function ItemsTabClass:EquipItemInSet(item, itemSetId) slotName = slotName .. " Swap" end if not item.id or not self.items[item.id] then - item = new("Item", item.raw) + item = new("Item"):Item(item.raw) self:AddItem(item, true) end local altSlot = slotName:gsub("1","2") @@ -2163,9 +2163,9 @@ function ItemsTabClass:UpdateCustomControls() local line = itemLib.formatModLine(modLine) if line then if not self.controls["displayItemCustomModifierRemove"..i] then - self.controls["displayItemCustomModifierRemove"..i] = new("ButtonControl", {"TOPLEFT",self.controls.displayItemSectionCustom,"TOPLEFT"}, {0, i * 22 + 4, 70, 20}, "^7Remove") - self.controls["displayItemCustomModifier"..i] = new("LabelControl", {"LEFT",self.controls["displayItemCustomModifierRemove"..i],"RIGHT"}, {65, 0, 0, 16}) - self.controls["displayItemCustomModifierLabel"..i] = new("LabelControl", {"LEFT",self.controls["displayItemCustomModifierRemove"..i],"RIGHT"}, {5, 0, 0, 16}) + self.controls["displayItemCustomModifierRemove"..i] = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemSectionCustom,"TOPLEFT"}, {0, i * 22 + 4, 70, 20}, "^7Remove") + self.controls["displayItemCustomModifier"..i] = new("LabelControl"):LabelControl({"LEFT",self.controls["displayItemCustomModifierRemove"..i],"RIGHT"}, {65, 0, 0, 16}) + self.controls["displayItemCustomModifierLabel"..i] = new("LabelControl"):LabelControl({"LEFT",self.controls["displayItemCustomModifierRemove"..i],"RIGHT"}, {5, 0, 0, 16}) end self.controls["displayItemCustomModifierRemove"..i].shown = true local label = itemLib.formatModLine(modLine) @@ -2383,11 +2383,11 @@ end -- Opens the item set manager function ItemsTabClass:OpenItemSetManagePopup() local controls = { } - controls.setList = new("ItemSetListControl", nil, {-155, 50, 300, 200}, self) - controls.sharedList = new("SharedItemSetListControl", nil, {155, 50, 300, 200}, self) + controls.setList = new("ItemSetListControl"):ItemSetListControl(nil, {-155, 50, 300, 200}, self) + controls.sharedList = new("SharedItemSetListControl"):SharedItemSetListControl(nil, {155, 50, 300, 200}, self) controls.setList.dragTargetList = { controls.sharedList } controls.sharedList.dragTargetList = { controls.setList } - controls.close = new("ButtonControl", nil, {0, 260, 90, 20}, "Done", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {0, 260, 90, 20}, "Done", function() main:ClosePopup() end) main:OpenPopup(630, 290, "Manage Item Sets", controls) @@ -2397,7 +2397,7 @@ end function ItemsTabClass:CraftItem() local controls = { } local function makeItem(base) - local item = new("Item") + local item = new("Item"):Item() item.name = base.name item.base = base.base item.baseName = base.name @@ -2485,7 +2485,7 @@ function ItemsTabClass:CraftItem() self:AddItemTooltip(tooltip, makeItem(value), nil, true) end end - controls.save = new("ButtonControl", nil, {-45, 100, 80, 20}, "Create", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 100, 80, 20}, "Create", function() main:ClosePopup() local item = makeItem(controls.base.list[controls.base.selIndex]) self:SetDisplayItem(item) @@ -2496,7 +2496,7 @@ function ItemsTabClass:CraftItem() self.lastCraftTypeSel = controls.type.selIndex self.lastCraftBaseSel = controls.base.selIndex end) - controls.cancel = new("ButtonControl", nil, {45, 100, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 100, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(370, 130, "Craft Item", controls) @@ -2513,8 +2513,8 @@ function ItemsTabClass:EditDisplayItemText(alsoAddItem) return "Rarity: "..controls.rarity.list[controls.rarity.selIndex].rarity.."\n"..controls.edit.buf end end - controls.rarity = new("DropDownControl", nil, {-190, 10, 100, 18}, rarityDropList) - controls.edit = new("EditControl", nil, {0, 40, 480, 420}, "", nil, "^%C\t\n", nil, nil, 14) + controls.rarity = new("DropDownControl"):DropDownControl(nil, {-190, 10, 100, 18}, rarityDropList) + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 480, 420}, "", nil, "^%C\t\n", nil, nil, 14) if self.displayItem then controls.edit:SetText(self.displayItem:BuildRaw():gsub("Rarity: %w+\n","")) controls.rarity:SelByValue(self.displayItem.rarity, "rarity") @@ -2523,7 +2523,7 @@ function ItemsTabClass:EditDisplayItemText(alsoAddItem) end controls.edit.font = "FIXED" controls.edit.pasteFilter = sanitiseText - controls.save = new("ButtonControl", nil, {-45, 470, 80, 20}, self.displayItem and "Save" or "Create", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 470, 80, 20}, self.displayItem and "Save" or "Create", function() local id = self.displayItem and self.displayItem.id self:CreateDisplayItemFromRaw(buildRaw(), not self.displayItem) self.displayItem.id = id @@ -2533,12 +2533,12 @@ function ItemsTabClass:EditDisplayItemText(alsoAddItem) main:ClosePopup() end, nil, true) controls.save.enabled = function() - local item = new("Item", buildRaw()) + local item = new("Item"):Item(buildRaw()) return item.base ~= nil end controls.save.tooltipFunc = function(tooltip) tooltip:Clear() - local item = new("Item", buildRaw()) + local item = new("Item"):Item(buildRaw()) if item.base then self:AddItemTooltip(tooltip, item, nil, true) else @@ -2551,7 +2551,7 @@ function ItemsTabClass:EditDisplayItemText(alsoAddItem) tooltip:AddLine(14, "Scholar's Platinum Kris of Joy") end end - controls.cancel = new("ButtonControl", nil, {45, 470, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 470, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(500, 500, self.displayItem and "Edit Item Text" or "Create Custom Item from Text", controls, nil, "edit") @@ -2583,7 +2583,7 @@ end ---@return table @The new item function ItemsTabClass:anointItem(node) self.anointEnchantSlot = self.anointEnchantSlot or 1 - local item = new("Item", self.displayItem:BuildRaw()) + local item = new("Item"):Item(self.displayItem:BuildRaw()) item.id = self.displayItem.id if #item.enchantModLines >= self.anointEnchantSlot then t_remove(item.enchantModLines, self.anointEnchantSlot) @@ -2676,7 +2676,7 @@ function ItemsTabClass:AnointDisplayItem(enchantSlot) local width = saveLabelWidth() return -(width + 90) / 2 end - controls.save = new("ButtonControl", {"BOTTOMLEFT", nil, "BOTTOM" }, {saveLabelX, -4, saveLabelWidth, 20}, saveLabel, function() + controls.save = new("ButtonControl"):ButtonControl({"BOTTOMLEFT", nil, "BOTTOM" }, {saveLabelX, -4, saveLabelWidth, 20}, saveLabel, function() self:SetDisplayItem(self:anointItem(controls.notableDB.selValue)) main:ClosePopup() end) @@ -2684,7 +2684,7 @@ function ItemsTabClass:AnointDisplayItem(enchantSlot) tooltip:Clear() self:AppendAnointTooltip(tooltip, controls.notableDB.selValue) end - controls.close = new("ButtonControl", {"TOPLEFT", controls.save, "TOPRIGHT" }, {10, 0, 80, 20}, "Cancel", function() + controls.close = new("ButtonControl"):ButtonControl({"TOPLEFT", controls.save, "TOPRIGHT" }, {10, 0, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(380, 448, "Anoint Item", controls) @@ -3201,7 +3201,7 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() t_insert(sourceList, { label = "Custom", sourceId = "CUSTOM" }) buildMods(sourceList[1].sourceId) local function addModifier() - local item = new("Item", self.displayItem:BuildRaw()) + local item = new("Item"):Item(self.displayItem:BuildRaw()) item.id = self.displayItem.id local sourceId = sourceList[controls.source.selIndex].sourceId if sourceId == "CUSTOM" then @@ -3222,8 +3222,8 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() item:BuildAndParseRaw() return item end - controls.sourceLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Source:") - controls.source = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 150, 18}, sourceList, function(index, value) + controls.sourceLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Source:") + controls.source = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 150, 18}, sourceList, function(index, value) buildMods(value.sourceId) controls.modSelect:SetSel(1) if controls.sort then @@ -3231,18 +3231,18 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() end end) controls.source.enabled = #sourceList > 1 - controls.sortLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {350, 20, 0, 16}, "^7Sort by:") + controls.sortLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {350, 20, 0, 16}, "^7Sort by:") controls.sortLabel.shown = function() return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" end - controls.sort = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {355, 20, 240, 18}, sortList, function(index, value) + controls.sort = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {355, 20, 240, 18}, sortList, function(index, value) applySort(value.stat, true) end) controls.sort.shown = function() return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" end - controls.modSelectLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 45, 0, 16}, "^7Modifier:") - controls.modSelect = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 600, 18}, modList) + controls.modSelectLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 45, 0, 16}, "^7Modifier:") + controls.modSelect = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 600, 18}, modList) controls.modSelect.shown = function() return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" end @@ -3255,11 +3255,11 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() self:AddModComparisonTooltip(tooltip, value.mod) end end - controls.custom = new("EditControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 440, 18}) + controls.custom = new("EditControl"):EditControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 440, 18}) controls.custom.shown = function() return sourceList[controls.source.selIndex].sourceId == "CUSTOM" end - controls.save = new("ButtonControl", nil, {-45, 75, 80, 20}, "Add", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 75, 80, 20}, "Add", function() self:SetDisplayItem(addModifier()) main:ClosePopup() end) @@ -3267,7 +3267,7 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() tooltip:Clear() self:AddItemTooltip(tooltip, addModifier()) end - controls.close = new("ButtonControl", nil, {45, 75, 80, 20}, "Cancel", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {45, 75, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(710, 105, "Add Modifier to Item", controls, "save", sourceList[controls.source.selIndex].sourceId == "CUSTOM" and "custom") diff --git a/src/Classes/ItemsTab.lua.rej b/src/Classes/ItemsTab.lua.rej new file mode 100644 index 0000000000..1b4f7c3371 --- /dev/null +++ b/src/Classes/ItemsTab.lua.rej @@ -0,0 +1,948 @@ +diff a/src/Classes/ItemsTab.lua b/src/Classes/ItemsTab.lua (rejected hunks) +@@ -78,14 +78,18 @@ local function buildModSortList() + return sortList, sortStats + end + +-local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Control", function(self, build) +- self.UndoHandler() +- self.ControlHost() +- self.Control() ++---@class ItemsTab: UndoHandler, ControlHost, Control ++local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Control") ++ ++---@param build Build ++function ItemsTabClass:ItemsTab(build) ++ self:UndoHandler() ++ self:ControlHost() ++ self:Control() + + self.build = build + +- self.socketViewer = new("PassiveTreeView") ++ self.socketViewer = new("PassiveTreeView"):PassiveTreeView() + + self.items = { } + self.itemOrderList = { } +@@ -129,7 +133,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro + self.slots = { } + self.orderedSlots = { } + self.slotOrder = { } +- self.slotAnchor = new("Control", {"TOPLEFT",self,"TOPLEFT"}, {96, 76, 310, 0}) ++ self.slotAnchor = new("Control"):Control({"TOPLEFT",self,"TOPLEFT"}, {96, 76, 310, 0}) + local prevSlot = self.slotAnchor + local function addSlot(slot) + prevSlot = slot +@@ -139,7 +143,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro + t_insert(self.controls, slot) + end + for index, slotName in ipairs(baseSlots) do +- local slot = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName) ++ local slot = new("ItemSlotControl"):ItemSlotControl({"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName) + addSlot(slot) + if slotName:match("Weapon") then + -- Add alternate weapon slot +@@ -147,14 +151,14 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro + slot.shown = function() + return not self.activeItemSet.useSecondWeaponSet + end +- local swapSlot = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Swap", slotName) ++ local swapSlot = new("ItemSlotControl"):ItemSlotControl({"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Swap", slotName) + addSlot(swapSlot) + swapSlot.weaponSet = 2 + swapSlot.shown = function() + return self.activeItemSet.useSecondWeaponSet + end + for i = 1, 6 do +- local abyssal = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Swap Abyssal Socket "..i, "Abyssal #"..i) ++ local abyssal = new("ItemSlotControl"):ItemSlotControl({"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Swap Abyssal Socket "..i, "Abyssal #"..i) + addSlot(abyssal) + abyssal.parentSlot = swapSlot + abyssal.weaponSet = 2 +@@ -175,7 +179,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro + if slotName == "Weapon 1" or slotName == "Weapon 2" or slotName == "Helmet" or slotName == "Gloves" or slotName == "Body Armour" or slotName == "Boots" or slotName == "Belt" then + -- Add Abyssal Socket slots + for i = 1, 6 do +- local abyssal = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Abyssal Socket "..i, "Abyssal #"..i) ++ local abyssal = new("ItemSlotControl"):ItemSlotControl({"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Abyssal Socket "..i, "Abyssal #"..i) + addSlot(abyssal) + abyssal.parentSlot = slot + if slotName:match("Weapon") then +@@ -261,24 +265,24 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro + self.controls.weaponSwap2.locked = function() + return self.activeItemSet.useSecondWeaponSet + end +- self.controls.weaponSwapLabel = new("LabelControl", {"RIGHT",self.controls.weaponSwap1,"LEFT"}, {-4, 0, 0, 14}, "^7Weapon Set:") ++ self.controls.weaponSwapLabel = new("LabelControl"):LabelControl({"RIGHT",self.controls.weaponSwap1,"LEFT"}, {-4, 0, 0, 14}, "^7Weapon Set:") + + -- All items list + if main.portraitMode then +- self.controls.itemList = new("ItemListControl", {"TOPRIGHT",self.lastSlot,"BOTTOMRIGHT"}, {0, 0, 360, 308}, self, true) ++ self.controls.itemList = new("ItemListControl"):ItemListControl({"TOPRIGHT",self.lastSlot,"BOTTOMRIGHT"}, {0, 0, 360, 308}, self, true) + else +- self.controls.itemList = new("ItemListControl", {"TOPLEFT",self.controls.setManage,"TOPRIGHT"}, {20, 20, 360, 308}, self, true) ++ self.controls.itemList = new("ItemListControl"):ItemListControl({"TOPLEFT",self.controls.setManage,"TOPRIGHT"}, {20, 20, 360, 308}, self, true) + end + + -- Database selector +- self.controls.selectDBLabel = new("LabelControl", {"TOPLEFT",self.controls.itemList,"BOTTOMLEFT"}, {0, 14, 0, 16}, "^7Import from:") ++ self.controls.selectDBLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.itemList,"BOTTOMLEFT"}, {0, 14, 0, 16}, "^7Import from:") + self.controls.selectDBLabel.shown = function() + return self.height < 980 + end +- self.controls.selectDB = new("DropDownControl", {"LEFT",self.controls.selectDBLabel,"RIGHT"}, {4, 0, 150, 18}, { "Uniques", "Rare Templates" }) ++ self.controls.selectDB = new("DropDownControl"):DropDownControl({"LEFT",self.controls.selectDBLabel,"RIGHT"}, {4, 0, 150, 18}, { "Uniques", "Rare Templates" }) + + -- Unique database +- self.controls.uniqueDB = new("ItemDBControl", {"TOPLEFT",self.controls.itemList,"BOTTOMLEFT"}, {0, 76, 360, function(c) return m_min(244, self.maxY - select(2, c:GetPos())) end}, self, main.uniqueDB, "UNIQUE") ++ self.controls.uniqueDB = new("ItemDBControl"):ItemDBControl({"TOPLEFT",self.controls.itemList,"BOTTOMLEFT"}, {0, 76, 360, function(c) return m_min(244, self.maxY - select(2, c:GetPos())) end}, self, main.uniqueDB, "UNIQUE") + self.controls.uniqueDB.y = function() + return self.controls.selectDBLabel:IsShown() and 118 or 96 + end +@@ -287,7 +291,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro + end + + -- Rare template database +- self.controls.rareDB = new("ItemDBControl", {"TOPLEFT",self.controls.itemList,"BOTTOMLEFT"}, {0, 76, 360, function(c) return m_min(260, self.maxY - select(2, c:GetPos())) end}, self, main.rareDB, "RARE") ++ self.controls.rareDB = new("ItemDBControl"):ItemDBControl({"TOPLEFT",self.controls.itemList,"BOTTOMLEFT"}, {0, 76, 360, function(c) return m_min(260, self.maxY - select(2, c:GetPos())) end}, self, main.rareDB, "RARE") + self.controls.rareDB.y = function() + return self.controls.selectDBLabel:IsShown() and 78 or 396 + end +@@ -295,16 +299,16 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro + return not self.controls.selectDBLabel:IsShown() or self.controls.selectDB.selIndex == 2 + end + -- Create/import item +- self.controls.craftDisplayItem = new("ButtonControl", {"TOPLEFT",main.portraitMode and self.controls.setManage or self.controls.itemList,"TOPRIGHT"}, {20, main.portraitMode and 0 or -20, 120, 20}, "Craft item...", function() ++ self.controls.craftDisplayItem = new("ButtonControl"):ButtonControl({"TOPLEFT",main.portraitMode and self.controls.setManage or self.controls.itemList,"TOPRIGHT"}, {20, main.portraitMode and 0 or -20, 120, 20}, "Craft item...", function() + self:CraftItem() + end) + self.controls.craftDisplayItem.shown = function() + return self.displayItem == nil + end +- self.controls.newDisplayItem = new("ButtonControl", {"TOPLEFT",self.controls.craftDisplayItem,"TOPRIGHT"}, {8, 0, 120, 20}, "Create custom...", function() ++ self.controls.newDisplayItem = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.craftDisplayItem,"TOPRIGHT"}, {8, 0, 120, 20}, "Create custom...", function() + self:EditDisplayItemText() + end) +- self.controls.displayItemTip = new("LabelControl", {"TOPLEFT",self.controls.craftDisplayItem,"BOTTOMLEFT"}, {0, 8, 100, 16}, ++ self.controls.displayItemTip = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.craftDisplayItem,"BOTTOMLEFT"}, {0, 8, 100, 16}, + [[^7Double-click an item from one of the lists, + or copy and paste an item from in game + (hover over the item and Ctrl+C) to view or edit +@@ -350,7 +353,7 @@ holding Shift will put it in the second.]]) + end + -- Section: Variant(s) + +- self.controls.displayItemSectionVariant = new("Control", {"TOPLEFT",self.controls.addDisplayItem,"BOTTOMLEFT"}, {0, 8, 0, function() ++ self.controls.displayItemSectionVariant = new("Control"):Control({"TOPLEFT",self.controls.addDisplayItem,"BOTTOMLEFT"}, {0, 8, 0, function() + if not self.displayItem then + return 0 + end +@@ -375,7 +378,7 @@ holding Shift will put it in the second.]]) + (self.displayItem.hasAltVariant4 and 24 or 0) + + (self.displayItem.hasAltVariant5 and 24 or 0)) + end}) +- self.controls.displayItemVersion = new("DropDownControl", {"TOPLEFT", self.controls.displayItemSectionVariant,"TOPLEFT"}, {0, 0, 300, 20}, nil, function(index, value) ++ self.controls.displayItemVersion = new("DropDownControl"):DropDownControl({"TOPLEFT", self.controls.displayItemSectionVariant,"TOPLEFT"}, {0, 0, 300, 20}, nil, function(index, value) + self.displayItem.selectedVersion = index + self.displayItem:NormaliseVariantSelections() + self.displayItem:BuildAndParseRaw() +@@ -388,7 +391,7 @@ holding Shift will put it in the second.]]) + return self.displayItem and self.displayItem.usesVariantGroups + and self.displayItem.versionList and #self.displayItem.versionList > 1 + end +- self.controls.displayItemVariant = new("DropDownControl", {"TOPLEFT", self.controls.displayItemSectionVariant,"TOPLEFT"}, {0, 0, 300, 20}, nil, function(index, value) ++ self.controls.displayItemVariant = new("DropDownControl"):DropDownControl({"TOPLEFT", self.controls.displayItemSectionVariant,"TOPLEFT"}, {0, 0, 300, 20}, nil, function(index, value) + self:SelectDisplayItemVariant(index, value, "variant", self.controls.displayItemVariant) + end) + self.controls.displayItemVariant.y = function() +@@ -398,35 +401,35 @@ holding Shift will put it in the second.]]) + self.controls.displayItemVariant.shown = function() + return self.displayItem.variantList and #self.displayItem.variantList > 1 + end +- self.controls.displayItemAltVariant = new("DropDownControl", {"TOPLEFT",self.controls.displayItemVariant,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) ++ self.controls.displayItemAltVariant = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemVariant,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) + self:SelectDisplayItemVariant(index, value, "variantAlt", self.controls.displayItemAltVariant) + end) + self.controls.displayItemAltVariant.maxDroppedWidth = 1000 + self.controls.displayItemAltVariant.shown = function() + return self.displayItem.hasAltVariant + end +- self.controls.displayItemAltVariant2 = new("DropDownControl", {"TOPLEFT",self.controls.displayItemAltVariant,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) ++ self.controls.displayItemAltVariant2 = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemAltVariant,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) + self:SelectDisplayItemVariant(index, value, "variantAlt2", self.controls.displayItemAltVariant2) + end) + self.controls.displayItemAltVariant2.maxDroppedWidth = 1000 + self.controls.displayItemAltVariant2.shown = function() + return self.displayItem.hasAltVariant2 + end +- self.controls.displayItemAltVariant3 = new("DropDownControl", {"TOPLEFT",self.controls.displayItemAltVariant2,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) ++ self.controls.displayItemAltVariant3 = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemAltVariant2,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) + self:SelectDisplayItemVariant(index, value, "variantAlt3", self.controls.displayItemAltVariant3) + end) + self.controls.displayItemAltVariant3.maxDroppedWidth = 1000 + self.controls.displayItemAltVariant3.shown = function() + return self.displayItem.hasAltVariant3 + end +- self.controls.displayItemAltVariant4 = new("DropDownControl", {"TOPLEFT",self.controls.displayItemAltVariant3,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) ++ self.controls.displayItemAltVariant4 = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemAltVariant3,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) + self:SelectDisplayItemVariant(index, value, "variantAlt4", self.controls.displayItemAltVariant4) + end) + self.controls.displayItemAltVariant4.maxDroppedWidth = 1000 + self.controls.displayItemAltVariant4.shown = function() + return self.displayItem.hasAltVariant4 + end +- self.controls.displayItemAltVariant5 = new("DropDownControl", {"TOPLEFT",self.controls.displayItemAltVariant4,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) ++ self.controls.displayItemAltVariant5 = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemAltVariant4,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) + self:SelectDisplayItemVariant(index, value, "variantAlt5", self.controls.displayItemAltVariant5) + end) + self.controls.displayItemAltVariant5.maxDroppedWidth = 1000 +@@ -452,11 +455,11 @@ holding Shift will put it in the second.]]) + end + + -- Section: Sockets and Links +- self.controls.displayItemSectionSockets = new("Control", {"TOPLEFT",self.controls.displayItemSectionVariant,"BOTTOMLEFT"}, {0, 0, 0, function() ++ self.controls.displayItemSectionSockets = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionVariant,"BOTTOMLEFT"}, {0, 0, 0, function() + return self.displayItem and self.displayItem.selectableSocketCount > 0 and 28 or 0 + end}) + for i = 1, 6 do +- local drop = new("DropDownControl", {"TOPLEFT",self.controls.displayItemSectionSockets,"TOPLEFT"}, {(i-1) * 64, 0, 36, 20}, socketDropList, function(index, value) ++ local drop = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemSectionSockets,"TOPLEFT"}, {(i-1) * 64, 0, 36, 20}, socketDropList, function(index, value) + self.displayItem.sockets[i].color = value.color + self.displayItem:BuildAndParseRaw() + self:UpdateDisplayItemTooltip() +@@ -466,7 +469,7 @@ holding Shift will put it in the second.]]) + end + self.controls["displayItemSocket"..i] = drop + if i < 6 then +- local link = new("CheckBoxControl", {"LEFT",drop,"RIGHT"}, {4, 0, 20}, nil, function(state) ++ local link = new("CheckBoxControl"):CheckBoxControl({"LEFT",drop,"RIGHT"}, {4, 0, 20}, nil, function(state) + if state and self.displayItem.sockets[i].group ~= self.displayItem.sockets[i+1].group then + for s = i + 1, #self.displayItem.sockets do + self.displayItem.sockets[s].group = self.displayItem.sockets[s].group - 1 +@@ -485,7 +488,7 @@ holding Shift will put it in the second.]]) + self.controls["displayItemLink"..i] = link + end + end +- self.controls.displayItemAddSocket = new("ButtonControl", {"TOPLEFT",self.controls.displayItemSectionSockets,"TOPLEFT"}, {function() return (#self.displayItem.sockets - self.displayItem.abyssalSocketCount) * 64 - 12 end, 0, 20, 20}, "+", function() ++ self.controls.displayItemAddSocket = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemSectionSockets,"TOPLEFT"}, {function() return (#self.displayItem.sockets - self.displayItem.abyssalSocketCount) * 64 - 12 end, 0, 20, 20}, "+", function() + local insertIndex = #self.displayItem.sockets - self.displayItem.abyssalSocketCount + 1 + t_insert(self.displayItem.sockets, insertIndex, { + color = self.displayItem.defaultSocketColor, +@@ -503,28 +506,28 @@ holding Shift will put it in the second.]]) + end + + -- Section: Enchant / Anoint / Corrupt +- self.controls.displayItemSectionEnchant = new("Control", {"TOPLEFT",self.controls.displayItemSectionSockets,"BOTTOMLEFT"}, {0, 0, 0, function() ++ self.controls.displayItemSectionEnchant = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionSockets,"BOTTOMLEFT"}, {0, 0, 0, function() + return (self.controls.displayItemEnchant:IsShown() or self.controls.displayItemEnchant2:IsShown() or self.controls.displayItemAnoint:IsShown() or self.controls.displayItemAnoint2:IsShown() or self.controls.displayItemCorrupt:IsShown() ) and 28 or 0 + end}) +- self.controls.displayItemEnchant = new("ButtonControl", { "TOPLEFT", self.controls.displayItemSectionEnchant, "TOPLEFT" }, { 0, 0, 160, 20 }, "Change Enchantment...", function() ++ self.controls.displayItemEnchant = new("ButtonControl"):ButtonControl({ "TOPLEFT", self.controls.displayItemSectionEnchant, "TOPLEFT" }, { 0, 0, 160, 20 }, "Change Enchantment...", function() + self:EnchantDisplayItem(1) + end) + self.controls.displayItemEnchant.shown = function() + return self.displayItem and self.displayItem.enchantments + end +- self.controls.displayItemEnchant2 = new("ButtonControl", { "TOPLEFT", self.controls.displayItemEnchant, "TOPRIGHT", true }, { 8, 0, 160, 20 }, "Change Enchantment 2...", function() ++ self.controls.displayItemEnchant2 = new("ButtonControl"):ButtonControl({ "TOPLEFT", self.controls.displayItemEnchant, "TOPRIGHT", true }, { 8, 0, 160, 20 }, "Change Enchantment 2...", function() + self:EnchantDisplayItem(2) + end) + self.controls.displayItemEnchant2.shown = function() + return self.displayItem and self.displayItem.enchantments and self.displayItem.canHaveTwoEnchants and #self.displayItem.enchantModLines > 0 + end +- self.controls.displayItemAnoint = new("ButtonControl", {"TOPLEFT",self.controls.displayItemEnchant2,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint...", function() ++ self.controls.displayItemAnoint = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemEnchant2,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint...", function() + self:AnointDisplayItem(1) + end) + self.controls.displayItemAnoint.shown = function() + return self.displayItem and isAnointable(self.displayItem) + end +- self.controls.displayItemAnoint2 = new("ButtonControl", {"TOPLEFT",self.controls.displayItemAnoint,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint 2...", function() ++ self.controls.displayItemAnoint2 = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemAnoint,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint 2...", function() + self:AnointDisplayItem(2) + end) + self.controls.displayItemAnoint2.shown = function() +@@ -533,7 +536,7 @@ holding Shift will put it in the second.]]) + self.displayItem.canHaveTwoEnchants and + #self.displayItem.enchantModLines > 0 + end +- self.controls.displayItemAnoint3 = new("ButtonControl", {"TOPLEFT",self.controls.displayItemAnoint2,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint 3...", function() ++ self.controls.displayItemAnoint3 = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemAnoint2,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint 3...", function() + self:AnointDisplayItem(3) + end) + self.controls.displayItemAnoint3.shown = function() +@@ -542,7 +545,7 @@ holding Shift will put it in the second.]]) + self.displayItem.canHaveThreeEnchants and + #self.displayItem.enchantModLines > 1 + end +- self.controls.displayItemAnoint4 = new("ButtonControl", {"TOPLEFT",self.controls.displayItemAnoint3,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint 4...", function() ++ self.controls.displayItemAnoint4 = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemAnoint3,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint 4...", function() + self:AnointDisplayItem(4) + end) + self.controls.displayItemAnoint4.shown = function() +@@ -551,21 +554,21 @@ holding Shift will put it in the second.]]) + self.displayItem.canHaveFourEnchants and + #self.displayItem.enchantModLines > 2 + end +- self.controls.displayItemCorrupt = new("ButtonControl", {"TOPLEFT",self.controls.displayItemAnoint4,"TOPRIGHT",true}, {8, 10, 100, 20}, "Corrupt...", function() ++ self.controls.displayItemCorrupt = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemAnoint4,"TOPRIGHT",true}, {8, 10, 100, 20}, "Corrupt...", function() + self:CorruptDisplayItem("Corrupted") + end) + self.controls.displayItemCorrupt.shown = function() + return self.displayItem and self.displayItem.corruptible + end + --[[ +- self.controls.displayItemScourge = new("ButtonControl", {"TOPLEFT",self.controls.displayItemCorrupt,"TOPRIGHT",true}, {8, 0, 100, 20}, "Scourge...", function() ++ self.controls.displayItemScourge = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemCorrupt,"TOPRIGHT",true}, {8, 0, 100, 20}, "Scourge...", function() + self:CorruptDisplayItem("Scourge") + end) + self.controls.displayItemScourge.shown = function() + return self.displayItem and self.displayItem.corruptible + end + --]] +- self.controls.displayItemAddImplicit = new("ButtonControl", {"TOPLEFT",self.controls.displayItemCorrupt,"TOPRIGHT",true}, {8, 0, 120, 20}, "Add Implicit...", function() ++ self.controls.displayItemAddImplicit = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemCorrupt,"TOPRIGHT",true}, {8, 0, 120, 20}, "Add Implicit...", function() + self:AddImplicitToDisplayItem() + end) + self.controls.displayItemAddImplicit.shown = function() +@@ -604,11 +607,11 @@ holding Shift will put it in the second.]]) + self.displayItem:BuildAndParseRaw() + self:UpdateDisplayItemTooltip() + end +- self.controls.displayItemSectionInfluence = new("Control", {"TOPLEFT",self.controls.displayItemSectionEnchant,"BOTTOMLEFT"}, {0, 0, 0, function() ++ self.controls.displayItemSectionInfluence = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionEnchant,"BOTTOMLEFT"}, {0, 0, 0, function() + return self.displayItem and self.displayItem.canBeInfluenced and 28 or 0 + end}) + local influenceTipText = table.concat(main:WrapString("Selecting an influence here will also allow the modifier dropdowns to contain influenced mods.", 16, 140), "\n") +- self.controls.displayItemInfluence = new("DropDownControl", {"TOPLEFT",self.controls.displayItemSectionInfluence,"TOPRIGHT"}, {0, 0, 100, 20}, influenceDisplayList, function(index, value) ++ self.controls.displayItemInfluence = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemSectionInfluence,"TOPRIGHT"}, {0, 0, 100, 20}, influenceDisplayList, function(index, value) + local otherIndex = self.controls.displayItemInfluence2.selIndex + setDisplayItemInfluence({ index - 1, otherIndex - 1 }) + end) +@@ -616,7 +619,7 @@ holding Shift will put it in the second.]]) + self.controls.displayItemInfluence.shown = function() + return self.displayItem and self.displayItem.canBeInfluenced + end +- self.controls.displayItemInfluence2 = new("DropDownControl", {"TOPLEFT",self.controls.displayItemInfluence,"TOPRIGHT",true}, {8, 0, 100, 20}, influenceDisplayList, function(index, value) ++ self.controls.displayItemInfluence2 = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemInfluence,"TOPRIGHT",true}, {8, 0, 100, 20}, influenceDisplayList, function(index, value) + local otherIndex = self.controls.displayItemInfluence.selIndex + setDisplayItemInfluence({ index - 1, otherIndex - 1 }) + end) +@@ -626,15 +629,15 @@ holding Shift will put it in the second.]]) + self.controls.displayItemInfluence2.tooltipText = influenceTipText + + -- Section: Item Quality +- self.controls.displayItemSectionQuality = new("Control", {"TOPLEFT",self.controls.displayItemSectionInfluence,"BOTTOMLEFT"}, {0, 0, 0, function() ++ self.controls.displayItemSectionQuality = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionInfluence,"BOTTOMLEFT"}, {0, 0, 0, function() + return (self.controls.displayItemQuality:IsShown() and self.controls.displayItemQualityEdit:IsShown()) and 28 or 0 + end}) +- self.controls.displayItemQuality = new("LabelControl", { "TOPLEFT", self.controls.displayItemSectionQuality, "TOPRIGHT" }, { 0, 0, 0, 16 }, "^7Quality:") ++ self.controls.displayItemQuality = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.displayItemSectionQuality, "TOPRIGHT" }, { 0, 0, 0, 16 }, "^7Quality:") + self.controls.displayItemQuality.shown = function() + return self.displayItem and self.displayItem.quality and (self.displayItem.base.type ~= "Amulet" or self.displayItem.base.type ~= "Belt" or self.displayItem.base.type ~= "Jewel" or self.displayItem.base.type ~= "Quiver" or self.displayItem.base.type ~= "Ring" or self.displayItem.type ~= "Graft") + end + +- self.controls.displayItemQualityEdit = new("EditControl", {"LEFT",self.controls.displayItemQuality,"RIGHT"}, {2, 0, 60, 20}, nil, nil, "%D", 2, function(buf) ++ self.controls.displayItemQualityEdit = new("EditControl"):EditControl({"LEFT",self.controls.displayItemQuality,"RIGHT"}, {2, 0, 60, 20}, nil, nil, "%D", 2, function(buf) + self.displayItem.quality = tonumber(buf) + self.displayItem:BuildAndParseRaw() + self:UpdateDisplayItemTooltip() +@@ -652,10 +655,10 @@ holding Shift will put it in the second.]]) + end + end + -- Section: Catalysts +- self.controls.displayItemSectionCatalyst = new("Control", {"TOPLEFT",self.controls.displayItemSectionQuality,"BOTTOMLEFT"}, {0, 0, 0, function() ++ self.controls.displayItemSectionCatalyst = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionQuality,"BOTTOMLEFT"}, {0, 0, 0, function() + return (self.controls.displayItemCatalyst:IsShown() or self.controls.displayItemCatalystQualityEdit:IsShown()) and 28 or 0 + end}) +- self.controls.displayItemCatalyst = new("DropDownControl", {"TOPLEFT",self.controls.displayItemSectionCatalyst,"TOPRIGHT"}, {0, 0, 250, 20}, ++ self.controls.displayItemCatalyst = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemSectionCatalyst,"TOPRIGHT"}, {0, 0, 250, 20}, + {"Catalyst","Abrasive (Attack)","Accelerating (Speed)","Dextral (Suffix)","Fertile (Life & Mana)","Imbued (Caster)","Intrinsic (Attribute)","Noxious (Physical & Chaos Damage)", + "Prismatic (Resistance)","Sinistral (Prefix)","Tempering (Defense)","Turbulent (Elemental)","Unstable (Critical)"}, + function(index, value) +@@ -677,7 +680,7 @@ holding Shift will put it in the second.]]) + self.controls.displayItemCatalyst.shown = function() + return self.displayItem and (self.displayItem.crafted or self.displayItem.hasModTags) and (self.displayItem.base.type == "Amulet" or self.displayItem.base.type == "Ring" or self.displayItem.base.type == "Belt") + end +- self.controls.displayItemCatalystQualityEdit = new("EditControl", {"LEFT",self.controls.displayItemCatalyst,"RIGHT"}, {2, 0, 60, 20}, nil, nil, "%D", 2, function(buf) ++ self.controls.displayItemCatalystQualityEdit = new("EditControl"):EditControl({"LEFT",self.controls.displayItemCatalyst,"RIGHT"}, {2, 0, 60, 20}, nil, nil, "%D", 2, function(buf) + self.displayItem.catalystQuality = tonumber(buf) + if self.displayItem.crafted then + for i = 1, self.displayItem.affixLimit do +@@ -706,27 +709,27 @@ holding Shift will put it in the second.]]) + end + } + +- self.controls.displayItemClusterJewelNodeCountLabel = new("LabelControl", {"TOPLEFT",self.controls.displayItemClusterJewelSkill,"BOTTOMLEFT"}, {0, 7, 0, 14}, "^7Added Passives:") +- self.controls.displayItemClusterJewelNodeCount = new("SliderControl", {"LEFT",self.controls.displayItemClusterJewelNodeCountLabel,"RIGHT"}, {2, 0, 150, 20}, function(val) ++ self.controls.displayItemClusterJewelNodeCountLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.displayItemClusterJewelSkill,"BOTTOMLEFT"}, {0, 7, 0, 14}, "^7Added Passives:") ++ self.controls.displayItemClusterJewelNodeCount = new("SliderControl"):SliderControl({"LEFT",self.controls.displayItemClusterJewelNodeCountLabel,"RIGHT"}, {2, 0, 150, 20}, function(val) + local divVal = self.controls.displayItemClusterJewelNodeCount:GetDivVal() + local clusterJewel = self.displayItem.clusterJewel + self.displayItem.clusterJewelNodeCount = round(val * (clusterJewel.maxNodes - clusterJewel.minNodes) + clusterJewel.minNodes) + self:CraftClusterJewel() + end) + +- self.controls.craftingSortingLabel = new("LabelControl", { "TOPLEFT", self.controls.displayItemSectionClusterJewel, "BOTTOMLEFT" }, { 0, 0, 0, 16 }, "^7Modifier sorting:") ++ self.controls.craftingSortingLabel = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.displayItemSectionClusterJewel, "BOTTOMLEFT" }, { 0, 0, 0, 16 }, "^7Modifier sorting:") + self.controls.craftingSortingLabel.shown = function() + return self.displayItem and self.displayItem.crafted and + -- cluster jewels don't have good comparison support and sorting would be misleading + not (self.displayItem.base.type == "Jewel" and self.displayItem.base.subType == "Cluster") + end +- self.controls.craftingSorting = new("DropDownControl", { "LEFT", self.controls.craftingSortingLabel, "RIGHT" }, { 4, 0, 200, 20 }, sortingOptions, function() ++ self.controls.craftingSorting = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.craftingSortingLabel, "RIGHT" }, { 4, 0, 200, 20 }, sortingOptions, function() + self:UpdateAffixControls() + end) + + -- Section: Affix Selection + local maxModCount = 9 +- self.controls.displayItemSectionAffix = new("Control", { "TOPLEFT", self.controls.craftingSortingLabel, "BOTTOMLEFT", true }, { 0, function() ++ self.controls.displayItemSectionAffix = new("Control"):Control({ "TOPLEFT", self.controls.craftingSortingLabel, "BOTTOMLEFT", true }, { 0, function() + if self.controls.craftingSortingLabel.shown() then + return 8 + else +@@ -793,7 +796,7 @@ holding Shift will put it in the second.]]) + end + return range + end +- drop = new("DropDownControl", {"TOPLEFT",prev,"TOPLEFT"}, {i==1 and 40 or 0, 0, 418, 20}, nil, function(index, value) ++ drop = new("DropDownControl"):DropDownControl({"TOPLEFT",prev,"TOPLEFT"}, {i==1 and 40 or 0, 0, 418, 20}, nil, function(index, value) + local affix = { modId = "None", fractured = self.displayItem[drop.outputTable][drop.outputIndex].fractured } + if value.modId then + affix.modId = value.modId +@@ -968,24 +971,24 @@ holding Shift will put it in the second.]]) + end + drop.slider = slider + self.controls["displayItemAffix"..i] = drop +- self.controls["displayItemAffixLabel"..i] = new("LabelControl", {"RIGHT",drop,"LEFT"}, {-4, 0, 0, 14}, function() ++ self.controls["displayItemAffixLabel"..i] = new("LabelControl"):LabelControl({"RIGHT",drop,"LEFT"}, {-4, 0, 0, 14}, function() + local ignoreModType = self.displayItem.rareLikeUnique and self.displayItem.rareLikeUnique.ignoreModType + return ignoreModType and "^7Explicit:" + or drop.outputTable == "prefixes" and "^7Prefix:" + or "^7Suffix:" + end) + self.controls["displayItemAffixRange"..i] = slider +- self.controls["displayItemAffixRangeLabel"..i] = new("LabelControl", {"RIGHT",slider,"LEFT"}, {-4, 0, 0, 14}, function() ++ self.controls["displayItemAffixRangeLabel"..i] = new("LabelControl"):LabelControl({"RIGHT",slider,"LEFT"}, {-4, 0, 0, 14}, function() + return drop.selIndex > 1 and "^7Roll:" or "^x7F7F7FRoll:" + end) + end + + -- Section: Custom modifiers + -- if either Custom or Crucible mod buttons are shown, create the control for the list of mods +- self.controls.displayItemSectionCustom = new("Control", {"TOPLEFT",self.controls.displayItemSectionAffix,"BOTTOMLEFT",true}, {0, 0, 0, function() ++ self.controls.displayItemSectionCustom = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionAffix,"BOTTOMLEFT",true}, {0, 0, 0, function() + return (self.controls.displayItemAddCustom:IsShown() or self.controls.displayItemAddCrucible:IsShown()) and 28 + self.displayItem.customCount * 22 or 0 + end}) +- self.controls.displayItemAddCustom = new("ButtonControl", {"TOPLEFT",self.controls.displayItemSectionCustom,"TOPLEFT"}, {0, 0, 120, 20}, "Add modifier...", function() ++ self.controls.displayItemAddCustom = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemSectionCustom,"TOPLEFT"}, {0, 0, 120, 20}, "Add modifier...", function() + self:AddCustomModifierToDisplayItem() + end) + self.controls.displayItemAddCustom.shown = function() +@@ -994,7 +997,7 @@ holding Shift will put it in the second.]]) + + -- Section: Crucible modifiers + -- if the Add modifier button is not shown, take its place, otherwise move it to the right of it +- self.controls.displayItemAddCrucible = new("ButtonControl", {"TOPLEFT",self.controls.displayItemSectionCustom,"TOPLEFT"}, {function() ++ self.controls.displayItemAddCrucible = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemSectionCustom,"TOPLEFT"}, {function() + return (self.controls.displayItemAddCustom:IsShown() and 128) or 0 + end, 0, 150, 20}, "Add Crucible mod...", function() + self:AddCrucibleModifierToDisplayItem() +@@ -1005,7 +1008,7 @@ holding Shift will put it in the second.]]) + + -- Section: Modifier Range + local labelFontSize = 14 +- self.controls.displayItemSectionRange = new("Control", { "TOPLEFT", self.controls.displayItemSectionCustom, "BOTTOMLEFT" }, { 0, 0, 0, function() ++ self.controls.displayItemSectionRange = new("Control"):Control({ "TOPLEFT", self.controls.displayItemSectionCustom, "BOTTOMLEFT" }, { 0, 0, 0, function() + if not self.displayItem or not self.displayItem.rangeLineList[1] then + return 0 + end +@@ -1022,7 +1025,7 @@ holding Shift will put it in the second.]]) + end}) + local foulbornIcon = NewImageHandle() + foulbornIcon:Load("Assets/breachicon.png") +- self.controls.displayItemRangeLine = new("DropDownControl", {"TOPLEFT",self.controls.displayItemSectionRange,"TOPLEFT"}, {0, 0, 350, 18}, nil, function(index, value) ++ self.controls.displayItemRangeLine = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemSectionRange,"TOPLEFT"}, {0, 0, 350, 18}, nil, function(index, value) + self.controls.displayItemRangeSlider.val = self.displayItem.rangeLineList[index].range + end) + self.controls.displayItemRangeLine.shown = function() +@@ -1031,7 +1034,7 @@ holding Shift will put it in the second.]]) + local function getSelectedModLine() + return self.displayItem and self.displayItem.rangeLineList[self.controls.displayItemRangeLine.selIndex] or nil + end +- local box = new("CheckBoxControl", { "LEFT", self.controls.displayItemRangeLine, "RIGHT", true }, { 0, 0, 18 }, nil) ++ local box = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.displayItemRangeLine, "RIGHT", true }, { 0, 0, 18 }, nil) + box.changeFunc = function(val) + local line = getSelectedModLine() + if line and line.modId and line.newModId then +@@ -1068,7 +1071,7 @@ holding Shift will put it in the second.]]) + end + end + self.controls.displayItemMutatedCheckbox = box +- local slider = new("SliderControl", { "LEFT", self.controls.displayItemMutatedCheckbox, "RIGHT", true }, { 4, 0, 100, 18 }, function(val) ++ local slider = new("SliderControl"):SliderControl({ "LEFT", self.controls.displayItemMutatedCheckbox, "RIGHT", true }, { 4, 0, 100, 18 }, function(val) + local line = getSelectedModLine() + line.range = val + self.displayItem:BuildAndParseRaw() +@@ -1093,7 +1096,7 @@ holding Shift will put it in the second.]]) + + -- layout: [box] <- [slider] <- text + +- local box = new("CheckBoxControl", { "TOPLEFT", baseControl, "TOPLEFT", true }, { 0, 0, 18 }, nil, function(val) ++ local box = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", baseControl, "TOPLEFT", true }, { 0, 0, 18 }, nil, function(val) + local line = self.displayItem and self.displayItem.rangeLineList[i] + if line and line.modId and line.newModId then + self.displayItem:MutateMod(line.modId, line.newModId, not line.mutated) +@@ -1134,7 +1137,7 @@ holding Shift will put it in the second.]]) + + self.controls["displayItemStackedMutatedCheckbox" .. i] = box + +- local slider = new("SliderControl", { "LEFT", box, "RIGHT", true }, { 4, 0, 100, 18 }, function(val) ++ local slider = new("SliderControl"):SliderControl({ "LEFT", box, "RIGHT", true }, { 4, 0, 100, 18 }, function(val) + if self.displayItem and self.displayItem.rangeLineList[i] then + self.displayItem.rangeLineList[i].range = val + self.displayItem:BuildAndParseRaw() +@@ -1156,7 +1159,7 @@ holding Shift will put it in the second.]]) + + self.controls["displayItemStackedRangeSlider" .. i] = slider + +- self.controls["displayItemStackedRangeLine" .. i] = new("LabelControl", { "LEFT", slider, "RIGHT", true }, { 4, -2, 350, labelFontSize }, function() ++ self.controls["displayItemStackedRangeLine" .. i] = new("LabelControl"):LabelControl({ "LEFT", slider, "RIGHT", true }, { 4, -2, 350, labelFontSize }, function() + local modLine = self.displayItem.rangeLineList[i] + if self.displayItem and modLine then + local colour = modLine.mutated and colorCodes.MUTATED or "^7" +@@ -1172,11 +1175,11 @@ holding Shift will put it in the second.]]) + end + end + -- Tooltip anchor +- self.controls.displayItemTooltipAnchor = new("Control", {"TOPLEFT",self.controls.displayItemSectionRange,"BOTTOMLEFT"}) ++ self.controls.displayItemTooltipAnchor = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionRange,"BOTTOMLEFT"}) + + -- Scroll bars +- self.controls.scrollBarH = new("ScrollBarControl", nil, {0, 0, 0, 18}, 100, "HORIZONTAL", true) +- self.controls.scrollBarV = new("ScrollBarControl", nil, {0, 0, 18, 0}, 100, "VERTICAL", true) ++ self.controls.scrollBarH = new("ScrollBarControl"):ScrollBarControl(nil, {0, 0, 0, 18}, 100, "HORIZONTAL", true) ++ self.controls.scrollBarV = new("ScrollBarControl"):ScrollBarControl(nil, {0, 0, 18, 0}, 100, "VERTICAL", true) + + -- Initialise drag target lists + t_insert(self.controls.itemList.dragTargetList, self.controls.sharedItemList) +@@ -1857,7 +1861,7 @@ end + + -- Attempt to create a new item from the given item raw text and sets it as the new display item + function ItemsTabClass:CreateDisplayItemFromRaw(itemRaw, normalise) +- local newItem = new("Item", itemRaw) ++ local newItem = new("Item"):Item(itemRaw) + if newItem.base then + if normalise then + self:CopyAnointsAndEldritchImplicits(newItem, main.migrateEldritchImplicits, false) +@@ -2221,7 +2225,7 @@ function ItemsTabClass:UpdateAffixControl(control, item, affixType, outputTable, + if sortOption.stat and self.controls.craftingSortingLabel.shown() then + local calcFunc = self.build.calcsTab:GetMiscCalculator() + local slotName = self.displayItem:GetPrimarySlot() +- local testSubject = new("Item", self.displayItem:BuildRaw()) ++ local testSubject = new("Item"):Item(self.displayItem:BuildRaw()) + local controlPowerCache = powerCache + if selAffix and selAffix ~= "None" then + testSubject[outputTable][outputIndex] = { modId = "None" } +@@ -2260,7 +2264,7 @@ function ItemsTabClass:UpdateAffixControl(control, item, affixType, outputTable, + calcFunc({ repSlotName = slotName, repItem = testSubject }), + sortOption + ) +- testSubject = new("Item", originalItem) ++ testSubject = new("Item"):Item(originalItem) + else + for _, line in ipairs(mod) do + local rangedLine = itemLib.applyRange(line, main.defaultItemAffixQuality or 0.5, 1, 1) +@@ -2407,7 +2411,7 @@ end + + function ItemsTabClass:AddModComparisonTooltip(tooltip, mod) + local slotName = self.displayItem:GetPrimarySlot() +- local newItem = new("Item", self.displayItem:BuildRaw()) ++ local newItem = new("Item"):Item(self.displayItem:BuildRaw()) + + for _, subMod in ipairs(mod) do + t_insert(newItem.explicitModLines, { line = checkLineForAllocates(subMod, self.build.spec.nodes), modTags = mod.modTags, [mod.type] = true }) +@@ -2563,21 +2567,21 @@ function ItemsTabClass:CraftItem() + item:BuildAndParseRaw() + return item + end +- controls.rarityLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {50, 20, 0, 16}, "Rarity:") +- controls.rarity = new("DropDownControl", nil, {-80, 20, 100, 18}, rarityDropList) ++ controls.rarityLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {50, 20, 0, 16}, "Rarity:") ++ controls.rarity = new("DropDownControl"):DropDownControl(nil, {-80, 20, 100, 18}, rarityDropList) + controls.rarity.selIndex = self.lastCraftRaritySel or 3 +- controls.title = new("EditControl", nil, {70, 20, 190, 18}, "", "Name") ++ controls.title = new("EditControl"):EditControl(nil, {70, 20, 190, 18}, "", "Name") + controls.title.shown = function() + return controls.rarity.selIndex >= 3 + end +- controls.typeLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {50, 45, 0, 16}, "Type:") +- controls.type = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {55, 45, 295, 18}, self.build.data.itemBaseTypeList, function(index, value) ++ controls.typeLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {50, 45, 0, 16}, "Type:") ++ controls.type = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {55, 45, 295, 18}, self.build.data.itemBaseTypeList, function(index, value) + controls.base.list = self.build.data.itemBaseLists[self.build.data.itemBaseTypeList[index]] + controls.base.selIndex = 1 + end) + controls.type.selIndex = self.lastCraftTypeSel or 1 +- controls.baseLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {50, 70, 0, 16}, "Base:") +- controls.base = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {55, 70, 200, 18}, self.build.data.itemBaseLists[self.build.data.itemBaseTypeList[controls.type.selIndex]]) ++ controls.baseLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {50, 70, 0, 16}, "Base:") ++ controls.base = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {55, 70, 200, 18}, self.build.data.itemBaseLists[self.build.data.itemBaseTypeList[controls.type.selIndex]]) + controls.base.selIndex = self.lastCraftBaseSel or 1 + controls.base.tooltipFunc = function(tooltip, mode, index, value) + tooltip:Clear() +@@ -2727,7 +2731,7 @@ function ItemsTabClass:EnchantDisplayItem(enchantSlot) + buildEnchantmentSourceList() + buildEnchantmentList() + local function enchantItem(idx, remove) +- local item = new("Item", self.displayItem:BuildRaw()) ++ local item = new("Item"):Item(self.displayItem:BuildRaw()) + local index = idx or controls.enchantment.selIndex + item.id = self.displayItem.id + local entry = enchantmentList[index] +@@ -2756,7 +2760,7 @@ function ItemsTabClass:EnchantDisplayItem(enchantSlot) + if entry.sortValues[stat] ~= nil then + return entry.sortValues[stat] + end +- local item = new("Item", self.displayItem:BuildRaw()) ++ local item = new("Item"):Item(self.displayItem:BuildRaw()) + item.id = self.displayItem.id + local line = entry.line + local first, second = line:match("([^/]+)/([^/]+)") +@@ -2813,8 +2817,8 @@ function ItemsTabClass:EnchantDisplayItem(enchantSlot) + end + end + if haveSkills then +- controls.skillLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Skill:") +- controls.skill = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 180, 18}, skillList, function(index, value) ++ controls.skillLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Skill:") ++ controls.skill = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 180, 18}, skillList, function(index, value) + buildEnchantmentSourceList() + buildEnchantmentList() + controls.enchantment:SetSel(1) +@@ -2822,7 +2826,7 @@ function ItemsTabClass:EnchantDisplayItem(enchantSlot) + applySort(controls.sort.list[controls.sort.selIndex].stat, true) + end + end) +- controls.allSkills = new("CheckBoxControl", {"TOPLEFT",nil,"TOPLEFT"}, {350, 20, 18}, "All skills:", function(state) ++ controls.allSkills = new("CheckBoxControl"):CheckBoxControl({"TOPLEFT",nil,"TOPLEFT"}, {350, 20, 18}, "All skills:", function(state) + buildSkillList(not state) + controls.skill:SetSel(1) + buildEnchantmentList() +@@ -2837,33 +2841,33 @@ function ItemsTabClass:EnchantDisplayItem(enchantSlot) + controls.allSkills.enabled = false + end + end +- controls.enchantmentSourceLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 45, 0, 16}, "^7Source:") +- controls.enchantmentSource = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 180, 18}, enchantmentSourceList, function(index, value) ++ controls.enchantmentSourceLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 45, 0, 16}, "^7Source:") ++ controls.enchantmentSource = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 180, 18}, enchantmentSourceList, function(index, value) + buildEnchantmentList() + controls.enchantment:SetSel(m_min(controls.enchantment.selIndex, #enchantmentList)) + if controls.sort then + applySort(controls.sort.list[controls.sort.selIndex].stat, true) + end + end) +- controls.sortLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {350, 45, 0, 16}, "^7Sort by:") +- controls.sort = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {355, 45, 240, 18}, sortList, function(index, value) ++ controls.sortLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {350, 45, 0, 16}, "^7Sort by:") ++ controls.sort = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {355, 45, 240, 18}, sortList, function(index, value) + applySort(value.stat, true) + end) +- controls.enchantmentLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 70, 0, 16}, "^7Enchantment:") +- controls.enchantment = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 70, 495, 18}, enchantmentList) ++ controls.enchantmentLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 70, 0, 16}, "^7Enchantment:") ++ controls.enchantment = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 70, 495, 18}, enchantmentList) + controls.enchantment.tooltipFunc = function(tooltip, mode, index) + tooltip:Clear() + self:AddItemTooltip(tooltip, enchantItem(index), nil, true) + end +- controls.save = new("ButtonControl", nil, {-88, 100, 80, 20}, "Enchant", function() ++ controls.save = new("ButtonControl"):ButtonControl(nil, {-88, 100, 80, 20}, "Enchant", function() + self:SetDisplayItem(enchantItem()) + main:ClosePopup() + end) +- controls.remove = new("ButtonControl", nil, {0, 100, 80, 20}, "Remove", function() ++ controls.remove = new("ButtonControl"):ButtonControl(nil, {0, 100, 80, 20}, "Remove", function() + self:SetDisplayItem(enchantItem(nil, true)) + main:ClosePopup() + end) +- controls.close = new("ButtonControl", nil, {88, 100, 80, 20}, "Cancel", function() ++ controls.close = new("ButtonControl"):ButtonControl(nil, {88, 100, 80, 20}, "Cancel", function() + main:ClosePopup() + end) + main:OpenPopup(605, 130, "Enchant Item", controls) +@@ -2979,7 +2983,7 @@ function ItemsTabClass:AnointDisplayItem(enchantSlot) + self.anointEnchantSlot = enchantSlot or 1 + + local controls = { } +- controls.notableDB = new("NotableDBControl", {"TOPLEFT",nil,"TOPLEFT"}, {10, 60, 360, 360}, self, self.build.spec.tree.nodes, "ANOINT") ++ controls.notableDB = new("NotableDBControl"):NotableDBControl({"TOPLEFT",nil,"TOPLEFT"}, {10, 60, 360, 360}, self, self.build.spec.tree.nodes, "ANOINT") + + local function saveLabel() + local node = controls.notableDB.selValue +@@ -3066,7 +3070,7 @@ function ItemsTabClass:CorruptDisplayItem(modType) + if entry.sortValues[stat] ~= nil then + return entry.sortValues[stat] + end +- local item = new("Item", self.displayItem:BuildRaw()) ++ local item = new("Item"):Item(self.displayItem:BuildRaw()) + item.id = self.displayItem.id + item.corrupted = true + local mod = entry.mod +@@ -3134,7 +3138,7 @@ function ItemsTabClass:CorruptDisplayItem(modType) + if controls.implicit4 then controls.implicit4:UpdateSearch() end + end + local function corruptItem(addingImplicits) +- local item = new("Item", self.displayItem:BuildRaw()) ++ local item = new("Item"):Item(self.displayItem:BuildRaw()) + item.id = self.displayItem.id + item.corrupted = true + -- either add implicits or roll ranges. if in the future it is possible +@@ -3174,7 +3178,7 @@ function ItemsTabClass:CorruptDisplayItem(modType) + return item + end + if self.displayItem.rarity == "UNIQUE" or self.displayItem.rarity == "RELIC" then +- local item = new("Item", self.displayItem:BuildRaw()) ++ local item = new("Item"):Item(self.displayItem:BuildRaw()) + local offset = 20 + for i, mod in ipairs(item.explicitModLines) do + local modRange = mod.range or main.defaultItemAffixQuality +@@ -3184,10 +3188,9 @@ function ItemsTabClass:CorruptDisplayItem(modType) + local lines = main:WrapString("^7" .. line, 16, 430) + return table.concat(lines, "\n"), #lines + end +- controls["rollRangeValue" .. i] = new("LabelControl", { "TOPLEFT", nil, "TOPLEFT" }, ++ controls["rollRangeValue" .. i] = new("LabelControl"):LabelControl({ "TOPLEFT", nil, "TOPLEFT" }, + { 10, 10 + offset, 200, 16 }, "^71.00") +- controls["rollRangeSlider" .. i] = new("SliderControl", +- { "LEFT", controls["rollRangeValue" .. i], "RIGHT" }, { 5, 0, 80, 18 }, function(val) ++ controls["rollRangeSlider" .. i] = new("SliderControl"):SliderControl({ "LEFT", controls["rollRangeValue" .. i], "RIGHT" }, { 5, 0, 80, 18 }, function(val) + corruptedRanges[i] = 0.78 + round(0.44 * val, 2) -- 0.78-1.22 + controls["rollRangeValue" .. i].label = "^7" .. string.format("%.2f", corruptedRanges[i]) + controls["rollRangeLabel" .. i].label = formatLabel(corruptedRanges[i]) +@@ -3197,8 +3200,7 @@ function ItemsTabClass:CorruptDisplayItem(modType) + controls["rollRangeValue" .. i].label = "^7" .. string.format("%.2f", corruptedRanges[i]) + local label, lineCount = formatLabel(corruptedRanges[i]) + offset = offset + 16 * (lineCount - 1) +- controls["rollRangeLabel" .. i] = new("LabelControl", +- { "LEFT", controls["rollRangeSlider" .. i], "RIGHT" }, ++ controls["rollRangeLabel" .. i] = new("LabelControl"):LabelControl({ "LEFT", controls["rollRangeSlider" .. i], "RIGHT" }, + { 5, 0, 200, 16 }, label) + -- hide them by default as they are a secondary window + controls["rollRangeLabel" .. i].shown = false +@@ -3218,7 +3220,7 @@ function ItemsTabClass:CorruptDisplayItem(modType) + end + controls.implicitCannotBeChangedLabel.shown = implicitNum > 0 and not canChangeImplicits + end +- controls.implicits = new("ButtonControl", { "TOPLEFT", nil, "TOPLEFT" }, { 5, 5, 80, 20 }, "Implicits", ++ controls.implicits = new("ButtonControl"):ButtonControl({ "TOPLEFT", nil, "TOPLEFT" }, { 5, 5, 80, 20 }, "Implicits", + function() + local implicitNum = currentModType == "Corrupted" and 2 or 4 + local canChangeImplicits = currentModType ~= "Corrupted" or not self.displayItem.implicitsCannotBeChanged +@@ -3237,7 +3239,7 @@ function ItemsTabClass:CorruptDisplayItem(modType) + controls.implicits.shown = function() + return self.displayItem.rarity == "UNIQUE" or self.displayItem.rarity == "RELIC" + end +- controls.rolls = new("ButtonControl", { "LEFT", controls.implicits, "RIGHT" }, { 5, 0, 80, 20 }, ++ controls.rolls = new("ButtonControl"):ButtonControl({ "LEFT", controls.implicits, "RIGHT" }, { 5, 0, 80, 20 }, + "Roll Ranges", + function() + setImplicitControlsShown(0, false) +@@ -3255,9 +3257,9 @@ function ItemsTabClass:CorruptDisplayItem(modType) + controls.rolls.shown = function() + return self.displayItem.rarity == "UNIQUE" or self.displayItem.rarity == "RELIC" + end +- controls.sourceLabel = new("LabelControl", { "TOPRIGHT", nil, "TOPLEFT" }, { 95, 30, 0, 16 }, ++ controls.sourceLabel = new("LabelControl"):LabelControl({ "TOPRIGHT", nil, "TOPLEFT" }, { 95, 30, 0, 16 }, + "^7Source:") +- controls.source = new("DropDownControl", { "TOPLEFT", nil, "TOPLEFT" }, { 100, 30, 150, 18 }, ++ controls.source = new("DropDownControl"):DropDownControl({ "TOPLEFT", nil, "TOPLEFT" }, { 100, 30, 150, 18 }, + sourceList, function(index, value) + if value == "Scourge" then + currentModType = "ScourgeUpside" +@@ -3285,19 +3287,19 @@ function ItemsTabClass:CorruptDisplayItem(modType) + controls.implicit4:SetSel(1) + end) + controls.source.enabled = #sourceList > 1 +- controls.sortLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {350, 20, 0, 16}, "^7Sort by:") +- controls.sort = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {355, 20, 240, 18}, sortList, function(index, value) ++ controls.sortLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {350, 20, 0, 16}, "^7Sort by:") ++ controls.sort = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {355, 20, 240, 18}, sortList, function(index, value) + applySort(value.stat) + end) + local implicitRowSize = 20 + local implicitYPos = 35 +- controls.implicitCannotBeChangedLabel = new("LabelControl", { "TOPLEFT", nil, "TOPLEFT" }, { 20, implicitYPos + implicitRowSize, 0, 20 }, "^7This Items Implicits Cannot Be Changed") ++ controls.implicitCannotBeChangedLabel = new("LabelControl"):LabelControl({ "TOPLEFT", nil, "TOPLEFT" }, { 20, implicitYPos + implicitRowSize, 0, 20 }, "^7This Items Implicits Cannot Be Changed") + controls.implicitCannotBeChangedLabel.shown = self.displayItem.implicitsCannotBeChanged + for i = 1, 4 do + local controlName = "implicit" .. i +- controls[controlName .. "Label"] = new("LabelControl", { "TOPRIGHT", nil, "TOPLEFT" }, { 75, implicitYPos + i * implicitRowSize, 0, 16 }, ++ controls[controlName .. "Label"] = new("LabelControl"):LabelControl({ "TOPRIGHT", nil, "TOPLEFT" }, { 75, implicitYPos + i * implicitRowSize, 0, 16 }, + string.format("^7Implicit #%d:", i)) +- controls[controlName] = new("DropDownControl", { "TOPLEFT", nil, "TOPLEFT" }, { 80, implicitYPos + i * implicitRowSize, 440, 18 }, nil) ++ controls[controlName] = new("DropDownControl"):DropDownControl({ "TOPLEFT", nil, "TOPLEFT" }, { 80, implicitYPos + i * implicitRowSize, 440, 18 }, nil) + controls[controlName].tooltipFunc = function(tooltip, mode, index, value) + tooltip:Clear() + if mode ~= "OUT" and value and value.mod then +@@ -3326,7 +3328,7 @@ function ItemsTabClass:CorruptDisplayItem(modType) + controls["implicit" .. i].selFunc() + end + end +- controls.save = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, { -45, -4, 80, 20 }, modType, function() ++ controls.save = new("ButtonControl"):ButtonControl({ "BOTTOM", nil, "BOTTOM" }, { -45, -4, 80, 20 }, modType, function() + self:SetDisplayItem(corruptItem(controls.implicit1.shown)) + main:ClosePopup() + end) +@@ -3334,7 +3336,7 @@ function ItemsTabClass:CorruptDisplayItem(modType) + tooltip:Clear() + self:AddItemTooltip(tooltip, corruptItem(controls.implicit1.shown), nil, false) + end +- controls.close = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, { 45, -4, 80, 20 }, "Cancel", function() ++ controls.close = new("ButtonControl"):ButtonControl({ "BOTTOM", nil, "BOTTOM" }, { 45, -4, 80, 20 }, "Cancel", function() + main:ClosePopup() + end) + main:OpenPopup(605, 103 + 20 * 2, modType .. " Item", controls) +@@ -3358,7 +3360,7 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() + if listMod.sortValues[stat] ~= nil then + return listMod.sortValues[stat] + end +- local item = new("Item", self.displayItem:BuildRaw()) ++ local item = new("Item"):Item(self.displayItem:BuildRaw()) + item.id = self.displayItem.id + for _, line in ipairs(listMod.mod) do + t_insert(item.explicitModLines, { line = checkLineForAllocates(line, self.build.spec.nodes), modTags = listMod.mod.modTags, [listMod.type] = true }) +@@ -3708,7 +3710,7 @@ function ItemsTabClass:AddCrucibleModifierToDisplayItem() + end + end + local function addModifier() +- local item = new("Item", self.displayItem:BuildRaw()) ++ local item = new("Item"):Item(self.displayItem:BuildRaw()) + item.id = self.displayItem.id + item.crucibleModLines = { } + local listMod = { +@@ -3735,8 +3737,8 @@ function ItemsTabClass:AddCrucibleModifierToDisplayItem() + buildCrucibleMods() + local y = 45 + for i = 1,5 do +- controls["modSelectNode"..i.."Label"] = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, y, 0, 16}, "^7Node "..i..":") +- controls["modSelectNode"..i] = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, y, 555, 18}, modList[i]) ++ controls["modSelectNode"..i.."Label"] = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, y, 0, 16}, "^7Node "..i..":") ++ controls["modSelectNode"..i] = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, y, 555, 18}, modList[i]) + controls["modSelectNode"..i].tooltipFunc = function(tooltip, mode, index, value) + tooltip:Clear() + if mode ~= "OUT" and value and value ~= "None" then +@@ -3756,7 +3758,7 @@ function ItemsTabClass:AddCrucibleModifierToDisplayItem() + end + end + end +- controls.save = new("ButtonControl", nil, {-45, 157, 80, 20}, "Add", function() ++ controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 157, 80, 20}, "Add", function() + self:SetDisplayItem(addModifier()) + main:ClosePopup() + end) +@@ -3764,7 +3766,7 @@ function ItemsTabClass:AddCrucibleModifierToDisplayItem() + tooltip:Clear() + self:AddItemTooltip(tooltip, addModifier()) + end +- controls.close = new("ButtonControl", nil, {45, 157, 80, 20}, "Cancel", function() ++ controls.close = new("ButtonControl"):ButtonControl(nil, {45, 157, 80, 20}, "Cancel", function() + main:ClosePopup() + end) + main:OpenPopup(710, 185, "Add Crucible Modifier to Item", controls, "save") +@@ -3959,7 +3961,7 @@ function ItemsTabClass:AddImplicitToDisplayItem() + if listMod.sortValues[stat] ~= nil then + return listMod.sortValues[stat] + end +- local item = new("Item", self.displayItem:BuildRaw()) ++ local item = new("Item"):Item(self.displayItem:BuildRaw()) + item.id = self.displayItem.id + applyCandidateMod(item, listMod) + item:BuildAndParseRaw() +@@ -4039,7 +4041,7 @@ function ItemsTabClass:AddImplicitToDisplayItem() + end + end + local function addModifier() +- local item = new("Item", self.displayItem:BuildRaw()) ++ local item = new("Item"):Item(self.displayItem:BuildRaw()) + item.id = self.displayItem.id + local sourceId = sourceList[controls.source.selIndex].sourceId + if sourceId == "CUSTOM" then +@@ -4054,8 +4056,8 @@ function ItemsTabClass:AddImplicitToDisplayItem() + item:BuildAndParseRaw() + return item + end +- controls.sourceLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Source:") +- controls.source = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 150, 18}, sourceList, function(index, value) ++ controls.sourceLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Source:") ++ controls.source = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 150, 18}, sourceList, function(index, value) + if value.sourceId ~= "CUSTOM" then + controls.modSelectLabel.y = 70 + buildMods(value.sourceId) +@@ -4070,18 +4072,18 @@ function ItemsTabClass:AddImplicitToDisplayItem() + end + end) + controls.source.enabled = #sourceList > 1 +- controls.sortLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {350, 20, 0, 16}, "^7Sort by:") ++ controls.sortLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {350, 20, 0, 16}, "^7Sort by:") + controls.sortLabel.shown = function() + return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" + end +- controls.sort = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {355, 20, 240, 18}, sortList, function(index, value) ++ controls.sort = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {355, 20, 240, 18}, sortList, function(index, value) + applySort(value.stat, true) + end) + controls.sort.shown = function() + return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" + end +- controls.modGroupSelectLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 45, 0, 16}, "^7Type:") +- controls.modGroupSelect = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 600, 18}, modGroups, function(index, value) ++ controls.modGroupSelectLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 45, 0, 16}, "^7Type:") ++ controls.modGroupSelect = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 600, 18}, modGroups, function(index, value) + controls.modSelect.list = modList[value.modListIndex] + controls.modSelect:SetSel(1) + end) +@@ -4103,8 +4105,8 @@ function ItemsTabClass:AddImplicitToDisplayItem() + self:AddModComparisonTooltip(tooltip, value.mod) + end + end +- controls.modSelectLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 70, 0, 16}, "^7Modifier:") +- controls.modSelect = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 70, 600, 18}, sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" and modList[modGroups[1].modListIndex] or { }) ++ controls.modSelectLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 70, 0, 16}, "^7Modifier:") ++ controls.modSelect = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 70, 600, 18}, sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" and modList[modGroups[1].modListIndex] or { }) + controls.modSelect.shown = function() + return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" + end +@@ -4117,11 +4119,11 @@ function ItemsTabClass:AddImplicitToDisplayItem() + self:AddModComparisonTooltip(tooltip, value.mod) + end + end +- controls.custom = new("EditControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 440, 18}) ++ controls.custom = new("EditControl"):EditControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 440, 18}) + controls.custom.shown = function() + return sourceList[controls.source.selIndex].sourceId == "CUSTOM" + end +- controls.save = new("ButtonControl", nil, {-45, 100, 80, 20}, "Add", function() ++ controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 100, 80, 20}, "Add", function() + self:SetDisplayItem(addModifier()) + main:ClosePopup() + end) +@@ -4129,7 +4131,7 @@ function ItemsTabClass:AddImplicitToDisplayItem() + tooltip:Clear() + self:AddItemTooltip(tooltip, addModifier()) + end +- controls.close = new("ButtonControl", nil, {45, 100, 80, 20}, "Cancel", function() ++ controls.close = new("ButtonControl"):ButtonControl(nil, {45, 100, 80, 20}, "Cancel", function() + main:ClosePopup() + end) + main:OpenPopup(710, 130, "Add Implicit to Item", controls, "save", sourceList[controls.source.selIndex].sourceId == "CUSTOM" and "custom") +@@ -4768,7 +4770,7 @@ function ItemsTabClass:AddItemTooltip(tooltip, item, slot, dbMode, maxWidth) + (#itemSkills > 1 and "s" or "") .. ".") + for i, itemSkill in ipairs(itemSkills) do + if not tooltip.childTooltips[i] then +- tooltip.childTooltips[i] = new("Tooltip") ++ tooltip.childTooltips[i] = new("Tooltip"):Tooltip() + end + -- find gem since the item data only contains the skill id + local skill = data.skills[itemSkill.skillId] diff --git a/src/Classes/LabelControl.lua b/src/Classes/LabelControl.lua index 2f799ece2d..afedc6fdf3 100644 --- a/src/Classes/LabelControl.lua +++ b/src/Classes/LabelControl.lua @@ -3,13 +3,20 @@ -- Class: Label Control -- Simple text label. -- -local LabelClass = newClass("LabelControl", "Control", function(self, anchor, rect, label) - self.Control(anchor, rect) +---@class LabelControl: Control +local LabelClass = newClass("LabelControl", "Control") + +---@param anchor? ControlAnchor +---@param rect? ControlRect +---@param label string +function LabelClass:LabelControl(anchor, rect, label) + self:Control(anchor, rect) self.label = label self.width = function() return DrawStringWidth(self:GetProperty("height"), "VAR", self:GetProperty("label")) end -end) + return self +end function LabelClass:Draw() local x, y = self:GetPos() diff --git a/src/Classes/ListControl.lua b/src/Classes/ListControl.lua index 34dd0e7f41..7527b4cd96 100644 --- a/src/Classes/ListControl.lua +++ b/src/Classes/ListControl.lua @@ -30,16 +30,19 @@ local m_min = math.min local m_max = math.max local m_floor = math.floor -local ListClass = newClass("ListControl", "Control", "ControlHost", function(self, anchor, rect, rowHeight, scroll, isMutable, list, forceTooltip) - self.Control(anchor, rect) - self.ControlHost() +---@class ListControl: Control, ControlHost +local ListClass = newClass("ListControl", "Control", "ControlHost") + +function ListClass:ListControl(anchor, rect, rowHeight, scroll, isMutable, list, forceTooltip) + self:Control(anchor, rect) + self:ControlHost() self.rowHeight = rowHeight self.scroll = scroll self.isMutable = isMutable self.list = list or { } self.forceTooltip = forceTooltip self.colList = { { } } - self.tooltip = new("Tooltip") + self.tooltip = new("Tooltip"):Tooltip() self.font = "VAR" if self.scroll then if self.scroll == "HORIZONTAL" then @@ -48,7 +51,7 @@ local ListClass = newClass("ListControl", "Control", "ControlHost", function(sel self.scrollH = false end end - self.controls.scrollBarH = new("ScrollBarControl", {"BOTTOM",self,"BOTTOM"}, {-8, -1, 0, self.scroll and 16 or 0}, rowHeight * 2, "HORIZONTAL") { + self.controls.scrollBarH = new("ScrollBarControl"):ScrollBarControl({"BOTTOM",self,"BOTTOM"}, {-8, -1, 0, self.scroll and 16 or 0}, rowHeight * 2, "HORIZONTAL") { shown = function() return self.scrollH end, @@ -57,7 +60,7 @@ local ListClass = newClass("ListControl", "Control", "ControlHost", function(sel return width - 18 end } - self.controls.scrollBarV = new("ScrollBarControl", {"RIGHT",self,"RIGHT"}, {-1, 0, self.scroll and 16 or 0, 0}, rowHeight * 2, "VERTICAL") { + self.controls.scrollBarV = new("ScrollBarControl"):ScrollBarControl({"RIGHT",self,"RIGHT"}, {-1, 0, self.scroll and 16 or 0, 0}, rowHeight * 2, "VERTICAL") { y = function() return (self.scrollH and -8 or 0) end, @@ -71,7 +74,9 @@ local ListClass = newClass("ListControl", "Control", "ControlHost", function(sel self.controls.scrollBarV.shown = false end self.labelPositionOffset = {0, 0} -end) + return self +end + function ListClass:SelectIndex(index) self.selValue = self.list[index] diff --git a/src/Classes/MinionListControl.lua.rej b/src/Classes/MinionListControl.lua.rej new file mode 100644 index 0000000000..868199b696 --- /dev/null +++ b/src/Classes/MinionListControl.lua.rej @@ -0,0 +1,40 @@ +diff a/src/Classes/MinionListControl.lua b/src/Classes/MinionListControl.lua (rejected hunks) +@@ -8,14 +8,17 @@ local t_insert = table.insert + local t_remove = table.remove + local s_format = string.format + +-local MinionListClass = newClass("MinionListControl", "ListControl", function(self, anchor, rect, data, list, dest) +- self.ListControl(anchor, rect, 16, "VERTICAL", not dest, list) ++---@class MinionListControl: ListControl ++local MinionListClass = newClass("MinionListControl", "ListControl") ++ ++function MinionListClass:MinionListControl(anchor, rect, data, list, dest) ++ self:ListControl(anchor, rect, 16, "VERTICAL", not dest, list) + self.data = data + self.dest = dest + if dest then + self.dragTargetList = { dest } + self.label = "^7Available Spectres:" +- self.controls.add = new("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Add", function() ++ self.controls.add = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Add", function() + self:AddSel() + end) + self.controls.add.enabled = function() +@@ -23,14 +26,15 @@ local MinionListClass = newClass("MinionListControl", "ListControl", function(se + end + else + self.label = "^7Spectres in Build:" +- self.controls.delete = new("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Remove", function() ++ self.controls.delete = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Remove", function() + self:OnSelDelete(self.selIndex, self.selValue) + end) + self.controls.delete.enabled = function() + return self.selValue ~= nil + end + end +-end) ++ return self ++end + + function MinionListClass:AddSel() + if self.dest and not isValueInArray(self.dest.list, self.selValue) then diff --git a/src/Classes/MinionSearchListControl.lua.rej b/src/Classes/MinionSearchListControl.lua.rej new file mode 100644 index 0000000000..116465ed88 --- /dev/null +++ b/src/Classes/MinionSearchListControl.lua.rej @@ -0,0 +1,35 @@ +diff a/src/Classes/MinionSearchListControl.lua b/src/Classes/MinionSearchListControl.lua (rejected hunks) +@@ -8,16 +8,19 @@ local t_insert = table.insert + local t_remove = table.remove + local s_format = string.format + +-local MinionSearchListClass = newClass("MinionSearchListControl", "MinionListControl", function(self, anchor, rect, data, list, dest) +- self.MinionListControl(anchor, rect, data, list, dest) ++---@class MinionSearchListControl: MinionListControl ++local MinionSearchListClass = newClass("MinionSearchListControl", "MinionListControl") ++ ++function MinionSearchListClass:MinionSearchListControl(anchor, rect, data, list, dest) ++ self:MinionListControl(anchor, rect, data, list, dest) + self.unfilteredList = copyTable(list) + self.isMutable = false + +- self.controls.searchText = new("EditControl", {"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 203, 18}, "", "Search", "%c", 100, function(buf) ++ self.controls.searchText = new("EditControl"):EditControl({"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 203, 18}, "", "Search", "%c", 100, function(buf) + self:ListFilterChanged(buf, self.controls.searchModeDropDown.selIndex) + end, nil, nil, true) + +- self.controls.searchModeDropDown = new("DropDownControl", {"LEFT",self.controls.searchText,"RIGHT"}, {2, 0, 60, 18}, { "Names", "Skills", "Both"}, function(index, value) ++ self.controls.searchModeDropDown = new("DropDownControl"):DropDownControl({"LEFT",self.controls.searchText,"RIGHT"}, {2, 0, 60, 18}, { "Names", "Skills", "Both"}, function(index, value) + self:ListFilterChanged(self.controls.searchText.buf, index) + end) + +@@ -28,7 +31,8 @@ local MinionSearchListClass = newClass("MinionSearchListControl", "MinionListCon + self.controls.delete.y = self.controls.add.y - 20 + end + +-end) ++ return self ++end + + function MinionSearchListClass:DoesEntryMatchFilters(searchStr, minionId, filterMode) + if filterMode == 1 or filterMode == 3 then diff --git a/src/Classes/ModDB.lua b/src/Classes/ModDB.lua index 0fdba90fef..d9ccf0d772 100644 --- a/src/Classes/ModDB.lua +++ b/src/Classes/ModDB.lua @@ -17,10 +17,14 @@ local bor = OR64 -- bit.bor local mod_createMod = modLib.createMod -local ModDBClass = newClass("ModDB", "ModStore", function(self, parent) - self.ModStore(parent) +---@class ModDB: ModStore +local ModDBClass = newClass("ModDB", "ModStore") + +function ModDBClass:ModDB(parent) + self:ModStore(parent) self.mods = { } -end) + return self +end function ModDBClass:AddMod(mod) local name = mod.name diff --git a/src/Classes/ModList.lua b/src/Classes/ModList.lua index 7bbadba7d6..ff33169ad7 100644 --- a/src/Classes/ModList.lua +++ b/src/Classes/ModList.lua @@ -16,9 +16,13 @@ local bor = OR64 -- bit.bor local mod_createMod = modLib.createMod -local ModListClass = newClass("ModList", "ModStore", function(self, parent) - self.ModStore(parent) -end) +---@class ModList: ModStore +local ModListClass = newClass("ModList", "ModStore") + +function ModListClass:ModList(parent) + self:ModStore(parent) + return self +end function ModListClass:AddMod(mod) t_insert(self, mod) diff --git a/src/Classes/ModStore.lua b/src/Classes/ModStore.lua index 972c783749..c31acde6c8 100644 --- a/src/Classes/ModStore.lua +++ b/src/Classes/ModStore.lua @@ -27,12 +27,16 @@ local conditionName = setmetatable({ }, { __index = function(t, var) return t[var] end }) -local ModStoreClass = newClass("ModStore", function(self, parent) +---@class ModStore +local ModStoreClass = newClass("ModStore") + +function ModStoreClass:ModStore(parent) self.parent = parent or false self.actor = parent and parent.actor or { } self.multipliers = { } self.conditions = { } -end) + return self +end local function getActor(self, actorType) if actorType == "player" then diff --git a/src/Classes/NotableDBControl.lua.rej b/src/Classes/NotableDBControl.lua.rej new file mode 100644 index 0000000000..e6bc9b7704 --- /dev/null +++ b/src/Classes/NotableDBControl.lua.rej @@ -0,0 +1,38 @@ +diff a/src/Classes/NotableDBControl.lua b/src/Classes/NotableDBControl.lua (rejected hunks) +@@ -19,8 +19,10 @@ local function IsAnointableNode(node) + end + + ---@class NotableDBControl : ListControl +-local NotableDBClass = newClass("NotableDBControl", "ListControl", function(self, anchor, rect, itemsTab, db, dbType) +- self.ListControl(anchor, rect, 16, "VERTICAL", false) ++local NotableDBClass = newClass("NotableDBControl", "ListControl") ++ ++function NotableDBClass:NotableDBControl(anchor, rect, itemsTab, db, dbType) ++ self:ListControl(anchor, rect, 16, "VERTICAL", false) + self.itemsTab = itemsTab + self.db = db + self.dbType = dbType +@@ -32,18 +34,19 @@ local NotableDBClass = newClass("NotableDBControl", "ListControl", function(self + self.sortDropList = { } + self.sortOrder = { } + self.sortMode = "NAME" +- self.controls.sort = new("DropDownControl", {"BOTTOMLEFT",self,"TOPLEFT"}, {0, -22, 360, 18}, self.sortDropList, function(index, value) ++ self.controls.sort = new("DropDownControl"):DropDownControl({"BOTTOMLEFT",self,"TOPLEFT"}, {0, -22, 360, 18}, self.sortDropList, function(index, value) + self:SetSortMode(value.sortMode) + end) +- self.controls.search = new("EditControl", {"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 258, 18}, "", "Search", "%c", 100, function() ++ self.controls.search = new("EditControl"):EditControl({"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 258, 18}, "", "Search", "%c", 100, function() + self.listBuildFlag = true + end, nil, nil, true) +- self.controls.searchMode = new("DropDownControl", {"LEFT",self.controls.search,"RIGHT"}, {2, 0, 100, 18}, { "Anywhere", "Names", "Modifiers" }, function(index, value) ++ self.controls.searchMode = new("DropDownControl"):DropDownControl({"LEFT",self.controls.search,"RIGHT"}, {2, 0, 100, 18}, { "Anywhere", "Names", "Modifiers" }, function(index, value) + self.listBuildFlag = true + end) + self:BuildSortOrder() + self.listBuildFlag = true +-end) ++ return self ++end + + ---@param node table @The notable node to check + ---@return boolean @Whether the notable matches the type and search filters. diff --git a/src/Classes/NotesTab.lua b/src/Classes/NotesTab.lua index a7dc1fcf8a..3dba394432 100644 --- a/src/Classes/NotesTab.lua +++ b/src/Classes/NotesTab.lua @@ -5,9 +5,13 @@ -- local t_insert = table.insert -local NotesTabClass = newClass("NotesTab", "ControlHost", "Control", function(self, build) - self.ControlHost() - self.Control() +---@class NotesTab: ControlHost, Control +local NotesTabClass = newClass("NotesTab", "ControlHost", "Control") + +---@param build Build +function NotesTabClass:NotesTab(build) + self:ControlHost() + self:Control() self.build = build diff --git a/src/Classes/NotesTab.lua.rej b/src/Classes/NotesTab.lua.rej new file mode 100644 index 0000000000..ca7bb251c4 --- /dev/null +++ b/src/Classes/NotesTab.lua.rej @@ -0,0 +1,52 @@ +diff a/src/Classes/NotesTab.lua b/src/Classes/NotesTab.lua (rejected hunks) +@@ -17,33 +21,34 @@ local NotesTabClass = newClass("NotesTab", "ControlHost", "Control", function(se + local notesDesc = [[^7You can use Ctrl +/- (or Ctrl+Scroll) to zoom in and out and Ctrl+0 to reset. + This field also supports different colors. Using the caret symbol (^) followed by a Hex code or a number (0-9) will set the color. + Below are some common color codes PoB uses: ]] +- self.controls.notesDesc = new("LabelControl", {"TOPLEFT",self,"TOPLEFT"}, {8, 8, 150, 16}, notesDesc) +- self.controls.normal = new("ButtonControl", {"TOPLEFT",self.controls.notesDesc,"TOPLEFT"}, {0, 48, 100, 18}, colorCodes.NORMAL.."NORMAL", function() self:SetColor(colorCodes.NORMAL) end) +- self.controls.magic = new("ButtonControl", {"TOPLEFT",self.controls.normal,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.MAGIC.."MAGIC", function() self:SetColor(colorCodes.MAGIC) end) +- self.controls.rare = new("ButtonControl", {"TOPLEFT",self.controls.magic,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.RARE.."RARE", function() self:SetColor(colorCodes.RARE) end) +- self.controls.unique = new("ButtonControl", {"TOPLEFT",self.controls.rare,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.UNIQUE.."UNIQUE", function() self:SetColor(colorCodes.UNIQUE) end) +- self.controls.fire = new("ButtonControl", {"TOPLEFT",self.controls.normal,"TOPLEFT"}, {0, 18, 100, 18}, colorCodes.FIRE.."FIRE", function() self:SetColor(colorCodes.FIRE) end) +- self.controls.cold = new("ButtonControl", {"TOPLEFT",self.controls.fire,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.COLD.."COLD", function() self:SetColor(colorCodes.COLD) end) +- self.controls.lightning = new("ButtonControl", {"TOPLEFT",self.controls.cold,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.LIGHTNING.."LIGHTNING", function() self:SetColor(colorCodes.LIGHTNING) end) +- self.controls.chaos = new("ButtonControl", {"TOPLEFT",self.controls.lightning,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.CHAOS.."CHAOS", function() self:SetColor(colorCodes.CHAOS) end) +- self.controls.strength = new("ButtonControl", {"TOPLEFT",self.controls.fire,"TOPLEFT"}, {0, 18, 100, 18}, colorCodes.STRENGTH.."STRENGTH", function() self:SetColor(colorCodes.STRENGTH) end) +- self.controls.dexterity = new("ButtonControl", {"TOPLEFT",self.controls.strength,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.DEXTERITY.."DEXTERITY", function() self:SetColor(colorCodes.DEXTERITY) end) +- self.controls.intelligence = new("ButtonControl", {"TOPLEFT",self.controls.dexterity,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.INTELLIGENCE.."INTELLIGENCE", function() self:SetColor(colorCodes.INTELLIGENCE) end) +- self.controls.default = new("ButtonControl", {"TOPLEFT",self.controls.intelligence,"TOPLEFT"}, {120, 0, 100, 18}, "^7DEFAULT", function() self:SetColor("^7") end) ++ self.controls.notesDesc = new("LabelControl"):LabelControl({"TOPLEFT",self,"TOPLEFT"}, {8, 8, 150, 16}, notesDesc) ++ self.controls.normal = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.notesDesc,"TOPLEFT"}, {0, 48, 100, 18}, colorCodes.NORMAL.."NORMAL", function() self:SetColor(colorCodes.NORMAL) end) ++ self.controls.magic = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.normal,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.MAGIC.."MAGIC", function() self:SetColor(colorCodes.MAGIC) end) ++ self.controls.rare = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.magic,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.RARE.."RARE", function() self:SetColor(colorCodes.RARE) end) ++ self.controls.unique = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.rare,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.UNIQUE.."UNIQUE", function() self:SetColor(colorCodes.UNIQUE) end) ++ self.controls.fire = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.normal,"TOPLEFT"}, {0, 18, 100, 18}, colorCodes.FIRE.."FIRE", function() self:SetColor(colorCodes.FIRE) end) ++ self.controls.cold = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.fire,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.COLD.."COLD", function() self:SetColor(colorCodes.COLD) end) ++ self.controls.lightning = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.cold,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.LIGHTNING.."LIGHTNING", function() self:SetColor(colorCodes.LIGHTNING) end) ++ self.controls.chaos = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.lightning,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.CHAOS.."CHAOS", function() self:SetColor(colorCodes.CHAOS) end) ++ self.controls.strength = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.fire,"TOPLEFT"}, {0, 18, 100, 18}, colorCodes.STRENGTH.."STRENGTH", function() self:SetColor(colorCodes.STRENGTH) end) ++ self.controls.dexterity = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.strength,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.DEXTERITY.."DEXTERITY", function() self:SetColor(colorCodes.DEXTERITY) end) ++ self.controls.intelligence = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.dexterity,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.INTELLIGENCE.."INTELLIGENCE", function() self:SetColor(colorCodes.INTELLIGENCE) end) ++ self.controls.default = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.intelligence,"TOPLEFT"}, {120, 0, 100, 18}, "^7DEFAULT", function() self:SetColor("^7") end) + +- self.controls.edit = new("EditControl", {"TOPLEFT",self.controls.fire,"TOPLEFT"}, {0, 48, 0, 0}, "", nil, "^%C\t\n", nil, nil, 16, true) ++ self.controls.edit = new("EditControl"):EditControl({"TOPLEFT",self.controls.fire,"TOPLEFT"}, {0, 48, 0, 0}, "", nil, "^%C\t\n", nil, nil, 16, true) + self.controls.edit.width = function() + return self.width - 16 + end + self.controls.edit.height = function() + return self.height - 128 + end +- self.controls.toggleColorCodes = new("ButtonControl", {"TOPRIGHT",self,"TOPRIGHT"}, {-10, 70, 160, 20}, "Show Color Codes", function() ++ self.controls.toggleColorCodes = new("ButtonControl"):ButtonControl({"TOPRIGHT",self,"TOPRIGHT"}, {-10, 70, 160, 20}, "Show Color Codes", function() + self.showColorCodes = not self.showColorCodes + self:SetShowColorCodes(self.showColorCodes) + end) + self:SelectControl(self.controls.edit) +-end) ++ return self ++end + + function NotesTabClass:SetShowColorCodes(setting) + self.showColorCodes = setting diff --git a/src/Classes/PartyTab.lua b/src/Classes/PartyTab.lua index b0f7983713..6e41497b8b 100644 --- a/src/Classes/PartyTab.lua +++ b/src/Classes/PartyTab.lua @@ -9,15 +9,19 @@ local s_format = string.format local t_insert = table.insert local m_max = math.max -local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(self, build) - self.ControlHost() - self.Control() +---@class PartyTab: ControlHost, Control +local PartyTabClass = newClass("PartyTab", "ControlHost", "Control") + +---@param build Build +function PartyTabClass:PartyTab(build) + self:ControlHost() + self:Control() self.build = build - self.actor = { Aura = { }, Curse = { }, Warcry = { }, Link = { }, modDB = new("ModDB"), output = { } } + self.actor = { Aura = { }, Curse = { }, Warcry = { }, Link = { }, modDB = new("ModDB"):ModDB(), output = { } } self.actor.modDB.actor = self.actor - self.enemyModList = new("ModList") + self.enemyModList = new("ModList"):ModList() self.buffExports = { } self.enableExportBuffs = false @@ -61,7 +65,7 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se All of these effects can be found in the Calcs tab]] - self.controls.notesDesc = new("LabelControl", {"TOPLEFT",self,"TOPLEFT"}, {8, 8, 150, theme.stringHeight}, notesDesc) + self.controls.notesDesc = new("LabelControl"):LabelControl({"TOPLEFT",self,"TOPLEFT"}, {8, 8, 150, theme.stringHeight}, notesDesc) self.controls.notesDesc.width = function() local width = self.width / 2 - 16 if width ~= self.controls.notesDesc.lastWidth then @@ -70,7 +74,7 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se end return width end - self.controls.importCodeHeader = new("LabelControl", {"TOPLEFT",self.controls.notesDesc,"BOTTOMLEFT"}, {0, 32, 0, theme.stringHeight}, "^7Enter a build code/URL below:") + self.controls.importCodeHeader = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.notesDesc,"BOTTOMLEFT"}, {0, 32, 0, theme.stringHeight}, "^7Enter a build code/URL below:") self.controls.importCodeHeader.y = function() return theme.lineCounter(self.controls.notesDesc.label) + 4 end @@ -270,7 +274,7 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se end if partyDestinations[self.controls.importCodeDestination.selIndex] == "All" or partyDestinations[self.controls.importCodeDestination.selIndex] == "EnemyConditions" or partyDestinations[self.controls.importCodeDestination.selIndex] == "EnemyMods" then wipeTable(self.enemyModList) - self.enemyModList = new("ModList") + self.enemyModList = new("ModList"):ModList() self:ParseBuffs(self.enemyModList, self.controls.enemyCond.buf, "EnemyConditions") self:ParseBuffs(self.enemyModList, self.controls.enemyMods.buf, "EnemyMods", self.controls.simpleEnemyMods) end @@ -280,7 +284,7 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se end end - self.controls.importCodeIn = new("EditControl", {"TOPLEFT",self.controls.importCodeHeader,"BOTTOMLEFT"}, {0, 4, 328, theme.buttonHeight}, "", nil, nil, nil, importCodeHandle) + self.controls.importCodeIn = new("EditControl"):EditControl({"TOPLEFT",self.controls.importCodeHeader,"BOTTOMLEFT"}, {0, 4, 328, theme.buttonHeight}, "", nil, nil, nil, importCodeHandle) self.controls.importCodeIn.width = function() return (self.width > 880) and 328 or (self.width / 2 - 100) end @@ -289,13 +293,13 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.importCodeGo.onClick() end end - self.controls.importCodeState = new("LabelControl", {"LEFT",self.controls.importCodeIn,"RIGHT"}, {8, 0, 0, theme.stringHeight}) + self.controls.importCodeState = new("LabelControl"):LabelControl({"LEFT",self.controls.importCodeIn,"RIGHT"}, {8, 0, 0, theme.stringHeight}) self.controls.importCodeState.label = function() return self.importCodeDetail or "" end - self.controls.importCodeDestination = new("DropDownControl", {"TOPLEFT",self.controls.importCodeIn,"BOTTOMLEFT"}, {0, 4, 160, theme.buttonHeight}, partyDestinations) + self.controls.importCodeDestination = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.importCodeIn,"BOTTOMLEFT"}, {0, 4, 160, theme.buttonHeight}, partyDestinations) self.controls.importCodeDestination.tooltipText = "Destination for Import/clear\nCurrently Links Skills do not export" - self.controls.importCodeGo = new("ButtonControl", {"LEFT",self.controls.importCodeDestination,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Import", function() + self.controls.importCodeGo = new("ButtonControl"):ButtonControl({"LEFT",self.controls.importCodeDestination,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Import", function() local importCodeFetching = false if self.importCodeSite and not self.importCodeXML then self.importCodeFetching = true @@ -323,7 +327,7 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.importCodeGo.onClick() end end - self.controls.appendNotReplace = new("CheckBoxControl", {"LEFT",self.controls.importCodeGo,"RIGHT"}, {60, 0, theme.buttonHeight}, "Append", function(state) + self.controls.appendNotReplace = new("CheckBoxControl"):CheckBoxControl({"LEFT",self.controls.importCodeGo,"RIGHT"}, {60, 0, theme.buttonHeight}, "Append", function(state) end, "This sets the import button to append to the current party lists instead of replacing them (curses will still replace)", false) self.controls.appendNotReplace.x = function() return (self.width > theme.widthThreshold1) and 60 or (-276) @@ -332,36 +336,36 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se return (self.width > theme.widthThreshold1) and 0 or 24 end - self.controls.clear = new("ButtonControl", {"LEFT",self.controls.appendNotReplace,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Clear", function() + self.controls.clear = new("ButtonControl"):ButtonControl({"LEFT",self.controls.appendNotReplace,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Clear", function() clearInputText() wipeTable(self.enemyModList) - self.enemyModList = new("ModList") + self.enemyModList = new("ModList"):ModList() self.build.buildFlag = true end) self.controls.clear.tooltipText = "^7Clears all the party tab imported data" - self.controls.ShowAdvanceTools = new("CheckBoxControl", {"TOPLEFT",self.controls.importCodeDestination,"BOTTOMLEFT"}, {140, 4, theme.buttonHeight}, "^7Show Advanced Info", function(state) + self.controls.ShowAdvanceTools = new("CheckBoxControl"):CheckBoxControl({"TOPLEFT",self.controls.importCodeDestination,"BOTTOMLEFT"}, {140, 4, theme.buttonHeight}, "^7Show Advanced Info", function(state) end, "This shows the advanced info like what stats each aura/curse etc are adding, as well as enables the ability to edit them without a re-export\nDo not edit any boxes unless you know what you are doing, use copy/paste or import instead", false) self.controls.ShowAdvanceTools.y = function() return (self.width > theme.widthThreshold1) and 4 or 28 end - self.controls.removeEffects = new("ButtonControl", {"LEFT",self.controls.ShowAdvanceTools,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Disable Party Effects", function() + self.controls.removeEffects = new("ButtonControl"):ButtonControl({"LEFT",self.controls.ShowAdvanceTools,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Disable Party Effects", function() wipeTable(self.actor) wipeTable(self.enemyModList) - self.actor = { Aura = {}, Curse = {}, Warcry = { }, Link = {}, modDB = new("ModDB"), output = { } } + self.actor = { Aura = {}, Curse = {}, Warcry = { }, Link = {}, modDB = new("ModDB"):ModDB(), output = { } } self.actor.modDB.actor = self.actor - self.enemyModList = new("ModList") + self.enemyModList = new("ModList"):ModList() self.build.buildFlag = true end) self.controls.removeEffects.tooltipText = "^7Removes the effects of the supports, without removing the data\nUse \"rebuild all\" to apply the effects again" - self.controls.rebuild = new("ButtonControl", {"LEFT",self.controls.removeEffects,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "^7Rebuild All", function() + self.controls.rebuild = new("ButtonControl"):ButtonControl({"LEFT",self.controls.removeEffects,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "^7Rebuild All", function() wipeTable(self.actor) wipeTable(self.enemyModList) - self.actor = { Aura = {}, Curse = {}, Warcry = { }, Link = {}, modDB = new("ModDB"), output = { } } + self.actor = { Aura = {}, Curse = {}, Warcry = { }, Link = {}, modDB = new("ModDB"):ModDB(), output = { } } self.actor.modDB.actor = self.actor - self.enemyModList = new("ModList") + self.enemyModList = new("ModList"):ModList() self:ParseBuffs(self.actor["modDB"], self.controls.editPartyMemberStats.buf, "PartyMemberStats", self.actor["output"]) self:ParseBuffs(self.actor["Aura"], self.controls.editAuras.buf, "Aura", self.controls.simpleAuras) self:ParseBuffs(self.actor["Curse"], self.controls.editCurses.buf, "Curse", self.controls.simpleCurses) @@ -379,11 +383,11 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se return (self.width > theme.widthThreshold1) and 0 or 24 end - self.controls.editAurasLabel = new("LabelControl", {"TOPLEFT",self.controls.ShowAdvanceTools,"TOPLEFT"}, {-140, 40, 0, theme.stringHeight}, "^7Auras") + self.controls.editAurasLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.ShowAdvanceTools,"TOPLEFT"}, {-140, 40, 0, theme.stringHeight}, "^7Auras") self.controls.editAurasLabel.y = function() return 36 + ((self.width <= theme.widthThreshold1) and 24 or 0) end - self.controls.editAuras = new("EditControl", {"TOPLEFT",self.controls.editAurasLabel,"TOPLEFT"}, {0, 18, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) + self.controls.editAuras = new("EditControl"):EditControl({"TOPLEFT",self.controls.editAurasLabel,"TOPLEFT"}, {0, 18, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) self.controls.editAuras.width = function() return self.width / 2 - 16 end @@ -394,16 +398,16 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.editAuras.shown = function() return self.controls.ShowAdvanceTools.state end - self.controls.simpleAuras = new("LabelControl", {"TOPLEFT",self.controls.editAurasLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") + self.controls.simpleAuras = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.editAurasLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") self.controls.simpleAuras.shown = function() return not self.controls.ShowAdvanceTools.state end - self.controls.editWarcriesLabel = new("LabelControl", {"TOPLEFT",self.controls.editAurasLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Warcry Skills") + self.controls.editWarcriesLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.editAurasLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Warcry Skills") self.controls.editWarcriesLabel.y = function() return self.controls.ShowAdvanceTools.state and (self.controls.editAuras.height() + 8) or (theme.lineCounter(self.controls.simpleAuras.label) + 4) end - self.controls.editWarcries = new("EditControl", {"TOPLEFT",self.controls.editWarcriesLabel,"TOPLEFT"}, {0, 18, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) + self.controls.editWarcries = new("EditControl"):EditControl({"TOPLEFT",self.controls.editWarcriesLabel,"TOPLEFT"}, {0, 18, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) self.controls.editWarcries.width = function() return self.width / 2 - 16 end @@ -413,16 +417,16 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.editWarcries.shown = function() return self.controls.ShowAdvanceTools.state end - self.controls.simpleWarcries = new("LabelControl", {"TOPLEFT",self.controls.editWarcriesLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") + self.controls.simpleWarcries = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.editWarcriesLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") self.controls.simpleWarcries.shown = function() return not self.controls.ShowAdvanceTools.state end - self.controls.editLinksLabel = new("LabelControl", {"TOPLEFT",self.controls.editWarcriesLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Link Skills") + self.controls.editLinksLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.editWarcriesLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Link Skills") self.controls.editLinksLabel.y = function() return self.controls.ShowAdvanceTools.state and (self.controls.editWarcries.height() + 8) or (theme.lineCounter(self.controls.simpleWarcries.label) + 4) end - self.controls.editLinks = new("EditControl", {"TOPLEFT",self.controls.editLinksLabel,"TOPLEFT"}, {0, 18, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) + self.controls.editLinks = new("EditControl"):EditControl({"TOPLEFT",self.controls.editLinksLabel,"TOPLEFT"}, {0, 18, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) self.controls.editLinks.width = function() return self.width / 2 - 16 end @@ -432,13 +436,13 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.editLinks.shown = function() return self.controls.ShowAdvanceTools.state end - self.controls.simpleLinks = new("LabelControl", {"TOPLEFT",self.controls.editLinksLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") + self.controls.simpleLinks = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.editLinksLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") self.controls.simpleLinks.shown = function() return not self.controls.ShowAdvanceTools.state end - self.controls.editPartyMemberStatsLabel = new("LabelControl", {"TOPLEFT",self.controls.notesDesc,"TOPRIGHT"}, {8, 0, 0, theme.stringHeight}, "^7Party Member Stats") - self.controls.editPartyMemberStats = new("EditControl", {"TOPLEFT",self.controls.editPartyMemberStatsLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) + self.controls.editPartyMemberStatsLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.notesDesc,"TOPRIGHT"}, {8, 0, 0, theme.stringHeight}, "^7Party Member Stats") + self.controls.editPartyMemberStats = new("EditControl"):EditControl({"TOPLEFT",self.controls.editPartyMemberStatsLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) self.controls.editPartyMemberStats.width = function() return self.width / 2 - 16 end @@ -449,11 +453,11 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se return self.controls.ShowAdvanceTools.state end - self.controls.enemyCondLabel = new("LabelControl", {"TOPLEFT",self.controls.editPartyMemberStatsLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Enemy Conditions") + self.controls.enemyCondLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.editPartyMemberStatsLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Enemy Conditions") self.controls.enemyCondLabel.y = function() return self.controls.ShowAdvanceTools.state and (self.controls.editPartyMemberStats.height() + 8) or 4 end - self.controls.enemyCond = new("EditControl", {"TOPLEFT",self.controls.enemyCondLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) + self.controls.enemyCond = new("EditControl"):EditControl({"TOPLEFT",self.controls.enemyCondLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) self.controls.enemyCond.width = function() return self.width / 2 - 16 end @@ -463,16 +467,16 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.enemyCond.shown = function() return self.controls.ShowAdvanceTools.state end - self.controls.simpleEnemyCond = new("LabelControl", {"TOPLEFT",self.controls.enemyCondLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "^7---------------------------\n") + self.controls.simpleEnemyCond = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.enemyCondLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "^7---------------------------\n") self.controls.simpleEnemyCond.shown = function() return not self.controls.ShowAdvanceTools.state end - self.controls.enemyModsLabel = new("LabelControl", {"TOPLEFT",self.controls.enemyCondLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Enemy Modifiers") + self.controls.enemyModsLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.enemyCondLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Enemy Modifiers") self.controls.enemyModsLabel.y = function() return self.controls.ShowAdvanceTools.state and (self.controls.enemyCond.height() + 8) or (theme.lineCounter(self.controls.simpleEnemyCond.label) + 4) end - self.controls.enemyMods = new("EditControl", {"TOPLEFT",self.controls.enemyModsLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) + self.controls.enemyMods = new("EditControl"):EditControl({"TOPLEFT",self.controls.enemyModsLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) self.controls.enemyMods.width = function() return self.width / 2 - 16 end @@ -482,16 +486,16 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.enemyMods.shown = function() return self.controls.ShowAdvanceTools.state end - self.controls.simpleEnemyMods = new("LabelControl", {"TOPLEFT",self.controls.enemyModsLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "\n") + self.controls.simpleEnemyMods = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.enemyModsLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "\n") self.controls.simpleEnemyMods.shown = function() return not self.controls.ShowAdvanceTools.state end - self.controls.editCursesLabel = new("LabelControl", {"TOPLEFT",self.controls.enemyModsLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Curses") + self.controls.editCursesLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.enemyModsLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Curses") self.controls.editCursesLabel.y = function() return self.controls.ShowAdvanceTools.state and (self.controls.enemyMods.height() + 8) or (theme.lineCounter(self.controls.simpleEnemyMods.label) + 4) end - self.controls.editCurses = new("EditControl", {"TOPLEFT",self.controls.editCursesLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) + self.controls.editCurses = new("EditControl"):EditControl({"TOPLEFT",self.controls.editCursesLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) self.controls.editCurses.width = function() return self.width / 2 - 16 end @@ -501,12 +505,13 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.editCurses.shown = function() return self.controls.ShowAdvanceTools.state end - self.controls.simpleCurses = new("LabelControl", {"TOPLEFT",self.controls.editCursesLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") + self.controls.simpleCurses = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.editCursesLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") self.controls.simpleCurses.shown = function() return not self.controls.ShowAdvanceTools.state end self:SelectControl(self.controls.editAuras) -end) + return self +end function PartyTabClass:Load(xml, fileName) for _, node in ipairs(xml) do @@ -842,7 +847,7 @@ function PartyTabClass:ParseBuffs(list, buf, buffType, label) end if not listElement[currentName] then listElement[currentName] = { - modList = new("ModList"), + modList = new("ModList"):ModList(), effectMult = currentEffect } if isMark then @@ -851,7 +856,7 @@ function PartyTabClass:ParseBuffs(list, buf, buffType, label) elseif listElement[currentName].effectMult ~= currentEffect then if listElement[currentName].effectMult < currentEffect then listElement[currentName] = { - modList = new("ModList"), + modList = new("ModList"):ModList(), effectMult = currentEffect } else diff --git a/src/Classes/PassiveMasteryControl.lua b/src/Classes/PassiveMasteryControl.lua index fb8b2f3580..a3f9e054ff 100644 --- a/src/Classes/PassiveMasteryControl.lua +++ b/src/Classes/PassiveMasteryControl.lua @@ -9,20 +9,23 @@ local m_min = math.min local m_max = math.max local m_floor = math.floor ---constructor -local PassiveMasteryControlClass = newClass("PassiveMasteryControl", "ListControl", function(self, anchor, rect, list, treeTab, node, saveButton) +---@class PassiveMasteryControl: ListControl +local PassiveMasteryControlClass = newClass("PassiveMasteryControl", "ListControl") + +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, false, false, self.list) self.treeTab = treeTab self.treeView = treeTab.viewer self.node = node self.selIndex = nil self.saveButton = saveButton -end) + return self +end function PassiveMasteryControlClass:Draw(viewPort) self.ListControl.Draw(self, viewPort) diff --git a/src/Classes/PassiveSpec.lua b/src/Classes/PassiveSpec.lua index ffed6f6ff2..0622c668cb 100644 --- a/src/Classes/PassiveSpec.lua +++ b/src/Classes/PassiveSpec.lua @@ -2564,12 +2564,12 @@ end --- Adds a line to or replaces a node given a line to add/replace with --- @param node table The node to replace/add to --- @param sd string The line being parsed and added ---- @param replacement boolean true to replace the node with the new mod, false to simply add it +--- @param replacement? boolean true to replace the node with the new mod, false to simply add it function PassiveSpecClass:NodeAdditionOrReplacementFromString(node,sd,replacement) local addition = {} addition.sd = {sd} addition.mods = { } - addition.modList = new("ModList") + addition.modList = new("ModList"):ModList() addition.modKey = "" local i = 1 while addition.sd[i] do @@ -2640,7 +2640,7 @@ function PassiveSpecClass:NodeAdditionOrReplacementFromString(node,sd,replacemen node.mods = tableConcat(node.mods, addition.mods) node.modKey = node.modKey .. addition.modKey end - local modList = new("ModList") + local modList = new("ModList"):ModList() modList:AddList(addition.modList) if not replacement then modList:AddList(node.modList) diff --git a/src/Classes/PassiveSpec.lua.rej b/src/Classes/PassiveSpec.lua.rej new file mode 100644 index 0000000000..24a536ef9f --- /dev/null +++ b/src/Classes/PassiveSpec.lua.rej @@ -0,0 +1,34 @@ +diff a/src/Classes/PassiveSpec.lua b/src/Classes/PassiveSpec.lua (rejected hunks) +@@ -16,8 +16,11 @@ local b_rshift = bit.rshift + local band = bit.band + local bor = bit.bor + +-local PassiveSpecClass = newClass("PassiveSpec", "UndoHandler", function(self, build, treeVersion, convert) +- self.UndoHandler() ++---@class PassiveSpec: UndoHandler ++local PassiveSpecClass = newClass("PassiveSpec", "UndoHandler") ++ ++function PassiveSpecClass:PassiveSpec(build, treeVersion, convert) ++ self:UndoHandler() + + self.build = build + +@@ -25,7 +28,8 @@ local PassiveSpecClass = newClass("PassiveSpec", "UndoHandler", function(self, b + self:Init(treeVersion, convert) + + self:SelectClass(0) +-end) ++ return self ++end + + function PassiveSpecClass:Init(treeVersion, convert) + self.treeVersion = treeVersion +@@ -1621,7 +1625,7 @@ function PassiveSpecClass:ReplaceNode(old, newNode) + old.name = newNode.name + old.mods = newNode.mods + old.modKey = newNode.modKey +- old.modList = new("ModList") ++ old.modList = new("ModList"):ModList() + old.modList:AddList(newNode.modList) + old.sprites = newNode.sprites + old.effectSprites = newNode.effectSprites diff --git a/src/Classes/PassiveSpecListControl.lua b/src/Classes/PassiveSpecListControl.lua index 50b201044a..00d59aa910 100644 --- a/src/Classes/PassiveSpecListControl.lua +++ b/src/Classes/PassiveSpecListControl.lua @@ -63,7 +63,7 @@ function PassiveSpecListClass:RenameSpec(spec, popupTitle, addOnName) main:ClosePopup() end) controls.save.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() main:ClosePopup() end) -- main:OpenPopup(370, 100, spec.title and "Rename" or "Set Name", controls, "save", "edit") diff --git a/src/Classes/PassiveSpecListControl.lua.rej b/src/Classes/PassiveSpecListControl.lua.rej new file mode 100644 index 0000000000..888924a70b --- /dev/null +++ b/src/Classes/PassiveSpecListControl.lua.rej @@ -0,0 +1,65 @@ +diff a/src/Classes/PassiveSpecListControl.lua b/src/Classes/PassiveSpecListControl.lua (rejected hunks) +@@ -7,11 +7,14 @@ local t_insert = table.insert + local t_remove = table.remove + local m_max = math.max + +-local PassiveSpecListClass = newClass("PassiveSpecListControl", "ListControl", function(self, anchor, rect, treeTab) +- self.ListControl(anchor, rect, 16, "VERTICAL", true, treeTab.specList) ++---@class PassiveSpecListControl: ListControl ++local PassiveSpecListClass = newClass("PassiveSpecListControl", "ListControl") ++ ++function PassiveSpecListClass:PassiveSpecListControl(anchor, rect, treeTab) ++ self:ListControl(anchor, rect, 16, "VERTICAL", true, treeTab.specList) + self.treeTab = treeTab +- self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() +- local newSpec = new("PassiveSpec", treeTab.build, self.selValue.treeVersion) ++ self.controls.copy = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() ++ local newSpec = new("PassiveSpec"):PassiveSpec(treeTab.build, self.selValue.treeVersion) + newSpec.title = self.selValue.title + newSpec.jewels = copyTable(self.selValue.jewels) + newSpec:RestoreUndoState(self.selValue:CreateUndoState()) +@@ -21,35 +24,36 @@ local PassiveSpecListClass = newClass("PassiveSpecListControl", "ListControl", f + self.controls.copy.enabled = function() + return self.selValue ~= nil + end +- self.controls.delete = new("ButtonControl", {"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() ++ self.controls.delete = new("ButtonControl"):ButtonControl({"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() + self:OnSelDelete(self.selIndex, self.selValue) + end) + self.controls.delete.enabled = function() + return self.selValue ~= nil and #self.list > 1 + end +- self.controls.rename = new("ButtonControl", {"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() ++ self.controls.rename = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() + self:RenameSpec(self.selValue, "Rename Tree") + end) + self.controls.rename.enabled = function() + return self.selValue ~= nil + end +- self.controls.new = new("ButtonControl", {"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() +- local newSpec = new("PassiveSpec", treeTab.build, latestTreeVersion) ++ self.controls.new = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() ++ local newSpec = new("PassiveSpec"):PassiveSpec(treeTab.build, latestTreeVersion) + newSpec:SelectClass(treeTab.build.spec.curClassId) + newSpec:SelectAscendClass(treeTab.build.spec.curAscendClassId) + newSpec:SelectSecondaryAscendClass(treeTab.build.spec.curSecondaryAscendClassId) + self:RenameSpec(newSpec, "New Tree", true) + end) + self:UpdateItemsTabPassiveTreeDropdown() +-end) ++ return self ++end + + function PassiveSpecListClass:RenameSpec(spec, title, addOnName) + local controls = { } +- controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter name for this passive tree:") +- controls.edit = new("EditControl", nil, {0, 40, 350, 20}, spec.title, nil, nil, 100, function(buf) ++ controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter name for this passive tree:") ++ controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, spec.title, nil, nil, 100, function(buf) + controls.save.enabled = buf:match("%S") + end) +- controls.save = new("ButtonControl", nil, {-45, 70, 80, 20}, "Save", function() ++ controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Save", function() + spec.title = controls.edit.buf + self.treeTab.modFlag = true + if addOnName then diff --git a/src/Classes/PassiveTree.lua.rej b/src/Classes/PassiveTree.lua.rej new file mode 100644 index 0000000000..5001fcbfb7 --- /dev/null +++ b/src/Classes/PassiveTree.lua.rej @@ -0,0 +1,50 @@ +diff a/src/Classes/PassiveTree.lua b/src/Classes/PassiveTree.lua (rejected hunks) +@@ -49,7 +49,29 @@ local function getFile(URL) + return #page > 0 and page + end + +-local PassiveTreeClass = newClass("PassiveTree", function(self, treeVersion) ++---@class PassiveTreeGroup ++---@field x number ++---@field y number ++---@field orbits integer[] ++---@field nodes string[] ++---@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, any> ++---@field jewelSlots integer[] ++---@field min_x integer ++---@field min_y integer ++---@field max_x integer ++---@field max_y integer ++---@field constants table ++---@field points table ++local PassiveTreeClass = newClass("PassiveTree") ++ ++function PassiveTreeClass:PassiveTree(treeVersion) + self.treeVersion = treeVersion + local versionNum = treeVersions[treeVersion].num + +@@ -764,14 +786,15 @@ local PassiveTreeClass = newClass("PassiveTree", function(self, treeVersion) + if treeVersion == latestTreeVersion then + buildTreeDependentUniques(self) + end +-end) ++ return self ++end + + function PassiveTreeClass:ProcessStats(node, startIndex) + startIndex = startIndex or 1 + if startIndex == 1 then + node.modKey = "" + node.mods = { } +- node.modList = new("ModList") ++ node.modList = new("ModList"):ModList() + end + + if not node.sd then diff --git a/src/Classes/PassiveTreeView.lua b/src/Classes/PassiveTreeView.lua index 8c1aa57644..77f5440444 100644 --- a/src/Classes/PassiveTreeView.lua +++ b/src/Classes/PassiveTreeView.lua @@ -50,7 +50,8 @@ local PassiveTreeViewClass = newClass("PassiveTreeView", function(self) self.searchStrResults = {} self.showStatDifferences = true self.hoverNode = nil -end) + return self +end function PassiveTreeViewClass:Load(xml, fileName) if xml.attrib.zoomLevel then @@ -156,6 +157,7 @@ function PassiveTreeViewClass:GetCompareNodeColor(node, compareNode, spec, build return nodeDefaultColor end +---@param build Build function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) local spec = build.spec local tree = spec.tree diff --git a/src/Classes/PassiveTreeView.lua.rej b/src/Classes/PassiveTreeView.lua.rej new file mode 100644 index 0000000000..4d695de861 --- /dev/null +++ b/src/Classes/PassiveTreeView.lua.rej @@ -0,0 +1,24 @@ +diff a/src/Classes/PassiveTreeView.lua b/src/Classes/PassiveTreeView.lua (rejected hunks) +@@ -25,7 +25,10 @@ local function isAbyssConquered(node) + return conqueror and conqueror.type and conqueror.type:match("^abyss_") + end + +-local PassiveTreeViewClass = newClass("PassiveTreeView", function(self) ++---@class PassiveTreeView ++local PassiveTreeViewClass = newClass("PassiveTreeView") ++ ++function PassiveTreeViewClass:PassiveTreeView() + self.ring = NewImageHandle() + self.ring:Load("Assets/ring.png", "CLAMP") + self.highlightRing = NewImageHandle() +@@ -64,8 +67,8 @@ local PassiveTreeViewClass = newClass("PassiveTreeView", function(self) + self.kalguur2 = NewImageHandle() + self.kalguur2:Load("TreeData/PassiveSkillScreenKalguuranJewelCircle2.png", "CLAMP") + +- self.tooltip = new("Tooltip") +- self.skillTooltip = new("Tooltip") ++ self.tooltip = new("Tooltip"):Tooltip() ++ self.skillTooltip = new("Tooltip"):Tooltip() + + self.zoomLevel = 3 + self.zoom = 1.2 ^ self.zoomLevel diff --git a/src/Classes/PathControl.lua b/src/Classes/PathControl.lua index 4d62bef272..af32ccbbb5 100644 --- a/src/Classes/PathControl.lua +++ b/src/Classes/PathControl.lua @@ -6,16 +6,20 @@ local ipairs = ipairs local t_insert = table.insert -local PathClass = newClass("PathControl", "Control", "ControlHost", "UndoHandler", function(self, anchor, rect, basePath, subPath, onChange) - self.Control(anchor, rect) - self.ControlHost() - self.UndoHandler() +---@class PathControl +local PathClass = newClass("PathControl", "Control", "ControlHost", "UndoHandler") + +function PathClass:PathControl(anchor, rect, basePath, subPath, onChange) + self:Control(anchor, rect) + self:ControlHost() + self:UndoHandler() self.basePath = basePath self.baseName = basePath:match("([^/]+)/$") or "Base" self:SetSubPath(subPath or "") self:ResetUndo() self.onChange = onChange -end) + return self +end function PathClass:SetSubPath(subPath, noUndo) if subPath == self.subPath then @@ -33,7 +37,7 @@ function PathClass:SetSubPath(subPath, noUndo) for index, folder in ipairs(self.folderList) do local button = self.controls["folder"..i] if not button then - button = new("ButtonControl", {"LEFT",self,"LEFT"}, {0, 0, 0, self.height - 4}) + button = new("ButtonControl"):ButtonControl({"LEFT",self,"LEFT"}, {0, 0, 0, self.height - 4}) self.controls["folder"..i] = button end button.shown = true diff --git a/src/Classes/PoBArchivesProvider.lua b/src/Classes/PoBArchivesProvider.lua index c2b6ab2a52..d2d694b774 100644 --- a/src/Classes/PoBArchivesProvider.lua +++ b/src/Classes/PoBArchivesProvider.lua @@ -9,17 +9,19 @@ local dkjson = require "dkjson" local archivesUrl = 'https://pobarchives.com' -local PoBArchivesProviderClass = newClass("PoBArchivesProvider", "ExtBuildListProvider", - function(self, mode) - if mode == "builds" then - self.ExtBuildListProvider({"Trending", "Latest"}) - else - self.ExtBuildListProvider({"Similar Builds"}) - end - self.buildList = {} - self.mode = mode +---@class PoBArchivesProvider: ExtBuildListProvider +local PoBArchivesProviderClass = newClass("PoBArchivesProvider", "ExtBuildListProvider") + +function PoBArchivesProviderClass:PoBArchivesProvider(mode) + if mode == "builds" then + self:ExtBuildListProvider({"Trending", "Latest"}) + else + self:ExtBuildListProvider({"Similar Builds"}) end -) + self.buildList = {} + self.mode = mode + return self +end function PoBArchivesProviderClass:GetApiUrl() if self.importCode then diff --git a/src/Classes/PoEAPI.lua.rej b/src/Classes/PoEAPI.lua.rej new file mode 100644 index 0000000000..6fdabcee7e --- /dev/null +++ b/src/Classes/PoEAPI.lua.rej @@ -0,0 +1,26 @@ +diff a/src/Classes/PoEAPI.lua b/src/Classes/PoEAPI.lua (rejected hunks) +@@ -11,17 +11,21 @@ local scopesOAuth = { + + local filename = "poe_api_response.json" + +-local PoEAPIClass = newClass("PoEAPI", function(self, authToken, refreshToken, tokenExpiry) ++---@class PoEAPI ++local PoEAPIClass = newClass("PoEAPI") ++ ++function PoEAPIClass:PoEAPI(authToken, refreshToken, tokenExpiry) + self.retries = 0 + self.authToken = authToken + self.refreshToken = refreshToken + self.tokenExpiry = tokenExpiry or 0 + self.baseUrl = "https://api.pathofexile.com" +- self.rateLimiter = new("TradeQueryRateLimiter") ++ self.rateLimiter = new("TradeQueryRateLimiter"):TradeQueryRateLimiter() + self.tokenHasBeenValidated = false + + self.ERROR_NO_AUTH = "No auth token" +-end) ++ return self ++end + + -- performs a basic check on the validity of the current login by refreshing the + -- token if necessary. if a refresh is attempted and fails, the login details diff --git a/src/Classes/PopupDialog.lua b/src/Classes/PopupDialog.lua index 223059def9..1e54e8c695 100644 --- a/src/Classes/PopupDialog.lua +++ b/src/Classes/PopupDialog.lua @@ -5,10 +5,13 @@ -- local m_floor = math.floor -local PopupDialogClass = newClass("PopupDialog", "ControlHost", "Control", function(self, width, height, title, controls, enterControl, defaultControl, +---@class PopupDialog: ControlHost, Control +local PopupDialogClass = newClass("PopupDialog", "ControlHost", "Control") + +function PopupDialogClass:PopupDialog(width, height, title, controls, enterControl, defaultControl, escapeControl, scrollBarFunc, resizeFunc) - self.ControlHost() - self.Control(nil, {0, 0, width, height}) + self:ControlHost() + self:Control(nil, {0, 0, width, height}) self.x = function() return m_floor((main.screenW - width) / 2) end @@ -35,7 +38,8 @@ local PopupDialogClass = newClass("PopupDialog", "ControlHost", "Control", funct self.scrollBarFunc = scrollBarFunc -- allow resizing of popup self.resizeFunc = resizeFunc -end) + return self +end function PopupDialogClass:Draw(viewPort) local x, y = self:GetPos() diff --git a/src/Classes/PowerReportListControl.lua b/src/Classes/PowerReportListControl.lua index d33ed88456..0e8434129f 100644 --- a/src/Classes/PowerReportListControl.lua +++ b/src/Classes/PowerReportListControl.lua @@ -8,8 +8,11 @@ local t_insert = table.insert local t_remove = table.remove local t_sort = table.sort -local PowerReportListClass = newClass("PowerReportListControl", "ListControl", function(self, anchor, rect, nodeSelectCallback) - self.ListControl(anchor, rect, 16, "VERTICAL", false) +---@class PowerReportListControl: ListControl +local PowerReportListClass = newClass("PowerReportListControl", "ListControl") + +function PowerReportListClass:PowerReportListControl(anchor, rect, nodeSelectCallback) + self:ListControl(anchor, rect, 16, "VERTICAL", false) local width = rect[3] self.powerColumn = { width = width * 0.16, label = "", sortable = true } @@ -26,7 +29,7 @@ local PowerReportListClass = newClass("PowerReportListControl", "ListControl", f self.allocated = false self.label = "Building Tree..." - self.controls.filterSelect = new("DropDownControl", {"BOTTOMRIGHT", self, "TOPRIGHT"}, {0, -2, 200, 20}, + self.controls.filterSelect = new("DropDownControl"):DropDownControl({"BOTTOMRIGHT", self, "TOPRIGHT"}, {0, -2, 200, 20}, { "Show Unallocated", "Show Unallocated & Clusters", "Show Allocated" }, function(index, value) self.showClusters = index == 2 diff --git a/src/Classes/PowerReportListControl.lua.rej b/src/Classes/PowerReportListControl.lua.rej new file mode 100644 index 0000000000..b0ebce0248 --- /dev/null +++ b/src/Classes/PowerReportListControl.lua.rej @@ -0,0 +1,17 @@ +diff a/src/Classes/PowerReportListControl.lua b/src/Classes/PowerReportListControl.lua (rejected hunks) +@@ -35,12 +38,13 @@ local PowerReportListClass = newClass("PowerReportListControl", "ListControl", f + self:ReList() + self:ReSort(3) -- Sort by power + end) +- self.controls.masteryCheck = new("CheckBoxControl", {"RIGHT", self.controls.filterSelect, "LEFT"}, {-120, 0, 18}, "Show Masteries:", function(state) ++ self.controls.masteryCheck = new("CheckBoxControl"):CheckBoxControl({"RIGHT", self.controls.filterSelect, "LEFT"}, {-120, 0, 18}, "Show Masteries:", function(state) + self.showMasteries = state + self:ReList() + self:ReSort(3) -- Sort by power + end, nil, true) +-end) ++ return self ++end + + function PowerReportListClass:SetReport(stat, report) + self.powerColumn.label = stat and stat.label or "" diff --git a/src/Classes/RectangleOutlineControl.lua b/src/Classes/RectangleOutlineControl.lua index 8b8b0b9d47..d01a58d814 100644 --- a/src/Classes/RectangleOutlineControl.lua +++ b/src/Classes/RectangleOutlineControl.lua @@ -3,11 +3,15 @@ -- Class: RectangleOutline Control -- Simple Outline Only Rectangle control -- -local RectangleOutlineClass = newClass("RectangleOutlineControl", "Control", function(self, anchor, rect, colors, stroke) - self.Control(anchor, rect) +---@class RectangleOutlineControl: Control +local RectangleOutlineClass = newClass("RectangleOutlineControl", "Control") + +function RectangleOutlineClass:RectangleOutlineControl(anchor, rect, colors, stroke) + self:Control(anchor, rect) self.stroke = stroke or 1 self.colors = colors or { 1, 1, 1 } -end) + return self +end function RectangleOutlineClass:Draw() local x, y = self:GetPos() diff --git a/src/Classes/ResizableEditControl.lua b/src/Classes/ResizableEditControl.lua index 66a0402e3f..4f5145fc3b 100644 --- a/src/Classes/ResizableEditControl.lua +++ b/src/Classes/ResizableEditControl.lua @@ -6,14 +6,17 @@ local m_max = math.max local m_min = math.min -local ResizableEditClass = newClass("ResizableEditControl", "EditControl", function(self, anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) - self.EditControl(anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) +---@class ResizableEditControl: EditControl +local ResizableEditClass = newClass("ResizableEditControl", "EditControl") + +function ResizableEditClass:ResizableEditControl(anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) + self:EditControl(anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) local x, y, width, height, minWidth, minHeight, maxWidth, maxHeight = unpack(rect) self.minHeight = minHeight or height self.maxHeight = maxHeight or height self.minWidth = minWidth or width self.maxWidth = maxWidth or width - self.controls.draggerHeight = new("DraggerControl", {"BOTTOMRIGHT", self, "BOTTOMRIGHT"}, {7, 7, 14, 14}, "//", nil, nil, function (position) + self.controls.draggerHeight = new("DraggerControl"):DraggerControl({"BOTTOMRIGHT", self, "BOTTOMRIGHT"}, {7, 7, 14, 14}, "//", nil, nil, function (position) -- onRightClick if (self.height ~= self.minHeight) or (self.width ~= self.minWidth) then self:SetWidth(self.minWidth) @@ -24,7 +27,9 @@ local ResizableEditClass = newClass("ResizableEditControl", "EditControl", funct end end) self.protected = false -end) + return self +end + function ResizableEditClass:Draw(viewPort, noTooltip) self:SetBoundedDrag(self) self.EditControl:Draw(viewPort, noTooltip) diff --git a/src/Classes/ScrollBarControl.lua b/src/Classes/ScrollBarControl.lua index 7dfc416e9e..145fb94bfd 100644 --- a/src/Classes/ScrollBarControl.lua +++ b/src/Classes/ScrollBarControl.lua @@ -8,8 +8,11 @@ local m_max = math.max local m_ceil = math.ceil local m_floor = math.floor -local ScrollBarClass = newClass("ScrollBarControl", "Control", function(self, anchor, rect, step, dir, autoHide) - self.Control(anchor, rect) +---@class ScrollBarControl: Control +local ScrollBarClass = newClass("ScrollBarControl", "Control") + +function ScrollBarClass:ScrollBarControl(anchor, rect, step, dir, autoHide) + self:Control(anchor, rect) self.step = step or self.width * 2 self.dir = dir or "VERTICAL" self.offset = 0 @@ -19,7 +22,8 @@ local ScrollBarClass = newClass("ScrollBarControl", "Control", function(self, an return self.enabled end end -end) + return self +end function ScrollBarClass:SetContentDimension(conDim, viewDim) self.conDim = conDim diff --git a/src/Classes/SearchHost.lua.rej b/src/Classes/SearchHost.lua.rej new file mode 100644 index 0000000000..9de4aefebe --- /dev/null +++ b/src/Classes/SearchHost.lua.rej @@ -0,0 +1,21 @@ +diff a/src/Classes/SearchHost.lua b/src/Classes/SearchHost.lua (rejected hunks) +@@ -4,13 +4,17 @@ + -- Search host + -- + +-local SearchHostClass = newClass("SearchHost", function(self, listAccessor, valueAccessor, ignoreOrder) ++---@class SearchHost ++local SearchHostClass = newClass("SearchHost") ++ ++function SearchHostClass:SearchHost(listAccessor, valueAccessor, ignoreOrder) + self.searchListAccessor = listAccessor + self.valueAccessor = valueAccessor + self.searchTerm = "" + self.searchInfos = {} + self.ignoreOrder = ignoreOrder or false +-end) ++ return self ++end + + local function splitWords(s) + local words = {} diff --git a/src/Classes/SectionControl.lua b/src/Classes/SectionControl.lua index 45e1498d2e..e0acb6fd21 100644 --- a/src/Classes/SectionControl.lua +++ b/src/Classes/SectionControl.lua @@ -4,10 +4,14 @@ -- Section box with label -- -local SectionClass = newClass("SectionControl", "Control", function(self, anchor, rect, label) - self.Control(anchor, rect) +---@class SectionControl: Control +local SectionClass = newClass("SectionControl", "Control") + +function SectionClass:SectionControl(anchor, rect, label) + self:Control(anchor, rect) self.label = label -end) + return self +end function SectionClass:Draw() local x, y = self:GetPos() diff --git a/src/Classes/SharedItemListControl.lua b/src/Classes/SharedItemListControl.lua index b7605b61dc..a4891b368f 100644 --- a/src/Classes/SharedItemListControl.lua +++ b/src/Classes/SharedItemListControl.lua @@ -7,19 +7,23 @@ local pairs = pairs local t_insert = table.insert local t_remove = table.remove -local SharedItemListClass = newClass("SharedItemListControl", "ListControl", function(self, anchor, rect, itemsTab, forceTooltip) - self.ListControl(anchor, rect, 16, "VERTICAL", true, main.sharedItemList, forceTooltip) +---@class SharedItemListControl: ListControl +local SharedItemListClass = newClass("SharedItemListControl", "ListControl") + +function SharedItemListClass:SharedItemListControl(anchor, rect, itemsTab, forceTooltip) + self:ListControl(anchor, rect, 16, "VERTICAL", true, main.sharedItemList, forceTooltip) self.itemsTab = itemsTab self.label = "^7Shared items:" self.defaultText = "^x7F7F7FThis is a list of items that will be shared between all of\nyour builds.\nYou can add items to this list by dragging them from\none of the other lists." self.dragTargetList = { } - self.controls.delete = new("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Delete", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Delete", function() self:OnSelDelete(self.selIndex, self.selValue) end) self.controls.delete.enabled = function() return self.selValue ~= nil end -end) + return self +end function SharedItemListClass:GetRowValue(column, index, item) if column == 1 then @@ -44,7 +48,7 @@ end function SharedItemListClass:ReceiveDrag(type, value, source) if type == "Item" then local rawItem = { raw = value:BuildRaw() } - local newItem = new("Item", rawItem.raw) + local newItem = new("Item"):Item(rawItem.raw) if not value.id then newItem:NormaliseQuality() end diff --git a/src/Classes/SharedItemSetListControl.lua b/src/Classes/SharedItemSetListControl.lua index c24932a705..ba604874c7 100644 --- a/src/Classes/SharedItemSetListControl.lua +++ b/src/Classes/SharedItemSetListControl.lua @@ -8,37 +8,41 @@ local t_remove = table.remove local m_max = math.max local s_format = string.format -local SharedItemSetListClass = newClass("SharedItemSetListControl", "ListControl", function(self, anchor, rect, itemsTab) - self.ListControl(anchor, rect, 16, "VERTICAL", true, main.sharedItemSetList) +---@class SharedItemSetListControl: ListControl +local SharedItemSetListClass = newClass("SharedItemSetListControl", "ListControl") + +function SharedItemSetListClass:SharedItemSetListControl(anchor, rect, itemsTab) + self:ListControl(anchor, rect, 16, "VERTICAL", true, main.sharedItemSetList) self.itemsTab = itemsTab self.defaultText = "^x7F7F7FThis is a list of item sets that will be shared\nbetween all of your builds.\nYou can add sets to this list by dragging them\nfrom the build's set list." - self.controls.delete = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Delete", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Delete", function() self:OnSelDelete(self.selIndex, self.selValue) end) self.controls.delete.enabled = function() return self.selValue ~= nil end - self.controls.rename = new("ButtonControl", {"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() + self.controls.rename = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() self:RenameSet(self.selValue) end) self.controls.rename.enabled = function() return self.selValue ~= nil end -end) + return self +end function SharedItemSetListClass:RenameSet(sharedItemSet) local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter name for this item set:") - controls.edit = new("EditControl", nil, {0, 40, 350, 20}, sharedItemSet.title, nil, nil, 100, function(buf) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter name for this item set:") + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, sharedItemSet.title, nil, nil, 100, function(buf) controls.save.enabled = buf:match("%S") end) - controls.save = new("ButtonControl", nil, {-45, 70, 80, 20}, "Save", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Save", function() sharedItemSet.title = controls.edit.buf self.itemsTab.modFlag = true main:ClosePopup() end) controls.save.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(370, 100, sharedItemSet.title and "Rename" or "Set Name", controls, "save", "edit") @@ -82,7 +86,7 @@ function SharedItemSetListClass:ReceiveDrag(type, value, source) if slot.selItemId ~= 0 then local item = self.itemsTab.items[slot.selItemId] local rawItem = { raw = item:BuildRaw() } - local newItem = new("Item", rawItem.raw) + local newItem = new("Item"):Item(rawItem.raw) if not value.id then newItem:NormaliseQuality() end diff --git a/src/Classes/SkillListControl.lua b/src/Classes/SkillListControl.lua index 891f4374b4..99a1af81c7 100644 --- a/src/Classes/SkillListControl.lua +++ b/src/Classes/SkillListControl.lua @@ -49,11 +49,11 @@ local SkillListClass = newClass("SkillListControl", "ListControl", function(self self.controls.deleteAll.enabled = function() return #self.list > 0 end - self.controls.new = new("ButtonControl", {"RIGHT",self.controls.deleteAll,"LEFT"}, {-4, 0, 60, 18}, "New", function() - local newGroup = { - label = "", - enabled = true, - gemList = { } + self.controls.new = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.deleteAll,"LEFT"}, {-4, 0, 60, 18}, "New", function() + local newGroup = { + label = "", + enabled = true, + gemList = { } } t_insert(self.list, newGroup) self.selIndex = #self.list @@ -66,7 +66,8 @@ local SkillListClass = newClass("SkillListControl", "ListControl", function(self for k, x in pairs(slot_map) do x.icon:Load(x.path) end -end) + return self +end function SkillListClass:GetRowValue(column, index, socketGroup) if column == 1 then diff --git a/src/Classes/SkillListControl.lua.rej b/src/Classes/SkillListControl.lua.rej new file mode 100644 index 0000000000..ba97f60336 --- /dev/null +++ b/src/Classes/SkillListControl.lua.rej @@ -0,0 +1,26 @@ +diff a/src/Classes/SkillListControl.lua b/src/Classes/SkillListControl.lua (rejected hunks) +@@ -26,17 +26,20 @@ local slot_map = { + ["Belt"] = { icon = NewImageHandle(), path = "Assets/icon_belt.png" }, + } + +-local SkillListClass = newClass("SkillListControl", "ListControl", function(self, anchor, rect, skillsTab) +- self.ListControl(anchor, rect, 16, "VERTICAL", true, skillsTab.socketGroupList) ++---@class SkillListControl: ListControl ++local SkillListClass = newClass("SkillListControl", "ListControl") ++ ++function SkillListClass:SkillListControl(anchor, rect, skillsTab) ++ self:ListControl(anchor, rect, 16, "VERTICAL", true, skillsTab.socketGroupList) + self.skillsTab = skillsTab + self.label = "^7Socket Groups:" +- self.controls.delete = new("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Delete", function() ++ self.controls.delete = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Delete", function() + self:OnSelDelete(self.selIndex, self.selValue) + end) + self.controls.delete.enabled = function() + return self.selValue ~= nil and self.selValue.source == nil + end +- self.controls.deleteAll = new("ButtonControl", {"RIGHT",self.controls.delete,"LEFT"}, {-4, 0, 70, 18}, "Delete All", function() ++ self.controls.deleteAll = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.delete,"LEFT"}, {-4, 0, 70, 18}, "Delete All", function() + main:OpenConfirmPopup("Delete All", "Are you sure you want to delete all socket groups in this build?", "Delete", function() + wipeTable(self.list) + skillsTab:RebuildImbuedSupportBySlot() diff --git a/src/Classes/SkillSetListControl.lua.rej b/src/Classes/SkillSetListControl.lua.rej new file mode 100644 index 0000000000..a8319aa910 --- /dev/null +++ b/src/Classes/SkillSetListControl.lua.rej @@ -0,0 +1,66 @@ +diff a/src/Classes/SkillSetListControl.lua b/src/Classes/SkillSetListControl.lua (rejected hunks) +@@ -8,10 +8,13 @@ local t_remove = table.remove + local m_max = math.max + local s_format = string.format + +-local SkillSetListClass = newClass("SkillSetListControl", "ListControl", function(self, anchor, rect, skillsTab) +- self.ListControl(anchor, rect, 16, "VERTICAL", true, skillsTab.skillSetOrderList) ++---@class SkillSetListControl: ListControl ++local SkillSetListClass = newClass("SkillSetListControl", "ListControl") ++ ++function SkillSetListClass:SkillSetListControl(anchor, rect, skillsTab) ++ self:ListControl(anchor, rect, 16, "VERTICAL", true, skillsTab.skillSetOrderList) + self.skillsTab = skillsTab +- self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() ++ self.controls.copy = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() + local skillSet = skillsTab.skillSets[self.selValue] + local newSkillSet = copyTable(skillSet, true) + newSkillSet.socketGroupList = { } +@@ -33,30 +36,31 @@ local SkillSetListClass = newClass("SkillSetListControl", "ListControl", functio + self.controls.copy.enabled = function() + return self.selValue ~= nil + end +- self.controls.delete = new("ButtonControl", {"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() ++ self.controls.delete = new("ButtonControl"):ButtonControl({"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() + self:OnSelDelete(self.selIndex, self.selValue) + end) + self.controls.delete.enabled = function() + return self.selValue ~= nil and #self.list > 1 + end +- self.controls.rename = new("ButtonControl", {"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() ++ self.controls.rename = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() + self:RenameSet(skillsTab.skillSets[self.selValue]) + end) + self.controls.rename.enabled = function() + return self.selValue ~= nil + end +- self.controls.new = new("ButtonControl", {"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() ++ self.controls.new = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() + self:RenameSet(skillsTab:NewSkillSet(), true) + end) +-end) ++ return self ++end + + function SkillSetListClass:RenameSet(skillSet, addOnName) + local controls = { } +- controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter name for this skill set:") +- controls.edit = new("EditControl", nil, {0, 40, 350, 20}, skillSet.title, nil, nil, 100, function(buf) ++ controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter name for this skill set:") ++ controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, skillSet.title, nil, nil, 100, function(buf) + controls.save.enabled = buf:match("%S") + end) +- controls.save = new("ButtonControl", nil, {-45, 70, 80, 20}, "Save", function() ++ controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Save", function() + skillSet.title = controls.edit.buf + self.skillsTab.modFlag = true + if addOnName then +@@ -69,7 +73,7 @@ function SkillSetListClass:RenameSet(skillSet, addOnName) + main:ClosePopup() + end) + controls.save.enabled = false +- controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() ++ controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() + if addOnName then + self.skillsTab.skillSets[skillSet.id] = nil + end diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index ac8688c0b4..4c32f5a5d3 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -77,10 +77,14 @@ local sortGemTypeList = { { label = "Effective Hit Pool", type = "TotalEHP" }, } -local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Control", function(self, build) - self.UndoHandler() - self.ControlHost() - self.Control() +---@class SkillsTab: UndoHandler, ControlHost, Control +local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Control") + +---@param build Build +function SkillsTabClass:SkillsTab(build) + self:UndoHandler() + self:ControlHost() + self:Control() self.build = build @@ -264,7 +268,7 @@ will automatically apply to the skill.]] end -- Scroll bar - self.controls.scrollBarH = new("ScrollBarControl", nil, {0, 0, 0, 18}, 100, "HORIZONTAL", true) + self.controls.scrollBarH = new("ScrollBarControl"):ScrollBarControl(nil, {0, 0, 0, 18}, 100, "HORIZONTAL", true) -- Initialise skill sets self.skillSets = { } @@ -752,7 +756,7 @@ function SkillsTabClass:CreateGemSlot(index) self.build.buildFlag = true end -- Delete gem - slot.delete = new("ButtonControl", nil, {0, 0, 20, 20}, "x", function() + slot.delete = new("ButtonControl"):ButtonControl(nil, {0, 0, 20, 20}, "x", function() return deleteGem() end) if index == 1 then @@ -773,7 +777,7 @@ function SkillsTabClass:CreateGemSlot(index) self.controls["gemSlot"..index.."Delete"] = slot.delete -- Gem name specification - slot.nameSpec = new("GemSelectControl", { "LEFT", slot.delete, "RIGHT" }, { 2, 0, 300, 20 }, self, index, function(gemId, addUndo, focusLost, bufMatchesGem) + slot.nameSpec = new("GemSelectControl"):GemSelectControl({ "LEFT", slot.delete, "RIGHT" }, { 2, 0, 300, 20 }, self, index, function(gemId, addUndo, focusLost, bufMatchesGem) if not self.displayGroup then return end @@ -1124,7 +1128,7 @@ function SkillsTabClass:CreateGemSlot(index) self.controls["gemSlot"..index.."EnableGlobal1"] = slot.enableGlobal1 -- Enable global-effect skill 2 - slot.enableGlobal2 = new("CheckBoxControl", {"LEFT",slot.enableGlobal1,"RIGHT",true}, {0, 0, 20}, "", function(state) + slot.enableGlobal2 = new("CheckBoxControl"):CheckBoxControl({"LEFT",slot.enableGlobal1,"RIGHT",true}, {0, 0, 20}, "", function(state) local gemInstance = self.displayGroup.gemList[index] gemInstance.enableGlobal2 = state self:AddUndoState() @@ -1475,8 +1479,8 @@ end -- Opens the skill set manager function SkillsTabClass:OpenSkillSetManagePopup() main:OpenPopup(370, 290, "Manage Skill Sets", { - new("SkillSetListControl", nil, {0, 50, 350, 200}, self), - new("ButtonControl", nil, {0, 260, 90, 20}, "Done", function() + new("SkillSetListControl"):SkillSetListControl(nil, {0, 50, 350, 200}, self), + new("ButtonControl"):ButtonControl(nil, {0, 260, 90, 20}, "Done", function() main:ClosePopup() end), }) diff --git a/src/Classes/SkillsTab.lua.rej b/src/Classes/SkillsTab.lua.rej new file mode 100644 index 0000000000..498b62159d --- /dev/null +++ b/src/Classes/SkillsTab.lua.rej @@ -0,0 +1,249 @@ +diff a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua (rejected hunks) +@@ -92,7 +96,7 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont + self.defaultGemQuality = main.defaultGemQuality + + -- Set selector +- self.controls.setSelect = new("DropDownControl", { "TOPLEFT", self, "TOPLEFT" }, { 76, 8, 210, 20 }, nil, function(index, value) ++ self.controls.setSelect = new("DropDownControl"):DropDownControl({ "TOPLEFT", self, "TOPLEFT" }, { 76, 8, 210, 20 }, nil, function(index, value) + self:SetActiveSkillSet(self.skillSetOrderList[index]) + self:AddUndoState() + end) +@@ -100,14 +104,14 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont + self.controls.setSelect.enabled = function() + return #self.skillSetOrderList > 1 + end +- self.controls.setLabel = new("LabelControl", { "RIGHT", self.controls.setSelect, "LEFT" }, { -2, 0, 0, 16 }, "^7Skill set:") +- self.controls.setManage = new("ButtonControl", { "LEFT", self.controls.setSelect, "RIGHT" }, { 4, 0, 90, 20 }, "Manage...", function() ++ self.controls.setLabel = new("LabelControl"):LabelControl({ "RIGHT", self.controls.setSelect, "LEFT" }, { -2, 0, 0, 16 }, "^7Skill set:") ++ self.controls.setManage = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.setSelect, "RIGHT" }, { 4, 0, 90, 20 }, "Manage...", function() + self:OpenSkillSetManagePopup() + end) + + -- Socket group list +- self.controls.groupList = new("SkillListControl", { "TOPLEFT", self, "TOPLEFT" }, { 20, 54, 360, 300 }, self) +- self.controls.groupTip = new("LabelControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { 0, 8, 0, 14 }, ++ self.controls.groupList = new("SkillListControl"):SkillListControl({ "TOPLEFT", self, "TOPLEFT" }, { 20, 54, 360, 300 }, self) ++ self.controls.groupTip = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { 0, 8, 0, 14 }, + [[ + ^7Usage Tips: + - You can copy/paste socket groups using Ctrl+C and Ctrl+V. +@@ -120,14 +124,14 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont + -- Gem options + local optionInputsX = 170 + local optionInputsY = 45 +- self.controls.optionSection = new("SectionControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { 0, optionInputsY + 50, 360, 156 }, "Gem Options") +- self.controls.sortGemsByDPS = new("CheckBoxControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 70, 20 }, "Sort gems by DPS:", function(state) ++ self.controls.optionSection = new("SectionControl"):SectionControl({ "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { 0, optionInputsY + 50, 360, 156 }, "Gem Options") ++ self.controls.sortGemsByDPS = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 70, 20 }, "Sort gems by DPS:", function(state) + self.sortGemsByDPS = state + end, nil, true) +- self.controls.sortGemsByDPSFieldControl = new("DropDownControl", { "LEFT", self.controls.sortGemsByDPS, "RIGHT" }, { 10, 0, 140, 20 }, sortGemTypeList, function(index, value) ++ self.controls.sortGemsByDPSFieldControl = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.sortGemsByDPS, "RIGHT" }, { 10, 0, 140, 20 }, sortGemTypeList, function(index, value) + self.sortGemsByDPSField = value.type + end) +- self.controls.defaultLevel = new("DropDownControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 94, 170, 20 }, defaultGemLevelList, function(index, value) ++ self.controls.defaultLevel = new("DropDownControl"):DropDownControl({ "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 94, 170, 20 }, defaultGemLevelList, function(index, value) + self.defaultGemLevel = value.gemLevel + end) + self.controls.defaultLevel.tooltipFunc = function(tooltip, mode, index, value) +@@ -136,36 +140,36 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont + tooltip:AddLine(16, "^7" .. value.description) + end + end +- self.controls.defaultLevelLabel = new("LabelControl", { "RIGHT", self.controls.defaultLevel, "LEFT" }, { -4, 0, 0, 16 }, "^7Default gem level:") +- self.controls.defaultQuality = new("EditControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 118, 60, 20 }, nil, nil, "%D", 2, function(buf) ++ self.controls.defaultLevelLabel = new("LabelControl"):LabelControl({ "RIGHT", self.controls.defaultLevel, "LEFT" }, { -4, 0, 0, 16 }, "^7Default gem level:") ++ self.controls.defaultQuality = new("EditControl"):EditControl({ "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 118, 60, 20 }, nil, nil, "%D", 2, function(buf) + self.defaultGemQuality = m_min(tonumber(buf) or 0, 23) + end) +- self.controls.defaultQualityLabel = new("LabelControl", { "RIGHT", self.controls.defaultQuality, "LEFT" }, { -4, 0, 0, 16 }, "^7Default gem quality:") +- self.controls.showSupportGemTypes = new("DropDownControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 142, 170, 20 }, showSupportGemTypeList, function(index, value) ++ self.controls.defaultQualityLabel = new("LabelControl"):LabelControl({ "RIGHT", self.controls.defaultQuality, "LEFT" }, { -4, 0, 0, 16 }, "^7Default gem quality:") ++ self.controls.showSupportGemTypes = new("DropDownControl"):DropDownControl({ "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 142, 170, 20 }, showSupportGemTypeList, function(index, value) + self.showSupportGemTypes = value.show + end) +- self.controls.showSupportGemTypesLabel = new("LabelControl", { "RIGHT", self.controls.showSupportGemTypes, "LEFT" }, { -4, 0, 0, 16 }, "^7Show support gems:") +- self.controls.showLegacyGems = new("CheckBoxControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 166, 20 }, "^7Show legacy gems:", function(state) ++ self.controls.showSupportGemTypesLabel = new("LabelControl"):LabelControl({ "RIGHT", self.controls.showSupportGemTypes, "LEFT" }, { -4, 0, 0, 16 }, "^7Show support gems:") ++ self.controls.showLegacyGems = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 166, 20 }, "^7Show legacy gems:", function(state) + self.showLegacyGems = state + end) + + -- Socket group details + if main.portraitMode then +- self.anchorGroupDetail = new("Control", { "TOPLEFT", self.controls.optionSection, "BOTTOMLEFT" }, { 0, 20, 0, 0 }) ++ self.anchorGroupDetail = new("Control"):Control({ "TOPLEFT", self.controls.optionSection, "BOTTOMLEFT" }, { 0, 20, 0, 0 }) + else +- self.anchorGroupDetail = new("Control", { "TOPLEFT", self.controls.groupList, "TOPRIGHT" }, { 20, 0, 0, 0 }) ++ self.anchorGroupDetail = new("Control"):Control({ "TOPLEFT", self.controls.groupList, "TOPRIGHT" }, { 20, 0, 0, 0 }) + end + self.anchorGroupDetail.shown = function() + return self.displayGroup ~= nil + end +- self.controls.groupLabel = new("EditControl", { "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 0, 0, 380, 20 }, nil, "Label", "%c", 50, function(buf) ++ self.controls.groupLabel = new("EditControl"):EditControl({ "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 0, 0, 380, 20 }, nil, "Label", "%c", 50, function(buf) + self.displayGroup.label = buf + self:ProcessSocketGroup(self.displayGroup) + self:AddUndoState() + self.build.buildFlag = true + end) +- self.controls.groupSlotLabel = new("LabelControl", { "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 0, 30, 0, 16 }, "^7Socketed in:") +- self.controls.groupSlot = new("DropDownControl", { "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 85, 28, 130, 20 }, groupSlotDropList, function(index, value) ++ self.controls.groupSlotLabel = new("LabelControl"):LabelControl({ "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 0, 30, 0, 16 }, "^7Socketed in:") ++ self.controls.groupSlot = new("DropDownControl"):DropDownControl({ "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 85, 28, 130, 20 }, groupSlotDropList, function(index, value) + -- maintain imbued support to new slot + if self.imbuedSupportBySlot[self.displayGroup.slot] and self.displayGroup.imbuedSupport then + if value.slotName and not self.imbuedSupportBySlot[value.slotName] then +@@ -200,12 +204,12 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont + self.controls.groupSlot.enabled = function() + return self.displayGroup.source == nil + end +- self.controls.groupEnabled = new("CheckBoxControl", { "LEFT", self.controls.groupSlot, "RIGHT" }, { 70, 0, 20 }, "Enabled:", function(state) ++ self.controls.groupEnabled = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.groupSlot, "RIGHT" }, { 70, 0, 20 }, "Enabled:", function(state) + self.displayGroup.enabled = state + self:AddUndoState() + self.build.buildFlag = true + end) +- self.controls.includeInFullDPS = new("CheckBoxControl", { "LEFT", self.controls.groupEnabled, "RIGHT" }, { 145, 0, 20 }, "Include in Full DPS:", function(state) ++ self.controls.includeInFullDPS = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.groupEnabled, "RIGHT" }, { 145, 0, 20 }, "Include in Full DPS:", function(state) + self.displayGroup.includeInFullDPS = state + self:AddUndoState() + self.build.buildFlag = true +@@ -225,7 +229,7 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont + end + return item, groupSlot + end +- self.controls.socketsLabel = new("LabelControl", { "TOPLEFT", self.controls.groupSlotLabel, "BOTTOMLEFT" }, { 0, 8, 0, 16 }, function() ++ self.controls.socketsLabel = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.groupSlotLabel, "BOTTOMLEFT" }, { 0, 8, 0, 16 }, function() + local item = getSelectedItem() + local socketLine = "" + if item and item.base and not item.base.socketLimit then +@@ -239,7 +243,7 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont + local item = getSelectedItem() + return not not item + end +- self.controls.optimiseSockets = new("ButtonControl", { "LEFT", self.controls.socketsLabel, "RIGHT" }, { 4, 0, 120, 18 }, "^7Optimise Sockets", function() ++ self.controls.optimiseSockets = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.socketsLabel, "RIGHT" }, { 4, 0, 120, 18 }, "^7Optimise Sockets", function() + local item, groupSlot = getSelectedItem() + if not item or not groupSlot or not item.base then + return +@@ -292,8 +296,8 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont + -- buildFlag to true triggers the reload/run the CalcSetup to add on the support + -- the last var in the GemSelectControl init, the true, sets imbuedSelect to true which sets the level to 1 and support filtering + self.imbuedSupportBySlot = { } +- self.controls.imbuedSupportLabel = new("LabelControl", { "TOPLEFT", self.controls.socketsLabel, "BOTTOMLEFT", true }, { 0, 8, 0, 16 }, colorCodes.CRAFTED .. "Imbued Support:") +- self.controls.imbuedSupport = new("GemSelectControl", { "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 8, 0, 250, 20 }, self, 1, function(gemData, _, _, gemMatch, slotName) ++ self.controls.imbuedSupportLabel = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.socketsLabel, "BOTTOMLEFT", true }, { 0, 8, 0, 16 }, colorCodes.CRAFTED .. "Imbued Support:") ++ self.controls.imbuedSupport = new("GemSelectControl"):GemSelectControl({ "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 8, 0, 250, 20 }, self, 1, function(gemData, _, _, gemMatch, slotName) + local targetSlot = slotName or (self.displayGroup and self.displayGroup.slot) + if not targetSlot then + return +@@ -332,7 +336,7 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont + return self.displayGroup and not + self.displayGroup.source + end +- self.controls.imbuedSupportClear = new("ButtonControl", { "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 260, 0, 20, 20}, "x", function() ++ self.controls.imbuedSupportClear = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 260, 0, 20, 20}, "x", function() + self.controls.imbuedSupport.gemId = nil + self.controls.imbuedSupport:SetText("") + self.controls.imbuedSupport:gemChangeFunc(nil) +@@ -342,11 +346,11 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont + end + self.controls.imbuedSupportClear.tooltipText = "Remove this imbued support." + +- self.controls.groupCountLabel = new("LabelControl", { "LEFT", self.controls.includeInFullDPS, "RIGHT" }, { 16, 0, 0, 16 }, "^7Count:") ++ self.controls.groupCountLabel = new("LabelControl"):LabelControl({ "LEFT", self.controls.includeInFullDPS, "RIGHT" }, { 16, 0, 0, 16 }, "^7Count:") + self.controls.groupCountLabel.shown = function() + return self.displayGroup.source ~= nil + end +- self.controls.groupCount = new("EditControl", { "LEFT", self.controls.groupCountLabel, "RIGHT" }, { 4, 0, 60, 20 }, nil, nil, "%D", 2, function(buf) ++ self.controls.groupCount = new("EditControl"):EditControl({ "LEFT", self.controls.groupCountLabel, "RIGHT" }, { 4, 0, 60, 20 }, nil, nil, "%D", 2, function(buf) + self.displayGroup.groupCount = tonumber(buf) or 1 + self:AddUndoState() + self.build.buildFlag = true +@@ -354,7 +358,7 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont + self.controls.groupCount.shown = function() + return self.displayGroup.source ~= nil + end +- self.controls.sourceNote = new("LabelControl", { "TOPLEFT", self.controls.socketsLabel, "TOPLEFT" }, { 0, 30, 0, 16 }) ++ self.controls.sourceNote = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.socketsLabel, "TOPLEFT" }, { 0, 30, 0, 16 }) + self.controls.sourceNote.shown = function() + return self.displayGroup.source ~= nil + end +@@ -400,15 +404,16 @@ will automatically apply to the skill.]] + self:SetActiveSkillSet(1) + + -- Skill gem slots +- self.anchorGemSlots = new("Control", { "TOPLEFT", self.controls.imbuedSupportLabel, "BOTTOMLEFT" }, { 0, 30, 0, 0 }) ++ self.anchorGemSlots = new("Control"):Control({ "TOPLEFT", self.controls.imbuedSupportLabel, "BOTTOMLEFT" }, { 0, 30, 0, 0 }) + self.gemSlots = {} + self:CreateGemSlot(1) +- self.controls.gemNameHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].nameSpec, "TOPLEFT"}, {0, -2, 0, 16}, "^7Gem name:") +- self.controls.gemLevelHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].level, "TOPLEFT"}, {0, -2, 0, 16}, "^7Level:") +- self.controls.gemQualityHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].quality, "TOPLEFT"}, {0, -2, 0, 16}, "^7Quality:") +- self.controls.gemEnableHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].enabled, "TOPLEFT"}, {-16, -2, 0, 16}, "^7Enabled:") +- self.controls.gemCountHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].count, "TOPLEFT"}, {8, -2, 0, 16}, "^7Count:") +-end) ++ self.controls.gemNameHeader = new("LabelControl"):LabelControl({"BOTTOMLEFT", self.gemSlots[1].nameSpec, "TOPLEFT"}, {0, -2, 0, 16}, "^7Gem name:") ++ self.controls.gemLevelHeader = new("LabelControl"):LabelControl({"BOTTOMLEFT", self.gemSlots[1].level, "TOPLEFT"}, {0, -2, 0, 16}, "^7Level:") ++ self.controls.gemQualityHeader = new("LabelControl"):LabelControl({"BOTTOMLEFT", self.gemSlots[1].quality, "TOPLEFT"}, {0, -2, 0, 16}, "^7Quality:") ++ self.controls.gemEnableHeader = new("LabelControl"):LabelControl({"BOTTOMLEFT", self.gemSlots[1].enabled, "TOPLEFT"}, {-16, -2, 0, 16}, "^7Enabled:") ++ self.controls.gemCountHeader = new("LabelControl"):LabelControl({"BOTTOMLEFT", self.gemSlots[1].count, "TOPLEFT"}, {8, -2, 0, 16}, "^7Count:") ++ return self ++end + + + function SkillsTabClass:LoadSkill(node, skillSetId) +@@ -812,7 +817,7 @@ function SkillsTabClass:CreateGemSlot(index) + self.controls["gemSlot"..index.."Name"] = slot.nameSpec + + -- Gem level +- slot.level = new("EditControl", { "LEFT", slot.nameSpec, "RIGHT" }, { 2, 0, 60, 20 }, nil, nil, "%D", 2, function(buf) ++ slot.level = new("EditControl"):EditControl({ "LEFT", slot.nameSpec, "RIGHT" }, { 2, 0, 60, 20 }, nil, nil, "%D", 2, function(buf) + local gemInstance = self.displayGroup.gemList[index] + if not gemInstance then + gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, enabled = true, enableGlobal1 = true, enableGlobal2 = true, count = 1, new = true } +@@ -834,7 +839,7 @@ function SkillsTabClass:CreateGemSlot(index) + self.controls["gemSlot"..index.."Level"] = slot.level + + -- Gem quality +- slot.quality = new("EditControl", {"LEFT",slot.level,"RIGHT"}, {2, 0, 60, 20}, nil, nil, "%D", 2, function(buf) ++ slot.quality = new("EditControl"):EditControl({"LEFT",slot.level,"RIGHT"}, {2, 0, 60, 20}, nil, nil, "%D", 2, function(buf) + local gemInstance = self.displayGroup.gemList[index] + if not gemInstance then + gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, enabled = true, enableGlobal1 = true, enableGlobal2 = true, count = 1, new = true } +@@ -925,7 +930,7 @@ function SkillsTabClass:CreateGemSlot(index) + self.controls["gemSlot"..index.."Quality"] = slot.quality + + -- Enable gem +- slot.enabled = new("CheckBoxControl", {"LEFT",slot.quality,"RIGHT"}, {18, 0, 20}, nil, function(state) ++ slot.enabled = new("CheckBoxControl"):CheckBoxControl({"LEFT",slot.quality,"RIGHT"}, {18, 0, 20}, nil, function(state) + local gemInstance = self.displayGroup.gemList[index] + if not gemInstance then + gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, enabled = true, enableGlobal1 = true, enableGlobal2 = true, count = 1, new = true } +@@ -964,7 +969,7 @@ function SkillsTabClass:CreateGemSlot(index) + self.controls["gemSlot"..index.."Enable"] = slot.enabled + + -- Count gem +- slot.count = new("EditControl", {"LEFT",slot.enabled,"RIGHT"}, {18, 0, 60, 20}, nil, nil, "%D", 2, function(buf) ++ slot.count = new("EditControl"):EditControl({"LEFT",slot.enabled,"RIGHT"}, {18, 0, 60, 20}, nil, nil, "%D", 2, function(buf) + local gemInstance = self.displayGroup.gemList[index] + if not gemInstance then + gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, enabled = true, enableGlobal1 = true, count = 1, new = true } +@@ -1005,14 +1010,14 @@ function SkillsTabClass:CreateGemSlot(index) + self.controls["gemSlot"..index.."Count"] = slot.count + + -- Parser/calculator error message +- slot.errMsg = new("LabelControl", {"LEFT",slot.count,"RIGHT"}, {2, 2, 0, 16}, function() ++ slot.errMsg = new("LabelControl"):LabelControl({"LEFT",slot.count,"RIGHT"}, {2, 2, 0, 16}, function() + local gemInstance = self.displayGroup and self.displayGroup.gemList[index] + return "^1"..(gemInstance and gemInstance.errMsg or "") + end) + self.controls["gemSlot"..index.."ErrMsg"] = slot.errMsg + + -- Enable global-effect skill 1 +- slot.enableGlobal1 = new("CheckBoxControl", {"TOPLEFT",slot.delete,"BOTTOMLEFT"}, {0, 2, 20}, "", function(state) ++ slot.enableGlobal1 = new("CheckBoxControl"):CheckBoxControl({"TOPLEFT",slot.delete,"BOTTOMLEFT"}, {0, 2, 20}, "", function(state) + local gemInstance = self.displayGroup.gemList[index] + gemInstance.enableGlobal1 = state + self:AddUndoState() diff --git a/src/Classes/SliderControl.lua b/src/Classes/SliderControl.lua index 2c3048de48..89dba3e1fc 100644 --- a/src/Classes/SliderControl.lua +++ b/src/Classes/SliderControl.lua @@ -7,14 +7,18 @@ local m_min = math.min local m_max = math.max local m_ceil = math.ceil -local SliderClass = newClass("SliderControl", "Control", "TooltipHost", function(self, anchor, rect, changeFunc, scrollWheelSpeedTbl) - self.Control(anchor, rect) - self.TooltipHost() +---@class SliderControl: Control, TooltipHost +local SliderClass = newClass("SliderControl", "Control", "TooltipHost") + +function SliderClass:SliderControl(anchor, rect, changeFunc, scrollWheelSpeedTbl) + self:Control(anchor, rect) + self:TooltipHost() self.knobSize = self.height - 2 self.val = 0 self.changeFunc = changeFunc self.scrollWheelSpeedTbl = scrollWheelSpeedTbl or { ["SHIFT"] = 0.25, ["CTRL"] = 0.01, ["DEFAULT"] = 0.05 } -end) + return self +end function SliderClass:IsMouseOver() if not self:IsShown() then diff --git a/src/Classes/TextListControl.lua b/src/Classes/TextListControl.lua index 7302a153b9..b9c7f726d5 100644 --- a/src/Classes/TextListControl.lua +++ b/src/Classes/TextListControl.lua @@ -3,10 +3,13 @@ -- Class: Text List -- Simple list control for displaying a block of text -- -local TextListClass = newClass("TextListControl", "Control", "ControlHost", function(self, anchor, rect, columns, list, sectionHeights) - self.Control(anchor, rect) - self.ControlHost() - self.controls.scrollBar = new("ScrollBarControl", {"RIGHT",self,"RIGHT"}, {-1, 0, 18, 0}, 40) +---@class TextListControl: Control, ControlHost +local TextListClass = newClass("TextListControl", "Control", "ControlHost") + +function TextListClass:TextListControl(anchor, rect, columns, list, sectionHeights) + self:Control(anchor, rect) + self:ControlHost() + self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({"RIGHT",self,"RIGHT"}, {-1, 0, 18, 0}, 40) self.controls.scrollBar.height = function() local width, height = self:GetSize() return height - 2 @@ -14,7 +17,8 @@ local TextListClass = newClass("TextListControl", "Control", "ControlHost", func self.columns = columns or { { x = 0, align = "LEFT" } } self.list = list or { } self.sectionHeights = sectionHeights -end) + return self +end function TextListClass:IsMouseOver() if not self:IsShown() then diff --git a/src/Classes/TimelessJewelListControl.lua b/src/Classes/TimelessJewelListControl.lua index 5a55490875..131247178c 100644 --- a/src/Classes/TimelessJewelListControl.lua +++ b/src/Classes/TimelessJewelListControl.lua @@ -9,13 +9,17 @@ local m_min = math.min local m_max = math.max local t_concat = table.concat -local TimelessJewelListControlClass = newClass("TimelessJewelListControl", "ListControl", function(self, anchor, rect, build) +---@class TimelessJewelListControl: ListControl +local TimelessJewelListControlClass = newClass("TimelessJewelListControl", "ListControl") + +function TimelessJewelListControlClass:TimelessJewelListControl(anchor, rect, build) self.build = build self.sharedList = self.build.timelessData.sharedResults or { } self.list = self.build.timelessData.searchResults or { } - self.ListControl(anchor, rect, 16, true, false, self.list) + self:ListControl(anchor, rect, 16, true, false, self.list) self.selIndex = nil -end) + return self +end function TimelessJewelListControlClass:Draw(viewPort, noTooltip) self.noTooltip = noTooltip @@ -227,7 +231,7 @@ Passives in radius are Conquered by the Templars Historic ]] end - local item = new("Item", itemData) + local item = new("Item"):Item(itemData) self.build.itemsTab:AddItem(item, true) self.build.itemsTab:PopulateSlots() self.list[index].label = "^xB2B2B2" .. self.list[index].label diff --git a/src/Classes/TimelessJewelSocketControl.lua b/src/Classes/TimelessJewelSocketControl.lua index 7ff6bcf0cf..3e841231df 100644 --- a/src/Classes/TimelessJewelSocketControl.lua +++ b/src/Classes/TimelessJewelSocketControl.lua @@ -6,11 +6,15 @@ local m_min = math.min -local TimelessJewelSocketClass = newClass("TimelessJewelSocketControl", "DropDownControl", function(self, anchor, rect, list, selFunc, build, socketViewer) - self.DropDownControl(anchor, rect, list, selFunc) +---@class TimelessJewelSocketControl: DropDownControl +local TimelessJewelSocketClass = newClass("TimelessJewelSocketControl", "DropDownControl") + +function TimelessJewelSocketClass:TimelessJewelSocketControl(anchor, rect, list, selFunc, build, socketViewer) + self:DropDownControl(anchor, rect, list, selFunc) self.build = build self.socketViewer = socketViewer -end) + return self +end function TimelessJewelSocketClass:Draw(viewPort, noTooltip) local x, y = self:GetPos() diff --git a/src/Classes/Tooltip.lua.rej b/src/Classes/Tooltip.lua.rej new file mode 100644 index 0000000000..fa600476a5 --- /dev/null +++ b/src/Classes/Tooltip.lua.rej @@ -0,0 +1,20 @@ +diff a/src/Classes/Tooltip.lua b/src/Classes/Tooltip.lua (rejected hunks) +@@ -40,12 +40,16 @@ for _, recipeName in pairs(recipeNames) do + recipeImages[recipeName]:Load("TreeData/" .. recipeName .. ".png", "CLAMP") + end + +-local TooltipClass = newClass("Tooltip", function(self) ++---@class Tooltip ++local TooltipClass = newClass("Tooltip") ++ ++function TooltipClass:Tooltip() + self.lines = { } + self.blocks = { } + self.childTooltips = nil + self:Clear() +-end) ++ return self ++end + + function TooltipClass:Clear(clearUpdateParams) + wipeTable(self.lines) diff --git a/src/Classes/TooltipHost.lua b/src/Classes/TooltipHost.lua index bd8db5231d..42a9c3e0e9 100644 --- a/src/Classes/TooltipHost.lua +++ b/src/Classes/TooltipHost.lua @@ -3,10 +3,14 @@ -- Class: Tooltip Host -- Tooltip host -- -local TooltipHostClass = newClass("TooltipHost", function(self, tooltipText) - self.tooltip = new("Tooltip") +---@class TooltipHost +local TooltipHostClass = newClass("TooltipHost") + +function TooltipHostClass:TooltipHost(tooltipText) + self.tooltip = new("Tooltip"):Tooltip() self.tooltipText = tooltipText -end) + return self +end function TooltipHostClass:DrawTooltip(x, y, width, height, viewPort, ...) if self.tooltipFunc then diff --git a/src/Classes/TradeHelpers.lua b/src/Classes/TradeHelpers.lua index 5057fe0b26..1891bc5e0e 100644 --- a/src/Classes/TradeHelpers.lua +++ b/src/Classes/TradeHelpers.lua @@ -526,7 +526,7 @@ end -- with a preset changeFunc intended for mod values function M.newPlainNumericEdit(anchor, rect, init, prompt, limit, integer, changeFunc) local format = integer and "%D" or "^%d." - local ctrl = new("EditControl", anchor, rect, init, prompt, format, limit, changeFunc) + local ctrl = new("EditControl"):EditControl(anchor, rect, init, prompt, format, limit, changeFunc) -- Remove the +/- spinner buttons that "%D" filter triggers ctrl.isNumeric = false if ctrl.controls then diff --git a/src/Classes/TradeQuery.lua b/src/Classes/TradeQuery.lua index 261457739e..1382edf04d 100644 --- a/src/Classes/TradeQuery.lua +++ b/src/Classes/TradeQuery.lua @@ -198,7 +198,7 @@ end -- Opens the item pricing popup function TradeQueryClass:PriceItem() - self.tradeQueryGenerator = new("TradeQueryGenerator", self) + self.tradeQueryGenerator = new("TradeQueryGenerator"):TradeQueryGenerator(self) main.onFrameFuncs["TradeQueryGenerator"] = function() self.tradeQueryGenerator:OnFrame() end @@ -215,7 +215,7 @@ function TradeQueryClass:PriceItem() local itemSet = self.itemsTab.itemSets[itemSetId] t_insert(newItemList, itemSet.title or "Default") end - self.controls.setSelect = new("DropDownControl", {"TOPLEFT", nil, "TOPLEFT"}, {pane_margins_horizontal, pane_margins_vertical, 188, row_height}, newItemList, function(index, value) + self.controls.setSelect = new("DropDownControl"):DropDownControl({"TOPLEFT", nil, "TOPLEFT"}, {pane_margins_horizontal, pane_margins_vertical, 188, row_height}, newItemList, function(index, value) self.itemsTab:SetActiveItemSet(self.itemsTab.itemSetOrderList[index]) self.itemsTab:AddUndoState() end) @@ -312,7 +312,7 @@ on trade site to work on other leagues and realms)]] -- Fetches Box self.maxFetchPerSearchDefault = 2 - self.controls.fetchCountEdit = new("EditControl", {"TOPRIGHT", nil, "TOPRIGHT"}, {-12, 19, 150, row_height}, "", "Fetch Pages", "%D", 3, function(buf) + self.controls.fetchCountEdit = new("EditControl"):EditControl({"TOPRIGHT", nil, "TOPRIGHT"}, {-12, 19, 150, row_height}, "", "Fetch Pages", "%D", 3, function(buf) self.maxFetchPages = m_min(m_max(tonumber(buf) or self.maxFetchPerSearchDefault, 1), 10) self.tradeQueryRequests.maxFetchPerSearch = 10 * self.maxFetchPages self.controls.fetchCountEdit.focusValue = self.maxFetchPages @@ -336,7 +336,7 @@ on trade site to work on other leagues and realms)]] self.statSortSelectionList = { } initStatSortSelectionList(self.statSortSelectionList) end - self.controls.StatWeightMultipliersButton = new("ButtonControl", {"TOPRIGHT", self.controls.fetchCountEdit, "BOTTOMRIGHT"}, {0, row_vertical_padding, 150, row_height}, "^7Adjust search weights", function() + self.controls.StatWeightMultipliersButton = new("ButtonControl"):ButtonControl({"TOPRIGHT", self.controls.fetchCountEdit, "BOTTOMRIGHT"}, {0, row_vertical_padding, 150, row_height}, "^7Adjust search weights", function() self.itemsTab.modFlag = true self:SetStatWeights() end) @@ -361,7 +361,7 @@ on trade site to work on other leagues and realms)]] self.sortModes.Price, self.sortModes.Weight, } - self.controls.itemSortSelection = new("DropDownControl", {"TOPRIGHT", self.controls.StatWeightMultipliersButton, "TOPLEFT"}, {-8, 0, 170, row_height}, self.itemSortSelectionList, function(index, value) + self.controls.itemSortSelection = new("DropDownControl"):DropDownControl({"TOPRIGHT", self.controls.StatWeightMultipliersButton, "TOPLEFT"}, {-8, 0, 170, row_height}, self.itemSortSelectionList, function(index, value) self.pbItemSortSelectionIndex = index for row_idx, _ in pairs(self.resultTbl) do self:UpdateControlsWithItems(row_idx) @@ -525,7 +525,7 @@ Highest Weight - Displays the order retrieved from trade]] end end - self.controls.otherTradesLabel = new("LabelControl", top_pane_alignment_ref, {0, (#slotTables+1)*(row_height + row_vertical_padding), 100, 16}, "^8Other trades:") + self.controls.otherTradesLabel = new("LabelControl"):LabelControl(top_pane_alignment_ref, {0, (#slotTables+1)*(row_height + row_vertical_padding), 100, 16}, "^8Other trades:") self.controls.otherTradesLabel.shown = function() return hideRowFunc(self, #slotTables+1) end @@ -630,7 +630,7 @@ function TradeQueryClass:SetStatWeights(previousSelectionList) -- account for top gap, bottom button size and gap, and a gap before buttons local listHeight = popupHeight - 45 - 30 - 10 - controls.ListControl = new("TradeStatWeightMultiplierListControl", { "TOPLEFT", nil, "TOPRIGHT" }, + controls.ListControl = new("TradeStatWeightMultiplierListControl"):TradeStatWeightMultiplierListControl({ "TOPLEFT", nil, "TOPRIGHT" }, { -410, 45, 400, listHeight }, statList, sliderController) for _, stat in ipairs(data.powerStatList) do @@ -647,8 +647,8 @@ function TradeQueryClass:SetStatWeights(previousSelectionList) end end - controls.SliderLabel = new("LabelControl", { "TOPLEFT", nil, "TOPRIGHT" }, {-410, 20, 0, 16}, "^7"..statList[1].stat.label..":") - controls.Slider = new("SliderControl", { "TOPLEFT", controls.SliderLabel, "TOPRIGHT" }, {20, 0, 150, 16}, function(value) + controls.SliderLabel = new("LabelControl"):LabelControl({ "TOPLEFT", nil, "TOPRIGHT" }, {-410, 20, 0, 16}, "^7"..statList[1].stat.label..":") + controls.Slider = new("SliderControl"):SliderControl({ "TOPLEFT", controls.SliderLabel, "TOPRIGHT" }, {20, 0, 150, 16}, function(value) if value == 0 then controls.SliderValue.label = "^7Disabled" statList[sliderController.index].stat.weightMult = 0 @@ -659,7 +659,7 @@ function TradeQueryClass:SetStatWeights(previousSelectionList) statList[sliderController.index].label = s_format("%.2f : ", 0.01 + value * 0.99)..statList[sliderController.index].stat.label end end) - controls.SliderValue = new("LabelControl", { "TOPLEFT", controls.Slider, "TOPRIGHT" }, {20, 0, 0, 16}, "^7Disabled") + controls.SliderValue = new("LabelControl"):LabelControl({ "TOPLEFT", controls.Slider, "TOPRIGHT" }, {20, 0, 0, 16}, "^7Disabled") controls.Slider.tooltip.realDraw = controls.Slider.tooltip.Draw controls.Slider.tooltip.Draw = function(self, x, y, width, height, viewPort) local sliderOffsetX = round(184 * (1 - controls.Slider.val)) @@ -685,7 +685,7 @@ function TradeQueryClass:SetStatWeights(previousSelectionList) end end - controls.finalise = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, {-90, -10, 80, 20}, "Save", function() + controls.finalise = new("ButtonControl"):ButtonControl({ "BOTTOM", nil, "BOTTOM" }, {-90, -10, 80, 20}, "Save", function() main:ClosePopup() -- used in ItemsTab to save to xml under TradeSearchWeights node @@ -703,13 +703,13 @@ function TradeQueryClass:SetStatWeights(previousSelectionList) self:UpdateControlsWithItems(row_idx) end end) - controls.cancel = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, { 0, -10, 80, 20 }, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl({ "BOTTOM", nil, "BOTTOM" }, { 0, -10, 80, 20 }, "Cancel", function() if previousSelectionList and #previousSelectionList > 0 then self.statSortSelectionList = copyTable(previousSelectionList, true) end main:ClosePopup() end) - controls.reset = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, { 90, -10, 80, 20 }, "Reset", function() + controls.reset = new("ButtonControl"):ButtonControl({ "BOTTOM", nil, "BOTTOM" }, { 90, -10, 80, 20 }, "Reset", function() local previousSelection = { } if isSameAsDefaultList(self.statSortSelectionList) then previousSelection = copyTable(previousSelectionList, true) @@ -846,7 +846,7 @@ function TradeQueryClass:UpdateDropdownList(row_idx) local pb_index = self.sortedResultTbl[row_idx][result_index].index local result = self.resultTbl[row_idx][pb_index] local price = string.format(" %s(%d %s)", colorCodes["CURRENCY"], result.amount, result.currency) - local item = new("Item", result.item_string) + local item = new("Item"):Item(result.item_string) table.insert(dropdownLabels, colorCodes[item.rarity] .. item.name .. price) end self.controls["resultDropdown".. row_idx].selIndex = 1 @@ -985,7 +985,7 @@ end function TradeQueryClass:FilterToSafeItems(itemEntries, slotName) local itemsSafe = {} for _, entry in ipairs(itemEntries) do - local item = new("Item", entry.item_string) + local item = new("Item"):Item(entry.item_string) if item.base and ((not slotName) or self.itemsTab:IsItemValidForSlot(item, slotName)) then t_insert(itemsSafe, entry) end @@ -1187,14 +1187,14 @@ you can add them, copy the link here, and press "Price Item" to evaluate the ite if not result then return end - local item = new("Item", result.item_string) + local item = new("Item"):Item(result.item_string) tooltip:Clear() local tooltipSlot = slotTbl.selectedJewelNodeId and self.itemsTab.sockets[slotTbl.selectedJewelNodeId] or activeSlot self.itemsTab:AddItemTooltip(tooltip, item, tooltipSlot) tooltip:AddSeparator(10) tooltip:AddLine(16, string.format("^7Price: %s %s", result.amount, result.currency)) end - controls["importButton"..row_idx] = new("ButtonControl", { "TOPLEFT", controls["resultDropdown"..row_idx], "TOPRIGHT"}, {8, 0, 100, row_height}, "Import Item", function() + controls["importButton"..row_idx] = new("ButtonControl"):ButtonControl({ "TOPLEFT", controls["resultDropdown"..row_idx], "TOPRIGHT"}, {8, 0, 100, row_height}, "Import Item", function() self.itemsTab:CreateDisplayItemFromRaw(self.resultTbl[row_idx][self.itemIndexTbl[row_idx]].item_string) local item = self.itemsTab.displayItem -- pass "true" to not auto equip it as we will have our own logic @@ -1226,8 +1226,7 @@ you can add them, copy the link here, and press "Price Item" to evaluate the ite return self.itemIndexTbl[row_idx] and self.resultTbl[row_idx][self.itemIndexTbl[row_idx]].item_string ~= nil end -- Whisper so we can copy to clipboard - controls["whisperButton" .. row_idx] = new("ButtonControl", - { "TOPLEFT", controls["importButton" .. row_idx], "TOPRIGHT" }, { 8, 0, 155, row_height }, function() + controls["whisperButton" .. row_idx] = new("ButtonControl"):ButtonControl({ "TOPLEFT", controls["importButton" .. row_idx], "TOPRIGHT" }, { 8, 0, 155, row_height }, function() local itemResult = self.itemIndexTbl[row_idx] and self.resultTbl[row_idx][self.itemIndexTbl[row_idx]] if not itemResult then return "" end diff --git a/src/Classes/TradeQuery.lua.rej b/src/Classes/TradeQuery.lua.rej new file mode 100644 index 0000000000..3dba05f3f7 --- /dev/null +++ b/src/Classes/TradeQuery.lua.rej @@ -0,0 +1,176 @@ +diff a/src/Classes/TradeQuery.lua b/src/Classes/TradeQuery.lua (rejected hunks) +@@ -19,7 +19,10 @@ local s_format = string.format + + local baseSlots = { "Weapon 1", "Weapon 2", "Weapon 1 Swap", "Weapon 2 Swap", "Helmet", "Body Armour", "Gloves", "Boots", "Amulet", "Ring 1", "Ring 2", "Ring 3", "Belt", "Flask 1", "Flask 2", "Flask 3", "Flask 4", "Flask 5" } + +-local TradeQueryClass = newClass("TradeQuery", function(self, itemsTab) ++---@class TradeQuery ++local TradeQueryClass = newClass("TradeQuery") ++ ++function TradeQueryClass:TradeQuery(itemsTab) + self.itemsTab = itemsTab + self.itemsTab.leagueDropList = { } + self.totalPrice = { } +@@ -56,15 +59,16 @@ local TradeQueryClass = newClass("TradeQuery", function(self, itemsTab) + -- last query for each row + self.lastQueries = {} + +- self.tradeQueryRequests = new("TradeQueryRequests") ++ self.tradeQueryRequests = new("TradeQueryRequests"):TradeQueryRequests() + if not main.api then +- main.api = new("PoEAPI", main.lastToken, main.lastRefreshToken, main.tokenExpiry) ++ main.api = new("PoEAPI"):PoEAPI(main.lastToken, main.lastRefreshToken, main.tokenExpiry) + end + + self.hostName = "https://www.pathofexile.com/" + -- www. optional + self.hostNamePattern = "h?t?t?p?s?:?/?/?w?w?w?%.?pathofexile%.com/" +-end) ++ return self ++end + + + +@@ -323,7 +327,7 @@ function TradeQueryClass:PriceItem() + end + end) + end +- self.controls.tradeAuthButton = new("ButtonControl", {"TOPLEFT", self.controls.setSelect, "TOPLEFT"}, {0, row_height + row_vertical_padding, 188, row_height}, self.loginStatus, function() ++ self.controls.tradeAuthButton = new("ButtonControl"):ButtonControl({"TOPLEFT", self.controls.setSelect, "TOPLEFT"}, {0, row_height + row_vertical_padding, 188, row_height}, self.loginStatus, function() + -- LOGIN + if not main.api.authToken then + main.api:FetchAuthToken(function() +@@ -378,7 +382,7 @@ on trade site to work on other leagues and realms)]] + "Any (includes offline)" + } + +- self.controls.tradeTypeSelection = new("DropDownControl", { "TOPLEFT", self.controls.tradeAuthButton, "BOTTOMLEFT" }, ++ self.controls.tradeTypeSelection = new("DropDownControl"):DropDownControl({ "TOPLEFT", self.controls.tradeAuthButton, "BOTTOMLEFT" }, + { 0, row_vertical_padding, 188, row_height }, self.tradeTypes, function(index, value) + self.tradeTypeIndex = index + end) +@@ -451,11 +455,11 @@ Lowest Price - Sorts from lowest to highest price of retrieved items + Highest Weight - Displays the order retrieved from trade]] + -- avoid calling selFunc to avoid updating controls before they are initialised + self.controls.itemSortSelection:SetSel(self.pbItemSortSelectionIndex, true) +- self.controls.itemSortSelectionLabel = new("LabelControl", {"TOPRIGHT", self.controls.itemSortSelection, "TOPLEFT"}, {-4, 0, 56, 16}, "^7Sort By:") ++ self.controls.itemSortSelectionLabel = new("LabelControl"):LabelControl({"TOPRIGHT", self.controls.itemSortSelection, "TOPLEFT"}, {-4, 0, 56, 16}, "^7Sort By:") + + -- Realm selection +- self.controls.realmLabel = new("LabelControl", {"LEFT", self.controls.setSelect, "RIGHT"}, {18, 0, 20, row_height - 4}, "^7Realm:") +- self.controls.realm = new("DropDownControl", {"LEFT", self.controls.realmLabel, "RIGHT"}, {6, 0, 150, row_height}, self.realmDropList, function(index, value) ++ self.controls.realmLabel = new("LabelControl"):LabelControl({"LEFT", self.controls.setSelect, "RIGHT"}, {18, 0, 20, row_height - 4}, "^7Realm:") ++ self.controls.realm = new("DropDownControl"):DropDownControl({"LEFT", self.controls.realmLabel, "RIGHT"}, {6, 0, 150, row_height}, self.realmDropList, function(index, value) + self.pbRealmIndex = index + if self.pbRealm ~= self.realmIds[value] then + self.pbRealm = self.realmIds[value] +@@ -497,8 +501,8 @@ Highest Weight - Displays the order retrieved from trade]] + end + + -- League selection +- self.controls.leagueLabel = new("LabelControl", {"TOPRIGHT", self.controls.realmLabel, "TOPRIGHT"}, {0, row_height + row_vertical_padding, 20, row_height - 4}, "^7League:") +- self.controls.league = new("DropDownControl", {"LEFT", self.controls.leagueLabel, "RIGHT"}, {6, 0, 150, row_height}, self.itemsTab.leagueDropList, function(index, value) ++ self.controls.leagueLabel = new("LabelControl"):LabelControl({"TOPRIGHT", self.controls.realmLabel, "TOPRIGHT"}, {0, row_height + row_vertical_padding, 20, row_height - 4}, "^7League:") ++ self.controls.league = new("DropDownControl"):DropDownControl({"LEFT", self.controls.leagueLabel, "RIGHT"}, {6, 0, 150, row_height}, self.itemsTab.leagueDropList, function(index, value) + self.pbLeagueIndex = index + self.pbLeague = value + end) +@@ -554,7 +558,7 @@ Highest Weight - Displays the order retrieved from trade]] + t_insert(slotTables, { slotName = self.itemsTab.sockets[nodeId].label, nodeId = nodeId }) + end + +- self.controls.sectionAnchor = new("LabelControl", {"LEFT", self.controls.tradeTypeSelection, "LEFT"}, {0, row_vertical_padding, 0, 0}, "") ++ self.controls.sectionAnchor = new("LabelControl"):LabelControl({"LEFT", self.controls.tradeTypeSelection, "LEFT"}, {0, row_vertical_padding, 0, 0}, "") + top_pane_alignment_ref = {"TOPLEFT", self.controls.sectionAnchor, "TOPLEFT"} + local scrollBarShown = #slotTables > 21 -- clipping starts beyond this + -- dynamically hide rows that are above or below the scrollBar +@@ -615,15 +619,15 @@ Highest Weight - Displays the order retrieved from trade]] + self.pane_height = (row_height + row_vertical_padding) * effective_row_count + 3 * pane_margins_vertical + row_height / 2 + local pane_width = 885 + (scrollBarShown and 25 or 0) + +- self.controls.scrollBar = new("ScrollBarControl", {"TOPRIGHT", self.controls["StatWeightMultipliersButton"],"TOPRIGHT"}, {0, 25, 18, 0}, 50, "VERTICAL", false) ++ self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({"TOPRIGHT", self.controls["StatWeightMultipliersButton"],"TOPRIGHT"}, {0, 25, 18, 0}, 50, "VERTICAL", false) + self.controls.scrollBar.shown = function() return scrollBarShown end + +- self.controls.fullPrice = new("LabelControl", {"BOTTOM", nil, "BOTTOM"}, {0, -row_height - pane_margins_vertical - row_vertical_padding, pane_width - 2 * pane_margins_horizontal, row_height}, "") +- self.controls.close = new("ButtonControl", {"BOTTOM", nil, "BOTTOM"}, {0, -pane_margins_vertical, 90, row_height}, "Done", function() ++ self.controls.fullPrice = new("LabelControl"):LabelControl({"BOTTOM", nil, "BOTTOM"}, {0, -row_height - pane_margins_vertical - row_vertical_padding, pane_width - 2 * pane_margins_horizontal, row_height}, "") ++ self.controls.close = new("ButtonControl"):ButtonControl({"BOTTOM", nil, "BOTTOM"}, {0, -pane_margins_vertical, 90, row_height}, "Done", function() + main:ClosePopup() + end) + +- self.controls.pbNotice = new("LabelControl", {"BOTTOMRIGHT", nil, "BOTTOMRIGHT"}, {-row_height - pane_margins_vertical - row_vertical_padding, -pane_margins_vertical, 300, row_height}, "") ++ self.controls.pbNotice = new("LabelControl"):LabelControl({"BOTTOMRIGHT", nil, "BOTTOMRIGHT"}, {-row_height - pane_margins_vertical - row_vertical_padding, -pane_margins_vertical, 300, row_height}, "") + + -- used in PopupDialog:Draw() + local function scrollBarFunc() +@@ -835,7 +839,7 @@ function TradeQueryClass:GetResultEvaluation(row_idx, result_index, calcFunc, ba + } + table.sort(result.evaluation, function(a, b) return a.weight > b.weight end) + else +- local item = new("Item", result.item_string) ++ local item = new("Item"):Item(result.item_string) + + local output = self:ReduceOutput(calcFunc({ repSlotName = slotName, repItem = item })) + local weight = self.tradeQueryGenerator.WeightedRatioOutputs(baseOutput, output, self.statSortSelectionList) +@@ -1015,8 +1019,8 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro + return selectedNodeId and self.itemsTab.sockets[selectedNodeId] or activeSlot + end + local nameColor = slotTbl.unique and colorCodes.UNIQUE or "^7" +- controls["name" .. row_idx] = new("LabelControl", top_pane_alignment_ref, { 0, row_idx * (row_height + row_vertical_padding), 135, row_height - 4 }, nameColor .. slotTbl.slotName) +- controls["bestButton" .. row_idx] = new("ButtonControl", { "LEFT", controls["name" .. row_idx], "LEFT" }, { 135 + 8, 0, 80, row_height }, "Find best", function() ++ controls["name" .. row_idx] = new("LabelControl"):LabelControl(top_pane_alignment_ref, { 0, row_idx * (row_height + row_vertical_padding), 135, row_height - 4 }, nameColor .. slotTbl.slotName) ++ controls["bestButton" .. row_idx] = new("ButtonControl"):ButtonControl({ "LEFT", controls["name" .. row_idx], "LEFT" }, { 135 + 8, 0, 80, row_height }, "Find best", function() + self.tradeQueryGenerator:RequestQuery(activeSlot, { slotTbl = slotTbl, controls = controls, row_idx = row_idx }, self.statSortSelectionList, function(context, query, errMsg) + if errMsg then + self:SetNotice(context.controls.pbNotice, colorCodes.NEGATIVE .. errMsg) +@@ -1047,7 +1051,7 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro + -- replace eldritch mods or enchants if the user requested + -- so in TradeQueryGenerator + for i, _ in ipairs(itemsSafe) do +- local item = new("Item", itemsSafe[i].item_string) ++ local item = new("Item"):Item(itemsSafe[i].item_string) + -- assume the user will add quality if they buy the item + item:NormaliseQuality() + if self.tradeQueryGenerator.lastIncludeEldritch == "Copy Current" or +@@ -1095,7 +1099,7 @@ you can add them, copy the link here, and press "Price Item" to evaluate the ite + itemSlotHelper.DrawViewer(self.itemsTab, nodeId, viewerX, viewerY, boxSize, boxSize) + end + local pbURL +- controls["uri"..row_idx] = new("EditControl", { "TOPLEFT", controls["bestButton"..row_idx], "TOPRIGHT"}, {8, 0, 514, row_height}, nil, nil, "^%C\t\n", nil, function(buf) ++ controls["uri"..row_idx] = new("EditControl"):EditControl({ "TOPLEFT", controls["bestButton"..row_idx], "TOPRIGHT"}, {8, 0, 514, row_height}, nil, nil, "^%C\t\n", nil, function(buf) + local subpath = buf:match(self.hostNamePattern .. "trade/search/(.+)$") or "" + local paths = {} + for path in subpath:gmatch("[^/]+") do +@@ -1122,7 +1126,7 @@ you can add them, copy the link here, and press "Price Item" to evaluate the ite + tooltip:AddLine(16, "Control + click to open in web-browser") + end + end +- controls["priceButton"..row_idx] = new("ButtonControl", { "TOPLEFT", controls["uri"..row_idx], "TOPRIGHT"}, {8, 0, 100, row_height}, "Price Item", ++ controls["priceButton"..row_idx] = new("ButtonControl"):ButtonControl({ "TOPLEFT", controls["uri"..row_idx], "TOPRIGHT"}, {8, 0, 100, row_height}, "Price Item", + function() + controls["priceButton"..row_idx].label = "Searching..." + local url = controls["uri" .. row_idx].buf +@@ -1164,11 +1168,11 @@ you can add them, copy the link here, and press "Price Item" to evaluate the ite + local clampItemIndex = function(index) + return m_min(m_max(index or 1, 1), self.sortedResultTbl[row_idx] and #self.sortedResultTbl[row_idx] or 1) + end +- controls["changeButton" .. row_idx] = new("ButtonControl", { "LEFT", controls["name" .. row_idx], "LEFT" }, { 135 + 8, 0, 80, row_height }, "<< Search", function() ++ controls["changeButton" .. row_idx] = new("ButtonControl"):ButtonControl({ "LEFT", controls["name" .. row_idx], "LEFT" }, { 135 + 8, 0, 80, row_height }, "<< Search", function() + self:ResetResultRow(row_idx) + end) + controls["changeButton"..row_idx].shown = function() return self.resultTbl[row_idx] end +- controls["resultDropdown" .. row_idx] = new("DropDownControl", { "TOPLEFT", controls["changeButton" .. row_idx], "TOPRIGHT" }, { 8, 0, 351, row_height }, {}, function(index) ++ controls["resultDropdown" .. row_idx] = new("DropDownControl"):DropDownControl({ "TOPLEFT", controls["changeButton" .. row_idx], "TOPRIGHT" }, { 8, 0, 351, row_height }, {}, function(index) + self.itemIndexTbl[row_idx] = self.sortedResultTbl[row_idx][index].index + self:SetFetchResultReturn(row_idx, self.itemIndexTbl[row_idx]) + end) +@@ -1225,7 +1229,7 @@ you can add them, copy the link here, and press "Price Item" to evaluate the ite + local selected_result_index = self.itemIndexTbl[row_idx] + local item_string = self.resultTbl[row_idx][selected_result_index].item_string + if selected_result_index and item_string then +- local item = new("Item", item_string) ++ local item = new("Item"):Item(item_string) + local tooltipSlot = slotTbl.selectedJewelNodeId and self.itemsTab.sockets[slotTbl.selectedJewelNodeId] or activeSlot + self.itemsTab:AddItemTooltip(tooltip, item, tooltipSlot, true) + addMegalomaniacCompareToTooltipIfApplicable(tooltip, selected_result_index) diff --git a/src/Classes/TradeQueryGenerator.lua b/src/Classes/TradeQueryGenerator.lua index 415a668a0f..cb26c1a21c 100644 --- a/src/Classes/TradeQueryGenerator.lua +++ b/src/Classes/TradeQueryGenerator.lua @@ -111,7 +111,10 @@ local function logToFile(...) ConPrintf(...) end -local TradeQueryGeneratorClass = newClass("TradeQueryGenerator", function(self, queryTab) +---@class TradeQueryGenerator +local TradeQueryGeneratorClass = newClass("TradeQueryGenerator") + +function TradeQueryGeneratorClass:TradeQueryGenerator(queryTab) self:InitMods() self.queryTab = queryTab self.itemsTab = queryTab.itemsTab @@ -868,7 +871,7 @@ Implicits: 0]] -- Open progress tracking blocker popup local controls = { } - controls.progressText = new("LabelControl", {"TOP",nil,"TOP"}, {0, 30, 0, 16}, string.format("Calculating Mod Weights...")) + controls.progressText = new("LabelControl"):LabelControl({"TOP",nil,"TOP"}, {0, 30, 0, 16}, string.format("Calculating Mod Weights...")) self.calcContext.popup = main:OpenPopup(280, 65, "Please Wait", controls) end @@ -1332,7 +1335,7 @@ Remove: anoints are completely ignored, and removed from items.]] local _, lastItemY = lastItemAnchor:GetPos() local _, lastItemH = lastItemAnchor:GetSize() - controls.modSelectorHeaderAnchor = new("Control", { "TOPLEFT", nil, "TOPLEFT" }, + controls.modSelectorHeaderAnchor = new("Control"):Control({ "TOPLEFT", nil, "TOPLEFT" }, -- position right below last item, centered horizontally { (popupWidth - totalWidth) / 2, lastItemH + lastItemY, 0, 0 }, "") @@ -1390,7 +1393,7 @@ Remove: anoints are completely ignored, and removed from items.]] -- mod filter dropdown and aux controls for i = 1, maxSelectors do -- dropdown which lists all mods that fit - local dropdown = new("DropDownControl", { "TOPLEFT", lastItemAnchor, "BOTTOMLEFT" }, + local dropdown = new("DropDownControl"):DropDownControl({ "TOPLEFT", lastItemAnchor, "BOTTOMLEFT" }, { 0, 4, totalWidth, 20 }, nil, function(idx, val) if idx == 1 then @@ -1418,7 +1421,7 @@ Remove: anoints are completely ignored, and removed from items.]] controls["modSelectorMin" .. i] = minimumBox -- button which removes the mod row - local clearButton = new("ButtonControl", { "LEFT", minimumBox, "RIGHT" }, { xSpacing, 0, buttonSize, buttonSize }, + local clearButton = new("ButtonControl"):ButtonControl({ "LEFT", minimumBox, "RIGHT" }, { xSpacing, 0, buttonSize, buttonSize }, "x", function() table.remove(selectedMods, i) setModSelectors(controls) diff --git a/src/Classes/TradeQueryGenerator.lua.rej b/src/Classes/TradeQueryGenerator.lua.rej new file mode 100644 index 0000000000..59cbc99fd6 --- /dev/null +++ b/src/Classes/TradeQueryGenerator.lua.rej @@ -0,0 +1,10 @@ +diff a/src/Classes/TradeQueryGenerator.lua b/src/Classes/TradeQueryGenerator.lua (rejected hunks) +@@ -83,7 +83,7 @@ local function canModSpawnForItemCategory(mod, category) + end + end + -- mock item +- local itemClass = new("Item") ++ local itemClass = new("Item"):Item() + local itemObj = {} + -- add all influences to fake item + for _, curInfluenceInfo in ipairs(itemLib.influenceInfo.all) do diff --git a/src/Classes/TradeQueryRateLimiter.lua b/src/Classes/TradeQueryRateLimiter.lua index c96b5c9068..896b86cc8c 100644 --- a/src/Classes/TradeQueryRateLimiter.lua +++ b/src/Classes/TradeQueryRateLimiter.lua @@ -6,7 +6,9 @@ -- ---@class TradeQueryRateLimiter -local TradeQueryRateLimiterClass = newClass("TradeQueryRateLimiter", function(self) +local TradeQueryRateLimiterClass = newClass("TradeQueryRateLimiter") + +function TradeQueryRateLimiterClass:TradeQueryRateLimiter() -- policies_sample = { -- -- label: policy -- ["trade-search-request-limit"] = { diff --git a/src/Classes/TradeQueryRateLimiter.lua.rej b/src/Classes/TradeQueryRateLimiter.lua.rej new file mode 100644 index 0000000000..2237082e9e --- /dev/null +++ b/src/Classes/TradeQueryRateLimiter.lua.rej @@ -0,0 +1,11 @@ +diff a/src/Classes/TradeQueryRateLimiter.lua b/src/Classes/TradeQueryRateLimiter.lua (rejected hunks) +@@ -56,7 +58,8 @@ local TradeQueryRateLimiterClass = newClass("TradeQueryRateLimiter", function(se + ["character-list-request-limit"] = {}, + ["character-request-limit"] = {} + } +-end) ++ return self ++end + + function TradeQueryRateLimiterClass:GetPolicyName(key) + return self.policyNames[key] diff --git a/src/Classes/TradeQueryRequests.lua.rej b/src/Classes/TradeQueryRequests.lua.rej new file mode 100644 index 0000000000..742e002c9c --- /dev/null +++ b/src/Classes/TradeQueryRequests.lua.rej @@ -0,0 +1,25 @@ +diff a/src/Classes/TradeQueryRequests.lua b/src/Classes/TradeQueryRequests.lua (rejected hunks) +@@ -8,17 +8,19 @@ local dkjson = require "dkjson" + local utils = LoadModule("Modules/Utils") + + ---@class TradeQueryRequests +-local TradeQueryRequestsClass = newClass("TradeQueryRequests", function(self, rateLimiter) ++local TradeQueryRequestsClass = newClass("TradeQueryRequests") ++ ++function TradeQueryRequestsClass:TradeQueryRequests(rateLimiter) + self.maxFetchPerSearch = 10 +- self.tradeQuery = tradeQuery +- self.rateLimiter = rateLimiter or new("TradeQueryRateLimiter") ++ self.rateLimiter = rateLimiter or new("TradeQueryRateLimiter"):TradeQueryRateLimiter() + self.requestQueue = { + ["search"] = {}, + ["fetch"] = {}, + } + self.hostName = "https://www.pathofexile.com/" + self.hostNamePattern = "h?t?t?p?s?:?/?/?w?w?w?%.?pathofexile%.com/" +-end) ++ return self ++end + + ---Main routine for processing request queue + --- @param onRateLimit fun(integer)? diff --git a/src/Classes/TradeStatWeightMultiplierListControl.lua b/src/Classes/TradeStatWeightMultiplierListControl.lua index f0260d89de..3be20855b1 100644 --- a/src/Classes/TradeStatWeightMultiplierListControl.lua +++ b/src/Classes/TradeStatWeightMultiplierListControl.lua @@ -4,12 +4,16 @@ -- Specialized UI element for listing and modifying Trade Stat Weight Multipliers. -- -local TradeStatWeightMultiplierListControlClass = newClass("TradeStatWeightMultiplierListControl", "ListControl", function(self, anchor, rect, list, indexController) +---@class TradeStatWeightMultiplierListControl: ListControl +local TradeStatWeightMultiplierListControlClass = newClass("TradeStatWeightMultiplierListControl", "ListControl") + +function TradeStatWeightMultiplierListControlClass:TradeStatWeightMultiplierListControl(anchor, rect, list, indexController) self.list = list self.indexController = indexController - self.ListControl(anchor, rect, 16, true, false, self.list) + self:ListControl(anchor, rect, 16, true, false, self.list) self.selIndex = nil -end) + return self +end function TradeStatWeightMultiplierListControlClass:Draw(viewPort, noTooltip) self.noTooltip = noTooltip diff --git a/src/Classes/TreeTab.lua b/src/Classes/TreeTab.lua index b6df152ddc..fed700c636 100644 --- a/src/Classes/TreeTab.lua +++ b/src/Classes/TreeTab.lua @@ -115,7 +115,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) end -- Compare checkbox - self.controls.compareCheck = new("CheckBoxControl", { "LEFT", self.controls.specSelect, "RIGHT" }, { 74, 0, 20 }, "Compare:", function(state) + self.controls.compareCheck = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.specSelect, "RIGHT" }, { 74, 0, 20 }, "Compare:", function(state) self.isComparing = state self:SetCompareSpec(self.activeCompareSpec) self.controls.compareSelect.shown = state @@ -127,7 +127,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) end) -- Compare tree dropdown - self.controls.compareSelect = new("DropDownControl", { "LEFT", self.controls.compareCheck, "RIGHT" }, { 8, 0, 190, 20 }, nil, function(index, value) + self.controls.compareSelect = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.compareCheck, "RIGHT" }, { 8, 0, 190, 20 }, nil, function(index, value) if self.specList[index] then self:SetCompareSpec(index) else @@ -177,7 +177,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) self.controls.versionSelect.selIndex = #self.treeVersions -- Tree Search Textbox - self.controls.treeSearch = new("EditControl", { "LEFT", self.controls.versionSelect, "RIGHT" }, { 8, 0, main.portraitMode and 200 or 300, 20 }, "", "Search", "%c", 100, function(buf) + self.controls.treeSearch = new("EditControl"):EditControl({ "LEFT", self.controls.versionSelect, "RIGHT" }, { 8, 0, main.portraitMode and 200 or 300, 20 }, "", "Search", "%c", 100, function(buf) self.viewer.searchStr = buf self.searchFlag = buf ~= self.viewer.searchStrSaved end, nil, nil, true) @@ -201,7 +201,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) end) -- Control for setting max node depth to limit calculation time of the heat map - self.controls.nodePowerMaxDepthSelect = new("DropDownControl", { "LEFT", self.controls.treeHeatMap, "RIGHT" }, { 8, 0, 55, 20 }, { "All", 5, 10, 15, "Custom" }, function(index, value) + self.controls.nodePowerMaxDepthSelect = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.treeHeatMap, "RIGHT" }, { 8, 0, 55, 20 }, { "All", 5, 10, 15, "Custom" }, function(index, value) -- Show custom value control and resize/move elements self.isCustomMaxDepth = value == "Custom" if self.isCustomMaxDepth then @@ -234,7 +234,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) self.controls.nodePowerMaxDepthSelect.tooltipText = "Limit of Node distance to search (lower = faster)" -- Control for setting max node depth by custom value - self.controls.nodePowerMaxDepthCustom = new("EditControl", { "LEFT", self.controls.nodePowerMaxDepthSelect, "RIGHT" }, { 8, 0, 70, 20 }, "0", nil, "%D", nil, function(value) + self.controls.nodePowerMaxDepthCustom = new("EditControl"):EditControl({ "LEFT", self.controls.nodePowerMaxDepthSelect, "RIGHT" }, { 8, 0, 70, 20 }, "0", nil, "%D", nil, function(value) self.build.calcsTab.nodePowerMaxDepth = tonumber(value) -- If the heat map is shown, recalculate it with new value @@ -245,7 +245,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) self.controls.nodePowerMaxDepthCustom.shown = false -- Control for selecting the power stat to sort by (Defense, DPS, etc) - self.controls.treeHeatMapStatSelect = new("DropDownControl", { "LEFT", self.controls.nodePowerMaxDepthSelect, "RIGHT" }, { 8, 0, 150, 20 }, nil, function(index, value) + self.controls.treeHeatMapStatSelect = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.nodePowerMaxDepthSelect, "RIGHT" }, { 8, 0, 150, 20 }, nil, function(index, value) self:SetPowerCalc(value) end) self.controls.treeHeatMap.tooltipText = function() @@ -261,14 +261,14 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) end -- Show/Hide Power Report Button - self.controls.powerReport = new("ButtonControl", { "LEFT", self.controls.treeHeatMapStatSelect, "RIGHT" }, { 8, 0, 150, 20 }, + self.controls.powerReport = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.treeHeatMapStatSelect, "RIGHT" }, { 8, 0, 150, 20 }, function() return self.controls.powerReportList.shown and "Hide Power Report" or "Show Power Report" end, function() self.controls.powerReportList.shown = not self.controls.powerReportList.shown end) -- Power Report List local yPos = self.controls.treeHeatMap.y == 0 and self.controls.specSelect.height + 4 or self.controls.specSelect.height * 2 + 8 - self.controls.powerReportList = new("PowerReportListControl", { "TOPLEFT", self.controls.specSelect, "BOTTOMLEFT" }, { 0, yPos, 700, 170 }, function(selectedNode) + self.controls.powerReportList = new("PowerReportListControl"):PowerReportListControl({ "TOPLEFT", self.controls.specSelect, "BOTTOMLEFT" }, { 0, yPos, 700, 170 }, function(selectedNode) -- this code is called by the list control when the user "selects" one of the passives in the list. -- we use this to set a flag which causes the next Draw() to recenter the passive tree on the desired node. if selectedNode.x then @@ -489,7 +489,7 @@ function TreeTabClass:Load(xml, dbFileName) self.specList = { } if xml.elem == "Spec" then -- Import single spec from old build - self.specList[1] = new("PassiveSpec", self.build, defaultTreeVersion) + self.specList[1] = new("PassiveSpec"):PassiveSpec(self.build, defaultTreeVersion) self.specList[1]:Load(xml, dbFileName) self.activeSpec = 1 self.build.spec = self.specList[1] @@ -502,14 +502,14 @@ function TreeTabClass:Load(xml, dbFileName) main:OpenMessagePopup("Unknown Passive Tree Version", "The build you are trying to load uses an unrecognised version of the passive skill tree.\nYou may need to update the program before loading this build.") return true end - local newSpec = new("PassiveSpec", self.build, node.attrib.treeVersion or defaultTreeVersion) + local newSpec = new("PassiveSpec"):PassiveSpec(self.build, node.attrib.treeVersion or defaultTreeVersion) newSpec:Load(node, dbFileName) t_insert(self.specList, newSpec) end end end if not self.specList[1] then - self.specList[1] = new("PassiveSpec", self.build, latestTreeVersion) + self.specList[1] = new("PassiveSpec"):PassiveSpec(self.build, latestTreeVersion) end self:SetActiveSpec(tonumber(xml.attrib.activeSpec) or 1) end @@ -675,13 +675,13 @@ end function TreeTabClass:OpenVersionConvertAllPopup(version) local controls = { } - controls.warningLabel = new("LabelControl", nil, {0, 20, 0, 16}, "^7Warning: some or all of the passives may be de-allocated due to changes in the tree.\n\n" .. + controls.warningLabel = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Warning: some or all of the passives may be de-allocated due to changes in the tree.\n\n" .. "Convert will replace all trees that are not Version "..treeVersions[version].display..".\nThis action cannot be undone.\n") - controls.convert = new("ButtonControl", nil, {-58, 105, 100, 20}, "Convert", function() + controls.convert = new("ButtonControl"):ButtonControl(nil, {-58, 105, 100, 20}, "Convert", function() self:ConvertAllToVersion(version) main:ClosePopup() end) - controls.cancel = new("ButtonControl", nil, {58, 105, 100, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {58, 105, 100, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(570, 140, "Convert all to Version "..treeVersions[version].display, controls, "convert", "edit") @@ -692,7 +692,7 @@ function TreeTabClass:OpenImportPopup() local controls = { } local function decodePoePlannerTreeLink(treeLink) -- treeVersion is not known at this point. We need to decode the URL to get it. - local tmpSpec = new("PassiveSpec", self.build, latestTreeVersion) + local tmpSpec = new("PassiveSpec"):PassiveSpec(self.build, latestTreeVersion) local newTreeVersion_or_errMsg = tmpSpec:DecodePoePlannerURL(treeLink, true) -- Check for an error message if string.find(newTreeVersion_or_errMsg, "Invalid") then @@ -701,7 +701,7 @@ function TreeTabClass:OpenImportPopup() end -- 20230908. We always create a new Spec() - local newSpec = new("PassiveSpec", self.build, newTreeVersion_or_errMsg) + local newSpec = new("PassiveSpec"):PassiveSpec(self.build, newTreeVersion_or_errMsg) newSpec.title = controls.name.buf newSpec:DecodePoePlannerURL(treeLink, false) --DecodePoePlannerURL was used above and URL proven correct. t_insert(self.specList, newSpec) @@ -808,7 +808,7 @@ function TreeTabClass:OpenImportPopup() end end) controls.import.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 85, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 85, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(580, 115, "Import Tree", controls, "import", "name") @@ -818,9 +818,9 @@ function TreeTabClass:OpenExportPopup() local treeLink = self.build.spec:EncodeURL(treeVersions[self.build.spec.treeVersion].url) local popup local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "Passive tree link:") - controls.edit = new("EditControl", nil, {0, 40, 350, 18}, treeLink, nil, "%Z") - controls.shrink = new("ButtonControl", nil, {-90, 70, 140, 20}, "Shrink with PoEURL", function() + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "Passive tree link:") + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 18}, treeLink, nil, "%Z") + controls.shrink = new("ButtonControl"):ButtonControl(nil, {-90, 70, 140, 20}, "Shrink with PoEURL", function() controls.shrink.enabled = false controls.shrink.label = "Shrinking..." launch:DownloadPage("http://poeurl.com/shrink.php?url="..treeLink, function(response, errMsg) @@ -834,10 +834,10 @@ function TreeTabClass:OpenExportPopup() end end) end) - controls.copy = new("ButtonControl", nil, {30, 70, 80, 20}, "Copy", function() + controls.copy = new("ButtonControl"):ButtonControl(nil, {30, 70, 80, 20}, "Copy", function() Copy(treeLink) end) - controls.done = new("ButtonControl", nil, {120, 70, 80, 20}, "Done", function() + controls.done = new("ButtonControl"):ButtonControl(nil, {120, 70, 80, 20}, "Done", function() main:ClosePopup() end) popup = main:OpenPopup(380, 100, "Export Tree", controls, "done", "edit") @@ -1043,7 +1043,7 @@ function TreeTabClass:BuildPowerReportList(currentStat) end function TreeTabClass:FindTimelessJewel() - local socketViewer = new("PassiveTreeView") + local socketViewer = new("PassiveTreeView"):PassiveTreeView() local treeData = self.build.spec.tree local legionNodes = treeData.legion.nodes local legionAdditions = treeData.legion.additions @@ -1473,8 +1473,8 @@ function TreeTabClass:FindTimelessJewel() end local socketFilterAdditionalDistanceMAX = 10 - controls.socketFilterAdditionalDistanceLabel = new("LabelControl", {"LEFT", controls.socketFilter, "RIGHT"}, {10, 0, 0, 16}, "^7Node Distance:") - controls.socketFilterAdditionalDistance = new("SliderControl", {"LEFT", controls.socketFilterAdditionalDistanceLabel, "RIGHT"}, {10, 0, 66, 18}, function(value) + controls.socketFilterAdditionalDistanceLabel = new("LabelControl"):LabelControl({"LEFT", controls.socketFilter, "RIGHT"}, {10, 0, 0, 16}, "^7Node Distance:") + controls.socketFilterAdditionalDistance = new("SliderControl"):SliderControl({"LEFT", controls.socketFilterAdditionalDistanceLabel, "RIGHT"}, {10, 0, 66, 18}, function(value) timelessData.socketFilterDistance = m_floor(value * socketFilterAdditionalDistanceMAX + 0.01) controls.socketFilterAdditionalDistanceValue.label = s_format("^7%d", timelessData.socketFilterDistance) end, { ["SHIFT"] = 1, ["CTRL"] = 1 / (socketFilterAdditionalDistanceMAX * 2), ["DEFAULT"] = 1 / socketFilterAdditionalDistanceMAX }) @@ -1493,7 +1493,7 @@ function TreeTabClass:FindTimelessJewel() end return controls.socketFilterAdditionalDistance.tooltip.realDraw(self, x, y, width, height, viewPort) end - controls.socketFilterAdditionalDistanceValue = new("LabelControl", {"LEFT", controls.socketFilterAdditionalDistance, "RIGHT"}, {5, 0, 0, 16}, "^70") + controls.socketFilterAdditionalDistanceValue = new("LabelControl"):LabelControl({"LEFT", controls.socketFilterAdditionalDistance, "RIGHT"}, {5, 0, 0, 16}, "^70") controls.socketFilterAdditionalDistance:SetVal((timelessData.socketFilterDistance or 0) / socketFilterAdditionalDistanceMAX) controls.socketFilterAdditionalDistanceLabel.shown = timelessData.socketFilter controls.socketFilterAdditionalDistance.shown = timelessData.socketFilter @@ -1519,7 +1519,7 @@ function TreeTabClass:FindTimelessJewel() end end end - controls.nodeSliderValue = new("LabelControl", {"LEFT", controls.nodeSlider, "RIGHT"}, {5, 0, 0, 16}, "^71.000") + controls.nodeSliderValue = new("LabelControl"):LabelControl({"LEFT", controls.nodeSlider, "RIGHT"}, {5, 0, 0, 16}, "^71.000") controls.nodeSlider.tooltip.realDraw = controls.nodeSlider.tooltip.Draw controls.nodeSlider.tooltip.Draw = function(self, x, y, width, height, viewPort) local sliderOffsetX = round(184 * (1 - controls.nodeSlider.val)) @@ -1548,7 +1548,7 @@ function TreeTabClass:FindTimelessJewel() end end end - controls.nodeSlider2Value = new("LabelControl", {"LEFT", controls.nodeSlider2, "RIGHT"}, {5, 0, 0, 16}, "^71.000") + controls.nodeSlider2Value = new("LabelControl"):LabelControl({"LEFT", controls.nodeSlider2, "RIGHT"}, {5, 0, 0, 16}, "^71.000") controls.nodeSlider2.tooltip.realDraw = controls.nodeSlider2.tooltip.Draw controls.nodeSlider2.tooltip.Draw = function(self, x, y, width, height, viewPort) local sliderOffsetX = round(184 * (1 - controls.nodeSlider2.val)) diff --git a/src/Classes/TreeTab.lua.rej b/src/Classes/TreeTab.lua.rej new file mode 100644 index 0000000000..776b8bc18c --- /dev/null +++ b/src/Classes/TreeTab.lua.rej @@ -0,0 +1,653 @@ +diff a/src/Classes/TreeTab.lua b/src/Classes/TreeTab.lua (rejected hunks) +@@ -19,24 +19,28 @@ local s_gsub = string.gsub + local s_byte = string.byte + local dkjson = require "dkjson" + +-local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) +- self.ControlHost() ++---@class TreeTab: ControlHost ++local TreeTabClass = newClass("TreeTab", "ControlHost") ++ ++---@param build Build ++function TreeTabClass:TreeTab(build) ++ self:ControlHost() + + self.build = build + self.isComparing = false; + self.isCustomMaxDepth = false; + +- self.viewer = new("PassiveTreeView") ++ self.viewer = new("PassiveTreeView"):PassiveTreeView() + + self.specList = { } +- self.specList[1] = new("PassiveSpec", build, latestTreeVersion) ++ self.specList[1] = new("PassiveSpec"):PassiveSpec(build, latestTreeVersion) + self:SetActiveSpec(1) + self:SetCompareSpec(1) + +- self.anchorControls = new("Control", nil, {0, 0, 0, 20}) ++ self.anchorControls = new("Control"):Control(nil, {0, 0, 0, 20}) + + -- Tree list dropdown +- self.controls.specSelect = new("DropDownControl", { "LEFT",self.anchorControls,"RIGHT" }, { 0, 0, 190, 20 }, nil, function(index, value) ++ self.controls.specSelect = new("DropDownControl"):DropDownControl({ "LEFT",self.anchorControls,"RIGHT" }, { 0, 0, 190, 20 }, nil, function(index, value) + if self.specList[index] then + self.build.modFlag = true + self:SetActiveSpec(index) +@@ -126,18 +130,18 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) + self.controls.compareSelect.maxDroppedWidth = 1000 + self.controls.compareSelect.enableDroppedWidth = true + self.controls.compareSelect.enableChangeBoxWidth = true +- self.controls.reset = new("ButtonControl", { "LEFT", self.controls.compareCheck, "RIGHT" }, { 8, 0, 145, 20 }, "Reset Tree/Tattoos", function() ++ self.controls.reset = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.compareCheck, "RIGHT" }, { 8, 0, 145, 20 }, "Reset Tree/Tattoos", function() + local controls = { } + local buttonY = 65 +- controls.warningLabel = new("LabelControl", nil, { 0, 30, 0, 16 }, "^7Warning: resetting your passive tree or removing all tattoos cannot be undone.\n") +- controls.reset = new("ButtonControl", nil, { -130, buttonY, 100, 20 }, "Reset Tree", function() ++ controls.warningLabel = new("LabelControl"):LabelControl(nil, { 0, 30, 0, 16 }, "^7Warning: resetting your passive tree or removing all tattoos cannot be undone.\n") ++ controls.reset = new("ButtonControl"):ButtonControl(nil, { -130, buttonY, 100, 20 }, "Reset Tree", function() + self.build.spec:ResetNodes() + self.build.spec:BuildAllDependsAndPaths() + self.build.spec:AddUndoState() + self.build.buildFlag = true + main:ClosePopup() + end) +- controls.removeTattoo = new("ButtonControl", nil, { 0, buttonY, 144, 20 }, "Remove All Tattoos", function() ++ controls.removeTattoo = new("ButtonControl"):ButtonControl(nil, { 0, buttonY, 144, 20 }, "Remove All Tattoos", function() + for id, node in pairs(self.build.spec.hashOverrides) do --hashOverrides will contain only the nodes that have been tattoo-ed + if node.isTattoo then + self:RemoveTattooFromNode(self.build.spec.nodes[id]) +@@ -147,7 +151,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) + self.build.buildFlag = true + main:ClosePopup() + end) +- controls.cancel = new("ButtonControl", nil, { 130, buttonY, 100, 20 }, "Cancel", function() ++ controls.cancel = new("ButtonControl"):ButtonControl(nil, { 130, buttonY, 100, 20 }, "Cancel", function() + main:ClosePopup() + end) + main:OpenPopup(570, 100, "Reset Tree/Tattoos", controls, nil, "edit", "cancel") +@@ -162,8 +166,8 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) + } + t_insert(self.treeVersions, value) + end +- self.controls.versionText = new("LabelControl", { "LEFT", self.controls.reset, "RIGHT" }, { 8, 0, 0, 16 }, "^7Version:") +- self.controls.versionSelect = new("DropDownControl", { "LEFT", self.controls.versionText, "RIGHT" }, { 8, 0, 100, 20 }, self.treeVersions, function(index, selected) ++ self.controls.versionText = new("LabelControl"):LabelControl({ "LEFT", self.controls.reset, "RIGHT" }, { 8, 0, 0, 16 }, "^7Version:") ++ self.controls.versionSelect = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.versionText, "RIGHT" }, { 8, 0, 100, 20 }, self.treeVersions, function(index, selected) + if selected.value ~= self.build.spec.treeVersion then + self:OpenVersionConvertPopup(selected.value, true) + end +@@ -184,7 +188,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) + -- table holding all realm/league pairs. (allLeagues[realm] = [league.id,...]) + self.tradeLeaguesList = {} + -- Find Timeless Jewel Button +- self.controls.findTimelessJewel = new("ButtonControl", { "LEFT", self.controls.treeSearch, "RIGHT" }, { 8, 0, 150, 20 }, "Find Timeless Jewel", function() ++ self.controls.findTimelessJewel = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.treeSearch, "RIGHT" }, { 8, 0, 150, 20 }, "Find Timeless Jewel", function() + self:FindTimelessJewel() + end) + +@@ -192,7 +196,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) + self.defaultTattoo = { } + + -- Show Node Power Checkbox +- self.controls.treeHeatMap = new("CheckBoxControl", { "LEFT", self.controls.findTimelessJewel, "RIGHT" }, { 130, 0, 20 }, "Show Node Power:", function(state) ++ self.controls.treeHeatMap = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.findTimelessJewel, "RIGHT" }, { 130, 0, 20 }, "Show Node Power:", function(state) + self.viewer.showHeatMap = state + self.controls.treeHeatMapStatSelect.shown = state + +@@ -319,7 +323,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) + end + end + +- self.controls.specConvertText = new("LabelControl", { "BOTTOMLEFT", self.controls.specSelect, "TOPLEFT" }, { 0, -14, 0, 16 }, "^7This is an older tree version, which may not be fully compatible with the current game version.") ++ self.controls.specConvertText = new("LabelControl"):LabelControl({ "BOTTOMLEFT", self.controls.specSelect, "TOPLEFT" }, { 0, -14, 0, 16 }, "^7This is an older tree version, which may not be fully compatible with the current game version.") + self.controls.specConvertText.shown = function() + return self.showConvert + end +@@ -332,16 +336,17 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) + local function buildConvertAllButtonLabel() + return colorCodes.POSITIVE.."Convert all trees to "..treeVersions[getLatestTreeVersion()].display + end +- self.controls.specConvert = new("ButtonControl", { "LEFT", self.controls.specConvertText, "RIGHT" }, { 8, 0, function() return DrawStringWidth(16, "VAR", buildConvertButtonLabel()) + 20 end, 20 }, buildConvertButtonLabel, function() ++ self.controls.specConvert = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.specConvertText, "RIGHT" }, { 8, 0, function() return DrawStringWidth(16, "VAR", buildConvertButtonLabel()) + 20 end, 20 }, buildConvertButtonLabel, function() + self:ConvertToVersion(getLatestTreeVersion(), false, true) + end) +- self.controls.specConvertAll = new("ButtonControl", { "LEFT", self.controls.specConvert, "RIGHT" }, { 8, 0, function() return DrawStringWidth(16, "VAR", buildConvertAllButtonLabel()) + 20 end, 20 }, buildConvertAllButtonLabel, function() ++ self.controls.specConvertAll = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.specConvert, "RIGHT" }, { 8, 0, function() return DrawStringWidth(16, "VAR", buildConvertAllButtonLabel()) + 20 end, 20 }, buildConvertAllButtonLabel, function() + self:OpenVersionConvertAllPopup(getLatestTreeVersion()) + end) + self.jumpToNode = false + self.jumpToX = 0 + self.jumpToY = 0 +-end) ++ return self ++end + + function TreeTabClass:RemoveTattooFromNode(node) + self.build.spec.tree.nodes[node.id].isTattoo = false +@@ -592,7 +597,7 @@ function TreeTabClass:ConvertToVersion(version, remove, success, ignoreTreeSubTy + version = version..treeSubTypeCapture + end + end +- local newSpec = new("PassiveSpec", self.build, version) ++ local newSpec = new("PassiveSpec"):PassiveSpec(self.build, version) + newSpec.title = self.build.spec.title + newSpec.jewels = copyTable(self.build.spec.jewels) + newSpec:RestoreUndoState(self.build.spec:CreateUndoState(), version) +@@ -628,19 +633,19 @@ end + + function TreeTabClass:OpenSpecManagePopup() + local importTree = +- new("ButtonControl", nil, {-99, 259, 90, 20}, "Import Tree", function() ++ new("ButtonControl"):ButtonControl(nil, {-99, 259, 90, 20}, "Import Tree", function() + self:OpenImportPopup() + end) + local exportTree = +- new("ButtonControl", {"LEFT", importTree, "RIGHT"}, {8, 0, 90, 20}, "Export Tree", function() ++ new("ButtonControl"):ButtonControl({"LEFT", importTree, "RIGHT"}, {8, 0, 90, 20}, "Export Tree", function() + self:OpenExportPopup() + end) + + main:OpenPopup(370, 290, "Manage Passive Trees", { +- new("PassiveSpecListControl", nil, {0, 50, 350, 200}, self), ++ new("PassiveSpecListControl"):PassiveSpecListControl(nil, {0, 50, 350, 200}, self), + importTree, + exportTree, +- new("ButtonControl", {"LEFT", exportTree, "RIGHT"}, {8, 0, 90, 20}, "Done", function() ++ new("ButtonControl"):ButtonControl({"LEFT", exportTree, "RIGHT"}, {8, 0, 90, 20}, "Done", function() + main:ClosePopup() + end), + }) +@@ -648,17 +653,17 @@ end + + function TreeTabClass:OpenVersionConvertPopup(version, ignoreTreeSubType) + local controls = { } +- controls.warningLabel = new("LabelControl", nil, {0, 20, 0, 16}, "^7Warning: some or all of the passives may be de-allocated due to changes in the tree.\n\n" .. ++ controls.warningLabel = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Warning: some or all of the passives may be de-allocated due to changes in the tree.\n\n" .. + "Convert will replace your current tree.\nCopy + Convert will backup your current tree.\n") +- controls.convert = new("ButtonControl", nil, {-125, 105, 100, 20}, "Convert", function() ++ controls.convert = new("ButtonControl"):ButtonControl(nil, {-125, 105, 100, 20}, "Convert", function() + self:ConvertToVersion(version, true, false, ignoreTreeSubType) + main:ClosePopup() + end) +- controls.convertCopy = new("ButtonControl", nil, {0, 105, 125, 20}, "Copy + Convert", function() ++ controls.convertCopy = new("ButtonControl"):ButtonControl(nil, {0, 105, 125, 20}, "Copy + Convert", function() + self:ConvertToVersion(version, false, false, ignoreTreeSubType) + main:ClosePopup() + end) +- controls.cancel = new("ButtonControl", nil, {125, 105, 100, 20}, "Cancel", function() ++ controls.cancel = new("ButtonControl"):ButtonControl(nil, {125, 105, 100, 20}, "Cancel", function() + self.controls.versionSelect:SelByValue(self.build.spec.treeVersion, 'value') + main:ClosePopup() + end) +@@ -709,7 +714,7 @@ function TreeTabClass:OpenImportPopup() + -- newTreeVersion is passed in as an output of validateTreeVersion(). It will always be a valid tree version text string + -- 20230908. We always create a new Spec() + ConPrintf("Tree version: " .. newTreeVersion) +- local newSpec = new("PassiveSpec", self.build, newTreeVersion) ++ local newSpec = new("PassiveSpec"):PassiveSpec(self.build, newTreeVersion) + newSpec.title = controls.name.buf + local errMsg = newSpec:DecodeURL(treeLink) + if errMsg then +@@ -740,18 +745,18 @@ function TreeTabClass:OpenImportPopup() + return latestTreeVersion .. (alternateType and ("_" .. alternateType:gsub("-", "_")) or "") + end + +- controls.nameLabel = new("LabelControl", nil, {-180, 20, 0, 16}, "Enter name for this passive tree:") +- controls.name = new("EditControl", nil, {100, 20, 350, 18}, "", nil, nil, nil, function(buf) ++ controls.nameLabel = new("LabelControl"):LabelControl(nil, {-180, 20, 0, 16}, "Enter name for this passive tree:") ++ controls.name = new("EditControl"):EditControl(nil, {100, 20, 350, 18}, "", nil, nil, nil, function(buf) + controls.msg.label = "" + controls.import.enabled = buf:match("%S") and controls.edit.buf:match("%S") + end) +- controls.editLabel = new("LabelControl", nil, {-150, 45, 0, 16}, "Enter passive tree link:") +- controls.edit = new("EditControl", nil, {100, 45, 350, 18}, "", nil, nil, nil, function(buf) ++ controls.editLabel = new("LabelControl"):LabelControl(nil, {-150, 45, 0, 16}, "Enter passive tree link:") ++ controls.edit = new("EditControl"):EditControl(nil, {100, 45, 350, 18}, "", nil, nil, nil, function(buf) + controls.msg.label = "" + controls.import.enabled = buf:match("%S") and controls.name.buf:match("%S") + end) +- controls.msg = new("LabelControl", nil, {0, 65, 0, 16}, "") +- controls.import = new("ButtonControl", nil, {-45, 85, 80, 20}, "Import", function() ++ controls.msg = new("LabelControl"):LabelControl(nil, {0, 65, 0, 16}, "") ++ controls.import = new("ButtonControl"):ButtonControl(nil, {-45, 85, 80, 20}, "Import", function() + local treeLink = controls.edit.buf + if #treeLink == 0 then + return +@@ -900,7 +905,7 @@ function TreeTabClass:ModifyNodePopup(selectedNode) + end + end + for idx, desc in ipairs(wrapTable) do +- controls[idx] = new("LabelControl", {"TOPLEFT", controls[idx-1] or controls.modSelect,"TOPLEFT"}, {0, 20, 600, 16}, "^7"..desc) ++ controls[idx] = new("LabelControl"):LabelControl({"TOPLEFT", controls[idx-1] or controls.modSelect,"TOPLEFT"}, {0, 20, 600, 16}, "^7"..desc) + totalHeight = totalHeight + 20 + end + main.popups[1].height = totalHeight + 75 +@@ -912,8 +917,8 @@ function TreeTabClass:ModifyNodePopup(selectedNode) + end + + buildMods(selectedNode) +- controls.modSelectLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {170, 25, 0, 16}, "^7Modifier:") +- controls.modSelect = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {175, 25, 250, 18}, modGroups, function(idx) constructUI(modGroups[idx]) end) ++ controls.modSelectLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {170, 25, 0, 16}, "^7Modifier:") ++ controls.modSelect = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {175, 25, 250, 18}, modGroups, function(idx) constructUI(modGroups[idx]) end) + controls.modSelect.selIndex = self.defaultTattoo[nodeName] or 1 + controls.modSelect.tooltipFunc = function(tooltip, mode, index, value) + tooltip:Clear() +@@ -923,7 +928,7 @@ function TreeTabClass:ModifyNodePopup(selectedNode) + end + end + end +- controls.save = new("ButtonControl", nil, {-90, 75, 80, 20}, "Add", function() ++ controls.save = new("ButtonControl"):ButtonControl(nil, {-90, 75, 80, 20}, "Add", function() + addModifier(selectedNode) + self.build.spec:AddUndoState() + self.modFlag = true +@@ -931,7 +936,7 @@ function TreeTabClass:ModifyNodePopup(selectedNode) + self.defaultTattoo[nodeName] = controls.modSelect.selIndex + main:ClosePopup() + end) +- controls.reset = new("ButtonControl", nil, {0, 75, 80, 20}, "Reset Node", function() ++ controls.reset = new("ButtonControl"):ButtonControl(nil, {0, 75, 80, 20}, "Reset Node", function() + self:RemoveTattooFromNode(selectedNode) + self.build.spec:AddUndoState() + self.modFlag = true +@@ -939,7 +944,7 @@ function TreeTabClass:ModifyNodePopup(selectedNode) + self.defaultTattoo[nodeName] = nil + main:ClosePopup() + end) +- controls.close = new("ButtonControl", nil, {90, 75, 80, 20}, "Cancel", function() ++ controls.close = new("ButtonControl"):ButtonControl(nil, {90, 75, 80, 20}, "Cancel", function() + main:ClosePopup() + end) + +@@ -976,13 +981,13 @@ function TreeTabClass:ModifyNodePopup(selectedNode) + end + return count + end +- controls.totalTattoos = new("ButtonControl", nil, { 0, 95, 145, 20 }, "^7Tattoo Count: ".. getTattooCount() .."/50", function() return end) ++ controls.totalTattoos = new("ButtonControl"):ButtonControl(nil, { 0, 95, 145, 20 }, "^7Tattoo Count: ".. getTattooCount() .."/50", function() return end) + controls.totalTattoos.tooltipFunc = function(tooltip, mode, index, value) getTattooCount(tooltip) end + main:OpenPopup(600, 105, "Replace Modifier of Node", controls, "save") + constructUI(modGroups[self.defaultTattoo[nodeName] or 1]) + + -- Show Legacy Tattoos +- controls.showLegacyTattoo = new("CheckBoxControl", { "LEFT", controls.totalTattoos, "RIGHT" }, { 195, 0, 20 }, "Show Legacy Tattoos:", function(state) ++ controls.showLegacyTattoo = new("CheckBoxControl"):CheckBoxControl({ "LEFT", controls.totalTattoos, "RIGHT" }, { 195, 0, 20 }, "Show Legacy Tattoos:", function(state) + self.showLegacyTattoo = state + buildMods(selectedNode) + end) +@@ -1024,13 +1029,13 @@ function TreeTabClass:OpenMasteryPopup(node, viewPort) + --Check to make sure that the effects list has a potential mod to apply to a mastery + if not (next(effects) == nil) then + local passiveMasteryControlHeight = (#effects + 1) * 14 + 2 +- controls.close = new("ButtonControl", nil, {0, 30 + passiveMasteryControlHeight, 90, 20}, "Cancel", function() ++ controls.close = new("ButtonControl"):ButtonControl(nil, {0, 30 + passiveMasteryControlHeight, 90, 20}, "Cancel", function() + node.sd = cachedSd + node.allMasteryOptions = cachedAllMasteryOption + self.build.spec.tree:ProcessStats(node) + main:ClosePopup() + end) +- controls.effect = new("PassiveMasteryControl", {"TOPLEFT",nil,"TOPLEFT"}, {6, 25, 0, passiveMasteryControlHeight}, effects, self, node, controls.save) ++ controls.effect = new("PassiveMasteryControl"):PassiveMasteryControl({"TOPLEFT",nil,"TOPLEFT"}, {6, 25, 0, passiveMasteryControlHeight}, effects, self, node, controls.save) + main:OpenPopup(controls.effect.width + 12, controls.effect.height + 60, node.name, controls, nil, nil, "close") + end + end +@@ -1504,13 +1509,13 @@ function TreeTabClass:FindTimelessJewel() + self.build.modFlag = true + end + +- controls.devotionSelectLabel = new("LabelControl", {"TOPRIGHT", nil, "TOPLEFT"}, {920, 25, 0, 16}, "^7Devotion modifiers:") ++ controls.devotionSelectLabel = new("LabelControl"):LabelControl({"TOPRIGHT", nil, "TOPLEFT"}, {920, 25, 0, 16}, "^7Devotion modifiers:") + controls.devotionSelectLabel.shown = timelessData.jewelType.id == 4 +- controls.devotionSelect1 = new("DropDownControl", {"TOP", controls.devotionSelectLabel, "BOTTOM"}, {0, 8, 200, 18}, devotionVariants, function(index, value) ++ controls.devotionSelect1 = new("DropDownControl"):DropDownControl({"TOP", controls.devotionSelectLabel, "BOTTOM"}, {0, 8, 200, 18}, devotionVariants, function(index, value) + timelessData.devotionVariant1 = index + end) + controls.devotionSelect1.selIndex = timelessData.devotionVariant1 +- controls.devotionSelect2 = new("DropDownControl", {"TOP", controls.devotionSelect1, "BOTTOM"}, {0, 7, 200, 18}, devotionVariants, function(index, value) ++ controls.devotionSelect2 = new("DropDownControl"):DropDownControl({"TOP", controls.devotionSelect1, "BOTTOM"}, {0, 7, 200, 18}, devotionVariants, function(index, value) + timelessData.devotionVariant2 = index + end) + controls.devotionSelect2.selIndex = timelessData.devotionVariant2 +@@ -1526,7 +1531,7 @@ function TreeTabClass:FindTimelessJewel() + local clearProtected + self.allocatedNodesInRadiusCount = 0 + +- controls.jewelSelect = new("DropDownControl", {"TOPLEFT", nil, "TOPLEFT"}, {520, 25, 200, rowHeight}, jewelTypes, function(index, value) ++ controls.jewelSelect = new("DropDownControl"):DropDownControl({"TOPLEFT", nil, "TOPLEFT"}, {520, 25, 200, rowHeight}, jewelTypes, function(index, value) + timelessData.jewelType = value + controls.devotionSelectLabel.shown = value.id == 4 -- Militant Faith + controls.abyssAscendancyLabel.shown = value.id == 11 +@@ -1545,15 +1550,15 @@ function TreeTabClass:FindTimelessJewel() + end + end) + controls.jewelSelect.selIndex = timelessData.jewelType.id +- controls.jewelSelectLabel = new("LabelControl", {"RIGHT", controls.jewelSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Jewel Type:") ++ controls.jewelSelectLabel = new("LabelControl"):LabelControl({"RIGHT", controls.jewelSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Jewel Type:") + + +- controls.conquerorSelect = new("DropDownControl", {"TOPLEFT", controls.jewelSelect, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, conquerorTypes[timelessData.jewelType.id], function(index, value) ++ controls.conquerorSelect = new("DropDownControl"):DropDownControl({"TOPLEFT", controls.jewelSelect, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, conquerorTypes[timelessData.jewelType.id], function(index, value) + timelessData.conquerorType = value + self.build.modFlag = true + end) + controls.conquerorSelect.selIndex = timelessData.conquerorType.id +- controls.conquerorSelectLabel = new("LabelControl", {"RIGHT", controls.conquerorSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Conqueror:") ++ controls.conquerorSelectLabel = new("LabelControl"):LabelControl({"RIGHT", controls.conquerorSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Conqueror:") + + setAllocatedNodes = function() + if timelessData.jewelSocket.id == -1 or not treeData.nodes[timelessData.jewelSocket.id] then +@@ -1588,7 +1593,7 @@ function TreeTabClass:FindTimelessJewel() + end + + +- controls.socketSelect = new("TimelessJewelSocketControl", {"TOPLEFT", controls.conquerorSelect, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, jewelSockets, function(index, value) ++ controls.socketSelect = new("TimelessJewelSocketControl"):TimelessJewelSocketControl({"TOPLEFT", controls.conquerorSelect, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, jewelSockets, function(index, value) + timelessData.jewelSocket = value + setAllocatedNodes() -- reset list when changing sockets + self.build.modFlag = true +@@ -1600,7 +1605,7 @@ function TreeTabClass:FindTimelessJewel() + break + end + end +- controls.socketSelectLabel = new("LabelControl", {"RIGHT", controls.socketSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Jewel Socket:") ++ controls.socketSelectLabel = new("LabelControl"):LabelControl({"RIGHT", controls.socketSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Jewel Socket:") + + clearProtected = function() + protectedNodesCount = 0 +@@ -1612,7 +1617,7 @@ function TreeTabClass:FindTimelessJewel() + end + end + +- controls.socketFilter = new("CheckBoxControl", {"TOPLEFT", controls.socketSelect, "BOTTOMLEFT"}, {0, rowSpacing, rowHeight}, nil, function(value) ++ controls.socketFilter = new("CheckBoxControl"):CheckBoxControl({"TOPLEFT", controls.socketSelect, "BOTTOMLEFT"}, {0, rowSpacing, rowHeight}, nil, function(value) + timelessData.socketFilter = value + self.build.modFlag = true + controls.socketFilterAdditionalDistanceLabel.shown = value +@@ -1626,7 +1631,7 @@ function TreeTabClass:FindTimelessJewel() + clearProtected() + end + end) +- controls.socketFilterLabel = new("LabelControl", {"RIGHT", controls.socketFilter, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Filter Nodes:") ++ controls.socketFilterLabel = new("LabelControl"):LabelControl({"RIGHT", controls.socketFilter, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Filter Nodes:") + controls.socketFilter.tooltipFunc = function(tooltip, mode, index, value) + tooltip:Clear() + tooltip:AddLine(16, "^7Enable this option to exclude nodes that you do not have allocated on your active passive skill tree.") +@@ -1635,7 +1640,7 @@ function TreeTabClass:FindTimelessJewel() + controls.socketFilter.state = timelessData.socketFilter + + -- Protect notables that must not be replaced by Militant Faith or Reclaimed Malevolence. +- controls.protectAllocatedLabel = new("LabelControl", { "TOPLEFT", nil, "TOPLEFT" }, { ++ controls.protectAllocatedLabel = new("LabelControl"):LabelControl({ "TOPLEFT", nil, "TOPLEFT" }, { + 15, + function() + return timelessData.jewelType.id == 11 and 85 or 25 +@@ -1643,17 +1648,17 @@ function TreeTabClass:FindTimelessJewel() + 0, + 16, + }, "^7Protect allocated nodes from changing:") +- controls.protectAllocatedSelect = new("DropDownControl", { "TOPLEFT", controls.protectAllocatedLabel, "BOTTOMLEFT" }, { 0, 8, 200, 18 }, nil, nil) +- controls.protectAllocatedButtonAdd = new("ButtonControl", { "LEFT", controls.protectAllocatedSelect, "RIGHT" }, { 5, 0, 44, 18 }, "Add", function() ++ controls.protectAllocatedSelect = new("DropDownControl"):DropDownControl({ "TOPLEFT", controls.protectAllocatedLabel, "BOTTOMLEFT" }, { 0, 8, 200, 18 }, nil, nil) ++ controls.protectAllocatedButtonAdd = new("ButtonControl"):ButtonControl({ "LEFT", controls.protectAllocatedSelect, "RIGHT" }, { 5, 0, 44, 18 }, "Add", function() + local selValue = controls.protectAllocatedSelect:GetSelValue() + local nodeName = selValue and selValue.label + if nodeName and not controls["protected:"..nodeName] then + protectedNodesCount = protectedNodesCount + 1 + t_insert(protectedNodes, nodeName) +- controls["protected:"..nodeName] = new("LabelControl", { "TOPLEFT", controls.protectAllocatedSelect, "BOTTOMLEFT" }, { 0, 16 * protectedNodesCount - 10, 0, 16 }, "^7"..nodeName) ++ controls["protected:"..nodeName] = new("LabelControl"):LabelControl({ "TOPLEFT", controls.protectAllocatedSelect, "BOTTOMLEFT" }, { 0, 16 * protectedNodesCount - 10, 0, 16 }, "^7"..nodeName) + end + end) +- controls.protectAllocatedButtonClear = new("ButtonControl", { "LEFT", controls.protectAllocatedButtonAdd, "RIGHT" }, { 5, 0, 44, 18 }, "Clear", function() ++ controls.protectAllocatedButtonClear = new("ButtonControl"):ButtonControl({ "LEFT", controls.protectAllocatedButtonAdd, "RIGHT" }, { 5, 0, 44, 18 }, "Clear", function() + clearProtected() + end) + -- set shown and list on load +@@ -1664,9 +1669,9 @@ function TreeTabClass:FindTimelessJewel() + + -- This requirement is separate from ordinary node weights and remains above + -- the protection list so adding protected nodes does not move the selector. +- controls.abyssAscendancyLabel = new("LabelControl", {"TOPLEFT", nil, "TOPLEFT"}, {15, 25, 0, 16}, "^7Required ascendancy outcome:") ++ controls.abyssAscendancyLabel = new("LabelControl"):LabelControl({"TOPLEFT", nil, "TOPLEFT"}, {15, 25, 0, 16}, "^7Required ascendancy outcome:") + controls.abyssAscendancyLabel.shown = timelessData.jewelType.id == 11 +- controls.abyssAscendancySelect = new("DropDownControl", {"TOPLEFT", controls.abyssAscendancyLabel, "BOTTOMLEFT"}, {0, 8, 200, 18}, abyssAscendancyOptions, function(index, value) ++ controls.abyssAscendancySelect = new("DropDownControl"):DropDownControl({"TOPLEFT", controls.abyssAscendancyLabel, "BOTTOMLEFT"}, {0, 8, 200, 18}, abyssAscendancyOptions, function(index, value) + local searchLines = { } + for _, searchRow in ipairs(searchListTbl) do + if not searchRow[1]:match("^abyss_special_ascendancy_notable_") then +@@ -1741,11 +1746,11 @@ function TreeTabClass:FindTimelessJewel() + local scrollWheelSpeedTbl2 = { ["SHIFT"] = 0.2, ["CTRL"] = 0.002, ["DEFAULT"] = 0.02 } + + local nodeSliderStatLabel = "None" +- controls.nodeSlider = new("SliderControl", {"TOPLEFT", controls.socketFilter, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, function(value) ++ controls.nodeSlider = new("SliderControl"):SliderControl({"TOPLEFT", controls.socketFilter, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, function(value) + controls.nodeSliderValue.label = s_format("^7%.3f", value * 10) + parseSearchList(1, controls.searchListFallback and controls.searchListFallback.shown or false) + end, scrollWheelSpeedTbl) +- controls.nodeSliderLabel = new("LabelControl", {"RIGHT", controls.nodeSlider, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Primary Node Weight:") ++ controls.nodeSliderLabel = new("LabelControl"):LabelControl({"RIGHT", controls.nodeSlider, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Primary Node Weight:") + controls.nodeSlider.tooltipFunc = function(tooltip, mode, index, value) + tooltip:Clear() + if not controls.nodeSlider.dragging then +@@ -1770,11 +1775,11 @@ function TreeTabClass:FindTimelessJewel() + controls.nodeSlider:SetVal(0.1) + + local nodeSlider2StatLabel = "None" +- controls.nodeSlider2 = new("SliderControl", {"TOPLEFT", controls.nodeSlider, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, function(value) ++ controls.nodeSlider2 = new("SliderControl"):SliderControl({"TOPLEFT", controls.nodeSlider, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, function(value) + controls.nodeSlider2Value.label = s_format("^7%.3f", value * 10) + parseSearchList(1, controls.searchListFallback and controls.searchListFallback.shown or false) + end, scrollWheelSpeedTbl) +- controls.nodeSlider2Label = new("LabelControl", {"RIGHT", controls.nodeSlider2, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Secondary Node Weight:") ++ controls.nodeSlider2Label = new("LabelControl"):LabelControl({"RIGHT", controls.nodeSlider2, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Secondary Node Weight:") + controls.nodeSlider2.tooltipFunc = function(tooltip, mode, index, value) + tooltip:Clear() + if not controls.nodeSlider2.dragging then +@@ -1798,7 +1803,7 @@ function TreeTabClass:FindTimelessJewel() + end + controls.nodeSlider2:SetVal(0.1) + +- controls.nodeSlider3 = new("SliderControl", {"TOPLEFT", controls.nodeSlider2, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, function(value) ++ controls.nodeSlider3 = new("SliderControl"):SliderControl({"TOPLEFT", controls.nodeSlider2, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, function(value) + if value == 1 then + controls.nodeSlider3Value.label = "^7Required" + else +@@ -1806,14 +1811,14 @@ function TreeTabClass:FindTimelessJewel() + end + parseSearchList(1, controls.searchListFallback and controls.searchListFallback.shown or false) + end, scrollWheelSpeedTbl2) +- controls.nodeSlider3Label = new("LabelControl", {"RIGHT", controls.nodeSlider3, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Minimum Node Weight:") ++ controls.nodeSlider3Label = new("LabelControl"):LabelControl({"RIGHT", controls.nodeSlider3, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Minimum Node Weight:") + controls.nodeSlider3.tooltipFunc = function(tooltip, mode, index, value) + tooltip:Clear() + if not controls.nodeSlider3.dragging then + tooltip:AddLine(16, "^7Seeds that do not meet the minimum weight threshold for a desired node are excluded from the search results.") + end + end +- controls.nodeSlider3Value = new("LabelControl", {"LEFT", controls.nodeSlider3, "RIGHT"}, {5, 0, 0, 16}, "^70") ++ controls.nodeSlider3Value = new("LabelControl"):LabelControl({"LEFT", controls.nodeSlider3, "RIGHT"}, {5, 0, 0, 16}, "^70") + controls.nodeSlider3.tooltip.realDraw = controls.nodeSlider3.tooltip.Draw + controls.nodeSlider3.tooltip.Draw = function(self, x, y, width, height, viewPort) + local sliderOffsetX = round(184 * (1 - controls.nodeSlider3.val)) +@@ -1861,7 +1866,7 @@ function TreeTabClass:FindTimelessJewel() + statCount == 1 and t_concat(legionPassive.sd, " + ") or legionPassive.sd[1] or "None", + legionPassive.sd[2] or "None" + end +- controls.nodeSelect = new("DropDownControl", {"TOPLEFT", controls.nodeSlider3, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, modData, function(index, value) ++ controls.nodeSelect = new("DropDownControl"):DropDownControl({"TOPLEFT", controls.nodeSlider3, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, modData, function(index, value) + nodeSliderStatLabel = "None" + nodeSlider2StatLabel = "None" + if value.id then +@@ -1916,7 +1921,7 @@ function TreeTabClass:FindTimelessJewel() + self.build.modFlag = true + end + end) +- controls.nodeSelectLabel = new("LabelControl", {"RIGHT", controls.nodeSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Search for Node:") ++ controls.nodeSelectLabel = new("LabelControl"):LabelControl({"RIGHT", controls.nodeSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Search for Node:") + controls.nodeSelect.tooltipFunc = function(tooltip, mode, index, value) + tooltip:Clear() + if mode ~= "OUT" and value.descriptions then +@@ -2104,12 +2109,12 @@ function TreeTabClass:FindTimelessJewel() + }) + end + end +- controls.fallbackWeightsList = new("DropDownControl", {"TOPLEFT", controls.nodeSelect, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, fallbackWeightsList, function(index) ++ controls.fallbackWeightsList = new("DropDownControl"):DropDownControl({"TOPLEFT", controls.nodeSelect, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, fallbackWeightsList, function(index) + timelessData.fallbackWeightMode.idx = index + end) +- controls.fallbackWeightsLabel = new("LabelControl", {"RIGHT", controls.fallbackWeightsList, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Fallback Weight Mode:") ++ controls.fallbackWeightsLabel = new("LabelControl"):LabelControl({"RIGHT", controls.fallbackWeightsList, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Fallback Weight Mode:") + controls.fallbackWeightsList.selIndex = timelessData.fallbackWeightMode.idx or 1 +- controls.fallbackWeightsButton = new("ButtonControl", {"LEFT", controls.fallbackWeightsList, "RIGHT"}, {5, 0, 66, 18}, "Generate", function() ++ controls.fallbackWeightsButton = new("ButtonControl"):ButtonControl({"LEFT", controls.fallbackWeightsList, "RIGHT"}, {5, 0, 66, 18}, "Generate", function() + setupFallbackWeights() + controls.searchListFallbackButton.label = "^4Fallback Nodes" + end) +@@ -2117,12 +2122,12 @@ function TreeTabClass:FindTimelessJewel() + tooltip:Clear() + tooltip:AddLine(16, "^7Click this button to generate new fallback node weights, replacing your old ones.") + end +- controls.totalMinimumWeight = new("EditControl", {"TOPLEFT", controls.fallbackWeightsList, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, "", nil, "%D", nil, function(val) ++ controls.totalMinimumWeight = new("EditControl"):EditControl({"TOPLEFT", controls.fallbackWeightsList, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, "", nil, "%D", nil, function(val) + local num = tonumber(val) + timelessData.totalMinimumWeight = num or nil + self.build.modFlag = true + end) +- controls.totalMinimumWeightLabel = new("LabelControl", {"RIGHT", controls.totalMinimumWeight, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Total Minimum Weight:") ++ controls.totalMinimumWeightLabel = new("LabelControl"):LabelControl({"RIGHT", controls.totalMinimumWeight, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Total Minimum Weight:") + controls.totalMinimumWeight.tooltipFunc = function(tooltip, mode, index, value) + tooltip:Clear() + tooltip:AddLine(16, "^7Optional: Only show results where total weight meets or exceeds this value.") +@@ -2133,7 +2138,7 @@ function TreeTabClass:FindTimelessJewel() + local buttonHeight = 20 + local edgePadding = 12 + local listYOffset = -(buttonHeight + edgePadding * 2) +- controls.searchList = new("EditControl", { "BOTTOMLEFT", nil, "BOTTOMLEFT" }, ++ controls.searchList = new("EditControl"):EditControl({ "BOTTOMLEFT", nil, "BOTTOMLEFT" }, + { edgePadding, listYOffset, listWidth, listHeight }, timelessData.searchList, nil, + "^%C\t\n", nil, function(value) + timelessData.searchList = value +@@ -2144,7 +2149,7 @@ function TreeTabClass:FindTimelessJewel() + controls.searchList.enabled = true + controls.searchList:SetText(timelessData.searchList and timelessData.searchList or "") + +- controls.searchListFallback = new("EditControl", { "BOTTOMLEFT", nil, "BOTTOMLEFT" }, ++ controls.searchListFallback = new("EditControl"):EditControl({ "BOTTOMLEFT", nil, "BOTTOMLEFT" }, + { edgePadding, listYOffset, listWidth, listHeight }, + timelessData.searchListFallback, nil, "^%C\t\n", nil, function(value) + timelessData.searchListFallback = value +@@ -2155,7 +2160,7 @@ function TreeTabClass:FindTimelessJewel() + controls.searchListFallback.enabled = false + controls.searchListFallback:SetText(timelessData.searchListFallback and timelessData.searchListFallback or "") + +- controls.searchListButton = new("ButtonControl", ++ controls.searchListButton = new("ButtonControl"):ButtonControl( + { "BOTTOMLEFT", nil, "BOTTOMLEFT" }, + { edgePadding, listYOffset - listHeight - rowSpacing, 106, buttonHeight }, "^7Desired Nodes", function() + if controls.searchListFallback.shown then +@@ -2174,7 +2179,7 @@ function TreeTabClass:FindTimelessJewel() + end + controls.searchListButton.locked = function() return controls.searchList.shown end + +- controls.searchListFallbackButton = new("ButtonControl", {"LEFT", controls.searchListButton, "RIGHT"}, {5, 0, 110, buttonHeight}, "^7Fallback Nodes", function() ++ controls.searchListFallbackButton = new("ButtonControl"):ButtonControl({"LEFT", controls.searchListButton, "RIGHT"}, {5, 0, 110, buttonHeight}, "^7Fallback Nodes", function() + controls.searchList.shown = false + controls.searchList.enabled = false + controls.searchListFallback.shown = true +@@ -2191,11 +2196,11 @@ function TreeTabClass:FindTimelessJewel() + end + controls.searchListFallbackButton.locked = function() return controls.searchListFallback.shown end + +- controls.searchResults = new("TimelessJewelListControl", { "BOTTOMLEFT", nil, "BOTTOMLEFT" }, ++ controls.searchResults = new("TimelessJewelListControl"):TimelessJewelListControl({ "BOTTOMLEFT", nil, "BOTTOMLEFT" }, + { edgePadding*2 + listWidth, -(buttonHeight + edgePadding * 2), listWidth, listHeight }, self.build) +- self.tradeQueryRequests = new("TradeQueryRequests") +- controls.msg = new("LabelControl", nil, { -280, 5, 0, 20 }, "") +- controls.searchTradeButton = new("ButtonControl", { "BOTTOMRIGHT", controls.searchResults, "TOPRIGHT" }, { 0, -rowSpacing, 170, buttonHeight }, "Open Trade URL", function() ++ self.tradeQueryRequests = new("TradeQueryRequests"):TradeQueryRequests() ++ controls.msg = new("LabelControl"):LabelControl(nil, { -280, 5, 0, 20 }, "") ++ controls.searchTradeButton = new("ButtonControl"):ButtonControl({ "BOTTOMRIGHT", controls.searchResults, "TOPRIGHT" }, { 0, -rowSpacing, 170, buttonHeight }, "Open Trade URL", function() + local seedTrades = {} + local startRow, endRow + if controls.searchResults.highlightIndex and not controls.searchMore.state then +@@ -2318,17 +2323,17 @@ function TreeTabClass:FindTimelessJewel() + tooltip:AddLine(16, "^7After selecting a row You can also shift+click on another row to select a range of rows to search.") + end + +- controls.searchTradeLeagueSelect = new("DropDownControl", { "RIGHT", controls.searchTradeButton, "LEFT" }, ++ controls.searchTradeLeagueSelect = new("DropDownControl"):DropDownControl({ "RIGHT", controls.searchTradeButton, "LEFT" }, + { -labelSpacing, 0, 140, buttonHeight }, nil, function(idx, val) + self.timelessJewelLeagueSelect = val + end) +- controls.searchTradeLeagueLabel = new("LabelControl", { "TOPRIGHT", controls.searchTradeLeagueSelect, "TOPLEFT" }, ++ controls.searchTradeLeagueLabel = new("LabelControl"):LabelControl({ "TOPRIGHT", controls.searchTradeLeagueSelect, "TOPLEFT" }, + { -labelSpacing, 0, 0, labelHeight }, "^7League:") + -- Realm selection + self.realmList = { + "PC", "Sony", "Xbox" + } +- controls.realmSelection = new("DropDownControl", { "BOTTOMLEFT", controls.searchTradeLeagueSelect, "TOPLEFT" }, ++ controls.realmSelection = new("DropDownControl"):DropDownControl({ "BOTTOMLEFT", controls.searchTradeLeagueSelect, "TOPLEFT" }, + { 0, -rowSpacing, 50, buttonHeight }, self.realmList, nil) + local function updateLeagues() + local currentRealmId = controls.realmSelection:GetSelValue():lower() +@@ -2382,7 +2387,7 @@ function TreeTabClass:FindTimelessJewel() + -- manually call the function because when initialising, because the + -- function does not get called when the selection index stays the same + controls.realmSelection.selFunc(controls.realmSelection.selIndex) +- controls.realmLabel = new("LabelControl", { "TOPRIGHT", controls.realmSelection, "TOPLEFT" }, ++ controls.realmLabel = new("LabelControl"):LabelControl({ "TOPRIGHT", controls.realmSelection, "TOPLEFT" }, + { -labelSpacing, 0, 0, labelHeight }, "^7Realm:") + + -- Buyout selection +@@ -2393,7 +2398,7 @@ function TreeTabClass:FindTimelessJewel() + "In person (online)", + "Any (includes offline)" + } +- controls.tradeTypeSelection = new("DropDownControl", { "BOTTOMRIGHT", controls.searchTradeButton, "TOPRIGHT" }, ++ controls.tradeTypeSelection = new("DropDownControl"):DropDownControl({ "BOTTOMRIGHT", controls.searchTradeButton, "TOPRIGHT" }, + { 0, -rowSpacing, 205, buttonHeight }, tradeTypes, function(index, value) + self.tradeTypeIndex = index + end) +@@ -2402,7 +2407,7 @@ function TreeTabClass:FindTimelessJewel() + controls.tradeTypeSelection:SetSel(self.tradeTypeIndex) + + -- Checkbox to search a lot at once, or just a few +- controls.searchMore = new("CheckBoxControl", { "BOTTOMRIGHT", controls.tradeTypeSelection, "TOPRIGHT" }, ++ controls.searchMore = new("CheckBoxControl"):CheckBoxControl({ "BOTTOMRIGHT", controls.tradeTypeSelection, "TOPRIGHT" }, + { 0, -rowSpacing, 19 }, nil, function(state) + self.lastSearchMore = state + end, +@@ -2412,7 +2417,7 @@ function TreeTabClass:FindTimelessJewel() + if self.lastSearchMore then + controls.searchMore.state = self.lastSearchMore + end +- controls.searchMoreLabel = new("LabelControl", { "RIGHT", controls.searchMore, "LEFT" }, ++ controls.searchMoreLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.searchMore, "LEFT" }, + { -labelSpacing, 0, 0, labelHeight }, "^7Search Maximum Amount:") + + -- Helper function to search a single socket +@@ -2780,7 +2785,7 @@ function TreeTabClass:FindTimelessJewel() + local buttonDivider = 10 + local buttonWidth = 80 + -- reset button anchored to middle of panel and other buttons anchored to it +- controls.resetButton = new("ButtonControl", {"BOTTOMLEFT", nil, "BOTTOMLEFT"}, {panelWidth / 2 - buttonWidth/2, -edgePadding, buttonWidth, buttonHeight}, "Reset", function() ++ controls.resetButton = new("ButtonControl"):ButtonControl({"BOTTOMLEFT", nil, "BOTTOMLEFT"}, {panelWidth / 2 - buttonWidth/2, -edgePadding, buttonWidth, buttonHeight}, "Reset", function() + updateSearchList("", true) + updateSearchList("", false) + controls.abyssAscendancySelect.selIndex = 1 +@@ -2788,10 +2793,10 @@ function TreeTabClass:FindTimelessJewel() + controls.searchTradeButton.enabled = false + clearProtected() + end) +- controls.closeButton = new("ButtonControl", {"LEFT", controls.resetButton, "RIGHT"}, {buttonDivider, 0, buttonWidth, buttonHeight}, "Cancel", function() ++ controls.closeButton = new("ButtonControl"):ButtonControl({"LEFT", controls.resetButton, "RIGHT"}, {buttonDivider, 0, buttonWidth, buttonHeight}, "Cancel", function() + main:ClosePopup() + end) +- controls.searchButton = new("ButtonControl", {"RIGHT", controls.resetButton, "LEFT"}, {-buttonDivider, 0, buttonWidth, buttonHeight}, "Search", function() ++ controls.searchButton = new("ButtonControl"):ButtonControl({"RIGHT", controls.resetButton, "LEFT"}, {-buttonDivider, 0, buttonWidth, buttonHeight}, "Search", function() + if timelessData.jewelSocket.id == -1 then + wipeTable(timelessData.searchResults) + wipeTable(timelessData.sharedResults) diff --git a/src/Classes/UndoHandler.lua b/src/Classes/UndoHandler.lua index 6759de6cf0..4e6674808f 100644 --- a/src/Classes/UndoHandler.lua +++ b/src/Classes/UndoHandler.lua @@ -9,10 +9,16 @@ local t_insert = table.insert local t_remove = table.remove -local UndoHandlerClass = newClass("UndoHandler", function(self) +---@class UndoHandler +---@field CreateUndoState fun() Must be manually defined. Creates a state that can be restored +---@field RestoreUndoState fun(state: any) Must be manually defined. Restores a state created by calling CreateUndoState() +local UndoHandlerClass = newClass("UndoHandler") + +function UndoHandlerClass:UndoHandler() self.undo = { } self.redo = { } -end) + return self +end -- Initialises the undo/redo buffers -- Should be called after the current state is first loaded/initialised @@ -24,6 +30,7 @@ end -- Adds a new undo state to the undo buffer, and also clears the redo buffer -- Should be called after the user makes a change to the current state +---@param noClearRedo boolean? function UndoHandlerClass:AddUndoState(noClearRedo) t_insert(self.undo, 1, self:CreateUndoState()) self.undo[102] = nil diff --git a/src/Data/Bases/amulet.lua.rej b/src/Data/Bases/amulet.lua.rej new file mode 100644 index 0000000000..504bd03bf9 --- /dev/null +++ b/src/Data/Bases/amulet.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/amulet.lua b/src/Data/Bases/amulet.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + + itemBases["Paua Amulet"] = { + type = "Amulet", +@@ -1627,3 +1626,4 @@ itemBases["Monkey Paw Talisman (Frenzy)"] = { + "Every fell beast, every creature, had to die.\"", + }, + } ++end diff --git a/src/Data/Bases/axe.lua.rej b/src/Data/Bases/axe.lua.rej new file mode 100644 index 0000000000..a4187447d4 --- /dev/null +++ b/src/Data/Bases/axe.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/axe.lua b/src/Data/Bases/axe.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + itemBases["Rusted Hatchet"] = { + type = "One Handed Axe", + socketLimit = 3, +@@ -508,3 +507,4 @@ itemBases["Apex Cleaver"] = { + weapon = { PhysicalMin = 78, PhysicalMax = 121, CritChanceBase = 5, AttackRateBase = 1.35, Range = 13, }, + req = { level = 70, str = 139, dex = 65, }, + } ++end diff --git a/src/Data/Bases/belt.lua.rej b/src/Data/Bases/belt.lua.rej new file mode 100644 index 0000000000..c767c984f1 --- /dev/null +++ b/src/Data/Bases/belt.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/belt.lua b/src/Data/Bases/belt.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + itemBases["Rustic Sash"] = { + type = "Belt", + tags = { belt = true, default = true, }, +@@ -129,3 +128,4 @@ itemBases["Golden Obi"] = { + implicitIds = { "ItemFoundRarityIncreaseImplicitDemigodsBelt1", }, + req = { }, + } ++end diff --git a/src/Data/Bases/body.lua.rej b/src/Data/Bases/body.lua.rej new file mode 100644 index 0000000000..59ee575d10 --- /dev/null +++ b/src/Data/Bases/body.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/body.lua b/src/Data/Bases/body.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + + itemBases["Plate Vest"] = { + type = "Body Armour", +@@ -1258,3 +1257,4 @@ itemBases["Golden Mantle"] = { + armour = { ArmourBaseMin = 75, ArmourBaseMax = 86, EvasionBaseMin = 75, EvasionBaseMax = 86, EnergyShieldBaseMin = 17, EnergyShieldBaseMax = 19, }, + req = { level = 20, str = 8, dex = 8, int = 8, }, + } ++end diff --git a/src/Data/Bases/boots.lua b/src/Data/Bases/boots.lua index dfc0740fc9..2d09547181 100644 --- a/src/Data/Bases/boots.lua +++ b/src/Data/Bases/boots.lua @@ -1960,3 +1960,4 @@ itemBases["Golden Caligae"] = { armour = { }, req = { level = 12, }, } +end diff --git a/src/Data/Bases/boots.lua.rej b/src/Data/Bases/boots.lua.rej new file mode 100644 index 0000000000..1da84fa721 --- /dev/null +++ b/src/Data/Bases/boots.lua.rej @@ -0,0 +1,10 @@ +diff a/src/Data/Bases/boots.lua b/src/Data/Bases/boots.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + + itemBases["Iron Greaves"] = { + type = "Boots", diff --git a/src/Data/Bases/bow.lua.rej b/src/Data/Bases/bow.lua.rej new file mode 100644 index 0000000000..6b8bc8587e --- /dev/null +++ b/src/Data/Bases/bow.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/bow.lua b/src/Data/Bases/bow.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + itemBases["Crude Bow"] = { + type = "Bow", + socketLimit = 6, +@@ -293,3 +292,4 @@ itemBases["Ethereal Bow"] = { + weapon = { PhysicalMin = 5, PhysicalMax = 9, CritChanceBase = 6, AttackRateBase = 1.5, Range = 120, }, + req = { dex = 14, }, + } ++end diff --git a/src/Data/Bases/claw.lua.rej b/src/Data/Bases/claw.lua.rej new file mode 100644 index 0000000000..79804f4e6a --- /dev/null +++ b/src/Data/Bases/claw.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/claw.lua b/src/Data/Bases/claw.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + itemBases["Nailed Fist"] = { + type = "Claw", + socketLimit = 3, +@@ -310,3 +309,4 @@ itemBases["Void Fangs"] = { + weapon = { PhysicalMin = 22, PhysicalMax = 41, CritChanceBase = 7, AttackRateBase = 1.6, Range = 11, }, + req = { level = 70, dex = 113, int = 113, }, + } ++end diff --git a/src/Data/Bases/dagger.lua.rej b/src/Data/Bases/dagger.lua.rej new file mode 100644 index 0000000000..b9cf3f4894 --- /dev/null +++ b/src/Data/Bases/dagger.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/dagger.lua b/src/Data/Bases/dagger.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + itemBases["Glass Shank"] = { + type = "Dagger", + socketLimit = 3, +@@ -371,3 +370,4 @@ itemBases["Infernal Blade"] = { + weapon = { PhysicalMin = 21, PhysicalMax = 85, CritChanceBase = 8.5, AttackRateBase = 1.45, Range = 10, }, + req = { level = 70, dex = 121, int = 121, }, + } ++end diff --git a/src/Data/Bases/fishing.lua.rej b/src/Data/Bases/fishing.lua.rej new file mode 100644 index 0000000000..4709ba8243 --- /dev/null +++ b/src/Data/Bases/fishing.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/fishing.lua b/src/Data/Bases/fishing.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + itemBases["Fishing Rod"] = { + type = "Fishing Rod", + socketLimit = 4, +@@ -10,3 +9,4 @@ itemBases["Fishing Rod"] = { + weapon = { PhysicalMin = 8, PhysicalMax = 15, CritChanceBase = 5, AttackRateBase = 1.2, Range = 13, }, + req = { str = 8, dex = 8, }, + } ++end diff --git a/src/Data/Bases/flask.lua.rej b/src/Data/Bases/flask.lua.rej new file mode 100644 index 0000000000..df058bfd2a --- /dev/null +++ b/src/Data/Bases/flask.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/flask.lua b/src/Data/Bases/flask.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + itemBases["Small Life Flask"] = { + type = "Flask", + subType = "Life", +@@ -399,3 +398,4 @@ itemBases["Iron Flask"] = { + flask = { duration = 4, chargesUsed = 40, chargesMax = 60, buff = { "+200 to Ward" }, }, + req = { level = 27, }, + } ++end diff --git a/src/Data/Bases/gloves.lua.rej b/src/Data/Bases/gloves.lua.rej new file mode 100644 index 0000000000..7907d3e86a --- /dev/null +++ b/src/Data/Bases/gloves.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/gloves.lua b/src/Data/Bases/gloves.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + + itemBases["Iron Gauntlets"] = { + type = "Gloves", +@@ -837,3 +836,4 @@ itemBases["Golden Bracers"] = { + armour = { }, + req = { level = 12, }, + } ++end diff --git a/src/Data/Bases/helmet.lua b/src/Data/Bases/helmet.lua index 486ea0281e..09ee01735f 100644 --- a/src/Data/Bases/helmet.lua +++ b/src/Data/Bases/helmet.lua @@ -2677,3 +2677,4 @@ itemBases["Golden Visage"] = { armour = { }, req = { level = 12, }, } +end diff --git a/src/Data/Bases/helmet.lua.rej b/src/Data/Bases/helmet.lua.rej new file mode 100644 index 0000000000..531eae43af --- /dev/null +++ b/src/Data/Bases/helmet.lua.rej @@ -0,0 +1,10 @@ +diff a/src/Data/Bases/helmet.lua b/src/Data/Bases/helmet.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + + itemBases["Iron Hat"] = { + type = "Helmet", diff --git a/src/Data/Bases/jewel.lua b/src/Data/Bases/jewel.lua index 7f19b8c210..7c2674e775 100644 --- a/src/Data/Bases/jewel.lua +++ b/src/Data/Bases/jewel.lua @@ -64,3 +64,4 @@ itemBases["Timeless Jewel"] = { implicitModTypes = { }, req = { }, } +end diff --git a/src/Data/Bases/jewel.lua.rej b/src/Data/Bases/jewel.lua.rej new file mode 100644 index 0000000000..3a86e63cac --- /dev/null +++ b/src/Data/Bases/jewel.lua.rej @@ -0,0 +1,10 @@ +diff a/src/Data/Bases/jewel.lua b/src/Data/Bases/jewel.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + itemBases["Crimson Jewel"] = { + type = "Jewel", + tags = { default = true, jewel = true, not_dex = true, not_for_sale = true, not_int = true, strjewel = true, }, diff --git a/src/Data/Bases/mace.lua.rej b/src/Data/Bases/mace.lua.rej new file mode 100644 index 0000000000..04d192a963 --- /dev/null +++ b/src/Data/Bases/mace.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/mace.lua b/src/Data/Bases/mace.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + itemBases["Driftwood Club"] = { + type = "One Handed Mace", + socketLimit = 3, +@@ -895,3 +894,4 @@ itemBases["Impact Force Propagator"] = { + weapon = { PhysicalMin = 81, PhysicalMax = 135, CritChanceBase = 5, AttackRateBase = 1.15, Range = 13, }, + req = { level = 70, str = 220, }, + } ++end diff --git a/src/Data/Bases/quiver.lua.rej b/src/Data/Bases/quiver.lua.rej new file mode 100644 index 0000000000..c2f3181cf5 --- /dev/null +++ b/src/Data/Bases/quiver.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/quiver.lua b/src/Data/Bases/quiver.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + itemBases["Cured Quiver"] = { + type = "Quiver", + hidden = true, +@@ -267,3 +266,4 @@ itemBases["Artillery Quiver"] = { + implicitIds = { "SummonTotemCastSpeedImplicit1", }, + req = { level = 74, }, + } ++end diff --git a/src/Data/Bases/ring.lua.rej b/src/Data/Bases/ring.lua.rej new file mode 100644 index 0000000000..31f88faa8d --- /dev/null +++ b/src/Data/Bases/ring.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/ring.lua b/src/Data/Bases/ring.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + + itemBases["Iron Ring"] = { + type = "Ring", +@@ -449,3 +448,4 @@ itemBases["Jet Ring"] = { + implicitIds = { "AllDefensesImplicitJetRing", }, + req = { }, + } ++end diff --git a/src/Data/Bases/shield.lua b/src/Data/Bases/shield.lua index 979171b0e5..f612834f6a 100644 --- a/src/Data/Bases/shield.lua +++ b/src/Data/Bases/shield.lua @@ -1,7 +1,6 @@ -- This file is automatically generated, do not edit! -- Item data (c) Grinding Gear Games -local itemBases = ... - +return function(itemBases) itemBases["Splintered Tower Shield"] = { type = "Shield", diff --git a/src/Data/Bases/shield.lua.rej b/src/Data/Bases/shield.lua.rej new file mode 100644 index 0000000000..aaa602682f --- /dev/null +++ b/src/Data/Bases/shield.lua.rej @@ -0,0 +1,6 @@ +diff a/src/Data/Bases/shield.lua b/src/Data/Bases/shield.lua (rejected hunks) +@@ -1164,3 +1163,4 @@ itemBases["Golden Flame"] = { + armour = { BlockChance = 20, MovementPenalty = 3, }, + req = { level = 15, }, + } ++end diff --git a/src/Data/Bases/staff.lua.rej b/src/Data/Bases/staff.lua.rej new file mode 100644 index 0000000000..b12e299fc2 --- /dev/null +++ b/src/Data/Bases/staff.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/staff.lua b/src/Data/Bases/staff.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + itemBases["Gnarled Branch"] = { + type = "Staff", + socketLimit = 6, +@@ -323,3 +322,4 @@ itemBases["Eventuality Rod"] = { + weapon = { PhysicalMin = 78, PhysicalMax = 144, CritChanceBase = 8.3, AttackRateBase = 1.25, Range = 13, }, + req = { level = 70, str = 117, int = 117, }, + } ++end diff --git a/src/Data/Bases/sword.lua.rej b/src/Data/Bases/sword.lua.rej new file mode 100644 index 0000000000..7cb3c38165 --- /dev/null +++ b/src/Data/Bases/sword.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/sword.lua b/src/Data/Bases/sword.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + + itemBases["Rusted Sword"] = { + type = "One Handed Sword", +@@ -959,3 +958,4 @@ itemBases["Energy Blade Two Handed"] = { + weapon = { PhysicalMin = 0, PhysicalMax = 0, CritChanceBase = 7, AttackRateBase = 1.6, Range = 13, }, + req = { }, + } ++end diff --git a/src/Data/Bases/wand.lua.rej b/src/Data/Bases/wand.lua.rej new file mode 100644 index 0000000000..edbf820885 --- /dev/null +++ b/src/Data/Bases/wand.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Bases/wand.lua b/src/Data/Bases/wand.lua (rejected hunks) +@@ -1,7 +1,6 @@ + -- This file is automatically generated, do not edit! + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + itemBases["Driftwood Wand"] = { + type = "Wand", + socketLimit = 3, +@@ -313,3 +312,4 @@ itemBases["Convening Wand"] = { + weapon = { PhysicalMin = 25, PhysicalMax = 47, CritChanceBase = 8, AttackRateBase = 1.5, Range = 120, }, + req = { level = 50, int = 183, }, + } ++end diff --git a/src/Data/BossSkills.lua b/src/Data/BossSkills.lua index 6bb77b7c4d..a82293b505 100644 --- a/src/Data/BossSkills.lua +++ b/src/Data/BossSkills.lua @@ -5,6 +5,7 @@ -- Boss Skill data (c) Grinding Gear Games -- return { + bossSkills = { ["Atziri Flameblast"] = { DamageType = "Spell", DamageMultipliers = { @@ -167,7 +168,9 @@ return { }, tooltip = "Cannot be Blocked, Dodged, or Suppressed. \n It is three separate hits, and has a large DoT effect. Neither is taken into account here. \n i.e. Hits before death should be more than 3 to survive" }, -},{ + }, + + bossSkillsList = { { val = "None", label = "None" }, { val = "Atziri Flameblast", label = "Atziri Flameblast" }, { val = "Shaper Ball", label = "Shaper Ball" }, @@ -178,5 +181,5 @@ return { { val = "Exarch Ball", label = "Exarch Ball" }, { val = "Eater Beam", label = "Eater Beam" }, { val = "Maven Fireball", label = "Maven Fireball" }, - { val = "Maven Memory Game", label = "Maven Memory Game" } -} \ No newline at end of file + { val = "Maven Memory Game", label = "Maven Memory Game" } }, +} diff --git a/src/Data/Bosses.lua b/src/Data/Bosses.lua index 13f07d5cb2..66239e31f8 100644 --- a/src/Data/Bosses.lua +++ b/src/Data/Bosses.lua @@ -4,8 +4,7 @@ -- Boss Data -- Boss data (c) Grinding Gear Games -- -local bosses = ... - +local bosses = {} bosses["Venarius"] = { armourMult = 50, evasionMult = 0, @@ -121,3 +120,4 @@ bosses["Drox"] = { evasionMult = 0, isUber = false, } +return bosses diff --git a/src/Data/Minions.lua.rej b/src/Data/Minions.lua.rej new file mode 100644 index 0000000000..e8b2621cb7 --- /dev/null +++ b/src/Data/Minions.lua.rej @@ -0,0 +1,19 @@ +diff a/src/Data/Minions.lua b/src/Data/Minions.lua (rejected hunks) +@@ -4,8 +4,10 @@ + -- Minion Data + -- Monster data (c) Grinding Gear Games + -- +-local minions, mod = ... + ++return function(mod, flag) ++ ---@class MinionData ++ local minions = {} + minions["RaisedZombie"] = { + name = "Raised Zombie", + monsterTags = { "animal_claw_weapon", "fast_movement", "flesh_armour", "is_unarmed", "medium_height", "melee", "physical_affinity", "red_blood", "undead", "zombie", }, +@@ -1945,3 +1947,5 @@ minions["ShamblingUndead"] = { + -- set_item_drop_slots [set_item_drop_slots = 0] + }, + } ++ return minions ++end diff --git a/src/Data/Misc.lua.rej b/src/Data/Misc.lua.rej new file mode 100644 index 0000000000..6ef183cbf6 --- /dev/null +++ b/src/Data/Misc.lua.rej @@ -0,0 +1,15 @@ +diff a/src/Data/Misc.lua b/src/Data/Misc.lua (rejected hunks) +@@ -1,6 +1,7 @@ + -- This file is automatically generated, do not edit! + +-local data = ... ++---@class MiscDataExport ++local data = {} + -- From DefaultMonsterStats.dat + data.monsterEvasionTable = { 67, 86, 104, 124, 144, 166, 188, 211, 234, 259, 285, 311, 339, 368, 397, 428, 460, 493, 527, 563, 600, 638, 677, 718, 760, 804, 849, 896, 944, 994, 1046, 1100, 1155, 1212, 1271, 1332, 1395, 1460, 1528, 1597, 1669, 1743, 1819, 1898, 1979, 2063, 2150, 2239, 2331, 2426, 2524, 2626, 2730, 2837, 2948, 3063, 3180, 3302, 3427, 3556, 3689, 3826, 3967, 4112, 4262, 4416, 4575, 4739, 4907, 5081, 5260, 5444, 5633, 5828, 6029, 6235, 6448, 6667, 6892, 7124, 7362, 7608, 7860, 8120, 8388, 8663, 8946, 9237, 9536, 9844, 10160, 10486, 10821, 11165, 11519, 11883, 12258, 12643, 13038, 13445, } + data.monsterAccuracyTable = { 14, 15, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 28, 29, 31, 32, 34, 35, 37, 39, 41, 43, 45, 47, 49, 52, 54, 57, 59, 62, 65, 68, 71, 74, 77, 81, 84, 88, 92, 96, 100, 105, 109, 114, 119, 124, 129, 135, 140, 146, 152, 159, 165, 172, 179, 187, 195, 203, 211, 220, 229, 238, 247, 257, 268, 279, 290, 301, 314, 326, 339, 352, 366, 381, 396, 412, 428, 444, 462, 480, 499, 518, 538, 559, 580, 603, 626, 650, 675, 701, 728, 755, 784, 814, 845, 877, 910, 945, 980, } +@@ -473,3 +474,4 @@ data.mapLevelBossLifeMult = { [1] = 1.5, [2] = 1.52, [3] = 1.54, [4] = 1.56, [5] + data.mapLevelBossAilmentMult = { [1] = 0.81, [2] = 0.81, [3] = 0.81, [4] = 0.81, [5] = 0.81, [6] = 0.81, [7] = 0.81, [8] = 0.81, [9] = 0.81, [10] = 0.81, [11] = 0.81, [12] = 0.81, [13] = 0.81, [14] = 0.81, [15] = 0.81, [16] = 0.81, [17] = 0.81, [18] = 0.81, [19] = 0.81, [20] = 0.81, [21] = 0.81, [22] = 0.81, [23] = 0.81, [24] = 0.81, [25] = 0.81, [26] = 0.81, [27] = 0.81, [28] = 0.81, [29] = 0.81, [30] = 0.81, [31] = 0.81, [32] = 0.81, [33] = 0.81, [34] = 0.81, [35] = 0.81, [36] = 0.81, [37] = 0.81, [38] = 0.81, [39] = 0.81, [40] = 0.81, [41] = 0.81, [42] = 0.81, [43] = 0.81, [44] = 0.81, [45] = 0.81, [46] = 0.81, [47] = 0.81, [48] = 0.81, [49] = 0.81, [50] = 0.81, [51] = 0.8, [52] = 0.79, [53] = 0.78, [54] = 0.77, [55] = 0.76, [56] = 0.75, [57] = 0.74, [58] = 0.73, [59] = 0.72, [60] = 0.71, [61] = 0.7, [62] = 0.69, [63] = 0.68, [64] = 0.67, [65] = 0.66, [66] = 0.65, [67] = 0.64, [68] = 0.63, [69] = 0.59, [70] = 0.58, [71] = 0.57, [72] = 0.56, [73] = 0.55, [74] = 0.53, [75] = 0.52, [76] = 0.51, [77] = 0.5, [78] = 0.49, [79] = 0.48, [80] = 0.48, [81] = 0.47, [82] = 0.47, [83] = 0.47, [84] = 0.47, [85] = 0.47, [86] = 0.47, [87] = 0.47, [88] = 0.47, [89] = 0.47, [90] = 0.47, } + -- From VillageBalancePerLevelShared.dat + data.goldRespecPrices = { 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 11, 12, 14, 15, 17, 18, 20, 22, 24, 26, 28, 31, 34, 36, 39, 43, 46, 50, 54, 58, 62, 67, 72, 83, 90, 97, 105, 113, 121, 130, 151, 161, 171, 182, 209, 222, 237, 252, 267, 295, 313, 333, 354, 376, 427, 452, 482, 513, 546, 618, 656, 694, 733, 773, 816, 860, 892, 921, 1055, 1203, 1365, 1541, 1748, 1974, 2221, 2490, 2770, 3073, 3400, 3752, 4131, 4538, 4976, 5444, 5967, 6526, 7126, 7766, 8450, 9851, 11380, 13042, 14847, 16801, 18914, 21192, 23647, 26286, 29119, } ++return data diff --git a/src/Data/ModCache.lua.rej b/src/Data/ModCache.lua.rej new file mode 100644 index 0000000000..7c5192604c --- /dev/null +++ b/src/Data/ModCache.lua.rej @@ -0,0 +1,13 @@ +diff a/src/Data/ModCache.lua b/src/Data/ModCache.lua (rejected hunks) +@@ -1,4 +1,5 @@ +-local c=...c[" Wolf Alpha Talisman"]={nil," Wolf Alpha Talisman "} ++local c = {} ++c[" Wolf Alpha Talisman"]={nil," Wolf Alpha Talisman "} + c[" Wolf Alpha Talisman League: Talisman Standard"]={nil," Wolf Alpha Talisman League: Talisman Standard "} + c["(10-15)% increased Energy Shield Recharge Rate"]={nil,"(10-15)% increased Energy Shield Recharge Rate "} + c["(10-20)% increased Effect of Cold Ailments"]={nil,"(10-20)% increased Effect of Cold Ailments "} +@@ -13173,3 +13174,4 @@ c["wielding a Bow, with a 1 second Cooldown 12% increased Cast Speed"]={nil,"wie + c["you consume a total of 8 Steel Shards"]={nil,"you consume a total of 8 Steel Shards "} + c["your maximum number of Crab Barriers"]={nil,"your maximum number of Crab Barriers "} + c["your maximum number of Power Charges"]={nil,"your maximum number of Power Charges "} ++return c diff --git a/src/Data/SkillStatMap.lua b/src/Data/SkillStatMap.lua index 6e5decaed8..8bfd48b325 100644 --- a/src/Data/SkillStatMap.lua +++ b/src/Data/SkillStatMap.lua @@ -3,8 +3,7 @@ -- Stat to internal modifier mapping table for skills -- Stat data (c) Grinding Gear Games -- -local mod, flag, skill = ... - +return function(mod, flag, skill) return { -- -- Skill data modifiers diff --git a/src/Data/SkillStatMap.lua.rej b/src/Data/SkillStatMap.lua.rej new file mode 100644 index 0000000000..36306b9ea3 --- /dev/null +++ b/src/Data/SkillStatMap.lua.rej @@ -0,0 +1,6 @@ +diff a/src/Data/SkillStatMap.lua b/src/Data/SkillStatMap.lua (rejected hunks) +@@ -2372,3 +2371,4 @@ return { + -- Display only + }, + } ++end diff --git a/src/Data/Skills/act_dex.lua.rej b/src/Data/Skills/act_dex.lua.rej new file mode 100644 index 0000000000..76f86f3475 --- /dev/null +++ b/src/Data/Skills/act_dex.lua.rej @@ -0,0 +1,19 @@ +diff a/src/Data/Skills/act_dex.lua b/src/Data/Skills/act_dex.lua (rejected hunks) +@@ -4,8 +4,7 @@ + -- Active Dexterity skill gems + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + skills["AlchemistsMark"] = { + name = "Alchemist's Mark", + baseTypeName = "Alchemist's Mark", +@@ -18480,4 +18479,5 @@ skills["QuickstepHardMode"] = { + [9] = { cooldown = 10, levelRequirement = 1, storedUses = 1, }, + [10] = { cooldown = 10, levelRequirement = 1, storedUses = 1, }, + }, +-} +\ No newline at end of file ++} ++end diff --git a/src/Data/Skills/act_int.lua.rej b/src/Data/Skills/act_int.lua.rej new file mode 100644 index 0000000000..0013a82602 --- /dev/null +++ b/src/Data/Skills/act_int.lua.rej @@ -0,0 +1,19 @@ +diff a/src/Data/Skills/act_int.lua b/src/Data/Skills/act_int.lua (rejected hunks) +@@ -4,8 +4,7 @@ + -- Active Intelligence skill gems + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + skills["Arc"] = { + name = "Arc", + baseTypeName = "Arc", +@@ -21483,4 +21482,5 @@ skills["Zealotry"] = { + [39] = { 19, 53, 33, cooldown = 1.2, levelRequirement = 99, manaReservationPercent = 50, storedUses = 1, statInterpolation = { 1, 1, 1, }, }, + [40] = { 20, 54, 34, cooldown = 1.2, levelRequirement = 100, manaReservationPercent = 50, storedUses = 1, statInterpolation = { 1, 1, 1, }, }, + }, +-} +\ No newline at end of file ++} ++end diff --git a/src/Data/Skills/act_str.lua.rej b/src/Data/Skills/act_str.lua.rej new file mode 100644 index 0000000000..c59d056df1 --- /dev/null +++ b/src/Data/Skills/act_str.lua.rej @@ -0,0 +1,19 @@ +diff a/src/Data/Skills/act_str.lua b/src/Data/Skills/act_str.lua (rejected hunks) +@@ -4,8 +4,7 @@ + -- Active Strength skill gems + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + skills["Absolution"] = { + name = "Absolution", + baseTypeName = "Absolution", +@@ -13105,4 +13104,5 @@ skills["WarBanner"] = { + [39] = { 4, 8, 13, 13, cooldown = 1, levelRequirement = 99, storedUses = 1, statInterpolation = { 1, 1, 1, 1, }, cost = { Mana = 23, }, }, + [40] = { 4, 8, 13, 14, cooldown = 1, levelRequirement = 100, storedUses = 1, statInterpolation = { 1, 1, 1, 1, }, cost = { Mana = 23, }, }, + }, +-} +\ No newline at end of file ++} ++end diff --git a/src/Data/Skills/minion.lua.rej b/src/Data/Skills/minion.lua.rej new file mode 100644 index 0000000000..2e1887bbeb --- /dev/null +++ b/src/Data/Skills/minion.lua.rej @@ -0,0 +1,19 @@ +diff a/src/Data/Skills/minion.lua b/src/Data/Skills/minion.lua (rejected hunks) +@@ -4,8 +4,7 @@ + -- Minion active skills + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + skills["ChaosElementalCascadeSummoned"] = { + name = "Cascade", + hidden = true, +@@ -2346,4 +2345,5 @@ skills["MeleePartialChaos"] = { + levels = { + [1] = { 0, baseMultiplier = 0.75, levelRequirement = 1, statInterpolation = { 2, }, }, + }, +-} +\ No newline at end of file ++} ++end diff --git a/src/Data/Skills/other.lua.rej b/src/Data/Skills/other.lua.rej new file mode 100644 index 0000000000..741b8a2cd1 --- /dev/null +++ b/src/Data/Skills/other.lua.rej @@ -0,0 +1,17 @@ +diff a/src/Data/Skills/other.lua b/src/Data/Skills/other.lua (rejected hunks) +@@ -4,8 +4,7 @@ + -- Other active skills + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + skills["RepeatingShockwave"] = { + name = "Abberath's Fury", + hidden = true, +@@ -6144,3 +6143,5 @@ skills["EnemyExplode"] = { + [1] = { damageEffectiveness = 1, baseMultiplier = 1, levelRequirement = 1, } + } + } ++ ++end diff --git a/src/Data/Skills/spectre.lua.rej b/src/Data/Skills/spectre.lua.rej new file mode 100644 index 0000000000..77f89e3ea0 --- /dev/null +++ b/src/Data/Skills/spectre.lua.rej @@ -0,0 +1,19 @@ +diff a/src/Data/Skills/spectre.lua b/src/Data/Skills/spectre.lua (rejected hunks) +@@ -4,8 +4,7 @@ + -- Spectre active skills + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + skills["AxisCasterGlacialCascade"] = { + name = "Glacial Cascade", + hidden = true, +@@ -11884,4 +11883,5 @@ skills["VaalOverseerHeavyStrike"] = { + [1] = { baseMultiplier = 1.26, cooldown = 2, levelRequirement = 1, storedUses = 1, }, + [2] = { baseMultiplier = 1.26, cooldown = 2, levelRequirement = 68, storedUses = 1, }, + }, +-} +\ No newline at end of file ++} ++end diff --git a/src/Data/Skills/sup_dex.lua.rej b/src/Data/Skills/sup_dex.lua.rej new file mode 100644 index 0000000000..b81839eaec --- /dev/null +++ b/src/Data/Skills/sup_dex.lua.rej @@ -0,0 +1,19 @@ +diff a/src/Data/Skills/sup_dex.lua b/src/Data/Skills/sup_dex.lua (rejected hunks) +@@ -4,8 +4,7 @@ + -- Dexterity support gems + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + skills["SupportAddedColdDamage"] = { + name = "Added Cold Damage", + description = "Supports any skill that hits enemies.", +@@ -5050,4 +5049,5 @@ skills["SupportWitheringTouch"] = { + [39] = { 44, levelRequirement = 99, manaMultiplier = 30, statInterpolation = { 1, }, }, + [40] = { 44, levelRequirement = 100, manaMultiplier = 30, statInterpolation = { 1, }, }, + }, +-} +\ No newline at end of file ++} ++end diff --git a/src/Data/Skills/sup_int.lua.rej b/src/Data/Skills/sup_int.lua.rej new file mode 100644 index 0000000000..ff6ef8b7c7 --- /dev/null +++ b/src/Data/Skills/sup_int.lua.rej @@ -0,0 +1,19 @@ +diff a/src/Data/Skills/sup_int.lua b/src/Data/Skills/sup_int.lua (rejected hunks) +@@ -4,8 +4,7 @@ + -- Intelligence support gems + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + skills["SupportAddedChaosDamage"] = { + name = "Added Chaos Damage", + description = "Supports any skill that hits enemies.", +@@ -7004,4 +7003,5 @@ skills["SupportVaalSacrifice"] = { + [14] = { 120, levelRequirement = 94, statInterpolation = { 1, }, }, + [15] = { 125, levelRequirement = 95, statInterpolation = { 1, }, }, + }, +-} +\ No newline at end of file ++} ++end diff --git a/src/Data/Skills/sup_str.lua.rej b/src/Data/Skills/sup_str.lua.rej new file mode 100644 index 0000000000..643936e7bd --- /dev/null +++ b/src/Data/Skills/sup_str.lua.rej @@ -0,0 +1,19 @@ +diff a/src/Data/Skills/sup_str.lua b/src/Data/Skills/sup_str.lua (rejected hunks) +@@ -4,8 +4,7 @@ + -- Strength support gems + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + skills["SupportAddedFireDamage"] = { + name = "Added Fire Damage", + description = "Supports any skill that hits enemies.", +@@ -5545,4 +5544,5 @@ skills["SupportExpertRetaliation"] = { + [39] = { 107, 53, levelRequirement = 99, manaMultiplier = 30, statInterpolation = { 1, 1, }, }, + [40] = { 108, 54, levelRequirement = 100, manaMultiplier = 30, statInterpolation = { 1, 1, }, }, + }, +-} +\ No newline at end of file ++} ++end diff --git a/src/Data/Spectres.lua.rej b/src/Data/Spectres.lua.rej new file mode 100644 index 0000000000..6f0cb56248 --- /dev/null +++ b/src/Data/Spectres.lua.rej @@ -0,0 +1,19 @@ +diff a/src/Data/Spectres.lua b/src/Data/Spectres.lua (rejected hunks) +@@ -4,8 +4,10 @@ + -- Spectre Data + -- Monster data (c) Grinding Gear Games + -- +-local minions, mod, flag = ... + ++return function(mod, flag) ++ ---@class SpectreData ++ local minions = {} + -- Blackguard + minions["Metadata/Monsters/Axis/AxisCaster"] = { + name = "Blackguard Mage", +@@ -7225,3 +7227,5 @@ minions["Metadata/Monsters/VaalMonsters/VaalOverseer"] = { + modList = { + }, + } ++ return minions ++end diff --git a/src/Export/Bases/amulet.txt.rej b/src/Export/Bases/amulet.txt.rej new file mode 100644 index 0000000000..42418af62a --- /dev/null +++ b/src/Export/Bases/amulet.txt.rej @@ -0,0 +1,18 @@ +diff a/src/Export/Bases/amulet.txt b/src/Export/Bases/amulet.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Amulet + #influenceBaseTag amulet + +@@ -20,4 +19,5 @@ local itemBases = ... + #base Metadata/Items/Amulets/Talismans/Talisman2_6_4 Avian Twins Talisman (Cold-To-Fire) + #base Metadata/Items/Amulets/Talismans/Talisman2_6_5 Avian Twins Talisman (Lightning-To-Cold) + #base Metadata/Items/Amulets/Talismans/Talisman3_6_1 Monkey Paw Talisman (Power) +-#base Metadata/Items/Amulets/Talismans/Talisman3_6_2 Monkey Paw Talisman (Frenzy) +\ No newline at end of file ++#base Metadata/Items/Amulets/Talismans/Talisman3_6_2 Monkey Paw Talisman (Frenzy) ++end +\ No newline at end of file diff --git a/src/Export/Bases/axe.txt.rej b/src/Export/Bases/axe.txt.rej new file mode 100644 index 0000000000..7835534448 --- /dev/null +++ b/src/Export/Bases/axe.txt.rej @@ -0,0 +1,14 @@ +diff a/src/Export/Bases/axe.txt b/src/Export/Bases/axe.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type One Handed Axe + #influenceBaseTag axe + #socketLimit 3 +@@ -10,3 +9,4 @@ local itemBases = ... + #influenceBaseTag 2h_axe + #socketLimit 6 + #baseMatch BaseType Metadata/Items/Weapons/TwoHandWeapons/TwoHandAxes/AbstractTwoHandAxe ++end diff --git a/src/Export/Bases/belt.txt.rej b/src/Export/Bases/belt.txt.rej new file mode 100644 index 0000000000..25e04428d6 --- /dev/null +++ b/src/Export/Bases/belt.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Bases/belt.txt b/src/Export/Bases/belt.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Belt + #influenceBaseTag belt + #baseMatch Metadata/Items/Belts/Belt%d+ +@@ -11,4 +10,5 @@ local itemBases = ... + #base Metadata/Items/Belts/BeltAbyss + #base Metadata/Items/Belts/BeltFaridun + +-#base Metadata/Items/Belts/BeltDemigods1 +\ No newline at end of file ++#base Metadata/Items/Belts/BeltDemigods1 ++end diff --git a/src/Export/Bases/body.txt.rej b/src/Export/Bases/body.txt.rej new file mode 100644 index 0000000000..f822cec442 --- /dev/null +++ b/src/Export/Bases/body.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Bases/body.txt b/src/Export/Bases/body.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Body Armour + #influenceBaseTag body_armour + #socketLimit 6 +@@ -26,4 +25,5 @@ local itemBases = ... + #subType Armour/Evasion/Energy Shield + #baseMatch Metadata/Items/Armours/BodyArmours/BodyStrDexInt%d+ + #forceHide true +-#base Metadata/Items/Armours/BodyArmours/BodyDemigods1 +\ No newline at end of file ++#base Metadata/Items/Armours/BodyArmours/BodyDemigods1 ++end diff --git a/src/Export/Bases/boots.txt.rej b/src/Export/Bases/boots.txt.rej new file mode 100644 index 0000000000..f4de6ba6a1 --- /dev/null +++ b/src/Export/Bases/boots.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Bases/boots.txt b/src/Export/Bases/boots.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Boots + #influenceBaseTag boots + #socketLimit 4 +@@ -40,4 +39,5 @@ local itemBases = ... + #baseMatch Metadata/Items/Armours/Boots/BootsExpedition%d+ + + #subType +-#base Metadata/Items/Armours/Boots/BootsDemigods1 +\ No newline at end of file ++#base Metadata/Items/Armours/Boots/BootsDemigods1 ++end diff --git a/src/Export/Bases/bow.txt.rej b/src/Export/Bases/bow.txt.rej new file mode 100644 index 0000000000..032bb1edd6 --- /dev/null +++ b/src/Export/Bases/bow.txt.rej @@ -0,0 +1,13 @@ +diff a/src/Export/Bases/bow.txt b/src/Export/Bases/bow.txt (rejected hunks) +@@ -1,7 +1,7 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Bow + #influenceBaseTag bow + #socketLimit 6 +-#baseMatch BaseType Metadata/Items/Weapons/TwoHandWeapons/Bows/AbstractBow +\ No newline at end of file ++#baseMatch BaseType Metadata/Items/Weapons/TwoHandWeapons/Bows/AbstractBow ++end diff --git a/src/Export/Bases/claw.txt.rej b/src/Export/Bases/claw.txt.rej new file mode 100644 index 0000000000..571ba24808 --- /dev/null +++ b/src/Export/Bases/claw.txt.rej @@ -0,0 +1,13 @@ +diff a/src/Export/Bases/claw.txt b/src/Export/Bases/claw.txt (rejected hunks) +@@ -1,7 +1,7 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Claw + #influenceBaseTag claw + #socketLimit 3 +-#baseMatch BaseType Metadata/Items/Weapons/OneHandWeapons/Claws/AbstractClaw +\ No newline at end of file ++#baseMatch BaseType Metadata/Items/Weapons/OneHandWeapons/Claws/AbstractClaw ++end diff --git a/src/Export/Bases/dagger.txt.rej b/src/Export/Bases/dagger.txt.rej new file mode 100644 index 0000000000..3fedab89b7 --- /dev/null +++ b/src/Export/Bases/dagger.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Bases/dagger.txt b/src/Export/Bases/dagger.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Dagger + #influenceBaseTag dagger + #socketLimit 3 +@@ -10,4 +9,5 @@ local itemBases = ... + #subType Rune Dagger + #influenceBaseTag rune_dagger + #socketLimit 3 +-#baseMatch BaseType Metadata/Items/Weapons/OneHandWeapons/Daggers/AbstractRuneDagger +\ No newline at end of file ++#baseMatch BaseType Metadata/Items/Weapons/OneHandWeapons/Daggers/AbstractRuneDagger ++end diff --git a/src/Export/Bases/fishing.txt.rej b/src/Export/Bases/fishing.txt.rej new file mode 100644 index 0000000000..f12923d2d4 --- /dev/null +++ b/src/Export/Bases/fishing.txt.rej @@ -0,0 +1,11 @@ +diff a/src/Export/Bases/fishing.txt b/src/Export/Bases/fishing.txt (rejected hunks) +@@ -1,7 +1,7 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Fishing Rod + #socketLimit 4 + #forceShow true + #baseMatch Metadata/Items/Weapons/TwoHandWeapon/FishingRods/FishingRod ++end diff --git a/src/Export/Bases/flask.txt.rej b/src/Export/Bases/flask.txt.rej new file mode 100644 index 0000000000..3f4e2a4e6e --- /dev/null +++ b/src/Export/Bases/flask.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Bases/flask.txt b/src/Export/Bases/flask.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Flask + #subType Life + #baseMatch Metadata/Items/Flasks/FlaskLife +@@ -12,4 +11,5 @@ local itemBases = ... + #baseMatch Metadata/Items/Flasks/FlaskHybrid + + #subType Utility +-#baseMatch Metadata/Items/Flasks/FlaskUtility +\ No newline at end of file ++#baseMatch Metadata/Items/Flasks/FlaskUtility ++end diff --git a/src/Export/Bases/gloves.txt.rej b/src/Export/Bases/gloves.txt.rej new file mode 100644 index 0000000000..0c6190a8a8 --- /dev/null +++ b/src/Export/Bases/gloves.txt.rej @@ -0,0 +1,14 @@ +diff a/src/Export/Bases/gloves.txt b/src/Export/Bases/gloves.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Gloves + #influenceBaseTag gloves + #socketLimit 4 +@@ -35,3 +34,4 @@ local itemBases = ... + + #subType + #base Metadata/Items/Armours/Gloves/GlovesDemigods1 ++end diff --git a/src/Export/Bases/helmet.txt.rej b/src/Export/Bases/helmet.txt.rej new file mode 100644 index 0000000000..e5d489e1ad --- /dev/null +++ b/src/Export/Bases/helmet.txt.rej @@ -0,0 +1,14 @@ +diff a/src/Export/Bases/helmet.txt b/src/Export/Bases/helmet.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Helmet + #influenceBaseTag helmet + #socketLimit 4 +@@ -32,3 +31,4 @@ local itemBases = ... + + #subType + #base Metadata/Items/Armours/Helmets/HelmetWreath1 ++end diff --git a/src/Export/Bases/jewel.txt b/src/Export/Bases/jewel.txt index 61c1ae4321..2f1601a52a 100644 --- a/src/Export/Bases/jewel.txt +++ b/src/Export/Bases/jewel.txt @@ -1,6 +1,5 @@ -- Item data (c) Grinding Gear Games -local itemBases = ... - +return function(itemBases) #type Jewel #base Metadata/Items/Jewels/JewelStr #base Metadata/Items/Jewels/JewelDex diff --git a/src/Export/Bases/jewel.txt.rej b/src/Export/Bases/jewel.txt.rej new file mode 100644 index 0000000000..615cbda0a0 --- /dev/null +++ b/src/Export/Bases/jewel.txt.rej @@ -0,0 +1,9 @@ +diff a/src/Export/Bases/jewel.txt b/src/Export/Bases/jewel.txt (rejected hunks) +@@ -25,4 +24,5 @@ local itemBases = ... + #subType Charm + #base Metadata/Items/AnimalCharms/StrAnimalCharm + #base Metadata/Items/AnimalCharms/DexAnimalCharm +-#base Metadata/Items/AnimalCharms/IntAnimalCharm +\ No newline at end of file ++#base Metadata/Items/AnimalCharms/IntAnimalCharm ++end diff --git a/src/Export/Bases/mace.txt.rej b/src/Export/Bases/mace.txt.rej new file mode 100644 index 0000000000..a4645e12fc --- /dev/null +++ b/src/Export/Bases/mace.txt.rej @@ -0,0 +1,14 @@ +diff a/src/Export/Bases/mace.txt b/src/Export/Bases/mace.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type One Handed Mace + #influenceBaseTag mace + #socketLimit 3 +@@ -14,3 +13,4 @@ local itemBases = ... + #influenceBaseTag 2h_mace + #socketLimit 6 + #baseMatch BaseType Metadata/Items/Weapons/TwoHandWeapons/TwoHandMaces/AbstractTwoHandMace ++end diff --git a/src/Export/Bases/quiver.txt.rej b/src/Export/Bases/quiver.txt.rej new file mode 100644 index 0000000000..d88d0835a4 --- /dev/null +++ b/src/Export/Bases/quiver.txt.rej @@ -0,0 +1,14 @@ +diff a/src/Export/Bases/quiver.txt b/src/Export/Bases/quiver.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Quiver + #influenceBaseTag quiver + #forceHide true +@@ -12,3 +11,4 @@ local itemBases = ... + #baseMatch Metadata/Items/Quivers/Descent + #forceShow false + #baseMatch Metadata/Items/Quivers/QuiverAtlas%d+ ++end diff --git a/src/Export/Bases/ring.txt.rej b/src/Export/Bases/ring.txt.rej new file mode 100644 index 0000000000..fbfe40a96d --- /dev/null +++ b/src/Export/Bases/ring.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Bases/ring.txt b/src/Export/Bases/ring.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Ring + #influenceBaseTag ring + +@@ -19,4 +18,5 @@ local itemBases = ... + + #base Metadata/Items/Rings/BreachRing + #base Metadata/Items/Rings/RingDemigods1 +-#base Metadata/Items/Rings/RingVictor1 +\ No newline at end of file ++#base Metadata/Items/Rings/RingVictor1 ++end diff --git a/src/Export/Bases/shield.txt.rej b/src/Export/Bases/shield.txt.rej new file mode 100644 index 0000000000..36c30bcf93 --- /dev/null +++ b/src/Export/Bases/shield.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Bases/shield.txt b/src/Export/Bases/shield.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Shield + #influenceBaseTag shield + #socketLimit 3 +@@ -27,4 +26,5 @@ local itemBases = ... + #baseMatch Metadata/Items/Armours/Shields/ShieldDexInt%d+ + + #subType +-#base Metadata/Items/Armours/Shields/ShieldDemigods +\ No newline at end of file ++#base Metadata/Items/Armours/Shields/ShieldDemigods ++end diff --git a/src/Export/Bases/staff.txt.rej b/src/Export/Bases/staff.txt.rej new file mode 100644 index 0000000000..67fac69952 --- /dev/null +++ b/src/Export/Bases/staff.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Bases/staff.txt b/src/Export/Bases/staff.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Staff + #influenceBaseTag staff + #socketLimit 6 +@@ -10,4 +9,5 @@ local itemBases = ... + #subType Warstaff + #influenceBaseTag warstaff + #socketLimit 6 +-#baseMatch BaseType Metadata/Items/Weapons/TwoHandWeapons/Staves/AbstractWarstaff +\ No newline at end of file ++#baseMatch BaseType Metadata/Items/Weapons/TwoHandWeapons/Staves/AbstractWarstaff ++end diff --git a/src/Export/Bases/sword.txt.rej b/src/Export/Bases/sword.txt.rej new file mode 100644 index 0000000000..6cf2c6ab19 --- /dev/null +++ b/src/Export/Bases/sword.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Bases/sword.txt b/src/Export/Bases/sword.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type One Handed Sword + #socketLimit 3 + #influenceBaseTag sword +@@ -26,4 +25,5 @@ local itemBases = ... + + #forceHide true + #base Metadata/Items/Weapons/TwoHandWeapons/TwoHandSwords/StormBladeTwoHand +-#forceHide false +\ No newline at end of file ++#forceHide false ++end diff --git a/src/Export/Bases/wand.txt.rej b/src/Export/Bases/wand.txt.rej new file mode 100644 index 0000000000..3511cfbea8 --- /dev/null +++ b/src/Export/Bases/wand.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Bases/wand.txt b/src/Export/Bases/wand.txt (rejected hunks) +@@ -1,6 +1,5 @@ + -- Item data (c) Grinding Gear Games +-local itemBases = ... +- ++return function(itemBases) + #type Wand + #influenceBaseTag wand + #socketLimit 3 +@@ -19,4 +18,5 @@ local itemBases = ... + #type Wand + #influenceBaseTag wand + #socketLimit 3 +-#base Metadata/Items/Weapons/OneHandWeapons/Wands/WandMinion2 +\ No newline at end of file ++#base Metadata/Items/Weapons/OneHandWeapons/Wands/WandMinion2 ++end diff --git a/src/Export/Classes/Dat64File.lua b/src/Export/Classes/Dat64File.lua index 9ebb0b6e22..4d052f3423 100644 --- a/src/Export/Classes/Dat64File.lua +++ b/src/Export/Classes/Dat64File.lua @@ -84,7 +84,10 @@ local dataTypes = { }, } -local Dat64FileClass = newClass("Dat64File", function(self, name, raw) +---@class Dat64File +local Dat64FileClass = newClass("Dat64File") + +function Dat64FileClass:Dat64File(name, raw) self.name = name:lower() self.raw = raw @@ -124,7 +127,8 @@ local Dat64FileClass = newClass("Dat64File", function(self, name, raw) --ConPrintf("Loaded '%s': %d Rows at %d Bytes", self.name, self.rowCount, self.rowSize) self:OnSpecChanged() -end) + return self +end function Dat64FileClass:OnSpecChanged() wipeTable(self.cols) diff --git a/src/Export/Classes/DatFile.lua b/src/Export/Classes/DatFile.lua index f63f80a92e..6bc843fe95 100644 --- a/src/Export/Classes/DatFile.lua +++ b/src/Export/Classes/DatFile.lua @@ -76,7 +76,10 @@ local dataTypes = { }, } -local DatFileClass = newClass("DatFile", function(self, name, raw) +---@class DatFile +local DatFileClass = newClass("DatFile") + +function DatFileClass:DatFile(name, raw) self.name = name self.raw = raw @@ -116,7 +119,8 @@ local DatFileClass = newClass("DatFile", function(self, name, raw) --ConPrintf("Loaded '%s': %d Rows at %d Bytes", self.name, self.rowCount, self.rowSize) self:OnSpecChanged() -end) + return self +end function DatFileClass:OnSpecChanged() wipeTable(self.cols) diff --git a/src/Export/Classes/DatListControl.lua b/src/Export/Classes/DatListControl.lua index e1153982d9..a47aac70d7 100644 --- a/src/Export/Classes/DatListControl.lua +++ b/src/Export/Classes/DatListControl.lua @@ -3,12 +3,16 @@ -- Class: Dat List -- Dat list control. -- -local DatListClass = newClass("DatListControl", "ListControl", function(self, anchor, rect) +---@class DatListControl: ListControl +local DatListClass = newClass("DatListControl", "ListControl") + +function DatListClass:DatListControl(anchor, rect) self.originalList = main.datFileList self.searchBuf = "" self.filteredList = self.originalList - self.ListControl(anchor, rect, 14, "VERTICAL", false, self.filteredList) -end) + self:ListControl(anchor, rect, 14, "VERTICAL", false, self.filteredList) + return self +end function DatListClass:BuildFilteredList() local search = self.searchBuf:lower() diff --git a/src/Export/Classes/GGPKData.lua b/src/Export/Classes/GGPKData.lua index 88236939ea..f327739712 100644 --- a/src/Export/Classes/GGPKData.lua +++ b/src/Export/Classes/GGPKData.lua @@ -31,7 +31,10 @@ end -- Path can be in any format recognized by the extractor at oozPath, ie, -- a .ggpk file or a Steam Path of Exile directory -local GGPKClass = newClass("GGPKData", function(self, path, datPath, reExport) +---@class GGPKData +local GGPKClass = newClass("GGPKData") + +function GGPKClass:GGPKData(path, datPath, reExport) if datPath then self.oozPath = datPath:match("\\$") and datPath or (datPath .. "\\") else diff --git a/src/Export/Classes/GGPKData.lua.rej b/src/Export/Classes/GGPKData.lua.rej new file mode 100644 index 0000000000..7ccdcf85d7 --- /dev/null +++ b/src/Export/Classes/GGPKData.lua.rej @@ -0,0 +1,11 @@ +diff a/src/Export/Classes/GGPKData.lua b/src/Export/Classes/GGPKData.lua (rejected hunks) +@@ -46,7 +49,8 @@ local GGPKClass = newClass("GGPKData", function(self, path, datPath, reExport) + self.ot = { } + + self:AddDat64Files() +-end) ++ return self ++end + + function GGPKClass:CleanDir(reExport) + if reExport then diff --git a/src/Export/Classes/GGPKSourceListControl.lua b/src/Export/Classes/GGPKSourceListControl.lua index 90f01fd3ca..ab478c1f8e 100644 --- a/src/Export/Classes/GGPKSourceListControl.lua +++ b/src/Export/Classes/GGPKSourceListControl.lua @@ -3,46 +3,50 @@ -- Class: GGPK Source List -- GGPK source list control. -- -local GGPKSourceListClass = newClass("GGPKSourceListControl", "ListControl", function(self, anchor, rect) - self.ListControl(anchor, rect, 16, false, false, main.datSources) +---@class GGPKSourceListControl: ListControl +local GGPKSourceListClass = newClass("GGPKSourceListControl", "ListControl") + +function GGPKSourceListClass:GGPKSourceListControl(anchor, rect) + self:ListControl(anchor, rect, 16, false, false, main.datSources) self.colList = { { width = self.width * 0.25, label = "Name", sortable = true }, { width = self.width * 0.75, label = "Spec File Path" }, } self.colLabels = true - self.controls.new = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {-62, -4, 60, 18}, "New", function() + self.controls.new = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self,"TOP"}, {-62, -4, 60, 18}, "New", function() local datSource = {} self:EditDATSource(datSource, true) end) - self.controls.delete = new("ButtonControl", {"LEFT",self.controls.new,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"LEFT",self.controls.new,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() self:OnSelDelete(self.selIndex) end) self.controls.delete.enabled = function() return self.selValue ~= nil and #self.list > 1 end -end) + return self +end function GGPKSourceListClass:EditDATSource(datSource, newSource) local controls = { } - controls.labelLabel = new("LabelControl", nil, {-30, 20, 0, 16}, "^7Name:") - controls.label = new("EditControl", nil, {85, 20, 180, 20}, datSource.label, nil, nil, nil, function(buf) + controls.labelLabel = new("LabelControl"):LabelControl(nil, {-30, 20, 0, 16}, "^7Name:") + controls.label = new("EditControl"):EditControl(nil, {85, 20, 180, 20}, datSource.label, nil, nil, nil, function(buf) controls.save.enabled = (controls.dat.buf:match("%S") or controls.ggpk.buf:match("%S")) and buf:match("%S") end) - controls.ggpkLabel = new("LabelControl", nil, {0, 40, 0, 16}, "^7Source from GGPK/Steam PoE path:") - controls.ggpk = new("EditControl", {"TOP",controls.ggpkLabel,"TOP"}, {0, 20, 350, 20}, datSource.ggpkPath, nil, nil, nil, function(buf) + controls.ggpkLabel = new("LabelControl"):LabelControl(nil, {0, 40, 0, 16}, "^7Source from GGPK/Steam PoE path:") + controls.ggpk = new("EditControl"):EditControl({"TOP",controls.ggpkLabel,"TOP"}, {0, 20, 350, 20}, datSource.ggpkPath, nil, nil, nil, function(buf) controls.save.enabled = (buf:match("%S") or controls.dat.buf:match("%S")) and controls.label.buf:match("%S") and controls.spec.buf:match("%S") end) controls.ggpk.enabled = function() return not controls.dat.buf:match("%S") end - controls.datLabel = new("LabelControl", {"TOP",controls.ggpk,"TOP"}, {0, 22, 0, 16}, "^7Source from DAT files:") - controls.dat = new("EditControl", {"TOP",controls.datLabel,"TOP"}, {0, 20, 350, 20}, datSource.datFilePath, nil, nil, nil, function(buf) + controls.datLabel = new("LabelControl"):LabelControl({"TOP",controls.ggpk,"TOP"}, {0, 22, 0, 16}, "^7Source from DAT files:") + controls.dat = new("EditControl"):EditControl({"TOP",controls.datLabel,"TOP"}, {0, 20, 350, 20}, datSource.datFilePath, nil, nil, nil, function(buf) controls.save.enabled = (buf:match("%S") or controls.ggpk.buf:match("%S")) and controls.label.buf:match("%S") and controls.spec.buf:match("%S") end) controls.dat.enabled = function() return not controls.ggpk.buf:match("%S") end - controls.specLabel = new("LabelControl", {"TOP",controls.dat,"TOP"}, {0, 22, 0, 16}, "^7Spec File location:") - controls.spec = new("EditControl", {"TOP",controls.specLabel,"TOP"}, {0, 20, 350, 20}, datSource.spec or "spec.lua", nil, nil, nil, function(buf) + controls.specLabel = new("LabelControl"):LabelControl({"TOP",controls.dat,"TOP"}, {0, 22, 0, 16}, "^7Spec File location:") + controls.spec = new("EditControl"):EditControl({"TOP",controls.specLabel,"TOP"}, {0, 20, 350, 20}, datSource.spec or "spec.lua", nil, nil, nil, function(buf) controls.save.enabled = (controls.dat.buf:match("%S") or controls.ggpk.buf:match("%S")) and controls.label.buf:match("%S") and buf:match("%S") end) - controls.save = new("ButtonControl", {"TOP",controls.spec,"TOP"}, {-45, 22, 80, 20}, "Save", function() + controls.save = new("ButtonControl"):ButtonControl({"TOP",controls.spec,"TOP"}, {-45, 22, 80, 20}, "Save", function() local reload = datSource.label == (main.datSource and main.datSource.label) datSource.label = controls.label.buf datSource.ggpkPath = controls.ggpk.buf or "" @@ -59,7 +63,7 @@ function GGPKSourceListClass:EditDATSource(datSource, newSource) main:ClosePopup() end) controls.save.enabled = false - controls.cancel = new("ButtonControl", {"TOP",controls.spec,"TOP"}, {45, 22, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl({"TOP",controls.spec,"TOP"}, {45, 22, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(370, 200, datSource[1] and "Edit DAT Source" or "New DAT Source", controls, "save", "edit") diff --git a/src/Export/Classes/RowListControl.lua b/src/Export/Classes/RowListControl.lua index e108716069..46a70a93e2 100644 --- a/src/Export/Classes/RowListControl.lua +++ b/src/Export/Classes/RowListControl.lua @@ -6,11 +6,15 @@ local ipairs = ipairs local t_insert = table.insert -local RowListClass = newClass("RowListControl", "ListControl", function(self, anchor, rect) - self.ListControl(anchor, rect, 14, "HORIZONTAL", false, { }) +---@class RowListControl: ListControl +local RowListClass = newClass("RowListControl", "ListControl") + +function RowListClass:RowListControl(anchor, rect) + self:ListControl(anchor, rect, 14, "HORIZONTAL", false, { }) self.colLabels = true self._autoSizeToggleState = {} -- internal toggle memory, not saved to spec -end) + return self +end function RowListClass:BuildRows(filter) wipeTable(self.list) diff --git a/src/Export/Classes/ScriptListControl.lua b/src/Export/Classes/ScriptListControl.lua index 048f02544c..c4bc132769 100644 --- a/src/Export/Classes/ScriptListControl.lua +++ b/src/Export/Classes/ScriptListControl.lua @@ -3,9 +3,13 @@ -- Class: Script List -- Script list control. -- -local ScriptListClass = newClass("ScriptListControl", "ListControl", function(self, anchor, rect) - self.ListControl(anchor, rect, 16, "VERTICAL", false, main.scriptList) -end) +---@class ScriptListControl: ListControl +local ScriptListClass = newClass("ScriptListControl", "ListControl") + +function ScriptListClass:ScriptListControl(anchor, rect) + self:ListControl(anchor, rect, 16, "VERTICAL", false, main.scriptList) + return self +end function ScriptListClass:GetRowValue(column, index, script) if column == 1 then diff --git a/src/Export/Classes/SpecColListControl.lua b/src/Export/Classes/SpecColListControl.lua index 9371234e68..ca491dcf11 100644 --- a/src/Export/Classes/SpecColListControl.lua +++ b/src/Export/Classes/SpecColListControl.lua @@ -5,9 +5,13 @@ -- local t_remove = table.remove -local SpecColListClass = newClass("SpecColListControl", "ListControl", function(self, anchor, rect) - self.ListControl(anchor, rect, 14, "VERTICAL", true) -end) +---@class SpecColListControl: ListControl +local SpecColListClass = newClass("SpecColListControl", "ListControl") + +function SpecColListClass:SpecColListControl(anchor, rect) + self:ListControl(anchor, rect, 14, "VERTICAL", true) + return self +end function SpecColListClass:GetRowValue(column, index, specCol) if column == 1 then diff --git a/src/Export/Enemies/BossSkills.txt b/src/Export/Enemies/BossSkills.txt index 8c56f8111e..529a9aaa5e 100644 --- a/src/Export/Enemies/BossSkills.txt +++ b/src/Export/Enemies/BossSkills.txt @@ -4,6 +4,7 @@ -- Boss Skill data (c) Grinding Gear Games -- return { + bossSkills = { #boss Atziri Metadata/Monsters/Atziri/Atziri true true #skill Flameblast AtziriFlameblastEmpowered, stages = 10, #tooltip "The Uber variant has 10 ^xB97123Fire^7 penetration (Applied on Pinnacle And Uber)" @@ -31,4 +32,9 @@ return { #tooltip "Allocating Throw the Gauntlet increases Damage by a further 100% (Applied on Uber) and causes the fireball to have 30 ^xB97123Fire^7 penetration (Applied on Uber)" #skill MemoryGame MavenMemoryGame, skillIndexUber = nil, #tooltip "Cannot be Blocked, Dodged, or Suppressed. \n It is three separate hits, and has a large DoT effect. Neither is taken into account here. \n i.e. Hits before death should be more than 3 to survive" -#skillList \ No newline at end of file + }, + + bossSkillsList = { +#skillList + }, +} \ No newline at end of file diff --git a/src/Export/Enemies/Bosses.txt b/src/Export/Enemies/Bosses.txt index b742ecc932..3892b0e3db 100644 --- a/src/Export/Enemies/Bosses.txt +++ b/src/Export/Enemies/Bosses.txt @@ -3,8 +3,7 @@ -- Boss Data -- Boss data (c) Grinding Gear Games -- -local bosses = ... - +local bosses = {} #boss Venarius SynthesisVenarius {Uber} #boss EaterOfWorlds AtlasInvadersConsumeBoss {Uber} #boss SearingExarch AtlasInvadersCleansingBoss {Uber} @@ -31,4 +30,5 @@ local bosses = ... #boss Baran AtlasExiles1 #boss Veritania AtlasExiles2 #boss AlHezmin AtlasExiles3 -#boss Drox AtlasExiles4 \ No newline at end of file +#boss Drox AtlasExiles4 +return bosses \ No newline at end of file diff --git a/src/Export/Main.lua b/src/Export/Main.lua index f6ef44f74a..3b463d7149 100644 --- a/src/Export/Main.lua +++ b/src/Export/Main.lua @@ -20,7 +20,7 @@ LoadModule("../Modules/Common.lua") LoadModule("../Classes/ControlHost.lua") -main = new("ControlHost") +main = new("ControlHost"):ControlHost() local classList = { "UndoHandler", @@ -53,10 +53,10 @@ local ourClassList = { "GGPKData", } for _, className in ipairs(classList) do - LoadModule("../Classes/"..className..".lua", launch, main) + LoadModule("../Classes/" .. className .. ".lua") end for _, className in ipairs(ourClassList) do - LoadModule("Classes/"..className, launch, main) + LoadModule("Classes/" .. className) end local tempTable1 = { } @@ -164,14 +164,14 @@ function main:Init() self.colList = { } - self.controls.shownLeagueLabel = new("LabelControl", nil, {10, 10, 100, 16}, "^7Data from:") - self.controls.leagueLabel = new("LabelControl", {"LEFT", self.controls.shownLeagueLabel, "RIGHT"}, {10, 0, 100, 16}, function() return "^7" .. (self.leagueLabel or "Unknown") end) - self.controls.addSource = new("ButtonControl", nil, {10, 30, 100, 18}, "Edit Sources...", function() - self.OpenPathPopup() + self.controls.shownLeagueLabel = new("LabelControl"):LabelControl(nil, {10, 10, 100, 16}, "^7Data from:") + self.controls.leagueLabel = new("LabelControl"):LabelControl({"LEFT", self.controls.shownLeagueLabel, "RIGHT"}, {10, 0, 100, 16}, function() return "^7" .. (self.leagueLabel or "Unknown") end) + self.controls.addSource = new("ButtonControl"):ButtonControl(nil, {10, 30, 100, 18}, "Edit Sources...", function() + self:OpenPathPopup() end) self.datSources = self.datSources or { } - self.controls.datSource = new("DropDownControl", nil, {10, 50, 250, 18}, self.datSources, function(_, value) + self.controls.datSource = new("DropDownControl"):DropDownControl(nil, {10, 50, 250, 18}, self.datSources, function(_, value) self:LoadDatSource(value) end, nil) @@ -179,11 +179,11 @@ function main:Init() self.controls.datSource:SelByValue(self.datSource.label, "label") end - self.controls.scripts = new("ButtonControl", nil, {160, 30, 100, 18}, "Scripts >>", function() + self.controls.scripts = new("ButtonControl"):ButtonControl(nil, {160, 30, 100, 18}, "Scripts >>", function() self:SetCurrentDat() end) - self.controls.scriptAll = new("ButtonControl", nil, {270, 10, 140, 18}, "Run All", function() + self.controls.scriptAll = new("ButtonControl"):ButtonControl(nil, {270, 10, 140, 18}, "Run All", function() do -- run stat desc first local errMsg = PLoadModule("Scripts/".."statdesc"..".lua") if errMsg then @@ -240,14 +240,14 @@ function main:Init() end ) - self.controls.datSearch = new("EditControl", {"TOPLEFT", self.controls.datSource, "BOTTOMLEFT"}, {0, 2, 250, 18}, nil, "^7Search", nil, nil, function(buf) + self.controls.datSearch = new("EditControl"):EditControl({"TOPLEFT", self.controls.datSource, "BOTTOMLEFT"}, {0, 2, 250, 18}, nil, "^7Search", nil, nil, function(buf) self.controls.datList.searchBuf = buf self.controls.datList:BuildFilteredList() end, nil, nil, true) - self.controls.datList = new("DatListControl", {"TOPLEFT",self.controls.datSearch,"BOTTOMLEFT"}, {0, 2, 250, function() return self.screenH - 100 end}) + self.controls.datList = new("DatListControl"):DatListControl({"TOPLEFT",self.controls.datSearch,"BOTTOMLEFT"}, {0, 2, 250, function() return self.screenH - 100 end}) - self.controls.specEditToggle = new("ButtonControl", nil, {270, 10, 100, 18}, function() return self.editSpec and "Done <<" or "Edit >>" end, function() + self.controls.specEditToggle = new("ButtonControl"):ButtonControl(nil, {270, 10, 100, 18}, function() return self.editSpec and "Done <<" or "Edit >>" end, function() self.editSpec = not self.editSpec if self.editSpec then self:SetCurrentCol(1) @@ -257,13 +257,13 @@ function main:Init() return self.curDatFile end } - self.controls.specColList = new("SpecColListControl", {"TOPLEFT",self.controls.specEditToggle,"BOTTOMLEFT"}, {0, 2, 200, 200}) { + self.controls.specColList = new("SpecColListControl"):SpecColListControl({"TOPLEFT",self.controls.specEditToggle,"BOTTOMLEFT"}, {0, 2, 200, 200}) { shown = function() return self.editSpec end } - self.controls.colName = new("EditControl", {"TOPLEFT",self.controls.specColList,"TOPRIGHT"}, {10, 0, 150, 18}, nil, nil, nil, nil, function(buf) + self.controls.colName = new("EditControl"):EditControl({"TOPLEFT",self.controls.specColList,"TOPRIGHT"}, {10, 0, 150, 18}, nil, nil, nil, nil, function(buf) self.curSpecCol.name = buf self.curDatFile:OnSpecChanged() self.controls.rowList:BuildColumns() @@ -277,19 +277,19 @@ function main:Init() end } - self.controls.colType = new("DropDownControl", {"TOPLEFT",self.controls.colName,"BOTTOMLEFT"}, {0, 4, 90, 18}, self.typeDrop, function(_, value) + self.controls.colType = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.colName,"BOTTOMLEFT"}, {0, 4, 90, 18}, self.typeDrop, function(_, value) self.curSpecCol.type = value self.curDatFile:OnSpecChanged() self:UpdateCol() end, "^7Field type in the dat file") - self.controls.colIsList = new("CheckBoxControl", {"TOPLEFT",self.controls.colType,"BOTTOMLEFT"}, {30, 4, 18}, "List:", function(state) + self.controls.colIsList = new("CheckBoxControl"):CheckBoxControl({"TOPLEFT",self.controls.colType,"BOTTOMLEFT"}, {30, 4, 18}, "List:", function(state) self.curSpecCol.list = state self.curDatFile:OnSpecChanged() self.controls.rowList:BuildColumns() end) - self.controls.colRefTo = new("EditControl", {"TOPLEFT",self.controls.colType,"BOTTOMLEFT"}, {0, 26, 150, 18}, nil, nil, nil, nil, function(buf) + self.controls.colRefTo = new("EditControl"):EditControl({"TOPLEFT",self.controls.colType,"BOTTOMLEFT"}, {0, 26, 150, 18}, nil, nil, nil, nil, function(buf) self.curSpecCol.refTo = buf self.curDatFile:OnSpecChanged() end) { @@ -299,7 +299,7 @@ function main:Init() end } - self.controls.colWidth = new("EditControl", {"TOPLEFT",self.controls.colRefTo,"BOTTOMLEFT"}, {0, 4, 100, 18}, nil, nil, "%D", nil, function(buf) + self.controls.colWidth = new("EditControl"):EditControl({"TOPLEFT",self.controls.colRefTo,"BOTTOMLEFT"}, {0, 4, 100, 18}, nil, nil, "%D", nil, function(buf) self.curSpecCol.width = m_max(tonumber(buf) or 150, 20) self.controls.rowList:BuildColumns() end) { @@ -310,7 +310,7 @@ function main:Init() end } - self.controls.enumBase = new("EditControl", {"TOPLEFT",self.controls.colWidth,"BOTTOMLEFT"}, {0, 4, 100, 18}, nil, nil, "%D", nil, function(buf) + self.controls.enumBase = new("EditControl"):EditControl({"TOPLEFT",self.controls.colWidth,"BOTTOMLEFT"}, {0, 4, 100, 18}, nil, nil, "%D", nil, function(buf) self.curSpecCol.enumBase = tonumber(buf) or 0 self.curDatFile:OnSpecChanged() end) { @@ -321,14 +321,14 @@ function main:Init() end } - self.controls.colDelete = new("ButtonControl", {"BOTTOMRIGHT",self.controls.colName,"TOPRIGHT"}, {0, -4, 18, 18}, "x", function() + self.controls.colDelete = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self.controls.colName,"TOPRIGHT"}, {0, -4, 18, 18}, "x", function() t_remove(self.curDatFile.spec, self.curSpecColIndex) self.curDatFile:OnSpecChanged() self.controls.rowList:BuildColumns() self:SetCurrentCol() end) - self.controls.filter = new("EditControl", nil, {270, 0, 800, 18}, nil, "^8Filter") { + self.controls.filter = new("EditControl"):EditControl(nil, {270, 0, 800, 18}, nil, "^8Filter") { y = function() return self.editSpec and 240 or 30 end, @@ -341,10 +341,10 @@ function main:Init() end, } self.controls.filter.tooltipText = "Takes a Lua expression that returns true or false for a row.\nE.g. `Id:match(\"test\")` or for a key column, `Col and Col.Id:match(\"test\")`" - self.controls.filterError = new("LabelControl", {"LEFT",self.controls.filter,"RIGHT"}, {4, 2, 0, 14}, "") - self.controls.showRaw = new("LabelControl", {"LEFT",self.controls.filter,"RIGHT"}, {600, 2, 0, 14}, "^7Hold ALT to show raw data.") + self.controls.filterError = new("LabelControl"):LabelControl({"LEFT",self.controls.filter,"RIGHT"}, {4, 2, 0, 14}, "") + self.controls.showRaw = new("LabelControl"):LabelControl({"LEFT",self.controls.filter,"RIGHT"}, {600, 2, 0, 14}, "^7Hold ALT to show raw data.") - self.controls.rowList = new("RowListControl", nil, {270, 0, 0, 0}) { + self.controls.rowList = new("RowListControl"):RowListControl(nil, {270, 0, 0, 0}) { y = function() return self.editSpec and 260 or 50 end, @@ -359,7 +359,7 @@ function main:Init() end } - self.controls.addCol = new("ButtonControl", {"LEFT",self.controls.specEditToggle,"RIGHT"}, {10, 0, 80, 18}, "Add", function() + self.controls.addCol = new("ButtonControl"):ButtonControl({"LEFT",self.controls.specEditToggle,"RIGHT"}, {10, 0, 80, 18}, "Add", function() self:AddSpecCol() end) { shown = function() @@ -399,8 +399,8 @@ end function main:OpenPathPopup() main:OpenPopup(370, 290, "Manage GGPK versions", { - new("GGPKSourceListControl", nil, {0, 50, 350, 200}, self), - new("ButtonControl", nil, {0, 260, 90, 20}, "Done", function() + new("GGPKSourceListControl"):GGPKSourceListControl(nil, {0, 50, 350, 200}, self), + new("ButtonControl"):ButtonControl(nil, {0, 260, 90, 20}, "Done", function() main:ClosePopup() end), }) @@ -489,10 +489,10 @@ function main:InitGGPK() local now = GetTime() local ggpkPath = self.datSource.ggpkPath if ggpkPath and ggpkPath ~= "" then - self.ggpk = new("GGPKData", ggpkPath, nil, self.reExportGGPKData) + self.ggpk = new("GGPKData"):GGPKData(ggpkPath, nil, self.reExportGGPKData) ConPrintf("GGPK: %d ms", GetTime() - now) elseif self.datSource.datFilePath then - self.ggpk = new("GGPKData", nil, self.datSource.datFilePath, self.reExportGGPKData) + self.ggpk = new("GGPKData"):GGPKData(nil, self.datSource.datFilePath, self.reExportGGPKData) ConPrintf("GGPK: %d ms", GetTime() - now) end end @@ -505,7 +505,7 @@ function main:LoadDatFiles() ConPrintf("DAT find: %d ms", GetTime() - now) now = GetTime() end - local datFile = new("DatFile", record.name:gsub("%.dat$",""), record.data) + local datFile = new("DatFile"):DatFile(record.name:gsub("%.dat$",""), record.data) t_insert(self.datFileList, datFile) self.datFileByName[datFile.name] = datFile end @@ -519,7 +519,7 @@ function main:LoadDat64Files() ConPrintf("DAT64 find: %d ms", GetTime() - now) now = GetTime() end - local datFile = new("Dat64File", record.name:gsub("%.datc64$",""), record.data) + local datFile = new("Dat64File"):Dat64File(record.name:gsub("%.datc64$",""), record.data) t_insert(self.datFileList, datFile) self.datFileByName[datFile.name] = datFile end @@ -777,7 +777,7 @@ function main:CopyFolder(srcName, dstName) end function main:OpenPopup(width, height, title, controls, enterControl, defaultControl, escapeControl, scrollBarFunc, resizeFunc) - local popup = new("PopupDialog", width, height, title, controls, enterControl, defaultControl, escapeControl, scrollBarFunc, resizeFunc) + local popup = new("PopupDialog"):PopupDialog(width, height, title, controls, enterControl, defaultControl, escapeControl, scrollBarFunc, resizeFunc) t_insert(self.popups, 1, popup) return popup end @@ -790,10 +790,10 @@ function main:OpenMessagePopup(title, msg) local controls = { } local numMsgLines = 0 for line in string.gmatch(msg .. "\n", "([^\n]*)\n") do - t_insert(controls, new("LabelControl", nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) + t_insert(controls, new("LabelControl"):LabelControl(nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) numMsgLines = numMsgLines + 1 end - controls.close = new("ButtonControl", nil, {0, 40 + numMsgLines * 16, 80, 20}, "Ok", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {0, 40 + numMsgLines * 16, 80, 20}, "Ok", function() main:ClosePopup() end) return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "close") @@ -803,15 +803,15 @@ function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm) local controls = { } local numMsgLines = 0 for line in string.gmatch(msg .. "\n", "([^\n]*)\n") do - t_insert(controls, new("LabelControl", nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) + t_insert(controls, new("LabelControl"):LabelControl(nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) numMsgLines = numMsgLines + 1 end local confirmWidth = m_max(80, DrawStringWidth(16, "VAR", confirmLabel) + 10) - controls.confirm = new("ButtonControl", nil, {-5 - m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, confirmLabel, function() + controls.confirm = new("ButtonControl"):ButtonControl(nil, {-5 - m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, confirmLabel, function() main:ClosePopup() onConfirm() end) - t_insert(controls, new("ButtonControl", nil, {5 + m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, "Cancel", function() + t_insert(controls, new("ButtonControl"):ButtonControl(nil, {5 + m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, "Cancel", function() main:ClosePopup() end)) return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "confirm") @@ -819,11 +819,11 @@ end function main:OpenNewFolderPopup(path, onClose) local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter folder name:") - controls.edit = new("EditControl", nil, {0, 40, 350, 20}, nil, nil, "\\/:%*%?\"<>|%c", 100, function(buf) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter folder name:") + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, nil, nil, "\\/:%*%?\"<>|%c", 100, function(buf) controls.create.enabled = buf:match("%S") end) - controls.create = new("ButtonControl", nil, {-45, 70, 80, 20}, "Create", function() + controls.create = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Create", function() local newFolderName = controls.edit.buf local res, msg = MakeDir(path..newFolderName) if not res then @@ -836,7 +836,7 @@ function main:OpenNewFolderPopup(path, onClose) main:ClosePopup() end) controls.create.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() if onClose then onClose() end diff --git a/src/Export/Main.lua.rej b/src/Export/Main.lua.rej new file mode 100644 index 0000000000..2224cc062d --- /dev/null +++ b/src/Export/Main.lua.rej @@ -0,0 +1,39 @@ +diff a/src/Export/Main.lua b/src/Export/Main.lua (rejected hunks) +@@ -195,7 +195,7 @@ function main:Init() + end + } + +- self.controls.clearOutput = new("ButtonControl", nil, {1230, 10, 100, 18}, "Clear", function() ++ self.controls.clearOutput = new("ButtonControl"):ButtonControl(nil, {1230, 10, 100, 18}, "Clear", function() + wipeTable(self.scriptOutput) + end) { + shown = function() +@@ -205,23 +205,23 @@ function main:Init() + return #self.scriptOutput > 0 + end + } +- self.controls.clearAutoClearOutput = new("CheckBoxControl", { "TOPLEFT", self.controls.clearOutput, "BOTTOMLEFT" }, { 120, 10, 20, 20 }, "Auto Clear Output:", function(state) ++ self.controls.clearAutoClearOutput = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", self.controls.clearOutput, "BOTTOMLEFT" }, { 120, 10, 20, 20 }, "Auto Clear Output:", function(state) + self.clearAutoClearOutput = state + end, nil, false) +- self.controls.helpText = new("LabelControl", {"TOPLEFT",self.controls.clearOutput,"BOTTOMLEFT"}, {0, 42, 100, 16}, "Press Ctrl+F5 to re-export\ndata from the game") ++ self.controls.helpText = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.clearOutput,"BOTTOMLEFT"}, {0, 42, 100, 16}, "Press Ctrl+F5 to re-export\ndata from the game") + +- self.controls.scriptList = new("ScriptListControl", nil, {270, 35, 140, 400}) { ++ self.controls.scriptList = new("ScriptListControl"):ScriptListControl(nil, {270, 35, 140, 400}) { + shown = function() + return not self.curDatFile + end + } +- self.controls.scriptOutput = new("TextListControl", nil, {420, 10, 800, 600}, nil, self.scriptOutput) { ++ self.controls.scriptOutput = new("TextListControl"):TextListControl(nil, {420, 10, 800, 600}, nil, self.scriptOutput) { + shown = function() + return not self.curDatFile + end + } + +- self.controls.copyScriptOutput = new("ButtonControl",{"TOPRIGHT", self.controls.scriptOutput, "BOTTOMRIGHT"},{0, 4, 80, 20},"Copy",function() ++ self.controls.copyScriptOutput = new("ButtonControl"):ButtonControl({"TOPRIGHT", self.controls.scriptOutput, "BOTTOMRIGHT"},{0, 4, 80, 20},"Copy",function() + local lines = {} + local textList = self.controls.scriptOutput.list or {} -- grab the actual list + for _, entry in ipairs(textList) do diff --git a/src/Export/Minions/Minions.txt.rej b/src/Export/Minions/Minions.txt.rej new file mode 100644 index 0000000000..2183e8552c --- /dev/null +++ b/src/Export/Minions/Minions.txt.rej @@ -0,0 +1,23 @@ +diff a/src/Export/Minions/Minions.txt b/src/Export/Minions/Minions.txt (rejected hunks) +@@ -3,8 +3,10 @@ + -- Minion Data + -- Monster data (c) Grinding Gear Games + -- +-local minions, mod = ... + ++return function(mod, flag) ++ ---@class MinionData ++ local minions = {} + #monster Metadata/Monsters/RaisedZombies/RaisedZombieStandard RaisedZombie + #limit ActiveZombieLimit + #emit +@@ -265,4 +267,6 @@ minions["GuardianRelicAll"] = { + + #monster Metadata/Monsters/RaisedZombies/RestlessDeadPlayerSummoned ShamblingUndead + #limit ShamblingUndeadLimit +-#emit +\ No newline at end of file ++#emit ++ return minions ++end +\ No newline at end of file diff --git a/src/Export/Minions/Spectres.txt.rej b/src/Export/Minions/Spectres.txt.rej new file mode 100644 index 0000000000..926d6d992f --- /dev/null +++ b/src/Export/Minions/Spectres.txt.rej @@ -0,0 +1,22 @@ +diff a/src/Export/Minions/Spectres.txt b/src/Export/Minions/Spectres.txt (rejected hunks) +@@ -3,8 +3,10 @@ + -- Spectre Data + -- Monster data (c) Grinding Gear Games + -- +-local minions, mod, flag = ... + ++return function(mod, flag) ++ ---@class SpectreData ++ local minions = {} + -- Blackguard + #spectre Metadata/Monsters/Axis/AxisCaster + #spectre Metadata/Monsters/Axis/AxisCasterArc +@@ -446,4 +448,6 @@ local minions, mod, flag = ... + #spectre Metadata/Monsters/FaridunLeague/FaridunWarlock/FaridunWarlockMid_ + #spectre Metadata/Monsters/FaridunLeague/FaridunWarlock/FaridunWarlockHigh + -- Undead Vaal Commander +-#spectre Metadata/Monsters/VaalMonsters/VaalOverseer +\ No newline at end of file ++#spectre Metadata/Monsters/VaalMonsters/VaalOverseer ++ return minions ++end diff --git a/src/Export/Scripts/bossData.lua b/src/Export/Scripts/bossData.lua index cf3a4e03dd..3d7e58bd0e 100644 --- a/src/Export/Scripts/bossData.lua +++ b/src/Export/Scripts/bossData.lua @@ -554,13 +554,11 @@ end end -- #skillList - directiveTable.skills.skillList = function(state, args, out) - out:write('},{\n') +directiveTable.skills.skillList = function(state, args, out) out:write(' { val = "None", label = "None" }') for _, skillName in pairs(state.skillList) do out:write(',\n { val = "', skillName, '", label = "', skillName, '" }') end - out:write('\n}') state.boss = nil state.skillList = nil end diff --git a/src/Export/Scripts/minions.lua b/src/Export/Scripts/minions.lua index ce4d82d25e..aa5ed7cbc2 100644 --- a/src/Export/Scripts/minions.lua +++ b/src/Export/Scripts/minions.lua @@ -15,7 +15,7 @@ local function makeSkillDataMod(dataKey, dataValue, ...) return makeSkillMod("SkillData", "LIST", { key = dataKey, value = dataValue }, 0, 0, ...) end dofile("../Data/Global.lua") -local skillStatMap = LoadModule("../Data/SkillStatMap.lua", makeSkillMod, makeFlagMod, makeSkillDataMod) +local skillStatMap = LoadModule("../Data/SkillStatMap")(makeSkillMod, makeFlagMod, makeSkillDataMod) local function tableToString(tbl, pre) pre = pre or "" diff --git a/src/Export/Scripts/miscdata.lua.rej b/src/Export/Scripts/miscdata.lua.rej new file mode 100644 index 0000000000..48f86ab941 --- /dev/null +++ b/src/Export/Scripts/miscdata.lua.rej @@ -0,0 +1,19 @@ +diff a/src/Export/Scripts/miscdata.lua b/src/Export/Scripts/miscdata.lua (rejected hunks) +@@ -2,7 +2,8 @@ + local utils = LoadModule("../Modules/Utils") + local out = io.open("../Data/Misc.lua", "w") + out:write("-- This file is automatically generated, do not edit!\n\n") +-out:write('local data = ...\n') ++out:write('---@class MiscDataExport\n') ++out:write('local data = {}\n') + local evasion = "" + local accuracy = "" + local life = "" +@@ -141,6 +142,7 @@ for row in dat("VillageBalancePerLevelShared"):Rows() do + end + out:write('}\n') + ++out:write('return data\n') + out:close() + + local currencies = {} diff --git a/src/Export/Skills/act_dex.txt.rej b/src/Export/Skills/act_dex.txt.rej new file mode 100644 index 0000000000..a885ae216f --- /dev/null +++ b/src/Export/Skills/act_dex.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Skills/act_dex.txt b/src/Export/Skills/act_dex.txt (rejected hunks) +@@ -3,8 +3,7 @@ + -- Active Dexterity skill gems + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + #skill AlchemistsMark + #flags spell curse mark area duration + statMap = { +@@ -3669,3 +3668,5 @@ local skills, mod, flag, skill = ... + #skill QuickstepHardMode + #flags movement travel + #mods ++ ++end diff --git a/src/Export/Skills/act_int.txt.rej b/src/Export/Skills/act_int.txt.rej new file mode 100644 index 0000000000..7dd1ad1863 --- /dev/null +++ b/src/Export/Skills/act_int.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Skills/act_int.txt b/src/Export/Skills/act_int.txt (rejected hunks) +@@ -3,8 +3,7 @@ + -- Active Intelligence skill gems + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + #skill Arc + #flags spell chaining + statMap = { +@@ -4695,3 +4694,5 @@ local skills, mod, flag, skill = ... + }, + #baseMod skill("radius", 40) + #mods ++ ++end diff --git a/src/Export/Skills/act_str.txt.rej b/src/Export/Skills/act_str.txt.rej new file mode 100644 index 0000000000..032e592679 --- /dev/null +++ b/src/Export/Skills/act_str.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Skills/act_str.txt b/src/Export/Skills/act_str.txt (rejected hunks) +@@ -3,8 +3,7 @@ + -- Active Strength skill gems + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + #skill Absolution + #flags spell minion duration area + minionList = { +@@ -2495,3 +2494,5 @@ local skills, mod, flag, skill = ... + #baseMod mod("AuraEffect", "MORE", -100, 0, 0, { type = "Condition", var = "BannerPlanted", neg = true }) + #baseMod flag("Condition:AffectedByPlacedBanner", { type = "Condition", var = "BannerPlanted" }, { type = "GlobalEffect", effectType = "Buff" }) + #mods ++ ++end diff --git a/src/Export/Skills/glove.txt.rej b/src/Export/Skills/glove.txt.rej new file mode 100644 index 0000000000..a95ffe2d2a --- /dev/null +++ b/src/Export/Skills/glove.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Skills/glove.txt b/src/Export/Skills/glove.txt (rejected hunks) +@@ -3,8 +3,7 @@ + -- Glove enchantment skills + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + #skill EnchantmentOfBladesOnHit + #flags spell projectile + fromItem = true, +@@ -340,3 +339,5 @@ local skills, mod, flag, skill = ... + #flags spell projectile area + fromItem = true, + #mods ++ ++end diff --git a/src/Export/Skills/minion.txt.rej b/src/Export/Skills/minion.txt.rej new file mode 100644 index 0000000000..644e2d13c9 --- /dev/null +++ b/src/Export/Skills/minion.txt.rej @@ -0,0 +1,20 @@ +diff a/src/Export/Skills/minion.txt b/src/Export/Skills/minion.txt (rejected hunks) +@@ -3,8 +3,7 @@ + -- Minion active skills + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + #skill ChaosElementalCascadeSummoned Cascade + #flags spell area + #mods +@@ -486,4 +485,6 @@ skills["GuardianSentinelFireAura"] = { + + #skill MeleePartialChaos + #flags attack melee +-#mods +\ No newline at end of file ++#mods ++ ++end diff --git a/src/Export/Skills/other.txt.rej b/src/Export/Skills/other.txt.rej new file mode 100644 index 0000000000..528894fef2 --- /dev/null +++ b/src/Export/Skills/other.txt.rej @@ -0,0 +1,17 @@ +diff a/src/Export/Skills/other.txt b/src/Export/Skills/other.txt (rejected hunks) +@@ -3,8 +3,7 @@ + -- Other active skills + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + #skill RepeatingShockwave + #flags spell area + fromItem = true, +@@ -1670,3 +1669,5 @@ skills["EnemyExplode"] = { + [1] = { damageEffectiveness = 1, baseMultiplier = 1, levelRequirement = 1, } + } + } ++ ++end diff --git a/src/Export/Skills/spectre.txt.rej b/src/Export/Skills/spectre.txt.rej new file mode 100644 index 0000000000..05435771f8 --- /dev/null +++ b/src/Export/Skills/spectre.txt.rej @@ -0,0 +1,20 @@ +diff a/src/Export/Skills/spectre.txt b/src/Export/Skills/spectre.txt (rejected hunks) +@@ -3,8 +3,7 @@ + -- Spectre active skills + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + #skill AxisCasterGlacialCascade + #flags spell area + #baseMod skill("radius", 12) +@@ -2299,4 +2298,6 @@ skills["LegionKaruiMeleeCombo2"] = { + + #skill VaalOverseerHeavyStrike Heavy Strike + #flags attack melee +-#mods +\ No newline at end of file ++#mods ++ ++end diff --git a/src/Export/Skills/sup_dex.txt.rej b/src/Export/Skills/sup_dex.txt.rej new file mode 100644 index 0000000000..40757d22bc --- /dev/null +++ b/src/Export/Skills/sup_dex.txt.rej @@ -0,0 +1,20 @@ +diff a/src/Export/Skills/sup_dex.txt b/src/Export/Skills/sup_dex.txt (rejected hunks) +@@ -3,8 +3,7 @@ + -- Dexterity support gems + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + #skill SupportAddedColdDamage + #mods + +@@ -689,4 +688,6 @@ local skills, mod, flag, skill = ... + #mods + + #skill SupportWitheringTouch +-#mods +\ No newline at end of file ++#mods ++ ++end diff --git a/src/Export/Skills/sup_int.txt.rej b/src/Export/Skills/sup_int.txt.rej new file mode 100644 index 0000000000..e7480b0edb --- /dev/null +++ b/src/Export/Skills/sup_int.txt.rej @@ -0,0 +1,20 @@ +diff a/src/Export/Skills/sup_int.txt b/src/Export/Skills/sup_int.txt (rejected hunks) +@@ -3,8 +3,7 @@ + -- Intelligence support gems + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + #skill SupportAddedChaosDamage + #mods + +@@ -1027,4 +1026,6 @@ local skills, mod, flag, skill = ... + mod("Speed", "MORE", nil, ModFlag.Cast), + }, + }, +-#mods +\ No newline at end of file ++#mods ++ ++end diff --git a/src/Export/Skills/sup_str.txt.rej b/src/Export/Skills/sup_str.txt.rej new file mode 100644 index 0000000000..8f6ad188a9 --- /dev/null +++ b/src/Export/Skills/sup_str.txt.rej @@ -0,0 +1,20 @@ +diff a/src/Export/Skills/sup_str.txt b/src/Export/Skills/sup_str.txt (rejected hunks) +@@ -3,8 +3,7 @@ + -- Strength support gems + -- Skill data (c) Grinding Gear Games + -- +-local skills, mod, flag, skill = ... +- ++return function(skills, mod, flag, skill) + #skill SupportAddedFireDamage + #mods + +@@ -826,4 +825,6 @@ local skills, mod, flag, skill = ... + mod("CooldownRecovery", "MORE", nil), + }, + }, +-#mods +\ No newline at end of file ++#mods ++ ++end diff --git a/src/GameVersions.lua.rej b/src/GameVersions.lua.rej new file mode 100644 index 0000000000..cbb97b934f --- /dev/null +++ b/src/GameVersions.lua.rej @@ -0,0 +1,6 @@ +diff a/src/GameVersions.lua b/src/GameVersions.lua (rejected hunks) +@@ -1,3 +1,4 @@ ++---@diagnostic disable: lowercase-global + -- Game versions + ---Default target version for unknown builds and builds created before 3.0.0. + legacyTargetVersion = "2_6" diff --git a/src/HeadlessWrapper.lua.rej b/src/HeadlessWrapper.lua.rej new file mode 100644 index 0000000000..0c623c25ae --- /dev/null +++ b/src/HeadlessWrapper.lua.rej @@ -0,0 +1,232 @@ +diff a/src/HeadlessWrapper.lua b/src/HeadlessWrapper.lua (rejected hunks) +@@ -1,178 +1,26 @@ + #@ ++---@diagnostic disable: lowercase-global + -- This wrapper allows the program to run headless on any OS (in theory) + -- It can be run using a standard lua interpreter, although LuaJIT is preferable + ++-- define global SimpleGraphic API functions. some of these have dummy function ++-- bodies intended for headless use. ++dofile("_SimpleGraphic.def.lua") + +- +--- Callbacks +-local callbackTable = { } +-local mainObject +-function runCallback(name, ...) +- if callbackTable[name] then +- return callbackTable[name](...) +- elseif mainObject and mainObject[name] then +- return mainObject[name](mainObject, ...) +- end +-end +-function SetCallback(name, func) +- callbackTable[name] = func +-end +-function GetCallback(name) +- return callbackTable[name] +-end +-function SetMainObject(obj) +- mainObject = obj +-end +- +--- Image Handles +-local imageHandleClass = { } +-imageHandleClass.__index = imageHandleClass +-function NewImageHandle() +- return setmetatable({ }, imageHandleClass) +-end +-function imageHandleClass:Load(fileName, ...) +- self.valid = true +-end +-function imageHandleClass:Unload() +- self.valid = false +-end +-function imageHandleClass:IsValid() +- return self.valid +-end +-function imageHandleClass:SetLoadingPriority(pri) end +-function imageHandleClass:ImageSize() +- return 1, 1 +-end +- +--- Rendering +-function RenderInit(flag, ...) end +-function GetScreenSize() +- return 1920, 1080 +-end +-function GetScreenScale() +- return 1 +-end + function GetVirtualScreenSize() +- return GetScreenSize() +-end +-function GetDPIScaleOverridePercent() +- return 1 +-end +-function SetDPIScaleOverridePercent(scale) end +-function SetClearColor(r, g, b, a) end +-function SetDrawLayer(layer, subLayer) end +-function SetViewport(x, y, width, height) end +-function SetDrawColor(r, g, b, a) end +-function DrawImage(imgHandle, left, top, width, height, tcLeft, tcTop, tcRight, tcBottom) end +-function DrawImageQuad(imageHandle, x1, y1, x2, y2, x3, y3, x4, y4, s1, t1, s2, t2, s3, t3, s4, t4) end +-function DrawString(left, top, align, height, font, text) end +-function DrawStringWidth(height, font, text) +- return 1 +-end +-function DrawStringCursorIndex(height, font, text, cursorX, cursorY) +- return 0 +-end +-function StripEscapes(text) +- return text:gsub("%^%d",""):gsub("%^x%x%x%x%x%x%x","") +-end +-function GetAsyncCount() +- return 0 ++ return 1920, 1080 + end + +--- Search Handles +-function NewFileSearch() end ++-- Callbacks ++__callbackTable__ = { } + +--- General Functions +-function SetWindowTitle(title) end +-function GetCursorPos() +- return 0, 0 +-end +-function SetCursorPos(x, y) end +-function ShowCursor(doShow) end +-function IsKeyDown(keyName) end +-function Copy(text) end +-function Paste() end +-function Deflate(data) +- -- TODO: Might need this +- return "" +-end +-function Inflate(data) +- -- TODO: And this +- return "" +-end +-function GetTime() +- return 0 +-end +-function GetScriptPath() +- return "" +-end +-function GetRuntimePath() +- return "" +-end +-function GetUserPath() +- return "" +-end +-function MakeDir(path) end +-function RemoveDir(path) end +-function SetWorkDir(path) end +-function GetWorkDir() +- return "" +-end +-function LaunchSubScript(scriptText, funcList, subList, ...) end +-function AbortSubScript(ssID) end +-function IsSubScriptRunning(ssID) end +-function LoadModule(fileName, ...) +- if not fileName:match("%.lua") then +- fileName = fileName .. ".lua" +- end +- local func, err = loadfile(fileName) +- if func then +- return func(...) +- else +- error("LoadModule() error loading '"..fileName.."': "..err) +- end +-end +-function PLoadModule(fileName, ...) +- if not fileName:match("%.lua") then +- fileName = fileName .. ".lua" +- end +- local func, err = loadfile(fileName) +- if func then +- return PCall(func, ...) +- else +- error("PLoadModule() error loading '"..fileName.."': "..err) +- end +-end +-function PCall(func, ...) +- local ret = { pcall(func, ...) } +- if ret[1] then +- table.remove(ret, 1) +- return nil, unpack(ret) +- else +- return ret[2] ++function runCallback(name, ...) ++ if __callbackTable__[name] then ++ return __callbackTable__[name](...) ++ elseif __mainObject__ and __mainObject__[name] then ++ return __mainObject__[name](__mainObject__, ...) + end + end +-function ConPrintf(fmt, ...) +- -- Optional +- print(string.format(fmt, ...)) +-end +-function ConPrintTable(tbl, noRecurse) end +-function ConExecute(cmd) end +-function ConClear() end +-function SpawnProcess(cmdName, args) end +-function OpenURL(url) end +-function SetProfiling(isEnabled) end +-function Restart() end +-function Exit() end +-function TakeScreenshot() end +- +----@return string? provider +----@return string? version +----@return number? status +-function GetCloudProvider(fullPath) +- return nil, nil, nil +-end +- + + local l_require = require + function require(name) +@@ -189,32 +37,32 @@ dofile("Launch.lua") + -- Prevents loading of ModCache + -- Allows running mod parsing related tests without pushing ModCache + -- The CI env var will be true when run from github workflows but should be false for other tools using the headless wrapper +-mainObject.continuousIntegrationMode = os.getenv("CI") ++__mainObject__.continuousIntegrationMode = os.getenv("CI") + + runCallback("OnInit") + runCallback("OnFrame") -- Need at least one frame for everything to initialise + +-if mainObject.promptMsg then ++if __mainObject__.promptMsg then + -- Something went wrong during startup +- print(mainObject.promptMsg) ++ print(__mainObject__.promptMsg) + io.read("*l") + return + end + + -- The build module; once a build is loaded, you can find all the good stuff in here +-build = mainObject.main.modes["BUILD"] ++build = __mainObject__.main.modes["BUILD"] + + -- Here's some helpful helper functions to help you get started + function newBuild() +- mainObject.main:SetMode("BUILD", false, "Help, I'm stuck in Path of Building!") ++ __mainObject__.main:SetMode("BUILD", false, "Help, I'm stuck in Path of Building!") + runCallback("OnFrame") + end + function loadBuildFromXML(xmlText, name) +- mainObject.main:SetMode("BUILD", false, name or "", xmlText) ++ __mainObject__.main:SetMode("BUILD", false, name or "", xmlText) + runCallback("OnFrame") + end + function loadBuildFromJSON(characterJSON) +- mainObject.main:SetMode("BUILD", false, "") ++ __mainObject__.main:SetMode("BUILD", false, "") + runCallback("OnFrame") + -- characterJSON could, for example, be the response from the PoE API: + -- https://www.pathofexile.com/developer/docs/reference#characters-get diff --git a/src/Launch.lua b/src/Launch.lua index a0f9d64761..7a651f90f9 100644 --- a/src/Launch.lua +++ b/src/Launch.lua @@ -12,6 +12,7 @@ SetWindowTitle(APP_NAME) ConExecute("set vid_mode 8") ConExecute("set vid_resizable 3") +---@diagnostic disable-next-line: lowercase-global launch = { } SetMainObject(launch) jit.opt.start('maxtrace=4000','maxmcode=8192') @@ -317,16 +318,15 @@ function launch:DownloadPage(url, callback, params) } end end - function launch:ApplyUpdate(mode) if mode == "basic" then -- Need to revert to the basic environment to fully apply the update - LoadModule("UpdateApply", "Update/opFile.txt") + LoadModule("UpdateApply")("Update/opFile.txt") SpawnProcess(GetRuntimePath()..'/Update', 'UpdateApply.lua Update/opFileRuntime.txt') Exit() elseif mode == "normal" then -- Update can be applied while normal environment is running - LoadModule("UpdateApply", "Update/opFile.txt") + LoadModule("UpdateApply")("Update/opFile.txt") Restart() self.doRestart = "Updating..." end diff --git a/src/Modules/Build.lua b/src/Modules/Build.lua index e8b9a48140..dcbc5ec525 100644 --- a/src/Modules/Build.lua +++ b/src/Modules/Build.lua @@ -587,7 +587,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin self.spec:SetWindowTitleWithBuildClass() --[[ - local testTooltip = new("Tooltip") + local testTooltip = new("Tooltip"):Tooltip() for _, item in pairs(main.uniqueDB.list) do ConPrintf("%s", item.name) self.itemsTab:AddItemTooltip(testTooltip, item) @@ -1419,24 +1419,24 @@ end function buildMode:OpenConversionPopup() local controls = { } local currentVersion = treeVersions[latestTreeVersion].display - controls.note = new("LabelControl", nil, {0, 20, 0, 16}, colorCodes.TIP..[[ + controls.note = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, colorCodes.TIP..[[ Info:^7 You are trying to load a build created for a version of Path of Exile that is not supported by us. You will have to convert it to the current game version to load it. To use a build newer than the current supported game version, you may have to update. To use a build older than the current supported game version, we recommend loading it in an older version of Path of Building Community instead. ]]) - controls.label = new("LabelControl", nil, {0, 110, 0, 16}, colorCodes.WARNING..[[ + controls.label = new("LabelControl"):LabelControl(nil, {0, 110, 0, 16}, colorCodes.WARNING..[[ Warning:^7 Converting a build to a different game version may have side effects. For example, if the passive tree has changed, then some passives may be deallocated. You should create a backup copy of the build before proceeding. ]]) - controls.convert = new("ButtonControl", nil, {-40, 170, 120, 20}, "Convert to ".. currentVersion, function() + controls.convert = new("ButtonControl"):ButtonControl(nil, {-40, 170, 120, 20}, "Convert to ".. currentVersion, function() main:ClosePopup() self:Shutdown() self:Init(self.dbFileName, self.buildName, nil, true) end) - controls.cancel = new("ButtonControl", nil, {60, 170, 70, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {60, 170, 70, 20}, "Cancel", function() main:ClosePopup() self:CloseBuild() end) @@ -1450,13 +1450,13 @@ function buildMode:OpenSavePopup(mode) ["UPDATE"] = "before updating?", } local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7This build has unsaved changes.\nDo you want to save them "..modeDesc[mode]) - controls.save = new("ButtonControl", nil, {-90, 70, 80, 20}, "Save", function() + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7This build has unsaved changes.\nDo you want to save them "..modeDesc[mode]) + controls.save = new("ButtonControl"):ButtonControl(nil, {-90, 70, 80, 20}, "Save", function() main:ClosePopup() self.actionOnSave = mode self:SaveDBFile() end) - controls.noSave = new("ButtonControl", nil, {0, 70, 80, 20}, "Don't Save", function() + controls.noSave = new("ButtonControl"):ButtonControl(nil, {0, 70, 80, 20}, "Don't Save", function() main:ClosePopup() if mode == "LIST" then self:CloseBuild() @@ -1466,7 +1466,7 @@ function buildMode:OpenSavePopup(mode) launch:ApplyUpdate(launch.updateAvailable) end end) - controls.close = new("ButtonControl", nil, {90, 70, 80, 20}, "Cancel", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {90, 70, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(300, 100, "Save Changes", controls) @@ -1896,7 +1896,7 @@ function buildMode:OpenSimilarPopup() local buildProviders = { { name = "PoB Archives", - impl = new("PoBArchivesProvider", "similar") + impl = new("PoBArchivesProvider"):PoBArchivesProvider("similar") } } local width = 600 @@ -1904,7 +1904,7 @@ function buildMode:OpenSimilarPopup() return main.screenH * 0.8 end local padding = 50 - controls.similarBuildList = new("ExtBuildListControl", nil, {0, padding, width, height() - 2 * padding}, buildProviders) + controls.similarBuildList = new("ExtBuildListControl"):ExtBuildListControl(nil, {0, padding, width, height() - 2 * padding}, buildProviders) controls.similarBuildList.shown = true controls.similarBuildList.height = function() return height() - 2 * padding @@ -1917,7 +1917,7 @@ function buildMode:OpenSimilarPopup() -- controls.similarBuildList.shown = not controls.similarBuildList:IsShown() - controls.close = new("ButtonControl", nil, {0, height() - (padding + 20) / 2, 80, 20}, "Close", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {0, height() - (padding + 20) / 2, 80, 20}, "Close", function() main:ClosePopup() end) -- used in PopupDialog to dynamically size the popup diff --git a/src/Modules/Build.lua.rej b/src/Modules/Build.lua.rej new file mode 100644 index 0000000000..5be88b4e18 --- /dev/null +++ b/src/Modules/Build.lua.rej @@ -0,0 +1,402 @@ +diff a/src/Modules/Build.lua b/src/Modules/Build.lua (rejected hunks) +@@ -15,7 +15,10 @@ local m_floor = math.floor + local m_abs = math.abs + local s_format = string.format + +-local buildMode = new("ControlHost") ++---@class Build: ControlHost ++---@field spec PassiveSpec added by TreeTab ++---@field powerBuilderCallback fun() ++local buildMode = new("ControlHost"):ControlHost() + + local function InsertIfNew(t, val) + if (not t) then return end +@@ -112,24 +115,24 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin + self.secondaryAscendDropLegacySelection = nil + self.secondaryAscendDropEntryCount = nil + +- local miscTooltip = new("Tooltip") ++ local miscTooltip = new("Tooltip"):Tooltip() + + -- Controls: top bar, left side +- self.anchorTopBarLeft = new("Control", nil, {4, 4, 0, 20}) +- self.controls.back = new("ButtonControl", {"LEFT",self.anchorTopBarLeft,"RIGHT"}, {0, 0, 60, 20}, "<< Back", function() ++ self.anchorTopBarLeft = new("Control"):Control(nil, {4, 4, 0, 20}) ++ self.controls.back = new("ButtonControl"):ButtonControl({"LEFT",self.anchorTopBarLeft,"RIGHT"}, {0, 0, 60, 20}, "<< Back", function() + if self.unsaved then + self:OpenSavePopup("LIST") + else + self:CloseBuild() + end + end) +- self.controls.save = new("ButtonControl", {"LEFT",self.controls.back,"RIGHT"}, {8, 0, 50, 20}, "Save", function() ++ self.controls.save = new("ButtonControl"):ButtonControl({"LEFT",self.controls.back,"RIGHT"}, {8, 0, 50, 20}, "Save", function() + self:SaveDBFile() + end) + self.controls.save.enabled = function() + return not self.dbFileName or self.unsaved + end +- self.controls.saveAs = new("ButtonControl", {"LEFT",self.controls.save,"RIGHT"}, {8, 0, 70, 20}, "Save As", function() ++ self.controls.saveAs = new("ButtonControl"):ButtonControl({"LEFT",self.controls.save,"RIGHT"}, {8, 0, 70, 20}, "Save As", function() + self:OpenSaveAsPopup() + end) + self.controls.saveAs.enabled = function() +@@ -140,7 +143,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin + local function buildNameConditional() + return self.anchorTopBarRight:GetPos() < 800 + end +- self.controls.buildName = new("Control", {"LEFT",self.controls.saveAs,"RIGHT"}, {4, 36, 0, 20}) ++ self.controls.buildName = new("Control"):Control({"LEFT",self.controls.saveAs,"RIGHT"}, {4, 36, 0, 20}) + self.controls.buildName.width = function(control) + local limit = buildNameConditional() and 203 or + (self.anchorTopBarRight:GetPos() - 98 - 62 +@@ -182,12 +185,12 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin + end + + -- Controls: top bar, right side +- self.anchorTopBarRight = new("Control", nil, {function() return main.screenW / 2 + 6 end, 4, 0, 20}) ++ self.anchorTopBarRight = new("Control"):Control(nil, {function() return main.screenW / 2 + 6 end, 4, 0, 20}) + + local function getPointDisplayX() -- I had it hardcoded to -323 before switching to the control sizing + return - (23 + self.controls.pointDisplay:GetSize() + self.controls.levelScalingButton:GetSize() + self.controls.characterLevel:GetSize()) + end +- self.controls.pointDisplay = new("Control", {"LEFT",self.anchorTopBarRight,"RIGHT"}, {function() return getPointDisplayX() end, 0, 0, 20}) ++ self.controls.pointDisplay = new("Control"):Control({"LEFT",self.anchorTopBarRight,"RIGHT"}, {function() return getPointDisplayX() end, 0, 0, 20}) + self.controls.pointDisplay.width = function(control) + return DrawStringWidth(16, "FIXED", control.str) + 8 + end +@@ -208,14 +211,14 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin + SetDrawLayer(nil, 0) + end + end +- self.controls.levelScalingButton = new("ButtonControl", {"LEFT",self.controls.pointDisplay,"RIGHT"}, {7, 0, 50, 20}, self.characterLevelAutoMode and "Auto" or "Manual", function() ++ self.controls.levelScalingButton = new("ButtonControl"):ButtonControl({"LEFT",self.controls.pointDisplay,"RIGHT"}, {7, 0, 50, 20}, self.characterLevelAutoMode and "Auto" or "Manual", function() + self.characterLevelAutoMode = not self.characterLevelAutoMode + self.controls.levelScalingButton.label = self.characterLevelAutoMode and "Auto" or "Manual" + self.configTab:BuildModList() + self.modFlag = true + self.buildFlag = true + end) +- self.controls.characterLevel = new("EditControl", {"LEFT",self.controls.levelScalingButton,"RIGHT"}, {5, 0, 106, 20}, "", "Level", "%D", 3, function(buf) ++ self.controls.characterLevel = new("EditControl"):EditControl({"LEFT",self.controls.levelScalingButton,"RIGHT"}, {5, 0, 106, 20}, "", "Level", "%D", 3, function(buf) + self.characterLevel = m_min(m_max(tonumber(buf) or 1, 1), 100) + self.configTab:BuildModList() + self.modFlag = true +@@ -252,7 +255,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin + end + end + end +- self.controls.classDrop = new("DropDownControl", {"LEFT",self.controls.characterLevel,"RIGHT"}, {10, 0, 85, 20}, nil, function(index, value) ++ self.controls.classDrop = new("DropDownControl"):DropDownControl({"LEFT",self.controls.characterLevel,"RIGHT"}, {10, 0, 85, 20}, nil, function(index, value) + if value.classId ~= self.spec.curClassId then + if self.spec:CountAllocNodes() == 0 or self.spec:IsClassConnected(value.classId) then + self.spec:SelectClass(value.classId) +@@ -276,13 +279,13 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin + end + end + end) +- self.controls.ascendDrop = new("DropDownControl", {"LEFT",self.controls.classDrop,"RIGHT"}, {4, 0, 120, 20}, nil, function(index, value) ++ self.controls.ascendDrop = new("DropDownControl"):DropDownControl({"LEFT",self.controls.classDrop,"RIGHT"}, {4, 0, 120, 20}, nil, function(index, value) + self.spec:SelectAscendClass(value.ascendClassId) + self.spec:AddUndoState() + self.spec:SetWindowTitleWithBuildClass() + self.buildFlag = true + end) +- self.controls.secondaryAscendDrop = new("DropDownControl", {"LEFT",self.controls.ascendDrop,"RIGHT"}, {4, 0, 160, 20}, { ++ self.controls.secondaryAscendDrop = new("DropDownControl"):DropDownControl({"LEFT",self.controls.ascendDrop,"RIGHT"}, {4, 0, 160, 20}, { + { label = "None", ascendClassId = 0 }, + }, function(index, value) + if not value or not self.spec then +@@ -298,7 +301,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin + local initialSecondarySelection = (self.spec and self.spec.curSecondaryAscendClassId) or 0 + self.controls.secondaryAscendDrop:SelByValue(initialSecondarySelection, "ascendClassId") + +- self.controls.buildLoadouts = new("DropDownControl", {"LEFT",self.controls.secondaryAscendDrop,"RIGHT"}, {4, 0, 190, 20}, {}, function(index, value) ++ self.controls.buildLoadouts = new("DropDownControl"):DropDownControl({"LEFT",self.controls.secondaryAscendDrop,"RIGHT"}, {4, 0, 190, 20}, {}, function(index, value) + if value == "^7^7Loadouts:" or value == "^7^7-----" then + self.controls.buildLoadouts:SetSel(1) + return +@@ -315,14 +318,14 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin + end + if value == "^7^7New Loadout" then + local controls = { } +- controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter name for this loadout:") +- controls.edit = new("EditControl", nil, {0, 40, 350, 20}, "New Loadout", nil, nil, 100, function(buf) ++ controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter name for this loadout:") ++ controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, "New Loadout", nil, nil, 100, function(buf) + controls.save.enabled = buf:match("%S") + end) +- controls.save = new("ButtonControl", nil, {-45, 70, 80, 20}, "Save", function() ++ controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Save", function() + local loadout = controls.edit.buf + +- local newSpec = new("PassiveSpec", self, latestTreeVersion) ++ local newSpec = new("PassiveSpec"):PassiveSpec(self, latestTreeVersion) + newSpec.title = loadout + t_insert(self.treeTab.specList, newSpec) + +@@ -343,7 +346,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin + main:ClosePopup() + end) + controls.save.enabled = false +- controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() ++ controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() + main:ClosePopup() + end) + main:OpenPopup(370, 100, "Set Name", controls, "save", "edit", "cancel") +@@ -424,54 +427,57 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin + end + + -- List of display stats +- self.displayStats, self.minionDisplayStats, self.extraSaveStats = LoadModule("Modules/BuildDisplayStats") ++ local displayStatsModule = LoadModule("Modules/BuildDisplayStats") ++ self.displayStats = displayStatsModule.displayStats ++ self.minionDisplayStats = displayStatsModule.minionDisplayStats ++ self.extraSaveStats = displayStatsModule.extraSaveStats + + -- Controls: Side bar +- self.anchorSideBar = new("Control", nil, {4, 60, 0, 0}) ++ self.anchorSideBar = new("Control"):Control(nil, {4, 60, 0, 0}) + self.anchorSideBar.y = function() + return buildNameConditional() and 60 or 36 + end + +- self.controls.modeImport = new("ButtonControl", {"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 0, 134, 20}, "Import/Export Build", function() ++ self.controls.modeImport = new("ButtonControl"):ButtonControl({"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 0, 134, 20}, "Import/Export Build", function() + self.viewMode = "IMPORT" + self.importTab:TryFetchCharacterList() + end) + self.controls.modeImport.locked = function() return self.viewMode == "IMPORT" end +- self.controls.modeNotes = new("ButtonControl", {"LEFT",self.controls.modeImport,"RIGHT"}, {4, 0, 58, 20}, "Notes", function() ++ self.controls.modeNotes = new("ButtonControl"):ButtonControl({"LEFT",self.controls.modeImport,"RIGHT"}, {4, 0, 58, 20}, "Notes", function() + self.viewMode = "NOTES" + end) + self.controls.modeNotes.locked = function() return self.viewMode == "NOTES" end +- self.controls.modeConfig = new("ButtonControl", {"TOPRIGHT",self.anchorSideBar,"TOPLEFT"}, {300, 0, 100, 20}, "Configuration", function() ++ self.controls.modeConfig = new("ButtonControl"):ButtonControl({"TOPRIGHT",self.anchorSideBar,"TOPLEFT"}, {300, 0, 100, 20}, "Configuration", function() + self.viewMode = "CONFIG" + end) + self.controls.modeConfig.locked = function() return self.viewMode == "CONFIG" end +- self.controls.modeTree = new("ButtonControl", {"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 26, 72, 20}, "Tree", function() ++ self.controls.modeTree = new("ButtonControl"):ButtonControl({"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 26, 72, 20}, "Tree", function() + self.viewMode = "TREE" + end) + self.controls.modeTree.locked = function() return self.viewMode == "TREE" end +- self.controls.modeSkills = new("ButtonControl", {"LEFT",self.controls.modeTree,"RIGHT"}, {4, 0, 72, 20}, "Skills", function() ++ self.controls.modeSkills = new("ButtonControl"):ButtonControl({"LEFT",self.controls.modeTree,"RIGHT"}, {4, 0, 72, 20}, "Skills", function() + self.viewMode = "SKILLS" + end) + self.controls.modeSkills.locked = function() return self.viewMode == "SKILLS" end +- self.controls.modeItems = new("ButtonControl", {"LEFT",self.controls.modeSkills,"RIGHT"}, {4, 0, 72, 20}, "Items", function() ++ self.controls.modeItems = new("ButtonControl"):ButtonControl({"LEFT",self.controls.modeSkills,"RIGHT"}, {4, 0, 72, 20}, "Items", function() + self.viewMode = "ITEMS" + end) + self.controls.modeItems.locked = function() return self.viewMode == "ITEMS" end +- self.controls.modeCalcs = new("ButtonControl", {"LEFT",self.controls.modeItems,"RIGHT"}, {4, 0, 72, 20}, "Calcs", function() ++ self.controls.modeCalcs = new("ButtonControl"):ButtonControl({"LEFT",self.controls.modeItems,"RIGHT"}, {4, 0, 72, 20}, "Calcs", function() + self.viewMode = "CALCS" + end) + self.controls.modeCalcs.locked = function() return self.viewMode == "CALCS" end +- self.controls.modeParty = new("ButtonControl", {"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 52, 72, 20}, "Party", function() ++ self.controls.modeParty = new("ButtonControl"):ButtonControl({"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 52, 72, 20}, "Party", function() + self.viewMode = "PARTY" + end) + self.controls.modeParty.locked = function() return self.viewMode == "PARTY" end +- self.controls.modeCompare = new("ButtonControl", {"LEFT",self.controls.modeParty,"RIGHT"}, {4, 0, 72, 20}, "Compare", function() ++ self.controls.modeCompare = new("ButtonControl"):ButtonControl({"LEFT",self.controls.modeParty,"RIGHT"}, {4, 0, 72, 20}, "Compare", function() + self.viewMode = "COMPARE" + end) + self.controls.modeCompare.locked = function() return self.viewMode == "COMPARE" end + -- Skills +- self.controls.mainSkillLabel = new("LabelControl", {"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 80, 300, 16}, "^7Main Skill:") +- self.controls.mainSocketGroup = new("DropDownControl", {"TOPLEFT",self.controls.mainSkillLabel,"BOTTOMLEFT"}, {0, 2, 300, 18}, nil, function(index, value) ++ self.controls.mainSkillLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 80, 300, 16}, "^7Main Skill:") ++ self.controls.mainSocketGroup = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.mainSkillLabel,"BOTTOMLEFT"}, {0, 2, 300, 18}, nil, function(index, value) + self.mainSocketGroup = index + self.modFlag = true + self.buildFlag = true +@@ -483,44 +489,44 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin + self.skillsTab:AddSocketGroupTooltip(tooltip, socketGroup) + end + end +- self.controls.mainSkill = new("DropDownControl", {"TOPLEFT",self.controls.mainSocketGroup,"BOTTOMLEFT"}, {0, 2, 300, 18}, nil, function(index, value) ++ self.controls.mainSkill = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.mainSocketGroup,"BOTTOMLEFT"}, {0, 2, 300, 18}, nil, function(index, value) + local mainSocketGroup = self.skillsTab.socketGroupList[self.mainSocketGroup] + mainSocketGroup.mainActiveSkill = index + self.modFlag = true + self.buildFlag = true + end) +- self.controls.mainSkillPart = new("DropDownControl", {"TOPLEFT",self.controls.mainSkill,"BOTTOMLEFT",true}, {0, 2, 300, 18}, nil, function(index, value) ++ self.controls.mainSkillPart = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.mainSkill,"BOTTOMLEFT",true}, {0, 2, 300, 18}, nil, function(index, value) + local mainSocketGroup = self.skillsTab.socketGroupList[self.mainSocketGroup] + local srcInstance = mainSocketGroup.displaySkillList[mainSocketGroup.mainActiveSkill].activeEffect.srcInstance + srcInstance.skillPart = index + self.modFlag = true + self.buildFlag = true + end) +- self.controls.mainSkillStageCountLabel = new("LabelControl", {"TOPLEFT",self.controls.mainSkillPart,"BOTTOMLEFT",true}, {0, 3, 0, 16}, "^7Stages:") { ++ self.controls.mainSkillStageCountLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.mainSkillPart,"BOTTOMLEFT",true}, {0, 3, 0, 16}, "^7Stages:") { + shown = function() + return self.controls.mainSkillStageCount:IsShown() + end, + } +- self.controls.mainSkillStageCount = new("EditControl", {"LEFT",self.controls.mainSkillStageCountLabel,"RIGHT",true}, {2, 0, 60, 18}, nil, nil, "%D", nil, function(buf) ++ self.controls.mainSkillStageCount = new("EditControl"):EditControl({"LEFT",self.controls.mainSkillStageCountLabel,"RIGHT",true}, {2, 0, 60, 18}, nil, nil, "%D", nil, function(buf) + local mainSocketGroup = self.skillsTab.socketGroupList[self.mainSocketGroup] + local srcInstance = mainSocketGroup.displaySkillList[mainSocketGroup.mainActiveSkill].activeEffect.srcInstance + srcInstance.skillStageCount = tonumber(buf) + self.modFlag = true + self.buildFlag = true + end) +- self.controls.mainSkillMineCountLabel = new("LabelControl", {"TOPLEFT",self.controls.mainSkillStageCountLabel,"BOTTOMLEFT",true}, {0, 3, 0, 16}, "^7Active Mines:") { ++ self.controls.mainSkillMineCountLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.mainSkillStageCountLabel,"BOTTOMLEFT",true}, {0, 3, 0, 16}, "^7Active Mines:") { + shown = function() + return self.controls.mainSkillMineCount:IsShown() + end, + } +- self.controls.mainSkillMineCount = new("EditControl", {"LEFT",self.controls.mainSkillMineCountLabel,"RIGHT",true}, {2, 0, 60, 18}, nil, nil, "%D", nil, function(buf) ++ self.controls.mainSkillMineCount = new("EditControl"):EditControl({"LEFT",self.controls.mainSkillMineCountLabel,"RIGHT",true}, {2, 0, 60, 18}, nil, nil, "%D", nil, function(buf) + local mainSocketGroup = self.skillsTab.socketGroupList[self.mainSocketGroup] + local srcInstance = mainSocketGroup.displaySkillList[mainSocketGroup.mainActiveSkill].activeEffect.srcInstance + srcInstance.skillMineCount = tonumber(buf) + self.modFlag = true + self.buildFlag = true + end) +- self.controls.mainSkillMinion = new("DropDownControl", {"TOPLEFT",self.controls.mainSkillMineCountLabel,"BOTTOMLEFT",true}, {0, 3, 178, 18}, nil, function(index, value) ++ self.controls.mainSkillMinion = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.mainSkillMineCountLabel,"BOTTOMLEFT",true}, {0, 3, 178, 18}, nil, function(index, value) + local mainSocketGroup = self.skillsTab.socketGroupList[self.mainSocketGroup] + local srcInstance = mainSocketGroup.displaySkillList[mainSocketGroup.mainActiveSkill].activeEffect.srcInstance + if value.itemSetId then +@@ -549,24 +555,24 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin + tooltip:AddLine(14, colorCodes.TIP.."Tip: You can drag items from the Items tab onto this dropdown to equip them onto the minion.") + end + end +- self.controls.mainSkillMinionLibrary = new("ButtonControl", {"LEFT",self.controls.mainSkillMinion,"RIGHT"}, {2, 0, 120, 18}, "Manage Spectres...", function() ++ self.controls.mainSkillMinionLibrary = new("ButtonControl"):ButtonControl({"LEFT",self.controls.mainSkillMinion,"RIGHT"}, {2, 0, 120, 18}, "Manage Spectres...", function() + self:OpenSpectreLibrary() + end) +- self.controls.mainSkillMinionSkill = new("DropDownControl", {"TOPLEFT",self.controls.mainSkillMinion,"BOTTOMLEFT",true}, {0, 2, 200, 16}, nil, function(index, value) ++ self.controls.mainSkillMinionSkill = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.mainSkillMinion,"BOTTOMLEFT",true}, {0, 2, 200, 16}, nil, function(index, value) + local mainSocketGroup = self.skillsTab.socketGroupList[self.mainSocketGroup] + local srcInstance = mainSocketGroup.displaySkillList[mainSocketGroup.mainActiveSkill].activeEffect.srcInstance + srcInstance.skillMinionSkill = index + self.modFlag = true + self.buildFlag = true + end) +- self.controls.statBoxAnchor = new("Control", {"TOPLEFT",self.controls.mainSkillMinionSkill,"BOTTOMLEFT",true}, {0, 2, 0, 0}) +- self.controls.statBox = new("TextListControl", {"TOPLEFT",self.controls.statBoxAnchor,"BOTTOMLEFT"}, {0, 2, 300, 0}, {{x=170,align="RIGHT_X"},{x=174,align="LEFT"}}) ++ self.controls.statBoxAnchor = new("Control"):Control({"TOPLEFT",self.controls.mainSkillMinionSkill,"BOTTOMLEFT",true}, {0, 2, 0, 0}) ++ self.controls.statBox = new("TextListControl"):TextListControl({"TOPLEFT",self.controls.statBoxAnchor,"BOTTOMLEFT"}, {0, 2, 300, 0}, {{x=170,align="RIGHT_X"},{x=174,align="LEFT"}}) + self.controls.statBox.height = function(control) + local x, y = control:GetPos() + local warnHeight = main.showWarnings and #self.controls.warnings.lines > 0 and 18 or 0 + return main.screenH - main.mainBarHeight - 4 - y - warnHeight + end +- self.controls.warnings = new("Control",{"TOPLEFT",self.controls.statBox,"BOTTOMLEFT",true}, {0, 0, 0, 18}) ++ self.controls.warnings = new("Control"):Control({"TOPLEFT",self.controls.statBox,"BOTTOMLEFT",true}, {0, 0, 0, 18}) + self.controls.warnings.lines = {} + self.controls.warnings.width = function(control) + return control.str and DrawStringWidth(16, "FIXED", control.str) + 8 or 0 +@@ -595,15 +601,15 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin + self.latestTree = main.tree[latestTreeVersion] + data.setJewelRadiiGlobally(latestTreeVersion) + self.data = data +- self.importTab = new("ImportTab", self) +- self.notesTab = new("NotesTab", self) +- self.partyTab = new("PartyTab", self) +- self.configTab = new("ConfigTab", self) +- self.itemsTab = new("ItemsTab", self) +- self.treeTab = new("TreeTab", self) +- self.skillsTab = new("SkillsTab", self) +- self.calcsTab = new("CalcsTab", self) +- self.compareTab = new("CompareTab", self) ++ self.importTab = new("ImportTab"):ImportTab(self) ++ self.notesTab = new("NotesTab"):NotesTab(self) ++ self.partyTab = new("PartyTab"):PartyTab(self) ++ self.configTab = new("ConfigTab"):ConfigTab(self) ++ self.itemsTab = new("ItemsTab"):ItemsTab(self) ++ self.treeTab = new("TreeTab"):TreeTab(self) ++ self.skillsTab = new("SkillsTab"):SkillsTab(self) ++ self.calcsTab = new("CalcsTab"):CalcsTab(self) ++ self.compareTab = new("CompareTab"):CompareTab(self) + -- Used for pined calcs panes + self.overlayPanes = { } + +@@ -1395,13 +1401,13 @@ function buildMode:OpenSaveAsPopup() + end + end + end +- controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter new build name:") +- controls.edit = new("EditControl", nil, {0, 40, 450, 20}, ++ controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter new build name:") ++ controls.edit = new("EditControl"):EditControl(nil, {0, 40, 450, 20}, + not self.dbFileName and main.predefinedBuildName or (self.buildName or self.dbFileName):gsub("[\\/:%*%?\"<>|%c]", "-"), nil, "\\/:%*%?\"<>|%c", 100, function(buf) + updateBuildName() + end) +- controls.folderLabel = new("LabelControl", {"TOPLEFT",nil,"TOPLEFT"}, {10, 70, 0, 16}, "^7Folder:") +- controls.newFolder = new("ButtonControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 67, 94, 20}, "New Folder...", function() ++ controls.folderLabel = new("LabelControl"):LabelControl({"TOPLEFT",nil,"TOPLEFT"}, {10, 70, 0, 16}, "^7Folder:") ++ controls.newFolder = new("ButtonControl"):ButtonControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 67, 94, 20}, "New Folder...", function() + main:OpenNewFolderPopup(main.buildPath..controls.folder.subPath, function(newFolderName) + if newFolderName then + controls.folder:OpenFolder(newFolderName) +@@ -1409,13 +1415,13 @@ function buildMode:OpenSaveAsPopup() + end) + end) + +- controls.folder = new("FolderListControl", nil, {0, 115, 450, 400}, self.dbFileSubPath, function(subPath) ++ controls.folder = new("FolderListControl"):FolderListControl(nil, {0, 115, 450, 400}, self.dbFileSubPath, function(subPath) + updateBuildName() + end) + controls.folder.sortMode = self.saveAsSortMode + controls.folder:SortList() + +- controls.save = new("ButtonControl", nil, {-45, 525, 80, 20}, "Save", function() ++ controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 525, 80, 20}, "Save", function() + main:ClosePopup() + self.dbFileName = newFileName + self.buildName = newBuildName +@@ -1423,7 +1429,7 @@ function buildMode:OpenSaveAsPopup() + self:SaveDBFile() + self.spec:SetWindowTitleWithBuildClass() + end) +- controls.close = new("ButtonControl", nil, {45, 525, 80, 20}, "Cancel", function() ++ controls.close = new("ButtonControl"):ButtonControl(nil, {45, 525, 80, 20}, "Cancel", function() + main:ClosePopup() + self.actionOnSave = nil + end) +@@ -1435,7 +1441,7 @@ function buildMode:OpenSaveAsPopup() + controls.save.enabled = false + end + +- controls.buildSortMode = new("DropDownControl", { "TOPRIGHT", nil, "TOPRIGHT" }, { -10, 70, 120, 18 }, { ++ controls.buildSortMode = new("DropDownControl"):DropDownControl({ "TOPRIGHT", nil, "TOPRIGHT" }, { -10, 70, 120, 18 }, { + { label = "Sort By Name", mode = "NAME" }, + { label = "Sort By Last Edited", mode = "EDITED" }, + }, function(index, value) +@@ -1464,19 +1470,19 @@ function buildMode:OpenSpectreLibrary() + end + end) + local controls = { } +- controls.list = new("MinionListControl", nil, {-139, 40, 265, 250}, self.data, destList) +- controls.source = new("MinionSearchListControl", nil, {139, 60, 265, 230}, self.data, sourceList, controls.list) +- controls.save = new("ButtonControl", nil, {-45, 330, 80, 20}, "Save", function() ++ controls.list = new("MinionListControl"):MinionListControl(nil, {-139, 40, 265, 250}, self.data, destList) ++ controls.source = new("MinionSearchListControl"):MinionSearchListControl(nil, {139, 60, 265, 230}, self.data, sourceList, controls.list) ++ controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 330, 80, 20}, "Save", function() + self.spectreList = destList + self.modFlag = true + self.buildFlag = true + main:ClosePopup() + end) +- controls.cancel = new("ButtonControl", nil, {45, 330, 80, 20}, "Cancel", function() ++ controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 330, 80, 20}, "Cancel", function() + main:ClosePopup() + end) +- controls.noteLine1 = new("LabelControl", {"TOPLEFT",controls.list,"BOTTOMLEFT"}, {99, 2, 0, 16}, "^7Spectres in your Library must be assigned to an active") +- controls.noteLine2 = new("LabelControl", {"TOPLEFT",controls.list,"BOTTOMLEFT"}, {95, 18, 0, 16}, "^7Raise Spectre gem for their buffs and curses to activate") ++ controls.noteLine1 = new("LabelControl"):LabelControl({"TOPLEFT",controls.list,"BOTTOMLEFT"}, {99, 2, 0, 16}, "^7Spectres in your Library must be assigned to an active") ++ controls.noteLine2 = new("LabelControl"):LabelControl({"TOPLEFT",controls.list,"BOTTOMLEFT"}, {95, 18, 0, 16}, "^7Raise Spectre gem for their buffs and curses to activate") + local spectrePopup = main:OpenPopup(575, 360, "Spectre Library", controls) + spectrePopup:SelectControl(spectrePopup.controls.source.controls.searchText) + end diff --git a/src/Modules/BuildDisplayStats.lua b/src/Modules/BuildDisplayStats.lua index 538efd46ca..c036e00397 100644 --- a/src/Modules/BuildDisplayStats.lua +++ b/src/Modules/BuildDisplayStats.lua @@ -260,4 +260,4 @@ local extraSaveStats = { "ActiveMinionLimit", } -return displayStats, minionDisplayStats, extraSaveStats +return { displayStats = displayStats, minionDisplayStats = minionDisplayStats, extraSaveStats = extraSaveStats } diff --git a/src/Modules/BuildList.lua b/src/Modules/BuildList.lua index c9b67025cd..3f247f2d02 100644 --- a/src/Modules/BuildList.lua +++ b/src/Modules/BuildList.lua @@ -10,7 +10,7 @@ local t_insert = table.insert local buildListHelpers = LoadModule("Modules/BuildListHelpers") local buildSortDropList = buildListHelpers.buildSortDropList -local listMode = new("ControlHost") +local listMode = new("ControlHost"):ControlHost() function listMode:Init(selBuildName, subPath) if self.initialised then @@ -28,7 +28,7 @@ function listMode:Init(selBuildName, subPath) return end - self.anchor = new("Control", nil, {0, 4, 0, 0}) + self.anchor = new("Control"):Control(nil, {0, 4, 0, 0}) self.anchor.x = function() return main.screenW / 2 end @@ -36,34 +36,34 @@ function listMode:Init(selBuildName, subPath) self.subPath = subPath or "" self.list = { } - self.controls.new = new("ButtonControl", {"TOP",self.anchor,"TOP"}, {-259, 0, 60, 20}, "New", function() + self.controls.new = new("ButtonControl"):ButtonControl({"TOP",self.anchor,"TOP"}, {-259, 0, 60, 20}, "New", function() main:SetMode("BUILD", false, "Unnamed build") end) - self.controls.newFolder = new("ButtonControl", {"LEFT",self.controls.new,"RIGHT"}, {8, 0, 90, 20}, "New Folder", function() + self.controls.newFolder = new("ButtonControl"):ButtonControl({"LEFT",self.controls.new,"RIGHT"}, {8, 0, 90, 20}, "New Folder", function() self.controls.buildList:NewFolder() end) - self.controls.open = new("ButtonControl", {"LEFT",self.controls.newFolder,"RIGHT"}, {8, 0, 60, 20}, "Open", function() + self.controls.open = new("ButtonControl"):ButtonControl({"LEFT",self.controls.newFolder,"RIGHT"}, {8, 0, 60, 20}, "Open", function() self.controls.buildList:LoadBuild(self.controls.buildList.selValue) end) self.controls.open.enabled = function() return self.controls.buildList.selValue ~= nil end - self.controls.copy = new("ButtonControl", {"LEFT",self.controls.open,"RIGHT"}, {8, 0, 60, 20}, "Copy", function() + self.controls.copy = new("ButtonControl"):ButtonControl({"LEFT",self.controls.open,"RIGHT"}, {8, 0, 60, 20}, "Copy", function() self.controls.buildList:RenameBuild(self.controls.buildList.selValue, true) end) self.controls.copy.enabled = function() return self.controls.buildList.selValue ~= nil end - self.controls.rename = new("ButtonControl", {"LEFT",self.controls.copy,"RIGHT"}, {8, 0, 60, 20}, "Rename", function() + self.controls.rename = new("ButtonControl"):ButtonControl({"LEFT",self.controls.copy,"RIGHT"}, {8, 0, 60, 20}, "Rename", function() self.controls.buildList:RenameBuild(self.controls.buildList.selValue) end) self.controls.rename.enabled = function() return self.controls.buildList.selValue ~= nil end - self.controls.delete = new("ButtonControl", {"LEFT",self.controls.rename,"RIGHT"}, {8, 0, 60, 20}, "Delete", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"LEFT",self.controls.rename,"RIGHT"}, {8, 0, 60, 20}, "Delete", function() self.controls.buildList:DeleteBuild(self.controls.buildList.selValue) end) self.controls.delete.enabled = function() return self.controls.buildList.selValue ~= nil end - self.controls.sort = new("DropDownControl", {"LEFT",self.controls.delete,"RIGHT"}, {8, 0, 140, 20}, buildSortDropList, function(index, value) + self.controls.sort = new("DropDownControl"):DropDownControl({"LEFT",self.controls.delete,"RIGHT"}, {8, 0, 140, 20}, buildSortDropList, function(index, value) main.buildSortMode = value.sortMode self:SortList() end) self.controls.sort:SelByValue(main.buildSortMode, "sortMode") - self.controls.buildList = new("BuildListControl", {"TOP",self.anchor,"TOP"}, {0, 75, 900, 0}, self) + self.controls.buildList = new("BuildListControl"):BuildListControl({"TOP",self.anchor,"TOP"}, {0, 75, 900, 0}, self) self.controls.buildList.height = function() return main.screenH - 80 end @@ -111,10 +111,10 @@ function listMode:getPublicBuilds() local buildProviders = { { name = "PoB Archives", - impl = new("PoBArchivesProvider", "builds") + impl = new("PoBArchivesProvider"):PoBArchivesProvider("builds") } } - local extBuildList = new("ExtBuildListControl", {"LEFT",self.controls.buildList,"RIGHT"}, {25, 0, main.screenW * 1 / 4 - 50, 0}, buildProviders) + local extBuildList = new("ExtBuildListControl"):ExtBuildListControl({"LEFT",self.controls.buildList,"RIGHT"}, {25, 0, main.screenW * 1 / 4 - 50, 0}, buildProviders) extBuildList:Init("PoB Archives") extBuildList.height = function() return main.screenH - 80 diff --git a/src/Modules/BuildList.lua.rej b/src/Modules/BuildList.lua.rej new file mode 100644 index 0000000000..0ae26924ab --- /dev/null +++ b/src/Modules/BuildList.lua.rej @@ -0,0 +1,10 @@ +diff a/src/Modules/BuildList.lua b/src/Modules/BuildList.lua (rejected hunks) +@@ -93,7 +93,7 @@ function listMode:Init(selBuildName, subPath) + self.controls.ExtBuildList = self:getPublicBuilds() + end + +- self.controls.searchText = new("EditControl", {"TOP",self.anchor,"TOP"}, {0, 25, 640, 20}, self.filterBuildList, "Search", "%c%(%)", 100, function(buf) ++ self.controls.searchText = new("EditControl"):EditControl({"TOP",self.anchor,"TOP"}, {0, 25, 640, 20}, self.filterBuildList, "Search", "%c%(%)", 100, function(buf) + main.filterBuildList = buf + self:FilterBuildList() + end, nil, nil, true) diff --git a/src/Modules/CalcActiveSkill.lua b/src/Modules/CalcActiveSkill.lua index 49d8ca6c40..6b23040cec 100644 --- a/src/Modules/CalcActiveSkill.lua +++ b/src/Modules/CalcActiveSkill.lua @@ -3,7 +3,8 @@ -- Module: Calc Active Skill -- Active skill setup. -- -local calcs = ... +---@class Calcs +local calcs = require("Modules.CalcBase") local pairs = pairs local ipairs = ipairs diff --git a/src/Modules/CalcActiveSkill.lua.rej b/src/Modules/CalcActiveSkill.lua.rej new file mode 100644 index 0000000000..6ed6019ece --- /dev/null +++ b/src/Modules/CalcActiveSkill.lua.rej @@ -0,0 +1,22 @@ +diff a/src/Modules/CalcActiveSkill.lua b/src/Modules/CalcActiveSkill.lua (rejected hunks) +@@ -178,9 +179,9 @@ function calcs.copyActiveSkill(env, mode, skill) + local newSkill = calcs.createActiveSkill(activeEffect, skill.supportList, skill.actor, skill.socketGroup, skill.summonSkill) + local newEnv, _, _, _ = calcs.initEnv(env.build, mode, env.override) + calcs.buildActiveSkillModList(newEnv, newSkill) +- newSkill.skillModList = new("ModList", newSkill.baseSkillModList) ++ newSkill.skillModList = new("ModList"):ModList(newSkill.baseSkillModList) + if newSkill.minion then +- newSkill.minion.modDB = new("ModDB") ++ newSkill.minion.modDB = new("ModDB"):ModDB() + newSkill.minion.modDB.actor = newSkill.minion + calcs.createMinionSkills(env, newSkill) + newSkill.skillPartName = newSkill.minion.mainSkill.activeEffect.grantedEffect.name +@@ -479,7 +480,7 @@ function calcs.buildActiveSkillModList(env, activeSkill) + end + + -- Initialise skill modifier list +- local skillModList = new("ModList", activeSkill.actor.modDB) ++ local skillModList = new("ModList"):ModList(activeSkill.actor.modDB) + activeSkill.skillModList = skillModList + activeSkill.baseSkillModList = skillModList + diff --git a/src/Modules/CalcBase.lua b/src/Modules/CalcBase.lua new file mode 100644 index 0000000000..cf23cec318 --- /dev/null +++ b/src/Modules/CalcBase.lua @@ -0,0 +1,4 @@ +-- This module is used as a base that the other calc sections can `require` to add their functions to +---@class Calcs +local calcs = {} +return calcs diff --git a/src/Modules/CalcBreakdown.lua b/src/Modules/CalcBreakdown.lua index a2ab6b7738..58196bc8a0 100644 --- a/src/Modules/CalcBreakdown.lua +++ b/src/Modules/CalcBreakdown.lua @@ -3,8 +3,6 @@ -- Module: Calc Breakdown -- Calculation breakdown generators -- -local modDB, output, actor = ... - local unpack = unpack local ipairs = ipairs local t_insert = table.insert diff --git a/src/Modules/CalcBreakdown.lua.rej b/src/Modules/CalcBreakdown.lua.rej new file mode 100644 index 0000000000..92cf3259df --- /dev/null +++ b/src/Modules/CalcBreakdown.lua.rej @@ -0,0 +1,450 @@ +diff a/src/Modules/CalcBreakdown.lua b/src/Modules/CalcBreakdown.lua (rejected hunks) +@@ -12,240 +10,242 @@ local m_floor = math.floor + local m_sqrt = math.sqrt + local s_format = string.format + +-local breakdown = { } ++return function(modDB, output, actor) ++ local breakdown = {} + +-function breakdown.multiChain(out, chain) +- local base = (chain.base and chain.base[2]) or nil +- local multiplier = 1 +- local lines = 0 -- lines is the total number of non 1 multipliers. +- if chain.label then +- t_insert(out, chain.label) +- end +- if base ~= nil then +- t_insert(out, s_format(unpack(chain.base))) +- end +- if base ~= 0 then +- for _, mult in ipairs(chain) do +- if mult[2] and mult[2] ~= 1 then +- multiplier = multiplier * mult[2] +- t_insert(out, "x "..s_format(unpack(mult))) +- lines = lines + 1 ++ function breakdown.multiChain(out, chain) ++ local base = (chain.base and chain.base[2]) or nil ++ local multiplier = 1 ++ local lines = 0 -- lines is the total number of non 1 multipliers. ++ if chain.label then ++ t_insert(out, chain.label) ++ end ++ if base ~= nil then ++ t_insert(out, s_format(unpack(chain.base))) ++ end ++ if base ~= 0 then ++ for _, mult in ipairs(chain) do ++ if mult[2] and mult[2] ~= 1 then ++ multiplier = multiplier * mult[2] ++ t_insert(out, "x " .. s_format(unpack(mult))) ++ lines = lines + 1 ++ end + end + end ++ if chain.total then ++ t_insert(out, chain.total) ++ elseif not chain.noTotal and (lines > 0 and base ~= nil) or (lines > 1 and base == nil) then ++ t_insert(out, s_format("= %.2f", multiplier * (base or 1))) ++ end ++ return lines + end +- if chain.total then +- t_insert(out, chain.total) +- elseif not chain.noTotal and (lines > 0 and base ~= nil) or (lines > 1 and base == nil) then +- t_insert(out, s_format("= %.2f", multiplier * (base or 1))) +- end +- return lines +-end + +-function breakdown.simple(extraBase, cfg, total, ...) +- extraBase = extraBase or 0 +- local base = modDB:Sum("BASE", cfg, (...)) +- if (base + extraBase) ~= 0 then +- local inc = modDB:Sum("INC", cfg, ...) +- local more = modDB:More(cfg, ...) +- if inc ~= 0 or more ~= 1 or (base ~= 0 and extraBase ~= 0) then +- local out = { } +- if base ~= 0 and extraBase ~= 0 then +- out[1] = s_format("(%g + %g) ^8(base)", extraBase, base) +- else +- out[1] = s_format("%g ^8(base)", base + extraBase) +- end +- if inc ~= 0 then +- t_insert(out, s_format("x %.2f ^8(increased/reduced)", 1 + inc/100)) ++ function breakdown.simple(extraBase, cfg, total, ...) ++ extraBase = extraBase or 0 ++ local base = modDB:Sum("BASE", cfg, (...)) ++ if (base + extraBase) ~= 0 then ++ local inc = modDB:Sum("INC", cfg, ...) ++ local more = modDB:More(cfg, ...) ++ if inc ~= 0 or more ~= 1 or (base ~= 0 and extraBase ~= 0) then ++ local out = {} ++ if base ~= 0 and extraBase ~= 0 then ++ out[1] = s_format("(%g + %g) ^8(base)", extraBase, base) ++ else ++ out[1] = s_format("%g ^8(base)", base + extraBase) ++ end ++ if inc ~= 0 then ++ t_insert(out, s_format("x %.2f ^8(increased/reduced)", 1 + inc / 100)) ++ end ++ if more ~= 1 then ++ t_insert(out, s_format("x %.2f ^8(more/less)", more)) ++ end ++ t_insert(out, s_format("= %g", total)) ++ return out + end +- if more ~= 1 then +- t_insert(out, s_format("x %.2f ^8(more/less)", more)) +- end +- t_insert(out, s_format("= %g", total)) +- return out + end + end +-end + +-function breakdown.mod(modList, cfg, ...) +- local inc = modList:Sum("INC", cfg, ...) +- local more = modList:More(cfg, ...) +- if inc ~= 0 or more ~= 1 then +- return { +- s_format("%.2f ^8(increased/reduced)", 1 + inc/100), +- s_format("x %.2f ^8(more/less)", more), +- s_format("= %.2f", (1 + inc/100) * more), +- } ++ function breakdown.mod(modList, cfg, ...) ++ local inc = modList:Sum("INC", cfg, ...) ++ local more = modList:More(cfg, ...) ++ if inc ~= 0 or more ~= 1 then ++ return { ++ s_format("%.2f ^8(increased/reduced)", 1 + inc / 100), ++ s_format("x %.2f ^8(more/less)", more), ++ s_format("= %.2f", (1 + inc / 100) * more), ++ } ++ end + end +-end +- +-function breakdown.slot(source, sourceName, cfg, base, total, ...) +- local inc = modDB:Sum("INC", cfg, ...) +- local more = modDB:More(cfg, ...) +- t_insert(breakdown[...].slots, { +- base = base, +- inc = (inc ~= 0) and s_format(" x %.2f", 1 + inc/100), +- more = (more ~= 1) and s_format(" x %.2f", more), +- total = s_format("%.2f", total or (base * (1 + inc / 100) * more)), +- source = source, +- sourceName = sourceName, +- item = actor.itemList[source], +- }) +-end + +-function breakdown.area(base, areaMod, total, incBreakpoint, moreBreakpoint, redBreakpoint, lessBreakpoint, label) +- local out = {} +- t_insert(out, label) +- if base ~= total then +- t_insert(out, s_format("%.1fm ^8(base radius)", base / 10)) +- t_insert(out, s_format("x %.2f ^8(square root of area of effect modifier)", m_floor(100 * m_sqrt(areaMod)) / 100)) +- t_insert(out, s_format("= %.1fm", total / 10)) ++ function breakdown.slot(source, sourceName, cfg, base, total, ...) ++ local inc = modDB:Sum("INC", cfg, ...) ++ local more = modDB:More(cfg, ...) ++ t_insert(breakdown[...].slots, { ++ base = base, ++ inc = (inc ~= 0) and s_format(" x %.2f", 1 + inc / 100), ++ more = (more ~= 1) and s_format(" x %.2f", more), ++ total = s_format("%.2f", total or (base * (1 + inc / 100) * more)), ++ source = source, ++ sourceName = sourceName, ++ item = actor.itemList[source], ++ }) + end +- if incBreakpoint and moreBreakpoint and redBreakpoint and lessBreakpoint then +- t_insert(out, s_format("^8Next 0.1m breakpoint: %d%% increased AoE / a %d%% more AoE multiplier", incBreakpoint, moreBreakpoint)) +- t_insert(out, s_format("^8Previous 0.1m breakpoint: %d%% reduced AoE / a %d%% less AoE multiplier", redBreakpoint, lessBreakpoint)) ++ ++ function breakdown.area(base, areaMod, total, incBreakpoint, moreBreakpoint, redBreakpoint, lessBreakpoint, label) ++ local out = {} ++ t_insert(out, label) ++ if base ~= total then ++ t_insert(out, s_format("%.1fm ^8(base radius)", base / 10)) ++ t_insert(out, s_format("x %.2f ^8(square root of area of effect modifier)", m_floor(100 * m_sqrt(areaMod)) / 100)) ++ t_insert(out, s_format("= %.1fm", total / 10)) ++ end ++ if incBreakpoint and moreBreakpoint and redBreakpoint and lessBreakpoint then ++ t_insert(out, s_format("^8Next 0.1m breakpoint: %d%% increased AoE / a %d%% more AoE multiplier", incBreakpoint, moreBreakpoint)) ++ t_insert(out, s_format("^8Previous 0.1m breakpoint: %d%% reduced AoE / a %d%% less AoE multiplier", redBreakpoint, lessBreakpoint)) ++ end ++ out.radius = total ++ return out + end +- out.radius = total +- return out +-end + +-function breakdown.effMult(damageType, resist, pen, taken, mult, takenMore, sourceRes, useRes, invertChance, effectiveResist) +- local out = { } +- local resistForm = (damageType == "Physical") and "physical damage reduction" or "resistance" +- local resistLabel = resistForm +- effectiveResist = effectiveResist or resist - pen ++ function breakdown.effMult(damageType, resist, pen, taken, mult, takenMore, sourceRes, useRes, invertChance, effectiveResist) ++ local out = {} ++ local resistForm = (damageType == "Physical") and "physical damage reduction" or "resistance" ++ local resistLabel = resistForm ++ effectiveResist = effectiveResist or resist - pen + +- if sourceRes and sourceRes ~= damageType then +- t_insert(out, s_format("Enemy %s: %d%% ^8(%s)", resistLabel, resist, sourceRes)) +- elseif resist ~= 0 then +- t_insert(out, s_format("Enemy %s: %d%%", resistLabel, resist)) +- end +- if invertChance and invertChance ~= 0 and useRes then +- local normalResist = resist - pen +- local invertedResist = -resist - pen +- t_insert(out, "Effective resistance:") +- t_insert(out, s_format("%g%% ^8(non-inverted hit after penetration)", normalResist)) +- t_insert(out, s_format("%g%% ^8(inverted hit after penetration)", invertedResist)) +- t_insert(out, s_format("= %g%% ^8(weighted average from %.0f%% inversion chance)", effectiveResist, invertChance * 100)) +- elseif pen ~= 0 or not useRes then +- t_insert(out, "Effective resistance:") +- t_insert(out, s_format("%d%% ^8(resistance)", resist)) +- if pen < 0 then +- t_insert(out, s_format("+ %d%% ^8(penetration)", -pen)) +- elseif pen > 0 then +- t_insert(out, s_format("- %d%% ^8(penetration)", pen)) ++ if sourceRes and sourceRes ~= damageType then ++ t_insert(out, s_format("Enemy %s: %d%% ^8(%s)", resistLabel, resist, sourceRes)) ++ elseif resist ~= 0 then ++ t_insert(out, s_format("Enemy %s: %d%%", resistLabel, resist)) ++ end ++ if invertChance and invertChance ~= 0 and useRes then ++ local normalResist = resist - pen ++ local invertedResist = -resist - pen ++ t_insert(out, "Effective resistance:") ++ t_insert(out, s_format("%g%% ^8(non-inverted hit after penetration)", normalResist)) ++ t_insert(out, s_format("%g%% ^8(inverted hit after penetration)", invertedResist)) ++ t_insert(out, s_format("= %g%% ^8(weighted average from %.0f%% inversion chance)", effectiveResist, invertChance * 100)) ++ elseif pen ~= 0 or not useRes then ++ t_insert(out, "Effective resistance:") ++ t_insert(out, s_format("%d%% ^8(resistance)", resist)) ++ if pen < 0 then ++ t_insert(out, s_format("+ %d%% ^8(penetration)", -pen)) ++ elseif pen > 0 then ++ t_insert(out, s_format("- %d%% ^8(penetration)", pen)) ++ end ++ if not useRes then ++ t_insert(out, s_format("x %d%% ^8(resistance ignored)", 0)) ++ t_insert(out, s_format("= %d%%", (0))) ++ else ++ t_insert(out, s_format("= %d%%", (resist - pen))) ++ end + end +- if not useRes then +- t_insert(out, s_format("x %d%% ^8(resistance ignored)", 0)) +- t_insert(out, s_format("= %d%%", (0))) +- else +- t_insert(out, s_format("= %d%%", (resist - pen))) ++ if useRes then ++ breakdown.multiChain(out, { ++ label = "Effective DPS modifier:", ++ { "%.2f ^8(%s)", 1 - effectiveResist / 100, resistForm }, ++ { "%.2f ^8(increased/reduced damage taken)", 1 + taken / 100 }, ++ { "%.2f ^8(more/less damage taken)", takenMore }, ++ total = s_format("= %.3f", mult), ++ }) ++ else ++ t_insert(out, "Effective DPS modifier:") ++ t_insert(out, s_format("= %.3f ^8(increased/reduced damage taken)", mult)) + end ++ return out + end +- if useRes then ++ ++ function breakdown.dot(out, baseVal, inc, more, mult, rate, aura, effMult, total) + breakdown.multiChain(out, { +- label = "Effective DPS modifier:", +- { "%.2f ^8(%s)", 1 - effectiveResist / 100, resistForm }, +- { "%.2f ^8(increased/reduced damage taken)", 1 + taken / 100 }, +- { "%.2f ^8(more/less damage taken)", takenMore }, +- total = s_format("= %.3f", mult), ++ base = { "%.1f ^8(base damage per second)", baseVal }, ++ { "%.2f ^8(increased/reduced)", 1 + inc / 100 }, ++ { "%.2f ^8(more/less)", more }, ++ { "%.2f ^8(multiplier)", 1 + (mult or 0) / 100 }, ++ { "%.2f ^8(rate modifier)", rate }, ++ { "%.3f ^8(aura effect modifier)", aura }, ++ { "%.3f ^8(effective DPS modifier)", effMult }, ++ total = s_format("= %.1f ^8per second", total), + }) +- else +- t_insert(out, "Effective DPS modifier:") +- t_insert(out, s_format("= %.3f ^8(increased/reduced damage taken)", mult)) + end +- return out +-end +- +-function breakdown.dot(out, baseVal, inc, more, mult, rate, aura, effMult, total) +- breakdown.multiChain(out, { +- base = { "%.1f ^8(base damage per second)", baseVal }, +- { "%.2f ^8(increased/reduced)", 1 + inc/100 }, +- { "%.2f ^8(more/less)", more }, +- { "%.2f ^8(multiplier)", 1 + (mult or 0)/100 }, +- { "%.2f ^8(rate modifier)", rate }, +- { "%.3f ^8(aura effect modifier)", aura }, +- { "%.3f ^8(effective DPS modifier)", effMult }, +- total = s_format("= %.1f ^8per second", total), +- }) +-end + +-function breakdown.critDot(dotMulti, critMulti, dotChance, critChance) +- local combined = (dotMulti * dotChance) + (critMulti * critChance) +- local out = { } +- if dotChance > 0 then +- t_insert(out, s_format("Contribution from Non-crits:")) +- t_insert(out, s_format("%.2f ^8(dot multiplier for non-crits)", dotMulti)) +- t_insert(out, s_format("x %.4f ^8(portion of instances created by non-crits)", dotChance)) +- t_insert(out, s_format("= %.2f", dotMulti * dotChance)) +- end +- if critChance > 0 then +- t_insert(out, s_format("Contribution from Crits:")) +- t_insert(out, s_format("%.2f ^8(dot multiplier for crits)", critMulti)) +- t_insert(out, s_format("x %.4f ^8(portion of instances created by crits)", critChance)) +- t_insert(out, s_format("= %.2f", critMulti * critChance)) +- end +- if (dotChance > 0 and critChance > 0) and (dotMulti ~= critMulti)then +- t_insert(out, s_format("Effective DoT Multiplier:")) +- t_insert(out, s_format("%.2f + %.2f", dotMulti * dotChance, critMulti * critChance)) +- t_insert(out, s_format("= %.2f", combined)) +- end +- return out +-end +- +-function breakdown.leech(instant, instantRate, instances, pool, rate, max, dur, instantLeechProportion, hitRate) +- local out = { } +- if actor.mainSkill.skillData.showAverage then +- if instant > 0 then +- if instantLeechProportion ~= 1 then +- t_insert(out, s_format("Instant Leech: %.1f ^8(%d%% x %.1f)", instant, instantLeechProportion * 100, dur * pool * data.misc.LeechRateBase / (1-instantLeechProportion))) +- else +- t_insert(out, s_format("Instant Leech: %.1f", instant)) +- end ++ function breakdown.critDot(dotMulti, critMulti, dotChance, critChance) ++ local combined = (dotMulti * dotChance) + (critMulti * critChance) ++ local out = {} ++ if dotChance > 0 then ++ t_insert(out, s_format("Contribution from Non-crits:")) ++ t_insert(out, s_format("%.2f ^8(dot multiplier for non-crits)", dotMulti)) ++ t_insert(out, s_format("x %.4f ^8(portion of instances created by non-crits)", dotChance)) ++ t_insert(out, s_format("= %.2f", dotMulti * dotChance)) + end +- if instances > 0 then +- t_insert(out, "Total leeched per instance:") +- t_insert(out, s_format("%d ^8(size of leech destination pool)", pool)) +- t_insert(out, s_format("x %.2f ^8(base leech rate is %d%% per second)", data.misc.LeechRateBase, 100 * data.misc.LeechRateBase)) +- local rateMod = calcLib.mod(modDB, skillCfg, rate) +- if rateMod ~= 1 then +- t_insert(out, s_format("x %.2f ^8(leech rate modifier)", rateMod)) +- end +- t_insert(out, s_format("x %.2fs ^8(instance duration)", dur)) +- t_insert(out, s_format("= %.1f", pool * data.misc.LeechRateBase * rateMod * dur)) ++ if critChance > 0 then ++ t_insert(out, s_format("Contribution from Crits:")) ++ t_insert(out, s_format("%.2f ^8(dot multiplier for crits)", critMulti)) ++ t_insert(out, s_format("x %.4f ^8(portion of instances created by crits)", critChance)) ++ t_insert(out, s_format("= %.2f", critMulti * critChance)) + end +- else +- if instantRate > 0 then +- if instantLeechProportion ~= 1 then +- t_insert(out, s_format("Instant Leech: %.1f ^8(%d%% x %.1f)", instant, instantLeechProportion * 100, dur * pool * data.misc.LeechRateBase / (1-instantLeechProportion))) +- else +- t_insert(out, s_format("Instant Leech: %.1f", instant)) +- end +- t_insert(out, s_format("Instant Leech per second: %.1f ^8(%.1f x %.2f)", instantRate, instant, hitRate)) ++ if (dotChance > 0 and critChance > 0) and (dotMulti ~= critMulti) then ++ t_insert(out, s_format("Effective DoT Multiplier:")) ++ t_insert(out, s_format("%.2f + %.2f", dotMulti * dotChance, critMulti * critChance)) ++ t_insert(out, s_format("= %.2f", combined)) + end +- if instances > 0 then +- t_insert(out, "Rate per instance:") +- t_insert(out, s_format("%d ^8(size of leech destination pool)", pool)) +- t_insert(out, s_format("x %.2f ^8(base leech rate is %d%% per second)", data.misc.LeechRateBase, 100 * data.misc.LeechRateBase)) +- local rateMod = calcLib.mod(modDB, skillCfg, rate) +- if rateMod ~= 1 then +- t_insert(out, s_format("x %.2f ^8(leech rate modifier)", rateMod)) ++ return out ++ end ++ ++ function breakdown.leech(instant, instantRate, instances, pool, rate, max, dur, instantLeechProportion, hitRate) ++ local out = {} ++ if actor.mainSkill.skillData.showAverage then ++ if instant > 0 then ++ if instantLeechProportion ~= 1 then ++ t_insert(out, s_format("Instant Leech: %.1f ^8(%d%% x %.1f)", instant, instantLeechProportion * 100, dur * pool * data.misc.LeechRateBase / (1 - instantLeechProportion))) ++ else ++ t_insert(out, s_format("Instant Leech: %.1f", instant)) ++ end ++ end ++ if instances > 0 then ++ t_insert(out, "Total leeched per instance:") ++ t_insert(out, s_format("%d ^8(size of leech destination pool)", pool)) ++ t_insert(out, s_format("x %.2f ^8(base leech rate is %d%% per second)", data.misc.LeechRateBase, 100 * data.misc.LeechRateBase)) ++ local rateMod = calcLib.mod(modDB, skillCfg, rate) ++ if rateMod ~= 1 then ++ t_insert(out, s_format("x %.2f ^8(leech rate modifier)", rateMod)) ++ end ++ t_insert(out, s_format("x %.2fs ^8(instance duration)", dur)) ++ t_insert(out, s_format("= %.1f", pool * data.misc.LeechRateBase * rateMod * dur)) + end +- t_insert(out, s_format("= %.1f ^8per second", pool * data.misc.LeechRateBase * rateMod)) +- t_insert(out, "Maximum leech rate against one target:") +- t_insert(out, s_format("%.1f", pool * data.misc.LeechRateBase * rateMod)) +- t_insert(out, s_format("x %.2f ^8(average instances)", instances)) +- local total = pool * data.misc.LeechRateBase * rateMod * instances +- t_insert(out, s_format("= %.1f ^8per second", total)) +- if total <= max then +- t_insert(out, s_format("Time to reach max: %.1fs", dur)) ++ else ++ if instantRate > 0 then ++ if instantLeechProportion ~= 1 then ++ t_insert(out, s_format("Instant Leech: %.1f ^8(%d%% x %.1f)", instant, instantLeechProportion * 100, dur * pool * data.misc.LeechRateBase / (1 - instantLeechProportion))) ++ else ++ t_insert(out, s_format("Instant Leech: %.1f", instant)) ++ end ++ t_insert(out, s_format("Instant Leech per second: %.1f ^8(%.1f x %.2f)", instantRate, instant, hitRate)) + end +- t_insert(out, s_format("Leech rate cap: %.1f", max)) +- if total > max then +- t_insert(out, s_format("Time to reach cap: %.1fs", dur / total * max)) ++ if instances > 0 then ++ t_insert(out, "Rate per instance:") ++ t_insert(out, s_format("%d ^8(size of leech destination pool)", pool)) ++ t_insert(out, s_format("x %.2f ^8(base leech rate is %d%% per second)", data.misc.LeechRateBase, 100 * data.misc.LeechRateBase)) ++ local rateMod = calcLib.mod(modDB, skillCfg, rate) ++ if rateMod ~= 1 then ++ t_insert(out, s_format("x %.2f ^8(leech rate modifier)", rateMod)) ++ end ++ t_insert(out, s_format("= %.1f ^8per second", pool * data.misc.LeechRateBase * rateMod)) ++ t_insert(out, "Maximum leech rate against one target:") ++ t_insert(out, s_format("%.1f", pool * data.misc.LeechRateBase * rateMod)) ++ t_insert(out, s_format("x %.2f ^8(average instances)", instances)) ++ local total = pool * data.misc.LeechRateBase * rateMod * instances ++ t_insert(out, s_format("= %.1f ^8per second", total)) ++ if total <= max then ++ t_insert(out, s_format("Time to reach max: %.1fs", dur)) ++ end ++ t_insert(out, s_format("Leech rate cap: %.1f", max)) ++ if total > max then ++ t_insert(out, s_format("Time to reach cap: %.1fs", dur / total * max)) ++ end + end + end ++ return out + end +- return out +-end + +-return breakdown ++ return breakdown ++end diff --git a/src/Modules/CalcDefence.lua b/src/Modules/CalcDefence.lua index e15529390a..770b07a371 100644 --- a/src/Modules/CalcDefence.lua +++ b/src/Modules/CalcDefence.lua @@ -3,7 +3,8 @@ -- Module: Calc Defence -- Performs defence calculations. -- -local calcs = ... +---@class Calcs +local calcs = require("Modules.CalcBase") local pairs = pairs local ipairs = ipairs @@ -4356,3 +4357,5 @@ function calcs.buildDefenceEstimations(env, actor) end --endregion end + +return calcs diff --git a/src/Modules/CalcDefence.lua.rej b/src/Modules/CalcDefence.lua.rej new file mode 100644 index 0000000000..bd66d9c9f4 --- /dev/null +++ b/src/Modules/CalcDefence.lua.rej @@ -0,0 +1,13 @@ +diff a/src/Modules/CalcDefence.lua b/src/Modules/CalcDefence.lua (rejected hunks) +@@ -76,9 +77,9 @@ function calcs.armourReduction(armour, raw) + end + + -- Based on code from FR and BS found in act_*.txt +----@param activeSkill/output/breakdown references table passed in from calc offence ++---@param activeSkill any /output/breakdown references table passed in from calc offence + ---@param sourceType string type of incoming damage - it will be converted (taken as) from this type if applicable +----@param baseDmg for which to calculate the damage ++---@param baseDmg number for which to calculate the damage + ---@return table of taken damage parts, and number, sum of damages + function calcs.applyDmgTakenConversion(activeSkill, output, breakdown, sourceType, baseDmg) + local damageBreakdown = { } diff --git a/src/Modules/CalcMirages.lua b/src/Modules/CalcMirages.lua index c28b521d1a..846e67075c 100644 --- a/src/Modules/CalcMirages.lua +++ b/src/Modules/CalcMirages.lua @@ -4,7 +4,9 @@ -- Handles mirages that use player skills -- -local calcs = ... +---@class Calcs +local calcs = require("Modules.CalcBase") + local pairs = pairs local ipairs = ipairs local t_insert = table.insert diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index b6de2bf85d..73b0edbc63 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -3,7 +3,8 @@ -- Module: Calc Offence -- Performs offence calculations. -- -local calcs = ... +---@class Calcs +local calcs = require("Modules.CalcBase") local pairs = pairs local ipairs = ipairs @@ -2384,7 +2385,7 @@ function calcs.offence(env, actor, activeSkill) local critOverride = skillModList:Override(skillCfg, "WeaponBaseCritChance") if skillFlags.weapon1Attack then if breakdown then - breakdown.MainHand = LoadModule(calcs.breakdownModule, skillModList, output.MainHand) + breakdown.MainHand = LoadModule(calcs.breakdownModule)(skillModList, output.MainHand) end activeSkill.weapon1Cfg.skillStats = output.MainHand local source = copyTable(actor.weaponData1) @@ -2414,7 +2415,7 @@ function calcs.offence(env, actor, activeSkill) end if skillFlags.weapon2Attack then if breakdown then - breakdown.OffHand = LoadModule(calcs.breakdownModule, skillModList, output.OffHand) + breakdown.OffHand = LoadModule(calcs.breakdownModule)(skillModList, output.OffHand) end activeSkill.weapon2Cfg.skillStats = output.OffHand local source = copyTable(actor.weaponData2) diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index dbc4bb9767..b2ea93ba6a 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -3,7 +3,8 @@ -- Module: Calc Perform -- Manages the offence/defence calculations. -- -local calcs = ... +---@class Calcs +local calcs = require("Modules.CalcBase") local pairs = pairs local ipairs = ipairs @@ -40,7 +41,7 @@ end -- Merge an instance of a buff, taking the highest value of each modifier local function mergeBuff(src, destTable, destKey) if not destTable[destKey] then - destTable[destKey] = new("ModList") + destTable[destKey] = new("ModList"):ModList() end local dest = destTable[destKey] for _, mod in ipairs(src) do @@ -1168,9 +1169,9 @@ function calcs.perform(env, skipEHP) -- Build minion skills for _, activeSkill in ipairs(env.player.activeSkillList) do - activeSkill.skillModList = new("ModList", activeSkill.baseSkillModList) + activeSkill.skillModList = new("ModList"):ModList(activeSkill.baseSkillModList) if activeSkill.minion then - activeSkill.minion.modDB = new("ModDB") + activeSkill.minion.modDB = new("ModDB"):ModDB() activeSkill.minion.modDB.actor = activeSkill.minion calcs.createMinionSkills(env, activeSkill) activeSkill.skillPartName = activeSkill.minion.mainSkill.activeEffect.grantedEffect.name @@ -1414,10 +1415,10 @@ function calcs.perform(env, skipEHP) local breakdown = nil if env.mode == "CALCS" then -- Initialise breakdown module - breakdown = LoadModule(calcs.breakdownModule, modDB, output, env.player) + breakdown = LoadModule(calcs.breakdownModule)(modDB, output, env.player) env.player.breakdown = breakdown if env.minion then - env.minion.breakdown = LoadModule(calcs.breakdownModule, env.minion.modDB, env.minion.output, env.minion) + env.minion.breakdown = LoadModule(calcs.breakdownModule)(env.minion.modDB, env.minion.output, env.minion) end end @@ -1616,13 +1617,13 @@ function calcs.perform(env, skipEHP) -- so utility flasks are grouped by base, unique flasks are grouped by name, and magic flasks by their modifiers if buffModList[1] then if not onlyMinion then - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(buffModList, effectMod) mergeBuff(srcList, flaskBuffs, baseName) mergeBuff(srcList, flaskBuffsPerBase[item.baseName], baseName) end if (not onlyRecovery or checkNonRecoveryFlasksForMinions) and (flasksApplyToMinion or quickSilverAppliesToAllies or (nonUniqueFlasksApplyToMinion and item.rarity ~= "UNIQUE" and item.rarity ~= "RELIC")) then - srcList = new("ModList") + srcList = new("ModList"):ModList() srcList:ScaleAddList(buffModList, effectModNonPlayer) mergeBuff(srcList, flaskBuffsNonPlayer, baseName) mergeBuff(srcList, flaskBuffsPerBaseNonPlayer[item.baseName], baseName) @@ -1741,7 +1742,7 @@ function calcs.perform(env, skipEHP) end if modList[1] then - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(modList, effectMod) local key if item.rarity == "UNIQUE" or item.rarity == "RELIC" then @@ -1988,8 +1989,8 @@ function calcs.perform(env, skipEHP) minionCurses.limit = modData.value + 1 break elseif modData.name == "AllyModifier" and modData.type == "LIST" then - buffs["Spectre"] = buffs["Spectre"] or new("ModList") - minionBuffs["Spectre"] = minionBuffs["Spectre"] or new("ModList") + buffs["Spectre"] = buffs["Spectre"] or new("ModList"):ModList() + minionBuffs["Spectre"] = minionBuffs["Spectre"] or new("ModList"):ModList() for _, modValue in pairs(modData.value) do local copyModValue = copyTable(modValue) copyModValue.source = "Spectre:"..spectreData.name @@ -1997,14 +1998,14 @@ function calcs.perform(env, skipEHP) t_insert(buffs["Spectre"], copyModValue) end elseif modData.name == "MinionModifier" and modData.type == "LIST" then - minionBuffs["Spectre"] = minionBuffs["Spectre"] or new("ModList") + minionBuffs["Spectre"] = minionBuffs["Spectre"] or new("ModList"):ModList() for _, modValue in pairs(modData.value) do local copyModValue = copyTable(modValue) copyModValue.source = "Spectre:"..spectreData.name t_insert(minionBuffs["Spectre"], copyModValue) end elseif modData.name == "PlayerModifier" and modData.type == "LIST" then - buffs["Spectre"] = buffs["Spectre"] or new("ModList") + buffs["Spectre"] = buffs["Spectre"] or new("ModList"):ModList() for _, modValue in pairs(modData.value) do local copyModValue = copyTable(modValue) copyModValue.source = "Spectre:"..spectreData.name @@ -2232,7 +2233,7 @@ function calcs.perform(env, skipEHP) modDB.conditions["AffectedBy"..buff.name:sub(6):gsub(" ","")] = true end modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(buff.modList, mult) srcList:ScaleAddList(extraAuraModList, mult) mergeBuff(srcList, buffs, buff.name) @@ -2247,7 +2248,7 @@ function calcs.perform(env, skipEHP) activeSkill.minionBuffSkill = true env.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true env.minion.modDB.conditions["AffectedByAura"] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(buff.modList, mult) srcList:ScaleAddList(extraAuraModList, mult) mergeBuff(srcList, minionBuffs, buff.name) @@ -2354,7 +2355,7 @@ function calcs.perform(env, skipEHP) activeSkill.debuffSkill = true enemyDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() local mult = 1 local extraAuraModList = { } if buff.type == "AuraDebuff" then @@ -2384,7 +2385,7 @@ function calcs.perform(env, skipEHP) t_insert(newModList, mod) end -- A full modlist causes issues with copy table for mine auras - --local newModList = new("ModList") + --local newModList = new("ModList"):ModList() --newModList:AddList(buff.modList) --newModList:AddList(extraAuraModList) buffExports["Aura"][buff.name..(buffExports["Aura"][buff.name] and "_Debuff" or "")] = { effectMult = mult, modList = newModList } @@ -2492,7 +2493,7 @@ function calcs.perform(env, skipEHP) activeSkill.minionBuffSkill = true env.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true env.minion.modDB.conditions["AffectedByLink"] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() inc = inc + env.minion.modDB:Sum("INC", nil, "BuffEffectOnSelf", "LinkEffectOnSelf") more = more * env.minion.modDB:More(nil, "BuffEffectOnSelf", "LinkEffectOnSelf") mult = (1 + inc / 100) * more @@ -2617,7 +2618,7 @@ function calcs.perform(env, skipEHP) modDB.conditions["AffectedBy"..buff.name:sub(6):gsub(" ","")] = true end modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(buff.modList, mult) srcList:ScaleAddList(extraAuraModList, mult) setSpectreSource(srcList, buff.name) @@ -2632,7 +2633,7 @@ function calcs.perform(env, skipEHP) activeMinionSkill.minionBuffSkill = true env.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true env.minion.modDB.conditions["AffectedByAura"] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(buff.modList, mult) srcList:ScaleAddList(extraAuraModList, mult) setSpectreSource(srcList, buff.name) @@ -2715,7 +2716,7 @@ function calcs.perform(env, skipEHP) end if env.mode_effective and stackCount > 0 then activeMinionSkill.debuffSkill = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() local mult = 1 if buff.type == "AuraDebuff" then mult = 0 @@ -2819,7 +2820,7 @@ function calcs.perform(env, skipEHP) if not enemyDB.conditions["AffectedBy"..auraNameCompressed] then enemyDB.conditions["AffectedBy"..auraNameCompressed] = true modDB.conditions["AffectedBy"..auraNameCompressed] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(aura.modList, aura.effectMult / 100) mergeBuff(srcList, debuffs, auraName) end @@ -2831,7 +2832,7 @@ function calcs.perform(env, skipEHP) if not enemyDB.conditions["AffectedBy"..auraNameCompressed] then enemyDB.conditions["AffectedBy"..auraNameCompressed] = true modDB.conditions["AffectedBy"..auraNameCompressed] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(aura.modList, aura.effectMult / 100) mergeBuff(srcList, debuffs, auraName) end @@ -2844,7 +2845,7 @@ function calcs.perform(env, skipEHP) if not modDB.conditions["AffectedBy"..warcryNameCompressed] then modDB.conditions["AffectedByWarcry"] = true modDB.conditions["AffectedBy"..warcryNameCompressed] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() for _, warcryBuff in ipairs(warcry.modList) do srcList:ScaleAddList({warcryBuff}, (warcry.effectMult or 100) / 100 * (warcryBuff[1].warcryPowerBonus or 1)) end @@ -2867,7 +2868,7 @@ function calcs.perform(env, skipEHP) if not modDB.conditions["AffectedBy"..linkNameCompressed] then modDB.conditions["AffectedByLink"] = true modDB.conditions["AffectedBy"..linkNameCompressed] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(link.modList, (link.effectMult or 100) / 100) mergeBuff(srcList, buffs, linkName) end @@ -2889,7 +2890,7 @@ function calcs.perform(env, skipEHP) -- Check for extra curses for dest, modDB in pairs({[curses] = modDB, [minionCurses] = env.minion and env.minion.modDB}) do for _, value in ipairs(modDB:List(nil, "ExtraCurse")) do - local gemModList = new("ModList") + local gemModList = new("ModList"):ModList() local grantedEffect = env.data.skills[value.skillId] if grantedEffect then calcs.mergeSkillInstanceMods(env, gemModList, { @@ -2941,7 +2942,7 @@ function calcs.perform(env, skipEHP) local newCurse = { name = curseName, priority = 0, - modList = new("ModList") + modList = new("ModList"):ModList() } local mult = curse.effectMult / 100 if curse.isMark then diff --git a/src/Modules/CalcPerform.lua.rej b/src/Modules/CalcPerform.lua.rej new file mode 100644 index 0000000000..958448753f --- /dev/null +++ b/src/Modules/CalcPerform.lua.rej @@ -0,0 +1,290 @@ +diff a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua (rejected hunks) +@@ -1719,7 +1720,7 @@ function calcs.perform(env, skipEHP) + mergeBuff(srcList, flaskBuffsNonUtility, key) + end + if (not onlyRecovery or checkNonRecoveryFlasksForMinions) and (flasksApplyToMinion or quickSilverAppliesToAllies or (nonUniqueFlasksApplyToMinion and item.rarity ~= "UNIQUE" and item.rarity ~= "RELIC")) then +- srcList = new("ModList") ++ srcList = new("ModList"):ModList() + srcList:ScaleAddList(modList, effectModNonPlayer) + mergeBuff(srcList, flaskBuffsNonPlayer, key) + mergeBuff(srcList, flaskBuffsPerBaseNonPlayer[item.baseName], key) +@@ -1841,14 +1842,14 @@ function calcs.perform(env, skipEHP) + + -- same deal as flasks, go look at the comment there + if buffModList[1] then +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + srcList:ScaleAddList(buffModList, effectMod) + mergeBuff(srcList, tinctureBuffs, baseName) + mergeBuff(srcList, tinctureBuffsPerBase[item.baseName], baseName) + end + + if modList[1] then +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + srcList:ScaleAddList(modList, effectMod) + local key + if item.rarity == "UNIQUE" or item.rarity == "RELIC" then +@@ -2270,7 +2271,7 @@ function calcs.perform(env, skipEHP) + if not buff.applyNotPlayer then + activeSkill.buffSkill = true + modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + local inc = modStore:Sum("INC", skillCfg, "BuffEffect", "BuffEffectOnSelf", "BuffEffectOnPlayer") + skillModList:Sum("INC", skillCfg, buff.name:gsub(" ", "").."Effect") + local more = modStore:More(skillCfg, "BuffEffect", "BuffEffectOnSelf") + srcList:ScaleAddList(buff.modList, (1 + inc / 100) * more) +@@ -2282,7 +2283,7 @@ function calcs.perform(env, skipEHP) + if env.minion and not env.minion.hostile and (buff.applyMinions or buff.applyAllies or skillModList:Flag(nil, "BuffAppliesToAllies")) then + activeSkill.minionBuffSkill = true + env.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + local inc = modStore:Sum("INC", skillCfg, "BuffEffect") + env.minion.modDB:Sum("INC", nil, "BuffEffectOnSelf") + local more = modStore:More(skillCfg, "BuffEffect") * env.minion.modDB:More(nil, "BuffEffectOnSelf") + srcList:ScaleAddList(buff.modList, (1 + inc / 100) * more) +@@ -2301,7 +2302,7 @@ function calcs.perform(env, skipEHP) + local modStore = buff.activeSkillBuff and skillModList or modDB + if not buff.applyNotPlayer then + activeSkill.buffSkill = true +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + local inc = modStore:Sum("INC", skillCfg, "BuffEffect", "BuffEffectOnSelf", "BuffEffectOnPlayer") + local more = modStore:More(skillCfg, "BuffEffect", "BuffEffectOnSelf") + srcList:ScaleAddList(buff.modList, (1 + inc / 100) * more) +@@ -2334,12 +2335,12 @@ function calcs.perform(env, skipEHP) + local cooldownOverride = modStore:Override(skillCfg, "CooldownRecovery") + local actual_cooldown = cooldownOverride or (activeSkill.skillData.cooldown + modStore:Sum("BASE", skillCfg, "CooldownRecovery")) / calcLib.mod(modStore, skillCfg, "CooldownRecovery") + local uptime = modDB:Flag(nil, "Condition:WarcryMaxHit") and 1 or m_min(full_duration / actual_cooldown, 1) +- local extraWarcryModList = activeSkill.activeEffect.grantedEffect.name == "Rallying Cry" and new("ModList") or {} ++ local extraWarcryModList = activeSkill.activeEffect.grantedEffect.name == "Rallying Cry" and new("ModList"):ModList() or {} + if not modDB:Flag(nil, "CannotGainWarcryBuffs") then + if not buff.applyNotPlayer then + activeSkill.buffSkill = true + modDB.conditions["AffectedBy"..warcryName] = true +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + local inc = modStore:Sum("INC", skillCfg, "BuffEffect", "BuffEffectOnSelf", "BuffEffectOnPlayer") + local more = modStore:More(skillCfg, "BuffEffect", "BuffEffectOnSelf") + for _, warcryBuff in ipairs(buff.modList) do +@@ -2352,7 +2353,7 @@ function calcs.perform(env, skipEHP) + if env.minion then + activeSkill.minionBuffSkill = true + env.minion.modDB.conditions["AffectedBy"..warcryName] = true +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + local inc = skillModList:Sum("INC", skillCfg, "BuffEffect") + env.minion.modDB:Sum("INC", skillCfg, "BuffEffectOnSelf") + local more = skillModList:More(skillCfg, "BuffEffect") * env.minion.modDB:More(skillCfg, "BuffEffectOnSelf") + for _, warcryBuff in ipairs(buff.modList) do +@@ -2380,7 +2381,7 @@ function calcs.perform(env, skipEHP) + mergeBuff(srcList, minionBuffs, buff.name) + end + if partyTabEnableExportBuffs then +- local newModList = new("ModList") ++ local newModList = new("ModList"):ModList() + local inc = skillModList:Sum("INC", skillCfg, "BuffEffect") + local more = skillModList:More(skillCfg, "BuffEffect") + newModList:AddList(buff.modList) +@@ -2441,7 +2442,7 @@ function calcs.perform(env, skipEHP) + local inc = skillModList:Sum("INC", skillCfg, "AuraEffect", "BuffEffect") + local more = skillModList:More(skillCfg, "AuraEffect", "BuffEffect") + local mult = (1 + inc / 100) * more +- local newModList = new("ModList") ++ local newModList = new("ModList"):ModList() + newModList:AddList(buff.modList) + newModList:AddList(extraAuraModList) + if buffExports["Aura"][buff.name] then +@@ -2450,7 +2451,7 @@ function calcs.perform(env, skipEHP) + buffExports["Aura"][buff.name] = { effectMult = mult, modList = newModList } + if modDB:Flag(nil, "AurasAffectEnemies") and not activeSkill.skillModList:Flag(skillCfg, "SelfAurasAffectYouAndLinkedTarget") then + local newModList = {} +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + for _, mod in ipairs(buff.modList) do + t_insert(newModList, mod) + end +@@ -2468,7 +2469,7 @@ function calcs.perform(env, skipEHP) + env.player.mainSkill.skillModList.conditions["AffectedBy"..buff.name:gsub(" ","")] = true + env.player.mainSkill.skillModList.conditions["AffectedByAura"] = true + +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + local inc = skillModList:Sum("INC", skillCfg, "AuraEffect", "BuffEffect", "AuraBuffEffect") + local more = skillModList:More(skillCfg, "AuraEffect", "BuffEffect", "AuraBuffEffect") + local lists = {extraAuraModList, buff.modList} +@@ -2521,7 +2522,7 @@ function calcs.perform(env, skipEHP) + local inc = skillModList:Sum("INC", skillCfg, "AuraEffect", "BuffEffect", "DebuffEffect") + local more = skillModList:More(skillCfg, "AuraEffect", "BuffEffect", "DebuffEffect") + mult = (1 + inc / 100) * more +- local newModList = new("ModList") ++ local newModList = new("ModList"):ModList() + newModList:AddList(extraAuraModList) + buffExports["Aura"][buff.name..(buffExports["Aura"][buff.name] and "_Debuff" or "")] = { effectMult = mult, modList = newModList } + if allyBuffs["AuraDebuff"] and allyBuffs["AuraDebuff"][buff.name] and allyBuffs["AuraDebuff"][buff.name].effectMult / 100 > mult then +@@ -2631,21 +2632,21 @@ function calcs.perform(env, skipEHP) + mult = (1 + inc / 100) * more + end + if buff.type == "Curse" then +- curse.modList = new("ModList") ++ curse.modList = new("ModList"):ModList() + curse.modList:ScaleAddList(buff.modList, mult) + if partyTabEnableExportBuffs then + buffExports["Curse"][buff.name] = { isMark = curse.isMark, effectMult = curse.isMark and mult or (1 + inc / 100) * moreMark, modList = buff.modList } + end + else + -- Curse applies a buff; scale by curse effect, then buff effect +- local temp = new("ModList") ++ local temp = new("ModList"):ModList() + temp:ScaleAddList(buff.modList, mult) +- curse.buffModList = new("ModList") ++ curse.buffModList = new("ModList"):ModList() + local buffInc = modDB:Sum("INC", skillCfg, "BuffEffectOnSelf") + local buffMore = modDB:More(skillCfg, "BuffEffectOnSelf") + curse.buffModList:ScaleAddList(temp, (1 + buffInc / 100) * buffMore) + if env.minion then +- curse.minionBuffModList = new("ModList") ++ curse.minionBuffModList = new("ModList"):ModList() + local buffInc = env.minion.modDB:Sum("INC", nil, "BuffEffectOnSelf") + local buffMore = env.minion.modDB:More(nil, "BuffEffectOnSelf") + curse.minionBuffModList:ScaleAddList(temp, (1 + buffInc / 100) * buffMore) +@@ -2680,7 +2681,7 @@ function calcs.perform(env, skipEHP) + local more = skillModList:More(skillCfg, "LinkEffect", "BuffEffect") + local mult = (1 + inc / 100) * more + if partyTabEnableExportBuffs then +- local newModList = new("ModList") ++ local newModList = new("ModList"):ModList() + newModList:AddList(buff.modList) + newModList:AddList(extraLinkModList) + buffExports["Link"][buff.name] = { effectMult = mult, modList = newModList } +@@ -2744,7 +2745,7 @@ function calcs.perform(env, skipEHP) + if buff.applyAllies then + activeMinionSkill.buffSkill = true + modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + local inc = modStore:Sum("INC", skillCfg, "BuffEffect", "BuffEffectOnPlayer") + modDB:Sum("INC", nil, "BuffEffectOnSelf") + local more = modStore:More(skillCfg, "BuffEffect", "BuffEffectOnPlayer") * modDB:More(nil, "BuffEffectOnSelf") + srcList:ScaleAddList(buff.modList, (1 + inc / 100) * more) +@@ -2768,7 +2769,7 @@ function calcs.perform(env, skipEHP) + else + activeSkill.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true + end +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + local inc = modStore:Sum("INC", skillCfg, "BuffEffect", (env.minion == castingMinion) and "BuffEffectOnSelf" or nil) + local more = modStore:More(skillCfg, "BuffEffect", (env.minion == castingMinion) and "BuffEffectOnSelf" or nil) + srcList:ScaleAddList(buff.modList, (1 + inc / 100) * more) +@@ -2833,7 +2834,7 @@ function calcs.perform(env, skipEHP) + local inc = skillModList:Sum("INC", skillCfg, "AuraEffect", "BuffEffect") + local more = skillModList:More(skillCfg, "AuraEffect", "BuffEffect") + local mult = (1 + inc / 100) * more +- local newModList = new("ModList") ++ local newModList = new("ModList"):ModList() + newModList:AddList(buff.modList) + newModList:AddList(extraAuraModList) + setSpectreSource(newModList, buff.name) +@@ -2846,7 +2847,7 @@ function calcs.perform(env, skipEHP) + env.player.mainSkill.skillModList.conditions["AffectedBy"..buff.name:gsub(" ","")] = true + env.player.mainSkill.skillModList.conditions["AffectedByAura"] = true + +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + local inc = skillModList:Sum("INC", skillCfg, "AuraEffect", "BuffEffect", "AuraBuffEffect") + local more = skillModList:More(skillCfg, "AuraEffect", "BuffEffect", "AuraBuffEffect") + local lists = {extraAuraModList, buff.modList} +@@ -2882,7 +2883,7 @@ function calcs.perform(env, skipEHP) + } + local inc = skillModList:Sum("INC", skillCfg, "CurseEffect") + enemyDB:Sum("INC", nil, "CurseEffectOnSelf") + local more = skillModList:More(skillCfg, "CurseEffect") * enemyDB:More(nil, "CurseEffectOnSelf") +- curse.modList = new("ModList") ++ curse.modList = new("ModList"):ModList() + curse.modList:ScaleAddList(buff.modList, (1 + inc / 100) * more) + t_insert(minionCurses, curse) + end +@@ -2943,14 +2944,14 @@ function calcs.perform(env, skipEHP) + modDB.conditions["AffectedBy"..buffName:gsub(" ","")] = true + local inc = modDB:Sum("INC", nil, "BuffEffectOnSelf", "AuraEffectOnSelf") + local more = modDB:More(nil, "BuffEffectOnSelf", "AuraEffectOnSelf") +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + srcList:ScaleAddList(buff.modList, (buff.effectMult + inc) / 100 * more) + mergeBuff(srcList, buffs, buffName) + if env.minion then + env.minion.modDB.conditions["AffectedBy"..buffName:gsub(" ","")] = true + local inc = env.minion.modDB:Sum("INC", nil, "BuffEffectOnSelf", "AuraEffectOnSelf") + local more = env.minion.modDB:More(nil, "BuffEffectOnSelf", "AuraEffectOnSelf") +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + srcList:ScaleAddList(buff.modList, (buff.effectMult + inc) / 100 * more) + mergeBuff(srcList, minionBuffs, buffName) + end +@@ -2963,14 +2964,14 @@ function calcs.perform(env, skipEHP) + if not modDB:Flag(nil, "AlliesAurasCannotAffectSelf") and not modDB.conditions["AffectedBy"..auraNameCompressed] then + modDB.conditions["AffectedByAura"] = true + modDB.conditions["AffectedBy"..auraNameCompressed] = true +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + srcList:ScaleAddList(aura.modList, aura.effectMult / 100) + mergeBuff(srcList, buffs, auraName) + end + if env.minion and not env.minion.modDB.conditions["AffectedBy"..auraNameCompressed] then + env.minion.modDB.conditions["AffectedByAura"] = true + env.minion.modDB.conditions["AffectedBy"..auraNameCompressed] = true +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + srcList:ScaleAddList(aura.modList, aura.effectMult / 100) + mergeBuff(srcList, minionBuffs, auraName) + end +@@ -2983,14 +2984,14 @@ function calcs.perform(env, skipEHP) + modDB.conditions["AffectedByAura"] = true + modDB.conditions["AffectedBy"..auraName:sub(6):gsub(" ","")] = true + modDB.conditions["AffectedBy"..auraNameCompressed] = true +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + srcList:ScaleAddList(aura.modList, aura.effectMult / 100) + mergeBuff(srcList, buffs, auraName) + end + if env.minion and not env.minion.modDB.conditions["AffectedBy"..auraNameCompressed] then + env.minion.modDB.conditions["AffectedByAura"] = true + env.minion.modDB.conditions["AffectedBy"..auraNameCompressed] = true +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + srcList:ScaleAddList(aura.modList, aura.effectMult / 100) + mergeBuff(srcList, minionBuffs, auraName) + end +@@ -3038,7 +3039,7 @@ function calcs.perform(env, skipEHP) + if env.minion and not env.minion.modDB.conditions["AffectedBy"..warcryNameCompressed] then + env.minion.modDB.conditions["AffectedByWarcry"] = true + env.minion.modDB.conditions["AffectedBy"..warcryNameCompressed] = true +- local srcList = new("ModList") ++ local srcList = new("ModList"):ModList() + for _, warcryBuff in ipairs(warcry.modList) do + srcList:ScaleAddList({warcryBuff}, (warcry.effectMult or 100) / 100 * (warcryBuff[1].warcryPowerBonus or 1)) + end +@@ -3121,7 +3122,7 @@ function calcs.perform(env, skipEHP) + fromPlayer = (dest == curses), + priority = determineCursePriority(grantedEffect.name), + } +- curse.modList = new("ModList") ++ curse.modList = new("ModList"):ModList() + curse.modList:ScaleAddList(curseModList, (1 + enemyDB:Sum("INC", nil, "CurseEffectOnSelf") / 100) * enemyDB:More(nil, "CurseEffectOnSelf")) + t_insert(dest, curse) + end +@@ -3329,7 +3330,7 @@ function calcs.perform(env, skipEHP) + if modDB:Flag(nil, "ManaIncreasedByOvercappedLightningRes") then + -- Calculate resistances for ManaIncreasedByOvercappedLightningRes without mutating conversion mods on the player ModDB. + local tempResistActor = { +- modDB = new("ModDB", modDB), ++ modDB = new("ModDB"):ModDB(modDB), + output = output, + activeSkillList = env.player.activeSkillList, + enemy = env.player.enemy, +@@ -3349,7 +3350,7 @@ function calcs.perform(env, skipEHP) + end + + -- Check for extra auras +- buffExports["Aura"]["extraAura"] = { effectMult = 1, modList = new("ModList") } ++ buffExports["Aura"]["extraAura"] = { effectMult = 1, modList = new("ModList"):ModList() } + for _, value in ipairs(modDB:List(nil, "ExtraAura")) do + local modList = { value.mod } + if not value.onlyAllies and not (value.fromAllies and modDB:Flag(nil, "AlliesAurasCannotAffectSelf")) then diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index 5ba727778c..1023ec9dc0 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -3,7 +3,8 @@ -- Module: Calc Setup -- Initialises the environment for calculations. -- -local calcs = ... +---@class Calcs +local calcs = require("Modules.CalcBase") local pairs = pairs local ipairs = ipairs @@ -225,7 +226,7 @@ function calcs.buildModListForNode(env, node, incSmallPassiveSkill, includeKeyst -- Apply effect scaling local scale = calcLib.mod(modList, nil, "PassiveSkillEffect") if scale ~= 1 then - local scaledList = new("ModList") + local scaledList = new("ModList"):ModList() scaledList:ScaleAddList(modList, scale) modList = scaledList end @@ -1227,7 +1228,7 @@ function calcs.initEnv(build, mode, override, specEnv) local info = env.data.weaponTypeInfo[type] if info and type ~= "Bow" then local name = info.oneHand and "Energy Blade One Handed" or "Energy Blade Two Handed" - local item = new("Item") + local item = new("Item"):Item() item.name = name item.base = data.itemBases[name] item.baseName = name @@ -1256,7 +1257,7 @@ function calcs.initEnv(build, mode, override, specEnv) end elseif slotName == "Weapon 1" and item.name == "The Iron Mass, Gladius" then -- Special handling for The Iron Mass - env.theIronMass = new("ModList") + env.theIronMass = new("ModList"):ModList() for _, mod in ipairs(srcList) do -- Filter out mods that apply to socketed gems, or which add supports local add = true @@ -1274,7 +1275,7 @@ function calcs.initEnv(build, mode, override, specEnv) end elseif slotName == "Weapon 1" and item.grantedSkills[1] and item.grantedSkills[1].skillId == "UniqueAnimateWeapon" then -- Special handling for The Dancing Dervish - env.weaponModList1 = new("ModList") + env.weaponModList1 = new("ModList"):ModList() for _, mod in ipairs(srcList) do -- Filter out mods that apply to socketed gems, or which add supports local add = true diff --git a/src/Modules/CalcSetup.lua.rej b/src/Modules/CalcSetup.lua.rej new file mode 100644 index 0000000000..503daa66dd --- /dev/null +++ b/src/Modules/CalcSetup.lua.rej @@ -0,0 +1,96 @@ +diff a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua (rejected hunks) +@@ -114,7 +115,7 @@ function calcs.initModDB(env, modDB) + end + + function calcs.buildModListForNode(env, node) +- local modList = new("ModList") ++ local modList = new("ModList"):ModList() + if node.type == "Keystone" then + modList:AddMod(node.keystoneMod) + else +@@ -178,7 +179,7 @@ function calcs.buildModListForNodeList(env, nodeList, finishJewels) + end + + -- Add node modifiers +- local modList = new("ModList") ++ local modList = new("ModList"):ModList() + local explodeSources = {} + for _, node in pairs(nodeList) do + local nodeModList, explode = calcs.buildModListForNode(env, node) +@@ -400,11 +401,11 @@ function calcs.initEnv(build, mode, override, specEnv) + env.override = override + env.classId = env.spec.curClassId + +- modDB = new("ModDB") ++ modDB = new("ModDB"):ModDB() + env.modDB = modDB +- enemyDB = new("ModDB") ++ enemyDB = new("ModDB"):ModDB() + env.enemyDB = enemyDB +- env.itemModDB = new("ModDB") ++ env.itemModDB = new("ModDB"):ModDB() + + env.enemyLevel = build.configTab.enemyLevel or m_min(data.misc.MaxEnemyLevel, build.characterLevel) + +@@ -997,7 +998,7 @@ function calcs.initEnv(build, mode, override, specEnv) + end + if item.type == "Shield" and env.allocNodes[45175] and env.allocNodes[45175].dn == "Necromantic Aegis" then + -- Special handling for Necromantic Aegis +- env.aegisModList = new("ModList") ++ env.aegisModList = new("ModList"):ModList() + for _, mod in ipairs(srcList) do + -- Filter out mods that apply to socketed gems, or which add supports + local add = true +@@ -1127,25 +1128,25 @@ function calcs.initEnv(build, mode, override, specEnv) + local widowHailMod= (1 + (items["Weapon 1"] and items["Weapon 1"].baseModList:Sum("INC", nil, "EffectOfBonusesFromQuiver") + env.initialNodeModDB:Sum("INC", nil, "EffectOfBonusesFromQuiver") or 100) / 100) + scale = scale * widowHailMod + env.modDB:NewMod("WidowHailMultiplier", "BASE", widowHailMod, "Widowhail") +- local combinedList = new("ModList") ++ local combinedList = new("ModList"):ModList() + for _, mod in ipairs(srcList) do + combinedList:MergeMod(mod) + end + env.itemModDB:ScaleAddList(combinedList, scale) + elseif env.modDB.multipliers["Corrupted" .. item.rarity:gsub("(%a)(%u*)", function(a, b) return a..string.lower(b) end) .. "JewelEffect"] and item.type == "Jewel" and item.corrupted and slot.nodeId and item.base.subType ~= "Charm" and not env.spec.nodes[slot.nodeId].containJewelSocket then + scale = scale + env.modDB.multipliers["Corrupted" .. item.rarity:gsub("(%a)(%u*)", function(a, b) return a..string.lower(b) end) .. "JewelEffect"] +- local combinedList = new("ModList") ++ local combinedList = new("ModList"):ModList() + for _, mod in ipairs(srcList) do + combinedList:MergeMod(mod) + end + env.itemModDB:ScaleAddList(combinedList, scale) + elseif item.type == "Gloves" and calcLib.mod(env.initialNodeModDB, nil, "EffectOfBonusesFromGloves") ~=1 then + scale = calcLib.mod(env.initialNodeModDB, nil, "EffectOfBonusesFromGloves") - 1 +- local combinedList = new("ModList") ++ local combinedList = new("ModList"):ModList() + for _, mod in ipairs(srcList) do + combinedList:MergeMod(mod) + end +- local scaledList = new("ModList") ++ local scaledList = new("ModList"):ModList() + scaledList:ScaleAddList(combinedList, scale) + for _, mod in ipairs(scaledList) do + combinedList:MergeMod(mod, true) +@@ -1153,11 +1154,11 @@ function calcs.initEnv(build, mode, override, specEnv) + env.itemModDB:AddList(combinedList) + elseif item.type == "Boots" and calcLib.mod(env.initialNodeModDB, nil, "EffectOfBonusesFromBoots") ~= 1 then + scale = calcLib.mod(env.initialNodeModDB, nil, "EffectOfBonusesFromBoots") - 1 +- local combinedList = new("ModList") ++ local combinedList = new("ModList"):ModList() + for _, mod in ipairs(srcList) do + combinedList:MergeMod(mod) + end +- local scaledList = new("ModList") ++ local scaledList = new("ModList"):ModList() + scaledList:ScaleAddList(combinedList, scale) + for _, mod in ipairs(scaledList) do + combinedList:MergeMod(mod, true) +@@ -1322,7 +1323,7 @@ function calcs.initEnv(build, mode, override, specEnv) + end + if not override or (override and not override.extraJewelFuncs) then + override = override or {} +- override.extraJewelFuncs = new("ModList") ++ override.extraJewelFuncs = new("ModList"):ModList() + override.extraJewelFuncs.actor = env.player + for _, mod in ipairs(env.modDB:Tabulate("LIST", nil, "ExtraJewelFunc")) do + override.extraJewelFuncs:AddMod(mod.mod) diff --git a/src/Modules/CalcTools.lua b/src/Modules/CalcTools.lua index a44b7b6f33..93d0f4903e 100644 --- a/src/Modules/CalcTools.lua +++ b/src/Modules/CalcTools.lua @@ -208,7 +208,7 @@ end --- Correct the tags on conversion with multipliers so they carry over correctly --- @param mod table --- @param multiplier number ---- @param minionMods bool @convert ActorConditions pointing at parent to normal Conditions +--- @param minionMods boolean @convert ActorConditions pointing at parent to normal Conditions --- @return table @converted multipliers function calcLib.getConvertedModTags(mod, multiplier, minionMods) local modifiers = { } @@ -248,7 +248,7 @@ end --- Use getGameIdFromGemName to get gameId from the gemName and passed in type. Return true if they're the same and not nil --- @param gemName string ---- @param type string +--- @param typeName string --- @param dropVaal boolean --- @return boolean function calcLib.isGemIdSame(gemName, typeName, dropVaal) diff --git a/src/Modules/CalcTriggers.lua b/src/Modules/CalcTriggers.lua index 5dafee82a0..52dfac2e5c 100644 --- a/src/Modules/CalcTriggers.lua +++ b/src/Modules/CalcTriggers.lua @@ -4,8 +4,9 @@ -- Performs trigger rate calculations -- -local calcs = ... -local pairs = pairs +---@class Calcs +local calcs = require("Modules.CalcBase") + local ipairs = ipairs local t_insert = table.insert local t_remove = table.remove diff --git a/src/Modules/Calcs.lua b/src/Modules/Calcs.lua index f8cf2e8278..b2a4a0c791 100644 --- a/src/Modules/Calcs.lua +++ b/src/Modules/Calcs.lua @@ -10,15 +10,16 @@ local s_format = string.format local m_min = math.min local m_ceil = math.ceil -local calcs = { } +---@class Calcs +local calcs = require("Modules.CalcBase") calcs.breakdownModule = "Modules/CalcBreakdown" -LoadModule("Modules/CalcSetup", calcs) -LoadModule("Modules/CalcPerform", calcs) -LoadModule("Modules/CalcActiveSkill", calcs) -LoadModule("Modules/CalcDefence", calcs) -LoadModule("Modules/CalcOffence", calcs) -LoadModule("Modules/CalcTriggers", calcs) -LoadModule("Modules/CalcMirages.lua", calcs) +require("Modules.CalcSetup") +require("Modules.CalcPerform") +require("Modules.CalcActiveSkill") +require("Modules.CalcDefence") +require("Modules.CalcOffence") +require("Modules.CalcTriggers") +require("Modules.CalcMirages") -- Get the average value of a table -- note this is unused function math.average(t) diff --git a/src/Modules/Common.lua b/src/Modules/Common.lua index 6fd1ec57a9..45b39ce78c 100644 --- a/src/Modules/Common.lua +++ b/src/Modules/Common.lua @@ -1,3 +1,4 @@ +---@diagnostic disable: lowercase-global -- Path of Building -- -- Module: Common @@ -68,13 +69,17 @@ end local function getClass(className) local class = common.classes[className] if not class then - LoadModule("Classes/"..className) + LoadModule("Classes/" .. className) class = common.classes[className] - assert(class, "Class '"..className.."' not defined in class file") + assert(class, "Class '" .. className .. "' not defined in class file") end return class end --- newClass(""[, ""[, "" ...]], constructorFunc) + +---@generic T +---@param className `T` +---@param ... string parent class names +---@return T function newClass(className, ...) local class = { } common.classes[className] = class @@ -87,11 +92,10 @@ function newClass(className, ...) end class._className = className local numVarArg = select("#", ...) - class._constructor = select(numVarArg, ...) - if numVarArg > 1 then + if numVarArg > 0 then -- Build list of parent classes class._parents = { } - for i = 1, numVarArg - 1 do + for i = 1, numVarArg do class._parents[i] = getClass(select(i, ...)) end -- Build list of all classes directly or indirectly inherited by this class @@ -112,9 +116,39 @@ function newClass(className, ...) end return class end -function new(className, ...) + +---@generic T +---@param className `T` +---@param extraArg nil Never pass extra parameters. Defined purely to guard against old syntax. +---@return T +function new(className, extraArg) + if extraArg then + local line = s_format( + "Extra argument passed to new() during creation of class %s. Extra arguments are not allowed.\nAre you perhaps trying to pass constructor arguments here?", + className) + error(line) + end local class = getClass(className) - local object = setmetatable({ }, class) + -- protect against calling new("Foo") without calling :Foo() + local object + if class[className] then + if not rawget(class, "_unconstructedMeta") then + class._unconstructedMeta = { + __index = function(obj, key) + if key == className then + setmetatable(obj, class) + return class[className] + end + error(s_format( + "Object of class '%s' was used before it was constructed (accessed '%s'). Did you forget to call new(\"%s\"):%s()?", + className, tostring(key), className, className)) + end, + } + end + object = setmetatable({}, class._unconstructedMeta) + else + object = setmetatable({}, class) + end object.Object = object if class._parents then -- Add parent and superparent class proxies @@ -130,30 +164,43 @@ function new(className, ...) end end, __newindex = object, - __call = function(...) - if not parent._constructor then + __call = function(_, self, ...) + if not parent[parent._className] then error("Parent class '"..parent._className.."' of class '"..class._className.."' has no constructor") end if object._parentInit[parent] then error("Parent class '"..parent._className.."' of class '"..class._className.."' has already been initialised") end - parent._constructor(...) + if self ~= object then + error(string.format("Parent class %s constructor of class %s was not provided self. Are you perhaps calling it with self.%s instead of self:%s?", parent._className, className, parent._className, parent._className)) + end + parent[parent._className](self, ...) object._parentInit[parent] = true end, } object[parent._className] = setmetatable(proxyMeta, proxyMeta) end end - if class._constructor then - class._constructor(object, ...) - end - if class._parents then - -- Check that the constructors for all parent and superparent classes have been called - for parent in pairs(class._superParents) do - if parent._constructor and not object._parentInit[parent] then - error("Parent class '"..parent._className.."' of class '"..className.."' must be initialised") + + if class[className] and not rawget(class, "_constructorInitialised") then + local originalFunc = class[className] + class[className] = function(self, ...) + local ret = originalFunc(self, ...) + if class._parents then + -- Check that the constructors for all parent and superparent classes have been called + for parent in pairs(class._superParents) do + if parent[parent._className] and not self._parentInit[parent] then + error("Parent class '" .. + parent._className .. "' of class '" .. className .. "' must be initialised") + end + end + end + if not ret then + error(string.format("Class %s constructor did not return a value", className)) end + return ret end + class._constructorInitialised = true end return object end @@ -418,6 +465,10 @@ function writeLuaTable(out, t, indent) end -- Make a copy of a table and all subtables +---@generic T +---@param tbl T +---@param noRecurse boolean? +---@return T copy Note that this type can be misleading if noRecurse is set to true. Type hint explicitly if necessary. function copyTable(tbl, noRecurse) local out = {} for k, v in pairs(tbl) do @@ -466,11 +517,11 @@ function mergeDB(srcDB, modDB) end function specCopy(env) - local modDB = new("ModDB") + local modDB = new("ModDB"):ModDB() modDB:AddDB(env.modDB) modDB.conditions = copyTable(env.modDB.conditions) modDB.multipliers = copyTable(env.modDB.multipliers) - local enemyDB = new("ModDB") + local enemyDB = new("ModDB"):ModDB() if env.enemyDB then enemyDB:AddDB(env.enemyDB) enemyDB.conditions = copyTable(env.enemyDB.conditions) @@ -478,7 +529,7 @@ function specCopy(env) end local minionDB = nil if env.minion then - minionDB = new("ModDB") + minionDB = new("ModDB"):ModDB() minionDB:AddDB(env.minion.modDB) minionDB.conditions = copyTable(env.minion.modDB.conditions) minionDB.multipliers = copyTable(env.minion.modDB.multipliers) diff --git a/src/Modules/ConfigOptions.lua.rej b/src/Modules/ConfigOptions.lua.rej new file mode 100644 index 0000000000..200443bd8d --- /dev/null +++ b/src/Modules/ConfigOptions.lua.rej @@ -0,0 +1,10 @@ +diff a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua (rejected hunks) +@@ -119,7 +119,7 @@ local function mapAffixDropDownFunction(val, modList, enemyModList, build) + local affixData = data.mapMods.AffixData[val] or {} + if affixData.apply then + if affixData.type == "check" then +- affixData.apply(var, (1 + (build.configTab.input['multiplierMapModEffect'] or 0)/100), modList, enemyModList) ++ affixData.apply(val, (1 + (build.configTab.input['multiplierMapModEffect'] or 0) / 100), modList, enemyModList) + elseif affixData.type == "list" then + affixData.apply(4 - (build.configTab.varControls['multiplierMapModTier'].selIndex or 1), (1 + (build.configTab.input['multiplierMapModEffect'] or 0)/100), affixData.values, modList, enemyModList) + elseif affixData.type == "count" then diff --git a/src/Modules/Data.lua b/src/Modules/Data.lua index 56d22b13aa..51627672ee 100644 --- a/src/Modules/Data.lua +++ b/src/Modules/Data.lua @@ -863,8 +863,9 @@ do UberEvasionMean = 100 + uberEvasionTotal / uberCount } - data.bossSkills, data.bossSkillsList = LoadModule("Data/BossSkills") - + local bossSkillData = LoadModule("Data/BossSkills") + data.bossSkills = bossSkillData.bossSkills + data.bossSkillsList = bossSkillData.bossSkillsList data.enemyIsBossTooltip = [[Bosses' damage is monster damage scaled to an average damage of their attacks This is divided by 4.40 to represent 4 damage types + some (40% as much) ^xD02090chaos ^7Fill in the exact damage numbers if more precision is needed @@ -896,7 +897,7 @@ end -- Load skills data.skills = { } -data.skillStatMap = LoadModule("Data/SkillStatMap", makeSkillMod, makeFlagMod, makeSkillDataMod) +data.skillStatMap = LoadModule("Data/SkillStatMap")(makeSkillMod, makeFlagMod, makeSkillDataMod) data.skillStatMapMeta = { __index = function(t, key) local map = data.skillStatMap[key] @@ -911,7 +912,7 @@ data.skillStatMapMeta = { end } for _, type in pairs(skillTypes) do - LoadModule("Data/Skills/"..type, data.skills, makeSkillMod, makeFlagMod, makeSkillDataMod) + LoadModule("Data/Skills/" .. type)(data.skills, makeSkillMod, makeFlagMod, makeSkillDataMod) end for skillId, grantedEffect in pairs(data.skills) do grantedEffect.name = sanitiseText(grantedEffect.name) @@ -1056,10 +1057,8 @@ for id, gem in pairs(toAddGems) do end -- Load minions -data.minions = { } -LoadModule("Data/Minions", data.minions, makeSkillMod, makeFlagMod) -data.spectres = { } -LoadModule("Data/Spectres", data.spectres, makeSkillMod, makeFlagMod) +data.minions = LoadModule("Data/Minions")(makeSkillMod, makeFlagMod) +data.spectres = LoadModule("Data/Spectres")(makeSkillMod, makeFlagMod) for name, spectre in pairs(data.spectres) do spectre.limit = "ActiveSpectreLimit" data.minions[name] = spectre diff --git a/src/Modules/Data.lua.rej b/src/Modules/Data.lua.rej new file mode 100644 index 0000000000..971145f313 --- /dev/null +++ b/src/Modules/Data.lua.rej @@ -0,0 +1,63 @@ +diff a/src/Modules/Data.lua b/src/Modules/Data.lua (rejected hunks) +@@ -103,10 +103,16 @@ end + -- Remaining Item Data and uniques + ---------------------------------------- + ++---@diagnostic disable-next-line: lowercase-global ++---@class Data : MiscDataExport ++---@field bosses BossData + data = { } + + -- Misc data tables +-LoadModule("Data/Misc", data) ++local miscData = LoadModule("Data/Misc") ++for k, v in pairs(miscData) do ++ data[k] = v ++end + + ---@alias TransformFunc fun(in: number|string): (number|string)? + ---@class StatTable +@@ -636,9 +642,6 @@ data.enchantmentSource = { + { name = "NORMAL", label = "Normal Labyrinth" }, + } + +--- Misc data tables +-LoadModule("Data/Misc", data) +- + -- Stat descriptions + data.describeStats = LoadModule("Modules/StatDescriber") + +@@ -928,7 +931,9 @@ data.timelessJewelAdditions = 337 -- #legionAdditions + data.nodeIDList = LoadModule("Data/TimelessJewelData/NodeIndexMapping") + data.abyssNotableNames = LoadModule("Data/TimelessJewelData/AbyssNotableNames") + data.timelessJewelLUTs = { } +-data.readLUT, data.repairLUTs = LoadModule("Modules/DataLegionLookUpTableHelper") ++local helperMod = LoadModule("Modules/DataLegionLookUpTableHelper") ++data.readLUT = helperMod.readLUT ++data.repairLUTs = helperMod.repairLUTs + data.readAbyssJewelLUT, data.resolveAbyssJewelComponent, data.getAbyssJewelComponentRoll = LoadModule("Modules/DataAbyssJewelLookUpTableHelper") + + -- this runs if the "size" key is missing from nodeIDList and attempts to rebuild all jewel LUTs and the nodeIDList +@@ -938,10 +943,9 @@ if not data.nodeIDList.size and launch.devMode then + end + + -- Load bosses +-do +- data.bosses = { } +- LoadModule("Data/Bosses", data.bosses) +- ++do ++ ---@class BossData ++ data.bosses = LoadModule("Data/Bosses") + local count, uberCount = 0, 0 + local armourTotal, evasionTotal = 0, 0 + local uberArmourTotal, uberEvasionTotal = 0, 0 +@@ -1211,7 +1214,7 @@ end + ---@type table + data.itemBases = { } + for _, type in pairs(itemTypes) do +- LoadModule("Data/Bases/"..type, data.itemBases) ++ LoadModule("Data/Bases/" .. type)(data.itemBases) + end + + ---@class ItemBaseEntry diff --git a/src/Modules/DataLegionLookUpTableHelper.lua b/src/Modules/DataLegionLookUpTableHelper.lua index cf9cf29a63..2f346810a0 100644 --- a/src/Modules/DataLegionLookUpTableHelper.lua +++ b/src/Modules/DataLegionLookUpTableHelper.lua @@ -313,4 +313,4 @@ local function readLUT(seed, nodeID, jewelType) return { } end -return readLUT, repairLUTs \ No newline at end of file +return { readLUT = readLUT, repairLUTs = repairLUTs } diff --git a/src/Modules/Main.lua b/src/Modules/Main.lua index 98d4a786c0..90eefc2f7b 100644 --- a/src/Modules/Main.lua +++ b/src/Modules/Main.lua @@ -47,7 +47,10 @@ end local tempTable1 = { } local tempTable2 = { } -main = new("ControlHost") +---@diagnostic disable-next-line: lowercase-global +---@class Main : ControlHost +---@field allowTreeDownload? boolean +main = new("ControlHost"):ControlHost() function main:Init() self:DetectUnicodeSupport() @@ -126,7 +129,9 @@ function main:Init() self.saveNewModCache = true else -- Load mod cache - LoadModule("Data/ModCache", modLib.parseModCache) + for k, v in pairs(LoadModule("Data/ModCache")) do + modLib.parseModCache[k] = v + end end --[[ this does not work properly anymore see PR #7675 @@ -138,6 +143,7 @@ function main:Init() self.inputEvents = { } self.tooltipLines = { } + ---@type table self.tree = { } self:LoadTree(latestTreeVersion) @@ -195,23 +201,23 @@ function main:Init() self.defaultItemAffixQuality = saved end - self.anchorMain = new("Control", nil, {4, 0, 0, 0}) + self.anchorMain = new("Control"):Control(nil, {4, 0, 0, 0}) self.anchorMain.y = function() return self.screenH - 4 end - self.controls.options = new("ButtonControl", {"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {0, 0, 68, 20}, "Options", function() + self.controls.options = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {0, 0, 68, 20}, "Options", function() self:OpenOptionsPopup() end) - self.controls.about = new("ButtonControl", {"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {72, 0, 68, 20}, "About", function() + self.controls.about = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {72, 0, 68, 20}, "About", function() self:OpenAboutPopup() end) - self.controls.applyUpdate = new("ButtonControl", {"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {0, -24, 140, 20}, "^x50E050Update Ready", function() + self.controls.applyUpdate = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {0, -24, 140, 20}, "^x50E050Update Ready", function() self:OpenUpdatePopup() end) self.controls.applyUpdate.shown = function() return launch.updateAvailable and launch.updateAvailable ~= "none" end - self.controls.checkUpdate = new("ButtonControl", {"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {0, -24, 140, 20}, "", function() + self.controls.checkUpdate = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {0, -24, 140, 20}, "", function() launch:CheckForUpdate() end) self.controls.checkUpdate.shown = function() @@ -294,7 +300,7 @@ end function main:SaveModCache() -- Update mod cache local out = io.open("Data/ModCache.lua", "w") - out:write('local c=...') + out:write('local c = {}\n') for line, dat in pairsSortByKey(modLib.parseModCache) do if not dat[1] or not dat[1][1] or (dat[1][1].name ~= "JewelFunc" and dat[1][1].name ~= "ExtraJewelFunc") then out:write('c["', line:gsub("\n","\\n"), '"]={') @@ -310,9 +316,12 @@ function main:SaveModCache() end end end + out:write('return c\n') out:close() end +---@param treeVersion string +---@return PassiveTree? function main:LoadTree(treeVersion) if self.tree[treeVersion] then data.setJewelRadiiGlobally(treeVersion) @@ -320,7 +329,7 @@ function main:LoadTree(treeVersion) elseif isValueInTable(treeVersionList, treeVersion) then data.setJewelRadiiGlobally(treeVersion) --ConPrintf("[main:LoadTree] - Lazy Loading Tree " .. treeVersion) - self.tree[treeVersion] = new("PassiveTree", treeVersion) + self.tree[treeVersion] = new("PassiveTree"):PassiveTree(treeVersion) return self.tree[treeVersion] end return nil @@ -706,7 +715,7 @@ function main:LoadSharedItems() rawItem.raw = subChild end end - local newItem = new("Item", rawItem.raw) + local newItem = new("Item"):Item(rawItem.raw) t_insert(self.sharedItemList, newItem) elseif child.elem == "ItemSet" then local sharedItemSet = { title = child.attrib.title, slots = { } } @@ -718,7 +727,7 @@ function main:LoadSharedItems() rawItem.raw = subChild end end - local newItem = new("Item", rawItem.raw) + local newItem = new("Item"):Item(rawItem.raw) sharedItemSet.slots[grandChild.attrib.slotName] = newItem end end @@ -815,14 +824,14 @@ function main:OpenPathPopup(invalidPath, errMsg, ignoreBuild) local controls = { } local defaultLabelPlacementX = 8 - controls.label = new("LabelControl", { "TOPLEFT", nil, "TOPLEFT" }, { defaultLabelPlacementX, 20, 206, 16 }, function() + controls.label = new("LabelControl"):LabelControl({ "TOPLEFT", nil, "TOPLEFT" }, { defaultLabelPlacementX, 20, 206, 16 }, function() return "^7User settings path cannot be loaded: ".. errMsg .. "\nCurrent Path: "..invalidPath:gsub("?", "^1?^7").."/Path of Building/".. "\nIf this location is managed by OneDrive, navigate to that folder and manually try" .. "\nto open Settings.xml in a text editor before re-opening Path of Building" .. "\nOtherwise, specify a new location for your Settings.xml:" end) - controls.userPath = new("EditControl", { "TOPLEFT", controls.label, "TOPLEFT" }, { 0, 60, 206, 20 }, invalidPath, nil, nil, nil, function(buf) + controls.userPath = new("EditControl"):EditControl({ "TOPLEFT", controls.label, "TOPLEFT" }, { 0, 60, 206, 20 }, invalidPath, nil, nil, nil, function(buf) invalidPath = sanitiseText(buf) if not invalidPath:match("?") then controls.save.enabled = true @@ -830,7 +839,7 @@ function main:OpenPathPopup(invalidPath, errMsg, ignoreBuild) controls.save.enabled = false end end) - controls.save = new("ButtonControl", { "TOPLEFT", controls.userPath, "TOPLEFT" }, { 0, 26, 206, 20 }, "Save", function() + controls.save = new("ButtonControl"):ButtonControl({ "TOPLEFT", controls.userPath, "TOPLEFT" }, { 0, 26, 206, 20 }, "Save", function() local res, msg = MakeDir(controls.userPath.buf) if not res and msg ~= "No error" then self:OpenMessagePopup("Error", "Couldn't create '"..controls.userPath.buf.."' : "..msg) @@ -840,7 +849,7 @@ function main:OpenPathPopup(invalidPath, errMsg, ignoreBuild) end end) controls.save.enabled = false - controls.cancel = new("ButtonControl", nil, { 0, 0, 0, 0 }, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, { 0, 0, 0, 0 }, "Cancel", function() -- Do nothing, require user to enter a location end) self:OpenPopup(600, 150, "Change Settings Path", controls, "save", nil, "cancel") @@ -906,7 +915,7 @@ function main:OpenOptionsPopup(savedState) local popupWidth = useTwoColumns and columnWidth * 2 or columnWidth -- Scrollbar anchor - controls.sectionAnchor = new("Control", { "TOPLEFT", nil, "TOPLEFT" }, { 0, 0, popupWidth, 0 }) + controls.sectionAnchor = new("Control"):Control({ "TOPLEFT", nil, "TOPLEFT" }, { 0, 0, popupWidth, 0 }) -- local func to make a new line with a heightModifier local function nextRow(heightModifier) @@ -918,9 +927,9 @@ function main:OpenOptionsPopup(savedState) -- local func to make a new section header local function drawSectionHeader(id, title, omitHorizontalLine) local headerBGColor ={ .6, .6, .6} - controls["section-"..id .. "-bg"] = new("RectangleOutlineControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + scrollBarWidth + 8, currentY, columnWidth - (scrollBarWidth * 2) - 17, 26 }, headerBGColor, 1) + controls["section-"..id .. "-bg"] = new("RectangleOutlineControl"):RectangleOutlineControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + scrollBarWidth + 8, currentY, columnWidth - (scrollBarWidth * 2) - 17, 26 }, headerBGColor, 1) nextRow(.2) - controls["section-"..id .. "-label"] = new("LabelControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + columnWidth / 2 - 60, currentY, 0, 16 }, "^7" .. title) + controls["section-"..id .. "-label"] = new("LabelControl"):LabelControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + columnWidth / 2 - 60, currentY, 0, 16 }, "^7" .. title) nextRow(1.5) end @@ -929,25 +938,25 @@ function main:OpenOptionsPopup(savedState) drawSectionHeader("app", "Application options") - controls.connectionProtocol = new("DropDownControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 100, 18 }, { + controls.connectionProtocol = new("DropDownControl"):DropDownControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 100, 18 }, { { label = "Auto", protocol = 0 }, { label = "IPv4", protocol = 1 }, { label = "IPv6", protocol = 2 }, }, function(index, value) self.connectionProtocol = value.protocol end) - controls.connectionProtocolLabel = new("LabelControl", { "RIGHT", controls.connectionProtocol, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Connection Protocol:") + controls.connectionProtocolLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.connectionProtocol, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Connection Protocol:") controls.connectionProtocol.tooltipText = "Changes which protocol is used when downloading updates and importing builds." controls.connectionProtocol:SelByValue(launch.connectionProtocol, "protocol") nextRow() - controls.proxyType = new("DropDownControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 80, 18 }, { + controls.proxyType = new("DropDownControl"):DropDownControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 80, 18 }, { { label = "HTTP", scheme = "http" }, { label = "SOCKS", scheme = "socks5" }, { label = "SOCKS5H", scheme = "socks5h" }, }) - controls.proxyLabel = new("LabelControl", { "RIGHT", controls.proxyType, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Proxy server:") - controls.proxyURL = new("EditControl", { "LEFT", controls.proxyType, "RIGHT" }, { 4, 0, 206, 18 }) + controls.proxyLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.proxyType, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Proxy server:") + controls.proxyURL = new("EditControl"):EditControl({ "LEFT", controls.proxyType, "RIGHT" }, { 4, 0, 206, 18 }) if launch.proxyURL then local scheme, url = launch.proxyURL:match("(%w+)://(.+)") @@ -956,7 +965,7 @@ function main:OpenOptionsPopup(savedState) end nextRow() - controls.dpiScaleOverride = new("DropDownControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 150, 18 }, { + controls.dpiScaleOverride = new("DropDownControl"):DropDownControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 150, 18 }, { { label = "Use system default", percent = 0 }, { label = "100%", percent = 100 }, { label = "125%", percent = 125 }, @@ -1167,7 +1176,7 @@ function main:OpenOptionsPopup(savedState) if launch.devMode then nextRow() - controls.disableDevAutoSave = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Disable Dev AutoSave:", function(state) + controls.disableDevAutoSave = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Disable Dev AutoSave:", function(state) self.disableDevAutoSave = state end) controls.disableDevAutoSave.tooltipText = "Do not Autosave builds while on Dev branch" @@ -1190,7 +1199,7 @@ function main:OpenOptionsPopup(savedState) nextRow(1.5) -- lock the Save/Cancel buttons to the bottom so they don't scroll away - controls.save = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, {-45, -10, 80, 20}, "Save", function() + controls.save = new("ButtonControl"):ButtonControl({ "BOTTOM", nil, "BOTTOM" }, {-45, -10, 80, 20}, "Save", function() launch.connectionProtocol = tonumber(self.connectionProtocol) if controls.proxyURL.buf:match("%w") then launch.proxyURL = controls.proxyType.list[controls.proxyType.selIndex].scheme .. "://" .. controls.proxyURL.buf @@ -1215,7 +1224,7 @@ function main:OpenOptionsPopup(savedState) main:ClosePopup() main:SaveSettings() end) - controls.cancel = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, {45, -10, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl({ "BOTTOM", nil, "BOTTOM" }, {45, -10, 80, 20}, "Cancel", function() self.nodePowerTheme = savedState.nodePowerTheme self.colorPositive = savedState.colorPositive updateColorCode("POSITIVE", self.colorPositive) @@ -1252,7 +1261,7 @@ function main:OpenOptionsPopup(savedState) local popupHeight = useScrollBar and (self.screenH - 20) or currentY + 30 if useScrollBar then - controls.scrollBar = new("ScrollBarControl", {"TOPRIGHT", nil, "TOPRIGHT"}, {-2, 25, scrollBarWidth, popupHeight - 65}, 50, "VERTICAL", true) + controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({"TOPRIGHT", nil, "TOPRIGHT"}, {-2, 25, scrollBarWidth, popupHeight - 65}, 50, "VERTICAL", true) controls.scrollBar:SetContentDimension(currentY, popupHeight - 65) end @@ -1346,15 +1355,15 @@ function main:OpenUpdatePopup() end end local controls = { } - controls.changeLog = new("TextListControl", nil, {0, 20, 780, 542}, nil, changeList) - controls.update = new("ButtonControl", nil, {-45, 570, 80, 20}, "Update", function() + controls.changeLog = new("TextListControl"):TextListControl(nil, {0, 20, 780, 542}, nil, changeList) + controls.update = new("ButtonControl"):ButtonControl(nil, {-45, 570, 80, 20}, "Update", function() self:ClosePopup() local ret = self:CallMode("CanExit", "UPDATE") if ret == nil or ret == true then launch:ApplyUpdate(launch.updateAvailable) end end) - controls.cancel = new("ButtonControl", nil, {45, 570, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 570, 80, 20}, "Cancel", function() self:ClosePopup() end) self:OpenPopup(800, 600, "Update Available", controls) @@ -1648,7 +1657,7 @@ function main:CopyFolder(srcName, dstName) end function main:OpenPopup(width, height, title, controls, enterControl, defaultControl, escapeControl, scrollBarFunc, resizeFunc) - local popup = new("PopupDialog", width, height, title, controls, enterControl, defaultControl, escapeControl, scrollBarFunc, resizeFunc) + local popup = new("PopupDialog"):PopupDialog(width, height, title, controls, enterControl, defaultControl, escapeControl, scrollBarFunc, resizeFunc) t_insert(self.popups, 1, popup) return popup end @@ -1661,10 +1670,10 @@ function main:OpenMessagePopup(title, msg) local controls = { } local numMsgLines = 0 for line in string.gmatch(msg .. "\n", "([^\n]*)\n") do - t_insert(controls, new("LabelControl", nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) + t_insert(controls, new("LabelControl"):LabelControl(nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) numMsgLines = numMsgLines + 1 end - controls.close = new("ButtonControl", nil, {0, 40 + numMsgLines * 16, 80, 20}, "Ok", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {0, 40 + numMsgLines * 16, 80, 20}, "Ok", function() main:ClosePopup() end) return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "close") @@ -1674,7 +1683,7 @@ function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm, extraLabel, local controls = { } local numMsgLines = 0 for line in string.gmatch(msg .. "\n", "([^\n]*)\n") do - t_insert(controls, new("LabelControl", nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) + t_insert(controls, new("LabelControl"):LabelControl(nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) numMsgLines = numMsgLines + 1 end local confirmWidth = m_max(80, DrawStringWidth(16, "VAR", confirmLabel) + 10) @@ -1689,7 +1698,7 @@ function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm, extraLabel, local buttonY = 40 + numMsgLines * 16 local function placeButton(width, label, onClick, isConfirm) local centerX = leftEdge + width / 2 - local ctrl = new("ButtonControl", nil, {centerX, buttonY, width, 20}, label, function() + local ctrl = new("ButtonControl"):ButtonControl(nil, {centerX, buttonY, width, 20}, label, function() main:ClosePopup() onClick() end) @@ -1706,11 +1715,11 @@ function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm, extraLabel, return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, totalWidth + 40), 70 + numMsgLines * 16, title, controls, "confirm") else -- Two button layout (original) - controls.confirm = new("ButtonControl", nil, {-5 - m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, confirmLabel, function() + controls.confirm = new("ButtonControl"):ButtonControl(nil, {-5 - m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, confirmLabel, function() main:ClosePopup() onConfirm() end) - t_insert(controls, new("ButtonControl", nil, {5 + m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, "Cancel", function() + t_insert(controls, new("ButtonControl"):ButtonControl(nil, {5 + m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, "Cancel", function() main:ClosePopup() end)) return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "confirm") @@ -1719,11 +1728,11 @@ end function main:OpenNewFolderPopup(path, onClose) local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter folder name:") - controls.edit = new("EditControl", nil, {0, 40, 350, 20}, nil, nil, "\\/:%*%?\"<>|%c", 100, function(buf) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter folder name:") + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, nil, nil, "\\/:%*%?\"<>|%c", 100, function(buf) controls.create.enabled = buf:match("%S") end) - controls.create = new("ButtonControl", nil, {-45, 70, 80, 20}, "Create", function() + controls.create = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Create", function() local newFolderName = controls.edit.buf local res, msg = MakeDir(path..newFolderName) if not res then @@ -1736,7 +1745,7 @@ function main:OpenNewFolderPopup(path, onClose) main:ClosePopup() end) controls.create.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() if onClose then onClose() end @@ -1761,14 +1770,14 @@ function main:OpenCloudErrorPopup(fileName) local controls = { } local numMsgLines = 0 for line in string.gmatch(msg .. "\n", "([^\n]*)\n") do - t_insert(controls, new("LabelControl", nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) + t_insert(controls, new("LabelControl"):LabelControl(nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) numMsgLines = numMsgLines + 1 end - controls.help = new("ButtonControl", nil, {-55, 40 + numMsgLines * 16, 80, 20}, "Help (web)", function() + controls.help = new("ButtonControl"):ButtonControl(nil, {-55, 40 + numMsgLines * 16, 80, 20}, "Help (web)", function() OpenURL(url) end) controls.help.tooltipText = url - controls.close = new("ButtonControl", nil, {55, 40 + numMsgLines * 16, 80, 20}, "Ok", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {55, 40 + numMsgLines * 16, 80, 20}, "Ok", function() main:ClosePopup() end) return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "close") diff --git a/src/Modules/Main.lua.rej b/src/Modules/Main.lua.rej new file mode 100644 index 0000000000..72feb93f08 --- /dev/null +++ b/src/Modules/Main.lua.rej @@ -0,0 +1,9 @@ +diff a/src/Modules/Main.lua b/src/Modules/Main.lua (rejected hunks) +@@ -1067,7 +1067,6 @@ function main:OpenOptionsPopup(savedState) + end) + controls.showThousandsSeparators.state = self.showThousandsSeparators + +- nextRow() + nextRow() + controls.useCompactValues = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Compact large numbers (e.g. 12.3K):", function(state) + self.useCompactValues = state diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 52fa3b4316..98c7b13406 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -2254,6 +2254,7 @@ local explodeFunc = function(chance, amount, type, ...) end -- List of special modifiers +---@type table local specialModList = { -- Explode mods ["enemies you kill have a (%d+)%% chance to explode, dealing a (.+) of their maximum life as (.+) damage"] = function(chance, _, amount, type) -- Obliteration, Unspeakable Gifts (chaos cluster), synth implicit mod, current crusader body mod, Ngamahu Warmonger tattoo @@ -6491,6 +6492,11 @@ end -- Scan a line for the earliest and longest match from the pattern list -- If a match is found, returns the corresponding value from the pattern list, plus the remainder of the line and a table of captures +---@generic T +---@param line string +---@param patternList table +---@param plain? boolean +---@return T?, string, string[]? local function scan(line, patternList, plain) local bestIndex, bestEndIndex local bestPattern = "" @@ -6634,6 +6640,7 @@ local function parseMod(line, order) modFlag, line = scan(line, modFlagList, true) -- Find modifier value and type according to form + ---@type string|number|table local modValue = tonumber(formCap[1]) or formCap[1] local modType = "BASE" local modSuffix @@ -7166,7 +7173,7 @@ local jewelSelfUnallocFuncs = { ["Grants all bonuses of Unallocated Small Passive Skills in Radius"] = function(node, out, data) if node then if node.type == "Normal" then - data.modList = data.modList or new("ModList") + data.modList = data.modList or new("ModList"):ModList() -- Filter out "Condition:ConnectedTo" mods as these nodes are not technically allocated by this jewel func for _, mod in ipairs(out) do @@ -7303,23 +7310,26 @@ local unsupported = { } local count = 0 --local foo = io.open("../unsupported.txt", "w") --foo:close() -return function(line, isComb) - if not cache[line] then - local modList, extra = parseMod(line, 1) - if modList and extra then - modList, extra = parseMod(line, 2) - end - cache[line] = { modList, extra } - if foo and not isComb and not cache[line][1] then - local form = line:gsub("[%+%-]?%d+%.?%d*","{num}") - if not unsupported[form] then - unsupported[form] = true - count = count + 1 - foo = io.open("../unsupported.txt", "a+") - foo:write(count, ': ', form, (cache[line][2] and #cache[line][2] < #line and (' {' .. cache[line][2]).. '}') or "", '\n') - foo:close() +return { + parseMod = function(line, isComb) + if not cache[line] then + local modList, extra = parseMod(line, 1) + if modList and extra then + modList, extra = parseMod(line, 2) + end + cache[line] = { modList, extra } + if foo and not isComb and not cache[line][1] then + local form = line:gsub("[%+%-]?%d+%.?%d*", "{num}") + if not unsupported[form] then + unsupported[form] = true + count = count + 1 + foo = io.open("../unsupported.txt", "a+") + foo:write(count, ': ', form, (cache[line][2] and #cache[line][2] < #line and (' {' .. cache[line][2]) .. '}') or "", '\n') + foo:close() + end end end - end - return unpack(copyTable(cache[line])) -end, cache + return unpack(copyTable(cache[line])) + end, + parseModCache = cache +} diff --git a/src/Modules/ModParser.lua.rej b/src/Modules/ModParser.lua.rej new file mode 100644 index 0000000000..db292deac5 --- /dev/null +++ b/src/Modules/ModParser.lua.rej @@ -0,0 +1,10 @@ +diff a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua (rejected hunks) +@@ -6378,7 +6379,7 @@ local jewelSelfUnallocFuncs = { + ["Grants all bonuses of Unallocated Notable Passive Skills in Radius"] = function(node, out, data) + if node then + if node.type == "Notable" then +- data.modList = data.modList or new("ModList") ++ data.modList = data.modList or new("ModList"):ModList() + + -- Filter out "Condition:ConnectedTo" mods as these nodes are not technically allocated by this jewel func + for _, mod in ipairs(out) do diff --git a/src/Modules/ModTools.lua b/src/Modules/ModTools.lua index 049e9d58e5..ccbcd4da79 100644 --- a/src/Modules/ModTools.lua +++ b/src/Modules/ModTools.lua @@ -34,6 +34,7 @@ function modLib.createMod(modName, modType, modVal, ...) keywordFlags = select(3, ...) tagStart = 4 end + ---@class Mod return { name = modName, type = modType, @@ -44,8 +45,9 @@ function modLib.createMod(modName, modType, modVal, ...) select(tagStart, ...) } end - -modLib.parseMod, modLib.parseModCache = LoadModule("Modules/ModParser", launch) +local modParserModule = LoadModule("Modules/ModParser") +modLib.parseMod = modParserModule.parseMod +modLib.parseModCache = modParserModule.parseModCache function modLib.parseTags(line) if not line or line == "-" then diff --git a/src/Modules/ModTools.lua.rej b/src/Modules/ModTools.lua.rej new file mode 100644 index 0000000000..ec634a0b3f --- /dev/null +++ b/src/Modules/ModTools.lua.rej @@ -0,0 +1,19 @@ +diff a/src/Modules/ModTools.lua b/src/Modules/ModTools.lua (rejected hunks) +@@ -15,8 +15,17 @@ local s_format = string.format + local band = bit.band + local bor = bit.bor + ++---@diagnostic disable-next-line: lowercase-global + modLib = { } + ++--- "Flag" is only used with CanNotUseItem ++---@alias Doubled ["MORE", "OVERRIDE"] ++---@alias NumericModTypes "INC"|"MORE"|"BASE"|"OVERRIDE"|"MAX"|"CHANCE"|"DUMMY"|"Flag"|"MIN"|Doubled ++ ++---@overload fun(modName: string, modType: NumericModTypes, modVal?: number) ++---@overload fun(modName: string, modType: "FLAG", modVal: boolean) ++---@overload fun(modName: string, modType: "LIST", modVal: any[]|any) ++---@return Mod + function modLib.createMod(modName, modType, modVal, ...) + local flags = 0 + local keywordFlags = 0 diff --git a/src/UpdateApply.lua b/src/UpdateApply.lua index 6abaf71ea7..1032a9b149 100644 --- a/src/UpdateApply.lua +++ b/src/UpdateApply.lua @@ -4,44 +4,57 @@ -- Module: Update Apply -- Applies updates. -- -local opFileName = ... -print("Applying update...") -local opFile = io.open(opFileName, "r") -if not opFile then - print("No operations list present.\n") - return -end -local lines = { } -for line in opFile:lines() do - table.insert(lines, line) -end -opFile:close() -os.remove(opFileName) -for _, line in ipairs(lines) do - local op, args = line:match("(%a+) ?(.*)") - if op == "move" then - local src, dst = args:match('"(.*)" "(.*)"') - dst = dst:gsub("{space}", " ") - print("Updating '"..dst.."'") - local srcFile = io.open(src, "rb") - assert(srcFile, "couldn't open "..src) - local dstFile - while not dstFile do - dstFile = io.open(dst, "w+b") - end - if dstFile then - dstFile:write(srcFile:read("*a")) - dstFile:close() +---@param opFileName string +local function applyUpdate(opFileName) + print("Applying update...") + local opFile = io.open(opFileName, "r") + if not opFile then + print("No operations list present.\n") + return + end + local lines = {} + for line in opFile:lines() do + table.insert(lines, line) + end + opFile:close() + os.remove(opFileName) + for _, line in ipairs(lines) do + local op, args = line:match("(%a+) ?(.*)") + if op == "move" then + local src, dst = args:match('"(.*)" "(.*)"') + dst = dst:gsub("{space}", " ") + print("Updating '" .. dst .. "'") + local srcFile = io.open(src, "rb") + assert(srcFile, "couldn't open " .. src) + local dstFile + while not dstFile do + dstFile = io.open(dst, "w+b") + end + if dstFile then + dstFile:write(srcFile:read("*a")) + dstFile:close() + end + srcFile:close() + os.remove(src) + elseif op == "delete" then + local file = args:match('"(.*)"') + print("Deleting '" .. file .. "'") + os.remove(file) + elseif op == "start" then + local target = args:match('"(.*)"') + SpawnProcess(target) end - srcFile:close() - os.remove(src) - elseif op == "delete" then - local file = args:match('"(.*)"') - print("Deleting '"..file.."'") - os.remove(file) - elseif op == "start" then - local target = args:match('"(.*)"') - SpawnProcess(target) end end + +-- this file is used both as a module and as a script depending on the update +-- mode. basic mode will spawn a process, while normal mode will use this as a +-- module. + +local opFileName = ... +if opFileName then + return applyUpdate(opFileName) +end + +return applyUpdate diff --git a/src/_SimpleGraphic.def.lua b/src/_SimpleGraphic.def.lua new file mode 100644 index 0000000000..158ed456dc --- /dev/null +++ b/src/_SimpleGraphic.def.lua @@ -0,0 +1,516 @@ +--- this file defines function signatures for the runtime API, and is not meant +-- to be used directly. the function bodies here ARE NOT correct for regular +-- PoB use. they are implemented by SimpleGraphic, and are only correct for +-- headless mode, in which case this file IS executed. +---@meta + +---@alias Font "FIXED"|"VAR"|"VAR BOLD"|"FONTIN SC"|"FONTIN SC ITALIC"|"FONTIN"|"FONTIN ITALIC" + +---@param name string +---@param func? fun() +function SetCallback(name, func) + ---@diagnostic disable-next-line: undefined-global headless wrapper + __callbackTable__[name] = func +end + +---@param name string +---@return table +function GetCallback(name) + ---@diagnostic disable-next-line: undefined-global headless wrapper + return __callbackTable__[name] +end + +---@param object? table +function SetMainObject(object) + __mainObject__ = object +end + +---@class ImageHandle +local imageHandleClass = {} +imageHandleClass.__index = imageHandleClass + +---@return ImageHandle +function NewImageHandle() + return setmetatable({}, imageHandleClass) +end + +---@param fileName string +---@param ... "ASYNC"|"CLAMP"|"MIPMAP" +function imageHandleClass:Load(fileName, ...) + self.valid = true +end + +---@class ArtHandle +local artHandleClass = {} + +---@return integer width +---@return integer height +function artHandleClass:Size() end + +---@alias ArtFlag "CLAMP"|"MIPMAP"|"NEAREST" + +---@param art ArtHandle +---@param x1 integer +---@param y1 integer +---@param x2 integer +---@param y2 integer +---@param ... ArtFlag +function imageHandleClass:LoadArtRectangle(art, x1, y1, x2, y2, ...) end + +---@param art ArtHandle +---@param xC integer +---@param yC integer +---@param rMin integer +---@param rMax integer +---@param ... ArtFlag +function imageHandleClass:LoadArtArcBand(art, xC, yC, rMin, rMax, ...) end + +function imageHandleClass:Unload() + self.valid = false +end + +---@return boolean +function imageHandleClass:IsValid() + return self.valid +end + +---@return boolean +function imageHandleClass:IsLoading() + return false +end + +---@param priority number +function imageHandleClass:SetLoadingPriority(priority) end + +---@return integer width +---@return integer height +function imageHandleClass:ImageSize() + return 1, 1 +end + +---@param fileName string +---@return userdata +function NewArtHandle(fileName) end + +---@class TexHandle +local texHandleClass = {} + +---@class TextureInfo +---@field formatStr ""|"RGB"|"RGBA"|"BC1"|"BC7" +---@field width integer +---@field height integer +---@field layerCount integer +---@field mipCount integer +local textureInfoClass = {} + +---@class Texture +local Texture = {} + +---@return TexHandle +function Texture.new() end + +-- `gli::format` id, or a matching format string. see `core_tex_manipulation.cpp` +---@alias TextureFormat integer|"RGB"|"RGBA"|"BC1"|"BC7" + +---@param format TextureFormat +---@param width integer +---@param height integer +---@param layerCount integer +---@param mipCount integer +---@return boolean success +function texHandleClass:Allocate(format, width, height, layerCount, mipCount) end + +---@param fileName string +---@return boolean success +function texHandleClass:Load(fileName) end + +---@param fileName string +---@return boolean success +function texHandleClass:Save(fileName) end + +---@return TextureInfo +function texHandleClass:Info() end + +---@return boolean +function texHandleClass:IsValid() end + +---@param textures TexHandle[] +---@return boolean success +function texHandleClass:StackTextures(textures) end + +---@return integer width +---@return integer height +function GetScreenSize() + return 1920, 1080 +end + +---@return number +function GetScreenScale() + return 1 +end + +---@param red number +---@param green number +---@param blue number +---@param alpha? number +function SetClearColor(red, green, blue, alpha) end + +---@param layer? number +---@param subLayer? number +function SetDrawLayer(layer, subLayer) end + +---@return integer +function GetDrawLayer() end + +---@param x number +---@param y number +---@param width number +---@param height number +---@overload fun() +function SetViewport(x, y, width, height) end + +---@param mode ("ALPHA"|"PREALPHA"|"ADDITIVE") +function SetBlendMode(mode) end + +---@param r number +---@param g number +---@param b number +---@param a number? +function SetDrawColor(r, g, b, a) end + +---@param escapeStr string +function SetDrawColor(escapeStr) end + +---@return number r +---@return number g +---@return number b +---@return number a +function GetDrawColor() end + +---@param percent integer +function SetDPIScaleOverridePercent(percent) end + +---@return integer +function GetDPIScaleOverridePercent() + return 1 +end + +---@param imgHandle? ImageHandle +---@param left number +---@param top number +---@param width number +---@param height number +function DrawImage(imgHandle, left, top, width, height) end + +---@param imgHandle? ImageHandle +---@param left number +---@param top number +---@param width number +---@param height number +---@param tcLeft number +---@param tcTop number +---@param tcRight number +---@param tcBottom number +function DrawImage(imgHandle, left, top, width, height, tcLeft, tcTop, tcRight, tcBottom) end + +---@param imgHandle? ImageHandle +---@param left number +---@param top number +---@param width number +---@param height number +---@param stackIdx integer must be positive +---@param mask? integer must be positive +function DrawImage(imgHandle, left, top, width, height, tcLeft, tcTop, tcRight, tcBottom, stackIdx, mask) end + +---@param imgHandle? ImageHandle +---@param x1 number +---@param y1 number +---@param x2 number +---@param y2 number +---@param x3 number +---@param y3 number +---@param x4 number +---@param y4 number +function DrawImageQuad(imgHandle, x1, y1, x2, y2, x3, y3, x4, y4) end + +---@param imgHandle? ImageHandle +---@param x1 number +---@param y1 number +---@param x2 number +---@param y2 number +---@param x3 number +---@param y3 number +---@param x4 number +---@param s1 number +---@param t1 number +---@param s2 number +---@param t2 number +---@param s3 number +---@param t3 number +---@param s4 number +---@param t4 number +function DrawImageQuad(imgHandle, x1, y1, x2, y2, x3, y3, x4, y4, s1, t1, s2, t2, s3, t3, s4, t4) end + +---@param imgHandle? ImageHandle +---@param x1 number +---@param y1 number +---@param x2 number +---@param y2 number +---@param x3 number +---@param y3 number +---@param x4 number +---@param y4 number +---@param stackIdx integer? must be positive +---@param mask integer? must be positive +function DrawImageQuad(imgHandle, x1, y1, x2, y2, x3, y3, x4, y4, stackIdx, mask) end + +---@param left number +---@param top number +---@param align? ("LEFT"|"CENTER"|"RIGHT"|"CENTER_X"|"RIGHT_X") +---@param height number +---@param font Font +---@param text string +function DrawString(left, top, align, height, font, text) end + +---@param height number +---@param font Font +---@param text string +---@return integer physicalWidth +function DrawStringWidth(height, font, text) + return 1 +end + +---@param height number +---@param font Font +---@param text string +---@param cursorX number +---@param cursorY number +---@return integer +function DrawStringCursorIndex(height, font, text, cursorX, cursorY) + return 0 +end + +---@param text string +---@return string +function StripEscapes(text) + local s, _ = text:gsub("%^%d", ""):gsub("%^x%x%x%x%x%x%x", "") + return s +end + +---@return integer asyncCount +function GetAsyncCount() + return 0 +end + +---@param flag1 string +---@param ... string +function RenderInit(flag1, ...) end + +---@class FileSearchHandle +local fileSearchHandleClass = {} + +---@return boolean +function fileSearchHandleClass:NextFile() end + +---@return string +function fileSearchHandleClass:GetFileName() end + +---@return integer +function fileSearchHandleClass:GetFileSize() end + +---@return number +function fileSearchHandleClass:GetFileModifiedTime() end + +---@param spec string +---@param findDirectories? boolean +---@return FileSearchHandle +function NewFileSearch(spec, findDirectories) end + +---@param path string +---@return string? name +---@return string? version +---@return integer? status +function GetCloudProvider(path) + return nil, nil, nil +end + +---@param title string +function SetWindowTitle(title) end + +---@return number x +---@return number y +function GetCursorPos() + return 0, 0 +end + +---@param x number +---@param y number +function SetCursorPos(x, y) end + +---@param doShow boolean +function ShowCursor(doShow) end + +---@param keyName string cannot be empty or an unrecognised key name +function IsKeyDown(keyName) end + +---@param text string +function Copy(text) end + +---@return string? data +function Paste() end + +---@param data string +---@return string? compressedData +---@return string? errMsg +function Deflate(data) + return "" +end + +---@param data string +---@return string? data +---@return string? errMsg +function Inflate(data) + return "" +end + +---@return integer timeMillis +function GetTime() + return 0 +end + +---@return string scriptPath +---@return string? scriptFallback +---@return string? errMsg +function GetScriptPath() + return "" +end + +---@return string runtimePath +---@return string? fallbackPath +---@return string? errMsg +function GetRuntimePath() + return "" +end + +---@return string? userPath +---@return string? invalidPath +---@return string? errMsg +function GetUserPath() + return "" +end + +---@param path string +---@return true|([nil, string]) true on success, or nil and error message +function MakeDir(path) end + +---@param path string +---@param recurse? boolean +function RemoveDir(path, recurse) end + +---@param path string +function SetWorkDir(path) end + +---@return string +function GetWorkDir() + return "" +end + +---@alias SubScriptID userdata + +---@param scriptText string +---@param funcList string +---@param subList string +---@param ... nil|boolean|number|string +---@return SubScriptID +function LaunchSubScript(scriptText, funcList, subList, ...) end + +---@param ssID SubScriptID +function AbortSubScript(ssID) end + +---@param ssID SubScriptID +---@return boolean isRunning +function IsSubScriptRunning(ssID) end + +---@param name string +---@param ... any +---@return unknown retVal use ---@module "name" instead +function LoadModule(name, ...) + if not name:match("%.lua") then + name = name .. ".lua" + end + local func, err = loadfile(name) + if func then + return func(...) + else + error("LoadModule() error loading '" .. name .. "': " .. err) + end +end + +---@param modName string +---@param ... any +---@return unknown retVal use ---@module "name" instead +function PLoadModule(modName, ...) + if not modName:match("%.lua") then + modName = modName .. ".lua" + end + local func, err = loadfile(modName) + if func then + return PCall(func, ...) + else + error("PLoadModule() error loading '" .. modName .. "': " .. err) + end +end + +---@generic T +---@generic R +---@param func fun(...: T): R +---@param ... any +---@return any? err +---@return R? retVal +function PCall(func, ...) + local ret = { pcall(func, ...) } + if ret[1] then + table.remove(ret, 1) + ---@diagnostic disable-next-line: redundant-return-value headless wrapper + return nil, unpack(ret) + else + return ret[2] + end +end + +--- A function similar to C `printf` which prints to the console (`^~` on US layout) of the program. +---@param fmt string +---@param ... any +function ConPrintf(fmt, ...) + -- Optional + print(string.format(fmt, ...)) +end + +---@param tbl table +---@param noRecurse any converted to boolean +function ConPrintTable(tbl, noRecurse) end + +---@param cmd string +function ConExecute(cmd) end + +function ConClear() end + +---@param cmdName string +---@param args string? +function SpawnProcess(cmdName, args) end + +---@param url string +---@return string? error +function OpenURL(url) end + +---@param isEnabled boolean +function SetProfiling(isEnabled) end + +function TakeScreenshot() end + +function Restart() end + +---@param msg string? +function Exit(msg) end + +function SetForeground() end