Passed
Push — master ( cc891d...b53f20 )
by Nico
11:42
created

ApplyDamage::damageRandomShipSystem()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 4
dl 0
loc 13
ccs 0
cts 6
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Spacecraft\Lib\Damage;
6
7
use Override;
0 ignored issues
show
Bug introduced by
The type Override was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use RuntimeException;
9
use Stu\Component\Spacecraft\System\SpacecraftSystemManagerInterface;
10
use Stu\Component\Spacecraft\System\SpacecraftSystemModeEnum;
11
use Stu\Component\Spacecraft\System\SpacecraftSystemTypeEnum;
12
use Stu\Lib\Damage\DamageModeEnum;
13
use Stu\Lib\Damage\DamageWrapper;
14
use Stu\Lib\Information\InformationInterface;
15
use Stu\Lib\Information\InformationWrapper;
16
use Stu\Module\Colony\Lib\ColonyLibFactoryInterface;
17
use Stu\Module\Spacecraft\Lib\SpacecraftWrapperInterface;
18
use Stu\Orm\Entity\ColonyInterface;
19
use Stu\Orm\Entity\PlanetFieldInterface;
20
use Stu\Orm\Entity\SpacecraftSystemInterface;
21
22
//TODO unit tests and move to Lib/Damage
23
final class ApplyDamage implements ApplyDamageInterface
24
{
25 1
    public function __construct(
26
        private ColonyLibFactoryInterface $colonyLibFactory,
27
        private SpacecraftSystemManagerInterface $spacecraftSystemManager
28 1
    ) {}
29
30
    #[Override]
31
    public function damage(
32
        DamageWrapper $damageWrapper,
33
        SpacecraftWrapperInterface $shipWrapper,
34
        InformationInterface $informations
35
    ): void {
36
37
        if ($damageWrapper->getNetDamage() <= 0) {
38
            throw new RuntimeException('this should not happen');
39
        }
40
41
        $ship = $shipWrapper->get();
42
43
        if ($ship->getShieldState()) {
44
45
            if ($damageWrapper->isShieldPenetration()) {
46
                $informations->addInformationf('- Projektil hat Schilde durchdrungen!');
47
            } else {
48
                $this->damageShields($shipWrapper, $damageWrapper, $informations);
49
            }
50
        }
51
        if ($damageWrapper->getNetDamage() <= 0) {
52
            return;
53
        }
54
55
        $disablemessage = false;
56
        $damage = (int) $damageWrapper->getDamageRelative($ship, DamageModeEnum::HULL);
57
        if ($ship->getSystemState(SpacecraftSystemTypeEnum::RPG_MODULE) && $ship->getHull() - $damage < round($ship->getMaxHull() / 100 * 10)) {
58
            $damage = (int) round($ship->getHull() - $ship->getMaxHull() / 100 * 10);
59
            $disablemessage = _('-- Das Schiff wurde kampfunfähig gemacht');
60
            $ship->setDisabled(true);
61
        }
62
        if ($ship->getHull() > $damage) {
63
            if ($damageWrapper->isCrit()) {
64
                $systemName = $this->destroyRandomShipSystem($shipWrapper, $damageWrapper);
65
66
                if ($systemName !== null) {
67
                    $informations->addInformation("- Kritischer Hüllen-Treffer zerstört System: " . $systemName);
68
                }
69
            }
70
            $huelleVorher = $ship->getHull();
71
            $ship->setHuell($huelleVorher - $damage);
72
            $informations->addInformation("- Hüllenschaden: " . $damage . " - Status: " . $ship->getHull());
73
74
            if (!$this->checkForDamagedShipSystems(
75
                $shipWrapper,
76
                $damageWrapper,
77
                $huelleVorher,
78
                $informations
79
            )) {
80
                $this->damageRandomShipSystem(
81
                    $shipWrapper,
82
                    $damageWrapper,
83
                    $informations,
84
                    (int)ceil((100 * $damage * random_int(1, 5)) / $ship->getMaxHull())
85
                );
86
            }
87
88
            if ($disablemessage) {
89
                $informations->addInformation($disablemessage);
90
            }
91
92
            if ($ship->isDestroyed()) {
93
                $informations->addInformation("-- Das Schiff wurde zerstört!");
94
            }
95
96
            return;
97
        }
98
        $informations->addInformation("- Hüllenschaden: " . $damage);
99
        $informations->addInformation("-- Das Schiff wurde zerstört!");
100
        $ship->setIsDestroyed(true);
101
    }
102
103
    private function damageShields(SpacecraftWrapperInterface $wrapper, DamageWrapper $damageWrapper, InformationInterface $informations): void
104
    {
105
        $ship = $wrapper->get();
106
107
        $damage = (int) $damageWrapper->getDamageRelative($ship, DamageModeEnum::SHIELDS);
108
        if ($damage >= $ship->getShield()) {
109
            $informations->addInformation("- Schildschaden: " . $ship->getShield());
110
            $informations->addInformation("-- Schilde brechen zusammen!");
111
112
            $this->spacecraftSystemManager->deactivate($wrapper, SpacecraftSystemTypeEnum::SHIELDS);
113
114
            $ship->setShield(0);
115
        } else {
116
            $ship->setShield($ship->getShield() - $damage);
117
            $informations->addInformation("- Schildschaden: " . $damage . " - Status: " . $ship->getShield());
118
        }
119
120
        $shieldSystemData = $wrapper->getShieldSystemData();
121
        if ($shieldSystemData === null) {
122
            throw new RuntimeException('this should not happen');
123
        }
124
125
        $shieldSystemData->setShieldRegenerationTimer(time())->update();
126
    }
127
128
    #[Override]
129
    public function damageBuilding(
130
        DamageWrapper $damageWrapper,
131
        PlanetFieldInterface $target,
132
        bool $isOrbitField
133
    ): InformationWrapper {
134
        $informations = new InformationWrapper();
135
136
        $colony = $target->getHost();
137
        if (!$colony instanceof ColonyInterface) {
138
            throw new RuntimeException('this should not happen');
139
        }
140
141
        if (!$isOrbitField && $this->colonyLibFactory->createColonyShieldingManager($colony)->isShieldingEnabled()) {
142
            $damage = (int) $damageWrapper->getDamageRelative($colony, DamageModeEnum::SHIELDS);
143
            if ($damage > $colony->getShields()) {
144
                $informations->addInformation("- Schildschaden: " . $colony->getShields());
145
                $informations->addInformation("-- Schilde brechen zusammen!");
146
147
                $colony->setShields(0);
148
            } else {
149
                $colony->setShields($colony->getShields() - $damage);
150
                $informations->addInformation("- Schildschaden: " . $damage . " - Status: " . $colony->getShields());
151
            }
152
        }
153
        if ($damageWrapper->getNetDamage() <= 0) {
154
            return $informations;
155
        }
156
        $damage = (int) $damageWrapper->getDamageRelative($colony, DamageModeEnum::HULL);
157
        if ($target->getIntegrity() > $damage) {
158
            $target->setIntegrity($target->getIntegrity() - $damage);
159
            $informations->addInformation("- Gebäudeschaden: " . $damage . " - Status: " . $target->getIntegrity());
160
161
            return $informations;
162
        }
163
        $informations->addInformation("- Gebäudeschaden: " . $damage);
164
        $informations->addInformation("-- Das Gebäude wurde zerstört!");
165
        $target->setIntegrity(0);
166
167
        return $informations;
168
    }
169
170
    private function checkForDamagedShipSystems(
171
        SpacecraftWrapperInterface $wrapper,
172
        DamageWrapper $damageWrapper,
173
        int $huelleVorher,
174
        InformationInterface $informations
175
    ): bool {
176
        $ship = $wrapper->get();
177
        $systemsToDamage = ceil($huelleVorher * 6 / $ship->getMaxHull()) -
178
            ceil($ship->getHull() * 6 / $ship->getMaxHull());
179
180
        if ($systemsToDamage == 0) {
181
            return false;
182
        }
183
184
        for ($i = 1; $i <= $systemsToDamage; $i++) {
185
            $this->damageRandomShipSystem($wrapper, $damageWrapper, $informations);
186
        }
187
188
        return true;
189
    }
190
191
    private function destroyRandomShipSystem(SpacecraftWrapperInterface $wrapper, DamageWrapper $damageWrapper): ?string
192
    {
193
        $healthySystems = $this->getHealthySystems($wrapper, $damageWrapper);
194
        shuffle($healthySystems);
195
196
        if ($healthySystems === []) {
197
            return null;
198
        }
199
        $system = $healthySystems[0];
200
        $system->setStatus(0);
201
        $system->setMode(SpacecraftSystemModeEnum::MODE_OFF);
202
        $this->spacecraftSystemManager->handleDestroyedSystem($wrapper, $healthySystems[0]->getSystemType());
203
204
        return $healthySystems[0]->getSystemType()->getDescription();
205
    }
206
207
    private function damageRandomShipSystem(
208
        SpacecraftWrapperInterface $wrapper,
209
        DamageWrapper $damageWrapper,
210
        InformationInterface $informations,
211
        ?int $percent = null
212
    ): void {
213
        $healthySystems = $this->getHealthySystems($wrapper, $damageWrapper);
214
        shuffle($healthySystems);
215
216
        if ($healthySystems !== []) {
217
            $system = $healthySystems[0];
218
219
            $this->damageShipSystem($wrapper, $system, $percent ?? random_int(1, 70), $informations);
220
        }
221
    }
222
223
    /** @return array<SpacecraftSystemInterface>  */
224
    private function getHealthySystems(SpacecraftWrapperInterface $wrapper, DamageWrapper $damageWrapper): array
225
    {
226
        return $wrapper->get()->getSystems()
227
            ->filter(fn(SpacecraftSystemInterface $system): bool => $damageWrapper->canDamageSystem($system->getSystemType()))
228
            ->filter(fn(SpacecraftSystemInterface $system): bool => $system->getStatus() > 0)
229
            ->filter(fn(SpacecraftSystemInterface $system): bool => $system->getSystemType()->canBeDamaged())
230
            ->toArray();
231
    }
232
233
    #[Override]
234
    public function damageShipSystem(
235
        SpacecraftWrapperInterface $wrapper,
236
        SpacecraftSystemInterface $system,
237
        int $dmg,
238
        InformationInterface $informations
239
    ): bool {
240
        $status = $system->getStatus();
241
        $systemName = $system->getSystemType()->getDescription();
242
243
        if ($status > $dmg) {
244
            $system->setStatus($status - $dmg);
245
            $this->spacecraftSystemManager->handleDamagedSystem($wrapper, $system->getSystemType());
246
            $informations->addInformation("- Folgendes System wurde beschädigt: " . $systemName);
247
248
            return false;
249
        } else {
250
            $system->setStatus(0);
251
            $system->setMode(SpacecraftSystemModeEnum::MODE_OFF);
252
            $this->spacecraftSystemManager->handleDestroyedSystem($wrapper, $system->getSystemType());
253
            $informations->addInformation("- Der Schaden zerstört folgendes System: " . $systemName);
254
255
            return true;
256
        }
257
    }
258
}
259