MODULE: ShowInteractiveAreas - to help Point & Click amateurs

Started by Billbis, Fri 30/11/2012 19:01:32

Previous topic - Next topic

Billbis

1.General presentation and Download
2.Installation
3.Optionnal configurations
4.F.A.Q.
5.Module Script
6.Alternative Edition

General presentation and Download
ShowInteractiveAreas.zip
(zip file, host by dropbox, 6,84 ko)

On most modern Point & Click, there is an keyboard key that enlights all interactive areas to player. Of course, hard core point&clicker like us hate such an options.  ;)
This module is my attempt to implement such a function in AGS project. While a key is pressed (default: space bar), a sprite (by default, yours interact and talk to mouse cursor sprites) is display on each interactive areas present at screen (visible & clickable objects, enable hotspots and clickable characters).
Before player presses space bar:

And while player presses space bar:


This is my first module. If you have any idea about how to improve it, either on the code or on the help files, please tell me.

Installation

Unzip ShowInteractiveAreas.zip
Open your AGS project
Right clic on "Scripts"
Clic on "Import script..."
Open "ShowInteractiveAreas.scm"
Done!

Optionnal configurations

sia_HOTSPOT_LIMIT might be leave as it is or be adjust to your highest Hotspot number to optimize (a very little bit) calculation time.

sia_SHOOTING_POINT_N is the number of points that will be randomly shot at screen to determine hotspot coordinates. Empirically determined by me. Increasing this number will improve accruacy, decreasing this number will improve calculation time. You may decrease this number if your game resolution is smaller than 1024*768.

Two bools are available, sia_CheatEnable and sia_EnableHere to set up this moduleas optional and to deactivate it in certain rooms or situations.

Other customizations are possible by editing ShowInteractiveArea.asc directly.

F.A.Q.

I have an object / hotpsot / character I do not want to be shown as active by this module. How to do that?
Spoiler
Several way of doing that. You may take advantage of the IsInteractionAvailable function, or create a "siaVisible" custom property that apply to objects / hotspots / character and set it true by default, and false on inactive areas. I recommend the second approach. Ask if you want more details.
[close]

Cursor is not properly positioned on fragmented hotspots.
Spoiler
Consider dividing your fragmented hotspots into individual non fragmented hotpots. Alternatively, you may also manually indicates hotspot coordinates in these situations (for example, in custom properties). Ask if you want more details.
Alternatively, you can use the *Alternative Edition* of this module.
[close]

On apparently random and very rare occasions, no cursor is drawn on my tiniest hotpsots.
Spoiler
It is not a bug, it is a feature. :D
Alternatively, you can use the *Alternative Edition* of this module.
[close]

Module Script

ShowInteractiveAreas.ash
Spoiler
Code: AGS
// Script header for module 'ShowInteractiveAreas', v1.3
//
// Author: Billbis
//
// Abstract:
//
//   While Space Bar is pressed, this module displays a mouse cursor over each 
//   interactive areas. This function is present in most modern Point & Click. It helps
//   players not to miss an object / hotspot / character. Ojects, characters and hotspots
//   coordinates are automtically determined.
//
// Dependencies:
//
//   AGS version required:  build for AGS 3.2.1, not sure if it works with older versions.
//
//   AGS setting required: No particular configuration is needed.
//
// Configuration:
//
//   Optional:
//
//     sia_HOTSPOT_LIMIT might be leave as it is or be adjust to your highest Hotspot number
//     to optimize (a very little bit) calculation time.
//
//     sia_SHOOTING_POINT_N is the number of points that will be randomly shot at screen to
//     determine hotspot coordinates. Empirically determined by me. Increasing this number will
//     improve accruacy, decreasing this number will improve calculation time. You may decrease
//     this number if your game resolution is smaller than 1024*768.
//
//     Two bools are available, sia_CheatEnable and sia_EnableHere to set up this module
//     as optional and to deactivate it in certain rooms or situations.
//
//     Other customizations are possible by editing ShowInteractiveArea.asc directly.
//
// Caveats:
//
//   This module uses ONE overlay, which can perturb your game if you already use 20
//   of them at some point in your game (20 Overlays max display at a same time,
//   AGS limitation).
//
//   Due to probabilistic determination of hotspots coordinates, very small hotspots might not
//   be correctly detected. For sia_SHOOTING_POINT_N = 10000 and 1024*768 resolutions, hotspots
//   with a total area of 55 pixels will be miss half of the time on first key press. But only 
//   one time over four on second key press, etc. No problems with small objects or characters.   
//
//   Fragmented areas or weird shapes of hotspots / objects / characters can lead to bad cursor 
//   positionning.
//
// Revision history:
//   version 1.3: 07/04/2013
//      Non-enabled hotspots won't be display anymore.
//   version 1.2: 07/04/2013
//      Non-clickable objects won't be display anymore.
//   version 1.1: 03/20/2013
//      The module now works when player is moving.
//   version 1.0: 11/30/2012
//      Improve hotspot detection (algorythm now remember hotspots it previously found).
//   version beta 0.2: 11/24/2012
//      *NEW* Automatic detections of hotspot coordinates.
//   version beta 0.1: 11/23/2012
//      First release.
//  
// Licence:
//
//   ShowInteractiveAreas AGS script module is publish under the terms of the 
//   Do What The Fuck You Want To Public License, Version 2
//
// This program is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What The Fuck You Want
// To Public License, Version 2, as published by Sam Hocevar. See
// http://sam.zoy.org/wtfpl/COPYING for more details.
//
// Thanks:
//
//   Pidem and Kitai
//
// Defines
#define sia_HOTSPOT_LIMIT  50
#define sia_SHOOTING_POINT_N 10000
// Imports
import bool sia_CheatEnable, sia_EnableHere;
[close]

