Unhandled Events - Not triggering during the game [SOLVED]

Started by Tenacious Stu, Thu 14/02/2013 01:19:41

Previous topic - Next topic

Tenacious Stu

Hi everyone

I'm trying to get the unhandled event function to work properly, but everything I've tried just seems to have no effect in-game. I'm not getting any errors with my code, but whatever I seem to try, when I right click or left click on an object/character/hotspot that has no events scripted, none of the unhandled events seem to trigger and nothing happens.

Here's the code I've tried:

Code: AGS
function unhandled_event(int what, int type) {

   //  Unhandled Hotspot
   if (what == 1) {         // Hotspot      
      if (type==1) {         // 1    1   Look at hotspot
      }
      else if (type==2) {  //  1    2   Interact with hotspot
      }
      else if (type==3) {  //  1    3   Use inventory on hotspot
      }
      else  {                     //  Undefined
      }
   }
      
   //  Unhandled Object
   else if (what== 2) {   
      // 
      if (type==0) {         //  2    0   Look at object
         Display("It looks fine.");
      }
      else if (type==1) {  //  2    1   Interact with object
          Display ("You have more important things to worry about at the moment.");
      }
      else if (type==3) {  //  2    3   Use inventory on object
      }
      else  {                     //  Undefined
      }
   }

   //  Unhandled Character
   else if (what==3)  {  
   //
      if (type==0) {  //  3    0   Look at character
      cBoy.Say ("Looking good.");
      }
      else if (type==1) {  //  3    1   Interact with character
      cBoy.Say ("I don't want to interact with him/her.");
      }
      else if (type==3) {  //  3    3   Use inventory on character
      }
      else  {                     //  Undefined
      }
   }
      
   // Unhandled Inventory
   else if (what==5) {
     //
      if (type==0) {  //  5    0   Look at inventory
      }
      else if (type==1) {  //  5    1   Interact with inventory (currently not possible)
      }
      else if (type==3) {  //  5    3   Use an inventory item on another
      }
      else  {                     //  Undefined
      }     
   }

  // Unhandled Undefined
   else {
      // This isn't supposed to happen
   }
}


I also tried this:

Code: AGS

function unhandled_event(int what, int type) {

	if ((what==1)&&(type==1)) { //Look at Hotspot
		cBoy.Say ("Nice Hotspot.");
	}
	else if ((what==1)&&(type==2)) { //Interact with Hotspot
		cBoy.Say("I'm not touching that.");
	}
	else if ((what==1)&&(type==3)) { //Use Inventory on Hotspot
		cBoy.Say("I don't want to.");      
	} 
	else if ((what==2)&&(type==0)) { //Look at Object
		cBoy.Say("Nice Object.");
	} 
	else if ((what==2)&&(type==1)) { //Interact with Object
		cBoy.Say("I don't want that Object");
	} 
	else if ((what==2)&&(type==3)) { //Use Inventory on Object
		cBoy.Say("Those two objects won't work together.");      
	}
	else if ((what==3)&&(type==0)) { //Look at Character
		cBoy.Say("Looking good.");
	} 
	else if ((what==3)&&(type==1)) { //Interact with Character
		cBoy.Say("I don't want to touch them.");
	}
	else if ((what==3)&&(type==3)) { //Use Inventory on Character
		 cBoy.Say("I'm not giving my stuff away.");      
	}
}


I've also tried just having this:

Code: AGS
function unhandled_event (int what, int type) {

  if (what == 2) {  // object
    if (type == 0) {  // look at object
      cBoy.Say ("Wow, nice object.");
    }
  }
}


But whatever I seem to try nothing works. It's making me think that it may have something to do with the way I'm interacting with things on mouse click. My code for that is here:

Code: AGS
function on_mouse_click(MouseButton button) {
  CursorMode mode = eModeInteract;
  if ((button == eMouseRight) || (button == eMouseRightInv)) mode = eModeLookat;
  else if (player.ActiveInventory != null) mode = eModeUseinv;
  if ((button == eMouseLeftInv) || (button == eMouseRightInv))
  {
    InventoryItem *iat = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
    if (iat) {
      if (iat.IsInteractionAvailable(mode)) iat.RunInteraction(mode);
      else if ((button == eMouseLeftInv) && (player.ActiveInventory == null)) player.ActiveInventory = iat;
      else if ((button == eMouseRightInv) && (player.ActiveInventory != null)) player.ActiveInventory = null;
    }
  }
  else if (IsInteractionAvailable(mouse.x, mouse.y, mode)) ProcessClick(mouse.x, mouse.y, mode);
  else if ((button == eMouseLeft) && (player.ActiveInventory == null))
  {
    ProcessClick(mouse.x, mouse.y, eModeWalkto);
  }
  else if ((button == eMouseRight) && (player.ActiveInventory != null))
  {
    player.ActiveInventory = null;
  }
}


Or perhaps, there is some setting that I have wrong that won't let me use the unhandled event function?

I hope you guys can help me out. Thanks in advance  :smiley:

geork

The problem may lie in this line:
Code: AGS
else if (IsInteractionAvailable(mouse.x, mouse.y, mode)) ProcessClick(mouse.x, mouse.y, mode);

From the manual:
Quote[isInteractionAvailable] is very similar to ProcessClick, except that rather than carry out any interactions it encounters, it simply returns 1 if something would have happened, or 0 if unhandled_event would have been run.
Therefore, you are only calling ProcessClick when an interaction IS available, and never when it would carry over to an unhandled event.
You could try changing it to this:
Code: AGS
//from the bottom half
  else if ((button == eMouseLeft) && (player.ActiveInventory == null) && (GetLocationType(mouse.x, mouse.y) == eLocationNothing))
  {
    ProcessClick(mouse.x, mouse.y, eModeWalkto);
  }
  else if ((button == eMouseRight) && (player.ActiveInventory != null))
  {
    player.ActiveInventory = null;
  }
  else ProcessClick(mouse.x, mouse.y, mode);


The GetLocationType check in line 2 means that clause is executed when the cursor is not over a hotspot, object or character.

Hope this helps! :)

Khris

Indeed.
To quote the manual:
Quoteunhandled_event (int what, int type)
    Called when an event occurs, but no handler is set up in the Events list.

Instead of rewriting unhandled_event (twice) when it didn't work, why didn't you simply put a Display command at the start of the function? That way you would have noticed immediately that it isn't called at all.

Tenacious Stu

@Khris

Thanks Khris, to be honest I've never used a Display command to check code when in game. I'm not sure how to place one? In this instance would it have shown that nothing was happening, rather than running through the unhandled event code, allowing me to see that the problem lay elsewhere? I'll try to use this with future issues.

@geork

Thanks. Your code seems to work, but is there a tweak I can make to allow unhandled events to be called when an inventory is clicked? So that when you look at an inventory item or use an item with another item it triggers unhandled events? I think I understand that it isn't working because the same reason, in the fist half of the code it says

Code: AGS
if (iat.IsInteractionAvailable(mode)) iat.RunInteraction(mode);


which will run the interaction if one is available, but what if there isn't one available? I'm not sure how to rejigger the code, so that it uses unhandled events. Would it be something similar to what you did with the second half of the code?

This is how my code looks at the minute (excuse all the comments, I was trying to gain a better understanding of the whole thing)

