Skip to content

In Depth Guide

Gianluca edited this page May 18, 2022 · 2 revisions

Constant Factors

Some values presented in .ndf files need to be multiplied by a constant factor. I know of two constants so far that are defined in GDConstantes.ndf:

  • MultiplicateurMetreRTSVersDistanceFeedbackTactique: 1.0 div 2.83 — Needs to be multiplied with the distance to receive accurate results. E.g. 6000 m * (1.0 / 2.83) = 2120 m
  • MultiplicateurMetreRTSVersVitesseTactiquePourVehicule: 0.45 div 1.0 — Needs to be multiplied with the speed to receive accurate results. E.g. 120 km/h * (0.45 / 1.0) = 54 km/h

Damage Calculation

The unit's health pool is defined by MaxDamages in UniteDescriptor.ndf. It does not matter if HE or Penetration damage is dealt, ultimately ever damage type is converted into damage and subtracted from one and the same health pool (MaxDamages).

Ammunition

We will be looking at Arme in Ammunition.ndf. This variables has two parts: Family and Index. The Family defines which damage type is being dealt. Index on the other hand describes the weapon's 'power'. Please notice that Index does not exactly mean the damage output, hence I used 'power', it is more of a variable used in the damage calculation. Usually you can read Arme out directly, but if your ammunition type is kinetic AP, you absolutely need to adjust the Index first because kinetic shells lose power over distance. Consult this chapter to find out whether you are using kinetic AP and how you would go about adjusting the Index.

Ultimately, Arme in Ammunition.ndf defines which damage scheme is being used by referencing another file called DamageResistance.ndf. In there a giant, overwhelming, but very important table can be found: It lists every damage outcome of every weapon versus every armor:

  • Column: Holds all damage types (Referenced by the before seen variable Arme)
  • row: Holds the armor type

Armor

As you see we need to figure out against which type of armor we are going up against before we are able to read out the table. For every unit armor is individually defined in UniteDescriptor.ndf by the variables ArmorDescriptorFront, ArmorDescriptorSides, ArmorDescriptorRear and ArmorDescriptorTop. These strings are referencing ArmorDescriptor.ndf, which translates them to the row names of the giant table in DamageResistance.ndf.

The following armor types are actively being used by WARNO.

  • ArmorDescriptor_Batiment_1: Used for buildings
  • ArmorDescriptor_Infanterie_1: Used for Infantry; Can't receive armor-piercing (AP) damage, therefore in-game armory shows zero armor. However, there are multiple damage reductions present against various non-AP ammunition types.
  • ArmorDescriptor_Vehicule_1: Used for vehicles; equivalent to ArmorDescriptor_Blindage_1.
  • ArmorDescriptor_Vehicule_leger: Used for vehicles; Receives damage from every ammunition. Usually more than double the amount of damage received than ArmorDescriptor_Vehicule_1.
  • ArmorDescriptor_Blindage_1 to ArmorDescriptor_Blindage_20: Used for vehicles; Having blindage over 2 is utterly important: Going from ArmorDescriptor_Blindage_1 to ArmorDescriptor_Blindage_2 mostly halves the AP damage received. After that, it is only decreasing by small amounts.
  • ArmorDescriptor_Helico_1 to ArmorDescriptor_Helico_3: Used on helicopters and planes; ArmorDescriptor_Helico_1 is equivalent to ArmorDescriptor_Blindage_1. Using ArmorDescriptor_Helico_2 at least halves the damage received. After that, it is also only decreasing by small amounts.

Calculation

We have the row, defined by Arme in DamageResistance.ndf, and the newly acquired column, defined in UniteDescriptor.ndf and translated in ArmorDescriptor.ndf. This enables us to pin-point one cell of this giant table.
To conclude the damage calculation, retrieve the cell's value and multiply it with PhysicalDamages in Ammunition.ndf to get the actual damage dealt which will be subtract from the opponent's health pool.

Damage Reduction for Kinetic Armor-Piercing (AP)

