Beginner - Changing Cursor So That Over Hotspot It Automatically Changes

Started by timmle, Wed 30/07/2008 21:04:13

Previous topic - Next topic

timmle

I am incredibly new at this, so be gentle.

I'm just slowly building this from the bottom up and my first step is to get my cursor how i want it.

I'm a big fan of broken sword and i would prefer my cursor to act like that.

For instance;  I have a door which when the mouse rolls over it i would like it to change to the eye, but when the mouse rolls over the door handle it activates the 'To Do' cursor instead.

I have my Look At Hotspot code typed in for my door, and i understand i will have to do this on my actions, but as i understand it i will have to make changes to he global script for this cursor thing to apply to the whole game?

I have searched the forums using the search function and the best i can, and there are a few topics which go over the same thing that i would like, but i am not at a good enough level of understanding yet to be able to just write code or write the rest of it by myself.

What code would i use to achieve this, and would it be placed in the globalscript file?

BOYD1981

i'm no expert at this so i really should let somebody more experienced answer first but, as far as i'm aware there is no need to make any changes globally to the game to achieve this unless you actually only do want to script this once and not for every door handle in the game.
getting the cursor to change to the action mode is fairly straight forward, under a hotspot's interaction editor there's an option for doing something when the cursor is over the hotspot.
if you did want to save yourself some bother and not add the script for every door handle hotspot then i think it could be done by adjusting the hotspot properties so that they all have a specific property, then you'd just have to script a mouseover interaction to change the cursor mode when it's over any hotspot with that property, although i am not entirely sure where you would this (my guess would be repeatedly_excute_always).
i am making it sound way more complicated than it is though, so i suggest you look at Properties in the AGS help file for some more coherant information :)

Limey Lizard, Waste Wizard!
01101101011000010110010001100101001000000111100101101111011101010010000001101100011011110110111101101011

Khris

Yep, inside the repeatedly_execute function.

Since you'll want different default actions for different hotspots, you'll have to tell the game each hotspot's default cursor. This can be done using the properties.
In a hotspot's properties (hehe) pane, click on Properties (below Properties, hehe), then click the little button with the ellipses.
In the window, click the Edit schema... button.
Right-click inside the new window, click Add new property, then enter:
def_curs
default left-click action
Number
2

(I've chosen 2 as default action, that's eModeInteract, the Broken Sword cogs cursor. If your game's gonna have more hotspots where the looking glass is supposed to be the default action, enter 1.
It's not that important but will save you some time later.)

Now click OK, then Close.

You've just added a number property to every hotspot ever to be in the game (and all objects, characters, etc.)
It's default value will be 2, so in the course of designing, you'll have to change it to whatever the left-click action for the new hotspot/object's supposed to be. For eModeLookat, enter 1, for eModePickup, enter 5. Character's will always have 3/eModeTalkto as default as you'll see soon, though that could be changed, if you wanted. (You can see the numbers of the cursor modes if you expand the Mouse cursors node in the editor.)

The next step is to automatically switch the cursor:
Open the global script, then navigate to the repeatedly_execute function (by hand or selecting it from the drop-down menu at the top).
Change it to:
Code: ags
function repeatedly_execute() {

  if (IsGamePaused()) return;

  int mm = mouse.Mode;
  int nm;     // new mode
  Hotspot*h;
  Object*o;
  int lt = GetLocationType(mouse.x, mouse.y);   // what's under the cursor?

  if (mm != eModeUseinv) {
    if (lt == eLocationNothing) nm = eModeWalkto;
    if (lt == eLocationHotspot) {
      h = Hotspot.GetAtScreenXY(mouse.x, mouse.y);
      nm = h.GetProperty("def_curs");
    }
    if (lt == eLocationObject) {
      o = Object.GetAtScreenXY(mouse.x, mouse.y);
      nm = o.GetProperty("def_curs");
    }
    if (lt == eLocationCharacter) {
      nm = eModeTalkto;
    }

    if (nm != mm) mouse.Mode = nm;  // only change if necessary to not disturb animated cursors
  }
}


Now look for the on_mouse_click function, in there look for this part:
Code: ags
  else if (button == eMouseRight || button == eMouseWheelSouth){
    // right-click our mouse-wheel down, so cycle cursor
    mouse.SelectNextMode();
  }


Replace it with:
Code: ags
  else if (button == eMouseRight){
    // right-click
    if (mouse.Mode == eModeUseinv) mouse.Mode = eModeWalkto;   // loose inv item
    else ProcessClick(mouse.x, mouse.y, eModeLookat);             // or look at ...
  }

Then remove the last else-if block checking for eMouseWheelNorth.

There's still room for improvement, e.g. you can mark hotspots representing exits with an additional property, then use eModeInteract as mouse.Mode but change the cursor's graphic to a door animation.

This doesn't interfere with AGS's usual way of processing mouse clicks, so combining it with non-blocking walks is also possible. But it's late here and I gotta go to sleep.

Maybe one or two errors sneaked their way into all of the above; I'll be back tomorrow.

EDIT: corrected rep_ex.

timmle

It did seem to throw up some errors and didn't execute.

I copied over the repeatedly execute function so that it got rid of the on game pause part, i hope that is right.

And on the deleting wheelmouse north----------

else if (button == eMouseWheelNorth) {
    // Mouse-wheel up, cycle cursors
    // If mode isn't WALK, set the previous mode (notice usage of numbers instead
    // of eNums, when it suits us)...
    if (mouse.Mode>0) mouse.Mode=mouse.Mode-1;
    else
    {
      // ...but if it is WALK mode...
      if (player.ActiveInventory!=null)
      {
        //...and the player has a selected inventory item, set mouse mode to UseInv.
        mouse.Mode=eModeUseinv;
      }
      else
      {
        // If they don't, however, just set it to mode TALK (change this line if you add more cursor modes)
        mouse.Mode=eModeTalkto;
      }
    }
  }
}


