Passed
Pull Request — master (#1686)
by Nico
31:24
created

Ship   F

Complexity

Total Complexity 287

Size/Duplication

Total Lines 1731
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 465
c 0
b 0
f 0
dl 0
loc 1731
ccs 0
cts 613
cp 0
rs 2
wmc 287

208 Methods

Rating   Name   Duplication   Size   Complexity  
A getCloakState() 0 3 1
A getSubspaceState() 0 3 1
A getAstroState() 0 3 1
A getTachyonState() 0 3 1
A isFleetLeader() 0 3 1
A getSystem() 0 3 2
A setUser() 0 4 1
A getUser() 0 3 1
A setFleet() 0 4 1
A getFleet() 0 3 1
A setTractoredShipId() 0 4 1
A getMapCX() 0 3 1
A getTractoredShip() 0 3 1
A getDockPrivileges() 0 3 1
A hasFreeDockingSlots() 0 3 1
A getTractoringShip() 0 3 1
A getHoldingWeb() 0 3 1
A getDockingSlotCount() 0 5 3
A setTractoredShip() 0 4 1
A dockedOnTradePost() 0 3 2
A getMapCY() 0 3 1
A isInterceptAble() 0 3 1
A getDockedShipCount() 0 3 1
A getFreeDockingSlotCount() 0 3 1
A setTractoringShip() 0 4 1
A setHoldingWeb() 0 9 2
A getHealthySystems() 0 9 3
A displayNbsActions() 0 3 2
A hasTranswarp() 0 3 1
A hasUplink() 0 3 1
A setDockedTo() 0 4 1
A getStoredShuttleCount() 0 11 3
A hasNbsLss() 0 3 1
A getTranswarpCooldown() 0 5 2
A getDockedShips() 0 3 1
A setDockedToId() 0 4 1
A hasFreeShuttleSpace() 0 8 3
A getDockedTo() 0 3 1
A getMaxTorpedos() 0 5 2
A getStoredShuttles() 0 11 3
A getWebState() 0 3 1
A setAlertState() 0 4 1
A getImpulseState() 0 3 1
A setCx() 0 4 1
A setFleetId() 0 4 1
A isLSSModeBorder() 0 3 1
A isSystemHealthy() 0 7 2
A getSystemState() 0 8 3
A getSy() 0 3 1
A getLayer() 0 8 2
A getName() 0 3 1
A setName() 0 4 1
A getSystemsId() 0 3 2
A getLSSmode() 0 3 1
A __construct() 0 8 1
A getSx() 0 3 1
A getCy() 0 3 1
A setAlertStateGreen() 0 3 1
A setFlightDirection() 0 4 1
A getUserId() 0 3 1
A getUserName() 0 3 1
A getId() 0 7 2
A getFleetId() 0 3 1
A getLayerId() 0 3 1
A setLSSMode() 0 4 1
A setLayerId() 0 4 1
A getFlightDirection() 0 3 1
A isLSSModeNormal() 0 3 1
A getAlertState() 0 3 1
A getCx() 0 3 1
A getWarpState() 0 3 1
A setCy() 0 4 1
A hasRPGModule() 0 3 1
A getCurrentMapField() 0 3 1
A getTorpedoCount() 0 7 2
A hasCloak() 0 3 1
A setShield() 0 4 1
A getConstructionHubState() 0 3 1
A getShieldState() 0 3 1
A getTractorPayload() 0 8 2
A getTakeoverPassive() 0 3 1
A getDockedWorkbeeCount() 0 11 3
A setMaxHuell() 0 4 1
A getBuildplan() 0 3 1
A getColorStyle() 0 24 5
A isOverSystem() 0 7 2
A getLocation() 0 3 1
A getCrewCount() 0 3 1
A setDisabled() 0 4 1
A canMove() 0 4 2
A isTrumfield() 0 3 1
A isConstruction() 0 3 1
A getSystems() 0 3 1
A setTorpedoStorage() 0 4 1
A isUnderRepair() 0 4 2
A hasTachyonScanner() 0 3 1
A isTractored() 0 3 1
A setTakeoverPassive() 0 5 1
A getMapRegion() 0 8 2
A getShipSystem() 0 8 2
A getPosY() 0 6 2
A isTractoring() 0 3 1
A getBeamFactor() 0 3 1
A getHullColorStyle() 0 3 1
A canMan() 0 6 4
A isShuttleRampHealthy() 0 3 1
A canBuildConstruction() 0 3 1
A getHoldingWebBackgroundStyle() 0 15 4
A setHitChance() 0 4 1
A getSpacecraftType() 0 3 1
A getShieldRegenerationTimer() 0 3 1
A setEvadeChance() 0 4 1
A getHull() 0 3 1
A getShieldRegenerationRate() 0 3 1
A isOverWormhole() 0 3 2
A setBuildplan() 0 4 1
A setStarsystemMap() 0 17 3
A updateLocation() 0 6 1
A getTakeoverActive() 0 3 1
A getEvadeChance() 0 8 2
A getPhaserState() 0 3 1
A getLss() 0 3 1
A isMatrixScannerHealthy() 0 3 1
A isDestroyed() 0 3 1
A getMaxStorage() 0 3 1
A getExcessCrewCount() 0 3 1
A setSpacecraftType() 0 4 1
A setRump() 0 4 1
A setInfluenceArea() 0 4 1
A setDatabaseId() 0 4 1
A hasEscapePods() 0 3 2
A getMap() 0 3 1
A hasCrewmanOfUser() 0 9 3
A getIsFleetLeader() 0 3 2
A setFormerRumpId() 0 4 1
A hasActiveWeapon() 0 3 2
A isOverColony() 0 3 2
A getShield() 0 3 1
A getHoldingWebImageStyle() 0 15 4
A getBaseDamage() 0 8 2
A setBaseDamage() 0 4 1
A isBoardingPossible() 0 3 1
A hasTorpedo() 0 3 1
A hasWarpdrive() 0 3 1
A hasShipSystem() 0 3 1
A getSectorId() 0 8 2
A setMaxShield() 0 4 1
A isShuttle() 0 3 1
B getModules() 0 22 7
A setIsFleetLeader() 0 4 1
A setShieldRegenerationTimer() 0 4 1
A getAstroStartTurn() 0 3 1
A getRumpName() 0 3 1
A getHitChance() 0 8 2
A getFormerRumpId() 0 3 1
A setHuell() 0 4 1
A getRepairRate() 0 4 1
A hasAstroLaboratory() 0 3 1
A getShieldRegenerationPercentage() 0 3 2
A hasPhaser() 0 3 1
A getRPGModuleState() 0 3 1
A setIsInEmergency() 0 4 1
A getTorpedoState() 0 3 1
A setMap() 0 11 2
A setTradePost() 0 5 1
A getMaxShield() 0 8 2
A hasSubspaceScanner() 0 3 1
A isTractorbeamPossible() 0 3 1
A getSectorString() 0 6 2
A getTheoreticalReactorOutput() 0 3 1
A getRumpId() 0 3 1
A getState() 0 3 1
A getBeamableStorage() 0 5 1
A getLogbook() 0 3 1
A getInfluenceArea() 0 3 1
A getPosX() 0 6 2
A isAlertGreen() 0 3 1
A canIntercept() 0 3 2
A hasShuttleRamp() 0 3 1
A setTakeoverActive() 0 5 1
A getTorpedo() 0 7 2
A getReactorLoad() 0 3 1
A getMaxHull() 0 3 1
A getStorageSum() 0 6 1
A getRump() 0 3 1
A setIsDestroyed() 0 4 1
A getDatabaseId() 0 3 1
A hasEnoughCrew() 0 20 6
A isDisabled() 0 3 1
A isWarpPossible() 0 3 2
A setState() 0 4 1
A getTorpedoStorage() 0 3 1
A setAstroStartTurn() 0 4 1
A getCrewAssignments() 0 3 1
A isDeflectorHealthy() 0 3 1
A isTorpedoStorageHealthy() 0 3 1
A getNbs() 0 3 1
A getStorage() 0 3 1
A isWarpAble() 0 3 1
A getStarsystemMap() 0 3 1
A isWebEmitterHealthy() 0 3 1
A isTroopQuartersHealthy() 0 3 1
A getTradePost() 0 3 1
A __toString() 0 7 2
A setSensorRange() 0 4 1
A getSensorRange() 0 8 2
A getIsInEmergency() 0 3 1
A isBase() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Ship often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Ship, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Orm\Entity;
6
7
use Doctrine\Common\Collections\ArrayCollection;
8
use Doctrine\Common\Collections\Collection;
9
use Doctrine\ORM\Mapping\Column;
10
use Doctrine\ORM\Mapping\Entity;
11
use Doctrine\ORM\Mapping\GeneratedValue;
12
use Doctrine\ORM\Mapping\Id;
13
use Doctrine\ORM\Mapping\Index;
14
use Doctrine\ORM\Mapping\JoinColumn;
15
use Doctrine\ORM\Mapping\ManyToOne;
16
use Doctrine\ORM\Mapping\OneToMany;
17
use Doctrine\ORM\Mapping\OneToOne;
18
use Doctrine\ORM\Mapping\OrderBy;
19
use Doctrine\ORM\Mapping\Table;
20
use RuntimeException;
21
use Stu\Component\Game\TimeConstants;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Game\TimeConstants 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...
22
use Stu\Component\Map\MapEnum;
23
use Stu\Component\Ship\ShipAlertStateEnum;
24
use Stu\Component\Ship\ShipEnum;
25
use Stu\Component\Ship\ShipLSSModeEnum;
26
use Stu\Component\Ship\ShipModuleTypeEnum;
27
use Stu\Component\Ship\ShipRumpEnum;
28
use Stu\Component\Ship\ShipStateEnum;
29
use Stu\Component\Ship\SpacecraftTypeEnum;
30
use Stu\Component\Ship\System\ShipSystemModeEnum;
31
use Stu\Component\Ship\System\ShipSystemTypeEnum;
32
use Stu\Component\Ship\System\Type\TorpedoStorageShipSystem;
33
use Stu\Component\Ship\System\Type\TractorBeamShipSystem;
34
use Stu\Component\Station\StationUtility;
35
use Stu\Lib\Map\Location;
36
use Stu\Module\Control\GameControllerInterface;
37
use Stu\Module\Logging\LoggerUtilInterface;
38
use Stu\Module\Ship\Lib\Battle\FightLib;
39
40
/**
41
 * @Entity(repositoryClass="Stu\Orm\Repository\ShipRepository")
42
 * @Table(
43
 *     name="stu_ships",
44
 *     indexes={
45
 *         @Index(name="ship_fleet_idx", columns={"fleets_id"}),
46
 *         @Index(name="ship_map_idx", columns={"map_id"}),
47
 *         @Index(name="ship_starsystem_map_idx", columns={"starsystem_map_id"}),
48
 *         @Index(name="outer_system_location_idx", columns={"cx", "cy"}),
49
 *         @Index(name="ship_rump_idx", columns={"rumps_id"}),
50
 *         @Index(name="ship_web_idx", columns={"holding_web_id"}),
51
 *         @Index(name="ship_user_idx", columns={"user_id"}),
52
 *         @Index(name="ship_tractored_idx", columns={"tractored_ship_id"}),
53
 *         @Index(name="ship_influence_area_idx", columns={"influence_area_id"})
54
 *     }
55
 * )
56
 **/
57
class Ship implements ShipInterface
58
{
59
    /**
60
     * @Id
61
     * @Column(type="integer")
62
     * @GeneratedValue(strategy="IDENTITY")
63
     *
64
     */
65
    private ?int $id = null;
66
67
    /**
68
     * @Column(type="integer")
69
     *
70
     */
71
    private int $user_id = 0;
72
73
    /**
74
     * @Column(type="integer")
75
     *
76
     */
77
    private int $rumps_id = 0;
78
79
    /**
80
     * @Column(type="integer", nullable=true)
81
     *
82
     */
83
    private ?int $plans_id = null;
0 ignored issues
show
introduced by
The private property $plans_id is not used, and could be removed.
Loading history...
84
85
    /**
86
     * @Column(type="integer", nullable=true)
87
     *
88
     */
89
    private ?int $fleets_id = null;
90
91
    /**
92
     * @Column(type="integer", length=5)
93
     *
94
     */
95
    private int $layer_id = MapEnum::DEFAULT_LAYER;
96
97
    /**
98
     * @Column(type="integer", length=5)
99
     *
100
     */
101
    private int $cx = 0;
102
103
    /**
104
     * @Column(type="integer", length=5)
105
     *
106
     */
107
    private int $cy = 0;
108
109
    /**
110
     * @Column(type="smallint", length=1)
111
     *
112
     */
113
    private int $direction = 0;
114
115
    /**
116
     * @Column(type="string")
117
     *
118
     */
119
    private string $name = '';
120
121
    /**
122
     * @Column(type="smallint", length=1, enumType=ShipAlertStateEnum::class)
123
     *
124
     */
125
    private ShipAlertStateEnum $alvl = ShipAlertStateEnum::ALERT_GREEN;
126
127
    /**
128
     * @Column(type="smallint", length=1)
129
     *
130
     */
131
    private int $lss_mode = ShipLSSModeEnum::LSS_NORMAL;
132
133
    /**
134
     * @Column(type="integer", length=5, nullable=true)
135
     *
136
     */
137
    private ?int $warpcore = 0;
138
139
    /**
140
     * @Column(type="integer", length=6)
141
     *
142
     */
143
    private int $huelle = 0;
144
145
    /**
146
     * @Column(type="integer", length=6)
147
     *
148
     */
149
    private int $max_huelle = 0;
150
151
    /**
152
     * @Column(type="integer", length=6)
153
     *
154
     */
155
    private int $schilde = 0;
156
157
    /**
158
     * @Column(type="integer", length=6)
159
     *
160
     */
161
    private int $max_schilde = 0;
162
163
    /**
164
     * @Column(type="integer", nullable=true)
165
     *
166
     */
167
    private ?int $tractored_ship_id = null;
168
169
    /**
170
     * @Column(type="integer", nullable=true)
171
     *
172
     */
173
    private ?int $holding_web_id = null;
174
175
    /**
176
     * @Column(type="integer", nullable=true)
177
     *
178
     */
179
    private ?int $dock = null;
180
181
    /**
182
     * @Column(type="integer")
183
     *
184
     */
185
    private int $former_rumps_id = 0;
186
187
    /**
188
     * @Column(type="smallint", length=1, nullable=true)
189
     *
190
     */
191
    private ?int $type = SpacecraftTypeEnum::SPACECRAFT_TYPE_SHIP;
192
193
    /**
194
     * @Column(type="integer")
195
     *
196
     */
197
    private int $database_id = 0;
198
199
    /**
200
     * @Column(type="boolean")
201
     *
202
     */
203
    private bool $is_destroyed = false;
204
205
    /**
206
     * @Column(type="boolean")
207
     *
208
     */
209
    private bool $disabled = false;
210
211
    /**
212
     * @Column(type="smallint", length=3)
213
     *
214
     */
215
    private int $hit_chance = 0;
216
217
    /**
218
     * @Column(type="smallint", length=3)
219
     *
220
     */
221
    private int $evade_chance = 0;
222
223
    /**
224
     * @Column(type="smallint", length=4, nullable=true)
225
     *
226
     */
227
    private ?int $reactor_output = 0;
228
229
    /**
230
     * @Column(type="smallint", length=4)
231
     *
232
     */
233
    private int $base_damage = 0;
234
235
    /**
236
     * @Column(type="smallint", length=3)
237
     *
238
     */
239
    private int $sensor_range = 0;
240
241
    /**
242
     * @Column(type="integer")
243
     *
244
     */
245
    private int $shield_regeneration_timer = 0;
246
247
    /**
248
     * @Column(type="smallint", enumType=ShipStateEnum::class)
249
     *
250
     */
251
    private ShipStateEnum $state = ShipStateEnum::SHIP_STATE_NONE;
252
253
    /**
254
     * @Column(type="integer", nullable=true)
255
     *
256
     */
257
    private ?int $astro_start_turn = null;
258
259
    /**
260
     * @Column(type="boolean")
261
     *
262
     */
263
    private bool $is_fleet_leader = false;
264
265
    /**
266
     * @Column(type="integer", nullable=true) *
267
     *
268
     */
269
    private ?int $map_id = null;
0 ignored issues
show
introduced by
The private property $map_id is not used, and could be removed.
Loading history...
270
271
    /**
272
     * @Column(type="integer", nullable=true) *
273
     *
274
     */
275
    private ?int $starsystem_map_id = null;
0 ignored issues
show
introduced by
The private property $starsystem_map_id is not used, and could be removed.
Loading history...
276
277
    /**
278
     * @Column(type="integer", nullable=true) *
279
     *
280
     */
281
    private ?int $influence_area_id = null;
0 ignored issues
show
introduced by
The private property $influence_area_id is not used, and could be removed.
Loading history...
282
283
    /**
284
     * @Column(type="boolean")
285
     *
286
     */
287
    private bool $in_emergency = false;
288
289
    /**
290
     * @ManyToOne(targetEntity="Fleet", inversedBy="ships")
291
     * @JoinColumn(name="fleets_id", referencedColumnName="id")
292
     */
293
    private ?FleetInterface $fleet = null;
294
295
    /**
296
     * @OneToOne(targetEntity="TradePost", mappedBy="ship")
297
     */
298
    private ?TradePostInterface $tradePost = null;
299
300
    /**
301
     * @ManyToOne(targetEntity="Ship", inversedBy="dockedShips")
302
     * @JoinColumn(name="dock", referencedColumnName="id")
303
     */
304
    private ?ShipInterface $dockedTo = null;
305
306
    /**
307
     * @var ArrayCollection<int, ShipInterface>
308
     *
309
     * @OneToMany(targetEntity="Ship", mappedBy="dockedTo", indexBy="id")
310
     * @OrderBy({"fleets_id": "DESC", "is_fleet_leader": "DESC"})
311
     */
312
    private Collection $dockedShips;
313
314
    /**
315
     * @var ArrayCollection<int, DockingPrivilegeInterface>
316
     *
317
     * @OneToMany(targetEntity="DockingPrivilege", mappedBy="ship")
318
     */
319
    private Collection $dockingPrivileges;
320
321
    /**
322
     * @OneToOne(targetEntity="Ship")
323
     * @JoinColumn(name="tractored_ship_id", referencedColumnName="id")
324
     */
325
    private ?ShipInterface $tractoredShip = null;
326
327
    /**
328
     * @OneToOne(targetEntity="Ship", mappedBy="tractoredShip")
329
     */
330
    private ?ShipInterface $tractoringShip = null;
331
332
    /**
333
     * @ManyToOne(targetEntity="TholianWeb")
334
     * @JoinColumn(name="holding_web_id", referencedColumnName="id", onDelete="CASCADE")
335
     */
336
    private ?TholianWebInterface $holdingWeb = null;
337
338
    /**
339
     * @ManyToOne(targetEntity="User")
340
     * @JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")
341
     */
342
    private UserInterface $user;
343
344
    /**
345
     * @var ArrayCollection<int, ShipCrewInterface>
346
     *
347
     * @OneToMany(targetEntity="ShipCrew", mappedBy="ship", indexBy="id")
348
     * @OrderBy({"id": "ASC"})
349
     */
350
    private Collection $crew;
351
352
    /**
353
     * @OneToOne(targetEntity="TorpedoStorage", mappedBy="ship")
354
     */
355
    private ?TorpedoStorageInterface $torpedoStorage = null;
356
357
    /**
358
     * @var ArrayCollection<int, ShipSystemInterface>
359
     *
360
     * @OneToMany(targetEntity="ShipSystem", mappedBy="ship", indexBy="system_type")
361
     * @OrderBy({"system_type": "ASC"})
362
     */
363
    private Collection $systems;
364
365
    /**
366
     * @ManyToOne(targetEntity="ShipRump")
367
     * @JoinColumn(name="rumps_id", referencedColumnName="id")
368
     */
369
    private ShipRumpInterface $rump;
370
371
    /**
372
     * @ManyToOne(targetEntity="ShipBuildplan")
373
     * @JoinColumn(name="plans_id", referencedColumnName="id", onDelete="CASCADE")
374
     */
375
    private ?ShipBuildplanInterface $buildplan = null;
376
377
    /**
378
     * @var ArrayCollection<int, StorageInterface>
379
     *
380
     * @OneToMany(targetEntity="Storage", mappedBy="ship", indexBy="commodity_id")
381
     * @OrderBy({"commodity_id": "ASC"})
382
     */
383
    private Collection $storage;
384
385
    /**
386
     * @ManyToOne(targetEntity="Map")
387
     * @JoinColumn(name="map_id", referencedColumnName="id")
388
     */
389
    private ?MapInterface $map = null;
390
391
    /**
392
     * @ManyToOne(targetEntity="StarSystemMap")
393
     * @JoinColumn(name="starsystem_map_id", referencedColumnName="id")
394
     */
395
    private ?StarSystemMapInterface $starsystem_map = null;
396
397
    /**
398
     * @ManyToOne(targetEntity="StarSystem")
399
     * @JoinColumn(name="influence_area_id", referencedColumnName="id")
400
     */
401
    private ?StarSystemInterface $influenceArea = null;
402
403
    /**
404
     * @var ArrayCollection<int, ShipLogInterface>
405
     *
406
     * @OneToMany(targetEntity="ShipLog", mappedBy="ship", fetch="EXTRA_LAZY")
407
     * @OrderBy({"id": "DESC"})
408
     */
409
    private Collection $logbook;
410
411
    /**
412
     * @OneToOne(targetEntity="ShipTakeover", mappedBy="source")
413
     */
414
    private ?ShipTakeoverInterface $takeoverActive = null;
415
416
    /**
417
     * @OneToOne(targetEntity="ShipTakeover", mappedBy="target")
418
     */
419
    private ?ShipTakeoverInterface $takeoverPassive = null;
420
421
    public function __construct()
422
    {
423
        $this->dockedShips = new ArrayCollection();
424
        $this->dockingPrivileges = new ArrayCollection();
425
        $this->crew = new ArrayCollection();
426
        $this->systems = new ArrayCollection();
427
        $this->storage = new ArrayCollection();
428
        $this->logbook = new ArrayCollection();
429
    }
430
431
    public function getId(): int
432
    {
433
        if ($this->id === null) {
434
            throw new RuntimeException('entity not yet persisted');
435
        }
436
437
        return $this->id;
438
    }
439
440
    public function getUserId(): int
441
    {
442
        return $this->user_id;
443
    }
444
445
    public function getUserName(): string
446
    {
447
        return $this->getUser()->getName();
448
    }
449
450
    public function getFleetId(): ?int
451
    {
452
        return $this->fleets_id;
453
    }
454
455
    public function setFleetId(?int $fleetId): ShipInterface
456
    {
457
        $this->fleets_id = $fleetId;
458
        return $this;
459
    }
460
461
    public function getSystemsId(): ?int
462
    {
463
        return $this->getSystem() !== null ? $this->getSystem()->getId() : null;
464
    }
465
466
    public function getLayer(): ?LayerInterface
467
    {
468
        $map = $this->getMap();
469
        if ($map !== null) {
470
            return $map->getLayer();
471
        }
472
473
        return $this->getSystem()->getLayer();
474
    }
475
476
    public function getLayerId(): int
477
    {
478
        return $this->layer_id;
479
    }
480
481
    public function setLayerId(int $layerId): ShipInterface
482
    {
483
        $this->layer_id = $layerId;
484
        return $this;
485
    }
486
487
    public function getCx(): int
488
    {
489
        return $this->cx;
490
    }
491
492
    public function setCx(int $cx): ShipInterface
493
    {
494
        $this->cx = $cx;
495
        return $this;
496
    }
497
498
    public function getCy(): int
499
    {
500
        return $this->cy;
501
    }
502
503
    public function setCy(int $cy): ShipInterface
504
    {
505
        $this->cy = $cy;
506
        return $this;
507
    }
508
509
    public function getSx(): int
510
    {
511
        return $this->getStarsystemMap()->getSx();
512
    }
513
514
    public function getSy(): int
515
    {
516
        return $this->getStarsystemMap()->getSy();
517
    }
518
519
    public function getFlightDirection(): int
520
    {
521
        return $this->direction;
522
    }
523
524
    public function setFlightDirection(int $direction): ShipInterface
525
    {
526
        $this->direction = $direction;
527
        return $this;
528
    }
529
530
    public function getName(): string
531
    {
532
        return $this->name;
533
    }
534
535
    public function setName(string $name): ShipInterface
536
    {
537
        $this->name = $name;
538
        return $this;
539
    }
540
541
    public function getLSSmode(): int
542
    {
543
        return $this->lss_mode;
544
    }
545
546
    public function isLSSModeNormal(): bool
547
    {
548
        return $this->getLSSMode() === ShipLSSModeEnum::LSS_NORMAL;
549
    }
550
551
    public function isLSSModeBorder(): bool
552
    {
553
        return $this->getLSSMode() === ShipLSSModeEnum::LSS_BORDER;
554
    }
555
556
    public function setLSSMode(int $lssMode): ShipInterface
557
    {
558
        $this->lss_mode = $lssMode;
559
        return $this;
560
    }
561
562
    public function getAlertState(): ShipAlertStateEnum
563
    {
564
        return $this->alvl;
565
    }
566
567
    public function setAlertState(ShipAlertStateEnum $state): ShipInterface
568
    {
569
        $this->alvl = $state;
570
        return $this;
571
    }
572
573
    public function setAlertStateGreen(): ShipInterface
574
    {
575
        return $this->setAlertState(ShipAlertStateEnum::ALERT_GREEN);
576
    }
577
578
    public function isSystemHealthy(ShipSystemTypeEnum $type): bool
579
    {
580
        if (!$this->hasShipSystem($type)) {
581
            return false;
582
        }
583
584
        return $this->getShipSystem($type)->getStatus() > 0;
585
    }
586
587
    public function getSystemState(ShipSystemTypeEnum $type): bool
588
    {
589
        if (!$this->hasShipSystem($type)) {
590
            return false;
591
        }
592
593
        return $this->getShipSystem($type)->getMode() === ShipSystemModeEnum::MODE_ON
594
            || $this->getShipSystem($type)->getMode() === ShipSystemModeEnum::MODE_ALWAYS_ON;
595
    }
596
597
    public function getImpulseState(): bool
598
    {
599
        return $this->getSystemState(ShipSystemTypeEnum::SYSTEM_IMPULSEDRIVE);
600
    }
601
602
    public function getWarpState(): bool
603
    {
604
        return $this->getSystemState(ShipSystemTypeEnum::SYSTEM_WARPDRIVE);
605
    }
606
607
    public function getWebState(): bool
608
    {
609
        return $this->getHoldingWeb() !== null;
610
    }
611
612
    public function getTheoreticalReactorOutput(): int
613
    {
614
        return $this->reactor_output;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->reactor_output could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
615
    }
616
617
    public function getReactorLoad(): int
618
    {
619
        return $this->warpcore;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->warpcore could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
620
    }
621
622
    public function getCloakState(): bool
623
    {
624
        return $this->getSystemState(ShipSystemTypeEnum::SYSTEM_CLOAK);
625
    }
626
627
    public function getTachyonState(): bool
628
    {
629
        return $this->getSystemState(ShipSystemTypeEnum::SYSTEM_TACHYON_SCANNER);
630
    }
631
632
    public function getSubspaceState(): bool
633
    {
634
        return $this->getSystemState(ShipSystemTypeEnum::SYSTEM_SUBSPACE_SCANNER);
635
    }
636
637
    public function getAstroState(): bool
638
    {
639
        return $this->getSystemState(ShipSystemTypeEnum::SYSTEM_ASTRO_LABORATORY);
640
    }
641
642
    public function getRPGModuleState(): bool
643
    {
644
        return $this->getSystemState(ShipSystemTypeEnum::SYSTEM_RPG_MODULE);
645
    }
646
647
    public function getConstructionHubState(): bool
648
    {
649
        return $this->getSystemState(ShipSystemTypeEnum::SYSTEM_CONSTRUCTION_HUB);
650
    }
651
652
    public function getHull(): int
653
    {
654
        return $this->huelle;
655
    }
656
657
    public function setHuell(int $hull): ShipInterface
658
    {
659
        $this->huelle = $hull;
660
        return $this;
661
    }
662
663
    public function getMaxHull(): int
664
    {
665
        return $this->max_huelle;
666
    }
667
668
    public function setMaxHuell(int $maxHull): ShipInterface
669
    {
670
        $this->max_huelle = $maxHull;
671
        return $this;
672
    }
673
674
    public function getShield(): int
675
    {
676
        return $this->schilde;
677
    }
678
679
    public function setShield(int $schilde): ShipInterface
680
    {
681
        $this->schilde = $schilde;
682
        return $this;
683
    }
684
685
    /**
686
     * proportional to shield system status
687
     */
688
    public function getMaxShield(): int
689
    {
690
        if (!$this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_SHIELDS)) {
691
            return $this->max_schilde;
692
        }
693
694
        return (int) (ceil($this->max_schilde
695
            * $this->getShipSystem(ShipSystemTypeEnum::SYSTEM_SHIELDS)->getStatus() / 100));
696
    }
697
698
    public function setMaxShield(int $maxShields): ShipInterface
699
    {
700
        $this->max_schilde = $maxShields;
701
        return $this;
702
    }
703
704
    public function getShieldState(): bool
705
    {
706
        return $this->getSystemState(ShipSystemTypeEnum::SYSTEM_SHIELDS);
707
    }
708
709
    public function getNbs(): bool
710
    {
711
        return $this->getSystemState(ShipSystemTypeEnum::SYSTEM_NBS);
712
    }
713
714
    public function getLss(): bool
715
    {
716
        return $this->getSystemState(ShipSystemTypeEnum::SYSTEM_LSS);
717
    }
718
719
    public function getPhaserState(): bool
720
    {
721
        return $this->getSystemState(ShipSystemTypeEnum::SYSTEM_PHASER);
722
    }
723
724
    public function isAlertGreen(): bool
725
    {
726
        return $this->getAlertState() === ShipAlertStateEnum::ALERT_GREEN;
727
    }
728
729
    public function getTorpedoState(): bool
730
    {
731
        return $this->getSystemState(ShipSystemTypeEnum::SYSTEM_TORPEDO);
732
    }
733
734
    public function getFormerRumpId(): int
735
    {
736
        return $this->former_rumps_id;
737
    }
738
739
    public function setFormerRumpId(int $formerShipRumpId): ShipInterface
740
    {
741
        $this->former_rumps_id = $formerShipRumpId;
742
        return $this;
743
    }
744
745
    public function getTorpedoCount(): int
746
    {
747
        if ($this->getTorpedoStorage() === null) {
748
            return 0;
749
        }
750
751
        return $this->getTorpedoStorage()->getStorage()->getAmount();
752
    }
753
754
    public function isBase(): bool
755
    {
756
        return $this->type === SpacecraftTypeEnum::SPACECRAFT_TYPE_STATION;
757
    }
758
759
    public function isTrumfield(): bool
760
    {
761
        return $this->getRump()->isTrumfield();
762
    }
763
764
    public function isShuttle(): bool
765
    {
766
        return $this->getRump()->getCategoryId() === ShipRumpEnum::SHIP_CATEGORY_SHUTTLE;
767
    }
768
769
    public function isConstruction(): bool
770
    {
771
        return $this->getRump()->getCategoryId() === ShipRumpEnum::SHIP_CATEGORY_CONSTRUCTION;
772
    }
773
774
    public function getSpacecraftType(): int
775
    {
776
        return $this->type;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->type could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
777
    }
778
779
    public function setSpacecraftType(int $type): ShipInterface
780
    {
781
        $this->type = $type;
782
        return $this;
783
    }
784
785
    public function getDatabaseId(): int
786
    {
787
        return $this->database_id;
788
    }
789
790
    public function setDatabaseId(int $databaseEntryId): ShipInterface
791
    {
792
        $this->database_id = $databaseEntryId;
793
        return $this;
794
    }
795
796
    public function isDestroyed(): bool
797
    {
798
        return $this->is_destroyed;
799
    }
800
801
    public function setIsDestroyed(bool $isDestroyed): ShipInterface
802
    {
803
        $this->is_destroyed = $isDestroyed;
804
        return $this;
805
    }
806
807
    public function isDisabled(): bool
808
    {
809
        return $this->disabled;
810
    }
811
812
    public function setDisabled(bool $isDisabled): ShipInterface
813
    {
814
        $this->disabled = $isDisabled;
815
        return $this;
816
    }
817
818
819
820
    /**
821
     * proportional to computer system status
822
     */
823
    public function getHitChance(): int
824
    {
825
        if (!$this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_COMPUTER)) {
826
            return $this->hit_chance;
827
        }
828
829
        return (int) (ceil($this->hit_chance
830
            * $this->getShipSystem(ShipSystemTypeEnum::SYSTEM_COMPUTER)->getStatus() / 100));
831
    }
