PDA

View Full Version : 5E, manager_action_damage.lua, getReductionType() uses "last" value



celestian
March 11th, 2020, 16:58
I am not sure if this is intended but I ran across this working on something last night. The function getReductionType() returns a list of damage types with the associated modifier. So if it's "RESIST: 12 fire" it will note "fire" with a modifier of 12. If there are 2 entries with fire it'll pick whichever one is "last" in the node list. So if you have RESIST: 12 fire and another entry of RESIST: 20 cold,fire it could pick 12 or 20 depending on whichever node is last in the for loop.

This might not be an issue for 5E but I thought I would mention it. I would "think" the intent would be to use the highest modifier or maybe stack them? For my case I needed the highest (best) one.

Here is the code snippet with the highlighted section.



function getReductionType(rSource, rTarget, sEffectType)
local aEffects = EffectManager5E.getEffectsByType(rTarget, sEffectType, {}, rSource);

local aFinal = {};
for _,v in pairs(aEffects) do
local rReduction = {};

rReduction.mod = v.mod;
rReduction.aNegatives = {};
for _,vType in pairs(v.remainder) do
if #vType > 1 and ((vType:sub(1,1) == "!") or (vType:sub(1,1) == "~")) then
if StringManager.contains(DataCommon.dmgtypes, vType:sub(2)) then
table.insert(rReduction.aNegatives, vType:sub(2));
end
end
end

for _,vType in pairs(v.remainder) do
if vType ~= "untyped" and vType ~= "" and vType:sub(1,1) ~= "!" and vType:sub(1,1) ~= "~" then
if StringManager.contains(DataCommon.dmgtypes, vType) or vType == "all" then
aFinal[vType] = rReduction;
end
end
end
end

return aFinal;
end

Moon Wizard
March 11th, 2020, 22:54
Yeah, seems like it should be maximum of existing type. However, that doesn't handle the negatives situation, which makes it even more complex. (i.e. what if negated terms are different between two of same type and not the same.) In that case, the whole system would need to be rewritten. Going to leave for now, as I don't have time to rebuild for that level of flexibility.

Regards,
JPG

celestian
March 11th, 2020, 23:04
Yeah, seems like it should be maximum of existing type. However, that doesn't handle the negatives situation, which makes it even more complex. (i.e. what if negated terms are different between two of same type and not the same.) In that case, the whole system would need to be rewritten. Going to leave for now, as I don't have time to rebuild for that level of flexibility.

Regards,
JPG

Not sure if this is helpful but here is what I did which covers some of... maybe... what you mean... Assuming you mean negative number values because negative !magic I'm not sure would deal with "RESIST: 12 fire,!magic" if that is even a thing?

I've arrays with lists of effect tags that I store "get highest" type and "get lowest" (not additive) already and applied it here to grab values. I think in this case you'd always want the highest so if one is -1 and another is 3, you'd still want 3 so this should work if I understand your goal.



function getReductionType(rSource, rTarget, sEffectType)
local aEffects = EffectManager5E.getEffectsByType(rTarget, sEffectType, {}, rSource);
-- check sEffectType, does it need highest value
local bGetHighest = (StringManager.contains(DataCommonADND.basetypes, sEffectType));
-- check sEffectType, does it need lowtypes value
local bGetLowest = (StringManager.contains(DataCommonADND.lowtypes, sEffectType));

local aFinal = {};
local aBest = {};
for _,v in pairs(aEffects) do
local rReduction = {};

rReduction.mod = v.mod;
rReduction.aNegatives = {};
for _,vType in pairs(v.remainder) do
if #vType > 1 and ((vType:sub(1,1) == "!") or (vType:sub(1,1) == "~")) then
if StringManager.contains(DataCommon.dmgtypes, vType:sub(2)) then
table.insert(rReduction.aNegatives, vType:sub(2));
end
end
end

for _,vType in pairs(v.remainder) do
if vType ~= "untyped" and vType ~= "" and vType:sub(1,1) ~= "!" and vType:sub(1,1) ~= "~" then
if StringManager.contains(DataCommon.dmgtypes, vType) or vType == "all" then
-- need highest value
if bGetHighest then
if (not aBest[vType]) or (rReduction.mod > aBest[vType]) then
aBest[vType] = rReduction.mod;
aFinal[vType] = rReduction;
end
-- need lowtypes value
elseif bGetLowest then
if (not aBest[vType]) or (rReduction.mod < aBest[vType]) then
aBest[vType] = rReduction.mod;
aFinal[vType] = rReduction;
end
else
-- otherwise we just set it
aFinal[vType] = rReduction;
end
end
end
end
end

return aFinal;
end

Moon Wizard
March 12th, 2020, 01:06
This code also applies to physical damage types, so non-magical slashing weapon resistance would be "RESIST: # slashing,!magic". Your version doesn't address when aNegatives list differs. (And neither does the current code I wrote.) It works best with simple damage resistances; and one complex one. I get what you're saying in original post, but to do it right is even more complex.

JPG