Gamebook - Save formatting into one variable?

Hi,

I decided to turn toward the community as I am unable to make my idea work after a few days of trying.

I'd like to make a fancy gamebook, where there would be different font for the general text and for conversations.
The name of the characters also would be colored.

I've read plenty of articles and forums, but I can't make it work in Gamebook. Perhaps people didn't ask it yet or it didn't pay my attention? Or it is not even possible?

Let me show it through an example:

Xelary: Hey, guys! (Conversation font & color)
Calytrix: Oh, hi..! (Conversation font & color)

One greeted the other on a preoccupied tone. (General font & color)

Currently, this looks like this:

msg("<font color=\"#006600\"><b>Xelary</b></font>: ```Hey, guys!```")

If I wanted to change the formatting later, then I would need to re-done everything that way for each dialogue where Xelary speaks.
I wonder if it was possible to use just one variable, which contains everything? Something similar to this:

<!--Saved by Quest 5.6.5783.24153-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="fontstyle">
    <gameid>e54b175d-ce44-4462-972d-4a7f68c993e0</gameid>
    <version>1.0</version>
    <firstpublished>2016</firstpublished>
    <start type="script"><![CDATA[
      JS.addExternalStylesheet("http://fonts.googleapis.com/css?family=Nothing+You+Could+Do")
      JS.addExternalStylesheet("http://fonts.googleapis.com/css?family=Coming+Soon")
      
      OutputTextNoBr(game.css)

      msg ("<span style=\"font-family:courier\">This is Courier</span>")
      msg ("<span style=\"font-family:courier; color:red\">This is Courier in red</span>")
      msg ("<span style=\"font-family:courier; font-weight:bold\">This is Courier bold</span>")
      msg ("<span style=\"font-family:'Nothing You Could Do'\">This is Nothing You Could Do</span>")
      msg ("<span style=\"font-family:'Coming Soon'\">This is Coming Soon</span>")
      msg("")
      msg("<span class=\"speaker1\">What's on second</span>")
      msg("<span class=\"speaker2\">I didn't ask you who's on second</span>")
      msg("<span class=\"speaker1\">No, Who's on first</span>")
      msg("<span class=\"speaker2\">I don't know</span>")
      msg("<span class=\"speaker1\">Third base</span>")
      msg("<span class=\"speaker2\">Third base</span>")
      
    ]]></start>
    <css>
    <![CDATA[
      <style type="text/css">
      	.speaker1 {
      	    font-family: 'Nothing You Could Do';
      	    color: green;
      	}
      	.speaker2 {
      	    font-family: 'Coming Soon';
      	    color: blue;
      	}
      </style>
      ]]>
   </css>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
  </object>
</asl>

Originally posted there:
https://textadventures.co.uk/forum/quest/topic/6030/changing-fonts-when-someone-is-speaking

Basically, I would like one variable which contains the specified formatting. Like Font Type, color, be bold / italic etc...

So it would rather look something like that:

msg ("<span class=\"Name_Xelary\">Xelary:</span> <span class=\"Conversation\">Hey, guys!</span>")

msg ("<span class=\"Name_Calytrix\">Calytrix:</span> <span class=\"Conversation\">Oh, hi..!</span>")

msg ("")

msg ("<span class=\"General\">One greeted the other on a preoccupied tone.</span>")

So, I would just need to change the saved info in "Name_Xelary", if I wanted to change font type or font color etc...


That seems a good way to do it; that's pretty much what classes were designed for.

So, what's the problem?


I can't make the variable "Name_Xelary" in gamebook. Or any variables like that, containing more than one formatting.
The example above works in textadventure, but I can't make it work in gamebook.

How could I make a class in gamebook that I could use the same way?


EDIT: This would only work in TA, not gamebook. Sorry, I don't know gamebook.

You could even make a couple of string attributes like game.character and game.dialogue that will contain the text that you currently want to print.

Then make a changed script for each attribute, i.e., game.changedcharacter and game.changeddialogue. In the changed scripts, create a variable that adds the HTML/CSS styling to the text that you are printing (tags + game.character + game.dialogue), and then print out the variable.

Then, whenever you want to print out some text, just set the value of game.character and game.dialogue to whatever text you need.


I can't make the variable "Name_Xelary" in gamebook.

It's not a variable. It's a piece of text that's being sent to the browser. I see no reason the same code wouldn't work in a gamebook.
(possibly with some workaround for the editor not displaying the right fields).

