Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - Billbis

#1
Hints & Tips / Among Thorns
Sun 14/02/2016 21:15:11
So...
Spoiler
I am in front of the flat. I deal with the first police officer messing with the radio. Now what should I do for the second policeman?
[close]
EDIT: Found!
Spoiler
Someone in flat 3 really want a pizza.
[close]
#2
So, what I am suppose to do with the canon?
Spoiler
I can load a coconut, and fire the canon with my spell, but it does not much...
[close]
Thanks!
#3
A MAGS game by Billbis & Creamy


Will you convince your girlfriend's parents to let you marry her? The fact that you are half human, half octopus might be an issue.

Created for the March 2015 MAGS (theme "Monsters").

How to play:

Arrows: move the character
Space bar: Interact, skip text
Escape: Open/close menu
Enter: Select option from menu

Notable features
- HD graphics (1280 x 720)
- Three endings

Linux version:
use mirror download link

Many thanks to:
Khris for AltKeyboardMovement module
Pidem for the jingles
Berika for the kind proofreading
Kevin MacLeod for the lovely music
#4
Hi there,

I am trying to display a small text that will stay on screen in a non blocking way as far as the player is onto a given region (not that hard).
For aesthetic reasons, I want to use my magnificent Text Window Gui I just created and who gives marvel results with Display functions.
I am a bit lost about how using text window gui without calling the high level Display functions. I am trying to do something like this:

Code: ags
void enterRegion(String text,  int x,  int y) {
    // gTextWindow.Text = text; <- this do note seems to exist at the moment.
    gTextWindow.SetPosition(x, y);
    gTextWindow.Visible=true;
}

Is that possible?
(using AGS 3.4.0.x, for that matter)
Thanks!
#5
Beware another of my useless modules!


Introduction:
This module contains alternative functions to FaceLocation, FaceCharacter and FaceObject functions that take in account the perspective of the room.

Build-in functions work with hard-coded fixed angle (see right image) which correspond to a top-bottom view (see, the Mexican).
If player is at the center of the circle and the point to look is at point A, if the angle between horizontal line and A is less that pi/4 radiant (45°), the character will look at the right. But on a more side view perspective, this "decision circle" is flatten on the ground, and the "decision angle" is smaller (see left image, and also, the Mexican).

It is also the case for 8-direction view characters.


Usage:
This module contains 4 functions that are used like that:
Code: ags
cEgo.FaceSVDirection(eUp);
cEgo.FaceSVLocation(150,150);
cEgo.FaceSVCharacter(cBillbis);
cEgo.FaceSVObject(oKey);


If your characters are using 8 direction views, you must declare it like that, for example in a game_start() function located below the module script:
Code: ags
function game_start() {
    SideViewFL.CharacterWithDiagonalLoops(cEgo, true);
    SideViewFL.CharacterWithDiagonalLoops(cSamuel, true);
}


On "inverted" floor, when the more the character goes up, the more he comes closer to the screen:
Code: ags
function region1_WalksOnto() {
    SideViewFL.CharacterWalkingOnTheRoof(cEgo, true);
}


You can specify the perspective of the room or the "decision angles" by several methods. On most side view perspective, the default value should be OK (horizon line close to the middle of the room, flatness set to 0.5).

First, you can set the flatness of the perspective:
Code: ags
SideViewFL.Flatness = 0.5; // float between 0 and 1

Flatness correspond to the degree of flattening of the circles on the first images: it is the ratio B/A where:
-A is the distance on the floor walked by the character when moving of X pixel to the side.
-B is the distance on the floor walked by the character when moving of X pixel to the back.
It's default value is 0.5.

Second, you can specify the coordinate of the horizon on your room:
Code: ags
SideViewFL.HorizonLevel = 120;


Third, you can directly specify the "decision" angle at which the character will change its view:
Code: ags
SideViewFL.Angle4Dir = Maths.Pi/6.0;
SideViewFL.Angle8Dir1 = Maths.Pi/8.0;
SideViewFL.Angle8Dir2 = Maths.Pi/4.0; // Angle8Dir1 <= Angle8Dir2




/!\ Modifying flatness or Horizon level will modify Angle4Dir, Angle8Dir1 and Angle8Dir2. /!\
/!\ This module is compatible with AGS 3.3.0 and (likely) AGS 3.2.1., but contains global eDirection enum and FaceDirection function. Draconian edition and AGS 3.3.1 already contains a enum eDirection (or similar), and some template also comes with FaceDirection functions, therefor beware of potential incompatibilities! I will try to propose an AGS 3.3.1 compatible version soon. /!\

Thanks:
Kitai, Pidem, valoulef.

Licence:
Do whatever you want.

