diff --git a/spec/System/TestSkills_spec.lua b/spec/System/TestSkills_spec.lua index 63a681fca..9c756768e 100644 --- a/spec/System/TestSkills_spec.lua +++ b/spec/System/TestSkills_spec.lua @@ -102,6 +102,25 @@ describe("TestSkills", function() assert.True(math.abs(finalCost - 8.67) < 0.1) -- floor(9 * 1.5) / 1.5 end) + it("Fractional skill count scales Full DPS", function() + build.skillsTab:PasteSocketGroup("Ball Lightning 20/0 1") + build.skillsTab.socketGroupList[1].includeInFullDPS = true + runCallback("OnFrame") + + local fullDPS = build.calcsTab.mainOutput.FullDPS + assert.truthy(fullDPS) + assert.True(fullDPS > 0) + + newBuild() + + build.skillsTab:PasteSocketGroup("Ball Lightning 20/0 0.5") + build.skillsTab.socketGroupList[1].includeInFullDPS = true + runCallback("OnFrame") + + assert.are.equals(0.5, build.skillsTab.socketGroupList[1].gemList[1].count) + assert.True(math.abs(build.calcsTab.mainOutput.FullDPS - fullDPS * 0.5) < fullDPS * 0.001) + end) + it("Test mana cost efficiency with support gems", function() -- Test interaction between cost efficiency and cost multipliers build.skillsTab:PasteSocketGroup("Contagion 6/0 1\nMagnified Area I 1/0 1") diff --git a/src/Classes/EditControl.lua b/src/Classes/EditControl.lua index 2964057ad..ca597de71 100644 --- a/src/Classes/EditControl.lua +++ b/src/Classes/EditControl.lua @@ -61,7 +61,7 @@ local EditClass = newClass("EditControl", "ControlHost", "Control", "UndoHandler local _, height = self:GetSize() return height - 4 end - if self.filter == "%D" or self.filter == "^%-%d" then + if self.filter == "%D" or self.filter == "^%-%d" or self.filter == "^%d." then -- Add +/- buttons for integer number edits self.isNumeric = true self.controls.buttonDown = new("ButtonControl", {"RIGHT",self,"RIGHT"}, {-2, 0, buttonSize, buttonSize}, "-", function() @@ -686,8 +686,12 @@ function EditClass:OnKeyUp(key) end end elseif key == "WHEELDOWN" or key == "DOWN" then - if cur and (self.filter ~= "%D" or cur > 0)then - self:SetText(tostring(cur - (self.numberInc or 1)), true) + if cur then + local value = cur - (self.numberInc or 1) + if self.filter == "%D" or self.filter == "^%d." then + value = m_max(value, 0) + end + self:SetText(tostring(value), true) else if self.placeholder then self:SetText(tostring((tonumber(self.placeholder) or 0) - (self.numberInc or 1)), true) diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index 371355f55..8425f00d9 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -193,7 +193,7 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.controls.groupCountLabel.shown = function() return self.displayGroup.source ~= nil end - self.controls.groupCount = new("EditControl", { "LEFT", self.controls.groupCountLabel, "RIGHT" }, { 4, 0, 60, 20 }, nil, nil, "%D", 2, function(buf) + self.controls.groupCount = new("EditControl", { "LEFT", self.controls.groupCountLabel, "RIGHT" }, { 4, 0, 80, 20 }, nil, nil, "^%d.", 6, function(buf) self.displayGroup.groupCount = tonumber(buf) or 1 self:AddUndoState() self.build.buildFlag = true @@ -254,7 +254,7 @@ will automatically apply to the skill.]] self.controls.gemLevelHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].level, "TOPLEFT"}, {0, -2, 0, 16}, "^7Level:") self.controls.gemQualityHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].quality, "TOPLEFT"}, {0, -2, 0, 16}, "^7Quality:") self.controls.gemEnableHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].enabled, "TOPLEFT"}, {-16, -2, 0, 16}, "^7Enabled:") - self.controls.gemCountHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].count, "TOPLEFT"}, {8, -2, 0, 16}, "^7Count:") + self.controls.gemCountHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].count, "TOPLEFT"}, {18, -2, 0, 16}, "^7Count:") end) function SkillsTabClass:LoadSkill(node, skillSetId) @@ -506,7 +506,7 @@ function SkillsTabClass:Draw(viewPort, inputEvents) self.controls.scrollBarH.y = viewPort.y + viewPort.height - 18 do - local maxX = self.controls.gemCountHeader:GetPos() + self.controls.gemCountHeader:GetSize() + 15 + local maxX = self.controls.gemCountHeader:GetPos() + self.controls.gemCountHeader:GetSize() + 25 local contentWidth = maxX - self.x self.controls.scrollBarH:SetContentDimension(contentWidth, viewPort.width) end @@ -568,7 +568,7 @@ function SkillsTabClass:CopySocketGroup(socketGroup) skillText = skillText .. "Slot: " .. socketGroup.slot .. "\r\n" end for _, gemInstance in ipairs(socketGroup.gemList) do - skillText = skillText .. string.format("%s %d/%d %s %d\r\n", gemInstance.nameSpec, gemInstance.level, gemInstance.quality, gemInstance.enabled and "" or "DISABLED", gemInstance.count or 1) + skillText = skillText .. string.format("%s %d/%d %s %s\r\n", gemInstance.nameSpec, gemInstance.level, gemInstance.quality, gemInstance.enabled and "" or "DISABLED", string.format("%g", gemInstance.count or 1)) end Copy(skillText) end @@ -585,7 +585,7 @@ function SkillsTabClass:PasteSocketGroup(testInput) if slot then newGroup.slot = slot end - for nameSpec, level, quality, state, count in skillText:gmatch("([ %a']+) (%d+)/(%d+) ?(%a*) (%d+)") do + for nameSpec, level, quality, state, count in skillText:gmatch("([ %a']+) (%d+)/(%d+) ?(%a*) ([%d%.]+)") do t_insert(newGroup.gemList, { nameSpec = nameSpec, level = tonumber(level) or 20, @@ -853,7 +853,7 @@ function SkillsTabClass:CreateGemSlot(index) self.controls["gemSlot"..index.."Enable"] = slot.enabled -- Count gem - slot.count = new("EditControl", {"LEFT",slot.enabled,"RIGHT"}, {18, 0, 60, 20}, nil, nil, "%D", 2, function(buf) + slot.count = new("EditControl", {"LEFT",slot.enabled,"RIGHT"}, {18, 0, 80, 20}, nil, nil, "^%d.", 5, function(buf) local gemInstance = self.displayGroup.gemList[index] if not gemInstance then gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, enabled = true, enableGlobal1 = true, count = 1, new = true } @@ -864,7 +864,6 @@ function SkillsTabClass:CreateGemSlot(index) slot.enableGlobal1.state = true end gemInstance.count = tonumber(buf) or 1 - slot.count.buf = tostring(gemInstance.count) self:ProcessSocketGroup(self.displayGroup) self:AddUndoState() self.build.buildFlag = true @@ -883,7 +882,7 @@ function SkillsTabClass:CreateGemSlot(index) end slot.count.tooltipFunc = function(tooltip) if tooltip:CheckForUpdate(self.build.outputRevision, self.displayGroup) then - tooltip:AddLine(16, "^8Note: `count` integer value scales the DPS of associated skill by a scalar.") + tooltip:AddLine(16, "^8Note: `count` numeric value scales the DPS of associated skill by a scalar.") tooltip:AddLine(16, "^8To be used with totems, minions, shot-gunning of projectiles (e.g., VD, magma-orbs),") tooltip:AddLine(16, "^8multi-hit projectiles (e.g. ball-lightning), traps, mines.") end diff --git a/src/Modules/Build.lua b/src/Modules/Build.lua index ee4b202c7..8ab26d85e 100644 --- a/src/Modules/Build.lua +++ b/src/Modules/Build.lua @@ -1007,11 +1007,12 @@ function buildMode:Save(xml) if skillData.trigger and skillData.trigger ~= "" then triggerStr = skillData.trigger end + local skillCount = skillData.count or 1 local lhsString = skillData.name - if skillData.count >= 2 then - lhsString = tostring(skillData.count).."x "..skillData.name + if skillCount ~= 1 then + lhsString = s_format("%g", skillCount).."x "..skillData.name end - t_insert(xml, { elem = "FullDPSSkill", attrib = { stat = lhsString, value = tostring(skillData.dps * skillData.count), skillPart = skillData.skillPart or "", source = skillData.source or skillData.trigger or "" } }) + t_insert(xml, { elem = "FullDPSSkill", attrib = { stat = lhsString, value = tostring(skillData.dps * skillCount), skillPart = skillData.skillPart or "", source = skillData.source or skillData.trigger or "" } }) end addedStatNames[statName] = true else @@ -1928,14 +1929,15 @@ function buildMode:AddDisplayStatList(statList, actor) if skillData.trigger and skillData.trigger ~= "" then triggerStr = colorCodes.WARNING.." ("..skillData.trigger..")"..labelColor end + local skillCount = skillData.count or 1 local lhsString = labelColor..skillData.name..triggerStr..":" - if skillData.count >= 2 then - lhsString = labelColor..tostring(skillData.count).."x "..skillData.name..triggerStr..":" + if skillCount ~= 1 then + lhsString = labelColor..s_format("%g", skillCount).."x "..skillData.name..triggerStr..":" end t_insert(statBoxList, { height = 16, lhsString, - self:FormatStat({fmt = "1.f"}, skillData.dps * skillData.count, overCapStatVal), + self:FormatStat({fmt = "1.f"}, skillData.dps * skillCount, overCapStatVal), }) if skillData.skillPart then t_insert(statBoxList, {