Uh... I'm relatively new to all the inventory stuff and it's more complicated than I thought.
I have 4 players in my game who can all fight against each other. After a fight the winner can take one item out of the loser's inventory. In the game items don't turn into cursors, you just click them to use or steal them. I wanted to make the steal-thingie via the item's "interact with inventory item"-action. But I need to know whose item it is. If it's the actual player's item an info should pop up, if it's one of the enemy's items then the player should steal it.
Thanks in advance.
PS: If there's a command that can be easily found in the manual... then I didn't find it ;)
Maybe something with GUIControl.AsInvWindow (or whatever the command is). I'll look in the manual and see what I can throw together.
[Edit]: I think this might work, modify as needed. (Like an InvItem extender or such)
Character* ItemOwner() {
GUIControl *control=GUIControl.GetAtScreenXY(mouse.x, mouse.y);
return control.AsInvWindow.CharacterToUse;
}
~Trent
It should work using this:
int GetItemOwnerID() {
GUIControl*gc = GUIControl.GetAtScreenXY(mouse.x, mouse.y);
InvWindow*iw;
if (gc != null) iw = gc.AsInvWindow;
if (iw != null) return iw.CharacterToUse.ID;
return -1;
}
It's still tedious to put "Character*c = character[GetItemOwnerID()];" and following lines into every "interact with inventory item"-event though.
A better way would be to use a state variable and handle the stealing in on_mouse_click using eMouseLeftInv.
Thanks for the replies.
I'll try around today and see if I can get it to work (though I don't quite understand what you both wrote there...). I'll report back when it works or when I have problems.
Sorry for the late reply, for some strange reason my connection was down for the weekend.
I tested both versions and they work fine. It seems I completely forgot that one can declare functions that return pointers though. ;D
However, I noticed that calling this after a click on the default inventory always returns null because the default Invwindow's character ID is set to -1, i.e. the current player character.
So it's important to change that to 0/player.ID.
Okay, I guess I have it now but I encountered another problem, seemingly related to general inventory interaction.
I have set "Handle inventory clicks in script" to true and put
mouse.Mode=eModeInteract;
in the game_start() section.
Furthermore I have the following:
function on_mouse_click(MouseButton button) {
if (IsGamePaused() == 1) {
}
else if (button == eMouseLeft) {
ProcessClick(mouse.x, mouse.y, mouse.Mode );
}
}
This in the header of the global script:
int ItemOwner() {
GUIControl *control=GUIControl.GetAtScreenXY(mouse.x, mouse.y);
return control.AsInvWindow.CharacterToUse.ID;
}
And the following action for stealing an item:
function iTrank_klein_Interact()
{
if(ItemOwner()!=kampfspieler && grab){
character[ItemOwner()].LoseInventory(iTrank_klein);
character[kampfspieler].AddInventory(iTrank_klein);
grab=false;
}
}
But nothing happens when I click the item (iTrank_klein). There's no problem with the variables, even if I delete / change the if-statement or the resulting action nothing happens. So I guess there's something wrong with the inventory handling / on_mouseclick function or something else I don't know much about. I just want to have one cursor (which works fine) and one interaction for each item...
Help is appreciated.
First of all:
Quote from: headerDo not place functions here;
Put Trent's code right above on_mouse_click.
Then make the start of on_mouse_click look like this:
function on_mouse_click(MouseButton button) {
// if inv GUI's Visibility is set to "Pause game when shown", the eMouseLeftInv code needs
// to be above the IsGamePaused() line
if (button == eMouseLeftInv) { // handle left clicks on inv items
Character*owner = ItemOwner();
...
...
}
if (IsGamePaused() == 1) return; // don't handle standard clicks if game is paused
if (button == eMouseLeft) {
ProcessClick(mouse.x, mouse.y, mouse.Mode );
}
}
Ah, yes, adding these lines to the on_mouse_click part made it work:
else if (button == eMouseLeftInv) {
inventory[game.inv_activated].RunInteraction(eModeInteract);
}
I thought eMouseLeft + Process.Click would suffice, but well... I haven't worked on anything inventory-related for a long time now an didn't ever know much about it ::)
Thank you both, everything works fine now.
Quote from: KhrisMUC on Mon 11/05/2009 13:23:37
I tested both versions and they work fine. It seems I completely forgot that one can declare functions that return pointers though. ;D
And I forgot to add in null checks ;D so a combo of both codes would be best.
Matti, it's great that the RunInteraction works, but you're gonna be doing a
lot of duplicate code that way. Best to add a system under on_mouse_click that will work with any character and any item.
~Trent
You're right. And that's what I just did. I simply copied the item's interaction code to the on_mouse part and replaced the items name with inventory[game.inv_activated]. This is all(!) I got now and it seems to work perfectly:
int ItemOwner() {
GUIControl *control=GUIControl.GetAtScreenXY(mouse.x, mouse.y);
return control.AsInvWindow.CharacterToUse.ID;
}
function on_mouse_click(MouseButton button) {
if (IsGamePaused() == 1) {
}
else if (button == eMouseLeftInv) {
inventory[game.inv_activated].RunInteraction(eModeInteract);
if(ItemOwner()!=kampfspieler && grab){
character[ItemOwner()].LoseInventory(inventory[game.inv_activated]);
character[kampfspieler].AddInventory(inventory[game.inv_activated]);
grab=false;
}
}
else if (button == eMouseLeft) {
ProcessClick(mouse.x, mouse.y, eModeInteract );
}
}
Thanks again (for reminding me to keep the script as short as possible ;))
Do you even still need this line:
inventory[game.inv_activated].RunInteraction(eModeInteract);
?
I think you can remove it.
I don't need it for the stealing stuff to work, but the items should still be interactable (when they belong to the player, not the enemy). So yes, I need that line.
If the object is only interactable by the owner, shouldn't that be under an else or else if statement?
~Trent
There's only a few interactible objects and I include conditions in their event script.
Plus, most interactions can only be done when only the player's inventory is shown so it's automatically the owner who is using the items.