Let inv1 on inv2 have the same result as vice versa

Started by HandsFree, Sat 05/10/2013 10:05:43

Previous topic - Next topic

HandsFree

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

Khris

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.


monkey0506

#3
I tend to write a function like this:

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


Khris

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
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
  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?

monkey0506

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

Billbis

You all probably know this, but I just wanted to emphasize that you can link the same function to different events :

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

monkey0506

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

Billbis

Yes, you're right. It's useless for inventory item on inventory item usage. It is mostly useful when dealing with hotspots / objects.

SMF spam blocked by CleanTalk