File Updated: Feb 21, 2007 9:30pm EST
The past couple of weeks I've been investigating how to solve the issue with unit animations.
For those not aware, animation speeds have a very big effect on how fast a unit can kill another.
I've found the solution to balancing the damage rates between units by using the attack delay property.
I've written a program that creates a equalized unit EDU with the only difference between units are the attack delays
ATTACHED is a animation balanced test EDU.
*The attached file should only be used by people trying to balance units.*
Using this file, units should be equally powered.
Note:
1. If you test cavalry vs infantry, make sure you control the cavalry and don't allow them to charge. If they charge, they will destroy the infantry unit.
2. Missile Units have only been balanced in melee
The following example shows that all the important combat variables have been equalized. The attack delay's in bold have been adjusted from emphirical data gathered by using this EDU in order to balance the units.
I didn't have to go through each unit because many units share the same animation.
This data can be gathered using the following files
export_descr_unit.txt
battle_models.modeldb
descr_skeleton.txt
type Highland Nobles
dictionary Highland_Nobles ; Highland Nobles
category infantry
class heavy
voice_type Heavy
banner faction main_infantry
banner holy crusade
soldier Highland_Nobles, 60, 0, 1.0
attributes sea_faring, hide_forest, can_withdraw
formation 1.2, 1.2, 2.4, 2.4, 4, square
stat_health 1, 0
stat_pri 1, 0, no, 0, 0, melee, melee_blade, slashing, sword, 500, 1.0
;stat_pri_ex 0, 0, 0
stat_pri_attr no
stat_sec 0, 0, no, 0, 0, no, melee_simple, blunt, none, 0, 0.35
;stat_sec_ex 0, 0, 0
stat_sec_attr no
stat_pri_armour 0, 0, 0, metal
;stat_armour_ex 5, 7, 0, 0, 4, 0, 0, metal
stat_sec_armour 0, 0, flesh
stat_heat 2
stat_ground 1, -2, 3, 2
stat_mental 15, disciplined, highly_trained
stat_charge_dist 30
stat_fire_delay -2500
stat_food 60, 300
stat_cost 1, 60, 20, 90, 70, 60, 4, 120
armour_ug_levels 2, 3
armour_ug_models Highland_Nobles, Highland_Nobles_ug1
ownership scotland
era 1 scotland
era 2 scotland
;unit_info 14, 0, 9
type Voulgier
dictionary Voulgier ; Voulgier
category infantry
class heavy
voice_type Heavy
banner faction main_infantry
banner holy crusade
soldier Voulgier, 60, 0, 1.0
attributes sea_faring, hide_forest, can_withdraw
formation 1.2, 1.2, 2.4, 2.4, 4, square
stat_health 1, 0
stat_pri 1, 0, no, 0, 0, melee, melee_blade, piercing, axe, 3000, 1.0
;stat_pri_ex 0, 0, 0
stat_pri_attr no
stat_sec 1, 0, no, 0, 0, melee, melee_blade, piercing, axe, 1500, 1.0
;stat_sec_ex 0, 0, 0
stat_sec_attr no
stat_pri_armour 0, 0, 0, metal
;stat_armour_ex 5, 7, 8, 0, 3, 0, 0, metal
stat_sec_armour 0, 0, flesh
stat_heat 2
stat_ground 1, -2, 3, 2
stat_mental 15, disciplined, highly_trained
stat_charge_dist 30
stat_fire_delay -2500
stat_food 60, 300
stat_cost 1, 60, 20, 75, 55, 60, 4, 120
armour_ug_levels 2, 3, 4
armour_ug_models Voulgier, Voulgier_ug1, Voulgier_ug2
ownership france
era 2 france
;unit_info 7, 0, 8
From battle_models.modeldb:
The value in bold are the attack animations.
16 -0.090000004 0 0 -0.34999999 0.80000001 0.60000002
11 swiss_guard
1 4
57 unit_models/_Units/RN_Half_3Q_Plate/swiss_guard_lod0.mesh 121
57 unit_models/_Units/RN_Half_3Q_Plate/swiss_guard_lod1.mesh 900
57 unit_models/_Units/RN_Half_3Q_Plate/swiss_guard_lod2.mesh 2500
57 unit_models/_Units/RN_Half_3Q_Plate/swiss_guard_lod3.mesh 6400 1
12 papal_states
82 unit_models/_Units/RN_Half_3Q_Plate/textures/rn_half_3q_plate_papal_states.texture
76 unit_models/_Units/RN_Half_3Q_Plate/textures/rn_half_3q_plate_normal.texture
48 unit_sprites/papal_states_Swiss_Guard_sprite.spr 1
12 papal_states
73 unit_models/AttachmentSets/Final European Light_papal_states_diff.texture
73 unit_models/AttachmentSets/Final European Light_papal_states_norm.texture 0
1
4 None
20 MTW2_Halberd_Primary
22 MTW2_Halberd_Secondary 1
17 MTW2_Pike_primary 1
17 MTW2_Pike_primary
Those of you interested in the actual animation delays I've found, see below.
/* ------------------------------------------------------ */
/* Mounted Animations Below */
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_HR_Lance";
animationInfo.equalizerDelay = 0;
animationInfo.attackBase = 5;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_HR_Sword";
animationInfo.equalizerDelay = 40000;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_CR_Sword";
animationInfo.equalizerDelay = 40000;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_HR_Mace";
animationInfo.equalizerDelay = 3000;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_HR_Non_Shield";
animationInfo.equalizerDelay = 6000;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_HR_Spear";
animationInfo.equalizerDelay = 40000;
animationInfo.attackBase = 3;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_CR_Spear";
animationInfo.equalizerDelay = 40000;
animationInfo.attackBase = 3;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
/* Mounted Missile Animations Below */
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_HR_Javelin";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 5;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_HR_Crossbow";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 3;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_HR_Bow";
animationInfo.equalizerDelay = 0;
animationInfo.attackBase = 3;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_CR_Bow";
animationInfo.equalizerDelay = 0;
animationInfo.attackBase = 3;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_HR_Pistol";
animationInfo.equalizerDelay = 0;
animationInfo.attackBase = 5;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_CR_Arquebus";
animationInfo.equalizerDelay = 0;
animationInfo.attackBase = 7;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
/* Infantry Animations Below */
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Knifeman";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Fast_Knifeman";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Crew_Bombard";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Crew_Monster_Ribault";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Crew_Cannon";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Crew_Mortar";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Crew_Ribault";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Crew_Culverin";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Crew_Serpentine";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Crew_Basilisk";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Crew_Huge_Bombard";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Elephant_Rockett_Crew";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Elephant_Artillery_Crew";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Ballista";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Catapult";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Trebuchet";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 2;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Mace";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Fast_Mace";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Slow_Mace";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Pike";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Slow_Pike";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Swordsman";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Slow_Swordsman";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Fast_Swordsman";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Non_Shield";
animationInfo.equalizerDelay = 30000;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Non_Shield_Fast";
animationInfo.equalizerDelay = 30000;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
/* Broken 1.1 Animation */
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_2H_Axe";
animationInfo.equalizerDelay = -1500;
animationInfo.attackBase = 5;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Fast_2H_Axe";
animationInfo.equalizerDelay = -1500;
animationInfo.attackBase = 5;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Slow_2HSwordsman";
animationInfo.equalizerDelay = 500;
animationInfo.attackBase = 5;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_2HSwordsman";
animationInfo.equalizerDelay = 500;
animationInfo.attackBase = 5;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Halberd_Primary";
animationInfo.equalizerDelay = 3000;
animationInfo.attackBase = 5;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Halberd_Secondary";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 5;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Spear";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 3;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Fast_Spear";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 3;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
/* Missile Animations Below */
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Fast_Javelin";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 5;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Crossbow";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Fast_Crossbow";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Pavise_Crossbow";
animationInfo.equalizerDelay = 1500;
animationInfo.attackBase = 4;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Bowman";
animationInfo.equalizerDelay = 0;
animationInfo.attackBase = 3;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Fast_Bowman";
animationInfo.equalizerDelay = 0;
animationInfo.attackBase = 3;
animationInfoList.add(animationInfo);
/* ------------------------------------------------------ */
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Fast_Musket";
animationInfo.equalizerDelay = 0;
animationInfo.attackBase = 8;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Fast_Arquebus";
animationInfo.equalizerDelay = 0;
animationInfo.attackBase = 7;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Elephant_Crew";
animationInfo.equalizerDelay = 500;
animationInfo.attackBase = 7;
animationInfoList.add(animationInfo);
animationInfo = new AnimationInfo();
animationInfo.animationName = "MTW2_Handgun";
animationInfo.equalizerDelay = 0;
animationInfo.attackBase = 5;
animationInfoList.add(animationInfo);




