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.
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...
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.
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.
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.
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 {}
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.
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.
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();
}
?
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.
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.
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.
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.
Good good, and I've got another function to play with now