Passed
Push — master ( f4068b...77f637 )
by Nico
40:27 queued 14:09
created

ApplyDamage::damageBuilding()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 35
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
cc 6
eloc 22
nc 9
nop 3
dl 0
loc 35
ccs 0
cts 22
cp 0
crap 42
rs 8.9457
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Ship\Lib\Damage;
6
7
use Stu\Component\Ship\ShipEnum;
8
use Stu\Component\Ship\System\ShipSystemManagerInterface;
9
use Stu\Component\Ship\System\ShipSystemModeEnum;
10
use Stu\Component\Ship\System\ShipSystemTypeEnum;
11
use Stu\Lib\DamageWrapper;
12
use Stu\Lib\InformationWrapper;
13
use Stu\Module\Colony\Lib\ColonyLibFactoryInterface;
14
use Stu\Module\Ship\Lib\ShipWrapperInterface;
15
use Stu\Orm\Entity\PlanetFieldInterface;
16
use Stu\Orm\Entity\ShipSystemInterface;
17
18
//TODO unit tests and move to Lib/Damage
19
final class ApplyDamage implements ApplyDamageInterface
20
{
21
    private ShipSystemManagerInterface $shipSystemManager;
22
23
    private ColonyLibFactoryInterface $colonyLibFactory;
24
25 2
    public function __construct(
26
        ColonyLibFactoryInterface $colonyLibFactory,
27
        ShipSystemManagerInterface $shipSystemManager
28
    ) {
29 2
        $this->shipSystemManager = $shipSystemManager;
30 2
        $this->colonyLibFactory = $colonyLibFactory;
31
    }
32
33
    public function damage(
34
        DamageWrapper $damageWrapper,
35
        ShipWrapperInterface $shipWrapper
36
    ): InformationWrapper {
37
        $ship = $shipWrapper->get();
38
        $ship->setShieldRegenerationTimer(time());
39
40
        $informations = new InformationWrapper();
41
        if ($ship->getShieldState()) {
42
            $damage = (int) $damageWrapper->getDamageRelative($ship, ShipEnum::DAMAGE_MODE_SHIELDS);
43
            if ($damage >= $ship->getShield()) {
44
                $informations->addInformation("- Schildschaden: " . $ship->getShield());
45
                $informations->addInformation("-- Schilde brechen zusammen!");
46
47
                $this->shipSystemManager->deactivate($shipWrapper, ShipSystemTypeEnum::SYSTEM_SHIELDS);
48
49
                $ship->setShield(0);
50
            } else {
51
                $ship->setShield($ship->getShield() - $damage);
52
                $informations->addInformation("- Schildschaden: " . $damage . " - Status: " . $ship->getShield());
53
            }
54
        }
55
        if ($damageWrapper->getNetDamage() <= 0) {
56
            return $informations;
57
        }
58
        $disablemessage = false;
59
        $damage = (int) $damageWrapper->getDamageRelative($ship, ShipEnum::DAMAGE_MODE_HULL);
60
        if ($ship->getSystemState(ShipSystemTypeEnum::SYSTEM_RPG_MODULE) && $ship->getHull() - $damage < round($ship->getMaxHull() / 100 * 10)) {
61
            $damage = (int) round($ship->getHull() - $ship->getMaxHull() / 100 * 10);
62
            $disablemessage = _('-- Das Schiff wurde kampfunfähig gemacht');
63
            $ship->setDisabled(true);
64
        }
65
        if ($ship->getHull() > $damage) {
66
            if ($damageWrapper->isCrit()) {
67
                $systemName = $this->destroyRandomShipSystem($shipWrapper);
68
69
                if ($systemName !== null) {
70
                    $informations->addInformation("- Kritischer Hüllen-Treffer zerstört System: " . $systemName);
71
                }
72
            }
73
            $huelleVorher = $ship->getHull();
74
            $ship->setHuell($huelleVorher - $damage);
75
            $informations->addInformation("- Hüllenschaden: " . $damage . " - Status: " . $ship->getHull());
76
77
            if (!$this->checkForDamagedShipSystems(
78
                $shipWrapper,
79
                $huelleVorher,
80
                $informations
81
            )) {
82
                $this->damageRandomShipSystem(
83
                    $shipWrapper,
84
                    $informations,
85
                    (int)ceil((100 * $damage * random_int(1, 5)) / $ship->getMaxHull())
86
                );
87
            }
88
89
            if ($disablemessage) {
90
                $informations->addInformation($disablemessage);
91
            }
92
93
            if ($ship->isDestroyed()) {
94
                $informations->addInformation("-- Das Schiff wurde zerstört!");
95
            }
96
97
            return $informations;
98
        }
99
        $informations->addInformation("- Hüllenschaden: " . $damage);
100
        $informations->addInformation("-- Das Schiff wurde zerstört!");
101
        $ship->setIsDestroyed(true);
102
103
        return $informations;
104
    }
105
106
    public function damageBuilding(
107
        DamageWrapper $damageWrapper,
108
        PlanetFieldInterface $target,
109
        bool $isOrbitField
110
    ): InformationWrapper {
111
        $informations = new InformationWrapper();
112
113
        $colony = $target->getColony();
114
        if (!$isOrbitField && $this->colonyLibFactory->createColonyShieldingManager($colony)->isShieldingEnabled()) {
115
            $damage = (int) $damageWrapper->getDamageRelative($colony, ShipEnum::DAMAGE_MODE_SHIELDS);
116
            if ($damage > $colony->getShields()) {
117
                $informations->addInformation("- Schildschaden: " . $colony->getShields());
118
                $informations->addInformation("-- Schilde brechen zusammen!");
119
120
                $colony->setShields(0);
121
            } else {
122
                $colony->setShields($colony->getShields() - $damage);
123
                $informations->addInformation("- Schildschaden: " . $damage . " - Status: " . $colony->getShields());
124
            }
125
        }
126
        if ($damageWrapper->getNetDamage() <= 0) {
127
            return $informations;
128
        }
129
        $damage = (int) $damageWrapper->getDamageRelative($colony, ShipEnum::DAMAGE_MODE_HULL);
130
        if ($target->getIntegrity() > $damage) {
131
            $target->setIntegrity($target->getIntegrity() - $damage);
132
            $informations->addInformation("- Gebäudeschaden: " . $damage . " - Status: " . $target->getIntegrity());
133
134
            return $informations;
135
        }
136
        $informations->addInformation("- Gebäudeschaden: " . $damage);
137
        $informations->addInformation("-- Das Gebäude wurde zerstört!");
138
        $target->setIntegrity(0);
139
140
        return $informations;
141
    }
142
143
    private function checkForDamagedShipSystems(
144
        ShipWrapperInterface $wrapper,
145
        int $huelleVorher,
146
        InformationWrapper $informations
147
    ): bool {
148
        $ship = $wrapper->get();
149
        $systemsToDamage = ceil($huelleVorher * 6 / $ship->getMaxHull()) -
150
            ceil($ship->getHull() * 6 / $ship->getMaxHull());
151
152
        if ($systemsToDamage == 0) {
153
            return false;
154
        }
155
156
        for ($i = 1; $i <= $systemsToDamage; $i++) {
157
            $this->damageRandomShipSystem($wrapper, $informations);
158
        }
159
160
        return true;
161
    }
162
163
    private function destroyRandomShipSystem(ShipWrapperInterface $wrapper): ?string
164
    {
165
        $healthySystems = $wrapper->get()->getHealthySystems();
166
        shuffle($healthySystems);
167
168
        if ($healthySystems === []) {
169
            return null;
170
        }
171
        $system = $healthySystems[0];
172
        $system->setStatus(0);
173
        $system->setMode(ShipSystemModeEnum::MODE_OFF);
174
        $this->shipSystemManager->handleDestroyedSystem($wrapper, $healthySystems[0]->getSystemType());
175
176
        return ShipSystemTypeEnum::getDescription($healthySystems[0]->getSystemType());
177
    }
178
179
    private function damageRandomShipSystem(
180
        ShipWrapperInterface $wrapper,
181
        InformationWrapper $informations,
182
        int $percent = null
183
    ): void {
184
        $healthySystems = $wrapper->get()->getHealthySystems();
185
        shuffle($healthySystems);
186
187
        if ($healthySystems !== []) {
188
            $system = $healthySystems[0];
189
190
            $this->damageShipSystem($wrapper, $system, $percent ?? random_int(1, 70), $informations);
191
        }
192
    }
193
194
    public function damageShipSystem(
195
        ShipWrapperInterface $wrapper,
196
        ShipSystemInterface $system,
197
        int $dmg,
198
        InformationWrapper $informations
199
    ): bool {
200
        $status = $system->getStatus();
201
        $systemName = ShipSystemTypeEnum::getDescription($system->getSystemType());
202
203
        if ($status > $dmg) {
204
            $system->setStatus($status - $dmg);
205
            $this->shipSystemManager->handleDamagedSystem($wrapper, $system->getSystemType());
206
            $informations->addInformation("- Folgendes System wurde beschädigt: " . $systemName);
207
208
            return false;
209
        } else {
210
            $system->setStatus(0);
211
            $system->setMode(ShipSystemModeEnum::MODE_OFF);
212
            $this->shipSystemManager->handleDestroyedSystem($wrapper, $system->getSystemType());
213
            $informations->addInformation("- Der Schaden zerstört folgendes System: " . $systemName);
214
215
            return true;
216
        }
217
    }
218
}
219