[SOLVED] Change string attribute?

Groctel
04 Jan 2017, 22:44I 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 woman
script:
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
04 Jan 2017, 23:04I 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
05 Jan 2017, 19:32it 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
05 Jan 2017, 19:44you 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
17 Jan 2017, 22:33Hi! 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
22 Jan 2017, 22:25ShowMenu 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.