Ambient behaviour

From Dragon Age Toolset Wiki
Jump to: navigation, search
Creature topics:

Ambient behaviour begins when the player moves within 50m of a creature and ceases when the player remains more than 50m away for at least 40s. Ambient behaviour alternates between a movement phase and an animation phase, simulating a bubble of activity around the player. In a movement phase, the creature (optionally) moves to a new destination (typically a waypoint but it could be any object) and turns to face the same direction as the destination object. In an animation phase, the creature (optionally) performs one or more animations either in sequence or at random. Exact behaviour is controlled by local variables set on either the creature instance or template (see table below). All other local variables with the prefix AMBIENT_* are used internally by the ambient behaviour system (see script sys_ambient_h.nss) and should not be manually modified. Never directly modify AMBIENT_* local variables at run time using SetLocalInt - always use the functions Ambient_Start, Ambient_Stop, Ambient_OverrideBehaviour, and Ambient_RestoreBehaviour instead. Ambient behaviour is persisted when a game is saved and automatically resumes when a game is loaded.

Local Variables (var_creature)

Variable name Type Default Description
AMBIENT_SYSTEM_STATE int 0 Bitmask controlling ambient system operation. (ergo, values below are in hexadecimal).
  • 0x01 (AMBIENT_SYSTEM_ENABLED): Ambient behaviour enabled. For non-looping animations this is the only bit that need be set.
  • 0x02 (AMBIENT_SYSTEM_SPAWNSTART): Begin ambient behaviour immediately after spawning. Generally, only infinitely looping animations require this.
  • 0x04 (AMBIENT_SYSTEM_NOPLAYNEXT): Sets bPlayNext parameter to CommandPlayAnimation to false. Only infinitely looping animations require this.
  • 0x08 (AMBIENT_SYSTEM_NOBLEND): Sets bBlendIn parameter to CommandPlayAnimation to false. Set this to force a creature to resume an infinitely looping animation after a conversation.
  • 0x10 (AMBIENT_SYSTEM_ALWAYSON): Ambient behaviour never stops, regardless of distance to player. This should rarely, if ever, be used but at least the functionality exists if needed.
AMBIENT_MOVE_PATTERN int 0 Dictates how the creature moves. Add 100 to the values below make creature run instead of walk. Add 10-90 for a random mix of running and walking (a higher value means more running).
  • 0 (AMBIENT_MOVE_NONE): No ambient movement
  • 1 (AMBIENT_MOVE_PATROL): Patrol waypoints (1, 2, 3, 2, 1, ...)
  • 2 (AMBIENT_MOVE_LOOP): Loop through waypoints (1, 2, 3, 1, 2, 3, ...)
  • 3 (AMBIENT_MOVE_WARP): Jump creature from the last waypoint to the first (1, 2, 3, jump to 1, 2, 3, ...)
  • 4 (AMBIENT_MOVE_RANDOM): Move to a random waypoint other than the one the creature is currently at
  • 5 (AMBIENT_MOVE_WANDER): Move to random location within 10m of home location
  • 6 (AMBIENT_MOVE_WANDER_FAR): Move to random location within 30m of home location
  • 7 (AMBIENT_MOVE_PATH_PATROL): Patrol all waypoints using CommandMoveToMultiLocations (1,2,3,2,1,...)
  • 8 (AMBIENT_MOVE_PATH_LOOP): Loop through all waypoints using CommandMoveToMultiLocations (1,2,3. 1,2,3)
  • 9 (AMBIENT_MOVE_ONCE): Walk through the waypoint set once (1-2-3)
AMBIENT_MOVE_PREFIX string ap_<tag> The prefix is used to determine the waypoints the creature can travel to. Note that <tag> is a placeholder filled in at run-time with the tag of the creature. Hence, for example, if AMBIENT_MOVE_PREFIX is ap_<tag> and the creature's tag is cr_dog then the system will look for waypoints with tags ap_cr_dog_01, ap_cr_dog_02, etc. If no waypoint is found with the _01 extension, the system will search instead for all waypoints with tags matching the AMBIENT_MOVE_PREFIX value exactly (i.e. ap_cr_dog). This is useful in cases where you just want to add N waypoints all with the same tag.
AMBIENT_ANIM_PATTERN int 0 A row ID in ambient_anim_patterns 2da. Specifies the list of possible actions the creature can/will perform during an animation phase.
  • 0: No ambient animation pattern (ergo, no ambient animations).
