Mouse Over event for Objects?

Started by Nero_Ace, Fri 19/04/2013 11:45:54

Previous topic - Next topic

Nero_Ace

I tried looking for it everywhere but couldn't find the answer. The thing I'm trying to do is have the mouse cursor change automatically over certain objects.

For example, if the cursor mouses over an object, it changes to an interact button; if you mouse over an area transition hotspot, it changes to a WalkTo icon, etc.

However, while it works well enough for the hotspots, I can't get it to work for objects, the primary reason being that objects don't seem to have  Mouse Over event. Is there a way to do it without the Event or should i start drawing hotspots around the objects to simulate the effect?

EDIT

Also, while I'm at this, I'm finding the giant part of Global Script to be a big mess as it contains stuff related to Mouse Wheel North, Middle Mouse Click and other stuff I do not want and just keeps interfering with the game mechanics.
What should I replace all of this with so that the "Any Click" event of every kind of hotspot, object, etc. can be tied to the Global Script?

Slasher

#1
Hi

there are a few ways to you can go. You mention about Hotspots.

Using Hotspots is one way. Sometimes if I have an object that is quite small, and to assist the user, it makes sense to draw a big Hotspot behind it and use that to trigger events (especially for Mouseover Hotspot).

I've used these to disable mouse wheel:

Code: AGS

  mouse.DisableMode(eMouseMiddle);
  mouse.DisableMode(eMouseWheelNorth);
  mouse.DisableMode(eMouseWheelSouth);




Crimson Wizard

#2
There is always a way to know what is beyond mouse cursor by using following functions:
GetLocationType
Character.GetAtScreenXY
GUI.GetAtScreenXY
GUIControl.GetAtScreenXY
Hotspot.GetAtScreenXY
InventoryItem.GetAtScreenXY
Object.GetAtScreenXY
Region.GetAtRoomXY


For example, to know which object is under cursor:
Code: ags

Object *obj = Object.GetAtScreenXY(mouse.x, mouse.y);
if (obj != null)
{
   // you have an object there, do what you want
}


Since you want your cursor to react on its location, this code should be put into global repeatedly_execute function:
Code: ags

function repeatedly_execute()
{
   Object *obj = Object.GetAtScreenXY(mouse.x, mouse.y);
   if (obj != null)
   {
      // set new mouse mode until mouse leaves object
      Mouse.SaveCursorUntilItLeaves();
      Mouse.Mode = eModeInteract;
   }
}





If you want more general solution, use GetLocationType:
Code: ags

function repeatedly_execute()
{
   LocationType loc_type = GetLocationType(mouse.x, mouse.y);
   if (loc_type != eLocationNothing)
   {
     Mouse.SaveCursorUntilItLeaves();
     if (loc_type == eLocationHotspot)
     {
       Mouse.Mode = eModeWalk;
     }
     else if (loc_type == eLocationObject)
     {
       Mouse.Mode = eModeInteract;
     }
     // and so forth
   }
}

Nero_Ace

This is excellent. I'll try using the general method.

One more query, if you don't mind -

Some of my hotspots take you to a different room while others initiate pick up events or interacting with characters. Is there a way to tell the code what "type" of hotspot it is and get it to differentiate cursors for the different types?
Also, I have an always on Inventory System. So what I need is for the cursor to automatically change to the interact icon when you hover over the GUI with the inventory system, It only covers the top 110 pixels of the screen.

Crimson Wizard

#4
Quote from: Nero_Ace on Fri 19/04/2013 12:25:00
Some of my hotspots take you to a different room while others initiate pick up events or interacting with characters. Is there a way to tell the code what "type" of hotspot it is and get it to differentiate cursors for the different types?
This is usually done using Custom Properties.
http://www.adventuregamestudio.co.uk/wiki/Other_features_(manual)#Custom_Properties

For example, you create a property "ActionType" for hotspots, where 1 means "leave area", 2 means "interact" etc. Then you apply those values to every hotspot in the room editor.

In script:
Code: ags

if (loc_type == eLocationHotspot)
{
  Hotspot *h = Hotspot.GetAtScreenXY(mouse.x, mouse.y);
  int action_type = h->GetProperty("ActionType");
  if (action_type == 1)
     Mouse.Mode = eModeWalk;
  else if (action_type == 2)
     Mouse.Mode = eModeInteract;
}



