Skip to content

Commit 3d91f1d

Browse files
author
LocalIdentity
committed
Merge branch 'dev'
2 parents 2112a8b + aedc2cd commit 3d91f1d

File tree

96 files changed

+284728
-4925
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+284728
-4925
lines changed

Classes/ConfigTab.lua

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,27 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont
192192
end
193193
end
194194
control.tooltipText = varData.tooltip
195+
elseif varData.ifSkillFlag or varData.ifSkillFlagList then
196+
control.shown = function()
197+
if varData.ifSkillFlagList then
198+
for _, skillFlag in ipairs(varData.ifSkillFlagList) do
199+
for _, activeSkill in ipairs(self.build.calcsTab.mainEnv.player.activeSkillList) do
200+
if activeSkill.skillFlags[skillFlag] then
201+
return true
202+
end
203+
end
204+
end
205+
else
206+
-- print(ipairs(self.build.calcsTab.mainEnv.skillsUsed))
207+
for _, activeSkill in ipairs(self.build.calcsTab.mainEnv.player.activeSkillList) do
208+
if activeSkill.skillFlags[varData.ifSkillFlag] then
209+
return true
210+
end
211+
end
212+
end
213+
return false
214+
end
215+
control.tooltipText = varData.tooltip
195216
else
196217
control.tooltipText = varData.tooltip
197218
end

Classes/ImportTab.lua

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,23 @@ function ImportTabClass:ImportItem(itemData, slotName)
787787
end
788788
end
789789

790+
791+
-- parse real gem name by ommiting the first word if alt qual is set
792+
function ImportTabClass:GetBaseNameAndQuality(gemTypeLine)
793+
if gemTypeLine then
794+
local firstword, otherwords = gemTypeLine:match("(%w+)%s(.+)")
795+
if firstword and otherwords then
796+
for indx, entry in ipairs(self.build.skillsTab.getAlternateGemQualityList()) do
797+
if firstword == entry.label then
798+
return otherwords, entry.type
799+
end
800+
end
801+
end
802+
end
803+
804+
return gemTypeLine, "Default"
805+
end
806+
790807
function ImportTabClass:ImportSocketedItems(item, socketedItems, slotName)
791808
-- Build socket group list
792809
local itemSocketGroupList = { }
@@ -796,16 +813,19 @@ function ImportTabClass:ImportSocketedItems(item, socketedItems, slotName)
796813
self:ImportItem(socketedItem, slotName .. " Abyssal Socket "..abyssalSocketId)
797814
abyssalSocketId = abyssalSocketId + 1
798815
else
799-
local gemId = self.build.data.gemForBaseName[socketedItem.typeLine]
816+
local normalizedBasename, qualityType = self:GetBaseNameAndQuality(socketedItem.typeLine)
817+
local gemId = self.build.data.gemForBaseName[normalizedBasename]
800818
if not gemId and socketedItem.hybrid then
801819
-- Dual skill gems (currently just Stormbind) show the second skill as the typeLine, which won't match the actual gem
802820
-- Luckily the primary skill name is also there, so we can find the gem using that
803-
gemId = self.build.data.gemForBaseName[socketedItem.hybrid.baseTypeName]
821+
normalizedBasename, qualityType = self:GetBaseNameAndQuality(socketedItem.hybrid.baseTypeName)
822+
gemId = self.build.data.gemForBaseName[normalizedBasename]
804823
end
805824
if gemId then
806825
local gemInstance = { level = 20, quality = 0, enabled = true, enableGlobal1 = true, gemId = gemId }
807826
gemInstance.nameSpec = self.build.data.gems[gemId].name
808827
gemInstance.support = socketedItem.support
828+
gemInstance.qualityId = qualityType
809829
for _, property in pairs(socketedItem.properties) do
810830
if property.name == "Level" then
811831
gemInstance.level = tonumber(property.values[1][1]:match("%d+"))

Classes/ItemSlotControl.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,13 @@ function ItemSlotClass:Draw(viewPort)
126126
self:DrawControls(viewPort)
127127
if not main.popups[1] and self.nodeId and (self.dropped or (self:IsMouseOver() and (self.otherDragSource or not self.itemsTab.selControl))) then
128128
SetDrawLayer(nil, 15)
129+
local viewerY
130+
if self.DropDownControl.dropUp and self.DropDownControl.dropped then
131+
viewerY = y + 20
132+
else
133+
viewerY = m_min(y - 300 - 5, viewPort.y + viewPort.height - 304)
134+
end
129135
local viewerX = x
130-
local viewerY = m_min(y - 300 - 5, viewPort.y + viewPort.height - 304)
131136
SetDrawColor(1, 1, 1)
132137
DrawImage(nil, viewerX, viewerY, 304, 304)
133138
local viewer = self.itemsTab.socketViewer

