Dealing with NPCs' possessions

I'm trying to figure out how to create a verb associated with an NPC's possessions. The examples are:

Take Demon's Sword
and
Grab Demon's Horns.

I can't figure out how to make an object that the game recognizes as "demon's sword" or "demon's horns."


UPDATE

Click the link for a much more efficient method. (http://textadventures.co.uk/forum/quest/topic/n5o624fsz0_kcw0kh6z46a/dealing-with-npcs-possessions#8f079b35-1292-4b9a-8967-65f789f55dfc)

Click here to see the complicated way to do it.

First turn on advanced scripts for the game:

image

Then, click on the Advanced Scripts tab, and adjust your backdrop script to include objects in the NPC object. (Substitute 'demon' with your NPC's name.)

image

Make sure you set it up so the sword can be taken.

( Also, to make it respond correctly (instead of saying 'You pick it up.' when you initially take it from an NPC), add a line with {once: You take the demon's sword.}{notfirst: You pick it up.})

image

Also make sure the sword has 'demon's sword' as the alias and in other names:

image

image


TRANSCRIPT:

NPC possessions

You are in a room.
You can see demon.

> take the demon's sword
You take the demon's sword.

> drop it
You drop it.

> get it
You pick it up.


EXTRA STEP:

Add an in-room description to your NPC that tells the player he is carrying a sword.

Activate the feature be ticking the 'In-room Descriptions' box:

image

Then add a line like this to the appropriate field:

image


TRANSCRIPT:

NPC possessions

You are in a room.
You can see demon.

The demon is carrying a sword.

> get the demon's sword
You take the demon's sword.

> l
You are in a room.
You can see demon.


Example game:

<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="NPC possessions">
    <gameid>51f2bdf9-9949-4a2a-9a6c-6cc593238a47</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>
    <feature_advancedscripts />
    <scopebackdrop type="script">
      foreach (o, GetDirectChildren(demon)) {
        list add (items, o)
      }
    </scopebackdrop>
    <appendobjectdescription />
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="demon">
      <inherit name="editor_object" />
      <inherit name="namedmale" />
      <alt type="stringlist" />
      <listalias type="string"></listalias>
      <inroomdescription><![CDATA[{if sword.parent=demon: <br/>The demon is carrying a sword.<br/>}]]></inroomdescription>
      <object name="sword">
        <inherit name="editor_object" />
        <take />
        <alt type="stringlist">
          <value>demon's sword</value>
        </alt>
        <alias>demon's sword</alias>
        <takemsg>{once: You take the demon's sword.}{notfirst: You pick it up.}</takemsg>
      </object>
    </object>
  </object>
</asl>

Resource:

http://docs.textadventures.co.uk/quest/advanced_scope.html


Interesting :p I was just playing with something that's tangentially relevant. I'm also trying to take a box off the demon; who obviously doesn't want to give it up. Here's the 'take' script I have for the box:

if (demon.is_distracted) {
  msg ("You grab the box while the demon is distracted")
  this.parent = game.pov
  this.take = true
}
else {
  dmg = GetRandomInt(5, 20)
  take_damage (dmg, "The demon sees you reaching for his box, and gives you a slap that makes your ears ring")
}

I figured that's the easiest way to make a box that is initially a challenge to obtain, but later on reverts to the standard behaviour.


@mrangel

Hey, that's pretty good!

@Jador

An easier way would be just putting the sword in the room with the demon and making it scenery.

Then, you wouldn't have to deal with the scope script, and you could put the in-room description on the sword.

Throwing a take script in like mrangel posted would make it much more fun/challenging, too!

NOTE: You'd need a different script under ELSE, though. It appears that mrangel has created a function he's calling in that second line. ...and you'd probably want to put all of that under a firsttime as well. Then set it up to just print the normal take message for taking the box once it has been moved.


KV: using afirsttime block doesn't seem to make sense to me. The demon will keep on hitting you as long as you keep on trying to take his object, which seems like perfectly reasonable behaviour. Until you actually manage it, of course, at which point this.take = true replaces the script attribute with a boolean, restoring the default behaviour for an object that can be taken. I figured that was simpler.


That scope script seems an awful lot of effort. I just made my NPCs containers ("surface" type, so they don't get open or close verbs, and change the prefix to "Carrying"). Then you can see his stuff when you look at him, and in the room description, depending on your settings.


using a firsttime block doesn't seem to make sense to me. The demon will keep on hitting you as long as you keep on trying to take his object...

Oh, I was running my fingertips without thinking it through (and, apparently, without reading your code through). (Sorry!) The this.take attribute is the way I'd do it.

That scope script seems an awful lot of effort. I just made my NPCs containers

Yep, yep! This is probably the most efficient way to do it, but most new folks seem to be leery of using containers, so I went with the scope (for some reason -- even though it's complicated, too; ha-ha! I'm crazy).

All of the NPCs like this are transparent containers in my last game. (Of course, that was because I had no clue how to use the scope functions back then. )

Recently I've been using the scope script and altering the 'look' script to list the direct children. It seemed to be about the same amount of work as fooling around with all the container settings. Removing 'Open' and 'Close' from the verbs list and all that...

...but making them surfaces is pretty darn slick!!!


REVISED (thanks for the help, mrangel!)


Go the the Features tab on the NPC, and select Container:

image


Click on the Container tab that appears

  • Change it to Surface in the drop-down menu
  • Check both boxes (Hide children and List children)
  • Put your own custom messages in the input fields

image


Set up the sword

  • Set up 'other names' the game will understand as the sword (you need to put "demon's sword" here because you can't use an apostrophe in the object name) and add the description. (I left the alias blank for now, so it will simply print 'sword'. This will be changed to "demon's sword" once it has been taken the first time (see the next step). This way, it will print 'He is carrying a sword' rather than 'He is carrying a demon's sword.')

image


Set up a script for taking the sword under the object's Inventory tab:

image


Here's my example script for taking the sword:

if (not this.hasbeenmoved) {
  msg ("\"Not so fast!\" roars the demon as he moves the sword out of your reach.  \"A game first, I think!<br/><br/>\"Tell me a word that rhymes with DUCK!\"<br/><br/><center><h3>JUST ENTER THE WORD BY ITSELF AND PRESS <b>ENTER</b></h3></center>")
  get input {
    result = LCase(result)
    if (EndsWith(result, "uck")) {
      msg ("\"Well played, lad!\" exclaims the demon, handing you his sword and giving you a pat on the back.<br/>")
      MoveObject (this, player)
      this.alias = "demon's sword"
    }
    else {
      msg ("\"Wrong!\" <br/><br/>The demon laughs at your lack of poetic skill and returns to doing nothing in particular.<br/>")
    }
  }
}
else {
  msg ("You pick it up.")
  MoveObject (this, player)
}

TRANSCRIPT:

NPC possessions

You are in a room.
You can see a demon.

> get the demon's sword
I can't see that.

> x demon
The demon is green, ugly, and generally nasty-looking.
...and he doesn't appear to like it when you stare at him...

He is carrying a sword.

> get the demon's sword
"Not so fast!" roars the demon as he moves the sword out of your reach. "A game first, I think!

"Tell me a word that rhymes with DUCK!"

JUST ENTER THE WORD BY ITSELF AND PRESS ENTER

You entered: truck.

"Well played, lad!" exclaims the demon, handing you his sword and giving you a pat on the back.

> i
You are carrying a demon's sword.

> drop sword
You drop it.

> get it
You pick it up.


Click here to view the example game's code.
<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="NPC possessions">
    <gameid>51f2bdf9-9949-4a2a-9a6c-6cc593238a47</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>
    <appendobjectdescription type="boolean">false</appendobjectdescription>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="demon">
      <inherit name="editor_object" />
      <inherit name="namedmale" />
      <inherit name="surface" />
      <feature_container />
      <hidechildren />
      <listchildren />
      <listchildrenprefix>He is carrying</listchildrenprefix>
      <look><![CDATA[The demon is green, ugly, and generally nasty-looking.<br/>...and he doesn't appear to like it when you stare at him...<br/>]]></look>
      <scenery type="boolean">false</scenery>
      <speak>"No time to talk right now, lad," he says.</speak>
      <contentsprefix>who is carrying </contentsprefix>
      <object name="sword">
        <inherit name="editor_object" />
        <look><![CDATA[The Sword of Whatever - once thought to be a myth, but now you know that's not the case!<br/><br/>It's said to have been forged by WhoEvers back in the day, so it's probably a pretty good sword, right?<br/>]]></look>
        <take type="script"><![CDATA[
          if (not this.hasbeenmoved) {
            msg ("\"Not so fast!\" roars the demon as he moves the sword out of your reach.  \"A game first, I think!<br/><br/>\"Tell me a word that rhymes with DUCK!\"<br/><br/><center><h3>JUST ENTER THE WORD BY ITSELF AND PRESS <b>ENTER</b></h3></center>")
            get input {
              result = LCase(result)
              if (EndsWith(result, "uck")) {
                msg ("<br><b>You entered: " + result + ".<b><br/>")
                msg ("\"Well played, lad!\" exclaims the demon, handing you his sword and giving you a pat on the back.<br/>")
                MoveObject (this, player)
                this.alias = "demon's sword"
              }
              else {
                msg ("\"Wrong!\" <br/><br/>The demon laughs at your lack of poetic skill and returns to doing nothing in particular.<br/>")
              }
            }
          }
          else {
            msg ("You pick it up.")
            MoveObject (this, player)
          }
        ]]></take>
        <alt type="stringlist">
          <value>demon's sword</value>
        </alt>
      </object>
    </object>
  </object>
</asl>

Resources:

mrangel: http://textadventures.co.uk/forum/quest/topic/n5o624fsz0_kcw0kh6z46a/dealing-with-npcs-possessions#30a1324d-1d3b-4f98-8568-02a9e6385241

http://docs.textadventures.co.uk/quest/tutorial/using_containers.html


EQUIPMENT SYSTEM BASICS:


for an equipment system:

use Object (reference/pointer) Attributes and/or Objectlist (reference/pointer) Attributes, Objects, and Object Types / Types / Inherited Attributes


as for identification/flagging of what Object, there's a few methods:

  1. Your Object's naming/labeling convention/system:

http://docs.textadventures.co.uk/quest/functions/#string

'StartsWith', 'EndsWith', 'Mid', etc

  1. A normal Attribute: a String, Boolean, Integer, etc:

'HasAttribute', 'HasXXX', 'GetAttribute', 'GetXXX'

  1. An Inherited Attribute (via using Object Types / Types):

'DoesInherit'


Also, using Commands with the identification/flagging and scripting methods mentioned above, an example:

<object name="demon_sword">
</object>

<object name="demon_axe">
</object>

<object name="holy_sword">
</object>

</object name="holy_axe">
</object>

<command name="example_command">
  <pattern>example #object_parameter#</pattern>
  <script>
    if (StartsWith (object_parameter.name, "demon")) {
      object_parameter.parent = game.pov
      game.pov.equipment_object_attribute = object_parameter
    }
  </script>
  <unresolved>Wrong input: the '#object#' Parameter, looks for that inputted Object ONLY within the room you're currently in, so either you typed in an Object that doesn't exist at all, or it just doesn't exist within the room you're currently in</unresolved>
</command>

Ah, I didn't know about this.hasbeenmoved. I think I prefer my version though… avoid wrapping an 'if' statement around everything, fewer levels of indentation in case the function later gets big enough that you're scrolling up and down to find the matching braces.


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

Support

Forums