ProcessClick / hotspot detection glitching [solved]

Started by Ultra Magnus, Fri 06/08/2010 16:31:08

Previous topic - Next topic

Ultra Magnus

Hey people.
I'm having trouble with clicking on some hotspots. Here's the code I'm using...

Code: ags

function on_mouse_click(MouseButton button)
{
  if (IsGamePaused()==1) { }
  else if (gInventory.Visible==true && GUI.GetAtScreenXY(mouse.x, mouse.y)==null) {gInventory.Visible=false;}
  else if (button==eMouseLeft) {
    if (cCharacter.Room==cEgo.Room && GUIControl.GetAtScreenXY(mouse.x, mouse.y)==null) {
      cCharacter.Walk(mouse.x, mouse.y, eBlock, eWalkableAreas);
      cCharacter.FaceLocation(mouse.x, cCharacter.y, eNoBlock);
    }
    ProcessClick(mouse.x, mouse.y, eModeInteract);
  }
<snipped>
}


Now, the problem is on the screens where cCharacter is in the same room as cEgo.
Most of the time it works as it should, but sometimes the character just walks over to the hotspot and it doesn't process the click afterwards. I've also got rep_exec telling the cursor to change its graphic when over a hotspot, so I know the game knows there's a hotspot there, it just sometimes chooses to ignore it. Furthermore, from what I can tell, the closer the mouse is to the centre of the hotspot, the more likely it is to not register.

Any ideas on why this is happening and maybe how to stop it?
Thanks in advance.
I don't mean to sound bitter, cold, or cruel, but I am, so that's how it comes out.

I'm tired of pretending I'm not bitchin', a total frickin' rock star from Mars.

Khris

I was stumped for a bit, but then it hit me.
The problem is that due to the character doing a blocking walk, a considerable amount of time may pass until ProcessClick is called. The thing is, it uses the current mouse coordinates, not necessarily the ones you clicked at.

It's an easy fix though:

Code: ags
function on_mouse_click(MouseButton button)
{

  int mx = mouse.x, my = mouse.y;

  if (IsGamePaused()==1) { }
  else if (gInventory.Visible==true && GUI.GetAtScreenXY(mx, my)==null) {gInventory.Visible=false;}
  else if (button==eMouseLeft) {
    if (cCharacter.Room==cEgo.Room && GUIControl.GetAtScreenXY(mx, my)==null) {
      cCharacter.Walk(mx, my, eBlock, eWalkableAreas);
      cCharacter.FaceLocation(mx, cCharacter.y, eNoBlock);
    }
    ProcessClick(mx, my, eModeInteract);
  }
<snipped>
}

Ultra Magnus

#2
Hey, thanks for the help, but it didn't work. It's still not processing the click even if I'm really careful not to move the mouse. And as I said, it only seems to happen when the cursor's right in (or close to) the centre of the hotspot.

But typing that did just make me realise something. When the mouse is clicked in the centre of a hotspot that makes the character walk and stand right in front of it, whereas clicking slightly to either side makes him stand next to it. So this probably means that by the time ProcessClick is called, the mouse isn't over the hotspot anymore because it's over the character instead (because he's standing between them).
By this theory, the reason why your suggested fix didn't work is because it's not just the mouse's coordinates that are the problem, but their relation to the character. It's still clicking the same spot, but the character's still in the way.

So, now (I think) I know what the problem is, is there an easy way to work around it, or do I just need to go through the game manually setting the walk-to point for every hotspot?
I don't mean to sound bitter, cold, or cruel, but I am, so that's how it comes out.

I'm tired of pretending I'm not bitchin', a total frickin' rock star from Mars.

Khris

Just make the character not clickable.
If he's supposed to stay clickable, use this:

Code: ags
  // at time of click
  Hotspot*h = Hotspot.GetAtScreen(mx, my);
  int lt = GetLocationType(mx, my);

  // instead of ProcessClick(...)
  if (lt == eLocationHotspot) {
    if (h != hotspot[0]) h.RunInteraction(eModeInteract);
  }
  else ProcessClick(mx, my, eModeInteract);


This could get messy quickly, though.
An alternative is to turn the character not clickable immediately before ProcessClick, then turn him back in the rep_ex.
Code: ags
  if (!cCharacter.Clickable) cCharacter.Clickable = true;

should do it.

Ultra Magnus

I don't mean to sound bitter, cold, or cruel, but I am, so that's how it comes out.

I'm tired of pretending I'm not bitchin', a total frickin' rock star from Mars.

SMF spam blocked by CleanTalk