832
833
    public function setHitChance(int $hitChance): ShipInterface
834
    {
835
        $this->hit_chance = $hitChance;
836
        return $this;
837
    }
838
839
    /**
840
     * proportional to impulsedrive system status
841
     */
842
    public function getEvadeChance(): int
843
    {
844
        if (!$this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_IMPULSEDRIVE)) {
845
            return $this->evade_chance;
846
        }
847
848
        return (int) (ceil($this->evade_chance
849
            * $this->getShipSystem(ShipSystemTypeEnum::SYSTEM_IMPULSEDRIVE)->getStatus() / 100));
850
    }
851
852
    public function setEvadeChance(int $evadeChance): ShipInterface
853
    {
854
        $this->evade_chance = $evadeChance;
855
        return $this;
856
    }
857
858
    /**
859
     * proportional to energy weapon system status
860
     */
861
    public function getBaseDamage(): int
862
    {
863
        if (!$this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_PHASER)) {
864
            return $this->base_damage;
865
        }
866
867
        return (int) (ceil($this->base_damage
868
            * $this->getShipSystem(ShipSystemTypeEnum::SYSTEM_PHASER)->getStatus() / 100));
869
    }
870
871
    public function setBaseDamage(int $baseDamage): ShipInterface
872
    {
873
        $this->base_damage = $baseDamage;
874
        return $this;
875
    }
