Vam
February 21st, 2022, 15:20
I recently purchased @SilentRuin's Polymorph extension, and I love it. Unfortunately I also use @bmos's Aura Effect, and the two do not get along. I've spent a few hours this morning troubleshooting it, and while I don't have a fix I do have a workaround. I'll start with the workaround for anyone who wants to use these together, and then share my other findings in case either SilentRuin or bmos can see anything I can't for a proper fix.
The workaround is to install Aura Effect manually from the github repo and remove the load order from the xml definition. You can download the 1.8 ext file from https://github.com/bmos/FG-Aura-Effect/releases/tag/v1.8. Unzip it into a "FG-Aura-Effect" folder in your extensions folder. Use your favorite text editor to load the extension.xml file and remove the line: "<loadorder>999</loadorder>". This is on line 8 in version 1.8. Start / restart FG, enable both extensions, and at least from my testing you're good to go.
You can stop reading now unless you want to learn more about the problem.
The crash happens in manager_combat.lua from CoreRPG in this code:
for _,fCustomDelete in ipairs(aCustomDeleteCombatantEffectHandlers) do
if fCustomDelete(nodeEffectList.getParent()) then
return true;
end
end
The value for nodeEffectList changes while the loop is running. How? I have no idea. From my limited understanding of Lua this should not be possible.
I wanted to see if Aura Effect was doing anything funky. I found that if I commented out this line it didn't crash:
CombatManager.setCustomDeleteCombatantEffectHandle r(checkDeletedAuraEffects);
However if I commented out the entire contents of the checkDeletedAuraEffects function it still crashed. Again, that doesn't seem to make sense. I removed everything from the script other than the one line above in the onInit function, and an empty version of checkDeletedAuraEffects, and it STILL crashed. I deleted all the other files other than the one lua script and the xml definition. It still crashed. I removed everything not required from the XML and it worked! I restored the full version and removed a chunk at a time from the xml to find the loadorder workaround.
Next I looked at it from the other side. What could Polymorph be doing to cause this? I found a call to CombatManager.setCustomDeleteCombatantEffectHandle r and commented it out. It fixed the crash at the expense of functionality. I commented out the contents of the onEffectsChildDeleted function which was the handler added. It fixed the crash. Remember, when I did this in Aura Effect it did NOT fix the crash. Interesting. I got it narrowed down to a single line in the deleted handler:
NotifyHostPolymorphismActivated(nodeCT, true, nLastHP);
Removing this line fixes the crash, but it breaks the Polymorph extension. I think the next step would be to see if I can narrow down what happens in the OOB_MSGTYPE_POLYMORPHACTIVATED handler, but I didn't go any further with that.
Instead I went back to the CoreRPG code that is actually crashing. I added some debug statements to it:
function onDeleteCombatantEffectEvent(nodeEffectList)
Debug.console('start loop', nodeEffectList)
for _,fCustomDelete in ipairs(aCustomDeleteCombatantEffectHandlers) do
Debug.console('in loop', nodeEffectList)
if fCustomDelete(nodeEffectList.getParent()) then
return true;
end
end
Debug.console('end loop', nodeEffectList)
return false;
end
Aha, it is recursing and somehow this is blowing away the nodeEffectList value! Why? I don't know. But I think that if Polymorph could avoid this recursion it would *probably* solve the problem. Here's the logs from above when ending polymorph concentration:
[2/21/2022 9:37:55 AM] s'start loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'in loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'in loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'start loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'in loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'in loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'in loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'end loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'in loop' | userdata
[2/21/2022 9:37:55 AM] [ERROR] Handler error: [string "scripts/manager_combat.lua"]:100: attempt to index local 'nodeEffectList' (a userdata value)
I think that the change in load order fixes it because the loop then ends without using the corrupted value, so the recursion doesn't cause the crash.
I started trying to narrow things down in the OOB_MSGTYPE_POLYMORPHACTIVATED handler, but gave up. I think the PolymorphActivated function is causing the unwanted recursion somewhere. I also think there's something wonky in the Lua interpreter that's allowing the value in the first loop to be corrupted. Maybe someone with more extension / Lua experience will spot something I missed.
The workaround is to install Aura Effect manually from the github repo and remove the load order from the xml definition. You can download the 1.8 ext file from https://github.com/bmos/FG-Aura-Effect/releases/tag/v1.8. Unzip it into a "FG-Aura-Effect" folder in your extensions folder. Use your favorite text editor to load the extension.xml file and remove the line: "<loadorder>999</loadorder>". This is on line 8 in version 1.8. Start / restart FG, enable both extensions, and at least from my testing you're good to go.
You can stop reading now unless you want to learn more about the problem.
The crash happens in manager_combat.lua from CoreRPG in this code:
for _,fCustomDelete in ipairs(aCustomDeleteCombatantEffectHandlers) do
if fCustomDelete(nodeEffectList.getParent()) then
return true;
end
end
The value for nodeEffectList changes while the loop is running. How? I have no idea. From my limited understanding of Lua this should not be possible.
I wanted to see if Aura Effect was doing anything funky. I found that if I commented out this line it didn't crash:
CombatManager.setCustomDeleteCombatantEffectHandle r(checkDeletedAuraEffects);
However if I commented out the entire contents of the checkDeletedAuraEffects function it still crashed. Again, that doesn't seem to make sense. I removed everything from the script other than the one line above in the onInit function, and an empty version of checkDeletedAuraEffects, and it STILL crashed. I deleted all the other files other than the one lua script and the xml definition. It still crashed. I removed everything not required from the XML and it worked! I restored the full version and removed a chunk at a time from the xml to find the loadorder workaround.
Next I looked at it from the other side. What could Polymorph be doing to cause this? I found a call to CombatManager.setCustomDeleteCombatantEffectHandle r and commented it out. It fixed the crash at the expense of functionality. I commented out the contents of the onEffectsChildDeleted function which was the handler added. It fixed the crash. Remember, when I did this in Aura Effect it did NOT fix the crash. Interesting. I got it narrowed down to a single line in the deleted handler:
NotifyHostPolymorphismActivated(nodeCT, true, nLastHP);
Removing this line fixes the crash, but it breaks the Polymorph extension. I think the next step would be to see if I can narrow down what happens in the OOB_MSGTYPE_POLYMORPHACTIVATED handler, but I didn't go any further with that.
Instead I went back to the CoreRPG code that is actually crashing. I added some debug statements to it:
function onDeleteCombatantEffectEvent(nodeEffectList)
Debug.console('start loop', nodeEffectList)
for _,fCustomDelete in ipairs(aCustomDeleteCombatantEffectHandlers) do
Debug.console('in loop', nodeEffectList)
if fCustomDelete(nodeEffectList.getParent()) then
return true;
end
end
Debug.console('end loop', nodeEffectList)
return false;
end
Aha, it is recursing and somehow this is blowing away the nodeEffectList value! Why? I don't know. But I think that if Polymorph could avoid this recursion it would *probably* solve the problem. Here's the logs from above when ending polymorph concentration:
[2/21/2022 9:37:55 AM] s'start loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'in loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'in loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'start loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'in loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'in loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'in loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'end loop' | databasenode = { combattracker.list.id-00008.effects }
[2/21/2022 9:37:55 AM] s'in loop' | userdata
[2/21/2022 9:37:55 AM] [ERROR] Handler error: [string "scripts/manager_combat.lua"]:100: attempt to index local 'nodeEffectList' (a userdata value)
I think that the change in load order fixes it because the loop then ends without using the corrupted value, so the recursion doesn't cause the crash.
I started trying to narrow things down in the OOB_MSGTYPE_POLYMORPHACTIVATED handler, but gave up. I think the PolymorphActivated function is causing the unwanted recursion somewhere. I also think there's something wonky in the Lua interpreter that's allowing the value in the first loop to be corrupted. Maybe someone with more extension / Lua experience will spot something I missed.