AMBIENT_ANIM_FREQ float -1.0 Animation frequency. The part left of the decimal specifies the minimum and the part right of the decimal specifies the maximum number of random animations to play during an animation phase. So, for example, a value of 1.3 will play between 1 and 3 random animations from the animation pattern listed in ambient_ai.xls. A value of -1.0 plays all animations in the animation pattern in the order they are listed in ambient_ai.xls. Animation pattens that are highlighted in green on the worksheeet should always be played in order (i.e. AMBIENT_ANIM_FREQ is -1.0).
AMBIENT_COMMAND int 0 If non-zero, this value forces the creature to perform a specific command (instead of moving and animating).
  • 0: Use standard ambient ambient behaviour system to perform movement and animations.
  • 1: Forces creature to attack the nearest object with tag <tag>_target. There's an interval of 1-5 seconds between attack commands.
  • 2: Forces creature to attack the nearest object with tag <tag>_target. There's an interval of 0-0.5 seconds between attack commands.
AMBIENT_ANIM_PATTERN_OVERRIDE int 0 Overrides AMBIENT_ANIM_PATTERN if non-zero.
AMBIENT_ANIM_FREQ_OVERRIDE int 0 Overrides AMBIENT_ANIM_FREQ if non-zero.
AMBIENT_ANIM_STATE int 0 Internal use by ambient behaviour system. Tracks number of animations left to play.
AMBIENT_MOVE_COUNT int -1 Internal use by ambient behaviour system. Tracks total number of destination points for a creature.
AMBIENT_MOVE_STATE int 0 Internal use by ambient behaviour system. Tracks the last waypoint creature moved to and direction of travel.
AMBIENT_TICK_COUNT int 0 Used internally, do not modify
AMBIENT_ANIM_OVERRIDE_COUNT int 0

ambient_anim_patterns 2da

The actions used in an animation phase are listed in the ambient_anim_patterns 2da. Each row defines an animation pattern, consisting of up to thirteen actions. Each action is composed of an animation (left of the decimal) and the number of loops it is played (right of decimal). For example, 619.02 will play a sleeping loop animation twice and 619.99 will play an infinitely looping sleeping animation. Non-looping animations require no loop-count (i.e. decimal) component. The list of all available animations is located in ANIM_ 2da.

sys_ambient_h

The script sys_ambient_h contains the implementation of the ambient behaviour system. The AMBIENT_* local variables should never be directly modified at run-time. Instead, use the following functions to customize a creature's ambient behaviour through script.

// Normally this function is called automatically to begin or resume  ambient behaviour when a 
// creature perceives the player. However, it can be called explicitly to force a creature to begin 
// performing ambient behaviour or, if nAmbientEnable is 1, to enable ambient behaviour on a creature. 
void Ambient_Start(object oCreature = OBJECT_SELF, int nAmbientEnable = 0, int nMovePattern = 0, string sMovePrefix = "");
 
// Normally this function is called automatically to pause ambient behaviour after the party has 
// been out of the creature's sight for a while. However, this function can be used to force a 
// creature to temporarily cease ambient behaviour. Note that the creature will automatically  
// resume ambient behaviour when it perceives the player again. 
void Ambient_Pause(object oCreature = OBJECT_SELF, int bCheckVisibility = TRUE);
 
// Turns off ambient behaviour on a creature. The creature will resume ambient behaviour only 
// after Ambient_Start() is called.
void Ambient_Stop(object oCreature = OBJECT_SELF);
 
// Overrides the ambient animation pattern and animation frequency defined by the creature's template. 
void Ambient_OverrideBehaviour(object oCreature, int nAnimPattern, float fAnimFreq);
 
