Using variables in widgets in Sugarcube 2.0

Hi, I’m having a bit of trouble with one of my widgets because I increased the number of characters in my game and it’s tedious to update the widget, so I’m trying to make it more fast and easy to use.

In my game all the characters have the same base stats, and one of them is “Suspicion”. I want a widget that can alter the suspicion of any character by writing it’s name in the widget.

<<set $Martha={
           susp: 0,
}>>

That’s how my character stats are written, so the desireble variable to change in this example is called $Martha.susp.

My widget is written like this:

<<widget "Test">>
	<<if $args[0]>>
		<<set _number to $args[0]>>
	<<endif>>
	<<if $args[1]>>
		<<set _name to $args[1]>>
	<<endif>>
	<<if $args[2] eq "susp">>
		<<set $_name.susp+= _incrNPC>>
		<<if $_name.susp>=100>>
			<<set $_name.susp to 100>>
		<<endif>>
	<<endif>>
<</widget>>

<<Test 5 "Martha" "susp">>

The idea is that with this widget I can alter any variable from multiple characters. I have the same 6 stats in over 30 characters, so doing this one by one is tedious, so I hope you can help me.

Thank you for your help.

Please use the Preformatted text option when supplying code examples.
eg.

<<set $Martha to {
	susp: 0
}>>

You can use the State.variables object and Bracket Notation to access the current value of a story variable by Name.
eg. State.variables["Martha"] would access the same value as $Martha

You can use the same Bracket Notation to access the current value of an object property by Name.
eg. State.variables["Martha"]["susp"] would access the same value as $Martha.susp

You can use the <number>.clamp() function to limit a number to a set range.

So if your widget assigned the following temporary variables…

<<set _number to $args[0]>>
<<set _name to $args[1]>>
<<set _stat to $args[2]>>

…then the code to update the specified property on the specified object would be…

<<set State.variables[_name][_stat] to (State.variables[_name][_stat] + _number).clamp(0, 100)>>

It works like a charm, thank you so much.

Sorry I didn’t know how to format the code, I’ll take note.

I wanted to make it so that some variables have different levels. For example, the first level lets you have that variable from 0 to 100, but the second level lets you go from 100 to 200. I tried limiting it this way:

<<widget "NPCC">>
	<<set _number to $args[0]>>
	<<set _name to $args[1]>>
	<<set _stat to $args[2]>>
	<<if State.variables[_name][mainlvl] eq 0>>
			<<set State.variables[_name][_stat] to (State.variables[_name][_stat] + _number).clamp(0, 100)>>
	<<elseif State.variables[_name][mainlvl] eq 1>>
			<<set State.variables[_name][_stat] to (State.variables[_name][_stat] + _number).clamp(100, 200)>>
	<<endif>>
<</widget>>

The problem here is that Twine says that the variable “mainlvl” is not defined, and I defined it in the same passage as all the NPC ones.

Thank you for your help.

The problem is that you have mainlvl, instead of _mainlvl or $mainlvl.

Also, assuming the pattern continues, you could do your widget like this:

<<widget "NPCC">>
	<<set _number to $args[0]>>
	<<set _name to $args[1]>>
	<<set _stat to $args[2]>>
	<<set _range to State.variables[_name][$mainlvl] * 100>>
	<<set State.variables[_name][_stat] to (State.variables[_name][_stat] + _number).clamp(_range, _range + 100)>>
<</widget>>

That would give you a range of (level * 100) to (level * 100 + 100) for any number of levels. (Assuming that $mainlvl is the correct variable name.)

Hope that helps! :slight_smile:

The problem here is that every NPC has the variable $something.mainlvl (instead of “something” there goes their names) so what I was trying to do is that if you called the widget like this:

<<NPCC 5 "Martha" "suspicion">> so if you use this, the suspicion will increase 5 points until 100 if the $Martha.mainlvl is equal to 0. But if it’s 1 or more, it will have other limits.

The problem is that every NPC has this variable, the only thing that changes is the name, so what I wanted to do is for the widget to test the mainlvl of the name called previously, so that if I want to use, for example: <<NPCC 10 "Lyam" "suspicion">> I don’t have to make extra conditions in the widget.

I don’t really know if I explained myself correctly, it sounds gibberish to me, but it’s the closest I’ve been to explaining this problem. I’m also not a native english speaker, as you may have noticed, so I’ll try to explain it more carefully in the future.

Thank you a lot for your time.

Ah, so you probably want State.variables[_name].mainlvl.

To put it in brackets, you would need State.variables[_name]["mainlvl"] (a string). The way you have it, it’s trying to use the contents of a javascript variable called mainlvl as the name.

In general, I use the dot-notation if I know the exact name while writing the code, and the bracket notation if the name will change and I need the computer to compute it while the game is running. You also need the bracket notation if you’re using a name that isn’t a valid JavaScript name (if it has spaces or punctuation or something).

1 Like

You made my day extra happy, thanks a lot. It works just as you said. Also, thanks for the tip.