876
877
    /**
878
     * proportional to sensor system status
879
     */
880
    public function getSensorRange(): int
881
    {
882
        if (!$this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_LSS)) {
883
            return $this->sensor_range;
884
        }
885
886
        return (int) (ceil($this->sensor_range
887
            * $this->getShipSystem(ShipSystemTypeEnum::SYSTEM_LSS)->getStatus() / 100));
888
    }
889
890
    public function setSensorRange(int $sensorRange): ShipInterface
891
    {
892
        $this->sensor_range = $sensorRange;
893
        return $this;
894
    }
895
896
    /**
897
     * proportional to tractor beam system status
898
     */
899
    public function getTractorPayload(): int
900
    {
901
        if (!$this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_TRACTOR_BEAM)) {
902
            return 0;
903
        }
904
905
        return (int) (ceil($this->getRump()->getTractorPayload()
906
            * $this->getShipSystem(ShipSystemTypeEnum::SYSTEM_TRACTOR_BEAM)->getStatus() / 100));
907
    }
908
909
    public function getShieldRegenerationTimer(): int
910
    {
911
        return $this->shield_regeneration_timer;
912
    }
913
914
    public function setShieldRegenerationTimer(int $shieldRegenerationTimer): ShipInterface
915
    {
916
        $this->shield_regeneration_timer = $shieldRegenerationTimer;
917
        return $this;
918
    }
