0 votes
by (150 points)

Hello there, i'm making my first twine game using sugarcube, and i do have a few questions.

The first one is about the design of the shop, i want each trader to have different items, and different number of each item (choose randomly). So i used some lists and with a for I have access to each item of the list. But while everything work fine while your on the page, if you exit the shop and go back, you will realize that the new items you bought have disappeared.

After some checks it seems to be because with the for using [_i] the variable is not "saved". If you look at the before passage you will see that with a if statement for each item i did succefully overwrite the variable but it doesn't seems to be a good idea if I want to have like 10 or more items.

Thanks in advance.

Everything is not totally clear in my head  about the problem so i attached the code I'm using while having the issue.

start:

<<set $potion_hp_debut to {
"name": "potion de vie (grade inférieur)",
"description": "Une petite potion remontant de 100hp votre vie. ",
"hp": 100,
"mana":0,
"atk": 0,
"atkm": 0,
"def": 0,
"defm": 0,
"agi": 0,
"vit": 0,
"prix":50,
"nombre_joueur":5,
"nombre_shop":0,
}>>
<<set $potion_mp_debut to {
"name": "potion de mana (grade inférieur)",
"description": "Une petite potion remontant de 100mp votre mana. ",
"hp": 0,
"mana":100,
"atk": 0,
"atkm": 0,
"def": 0,
"defm": 0,
"agi": 0,
"vit": 0,
"prix":60,
"nombre_joueur":5,
"nombre_shop":0,
}>>

<<set $marchand_itinerant_1 to {
"name":"marchand itinérant Bob",
"or":200,
"marchandises_musthave":[$potion_hp_debut,$potion_mp_debut],
"marchandises":[$bouclier2,$epee2,$wand2,$arc2],
"nombre_must_have_min":2,
"nombre_must_have_max":10,
"nombre_item_min":1,
"nombre_item_max":2
}>>
<<set $marchand_actuel to $marchand_itinerant_1>>
[[before]]







before:

<<set $money_shop=$marchand_actuel.or>>
<<for _i = 0; _i < $marchand_actuel.marchandises_musthave.length; _i++>>
	<<capture _i>>
	<<set $marchand_actuel.marchandises_musthave[_i].nombre_shop to setup.nombre_item($marchand_actuel.nombre_must_have_min,$marchand_actuel.nombre_must_have_max)>>
	<<if $marchand_actuel.marchandises_musthave[_i].name == $potion_hp_debut.name>>
		<<set $potion_hp_debut.nombre_shop to $marchand_actuel.marchandises_musthave[_i].nombre_shop>>
	<</if>>
	<<if $marchand_actuel.marchandises_musthave[_i].name == $potion_mp_debut.name>>
		<<set $potion_mp_debut.nombre_shop to $marchand_actuel.marchandises_musthave[_i].nombre_shop>>
	<</if>>
	<</capture>>
<</for>>

<<set $items to $marchand_actuel.marchandises_musthave>>

[[continuer(temporaire)|store]]








store:

<strong>Bienvenue dans le magasin de $marchand_actuel.name . </strong>
Votre or: $money ¤
L'or restant du marchand: $marchand_actuel.or ¤

Vos objets:
<<for _j = 0; _j < $items.length; _j++>>
<<nobr>>
	<<if $items[_j].nombre_joueur >=1>>
		<<if  $money_shop>= Math.round(0.75*$items[_j].prix)>>
			<<capture _j>>
				$items[_j].name ( $items[_j].nombre_joueur) [[Sell|store][$items[_j].nombre_shop +=1,$items[_j].nombre_joueur -=1,$money+=Math.round(0.75*$items[_j].prix),$money_shop -=Math.round(0.75*$items[_j].prix) ]]
			<</capture>>
		<<else>>
			$items[_j].name ( $items[_j].nombre_joueur)| Le marchand n'a pas assez d'assez d'argent pour l'acheter.
		<</if>>
	<</if>>
<</nobr>>
<</for>>

Objets du marchand:

<<for _i = 0; _i < $items.length; _i++>>
<<nobr>>
	<<if $items[_i].nombre_shop >0 >>
		<<if $items[_i].prix > $money>>
			$items[_i].name | Coût: $items[_i].prix ¤ |quantité restante: $items[_i].nombre_shop : <strong>Vous n'avez pas assez d'argent.</strong>
		<<else>>
			<<capture _i>>
			$items[_i].name | Coût: $items[_i].prix ¤ |quantité restante: $items[_i].nombre_shop : [[Buy|store][$items[_i].nombre_shop -=1,$items[_i].nombre_joueur +=1,$money-=$items[_i].prix,$money_shop+=$items[_i].prix ]]
			<</capture _i>>
		<</if>>
	<<else>>
		$items[_i].name | Coût: $items[_i].prix ¤ |quantité restante: $items[_i].nombre_shop : <strong>Rupture de stock.</strong>
	<</if>>
<</nobr>>
<</for>>

2 Answers

0 votes
by (144k points)
selected by
 
Best answer

Further to @HiEv's question.

> if you exit the shop and go back, you will realize that the new items you bought have disappeared.

Which story variable are you examining when you check for the recently purchased items?

1. $items
2. $marchand_actuel.marchandises_musthaveare
3. $marchand_itinerant_1.marchandises_musthaveare

