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
Pull Request — master (#1078)
by Dan
05:25
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