Behaviors and Reactions

From PSwiki
Jump to navigation Jump to search

As discussed earlier in NPC Scripting, any NPC Types are really simply a collection of behaviors and reactions to events. At the most meta level, all of us fit this definition. How we act and how we respond to stimuli determines everything about our activities over time. Thus it seems sufficient and general to model npc behavior this way also.

Each behavior gets a script made of Behavior_Operations as documented in the previous sections. For now we will neglect those, however and just talk about the behaviors themselves.

Example

Here is an example of an NPC Type’s behavior/reaction list:

 <npctype name="Wanderer">
     <behavior name="walk" decay="0" growth="0" initial="50">
     <behavior name="turn" completion_decay="100">
     <behavior name="fight">
     <behavior name="chase" completion_decay="100">
     
<react event="collision" behavior="turn" delta="100" /> <react event="out of bounds" behavior="turn" delta="100" /> <react event="attack" behavior="fight" delta="150" /> <react event="damage" behavior="fight" delta="20" weight="1" /> <react event="target out of range" behavior="chase" delta="0" /> <react event="death" behavior="fight" delta="-1" /> </npctype>

This collection of behaviors and reactions is sufficient to have a basic outdoor wandering monster who will avoid collisions, stay in his boundary region, fight back if attacked and stop attacking if he dies.

List of priorities for NPCs

Similar to the way the hate list maintains a prioritized list of enemies for each NPC, each NPC also maintains a set of priorities for the list of behaviors in its npctype. The priority list starts out with 0 as the default score, unless an “initial” attribute is specified. (One behavior should have this attribute so the npc has a place to start.) Thus, any “Wanderer” NPC will start with the following priority list:

P-List: walk-50, turn-0, fight-0, chase-0

Thus on startup the NPC will begin by walking and using the operations inside that behavior tag to do something until an event occurs which preempts the behavior by making something else higher priority. For example, if he goes out of bounds, he will get an “out of bounds” perception, which he has a <react> tag for. It says to add 100 points to the “turn” behavior priority, which results in:

P-List: walk-50, turn-100, fight-0, chase-0

So his “walk” behavior is interrupted and the “turn” behavior and script is activated. This script starts running and the npc starts turning. Turning to point back into the boundary region should only take a couple of seconds. When the script complets for this behavior, the “completion_decay” of the behavior kicks in and affects the P-List again:

P-List: walk-50, turn-0, fight-0, chase-0

There are many real-world examples of how “completion_decay” exists in humans. Many actions are the top priority until they are completed, and then one simply doesn’t need to do them anymore. “completion_decay” is modeling that change in priority when an action is performed.

Now that the priority for turn has gone back to 0, “walk” again is the highest priority behavior and the npc starts walking again.

So now the npc is attacked by a player in the forest. “attack” is a perception sent by the server, as discussed in a previous section, and one for which this npctype has a <react> tag, telling him to add 150 to his “fight” priority, resulting in:

P-List: walk-50, turn-0, fight-150, chase-0

So now the npc stops walking and starts his fight behavior, which probably has the <melee> operation in it, using the hate list to fight back against one or more attackers. As the attack progresses, damage perceptions come in. A damage perception of 10HP has a <react> script also, which adds 10 points to the fight priority and also has a “weight” attribute which affects the hate list instead of the behavior list:

P-List: walk-50, turn-0, fight-160, chase-0

Since the fight behavior is already the highest, it might be redundant to keep increasing it like this, but personally I view it as the npc getting more enraged, which means it will take him longer to calm down when he runs out of enemies. The weight=”1” attribute means that the attacker’s hate score will go up by 1*HP.

Now imagine that the attacking player is losing the fight, and decides to run away. Very quickly, the “target out of range” perception will fire, created by the melee operation when the most hated enemy is farther away than the melee_range but within the seek_range. This NPC is scripted to chase after hated enemies if they run away with his <react event=”target out of range”> tag. The “delta” specified of 0 is a special delta which means “Make the named behavior the highest no matter what.” When reactions are coded with 0 deltas, NPCs are really acting like state machines again.

P-List: walk-50, turn-0, fight-160, chase-185 (Highest means at least 25 higher than the next highest to cause a preemption and switch.)

So now the NPC stops attacking and begins chasing the most hated enemy. The <chase> tag has a range specified for the chase to be completed (probably 2m again), so when the npc has caught the player, the chase behavior completion decay hits. The chase behavior has a specified completion decay of 100, but since chase was escalated artificially high by the 0 react, it is restored intead back to its original value.

P-List: walk-50, turn-0, fight-160, chase-0

So the npc stops chasing and resumes fighting the player immediately when he catches him. Now the npc finally kills the player and the fight is over. The “fight” behavior is still the highest one, so the npc keeps looking around for other enemies to fight, such as group members. If none are found, his fight behavior keeps decreasing by 10 points per iteration. P-List: walk-50, turn-0, fight-160, chase-0 P-List: walk-50, turn-0, fight-150, chase-0 P-List: walk-50, turn-0, fight-140, chase-0 P-List: walk-50, turn-0, fight-130, chase-0 And so on…

