Creating NPCs

From Pragma
Jump to: navigation, search


Schedules

NPC behavior should be handled mostly through schedules. A schedule represents the root-node of a collection of tasks, which build a behavior tree.
You can add new tasks to the schedule, which will be executed one by one in order. Each task can have multiple sub-tasks.

Tasks

A task is an atomic activity a NPC can perform. Complex behavior can be created by binding tasks together through a schedule.
You can create custom tasks in Lua, however there are also some pre-defined hardcoded tasks available.

Parameters

Some tasks can have additional parameters assigned to them, to change the task behavior dynamically. There are two ways of doing so:

Task Parameters

If you want a task to always use a specific parameter value, you can use one of the AIBehaviorTask:SetTask*-functions.

Schedule Parameters

You can use AIBehaviorTask:SetScheduleParameter to make a task-parameter point to a schedule parameter instead. This is useful if you have multiple tasks using the same parameter.

Example:

local sched = ai.create_schedule()
sched:SetParameterEntity(0,ents.get_players()[1]) -- Schedule parameter 0

local taskMove = ai.create_task(ai.TASK_MOVE_TO_TARGET)
taskMove:SetScheduleParameter(0,0) -- Task parameter 0 will point to schedule parameter 0
sched:AddTask(taskMove)

local taskActivity = ai.create_task(ai.TASK_PLAY_ACTIVITY)
taskActivity:SetParameterInt(0,ACT_MELEE_ATTACK1)
taskActivity:SetScheduleParameter(1,0) -- Task parameter 1 will point to schedule parameter 0
sched:AddTask(taskActivity)

This schedule will make the NPC move to player 1, and play an attack animation while facing player 1.

Relationships and factions

Animations

Animation Events

Animation events can be used to trigger certain behavior at a precise moment during a specific animation.
You could use them to make your NPC deal damage when playing an attack animation, make your NPC jump at a specific frame, play sounds, etc.
There are two ways of creating animation events:

Model-based

You can integrate animation events directly into the model. To do so, you can use the $event command when compiling the model.
These events cannot be changed after the model has been compiled, however this way has the advantage that the events are not dependent on the entity.
All model-based events will invoke the HandleAnimationEvent entity hook during runtime (See below).

Entity-based

You can also dynamically add animation events to certain entities during runtime. To do so, you can call Entity:AddAnimationEvent.
Changing an entity's model clears all existing dynamic animation events, so make sure to add them after the model has been set. The best way to do this is the OnModelChanged entity hook:

function NPCZombie:OnModelChanged(mdl)
	if(mdl == nil) then return end
	self:AddAnimationEvent("melee",5,function()
		self:DealMeleeDamage()
	end)
	self:AddAnimationEvent("jump",24,AE_EMITSOUND,{"npc_raptor.tense"})
end

Animation events can be added clientside or serverside depending on your needs. You can either supply a function directly, which will be called whenever the event is triggered, or use an AnimationEvent id.
You can also use custom ids which will invoke the HandleAnimationEvent entity hook:

local AE_MELEE_ATTACK1 = 5001
function NPCRaptor:HandleAnimationEvent(evId,args)
	if(evId == AE_MELEE_ATTACK1) then
		self:DealMeleeDamage()
	else return false end -- Return false for animation events we don't use / care about
	return true -- Return true to disable default behavior
end

Engine Tasks

There are several pre-defined tasks which you can use for generic behavior. These are hardcoded and cannot be modified (Aside from parameters) or derived from:

ai.TASK_MOVE_TO_TARGET

The NPC will move to the specified target. The task will succeed once the NPC has reached the specified distance to the target. If the target is unreachable, the task will fail.

Parameters

  1. / / target: The target the NPC is supposed to move to (Optional.). If no target is specified, the NPC will move to its current primary target.
  2. distance: The NPC will move until it has reached this distance to the target. (Optional.). If no distance is specified, the NPC will move as close to the target as possible. If no target is specified, you can specify the distance via parameter 0 instead.
  3. activity: The move activity the NPC should use while moving (Optional.)

ai.TASK_PLAY_ANIMATION

The NPC will play the specified animation. The task will succeed once the animation has finished. If the animation has been interrupted, the task will fail.

Parameters

  1. / animation {required}: The animation to play.
  2. / / faceTarget: The target the NPC should be facing while the animation is playing. If the parameter is set to true, the NPC will face its primary target.

ai.TASK_PLAY_ACTIVITY

The NPC will play the specified activity. The task will succeed once the animation has finished. If the animation has been interrupted, the task will fail.

Parameters

  1. {required}: The activity to play.
  2. / / faceTarget: The target the NPC should be facing while the animation is playing. If the parameter is set to true, the NPC will face its primary target.

ai.TASK_MOVE_RANDOM

The NPC will move in a random direction. The task will succeed if the NPC has reached the goal. If the goal is unreachable, the task will fail.

Parameters

  1. distance: The distance the NPC should move.
  2. activity: The move activity the NPC should use while moving (Optional.)

ai.TASK_PLAY_SOUND

This task will emit a sound from the NPC and immediately return success, regardless of whether the sound could be played or not.

Parameters

  1. target {required}: The sound which the task should play. The sound will be emitted from the NPC.
  2. gain: The volume of the sound. (Optional.)
  3. pitch: The pitch of the sound (Optional.)

Custom Tasks

Notes: debugrenderer.draw_cone