undroppable object handling

XanMag
16 Jul 2016, 00:17

Simple enough question. Just looking for good opinions.

I have two objects the player starts the game with and those two objects cannot be dropped. The game does allow me to put them in another object outside of the player inventory. Is the easiest way to handle this to create a global command that prevents these objects from being put in another object. Is there another loophole around dropping these objects other than this that I am overlooking that I need to consider?

Also, what would be the proper syntax for the regular expression. Right now I have this:

^(put|place) (?<object>.*) in|into (barrel|metal barrel|metal)$

followed by an If and Else If statements for each of the two objects, but I really need to change the barrel object to ANY object.

Thanks again!


hegemonkhan
16 Jul 2016, 01:01

I don't think there's really a way to truly stop/block an Object from being (put/scriptedly put/moved) inside of another Object... I think you're just going to have to have script that checks the Object(s)' locations every turn (via a global Turnscript or the special 'changed' Script Attribute), and if they're not where you want them to be, then you move them back into where they're supposed to be.

for a simple example:

<turnscript name="global_turnscript">
  <enabled />
  <script>
    if (not book.parent = player) {
      book.parent = player
    }
  </script>
</turnscript>

XanMag
16 Jul 2016, 01:51

^(put|place) (?<object>.*) in|into (barrel|metal barrel|metal)$

This works for not allowing the two items to not be dropped in the metal barrel, but I need to know what syntax to use to prevent them from being dropped into every other container. I thought it might be #object# or #text# but when I use that, it allows me to drop the objects in the barrel.


The Pixie
16 Jul 2016, 09:15

I would override the existing "put" command to check if the object is droppable. Add this to the else ifs:

else if (not object1.drop) {
  msg ("Probably best to keep " + GetDisplayName(object1) + " where you can reach it easily.")
}

In fact, this is probably how the command should work by default.


XanMag
22 Jul 2016, 13:23

I do not want to be able to put two objects in any container. They must stay in the players inventory. So here is my code for the altered put command.

else if (not object1.anklet) {
  msg ("This anklet casts some sort of spell over you.  You have a keen longing for it.  Also, you have a feeling that it may be important later.  You hold onto it.")
}
else if (not object1.Man Card) {
  msg ("You dare not part with this Man Card.  You earned this in part one of this adventure and it is the only manly thing about you.")
}

These objects do not get placed in the container (which is good), but the message in the 'then' script does not print. It just remains blank.

On a related, side note... I only want a specific four objects to be able to be placed in the metal barrel container - skewered chicken, moss2, planks2, and glass orb (the glass orb is not created yet so is not in an 'else if' script yet). The point is that the player needs to start a fire in the barrel. Those four objects will be removed from the game (obviously because they have been burned). It would make sense that anything OTHER THAN those objects would also get destroyed, but I don't want that to be a possibility. So, would it work if I put a simple comment like 'You're not so sure that is such a wise idea.' when the player tries to put ANYTHING else in the barrel in the 'Else' section of the following script?

if (object = planks2) {
  msg ("You drop the sticky, oiled planks into the barrel.")
  MoveObject (planks1, metal barrel)
}
else if (object = moss2) {
  msg ("You drop the mossy-kindling in the barrel.  Now you should be able to burn it if you can get it to light.")
  MoveObject (moss2, metal barrel)
}
else if (object = skewered chicken) {
  if (GetBoolean(metal barrel, "lit")) {
    msg ("You place the skewered chicken on top of the metal barrel and above the roaring flames.  Like a true chicken-chef, you slowly turn the barb to evenly cook the chicken.  After a few minutes, you are convinced that this chicken has been thoroughly cooked!  You give it a few minutes to cool, remove the barb and toss it aside, and add the cooked chicken to your inventory.")
    RemoveObject (skewered chicken)
    RemoveObject (planks1)
    RemoveObject (moss2)
    RemoveObject
  }
  else {
    msg ("You have the right idea here, but you don't want to place a nice, clean, ready-to-cook chicken over a dirty empty barrel.  You probably need to get a fire started first.")
  }
}
else if (object = planks1) {
  msg ("You drop the dry plank into the barrel, but you wonder if it will really get the job done...")
  MoveObject (planks1, metal barrel)
}

