Skip to content

Latest commit

 

History

History
473 lines (379 loc) · 33.2 KB

File metadata and controls

473 lines (379 loc) · 33.2 KB

Contributing to Path of Building

Table of contents

  1. Reporting bugs
  2. Requesting features
  3. Contributing code
  4. Setting up a development installation
  5. Setting up a development environment
  6. Keeping your fork up to date
  7. Path of Building development tutorials
  8. Exporting GGPK data from Path of Exile
  9. Using the inbuilt profiler

Reporting bugs

Before creating an issue:

  • Check that the bug hasn't been reported in an existing issue. View similar issues to the left of the submit button.
  • Make sure you are running the latest version of the program. Click "Check for Update" in the bottom left corner.
  • If you've found an issue with offence or defence calculations, make sure you check the breakdown for that calculation in the Calcs tab to see how it is being performed, as this may help you find the cause.

When creating an issue:

  • Select the "Bug Report" issue template and fill out all fields.
  • Please provide detailed instructions on how to reproduce the bug, if possible.
  • Provide a build share code for a build that is affected by the bug, if possible. In the "Import/Export Build" tab, click "Generate", then "Share" and add the link to your post.

Build share codes allow us to reproduce bugs much more quickly.

Requesting features

Feature requests are always welcome. Note that not all requests will receive an immediate response.

Before submitting a feature request:

  • Check that the feature hasn't already been requested. Look at all issues with titles that might be related to the feature.
  • Make sure you are running the latest version of the program, as the feature may already have been added. Click "Check for Update" in the bottom left corner.

When submitting a feature request:

  • Select the "Feature Request" issue template and fill out all fields.
  • Be specific! The more details, the better.
  • Small requests are fine, even if it's just adding support for a minor modifier on a rarely-used unique.

Contributing code

Before submitting a pull request:

  • Familiarise yourself with the code base here to get you started.
  • There is a Discord server for active development on the fork and members are happy to answer your questions there. If you are interested in joining, send a private message to localidentity or wires77 and we'll send you an invitation.

When submitting a pull request:

  • Pull requests must be created against the dev branch, as all changes to the code are staged there before merging to master.
  • Make sure that the changes have been thoroughly tested!
  • If you're updating mod parsing logic, make sure to reload PoB with Ctrl + F5 to regenerate ./src/Data/ModCache.lua. This is a very large, automatically generated file that can be used to verify your changes didn't affect any other mods inadvertently. Make sure to commit ./src/Data/ModCache.lua if your changes cause it to differ.
  • There are many more files in the ./src/Data directory that are automatically generated. This is indicated by the header -- This file is automatically generated, do not edit!. To change these, instead change the scripts in the ./src/Export directory and rerun the exporter. For your PR, please include all relevant changes to both the scripts and data files.

Setting up a development installation

Note: This tutorial assumes that you are already familiar with Git.

The easiest way to make and test changes is by setting up a development installation, in which the program runs directly from a local copy of the repository:

  1. Clone the repository using this command:

    git clone -b dev https://github.com/PathOfBuildingCommunity/PathOfBuilding.git
    
  2. Go to the actual folder on your computer where you cloned Path of Building. (e.g. C:/XX/GitHub/PathOfBuilding/runtime/)

    cd PathOfBuilding
    
  3. Start Path of Building from the repository by running ./runtime/Path{space}of{space}Building.exe.

    • Note for Linux users: The executable files should automatically have the correct permissions when cloned fresh. If you still encounter permission issues, run once: chmod +x ./runtime/Path{space}of{space}Building-PoE2.exe You can now use the shortcut to run the program from the repository. Running the program in this manner automatically enables "Dev Mode", which has some handy debugging feature:
  • F5 restarts the program in-place (this is what usually happens when an update is applied).
  • Ctrl + ~ toggles the console (Note that this does not work with all keyboard layouts. US layout is a safe bet though).
  • ConPrintf() can be used to output to the console. Search for "===" in the project files if you want to get rid of the default debugging strings.
  • Holding Alt adds additional debugging information to tooltips:
    • Items and passives show all internal modifiers that they are granting.
    • Stats that aren't parsed correctly will show any unrecognised parts of the stat description.
    • Passives also show node ID and node power values.
    • Conditional options in the Configuration tab show the list of dependent modifiers.
  • While in the Tree tab, holding Alt also highlights nodes that have unrecognised modifiers.
  • Holding Ctrl while launching the program will rebuild the mod cache.

