How to change an attribute's value in-game?

Beginner to using Quest here. The tutorial has been really helpful for getting me started, but would hint at being able to do something without actually telling me how.

For example, it teaches you how to add the "weight" attribute to an object, so that you can use some flour to bake a cake or whatever. That's all fine and dandy. But I have the "weight" attribute set up for the flour, and can't change it in the game. I want to use up only some of the flour when I pour it. How would I change the value of the "weight" attribute by pouring it? How would you set up that script?

I plan on having combat in my game, which means I'll be using Hit Points (like any proper rpg should), and I need to know how to change a character's HP after getting attacked. The fact that the tutorial left this information out is actually kind of shocking.


If you already have the attribute weight set to an integer on the object named flour:


To increase the weight by 1, you can use:

flour.weight = flour.weight + 1


To increase the weight by 50, you can use:

flour.weight = flour.weight +50


To decrease the weight by 1:

flour.weight = flour.weight - 1

--
To decrease by 42:
flour.weight = flour.weight - 42


Okay, here's what I tried:

I made a "pour" verb for the "flour" object. For the expression, I put "It empties until there's only " + flour.weight = flour.weight - 2 + " grams remaining."
I figured that would subtract 2 from the "weight" attribute, but whenever I try the command, I just get the error message "FALSE".

What am I doing wrong here? Am I way off?


