Creating a schedule: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
(Redirected page to Schedule)
 
(8 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{npc tut}}
#redirect [[schedule]]
 
A schedule is a list of [[task]]s for an NPC to perform. A new schedule is chosen '''only''' when there is no active one; this might be because the NPC has only just spawned, because it has completed a schedule since it last [[NPCThink()|thought]], or because the schedule it was running previously encountered an interrupt [[condition]].
 
== Creating a new schedule ==
 
=== Enumeration ===
Schedules are defined in the NPC's [[AI_BEGIN_CUSTOM_NPC]] [[macro]] block. Before you start to do that however, you will need to add a new item to the class' enum:
 
enum
{
      SCHED_DODGE_ENEMY_FIRE = LAST_SHARED_SCHEDULE,
};
 
{{todo|Elsewhere <code>BaseClass::NEXT_SCHEDULE</code> is used, not <code>LAST_SHARED_SCHEDULE</code>. What's the difference?}}
 
=== Definition ===
Once the schedule is enumerated, we can start defining it within <code>AI_BEGIN_CUSTOM_NPC</code>. All schedules use the same structure:
 
DEFINE_SCHEDULE
(
SCHED_DODGE_ENEMY_FIRE,
" Tasks"
" TASK_FIND_DODGE_DIRECTION 3"
" TASK_JUMP 0"
""
" Interrupts"
      "              COND_LIGHT_DAMAGE"
);
 
{{warning|The first character of each string (except for the 'gap') must be a space or a tab. Your schedule will otherwise be invalid!}}
 
As you can see, there are two parts to the definition:
 
#'''<code>Tasks</code>''' is simply the list of sequential [[task]]s an NPC must perform in order to complete the schedule.
#*Every task requires a numeric value to be passed with it! If the task doesn't actually make use of one, just pass <code>0</code>.
#'''<code>Interrupts</code>''' is a list of [[conditions]] that will cause the schedule to be abandoned, and a new one chosen, if any are ever detected.
 
In the example schedule given above, the NPC will attempt to find a suitable direction to dodge in (checking in a maximum of three directions, judging by the parameter) before using the output of that task, stored somewhere in the class, to perform the movement itself. But if it encounters <code>COND_LIGHT_DAMAGE</code> (any damage greater than zero) during the process, it will abandon the schedule and select another.
 
The behavioural code that decides what the NPC actually ''does'' is defined in the component [[task]]s.
 
== SelectSchedule() ==
 
<code>SelectSchedule()</code> is called whenever an NPC finds itself without a schedule, and contains the logic that decides which should be selected to fill the gap. The NPC's current [[state]] and [[condition]]s usually play a large part in the decision.
 
A schedule is selected if the function returns it's name - e.g. <code>return SCHED_DODGE_ENEMY_FIRE;</code>.
 
{{tip|If you expect to write a lot of schedule selection logic, you may find it useful to split it into sub-functions of your own making. <code>CAI_BaseNPC</code> for instance has <code>SelectIdleSchedule()</code>, <code>SelectCombatSchedule()</code>, etc. that are called depending on the NPC's state.}}
 
=== Useful functions ===
 
;<code>HasCondition([[int]] condition)</code>
:True if the specified [[condition]] has been set for the current think. Of course, you'd use your enumerated names instead of passing an integer directly!
;<code>GetState()</code>
:Returns the NPC's state. You can also access m_NPCState directly, but GetState() is read-only and therefore safer.
;<code>return BaseClass<nowiki>::</nowiki>SelectSchedule()</code>
:There are very few situations where you won't want to call the base class' function. Do so at the ''end'' of your function, since a return obviously takes precedence over any code that comes after it.
 
== TranslateSchedule() ==
 
<code>TranslateSchedule()</code> is called immediately after <code>SelectSchedule()</code>. It is designed to allow child classes to replace their parent's or parents' schedules with those of their own without having to duplicate selection logic.
 
int CNPC_Custom::TranslateSchedule( int scheduleType )
{
switch( scheduleType )
{
case SCHED_IDLE_WALK:
{
return SCHED_CUSTOM_IDLE_WALK;
break;
}
}
return BaseClass::TranslateSchedule( scheduleType );
}
{{navbar-last|Creating an interaction|Creating an NPC}}

Latest revision as of 03:03, 16 September 2011

Redirect to: