├── .gitattributes ├── .gitignore ├── Assets ├── game_ui_small.png ├── patreon_logo.png ├── range_guide.png ├── ring.png └── small_ring.png ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Classes ├── BuildListControl.lua ├── ButtonControl.lua ├── CalcBreakdownControl.lua ├── CalcSectionControl.lua ├── CalcsTab.lua ├── CheckBoxControl.lua ├── ConfigTab.lua ├── Control.lua ├── ControlHost.lua ├── DropDownControl.lua ├── EditControl.lua ├── FolderListControl.lua ├── GemSelectControl.lua ├── ImportTab.lua ├── Item.lua ├── ItemDBControl.lua ├── ItemListControl.lua ├── ItemSetListControl.lua ├── ItemSlotControl.lua ├── ItemsTab.lua ├── LabelControl.lua ├── ListControl.lua ├── MinionListControl.lua ├── ModDB.lua ├── ModList.lua ├── ModStore.lua ├── NotesTab.lua ├── PassiveSpec.lua ├── PassiveSpecListControl.lua ├── PassiveTree.lua ├── PassiveTreeView.lua ├── PathControl.lua ├── PopupDialog.lua ├── ScrollBarControl.lua ├── SectionControl.lua ├── SharedItemListControl.lua ├── SharedItemSetListControl.lua ├── SkillListControl.lua ├── SkillsTab.lua ├── SliderControl.lua ├── TextListControl.lua ├── Tooltip.lua ├── TooltipHost.lua ├── TreeTab.lua └── UndoHandler.lua ├── Data ├── 2_6 │ ├── Bases │ │ ├── amulet.lua │ │ ├── axe.lua │ │ ├── belt.lua │ │ ├── body.lua │ │ ├── boots.lua │ │ ├── bow.lua │ │ ├── claw.lua │ │ ├── dagger.lua │ │ ├── flask.lua │ │ ├── gloves.lua │ │ ├── helmet.lua │ │ ├── jewel.lua │ │ ├── mace.lua │ │ ├── quiver.lua │ │ ├── ring.lua │ │ ├── shield.lua │ │ ├── staff.lua │ │ ├── sword.lua │ │ └── wand.lua │ ├── EnchantmentBoots.lua │ ├── EnchantmentGloves.lua │ ├── EnchantmentHelmet.lua │ ├── Essence.lua │ ├── Gems.lua │ ├── Minions.lua │ ├── Misc.lua │ ├── ModCache.lua │ ├── ModFlask.lua │ ├── ModItem.lua │ ├── ModJewel.lua │ ├── ModMaster.lua │ ├── Rares.lua │ ├── SkillStatMap.lua │ ├── Skills │ │ ├── act_dex.lua │ │ ├── act_int.lua │ │ ├── act_str.lua │ │ ├── glove.lua │ │ ├── minion.lua │ │ ├── other.lua │ │ ├── spectre.lua │ │ ├── sup_dex.lua │ │ ├── sup_int.lua │ │ └── sup_str.lua │ └── Spectres.lua ├── 3_0 │ ├── Bases │ │ ├── amulet.lua │ │ ├── axe.lua │ │ ├── belt.lua │ │ ├── body.lua │ │ ├── boots.lua │ │ ├── bow.lua │ │ ├── claw.lua │ │ ├── dagger.lua │ │ ├── flask.lua │ │ ├── gloves.lua │ │ ├── helmet.lua │ │ ├── jewel.lua │ │ ├── mace.lua │ │ ├── quiver.lua │ │ ├── ring.lua │ │ ├── shield.lua │ │ ├── staff.lua │ │ ├── sword.lua │ │ └── wand.lua │ ├── ClusterJewels.lua │ ├── EnchantmentBoots.lua │ ├── EnchantmentGloves.lua │ ├── EnchantmentHelmet.lua │ ├── Essence.lua │ ├── Gems.lua │ ├── Minions.lua │ ├── Misc.lua │ ├── ModCache.lua │ ├── ModFlask.lua │ ├── ModItem.lua │ ├── ModJewel.lua │ ├── ModJewelAbyss.lua │ ├── ModJewelCluster.lua │ ├── ModMaster.lua │ ├── Rares.lua │ ├── SkillStatMap.lua │ ├── Skills │ │ ├── act_dex.lua │ │ ├── act_int.lua │ │ ├── act_str.lua │ │ ├── glove.lua │ │ ├── minion.lua │ │ ├── other.lua │ │ ├── spectre.lua │ │ ├── sup_dex.lua │ │ ├── sup_int.lua │ │ └── sup_str.lua │ ├── Spectres.lua │ └── StatDescriptions │ │ ├── active_skill_gem_stat_descriptions.lua │ │ ├── aura_skill_stat_descriptions.lua │ │ ├── banner_aura_skill_stat_descriptions.lua │ │ ├── beam_skill_stat_descriptions.lua │ │ ├── brand_skill_stat_descriptions.lua │ │ ├── buff_skill_stat_descriptions.lua │ │ ├── curse_skill_stat_descriptions.lua │ │ ├── debuff_skill_stat_descriptions.lua │ │ ├── gem_stat_descriptions.lua │ │ ├── minion_attack_skill_stat_descriptions.lua │ │ ├── minion_skill_stat_descriptions.lua │ │ ├── minion_spell_skill_stat_descriptions.lua │ │ ├── monster_stat_descriptions.lua │ │ ├── offering_skill_stat_descriptions.lua │ │ ├── skill_stat_descriptions.lua │ │ ├── stat_descriptions.lua │ │ └── variable_duration_skill_stat_descriptions.lua ├── Global.lua ├── New.lua └── Uniques │ ├── amulet.lua │ ├── axe.lua │ ├── belt.lua │ ├── body.lua │ ├── boots.lua │ ├── bow.lua │ ├── claw.lua │ ├── dagger.lua │ ├── flask.lua │ ├── gloves.lua │ ├── helmet.lua │ ├── jewel.lua │ ├── mace.lua │ ├── quiver.lua │ ├── ring.lua │ ├── shield.lua │ ├── staff.lua │ ├── sword.lua │ └── wand.lua ├── Export ├── Bases │ ├── amulet.txt │ ├── axe.txt │ ├── belt.txt │ ├── body.txt │ ├── boots.txt │ ├── bow.txt │ ├── claw.txt │ ├── dagger.txt │ ├── flask.txt │ ├── gloves.txt │ ├── helmet.txt │ ├── jewel.txt │ ├── mace.txt │ ├── quiver.txt │ ├── ring.txt │ ├── shield.txt │ ├── staff.txt │ ├── sword.txt │ └── wand.txt ├── Classes │ ├── DatFile.lua │ ├── DatListControl.lua │ ├── GGPKFile.lua │ ├── RowListControl.lua │ ├── ScriptListControl.lua │ └── SpecColListControl.lua ├── DatView.sln ├── Export.sln ├── Launch.lua ├── Main.lua ├── Minions │ ├── Minions.txt │ ├── Spectres.txt │ └── modmap.ini ├── Scripts │ ├── bases.lua │ ├── cluster.lua │ ├── enchant.lua │ ├── essence.lua │ ├── masters.lua │ ├── minions.lua │ ├── miscdata.lua │ ├── mods.lua │ ├── skills.lua │ └── statdesc.lua ├── Skills │ ├── act_dex.txt │ ├── act_int.txt │ ├── act_str.txt │ ├── glove.txt │ ├── minion.txt │ ├── other.txt │ ├── spectre.txt │ ├── sup_dex.txt │ ├── sup_int.txt │ └── sup_str.txt ├── Tree │ ├── tree.lua │ └── tree_in.lua ├── browse.lua ├── essence.txt ├── essenceMatch.lua ├── passives.lua ├── psg.lua ├── spec.lua └── statdesc.lua ├── GameVersions.lua ├── HeadlessWrapper.lua ├── LICENSE.md ├── Launch.lua ├── LaunchInstall.lua ├── Modules ├── Build.lua ├── BuildList.lua ├── CalcActiveSkill.lua ├── CalcBreakdown.lua ├── CalcDefence-2_6.lua ├── CalcDefence-3_0.lua ├── CalcOffence-2_6.lua ├── CalcOffence-3_0.lua ├── CalcPerform.lua ├── CalcSections-2_6.lua ├── CalcSections-3_0.lua ├── CalcSetup.lua ├── CalcTools.lua ├── Calcs.lua ├── Common.lua ├── ConfigOptions.lua ├── Data.lua ├── ItemTools.lua ├── Main.lua ├── ModParser-2_6.lua ├── ModParser-3_0.lua ├── ModTools.lua └── StatDescriber.lua ├── PathOfBuilding.sln ├── README.md ├── TreeData ├── AmberOil.png ├── AscendancyButton.png ├── AscendancyButtonHighlight.png ├── AscendancyButtonPressed.png ├── AscendancyFrameLargeAllocated.png ├── AscendancyFrameLargeCanAllocate.png ├── AscendancyFrameLargeNormal.png ├── AscendancyFrameSmallAllocated.png ├── AscendancyFrameSmallCanAllocate.png ├── AscendancyFrameSmallNormal.png ├── AscendancyMiddle.png ├── AzureOil.png ├── Background1.png ├── BackgroundDex.png ├── BackgroundDexInt.png ├── BackgroundInt.png ├── BackgroundStr.png ├── BackgroundStrDex.png ├── BackgroundStrInt.png ├── BlackOil.png ├── BlightedNotableFrameAllocated.png ├── BlightedNotableFrameCanAllocate.png ├── BlightedNotableFrameUnallocated.png ├── ClassesAscendant.png ├── ClassesAssassin.png ├── ClassesBerserker.png ├── ClassesChampion.png ├── ClassesChieftain.png ├── ClassesDeadeye.png ├── ClassesElementalist.png ├── ClassesGladiator.png ├── ClassesGuardian.png ├── ClassesHierophant.png ├── ClassesInquisitor.png ├── ClassesJuggernaut.png ├── ClassesNecromancer.png ├── ClassesOccultist.png ├── ClassesPathfinder.png ├── ClassesRaider.png ├── ClassesSaboteur.png ├── ClassesSlayer.png ├── ClassesTrickster.png ├── ClearOil.png ├── CrimsonOil.png ├── EternalEmpireJewelCircle1.png ├── EternalEmpireJewelCircle2.png ├── GoldenOil.png ├── GroupBackgroundLargeHalfAlt.png ├── GroupBackgroundMediumAlt.png ├── GroupBackgroundSmallAlt.png ├── JewelCircle1.png ├── JewelCircle1Inverse.png ├── JewelFrameAllocated.png ├── JewelFrameCanAllocate.png ├── JewelFrameUnallocated.png ├── JewelSocketActiveAbyss.png ├── JewelSocketActiveAbyssAlt.png ├── JewelSocketActiveBlue.png ├── JewelSocketActiveBlueAlt.png ├── JewelSocketActiveGreen.png ├── JewelSocketActiveGreenAlt.png ├── JewelSocketActiveLegion.png ├── JewelSocketActiveLegionAlt.png ├── JewelSocketActivePrismatic.png ├── JewelSocketActivePrismaticAlt.png ├── JewelSocketActiveRed.png ├── JewelSocketActiveRedAlt.png ├── JewelSocketAltActive.png ├── JewelSocketAltCanAllocate.png ├── JewelSocketAltNormal.png ├── JewelSocketClusterAltCanAllocate1Large.png ├── JewelSocketClusterAltCanAllocate1Medium.png ├── JewelSocketClusterAltCanAllocate1Small.png ├── JewelSocketClusterAltNormal1Large.png ├── JewelSocketClusterAltNormal1Medium.png ├── JewelSocketClusterAltNormal1Small.png ├── KaruiJewelCircle1.png ├── KaruiJewelCircle2.png ├── KeystoneFrameAllocated.png ├── KeystoneFrameCanAllocate.png ├── KeystoneFrameUnallocated.png ├── LineConnectorActive.png ├── LineConnectorIntermediate.png ├── LineConnectorNormal.png ├── MarakethJewelCircle1.png ├── MarakethJewelCircle2.png ├── NotableFrameAllocated.png ├── NotableFrameCanAllocate.png ├── NotableFrameUnallocated.png ├── OpalescentOil.png ├── Orbit1Active.png ├── Orbit1Intermediate.png ├── Orbit1Normal.png ├── Orbit2Active.png ├── Orbit2Intermediate.png ├── Orbit2Normal.png ├── Orbit3Active.png ├── Orbit3Intermediate.png ├── Orbit3Normal.png ├── Orbit4Active.png ├── Orbit4Intermediate.png ├── Orbit4Normal.png ├── PSGroupBackground1.png ├── PSGroupBackground2.png ├── PSGroupBackground3.png ├── PSLineDeco.png ├── PSLineDecoHighlighted.png ├── PSPointsFrame.png ├── PSSkillFrame.png ├── PSSkillFrameActive.png ├── PSSkillFrameHighlighted.png ├── PSStartNodeBackgroundInactive.png ├── PassiveSkillScreenAscendancyButton.png ├── PassiveSkillScreenAscendancyButtonHighlight.png ├── PassiveSkillScreenAscendancyButtonPressed.png ├── PassiveSkillScreenAscendancyFrameLargeAllocated.png ├── PassiveSkillScreenAscendancyFrameLargeCanAllocate.png ├── PassiveSkillScreenAscendancyFrameLargeNormal.png ├── PassiveSkillScreenAscendancyFrameSmallAllocated.png ├── PassiveSkillScreenAscendancyFrameSmallCanAllocate.png ├── PassiveSkillScreenAscendancyFrameSmallNormal.png ├── PassiveSkillScreenAscendancyMiddle.png ├── PassiveSkillScreenEternalEmpireJewelCircle1.png ├── PassiveSkillScreenEternalEmpireJewelCircle2.png ├── PassiveSkillScreenJewelCircle1.png ├── PassiveSkillScreenKaruiJewelCircle1.png ├── PassiveSkillScreenKaruiJewelCircle2.png ├── PassiveSkillScreenMarakethJewelCircle1.png ├── PassiveSkillScreenMarakethJewelCircle2.png ├── PassiveSkillScreenTemplarJewelCircle1.png ├── PassiveSkillScreenTemplarJewelCircle2.png ├── PassiveSkillScreenVaalJewelCircle1.png ├── PassiveSkillScreenVaalJewelCircle2.png ├── SepiaOil.png ├── SilverOil.png ├── TealOil.png ├── TemplarJewelCircle1.png ├── TemplarJewelCircle2.png ├── VaalJewelCircle1.png ├── VaalJewelCircle2.png ├── VerdantOil.png ├── VioletOil.png ├── centerduelist.png ├── centermarauder.png ├── centerranger.png ├── centerscion.png ├── centershadow.png ├── centertemplar.png ├── centerwitch.png ├── imgPSFadeCorner.png └── imgPSFadeSide.png ├── UpdateApply.lua ├── UpdateCheck.lua ├── changelog.txt ├── manifest.xml ├── runtime-win32.zip ├── tree-2_6.zip ├── tree-3_10.zip ├── tree-3_11.zip ├── tree-3_6.zip ├── tree-3_7.zip ├── tree-3_8.zip └── tree-3_9.zip /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Assets/game_ui_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/Assets/game_ui_small.png -------------------------------------------------------------------------------- /Assets/patreon_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/Assets/patreon_logo.png -------------------------------------------------------------------------------- /Assets/range_guide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/Assets/range_guide.png -------------------------------------------------------------------------------- /Assets/ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/Assets/ring.png -------------------------------------------------------------------------------- /Assets/small_ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/Assets/small_ring.png -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Path of Building 2 | 3 | ## Reporting bugs 4 | 5 | #### Before creating an issue: 6 | * Check that the bug hasn't been reported in an existing issue. 7 | * Make sure you are running the latest version of the program; click "Check for Update" at the bottom left corner. 8 | * 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. 9 | 10 | #### When creating an issue: 11 | * Please provide detailed instructions on how to reproduce the bug, if possible. 12 | * If the issue affects a specific build, please provide the build share code: In the Import/Export Build tab, click "Generate", then "Share with Pastebin" and add the link to your post. 13 | 14 | ## Requesting features 15 | Feature requests are always welcome. Note that not all requests will recieve an immediate response. 16 | 17 | #### Before submitting a feature request: 18 | * Check that the feature hasn't already been requested; look at all issues with titles that might be related to the feature. 19 | * Make sure you are running the latest version of the program, as the feature may already have been added; click "Check for Update" at the bottom left corner. 20 | 21 | #### When submitting a feature request: 22 | * Be specific! The more details, the better. 23 | * Small requests are fine, even if it's just adding support for a minor modifier on a rarely-used unique. 24 | 25 | ## Contributing code 26 | 27 | #### When submitting a pull request: 28 | * **Pull requests must be made against the 'dev' branch**, as all changes to the code are staged there before merging to 'master'. 29 | * Make sure that the changes have been thoroughly tested! 30 | 31 | #### Setting up a development install 32 | 33 | The easiest way to make and test changes is by setting up a development install, in which the program runs directly from a local copy of the repository: 34 | 1. Clone or download the repository; make sure you grab the dev branch. If you have [Git](https://git-scm.com/) installed, you can use this command: `git clone -b dev https://github.com/Openarl/PathOfBuilding.git`. 35 | 2. Copy the 'TreeData' folder from your main installation into the repository; if you used the .exe to install then it will be in "%ProgramData%\Path of Building". 36 | 3. Create a shortcut to the 'Path of Building.exe' in your main installation of the program. 37 | 4. Add the path and filename of the repository's 'Launch.lua' as an argument to the shortcut; you should end up with something like: `"C:\Program Files (x86)\Path of Building\Path of Building.exe" "C:\Path of Building\Launch.lua"`. 38 | 39 | 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: 40 | * `F5` restarts the program in-place (this is what usually happens when an update is applied). 41 | * `Ctrl` + `~` toggles the console; ConPrintf can be used to output to it. 42 | * Holding `Alt` adds additional debugging information to tooltips: 43 | * Items and passives show all internal modifiers that they are granting. 44 | * Stats that aren't parsed correctly will show any unrecognised parts of the stat description. 45 | * Passives also show node ID and node power values. 46 | * Conditional options in the Configuration tab show the list of dependant modifiers. 47 | * While in the Tree tab, holding `Alt` also highlights nodes that have unrecognised modifiers. 48 | * Holding `Ctrl` while launching the program will rebuild the `ModCache` 49 | 50 | Note that the updates system is disabled in Dev Mode, so you must update manually. 51 | 52 | The repository also contains the system used to export data from the game's Content.ggpk file. This can be found in the Export folder. 53 | The data is exported using the scripts in Export/Scripts, which are run from within the .dat viewer. 54 | The viewer can be run using the same method as the main program: passing the path to Export/Launch.lua to Path of Building.exe. 55 | Once open, enter the path to your PoE installation's Content.ggpk file in the text box at the top left; if successful, you will see a list of the data tables in the .ggpk file. 56 | Double-clicking a script in the scripts list will run it, and the box to the right will show any messages from the script. -------------------------------------------------------------------------------- /Classes/ButtonControl.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Button Control 4 | -- Basic button control. 5 | -- 6 | local ButtonClass = newClass("ButtonControl", "Control", "TooltipHost", function(self, anchor, x, y, width, height, label, onClick) 7 | self.Control(anchor, x, y, width, height) 8 | self.TooltipHost() 9 | self.label = label 10 | self.onClick = onClick 11 | end) 12 | 13 | function ButtonClass:Click() 14 | if self:IsShown() and self:IsEnabled() then 15 | self.onClick() 16 | end 17 | end 18 | 19 | function ButtonClass:SetImage(path) 20 | if path then 21 | self.image = NewImageHandle() 22 | self.image:Load(path) 23 | else 24 | self.image = nil 25 | end 26 | end 27 | 28 | function ButtonClass:IsMouseOver() 29 | if not self:IsShown() then 30 | return false 31 | end 32 | return self:IsMouseInBounds() 33 | end 34 | 35 | function ButtonClass:Draw(viewPort) 36 | local x, y = self:GetPos() 37 | local width, height = self:GetSize() 38 | local enabled = self:IsEnabled() 39 | local mOver = self:IsMouseOver() 40 | local locked = self:GetProperty("locked") 41 | if not enabled then 42 | SetDrawColor(0.33, 0.33, 0.33) 43 | elseif mOver or locked then 44 | SetDrawColor(1, 1, 1) 45 | else 46 | SetDrawColor(0.5, 0.5, 0.5) 47 | end 48 | DrawImage(nil, x, y, width, height) 49 | if not enabled then 50 | SetDrawColor(0, 0, 0) 51 | elseif self.clicked and mOver then 52 | SetDrawColor(0.5, 0.5, 0.5) 53 | elseif mOver or locked then 54 | SetDrawColor(0.33, 0.33, 0.33) 55 | else 56 | SetDrawColor(0, 0, 0) 57 | end 58 | DrawImage(nil, x + 1, y + 1, width - 2, height - 2) 59 | if self.image then 60 | if enabled then 61 | SetDrawColor(1, 1, 1) 62 | else 63 | SetDrawColor(0.33, 0.33, 0.33) 64 | end 65 | DrawImage(self.image, x + 2, y + 2, width - 4, height - 4) 66 | if self.clicked and mOver then 67 | SetDrawColor(1, 1, 1, 0.5) 68 | DrawImage(nil, x + 1, y + 1, width - 2, height - 2) 69 | end 70 | end 71 | if enabled then 72 | SetDrawColor(1, 1, 1) 73 | else 74 | SetDrawColor(0.33, 0.33, 0.33) 75 | end 76 | local label = self:GetProperty("label") 77 | if label == "+" then 78 | DrawImage(nil, x + width * 0.2, y + height * 0.45, width * 0.6, height * 0.1) 79 | DrawImage(nil, x + width * 0.45, y + height * 0.2, width * 0.1, height * 0.6) 80 | elseif label == "-" then 81 | DrawImage(nil, x + width * 0.2, y + height * 0.45, width * 0.6, height * 0.1) 82 | elseif label == "x" then 83 | DrawImageQuad(nil, x + width * 0.2, y + height * 0.3, x + width * 0.3, y + height * 0.2, x + width * 0.8, y + height * 0.7, x + width * 0.7, y + height * 0.8) 84 | DrawImageQuad(nil, x + width * 0.7, y + height * 0.2, x + width * 0.8, y + height * 0.3, x + width * 0.3, y + height * 0.8, x + width * 0.2, y + height * 0.7) 85 | else 86 | local overSize = self.overSizeText or 0 87 | DrawString(x + width / 2, y + 2 - overSize, "CENTER_X", height - 4 + overSize * 2, "VAR",label ) 88 | end 89 | if mOver then 90 | SetDrawLayer(nil, 100) 91 | self:DrawTooltip(x, y, width, height, viewPort) 92 | SetDrawLayer(nil, 0) 93 | end 94 | end 95 | 96 | function ButtonClass:OnKeyDown(key) 97 | if not self:IsShown() or not self:IsEnabled() then 98 | return 99 | end 100 | if key == "LEFTBUTTON" then 101 | self.clicked = true 102 | end 103 | return self 104 | end 105 | 106 | function ButtonClass:OnKeyUp(key) 107 | if not self:IsShown() or not self:IsEnabled() then 108 | return 109 | end 110 | if key == "LEFTBUTTON" and self.clicked then 111 | self.clicked = false 112 | if self:IsMouseOver() then 113 | return self.onClick() 114 | end 115 | end 116 | self.clicked = false 117 | end 118 | -------------------------------------------------------------------------------- /Classes/CheckBoxControl.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Check Box Control 4 | -- Basic check box control. 5 | -- 6 | local CheckBoxClass = newClass("CheckBoxControl", "Control", "TooltipHost", function(self, anchor, x, y, size, label, changeFunc, tooltipText) 7 | self.Control(anchor, x, y, size, size) 8 | self.TooltipHost(tooltipText) 9 | self.label = label 10 | self.changeFunc = changeFunc 11 | end) 12 | 13 | function CheckBoxClass:IsMouseOver() 14 | if not self:IsShown() then 15 | return false 16 | end 17 | return self:IsMouseInBounds() 18 | end 19 | 20 | function CheckBoxClass:Draw(viewPort) 21 | local x, y = self:GetPos() 22 | local size = self.width 23 | local enabled = self:IsEnabled() 24 | local mOver = self:IsMouseOver() 25 | if not enabled then 26 | SetDrawColor(0.33, 0.33, 0.33) 27 | elseif mOver then 28 | SetDrawColor(1, 1, 1) 29 | else 30 | SetDrawColor(0.5, 0.5, 0.5) 31 | end 32 | DrawImage(nil, x, y, size, size) 33 | if not enabled then 34 | SetDrawColor(0, 0, 0) 35 | elseif self.clicked and mOver then 36 | SetDrawColor(0.5, 0.5, 0.5) 37 | elseif mOver then 38 | SetDrawColor(0.33, 0.33, 0.33) 39 | else 40 | SetDrawColor(0, 0, 0) 41 | end 42 | DrawImage(nil, x + 1, y + 1, size - 2, size - 2) 43 | if self.state then 44 | if not enabled then 45 | SetDrawColor(0.33, 0.33, 0.33) 46 | elseif mOver then 47 | SetDrawColor(1, 1, 1) 48 | else 49 | SetDrawColor(0.75, 0.75, 0.75) 50 | end 51 | main:DrawCheckMark(x + size/2, y + size/2, size * 0.8) 52 | end 53 | if enabled then 54 | SetDrawColor(1, 1, 1) 55 | else 56 | SetDrawColor(0.33, 0.33, 0.33) 57 | end 58 | local label = self:GetProperty("label") 59 | if label then 60 | DrawString(x - 5, y + 2, "RIGHT_X", size - 4, "VAR", label) 61 | end 62 | if mOver then 63 | SetDrawLayer(nil, 100) 64 | self:DrawTooltip(x, y, size, size, viewPort, self.state) 65 | SetDrawLayer(nil, 0) 66 | end 67 | end 68 | 69 | function CheckBoxClass:OnKeyDown(key) 70 | if not self:IsShown() or not self:IsEnabled() then 71 | return 72 | end 73 | if key == "LEFTBUTTON" then 74 | self.clicked = true 75 | end 76 | return self 77 | end 78 | 79 | function CheckBoxClass:OnKeyUp(key) 80 | if not self:IsShown() or not self:IsEnabled() then 81 | return 82 | end 83 | if key == "LEFTBUTTON" then 84 | if self:IsMouseOver() then 85 | self.state = not self.state 86 | if self.changeFunc then 87 | self.changeFunc(self.state) 88 | end 89 | end 90 | end 91 | self.clicked = false 92 | end 93 | -------------------------------------------------------------------------------- /Classes/Control.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Control 4 | -- UI control base class 5 | -- 6 | local t_insert = table.insert 7 | local m_floor = math.floor 8 | 9 | local anchorPos = { 10 | ["TOPLEFT"] = { 0 , 0 }, 11 | ["TOP"] = { 0.5, 0 }, 12 | ["TOPRIGHT"] = { 1 , 0 }, 13 | ["RIGHT"] = { 1 , 0.5 }, 14 | ["BOTTOMRIGHT"] = { 1 , 1 }, 15 | ["BOTTOM"] = { 0.5, 1 }, 16 | ["BOTTOMLEFT"] = { 0 , 1 }, 17 | ["LEFT"] = { 0 , 0.5 }, 18 | ["CENTER"] = { 0.5, 0.5 }, 19 | } 20 | 21 | local ControlClass = newClass("Control", function(self, anchor, x, y, width, height) 22 | self.x = x or 0 23 | self.y = y or 0 24 | self.width = width or 0 25 | self.height = height or 0 26 | self.shown = true 27 | self.enabled = true 28 | self.anchor = { } 29 | if anchor then 30 | self:SetAnchor(anchor[1], anchor[2], anchor[3], nil, nil, anchor[4]) 31 | end 32 | end) 33 | 34 | function ControlClass:GetProperty(name) 35 | if type(self[name]) == "function" then 36 | return self[name](self) 37 | else 38 | return self[name] 39 | end 40 | end 41 | 42 | function ControlClass:SetAnchor(point, other, otherPoint, x, y, collapse) 43 | self.anchor.point = point 44 | self.anchor.other = other 45 | self.anchor.otherPoint = otherPoint 46 | self.anchor.collapse = collapse 47 | if x and y then 48 | self.x = x 49 | self.y = y 50 | end 51 | end 52 | 53 | function ControlClass:GetPos() 54 | if self.anchor.collapse and self.anchor.other and not self.anchor.other:GetProperty("shown") then 55 | return self.anchor.other:GetPos() 56 | end 57 | local x = self:GetProperty("x") 58 | local y = self:GetProperty("y") 59 | if self.anchor.other then 60 | local otherX, otherY = self.anchor.other:GetPos() 61 | local otherW, otherH = 0, 0 62 | local width, height = 0, 0 63 | local otherPos = anchorPos[self.anchor.otherPoint] 64 | assert(otherPos, "invalid anchor position '"..tostring(self.anchor.otherPoint).."'") 65 | if self.anchor.otherPoint ~= "TOPLEFT" then 66 | otherW, otherH = self.anchor.other:GetSize() 67 | end 68 | local pos = anchorPos[self.anchor.point] 69 | assert(pos, "invalid anchor position '"..tostring(self.anchor.point).."'") 70 | if self.anchor.point ~= "TOPLEFT" then 71 | width, height = self:GetSize() 72 | end 73 | x = m_floor(otherX + otherW * otherPos[1] + x - width * pos[1]) 74 | y = m_floor(otherY + otherH * otherPos[2] + y - height * pos[2]) 75 | end 76 | return x, y 77 | end 78 | 79 | function ControlClass:GetSize() 80 | return self:GetProperty("width"), self:GetProperty("height") 81 | end 82 | 83 | function ControlClass:IsShown() 84 | return (not self.anchor.other or self.anchor.collapse or self.anchor.other:IsShown()) and self:GetProperty("shown") 85 | end 86 | 87 | function ControlClass:IsEnabled() 88 | return self:GetProperty("enabled") 89 | end 90 | 91 | function ControlClass:IsMouseInBounds() 92 | local x, y = self:GetPos() 93 | local width, height = self:GetSize() 94 | local cursorX, cursorY = GetCursorPos() 95 | return cursorX >= x and cursorY >= y and cursorX < x + width and cursorY < y + height 96 | end 97 | 98 | function ControlClass:SetFocus(focus) 99 | if focus ~= self.hasFocus then 100 | if focus and self.OnFocusGained then 101 | self:OnFocusGained() 102 | elseif not focus and self.OnFocusLost then 103 | self:OnFocusLost() 104 | end 105 | self.hasFocus = focus 106 | end 107 | end 108 | 109 | function ControlClass:AddToTabGroup(master) 110 | if master.tabOrder then 111 | t_insert(master.tabOrder, self) 112 | else 113 | master.tabOrder = { master, self } 114 | end 115 | self.tabOrder = master.tabOrder 116 | end 117 | 118 | function ControlClass:TabAdvance(step) 119 | if self.tabOrder then 120 | local index = isValueInArray(self.tabOrder, self) 121 | if index then 122 | while true do 123 | index = index + step 124 | if index > #self.tabOrder then 125 | index = 1 126 | elseif index < 1 then 127 | index = #self.tabOrder 128 | end 129 | if self.tabOrder[index] == self or (self.tabOrder[index].OnKeyDown and self.tabOrder[index]:IsShown()) then 130 | return self.tabOrder[index] 131 | end 132 | end 133 | end 134 | end 135 | return self 136 | end -------------------------------------------------------------------------------- /Classes/ControlHost.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Control Host 4 | -- Host for UI controls 5 | -- 6 | 7 | local ControlHostClass = newClass("ControlHost", function(self) 8 | self.controls = { } 9 | end) 10 | 11 | function ControlHostClass:SelectControl(newSelControl) 12 | if self.selControl == newSelControl then 13 | return 14 | end 15 | if self.selControl then 16 | self.selControl:SetFocus(false) 17 | end 18 | self.selControl = newSelControl 19 | if self.selControl then 20 | self.selControl:SetFocus(true) 21 | end 22 | end 23 | 24 | function ControlHostClass:GetMouseOverControl() 25 | for _, control in pairs(self.controls) do 26 | if control.IsMouseOver and control:IsMouseOver() then 27 | return control 28 | end 29 | end 30 | end 31 | 32 | function ControlHostClass:ProcessControlsInput(inputEvents, viewPort) 33 | for id, event in ipairs(inputEvents) do 34 | if event.type == "KeyDown" then 35 | if self.selControl then 36 | self:SelectControl(self.selControl:OnKeyDown(event.key, event.doubleClick)) 37 | inputEvents[id] = nil 38 | end 39 | if not self.selControl and event.key:match("BUTTON") then 40 | self:SelectControl() 41 | if isMouseInRegion(viewPort) then 42 | local mOverControl = self:GetMouseOverControl() 43 | if mOverControl and mOverControl.OnKeyDown then 44 | self:SelectControl(mOverControl:OnKeyDown(event.key, event.doubleClick)) 45 | inputEvents[id] = nil 46 | end 47 | end 48 | end 49 | elseif event.type == "KeyUp" then 50 | if self.selControl then 51 | if self.selControl.OnKeyUp then 52 | self:SelectControl(self.selControl:OnKeyUp(event.key)) 53 | end 54 | inputEvents[id] = nil 55 | elseif isMouseInRegion(viewPort) then 56 | local mOverControl = self:GetMouseOverControl(viewPort) 57 | if mOverControl and mOverControl.OnKeyUp then 58 | if mOverControl:OnKeyUp(event.key) then 59 | inputEvents[id] = nil 60 | end 61 | end 62 | end 63 | elseif event.type == "Char" then 64 | if self.selControl then 65 | if self.selControl.OnChar then 66 | self:SelectControl(self.selControl:OnChar(event.key)) 67 | end 68 | inputEvents[id] = nil 69 | end 70 | end 71 | end 72 | end 73 | 74 | function ControlHostClass:DrawControls(viewPort) 75 | for _, control in pairs(self.controls) do 76 | if control:IsShown() and control.Draw then 77 | control:Draw(viewPort) 78 | end 79 | end 80 | end 81 | -------------------------------------------------------------------------------- /Classes/FolderListControl.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Folder List 4 | -- Folder list control. 5 | -- 6 | local ipairs = ipairs 7 | local t_insert = table.insert 8 | 9 | local FolderListClass = newClass("FolderListControl", "ListControl", function(self, anchor, x, y, width, height, subPath, onChange) 10 | self.ListControl(anchor, x, y, width, height, 16, false, false, { }) 11 | self.subPath = subPath or "" 12 | self.controls.path = new("PathControl", {"BOTTOM",self,"TOP"}, 0, -2, width, 24, main.buildPath, self.subPath, function(subPath) 13 | self.subPath = subPath 14 | self:BuildList() 15 | self.selIndex = nil 16 | self.selValue = nil 17 | if onChange then 18 | onChange(subPath) 19 | end 20 | end) 21 | self:BuildList() 22 | end) 23 | 24 | function FolderListClass:BuildList() 25 | wipeTable(self.list) 26 | local handle = NewFileSearch(main.buildPath..self.subPath.."*", true) 27 | while handle do 28 | local fileName = handle:GetFileName() 29 | t_insert(self.list, { 30 | name = fileName, 31 | fullFileName = main.buildPath..self.subPath..fileName, 32 | }) 33 | if not handle:NextFile() then 34 | break 35 | end 36 | end 37 | end 38 | 39 | function FolderListClass:OpenFolder(folderName) 40 | self.controls.path:SetSubPath(self.subPath .. folderName .. "/") 41 | end 42 | 43 | function FolderListClass:GetRowValue(column, index, folder) 44 | if column == 1 then 45 | return folder.name 46 | end 47 | end 48 | 49 | function FolderListClass:OnSelClick(index, folder, doubleClick) 50 | if doubleClick then 51 | self:OpenFolder(folder.name) 52 | end 53 | end 54 | 55 | function FolderListClass:OnSelDelete(index, folder) 56 | if NewFileSearch(folder.fullFileName.."/*") or NewFileSearch(folder.fullFileName.."/*", true) then 57 | main:OpenMessagePopup("Delete Folder", "The folder is not empty.") 58 | else 59 | local res, msg = RemoveDir(folder.fullFileName) 60 | if not res then 61 | main:OpenMessagePopup("Error", "Couldn't delete '"..folder.fullFileName.."': "..msg) 62 | return 63 | end 64 | self:BuildList() 65 | self.selIndex = nil 66 | self.selValue = nil 67 | end 68 | end -------------------------------------------------------------------------------- /Classes/LabelControl.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Label Control 4 | -- Simple text label. 5 | -- 6 | local LabelClass = newClass("LabelControl", "Control", function(self, anchor, x, y, width, height, label) 7 | self.Control(anchor, x, y, width, height) 8 | self.label = label 9 | self.width = function() 10 | return DrawStringWidth(self:GetProperty("height"), "VAR", self:GetProperty("label")) 11 | end 12 | end) 13 | 14 | function LabelClass:Draw() 15 | local x, y = self:GetPos() 16 | DrawString(x, y, "LEFT", self:GetProperty("height"), "VAR", self:GetProperty("label")) 17 | end -------------------------------------------------------------------------------- /Classes/MinionListControl.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Minion List 4 | -- Minion list control. 5 | -- 6 | local ipairs = ipairs 7 | local t_insert = table.insert 8 | local t_remove = table.remove 9 | local s_format = string.format 10 | 11 | local MinionListClass = newClass("MinionListControl", "ListControl", function(self, anchor, x, y, width, height, data, list, dest) 12 | self.ListControl(anchor, x, y, width, height, 16, false, not dest, list) 13 | self.data = data 14 | self.dest = dest 15 | if dest then 16 | self.dragTargetList = { dest } 17 | self.label = "^7Available Spectres:" 18 | self.controls.add = new("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, 0, -2, 60, 18, "Add", function() 19 | self:AddSel() 20 | end) 21 | self.controls.add.enabled = function() 22 | return self.selValue ~= nil and not isValueInArray(dest.list, self.selValue) 23 | end 24 | else 25 | self.label = "^7Spectres in Build:" 26 | self.controls.delete = new("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, 0, -2, 60, 18, "Remove", function() 27 | self:OnSelDelete(self.selIndex, self.selValue) 28 | end) 29 | self.controls.delete.enabled = function() 30 | return self.selValue ~= nil 31 | end 32 | end 33 | end) 34 | 35 | function MinionListClass:AddSel() 36 | if self.dest and not isValueInArray(self.dest.list, self.selValue) then 37 | t_insert(self.dest.list, self.selValue) 38 | end 39 | end 40 | 41 | function MinionListClass:GetRowValue(column, index, minionId) 42 | local minion = self.data.minions[minionId] 43 | if column == 1 then 44 | return minion.name 45 | end 46 | end 47 | 48 | function MinionListClass:AddValueTooltip(tooltip, index, minionId) 49 | if tooltip:CheckForUpdate(minionId) then 50 | local minion = self.data.minions[minionId] 51 | tooltip:AddLine(18, "^7"..minion.name) 52 | tooltip:AddLine(14, s_format("^7Life multiplier: x%.2f", minion.life)) 53 | if minion.energyShield then 54 | tooltip:AddLine(14, s_format("^7Energy Shield: %d%% of base Life", minion.energyShield * 100)) 55 | end 56 | if minion.armour then 57 | tooltip:AddLine(14, s_format("^7Armour multiplier: x%.2f", minion.armour)) 58 | end 59 | tooltip:AddLine(14, s_format("^7Resistances: %s%d^7/%s%d^7/%s%d^7/%s%d", 60 | colorCodes.FIRE, minion.fireResist, 61 | colorCodes.COLD, minion.coldResist, 62 | colorCodes.LIGHTNING, minion.lightningResist, 63 | colorCodes.CHAOS, minion.chaosResist 64 | )) 65 | tooltip:AddLine(14, s_format("^7Base damage: x%.2f", minion.damage)) 66 | tooltip:AddLine(14, s_format("^7Base attack speed: %.2f", 1 / minion.attackTime)) 67 | for _, skillId in ipairs(minion.skillList) do 68 | if self.data.skills[skillId] then 69 | tooltip:AddLine(14, "^7Skill: "..self.data.skills[skillId].name) 70 | end 71 | end 72 | end 73 | end 74 | 75 | function MinionListClass:GetDragValue(index, value) 76 | return "MinionId", value 77 | end 78 | 79 | function MinionListClass:CanReceiveDrag(type, value) 80 | return type == "MinionId" and not isValueInArray(self.list, value) 81 | end 82 | 83 | function MinionListClass:ReceiveDrag(type, value, source) 84 | t_insert(self.list, self.selDragIndex or #self.list + 1, value) 85 | end 86 | 87 | function MinionListClass:OnSelClick(index, minionId, doubleClick) 88 | if doubleClick and self.dest then 89 | self:AddSel() 90 | end 91 | end 92 | 93 | function MinionListClass:OnSelDelete(index, minionId) 94 | if not self.dest then 95 | t_remove(self.list, index) 96 | self.selIndex = nil 97 | self.selValue = nil 98 | end 99 | end 100 | -------------------------------------------------------------------------------- /Classes/NotesTab.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Module: Notes Tab 4 | -- Notes tab for the current build. 5 | -- 6 | local t_insert = table.insert 7 | 8 | local NotesTabClass = newClass("NotesTab", "ControlHost", "Control", function(self, build) 9 | self.ControlHost() 10 | self.Control() 11 | 12 | self.build = build 13 | 14 | self.lastContent = "" 15 | 16 | self.controls.edit = new("EditControl", {"TOPLEFT",self,"TOPLEFT"}, 8, 8, 0, 0, "", nil, "^%C\t\n", nil, nil, 16) 17 | self.controls.edit.width = function() 18 | return self.width - 16 19 | end 20 | self.controls.edit.height = function() 21 | return self.height - 16 22 | end 23 | self:SelectControl(self.controls.edit) 24 | end) 25 | 26 | function NotesTabClass:Load(xml, fileName) 27 | for _, node in ipairs(xml) do 28 | if type(node) == "string" then 29 | self.controls.edit:SetText(node) 30 | end 31 | end 32 | self.lastContent = self.controls.edit.buf 33 | end 34 | 35 | function NotesTabClass:Save(xml) 36 | t_insert(xml, self.controls.edit.buf) 37 | self.lastContent = self.controls.edit.buf 38 | end 39 | 40 | function NotesTabClass:Draw(viewPort, inputEvents) 41 | self.x = viewPort.x 42 | self.y = viewPort.y 43 | self.width = viewPort.width 44 | self.height = viewPort.height 45 | 46 | for id, event in ipairs(inputEvents) do 47 | if event.type == "KeyDown" then 48 | if event.key == "z" and IsKeyDown("CTRL") then 49 | self.controls.edit:Undo() 50 | elseif event.key == "y" and IsKeyDown("CTRL") then 51 | self.controls.edit:Redo() 52 | end 53 | end 54 | end 55 | self:ProcessControlsInput(inputEvents, viewPort) 56 | 57 | main:DrawBackground(viewPort) 58 | 59 | self:DrawControls(viewPort) 60 | 61 | self.modFlag = (self.lastContent ~= self.controls.edit.buf) 62 | end 63 | -------------------------------------------------------------------------------- /Classes/PathControl.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Path Control 4 | -- Path control. 5 | -- 6 | local ipairs = ipairs 7 | local t_insert = table.insert 8 | 9 | local PathClass = newClass("PathControl", "Control", "ControlHost", "UndoHandler", function(self, anchor, x, y, width, height, basePath, subPath, onChange) 10 | self.Control(anchor, x, y, width, height) 11 | self.ControlHost() 12 | self.UndoHandler() 13 | self.basePath = basePath 14 | self.baseName = basePath:match("([^/]+)/$") or "Base" 15 | self:SetSubPath(subPath or "") 16 | self:ResetUndo() 17 | self.onChange = onChange 18 | end) 19 | 20 | function PathClass:SetSubPath(subPath, noUndo) 21 | if subPath == self.subPath then 22 | return 23 | end 24 | self.subPath = subPath 25 | self.folderList = { 26 | { label = self.baseName, path = "" }, 27 | } 28 | for folder, endIndex in subPath:gmatch("([^/]+)()") do 29 | t_insert(self.folderList, { label = folder, path = subPath:sub(1, endIndex) }) 30 | end 31 | local x = 2 32 | local i = 1 33 | for index, folder in ipairs(self.folderList) do 34 | local button = self.controls["folder"..i] 35 | if not button then 36 | button = new("ButtonControl", {"LEFT",self,"LEFT"}, 0, 0, 0, self.height - 4) 37 | self.controls["folder"..i] = button 38 | end 39 | button.shown = true 40 | button.x = x 41 | button.label = folder.label 42 | button.width = DrawStringWidth(self.height - 8, "VAR", folder.label) + 10 43 | button.onClick = function() 44 | self:SetSubPath(folder.path) 45 | end 46 | folder.button = button 47 | x = x + button.width + 12 48 | i = i + 1 49 | end 50 | while self.controls["folder"..i] do 51 | self.controls["folder"..i].shown = false 52 | i = i + 1 53 | end 54 | if self.onChange then 55 | self.onChange(subPath) 56 | end 57 | if not noUndo then 58 | self:AddUndoState() 59 | end 60 | end 61 | 62 | function PathClass:IsMouseOver() 63 | if not self:IsShown() then 64 | return 65 | end 66 | return self:IsMouseInBounds() or self:GetMouseOverControl() 67 | end 68 | 69 | function PathClass:Draw(viewPort) 70 | local x, y = self:GetPos() 71 | local width, height = self:GetSize() 72 | SetDrawColor(0.5, 0.5, 0.5) 73 | DrawImage(nil, x, y, width, height) 74 | SetDrawColor(0, 0, 0) 75 | DrawImage(nil, x + 1, y + 1, width - 2, height - 2) 76 | self:DrawControls(viewPort) 77 | for index, folder in ipairs(self.folderList) do 78 | local buttonX, buttonY = folder.button:GetPos() 79 | local buttonW, buttonH = folder.button:GetSize() 80 | SetDrawColor(1, 1, 1) 81 | main:DrawArrow(buttonX + buttonW + 6, y + height/2, 8, 8, "RIGHT") 82 | if self.otherDragSource and index < #self.folderList then 83 | SetDrawColor(0, 1, 0, 0.25) 84 | DrawImage(nil, buttonX, buttonY, buttonW, buttonH) 85 | end 86 | end 87 | end 88 | 89 | function PathClass:OnKeyDown(key, doubleClick) 90 | if not self:IsShown() or not self:IsEnabled() then 91 | return 92 | end 93 | local mOverControl = self:GetMouseOverControl() 94 | if mOverControl and mOverControl.OnKeyDown then 95 | return mOverControl:OnKeyDown(key) 96 | end 97 | end 98 | 99 | function PathClass:CreateUndoState() 100 | return self.subPath 101 | end 102 | 103 | function PathClass:RestoreUndoState(state) 104 | self:SetSubPath(state, true) 105 | end 106 | 107 | -------------------------------------------------------------------------------- /Classes/PopupDialog.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Popup Dialog 4 | -- Popup Dialog Box with a configurable list of controls 5 | -- 6 | local m_floor = math.floor 7 | 8 | local PopupDialogClass = newClass("PopupDialog", "ControlHost", "Control", function(self, width, height, title, controls, enterControl, defaultControl, escapeControl) 9 | self.ControlHost() 10 | self.Control(nil, 0, 0, width, height) 11 | self.x = function() 12 | return m_floor((main.screenW - width) / 2) 13 | end 14 | self.y = function() 15 | return m_floor((main.screenH - height) / 2) 16 | end 17 | self.title = title 18 | self.controls = controls 19 | self.enterControl = enterControl 20 | self.escapeControl = escapeControl 21 | for id, control in pairs(self.controls) do 22 | if not control.anchor.point then 23 | control:SetAnchor("TOP", self, "TOP") 24 | elseif not control.anchor.other then 25 | control.anchor.other = self 26 | elseif type(control.anchor.other) ~= "table" then 27 | control.anchor.other = self.controls[control.anchor.other] 28 | end 29 | end 30 | if defaultControl then 31 | self:SelectControl(self.controls[defaultControl]) 32 | end 33 | end) 34 | 35 | function PopupDialogClass:Draw(viewPort) 36 | local x, y = self:GetPos() 37 | local width, height = self:GetSize() 38 | -- Draw dialog background 39 | SetDrawColor(0.8, 0.8, 0.8) 40 | DrawImage(nil, x, y, width, height) 41 | SetDrawColor(0.1, 0.1, 0.1) 42 | DrawImage(nil, x + 2, y + 2, width - 4, height - 4) 43 | -- Draw dialog title box 44 | local title = self:GetProperty("title") 45 | local titleWidth = DrawStringWidth(16, "VAR", title) 46 | local titleX = x + m_floor((width - titleWidth - 8) / 2) 47 | SetDrawColor(1, 1, 1) 48 | DrawImage(nil, titleX, y - 10, titleWidth + 8, 24) 49 | SetDrawColor(0, 0, 0) 50 | DrawImage(nil, titleX + 2, y - 8, titleWidth + 4, 20) 51 | SetDrawColor(1, 1, 1) 52 | DrawString(titleX + 4, y - 7, "LEFT", 16, "VAR", title) 53 | -- Draw controls 54 | self:DrawControls(viewPort) 55 | end 56 | 57 | function PopupDialogClass:ProcessInput(inputEvents, viewPort) 58 | for id, event in ipairs(inputEvents) do 59 | if event.type == "KeyDown" then 60 | if event.key == "ESCAPE" then 61 | if self.escapeControl then 62 | self.controls[self.escapeControl]:Click() 63 | else 64 | main:ClosePopup() 65 | end 66 | return 67 | elseif event.key == "RETURN" then 68 | if self.enterControl then 69 | self.controls[self.enterControl]:Click() 70 | return 71 | end 72 | end 73 | end 74 | end 75 | self:ProcessControlsInput(inputEvents, viewPort) 76 | end -------------------------------------------------------------------------------- /Classes/SectionControl.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Section Control 4 | -- Section box with label 5 | -- 6 | 7 | local SectionClass = newClass("SectionControl", "Control", function(self, anchor, x, y, width, height, label) 8 | self.Control(anchor, x, y, width, height) 9 | self.label = label 10 | end) 11 | 12 | function SectionClass:Draw() 13 | local x, y = self:GetPos() 14 | local width, height = self:GetSize() 15 | SetDrawLayer(nil, -10) 16 | SetDrawColor(0.66, 0.66, 0.66) 17 | DrawImage(nil, x, y, width, height) 18 | SetDrawColor(0.1, 0.1, 0.1) 19 | DrawImage(nil, x + 2, y + 2, width - 4, height - 4) 20 | SetDrawLayer(nil, 0) 21 | local label = self:GetProperty("label") 22 | local labelWidth = DrawStringWidth(14, "VAR", label) 23 | SetDrawColor(0.66, 0.66, 0.66) 24 | DrawImage(nil, x + 6, y - 8, labelWidth + 6, 18) 25 | SetDrawColor(0, 0, 0) 26 | DrawImage(nil, x + 7, y - 7, labelWidth + 4, 16) 27 | SetDrawColor(1, 1, 1) 28 | DrawString(x + 9, y - 6, "LEFT", 14, "VAR", label) 29 | end -------------------------------------------------------------------------------- /Classes/SharedItemListControl.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Item list 4 | -- Shared item list control. 5 | -- 6 | local pairs = pairs 7 | local t_insert = table.insert 8 | local t_remove = table.remove 9 | 10 | local SharedItemListClass = newClass("SharedItemListControl", "ListControl", function(self, anchor, x, y, width, height, itemsTab) 11 | self.ListControl(anchor, x, y, width, height, 16, false, true, main.sharedItemList) 12 | self.itemsTab = itemsTab 13 | self.label = "^7Shared items:" 14 | 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." 15 | self.dragTargetList = { } 16 | self.controls.delete = new("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, 0, -2, 60, 18, "Delete", function() 17 | self:OnSelDelete(self.selIndex, self.selValue) 18 | end) 19 | self.controls.delete.enabled = function() 20 | return self.selValue ~= nil 21 | end 22 | end) 23 | 24 | function SharedItemListClass:GetRowValue(column, index, verItem) 25 | local item = verItem[self.itemsTab.build.targetVersion] 26 | if column == 1 then 27 | return colorCodes[item.rarity] .. item.name 28 | end 29 | end 30 | 31 | function SharedItemListClass:AddValueTooltip(tooltip, index, verItem) 32 | if main.popups[1] then 33 | tooltip:Clear() 34 | return 35 | end 36 | local item = verItem[self.itemsTab.build.targetVersion] 37 | if tooltip:CheckForUpdate(item, IsKeyDown("SHIFT"), launch.devModeAlt, self.itemsTab.build.outputRevision) then 38 | self.itemsTab:AddItemTooltip(tooltip, item) 39 | end 40 | end 41 | 42 | function SharedItemListClass:GetDragValue(index, verItem) 43 | local item = verItem[self.itemsTab.build.targetVersion] 44 | return "Item", item 45 | end 46 | 47 | function SharedItemListClass:ReceiveDrag(type, value, source) 48 | if type == "Item" then 49 | local verItem = { raw = value:BuildRaw() } 50 | for _, targetVersion in ipairs(targetVersionList) do 51 | local newItem = new("Item", targetVersion, verItem.raw) 52 | if not value.id then 53 | newItem:NormaliseQuality() 54 | end 55 | verItem[targetVersion] = newItem 56 | end 57 | t_insert(self.list, self.selDragIndex or #self.list, verItem) 58 | end 59 | end 60 | 61 | function SharedItemListClass:OnSelClick(index, verItem, doubleClick) 62 | local item = verItem[self.itemsTab.build.targetVersion] 63 | if doubleClick then 64 | self.itemsTab:CreateDisplayItemFromRaw(item.raw, true) 65 | self.selDragging = false 66 | end 67 | end 68 | 69 | function SharedItemListClass:OnSelCopy(index, verItem) 70 | local item = verItem[self.itemsTab.build.targetVersion] 71 | Copy(item:BuildRaw():gsub("\n","\r\n")) 72 | end 73 | 74 | function SharedItemListClass:OnSelDelete(index, verItem) 75 | local item = verItem[self.itemsTab.build.targetVersion] 76 | main:OpenConfirmPopup("Delete Item", "Are you sure you want to remove '"..item.name.."' from the shared item list?", "Delete", function() 77 | t_remove(self.list, index) 78 | self.selIndex = nil 79 | self.selValue = nil 80 | end) 81 | end 82 | -------------------------------------------------------------------------------- /Classes/SharedItemSetListControl.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Shared Item Set List 4 | -- Shared item set list control. 5 | -- 6 | local t_insert = table.insert 7 | local t_remove = table.remove 8 | local m_max = math.max 9 | local s_format = string.format 10 | 11 | local SharedItemSetListClass = newClass("SharedItemSetListControl", "ListControl", function(self, anchor, x, y, width, height, itemsTab) 12 | self.ListControl(anchor, x, y, width, height, 16, false, true, main.sharedItemSetList) 13 | self.itemsTab = itemsTab 14 | 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." 15 | self.controls.delete = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, 2, -4, 60, 18, "Delete", function() 16 | self:OnSelDelete(self.selIndex, self.selValue) 17 | end) 18 | self.controls.delete.enabled = function() 19 | return self.selValue ~= nil 20 | end 21 | self.controls.rename = new("ButtonControl", {"BOTTOMRIGHT",self,"TOP"}, -2, -4, 60, 18, "Rename", function() 22 | self:RenameSet(self.selValue) 23 | end) 24 | self.controls.rename.enabled = function() 25 | return self.selValue ~= nil 26 | end 27 | end) 28 | 29 | function SharedItemSetListClass:RenameSet(sharedItemSet) 30 | local controls = { } 31 | controls.label = new("LabelControl", nil, 0, 20, 0, 16, "^7Enter name for this item set:") 32 | controls.edit = new("EditControl", nil, 0, 40, 350, 20, sharedItemSet.title, nil, nil, 100, function(buf) 33 | controls.save.enabled = buf:match("%S") 34 | end) 35 | controls.save = new("ButtonControl", nil, -45, 70, 80, 20, "Save", function() 36 | sharedItemSet.title = controls.edit.buf 37 | self.itemsTab.modFlag = true 38 | main:ClosePopup() 39 | end) 40 | controls.save.enabled = false 41 | controls.cancel = new("ButtonControl", nil, 45, 70, 80, 20, "Cancel", function() 42 | main:ClosePopup() 43 | end) 44 | main:OpenPopup(370, 100, sharedItemSet.title and "Rename" or "Set Name", controls, "save", "edit") 45 | end 46 | 47 | function SharedItemSetListClass:GetRowValue(column, index, sharedItemSet) 48 | if column == 1 then 49 | return sharedItemSet.title or "Default" 50 | end 51 | end 52 | 53 | function SharedItemSetListClass:AddValueTooltip(tooltip, index, sharedItemSet) 54 | tooltip:Clear() 55 | for _, slot in ipairs(self.itemsTab.orderedSlots) do 56 | if not slot.nodeId then 57 | local slotName = slot.slotName 58 | local item = sharedItemSet.slots[slotName] and sharedItemSet.slots[slotName][self.itemsTab.build.targetVersion] 59 | if item then 60 | tooltip:AddLine(16, s_format("^7%s: %s%s", self.itemsTab.slots[slotName].label, colorCodes[item.rarity], item.name)) 61 | end 62 | end 63 | end 64 | end 65 | 66 | function SharedItemSetListClass:GetDragValue(index, value) 67 | return "SharedItemList", value 68 | end 69 | 70 | function SharedItemSetListClass:CanReceiveDrag(type, value) 71 | return type == "ItemList" 72 | end 73 | 74 | function SharedItemSetListClass:ReceiveDrag(type, value, source) 75 | if type == "ItemList" then 76 | local sharedItemList = { title = value.title, slots = { } } 77 | for slotName, slot in pairs(self.itemsTab.slots) do 78 | if not slot.nodeId then 79 | if value ~= self.itemsTab.activeItemSet then 80 | slot = value[slotName] 81 | end 82 | if slot.selItemId ~= 0 then 83 | local item = self.itemsTab.items[slot.selItemId] 84 | local verItem = { raw = item:BuildRaw() } 85 | for _, targetVersion in ipairs(targetVersionList) do 86 | local newItem = new("Item", targetVersion, verItem.raw) 87 | if not value.id then 88 | newItem:NormaliseQuality() 89 | end 90 | verItem[targetVersion] = newItem 91 | end 92 | sharedItemList.slots[slotName] = verItem 93 | end 94 | end 95 | end 96 | t_insert(self.list, self.dragIndex or #self.list + 1, sharedItemList) 97 | end 98 | end 99 | 100 | function SharedItemSetListClass:OnSelDelete(index, sharedItemSet) 101 | main:OpenConfirmPopup("Delete Item Set", "Are you sure you want to delete '"..(sharedItemSet.title or "Default").."' from the shared item set list?", "Delete", function() 102 | t_remove(self.list, index) 103 | self.selIndex = nil 104 | self.selValue = nil 105 | end) 106 | end 107 | 108 | function SharedItemSetListClass:OnSelKeyDown(index, sharedItemSet, key) 109 | if key == "F2" then 110 | self:RenameSet(sharedItemSet) 111 | end 112 | end -------------------------------------------------------------------------------- /Classes/SkillListControl.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Skill List 4 | -- Skill list control. 5 | -- 6 | local ipairs = ipairs 7 | local t_insert = table.insert 8 | local t_remove = table.remove 9 | 10 | local SkillListClass = newClass("SkillListControl", "ListControl", function(self, anchor, x, y, width, height, skillsTab) 11 | self.ListControl(anchor, x, y, width, height, 16, false, true, skillsTab.socketGroupList) 12 | self.skillsTab = skillsTab 13 | self.label = "^7Socket Groups:" 14 | self.controls.delete = new("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, 0, -2, 60, 18, "Delete", function() 15 | self:OnSelDelete(self.selIndex, self.selValue) 16 | end) 17 | self.controls.delete.enabled = function() 18 | return self.selValue ~= nil and self.selValue.source == nil 19 | end 20 | self.controls.deleteAll = new("ButtonControl", {"RIGHT",self.controls.delete,"LEFT"}, -4, 0, 70, 18, "Delete All", function() 21 | main:OpenConfirmPopup("Delete All", "Are you sure you want to delete all socket groups in this build?", "Delete", function() 22 | wipeTable(self.list) 23 | skillsTab:SetDisplayGroup() 24 | skillsTab:AddUndoState() 25 | skillsTab.build.buildFlag = true 26 | self.selIndex = nil 27 | self.selValue = nil 28 | end) 29 | end) 30 | self.controls.deleteAll.enabled = function() 31 | return #self.list > 0 32 | end 33 | self.controls.new = new("ButtonControl", {"RIGHT",self.controls.deleteAll,"LEFT"}, -4, 0, 60, 18, "New", function() 34 | local newGroup = { 35 | label = "", 36 | enabled = true, 37 | gemList = { } 38 | } 39 | t_insert(self.list, newGroup) 40 | self.selIndex = #self.list 41 | self.selValue = newGroup 42 | skillsTab:SetDisplayGroup(newGroup) 43 | skillsTab:AddUndoState() 44 | skillsTab.build.buildFlag = true 45 | return skillsTab.gemSlots[1].nameSpec 46 | end) 47 | end) 48 | 49 | function SkillListClass:GetRowValue(column, index, socketGroup) 50 | if column == 1 then 51 | local label = socketGroup.displayLabel or "?" 52 | if not socketGroup.enabled or not socketGroup.slotEnabled then 53 | label = "^x7F7F7F" .. label .. " (Disabled)" 54 | end 55 | return label 56 | end 57 | end 58 | 59 | function SkillListClass:AddValueTooltip(tooltip, index, socketGroup) 60 | if not socketGroup.displaySkillList then 61 | tooltip:Clear() 62 | return 63 | end 64 | if tooltip:CheckForUpdate(socketGroup, self.skillsTab.build.outputRevision) then 65 | self.skillsTab:AddSocketGroupTooltip(tooltip, socketGroup) 66 | end 67 | end 68 | 69 | function SkillListClass:OnOrderChange() 70 | self.skillsTab:AddUndoState() 71 | self.skillsTab.build.buildFlag = true 72 | end 73 | 74 | function SkillListClass:OnSelect(index, socketGroup) 75 | self.skillsTab:SetDisplayGroup(socketGroup) 76 | end 77 | 78 | function SkillListClass:OnSelCopy(index, socketGroup) 79 | if not socketGroup.source then 80 | self.skillsTab:CopySocketGroup(socketGroup) 81 | end 82 | end 83 | 84 | function SkillListClass:OnSelDelete(index, socketGroup) 85 | if socketGroup.source then 86 | main:OpenMessagePopup("Delete Socket Group", "This socket group cannot be deleted as it is created by an equipped item.") 87 | elseif not socketGroup.gemList[1] then 88 | t_remove(self.list, index) 89 | if self.skillsTab.displayGroup == socketGroup then 90 | self.skillsTab.displayGroup = nil 91 | end 92 | self.skillsTab:AddUndoState() 93 | self.skillsTab.build.buildFlag = true 94 | self.selValue = nil 95 | else 96 | main:OpenConfirmPopup("Delete Socket Group", "Are you sure you want to delete '"..socketGroup.displayLabel.."'?", "Delete", function() 97 | t_remove(self.list, index) 98 | if self.skillsTab.displayGroup == socketGroup then 99 | self.skillsTab:SetDisplayGroup() 100 | end 101 | self.skillsTab:AddUndoState() 102 | self.skillsTab.build.buildFlag = true 103 | self.selValue = nil 104 | end) 105 | end 106 | end 107 | -------------------------------------------------------------------------------- /Classes/TextListControl.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Text List 4 | -- Simple list control for displaying a block of text 5 | -- 6 | local TextListClass = newClass("TextListControl", "Control", "ControlHost", function(self, anchor, x, y, width, height, columns, list) 7 | self.Control(anchor, x, y, width, height) 8 | self.ControlHost() 9 | self.controls.scrollBar = new("ScrollBarControl", {"RIGHT",self,"RIGHT"}, -1, 0, 18, 0, 40) 10 | self.controls.scrollBar.height = function() 11 | local width, height = self:GetSize() 12 | return height - 2 13 | end 14 | self.columns = columns or { { x = 0, align = "LEFT" } } 15 | self.list = list or { } 16 | end) 17 | 18 | function TextListClass:IsMouseOver() 19 | if not self:IsShown() then 20 | return 21 | end 22 | return self:IsMouseInBounds() or self:GetMouseOverControl() 23 | end 24 | 25 | function TextListClass:Draw(viewPort) 26 | local x, y = self:GetPos() 27 | local width, height = self:GetSize() 28 | local scrollBar = self.controls.scrollBar 29 | local contentHeight = 0 30 | for _, lineInfo in pairs(self.list) do 31 | contentHeight = contentHeight + lineInfo.height 32 | end 33 | scrollBar:SetContentDimension(contentHeight, height - 4) 34 | SetDrawColor(0.66, 0.66, 0.66) 35 | DrawImage(nil, x, y, width, height) 36 | SetDrawColor(0.05, 0.05, 0.05) 37 | DrawImage(nil, x + 1, y + 1, width - 2, height - 2) 38 | self:DrawControls(viewPort) 39 | SetViewport(x + 2, y + 2, width - 20, height - 4) 40 | for colIndex, colInfo in pairs(self.columns) do 41 | local lineY = -scrollBar.offset 42 | for _, lineInfo in ipairs(self.list) do 43 | if lineInfo[colIndex] then 44 | DrawString(lineInfo.x or colInfo.x, lineY, lineInfo.align or colInfo.align, lineInfo.height, lineInfo.font or "VAR", lineInfo[colIndex]) 45 | end 46 | lineY = lineY + lineInfo.height 47 | end 48 | end 49 | SetViewport() 50 | end 51 | 52 | function TextListClass:OnKeyDown(key, doubleClick) 53 | if not self:IsShown() or not self:IsEnabled() then 54 | return 55 | end 56 | local mOverControl = self:GetMouseOverControl() 57 | if mOverControl and mOverControl.OnKeyDown then 58 | return mOverControl:OnKeyDown(key) 59 | end 60 | end 61 | 62 | function TextListClass:OnKeyUp(key) 63 | if not self:IsShown() or not self:IsEnabled() then 64 | return 65 | end 66 | if key == "WHEELDOWN" then 67 | self.controls.scrollBar:Scroll(1) 68 | return self 69 | elseif key == "WHEELUP" then 70 | self.controls.scrollBar:Scroll(-1) 71 | return self 72 | end 73 | end -------------------------------------------------------------------------------- /Classes/Tooltip.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Tooltip 4 | -- Tooltip 5 | -- 6 | local ipairs = ipairs 7 | local t_insert = table.insert 8 | local m_max = math.max 9 | local m_floor = math.floor 10 | local s_gmatch = string.gmatch 11 | 12 | local TooltipClass = newClass("Tooltip", function(self) 13 | self.lines = { } 14 | self:Clear() 15 | end) 16 | 17 | function TooltipClass:Clear() 18 | wipeTable(self.lines) 19 | if self.updateParams then 20 | wipeTable(self.updateParams) 21 | end 22 | self.center = false 23 | self.color = { 0.5, 0.3, 0 } 24 | end 25 | 26 | function TooltipClass:CheckForUpdate(...) 27 | local doUpdate = false 28 | if not self.updateParams then 29 | self.updateParams = { } 30 | end 31 | for i = 1, select('#', ...) do 32 | if self.updateParams[i] ~= select(i, ...) then 33 | doUpdate = true 34 | break 35 | end 36 | end 37 | if doUpdate then 38 | self:Clear() 39 | for i = 1, select('#', ...) do 40 | self.updateParams[i] = select(i, ...) 41 | end 42 | return true 43 | end 44 | end 45 | 46 | function TooltipClass:AddLine(size, text) 47 | if text then 48 | for line in s_gmatch(text .. "\n", "([^\n]*)\n") do 49 | if self.maxWidth then 50 | for _, line in ipairs(main:WrapString(line, size, self.maxWidth - 12)) do 51 | t_insert(self.lines, { size = size, text = line }) 52 | end 53 | else 54 | t_insert(self.lines, { size = size, text = line }) 55 | end 56 | end 57 | end 58 | end 59 | 60 | function TooltipClass:AddSeparator(size) 61 | t_insert(self.lines, { size = size }) 62 | end 63 | 64 | function TooltipClass:GetSize() 65 | local ttW, ttH = 0, 0 66 | for i, data in ipairs(self.lines) do 67 | if data.text or (self.lines[i - 1] and self.lines[i + 1] and self.lines[i + 1].text) then 68 | ttH = ttH + data.size + 2 69 | end 70 | if data.text then 71 | ttW = m_max(ttW, DrawStringWidth(data.size, "VAR", data.text)) 72 | end 73 | end 74 | return ttW + 12, ttH + 10 75 | end 76 | 77 | function TooltipClass:Draw(x, y, w, h, viewPort) 78 | if #self.lines == 0 then 79 | return 80 | end 81 | local ttW, ttH = self:GetSize() 82 | local ttX = x 83 | local ttY = y 84 | if w and h then 85 | ttX = ttX + w + 5 86 | if ttX + ttW > viewPort.x + viewPort.width then 87 | ttX = m_max(viewPort.x, x - 5 - ttW) 88 | if ttX + ttW > x then 89 | ttY = ttY + h 90 | end 91 | end 92 | if ttY + ttH > viewPort.y + viewPort.height then 93 | ttY = m_max(viewPort.y, y + h - ttH) 94 | end 95 | elseif self.center then 96 | ttX = m_floor(x - ttW/2) 97 | end 98 | if type(self.color) == "string" then 99 | SetDrawColor(self.color) 100 | else 101 | SetDrawColor(unpack(self.color)) 102 | end 103 | DrawImage(nil, ttX, ttY, ttW, 3) 104 | DrawImage(nil, ttX, ttY, 3, ttH) 105 | DrawImage(nil, ttX, ttY + ttH - 3, ttW, 3) 106 | DrawImage(nil, ttX + ttW - 3, ttY, 3, ttH) 107 | SetDrawColor(0, 0, 0, 0.75) 108 | DrawImage(nil, ttX + 3, ttY + 3, ttW - 6, ttH - 6) 109 | SetDrawColor(1, 1, 1) 110 | local y = ttY + 6 111 | for i, data in ipairs(self.lines) do 112 | if data.text then 113 | if self.center then 114 | DrawString(ttX + ttW/2, y, "CENTER_X", data.size, "VAR", data.text) 115 | else 116 | DrawString(ttX + 6, y, "LEFT", data.size, "VAR", data.text) 117 | end 118 | y = y + data.size + 2 119 | elseif self.lines[i + 1] and self.lines[i - 1] and self.lines[i + 1].text then 120 | if type(self.color) == "string" then 121 | SetDrawColor(self.color) 122 | else 123 | SetDrawColor(unpack(self.color)) 124 | end 125 | DrawImage(nil, ttX + 3, y - 1 + data.size / 2, ttW - 6, 2) 126 | y = y + data.size + 2 127 | end 128 | end 129 | return ttW, ttH 130 | end -------------------------------------------------------------------------------- /Classes/TooltipHost.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Tooltip Host 4 | -- Tooltip host 5 | -- 6 | local TooltipHostClass = newClass("TooltipHost", function(self, tooltipText) 7 | self.tooltip = new("Tooltip") 8 | self.tooltipText = tooltipText 9 | end) 10 | 11 | function TooltipHostClass:DrawTooltip(x, y, width, height, viewPort, ...) 12 | if self.tooltipFunc then 13 | self.tooltipFunc(self.tooltip, ...) 14 | self.tooltip:Draw(x, y, width, height, viewPort) 15 | else 16 | local tooltipText = self.Object:GetProperty("tooltipText") 17 | if tooltipText then 18 | self.tooltip:Clear() 19 | self.tooltip:AddLine(14, tooltipText) 20 | self.tooltip:Draw(x, y, width, height, viewPort) 21 | end 22 | end 23 | end -------------------------------------------------------------------------------- /Classes/UndoHandler.lua: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Class: Undo Handler 4 | -- Handler for classes that need to provide undo/redo functionality 5 | -- Classes that use this must define 2 functions: 6 | -- undoState = :CreateUndoState() Returns a new undo state that reflects the current state 7 | -- :RestoreUndoState(undoState) Reverts the current state to the given undo state 8 | -- 9 | local t_insert = table.insert 10 | local t_remove = table.remove 11 | 12 | local UndoHandlerClass = newClass("UndoHandler", function(self) 13 | self.undo = { } 14 | self.redo = { } 15 | end) 16 | 17 | -- Initialises the undo/redo buffers 18 | -- Should be called after the current state is first loaded/initialised 19 | function UndoHandlerClass:ResetUndo() 20 | self.undo = wipeTable(self.undo) 21 | self.redo = wipeTable(self.redo) 22 | self.undo[1] = self:CreateUndoState() 23 | end 24 | 25 | -- Adds a new undo state to the undo buffer, and also clears the redo buffer 26 | -- Should be called after the user makes a change to the current state 27 | function UndoHandlerClass:AddUndoState(noClearRedo) 28 | t_insert(self.undo, 1, self:CreateUndoState()) 29 | self.undo[102] = nil 30 | self.modFlag = true 31 | if not noClearRedo then 32 | self.redo = wipeTable(self.redo) 33 | end 34 | end 35 | 36 | -- Reverts the current state to the previous undo state 37 | function UndoHandlerClass:Undo() 38 | if self.undo[2] then 39 | t_insert(self.redo, 1, t_remove(self.undo, 1)) 40 | self:RestoreUndoState(t_remove(self.undo, 1)) 41 | self:AddUndoState(true) 42 | end 43 | end 44 | 45 | -- Reverts the most recent undo operation 46 | function UndoHandlerClass:Redo() 47 | if self.redo[1] then 48 | self:RestoreUndoState(t_remove(self.redo, 1)) 49 | self:AddUndoState(true) 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /Data/2_6/Bases/belt.lua: -------------------------------------------------------------------------------- 1 | -- This file is automatically generated, do not edit! 2 | -- Item data (c) Grinding Gear Games 3 | local itemBases = ... 4 | 5 | itemBases["Rustic Sash"] = { 6 | type = "Belt", 7 | tags = { default = true, belt = true, }, 8 | implicit = "(12-24)% increased Physical Damage", 9 | req = { }, 10 | } 11 | itemBases["Chain Belt"] = { 12 | type = "Belt", 13 | tags = { default = true, belt = true, }, 14 | implicit = "+(9-20) to maximum Energy Shield", 15 | req = { }, 16 | } 17 | itemBases["Leather Belt"] = { 18 | type = "Belt", 19 | tags = { default = true, belt = true, }, 20 | implicit = "+(25-40) to maximum Life", 21 | req = { level = 8, }, 22 | } 23 | itemBases["Heavy Belt"] = { 24 | type = "Belt", 25 | tags = { default = true, belt = true, }, 26 | implicit = "+(25-35) to Strength", 27 | req = { level = 8, }, 28 | } 29 | itemBases["Cloth Belt"] = { 30 | type = "Belt", 31 | tags = { default = true, belt = true, }, 32 | implicit = "(15-25)% increased Stun and Block Recovery", 33 | req = { level = 16, }, 34 | } 35 | itemBases["Studded Belt"] = { 36 | type = "Belt", 37 | tags = { default = true, belt = true, }, 38 | implicit = "(20-30)% increased Stun Duration on Enemies", 39 | req = { level = 16, }, 40 | } 41 | itemBases["Vanguard Belt"] = { 42 | type = "Belt", 43 | tags = { default = true, belt = true, not_for_sale = true, atlas_base_type = true, beltatlas1 = true, }, 44 | implicit = "+(260-320) to Armour and Evasion Rating", 45 | req = { level = 78, }, 46 | } 47 | itemBases["Crystal Belt"] = { 48 | type = "Belt", 49 | tags = { default = true, belt = true, not_for_sale = true, atlas_base_type = true, beltatlas2 = true, }, 50 | implicit = "+(60-80) to maximum Energy Shield", 51 | req = { level = 79, }, 52 | } 53 | 54 | itemBases["Golden Obi"] = { 55 | type = "Belt", 56 | hidden = true, 57 | tags = { default = true, belt = true, not_for_sale = true, }, 58 | implicit = "(20-30)% increased Rarity of Items found", 59 | req = { }, 60 | } 61 | -------------------------------------------------------------------------------- /Data/2_6/Bases/jewel.lua: -------------------------------------------------------------------------------- 1 | -- This file is automatically generated, do not edit! 2 | -- Item data (c) Grinding Gear Games 3 | local itemBases = ... 4 | 5 | itemBases["Crimson Jewel"] = { 6 | type = "Jewel", 7 | tags = { default = true, jewel = true, not_dex = true, not_int = true, not_for_sale = true, strjewel = true, }, 8 | req = { }, 9 | } 10 | itemBases["Viridian Jewel"] = { 11 | type = "Jewel", 12 | tags = { default = true, jewel = true, not_str = true, not_int = true, not_for_sale = true, dexjewel = true, }, 13 | req = { }, 14 | } 15 | itemBases["Cobalt Jewel"] = { 16 | type = "Jewel", 17 | tags = { default = true, jewel = true, not_dex = true, not_str = true, not_for_sale = true, intjewel = true, }, 18 | req = { }, 19 | } 20 | itemBases["Prismatic Jewel"] = { 21 | type = "Jewel", 22 | tags = { default = true, jewel = true, intjewel = true, dexjewel = true, strjewel = true, not_for_sale = true, }, 23 | req = { }, 24 | } 25 | -------------------------------------------------------------------------------- /Data/2_6/Bases/quiver.lua: -------------------------------------------------------------------------------- 1 | -- This file is automatically generated, do not edit! 2 | -- Item data (c) Grinding Gear Games 3 | local itemBases = ... 4 | 5 | itemBases["Cured Quiver"] = { 6 | type = "Quiver", 7 | hidden = true, 8 | tags = { default = true, quiver = true, }, 9 | implicit = "Adds 2 to 4 Fire Damage to Attacks", 10 | req = { }, 11 | } 12 | itemBases["Rugged Quiver"] = { 13 | type = "Quiver", 14 | hidden = true, 15 | tags = { default = true, quiver = true, }, 16 | implicit = "Adds 2 to 3 Cold Damage to Attacks", 17 | req = { }, 18 | } 19 | itemBases["Conductive Quiver"] = { 20 | type = "Quiver", 21 | hidden = true, 22 | tags = { default = true, quiver = true, }, 23 | implicit = "Adds 1 to 5 Lightning Damage to Attacks", 24 | req = { }, 25 | } 26 | itemBases["Heavy Quiver"] = { 27 | type = "Quiver", 28 | hidden = true, 29 | tags = { default = true, quiver = true, }, 30 | implicit = "Adds 1 to 4 Physical Damage to Attacks", 31 | req = { level = 5, }, 32 | } 33 | itemBases["Light Quiver"] = { 34 | type = "Quiver", 35 | hidden = true, 36 | tags = { default = true, quiver = true, }, 37 | implicit = "+(30-40) to Dexterity", 38 | req = { level = 12, }, 39 | } 40 | itemBases["Serrated Arrow Quiver"] = { 41 | type = "Quiver", 42 | tags = { default = true, quiver = true, }, 43 | implicit = "Adds 1 to 4 Physical Damage to Attacks with Bows", 44 | req = { level = 5, }, 45 | } 46 | itemBases["Two-Point Arrow Quiver"] = { 47 | type = "Quiver", 48 | tags = { default = true, quiver = true, }, 49 | implicit = "(20-30)% increased Accuracy Rating", 50 | req = { level = 4, }, 51 | } 52 | itemBases["Sharktooth Arrow Quiver"] = { 53 | type = "Quiver", 54 | tags = { default = true, quiver = true, }, 55 | implicit = "+(3-4) Life gained for each Enemy hit by your Attacks", 56 | req = { level = 10, }, 57 | } 58 | itemBases["Blunt Arrow Quiver"] = { 59 | type = "Quiver", 60 | tags = { default = true, quiver = true, }, 61 | implicit = "(25-35)% increased Stun Duration on Enemies", 62 | req = { level = 16, }, 63 | } 64 | itemBases["Fire Arrow Quiver"] = { 65 | type = "Quiver", 66 | tags = { default = true, quiver = true, }, 67 | implicit = "Adds 4 to 8 Fire Damage to Attacks with Bows", 68 | req = { level = 22, }, 69 | } 70 | itemBases["Broadhead Arrow Quiver"] = { 71 | type = "Quiver", 72 | tags = { default = true, quiver = true, }, 73 | implicit = "Adds 6 to 12 Physical Damage to Attacks with Bows", 74 | req = { level = 28, }, 75 | } 76 | itemBases["Penetrating Arrow Quiver"] = { 77 | type = "Quiver", 78 | tags = { default = true, quiver = true, }, 79 | implicit = "10% chance of Arrows Piercing", 80 | req = { level = 36, }, 81 | } 82 | itemBases["Spike-Point Arrow Quiver"] = { 83 | type = "Quiver", 84 | tags = { default = true, quiver = true, }, 85 | implicit = "(20-30)% increased Global Critical Strike Chance", 86 | req = { level = 45, }, 87 | } 88 | -------------------------------------------------------------------------------- /Data/2_6/EnchantmentBoots.lua: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | 3 | return { 4 | ["CRUEL"] = { 5 | "Adds 16 to 24 Fire Damage if you've Killed Recently", 6 | "Adds 16 to 24 Cold Damage if you've been Hit Recently", 7 | "Adds 1 to 56 Lightning Damage if you haven't Killed Recently", 8 | "Adds 44 to 64 Chaos Damage if you've taken a Critical Strike Recently", 9 | "8% increased Attack and Cast Speed if you've Killed Recently", 10 | "60% increased Critical Strike Chance if you haven't Crit Recently", 11 | "6% chance to Freeze, Shock and Ignite if you haven't Crit Recently", 12 | "Damage Penetrates 6% of Enemy Elemental Resistances if you haven't Killed Recently", 13 | "10% reduced Mana Cost of Skills if you've been Hit Recently", 14 | "0.4% of Damage Leeched as Life and Mana if you've Killed Recently", 15 | "Regenerate 1% of Life and Mana per second if you were Hit Recently", 16 | "6% Chance to Dodge if you've taken a Critical Strike Recently", 17 | "5% chance to Dodge Spell Damage if you've taken Spell Damage Recently", 18 | "6% increased Movement Speed if you haven't been Hit Recently", 19 | "50% chance to Avoid being Stunned if you've Killed Recently", 20 | }, 21 | ["MERCILESS"] = { 22 | "Adds 33 to 50 Fire Damage if you've Killed Recently", 23 | "Adds 33 to 50 Cold Damage if you've been Hit Recently", 24 | "Adds 1 to 120 Lightning Damage if you haven't Killed Recently", 25 | "Adds 88 to 132 Chaos Damage if you've taken a Critical Strike Recently", 26 | "12% increased Attack and Cast Speed if you've Killed Recently", 27 | "90% increased Critical Strike Chance if you haven't Crit Recently", 28 | "8% chance to Freeze, Shock and Ignite if you haven't Crit Recently", 29 | "Damage Penetrates 8% of Enemy Elemental Resistances if you haven't Killed Recently", 30 | "14% reduced Mana Cost of Skills if you've been Hit Recently", 31 | "0.5% of Damage Leeched as Life and Mana if you've Killed Recently", 32 | "Regenerate 1.5% of Life and Mana per second if you were Hit Recently", 33 | "8% Chance to Dodge if you've taken a Critical Strike Recently", 34 | "6% chance to Dodge Spell Damage if you've taken Spell Damage Recently", 35 | "8% increased Movement Speed if you haven't been Hit Recently", 36 | "65% chance to Avoid being Stunned if you've Killed Recently", 37 | }, 38 | ["ENDGAME"] = { 39 | "Adds 45 to 68 Fire Damage if you've Killed Recently", 40 | "Adds 45 to 68 Cold Damage if you've been Hit Recently", 41 | "Adds 1 to 160 Lightning Damage if you haven't Killed Recently", 42 | "Adds 120 to 180 Chaos Damage if you've taken a Critical Strike Recently", 43 | "16% increased Attack and Cast Speed if you've Killed Recently", 44 | "120% increased Critical Strike Chance if you haven't Crit Recently", 45 | "10% chance to Freeze, Shock and Ignite if you haven't Crit Recently", 46 | "Damage Penetrates 10% of Enemy Elemental Resistances if you haven't Killed Recently", 47 | "18% reduced Mana Cost of Skills if you've been Hit Recently", 48 | "0.6% of Damage Leeched as Life and Mana if you've Killed Recently", 49 | "Regenerate 2% of Life and Mana per second if you were Hit Recently", 50 | "10% Chance to Dodge if you've taken a Critical Strike Recently", 51 | "8% chance to Dodge Spell Damage if you've taken Spell Damage Recently", 52 | "10% increased Movement Speed if you haven't been Hit Recently", 53 | "80% chance to Avoid being Stunned if you've Killed Recently", 54 | }, 55 | } -------------------------------------------------------------------------------- /Data/2_6/EnchantmentGloves.lua: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | 3 | return { 4 | ["NORMAL"] = { 5 | "Cast Word of Blades on Hit", 6 | "Cast Word of Flames on Hit", 7 | "Attack with Word of Force on Hit", 8 | "Cast Word of Frost on Kill", 9 | "Attack with Word of Fury on Hit", 10 | "Cast Word of Inferno on Kill", 11 | "Attack with Word of Ire when Hit", 12 | "Attack with Word of Light when you take a Critical Strike", 13 | "Cast Word of Reflection when Hit", 14 | "Attack with Word of Spite when Hit", 15 | "Cast Word of the Tempest on Hit", 16 | "Cast Word of the Grave when your Skills or Minions Kill", 17 | "Cast Word of Thunder on Kill", 18 | "Attack with Word of War on Kill", 19 | "Cast Word of Winter when Hit", 20 | }, 21 | ["CRUEL"] = { 22 | "Cast Edict of Blades on Hit", 23 | "Cast Edict of Flames on Hit", 24 | "Attack with Edict of Force on Hit", 25 | "Cast Edict of Frost on Kill", 26 | "Attack with Edict of Fury on Hit", 27 | "Cast Edict of Inferno on Kill", 28 | "Attack with Edict of Ire when Hit", 29 | "Attack with Edict of Light when you take a Critical Strike", 30 | "Cast Edict of Reflection when Hit", 31 | "Attack with Edict of Spite when Hit", 32 | "Cast Edict of the Tempest on Hit", 33 | "Cast Edict of the Grave when your Skills or Minions Kill", 34 | "Cast Edict of Thunder on Kill", 35 | "Attack with Edict of War on Kill", 36 | "Cast Edict of Winter when Hit", 37 | }, 38 | ["MERCILESS"] = { 39 | "Cast Decree of Blades on Hit", 40 | "Cast Decree of Flames on Hit", 41 | "Attack with Decree of Force on Hit", 42 | "Cast Decree of Frost on Kill", 43 | "Attack with Decree of Fury on Hit", 44 | "Cast Decree of Inferno on Kill", 45 | "Attack with Decree of Ire when Hit", 46 | "Attack with Decree of Light when you take a Critical Strike", 47 | "Cast Decree of Reflection when Hit", 48 | "Attack with Decree of Spite when Hit", 49 | "Cast Decree of the Tempest on Hit", 50 | "Cast Decree of the Grave when your Skills or Minions Kill", 51 | "Cast Decree of Thunder on Kill", 52 | "Attack with Decree of War on Kill", 53 | "Cast Decree of Winter when Hit", 54 | }, 55 | ["ENDGAME"] = { 56 | "Cast Commandment of Blades on Hit", 57 | "Cast Commandment of Flames on Hit", 58 | "Attack with Commandment of Force on Hit", 59 | "Cast Commandment of Frost on Kill", 60 | "Attack with Commandment of Fury on Hit", 61 | "Cast Commandment of Inferno on Kill", 62 | "Attack with Commandment of Ire when Hit", 63 | "Attack with Commandment of Light when you take a Critical Strike", 64 | "Cast Commandment of Reflection when Hit", 65 | "Attack with Commandment of Spite when Hit", 66 | "Cast Commandment of the Tempest on Hit", 67 | "Cast Commandment of the Grave when your Skills or Minions Kill", 68 | "Cast Commandment of Thunder on Kill", 69 | "Attack with Commandment of War on Kill", 70 | "Cast Commandment of Winter when Hit", 71 | }, 72 | } -------------------------------------------------------------------------------- /Data/2_6/Misc.lua: -------------------------------------------------------------------------------- 1 | local data = ... 2 | -- From DefaultMonsterStats.dat 3 | data.monsterEvasionTable = { 36, 42, 49, 56, 64, 72, 80, 89, 98, 108, 118, 128, 140, 151, 164, 177, 190, 204, 219, 235, 251, 268, 286, 305, 325, 345, 367, 389, 412, 437, 463, 489, 517, 546, 577, 609, 642, 676, 713, 750, 790, 831, 873, 918, 964, 1013, 1063, 1116, 1170, 1227, 1287, 1349, 1413, 1480, 1550, 1623, 1698, 1777, 1859, 1944, 2033, 2125, 2221, 2321, 2425, 2533, 2645, 2761, 2883, 3009, 3140, 3276, 3418, 3565, 3717, 3876, 4041, 4213, 4391, 4576, 4768, 4967, 5174, 5389, 5613, 5845, 6085, 6335, 6595, 6864, 7144, 7434, 7735, 8048, 8372, 8709, 9058, 9420, 9796, 10186, } 4 | data.monsterAccuracyTable = { 18, 19, 20, 21, 23, 24, 25, 27, 28, 30, 31, 33, 35, 36, 38, 40, 42, 44, 46, 49, 51, 54, 56, 59, 62, 65, 68, 71, 74, 78, 81, 85, 89, 93, 97, 101, 106, 111, 116, 121, 126, 132, 137, 143, 149, 156, 162, 169, 177, 184, 192, 200, 208, 217, 226, 236, 245, 255, 266, 277, 288, 300, 312, 325, 338, 352, 366, 381, 396, 412, 428, 445, 463, 481, 500, 520, 540, 562, 584, 607, 630, 655, 680, 707, 734, 762, 792, 822, 854, 887, 921, 956, 992, 1030, 1069, 1110, 1152, 1196, 1241, 1288, } 5 | data.monsterLifeTable = { 15, 18, 21, 25, 29, 33, 38, 43, 49, 55, 61, 68, 76, 85, 94, 104, 114, 126, 138, 152, 166, 182, 199, 217, 236, 257, 280, 304, 331, 359, 389, 422, 456, 494, 534, 577, 624, 673, 726, 783, 844, 910, 980, 1055, 1135, 1221, 1313, 1411, 1516, 1629, 1749, 1878, 2015, 2162, 2319, 2486, 2665, 2857, 3061, 3279, 3512, 3760, 4025, 4308, 4610, 4932, 5276, 5642, 6033, 6449, 6894, 7367, 7872, 8410, 8984, 9595, 10246, 10940, 11679, 12466, 13304, 14198, 15149, 16161, 17240, 18388, 19610, 20911, 22296, 23770, 25338, 27007, 28784, 30673, 32684, 34823, 37098, 39519, 42093, 44831, } 6 | data.monsterAllyLifeTable = { 15, 17, 20, 23, 26, 30, 33, 37, 41, 46, 50, 55, 60, 66, 71, 77, 84, 91, 98, 105, 113, 122, 131, 140, 150, 161, 171, 183, 195, 208, 222, 236, 251, 266, 283, 300, 318, 337, 357, 379, 401, 424, 448, 474, 501, 529, 559, 590, 622, 656, 692, 730, 769, 810, 853, 899, 946, 996, 1048, 1102, 1159, 1219, 1281, 1346, 1415, 1486, 1561, 1640, 1722, 1807, 1897, 1991, 2089, 2192, 2299, 2411, 2528, 2651, 2779, 2913, 3053, 3199, 3352, 3511, 3678, 3853, 4035, 4225, 4424, 4631, 4848, 5074, 5310, 5557, 5815, 6084, 6364, 6658, 6964, 7283, } 7 | data.monsterDamageTable = { 5, 6, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 23, 24, 26, 28, 30, 32, 34, 36, 39, 41, 44, 47, 50, 53, 56, 59, 63, 67, 71, 75, 80, 84, 89, 94, 100, 106, 112, 118, 125, 131, 139, 147, 155, 163, 172, 181, 191, 202, 212, 224, 236, 248, 262, 275, 290, 305, 321, 338, 355, 374, 393, 413, 434, 456, 480, 504, 530, 556, 584, 614, 645, 677, 711, 746, 783, 822, 862, 905, 949, 996, 1045, 1096, 1149, 1205, 1264, 1325, 1390, 1457, 1527, 1601, 1678, 1758, } 8 | -- From MonsterVarieties.dat combined with SkillTotemVariations.dat 9 | data.totemLifeMult = { [1] = 2.94, [2] = 2.94, [3] = 2.94, [4] = 2.94, [5] = 2.94, [6] = 4.2, [7] = 2.94, [8] = 2.94, [9] = 2.94, [10] = 2.94, [11] = 2.94, [12] = 2.94, [13] = 4.5, [15] = 4.5, } 10 | -------------------------------------------------------------------------------- /Data/3_0/Bases/belt.lua: -------------------------------------------------------------------------------- 1 | -- This file is automatically generated, do not edit! 2 | -- Item data (c) Grinding Gear Games 3 | local itemBases = ... 4 | 5 | itemBases["Rustic Sash"] = { 6 | type = "Belt", 7 | tags = { default = true, belt = true, }, 8 | implicit = "(12-24)% increased Global Physical Damage", 9 | req = { }, 10 | } 11 | itemBases["Chain Belt"] = { 12 | type = "Belt", 13 | tags = { default = true, belt = true, }, 14 | implicit = "+(9-20) to maximum Energy Shield", 15 | req = { }, 16 | } 17 | itemBases["Leather Belt"] = { 18 | type = "Belt", 19 | tags = { default = true, belt = true, }, 20 | implicit = "+(25-40) to maximum Life", 21 | req = { level = 8, }, 22 | } 23 | itemBases["Heavy Belt"] = { 24 | type = "Belt", 25 | tags = { default = true, belt = true, }, 26 | implicit = "+(25-35) to Strength", 27 | req = { level = 8, }, 28 | } 29 | itemBases["Cloth Belt"] = { 30 | type = "Belt", 31 | tags = { default = true, belt = true, }, 32 | implicit = "(15-25)% increased Stun and Block Recovery", 33 | req = { level = 16, }, 34 | } 35 | itemBases["Studded Belt"] = { 36 | type = "Belt", 37 | tags = { default = true, belt = true, }, 38 | implicit = "(20-30)% increased Stun Duration on Enemies", 39 | req = { level = 16, }, 40 | } 41 | itemBases["Vanguard Belt"] = { 42 | type = "Belt", 43 | tags = { default = true, belt = true, not_for_sale = true, atlas_base_type = true, beltatlas1 = true, }, 44 | implicit = "+(260-320) to Armour and Evasion Rating", 45 | req = { level = 78, }, 46 | } 47 | itemBases["Crystal Belt"] = { 48 | type = "Belt", 49 | tags = { default = true, belt = true, not_for_sale = true, atlas_base_type = true, beltatlas2 = true, }, 50 | implicit = "+(60-80) to maximum Energy Shield", 51 | req = { level = 79, }, 52 | } 53 | itemBases["Stygian Vise"] = { 54 | type = "Belt", 55 | tags = { default = true, belt = true, not_for_sale = true, }, 56 | implicit = "Has 1 Abyssal Socket", 57 | req = { }, 58 | } 59 | 60 | itemBases["Golden Obi"] = { 61 | type = "Belt", 62 | hidden = true, 63 | tags = { default = true, belt = true, not_for_sale = true, }, 64 | implicit = "(20-30)% increased Rarity of Items found", 65 | req = { }, 66 | } 67 | -------------------------------------------------------------------------------- /Data/3_0/Bases/jewel.lua: -------------------------------------------------------------------------------- 1 | -- This file is automatically generated, do not edit! 2 | -- Item data (c) Grinding Gear Games 3 | local itemBases = ... 4 | 5 | itemBases["Crimson Jewel"] = { 6 | type = "Jewel", 7 | tags = { default = true, jewel = true, not_dex = true, not_int = true, not_for_sale = true, strjewel = true, }, 8 | req = { }, 9 | } 10 | itemBases["Viridian Jewel"] = { 11 | type = "Jewel", 12 | tags = { default = true, jewel = true, not_str = true, not_int = true, not_for_sale = true, dexjewel = true, }, 13 | req = { }, 14 | } 15 | itemBases["Cobalt Jewel"] = { 16 | type = "Jewel", 17 | tags = { default = true, jewel = true, not_dex = true, not_str = true, not_for_sale = true, intjewel = true, }, 18 | req = { }, 19 | } 20 | itemBases["Prismatic Jewel"] = { 21 | type = "Jewel", 22 | tags = { default = true, jewel = true, intjewel = true, dexjewel = true, strjewel = true, not_for_sale = true, }, 23 | req = { }, 24 | } 25 | itemBases["Timeless Jewel"] = { 26 | type = "Jewel", 27 | tags = { default = true, jewel = true, intjewel = true, dexjewel = true, strjewel = true, not_for_sale = true, }, 28 | req = { }, 29 | } 30 | 31 | itemBases["Ghastly Eye Jewel"] = { 32 | type = "Jewel", 33 | subType = "Abyss", 34 | tags = { default = true, not_for_sale = true, abyss_jewel_summoner = true, abyss_jewel = true, }, 35 | req = { }, 36 | } 37 | itemBases["Hypnotic Eye Jewel"] = { 38 | type = "Jewel", 39 | subType = "Abyss", 40 | tags = { default = true, not_for_sale = true, abyss_jewel_caster = true, abyss_jewel = true, }, 41 | req = { }, 42 | } 43 | itemBases["Murderous Eye Jewel"] = { 44 | type = "Jewel", 45 | subType = "Abyss", 46 | tags = { default = true, not_for_sale = true, abyss_jewel_melee = true, abyss_jewel = true, }, 47 | req = { }, 48 | } 49 | itemBases["Searching Eye Jewel"] = { 50 | type = "Jewel", 51 | subType = "Abyss", 52 | tags = { default = true, not_for_sale = true, abyss_jewel_ranged = true, abyss_jewel = true, }, 53 | req = { }, 54 | } 55 | 56 | itemBases["Large Cluster Jewel"] = { 57 | type = "Jewel", 58 | subType = "Cluster", 59 | tags = { default = true, jewel = true, not_for_sale = true, expansion_jewel_large = true, }, 60 | req = { }, 61 | } 62 | itemBases["Medium Cluster Jewel"] = { 63 | type = "Jewel", 64 | subType = "Cluster", 65 | tags = { default = true, jewel = true, not_for_sale = true, expansion_jewel_medium = true, }, 66 | req = { }, 67 | } 68 | itemBases["Small Cluster Jewel"] = { 69 | type = "Jewel", 70 | subType = "Cluster", 71 | tags = { default = true, jewel = true, not_for_sale = true, expansion_jewel_small = true, }, 72 | req = { }, 73 | } 74 | -------------------------------------------------------------------------------- /Data/3_0/Bases/quiver.lua: -------------------------------------------------------------------------------- 1 | -- This file is automatically generated, do not edit! 2 | -- Item data (c) Grinding Gear Games 3 | local itemBases = ... 4 | 5 | itemBases["Cured Quiver"] = { 6 | type = "Quiver", 7 | hidden = true, 8 | tags = { default = true, quiver = true, }, 9 | implicit = "Adds 2 to 4 Fire Damage to Attacks", 10 | req = { }, 11 | } 12 | itemBases["Rugged Quiver"] = { 13 | type = "Quiver", 14 | hidden = true, 15 | tags = { default = true, quiver = true, }, 16 | implicit = "Adds 2 to 3 Cold Damage to Attacks", 17 | req = { }, 18 | } 19 | itemBases["Conductive Quiver"] = { 20 | type = "Quiver", 21 | hidden = true, 22 | tags = { default = true, quiver = true, }, 23 | implicit = "Adds 1 to 5 Lightning Damage to Attacks", 24 | req = { }, 25 | } 26 | itemBases["Heavy Quiver"] = { 27 | type = "Quiver", 28 | hidden = true, 29 | tags = { default = true, quiver = true, }, 30 | implicit = "Adds 1 to 4 Physical Damage to Attacks", 31 | req = { level = 5, }, 32 | } 33 | itemBases["Light Quiver"] = { 34 | type = "Quiver", 35 | hidden = true, 36 | tags = { default = true, quiver = true, }, 37 | implicit = "+(30-40) to Dexterity", 38 | req = { level = 12, }, 39 | } 40 | itemBases["Serrated Arrow Quiver"] = { 41 | type = "Quiver", 42 | tags = { default = true, quiver = true, }, 43 | implicit = "Adds 1 to 4 Physical Damage to Bow Attacks", 44 | req = { level = 5, }, 45 | } 46 | itemBases["Two-Point Arrow Quiver"] = { 47 | type = "Quiver", 48 | tags = { default = true, quiver = true, }, 49 | implicit = "(20-30)% increased Global Accuracy Rating", 50 | req = { level = 4, }, 51 | } 52 | itemBases["Sharktooth Arrow Quiver"] = { 53 | type = "Quiver", 54 | tags = { default = true, quiver = true, }, 55 | implicit = "+(3-4) Life gained for each Enemy hit by your Attacks", 56 | req = { level = 10, }, 57 | } 58 | itemBases["Blunt Arrow Quiver"] = { 59 | type = "Quiver", 60 | tags = { default = true, quiver = true, }, 61 | implicit = "(25-35)% increased Stun Duration on Enemies", 62 | req = { level = 16, }, 63 | } 64 | itemBases["Fire Arrow Quiver"] = { 65 | type = "Quiver", 66 | tags = { default = true, quiver = true, }, 67 | implicit = "Adds 4 to 8 Fire Damage to Bow Attacks", 68 | req = { level = 22, }, 69 | } 70 | itemBases["Broadhead Arrow Quiver"] = { 71 | type = "Quiver", 72 | tags = { default = true, quiver = true, }, 73 | implicit = "Adds 6 to 12 Physical Damage to Bow Attacks", 74 | req = { level = 28, }, 75 | } 76 | itemBases["Penetrating Arrow Quiver"] = { 77 | type = "Quiver", 78 | tags = { default = true, quiver = true, }, 79 | implicit = "Arrows Pierce an additional Target", 80 | req = { level = 36, }, 81 | } 82 | itemBases["Spike-Point Arrow Quiver"] = { 83 | type = "Quiver", 84 | tags = { default = true, quiver = true, }, 85 | implicit = "(20-30)% increased Global Critical Strike Chance", 86 | req = { level = 45, }, 87 | } 88 | itemBases["Ornate Quiver"] = { 89 | type = "Quiver", 90 | tags = { default = true, quiver = true, not_for_sale = true, }, 91 | implicit = "Has 1 Socket", 92 | req = { level = 45, }, 93 | } 94 | -------------------------------------------------------------------------------- /Data/3_0/EnchantmentBoots.lua: -------------------------------------------------------------------------------- 1 | -- This file is automatically generated, do not edit! 2 | -- Item data (c) Grinding Gear Games 3 | 4 | return { 5 | ["CRUEL"] = { 6 | "Adds 16 to 24 Fire Damage if you've Killed Recently", 7 | "Regenerate 1% of Life per second if you were Hit Recently", 8 | "10% reduced Mana Cost of Skills if you've been Hit Recently", 9 | "50% chance to Avoid being Stunned if you've Killed Recently", 10 | "5% chance to Dodge Spell Hits if you've taken Spell Damage Recently", 11 | "8% increased Attack and Cast Speed if you've Killed Recently", 12 | "Adds 16 to 24 Cold Damage if you've been Hit Recently", 13 | "Adds 1 to 56 Lightning Damage if you haven't Killed Recently", 14 | "0.4% of Damage Leeched as Life if you've Killed Recently", 15 | "6% Chance to Dodge Attack Hits if you've taken a Critical Strike Recently", 16 | "6% chance to Freeze, Shock and Ignite if you haven't Crit Recently", 17 | "6% increased Movement Speed if you haven't been Hit Recently", 18 | "60% increased Critical Strike Chance if you haven't Crit Recently", 19 | "Damage Penetrates 6% of Enemy Elemental Resistances if you haven't Killed Recently", 20 | "Adds 44 to 64 Chaos Damage if you've taken a Critical Strike Recently", 21 | "30% increased Mana Regeneration Rate if you've cast a Spell Recently", 22 | }, 23 | ["MERCILESS"] = { 24 | "Adds 33 to 50 Fire Damage if you've Killed Recently", 25 | "Regenerate 1.5% of Life per second if you were Hit Recently", 26 | "14% reduced Mana Cost of Skills if you've been Hit Recently", 27 | "65% chance to Avoid being Stunned if you've Killed Recently", 28 | "6% chance to Dodge Spell Hits if you've taken Spell Damage Recently", 29 | "12% increased Attack and Cast Speed if you've Killed Recently", 30 | "Adds 33 to 50 Cold Damage if you've been Hit Recently", 31 | "Adds 1 to 120 Lightning Damage if you haven't Killed Recently", 32 | "0.5% of Damage Leeched as Life if you've Killed Recently", 33 | "8% Chance to Dodge Attack Hits if you've taken a Critical Strike Recently", 34 | "8% chance to Freeze, Shock and Ignite if you haven't Crit Recently", 35 | "8% increased Movement Speed if you haven't been Hit Recently", 36 | "90% increased Critical Strike Chance if you haven't Crit Recently", 37 | "Damage Penetrates 8% of Enemy Elemental Resistances if you haven't Killed Recently", 38 | "Adds 88 to 132 Chaos Damage if you've taken a Critical Strike Recently", 39 | "50% increased Mana Regeneration Rate if you've cast a Spell Recently", 40 | }, 41 | ["ENDGAME"] = { 42 | "Adds 45 to 68 Fire Damage if you've Killed Recently", 43 | "Regenerate 2% of Life per second if you were Hit Recently", 44 | "18% reduced Mana Cost of Skills if you've been Hit Recently", 45 | "80% chance to Avoid being Stunned if you've Killed Recently", 46 | "8% chance to Dodge Spell Hits if you've taken Spell Damage Recently", 47 | "16% increased Attack and Cast Speed if you've Killed Recently", 48 | "Adds 45 to 68 Cold Damage if you've been Hit Recently", 49 | "Adds 1 to 160 Lightning Damage if you haven't Killed Recently", 50 | "0.6% of Damage Leeched as Life if you've Killed Recently", 51 | "10% Chance to Dodge Attack Hits if you've taken a Critical Strike Recently", 52 | "10% chance to Freeze, Shock and Ignite if you haven't Crit Recently", 53 | "10% increased Movement Speed if you haven't been Hit Recently", 54 | "120% increased Critical Strike Chance if you haven't Crit Recently", 55 | "Damage Penetrates 10% of Enemy Elemental Resistances if you haven't Killed Recently", 56 | "Adds 120 to 180 Chaos Damage if you've taken a Critical Strike Recently", 57 | "70% increased Mana Regeneration Rate if you've cast a Spell Recently", 58 | }, 59 | } -------------------------------------------------------------------------------- /Data/3_0/EnchantmentGloves.lua: -------------------------------------------------------------------------------- 1 | -- This file is automatically generated, do not edit! 2 | -- Item data (c) Grinding Gear Games 3 | 4 | return { 5 | ["NORMAL"] = { 6 | "Trigger Word of Blades on Hit", 7 | "Trigger Word of Flames on Hit", 8 | "Trigger Word of Frost on Kill", 9 | "Trigger Word of the Grave when your Skills or Minions Kill", 10 | "Trigger Word of Reflection when Hit", 11 | "Trigger Word of Force on Hit", 12 | "Trigger Word of Light when you take a Critical Strike", 13 | "Trigger Word of Thunder on Kill", 14 | "Trigger Word of War on Kill", 15 | "Trigger Word of Inferno on Kill", 16 | "Trigger Word of Winter when Hit", 17 | "Trigger Word of the Tempest on Hit", 18 | "Trigger Word of Fury on Hit", 19 | "Trigger Word of Spite when Hit", 20 | "Trigger Word of Ire when Hit", 21 | }, 22 | ["CRUEL"] = { 23 | "Trigger Edict of Blades on Hit", 24 | "Trigger Edict of Flames on Hit", 25 | "Trigger Edict of Frost on Kill", 26 | "Trigger Edict of the Grave when your Skills or Minions Kill", 27 | "Trigger Edict of Reflection when Hit", 28 | "Trigger Edict of Force on Hit", 29 | "Trigger Edict of Light when you take a Critical Strike", 30 | "Trigger Edict of Thunder on Kill", 31 | "Trigger Edict of War on Kill", 32 | "Trigger Edict of Inferno on Kill", 33 | "Trigger Edict of Winter when Hit", 34 | "Trigger Edict of the Tempest on Hit", 35 | "Trigger Edict of Fury on Hit", 36 | "Trigger Edict of Spite when Hit", 37 | "Trigger Edict of Ire when Hit", 38 | }, 39 | ["MERCILESS"] = { 40 | "Trigger Decree of Blades on Hit", 41 | "Trigger Decree of Flames on Hit", 42 | "Trigger Decree of Frost on Kill", 43 | "Trigger Decree of the Grave when your Skills or Minions Kill", 44 | "Trigger Decree of Reflection when Hit", 45 | "Trigger Decree of Force on Hit", 46 | "Trigger Decree of Light when you take a Critical Strike", 47 | "Trigger Decree of Thunder on Kill", 48 | "Trigger Decree of War on Kill", 49 | "Trigger Decree of Inferno on Kill", 50 | "Trigger Decree of Winter when Hit", 51 | "Trigger Decree of the Tempest on Hit", 52 | "Trigger Decree of Fury on Hit", 53 | "Trigger Decree of Spite when Hit", 54 | "Trigger Decree of Ire when Hit", 55 | }, 56 | ["ENDGAME"] = { 57 | "Trigger Commandment of Blades on Hit", 58 | "Trigger Commandment of Flames on Hit", 59 | "Trigger Commandment of Frost on Kill", 60 | "Trigger Commandment of the Grave when your Skills or Minions Kill", 61 | "Trigger Commandment of Reflection when Hit", 62 | "Trigger Commandment of Force on Hit", 63 | "Trigger Commandment of Light when you take a Critical Strike", 64 | "Trigger Commandment of Thunder on Kill", 65 | "Trigger Commandment of War on Kill", 66 | "Trigger Commandment of Inferno on Kill", 67 | "Trigger Commandment of Winter when Hit", 68 | "Trigger Commandment of the Tempest on Hit", 69 | "Trigger Commandment of Fury on Hit", 70 | "Trigger Commandment of Spite when Hit", 71 | "Trigger Commandment of Ire when Hit", 72 | }, 73 | } -------------------------------------------------------------------------------- /Data/3_0/Misc.lua: -------------------------------------------------------------------------------- 1 | local data = ... 2 | -- From DefaultMonsterStats.dat 3 | data.monsterEvasionTable = { 53, 67, 82, 97, 113, 130, 148, 166, 185, 205, 226, 248, 271, 295, 320, 346, 373, 401, 431, 462, 493, 527, 561, 597, 635, 674, 715, 757, 801, 846, 894, 943, 994, 1048, 1103, 1160, 1220, 1282, 1346, 1413, 1482, 1554, 1628, 1705, 1785, 1868, 1954, 2044, 2136, 2232, 2332, 2435, 2541, 2652, 2766, 2885, 3008, 3135, 3267, 3403, 3544, 3690, 3842, 3998, 4160, 4328, 4501, 4681, 4867, 5059, 5258, 5463, 5676, 5895, 6123, 6358, 6601, 6852, 7112, 7380, 7658, 7945, 8241, 8548, 8864, 9191, 9529, 9879, 10239, 10612, 10997, 11395, 11806, 12230, 12668, 13121, 13588, 14071, 14569, 15084, } 4 | 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, } 5 | data.monsterLifeTable = { 15, 18, 21, 25, 29, 33, 38, 43, 49, 55, 61, 68, 76, 85, 94, 104, 114, 126, 138, 152, 166, 182, 199, 217, 236, 257, 280, 304, 331, 359, 389, 422, 456, 494, 534, 577, 624, 673, 726, 783, 844, 910, 980, 1055, 1135, 1221, 1313, 1411, 1516, 1629, 1749, 1878, 2015, 2162, 2319, 2486, 2665, 2857, 3061, 3279, 3512, 3760, 4025, 4308, 4610, 4932, 5276, 5642, 6033, 6449, 6894, 7367, 7872, 8410, 8984, 9595, 10246, 10940, 11679, 12466, 13304, 14198, 15149, 16161, 17240, 18388, 19610, 20911, 22296, 23770, 25338, 27007, 28784, 30673, 32684, 34823, 37098, 39519, 42093, 44831, } 6 | data.monsterAllyLifeTable = { 15, 17, 20, 23, 26, 30, 33, 37, 41, 46, 50, 55, 60, 66, 71, 77, 84, 91, 98, 105, 113, 122, 131, 140, 150, 161, 171, 183, 195, 208, 222, 236, 251, 266, 283, 300, 318, 337, 357, 379, 401, 424, 448, 474, 501, 529, 559, 590, 622, 656, 692, 730, 769, 810, 853, 899, 946, 996, 1048, 1102, 1159, 1219, 1281, 1346, 1415, 1486, 1561, 1640, 1722, 1807, 1897, 1991, 2089, 2192, 2299, 2411, 2528, 2651, 2779, 2913, 3053, 3199, 3352, 3511, 3678, 3853, 4035, 4225, 4424, 4631, 4848, 5074, 5310, 5557, 5815, 6084, 6364, 6658, 6964, 7283, } 7 | data.monsterDamageTable = { 5, 6, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 23, 24, 26, 28, 30, 32, 34, 36, 39, 41, 44, 47, 50, 53, 56, 59, 63, 67, 71, 75, 80, 84, 89, 94, 100, 106, 112, 118, 125, 131, 139, 147, 155, 163, 172, 181, 191, 202, 212, 224, 236, 248, 262, 275, 290, 305, 321, 338, 355, 374, 393, 413, 434, 456, 480, 504, 530, 556, 584, 614, 645, 677, 711, 746, 783, 822, 862, 905, 949, 996, 1045, 1096, 1149, 1205, 1264, 1325, 1390, 1457, 1527, 1601, 1678, 1758, } 8 | -- From MonsterVarieties.dat combined with SkillTotemVariations.dat 9 | data.totemLifeMult = { [1] = 2.4, [2] = 2.4, [3] = 2.4, [4] = 2.4, [5] = 2.4, [6] = 2.4, [7] = 2.4, [8] = 2.6, [9] = 2.4, [10] = 2.4, [11] = 2.4, [12] = 2.4, [13] = 3, [15] = 3, [16] = 7.44, [17] = 2.6, [18] = 2.4, [19] = 2.4, } 10 | -------------------------------------------------------------------------------- /Data/3_0/StatDescriptions/banner_aura_skill_stat_descriptions.lua: -------------------------------------------------------------------------------- 1 | return {[1]={lang={English={[1]={[1]={k="milliseconds_to_seconds_2dp",v=1},limit={[1]={[1]=1,[2]="#"}},text="Banner lasts %1% seconds after being placed"}}},name="buff_duration",stats={[1]="buff_effect_duration"}},[2]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Gain 1 Stage when you Impale an Enemy while carrying the Banner, up to 5 per second"}}},name="banner_add_stage_on_impale",stats={[1]="banner_add_stage_on_impale"}},[3]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Gain 1 Stage when you Kill an Enemy while carrying the Banner"}}},name="banner_add_stage_on_kill",stats={[1]="banner_add_stage_on_kill"}},[4]={lang={English={[1]={[1]={k="milliseconds_to_seconds",v=1},limit={[1]={[1]=1000,[2]=1000}},text="%1$+d second to Base Placed Banner Duration per Stage"},[2]={[1]={k="milliseconds_to_seconds",v=1},limit={[1]={[1]="#",[2]="#"}},text="%1$+d seconds to Base Placed Banner Duration per Stage"}}},name="banner_stage_duration",stats={[1]="banner_additional_base_duration_per_stage_ms"}},[5]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="When placed, %1%%% increased Area of Effect per Stage"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="When placed, %1%%% reduced Area of Effect per Stage"}}},name="banner_stage_aoe",stats={[1]="banner_area_of_effect_+%_per_stage"}},[6]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="When placed, %1%%% increased Aura effect per Stage"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="When placed, %1%%% reduced Aura effect per Stage"}}},name="banner_stage_aura_effect",stats={[1]="banner_buff_effect_+%_per_stage"}},[7]={lang={English={[1]={[1]={k="milliseconds_to_seconds_2dp",v=1},limit={[1]={[1]="#",[2]="#"}},text="Base Duration of %1% seconds after being Placed"}}},name="base_duration_identifier",stats={[1]="base_skill_effect_duration"}},[8]={lang={English={[1]={[1]={k="milliseconds_to_seconds_2dp",v=1},[2]={k="reminderstring",v="ReminderTextAdrenaline"},limit={[1]={[1]=1000,[2]=1000}},text="Gain Adrenaline for %1% second per Stage on Placing the Banner"},[2]={[1]={k="milliseconds_to_seconds_2dp",v=1},[2]={k="reminderstring",v="ReminderTextAdrenaline"},limit={[1]={[1]="#",[2]="#"}},text="Gain Adrenaline for %1% seconds per Stage on Placing the Banner"}}},name="war_banner_adrenaline",stats={[1]="bloodstained_banner_adrenaline_duration_per_stage_ms"}},[9]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Nearby Enemies have %1%%% more Accuracy Rating"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="Nearby Enemies have %1%%% less Accuracy Rating"}}},name="dread_banner_accuracy_final",stats={[1]="puresteel_banner_accuracy_rating_+%_final"}},[10]={lang={English={[1]={[1]={k="milliseconds_to_seconds_2dp",v=1},[2]={k="reminderstring",v="ReminderTextFortify"},limit={[1]={[1]=1000,[2]=1000}},text="Gain Fortify for %1% second per Stage on Placing the Banner"},[2]={[1]={k="milliseconds_to_seconds_2dp",v=1},[2]={k="reminderstring",v="ReminderTextFortify"},limit={[1]={[1]="#",[2]="#"}},text="Gain Fortify for %1% seconds per Stage on Placing the Banner"}}},name="dread_banner_fortify",stats={[1]="puresteel_banner_fortify_duration_per_stage_ms"}},[11]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="%1%%% increased Fortify effect per Stage"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="%1%%% reduced Fortify effect per Stage"}}},name="dread_banner_fortify_effect",stats={[1]="puresteel_banner_fortify_effect_+%_per_stage"}},["banner_add_stage_on_impale"]=2,["banner_add_stage_on_kill"]=3,["banner_additional_base_duration_per_stage_ms"]=4,["banner_area_of_effect_+%_per_stage"]=5,["banner_buff_effect_+%_per_stage"]=6,["base_skill_effect_duration"]=7,["bloodstained_banner_adrenaline_duration_per_stage_ms"]=8,["buff_effect_duration"]=1,parent="aura_skill_stat_descriptions",["puresteel_banner_accuracy_rating_+%_final"]=9,["puresteel_banner_fortify_duration_per_stage_ms"]=10,["puresteel_banner_fortify_effect_+%_per_stage"]=11} -------------------------------------------------------------------------------- /Data/3_0/StatDescriptions/beam_skill_stat_descriptions.lua: -------------------------------------------------------------------------------- 1 | return {[1]={lang={English={[1]={limit={[1]={[1]=1,[2]=1}},text="Beams Split towards %1% additional target"},[2]={limit={[1]={[1]="#",[2]="#"}},text="Beams Split towards %1% additional targets"}}},name="base_split_num",stats={[1]="projectile_number_to_split"}},parent="skill_stat_descriptions",["projectile_number_to_split"]=1} -------------------------------------------------------------------------------- /Data/3_0/StatDescriptions/brand_skill_stat_descriptions.lua: -------------------------------------------------------------------------------- 1 | return {[1]={stats={[1]="base_number_of_sigils_allowed_per_target"}},[2]={lang={English={[1]={[1]={k="milliseconds_to_seconds_2dp",v=1},limit={[1]={[1]="#",[2]="#"}},text="Can be Detached for a total Duration of %1% seconds"}}},name="base_secondary_duration_identifier",stats={[1]="base_secondary_skill_effect_duration"}},[3]={lang={English={[1]={[1]={k="milliseconds_to_seconds_2dp",v=1},limit={[1]={[1]="#",[2]="#"}},text="Can be Attached for a total Duration of %1% seconds"}}},name="base_duration_identifier",stats={[1]="base_skill_effect_duration"}},[4]={lang={English={[1]={[1]={k="milliseconds_to_seconds_2dp",v=1},limit={[1]={[1]="#",[2]="#"}},text="Base Debuff Duration is %1% seconds"}}},name="base_tertiary_duration_identifier",stats={[1]="base_tertiary_skill_effect_duration"}},[5]={lang={English={[1]={limit={[1]={[1]=1,[2]=1}},text="Can have %1% Brand Attached to an Enemy"},[2]={limit={[1]={[1]=2,[2]="#"}},text="Can have %1% Brands Attached to an Enemy"}}},name="brand_target_limit",stats={[1]="brands_per_target_limit"}},[6]={lang={English={[1]={limit={[1]={[1]=1,[2]=1}},text="Sends beam to the Branded Enemy"},[2]={limit={[1]={[1]=2,[2]="#"}},text="Sends beams to %1% Enemies, including the Branded Enemy"}}},name="storm_brand_beam_num",stats={[1]="conduit_sigil_number_of_beam_targets"}},[7]={lang={English={[1]={[1]={k="milliseconds_to_seconds_2dp",v=1},limit={[1]={[1]=1,[2]="#"}},text="Can be Detached for a total Duration of %1% seconds"}}},name="secondary_skill_duration",stats={[1]="secondary_skill_effect_duration"}},[8]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Deals %1%%% more Damage to Branded Enemy"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="Deals %1%%% less Damage to Branded Enemy"}}},name="sigil_attached_target_damage_final",stats={[1]="sigil_attached_target_damage_+%_final"}},[9]={lang={English={[1]={[1]={k="milliseconds_to_seconds_2dp",v=1},limit={[1]={[1]=1000,[2]=1000}},text="Activates every %1% second while Attached"},[2]={[1]={k="milliseconds_to_seconds_2dp",v=1},limit={[1]={[1]="#",[2]="#"}},text="Activates every %1% seconds while Attached"}}},name="sigil_activate_frequency",stats={[1]="sigil_repeat_frequency_ms"}},[10]={lang={English={[1]={[1]={k="milliseconds_to_seconds_2dp",v=1},limit={[1]={[1]=1,[2]="#"}},text="Can be Attached for a total Duration of %1% seconds"}}},name="skill_duration",stats={[1]="skill_effect_duration"}},[11]={lang={English={[1]={[1]={k="milliseconds_to_seconds_2dp",v=1},limit={[1]={[1]=1,[2]="#"}},text="Debuff Lasts %1% seconds"}}},name="tertiary_buff_duration",stats={[1]="tertiary_buff_effect_duration"}},["base_number_of_sigils_allowed_per_target"]=1,["base_secondary_skill_effect_duration"]=2,["base_skill_effect_duration"]=3,["base_tertiary_skill_effect_duration"]=4,["brands_per_target_limit"]=5,["conduit_sigil_number_of_beam_targets"]=6,parent="skill_stat_descriptions",["secondary_skill_effect_duration"]=7,["sigil_attached_target_damage_+%_final"]=8,["sigil_repeat_frequency_ms"]=9,["skill_effect_duration"]=10,["tertiary_buff_effect_duration"]=11} -------------------------------------------------------------------------------- /Data/3_0/StatDescriptions/buff_skill_stat_descriptions.lua: -------------------------------------------------------------------------------- 1 | return {[1]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"},[2]={[1]="#",[2]="#"}},text="Adds %1% to %2% Fire Damage to Attacks"}}},name="attack_added_fire",stats={[1]="attack_minimum_added_fire_damage",[2]="attack_maximum_added_fire_damage"}},[2]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"},[2]={[1]="#",[2]="#"}},text="Adds %1% to %2% Cold Damage to Attacks"}}},name="attack_added_cold",stats={[1]="attack_minimum_added_cold_damage",[2]="attack_maximum_added_cold_damage"}},[3]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"},[2]={[1]="#",[2]="#"}},text="Buff grants %1% to %2% Added Attack Lightning Damage"}}},name="attack_added_lightning",stats={[1]="attack_minimum_added_lightning_damage",[2]="attack_maximum_added_lightning_damage"}},[4]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"},[2]={[1]="#",[2]="#"}},text="Buff grants %1% to %2% Added Spell Lightning Damage"}}},name="spell_added_lightning",stats={[1]="spell_minimum_added_lightning_damage",[2]="spell_maximum_added_lightning_damage"}},[5]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Buff grants %1%%% more Burning Damage"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="Buff grants %1%%% less Burning Damage"}}},name="herald_of_ash_burning_damage",stats={[1]="herald_of_ash_burning_damage_+%_final"}},[6]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Buff grants %1%%% increased Fire Damage"}}},name="herald_of_ash_fire_damage_incr",stats={[1]="herald_of_ash_fire_damage_+%"}},[7]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Buff grants %1%%% more Spell Fire Damage"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="Buff grants %1%%% less Spell Fire Damage"}}},name="herald_of_ash_spell_fire_damage_incr",stats={[1]="herald_of_ash_spell_fire_damage_+%_final"}},[8]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Buff grants %1%%% increased Cold Damage"}}},name="herald_of_ice_cold_damage_incr",stats={[1]="herald_of_ice_cold_damage_+%"}},[9]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Buff grants %1%%% increased Lightning Damage"}}},name="herald_of_thunder_lightning_damage_incr",stats={[1]="herald_of_thunder_lightning_damage_+%"}},[10]={lang={English={[1]={[1]={k="reminderstring",v="ReminderTextPhasing"},limit={[1]={[1]="#",[2]="#"}},text="Buff grants Phasing"}}},name="phasing",stats={[1]="phase_through_objects"}},[11]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Buff grants %1$+d to Armour"}}},name="base_armour",stats={[1]="base_physical_damage_reduction_rating"}},[12]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Buff grants %1%%% additional Physical Damage Reduction per Endurance Charge"}}},name="endurance_charge_phys_reduction",stats={[1]="physical_damage_reduction_%_per_endurance_charge"}},[13]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Buff grants %1$+d%% to all Resistances per Endurance Charge"}}},name="endurance_charge_ele_resist",stats={[1]="resist_all_elements_%_per_endurance_charge"}},[14]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Buff grants %1%%% more Armour"}}},name="vaal_molten_shall_armour_incr",stats={[1]="vaal_molten_shall_armour_+%_final"}},["attack_maximum_added_cold_damage"]=2,["attack_maximum_added_fire_damage"]=1,["attack_maximum_added_lightning_damage"]=3,["attack_minimum_added_cold_damage"]=2,["attack_minimum_added_fire_damage"]=1,["attack_minimum_added_lightning_damage"]=3,["base_physical_damage_reduction_rating"]=11,["herald_of_ash_burning_damage_+%_final"]=5,["herald_of_ash_fire_damage_+%"]=6,["herald_of_ash_spell_fire_damage_+%_final"]=7,["herald_of_ice_cold_damage_+%"]=8,["herald_of_thunder_lightning_damage_+%"]=9,parent="skill_stat_descriptions",["phase_through_objects"]=10,["physical_damage_reduction_%_per_endurance_charge"]=12,["resist_all_elements_%_per_endurance_charge"]=13,["spell_maximum_added_lightning_damage"]=4,["spell_minimum_added_lightning_damage"]=4,["vaal_molten_shall_armour_+%_final"]=14} -------------------------------------------------------------------------------- /Data/3_0/StatDescriptions/minion_spell_skill_stat_descriptions.lua: -------------------------------------------------------------------------------- 1 | return {[1]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="This Spell and Minions have %1%%% increased Cast Speed"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="This Spell and Minions have %1%%% reduced Cast Speed"}}},name="cast_speed_incr",stats={[1]="base_cast_speed_+%"}},[2]={lang={English={[1]={[1]={k="reminderstring",v="ReminderTextLowLife"},limit={[1]={[1]=1,[2]="#"}},text="This Spell and Minions have %1%%% increased Cast Speed when on Low Life"},[2]={[1]={k="negate",v=1},[2]={k="reminderstring",v="ReminderTextLowLife"},limit={[1]={[1]="#",[2]=-1}},text="This Spell and Minions have %1%%% reduced Cast Speed when on Low Life"}}},name="cast_speed_incr_on_low_life",stats={[1]="cast_speed_+%_when_on_low_life"}},[3]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="This Spell and Minions have %1%%% more Cast Speed"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="This Spell and Minions have %1%%% less Cast Speed"}}},name="multicast_cast_speed_incr",stats={[1]="support_multicast_cast_speed_+%_final"}},[4]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="This Spell and Minions have %1%%% more Cast Speed"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="This Spell and Minions have %1%%% less Cast Speed"}}},name="totem_cast_speed",stats={[1]="support_spell_totem_cast_speed_+%_final"}},[5]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Minion's Melee Strike Skills deal Fire-only Splash Damage to Surrounding Targets"}}},name="melee_splash_fire_only",stats={[1]="summon_raging_spirit_melee_splash_fire_damage_only"}},[6]={lang={English={[1]={[1]={k="reminderstring",v="ReminderTextMultipleMines"},limit={[1]={[1]="#",[2]="#"}},text="This Skill and Minions have %1%%% chance to throw up to 1 additional Trap or Mine"}}},stats={[1]="support_additional_trap_mine_%_chance_for_1_additional_trap_mine"}},[7]={lang={English={[1]={[1]={k="reminderstring",v="ReminderTextMultipleMines"},limit={[1]={[1]="#",[2]="#"}},text="This Skill and Minions have %1%%% chance to throw up to 2 additional Traps or Mines"}}},stats={[1]="support_additional_trap_mine_%_chance_for_2_additional_trap_mine"}},[8]={lang={English={[1]={[1]={k="reminderstring",v="ReminderTextMultipleMines"},limit={[1]={[1]="#",[2]="#"}},text="This Skill and Minions have %1%%% chance to throw up to 3 additional Traps or Mines"}}},stats={[1]="support_additional_trap_mine_%_chance_for_3_additional_trap_mine"}},["base_cast_speed_+%"]=1,["cast_speed_+%_when_on_low_life"]=2,parent="minion_skill_stat_descriptions",["summon_raging_spirit_melee_splash_fire_damage_only"]=5,["support_additional_trap_mine_%_chance_for_1_additional_trap_mine"]=6,["support_additional_trap_mine_%_chance_for_2_additional_trap_mine"]=7,["support_additional_trap_mine_%_chance_for_3_additional_trap_mine"]=8,["support_multicast_cast_speed_+%_final"]=3,["support_spell_totem_cast_speed_+%_final"]=4} -------------------------------------------------------------------------------- /Data/3_0/StatDescriptions/offering_skill_stat_descriptions.lua: -------------------------------------------------------------------------------- 1 | return {[1]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"},[2]={[1]="#",[2]="#"}},text="Sacrifices %1%%% of your Life\nMinions Regenerate %2%%% of Sacrificed Life per second"}}},name="blood_offering_life_loss",stats={[1]="blood_offering_%_of_life_to_lose",[2]="blood_offering_%_of_lost_life_to_regenerate_as_life_per_second"}},[2]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="%1%%% more Life Regeneration granted to Minions per corpse Consumed"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="%1%%% less Life Regeneration granted to Minions per corpse Consumed"}}},name="blood_offering_life_regen_multi",stats={[1]="blood_offering_life_regenerated_+%_final_per_corpse"}},[3]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Grants Minions %1%%% increased Attack Speed"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="Grants Minions %1%%% reduced Attack Speed"}}},name="attack_speed_incr_skill_granted",stats={[1]="attack_speed_+%_granted_from_skill"}},[4]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Grants Minions %1%%% increased Damage"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="Grants Minions %1%%% reduced Damage"}}},name="damage_incr",stats={[1]="damage_+%"}},[5]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Grants Minions %1%%% increased Cast Speed"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="Grants Minions %1%%% reduced Cast Speed"}}},name="cast_speed_incr_skill_granted",stats={[1]="cast_speed_+%_granted_from_skill"}},[6]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Grants Minions %1%%% increased Movement Speed"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="Grants Minions %1%%% reduced Movement Speed"}}},name="movement_speed_incr",stats={[1]="base_movement_velocity_+%"}},[7]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Grants Minions %1$+d%% Chance to Block Attack Damage"}}},name="base_block",stats={[1]="monster_base_block_%"}},[8]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Grants Minions %1$+d%% Chance to Block Spell Damage"}}},name="base_spell_block",stats={[1]="base_spell_block_%"}},[9]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Minions recover %1% Life when they Block"}}},name="recover_life_on_block",stats={[1]="recover_X_life_on_block"}},[10]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Minions gain %1%%% of their Physical Damage as Extra Chaos Damage"}}},name="physical_damage_to_add_as_chaos",stats={[1]="physical_damage_%_to_add_as_chaos"}},[11]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Minions gain %1%%% of their Maximum Life as\nExtra Maximum Energy Shield for each corpse Consumed"}}},name="spirit_offering_life_as_es_per_corpse",stats={[1]="spirit_offering_life_%_added_as_base_maximum_energy_shield_per_corpse_consumed"}},[12]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Grants Minions +%1%%% to Chaos Resistance"}}},name="chaos_res",stats={[1]="base_chaos_damage_resistance_%"}},[13]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Minions gain %1$+d%% to all Elemental Resistances"}}},name="elemental_resist",stats={[1]="base_resist_all_elements_%"}},["attack_speed_+%_granted_from_skill"]=3,["base_chaos_damage_resistance_%"]=12,["base_movement_velocity_+%"]=6,["base_resist_all_elements_%"]=13,["base_spell_block_%"]=8,["blood_offering_%_of_life_to_lose"]=1,["blood_offering_%_of_lost_life_to_regenerate_as_life_per_second"]=1,["blood_offering_life_regenerated_+%_final_per_corpse"]=2,["cast_speed_+%_granted_from_skill"]=5,["damage_+%"]=4,["monster_base_block_%"]=7,parent="skill_stat_descriptions",["physical_damage_%_to_add_as_chaos"]=10,["recover_X_life_on_block"]=9,["spirit_offering_life_%_added_as_base_maximum_energy_shield_per_corpse_consumed"]=11} -------------------------------------------------------------------------------- /Data/3_0/StatDescriptions/variable_duration_skill_stat_descriptions.lua: -------------------------------------------------------------------------------- 1 | return {[1]={lang={English={[1]={[1]={k="reminderstring",v="ReminderTextDamagingAilments"},limit={[1]={[1]=1,[2]="#"}},text="%1%%% increased Duration of this Skill and Damaging Ailments"},[2]={[1]={k="negate",v=1},[2]={k="reminderstring",v="ReminderTextDamagingAilments"},limit={[1]={[1]="#",[2]=-1}},text="%1%%% reduced Duration of this Skill and Damaging Ailments"}}},name="skill_and_damaging_ailment_duration_incr",stats={[1]="skill_effect_and_damaging_ailment_duration_+%"}},[2]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="%1%%% increased Duration "},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="%1%%% reduced Duration "}}},name="skill_duration_incr",stats={[1]="skill_effect_duration_+%"}},[3]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="%1%%% more Duration "},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="%1%%% less Duration "}}},name="support_less_duration",stats={[1]="support_reduced_duration_skill_effect_duration_+%_final"}},parent="skill_stat_descriptions",["skill_effect_and_damaging_ailment_duration_+%"]=1,["skill_effect_duration_+%"]=2,["support_reduced_duration_skill_effect_duration_+%_final"]=3} -------------------------------------------------------------------------------- /Data/New.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- Upcoming uniques will live here until their mods/rolls are finalised 3 | -- 4 | 5 | data.uniques.new = { 6 | -- 3.10 7 | [[ 8 | Calamitous Visions 9 | Small Cluster Jewel 10 | Adds Lone Messenger 11 | ]],[[ 12 | Kitava's Teachings 13 | Small Cluster Jewel 14 | Adds Disciple of Kitava 15 | ]],[[ 16 | Natural Affinity 17 | Small Cluster Jewel 18 | Adds Nature's Patience 19 | ]],[[ 20 | One With Nothing 21 | Small Cluster Jewel 22 | Adds Hollow Palm Technique 23 | ]],[[ 24 | The Front Line 25 | Small Cluster Jewel 26 | Adds Veteran's Awareness 27 | ]],[[ 28 | The Interrogation 29 | Small Cluster Jewel 30 | Adds Secrets of Suffering 31 | ]],[[ 32 | The Siege 33 | Small Cluster Jewel 34 | Adds Kineticism 35 | ]],[[ 36 | Voices 37 | Large Cluster Jewel 38 | Variant: {3_0}Adds 1 Small Passive Skill 39 | Variant: Adds 3 Small Passive Skills 40 | Variant: Adds 5 Small Passive Skills 41 | Variant: Adds 7 Small Passive Skills 42 | Adds 3 Jewel Socket Passive Skills 43 | {variant:1}Adds 1 Small Passive Skill which grants nothing 44 | {variant:2}Adds 3 Small Passive Skills which grant nothing 45 | {variant:3}Adds 5 Small Passive Skills which grant nothing 46 | {variant:4}Adds 7 Small Passive Skills which grant nothing 47 | ]], 48 | 49 | 50 | -- New 51 | [[ 52 | Glorious Vanity 53 | Timeless Jewel 54 | League: Legion 55 | Source: Drops from normal{Vaal} legion 56 | Limited to: 1 Historic 57 | Radius: Large 58 | Bathed in the blood of (100-8000) sacrificed in the name of Doryani 59 | Passives in radius are Conquered by the Vaal 60 | Historic 61 | ]],[[ 62 | Brutal Restraint 63 | Timeless Jewel 64 | League: Legion 65 | Source: Drops from normal{Maraketh} legion 66 | Limited to: 1 Historic 67 | Radius: Large 68 | Denoted service of (500-8000) dekhara in the akhara of Deshret 69 | Passives in radius are Conquered by the Maraketh 70 | Historic 71 | ]],[[ 72 | Elegant Hubris 73 | Timeless Jewel 74 | League: Legion 75 | Source: Drops from normal{Eternal} legion 76 | Limited to: 1 Historic 77 | Radius: Large 78 | Commissioned (2000-160000) coins to commemorate Cadiro 79 | Passives in radius are Conquered by the Eternal Empire 80 | Historic 81 | ]],[[ 82 | Lethal Pride 83 | Timeless Jewel 84 | League: Legion 85 | Source: Drops from normal{Karui} legion 86 | Limited to: 1 Historic 87 | Radius: Large 88 | Commanded leadership over (10000-18000) warriors under Kaom 89 | Passives in radius are Conquered by the Karui 90 | Historic 91 | ]],[[ 92 | Militant Faith 93 | Timeless Jewel 94 | League: Legion 95 | Source: Drops from normal{Templar} legion 96 | Limited to: 1 Historic 97 | Radius: Large 98 | Carved to glorify (2000-10000) new faithful converted by High Templar Venarius 99 | Passives in radius are Conquered by the Templars 100 | Historic 101 | ]], 102 | } 103 | 104 | -- Automatically generate Megalomaniac because like heck I'm entering all those variants manually lol 105 | local lines = { 106 | "Megalomaniac", 107 | "Medium Cluster Jewel", 108 | "Has Alt Variant: true", 109 | "Has Alt Variant Two: true", 110 | "Adds 4 Passive Skills", 111 | "Added Small Passive Skills grant Nothing", 112 | } 113 | local notables = { } 114 | for name in pairs(data["3_0"].clusterJewels.notableSortOrder) do 115 | table.insert(notables, name) 116 | end 117 | table.sort(notables) 118 | for index, name in ipairs(notables) do 119 | table.insert(lines, "Variant: "..name) 120 | table.insert(lines, "{variant:"..index.."}1 Added Passive Skill is "..name) 121 | end 122 | table.insert(data.uniques.new, table.concat(lines, '\n')) -------------------------------------------------------------------------------- /Export/Bases/amulet.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Amulet 5 | #baseTags amulet 6 | 7 | #baseMatch Metadata/Items/Amulets/Amulet%d+ 8 | #base Metadata/Items/Amulet/AmuletAtlas1 9 | #base Metadata/Items/Amulet/AmuletAtlas2 10 | 11 | #base Metadata/Items/Amulet/AmuletVictor1 12 | 13 | #subType Talisman 14 | #baseMatch Metadata/Items/Amulets/Talismans/Talisman -------------------------------------------------------------------------------- /Export/Bases/axe.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type One Handed Axe 5 | #baseTags weapon onehand axe one_hand_weapon 6 | #socketLimit 3 7 | #baseMatch Metadata/Items/Weapons/OneHandWeapons/OneHandAxes/OneHandAxe 8 | 9 | #type Two Handed Axe 10 | #baseTags weapon twohand axe two_hand_weapon 11 | #socketLimit 6 12 | #baseMatch Metadata/Items/Weapons/TwoHandWeapons/TwoHandAxes/TwoHandAxe 13 | -------------------------------------------------------------------------------- /Export/Bases/belt.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Belt 5 | #baseTags belt 6 | #baseMatch Metadata/Items/Belts/Belt%d+ 7 | #base Metadata/Items/Belts/BeltAtlas1 8 | #base Metadata/Items/Belts/BeltAtlas2 9 | #base Metadata/Items/Belts/BeltAbyss 10 | 11 | #base Metadata/Items/Belts/BeltDemigods1 -------------------------------------------------------------------------------- /Export/Bases/body.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Body Armour 5 | #baseTags armour body_armour 6 | #socketLimit 6 7 | 8 | #subType Armour 9 | #baseMatch Metadata/Items/Armours/BodyArmours/BodyStr%d+ 10 | 11 | #subType Evasion 12 | #baseMatch Metadata/Items/Armours/BodyArmours/BodyDex%d+ 13 | 14 | #subType Energy Shield 15 | #baseMatch Metadata/Items/Armours/BodyArmours/BodyInt%d+ 16 | 17 | #subType Armour/Evasion 18 | #baseMatch Metadata/Items/Armours/BodyArmours/BodyStrDex%d+ 19 | 20 | #subType Armour/Energy Shield 21 | #baseMatch Metadata/Items/Armours/BodyArmours/BodyStrInt%d+ 22 | 23 | #subType Evasion/Energy Shield 24 | #baseMatch Metadata/Items/Armours/BodyArmours/BodyDexInt%d+ 25 | 26 | #subType Armour/Evasion/Energy Shield 27 | #baseMatch Metadata/Items/Armours/BodyArmours/BodyStrDexInt%d+ 28 | #forceHide true 29 | #base Metadata/Items/Armours/BodyArmours/BodyDemigods1 -------------------------------------------------------------------------------- /Export/Bases/boots.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Boots 5 | #baseTags armour boots 6 | #socketLimit 4 7 | 8 | #subType Armour 9 | #baseMatch Metadata/Items/Armours/Boots/BootsStr%d+ 10 | 11 | #subType Evasion 12 | #baseMatch Metadata/Items/Armours/Boots/BootsDex%d+ 13 | 14 | #subType Energy Shield 15 | #baseMatch Metadata/Items/Armours/Boots/BootsInt%d+ 16 | 17 | #subType Armour/Evasion 18 | #baseMatch Metadata/Items/Armours/Boots/BootsStrDex%d+ 19 | #forceShow true 20 | #base Metadata/Items/Armours/Boots/BootsAtlas2 Two-Toned Boots (Armour/Evasion) 21 | #forceShow false 22 | 23 | #subType Armour/Energy Shield 24 | #baseMatch Metadata/Items/Armours/Boots/BootsStrInt%d+ 25 | #forceShow true 26 | #base Metadata/Items/Armours/Boots/BootsAtlas3 Two-Toned Boots (Armour/Energy Shield) 27 | #forceShow false 28 | 29 | #subType Evasion/Energy Shield 30 | #baseMatch Metadata/Items/Armours/Boots/BootsDexInt%d+ 31 | #forceShow true 32 | #base Metadata/Items/Armours/Boots/BootsAtlas1 Two-Toned Boots (Evasion/Energy Shield) 33 | #forceShow false 34 | 35 | #subType 36 | #base Metadata/Items/Armours/Boots/BootsDemigods1 -------------------------------------------------------------------------------- /Export/Bases/bow.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Bow 5 | #baseTags weapon twohand bow ranged two_hand_weapon 6 | #socketLimit 6 7 | #baseMatch Metadata/Items/Weapons/TwoHandWeapons/Bows/Bow -------------------------------------------------------------------------------- /Export/Bases/claw.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Claw 5 | #baseTags weapon onehand claw one_hand_weapon 6 | #socketLimit 3 7 | #baseMatch Metadata/Items/Weapons/OneHandWeapons/Claws/Claw -------------------------------------------------------------------------------- /Export/Bases/dagger.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Dagger 5 | #baseTags weapon onehand dagger one_hand_weapon 6 | #socketLimit 3 7 | #baseMatch Metadata/Items/Weapons/OneHandWeapons/Daggers/Dagger -------------------------------------------------------------------------------- /Export/Bases/flask.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Flask 5 | #subType Life 6 | #baseTags flask life_flask 7 | #baseMatch Metadata/Items/Flasks/FlaskLife 8 | 9 | #subType Mana 10 | #baseTags flask mana_flask 11 | #baseMatch Metadata/Items/Flasks/FlaskMana 12 | 13 | #subType Hybrid 14 | #baseTags flask hybrid_flask 15 | #baseMatch Metadata/Items/Flasks/FlaskHybrid 16 | 17 | #subType Utility 18 | #baseTags flask utility_flask 19 | #baseMatch Metadata/Items/Flasks/FlaskUtility 20 | #baseTags flask utility_flask critical_utility_flask 21 | #base Metadata/Items/Flasks/FlaskUtility1 -------------------------------------------------------------------------------- /Export/Bases/gloves.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Gloves 5 | #baseTags armour gloves 6 | #socketLimit 4 7 | 8 | #subType Armour 9 | #baseMatch Metadata/Items/Armours/Gloves/GlovesStr%d+ 10 | #base Metadata/Items/Armours/Gloves/GlovesAtlasStr 11 | 12 | #subType Evasion 13 | #baseMatch Metadata/Items/Armours/Gloves/GlovesDex%d+ 14 | #base Metadata/Items/Armours/Gloves/GlovesAtlasDex 15 | 16 | #subType Energy Shield 17 | #baseMatch Metadata/Items/Armours/Gloves/GlovesInt%d+ 18 | #base Metadata/Items/Armours/Gloves/GlovesAtlasInt 19 | 20 | #subType Armour/Evasion 21 | #baseMatch Metadata/Items/Armours/Gloves/GlovesStrDex%d+ 22 | 23 | #subType Armour/Energy Shield 24 | #baseMatch Metadata/Items/Armours/Gloves/GlovesStrInt%d+ 25 | 26 | #subType Evasion/Energy Shield 27 | #baseMatch Metadata/Items/Armours/Gloves/GlovesDexInt%d+ 28 | 29 | #subType 30 | #base Metadata/Items/Armours/Gloves/GlovesDemigods1 31 | -------------------------------------------------------------------------------- /Export/Bases/helmet.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Helmet 5 | #baseTags armour helmet 6 | #socketLimit 4 7 | 8 | #subType Armour 9 | #baseMatch Metadata/Items/Armours/Helmets/HelmetStr%d+ 10 | 11 | #subType Evasion 12 | #baseMatch Metadata/Items/Armours/Helmets/HelmetDex%d+ 13 | 14 | #subType Energy Shield 15 | #baseMatch Metadata/Items/Armours/Helmets/HelmetInt%d+ 16 | 17 | #subType Armour/Evasion 18 | #baseMatch Metadata/Items/Armours/Helmets/HelmetStrDex%d+ 19 | 20 | #subType Armour/Energy Shield 21 | #baseMatch Metadata/Items/Armours/Helmets/HelmetStrInt%d+ 22 | #base Metadata/Items/Armours/Helmets/HelmetAtlas1 23 | 24 | #subType Evasion/Energy Shield 25 | #baseMatch Metadata/Items/Armours/Helmets/HelmetDexInt%d+ 26 | 27 | #subType 28 | #base Metadata/Items/Armours/Helmets/HelmetWreath1 29 | -------------------------------------------------------------------------------- /Export/Bases/jewel.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Jewel 5 | #baseTags 6 | #base Metadata/Items/Jewels/JewelStr 7 | #base Metadata/Items/Jewels/JewelDex 8 | #base Metadata/Items/Jewels/JewelInt 9 | #base Metadata/Items/Jewels/JewelPrismatic 10 | #base Metadata/Items/Jewels/JewelTimeless 11 | 12 | #subType Abyss 13 | #base Metadata/Items/Jewels/JewelAbyssSummoner 14 | #base Metadata/Items/Jewels/JewelAbyssCaster 15 | #base Metadata/Items/Jewels/JewelAbyssMelee 16 | #base Metadata/Items/Jewels/JewelAbyssRanged 17 | 18 | #subType Cluster 19 | #base Metadata/Items/Jewels/JewelPassiveTreeExpansionLarge 20 | #base Metadata/Items/Jewels/JewelPassiveTreeExpansionMedium 21 | #base Metadata/Items/Jewels/JewelPassiveTreeExpansionSmall -------------------------------------------------------------------------------- /Export/Bases/mace.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type One Handed Mace 5 | #baseTags weapon onehand mace one_hand_weapon 6 | #socketLimit 3 7 | #baseMatch Metadata/Items/Weapons/OneHandWeapons/OneHandMaces/OneHandMace 8 | 9 | #type Sceptre 10 | #baseMatch Metadata/Items/Weapons/OneHandWeapons/OneHandMaces/Sceptre 11 | 12 | #type Two Handed Mace 13 | #baseTags weapon twohand mace two_hand_weapon 14 | #socketLimit 6 15 | #baseMatch Metadata/Items/Weapons/TwoHandWeapons/TwoHandMaces/TwoHandMace 16 | -------------------------------------------------------------------------------- /Export/Bases/quiver.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Quiver 5 | #baseTags quiver 6 | #baseMatch Metadata/Items/Quivers/Quiver%d+ 7 | -------------------------------------------------------------------------------- /Export/Bases/ring.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Ring 5 | #baseTags ring 6 | 7 | #baseMatch Metadata/Items/Rings/Ring%d+ 8 | #forceShow true 9 | #base Metadata/Items/Rings/Ring12 Two-Stone Ring (Fire/Lightning) 10 | #base Metadata/Items/Rings/Ring13 Two-Stone Ring (Cold/Lightning) 11 | #base Metadata/Items/Rings/Ring14 Two-Stone Ring (Fire/Cold) 12 | #forceShow false 13 | #base Metadata/Items/Rings/RingAtlas1 14 | #base Metadata/Items/Rings/RingAtlas2 15 | #base Metadata/Items/Rings/RingAtlas3 16 | #base Metadata/Items/Rings/RingAtlas4 17 | 18 | #base Metadata/Items/Rings/BreachRing 19 | #base Metadata/Items/Rings/RingDemigods1 20 | #base Metadata/Items/Rings/RingVictor1 -------------------------------------------------------------------------------- /Export/Bases/shield.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Shield 5 | #baseTags armour shield 6 | #socketLimit 3 7 | 8 | #subType Armour 9 | #baseMatch Metadata/Items/Armours/Shields/ShieldStr%d+ 10 | 11 | #subType Evasion 12 | #baseMatch Metadata/Items/Armours/Shields/ShieldDex%d+ 13 | 14 | #subType Energy Shield 15 | #baseMatch Metadata/Items/Armours/Shields/ShieldInt%d+ 16 | 17 | #subType Armour/Evasion 18 | #baseMatch Metadata/Items/Armours/Shields/ShieldStrDex%d+ 19 | 20 | #subType Armour/Energy Shield 21 | #baseMatch Metadata/Items/Armours/Shields/ShieldStrInt%d+ 22 | 23 | #subType Evasion/Energy Shield 24 | #baseMatch Metadata/Items/Armours/Shields/ShieldDexInt%d+ 25 | 26 | #subType 27 | #base Metadata/Items/Armours/Shields/ShieldDemigods -------------------------------------------------------------------------------- /Export/Bases/staff.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Staff 5 | #baseTags weapon twohand staff two_hand_weapon 6 | #socketLimit 6 7 | #baseMatch Metadata/Items/Weapons/TwoHandWeapons/Staves/Staff -------------------------------------------------------------------------------- /Export/Bases/sword.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type One Handed Sword 5 | #socketLimit 3 6 | #baseTags weapon onehand sword one_hand_weapon 7 | 8 | #baseMatch Metadata/Items/Weapons/OneHandWeapons/OneHandSwords/OneHandSword 9 | 10 | #base Metadata/items/Weapons/OneHandWeapons/OneHandSwords/OneHandSwordC 11 | 12 | #type Thrusting One Handed Sword 13 | #baseMatch Metadata/Items/Weapons/OneHandWeapons/OneHandThrustingSwords/Rapier 14 | 15 | #type Two Handed Sword 16 | #socketLimit 6 17 | #baseTags weapon twohand sword two_hand_weapon 18 | #baseMatch Metadata/Items/Weapons/TwoHandWeapons/TwoHandSwords/TwoHandSword 19 | -------------------------------------------------------------------------------- /Export/Bases/wand.txt: -------------------------------------------------------------------------------- 1 | -- Item data (c) Grinding Gear Games 2 | local itemBases = ... 3 | 4 | #type Wand 5 | #baseTags weapon onehand wand ranged one_hand_weapon 6 | #socketLimit 3 7 | #baseMatch Metadata/Items/Weapons/OneHandWeapons/Wands/Wand -------------------------------------------------------------------------------- /Export/Classes/DatListControl.lua: -------------------------------------------------------------------------------- 1 | -- Dat View 2 | -- 3 | -- Class: Dat List 4 | -- Dat list control. 5 | -- 6 | local ipairs = ipairs 7 | local t_insert = table.insert 8 | local t_remove = table.remove 9 | 10 | local DatListClass = newClass("DatListControl", "ListControl", function(self, anchor, x, y, width, height) 11 | self.ListControl(anchor, x, y, width, height, 14, false, false, main.datFileList) 12 | end) 13 | 14 | function DatListClass:GetRowValue(column, index, datFile) 15 | if column == 1 then 16 | return "^7"..datFile.name 17 | end 18 | end 19 | 20 | function DatListClass:OnSelect(index, datFile) 21 | main:SetCurrentDat(datFile) 22 | end 23 | 24 | function DatListClass:OnAnyKeyDown(key) 25 | if key:match("%a") then 26 | for i = 1, #self.list do 27 | local valIndex = ((self.selIndex or 1) - 1 + i) % #self.list + 1 28 | local val = self.list[valIndex] 29 | if val.name:sub(1, 1):lower() == key:lower() then 30 | self:SelectIndex(valIndex) 31 | return 32 | end 33 | end 34 | end 35 | end -------------------------------------------------------------------------------- /Export/Classes/GGPKFile.lua: -------------------------------------------------------------------------------- 1 | -- Dat View 2 | -- 3 | -- Class: GGPK File 4 | -- GGPK File 5 | -- 6 | local ipairs = ipairs 7 | local t_insert = table.insert 8 | local t_remove = table.remove 9 | 10 | local GGPKClass = newClass("GGPKFile", function(self, path) 11 | self.path = path 12 | 13 | self.ggpk = { } 14 | self:ReadRecord(self.ggpk) 15 | for i = 1, self.ggpk.numRecord do 16 | self:ReadRecord(self.ggpk.recordList[i]) 17 | end 18 | end) 19 | 20 | function GGPKClass:Open() 21 | if not self.file then 22 | self.file = io.open(self.path, "rb") 23 | end 24 | end 25 | 26 | function GGPKClass:Close() 27 | if self.file then 28 | self.file:close() 29 | self.file = nil 30 | end 31 | end 32 | 33 | function GGPKClass:ReadRecord(record) 34 | self:Open() 35 | self.file:seek("set", record.offset) 36 | local raw = self.file:read(8) 37 | record.length = bytesToUInt(raw, 1) 38 | record.tag = raw:sub(5) 39 | if record.tag == "GGPK" then 40 | raw = self.file:read(4) 41 | record.numRecord = bytesToUInt(raw, 1) 42 | raw = self.file:read(record.numRecord * 8) 43 | record.recordList = { } 44 | for i = 1, record.numRecord do 45 | record.recordList[i] = { 46 | offset = bytesToULong(raw, (i-1) * 8 + 1), 47 | } 48 | end 49 | -- ConPrintf("GGPK: %d records", record.numRecord) 50 | elseif record.tag == "PDIR" then 51 | raw = self.file:read(40) 52 | local nameLength = bytesToUInt(raw, 1) 53 | record.numRecord = bytesToUInt(raw, 5) 54 | record.hash = raw:sub(9) 55 | raw = self.file:read(nameLength * 2 + record.numRecord * 12) 56 | record.name = convertUTF16to8(raw) 57 | record.recordList = { } 58 | for i = 1, record.numRecord do 59 | record.recordList[i] = { 60 | nameHash = bytesToUInt(raw, nameLength * 2 + (i-1) * 12 + 1), 61 | offset = bytesToULong(raw, nameLength * 2 + (i-1) * 12 + 5), 62 | } 63 | end 64 | -- ConPrintf("PDIR '%s': %d records", record.name, record.numRecord) 65 | elseif record.tag == "FILE" then 66 | raw = self.file:read(36) 67 | local nameLength = bytesToUInt(raw, 1) 68 | record.hash = raw:sub(5) 69 | record.name = convertUTF16to8(self.file:read(nameLength * 2)) 70 | local headLength = 44 + nameLength * 2 71 | record.dataOffset = record.offset + headLength 72 | record.dataLength = record.length - headLength 73 | -- ConPrintf("FILE '%s': %d bytes", record.name, record.dataLength) 74 | elseif record.tag == "FREE" then 75 | record.nextFree = bytesToULong(self.file:read(8)) 76 | -- ConPrintf("FREE") 77 | end 78 | record.read = true 79 | end 80 | 81 | function GGPKClass:GetRecord(name) 82 | self:Open() 83 | local record = self.ggpk.recordList[1] 84 | for part in name:gmatch("[^\\/]+") do 85 | if not record.recordList then 86 | self:ReadRecord(record) 87 | end 88 | local hash = murmurHash2(convertUTF8to16(part:lower())) 89 | local found 90 | for _, record in ipairs(record.recordList) do 91 | if record.nameHash == hash then 92 | found = record 93 | break 94 | end 95 | end 96 | if not found then 97 | return 98 | end 99 | record = found 100 | end 101 | return record 102 | end 103 | 104 | function GGPKClass:ReadFile(name) 105 | local record = self:GetRecord(name) 106 | if record then 107 | if not record.read then 108 | self:ReadRecord(record) 109 | end 110 | if record.tag == "FILE" then 111 | self.file:seek("set", record.dataOffset) 112 | return self.file:read(record.dataLength) 113 | end 114 | end 115 | end 116 | 117 | function GGPKClass:Find(path, name) 118 | local out = { } 119 | local dir = self:GetRecord(path) 120 | if not dir.read then 121 | self:ReadRecord(dir) 122 | end 123 | for _, record in ipairs(dir.recordList) do 124 | if not record.read then 125 | self:ReadRecord(record) 126 | end 127 | if record.name and record.name:match(name) then 128 | local result = { } 129 | result.name = record.name 130 | result.dir = record.tag == "PDIR" 131 | result.fullName = path .. "/" .. record.name 132 | if record.tag == "FILE" then 133 | self.file:seek("set", record.dataOffset) 134 | result.data = self.file:read(record.dataLength) 135 | end 136 | t_insert(out, result) 137 | end 138 | end 139 | table.sort(out, function(a,b) return a.name < b.name end) 140 | return out 141 | end -------------------------------------------------------------------------------- /Export/Classes/RowListControl.lua: -------------------------------------------------------------------------------- 1 | -- Dat View 2 | -- 3 | -- Class: Row List 4 | -- Row list control. 5 | -- 6 | local ipairs = ipairs 7 | local t_insert = table.insert 8 | local t_remove = table.remove 9 | 10 | local RowListClass = newClass("RowListControl", "ListControl", function(self, anchor, x, y, width, height) 11 | self.ListControl(anchor, x, y, width, height, 14, true, false, { }) 12 | self.colLabels = true 13 | end) 14 | 15 | function RowListClass:BuildRows(filter) 16 | wipeTable(self.list) 17 | local filterFunc 18 | main.controls.filterError.label = "" 19 | if filter:match("%S") then 20 | local error 21 | filterFunc, error = loadstring([[ 22 | return ]]..filter..[[ 23 | ]]) 24 | if error then 25 | main.controls.filterError.label = "^7"..error 26 | end 27 | end 28 | for rowIndex, row in ipairs(main.curDatFile.rows) do 29 | if filterFunc then 30 | setfenv(filterFunc, main.curDatFile:GetRowByIndex(rowIndex)) 31 | local status, result = pcall(filterFunc) 32 | if status then 33 | if result then 34 | t_insert(self.list, rowIndex) 35 | end 36 | else 37 | main.controls.filterError.label = string.format("^7Row %d: %s", rowIndex, result) 38 | return 39 | end 40 | else 41 | t_insert(self.list, rowIndex) 42 | end 43 | end 44 | end 45 | 46 | function RowListClass:BuildColumns() 47 | wipeTable(self.colList) 48 | self.colList[1] = { width = 50, label = "#", font = "FIXED" } 49 | for _, specCol in ipairs(main.curDatFile.spec) do 50 | t_insert(self.colList, { width = specCol.width, label = specCol.name, font = function() return IsKeyDown("CTRL") and "FIXED" or "VAR" end }) 51 | end 52 | local short = main.curDatFile.rowSize - main.curDatFile.specSize 53 | if short > 0 then 54 | t_insert(self.colList, { width = short * DrawStringWidth(self.rowHeight, "FIXED", "00 "), font = "FIXED" }) 55 | end 56 | end 57 | 58 | function RowListClass:GetRowValue(column, index, row) 59 | if column == 1 then 60 | return string.format("%5d", row) 61 | end 62 | if not main.curDatFile.spec[column - 1] or IsKeyDown("CTRL") then 63 | local out = { main.curDatFile:ReadCellRaw(row, column - 1) } 64 | for i, b in ipairs(out) do 65 | out[i] = string.format("%02X", b) 66 | end 67 | return table.concat(out, main.curDatFile.spec[column - 1] and "" or " ") 68 | else 69 | local data = main.curDatFile:ReadCellText(row, column - 1) 70 | if type(data) == "table" then 71 | for i, v in ipairs(data) do 72 | data[i] = tostring(v) 73 | end 74 | return table.concat(data, ", ") 75 | else 76 | return tostring(data) 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /Export/Classes/ScriptListControl.lua: -------------------------------------------------------------------------------- 1 | -- Dat View 2 | -- 3 | -- Class: Script List 4 | -- Script list control. 5 | -- 6 | local ipairs = ipairs 7 | local t_insert = table.insert 8 | local t_remove = table.remove 9 | 10 | local ScriptListClass = newClass("ScriptListControl", "ListControl", function(self, anchor, x, y, width, height) 11 | self.ListControl(anchor, x, y, width, height, 16, false, false, main.scriptList) 12 | end) 13 | 14 | function ScriptListClass:GetRowValue(column, index, script) 15 | if column == 1 then 16 | return "^7"..script 17 | end 18 | end 19 | 20 | function ScriptListClass:OnSelClick(index, script, doubleClick) 21 | if doubleClick then 22 | local errMsg = PLoadModule("Scripts/"..script..".lua") 23 | if errMsg then 24 | print(errMsg) 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /Export/Classes/SpecColListControl.lua: -------------------------------------------------------------------------------- 1 | -- Dat View 2 | -- 3 | -- Class: Spec Col List 4 | -- Spec column list control. 5 | -- 6 | local ipairs = ipairs 7 | local t_insert = table.insert 8 | local t_remove = table.remove 9 | 10 | local SpecColListClass = newClass("SpecColListControl", "ListControl", function(self, anchor, x, y, width, height) 11 | self.ListControl(anchor, x, y, width, height, 14, false, true) 12 | end) 13 | 14 | function SpecColListClass:GetRowValue(column, index, specCol) 15 | if column == 1 then 16 | return #specCol.name > 0 and ("^7"..specCol.name) or "???" 17 | end 18 | end 19 | 20 | function SpecColListClass:OnSelect(index, specCol) 21 | main:SetCurrentCol(index) 22 | end 23 | 24 | function SpecColListClass:OnOrderChange() 25 | main.curDatFile:OnSpecChanged() 26 | main.controls.rowList:BuildColumns() 27 | end 28 | 29 | function SpecColListClass:OnSelDelete(index, specCol) 30 | t_remove(self.list, index) 31 | main:SetCurrentCol() 32 | main.curDatFile:OnSpecChanged() 33 | main.controls.rowList:BuildColumns() 34 | end -------------------------------------------------------------------------------- /Export/DatView.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{87760D8B-5D2D-4C32-8625-49292C0A2A02}" 7 | ProjectSection(SolutionItems) = preProject 8 | Launch.lua = Launch.lua 9 | Main.lua = Main.lua 10 | EndProjectSection 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Classes", "Classes", "{A517B8FF-61D0-4FD5-9037-1437259A0166}" 13 | ProjectSection(SolutionItems) = preProject 14 | Classes\DatFile.lua = Classes\DatFile.lua 15 | Classes\DatListControl.lua = Classes\DatListControl.lua 16 | Classes\GGPKFile.lua = Classes\GGPKFile.lua 17 | Classes\RowListControl.lua = Classes\RowListControl.lua 18 | Classes\ScriptListControl.lua = Classes\ScriptListControl.lua 19 | Classes\SpecColListControl.lua = Classes\SpecColListControl.lua 20 | EndProjectSection 21 | EndProject 22 | Global 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | GlobalSection(NestedProjects) = preSolution 27 | {A517B8FF-61D0-4FD5-9037-1437259A0166} = {87760D8B-5D2D-4C32-8625-49292C0A2A02} 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /Export/Export.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{ECF13334-6BFE-4F72-A68F-DF00F5C86DE7}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Skills", "Skills", "{740FE360-DB7C-403B-A6BD-61EDFAB1B54D}" 9 | ProjectSection(SolutionItems) = preProject 10 | ..\Data\3_0\Skills\act_dex.lua = ..\Data\3_0\Skills\act_dex.lua 11 | Skills\act_dex.txt = Skills\act_dex.txt 12 | ..\Data\3_0\Skills\act_int.lua = ..\Data\3_0\Skills\act_int.lua 13 | Skills\act_int.txt = Skills\act_int.txt 14 | ..\Data\3_0\Skills\act_str.lua = ..\Data\3_0\Skills\act_str.lua 15 | Skills\act_str.txt = Skills\act_str.txt 16 | ..\Data\3_0\Skills\glove.lua = ..\Data\3_0\Skills\glove.lua 17 | Skills\glove.txt = Skills\glove.txt 18 | ..\Data\3_0\Skills\minion.lua = ..\Data\3_0\Skills\minion.lua 19 | Skills\minion.txt = Skills\minion.txt 20 | ..\Data\3_0\Skills\other.lua = ..\Data\3_0\Skills\other.lua 21 | Skills\other.txt = Skills\other.txt 22 | ..\Data\3_0\Skills\spectre.lua = ..\Data\3_0\Skills\spectre.lua 23 | Skills\spectre.txt = Skills\spectre.txt 24 | ..\Data\3_0\Skills\sup_dex.lua = ..\Data\3_0\Skills\sup_dex.lua 25 | Skills\sup_dex.txt = Skills\sup_dex.txt 26 | ..\Data\3_0\Skills\sup_int.lua = ..\Data\3_0\Skills\sup_int.lua 27 | Skills\sup_int.txt = Skills\sup_int.txt 28 | ..\Data\3_0\Skills\sup_str.lua = ..\Data\3_0\Skills\sup_str.lua 29 | Skills\sup_str.txt = Skills\sup_str.txt 30 | EndProjectSection 31 | EndProject 32 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Minions", "Minions", "{9FE6A1A9-0224-4724-9684-CC44B4540BE3}" 33 | ProjectSection(SolutionItems) = preProject 34 | ..\Data\3_0\Minions.lua = ..\Data\3_0\Minions.lua 35 | Minions\Minions.txt = Minions\Minions.txt 36 | Minions\modmap.ini = Minions\modmap.ini 37 | ..\Data\3_0\Spectres.lua = ..\Data\3_0\Spectres.lua 38 | Minions\Spectres.txt = Minions\Spectres.txt 39 | EndProjectSection 40 | EndProject 41 | Global 42 | GlobalSection(SolutionProperties) = preSolution 43 | HideSolutionNode = FALSE 44 | EndGlobalSection 45 | GlobalSection(NestedProjects) = preSolution 46 | {740FE360-DB7C-403B-A6BD-61EDFAB1B54D} = {ECF13334-6BFE-4F72-A68F-DF00F5C86DE7} 47 | {9FE6A1A9-0224-4724-9684-CC44B4540BE3} = {ECF13334-6BFE-4F72-A68F-DF00F5C86DE7} 48 | EndGlobalSection 49 | EndGlobal 50 | -------------------------------------------------------------------------------- /Export/Minions/Minions.txt: -------------------------------------------------------------------------------- 1 | -- Path of Building 2 | -- 3 | -- Minion Data 4 | -- Monster data (c) Grinding Gear Games 5 | -- 6 | local minions, mod = ... 7 | 8 | #monster Metadata/Monsters/RaisedZombies/RaisedZombieStandard RaisedZombie 9 | #limit ActiveZombieLimit 10 | #emit 11 | 12 | #monster Metadata/Monsters/ChaosElemental/ChaosElementalSummoned SummonedChaosGolem 13 | #limit ActiveGolemLimit 14 | #emit 15 | 16 | #monster Metadata/Monsters/FireElemental/FireElementalSummoned SummonedFlameGolem 17 | #limit ActiveGolemLimit 18 | #emit 19 | 20 | #monster Metadata/Monsters/IceElemental/IceElementalSummoned SummonedIceGolem 21 | #limit ActiveGolemLimit 22 | #emit 23 | 24 | #monster Metadata/Monsters/LightningGolem/LightningGolemSummoned SummonedLightningGolem 25 | #limit ActiveGolemLimit 26 | #emit 27 | 28 | #monster Metadata/Monsters/RockGolem/RockGolemSummoned SummonedStoneGolem 29 | #limit ActiveGolemLimit 30 | #emit 31 | 32 | #monster Metadata/Monsters/SummonedSkull/SummonedSkull SummonedRagingSpirit 33 | #limit ActiveRagingSpiritLimit 34 | #emit 35 | 36 | #monster Metadata/Monsters/SummonedSkull/SpectralSummonedSkull SummonedEssenceSpirit 37 | #mod mod("Condition:FullLife", "FLAG", true) 38 | #emit 39 | 40 | #monster Metadata/Monsters/Lion/SummonedSpectralWolf SummonedSpectralWolf 41 | #limit ActiveWolfLimit 42 | #emit 43 | 44 | #monster Metadata/Monsters/RaisedSkeletons/RaisedSkeletonStandard RaisedSkeleton 45 | #limit ActiveSkeletonLimit 46 | #emit 47 | 48 | #monster Metadata/Monsters/RaisedSkeletons/RaisedSkeletonSpellcaster1Army RaisedSkeletonCaster 49 | #limit ActiveSkeletonLimit 50 | #skill SkeletonMinionProjectileFire 51 | #skill SkeletonMinionProjectileLightning 52 | #emit 53 | 54 | #monster Metadata/Monsters/RaisedSkeletons/RaisedSkeletonRanged1Army RaisedSkeletonArcher 55 | #limit ActiveSkeletonLimit 56 | #emit 57 | 58 | #monster Metadata/Monsters/Clone/RangerClone Clone 59 | #emit 60 | 61 | #monster Metadata/Monsters/SummonedSpider/SummonedSpider SpiderMinion 62 | #limit ActiveSpiderLimit 63 | #emit 64 | 65 | #monster Metadata/Monsters/AnimatedItem/AnimatedWeapon AnimatedWeapon 66 | #emit 67 | 68 | #monster Metadata/Monsters/AnimatedItem/AnimatedArmour AnimatedArmour 69 | #mod mod("Speed", "MORE", 10, ModFlag.Attack, 0, { type = "Condition", var = "DualWielding" }) 70 | #mod mod("PhysicalDamage", "MORE", 20, ModFlag.Attack, 0, { type = "Condition", var = "DualWielding" }) 71 | #mod mod("BlockChance", "BASE", 15, 0, 0, { type = "Condition", var = "DualWielding" }) 72 | #emit 73 | 74 | #monster Metadata/Monsters/IcyRagingSpirit/IcyRagingSpirit IcyRagingSpirit 75 | #emit 76 | 77 | #monster Metadata/Monsters/AnimatedItem/UniqueAnimatedWeapon UniqueAnimatedWeapon 78 | #emit 79 | 80 | #monster Metadata/Monsters/SummonedPhantasm/SummonedPhantasm SummonedPhantasm 81 | #limit ActivePhantasmLimit 82 | #emit 83 | 84 | #monster Metadata/Monsters/SpiderPlated/HeraldOfAgonySpiderPlated HeraldOfAgonySpiderPlated 85 | #mod mod("Condition:FullLife", "FLAG", true) 86 | #emit 87 | 88 | #monster Metadata/Monsters/Axis/AxisEliteSoldierHeraldOfLight AxisEliteSoldierHeraldOfLight 89 | #emit 90 | 91 | #monster Metadata/Monsters/AnimatedItem/HolyLivingRelic HolyLivingRelic 92 | #limit ActiveHolyRelicLimit 93 | #emit 94 | 95 | #monster Metadata/Monsters/Axis/AxisEliteSoldierDominatingBlow AxisEliteSoldierDominatingBlow 96 | #emit 97 | 98 | #monster Metadata/Monsters/Rhoas/RhoaUniqueSummoned RhoaUniqueSummoned 99 | #limit ActiveBeastMinionLimit 100 | #emit 101 | 102 | #monster Metadata/Monsters/Snake/SnakeSpitUniqueSummoned SnakeSpitUniqueSummoned 103 | #limit ActiveBeastMinionLimit 104 | #emit 105 | 106 | #monster Metadata/Monsters/DropBear/DropBearUniqueSummoned DropBearUniqueSummoned 107 | #limit ActiveBeastMinionLimit 108 | #emit 109 | 110 | #monster Metadata/Monsters/BoneGolem/BoneGolem SummonedCarrionGolem 111 | #limit ActiveGolemLimit 112 | #emit -------------------------------------------------------------------------------- /Export/Minions/modmap.ini: -------------------------------------------------------------------------------- 1 | # General 2 | [MonsterMultipleProjectilesImplicit1] 3 | mod("ProjectileCount", "BASE", 2) 4 | [MonsterConvertToFireDamage2] 5 | mod("PhysicalDamageConvertToFire", "BASE", 50) 6 | [MonsterConvertToColdDamage2] 7 | mod("PhysicalDamageConvertToCold", "BASE", 50) 8 | [MonsterPhysicalAddedAsColdSkeletonMaps] 9 | mod("PhysicalDamageGainAsCold", "BASE", 100) 10 | [MonsterCurseCastSpeedPenalty] 11 | mod("Speed", "INC", -80, ModFlag.Cast, KeywordFlag.Curse) 12 | [MonsterImplicitDamageReduction1] 13 | mod("Armour", "INC", 40) 14 | [MonsterAttackBlock30Bypass15] 15 | mod("BlockChance", "BASE", 30) 16 | [MonsterAttackBlock40Bypass20] 17 | mod("BlockChance", "BASE", 40) 18 | [MonsterAlwaysHits] 19 | mod("CannotBeEvaded", "FLAG", true) 20 | 21 | # Type-specific 22 | [MonsterSnakeChaos] 23 | mod("PhysicalDamageConvertToChaos", "BASE", 30) 24 | [MonsterPhysicalAddedAsLightningSkeletonMaps] 25 | mod("PhysicalDamageGainAsLightning", "BASE", 100) 26 | [MonsterPhysicalAddedAsFireSkeletonMaps] 27 | mod("PhysicalDamageGainAsFire", "BASE", 100) 28 | [MonsterElementalSkeletonLightning] 29 | mod("PhysicalDamageConvertToLightning", "BASE", 50) 30 | [MonsterGoatmanShamanCastSpeed] 31 | mod("Speed", "INC", -50, ModFlag.Cast) 32 | [MonsterPhysicalAddedAsFireHolyFireElemental] 33 | mod("PhysicalDamageGainAsFire", "BASE", 60) 34 | [KaomWarriorSlowFireBeam2] 35 | mod("TotemLife", "INC", 250) 36 | [MonsterSummonedElementalFire] 37 | mod("PhysicalDamageConvertToFire", "BASE", 50) 38 | [MonsterSummonedElementalCold] 39 | mod("PhysicalDamageConvertToCold", "BASE", 50) 40 | [RagingSpiritAddedPhys] 41 | mod("PhysicalMin", "BASE", 4, ModFlag.Attack) 42 | mod("PhysicalMax", "BASE", 5, ModFlag.Attack) 43 | [MonsterSummonedSkullFastAttack1] 44 | mod("Speed", "MORE", 40, ModFlag.Attack) 45 | [MirrorArrowEnergyShield] 46 | mod("EnergyShield", "BASE", 10) 47 | [MonsterConvertToChaosHeraldOfAgony1] 48 | mod("PhysicalDamageConvertToChaos", "BASE", 40) -------------------------------------------------------------------------------- /Export/Scripts/cluster.lua: -------------------------------------------------------------------------------- 1 | if not loadStatFile then 2 | dofile("statdesc.lua") 3 | end 4 | loadStatFile("passive_skill_stat_descriptions.txt") 5 | 6 | local out = io.open("../Data/3_0/ClusterJewels.lua", "w") 7 | out:write('-- This file is automatically generated, do not edit!\n') 8 | out:write('-- Jewel data (c) Grinding Gear Games\n\nreturn {\n') 9 | 10 | out:write('\tjewels = {\n') 11 | for jewel in dat"PassiveTreeExpansionJewels":Rows() do 12 | out:write('\t\t["', jewel.BaseItemType.Name, '"] = {\n') 13 | out:write('\t\t\tsize = "', jewel.Size.Id, '",\n') 14 | out:write('\t\t\tsizeIndex = ', jewel.Size._rowIndex - 1, ',\n') 15 | out:write('\t\t\tminNodes = ', jewel.MinNodes, ',\n') 16 | out:write('\t\t\tmaxNodes = ', jewel.MaxNodes, ',\n') 17 | out:write('\t\t\tsmallIndicies = { ', table.concat(jewel.SmallIndicies, ', '), ' },\n') 18 | out:write('\t\t\tnotableIndicies = { ', table.concat(jewel.NotableIndicies, ', '), ' },\n') 19 | out:write('\t\t\tsocketIndicies = { ', table.concat(jewel.SocketIndicies, ', '), ' },\n') 20 | out:write('\t\t\ttotalIndicies = ', jewel.TotalIndicies, ',\n') 21 | out:write('\t\t\tskills = {\n') 22 | for index, skill in ipairs(dat"PassiveTreeExpansionSkills":GetRowList("JewelSize", jewel.Size)) do 23 | out:write('\t\t\t\t["', skill.Node.Id, '"] = {\n') 24 | out:write('\t\t\t\t\tname = "', skill.Node.Name, '",\n') 25 | out:write('\t\t\t\t\ticon = "', skill.Node.Icon:gsub("dds$","png"), '",\n') 26 | if skill.Mastery then 27 | out:write('\t\t\t\t\tmasteryIcon = "', skill.Mastery.Icon:gsub("dds$","png"), '",\n') 28 | end 29 | out:write('\t\t\t\t\ttag = "', skill.Tag.Id, '",\n') 30 | local stats = { } 31 | for index, stat in ipairs(skill.Node.Stats) do 32 | stats[stat.Id] = { min = skill.Node["Stat"..index], max = skill.Node["Stat"..index] } 33 | end 34 | local desc = describeStats(stats) 35 | out:write('\t\t\t\t\tstats = { "', table.concat(desc, '", "'), '" },\n') 36 | out:write('\t\t\t\t\tenchant = {\n') 37 | for index, stat in ipairs(skill.Node.Stats) do 38 | local stats = { 39 | [stat.Id] = { min = skill.Node["Stat"..index], max = skill.Node["Stat"..index] } 40 | } 41 | for _, line in ipairs(describeStats(stats)) do 42 | out:write('\t\t\t\t\t\t"Added Small Passive Skills grant: ', line, '",\n') 43 | end 44 | end 45 | out:write('\t\t\t\t\t},\n') 46 | out:write('\t\t\t\t},\n') 47 | end 48 | out:write('\t\t\t},\n') 49 | out:write('\t\t},\n') 50 | end 51 | out:write('\t},\n') 52 | 53 | out:write('\tnotableSortOrder = {\n') 54 | for skill in dat"PassiveTreeExpansionSpecialSkills":Rows() do 55 | if skill.Node.Notable then 56 | out:write('\t\t["', skill.Node.Name, '"] = ', skill.Stat._rowIndex, ',\n') 57 | end 58 | end 59 | out:write('\t},\n') 60 | out:write('\tkeystones = {\n') 61 | for skill in dat"PassiveTreeExpansionSpecialSkills":Rows() do 62 | if skill.Node.Keystone then 63 | out:write('\t\t"', skill.Node.Name, '",\n') 64 | end 65 | end 66 | out:write('\t},\n') 67 | 68 | out:write('}') 69 | out:close() 70 | 71 | print("Cluster jewel data exported.") -------------------------------------------------------------------------------- /Export/Scripts/essence.lua: -------------------------------------------------------------------------------- 1 | local colMap = { 2 | ["Amulet"] = "AmuletMod", 3 | ["Ring"] = "RingMod", 4 | ["Belt"] = "BeltMod", 5 | ["Quiver"] = "QuiverMod", 6 | ["Helmet"] = "HelmetMod", 7 | ["Body Armour"] = "BodyArmourMod", 8 | ["Boots"] = "BootsMod", 9 | ["Gloves"] = "GlovesMod", 10 | ["Shield"] = "ShieldMod", 11 | ["Bow"] = "BowMod", 12 | ["Claw"] = "ClawMod", 13 | ["Dagger"] = "DaggerMod", 14 | ["Staff"] = "StaffMod", 15 | ["Wand"] = "WandMod", 16 | ["One Handed Axe"] = "OneHandAxeMod", 17 | ["One Handed Mace"] = "OneHandMaceMod", 18 | ["One Handed Sword"] = "OneHandSwordMod", 19 | ["Sceptre"] = "SceptreMod", 20 | ["Thrusting One Handed Sword"] = "ThrustingOneHandSwordMod", 21 | ["Two Handed Axe"] = "TwoHandAxeMod", 22 | ["Two Handed Mace"] = "TwoHandMaceMod", 23 | ["Two Handed Sword"] = "TwoHandSwordMod", 24 | } 25 | local out = io.open("../Data/3_0/Essence.lua", "w") 26 | out:write('-- This file is automatically generated, do not edit!\n') 27 | out:write('-- Item data (c) Grinding Gear Games\n\nreturn {\n') 28 | for essence in dat"Essences":Rows() do 29 | if essence.Tier > 0 then 30 | out:write('\t["', essence.BaseItemType.Id, '"] = { name = "', essence.BaseItemType.Name, '", ') 31 | out:write('type = ', essence.Type._rowIndex - 1, ', tier = ', essence.Tier, ', ') 32 | out:write('mods = { ') 33 | for type, col in pairs(colMap) do 34 | out:write('["', type, '"] = "', essence[col].Id, '", ') 35 | end 36 | out:write('}, },\n') 37 | end 38 | end 39 | out:write('}') 40 | out:close() 41 | 42 | print("Essences exported.") 43 | -------------------------------------------------------------------------------- /Export/Scripts/masters.lua: -------------------------------------------------------------------------------- 1 | if not loadStatFile then 2 | dofile("statdesc.lua") 3 | end 4 | loadStatFile("stat_descriptions.txt") 5 | 6 | local itemClassMap = { 7 | ["LifeFlask"] = "Flask", 8 | ["ManaFlask"] = "Flask", 9 | ["HybridFlask"] = "Flask", 10 | ["Amulet"] = "Amulet", 11 | ["Ring"] = "Ring", 12 | ["Claw"] = "Claw", 13 | ["Dagger"] = "Dagger", 14 | ["Wand"] = "Wand", 15 | ["One Hand Sword"] = "One Handed Sword", 16 | ["Thrusting One Hand Sword"] = "Thrusting One Handed Sword", 17 | ["One Hand Axe"] = "One Handed Axe", 18 | ["One Hand Mace"] = "One Handed Mace", 19 | ["Bow"] = "Bow", 20 | ["Staff"] = "Staff", 21 | ["Two Hand Sword"] = "Two Handed Sword", 22 | ["Two Hand Axe"] = "Two Handed Axe", 23 | ["Two Hand Mace"] = "Two Handed Mace", 24 | ["Quiver"] = "Quiver", 25 | ["Belt"] = "Belt", 26 | ["Gloves"] = "Gloves", 27 | ["Boots"] = "Boots", 28 | ["Body Armour"] = "Body Armour", 29 | ["Helmet"] = "Helmet", 30 | ["Shield"] = "Shield", 31 | ["Sceptre"] = "Sceptre", 32 | ["UtilityFlask"] = "Flask", 33 | ["UtilityFlaskCritical"] = "Flask", 34 | ["Map"] = "Map", 35 | ["Jewel"] = "Jewel", 36 | ["Rune Dagger"] = "Dagger", 37 | ["Warstaff"] = "Staff", 38 | } 39 | local out = io.open("../Data/3_0/ModMaster.lua", "w") 40 | out:write('-- This file is automatically generated, do not edit!\n') 41 | out:write('-- Item data (c) Grinding Gear Games\n\nreturn {\n') 42 | for _, craft in ipairs(dat"CraftingBenchOptions":GetRowList("IsDisabled", false)) do 43 | if craft.Mod then 44 | out:write('\t{ ') 45 | if craft.Mod.GenerationType == 1 then 46 | out:write('type = "Prefix", ') 47 | elseif craft.Mod.GenerationType == 2 then 48 | out:write('type = "Suffix", ') 49 | end 50 | out:write('affix = "', craft.Mod.Name, '", ') 51 | local stats, orders = describeMod(craft.Mod) 52 | out:write('"', table.concat(stats, '", "'), '", ') 53 | out:write('statOrder = { ', table.concat(orders, ', '), ' }, ') 54 | out:write('level = ', craft.Mod.Level, ', group = "', craft.Mod.Family, '", ') 55 | out:write('types = { ') 56 | for _, catagory in ipairs(craft.ItemCategories) do 57 | for _, itemClass in ipairs(catagory.ItemClasses) do 58 | out:write('["', itemClassMap[itemClass.Id], '"] = true, ') 59 | end 60 | end 61 | out:write('}, ') 62 | out:write('},\n') 63 | end 64 | end 65 | out:write('}') 66 | out:close() 67 | 68 | print("Master mods exported.") -------------------------------------------------------------------------------- /Export/Scripts/miscdata.lua: -------------------------------------------------------------------------------- 1 | local out = io.open("../Data/3_0/Misc.lua", "w") 2 | 3 | out:write('local data = ...\n') 4 | local evasion = "" 5 | local accuracy = "" 6 | local life = "" 7 | local allyLife = "" 8 | local damage = "" 9 | for stats in dat"DefaultMonsterStats":Rows() do 10 | evasion = evasion .. stats.Evasion .. ", " 11 | accuracy = accuracy .. stats.Accuracy .. ", " 12 | life = life .. stats.MonsterLife .. ", " 13 | allyLife = allyLife .. stats.MinionLife .. ", " 14 | damage = damage .. stats.Damage .. ", " 15 | end 16 | out:write('-- From DefaultMonsterStats.dat\n') 17 | out:write('data.monsterEvasionTable = { '..evasion..'}\n') 18 | out:write('data.monsterAccuracyTable = { '..accuracy..'}\n') 19 | out:write('data.monsterLifeTable = { '..life..'}\n') 20 | out:write('data.monsterAllyLifeTable = { '..allyLife..'}\n') 21 | out:write('data.monsterDamageTable = { '..damage..'}\n') 22 | 23 | local totemMult = "" 24 | local keys = { } 25 | for var in dat"SkillTotemVariations":Rows() do 26 | if not keys[var.SkillTotem] then 27 | keys[var.SkillTotem] = true 28 | totemMult = totemMult .. "[" .. var.SkillTotem .. "] = " .. var.MonsterVariety.LifeMultiplier / 100 .. ", " 29 | end 30 | end 31 | out:write('-- From MonsterVarieties.dat combined with SkillTotemVariations.dat\n') 32 | out:write('data.totemLifeMult = { '..totemMult..'}\n') 33 | 34 | out:close() 35 | 36 | print("Misc data exported.") 37 | -------------------------------------------------------------------------------- /Export/Scripts/mods.lua: -------------------------------------------------------------------------------- 1 | if not loadStatFile then 2 | dofile("statdesc.lua") 3 | end 4 | loadStatFile("stat_descriptions.txt") 5 | 6 | local function writeMods(outName, condFunc) 7 | local out = io.open(outName, "w") 8 | out:write('-- This file is automatically generated, do not edit!\n') 9 | out:write('-- Item data (c) Grinding Gear Games\n\nreturn {\n') 10 | for mod in dat"Mods":Rows() do 11 | if condFunc(mod) then 12 | local stats, orders = describeMod(mod) 13 | if #orders > 0 then 14 | out:write('\t["', mod.Id, '"] = { ') 15 | if mod.GenerationType == 1 then 16 | out:write('type = "Prefix", ') 17 | elseif mod.GenerationType == 2 then 18 | out:write('type = "Suffix", ') 19 | elseif mod.GenerationType == 5 then 20 | out:write('type = "Corrupted", ') 21 | end 22 | out:write('affix = "', mod.Name, '", ') 23 | out:write('"', table.concat(stats, '", "'), '", ') 24 | out:write('statOrderKey = "', table.concat(orders, ','), '", ') 25 | out:write('statOrder = { ', table.concat(orders, ', '), ' }, ') 26 | out:write('level = ', mod.Level, ', group = "', mod.Family, '", ') 27 | out:write('weightKey = { ') 28 | for _, tag in ipairs(mod.SpawnTags) do 29 | out:write('"', tag.Id, '", ') 30 | end 31 | out:write('}, ') 32 | out:write('weightVal = { ', table.concat(mod.SpawnWeights, ', '), ' }, ') 33 | out:write('weightMultiplierKey = { ') 34 | for _, tag in ipairs(mod.GenerationWeightTags) do 35 | out:write('"', tag.Id, '", ') 36 | end 37 | out:write('}, ') 38 | out:write('weightMultiplierVal = { ', table.concat(mod.GenerationWeightValues, ', '), ' }, ') 39 | if mod.Tags[1] then 40 | out:write('tags = { ') 41 | for _, tag in ipairs(mod.Tags) do 42 | out:write('"', tag.Id, '", ') 43 | end 44 | out:write('}, ') 45 | end 46 | out:write('},\n') 47 | else 48 | print("Mod '"..mod.Id.."' has no stats") 49 | end 50 | end 51 | end 52 | out:write('}') 53 | out:close() 54 | end 55 | 56 | writeMods("../Data/3_0/ModItem.lua", function(mod) 57 | return mod.Domain == 1 and (mod.GenerationType == 1 or mod.GenerationType == 2 or mod.GenerationType == 5) 58 | end) 59 | writeMods("../Data/3_0/ModFlask.lua", function(mod) 60 | return mod.Domain == 2 and (mod.GenerationType == 1 or mod.GenerationType == 2) 61 | end) 62 | writeMods("../Data/3_0/ModJewel.lua", function(mod) 63 | return mod.Domain == 10 and (mod.GenerationType == 1 or mod.GenerationType == 2 or mod.GenerationType == 5) 64 | end) 65 | writeMods("../Data/3_0/ModJewelAbyss.lua", function(mod) 66 | return mod.Domain == 13 and (mod.GenerationType == 1 or mod.GenerationType == 2 or mod.GenerationType == 5) 67 | end) 68 | writeMods("../Data/3_0/ModJewelCluster.lua", function(mod) 69 | return mod.Domain == 21 and (mod.GenerationType == 1 or mod.GenerationType == 2 or mod.GenerationType == 5) 70 | end) 71 | 72 | print("Mods exported.") -------------------------------------------------------------------------------- /Export/Scripts/statdesc.lua: -------------------------------------------------------------------------------- 1 | local nk = { } 2 | 3 | local function processStatFile(name) 4 | local statDescriptor = { } 5 | local curLang 6 | local curDescriptor = { } 7 | local text = convertUTF16to8(getFile("Metadata/StatDescriptions/"..name..".txt")) 8 | for line in text:gmatch("[^\r\n]+") do 9 | local parent = line:match('include "Metadata/StatDescriptions/(.+)%.txt"$') 10 | if parent then 11 | statDescriptor.parent = parent 12 | else 13 | local noDesc = line:match("no_description ([%w_%+%-%%]+)") 14 | if noDesc then 15 | table.insert(statDescriptor, { stats = { noDesc } }) 16 | statDescriptor[noDesc] = #statDescriptor 17 | elseif line:match("description") then 18 | local name = line:match("description ([%w_]+)") 19 | curLang = { } 20 | curDescriptor = { lang = { ["English"] = curLang }, order = order, name = name } 21 | table.insert(statDescriptor, curDescriptor) 22 | elseif not curDescriptor.stats then 23 | local stats = line:match("%d+%s+([%w_%+%-%% ]+)") 24 | if stats then 25 | curDescriptor.stats = { } 26 | for stat in stats:gmatch("[%w_%+%-%%]+") do 27 | table.insert(curDescriptor.stats, stat) 28 | statDescriptor[stat] = #statDescriptor 29 | end 30 | end 31 | else 32 | local langName = line:match('lang "(.+)"') 33 | if langName then 34 | curLang = nil--{ } 35 | curDescriptor.lang[langName] = curLang 36 | elseif curLang then 37 | local statLimits, text, special = line:match('([%d%-#!| ]+) "(.-)"%s*(.*)') 38 | if statLimits then 39 | local desc = { text = text, limit = { } } 40 | for statLimit in statLimits:gmatch("[%d%-#|]+") do 41 | local limit = { } 42 | if statLimit == "#" then 43 | limit[1] = "#" 44 | limit[2] = "#" 45 | elseif statLimit:match("^%-?%d+$") then 46 | limit[1] = tonumber(statLimit) 47 | limit[2] = tonumber(statLimit) 48 | else 49 | local negate = statLimit:match("^!(-?%d+)$") 50 | if negate then 51 | limit[1] = "!" 52 | limit[2] = tonumber(negate) 53 | else 54 | limit[1], limit[2] = statLimit:match("([%d%-#]+)|([%d%-#]+)") 55 | limit[1] = tonumber(limit[1]) or limit[1] 56 | limit[2] = tonumber(limit[2]) or limit[2] 57 | end 58 | end 59 | table.insert(desc.limit, limit) 60 | end 61 | for k, v in special:gmatch("([%w%%_]+) (%w+)") do 62 | table.insert(desc, { 63 | k = k, 64 | v = tonumber(v) or v, 65 | }) 66 | nk[k] = v 67 | end 68 | table.insert(curLang, desc) 69 | end 70 | end 71 | end 72 | end 73 | end 74 | local out = io.open("../Data/3_0/StatDescriptions/"..name..".lua", "w") 75 | out:write("return ") 76 | writeLuaTable(out, statDescriptor) 77 | out:close() 78 | end 79 | 80 | local statFileList = { 81 | "active_skill_gem_stat_descriptions", 82 | "aura_skill_stat_descriptions", 83 | "banner_aura_skill_stat_descriptions", 84 | "beam_skill_stat_descriptions", 85 | "brand_skill_stat_descriptions", 86 | "curse_skill_stat_descriptions", 87 | "debuff_skill_stat_descriptions", 88 | "gem_stat_descriptions", 89 | "minion_attack_skill_stat_descriptions", 90 | "minion_skill_stat_descriptions", 91 | "minion_spell_skill_stat_descriptions", 92 | "monster_stat_descriptions", 93 | "offering_skill_stat_descriptions", 94 | "skill_stat_descriptions", 95 | "stat_descriptions", 96 | "variable_duration_skill_stat_descriptions", 97 | "buff_skill_stat_descriptions", 98 | } 99 | for _, name in ipairs(statFileList) do 100 | processStatFile(name) 101 | end 102 | 103 | for k, v in pairs(nk) do 104 | --print("'"..k.."' = '"..v.."'") 105 | end 106 | 107 | print("Stat descriptions exported.") 108 | -------------------------------------------------------------------------------- /Export/browse.lua: -------------------------------------------------------------------------------- 1 | #@ 2 | 3 | dofile("_common.lua") 4 | 5 | loadDat("SkillGems") 6 | loadDat("ActiveSkills") 7 | loadDat("GemTags") 8 | loadDat("Stats") 9 | loadDat("Mods") 10 | loadDat("GrantedEffects") 11 | loadDat("GrantedEffectsPerLevel") 12 | loadDat("MonsterVarieties") 13 | loadDat("MonsterTypes") 14 | loadDat("MonsterResistances") 15 | loadDat("ItemClasses") 16 | 17 | function actWithType(skillType) 18 | for _, k in ipairs(ActiveSkills.ActiveSkillTypes(skillType)) do 19 | if ActiveSkills[k].DisplayedName ~= "" then 20 | print(ActiveSkills[k].DisplayedName) 21 | end 22 | end 23 | end 24 | function supWithType(skillType) 25 | for _, data in ipairs({"AllowedActiveSkillTypes","AddedActiveSkillTypes","ExcludedActiveSkillTypes"}) do 26 | print(data..":") 27 | for _, k in ipairs(GrantedEffects[data](skillType)) do 28 | print(GrantedEffects[k].Id) 29 | end 30 | end 31 | end 32 | function withType(skillType) 33 | print("Active:") 34 | actWithType(skillType) 35 | supWithType(skillType) 36 | end 37 | function skillWithStat(statId) 38 | local foo = { } 39 | for _, key in ipairs(GEPL.StatsKeys(Stats.Id(statId)[1])) do 40 | foo[GEPL[key].GrantedEffectsKey] = true 41 | end 42 | for k in pairs(foo) do 43 | print(GE[k].Id) 44 | end 45 | end 46 | local function mod(key) 47 | local m = Mods[key] 48 | print("Mod #"..key..": "..m.Id) 49 | for i = 1, 5 do 50 | local key = m["StatsKey"..i] 51 | if key then 52 | print("Stat #"..key..": ["..m["Stat"..i.."Min"].." to "..m["Stat"..i.."Max"].."] "..Stats[key].Id) 53 | end 54 | end 55 | end 56 | function spectre(name) 57 | for i, key in ipairs(MV.Name(name)) do 58 | local mon = MV[key] 59 | print("#"..i..": "..mon.Id.." ["..key.."]") 60 | print("AIS: "..mon.AISFile) 61 | print("life = "..mon.LifeMultiplier/100) 62 | if MT[mon.MonsterTypesKey].EnergyShieldFromLife ~= 0 then 63 | print("energyShield = "..(0.4 * MT[mon.MonsterTypesKey].EnergyShieldFromLife / 100)) 64 | end 65 | if MT[mon.MonsterTypesKey].Armour ~= 0 then 66 | print("armour = "..MT[mon.MonsterTypesKey].Armour / 100) 67 | end 68 | print("fireResist = "..MR[MT[mon.MonsterTypesKey].MonsterResistancesKey].FireMerciless) 69 | print("coldResist = "..MR[MT[mon.MonsterTypesKey].MonsterResistancesKey].ColdMerciless) 70 | print("lightningResist = "..MR[MT[mon.MonsterTypesKey].MonsterResistancesKey].LightningMerciless) 71 | print("chaosResist = "..MR[MT[mon.MonsterTypesKey].MonsterResistancesKey].ChaosMerciless) 72 | print("damage = "..(mon.DamageMultiplier/100)) 73 | print("damageSpread = "..(MT[mon.MonsterTypesKey].DamageSpread / 100)) 74 | print("attackTime = "..mon.AttackSpeed/1000) 75 | print("attackRange = "..mon.MaximumAttackDistance) 76 | print("accuracy = "..MT[mon.MonsterTypesKey].Unknown1 / 100) 77 | if mon.MainHand_ItemClassesKey then 78 | print("weaponType1 = "..IC[mon.MainHand_ItemClassesKey].Name) 79 | end 80 | if mon.OffHand_ItemClassesKey then 81 | print("weaponType2 = "..IC[mon.OffHand_ItemClassesKey].Name) 82 | end 83 | for _, key in ipairs(mon.GrantedEffectsKeys) do 84 | print("Skill #"..key..": "..GE[key].Id) 85 | end 86 | for _, key in ipairs(mon.ModsKeys) do 87 | mod(key) 88 | end 89 | for _, key in ipairs(mon.Special_ModsKeys) do 90 | mod(key) 91 | end 92 | end 93 | end 94 | 95 | local str 96 | while true do 97 | print(">>") 98 | str = io.read("*l") 99 | if str == "quit" then 100 | break 101 | end 102 | local func, msg = loadstring(str) 103 | if func then 104 | local ret, msg = pcall(func) 105 | if not ret then 106 | print(msg) 107 | end 108 | else 109 | print(msg) 110 | end 111 | end -------------------------------------------------------------------------------- /Export/essenceMatch.lua: -------------------------------------------------------------------------------- 1 | loadStatFile("stat_descriptions.txt") 2 | 3 | local mode 4 | local ess = { } 5 | local curEss 6 | for line in io.lines("essence.txt") do 7 | if not mode then 8 | if line == "Rarity: Currency" then 9 | mode = "NAME" 10 | end 11 | elseif mode == "NAME" then 12 | curEss = { } 13 | ess[line] = curEss 14 | mode = "UPGRADES" 15 | elseif mode == "UPGRADES" and line:match("^Upgrades") then 16 | mode = "STAT" 17 | elseif mode == "STAT" then 18 | if line == "--------" then 19 | mode = nil 20 | else 21 | local type, mod = line:match("(.+): (.+)") 22 | if type then 23 | curEss[type] = { mod:gsub("^(%(%d+%-%d+%)%%? to)", "+%1"):gsub("^(%(%d+%-%d+%)%%? Chance)", "+%1") } 24 | end 25 | end 26 | end 27 | end 28 | 29 | local out = io.open("essence.csv", "w") 30 | local h = { } 31 | for name, index in pairs(Essences.headerMap) do 32 | if name:match("ModsKey") and not name:match("ModsKeys") then 33 | table.insert(h, name) 34 | end 35 | end 36 | table.sort(h, function(a,b) return Essences.headerMap[a] < Essences.headerMap[b] end) 37 | out:write('Name;', table.concat(h, ';'), '\n') 38 | for essenceKey = 0, Essences.maxRow do 39 | local essence = Essences[essenceKey] 40 | if essence.Tier >= 7 then 41 | local name = BaseItemTypes[essence.BaseItemTypesKey].Name 42 | out:write(name, ';') 43 | for _, h in ipairs(h) do 44 | local k = essence[h] 45 | if k then 46 | local md = describeMod(M[k]) 47 | if md[1] then 48 | local foo = { } 49 | for type, mod in pairs(ess[name]) do 50 | if mod[1] == md[1] then 51 | table.insert(foo, type) 52 | mod.match = true 53 | end 54 | end 55 | out:write(table.concat(foo, ','), ';') 56 | --out:write(md[1]:gsub("(%a%a%a)%a+","%1"), ';') 57 | else 58 | out:write(';') 59 | end 60 | else 61 | out:write(';') 62 | end 63 | end 64 | out:write('\n') 65 | end 66 | end 67 | out:write('\nNo match:\n') 68 | for name, ess in pairs(ess) do 69 | for type, mod in pairs(ess) do 70 | if not mod.match then 71 | out:write(name, ';', type, ';', mod[1], '\n') 72 | end 73 | end 74 | end 75 | out:close() 76 | -------------------------------------------------------------------------------- /Export/passives.lua: -------------------------------------------------------------------------------- 1 | local out = io.open("../Data/3_0/Passives.lua", "w") 2 | out:write('-- This file is automatically generated, do not edit!\n') 3 | out:write('-- Passive skill data (c) Grinding Gear Games\n\nreturn {\n') 4 | for passiveKey = 0, PassiveSkills.maxRow do 5 | local passive = PassiveSkills[passiveKey] 6 | out:write('\t[', passive.PassiveSkillGraphId, '] = { ') 7 | out:write('name = "', passive.Name, '", ') 8 | if passive.StatsKeys[1] > 0 then 9 | if passive.GrantedBuff_BuffDefinitionsKey then 10 | loadStatFile("passive_skill_aura_stat_descriptions.txt") 11 | else 12 | loadStatFile("passive_skill_stat_descriptions.txt") 13 | end 14 | local stats = { } 15 | for i, statKey in ipairs(passive.StatsKeys) do 16 | stats[Stats[statKey].Id] = { min = passive["Stat"..i.."Value"], max = passive["Stat"..i.."Value"] } 17 | end 18 | out:write('"', table.concat(describeStats(stats), '", "'), '", ') 19 | end 20 | out:write('},\n') 21 | end 22 | out:write('}') 23 | out:close() 24 | 25 | print("Passives exported.") -------------------------------------------------------------------------------- /GameVersions.lua: -------------------------------------------------------------------------------- 1 | defaultTargetVersion = "2_6" 2 | liveTargetVersion = "3_0" 3 | targetVersionList = { "2_6", "3_0" } 4 | targetVersions = { 5 | ["2_6"] = { 6 | short = "2.6", 7 | long = "2.6 (Atlas of Worlds)", 8 | treeVersionList = { "2_6" }, 9 | defaultTreeVersion = "2_6", 10 | latestTreeVersion = "2_6", 11 | }, 12 | ["3_0"] = { 13 | short = "3.11", 14 | long = "3.11 (Conquerors of the Atlas)", 15 | treeVersionList = { "3_6", "3_7", "3_8", "3_9", "3_10", "3_11" }, 16 | defaultTreeVersion = "3_6", 17 | latestTreeVersion = "3_11", 18 | }, 19 | } 20 | 21 | treeVersionList = { "2_6", "3_6", "3_7", "3_8", "3_9", "3_10", "3_11" } 22 | treeVersions = { 23 | ["2_6"] = { 24 | short = "2.6", 25 | num = 2.06, 26 | export = "https://www.pathofexile.com/passive-skill-tree/2.6.2/", 27 | targetVersion = "2_6", 28 | }, 29 | ["3_6"] = { 30 | short = "3.6", 31 | num = 3.06, 32 | export = "https://www.pathofexile.com/passive-skill-tree/3.6.0/", 33 | targetVersion = "3_0", 34 | }, 35 | ["3_7"] = { 36 | short = "3.7", 37 | num = 3.07, 38 | export = "https://www.pathofexile.com/passive-skill-tree/3.7.0/", 39 | targetVersion = "3_0", 40 | }, 41 | ["3_8"] = { 42 | short = "3.8", 43 | num = 3.08, 44 | export = "https://www.pathofexile.com/passive-skill-tree/3.8.0/", 45 | targetVersion = "3_0", 46 | }, 47 | ["3_9"] = { 48 | short = "3.9", 49 | num = 3.09, 50 | export = "https://www.pathofexile.com/passive-skill-tree/3.9.0/", 51 | targetVersion = "3_0", 52 | }, 53 | ["3_10"] = { 54 | short = "3.10", 55 | num = 3.10, 56 | export = "https://www.pathofexile.com/passive-skill-tree/3.10.0/", 57 | targetVersion = "3_0", 58 | }, 59 | ["3_11"] = { 60 | short = "3.11", 61 | num = 3.11, 62 | export = "https://www.pathofexile.com/passive-skill-tree/3.11.0/", 63 | targetVersion = "3_0", 64 | }, 65 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 David Gowor 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /LaunchInstall.lua: -------------------------------------------------------------------------------- 1 | #@ SimpleGraphic 2 | -- Path of Building 3 | -- 4 | -- Module: Launch Install 5 | -- Installation bootstrap 6 | -- 7 | 8 | local basicFiles = { "UpdateCheck.lua", "UpdateApply.lua", "Launch.lua" } 9 | 10 | local xml = require("xml") 11 | local curl = require("lcurl.safe") 12 | 13 | ConClear() 14 | ConPrintf("Preparing to complete installation...\n") 15 | 16 | local localBranch, localSource 17 | local localManXML = xml.LoadXMLFile("manifest.xml") 18 | if localManXML and localManXML[1].elem == "PoBVersion" then 19 | for _, node in ipairs(localManXML[1]) do 20 | if type(node) == "table" then 21 | if node.elem == "Version" then 22 | localBranch = node.attrib.branch 23 | elseif node.elem == "Source" then 24 | if node.attrib.part == "program" then 25 | localSource = node.attrib.url 26 | end 27 | end 28 | end 29 | end 30 | end 31 | if not localBranch or not localSource then 32 | Exit("Install failed. (Missing or invalid manifest)") 33 | return 34 | end 35 | localSource = localSource:gsub("{branch}", localBranch) 36 | for _, name in ipairs(basicFiles) do 37 | local text = "" 38 | local easy = curl.easy() 39 | easy:setopt_url(localSource..name) 40 | easy:setopt_writefunction(function(data) 41 | text = text..data 42 | return true 43 | end) 44 | easy:perform() 45 | local size = easy:getinfo(curl.INFO_SIZE_DOWNLOAD) 46 | easy:close() 47 | if size == 0 then 48 | Exit("Install failed. (Couldn't download program files)") 49 | return 50 | end 51 | local outFile = io.open(name, "wb") 52 | outFile:write(text) 53 | outFile:close() 54 | end 55 | Restart() -------------------------------------------------------------------------------- /Modules/ItemTools.lua: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/Modules/ItemTools.lua -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Path of Building 2 | 3 | Welcome to Path of Building, an offline build planner for Path of Exile! 4 | ## Features 5 | * Comprehensive offence + defence calculations: 6 | * Calculate your skill DPS, damage over time, life/mana/ES totals and much more! 7 | * Can factor in auras, buffs, charges, curses, monster resistances and more, to estimate your effective DPS 8 | * Also calculates life/mana reservations 9 | * Shows a summary of character stats in the side bar, as well as a detailed calculations breakdown tab which can show you how the stats were derived 10 | * Supports all skills and support gems, and most passives and item modifiers 11 | * Throughout the program, supported modifiers will show in blue and unsupported ones in red 12 | * Full support for minions 13 | * Passive skill tree planner: 14 | * Support for jewels including most radius/conversion jewels 15 | * Features alternate path tracing (mouse over a sequence of nodes while holding shift, then click to allocate them all) 16 | * Fully intergrated with the offence/defence calculations; see exactly how each node will affect your character! 17 | * Can import PathOfExile.com and PoEPlanner.com passive tree links; links shortened with PoEURL.com also work 18 | * Skill planner: 19 | * Add any number of main or supporting skills to your build 20 | * Supporting skills (auras, curses, buffs) can be toggled on and off 21 | * Automatically applies Socketed Gem modifiers from the item a skill is socketed into 22 | * Automatically applies support gems granted by items 23 | * Item planner: 24 | * Add items from in game by copying and pasting them straight into the program! 25 | * Automatically adds quality to non-corrupted items 26 | * Fully intergrated with the offence/defence calculations; see exactly how much of an upgrade a given item is! 27 | * Contains a searchable database of all uniques that are currently in game (and some that aren't yet!) 28 | * You can choose the modifier rolls when you add a unique to your build 29 | * Includes all league-specific items and legacy variants 30 | * Features an item crafting system: 31 | * You can select from any of the game's base item types 32 | * You can select prefix/suffix modifiers from lists 33 | * Custom modifiers can be added, with Master and Essence modifiers available 34 | * Also contains a database of rare item templates: 35 | * Allows you to create rare items for your build to approximate the gear you will be using 36 | * Choose which modifiers appear on each item, and the rolls for each modifier, to suit your needs 37 | * Has templates that should cover the majority of builds (inb4 'why is there no coral amulet?') 38 | * Other features: 39 | * You can import passive tree, items, and skills from existing characters 40 | * Share builds with other users by generating a share code 41 | * Automatic updating; most updates will only take a couple of seconds to apply 42 | * Somewhat more open source than usual (look in %ProgramData%\Path of Building if you're interested) 43 | 44 | ## Download 45 | Head over to the [Releases](https://github.com/Openarl/PathOfBuilding/releases) page to download the installer. 46 | 47 | ## Donate 48 | If you'd like to help support the development of Path of Building, I have a [Patreon page](https://www.patreon.com/openarl). 49 | 50 | ## Screenshots 51 | ![ss1](https://cloud.githubusercontent.com/assets/19189971/18089779/f0fe23fa-6f04-11e6-8ed7-ff7d5b9f867a.png) 52 | ![ss2](https://cloud.githubusercontent.com/assets/19189971/18089778/f0f923f0-6f04-11e6-89c2-b2c1410d3583.png) 53 | ![ss3](https://cloud.githubusercontent.com/assets/19189971/18089780/f0ff234a-6f04-11e6-8c88-6193fe59a5c4.png) 54 | 55 | ## Changelog 56 | You can find the full version history [here](CHANGELOG.md). -------------------------------------------------------------------------------- /TreeData/AmberOil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/AmberOil.png -------------------------------------------------------------------------------- /TreeData/AscendancyButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/AscendancyButton.png -------------------------------------------------------------------------------- /TreeData/AscendancyButtonHighlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/AscendancyButtonHighlight.png -------------------------------------------------------------------------------- /TreeData/AscendancyButtonPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/AscendancyButtonPressed.png -------------------------------------------------------------------------------- /TreeData/AscendancyFrameLargeAllocated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/AscendancyFrameLargeAllocated.png -------------------------------------------------------------------------------- /TreeData/AscendancyFrameLargeCanAllocate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/AscendancyFrameLargeCanAllocate.png -------------------------------------------------------------------------------- /TreeData/AscendancyFrameLargeNormal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/AscendancyFrameLargeNormal.png -------------------------------------------------------------------------------- /TreeData/AscendancyFrameSmallAllocated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/AscendancyFrameSmallAllocated.png -------------------------------------------------------------------------------- /TreeData/AscendancyFrameSmallCanAllocate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/AscendancyFrameSmallCanAllocate.png -------------------------------------------------------------------------------- /TreeData/AscendancyFrameSmallNormal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/AscendancyFrameSmallNormal.png -------------------------------------------------------------------------------- /TreeData/AscendancyMiddle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/AscendancyMiddle.png -------------------------------------------------------------------------------- /TreeData/AzureOil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/AzureOil.png -------------------------------------------------------------------------------- /TreeData/Background1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/Background1.png -------------------------------------------------------------------------------- /TreeData/BackgroundDex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/BackgroundDex.png -------------------------------------------------------------------------------- /TreeData/BackgroundDexInt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/BackgroundDexInt.png -------------------------------------------------------------------------------- /TreeData/BackgroundInt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/BackgroundInt.png -------------------------------------------------------------------------------- /TreeData/BackgroundStr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/BackgroundStr.png -------------------------------------------------------------------------------- /TreeData/BackgroundStrDex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/BackgroundStrDex.png -------------------------------------------------------------------------------- /TreeData/BackgroundStrInt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/BackgroundStrInt.png -------------------------------------------------------------------------------- /TreeData/BlackOil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/BlackOil.png -------------------------------------------------------------------------------- /TreeData/BlightedNotableFrameAllocated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/BlightedNotableFrameAllocated.png -------------------------------------------------------------------------------- /TreeData/BlightedNotableFrameCanAllocate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/BlightedNotableFrameCanAllocate.png -------------------------------------------------------------------------------- /TreeData/BlightedNotableFrameUnallocated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/BlightedNotableFrameUnallocated.png -------------------------------------------------------------------------------- /TreeData/ClassesAscendant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesAscendant.png -------------------------------------------------------------------------------- /TreeData/ClassesAssassin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesAssassin.png -------------------------------------------------------------------------------- /TreeData/ClassesBerserker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesBerserker.png -------------------------------------------------------------------------------- /TreeData/ClassesChampion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesChampion.png -------------------------------------------------------------------------------- /TreeData/ClassesChieftain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesChieftain.png -------------------------------------------------------------------------------- /TreeData/ClassesDeadeye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesDeadeye.png -------------------------------------------------------------------------------- /TreeData/ClassesElementalist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesElementalist.png -------------------------------------------------------------------------------- /TreeData/ClassesGladiator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesGladiator.png -------------------------------------------------------------------------------- /TreeData/ClassesGuardian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesGuardian.png -------------------------------------------------------------------------------- /TreeData/ClassesHierophant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesHierophant.png -------------------------------------------------------------------------------- /TreeData/ClassesInquisitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesInquisitor.png -------------------------------------------------------------------------------- /TreeData/ClassesJuggernaut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesJuggernaut.png -------------------------------------------------------------------------------- /TreeData/ClassesNecromancer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesNecromancer.png -------------------------------------------------------------------------------- /TreeData/ClassesOccultist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesOccultist.png -------------------------------------------------------------------------------- /TreeData/ClassesPathfinder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesPathfinder.png -------------------------------------------------------------------------------- /TreeData/ClassesRaider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesRaider.png -------------------------------------------------------------------------------- /TreeData/ClassesSaboteur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesSaboteur.png -------------------------------------------------------------------------------- /TreeData/ClassesSlayer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesSlayer.png -------------------------------------------------------------------------------- /TreeData/ClassesTrickster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClassesTrickster.png -------------------------------------------------------------------------------- /TreeData/ClearOil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/ClearOil.png -------------------------------------------------------------------------------- /TreeData/CrimsonOil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/CrimsonOil.png -------------------------------------------------------------------------------- /TreeData/EternalEmpireJewelCircle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/EternalEmpireJewelCircle1.png -------------------------------------------------------------------------------- /TreeData/EternalEmpireJewelCircle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/EternalEmpireJewelCircle2.png -------------------------------------------------------------------------------- /TreeData/GoldenOil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/GoldenOil.png -------------------------------------------------------------------------------- /TreeData/GroupBackgroundLargeHalfAlt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/GroupBackgroundLargeHalfAlt.png -------------------------------------------------------------------------------- /TreeData/GroupBackgroundMediumAlt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/GroupBackgroundMediumAlt.png -------------------------------------------------------------------------------- /TreeData/GroupBackgroundSmallAlt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/GroupBackgroundSmallAlt.png -------------------------------------------------------------------------------- /TreeData/JewelCircle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelCircle1.png -------------------------------------------------------------------------------- /TreeData/JewelCircle1Inverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelCircle1Inverse.png -------------------------------------------------------------------------------- /TreeData/JewelFrameAllocated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelFrameAllocated.png -------------------------------------------------------------------------------- /TreeData/JewelFrameCanAllocate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelFrameCanAllocate.png -------------------------------------------------------------------------------- /TreeData/JewelFrameUnallocated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelFrameUnallocated.png -------------------------------------------------------------------------------- /TreeData/JewelSocketActiveAbyss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketActiveAbyss.png -------------------------------------------------------------------------------- /TreeData/JewelSocketActiveAbyssAlt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketActiveAbyssAlt.png -------------------------------------------------------------------------------- /TreeData/JewelSocketActiveBlue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketActiveBlue.png -------------------------------------------------------------------------------- /TreeData/JewelSocketActiveBlueAlt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketActiveBlueAlt.png -------------------------------------------------------------------------------- /TreeData/JewelSocketActiveGreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketActiveGreen.png -------------------------------------------------------------------------------- /TreeData/JewelSocketActiveGreenAlt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketActiveGreenAlt.png -------------------------------------------------------------------------------- /TreeData/JewelSocketActiveLegion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketActiveLegion.png -------------------------------------------------------------------------------- /TreeData/JewelSocketActiveLegionAlt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketActiveLegionAlt.png -------------------------------------------------------------------------------- /TreeData/JewelSocketActivePrismatic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketActivePrismatic.png -------------------------------------------------------------------------------- /TreeData/JewelSocketActivePrismaticAlt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketActivePrismaticAlt.png -------------------------------------------------------------------------------- /TreeData/JewelSocketActiveRed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketActiveRed.png -------------------------------------------------------------------------------- /TreeData/JewelSocketActiveRedAlt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketActiveRedAlt.png -------------------------------------------------------------------------------- /TreeData/JewelSocketAltActive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketAltActive.png -------------------------------------------------------------------------------- /TreeData/JewelSocketAltCanAllocate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketAltCanAllocate.png -------------------------------------------------------------------------------- /TreeData/JewelSocketAltNormal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketAltNormal.png -------------------------------------------------------------------------------- /TreeData/JewelSocketClusterAltCanAllocate1Large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketClusterAltCanAllocate1Large.png -------------------------------------------------------------------------------- /TreeData/JewelSocketClusterAltCanAllocate1Medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketClusterAltCanAllocate1Medium.png -------------------------------------------------------------------------------- /TreeData/JewelSocketClusterAltCanAllocate1Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketClusterAltCanAllocate1Small.png -------------------------------------------------------------------------------- /TreeData/JewelSocketClusterAltNormal1Large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketClusterAltNormal1Large.png -------------------------------------------------------------------------------- /TreeData/JewelSocketClusterAltNormal1Medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketClusterAltNormal1Medium.png -------------------------------------------------------------------------------- /TreeData/JewelSocketClusterAltNormal1Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/JewelSocketClusterAltNormal1Small.png -------------------------------------------------------------------------------- /TreeData/KaruiJewelCircle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/KaruiJewelCircle1.png -------------------------------------------------------------------------------- /TreeData/KaruiJewelCircle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/KaruiJewelCircle2.png -------------------------------------------------------------------------------- /TreeData/KeystoneFrameAllocated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/KeystoneFrameAllocated.png -------------------------------------------------------------------------------- /TreeData/KeystoneFrameCanAllocate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/KeystoneFrameCanAllocate.png -------------------------------------------------------------------------------- /TreeData/KeystoneFrameUnallocated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/KeystoneFrameUnallocated.png -------------------------------------------------------------------------------- /TreeData/LineConnectorActive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/LineConnectorActive.png -------------------------------------------------------------------------------- /TreeData/LineConnectorIntermediate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/LineConnectorIntermediate.png -------------------------------------------------------------------------------- /TreeData/LineConnectorNormal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/LineConnectorNormal.png -------------------------------------------------------------------------------- /TreeData/MarakethJewelCircle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/MarakethJewelCircle1.png -------------------------------------------------------------------------------- /TreeData/MarakethJewelCircle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/MarakethJewelCircle2.png -------------------------------------------------------------------------------- /TreeData/NotableFrameAllocated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/NotableFrameAllocated.png -------------------------------------------------------------------------------- /TreeData/NotableFrameCanAllocate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/NotableFrameCanAllocate.png -------------------------------------------------------------------------------- /TreeData/NotableFrameUnallocated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/NotableFrameUnallocated.png -------------------------------------------------------------------------------- /TreeData/OpalescentOil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/OpalescentOil.png -------------------------------------------------------------------------------- /TreeData/Orbit1Active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/Orbit1Active.png -------------------------------------------------------------------------------- /TreeData/Orbit1Intermediate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/Orbit1Intermediate.png -------------------------------------------------------------------------------- /TreeData/Orbit1Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/Orbit1Normal.png -------------------------------------------------------------------------------- /TreeData/Orbit2Active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/Orbit2Active.png -------------------------------------------------------------------------------- /TreeData/Orbit2Intermediate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/Orbit2Intermediate.png -------------------------------------------------------------------------------- /TreeData/Orbit2Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/Orbit2Normal.png -------------------------------------------------------------------------------- /TreeData/Orbit3Active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/Orbit3Active.png -------------------------------------------------------------------------------- /TreeData/Orbit3Intermediate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/Orbit3Intermediate.png -------------------------------------------------------------------------------- /TreeData/Orbit3Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/Orbit3Normal.png -------------------------------------------------------------------------------- /TreeData/Orbit4Active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/Orbit4Active.png -------------------------------------------------------------------------------- /TreeData/Orbit4Intermediate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/Orbit4Intermediate.png -------------------------------------------------------------------------------- /TreeData/Orbit4Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/Orbit4Normal.png -------------------------------------------------------------------------------- /TreeData/PSGroupBackground1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PSGroupBackground1.png -------------------------------------------------------------------------------- /TreeData/PSGroupBackground2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PSGroupBackground2.png -------------------------------------------------------------------------------- /TreeData/PSGroupBackground3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PSGroupBackground3.png -------------------------------------------------------------------------------- /TreeData/PSLineDeco.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PSLineDeco.png -------------------------------------------------------------------------------- /TreeData/PSLineDecoHighlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PSLineDecoHighlighted.png -------------------------------------------------------------------------------- /TreeData/PSPointsFrame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PSPointsFrame.png -------------------------------------------------------------------------------- /TreeData/PSSkillFrame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PSSkillFrame.png -------------------------------------------------------------------------------- /TreeData/PSSkillFrameActive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PSSkillFrameActive.png -------------------------------------------------------------------------------- /TreeData/PSSkillFrameHighlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PSSkillFrameHighlighted.png -------------------------------------------------------------------------------- /TreeData/PSStartNodeBackgroundInactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PSStartNodeBackgroundInactive.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenAscendancyButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenAscendancyButton.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenAscendancyButtonHighlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenAscendancyButtonHighlight.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenAscendancyButtonPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenAscendancyButtonPressed.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenAscendancyFrameLargeAllocated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenAscendancyFrameLargeAllocated.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenAscendancyFrameLargeCanAllocate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenAscendancyFrameLargeCanAllocate.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenAscendancyFrameLargeNormal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenAscendancyFrameLargeNormal.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenAscendancyFrameSmallAllocated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenAscendancyFrameSmallAllocated.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenAscendancyFrameSmallCanAllocate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenAscendancyFrameSmallCanAllocate.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenAscendancyFrameSmallNormal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenAscendancyFrameSmallNormal.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenAscendancyMiddle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenAscendancyMiddle.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenEternalEmpireJewelCircle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenEternalEmpireJewelCircle1.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenEternalEmpireJewelCircle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenEternalEmpireJewelCircle2.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenJewelCircle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenJewelCircle1.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenKaruiJewelCircle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenKaruiJewelCircle1.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenKaruiJewelCircle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenKaruiJewelCircle2.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenMarakethJewelCircle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenMarakethJewelCircle1.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenMarakethJewelCircle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenMarakethJewelCircle2.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenTemplarJewelCircle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenTemplarJewelCircle1.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenTemplarJewelCircle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenTemplarJewelCircle2.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenVaalJewelCircle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenVaalJewelCircle1.png -------------------------------------------------------------------------------- /TreeData/PassiveSkillScreenVaalJewelCircle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/PassiveSkillScreenVaalJewelCircle2.png -------------------------------------------------------------------------------- /TreeData/SepiaOil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/SepiaOil.png -------------------------------------------------------------------------------- /TreeData/SilverOil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/SilverOil.png -------------------------------------------------------------------------------- /TreeData/TealOil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/TealOil.png -------------------------------------------------------------------------------- /TreeData/TemplarJewelCircle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/TemplarJewelCircle1.png -------------------------------------------------------------------------------- /TreeData/TemplarJewelCircle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/TemplarJewelCircle2.png -------------------------------------------------------------------------------- /TreeData/VaalJewelCircle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/VaalJewelCircle1.png -------------------------------------------------------------------------------- /TreeData/VaalJewelCircle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/VaalJewelCircle2.png -------------------------------------------------------------------------------- /TreeData/VerdantOil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/VerdantOil.png -------------------------------------------------------------------------------- /TreeData/VioletOil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/VioletOil.png -------------------------------------------------------------------------------- /TreeData/centerduelist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/centerduelist.png -------------------------------------------------------------------------------- /TreeData/centermarauder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/centermarauder.png -------------------------------------------------------------------------------- /TreeData/centerranger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/centerranger.png -------------------------------------------------------------------------------- /TreeData/centerscion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/centerscion.png -------------------------------------------------------------------------------- /TreeData/centershadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/centershadow.png -------------------------------------------------------------------------------- /TreeData/centertemplar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/centertemplar.png -------------------------------------------------------------------------------- /TreeData/centerwitch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/centerwitch.png -------------------------------------------------------------------------------- /TreeData/imgPSFadeCorner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/imgPSFadeCorner.png -------------------------------------------------------------------------------- /TreeData/imgPSFadeSide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/TreeData/imgPSFadeSide.png -------------------------------------------------------------------------------- /UpdateApply.lua: -------------------------------------------------------------------------------- 1 | #@ 2 | -- Path of Building 3 | -- 4 | -- Module: Update Apply 5 | -- Applies updates. 6 | -- 7 | local opFileName = ... 8 | 9 | print("Applying update...") 10 | local opFile = io.open(opFileName, "r") 11 | if not opFile then 12 | print("No operations list present.\n") 13 | return 14 | end 15 | local lines = { } 16 | for line in opFile:lines() do 17 | table.insert(lines, line) 18 | end 19 | opFile:close() 20 | os.remove(opFileName) 21 | for _, line in ipairs(lines) do 22 | local op, args = line:match("(%a+) ?(.*)") 23 | if op == "move" then 24 | local src, dst = args:match('"(.*)" "(.*)"') 25 | print("Updating '"..dst.."'") 26 | local srcFile = io.open(src, "rb") 27 | assert(srcFile, "couldn't open "..src) 28 | local dstFile 29 | while not dstFile do 30 | dstFile = io.open(dst, "w+b") 31 | end 32 | if dstFile then 33 | dstFile:write(srcFile:read("*a")) 34 | dstFile:close() 35 | end 36 | srcFile:close() 37 | os.remove(src) 38 | elseif op == "delete" then 39 | local file = args:match('"(.*)"') 40 | print("Deleting '"..file.."'") 41 | os.remove(file) 42 | elseif op == "start" then 43 | local target = args:match('"(.*)"') 44 | SpawnProcess(target) 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /runtime-win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/runtime-win32.zip -------------------------------------------------------------------------------- /tree-2_6.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/tree-2_6.zip -------------------------------------------------------------------------------- /tree-3_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/tree-3_10.zip -------------------------------------------------------------------------------- /tree-3_11.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/tree-3_11.zip -------------------------------------------------------------------------------- /tree-3_6.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/tree-3_6.zip -------------------------------------------------------------------------------- /tree-3_7.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/tree-3_7.zip -------------------------------------------------------------------------------- /tree-3_8.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/tree-3_8.zip -------------------------------------------------------------------------------- /tree-3_9.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Openarl/PathOfBuilding/81eeead3f6c9ba62f8a02fc305b742d5ecae3ead/tree-3_9.zip --------------------------------------------------------------------------------