0
\$\begingroup\$

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?

\$\endgroup\$
0
\$\begingroup\$

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.)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.