Code: AGS
function on_mouse_click(MouseButton button) {
  CursorMode mode = eModeInteract;
  if ((button == eMouseRight) || (button == eMouseRightInv)) mode = eModeLookat; //If the player right clicks or right clicks on an inventory item, it will Look at what is being clicked on
  else if (player.ActiveInventory != null) mode = eModeUseinv; //if the player has an active inventory item it will use inventory
  if ((button == eMouseLeftInv) || (button == eMouseRightInv)) //if the player right or left clicks on inventory
  {
    InventoryItem *iat = InventoryItem.GetAtScreenXY(mouse.x, mouse.y); // "iat" is whether there is an inventory item being clicked on
    if (iat) { // If there is an inventory item being clicked on:
      if (iat.IsInteractionAvailable(mode)) iat.RunInteraction(mode); // if there is an interaction available then run it
      else if ((button == eMouseLeftInv) && (player.ActiveInventory == null)) player.ActiveInventory = iat; //If Player Left Clicks and currently does not have an inventory item selected then it will select one
      else if ((button == eMouseRightInv) && (player.ActiveInventory != null)) player.ActiveInventory = null; //If Player Right Clicks and has an inventory item selected, it will deselct the item
    }
  }
    else if ((button == eMouseLeft) && (player.ActiveInventory == null) && (GetLocationType(mouse.x, mouse.y) == eLocationNothing))
  { // If the player left clicks and has no inventory selected and the mouse is not over a Hotspot, Object or Character, then...
    ProcessClick(mouse.x, mouse.y, eModeWalkto); // The player will walk to mouse coordinates
  }
    else if ((button == eMouseRight) && (player.ActiveInventory != null))
  { // If the player right clicks and has an inventory item selected, then...
    player.ActiveInventory = null; //The player will deselect the inventory item
  }
    else ProcessClick(mouse.x, mouse.y, mode); // else process the click
}


Thanks guys

Khris

Quote from: Tenacious Stu on Thu 14/02/2013 12:54:08to be honest I've never used a Display command to check code when in game. I'm not sure how to place one?

All you need to do is put Display("unhandled"); at the very start of unhandled_event().
As soon as it's supposed to be called, if you don't get to see the text displayed, something's wrong. Plus, you'll know that the fault isn't within its contents, at least not only there, but there's something wrong elsewhere already because the function isn't called.

You can also do something like this:
Code: ags
  if (player.ActiveInventory == null) Display("ActiveInventory is null");
  else Display("ActiveInventory: %s", player.ActiveInventory.Name);

Stuff like that is extremely useful to troubleshoot complex code.

Tenacious Stu

Hi Guys

I'm still having issues with the unhandled events not triggering when an inventory item is looked at or another inventory item is used on an item.

As I said in my previous post I believe it has something to do with this line of code:

Code: AGS
if (iat.IsInteractionAvailable(mode)) iat.RunInteraction(mode);


But after staring at it for some time, I can't seem to figure out how to fix this. Here is how the code looks right now:

Code: AGS
function on_mouse_click(MouseButton button) {
  CursorMode mode = eModeInteract;
  if ((button == eMouseRight) || (button == eMouseRightInv)) mode = eModeLookat; //If the player right clicks or right clicks on an inventory item, it will Look at what is being clicked on
  else if (player.ActiveInventory != null) mode = eModeUseinv; //if the player has an active inventory item it will use inventory
  if ((button == eMouseLeftInv) || (button == eMouseRightInv)) //if the player right or left clicks on inventory
  {
    InventoryItem *iat = InventoryItem.GetAtScreenXY(mouse.x, mouse.y); // "iat" is whether there is an inventory item being clicked on
    if (iat) { // If there is an inventory item being clicked on:
      if (iat.IsInteractionAvailable(mode)) iat.RunInteraction(mode); // if there is an interaction available then run it
      else if ((button == eMouseLeftInv) && (player.ActiveInventory == null)) player.ActiveInventory = iat; //If Player Left Clicks and currently does not have an inventory item selected then it will select one
      else if ((button == eMouseRightInv) && (player.ActiveInventory != null)) player.ActiveInventory = null; //If Player Right Clicks and has an inventory item selected, it will deselct the item
    }
  }
    else if ((button == eMouseLeft) && (player.ActiveInventory == null) && (GetLocationType(mouse.x, mouse.y) == eLocationNothing))
  { // If the player left clicks and has no inventory selected and the mouse is not over a Hotspot, Object or Character, then...
    ProcessClick(mouse.x, mouse.y, eModeWalkto); // The player will walk to mouse coordinates
  }
    else if ((button == eMouseRight) && (player.ActiveInventory != null))
  { // If the player right clicks and has an inventory item selected, then...
    player.ActiveInventory = null; //The player will deselect the inventory item
  }
    else ProcessClick(mouse.x, mouse.y, mode); // else process the click
}


