Cursor and Interface question.

Started by Mats Berglinn, Sat 06/11/2004 13:09:16

Previous topic - Next topic

Mats Berglinn

I'm altering a Verb Coin template to use it for my current project Caribbean Mysteries. Right now whenever I click on the screen I can bring up the verb coin interface, which is not what it's suppouse to do. I like to the Interface be active only when the cursor lands on a hotspot, iventory item or character. Also, I want to change the cursor when it lands on a iventory item (changing color from white to red just like CMI) and back when it's not on a iventory item etc. Could you guys help me this?

I have a cursor that is white (cursor 0) and a red cursor (cursor 2)

Here's the script for the Interface (from the Global script)
function repeatedly_execute() {

if (IsGUIOn(2) == 0) { //is the GUI up?
if (clicked == 1) { //we check if someone clicked..
  if (IsButtonDown(LEFT) == 0) { //this executes if the button is released
    if (timer < 20) {
      ProcessClick(mousex,mousey,0);
      clicked=0; //stop that checking
      timer=0; //reset the timer
      //if the button isn't held more than 20 (about half a sec.), you'll
      //walk to the destination mousex,mousey...
      }
    }
  if (IsButtonDown(LEFT) == 1) timer++; //While it's held, timer is increasing
  if (timer >= 20) { //when you've held it for 20 (half a sec.), the GUI pops
    SetGUIPosition(2,guix,guiy);  //selfexplanatory? Oh, our GUI is numero 2.
    InterfaceOn(2); //turn the GUI on
    clicked=0; //guess what..
    timer=0; //and this?
    }
  }
}
else { //what will be checked when the GUI is infact on
  if (IsButtonDown(LEFT) == 0) { //what will happen if you release da button?
    if (GetGUIAt(mouse.x,mouse.y) == 2) {
      //this function checks if the cursor
      //is over an GUI
        int whatbutton;
        whatbutton = GetGUIObjectAt(mouse.x,mouse.y);
        InterfaceOff(2); //we'll turn the interface off
        Wait(1); //To make sure that the GUI is gone
        if (whatbutton > -1) ProcessClick(mousex,mousey,whatbutton+1);
          //This is the great part. First we check which button. Then, since
          //the buttons is set in the default cursor modes values subracted
          //by 1, we'll add one and we'll get the appropriate cursor mode.
          //Since GetGUIObjectAt() returns -1 if it's not over an button, it
          //would execute in walkmode if you're still inside the GUI-area when
          //releasing it. So first we make sure that you released on
          //a button, ie. that the int whatbutton is bigger than -1
        }
     else InterfaceOff(2); //otherwise, we'll simply turn it off, without s.t. else
     }
  }
}
#sectionend repeatedly_execute  // DO NOT EDIT OR REMOVE THIS LINE



#sectionstart on_key_press  // DO NOT EDIT OR REMOVE THIS LINE
function on_key_press(int keycode) {
  // called when a key is pressed. keycode holds the key's ASCII code
  if (IsGamePaused() == 1) keycode=0;  // game paused, so don't react to keypresses
  if (keycode==17)  QuitGame(1);   // Ctrl-Q
  if (keycode==363) SaveGameDialog();   // F5
  if (keycode==365) RestoreGameDialog();  // F7
  if (keycode==367) RestartGame();  // F9
  if (keycode==434) SaveScreenShot("scrnshot.bmp");  // F12
  if (keycode==9)   InventoryScreen();  // Tab, show inventory
  if (keycode==19)  Debug(0,0);  // Ctrl-S, give all inventory
  if (keycode==22)  Debug(1,0);  // Ctrl-V, version
  if (keycode==1)   Debug(2,0);  // Ctrl-A, show walkable areas
  if (keycode==24)  Debug(3,0);  // Ctrl-X, teleport to room
}
#sectionend on_key_press  // DO NOT EDIT OR REMOVE THIS LINE


