Passed
Push — master ( 288b46...98b0e3 )
by Nico
31:30 queued 08:00
created

AttackBuilding   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 235
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 130
dl 0
loc 235
ccs 0
cts 123
cp 0
rs 10
c 0
b 0
f 0
wmc 29

4 Methods

Rating   Name   Duplication   Size   Complexity  
A performSessionCheck() 0 3 1
F handle() 0 159 25
A __construct() 0 28 1
A addMessageMerge() 0 4 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Ship\Action\AttackBuilding;
6
7
use request;
8
use Stu\Component\Building\BuildingEnum;
9
use Stu\Component\Colony\ColonyFunctionManager;
10
use Stu\Component\Colony\ColonyFunctionManagerInterface;
11
use Stu\Lib\InformationWrapper;
12
use Stu\Module\Colony\Lib\PlanetFieldTypeRetrieverInterface;
13
use Stu\Module\Control\ActionControllerInterface;
14
use Stu\Module\Control\GameControllerInterface;
15
use Stu\Module\Message\Lib\PrivateMessageFolderSpecialEnum;
16
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
17
use Stu\Module\Ship\Lib\Battle\AlertRedHelperInterface;
18
use Stu\Module\Ship\Lib\Battle\FightLibInterface;
19
use Stu\Module\Ship\Lib\Message\MessageInterface;
20
use Stu\Module\Ship\Lib\Battle\Provider\AttackerProviderFactoryInterface;
21
use Stu\Module\Ship\Lib\Battle\Weapon\EnergyWeaponPhaseInterface;
22
use Stu\Module\Ship\Lib\Battle\Weapon\ProjectileWeaponPhaseInterface;
23
use Stu\Module\Ship\Lib\InteractionCheckerInterface;
24
use Stu\Module\Ship\Lib\ShipLoaderInterface;
25
use Stu\Module\Ship\View\ShowShip\ShowShip;
26
use Stu\Orm\Repository\ColonyRepositoryInterface;
27
use Stu\Orm\Repository\PlanetFieldRepositoryInterface;
28
29
final class AttackBuilding implements ActionControllerInterface
30
{
31
    public const ACTION_IDENTIFIER = 'B_ATTACK_BUILDING';
32
33
    private ShipLoaderInterface $shipLoader;
34
35
    private PlanetFieldRepositoryInterface $planetFieldRepository;
36
37
    private ColonyRepositoryInterface $colonyRepository;
38
39
    private InteractionCheckerInterface $interactionChecker;
40
41
    private FightLibInterface $fightLib;
42
43
    private EnergyWeaponPhaseInterface $energyWeaponPhase;
44
45
    private ProjectileWeaponPhaseInterface $projectileWeaponPhase;
46
47
    private PrivateMessageSenderInterface $privateMessageSender;
48
49
    private AlertRedHelperInterface $alertRedHelper;
50
51
    private InformationWrapper $informations;
52
53
    private PlanetFieldTypeRetrieverInterface $planetFieldTypeRetriever;
54
55
    private ColonyFunctionManagerInterface $colonyFunctionManager;
56
57
    private AttackerProviderFactoryInterface $attackerProviderFactory;
58
59
    public function __construct(
60
        ShipLoaderInterface $shipLoader,
61
        PlanetFieldRepositoryInterface $planetFieldRepository,
62
        ColonyRepositoryInterface $colonyRepository,
63
        InteractionCheckerInterface $interactionChecker,
64
        FightLibInterface $fightLib,
65
        EnergyWeaponPhaseInterface $energyWeaponPhase,
66
        ProjectileWeaponPhaseInterface $projectileWeaponPhase,
67
        PrivateMessageSenderInterface $privateMessageSender,
68
        AlertRedHelperInterface $alertRedHelper,
69
        PlanetFieldTypeRetrieverInterface $planetFieldTypeRetriever,
70
        ColonyFunctionManagerInterface $colonyFunctionManager,
71
        AttackerProviderFactoryInterface $attackerProviderFactory
72
    ) {
73
        $this->shipLoader = $shipLoader;
74
        $this->planetFieldRepository = $planetFieldRepository;
75
        $this->colonyRepository = $colonyRepository;
76
        $this->interactionChecker = $interactionChecker;
77
        $this->fightLib = $fightLib;
78
        $this->energyWeaponPhase = $energyWeaponPhase;
79
        $this->projectileWeaponPhase = $projectileWeaponPhase;
80
        $this->privateMessageSender = $privateMessageSender;
81
        $this->alertRedHelper = $alertRedHelper;
82
        $this->planetFieldTypeRetriever = $planetFieldTypeRetriever;
83
        $this->colonyFunctionManager = $colonyFunctionManager;
84
        $this->attackerProviderFactory = $attackerProviderFactory;
85
86
        $this->informations = new InformationWrapper();
87
    }
88
89
    public function handle(GameControllerInterface $game): void
90
    {
91
        $user = $game->getUser();
92
        $userId = $user->getId();
93
94
        $wrapper = $this->shipLoader->getWrapperByIdAndUser(
95
            request::indInt('id'),
96
            $userId
97
        );
98
99
        $colonyId = request::getIntFatal('colid');
100
        $fieldId = request::getIntFatal('field');
101
102
103
        $field = $this->planetFieldRepository->find($fieldId);
104
        $colony = $this->colonyRepository->find($colonyId);
105
        if ($field === null || $colony === null) {
106
            $game->addInformation(_('Feld oder Kolonie nicht vorhanden'));
107
            return;
108
        }
109
110
        if ($field->getFieldId() >= 80) {
111
            $game->addInformation(_('Der Untergrund kann nicht attackiert werden'));
112
            return;
113
        }
114
115
        $ship = $wrapper->get();
116
117
        if (!$ship->hasEnoughCrew($game)) {
118
            return;
119
        }
120
121
        if ($colony->getUser()->isVacationRequestOldEnough()) {
122
            $game->addInformation(_('Aktion nicht möglich, der Spieler befindet sich im Urlaubsmodus!'));
123
            return;
124
        }
125
126
        $epsSystem = $wrapper->getEpsSystemData();
127
128
        if ($epsSystem === null || $epsSystem->getEps() == 0) {
129
            $game->addInformation(_('Keine Energie vorhanden'));
130
            return;
131
        }
132
        if ($ship->isDisabled()) {
133
            $game->addInformation(_('Das Schiff ist kampfunfähig'));
134
            return;
135
        }
136
137
        if ($colony->getId() !== $field->getColonyId()) {
138
            return;
139
        }
140
        if (!$this->interactionChecker->checkColonyPosition($colony, $ship)) {
141
            return;
142
        }
143
144
        $isFleetAttack = false;
145
        $fleetWrapper = $wrapper->getFleetWrapper();
146
        if ($ship->isFleetLeader() && $fleetWrapper !== null) {
147
            $attackers = $fleetWrapper->getShipWrappers();
148
            $isFleetAttack = true;
149
        } else {
150
            $attackers = [$ship->getId() => $wrapper];
151
        }
152
153
        foreach ($attackers as $attackship) {
154
            $this->informations->addInformationWrapper($this->fightLib->ready($attackship));
155
        }
156
157
        // DEFENDING FLEETS
158
        foreach ($colony->getDefenders() as $fleet) {
159
            $this->alertRedHelper->performAttackCycle($fleet->getLeadShip(), $ship, $this->informations, true);
160
        }
161
162
        // ORBITAL DEFENSE
163
        $count = $this->colonyFunctionManager->getBuildingWithFunctionCount(
164
            $colony,
165
            BuildingEnum::BUILDING_FUNCTION_ENERGY_PHALANX,
166
            [ColonyFunctionManager::STATE_ENABLED]
167
        );
168
        $defendingPhalanx =  $this->attackerProviderFactory->getEnergyPhalanxAttacker($colony);
169
170
        for ($i = 0; $i < $count; $i++) {
171
            $attackerPool = $this->fightLib->filterInactiveShips($attackers);
172
173
            if ($attackerPool === []) {
174
                break;
175
            }
176
            $this->addMessageMerge($this->energyWeaponPhase->fire($defendingPhalanx, $attackerPool));
177
        }
178
179
        $count = $this->colonyFunctionManager->getBuildingWithFunctionCount(
180
            $colony,
181
            BuildingEnum::BUILDING_FUNCTION_PARTICLE_PHALANX,
182
            [ColonyFunctionManager::STATE_ENABLED]
183
        );
184
        $defendingPhalanx = $this->attackerProviderFactory->getProjectilePhalanxAttacker($colony);
185
186
        for ($i = 0; $i < $count; $i++) {
187
            $attackerPool = $this->fightLib->filterInactiveShips($attackers);
188
189
            if ($attackerPool === []) {
190
                break;
191
            }
192
            $this->addMessageMerge($this->projectileWeaponPhase->fire($defendingPhalanx, $attackerPool));
193
        }
194
195
        // OFFENSE OF ATTACKING SHIPS
196
        $isOrbitField = $this->planetFieldTypeRetriever->isOrbitField($field);
197
        $attackerPool = $this->fightLib->filterInactiveShips($attackers);
198
        $count = $this->colonyFunctionManager->getBuildingWithFunctionCount(
199
            $colony,
200
            BuildingEnum::BUILDING_FUNCTION_ANTI_PARTICLE,
201
            [ColonyFunctionManager::STATE_ENABLED]
202
        ) * 6;
203
204
        foreach ($attackerPool as $attackerWrapper) {
205
            $shipAttacker = $this->attackerProviderFactory->getShipAttacker($attackerWrapper);
206
207
            if ($isOrbitField) {
208
                $this->informations->addInformationWrapper($this->energyWeaponPhase->fireAtBuilding($shipAttacker, $field, $isOrbitField));
209
210
                if ($field->getIntegrity() === 0) {
211
                    break;
212
                }
213
            }
214
            $this->informations->addInformationWrapper($this->projectileWeaponPhase->fireAtBuilding($shipAttacker, $field, $isOrbitField, $count));
215
216
            if ($field->getIntegrity() === 0) {
217
                break;
218
            }
219
        }
220
221
        $this->colonyRepository->save($colony);
222
223
        $pm = sprintf(
224
            _("Kampf in Sektor %s, Kolonie %s\n%s"),
225
            $ship->getSectorString(),
226
            $colony->getName(),
227
            $this->informations->getInformationsAsString()
228
        );
229
        $this->privateMessageSender->send(
230
            $userId,
231
            $colony->getUserId(),
232
            $pm,
233
            PrivateMessageFolderSpecialEnum::PM_SPECIAL_COLONY
234
        );
235
236
        if ($ship->isDestroyed()) {
237
            $game->addInformationWrapper($this->informations);
238
            return;
239
        }
240
        $game->setView(ShowShip::VIEW_IDENTIFIER);
241
242
        if ($isFleetAttack) {
243
            $game->addInformation(_("Angriff durchgeführt"));
244
            $game->setTemplateVar('FIGHT_RESULTS', $this->informations->getInformations());
245
        } else {
246
            $game->addInformationWrapper($this->informations);
247
            $game->setTemplateVar('FIGHT_RESULTS', null);
248
        }
249
    }
250
251
    /**
252
     * @param MessageInterface[] $messages
253
     */
254
    private function addMessageMerge(array $messages): void
255
    {
256
        foreach ($messages as $message) {
257
            $this->informations->addInformationArray($message->getMessage());
258
        }
259
    }
260
261
    public function performSessionCheck(): bool
262
    {
263
        return true;
264
    }
265
}
266