Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Failed Conditions
Push — master ( 9b048e...fe1ddb )
by Dan
23s queued 16s
created

SmrWeapon::getMaxDamage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
/**
4
 * Defines a concrete realization of a weapon type for ships/planets.
5
 */
6
class SmrWeapon extends AbstractSmrCombatWeapon {
7
	use Traits\RaceID;
8
9
	const BONUS_DAMAGE = 15; // additive bonus
10
	const BONUS_ACCURACY = 4; // additive bonus
11
12
	const HIGHEST_POWER_LEVEL = 5; // must track the highest power level in db
13
14
	protected int $weaponTypeID;
15
	protected SmrWeaponType $weaponType;
16
	protected bool $bonusAccuracy = false; // default
17
	protected bool $bonusDamage = false; // default
18
	protected bool $damageRollover = false; // fixed for all SmrWeapons
19
20
	public static function getWeapon(int $weaponTypeID, Smr\Database $db = null) : SmrWeapon {
21
		return new SmrWeapon($weaponTypeID, $db);
22
	}
23
24
	protected function __construct(int $weaponTypeID, Smr\Database $db = null) {
25
		$this->weaponType = SmrWeaponType::getWeaponType($weaponTypeID, $db);
26
		$this->weaponTypeID = $weaponTypeID;
27
		$this->raceID = $this->weaponType->getRaceID();
28
	}
29
30
	public function hasBonusAccuracy() : bool {
31
		return $this->bonusAccuracy;
32
	}
33
34
	public function setBonusAccuracy(bool $bonusAccuracy) : void {
35
		$this->bonusAccuracy = $bonusAccuracy;
36
	}
37
38
	public function hasBonusDamage() : bool {
39
		return $this->bonusDamage;
40
	}
41
42
	public function setBonusDamage(bool $bonusDamage) : void {
43
		$this->bonusDamage = $bonusDamage;
44
	}
45
46
	private function hasEnhancements() : bool {
47
		return $this->getNumberOfEnhancements() > 0;
48
	}
49
50
	private function getNumberOfEnhancements() : int {
51
		return (int)$this->bonusAccuracy + (int)$this->bonusDamage;
52
	}
53
54
	/**
55
	 * Return weapon name suitable for HTML display.
56
	 * The name is displayed in green with pluses if enhancements are present.
57
	 */
58
	public function getName() : string {
59
		$name = $this->weaponType->getName();
60
		if ($this->hasEnhancements()) {
61
			$name = '<span class="green">' . $name . str_repeat('+', $this->getNumberOfEnhancements()) . '</span>';
62
		}
63
		return $name;
64
	}
65
66
	/**
67
	 * Return the weapon base accuracy.
68
	 */
69
	public function getBaseAccuracy() : int {
70
		$baseAccuracy = $this->weaponType->getAccuracy();
71
		if ($this->bonusAccuracy) {
72
			$baseAccuracy += self::BONUS_ACCURACY;
73
		}
74
		return $baseAccuracy;
75
	}
76
77
	/**
78
	 * Return the weapon shield damage.
79
	 */
80
	public function getShieldDamage() : int {
81
		$shieldDamage = $this->weaponType->getShieldDamage();
82
		if ($this->bonusDamage && $shieldDamage > 0) {
83
			$shieldDamage += self::BONUS_DAMAGE;
84
		}
85
		return $shieldDamage;
86
	}
87
88
	/**
89
	 * Return the weapon armour damage.
90
	 */
91
	public function getArmourDamage() : int {
92
		$armourDamage = $this->weaponType->getArmourDamage();
93
		if ($this->bonusDamage && $armourDamage > 0) {
94
			$armourDamage += self::BONUS_DAMAGE;
95
		}
96
		return $armourDamage;
97
	}
98
99
	public function getBuyHREF(SmrLocation $location) : string {
100
		$container = Page::create('shop_weapon_processing.php');
101
		$container['LocationID'] = $location->getTypeID();
102
		$container['Weapon'] = $this;
103
		return $container->href();
104
	}
105
106
	public function getSellHREF(SmrLocation $location, int $orderID) : string {
107
		$container = Page::create('shop_weapon_processing.php');
108
		$container['LocationID'] = $location->getTypeID();
109
		$container['Weapon'] = $this;
110
		$container['OrderID'] = $orderID;
111
		return $container->href();
112
	}
113
114
	public function getWeaponTypeID() : int {
115
		return $this->weaponTypeID;
116
	}
117
118
	/**
119
	 * Weapon cost is increased by 100% for each enhancement present
120
	 */
121
	public function getCost() : int {
122
		return $this->weaponType->getCost() * (1 + $this->getNumberOfEnhancements());
123
	}
124
125
	public function getPowerLevel() : int {
126
		return $this->weaponType->getPowerLevel();
127
	}
128
129
	public function getBuyerRestriction() : int {
130
		return $this->weaponType->getBuyerRestriction();
131
	}
132
133
	/**
134
	 * Ships are only allowed to equip one of each type of Unique weapon
135
	 */
136
	public function isUniqueType() : bool {
137
		return $this->getPowerLevel() === self::HIGHEST_POWER_LEVEL;
138
	}
139
140
	protected function getWeightedRandomForPlayer(AbstractSmrPlayer $player) : WeightedRandom {
141
		return WeightedRandom::getWeightedRandomForPlayer($player, 'Weapon', $this->getWeaponTypeID());
142
	}
143
144
	/**
145
	 * Given $weaponAccuracy as a percent, decide if the weapon hits.
146
	 */
147
	protected function checkHit(AbstractSmrPlayer $player, float $weaponAccuracy) : bool {
148
		// Skip weighting factor for absolute hits/misses.
149
		if ($weaponAccuracy >= 100) {
150
			return true;
151
		} elseif ($weaponAccuracy <= 0) {
152
			return false;
153
		}
154
		return $this->getWeightedRandomForPlayer($player)->flipWeightedCoin($weaponAccuracy);
155
	}
156
157
	public static function getPlayerLevelAccuracyMod(AbstractSmrPlayer $player) : float {
158
		return ($player->getLevelID() * $player->getLevelID() / 60 + $player->getLevelID() / 2 + 2) / 100;
159
	}
160
161
	public function getModifiedAccuracy(AbstractSmrPlayer $weaponPlayer) : float {
162
		$modifiedAccuracy = $this->getBaseAccuracy();
163
		$modifiedAccuracy += $this->getBaseAccuracy() * self::getPlayerLevelAccuracyMod($weaponPlayer);
164
		return $modifiedAccuracy;
165
	}
166
167
	public function getModifiedAccuracyAgainstForces(AbstractSmrPlayer $weaponPlayer, SmrForce $forces) : float {
0 ignored issues
show
Unused Code introduced by
The parameter $forces is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

167
	public function getModifiedAccuracyAgainstForces(AbstractSmrPlayer $weaponPlayer, /** @scrutinizer ignore-unused */ SmrForce $forces) : float {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
168
		$modifiedAccuracy = $this->getModifiedAccuracy($weaponPlayer);
169
		return $modifiedAccuracy;
170
	}
171
172
	public function getModifiedAccuracyAgainstPort(AbstractSmrPlayer $weaponPlayer, SmrPort $port) : float {
173
		$modifiedAccuracy = $this->getModifiedAccuracy($weaponPlayer);
174
		$modifiedAccuracy -= $this->getBaseAccuracy() * $port->getLevel() / 50;
175
		return $modifiedAccuracy;
176
	}
177
178
	public function getModifiedAccuracyAgainstPlanet(AbstractSmrPlayer $weaponPlayer, SmrPlanet $planet) : float {
179
		$modifiedAccuracy = $this->getModifiedAccuracy($weaponPlayer);
180
		$modifiedAccuracy -= $this->getBaseAccuracy() * $planet->getLevel() / 350;
181
		return $modifiedAccuracy;
182
	}
183
184
	public function getModifiedAccuracyAgainstPlayer(AbstractSmrPlayer $weaponPlayer, AbstractSmrPlayer $targetPlayer) : float {
185
		$modifiedAccuracy = $this->getModifiedAccuracy($weaponPlayer);
186
		$modifiedAccuracy -= $this->getBaseAccuracy() * self::getPlayerLevelAccuracyMod($targetPlayer) / 2;
187
188
		$weaponShip = $weaponPlayer->getShip();
189
		$targetShip = $targetPlayer->getShip();
190
		$mrDiff = $targetShip->getMR() - $weaponShip->getMR();
191
		if ($mrDiff > 0) {
192
			$modifiedAccuracy -= $this->getBaseAccuracy() * ($mrDiff / MR_FACTOR) / 100;
193
		}
194
195
		return $modifiedAccuracy;
196
	}
197
198
	public function getModifiedPortAccuracy(SmrPort $port) : float {
0 ignored issues
show
Unused Code introduced by
The parameter $port is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

198
	public function getModifiedPortAccuracy(/** @scrutinizer ignore-unused */ SmrPort $port) : float {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
199
		$modifiedAccuracy = $this->getBaseAccuracy();
200
		return $modifiedAccuracy;
201
	}
202
203
	public function getModifiedPortAccuracyAgainstPlayer(SmrPort $port, AbstractSmrPlayer $targetPlayer) : float {
204
		$modifiedAccuracy = $this->getModifiedPortAccuracy($port);
205
		$modifiedAccuracy -= $this->getBaseAccuracy() * self::getPlayerLevelAccuracyMod($targetPlayer);
206
		return $modifiedAccuracy;
207
	}
208
209
	public function getModifiedPlanetAccuracy(SmrPlanet $planet) : float {
210
		$modifiedAccuracy = $this->getBaseAccuracy();
211
		if ($this->getWeaponTypeID() == WEAPON_PLANET_TURRET) {
212
			$modifiedAccuracy += $planet->getLevel() / 2;
213
		} else {
214
			$modifiedAccuracy += $planet->getAccuracyBonus();
215
		}
216
		return $modifiedAccuracy;
217
	}
218
219
	public function getModifiedPlanetAccuracyAgainstPlayer(SmrPlanet $planet, AbstractSmrPlayer $targetPlayer) : float {
220
		$modifiedAccuracy = $this->getModifiedPlanetAccuracy($planet);
221
		$modifiedAccuracy -= $this->getBaseAccuracy() * self::getPlayerLevelAccuracyMod($targetPlayer);
222
		return $modifiedAccuracy;
223
	}
224
225
	public function getModifiedDamageAgainstForces(AbstractSmrPlayer $weaponPlayer, SmrForce $forces) : array {
226
		if (!$this->canShootForces()) {
227
			// If we can't shoot forces then just return a damageless array and don't waste resources calculated any damage mods.
228
			return array('MaxDamage' => 0, 'Shield' => 0, 'Armour' => 0, 'Rollover' => $this->isDamageRollover());
229
		}
230
		$damage = $this->getDamage();
231
		return $damage;
232
	}
233
234
	public function getModifiedDamageAgainstPort(AbstractSmrPlayer $weaponPlayer, SmrPort $port) : array {
235
		if (!$this->canShootPorts()) {
236
			// If we can't shoot forces then just return a damageless array and don't waste resources calculated any damage mods.
237
			return array('MaxDamage' => 0, 'Shield' => 0, 'Armour' => 0, 'Rollover' => $this->isDamageRollover());
238
		}
239
		$damage = $this->getDamage();
240
		return $damage;
241
	}
242
243
	public function getModifiedDamageAgainstPlanet(AbstractSmrPlayer $weaponPlayer, SmrPlanet $planet) : array {
244
		if (!$this->canShootPlanets()) {
245
			// If we can't shoot forces then just return a damageless array and don't waste resources calculated any damage mods.
246
			return array('MaxDamage' => 0, 'Shield' => 0, 'Armour' => 0, 'Rollover' => $this->isDamageRollover());
247
		}
248
		$damage = $this->getDamage();
249
250
		$planetMod = self::PLANET_DAMAGE_MOD;
251
		$damage['MaxDamage'] = ICeil($damage['MaxDamage'] * $planetMod);
252
		$damage['Shield'] = ICeil($damage['Shield'] * $planetMod);
253
		$damage['Armour'] = ICeil($damage['Armour'] * $planetMod);
254
255
		return $damage;
256
	}
257
258
	public function getModifiedForceDamageAgainstPlayer(SmrForce $forces, AbstractSmrPlayer $targetPlayer) : array {
259
		$return = array('MaxDamage' => 0, 'Shield' => 0, 'Armour' => 0, 'Rollover' => $this->isDamageRollover());
260
		return $return;
261
	}
262
263
	public function getModifiedDamageAgainstPlayer(AbstractSmrPlayer $weaponPlayer, AbstractSmrPlayer $targetPlayer) : array {
264
		if (!$this->canShootTraders()) { // If we can't shoot traders then just return a damageless array and don't waste resources calculating any damage mods.
265
			$return = array('MaxDamage' => 0, 'Shield' => 0, 'Armour' => 0, 'Rollover' => $this->isDamageRollover());
266
			return $return;
267
		}
268
		$damage = $this->getDamage();
269
		return $damage;
270
	}
271
272
	public function getModifiedPortDamageAgainstPlayer(SmrPort $port, AbstractSmrPlayer $targetPlayer) : array {
273
		if (!$this->canShootTraders()) { // If we can't shoot traders then just return a damageless array and don't waste resources calculating any damage mods.
274
			$return = array('MaxDamage' => 0, 'Shield' => 0, 'Armour' => 0, 'Rollover' => $this->isDamageRollover());
275
			return $return;
276
		}
277
		$damage = $this->getDamage();
278
		return $damage;
279
	}
280
281
	public function getModifiedPlanetDamageAgainstPlayer(SmrPlanet $planet, AbstractSmrPlayer $targetPlayer) : array {
282
		if (!$this->canShootTraders()) { // If we can't shoot traders then just return a damageless array and don't waste resources calculating any damage mods.
283
			$return = array('MaxDamage' => 0, 'Shield' => 0, 'Armour' => 0, 'Rollover' => $this->isDamageRollover());
284
			return $return;
285
		}
286
		$damage = $this->getDamage();
287
		return $damage;
288
	}
289
290
	public function shootForces(AbstractSmrPlayer $weaponPlayer, SmrForce $forces) : array {
291
		$return = array('Weapon' => $this, 'TargetForces' => $forces, 'Hit' => false);
292
		$modifiedAccuracy = $this->getModifiedAccuracyAgainstForces($weaponPlayer, $forces);
293
		if ($this->checkHit($weaponPlayer, $modifiedAccuracy)) {
294
			$return['Hit'] = true;
295
			return $this->doPlayerDamageToForce($return, $weaponPlayer, $forces);
296
		}
297
		return $return;
298
	}
299
300
	public function shootPort(AbstractSmrPlayer $weaponPlayer, SmrPort $port) : array {
301
		$return = array('Weapon' => $this, 'TargetPort' => $port, 'Hit' => false);
302
		$modifiedAccuracy = $this->getModifiedAccuracyAgainstPort($weaponPlayer, $port);
303
		if ($this->checkHit($weaponPlayer, $modifiedAccuracy)) {
304
			$return['Hit'] = true;
305
			return $this->doPlayerDamageToPort($return, $weaponPlayer, $port);
306
		}
307
		return $return;
308
	}
309
310
	public function shootPlanet(AbstractSmrPlayer $weaponPlayer, SmrPlanet $planet, bool $delayed) : array {
311
		$return = array('Weapon' => $this, 'TargetPlanet' => $planet, 'Hit' => false);
312
		$modifiedAccuracy = $this->getModifiedAccuracyAgainstPlanet($weaponPlayer, $planet);
313
		if ($this->checkHit($weaponPlayer, $modifiedAccuracy)) {
314
			$return['Hit'] = true;
315
			return $this->doPlayerDamageToPlanet($return, $weaponPlayer, $planet, $delayed);
316
		}
317
		return $return;
318
	}
319
320
	public function shootPlayer(AbstractSmrPlayer $weaponPlayer, AbstractSmrPlayer $targetPlayer) : array {
321
		$return = array('Weapon' => $this, 'TargetPlayer' => $targetPlayer, 'Hit' => false);
322
		$modifiedAccuracy = $this->getModifiedAccuracyAgainstPlayer($weaponPlayer, $targetPlayer);
323
		if ($this->checkHit($weaponPlayer, $modifiedAccuracy)) {
324
			$return['Hit'] = true;
325
			return $this->doPlayerDamageToPlayer($return, $weaponPlayer, $targetPlayer);
326
		}
327
		return $return;
328
	}
329
330
	public function shootPlayerAsForce(SmrForce $forces, AbstractSmrPlayer $targetPlayer) : array {
331
		$return = array('Weapon' => $this, 'TargetPlayer' => $targetPlayer, 'Hit' => false);
332
		return $return;
333
	}
334
335
	public function shootPlayerAsPort(SmrPort $port, AbstractSmrPlayer $targetPlayer) : array {
336
		$return = array('Weapon' => $this, 'TargetPlayer' => $targetPlayer, 'Hit' => false);
337
		$modifiedAccuracy = $this->getModifiedPortAccuracyAgainstPlayer($port, $targetPlayer);
338
		if ($this->checkHit($targetPlayer, $modifiedAccuracy)) {
339
			$return['Hit'] = true;
340
			return $this->doPortDamageToPlayer($return, $port, $targetPlayer);
341
		}
342
		return $return;
343
	}
344
345
	public function shootPlayerAsPlanet(SmrPlanet $planet, AbstractSmrPlayer $targetPlayer) : array {
346
		$return = array('Weapon' => $this, 'TargetPlayer' => $targetPlayer, 'Hit' => false);
347
		$modifiedAccuracy = $this->getModifiedPlanetAccuracyAgainstPlayer($planet, $targetPlayer);
348
		if ($this->checkHit($targetPlayer, $modifiedAccuracy)) {
349
			$return['Hit'] = true;
350
			return $this->doPlanetDamageToPlayer($return, $planet, $targetPlayer);
351
		}
352
		return $return;
353
	}
354
355
}
356