The above script is not complete as other things will be happening, too, but I think you get the idea.

I would test this all out, but seeing that it is a rather complex event, I can't really do that right away and I don't want to write the whole script without checking with smarter folks like yourself first! So, will it work?

Thanks in advance!

XanMag


The Pixie
22 Jul 2016, 13:45

You are using anklet like it is an attribute. You probably want:

else if (not object1 = anklet) {
  msg ("This anklet casts some sort of spell over you.  You have a keen longing for it.  Also, you have a feeling that it may be important later.  You hold onto it.")
}

I was using drop, which is an attribute, and is set to false if an object cannot be dropped, so was doing something slightly different.

With regards to your other script, it looks broadly right but the third line should be planks2 not planks1.

Looks to me like planks1 can also be added to the drum, is that right? Is it possible to add planks1 after planks2? Either way, check the RemoveObjects. Also on that subject, I would remove them when the fire is lit, and flag the barrel as on fire or have a fire object in it, rather than when cooking the chicken.

also, you need a final else to catch any other object.


XanMag
22 Jul 2016, 14:19

I replaced the .anklet with = anklet, but I am still getting the same result.

else if (not object1 = anklet) {
  msg ("This anklet casts some sort of spell over you.  You have a keen longing for it.  Also, you have a feeling that it may be important later.  You hold onto it.")
}
else if (not object1 = Man Card) {
  msg ("You dare not part with this Man Card.  You earned this in part one of this adventure and it is the only manly thing about you.")
}

What am I missing?


bergedorfcacher
22 Jul 2016, 14:28

I don't understand the 'not' in your if clauses. If the object is not an anklet, you talk about an anklet? That looks strange to me.


XanMag
22 Jul 2016, 14:38

Strange to me too, but I'm just following The Pixie's instructions. Pix could tell me to jump off a cliff as a solution to a coding problem I have and I likely would. =)

I removed the not just to see what happens and I get the same result.


bergedorfcacher
22 Jul 2016, 14:46

Hmm, your code snippet starts with 'else', so surely there is something above. Could you post the entire thing?


The Pixie
22 Jul 2016, 15:35

Sorry, yes the not should go as well.


XanMag
22 Jul 2016, 16:10

Here is all of the altered built-in put command. The only thing I changed was adding the 'Else If's for the two objects.

// put object1 in/on object 2
if (object1.parent = object2) {
  msg (DynamicTemplate("AlreadyThere", object1))
}
else if (not ListContains(ScopeInventory(), object1)) {
  msg (DynamicTemplate("NotCarrying", object1))
}
else if (not ListContains(ScopeReachable(), object1)) {
  msg (DynamicTemplate("ObjectNotOpen", GetBlockingObject(object1)))
}
else if (not ListContains(ScopeReachable(), object2)) {
  msg (DynamicTemplate("ObjectNotOpen", GetBlockingObject(object2)))
}
else if (not object2.container) {
  msg (Template("CannotDoThat"))
}
else if (not object2.isopen) {
  msg (DynamicTemplate("ObjectNotOpen", object2))
}
else if (object1 = anklet) {
  msg ("This anklet casts some sort of spell over you.  You have a keen longing for it.  Also, you have a feeling that it may be important later.  You hold onto it.")
}
else if (object1 = Man Card) {
  msg ("You dare not part with this Man Card.  You earned this in part one of this adventure and it is the only manly thing about you.")
}
else {
  if (GetBoolean(object2, "hidechildren")) {
    object2.hidechildren = false
  }
  if (HasDelegateImplementation(object2, "addscript")) {
    rundelegate (object2, "addscript", object1)
  }
  else {
    object1.parent = object2
    msg (Template("Done"))
  }
}
// must be carrying object1
// object1 must not be inside a closed container
// object2 must not be inside a closed container
// object2 must be an open container or surface

