ProjectileWeaponPhase::fireAtBuilding()   C
last analyzed

Complexity

Conditions 11
Paths 5

Size

Total Lines 84
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 132

Importance

Changes 0
Metric Value
cc 11
eloc 52
nc 5
nop 4
dl 0
loc 84
ccs 0
cts 55
cp 0
crap 132
rs 6.9006
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Spacecraft\Lib\Battle\Weapon;
6
7
use Stu\Component\Spacecraft\SpacecraftModuleTypeEnum;
8
use Stu\Lib\Damage\DamageWrapper;
9
use Stu\Lib\Information\InformationWrapper;
10
use Stu\Module\Spacecraft\Lib\Battle\Party\BattlePartyInterface;
11
use Stu\Module\Spacecraft\Lib\Battle\Provider\ProjectileAttackerInterface;
12
use Stu\Module\Spacecraft\Lib\Battle\SpacecraftAttackCauseEnum;
13
use Stu\Module\Spacecraft\Lib\Message\MessageCollectionInterface;
14
use Stu\Orm\Entity\Colony;
15
use Stu\Orm\Entity\PlanetField;
16
use Stu\Orm\Entity\Spacecraft;
17
use Stu\Orm\Entity\TorpedoType;
18
19
//TODO unit tests
20
final class ProjectileWeaponPhase extends AbstractWeaponPhase implements ProjectileWeaponPhaseInterface
21
{
22 1
    #[\Override]
23
    public function fire(
24
        ProjectileAttackerInterface $attacker,
25
        BattlePartyInterface $targetPool,
26
        SpacecraftAttackCauseEnum $attackCause,
27
        MessageCollectionInterface $messages
28
    ): void {
29
30 1
        for ($i = 1; $i <= $attacker->getTorpedoVolleys(); $i++) {
31
            if ($targetPool->isDefeated()) {
32
                break;
33
            }
34
35
            $torpedo = $attacker->getTorpedo();
36
            $targetWrapper = $targetPool->getRandomActiveMember();
37
            $target = $targetWrapper->get();
38
39
            if (
40
                $torpedo === null
41
                || !$attacker->getTorpedoState()
42
                || !$attacker->hasSufficientEnergy($this->getProjectileWeaponEnergyCosts())
43
                || $attacker->getTorpedoCount() === 0
44
            ) {
45
                break;
46
            }
47
48
            if ($attacker->isAvoidingHullHits($target)) {
49
                break;
50
            }
51
52
            $isCritical = $this->isCritical($torpedo, $target->isCloaked());
53
            $netDamage = $attacker->getProjectileWeaponDamage($isCritical);
54
55
            $damage_wrapper = new DamageWrapper($netDamage);
56
57
            $torpedoName =  $torpedo->getName();
58
59
            $attacker->lowerTorpedoCount(1);
60
            $attacker->reduceEps($this->getProjectileWeaponEnergyCosts());
61
62
            $message = $this->messageFactory->createMessage($attacker->getUserId(), $target->getUser()->getId());
63
            $messages->add($message);
64
65
            $message->add("Die " . $attacker->getName() . " feuert einen " . $torpedoName . " auf die " . $target->getName());
66
67
            $hitchance = $this->getHitChance($attacker);
68
            $evadeChance = $this->getEvadeChance($targetWrapper);
69
            if ($hitchance * (100 - $evadeChance) < random_int(1, 10000)) {
70
                $message->add("Die " . $target->getName() . " wurde verfehlt");
71
                continue;
72
            }
73
74
            $damage_wrapper->setCrit($isCritical);
75
            $damage_wrapper->setShieldPenetration($attacker->isShieldPenetration());
76
            $damage_wrapper->setShieldDamageFactor($torpedo->getShieldDamageFactor());
77
            $damage_wrapper->setHullDamageFactor($torpedo->getHullDamageFactor());
78
            $damage_wrapper->setIsTorpedoDamage(true);
79
            $damage_wrapper->setPirateWrath($this->getUser($attacker->getUserId()), $target);
80
            $this->setTorpedoHullModificator($target, $torpedo, $damage_wrapper);
81
82
            $this->applyDamage->damage($damage_wrapper, $targetWrapper, $message);
83
84
            if ($target->getCondition()->isDestroyed()) {
85
                $this->checkForSpacecraftDestruction(
86
                    $attacker,
87
                    $targetWrapper,
88
                    $attackCause->getDestructionCause(),
89
                    $message
90
                );
91
            }
92
        }
93
    }
94
95
    #[\Override]
96
    public function fireAtBuilding(
97
        ProjectileAttackerInterface $attacker,
98
        PlanetField $target,
99
        bool $isOrbitField,
100
        int &$antiParticleCount
101
    ): InformationWrapper {
102
103
        $informations = new InformationWrapper();
104
105
        $host = $target->getHost();
106
        if (!$host instanceof Colony) {
107
            return $informations;
108
        }
109
110
        $building = $target->getBuilding();
111
        if ($building === null) {
112
            return $informations;
113
        }
114
115
        for ($i = 1; $i <= $attacker->getTorpedoVolleys(); $i++) {
116
            $torpedo = $attacker->getTorpedo();
117
118
            if (
119
                $torpedo === null
120
                || !$attacker->getTorpedoState()
121
                || !$attacker->hasSufficientEnergy($this->getProjectileWeaponEnergyCosts())
122
            ) {
123
                break;
124
            }
125
126
            $attacker->lowerTorpedoCount(1);
127
            $attacker->reduceEps($this->getProjectileWeaponEnergyCosts());
128
129
            $informations->addInformation(sprintf(
130
                _("Die %s feuert einen %s auf das Gebäude %s auf Feld %d"),
131
                $attacker->getName(),
132
                $torpedo->getName(),
133
                $building->getName(),
134
                $target->getFieldId()
135
            ));
136
137
            if ($antiParticleCount > 0) {
138
                $antiParticleCount--;
139
                $informations->addInformation("Der Torpedo wurde vom orbitalem Torpedoabwehrsystem abgefangen");
140
                continue;
141
            }
142
            if ($attacker->getHitChance() < random_int(1, 100)) {
143
                $informations->addInformation("Das Gebäude wurde verfehlt");
144
                continue;
145
            }
146
            $isCritical = random_int(1, 100) <= $torpedo->getCriticalChance();
147
            $damage_wrapper = new DamageWrapper(
148
                $attacker->getProjectileWeaponDamage($isCritical)
149
            );
150
            $damage_wrapper->setCrit($isCritical);
151
            $damage_wrapper->setShieldDamageFactor($torpedo->getShieldDamageFactor());
152
            $damage_wrapper->setHullDamageFactor($torpedo->getHullDamageFactor());
153
            $damage_wrapper->setIsTorpedoDamage(true);
154
155
            $informations->addInformationWrapper($this->applyBuildingDamage->damageBuilding($damage_wrapper, $target, $isOrbitField));
156
157
            if ($target->getIntegrity() === 0) {
158
                $this->entryCreator->addEntry(
159
                    sprintf(
160
                        _('Das Gebäude %s auf Kolonie %s wurde von der %s zerstört'),
161
                        $building->getName(),
162
                        $host->getName(),
163
                        $attacker->getName()
164
                    ),
165
                    $attacker->getUserId(),
166
                    $host
167
                );
168
169
                $this->buildingManager->remove($target);
170
                break;
171
            }
172
            //deactivate if high damage
173
            elseif ($target->hasHighDamage()) {
174
                $this->buildingManager->deactivate($target);
175
            }
176
        }
177
178
        return $informations;
179
    }
180
181
    private function getProjectileWeaponEnergyCosts(): int
182
    {
183
        // @todo
184
        return 1;
185
    }
186
187
    private function isCritical(TorpedoType $torpedo, bool $isTargetCloaked): bool
188
    {
189
        $critChance = $isTargetCloaked ? $torpedo->getCriticalChance() * 2 : $torpedo->getCriticalChance();
190
        return random_int(1, 100) <= $critChance;
191
    }
192
193
    private function setTorpedoHullModificator(
194
        Spacecraft $target,
195
        TorpedoType $torpedo,
196
        DamageWrapper $damageWrapper
197
    ): void {
198
199
        $targetHullModule = $this->getModule($target, SpacecraftModuleTypeEnum::HULL);
200
        if ($targetHullModule === null) {
201
            return;
202
        }
203
204
        $torpedoHull = $targetHullModule->getTorpedoHull()->get($torpedo->getId());
205
206
        if ($torpedoHull !== null) {
207
            $damageWrapper->setModificator($torpedoHull->getModificator());
208
        }
209
    }
210
}
211