Passed
Push — master ( 48bfaa...170129 )
by Nico
25:44
created

ShipAttackCore::sendPms()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 8
nc 1
nop 4
dl 0
loc 17
ccs 0
cts 10
cp 0
crap 6
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Ship\Lib\Battle;
6
7
use RuntimeException;
8
use Stu\Lib\Information\InformationWrapper;
9
use Stu\Module\Message\Lib\DistributedMessageSenderInterface;
10
use Stu\Module\Message\Lib\PrivateMessageFolderSpecialEnum;
11
use Stu\Module\Ship\Lib\Battle\AlertRedHelperInterface;
12
use Stu\Module\Ship\Lib\Battle\FightLibInterface;
13
use Stu\Module\Ship\Lib\Message\MessageCollectionInterface;
14
use Stu\Module\Ship\Lib\Battle\ShipAttackCycleInterface;
15
use Stu\Module\Ship\Lib\FleetWrapperInterface;
16
use Stu\Module\Ship\Lib\ShipWrapperFactoryInterface;
17
use Stu\Module\Ship\Lib\ShipWrapperInterface;
18
use Stu\Orm\Entity\ShipInterface;
19
20
final class ShipAttackCore implements ShipAttackCoreInterface
21
{
22
    private DistributedMessageSenderInterface $distributedMessageSender;
23
24
    private ShipAttackCycleInterface $shipAttackCycle;
25
26
    private AlertRedHelperInterface $alertRedHelper;
27
28
    private FightLibInterface $fightLib;
29
30
    private ShipWrapperFactoryInterface $shipWrapperFactory;
31
32
    public function __construct(
33
        DistributedMessageSenderInterface $distributedMessageSender,
34
        ShipAttackCycleInterface $shipAttackCycle,
35
        AlertRedHelperInterface $alertRedHelper,
36
        FightLibInterface $fightLib,
37
        ShipWrapperFactoryInterface $shipWrapperFactory
38
    ) {
39
        $this->distributedMessageSender = $distributedMessageSender;
40
        $this->shipAttackCycle = $shipAttackCycle;
41
        $this->alertRedHelper = $alertRedHelper;
42
        $this->fightLib = $fightLib;
43
        $this->shipWrapperFactory = $shipWrapperFactory;
44
    }
45
46
    public function attack(
47
        ShipWrapperInterface|FleetWrapperInterface $wrapper,
48
        ShipWrapperInterface $targetWrapper,
49
        bool &$isFleetFight,
50
        InformationWrapper $informations
51
    ): void {
52
        $ship = $wrapper instanceof ShipWrapperInterface ?  $wrapper->get() : $wrapper->get()->getLeadShip();
53
54
        $target = $targetWrapper->get();
55
        $userId = $ship->getUser()->getId();
56
        $isTargetBase = $target->isBase();
57
58
        $isActiveTractorShipWarped = $this->isActiveTractorShipWarped($ship, $target);
59
60
        [$attacker, $defender, $isFleetFight, $isWebSituation] = $this->getAttackersAndDefenders(
61
            $wrapper,
62
            $targetWrapper
63
        );
64
65
        $messageCollection = $this->shipAttackCycle->cycle($attacker, $defender, $isWebSituation);
66
67
        $this->sendPms(
68
            $userId,
69
            $ship->getSectorString(),
70
            $messageCollection,
71
            !$isWebSituation && $isTargetBase
72
        );
73
74
        $informations->addInformationWrapper($messageCollection->getInformationDump());
75
76
        if ($isActiveTractorShipWarped) {
77
            //Alarm-Rot check for ship
78
            if (!$ship->isDestroyed()) {
79
                $this->alertRedHelper->doItAll($ship, $informations);
80
            }
81
82
            //Alarm-Rot check for traktor ship
83
            if (!$this->isTargetDestroyed($target)) {
84
                $this->alertRedHelper->doItAll($target, $informations);
85
            }
86
        }
87
    }
88
89
    private function isTargetDestroyed(ShipInterface $ship): bool
90
    {
91
        return $ship->isDestroyed();
92
    }
93
94
    private function isActiveTractorShipWarped(ShipInterface $ship, ShipInterface $target): bool
95
    {
96
        $tractoringShip = $ship->getTractoringShip();
97
        if ($tractoringShip === null) {
98
            return false;
99
        }
100
101
        if ($tractoringShip !== $target) {
102
            return false;
103
        } else {
104
            return $target->getWarpDriveState();
105
        }
106
    }
107
108
    private function sendPms(
109
        int $userId,
110
        string $sectorString,
111
        MessageCollectionInterface $messageCollection,
112
        bool $isTargetBase
113
    ): void {
114
115
        $header = sprintf(
116
            _("Kampf in Sektor %s"),
117
            $sectorString
118
        );
119
120
        $this->distributedMessageSender->distributeMessageCollection(
121
            $messageCollection,
122
            $userId,
123
            $isTargetBase ? PrivateMessageFolderSpecialEnum::PM_SPECIAL_STATION : PrivateMessageFolderSpecialEnum::PM_SPECIAL_SHIP,
124
            $header
125
        );
126
    }
127
128
    /**
129
     * @return array{0: array<int, ShipWrapperInterface>, 1: array<int, ShipWrapperInterface>, 2: bool, 3: bool}
130
     */
131
    private function getAttackersAndDefenders(ShipWrapperInterface|FleetWrapperInterface $wrapper, ShipWrapperInterface $targetWrapper): array
132
    {
133
        $ship = $wrapper instanceof ShipWrapperInterface ?  $wrapper->get() : $wrapper->get()->getLeadShip();
134
135
        [$attacker, $defender, $isFleetFight] = $this->fightLib->getAttackersAndDefenders($wrapper, $targetWrapper);
136
137
        $isWebSituation = $this->fightLib->isTargetOutsideFinishedTholianWeb($ship, $targetWrapper->get());
138
139
        //if in tholian web and defenders outside, reflect damage
140
        if ($isWebSituation) {
141
            $holdingWeb = $ship->getHoldingWeb();
142
            if ($holdingWeb === null) {
143
                throw new RuntimeException('this should not happen');
144
            }
145
146
            $defender = $this->shipWrapperFactory->wrapShips($holdingWeb->getCapturedShips()->toArray());
147
        }
148
149
        return [
150
            $attacker,
151
            $defender,
152
            $isFleetFight,
153
            $isWebSituation
154
        ];
155
    }
156
}
157