Howdy, Stranger!

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

Notepad for Player in Harlowe?

edited October 2015 in Help! with 2.0
Hi all.

Is there away to have a notepad option for the player that saves along with all other information when clicking save?

this is what I'm using to save everything at the bottom of each passage:
(link: "Main menu")[(goto: "main menu")]

<div id="stats">[Save]<save| | [Restore]<restore|
(click: ?save)[It's saved(savegame: "A","Test Save")]
(click: ?restore)[It is being restored(loadgame: "A")]

</div>

Any help would be much appreciated!
Thanks in advance.

Comments

  • Harlowe has no built-it ability for player based text input except for the (prompt:) macro, so other Author's have resorted to using Javascript (and some Harlowe magic) to implement a workaround.

    Add the following to your Story Javascript area:
    if (typeof window.customScripts == "undefined") {
    	window.customScripts = {
    		updateNamedHook: function(hookName) {
    			var value = $("input[name='" + hookName + "'], textarea[name='" + hookName + "']")[0].value;
    			// Find the named hook node and set the text inside.
    			$("tw-hook[title*='" + hookName + "']").text(value);
    		}
    	}; 
    };
    
    ... it adds a Javascript function named customScripts.updateNamedHook which you can use to update a named hook with the value entered into either a text input or text box (textarea) field.

    Replace your example from above with the following:
    (link: "Main menu")[(goto: "main menu")]
    
    {
    (set: $savenote to "")
    <span style="display: none;">|savenote>[]</span>}
    <textarea rows="4" cols="50" name="savenote"></textarea>
    <button type="submit" onclick="customScripts.updateNamedHook('savenote', this)">Update Note</button>{
    (live: 500ms)[(set: $savenote = ?savenote)]
    }
    
    <div id="stats">[Save]<save| | [Restore]<restore|
    (click: ?save)[It's saved(savegame: "A","Test Save")]
    (click: ?restore)[It is being restored(loadgame: "A")]
    </div
    
    The above works by doing the following:
    a. The Update Note button stores the current contents of the savenote textarea into the savenote named hook.
    b. The (live:) macro stores the contents of the savenote named hook into the $savenote variable. Which will be saved along with all the other story variables which you use the (savegame:) macro.

    warning: The timer event created by the (live:) macro is firing every 0.5 of a second, and this can cause a delay in the way the story handles things like the player clicking on a link.

    note: The customScripts.updateNamedHook function can handle both textarea and text input fields, so if you decide you want a text input field instead do the following:
    Replace:
    <textarea rows="4" cols="50" name="savenote"></textarea>
    With:
    <input type="text" name="savenote" value="">
    
  • Where do the notes go? I'm testing it and sometimes when I go to save the game it gives me an error:

    "The game's variables contain a complex data structure; the game can no longer be saved."

    Additionally, I'd like all notes to be printed in a running list of all notes in a single passage.

    In my tests, even when putting the text box in each passage individually the note isn't saved anywhere.
  • Sorry, I misunderstood the "have a notepad option" to mean a single note (comment) to be persisted with the other story data contained within a save.
    I also forgot that Harlowe only saves the value that a variable had at the time the passage was displayed, so the value of any dynamically changed variable like $savenote will not be included in a save created via a link on the same passage.

    So the problem consists of two parts:

    1. You want a journal that the Reader can add entries to:
    Add the following to a passage, it allows journal entries to be added to a $journal array, it also shows the array.
    Journal:
    |journal>[$journal]
    
    {
    (set: $journalEntry to "")
    <span style="display: none;">|journalEntry>[]</span>}
    <textarea rows="4" cols="50" name="journalEntry"></textarea>
    <button type="submit" onclick="customScripts.updateNamedHook('journalEntry', this)">Add Entry</button>{
    (live: 500ms)[
    	(set: $journalEntry to ?journalEntry)
    	(replace: ?journalEntry)[]
    	(if: $journalEntry is not "")[
    		(set: $journal to it + (array: $journalEntry))
    		(replace: ?journal)[$journal]
    	]
    ]
    }
    
    ... the above requires the following code to initialise the $journal variable, you place it within your startup tagged passage. If you don't have one then create a new passage, name it something like Startup and assign the new passage a startup tag.
    (set: $journal to (array:))
    

    2. You need to call the (savegame:) macro after changing to a different passage.
  • Awesome! Sorry about using the wrong vernacular there.

    Thanks for following up! I'll test it out now.
  • I can't seem to make the additions stay in the passage.

    Here is what I have just testing it out.
    (the bottom links and saves were to see if that would help but it didn't)
    (set: $journal to (array:))
    Journal:
    |journal>[$journal]
    
    {
    (set: $journalEntry to "")
    <span style="display: none;">|journalEntry>[]</span>}
    <textarea rows="4" cols="50" name="journalEntry"></textarea>
    <button type="submit" onclick="customScripts.updateNamedHook('journalEntry', this)">Add Entry</button>{
    (live: 500ms)[
    	(set: $journalEntry to ?journalEntry)
    	(replace: ?journalEntry)[]
    	(if: $journalEntry is not "")[
    		(set: $journal to it + (array: $journalEntry))
    		(replace: ?journal)[$journal]
    	]
    ]
    }
    
    <div id="stats">[Save]<save| | [Restore]<restore|
    (click: ?save)[It's saved(savegame: "A","Test Save")]
    (click: ?restore)[It is being restored(loadgame: "A")]
    
    
    (link: "Back to Game")[(savegame:)(goto: $page)]
    
    (link: "Back to Main Menu")[(savegame:)(goto: "main menu")] 
    
    
  • Besides the fact that the (set: $journal to (array:)) line should be in your startup tagged passage, so that the $journal variable only gets initialized at the start of the story, I don't see anything wrong with the code.

    What exactly do you mean when you save "I can't seem to make the additions stay in the passage." ??
  • Well after I add an entry, and save, and leave the passage, and then come back via links (as opposed to the back button) the entries no longer appear.

    Is there a way to recall them or are they simply gone?

    Also, now I can't seem to add any additions at all, I get an error
    Attached is a screenshot of the error.
  • Having the (set: $journal to (array:)) line in the passage is overriding the existing value of $journal with an empty array each time the passage is displayed, which would result in you having no entries. I have explained twice where that line should be located, in your story's startup tagged passage.

    The error message is indicating that the system can not find the customScripts related code, that is the Javascript code I included in my first comment under the Add the following to your Story Javascript area: title. Check your Story Javascript area to make sure the code is still there and if it is not then re-add it again.
    If you are unsure where the Story Javascript area is then click on the blue upward pointing triangle in the bottom left corner of the Story Passage Map (blue screen with grid) and select the Edit Story Javascript option.
  • Oh okay, I was thinking I wouldn't need the javascript anymore for the second solution you posted. My mistake.

    I moved the (set $journal to (array:)) to the startup passage (and it was there to begin with - I just didn't understand what that code was actually doing, thanks for explaining that.)

    The entries stay put now, however I'm now getting this error again:
  • Do you still get that error if you don't add entries to the journal?

    If you only get the error after adding journal entries, then:

    a. do you get the error after adding one entry, two entries, etc?

    b. what type of text are you adding in the journal entries?
    eg. Are you adding only letters and number, are you adding other types of characters, are you cut-n-pasting text from other software like MS Word, etc...

    I have tested the code and Harlowe had no problems saving the journal array, with or without entries.
  • It only happens once I have added up to two entries. Only letters. No numbers.

    "Testing" and then "again"

    It's printed out kinda funny too:

    "Testing,again" But from what I gather thats a normal thing with arrays?

    So if that's the case, that it doesn't work with more than one entry, how do I fix that?
  • While creating the attached Journal Entry Test Archive I noticed I was incorrectly using the hook element's title instead of it's name in the Javascript I gave you, this would result in the Add Entry button only working for the Test and Play options and not in the Publish to File option.

    Replace the code in your Story Javascript area with the following:
    if (typeof window.customScripts == "undefined") {
    	window.customScripts = {
    		updateNamedHook: function(hookName) {
    			var value = $("input[name='" + hookName + "'], textarea[name='" + hookName + "']")[0].value;
    			// Find the named hook node and set the text inside.
    			$("tw-hook[name*='" + hookName + "']").text(value);
    		}
    	}; 
    };
    

    I have tested a story HTML created from attached Archive file in both Firefox and Chrome and did not have the error you are getting although I do get an error when restoring a save in Internet Explorer and Edge but that happens with all Harlowe based story HTML files I create.

    You can use Twine 2's Import From File option to import the Archive and run the tests yourself.
  • edited October 2015
    Awesome, that makes sense. I should I have just tried that myself. I ended up recreating the setup I had inside yours and figured out that the error came from my main menu passage.

    I had it something like this:
    Welcome.
    (if: (count: (history:), "main menu") < 1)[{
    (set: $look to "Lots and lots of text explaining things for beta testers...Lots and lots of text explaining things for beta testers...Lots and lots of text explaining things for beta testers...Lots and lots of text explaining things for beta testers...Lots and lots of text explaining things for beta testers...Lots and lots of text explaining things for beta testers...
    
    Lots and lots of text explaining things for beta testers...
    Enjoy!")
    
    }
    (print: $look)](elseif: (count: (history:), "main menu") > 0)[(set: $clook to (text-style: "bold"))
    [$clook[Click here to see the beginning text.]]<meaning2|
    (click: ?meaning2)[$look]]
    
    [[Go back->$page]]
    
    [[Journal]]
    
    [[Review Stats]]
    
    {
    (if: (count: (history:), "Start Nexus") > 0)[(link: "Restart Nexus")[(goto: "Are you sure?")]](else:)[
    [[Start Game]]
    ]}
    
    
    <div id="stats">[Save]<save| | [Restore]<restore|
    (click: ?save)[It's saved(savegame: "A","Test Save")]
    (click: ?restore)[It is being restored(loadgame: "A")]
    
    </div>
    

    I changed it to:
    (if: (count: (history:), "main menu") < 1)[
    (link: "Welcome Information")(goto: "Welcome Information")](else:)[Would you like to read the Welcome Information again? - [[Welcome Information]] ]
    
    [[Go back->$page]]
    
    [[Journal->Journal Entry]]
    
    [[Review Stats]]
    
    
    
    {
    (if: (count: (history:), "Start Game") > 0)[(link: "Restart Game")[(goto: "Are you sure?")]](else:)[
    [[Start Game]]
    ]}
    
    
    <div id="stats">[Save]<save| | [Restore]<restore|
    (click: ?save)[It's saved(savegame: "A","Test Save")]
    (click: ?restore)[It is being restored(loadgame: "A")]
    
    </div>
    

    The latter holds the same effect and resolves the complex variable error I was getting.

    Thanks for your help, Greyelf!
  • edited October 2015
    The error was due to the (set: $clook to (text-style: "bold")) line of code.

    The Harlowe overview states:
    (savegame:) currently has a significant limitation: it will fail if the story's variables are ever (set:) to values which aren't strings, numbers, booleans, arrays, datamaps or datasets.
    If, for instance, you put a changer command in a variable, like (set: $fancytext to (font:"Arnold Bocklin")), (savegame:) would no longer work.
  • I should try to familiarize myself with the Harlowe overview again. The last time I did I knew almost nothing about Twine or Harlowe, so things kind of went over my head.

    Thanks again.
  • I tested the game once it was uploaded someplace (philome.la) but the restore function seems to only be working for the state of the passages and not the journal entries.

    Is there anything else I should be adding to the javascript?

    This is what I have in it right now, as you mentioned I should have for the publish feature to work:
    if (typeof window.customScripts == "undefined") {
    	window.customScripts = {
    		updateNamedHook: function(hookName) {
    			var value = $("input[name='" + hookName + "'], textarea[name='" + hookName + "']")[0].value;
    			// Find the named hook node and set the text inside.
    			$("tw-hook[name*='" + hookName + "']").text(value);
    		}
    	}; 
    };
    
    
  • The issue seems that the (savegame:) macro appears to save the current passage and the state of it's variables as they were at the time the passage was first displayed.

    So any variables you dynamically changed (like $journal) since the passage was displayed will be reverted back to their original value at the time the saved passage was displayed when you do a restore. For the dynamically changed values to be saved you need to first move to a different passage (which can be the same passage) before calling (savegame:)
  • Okay, got it.

    I took the option to save out of the journal passage and now it's working, like you said.

    Interesting quirk of the (savegame:) macro.
Sign In or Register to comment.