Skip to content

Commit e1f94ad

Browse files
committed
Merge branch 'dev' into merc-uniques
2 parents 47c61f0 + f7cc078 commit e1f94ad

28 files changed

Lines changed: 752 additions & 350 deletions

.github/workflows/backport.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Port changes to PoB2
2+
3+
on:
4+
pull_request_target:
5+
types: [closed]
6+
7+
env:
8+
LABEL_STRING: ${{ join(github.event.pull_request.labels.*.name, ',') }}
9+
10+
jobs:
11+
backport:
12+
if: github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'pob2')
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Notify PathOfBuilding repo
16+
uses: peter-evans/repository-dispatch@v3
17+
with:
18+
token: ${{ secrets.WIRES77_PAT }}
19+
repository: ${{ github.repository_owner }}/PathOfBuilding-PoE2
20+
event-type: port-changes
21+
client-payload: '{"patch_url": "${{ github.event.pull_request.patch_url }}", "msg": "Apply changes from ${{ github.event.pull_request.html_url }}", "id": ${{ github.event.pull_request.number }}, "title": "${{ github.event.pull_request.title }}", "labels": "${{ env.LABEL_STRING }}", "name": "${{ github.event.pull_request.user.name }}", "user": "${{ github.event.pull_request.user.login }}"}'
22+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Update code with code from PoB2
2+
3+
on:
4+
repository_dispatch:
5+
types:
6+
- port-changes
7+
8+
jobs:
9+
apply-patch:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Checkout
13+
uses: actions/checkout@v3
14+
with:
15+
ref: 'dev'
16+
- name: Apply patch
17+
run: |
18+
curl -L ${{ github.event.client_payload.patch_url }} | git apply -v --index
19+
- name: Create Pull Request
20+
uses: peter-evans/create-pull-request@v5
21+
with:
22+
title: "[pob2-port] ${{ github.event.client_payload.title }}"
23+
branch: pob2-pr-${{ github.event.client_payload.id }}
24+
body: |
25+
${{ github.event.client_payload.msg }}
26+
author: ${{ github.event.client_payload.name || github.event.client_payload.user }} <${{ github.event.client_payload.user }}@users.noreply.github.com>
27+
commit-message: ${{ github.event.client_payload.msg }}
28+
labels: ${{ github.event.client_payload.labels }}

.github/workflows/release.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ jobs:
4040
sed -i 's/\[Voronoff/\[Tom Clancy Is Dead/' temp_change.md;
4141
sed -i 's/\[PJacek/\[TPlant/' temp_change.md;
4242
sed -i 's/\[justjuangui/\[trompetin17/' temp_change.md;
43+
sed -i 's/\r//g' temp_change.md;
4344
cp temp_change.md changelog_temp.txt;
4445
cat CHANGELOG.md | tr \\r \\n | sed '1d' >> temp_change.md;
4546
printf "# Changelog\n\n## [v${{ github.event.inputs.releaseVersion }}](https://github.com/PathOfBuildingCommunity/PathOfBuilding/tree/v${{ github.event.inputs.releaseVersion }}) ($(date +'%Y/%m/%d'))\n\n" | cat - temp_change.md > CHANGELOG.md;

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ Z:\home\dev\.vscode\extensions\tangzx.emmylua-0.8.20-linux-x64\debugger\emmy\win
208208

209209
## Testing
210210

