This section explains how the format of the Reactions XML files, the properties it can use, how to use them, etc. Think of it as a reference guide while editing the HitDeathReactions system XML files.
This document will explain XML properties frequently. The format used for those properties is as follows:
<property_name>
<property_type> (<property_format>) <description>If the color of a property is red, it means that property is of advanced or marginal use. I don't expect them to be used a lot, and usually only by programmers or technical staff for test purposes.
You can find the reactions XML files in this location: GameData/Libs/HitDeathReactionsData/*.xml
An entity will use a given .xml if that file is specified on its fileHitDeathReactionsParamsDataFile
property (by default it will be Libs/HitDeathReactionsData/HitDeathReactions_Default.xml
)
Each reaction file has five main sections:
<DeathHitReactionsParams>
and </DeathHitReactionsParams>
), it contains the other four important sections:All sections are not mandatory (but of course, having an empty file won't do a lot, will it?). Below you will find more information about them.
This section is usually at the beginning of the file, outside the root element (which is <DeathHitReactionsParams>
) and starts with the tag <!DOCTYPE
. This section is not specific of the HitDeathReactions system, but a section part of the XML standard that can be on any XML file.
It's used on the HitDeathReactions XML files to define XML Entities, which are basically macros that facilitates editing. e.g.:
<?xml version="1.0"?>
<!-- DTD (Document Type Definition) for defining XML Internal General Entities. Think of them as macros -->
<!DOCTYPE HitDeathReactions_Example [
<!ENTITY Legs '
<Part value="L Leg"/>
<Part value="R Leg"/>
'>
<!-- Lower body part names -->
<!ENTITY LowerBody '
<Part value="Pelvis"/>
&Legs;
'>
]>
<DeathHitReactionsParams>
<!-- HITS -->
<HitReactionParams>
<HitReactionParam animName="LowerBodyImpact">
<AllowedParts>
<!-- To use XML Entities put the name between the characters & and ; like &this;, it will be the same
as if you had typed the same text you wrote on the Entity definition -->
&LowerBody;
</AllowedParts>
</HitReactionParam>
</HitReactionParams>
<!-- DEATHS -->
<DeathReactionParams>
<DeathReactionParam animName="LowerBodyDeath">
<AllowedParts>
<!-- If we change the contents of the LowerBody entity, the changes will apply on every use of that
entity, which is very useful while editing these files -->
&LowerBody;
</AllowedParts>
</DeathReactionParam>
</DeathReactionsParams>
</DeathHitReactionsParams>
This section allows to configure some aspects of the system for the character using the file by assigning some values to some attributes of the element <HitDeathReactionsConfig>.
These are the attributes you can use:
All properties are optional, if not specified they will take their default value.
<?xml version="1.0"?>
<!-- Omitted DTD -->
<DeathHitReactionsParams>
<HitDeathReactionsConfig collisionBone="Spine02" collisionRadius="1"
collisionVerticalOffset="0.8"
maximumReactionTime="4.5"/>
<!-- Omitted Hit/Death/Collision reactions sections -->
</DeathHitReactionsParams>
This section is delimited by the tags <HitReactionParams>
and </HitReactionParams>
. It can contain any number of reactions, which are delimited by the tags <HitReactionParam>
and </HitReactionParam>
.
When a hit is detected the system starts evaluating reaction by reaction, in the order the are defined on the XML file. If one reaction is validated, it's executed and the process finalizes.
More details about their attributes and parameterization in the Reactions properties section
This section is delimited by the tags <DeathReactionParams>
and </DeathReactionParams>
. It can contain any number of reactions, which are delimited by the tags <DeathReactionParam>
and </DeathReactionParam>
.
When a kill is detected the system starts evaluating reaction by reaction, in the order the are defined on the XML file. If one reaction is validated, it's executed and the process finalizes.
The main difference between Death Reactions and Hit Reactions is that the execution of a Death Reaction always ends enabling the ragdoll in the character.
More details about their attributes and parameterization in the Reactions properties section
This section is delimited by the tags <CollisionReactionParams>
and </CollisionReactionParams>
. It can contain any number of reactions, which are delimited by the tags <CollisionReaction>
and </CollisionReaction>
.
Some Hit and Death reactions detect collisions with the environment while executing (specifically those with the ragdollOnCollision
or reactionOnCollision
property set, see the Reactions properties section).
If a collision is detected it can trigger one of these "Collision Reaction". These reactions are not validated, instead they are chosen based on the reactionOnCollision
property value or the parameter on some AnimationEvents (ReactionOnCollision) launched during the reaction.
If a Collision Reaction is triggered from a Death Reaction it will always end enabling the ragdoll in the character.
More details about their attributes and parameterization in the Reactions properties section.
Reactions do two important things:
A reaction can only be executed if it's valid. That is, if any of its validation blocks is valid, which means the requirements/constraints of that validation block fulfill the hit context.
Therefore a reaction can have several validation blocks or just one. You can specify several validation blocks by enclosing them inside the <ValidationSection>
element.
I'll illustrate that with examples so it's easier to understand:
<HitReactionParam animName="smallCaliberReaction">
<AllowedProjectiles>
<Projectile value="SMGBullet"/>
<Projectile value="PistolBullet"/>
</AllowedProjectiles>
</HitReactionParam>
... is equivalent to this version:
<HitReactionParam animName="smallCaliberReaction">
<ValidationSection>
<Variation>
<AllowedProjectiles>
<Projectile value="SMGBullet"/>
<Projectile value="PistolBullet"/>
</AllowedProjectiles>
</Variation>
</ValidationSection>
</HitReactionParam>
In both previous examples the <AllowedProjectiles>
element is the only constraint of the only validation that reaction is using.
Now imagine you want the animation "smallCaliberReaction" to be triggered also when the hit type is "collision" and the damage is less than 100. You could do something like this:
<HitReactionParam animName="smallCaliberReaction">
<ValidationSection>
<Variation>
<AllowedProjectiles>
<Projectile value="SMGBullet"/>
<Projectile value="PistolBullet"/>
</AllowedProjectiles>
</Variation>
</ValidationSection>
</HitReactionParam>
<HitReactionParam animName="smallCaliberReaction" maximumDamage="100">
<AllowedHitTypes>
<HitType value="collision"/>
</AllowedHitTypes>
</HitReactionParam>
But generally is better if you limit the number of reaction blocks as much as possible. Instead, you could use the equivalent (and better) following version:
<HitReactionParam animName="smallCaliberReaction">
<ValidationSection>
<Variation>
<AllowedProjectiles>
<Projectile value="SMGBullet"/>
<Projectile value="PistolBullet"/>
</AllowedProjectiles>
</Variation>
<Variation maximumDamage="100">
<AllowedHitTypes>
<HitType value="collision"/>
</AllowedHitTypes>
</Variation>
</ValidationSection>
</HitReactionParam>
Each validation process can be customized (using the validationFunc
property, see below) or just use the default C++ validation code (if the validationFunc
property isn't specified), which is the most used approach.
Once a reaction is validated, the next step is to execute it. The execution process can be customized (using the reactionFunc
property, see below) or just use the default C++ execution code (if the reactionFunc
property isn't specified), which usually translates into playing an animation.
The default C++ validation code uses some properties that specify when a reaction is valid based on the context of the hit/kill. You can see them as constraints for the reaction to be selected.
If a constraint is not present, that means it won't have any effect (e.g., a reaction without any validation property/constraint will always be valid). These are the properties currently used for the Default Validation code:
You can easily see the speed a character has by typing g_hitDeathReactions_debug 1 on the console and looking to the speedFlat value. You can find the speed values an AI uses if you look into its AI script file. Look for the AIMovementSpeeds table.
<!-- This reaction will be executed when the hit causes the health of the character to go past 75% of health, 50% of health, 1500 health points and 25% of health. The order in which you define them is not relevant -->
<HitReactionParam animName="alienHeavyReaction">
<OnlyWhenPassingHealthThresholds>
<HealthThreshold value="0.75"/>
<HealthThreshold value="0.5"/>
<HealthThreshold value="1500"/>
<HealthThreshold value="0.25"/>
</OnlyWhenPassingHealthThresholds>
</HitReactionParam>
<HitReactionParam animName="halfOfTheTime" probabilityPercent="0.5"/>
<?xml version="1.0"?>
<!-- DTD (Document Type Definition) for defining XML Internal General Entities. Think of them as macros -->
<!DOCTYPE HitDeathReactions_Example [
<!ENTITY StandingStances '
<Stance value="STANCE_STAND"/>
<Stance value="STANCE_RELAXED"/>
<Stance value="STANCE_STEALTH"/>
<Stance value="STANCE_ALERTED"/>
'>
]>
<DeathHitReactionsParams>
<!-- Omitted HitDeathReactions config section -->
<HitReactionParams>
<HitReactionParam animName="standingHitReaction">
<AllowedStances>
&StandingStances;
</AllowedStances>
</HitReactionParam>
<HitReactionParam animName="crouchHitReaction">
<AllowedStances>
<Stance value="STANCE_CROUCH"/>
</AllowedStances>
</HitReactionParam>
</HitReactionParams>
<!-- Omitted Death/Collision reactions sections -->
</DeathHitReactionsParams>
STANCE_PRONE, STANCE_CROUCH, STANCE_STAND, STANCE_RELAXED, STANCE_ALERTED, STANCE_STEALTH, STANCE_LOW_COVER, STANCE_HIGH_COVER, STANCE_SWIM, STANCE_LASTSTAND
<HitReactionParam animName="explosionReaction">
<AllowedHitTypes>
<HitType value="frag"/>
<HitType value="explosion"/>
</AllowedHitTypes>
</HitReactionParam>
melee, collision, frag, normal, repair, bullet, gaussbullet, fire, stealthKill, silentMelee, tac, fall, event, punish, punishFall, avmine, moacbullet, scout_moac, aacannon, emp, pingerPing, kvolt, impulse_hit, heavyBullet, HMG, stamp, mike_burn, alienDropPodBounce, explosion, disableCollisions
<HitReactionParam animName="smallCaliberReaction">
<AllowedProjectiles>
<Projectile value="SMGBullet"/>
<Projectile value="PistolBullet"/>
</AllowedProjectiles>
</HitReactionParam>
<HitReactionParam animName="gaussHitReaction">
<AllowedWeapons>
<Weapon value="Gauss"/>
</AllowedWeapons>
</HitReactionParam>
<DeathReactionParam animName="legsDeathReaction">
<AllowedParts>
<Part value="L Leg"/>
<Part value="R Leg"/>
</AllowedParts>
</DeathReactionParam>
An easy way to obtain the name of the bones or attachments you are interested on (at least easier than ask a technical artist) would be to type i_giveItem debugGun on the console, and then aim to the character. The part or attachment you are aiming at will be displayed on a text like this: "partId: 77 (Bip01 Head)". Bip01 Head would be what you are looking for.
The default C++ execution code can cause a diverse range of effects, parameterized on its properties. If a property is not present, that means it won't cause any effect.
A reaction without any execution property won't do anything and will be considered as failed, so the game code will run the fallback code (a physic impulse on hits, ragdoll + impulses on deaths). That could be useful for some situations (there are already several reactions doing it).
These are the properties currently used for the Default Execution code:
<!-- This reaction will play an additive animation in the layer 5 (I recommend using that layer or higher for partial/additive anims). In an hypothetical case, the system will behave like this:
(list is shuffled)
1st hit: Plays "stand_tac_hitShoulder_rifle_add_3p_01"
2nd hit: Plays "stand_tac_hitShoulderHMG_rifle_add_3p_02"
3rd hit: Plays "stand_tac_hitBelly_rifle_add_3p_01"
4th hit: Plays "stand_tac_hitShoulderHMG_rifle_add_3p_03"
5th hit: Plays "stand_tac_hitShoulderHMG_rifle_add_3p_01"
(list is shuffled)
6th hit: Plays "stand_tac_hitBelly_rifle_add_3p_01"
...
It won't matter which character has received the hit, the list is global to all the characters using the same reactions (so if you shot character A and then shot character B and both trigger the same reaction you can be sure they won't play the same animation in a row) -->
<HitReactionParam>
<ReactionAnim additive="1" layer="5">
<AnimNames>
<AnimName name="stand_tac_hitBelly_rifle_add_3p_01"/>
<AnimName name="stand_tac_hitShoulder_rifle_add_3p_01"/>
<AnimName name="stand_tac_hitShoulderHMG_rifle_add_3p_0" variants="3"/>
<!-- variants="3" above is equivalent to:
<AnimName name="stand_tac_hitShoulderHMG_rifle_add_3p_01"/>
<AnimName name="stand_tac_hitShoulderHMG_rifle_add_3p_02"/>
<AnimName name="stand_tac_hitShoulderHMG_rifle_add_3p_03"/>
-->
</AnimNames>
</ReactionAnim>
</HitReactionParam>
<DeathReactionParam animName="death_reaction_anim" />
... is equivalent to:
<DeathReactionParam>
<ReactionAnim>
<AnimNames>
<AnimName name="death_reaction_anim"/>
</AnimNames>
</ReactionAnim>
</DeathReactionParam>
If both animName and ReactionAnim are used, animName will be ignored.
<!-- if shot from the left while running the reaction will set the "signal" input to "hitRunForward" and will set the variation input "stance" to "stand", the variation input "hitName" to "lft_torso_3p" and the variation input "variant" to "01" -->
<HitReactionParam shotOrigin="left" minimumSpeed="&RunningSpeed;">
<AnimGraphReaction inputValue="hitRunForward">
<Variations>
<Variation name="stance" value="stand" />
<Variation name="hitName" value="lft_torso_3p" />
<Variation name="variant" value="01" />
</Variations>
</AnimGraphReaction>
</HitReactionParam>
<HitDeathReactionParams>
<!-- HIT REACTIONS -->
<HitReactionParams>
<!-- If the collision sphere detects a collision with the environment, the system will trigger the collision reaction number 2 (front collision, see below) -->
<HitReactionParam minimumSpeed="&RunningSpeed;" movementDirection="forward" reactionOnCollision="2">
<AnimGraphReaction inputValue="hitRunForward">
<Variations>
<Variation name="stance" value="stand" />
<Variation name="hitName" value="torsoStumble" />
<Variation name="variant" value="02" />
</Variations>
</AnimGraphReaction>
</HitReactionParam>
<!-- If the collision sphere detects a collision with the environment, the system will trigger the collision reaction number 3 (right side collision, see below) -->
<HitReactionParam minimumSpeed="&RunningSpeed;" movementDirection="right" reactionOnCollision="3">
<AnimGraphReaction inputValue="hitStrafe">
<Variations>
<Variation name="hitName" value="Rgt_all_torso" />
</Variations>
</AnimGraphReaction>
</HitReactionParam>
<HitReactionParams>
<!-- COLLISION REACTIONS -->
<CollisionReactionParams>
<!-- THE FIRST REACTION COLLISION SHOULD ALWAYS BE A FALL AND PLAY ONE, OTHERWISE ragdollOnCollision
PROPERTY WON'T TRIGGER ANY RAGDOLL IN HIT REACTIONS -->
<!-- Fall and Play collision -->
<CollisionReaction reactionFunc="FallAndPlay_Reaction" />
<!-- front collision -->
<CollisionReaction animName="stand_tac_hitColl_front_torso_3p_01" snapOrientationAngle="0">
</CollisionReaction>
<!-- right side collision -->
<CollisionReaction animName="stand_tac_hitColl_rgt_torso_3p_01" snapOrientationAngle="90">
</CollisionReaction>
<!-- ... -->
</CollisionReactionParams>
</HitDeathReactionParams>
If the animation being played during the reaction execution uses ReactionOnCollision animation events it will be able to enable/disable/modify the collisions with the environment. The custom parameter of the animation event will change the value of the reactionOnCollision property on the reaction. So triggering a ReactionOnCollision animation event with "0" as custom parameter will disable collisions with environment, with "2" will enable it and make it trigger the second collision reaction defined, etc.
Some reaction don't even use the reactionOnCollision property, but rely on the animation to set the collision with the environment itself.
On Crysis 2, the typical indexes for the collision reactions are as follow:
<HitReactionParam animName="StumbleForward" ragdollOnCollision="1"/>
... is equivalent to:
<HitReactionParam animName="StumbleForward" reactionOnCollision="1"/>
<DeathReactionParam animName="stand_deathHeavy_front_torso_01" snapOrientationAngle="0" shotOrigin="ahead" ragdollOnCollision="1">
<AllowedHitTypes>
&HeavyHitTypes;
</AllowedHitTypes>
</DeathReactionParam>
<DeathReactionParam animName="stand_deathHeavy_back_torso_01" snapOrientationAngle="180" shotOrigin="behind" ragdollOnCollision="1">
<AllowedHitTypes>
&HeavyHitTypes;
</AllowedHitTypes>
</DeathReactionParam>
<validationsection>
as much as possible.g_hitDeathReactions_reload
command on each change and you'll be done in a few minutes.