Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: SwanOnARedCouch on Sat 01/10/2016 12:24:49

Title: Making the character walk to objects per default.
Post by: SwanOnARedCouch on Sat 01/10/2016 12:24:49
Hello everyone!
Very recently, I started making a little point and click adventure. With little to no expirience. But so far, everything worked out pretty good. I have the first room with a bunch of hotspots and the first proper object. That's where I started struggling.
I have read quite a lot of posts in here, where people had problems with making the character walk to objects. I know how to do that, but, and this might be the actual problem, I am very lazy. So I was wondering if there is a more effective way then putting in the walk to command for every single possible interaction.
I tried using the "Any click on object" thing, but this apparently gets executed after the actual interaction. Is there a way of solving this in order to save time? Maybe a code that can be included in the Global Script, that makes the character always walk to any object first?
I also have the same issue with the character facing both objects and hotspots, but I assume the solution is - granted there is one - is similar.

Thanks in advance!
(Please keep in mind, that I have no knowledge about coding, so you might need to explain stuff a bit more.)
Title: Re: Making the character walk to objects per default.
Post by: Jack on Sat 01/10/2016 13:00:33
Have a look at unhandled_event in the manual. This is where all clicks end up which are not handled in any other way first. You'll still need to programatically estimate where the player character should stand, as the desired position relative to the object will probably change depending on where that object is in the room. Designing walkable areas to suit this would also help.
Title: Re: Making the character walk to objects per default.
Post by: SwanOnARedCouch on Sat 01/10/2016 16:24:21
Thanks for the fast reply, but I'm uncertain if that's what I was looking for.
I had a look at unhandled_event and ended up pretty confused. (This is my first time using anything more complicated than RPG Maker.) As far as I understood it, this command 'jumps into action' if the player clicks something that I have not (yet) have included a response to. Or am I completley wrong? Could you maybe provide me with an example?
Or maybe I should ask more specifically?:
Let's say, I have a room with three objects in it. For each object I have scripted something for the three basic interactions (look, interact and talk). I did not script something to make the character walk to the object first. Now I could add that for every object and interaction, which would make a total of nine, even though it would be three that repeat themselves. Still it seems kinda tedious, especially in the long run.
Ideally, I would want a piece of code that makes the player walk to any object without me adding anymore scripts. A piece of code that has to be re-used once for every object, wouldn't be as ideal, but still a great time-saver.
Title: Re: Making the character walk to objects per default.
Post by: Mandle on Sat 01/10/2016 16:48:57
Isn't there a generic object name like Object[0] or something that counts as a global interaction with any object?
Title: Re: Making the character walk to objects per default.
Post by: Jack on Sat 01/10/2016 17:07:39
Quote from: SwanOnARedCouch on Sat 01/10/2016 16:24:21
As far as I understood it, this command 'jumps into action' if the player clicks something that I have not (yet) have included a response to. Or am I completley wrong? Could you maybe provide me with an example?

No, that's about the gist of it. Executing it would go something like this:


function unhandled_event (int what, int type)
{
  if ((what == 2) && (type == 1))  // runs only on "interact with object"
  {
    Object*obj = Object.GetAtScreenXY(mouse.x, mouse.y);
    if (obj != null)
      cEgo.WalkTo(obj.X, obj.Y, eNoBlock, eWalkableAreas);
  } 
}


This would mean though that you will have to handle all your interactions through unhandled_event, executing specific code after you have identified which object was clicked. There is "automatically walk to hotspots in look mode" (in general settings), but as the name suggests it works only in look mode.
Title: Re: Making the character walk to objects per default.
Post by: SwanOnARedCouch on Mon 03/10/2016 10:53:00
I'm having some problems with the code.
First, I got an Error saying that "WalkTo" is not a public member of "Character". I changed "WalkTo" into "Walk To", but I don't know if that solved it, because I got a new Error.
Apparently, the editor expects a normal bracket somewhere in this line:
Code (ags) Select
if (obj != null)
I couldn't figure out where though, so I couldn't start the game.

Little Addition:
If I put "Walk" instead of "WalkTo" (or "Walk To") in, I get a very weird Error, saying that it's missing a } and the function is still open. However, it says that error occurs on line -10. How is that possible?
Title: Re: Making the character walk to objects per default.
Post by: Khris on Mon 03/10/2016 23:25:41
I assume you want the player to behave just like she does for hotspots? As in a blocking walk to the object right before the event function?
You can do this by editing the GlobalScript's on_mouse_click function.

Assuming you're using the Default Game template, you should have this in there:
  else if (button == eMouseLeft) {
    ProcessClick(mouse.x, mouse.y, mouse.Mode );
  }

You need to replace that with:
  else if (button == eMouseLeft) {
   
    int mx = mouse.x; int my = mouse.y;
    if (GetLocationType(mx, my) == eLocationObject) {
      Object *o = Object.GetAtScreenXY(mx, my);
      int x = o.X + Game.SpriteWidth[o.Graphic] / 2;
      int y = o.Y;
      player.Walk(x, y, eBlock);
      player.FaceObject(o, eBlock);
      o.RunInteraction(mouse.Mode);
    }
    else ProcessClick(mouse.x, mouse.y, mouse.Mode );
  }



