summaryrefslogtreecommitdiff
path: root/actions.py
blob: f3cd39cb59c2166dbf5764e4cad353c746b11e12 (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
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