Problem with a boolean not flipping/tripping when script says to

I'm going to try to be very careful with my wording to avoid possible confusion and the like.

There's something wrong with my code and I don't know what it is, as I did it the same way as it was done in testing on my other thread. The first time it works just fine, just gives me the credits amount. The second time it runs the first part of the "if" just fine except that it doesn't actually change attribute gift to be True instead of false, so if I run it again it just keeps adding the gift to my credits even though it was only supposed to do that once. I'm not getting any error codes when I try to run the script. It's just not doing part of what it's supposed to do.

firsttime {
  msg ("You have " +player.credits+ " credits in your bank.")
}
otherwise {
  if (BankApp.gift = False) {
    gift = True
    do (BankApp, "momgift")
  }
  else {
    msg ("You have " +player.credits+ " credits in your bank.")
    if (player.credits = <=5000) {
      msg ("\"You're running a bit low, try examing people and objects for quests. With people you might actually have to talk to them to get a quest. Yikes, socializing, that's scary stuff! It's worth it for money though.\"")
    }
    else if (player.credits = <=10000) {
      msg ("\"Keep an eye on your spending. You might wish to take on some quests somtime soon. You can usually find them by examining objects that see Out Of Place, or talking to people.\"")
    }
    else if (player.credits = 0) {
      msg ("\"You're out of money and will no longer be able to buy things. To earn money, do quests. Quests can be located by examining Out Of Place objects or talking to NPCs. Not all NPCs or Out of Place objects have quests but quite a few do.\"")
    }
    else if (player.credits = <30000) {
      msg ("\"You're doing great, a decent amount of credits. If you don't spend too frivolously, it should last you quite a while. If you'd like more credits, do some quests!\"")
    }
    else {
      msg ("\"Nice! You shouldn't be worried about credits if you don't waste your money on frivolous things. Quests are a good way to earn more credits!\"")
    }
  }
}

(this is momgift):

 <momgift type="script">
          player.credits = player.credits + this.cost
          msg ("You have " +player.credits+ " credits in your bank. Be sure to thank your mother for her generous gift.")
        </momgift>

HK edited, version 3


you just accidentally have a Variable VARIABLE (gift) instead of using your Attribute VARIABLE (BankApp.gift):

