From 9fa4cfbe2f948f4067ca1572bbc5dbfab678e7da Mon Sep 17 00:00:00 2001 From: Supremist Date: Wed, 29 Oct 2025 22:58:37 +0200 Subject: Add Attack action --- actions.py | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 actions.py (limited to 'actions.py') diff --git a/actions.py b/actions.py new file mode 100644 index 0000000..f3cd39c --- /dev/null +++ b/actions.py @@ -0,0 +1,75 @@ +from typing import Any + +from dataclasses import dataclass +from items import Weapon +from game import d, Roll +from character import Character + + +@dataclass +class Attack: + attacker: Character + target: Any + weapon: Weapon + strike_type="melee" + previous_attacks: int = 0 + distance: int = 0 + + def bonus(self): + return self.attacker.attack_bonus(self.weapon, self.strike_type) + self.map() + + def roll(self): + ac = self.target.ac() + return d(20).apply(Roll.check, ac, self.bonus()) + + def strike(self): + def strike_dmg(check): + return self.damage(check) + return self.roll().apply(strike_dmg) + + def damage(self, check=Roll.Success): + persistant_damage_factor = 3 + 1/3 + wp = self.weapon + dmg_bonus = self.attacker.attack_damage_bonus(wp, self.strike_type) + if wp.backstabber: + dmg_bonus += 1 + if wp.potency >= 3: + dmg_bonus += 1 + + if wp.twin and self.previous_attacks > 0: + dmg_bonus += wp.dice_count() + + if check == Roll.Success: + return wp.dice_count() * d(wp.main_die) + dmg_bonus + if check == Roll.Crit: + dmg = None + if wp.fatal is not None and wp.fatal > 0: + dmg = (wp.dice_count() + 1) * d(wp.fatal) + else: + dmg = wp.dice_count() * d(wp.main_die) + dmg = 2 * (dmg+dmg_bonus) + + if wp.deadly is not None and wp.deadly > 0: + dmg += max(1, wp.dice_count()-1) * d(wp.deadly) + + if wp.group == "crossbow": + dmg += persistant_damage_factor * d(8).expected() + elif wp.group == "dart" or wp.group == "knife": + dmg += persistant_damage_factor * d(6).expected() + elif wp.group == "dagger": + dmg += persistant_damage_factor * d(6).expected() + elif wp.group == "pick": + dmg += 2 * wp.dice_count() + + return dmg + return 0 + + def range_penalty(self): + return 0 + + def map(self): + factor = max(0, min(2, self.previous_attacks)) + if self.weapon.agile: + return factor * -4 + return factor * -5 + -- cgit v1.2.3