custom inventory (SOLVED)

Started by Husky, Thu 05/10/2006 04:34:18

Previous topic - Next topic

Husky

Hello.Ã,  I'm trying to implement a few different features into my custom inventory.Ã,  Although, I've found solutions in the forms to do some of these in isolation, when I try to do everything, it gets complicated and does not work.Ã,  Also, I'm pretty new to coding, but am having fun giving it a go.Ã,  However, if my approach seems mental, just let me know and we'll go in a different direction.

Goals for custom inventory:
1.) Rectangular graphic highlight boarder around inventory items on mouse over
2.) Display inventory name on GUI label on mouse over
3.) Same rectangular graphic highlight boarder on empty inventory slots on mouse over
4.) Display names like ”nothing” or “zilch” on mouse over of empty inventory slots

Attempted solution (possibly mental):
Ã,  Ã,  Ã, My solution for highlighting was to place buttons on top of the GUI inventory window.Ã,  I made the button graphics invisible by default, then I have the button graphic switch to a highlight rectangle when there is a mouse over.
Ã,  Ã,  Ã, The pros of this solution are: 1) the highlights flash on regardless if there is inventory in the slot.Ã,  2) The highlights are the exact shape and size that I want.Ã,  3.)Ã,  Using buttons lets me display things like “nothing” or “zilch”Ã,  when the mouse is over an empty slot.Ã,  See code:

In repeatedly_execute
Code: ags
 if (Button.GetAtScreenXY(mouse.x, mouse.y) == btnInv01) InvLabel.SetText("Nothing");
Ã,  else if (Button.GetAtScreenXY(mouse.x, mouse.y) == btnInv02) InvLabel.SetText ("Nil");
Ã,  else if (Button.GetAtScreenXY(mouse.x, mouse.y) == btnInv03) InvLabel.SetText ("Nada");
Ã,  else if (Button.GetAtScreenXY(mouse.x, mouse.y) == btnInv04) InvLabel.SetText ("Zilch");
Ã,  else if (Button.GetAtScreenXY(mouse.x, mouse.y) == btnInv05) InvLabel.SetText ("Zip");
Ã,  else if (Button.GetAtScreenXY(mouse.x, mouse.y) == btnInv06) InvLabel.SetText ("Zippo");
Ã,  else InvLabel.SetText("Inventory");


Ã,  Ã,  Ã, The cons of this solution are: 1) I can't select my inventory items!Ã,  Oh no!Ã,  It seems that having a button in the same place as a potential inventory item is somehow interfering.Ã,  2.) I fear the buttons may also interfere with displaying the inventory item's names (when they are actually there) on a GUI label with mouse over.Ã,  However, I don't know if this fear has any foundation because I can't get the following code to work even in isolation anyway:

In repeatedly_execute
Code: ags
 InventoryItem *item = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
if (item == null) { /* do nothing */ } // if no GUI control there, do nothing
else {
 String buffer=String.Format("%s", InventoryItem.GetAtScreenXY(mouse.x, mouse.y));
 InvLabel.SetText(buffer);
}


Anyway, I know this is a long post.Ã,  However, if you do have the inclination and time, your thoughts on this matter would be greatly appreciated and of much value to me.

Thanks in advance.

Khris

Code: ags
 String buffer=String.Format("%s", InventoryItem.GetAtScreenXY(mouse.x, mouse.y));
won't work because InventoryItem.GetAtScreenXY(mouse.x, mouse.y) returns an InventoryItem, not a S/string.
You'd have to use:
Code: ags
 InventoryItem*i=InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
 if (i!=null) String buffer=String.Format("%s", i.Name);


The two cons are related. My guess is that the buttons prevent InventoryItem.GetAtScreenXY(mouse.x, mouse.y) from returning the Item.

There's no Button.GetAtScreenXY(), so at first, change this
Code: ags
 if (Button.GetAtScreenXY(mouse.x, mouse.y) == btnInv01) InvLabel.SetText("Nothing");
  else if (Button.GetAtScreenXY(mouse.x, mouse.y) == btnInv02) InvLabel.SetText ("Nil");
