0 votes
asked by (200 points)

So I have tried several configurations but none of them function. Currently I am trying to use a link to make the change to the array, putting the first object into the last slot and shifting all of the items up. The point of this is to create an weapons inventory that allows the user to cycle through their weapons and have the game use the first slot for combat. I am using twine2 sugarcube2.

<<link "change weapon" >> <<set $weapons[0] to $move[0]>> <<script>>$weapons.delete(0)<</script>><<set $weapons[4] to $move[0]>>
					 <<replace "#inv1">> $weapons[0].name<</replace>>
					 <<replace "#inv2">> $weapons[1].name<</replace>>
					 <<replace "#inv3">> $weapons[2].name<</replace>>
					 <<replace "#inv4">> $weapons[3].name<</replace>> 
					 <<replace "#inv5">> $weapons[4].name<</replace>>
					  <</link>>

 

2 Answers

+1 vote
answered by (58.8k points)
edited by
 
Best answer

You have a few issues here:

  1. You cannot directly use story or temporary variables within the <<script>> macro as it only accepts pure JavaScript.  To directly use story or temporary variables you'd need something which accepts TwineScript, like <<run>>.
  2. You cannot use <Array>.delete() to delete by indices as it deletes by value.  To delete an array member(s) by indices you want <Array>.deleteAt().

There are multiple ways to accomplish your goal, however, the easiest thing to do would be to use <Array>.push() and <Array>.shift() to shift the first member off of the array and push it onto the end.

 

Here's an example which uses <<run>>:

<<link "change weapon">>
	<<run $weapons.push($weapons.shift())>>
	<<replace "#inv1">> $weapons[0].name<</replace>>
	<<replace "#inv2">> $weapons[1].name<</replace>>
	<<replace "#inv3">> $weapons[2].name<</replace>>
	<<replace "#inv4">> $weapons[3].name<</replace>>
	<<replace "#inv5">> $weapons[4].name<</replace>>
<</link>>

 

For bonus points, here's the same example but using <<script>>, just to show how you'd access story variables in JavaScript: (see: State.variables)

<<link "change weapon">>
	<<script>>
	var sv = State.variables;
	sv.weapons.push(sv.weapons.shift());
	<</script>>
	<<replace "#inv1">> $weapons[0].name<</replace>>
	<<replace "#inv2">> $weapons[1].name<</replace>>
	<<replace "#inv3">> $weapons[2].name<</replace>>
	<<replace "#inv4">> $weapons[3].name<</replace>>
	<<replace "#inv5">> $weapons[4].name<</replace>>
<</link>>

 

commented by (200 points)
Thanks that did the trick. I can safely run an if statement in between the replace macros and set the conditions to the length of the array right?
commented by (58.8k points)

If you mean so that you can have an array of varying length, then yes.  That said, there are better ways to accomplish the goal.

Here's an example using a <<for>> loop (range form shown) to handle an array of any length:

<<link "change weapon">>
	<<run $weapons.push($weapons.shift())>>
	<<for _i, _name range $weapons>>
		<<replace `"#inv" + (_i + 1)`>> _name<</replace>>
	<</for>>
<</link>>

NOTES: For each iteration of the array the temporary variables _i and _name are set to the array index and value, respectively.  The argument to <<replace>> uses a backquote expression to generate the selector (e.g. for index 0 it generates "#inv1").

+1 vote
answered by (20.6k points)
edited by

Instead of having them click multiple times to cycle through weapons, why not just have them click the one they want to make primary?

<<set $weapons = [ {name: "sword"}, {name: "axe"}, {name: "dagger"}, {name: "fist"}, {name: "rubber chicken"}]>>
Weapons:\
<<capture _i>><<for _i = 0; _i < $weapons.length; _i++>>\
<<set _inv = "inv" + (_i + 1)>>\
<span @id="_inv" title="Click to make this the primary weapon"> <<link $weapons[_i].name>>
	<<set _temp = $weapons[_i]>>
	<<set $weapons[_i] = $weapons[0]>>
	<<set $weapons[0] = _temp>>
	<<set _inv = "#inv" + (_i + 1)>>
	<<run $("#inv1 a").empty().wiki(" " + $weapons[0].name)>>
	<<run $(_inv + " a").empty().wiki(" " + $weapons[_i].name)>>
<</link>><<if _i == 0>> (primary)<</if>></span>\
<<if _i < $weapons.length - 1>> |<</if>>\
<</for>><</capture>>

That uses jQuery to replace the text of the link, using the span's ID to find the link.  Note that the <<capture>> macro is used to make sure that the variable _i has the correct value at the time the user clicks on it.

Hope that helps!  :-)

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.
...