We need to consult Ammunition.ndf to check whether we are dealing with kinetic AP. For this to be true, the Family in the variable Arme needs to be set to ap and PiercingWeapon must be set to True. If we are, we need to take its damage loss over range into consideration. In the in-game armory, the AP damage value is given at the weapon's maximum range. However, in Ammunition.ndf the AP damage value is given at point-blank range.

AP_damage = AP_damage_point_blank - (range / factor)

  • AP_damage: Resulting AP damage
  • AP_damage_point_blank: AP damage at point-blank equivalent to the index defined in varibale Arme
  • range: Range to the enemy
  • factor: Defined as the amount of AP damage decrease over a given range. To find this value we need to look at to what DamageTypeEvolutionOverRangeDescriptor is pointing to in DamageStairTypeEvolutionOverRangeDescriptor.ndf. For now, however, it is set to 1 AP damage reduction every 175m or 700m.

If you want to reproduce the values shown in the in-game armory, you would exchange range with the weapon's maximum range defined by PorteeMaximale. Be aware, that this value is given in metre, so it has to be multiplied with the corresponding constant factor.

Accuracy

Accuracy is defined as the probability of landing a successful shot on an enemy unit. Be aware that this whole accuracy system is not yet understood fully and assumptions are being made.
To start off with a fact, HitRollRuleDescriptor in Ammunition.ndf describes the accuracy for each ammunition type individually. This descriptor consists of:

  • BaseCriticModifier
  • BaseEffectModifier
  • BaseHitValueModifiers
  • HitModifierList

My best guess is that BaseCriticModifier and BaseEffectModifier are only used for the probability of triggering critical effects like "reseting targeting computer" and so on. We will ignore them both for now. What we are really interested in is BaseHitValueModifiers and HitModifierList.

Now, for every shot a dice is rolled which will define if this particular shot is a hit or a miss. Just a random number would be too boring, we want to spice up the outcome with some parameters. My understanding is that HitModifierList is exactly that: Parameters for the dice roll. This list consists of the following items: Precision, DistanceToTarget, SuccesiveShots and Suppress. Now, what do these mean? Do note though, these are pure guesses.

  • Precision: It think it is the value when active BaseHitValueModifiers are summed up. Basically this is the base chance of a hit. If the target has Electronic countermeasures (ECM), subtract its value from the base hit chance.
  • DistanceToTarget: In HitRollConstants.ndf there is a list called RangeModifiersTable. It might state how to translate the distance to this parameter’s value. First off, you would calculate distance_to_target / weapon_maxRange to get a ratio which needs to be plugged into the left side of the list. Read out the corresponding right side to get the value for this parameter. So if the target is close to the attacker, it will yield a higher parameter value.
  • SuccesiveShots: There is a list in HitRollConstants.ndf called SuccessiveHitModifiersTable. This parameter will yield 0 if the target has not been hit yet, 1 for the first successive shot and 2 for every greater successive shot count.
  • Suppress: Current suppress damage this unit has.

In HitRollConstants.ndf a developer described the dice roll calculation to be: Success if roll > RollSuccessThreshold - modifiersum. I interpret this to be: Hit if random_generated_number (RNG) > RollSuccessThreshold - sum_of_every_parameter_in_HitModifierList

If you look closely into the HitRollConstants.ndf, you will notice three types of dice rolls: Hit, Pierce and critic:

  • Hit: Describes the dice roll for the hit probability we just studied above.
  • Pierce: Describes the dice roll for the probability that an kinetic AP ammunition will pierce through armor. However, there is not much else known about this dice roll for now.
  • Critic: Describes the dice roll for the probability that this shot will trigger critical effects which will render units useless for a given time.

Currently, the only way units differ from one another is through EBaseHitValueModifier/Idling and EBaseHitValueModifier/Moving of BaseHitValueModifiers in Ammunition.ndf. These values are the ones which represent the unit's Accuracy reading in the armory. However, be aware that the accuracy is displayed per salvo. You would need to multiply these values with NbTirParSalves in Ammunition.ndf to get the in-game displayed results.

