0 votes
by (160 points)

I've created the following series of <<set>> macros for a complex object in my code called $cardSequencer. It runs fine in a normal passage, but as soon as I put it into StoryInit, or put it in a widget, I get a mysterious Unexpected or Invalid token error inside a <<set>> macro (of course it won't tell me which one, since it's in a widget). It's super frustrating, because I'm literally copy-pasting the code from the passage to the widget, and then it suddenly doesn't work. 

The <<resetsequencer>> macro is made of the exact same code as shown right below it.

<<resetsequencer>>

<<set $cardSequencer.CurrentMethod to "">>
	<<set $cardSequencer.Interrupt to {
									active: false,
									previousMethod: {},
									card: "",
									script: "<<set $currentCard to $cardSequencer.Interrupt.card>><<set $cardSequencer.CurrentMethod to $cardSequencer.Interrupt.previousMethod.name>>"
									}>>
	<<set $cardSequencer.SingleCard to {
									name: "SingleCard",
									active: false, 
									card: "",
									script: "<<set $currentCard to $cardSequencer.SingleCard.card>>"
									}>>
	<<set $cardSequencer.DoubleCard to {
									name: "DoubleCard",
									active: false,
									firstCardPlayed: false,
									firstCard: "",
									secondCard: "",
									script: "<<if $cardSequencer.DoubleCard.firstCardPlayed is false>>
												<<set $currentCard to $cardSequencer.DoubleCard.firstCard>>
												<<set $cardSequencer.DoubleCard.firstCardPlayed to true>>
												<<set $cardSequencer.DoubleCard.active to true>>
												<<else>>
												<<set $currentCard to $cardSequencer.DoubleCard.secondCard>>
												<<set $cardSequencer.DoubleCard.firstCardPlayed to true>>
												<</if>>"
									}>>
	<<set $cardSequencer.TripleCard to {
									name: "TripleCard",
									active: false, 
									firstCardPlayed: false, 
									secondCardPlayed: false, 
									firstCard: "", 
									secondCard: "", 
									thirdCard: "",
									script: "<<if $cardSequencer.TripleCard.firstCardPlayed is false>>
												<<set $currentCard to $cardSequencer.TripleCard.firstCard>>
												<<set $cardSequencer.TripleCard.firstCardPlayed to true>>
												<<set $cardSequencer.TripleCard.active to true>>
												<<elseif $cardSequencer.TripleCard.secondCardPlayed is false>>
													<<set $currentCard to $cardSequencer.TripleCard.secondCard>>
													<<set $cardSequencer.TripleCard.secondCardPlayed to true>>
													<<set $cardSequencer.TripleCard.active to true>>
													<<else>>
														<<set $currentCard to $cardSequencer.TripleCard.thirdCard>>
														<<set $cardSequencer.TripleCard.firstCardPlayed to false>>
														<<set $cardSequencer.TripleCard.secondCardPlayed to false>>
														<</if>>"
									
									}>>

The error message:

Error: <<resetsequencer>>: errors within widget contents (Error: <<set>>: bad evaluation: Invalid or unexpected token; Error: <<set>>: bad evaluation: Invalid or unexpected token)

<<resetsequencer>>

The output then has 5 successfully executed <<set>> functions, just as expected

 

For reference, here's the exact widget code. Again, it's a copy-paste of the normal passage code.