Do i delete all of that???



Khris

Sorry, I forgot two asterisks.
And I put the pause line back in.
Please replace your rep_ex with the one from my previous post once more.

And yes, all the eMouseWheelNorth code is supposed to be deleted, it's just that long because of a necessary additional check and lots of comments, there's isn't that much in there.

Also, mind the {s and }s. Only delete up until and including the } with two spaces in front of it.

timmle

Thankyou very much, that worked like a charm after the edit, it's working perfectly, now all i have to do with each hotspot in edit Schematics is choose which icon i want to appear as default which you showed me in the first step.

Two questions now if you please;

1) If i have two things actions (Look And Action) on the same hotspot, do i just enter those things into the properties where i normally would, or do i have to edit schematics again for each hotspot, and put like a def_right_click action in there?

And Secondly;

How do i apply this to the inventory window now, because i have entered this code i can't click on the magnifying glass or the pointer as it doesn't do anything, but i can't pick up the item in the inventory either, so how would i use the deafult cursor (what is set to my walk) to choose the icon in the inventory?

Thankyou Once Again.

Khris

1) Broken Sword style in this case would be: Hover over the hotspot -> mouse turns into cogs.
Left-click -> action
Right-click -> look

So in this case (assuming that the hotspot's default action in the properties is 2/eModeInteract), the only thing left to do is to add whatever you want to happen to the hotspot's "look at hotspot" and "interact with hotspot" events, like you would with the default sierra interface.

2) You'll have to add a few lines of code to both rep_ex and on_mouse_click:
Code: ags
function repeatedly_execute() {
  
  // put anything you want to happen every game cycle, even when
  // the game is paused, here
  
  int x = mouse.x;
  int y = mouse.y;
  
  if (IsGamePaused() == 1) return;

  int mm = mouse.Mode;
  int nm;     // new mode
  Hotspot*h;
  Object*o;
  InventoryItem*i;
  int lt = GetLocationType(x, y);   // what's under the cursor?

  GUI*g = GUI.GetAtScreenXY(x, y);
  
  if (mm != eModeUseinv) {
    if (g == gInventory) {
      if (mm != eModeUseinv) nm = eModePointer;
    }
    else {
      if (lt == eLocationNothing) nm = eModeWalkto;
      if (lt == eLocationHotspot) {
        h = Hotspot.GetAtScreenXY(x, y);
        nm = h.GetProperty("def_curs");
      }
      if (lt == eLocationObject) {
        o = Object.GetAtScreenXY(x, y);
        nm = o.GetProperty("def_curs");
      }
      if (lt == eLocationCharacter) {
        nm = eModeTalkto;
      }
    }
    if (nm != mm) mouse.Mode = nm;  // only change if necessary to not disturb animated cursors
  }
}