ShowInteractiveAreas.asc
Spoiler
Code: AGS
// ShowInteractiveAreas script

//General definitions

// Three arrays that will be needed to calculate Hotspot center coordinates.
int siaHotspotX[];
int siaHotspotY[];
int siaHotspotN[];

bool sia_CheatEnable = true; // Use this bool if you want to create an option to set this module optional.
bool sia_EnableHere = true; // Use this bool in situations or rooms you do not want this module to be active.

function on_event(EventType siaevent, int siadata) {
  if (siaevent == eEventEnterRoomBeforeFadein) {
      siaHotspotX = new int[sia_HOTSPOT_LIMIT]; //Each time player change room, this erase old hotspot coordinates.
      siaHotspotY = new int[sia_HOTSPOT_LIMIT];
      siaHotspotN = new int[sia_HOTSPOT_LIMIT];
  }
}

//When player hits SpaceBar
function on_key_press(eKeyCode keycode) {
  if (keycode == eKeySpace){//Change eKeySpace by the key you want to use.
    if (sia_CheatEnable && sia_EnableHere && !IsGamePaused ()) {
      PauseGame();
    //Screening for Hotspots.
      Hotspot *h;
      int index = 0;
      int x, y;
      while (index < sia_SHOOTING_POINT_N) { //We randomly shoot sia_SHOOTING_POINT_N points, and calculate the barycenter of each point that fall on the same Hotspot.
        x = Random(System.ViewportWidth - 1);
        y = Random(System.ViewportHeight - 1);
        h = Hotspot.GetAtScreenXY(x, y);
        if (h.ID > 0) { //Hotspot 0 is not a hotspot.
          siaHotspotX[h.ID] = (siaHotspotN[h.ID]*siaHotspotX[h.ID] + x + GetViewportX()) / (siaHotspotN[h.ID] + 1) + Random(1); //Barycenter calculation
          siaHotspotY[h.ID] = (siaHotspotN[h.ID]*siaHotspotY[h.ID] + y + GetViewportY()) / (siaHotspotN[h.ID] + 1) + Random(1); //Random(1) corrects AGS int rounding
          siaHotspotN[h.ID] = siaHotspotN[h.ID] + 1;
        }
        index++;
      }    
      DynamicSprite *siasprite = DynamicSprite.Create(System.ViewportWidth, System.ViewportHeight); // Technical stuff to create a drawing surface
      DrawingSurface *siasurface = siasprite.GetDrawingSurface();      
      index = 1; //Hotspot 0 is not a hotspot.
      while (index < sia_HOTSPOT_LIMIT) {
        if (siaHotspotX[index] !=0 && siaHotspotY[index] !=0 && hotspot[index].Enabled) {
          //If an hotspot have coordinates, we draw a mouse cursor on it.
          //Alternatively, you can repalce
          //    Mouse.GetModeGraphic(eModeInteract)
          //by
          //    42
          //to use your favourite sprite number 42.
          siasurface.DrawImage(siaHotspotX[index] - GetViewportX(), siaHotspotY[index] - GetViewportY(), Mouse.GetModeGraphic(eModeInteract));
        }
        index++;
      }
      //Calclucalting Objects positions and drawing cursors.
      if (Room.ObjectCount > 0) {
        int siaObjectX,  siaObjectY;
        Object *o;
        index = 0;
        while (index < Room.ObjectCount) {
          o = object[index];
          if (o.Visible && o.Clickable) {
            siaObjectX = o.X + Game.SpriteWidth[o.Graphic]/2;
            siaObjectY = o.Y - Game.SpriteHeight[o.Graphic]/2;
            //If an object is Visible, we draw a mouse cursor on it.
            //Alternatively, you can repalce
            //    Mouse.GetModeGraphic(eModeInteract)
            //by
            //    42
            //to use your favourite sprite number 42.
            siasurface.DrawImage(siaObjectX - GetViewportX(), siaObjectY - GetViewportY(), Mouse.GetModeGraphic(eModeInteract));
          }
          index++;
        }
      }
      //Calclucalting Characters positions and drawing cursors.
      if (Game.CharacterCount > 0) {
        int siaCharacterX,  siaCharacterY;
        Character *c;
        index = 0;
        while (index < Game.CharacterCount) {
          c = character[index];
          if (c.Room == player.Room && c.Clickable) {
            ViewFrame *siacharcatervf = Game.GetViewFrame(c.View, c.Loop, c.Frame);
            siaCharacterX = c.x;
            siaCharacterY = c.y - Game.SpriteHeight[siacharcatervf.Graphic]*c.Scaling/2*100;
            //If a character is clickable, then we draw a mouse cursor on it
            //Alternatively, you can repalce
            //    Mouse.GetModeGraphic(eModeTalkto)
            //by
            //    42
            //to use your favourite sprite number 42.
            siasurface.DrawImage(siaCharacterX - GetViewportX(), siaCharacterY - GetViewportY(), Mouse.GetModeGraphic(eModeTalkto));
          }
          index++;
        }
      }
      siasurface.Release();  // Technical stuff to display the beautiful overlay we have drawn.
      Overlay *siaoverlay = Overlay.CreateGraphical(0, 0, siasprite.Graphic, true);
      while (IsKeyPressed(eKeySpace)) Wait(1); //While Key is pressed, overlay is display.
      siaoverlay.Remove(); //Cleaning a little bit behind us.
      siasprite.Delete();
      siaoverlay = null ;
      UnPauseGame();
    }
  }
}

