Turn-Script Question

Anonynn
Hello, hello! So I reviewed the tutorial on Turn-Scripts...but it wasn't quite what I was thinking so I've become a bit stumped.

I have an item "Lantern" and another item called "Small Oil Cartridges" that are supposed to go with it. ((I'm not so keen on the Use/Give scripts because they are a little confusing)). The idea is that if the player has an oil cartridge and uses the verb on the lantern "use oil" then it'll auto-illuminate the lantern. From there I would like the lantern light to become a turn-based timer, for example, after 15 turns the lantern will go out and the player will have to use another cartridge. Different sizes (4 different sizes current planned) will increase the turns that the oil cartridges last.

Is there a better way to do this? If not, how would I set up a turn script? I notice in the tutorial that it's put on the player, so in this case do I put an attribute on the lantern called "turns" and make it an integer?

Here's the code of what I have so far.

Lantern

if (not Got(small_oil_cartridge)) {
msg ("<br/>Without oil, you cannot light this lantern. It is essentially useless right now. <br/>")
}
else if (Got(small_oil_cartridge)) {
msg ("<br/>After inserting an oil cartridge into the slot, you gently close the opening and then gingerly turn the knob a few times until you hear a soft click. Moments later, a bright glow begins emitting from the old contraption. Inside, an orange flame burns brightly, which can now act as a guide through dark places. An orange glow surrounds you. <br/>")
SetObjectLightstrength (old_lantern, "strong")
use_container ("small_oil_cartridge")
}



And currently the small oil cartridges don't have any scripts yet. I will be adding the other sizes to the lantern script as well which will be similar to the small, except with modified descriptions for brightness.

TinFoilMkIV
In the tutorial the turn script itself is just in the general objects tree, it's not actually inside any rooms at all, which is where it needs to be if you want it to be able to apply at any point in the game, as placing it inside a room will make it only active inside that room.

The part you were seeing on the player object is just a basic integer attribute. They created the attribute first so they had something to modify with the turn script, while the script simply adds +1 to the player.turn value every time it goes off. So basically you would just put a turn counter for how many turns of light you have left on the lantern and have the script modify that instead.

That being said turn scripts can be a bit tricky depending on what exactly you want out of them, and it's likely you'll want something a bit more than just the basic functionality. The problem here is that a standard turn scrip that's active goes off every time the player enters an input no matter what it is, even if it's an invalid command, the turn script still goes off. So you might see how that could be a problem with a time limited light source that loses fuel even when taking actions that shouldn't take an actual in game turn, or even a typo.

I'm not really sure the best way to go about it, but you will need a way for the game to determine what actions count as an actual game turn, and then use an attribute to let it know when that turn is actually happening. The first thing that comes to mind for me is to add code to any verb or command that qualifies as a full turn action, and have that set an attribute to signify that a turn has passed. Then in the turn script itself have it start with an 'if' statement that checks to see whether this attribute has been set, if yes, then do your normal turn stuff that needs to be done, then set the turn variable back off, and if not, then do nothing. This way you have control over what inputs count as an actual turn, although you then have to make sure every action that should be a turn actually counts as one.


EDIT: found a source to confirm the issue with quest counting any input as a "turn" for turn scripts, so a completely unrestricted turn script is generally undesirable in most cases.

Note
Quest counts each player input as a turn. If the player spending 10 turns typing commands that are not recognised, that is still 10 turns.


http://docs.textadventures.co.uk/quest/ ... vents.html

HegemonKhan
there's a few ways to deal with Turnscripts:

1. have an 'if' Script, and thus, so while the Turnscript is activating every action you do, the 'if' Script in the Turnscirpt, is preventing the (rest of the) scripts inside of the Turnscript, from activating (until~unless the 'if' Script's condition is met).

2. enable~disable the Turnscript as needed.

---------

as for "Turns", there's:

The quest engine's Internal Turns:

the internal turns, which are generally any action that you do (clicking and~or typing+entering during game play), which the Turnscript uses for its interval of firing off its scripts (if it's enabled and~or you're in its room: if its a local turnscript).

I'm not aware of how (or if) these can be worked with or manipulated, or even (directly) displayed.

You can create your own "turns" Attribute, which can be based upon the internal turns or upon your own Scripting (for example: if you "rest" during the game, say 50 turns go by, and if you "sleep" during the game, say 100 turns go by, but if you just look at your character screen, no turns go by). Not the best example, as usually you'd have the turns be in terms of hrs and~or mins, but hopefully you get the concept. *EACH* action~verb~scripting~etc you do, would need scripts determining whether to increase your turns or not, and if so, then by how many).

some quick pseudocode examples:

'eat' Verb~Command:

snack or meal?
if snack, turns increase by 5
if meal, turns increase by 10

"walk north" Verb-Command~Compass:

go to townA or townB?
if townA, turns increase by 50
if townB, turns increase by 100

you're in control of the turns fully, but this is a lot of work~coding to do...

if you want to implement this concept with a Turnscript, it's a bit more tricky (as a Turnscript is more like a Command, in that you deal with all the possibilities, as opposed to a Verb, where you only deal with a few specific possibilities for each Verb), but generally the same concept.

The Pixie
TinFoilMkIV wrote:In the tutorial the turn script itself is just in the general objects tree, it's not actually inside any rooms at all, which is where it needs to be if you want it to be able to apply at any point in the game, as placing it inside a room will make it only active inside that room.

If it is in the general tree it will run whatever room the player is in, which what neonayon wants.

That being said turn scripts can be a bit tricky depending on what exactly you want out of them, and it's likely you'll want something a bit more than just the basic functionality. The problem here is that a standard turn scrip that's active goes off every time the player enters an input no matter what it is, even if it's an invalid command, the turn script still goes off. So you might see how that could be a problem with a time limited light source that loses fuel even when taking actions that shouldn't take an actual in game turn, or even a typo.

I'm not really sure the best way to go about it, but you will need a way for the game to determine what actions count as an actual game turn, and then use an attribute to let it know when that turn is actually happening. The first thing that comes to mind for me is to add code to any verb or command that qualifies as a full turn action, and have that set an attribute to signify that a turn has passed. Then in the turn script itself have it start with an 'if' statement that checks to see whether this attribute has been set, if yes, then do your normal turn stuff that needs to be done, then set the turn variable back off, and if not, then do nothing. This way you have control over what inputs count as an actual turn, although you then have to make sure every action that should be a turn actually counts as one.


I have implemented this, but it is not trivial. You need the built-in commands like WEST and TAKE BALL to get recognised as valid commands. Also, what counts as a valid command? If you try to go west but cannot because the door is locked, presumably the character is doing something, and that might count as a turn.

A partial solution is to implement a script called "unresolvedcommandhandler" on the game object, and have it set a flag. You turn script can check if the flag is set, and only increment if it has not, reseting the flag. Pretty easy to do, but does not catch everything.

I wanted to have in-game text displayed differently to meta-text, so I added a Print function that output text in a different colour, and with an indent, and then I had that set a flag. Then I set up new dynamic templates for TAKE, DROP, etc. over-rode various built-in functions to all use Print too. Basically all in-character text used Print, so got flagged as a successful command, anything else did not. It is a lot of effort, and if you need me to talk you through how I did it, then I would not advise trying to use. Especially if you already have a lot of your game written.

Both of these techniques assume you have only one turn script, by the way.

TinFoilMkIV
The Pixie wrote:

"TinFoilMkIV"

In the tutorial the turn script itself is just in the general objects tree, it's not actually inside any rooms at all, which is where it needs to be if you want it to be able to apply at any point in the game, as placing it inside a room will make it only active inside that room.


If it is in the general tree it will run whatever room the player is in, which what neonayon wants.

That is what I meant, tho it's a good thing you clarified because looking back I can see I wrote that really poorly.

Anonynn
Hmm, so that sounds incredibly complicated. I don't mind the turn-scripts including false commands or mistypes, and I figure putting the turn-script in the "game.object" would likely make it global. I've just never used a turn-script before. They are little intimidating. Timers are easy xD Maybe I should just go with one of those.

Anonynn

Hmm, so that sounds incredibly complicated. I don't mind the turn-scripts including false commands or mistypes, and I figure putting the turn-script in the "game.object" would likely make it global. I've just never used a turn-script before. They are little intimidating. Timers are easy xD Maybe I should just go with one of those.



So I went ahead and tried turn-scripts but came across a very...interesting bug I think. So I have three different turn-scripts.

T-Script Name: small_oil
T-Script Name: medium_oil
T-Script Name: large_oil

Here is the coding for the small_oil turn-script
SetTurnTimeout (15) {
msg ("<br/>The lantern begins to flicker before the oil cartridge is finally used up. Moments later, the lantern dies. <br/>")
SwitchOff (old_lantern)
DisableTurnScript (small_oil)
}


Now...strangely enough whenever I went through to the medium and large, and changed the code to this...

SetTurnTimeout (15) {
msg ("<br/>The lantern begins to flicker before the oil cartridge is finally used up. Moments later, the lantern dies. <br/>")
SwitchOff (old_lantern)
DisableTurnScript (medium_oil)
}


It kept changing all three turn-scripts to "medium_oil" or "large_oil" --- which I'm not sure is the bug or not.

So I just went back and deleted the other two sizes and did this instead...

Turn-Script:
SetTurnTimeout (35) {
DisableTurnScript (oil)
SwitchOff (old_lantern)
msg ("<br/>The lantern begins to flicker before the oil cartridge is finally used up. Moments later, the lantern dies. <br/>")
}


Lantern:
if (not Got(oil_cartridge)) {
msg ("<br/>Without oil, you cannot light this lantern. It is essentially useless right now<br/>")
}
else {
if (Got(oil_cartridge)) {
msg ("<br/>After inserting an oil cartridge into the slot, you gently close the opening and then gingerly turn the knob a few times until you hear a soft click. Moments later, a bright glow begins emitting from the old contraption. Inside, an orange flame burns brightly, which can now act as a guide through dark places. An orange glow surrounds you. <br/>")
EnableTurnScript (oil)
SetObjectLightstrength (old_lantern, "strong")
RemoveObject (oil_cartridge)
}
}


The only two problems I'm coming across is the "Disable Turn-Script" message keeps repeating endlessly after every following turn, and the lantern isn't lighting up any of the spaces that are set to "dark".

The Pixie
I think you are confusing two different techniques. SetTurnTimeout makes something happen in so many turns. If you are using that, you just to call it once when the cartridge is inserted, which is probably the easiest way for this. The other technique is the turn script.

What you have is a turn script that will every turn set an event to happen in 35 turns. So when the lamp goes on, each turn an event is set up for 35 turns after that. When the first delayed event goes off, the turnscript is stopped, but next turn the second one will fire, and try to turn off the turn script again, and then the third, etc, for 35 turns.

What you could do is set an int attribute on the cartridges called "lifetime", then on the USE script for all cartridges have this:
if (IsSwitchedOn (old_lantern)) {
msg ("<br/>The lantern is already shining brightly; no need to use a cartridge now.. <br/>")
}
else {
SetTurnTimeout (this.lifetime) {
msg ("<br/>The lantern begins to flicker before the oil cartridge is finally used up. Moments later, the lantern dies. <br/>")
SwitchOff (old_lantern)
SetObjectLightstrength (old_lantern, "")
}
SwitchOn (old_lantern)
SetObjectLightstrength (old_lantern, "strong")
destroy(this.name)
}

HegemonKhan
err... my apologies for any confusion, I totally forgot that, that command~method~whatever (SetTurnTimeOut) existed, laughs.

err... is the 'SetTurnTimeout' a method of the Turnscript? Or, does the 'SetTurnTimeout' create a Turnscript? It's been so long for me, I'm now confused. The quest wiki doc, doesn't show the 'SetTurnTimeout' as a method~Attribute of a Turnscript Element... but I thought as I'm trying to remember, if this was a method~Attribute of a Turnscript, or not. I know that there's a similar Function~method for the Timer... maybe the wiki just is missing it, or it's not a method~Attribute of the Turnscript.

ach, regardless, I think everyone can see that I'm now really confused. Again, my apologies for causing anyone else confusion, due to my own confusion.

---------------

Edit: after some research using the quest doc site, those various scripts~functions~methods, at least conceptually work like constructors~mutators~accessors for the TurnScript Element.

I'm guessing that the 'SetTurnTimeout' is indeed a method~Attribute of the Turncript Element, and it's just not documented in the wiki doc site. Or, well, since they're methods, whereas the 'enabled' is a member~quest:Attribute, and 'scripts', is well, scripts (enables the adding of scripts or its just a Script Attribute named 'script', lol).

maybe I still got this all wrong... wouldn't be surprising... HK is often so confused, it's beyond human comprehension, laughs... sighs... lol....

-------------

I think my 3 programming classes (Java, C++, and Python) have fried my brain! (I'm bloody having to learn graphics for both Java and Python, and learning OOD~OOP along in regards to files: .h ~ header vs .cpp ~ body, and I've never done graphics before, ARGH!)

for anyone going into CS (Computer Science) ~ Programming:

NEVER EVER take 3 programming classes at the same time! It's just way too much work!

(unless you already know all 3 of them, inside and out, and~or you're a programming genius)

The Pixie
HegemonKhan wrote:err... my apologies for any confusion, I totally forgot that, that command~method~whatever (SetTurnTimeOut) existed, laughs.

I too had forgetten the SetTurnTimeOut function existed, and only realised it was the best way to do it when I read neonayon's post.

err... is the 'SetTurnTimeout' a method of the Turnscript? Or, does the 'SetTurnTimeout' create a Turnscript? It's been so long for me, I'm now confused. The quest wiki doc, doesn't show the 'SetTurnTimeout' as a method~Attribute of a Turnscript Element... but I thought as I'm trying to remember, if this was a method~Attribute of a Turnscript, or not. I know that there's a similar Function~method for the Timer... maybe the wiki just is missing it, or it's not a method~Attribute of the Turnscript.


It is just a function, and is best used independently of turn scripts (you can use both in a game, but not to do the same thing).

XanMag
Look at this mess.... Jay really helped me with this one. I kept having the problem where I could not disable a turn script, because evidently... once it is started it is started and cannot be stopped. I still don't understand it entirely, but thanks to Jay, I got a good working TS.

if (GetBoolean(Xanadu, "healthy")) {
Xanadu.sickcount = 0
}
else {
if (Xanadu.sickcount = 2) {
msg ("----<br/>Your mouth, tongue, and throat have this odd, tingling sensation.")
}
else if (Xanadu.sickcount = 5) {
msg ("----<br/>Aside from the tingly sensation in your mouth and throat, it now feels like little, drunk gymnasts are doing flips and twists in your gut. In doing so, those little gymnasts are somehow also playing an odd assortment of instruments that make some of the strangest gurgling, burbling, and sloshing sounds you have ever heard. Perhaps you should find your way to a restroom?")
}
else if (Xanadu.sickcount = 8) {
msg ("----<br/><i>'Oh, Dear Eight Pound, Six Ounce, Newborn Baby Jesus, in your golden, fleece diapers...'</i> you mutter as you begin your prayers. The twirling in your stomach has escalated to an all out riot. Whatever is in there, is fighting violently to get out. Your esophageal and anal sphincters are now on all out 'pucker mode'. Sweat has beaded on your brow. It is a cold and unwelcome sweat. You really, really, really need to find a restroom.")
}
else if (Xanadu.sickcount = 12) {
msg ("---<br/>You can no longer swallow your bathroom pride...<br/><br/>You drop your pants immediately where you stand. Before they hit the floor, the eruptions begin. There is so much leaving your body (from both ends), you quickly dehydrate and become disoriented. You stumble around, slipping in wet puddles. You remember dancing lights and spinning rooms. You stumble into a cold room and pass out...<br/>---")
SetObjectFlagOn (Xanadu, "healthy")
AddToInventory (rotten food)
play sound ("fart.wav", false, false)
MoveObject (Xanadu, Prison Cell)
}
else {
if (game.pov.parent = farthest stall) {
play sound ("fart.wav", false, false)
msg ("---<br/>With your knees crossed coupled with your difficulty in standing up straight, you are having a hard time getting your pants down.<br/><br/>Just in the nick of time, you do get your pants opened up and you drop them to the floor...<br/><br/>Before you can sit down, however, the dam breaks and the flood gates open. At first, it just sounds like a high pressure fire hose. Sprinkled in are some odd toots and squeaks as the sulfurous emission continues. At the tail end (no pun intended) of your fecal display, the cacophony of noises erupts into a crescendo of honks, bloots, ka-phroops, slurps, and fizzles. Just when you thought the misery was over, the vomiting begins. The projectile barf flies forth in a fancy array of colors. The explosiveness of it all is enough to make Mt. Pinatubo blush. You hurl, spew, chowdergargle, and blow chunks. You upchuck one last time and wipe your mouth on your sleeve. At least you are feeling a little better now.<br/><br/>You wipe your bleary, wet eyes and take in your surroundings.<br/>---")
wait {
msg ("---<br/>Wow. Disgusting. I can't even describe how unclean this stall is. There are colors and smells and textures in here that go beyond rational explanation. Is it possible to hold this much filth in one human stomach? Wait... You don't remember eating anything that was neon green. How did shit get on the ceiling? <br/><br/>Anyway, you sheepishly back out of the stall, disappear from the restroom, and sneak off down the hallway to avoid embarrassment. Although you feel sorry for whatever poor soul has to clean this up, you hope it gets done pretty quickly. Ick...<br/>---")
DisableTurnScript (sickturnscript)
MoveObject (rotten food, Item Warehouse 1)
IncreaseScore (10)
MoveObject (Xanadu, Long Hallway)
UnlockExit (JCLock)
SetObjectFlagOn (Xanadu, "healthy")
SetObjectFlagOn (farthest stall, "unclean")
MoveObject (janitors cart, Filthy Restroom)
}
}
}
Xanadu.sickcount = Xanadu.sickcount + 1
}


Good luck.

XanMag

Anonynn

if (IsSwitchedOn (old_lantern)) {
msg ("<br/>The lantern is already shining brightly; no need to use a cartridge now.. <br/>")
}
else {
SetTurnTimeout (this.lifetime) {
msg ("<br/>The lantern begins to flicker before the oil cartridge is finally used up. Moments later, the lantern dies. <br/>")
SwitchOff (old_lantern)
SetObjectLightstrength (old_lantern, "")
}
SwitchOn (old_lantern)
SetObjectLightstrength (old_lantern, "strong")
destroy(this.name)
}



Thanks everyone! I'll give this a shot!

UPDATE:

It's not working. No messages for the script are appearing and the light doesn't work in the dark area. : /

I also added the "lifetime" attribute to the oil and made it an integer of 35.

The Pixie
I realise there are two issues with the script. The first is it gives no message when the cartiridge is used. The second is it will work even if the lantern is in another room. Here is an updated version.
if (not old_lantern.parent = player) {
msg("The cartridge is for use on a lantern, and you are not carrying a lantern.")
}
else if (IsSwitchedOn (old_lantern)) {
msg ("<br/>The lantern is already shining brightly; no need to use a cartridge now. <br/>")
}
else {
msg ("<br/>You put the cartridge in the lantern and it starts to glow brightly. <br/>")
SetTurnTimeout (this.lifetime) {
msg ("<br/>The lantern begins to flicker before the oil cartridge is finally used up. Moments later, the lantern dies. <br/>")
SwitchOff (old_lantern)
SetObjectLightstrength (old_lantern, "")
}
SwitchOn (old_lantern)
SetObjectLightstrength (old_lantern, "strong")
destroy (this.name)
}

However, even the original should have worked if you were carrying the lantern. I have tested it and it does light a room, and it does stop doing so after the required number of turns.

Here is a full demo of it.
<!--Saved by Quest 5.6.5783.24153-->
<asl version="550">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="lantern">
<gameid>f6e3d45a-fbf4-40a1-91e7-7aa506071d85</gameid>
<version>1.0</version>
<firstpublished>2015</firstpublished>
<feature_lightdark />
</game>
<object name="room">
<inherit name="editor_room" />
<description>The first room</description>
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="old_lantern">
<inherit name="editor_object" />
<take />
<alias>lantern</alias>
</object>
<object name="cart">
<inherit name="editor_object" />
<feature_usegive />
<use type="script"><![CDATA[
if (not old_lantern.parent = player) {
msg ("The cartridge is for use on a lantern, and you are not carrying a lantern.")
}
else if (IsSwitchedOn (old_lantern)) {
msg ("<br/>The lantern is already shining brightly; no need to use a cartridge now. <br/>")
}
else {
msg ("<br/>You put the cartridge in the lantern and it starts to glow brightly. <br/>")
SetTurnTimeout (this.lifetime) {
msg ("<br/>The lantern begins to flicker before the oil cartridge is finally used up. Moments later, the lantern dies. <br/>")
SwitchOff (old_lantern)
SetObjectLightstrength (old_lantern, "")
}
SwitchOn (old_lantern)
SetObjectLightstrength (old_lantern, "strong")
destroy (this.name)
}
]]></use>
<take />
<lifetime type="int">5</lifetime>
</object>
<exit alias="south" to="room2">
<inherit name="southdirection" />
</exit>
</object>
<object name="room2">
<inherit name="editor_room" />
<dark />
<description>The second room</description>
<darkroomdescription>This room is dark.</darkroomdescription>
<exit alias="north" to="room">
<inherit name="northdirection" />
</exit>
</object>
</asl>

Anonynn
Weird...I'm sure the code works, but when I use it and have the lantern and the oil in the inventory pane, the oil doesn't recognize that the lantern is being carried! Shenanigans.

> use oil Oil Cartridge

The cartridge is for use on a lantern, and you are not carrying a lantern.

I checked all the spellings too and they are spot on, so I'm not sure why the verb isn't registering the lantern at all.

UPDATE
:
I'm dumb....I've been copy pasting the lantern into the room for testing, so that's probably why the cartridges weren't picking it up. I'll have to check after my B-day party, but I'm pretty sure that is the cause of it not working @.@

Anonynn
Hmm...one last thing seems to be wonky. The lantern object seems to permanently acquire the "on" status. What I mean is, after you use the cartridge and the turns run out, the lantern is still registering as being lit. I tested it because I haven't a second lighting object "candle" and had them both, then dropped both in the previous room, then brought one in at a time and the lantern even without the cartridge was still brightly shining!

UPDATE:
Actually...strange enough, even if BOTH "light objects" are turned off, the dark room remains lit with one or both in the inventory, but if I hold neither in the inventory, then the dark room is dark again. What's up with that?


That code is brilliant though btw.

Anonynn
Anyone know what might be causing the lingering light issue?

sophia107
it's not actually inside any rooms at all etuicoquesamsung.com www.etuicoquesamsung.com

Anonynn
What do you mean? I know the room itself isn't causing the lighting, it's after the two light source are lit that the game registers them as being forever lit, even when both are switched off. So I'm not sure what's causing that.

UPDATE:

Figured out the problems. There was an error in the code.

if (not old_lantern.parent = player) {
msg("The cartridge is for use on a lantern, and you are not carrying a lantern.")
}
else if (IsSwitchedOn (old_lantern)) {
msg ("<br/>The lantern is already shining brightly; no need to use a cartridge now. <br/>")
}
else {
msg ("<br/>You put the cartridge in the lantern and it starts to glow brightly. <br/>")
SetTurnTimeout (this.lifetime) {
msg ("<br/>The lantern begins to flicker before the oil cartridge is finally used up. Moments later, the lantern dies. <br/>")
SwitchOff (old_lantern)
SetObjectLightstrength (old_lantern, "")
}



Must have just been an overlook, so I fixed it to this.

if (not old_lantern.parent = player) {
msg ("<br/>The cartridge is for use on a lantern, and you are not carrying a lantern.<br/>")
}
else if (IsSwitchedOn (old_lantern)) {
msg ("<br/>The lantern is already shining brightly; no need to use a cartridge now. <br/>")
}
else {
msg ("<br/>After inserting an oil cartridge into the slot, you gently close the opening and then gingerly turn the knob a few times until you hear a soft click. Moments later, a bright glow begins emitting from the old contraption. Inside, an orange flame burns brightly, which can now act as a guide through dark places. An orange glow surrounds you.<br/>")
SetTurnTimeout (this.lifetime) {
msg ("<br/>The lantern begins to flicker before the oil cartridge is finally used up. Moments later, the lantern dies. <br/>")
SwitchOff (old_lantern)
SetObjectLightstrength (old_lantern, "weak")
}
SwitchOn (old_lantern)
SetObjectLightstrength (old_lantern, "strong")
destroy (this.name)
}


I added the "SetObjectLightstrength (old_lantern, "weak"). So just a simple oversight. The item wasn't directed to weaken the lightsource after the cartridge was used up. Thank you again, Pixie!

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

Support

Forums