A couple questions about Store and Containers

RobBronson
01 Aug 2018, 04:25

So, setting up a store (as per Pixies post) I realized something was not quite right. My player is set to only carry "X" amount of items. Yet if he is at max on items carried, and I buy stuff from a store, it adds those items to inventory anyway. How do I make it check to make sure my player can carry those extra items before letting him buy them?

Second question:
I have a Backpack...it is a container. I have the container set to hold a max number of items as well as a max volume weight of each item. Yet...It doesn't work. I can still put unlimited items of unlimited volume in the pack. I thought by setting those values it would work. It works when I set my player object to only carry so many items. What am I missing?

I appreciate everyone that has helped my this far. I hope not to be a burden much longer. I do thank you all.


The Pixie
01 Aug 2018, 08:15

Are you do this from the tutorial here:
http://docs.textadventures.co.uk/quest/shop.html

If so, you would need to modify the BuyObjectfunction to test if anything else can be taken. If starts like this:

if (obj.price > game.pov.money) {
  msg ("You can't afford that!")
}
else {

Replace those lines, with these:

volume = 0
continue = true
foreach (o, GetAllChildObjects(game.pov)) {
  if (HasInt(o "volume")) {
    volume = volume + o.volume
  }
}
volume = volume + GetVolume(obj,true)
if (HasInt(game.pov, "maxvolume")) {
  if (volume > game.pov.maxvolume) {
    continue = false
    message = "Insufficient volume to buy anything now."
  }
}
children = GetDirectChildren(game.pov)
if (HasInt(game.pov, "maxobjects")) {
  if (game.pov.maxobjects > 0) {
    if (ListCount(children) >= game.pov.maxobjects) {
      continue = false
      message = "Carrying too many items to buy anything now."
    }
  }
}
if (continue = false) {
  msg (message)
}
else if (obj.price > game.pov.money) {
  msg ("You can't afford that!")
}
else {

I have not tested it, but it is mostly from the DoTake function, so should work.


mrangel
01 Aug 2018, 10:33

Or you could be lazy and change

obj.parent = game.pov

to

obj.parent = game.pov.parent
DoTake (obj, false)

(Which means that you can buy an object when your inventory is full, but it gets left on the counter until you drop something else to pick it up)


RobBronson
01 Aug 2018, 18:20

Excellent...that works great. Thank you both.
Now for my second question...I currently have my Put In verb as follows:

if (GetBoolean(Small_Backpack, "bpack")) {
  msg ("You can not reach to put things in the backpack while you are wearing it,genius.")
}
if (not Small_Backpack.isopen) {
  msg ("You must open the backpack in order to add or remove items, Einstein.")
}
else {
  MoveObject (Ammo_45_Lg, Small_Backpack)
  msg ("You have put the Ammo into your backpack.")

How do I add to that, in order for it to recognize the max item and volume that is allowed into the backpack?
I thought it would be automatic when I set the item max and volume of the pack and the items.


mrangel
01 Aug 2018, 18:32

I thought it would be automatic when I set the item max and volume of the pack and the items.

No. The default "put in" command checks that you can reach the backpack, that you have the object you're trying to put in it, that the backpack is open, and that there's room to fit the object in the backpack.

If you're writing your own "put in" command, you'll have to check all those things yourself.

The simplest way might be a modification like:

if (GetBoolean(Small_Backpack, "bpack")) {
  msg ("You can not reach to put things in the backpack while you are wearing it,genius.")
}
if (not Small_Backpack.isopen) {
  msg ("You must open the backpack in order to add or remove items, Einstein.")
}
else if (HasScript (Small_Backpack, "addscript")) {
  params = NewDictionary()
  dictionary add (params, "object", Ammo_45_Lg)
  do (Small_Backpack, "addscript", params)
}
else {
  MoveObject (Ammo_45_Lg, Small_Backpack)
  msg ("You have put the Ammo into your backpack.")
}

I'm wondering, are you doing this because you want to have "put in backpack" on the menu when a GUI-using player clicks on the ammo? If so, I've got a script around here somewhere which allows you to add a string like "Put ___ in backpack" to an object's displayverbs; that shows up as "Put in backpack" on the menu, but when the player clicks it, it sends the command "Put (whatever the object's alias is) in backpack", so you don't need to write a new verb for it. If that's what you're after, I can try to find that script.


RobBronson
01 Aug 2018, 19:28

You almost make it sound like I know what I am doing. lol
But in fact...I could not figure out how to make the default "put in" work...so, I was creating the verb on my items.
If I were to figure out the right way to use the default...would I not have to set the verb on each object item?
I like the fact of it saying "you put (certain object) in the backpack. However, the container will not always be a backpack.

Using the code you gave me works fine. Thank you once again :)


mrangel
01 Aug 2018, 19:58

No, you don't need to set up any verbs. Verbs are for commands that do something different depending which object you use them on.

By default, the player can type "put stick in backpack" and it just works (as long as the backpack is a container).

Making it show up on the dropdown menu is a bit harder, because "put in" needs you to select two objects.

In games where there's just one backpack, it's relatively simple. You can put "put in backpack" on an object's inventory verbs list (you don't need to create an actual verb).
Then you can modify the "put" command. I'm using the web editor, so I'd put a line in my start script:
put.pattern = "^(put (?<object1>.*) (on|in) (?<object2>.*)|put in (?<object2>backpack) (put (?<object1>.*))$"

