[Sugarcube] Adding new characters while game is running

Twine Version: 2.3.9
Story Format: Sugarcube

I’m currently working on a game where I’m generating a few different classes of things that the player can interact with - for example planets, locations and characters. I’m going to use characters as my example just for simplicity.

My previous version worked by having a set number of these at game load, i.e. generating five characters with names, personalities, looks etc. That version was Harlowe, so all of those were stored into a unique datamap for each - e.g. $character1, $character2.

I’m currently rebuilding the game and I’m working out the generation phase, getting it to work in Sugarcube. One of the things that would be extremely useful to be able to do is generate new characters as the game goes on. I’ve done a little bit of research and it feels like it’d be theoretically possible - my current though is maybe by creating a new Javascript game object called something like $character + a number from a variable such as a character number variable that gets +1 added to it each time a new character is generated.

I just wanted to check if this is the right path, whether its possible and whether anyone had any examples/knew of any resources that would help?

I also wanted to check - my current plan is to have this be a “create character” widget, with each character being its own javascript game object. Does this seem like the right path? I could also see arguments for having all of the characters contained within one game object.

I hope that all makes sense! I feel like I’d eventually figure something out, but I know from asking on here in the past people often have their own (usually much better than mine) solutions. Thanks in advance!

Creating variables on the fly is really easy. $bob in Twine script is the same as State.variables.bob in Javascript.

However, I think you may run into issues with this. If you set $bob manually in your script, you know that $bob exists and can easily reference the variable. But how do you reference $char2045 that was auto-generated?

What I would do is create an object list that holds characters, and then reference that instead of placing the characters directly into the global variable object with $. So like this:

<<set $chars = {}>>
<<set $char_id = 0>>

<<set $chars[$char_id] = {
	id: $char_id, 
	name: "Bob“
}>>
<<set $player = $char_id>>
<<set $char_id += 1>>

The player's name is <<=$chars[$player].name>>.

If you want to delete the character later, you can do:

<<run delete $chars[$player]>>

All of this code is untested, but should work.

Edit: After thinking about it harder, my original solution could have broken if you deleted a character because it would assign duplicate IDs. This should work better.

Probably the simplest way would be to have each character have its own character object (e.g. something like { name: "Anne", HP: 20, MP: 30 }), and then to either create an array of character objects (which would make listing and searching for data on them easier) or a generic object that contained the character objects (which would make finding individual characters easier).

For the array version you’d just have something like this in your StoryInit passage:

<<set $character = []>>

and then you could add characters by doing this:

<<set $character.push(_characterObject)>>

You would then access characters by their index in the array (e.g. $character[_characterIndex].propertyName).

For the generic object version you’d have something like this in your StoryInit passage:

<<set $character = {}>>

and then you could add characters by doing this:

<<set $character[_characterID] = _characterObject>>

You would then access characters by their character ID (e.g. $character[_characterID].propertyName). Each character would need a unique ID (if every character has a unique name, then you could use that as their character ID).

If there’s a possibility that characters would be deleted, then you’d probably want to use the generic object version, since deleting characters from the array would change the array indexes for any characters which followed the deleted one in the array.

Hope that helps! :grinning:

Thanks, this seems really useful. I agree about the referencing stuff bit - my current plan is to link the NPCs to factions and use that to reference stuff, but I need to do a bit of working it out. We’ll see, it might just be that I go for a large set list.

This was vaguely where I got to with the generic objects, but I got a bit of the syntax wrong! I’ve not had a chance to play around with this yet, but it’s very helpful! Thanks for the response.