Sources:
header:
Code: ags
// SideViewFL header, version 1.2
//
// Author: Billbis
//
// Abstract:
//
//   Alternative FaceLocation, FaceCharacter and FaceObject functions that take into account
//   the perspective of the room.
//
// Dependencies:
//
//   Made for AGS 3.3.0. Might work with previous and future AGS versions.
//
// Functions:
//
//   Character.FaceSVDirection(SpecifyDirection Dir, BlockingStyle BStyle)
//   Will trun the character to face the specified direction.
//   e.g.: cEgo.FaceSVDirection(eUp);
//
//   Character.FaceSVLocation(int x, int y, BlockingStyle BStyle)
//   Will turn the character to face the specified location (Room coordinates).
//   e.g.: cEgo.FaceSVLocation(150, 150);
//
//   Character.FaceSVCharacter(Character* toFace, BlockingStyle BStyle)
//   Will turn the character to face the specified character.
//   e.g.: cEgo.FaceSVCharacter(cBillbis);
//
//   Character.FaceSVObject(Object* toFace, BlockingStyle BStyle)
//   Will turn the character to face the specified object.
//   e.g.: cEgo.FaceSVCharacter(oKey);
//
// Configuartion:
//
//   If your characters are using 8 direction loops, you must declare it with the CharacterWithDiagonalLoops function,
//   for example in a game_start() function located bellow this script module.
//   e.g.: SideViewFL.CharacterWithDiagonalLoops(cEgo, true);
//
//   Optionnal:
//
//      When located on a 'inverte perspective' surface (i.e. a area when the lower theY coordinate, the closer the things are, e.g. a roof),
//      you should call the CharacherWalkingOnTheRoof function.
//      e.g.: SideViewFL.CharacherWalkingOnTheRoof(cEgo, true);
//
//      You can specify the 'flatness' of the game with SideViewFL.Flatness. Float value between 0 and 1.
//      Warning: resets Angle4Dir, Angle8Dir1 and Angle8Dir2 values.
//      e.g.: SideViewFL.Flatness = 0.5;
//
//      Alternatively, you can specify the Y coordinate of your horizon. Int value.
//      Consider using 'SideViewFL.Flatness = 1;' if your horizon is at infinity.
//      Warning: resets Flatness, Angle4Dir, Angle8Dir1 and Angle8Dir2 values.
//      e.g.: SideViewFL.HorizonLevel = 120;
//
//      N.B.: the following angle are relative to the horizontal.
//
//      You can specify the decision angle for 4 direction loops character, in Radiant. Float value between 0 and Pi/2.
//      e.g.: SideViewFL.Angle4Dir = Maths.Pi/3.0;
//
//      You can specify the decision angle for 8 direction loops character separating horizontal to digonal loops, in Radiant.
//      Float value between 0 and min(Pi/2, Angle8Dir2).
//      e.g.: SideViewFL.Angle8Dir1 = Maths.Pi/6.0;
//
//      You can specify the decision angle for 8 direction loops character separating diagonal to vertical loops, in Radiant.
//      Float value between max(0, Angle8Dir1) and Pi/2.
//      e.g.: SideViewFL.Angle8Dir2 = Maths.Pi/2.0;
//
// Caveats:
//
//   Contain a direction enum that will become obsolete in AGS 3.3.1. Beware of potential conflicts!
//
// Revision history:
//
//   2014/03/12: Fix another math error and a stupid mistake. Add 'invert perspective' surfaces support.
//   2014/03/11: Fix two math errors + new model behind HorizonLevel method.
//   2014/03/10: original release.
//
// License:
//
//   SideViewFL 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:
//
//   Kitai, Pidem

//////////////////////////
// Various declarations //
//////////////////////////

enum SpecifyDirection {
  eUp,
  eLeft,
  eRight,
  eDown,
  eUpRight,
  eUpLeft,
  eDownRight,
  eDownLeft, 
  eNone
};

struct SideViewFL {
    
    import static attribute float Angle4Dir;
    import static float get_Angle4Dir();// $AUTOCOMPLETEIGNORE$
    import static void set_Angle4Dir(float input);// $AUTOCOMPLETEIGNORE$
    
    import static attribute float Angle8Dir1;
    import static float get_Angle8Dir1();// $AUTOCOMPLETEIGNORE$
    import static void set_Angle8Dir1(float input);// $AUTOCOMPLETEIGNORE$
    import static attribute float Angle8Dir2;
    import static float get_Angle8Dir2();// $AUTOCOMPLETEIGNORE$
    import static void set_Angle8Dir2(float input);// $AUTOCOMPLETEIGNORE$
    
    import static attribute float Flatness;
    import static float get_Flatness();// $AUTOCOMPLETEIGNORE$
    import static void set_Flatness(float input);// $AUTOCOMPLETEIGNORE$
    
    import static attribute int HorizonLevel;
    import static int get_HorizonLevel();// $AUTOCOMPLETEIGNORE$
    import static void set_HorizonLevel(int input);// $AUTOCOMPLETEIGNORE$
    
    /// Does the character have 8 direction loops?
    import static void CharacterWithDiagonalLoops(Character *chara,  bool boule);
    /// Does the carracter currently standing on an invert perspective surface (i.e. a roof)?
    import static void CharacherWalkingOnTheRoof(Character *chara,  bool boule);
};

/// Trun the character to face the specified direction.
import void FaceSVDirection(this Character*, SpecifyDirection=eNone, BlockingStyle=eBlock);
/// Turn the character to face the specified location (Room coordinates).
import void FaceSVLocation(this Character*, int x, int y, BlockingStyle BStyle = eBlock);
/// Turn the character to face the specified character.
import void FaceSVCharacter(this Character*, Character* toFace, BlockingStyle BStyle = eBlock);
/// Turn the character to face the specified object.
import void FaceSVObject(this Character*, Object* toFace, BlockingStyle BStyle = eBlock);


