Skip to content

Episode 2 - Script

Hook

Footage

NPCs moving around in Stormwind and Goldshire.

Today, let's talk about and actually make a few existing NPCs move around Stormwind. Let's also introduce a new NPC in Goldshire and have her walk to Northshire Abbey.

Introduction

Footage

Beautiful lake near Stormwind.

Azeroth is a stunning world. Not just visually, but also in its size and diverse range of biomes. I loved exploring it as a new player in 2006, and today I can explore it all to my self on my own laptop! However, the state of Azeroth during the era of the WOTLK can be summed up quite simply as: static.

Introduction: Patreon

This is a short, but high-value, version of my complete video. I've set up a new Patreon for those who are interested in much more detail, a write up, and more videos. Link in the description.

Body: The Static World

Footage

Various biomes and beautiful locations around Azeroth.

When I first played WoW back in 2006, it was the world itself that I loved the most. Specifically, it was the sheer size of it that I was drawn to - there are so many biomes to explore, NPCs to talk to, side quests, and things to see. This was mostly what I did when I played the game way back when: I just travelled around, hardly doing any of the dungeons or raids, and mostly playing alone. I liked it that way.

As I moved around the world - the towns, the cities, and the landscapes - I began to notice the world was kind of static. Obviously buildings and such don't move, but neither did the NPCs. They never even so much as walked an inch or even ventured into the building they're so often standing directly next to... why?

Footage

Goldshire NPCs just stood there. Time lapse.

I also began to notice that the day/night cycle of Azeroth was basically just a visual effect. Nothing reacted to the cycle, not even the NPCs, who seem to be able to stand on the same spot 24 hours a day, come rain or sunshine. They don't even eat or sleep... again, why?

All of this got me thinking: can I make the NPCs move around from time to time, and can I make the day/night cycle relevant and even a cool game play mechanic?

