Gamebook - How do I make certian text trigger (Solved)

i'm a bit new so i'm not sure how to make it work. I want to make it so if you go into a page(in this case a sort of center room), and have not gone through 'the bathroom' then some text wouldn't be printed and others would in it place. or just not appear at all.

Edit: figure out thanks to help below. still using flags to set when text appears or not.


I believe the Game Book does also (Text Adventure does have it) have the built-in 'visited' Boolean Attribute

which you can use with the 'if' Script:

if (NAME_OF_PAGE.visited) {
  // scripting for having visited the specified page
}
<!--
// or:
if (not NAME_OF_PAGE.visited) {
  // scripting for NOT having visited the specified page
}
// optionally:
else { // if (not NAME_OF_PAGE.visited) {
   // scripting for NOT having visited the specified page
}
// or:
else { // if (NAME_OF_PAGE.visited) {
   // scripting for having visited the specified page
}
-->

'NAME_OF_PAGE' Page Object -> 'Page' Tab -> Page Type: [SCRIPT] or [TEXT+SCRIPT] -> (see below)

add new script -> 'scripts' section/category -> 'if' Script -> (see below)

if [EXPRESSION] NAME_OF_PAGE.visited
-> then, -> add new script -> (whatever script/s you want)
else,
-> add new script -> (whatever script/s you want)

or

if [EXPRESSION] not NAME_OF_PAGE.visited
-> then, -> add new script -> (whatever script/s you want)
else,
-> add new script -> (whatever script/s you want)


also, you can create an Object Attribute to store your old location (Room Object):

http://textadventures.co.uk/forum/quest/topic/cbqdk1cjk0evyjqptdweqw/gamebook-back-to-previous-page

and use it in an 'if' Script, if you want specifically to check if you just came from some Page Object


Is there a way to add in an AND command in casei want to check for mulipte flags. LIke if i have hat AND cape then an option appears. I tried else IF but didn't seem to work


an example:

'NAME_OF_STARTING_PAGE' Page Object -> Page Type: [script] or [text+script]:

(creating your Attributes and their initial values, so you can thus have them, and thus be able to adjust/change/manipulate their values and check them via the 'if' Script)

(add new script -> 'variables' category/section -> 'set a variable or attribute' Script -> see below, repeat as needed)

set variable game.state = [EXPRESSION] 0
set variable player.strength = [EXPRESSION] 0
set variable game.dragon_dead = [EXPRESSION] false
set variable player.right_hand = [EXPRESSION] "unarmed"

'WHATEVER' Page Object -> Page Type: [script] or [text+script]:

(add new script -> 'scripts' category/section -> 'if' Script -> see below)

if [EXPRESSION] NAME_OF_PAGE.visited and game.state = 3 and player.strength = 100 and game.dragon_dead and player.right_hand = "sword"
-> then, -> add new script -> (whatever script/s)

// or, nested 'ifs' also produce the same 'and' logic too:

if [EXPRESSION] NAME_OF_PAGE.visited
-> if [EXPRSSION] game.state = 3
->-> if [EXPRESSION] player.strength = 100
->->-> if [EXPRESSION] game.dragon_dead
->->->-> if [EXPRESSION] player.right_hand = "sword"
->->->->-> then, -> add new script -> (whatever script/s)
->->->-> else,
->->->->-> msg ("You still need the sword")
->->-> else,
->->->-> msg ("You still have to kill the dragon")
->-> else,
->->-> msg ("You still need 100 strength")
-> else,
->-> msg ("The game state needs to be 3")
else,
-> msg ("You've not visited the WHATEVER page yet")

the 'else if' is (mostly similiar to) 'or' logic, an example:

if [EXPRESSION] player.test_score > 89 // maybe an 'A' grade, or ... (goto first else if)
  set variable player.test_grade = [EXPRESSION] "A"
else if [EXPRESSION] player.test_score > 79 // maybe a 'B' grade, or... (goto next else if)
  set variable player.test_grade = [EXPRESSION] "B"
else if [EXPRESSION] player.test_score > 69 // maybe a 'C' grade, or... (goto next else if)
  set variable player.test_grade = [EXPRESSION] "C"
else if [EXPRESSION] player.test_score > 59 // maybe a 'D' grade, or... (goto else)
  set variable player.test_grade = [EXPRESSION] "D"