<<widget "resetsequencer">>
	
	<<set $cardSequencer.CurrentMethod to "">>
	<<set $cardSequencer.Interrupt to {
									active: false,
									previousMethod: {},
									card: "",
									script: "<<set $currentCard to $cardSequencer.Interrupt.card>><<set $cardSequencer.CurrentMethod to $cardSequencer.Interrupt.previousMethod.name>>"
									}>>
	<<set $cardSequencer.SingleCard to {
									name: "SingleCard",
									active: false, 
									card: "",
									script: "<<set $currentCard to $cardSequencer.SingleCard.card>>"
									}>>
	<<set $cardSequencer.DoubleCard to {
									name: "DoubleCard",
									active: false,
									firstCardPlayed: false,
									firstCard: "",
									secondCard: "",
									script: "<<if $cardSequencer.DoubleCard.firstCardPlayed is false>>
												<<set $currentCard to $cardSequencer.DoubleCard.firstCard>>
												<<set $cardSequencer.DoubleCard.firstCardPlayed to true>>
												<<set $cardSequencer.DoubleCard.active to true>>
												<<else>>
												<<set $currentCard to $cardSequencer.DoubleCard.secondCard>>
												<<set $cardSequencer.DoubleCard.firstCardPlayed to true>>
												<</if>>"
									}>>
	<<set $cardSequencer.TripleCard to {
									name: "TripleCard",
									active: false, 
									firstCardPlayed: false, 
									secondCardPlayed: false, 
									firstCard: "", 
									secondCard: "", 
									thirdCard: "",
									script: "<<if $cardSequencer.TripleCard.firstCardPlayed is false>>
												<<set $currentCard to $cardSequencer.TripleCard.firstCard>>
												<<set $cardSequencer.TripleCard.firstCardPlayed to true>>
												<<set $cardSequencer.TripleCard.active to true>>
												<<elseif $cardSequencer.TripleCard.secondCardPlayed is false>>
													<<set $currentCard to $cardSequencer.TripleCard.secondCard>>
													<<set $cardSequencer.TripleCard.secondCardPlayed to true>>
													<<set $cardSequencer.TripleCard.active to true>>
													<<else>>
														<<set $currentCard to $cardSequencer.TripleCard.thirdCard>>
														<<set $cardSequencer.TripleCard.firstCardPlayed to false>>
														<<set $cardSequencer.TripleCard.secondCardPlayed to false>>
														<</if>>"
									
									}>>
	
<</widget>>

 

1 Answer

+1 vote
by (153k points)
selected by
 
Best answer

JavaScript String literals can't span multiple lines, like the ones you're assigning to the script property.

You will need to either:

a. Break then down into multiple sub-literals and concatenate them together.

<<set $cardSequencer.TripleCard to {
	name: "TripleCard",
	active: false, 
	firstCardPlayed: false, 
	secondCardPlayed: false, 
	firstCard: "", 
	secondCard: "", 
	thirdCard: "",
	script: "<<if $cardSequencer.TripleCard.firstCardPlayed is false>>" +
				"<<set $currentCard to $cardSequencer.TripleCard.firstCard>>" +
				"<<set $cardSequencer.TripleCard.firstCardPlayed to true>>" +
				"<<set $cardSequencer.TripleCard.active to true>>" +
			"<<elseif $cardSequencer.TripleCard.secondCardPlayed is false>>" +
				"<<set $currentCard to $cardSequencer.TripleCard.secondCard>>" +
				"<<set $cardSequencer.TripleCard.secondCardPlayed to true>>" +
				"<<set $cardSequencer.TripleCard.active to true>>" +
			"<<else>>" +
				"<<set $currentCard to $cardSequencer.TripleCard.thirdCard>>" +
				"<<set $cardSequencer.TripleCard.firstCardPlayed to false>>" +
				"<<set $cardSequencer.TripleCard.secondCardPlayed to false>>" +
			"<</if>>"
}>>


b. Store the script code within a Passage and reference that instead.

1. Create a new Passage (Triple Card Script) and paste the following into it.

<<if $cardSequencer.TripleCard.firstCardPlayed is false>>
	<<set $currentCard to $cardSequencer.TripleCard.firstCard>>
	<<set $cardSequencer.TripleCard.firstCardPlayed to true>>
	<<set $cardSequencer.TripleCard.active to true>>
<<elseif $cardSequencer.TripleCard.secondCardPlayed is false>>
	<<set $currentCard to $cardSequencer.TripleCard.secondCard>>
	<<set $cardSequencer.TripleCard.secondCardPlayed to true>>
	<<set $cardSequencer.TripleCard.active to true>>
<<else>>
	<<set $currentCard to $cardSequencer.TripleCard.thirdCard>>
	<<set $cardSequencer.TripleCard.firstCardPlayed to false>>
	<<set $cardSequencer.TripleCard.secondCardPlayed to false>>
<</if>>

2. Reference the new Passage in the script property

<<set $cardSequencer.TripleCard to {
    name: "TripleCard",
    active: false, 
    firstCardPlayed: false, 
    secondCardPlayed: false, 
    firstCard: "", 
    secondCard: "", 
    thirdCard: "",
    script: "Triple Card Script"
}>>

3. The retreve the contents of the new Passage at the point you were executing the old script code.

by (160 points)
Thanks greyelf!

I thought I had tried it with the whole literal on one line, but I must have had some error that I fixed later when I did that. The widget is working now. :)
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.
...