bergedorfcacher
22 Jul 2016, 16:40

I have created a test game with a box an anklet and a Man Card and copied your script into the put command. Works perfectly fine. So your problem must be outside the script itself. I don't have enough experience to guess where that might be.


bergedorfcacher
22 Jul 2016, 16:42

Are anklet and Man Card really the object names, not aliases? (Sorry, just making wild guesses now.)


bergedorfcacher
22 Jul 2016, 16:47

Quick debugging suggestion: Before the first if put a line:

msg("Trying to put something ...")

and test it again. See if the text "Trying to put something ..." appears at all. If not, the script isn't executed at all, so something in your command setup is wrong.


XanMag
22 Jul 2016, 17:26

Yes, those are the actual names, not aliases.

Okay... so, I just put a random object (pole) in the players inventory and tried to put pole in barrel. I get the same response as if it were the man card or anklet.

Any suggestions where to go next?

Thanks!

EDIT: It wouldn't have anything to do with not having an 'else' script here, right?

if (object = planks2) {
  msg ("You drop the sticky, oiled planks into the barrel.")
  MoveObject (planks2, metal barrel)
}
else if (object = moss2) {
  msg ("You drop the mossy-kindling in the barrel.  Now you should be able to burn it if you can get it to light.")
  MoveObject (moss2, metal barrel)
}
else if (object = skewered chicken) {
  if (GetBoolean(metal barrel, "lit")) {
    msg ("You place the skewered chicken on top of the metal barrel and above the roaring flames.  Like a true chicken-chef, you slowly turn the barb to evenly cook the chicken.  After a few minutes, you are convinced that this chicken has been thoroughly cooked!  You give it a few minutes to cool, remove the barb and toss it aside, and add the cooked chicken to your inventory.")
    RemoveObject (skewered chicken)
    RemoveObject (planks2)
    RemoveObject (moss2)
    RemoveObject
  }
  else {
    msg ("You have the right idea here, but you don't want to place a nice, clean, ready-to-cook chicken over a dirty empty barrel.  You probably need to get a fire started first.")
  }
}
else if (object = planks1) {
  msg ("You drop the dry plank into the barrel, but you wonder if it will really get the job done...")
  MoveObject (planks1, metal barrel)
}

?


bergedorfcacher
22 Jul 2016, 17:46

Have you seen my suggestion to put a msg in the first line to check if that script is really run?

Also what is that new script you just posted. The put script works on the parameters object1 and object2, this latest one seems to have only object. So how are they related?

Another random though: are you cloning these objects somwhere?


XanMag
22 Jul 2016, 18:16

No clones.

I did do that little test and still got no response so it seems my put command isn't running at all.

That recent bit of code handles the ONLY objects I want to be able to put in that barrel.

If I try 'put anklet in barrel' in the 'else' part of that script, I do get a response. Could I possibly run the altered 'put' command in the else part of that script?


bergedorfcacher
22 Jul 2016, 18:55

OK, so we found out your put command isn't working at all. What does your pattern in the command look like, what input do you use for testing and what exactly is the output when you test?


XanMag
22 Jul 2016, 18:59

Read above^, we crossed paths. The ONLY object in barrel command was global but I moved it into the room with the barrel. I will try to put the anklet in a container in a different room. BRB! =)

And here is the regular expression for the 'ONLY' command:

^(put|place) (?<object>.*) (in|into|over|on) (barrel|metal barrel|metal)$

bergedorfcacher
22 Jul 2016, 19:08

OK, if you have the code you posted above (put object1 in/on object 2) running with the pattern
^(put|place) (?<object>.*) (in|into|over|on) (barrel|metal barrel|metal)$

it (the code) won't work because it requires object1 and object2.

If you are talking about two different commands, one might be hiding the other or something, but that goes far beyond my experince and knowledge about quest. :-)