Classes/ItemsTab.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro
103103
swapSlot.shown = function()
104104
return self.activeItemSet.useSecondWeaponSet
105105
end
106-
for i = 1, 2 do
106+
for i = 1, 6 do
107107
local abyssal = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 0, self, slotName.."Swap Abyssal Socket "..i, "Abyssal #"..i)
108108
addSlot(abyssal)
109109
abyssal.parentSlot = swapSlot
@@ -116,7 +116,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro
116116
end
117117
if slotName == "Weapon 1" or slotName == "Weapon 2" or slotName == "Helmet" or slotName == "Gloves" or slotName == "Body Armour" or slotName == "Boots" or slotName == "Belt" then
118118
-- Add Abyssal Socket slots
119-
for i = 1, 2 do
119+
for i = 1, 6 do
120120
local abyssal = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 0, self, slotName.." Abyssal Socket "..i, "Abyssal #"..i)
121121
addSlot(abyssal)
122122
abyssal.parentSlot = slot
@@ -1118,7 +1118,7 @@ function ItemsTabClass:AddItem(item, noAutoEquip, index)
11181118
self.items[item.id] = item
11191119
item:BuildModList()
11201120

1121-
if replacing and (replacing.clusterJewel or item.clusterJewel) then
1121+
if replacing and (replacing.clusterJewel or item.clusterJewel or replacing.baseName == "Timeless Jewel") then
11221122
-- We're replacing an existing item, and either the new or old one is a cluster jewel
11231123
if isValueInTable(self.build.spec.jewels, item.id) then
11241124
-- Item is currently equipped, so we need to rebuild the graphs

Classes/PassiveSpec.lua

