Lesson 9 of 10
Calculating damage
- 14 min
- 6 checks
- 3 hints
- Go to task
Goal
Armor, critical hits and dying only once
Explanation
Every hit in a combat game goes through the same steps. It starts with the attacker's power, then there's a chance of a critical hit that doubles that power, and then the target's armor is subtracted. If you forget that the armor can be bigger than the power, you get negative damage, and the hit heals whoever it lands on.
The function never calls math.random directly. Its source of randomness arrives in the rng parameter: in the game you pass math.random itself, and in a check you pass a function that returns whatever value you choose, so you can test critical hits and everything else with a result that never changes. A critical hit happens when rng() < critChance, so a chance of 0 never gives a critical hit and a chance of 1 always does.
Be careful with death. The line if target.hp <= 0 then onDeath(target) end calls onDeath on every hit that lands on the corpse, so the loot drops twice and the kill counts twice, and you can run the code to see it happen. Death is a transition from alive to dead that happens exactly once. Health is also clamped between 0 and maxHp, so it never drops below zero, and healing never pushes it above the maximum.
Your task
Fix rollDamage(attacker, target, rng) so it returns the damage along with true or false depending on whether the hit was critical. A critical hit doubles power before armor is subtracted, and the damage is never less than zero. Then fix changeHp(target, delta, onDeath) so it adds delta (which is negative for damage), clamps the health between 0 and maxHp, and calls onDeath(target) exactly once, when the health goes from a positive number to zero.
Checks
6 checks- Armor is subtracted from the power
- A critical hit doubles the power before armor is subtracted
- A chance of 0 never gives a critical hit and a chance of 1 always does
- Armor bigger than the power doesn't give negative damage
- Health stays between 0 and maxHp
- Death happens only once