PDA

View Full Version : Different behavior between module NPC and "local" NPC.



celestian
July 8th, 2017, 20:20
I've been debugging a issue that has been perplexing. I've a feeling this is related to modules somehow but can't wrap my head around a solution.

Right now when I add a weapon to a NPC that is LOCAL to the campaign everything works fine.

When I load a NPC from a module (NOT a read only module) and adjust it to have a weapon (adds feather to it in list at this point) the damagelist does not show properly until I close and reopen the NPC. Keep in mind the damagelist is actually there because I can execute a damage roll and it works. Any pre-existing weapons/damage in the module show/work fine except as noted below in "addHandler".

So, all that sounds kinda vague and confusing so here is some debug code that might help. This snippet of debug is from me dropping a weapon on the NPC and it being added and then the char_weapon.lua:onInit->onDataChanged() being run.



Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'nodeWeapon' | databasenode = { npc.id-00746.weaponlist.id-00003@2e Monsters }
Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'nodeChar' | databasenode = { npc.id-00746@2e Monsters }
Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'rActor' | { s'sType' = s'pc', s'sCreatureNode' = s'npc.id-00746@2e Monsters', s'sCTNode' = s'', s'sName' = s'Barghest' }
Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'aDamage' | { }
Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'aDamageNodes' | { }


As you can see there is no aDamageNodes, remember that for the next one.