script:
Code: ags
// FaceIsoLocation script

float Angle4Dir;
float Angle8Dir1;
float Angle8Dir2;
float Flatness;
int HorizonLevel;
bool IsCharacterWithDiagonalLoops[];
bool IsCharacterWalkingOnTheRoof[];

// Utilitary function
float SideView_Abs(float x) // return absolute value
{ 
    if (x >= 0.0) return x;
    else return -1.0*x;
}

// struct static definitions
static float SideViewFL::get_Angle4Dir() 
{
    return Angle4Dir;
}

static void SideViewFL::set_Angle4Dir(float input) 
{
    if (input >= 0.0 && input <= Maths.Pi/2.0) {
        Angle4Dir = input;
    }
}

static float SideViewFL::get_Angle8Dir1() 
{
    return Angle8Dir1;
}

static void SideViewFL::set_Angle8Dir1(float input) 
{
    if (input >= 0.0 && input <= Maths.Pi/2.0 && input <= Angle8Dir2) {
        Angle8Dir1 = input;
    }
}

static float SideViewFL::get_Angle8Dir2() 
{
    return Angle8Dir2;
}

static void SideViewFL::set_Angle8Dir2(float input) 
{
    if (input >= 0.0 && input <= Maths.Pi/2.0 && input >= Angle8Dir1) {
        Angle8Dir2 = input;
    }
}

static float SideViewFL::get_Flatness() 
{
    return Flatness;
}

static void SideViewFL::set_Flatness(float input) 
{
    if (input >= 0.0 && input <= 1.0) {
        Flatness = input;
        Angle4Dir = Maths.ArcCos(Flatness)/2.0;
        Angle8Dir1 = Maths.ArcCos(Flatness)/3.0;
        Angle8Dir2 = Maths.ArcCos(Flatness)/1.5;
    }
}

static int SideViewFL::get_HorizonLevel() 
{
    return HorizonLevel;
}

static void SideViewFL::set_HorizonLevel(int input)
{
    float horizonYf;
    horizonYf = IntToFloat(input);
    float RoomHeightf = IntToFloat(Room.Height);
    Flatness = Maths.ArcTan((RoomHeightf - 2.0*horizonYf)/RoomHeightf)/Maths.Pi + 0.5; // ^^
    Angle4Dir = Maths.ArcCos(Flatness)/2.0;
    Angle8Dir1 = Maths.ArcCos(Flatness)/3.0;
    Angle8Dir2 = Maths.ArcCos(Flatness)/1.5;
}

static void SideViewFL::CharacterWithDiagonalLoops(Character *chara,  bool boule)
{
    IsCharacterWithDiagonalLoops[chara.ID] = boule;
}

static void SideViewFL::CharacherWalkingOnTheRoof(Character *chara,  bool boule)
{
    IsCharacterWalkingOnTheRoof[chara.ID] = boule;
}


// Module core functions
void FaceSVDirection(this Character*, SpecifyDirection Dir, BlockingStyle BStyle)
{
    if(Dir == eUp) this.FaceLocation(this.x, this.y-1, BStyle);
    else if(Dir == eLeft) this.FaceLocation(this.x-1, this.y, BStyle);
    else if(Dir == eRight) this.FaceLocation(this.x+1, this.y, BStyle);
    else if(Dir == eDown) this.FaceLocation(this.x, this.y+1, BStyle);
    else if(Dir == eUpRight) this.FaceLocation(this.x+1, this.y-1, BStyle);
    else if(Dir == eUpLeft) this.FaceLocation(this.x-1, this.y-1, BStyle);
    else if(Dir == eDownRight) this.FaceLocation(this.x+1, this.y+1, BStyle);
    else if(Dir == eDownLeft) this.FaceLocation(this.x-1, this.y+1, BStyle);
}

