Passed
Push — master ( 90a788...d30360 )
by Paweł
02:57
created

AttackAction::blockOccurred()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 6
ccs 0
cts 2
cp 0
rs 10
cc 1
nc 1
nop 3
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AardsGerds\Game\Fight;
6
7
use AardsGerds\Game\Build\Attribute\Damage;
8
use AardsGerds\Game\Player\PlayerAction;
9
use AardsGerds\Game\Shared\IntegerValueException;
10
11
final class AttackAction
12
{
13
    /**
14
     * @throws IntegerValueException if target's health hits 0
15
     */
16
    public static function invoke(
17
        Fighter $attacker,
18
        Fighter $target,
19
        Attack $attack,
20
        PlayerAction $playerAction,
21
    ): void {
22
        if (self::blockOccurred($attacker, $target, $attack)) {
23
            $playerAction->tell("{$attacker->getName()} uses {$attack}, but {$target->getName()} has blocked this attack.");
24
            return;
25
        }
26
27
        $damage = self::calculateDamage($attacker, $attack);
28
29
        try {
30
            $target->getHealth()->decreaseBy($damage);
31
        } catch (IntegerValueException $exception) {
32
            $playerAction->tell("{$attacker->getName()} uses {$attack} and deals {$damage} damage, which brings opponent to their knees!");
33
            throw $exception;
34
        }
35
36
        $playerAction->tell("{$attacker->getName()} uses {$attack} and deals {$damage} damage.");
37
    }
38
39
    private static function calculateDamage(
40
        Fighter $attacker,
41
        Attack $attack,
42
    ): Damage {
43
        $initialDamage = new Damage(0);
44
45
        return match (true) {
46
            $attack instanceof MeleeAttack =>
47
                $initialDamage
48
                    ->increaseBy($attack->getDamage($attacker->getWeapon()
0 ignored issues
show
Bug introduced by
The method getDamage() does not exist on AardsGerds\Game\Fight\Attack. Since it exists in all sub-types, consider adding an abstract or default implementation to AardsGerds\Game\Fight\Attack. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

48
                    ->increaseBy($attack->/** @scrutinizer ignore-call */ getDamage($attacker->getWeapon()
Loading history...
49
                        ?? throw FightException::weaponRequired()))
50
                    ->increaseBy($attacker->getStrength()),
51
            $attack instanceof EtherumAttack => $attack->getDamage(),
52
            default => $initialDamage,
53
        };
54
    }
55
56
    private static function blockOccurred(
57
        Fighter $attacker,
58
        Fighter $target,
59
        Attack $attack,
60
    ): bool {
61
        return self::occurred(Block::calculateChance($attacker, $target, $attack));
62
    }
63
64
    private static function occurred(float $chance): bool
65
    {
66
        return mt_rand(1, 10000) <= $chance * 10000;
67
    }
68
}
69