919
920
    public function getState(): ShipStateEnum
921
    {
922
        return $this->state;
923
    }
924
925
    public function setState(ShipStateEnum $state): ShipInterface
926
    {
927
        $this->state = $state;
928
        return $this;
929
    }
930
931
    public function getIsInEmergency(): bool
932
    {
933
        return $this->in_emergency;
934
    }
935
936
    public function setIsInEmergency(bool $inEmergency): ShipInterface
937
    {
938
        $this->in_emergency = $inEmergency;
939
        return $this;
940
    }
941
942
    public function isUnderRepair(): bool
943
    {
944
        return $this->getState() === ShipStateEnum::SHIP_STATE_REPAIR_ACTIVE
945
            || $this->getState() === ShipStateEnum::SHIP_STATE_REPAIR_PASSIVE;
946
    }
947
948
    public function getAstroStartTurn(): ?int
949
    {
950
        return $this->astro_start_turn;
951
    }
952
953
    public function setAstroStartTurn(?int $turn): ShipInterface
954
    {
955
        $this->astro_start_turn = $turn;
956
        return $this;
957
    }
958
959
    public function getIsFleetLeader(): bool
960
    {
961
        return $this->getFleet() !== null && $this->is_fleet_leader;
962
    }
963
964
    public function setIsFleetLeader(bool $isFleetLeader): ShipInterface
