This is a revised version of the original design I outlined HERE. I appreciate the feedback from that thread, and I'm going to provide some examples for how my proposed system is better than the current system. I have modified my original idea based on new insights after reading Robbie's excellent post HERE. I'm going to skip the math-heavy exposition this time, and just go for the stats.
Preamble: Why it's not as complicated as it seems
You may look at this stuff at say, "Wait, aren't you adding a half dozen variables? How can I make sense of all of this? The current system is much simpler." The strange truth is: the current system only seems simple because a lot of the combat variables are hidden from the user. Examples of these currently in the game include:
- % chance to bypass armor completely
- % chance to do double
- Multiplier for counterattack damage
- % chance to dodge an incoming attack
All of these factor into the "simple" Attack/Defense system they currently have.
What's wrong with the old system?
This has been done to death, but the gist is this:
- Evenly matched opponents ( X Attack vs X Defense ) have an expected result of MISS. This prolongs combat needlessly, since half of your actions would have no effect. We're not simulating second-by-second combat in this game - it's a game about both champions and armies. 100 soldiers don't charge 100 peasants and "miss," even if they do poorly.
- The damage done by X Attack vs. X Damage doesn't scale well as X increases.
My Assumptions/Beliefs
My whole model is based around the idea of expected final damage when two units clash. I specifically want to avoid "stalemate" type results. As for champions vs. units, I believe the following:
- A troop of weak units should still be able to (somwhat) damage a single, high armor target.
- Champions are best suited to fighting other champions and monsters. In high fantasy, a single warrior doesn't often defeat large armies singlehandedly through combat skills alone - though they do it frequently with magic...
- Sovereigns should be casting spells or acting like a champion (above). Their spells should be effective against both single targets and troops, with some better for one or the other.
- If a large group surrounds a champion, they could eventually just dogpile him. Their numbers should count.
My model
None of these attributes is "multiplied by the troop size" for the UI. They are what they are.
ATTACK: This is your ability to successfully hit opponents in combat. It incorporates ideas about weapon skill, attack speed and more into one number.
DAMAGE: This is the average damage you do to an unarmored opponent when you hit him.
DEFENSE: This is your ability to "not get damaged at all" when someone attacks you. This incorporates dodging, parrying, deflecting, blocking, etc.
ARMOR: This is the average damage your armor soaks when you actually get hit.
SPLASH: This represents the number of units you can hit with a single attack. This is 1 by default. If you have a weapon capable of cleaving through multiple foes, this could be 2 or even 3. If you're breathing fire, this could be as high as 6 or 8. If your "attack" was really a fireball cast on a single unit, it could easily be 20.
* the actual effect of splash in the mechanics below don't make "splash" weapons more effective against single troops. The bonus only comes into play when you're facing a group.
Damage Calculation
** Don't worry about the apparent complexity of the calculation. This is not happening in a large RTS. This is a couple of floating point operations performed to resolve a single unit v unit attack - which is nothing. Additionally, it's the kind of thing that the computer can easily show you odds/expected damage for (think HOMM).
For the resolution of an attack, the final damage is derived as follows:
** FEEL FREE TO SKIP THIS PART
OverwhelmEffect = MAX( 1.0, Attacker.TroopSize / Defender.TroopSize)
RelativeAttack = OverwhelmEffect * Attacker.Attack
HitRatio = RelativeAttack / (RelativeAttack + Defender.Defense)
SplashEffect = MIN( Defender.TroopCount, Attacker.Splash )
ActualHits = HitRatio * Attacker.TroopSize * SplashEffect * Attacker.Attack
Penetration = Attacker.Damage / (Attacker.Damage + Defender.Armor)
DamagePerHit = Attacker.Damage * Penetration
ActualDamage = ActualHits * DamagePerHit
How it plays out in simulations
For each example, I aggregated the results of 500,000 simulated combats to the death. For each attack action, effective Attack and Defense were varied randomly around the unit's base value with a normal distribution limited over the range +/- 60%. Assume SPLASH = 1 unless otherwise specified. The Attacker has the first turn, but becomes the defender on even turns.
Example: A "sniff test."
ATTACKER: 1 Warrior: 1 Atk, 1 Dmg
DEFENDER: 1 Peasant: 0 Def, 0 Armor
Result: Warrior hits the peasant for 1 damage. That seems right.
Increasing Attack or Damage for the Warrior increases the damage accordingly. Giving the Warrior some amount of SPLASH > 1 has no effect, since he's fighting one troop.
Example: Two evenly matched groups of warriors
Warrior: 5 Attack, 2 Damage, 5 Defense, 2 Armor, 10 health each
ATTACKER: 10 Warriors (100 total health)
DEFENDER: 10 Warriors (100 total health)
Average Round 1 Result:
Attacker hits for 25 points of damage.
Defender retaliates for 20 points of damage
Aggregate Results:
Average total rounds: 6.77
Attacker wins 57.8% of encounters with 35 health remaining.
Defender wins 42.2% of encounters with 30 health remaining.
Example: Outnumbered, stronger defenders
Royal: 8 Attack, 2 Damage, 7 Defense, 3 Armor, 10 health each
Warrior: 5 Attack, 2 Damage, 5 Defense, 2 Armor, 10 health each
ATTACKER: 20 Warriors (200 total health)
DEFENDER: 10 Royals (100 total health)
Average Round 1 Result:
Attacker hits for 28.3 points of damage.
Defender retaliates for 46.7 points of damage
Aggregate Results:
Average total rounds: 2.93
Attacker wins 99.98% of encounters with 142 health remaining.
Defender wins 0.02% of encounters with 18 health remaining.
Example: Outnumbered, much stronger defenders
Troll: 8 Attack, 4 Damage, 2 Defense, 8 Armor, 18 health each, ** 3 SPLASH **
Warrior: 5 Attack, 2 Damage, 5 Defense, 2 Armor, 10 health each
ATTACKER: 20 Warriors (200 total health)
DEFENDER: 10 Trolls (180 total health)
Average Round 1 Result:
Attacker hits for 28.3 points of damage.
Defender retaliates for 46.7 points of damage
Aggregate Results:
Average total rounds: 1.02
Defender wins 100% of encounters with 147 health remaining.
Example: Fireball spell vs. 12 Warriors
Warrior: 5 Attack, 2 Damage, 5 Defense, 2 Armor, 10 health each
Fireball: 5 Attack, 3 Damage, ** 20 SPLASH **
Average Result: 54 damage
Example: Fireball spell vs. 1 Troll
Troll: 8 Attack, 4 Damage, 2 Defense, 8 Armor, 18 health each, ** 3 SPLASH **
Fireball: 5 Attack, 3 Damage, ** 20 SPLASH **
Average Result: 3 damage
Gnilbert