Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
npc_behaviour [2017/01/04 12:37] – created zdimensiontrs:npc_behaviour [2017/11/17 11:19] (current) stohrendorf
Line 1: Line 1:
-{{anchor:non-player-character-behaviour}}+{{indexmenu_n>6}} 
 ====== Non-Player Character Behaviour ====== ====== Non-Player Character Behaviour ======
  
Line 10: Line 11:
 Lara is unique player character, so she has a large set of both //control// and //collisional// routines, which are switched depending on her current //state//. Lara is unique player character, so she has a large set of both //control// and //collisional// routines, which are switched depending on her current //state//.
  
-**Note** +<note
->  +In original Tomb Raider source code, notation for collisional and state routines follows two different schemes. For Lara, collisional and control routines are called ''%%lara_col_STATE%%'' and ''%%lara_as_STATE%%'', where ''%%STATE%%'' is the name of the state, like //walk, run, reach//, and so on. 
-In original Tomb Raider source code, notation for collisional and state routines follows two different schemes. For Lara, collisional and control routines are called ''%%lara_col_STATE%%'' and ''%%lara_as_STATE%%'', where ''%%STATE%%'' is the name of the state, like //walk, run, reach//, and so on. + 
- +For other entity types, there is more generic scheme: collisional routines are called ''%%NAMECollision%%'', where ''%%NAME%%'' is entity type name, like //CreatureCollision//, and control routines are called ''%%NAMEControl%%'', where ''%%NAME%%'' is entity type name. E.g., bear will have a pair of routines linked to it, named //CreatureCollision// and //BearControl//. 
-For other entity types, there is more generic scheme: collisional routines are called ''%%NAMECollision%%'', where ''%%NAME%%'' is entity type name, like //CreatureCollision//, and control routines are called ''%%NAMEControl%%'', where ''%%NAME%%'' is entity type name. E.g., bear will have a pair of routines linked to it, named //CreatureCollision// and //BearControl//.+</note>
  
 ===== Entity Scripting ===== ===== Entity Scripting =====
Line 20: Line 21:
 Despite the existence of //script files//, here is no any scripting for entity behaviour, like in most contemporary games. This hardcoding makes it difficult to port the earlier Tomb Raider scenarios to the engines of the later games, which could be desirable with their improved hardware support. While textures, models, and animations can be ported, behaviour cannot be. Despite the existence of //script files//, here is no any scripting for entity behaviour, like in most contemporary games. This hardcoding makes it difficult to port the earlier Tomb Raider scenarios to the engines of the later games, which could be desirable with their improved hardware support. While textures, models, and animations can be ported, behaviour cannot be.
  
-However, there is a small change in TR4 and TR5 which indicates that specific entity behaviour can be altered — it’s called //OCB//. It was briefly described in [[meshes_models#object-code-bit|this section]]. OCB is a special value defined for each entity instance, based on which entity can switch the way it acts (most prominent examples are flame emitters, which change their size and emit direction based on OCB, and teeth spikes, which change their orientation in space).+However, there is a small change in TR4 and TR5 which indicates that specific entity behaviour can be altered — it’s called //OCB//. It was briefly described in [[trs:meshes_models#object-code-bit|this section]]. OCB is a special value defined for each entity instance, based on which entity can switch the way it acts (most prominent examples are flame emitters, which change their size and emit direction based on OCB, and teeth spikes, which change their orientation in space).
  
 Sometimes OCB is interpreted as a “packed” field with several values incorporated — like teeth spike OCB contain information about their horizontal and vertical orientation, and also about their “physical” behaviour (stick out constantly, pop-retract in looped manner, or pop-retract just once). Sometimes OCB is interpreted as a “packed” field with several values incorporated — like teeth spike OCB contain information about their horizontal and vertical orientation, and also about their “physical” behaviour (stick out constantly, pop-retract in looped manner, or pop-retract just once).
  