#sectionstart on_mouse_click  // DO NOT EDIT OR REMOVE THIS LINE
function on_mouse_click(int 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==RIGHT) {
    if (GetCursorMode() == 4) SetCursorMode(0); //checks wether you use an inv.
else { InterfaceOn(3); SetCursorMode(2); SetMouseCursor(6); }   
// else InventoryScreen();
                       //brings up the usual Sierra inventory..
                       //In the next versions, it'll simulate a CMI-like
                       //inventory...
    }
  else if (button==LEFT) {  // left-clicking code
    if (GetCursorMode() == 4) ProcessClick(mouse.x,mouse.y,4);
    else { //these codes check wether you use an inventory or not..

    clicked = 1; //we trigger the calculating

    mousex = mouse.x; //we set these params to store the exact location of
    mousey = mouse.y; //where you clicked...

    guix = mousex - 25; //and we set the whereabout's for the GUI... and to
    guiy = mousey - 25; //center the GUI, we'll remove 25 (see below)...

    if (guix < 0) guix = 0; if (guix > 269) guix = 269;
    if (guiy < 0) guiy = 0; if (guiy > 149) guiy = 149;
      //Now we'll check these so the verbcoin won't appear to close to
      //the edges. If not altered, it may be impossible to select certain
      //commands! Why these numbers? Well, the GUI is exactly 50x50, which...

      //(NOTATE: the GUI is 50x50, not the graphic. That's why the GUI never will be
      //displayed without some space to the screen edge!!!)

      //...means that to center it by our clicks, it must be set to the mouse
      //coordinates - 25... AND, since AGS first coord. is (0,0), you
      //subtract 1 from the values. Also, as all other things, it spawns from
      //the top-right corner, so in the top and left side, well simply put it
      //close as possible ie. 0. On the other side, well take the largest value
      //(which is 319) and subtract 50 (the size of the GUI) and the equalent
      //from the bottom (199-50)
      }
    }
  }
#sectionend on_mouse_click  // DO NOT EDIT OR REMOVE THIS LINE


#sectionstart interface_click  // DO NOT EDIT OR REMOVE THIS LINE
function interface_click(int interface, int button) {
////////////////////////////////////////////////
// Inventory-GUI                              //
////////////////////////////////////////////////

if (interface == 3) {

      if (button == 0) {     
         InterfaceOff(3);
         SetDefaultCursor();

      }
      if (button == 1) {     
         InterfaceOff(3);
         SetDefaultCursor();

      }
      if (button == 2) {     
         InterfaceOff(3);
         SetDefaultCursor();

      }   
   }

}

Ashen

What if you change:
Code: ags

if (timer >= 20) {
  SetGUIPosition(2,guix,guiy);  //selfexplanatory? Oh, our GUI is numero 2.
  InterfaceOn(2); //turn the GUI on
  clicked=0; //guess what..
  timer=0; //and this?
}

to:
Code: ags

if (timer >= 20) {
  if ((GetLocationType (mouse.x, mouse.y) != 0) || (GetInvAt (mouse.x, mouse.y) != -1)) {
  //Checks if mouse is over character/hotspot/object/inv first
    SetGUIPosition(2,guix,guiy);  //selfexplanatory? Oh, our GUI is numero 2.
    InterfaceOn(2); //turn the GUI on
    clicked=0; //guess what..
    timer=0; //and this?
  }
}


For the second part:
Code: ags

//in rep_ex
if ((GetGUIAt (mouse.x, mouse.y) == INVENTORY) && (character[EGO].activeinv == -1)) {
// If you're on the inventory, and haven't selected an item
  if (GetInvAt (mouse.x, mouse.y) != -1) ChangeCursorGraphic (mode, REDCURSOR);
  // Change cursor if over inv item ...
  else ChangeCursorGraphic (mode, WHITECURSOR);
  // ... And back when it isn't
}
else SetDefaultCursor ();

Or something like that, anyway. Works for me, but you'll have to play with it a bit, depending on how exactly your game's set up.
I know what you're thinking ... Don't think that.

Mats Berglinn

