I am really lost on this one. Here's what I did so far.
Create an object called vitamin.
Gave vitamin an attribute called "quantity."
Created a spawn function that generates object when entering a room.
Where I'm having issue is with the TAKE and DROP actions. Once I TAKE the item twice, Quest is asking the player to select which vitamin from a numbered list.
Which "vitamin"?
I really only want this to be a single category and to be able to display the quantity of the object (in this case, the vitamin) into a integer.
There are many ways to do stacking. If you already have a "quantity" attribute, I'd recommend destroying any duplicates.
If you're creating your stackable object using CloneObject
and similar functions (not create
or clone
), it will already have a prototype
attribute pointing to the original. You can use this attribute to check if any other clones of the same object are in the same location.
So your code would look something like:
For the "when this object is moved" function, I would suggest using the script attribute changedparent
, which is run automatically whenever an object is moved. This covers the case of picking up an object you already have one of, and dropping one where another is already there.
The changedparent
function could look like:
if (HasObject (this, "parent")) {
clones = FilterByAttribute (GetDirectChildren (this.parent), "prototype", this.prototype)
if (ListCount (clones) > 1) {
first = ListItem (clones, 0)
second = ListItem (clones, 1)
first.quantity = first.quantity + second.quantity
second.quantity = 0
}
}
This means that a stack of 5 and a stack of 3 will turn into a stack of 8 and a stack of 0.
Then you can use a script attribute named changedquantity
to remove the 0 and make it easy to see how many you have:
if (this.quantity = 0) {
destroy (this.name)
}
else if (this.quantity = 1) {
this.alias = "vitamin"
this.listalias = "vitamin"
}
else {
this.alias = this.quantity + " vitamins"
this.listalias = this.quantity + " vitamins"
}
Changescripts (script attributes starting with changed
) are run by the engine automatically whenever the corresponding attribute changes, so they're good for stuff like this. When the player uses a vitamin, the use script can just reduce its quantity, and trust the changescript to destroy it if that was the last one.
It may also be worth noting that there's sometimes problems with using destroy
, so most people use RemoveObject
instead. But RemoveObject just moves objects outside of any room, so they'll still be there taking up memory and bloating the save file, which can be a problem if you're spawning a lot of these objects. So if destroy
doesn't behave, it might be better to work around it by delaying the destruction of unwanted objects until the end of the turn. Like this:
if (this.quantity <= 0) {
if (HasAttribute (game, "objects_to_destroy")) {
list add (game.objects_to_destroy, this.name)
}
else {
game.objects_to_destroy = Split (this.name)
SetTurnTimeout (0) {
if (HasAttribute (game, "objects_to_destroy")) {
foreach (objname, ListCompact (game.objects_to_destroy)) {
destroy (objname)
}
game.objects_to_destroy = null
}
}
}
}
else if (this.quantity = 1) {
this.alias = "vitamin"
this.listalias = "vitamin"
}
else {
this.alias = this.quantity + " vitamins"
this.listalias = this.quantity + " vitamins"
}
(I used "vitamins" as the object name because that's the example you gave. If you have lots of stackable objects, it might be easier to have attributes for the singular and plural aliases, so you can use the same scripts for all of them, or make it a function)
The Pixie also created a library for stacking objects if you want to browse/use that system. https://github.com/ThePix/quest/wiki/Library:-Stackable-items
(My favourite method of stacking is not to use a quantity; instead, the stacked objects are placed inside the first one. So you have an object named "four vitamins" which contains objects named "three vitamins", "two vitamins", and "vitamin". Then you can mess around with the background scope script to make the inside objects accessible for commands without them showing up separately on the inventory; so that "drop vitamin" and "drop two vitamins" all work how you would expect; but "drop vitamins" causes the disambiguation menu to ask how many you want to drop. This can be a bit of a pain to implement, but I think it's worth it if you can get your head around the code)
Mrangel, how do you drop two vitamins, without having still four vitamins in inventory?
Mrangel, how do you drop two vitamins, without having still four vitamins in inventory?
In this example, you would have the changedparent script do something like (pseudocode):
Doing the changedparent scripts of both stacks ensures that the numbers are always right.
[Think that's right off the top of my head]