Making Interesting NPC Move Routes with Script Calls
June 8, 2021
June 8, 2021

Making Interesting NPC Move Routes with Script Calls

Making Interesting NPC Move Routes with Script Calls



June 8, 2021

‍Having NPCs wandering around a map can bring a lot of life to the scene, but sometimes it feels like the only options are to have them walk a simple planned route or move randomly. That’s not the case though! With some script calls and out-of-the-box thinking, we can add new moves into our NPC events.

Today our focus is on the Autonomous Movement section of events, so that our events can keep doing their move route without our players needing to interact with them.

We’ll be making use of MZ’s Script Call Reference sheet to find the script calls we can use in the move routes, so make sure to check it out while you’re working on your events!

Having an Event Watch Another Event

The first thing we’ll have an event do is turn to face another event. While there are built-in options for events to turn towards the player, the only way to have an event turn towards a different event is to use a script call. Obviously we’ll need two events to have this work, the event that will be turning towards the event (in this example it will be a Staring Man event) and the event that will be being watched (the Clown).

The Clown in our example is simple and will just walk around our Staring Man so that we can be sure that Staring Man is actually turning to stare. The Staring Man event is where the Autonomous Movement really matters. To make sure that the event is keeping its eyes on the Clown, let’s set the Frequency to ‘5: Highest’.

The move route in this case is short since it only needs to call the script call, using the button-right command.

If we check the script call reference page, the basic script call to turn towards another event is $gameMap.event(id).turnTowardCharacter(character) . We’ll need to replace the id and character parts for the script to work, with id being replaced with the moving event’s id (in this case, the Staring Man’s event id is 3) and character being replaced with the target event. We can’t just replace character with a number though, we need to make sure the engine knows we’re talking about an event by using $gameMap.event(id) and replacing id with the Clown’s event id (which is 10 in the case of my project). Putting that all together, our script call ends up being $gameMap.event(3).turnTowardCharacter($gameMap.event(10)) .

Now that will work fine, but since we’re having the script call happen in our Staring Man’s move route, we can actually shorten the script call a little bit. Instead of using $gameMap.event(3) to tell the engine which event is doing the action, we can use this to tell the engine that this event will be doing it.

So with those modifications, our script call to get our Staring Man event to watch the Clown ends up being this.turnTowardCharacter($gameMap.event(10)) .

All that’s left is to playtest and make sure that our Staring Man is keeping a constant eye on the Clown. Now we can add a NPC who’s keeping an eye on their kid running around the map, or have a guard watch a suspicious character who’s pacing outside of a noble’s house.

One Event Following Another

Watching another event is a nice touch, but what if we wanted to go further and have an event follow along right behind a different event? We could plan out an entire route for both of them to use, but if we want our leader to move randomly around the map then we’ll need two events, two variables, and a switch to get this to work well. For this example, Kid 1 will be the event that’s leading and Kid 2 will be the event that is following behind.

Kid 1 has the important role of choosing where the two events will be going. We’ll get to the move route in a minute, but before that let’s take a quick look at how we’ll be using the switch. Because other events will keep moving when the player is interacting with an event, if we don’t add in a way to keep these kids still there’s the chance that Kid 1 could wander off and leave Kid 2 while Kid 2 is talking to the player. So let’s turn on our switch to activate our events’ page 2 while the event is running, and then turn the switch off again once the event is done so they can continue moving.

Kid 1’s page 2 can pretty much be a copy of page 1, with the biggest difference being that it has its Autonomous Movement set to ‘Fixed’ so that it will stay still while our switch is on. Kid 2’s page 2 will be set up in the same way.

Now that our kids will behave when we talk to them, we can focus on their move routes. Kid 1’s move route needs to do two things: tell Kid 2 where they need to move to and move randomly. The Move at Random command will cover Kid 1’s movement, so all we need is some script calls to save Kid 1’s previous location into our two variables.

$gameVariables.setValue(var, value); is the script call we’ll be using, with var being the variable’s number (we’ll be using 100 and 101 in this example, but any two variables that you aren’t already using will work) and value will be where Kid 1 is standing. Since we need both the X and Y values to tell Kid 2 where to go, we’ll need to use the script call twice. To find the exact X and Y locations of Kid 1 we can use $gameMap.event(id).x and $gameMap.event(id).y . Though as we learned in the previous example, since we will be checking this event’s X and Y we can use the simpler this.x and this.y versions.

So Kid 1’s script call ends up being $gameVariables.setValue(100, this.x); $gameVariables.setValue(101, this.y); . And with that, we’ve saved the location where we want Kid 2 to move to!

Kid 2’s event has two pages set up similar to Kid 1, with the main difference being its move route.

Kid 2’s script call is actually made up of two script calls, one to point the sprite in the right direction and one to move the event. The script to move the event is $gameMap.event(id).moveStraight(d) , where d is the direction that the sprite is moving. But we can’t just put a number there since we don’t know for sure which direction Kid 2 needs to move, which is why we need that other script call. $gameMap.event(id).findDirectionTo(x, y) will let us point Kid 2 towards certain X and Y coordinates, and since we made sure to save Kid 1’s previous coordinates in variables we can replace the x with $gameVariables.value(100) and the y with $gameVariables.value(101). Then we just need to replace the earlier script’s d with this new script call so Kid 2 will move into the spot Kid 1 had been in.

And of course, we can replace the $gameMap.event(id)’s with this.

Putting it all together, we end up with this.moveStraight(this.findDirectionTo($gameVariables.value(100), $gameVariables.value(101))) .

All that’s left is to playtest and make sure our two kids stick together!

There are a few minor things to keep in mind with this setup. It’s possible that Kid 1 can be trapped in a corner by Kid 2 if there are areas on the map that only have one way in. That can be fixed by either making sure there are no spots an event can get trapped in or by making Kid 2’s event ‘Through’ so both the player and other events can pass through it but that could look odd in-game. Test out both methods to see which looks best for your game.

One Event Controlling Other Events

The last example we’ll look at in this tutorial is how to have one event control two kids playing with a ball. We could try to time each events’ movements separately, but it’s a lot simpler to have just one of the events control it all.

We’ll need three events for this to work, two kid events and one event for the ball.

The two kid events don’t have any move routes of their own, they just have the Stepping and Direction Fix options checked so that it will appear like they’re focused on playing.

The Ball event is where all the movement happens.

The Ball’s move route should follow a simple pattern: one of the kid events jumps in place and then the Ball jumps to the spot in front of the other kid, as if it was kicked, and then the other kid jumps and the Ball returns to its spot in front of the first kid. The Ball’s jumping can be done with the Jump command, and we just need to count how many tiles it needs to move to be in front of the other kid event. To control the kids, we’ll need a script call.

The script call to make an event jump is $gameMap.event(id).jump(+/-x, +/-y) , where the +/-x tells use how many tiles left or right (positive numbers for right, negative for left) the event moves and the +/-y tells use how many tiles up or down (positive number for down, negative for up). But since we don’t want the kid’s event to move, we can just put 0 in both spots.

So to make our first kid’s event jump, we’ll use $gameMap.event(4).jump(0, 0) .

The second script call also makes a kid event jump in place, but since the ball is in front of Kid 2 the id will be 5.

With the move route ready to go, we can playtest and see the playing kids in action!

And now we know how to add some new effects to our NPCs’ move routes. What other script calls could you imagine using in move routes to make them different?

Recommended Posts