965
    {
966
        $this->is_fleet_leader = $isFleetLeader;
967
        return $this;
968
    }
969
970
    public function getCrewAssignments(): Collection
971
    {
972
        return $this->crew;
973
    }
974
975
    public function getPosX(): int
976
    {
977
        if ($this->getSystem() !== null) {
978
            return $this->getSX();
979
        }
980
        return $this->getCX();
981
    }
982
983
    public function getPosY(): int
984
    {
985
        if ($this->getSystem() !== null) {
986
            return $this->getSY();
987
        }
988
        return $this->getCY();
989
    }
990
991
    public function getCrewCount(): int
992
    {
993
        return $this->getCrewAssignments()->count();
994
    }
995
996
    public function getExcessCrewCount(): int
997
    {
998
        return $this->getCrewCount() - $this->getBuildplan()->getCrew();
999
    }
1000
1001
    public function hasEnoughCrew(?GameControllerInterface $game = null): bool
1002
    {
1003
        if ($this->getBuildplan() === null) {
1004
            if ($game !== null) {
1005
                $game->addInformation(_("Keine Crew vorhanden"));
1006
            }
1007
            return false;
1008
        }
1009
1010
        $result = $this->getBuildplan()->getCrew() <= 0
1011
            || $this->getCrewCount() >= $this->getBuildplan()->getCrew();
1012
1013
        if (!$result && $game !== null) {
1014
            $game->addInformationf(
1015
                _("Es werden %d Crewmitglieder benötigt"),
1016
                $this->getBuildplan()->getCrew()
1017
            );
1018
        }
1019
1020
        return $result;
1021
    }
1022
1023
    public function getFleet(): ?FleetInterface
1024
    {
1025
        return $this->fleet;
1026
    }
1027
1028
    public function setFleet(?FleetInterface $fleet): ShipInterface
1029
    {
1030
        $this->fleet = $fleet;
1031
        return $this;
1032
    }
