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

FightLib::isTargetOutsideFinishedTholianWeb()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 2
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Ship\Lib\Battle;
6
7
use Stu\Component\Ship\Repair\CancelRepairInterface;
8
use Stu\Component\Ship\System\Exception\ShipSystemException;
9
use Stu\Component\Ship\System\ShipSystemManagerInterface;
10
use Stu\Component\Ship\System\ShipSystemTypeEnum;
11
use Stu\Lib\InformationWrapper;
12
use Stu\Module\Ship\Lib\ShipNfsItem;
13
use Stu\Module\Ship\Lib\ShipWrapperInterface;
14
use Stu\Orm\Entity\ShipInterface;
15
16
final class FightLib implements FightLibInterface
17
{
18
    private ShipSystemManagerInterface $shipSystemManager;
19
20
    private CancelRepairInterface $cancelRepair;
21
22
    private AlertLevelBasedReactionInterface $alertLevelBasedReaction;
23
24 43
    public function __construct(
25
        ShipSystemManagerInterface $shipSystemManager,
26
        CancelRepairInterface $cancelRepair,
27
        AlertLevelBasedReactionInterface $alertLevelBasedReaction
28
    ) {
29 43
        $this->shipSystemManager = $shipSystemManager;
30 43
        $this->cancelRepair = $cancelRepair;
31 43
        $this->alertLevelBasedReaction = $alertLevelBasedReaction;
32
    }
33
34 6
    public function ready(ShipWrapperInterface $wrapper): InformationWrapper
35
    {
36 6
        $ship = $wrapper->get();
37
38 6
        $informations = new InformationWrapper();
39
40
        if (
41 6
            $ship->isDestroyed()
42 6
            || $ship->getRump()->isEscapePods()
43
        ) {
44 2
            return $informations;
45
        }
46 4
        if ($ship->getBuildplan() === null) {
47 1
            return $informations;
48
        }
49 3
        if (!$ship->hasEnoughCrew()) {
50 1
            return $informations;
51
        }
52
53 2
        if ($ship->getDockedTo() !== null) {
54 1
            $ship->setDockedTo(null);
55 1
            $informations->addInformation("- Das Schiff hat abgedockt");
56
        }
57
58
        try {
59 2
            $this->shipSystemManager->deactivate($wrapper, ShipSystemTypeEnum::SYSTEM_WARPDRIVE);
60 1
        } catch (ShipSystemException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
61
        }
62
        try {
63 2
            $this->shipSystemManager->deactivate($wrapper, ShipSystemTypeEnum::SYSTEM_CLOAK);
64 1
        } catch (ShipSystemException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
65
        }
66
67 2
        $this->cancelRepair->cancelRepair($ship);
68
69 2
        $informations->addInformationWrapper($this->alertLevelBasedReaction->react($wrapper));
70
71 2
        if ($informations->getInformations() !== []) {
72 1
            $informations->addInformationArray([sprintf(_('Aktionen der %s'), $ship->getName())], true);
73
        }
74
75 2
        return $informations;
76
    }
77
78 1
    public function filterInactiveShips(array $base): array
79
    {
80 1
        return array_filter(
81 1
            $base,
82 1
            fn (ShipWrapperInterface $wrapper): bool => !$wrapper->get()->isDestroyed() && !$wrapper->get()->isDisabled()
83 1
        );
84
    }
85
86 4
    public function canFire(ShipWrapperInterface $wrapper): bool
87
    {
88 4
        $ship = $wrapper->get();
89 4
        if (!$ship->getNbs()) {
90 1
            return false;
91
        }
92 3
        if (!$ship->hasActiveWeapon()) {
93 1
            return false;
94
        }
95
96 2
        $epsSystem = $wrapper->getEpsSystemData();
97 2
        return $epsSystem !== null && $epsSystem->getEps() !== 0;
98
    }
99
100 11
    public function canAttackTarget(
101
        ShipInterface $ship,
102
        ShipInterface|ShipNfsItem $target,
103
        bool $checkActiveWeapons = true
104
    ): bool {
105 11
        if ($checkActiveWeapons && !$ship->hasActiveWeapon()) {
106 1
            return false;
107
        }
108
109
        //can't attack itself
110 10
        if ($target === $ship) {
111 1
            return false;
112
        }
113
114
        //can't attack trumfields
115 9
        if ($target->isTrumfield()) {
116 1
            return false;
117
        }
118
119
        //if tractored, can only attack tractoring ship
120 8
        $tractoringShip = $ship->getTractoringShip();
121 8
        if ($tractoringShip !== null) {
122 3
            return $target->getId() === $tractoringShip->getId();
123
        }
124
125
        //can't attack target under warp
126 5
        if ($target->getWarpState()) {
127 1
            return false;
128
        }
129
130
        //can't attack same fleet
131 4
        $ownFleetId = $ship->getFleetId();
132 4
        $targetFleetId = $target->getFleetId();
133 4
        if ($ownFleetId === null || $targetFleetId === null) {
134 2
            return true;
135
        }
136
137 2
        return $ownFleetId !== $targetFleetId;
138
    }
139
140 8
    public function getAttackersAndDefenders(ShipWrapperInterface $wrapper, ShipWrapperInterface $targetWrapper): array
141
    {
142 8
        $attackers = $this->getAttackers($wrapper);
143 8
        $defenders = $this->getDefenders($targetWrapper);
144
145 8
        return [
146 8
            $attackers,
147 8
            $defenders,
148 8
            count($attackers) + count($defenders) > 2
149 8
        ];
150
    }
151
152
    /** @return array<int, ShipWrapperInterface> */
153 8
    public function getAttackers(ShipWrapperInterface $wrapper): array
154
    {
155 8
        $ship = $wrapper->get();
156 8
        $fleet = $wrapper->getFleetWrapper();
157
158 8
        if ($ship->isFleetLeader() && $fleet !== null) {
159 1
            $attackers = $fleet->getShipWrappers();
160
        } else {
161 7
            $attackers = [$ship->getId() => $wrapper];
162
        }
163
164 8
        return $attackers;
165
    }
166
167
    /** @return array<int, ShipWrapperInterface> */
168 8
    private function getDefenders(ShipWrapperInterface $targetWrapper): array
169
    {
170 8
        $target = $targetWrapper->get();
171 8
        $targetFleet = $targetWrapper->getFleetWrapper();
172
173 8
        if ($targetFleet !== null) {
174 3
            $defenders = [];
175
176
            // only uncloaked defenders fight
177 3
            foreach ($targetFleet->getShipWrappers() as $shipId => $defWrapper) {
178
179 3
                $defShip = $defWrapper->get();
180 3
                if (!$defShip->getCloakState()) {
181 3
                    $defenders[$shipId] = $defWrapper;
182
183 3
                    $this->addDockedToAsDefender($targetWrapper, $defenders);
184
                }
185
            }
186
187
            // if all defenders were cloaked, they obviously were scanned and enter the fight as a whole fleet
188 3
            if ($defenders === []) {
189 3
                $defenders = $targetFleet->getShipWrappers();
190
            }
191
        } else {
192 5
            $defenders = [$target->getId() => $targetWrapper];
193
194 5
            $this->addDockedToAsDefender($targetWrapper, $defenders);
195
        }
196
197 8
        return $defenders;
198
    }
199
200
    /** @param array<int, ShipWrapperInterface> $defenders */
201 8
    private function addDockedToAsDefender(ShipWrapperInterface $targetWrapper, array &$defenders): void
202
    {
203 8
        $dockedToWrapper = $targetWrapper->getDockedToShipWrapper();
204
        if (
205 8
            $dockedToWrapper !== null
206 8
            && !$dockedToWrapper->get()->getUser()->isNpc()
207 8
            && $dockedToWrapper->get()->hasActiveWeapon()
208
        ) {
209 2
            $defenders[$dockedToWrapper->get()->getId()] = $dockedToWrapper;
210
        }
211
    }
212
213 4
    public function isTargetOutsideFinishedTholianWeb(ShipInterface $ship, ShipInterface $target): bool
214
    {
215 4
        $web = $ship->getHoldingWeb();
216 4
        if ($web === null) {
217 1
            return false;
218
        }
219
220 3
        return $web->isFinished() && ($target->getHoldingWeb() !== $web);
221
    }
222
223 5
    public static function isBoardingPossible(ShipInterface|ShipNfsItem $ship): bool
224
    {
225 5
        return !($ship->isBase()
226 5
            || $ship->isTrumfield()
227 5
            || $ship->getCloakState()
228 5
            || $ship->getShieldState()
229 5
            || $ship->getWarpState());
230
    }
231
}
232