[SOLVED] Creating an Inventory GUI as part of a context menu system

Started by SpacePirateCaine, Sun 02/02/2014 03:16:43

Previous topic - Next topic

SpacePirateCaine

Ahoy there - back again with a question about GUI design.

I managed to custom-create from scratch a GUI that functions similarly to a Windows-style right click context window, with the default functions working like a charm, but I have run into a bit of a snag when creating an inventory system that chains off of the existing GUI.

First, the GUI as I have it:


I have successfully built the section that correctly positions the Inventory GUI next to the Context Menu verbcoin, but what you are seeing there listed as "Inventory Item" is currently a placeholder button. It was originally my plan to have the GUI automatically populate itself with buttons representing the individual inventory items and resizing the GUI based on the number of buttons displayed, then having the game set player.ActiveInventory = <Whatever the button represents> then run a ProcessClick based on mouse coordinates saved as String a when the first GUI was opened inside the function btnInventory_OnClick(...).

Unfortunately, I am having trouble figuring out if it's even possible to generate GUI buttons at runtime and if that's even feasable, how to populate that list based on a list of inventory currently carried by the player/set so that they would be able to set the correct String for a call from ActiveInventory.

Maybe I'm thinking of this in needlessly complicated terms? If someone could point me in the right direction, it would be greatly appreciated. Should I change my method and go with an InvWindow, and if so, how would I display item names as opposed to icons and set the game to handle inventory item clicks as using them immediately, instead of setting them as the cursor, etc.?

I've been poring over the manual for a couple of days now and haven't quite figured it out.

Many thanks.
Check out MonstroCity! | Level 0 NPCs on YouTube! | Life's far too short to be pessimistic.

Ghost

You can't create buttons at runtime BUT why not just using button graphics as inventory item graphics? That way you can just create a normal inventory window. And since you can use different sprites for an item "in inventory" and "on cursor", this sounds like a feasible idea.
Would make any translation very hard, though- the buttons would have to have their item names as part of the sprite. No string formatting. But even that could be worked around with using dynamic sprites and printing the text on them.

As for "using an inventory item instantly", that is very easy to do. I usually use a custom property that is checked when an item is clicked (General Settings- override Inv. Clicks). It's very little code actually- you can just add it into the on_mouse_click function:

Code: AGS

// Left Mouse Button on Inventory Item
	// when no inventory is selected:
	// - INTERACT with target 
	// - SELECT target
	// else
	// - USE inventory on target
	else if (button == eMouseLeftInv)
	{
		InventoryItem *i = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
				
		if (i != null)
		{
			if (i.GetProperty("propInstantUse") == true)
			{
				if (player.ActiveInventory == null)
				{
					i.RunInteraction(eModeInteract);
				}
				else
				{
					i.RunInteraction(eModeUseinv);
				}
			}
			else
			{
				if (player.ActiveInventory == null)
				{
					player.ActiveInventory = i;
				}
				else
				{
					if (i.ID != player.ActiveInventory.ID)
					{
						i.RunInteraction(eModeUseinv);
					}
				}
			}
		}
	}

SpacePirateCaine

#2
Thank you very much Ghost, I was suspecting that I was going to need to do something like making the inventory graphics just look like the text that they would ultimately display. I've done so and it is fairly cleanly showing up - you have my thanks.

Unfortunately, I'm still running into some trouble with the forced interactions, as if I'm reading correctly, your script seems to be a method of interacting with the inventory specifically. I'm more looking for the following to happen:

You right click a character, object or hotspot and open the gVerbcoin GUI. Clicking Use... opens the gInventory GUI and displays a list of available inventory.
When you click the inventory inside the gInventory GUI, I am attempting to have the game process it as though the player had selected the inventory (player.ActiveInventory = i;) then process a click at the coordinates of the original right click (Stored as global variables MouseX and MouseY) as though they had used the inventory at that location.

Additionally, I never want to use inventory as a cursor, inventory should only be accessed and used via the context menu.

I attempted the following:

Code: ags

  else if (button == eMouseLeftInv)
  {
    InventoryItem *i = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
    if (i != null)
    {
      player.ActiveInventory = i;
      ProcessClick(MouseX, MouseY, eModeUseinv);
    }
  }


Thinking that it would suffice, but it appears that eModeUseinv only sets the cursor to the active inventory?

Is there some way to utilize i.RunInteraction(eModeUseinv) or perhaps (eModeInteract) at a specific location, as though the player had clicked the object on the specified x/y coordinates? In practice, this should be very similar to the way Gemini Rue handles inventory.
Check out MonstroCity! | Level 0 NPCs on YouTube! | Life's far too short to be pessimistic.

Khris

If your solution doesn't work, try this:
Code: ags
  else if (button == eMouseLeftInv) {
    player.ActiveInventory = inventory[game.inv_activated];
    mouse.Mode = eModeInteract; // reset cursor mode in case setting ActiveInv changes it
    int lt = GetLocationType(click_x, click_y);
    if (lt == eLocationHotspot) {
      Hotspot *h = Hotspot.GetAtScreenXY(click_x, click_y);
      h.RunInteraction(eModeUseinv);
    }
    ...  // same for Object/Character
  }


I also remember posting code that would create inv item graphics on the fly using a DynamicSprite and "drawStringing" the name to it.
And you can use buttons just fine by creating as many as AGS allows and turning unused ones invisible.

Ghost

Hm. So basically you don't need anything an inventory item could give you- maybe then a listbox would be better?
You can read in inventory items into a list box- basically you create a loop, iterate through the items via their index, and read in their name. Not sure if this is easy and/or comfortable though; you'd need a way to check if the item is held by the player.
But this would give you better control over populating the GUI. And a list box would then just run some code to make the interaction happen after clicking on an item...

This is guessing aloud but I remember at least one game doing it that way.

Khris

True, but mouse over highlighting is much easier with buttons.
And you don't even have to hide or reposition them, just decrease the size of the GUI.

SpacePirateCaine

Thank you both,

The script you posted works perfectly for my needs, Khris. I will need to consider what needs to be done for highlighting on mouseover, but at the moment this does exactly what I need it to and I can come back to that issue later. Your help is greatly appreciated.
Check out MonstroCity! | Level 0 NPCs on YouTube! | Life's far too short to be pessimistic.

SMF spam blocked by CleanTalk