I'm going to explore the movement of NPCs. I'll look at the day/night cycle next time because I want to dedicate a decent amount of development time to it and give my audience (that's you!) a decent bit of content with a balanced amount of detail.

Today however, let's take a look at what's involved with moving NPCs around.

NPC Movement

Footage

Three-way split focusing on our NPCs of interest.

To get the ball rolling, or should I say the NPC moving, I decided I would focus on moving a few pre-existing NPCs and also create my own. First, I started with a Stormwind Guard and designed a path for her. Second, a random Stormwind citizen was next: again all I did was design a path for her to follow. Finally, I invented a new NPCs in Goldshire and set her up on a long-winded journey to Northshire and back.

But how does one actually get NPCs moving in Azeroth? As I'm using AzerothCore, I started by exploring its feature set, specifically the game master commands involved and the database tables that store all the information.

Footage

Floating waypoint.

Behind the scenes, AzerothCore uses the concept of waypoints and paths. A waypoint is simply a location in Azeroth in the form of a 3D vector: X, Y, Z, and orientation. A path is, as you might have guessed, a collection of waypoints that form a path to be followed by an NPC. Easy enough so far.

However there's a part of the whole process that's actually quite difficult and really shows you how hard game design is, and that's designing routes for NPCs that make logical sense, feel natural, and also fit in with the environment around them.

But let's go straight to looking at the how behind making the waypoints work, as that content is reserved for Patreon members.

GM Commands

Footage

GM moving around placing waypoints.

The waypoints themselves can be placed by using an in-game game master command whilst standing in the right location (your X, Y, and Z) and facing the right direction (your orientation.) These commands update the database and a few tables behind the scenes.

Footage

GM moving around placing waypoints, with overlay of table names

There's a table for containing the waypoints - waypoint_data (not waypoints) - but there isn't one for the path information as it's embedded directly into the same table as the waypoint itself. For attaching the waypoint or the path to the NPC, there's also only a few simple tables to be concerned with and once updated, the NPC will begin following the waypoints and acting accordingly.

Footage

GM moving around placing waypoints, with overlay of GM commands.

The command for adding a new waypoint is:

.wp add <id>

The <id> is the waypoint ID, and this stays the same for the path you're creating.

You finalise the whole task by using another series of game master commands to reload and load the waypoints, applying them to the NPC, which results in them moving along the path you've designed:

Footage

GM moving around placing waypoints, with overlay of GM commands.

.wp reload <id>
.wp load <id>

With the .wp load command, you must have a creature selected in-game to apply the waypoint ID to. If all is well and good, your NPC will literally start making their way to the first waypoint, then the second, the third, and so on. Completely automatically without restarting the core or the client. Magic!

The NPC moving along the path isn't the only result you get from those game master commands, however. As we know, the database is also updated live to make the changes persistent, and that's where we encounter our first technical difficulty: how do we share those updates with others?

Hello Daisy

Footage

Daisy repo.

Now I just want to talk about my set of tools called Daisy real quick.

Daisy is an open-source, custom set of tools I wrote for interacting with the AzerothCore database via YAML. It's early days right now, but it already allows me to write a small amount of YAML in return for thousands of lines of readable, maintainable SQL.

This means instead of writing a lot of complex, repetitive SQL, which is error prone and annoying, you can instead write far, far less YAML and get highly readable, maintainable (but admittedly verbose) SQL. This is handy on a lot of levels, but that's not the focus of this piece, so I'll just leave that there for now.

There are two tools in the Daisy suite that we're interested in today:

  • daisy.py for converting YAML (Packs) to SQL
  • db2yaml.py for converting live database table entries into YAML, which can then be converted back to SQL via a Daisy Pack

The SQL

Footage

That Constable Guy from Stormwind walking around in circles on a mountain.

OK back to the core of this discussion.

I will admit that I do like to make things a bit more difficult for my self because I want everything and anything I produce to be reproducable by others. This means that however I solve the problem of making NPCs follow paths so they appear more natural, I want it to be done in a way that lets others use the results for their own entertainment. This raises the bar a bit, and that's why I wrote the db2yaml.py tool.

Given the waypoint commands update the database behind the scenes, how do we then make that reproducible for others? SQL. We need to extract those changes as SQL so that others can then inject that SQL into their own AzerothCore database, allowing them to replicate the work I've done. This is a sort of "AzerothCore-as-Code" like solution for the database.

As a side note, if you knew all of the X/Y/Z/orientation coordinates of every waypoint ahead of time, you could write the SQL first, but that's really time consuming. Instead what I do is leverage the ID of the waypoints in the database and use a custom made Python tool to extract the rows from the table (that's db2yaml.py). This allows me to use a template to produce the SQL, which in turn allows others to then use that SQL to replicate everything I've done.

For example, if you used the .wp add 1234 command twice and then used the db2yaml.py tool, you'd get the following YAML:

Footage

Overlay of this YAML.

waypoint_data:
  - id: 1234
    point: 1
    position_x: -9467.28
    position_y: 54.4442
    position_z: 56.8735
    orientation: 0.0
    delay: 160000 # 3m-ish
    move_type: 0
    action: 0
    action_chance: 100
    wpguid: 0

  - id: 1234
    point: 2
    position_x: -9454.5
    position_y: 58.102
    position_z: 56.0585
    orientation: 0.0
    delay: 0
    move_type: 0
    action: 0
    action_chance: 100
    wpguid: 0

Now you can embed this YAML into a Daisy Pack and then use daisy.py to produce a tonne of high quality SQL you can import into AzerothCore, across any number of instances, over and over. The SQL looks like this - again, it's very verbose and this is just one entry:

Footage

Scrolling overlay of this SQL.

-- START waypoint_data
SET
@id := 1234,
@point := 1,
@position_x := -9467.28,
@position_y := 54.4442,
@position_z := 56.8735,
@orientation := 0.0,
@delay := 160000,
@move_type := 0,
@action := 0,
@action_chance := 100,
@wpguid := 0;

DELETE FROM waypoint_data WHERE
  id=@id AND
  point=@point
