PathOfBuildingCommunity/PathOfBuilding

Anarchic Spiritblade damage conversion incorrectly applies to spells and attacks with other weapons

Opened this issue · 1 comments

Check version

  • I'm running the latest version of Path of Building and I've verified this by checking the changelog

Check for duplicates

  • I've checked for duplicate open and closed issues by using the search function of the issue tracker

Check for support

  • I've checked that the behaviour is supposed to be supported. If it isn't please open a feature request instead (Red text is a feature request).

What is the behaviour in-game?

The Anarchic Spiritblade (Heist Experimented basetype 1H Sword) has the line "100% of Physical Damage from Hits with this Weapon is Converted to a random Element". In game this only applies to attacks performed with this weapon.

What is the behaviour in Path of Building?

In Path of Building the damage conversion from "100% of Physical Damage from Hits with this Weapon is Converted to a random Element" also applies to spells and attacks that are not performed with the weapon (e.g. Spectral Shield Throw).

The same bug also affects other items with the same modifier wording such as:

  • Capricious Spiritblade, which is the lower level version of the Heist basetype
  • Story of the Vaal
  • Fate of the Vaal

How to reproduce the issue

  1. Equip Anarchic Spiritblade or Capricious Spiritblade in PoB
  2. Add any physical spell skill
  3. Check damage composition in the "Calcs" tab

Character build code

