Skip to main content

On Sale: GamesAssetsToolsTabletopComics
Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Twee: A Bridge from Twine to Decker

A topic by Internet Janitor created 15 days ago Views: 402 Replies: 11
Viewing posts 1 to 7
Developer(+7)

I just completed a first pass at a utility module that's been on my mind for quite a while: a library for working with Twine's .twee story file format from within Decker:

http://beyondloom.com/decker/twee.html

The "twee" module is a more robust and general version of the code previously seen in this prototype. In addition to being able to parse and emit .twee files, it can handle Twine's HTML Output Format, it can render a simple RText-oriented story format called "Ply", and it comes packaged with a self-contained contraption for playing Ply-based stories within a deck:

Finally, there's a simple Ply Story Format available for use with Twine itself:


http://beyondloom.com/decker/ply/format.js

I hope that these will provide some interesting possibilities for using these tools in concert!

(1 edit) (+2)

I'm very curious to see what people do with this one. 馃憖

(+3)

Mind. Blown. I have to try this.

(+3)

Oh, this is interesting. I'll definitely mess around as soon as I have the time.

(+5)

there鈥檚 no way you said you wouldn鈥檛 work on this until next year and dropped it like five days later lmao

Developer(+3)

There's some other stuff I intended to work on first, but, well, once the idea started rattling around in my head...

(+3)

no complaints, thank you so much! i'm about to take a short break from work to dig in :D

(1 edit) (+2)

i'm trying it out and i have a question: i didn't really understand how eval[] works within the module (it's listed in the lil fragments card). i thought i could use it to run code bits contained in a given field widget (or manipulate widgets like ! does in dialogizer), but... haven't really been able to do anything.

other than this, i'm loving it!

Developer(+2)

By default, Lil fragments in a Ply passage execute in an isolated scope that only has access to variables defined among passages and the variables I explicitly note in the documentation, which means no references to the widgets on the current card, the deck, etc. This is an important default, because otherwise it would not be possible to run these scripts in the stripped down "standalone" environment of the Twine Story Format where no surrounding deck exists.

You can get around this in several ways if you want to; for example you could modify the "Twine Player" example and install references to deck parts, functions, or anything else you want via the third "vars" argument to twee.render[]; you just have to explicitly opt into the things you want, and once you start doing this your stories will no longer work in Twine or the plyPlayer contraption:

# instead of this...
r:twee.render[story.value there vars.data]
# ...you could do this...
v:vars.data
v.deck :deck
v.print:print
v.pi   :pi
r:twee.render[story.value there v]

It's not a great idea to put function-calls with side effects in here, since all the fragments of a passage will be re-executed every time you revisit or refresh the passage. Beware!

From an "outside-in" perspective you could also naturally have other controls and scripts in the deck tweak or consult the flags this example stashes in the "vars" field.

Another way of making stuff happen in response to the player's actions is to add logic to the "link[]" event for the field where the rtext is rendered. In the "Twine Player" example there's some code that consults the current passage's "tags" and alters the "show" and "align" properties of the field:

# bonus: tag-based formatting cues:
p:(story.value.name dict rows story.value)[there]
output.show:if "inverted" in p.tags "invert" else "solid" end
output.align:if "center" in p.tags "center" elseif "right" in p.tags "right" else "left" end

You could have any sort of logic you want consulting the name, tags, or metadata of the just-visited passage.

If you use the plyPlayer contraption you're more limited, but it still offers a user-interceptable event if you edit the script of the contraption instance. The built-in example updates the "location" label to reflect the current passage name:

on passage name body tags meta do
 location.text:name
end
(+2)

perfect, that's what i was trying to do! i was aiming to plan the story entirely on twine and then add decker magic to it. the perfect combination! thanks a lot :)

(+3)

twee is the future of decker. this is looking too cool

(+3)

This is amazing!!! As a person who only knows Twine and (a tiny bit of) Decker, thank you so much for this.