Occasionally you want to create items in the middle of a game, and you want some variety. Random treasure in an RPG is a good example (see
Deeper for instance). Here is a way of doing that. Just paste the code at the bottom into your own game (in code view, paste it just
before the last line, which will be "</asl>").
The way it works is you send a prototype and a location to the
ClonePrototype function, and a copy of the prototype will appear at the given location. Let us say we want lots of hats in the game. Create a prototype hat in a hidden room, and the you can place copies with this function.
ClonePrototype (hat, room)
No different to CloneObjectAndMove so far, but you can set up the prototype to give some variety to the cloned object. Firstly you can set attributes.
Random Integer AttributesIf your prototype has a string attribute that in the form "r_int_<attname>", this will set an attribute, "<attname>", as an integer. Set "r_int_<attname>" to the range (no spaces). For example, for the hat, you might set this:
hat.r_int_size = "2-5"
The first clone will get the name hat1. The system will then set hat1.size to a random number from 2 to 5.
Random String AttributesIf your prototype has a stringlist attribute that in the form "r_str_<attname>", this will set an attribute, "<attname>", as a string, randomly chosen from the string list.
hat.r_str_colour = "blue;green;red"
The system will set hat1.colour to a randomly chosen colour.
Random DescriptionSet the description (the "look" attribute) like this:
It was a [big|small|floppy] hat.
... and one of "big", "small" and "floppy" will be selected at random. Why not use the text processor? Well the random option in the text processor makes a new selection each time the text is displayed. This will just do it when the item is created; thereafter it will stay the same for that specific hat.
Or it can select from a list on any object; useful if you want the same set of options several times:
It was a [big|small|floppy] hat made of [#game.hatmaterials].
In this case, hatmaterials is a string list on the game object. You can also include attributes of the object:
It was a [big|small|floppy] hat made of [#game.hatmaterials]. It was [#colour], and size [#size].
Here it is also including the string attribute colour and the integer size set up earlier.
Random AliasIt will do the same for the alias, so you could set that like this:
[#colour] hat
Note the name and description will match, because both use the "colour" attribute set up previously.
Text Process DirectivesThere is a issue using the text processor with cloned items (whether made by this system or not) in that you do not know what the name in advance. For this, you can use #### as a stand-in for the object name. For instance:
A [#colour] hat.{if ####.size>4: It is too big for you.}{if ####.size<5: It is too small for you.}
The CodeThis is version 1.1 (23/Apr/16), and includes the text processor bit.
<function name="ClonePrototype" parameters="obj, room">
o = CloneObjectAndMove(obj, room)
foreach (att, GetAttributeNames(o, true)) {
if (StartsWith(att, "r_")) {
s = GetString(o, att)
name = Mid(att, 7)
if (StartsWith(att, "r_int_")) {
l = Split(s, "-")
if (not ListCount(l) = 2) {
error ("Failed to clone object, could not parse attribute " + att + " (" + s + ")")
}
val = GetRandomInt(ToInt(StringListItem(l, 0)), ToInt(StringListItem(l, 1)))
}
if (StartsWith(att, "r_str_")) {
val = PickOneStr(GetAttribute(o, att))
}
// msg ("setting; " + name + " with " + val)
set (o, name, val)
}
}
if (HasString(o, "look")) {
o.look = Randomise(o, "look")
}
if (HasString(o, "alias")) {
o.alias = Randomise(o, "alias")
}
</function>
<function name="Randomise" parameters="o, attname" type="string">
s = GetAttribute(o, attname)
mylist = Split (s, "[")
output = StringListItem (mylist, 0)
list remove (mylist, output)
foreach (s1, mylist) {
list1 = Split (s1, "]")
if (not ListCount (list1) = 2) {
error ("Unable to parse (no matching ]): " + s)
}
s2 = StringListItem (list1, 0)
if (StartsWith(s2, "#")) {
s2 = Mid(s2, 2)
list2 = Split (s2, ".")
if (ListCount (list2) = 1) {
extra = GetAttribute(o, StringListItem(list2, 0))
}
else if (ListCount (list2) = 2) {
obj = GetObject(StringListItem(list2, 0))
if (obj = null) {
error ("Unable to parse (could not find object in the {#...} bit): " + s2)
}
list3 = GetAttribute(obj, StringListItem(list2, 1))
if (not TypeOf(list3) = "stringlist") {
error ("Unable to parse (could not find list attribute in the {#...} bit): " + s2)
}
extra = PickOneStr(list3)
}
else {
error ("Unable to parse (the {#...} bit): " + s2)
}
}
else {
list2 = Split (s2, "|")
pos = GetRandomInt (0, ListCount (list2) - 1)
extra = StringListItem (list2, pos)
}
output = output + extra + StringListItem (list1, 1)
}
return (Replace(output, "####", o.name))
</function>
<function name="PickOneStr" parameters="lst" type="string">
if (TypeOf(lst) = "string") {
lst = Split(lst, "|")
}
index = GetRandomInt(0, ListCount(lst) - 1)
return (StringListItem(lst, index))
</function>