export sia_CheatEnable, sia_EnableHere; //Do not forget to import these bools in global script header if you want to use them.
[close]

Alternative Edition
ShowInteractiveAreas *Alternative Edition*
(zip file, host by dropbox, 38.5 ko)

While standard edition of this module have the cool feature "automatic hotspot coordinates determinations", it comes with a few caveats that include:
-High calculation time (usually, a drop of ~1-2 FPS is observed on SpaceBar keypress, from 40 to 38). :smiley:
-Sometimes, it missed very tiny hotspot (<<1/1000 of screen surface). :smiley:
-Bad cursor positioning on hollow / fragmented hotspots.  :sad:
Alternative edition of ShowInteractiveAreas module correct those caveats, but come without the cool feature "automatic hotspot coordinates determinations". Indeed, it is replaced by a laborious "manual specification of each hotspot coordinates by user".
Alternative edition installation and usage is globally the same as standard edition, but few exceptions:
-You MUST creates 2 hotspots coordinates names exactly "sia_PropX" and "sia_PropY", with numeric values, a default value of -1, and that apply to Characters, Objects and Hotspots.

For each hotspot, you must feed these properties with actual room coordinates (TIPS: you can copy room coordinates from the editor by doing a middle click). No cursor will be drawn on hotspots with default value on these properties.
Characters and objects can be left with default values: there coordinates will be determine in real time. But you can specify some coordinates, in that case, cursor will be drawn at these room coordinates.

Module Script of *Alternative Edition*

