Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: Nero_Ace on Fri 19/04/2013 11:45:54

Title: Mouse Over event for Objects?
Post by: Nero_Ace on Fri 19/04/2013 11:45:54
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?
Title: Re: Mouse Over event for Objects?
Post by: Slasher on Fri 19/04/2013 12:04:08
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) Select

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



Title: Re: Mouse Over event for Objects?
Post by: Crimson Wizard on Fri 19/04/2013 12:09:55
There is always a way to know what is beyond mouse cursor by using following functions:
GetLocationType (http://www.adventuregamestudio.co.uk/wiki/Game_/_Global_functions#GetLocationType)
Character.GetAtScreenXY (http://www.adventuregamestudio.co.uk/wiki/Character_functions_and_properties#Character.GetAtScreenXY)
GUI.GetAtScreenXY (http://www.adventuregamestudio.co.uk/wiki/GUI_functions_and_properties#GUI.GetAtScreenXY)
GUIControl.GetAtScreenXY (http://www.adventuregamestudio.co.uk/wiki/GUI_control_functions_and_properties#GUIControl.GetAtScreenXY)
Hotspot.GetAtScreenXY (http://www.adventuregamestudio.co.uk/wiki/Hotspot_functions_and_properties#Hotspot.GetAtScreenXY)
InventoryItem.GetAtScreenXY (http://www.adventuregamestudio.co.uk/wiki/Inventory_item_functions_and_properties#InventoryItem.GetAtScreenXY)
Object.GetAtScreenXY (http://www.adventuregamestudio.co.uk/wiki/Object_functions_and_properties#Object.GetAtScreenXY)
Region.GetAtRoomXY (http://www.adventuregamestudio.co.uk/wiki/Region_functions_and_properties#Region.GetAtRoomXY)


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

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) Select

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) Select

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
   }
}
Title: Re: Mouse Over event for Objects?
Post by: Nero_Ace on Fri 19/04/2013 12:25:00
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.
Title: Re: Mouse Over event for Objects?
Post by: Crimson Wizard on Fri 19/04/2013 12:35:38
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) Select

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) Select

GUIControl *ctrl = GUIControl.GetAtScreenXY(mouse.x, mouse.y);
if (ctrl == gInvWindow /* use your actual inventory gui script name here */)
{
   // do something
}
Title: Re: Mouse Over event for Objects?
Post by: Khris on Fri 19/04/2013 13:06:41
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) Select
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!
Title: Re: Mouse Over event for Objects?
Post by: Nero_Ace on Sun 21/04/2013 09:31:21
Quote from: Crimson Wizard on Fri 19/04/2013 12:35:38
Hmm, probably this:
Code (ags) Select

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
Title: Re: Mouse Over event for Objects?
Post by: AmazingTash on Sat 18/02/2017 15:05:33
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) Select

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;
     }
   }