-**Tip** +<note tip
->  +For list of valid entity OCBs in TR4, you may refer to TRLE User’s Manual, although it was written in a big rush, and thus it lacks many existing OCBs for many entities. There are also fan-made OCB lists which are much more comprehensive. 
-For list of valid entity OCBs in TR4, you may refer to TRLE User’s Manual, although it was written in a big rush, and thus it lacks many existing OCBs for many entities. There are also fan-made OCB lists which are much more comprehensive. + 
- +As for TR5, no proper OCB list exists for its entity types, so it may be considered a big unknown. 
-As for TR5, no proper OCB list exists for its entity types, so it may be considered a big unknown.+</note>
  
 However, OCB can’t be seriously called “scripting”, as it also operates with pre-defined hardcoded behaviour. However, OCB can’t be seriously called “scripting”, as it also operates with pre-defined hardcoded behaviour.
  
-**Note** +<note
->  +Recent patches for TR4 game engine (used to play custom levels), like //TREP// and //TRNG//, feature some kind of basic scripting functionality. However, there’s still no sign of //real scripting language// in them, and such scripting is basically specifying pre-defined variables to alter entity behaviour, just like OCB does. 
-Recent patches for TR4 game engine (used to play custom levels), like //TREP// and //TRNG//, feature some kind of basic scripting functionality. However, there’s still no sign of //real scripting language// in them, and such scripting is basically specifying pre-defined variables to alter entity behaviour, just like OCB does.+</note>
  
 ===== Pathfinding ===== ===== Pathfinding =====
Line 43: Line 44:
  
 TR engines use three different structures to assist pathfinding. These are //boxes, overlaps, and zones//. Most sectors point to some //box//, the main exceptions being horizontal-portal sectors. Several neighbour sectors may point to the same box. A box is a horizontal rectangle, with corners and height specified; each box also has a pointer into the list of //overlaps//. Each segment in that list is the list of accessible neighbouring boxes for some box; the NPCs apparently select from this list to decide where to go next. TR engines use three different structures to assist pathfinding. These are //boxes, overlaps, and zones//. Most sectors point to some //box//, the main exceptions being horizontal-portal sectors. Several neighbour sectors may point to the same box. A box is a horizontal rectangle, with corners and height specified; each box also has a pointer into the list of //overlaps//. Each segment in that list is the list of accessible neighbouring boxes for some box; the NPCs apparently select from this list to decide where to go next.
 +Several neighbour sectors may point to the same box. Each box also has a pointer into the list of //overlaps//. Each segment in that list is the list of accessible neighbouring boxes for some box; the NPCs apparently select from this list to decide where to go next.
  
 This selection is done with the help of the //zones//. These structures of 6 (TR1) or 10 (TR2-TR5) ''%%int16_t%%''s that act as zone IDs; their overall indexing is the same as the boxes, meaning that each box will have an associated set of zone IDs. An NPC will select one of this set to use, and will prefer to go only into the overlaps-list boxes that have the same zone value as the box it is currently in. For example, one can create guard paths by making chains of zone-ID-sharing boxes, with their overlaps pointing to the next boxes in those chains. This selection is done with the help of the //zones//. These structures of 6 (TR1) or 10 (TR2-TR5) ''%%int16_t%%''s that act as zone IDs; their overall indexing is the same as the boxes, meaning that each box will have an associated set of zone IDs. An NPC will select one of this set to use, and will prefer to go only into the overlaps-list boxes that have the same zone value as the box it is currently in. For example, one can create guard paths by making chains of zone-ID-sharing boxes, with their overlaps pointing to the next boxes in those chains.
Line 48: Line 50:
 {{anchor:Boxes}} {{anchor:Boxes}}
 === Boxes === === Boxes ===
 +
 +A box is a horizontal rectangle, with corners and height specified.
 +
 +This is presumably the way //TRLE// creates boxes for each level:
 +
 +  * For each sector, extend one axis until a height difference is reached. 
 +  * Then extend this row (or column) perpendicular until another height difference is reached. This is a rectangle with the same height and it //defines a box//.
 +  * Do the same with the other axis first, and you get another box.
 +  * Repeat this process for every sector, maybe extending into neighbor rooms through the portals.
 +  * Make sure that there are no any duplicate boxes.
  
 There are two variations of box structure — one for TR1 and another for TR2 and any other game version. There are two variations of box structure — one for TR1 and another for TR2 and any other game version.
Line 60: Line 72:
     uint32_t Xmax;     uint32_t Xmax;
      int16_t TrueFloor;     // Height value in global units      int16_t TrueFloor;     // Height value in global units
-    uint16_t OverlapIndex;  // Bits 0-14 is the index into Overlaps[]. Bit 15 is used to terminate overlap list iteration for a single box.+    uint16_t OverlapIndex;  // Bits 0-13 is the index into Overlaps[]. 
 }; };
 </code> </code>
Line 72: Line 84:
     uint8_t Xmax;     uint8_t Xmax;
     int16_t TrueFloor;     // Height value in global units     int16_t TrueFloor;     // Height value in global units
-    int16_t OverlapIndex;  // Index into Overlaps[] (same as tr_box?)+    int16_t OverlapIndex;  // Bits 0-13 is the index into Overlaps[]
 }; };
 </code> </code>
-In ''%%OverlapIndex%%'', the high bit is sometimes set; this occurs in front of swinging doors and the like.+The ''%%OverlapIndex%%'' contains a block mask for path finding by enemies in two highest bits: Bit 15 (blockable) and bit 14 (blocked). The first one marks it as unpassable by large enemieslike the [[:items:details:tr1:trex|T-Rex (ID 18)]], the [[:items:details:tr1:mutant|Mutant (ID 20)]] or the [[:items:details:tr1:centaur|Centaur (ID 23)]] and is always set behind doors. The second one marks it unpassable for other enemies and is set for movable blocks (if blockable bit is set), for closed doors and for some flip maps (set at start).
  
 === Overlaps === === Overlaps ===
Line 81: Line 93:
 This is a set of lists of neighbouring boxes for each box, each member being a ''%%uint16_t%%''. NPCs apparently use this list to decide where to go next. This is a set of lists of neighbouring boxes for each box, each member being a ''%%uint16_t%%''. NPCs apparently use this list to decide where to go next.
  
-Overlaps must be parsed in serial manner, as with //FloorData// functions: the highest bit (''%%0x8000%%''being set marks the end of each list.+Overlaps must be parsed in serial manner, as with //FloorData// functions: the highest bit (''%%0x8000%%''is used to terminate overlap list iteration for a single box.
  
 === Zones === === Zones ===
Line 118: Line 130:
 </code> </code>
 The ground zones are for NPCs that travel on the ground, while the fly zones are for flying or swimming NPCs. The ground zones are for NPCs that travel on the ground, while the fly zones are for flying or swimming NPCs.
 +
 +==== Moods ====
 +
 +Each mobile NPC in TR may be in a certain //mood//. A mood defines the way creature behaves. The way NPCs change their mood is based on several conditions, mainly on certain enemy implementation.
 +
 +Most obvious example of mood change is wolf, which can sleep, walk slowly, chase Lara and flee. This change of mood is based on Lara’s position — if Lara is found in any of the box that NPC can reach, mood is changed to //chase//, which means that //pathfinding algorithm// is in effect (see further).
 +
 +There are another examples of mood changes. In TR3, monkeys are calm unless Lara shoots them. However, this is not the case for level 2 (Temple Ruins), where monkeys are hardcoded to chase Lara on start-up.
 +
 +{{anchor:pathfinding-algorithm}}
 +==== Pathfinding algorithm ====
 +
 +For most of TR NPCs, when they are in //chase// mood, pathfinding (and eventual attack) may be broken down to several steps:
 +
 +  * Collect all boxes that are in the same zone as the NPC.
 +  * Find a path using //[[https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm|Dijkstra algorithm]]// with respect to the NPC abilities and a //maximum depth of 5 boxes//.
 +  * Calculate a random point in the intersection of the current box and the next box on the waypoint.
 +  * If NPC is finally shortly at arriving at Lara, try to predict the direction in which Lara is running (with different lookahead distances for different types of NPCs).
 +  * Perform an attack based on aforementioned calculations.
  
 {{anchor:ai-objects}} {{anchor:ai-objects}}
 ===== AI Objects ===== ===== AI Objects =====
  