The first script didn't work as hoped it would. I tried out but if you hold the left mouse button on anywhere that don't have characters, hotspots or objects the Verb Coin still pops up (it never does in MI3 which is pretty smart because it's useless otherwise) but strangely the verb coin appears the last time I used the verb coin on a hotspot.

About the second script: Actually I wanted the cursor to change color when it is on objects, characters and hotspots but it doesn't matter since in MI3 the cursor changes color also on iventory items in the iventory menu. The problem is that AGS says the word 'INVENTORY' in the script is wrong.
Have I missed something or what?

stuh505

Looks like INVENTORY, REDCURSOR, and WHITECURSOR are supposed to be replaced with the GUI / sprite numbers used in your game for those things

Ashen

Yeah, what Stuh505 said. INVENTORY is the name of the default inventory GUI, which I was using, so you need to change it if that's not what you're using. Looks like (GetGUIAt (mouse.x, mouse.y) == 3) should do it.

Same with REDCURSOR and WHITECURSOR - which should be sprite numbers - and mode - which is whatever cursor mode you're using as default. Sorry if I wasn't clear.

However, try this instead:
Code: ags

if ((GetLocationType (mouse.x, mouse.y) !=0) || (GetInvAt (mouse.x, mouse.y) != -1)) {
  //Is cursor over hotspot, object, character or Inv item?
  // Yes it is, so...
  ChangeCursorGraphic (mode, REDCURSOR);
}
else ChangeCursorGraphic (mode, WHITECURSOR); //No it isn't, so cursor goes back to normal


Should also change on characters, hotspots, and objects now.
I know what you're thinking ... Don't think that.

Mats Berglinn

I have changed the code but the cursor don't change color at all. I have tried it out but no dice.

This is how the script looks like now:

#sectionstart repeatedly_execute  // DO NOT EDIT OR REMOVE THIS LINE
function repeatedly_execute() {

if (IsGUIOn(2) == 0) { //is the GUI up?
if (clicked == 1) { //we check if someone clicked..
  if (IsButtonDown(LEFT) == 0) { //this executes if the button is released
    if (timer < 20) {
      ProcessClick(mousex,mousey,0);
      clicked=0; //stop that checking
      timer=0; //reset the timer
      //if the button isn't held more than 20 (about half a sec.), you'll
      //walk to the destination mousex,mousey...
      }
    }
  if (IsButtonDown(LEFT) == 1) timer++; //While it's held, timer is increasing
  if (timer >= 20) { //when you've held it for 20 (half a sec.), the GUI pops
    if ((GetLocationType (mouse.x, mouse.y) != 0) || (GetInvAt (mouse.x, mouse.y) != -1))
  //Checks if mouse is over character/hotspot/object/inv first
    SetGUIPosition(2,guix,guiy);  //selfexplanatory? Oh, our GUI is numero 2.
    InterfaceOn(2); //turn the GUI on
    clicked=0; //guess what..
    timer=0; //and this?
    }
  }
}
else { //what will be checked when the GUI is infact on
  if (IsButtonDown(LEFT) == 0) { //what will happen if you release da button?
    if (GetGUIAt(mouse.x,mouse.y) == 2) {
      //this function checks if the cursor
      //is over an GUI
        int whatbutton;
        whatbutton = GetGUIObjectAt(mouse.x,mouse.y);
        InterfaceOff(2); //we'll turn the interface off
        Wait(1); //To make sure that the GUI is gone
        if (whatbutton > -1) ProcessClick(mousex,mousey,whatbutton+1);
          //This is the great part. First we check which button. Then, since
          //the buttons is set in the default cursor modes values subracted
          //by 1, we'll add one and we'll get the appropriate cursor mode.
          //Since GetGUIObjectAt() returns -1 if it's not over an button, it
          //would execute in walkmode if you're still inside the GUI-area when
          //releasing it. So first we make sure that you released on
          //a button, ie. that the int whatbutton is bigger than -1
        }
     else InterfaceOff(2); //otherwise, we'll simply turn it off, without s.t. else
     }
  }
  if ((GetLocationType (mouse.x, mouse.y) !=0) || (GetInvAt (mouse.x, mouse.y) != -1)) {
  //Is cursor over hotspot, object, character or Inv item?
  // Yes it is, so...
  ChangeCursorGraphic (MODE_LOOK,2056);
}
else ChangeCursorGraphic (MODE_WALK,2054); //No it isn't, so cursor goes back to normal
}
#sectionend repeatedly_execute  // DO NOT EDIT OR REMOVE THIS LINE



#sectionstart on_key_press  // DO NOT EDIT OR REMOVE THIS LINE
function on_key_press(int keycode) {
  // called when a key is pressed. keycode holds the key's ASCII code
  if (IsGamePaused() == 1) keycode=0;  // game paused, so don't react to keypresses
  if (keycode==17)  QuitGame(1);   // Ctrl-Q
  if (keycode==363) SaveGameDialog();   // F5
  if (keycode==365) RestoreGameDialog();  // F7
  if (keycode==367) RestartGame();  // F9
  if (keycode==434) SaveScreenShot("scrnshot.bmp");  // F12
  if (keycode==9)   InventoryScreen();  // Tab, show inventory
  if (keycode==19)  Debug(0,0);  // Ctrl-S, give all inventory
  if (keycode==22)  Debug(1,0);  // Ctrl-V, version
  if (keycode==1)   Debug(2,0);  // Ctrl-A, show walkable areas
  if (keycode==24)  Debug(3,0);  // Ctrl-X, teleport to room
}
#sectionend on_key_press  // DO NOT EDIT OR REMOVE THIS LINE


#sectionstart on_mouse_click  // DO NOT EDIT OR REMOVE THIS LINE
function on_mouse_click(int 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==RIGHT) {
    if (GetCursorMode() == 4) SetCursorMode(0); //checks wether you use an inv.
else { InterfaceOn(3); SetCursorMode(2); SetMouseCursor(6); }   
// else InventoryScreen();
                       //brings up the usual Sierra inventory..
                       //In the next versions, it'll simulate a CMI-like
                       //inventory...
    }
  else if (button==LEFT) {  // left-clicking code
    if (GetCursorMode() == 4) ProcessClick(mouse.x,mouse.y,4);
    else { //these codes check wether you use an inventory or not..

    clicked = 1; //we trigger the calculating

    mousex = mouse.x; //we set these params to store the exact location of
    mousey = mouse.y; //where you clicked...

    guix = mousex - 25; //and we set the whereabout's for the GUI... and to
    guiy = mousey - 25; //center the GUI, we'll remove 25 (see below)...

    if (guix < 0) guix = 0; if (guix > 269) guix = 269;
    if (guiy < 0) guiy = 0; if (guiy > 149) guiy = 149;
      //Now we'll check these so the verbcoin won't appear to close to
      //the edges. If not altered, it may be impossible to select certain
      //commands! Why these numbers? Well, the GUI is exactly 50x50, which...

      //(NOTATE: the GUI is 50x50, not the graphic. That's why the GUI never will be
      //displayed without some space to the screen edge!!!)

      //...means that to center it by our clicks, it must be set to the mouse
      //coordinates - 25... AND, since AGS first coord. is (0,0), you
      //subtract 1 from the values. Also, as all other things, it spawns from
      //the top-right corner, so in the top and left side, well simply put it
      //close as possible ie. 0. On the other side, well take the largest value
      //(which is 319) and subtract 50 (the size of the GUI) and the equalent
      //from the bottom (199-50)
      }
    }
  }