because each of the above variables references a different copy of the original Array value.

Background:
Each time a Passage Transition occurs the History system makes a copy of the current value of all known story variables, the copy is made available to the Passage about to be shown, and the original is stored within the History system.

This means that by the time you first see your "store" Passage none of the above listed story variables are referencing the original [$potion_hp_debut, $potion_mp_debut] Array, and that each of those variables are referencing a different copy of that Array. Which means that any updates made to one of those variables are not reflected in the other two variables.

by (150 points)

Thanks for your answers,

@Hiev: well i dont use some special macro just a basic link to a new passage. In this new passage i print the value which show the number of items ( here the 2 potions) that the player have.

It is the $potion_hp_debut.nombre_joueur stat 

 

 

According to what you and greyelf say, it seems that when i checked the purshased items using the $potion_hp_debut variable i haven't realize the change i did in the temporary $marchand_actuel.marchandises_musthaveare do not change the original potion one.

 

This lead me to the question , how to change the original potion stats using the temporary variable ? ( what i did in the before passage with the if statement that check if the temporary name equals the original one to set the new original value work but is useless if i want to add new items)

<<capture _i>>
	<<set $marchand_actuel.marchandises_musthave[_i].nombre_shop to setup.nombre_item($marchand_actuel.nombre_must_have_min,$marchand_actuel.nombre_must_have_max)>>
	<<if $marchand_actuel.marchandises_musthave[_i].name == $potion_hp_debut.name>>
		<<set $potion_hp_debut.nombre_shop to $marchand_actuel.marchandises_musthave[_i].nombre_shop>>
	<</if>>
	<<if $marchand_actuel.marchandises_musthave[_i].name == $potion_mp_debut.name>>
		<<set $potion_mp_debut.nombre_shop to $marchand_actuel.marchandises_musthave[_i].nombre_shop>>
	<</if>>
	<</capture>>

 

by (144k points)

Generally I recommend defining your objects in a single location as key/value pairs, and then using those object's keys to reference the original objects as needed.
(all of the following examples contain untested code)

1. Define your objects using key/value pairs, and use the object's key to reference it later.

<<set $potions to {
	"hp-debut": {
		"name": "potion de vie (grade inférieur)",
		"description": "Une petite potion remontant de 100hp votre vie. ",
		"hp": 100,
		"mana": 0,
		"atk": 0,
		"atkm": 0,
		"def": 0,
		"defm": 0,
		"agi": 0,
		"vit": 0,
		"prix": 50,
		"nombre_joueur": 5,
		"nombre_shop": 0,
	},
	"mp-debut": {
		"name": "potion de mana (grade inférieur)",
		"description": "Une petite potion remontant de 100mp votre mana. ",
		"hp": 0,
		"mana": 100,
		"atk": 0,
		"atkm": 0,
		"def": 0,
		"defm": 0,
		"agi": 0,
		"vit": 0,
		"prix": 60,
		"nombre_joueur": 5,
		"nombre_shop": 0,
	}
	/* etc...*/
}>>

<<set $merchants to {
	"itinerant-1": {
		"name": "marchand itinérant Bob",
		"or": 200,
		/* assign potion keys */
		"marchandises_musthave": ["hp-debut", "mp-debut"],
		/* assign item keys */
		"marchandises": ["bouclier-2", "epee-2", "wand-2", "arc-2"],
		"nombre_must_have_min": 2,
		"nombre_must_have_max": 10,
		"nombre_item_min": 1,
		"nombre_item_max": 2
	}
}>>

2. Use the keys to lookup the orginal object definition as needed.

/* show a list of musthave potions for a specific merchant,
   using temporary variables within a passage.
*/
<<set _merchant to $merchants["itinerant-1"]>>
<<set _musthave to _merchant["marchandises_musthave"]>>

<<for _key range _musthave>>
	$potions[_key]["name"]
<</for>>

3. Use the key to update the original object definition.

<<set _key to _musthave[0]>>

<<set $potions[_key].nombre_shop += 1>>

notes:
1. you don't need to use as many temporary variables as my examples do, I am only using them to make it easier to see the referncing back to the original object definitions.

2. you may want define the 'potions' and other items within the same $items story variable.

3. If you have object definitions that don't change after they have first initialised then you make want to move then from story variables (which are stored in History & Saves) to the special setup object (which isn't)

by (150 points)

thanks for the code, it work perfectly fine, except the

$potions[_key]["name"]

which show nothing, so I is suppose you wanted to mean

$potions[_key].name

anyway the basic code work, I will try to change my "options" to buy/sell etc but i think it should be okay now. Thanks.

by (144k points)

note: I did indicate that the examples in my previous comment were untested.

> so I is suppose you wanted to mean

No, what I meant to write was the following looping code

<<for _key range _musthave>>
	<<= $potions[_key]["name"]>>
<</for>>

 

0 votes
by (36k points)
I don't see a link in the "store" passage to exit the "store" passage.  Where is the code which shows how you're doing that?

I ask, because if you're using something like the <<back>> macro, then that will undo any changes you did in that passage, the same as would happen if you hit the "back" arrow on the UI bar.

So, how does the player exit the "store" passage in your code?
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.
...