blob: 9710faa5b4e54544ad973d9f5e5889d3d127664f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
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_bonus(self):
return self.attacker.attack_damage_bonus(self.weapon, self.strike_type)
def damage(self, check=Roll.Success):
persistant_damage_factor = 3 + 1/3
wp = self.weapon
dmg_bonus = self.damage_bonus()
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
|