ShowInteractiveAreas.ash
Spoiler
Code: AGS
// Script header for module 'ShowInteractiveAreas', v1.3 *Alternative Edition*
//
// Author: Billbis
//
// Abstract:
//
//   While Space Bar is pressed, this module displays a mouse cursor over each 
//   interactive areas. This function is present in most modern Point & Click. It helps
//   players not to miss an object / hotspot / character. Ojects and characters coordinates
//   are automtically determined. Hotspot coordinates must be entered via two custom properties.
//
// Dependencies:
//
//   AGS version required:  build for AGS 3.2.1, not sure if it works with older versions.
//
//   AGS setting required: You MUST creates two custom properties : sia_PropX and sia_PropY
//   that aplied to Objects, Characters and Hostpots, with a numeric default value of -1.
//   For each hotspot, you need to feed sia_PropX and sia_PropY with the room coordinates you want
//   the cursor to be drawn.
//
// Configuration:
//
//   Optional:
//
//     sia_HOTSPOT_LIMIT might be leave as it is or be adjust to your highest Hotspot number
//     to optimize (a very little bit) calculation time.
//
//     Two bools are available, sia_CheatEnable and sia_EnableHere to set up this module
//     as optional and to deactivate it in certain rooms or situations.
//
//     You can feed sia_PropX and sia_PropY with the room coordinates for (imobile) chracter and
//     object: cursor will be drawn at these positions in priority. If left to -1 (defalut value),
//     objects and characters coordinates will be automaticly determined.
//
//     Other customizations are possible by editing ShowInteractiveArea.asc directly.
//
// Caveats:
//
//   This module uses ONE overlay, which can perturb your game if you already use 20
//   of them at some point in your game (20 Overlays max display at a same time,
//   AGS limitation).
//  
//   Fragmented areas or weird shapes of objects / characters can lead to bad cursor 
//   positionning.
//
// Revision history:
//   version 1.3: 2013/07/04
//      First release of SIA *alternative edition*.
//  
// Licence:
//
//   ShowInteractiveAreas AGS script module is publish under the terms of the 
//   Do What The Fuck You Want To Public License, Version 2
//
// This program is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What The Fuck You Want
// To Public License, Version 2, as published by Sam Hocevar. See
// http://sam.zoy.org/wtfpl/COPYING for more details.
//
// Thanks:
//
//   Pidem and Kitai
//
// Defines
#define sia_HOTSPOT_LIMIT  50
// Imports
import bool sia_CheatEnable, sia_EnableHere;
[close]

ShowInteractiveAreas.asc
Spoiler
Code: AGS
// ShowInteractiveAreas script

//General definitions

bool sia_CheatEnable = true; // Use this bool if you want to create an option to set this module optional.
bool sia_EnableHere = true; // Use this bool in situations or rooms you do not want this module to be active.

//When player hits SpaceBar
function on_key_press(eKeyCode keycode) {
  if (keycode == eKeySpace){//Change eKeySpace by the key you want to use.
    if (sia_CheatEnable && sia_EnableHere && !IsGamePaused ()) {
      PauseGame();
      DynamicSprite *siasprite = DynamicSprite.Create(System.ViewportWidth, System.ViewportHeight); // Technical stuff to create a drawing surface
      DrawingSurface *siasurface = siasprite.GetDrawingSurface();
      Hotspot *h;
      int index = 1; //Hotspot 0 is not a hotspot.
      while (index < sia_HOTSPOT_LIMIT) {
        h = hotspot[index]; 
        if (h.Enabled && h.GetProperty("sia_PropX") != -1 && h.GetProperty("sia_PropY") != -1) {
          //If an hotspot have non default coordinates, we draw a mouse cursor on it.
          //Alternatively, you can repalce
          //    Mouse.GetModeGraphic(eModeInteract)
          //by
          //    42
          //to use your favourite sprite number 42.
          siasurface.DrawImage(h.GetProperty("sia_PropX") - GetViewportX(), h.GetProperty("sia_PropY") - GetViewportY(), Mouse.GetModeGraphic(eModeInteract));
        }
        index++;
      }
      //Calclucalting Objects positions and drawing cursors.
      if (Room.ObjectCount > 0) {
        int siaObjectX,  siaObjectY;
        Object *o;
        index = 0;
        while (index < Room.ObjectCount) {
          o = object[index];
          if (o.Visible && o.Clickable) {
            if (o.GetProperty("sia_PropX") != -1 && o.GetProperty("sia_PropY") != -1) {
              siaObjectX = o.GetProperty("sia_PropX");
              siaObjectY = o.GetProperty("sia_PropY");
            } else {
              siaObjectX = o.X + Game.SpriteWidth[o.Graphic]/2;
              siaObjectY = o.Y - Game.SpriteHeight[o.Graphic]/2;
            }
            //If an object is Visible, we draw a mouse cursor on it.
            //Alternatively, you can repalce
            //    Mouse.GetModeGraphic(eModeInteract)
            //by
            //    42
            //to use your favourite sprite number 42.
            siasurface.DrawImage(siaObjectX - GetViewportX(), siaObjectY - GetViewportY(), Mouse.GetModeGraphic(eModeInteract));
          }
          index++;
        }
      }
      //Calclucalting Characters positions and drawing cursors.
      if (Game.CharacterCount > 0) {
        int siaCharacterX,  siaCharacterY;
        Character *c;
        index = 0;
        while (index < Game.CharacterCount) {
          c = character[index];
          if (c.Room == player.Room && c.Clickable) {
            if (c.GetProperty("sia_PropX") != -1 && c.GetProperty("sia_PropY") != -1) {
              siaCharacterX = c.GetProperty("sia_PropX");
              siaCharacterY = c.GetProperty("sia_PropY");
            } else {
              ViewFrame *siacharcatervf = Game.GetViewFrame(c.View, c.Loop, c.Frame);
              siaCharacterX = c.x;
              siaCharacterY = c.y - Game.SpriteHeight[siacharcatervf.Graphic]*c.Scaling/2*100;
            }
            //If a character is clickable, then we draw a mouse cursor on it
            //Alternatively, you can repalce
            //    Mouse.GetModeGraphic(eModeTalkto)
            //by
            //    42
            //to use your favourite sprite number 42.
            siasurface.DrawImage(siaCharacterX - GetViewportX(), siaCharacterY - GetViewportY(), Mouse.GetModeGraphic(eModeTalkto));
          }
          index++;
        }
      }
      siasurface.Release();  // Technical stuff to display the beautiful overlay we have drawn.
      Overlay *siaoverlay = Overlay.CreateGraphical(0, 0, siasprite.Graphic, true);
      while (IsKeyPressed(eKeySpace)) Wait(1); //While Key is pressed, overlay is display.
      siaoverlay.Remove(); //Cleaning a little bit behind us.
      siasprite.Delete();
      siaoverlay = null ;
      UnPauseGame();
    }
  }
}