#sectionend on_mouse_click  // DO NOT EDIT OR REMOVE THIS LINE


#sectionstart interface_click  // DO NOT EDIT OR REMOVE THIS LINE
function interface_click(int interface, int button) {
////////////////////////////////////////////////
// Inventory-GUI                              //
////////////////////////////////////////////////

if (interface == 3) {

      if (button == 0) {     
         InterfaceOff(3);
         SetDefaultCursor();

      }
      if (button == 1) {     
         InterfaceOff(3);
         SetDefaultCursor();

      }
      if (button == 2) {     
         InterfaceOff(3);
         SetDefaultCursor();

      }   
   }

}

Ashen

Well, see, you're changing two cursor modes there (MODE_LOOK, MODE_WALK), which might be confusing it - you might be altering the cursor for a mode you're not in, which wouldn't have any noticeable effect. What happens if you try:
Code: ags

if ((GetLocationType (mouse.x, mouse.y) !=0) || (GetInvAt (mouse.x, mouse.y) != -1)) {
  //Is cursor over hotspot, object, character or Inv item?
  // Yes it is, so...
  ChangeCursorGraphic (MODE_LOOK,2056);
  ChangeCursorGraphic (MODE_WALK, 2056);
}
else {
  ChangeCursorGraphic (MODE_WALK,2054); //No it isn't, so cursor goes back to normal
  ChangeCursorGraphic (MODE_LOOK,2054);
}

Just as a test. This should change the cursor regardless of which mode you're in.
I know what you're thinking ... Don't think that.

Mats Berglinn

I've got some good and some bad news.

The good news are that the cursor changes color on characters, hotspots and objects.

The bads news are that it doesn't affect the inventory items. And I still have the problem with the interface that can be used on everywhere but should only be working on characters, hotspots and objects.

Ashen

What inventory GUI are you using? Have you setup your custom one yet, or are you still using the InventoryScreen() one? For me, it didn't work on the InventoryScreen() one, but does on a custom one. If you are using a custom one, the problem maybe that it's popup modal - which means the rep_ex script might not run. Try setting it to 'Normal', and switch it off in game_start.
If it's already set to 'Normal', or if that doesn't work, then I'm out of ideas, it works fine for me.

Also, I think you're missing a couple of braces, which may be why the GUI pops up wherever you click:
Code: ags

Ã,  if (timer >= 20) { //when you've held it for 20 (half a sec.), the GUI pops
Ã,  Ã,  if ((GetLocationType (mouse.x, mouse.y) != 0) || (GetInvAt (mouse.x, mouse.y) != -1))
Ã,  //Checks if mouse is over character/hotspot/object/inv first
Ã,  Ã,  SetGUIPosition(2,guix,guiy);Ã,  //selfexplanatory? Oh, our GUI is numero 2.
Ã,  Ã,  InterfaceOn(2); //turn the GUI on
Ã,  Ã,  clicked=0; //guess what..
Ã,  Ã,  timer=0; //and this?
Ã,  Ã,  }


