Cloning Problem

Hi all,

I was initially helped out by mrangel on the following thread:
http://textadventures.co.uk/forum/quest/topic/edt56jljtuqcchq2g_cazq/multiple-objects-numbered-description

I now want help with another problem that I cannot simply get my head around.

I will use the same object as the the previous thread for simplicity using 'Heavy Ball'. I now want four such 'Heavy Balls' in different locations specified as follows.

Object: Heavy_Ball1 - Alias: heavy ball
Object: Heavy_Ball2 - Alias: heavy ball
Object: Heavy_Ball3 - Alias: heavy ball
Object: Heavy_Ball4 - Alias: heavy ball

Scenario 1
The balls are still too heavy to carry all at once. My problem is when I'm carrying 'Heavy_Ball1' for instance and drop it where 'Heavy_Ball2' is located, I want it to read '2 balls'.

Scenario 2
The balls are now light enough that the player can now carry all four balls, (probably having drunk a secret magic potion brewed by a druid found in Gaul, still holding out against the romans (I digress)). So the inventory will have to say that you are carrying 4 balls(or however many you are carrying). Also again, if the player was to drop one of the balls where another ball is located, I want it to read you can see 2 balls, or whatever.

If anyone can help, it would be much appreciated.


I think if you haven't got a special case for being carried, you don't need a non-stacked ball object. So every object in this case is now a pile, even if it's a pile of 1 ball.

A lot of the difference here will be whether you want the player to take/drop one ball at a time, or all of them. I think the simplest way to implement it would be to have the basic commands moving the whole pile. So, you'd check if there's already balls at the target location, and if so merge the two piles together. So the changedparent script would be:

piles = FilterByAttribute (GetDirectChildren (this.parent), "prototype", this.prototype)
list remove (piles, this)
if (ListCount (piles) > 0) {
  pile = ListItem (piles, 0)
  this.count = this.count + pile.count
  pile.count = 0
}

In this case, when two piles/balls are moved into the same location I'm destroying the other one rather than 'this', in order to avoid the foreach bug with destroying objects.

Then we have the changedcount script:

if (this.count = 0) {
  destroy (this.name)
}
else if (this.count = 1) {
  this.alias = "heavy ball"
}
else {
  this.alias = this.count + " balls"
}

For separating the piles, you could add "take one" and "drop one" verbs.
Something like take one:

if (not ListCountains (ScopeReaachable(), this)) {
  msg ("You can't reach it.")
}
else if (this.count = 1) {
  this.parent = game.pov
}
else {
  piles = FilterByAttribute (GetDirectChildren (game.pov), "prototype", this.prototype)
  if (ListCount (piles) = 0) {
    CloneObjectAndMove (this.prototype, game.pov)
  }
  else {
    pile = ListItem (piles, 0)
    pile.count = pile.count + 1
  }
  this.count = this.count - 1
}

and for drop one, you'd have:

destination = game.pov.parent
if (not ListCountains (ScopeReaachableInvantory(), this)) {
  msg ("You aren't carrying it, or it's in a box.")
}
else if (this.count = 1) {
  this.parent = destination
}
else {
  piles = FilterByAttribute (GetDirectChildren (destination), "prototype", this.prototype)
  if (ListCount (piles) = 0) {
    CloneObjectAndMove (this.prototype, destination)
  }
  else {
    pile = ListItem (piles, 0)
    pile.count = pile.count + 1
  }
  this.count = this.count - 1
}

(in this case, you would have an original 'ball' object somewhere that the player can't reach it, and any others would have their prototype attribute set to that one; if you create them by cloning the original, this will be done automatically)

There are other ways to do it. My favourite is having multiple objects. So if you have 3 balls in a room, they are named "3 balls", "2 balls", and "ball"; and "2 balls" and "ball" are scenery so they don't show up in the objects list. This means that the player can still type "get 2 balls" if they want to, and it works mostly intuitively. Then, the changedparent script just needs to check for any in the same location with a lower number, move them too, and then change the aliases; no need to create or destroy extra clones. But that system is a bit weird, and I think most people around here didn't like it when I mentioned it in the past.


Edit: Sorry, I think I misread your post.

Reimplementing the "too heavy to carry more than one" thing wouldn't be too hard. Two ways to do that spring to mind.

Simplest, just make a 'take' script:

if (player.can_carry_multiple_balls) {
  msg ("You pick them up.")
  this.parent = game.pov
}
else {
  piles = FilterByAttribute (ScopeInventory(), "prototype", this.prototype)
  if (ListCount (piles) = 0 and this.count = 1) {
    // there's only one ball here, so just move it
    this.parent = game.pov
    msg ("You pick it up.")
  }
  else if (ListCount (piles) = 0) {
    // the player doesn't have one, but there's multiple here
    msg ("You manage to lift one of the heavy balls.")
    CloneObjectAndMove (this.prototype, game.pov)
    this.count = this.count - 1
  }
  else {
    // the player already has one
    msg ("You can't carry more than one of these.")
  }
}

In the later case, where the player has gained the ability to lift more, it might be better to change the displayed verbs. So the changedcount script would be something like:

if (HasAttribute (this, "generatedverbslist")) {
  if (ListCountains (this.generatedverbslist, "take one")) {
    list remove (this.generatedverbslist, "take one")
  }
  if (ListCountains (this.generatedverbslist, "drop one")) {
    list remove (this.generatedverbslist, "drop one")
  }
}
firsttime {
  this.displayverbs = this.displayverbs
  this.inventoryverbs = this.inventoryverbs
}
if (this.count = 0) {
  destroy (this.name)
}
else if (this.count = 1) {
  this.gender = "it"
  this.article = "it"
  this.possessive = "its"
  this.usedefaultprefix = true
  this.alias = "heavy ball"
  if (ListCountains (this.displayverbs, "take one")) {
    list remove (this.displayverbs, "take one")
  }
  if (ListCountains (this.inventoryverbs, "drop one")) {
    list remove (this.inventoryverbs, "drop one")
  }
}
else {
  this.gender = "they"
  this.article = "them"
  this.possessive = "their"
  this.usedefaultprefix = false
  this.prefix = this.count
  this.alias = "heavy balls"
  if (not ListCountains (this.displayverbs, "take one")) {
    list add (this.displayverbs, "take one")
  }
  if (not ListCountains (this.inventoryverbs, "drop one")) {
    list add (this.inventoryverbs, "drop one")
  }
}

Not sure if I fully understand the changedparent and changedcount scripts listed above.

I've created 4 objects; 'Heavy_Ball', numbered 1 - 4. Heavy_Ball1, Heavy_Ball2, etc. All with the same alias, 'heavy ball'.
Then each of those four objects, has the changedparent and the changedcount script. I'm also running the objects initialisation script and setting this.count = 1. Then each of the four Heavy_Ball objects has the same take script listed above.

I must be doing something wrong. I'm able to pick up all the objects and drop them all in the same place, but they are listed;
You see a heavy ball, a heavy ball, a heavy ball and ...


Have you set the prototype?

It's used to keep track of objects that are the same. If you create them manually, you'll need to set the prototype too.

An alternative would be replacing prototype with alias in all the scripts, which should work in your case. (but if you clone one, you'd have to change that)


I set the prototype on all of them.


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

Support

Forums