# Using Lua to define NPC behaviour

I'm working on a RPG in C using Lua for event scripting like NPC behavior. I ran into a design problem.

I have created Lua threads in the C API for each game object which can be a NPC. So this:

function objinteract(o)
if o.id == 1 then
textbox("Hello I'm ",o.name,"!");
yield();
end
end


Is what happens when the player talks to the NPC. But I'm not sure on how to implement walking/wandering.

I could do it like this:

function update(o)
if o.id == 0 then
movewest(o.id,3); -- move NPC three tiles west.
yield();
movenorth(o.id,3); -- move NPC three tiles north.
yield();
moveeast(o.id,3); -- move NPC three tiles east.
yield();
movesouth(o.id,3); -- move NPC three tiles south.
yield();
end
end


Though this is a good solution, if the NPC were to be talked to, the flow of the script would be lost because I'm using one thread for each NPC. Any solutions for this?

Instead of using a fixed path, you could define four waypoints {0,0, -3,0, -3,3, 0,3} and iterate through them. This means you'd need move_to_point instead of movewest.

Maintain the current destination and if interrupted, you resume travelling to that destination once you want to wander again. Additionally, this system will scale to more complex travelling behaviours.

I always like to think of AI divided into two: brain and body. The brain is the behaviours deciding what we should do and the body is the how. Both of them revise their decisions regularly (but not necessarily every frame).

Example: the brain decides "go to wander point A". The body determines the path and begins executing it. The player interacts with the NPC and the brain decides the player is most important so it switches to conversation behaviour. The body stands there and starts gesturing. When the conversation completes the brain re-selects the next waypoint.

So in your example, you might choose the action and then perform one update worth of that action:

function update(o)
if o.id == 0 then
-- brain:
local action = determine_action(o.id)
-- body:
if action.talk then
talk(o.id)
elseif action.walk then
-- might not get all the way to dest
move_towards_dest(o.id, action.dest)
end
yield();
end
end


Your talk could also yield which forces the conversation to continue and prevents interruption. (If I remember lua coroutines correctly.)