-Since TR3, in addition to pathfinding data structures, there are now special //AI objects//, which are used in a waypoint-like manner, defining specific action, like wandering between two points, guarding specific point or running to specific place in case Lara is around. For example, MP Guards in TR3’s “Area 51” may patrol specific area when they are limited by special //AI_PATROL// object.+Since TR3, in addition to pathfinding data structures, there are now special //AI objects//, which are used in a node-like manner, defining specific action, like wandering between two points, guarding specific point or running to specific place in case Lara is around. For example, MP Guards in TR3’s “Area 51” may patrol specific area when they are limited by special //AI_PATROL// object.
  
-**Note** +<note
->  +Not every NPC is “taught” to work with AI objects — usually, only “smart” human enemies or friends can take advantage of them. Analyzing level files with utilities like //FexInspect// may help understanding particular AI object setup and learn which NPCs can actually work with them. 
-Not every NPC is “taught” to work with AI objects — usually, only “smart” human enemies or friends can take advantage of them. Analyzing level files with utilities like //FexInspect// may help understanding particular AI object setup and learn which NPCs can actually work with them.+</note>
  
 Specific set of AI objects and their respective entity type IDs are different across game versions, but types themselves largely remained unchanged from TR3 to TR5. Here are they: Specific set of AI objects and their respective entity type IDs are different across game versions, but types themselves largely remained unchanged from TR3 to TR5. Here are they:
Line 136: Line 167:
   * **AI_FOLLOW** — Used primarily with friendly NPCs, and makes them wait for Lara and then “lead” her to specific point. For such behaviour, one AI_FOLLOW object must be placed in the same sector as NPC, and second AI_FOLLOW object must be placed on target point. If Lara shoots NPC affected with AI_FOLLOW behaviour, he will abandon it and become hostile.   * **AI_FOLLOW** — Used primarily with friendly NPCs, and makes them wait for Lara and then “lead” her to specific point. For such behaviour, one AI_FOLLOW object must be placed in the same sector as NPC, and second AI_FOLLOW object must be placed on target point. If Lara shoots NPC affected with AI_FOLLOW behaviour, he will abandon it and become hostile.
  
-**Note** +<note
->  +If there is a HEAVYTRIGGER under an AI_AMBUSH or AI_PATROL object, the enemy will activate it only when he gets there. 
-If there is a HEAVYTRIGGER under an AI_AMBUSH or AI_PATROL object, the enemy will activate it only when he gets there.+</note>
  
 {{:icons:tr4.png?nolink|TR4 only}}{{:icons:tr5.png?nolink|TR5 only}} TR4 introduced three additional AI objects, **AI_X1**, **AI_X2** and **LARA_START_POS**. First two are used, for example, with SAS Guards in //Cairo// story arc. When AI_X1 object is placed in the same sector with SAS Guard, he will prefer to shoot grenades instead of bullets. If another SAS Guard with AI_X2 is activated nearby, then first one will stop shooting grenades, and second one will shoot them instead. {{:icons:tr4.png?nolink|TR4 only}}{{:icons:tr5.png?nolink|TR5 only}} TR4 introduced three additional AI objects, **AI_X1**, **AI_X2** and **LARA_START_POS**. First two are used, for example, with SAS Guards in //Cairo// story arc. When AI_X1 object is placed in the same sector with SAS Guard, he will prefer to shoot grenades instead of bullets. If another SAS Guard with AI_X2 is activated nearby, then first one will stop shooting grenades, and second one will shoot them instead.
Line 161: Line 192:
 ==== AI Data Block in TR4-5 ==== ==== AI Data Block in TR4-5 ====
  
-Beginning with TR4, AI objects are //not kept along with other entities//. Instead, they have their own structure, which is basically meshes_modelssimplified [[#tr4_entity|[tr4_entity]]] structure, and moved to separate data block. This seems reasonable, as the only purpose of AI objects is to serve as “waypoints”, and they have neither //collisional// nor //control// code attached to them.+Beginning with TR4, AI objects are //not kept along with other entities//. Instead, they have their own structure, which is basically simplified [[trs:meshes_models#tr4_entity|[tr4_entity]]] structure, and moved to separate data block. This seems reasonable, as the only purpose of AI objects is to serve as “waypoints”, and they have neither //collisional// nor //control// code attached to them.
  
 The format of AI object structure as follows: The format of AI object structure as follows:
trs/npc_behaviour.1483533474.txt.gz · Last modified: by zdimension
Back to top
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0