Trade Inventory

Started by Gepard, Tue 06/04/2010 15:05:09

Previous topic - Next topic

Gepard

I have a problem creating a trade inventory for my game. I have a GUI with four inventory windows (similar to the one used in Fallout). One is the players inventory, on the other side is the traders (NPCs) inventory. Than there is inv window for the items that player wants to sell and another window for things he wants to buy. I want the player to be able to click on an item in his inventory and this item will be transfered into the sell inv window and also the other way around. When he click on an item in traders inventory, this item will be transfered to the inv window he wants to buy...

Now... How do I make a script that will "know" in which inventory window is the item located? Because now if I click on an item that is in players inventory, it could travel anywhere if you know what I mean. Also if there are two identical items, one in sellers inventory and the other in players inventory... Oooh! This is so hard. Please help anyone.

Thank you.
Drink up me 'arties! Yo ho!

Crimson Wizard

#1
I see two possibilities here.
1. When inventory item is selected, check mouse coordinates and compare them with inventory window positions.
2. Check which character owns selected item.

The second could work if all items are unique though... so I guess first variant is better in your case.

Matti

I had a similar problem once and somebody (Khris I think) helped me out using Crimson's first suggestion. I created an int:

Code: ags

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


..and then I checked which character's item was clicked:

Code: ags

function iWhatever_Interact(){
  if(ItemOwner()==1){
    //bla
  }
  else{
    //bla
  }
}


Quote from: Crimson Wizard on Tue 06/04/2010 15:10:42
1. When inventory item is selected, check mouse coordinates and compare them with inventory window positions.

Hm, that's quite simple and would've worked for me too. Haven't thought of that.

Crimson Wizard

Quote from: Mr. Matti on Tue 06/04/2010 15:47:02
Quote from: Crimson Wizard on Tue 06/04/2010 15:10:42
1. When inventory item is selected, check mouse coordinates and compare them with inventory window positions.

Hm, that's quite simple and would've worked for me too. Haven't thought of that.

Haha, actually I like your suggestion more, Mr. Matti ;) Looks more beautful code-wise.

Gepard

Thanks to both of you. Here is the code for items (after clicking on them):


Code: ags
if (GetGlobalInt(60)>0) {
 int seller = ItemOwner();
 if (ItemOwner()==0) {player.LoseInventory (isocks); character[INV1].AddInventory (isocks);}
 if (ItemOwner()==21) {character[INV1].LoseInventory (isocks); player.AddInventory (isocks);}
 if (ItemOwner()==22) {character[INV2].LoseInventory (isocks); character[INV3].AddInventory (isocks);}
 if (ItemOwner()==23) {character[INV3].LoseInventory (isocks); character[INV2].AddInventory (isocks);}
   }


Dont mind the globalint, its just to check if there is trade in progress.
Drink up me 'arties! Yo ho!

Khris

Just to be sure, you aren't going to write these four lines for every item there is in the game, right?

Gepard

Well... :D

Yes I am. Dont know how else to do that. To be exact the code now looks like this:

Code: ags
if (GetGlobalInt(60)>0) {
 int charsell = ItemOwner();
 
 if (ItemOwner()==0) {
		player.LoseInventory (isocks);
		character[INV1].AddInventory (isocks);
		value1 += inventory[5].GetProperty ("VALUE");
 }

 if (ItemOwner()==21) {
		character[INV1].LoseInventory (isocks);
		player.AddInventory (isocks);
		value1 -= inventory[5].GetProperty ("VALUE");
 }

 if (ItemOwner()==22) {
		character[INV2].LoseInventory (isocks);
		character[INV3].AddInventory (isocks);
	  value2 -= inventory[5].GetProperty ("VALUE");
 }

 if (ItemOwner()==23) {
		character[INV3].LoseInventory (isocks);
		character[INV2].AddInventory (isocks);
	  value2 += inventory[5].GetProperty ("VALUE");
 }

}


Value1 and 2 is displayed as a total value of all items that you want to sell/buy.
Drink up me 'arties! Yo ho!

Crimson Wizard

#7
I guess you can write a generic handling in on_mouse_click event. Ofcourse actual implementation depends on how your global script looks like, do you like adding more functions to be called from mouse_click function, etc, but anyway here's a simple example:


Code: ags

function on_mouse_click(MouseButton button)
{

......
 if (button == eMouseLeftInv)
 {
   if (GetGlobalInt(60)>0) {
     int charsell = ItemOwner();
     InventoryItem * iItem = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
 
       if (ItemOwner()==0) {
		player.LoseInventory (iItem);
		character[INV1].AddInventory (iItem);
	  value1 += iItem.GetProperty ("VALUE");
       }

       if (ItemOwner()==21) {
		character[INV1].LoseInventory (iItem);
		player.AddInventory (iItem);
	  value1 -= iItem.GetProperty ("VALUE");
       }

       if (ItemOwner()==22) {
		character[INV2].LoseInventory (iItem);
		character[INV3].AddInventory (iItem);
	  value2 -= iItem.GetProperty ("VALUE");
       }

       if (ItemOwner()==23) {
		character[INV3].LoseInventory (iItem);
		character[INV2].AddInventory (iItem);
	  value2 += iItem.GetProperty ("VALUE");
       }

   }
 }
......


}

