Want Javascript objects to be copied as references

0 votes
asked May 13 by sketchy (250 points)
retagged May 13 by sketchy


I'm trying to write a game so that each character is an object variable. The objects get pushed into various location arrays so the game knows where the characters are, and their stats and inventory remain consistent.


<<set $ralph = {name: "Ralph", hp: 10, inventory:[]}>>
<<set $jane = {name: "Jane", hp: 10, inventory:[]}>>
<<set $player = {name: "Playername", hp: 10, inventory:["key", "sword"]}>>

<<set $village = []>>
<<set $village.push($ralph)>> /* ralph is placed in the village */

Then the player can interact with them, and there's a passage for each type of interaction. So I have a variable that holds a reference to the character's object:

<<set $currentCharacter to $ralph >>

Then in the Fight passage, $currentCharacter is used for the interaction, so that the passage can work on any character.

The problem is, the references aren't working as I understand they should be. In the above examples, from what I can tell, it's only a copy of $ralph that gets added to the village, and only a copy of $ralph is set as $currentCharacter. This means that only the copy gets changed, and the original $ralph remains unchanged.

What I mean is probably best expressed by this story file that demonstrates what I'm trying to do and you can see how it fails (try changing character's HPs and switching characters and you'll see what I mean).

download demo file here

If you have any idea how to get these to reference properly, I'd really appreciate it. 

2 Answers

+2 votes
answered May 13 by greyelf (83,430 points)
selected May 13 by sketchy
Best answer

Please use the Question Tags to state the name and full version number of the Story Format you are using, as answers can vary based on that information. I was forced to download your linked file to determine that you are using SugarCube v2.21.0

The Passage Transition process clones the current state of all know variables, the original copy is passed to the History system and the cloned copy is made available to the passage being shown, thus allowing the ability to Undo. The cloning process breaks object references that point to the same object, each of those reference ends up pointing to their own unique copy of the original object.

The best way to get around this issue is to store the original objects in a collection of some type (Elements of an Array, Properties of a Generic Object, etc) and to assign the index / key to the 2nd (or more) reference instead.

<<set $npcs to {
	"Ralph"		: {name: "Ralph", hp: 10, inventory:[]},
	"Jane"		: {name: "Jane", hp: 10, inventory:[]}

<<set $player = {name: "Playername", hp: 10, inventory:["key", "sword"]}>>

<<set $village = []>>
<<set $village.push("Ralph")>>	/% ralph is placed in the village %/

Ralph's HP: <<= $npcs["Ralph"].hp>>

First Village's HP: <<= $npcs[$village[0]].hp>>


commented May 13 by sketchy (250 points)
Thank you, that seems like a good solution, and could be simpler than the way I wanted to do it anyway.

Also I learned two additional things from your code example, so thank for that as well.
0 votes
answered May 13 by Akjosch (6,240 points)

Your choices - if the references being kept intact is a hard requirement - are to either switch to a story format which doesn't do that (like Snowman) or rewrite how SugarCube deals with state changes, which is mostly contained in state.js - look up stateUnmarshal() and stateMarshal() there - and save.js.

commented May 13 by sketchy (250 points)
Both options seem a bit daunting for me, in particular the latter at my level. But thanks for the response!
Welcome to Twine Q&A, where you can ask questions and receive answers from other members of the community.

You can also find hints and information on Twine on the official wiki and the old forums archive.

See a spam question? Flag it instead of downvoting. A question flagged enough times will automatically be hidden while moderators review it.