Author Topic: [Another small issue] Custom interactions menu not working with inventory items  (Read 392 times)

My game uses a custom interaction menu that you guys helped me code a while ago (thanks!)
It works perfectly fine for everything during normal gameplay, but it seems that there's something that prevents it to work or appear when used to interact with the inventory items. So far I handled the inventory via custom buttons in the inventory window itself, now I really want to consolidate the ways the player interacts with anything, plus I wanted to add some custom interactions to a couple of items, so I thought I could easily expand the interction menu's function to work with inventory items too just like I expanded it to work with objects and characters. Apparently I was wrong :P

This is the code for the interaction menu:

Code: Adventure Game Studio
  1. function on_mouse_click(MouseButton button)
  2. {
  3.   // called when a mouse button is clicked. button is either LEFT or RIGH
  4.  
  5.   if (IsGamePaused() == 1) {
  6.     // Game is paused, so do nothing (ie. don't allow mouse click)
  7.   }
  8.   else if (button == eMouseLeft)  {
  9.     //reset everything before a fresh start on a new interactive element
  10.     gInteractionsMenu.Visible = false;
  11.     ListInteractions.Clear();
  12.     gInteractionsMenu.Height = 40;
  13.     ListInteractions.Height = 0;
  14.    
  15.     if (Room.GetProperty("InteractionMenu_Available") == true) {
  16.       //set the required variables
  17.       int AreThereInteractions = 0;
  18.       MouseActionX = mouse.x;
  19.       MouseActionY = mouse.y;
  20.       String CurrentOption;
  21.  
  22.       //these are pointers I properly created outside this function because I use them for a couple other stuff too
  23.       activeHotspot = Hotspot.GetAtScreenXY(mouse.x, mouse.y);
  24.       activeObject = Object.GetAtScreenXY(mouse.x, mouse.y);
  25.       activeCharacter = Character.GetAtScreenXY (mouse.x, mouse.y);
  26.       activeItem = InventoryItem.GetAtScreenXY (mouse.x, mouse.y);
  27.      
  28.       //Handling Inventory items
  29.       if(activeItem != null) { //safety check: pointers can be "null", and if so you can't call methods on them
  30.         ActionNumber = activeItem.GetProperty("Interaction_Number"); //Get the number of custom interactions thisobject/item/hotspot/character has
  31.         int ActionCounter = 1;
  32.         while (ActionNumber > 0)
  33.         {
  34.           CurrentOption = String.Format("Action_%d", ActionCounter);
  35.           ListInteractions.AddItem (String.Format("%s", activeItem.GetTextProperty(String.Format("%s", CurrentOption))));  
  36.           gInteractionsMenu.Height += 26;
  37.           ListInteractions.Height += 26;
  38.           ActionNumber -=1;
  39.           AreThereInteractions += 1;
  40.           ActionCounter +=1;
  41.         }
  42.         if (AreThereInteractions > 0) {
  43.           gInteractionsMenu.X = mouse.x;
  44.           gInteractionsMenu.Y = mouse.y;
  45.           ListInteractions.SelectedIndex = -1;
  46.           lbMenuTitle.Text = String.Format("%s", activeItem.Name);
  47.           gInteractionsMenu.Visible = true;
  48.         }
  49.       }
  50.  
  51.       // Repeat the same code with appropriate pointers for objects, characters and hotspots
  52.       // They have an additional else clause at the end to handle character movement when you're not clicking on something interactable
  53.  

As I said, it works perfectly during regular room browsing, but nothing happens when the inventory GUI is open.
I checked the z-order of the guis, in case it was drawn under the inventory screen. Nope, gInteractionMenu is set to appear on top of everything else.
I also made it so that the inventory menu didn't pause the game even though it leads to some undesirable behaviour if you click outside the GUI (By the way, any suggestion on how to handle that in case I have to keep it this way?), and of course I also made sure that the inventory item I was clicking on had the proper custom properties correctly set. Still nothing.

Help, please?
« Last Edit: 29 Nov 2017, 16:36 by Lord Vetinari »

Khris

  • having to deal with what games are going through
    • Lifetime Achievement Award Winner
    •  
    • I can help with play testing
    •  
    • I can help with scripting
    •  
    • I can help with translating
    •  
    • Khris worked on a game that was nominated for an AGS Award!
AGS only calls on_mouse_click(eMouseLeft) when you left-click the room; if you want do manually handle clicks on inventory items, you have to
a) turn on the respective option in General Settings / Inventory (Override built-in ...)
b) add code for (button == eMouseLeftInv)

Oh thank God, I feared I had some major rewrite to do.

Thank you, now it works perfectly!

EDIT: actually, I was a bit too hasty, there's a tiny annoying bug. If you select an option and therefore process an interaction, the menu disappears correctly. If you instead click somewhere else that is not another item (say, the arrow buttons to scroll the inventory up and down), the menu stays visible despite the gInteractionsMenu.Visible = false; that I put right after the button check to be sure that it hides any currently existing menu. Any idea why?
The code now looks like this:

Code: Adventure Game Studio
  1. function on_mouse_click(MouseButton button)
  2. {
  3.   if (button == eMouseLeftInv) {
  4.     // reset everything to start from scratch
  5.     gInteractionsMenu.Visible = false;
  6.     ListInteractions.Clear();
  7.     gInteractionsMenu.Height = 40;
  8.     ListInteractions.Height = 0;
  9.    
  10.     // set the required variables
  11.     int AreThereInteractions = 0;
  12.     vIntMouseActionX = mouse.x;
  13.     vIntMouseActionY = mouse.y;
  14.     String CurrentOption;
  15.     activeItem = InventoryItem.GetAtScreenXY (mouse.x,  mouse.y);
  16.     if(activeItem != null) { //safety check: pointers can be "null", and if so you can't call methods on them
  17.         ActionNumber = activeItem.GetProperty("Interaction_Number"); //Get the number of custom interactions thisobject/item/hotspot/character has
  18.         int ActionCounter = 1;
  19.         while (ActionNumber > 0)
  20.         {
  21.           CurrentOption = String.Format("Action_%d", ActionCounter);
  22.           ListInteractions.AddItem (String.Format("%s", activeItem.GetTextProperty(String.Format("%s", CurrentOption))));  
  23.           gInteractionsMenu.Height += 26;
  24.           ListInteractions.Height += 26;
  25.           ActionNumber -=1;
  26.           AreThereInteractions += 1;
  27.           ActionCounter +=1;
  28.         }
  29.         if (AreThereInteractions > 0) {
  30.           gInteractionsMenu.X = mouse.x;
  31.           gInteractionsMenu.Y = mouse.y;
  32.           ListInteractions.SelectedIndex = -1;
  33.           lbMenuTitle.Text = String.Format("%s", activeItem.Name);
  34.           gInteractionsMenu.Visible = true;
  35.         }
  36.      }
  37.   }
  38.  
  39.   else if (IsGamePaused() == 1) {
  40.     // Game is paused, so do nothing (ie. don't allow mouse click)
  41.     // This check goes after the inventory one because otherwise the inventory (which pauses the game) will prevent the item check to fire.
  42.   }
  43.  
  44.   else if (button == eMouseLeft)  {
  45.     // the old code for interacting with stuff in rooms
  46.   ]
  47.  

EDIT bonus question2: how do I use mouse mode Usermode1 on an inventory item? I would've guessed it was with the Other Click On Inventory Item event, but it doesn't seem to work.
To add more info on how this system works with regular rooms interactions, the player's selection from the interaction menu listbox is then handled in a function that I updated this way for handling inventory items too:

Code: Adventure Game Studio
  1. function ListInteractions_OnSelectionCh(GUIControl *control)
  2. {
  3.   if (ListInteractions.SelectedIndex == 0) {
  4.     MenuAction_1 = true;
  5.     gInteractionsMenu.Visible = false;
  6.     if (GUI.GetAtScreenXY(MouseActionX, MouseActionY) != null) {
  7.       GUI.ProcessClick (MouseActionX, MouseActionY, eModeUsermode1);
  8.     }
  9.     else {
  10.       Room.ProcessClick (MouseActionX, MouseActionY, eModeUsermode1);
  11.     }
  12.     MouseActionX = 0;
  13.     MouseActionY = 0;
  14.     mouse.Mode = 1;
  15.   }
  16.   else if (ListInteractions.SelectedIndex == 1) {
  17.     MenuAction_2 = true;
  18.     gInteractionsMenu.Visible = false;
  19.     if (GUI.GetAtScreenXY (MouseActionX, MouseActionY) != null) {
  20.       GUI.ProcessClick (MouseActionX, MouseActionY, eModeUsermode1);
  21.     }
  22.     else {
  23.       Room.ProcessClick (MouseActionX, MouseActionY, eModeUsermode1);
  24.     }
  25.     MouseActionX = 0;
  26.     MouseActionY = 0;
  27.     mouse.Mode = 1;
  28.   }
  29.   //and so on...
  30. }
  31.  

and finally, the object/character/hotspot events handles what happens based on the MenuAction_x variables.
I thought I could do the same with inventory objects simply by updating the function with GUI.ProcessClick on top of Room.ProcessClick, but evidently that's not the case.
« Last Edit: 30 Nov 2017, 08:21 by Lord Vetinari »

Sorry to bump this up, but I only have the next two weekends and a couple of wordays evening to finish fizing this stuff before a meeting on the 21st of Dicember during which I can probably start to turn this into something and team up with a proper coder, I'm pretty sure I can't figure out in such a short amount of time what's wrong all by myself. Please?

Khris

  • having to deal with what games are going through
    • Lifetime Achievement Award Winner
    •  
    • I can help with play testing
    •  
    • I can help with scripting
    •  
    • I can help with translating
    •  
    • Khris worked on a game that was nominated for an AGS Award!
The first issue can probably be solved with on_event:

Code: Adventure Game Studio
  1. // add to GlobalScript.asc
  2. function on_event(EventType event, int data) {
  3.   GUI* gui = GUI.GetAtScreenXY(mouse.x, mouse.y);
  4.   if (event == eEventGUIMouseUp) {
  5.     // inv item interaction menu
  6.     if (gInteractionsMenu.Visible && gui != gInteractionsMenu) gInteractionsMenu.Visible = false;
  7.   }
  8. }

As for simulating clicks on Inventory items, use
Code: Adventure Game Studio
  1.   inventory[game.inv_activated].RunInteraction(mouse.Mode);
(game.inv_activated contains the ID of the InvItem that was clicked when for instance on_mouse_click(eMouseLeftInv) is called)

It works perfectly, thank you!

Even if I'm hopefully leaving the coding side of things soon, I don't want to be a code monkey and I'd still like to understand what was going on. Why does Gui.Processclick does not work? Isn't it supposed to simulate a click of that type in the position I tell it to?