Eventually, “walk” behavior becomes the most active again and the npc resumes his wandering of the forest.


The key concepts here are that the NPC constantly maintains a priority list of behaviors and a priority of list of enemies to attack. <react> tags can affect behavior priority, hate list priority or both.

The interactions of events, behaviors and reactions can become very complex. The npc can be interrupted by an attack while moving, turning or even chasing another player. This priority structure was designed to allow for rich behavior interruption and resumption while having realistic reactions to world events and activities. Hopefully, with the right scripts we can create very life-like npcs that are also efficient on networking and CPU, with emergent behaviors that stay challenging and interesting to players for a long time to come.

Behavior

A behavior is a collection of Behavior_Operations. A behavior can be configured to behave in very different ways. The following table show the parameters that can be set for each behavior.

Parameter Type Default Description
name string Mandatory The name of this behavior
loop boolean false Set to true if this behavior should loop
decay float 0.0 The decay rate of this behavior to apply when the behavior is the active one.
completion_decay float 0.0 The decay to be applied when this behavior is done. -1 will be all of the current need.
failure string The FailurePerception to fire if a operation fail without having own failure perception.
growth float 0.0 The growth rate of this behavior to apply when the behavior isn't the active one.
initial float 0.0 The initial need for this behavior
interrupt string A perception to fire when this behavior is interrupted.
when_dead boolean false Set this to true if this behavior should be possible while dead. Resurrect Operation will need this.
resume boolean false Set to true if this behavior should resume after an interrupt.
min float none Set this attribute if a min need limit should be applied to this behavior.
max float none Set this attribute if a max need limit should be applied to this behavior.
 Ex: <behavior name="move" decay="0" growth="0" initial="80" loop="yes" resume="yes">
       ...
     </behavior>
     <behavior name="chase" decay="1" completion_decay="-1" growth="0" initial="0" >
       ...
     </behavior>

Reaction

Parameter Type Default Description
event string The event to react to.
behavior string[,...,string] The set of behavior to influence if this reaction is triggered.
delta float 0.0 Apply a delta value to the need of the affected behavior.
absolute float 0.0 Apply a absolute value to the need of the affected behavior.
range float 0.0
weight float 0.0 Passed to the perception when the reaction is accepted. Used to alter the hate list of the NPC.
faction_diff int 0 Used to match faction perceptions.
oper string The operator to use when comparing faction perceptions.
condition string The condition NPCClient math script has to return a none zero value in order for the reaction to react.
value string[,...,string] Used by some perceptions like time.
random integer[,...,integer] Used to add some random value to the value array.
type string The type is different for each perception. A "location sensed" will have the location type as the type. NPC Variables will be replaced.
active_only boolean false Only influence active behaviors
inactive_only boolean false Only influence inactive behaviors
no_timeout boolean false Removes the timeout for "player adjacent/nearby/.." reactions.
when_dead boolean false Influence behaviors even if the npc is dead.
when_invisible boolean false Set to true if an invisible NPC should accept this reaction.
when_invincible boolean false Set to true if an invincible NPC should accept this reaction.
only_interrupt string,[...,string] If set this event will only be accepted if it can interrupt one and active behavior from this list.
do_not_interrupt string,[...,string] Set this if this reaction should not interrupt some active behaviors.

The reaction influences the behaviors need:

  • GUARANTEED to be executed if no delta or absolute attribute set (careful delta=0 means DESIRE_NONE)
  • DELTA (delta attribute set)
  • or ABSOLUTE ( absolute attribute set)


 Ex:  <react event="damage"                behavior="Fight" delta="20" weight="1" />


 Ex:  <react event="time" value="16,0,,,"  random=",5,,," behavior="GoHome" />

This example show a reaction to a time event that will occur between 1600 and 1605. This is archived due to the random property. Each of the values in value represents "Hour,Minute,Year,Month,Day". Any parameter not set will match every possible combination.

 Ex:  <react event="location sensed"    behavior="ExploreLoc"    type="mine" only_interrupt="Explore" />

This example show a reaction to the location sensed perception where location of type mine will interrupt explore operation with the ExploreLoc behavior.

Perceptions

Perceptions it the invisible mechanism that makes reactions act. There are several situations where perceptions are fired. Some are hard coded into the NPCClient. Some are fired as responses to other script elements and the name might be configurable. An example on this is the Chase Operation where the perception name is configured through the operation. A hard coded perception is the Death Perceptions event.

Some perceptions might only be documented through the senders like the Behavior_Operations.

Attack Perceptions

This is perception is fired when someone is attacking a NPC.

Attribute Values/Type Default Description
event attack The perception name
weight float 0.0 The weight to apply to the hate list. The default is 0.0 so without setting a weight no adjustment to hate list will be done.
 Ex: <react event="attack" weight="10.0" ... />
   

This example will apply 10.0 to hate list for the NPC when reacting to the attack perception.

Collision Perceptions

This perception is fired when someone collide due to movements.