For this bit of debug I just closed the above NPC and re-opened it and you can see those values missing above are no longer missing.



Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'nodeWeapon' | databasenode = { npc.id-00746.weaponlist.id-00003@2e Monsters }
Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'nodeChar' | databasenode = { npc.id-00746@2e Monsters }
Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'rActor' | { s'sType' = s'pc', s'sCreatureNode' = s'npc.id-00746@2e Monsters', s'sCTNode' = s'', s'sName' = s'Barghest' }
Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'aDamage' | { }
Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'aDamageNodes' | { #1 = databasenode = { npc.id-00746.weaponlist.id-00003.damagelist.id-00001@2e Monsters }, #2 = databasenode = { npc.id-00746.weaponlist.id-00003.damagelist.id-00002@2e Monsters } }
Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'aDice' | { #1 = s'd6' }
Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'sDamage1' | s'1d6 bludgeoning'
Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'sDamage2' | s'1d6 bludgeoning'
Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'aDice' | { #1 = s'd3' }
Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'sDamage1' | s'1d3 bludgeoning'
Runtime Notice: s'char_weapon.lua' | s'onDamageChanged' | s'sDamage2' | s'1d3 bludgeoning'



I've also noticed that the "addHandler" "onDataChanged" configuired in the onInit() for a node's weaponlist doesn't seem to trigger (even tho it's added it) on a module NPC at all. Normally when I edit a weapon's damage the damagestring is updated as I do it... it's not adjusted at all. When I do the same thing to a local NPC it works as expected.


DB.addHandler(node.getNodeName(), "onChildUpdate", onDataChanged);


Here is the function I'm getting the above debug for tho I don't think it'll be much help. I've bolded the section where the value is coming back different.


function onDamageChanged()
local nodeWeapon = getDatabaseNode();
local nodeChar = nodeWeapon.getChild("...")
local rActor = ActorManager.getActor("pc", nodeChar);

local sBaseAbility = "strength";
if type.getValue() == 1 then
sBaseAbility = "dexterity";
end

local aDamage = {};
local aDamageNodes = UtilityManager.getSortedTable(DB.getChildren(nodeW eapon, "damagelist"));
for _,v in ipairs(aDamageNodes) do
local nMod = DB.getValue(v, "bonus", 0);
local sAbility = DB.getValue(v, "stat", "");
if sAbility == "base" then
sAbility = sBaseAbility;
end
if sAbility ~= "" then
nMod = nMod + ActorManager2.getAbilityBonus(rActor, sAbility, "damageadj");
end

-- add in prof modifiers
nMod = nMod + getToDamageProfs(nodeWeapon);

local aDice = DB.getValue(v, "dice", {});
if #aDice > 0 or nMod ~= 0 then
local sDamage = StringManager.convertDiceToString(DB.getValue(v, "dice", {}), nMod);
local sType = DB.getValue(v, "type", "");
if sType ~= "" then
sDamage = sDamage .. " " .. sType;
end
-- do this to make splitting up damage rolls,
-- for small/medium and large type damage style of AD&D viable -celestian
DB.removeHandler(nodeWeapon.getNodeName(), "onChildUpdate", onDataChanged);
DB.setValue(v, "damageasstring","string",sDamage);
DB.addHandler(nodeWeapon.getNodeName(), "onChildUpdate", onDataChanged);
--

end
end
end



Is there some odd behavior in the way modules entries and local copies work? Is there a solution to where I can avoid having to have a local the NPC to get the right values?

celestian
July 9th, 2017, 00:51
I've poked around a bit more. When you tweak a NPC in a module it creates a moduledb/*.xml file with those changes there. So, I checked that file and sure enough the changes I made exist. Tho I am beginning to suspect access to that is different than normal?

Moon Wizard
July 9th, 2017, 01:18
Module data and campaign data are treated exactly the same. The only difference is when he module data is loaded/saved, not during runtime.

The onUpdate event will only fire when the data on a node is changed, not when it is added. You'll need to add an onAdd handler as well if you want that event.

Regards,
JPG

celestian
July 9th, 2017, 01:35
Module data and campaign data are treated exactly the same. The only difference is when he module data is loaded/saved, not during runtime.

The onUpdate event will only fire when the data on a node is changed, not when it is added. You'll need to add an onAdd handler as well if you want that event.


I did experiment with a onAdd but had no luck. I added the "onAdd" to the 'node.getNodeName()' which was in this case 'npc.id-02036.weaponlist.id-00007@2e Monsters' node.

I'm only confused as to why this doesn't work on NPCs from modules but does on the locals. Perhaps this image will explain better.

All I did was drag/drop the Aarakocra onto the npc list to make a copy, renamed to -local then added a club to local and module version. You can see the local has the dmg boxes filled but the npc from the module has empty boxes. Additionally I also opened the "edit" damage window and changed the type a bit and as you can see the local copy added TEST (as I typed it showed each letter) but on the module version it did nothing there as well.

https://i.imgur.com/uYBdvPr.png

celestian
July 11th, 2017, 05:06
So I've been tinkering with this some more and the more I play with it the more it seems to be specifically module objects. It seems to run the onInit but doesn't use handlers (onAdd or onChange). It also returns an empty value on a addition unless you close and reopen the object and then the change shows up.

This same object when local (local npc or CT) works 100%.

Per Trenlo's suggestion...



To make NPCs read only in a module, add static="true" to the XML tag that the NPCs are listed in. For example: <reference static="true">


I checked and it IS set to true but even when it set to false I have the same issue with module objects.

Honestly if this is just expected behavior from NPC modules I'm ok with it just want to rule out me not coding something right to deal with it.

Trenloe
July 11th, 2017, 05:11
I checked and it IS set to true but even when it set to false I have the same issue with module objects.
As an aside - if the record is correctly set to static, it shouldn't be letting you add anything to the record. Does the padlock in the top right of the NPC character sheet show red and you can't unlock it? If not, then static="true" is not being set or read correctly. Your screenshots in post #4 seem to suggest that the module NPC is editable.

celestian
July 11th, 2017, 05:18
As an aside - if the record is correctly set to static, it shouldn't be letting you add anything to the record. Does the padlock in the top right of the NPC character sheet show red and you can't unlock it? If not, then static="true" is not being set or read correctly. Your screenshots in post #4 seem to suggest that the module NPC is editable.

Yeap, my intent was the module shouldn't be set readonly. For what it's worth what happens when you tweak a object in a module it seems to create a moduledb/*.xml file with ONLY the changes in it. It doesn't actually edit the module file ...and puts a feather on the object marking it "changed" but you can right click and revert to original state.

To be clear I only mentioned your suggestion because I wanted to make sure it wasn't that ;) At this point I'm trying everything I can think of to see what happens.

This is where it was set btw, probably not the same you mentioned.


<library>
<id-2emonsters static="true">
<categoryname type="string">2e</categoryname>
<name type="string">2emonsters</name>
<entries>
<npc>
<librarylink type="windowreference">
<class>referenceindexsorted</class>
<recordname>lists.npc@2e Monsters</recordname>
</librarylink>
<name type="string">NPCs</name>
</npc>
</entries>
</id-2emonsters>
</library>

Moon Wizard
July 11th, 2017, 05:20
Are you making sure that the path you are watching has the module name at the end when you use the addHandler call in onInit?
You might take a look at some of the code in CoreRPG/3.5E/5E that looks something like this DB.addHandler(DB.getPath(<node>, "<fieldname>"), "onUpdate", <onFieldUpdate>);
If you are just appending the field name to the end of the node name, that will be a problem since the name/path of a node is <datapath>@<modulename>. If you append the field name, it would incorrectly be <datapath>@<modulename><fieldname>, which would always find nothing.

Regards,
JPG

Trenloe
July 11th, 2017, 05:22
To be clear I only mentioned your suggestion because I wanted to make sure it wasn't that ;) At this point I'm trying everything I can think of to see what happens.

This is where it was set btw, probably not the same you mentioned.


<library>
<id-2emonsters static="true">
<categoryname type="string">2e</categoryname>
<name type="string">2emonsters</name>
<entries>
<npc>
<librarylink type="windowreference">
<class>referenceindexsorted</class>
<recordname>lists.npc@2e Monsters</recordname>
</librarylink>
<name type="string">NPCs</name>
</npc>
</entries>
</id-2emonsters>
</library>

Yeah, it's not set at the right point. It needs to be set in the hierarchy where the actual NPC data is, not the link to the NPC lists. Good to know that read-only appears to be working OK - as you shouldn't be able to make any changes to a read-only NPC module record. But, as your record wasn't actually read only, that's OK that FG allowed you to make changes.

celestian
July 11th, 2017, 05:31
Are you making sure that the path you are watching has the module name at the end when you use the addHandler call in onInit?
You might take a look at some of the code in CoreRPG/3.5E/5E that looks something like this DB.addHandler(DB.getPath(<node>, "<fieldname>"), "onUpdate", <onFieldUpdate>);
If you are just appending the field name to the end of the node name, that will be a problem since the name/path of a node is <datapath>@<modulename>. If you append the field name, it would incorrectly be <datapath>@<modulename><fieldname>, which would always find nothing.

Regards,
JPG

I believe I do. Here is the onInit debug



Runtime Notice: s'char_weapon.lua' | s'onInit' | s'node.getNodeName()' | s'npc.id-02036.weaponlist.id-00005@2e Monsters'


I then


DB.addHandler(node.getNodeName(), "onChildUpdate", onDataChanged);
DB.addHandler(node.getNodeName(), "onAdd", onDataChanged);


Is that what you're referring to?

npc.id-02036.weaponlist.id-00005 is the specific weapon record for the npc and @2e Monsters is the module it's in.

npc.id-02036.weaponlist.id-00005 is located in the Fantasy Grounds\Data\campaigns\AD&D 5Core Test\moduledb\2e Monsters.xml file in an NPC entry something like this.



<id-02036>
<encumbrance>
<load type="number">9</load>
</encumbrance>
<inventorylist>
<id-00001>
<carried type="number">2</carried>
<cost type="string">0 cp</cost>
<count type="number">1</count>
<damage type="string">1d6 bludgeoning; 1d3 bludgeoning, large</damage>
<description type="formattedtext">
<p></p>
</description>
<isidentified type="number">1</isidentified>
<locked type="number">1</locked>
<name type="string">Club</name>
<nonid_name type="string">Club</nonid_name>
<speedfactor type="number">4</speedfactor>
<type type="string">Weapon</type>
<weight type="number">3</weight>
</id-00001>
</inventorylist>
<temp>
<item type="deleted" />
<item type="deleted" />
</temp>
<category name="2e Monsters" baseicon="0" decalicon="0">
<weaponlist>
<id-00005>
<carried type="number">1</carried>
<damagelist>
<id-00001>
<damageasstring type="string">1d6 bludgeoning</damageasstring>
<dice type="dice">d6</dice>
<stat type="string">base</stat>
<type type="string">bludgeoning</type>
</id-00001>
<id-00002>
<damageasstring type="string">1d3 bludgeoning</damageasstring>
<dice type="dice">d3</dice>
<type type="string">bludgeoning</type>
</id-00002>
</damagelist>
<isidentified type="number">1</isidentified>
<name type="string">Club</name>
<shortcut type="windowreference">
<class>item</class>
<recordname>....inventorylist.id-00001</recordname>
</shortcut>
<speedfactor type="number">4</speedfactor>
</id-00005>
<category name="2e Monsters" baseicon="0" decalicon="0">
</category>
</weaponlist>
</category>
</id-02036>

Moon Wizard
July 11th, 2017, 06:02
If you can package together the ruleset and module in a place I can get to, as well as the steps to reproduce a specific test case (including how it should work vs. how it's working now), and send it to me at [email protected]; I can try and dig in and see what the issue is. Sorry if I'm asking for a lot, but debugging other people's rulesets is complex and takes a while.

Thanks,
JPG

celestian
July 11th, 2017, 08:03
If you can package together the ruleset and module in a place I can get to, as well as the steps to reproduce a specific test case (including how it should work vs. how it's working now), and send it to me at [email protected]; I can try and dig in and see what the issue is. Sorry if I'm asking for a lot, but debugging other people's rulesets is complex and takes a while.

Thanks,
JPG

Completely understand and appreciate your time. I'll pack it up and send an email.

celestian
July 13th, 2017, 00:20
So, with the help of Moon Wizard this has been resolved. The new 3.3.2 patch plus tweaks to the ruleset (deeper level addHandler's due to the way FG handles modules) make it work as expected!

Thanks a lot Moon!