[SOLVED] Change string attribute?

Groctel

I got a few attributes that equal to text strings and want to change them in the middle of a script to change them so they return a different text string. It is a basic dialogue script which works like this:

First, we have the talk to womanscript:

msg ("Hello, how are you?<br>")
Woman.answer1 = "Fine, and you?"
Woman.answer2 = "Well, it's been a horrible day!"
Woman.answer3 = "Meeeeh, could be better."
Woman.answer4 = "Doing good, I guess."
msg (<b>1- #Woman.answer1#<br>2- #Woman.answer2#<br>3- #Woman.answer3#<br>4- #Woman.answer4#</b>)
get input {
  if (result = "1") {
    ZZZ.Dialogueprint = Woman.answer1
    Dialogue
    msg ("I'm fine too, thanks!")
  }
  else if (result = "2") {
    ZZZ.Dialogueprint = Woman.answer2
    Dialogue
    msg ("Oh! I'm sorry about that.")
  }
  else if (result = "3") {
    ZZZ.Dialogueprint = Woman.answer3
    Dialogue
    msg ("At least it cannot be worse!")
  }
  else if (result = "4") {
    ZZZ.Dialogueprint = Woman.answer4
    Dialogue
    msg ("Me too!")
  }
  else {
    msg ("If you can read this, you have just found a bug and should tell the dev about it.")
  }
}

Then the Dialogue function that simply prints what the player says:

ZZZ.Dialogue = StartNewOutputSection ()
msg ("{ZZZ.Dialogueprint}")
EndOutputSection (ZZZ.Dialogue)
JS.eval ("$('."+PCSystem_Login.title+"').css('text-align', 'right').css('font-weight', 'bold');")

That's basically it. The point is that when it comes the the Woman.answer1 = "Fine, and you?" and the other three, the string is not changed. What am I doing wrong?

Btw: I'm running the desktop version, so the .answerx attributes are set beforehand.


The Pixie

I am not sure what the problem is, but have a couple of suggestions that might make the code simpler. Firstly, use ShowMenu, which does what you are trying to do with get input, but will be more reliable (what if the player types "5"?).
http://docs.textadventures.co.uk/quest/functions/showmenu.html

Secondly, send the result as a parameter to your Dialogue function, rather than setting it as an attribute.


hegemonkhan

it might have something to do with the 'StartNewOutputSection()/EndOutputSection()' stuff (I wasn't even aware this stuff existed, lol).

All Attributes can be set, re-set, changed, altered, manipulated, and etc through scripting:

player. strength = 100
// quest is able to parse the Value as to what type of Value it is, to what Type of Attribute it is/needs to be (so our 'player.strength' Attribute is an 'int/integer' Attribute, as it's Value, 100, is an Integer/int Value
msg (player.strength)
// outputs: 100

but, now let's have it be different:

player.strength = 50
msg (player.strength)
// outputs: 50

we can do this with all of the Attribute Types:

orc.dead = false
msg (orc.dead)
// outputs: false
orc.dead = true
msg (orc.dead)
// outputs: true

player.alias = "HK"
msg (player.alias)
// outputs: HK
player.alias = "Groctel"
msg (player.alias)
// outputs: Groctel

etc etc etc

and for Strings, we can do concatenation too:

game.x = "mama"
msg (game.x)
outputs: mama
game.x = game.x + "mia"
msg (game.x)
outputs: mamamia


hegemonkhan

you can take a look at some of this code for examples/ideas at what some things you can do:

http://textadventures.co.uk/forum/samples/topic/4988/character-creation-crude-code-and-sample-game


if you want to use a numbering input system, look into using Dictionary Attributes (a 'Dictionary' is just an 'input--->output' Function, or if you rather think of them this way, as a 'conversion' Function)

for example:

<object name="global_data_object">
  <attr name="color_list" type="simplestringlist">red; blue; yellow</attr>
  <attr name="color_dict" type="simplestringdictionary">1 = red; 2 = blue; 3 = yellow</attr> // (number to color only)
  // <attr name="color_dict" type="simplestringdictionary">red = 1; blue = 2; yellow = 3</attr> // (color to number only)
  // if you want to be able to go both ways (number to color or color to number), then you need to do this:
  // (remember, the value to the left of the '=' sign is the input value, and the value to the right of the '=' sign is the output value)
  // <attr name="color_dict" type="simplestringdictionary">1 = red; red = 1; 2 = blue; blue = 2; 3 = yellow; yellow = 3</attr>
</object>

// scripting:

msg ("Choose a color (Type in the number of your choice)")
DisplayList (global_data_object.color_list)
// the 'DisplayList' outputs for you (you can also manually code in such displayment too instead of using this built-in Function):
// 1. red
// 2. blue
// 3. yellow
get input {
  if (IsInt (result) and ToInt (result) > 0 and ToInt (result) <= ListCount (global_data_object.color_list) {
    player.color_selection = StringDictionaryItem (global_data_object.color_dictionary, result)
    // if you inputted '1', then: player.color_selection = "red"
    // if you inputted '2', then: player.color_selection = "blue"
    // if you inputted '3', then: player.color_selection = "yellow"
  } else {
    msg (Wrong input, try again")
    wait {
      ClearScreen
      // loop/call/do/invoke Script Attribute/Function/scripting again
    }
  }
}

Pixie ingeniously uses both way String Dictionary Attributes to handle RPG's 'elemental damages' (especially the handling of opposing elemental damage, ie your water damage spell used on a fire elemental monster, doing extra damage to it), as you can't do this (pseudocode):

if (monster.elemental:fire = spell.elemental:water or monster.elemental:water = spellelemental:fire), then monster.life = monster.life - spell.damage * 2 // (or 1.5 or whatever, meh)

as, if (fire = water ---> FALSE), this may seem like you can use this design, but not so, as it allows for any other elemental to be used for extra damage, and not specifically opposing elementals only.

but Pixie's ingenious-ness realized you can do this:

if (monster.elemental:fire = StringDictionaryItem (input: spell.elemental:water): outputs: fire)

which now works, as indeed, if (fire = water ---> fire, --->, fire = fire, --->, TRUE), and they're indeed opposite elementals, so it is correctly doing the extra damage.

and indeed works only for opposing elementals, as can be seen:

if (fire = air ---> earth, --->, fire = earth, --->, FALSE), and they're NOT opposite elementals, so it is correctly NOT doing the extra damage.
if (fire = fire ---> water, --->, fire = water, --->, FALSE), and they're NOT opposite elementals, so it is correctly NOT doing the extra damage.
if (fire = earth ---> air, --->, fire = air, --->, FALSE), and they're NOT opposite elementals, so it is correctly NOT doing the extra damage.


Groctel

Hi! Sorry for the super super late response. I need to keep a habit on checking and posting my threads :(

I tried the ShowMenu command, but I don't want the game to leave its interface and move to a new window for a second, so that option was not valid at all, sorry :<

Also, most of the code I originally submitted was horribly bad done, like calling different variables and not respecting upper and lower cases.

After some coding, a found a way of creating a simple and effective conversation engine. I'll explain it here for anyone who wants to copycat it into their game ^^


You will see the attributes are set to an object called zzz. I use it to dump the vars I don't want to store in any specific object so it is easier for me to control it.

First of all, I like to move the conversation into a new room and clear the screen. It's my personal style, but hey, it works for me.

So here is the woman we are going to talk to:

<object name="woman">
  <inherit name="editor_object" />
  <scenery />
  <alias>Woman</alias>
  <gender>she</gender>
  <article>her</article>
  <speak type="script">
    ClearScreen
    MoveObject (player, woman_dialogue)
  </speak>
</object>

And here is the dialogue room:

<object name="woman_dialogue">
  <inherit name="editor_room" />
  <usedefaultprefix type="boolean">false</usedefaultprefix>
  <alias>DIALOGUE: Woman</alias>
  <description type="script">
    convwoman
  </description>
</object>

The description calls a function called convwoman. For each dialogue I want the player to engage in I create a conversation function instead of just dropping it into the room description script. This is useful if you want to create a looping rpg-like conversation. You can just call the function when you reach the end and want to move back again to the top.

The convwoman covers as much as it can without entering another loop. In that case, it would call another function and start a loop there. Return points other than the function first message should also be included as separate functions.

Here's a simple two steps convwoman tree:

    msg ("Hi! How are you finding the testing room?")
    zzz.response1 = "Here goes response 1."
    zzz.response2 = "Here goes response 2"
    zzz.response3 = "Here goes response 3"
    zzz.response4 = "Here goes response 4"
    zzz.responsecount = 4
    on ready {
      convoptions
      convinput
      on ready {
        if (zzz.convnext = 1) {
          msg ("Here goes the answer to response 1")
        }
        else if (zzz.convnext = 2) {
          msg ("Here goes the answer to response 2")
          zzz.response1 = "Here goes response 1.1"
          zzz.response2 = "Here goes response 2.1"
          zzz.response3 = "Here goes response 3.1"
          zzz.responsecount = 3
          on ready {
            convoptions
            convinput
            on ready {
              if (zzz.convnext = 1) {
                msg ("Here goes the answer to response 1.1")
              }
              else if (zzz.convnext = 2) {
                msg ("Here goes the answer to response 2.1")
                convwoman22
              }
              else if (zzz.convnext = 3) {
                msg ("Here goes the answer to response 3.1")
              }
            }
          }
        }
        else if (zzz.convnext = 3) {
          msg ("Here goes the answer to response 3")
        }
        else if (zzz.convnext = 4) {
          msg ("Here goes the answer to response 4")
        }
      }
    }
// and so on

Then we have the three functions that make the engine work:

convoptions:

zzz.convmenu = StartNewOutputSection ()
msg ("")
if (zzz.responsecount > 0) {
  msg ("1. " + zzz.response1 + " ")
  if (zzz.responsecount > 1) {
    msg ("2. " + zzz.response2 + " ")
    if (zzz.responsecount > 2) {
      msg ("3. " + zzz.response3 + " ")
      if (zzz.responsecount > 3) {
        msg ("4. " + zzz.response4 + " ")
        if (zzz.responsecount > 4) {
          msg ("5. " + zzz.response5 + " ")
          if (zzz.responsecount > 5) {
            msg ("6. " + zzz.response6 + " ")
          }
        }
      }
    }
  }
}
else {
  msg ("You just encountered a bug and should tell the dev about it.")
}
EndOutputSection (zzz.convmenu)
JS.eval ("$('."+zzz.convmenu+"').css('font-weight', 'bold');")

convinput:

get input {
  if (IsInt (result)) {
    result = ToInt (result)
  }
  else {
    convinput
  }
  on ready {
    if (result > zzz.responsecount) {
      convinput
    }
    else if (result < zzz.responsecount) {
      if (result = 1) {
        zzz.convnext = 1
        zzz.convresponse = zzz.response1
        convresponseprint
      }
      else if (result = 2) {
        zzz.convnext = 2
        zzz.convresponse = zzz.response2
        convresponseprint
      }
      else if (result = 3) {
        zzz.convnext = 3
        zzz.convresponse = zzz.response3
        convresponseprint
      }
      else if (result = 4) {
        zzz.convnext = 4
        zzz.convresponse = zzz.response4
        convresponseprint
      }
      else if (result = 5) {
        zzz.convnext = 5
        zzz.convresponse = zzz.response5
        convresponseprint
      }
      else if (result = 6) {
        zzz.convnext = 6
        zzz.convresponse = zzz.response6
        convresponseprint
      }
      else {
        convinput
      }
    }
  }
}

And convresponseprint:

HideOutputSectionNow (zzz.convmenu)
on ready {
  SetAlignment ("right")
  msg ("<b>{zzz.convresponse}</b>")
  SetAlignment ("left")
}

Also, the HideOutputSectionNow function is used here:

JS.eval ("$('." + name+"').hide(0, function () { $(this).remove(); });")

Basically, the game first creates the responses by the zzz.response[x] = "String." lines. Then uses the on ready {} to make sure the responses are set before showing them by the convoptions function, which evaluates the number of possible responses it has to give the player up to six (you can make it as high as you want) and prints them inside a section. This way, you can control all the format with the JS.eval line and can make it disappear with HideOutputSectionNow.

After printing them, the program starts a get input {} loop with the function convinput, which checks if the input entered by the player can be transformed into an int. If it can, it checks if the int is between one and the maximum number of responses possible, then finds the response the player is referring to and copies both the number and the text to different variables, then runs convresponseprint. Every other case restarts the loop and asks for the input again.

Convresponseprint reads the text and displays it in bold and aligned to the right, so it can be easily read by the player. Right after it, the second on ready{} line checks at the main conversational tree and the correct branch is selected and displayed using zzz.convnext.

I hope you find it useful :)


Jay Nabonne

ShowMenu doesn't go to another window. It shows the menu inline in the main text body. There is an obsolete variant that does use a popup window (unless it's been removed), but that's not the default one you get from the editor.


Log in to post a reply.

Support

Forums