1033
1034
    public function isFleetLeader(): bool
1035
    {
1036
        return $this->getIsFleetLeader();
1037
    }
1038
1039
    public function getUser(): UserInterface
1040
    {
1041
        return $this->user;
1042
    }
1043
1044
    public function setUser(UserInterface $user): ShipInterface
1045
    {
1046
        $this->user = $user;
1047
        return $this;
1048
    }
1049
1050
    public function getSystem(): ?StarSystemInterface
1051
    {
1052
        return $this->getStarsystemMap() !== null ? $this->getStarsystemMap()->getSystem() : null;
1053
    }
1054
1055
    public function getModules(): array
1056
    {
1057
        $modules = [];
1058
1059
        foreach ($this->getBuildplan()->getModules() as $obj) {
1060
            $module = $obj->getModule();
1061
            $index = $module->getType() === ShipModuleTypeEnum::MODULE_TYPE_SPECIAL ? $module->getId() : $module->getType();
1062
            $modules[$index] = $module;
1063
        }
1064
1065
        if ($this->isBase()) {
1066
            foreach ($this->getSystems() as $system) {
1067
                $module = $system->getModule();
1068
1069
                if ($module !== null) {
1070
                    $index = $module->getType() === ShipModuleTypeEnum::MODULE_TYPE_SPECIAL ? $module->getId() : $module->getType();
1071
                    $modules[$index] = $module;
1072
                }
1073
            }
1074
        }
1075
1076
        return $modules;
1077
    }
1078
1079
    public function isDeflectorHealthy(): bool
1080
    {
1081
        return $this->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_DEFLECTOR);
1082
    }
1083
1084
    public function isTroopQuartersHealthy(): bool
1085
    {
1086
        return $this->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS);
1087
    }
1088
1089
    public function isMatrixScannerHealthy(): bool
1090
    {
1091
        return $this->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_MATRIX_SCANNER);
1092
    }
1093
1094
    public function isTorpedoStorageHealthy(): bool
1095
    {
1096
        return $this->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_TORPEDO_STORAGE);
1097
    }
1098
1099
    public function isShuttleRampHealthy(): bool
1100
    {
1101
        return $this->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_SHUTTLE_RAMP);
1102
    }
1103
1104
    public function isWebEmitterHealthy(): bool
1105
    {
1106
        return $this->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_THOLIAN_WEB);
1107
    }
1108
1109
    public function isWarpAble(): bool
1110
    {
1111
        return $this->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_WARPDRIVE);
1112
    }
1113
1114
    public function isTractoring(): bool
1115
    {
1116
        return $this->getTractoredShip() !== null;
1117
    }
1118
1119
    public function isTractored(): bool
1120
    {
1121
        return $this->getTractoringShip() !== null;
1122
    }
1123
1124
    public function isOverColony(): ?ColonyInterface
1125
    {
1126
        return $this->getStarsystemMap() !== null ? $this->getStarsystemMap()->getColony() : null;
1127
    }
1128
1129
    public function isOverSystem(): ?StarSystemInterface
1130
    {
1131
        if ($this->getSystem() !== null) {
1132
            return null;
1133
        }
1134
1135
        return $this->getMap()->getSystem();
1136
    }
1137
1138
    public function isOverWormhole(): bool
1139
    {
1140
        return $this->getMap() !== null && $this->getMap()->getRandomWormholeEntry() !== null;
1141
    }
1142
1143
    public function isWarpPossible(): bool
1144
    {
1145
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_WARPDRIVE) && $this->getSystem() === null;
1146
    }
1147
1148
    public function getTorpedo(): ?TorpedoTypeInterface
1149
    {
1150
        if ($this->getTorpedoStorage() === null) {
1151
            return null;
1152
        }
1153
1154
        return $this->getTorpedoStorage()->getTorpedo();
1155
    }
1156
1157
    public function getTorpedoStorage(): ?TorpedoStorageInterface
1158
    {
1159
        return $this->torpedoStorage;
1160
    }
1161
1162
    public function setTorpedoStorage(?TorpedoStorageInterface $torpedoStorage): ShipInterface
1163
    {
1164
        $this->torpedoStorage = $torpedoStorage;
1165
        return $this;
1166
    }
1167
1168
    public function getStorage(): Collection
1169
    {
1170
        return $this->storage;
1171
    }
1172
1173
    public function getLogbook(): Collection
1174
    {
1175
        return $this->logbook;
1176
    }
1177
1178
    public function getTakeoverActive(): ?ShipTakeoverInterface
1179
    {
1180
        return $this->takeoverActive;
1181
    }
1182
1183
    public function setTakeoverActive(?ShipTakeoverInterface $takeover): ShipInterface
1184
    {
1185
        $this->takeoverActive = $takeover;
1186
1187
        return $this;
1188
    }
1189
1190
    public function getTakeoverPassive(): ?ShipTakeoverInterface
1191
    {
1192
        return $this->takeoverPassive;
1193
    }
1194
1195
    public function setTakeoverPassive(?ShipTakeoverInterface $takeover): ShipInterface
1196
    {
1197
        $this->takeoverPassive = $takeover;
1198
1199
        return $this;
1200
    }
1201
1202
    public function getStorageSum(): int
1203
    {
1204
        return array_reduce(
1205
            $this->getStorage()->getValues(),
1206
            fn (int $sum, StorageInterface $storage): int => $sum + $storage->getAmount(),
1207
            0
1208
        );
1209
    }
1210
1211
    public function getMaxStorage(): int
1212
    {
1213
        return $this->getRump()->getStorage();
1214
    }
1215
1216
    public function getBeamableStorage(): array
1217
    {
1218
        return array_filter(
1219
            $this->getStorage()->getValues(),
1220
            fn (StorageInterface $storage): bool => $storage->getCommodity()->isBeamable() === true
1221
        );
1222
    }
1223
1224
    public function getTradePost(): ?TradePostInterface
1225
    {
1226
        return $this->tradePost;
1227
    }
1228
1229
    public function setTradePost(?TradePostInterface $tradePost): ShipInterface
1230
    {
1231
        $this->tradePost = $tradePost;
1232
1233
        return $this;
1234
    }
1235
1236
    public function getMap(): ?MapInterface
1237
    {
1238
        return $this->map;
1239
    }
1240
1241
    public function getMapRegion(): ?MapRegionInterface
1242
    {
1243
        $map = $this->getMap();
1244
        if ($map === null) {
1245
            return null;
1246
        }
1247
1248
        return $map->getMapRegion();
1249
    }
1250
1251
    public function updateLocation(?MapInterface $map, ?StarSystemMapInterface $starsystem_map): ShipInterface
1252
    {
1253
        $this->setMap($map);
1254
        $this->setStarsystemMap($starsystem_map);
1255
1256
        return $this;
1257
    }
1258
1259
    public function setMap(?MapInterface $map): ShipInterface
1260
    {
1261
        $this->map = $map;
1262
1263
        if ($map !== null) {
1264
            $this->setLayerId($map->getLayer()->getId());
1265
            $this->setCx($map->getCx());
1266
            $this->setCy($map->getCy());
1267
        }
1268
1269
        return $this;
1270
    }
1271
1272
    public function getStarsystemMap(): ?StarSystemMapInterface
1273
    {
1274
        return $this->starsystem_map;
1275
    }
1276
1277
    public function setStarsystemMap(?StarSystemMapInterface $systemMap): ShipInterface
1278
    {
1279
        $this->starsystem_map = $systemMap;
1280
1281
        if ($systemMap !== null) {
1282
            $system = $systemMap->getSystem();
1283
            $layer = $system->getLayer();
1284
            if ($layer === null) {
1285
                $this->setLayerId(MapEnum::LAYER_ID_WORMHOLES);
1286
            } else {
1287
                $this->setLayerId($layer->getId());
1288
            }
1289
            $this->setCx($systemMap->getSystem()->getCx());
1290
            $this->setCy($systemMap->getSystem()->getCy());
1291
        }
1292
1293
        return $this;
1294
    }
