The player will have a limited number of inventory (10 items), and so they would need to store extra items in drawers and such and then take them out if needed. They essentially work like backpacks in some video games. This will probably be achieved using multiple inventory GUIs, the problem is I'm not sure how I would go on about it. I'm thinking that I would need to create dummy characters for each drawer, but that's about it.
I should mention that this is a 1st-person perspective (so the player character is hidden).
Yes, a dummy character for each "drawer" is the way to go.
So when adding to the "drawer" you just add to cDrawer1 inventory, to access it, you need to either change the player to the cDrawer1 and once you pick up the item, you transfer it to the normal player charcter's active.inventory (or inventory depending how you choose to do it), and then change back to the normal player character.
Alternative is adding a cDummyHolder that will hold the player's normal inventory, and instead of changeing player character you can transfer all player.inventory to this cDummyHolder's inventory, then transfer all the inventory from the cDrawer1 to the player... do what you need to do, and then do the oposite, move the player's inventory back into the drawer and afterwards retrieve the items from cDummyHolder to the player.
Either option will work, but I think the first is probably easier to program. ;)
Hello, sorry for the late reply, I was trying to figure it out before responding. I'm trying to follow your first suggested method, I'm just stuck at the character switching part.
I'm trying to make it so that the player drags their item to the drawer inventory and clicks on an empty slot to transfer said item (and vice versa). I've managed to switch characters (from player to drawer dummy, cStorage1), but I can't get it to trigger on mouse click.
Does mouse_click not work in room scripts? Or maybe I'm approaching this wrong? Because putting this code in room_RepExec switches player character when your mouse is just hovering over the drawer inv. GUI.
function on_mouse_click(MouseButton button) {
if (GUIControl.GetAtScreenXY(mouse.x, mouse.y) == InventoryStorage1) {
if (player.ActiveInventory != null) {
cStorage1.SetAsPlayer();
}
}
}
You need to activate custom click handling in General settings -> Inventory.
Clicks on inventory windows should now cause on_mouse_click to be called, with button being eMouseLeftInv / eMouseRightInv.
Quote from: Khris on Mon 07/06/2021 08:29:53
You need to activate custom click handling in General settings -> Inventory.
Ugh! I think we must adjust all the templates to always have this activated. The "builtin handling" should be assumed a backward compatible option at this point.
You mean "Override built-in inventory window click handling", right? I do have it set on True already. I should also mention that I'm using the BASS template, I think.
Also changing "button" to eMouseLeftInv or anything else in on_mouse_click causes a parser error, unless if I'm doing it wrong.
a Parse error might mean that you are using = in an if condition, instead of == ... check if that~s the case. ;) Otherwise, post the code.
You're not supposed to change the function's signature. AGS calls this function, passing the actual button as button argument:
function on_mouse_click(Mousebutton button) {
if (button == eMouseLeftInv) {
ClaimEvent(); // do not also call global on_mouse_click(eMouseLeftInv);
InventoryItem *item = inventory[game.inv_activated];
// do stuff
}
}
My mistake, I added the button if-statement from your code example. Here's the thing, when I transfer an item from drawer inv. to player inv., it works. But not vice versa. The Display command also never triggers.
function on_mouse_click(MouseButton button) {
 GUIControl *ctrl = GUIControl.GetAtScreenXY(mouse.x, mouse.y);
 InventoryItem *item = inventory[game.inv_activated];
 if (ctrl == InventoryStorage1) {
  if (button == eMouseLeftInv) {
   ClaimEvent();
  Â
   if (item != null) { //Taking item from storage, works fine
    player.AddInventory(item);
    cStorage1.LoseInventory(item);
   }
 Â
  } else if (button == eModeLeft) {
   if (player.ActiveInventory != null){ //Putting item in storage, does nothing
     ClaimEvent();
    Â
     Display("Switching player and adding item!");
     cStorage1.SetAsPlayer();
     cStorage1.AddInventory(item);
    Â
     cRoger.SetAsPlayer(); //Player character
     player.LoseInventory(item);
    }
  }
 }
}
Edit note: I also found this (https://github.com/adventuregamestudio/ags/issues/472) discussion on Github relevant. So I guess it's not possible to click on empty inventory slots (unless if using on_event or eEventGUIMouseDown like the post suggested)?
Yeah, you need on_event to handle that.
eMouseLeftInv only fires when you click on an actual item (which means you can rely on inventory[game.inv_activated] not being null btw), clicking an empty part of an inv window doesn't even trigger an eMouseLeft call.
Just a tidbit, you don't need to change the player to add items to a character. You only need to change character if you need to see the inventory window for that character.
You can just do:
cStorage1.AddInventory(item);
cRoger.LoseInventory(item);
You just need to decide which inventory the player will be looking at (if it's cStorage or cRoger... or neither (laugh))
Ah ok, thank you for clearing it up. The drawer inv. pops up after clicking on a hotspot and it has a close button, so that way you can look at both your inventory and the drawer's.
I was hoping I would do all the storage work in rooms, because my global script is already getting cluttered and I'm not even 25% done with the game yet. I guess the best I could do is write a function as a shortcut for the code with GUI and GUIControl parameters, and use it for each drawer inv in on_event. (because there's gonna be a lot in the game).
Either way, I moved the current code to on_event, modified it, and it works now. Thanks for the help!
Quote from: hocuspocus2 on Tue 08/06/2021 21:41:25
I was hoping I would do all the storage work in rooms, because my global script is already getting cluttered.
You can create additional script modules to split the code btw.
Yeah, I know I can put custom functions in other scripts, but can I move special functions from the global script to extra scripts? The manual does say they can contain on_event, on_mouse_click, etc.
Quote from: hocuspocus2 on Wed 09/06/2021 01:11:47
Yeah, I know I can put custom functions in other scripts, but can I move special functions from the global script to extra scripts? The manual does say they can contain on_event, on_mouse_click, etc.
Well, yes, as the manual sais, each script module can contain these functions.
GlobalScript is special in one way only: it's the only script allowed to have object event functions for some reason.
Alright, thanks for the tip!