...
to
Code: ags
 InventoryItem*AtMouse;
 GuiControl*gc=GuiControl.GetAtScreenXY(mouse.x, mouse.y);
Button*b;
if (gc!=null) b=gc.AsButton;
if (b!=null) {
  if (b==btnInv01) {
    InvLabel.SetText("Nothing");
    AtMouse==InvWindow.ItemAtIndex[0];
  }
  else if (b==btnInv02) {
    InvLabel.SetText("Nil");
    AtMouse==InvWindow.ItemAtIndex[1];
  }
}
...

As you can see, I'm setting the InventoryItem at the mouse position in the which-button-check.
Change InvWindow to whatever your inventory window is called. You might have to adjust the index of ItemAtIndex[X], too.

Hope this helps. Not tested, but should put you on the right track.

SSH

Make sure the buttons and/or GUI that are over the inv window have their Clickable property turned off.
12

Husky

Got it!!!
Thank you very much for the help, KhrisMUC and SSH.

First, I turned off the clickable properties for the GUI buttons.

Next, here is the final code for one of the buttons: it says “nothing” with no inventory in slot and says the proper inventory name when inventory is in the slot, and highlights regardless if there is inventory or not.

Code: ags

if (Button.GetAtScreenXY(mouse.x, mouse.y) == btnInv01) {
Ã,  btnInv01.NormalGraphic = (77);Ã,  //Makes highlight regardless of inventory present
Ã,  InventoryItem*item = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
Ã,  Ã,  if (item == null) {Ã,  //no inventory, say "nothing"
Ã,  Ã,  Ã,  InvLabel.SetText("Nothing");
Ã,  }
Ã,  Ã,  else {Ã,  //otherwise, say the inventory name 
Ã,  Ã,  Ã,  String buffer=String.Format("%s", item.Name);
Ã,  Ã,  Ã,  InvLabel.SetText(buffer);
Ã,  }
}


...and then to turn off the highlights...

Code: ags

if (Button.GetAtScreenXY(mouse.x, mouse.y) != btnInv01) btnInv01.NormalGraphic = (68);


It took me a while to get the code just right, figuring out the syntax and all, but it was well worth it.
Thanks again.

Khris

I'm curious:
Button.GetAtScreenXY(mouse.x, mouse.y) won't compile for me, it throws a "Type mismatch: cannot convert 'GUIControl*' to 'Button*'"

And after typing Button., I don't even get an auto-complete window.

I'm using 2.72.652, isn't that the latest version?

Husky

#5
KhrisMUC,
Regarding Button.GetAtScreenXY(mouse.x, mouse.y).
Ã,  Ã,  Ã, My bad.
Ã,  Ã,  Ã, I'm using v2..72.650, however, it looks like I've had enforce new-style strings unchecked the whole time I've been working on this.
Ã,  Ã,  Ã, Maybe this is what let me get away with using that command?
Ã,  Ã,  Ã, It's a little tough on my end because I'm new-ish at programming and I'm mostly teaching myself from reading past posts.Ã,  So, it is sometimes hard for me to distinguish between what is the new code and what is the old code or simply between good code and bad code.
Ã,  Ã,  Ã, I do appreciate your pointing this out so I can continue improving my coding technique.
Ã,  Ã,  Ã, Thanks again for the help.

[EDIT:]Ã,  As pointed out by KhrisMUC, having enforce new-style strings unchecked is unrelated to this situation afterall.

Khris

enforce new-style strings disables the old string type. You probably meant enforce object-oriented scripting.

But that doesn't matter in this case; basically, everyting with a period in the middle is OO, and you've only used new code, as far as I can see.
I'm just wondering why you were able to compile that line, since I thought that a Button pointer could only be created by using GUIControl.AsButton.

And according to the manual, there's no Button.GetAtScreenXY(...).
AND I tried it and it didn't compile.

strazer

Perhaps "Button" is the name of one of his GUI controls?
And although GetAtScreenXY is intended to be used statically (i.e. GUIControl.GetAtScreenXY), maybe AGS just doesn't catch the error if the object used is also of the GUIControl type.