Thanks in advance for any suggestions

Khris

The problem is still exactly the same as before: you're not triggering the event if there's no handler, and wondering why unhandled isn't called.

To put it another way: in order for unhandled_event to be called, a mouse click after which nothing happens is not enough! Because AGS isn't HAL or Edi; it cannot detect this situation. You HAVE to call .RunInteraction(), regardless of whether there's one available or not, in order to make AGS call unhandled_event (if the latter is the case).
But again, just like before, you're actively making sure that unhandled_event is never called by not calling .RunInteraction if .IsInteractionAvailable returns 0.

      .RunInteraction()
              |
              |
              V
   .IsInteractionAvailabe()?
      |                |
     YES               NO
      |                |
      V                V
  event_x()        unhandled_event()

Tenacious Stu

#7
Hi

Sorry for reviving this old thread, but I've been away from working on the game and have come back to it with this problem still. I realised that this was never resolved here on the forums and so I thought I would complete it in case it would help anyone in the future. I've tried to make sense of it all and think I now understand why it wasn't working for Inventory stuff:

Code: AGS
if (iat.IsInteractionAvailable(mode)) iat.RunInteraction(mode);


Basically, I was telling AGS that if there is an interaction available, then run it, but at no point do I say if there isn't an interaction available then to run interaction anyway (which would call the unhandled event). Also I was under the impression that processclick was what would call an unhandled event, but I think this is just for walking to a location?

This is how my code looks now:

Code: AGS
function on_mouse_click(MouseButton button) {
 CursorMode mode = eModeInteract;
  if ((button == eMouseRight) || (button == eMouseRightInv)) mode = eModeLookat; //If the player right clicks or right clicks on an inventory item, it will Look at what is being clicked on
  else if (player.ActiveInventory != null) mode = eModeUseinv; //if the player has an active inventory item it will use inventory
 if ((button == eMouseLeftInv) || (button == eMouseRightInv)) //if the player right or left clicks on inventory
  {
    InventoryItem *iat = InventoryItem.GetAtScreenXY(mouse.x, mouse.y); // "iat" is whether there is an inventory item being clicked on
    if (iat) { // If there is an inventory item being clicked on:
  
     if (iat.IsInteractionAvailable(mode)) iat.RunInteraction(mode); // if there is an interaction available then run it

      else if ((button == eMouseLeftInv) && (player.ActiveInventory == null)) player.ActiveInventory = iat; //If Player Left Clicks and currently does not have an inventory item selected then it will select one
     else if ((button == eMouseRightInv) && (player.ActiveInventory != null)) player.ActiveInventory = null; //If Player Right Clicks and has an inventory item selected, it will deselct the item
      //else if ((button == eMouseRightInv) && (player.ActiveInventory == null)) ProcessClick(mouse.x, mouse.y, mode);//If Player Right Clicks and Doesn't have inv selected,
     else iat.RunInteraction(mode); //Run Interactions - If none, then calls Unhandled Event
    }

 }
   else if ((button == eMouseLeft) && (player.ActiveInventory == null) && (GetLocationType(mouse.x, mouse.y) == eLocationNothing))
  { // If the player left clicks and has no inventory selected and the mouse is not over a Hotspot, Object or Character, then...
    ProcessClick(mouse.x, mouse.y, eModeWalkto); // The player will walk to mouse coordinates
  }
   else if ((button == eMouseRight) && (player.ActiveInventory != null))
  { // If the player right clicks and has an inventory item selected, then...
   player.ActiveInventory = null; //The player will deselect the inventory item
  }
    else ProcessClick(mouse.x, mouse.y, mode); // else process the click
}


So, by adding in the
Code: AGS
else iat.RunInteraction(mode);
the game now knows to run interaction if there is no other option, which will call the unhandled event.

Thank you Khris and geork for helping me get to grips with the issue and apologies for my lack of understanding.

SMF spam blocked by CleanTalk