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