211-
PoB uses the [Busted](https://olivinelabs.com/busted/) framework to run its tests. Tests are stored under `spec/System` and run automatically when a PR is modified.
211+
PoB uses the [Busted](https://lunarmodules.github.io/busted/) framework to run its tests. Tests are stored under `spec/System` and run automatically when a PR is modified.
212212
More tests can be added to this folder to test specific functionality, or new test builds can be added to ensure nothing changed that wasn't intended.
213213

214214
### Running tests

spec/System/TestImpale_spec.lua

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,4 +284,45 @@ describe("TestAttacks", function()
284284
assert.are.near(120*1.3, build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- 6 impales * 10% stored damage * 1.3 attacks per second
285285
end)
286286

287+
it("impale dual wield simultaneous attack", function()
288+
newBuild()
289+
build.skillsTab:PasteSocketGroup("Cleave 20/0 Default 1\n")
290+
-- exactly 100
291+
build.itemsTab:CreateDisplayItemFromRaw("New Item\nVaal Blade\nQuality: 0\nAdds 54 to 14 physical damage\n50% chance to Impale Enemies on Hit with Attacks")
292+
build.itemsTab:AddDisplayItem()
293+
-- exactly 200 offhand
294+
build.itemsTab:CreateDisplayItemFromRaw("New Item\nVaal Blade\nQuality: 0\nAdds 54 to 14 physical damage\n100% increased Physical Damage\n50% chance to Impale Enemies on Hit with Attacks")
295+
build.itemsTab:AddDisplayItem()
296+
build.itemsTab:CreateDisplayItemFromRaw("New Item\nPaua Amulet\nYour hits can't be evaded\n-20 strength\n")
297+
build.itemsTab:AddDisplayItem()
298+
299+
-- 0% crit
300+
build.configTab.input.customMods = "\z
301+
never deal critical strikes\n\z
302+
Impale Damage dealt to Enemies Impaled by you Overwhelms 100% Physical Damage Reduction\n\z
303+
Overwhelm 100% physical damage reduction\n\z
304+
"
305+
build.configTab:BuildModList()
306+
runCallback("OnFrame")
307+
308+
assert.are.equals(50, build.calcsTab.mainOutput.MainHand.ImpaleChance)
309+
assert.are.equals(50, build.calcsTab.mainOutput.OffHand.ImpaleChance)
310+
assert.are.equals(50, build.calcsTab.mainOutput.MainHand.ImpaleChanceOnCrit)
311+
assert.are.equals(50, build.calcsTab.mainOutput.OffHand.ImpaleChanceOnCrit)
312+
313+
-- level 20 cleave (currently) has 511.2% damage effectiveness and a 40% less modifier for combined attacks
314+
-- things get rounded in the calc tab so there's some margin
315+
assert.are.near(5.112*100*0.6, build.calcsTab.mainOutput.MainHand.PhysicalHitAverage, 1)
316+
assert.are.near(5.112*200*0.6, build.calcsTab.mainOutput.OffHand.PhysicalHitAverage, 1)
317+
assert.are.near(5.112*100*0.6, build.calcsTab.mainOutput.MainHand.impaleStoredHitAvg, 1)
318+
assert.are.near(5.112*200*0.6, build.calcsTab.mainOutput.OffHand.impaleStoredHitAvg, 1)
319+
-- 5 impales * 10% stored damage * 50% impale chance
320+
assert.are.equals(1+(5*0.1*0.5), build.calcsTab.mainOutput.MainHand.ImpaleModifier)
321+
assert.are.equals(1+(5*0.1*0.5), build.calcsTab.mainOutput.OffHand.ImpaleModifier)
322+
323+
-- stored damage * 0.25 impale modifier * 1.3 attacks per second * 0.8 cleave modifier * 1.1 dual wield modifier
324+
assert.are.near(300*5.112*0.6*0.25*1.3*0.8*1.1, build.calcsTab.mainOutput.ImpaleDPS, 0.1)
325+
326+
end)
327+
287328
end)

src/Classes/Item.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -813,7 +813,7 @@ function ItemClass:ParseRaw(raw, rarity, highQuality)
813813
elseif gameModeStage == "FINDEXPLICIT" then
814814
gameModeStage = "DONE"
815815
end
816-
elseif foundExplicit then
816+
elseif foundExplicit or (not foundExplicit and gameModeStage == "EXPLICIT") then
817817
modLine.modList = { }
818818
modLine.extra = line
819819
t_insert(modLines, modLine)
@@ -1516,7 +1516,8 @@ function ItemClass:BuildModListForSlotNum(baseList, slotNum)
15161516
elseif self.base.tincture then
15171517
local tinctureData = self.tinctureData
15181518
tinctureData.manaBurn = (self.base.tincture.manaBurn + 0.01) / (1 + calcLocal(modList, "TinctureManaBurnRate", "INC", 0) / 100) / (1 + calcLocal(modList, "TinctureManaBurnRate", "MORE", 0) / 100)
1519-
tinctureData.cooldown = self.base.tincture.cooldown / (1 + calcLocal(modList, "TinctureCooldownRecovery", "INC", 0) / 100)
1519+
tinctureData.cooldownInc = calcLocal(modList, "TinctureCooldownRecovery", "INC", 0) + calcLocal(modList, "CooldownRecovery", "INC", 0)
1520+
tinctureData.cooldown = self.base.tincture.cooldown / (1 + tinctureData.cooldownInc / 100)
15201521
tinctureData.effectInc = calcLocal(modList, "TinctureEffect", "INC", 0) + calcLocal(modList, "LocalEffect", "INC", 0)
15211522
for _, value in ipairs(modList:List(nil, "TinctureData")) do
15221523
tinctureData[value.key] = value.value

src/Classes/ItemsTab.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3681,12 +3681,12 @@ function ItemsTabClass:AddItemTooltip(tooltip, item, slot, dbMode)
36813681
if effectMod ~= 1 then
36823682
t_insert(stats, s_format("^8Tincture effect modifier: ^7%+d%%", effectMod * 100 - 100))
36833683
end
3684-
t_insert(stats, s_format("^8Mana Burn Inflicted Every Second: ^7%.2f", tinctureData.manaBurn / (1 + modDB:Sum("INC", { actor = "player" }, "TinctureManaBurnRate")/100) / (1 + modDB:Sum("MORE", { actor = "player" }, "TinctureManaBurnRate")/100)))
3684+
t_insert(stats, s_format("^8Mana Burn Inflicted Every Second: ^7%.2f", 1 / (tinctureData.manaBurn / (1 + modDB:Sum("INC", { actor = "player" }, "TinctureManaBurnRate") / 100) / (1 + modDB:Sum("MORE", { actor = "player" }, "TinctureManaBurnRate") / 100))))
36853685
local TincturesNotInflictManaBurn = m_min(modDB:Sum("BASE", nil, "TincturesNotInflictManaBurn"), 100)
36863686
if TincturesNotInflictManaBurn ~= 0 then
36873687
t_insert(stats, s_format("^8Chance to not inflict Mana Burn: ^7%d%%", TincturesNotInflictManaBurn))
36883688
end
3689-
t_insert(stats, s_format("^8Tincture Cooldown when deactivated: ^7%.2f^8 seconds", tinctureData.cooldown / (1 + modDB:Sum("INC", { actor = "player" }, "TinctureCooldownRecovery")/100)))
3689+
t_insert(stats, s_format("^8Tincture Cooldown when deactivated: ^7%.2f^8 seconds", base.tincture.cooldown / (1 + (modDB:Sum("INC", { actor = "player" }, "TinctureCooldownRecovery") + tinctureData.cooldownInc) / 100)))
36903690

36913691
if stats[1] then
36923692
tooltip:AddLine(14, "^7Effective tincture stats:")

src/Classes/TradeQueryGenerator.lua

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ local TradeQueryGeneratorClass = newClass("TradeQueryGenerator", function(self,
109109
self.queryTab = queryTab
110110
self.itemsTab = queryTab.itemsTab
111111
self.calcContext = { }
112-
112+
self.lastMaxPrice = nil
113+
self.lastMaxPriceTypeIndex = nil
114+
self.lastMaxLevel = nil
113115
end)
114116

115117
local function fetchStats()
@@ -188,6 +190,9 @@ function TradeQueryGeneratorClass.WeightedRatioOutputs(baseOutput, newOutput, st
188190
end
189191
end
190192
for _, statTable in ipairs(statWeights) do
193+
if statTable.stat == "FullDPS" and not (baseOutput["FullDPS"] and newOutput["FullDPS"]) then
194+
meanStatDiff = meanStatDiff + ratioModSums("TotalDPS", "TotalDotDPS", "CombinedDPS") * statTable.weightMult
195+
end
191196
meanStatDiff = meanStatDiff + ratioModSums(statTable.stat) * statTable.weightMult
192197
end
193198
return meanStatDiff
@@ -652,7 +657,37 @@ function TradeQueryGeneratorClass:OnFrame()
652657
end
653658
end
654659

660+
local currencyTable = {
661+
{ name = "Chaos Orb Equivalent", id = nil },
662+
{ name = "Chaos Orb", id = "chaos" },
663+
{ name = "Divine Orb", id = "divine" },
664+
{ name = "Orb of Alchemy", id = "alch" },
665+
{ name = "Orb of Alteration", id = "alt" },
666+
{ name = "Chromatic Orb", id = "chrome" },
667+
{ name = "Exalted Orb", id = "exalted" },
668+
{ name = "Blessed Orb", id = "blessed" },
669+
{ name = "Cartographer's Chisel", id = "chisel" },
670+
{ name = "Gemcutter's Prism", id = "gcp" },
671+
{ name = "Jeweller's Orb", id = "jewellers" },
672+
{ name = "Orb of Scouring", id = "scour" },
673+
{ name = "Orb of Regret", id = "regret" },
674+
{ name = "Orb of Fusing", id = "fusing" },
675+
{ name = "Orb of Chance", id = "chance" },
676+
{ name = "Regal Orb", id = "regal" },
677+
{ name = "Vaal Orb", id = "vaal" }
678+
}
679+
655680
function TradeQueryGeneratorClass:StartQuery(slot, options)
681+
if self.lastMaxPrice then
682+
options.maxPrice = self.lastMaxPrice
683+
end
684+
if self.lastMaxPriceTypeIndex then
685+
options.maxPriceType = currencyTable[self.lastMaxPriceTypeIndex].id
686+
end
687+
if self.lastMaxLevel then
688+
options.maxLevel = self.lastMaxLevel
689+
end
690+
656691
-- Figure out what type of item we're searching for
657692
local existingItem = slot and self.itemsTab.items[slot.selItemId]
658693
local testItemType = existingItem and existingItem.baseName or "Unset Amulet"
@@ -921,12 +956,12 @@ function TradeQueryGeneratorClass:FinishQuery()
921956
end
922957
end
923958
if not options.includeMirrored then
924-
queryTable.query.filters.misc_filters = {
925-
disabled = false,
926-
filters = {
927-
mirrored = false,
928-
}
929-
}
959+
queryTable.query.filters.misc_filters = {
960+
disabled = false,
961+
filters = {
962+
mirrored = false,
963+
}
964+
}
930965
end
931966

932967
if options.maxPrice and options.maxPrice > 0 then
@@ -1072,35 +1107,19 @@ function TradeQueryGeneratorClass:RequestQuery(slot, context, statWeights, callb
10721107
end
10731108

10741109
-- Add max price limit selection dropbox
1075-
local currencyTable = {
1076-
{ name = "Chaos Orb Equivalent", id = nil },
1077-
{ name = "Chaos Orb", id = "chaos" },
1078-
{ name = "Divine Orb", id = "divine" },
1079-
{ name = "Orb of Alchemy", id = "alch" },
1080-
{ name = "Orb of Alteration", id = "alt" },
1081-
{ name = "Chromatic Orb", id = "chrome" },
1082-
{ name = "Exalted Orb", id = "exalted" },
1083-
{ name = "Blessed Orb", id = "blessed" },
1084-
{ name = "Cartographer's Chisel", id = "chisel" },
1085-
{ name = "Gemcutter's Prism", id = "gcp" },
1086-
{ name = "Jeweller's Orb", id = "jewellers" },
1087-
{ name = "Orb of Scouring", id = "scour" },
1088-
{ name = "Orb of Regret", id = "regret" },
1089-
{ name = "Orb of Fusing", id = "fusing" },
1090-
{ name = "Orb of Chance", id = "chance" },
1091-
{ name = "Regal Orb", id = "regal" },
1092-
{ name = "Vaal Orb", id = "vaal" }
1093-
}
10941110
local currencyDropdownNames = { }
10951111
for _, currency in ipairs(currencyTable) do
10961112
t_insert(currencyDropdownNames, currency.name)
10971113
end
10981114
controls.maxPrice = new("EditControl", {"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 70, 18}, nil, nil, "%D")
1115+
controls.maxPrice.buf = self.lastMaxPrice and tostring(self.lastMaxPrice) or ""
10991116
controls.maxPriceType = new("DropDownControl", {"LEFT",controls.maxPrice,"RIGHT"}, {5, 0, 150, 18}, currencyDropdownNames, nil)
1117+
controls.maxPriceType.selIndex = self.lastMaxPriceTypeIndex or 1
11001118
controls.maxPriceLabel = new("LabelControl", {"RIGHT",controls.maxPrice,"LEFT"}, {-5, 0, 0, 16}, "^7Max Price:")
11011119
updateLastAnchor(controls.maxPrice)
11021120

11031121
controls.maxLevel = new("EditControl", {"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 100, 18}, nil, nil, "%D")
1122+
controls.maxLevel.buf = self.lastMaxLevel and tostring(self.lastMaxLevel) or ""
11041123
controls.maxLevelLabel = new("LabelControl", {"RIGHT",controls.maxLevel,"LEFT"}, {-5, 0, 0, 16}, "Max Level:")
11051124
updateLastAnchor(controls.maxLevel)
11061125

@@ -1177,10 +1196,13 @@ function TradeQueryGeneratorClass:RequestQuery(slot, context, statWeights, callb
11771196
end
11781197
if controls.maxPrice.buf then
11791198
options.maxPrice = tonumber(controls.maxPrice.buf)
1199+
self.lastMaxPrice = options.maxPrice
11801200
options.maxPriceType = currencyTable[controls.maxPriceType.selIndex].id
1201+
self.lastMaxPriceTypeIndex = controls.maxPriceType.selIndex
11811202
end
11821203
if controls.maxLevel.buf then
11831204
options.maxLevel = tonumber(controls.maxLevel.buf)
1205+
self.lastMaxLevel = options.maxLevel
11841206
end
11851207
if controls.sockets and controls.sockets.buf then
11861208
options.sockets = tonumber(controls.sockets.buf)

0 commit comments

Comments
 (0)