Gepard

Yes, that works great!

THanks for help!
Drink up me 'arties! Yo ho!

Gepard

Now I have four inventory windows. Everything is working fine, considering moving items from one place to another. Now I need the "confirm trade" button to get all the items from one inventory into another inventory window. So far I managed to lose all inventory items from one window, but i dont know how to transfer them to another inventory.

 
Code: ags
int i = 1;
  while (i <= Game.InventoryItemCount) {
    character[INV1].InventoryQuantity[i] = 0;
    i++;
  }
  UpdateInventory();

Thanks!
Drink up me 'arties! Yo ho!

Khris

Code: ags
int i = 1;
  while (i <= Game.InventoryItemCount) {

    character[INV2].InventoryQuantity[i] += character[INV1].InventoryQuantity[i];

    character[INV1].InventoryQuantity[i] = 0;
    i++;
  }
  UpdateInventory();

Gepard

Oh yes, thats easy. Thanks. One more and hopefully last question. I am currently using your module Khris called Invamount. While it worked great so far, now Im having difficulties with it. It seems that when I add items to a character at game start like this:

 
Code: ags
character[B].AddInventory (ilockpicks);
  character[B].AddInventory (ilighthelmet);
  character[B].AddInventory (iammopack);
  character[B].AddInventory (iammopack);
  character[B].AddInventory (iammopack);
  character[B].AddInventory (iammopack);
  character[B].AddInventory (iammopack);


and than I open this four inventory windows gui, the ammo packs are displayed as one icon but the number is missing or not visible... And when I click on the ammo packs to move them to the inv window that contains things I wanna buy, the script always moves one more. If i click twice, I end up with three ammo packs but I only had to pay for two of them etc...
Drink up me 'arties! Yo ho!

Khris

Instead of adding the ammo pack 5 times, try:

Code: ags
  InvAmount.AddInv(character[B], iammopack, 5);


(The module calls an internal function to repaint the inventory item's sprite after the amount has changed. If you don't use the provided functions, that might happen too late or not at all. Always use the module's functions to add/lose more than one inv item.)

The code of that module is a bit outdated btw; I might update it at some point.

Gepard

Hm... Now it gives me this:


Error: run_text_script1: error -6 running function 'game_start':
Error: Null pointer referenced
in InvAmount (line 36)
from InvAmount (line 75)
from Global script (line 459)

 
Code: ags
InvAmount.AddInv (character[B], iammopack, 5);
  InvAmount.AddInv (character[B], ijerky, 5);
  InvAmount.AddInv (character[B], ibread, 2);
  InvAmount.AddInv (character[B], ilockpicks, 1);
  InvAmount.AddInv (character[B], ilighthelmet, 1);


Drink up me 'arties! Yo ho!

Khris

That means you didn't call the module's Init function first. Move the InvAmount.Init(...) line to the top of game_start().

Gepard


---------------------------
Illegal exception
---------------------------
An exception 0xC0000005 occured in ACWIN.EXE at EIP = 0x0043C24F ; program pointer is -42, ACI version 2.72.920, gtags (112,20)

AGS cannot continue, this exception was fatal. Please note down the numbers above, remember what you were doing at the time and notify CJ on the Tech forum.

in InvAmount (line 44)
from InvAmount (line 75)
from Global script (line 466)

Code: ags
function game_start() // called when the game starts, before the first room is loaded
  {
  //trade
    sellstuff.CharacterToUse = cF;
    giveinv.CharacterToUse = cInv1;
    takeinv.CharacterToUse = cInv2;
    sellerinv.CharacterToUse = cInv3;
  //other
    InvAmount.Init (3, 16, Inventory);
    InvAmount.Init (3, 16, giveinv);
    InvAmount.Init (3, 16, takeinv);
    InvAmount.Init (3, 16, sellerinv);
    mouse.Mode = eModeLookat;
    SetTimer (1, 36000);
//Traders
  //Belkirt
  Belkirt = 250;
  InvAmount.AddInv (character[B], iwater, 2);


Last line is the number 466

44 -   RawSaveScreen();
75 -   IAUpdInvItem(who, item);
Drink up me 'arties! Yo ho!

Khris

Right, you're using four inventory windows. InvAmount isn't built for that. I'm not sure why you're getting the error, the thing is you can't just call InvAmount.Init for every inv window and be done.
Plus, the RawSaveScreen business was a workaround; back then there were no DrawingSurfaces.

I might rewrite the module at some point in the future; until then you'll have to find another way.

Gepard

Ok, I will :f ) Thanks for all the help here in this topic.
Drink up me 'arties! Yo ho!

SMF spam blocked by CleanTalk