| 1558 | void BattleUnit::addFatalWound(BodyPart fatalWoundPart) { fatalWounds[fatalWoundPart]++; } |
| 1559 | |
| 1560 | void BattleUnit::applyDamageDirect(GameState &state, int damage, bool generateFatalWounds, |
| 1561 | BodyPart fatalWoundPart, int stunPower, |
| 1562 | StateRef<BattleUnit> attacker, bool violent) |
| 1563 | { |
| 1564 | |
| 1565 | // Just a blank value for checks (if equal to this means no event) |
| 1566 | static auto NO_EVENT = GameEventType::AgentArrived; |
| 1567 | |
| 1568 | if (isDead()) |
| 1569 | { |
| 1570 | return; |
| 1571 | } |
| 1572 | if (generateFatalWounds && agent->type->immuneToFatalWounds) |
| 1573 | { |
| 1574 | generateFatalWounds = false; |
| 1575 | } |
| 1576 | |
| 1577 | bool wasConscious = isConscious(); |
| 1578 | bool fatal = false; |
| 1579 | |
| 1580 | auto eventType = NO_EVENT; |
| 1581 | // Deal stun damage |
| 1582 | if (stunPower > 0) |
| 1583 | { |
| 1584 | stunDamage += clamp(damage, 0, std::max(0, stunPower + agent->getMaxHealth() - stunDamage)); |
| 1585 | } |
| 1586 | // Deal health damage |
| 1587 | else |
| 1588 | { |
| 1589 | bool lessThanOneThird = agent->modified_stats.health * 3 / agent->current_stats.health == 0; |
| 1590 | agent->modified_stats.health -= damage; |
| 1591 | agent->modified_stats.loseMorale(damage * 50 * (15 - agent->modified_stats.bravery / 10) / |
| 1592 | agent->current_stats.health / 100); |
| 1593 | eventType = (agent->modified_stats.health * 3 / agent->current_stats.health == 0) && |
| 1594 | !lessThanOneThird |
| 1595 | ? GameEventType::AgentBadlyInjured |
| 1596 | : GameEventType::AgentInjured; |
| 1597 | } |
| 1598 | |
| 1599 | // Generate fatal wounds |
| 1600 | if (generateFatalWounds && damage > agent->current_stats.health / 8 && |
| 1601 | randBoundsExclusive(state.rng, 0, 100) < 100 * damage / agent->current_stats.health) |
| 1602 | { |
| 1603 | addFatalWound(fatalWoundPart); |
| 1604 | eventType = GameEventType::AgentCriticallyWounded; |
| 1605 | fatal = true; |
| 1606 | } |
| 1607 | |
| 1608 | // Die or go unconscious |
| 1609 | if (isDead()) |
| 1610 | { |
| 1611 | eventType = NO_EVENT; // cancel event on death |
| 1612 | die(state, attacker, violent); |
| 1613 | return; |
| 1614 | } |
| 1615 | else if (!isConscious() && wasConscious) |
| 1616 | { |
| 1617 | eventType = NO_EVENT; // cancel event on falling down |
no test coverage detected