1295
1296
    public function getLocation(): Location
1297
    {
1298
        return new Location($this->getMap(), $this->getStarsystemMap());
1299
    }
1300
1301
    public function getInfluenceArea(): ?StarSystemInterface
1302
    {
1303
        return $this->influenceArea;
1304
    }
1305
1306
    public function setInfluenceArea(?StarSystemInterface $influenceArea): ShipInterface
1307
    {
1308
        $this->influenceArea = $influenceArea;
1309
        return $this;
1310
    }
1311
1312
    public function getBeamFactor(): int
1313
    {
1314
        return $this->getRump()->getBeamFactor();
1315
    }
1316
1317
    public function getSectorString(): string
1318
    {
1319
        if ($this->getStarsystemMap() !== null) {
1320
            return $this->getStarsystemMap()->getSectorString();
1321
        } else {
1322
            return $this->getMap()->getSectorString();
1323
        }
1324
    }
1325
1326
    public function getSectorId(): ?int
1327
    {
1328
        $layer = $this->getLayer();
1329
        if ($layer === null) {
1330
            return null;
1331
        }
1332
1333
        return $layer->getSectorId($this->getMapCX(), $this->getMapCY());
1334
    }
1335
1336
    public function getBuildplan(): ?ShipBuildplanInterface
1337
    {
1338
        return $this->buildplan;
1339
    }
1340
1341
    public function setBuildplan(?ShipBuildplanInterface $shipBuildplan): ShipInterface
1342
    {
1343
        $this->buildplan = $shipBuildplan;
1344
        return $this;
1345
    }
1346
1347
    public function getSystems(): Collection
1348
    {
1349
        return $this->systems;
1350
    }
1351
1352
    public function hasShipSystem(ShipSystemTypeEnum $type): bool
1353
    {
1354
        return $this->getSystems()->containsKey($type->value);
1355
    }
1356
1357
    public function getShipSystem(ShipSystemTypeEnum $type): ShipSystemInterface
1358
    {
1359
        $system = $this->getSystems()->get($type->value);
1360
        if ($system === null) {
1361
            throw new RuntimeException(sprintf('system type %d does not exist on ship', $type->value));
1362
        }
1363
1364
        return $system;
1365
    }
1366
1367
    public function getHealthySystems(): array
1368
    {
1369
        $healthySystems = [];
1370
        foreach ($this->getSystems() as $system) {
1371
            if ($system->getStatus() > 0) {
1372
                $healthySystems[] = $system;
1373
            }
1374
        }
1375
        return $healthySystems;
1376
    }
1377
1378
    public function displayNbsActions(): bool
1379
    {
1380
        return $this->getCloakState() == 0 && $this->getWarpstate() == 0;
1381
    }
1382
1383
    public function isTractorbeamPossible(): bool
1384
    {
1385
        return TractorBeamShipSystem::isTractorBeamPossible($this);
1386
    }
1387
1388
    public function isBoardingPossible(): bool
1389
    {
1390
        return FightLib::isBoardingPossible($this);
1391
    }
1392
1393
    public function isInterceptAble(): bool
1394
    {
1395
        return $this->getWarpState();
1396
    }
1397
1398
    public function getMapCX(): int
1399
    {
1400
        return (int) ceil($this->getCX() / MapEnum::FIELDS_PER_SECTION);
1401
    }
1402
1403
    public function getMapCY(): int
1404
    {
1405
        return (int) ceil($this->getCY() / MapEnum::FIELDS_PER_SECTION);
1406
    }
1407
1408
    public function dockedOnTradePost(): bool
1409
    {
1410
        return $this->getDockedTo() && $this->getDockedTo()->getTradePost() !== null;
1411
    }
1412
1413
    public function getDockPrivileges(): Collection
1414
    {
1415
        return $this->dockingPrivileges;
1416
    }
1417
1418
    public function getDockingSlotCount(): int
1419
    {
1420
        return ($this->getState() === ShipStateEnum::SHIP_STATE_UNDER_CONSTRUCTION)
1421
            || ($this->getState() === ShipStateEnum::SHIP_STATE_UNDER_SCRAPPING)
1422
            ? 50 : $this->getRump()->getDockingSlots();
1423
    }
1424
1425
    public function hasFreeDockingSlots(): bool
1426
    {
1427
        return $this->getDockingSlotCount() > $this->getDockedShipCount();
1428
    }
1429
1430
    public function getFreeDockingSlotCount(): int
1431
    {
1432
        return $this->getDockingSlotCount() - $this->getDockedShipCount();
1433
    }
1434
1435
    public function getDockedShipCount(): int
1436
    {
1437
        return $this->dockedShips->count();
1438
    }
1439
1440
    public function getTractoredShip(): ?ShipInterface
1441
    {
1442
        return $this->tractoredShip;
1443
    }
1444
1445
    public function setTractoredShip(?ShipInterface $ship): ShipInterface
1446
    {
1447
        $this->tractoredShip = $ship;
1448
        return $this;
1449
    }
1450
1451
    public function setTractoredShipId(?int $shipId): ShipInterface
1452
    {
1453
        $this->tractored_ship_id = $shipId;
1454
        return $this;
1455
    }
1456
1457
    public function getTractoringShip(): ?ShipInterface
1458
    {
1459
        return $this->tractoringShip;
1460
    }
1461
1462
    public function setTractoringShip(?ShipInterface $ship): ShipInterface
1463
    {
1464
        $this->tractoringShip = $ship;
1465
        return $this;
1466
    }
1467
1468
    public function getHoldingWeb(): ?TholianWebInterface
1469
    {
1470
        return $this->holdingWeb;
1471
    }
1472
1473
    public function setHoldingWeb(?TholianWebInterface $web): ShipInterface
1474
    {
1475
        $this->holdingWeb = $web;
1476
1477
        if ($web === null) {
1478
            $this->holding_web_id = null;
1479
        }
1480
1481
        return $this;
1482
    }
1483
1484
    public function getHoldingWebBackgroundStyle(): string
1485
    {
1486
        if ($this->getHoldingWeb() === null) {
1487
            return '';
1488
        }
1489
1490
        if ($this->getHoldingWeb()->isFinished()) {
1491
            $icon =  'web.png';
1492
        } else {
1493
            $closeTofinish = $this->getHoldingWeb()->getFinishedTime() - time() < TimeConstants::ONE_HOUR_IN_SECONDS;
1494
1495
            $icon = $closeTofinish ? 'web_u.png' : 'web_u2.png';
1496
        }
1497
1498
        return sprintf('src="assets/buttons/%s"; class="indexedGraphics" style="z-index: 5;"', $icon);
1499
    }
1500
1501
    public function getHoldingWebImageStyle(): string
1502
    {
1503
        if ($this->getHoldingWeb() === null) {
1504
            return '';
1505
        }
1506
1507
        if ($this->getHoldingWeb()->isFinished()) {
1508
            $icon =  'webfill.png';
1509
        } else {
1510
            $closeTofinish = $this->getHoldingWeb()->getFinishedTime() - time() < TimeConstants::ONE_HOUR_IN_SECONDS;
1511
1512
            $icon = $closeTofinish ? 'web_ufill.png' : 'web_ufill2.png';
1513
        }
1514
1515
        return $icon;
1516
    }
1517
1518
    public function getCurrentMapField(): StarSystemMapInterface|MapInterface
1519
    {
1520
        return $this->getStarsystemMap() ?? $this->getMap();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getStarsys...ap() ?? $this->getMap() could return the type null which is incompatible with the type-hinted return Stu\Orm\Entity\MapInterf...\StarSystemMapInterface. Consider adding an additional type-check to rule them out.
Loading history...
1521
    }
1522
1523
    private function getShieldRegenerationPercentage(): int
1524
    {
1525
        return $this->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_SHIELDS) ? 10 : 0;
