summaryrefslogtreecommitdiff
path: root/actions.py
diff options
context:
space:
mode:
authorSupremist <sergkarv@gmail.com>2025-10-29 22:58:37 +0200
committerSupremist <sergkarv@gmail.com>2025-10-29 22:58:37 +0200
commit9fa4cfbe2f948f4067ca1572bbc5dbfab678e7da (patch)
tree590bb32b5a11dd2f3b5f9a0999d5e809ad1f3749 /actions.py
parent0ada03ebf6a879e0a77475d525141d1090bcd634 (diff)
downloadpf2e_calc-9fa4cfbe2f948f4067ca1572bbc5dbfab678e7da.tar.xz
pf2e_calc-9fa4cfbe2f948f4067ca1572bbc5dbfab678e7da.zip
Add Attack action
Diffstat (limited to 'actions.py')
-rw-r--r--actions.py75
1 files changed, 75 insertions, 0 deletions
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
+