This article's documentation is for anything that uses the Source engine. Click here for more information.

Dynamic interactions: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
m (Ugh. I spent all that time... and I forgot to add it to the QC Keyvalues category...)
mNo edit summary
 
(13 intermediate revisions by 5 users not shown)
Line 1: Line 1:
{{wip|[[User:Gjsdeath|Gary]]}}
{{lang|{{PAGENAME}}|title=Dynamic Interactions}}{{source topicon}}[[Category:QC Keyvalues]]
[[File:Dynamic_interaction_modded_citizen_v_zombie0.jpg|thumb|512|Example of an dynamic interaction. This one is copied from Alyx and allows citizens to kick zombies.]]
[[Dynamic interactions]] are special NPC animations introduced in {{hl2ep1|4.1}}. They allow two NPCs to perform synchronized {{ent|scripted_sequence}}s with each other, with or without input from the level. They're mostly used for combat and/or kill animations, like Alyx kicking a zombie or a hunter throwing a citizen to the ground, but other types of interactions are possible.


The '''dynamic_interactions''' [[KeyValues]] block defines when and how to perform a dynamic interaction. For example; when [[Alyx]] kicks a zombie. It is embedded in a model with the [[$keyvalues]] QC command.
Two NPCs are involved in dynamic interactions. The '''main NPC''' is the NPC which starts and coordinates the interaction, e.g. Alyx in an "alyx vs. zombie" interaction. The '''partner NPC''' is the NPC which "receives" the interaction, e.g. the zombie in an "alyx vs. zombie" interaction.


{{Warning | This page is not done yet, all the information on it has not been confirmed!! I will be working on it for the next one or two days. If you want to confirm or add something, please add it to the discussion page for now. All the "confirms" are there because I just assumed a lot of those descriptions. My assumptions were based on the names and the code that they use.}}
Dynamic interactions are created with {{ent|$sequence}}s and a {{ent|$keyvalues}} block embedded in the main NPC's model, which defines how and when to perform a dynamic interaction. The partner NPC only needs a corresponding sequence with the same name as the main NPC's sequence. For example, Alyx has the dynamic interactions defined in her model using <code>$keyvalues</code>, but the zombie model just has sequences with matching names.


{{bugfix|Since dynamic interactions aren't tied to any specific partner class and only look for matching sequence names, main NPCs with the <code>$keyvalues</code> block defined can perform dynamic interactions with other main NPCs with the same <code>$keyvalues</code> block defined (e.g., Alyx vs. Alyx), which can result in both NPCs performing weird, twinned interactions with each other.|You can fix this in code by preventing interactions from starting if the other NPC has the same interaction <code>$keyvalues</code> defined.|code}}
[[Activity|Activities]] are used to allow an interaction to use one of a selection of sequences. If an interaction points to a sequence, only that sequence will be used. If an interaction points to an activity, any sequence with that activity will be used. The partner NPC will still use a sequence that matches the name of the selected sequence. (They should have the same activity definitions, though!)
Interactions can be forced with the <code>ForceInteractionWithNPC</code> input on the main NPC and can then be monitored with corresponding outputs.


== Example ==
== Example ==
 
Found in <code>models/Alyx_animations.mdl</code>
{{Note|This is only one of the interactions, and it has been restructured for easier reading!}}
<pre>
<pre>
  $keyvalues  
  $keyvalues  
Line 17: Line 25:
"alyx_v_zombie_180deg_64"  
"alyx_v_zombie_180deg_64"  
{  
{  
"trigger" "auto_in_combat"  
"trigger" "auto_in_combat"  
"origin_relative" "64 0 0"  
"origin_relative" "64 0 0"  
"angles_relative" "0 180 0"  
"angles_relative" "0 180 0"  
"activity" "ACT_DI_ALYX_ZOMBIE_MELEE"
"activity" "ACT_DI_ALYX_ZOMBIE_MELEE"
"delay" "10.0"  
"delay" "10.0"  
"needs_weapon" "ME"  
"needs_weapon" "ME"  
"weapon_mine" "weapon_alyxgun"  
"weapon_mine" "weapon_alyxgun"  
}   
}   
   
   
Line 29: Line 37:
  }
  }
</pre>
</pre>