Edit: fixed code
Title: Re: Making the character walk to objects per default.
Post by: SwanOnARedCouch on Tue 04/10/2016 10:35:17
Wow, thanks!
The character now moves to the object and faces it, but they interact with themself instead of the object. I suppose its because they are covering up the object? Also sometimes they move over to a hotspot and interacts with it instead. That happens when the mouse moves over a hotspot.
Is there a way to ensure interaction with the object that was clicked on and not the thing the mouse is pointig at after clicking?
Title: Re: Making the character walk to objects per default.
Post by: CaesarCub on Tue 04/10/2016 11:12:56
Maybe by changing line 12 of the previous code with:

Code (ags) Select

    ProcessClick(mx, my, mouse.Mode );


You will be using the old mouse coordinates and not the ones where the mouse actually is.
Title: Re: Making the character walk to objects per default.
Post by: SwanOnARedCouch on Tue 04/10/2016 11:22:20
That worked, thanks a lot! Now the character isn't wandering off anymore. But they still interact with themselves when covering an object. I don't necessarily need interactions with the player character, so maybe that can be deactivated? Or is there a way where I can keep it?
Title: Re: Making the character walk to objects per default.
Post by: Jack on Tue 04/10/2016 11:30:56
Quote from: SwanOnARedCouch on Mon 03/10/2016 10:53:00
I'm having some problems with the code.

Oh yeah, screwed up a few things there. Like, the if (obj != null) statement needs { and } surrounding the cEgo command, and I wrote WalkTo, when the real command is Walk. But Khris' solution is preferable, hooking into on_mouse_click. You will probably additionally want to check which mode the mouse cursor is in so that you can limit to certain interactions only (Mouse.Mode == eModeInteract). This is based on some assumptions about your interface so you may or may not need it. Also, once you determine that this is an object that you want to walk to, you can probably skip the processclick and go directly to your scripted interactions where you will check which object it is and act accordingly. For this reason you should probably place such a block in every room script, otherwise the global script version of on_mouse_click will get large and messy. There are better ways than duplicating the code but I think that will get a bit ambitious for one post.

But it might go:


      else if (button == eMouseLeft)
      {
        int mx = mouse.x; int my = mouse.y;
        if ((Mouse.Mode == eModeInteract) && (GetLocationType(mx, my) == eLocationObject))
        {
          Object *o = Object.GetAtScreenXY(mx, my);
          int x = o.X + Game.SpriteWidth[o.Graphic] / 2;
          player.Walk(x, o.Y, eBlock);
          player.FaceObject(o, eBlock);

          switch (o.ID)
          {
            case 0: vaseInteraction(); // this is a user-defined function in the room script
            case 1: andSoForth();
          }
        } else {
          ProcessClick(mx, my, mouse.Mode);
        }
      }


Switch is a new feature and may not be in the AGS version you're using. It's a neater way to do a bunch of if...else if checks.

Clickable character can be disabled in general settings, but if you want a clickable character, the above method should still work.
Title: Re: Making the character walk to objects per default.
Post by: Khris on Tue 04/10/2016 13:01:30
Sorry, I was half asleep already ;)
You need to call o.RunInteraction(mouse.Mode);I fixed the code in my previous post.
Title: Re: Making the character walk to objects per default.
Post by: SwanOnARedCouch on Tue 04/10/2016 14:41:20
YAY! It worked! Khris' new code did the trick. It also started the interactions on the player character, but since I don't really need them, I removed them and now it works just fine.
Thank you all so much!
One last question: Can a variation of this code be used to make the character face hotspots after walking towards them? In that case all my problems would be solved.
Title: Re: Making the character walk to objects per default.
Post by: Khris on Tue 04/10/2016 20:14:58
When I fixed my code I also added an "else" here:
else ProcessClick(mouse.x, mouse.y, mouse.Mode);
So a click will *either* run the object's interaction *or* process the click as usual, but not both. You shouldn't have to remove the player's interactions.

Anyway, to do the same for hotspots, you can try this:
  else if (button == eMouseLeft) {
   
    int mx = mouse.x; int my = mouse.y;
    int lt = GetLocationType(mx, my);
    if (lt == eLocationObject) {
      Object *o = Object.GetAtScreenXY(mx, my);
      player.Walk(o.X + Game.SpriteWidth[o.Graphic] / 2, o.Y, eBlock);
      player.FaceObject(o, eBlock);
      o.RunInteraction(mouse.Mode);
    }
    else if (lt == eLocationHotspot) {
      Hotspot *h = Hotspot.GetAtScreenXY(mx, my);
      player.Walk(h.WalkToX, h.WalkToY, eBlock);
      player.FaceLocation(h.WalkToX, h.WalkToY, eBlock);
      h.RunInteraction(mouse.Mode);
    }
    else ProcessClick(mx, my, mouse.Mode);
  }
Title: Re: Making the character walk to objects per default.
Post by: SwanOnARedCouch on Tue 04/10/2016 22:40:07
But doesn't
Code (ags) Select
      player.FaceLocation(h.WalkToX, h.WalkToY, eBlock);
Make the player face the WalkTo point? Which they are already standing on? Because currently, the character seems to face a rather random direction.
Title: Re: Making the character walk to objects per default.
Post by: Khris on Tue 04/10/2016 23:14:23
Right, what you can do is place the walkto point a few pixels outside the walkable area. That way the player will get as close as they can, then turn to face in the direction of the walkto point.
The alternative is to remove the FaceLocation command and turn the player appropriately in the hotspot's interaction function.
Title: Re: Making the character walk to objects per default.
Post by: SwanOnARedCouch on Tue 04/10/2016 23:51:01
I didn't even consider placing the WalkTo points outside of the walkable areas. It was a bit tricky first, but it works out fine.
You can consider my questions answered and my problems solved :-D
Thank you!