1526
    }
1527
1528
    public function getShieldRegenerationRate(): int
1529
    {
1530
        return (int) ceil(($this->getMaxShield() / 100) * $this->getShieldRegenerationPercentage());
1531
    }
1532
1533
    public function canIntercept(): bool
1534
    {
1535
        return !$this->isTractored() && !$this->isTractoring();
1536
    }
1537
1538
    public function canMove(): bool
1539
    {
1540
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_WARPDRIVE)
1541
            || $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_IMPULSEDRIVE);
1542
    }
1543
1544
    public function hasActiveWeapon(): bool
1545
    {
1546
        return $this->getPhaserState() || $this->getTorpedoState();
1547
    }
1548
1549
    public function hasEscapePods(): bool
1550
    {
1551
        return $this->getRump()->isEscapePods() && $this->getCrewCount() > 0;
1552
    }
1553
1554
    public function getRepairRate(): int
1555
    {
1556
        // @todo
1557
        return 100;
1558
    }
1559
1560
    public function getRump(): ShipRumpInterface
1561
    {
1562
        return $this->rump;
1563
    }
1564
1565
    public function getRumpId(): int
1566
    {
1567
        return $this->rumps_id;
1568
    }
1569
1570
    public function getRumpName(): string
1571
    {
1572
        return $this->getRump()->getName();
1573
    }
1574
1575
    public function setRump(ShipRumpInterface $shipRump): ShipInterface
1576
    {
1577
        $this->rump = $shipRump;
1578
        return $this;
1579
    }
1580
1581
    public function hasPhaser(): bool
1582
    {
1583
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_PHASER);
1584
    }
1585
1586
    public function hasTorpedo(): bool
1587
    {
1588
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_TORPEDO);
1589
    }
1590
1591
    public function hasCloak(): bool
1592
    {
1593
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_CLOAK);
1594
    }
1595
1596
    public function hasTachyonScanner(): bool
1597
    {
1598
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_TACHYON_SCANNER);
1599
    }
1600
1601
    public function hasShuttleRamp(): bool
1602
    {
1603
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_SHUTTLE_RAMP);
1604
    }
1605
1606
    public function hasSubspaceScanner(): bool
1607
    {
1608
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_SUBSPACE_SCANNER);
1609
    }
1610
1611
    public function hasAstroLaboratory(): bool
1612
    {
1613
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_ASTRO_LABORATORY);
1614
    }
1615
1616
    public function hasWarpdrive(): bool
1617
    {
1618
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_WARPDRIVE);
1619
    }
1620
1621
    public function hasRPGModule(): bool
1622
    {
1623
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_RPG_MODULE);
1624
    }
1625
1626
    public function hasNbsLss(): bool
1627
    {
1628
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_LSS);
1629
    }
1630
1631
    public function hasUplink(): bool
1632
    {
1633
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_UPLINK);
1634
    }
1635
1636
    public function hasTranswarp(): bool
1637
    {
1638
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_TRANSWARP_COIL);
1639
    }
1640
1641
    public function getTranswarpCooldown(): ?int
1642
    {
1643
        $cooldown = $this->getShipSystem(ShipSystemTypeEnum::SYSTEM_TRANSWARP_COIL)->getCooldown();
1644
1645
        return $cooldown > time() ? $cooldown : null;
1646
    }
1647
1648
    public function getMaxTorpedos(): int
1649
    {
1650
        return $this->getRump()->getBaseTorpedoStorage()
1651
            + ($this->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_TORPEDO_STORAGE)
1652
                ? TorpedoStorageShipSystem::TORPEDO_CAPACITY : 0);
1653
    }
1654
1655
    public function getDockedShips(): Collection
1656
    {
1657
        return $this->dockedShips;
1658
    }
1659
1660
    public function getDockedTo(): ?ShipInterface
1661
    {
1662
        return $this->dockedTo;
1663
    }
1664
1665
    public function setDockedTo(?ShipInterface $dockedTo): ShipInterface
1666
    {
1667
        $this->dockedTo = $dockedTo;
1668
        return $this;
1669
    }
1670
1671
    public function setDockedToId(?int $dockedToId): ShipInterface
1672
    {
1673
        $this->dock = $dockedToId;
1674
        return $this;
1675
    }
1676
1677
    public function hasFreeShuttleSpace(?LoggerUtilInterface $loggerUtil = null): bool
1678
    {
1679
        if ($loggerUtil !== null) {
1680
            $loggerUtil->log(sprintf('rumpShuttleSlots: %d', $this->getRump()->getShuttleSlots()));
1681
            $loggerUtil->log(sprintf('storedShuttleCount: %d', $this->getStoredShuttleCount()));
1682
        }
1683
        return $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_SHUTTLE_RAMP)
1684
            && $this->getRump()->getShuttleSlots() - $this->getStoredShuttleCount() > 0;
1685
    }
1686
1687
    public function getStoredShuttles(): array
1688
    {
1689
        $shuttles = [];
1690
1691
        foreach ($this->getStorage() as $stor) {
1692
            if ($stor->getCommodity()->isShuttle()) {
1693
                $shuttles[] = $stor->getCommodity();
1694
            }
1695
        }
1696
1697
        return $shuttles;
1698
    }
1699
1700
    public function getStoredShuttleCount(): int
1701
    {
1702
        $count = 0;
1703
1704
        foreach ($this->getStorage() as $stor) {
1705
            if ($stor->getCommodity()->isShuttle()) {
1706
                $count += $stor->getAmount();
1707
            }
1708
        }
1709
1710
        return $count;
1711
    }
1712
1713
    public function getDockedWorkbeeCount(): int
1714
    {
1715
        $count = 0;
1716
1717
        foreach ($this->getDockedShips() as $ships) {
1718
            if ($ships->getRump()->getCategoryId() === ShipRumpEnum::SHIP_CATEGORY_SHUTTLE) {
1719
                $count += 1;
1720
            }
1721
        }
1722
1723
        return $count;
1724
    }
1725
1726
    public function canMan(): bool
1727
    {
1728
        return $this->getCrewCount() === 0
1729
            && $this->getBuildplan() !== null
1730
            && $this->getBuildplan()->getCrew() > 0
1731
            && $this->hasShipSystem(ShipSystemTypeEnum::SYSTEM_LIFE_SUPPORT);
1732
    }
1733
1734
    public function canBuildConstruction(): bool
1735
    {
1736
        return StationUtility::canShipBuildConstruction($this);
1737
    }
1738
1739
    public function hasCrewmanOfUser(int $userId): bool
1740
    {
1741
        foreach ($this->getCrewAssignments() as $shipCrew) {
1742
            if ($shipCrew->getCrew()->getUser()->getId() === $userId) {
1743
                return true;
1744
            }
1745
        }
1746
1747
        return false;
1748
    }
1749
1750
    public function __toString(): string
1751
    {
1752
        if ($this->id !== null) {
1753
            return sprintf('id: %d, name: %s', $this->getId(), $this->getName());
1754
        }
1755
1756
        return $this->getName();
1757
    }
1758
1759
    public function getHullColorStyle(): string
1760
    {
1761
        return $this->getColorStyle($this->getHull(), $this->getMaxHull());
1762
    }
1763
1764
    private function getColorStyle(int $actual, int $max): string
1765
    {
1766
        // full
1767
        if ($actual === $max) {
1768
            return '';
1769
        }
1770
1771
        // less than 100% - green
1772
        if ($actual / $max > 0.75) {
1773
            return 'color: #19c100;';
1774
        }
1775
1776
        // less than 75% - yellow
1777
        if ($actual / $max > 0.50) {
1778
            return 'color: #f4e932;';
1779
        }
1780
1781
        // less than 50% - orange
1782
        if ($actual / $max > 0.25) {
1783
            return 'color: #f48b28;';
1784
        }
1785
1786
        // less than 25% - red
1787
        return 'color: #ff3c3c;';
1788
    }
1789
}
1790