export sia_CheatEnable, sia_EnableHere; //Do not forget to import these bools in global script header if you want to use them.
[close]

Snarky

Very useful module! But... firing random points at the screen to check for clickable stuff? Is that really the best solution to the problem? Isn't there a way to iterate through the hotspots+objects+characters+GUIs on screen and work out where they are? Then you wouldn't risk ever missing any, either.

Billbis

Ok, that's a fair enough question.
To clarify things, I just want to say that current version of this module (v1.0):
-does not care about GUI. Players never know if a tree is interactive in point & click, but let's admit he/she is smart enough to know that GUI buttons are clickable.
-perfectly detects object and characters, no matter how small they are. Simply by using object.X() and character.x().
-does perform a stochastic determination of hotspot coordinates, which is efficient (we will discuss about that).

Hotspot detection raises quite a long discussion on the French AGS forum.
It appears that to our knowledge, there is no hotspot.x() function or equivalent. This is quite understandable due to the very nature of hotspot, which is drawn by game maker and never move.
In such a situation, we explored three different approaches:
1- Create a hotspot.x() function, or an equivalent. But such a function needs to be feed with coordinates. So it was just two hotspot custom properties siaHotspotX and siaHotspotY. Game devellopers have to fill this custom properties for each hotspot in there game. The first version (dropbox link, <6ko) of the module was based on this. This a (very) laborious solution, but it is perfectly accurate and efficient. But come on, we can do better.  :smiley:
2- Screen screen (:)) for hotspots, pixel by pixel. Note that for 1024 x 768 games, that will require an noloopcheck. You immediatly feel that this is not a sustainable solution: it takes to long to be performed each time player press the key. You may want to do it on eEventEnterRoomBeforeFadein, so only once per room. But then you will have to do it not for each pixel at screen, but for each pixel present on the room ! Room size can be very different, so computation time will depend on room size. Even if you can admit that wider rooms need longer loading time, you do not expect any loading time in an adventure game. Furthermore, the future is made of HD, 4K and other retina display. So that clearly not a sustainable solution.
You might think that instead of screening each pixel individually, you can screen only 1 over 2 pixel. That is still a lot. So lets say one pixel over 16. That seems reasonable -but wait we will miss small and misplace hotspots!
3- That why I came to stochastic determination of hotspot coordinates. Which is reasonably fast and reasonably accurate. Perfect mix between the two first solution. :-D
I admit it is disturbing to know that your algorithm is not perfect and might do mistakes, but lets consider the advantages:
It is independent of game resolution, but only dependent of the relative size of your hotspot and your screen area, so quite adapted for a module.
It is accurate. Yes, it is. Let assume that your hotspot area is 1/1000 of your screen area. Which is ridiculously small for a hostpot.
The gray area is 1/1000 of the surface:

