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

Passed
Pull Request — master (#1005)
by Dan
04:25
created

SmrForce::shootPlayer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php declare(strict_types=1);
2
3
class SmrForce {
4
	protected static $CACHE_FORCES = array();
5
	protected static $CACHE_SECTOR_FORCES = array();
6
	protected static $TIDIED_UP = array();
7
8
	const LOWEST_MAX_EXPIRE_SCOUTS_ONLY = 432000; // 5 days
9
	const TIME_PER_SCOUT_ONLY = 86400; // 1 = 1 day
10
	const TIME_PERCENT_PER_SCOUT = 0.02; // 1/50th
11
	const TIME_PERCENT_PER_COMBAT = 0.02; // 1/50th
12
	const TIME_PERCENT_PER_MINE = 0.02; // 1/50th
13
	const REFRESH_ALL_TIME_PER_STACK = 1; // 1 second
14
15
	protected static $refreshAllHREF;
16
17
	protected $db;
18
	protected $SQL;
19
20
	protected $ownerID;
21
	protected $sectorID;
22
	protected $gameID;
23
	protected $combatDrones = 0;
24
	protected $scoutDrones = 0;
25
	protected $mines = 0;
26
	protected $expire = 0;
27
28
	protected $isNew;
29
	protected $hasChanged = false;
30
31
	public static function refreshCache() {
32
		foreach (self::$CACHE_FORCES as $gameID => &$gameForces) {
33
			foreach ($gameForces as $sectorID => &$gameSectorForces) {
34
				foreach ($gameSectorForces as $ownerID => &$forces) {
35
					$forces = self::getForce($gameID, $sectorID, $ownerID, true);
36
				}
37
			}
38
		}
39
	}
40
41
	public static function clearCache() {
42
		self::$CACHE_FORCES = array();
43
		self::$CACHE_SECTOR_FORCES = array();
44
	}
45
46
	public static function saveForces() {
47
		foreach (self::$CACHE_FORCES as $gameForces) {
48
			foreach ($gameForces as $gameSectorForces) {
49
				foreach ($gameSectorForces as $forces) {
50
					$forces->update();
51
				}
52
			}
53
		}
54
	}
55
56
	public static function getGalaxyForces($gameID, $galaxyID, $forceUpdate = false) {
57
		$db = MySqlDatabase::getInstance();
58
		$db->query('SELECT sector_has_forces.*, sector_id FROM sector LEFT JOIN sector_has_forces USING(game_id, sector_id) WHERE game_id = ' . $db->escapeNumber($gameID) . ' AND galaxy_id = ' . $db->escapeNumber($galaxyID));
59
		$galaxyForces = [];
60
		while ($db->nextRecord()) {
61
			$sectorID = $db->getInt('sector_id');
62
			if (!$db->hasField('owner_id')) {
63
				self::$CACHE_SECTOR_FORCES[$gameID][$sectorID] = [];
64
			} else {
65
				$ownerID = $db->getInt('owner_id');
66
				$force = self::getForce($gameID, $sectorID, $ownerID, $forceUpdate, $db);
67
				self::$CACHE_SECTOR_FORCES[$gameID][$sectorID][$ownerID] = $force;
68
				$galaxyForces[$sectorID][$ownerID] = $force;
69
			}
70
		}
71
		return $galaxyForces;
72
	}
73
74
	public static function getSectorForces($gameID, $sectorID, $forceUpdate = false) {
75
		if ($forceUpdate || !isset(self::$CACHE_SECTOR_FORCES[$gameID][$sectorID])) {
76
			self::tidyUpForces(SmrGalaxy::getGalaxyContaining($gameID, $sectorID));
77
			$db = MySqlDatabase::getInstance();
78
			$db->query('SELECT * FROM sector_has_forces WHERE sector_id = ' . $db->escapeNumber($sectorID) . ' AND game_id=' . $db->escapeNumber($gameID) . ' ORDER BY expire_time ASC');
79
			$forces = array();
80
			while ($db->nextRecord()) {
81
				$ownerID = $db->getInt('owner_id');
82
				$forces[$ownerID] = self::getForce($gameID, $sectorID, $ownerID, $forceUpdate, $db);
83
			}
84
			self::$CACHE_SECTOR_FORCES[$gameID][$sectorID] = $forces;
85
		}
86
		return self::$CACHE_SECTOR_FORCES[$gameID][$sectorID];
87
	}
88
89
	public static function getForce($gameID, $sectorID, $ownerID, $forceUpdate = false, $db = null) {
90
		if ($forceUpdate || !isset(self::$CACHE_FORCES[$gameID][$sectorID][$ownerID])) {
91
			self::tidyUpForces(SmrGalaxy::getGalaxyContaining($gameID, $sectorID));
92
			$p = new SmrForce($gameID, $sectorID, $ownerID, $db);
93
			self::$CACHE_FORCES[$gameID][$sectorID][$ownerID] = $p;
94
		}
95
		return self::$CACHE_FORCES[$gameID][$sectorID][$ownerID];
96
	}
97
98
	public static function tidyUpForces(SmrGalaxy $galaxyToTidy) {
99
		if (!isset(self::$TIDIED_UP[$galaxyToTidy->getGameID()][$galaxyToTidy->getGalaxyID()])) {
100
			self::$TIDIED_UP[$galaxyToTidy->getGameID()][$galaxyToTidy->getGalaxyID()] = true;
101
			$db = MySqlDatabase::getInstance();
102
			$db->query('UPDATE sector_has_forces
103
						SET refresher=0,
104
							expire_time = (refresh_at + if(combat_drones+mines=0,
105
															LEAST('.$db->escapeNumber(self::LOWEST_MAX_EXPIRE_SCOUTS_ONLY) . ', scout_drones*' . $db->escapeNumber(self::TIME_PER_SCOUT_ONLY) . '),
106
															LEAST('.$db->escapeNumber($galaxyToTidy->getMaxForceTime()) . ', (combat_drones*' . $db->escapeNumber(self::TIME_PERCENT_PER_COMBAT) . '+scout_drones*' . $db->escapeNumber(self::TIME_PERCENT_PER_SCOUT) . '+mines*' . $db->escapeNumber(self::TIME_PERCENT_PER_MINE) . ')*' . $db->escapeNumber($galaxyToTidy->getMaxForceTime()) . ')
107
														))
108
						WHERE game_id = '.$db->escapeNumber($galaxyToTidy->getGameID()) . ' AND sector_id >= ' . $db->escapeNumber($galaxyToTidy->getStartSector()) . ' AND sector_id <= ' . $db->escapeNumber($galaxyToTidy->getEndSector()) . ' AND refresher != 0 AND refresh_at <= ' . $db->escapeNumber(SmrSession::getTime()));
109
			$db->query('DELETE FROM sector_has_forces WHERE expire_time < ' . $db->escapeNumber(SmrSession::getTime()));
110
		}
111
	}
112
113
	protected function __construct($gameID, $sectorID, $ownerID, $db = null) {
114
		$this->db = MySqlDatabase::getInstance();
115
		$this->SQL = 'game_id = ' . $this->db->escapeNumber($gameID) . '
116
		              AND sector_id = '.$this->db->escapeNumber($sectorID) . '
117
		              AND owner_id = '.$this->db->escapeNumber($ownerID);
118
119
		if (isset($db)) {
120
			$this->isNew = false;
121
		} else {
122
			$db = $this->db;
123
			$this->db->query('SELECT * FROM sector_has_forces WHERE ' . $this->SQL);
124
			$this->isNew = !$db->nextRecord();
125
		}
126
127
		$this->gameID = $gameID;
128
		$this->ownerID = $ownerID;
129
		$this->sectorID = $sectorID;
130
		if (!$this->isNew) {
131
			$this->combatDrones = $db->getInt('combat_drones');
132
			$this->scoutDrones = $db->getInt('scout_drones');
133
			$this->mines = $db->getInt('mines');
134
			$this->expire = $db->getInt('expire_time');
135
		}
136
	}
137
138
	public function exists() {
139
		return ($this->hasCDs() || $this->hasSDs() || $this->hasMines()) && !$this->hasExpired();
140
	}
141
142
	public function canAcceptCDs() {
143
		return $this->getCDs() < 50;
144
	}
145
146
	public function canAcceptSDs() {
147
		return $this->getSDs() < 5;
148
	}
149
150
	public function canAcceptMines() {
151
		return $this->getMines() < 50;
152
	}
153
154
	public function hasCDs() {
155
		return $this->getCDs() > 0;
156
	}
157
158
	public function hasSDs() {
159
		return $this->getSDs() > 0;
160
	}
161
162
	public function hasMines() {
163
		return $this->getMines() > 0;
164
	}
165
166
	public function getCDs() {
167
		return $this->combatDrones;
168
	}
169
170
	public function getSDs() {
171
		return $this->scoutDrones;
172
	}
173
174
	public function getMines() {
175
		return $this->mines;
176
	}
177
178
	public function addMines($amount) {
179
		if ($amount < 0) {
180
			throw new Exception('Cannot add negative mines.');
181
		}
182
		$this->setMines($this->getMines() + $amount);
183
	}
184
185
	public function addCDs($amount) {
186
		if ($amount < 0) {
187
			throw new Exception('Cannot add negative CDs.');
188
		}
189
		$this->setCDs($this->getCDs() + $amount);
190
	}
191
192
	public function addSDs($amount) {
193
		if ($amount < 0) {
194
			throw new Exception('Cannot add negative SDs.');
195
		}
196
		$this->setSDs($this->getSDs() + $amount);
197
	}
198
199
	public function takeMines($amount) {
200
		if ($amount < 0) {
201
			throw new Exception('Cannot take negative mines.');
202
		}
203
		$this->setMines($this->getMines() - $amount);
204
	}
205
206
	public function takeCDs($amount) {
207
		if ($amount < 0) {
208
			throw new Exception('Cannot take negative CDs.');
209
		}
210
		$this->setCDs($this->getCDs() - $amount);
211
	}
212
213
	public function takeSDs($amount) {
214
		if ($amount < 0) {
215
			throw new Exception('Cannot take negative SDs.');
216
		}
217
		$this->setSDs($this->getSDs() - $amount);
218
	}
219
220
	public function setMines($amount) {
221
		if ($amount < 0) {
222
			throw new Exception('Cannot set negative mines.');
223
		}
224
		if ($amount == $this->getMines()) {
225
			return;
226
		}
227
		$this->hasChanged = true;
228
		$this->mines = $amount;
229
	}
230
231
	public function setCDs($amount) {
232
		if ($amount < 0) {
233
			throw new Exception('Cannot set negative CDs.');
234
		}
235
		if ($amount == $this->getCDs()) {
236
			return;
237
		}
238
		$this->hasChanged = true;
239
		$this->combatDrones = $amount;
240
	}
241
242
	public function setSDs($amount) {
243
		if ($amount < 0) {
244
			throw new Exception('Cannot set negative SDs.');
245
		}
246
		if ($amount == $this->getSDs()) {
247
			return;
248
		}
249
		$this->hasChanged = true;
250
		$this->scoutDrones = $amount;
251
	}
252
253
	public function hasExpired() {
254
		return $this->expire < SmrSession::getTime();
255
	}
256
257
	public function getExpire() {
258
		return $this->expire;
259
	}
260
261
	public function setExpire($time) {
262
		if ($time < 0) {
263
			throw new Exception('Cannot set negative expiry.');
264
		}
265
		if ($time == $this->getExpire()) {
266
			return;
267
		}
268
		if ($time > SmrSession::getTime() + $this->getMaxExpireTime()) {
269
			$time = SmrSession::getTime() + $this->getMaxExpireTime();
270
		}
271
		$this->hasChanged = true;
272
		$this->expire = $time;
273
		if (!$this->isNew) {
274
			$this->update();
275
		}
276
	}
277
278
	public function updateExpire() {
279
		// Changed (26/10/05) - scout drones count * 2
280
		if ($this->getCDs() == 0 && $this->getMines() == 0 && $this->getSDs() > 0) {
281
			$time = self::TIME_PER_SCOUT_ONLY * $this->getSDs();
282
		} else {
283
			$time = ($this->getCDs() * self::TIME_PERCENT_PER_COMBAT + $this->getSDs() * self::TIME_PERCENT_PER_SCOUT + $this->getMines() * self::TIME_PERCENT_PER_MINE) * $this->getMaxGalaxyExpireTime();
284
		}
285
		$this->setExpire(SmrSession::getTime() + $time);
286
	}
287
288
	public function getMaxExpireTime() {
289
		if ($this->hasCDs() || $this->hasMines()) {
290
			return $this->getMaxGalaxyExpireTime();
291
		}
292
		if (!$this->hasCDs() && !$this->hasMines() && $this->hasSDs()) {
293
			return max(self::LOWEST_MAX_EXPIRE_SCOUTS_ONLY, $this->getMaxGalaxyExpireTime());
294
		}
295
		return 0;
296
	}
297
298
	public function getMaxGalaxyExpireTime() {
299
		return $this->getGalaxy()->getMaxForceTime();
300
	}
301
302
	public function getBumpTurnCost(AbstractSmrShip $ship) {
303
		$mines = $this->getMines();
304
		if ($mines <= 1) {
305
			return 0;
306
		}
307
		if ($mines < 10) {
308
			$turns = 1;
309
		} elseif ($mines < 25) {
310
			$turns = 2;
311
		} else {
312
			$turns = 3;
313
		}
314
		if ($ship->isFederal() || $ship->hasDCS()) {
315
			$turns -= 1;
316
		}
317
		return $turns;
318
	}
319
320
	public function getAttackTurnCost(AbstractSmrShip $ship) {
321
		if ($ship->isFederal() || $ship->hasDCS()) {
322
			return 2;
323
		}
324
		return 3;
325
	}
326
327
	public function getOwnerID() {
328
		return $this->ownerID;
329
	}
330
331
	public function getGameID() {
332
		return $this->gameID;
333
	}
334
335
	public function getSector() {
336
		return SmrSector::getSector($this->getGameID(), $this->getSectorID());
337
	}
338
339
	public function getSectorID() {
340
		return $this->sectorID;
341
	}
342
343
	public function ping($pingMessage, AbstractSmrPlayer $playerPinging, $skipCheck = false) {
344
		if (!$this->hasSDs() && !$skipCheck) {
345
			return;
346
		}
347
		$owner = $this->getOwner();
348
		if (!$playerPinging->sameAlliance($owner)) {
349
			$playerPinging->sendMessage($owner->getAccountID(), MSG_SCOUT, $pingMessage, false);
350
		}
351
	}
352
353
	public function getGalaxy() {
354
		return SmrGalaxy::getGalaxyContaining($this->getGameID(), $this->getSectorID());
355
	}
356
357
	public function getOwner() {
358
		return SmrPlayer::getPlayer($this->getOwnerID(), $this->getGameID());
359
	}
360
361
	public function update() {
362
		if (!$this->isNew) {
363
			if (!$this->exists()) {
364
				$this->db->query('DELETE FROM sector_has_forces WHERE ' . $this->SQL);
365
				$this->isNew = true;
366
			} elseif ($this->hasChanged) {
367
				$this->db->query('UPDATE sector_has_forces SET combat_drones = ' . $this->db->escapeNumber($this->combatDrones) . ', scout_drones = ' . $this->db->escapeNumber($this->scoutDrones) . ', mines = ' . $this->db->escapeNumber($this->mines) . ', expire_time = ' . $this->db->escapeNumber($this->expire) . ' WHERE ' . $this->SQL);
368
			}
369
		} elseif ($this->exists()) {
370
			$this->db->query('INSERT INTO sector_has_forces (game_id, sector_id, owner_id, combat_drones, scout_drones, mines, expire_time)
371
								VALUES('.$this->db->escapeNumber($this->gameID) . ', ' . $this->db->escapeNumber($this->sectorID) . ', ' . $this->db->escapeNumber($this->ownerID) . ', ' . $this->db->escapeNumber($this->combatDrones) . ', ' . $this->db->escapeNumber($this->scoutDrones) . ', ' . $this->db->escapeNumber($this->mines) . ', ' . $this->db->escapeNumber($this->expire) . ')');
372
			$this->isNew = false;
373
		}
374
		// This instance is now in sync with the database
375
		$this->hasChanged = false;
376
	}
377
378
	/**
379
	 * Update the table fields associated with using Refresh All
380
	 */
381
	public function updateRefreshAll(SmrPlayer $player, $refreshTime) {
382
		$this->db->query('UPDATE sector_has_forces SET refresh_at=' . $this->db->escapeNumber($refreshTime) . ', refresher=' . $this->db->escapeNumber($player->getAccountID()) . ' WHERE ' . $this->SQL);
383
	}
384
385
	public function getExamineDropForcesHREF() {
386
		$container = create_container('skeleton.php', 'forces_drop.php');
387
		$container['owner_id'] = $this->getOwnerID();
388
		return SmrSession::getNewHREF($container);
389
	}
390
391
	public function getAttackForcesHREF() {
392
		$container = create_container('forces_attack_processing.php');
393
		$container['action'] = 'attack';
394
		$container['owner_id'] = $this->getOwnerID();
395
		return SmrSession::getNewHREF($container);
396
	}
397
398
	public function getRefreshHREF() {
399
		$container = create_container('forces_refresh_processing.php');
400
		$container['owner_id'] = $this->getOwnerID();
401
		return SmrSession::getNewHREF($container);
402
	}
403
404
	protected function getDropContainer() {
405
		return array('url' => 'forces_drop_processing.php', 'owner_id' => $this->getOwnerID());
406
	}
407
408
	public function getDropSDHREF() {
409
		$container = $this->getDropContainer();
410
		$container['drop_scout_drones'] = 1;
411
		return SmrSession::getNewHREF($container);
412
	}
413
414
	public function getTakeSDHREF() {
415
		$container = $this->getDropContainer();
416
		$container['take_scout_drones'] = 1;
417
		return SmrSession::getNewHREF($container);
418
	}
419
420
	public function getDropCDHREF() {
421
		$container = $this->getDropContainer();
422
		$container['drop_combat_drones'] = 1;
423
		return SmrSession::getNewHREF($container);
424
	}
425
426
	public function getTakeCDHREF() {
427
		$container = $this->getDropContainer();
428
		$container['take_combat_drones'] = 1;
429
		return SmrSession::getNewHREF($container);
430
	}
431
432
	public function getDropMineHREF() {
433
		$container = $this->getDropContainer();
434
		$container['drop_mines'] = 1;
435
		return SmrSession::getNewHREF($container);
436
	}
437
438
	public function getTakeMineHREF() {
439
		$container = $this->getDropContainer();
440
		$container['take_mines'] = 1;
441
		return SmrSession::getNewHREF($container);
442
	}
443
444
	public static function getRefreshAllHREF() {
445
		$container = create_container('forces_mass_refresh.php');
446
		return SmrSession::getNewHREF($container);
447
	}
448
449
	public function &shootPlayers(array $targetPlayers, $minesAreAttacker) {
450
		$results = array('TotalDamage' => 0);
451
		if (!$this->exists()) {
452
			$results['DeadBeforeShot'] = true;
453
			return $results;
454
		}
455
		$results['DeadBeforeShot'] = false;
456
457
		if ($this->hasMines()) {
458
			$thisMines = new SmrMines($this->getGameID(), $this->getMines());
459
			$results['Results']['Mines'] =& $thisMines->shootPlayerAsForce($this, array_rand_value($targetPlayers), $minesAreAttacker);
460
			$results['TotalDamage'] += $results['Results']['Mines']['ActualDamage']['TotalDamage'];
461
		}
462
463
		if ($this->hasCDs()) {
464
			$thisCDs = new SmrCombatDrones($this->getGameID(), $this->getCDs());
465
			$results['Results']['Drones'] =& $thisCDs->shootPlayerAsForce($this, array_rand_value($targetPlayers));
466
			$results['TotalDamage'] += $results['Results']['Drones']['ActualDamage']['TotalDamage'];
467
		}
468
469
		if (!$minesAreAttacker) {
470
			if ($this->hasSDs()) {
471
				$thisSDs = new SmrScoutDrones($this->getGameID(), $this->getSDs());
472
				$results['Results']['Scouts'] =& $thisSDs->shootPlayerAsForce($this, array_rand_value($targetPlayers));
473
				$results['TotalDamage'] += $results['Results']['Scouts']['ActualDamage']['TotalDamage'];
474
			}
475
		}
476
477
		$results['ForcesDestroyed'] = !$this->exists();
478
		return $results;
479
	}
480
481
	public function &doWeaponDamage(array $damage) {
482
		$alreadyDead = !$this->exists();
483
		$minesDamage = 0;
484
		$cdDamage = 0;
485
		$sdDamage = 0;
486
		if (!$alreadyDead) {
487
			$minesDamage = $this->doMinesDamage(min($damage['MaxDamage'], $damage['Armour']));
488
			$damage['Armour'] -= $minesDamage;
489
			$damage['MaxDamage'] -= $minesDamage;
490
			if (!$this->hasMines() && ($minesDamage == 0 || $damage['Rollover'])) {
491
				$cdDamage = $this->doCDDamage(min($damage['MaxDamage'], $damage['Armour']));
492
				$damage['Armour'] -= $cdDamage;
493
				$damage['MaxDamage'] -= $cdDamage;
494
				if (!$this->hasCDs() && ($cdDamage == 0 || $damage['Rollover'])) {
495
					$sdDamage = $this->doSDDamage(min($damage['MaxDamage'], $damage['Armour']));
496
				}
497
			}
498
		}
499
		$return = array(
500
						'KillingShot' => !$alreadyDead && !$this->exists(),
501
						'TargetAlreadyDead' => $alreadyDead,
502
						'Mines' => $minesDamage,
503
						'NumMines' => $minesDamage / MINE_ARMOUR,
504
						'HasMines' => $this->hasMines(),
505
						'CDs' => $cdDamage,
506
						'NumCDs' => $cdDamage / CD_ARMOUR,
507
						'HasCDs' => $this->hasCDs(),
508
						'SDs' => $sdDamage,
509
						'NumSDs' => $sdDamage / SD_ARMOUR,
510
						'HasSDs' => $this->hasSDs(),
511
						'TotalDamage' => $minesDamage + $cdDamage + $sdDamage
512
		);
513
		return $return;
514
	}
515
516
	protected function doMinesDamage($damage) {
517
		$actualDamage = min($this->getMines(), IFloor($damage / MINE_ARMOUR));
518
		$this->takeMines($actualDamage);
519
		return $actualDamage * MINE_ARMOUR;
520
	}
521
522
	protected function doCDDamage($damage) {
523
		$actualDamage = min($this->getCDs(), IFloor($damage / CD_ARMOUR));
524
		$this->takeCDs($actualDamage);
525
		return $actualDamage * CD_ARMOUR;
526
	}
527
528
	protected function doSDDamage($damage) {
529
		$actualDamage = min($this->getSDs(), IFloor($damage / SD_ARMOUR));
530
		$this->takeSDs($actualDamage);
531
		return $actualDamage * SD_ARMOUR;
532
	}
533
534
	public function &killForcesByPlayer(AbstractSmrPlayer $killer) {
0 ignored issues
show
Unused Code introduced by
The parameter $killer 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

534
	public function &killForcesByPlayer(/** @scrutinizer ignore-unused */ AbstractSmrPlayer $killer) {

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...
535
		$return = array();
536
		return $return;
537
	}
538
}
539