Hello friends
I'm trying to allow the player to drop an item from their inventory.
So far I'm working with if
if (Parser.Said("drop key")){
player.LoseInventory(iKey);
I've tried some other variations of this with no luck. For example placing this under the "Parser.ParseText(input); line in the Global settings. Also using player.LoseInventory(InventoryItem *item) <--- this one turned up errors I think are well beyond my understanding right now.
I've also tried static InventoryItem* iKey.GetAtScreenXY(int x, int y)
The manual suggests cEgo.LoseInventory(iKey); then directs me to Character.InventoryQuantity
But I could not figure out (without errors) where to place it in the global settings properly. I'm guessing I need to use the correct function, but I just can't think of which one it is.
I should mention, just in case, that my game has no characters visible in any room. Although they do exist. The way the player picks items is through the parser, which in the script triggers the item within a region which covers the entire room.
Thank you guys for any help, even if it's just direction.
*UPDATE*
Using else if (Parser.Said("drop key")){
player.LoseInventory(iKey); within the Parser.ParseText(input);
The player indeed drops the item but now the item is nowhere to be seen, however the player CAN pick it up again. I'd imagine this has something to do with InventoryItem* iKey.GetAtScreenXY(int x, int y). Perhaps the items is being returned to a "hidden" place, or something along those lines. I should mention that after testing. If the player drops the key in a different room than where it was found, the player cannot recover it from there. It only works in the place were the object/inventory item was originally. However it doesn't visibly return to its starting place.
Any direction is appreciated!
Cheers
Items are in your inventory, while objects are visible (or not) in a room. You need to make an object in the room (oKey) which you turn invisible when the player picks it up, and visible when the player drops it.
So you should code that the oKey turns invisible and that the player gets the iKey. Likewise, if your player loses the iKey, the oKey gets its visbility turned on again. You also need another if to check whether the oKey is visible in this room before letting the player pick up the iKey.
Quote from: heltenjon on Mon 11/12/2023 03:04:58Items are in your inventory, while objects are visible (or not) in a room. You need to make an object in the room (oKey) which you turn invisible when the player picks it up, and visible when the player drops it.
So you should code that the oKey turns invisible and that the player gets the iKey. Likewise, if your player loses the iKey, the oKey gets its visbility turned on again. You also need another if to check whether the oKey is visible in this room before letting the player pick up the iKey.
Thanks, so obvious, I cannot believe I overlooked that.
Cheers!
I'm guessing you're using a text box for the parser input? In this case you should have an ??_OnActivate(...) function in the Global Script (your post implies that processing commands works in general so I assume you got this far).
AGS re-runs this function whenever you hit enter while the textbox is visible, so inside this function is where all the parser command processing goes.
Like this:
function textBoxParser_OnActivate(GUIControl* control) {
Parser.ParseText(control.Text); // tell AGS to test understood commands against the current textbox content
if (Parser.Said("quit")) QuitGame(1);
if (Parser.Said("look")) CallRoomScript(1);
if (Parser.Said("take anyword")) {
// ... process take command
}
if (Parser.Said("drop key")) {
player.LoseInventory(iKey);
}
}
Note that I don't use "else if" here because these commands are all different so the parser will never match multiple commands at the same time.
Also note that using the LoseInventory() function is not related to the parser in any way, and you haven't told us which error you got. I assume the issue is what most beginner's trip over: not placing code like that inside a function.
AGS is event based, which means that all commands go inside the various event handler functions.
Putting a command like player.LoseInventory(iKey) directly inside a script wouldn't make any sense because AGS wouldn't know when to run it.
I can see how the if (Parser.Said("drop key")) {...} part might sound like something you can tell AGS to do at the very start of the game, and it will act accordingly as soon as the player has typed the "drop key" command, however that's not how the parser commands work. It's not a setting, it's a test that runs live at the time the command runs. Which means you have to re-do the Parser.Said("drop key") test every time the player has typed something.
(side note: the parser commands allow the use of special keywords like "rol" "anyword", optional words and synonyms. You don't have to use them, you could also simply directly compare whatever the player typed against a bunch of known commands.)
As for dropping the key (which is, again, completely unrelated to your using a parser): inventory items and room objects don't have any relation to each other whatsoever. The fact that both represent the same physical object is not known to AGS (and there's no built-in way to set up that connection).
So your question is based on a wrong assumption. The actual question is: how do I implement a system that allows me to drop items in any room? Since room objects cannot leave their room, you would have to add a key object to every room in theory.
You also cannot create room objects on the fly, so this question is in fact much more complex than it might seem unfortunately.
This post is already way too long so I'll leave it at that for now.
Quote from: Khris on Mon 11/12/2023 18:33:55Note that I don't use "else if" here because these commands are all different so the parser will never match multiple commands at the same time.
I'd like to point out that it may still be suitable to use "if/else if" sequence here, because in the above code the script will keep testing for other variants unnecessarily after one of them succeeded.
True, but performance isn't really an issue with parser commands.
I avoided else ifs because afaik there's a hard limit on how many you can have, and in the context of parser commands this could quickly become an issue.
OTOH it's probably preferable anyway to start by using "rol" to branch into various other functions.
Quote from: Khris on Mon 11/12/2023 18:33:55The actual question is: how do I implement a system that allows me to drop items in any room? Since room objects cannot leave their room, you would have to add a key object to every room in theory.
You also cannot create room objects on the fly, so this question is in fact much more complex than it might seem unfortunately.
Hmmm...could he solve it by making the key a character instead? A cKey could enter a room when iKey is dropped?
Quote from: heltenjon on Mon 11/12/2023 20:05:46Hmmm...could he solve it by making the key a character instead? A cKey could enter a room when iKey is dropped?
This sounds like a Kyrandia-style system. I recall there have been a Kyrandia template around, which let drop items anywhere (and do some other things), but i never used it myself, so cannot tell how convenient that would be:
https://www.adventuregamestudio.co.uk/forums/modules-plugins-tools/template-kyrandia-bass-hybrid/
For scripting this yourself, Characters is a traditional way to represent global objects (objects that could be in any room). Since AGS 3.6.0 dynamically created Room Overlays may be used for this purpose, except they would require more scripting, and manually scripted interaction.
@Khris I don't have a function textBoxParser_OnActivate in the Global Script. All of those are under a function interface_click(int interface, int button) and then
Parser.ParseText(input); //parses the 'input' variable through our list of known words
//Place all global parser commands here! :)
if (Parser.Said("quit [game]")) { QuitGame(1); }
else if (Parser.Said("save [game]")) { SaveGameDialog(); }
else if (Parser.Said("load [game]")) { RestoreGameDialog();}
else if (Parser.Said("restart [game]")) { gRestartgui.Visible= true; Mouse.Mode= eModePointer;}
else if (Parser.SaidUnknownWord()) { // if an unknown word has been said
Display("Please use another word for '%s'.", Parser.SaidUnknownWord()); // %s will be replaced with the unknown word and printed on screen
}
else if (Parser.Said("drop key")){
player.LoseInventory(iKey);
}
else if (Parser.Said("inv")) { ShowInv(); } //show inventory
else if (Parser.Said("look key") && (player.InventoryQuantity[iKey.ID])) {
ShowInvCloseup(42, "This is the ugliest key you have ever seen."); //This shows a closeup of the inventory item Key when looked at. 42 is the number of the key sprite (not the meaning of life!).
}
else { //if none of the previous commands matched
CallRoomScript(1); }
Thanks guys for all the input.
@Crimson Wizard I will check that template out.
I think the idea of having the item in every room might work somehow. But the scrip might get messy. If the player enters the room with iKey from room 1, then iKey2 can't be visible
and if the player drops the iKey, then iKey2 is visible, etc... I can already feel my head spinning trying to make that work.
Cheers!
Quote from: Rub on Mon 11/12/2023 23:50:20I think the idea of having the item in every room might work somehow. But the scrip might get messy. If the player enters the room with iKey from room 1, then iKey2 can't be visible
and if the player drops the iKey, then iKey2 is visible, etc... I can already feel my head spinning trying to make that work.
No, the iKey is the key that is in your inventory. The Key you see on screen if it is lying around in the current room, must be coded as an object (oKey) or a character (cKey). If you want the key to be droppable in every room, it will be easiest to code it as cKey. What you do then, is that if you drop the key (lose iKey from inventory), you have cKey arrive in the current room at coordinates you set.
If you want to put the oKey (object that is limited to a room) in every room, you set it as invisible everywhere except where it starts out. Then you need to make it visible in the current room if iKey is dropped on the floor. Doable, but cumbersome.
Disclaimer: I have no experience with the parser template. This reply deals with the general AGS behaviour only.
Quote from: heltenjon on Tue 12/12/2023 07:41:56Quote from: Rub on Mon 11/12/2023 23:50:20I think the idea of having the item in every room might work somehow. But the scrip might get messy. If the player enters the room with iKey from room 1, then iKey2 can't be visible
and if the player drops the iKey, then iKey2 is visible, etc... I can already feel my head spinning trying to make that work.
No, the iKey is the key that is in your inventory. The Key you see on screen if it is lying around in the current room, must be coded as an object (oKey) or a character (cKey). If you want the key to be droppable in every room, it will be easiest to code it as cKey. What you do then, is that if you drop the key (lose iKey from inventory), you have cKey arrive in the current room at coordinates you set.
If you want to put the oKey (object that is limited to a room) in every room, you set it as invisible everywhere except where it starts out. Then you need to make it visible in the current room if iKey is dropped on the floor. Doable, but cumbersome.
Disclaimer: I have no experience with the parser template. This reply deals with the general AGS behaviour only.
Hey
@heltenjon yes, sorry I didn't type the oKey or iKey last night. But I understand the differences.
True that it might be a bit tedious. But I will try nevertheless.
With the game being parser-based one advantage is that you don't need to be able to click the key, you just have to see it in the room. Which means you don't really need an object or a character, you can simply draw it on an overlay for instance (and those can be created dynamically).
We can also change custom properties at runtime, so each inventory item could get a room_number int property which is changed to 0 once picked up.
Now all you need is a function that updates the room by redrawing / removing the overlays representing dropped items and call it in room_Load and whenever something is dropped or picked up.
@Khris Thanks, I better start reading up on overlays in the manual then XD, can't say I've used them before.
Cheers!