I need a script which requires the player to perform the same action five times before the goal is achieved.
I tried this script on a custom command pattern, but it just repeats the first message along with the subsequent ones each time.
SetTurnTimeout (1) {
msg ("Start")
}
SetTurnTimeout (2) {
msg ("getting there")
}
SetTurnTimeout (3) {
msg ("still getting there")
}
SetTurnTimeout (4) {
msg ("nearly there")
}
SetTurnTimeout (5) {
msg ("WIN!")
}
How would I do this? Thanks in advance.
if (objectname.turncount = 5) {
msg ("start")
objectname.turncount = objectname.turncount - 1
}
if (objectname.turncount = 4) {
msg ("getting there")
objectname.turncount = objectname.turncount - 1
}
if (objectname.turncount = 3) {
msg ("still getting there")
objectname.turncount = objectname.turncount - 1
}
if (objectname.turncount = 2) {
msg ("nearly there")
objectname.turncount = objectname.turncount - 1
}
if (objectname.turncount = 1) {
msg ("WIN!")
objectname.turncount = objectname.turncount - 1
}
Hope that helps!
Thank you, anon.
So does the above go in my custom command script?
And do I say room or objectname.turncount or do I use my own room name, i.e cellar.turncount ?
I'm obviously doing something wrong. I've changed all the objectname to cellar and then added the code into my command script, but I get the following error.
Error running script: Error compiling expression 'cellar.turncount = 5': CompareElement: Operation 'Equal' is not defined for types 'Object' and 'Int32'
Got there in the end!! I don't know how ridiculous this method is, but it's the only one I could get to work.
IncreaseObjectCounter (cellar, "one")
if (GetInt(door cellar, "one") = 1) {
msg ("start")
}
IncreaseObjectCounter (cellar, "two")
if (GetInt(door cellar, "two") = 2) {
msg ("nearly there")
}
IncreaseObjectCounter (cellar, "three")
if (GetInt(door cellar, "three") = 3) {
msg ("win!")
}
<game name="example_game">
<attr name="your_action_counter_integer_attribute" type="int">0</attr>
<attr name="statusattributes" type="simplestringdictionary">your_action_counter_integer_attribute = Your Action Counter: !</attr>
</game>
<object name="room">
</object>
<object name="example_object">
<attr name="parent" type="object">room</attr>
<attr name="displayverbs" type="simplestringlist">example_action</attr>
<attr name="inventoryverbs" type="simplestringlist">example_action</attr>
<attr name="example_action" type="script">
if (game.your_action_counter_integer_attribute = 1) {
msg ("start")
} else if (game.your_action_counter_integer_attribute = 2) {
msg ("getting there")
} else if (game.your_action_counter_integer_attribute = 3) {
msg ("still getting there")
} else if (game.your_action_counter_integer_attribute = 4) {
msg ("nearly there")
} else if (game.your_action_counter_integer_attribute = 5) {
msg ("getting there")
game.your_action_counter_integer_attribute = 0
}
game.your_action_counter_integer_attribute = game.your_action_counter_integer_attribute + 1 // this is the same as your 'Increase Counter / whatever' Script in the GUI/Editor
</attr>
</object>
<object name="player">
<attr name="parent" type="object">room</attr>
</object>
<verb>
<property>example_action</property>
<pattern>example_action</pattern>
<defaultexpression>You can't do that action!</defaultexpression>
</verb>
here it would be using the GUI/Editor's 'increase Counter / whatever' Script:
<game name="example_game">
<attr name="your_action_counter_integer_attribute" type="int">0</attr>
<attr name="statusattributes" type="simplestringdictionary">your_action_counter_integer_attribute = Your Action Counter: !</attr>
</game>
<object name="room">
</object>
<object name="example_object">
<attr name="parent" type="object">room</attr>
<attr name="displayverbs" type="simplestringlist">example_action</attr>
<attr name="inventoryverbs" type="simplestringlist">example_action</attr>
<attr name="example_action" type="script">
if (game.your_action_counter_integer_attribute = 1) {
msg ("start")
} else if (game.your_action_counter_integer_attribute = 2) {
msg ("getting there")
} else if (game.your_action_counter_integer_attribute = 3) {
msg ("still getting there")
} else if (game.your_action_counter_integer_attribute = 4) {
msg ("nearly there")
} else if (game.your_action_counter_integer_attribute = 5) {
msg ("getting there")
game.your_action_counter_integer_attribute = 0
}
IncreaseObjectCounter (game, "your_action_counter_integer_attribute")
</attr>
</object>
<object name="player">
<attr name="parent" type="object">room</attr>
</object>
<verb>
<property>example_action</property>
<pattern>example_action</pattern>
<defaultexpression>You can't do that action!</defaultexpression>
</verb>
here's the syntax for Attributes:
NAME_OF_OBJECT.NAME_OF_ATTRIBUTE
or
NAME_OF_OBJECT.NAME_OF_ATTRIBUTE OPERATOR VALUE_OR_EXPRESSION
or
NAME_OF_OBJECT.NAME_OF_ATTRIBUTE = NAME_OF_OBJECT.NAME_OF_ATTRIBUTE (OPERATOR: except the '=' operation/symbol) VALUE_OR_EXPRESSION
replace 'NAME_OF_OBJECT' with the name of your Object (that which is containing the Attribute you want to use)
replace 'NAME_OF_ATTRIBUTE' with the name of the Attribute (that which is contained by the 'NAME_OF_OBJECT' Object)
replace 'OPERATOR' with the operation symbol you want to use: =, +, -, *, /, %, <>, >=, <=
replace 'VALUE_OR_EXPRESSION' with either a (simple) Value or a (complex) Expression
"
I'm obviously doing something wrong. I've changed all the objectname to cellar and then added the code into my command script, but I get the following error.
Error running script: Error compiling expression 'cellar.turncount = 5': CompareElement: Operation 'Equal' is not defined for types 'Object' and 'Int32'
(OurJud)
"
I presume you have a 'cellar' Object, but it seems you didn't create/add a 'turncount' Integer Attribute to your 'cellar' Object, and thus the error, it's looking for a 'turncount' Integer Attribute upon a 'cellar' Object, which it doesn't find, hence the error.
again, Attribute usage syntax:
NAME_OF_OBJECT.NAME_OF_ATTRIBUTE
or
NAME_OF_OBJECT.NAME_OF_ATTRIBUTE OPERATOR VALUE_OR_EXPRESSION
or
NAME_OF_OBJECT.NAME_OF_ATTRIBUTE = NAME_OF_OBJECT.NAME_OF_ATTRIBUTE OPERATOR VALUE_OR_EXPRESSION
IncreaseObjectCounter (NAME_OF_OBJECT, "NAME_OF_INTEGER_ATTRIBUTE") // the double quotes are required for using an Attribute's 'name' (ID) String Attribute, as double quotes tell quest that the VALUE (NAME_OF_INTEGER_ATTRIBUTE) is a String Value, which it must be, in order to be the 'name' (ID) String Attribute of a String Attribute. Whereas, if you notice the 'NAME_OF_OBJECT' has no double quotes, this is because the 'NAME_OF_OBJECT' is a reference of an Object, which is NOT a String Value, but an Object (reference) Value. Object (reference) Values and Object (reference) Attributes do NOT have double quotes. The only except is the special/reserved Values of 'true/True/false/False' as these are for the Boolean Attributes' Values. These (true/True/false/False) are NOT Object (reference) Values, even though they don't have double quotes. If you want to get/access/use the 'name' String Attribute of an Object, you do this: NAME_OF_OBJECT.name ---or--- NAME_OF_OBJECT.name = "(String) VALUE"
this is doing/is the same thing as this (a '+1' addition expression/operation, an saving/storing the new Value back into the Attribute, of course):
NAME_OF_OBJECT.NAME_OF_INTEGER_ATTRIBUTE = NAME_OF_OBJECT .NAME_OF_INTEGER_ATTRIBUTE + 1
I feel bad saying so, hege, when you've obviously put so much work into your answer, but I don't understand a single word of anything you've written there.
The frustrating thing is the script in my last code works, but I have no idea why. I was at it for hours and just got lucky. I study it to try and understand what's happening, but even though each block of that script is only three lines long, I don't understand it... and I'm the one who did it!!
I have a real blindness with this stuff and it's as frustrating as hell! I imagine my blindness is as frustrating as hell for you lot, too!
IncreaseObjectCounter (cellar, "one")
if (GetInt(door cellar, "one") = 1) {
msg ("start")
}
IncreaseObjectCounter (cellar, "two")
if (GetInt(door cellar, "two") = 2) {
msg ("nearly there")
}
IncreaseObjectCounter (cellar, "three")
if (GetInt(door cellar, "three") = 3) {
msg ("win!")
}
unless you've discovered some weird built-in stuff/underlying code stuff, lol, this is what is going on with your scripting (meaning you thus got some really convoluted design/setup --- which I like, laughs --- it means we're learning to code --- when we make something convoluted and it works too, lol):
you have an Object named: door cellar
you added an Integer Attribute, named: "one", to the 'door cellar' Object
you set the 'door cellar' Object's 'one' Integer Attribute to: 0
the 'IncreaseObjectCounter' Function increases your 'door cellar' Object's 'one' Integer Attribute by 1, so now it's: 1 // (0+1=1)
and thus your 'if' condtion returns true, as: 1 = 1, and the 'msg ("start")' is executed/done/run/activated/used/displayed/etc
you have an Object named: door cellar
you added an Integer Attribute, named: "two", to the 'door cellar' Object
you set the 'door cellar' Object's 'two' Integer Attribute to: 1
the 'IncreaseObjectCounter' Function increases your 'door cellar' Object's 'two' Integer Attribute by 1, so now it's: 2 // (1+1=2)
and thus your 'if' condtion returns true, as: 2 = 2, and the 'msg ("nearly there")' is executed/done/run/activated/used/displayed/etc
you have an Object named: door cellar
you added an Integer Attribute, named: "three", to the 'door cellar' Object
you set the 'door cellar' Object's 'three' Integer Attribute to: 2
the 'IncreaseObjectCounter' Function increases your 'door cellar' Object's 'three' Integer Attribute by 1, so now it's: 3 // (2+1=3)
and thus your 'if' condtion returns true, as: 3 = 3, and the 'msg ("win!!")' is executed/done/run/activated/used/displayed/etc
whereas, all you needed was this:
<object name="door cellar">
<attr name="NAME_OF_INTEGER_ATTRIBUTE" type="int">1</attr>
</object>
if (GetInt (door cellar, "NAME_OF_INTEGER_ATTRIBUTE") = 1) {
msg ("start")
}
else if (GetInt (door cellar, "NAME_OF_INTEGER_ATTRIBUTE") = 2) {
msg ("nearly there")
}
else if (GetInt(door cellar, "NAME_OF_INTEGER_ATTRIBUTE") = 3) {
msg ("win!")
set (door cellar, "NAME_OF_INTEGER_ATTRIBUTE", 0) // this isn't needed if this condition 'wins' the game (but that'd require the 'finish' Script to stop the game (which you should do, along with prompting the person they won / displaying score-whatever, when the game is over, lol)
}
IncreaseObjectCounter (door cellar, "NAME_OF_INTEGER_ATTRIBUTE")
replace (ALL) the 'NAME_OF_INTEGER_ATTRIBUTE' with the name of the Integer Attribute you've added to your 'door cellar' Object (and which you've initially set it's Value as: 1 --- see this already done in my code above)
also, you can reduce the coding, by doing this (as the 'GetInt' Function is not needed: extra un-needed work/operations/code is bad for you and the computer, lol):
<object name="door cellar">
<attr name="NAME_OF_INTEGER_ATTRIBUTE" type="int">1</attr>
</object>
if (door cellar.NAME_OF_INTEGER_ATTRIBUTE = 1) {
msg ("start")
}
else if (door cellar.NAME_OF_INTEGER_ATTRIBUTE = 2) {
msg ("nearly there")
}
else if (door cellar.NAME_OF_INTEGER_ATTRIBUTE = 3) {
msg ("win!")
door cellar.NAME_OF_INTEGER_ATTRIBUTE = 0 // this isn't needed if this condition 'wins' the game (but that'd require the 'finish' Script to stop the game (which you should do, along with prompting the person they won / displaying score-whatever, when the game is over, lol)
}
door cellar.NAME_OF_INTEGER_ATTRIBUTE = door cellar.NAME_OF_INTEGER_ATTRIBUTE + 1
replace (ALL) the 'NAME_OF_INTEGER_ATTRIBUTE' with the name of the Integer Attribute you've added to your 'door cellar' Object (and which you've initially set it's Value as: 1 --- see this already done in my code above)
I actually think you're starting to understand coding... you just need to be taught to understand the syntaxing only... I think you're getting the logic, but you're confused and not yet able to understand the syntax, so you just get messed up with how to correctly syntax what you want to do or can't understand yet other's syntax/help, due to just not getting the syntax.
Though, you may/probably are still also confused/overwhelmed by the terms/concepts too (as well as the syntax), but I'm guessing on this part. As the terms/concepts take quite awhile to start understanding them enough that they start to make sense to you and you can start to understand others when they talk about these terms/concepts.
the concept involved:
Have an Integer Attribute that increases (or decreases --- Anonynn's example --- it depends on design/goal for which, increase/decrease, is better. For this stuff, I think they're about equal. But they do have slight coding scripting-design differences). Check that Integer Attribute repeatedly for whether to do an action or not, and if doing an action, which action.
You could try (no coding)
Use the 'First time ' option to reply to your input
Then Print a suitable message to denote failure.
Else. Do first time again
Fail message ( possibly different)
Else first time
Fail message ( different?)
Else first time
Fail message (almost there?)
Else . Success message and anything else pertaining to succeeding.
This is clumsy, but uses no coding ( my coding is almost non existent)
I use this for a lot of stuff.
I do what Anonynn does. Here is the explanation from my "tutorial" game:
This is a frequent problem I see on the forums and one that I struggled with for the longest time. Once I figured this out, it is most likely the most helpful bit of coding I have learned. It really opens up gaming options! So, I will try to make this simple.
You will use something like this whenever you want multiple things to get accomplished before it triggers a new event or singular accomplishment. Want to have multiple keys used to open a door? Or, multiple pieces of a password collected before punching in a code? You want to wear multiple different pieces of clothing before you can sneak in to a top secret lab?? This is your answer.
In this room I had a jigsaw puzzle that you had to use pieces on to complete the puzzle
It's a bit complex, so if you have questions, ask on the forum.
I would also recommend Anonynn's method. The script goes on the command if the action is triggered that way. Change objectname
to an object in your game (or even the command), and remember to add turncount
as an integer attribute set to 5 on that object.
Thank you everyone. I shall have a go at all these methods when I next work on the game.
The Pixie
I would also recommend Anonynn's method. The script goes on the command if the action is triggered that way. Change objectname to an object in your game (or even the command), and remember to add turncount as an integer attribute set to 5 on that object.
I changed objectname
to fire axe
Then I went to the Attribute tab on the fire axe, clicked Add, typed turncount
and set the integer to 5, then I run the game and type the relevant command, and all that happens is that it prints out all five messages all at the same time.
Xan, I tried your method next, and you lost me at 3c. I don't see an option for setting the value to 0. I read on beyond this, but just got more and more confused.
I'm about to try Father's idea now.
Father, couldn't do yours.
When you use the 'first time' it wants you to put the 'otherwise' in. I don't see an option for 'else' anywhere. You only get the 'else' option when you use an 'if' script. If I try to put the 'else' in manually it just deletes it when I go back to the UI view.
Apart from the first line, every line that starts:
if (
... change it to:
else if (
But Father doesn't say anything about 'ifs'.
They just say to put a series of 'firsttimes' and 'elses'
Father:
You could try (no coding)
Use the 'First time ' option to reply to your input
Then Print a suitable message to denote failure.
Else. Do first time again
Fail message ( possibly different)
Else first time
Fail message ( different?)
Else first time
Fail message (almost there?)
Else . Success message and anything else pertaining to succeeding.
This is clumsy, but uses no coding ( my coding is almost non existent)
I use this for a lot of stuff.
Sorry, I'd addressed each suggestion and wrongly assumed you were referring to my last post.
I'll go try it now. Thanks.
That was hard work, but it works now. Thank you.
OurJud,
Copy-paste the following code into a new game so you can see it in the .aslx file. This would be very helpful I think. For this example, I did NOT need a changed attribute counter. It is simply based off of how many items you give the baker. Then, If you talk to her, you will see that with each item you give her, she has a different response. When you give her all items and talk to her again, she leaves the room to go make a cake (never to return).
If you want messages to pop-up based on only the act of giving the ingredients (or pushing a button), I think you will need the changed attribute I mentioned earlier. I set the changed responses to the 'talk to' verb. Ask if you have questions. This bit of scripting is THE most useful bit I have learned since I have started. There is SOOO much you can do when you get this part down. Most of X2 is based on this type of coding. Ask if you have questions!
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="Multiple conditions met test">
<gameid>02912a31-3e9c-4324-949f-937ddd85e5ea</gameid>
<version>1.0</version>
<firstpublished>2016</firstpublished>
</game>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="eggs">
<inherit name="editor_object" />
<look>Eggs.</look>
<take />
<feature_usegive />
<giveto type="scriptdictionary">
<item key="Bertha"><![CDATA[
msg ("You hand the eggs over to Bertha and she smiles.<br/>")
RemoveObject (eggs)
Bertha.IngredientsCount = Bertha.IngredientsCount - 1
]]></item>
</giveto>
<usedefaultprefix type="boolean">false</usedefaultprefix>
</object>
<object name="Bertha">
<inherit name="editor_object" />
<look>It's Bertha. She's a baker. Talk to her.</look>
<IngredientsCount type="int">4</IngredientsCount>
<speak type="script"><![CDATA[
if (Bertha.IngredientsCount = 4) {
firsttime {
msg ("\"Hi there, you handsome devil. Could you do me a favor and get me some ingredients so I can make a cake? I'll need eggs, flour, a pan, and sugar. Thanks, dear!\"")
}
otherwise {
msg ("\"I'm still in need of those four ingredients so I can make the cake. Help me out, why don't you?\"")
}
}
else if (Bertha.IngredientsCount = 3) {
msg ("\"You've given me one of those four things I need. Hurry along and fetch me three more items.")
}
else if (Bertha.IngredientsCount = 2) {
msg ("\"Oooh. Have way there, good lookin'. Just a couple more items to go!\"")
}
else if (Bertha.IngredientsCount = 1) {
msg ("\"Oh my. I just need one more thing. I'm getting excited about making this cake. Hurry along, darling.\"")
}
else if (Bertha.IngredientsCount = 0) {
msg ("\"Most awesome! Thanks for your help. I can now get to baking!\"<br/><br/>Bertha shuffles off to the kitchen to make a cake. (DEMO OVER)")
RemoveObject (Bertha)
}
]]></speak>
</object>
<object name="flour">
<inherit name="editor_object" />
<look>Flour.</look>
<take />
<feature_usegive />
<giveto type="scriptdictionary">
<item key="Bertha"><![CDATA[
msg ("You hand the flour over to Bertha and she smiles.<br/>")
RemoveObject (flour)
Bertha.IngredientsCount = Bertha.IngredientsCount - 1
]]></item>
</giveto>
</object>
<object name="pan">
<inherit name="editor_object" />
<look>A pan.</look>
<take />
<feature_usegive />
<giveto type="scriptdictionary">
<item key="Bertha"><![CDATA[
msg ("You hand the pan over to Bertha and she smiles.<br/>")
RemoveObject (pan)
Bertha.IngredientsCount = Bertha.IngredientsCount - 1
]]></item>
</giveto>
</object>
<object name="sugar">
<inherit name="editor_object" />
<look>Sugar.</look>
<take />
<feature_usegive />
<giveto type="scriptdictionary">
<item key="Bertha"><![CDATA[
msg ("You hand the sugar over to Bertha and she smiles.<br/>")
RemoveObject (sugar)
Bertha.IngredientsCount = Bertha.IngredientsCount - 1
]]></item>
</giveto>
</object>
</object>
</asl>
Thanks, hege. I'll have a play with this when I get this latest game out of the way.
You mean 'Xan', I think :D (though looking at Xan's long code post, I'd assume it was my post too, laughs)
XanMag
An alternative would be to actually move the items to the baker when the player hands them over, rather than removing them. Then you can count how many she is holding:
if (ListCount(GetDirectChildren(Bertha)) = 4) {
This would more closely model the game world. One of the big things about Quest as opposed to Twine or Squiffy is that it has a world model built in; it has objects that have a meaningful relationship with each other, allowing authors to readily track where things are. In my opinion, you are better using that wherever possible.
No need for extra attributes, and it means the game world is better modelling
In other words, keep making the alternative to 'first time' (otherwise) into another 'first time' script , putting progressive messages (nearly there) into first time until you want the sequence to finish. You can continue that as long as you want.
Arrgghh! Getting very confusing now. Sorry, hege and Xan. Yes it was the length of his post that threw me :D
Father, the game's out now, but I think I tried playing around with the first otherwise script but in my attempts it kept printing two turns at once.
I'm sure yours works but as I say that game is history now.
@TP,
Thanks for the tip. I've never used list counts or anything resembling them. I'll save this link and try messing with the next similar issue this way.
How would you handle it if someone tried to "get eggs", for example, and Bertha had the eggs?
I assume you would need an If script on the inventory tab of the eggs??
I do not think the player will be able to get the eggs if Bertha has them without you having to do any coding (you would need to make her a container, I think, if you did want that).
You could just make a command on Bertha called; "Ask for Eggs" and then when the player asks, it generates an egg in the room, or one gets added to their inventory. Just a thought.