Note that automatic updates are disabled in Dev Mode.

Forcing Dev Mode OFF when using dev branch

Sometimes you may need to force Dev mode OFF when running from the dev branch to debug a specific part of Path of Building (e.g. the update system).

To do so comment out Line 54 to line 58 of the Launch.lua file:

	--if localManXML and not self.versionBranch and not self.versionPlatform then
	--    -- Looks like a remote manifest, so we're probably running from a repository
	--    -- Enable dev mode to disable updates and set user path to be the script path
	--    self.devMode = true
	--end

and create a valid manifest.xml file in the ./src directory. Then run the ./runtime/Path{space}of{space}Building.exe as usual. You should get the typical update popup in the bottom left corner.

The manifest.xml file deserves its own in depth document, but usually copying from release and editing accordingly works well enough.

Keeping your fork up to date

Note: This tutorial assumes that you are already familiar with Git and basic command line tools.

Note: If you've configured a remote already, you can skip ahead to step 3.

  1. Add a new remote repository and name it upstream.

    git remote add upstream https://github.com/PathOfBuildingCommunity/PathOfBuilding.git
    
  2. Verify that adding the remote worked.

    git remote -v
    
  3. Fetch all branches and their commits from upstream.

    git fetch upstream
    
  4. Check out your local dev branch if you haven't already.

    git checkout dev
    
  5. Merge all changes from upstream/dev into your local dev branch.

    git rebase upstream/dev
    
  6. Push your updated branch to GitHub.

    git push -f origin dev
    

Setting up a development environment

Note: This tutorial assumes that you are already familiar with the development tool of your choice.

If you want to use a text editor, Visual Studio Code (proprietary) is recommended. If you want to use an IDE instead, PyCharm Community or IntelliJ Idea Community (open source) are recommended. They are all free and support EmmyLua, a Lua plugin that comes with a language server, debugger and many pleasant features. 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 or Eclipse Theia but can be built from source if needed.

Another alternative on VSCode is to use sumneko's Lua language server along with actboy168's debugger. 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

  2. Open ./src/Launch.lua

  3. Click the beginning of the line directly after function launch:OnInit()

  4. Insert the debugger code:

    Automatically:

    1. Open the Command Palette (F1)
    2. Type EmmyLua: Insert Emmy Debugger Code
    3. Choose x64 from the drop-down list

    Or manually:

    1. Open the Visual Studio Code extensions folder. On Windows, this defaults to %USERPROFILE%/.vscode/extensions
    2. Find the sub-folder that contains emmy_core.dll. You should find both x86 and x64; pick x64. For example, C:/Users/someuser/.vscode/extensions/tangzx.emmylua-0.9.22-win32-x64/debugger/emmy/windows/x64. Uses this in the snippet below. Note the version number will change with every update.
    3. Copy-paste the following code snippet:
    	-- Path to emmy_core.dll. You will need to update it to point to the EmmyLua dlls in YOUR installation.
    	-- Note the "?.dll" at the end of the path is mandatory.
    	package.cpath = package.cpath .. ";C:/Users/someuser/.vscode/extensions/tangzx.emmylua-0.5.19/debugger/emmy/windows/x64/?.dll"
    	local dbg = require("emmy_core")
    	-- This port must match the IDE configuration. Default is 9966.
    	dbg.tcpListen("localhost", 9966)
    	--dbg.waitIDE() -- Uncomment this line if you want PoB to wait until the debugger is attached.
  5. Set breakpoints in the source with VSCode's built-in breakpoint system (or use a non-local dbg and call _G.dbg.breakHere())

  6. Click the Run and Debug icon on the Activity Bar

  7. Make sure EmmyLua New Debug is selected in the "Run and Debug" dropdown

  8. Start your modified Path of Building Community

  9. In VSCode click Start Debugging (the green icon) or press F5

  10. The debugger should connect

You might also want to use actboy168 debugger. This is possible by using for example the following launch.json configuration:

{
    "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():
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 to the root of the Path of building folder with the following content:

{
    "$schema": "https://raw.githubusercontent.com/EmmyLuaLs/emmylua-analyzer-rust/refs/heads/main/crates/emmylua_code_analysis/resources/schema.json",
    "runtime": {
        "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"
        ]
    }
}

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:

{
    "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)".
  2. Select "x64" version.
  3. Select if you want the program to block (checkbox) until you attached the debugger (useful if you have to debug the startup process).
  4. Copy the generated code snippet directly below function launch:OnInit() in ./src/Launch.lua.
  5. Start Path of Building Community
  6. Attach the debugger

Miscellaneous tips

If you're on windows, consider downloading git for windows and installing git bash. Git bash comes with a variety of typical linux tools such as grep that can make navigating the code base much easier.

If you're using linux you can run the ./runtime/Path{space}of{space}Building.exe executable with wine. You will need to provide a valid wine path to the emmy lua debugger directory.

# winepath -w ~/.vscode/extensions/tangzx.emmylua-0.8.20-linux-x64/debugger/emmy/windows/x64/
Z:\home\dev\.vscode\extensions\tangzx.emmylua-0.8.20-linux-x64\debugger\emmy\windows\x64\

Testing

PoB uses the Busted framework to run its tests. Tests are stored under spec/System and run automatically when a PR is modified. More tests can be added to this folder to test specific functionality, or new test builds can be added to ensure nothing changed that wasn't intended.

Running tests

  1. Install Docker
  2. Run docker-compose up from the command line
  3. Review the results in the terminal

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 (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:

	package.cpath = package.cpath .. ";/usr/local/bin/?.so"
	local dbg = require("emmy_core")
	-- This port must match the IDE Code configuration. Default is 9966.
	dbg.tcpListen("localhost", 9966)
	dbg.waitIDE()

After running docker-compose up the code will wait at the dbg.waitIDE() line until a debugger is attached. This will allow stepping through any code that is internal to POB but will not work for busted related code. Note that this only works for unit tests described above.

Path of Building development tutorials

Exporting GGPK data from Path of Exile

Warning

This will not work on files from the torrent that is released before league launches, as it contains no Data section.

Note: This tutorial assumes that you are already familiar with the GGPK and its structure. poe-tool-dev/ggpk.discussion is a good starting point.

The ./src/Data folder contains generated files which are created using the scripts in the ./src/Export/Scripts folder based on Path of Exile game data. If you change any logic/configuration in ./src/Export, you will need to regenerate the appropriate ./src/Data files. You can do so by running the ./src/Export scripts using the .dat viewer at ./src/Export/Launch.lua:

Obtain an Oodle extractor

Tip

Binaries are usually available at https://github.com/zao/ooz/releases.

Note: For this tutorial, you will need a working installation of Visual Studio Community as well as some familiarity with build tools such as CMake.

  1. In Visual Studio, clone the following repository using this command:

     git clone --recurse-submodules -b master https://github.com/zao/ooz
    
  2. Configure CMake.

  3. Build bun_extract_file.exe, libbun.dll and libooz.dll.

Set up the exporter

  1. Copy bun_extract_file.exe, libbun.dll and libooz.dll to .\src\Export\ggpk\.

  2. Create a shortcut to .\runtime\Path{space}of{space}Building.exe with the path to .\src\Export\Launch.lua as the first argument. You should end up with something like:

    "<path to repo>\runtime\Path{space}of{space}Building.exe" "<path to repo>\src\Export\Launch.lua"
    
  3. Run the shortcut. "Dat View", the GGPK data viewer UI, should appear. If you get an error, be sure you're using the latest release of Path of Building Community.

  4. Click Edit Sources... to display the "New DAT Source" popup. Click New and enter a name.

  5. Paste the full path to Content.ggpk into the "Source from GGPK/Steam PoE path" box and hit Enter. For the stand-alone client, the path must include the file-name. (Do not put anything in the "Source from DAT files" box unless you have already manually unpacked the relevant files.)

    Example input for the stand-alone client:

    C:\Path of Exile\Content.ggpk
    

    Example input for Steam:

    C:\Program Files (x86)\Steam\steamapps\common\Path of Exile  
    

    If successful, you should see some cmd windows pop up as the files are unpacked, and then a list of the data tables in the GGPK file should appear.

  6. Click Scripts >> to show the list of available export scripts. Double-clicking a script will run it, and the box to the right will show any output from the script.

  7. If you run into any errors, update the code in ./src/Export as necessary and try again.

Using the inbuilt profiler

The profiler is found at https://github.com/charlesmallah/lua-profiler and is written entirely in lua under a MIT license.

Pressing pause will start and stop the profiler depending upon if profiling is active. This isn't very precise and has very wide scope so if you want to profile a certain section of code you can also call profiler.start() and profiler.stop() at the start and end of code block you want to profile. Then calling profile.report(fileName) will generate a file in the src folder with the profiling data. This file is called the name given to function or if none are given it is called "profiler.log".

This file contains:

  • Total time spent executing
  • A table containing information about the profiling
    • File, function and line are the file that a given function was executed in and the line of the function definition
    • Time and % are the time spent executing code within a function and its percentage relative to the total time spent
    • # Is the number of times the function was called
  • ~ is displayed if function execution time is less than 0.0001

Here is an example table that could be generated

> Total time: 0.510000 s
-------------------------------------------------------------------------------------------------------------------------------------
| FILE                          : FUNCTION                                        : LINE     : TIME        : %        : #           |
-------------------------------------------------------------------------------------------------------------------------------------
| ...ers\*****\Documents\GitHub\: Anon                                            :     104  : 0.4770      : 93.5     :           2 |
| Modules/Main                  : Anon                                            :     263  : 0.4770      : 93.5     :           2 |
| Modules/Build                 : CallMode                                        :     906  : 0.4730      : 92.7     :           2 |
| Classes/TreeTab               : Draw                                            :     178  : 0.4360      : 85.5     :           2 |
| Classes/PassiveTreeView       : Draw                                            :      97  : 0.4240      : 83.1     :           2 |
| Classes/Control               : IsMouseInBounds                                 :      91  : 0.4150      : 81.4     :           5 |
| Classes/Control               : GetProperty                                     :      83  : 0.4080      : 80.0     :          26 |
| Classes/PassiveTreeView       : renderConnector                                 :     378  : 0.2400      : 47.1     :        5256 |
| Classes/PassiveTreeView       : DrawAsset                                       :     751  : 0.0720      : 14.1     :        9532 |
| Classes/PassiveTreeView       : treeToScreen                                    :     178  : 0.0550      : 10.8     :       27020 |
| Classes/ControlHost           : DrawControls                                    :      85  : 0.0260      : 5.1      :          12 |
| Classes/Control               : GetSize                                         :      79  : 0.0230      : 4.5      :        1624 |
| Classes/PassiveTreeView       : setConnectorColor                               :     363  : 0.0210      : 4.1      :        5884 |
| Classes/PassiveTreeView       : renderGroup                                     :     333  : 0.0160      : 3.1      :        1222 |
| Classes/Control               : IsShown                                         :      83  : 0.0120      : 2.4      :         201 |
| Classes/PassiveTreeView       : getState                                        :     366  : 0.0100      : 2.0      :        5256 |
| Classes/ControlHost           : ProcessControlsInput                            :      32  : 0.0100      : 2.0      :           6 |
| Classes/ControlHost           : GetMouseOverControl                             :      24  : 0.0090      : 1.8      :          22 |
| Classes/Control               : GetProperty                                     :      34  : 0.0070      : 1.4      :        3794 |
| Classes/EditControl           : IsMouseOver                                     :     114  : 0.0060      : 1.2      :           8 |
| Classes/DropDownControl       : IsMouseOver                                     :     160  : 0.0050      : 1.0      :          18 |
| Classes/CheckBoxControl       : IsMouseOver                                     :      14  : 0.0030      : 0.6      :           6 |
| Classes/ScrollBarControl      : IsMouseOver                                     :      70  : 0.0030      : 0.6      :          27 |
| Modules/Build                 : GetProperty                                     :     141  : 0.0020      : 0.4      :          99 |
| Classes/DropDownControl       : CheckDroppedWidth                               :     467  : 0.0020      : 0.4      :          10 |
| Modules/Common                : __index                                         :      77  : 0.0010      : 0.2      :         306 |
| Modules/Build                 : GetProperty                                     :     596  : 0.0010      : 0.2      :          18 |
| Classes/TextListControl       : IsMouseOver                                     :      18  : 0.0010      : 0.2      :           1 |
-------------------------------------------------------------------------------------------------------------------------------------
| Modules/Main                  : GetProperty                                     :     111  : ~           : ~        :          16 |
| Classes/TextListControl       : GetProperty                                     :      10  : ~           : ~        :          10 |
| Classes/PassiveSpec           : CountAllocNodes                                 :     468  : ~           : ~        :          99 |
| Modules/Build                 : GetProperty                                     :     133  : ~           : ~        :          33 |
| Modules/Build                 : GetProperty                                     :     532  : ~           : ~        :          26 |
| Modules/Build                 : GetProperty                                     :     499  : ~           : ~        :           2 |
| Classes/SearchHost            : IsSearchActive                                  :      68  : ~           : ~        :          32 |
| Classes/DropDownControl       : GetDropCount                                    :      92  : ~           : ~        :          16 |
| Modules/Main                  : DrawArrow                                       :     921  : ~           : ~        :          12 |
| Modules/Build                 : GetProperty                                     :     483  : ~           : ~        :           2 |
| Modules/Main                  : GetProperty                                     :     154  : ~           : ~        :           3 |
| Modules/Main                  : Anon                                            :     405  : ~           : ~        :           1 |
| Classes/TradeQuery            : onFrameFunc                                     :      42  : ~           : ~        :           2 |
| Classes/TradeQueryRequests    : ProcessQueue                                    :      21  : ~           : ~        :           2 |
| Classes/LabelControl          : GetProperty                                     :       9  : ~           : ~        :          37 |
| Modules/Main                  : GetProperty                                     :     143  : ~           : ~        :           4 |
| Modules/Build                 : GetProperty                                     :     503  : ~           : ~        :           2 |
| Modules/Main                  : GetProperty                                     :     139  : ~           : ~        :           4 |
| Modules/Build                 : GetProperty                                     :     544  : ~           : ~        :          26 |
| Modules/Build                 : GetProperty                                     :     491  : ~           : ~        :           2 |
| ...ers\*****\Documents\GitHub\: Anon                                            :     166  : ~           : ~        :           1 |
| Modules/Build                 : IsEnabled                                       :     120  : ~           : ~        :           2 |
| Classes/EditControl           : GetProperty                                     :      62  : ~           : ~        :          84 |
| Modules/Build                 : GetProperty                                     :     487  : ~           : ~        :           2 |
| Modules/Build                 : GetProperty                                     :     495  : ~           : ~        :           2 |
| Modules/Build                 : GetProperty                                     :     479  : ~           : ~        :           2 |
| Modules/Build                 : IsEnabled                                       :     126  : ~           : ~        :           2 |
| Classes/ButtonControl         : IsMouseOver                                     :      30  : ~           : ~        :          64 |
| Classes/Control               : SetAnchor                                       :      42  : ~           : ~        :           2 |
| Classes/PassiveTreeView       : screenToTree                                    :     182  : ~           : ~        :           2 |
| Modules/Build                 : RefreshSkillSelectControls                      :    1174  : ~           : ~        :           2 |
| ...ers\*****\Documents\GitHub\: Anon                                            :     134  : ~           : ~        :           1 |
| Modules/Common                : wipeTable                                       :     420  : ~           : ~        :          16 |
| Modules/Main                  : CallMode                                        :     418  : ~           : ~        :           2 |
| Classes/DropDownControl       : SelByValue                                      :     122  : ~           : ~        :           2 |
| Classes/ItemsTab              : GetSocketAndJewelForNodeID                      :    1248  : ~           : ~        :          84 |
| Classes/Control               : IsEnabled                                       :      34  : ~           : ~        :          54 |
| Classes/Control               : IsEnabled                                       :      87  : ~           : ~        :          54 |
| Classes/ScrollBarControl      : SetContentDimension                             :      24  : ~           : ~        :          14 |
| Classes/EditControl           : UpdateScrollBars                                :     201  : ~           : ~        :           4 |
| Classes/UndoHandler           : ResetUndo                                       :      19  : ~           : ~        :           2 |
| Classes/DropDownControl       : SetList                                         :     458  : ~           : ~        :           6 |
| Classes/EditControl           : CreateUndoState                                 :     737  : ~           : ~        :           2 |
| Classes/EditControl           : SetText                                         :      90  : ~           : ~        :           2 |
| Modules/Common                : copyTable                                       :     351  : ~           : ~        :           2 |
-------------------------------------------------------------------------------------------------------------------------------------