Data storage for Quest system

Twine Version: 2.3.9
Sugarcube version: 2.32.1

I’m creating a twine game that uses a Quest system and a few day cycle passages.

Passage 1: Morning; Displays a short introduction line of you wake up etc. Then displays all possible actions: Walk around, interact and talk to…
Passage 2: Day; Displays the same but should directs you to a different passage (which is easy enough with a redirect passage I think)
Passage 3: Same as morning and day. Different passage with different style but functions the same.
Passage 4: Night, is used to handle codes and redirects the player into a short cutscene of sleeping and then wake up on Passage 1

Now for passage 1, 2 and 3 I also want to include a link to start or continue with a Quest. A Quest might be to build a home. Step one would be to gather supplies, step 2 is to create a place to build it. And in Step 3 you build the actual home.

For this I have created the following code inside the StoryInit passage

/*		Quests setup	/*
<<set $Quests to {
Active: [],
Completed: [],
Available: []
}>>

/*		Individual quest setup	/*
<<set $Quest1 to {
  name: "Quest 1",
  progress: [],
  deadline: 0,
  time: 0,
  short: "Start the Quest",
  passage: "C1Q1P1"
}>>

progress is being used as an array to keep track of progress. After completing step 1 I use:

<<set $Quest1.progress.pushUnique(1)>>

After step 2, the same happens with number 2. This helps create logic for when the Quest is supposed to be displayed in the day cycle passages.

Then after a few introductionairy passages I use the following code:

<<set $Quests.Active.pushUnique($Quest1)>>

To make Quest1 active and use:

<<for _i to 0; _i lt $Quests.Active.length; _i++>>
[[$Quests.Active[_i].short | $Quests.Active[_i].passage]]
<</for>>

This last piece of code is able to print out a link to every single ActiveQuest with the proper .passage information.

The problem I’m running into is that when I change the information of $Quest1.passage or $Quest1.name to something else,

	<<set $Quest1.passage to "C1Q1P2">>
	<<set $Quest1.short to "Create space">>

the information inside $Quests.active[0] does not update. And so when the player is send back to the passage of day the link created by the loop returns the player to the passage 1 because the array holds a copy of the data created in an earlier passage.

I read through other posts that this has something to do with the history of passages and the fact that the data is not static. Solutions are in the form of: Use setup object, reference by key and the use of Widget.

These solutions however do not achieve what I’m trying to do. I want to be able to start or initialize a new quest after another Quest has been completed. I want to create many different quests possibly having multiple active quests And I might want to display certain criteria to Quests like a timerestriction (complete within 5 days), or only being able to perform them during the morning passage. Or be able to wait 2 days before the quest is available again.

If anyone has a recommendation as to what I can do to achieve the desired outcome please let me know! I was so happy to have it working up until this point and I’m now fully frustrated that I’m unable to continue.

The problem is that variables are cloned on passage transition. This means that after a passage transition, $Quests.Active[0] is no longer a reference to $Quest1, but a new object. Modifying $Quest1 does not modify $Quests.active[0], and vice versa.

The way to get around this that would require fewest changes to you existing code would probably be to have the arrays inside $Quests simply contain the names of the quest variables instead, like this:

<<set $Quests.Active.pushUnique("Quest1")>>

Then you can use State.variables[$Quests.Active[_i]] to access the quest data, like this:

<<for _i to 0; _i lt $Quests.Active.length; _i++>>
[[State.variables[$Quests.Active[_i]].short | State.variables[$Quests.Active[_i]].passage]]
<</for>>

(That’s a little unwieldy. A more elegant way to do the same thing would be this.)

<<for _quest range $Quests.Active>>
[[State.variables[_quest].short | State.variables[_quest].passage]]
<</for>>

This works perfectly. Thank you so much for this!