NPCs: Give - ThePix/QuestJS GitHub Wiki

If you have NPCs you are likely to want to let the player give items to them. The NPC says he will help if the player gets the MacGuffin; the player gets it, now she has to give it to him.

We can see giving an item as a two step process. The first step involves the giver, and is handled by "getAgreementGive" (and "canManipulate"), which is discussed elsewhere.

What we are concerned with here is the second step, the character receiving the item and perhaps reacting, or refusing it. By default, NPCs will refuse any item the player gives him, but the player will accept any item given to her. But you can change that on an item-by-item basis for each character.

This is handled by two attributes, "receiveItems" and "receiveItemsFailMsg". The former is an array Quest will look though for a suitable response. The latter is a string or function that is used if the search fails.

The array, "receiveItems", is made up of dictionaries, each containing an "item" attribute that is a specific item or a "test" that is a function (or both). This entry will be used if the item matches or the test returns true (or both, if both are present). If there is a match, the function, "script" is run, and the search terminates. It will be passed a dictionary with attributes "item" and "npc".

You can have is print a message as well as or instead of running a script using the "msg" attribute, but usually the script is required as you need some code to handle transferring the item. The best way to do the transfer is with util.giveItem, which should be passed the parameters and will just sort it out for you.

Here is an example for a carrot-obsessed rabbit called Lara. She will grudgingly accept the knife, but rejects anything else that is not a carrot. Note that carrots are clones, so we check the name starts with "carrot" in the second entry.

  receiveItems:[
    {
      item:w.knife, 
      script:function(p) { 
        msg("'A knife?' says Lara. 'I guess I could use that... for something?'")
        util.giveItem(p)
      }
    },
    {
      test:function(options) {
        return options.item.name.startsWith('carrot')
      },
      script:function(options) { 
        msg("'A carrot!' says Lara with delight, before stuffing it in her mouth. 'So, do you have any more?'")
        // move first to ensure reactions like afterMove will run, then delete as it gets eaten
        util.giveItem(p)
        delete options.item.loc
      }
    },
    {
      msg:"'That's not a carrot,' Lara points out.",
      failed:true,
    },
  ],

Note the last entry, which has no test, so catches everything else. The item is not transferred to Lara, so no script used. It is flagged as a failed command.

The second example is for a character who will accept anything, but has a special response for the book.

  receiveItems:[
    {
      item:"book", 
      script:function(p) { 
        msg("'Oh!' says Kyle. 'Is this a book?'")
        util.giveItem(p)
        return true
      }
    },
    {
      test:function() { return true },
      script:function(p) { 
        msg("{multi}Done.", p)
        util.giveItem(p)
        return true
      }
    },
  ],

The functions here use a single parameter, which is a dictionary with the following name-value pairs (they are named to be consistent with other parts of Quest 6; the last two are for "moveToFrom"):

Name Description
item The item being given
char The giver (usually the player)
npc The receiver
toLoc The receiver's name
fromLoc The giver's name

NOTE: The "item" attribute can be set to either the item itself, as done for the first example, or to the item name, as in the second example. If you use the item itself, the item must be defined earlier (either higher up the file or in a file that loads earlier). If it is not, "item" will be set to undefined and it will match things it should not and general confusion will result!

Alternatively...

You can also code your own give function for each character, by giving him his own "handleGiveTo". Note that this is an attribute of the character receiving the item, and will be passed a dictionary with the attributes described above.

It is up to you to check the giver has the item, is willing and able to hand it over, and to handle the receiver dealing with it.

It should return a Boolean indicating success or failure.