Quote from: Nero_Ace on Fri 19/04/2013 12:25:00
Also, I have an always on Inventory System. So what I need is for the cursor to automatically change to the interact icon when you hover over the GUI with the inventory system
Hmm, probably this:
Code: ags

GUIControl *ctrl = GUIControl.GetAtScreenXY(mouse.x, mouse.y);
if (ctrl == gInvWindow /* use your actual inventory gui script name here */)
{
   // do something
}

Khris

It's not a good idea to set the cursor mode 40 times per second. Afaik, this breaks animated cursors.

I'd do this:
Code: ags
int old_lt;

function repeatedly_execute()

  int mx = mouse.x;
  int my = mouse.y;
  int lt = GetLocationType(mx, my);
  Region* r = Region.GetAtRoomXY(mx + GetViewportX(), my + GetViewportY());
  if (r.ID > 0) lt = -3;
  GUI* gu = GUI.GetAtScreenXY(mx, my);
  if (gu == gInventory) lt = -1;
  InventoryItem* ii = InventoryItem.GetAtScreenXY(mx, my);
  if (ii != null) lt = -2;

  if (lt != old_lt) {

    // at this point, the cursor was just moved over a different type of area
    
    if (lt == eLocationNothing) {
      mouse.ChangeModeGraphic(eModeWalkto, DEFAULT_WALKTO_SPRITE_SLOT);
      mouse.Mode = eModeWalkto;
    }
    if (lt == eLocationHotspot || lt == eLocationObject) mouse.Mode = eModeInteract;
    if (lt == eLocationCharacter) mouse.Mode = eModeTalkto;
    if (lt == -1) {
      // cursor over inv GUI
      if (mouse.Mode != eModeUseinv) mouse.Mode = eModeInteract;
    }
    if (lt == -3 && r.ID <= 5) {
      // cursor over exit region
      mouse.ChangeModeGraphic(eModeWalkto, LEAVE_ROOM_SPRITE_SLOT);
      mouse.Mode = eModeWalkto;
    }
  }
  old_lt = lt;
}


The all caps stuff needs to be replaced with the respective sprite slots. Use regions 1-5 for exits, 6-X for the rest.
Not tested!

Nero_Ace

#6
Quote from: Crimson Wizard on Fri 19/04/2013 12:35:38
Hmm, probably this:
Code: ags

GUIControl *ctrl = GUIControl.GetAtScreenXY(mouse.x, mouse.y);
if (ctrl == gInvWindow /* use your actual inventory gui script name here */)
{
   // do something
}


Sorry for the late reply. I've been trying to implement dialogues and finishing off a few other rooms. The submission for a prototype is in a few hours so I'm pretty swamped. Anyways, when I try to use this code it gives me an error and says that it
cannot convert 'GUIControl*' to 'GUI*'

I've pasted it in the repeatedly_execute function.

EDIT:

Okay, i changed it to GUI from GUIControl and it started working. But, there's a new problem now. When you end up selecting at item from the inventory window, it's supposed to switch to the cursor mode for that item.
However, since the mouse is on the inventory when you select it, the code executes and turns it into eModeInteract again.

EDIT 2:

Okay, never mind. Turns out, all I needed to do was add a code which checks if the character's current active inventory is null or not with a simple If statement and then execute the code accordingly.
No more errors. :) :-D

AmazingTash

#7
Quote from: Nero_Ace on Sun 21/04/2013 09:31:21
EDIT 2:

Okay, never mind. Turns out, all I needed to do was add a code which checks if the character's current active inventory is null or not with a simple If statement and then execute the code accordingly.
No more errors. :) :-D

Hello and sorry for digging out this old Thread.
I implemented the code and as a programming "beginner" i stuck on this last step. How do i do this? :-X


Code: ags

GUI *ctrl = GUI.GetAtScreenXY(mouse.x, mouse.y);
if (ctrl == gInventoryBar)
{}

   LocationType loc_type = GetLocationType(mouse.x, mouse.y);
   if (loc_type != eLocationNothing)
   {
     Mouse.SaveCursorUntilItLeaves();
     if (loc_type == eLocationHotspot)
     {
       Mouse.Mode = eModeWalkto;
     }
     else if (loc_type == eLocationObject)
     {
       Mouse.Mode = eModeLookat;
     }
   }

SMF spam blocked by CleanTalk