;

INSERT INTO waypoint_data (
  `id`,
  `point`,
  `position_x`,
  `position_y`,
  `position_z`,
  `orientation`,
  `delay`,
  `move_type`,
  `action`,
  `action_chance`,
  `wpguid`
)
VALUES (
  @id,
  @point,
  @position_x,
  @position_y,
  @position_z,
  @orientation,
  @delay,
  @move_type,
  @action,
  @action_chance,
  @wpguid
);
-- EOF waypoint_data

Yeah if you're watching this on a mobile, you're going to have to squint. Sorry.

Yes it's very verbose, but it's also highly readable, portable, maintainable, and can be used as documentation for the table itself and your work.

By the way, I'll talk about the action and delay columns in the extended video. See the description for details.

NPC Updates

Footage

Floating waypoint.

Now those waypoints on their own don't actually do anything. They're literally just 3D vectors with some additional meta data attached. You need to update the NPC(s) and tell them to walk or run to the first waypoint. That's when they'll continue along the path you've designed. Luckily this is just a few database updates and those can be done with Daisy using an update statement.

Footage

Overlay: table names.

You need to update the creature and creature_addon tables. It's best to update these tables even if the values are already set to what you expect, that way you create a complete, idempotent solution.

First you need to update the creature table, which contains the live instance of the creature in the world (which takes its template from creature_template):

FYI, this is a Daisy update statement. It was taken from an existing working code base.

Footage

Overlay: YAML

update:
  # Stormwind Guard 01
  - table: creature
    columns:
      currentwaypoint: *SW_GUARD_01_GUID_WP
      movementtype: 2 # waypoint
    where:
      guid:
        - *SW_GUARD_01_GUID

This can be translated to SQL as:

Footage

Overlay: SQL

UPDATE creature SET currentwaypoint=X and movementtype=2 WHERE guid=Y;

Where X and Y are valid values for a valid row. The advantage of the YAML, however, is readability and YAML Anchors, not to mention portability and the ability to easily generate documentation from the YAML.

Footage

NPC moving running or something. Overlay: Table and columns names.

Anyway! In the YAML I'm doing the same thing by updating the currentwaypoint and movementtype columns. I set the currentwaypoint to the value of the first waypoint in the path (with a position of 1.) I change the movementtype to 2 which means "path". Without this latter change, the NPC will not move at all. By the way, 1 is "random", which is nice for having the NPC just move about in a small area, which you can also define.

Finally I update the creature_addon table like so:

update:
  - table: creature_addon
    columns:
      path_id: *SW_GUARD_01_GUID_WP
      where:
        guid:
          - *SW_GUARD_01_GUID

I'm setting the path_id to the same value at the YAML Anchor. I'm updating this field based on the guid column being equal to the value at the SW_GUARD_01_GUID Anchor (120692 in this case.)

Close

Footage

NPCs stood still. Timelapse?

OK, so making an NPC move around in an organic manner, with a few personality traits like saying things to other NPCs, whilst pausing and eventually making their way back to where they started is... easy? Depending on what you want to do, you have to design a well thought out route for the NPC and then use delays, actions, and more, to ensure they appear natural and effortlessly fit into their environment.

But overall it's not really easy. There's a lot to consider when moving just a single NPC, and I don't mean the design of it. There's all the tables that need to be updated too. I've not actually explored all of the features yet. I really want to play around with having an NPC's waypoint script trigger another NPC to do something or even just cast a spell!

That's the thing I love about this engine: it gives you everything you need to create so much, but in a weird and frustrating way it doesn't give you all the documentation you need, forcing you to explore and learn. I guess I get a kick out of that?

Next steps

Footage

GM dancing somewhere silly.

I'm going to start working on moving most of the NPCs in Stormwind as well as adding more NPCs to make the city feel more alive. I'll then do the same for Elwynn Forest and some surrounding human areas. Once complete, I'm going to implement a day/night cycle to the same areas, which I believe will be a literal game changer.

Until next time.