else // an 'F' grade
  set variable player.test_grade = [EXPRESSION] "F"

basic Boolean Logic:

definition logic:

true = TRUE
false = FALSE

negation (not) logic:

not true = FALSE
not false = TRUE

'and' logic:

true and true = TRUE
true and false = FALSE
false and true = FALSE
false and false = FALSE

'or' logic:

true or true = TRUE
true or false = TRUE
false or true = TRUE
false or false = FALSE


ask if you need help with anything or need stuff explained more/better or ask about whatever


As delineated by HK:

SetFlagOn ("Flag1")
SetFlagOn ("Flag2")
if (GetBoolean (game, "Flag1") and (GetBoolean (game, "Flag2"))) {
  msg ("good job")
}

You can also use "or" instead of "and."

UPDATED: to put more close-parentheses in there, oops! :) Anyway if you just paste the code above into a blank text+script page (code view), it works. Take it from there. Set those flags on preceding pages, and use GetBoolean when needed. And call them whatever you want, obviously.


Adding on, if you use "or" it means if either flag is on.

If you use "and" it means if both flags are on.

And you can use as many as you like, including a mix of and/or. As long as you contain them in the right parantheses in the right places.


i've been using flags but I want to use the once command too. In text not script+text area.

for example {once: {if A=1: TEST} other words here {if flag: words}}

but then it glitches and won't work right as I intend. unless Gamebook can't do that sort of stacking


It can! Using just generic "Flag1" and "Flag2" this worked for me using Once, and then didn't show up at all when I revisited the page:

{once:{if Flag1:Hello!} How are you doing? {if Flag2:I'm fine!}}

Which, on the page, just looks like:

Hello! How are you doing? I'm fine!

(If Flag1 and Flag2 are on, of course)


Oh, okay for some reason when I try to use {if counter<=2:words} and I don't trigger enough of the counter for it to appear, it just appears as text within the paragraph. resorted to turning a flag on when the counter at 2 or higher and using that flag for text replacing

{once:{if A<=1: A} more text {if B: B!} more text.}


true/false is determined by string comparisons:

(each letter/character is checked/compared)

player.alias = "hk"
if ( (player.alias) = ("hk") )
// does ("h") = ("h") ---> true / suceeds
// does ("k") = ("k") ---> true / suceeds
// all trues ----> TRUE // "hk" = "hk"

player.alias = "hk"
if ( (player.alias) = ("hm") )
// does ("h") = ("h") ---> true / suceeds
// does ("k") = ("m") ---> false / fails
// NOT all trues ----> FALSE // "hk" <> "hm"

player.alias = "hm"
if ( (player.alias) = ("hk") )
// does ("h") = ("h") ---> true / suceeds
// does ("m") = ("k") ---> false / fails
// NOT all trues ----> FALSE // "hm" <> "hk"

quest IS case sensitive:

player.alias = "hk"
if ( (player.alias) = ("hK") )
// does ("h") = ("h") ---> true / suceeds
// does ("k") = ("K") ---> false / fails
// NOT all trues ----> FALSE // "hk" <> "hK"

(but you can use the built-in converter-helper Functions/Scripts: LCase (STRING), UCase (STRING), etc)


technically Boolean Attributes ("flags") are like this, for example:

if orc.dead = true
or
if orc.dead = false

but, quest is programmed to understand (and use) this shortened form for true:

if orc.dead

and (based upon the above) for 'false', you can thus do this:

if not orc.dead

or, for 'false', you can also do its normal syntax:

if orc.dead = false

however, there's no reason to do the normal syntax for Booleans for 'true' (if orc.dead = true), as that's an extra and un-needed operation

but the point is that regardless of the Attribute Type, it's doing the same string comparisons:

if orc.dead // Boolean Attribute // a "flag"
// is the same as
if orc.dead = true // Boolean Attribute // a "flag"
// which is same value comparison as all the other Types of Attributes:
if player.alias = "HK" // String Attribute
if dragon.life = 999 // Integer Attribute
if player.right_hand = sword // Object Attribute


there's 3 types of VARIABLES (keeping this simple):

VARIABLES:
-> 1. Variables: local/temporary: only exist within their parent scripting
-> 2. Attributes: global/permanent (so long as its parent Object exists / still exists): you can use them anywhere in your game, but do note that when you change their values, you change their values (those new/changed values are now the values the Attribute stores, so when you use that Attribute somewhere else, it's using those new/changed values, as the old values are lost/over-written... unless you store them in another/seperate Attribute before you change/over-write them, hehe)
-> 3. Parameters: deals with Functions, Commands, and Delegates-Script Attributes


Oh I see sorry, you wanted to check a counter and a flag, etc.

Another way is in Text+Script. Go into codeview and paste this in:

SetCounter ("Counter1", 2)
SetFlagOn ("Flag1")
SetFlagOn ("Flag2")
if (GetBoolean (game, "Flag1") and (GetBoolean (game, "Flag2"))) {
  if (GetInt(game, "Counter1") <= 2) {
  }
  msg ("Nailed it!")
}

And you can wrap all that in

firsttime {
}

If you only want them to see it once, the first time they visit the page.

But I see what you're saying about having it in one line of text. I'm pretty sure that can be done. I'll check back in later if you haven't figured it out (though it looks like your interim solution of setting a flag if the counter is a certain value will get that done --- and may even be the best solution!).


Hey wait a minute I just got exactly that to work just in Text mode:

{once:{if Counter1<=2:this text} also this text {if Flag1:and this text, too}}

Mind the spacing and capital letters matter, too.

(and nothing appears if the counter value isn't met)


in code, it's using the 'msg' Script/Function regardless of whether in the GUI/Editor, you set it to a String Type (or are typing in your text into a text box, as underneath that's a String Type, which uses the 'msg' Script) or a Script Type (the 'msg / print a message' Script):

print [MESSAGE] hi, my name is HK.
msg ("hi, my name is HK.")

print [MESSAGE] "hi, my name is HK."
msg ("\"hi, my name is HK.\"")

print [EXPRESSION] "\"hi, my name is HK.\""
msg ("\"hi, my name is HK.\"")

player.alias = "HK"
print [EXPRESSION] "hi, my name is " + player.alias + "."
msg ("hi, my name is " + player.alias + ".")

player.alias = "HK"
print [EXPRESSION] "hi, my name is {player.alias}."
msg ("hi, my name is {player.alias}.")

player.alias = "HK"
print [EXPRESSION] player.alias
msg (player.alias)

print [EXPRESSION] "hi, my name is HK."
msg ("hi, my name is HK.")

you can put it all as one line:

// 'and' logic:
if (GetBoolean (game, "Flag1") and GetBoolean (game, "Flag2") and GetInt (game, "Counter1") <= 2) {
  // scripting
}

// 'or' logic:
if (GetBoolean (game, "Flag1") or GetBoolean (game, "Flag2") or GetInt (game, "Counter1") <= 2) {
  // scripting
}

// if you got 'or' and 'and' logic together... the 'order of operations' matter, so you got to control it to be doing what you want, via using parenthesis, just like you would with a math problem, for example:

1 + 3 * 5:
 
(1 + 3) * 5 = 20
vs
1 + (3 * 5) = 16

by the way, '+ (plus: addition symbol)' is used for 'or' logic when writing Boolean Logic as arithmetic equations, and '* (asterisks: computer multiplication symbol) is used for 'and' logic

-------

the Boolean arithmetic identites/rules:

(this gets into circuitry/digital-design, Logic/Boolean Gates, and etc)

0 : false
1 : true

+ : or
* : and

X * Y = XY
XY = X * Y

X : 0 or 1 // "don't cares"

' : negation/not/complement/opposite // 0 <---> 1

// these are similar to ordinary math alegebra:
0 * X = 0
0 + X = X
1 * X = X
1 + X = 1
0' = 1
1' = 0
(X')' = X
X + X = X
X * X = X
X + X' = 1
X * X' = 0
X + Y = Y + X
X * Y = Y * X
X + (Y + Z) = (X + Y) + Z
X * (Y * Z) = (X * Y) * Z
X * (Y + Z) = (X * Y) + (X * Z)
// these are Boolean Arithmetic only:
(X + Y)' = (X') * (Y') // De Morgan
(X * Y)' = (X') + (Y') // De Morgan
X + (Y * X) = (X + Y) * (X + Z) // the weird rule, but it works in terms of Boolean logic arithmetic/manipulation

@major powers: Yeah, trigging a flag when the counter reaches X in Script+text and using that flag in the text section seems to be the only way to avoid bugs. I don't really need functions(don't really understand them quite yet) thanks for the help


About the 'Function' Element:

Functions work just like Verbs, except you can use inputs (your inputs, aka values, are the "Arguments", aka values, and the Arguments are stored into the position-matching Parameters, aka Variables, which can be used by/within the Function's scripting) in their scripting and it can return a value too, and they're not contained within Objects, you can use/"call" them anywhere

to use ("call") a Function:

GUI/Editor: run as script (Game Book: Page Type: [script] or [text+script]) -> add new script -> 'scripts' categegory/section -> 'call function' Script -> Name text box: NAME_OF_FUNCTION, add box: add in your Arguments/inputs/values if you got Parameters

in code:

NAME_OF_FUNCTION // having NO Parameters
or
NAME_OF_FUNCTION (Argument_1, Argument_2, etc more or less arguments)


to create/define your Function:

GUI/Editor: Functions -> Add -> Name text box: NAME_OF_FUNCTION, add Parameters box: add in your Parameters (NAMES OF YOUR Variables TO BE USED BY THE FUNCTION'S SCRIPTING), and lastly, add in your script(s) for the Function's scripting

in code, an example (using both Parameters and returning a Value):

<game name="example_game">
  <attr name="number_1" type="int">0</attr>
  <attr name="number_2" type="int">0</attr>
  <attr name="sum" type="int">0</attr>
  <attr name="start" type="script">
    msg ("Number 1?")
    get input {
      game.number_1 = ToInt (result)
      msg ("Number 2?")
      get input {
        game.number_2 = ToInt (result)
        game.sum = addition_of_two_integers_function (game.number_1, game.number_2) // Argument Position 1: game.number_1 // Argument Position 2: game.number_2
      }
    }
  </attr>
</game>

// Argument Position 1's Value (stored in an Attribute in this example) is matched to (and thus stored within) Parameter Position 1's Variable // num_1 = game.number_1 = (your first input)
// Argument Position 2's Value (stored in an Attribute in this example) is matched to (and thus stored within) Parameter Position 2's Variable // num_2 = game.number_2 = (your second input)

<function name="addition_of_two_integers_function" parameters="num_1, num_2" type="int"> // Parameter Position 1: num_1 // Parameter Position 2: num_2
  return (num_1 + num_2)
</function>

// example inputs and output:
game.number_1 = 4
game.number_2 = 3
game.sum = 7

if you don't have a return value, then you just call the function, you don't need to set the Function (the 'call function') to be stored within a VARIABLE, but if you do have a return value, then you MUST do something with that returned value: store it into a VARIABLE (like in my example above) or have it be used by another Function (aka it's returned value is used as an input/argument in another Function's function call) or use it within whatever other scripting Element.


for example of a Function with no return value (and no Parameters as well):

(probably the most simple Function there is, lol)

<game name="example_game">
  <attr name="start" type="script">
    hi_function
  </attr>
</game>

<function name="hi_function">
  msg ("hi")
</function>

"@major powers: Yeah, trigging a flag when the counter reaches X in Script+text and using that flag in the text section seems to be the only way to avoid bugs. I don't really need functions(don't really understand them quite yet) thanks for the help (Zubric)"


ah, this sounds like you're using a Variable VARIABLE... and since it doesn't exist outside of its parent scripting (it gets DESTROYED when it's parent scripting is done/finished), hence your error, as you're trying to use your Variable, which no longer exists, obviously an error, lol.

you want to be using an Attribute VARIABLE... I don't know the GUI/Editor script options for Integer Attribute ("counters") addition by '+1' that well... so hopefully Major Powers can explain how to use Attributes with the GUI/Editor's script options for counters and their increasing/decreasing by 1 operations/Functions.


here's an example that works (uses Attributes):

(oops, I used an Boolean Attribute / "flag", instead of an Integer Attribute / "counter"... well, it does still demonstrate the difference between using an Attribute vs a Variable, and thus the same applies for an Integer Attribute / "counter", too)

<game name="example_game">
  <attr name=hard_mode" type="boolean">false</attr>
  <attr name="start" type="script">
    ask ("Do you want to play in hard mode? (yes: hard mode, no: easy mode)") {
      game.hard_mode = result // result = (true or false) // true <--- yes // false <--- no
    }
  </attr>

<object name="room">
  <object name="player">
  </object>
  <object name="wise_wizard">
    <attr name="displayverbs" type="simplestringlist">talk</attr>
    <attr name="talk" type="script">
      msg ("{if game.hard_mode:You're playing the game in hard mode}{if not game.hard_mode:You're playing the game in easy mode}")
    </attr>
  </object>
</object>

<verb>
  <property>talk</property>
  <pattern>talk</pattern>
  <defaultexpression>You can't talk to that!</defaultexpression>
</verb>

here's an example of using a Variable which WILL cause an ERROR:

(oops, I used an Boolean Attribute / "flag", instead of an Integer Attribute / "counter"... well, it does still demonstrate the difference between using an Attribute vs a Variable, and thus the same applies for an Integer Attribute / "counter", too)

<game name="example_game">
  <attr name="start" type="script">
    ask ("Do you want to play in hard mode? (yes: hard mode, no: easy mode)") {
      hard_mode = result // result = (true or false) // true <--- yes // false <--- no
      // the 'hard_mode' VARIABLE is a Variable VARIABLE, and a Variable is local/temporary, as soon as this 'start' Script finishes, our 'hard_mode' Variable gets DESTROYED
    }
  </attr>

<object name="room">
  <object name="player">
  </object>
  <object name="wise_wizard">
    <attr name="displayverbs" type="simplestringlist">talk</attr>
    <attr name="talk" type="script">
      msg ("{if hard_mode:You're playing the game in hard mode}{if not hard_mode:You're playing the game in easy mode}")
      // ERROR: there is no 'hard_mode' Variable VARIABLE (as it was DESTROYED, as the 'start' Script of the 'game' Game Settings Object has finished already)
    </attr>
  </object>
</object>

<verb>
  <property>talk</property>
  <pattern>talk</pattern>
  <defaultexpression>You can't talk to that!</defaultexpression>
</verb>

people new to quest and to programming, should only/always use quest's Attribute VARIABLES, as we don't run into the problems of trying to use the Variables "out of scope" (as they don't exist "out of scope", as they're DESTROYED upon its parent scripting being finished/done)

Attribute VARIABLES = Attributes:

NAME_OF_OBJECT.NAME_OF_ATTRIBUTE
or
NAME_OF_OBJECT.NAME_OF_ATTRIBUTE = VALUE_OR_EXPRESSION
or
if (NAME_OF_OBJECT.NAME_OF_ATTRIBUTE OPERATOR VALUE_OR_EXPRESSION) { /* scripting */ }

------ vs -------

Variables VARIABLES = Variables:

NAME_OF_Variable
or
NAME_OF_Variable = VALUE_OR_EXPRESSION
or
if (NAME_OF_Variable OPERATOR VALUE_OR_EXPRESSION) { /* scripting */ }


ask if you need help or got questions with anything


Should read as this:
Sam walked to the cookie jar but it was empty.
but if said counter never reached the set value I get
Sam walked to the cookie jar {if counter<=3:but it was empty.}

I was using in script+text area when I needed to track it
IncreaseCounter ("flag")

So not sure why it did that. there no error message that i can see


template:

(replace my upper case stuff with what you're using as your labels/names for them)

// 'NAME_OF_YOUR_STARTING_PAGE' Page Object -> 'Page' Tab -> Page Type: [script] or [text+script] -> (see below)

// in code:
NAME_OF_YOUR_COOKIE_JAR_OBJECT.NAME_OF_YOUR_COUNTER/INTEGER_ATTRIBUTE = YOUR_STARTING_VALUE

// or, via the GUI/Editor:

add new script -> 'variables' section/category -> 'set a variable or attribute' Script -> (see below)

set variable NAME_OF_YOUR_COOKIE_JAR_OBJECT.NAME_OF_YOUR_COUNTER/INTEGER_ATTRIBUTE = [EXPRESSION] YOUR_STARTING_VALUE

// -------------

'WHATEVER' Page Object: 'Page' Tab -> Page Type: [script] or [text+script] -> (see below)

// in code:
msg ("Sam walked to the {NAME_OF_COOKIE_JAR_OBJECT.name}, {if NAME_OF_YOUR_COOKIE_JAR_OBJECT.NAME_OF_YOUR_COUNTER/INTEGER_ATTRIBUTE=0: but it was empty.}{if NAME_OF_YOUR_COOKIE_JAR_OBJECT.NAME_OF_YOUR_COUNTER/INTEGER_ATTRIBUTE>0: and takes a cookie and eats it}")
if (NAME_OF_YOUR_COOKIE_JAR_OBJECT.NAME_OF_YOUR_COUNTER/INTEGER_ATTRIBUTE > 0) {
  NAME_OF_YOUR_COOKIE_JAR_OBJECT.NAME_OF_YOUR_COUNTER/INTEGER_ATTRIBUTE = NAME_OF_YOUR_COOKIE_JAR_OBJECT.NAME_OF_YOUR_COUNTER/INTEGER_ATTRIBUTE - 1
}

// as hopefully you can see from the above... in this case, it's easier to just do the normal scripting (instead of the text processor commands):

if (NAME_OF_YOUR_COOKIE_JAR_OBJECT.NAME_OF_YOUR_COUNTER/INTEGER_ATTRIBUTE > 0) {
  NAME_OF_YOUR_COOKIE_JAR_OBJECT.NAME_OF_YOUR_COUNTER/INTEGER_ATTRIBUTE = NAME_OF_YOUR_COOKIE_JAR_OBJECT.NAME_OF_YOUR_COUNTER/INTEGER_ATTRIBUTE - 1
  msg ("Sam walks up to the " + NAME_OF_YOUR_COOKIE_JAR_OBJECT.name + ", and takes a cookie and eats it.")
} else {
  msg ("Sam walks up to the " + NAME_OF_YOUR_COOKIE_JAR_OBJECT.name + ", but it was empty.")
}

Good to know that for the future. Although sounds like it get really lengthy if i had a long paragraph with various factors that can change the words.


Is there anyway to avoid every msg being put on a new line?

Well he/she is pretty nice (he/she being the if command,) or do I literally have to make different sentences for every possibility?


you can do concatenation (literally putting things, aka strings, together)... and I left this out of my previous posts, as it'd take it's own post to explain what and how concatenation works.


let me know if interested, and I'll help you with concatenation (I'm lazy right now and I got to go somewhere soon)

here's a quick look at it:

(you can use the 'if' block with it, for answering your question, as this may not be apparent from me just briefly giving you a quick look at the concatenation itself)

my_string = "Hi, what is you name?"
msg (my_string)
my_string = my_string + " My name is HK."
msg (my_string)
my_string = my_string + " You seem nice, let's be friends!"
msg (my_string)

// results/ouputs/displayment:

Hi, what is your name? // first 'msg' Script
Hi, what is your name? My name is HK. // second 'msg' Script
Hi, what is your name? My name is HK. You seem nice, let's be friends! // third/last 'msg' Script

math arithmetic addition vs string concatenation:

5 + 5 = 10
55 + 55 = 110

"5" + "5" = "55"
"55" + "55" = "5555"
"mama" + "mia" = "mamamia"
"mama" + "5" = "mama5"


using concatenation (which means you're also doing the 'normal' scripting) and the text processor commands, together, is the most powerful/useful scripting you can do: MAX functionality! hehe :D


if you got a lot of combinations/options/outcomes/etc... you got a lot of them... there's no way to reduce them (as you want them, lol).

code-wise though in how you implement those combinations/etc can be more or less efficient than other code designs... but this is only code-wise-design, you can't do anything about the number/types of conbinations themselves, you're stuck with them.


your OS (operating system) software (windows version, MacOS whatever) is at least 50 million code lines... just to give you an idea...

computers are stupid, it takes a lot more instructions for a computer to do something than a person:

if I want to say hi, I jsut say hi (1 process)
if I want a computer to say hi, for pretend example, it'll take the computer 6 processes to say that same: hi


really smart/good programmers/genius'es can make the most concise code possible, but even then, it can still be really lengthy.

so, it's not so much about length (though if you can make something concise, do so!), but rather more about organization (easy to read and use).


also, some really useful Functions: the string manipulation Functions:

http://docs.textadventures.co.uk/quest/functions/ (scroll down to the very bottom: the 'string functions' section/category)

Asc, CapFirst, etc etc etc


Thanks solved


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

Support

Forums