Howdy, Stranger!

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

Save game in Sugarcane? Derail: Sugarcube Questions, ReDerail: CSS Blunders

2»

Comments

  • It would subtract one from the same variable each time. It could be the same text, or a "display" passage if that would be possible. If this would be annoying to code I can totally do something different though, it wouldn't be a game breaker by any means. Just having robust saves is awesome!
  • mostly wrote:
    It would subtract one from the same variable each time.


    Easy-peasy.  Consider it done.


    mostly wrote:
    It could be the same text, or a "display" passage if that would be possible.


    I can set it up to display a $variable, a passage (like <<display>> would), or a passage referenced by a $variable.  You're choice.

    One last question, where should the text be inserted?  Since it's being injected into an existing page, it'll need a target.  Or were you thinking of replacing something with it (same basic question though)?
  • Thank you! Based on your reply, it sounds like I could do exactly what I wanted with the <<replacelink>>, but without using <<replacelink>>!

    So, a link would open the save menu, subtract the variable by 1, and the link text would be replaced by a <<display>> passage. That would be abolutely awesome.

    Edit: Actually, could I have it set a few variables?
  • mostly wrote:
    Edit: Actually, could I have it set a few variables?


    Sure, that's not a problem.

    Actually, since you're going to be displaying a passage, you could just do all the $variable modifications in there, which would give you full control over that without having to update the code every time you wanted to change what you're doing to the $variables.  Sound like a plan?
  • Yes! That would be perfect.
  • Okay.  Change the <<script>> in the PassageDone special passage to something like this:

    <<script>>
    UISystem.addClickHandler(".passage #saves-menu-link", null, function () { UISystem.buildSaves(); },
    function () {
    $(".passage #saves-menu-link").replaceWith('<span id="saves-menu-span"></span>')
    var output = document.querySelector(".passage #saves-menu-span");
    var passage = state.active.variables.savesMenuPassage;
    if (!tale.has(passage)) { return throwError(output, 'passage "' + passage + '" does not exist'); }
    passage = tale.get(passage);
    new Wikifier(output, passage.processText());
    }
    );
    <</script>>
    The way it's written, you control which passage is displayed by setting the $savesMenuPassage variable.  For example:
    <<set $savesMenuPassage = "The ponies, they come...">>
  • Wow! That's brilliant! It works beautifully, thank you.

    You mentioned earlier you could make it so I could vary the save link text. That would be really helpful.

    Also, and please let me know if I'm getting annoying here,  is there any way of checking in the story if save data exists? Say I only wanted some text containing a load/save link to appear at the start of the story if the player had a saved game, would that be possible?
  • mostly wrote:
    You mentioned earlier you could make it so I could vary the save link text. That would be really helpful.


    Replace the current widget with this: (requires a quoted argument; usage: <<savesMenu "Let slip the saves of war!">>)

    <<widget savesMenu>><a id="saves-menu-link" class="link-internal"><<print $args[0]>></a><</widget>>
    Or, replace the widget with this: (can take an optional quoted argument; usage: <<savesMenu>> or <<savesMenu "Let slip the saves of war!">>)

    <<widget savesMenu>><a id="saves-menu-link" class="link-internal"><<if $args.length !== 0>><<print $args[0]>><<else>>DEFAULT_SAVES_MENU_LINK_TEXT<</if>></a><</widget>>

    mostly wrote:
      is there any way of checking in the story if save data exists? Say I only wanted some text containing a load/save link to appear at the start of the story if the player had a saved game, would that be possible?


    Put this in a script passage:

    window.savesCount = function ()
    {
    if (!SaveSystem.OK()) { return 0; }

    // retrieve the saves object
    var saves = storage.getItem("saves");
    if (saves === null) { return 0; }

    // iterate over the save slots, checking each for an existing save
    var count = 0;
    for (var i = 0; i < saves.slots.length; i++) { if (saves.slots[i] !== null) { count++; } }

    return count;
    }
    Usage example:

    <<if savesCount() neq 0>><<savesMenu "I see you've been here before...">><<else>>No saves for you!<</if>>
  • This is perfect, it's all exactly how I want it now! I think the save system is really slick, by the way. The only point I'd question is that deleting a save game closes the window, it seems unnatural to me. Coincidentally, it would be better for my game if it didn't, but it's really not a big deal. By the way, selecting 'Save to Disk...' on an iOS device will crash the browser, predictably enough. Again, not complaining, just thought it might be useful if you didn't know already.

    TheMadExile, thank you so much! I really owe you one!
  • mostly wrote:

    The only point I'd question is that deleting a save game closes the window, it seems unnatural to me.


    Sorry.  That's just the way the saves menu is written.  You'd have to roll your own saves menu to change that (which is possible, CoraBlue was doing that, but a lot of work).


    mostly wrote:
    By the way, selecting 'Save to Disk...' on an iOS device will crash the browser, predictably enough.


    I did not know that, though I'm not really surprised.  You shouldn't even be seeing the disk buttons though, so that's a problem.

    When you say "crash the browser", do you mean the page, if so was there an error, or the did the entire browser go down (which would be awesome in a bad way, of course)?
  • The whole browser, boom! Tabs are recovered when you load it back up, but the game restarts. I'm in iOS7 Safari, I can download and check other free browsers like Chrome if it would help. It's the least I could do!
  • Headshot! ;D

    Actually, I've just published a new release of SugarCube (-2900).  I'd appreciate it if you could test that.
  • I'd be happy to! I'm at work right now, but I'll definitely be able to give it a whirl tonight.

    From the release notes: [quote]Added several new static methods to the SaveSystem object to make it more useful to developers. Sounds interesting. Are these detailed in the documentation? Does it refer to the config.saves stuff?

    Just perused your website, by the way. Bodacious Space Pirates looks awesome, I've got to check that out.
  • mostly wrote:
    From the release notes: [quote]Added several new static methods to the SaveSystem object to make it more useful to developers.
    Sounds interesting. Are these detailed in the documentation? Does it refer to the config.saves stuff?

    No, the saves configuration object (config.saves) has existed for quite a while (some of its properties are newer than others).  What the message refers to are static methods on the SaveSystem object itself.  I added several new new static methods which should help with interacting directly with save objects.  They're something I've had in mind since CoraBlue was writing her own saves menu for SugarCube.  Having to write the savesCount() function for you (which is no longer necessary in -2900+) reminded me about them.

    And no, they're not documented yet.  Mostly because SaveSystem doesn't have any documentation at all (well, except for on these forums), since I never expected anyone to actually want to write their own save menus and/or poke the saves in other ways (probably silly of me not to have expected that, but yeah).  I need to rectify that sometime soon.

    Here's the public API for the SaveSystem: (the new methods are: length(), hasAuto(), getAuto(), count(), has(), get())

    /* SAVE SLOTS */
    // Returns the total number of available slots
    SaveSystem.length() :integer

    // Returns the total number of filled slots
    SaveSystem.count() :integer

    // Returns whether a slot is filled
    SaveSystem.has( slot ) :boolean
    <integer> slot: save slot index (0-indexed)

    // Returns a save object from a slot
    SaveSystem.get( slot ) :object
    <integer> slot: save slot index (0-indexed)

    // Loads a save from a slot
    SaveSystem.load( slot )
    <integer> slot: save slot index (0-indexed)

    // Saves the story/game to a slot
    SaveSystem.save( slot , title )
    <integer> slot: save slot index (0-indexed)
    <string> title: OPTIONAL title of the save, if omitted an excerpt from the passage is used

    // Deletes a save from a slot
    SaveSystem.delete( slot )
    <integer> slot: save slot index (0-indexed)


    /* AUTOSAVE */
    // Returns whether the autosave is filled
    SaveSystem.hasAuto() :boolean

    // Returns the autosave object
    SaveSystem.getAuto() :object

    // Loads the autosave
    SaveSystem.loadAuto()

    // Saves the story/game to the autosave slot (you probably don't want to call this manually, or maybe you do)
    SaveSystem.saveAuto( title )
    <string> title: OPTIONAL title of the autosave, if omitted an excerpt from the passage is used

    // Deletes the autosave
    SaveSystem.deleteAuto()


    /* DISK SAVES */
    // Saves the story/game to disk
    SaveSystem.exportSave()

    // Loads a save from disk (you do not call this manually, it must be called by the change handler of an <input type="file"> element)
    SaveSystem.importSave( event )
    <event object> event: the event object which was passed to the change handler of the associated <input type="file"> element


    /* PURGE */
    // Deletes all saves (incl. the autosave, if it's enabled)
    SaveSystem.purge()
  • Sorry to butt in like this, but is this also doable with other menu items, such as Restart or Options?

    I know for a fact that the first example you wrote worked beautifully simply by replacing "saves" with "options" in the appropriate places (which was pretty freaking cool, by the way):
    <<script>>
    UISystem.addClickHandler(".passage #options-menu-link", null, function () { UISystem.buildOptions(); });
    <</script>>
    and

    <<widget optionsMenu>><a id="options-menu-link" class="link-internal">options</a><</widget>>
    But would it work with your newer examples, such as like an OptionSystem or something like that?

    Thanks a bunch!  ;)
  • Primrose wrote:

    Sorry to butt in like this, but is this also doable with other menu items, such as Restart or Options?


    Yes.  You've already sussed out how to create your own options menu link.  A restart menu link would be similar.  For example:

    <<script>>
    UISystem.addClickHandler(".passage #menu-restart-link", null, function () { UISystem.buildRestart(); });
    <</script>>
    And:

    <<widget restartMenu>><a id="restart-menu-link" class="link-internal">restart</a><</widget>>

    Primrose wrote:

    But would it work with your newer examples, such as like an OptionSystem or something like that?


    No.  The options menu was always designed to be created by the author, so you work with it in a more normal way (although it is kind of klugey).  Basically, you'll need to create a new passage and call it MenuOptions (this is a special passage that SugarCube uses (via UISystem.buildOptions()) to populate the options menu), then add options macros to it to build up your options menu.  Depending on what options you intend to have, you will also possibly need to setup some things in some of the other special passages.

    It would likely be easier to look at an example of a (probably) typical options setup, so I'd look at that first and see what questions you might have.
  • Just gave the new beta a whirl in Safari. Good news: The "Save to Disk..." option no longer appears. Bad news - my passages, previously vertically centred, now appear at the very top of the page!
  • mostly wrote:
    Bad news - my passages, previously vertically centred, now appear at the very top of the page!


    I added a CSS @media query to make SugarCube somewhat nicer on mobile devices.  Since your project has some fairly heavy CSS modifications, you might need to add something like this to the bottom of your CSS now:

    @media screen and (max-width: 768px)
    {
    body { margin: 0; min-height: 0; }
    #passages { padding: 0; }
    }
    Try it out and let me know if it fixes the problem.
  • It's still happening, I'm afraid. I'll try with a simpler stylesheet.

    OK, it happens with just this in the stylesheet for an empty story (just some plain text in the start passage, which appear vertically centred in Chrome on my laptop but at the top (just under the uibar) on Safari:
    html
    {
    /* Vertical centering */
    width: 100%;
    height: 100%;
    display: table;
    }

    body {
    background-color: #000;
    margin: 0;
    height: 100%;
    display: table-cell;
    vertical-align: middle;
    font-size: 62.5%;
    }

    .passage
    {
    width: 45%;
    min-width: 26em;
    height: 100%;
    display: table;
    font-family: Sylfaen, Helvetica, "Helvetica Neue", Arial, sans-serif;
    /*letter-spacing: 0.1em;*/
    padding: 1.5em;
    padding-left: 2em;
    font-size: 1.75em;
    background-color: rgba(0,0,0,0.7);
    /*color: #eee;*/
    margin: 0 auto;
    /*border: white ridge 0.8em;*/
    border-radius: 1em;
    }
    Adding the extra @media code at the bottom doesn't affect it.

    Would it be helpful if I cut more out of the stylesheet to try and narrow down the problem?
  • mostly wrote:

    Would it be helpful if I cut more out of the stylesheet to try and narrow down the problem?


    No.  The code in the @media query is what's causing the problem.  My off-the-cuff solution just doesn't fix it.

    Let me play around with FF's responsive mode to see if I can see why the snippet isn't wait (looks at the snippet, D'oh!).

    Okay try this:

    @media screen and (max-width: 768px)
    {
    body { margin: 0; }
    #passages { padding: 0; min-height: inherit; }
    }
    I accidentally put the min-height property on the body selector, when it should go on the #passages selector.  It should work fine now.  I also changed the value to inherit (not required, but a better value anyway).
  • Yep, you nailed it! Please let me know if there's anything else in specific you'd like me to check.

    A couple of questions about the save stuff you've written for me:

    In the "display" passage that replaces the saves menu link text I'd like to include another save link, but when I do it isn't clickable. Can this be done?

    Also, any variable that I'm setting in the "display" passage isn't saved in the save game, can I have it run that stuff before the data is captured?
  • Hi! Thanks a bunch for making up that file for me; it's really helped (and introduced and couple other problems, but hopefully you can help with that, too).

    I thought the thread was kind of getting confusing with like two issues going on simultaneously, so I just moved my question to a new thread: http://twinery.org/forum/index.php/topic,1471.0.html

    Thanks again!  ;D
  • mostly wrote:
    In the "display" passage that replaces the saves menu link text I'd like to include another save link, but when I do it isn't clickable. Can this be done?


    With some difficulty, yes.  I assume that you'd like each of the saves menu links to have its own link and replacement text?


    mostly wrote:
    Also, any variable that I'm setting in the "display" passage isn't saved in the save game, can I have it run that stuff before the data is captured?


    Not from the replacement passage, no.  It is doable, however, though less convenient.  I'm going to need a list of the variables you want to modify and what the modifications should be.
  • I'll PM you the details, but if it's too long-winded I'm sure I can figure out something else. Thanks!
Sign In or Register to comment.