otherwise {
  if (BankApp.gift = False) {
    gift = True <--------------------- here, change it to this: BankApp.gift = True
    do (BankApp, "momgift")
  }

also, you probably know, but you need some other action/event/source/scripting that will toggle/change, your 'BankApp.gift = True' to 'BankApp.gift = False', as I presume you want to increase/change your 'player.credits' (aka, running/firing/activating your 'BankApp.momgift', via your: do (BankApp, "momgift") Function) more than just once.


also, your scripting logic order has an error and you got an error on the syntax for the operations, here's my fixes:

// WHATEVER (Verb, Object's Script Attribute, Function, Command, Turnscript, Timer, etc) Element's scirpting:
// (just using a 'Function' as an example for you)

<function name="example_function">
  firsttime {
    msg ("You have " +player.credits+ " credits in your bank.")
  }
  otherwise {
    if (BankApp.gift = False) {
      BankApp.gift = True
      do (BankApp, "momgift")
    }
    else {
      msg ("You have " +player.credits+ " credits in your bank.")
      if (player.credits <= 0) {
        msg ("\"You're out of money and will no longer be able to buy things. To earn money, do quests. Quests can be located by examining Out Of Place objects or talking to NPCs. Not all NPCs or Out of Place objects have quests but quite a few do.\"")
      }
      else if (player.credits <= 5000) {
        msg ("\"You're running a bit low, try examing people and objects for quests. With people you might actually have to talk to them to get a quest. Yikes, socializing, that's scary stuff! It's worth it for money though.\"")
      }
      else if (player.credits <= 10000) {
        msg ("\"Keep an eye on your spending. You might wish to take on some quests somtime soon. You can usually find them by examining objects that see Out Of Place, or talking to people.\"")
      }
      else if (player.credits <= 30000) {
        msg ("\"You're doing great, a decent amount of credits. If you don't spend too frivolously, it should last you quite a while. If you'd like more credits, do some quests!\"")
      }
      else {
        msg ("\"Nice! You shouldn't be worried about credits if you don't waste your money on frivolous things. Quests are a good way to earn more credits!\"")
      }
    }
  }
</function>

<object name="BankApp">
  <attr name="alias" type="string">bank app</attr>
  <attr name="gift" type="boolean">False</attr> // or (I don't know which Value, true/false, you need as your starting/initial Value): <attr name="gift" type="boolean">True</attr>
  <attr name="momgift" type="script">
    player.credits = player.credits + this.cost
    msg ("You have " +player.credits+ " credits in your bank. Be sure to thank your mother for her generous gift.")
  </attr>
</object>

VARIABLES:
-> Variables, example: strength
-> Attributes, example: player.strength
-> Parameters (deals with Functions, Commands, etc?)

a 'Variable' VARIABLE is a 'local' VARIABLE as it's not saved/stored (attached/contained within) an Object, a local Variable only exists for the scripting it is within, outside of that scripting and/or when the scripting ends, the Variable gets deleted and/or no longer exists.

for example:

<game name="example">
  <attr name="start" type="script">
    string_local_variable_1 = concatention_example ("joe")
    msg (string_local_variable_1)
    msg (string_local_variable_2)
  </attr>
</game>

<function name="concatenation_example" parameter="string_input_parameter" type="string">
  string_local_variable_2 = "blah"
  string_local_variable_2 = string_input_parameter + " " + string_local_variable_2
  return (string_local_variable_2)
</function>

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

output/results:

joe blah
ERROR: the 'string_local_variable_2' only exists within the 'concatenation_example' Function, and thus the error when we try to use this local Variable outside of where it exists (which is: in the 'start' Script Attribute of the 'game' Game Settings Object). This is known as an "out of scope" error.

whereas, since an 'Attribute' VARIABLE is actually contained within an 'Object' Element (or other Element), it is a 'global' VARIABLE, as it always exists (so long as the Element containing it, exists / still exists, of course), and thus you can use an Attribute anywhere.

an example:

<game name="example">
  <attr name="my_string_attribute" type="string">joe</attr>
  <attr name="start" type="script">
    msg (my_string_attribute)
    concatenation_example
    msg (my_string_attribute)
  </attr>
</game>

<function name="concatenation_example">
  game.my_string_attribute = game.my_string_attribute + " blah"
</function>

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

output/results:

joe
joe blah

Thank you! That solved both the problems! :D

I had noticed the syntax error (though it didn't pop up when I tested because of the variable error), but I wasn't entirely sure how to fix it in the GUI. I should have thought to correct it in the code and let the GUI handle itself, but I've been up for way too long and it didn't occur to me.

All this done, it shouldn't be a problem for me to have another code somewhere else (like at the end of a conversation) that resets the boolean to false so that the player can receive the gift again at a later date, now that I know for sure how to format the attribute in the code to make sure the right one is flipped.

EG:

//The rest of the conversation's code
msg "She disconnected you, rude, but she does have work to do."
BankApp.gift = False
//The rest of the code for the conversation related events.

The player wouldn't need to know this occurred until the next time they open the datapad and I (somehow) set it to give them a message that they need to use BankApp as a deposit has occurred. But that event bit thing is a problem for another day, or at least another hour.


I just edited my previous post with some information on, 'local variables' vs 'global attributes', VARIABLES, which you might want to read about, if you're new to coding.


edited my previous post again... I had some errors on it... the most current version is 'version 3', sorry on the re-editing...


for the 'if' Script in the GUI/Editor, you need to select the '[EXPRESSION]' script option for it if you want to use a different operation/operator, otherwise, the GUI/Editor puts in an '=' operation/operator, for you

I'm guessing this is why you've had this (the wrong syntax), an example (in code, as I don't know what the GUI/Editor's script options that well, lol):

if (player.credits = <= 0) { /* scripting */ }

so, instead, do this in the GUI/Editor:

if [EXPRESSION] player.credits <= 0

which is this (the correct syntax) in code:

if (player.credits <= 0) { /* scripting */ }


I'm both new and not new to coding (I have studied it before, but that was years ago when I was in high school and I didn't get past the most basic use of dictionaries in python which I'm not even sure apply to Quest), but it was a very informative and helpful read :3

There's a couple places and codes that will change the player's credits. This one just specifically controls the gift from the player's mother which happens a few times through the game. The others are during shopping or at the end of quests as a reward.

An example of a quest iI programmed as a test to make sure I could do it the way I wanted to (not necessarily to see if it was the best way, I know it's probably not.):

//the rest of the code things

<object name="quest">
      <inherit name="editor_object" />
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <prefix>one</prefix>
      <look>The quest is that you must sell the orange to the npc.</look>
      <take />
      <reward type="int">100</reward>
      <ontake type="script">
        SetObjectFlagOn (quest, "taken")
      </ontake>
      <changedcomplete type="script">
        if (GetBoolean(quest, "complete")) {
          UnlockExit (Goal)
          player.Credits = this.reward + player.Credits
          msg ("Quest Complete")
          msg ("You now have " +player.Credits+ " credits.")
          msg ("You've been rewarded you may proceed to the exit.")
        }
        else {
          msg ("You have not completed the quest")
        }
      </changedcomplete>
    </object>

//more code

I made it as an object in the GUI for two reasons: the first being that it just seemed easiest and the second because I don't know what other thing I could set it as that would allow the player to take/accept it. I know changedcomplete seems oddly placed. The quest started out having an attribute quest.complete that was a boolean, before I remembered that I could just set it as a flag that gets set by another piece of code, and when I made the quest complete script attribute I hit the wrong button on the GUI, but since I'm the only one who can see it and it doesn't affect the game experience, then I'm not actually sure that it's a problem.


ah, you know some coding, which can be seen by what you've posted already, hehe.

you're in luck, as quest has Lists (arrays in other languages) and Dictionaries, just like Python (Python is more popular in Europe and Quest is made my Alex who's european, so that's probably why quest has Lists and Dictionaries, whereas C++ and Java are more popular in the U.S.)

https://docs.textadventures.co.uk/quest/guides/using_lists.html
https://docs.textadventures.co.uk/quest/using_dictionaries.html
or:
http://docs.textadventures.co.uk/quest/guides/using_lists.html
http://docs.textadventures.co.uk/quest/using_dictionaries.html


quest has a special 'changedNAME_OF_ATTRIBUTE' Script Attribute, which fires/activates/runs whenever the Value of the 'NAME_OF_ATTRIBUTE' Attribute changes:

https://docs.textadventures.co.uk/quest/change_scripts.html
or this if the above link doesn't work:
http://docs.textadventures.co.uk/quest/change_scripts.html

the only other sources of dynamic scripting (repeatedly running/checking) is using Turnscripts and Timers


examples:

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

<object name="player">
  <attr name="parent" type="object">room</attr>
  <attr name="condition_string_attribute" type="string">normal</attr>
  <attr name="life_string_attribute" type="string">999/999</attr>
  <attr name="statusattributes" type="simplestringdictionary">life_string_attribute = Life: !</attr>
  <attr name="current_life_integer_attribute" type="int">999</attr>
  <attr name="maximum_life_integer_attribute" type="int">999</attr>
  <attr name="changedcurrent_life_integer_attribute" type="script">
    <![CDATA[
      if (this.current_life_integer_attribute < 0) {
        this.current_life_integer_attribute = 0
      } else if (this.current_life_integer_attribute > this.maximum_life_integer_attribute) {
        this.current_life_integer_attribute = this.maximum_life_integer_attribute
      }
      if (this.current_life_integer_attribute = 0) {
        player.condition_string_attribute = "dead"
      }
      this.life_string_attribute = this.current_life_integer_attribute + "/" + this.maximum_life_integer_attribute
    ]]>
  </attr>
  <attr name="changedmaximum_life_integer_attribute" type="script">
      this.life_string_attribute = this.current_life_integer_attribute + "/" + this.maximum_life_integer_attribute
  </attr>
</object>

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

// or:

<game name="XXX">
</game>

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

<object name="player">
  <attr name="parent" type="object">room</attr>
  <attr name="condition_string_attribute" type="string">normal</attr>
  <attr name="life_string_attribute" type="string">999/999</attr>
  <attr name="statusattributes" type="simplestringdictionary">life_string_attribute = Life: !</attr>
  <attr name="current_life_integer_attribute" type="int">999</attr>
  <attr name="maximum_life_integer_attribute" type="int">999</attr>
</object>

<turnscript name="global_turnscript">
  <attr name="enabled" type="boolean">true</attr> // quest changes it to this short-form: <enabled />
  <script>
    <![CDATA[
      if (player.current_life_integer_attribute < 0) {
        player.current_life_integer_attribute = 0
      } else if (player.current_life_integer_attribute > player.maximum_life_integer_attribute) {
        player.current_life_integer_attribute = player.maximum_life_integer_attribute
      }
      if (player.current_life_integer_attribute = 0) {
        player.condition_string_attribute = "dead"
      }
      player.life_string_attribute = player.current_life_integer_attribute + "/" + player.maximum_life_integer_attribute
    ]]>
  </script>
</turnscript>

Well that [the explanation/documentation of changedNAME_OF_ATTRIBUTE script attribute] explains a lot about how the quest worked out to actually run when the quest was completed even without me realizing I was doing it (or rather why it was doing it), I love it ! It seems really useful. Especially since some of the quests will have more than one way of completing them and this really simplifies the process of completing them.


a possible problem with the 'changed' Script Atribute is that you may have issues of when it is run vs when everything else is run... you might have some issues with the 'order of scripting operations' when working with the 'changed' Script Attribute. For example, the 'changed' script may fire off before/too-soon or after/too-late you want it to compared to another relevant script running...

otherwise, indeed the 'changed' Script Attribute is very convenient/quick/simple!

whereas, a Turnscript/Timer, let's you control/set the order of the scripting, which helps reduce the chance of conflicting order of scripting operations.


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

Support

Forums