// Restores a creature's ambient animation behaviour to that defined in the creature's template.
void Ambient_RestoreBehaviour(object oCreature);

Overriding Ambient Behaviour

Variable name Type Default Description
AMBIENT_ANIM_PATTERN_OVERRIDE int 0 A row ID in ambient_anim_patterns 2da. Specifies the list of possible actions the creature can/will perform during an animation phase.
  • 0: no animations.
AMBIENT_ANIM_FREQ_OVERRIDE float -1.0 Animation frequency. The portion left of decimal specifies the minimum and the portion right of the decimal specifies the maximum number of animations to play during an animation phase. A value of -1.0 plays all animations in the animation pattern in the order listed in ambient_anim_patterns 2da.
AMBIENT_ANIM_OVERRIDE_COUNT int Used internally, do not modify

Customising Ambient Behaviour

Animations

New ambient_anim_patterns can be added as an M2DA.

Provisionally, it seems that some animations are cutscene-only. They don't work when scripted. This requires further investigation and documentation, as there is a bug which may account for some or all of this.

Movement

The system doesn't provide an explicit hook for a user-defined movement pattern.

However, it does support walking once through a set of waypoints.

We can implement any custom movement pattern as several sets of waypoints (each with its own prefix).

For example, if we want to walk from A to B, then C or D and E depending on some condition, we might define the sets as ap1 (A, B), ap2 (C) and ap3 (D, E).

We tell Ambient AI to walk waypoints prefixed ap1. On completion, we tell it to walk ap2 or ap3, depending on the condition.

Intercepting the Ambient AI is tricky. By default, EVENT_TYPE_COMMAND_COMPLETE is handled directly by the rules_core script, which kicks off the next Ambient AI action before we can stop it. Presumably, this is for performance reasons.

Set the AI_CUSTOM_AI_ACTIVE variable (see Custom AI) on the creature template to generate a new event (EVENT_TYPE_CUSTOM_COMMAND_COMPLETE) which can be handled in the creature script. If the creature is a non-combatant, CAI_INACTIVE (1) works fine.

Using AMBIENT_MOVE_ONCE, when the final waypoint is reached, Ambient AI will reset the move pattern to AMBIENT_MOVE_NONE before this new event fires.

We can then trigger the next set of waypoints by including a snippet like this in our creature script:

        case EVENT_TYPE_CUSTOM_COMMAND_COMPLETE:
        {
         object oCreature = OBJECT_SELF;
 
         // Do nothing unless we have arrived at our destination 
 
         if (GetLocalInt(oCreature, AMBIENT_MOVE_PATTERN) == AMBIENT_MOVE_NONE)
            {     
              int    nLastCommandType = GetEventInteger(ev, 0);
              int    nCommandStatus   = GetEventInteger(ev, 1);
              int    nLastSubCommand  = GetEventInteger(ev, 2);
              object oLastTarget      = OBJECT_INVALID;
              object oBlockingObject  = GetEventObject(ev, 2);  
 
              // Check which path just finished
 
              if (GetLocalString(oCreature, AMBIENT_MOVE_PREFIX) != "ap1_<tag>") break;
 
              // Stop Ambient AI for good order
 
              Ambient_Stop(oCreature);
 
              // Fix bug in Ambient_Start
 
              SetLocalInt(oCreature, AMBIENT_MOVE_COUNT, AMBIENT_MOVE_COUNT_INVALID); 
              SetLocalInt(oCreature, AMBIENT_MOVE_STATE,  AMBIENT_MOVE_NEXT);   
 
              // Restart on new path           
 
              Ambient_Start(oCreature, AMBIENT_SYSTEM_ENABLED, AMBIENT_MOVE_ONCE, "ap2_<tag>");                
            }
 
          bEventHandled = TRUE;
          break;
        }

Note that when using any movement pattern other than AMBIENT_MOVE_ONCE, Ambient AI will issue the next movement command before EVENT_TYPE_CUSTOM_COMMAND_COMPLETE fires.

Bugs

Changing the movement path for a creature is bugged.