void FaceSVLocation(this Character*, int x, int y, BlockingStyle BStyle)
{
    int deltaX = x - this.x;
    int deltaY = this.y - y; //AGS Y axes is pointing down
    float deltaXf = IntToFloat(deltaX);
    float deltaYf = IntToFloat(deltaY);
    float alpha;
    if (deltaX >= 0) {
        alpha = Maths.ArcTan2(deltaYf, deltaXf);
    } else {
        alpha = Maths.ArcTan2(deltaYf, -deltaXf);
    }
    
    if (IsCharacterWithDiagonalLoops[this.ID] == false) { // Four loops character
        if (deltaX >= 0 && SideView_Abs(alpha) <= Angle4Dir) {
            this.FaceSVDirection(eRight, BStyle);
        } else if (deltaX < 0 && SideView_Abs(alpha) <= Angle4Dir) {
            this.FaceSVDirection(eLeft, BStyle);
        } else if (deltaY >0) {
            if (IsCharacterWalkingOnTheRoof[this.ID]) { // Invert perspective.
                this.FaceSVDirection(eDown, BStyle);
            } else {
                this.FaceSVDirection(eUp, BStyle);
            }
        } else {
            if (IsCharacterWalkingOnTheRoof[this.ID]) {
                this.FaceSVDirection(eUp, BStyle);
            } else {
                this.FaceSVDirection(eDown, BStyle);
            }
        }
    } else { // Eight loops character
        if (deltaX >= 0 && SideView_Abs(alpha) <= Angle8Dir1) {
            this.FaceSVDirection(eRight, BStyle);
        } else if (deltaX >= 0 && SideView_Abs(alpha) <= Angle8Dir2) {
            if (deltaY >=0) {
                if (IsCharacterWalkingOnTheRoof[this.ID]) {
                    this.FaceSVDirection(eDownRight, BStyle);
                } else {
                    this.FaceSVDirection(eUpRight, BStyle);
                }
            } else {
                if (IsCharacterWalkingOnTheRoof[this.ID]) {
                    this.FaceSVDirection(eUpRight, BStyle);
                } else {
                    this.FaceSVDirection(eDownRight, BStyle);
                }
            }
        } else if (deltaX < 0 && SideView_Abs(alpha) <= Angle8Dir1) {
            this.FaceSVDirection(eLeft, BStyle);
        } else if (deltaX < 0 && SideView_Abs(alpha) <= Angle8Dir2) {
            if (deltaY >=0) {
                if (IsCharacterWalkingOnTheRoof[this.ID]) {
                    this.FaceSVDirection(eDownLeft, BStyle);
                } else {
                    this.FaceSVDirection(eUpLeft, BStyle);
                }
            } else {
                if (IsCharacterWalkingOnTheRoof[this.ID]) {
                    this.FaceSVDirection(eUpLeft, BStyle);
                } else {
                    this.FaceSVDirection(eDownLeft, BStyle);
                }
            }
        } else if (deltaY >=0) {
            if (IsCharacterWalkingOnTheRoof[this.ID]) {
                this.FaceSVDirection(eDown, BStyle);
            } else {
                this.FaceSVDirection(eUp, BStyle);
            }
        } else {
            if (IsCharacterWalkingOnTheRoof[this.ID]) {
                this.FaceSVDirection(eUp, BStyle);
            } else {
                this.FaceSVDirection(eDown, BStyle);
            }
        }
    }
}

void FaceSVCharacter(this Character*, Character* toFace, BlockingStyle BStyle)
{
    this.FaceSVLocation(toFace.x, toFace.y, BStyle);
}

void FaceSVObject(this Character*, Object* toFace, BlockingStyle BStyle)
{
    int x, y;
    x = toFace.X + Game.SpriteWidth[toFace.Graphic]/2;
    y = toFace.Y - Game.SpriteHeight[toFace.Graphic]/2;
    this.FaceSVLocation( x, y, BStyle);
}

function game_start () {
    IsCharacterWithDiagonalLoops = new bool[Game.CharacterCount];
    IsCharacterWalkingOnTheRoof = new bool[Game.CharacterCount];
    int i = 0;
    while (i < Game.CharacterCount) {
        IsCharacterWithDiagonalLoops[i] = false;
        IsCharacterWalkingOnTheRoof[i] = false;
        i++;
    }
    SideViewFL.set_Flatness(0.5);
}
#6
Lema Sabachthani
A short interactive fiction made for the MAGS February 2014:
Fictional Spirituality



You have been sentence to death. But what you had done had to be done...

Available in English, French and Spanish.
The game is available since a few month, but I just published a sightly improved version, so I though it was the occasion to talk about it here.
This post-MAGS version contain only minor additions to the original version:
- now with talking animations!
- main character has now a interacting animation.
- addition of a small outro text.
- addition of one useless interaction.

If you haven't play the game in April, the release of this sightly improved version is a good time to give it a try. :)

Sources and ressources for the game can be found in this archive (~17Mo, open the project with AGS 3.3.0 or higher, you'll need this magical plugin).
Graphics, music and code are free to use (let says they are on CC0). :)
Sounds effects are under their respective licenses (from freesound.org, see SoundLicences.txt).

Thanks:
SpriteFont plugin by Calin Leafshade
FichierParametres module by Kitai
Beta test: Valoulef and Atavismus
English proofreading: Straydogstrut
Spanish translation: cireja
Sintony font by Eduardo Tunni
Piano by Pidem
Sound effects from Freesound.org (see SoundLicences.txt file)
#7
Here is another module of mine, poorly solving a rare issue but that do the job and that may be useful to some. I'm introducing you:

IsoWalk v1.1
(right click -> download, ~11ko)
For people using AGS for making high resolution games, and having 8 direction loops in there views.

Let's Problem introducing you the issue:
Quote from: Problem1. Usually AGS moves the characters freely in all directions at all possible angles. This can look bad, especially if you use diagonal walkcycles. If, in your animation, the character walks at 45°, but AGS decides to move the character at 55°, it looks really awkward, as if the character is sliding. I know it's a common problem in many adventures, but are there any ways around this?
More precisely, can you limit a character's movement to 8 fixed angles somehow through scripting? I'm not talking about keyboard controls, but point & click. It doesn't look too bad at low resolutions without diagonal walkcycles, but if you make a highres game with smooth animations and diagonal views, it looks plain wrong most of the time.

My module does it (well, mostly).


If the player is in A and walks to B, my module will tell him to go to B through P1. If P1 isn't in a Walkeable Area, it will try P2. If P2 isn't available either, it will give up and will call a normal Walk.
P1 and P2 priority order customizable (see bellow). Diagonals are fixed to 45° (pi/4 radiants).
Obviously, the effect renders better with 8 direction loops, but in can be interesting even with 4 direction loops character (give it a try or another :)).

