Quick question on integers

Heya all,

Got a question when it comes to numbers and attributes.

Say I want to make an attribute, Purity. And this can both raise or lower depending on the player's actions. It has a minimum of zero, and a maximum of 100.

First question is: How (preferably in the GUI) can I make it so an attribute has a maximum value, I.e my Purity cannot go above 100.

Would this require some kind of turn script that checks my purity every turn and if It goes If Purity > 100 set attribute Purity 100? And vice-versa for going negative?

Second question. Setting different interactions with objects, such as if the player were to drink something. At purity 0 it would have response A. At purity 20 it would have response B. 40 response C, etc.

Now originally I was thinking, If purity >=20 then do response B. But then if my purity is 40, and I also have if purity >40= C, then the two would conflict? It might seem simple, and I'm sure I've seen it before, but how could I set a range? I.e if Purity between 0 and 20, 21 and 40, 41 and 60.


Best way to cap an attribute is with a change script (assuming you are using the desktop version). Go to the Attributes tab, and select the Purity attribute. Then click on "Add change script". Paste in this code (click the "Code view" icon, paste this in, then click the icon again, and it will look like it was done in the GUI):

if (this.Purity < 0) {
  this.Purity = 0
}
if (this.Purity > 100) {
  this.Purity = 100
}

Now whenever Purity changes, this will fire and ensure it is in range.

Now originally I was thinking, If purity >=20 then do response B. But then if my purity is 40, and I also have if purity >40= C, then the two would conflict? It might seem simple, and I'm sure I've seen it before, but how could I set a range? I.e if Purity between 0 and 20, 21 and 40, 41 and 60.

Do it in reverse order, so the over 80 first, "else if" over 60, then "else if" 40. If it is 65, it will not fire the first, as it is not over 80, it will for the next, as desired, and it will not for the rest because it has already done.


you can take a look at this thread too, as it's about the same topic of handling ranges of Values:

http://textadventures.co.uk/forum/general/topic/9szbwwsseu2ralhrcchdtw/please-halp-creating-different-responses-based-on-score-range

ask if you got any questions, and/or need help on how to do the stuff in the gUI/Editor.


An alternative approach is to divide the number by 20. If you divide an integer by an integer, you will get an integer, with the value rounded down, so

0-19 -> 0
20-39 -> 1
etc

then you could do:

if ((player.Purity / 20) = 0) {
  msg ("Potty mouth!")
}
else if ((player.Purity / 20) = 1) {
etc.

Further question. I'm trying to use the purity attribute in text. Now I get I can add words in by going {player.purity>=50: alluring} into the text, but is there a way to use that else if you had up there? Say {player.purity<=75: alluring / else if player.purity<=50: interesting / else if player.purity<=25: disgusting} What's the proper way to insert the 'Else if' command into text?

Although I'm about to make a wild guess of

{player.purity<=75: alluring { else if player.purity<=50: interesting { else if player.purity<=25: disgusting}}}

And see if it works.


Sadly no. You would need two if directives for each range:

{if player.purity<=75: {if player.purity>50:alluring}}

Alternatively, you could have the change script set a string attribute, say "purity_as_string". Then it is just:

{player.purity_as_string}


Aha, I see. In that case I might devise a system of levels, where player.purity will bestow a player.plevel of A, B, C, D, E or F...

if player.Purity = <80 set attribute A
if player.Purity = <60 set attribute B
if player.Purity = <40 set attribute C

Etc, so I don't have to tread on my toes with numbers in the text. Probably going to be simpler.


For anyone else wondering about this mechanic, here's the result I'm going to try now.

if (player.purity = <90) {
  set (player, "plevel", "A")
}
else if (player.purity = <70) {
  set (player, "plevel", "B")
}
else if (player.purity = <50) {
  set (player, "plevel", C)
}
else if (player.purity = <20) {
  set (player, "plevel", D)
}
else {
  set (player, "plevel", E)
}

Edit: Checking back, when I try and use a Test command that prints {player.plevel} I encounter an issue where it just prints (Script) I wonder if I've screwed up here.

I had initially set that as a script attribute, probably where I went wrong. It's now a Turn Script.

if (player.purity =< 90) {
  player.plevel = "A"
}
else if (player.purity =< 70) {
  player.plevel = "B"
}
else if (player.purity =< 50) {
  player.plevel = "C"
}
else if (player.purity =< 20) {
  player.plevel = "D"
}
else {
  player.plevel = "E"
}

But when I use the Test command that prints {player.plevel} I get

Error running script: Error compiling expression 'player.purity =< 90': SyntaxError: Unexpected token "<"; expected one of "-", <INTEGER>, <REAL>, <STRING_LITERAL>, "True", "False", <HEX_LITERAL>, <CHAR_LITERAL>, "null", <DATETIME>, <TIMESPAN>, "(", <IDENTIFIER>, "if", or "cast"Line: 1, Column: 24


I would guess you have a script call "plevel" on the player, and so {player.plevel} is trying to print that. You will need to change the name of one of them.

Also, your comparisons should be <= not =<.


if/when you do this directly in code, you need to have your scripting within the 'CDATA' tag, as this tells quest that the '<' and '>' characters/symbols are to be seen as 'greater/lesser than' operations/operators, and not as syntax tags. If you do scripting through the GUI/Editor, it handles it for you, so you don't need the CDATA tag.

also, your logic (and syntax) is incorrect too, see below for fixes


examples:

// example of using the 'CDATA' tag:

// ERROR:

<game name="example_game">
  <attr name="start" attr name="script">
    if (player.current_life < 1) {
      msg ("You were killed or have died.")
      msg ("GAME OVER")
      finish
    }
  </attr>
</game>

<object name="room">
</object>

<object name="player">
  <attr name="current_life" type="int">999</attr>
</object>

// NO error:

<game name="example_game">
  <attr name="start" attr name="script">
    <![CDATA[
      if (player.current_life < 1) {
        msg ("You were killed or have died.")
        msg ("GAME OVER")
        finish
      }
    ]]>
  </attr>
</game>

<object name="room">
</object>

<object name="player">
  <attr name="current_life" type="int">999</attr>
</object>

//same for the other scripting containing Elements, for example:

<function name="example_function">
  <![CDATA[
    if (player.current_life < 1) {
      msg ("You were killed or have died.")
      msg ("GAME OVER")
      finish
    }
  ]]>
</function>

and here's examples of doing the correct logic:

// if creating the Attributes through the GUI/Editor ('whatever' Object -> 'Attribute' Tab -> Attribute box -> Add):
// test.score would be set as an Integer Attribute (Attribute Type: int)
// test.grade would be set as a String Attribute (Attribute Type: string)

// when using scripting to create/set an Attribute and its initial Value and/or change an Attribute's Value, quest uses/parses the Value as to determine what type of Attribute the Attribute is, for example, any Value in double quotes is a String Value (and thus the Attribute will be a String Attribute).

// high to low:

if (test.score > 89) {
  test.grade = "A"
} else if (test.score > 79) {
  test.grade = "B"
} else if (test.score > 69) {
  test.grade = "C"
} else if (test.score > 59) {
  test.grade = "D"
} else {
  test.grade = "F"
}

// low to high:

if (test.score < 60) {
  test.grade = "F"
} else if (test.score < 70) {
  test.grade = "D"
} else if (test.score < 80) {
  test.grade = "C"
} else if (test.score < 90) {
  test.grade = "B"
} else {
  test.grade = "A"
}

with the logic you had:

// showing you the fixed up syntax you needed for them:

if (player.purity <= 90) { // you probably need your '=' and '<' next to each other (as you had a space between them), also the '=' has to be on the right side and the 'greater/lesser than' on the left side: <= (NO error) vs: =< (ERROR!)
  set (player, "plevel", "A")
}
else if (player.purity <= 70) { // you probably need your '=' and '<' next to each other (as you had a space between them), also the '=' has to be on the right side and the 'greater/lesser than' on the left side: <= (NO error) vs: =< (ERROR!)
  set (player, "plevel", "B")
}
else if (player.purity <= 50) { // you probably need your '=' and '<' next to each other (as you had a space between them), also the '=' has to be on the right side and the 'greater/lesser than' on the left side: <= (NO error) vs: =< (ERROR!)
  set (player, "plevel", "C") // you forgot the double quotes on your 'C' Value to make it be a String Value
}
else if (player.purity <= 20) { // you probably need your '=' and '<' next to each other (as you had a space between them), also the '=' has to be on the right side and the 'greater/lesser than' on the left side: <= (NO error) vs: =< (ERROR!)
  set (player, "plevel", "D") // you forgot the double quotes on your 'D' Value to make it be a String Value
}
else {
  set (player, "plevel", "E") // you forgot the double quotes on your 'E' Value to make it be a String Value
}

or

if (player.purity <= 90) { // the '=' has to be on the right side and the 'greater/lesser than' on the left side: <= (NO error) vs: =< (ERROR!)
  player.plevel = "A"
}
else if (player.purity <= 70) { // the '=' has to be on the right side and the 'greater/lesser than' on the left side: <= (NO error) vs: =< (ERROR!)
  player.plevel = "B"
}
else if (player.purity <= 50) { // the '=' has to be on the right side and the 'greater/lesser than' on the left side: <= (NO error) vs: =< (ERROR!)
  player.plevel = "C"
}
else if (player.purity <= 20) { // the '=' has to be on the right side and the 'greater/lesser than' on the left side: <= (NO error) vs: =< (ERROR!)
  player.plevel = "D"
}
else {
  player.plevel = "E"
}

here's the logic steps going on:

if (player.purity <= 90) // if 90 or less, do the nested script below, or otherwise (your Value is OVER 90) goto/jump-to the first 'else if' below
-> // blah scripting
else if (player.purity <= 70) // if 70 or less, do the nested script below... HOWEVER your value is (ALWAYS) OVER 90 (see above), so you'll NEVER do the nested script below, and so you goto/jump-to the next 'else if'... and have the exact same problem/issue... this continues for all of your 'else ifs' as your Value is OVER 90 and they're checking for if your Value is (decreasingly) under 90 (70, 50, 20).
HOWEVER, you will get to the 'else' which will do it's nested script, as it doesn't check your Value.


Ah, right. It was me messing up the comparisons, as well as using < when I should have had >. Correct format for anyone wanting to do 'levels' based on meter, make this into a turn script with an integer attribute for your meter and a string attribute for your level.

if (player.purity => 90) {
  player.plevel = "A"
}
else if (player.purity => 70) {
  player.plevel = "B"
}
else if (player.purity => 50) {
  player.plevel = "C"
}
else if (player.purity => 20) {
  player.plevel = "D"
}
else {
  player.plevel = "E"
}

This seems to be working with {player.plevel} returning the desired character in a test command. Thanks for all the help!


you can use a Turnscript, but also there's the special 'changed' Script Attribute that can be used for this type of stuff too:

(there's pros and cons to both Turnscripts and the special 'changed' Script Attributes)

// the special 'changed' script:

<object name="player">
  <attr name="parent" type="object">room</attr>
  <attr name="purity" type="int">-1</attr>
  <attr name="plevel" type="string">unknown</attr>
  <attr name="changedpurity" type="script">
    <![CDATA[
      // ----------------------------------------------------------------------
      // this is just if you want to keep it's Value within 0 to 100:

      if (player.purity > 100) {
        player.purity = 100
      }
      else if player.purity < 0) {
        player.purity = 0
      }
      // ------------------------------------------
      if (player.purity >= 90) {
        player.plevel = "A"
      }
      else if (player.purity >= 70) {
        player.plevel = "B"
      }
      else if (player.purity >= 50) {
        player.plevel = "C"
      }
      else if (player.purity >= 20) {
        player.plevel = "D"
      }
      else {
        player.plevel = "E"
      }
    ]]>
  </attr>
</object>

<object name="room">
</object>

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

Support

Forums