E.g. ~/DamageTypeEvolutionOverRangeDescriptor_AP1_1Km points to Distance= 175.0, AP= 1.0. In this case the AP damage decreases 1 point every 175m.

Calculate Road Speed

In UniteDescriptor.ndf there are values called VitesseCombat and RealRoadSpeed which are not being used. Instead, we should use MaxSpeed which represents the off-road speed. Compute (MaxSpeed + MaxSpeed * SpeedBonusOnRoad) * MultiplicateurMetreRTSVersVitesseTactiquePourVehicule to get the true road speed.

Calculate Autonomy

Autonomy states how far a unit can move until it runs out of fuel. In previous titles, this was measured in seconds, however, in WARNO it is specifically stated in kilometres. For planes, Autonomy is equivalent to their FuelMoveDuration. For ground units, the following calculation holds very well. Be aware that this calculation was created using multiple results and searching a common pattern, hence the strange factor. Round up to the nearest integer if the first decimal place of the result is bigger than 5.

Autonomy = MaxSpeed * FuelMoveDuration * 0.0000975

Experience & Veterancy

What experience scheme is currently being used can be seen under ExperienceLevelsPackDescriptor in UniteDescriptor.ndf. This string is a reference to ExperienceLevels.ndf where all schemes are defined. However, at the moment every unit uses the following experience scheme:

  • Level 0 (POOR): Time in-between salves = 115%, Precision = -25, Suppress Damage = 125%
  • Level 1 (TRAINED): Everything at standard
  • Level 2 (VETERAN): Time in-between salves = 85%, Precision = +15, Suppress Damage = 75%
  • Level 3 (ELITE: Time in-between salves = 66%, Precision = +25, Suppress Damage = 50%

Furthermore, only armed units can gain Experience (described by CanWinExperience).
As outlined in Experience.ndf, ExperienceGainBySecond and ExperienceMultiplierBonusOnKill are set to 0 and 1 equivalently. This means, at least for now, units are either not able to level up or they only gain experience by killing.

Stress, Suppression, Cohesion and Morale

Stress and suppression are one and the same variable. In-game it is called stress and in the .ndf files it is mostly called suppression. Unlike Wargame: Red Dragon, this value is not shown in the WARNO UI. Instead, the current cohesion level is displayed.
Moral is poorly understood. The fact that it is only non-zero for planes makes it hard to believe that it is a system that has any impact in-game, if any. It might very well be a leftover from a previous game.
Cohesion is a direct effect of suppression. There are four levels which are described in EffetsSurUnite.ndf. Each comes with its own debuffs.

Which suppression system is being used is individually defined in UniteDescriptor.ndf under SuppressDamageLevelsPack. This variable is a reference to DamageLevels.ndf in which the following can be found: Every system has six different suppression levels (calm, engaged, worried, stressed, shaken and (panicked or pinned)), being triggered at different suppress damage levels defined by Value. Note that Value is most likely only the modifier for another variable, like the maximum amount of suppression damage. Each suppression level comes with custom debuffs: Morale is being modified (MoralModifier), chance of hitting the target is decreased (HitRollModifier) and EffectsPacks are being added. EffectsPacks can hold multiple effects, but the most important is the cohesion being changed. Its debuffs are outlined in EffetsSurUnite.ndf.

Suppression damage decreases over time. The following variables describe this behavior. They can be found in UniteDescriptor.ndf for every unit and are all references to DamageModules.ndf.

  • GroundUnit_SuppressDamagesRegenRatioList: Array detailing how much suppression damage is being recovered over a given time period: [Time, Suppression damage recovered]
  • GroundUnit_SuppressDamagesRegenRatioOutOfRange: How many seconds need to pass until suppression damage recovery starts.
  • GroundUnit_MaxSuppressionDamages: Maximum suppression damage that can be received, however, it is unknown what happens if this threshold is being exceeded.

SuppressDamages in Ammunition.ndf describes how much suppress damage a weapon can generate. I strongly believe that the amount of suppress damage received is the same for all units because MaxSuppressionDamages is set to 1000 for every unit type and there is no multiplier mentioned in UniteDescriptor.ndf whatsoever.