Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sugarcube FAQ

By FAQ, I mean FAQTIA. Frequently asked questions that I ask.

1 - How does one 'install Sugarcube' for their game?

2 - Will it have any unpleasant side effects for my currently-made project?

3 - I'm told there is a saving feature and I'd really love to implement that in my game. Is that true? If so, how do I implement it?

4 - Not related to Sugarcube: How can I implement macros in my game? I read somewhere that some guy got his game to play music in the background during a passage.

5 - What can Sugarcube do that the default layouts can't?

Keep in mind I have no idea what Sugarcube is, just that it's a layout that does a lot of nice stuff.
«1

Comments

  • Jinx wrote:

    1 - How does one 'install Sugarcube' for their game?

    In your Twine installation, in the "target" directory, create a subdirectory named "sugarcube". In that subdirectory, place the SugarCube "header.html" file.

    Jinx wrote:

    2 - Will it have any unpleasant side effects for my currently-made project?

    Installing it will not affect any of the other story formats. Projects will continue to use the same story format as before unless you manually switch them.

    If you switch your project to use SugarCube instead of the story format it was using originally, there are some differences you should look out for. They are mentioned in the SugarCube documentation. Among others, make sure your variables are initialized before you use them, the current state in JavaScript is named differently and a few CSS selectors are different.

    Jinx wrote:

    3 - I'm told there is a saving feature and I'd really love to implement that in my game. Is that true? If so, how do I implement it?

    I don't know if you'd love it, but I certainly do  ;)
    All you have to do is select SugarCube as the story format for your game, then you automatically get the save feature.

    Jinx wrote:

    4 - Not related to Sugarcube: How can I implement macros in my game? I read somewhere that some guy got his game to play music in the background during a passage.

    Macros are added by fragments of JavaScript. There are some ready-made macros that people like to use, for example from Leon's blog.

    Jinx wrote:

    5 - What can Sugarcube do that the default layouts can't?

    The save feature that you already mentioned. Random number generation that is consistent across back/forward and saves. Defining widgets, which is like a simpler version of macros (less powerful but also a lot easier to create). It also has some useful macros and JavaScript functions built-in, see the documentation for details.

    Jinx wrote:

    Keep in mind I have no idea what Sugarcube is, just that it's a layout that does a lot of nice stuff.

    It looks a lot like SugarCane, but it has more features.
  • I just implemented Sugarcube and a lot is messed up now.

    The code I used:
    <<textinput "$name" "cac2" "Enter">>

    What I got in the game:
    [IMG]http://i.imgur.com/YtOU8Cd.png[/img]

    ~

    Stats menu, hitting back should return you to the previous passage.
    The code I used:
    [[Back|previous()]]

    What I got in the game:
    [IMG]http://i.imgur.com/AmKp6cG.png[/img]
    Then...
    [IMG]http://i.imgur.com/cihTJ3W.png[/img]



    EDIT: Found out what I was doing wrong with the textinput. Instead of...

    <<textinput "$name" "cac2" "Enter">>

    It needs to be...

    <<textbox "$name" " " "cac2">>
  • Jinx wrote:

    EDIT: Found out what I was doing wrong with the textinput. Instead of...

    <<textinput "$name" "cac2" "Enter">>

    It needs to be...

    <<textbox "$name" " " "cac2">>


    I wouldn't use a space as the default argument, unless that's actually what you want.  You can simply use the empty string:
    <<textbox "$name" "" "cac2">>
    Additionally, if you also wanted an "Enter" button (which you don't need, &lt;&lt;textbox&gt;&gt; updates live and supports the Enter/Return key), you could add one like this:
    <<textbox "$name" "" "cac2">> <<button "Enter" "cac2">><</button>>
    There's also a non-built-in version of the &lt;&lt;textbox&gt;&gt; macro on SugarCube's website, under Extras, which includes a button argument, but simply using the &lt;&lt;button&gt;&gt; macro (as shown above) works just as well.


    Jinx wrote:

    Stats menu, hitting back should return you to the previous passage.
    The code I used:
    [[Back|previous()]]


    Use the &lt;&lt;back&gt;&gt; or &lt;&lt;return&gt;&gt; macros.  They're functionally equivalent except in how they modify the history.
    • &lt;&lt;back&gt;&gt;: Goes back by popping the history stack, essentially undoing the popped state(s).  It's like using your browser's Back button.
    • &lt;&lt;return&gt;&gt;: Goes back by pushing the destination state onto the history stack.  It's like following a link to the destination state.
    In this case, IIRC, the equivalent to [[Back|previous()]] would be:
    <<return "Back">>
    Simply using &lt;&lt;return&gt;&gt; would make the link text "Return".

    Alternatively, if you wanted most/all of your &lt;&lt;return&gt;&gt; calls to have the same non-default link text, you could do this in your StoryInit special passage:
    <<return::linktext "Back">>
    Then simply using &lt;&lt;return&gt;&gt; would make the link text "Back".

    That said, if you're using this on some kind of statistics display passage and that passage doesn't modify the game state at all (i.e. it's only to display the stats), then you may be better off using the &lt;&lt;back&gt;&gt; macro instead.
  • You're all angels. I love you all.

    One last question, once again unrelated to Sugarcube. Macros - I've seen people paste a macro that allows YouTube videos to play in the background, usually music.

    Can anyone provide a step-by-step tutorial on how to implement such a thing? It would really bring about a great atmosphere to my game.
  • The following three comments (two from Sharpe and one from lectronice) should help you with the sound.

    1. Contains two links to articles (with code) on how to do sound. (local file and youtube)
    http://twinery.org/forum/index.php/topic,1586.msg3436.html#msg3436

    2. Contains simple steps explaining the local file type in point 1.
    http://twinery.org/forum/index.php/topic,1586.msg3455.html#msg3455

    3. Simple change required to make code in point 1 compatible with SugarCube.
    http://twinery.org/forum/index.php/topic,1593.msg3541.html#msg3541

    Searching Forum is your friend. lol
  • greyelf wrote:

    The following three comments (two from Sharpe and one from lectronice) should help you with the sound.

    1. Contains two links to articles (with code) on how to do sound. (local file and youtube)
    http://twinery.org/forum/index.php/topic,1586.msg3436.html#msg3436

    2. Contains simple steps explaining the local file type in point 1.
    http://twinery.org/forum/index.php/topic,1586.msg3455.html#msg3455

    3. Simple change required to make code in point 1 compatible with SugarCube.
    http://twinery.org/forum/index.php/topic,1593.msg3541.html#msg3541

    Searching Forum is your friend. lol


    I asked for step-by-step but I can try to make sense of all these links...

    EDIT: Yeah these aren't clear directions. I'm getting errors.

    EDIT: I don't even know what a macro is, all I want is to play hidden YouTube videos in my game and I'm getting so much weird stuff and

    undefined
  • I've just installed Sugarcube and it looks pretty damn awesome.
    One question though: What should I do to insert a given macro/widget in every passage body?
    As I've read, Sugarcube is able to access any element on the page, but I not familiar with html, and css enough to figure out how...
  • Novbert wrote:

    One question though: What should I do to insert a given macro/widget in every passage body?
    As I've read, Sugarcube is able to access any element on the page, but I not familiar with html, and css enough to figure out how...


    I'm going to assume that you're not simply talking about how to call a macro/widget within a passage, but that there's some macro/midget you want called for every navigated to passage.  If that's the case, the obvious answer is to simply call the macro/widget within each passage, but I assume you'd rather avoid all that boilerplate.

    That leads me to some questions: Do you either simply want the macro/widget called or do you want it called and its output inserted somewhere into the passage?  Assuming the latter, where do you want the output inserted at?  First thing at the top, last thing at the bottom, or either somewhere in-between or in a variable location?  The first two could be done without a target element, though you could use one if you chose, the latter would require one.
  • TheMadExile wrote:

    That leads me to some questions: Do you either simply want the macro/widget called or do you want it called and its output inserted somewhere into the passage?  Assuming the latter, where do you want the output inserted at?  First thing at the top, last thing at the bottom, or either somewhere in-between or in a variable location?  The first two could be done without a target element, though you could use one if you chose, the latter would require one.


    Okay, to be more specific: I've read in this topic (http://twinery.org/forum/index.php?topic=763.0) a method to insert a new element on a page using the replace macro. My question is how the passage content itself can be modified using a similar approach.
    So let's assume I have these passages:
    :: StoryInit
    <<set $inventory to ["hat", "cane"]>>

    :: Start
    The sun shines on a comfy-looking park bench. No one is in sight.

    [[Stretch out on bench|Sleep]]

    :: Sleep
    You stretch out on the bench and take a well-deserved nap. You awake to find that some ruffian has swiped your cane!<<set $inventory[1] to "no cane">>

    :: Inventory display [widget]
    <<widget "inventory">>
    <<print "You are carrying: " + $inventory.toString()>><br>
    <</widget>>
    And I want the inventory widget to get included in every passage's body, before (or after) the passage content. I.e. I want passages to get displayed as if they would look like this:
    :: Start
    <<inventory>>
    The sun shines on a comfy-looking park bench. No one is in sight.

    [[Stretch out on bench|Sleep]]

    :: Sleep
    <<inventory>>
    You stretch out on the bench and take a well-deserved nap. You awake to find that some ruffian has swiped your cane!<<set $inventory[1] to "no cane">>
    but without manually inserting the inventory widget in every single passage's body. Can this be done in Sugarcube?

  • Novbert wrote:

    Can this be done in Sugarcube?


    Yes.

    Prepend the inventory (before):

    prerender["autoBoilerplate"] = function (content, task) {
    new Wikifier(content, "<<inventory>>");
    };
    Append the inventory (after):

    postrender["autoBoilerplate"] = function (content, task) {
    new Wikifier(content, "<<inventory>>");
    };
    Now, both of those will add the content to every normally rendered passage.  If you only want the &lt;&lt;inventory&gt;&gt; content added to some subset of those passages, then you'll need a little extra code.
  • Yay! Thanks a lot!
    Yes, I guess that might be necessary, but I guess that part can as well be handled within the widget itself by using some conditional parts for tags and whatnot.
    Thanks for the help again!
  • Okay, here's another one: Sugarcube doesn't seem to support the previous() function. Is this really the case or am I missing something? How can I get the previously visited passage's title in Sugarcube?
  • Novbert wrote:

    Yes, I guess that might be necessary, but I guess that part can as well be handled within the widget itself by using some conditional parts for tags and whatnot.


    Yes.  As a simple example, here's a prepend version which produces no output if the passage is tagged with hideinventory:

    <<widget "inventory">>\
    <<if tags().indexOf("hideinventory") === -1>>\
    <<print "You are carrying: " + $inventory.join(", ")>>

    <</if>>\
    <</widget>>
    I suppose I should also mention that, for what you're doing here, you could just as easily display an entire passage for your inventory instead of a widget.  For example:

    :: Inventory Boilerplate
    <<if tags().indexOf("hideinventory") === -1>>\
    <<print "You are carrying: " + $inventory.join(", ")>>

    <</if>>

    :: Inventory Boilerplate Scripting [script]
    prerender["autoBoilerplate"] = function (content, task) {
    new Wikifier(content, tale.get("Inventory Boilerplate").processText());
    };
    Six of one, half-a-dozen of the other.
  • Novbert wrote:

    Okay, here's another one: Sugarcube doesn't seem to support the previous() function. Is this really the case or am I missing something? How can I get the previously visited passage's title in Sugarcube?


    No, it doesn't currently, you aren't missing anything.  Why do you want the title of the previously visited passage (yes, the reason is important to my answer)?

    For instance, the primarily purpose of previous() in the vanilla headers is for use in constructs like [[Back|previous()]], which link back to the previously visited passage.  If you wanted it for a reason like that, then you probably don't need it, simply use &lt;&lt;return&gt;&gt; or its history undoing sibling &lt;&lt;back&gt;&gt; (which one would depend on how you want the link to work; the equivalent to [[Back|previous()]] is &lt;&lt;return &quot;Back&quot;&gt;&gt;).

    If you wanted it for some non-navigational reason, then you can get the title of the immediately previously visited passage like so: (assuming there is one!)

    // Safe, except on the initial passage (whatever it is), since there is no previous passage
    state.peek(1).title

    // Safe everywhere, though it will yield an empty string on the initial passage (whatever it is), since there is no previous passage
    (state.length > 1 ? state.peek(1).title : "")
    [EDIT] Updated the code.
  • Coolness! I'm currently still getting familiar with Twine in general and Sugarcube, but I thought it would be good to know in some cases where the player came from. E.g if some the passages represent phisical places, like "Street" and "Home", and I have some variables to store properties of these places (like "outside" or "inside") then I can alter the first few sentences of a given passage by looking up the properties/tags of the previous passage. I could write things like "You leave the kitchen and now you're in the hall" when the player moves "inside" the house but I can alter the sentence to "You leave the noise of the street behind and step into the main hall of the house" or "You finally arrrive home" if the player walks in from the outside.
    Thanks again for the quick answer! Keep it up, man!
  • Okay, I need this, but I am not java-skilled, so forgive me if I need it spelled out.

    You have been teleported temporarily to the treasure cave!  There's lots to do here!
    <<set $returnhere to {state.peek(1).title}>>

    // lots of other choices...

    Go back where you [[came from|$returnhere]]



    Like that?
  • Java and JavaScript are completely separate things with an unfortunate name similarity due to branding shenanigans.

    On to your question.  If "lots of other choices" means that the player will be navigating to an arbitrary number of other passages (e.g. via &lt;&lt;actions&gt;&gt;, links, or whatever), then yes you'd need something like that.  Though setting the return location is generally done on the passage you want to return to and not a later passage (e.g. [[Step into the portal|Treasure Cave][$returnLoc to passage()]]).  Maybe that's not possible with your setup though. /shrug

    As to your code.  It's almost correct, however, you have some spurious curly braces in there, it should look like:

    <<set $returnhere to state.peek(1).title>>
  • Okay, good, thank you.  The curly braces made it at least look important...

    I need to set where to return to because I'm hoping to have an inventory link in the sidebar, so there is no way to predict from where or when the player clicked it, thus I need to keep track of the Previous passage.  Similarly I have an item that lets someone teleport to a location, and I'd like to be able to replace them when they're done.

    My next question --

    Oh, hi everyone, by the way.  I didn't introduce.  I tend to lurk and then burst into full activity like the baby alien in John Hurt's chest.

    -- It was sort of asked earlier in the thread, and I don't know if this is a Sugarcube issue or Twine issue.  I want to have a game clock that can cause things to happen in the story.  Say if the count gets to six, the sun sets.  I have no problem running a silent passage in the StoryTitle or wherever, but I didn't think about how to get the text of what happens into the main window.  Is there a way to direct text from the sidebar to the main passage?

    This also applies to my inventory sidebar thing too...I'd like when the player clicks Inventory that they get a list of items in the main window that they can then interact with, and then return where they were by way of the state.peek trick above.
  • My god.  I don't know where you live, but I owe you at least a pizza or something.
  • Hanon wrote:

    I want to have a game clock that can cause things to happen in the story.  Say if the count gets to six, the sun sets.  I have no problem running a silent passage in the StoryTitle or wherever, but I didn't think about how to get the text of what happens into the main window.  Is there a way to direct text from the sidebar to the main passage?


    Firstly, please don't use StoryTitle.  SugarCube uses the story's title as the basis for the key used to store and load data used when playing the story and for saves. Because of this, the story title is not included in updates and it is strongly recommended that you do not add any kind of dynamic code to it.

    Secondly, don't use the other UI passages for this either, there are better passages for such work.  As I noted in another thread (likely the one you're thinking of), in SugarCube I'd suggest using PassageReady/PassageDone for such things (or the prerender/postrender task objects).

    And the answer is, yes, there are a multitude of ways to get content into the main passage container.  Where do you want this content to appear (yes, that's important)?  It can be prepended to the top, appended to the bottom, or injected into (or around) a selectable (probably, container) element that's part of the normal content.  The sky's virtually the limit here, so you need to narrow things down a bit.  Also, what are you wanting added?  Just some text or something more grandiose?


    Hanon wrote:

    This also applies to my inventory sidebar thing too...I'd like when the player clicks Inventory that they get a list of items in the main window that they can then interact with, and then return where they were by way of the state.peek trick above.


    If you're needing to return, then it's because you've navigated to another passage.  If that's the case, simply list your items in (and, importantly, from) that passage.  I'm not understanding the issue here.
  • Okay.  For inventory, I've managed to make a link appear on the left when the player picks up a sack.  My feeling is that I need to put all the possible inventory items (more passage links) in this passage and turn them on and off with variables.  Ideally clicking "inventory" on the side will replace the main window text with the inventory passage, and the player can futz around with stuff, then a "return" link remembers the passage the player started from and returns him there.   

    As far as the timer, my idea is that there's a general passage of code that increments the time, and then can also trigger things based on the time, or based on other variables.  For example if the timer gets to "morning" I'd like to display a passage that says "The sun is rising" as part of the main window text...end or beginning...wherever seems the most appropriate.  If the player is wounded, (for example) this timing passage will also count how many turns the player has been bleeding and provide appropriate messages mentioning this.

    I don't know what PassageReady/Done really does...I'm guessing PassageReady does things before displaying the text and PassageDone does things after displaying the text?  Is there  way I can put my time-management stuff in PassageReady and then have the main text displayed, and then PassageDone add remarks like "You've been bleeding a while, by the way, you might want to find a bandage."  ...or something.
  • Hi Hanon,

    Let me explain how I do this inventory-time thingy and maybe you can use it also (or propose a better solution).
    The basic concept is that I mark passage types with tags. A passage can be an entrance of an area (tagged:area) leading to multiple rooms, it can be a room (tagged: room) within that area, it can be an object's description (tagged:object) or anyhting else. I have a variable called $current to track the status of all those types so the setup is something like this:

    ::StoryInit
    <<set $current to {
    scene: "Opening Scene",
    area: "Home",
    room: "Living Room",
    object: "",
    }>>

    ::PassageReady
    <<if tags().indexOf("area") gt -1>>
    <<set $current["area"] to passage()>>
    <</if>>

    <<if tags().indexOf("room") gt -1>>
    <<set $current["room"] to passage()>>
    <</if>>

    <<if tags().indexOf("object") gt -1>>
    <<set $current["object"] to passage()>>
    <</if>>

    <<if tags().indexOf("scene") gt -1>>
    <<set $current["scene"] to passage()>>
    <</if>>

    ::Living Room (tag:room)
    /%some description%/
    Now every time the player goes to a passage tagged with
    room
    , the $current.room variable gets updated. Knowing this I can define a passage called Inventory or Menu and put this link at the end of it:
    [[Back|$current.room]]
    it will always lead the player back to the latest room passage he was in.

    You can also insert your timer logic in PassageReady and update the time every on every passage transition. When combining this with the prerender-postrender stuff TheMadExile described earlier, you can have a setup like:
    ::PassageReady
    <<updatetime>>

    ::updatetime (tag:widget)
    <<widget>>
    <<if (some condition)>>
    <<set $time to "morning>>
    <<endif>>
    <</widget>>

    ::Prerenderscript (tag: script)
    Prerender["autoBoilerplate"] = function (content, task) {
    new Wikifier(content, "<<display "Timeofday">>");
    };

    ::Timeofday
    <<if $time is '"morning">>
    <<print "The sun is rising">>
    <<endif>>

    Yes, you're right about PassageReady doing stuff before rendering the passage and PassageDone after that, but note, that you can't insert text into the passage itself with them. You need the prerender-postrender trickery to do so.
  • Hanon wrote:

    I don't know what PassageReady/Done really does...I'm guessing PassageReady does things before displaying the text and PassageDone does things after displaying the text?


    Got it in one.

    [quote="SugarCube docs Reserved & Special Names Passage Names"]
    PassageReady: Used for pre-passage-rendering tasks, like redoing dynamic changes (happens just before the rendering of each passage).
    PassageDone: Used for post-passage-rendering tasks, like redoing dynamic changes (happens just after the rendering of each passage).


    They and the prerender/postrender task objects are similar in that they both allow you to do dynamic things around the display of a passage (by navigation, the &lt;&lt;display&gt;&gt; macro does not trigger these).  The main differences being:
    • PassageReady/PassageDone are passages, while prerender/postrender are JavaScript objects used as repositories of functions (which I generally refer to as tasks).
    • PassageReady/PassageDone are executed before/after the passage is rendered, while the functions within the prerender/postrender objects are called during passage render, just before/after the passage content is generated.
    The order of execution typically looks something like this:
    [list type=decimal]
    State history updated for the incoming passage
    PassageReady executed, if not rendering "offscreen"
    Incoming passage is rendered
    [list type=upper-alpha]
    prerender tasks called
    Incoming passage content generated
    postrender tasks called


    Transition from outgoing passage to incoming passage, if not rendering "offscreen"
    PassageDone executed, if not rendering "offscreen"
    Update the UI elements, if not rendering "offscreen"

    Now you know.  And knowing is half the wait, my '80s is showing.


    Hanon wrote:

    Is there  way I can put my time-management stuff in PassageReady and then have the main text displayed, and then PassageDone add remarks like "You've been bleeding a while, by the way, you might want to find a bandage."  ...or something.


    Yes, certainly.  You can use the DOM (Content) macros within PassageDone to prepend and/or append your dynamic content to the main passage container.  If needed, you can even add target elements into a passage's content, so that once it's rendered you'll have targets which you can select to inject content into arbitrary areas of the main content area, rather than simply prepending/appending to it.

    As a contrived example, to handle time of day and bleeding messages, you might do something like this in PassageDone:

    /% Handle bleeding messages. %/
    <<if $bleedCount neq 0>>
    <<prepend ".passage .content">><<print $bleedMessages[$bleedCount]>>

    <</prepend>>
    <</if>>

    /% Handle time of day messages. %/
    <<if $timeOfDay eq "sunrise">>
    <<prepend ".passage .content">>The morning sun has vanquished the horrible night.

    <</prepend>>
    <<elseif $timeOfDay eq "sundown">>
    <<prepend ".passage .content">>What a horrible night to have a curse!

    <</prepend>>
    <</if>>
    n.b. The content additions are ordered in the reverse of how they're displayed to the player, since all of the additions are prepends in the example.
  • Novbert wrote:

    You can also insert your timer logic in PassageReady and update the time every on every passage transition. When combining this with the prerender-postrender stuff TheMadExile described earlier, you can have a setup like:

    ::PassageReady
    <<updatetime>>

    ::updatetime (tag:widget)
    <<widget>>
    <<if (some condition)>>
    <<set $time to "morning>>
    <<endif>>
    <</widget>>

    ::Prerenderscript (tag: script)
    Prerender["autoBoilerplate"] = function (content, task) {
    new Wikifier(content, "<<display "Timeofday">>");
    };

    ::Timeofday
    <<if $time is '"morning">>
    <<print "The sun is rising">>
    <<endif>>


    You have a couple of issues with your examples there:

    1. This has the prerender object's name title-capped and you're nesting the same type of quotes:

    Prerender["autoBoilerplate"] = function (content, task) {
    new Wikifier(content, "<<display "Timeofday">>");
    };
    Don't do either of those.  Case is important, prerender should be in all lowercase, and don't nest the same type of quotes, at least not without encoding them.

    It should be something like this:

    prerender["autoBoilerplate"] = function (content, task) {
    new Wikifier(content, '<<display "Timeofday">>');
    };

    2. This has spurious single quote in the &lt;&lt;if&gt;&gt; and you don't need to &lt;&lt;print&gt;&gt; a plain string literal:

    <<if $time is '"morning">>
    <<print "The sun is rising">>
    <<endif>>
    It should be something like this:

    <<if $time is "morning">>
    The sun is rising
    <<endif>>
    Tip: Keep an eye on your whitespace usage, particularly line-breaks, as they are copied to the output (e.g. the above adds a line-break before "The sun is rising", which may be unwanted).


    Novbert wrote:

    Yes, you're right about PassageReady doing stuff before rendering the passage and PassageDone after that, but note, that you can't insert text into the passage itself with them. You need the prerender-postrender trickery to do so.


    That's not entirely accurate.  You are (essentially) correct about PassageReady, however, PassageDone most certainly can manipulate the main passage area and the content within.  It doesn't have a direct reference to the content container like prerender/postrender do, no, but you can easily select the main passage container element via the selector ".passage .content" (among many others) and go from there (with the DOM (Content) macros or JavaScript, with or without jQuery).  As shown in my previous reply to this thread.
  • Thank you both for the examples - I can learn much more easily from practical examples. 

    I'm a little lost on concepts like "boilerplate" and 'wikifier", so perhaps I'm reaching a bit too far out of my ability level to try and do any type of story this complicated in Twine/Sugarcube.  I will experiment with these more extensively and see if I can make sense of it.
  • Hanon wrote:

    I'm a little lost on concepts like "boilerplate" and 'wikifier", so perhaps I'm reaching a bit too far out of my ability level to try and do any type of story this complicated in Twine/Sugarcube.  I will experiment with these more extensively and see if I can make sense of it.


    boilerplate, n. : (computing) A standard set of text or program code incorporated into several places within a computer program or its output, either dynamically or manually.

    Your boilerplate is the common content which you want added to all of your standard passages (e.g. your bleeding and time of day code).


    wikifier : (in this context) The Wikifier is the engine at the heart of all of the current Twine 1.x headers, which are based on TiddlyWiki.  It's what turns the TiddlyWiki wiki text/markup into plain text output.


    Except for CK's recent experimental format Snowman, which is based on Markdown, and whose engine is a JavaScript-hosted Markdown processor.

    The current vanilla headers and SugarCube have made extensions to the base TiddlyWiki markup syntax.
  • Okay, I think I'm starting to figure this out, and this is really slick.

    ::StoryInit
    <<set $current to {
    scene: "Opening Scene",
    area: "Home",
    room: "Living Room",
    object: "",
    }>>

    What are you doing with the "object" tag?  I guess you could have several passages interacting with an object and pop back to it.  This also would work really great for in-hand or wielding objects.  You have to select the key before you get the option to open the door. 

    I got a bit confused - I think MadExile was helping Novbert with high-level concepts when Novbert was helping me with specifics.  When I try this I'll watch the capitalization as he's specified and hopefully I can insert the correct code.
  • Well, the object tag can be used for context sensitive menus. What I was experimenting with is creating a footer wich displays after every passage (using that postrender trickery), and shows available actions. Now if the current passage is tagged with "room", this context sensitive footer can display neighbouring rooms. If it is tagged with "object", the menu can show stuff like "Use", "Pick", "Drop" (plus that "Back" button that takes the player back to the current room) etc. Of course if you want your menu to be static, the object tag is not necesary.
  • That's really neat, and I'd love to see if you get a game working like that!

    Another question, along the same lines.  Is there a way I can tag rooms to affect the player under certain conditions?

    For example, the player becomes a vampire and acquires a sensitivity to garlic with the $garlicallergy = true flag.  If I have an area of my game in a garlic bread factory, I would like his health to decrease slowly when in this area.  I'd like the passages to work the same way, but for the player to get messages this is happening appended to the room description.  What's the sanest way to go about this?
  • I think any dinamic addition to passage text can be handled by using prerender. I mean in the rednered "header" passage you can put an if branch to get triggered when the passage has a specific tag. Something along these lines:
    ::Passageheader (it should be included in the prerender script)

    <<if $garlicallergy=true>>\
    <<if tags().indexOf("garlic") > -1>>\
    There is some garlic here! You've lost \
    <<set $hplost to -= either(1,2,3)>>\
    <<set $hp -= $hplost>>\
    <<print $hp>> health points. <br>
    <<endif>>
    <<endif>>
Sign In or Register to comment.