eNrVPGlv4kq2n5tfYSHN0726hLjKeyaZEdnTN-mkIentS6uAAtwxNvGShG71f59zyjaYxcYOzEivW0qM6-x1lqpTRQ7__Tp2pGfuB7bnHtVJU65L3O15fdsdHtUf7s_3zPq__1U7vGPh6HZwHNkOjvyr9u5QPEsOf-bOUd0idSlk_pCHn1JSyncgNWFuOOKee8N-eP6F1z-qf_BcXpe6zO3bYfqp57Ag-MDG_Kh-z8cTh_l1iQU97vZP5iNX7lNkB3bowWBvxHzWC7l_jexbUejdeH2AGTAnAHpjZrsdr_fIwwvfiyZHdVqXnm3-EgNd3dzdtu8zstluVjbQ7d3hncOm3O-ELJQC-HFUb4GJ2JBf2iGQYk4EdKhiaFZTNqhR3y9EOo78IDxlY3isgNyZcN6fwWtNk-RB3vn8bDDgvdB-5ie-HZ6MmNubs9L0pkW1POQ3IdxETmhPHJv7c4WaNA_jcoUDkeU84HsvZM7pXWcOq5iyKjcpoYppFGN588nJpf_ZDkfHDpi2Mo-roWuHPIumKLrc1HRAMw1CrSKWq8hEJaosNw1D1YhmkCLkO88OPPfNRnmDyCeR40CcZzFzLdrmAfefWWgvipgLf-KNu7a7NAHljNHyObsdxM7eZn07Cm546PNgrl5TzcO9YS478YK5iyi0CPSO-5CAwgUMeQNCh_c8yFlVUJBHRcxre8DLQ1bSI0GoKs3b9DjrlIVbT5iYGuSpQqw3SNWGLF0OsuNFTknIMJMnFSs_kJ6ykITmxsEpf52BqQWB-ZQFLKB35WbKmlEkYBaSaFa-gM8eJoTNthFJ6uzyLsOfKE2imhaVZVXLLUN3o2lg95hzw17tcTSGGnPPHrmbsXN-ab22h6PQhfyWh0w0U8lDPrd9_ha8E8_pvwlvxLwgH1EhRZFZyhyw0ugdIPSV25shmIUR_-D6IutnVijFBh_wNgQhroe6Di-NM2eTBHOZFUTMbMjdhON0Hip6UyvCuua8N7qAxWObhbxcCp_by7IK7YvAWfvmL7AQco19CxgsYlQwFSKuNxWVm6QIq6KpzlzuD6edkc2dzJqWKGXgU9lO2KQMqrB2Fj9rdd0ox3GdSUopt94ult5ULS1X5M_M75erTFUle2ZBNgsTvdhqMXjWYPmuw2ERDQh9vrS2l_O3Kd4P3KQ41dBa_tiL_BJFFjWIgbMK5NeotILEO7M270e9ciXr2IG95ZL4tMgfHWcdipmrcRiy3uOp1x-WNpJgUgljtmMUqJ1oMoH8gbNflgDWQVj625kF0J5qbIa-BdfNhrJcVDDLM5hDl2YwWwaU57KEUl4XLOLLbDRaArw0i9mE3kByGEMBEA2EGy-TWZpW_vzAhq_U7k0ALu4p8yPeewHhR9gXCja7fRYa1jubEc597v6cLtOXS4FnGRRUoX7kYzSU5rGMkWWT7kxvbBfCbLVNtNwhsqBqEJkQTTM1xcxDXmwTkaaS_bdTpJXOjGJZatOUiaYSophaMd6a3swK5NreTEku65ssFZBXmywV9VsXEivABY2VFdgNjZVV2msaKyV1WNgrWEQpBCxehKxFKV4urqCsXS4SVSdlECqKt3n1lqLe22NY9ATBKQuZ1E92uJ-YbzM3pCBfXQo483uja0jb58xxulDFj-rZt_hpCZEgItI_3BcddXy6Gk88P5T4K_66Y344TVvbAlC8ATpBaLvCOyCFOE5d6oy8l1b_GdPPvec5wawfziYT7vYXaNz7nEssXQD0UAihI36QxiwIwXZxRQEyv8B1dNrQVdPQfjd-aRpV5IZOqUZ_LzTqr_rCCq4HsqHrmSppGKqqNjRDVRq6rBq0oVFNpg0gQI2GaipAlhpUVhoqwVFDN82Gomma3tA0YgEXAggNXVFVo6FZitZQVGIAtEU1taFQS6H4BlnIKCIllmY24IdMGoSoVG6oikF04K0BPESBDMQMAki6pVpAXSVWg4LDN6hqAIBlWkaDypQCEaBIGgoBnYGRCUSoomtWw7B0GUSM-eggkSarFPQCSU3QztIbBPWhsmUaQloCDBRNaRAFtrsNYhJgpBGQtAHJlqCKKsDEJlZ1FEAHpsDaUE1gqlNDblAqwygB1WXgoYICOn5WLQUMZVICRlN0BXAsCwTVdBmEprqp62gXilSE0pZhoUWAhapaMogra0hc1kBfamiIRCwQT1cpCBbPs6oSU4WpokRFkUA1TZYpCK_rBlBQTBMNC6aBZ2qgUqauAkMwDuCCLUEdBXlppoyQoATw0gmoLKP5qGai4CCCCaLpRsPS4IdmUEoxdLBzx_xpa9HLXBv8PQQfzhw3UTU5SUIATbjzu8OH9rV4eDcKw0lwsL__8vLSnLBw5A34K2xFmj1vvD8BJAiEveDRdpw9JLvfgn_Hw4fjr9-i0WX74-fu3ov6s_3tm2n8fGKPt3brWL2yo_svzvPgy_l073zQOx4P_-6cf71h0afet5vrzrT3FNwH9o-X8OKH_fET_-6f0LP3T49Uu3_5qOtfpqfD0-MeezW__rj8dhOY9xQs_BC0Oj8fBtE5V_6e3BjHF9-D4f1wZLxc_vw6Dn9edLpjxj_ZaigHU7M1-ap_vv3wNCR7XeNDcM3uri_s8ejrmKrta2YFr18nH28uIuVTv6vLId_z39vmp8lV94XSu3b43rxrffl4qbavvjmd4CmyTDp4MU4_P3f__ho-aqr79eyj6Xyx9i5arWuLAX9z-vPL8_DoSBh2P7XsYXzSFuzHn3C96tuQAOKcuY8JRWQ3zDj48MELeYBj-DL9cNhB0wdSAAnvgo-D4ykUsXNMyUtlLUlZCN3hYZx0szhH9dCPOGbZAYscfP8xYo6NGZTK2dfX8cGl6_njWRMRaEEKxb1QTPJ-OsFE1rq-jkdaTphQQ35pPo3zZiKRZPfTXJq8FKeRrbnYJ8zpBUJw2-05UZ9fucniO3Frh3VRMjyHxWZZP1Vpic6MzbtDkCYBvnC8LnNoipKczqLmQz7GuLjhIetD_dq_CkGFfdRjX5CDJzzZww3xZ84eXahzWABFjULE1UERLTjUCgIMIBdWu_5jXXrKGjz5gGCnse3rC6KSVNQlZXte5MbT67JxUqJSPv_HJl7wz0AS7BK3i5XYbHa6vdnpRrMLy2CVnjOtNhPXUMNhldgJOXcWZiE7AN74JTMLq0MLEzGTSYizy2lJGEuCs-QNpM7EZ1N4k8zN9v45C8gTWJjcuuiKi745e52AZsySvMli_tccFJlIt66UxgqYxLcf-WY7CGmTlemis2ZGkpetbuA5ES77krsS76P-MGNLUsrD5lQWLDl_veRdawcyEme96r8Q-TPu6F9XbjCxfXSwrBi5lqmYIXaQmBG6ao4gVXPE_cj3Xtx43zJvrS7MZh7IbFazAPn5gux2MvFn6GN0CL6SEGJ1lpJHqKli-RAvEPBRGExAXLmTKBSUj-pYn2NHqEtd2P1w5mY3PEvASOy7G427eIMl_o0evAo5toPe9240GODdIbBK6IuLUWfn52cn91efzhKUDhe9YymIukH8eFT_ZPMXIfUpzKLtBGgNx2GTgM-2YmK1kKjpAF4BNQF1ac_uEa2nNQfIp3T2yn3YOQ4_w67Ut3muXLPxDULFDHG3jRvkPGrYAMonFLe8MX_GO-8cS4m2VT4VzLu56ojcn48Le27m5HJORjdYIsT1Ini3PbB72GEonnJcXcZQBXbp9SKf9aYF85306_NpiI5aHoF4MB857orlYSejBVYVHblcq8aj-einvMdydY8H85FnzRzPFdf21lOZQRVQ-uC5wskhaFq2g7313Jk9c_gMJJ_gbTjiftJeyaN0A5knBSkMHN_uRmF-GGcgCmwl-n85FsKxfNT4FDxHBxwryEQLbb4cg2Zh8knFR6i5iawINT5nybVfcmpTMAXJAWWO-ePRAiOkZ7Q5-ifDBUEi8m_r2bP78cldTrgsgRUlDNjRb09GHEduT2b5fHJ7iucOCx5z5zsZzUd_gEUUrIXWUInXPKWIYFBtRwFjazsK7eWFxBy3XbyEmJ2HrUVOR4sCPzkmezOF-DDvzejirPHN2CJ9wzqYgwaF-XsGU-DeYeSegjHCAtcuSUqItT4PzLWrRCuuZGs1rUwxjs_k-lpRCMcgGwhBKb4sWOyVozQ7Mr_kzMETQM_ZjuDKNb2t9PTCgLn9UzzO2lJRPA2LJkAslex23Wp9PqXLVA_3002XODjCnU1yqtUJfdwR__S88Ve8Yqo2daIRjcqKamjx-6TTqiTdVVjxntpgeF84TMoVAb_gva4mVTWZapapy1Z86H0oNr9J5xef08ZvFPD4Zu9nziaeK16nW2-BlO6F47bfvDHbhtfh9EB6-HD18eGs1gpGPMDGAvi8BPL5Qe3Wnb5KrXHk8LCWHNQdSHc-l5QmVZry_N1J5IMiYS3ev_G-NBuhNaF4mz8dSLpcgx2EY_fAZXHkV89nA4D-3XKg1sKOJ5Cu3AHo06_9CtkwOPjBX6DqcX_6naXLt9-_IGMO-QH5_dcfRN4j-p9S6EnMcaT5Cq-WwMhN7fcf2h6R__wHNjN8zoC0dPY64bChA7NLuOBFjbGjUPuVmAlIZ_GBCV0kkDmQliB2QB0gNhUtP7E7r_1FUCahN75F4eJWS8wnJW5qKihB5T0F6QNG0lVfg4M9Adh6txFTEvh4j0VLpzPpGixDkHic5o3PKCgbIdSNEFo-BCgaw6T37kQjZ-6fsZALPtlutc9qHyC-EKDWcjHI7J7UwY5X2HVYn9dOYuc5kDB0auCVA_v1QMIvLxV86EQD8WE-w5b1-xqcz0m7lXGzMt5O6qvwxFRi-KvUH-JNu9iUmzN4wSyZT3B1uZYcDx1IF3vwPxMUxkJQkMTzJ8mtvO99kYMaEFdYg-Yvkl8p3BygwYQ8v4ks_wM9Kb3fJ8XZTBr43ljCoiG92OEIgt0OpDhzSPB04rmQEzGCMapwCvsAfhYTr1E9Gwex4pLQvKYY2aGl1q8UmzPRLRF9LNpUv3_1oiD0xtmYixtYgdSHeiT9YSp7lroQgLEmCbUIBLYd3v8-9vqp7rPEIvTsseSsJJS6XBK3LvtvjKgZxP80ppbjZZbP1ZTVunx-wxzWGzE7PSe69rxJ7ZLBRsydRVLSfKzF28vkE_irQmrZHecxmD25Tw2mRi9dqAa0qWeLQVwg5NVXhJSrGer6yDneg__ZcqItlZNZAm9QcP-sx4jd08xvUji1oSyneqL9uRlvqUDoWCGWakzWnnNE2lAa6gIyxfKiFSH_RTEUkyWVJFbsUrI2r1FQsidCC2GGWM3YAogEUQ0xsGAaUFrP01GC0rhAIGOsRaUplt7yZK69gIuitqAAigfokNrdYY6KnRFMfyBNvUh6GXFXPAiUHPj_T3FdAGFshDDX5gY8e89bEC4eyjteKNmAcdd9aF_j4jXu9CelAJcOYXz6MjNJHsoxd0Kp1Z0GASZ8Ea0SnePLm_BTlss0tOo06A5oEKnzwibLhPQdKKTvQKEqNI492DstE1AqELjksPNdmVtSRYQ1vvEmM6ybE20Hc0J2QEOtaJBd-eQugqwKDdFKq2T1tR5It_QfpbLIVSbowvGeebCNm6yPmrVeL4au-oAurovioLjBmJJ6jxtgKXmVZVVKhMp2IlvbqYpzxI2FOQJ5qw8rO8irytaqq5XNXSUQ2rhEom_NnJWV2zbGtcrG2L4u0a0pbC-Duq3h1JJpQtwLX0wTyasKaaKwuiiVVOlPpfiMb_eZU9vVeoHsRiO67RxXXsNtnZv03WiubS2IUjXlkW2NTXZQHNRdrdi03cyDvuUKavv10LZruB2ForKr1LAzQm_Z3MxRlAq22JVP7mgq3hwjJQue-CrNYsFLXq0reGsI4DeWFvHjNyXRxZekFvGTVxUK7rpQ2Fl5ozvIdLugQXal0M7S7iqhuG2W3qoVR6viUq3nDuzhyvXXKOCLX-KeXa0Vx7azb0H3-Mhz-txP0LjLx9PkS8bp7Voj-2dI1sFn_xJdiqQVoyz-CYc5GqGWupnZMpayQcDkD0V4jiMak1nVchHHs7-Uh98x5j7vd8RNV7wX3eHOICPzBl3T3JfCq6pmkWKU2dWyFMdUTDMXJbCHtnM7EPMNQorpngmXXgNI3ORwf_kPQv4HyM_3SA==