Lines changed: 182 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -471,26 +471,35 @@ end
471471
function PassiveSpecClass:BuildAllDependsAndPaths()
472472
-- This table will keep track of which nodes have been visited during each path-finding attempt
473473
local visited = { }
474-
474+
local attributes = { "Dexterity", "Intelligence", "Strength" }
475475
-- Check all nodes for other nodes which depend on them (i.e. are only connected to the tree through that node)
476476
for id, node in pairs(self.nodes) do
477477
node.depends = wipeTable(node.depends)
478478
node.dependsOnIntuitiveLeapLike = false
479+
node.conqueredBy = nil
480+
481+
-- ignore cluster jewel nodes that don't have an id in the tree
482+
if self.tree.nodes[id] then
483+
self:ReplaceNode(node,self.tree.nodes[id])
484+
end
485+
479486
if node.type ~= "ClassStart" and node.type ~= "Socket" then
480487
for nodeId, itemId in pairs(self.jewels) do
481488
if self.build.itemsTab.items[itemId] and self.build.itemsTab.items[itemId].jewelRadiusIndex then
482489
local radiusIndex = self.build.itemsTab.items[itemId].jewelRadiusIndex
483490
if self.allocNodes[nodeId] and self.nodes[nodeId].nodesInRadius and self.nodes[nodeId].nodesInRadius[radiusIndex][node.id] then
484-
if itemId ~= 0
485-
and self.build.itemsTab.items[itemId].jewelData
486-
and self.build.itemsTab.items[itemId].jewelData.intuitiveLeapLike then
487-
-- This node depends on Intuitive Leap-like behaviour
488-
-- This flag:
489-
-- 1. Prevents generation of paths from this node
490-
-- 2. Prevents this node from being deallocated via dependency
491-
-- 3. Prevents allocation of path nodes when this node is being allocated
492-
node.dependsOnIntuitiveLeapLike = true
493-
break
491+
if itemId ~= 0 and self.build.itemsTab.items[itemId].jewelData then
492+
if self.build.itemsTab.items[itemId].jewelData.intuitiveLeapLike then
493+
-- This node depends on Intuitive Leap-like behaviour
494+
-- This flag:
495+
-- 1. Prevents generation of paths from this node
496+
-- 2. Prevents this node from being deallocted via dependancy
497+
-- 3. Prevents allocation of path nodes when this node is being allocated
498+
node.dependsOnIntuitiveLeapLike = true
499+
end
500+
if self.build.itemsTab.items[itemId].jewelData.conqueredBy then
501+
node.conqueredBy = self.build.itemsTab.items[itemId].jewelData.conqueredBy
502+
end
494503
end
495504
end
496505
end
@@ -500,6 +509,64 @@ function PassiveSpecClass:BuildAllDependsAndPaths()
500509
node.depends[1] = node -- All nodes depend on themselves
501510
end
502511
end
512+
513+
for id, node in pairs(self.nodes) do
514+
-- If node is conquered, replace it or add mods
515+
if node.conqueredBy and node.type ~= "Socket" then
516+
local conqueredBy = node.conqueredBy
517+
local legionNodes = self.tree.legion.nodes
518+
519+
-- Replace with edited node if applicable
520+
if self.tree.legion.editedNodes and self.tree.legion.editedNodes[conqueredBy.id] and self.tree.legion.editedNodes[conqueredBy.id][node.id] then
521+
local editedNode = self.tree.legion.editedNodes[conqueredBy.id][node.id]
522+
node.dn = editedNode.dn
523+
node.sd = editedNode.sd
524+
node.sprites = editedNode.sprites
525+
node.mods = editedNode.mods
526+
node.modList = editedNode.modList
527+
node.modKey = editedNode.modKey
528+
else
529+
if node.type == "Keystone" then
530+
local legionNode = legionNodes[conqueredBy.conqueror.type.."_keystone_"..conqueredBy.conqueror.id]
531+
self:ReplaceNode(node, legionNode)
532+
elseif conqueredBy.conqueror.type == "eternal" and node.type == "Normal" then
533+
local legionNode =legionNodes["eternal_small_blank"]
534+
self:ReplaceNode(node,legionNode)
535+
elseif conqueredBy.conqueror.type == "templar" then
536+
if isValueInArray(attributes, node.dn) then
537+
local legionNode =legionNodes["templar_devotion_node"]
538+
self:ReplaceNode(node,legionNode)
539+
else
540+
self:NodeAdditionOrReplacementFromString(node,"+5 to Devotion")
541+
end
542+
elseif conqueredBy.conqueror.type == "maraketh" and node.type == "Normal" then
543+
local dex = isValueInArray(attributes, node.dn) and "2" or "4"
544+
self:NodeAdditionOrReplacementFromString(node,"+"..dex.." to Dexterity")
545+
elseif conqueredBy.conqueror.type == "karui" and node.type == "Normal" then
546+
local str = isValueInArray(attributes, node.dn) and "2" or "4"
547+
self:NodeAdditionOrReplacementFromString(node,"+"..str.." to Strength")
548+
elseif conqueredBy.conqueror.type == "vaal" and node.type == "Normal" then
549+
local legionNode =legionNodes["vaal_small_fire_resistance"]
550+
node.dn = "Vaal small node"
551+
node.sd = {"Right click to set mod"}
552+
node.sprites = legionNode.sprites
553+
node.mods = {""}
554+
node.modList = new("ModList")
555+
node.modKey = ""
556+
elseif conqueredBy.conqueror.type == "vaal" and node.type == "Notable" then
557+
local legionNode =legionNodes["vaal_notable_curse_1"]
558+
node.dn = "Vaal notable node"
559+
node.sd = {"Right click to set mod"}
560+
node.sprites = legionNode.sprites
561+
node.mods = {""}
562+
node.modList = new("ModList")
563+
node.modKey = ""
564+
end
565+
end
566+
end
567+
end
568+
569+
503570
for id, node in pairs(self.allocNodes) do
504571
node.visited = true
505572

@@ -580,6 +647,18 @@ function PassiveSpecClass:BuildAllDependsAndPaths()
580647
end
581648
end
582649

