Passed
Push — master ( dc0b89...206b37 )
by Nico
12:39
created

getProjectileWeaponEnergyCosts()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
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\ColonyInterface;
16
use Stu\Orm\Entity\PlanetFieldInterface;
17
use Stu\Orm\Entity\SpacecraftInterface;
18
use Stu\Orm\Entity\TorpedoTypeInterface;
19
20
//TODO unit tests
21
final class ProjectileWeaponPhase extends AbstractWeaponPhase implements ProjectileWeaponPhaseInterface
22
{
23
    #[Override]
24
    public function fire(
25
        ProjectileAttackerInterface $attacker,
26
        BattlePartyInterface $targetPool,
27
        SpacecraftAttackCauseEnum $attackCause,
28
        MessageCollectionInterface $messages
29
    ): void {
30
31
        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 = $attacker->getHitChance();
69
            if ($hitchance * (100 - $target->getEvadeChance()) < 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->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
        PlanetFieldInterface $target,
99
        bool $isOrbitField,
100
        int &$antiParticleCount
101
    ): InformationWrapper {
102
103
        $informations = new InformationWrapper();
104
105
        $host = $target->getHost();
106
        if (!$host instanceof ColonyInterface) {
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(TorpedoTypeInterface $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
        SpacecraftInterface $target,
195
        TorpedoTypeInterface $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