==Options==
==Options==
{{Note | The "partner" is the character that this character is interacting with.}}
;<code>trigger <choices></code>: What triggers this interaction. If this isn't defined, the interaction can be triggered via the input <code>forceinteractionwithnpc "<[[targetname]]> <interaction name>"</code>.
 
;<code>trigger <choices></code>
: ''What triggers this interaction...''
:; <code>auto_in_combat</code>
:; <code>auto_in_combat</code>
:: Automatically in combat.  
:: Automatically in combat.  
 
;<code>loop_break_trigger <choices></code>: Stop looping the action animation if <code>loop_in_action</code> was set.
;<code>loop_break_trigger <choices></code>
: ''Stop looping the action animation if <code>loop_in_action</code> was set.{{TODO | Find out what exactly this does...}}''
:; <code>on_damage</code>
:; <code>on_damage</code>
:: Break loop on damage. {{TODO | Confirm. }}
:: Break loop on damage.
:; <code>on_flashlight_illum</code>
:; <code>on_flashlight_illum</code>
:: Break loop once illuminated by player's flashlight. {{TODO | Confirm. }}
:: Break loop once illuminated by player's flashlight.  
 
;<code>origin_relative <[[vector]]></code>:Desired relative origin of the other NPC.
;<code>origin_relative <[[vector]]></code>
;<code>angles_relative <[[angles]]></code>:Desired relative angles of the other NPC.
 
;<code>velocity_relative <[[vector]]></code>:Desired relative velocity of the other NPC.
;<code>angles_relative <[[angles]]></code>
:{{bugfix|Non-functional.|Velocity checking can be added in <code>CAI_BaseNPC::InteractionCouldStart()</code>.|code}}
 
;<code>entry_sequence <[[sequence]]></code>:What sequence to play for this interaction before the main sequence/activity.
;<code>velocity_relative <[[vector]]></code>
;<code>entry_activity <[[activity]]></code>:What activity to play for this interaction before the main sequence/activity.
 
;<code>sequence <[[sequence]]></code>:What sequence to play for this interaction. (The "action" animation.)
;<code>entry_sequence <[[sequence]]></code>
;<code>activity <[[activity]]></code>:What activity to play for this interaction. (The "action" animation.)
: ''What sequence to play for this interaction before the main sequence/activity.'' {{TODO | Confirm. }}
;<code>exit_sequence <[[sequence]]></code>:What sequence to play for this interaction after the main sequence/activity.
 
;<code>exit_activity <[[activity]]></code>:What activity to play for this interaction after the main sequence/activity.
;<code>entry_activity <[[activity]]></code>
;<code>delay <[[float]]></code>:Delay before interaction can be used again.
: ''What activity to play for this interaction before the main sequence/activity.'' {{TODO | Confirm. }}
;<code>origin_max_delta <[[float]]></code>:Max distance sqr from the relative origin the NPC is allowed to be to trigger.
 