650+
function PassiveSpecClass:ReplaceNode(old, new)
651+
-- Edited nodes can share a name
652+
if old.sd == new.sd then return 1 end
653+
old.dn = new.dn
654+
old.sd = new.sd
655+
old.mods = new.mods
656+
old.modKey = new.modKey
657+
old.modList = new.modList
658+
old.sprites = new.sprites
659+
old.keystoneMod = new.keystoneMod
660+
end
661+
583662
function PassiveSpecClass:BuildClusterJewelGraphs()
584663
-- Remove old subgraphs
585664
for id, subGraph in pairs(self.subGraphs) do
@@ -845,7 +924,7 @@ function PassiveSpecClass:BuildSubgraph(jewel, parentSocket, id, upSize)
845924
-- Silently fail to handle cases of jewels with more notables than should be allowed
846925
break
847926
end
848-
927+
849928
-- Construct the new node
850929
local node = {
851930
type = "Notable",
@@ -916,7 +995,7 @@ function PassiveSpecClass:BuildSubgraph(jewel, parentSocket, id, upSize)
916995

917996
assert(indicies[0], "No entrance to subgraph")
918997
subGraph.entranceNode = indicies[0]
919-
998+
920999
-- Correct position to account for index of proxy node
9211000
for _, node in pairs(indicies) do
9221001
node.oidx = (node.oidx + proxyNode.oidx) % clusterJewel.totalIndicies
@@ -987,3 +1066,93 @@ end
9871066
function PassiveSpecClass:SetWindowTitleWithBuildClass()
9881067
main:SetWindowTitleSubtext(string.format("%s (%s)", self.build.buildName, self.curAscendClassId == 0 and self.curClassName or self.curAscendClassName))
9891068
end
1069+
1070+
--- Adds a line to or replaces a node given a line to add/replace with
1071+
--- @param node table The node to replace/add to
1072+
--- @param sd string The line being parsed and added
1073+
--- @param replacement boolean true to replace the node with the new mod, false to simply add it
1074+
function PassiveSpecClass:NodeAdditionOrReplacementFromString(node,sd,replacement)
1075+
local addition = {}
1076+
addition.sd = {sd}
1077+
addition.mods = { }
1078+
addition.modList = new("ModList")
1079+
addition.modKey = ""
1080+
local i = 1
1081+
while addition.sd[i] do
1082+
if addition.sd[i]:match("\n") then
1083+
local line = addition.sd[i]
1084+
local lineIdx = i
1085+
t_remove(addition.sd, i)
1086+
for line in line:gmatch("[^\n]+") do
1087+
t_insert(addition.sd, lineIdx, line)
1088+
lineIdx = lineIdx + 1
1089+
end
1090+
end
1091+
local line = addition.sd[i]
1092+
local parsedMod, unrecognizedMod = modLib.parseMod[self.build.targetVersion](line)
1093+
if not parsedMod or unrecognizedMod then
1094+
-- Try to combine it with one or more of the lines that follow this one
1095+
local endI = i + 1
1096+
while addition.sd[endI] do
1097+
local comb = line
1098+
for ci = i + 1, endI do
1099+
comb = comb .. " " .. addition.sd[ci]
1100+
end
1101+
parsedMod, unrecognizedMod = modLib.parseMod[self.build.targetVersion](comb, true)
1102+
if parsedMod and not unrecognizedMod then
1103+
-- Success, add dummy mod lists to the other lines that were combined with this one
1104+
for ci = i + 1, endI do
1105+
addition.mods[ci] = { list = { } }
1106+
end
1107+
break
1108+
end
1109+
endI = endI + 1
1110+
end
1111+
end
1112+
if not parsedMod then
1113+
-- Parser had no idea how to read this modifier
1114+
addition.unknown = true
1115+
elseif unrecognizedMod then
1116+
-- Parser recognised this as a modifier but couldn't understand all of it
1117+
addition.extra = true
1118+
else
1119+
for _, mod in ipairs(parsedMod) do
1120+
addition.modKey = addition.modKey.."["..modLib.formatMod(mod).."]"
1121+
end
1122+
end
1123+
addition.mods[i] = { list = parsedMod, extra = unrecognizedMod }
1124+
i = i + 1
1125+
while addition.mods[i] do
1126+
-- Skip any lines with dummy lists added by the line combining code
1127+
i = i + 1
1128+
end
1129+
end
1130+
1131+
-- Build unified list of modifiers from all recognised modifier lines
1132+
for _, mod in pairs(addition.mods) do
1133+
if mod.list and not mod.extra then
1134+
for i, mod in ipairs(mod.list) do
1135+
mod.source = "Tree:"..node.id
1136+
if type(mod.value) == "table" and mod.value.mod then
1137+
mod.value.mod.source = mod.source
1138+
end
1139+
addition.modList:AddMod(mod)
1140+
end
1141+
end
1142+
end
1143+
if replacement then
1144+
node.sd = addition.sd
1145+
node.mods = addition.mods
1146+
node.modKey = addition.modKey
1147+
else
1148+
node.sd = tableConcat(node.sd, addition.sd)
1149+
node.mods = tableConcat(node.mods, addition.mods)
1150+
node.modKey = node.modKey .. addition.modKey
1151+
end
1152+
local modList = new("ModList")
1153+
modList:AddList(addition.modList)
1154+
if not replacement then
1155+
modList:AddList(node.modList)
1156+
end
1157+
node.modList = modList
1158+
end

0 commit comments

Comments
 (0)