Complex Wind

Let's start with requiring someone to be holding the duck in order to wind it. We take the code from before, and stick an if/else around it.

@program $windup_toy.wind_cmd() +access=pub
  arg cmdstr, cmd, @args;
  
  if (.location() == sender()) {
    wound += 2;
    sender().tell("You wind up the " + .name() + ".");
    .location().announce(strfmt("%s winds up the %s.", sender().name(), .name()));
  } else {
    sender().tell("You have to be holding the " + .name() + ".");
  }
.

.location() is where the toy is now. If it is in the player's inventory then .location() will be equal to the value of sender() (which is the player who initiated the command that called this method).

Let's complicate the code once more, and then we'll be done with the wind_cmd method. We should have a maximum number of turns the toy will allow, otherwise a malicious player could spend a few hours winding the toy, and then unleash it on an unsuspecting public. If we wanted to be really fancy, we could make the toy break if they wound it too far, and require them to repair it with a screwdriver (which we would create for the purpose), but let's leave that as an exercise for the reader.

We might want different toys to have different maximum wind amounts, so we should have a way to indicate how many winds any given toy can take. One might assume we should use an object variable for this, but here's the problem: if we define a variable on $windup_toy, our windup duck will have that variable, but we won't have any easy way of setting the maximum winds of the duck because of encapsulation and the way that variable inheritance works.

Instead, we will use ColdCore settings. A setting is like an object variable, but both the setting itself and its value is inherited from the parent object to the child object. This way, if you set maximum-winds on $windup_toy to 20, then the windup duck will automatically have a default maximum-winds of 20 -- but you can also change the setting on the windup duck itself using the @set command.

@def-setting $windup_toy:maximum-winds=20 +type='integer
-- Defined setting $windup_toy:maximum-winds as:
    +parse=is_type
    +parse-args=integer
-- Default Setting:
  maximum-winds = 20
--

If you ever wanted to change maximum-winds on $windup_toy or even your windup duck, you would use the @set command. Remember if you have not changed the setting on the windup duck, but you change it on $windup_toy, then the duck will inherit the setting of $windup_toy. However, if you change the setting on just your windup duck, then only the duck will be affected and new $windup_toy children will inherit $windup_toy's maximum-winds.

@set $windup_toy:maximum-winds=30

or

@set hduck:maximum-winds=30

Now we insert another set of if/elses inside our current set.

@program $windup_toy.wind_cmd() +access=pub
  arg cmdstr, cmd, @args;
  var max_winds;
  
  max_winds = toint(.get_setting("maximum-winds", $windup_toy));
  
  if (.location() == sender()) {
    if (wound < max_winds) {
      wound += 2;
      sender().tell("You wind up the " + .name() + ".");
      .location().announce(strfmt("%s winds up the %s.", sender().name(), .name()));
	  if (wound >= max_winds)
	    sender().tell("The knob comes to a stop while winding.");
	} else {
	  sender().tell("The " + .name() + " is already fully wound.");
	}
  } else {
    sender().tell("You have to be holding the " + .name() + ".");
  }
.

Notice that we retrieve the maximum-winds setting using the .get_setting() method. When using .get_setting(), you have to pass the name of the setting you want, as well as the object it was originally defined on. Also note then that we make sure the setting we get is converted to an integer with the built-in function toint().

In order to add to the feel of the toy, we put in another test: if, after adding 2 to the wound variable, it has reached the maximum, we tell the player they've come to the end. The more completely you can describe an object's actions and responses to actions, the richer the feel of the Virtual Reality.