Different descriptions depending on item used: Is it possible?

Started by Indrid Cold, Thu 11/03/2010 10:47:51

Previous topic - Next topic

Indrid Cold

Hello everyone,

I've been trying to make a GUI that uses some elements from the one used in the Legend games Death Gate and Shannara. Specifically, I've had problems trying to make a different text appear depending on which inventory item is used on which thing.

For example, say there's a door in the room that's locked. If the player's active inventory item is a key, the text should say "Unlock door with key". If it's a hammer, it should say "Break door with hammer". If it's a magic wand, it would say "Make door disappear". And so on.

If there was a "mouseover" function for everything, it would be simple to define specific items and text for each thing (object, hotspot, character, invitem) but as there isn't it all has to go in repeatedly_execute, right?

For objects and hotspots that's not much of a problem, since they're unique to each room. There can be a function called there that checks the current object/hotspot and active inventory and returns the relevant line. Doing the same for characters and inv. items though means there has to be one global function, as they could be in any room, and I'm concerned it would be a problem for memory/performance issues.

Is there something I'm overlooking, or a simpler way to make this work?

Khris

First of all, there won't be any memory/performance issues. :)

To keep things tidy I'd handle inventory items and characters in the global script and send hotspots and objects to the room script. Like this:

Code: ags
function repeatedly_execute() {

  String ln = Game.GetLocationName(mouse.x, mouse.y);
  int lt = GetLocationType(mouse.x, mouse.y);
  InventoryItem*i = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);

  if (player.ActiveInventory == null) {    // no inv item selected, display name of hotspot under mouse
    if (i != null) lblAction.Text = i.Name;
    else lblAction.Text = ln;
  }

  else {

    if (i != null) InventoryAction(player.ActiveInventory, i.Name);

    else if (lt == eLocationCharacter) CharacterAction(player.ActiveInventory, ln);

    else if (lt == eLocationHotspot) {
      Hotspot*h = Hotspot.GetAtScreenXY(mouse.x, mouse.y);
      CallRoomScript(h.ID);
    }

    else if (lt == eLocationObject) {
      Object*o = Object.GetAtScreenXY(mouse.x, mouse.y);
      CallRoomScript(o.ID + 50);
    }

    else  InventoryAction(player.ActiveInventory, "");
  }
}


Top of global script:

Code: ags
String verb[100];

void SetLines() {

  verb[iHammer.ID*2] = "Smash";
  verb[iHammer.ID*2+1] = "Smash %s with hammer";
  verb[iKey.ID*2] = "Unlock";
  verb[iKey.ID*2+1] = "Unlock %s with key";
  ...
}

// inside game_start
  SetLines();


void InventoryAction(InventoryItem*ai, String second) {

  if (second == "") lblAction.Text = verb[ai.ID*2];
  else lblAction.Text = String.Format(verb[ai.ID*2+1], second);
}


Similarly for characters.

In room scripts:
Code: ags
void on_call(int p) {
  if (p < 50) {  // hotspots
    ...
  }
  else {   // objects
    p -= 50;
    ...
  }
}


This is very generic, you can still optimize this.

-You could use two inventory item Custom Properties to store the verb strings instead of an array.
That way you can't change them during the game, you can still intercept specific combinations and use a different string though.

-You could take it even further and add a Custom Property to all hotspots/objects/etc. for each inventory item.
Then use a dummy character to store the string used when there's nothing under the mouse.

The best way to do this heavily depends on the ratio of default/special texts.

EDIT:
Actually, the last method seems to be the best: you can put all the default texts in the property, then change them individually for every object/hotspot/etc.
So disregard all the code if you want to go for that :)

Indrid Cold

Thanks for the ideas!

I had thought to use a single custom property and make it a list, using a format like
Code: ags
{x}aaa|{y}bbb

Where x, y would be inventory ID numbers and aaa/bbb the relevant text for each item. I didn't think of using separate custom properties for each item, though.

What I was afraid of concerning the function method, was that the functions for characters and inv. items would get too big (as there would be an "else if" for most characters/items), and therefore it would take "too long" to execute repeatedly. If this is not an issue however, then I guess that method is viable as well.

In any case, thanks again for the suggestions. :)

Khris

While it shouldn't be an issue, you can avoid this by using arrays.

SMF spam blocked by CleanTalk