;<code>loop_in_action <[[float]]></code>:Loop the main animation.{{Note|While the value is a float, it's used as a bool in code.}}
;<code>sequence <[[sequence]]></code>
;<code>dont_teleport_at_end <choices></code>:Don't teleport/fix up positions at the end.
: ''What sequence to play for this interaction.(The "action")''
 
;<code>activity <[[activity]]></code>
: ''What activity to play for this interaction.(The "action")''
 
;<code>exit_sequence <[[sequence]]></code>
: ''What sequence to play for this interaction after the main sequence/activity.'' {{TODO | Confirm. }}
 
;<code>exit_activity <[[activity]]></code>
: ''What activity to play for this interaction after the main sequence/activity.'' {{TODO | Confirm. }}
 
;<code>delay <[[float]]></code>
: ''The delay... before starting the interaction? {{TODO | Confirm. }}
 
;<code>origin_max_delta <[[float]]></code>
: ''Something to do with delta animation... {{TODO | Confirm. }}
 
;<code>loop_in_action <[[float]]></code> {{Note | While the value is a float, it's used as a bool in code. }}
: ''Loop in the "action" animation(the "activity" or "sequence" options.). {{TODO | Confirm. }}
 
;<code>dont_teleport_at_end <choices></code>
: ''Don't teleport/fix up positions at the end {{TODO | Find out what exactly this does...}}''
:; <code>me</code>
:; <code>me</code>
:: Don't teleport/fix up this character's position{{TODO | Confirm. }}
:: Don't teleport/fix up this character's position.
:; <code>them</code>
:; <code>them</code>
:: Don't teleport/fix up this character's partner's position {{TODO | Confirm. }}
:: Don't teleport/fix up this character's partner's position.
:; <code>both</code>
:; <code>both</code>
:: Don't teleport/fix up this character's or his partner's position {{TODO | Confirm. }}
:: Don't teleport/fix up this character's or his partner's position.
 
;<code>needs_weapon <choices></code>:Needs a weapon to perform this interaction?
;<code>needs_weapon <choices></code>
: ''Needs a weapon to perform this interaction?''
:; <code>ME</code>
:; <code>ME</code>
:: Does this character need a weapon? {{TODO | Confirm. }}
:: Does this character need a weapon?  
:; <code>THEM</code>
:; <code>THEM</code>
:: Does this character's partner need a weapon? {{TODO | Confirm. }}
:: Does this character's partner need a weapon?  
:; <code>BOTH</code>
:; <code>BOTH</code>
:: Does both this character and his partner need a weapon? {{TODO | Confirm. }}
:: Does both this character and his partner need a weapon?  
;<code>weapon_mine <[[classname]]></code>:The weapon required to perform this interaction. If undefined, will perform with any weapon.
;<code>weapon_theirs <[[classname]]></code>:Partner's weapon required to perform this interaction. If undefined, will perform with any weapon.


;<code>weapon_mine <[[classname]]></code>
== Related or Useful Stuff ==
: ''This character needs this specific weapon to perform this interaction? {{TODO | Confirm. }}
=== Animation Events ===
 
{{main|Animation Events}}
;<code>weapon_theirs <[[classname]]></code>
: ''This character needs this specific weapon to perform this interaction? {{TODO | Confirm. }}
 
== Related or Useful Animation Events ==
These are useful animation events for those wanted to create an activity for a dynamic interaction.
These are useful animation events for those wanted to create an activity for a dynamic interaction.
READ: [[Animation_Events]]
{{Todo|Move to dedicated page or animation event page?}}
{{TODO | Move to dedicated page or animation event page?}}
 


=== Example ===
Example:
  { event AE_NPC_HURT_INTERACTION_PARTNER 28 "THEM 100" }
  { event AE_NPC_HURT_INTERACTION_PARTNER 28 "THEM 100" }


 
;<code>AE_NPC_HURT_INTERACTION_PARTNER "<choices> <[[int]]>" </code>:Hurt either this character or his partner… and how much (the int).
=== Animation Events ===
;<code>AE_NPC_HURT_INTERACTION_PARTNER "<choices> <[[int]]>" </code>
: ''Hurt either this character or his partner... and how much(the int).''
:; <code>ME</code>
:; <code>ME</code>
:: Hurt this character {{TODO | Confirm: Works? }}
:: Hurt this character.
:; <code>THEM</code>
:; <code>THEM</code>
:: Hurt the partner
:: Hurt the partner.
;<code>AE_NPC_SET_INTERACTION_CANTDIE "<[[bool]]>"</code>:Set those participating in the interaction to become invincible. {{Todo|Which NPC? The partner or this character?}}
;<code>AE_NPC_WEAPON_FIRE "<[[bool]]>"</code>:Fire this character's weapon. The bool is whether or not you want him to use the weapon's secondary fire.


;<code>AE_NPC_SET_INTERACTION_CANTDIE "<[[bool]]>"</code>
=== Console Variable ===
: ''Set those participating in the interaction to become invincible'' {{TODO | Which NPC? The partner or this character}}
[[File:Ai_debug_dyninteractions.jpg|thumb|128|Example of <code>ai_debug_dyninteractions</code> debugging information during a dynamic interaction.]]


;<code>AE_NPC_WEAPON_FIRE "<[[bool]]>"</code>
[[File:Ai_debug_dyninteractions2.jpg|thumb|128|Example of <code>ai_debug_dyninteractions</code> debugging information when a NPC is checking for the proper conditions to perform a dynamic interaction]]
: ''Fire this character's weapon. The bool is whether or not you want him to use the weapon's secondary fire.''


;<code>ai_debug_dyninteractions "<[[int]]>" </code>:Debug the NPC dynamic interaction system.
If <code>ai_debug_dyninteractions</code> is enabled, an axis will be created at the required relative position and this informaton is printed to the console while testing whether an interaction could start:
<pre>
DYNINT: (al) testing interaction "alyx_v_zombie_180deg_64"
  al is at: 404.55 -67.75 -115.91
  al distsqr: 0.37 (468.17 -60.77 -115.91), desired: (468.24 -61.37 -115.91)
  Idle_Relaxed_Shotgun_2 Speed: 0.00
  al angle matched: (0.00 186.25 0.00), desired (0.00, 185.72, 0.00)
</pre>
{{tip|Setting ai_debug_dyninteractions to <code>2</code> and selecting the NPC via <code>npc_select</code> and/or <code>ent_text</code> prints the distance information even if both NPCs are out of range.}}


== See Also ==
If <code>ai_debug_dyninteractions</code> is enabled, this informaton is printed to the console when a NPC begins a dynamic interaction:
 
<pre>
* [[$keyvalues]]
npc_alyx(al) starting dynamic interaction "alyx_v_zombie_180deg_64" with npc_citizen(dude2).
 
- Core sequence: alyx_zombie_fight2
</pre>


[[Category:QC Keyvalues]]
== See also ==
* [[Activity]]
* [[Animation Events]]
* [[Choreography creation|Choreography]]
* {{ent|$keyvalues}}
* {{ent|$sequence}}
* [[QC]]

Latest revision as of 10:05, 7 March 2024

English (en)Translate (Translate)
Example of an dynamic interaction. This one is copied from Alyx and allows citizens to kick zombies.

Dynamic interactions are special NPC animations introduced in Half-Life 2: Episode One Half-Life 2: Episode One. They allow two NPCs to perform synchronized scripted_sequences with each other, with or without input from the level. They're mostly used for combat and/or kill animations, like Alyx kicking a zombie or a hunter throwing a citizen to the ground, but other types of interactions are possible.

Two NPCs are involved in dynamic interactions. The main NPC is the NPC which starts and coordinates the interaction, e.g. Alyx in an "alyx vs. zombie" interaction. The partner NPC is the NPC which "receives" the interaction, e.g. the zombie in an "alyx vs. zombie" interaction.

Dynamic interactions are created with $sequences and a $keyvalues block embedded in the main NPC's model, which defines how and when to perform a dynamic interaction. The partner NPC only needs a corresponding sequence with the same name as the main NPC's sequence. For example, Alyx has the dynamic interactions defined in her model using $keyvalues, but the zombie model just has sequences with matching names.

Icon-Bug.pngBug:Since dynamic interactions aren't tied to any specific partner class and only look for matching sequence names, main NPCs with the $keyvalues block defined can perform dynamic interactions with other main NPCs with the same $keyvalues block defined (e.g., Alyx vs. Alyx), which can result in both NPCs performing weird, twinned interactions with each other.  [todo tested in ?]
Cpp.pngCode Fix:You can fix this in code by preventing interactions from starting if the other NPC has the same interaction $keyvalues defined.

Activities are used to allow an interaction to use one of a selection of sequences. If an interaction points to a sequence, only that sequence will be used. If an interaction points to an activity, any sequence with that activity will be used. The partner NPC will still use a sequence that matches the name of the selected sequence. (They should have the same activity definitions, though!)

Interactions can be forced with the ForceInteractionWithNPC input on the main NPC and can then be monitored with corresponding outputs.

Example

Found in models/Alyx_animations.mdl

Note.pngNote:This is only one of the interactions, and it has been restructured for easier reading!
 $keyvalues 
 { 
 
	dynamic_interactions 
	{

		"alyx_v_zombie_180deg_64" 
		{ 
			"trigger" "auto_in_combat" 
			"origin_relative" "64 0 0" 
			"angles_relative" "0 180 0" 
			"activity" "ACT_DI_ALYX_ZOMBIE_MELEE"
			"delay" "10.0" 
			"needs_weapon" "ME" 
			"weapon_mine" "weapon_alyxgun" 
		}   
 
	}
 }


Options

trigger <choices>
What triggers this interaction. If this isn't defined, the interaction can be triggered via the input forceinteractionwithnpc "<targetname> <interaction name>".
auto_in_combat
Automatically in combat.
loop_break_trigger <choices>
Stop looping the action animation if loop_in_action was set.
on_damage
Break loop on damage.
on_flashlight_illum
Break loop once illuminated by player's flashlight.
origin_relative <vector>
Desired relative origin of the other NPC.
angles_relative <angles>
Desired relative angles of the other NPC.
velocity_relative <vector>
Desired relative velocity of the other NPC.
Icon-Bug.pngBug:Non-functional.  [todo tested in ?]
Cpp.pngCode Fix:Velocity checking can be added in CAI_BaseNPC::InteractionCouldStart().
entry_sequence <sequence>
What sequence to play for this interaction before the main sequence/activity.
entry_activity <activity>
What activity to play for this interaction before the main sequence/activity.
sequence <sequence>
What sequence to play for this interaction. (The "action" animation.)
activity <activity>
What activity to play for this interaction. (The "action" animation.)
exit_sequence <sequence>
What sequence to play for this interaction after the main sequence/activity.
exit_activity <activity>
What activity to play for this interaction after the main sequence/activity.
delay <float>
Delay before interaction can be used again.
origin_max_delta <float>
Max distance sqr from the relative origin the NPC is allowed to be to trigger.
loop_in_action <float>
Loop the main animation.
Note.pngNote:While the value is a float, it's used as a bool in code.
dont_teleport_at_end <choices>
Don't teleport/fix up positions at the end.
me
Don't teleport/fix up this character's position.
them
Don't teleport/fix up this character's partner's position.
both
Don't teleport/fix up this character's or his partner's position.
needs_weapon <choices>
Needs a weapon to perform this interaction?
ME
Does this character need a weapon?
THEM
Does this character's partner need a weapon?
BOTH
Does both this character and his partner need a weapon?
weapon_mine <classname>
The weapon required to perform this interaction. If undefined, will perform with any weapon.
weapon_theirs <classname>
Partner's weapon required to perform this interaction. If undefined, will perform with any weapon.

Related or Useful Stuff

Animation Events

Main article:  Animation Events

These are useful animation events for those wanted to create an activity for a dynamic interaction.

Todo: Move to dedicated page or animation event page?

Example:

{ event AE_NPC_HURT_INTERACTION_PARTNER 28 "THEM 100" }
AE_NPC_HURT_INTERACTION_PARTNER "<choices> <int>"
Hurt either this character or his partner… and how much (the int).
ME
Hurt this character.
THEM
Hurt the partner.
AE_NPC_SET_INTERACTION_CANTDIE "<bool>"
Set those participating in the interaction to become invincible.
Todo: Which NPC? The partner or this character?
AE_NPC_WEAPON_FIRE "<bool>"
Fire this character's weapon. The bool is whether or not you want him to use the weapon's secondary fire.

Console Variable

Example of ai_debug_dyninteractions debugging information during a dynamic interaction.
Example of ai_debug_dyninteractions debugging information when a NPC is checking for the proper conditions to perform a dynamic interaction
ai_debug_dyninteractions "<int>"
Debug the NPC dynamic interaction system.

If ai_debug_dyninteractions is enabled, an axis will be created at the required relative position and this informaton is printed to the console while testing whether an interaction could start:

DYNINT: (al) testing interaction "alyx_v_zombie_180deg_64"
   al is at: 404.55 -67.75 -115.91
   al distsqr: 0.37 (468.17 -60.77 -115.91), desired: (468.24 -61.37 -115.91)
   Idle_Relaxed_Shotgun_2 Speed: 0.00
   al angle matched: (0.00 186.25 0.00), desired (0.00, 185.72, 0.00)
Tip.pngTip:Setting ai_debug_dyninteractions to 2 and selecting the NPC via npc_select and/or ent_text prints the distance information even if both NPCs are out of range.

If ai_debug_dyninteractions is enabled, this informaton is printed to the console when a NPC begins a dynamic interaction:

npc_alyx(al) starting dynamic interaction "alyx_v_zombie_180deg_64" with npc_citizen(dude2).
 - Core sequence: alyx_zombie_fight2

See also