Then, on first space bar pressed, it will be missed only (999/1000)^10000 = 0.005 % percent of the time. And if it is not found on fist pressure, there is more than 99,9 % chance that it will be detect on second pressure. Module remembers previously found hotspots and will not forget them until player leaves the room.
So, basically, even if it is possible, hotspot will not be missed. Try it, you will see.  ;)
Let finished by saying that:
-Game will not crash if the module do not detect a hotspot. And player can still click on that hotspot or press space bar again. It is not a big deal.
-If you have very small hotspots and want to use my module:  make bigger hotspot, or draw an object on it, or use custom properties to enter hotspots coordinates.
-If there is an efficient and accurate way to detect hotspot, please tell me.  :-*
-You can modify and redistribute this module freely.  (nod)
And not showing small hotspots to player is a good feature to do easter eggs!

Snarky


Crimson Wizard

#4
If this is a module that is supposed to be bundled with game project anyway, won't it be better to define Tip's x/y position for hotspots in hotspot's Custom Properties?

E: Ah, sorry, you mention this too, saying it's too labourous. Hmm, well, ok.

Billbis

If one thinks he is a hard worker person, he can use the beta 0.1 version of this module, which do exactly that: require two hotspot custom properties wich contain there approximate middle point corrdinates. You can found it here (<6 ko):wink:
However, let me insist again on the fact that last version of this module will not miss reasonnably big hotspots (i.e. >= 1/1000 of screen surface).
EDIT: The irony is that on the french forum, when I first presented this module, they asked for an automatic detection of hotspot coordinates.  :P

EDIT 2013/07/05: I now recommend alternative edition v1.3 of the module, and no more beta 0.1, see first post.

Crimson Wizard

There's a function in plugin interface that returns a room mask from the engine:
Code: cpp

BITMAP *IAGSEngine::GetRoomMask (int32 index)

So it is possible to get a Hotspot mask for a room, and draw it as an overlay, while the key is pressed, or something like that, similarly like walkable areas could be shown in game's Debug mode.

Never tried plugins myself though. But may be you could check that possibility out?

Billbis

Well, I am note a coder. Plugins and C++ are far to much complicated for my current skills.  :-\ But thank you for the advice.
I do not want to appear closed to optimisations, but still: do you encouter a problem with this module? Does it miss hotspots? It perfectly works with my projects (but I need more testers). We had a proverb in french: "Le mieux est l'ennemi du bien." (Better is the enemy of good.)

Crimson Wizard

No, I was just thinking about other possibilities.

This proverb is international, I guess :).

Khris

I coded a module that did the same thing a few years ago, and for hotspot detection I iterated through every third pixel horizontally and vertically and calculated the average of all x and y coords of each hotspot to get their center position.
This detects 100% of hotspots on the first try, provided that they are at least 3x3 pixels big, shows the icon at the actual center, and is very fast, too.
(And in theory allows hiding one pixel easter egg hotspots simply by placing them on coordinates where one of them isn't a multiple of 3 :))

It used a very convoluted way of displaying the icons though and I haven't released a proper, current version yet.

One suggestion I had: add the name of the hotspot next to the icon.

Billbis

2013/03/20: new version (1.1).
Opening post was updated.
The module now works even if player is moving (it pauses the game while space bar is pressed).
Also I RTFM and change all the System.ScreenWidth() by System.ViewportWidth(). It's cleaner, and more efficient for hotspot detection.

2013/07/04: new minor version (v1.2).
Opening post was updated.
Non clickable objects won't be display anymore by the module.

Billbis

Allow me to bump another time this topic:
-New minor version v1.3: Small code cleaning + non enabled hotspot won't be display anymore.
-New *Alternative edition* without automatic detection of hotspot coordinates, which is replaced by manual specification of hotspot coordinates by user on two custom properties.
See first post for details & downloads.
Side note: Thanks to PuNKKoMmANDO77, this module (and I by the same occasion) is now famous:wink:

PEd1

Does anyone have a link to this module?
The dropbox link at the top seems to be dead now...

Or is there some kind of newer version available?

SMF spam blocked by CleanTalk