should be (I've trimmed out the comments to make it more obvious where they go):
Code: ags

Ã,  if (timer >= 20) { 
Ã,  Ã,  if ((GetLocationType (mouse.x, mouse.y) != 0) || (GetInvAt (mouse.x, mouse.y) != -1)) { // Brace here
Ã,  Ã,    SetGUIPosition(2,guix,guiy);
Ã,  Ã,    InterfaceOn(2); 
Ã,  Ã,    clicked=0; 
Ã,  Ã,    timer=0; 
Ã,  Ã,  } // And here
Ã,  }


I just checked, and they are there in my earlier post, not sure how they got missed out.
I know what you're thinking ... Don't think that.

Mats Berglinn

I'm not sure what you mean about the inventory screen and normal one but if you mean if I'm using the regular boring original old-fashioned AGS Inventory then I wouldn't say I do. The one that I'm using came with the template and it looks like the one CMI (unfortunitly it doesn't work 100 % like CMI).

Anyway, the code for the Verb coin not pop-up everywhere did work but something weird happen when I test it. When I try to use the Verb coin on a blank space (no character, hotspot or object) nothing happens but then when I put the cursor on a character, object or hotspot the Verb Coin kind of pop up at the latest area and then disappear again. Strange huh?

Ashen

Very strange, yes. Do you mean it pops up if you move over character/hotspot/object after having clicked somewhere else, or everytime? If it's just after a click, it may be that the buffers (clicked and timer) haven't reset, so when you move onto something the script gets called. Try:
Code: ags

  if (timer >= 20) { 
    if ((GetLocationType (mouse.x, mouse.y) != 0) || (GetInvAt (mouse.x, mouse.y) != -1)) { // Brace here
      SetGUIPosition(2,guix,guiy);
      InterfaceOn(2); 
      clicked=0; 
      timer=0; 
    } // And here
    else { //clicked 'nowhere', so...
      clicked=0; // stop checking
      timer=0; //reset timer
    }
  }


And about the InventoryScreen();  thing, it calls the internal Inventory (smaller, bland, expands when you pick up more items), as opposed to opening the Inventory GUI (GUI3 by default, larger, bland but customisable, fixed size). Look up the show_inventory_window () function near the top of the global script of a new AGS game.
I know what you're thinking ... Don't think that.

Mats Berglinn

Yeah, you were right. The problem is solved now.

I think that the MI3 template, that I'm altering, is made before AGS had the Iventory Screen command. So, what do you think I should do?

Ashen

I don't think youre version of AGS will pr-date InventoryScreen, but you're not using it, so it doesn't matter.
Did you try setting the GUI to 'Normal' visibility? As I said, if that doesn't work, I'm fresh out of ideas.
I know what you're thinking ... Don't think that.

Mats Berglinn

I'm sorry to say this but it changing the GUI visibility to normal doesn't go so well with the Interface for the game. The Interface is like in MI3 and therefore the inventory should be pop-up, not be always vinsible.

Ashen

Set it to 'normal', then add a InterfaceOff (3); to the game_start function. It'll function just like a popup modal GUI, except the cursor change should work. If it doesn't, just change it back and remove the InterfaceOff ().

I know what you're thinking ... Don't think that.

Mats Berglinn


Electroshokker

#16
Hi there.

I'm working on exactly the same problem.

I've managed get some stuff running properly. (you can get the template I made here)

but not everything works quite right.

Check it out, maybe you can use some of the code. If I manage to fix all my problems, I'll update the template.

For the changes (white cursor to red): in the cursor panel: animate only when over hotspot or object (with as animation the red version)

Does nothing for the inventory issue, though.

EDIT:

if (gGui4.Visible == true){
  if (mouse.Mode != eModeUseinv){
      if (InventoryItem.GetAtScreenXY(mouse.x, mouse.y) != null)
         mouse.UseModeGraphic(eModeUsermode2);
      else
         mouse.UseDefaultGraphic();
   }
}


(with usermode2 displaying the red version, and gui4 being my inventory)

POSSIBLE BUG: when selecting an inventory item, the cursor will turn into the inventory item's graphics instead of the red cursor

SOLUTION: use usermode2 (usermode1 apparently changes into item graphics)

SMF spam blocked by CleanTalk