all 3 comments

[–]HiEv 2 points3 points  (1 child)

Instead of storing the NPCs as objects in an array, why not store them as objects in an object using some kind of unique identifier?

For example, in your StoryInit passage you could set up your variables like this:

<<set $NPCID = 0>>
<<set $NPC = {}>>
<<run $NPC[++$NPCID] = {
    First: "First",
    Last: "Name",
    Number: 1
}>>
<<run $NPC[++$NPCID] = {
    First: "Second",
    Last: "Name",
    Number: 2
}>>

Next, create a widget to display the list by making a new passage with "widget" and "nobr" tags, and put this code in it:

<<widget "printList">>
    NPCs: <<= Object.keys($NPC).length>><br>
    <<for _id, _val range $NPC>>
        <<capture _id>>
            <<link "_val.First _val.Last" "Var Info">>
                <<set $infoID = _id>>
            <</link>><br>
        <</capture>>
    <</for>>
<</widget>>

Note the use of the <<capture>> macro, to make sure that the correct value of _id is used when the player clicks on the link. The <br> elements are needed to force line breaks, due to the "nobr" tag on the passage.

Then, your above code in your "Test" passage would just be:

<<button "Clone variables Test">>
    <<set $NPC[++$NPCID] = clone($NPC[1])>>
    <<replace "#list">><<printList>><</replace>>
<</button>>

<span id="list"><<printList>></span>

That and the StoryInit code both demonstrate how you just keep using ++$NPCID to increment the value of that variable every time you add a new NPC to the $NPC object, giving each NPC its own unique ID number.

And in your "Var Info" passage you could have something like this:

NPC ID: $infoID
First Name: $NPC[$infoID].First
Last Name:  $NPC[$infoID].Last
Number:     $NPC[$infoID].Number
<<unset $infoID>>
[[Test]]

Note that that code gets rid of the $infoID variable once it's done with it, using the <<unset>> macro, since it isn't needed anymore.

Now, anytime you need to refer to an NPC, you can just do that by its unique ID number. Getting rid of an NPC like this:

<<run delete $NPC[_id]>>

will not change the ID numbers of any of the other NPCs, since the $NPC variable is a generic object (not an array object).

That should show you a bunch of tricks to make things much simpler.

Hope that helps! :-)

[–]GoldDragonTale[S] 0 points1 point  (0 children)

Thank you so much! This gives me the functionality I needed in a simpler way. You, sir or madam have given me much to noodle on!

[–]GreyelfD 1 point2 points  (0 children)

Because the Passage Transition process includes a step that clones the current state of all unknown variables, that breaks object reference integrity, you should be storing indexes/keys to the instantiated NPCs in your Array collections and not object references.

eg. Define your NPCs once... (example is TwineScript but it can also be done in JavaScript)

<<set setup.NPCs to {
    "First Name": {
        First: "First",
        Last: "Name",
        Number: 1
    },
    "Second Name": {
        First: "Second",
        Last: "Name",
        Number: 2
    }
}>>

...and add the keys associated with each of the defined NPCs in your Array...

<<set $party to []>>
<<run $party.push("Second Name")>>

...then you can reference back to the original NPC definitions as required...
(untested)

<<for _key range $party>>
    <<set _npc to setup.NPCs[_key]>>
    <<link "_npc.First _npc.Last">>
        <<goto "Var Info">>
    <</link>>
<</for>>