Getting the inventory item's owner [SOLVED]

Started by Matti, Fri 08/05/2009 19:54:24

Previous topic - Next topic

Matti

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

Trent R

#1
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)
Code: ags

Character* ItemOwner() {
  GUIControl *control=GUIControl.GetAtScreenXY(mouse.x, mouse.y);
  return control.AsInvWindow.CharacterToUse;
}



~Trent
To give back to the AGS community, I can get you free, full versions of commercial software. Recently, Paint Shop Pro X, and eXPert PDF Pro 6. Please PM me for details.


Current Project: The Wanderer
On Hold: Hero of the Rune

Khris

It should work using this:

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

Matti

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.

Khris

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.

Matti

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

Code: ags
mouse.Mode=eModeInteract;


in the game_start() section.

Furthermore I have the following:

Code: ags

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:

Code: ags

int ItemOwner() {
  GUIControl *control=GUIControl.GetAtScreenXY(mouse.x, mouse.y);
  return control.AsInvWindow.CharacterToUse.ID;
}


And the following action for stealing an item:

Code: ags

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.

Khris

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:

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

Matti


Ah, yes, adding these lines to the on_mouse_click part made it work:

Code: ags

  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.

Trent R

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
To give back to the AGS community, I can get you free, full versions of commercial software. Recently, Paint Shop Pro X, and eXPert PDF Pro 6. Please PM me for details.


Current Project: The Wanderer
On Hold: Hero of the Rune

Matti

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:

Code: ags

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

Khris

Do you even still need this line:
inventory[game.inv_activated].RunInteraction(eModeInteract);
?
I think you can remove it.

Matti

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.

Trent R

If the object is only interactable by the owner, shouldn't that be under an else or else if statement?


~Trent
To give back to the AGS community, I can get you free, full versions of commercial software. Recently, Paint Shop Pro X, and eXPert PDF Pro 6. Please PM me for details.


Current Project: The Wanderer
On Hold: Hero of the Rune

Matti

#13
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.

SMF spam blocked by CleanTalk