With multiple bags or containers, I can think of a few ways to make it work; but all would be quite complex and involve more code so I'd have to take a look when I'm not in the pub.


RobBronson
01 Aug 2018, 20:37

My game does not use the command bar. So I need "Put In" to appear when the object is clicked on from the inventory list.
I have multiple backpacks, boxes and various other containers to put things in.
Thanks to the bit of code you gave me above, I can make it work. I may be doing more work than I need to...but I think I've been doing that since I started this game. I'm certain if you saw my entire game code you would laugh at how I did somethings, yet might be amazed at how I figured some stuff out. ( In oddball, round about ways.)
Thanks again...


mrangel
02 Aug 2018, 11:56

One thought that comes to mind is having "Put in container" in the displayverbs, and changing the pattern of the default 'put' command so that "put in container (X)" is an acceptable alternative for "put (X) in container" - using 'container' specifically, to avoid confusion over where the space in the command is. This may seem counterintuitive for players who are typing the command, but as you don't have a command bar this isn't a problem.

Then you could give all bags/boxes/etc an alternate name "container" (on the 'object' tab, I think).

You click on any object, pick "Put in container" from the menu, and if there's more than one container in sight, you get a disambiguation menu asking which one you meant.


mrangel
02 Aug 2018, 16:35

OK ... found a chunk of javascript I was looking for.

  buildMenuOptions = function (verbs, text, elementId) {
    var verbsList = verbs.split("/");
    var options = [];
    var metadata = new Object();
    metadata[text] = elementId;
    var metadataString = JSON.stringify(metadata);

    $.each(verbsList, function (key, value) {
      var linkCmd = value;
      var linkTitle = value;
      if (value.match(/__/)) {
        linkCmd = linkCmd.replace(/__/, text);
        linkTitle = linkTitle.replace(/\s*__\s*/, " ");
      } else {
        linkCmd += " " + text
      }
      options = options.concat({
        title: linkTitle,
        action: {
          callback: function (s) {
            sendCommand(linkCmd, metadataString);
          }
        }
      });
    });

I think that if you add that, you could add "Put __ in bag" to the inventoryverbs for an item; it will show on the menu as "Put in bag", but when you click that option it will issue the command "Put apple in bag" or whatever, triggering the default "put X in Y" command without needing to modify the command itself.

You could use that either by creating multiple displayverbs ("Put __ in backpack", "Put __ in chest", etc); or by making a single displayverb "Put __ in container" and giving all containers the alternate name "container" so that when the player chooses that option, Quest will ask them which container they want to put the item in.