Storing Extra Inventory in Drawers (Secondary Inventory GUIs)

Started by hocuspocus2, Fri 04/06/2021 01:45:27

Previous topic - Next topic

hocuspocus2

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).

Cassiebsg

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.  ;)
There are those who believe that life here began out there...

hocuspocus2

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.

Code: ags

function on_mouse_click(MouseButton button) {
  if (GUIControl.GetAtScreenXY(mouse.x, mouse.y) == InventoryStorage1) {
    if (player.ActiveInventory != null) {
      cStorage1.SetAsPlayer();
    }
  }
}

Khris

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.

Crimson Wizard

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.

hocuspocus2

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.

Cassiebsg

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.
There are those who believe that life here began out there...

Khris

You're not supposed to change the function's signature. AGS calls this function, passing the actual button as  button  argument:

Code: ags
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
  }
}

hocuspocus2

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.

Code: ags

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 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)?

Khris

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.

Cassiebsg

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))
There are those who believe that life here began out there...

hocuspocus2

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!

Crimson Wizard

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.

hocuspocus2

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.

Crimson Wizard

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.


SMF spam blocked by CleanTalk