Attribute Values/Type Default Description
event collision The perception name
 Ex: <react event="collision"  ... />
   

Damage Perceptions

This perception is fired when someone do damage to an NPC.

Attribute Values/Type Default Description
event damage The perception name
weight float 0.0 The weight to apply to the damage regarding hate list. The default is 0.0 so without setting a weight no adjustment to hate list will be done.
 Ex: <react event="damage" weight="2.0" ... />
   

This example will apply double damage to hate list for the NPC when reacting to the damage perception.

Death Perceptions

This perception is fired when an NPC/Player dies and is broadcasted.

Attribute Values/Type Default Description
event death The perception name
range float 0.0 The range of the perception
 Ex: <react event="death" ... />
     <react event="death" range="10" ... />
   

Upon execution the dead entity is removed from the receivers hate list.

Faction Perceptions

This is perception can be filtered on the faction standing between the NPC and the sender. By defining the oper in the reaction the faction will be compared. Without the factions will not be compared.

Attribute Values/Type Default Description
talk Talk preception fired when talked to
event owner anyrange, owner sensed, owner nearby, owner adjacent Owner perceptions fired when owner is at different ranges(Will not get player perception if you are the owner).
player anyrange, player sensed, player nearby, player adjacent Player perceptions fired when player is at different ranges.
faction_diff integer The faction value to compare
oper >,< React if grater than or react when less than. If no oper is defined, faction will not be compared.
Range Value in meters Perception type
anyrange >30 PCPT_ANYRANGEPLAYER
sensed <=30 PCPT_ANYRANGEPLAYER
nearby <=10 PCPT_SHORTRANGEPLAYER
adjacent <=4 PCPT_VERYSHORTRANGEPLAYER
 Ex: <react event="talk" faction_diff="10" oper=">" ... />
   

This example will only react to talk if the faction difference is more than +10 to the originator of the talk perception.

 Ex: <react event="player nearby" ... />

This will allways react when a player is nearby.

In bounds Perception

This perception is fired whenever a NPC moves out of bounds.

Attribute Values/Type Default Description
event in bounds Checks if the NPC is in bounds of a region defined in sc_npc_definitions and set up in sc_locations.


 Ex:  <react event="in bounds" ... />

Item Perceptions

This perception is fired whenever a NPC moves into the nearby, adjacent, or sensed range from an item. In the nearby range the item is so close that it can be picked up.

Attribute Values/Type Default Description
event item nearby, item adjacent, item sensed The different perception fired that nearby, adjacent, or sensed range.


 Ex:  <react event="item adjacent"   behavior="pickup item" />
      <react event="inventory:added" behavior="equip item" />

Location Perception

This perception is fired whenever a NPC moves into the sensed range of a location.

Attribute Values/Type Default Description
event location sensed
type string The location type name of the location sensed.


 Ex:  <react event="location sensed" type="mine" ... />
      <react event="location sensed" ... />

NPC Cmd Perception

This perception is fired whenever a NPC receives a command from the server. If prefixed with npccmd:self only self will react. If prefixed with npccmd:global: all npcs will be able to react to this command. The command can be generated from the NPC Cmd Response Operation <npccmd cmd="npccmd:self:open_cage" /> used in NPC Dialogues scripting at the server.

Attribute Values/Type Default Description
event npccmod:global:xx The command sent from the server. See description above.


 Ex:  <react event="npccmd:global:start_riot" ... />
      <react event="npccmd:self:open_cage" ... />

Out of bounds Perception

This perception is fired whenever a NPC moves out of bounds.

Attribute Values/Type Default Description
event out of bounds Checks if the NPC is out of bounds of a region defined in sc_npc_definitions and set up in sc_locations.


 Ex:  <react event="out of bounds" ... />

Spell Perception

This perception is fired whenever a spell is casted.

Attribute Values/Type Default Description
event spell:target,spell:self,spell:unkown
type string The spell type.


 Ex:  
      <react event="spell:self" type="direct damage" ... />

      <react event="spell:target" type="direct healing" ... />

Spoken To Perception

This perception is fired whenever someone speak to a NPC. This can be used to suspend other activities while players interact with the NPC.

Attribute Values/Type Default Description
event spoken_to
type string true,false True if spoken to, or false if no longer spoken to.


 Ex:  <react event="spoken_to" type="true" ... />

Time Perception

This perception is fired every game minute. The time is in Game Time. It allows react to trigger on any combination of game hours, minutes, years, month, days.

Attribute Values/Type Default Description
event time
value hours[0-23],minutes[0-59],years,month[1-10],days[1-32] In the Yliakum Calendar there are 10 month in a year and 32 days per month. Match 1200 at the 2nd month like this "12,00,,2,"


  Ex: <react event="time" value="12,00,,2," ... />

Random times can be archived by using the random. Any value larger than the max hour, max minute, max month, max days will cause the event to be normalized and the next bigger value will be increased if valid. Eg. in the following example the hour will be increased if the selected random value of the minute is larger than 60.

  Ex: <react event="time" value="10,0,,," random=",120,,," ... />