Screenshots

image
image

Paliak commented

Fixing this is somewhat tricky as none of the code currently responsible to handling creation of damage conversion tables uses skill,mainhand,offhand passes which means typical conditional mod application does not work here.

if skillModList:Sum("BASE", skillCfg, "PhysicalDamageGainAsRandom", "PhysicalDamageConvertToRandom", "PhysicalDamageGainAsColdOrLightning") > 0 then
skillFlags.randomPhys = true
local physMode = env.configInput.physMode or "AVERAGE"
for i, value in ipairs(skillModList:Tabulate("BASE", skillCfg, "PhysicalDamageGainAsRandom")) do
local mod = value.mod
local effVal = mod.value / 3
if physMode == "AVERAGE" then
skillModList:NewMod("PhysicalDamageGainAsFire", "BASE", effVal, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
skillModList:NewMod("PhysicalDamageGainAsCold", "BASE", effVal, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
skillModList:NewMod("PhysicalDamageGainAsLightning", "BASE", effVal, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
elseif physMode == "FIRE" then
skillModList:NewMod("PhysicalDamageGainAsFire", "BASE", mod.value, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
elseif physMode == "COLD" then
skillModList:NewMod("PhysicalDamageGainAsCold", "BASE", mod.value, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
elseif physMode == "LIGHTNING" then
skillModList:NewMod("PhysicalDamageGainAsLightning", "BASE", mod.value, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
end
end
for i, value in ipairs(skillModList:Tabulate("BASE", skillCfg, "PhysicalDamageConvertToRandom")) do
local mod = value.mod
local effVal = mod.value / 3
if physMode == "AVERAGE" then
skillModList:NewMod("PhysicalDamageConvertToFire", "BASE", effVal, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
skillModList:NewMod("PhysicalDamageConvertToCold", "BASE", effVal, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
skillModList:NewMod("PhysicalDamageConvertToLightning", "BASE", effVal, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
elseif physMode == "FIRE" then
skillModList:NewMod("PhysicalDamageConvertToFire", "BASE", mod.value, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
elseif physMode == "COLD" then
skillModList:NewMod("PhysicalDamageConvertToCold", "BASE", mod.value, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
elseif physMode == "LIGHTNING" then
skillModList:NewMod("PhysicalDamageConvertToLightning", "BASE", mod.value, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
end
end
for i, value in ipairs(skillModList:Tabulate("BASE", skillCfg, "PhysicalDamageGainAsColdOrLightning")) do
local mod = value.mod
local effVal = mod.value / 2
if physMode == "AVERAGE" or physMode == "FIRE" then
skillModList:NewMod("PhysicalDamageGainAsCold", "BASE", effVal, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
skillModList:NewMod("PhysicalDamageGainAsLightning", "BASE", effVal, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
elseif physMode == "COLD" then
skillModList:NewMod("PhysicalDamageGainAsCold", "BASE", mod.value, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
elseif physMode == "LIGHTNING" then
skillModList:NewMod("PhysicalDamageGainAsLightning", "BASE", mod.value, mod.source, mod.flags, mod.keywordFlags, unpack(mod))
end
end
end

activeSkill.conversionTable = wipeTable(activeSkill.conversionTable)
for damageTypeIndex = 1, 4 do
local damageType = dmgTypeList[damageTypeIndex]
local globalConv = wipeTable(tempTable1)
local skillConv = wipeTable(tempTable2)
local add = wipeTable(tempTable3)
local globalTotal, skillTotal = 0, 0
for otherTypeIndex = damageTypeIndex + 1, 5 do
-- For all possible destination types, check for global and skill conversions
otherType = dmgTypeList[otherTypeIndex]
globalConv[otherType] = m_max(skillModList:Sum("BASE", skillCfg, damageType.."DamageConvertTo"..otherType, isElemental[damageType] and "ElementalDamageConvertTo"..otherType or nil, damageType ~= "Chaos" and "NonChaosDamageConvertTo"..otherType or nil), 0)
globalTotal = globalTotal + globalConv[otherType]
skillConv[otherType] = m_max(skillModList:Sum("BASE", skillCfg, "Skill"..damageType.."DamageConvertTo"..otherType), 0)
skillTotal = skillTotal + skillConv[otherType]
add[otherType] = m_max(skillModList:Sum("BASE", skillCfg, damageType.."DamageGainAs"..otherType, isElemental[damageType] and "ElementalDamageGainAs"..otherType or nil, damageType ~= "Chaos" and "NonChaosDamageGainAs"..otherType or nil), 0)
end
if skillTotal > 100 then
-- Skill conversion exceeds 100%, scale it down and remove non-skill conversions
local factor = 100 / skillTotal
for type, val in pairs(skillConv) do
-- Over-conversion is fixed in 3.0, so I finally get to uncomment this line!
skillConv[type] = val * factor
end
for type, val in pairs(globalConv) do
globalConv[type] = 0
end
elseif globalTotal + skillTotal > 100 then
-- Conversion exceeds 100%, scale down non-skill conversions
local factor = (100 - skillTotal) / globalTotal
for type, val in pairs(globalConv) do
globalConv[type] = val * factor
end
globalTotal = globalTotal * factor
end
local dmgTable = { }
for type, val in pairs(globalConv) do
dmgTable[type] = (globalConv[type] + skillConv[type] + add[type]) / 100
end
dmgTable.mult = 1 - m_min((globalTotal + skillTotal) / 100, 1)
activeSkill.conversionTable[damageType] = dmgTable
end
activeSkill.conversionTable["Chaos"] = { mult = 1 }

It should be easy enough to restrict the mod to hit attack types only but that would cause the mod to apply to hits in general not just with main hand.