I have a guide (it's a bit technical and more focused on code, but I do show how to do it in the GUI/Editor too), specifically scroll down to the 'Two Super Scripts' section of it (but you might want to read from the top down, as I try to give you an understanding of quest and of its coding and of coding in general to help you out with understanding this stuff better):

http://textadventures.co.uk/forum/samples/topic/5559/attributes-and-if-script-guide-by-hk

also, here is a step by step walkthrough guide in creating your own little demo game, on the basics of Attribute usage:

http://textadventures.co.uk/forum/quest/topic/5387/i-really-need-help#37375

(though it doesn't get into using the 'if' Script too much)


About your topic (this is covered in more detail in my top of post guide link):

basically, it's about using the 'two super scripts', which are:

  1. the 'Attribute' Script (creating/setting/re-setting/changing/altering/manipulating/etc):

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

(I like 'cheating' via using the '[EXPRESSION]' script option, as I don't know the GUI/Editor script options that well, lol)

general syntax:

set variable NAME_OF_OBJECT.NAME_OF_ATTRIBUTE = [EXPRESSION] VALUE_OR_EXPRESSION

(replace my all capitolized stuff with what you are actually using or want to use, your naming of this stuff, in your game)

example:

set variable player.strength = [EXPRESSION] 100 // this creates this 'strength' Integer Attribute on the 'player' Player Object if it doesn't already exists. If it does already exist, then it is setting/re-setting the Value to now being '100'

// and we can set/re-set it/change/manipulate/adjust it yet again:
set variable player.strength = [EXPRESSION] 50

these are just a direct change/setting/re-setting of the Value


now what about adjusting its (new) Value based upon its (old) Value (aka: arithmetic operations: addition, subtraction, multiplication, division) ???

we do it like this, an example (increasing it via addition operation and the incrementing value of 5):

// initial value/setting: set variable player.strength = [EXPRESSION] 0

set variable player.strength = [EXPRESSION] player.strength + 5

// new value/setting: player.strength = 5
// if done again:
// new value/setting: player.strength = 10
// new value/setting: player.strength = 15
// etc etc etc

conceptually how it works:

// initial/old value: player.strength = 0

player.strength = player.strength + 5
// player.strength (NEW) = player.strength (OLD: 0) + 5
// player.strength (NEW) = (0) + 5 = 5

// new value: player.strength = 5


// old value: player.strength = 5

player.strength = player.strength + 5
// player.strength (NEW) = player.strength (OLD: 5) + 5
// player.strength (NEW) = (5) + 5 = 10

// new value: player.strength = 10


// old value: player.strength = 10

player.strength = player.strength + 5
// player.strength (NEW) = player.strength (OLD: 10) + 5
// player.strength (NEW) = (10) + 5 = 15

// new value: player.strength = 15

you get the idea...


Addition:

set variable NAME_OF_OBJECT.NAME_OF_ATTRIBUTE = [EXPRESSION] NAME_OF_OBJECT.NAME_OF_ATTRIBUTE + VALUE_OR_EXPRESSION

Subtraction:

set variable NAME_OF_OBJECT.NAME_OF_ATTRIBUTE = [EXPRESSION] NAME_OF_OBJECT.NAME_OF_ATTRIBUTE - VALUE_OR_EXPRESSION

Multiplication:

set variable NAME_OF_OBJECT.NAME_OF_ATTRIBUTE = [EXPRESSION] NAME_OF_OBJECT.NAME_OF_ATTRIBUTE * VALUE_OR_EXPRESSION

Division:

set variable NAME_OF_OBJECT.NAME_OF_ATTRIBUTE = [EXPRESSION] NAME_OF_OBJECT.NAME_OF_ATTRIBUTE / VALUE_OR_EXPRESSION


you can do more complex stuff too:

set variable player.damage = [EXPRESSION] player.damage + (player.damage * player.strength / 100)

set variable player.maximum_life = [EXPRESSION] ((player.strength + player.endurance) / 2) * 5


"Okay, here's what I tried:

I made a "pour" verb for the "flour" object. For the expression, I put "It empties until there's only " + flour.weight = flour.weight - 2 + " grams remaining."
I figured that would subtract 2 from the "weight" attribute, but whenever I try the command, I just get the error message "FALSE".

What am I doing wrong here? Am I way off? (Arkantos)"


'flour' Object -> 'Attributes' Tab -> Attributes -> Add -> (see below)

(Object Name: flour)
Attribute Name: weight
Attribute Type: int // (integer)
Attribute Value: 0

in code scripting, doing this is the same as the above: flour.weight = 0

in GUI/Editor's 'set a variable or attribute' Script's syntax (aka, scripting), it is the same as the above too: set variable flour.weight = [EXPRESSION] 0

'flour' Object -> 'Verbs' Tab -> Add -> Name: pour -> (see below)

add new script -> set variable flour.weight = [EXPRESSION] flour.weight - 2

add new script -> print a message -> (see below)

print [EXPRESSION] "You reduced the " + this.name + "'s weight by 2, so, now you only have " + this.weight + " weight of " + this.name + "."

// output: You reduced the flour's weight by 2, so, now you only have [new: flour.weight Value] weight of flour.
//
// if your initial value was: flour.weight = 10
// new value: flour.weight = 8
// output:
// You reduced the flour's weight by 2, so, now you only have 8 weight of flour.


here's an example using combat, which hopefully should help you a lot with understanding this type of stuff:

(the 'this' is a special key-word/key-command, which GETS the reference/pointer of the parent Object of the scripting)

<object name="room">

  <inherit name="editor_room" />

</object>

<object name="player">

  <inherit name="editor_object" />
  <inherit name="editor_player" />

  <attr name="parent" type="object">room</attr> // the built-in 'parent' Object reference/pointer Attribute is what actually controls/determines the location (containment/parent-child heirarchy) of Objects in your game // this is saying that the 'player' Player Object is contained within the 'room' Room Object

  <attr name="current_life" type="int">999</attr>
  <attr name="damage" type="int">100</attr>
  <attr name="current_experience" type="int">0</attr>
  <attr name="current_currency" type="int">0</attr>

</object>

<object name="orc">

  <attr name="parent" type="object">room</attr> // the built-in 'parent' Object reference/pointer Attribute is what actually controls/determines the location (containment/parent-child heirarchy) of Objects in your game // this is saying that the 'orc' Object is contained within the 'room' Room Object

  <attr name="current_life" type="int">500</attr>
  <attr name="damage" type="int">50</attr>
  <attr name="dead" type="boolean">false</attr>
  <attr name="experience" type="int">50</attr>
  <attr name="currency" type="int">25</attr>

  // this is our 'fight' Verb (yes, Verbs are just a Script Attribute with some additional coding, see the '<verb></verb>' further below, to make it functionally into a Verb):

  <attr name="fight" type="script">
    <![CDATA[
      if (this.dead) { // if orc is dead
        firsttime {
          player.current_experience = player.current_experience + this.experience
          player.current_currency = player.current_currency + this.experience
          msg ("You loot the dead orc's corpse, gaining +" + this.experience + " experience, and +" + this.currency + " currency, and so you now have: " + player.current_currency + " currency and " + player.current_experience + " experience."
        } otherwise {
          msg ("You've already looted the dead orc's corpse, silly.")
        }
      } else { // if orc is alive
        // you go first, and attack/damage the orc:
        this.current_life = this.current_life - player.damage
        msg ("You attack the " + this.name + " for " + player.damage + " damage")
        if (this.current_life < 1) { // if orc is killed
          this.dead = true // setting the orc as actually being dead
          msg ("You killed the " + this.name + "!")
        } else { // if you didn't kill the orc
          msg ("The " + this.name + " still has " + this.current_life + " life remaining.")
          // the orc now gets it's combat turn, attacking/damaging you:
          player.current_life = player.current_life - this.damage
          msg ("The " + this.name + " attacks you for " + this.damage + " damage")
          if (player.current_life < 1) { // if you were killed
            msg ("You were killed by the " + this.name + ".")
            msg ("GAME OVER")
            finish
          } else { // if you were not killed
            msg ("You still have " + player.current_life + " life remaining.")
            do (this, "fight") // the combat round is over, and so we do another combat round (looping: doing/calling/invoking the 'orc.fight' Script Attribute / Verb again), this will continue, until one of you is dead
          }
        }
      }
    ]]>
  </attr>

</object>

<verb>

  <property>fight</property>
  <pattern>fight</pattern>
  <defaultexpression>You can't fight that!</defaultexpression>

</verb>

"Okay, here's what I tried:

I made a "pour" verb for the "flour" object. For the expression, I put "It empties until there's only " + flour.weight = flour.weight - 2 + " grams remaining."
I figured that would subtract 2 from the "weight" attribute, but whenever I try the command, I just get the error message "FALSE".

What am I doing wrong here? Am I way off? (Arkantos)"


if going by what (I think) you're describing exactly/precisely: "It empties until there's only " + flour.weight = flour.weight - 2 + " grams remaining. (Arkantos)", it's a bit more complex, see below (in-code example):

(this is a bit pointless, unless you were to actually do something that matters with each iteration/loop (subtraction) of your flour scripting, as you can just directly set your flour's Value to being 2 less, instead of subtracting it down to being 2 less)

<object name="flour">
  <attr name="weight" type="int">
  <attr name="pour" type="script">
    <![CDATA[
      target_weight_variable = this.weight - 2
      msg ("The " + this.name + " empties until there's only " + target_weight_variable + " grams of it remaining.")
      msg ("You have " + this.weight + " grams of " + this.name + ".")
      while (this.weight > target_weight_variable) {
        this.weight = this.weight - 1
        msg ("You now have " + this.weight + " grams of " + this.name + ".")
      }
      msg ("You now finally have " + this.weight + " grams of " + this.name + ", which was/is your target weight of: " + target_weight_variable + " grams of " + this.name + ".")
    ]]>
  </attr>
</object>

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

Hello,

It needs to be on two separate lines.

Try this script for that verb:

flour.weight = flour.weight - 2
msg ("It empties until there's only " + flour.weight + " grams remaining.")

Hi,
You would also need a check on when the bag of flour is empty, otherwise you could end up with -2 grams remaining.

If flour.weight = 0 then msg ("The bag of flour is empty") else //[rest of pour script]

Pixie's tutorial 'Handling Water' details something similar to what you are trying
http://docs.textadventures.co.uk/quest/handling_water.html


thank you, Doctor Agon, I forgot about that check to handle, good catch!

(though, if you want, you can work with negative values just fine as well, as I think quest is programmed to handle them well/correctly, but indeed, usually we don't work with negative numbers)


examples of min/max checking:

// example min/max values:

// NAME_OF_OBJECT.NAME_OF_MINIMUM_INTEGER/DOUBLE_ATTRIBUTE = 0
// NAME_OF_OBJECT.NAME_OF_MAXIMUM_INTEGER/DOUBLE_ATTRIBUTE = 100

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

// NAME_OF_OBJECT.NAME_OF_CURRENT_INTEGER/DOUBLE_ATTRIBUTE = [WHATEVER VALUE YOU WANT IT TO START AS]

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

<![CDATA[
  if (NAME_OF_OBJECT.NAME_OF_CURRENT_INTEGER/DOUBLE_ATTRIBUTE < NAME_OF_OBJECT.NAME_OF_MINIMUM_INTEGER/DOUBLE_ATTRIBUTE ) {
    NAME_OF_OBJECT.NAME_OF_CURRENT_INTEGER/DOUBLE_ATTRIBUTE = NAME_OF_OBJECT.NAME_OF_MINIMUM_INTEGER/DOUBLE_ATTRIBUTE 
  } else if (NAME_OF_OBJECT.NAME_OF_CURRENT_INTEGER/DOUBLE_ATTRIBUTE > NAME_OF_OBJECT.NAME_OF_MAXIMUM_INTEGER/DOUBLE_ATTRIBUTE) {
    NAME_OF_OBJECT.NAME_OF_CURRENT_INTEGER/DOUBLE_ATTRIBUTE = NAME_OF_OBJECT.NAME_OF_MAXIMUM_INTEGER/DOUBLE_ATTRIBUTE
  }
]]>

Whoo-hoo!

I just learned about min/max checking!

Ha! Now I can erase the 14 lines of code I wrote to keep the player from putting more than 6 bullets in the revolver!


You know...

I've never been to any other forum that provided answers before I even asked the question!


@ Richard:

ya, you'd do these checks before your other scripting: to get the values back within your desired range/bounds, and so then you do all of your other scripting with 'correct / in-bound / in-range' Values.

for quick simple code example:

(I couldn't think of any good/real/practical example at this moment - would require too much thinking which I don't want to do right now, lol, but it still works as an example, lol)

(I used the special 'changed' Script Attribute, but you can also use a Turnscript/Timer too)

<game name="example_game">
  <attr name="start" type="script">
    msg ("Player Strength Integer: " + player.strength_integer)
    msg ("Player Strength String: " + player.strength_string)
    player.strength_integer = 200
  </attr>
</game>

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

<object name="player">
  <inherit name="editor_object" />
  <inherit name="editor_player" />
  <attr name="parent" type="object">room</attr>
  <attr name="strength_integer" type="int">-1</attr>
  <attr name="strength_string" type="string">unknown</attr>
  <attr name="changedstrength_integer" type="script">
    <![CDATA[
      msg ("Player Strength Integer: " + player.strength_integer)
      msg ("Player Strength String: " + player.strength_string)
      if (player.strength_integer > 100) {
        player.strength_integer = 100
      } else if (player.strength_integer < 0) {
        player.strength_integer = 0
      }
      msg ("Player Strength Integer: " + player.strength_integer)
      msg ("Player Strength String: " + player.strength_string)
      if (player.strength_integer > 66) {
        player.strength_string = "strong"
      } else if (player.strength_integer > 33) {
        player.strength_string = "average"
      } else {
        player.strength_string = "weak"
      }
      msg ("Player Strength Integer: " + player.strength_integer)
      msg ("Player Strength String: " + player.strength_string)
    ]]>
  </attr>
</object>

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

Support

Forums