5E Product Walkthrough Playlist
Page 1 of 2 12 Last
  1. #1
    Varsuuk's Avatar
    Join Date
    Dec 2015
    Location
    New York
    Posts
    2,075

    getChildren / getChildrenGlobal

    I was trying to collect various subsides which had 1..n attack types and when getChildren returned it was always 0 elements via #operator.

    Spent a long time trying several things until switched to getChildrenGlobal.
    That worked.

    So... when do you you one or the other?
    The odd thing to me is that even if I "copy" the node by dragging it from the MOD file it is listed in (monster manual) - it still returns 0. I checked the DB and after slight drag and creating second copy, it is in the campaign/db.xml file now as well as the mm.mod file.

    When switch to global, it returns a different value than 0, ... 2 which I will read further to understand since I am retrieving it like:

    Code:
    function onAttacksChanged(nodeRecord)
      local aAttacks = DB.getChildrenGlobal(nodeRecord, "attacks");
    ...
    
    
    The xml:
    
    		<attacks>
    			<bite>
    				<name type="string">Bite</name>
    				<damage type="string">1d6</damage>
    				<numberOfAttacks>1</numberOfAttacks>
    			</bite>
    		</attacks>
    Naively at first, I expected a return of 1, 1 child node of attacks. If it counted it deeper, then 4. But I recall something in docs having to do with children nodes and numbering. Will look there tomorrow.

  2. #2
    Trenloe's Avatar
    Join Date
    May 2011
    Location
    Colorado, USA
    Posts
    33,362
    As the API document mentions for getChildrenGlobal: “... any children of that path will be compiled across the campaign database as well as all loaded module databases.”

    To check why getChildren was returning 0 records put some debug in the code to output the exact node being used: https://www.fantasygrounds.com/refdo...cp#getNodeName and make sure your code is executing against the node you think it’s executing against.
    Private Messages: My inbox is forever filling up with PMs. Please don't send me PMs unless they are actually private/personal messages. General FG questions should be asked in the forums - don't be afraid, the FG community don't bite and you're giving everyone the chance to respond and learn!

  3. #3
    Varsuuk's Avatar
    Join Date
    Dec 2015
    Location
    New York
    Posts
    2,075
    XML -> in a loaded MODULE:
    Code:
    	<giantbatvampirebat>
    		<id type="string">giantbatvampirebat</id>
    		<nameknown type="string">Giant Bat (Vampire Bat)</nameknown>
    		<name type="string">Bat, Giant (Vampire Bat)</name>
    		<nameunidentified type="string">Giant Bat</nameunidentified>
    		<isidentified type="number">1</isidentified> <!--  TODO SHOULD this always be identified? Should this field be included in module? -->
    		<hitdice type="string">1</hitdice>
    		<hitpoints>
    			<totaldamage type="number">0</totaldamage>
    			<realdamage type="number">0</realdamage>
    			<subdualdamage type="number">0</subdualdamage>
    			<total type="number">0</total>
    		</hitpoints>	
    		<defenses>
    			<ac type="number">8</ac>
    			<acasc type="number">11</acasc>
    		</defenses>
    		<attacks>
    			<bite>
    				<name type="string">Bite</name>
    				<damage type="string">1d6</damage>
    				<numberOfAttacks>1</numberOfAttacks>
    			</bite>
    		</attacks>
    		<savingthrow type="number">17</savingthrow>
    		<special type="String">Sucks blood</special>
    		<weaponlist>
                    ...

    The code (ran first with getChildren(), then getChildrenGlobal() )

    Code:
    function onAttacksChanged(nodeRecord)
      Debug.console("onAttacksChanged", nodeRecord.getNodeName(), nodeRecord);
      local aAttacks = DB.getChildrenGlobal(nodeRecord, "attacks");
      local nTypesOfAttacks = #aAttacks;
      Debug.console("onAttacksChanged", nodeRecord, nTypesOfAttacks);
      local sAttacks = "";
      
      
      for idx,attack in ipairs(aAttacks) do
      ...



    With getChildren:
    Code:
    Runtime Notice: Reloading ruleset
    Runtime Notice: s'onAttacksChanged' | s'monster.giantbatvampirebat@Swords & Wizardry Complete - Monsters' | databasenode = { monster.giantbatvampirebat@Swords & Wizardry Complete - Monsters }
    Runtime Notice: s'onAttacksChanged' | databasenode = { monster.giantbatvampirebat@Swords & Wizardry Complete - Monsters } | #0

    With getChildrenGlobal:
    Code:
    Runtime Notice: Reloading ruleset
    Runtime Notice: s'onAttacksChanged' | s'monster.giantbatvampirebat@Swords & Wizardry Complete - Monsters' | databasenode = { monster.giantbatvampirebat@Swords & Wizardry Complete - Monsters }
    Runtime Notice: s'onAttacksChanged' | databasenode = { monster.giantbatvampirebat@Swords & Wizardry Complete - Monsters } | #2

  4. #4
    Trenloe's Avatar
    Join Date
    May 2011
    Location
    Colorado, USA
    Posts
    33,362
    Ah, so the node is within a module, not the campaign database.

    We'd need MW to confirm if DB.getChildren only works against the campaign database.

    As a work around, try <databasenode>.getChildren - you'll need another step to get the "attacks" node, but see if that works.
    Private Messages: My inbox is forever filling up with PMs. Please don't send me PMs unless they are actually private/personal messages. General FG questions should be asked in the forums - don't be afraid, the FG community don't bite and you're giving everyone the chance to respond and learn!

  5. #5
    Varsuuk's Avatar
    Join Date
    Dec 2015
    Location
    New York
    Posts
    2,075
    I will do that - just got on train and finally had moment to try what I was thinking of since hitting "post" - I was wondering why it returned 2 vs 1 for the global version.

    Well, why not print in loop what the node is?
    I did.

    Odd:


    Runtime Notice: Reloading ruleset
    Runtime Notice: s'acchanged-self' | windowinstance = { class = monster_combat, node = monster.giantbatvampirebat@Swords & Wizardry Complete - Monsters, x,y,w,h = 97,326,435,483 }
    Runtime Notice: s'ac_ascending_text' | nil
    Runtime Notice: s'onAttacksChanged' | s'monster.giantbatvampirebat@Swords & Wizardry Complete - Monsters' | databasenode = { monster.giantbatvampirebat@Swords & Wizardry Complete - Monsters }
    Runtime Notice: s'onAttacksChanged' | databasenode = { monster.giantbatvampirebat@Swords & Wizardry Complete - Monsters } | #2
    Runtime Notice: s'--' | #1 | databasenode = { monster.giantbatvampirebat.attacks.bite@Swords & Wizardry Complete - Monsters }
    Runtime Notice: s'--' | #2 | databasenode = { monster.giantbatvampirebat.attacks.numberattacks_t ext@Swords & Wizardry Complete - Monsters }

    But while it was an "aha!" moment (and I realize I cannot place the text version under Attacks because it ruins my other logic...) but now I am on a mad search for WHERE it is finding the field. I've looked at both db.xml and not seeing "number attacks_text" but now that know the problem will find it.

    --- Well, the problem of why count was 2 not 1. Not about the global. I read that and thought it too - global includes modules opened and other is only for local campaign - but when "copied" bat by dragging I verified it is in the campaign xml but not finding it either - still 0.


    The troublesome "attacks.numberattacks_text" is at the end, I forgot I added it there - didn't original post entire method because hadn't tested and wanted to avoid posting embarrassingly wrong code still haven't tested it but figure now that see the error was from later on in function - should give full info
    Code:
    function onAttacksChanged(nodeRecord)
      Debug.console("onAttacksChanged", nodeRecord.getNodeName(), nodeRecord);
      local aAttacks = DB.getChildrenGlobal(nodeRecord, "attacks");
      local nTypesOfAttacks = #aAttacks;
      Debug.console("onAttacksChanged", nodeRecord, nTypesOfAttacks);
      local sAttacks = "";
      
      
      for idx,attack in ipairs(aAttacks) do
      Debug.console("--", idx, attack);
        local nNumberOfAttacks = DB.getValue(attack, "numberOfAttacks", 1);
        
        if nNumberOfAttacks == 1 then
          sAttacks = tostring(nNumberOfAttacks) .. DB.getValue(attack, "name");
        else      
          sAttacks = tostring(nNumberOfAttacks) .. 
            Plural.lookup(DB.getValue(attack, "name"));
        end
        
        sAttacks = sAttacks .. " (" .. DB.getValue(attack, "damage") .. ")";
        
        if idx ~= nTypesOfAttacks then
          sAttacks = sAttacks .. ", ";
        end
      end
      
      DB.setValue(nodeRecord, "attacks.numberattacks_text", "string", sAttacks);
    end


    *** UPDATE ***
    Verified with grep on dev directory, no where outside of xml control name and the lua script where it is set, do I find "numberattacks_text"

    Loading the db.xml file from Windows into Mac's BBEdit, I see no numberattacks_text either in the "copied" bat (I did /save as well to be sure):


    From campaign/db.xml:
    Code:
    ...
    			</abilitynoteslist>
    			<aligment type="string">Neutrality</aligment>
    			<attacks>
    				<bite>
    					<damage type="string">1d6</damage>
    					<name type="string">Bite</name>
    					<numberOfAttacks>
    					</numberOfAttacks>
    				</bite>
    			</attacks>
    			<challengelevel type="number">3</challengelevel>
    ...
    Last edited by Varsuuk; January 23rd, 2020 at 13:56. Reason: Added investigation results

  6. #6
    Trenloe's Avatar
    Join Date
    May 2011
    Location
    Colorado, USA
    Posts
    33,362
    What's in db.xml only reflects what is in the database when the file is saved - it doesn't represent what is in memory at any particular point. Your debug shows that when the debug ran there was a numberattacks_text node, and you have LUA code that sets a value in that node.
    Private Messages: My inbox is forever filling up with PMs. Please don't send me PMs unless they are actually private/personal messages. General FG questions should be asked in the forums - don't be afraid, the FG community don't bite and you're giving everyone the chance to respond and learn!

  7. #7
    Quote Originally Posted by Varsuuk View Post

    DB.setValue(nodeRecord, "attacks.numberattacks_text", "string", sAttacks);
    I'm curious... is this part of the code run when viewing an NPC?

    I ask because I ran into an issue doing something similar and caused me some headache. The problem was if this is run on any NPC when you view them (including modules loaded) after they are viewed they will then be flagged as "changed" (if they are from a module) because the node "numberattacks_text" is changed anytime they are viewed.

    You might consider instead of using a node, use a label and then update to "numberattacks_text_label.setValue(sAttacks)".
    ---
    Fantasy Grounds AD&D Reference Bundle, AD&D Adventure Bundle 1, AD&D Adventure Bundle 2
    Documentation for AD&D 2E ruleset.
    Custom Maps (I2, S4, T1-4, Barrowmaze,Lost City of Barakus)
    Note: Please do not message me directly on this site, post in the forums or ping me in FG's discord.

  8. #8
    Varsuuk's Avatar
    Join Date
    Dec 2015
    Location
    New York
    Posts
    2,075
    (*** I wrote this shortly after Trenloe's reply - but got to work and only now on commute back am I back on laptop ***)
    Yeah, I got that. That's why I THOUGHT typing /save on FG chat would make memory reflect it.

    Plus, I do /reload before every run, so in theory it is reading campaign/db.xml into men each time? And the code to count the entries is before the first time I set the entries.


    Another fly in ointment of sanity:
    Code:
    Runtime Notice: Reloading ruleset
    Runtime Notice: s'nACAsc' | #11
    Runtime Notice: s'onAttacksChanged' | s'monster.giantbatvampirebat@Swords & Wizardry Complete - Monsters' | databasenode = { monster.giantbatvampirebat@Swords & Wizardry Complete - Monsters }
    Runtime Notice: s'onAttacksChanged' | databasenode = { monster.giantbatvampirebat@Swords & Wizardry Complete - Monsters } | #0
    Running with get children() not Global(), it looks like refers to the module? in the first ands the local in the second... separated by only a couple lines. Putting a pin in that for now...


    ========

    Celestian, you are correct, and I will try that - remember that my desire always here was to avoid a field - but I did not get syntax right to use a control. So, I will try a "label" type vs the string controls I started on. Will update.

  9. #9
    Varsuuk's Avatar
    Join Date
    Dec 2015
    Location
    New York
    Posts
    2,075
    Deleted the campaign.
    Started new (diff name)
    Opened PHB/MM mods.
    Opened Npcs
    Dragged the only defined creature to create local copy.
    Opened the local (never having opened the module one)

    I saw the following (same code generating from above)

    Code:
    Runtime Notice: s'nACAsc' | #11
    Runtime Notice: s'onAttacksChanged' | s'monster.id-00001' | databasenode = { monster.id-00001 }
    Runtime Notice: s'onAttacksChanged' | databasenode = { monster.id-00001 } | #0
    So this time, local naming as expected. But no "Attacks" found.

    Now I hit /save in chat.

    After reviewing, I noticed what didn't on commute in, numberofattacks was ill formed. In module forgot when added to place type="number", so it copied incorrectly. Fixed but not out of woods yet, still #0:

    Code:
    			<attacks>
    				<bite>
    					<damage type="string">1d6</damage>
    					<name type="string">Bite</name>
    					<numberOfAttacks type="number">1</numberOfAttacks>
    				</bite>
    			</attacks>

    Trasin rivning gotta go

    Runtime Notice: Host session started
    Runtime Notice: s'nACAsc' | #11
    Runtime Notice: s'onAttacksChanged' | s'monster.id-00001' | databasenode = { monster.id-00001 }
    Runtime Notice: s'onAttacksChanged' | databasenode = { monster.id-00001 } | #0

  10. #10
    Trenloe's Avatar
    Join Date
    May 2011
    Location
    Colorado, USA
    Posts
    33,362
    Oh, I think the issue is that the table of children is not integer indexed, so # (and ipairs) won't actually work.

    In your debug, output the complete aAttacks lua table to the console, not #aAttacks.
    Private Messages: My inbox is forever filling up with PMs. Please don't send me PMs unless they are actually private/personal messages. General FG questions should be asked in the forums - don't be afraid, the FG community don't bite and you're giving everyone the chance to respond and learn!

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
DICE PACKS BUNDLE

Log in

Log in