Overriding core commands and verbs.

In my project the player can die, but instead of ending the game the player effectively becomes a ghost. He can walk around, look at things but cannot, for example, take things or smell things.

With core commands (i.e take) I can copy them to my project and add a check to the script.

With core verbs (i.e smell) I can copy them and make the script editable, in attributes and add a check there.

My question is: Is this the best way to achieve what I want or is there an easier way of overriding commands and verbs under certain conditions.


That seems like a fairly common way to do it. There are two other options that come to mind; which one is easiest will depend on your use cases.

  1. Commands that are in a room override global commands, but only apply when the player is in that room. So you could create a separate set of ghost commands for when the player is dead, and put them in an unreachable room somewhere (like a holding area)
    When the player dies, you would move those commands to be global (cmd.parent = null), and either move the standard commands to the holding area, or destroy them.

  2. You could give some commands an extra script attribute for its behaviour when the player is dead; call it ghost_script. Then when the player dies:

    foreach (cmd, AllCommands()) {
    if (HasScript (cmd, "ghost_script")) {
    cmd.script = cmd.ghost_script
    }
    }

  3. If you're just disabling commands:

    foreach (cmdname, Split("take;put;push;open;close;kick;use;eat")) {
    cmd = GetObject(cmdname)
    cmd.script => {
    msg ("You can't do that, you're dead.")
    }
    }

Which one works best for you will likely depend on how many commands are involved, and how much change you want to make to them.

If you can come back to life after being a ghost, you could save the original behaviour in a separate script attribute.
For example, when the player dies you could run:

foreach (cmdname, Split("take;put;push;open;close;kick;use;eat")) {
  cmd = GetObject(cmdname)
  cmd.alive_script = cmd.script
  cmd.script => {
    msg ("You can't do that, you're dead.")
  }
}

and when they come back to life:

foreach (cmd, AllCommands()) {
  if (HasScript (cmd, "alive_script")) {
    cmd.script = cmd.alive_script
  }
}

It's also worth noting that verbs are also commands: they just all have the same script (which is inherited from the defaultverb type), which just checks if the target object has a script for that verb, and runs it. So the above method with Split("list of command names") works fine with verbs. This could end up being a lot quicker than including a check on every object that has a verb.

If you're doing more fancy things - for example, a ghost might be able to see some kind of spiritual aura around an object as well as looking at it normally, you could add something like:

lookat.alive_script = lookat.script
lookat.script => {
  do (this, "alive_script", game.pov.currentcommandresolvedelements)
  if (HasScript (object, "ghostlook")) {
    do (object, "ghostlook")
  }
  else if (HasString (object, "ghostlook")) {
    msg (object.ghostlook)
  }
}

By using do (this, "alive_script", game.pov.currentcommandresolvedelements) you can execute extra functions before (or after) the command's default behaviour, such as displaying an extra description. And because it uses the same alive_script attribute as the script above, it will work like magic with the "coming back to life" script above.


Thanks mrangel, disabling commands is effectively what I'm doing so your third option looks like it will work best.

Thanks for the other examples.

do (this, "alive_script", game.pov.currentcommandresolvedelements)

I can definitely make use of this. thanks again.


Log in to post a reply.

Support

Forums