XanMag
22 Jul 2016, 19:11

So... it looks like I do get the response scripted in the altered put command when I tried to place the anklet in a container in a different room. From the looks of it, I will need to handle each room a little differently. The scripts I have in the altered put command need to go in the 'Else' part of the script in the room with the barrel. The global, altered put command will handle every other room.

On a related note, is there some way around (other than what I am visioning) to handle putting ANY object in ANY container? I know I can do the 'use object on object' but it doesn't make a whole lot of sense to use sandwich on lunch bag when put sandwich in lunch bag makes more sense, right?

Also, I have a bucket. I could put EVERY object imaginable into a bucket, even if it would not logically make sense. 'put truck in bucket' = Done? So, is the easiest way to create a local command in every room in which there is an immovable container and a global command for every container that can be moved from room to room? Of course this only applies to objects meant to have certain things put in them.

My brain is jumpy, so... forgive if this is a ridiculous question.


bergedorfcacher
22 Jul 2016, 19:37

Your question isn't ridiculous at all. more likely it is the core of your problem. (Of course I might misunderstand you.)

The global put command is precisely meant for handling the putting of ANY object in ANY container if I'm not mistaken. If you use the unchanged version it will allow all that. (Even the silly stuff like put elefant in cigarrete box.) If you decide to overwrite the standard command you can add the handling of exceptions:

else if (object1 = someobject)
for handling specific objects

else if (object2 = somecontainer)
for handling specific containers

else if (object1 = someobject and object2 = somecontainer)
for handling specific object container commbinations, for example

else if (object1 = elefant and object2 = cigarrete box) {
  msg("Don't be silly!")
}

Disclaimer: as mentioned before I'm pretty new to quest, so this might not be the best way to do it. But according to my tests it should work.


hegemonkhan
22 Jul 2016, 19:40

what bergedorfcacher is suggesting for a troubleshooting tactic, an example:

(apply the below to your 'if' scripting layers and every condition of them: the 'ifs', the 'else ifs' and the 'elses', and etc: every step/place in all of your relevant scripting involved)

scripting/action/event 1
msg ("xan1")
scripting/action/event 2
msg ("xan2")
scripting/action/event 3
msg ("xan3")

by doing this, you can see where the failure(s) are in your code, for example: 'xan1' is displayed, but not 'xan2', thus you got an issue with 'scripting/action/event 2'. Then, say we fixed the issue with 'scripting/action/event 2', and we run/test the game again, with it now displaying 'xan2', but it's failing to display 'xan3', which means we got another issue, this time with the 'scripting/action/event 3', that you need to figure out what's wrong with it / how to fix it.


bergedorfcacher
22 Jul 2016, 20:03

hegemonkhan, I think at this point we already have established that the script isn't the problem, but what script is run at which time. :-)


XanMag
22 Jul 2016, 20:24

Yep. I think I have it all figured out. I just had to rearrange the placement of my commands.

I realize there is a volume option and you could set small containers to a volume of 1, medium to a 5, and large as a 100, but then you would need to assign volumes to every object the player can pick up. Oh, elephant > 5, then "it won't fit in there."

I also realize you could probably assign an attribute to every object - small, medium, large, and... If object has 'small' attribute, then it can be put in any container, medium attribute can fit in medium/large container, etc... And, I believe there is an option under limited container to only allow so many objects in said container. That way you can't put 100 small objects in small container.

Anyway, for now the current problem with containers seems to be solved.

... It amazes me how picky I'm getting with certain things as I delve into my third big game. In game one, I was sooo very lenient on scripting. Game two, I thought I tightened the screws about as much as they could tighten, and now... well, I'm getting nit-picky about everything! Not sure if that is a sign of quality game making or just a severe case of OCD. lol

Thanks a ton for your help!


bergedorfcacher
22 Jul 2016, 20:33

Thanks for forcing me to understand commands a bit better! And also thanks for mentioning the limited containers. I hadn't come across those yet.