Does the Gamebook editor not let you set attributes for the game? (I'm used to the web editor, which doesn't let you set attributes for text adventures either, so I'm used to working around its limitations)

Looking at GamebookCore, I'm pretty sure that if you copied the exact same code into a gamebook, it would work just the same. (Except there's no "start" script, so you'd have to put it on the first page)

Or, if you're not going to change the appearance of a character's text during the game, you could use a dictionary and output it as necessary. Less efficient, but maybe simpler.

In the first page:

JS.addExternalStylesheet("http://fonts.googleapis.com/css?family=Nothing+You+Could+Do")
JS.addExternalStylesheet("http://fonts.googleapis.com/css?family=Coming+Soon")
game.character_formats = NewStringDictionary()
dictionary add (game.character_formats, "Character 1", "font-family: 'Nothing You Could Do'; color: green;")
dictionary add (game.character_formats, "Character 2", "font-family: 'Coming Soon';color: blue;")

format => {
  params = Tsplit (section)
  character = ListItem (params, 1)
  text = ListItem (params, 2)
  if (DictionaryContains (game.character_formats, character)) {
    game.textprocessorcommandresult = "<span style=\""+DictionaryItem (game.character_formats, character)+"\">" + character + "</span>: “<span style=\"conversation font and color here\">"
  }
  else {
    game.textprocessorcommandresult = character + ": “<span style=\"conversation font and color here\">"
  }
  game.textprocessorcommandresult = game.textprocessorcommandresult + ProcessTextSection (text, data) + "</span>”"
}
game.textprocessorcommands = game.textprocessorcommands
dictionary add (game.textprocessorcommands, "speech:", format)

and then later you can do:

msg ("{speech:Character 1:Who's on first?}")
msg ("{speech:Character 2:Yes, that's right.}")

and it will be formatted appropriately.

Not sure what kind of problems you're having with the existing code; but pretty sure that would work.


Thank you for taking time on my issue, I really appreciate it.

About "why the code I copied not working".
I also use web-editor, but downloaded the offline version to open the code.
These lines are written into an attribute called css:

      <style type="text/css">
      	.speaker1 {
      	    font-family: 'Nothing You Could Do';
      	    color: green;
      	}
      	.speaker2 {
      	    font-family: 'Coming Soon';
      	    color: blue;
      	}
      </style>

I can't add this to gamebook to make it recognize as a code. (online editor)
The editor makes Call functions out of it, which cannot be used.
I have no clue how could I add these lines to an attribute in gamebook.

The only things I managed to add were very simple things, like

msg ("Type your name!")
GetInput() {
  game.pname = result
  msg ("Alright, your name is " + game.pname + "!")
  msg ("Now, choose your gender!")
  ShowMenu ("As it is written above, choose your gender!", Split("Female;Male", ";"), false) {
    game.gender = result
    if (game.gender = "Female") {
      game.he = "she"
      game.him = "her"
      game.his = "her"
    }
    else {
      game.he = "he"
      game.him = "him"
      game.his = "his"
    }
    msg ("So, " + game.pname + " is a " + game.gender + " and " + game.he + " loves " + game.his + " axe, cuz it is close to " + game.him + ".")
    msg ("And now, press any key to continue to the next test!")
    wait {
      MovePlayer (Page2)
    }
  }
}

Sadly, I can't even try the code you have written, as I always get the Sorry, an internal error occurred. error message.

EDIT:
Alright, I used the Add script and copied that code you have written one by one, instead of copying it into code view.
It seems to work, with colors. But font does not change.
But I still wonder if there was a solution to use the one I brought up as an example. That css one.
It looked easier to add new attributes. I'm still figuring how your code is working. I'm not experienced in this.


[edited for typo]

These lines are written into an attribute called css:

You can't do that in the web editor

I can't add this to gamebook to make it recognize as a code. (online editor)

You would have the exact same problem in a text adventure. Adding an attribute like that needs to be done in full code view, which the web editor doesn't have.

to make it recognize as a code

That snippet isn't code. It's HTML, that needs to be sent to the browser. You need to put it in a string and print it out like any other message.

The example you gave initially puts all the CSS in a string attribute named game.css. This works in both text adventure and gamebook; but it can't be done in the web editor (which doesn't support custom attributes). You can work around this by putting it between quotes, with all the line breaks removed, inside a script.

The example you gave, to do it in the web editor, you would put this in your start script (text adventure) or first page (gamebook):

msg ("<style type="text/css">.speaker1 {font-family: 'Nothing You Could Do';color: green;}.speaker2 {font-family: 'Coming Soon';color: blue;}</style>")

(Note that you will need to do this in the GUI, because the web editor has a bug that crashes if you enter the < character in a string in code view).

An alternative would be putting the CSS in a separate file.
Then on the desktop version you could do:

JS.addExternalStylesheet (GetFileURL("name_of_stylesheet.css"))

(The web version, I think, doesn't allow you to add files to the game package. So to use it on the web version you'd have to put the file on a webserver somewhere and add a link to it)

Sadly, I can't even try the code you have written, as I always get the Sorry, an internal error occurred. error message.

Yeah, that's a web editor bug. You would need to remove all the <s from the code (I usually change them to [ temporarily), and then change them back in the GUI. Or use the desktop editor (which I can't do, because it's not compatible with either of my computers)

