Task: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
No edit summary
m (Added see also)
 
(8 intermediate revisions by 3 users not shown)
Line 1: Line 1:
A '''task''' is a logical step in a [[schedule]], it can be seen as a sequential set of steps the NPC must take in order to accomplish a schedule.
{{npc tut}}
{{Seealso|For community tasks, see [[Valve Developer Community:Tasks]]}}


A '''task''' becomes latent if TaskComplete() or TaskFail() isn't called. Meaning the schedule will not procede to the next '''task''' until the current one has been taken care of.
A '''Task''' is an action that an NPC can perform. [[Schedule]]s will run a list of tasks. Keep tasks as atomic as possible; don't squeeze two distinct actions into the same one.


If a '''task''' fails the schedule will fail and exit. It will NOT proceed to the next '''task'''.
== Creating a task ==


Custom tasks are added by first declaring a new enum value.


<source lang=cpp>
enum
{
TASK_JUMP = LAST_SHARED_TASK,
TASK_FIND_DODGE_DIRECTION,
LAST_MY_NPC_TASK,
};
</source>
After that, the task itself should be declared like this:
<source lang=cpp>
AI_BEGIN_CUSTOM_NPC( npc_custom, CNPC_Custom )
DECLARE_TASK( TASK_FIND_DODGE_DIRECTION )
AI_END_CUSTOM_NPC()
</source>
Then you add the tasks in your custom schedule in the order you want them to execute. See [[Schedule]] for more details on the following code:
<source lang=cpp>
AI_BEGIN_CUSTOM_NPC( npc_custom, CNPC_Custom )
DEFINE_SCHEDULE
(
SCHED_DODGE_ENEMY_FIRE,
" Tasks"
" TASK_FIND_DODGE_DIRECTION 3"
" TASK_JUMP 0"
""
" Interrupts"
      " COND_LIGHT_DAMAGE"
)
AI_END_CUSTOM_NPC()
</source>
== Task logic ==
Now that everything is set up it's finally time ''to write some actual AI code''.
* Tasks are initiated from <code>StartTask(Task_t *pTask)</code>, which should take the form of a <code>[[W:Switch statement#Examples|switch]]</code> statement that evaluates <code>pTask->iTask</code>. {{note|Remember to have a <code>default</code> case that falls back on <code>BaseClass::StartTask()</code>.}}
* Each task has an associated [[float]] value, <code>pTask->flTaskData</code>, which can be used to change its outcome.
* When the current task is complete, call <code>TaskComplete()</code>. The schedule will move on to the next task.
* If the current task has failed, call <code>TaskFail()</code> with an error message. A new schedule will be selected.
=== Example ===
This code makes the NPC play the <code>ACT_MP_JUMP</code> [[activity]] endlessly.


'''''ADDING A TASK TO A NPC CLASS'''''
<source lang=cpp>
*Add the task to an enum declaration in your class :
void CNewNPC::StartTask( const Task_t *pTask )
<pre>
enum
{
{
    TASK_ONE = BaseClass::NEXT_SCHEDULE,
switch (pTask->iTask)
    TASK_TWO,
{
    TASK_THREE,
case TASK_MYCUSTOMTASK:
if (FindGestureLayer(ACT_MP_JUMP) == -1)
AddGesture(ACT_MP_JUMP);
TaskComplete();
break;
 
default:
BaseClass::StartTask( pTask );
}
}
}
</pre>
</source>
 
=== Navigation ===
 
{{todo}}
 
=== Animation ===
 
* [[Animating a model]]


=== Combat ===


*Declare the task below the AI_BEGIN_CUSTOM_NPC(...) using the DECLARE_TASK(...) macro.
{{todo}}


*Add your case to the StartTask()
=== Speech ===


*Add your case to RunTask() ( needed if TaskComplete() not called in StartTask() )
* [[Response System]]
* [[Speech semaphore]]
* [[Choreography creation]]


== See also ==


* [[Shared tasks]]


{{navbar|Creating a schedule|Creating an NPC|Giving an NPC Memory}}
[[Category:AI Programming]]
[[Category:AI Programming]]

Latest revision as of 10:24, 9 May 2023

See also:  For community tasks, see Valve Developer Community:Tasks

A Task is an action that an NPC can perform. Schedules will run a list of tasks. Keep tasks as atomic as possible; don't squeeze two distinct actions into the same one.

Creating a task

Custom tasks are added by first declaring a new enum value.

enum 
{
	TASK_JUMP = LAST_SHARED_TASK,
	TASK_FIND_DODGE_DIRECTION, 
	LAST_MY_NPC_TASK,
};

After that, the task itself should be declared like this:

AI_BEGIN_CUSTOM_NPC( npc_custom, CNPC_Custom )
	DECLARE_TASK( TASK_FIND_DODGE_DIRECTION )
AI_END_CUSTOM_NPC()

Then you add the tasks in your custom schedule in the order you want them to execute. See Schedule for more details on the following code:

AI_BEGIN_CUSTOM_NPC( npc_custom, CNPC_Custom )
	DEFINE_SCHEDULE
	(
		SCHED_DODGE_ENEMY_FIRE,

		"	Tasks"
		"		TASK_FIND_DODGE_DIRECTION	3"
		"		TASK_JUMP	0"
		""
		"	Interrupts"
       	"		COND_LIGHT_DAMAGE"
	)
AI_END_CUSTOM_NPC()

Task logic

Now that everything is set up it's finally time to write some actual AI code.

  • Tasks are initiated from StartTask(Task_t *pTask), which should take the form of a switch statement that evaluates pTask->iTask.
    Note.pngNote:Remember to have a default case that falls back on BaseClass::StartTask().
  • Each task has an associated float value, pTask->flTaskData, which can be used to change its outcome.
  • When the current task is complete, call TaskComplete(). The schedule will move on to the next task.
  • If the current task has failed, call TaskFail() with an error message. A new schedule will be selected.

Example

This code makes the NPC play the ACT_MP_JUMP activity endlessly.

void CNewNPC::StartTask( const Task_t *pTask )
{
	switch (pTask->iTask)
	{
	case TASK_MYCUSTOMTASK:
		if (FindGestureLayer(ACT_MP_JUMP) == -1)
			AddGesture(ACT_MP_JUMP);
		TaskComplete();
		break;

	default:
		BaseClass::StartTask( pTask );
	}
}

Navigation

[Todo]

Animation

Combat

[Todo]

Speech

See also