Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: RetroJay on Wed 20/02/2008 21:43:08

Title: Walkto woes!
Post by: RetroJay on Wed 20/02/2008 21:43:08
Hi everyone.
I'm having a ''Walkto'' problem in my game.
I have created an "object" which is a closed door.
Now on other mouse clicks such as "Lookat", "Interact" and "speek" I used the ''move character'' and "Face location" to walk right up to the door and face it.
However I can't do this with "Walkto" and I am finding that when I click the "Walkto" cursor on the door my character 9 times out of 10 stands in the wrong place and facing the wrong direction. Is there a way to rectify this.
I did look before posting and found a few entries to do with "Walkto" but not the same prob as mine.

Thanks.
Title: Re: Walkto woes!
Post by: Matti on Wed 20/02/2008 22:56:50
Did you perhaps set the coordinates (the character is supposed to aim) to some point thats not within the walkable area?

Edit: Okay, this is unlikely for you say he walks properly 1 out of 10 times...
Title: Re: Walkto woes!
Post by: RetroJay on Wed 20/02/2008 23:17:24
It's a bit difficult to explain but here goes-
the walkable area goes up to the door. The door itself is quite big as it is a double door.
The problem is that if you click the Walkto cursor on the top of the door then my character walks to the far wall and faces that wall.
However if I click any other cursor on the door Then I have told my character to walk to certain coords and to face the door.
But I can't do this with the Walkto cursor.
Title: Re: Walkto woes!
Post by: OneDollar on Thu 21/02/2008 00:16:40
Walk-to doesn't work like the other interactions - when you click walk-to on an object you are telling the character to walk to the x and y coordinates that you click the mouse at, so you're not actually interacting with the object.

One solution I can think of at the moment would be to get rid of the inbuilt Walk-to mouse mode and create a new mode (eg over Usermode 1 or Usermode 2) that handles all the walking instead. Then you can treat uses of this new cursor mode on objects like other mouse modes. Making the new mode walk your character around is slightly harder though, especially if you're unfamiliar with scripting.

Alternatively if this is the only, or one of only a few instances you want to do this, you could use something like the following code in the room's repeatedly execute event:
if(mouse.IsButtonDown(eMouseLeft)&&(mouse.Mode==eModeWalkto)&&(Game.GetLocationName(mouse.x, mouse.y)=="Door")){
  player.Walk(x, y, eNoBlock, eWalkableAreas);
}

Where you replace 'Door' with the description of your door object (case sensitive) and 'x' and 'y' with the coordinates to move the character to. This script basically checks every game cycle to see if
1) The player is pressing the left mouse button and
2) The mouse mode is currently walk-to and
3) The mouse is currently over the door
and moves the player to the specified position if they are all true.
Title: Re: Walkto woes!
Post by: RetroJay on Thu 21/02/2008 01:50:42
OneDollar.
You are a genius.
Your bit of script works fine. I am so happy. :)
My character walks up to the door exactly where I want him now.
Just one more question. Can I simply put a "Face Location" command and a "Display Text" command after your script?
Sorry to be a pain. ;D

Thankyou.
Title: Re: Walkto woes!
Post by: Matti on Thu 21/02/2008 11:50:18
Quote from: RetroJay on Thu 21/02/2008 01:50:42
Can I simply put a "Face Location" command and a "Display Text" command after your script?

There should be no problem with that... just keep it within the {}
Title: Re: Walkto woes!
Post by: OneDollar on Thu 21/02/2008 12:15:45
Glad to be of service. I've done a bit of testing and doing multiple commands is possible but a bit different. As matti says, you can just put your commands inside the if function, but it does get a bit more complicated than that.

If you want the player to walk to a position, then face another, then say something, you need to change the player.Walk to be blocking (to make them finish their walk before facing and talking), unfortunately you start to encounter strange behaviour when you use eBlock instead of eNoBlock - the player will walk to the location, face, speak then walk again to wherever your mouse is. To solve this you could try something like this...

//At the top of the room script
bool walking=false;
int playerloop;

//In the room's repeatedly execute event
if(walking==true){  //if we've just run the function below
  player.StopMoving();  //stop the player moving
  player.Loop=playerloop;  //and face the direction he was facing when the function finished
  walking=false;
}

if(mouse.IsButtonDown(eMouseLeft)&&(mouse.Mode==eModeWalkto)&&(Game.GetLocationName(mouse.x, mouse.y)==oDoor.Name)){
  player.Walk(60, 60, eBlock, eWalkableAreas);  //walk to a location (blocking)
  player.FaceLocation(10, 10, eBlock);  //face a location
  player.Say("Here I go through the door");  //say something, (or replace with a Display function)
  playerloop=player.Loop;  //store the direction the player is facing
  walking=true;  //tell the function above that the player has finished walking and it needs to stop them walking towards the mouse!
}

