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

Player::getLevelProgress()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AardsGerds\Game\Player;
6
7
use AardsGerds\Game\Build\Attribute\AttributePoints;
8
use AardsGerds\Game\Build\Attribute\Etherum;
9
use AardsGerds\Game\Build\Attribute\Health;
10
use AardsGerds\Game\Build\Attribute\Initiative;
11
use AardsGerds\Game\Build\Attribute\Strength;
12
use AardsGerds\Game\Build\Experience;
13
use AardsGerds\Game\Build\Level;
14
use AardsGerds\Game\Build\LevelProgress;
15
use AardsGerds\Game\Build\Talent\SecretKnowledge\Ascension;
16
use AardsGerds\Game\Build\Talent\TalentCollection;
17
use AardsGerds\Game\Build\Talent\TalentPoints;
18
use AardsGerds\Game\Build\Talent\WeaponMastery\ShortSword\Novice\Slash;
19
use AardsGerds\Game\Build\Talent\WeaponMastery\WeaponMastery;
20
use AardsGerds\Game\Build\Talent\WeaponMastery\WeaponMasteryLevel;
21
use AardsGerds\Game\Entity\Entity;
22
use AardsGerds\Game\Inventory\Alchemy\Potion\HealthPotion;
23
use AardsGerds\Game\Inventory\Inventory;
24
use AardsGerds\Game\Inventory\Weapon\ShortSword\RustyShortSword;
25
use AardsGerds\Game\Inventory\Weapon\Weapon;
26
use AardsGerds\Game\Shared\IntegerValueException;
27
28
final class Player extends Entity
29
{
30 1
    public function __construct(
31
        string $name,
32
        Health $health,
33
        Etherum $etherum,
34
        Strength $strength,
35
        Initiative $initiative,
36
        TalentCollection $talentCollection,
37
        Inventory $inventory,
38
        ?Weapon $weapon,
39
        bool $corrupted,
40
        private LevelProgress $levelProgress,
41
        private Health $maximumHealth,
42
        private AttributePoints $attributePoints,
43
        private TalentPoints $talentPoints,
44
    ) {
45 1
        parent::__construct(
46 1
            $name,
47
            $health,
48
            $etherum,
49
            $strength,
50
            $initiative,
51
            $talentCollection,
52
            $inventory,
53
            $weapon,
54
            $corrupted,
55
        );
56 1
    }
57
58
    public static function new(string $name): self
59
    {
60
        return new self(
61
            $name,
62
            new Health(100),
63
            new Etherum(1),
64
            new Strength(5),
65
            new Initiative(10),
66
            new TalentCollection([
67
                WeaponMastery::shortSword(WeaponMasteryLevel::novice()),
68
                new Slash(),
69
            ]),
70
            new Inventory([new HealthPotion(), new HealthPotion()]),
71
            new RustyShortSword(),
72
            false,
73
            new LevelProgress(
74
                new Level(1),
75
                new Experience(0),
76
            ),
77
            new Health(100),
78
            new AttributePoints(0),
79
            new TalentPoints(0),
80
        );
81
    }
82
83 1
    public function getLevelProgress(): LevelProgress
84
    {
85 1
        return $this->levelProgress;
86
    }
87
88
    public function increaseExperience(Experience $experience, PlayerAction $playerAction): void
89
    {
90
        $this->levelProgress->increase($experience, $this, $playerAction);
91
    }
92
93 1
    public function getMaximumHealth(): Health
94
    {
95 1
        return $this->maximumHealth;
96
    }
97
98 1
    public function getAttributePoints(): AttributePoints
99
    {
100 1
        return $this->attributePoints;
101
    }
102
103 1
    public function getTalentPoints(): TalentPoints
104
    {
105 1
        return $this->talentPoints;
106
    }
107
108
    public function heal(Health $health): void
109
    {
110
        $this->health->increaseBy($health);
111
112
        if ($this->health->isGreaterThan($this->maximumHealth)) {
113
            $this->healCompletely();
114
        }
115
    }
116
117
    public function healCompletely(): void
118
    {
119
        $this->health->replaceWith($this->maximumHealth);
120
    }
121
122
    /**
123
     * @throws PlayerException
124
     */
125
    public function increaseEtherum(Etherum $etherum): void
126
    {
127
        $this->etherum->increaseBy($etherum);
128
129
        if ($this->isCorrupted()) {
130
            return;
131
        }
132
133
        $playerAscension = $this->talentCollection->findSecretKnowledge()?->getAscension()
134
            ?? throw PlayerException::etherumOverdose();
135
136
        $corruptionBoundary = $this->calculateCorruptionBoundary();
137
138
        if ($this->etherum->isGreaterThanOrEqual($corruptionBoundary)) {
139
            if ($playerAscension->isLowerThan(Ascension::sixthAscension())) {
140
                throw PlayerException::etherumOverdose();
141
            }
142
143
            $this->corrupted = true;
144
        }
145
    }
146
147
    private function calculateCorruptionBoundary(): Etherum
148
    {
149
        $ascension = $this->talentCollection->findSecretKnowledge()?->getAscension();
150
        if ($ascension === null) {
151
            return new Etherum(2);
152
        }
153
154
        try {
155
            $nextAscensionEtherum = $ascension->increment()->getRequiredEtherum();
156
        } catch (IntegerValueException $exception) {
157
            // entity has 8th ascension
158
            $nextAscensionEtherum = new Etherum($ascension->getRequiredEtherum()->get() * 2);
159
        }
160
161
        // etherum required by next ascension + 0.5 x etherum required by next ascension
162
        return $nextAscensionEtherum->increaseBy(
163
            new Etherum((int) ($nextAscensionEtherum->get() * 0.5)),
164
        );
165
    }
166
}
167