Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: HandsFree on Sat 05/10/2013 10:05:43

Title: Let inv1 on inv2 have the same result as vice versa
Post by: HandsFree on Sat 05/10/2013 10:05:43
If I want in general that using inventory1-on-inventory2 always gives the same result as using inv2-on-inv1... Is there a better way to achieve that other than just writing everything twice? I'm aware of the possiblilty to put code in a function and call that twice, but I'm hoping it can be generalized more.

thanks
Title: Re: Let inv1 on inv2 have the same result as vice versa
Post by: Khris on Sat 05/10/2013 11:17:21
Quote from: HandsFree on Sat 05/10/2013 10:05:43put code in a function and call that twice
is exactly what you need to do.

I don't see how making it even shorter would be possible, you have to establish that using x on y causes z and using y on x causes z.
Title: Re: Let inv1 on inv2 have the same result as vice versa
Post by: HandsFree on Sat 05/10/2013 18:20:11
OK, that's the way then. :)
thanks
Title: Re: Let inv1 on inv2 have the same result as vice versa
Post by: monkey0506 on Sat 05/10/2013 21:06:41
I tend to write a function like this:

Code (ags) Select
void Combine(this InventoryItem*, InventoryItem *other)
{
  if (other == null) return;
  if (this.ID > other.ID)
  {
    // make sure that this.ID is the lower ID
    other.Combine(this);
    return;
  }
  if (this == iCarrot)
  {
    if (other == iGrater)
    {
      player.LoseInventory(iCarrot);
      player.AddInventory(iGratedCarrots);
    }
  }
}


This function prevents you from having to duplicate the interaction code. You can call it with the inventory items in either order and it will sort it so your interactions can be defined in ascending order (based on item ID).
Title: Re: Let inv1 on inv2 have the same result as vice versa
Post by: HandsFree on Sun 06/10/2013 10:03:57
Interesting, I'll give that a try. :cool:
thanks
Title: Re: Let inv1 on inv2 have the same result as vice versa
Post by: Khris on Sun 06/10/2013 13:09:45
I'm a bit confused by this actually.

First of all, if your game doesn't have a huge amount of combinations like that, what I would do is this:
Code (ags) Select
function iCarrot_Useinv {
  if (player.ActiveInventory == iGrater) grate_carrot();
  else Unhandled(); // custom unhandled function or similar
}

The same for the the grater obviously, then a function called grate_carrot() further up.

Monkey:
I can see this Combine function being useful, but only if it is called directly inside on_mouse_click, as in
Code (ags) Select
  else if (button == eMouseLeftInv) {
    if (player.ActiveInventory != null) player.ActiveInventory.Combine(inventory[game.inv_activated]);
    ...
  }

Otherwise I don't see how you're avoiding duplicate interaction code. Is this how you intended it to be used?
Title: Re: Let inv1 on inv2 have the same result as vice versa
Post by: monkey0506 on Sun 06/10/2013 21:22:43
Well, arguably, even if you had separate event handlers, the only duplicate code would be a single function call with no logic, which is pretty typical for methods that avoid code duplication. Calling it directly from on_mouse_click would of course make it even simpler, but either way it would still be simpler to do that than to do:

Code (ags) Select
function iCarrot_Useinv()
{
  if (player.ActiveInventory == iGrater) grate_carrot();
  else Unhandled(); // custom unhandled function or similar
}

function iGrater_Useinv()
{
  if (player.ActiveInventory == iCarrot) grate_carrot();
  else Unhandled(); // custom unhandled function or similar
}


This actually involves duplication of logic, whereas either usage of the function (calling it from on_mouse_click or from the event handlers) I provided prevents duplicating the logic.
Title: Re: Let inv1 on inv2 have the same result as vice versa
Post by: Billbis on Tue 08/10/2013 20:06:34
You all probably know this, but I just wanted to emphasize that you can link the same function to different events :
(http://image.noelshack.com/fichiers/2013/41/1381259041-iposter.png)(http://image.noelshack.com/fichiers/2013/41/1381259036-ikey.png)
Code (AGS) Select
function iPoster_UseInv()
{
  //some code here.
}

It may be not the more ortodox way to avoid duplicate code, but IMO it is one of the advantages of the events-code linking system.
Title: Re: Let inv1 on inv2 have the same result as vice versa
Post by: monkey0506 on Tue 08/10/2013 21:06:43
The problem with that route is that you then have no idea which item was used on the other.

The event handler would then have to be something like this to avoid code duplication:

Code (ags) Select
function iPoster_UseInv()
{
  InventoryItem *a = inventory[game.inv_activated];
  InventoryItem *b = player.ActiveInventory;
  if (((a.ID > b.ID) && !((a == iPoster) && (b == iKey))) || ((a == iKey) && (b == iPoster)))
  {
    a = player.ActiveInventory;
    b = inventory[game.inv_activated];
  }
  if (a == iPoster)
  {
    if (b == iKey)
    {
      // interactions here
    }
  }
}


That's a rather horrible way of preventing code duplication.
Title: Re: Let inv1 on inv2 have the same result as vice versa
Post by: Billbis on Wed 09/10/2013 07:46:14
Yes, you're right. It's useless for inventory item on inventory item usage. It is mostly useful when dealing with hotspots / objects.