[Solved] Problems running custom commands with other scripts

chaosp
19 Jan 2018, 04:12

Hi bit of a beginner here and I'm stuck trying to get custom commands running with other scripts. For example I have a custom command fight with the command pattern fight #object# which initiates the very basic combat system I have made. This works fine when I have the player input "fight orc" for example, but I would like to have combat initiated at other times, eg the player enters a room and a script starts the fight process automatically.

I have tried using the do script so that when a player enters the room the script runs (do (orc, "fight") for example) but that produces an "Object reference not set to an instance of an object" error. Is there a way to replicate the player typing "fight orc" using a script?

Many thanks for your help.


hegemonkhan
19 Jan 2018, 04:40

(filler for getting my edited post, updated/posted)


HK edit: changed the 'do (XXX)' to 'rundelegate (XXX)' for the 2nd code sample, which uses Objects+Script_Attribute+Delegate, as I forgot to switch it over until just now (sorry about that).


there's probably a way to do/call/use/activate a Command, but I'm not sure how it's done... others may be able to help you with it... you can try this...

(replace my upper-case with your coding's labeling/naming)

do (NAME_OF_COMMAND, "script")
// or:
do (NAME_OF_COMMAND, "script", NAME_OF_MONSTER)


alternative methods would be to have your 'fight' Command's scripting be within either: a Function or an Object+Script_Attribute+(optional: Delegate):

simple example (using a Function):

<object name="room">
</object>

<object name="player">
  <inherit name="editor_object" />
  <inherit name="editor_player" />
  <attr name="parent" type="object">room</attr>
</object>

<object name="orc">
  <inherit name="monster_type" />
  <attr name="parent" type="object">room</attr>
</object>

<object name="ogre">
  <inherit name="monster_type" />
  <attr name="parent" type="object">room</attr>
</object>

<type name="monster_type">
  <attr name="fight" type="script">
    fight_function (this)
  </attr>
</type>

<command name="fight_command">
  <pattern>fight #object#</pattern>
  <script>
    fight_function (object)
  </script>
  <unresolved>Error: Object not found within the current room</unresolved>
</command>

<function name="fight_function" parameters="enemy_object_parameter">
  // your fight function's scripting using 'enemy_object_parameter'
</function>

<verb>
  <property>fight</property>
  <pattern>fight</pattern>
  <defaultexpression>You can't fight that!</defaultexpression>
</verb>

simple example (using an: Object + Script Attribute + Delegate):

<delegate name="fight_delegate" parameters="enemy_object_parameter" />

<game name="example_game">
</game>

<object name="room">
</object>

<object name="player">
  <inherit name="editor_object" />
  <inherit name="editor_player" />
  <attr name="parent" type="object">room</attr>
</object>

<object name="orc">
  <inherit name="monster_type" />
  <attr name="parent" type="object">room</attr>
</object>

<object name="ogre">
  <inherit name="monster_type" />
  <attr name="parent" type="object">room</attr>
</object>

<object name="fight_object">
  <attr name="fight_script_attribute" type="fight_delegate">
    // your fight scripting using 'enemy_object_parameter'
  </attr>
</object>

<type name="monster_type">
  <attr name="fight" type="script">
    rundelegate (fight_object, "fight_script_attribute", this)
  </attr>
</type>

<command name="fight_command">
  <pattern>fight #object#</pattern>
  <script>
    rundelegate (fight_object, "fight_script_attribute", object)
  </script>
  <unresolved>Error: Object not found within the current room</unresolved>
</command>

<verb>
  <property>fight</property>
  <pattern>fight</pattern>
  <defaultexpression>You can't fight that!</defaultexpression>
</verb>

K.V.
19 Jan 2018, 04:43

It's not a clone of an orc, is it?


chaosp
19 Jan 2018, 05:00

Thank you for your quick reply. I tried the variations of thedo (NAME_OF_COMMAND, "script") you suggested but no luck. I think the idea of putting the fight scripting into a function is probably the way to go (I've not had any experience with Object+Script_Attribute+(optional: Delegate)).

Thanks again, I'll post back if I get the function version working.


chaosp
19 Jan 2018, 05:03

Hi K.V, no it's unique orc (eg orc1). I've tried with other objects as well and still have the same problem.


K.V.
19 Jan 2018, 05:05

See if this example game helps you.

I am cloning an orc, but the script will work on the original orc as well. (So, it doesn't matter if you're using clones or not.)

<!--Saved by Quest 5.8.6590.33649-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Orc Fight">
    <gameid>c92ed3ee-24d4-4aac-ba77-e3de5d58a7ff</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <beforeenter type="script">
      clone = CloneObjectAndMoveHere(orc)
      clone.proto = orc
      clone.alias = "orc clone"
    </beforeenter>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="orc">
      <inherit name="editor_object" />
      <look type="script">
        if (HasAttribute(this,"fallen") and GetBoolean(this,"fallen")) {
          msg ("The orc is out cold.")
        }
        else {
          msg ("The orc looks like it wants to {command:fight orc:fight}!")
        }
      </look>
      <fight type="script"><![CDATA[
        if (HasAttribute(this,"fallen") and GetBoolean(this,"fallen")) {
          msg ("The orc is already down.")
        }
        else {
          msg ("You attack the orc.")
          if (RandomChance(75)) {
            msg ("<br/>The orc falls.")
            this.alias = "fallen orc"
            this.fallen = true
          }
        }
      ]]></fight>
    </object>
  </object>
  <command name="fight_cmd">
    <pattern>fight #object#</pattern>
    <unresolved>You can't fight something that isn't here.</unresolved>
    <script>
      if (HasAttribute(object,"fight")) {
        do (object, "fight")
      }
      else {
        msg ("You can't fight "+object.article+".")
      }
    </script>
  </command>
</asl>

chaosp
19 Jan 2018, 05:24

Thank you for everyone's help, I managed to get it working (as hegemonkhan suggested) by moving my fight script from the custom command fight to a function, and then calling the function whenever I needed to initiate combat. Thank you both for you sample game codes, I've learned lots from going through them!


The Pixie
19 Jan 2018, 09:17

Thank you for your quick reply. I tried the variations of the do (NAME_OF_COMMAND, "script") you suggested but no luck. I think the idea of putting the fight scripting into a function is probably the way to go (I've not had any experience with Object+Script_Attribute+(optional: Delegate)).

The problem with do (NAME_OF_COMMAND, "script") is that the object variable has not been set. Commands do this behind the scenes, from the command pattern #object#.

However, you can do that by sending a dictionary.

d = NewDictionary()
dictionary add (d, "object", orc)
do (NAME_OF_COMMAND, "script", d)

All that said, doing it as a function is probably easier!


hegemonkhan
19 Jan 2018, 16:04

ah, so you use a Dictionary for the Object's setting, for using a Command, thank you Pixie! (need to save/bookmark/favorite this post, lol)


K.V.
19 Jan 2018, 16:27

I've been following Pixie's Zombie Apocalypse guide*, and I wish I'd have read these last two posts before I fooled with it today.

I just fought that battle with do, and trying to pass the object variable to it did not work out. So, like Pix suggested here, I ended up using a function.

  <command name="reload_command">
    <pattern>reload</pattern>
    <script>
      if (HasAttribute(game.pov,"equipped")) {
        if (HasAttribute(game.pov.equipped,"ammo")) {
          object = game.pov.equipped
          if (game.debugging) {
            DbgMsg ("reload script: setting object to "+object)
          }
          ReloadIt (object)
        }
        else {
          msg ("You don't have that sort of a weapon equipped.")
        }
      }
      else {
        msg ("You haven't equipped a weapon.")
      }
    </script>
  </command>
  <command name="reload_object_cmd">
    <pattern>reload #object#</pattern>
    <script>
      ReloadIt (object)
    </script>
  </command>
  <type name="region_type" />
  <type name="room_type" />
  <function name="ReloadIt" parameters="object"><![CDATA[
    if (game.debugging) {
      DbgMsg ("ReloadIt: object = "+object)
    }
    if (not HasInt(object, "ammo")) {
      msg ("You can't reload a " + GetDisplayAlias(player.equipped) + ".")
    }
    else if (player.ammo < 1) {
      msg ("You have no ammo.")
    }
    else {
      bullets = object.ammomax - object.ammo
      if (bullets > player.ammo) {
        bullets = player.ammo
      }
      player.ammo = player.ammo - bullets
      object.ammo = object.ammo + bullets

      if (bullets > 0){
        msg ("You put " + bullets + " bullets in it.")
      }
      else {
        msg("You can't fit any more bullets in it.")
      }
    }
    WeaponUpdate
  ]]></function>

* Scripts from Pixie's guide are slightly modified.


REVISED SCRIPTS (just for archival purposes):

<command name="reload_cmd">
    <pattern>reload #object#;load #object#;reload;reload</pattern>
    <script>
      if (not IsDefined("object")) {
        if (HasAttribute(game.pov,"equipped")) {
          if (HasAttribute(game.pov.equipped,"ammo")) {
            object = game.pov.equipped
            if (game.debugging) {
              DbgMsg ("reload script: setting object to "+object)
            }
            ReloadWeapon (object)
          }
          else {
            msg ("You don't have that sort of a weapon equipped.")
          }
        }
        else {
          msg ("You have no weapon equipped.")
        }
      }
      else {
        if (HasAttribute(object,"ammo")) {
          ReloadWeapon (object)
        }
        else {
          msg ("You can't reload "+object.article+".")
        }
      }
    </script>
  </command>
<function name="ReloadWeapon" parameters="object"><![CDATA[
    if (game.debugging) {
      DbgMsg ("ReloadWeapon: object = "+object)
    }
    if (not HasInt(object, "ammo")) {
      msg ("You can't reload a " + GetDisplayAlias(player.equipped) + ".")
    }
    else if (player.ammo < 1) {
      msg ("You have no ammo.")
    }
    else {
      cartridges = object.ammomax - object.ammo
      if (cartridges > player.ammo) {
        cartridges = player.ammo
      }
      player.ammo = player.ammo - cartridges
      object.ammo = object.ammo + cartridges
      if (cartridges = 1) {
        msg (cartridges + " cartridge:  Loaded.")
      }
      if (cartridges > 1) {
        msg (cartridges + " cartridges:  Loaded.")
      }
      else {
        msg (object.article+" is fully loaded.")
      }
    }
    WeaponUpdate
  ]]></function>

K.V.
20 Jan 2018, 16:30

Today MrAngel taught me how to use IsDefined() properly, and I devised a dirty way to use do() to invoke a script with the local variable object in it.

You can enter SLAP or SLAP #object#.

Example game:

<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="SLAP">
    <gameid>f187b2c5-6dad-48ee-991c-7c5d401a782b</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <defaultwebfont type="string"></defaultwebfont>
    <start type="script">
      SetWebFontName ("Patrick Hand")
      SetWebFontName (game.defaultfont)
    </start>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
      <object name="nametag">
        <inherit name="editor_object" />
        <ondrop type="script">
        </ondrop>
        <take />
        <look type="script"><![CDATA[
          msg ("It reads:<br/><center><br/><div style=';border:1px solid black'><span style='font-weight:bold;font-size:110%'>Hello!  My name is:<span style='font-family:\"Patrick Hand\";font-size:135%;'><hr style='border-top:1px solid black' />XanMag</span></span></div></center>")
        ]]></look>
        <feature_usegive />
        <giveto type="scriptdictionary">
          <item key="XanMag">
            MoveObject (this, XanMag)
            msg ("\"Thanks!\"  says XM.  \"I've been looking for that!\"")
            this.alias = "nametag (worn)"
            this.take = false
            this.takemsg = "\"Leave my nametag alone, please,\" says XM."
          </item>
        </giveto>
        <alt type="stringlist">
          <value>tag</value>
        </alt>
        <inventoryverbs type="stringlist">
          <value>Look at</value>
          <value>Wear</value>
          <value>Drop</value>
        </inventoryverbs>
      </object>
    </object>
    <object name="XanMag">
      <inherit name="editor_object" />
      <inherit name="namedmale" />
      <inherit name="surface" />
      <look>He's drinking a beer.</look>
      <feature_container />
      <listchildren />
      <contentsprefix>who is carrying</contentsprefix>
      <addscript type="script">
        msg ("\"Get that off me!\" booms XanMag.{once:  He slaps you.}")
      </addscript>
      <listchildrenprefix>He is carrying</listchildrenprefix>
      <take />
      <alt type="stringlist">
        <value>xm</value>
      </alt>
      <speak>{random:"Hello," grumbles Xan.:"I like fish tacos," he says.:"Beer is good," says XM.}</speak>
    </object>
  </object>
  <command name="slap_cmd">
    <pattern>slap</pattern>
    <script>
      if (XanMag.parent = game.pov.parent) {
        do (slap_it_cmd, "script")
      }
      else {
        msg ("XanMag's not here, man!")
      }
    </script>
  </command>
  <command name="slap_it_cmd">
    <pattern>slap #object#</pattern>
    <script><![CDATA[
      if (not IsDefined("object")) {
        object = XanMag
      }
      if (object = XanMag) {
        msg ("You slap XanMag.<br/><br/>He takes a drink of his beer, laughs, then says, \"thank you, sir!  May I have another?\"")
      }
      else {
        msg ("You can't slap "+object.article+".")
      }
    ]]></script>
  </command>
  <command name="wear_cmd">
    <pattern>wear #object#</pattern>
    <script>
      if (object = nametag) {
        msg ("That appears to belong to XanMag.")
      }
      else {
        msg ("You can't wear "+object.article+".")
      }
    </script>
  </command>
</asl>

hegemonkhan
20 Jan 2018, 21:24

not quite however, as you can't dynamically get/pass/insert a value for the 'object' variable from the 'do' function call.

looks like the only way is via using a Dictionary as the argument's/parameter's value


K.V.
20 Jan 2018, 23:10

not quite however

I said it was dirty...

...but I am using do() to call a script which uses the object variable without passing it.

  <command name="slap_cmd">
    <pattern>slap</pattern>
    <script>
      if (XanMag.parent = game.pov.parent) {
        do (slap_it_cmd, "script")
      }
      else {
        msg ("XanMag's not here, man!")
      }
    </script>
  </command>
  <command name="slap_it_cmd">
    <pattern>slap #object#</pattern>
    <script><![CDATA[
      if (not IsDefined("object")) {
        object = XanMag
      }
      if (object = XanMag) {
        msg ("You slap XanMag.<br/><br/>He takes a drink of his beer, laughs, then says, \"thank you, sir!  May I have another?\"")
      }
      else {
        msg ("You can't slap "+object.article+".")
      }
    ]]></script>
  </command>

K.V.
21 Jan 2018, 00:07

How about creating a temporary attribute?

(Yes. I'm bored.)

<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Do things">
    <gameid>c4a82a07-95b9-4641-9e1e-4975aa275c51</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="puddle">
      <inherit name="editor_object" />
      <displayverbs type="stringlist">
        <value>Look at</value>
      </displayverbs>
      <jumpable />
    </object>
  </object>
  <command name="jump_over_it_cmd">
    <pattern>jump over #object#</pattern>
    <script>
      if (not IsDefined("object")) {
        if (TypeOf(game.tempobject)="object") {
          object = game.tempobject
        }
        else {
          msg ("You can't do that.")
          return (false)
        }
      }
      if (HasBoolean(object,"jumpable")) {
        if (object.jumpable) {
          msg ("You jump over "+object.article+".")
        }
        else {
          msg ("You can't jump over "+object.article+".")
        }
      }
      else {
        msg ("You can't do that.")
      }
    </script>
  </command>
  <command name="jump_over_cmd">
    <pattern>jump over</pattern>
    <script><![CDATA[
      thingstojump = NewObjectList()
      foreach (o, ScopeVisibleNotHeld()) {
        if (HasBoolean(o,"jumpable")) {
          if (o.jumpable) {
            list add (thingstojump, o)
          }
        }
      }
      if (ListCount(thingstojump)>0) {
        game.tempobject = PickOneObject(thingstojump)
        do (jump_over_it_cmd, "script")
        SetTurnTimeout (1) {
          game.tempobject = null
        }
        return (true)
      }
      msg ("There is nothing to jump over.")
    ]]></script>
  </command>
</asl>