Expendable Resources
Storyteller
04 Jul 2013, 16:44I'm trying to make an intricate game in Quest, and I want to make sure I don't leave out any details. I've always had a soft spot for details in games, especially when they take the time to add all the details they don't really need.
Unfortunately, with my minute coding knowledge, this brings up some barriers. So, here are a few questions to get me started:
(How do I include:)
1. Flashlight batteries depleting over time when the flashlight is on.
2. The ability to make an object directly effect the attributes of another, then destroy themselves.
(Let me explain this one a bit... Instead of setting Flashlight as a container, in which I include the objects batteries, and give them a "power" attribute; I've given "Flashlight" an attribute called "Batteries" with a default integer of 5. I want this number to slowly deplete, and for the flashlight to turn off when it is at zero(if the flashlight is on.), and the option to turn the flashlight back on to temporarily disappear. I want to create another object called "Batteries," which will increase the "Batteries" integer by a value of <= 5, depending on how much is already depleted. Once the batteries are put inside the Flashlight, I want them to cease to exist in the inventory, and in the room.)
Unfortunately, with my minute coding knowledge, this brings up some barriers. So, here are a few questions to get me started:
(How do I include:)
1. Flashlight batteries depleting over time when the flashlight is on.
2. The ability to make an object directly effect the attributes of another, then destroy themselves.
(Let me explain this one a bit... Instead of setting Flashlight as a container, in which I include the objects batteries, and give them a "power" attribute; I've given "Flashlight" an attribute called "Batteries" with a default integer of 5. I want this number to slowly deplete, and for the flashlight to turn off when it is at zero(if the flashlight is on.), and the option to turn the flashlight back on to temporarily disappear. I want to create another object called "Batteries," which will increase the "Batteries" integer by a value of <= 5, depending on how much is already depleted. Once the batteries are put inside the Flashlight, I want them to cease to exist in the inventory, and in the room.)
Carrot
04 Jul 2013, 17:44I have very little coding knowledge myself, but it sound like this could be done with a counter, a timer and an if script.
There are script options to create and move objects, I don't know about destroy and I am away from my computer at the moment, so I can't check. But I find it is better to move than destroy anyway. So create an empty room with no exits and call it storage. Then in the GUI select the script that moves the object once the counter has reached its set point and move that object to the storage room.
There are script options to create and move objects, I don't know about destroy and I am away from my computer at the moment, so I can't check. But I find it is better to move than destroy anyway. So create an empty room with no exits and call it storage. Then in the GUI select the script that moves the object once the counter has reached its set point and move that object to the storage room.
Liam315
04 Jul 2013, 21:43So there are a few parts to this problem and many ways you could go about doing it. I'll go through what I would do, although others may have different suggestions that you could prefer.
First there is the problem of putting batteries inside the flashlight. I can understand not wanting to make the torch a container that would allow other objects to go in that don't belong there, but by altering the "put" command you can ensure that ONLY the batteries are able to go in. The following code is a universal command that will work for any objects you want to "couple" together. Replace the default "put" command with the following (tell me if you need help on how to replace default commands):
To implement this on a pair of objects, create 2 attributes for an object. 1 is "couple" which is a script attribute that contains the script for what you want to happen when the objects are put together. 2 is "couplekey" which is an object attribute that should refer to the 2nd object you want to couple with the first.
In your case, you would create the 2 attributes on the flashlight. couplekey you would set to be the batteries, and couple would be a script describing what you want to happen (turn the torch on, change the attributes of the torch, move/destroy the batteries etc.) Note that using this method you can still move the batteries inside the flashlight without making it a container, thus allowing you to use the conditions "if flashlight contains batteries" in your other scripts.
The script allows for a second object to be coupled (with the attributes couple2 and couplekey2), so if you had another battery object then you can make it do the same thing when the first set is depleted.
Reducing the power of the batteries I would do with a timer or turn script, linked to turning the flashlight on and off. In the options tab of the flashlight, there is "run script after turning the object on" and the same for turning off. Use this to enable/disable a script.
Turn scripts can be added in the "scripts" tab of the game object, timers by going to advanced>timers in the object tree. Your turn script would be something like
to decrease the power by 1 per turn (setting it to a much greater number than 5 would be ideal). A similar thing would be used with a timer but it's probably best that you have a play around to figure out what type would work best for your needs.
To make something happen when the power reaches 0, you simply have to include an if... script at the end of your power depletion script. e.g.
Creating a "ghost" room to move unwanted objects to as carrot suggested is a good idea. Destroying the objects entirely can lead to unforeseen errors due to the way that Quest evaluates certain commands. It also allows you to recycle the same object over and over while presenting it as a "new" object. For example the batteries die, you "throw them away" (move them to the ghost room) then move them into another room later for the player to pick up again as a fresh set.
First there is the problem of putting batteries inside the flashlight. I can understand not wanting to make the torch a container that would allow other objects to go in that don't belong there, but by altering the "put" command you can ensure that ONLY the batteries are able to go in. The following code is a universal command that will work for any objects you want to "couple" together. Replace the default "put" command with the following (tell me if you need help on how to replace default commands):
if (HasAttribute(object2, "couple") and (object2.couplekey = object1)) {
do (object2, "couple")
}
else if (HasAttribute(object2, "couple2") and (object2.couplekey2 = object1)) {
do (object2, "couple2")
}
else {
if (object1.parent = object2) {
msg (DynamicTemplate("AlreadyThere", object1))
}
else if (not ListContains(ScopeInventory(), object1)) {
msg (DynamicTemplate("NotCarrying", object1))
}
else if (not ListContains(ScopeReachable(), object1)) {
msg (DynamicTemplate("ObjectNotOpen", GetBlockingObject(object1)))
}
else if (not ListContains(ScopeReachable(), object2)) {
msg (DynamicTemplate("ObjectNotOpen", GetBlockingObject(object2)))
}
else if (not object2.container) {
msg (Template("CannotDoThat"))
}
else if (not object2.isopen) {
msg (DynamicTemplate("ObjectNotOpen", object2))
}
else {
if (GetBoolean(object2, "hidechildren")) {
object2.hidechildren = false
}
if (HasDelegateImplementation(object2, "addscript")) {
rundelegate (object2, "addscript", object1)
}
else {
object1.parent = object2
msg (Template("Done"))
}
}
}
To implement this on a pair of objects, create 2 attributes for an object. 1 is "couple" which is a script attribute that contains the script for what you want to happen when the objects are put together. 2 is "couplekey" which is an object attribute that should refer to the 2nd object you want to couple with the first.
In your case, you would create the 2 attributes on the flashlight. couplekey you would set to be the batteries, and couple would be a script describing what you want to happen (turn the torch on, change the attributes of the torch, move/destroy the batteries etc.) Note that using this method you can still move the batteries inside the flashlight without making it a container, thus allowing you to use the conditions "if flashlight contains batteries" in your other scripts.
The script allows for a second object to be coupled (with the attributes couple2 and couplekey2), so if you had another battery object then you can make it do the same thing when the first set is depleted.
Reducing the power of the batteries I would do with a timer or turn script, linked to turning the flashlight on and off. In the options tab of the flashlight, there is "run script after turning the object on" and the same for turning off. Use this to enable/disable a script.
Turn scripts can be added in the "scripts" tab of the game object, timers by going to advanced>timers in the object tree. Your turn script would be something like
Flashlight.power = Flashlight.power -1
to decrease the power by 1 per turn (setting it to a much greater number than 5 would be ideal). A similar thing would be used with a timer but it's probably best that you have a play around to figure out what type would work best for your needs.
To make something happen when the power reaches 0, you simply have to include an if... script at the end of your power depletion script. e.g.
if (Flashlight.power = 0) {
SwitchOff (Flashlight)
}
Creating a "ghost" room to move unwanted objects to as carrot suggested is a good idea. Destroying the objects entirely can lead to unforeseen errors due to the way that Quest evaluates certain commands. It also allows you to recycle the same object over and over while presenting it as a "new" object. For example the batteries die, you "throw them away" (move them to the ghost room) then move them into another room later for the player to pick up again as a fresh set.
Storyteller
04 Jul 2013, 22:08Liam315 wrote:if (Flashlight.power = 0) {
SwitchOff (Flashlight)
}
I really appreciate all of the help, but unfortunately I can read very little code... Also, when my flashlight runs out of power, and it is switched off by the script, the room stays illuminated. It only gets dark if I switch the flashlight off within the inventory.
Carrot
04 Jul 2013, 22:51Rather than run the switch off command (as switches do not miraculously flip themselves - unless it is a soft switch) use the "set brightness" script as shown in your flashlight thread.
Storyteller
04 Jul 2013, 22:58Carrot wrote:Rather than run the switch off command (as switches do not miraculously flip themselves - unless it is a soft switch) use the "set brightness" script as shown in your flashlight thread.
I'm afraid I did... It didn't work. :/
HegemonKhan
04 Jul 2013, 23:08here's some resources, might as well provides these for you now, lol:
Libraries Forum Board: viewforum.php?f=18
(maybe more) Library Downloads Page: http://quest5.net/wiki/Libraries
think of libraries as like "patches" (or even entire game engine-core code) of code that you can put into to your game, to add and~or change your game.
here's a particular library for your OP question: viewtopic.php?f=18&t=3515
extremely useful links:
http://quest5.net/wiki/Category:All_Fun ... t_Commands (1st page ~ A to S)
http://quest5.net/w/index.php?title=Cat ... h#mw-pages (2nd page ~ S to Z)
http://quest5.net/wiki/Main_Page
http://quest5.net/wiki/Tutorial
http://quest5.net/wiki/How_to
enjoy!
-------------------------------------------------------------------
While Sora's Library deals with your major questions, it might not be exactly easy to transfer it over to what you want, so for a much more simple response to your OP, echoing much of what the above poster has already said:
as far as I know, there's only two ways to deal with having many objects (without the clutter or most other isues~hassles):
actual~real physical objects: cloning
(http://quest5.net/wiki/Category:All_Fun ... t_Commands ~ Clone, CloneObject, CloneObjectAndMove)
fake objects: an integer (or double) attribute
one good example scenario of such an issue, is what to do for making a "quiver~case holding many arrows and their depletion upon firing them in your bow"
obvious, you don't want any more objects than you need (as any game will already have tons and tons of vital needed objects).
the easy answer is the integer attribute: quiver.count=50, and then just adjust that integer as needed, there's either no arrow object or only one (or a few) arrow object(s) that aren't ever actually fired~used or nor moved.
Another example, is how to deal with a shop of items~equipment~etc and their buying~selling while keeping the shop in stock.
The player needs to be able to buy (and have, take) the item~equipment, but you want the shop to still have that item~equipment in stock to be bought again, should the player need to do so (or in the case of items, like with potions, the player will want to be able to buy many of them). the best answer to this is to use clones (though there's a few issues with them), and again attributes too as well.
--------------------------
1. Flashlight batteries depleting over time when the flashlight is on.
let me introduce you to the "TURNSCRIPT" (at the top of the GUI~Editor, click on the "Add" in the horiz. bar menu at the top)
a turnscript is an ALWAYS ACTIVE~RUNNING function~script (which can be global~entire~game or for specific rooms only, just place it where you want it to be running to run that way, lol), so this is extremely useful!
now we need a game_action_counter, a "turn" integer attribute...
so, in the GUI~Editor:
Game -> Attributes (TAB) -> Add Attribute ->
Name: global_turns
Type: int (integer)
Value: 0
(if you want this to be displayed on the right pane during game play, then also create~add a status attribute, named as the same, "turn", and leave the 2nd question window that comes up blank when you create~add the status attribute, whatever it is called, lol)
now we create the turnscript, make sure it is global (when you add it from the top bar menu, have the root ~ the top left most "Object" on the left pane's "tree of stuff" be highlighted, and not a specific room):
in code:
this will cause everytime you do something in the game, to then afterwards increase our "turns" by one.
now we add what we want to this turnscript, such as your request:
(you also of course have to create~add the attributes onto the actual object too)
so, each "turn" you'll now lose one flashlight_battery: turn 0 = 5 batteries -> turn 1 = 4 batteries -> etc...
but now we need your requested conditionals too:
now, this is getting a little messy already, so let's put the entire flashlight script block into~as a function, and then we'll call that function with our turnscript:
2. The ability to make an object directly effect the attributes of another, then destroy themselves.
This is no longer relevant for what you requested based on my method, but here's how to do this stuff, if you want to (such as for other things or uses):
here's how to remove and destroy:
http://quest5.net/wiki/RemoveObject
http://quest5.net/wiki/RemoveSceneryObjects
http://quest5.net/wiki/Destroy
But, as said by the above poster, it is better to MOVE stuff to a hidden "dump" object:
this is done by creating~adding an object which is NOT a child of any room object, this is called a "Data Object".
for example:
the benefit of this is that I've got a permanent object, which is hidden (unknown) to the game player~user during game play, which I~you (the game maker) can use to attach attributes onto, and then use them in the game. your own "data storage".
so, as an example, I can use the above data object to do this:
and as for objects affecting other objects' attributes, that just uses attributes and conditionals in your scriptings
an example:
Libraries Forum Board: viewforum.php?f=18
(maybe more) Library Downloads Page: http://quest5.net/wiki/Libraries
think of libraries as like "patches" (or even entire game engine-core code) of code that you can put into to your game, to add and~or change your game.
here's a particular library for your OP question: viewtopic.php?f=18&t=3515
extremely useful links:
http://quest5.net/wiki/Category:All_Fun ... t_Commands (1st page ~ A to S)
http://quest5.net/w/index.php?title=Cat ... h#mw-pages (2nd page ~ S to Z)
http://quest5.net/wiki/Main_Page
http://quest5.net/wiki/Tutorial
http://quest5.net/wiki/How_to
enjoy!

-------------------------------------------------------------------
While Sora's Library deals with your major questions, it might not be exactly easy to transfer it over to what you want, so for a much more simple response to your OP, echoing much of what the above poster has already said:
as far as I know, there's only two ways to deal with having many objects (without the clutter or most other isues~hassles):
actual~real physical objects: cloning
(http://quest5.net/wiki/Category:All_Fun ... t_Commands ~ Clone, CloneObject, CloneObjectAndMove)
fake objects: an integer (or double) attribute
one good example scenario of such an issue, is what to do for making a "quiver~case holding many arrows and their depletion upon firing them in your bow"
obvious, you don't want any more objects than you need (as any game will already have tons and tons of vital needed objects).
the easy answer is the integer attribute: quiver.count=50, and then just adjust that integer as needed, there's either no arrow object or only one (or a few) arrow object(s) that aren't ever actually fired~used or nor moved.
Another example, is how to deal with a shop of items~equipment~etc and their buying~selling while keeping the shop in stock.
The player needs to be able to buy (and have, take) the item~equipment, but you want the shop to still have that item~equipment in stock to be bought again, should the player need to do so (or in the case of items, like with potions, the player will want to be able to buy many of them). the best answer to this is to use clones (though there's a few issues with them), and again attributes too as well.
--------------------------
1. Flashlight batteries depleting over time when the flashlight is on.
let me introduce you to the "TURNSCRIPT" (at the top of the GUI~Editor, click on the "Add" in the horiz. bar menu at the top)
a turnscript is an ALWAYS ACTIVE~RUNNING function~script (which can be global~entire~game or for specific rooms only, just place it where you want it to be running to run that way, lol), so this is extremely useful!
now we need a game_action_counter, a "turn" integer attribute...
so, in the GUI~Editor:
Game -> Attributes (TAB) -> Add Attribute ->
Name: global_turns
Type: int (integer)
Value: 0
(if you want this to be displayed on the right pane during game play, then also create~add a status attribute, named as the same, "turn", and leave the 2nd question window that comes up blank when you create~add the status attribute, whatever it is called, lol)
now we create the turnscript, make sure it is global (when you add it from the top bar menu, have the root ~ the top left most "Object" on the left pane's "tree of stuff" be highlighted, and not a specific room):
in code:
<turnscript name="global_events_or_turns_turnscript">
game.global_turns = game.global_turns + 1
</turnscript>
this will cause everytime you do something in the game, to then afterwards increase our "turns" by one.
now we add what we want to this turnscript, such as your request:
(you also of course have to create~add the attributes onto the actual object too)
<turnscript name="global_events_or_turns_turnscript">
flashlight_batteries_power_count = flashlight_batteries_power_count - 1
game.global_turns = game.global_turns + 1
</turnscript>
so, each "turn" you'll now lose one flashlight_battery: turn 0 = 5 batteries -> turn 1 = 4 batteries -> etc...
but now we need your requested conditionals too:
<turnscript name="global_events_or_turns_turnscript">
if (HasAttribute ("flashlight, "strong") = true {
if (HasAttribute (flashlight, "switchable") = true) {
if (flashlight.switchedon=true) {
if (flashlight_batteries_power_count > 0) {
flashlight_batteries_power_count = flashlight_batteries_power_count - 1
} else {
flashlight.switchedon=false // this turns off the flashlight
flashlight.switchable=false // this makes it so that you can't just turn right back on the flashlight, lol
}
}
} else (if (HasAttribute (flashlight, "switchable") = false) {
if (flashlight_batteries_power_count > 0) {
flashlight.switchable=true // this makes the flashlight able to be turned on again, but you'll still have to actually turn on the flashlight to turn it on still, lol
}
}
}
game.global_turns = game.global_turns + 1
</turnscript>
now, this is getting a little messy already, so let's put the entire flashlight script block into~as a function, and then we'll call that function with our turnscript:
<function name="flashlight_batteries_power_count_function">
if (HasAttribute ("flashlight, "strong") = true {
if (HasAttribute (flashlight, "switchable") = true) {
if (flashlight.switchedon=true) {
if (flashlight_batteries_power_count > 0) {
flashlight_batteries_power_count = flashlight_batteries_power_count - 1
} else {
flashlight.switchedon=false // this turns off the flashlight
flashlight.switchable=false // this makes it so that you can't just turn right back on the flashlight, lol
}
}
} else (if (HasAttribute (flashlight, "switchable") = false) {
if (flashlight_batteries_power_count > 0) {
flashlight.switchable=true // this makes the flashlight able to be turned on again, but you'll still have to actually turn on the flashlight to turn it on still, lol
}
}
}
</function>
<turnscript name="global_events_or_turns_turnscript">
flashlight_batteries_power_count_function // the name of the function calls (activates) the function
game.global_turns = game.global_turns + 1
</turnscript>
2. The ability to make an object directly effect the attributes of another, then destroy themselves.
This is no longer relevant for what you requested based on my method, but here's how to do this stuff, if you want to (such as for other things or uses):
here's how to remove and destroy:
http://quest5.net/wiki/RemoveObject
http://quest5.net/wiki/RemoveSceneryObjects
http://quest5.net/wiki/Destroy
But, as said by the above poster, it is better to MOVE stuff to a hidden "dump" object:
this is done by creating~adding an object which is NOT a child of any room object, this is called a "Data Object".
for example:
<asl version="540">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="Testing Game Stuff">
<gameid>d83ba5bb-2e3c-4f31-80c9-3e88a2dc082c</gameid>
<version>1.0</version>
<firstpublished>2013</firstpublished>
</game>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
</object>
<object name="global_events_data_object">
<score type="int">0</score>
<dragon_killed type="boolean">false</dragon_killed>
<race_list type="simplestringlist">human;dwarf;elf;gnome;hobbit;orc</race_list>
(etc etc etc ANY stuff)
</object>
</asl>
the benefit of this is that I've got a permanent object, which is hidden (unknown) to the game player~user during game play, which I~you (the game maker) can use to attach attributes onto, and then use them in the game. your own "data storage".
so, as an example, I can use the above data object to do this:
<asl version="540">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="Testing Game Stuff">
<gameid>d83ba5bb-2e3c-4f31-80c9-3e88a2dc082c</gameid>
<version>1.0</version>
<firstpublished>2013</firstpublished>
<start type="script">
character_creation_function
</script>
</game>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
</object>
<object name="global_events_data_object">
<score type="int">0</score>
<dragon_killed type="boolean">false</dragon_killed>
<race_list type="simplestringlist">human;dwarf;elf;gnome;hobbit;orc</race_list>
(etc etc etc ANY stuff)
</object>
<function name="character_creation_function">
show menu ("What is your race?", global_events_data_object.race_list, false) {
player.race=result
}
</function>
</asl>
and as for objects affecting other objects' attributes, that just uses attributes and conditionals in your scriptings
an example:
<object name="healing_potion">
<verb name="drink">
<script><![CDATA[
if (player.healing_potion_count > 0) {
player.hp = player.hp + 50
player.healing_potion_count = player.healing_potion_count - 1
} else {
msg ("You don't have any more healing potions.")
}
]]><script>
</verb>
</object>
Storyteller
05 Jul 2013, 00:05 play sound ("flon.wav", false, false)
SetObjectLightstrength (fl1, "strong")
EnableTimer (Batteries)
SetTimerScript (Batteries) {
set (fl1, "batteries", fl1.batteries - 1)
if (fl1.batteries = 0) {
DisableTimer (Batteries)
msg ("The batteries in your flashlight have run out.")
SwitchOff (fl1)
SetObjectLightstrength (fl1, "")
SetDark (player.parent)
}
}
The room remains illuminated, whilst the flashlight is supposedly off.
If I activated this next batch of code, the room becomes dark, and it works fine.
play sound ("floff.wav", false, false)
DisableTimer (Batteries)
SetObjectLightstrength (fl1, "")
HegemonKhan
05 Jul 2013, 00:15not sure why it's not working...
is your last code, using that and not your longer code above, working correctly? is this what you're saying?
maybe you could try to put the "disabletimer" at the end of your timer if script:
you may also, still need your turnscript, with the turns attribute too... for this to work
is your last code, using that and not your longer code above, working correctly? is this what you're saying?
maybe you could try to put the "disabletimer" at the end of your timer if script:
play sound ("flon.wav", false, false)
SetObjectLightstrength (fl1, "strong")
EnableTimer (Batteries)
SetTimerScript (Batteries) {
set (fl1, "batteries", fl1.batteries - 1)
if (fl1.batteries = 0) {
msg ("The batteries in your flashlight have run out.")
SwitchOff (fl1)
SetObjectLightstrength (fl1, "")
SetDark (player.parent)
DisableTimer (Batteries)
}
}
you may also, still need your turnscript, with the turns attribute too... for this to work
Carrot
05 Jul 2013, 08:55Silly question, but is the dark box checked for the room being initially dark? It could be that you have created a room that isn't dark and not realised, hence why you need to SetDark (player.parent) - I don't think you should need to set that if your rooms have had the dark box checked?
Storyteller
05 Jul 2013, 17:57Carrot wrote:Silly question, but is the dark box checked for the room being initially dark? It could be that you have created a room that isn't dark and not realised, hence why you need to SetDark (player.parent) - I don't think you should need to set that if your rooms have had the dark box checked?
The room IS set to be initially dark. And, it's alright. It was suggested to me to try setting the room to dark, because when the battery in the flashlight runs it, it isn't make the room dark again.