Husky

Hey guys,
Here is the post where I learned about the Button.GetAtScreenXY(mouse.x, mouse.y) command.
http://americangirlscouts.org/bbc.com/yabb/index.php?topic=24804.0
See Ashen's quote second from the last.
I've been using this code all over my script.
I want to be using the proper code to prevent future trouble.Ã,  Is this truly wrong?
Thanks again.

Ashen

#9
Huh, and I was going to post saying Button.GetAtScreenXY does not and AFAIK never has existed...
I guess it's just a 'loophole' in the language, as strazer said - you can't do Button *theButton = Button.GetAtScreenXY(mouse.x, mouse.y); (won't compile - "can't convert GUIControl* to Button*"), but the code in the other thread seems to work, even in 2.72. It also seems to work with the other Control types (Label.GetAtScreenXY, etc).

Perhaps because the individual pointer types are contractions of GUIControl.As(Type) (or at least behave similarly) it shortcuts the need for the AsType check KhrisMUC showed? Not that GuiControl.AsButton.GetAtScreenXY works, mind you.
I know what you're thinking ... Don't think that.

monkey0506

#10
Button, Label, etc. are derived from the GUIControl class, so they all have the same function implemented, whether it autocompletes or not. You can't create a Button pointer (Button*) from a GUIControl pointer (GUIControl*) which is what will be returned regardless of what was actually typed. However, what you could do is compare a GUIControl to a Button, so even though Button.GetAtScreenXY returns a GUIControl*, you can still compare that pointer to a Button.

Also, InventoryItem.Name is a String, so String.Format("%s", item.Name) is redundant. As is setting a temporary variable to item.Name's value. You could just put "InvLabel.Text = item.Name;"

[EDIT:]

Just to clarify, Button.GetAtScreenXY is the same as GUIControl.GetAtScreenXY, however it is confusing because it returns a GUIControl*, not a Button* as you might expect when typing Button.GetAtScreenXY. So technically you should use GUIControl.GetAtScreenXY, which is still comparable to Button*s, though you can't assign it's value into a Button* directly (you have to use the GUIControl*'s AsButton property to cast it to a Button*).

Husky

#11
The deep reasoning behind all this is a little over my head.Ã,  However, from what I'm gathering, I should change all instances of Button.GetAtScreenXY(mouse.x, mouse.y) to GUIControl.GetAtScreenXY(mouse.x, mouse.y).
For instance:
Code: ags

if (Button.GetAtScreenXY(mouse.x, mouse.y) == btnIconWalk) LowLabel.Text = "Walk to";
 

is now
Code: ags

if (GUIControl.GetAtScreenXY(mouse.x, mouse.y) == btnIconWalk) LowLabel.Text = "Walk to";

Simple as that?Ã,  Yes?Ã,  The code runs fine both ways, but I'm gathering that the second way is proper and not simply benefiting from a programming loophole.

Monkey_05_06, thank you for the explanation of InventoryItem.Name being a String.Ã,  I have fine tuned my code per your suggestion.

Thanks everybody.Ã,  The code is running great and accomplishing what I hoped for.

[EDIT:] monkey_05_06, thanks for the additional explanation.Ã,  The deeper reasoning is now more clear to me.

monkey0506

It's not really a loop-hole per se, it's just the way that the GUIControl and Button structures are defined. The Button class is derived from the GUIControl class, so any properties of a GUIControl are also properties of a Button. This includes static member functions like GUIControl.GetAtScreenXY. So even though it doesn't autocomplete, Button.GetAtScreenXY is technically a valid function call. However, like I said before, it returns a GUIControl*, so it's safer to use GUIControl.GetAtScreenXY to prevent the line of thinking that Button.GetAtScreenXY would return a Button* (which though GUIControl*s and Button*s can be compared, you can't assign the value of one to the other).

I hope I've explained myself a little better here Husky, though in any case, you got the main point that you should use GUIControl.GetAtScreenXY not Button.GetAtScreenXY.

~Cheers

SMF spam blocked by CleanTalk