Code: ags
function on_mouse_click(MouseButton button) {
  // called when a mouse button is clicked. button is either LEFT or RIGHT
  if (IsGamePaused() == 1) {
    // Game is paused, so do nothing (ie. don't allow mouse click)
  }
  else if (button == eMouseLeft) {
    ProcessClick(mouse.x, mouse.y, mouse.Mode );
  }
  else if (button == eMouseRight){
    // right-click
    if (mouse.Mode == eModeUseinv) mouse.Mode = eModeWalkto;   // loose inv item
    else ProcessClick(mouse.x, mouse.y, eModeLookat);             // or look at ...
  }
  else if (button == eMouseMiddle) { 
    // Middle-button-click, default make character walk to clicked area (a little shortcut)
    // Could have been just "player.Walk(mouse.x,mouse.y)", but it's best to
    // leave our options open - what if you have a special script triggered
    // on "walking" mode?
    ProcessClick(mouse.x, mouse.y, eModeWalkto); 
  }
  else if (button == eMouseLeftInv) {
    if (mouse.Mode == eModeUseinv) inventory[game.inv_activated].RunInteraction(eModeUseinv);
    else {
      player.ActiveInventory = inventory[game.inv_activated];
      // mouse.Mode = eModeUseinv;
    }
  }
  else if (button == eMouseRightInv) {
    if (mouse.Mode == eModeUseinv) mouse.Mode = eModePointer;
    else inventory[game.inv_activated].RunInteraction(eModeLookat);
  }
}


In General settings, make sure that in the Inventory section, "Handle inventory clicks in script" is set to true.
Remove all buttons from the inventory GUI (except the scroll arrows).

timmle

You might be able to answer this quite quickly KhrisMUC.

Since i've put the Edit Schematics which applies to every hotspot i have changed the number for the cursor on each individual schematic option depending on which one i would like to be left click or i've added another one for say right click undeneath using 'add new property' in schematics and that has worked fine.

I now would like to remove all hotspots on my character, i have removed all the commands in the events tab, and the script in the globalscript.asc so that 'look at yourself', 'interact with yourself', and 'talk to yourself have all been taken out - because i just dont need that in the game.

But because of the schematic which applies to every hotspot in the game i still get the mouth icon running over the character, which i would like to remove.

I can't remove the schematic on that characters properties cos it messes things up and the game wont execute. I'm guessing because it removes all schematic options, whereas modifying it for each invididual hotspot or object doesn't remove it completely.


Is there an option anywhere to remove hotspots on your character?

olafmoriarty

Quote from: timmle on Sun 03/08/2008 15:34:15
Is there an option anywhere to remove hotspots on your character?

If I understand you correctly: On the character's Properties panel, under "Design", set "Clickable" to "false".

timmle

Thankyou for that, worked a charm, didnt think it was so simple!

olafmoriarty

You're welcome. It should be noted that doing this has another great advantage: You can now click on hotspots and objects behind your character without having to move the character first.

Technocrat

I've tried to put this to work, and while it works brilliantly in the game, the inventory is still giving me trouble. I took out the buttons, minus the scroll ones, but it still won't let me select the inventory items - i.e. the scroll buttons work, move up and down through the list, but when I click on the items, the cursor doesn't change. I've put in the updated code, but I'm still unclear on how to fix it.

Khris

a) Make sure your inventory GUI is called "gInventory".

b)
QuoteIn General settings, make sure that in the Inventory section, "Handle inventory clicks in script" is set to true.

fly

let me involve a little..beginner too..how can I make that cursor changes over only one hotspot ?
Anyone that is willing to explain to me some things please send me a pm, thx

Khris

There's a hotspot event called "Mouse moves over hotspot"...

Code: ags
function HOTSPOT-SCRIPTNAME_MouseMove() {
  mouse.SaveCursorUntilItLeaves();
  mouse.Mode = eModeNEWMODE;
}

Technocrat

Quote from: KhrisMUC on Tue 12/08/2008 23:38:23
a) Make sure your inventory GUI is called "gInventory".

b)
QuoteIn General settings, make sure that in the Inventory section, "Handle inventory clicks in script" is set to true.


This is very strange. After some experimenting, I found that setting the "Handle inventory clicks in script" to true meant that I couldn't select items in the inventory, but now that I've set it to false, the whole thing works fine...so far.

Khris

I'm not sure what's going on there, just note that setting it to false will effectively render the following part of on_mouse_click useless since it's never executed:
Code: ags
  else if (button == eMouseLeftInv) {
    if (mouse.Mode == eModeUseinv) inventory[game.inv_activated].RunInteraction(eModeUseinv);
    else {
      player.ActiveInventory = inventory[game.inv_activated];
      // mouse.Mode = eModeUseinv;
    }
  }
  else if (button == eMouseRightInv) {
    if (mouse.Mode == eModeUseinv) mouse.Mode = eModePointer;
    else inventory[game.inv_activated].RunInteraction(eModeLookat);
  }

SMF spam blocked by CleanTalk