The one problem with this is that the player faces the location of your mouse for a split second, before facing back again. I'm not quite sure how to fix that one at the moment. If you don't need a blocking walk, don't use one and remove the if(walking==true) function and the playerloop=player.Loop and walking=true lines, and it should run without the facing issue.

Note that I've also changed the "Door" part of the if function to oDoor.Name (where oDoor is the door object). This means you can safely change the description of the door (e.g. to "open door" or "closed door") without breaking the function.
Title: Re: Walkto woes!
Post by: Khris on Thu 21/02/2008 13:53:04
Using ClaimEvent() after the commands should do the trick, too (it stops AGS from processing the click).

However, using a custom mode isn't that hard:
function on_mouse_click(MouseButton button) {
  if (button==eMouseLeft) {
    // the following instead of ProcessClick(mouse.x, mouse.y, mouse.Mode);
    if (mouse.Mode==eModeCustomWalk && GetLocationType(mouse.x, mouse.y)==eLocationNothing)
      ProcessClick(mouse.x, mouse.y, eModeWalkto);
    else
      ProcessClick(mouse.x, mouse.y, mouse.Mode);
  }
  ..


Thus, clicking on an empty spot will invoke default Walkto behavior while clicking on an object, character or hotspot calls their CustomWalk interaction.
Title: Re: Walkto woes!
Post by: OneDollar on Thu 21/02/2008 15:04:29
Ah yeah, ClaimEvent would do it. Something like

if(mouse.IsButtonDown(eMouseLeft)&&(mouse.Mode==eModeWalkto)&&(Game.GetLocationName(mouse.x, mouse.y)==oDoor.Name)){
  player.Walk(60, 60, eBlock, eWalkableAreas);  //walk to a location (blocking)
  player.FaceLocation(10, 10, eBlock);  //face a location
  player.Say("Here I go through the door");  //say something, (or replace with a Display function)
  ClaimEvent();
}

?
Title: Re: Walkto woes!
Post by: Khris on Thu 21/02/2008 16:15:01
Yeah, that was the idea. Although I'm not sure if works with rep_ex; afaik it's meant to be used e.g. in a room's on_mouse_key function.
Title: Re: Walkto woes!
Post by: OneDollar on Thu 21/02/2008 18:38:27
No, it doesn't work outside of the on_mouse_click and on_key_press functions in the global script. You could find the

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 );
  }
  //etc...

bit in the global script and replace the "ProcessClick(mouse.x, mouse.y, mouse.Mode);" under the "else if (button == eMouseLeft){" with something like

  else if (button == eMouseLeft) {
    if(mouse.Mode==eModeWalkto)&&(Game.GetLocationName(mouse.x, mouse.y)=="Door")){
      player.Walk(60, 60, eBlock, eWalkableAreas);  //walk to a location (blocking)
      player.FaceLocation(10, 10, eBlock);  //face a location
      player.Say("Here I go through the door");  //say something, (or replace with a Display function)
      //etc...
    }else{
      ProcessClick(mouse.x, mouse.y, mouse.Mode );
    }
  }
  //etc...

but then you're approaching the point at which its simpler to write your own walk-to code.
Title: Re: Walkto woes!
Post by: Khris on Thu 21/02/2008 21:14:08
ClaimEvent is indeed meant to be used inside a room script, since its purpose is to prevent AGS from processing the global script's on_key_press and on_mouse_click function.
However it's true that it won't work in any other room function besides the two mentioned.

Since there's no need to do it in the rep_ex, solving the problem without an additional cursor mode is as easy as:
// room script

function on_mouse_click(MouseButton button) {
  if (button == eMouseLeft && mouse.Mode == eModeWalkto) {
    if (GetLocationType(mouse.x, mouse.y) == eLocationNothing) return;
    String s = Game.GetLocationName(mouse.x, mouse.y);

    if (s == "Door") {
      player.Walk(160, 114, eBlock, eWalkableAreas);
      player.FaceLocation(160, 113, eBlock);
      player.Say("Here I go through the door.");
    }
 
    if (s == "Tree") {
      player.Walk(190, 134, eBlock, eWalkableAreas);
      player.FaceLocation(191, 134, eBlock);
      player.Say("I can't climb this tree.");
    }

    ClaimEvent();
  }
}

Tested & working.
Title: Re: Walkto woes!
Post by: RetroJay on Thu 21/02/2008 21:40:17
WOW!!
Thanks everyone.

It appears I started something here.
But with all of your help I am delighted to inform you that the code
Khris has ended up with works wonderfully. :)

I see Khris that you have made it so as you can use this with more than just one object.
FANTASTIC!!
Once again thank you all very much.
Title: Re: Walkto woes!
Post by: OneDollar on Sat 23/02/2008 00:13:31
Good good, and I've got another function to play with now