Usage:
Code: ags
cEgo.IsoWalk(100, 100);
cEgo.IsoWalk(100, 100, eBlock, eAnywhere);

IsoWalkModule.ModuleON = false;
// deactivate the module. IsoWalk will act as normal Walk function. Useful to make this module optional.

IsoWalkModule.MinDistance = 100;
// Min distance in pixel necessary to activate the module, default is 20.

IsoWalkModule.UseAlternateHorizontalPath = true;
IsoWalkModule.UseAlternateVerticalPath = true;
// Waypoint order priority, true is diagonal move first. Default is false.


/! To use this module with the Lightweight BASS Template v2.0 that come with AGS, see this post. /!

By default, the module try to override mouse clicks in eModeWalkTo to call an IsoWalk. To deactivate that behavior, simply replace line 71 in the header :
Code: ags
#define IsoW_HACKWALK true

by :
Code: ags
#define IsoW_HACKWALK false

or delete lines 173 - 183 in the script:
Code: ags
// intercept left clicks in eModeWalkto to order a IsoWalk
function on_mouse_click(MouseButton button) {  
  if (IsoW_HACKWALK) {
    if (button == eMouseLeft) {
      if (Mouse.Mode == eModeWalkto) {
          player.IsoWalk(mouse.x + GetViewportX(), mouse.y + GetViewportY(), eNoBlock, eWalkableAreas);
          ClaimEvent();
      }
    }
  }
}


Caveats: If you are doing some cEgo.Moving checks, be sure to perform them bellow the IsoWalk script (either in a script bellow in the project tree, or in a room script), otherwise it may become false at the middle of the walk.
Due to a bug in the old AGS pathfinder that is called on straight line movement, a few "+3" are lurking around in the script. Should the bug be corrected, those "+3" will be removed.

Header:
Code: ags
// Header for module 'IsoWalk', version 1.1
//
// Author: Billbis & Pidem
//
// Abstract:
//
//   Enforce walking on the 8 standard directions when possible to avoid gliding effects.
//   Contain an alternative walk function (IsoWalk(int x, int y, optional BlockingStyle, optional WalkWhere))
//   Usage: cEgo.IsoWalk(100,100);
//   By default, hacks mouse click in WalkTo mode to perform a player.IsoWalk().
//   
// Dependencies:
//
//   AGS version required:  build for AGS 3.2.1 and 3.3.0, not sure if it works with older versions.
//
//   AGS setting required: No particular configuration is needed. Not very useful if you do not have
//   8 directions in your walking views or if your game is in Low Resolution.
//
// Configuration:
//
//   Optional:
//     
//     IsoW_HACKWALK is define as true.
//     Define it as false to use normal mouse comportment for eModeWalkTo (or delete the corresponding section in IsoWalk Script).
//     
//     IsoWalkModule.moduleON (bool) can be set to false to force IsoWalk to act as normal walk function.
//     (useful to set this module as optional).
//     IsoWalkModule.UseAlternateHorizontalPath and IsoWalkModule.UseAlternateVerticalPath (bool) will change waypoints priorities.
//     (see code comments for details).
//     IsoWalkModule.MinDistance (int) is the minimum distance (in pixel) to activate the module.
//
// Caveats:
//
//   This module works better on large free WalkeableAreas than on small busy ones.
//   If no alternative way is found, characters will use normal walk comportment.
//
// Revision history:
//   verion 1.1: 2014/05/22
//      Optional variables are now encaplusated in a struct.
//   version 1.0: 2014/03/04
//      Name change from Use 8 Direction to IsoWalk. Addition of a few '+3' to avoid a strange comportment of
//      AGS pathfinder.
//      The module now support multi-character non blocking IsoWalks !
//   version beta 0.4: 2013/06/27
//      Bug correction: WA detection now take in account viewport.
//   version beta 0.3: 2013/06/12
//      Addition of Minimal Distance setting.
//   version beta 0.2: 2013/03/08
//      Code cleaning + more customizations possibles.
//   version beta 0.1: 2013/03/03
//      First release.
//  
// License:
//
//   IsoWalk 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:
//
//   Kitai, valoulef


// Defines
//Override Mouse Click in mode WalkTo to use IsoWalk for the main character
#define IsoW_HACKWALK true // $AUTOCOMPLETEIGNORE$

//Struct definition
struct IsoWalkModule {
    
    import static attribute bool ModuleON;
    import static bool get_ModuleON(); // $AUTOCOMPLETEIGNORE$
    import static void set_ModuleON(bool input); // $AUTOCOMPLETEIGNORE$
    
    import static attribute bool UseAlternateHorizontalPath;
    import static bool get_UseAlternateHorizontalPath(); // $AUTOCOMPLETEIGNORE$
    import static void set_UseAlternateHorizontalPath(bool input); // $AUTOCOMPLETEIGNORE$    
    
    import static attribute bool UseAlternateVerticalPath;
    import static bool get_UseAlternateVerticalPath(); // $AUTOCOMPLETEIGNORE$
    import static void set_UseAlternateVerticalPath(bool input); // $AUTOCOMPLETEIGNORE$    
    
    import static attribute int MinDistance;
    import static int get_MinDistance(); // $AUTOCOMPLETEIGNORE$
    import static void set_MinDistance(int input); // $AUTOCOMPLETEIGNORE$
    
};

// Function imports

/// Walk to point (x,y) using only the 8 directions if possible.
import void IsoWalk(this Character*, int x, int y, BlockingStyle = eNoBlock, WalkWhere = eWalkableAreas);

Script:
Code: ags
// IsoWalk module script

//Variables declaration & definition
bool ModuleON = true; //if turn OFF, IsoWalk act as normal Walk. To set the module as an option.
bool UseAlternateHorizontalPath = false; //exchange waypoint priorities. False = vertical / horizontal first
bool UseAlternateVerticalPath = false; //True = diagonal first
int MinDistance = 20; //Minimum distance (in pixel) for the Module to be active.

// struct static definitions
static bool IsoWalkModule::get_ModuleON() {
    return ModuleON;
}
static void IsoWalkModule::set_ModuleON(bool input) {
    ModuleON = input;
}

static bool IsoWalkModule::get_UseAlternateHorizontalPath() {
    return UseAlternateHorizontalPath;
}
static void IsoWalkModule::set_UseAlternateHorizontalPath(bool input) {
    UseAlternateHorizontalPath = input;
}

static bool IsoWalkModule::get_UseAlternateVerticalPath() {
    return UseAlternateVerticalPath;
}
static void IsoWalkModule::set_UseAlternateVerticalPath(bool input) {
    UseAlternateVerticalPath = input;
}

static int IsoWalkModule::get_MinDistance() {
    return MinDistance;
}
static void IsoWalkModule::set_MinDistance(int input) {
    if (input >= 0 && input <= System.ViewportWidth) {
        MinDistance = input;
    }
}

// Stuff for non blocking walk
bool IsoW_noBlock = false; // optimisation of the repeatedly_execute() checks.
int IsoW_x[];
int IsoW_y[];
bool IsoW_eWalkableAreas[];
bool IsoW_character[]; 

function game_start () {
  IsoW_x = new int[Game.CharacterCount];
  IsoW_y = new int[Game.CharacterCount];
  IsoW_eWalkableAreas = new bool[Game.CharacterCount];
  IsoW_character = new bool[Game.CharacterCount];
}

//Functions definition

// Return absolute value
function IsoW_Abs(int x) { 
  if (x >= 0) return x;
  else return -x;
}

// Main module function
void IsoWalk(this Character*, int x, int y, BlockingStyle BStyle, WalkWhere WWhere) { // Alternative walk function. Core of the module.
  int ID = this.ID;
  int DeltaX = IsoW_Abs(x - this.x); //Distances between character and destination
  int DeltaY = IsoW_Abs(y - this.y);
  if ((ModuleON)&& ((DeltaX*DeltaX + DeltaY*DeltaY) > (MinDistance*MinDistance))) { //If Distance > MinDistance (Pythagore)
    int Signe;
    int xP1, xP2, xWP, yP1, yP2, yWP;
    //Calculating Waypoint Coordinates
    if (DeltaX >= DeltaY) { //Diagonal + Horizontal movement needed
      if (this.x - x >= 0) {
        Signe = 1;
      } else {
        Signe = -1;
      }
      if (!UseAlternateHorizontalPath) {
        xP1= x + DeltaY*Signe;  //Waypoint coordiantes
        yP1= this.y;
        xP2= this.x + DeltaY*(-Signe); //Alternative waypoint coordinate
        yP2= y;
      } else {// if IsoW_UseAlternateHorizontalPath P1 <-> P2
        xP1= this.x + DeltaY*(-Signe);  //Waypoint coordiantes
        yP1= y;
        xP2= x + DeltaY*Signe;//Alternative waypoint coordinate
        yP2= this.y;
      }
    } else { //DeltaX < DeltaY Diagonal + Vertical movement needed
      if (this.y - y >= 0) {
        Signe = 1;
      } else {
        Signe = -1;
      }
      if (!UseAlternateVerticalPath) {
        xP1= this.x;  //Waypoint coordiantes
        yP1= y + DeltaX*Signe;
        xP2= x; //Alternative waypoint coordinate
        yP2= this.y + DeltaX*(-Signe);
      } else {// if IsoW_UseAlternateVerticalPath P1 <-> P2
        xP1= x;  //Waypoint coordiantes
        yP1= this.y + DeltaX*(-Signe);
        xP2= this.x; //Alternative waypoint coordinate
        yP2= y + DeltaX*Signe;
      }
    }
    //Walking
    if ( WWhere == eWalkableAreas) {
      if (GetWalkableAreaAt(xP1-GetViewportX(), yP1-GetViewportY()) !=0) { //if P1 is in a WA, we use it
        xWP = xP1 + 3; // +3 are small hacks to force AGS to use Djikstra
        yWP = yP1 + 3;
      } else if (GetWalkableAreaAt(xP2-GetViewportX(), yP2-GetViewportY()) !=0) { //if P2 is in a WA but not P1, we use P2
        xWP = xP2 + 3;
        yWP = yP2 + 3;
      } else { //is not P1 neither P2 are in a WA, then we give up
        xWP = x;
        yWP = y;
      }
      if (BStyle == eBlock) {
        this.Walk(xWP, yWP, eBlock, eWalkableAreas);
        this.Walk(x, y, eBlock, eWalkableAreas);
      } else { //BStyle == eNoBlock
        this.Walk(xWP, yWP, eNoBlock, eWalkableAreas);
        IsoW_x[ID] = x;
        IsoW_y[ID] = y;
        IsoW_character[ID] = true;
        IsoW_eWalkableAreas[ID] = true;
        IsoW_noBlock = true; // 2nd part of the movement in Repeatidly_execute
      }
    } else { // WWhere == eAnywhere
      if (BStyle == eBlock) {
        this.Walk(xP1, yP1, eBlock, eAnywhere);
        this.Walk(x, y, eBlock, eAnywhere);
      } else { //BStyle == eNoBlock
        this.Walk(xP1, yP1, eNoBlock, eAnywhere);
        IsoW_x[ID] = x;
        IsoW_y[ID] = y;        
        IsoW_character[ID] = true;
        IsoW_eWalkableAreas[ID] = false;
        IsoW_noBlock = true; // 2nd part of the movement in Repeatidly_execute
      }
    }
  } else { //if module is OFF, or if too short distance
    this.Walk(x, y, BStyle, WWhere);
  }
}

//Non blocking movement
function repeatedly_execute() {
  if (IsoW_noBlock) {
    int i = 0;
    while (i < Game.CharacterCount) {
      if (IsoW_character[i] == true && character[i].Moving == false) {
        if (IsoW_eWalkableAreas[i]) {
          character[i].Walk(IsoW_x[i], IsoW_y[i], eNoBlock, eWalkableAreas);
        } else {
          character[i].Walk(IsoW_x[i], IsoW_y[i], eNoBlock, eAnywhere);
        }
        IsoW_character[i] = false;
      }
      i++;
    }
    IsoW_noBlock = false;
    i = 0;
    while (i < Game.CharacterCount) {
      if (IsoW_character[i]) {
        IsoW_noBlock = true;
      }
      i++;
    }
  }
}

// intercept left clicks in eModeWalkto to order a IsoWalk
function on_mouse_click(MouseButton button) {  
  if (IsoW_HACKWALK) {
    if (button == eMouseLeft) {
      if (Mouse.Mode == eModeWalkto) {
          player.IsoWalk(mouse.x + GetViewportX(), mouse.y + GetViewportY(), eNoBlock, eWalkableAreas);
          ClaimEvent();
      }
    }
  }
}
#8
Hey!
I'm making a Game for the February MAGS, called Lema Sabachthani.
It needs some proofreading as English is not my native language. So if someone is volunteer to proofread it, he or she will gain my eternal gratitude and some thanks in the credits. :P The MAGS end on March the 2nd, so I need proofreading as soon as possible.
Here's the .trs file (~9ko).
If possible, write the corrected sentence the line bellow the faulty one, and send the file back to me here or in a PM.
Obviously, warning! heavy spoilers inside!
Thanks!
#9
Nothing About The Dog
An amateur point&clicks adaptation of Jerome K. Jerome novel Three Men in a boat.

Topic aussi disponible en Français. :)

Screenshot 1:

Screenshot 2:


->Download Nothing About The Dog v1Cbeta4 (.zip file, around 68Mo)<-

To play the game, extract the archive and launch NATD_ags.exe. Game available in English and French. Estimated playtime: ~10 minutes.

Hello!
Here's my first video game! 8-0
I was planning to adapt the complete novel Three Men in a boat, and I started by the Chapter 10. It took me 18 month to complete it, so even if I plane to develop another chapter, I will certainly never complete this project (we always see to big the first time...). Anyway, Chapter 10 is now available & enjoyable, and I will soon start working on chatper 11.
The book Three Men in a boat is a comic novel first published in 1889 (freely available on the Internet now). Here's a small extract:
Quote from: Jerome K. JeromeIt always does seem to me that I am doing more work than I should do. It is not that I object to the work, mind you; I like work: it fascinates me. I can sit and look at it for hours. I love to keep it by me: the idea of getting rid of it nearly breaks my heart.
   You cannot give me too much work; to accumulate work has almost become a passion with me: my study is so full of it now, that there is hardly an inch of room for any more. I shall have to throw out a wing soon.
   And I am careful of my work, too. Why, some of the work that I have by me now has been in my possession for years and years, and there isn't a finger-mark on it. I take a great pride in my work; I take it down now and then and dust it. No man keeps his work in a better state of preservation than I do.
   But, though I crave for work, I still like to be fair. I do not ask for more than my proper share.
The story is just three buddies rowing up the Thames from London to Oxford because, you know, they worked so hard.

Many thanks to Calin Leafshade for its plugin SpriteFont render. Many thanks to vaztr, Mandle and Babar for there proofreading of the English version.
Because I am still terrible in English, it is probable than you'll meet a few typos. Do not hesitate to signal them to me!
On some configuration, on rare non reproducible occasions, you may encounter a crash while putting the kettle on the spirit shove (something like An exception 0xC0000005 occurred in ACWIN.EXE at EIP = 0x004522A6 ; program pointer is +72, ACI version 3.3.0.1144, gtags (3,3)). :(

Any comments welcome !

edit by darth - un-hid the screenshots (they must be visible)
edit 2017-05-31: the game development is paused for now...
#10
Hello there !

I finally manage to develop my first video game ! It's a Point&Click made with AGS (what a surprise! :-D).
It is called Nothing About The Dog and it's an adaption of the Jerome K. Jerome novel Three Men in a Boat. More precisely, so far I have adapt only the chapter 10. The game is around ten minutes long, with two rooms and two mini-games. Here's a pictures :

Yeah, their is room for my artistic talents to develop. :-\

French version of the game was released few weeks ago for intensive testing and bug discovery, and it is now pretty polished (at least, relatively to the first version).
My English level is quite bad... so I need help to proofread the English version of the game. Please, help me. :kiss:

The translation file is around 400 line long, but only 200 of them a real sentences. The other are just hotspot / objects / character names that are not displayed in the game.
On those 200 lines, around 100 are directly copy / paste from the novel (you can find the chapter 10 for free here, for example), the other were poorly written by me and are full of awful mistakes.

It will please me if 2 or 3 people:
-correct the most terrible English mistakes
-tell me if the original text (which date from 1889) is still readable now or if it need adaptation
-suggest me some reformulation of the sentences I wrote to adapt them to the style of the novel

This project is amateur, free and will certainly be open-source at some point, but if you help me I can offer you:
-credits in the game credits!
-a free version of the game!
-anticipated access to the game!
-my eternal gratitude!

You can download the game here (from my dropbox, around 65mo). It is by default in French, so be sure to modify the game language to "default" with the Winsetup.exe.
You can download an empty translation file here (around 17ko). It will ease me if you write your suggestion below the original sentences from this file and sent it back to me.

Many thanks!

EDIT: I've upload a new translation file including vaztr correction. Despite its fantastic job, I've made so many mistakes in the first place that there is still plenty of room for another proofreader! The game in not yet update, so it's better to work on the translation file.
#11
Engine Development / Bug in AGS pathfinder.
Thu 27/06/2013 21:29:01
Hello,
I (and other: Kitai and valoulef) have discovered a strange bug in AGS pathfinder (or, at least I think so). It is reproducible, but I have not so well define when it can occurs.
It happens mainly when a "pure horizontal" movement is ordered while the walkable area do not allow a single straight line passage. It may happen in pure vertical movement to, but that I am not sure.

I have made a small example project in which the bug is obvious : Download here, 1.8Mo
Its just the default template with an example room.
Spoiler
[close]
(sorry about image scale)
The archive contain an AGS project (and its compiled file). Just interact with the gray area to trigger this script :
Code: AGS
function hHotspot1_Interact()
{
  player.Say("First movement.");
  player.Walk(699, 551, eBlock, eWalkableAreas);
  player.Say("Second (buggy) movement.");
  player.Walk(67, 551, eBlock, eWalkableAreas);
}

Briefly, when player is in A and walk to B, character follow the yellow line, which doesn't seem to be the shortest pace.  :P
(Walkable area is the withe zone).

This bug is reproducible in AGS 3.2.1 and AGS 3.3.0 beta 4.
It does not depend on game resolution (tried in 1024x768 and 800x600).
It does not depend on blocking style.
It does depend on the shape of the walkable area.
It can be trigger with mouse click (and not script), but you'll have to be very accurate.
It is exacerbated when using this (still in development and not so well design) module that try to enforce walk on only 8 directions (verticals, horizontals and isometric diagonals).

Not sure if that helps, but it seems somehow dependent of 3x3 gird AGS uses for pathfinding :
Code: AGS

//Bug not present
player.Walk(699, 551, eBlock, eWalkableAreas);
player.Walk(67, 549, eBlock, eWalkableAreas);
//Bug present
player.Walk(699, 551, eBlock, eWalkableAreas);
player.Walk(67, 550, eBlock, eWalkableAreas);
//Bug present
player.Walk(699, 551, eBlock, eWalkableAreas);
player.Walk(67, 551, eBlock, eWalkableAreas);
//Bug not present
player.Walk(699, 551, eBlock, eWalkableAreas);
player.Walk(67, 552, eBlock, eWalkableAreas);
//Bug present
player.Walk(699, 552, eBlock, eWalkableAreas);
player.Walk(67, 552, eBlock, eWalkableAreas);


My wife think that it can be due to taking the wrong limit of ArcTan(delta(x)/delta(y)) when delat(y) is near 0, but  :-, it can be many other things and I am by far not competent to have a look in Engine source code.
#12
I have no idea of what will be the best solution, but I just wanted to enphasize that we should keep a way to quickely iterate things across all (existing) regions, like what we can do now :
Code: AGS
int i =1;
while (i < 50) { //current hostpot limit
    //do stuff on hotspot[i]
    i++;
}

But maybe there is no need to remind this to you, gods of code. ;)

(Split from here. - moderator)
(sorry about derailing the topic on the first reply.  :( - Billbis)
#13
As a novice programmer, I have taken the habit to test alternative methods of code by commenting / uncommenting portion of my scripts code.
I have not found such options in AGS editor 3.2.1 (but I may have not search at the right place...)
Would it be possible to add a button in the right click menu that will comment selected lines of code (i.e. adding a // at the beginning of each line)? and of course the reverse option will be useful too!
Am I the only one that will use this option?
Thanks.
#14
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]
SMF spam blocked by CleanTalk