It seems to work, with colors. But font does not change.

That's a bug in the original code. The URLs of the font files are wrong. (should be https://, not http://. It might work in the desktop player, I'm not sure, but security rules on modern browsers won't allow the HTTP version)

But I still wonder if there was a solution to use the one I brought up as an example. That css one.

You can do that with a gamebook the exact same way you do it with a text adventure. Just open it in full code view in the desktop editor, and add the css attribute that way.

The problems you've had with it are specific to the web editor, not gamebook mode.

If you want to use the css method in the web editor, look at the code earlier in this post. But be aware that this method will stop working if you use ClearScreen.

It looked easier to add new attributes.

My code is a little more complex than it needs to be. It's adding a command to the Text Processor; voodoo code that 99% of Quest users wouldn't even think about. I just thought that if you're in gamebook mode, you might appreciate being able to put {speech:character name:text} in a text page, rather than having to use script every time you want a conversation.


Thank you for your assist!

The one you have written seems difficult, but a very powerful solution. I still try to figure it out, so I could modify it for my needs.

So, I could make unique formatting for different characters (as you have done with character1 & character2).
Also, I am looking for to change the font type of the dialogue itself. Like, it would be "Coming Soon".

You helped me a lot with this web-browser explanation. I had no idea why it always "crashes".

Lot of testing ahead with the ones you've written here.
Thank you again!

EDIT:
However, there is an error message that I get when I change Page (Moving from Page1 to Page2) with the script you've written.

Error running script: Error adding key 'speech:' to dictionary: An item with the same key has already been added.

I wonder why this error appears?

Page1 scripts:

msg ("Type your name!")
GetInput() {
  game.pname = result
  msg ("Alright, your name is " + game.pname + "!")
  msg ("Now, choose your gender!")
  ShowMenu ("As it is written above, choose your gender!", Split("Female;Male", ";"), false) {
    game.gender = result
    if (game.gender = "Female") {
      game.he = "she"
      game.him = "her"
      game.his = "her"
    }
    else {
      game.he = "he"
      game.him = "him"
      game.his = "his"
    }
    msg ("So, " + game.pname + " is a " + game.gender + " and " + game.he + " loves " + game.his + " axe, cuz it is close to " + game.him + ".")
    msg ("And now, press any key to continue to the next test!")
    wait {
      MovePlayer (Page2)
    }
  }
}

Page2 scripts:

msg ("<font color=\"#006600\">Here</font>, I try to do a line-break.<br/>I wonder if it worked..!<br/>It worked, " + game.pname + "!<br/>Now check text types: <b>bold</b>, <i>italic</i>, <u>underlined</u>.")

It appears every time when I change pages.


Error running script: Error adding key 'speech:' to dictionary: An item with the same key has already been added.

Sounds like you're running the script more than once. The script I posted is designed to be run once, when the game starts. So for gamebook you'd put it on the first page.

So, I could make unique formatting for different characters (as you have done with character1 & character2).

The formats are added in the lines:

 dictionary add (game.character_formats, "Character 1", "font-family: 'Nothing You Could Do'; color: green;")
 dictionary add (game.character_formats, "Character 2", "font-family: 'Coming Soon';color: blue;")

You can add as many lines as necessary there.

(I would have preferred to add the dictionary as an attribute rather than writing a script to create it; but that's necessary if working around the web editor)

Also, I am looking for to change the font type of the dialogue itself. Like, it would be "Coming Soon".

In the code, I left in 2 places conversation font and color here. You can replace that with font-family: 'Coming Soon', or whichever font you want to use.

Hope I'm making sense there; I'm mostly better with code than with explanation.


Yes, you obviously explain it well enough!
I was able to follow the instructions so far.

The CSS method is working as well now just as you explained.

However, the code is put into the first page, it is called "game".
Or you mean, "Page1"? I haven't tried it yet, but will do.

I was wondering about this "conversation font and color here" part..! You were one step ahead of me!


However, the code is put into the first page, it is called "game".

The game element is a special thing that represents the entire game. Any script commands added to its "Scripts" tab will be run every time the player enters a new page. The first page will be the one that the player object is inside of.


Thank you for the help!
fontstyle.PNG


I was wondering if it was possible to get the name out of a variable with the engine mrangel has written.
As the protagonist can type their own name into the "game.pname" variable (page), I'd like to use it in conversations.
Can it be done? I tried a few methods, but none of them worked.


With that script as written, if you used the name {game.pname} it would display the name from the attribute. My script would treat {game.pname} like any other character name, but when that text is passed to the msg (Print message) built-in function, it will be replaced by the contents of the variable.

Hope that helps :)


Thank you once again!
It works like a charm. This engine couldn't be better.
You're breathtaking!


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums