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

Completed
Push — master ( 42cc88...1adc02 )
by Dan
19s queued 16s
created

SmrPlanet::getCombatName()   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
// This file defines more than just one class, which is not handled by
4
// the autoloader. So we must include it explicitly.
5
require_once('SmrPlanetType.class.php');
6
7
class SmrPlanet {
8
	protected static $CACHE_PLANETS = array();
9
10
	const DAMAGE_NEEDED_FOR_DOWNGRADE_CHANCE = 100;
11
	const CHANCE_TO_DOWNGRADE = 15; // percent
12
	const TIME_TO_CREDIT_BUST = 10800; // 3 hours
13
	const TIME_ATTACK_NEWS_COOLDOWN = 3600; // 1 hour
14
	const MAX_STOCKPILE = 600;
15
16
	protected $db;
17
	protected $SQL;
18
19
	protected $sectorID;
20
	protected $gameID;
21
	protected $planetName;
22
	protected $ownerID;
23
	protected $password;
24
	protected $shields;
25
	protected $armour;
26
	protected $drones;
27
	protected $credits;
28
	protected $bonds;
29
	protected $maturity;
30
	protected $stockpile;
31
	protected $buildings;
32
	protected $inhabitableTime;
33
	protected $currentlyBuilding;
34
	protected $mountedWeapons;
35
	protected $typeID;
36
	protected $typeInfo;
37
	
38
	protected $hasChanged = false;
39
	protected $hasChangedFinancial = false; // for credits, bond, maturity
40
	protected $hasChangedStockpile = false;
41
	protected $hasChangedWeapons = array();
42
	protected $hasChangedBuildings = array();
43
	protected $hasStoppedBuilding = array();
44
	protected $isNew = false;
45
46
	protected $delayedShieldsDelta = 0;
47
	protected $delayedCDsDelta = 0;
48
	protected $delayedArmourDelta = 0;
49
50
	public static function refreshCache() {
51
		foreach (self::$CACHE_PLANETS as $gameID => &$gamePlanets) {
52
			foreach ($gamePlanets as $sectorID => &$planet) {
53
				$planet = self::getPlanet($gameID, $sectorID, true);
54
			}
55
		}
56
	}
57
58
	public static function clearCache() {
59
		self::$CACHE_PLANETS = array();
60
	}
61
62
	public static function savePlanets() {
63
		foreach (self::$CACHE_PLANETS as $gamePlanets) {
64
			foreach ($gamePlanets as $planet) {
65
				$planet->update();
66
			}
67
		}
68
	}
69
70
	public static function getGalaxyPlanets($gameID, $galaxyID, $forceUpdate = false) {
71
		$db = new SmrMySqlDatabase();
72
		$db->query('SELECT planet.*, sector_id FROM sector LEFT JOIN planet USING (game_id, sector_id) WHERE game_id = ' . $db->escapeNumber($gameID) . ' AND galaxy_id = ' . $db->escapeNumber($galaxyID));
73
		$galaxyPlanets = [];
74
		while ($db->nextRecord()) {
75
			$sectorID = $db->getInt('sector_id');
76
			$planet = self::getPlanet($gameID, $sectorID, $forceUpdate, $db);
77
			if ($planet->exists()) {
78
				$galaxyPlanets[$sectorID] = $planet;
79
			}
80
		}
81
		return $galaxyPlanets;
82
	}
83
84
	public static function getPlanet($gameID, $sectorID, $forceUpdate = false, $db = null) {
85
		if ($forceUpdate || !isset(self::$CACHE_PLANETS[$gameID][$sectorID])) {
86
			self::$CACHE_PLANETS[$gameID][$sectorID] = new SmrPlanet($gameID, $sectorID, $db);
87
		}
88
		return self::$CACHE_PLANETS[$gameID][$sectorID];
89
	}
90
91
	public static function createPlanet($gameID, $sectorID, $type = 1) {
92
		if (!self::getPlanet($gameID, $sectorID)->exists()) {
93
			$minTime = SmrGame::getGame($gameID)->getStartTime();
94
			$inhabitableTime = $minTime + pow(mt_rand(45, 85), 3);
95
96
			// insert planet into db
97
			$db = new SmrMySqlDatabase();
98
			$db->query('INSERT INTO planet (game_id, sector_id, inhabitable_time, planet_type_id)
99
				VALUES (' . $db->escapeNumber($gameID) . ', ' . $db->escapeNumber($sectorID) . ', ' . $db->escapeNumber($inhabitableTime) . ', ' . $db->escapeNumber($type) . ')');
100
		}
101
		return self::getPlanet($gameID, $sectorID, true);
102
	}
103
104
	public static function removePlanet($gameID, $sectorID) {
105
		$db = new SmrMySqlDatabase();
106
		$SQL = 'game_id = ' . $db->escapeNumber($gameID) . ' AND sector_id = ' . $db->escapeNumber($sectorID);
107
		$db->query('DELETE FROM planet WHERE ' . $SQL);
108
		$db->query('DELETE FROM planet_has_cargo WHERE ' . $SQL);
109
		$db->query('DELETE FROM planet_has_building WHERE ' . $SQL);
110
		$db->query('DELETE FROM planet_is_building WHERE ' . $SQL);
111
		//kick everyone from planet
112
		$db->query('UPDATE player SET land_on_planet = \'FALSE\' WHERE ' . $SQL);
113
114
		self::$CACHE_PLANETS[$gameID][$sectorID] = null;
115
		unset(self::$CACHE_PLANETS[$gameID][$sectorID]);
116
	}
117
118
	protected function __construct($gameID, $sectorID, $db = null) {
119
		$this->db = new SmrMySqlDatabase();
120
		$this->SQL = 'game_id = ' . $this->db->escapeNumber($gameID) . ' AND sector_id = ' . $this->db->escapeNumber($sectorID);
121
122
		if (isset($db)) {
123
			$planetExists = $db->hasField('planet_type_id');
124
		} else {
125
			$db = $this->db;
126
			$db->query('SELECT * FROM planet WHERE ' . $this->SQL);
127
			$planetExists = $db->nextRecord();
128
		}
129
130
		if ($planetExists) {
131
			$this->gameID = (int)$gameID;
132
			$this->sectorID = (int)$sectorID;
133
			$this->planetName = stripslashes($db->getField('planet_name'));
134
			$this->ownerID = $db->getInt('owner_id');
135
			$this->password = $db->getField('password');
136
			$this->shields = $db->getInt('shields');
137
			$this->armour = $db->getInt('armour');
138
			$this->drones = $db->getInt('drones');
139
			$this->credits = $db->getInt('credits');
140
			$this->bonds = $db->getInt('bonds');
141
			$this->maturity = $db->getInt('maturity');
142
			$this->inhabitableTime = $db->getInt('inhabitable_time');
143
			$this->typeID = $db->getInt('planet_type_id');
144
			
145
			$this->typeInfo = SmrPlanetType::getTypeInfo($this->getTypeID());
146
			$this->checkBondMaturity();
147
		}
148
	}
149
150
	public function getInterestRate() {
151
		$level = $this->getLevel();
152
		if ($level < 9) {
153
			return .0404;
154
		} elseif ($level < 19) {
155
			return .0609;
156
		} elseif ($level < 29) {
157
			return .1236;
158
		} elseif ($level < 39) {
159
			return .050625;
160
		} elseif ($level < 49) {
161
			return .0404;
162
		} elseif ($level < 59) {
163
			return .030225;
164
		} elseif ($level < 69) {
165
			return .0201;
166
		} else {
167
			return .018081;
168
		}
169
	}
170
171
	public function checkBondMaturity($partial = false) {
172
		if ($this->getMaturity() > 0 && ($partial === true || $this->getMaturity() < TIME)) {
173
			// calc the interest for the time
174
			$interest = $this->getBonds() * $this->getInterestRate();
175
176
			if ($partial === true && $this->getMaturity() > TIME) {
177
				// Adjust interest based upon how much of the bond duration has passed.
178
				$interest -= ($interest / $this->getBondTime()) * ($this->getMaturity() - TIME);
179
			}
180
181
			// transfer money to free avail cash
182
			$this->increaseCredits($this->getBonds() + $interest);
183
184
			// reset bonds
185
			$this->setBonds(0);
186
187
			// reset maturity
188
			$this->setMaturity(0);
189
		}
190
	}
191
192
	public function getBondTime() : int {
193
		return IRound(BOND_TIME / $this->getGame()->getGameSpeed());
194
	}
195
196
	public function bond() {
197
		$this->checkBondMaturity(true);
198
199
		// add it to bond
200
		$this->increaseBonds($this->getCredits());
201
202
		// set free cash to 0
203
		$this->setCredits(0);
204
205
		// initialize time
206
		$this->setMaturity(TIME + $this->getBondTime());
207
	}
208
209
	public function getGameID() {
210
		return $this->gameID;
211
	}
212
213
	public function getGame() {
214
		return SmrGame::getGame($this->gameID);
215
	}
216
217
	public function getSectorID() {
218
		return $this->sectorID;
219
	}
220
221
	public function getGalaxy() {
222
		return SmrGalaxy::getGalaxyContaining($this->getGameID(), $this->getSectorID());
223
	}
224
225
	public function getOwnerID() {
226
		return $this->ownerID;
227
	}
228
229
	public function hasOwner() {
230
		return $this->ownerID != 0;
231
	}
232
233
	public function setOwnerID($claimerID) {
234
		if ($this->ownerID == $claimerID) {
235
			return;
236
		}
237
		$this->ownerID = $claimerID;
238
		$this->hasChanged = true;
239
	}
240
241
	public function getOwner() {
242
		return SmrPlayer::getPlayer($this->getOwnerID(), $this->getGameID());
243
	}
244
245
	public function getPassword() {
246
		return $this->password;
247
	}
248
249
	public function setPassword($password) {
250
		if ($this->password == $password) {
251
			return;
252
		}
253
		$this->password = $password;
254
		$this->hasChanged = true;
255
	}
256
257
	public function removePassword() {
258
		$this->setPassword('');
259
	}
260
261
	public function getCredits() {
262
		return $this->credits;
263
	}
264
265
	public function setCredits($num) {
266
		if ($this->credits == $num) {
267
			return;
268
		}
269
		if ($num < 0) {
270
			throw new Exception('You cannot set negative credits.');
271
		}
272
		$this->credits = $num;
273
		$this->hasChangedFinancial = true;
274
	}
275
276
	public function increaseCredits($num) {
277
		if ($num == 0) {
278
			return;
279
		}
280
		$this->setCredits($this->getCredits() + $num);
281
	}
282
283
	public function decreaseCredits($num) {
284
		if ($num == 0) {
285
			return;
286
		}
287
		$this->setCredits($this->getCredits() - $num);
288
	}
289
290
	public function getMaturity() {
291
		return $this->maturity;
292
	}
293
294
	public function setMaturity($num) {
295
		if ($this->maturity == $num) {
296
			return;
297
		}
298
		if ($num < 0) {
299
			throw new Exception('You cannot set negative maturity.');
300
		}
301
		$this->maturity = $num;
302
		$this->hasChangedFinancial = true;
303
	}
304
305
	public function getBonds() {
306
		return $this->bonds;
307
	}
308
309
	public function setBonds($num) {
310
		if ($this->bonds == $num) {
311
			return;
312
		}
313
		if ($num < 0) {
314
			throw new Exception('You cannot set negative bonds.');
315
		}
316
		$this->bonds = $num;
317
		$this->hasChangedFinancial = true;
318
	}
319
	
320
	public function increaseBonds($num) {
321
		if ($num == 0) {
322
			return;
323
		}
324
		$this->setBonds($this->getBonds() + $num);
325
	}
326
327
	public function decreaseBonds($num) {
328
		if ($num == 0) {
329
			return;
330
		}
331
		$this->setBonds($this->getBonds() - $num);
332
	}
333
334
	public function checkForExcessDefense() {
335
		if ($this->getShields() > $this->getMaxShields()) {
336
			$this->setShields($this->getMaxShields());
337
		}
338
		if ($this->getCDs() > $this->getMaxCDs()) {
339
			$this->setCDs($this->getMaxCDs());
340
		}
341
		if ($this->getArmour() > $this->getMaxArmour()) {
342
				$this->setArmour($this->getMaxArmour());
343
		}
344
		// Remove a random (0-indexed) mounted weapon, if over max mount slots
345
		while ($this->getMountedWeapons() && max(array_keys($this->getMountedWeapons())) >= $this->getMaxMountedWeapons()) {
346
			$removeID = array_rand($this->getMountedWeapons());
347
			$this->removeMountedWeapon($removeID);
348
			foreach ($this->getMountedWeapons() as $orderID => $weapon) {
349
				if ($orderID > $removeID) {
350
					$this->moveMountedWeaponUp($orderID);
351
				}
352
			}
353
		}
354
	}
355
356
	public function getShields($delayed = false) {
357
		return $this->shields + ($delayed ? $this->delayedShieldsDelta : 0);
358
	}
359
360
	public function hasShields($delayed = false) {
361
		return $this->getShields($delayed) > 0;
362
	}
363
364
	public function setShields($shields) {
365
		$shields = max(0, min($shields, $this->getMaxShields()));
366
		if ($this->shields == $shields) {
367
			return;
368
		}
369
		$this->shields = $shields;
370
		$this->hasChanged = true;
371
	}
372
373
	public function decreaseShields($number, $delayed = false) {
374
		if ($number == 0) {
375
			return;
376
		}
377
		if ($delayed === false) {
378
			$this->setShields($this->getShields() - $number);
379
		} else {
380
			$this->delayedShieldsDelta -= $number;
381
		}
382
	}
383
384
	public function increaseShields($number, $delayed = false) {
385
		if ($number == 0) {
386
			return;
387
		}
388
		if ($delayed === false) {
389
			$this->setShields($this->getShields() + $number);
390
		} else {
391
			$this->delayedShieldsDelta += $number;
392
		}
393
	}
394
395
	public function getMaxShields() {
396
		return $this->getBuilding(PLANET_GENERATOR) * PLANET_GENERATOR_SHIELDS;
397
	}
398
399
	public function getArmour($delayed = false) {
400
		return $this->armour + ($delayed ? $this->delayedArmourDelta : 0);
401
	}
402
403
	public function hasArmour($delayed = false) {
404
		return $this->getArmour($delayed) > 0;
405
	}
406
407
	public function setArmour($armour) {
408
		$armour = max(0, min($armour, $this->getMaxArmour()));
409
		if ($this->armour == $armour) {
410
			return;
411
		}
412
		$this->armour = $armour;
413
		$this->hasChanged = true;
414
	}
415
416
	public function decreaseArmour($number, $delayed = false) {
417
		if ($number == 0) {
418
			return;
419
		}
420
		if ($delayed === false) {
421
			$this->setArmour($this->getArmour() - $number);
422
		} else {
423
			$this->delayedArmourDelta -= $number;
424
		}
425
	}
426
427
	public function increaseArmour($number, $delayed = false) {
428
		if ($number == 0) {
429
			return;
430
		}
431
		if ($delayed === false) {
432
			$this->setArmour($this->getArmour() + $number);
433
		} else {
434
			$this->delayedArmourDelta += $number;
435
		}
436
	}
437
438
	public function getMaxArmour() {
439
		return $this->getBuilding(PLANET_BUNKER) * PLANET_BUNKER_ARMOUR;
440
	}
441
442
	public function getCDs($delayed = false) {
443
		return $this->drones + ($delayed ? $this->delayedCDsDelta : 0);
444
	}
445
446
	public function hasCDs($delayed = false) {
447
		return $this->getCDs($delayed) > 0;
448
	}
449
450
	public function setCDs($combatDrones) {
451
		$combatDrones = max(0, min($combatDrones, $this->getMaxCDs()));
452
		if ($this->drones == $combatDrones) {
453
			return;
454
		}
455
		$this->drones = $combatDrones;
456
		$this->hasChanged = true;
457
	}
458
459
	public function decreaseCDs($number, $delayed = false) {
460
		if ($number == 0) {
461
			return;
462
		}
463
		if ($delayed === false) {
464
			$this->setCDs($this->getCDs() - $number);
465
		} else {
466
			$this->delayedCDsDelta -= $number;
467
		}
468
	}
469
470
	public function increaseCDs($number, $delayed = false) {
471
		if ($number == 0) {
472
			return;
473
		}
474
		if ($delayed === false) {
475
			$this->setCDs($this->getCDs() + $number);
476
		} else {
477
			$this->delayedCDsDelta += $number;
478
		}
479
	}
480
481
	public function getMaxCDs() {
482
		return $this->getBuilding(PLANET_HANGAR) * PLANET_HANGAR_DRONES;
483
	}
484
485
	public function getMaxMountedWeapons() {
486
		return $this->getBuilding(PLANET_WEAPON_MOUNT);
487
	}
488
489
	public function getMountedWeapons() {
490
		if (!isset($this->mountedWeapons)) {
491
			$this->mountedWeapons = [];
492
			if ($this->hasBuilding(PLANET_WEAPON_MOUNT)) {
493
				$this->db->query('SELECT weapon_type.*, order_id FROM planet_has_weapon JOIN weapon_type USING (weapon_type_id) WHERE ' . $this->SQL);
494
				while ($this->db->nextRecord()) {
495
					$weaponTypeID = $this->db->getInt('weapon_type_id');
496
					$orderID = $this->db->getInt('order_id');
497
					$this->mountedWeapons[$orderID] = SmrWeapon::getWeapon($weaponTypeID, false, $this->db);
498
				}
499
			}
500
		}
501
		return $this->mountedWeapons;
502
	}
503
504
	public function hasMountedWeapon($orderID) {
505
		$this->getMountedWeapons(); // Make sure array is initialized
506
		return isset($this->mountedWeapons[$orderID]);
507
	}
508
509
	public function addMountedWeapon($weaponTypeID, $orderID) {
510
		$this->getMountedWeapons(); // Make sure array is initialized
511
		$this->mountedWeapons[$orderID] = SmrWeapon::getWeapon($weaponTypeID);
512
		$this->hasChangedWeapons[$orderID] = true;
513
	}
514
515
	public function removeMountedWeapon($orderID) {
516
		$this->getMountedWeapons(); // Make sure array is initialized
517
		unset($this->mountedWeapons[$orderID]);
518
		$this->hasChangedWeapons[$orderID] = true;
519
	}
520
521
	private function swapMountedWeapons($orderID1, $orderID2) {
522
		$this->getMountedWeapons(); // Make sure array is initialized
523
		if (isset($this->mountedWeapons[$orderID1])) {
524
			$saveWeapon = $this->mountedWeapons[$orderID1];
525
		}
526
		if (isset($this->mountedWeapons[$orderID2])) {
527
			$this->mountedWeapons[$orderID1] = $this->mountedWeapons[$orderID2];
528
		} else {
529
			unset($this->mountedWeapons[$orderID1]);
530
		}
531
		if (isset($saveWeapon)) {
532
			$this->mountedWeapons[$orderID2] = $saveWeapon;
533
		} else {
534
			unset($this->mountedWeapons[$orderID2]);
535
		}
536
		$this->hasChangedWeapons[$orderID1] = true;
537
		$this->hasChangedWeapons[$orderID2] = true;
538
	}
539
540
	public function moveMountedWeaponUp($orderID) {
541
		if ($orderID == 0) {
542
			throw new Exception('Cannot move this weapon up!');
543
		}
544
		$this->swapMountedWeapons($orderID - 1, $orderID);
545
	}
546
547
	public function moveMountedWeaponDown($orderID) {
548
		if ($orderID == $this->getMaxMountedWeapons() - 1) {
549
			throw new Exception('Cannot move this weapon down!');
550
		}
551
		$this->swapMountedWeapons($orderID + 1, $orderID);
552
	}
553
554
555
	public function isDestroyed($delayed = false) {
556
		return !$this->hasCDs($delayed) && !$this->hasShields($delayed) && !$this->hasArmour($delayed);
557
	}
558
559
	public function exists() {
560
		return $this->getGameID() != null && $this->getSectorID() !== null;
561
	}
562
563
	public function getStockpile($goodID = false) {
564
		if (!isset($this->stockpile)) {
565
			// initialize cargo array
566
			$this->stockpile = array();
567
			// get supplies from db
568
			$this->db->query('SELECT good_id, amount FROM planet_has_cargo WHERE ' . $this->SQL);
569
			// adding cargo and amount to array
570
			while ($this->db->nextRecord()) {
571
				$this->stockpile[$this->db->getInt('good_id')] = $this->db->getInt('amount');
572
			}
573
		}
574
		if ($goodID === false) {
575
			return $this->stockpile;
576
		}
577
		if (isset($this->stockpile[$goodID])) {
578
			return $this->stockpile[$goodID];
579
		}
580
		return 0;
581
	}
582
583
	public function hasStockpile($goodID = false) {
584
		if ($goodID === false) {
585
			$stockpile = $this->getStockpile($goodID);
586
			return count($stockpile) > 0 && max($stockpile) > 0;
0 ignored issues
show
Bug introduced by
It seems like $stockpile can also be of type integer; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

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

586
			return count(/** @scrutinizer ignore-type */ $stockpile) > 0 && max($stockpile) > 0;
Loading history...
587
		} else {
588
			return $this->getStockpile($goodID) > 0;
589
		}
590
	}
591
592
	public function setStockpile($goodID, $amount) {
593
		if ($amount < 0) {
594
			throw new Exception('Trying to set negative stockpile.');
595
		}
596
		if ($this->getStockpile($goodID) == $amount) {
597
			return;
598
		}
599
		$this->stockpile[$goodID] = $amount;
600
		$this->hasChangedStockpile = true;
601
	}
602
603
	public function decreaseStockpile($goodID, $amount) {
604
		if ($amount < 0) {
605
			throw new Exception('Trying to decrease negative stockpile.');
606
		}
607
		$this->setStockpile($goodID, $this->getStockpile($goodID) - $amount);
608
	}
609
610
	public function increaseStockpile($goodID, $amount) {
611
		if ($amount < 0) {
612
			throw new Exception('Trying to increase negative stockpile.');
613
		}
614
		$this->setStockpile($goodID, $this->getStockpile($goodID) + $amount);
615
	}
616
617
	public function getBuildings() {
618
		if (!isset($this->buildings)) {
619
			$this->buildings = array();
620
621
			// get buildingss from db
622
			$this->db->query('SELECT construction_id, amount FROM planet_has_building WHERE ' . $this->SQL);
623
			// adding building and amount to array
624
			while ($this->db->nextRecord()) {
625
				$this->buildings[$this->db->getInt('construction_id')] = $this->db->getInt('amount');
626
			}
627
628
			// Update building counts if construction has finished
629
			$this->getCurrentlyBuilding();
630
		}
631
		return $this->buildings;
632
	}
633
634
	public function getBuilding($buildingTypeID) {
635
		$buildings = $this->getBuildings();
636
		if (isset($buildings[$buildingTypeID])) {
637
			return $buildings[$buildingTypeID];
638
		}
639
		return 0;
640
	}
641
642
	public function hasBuilding($buildingTypeID) {
643
		return $this->getBuilding($buildingTypeID) > 0;
644
	}
645
646
	public function setBuilding($buildingTypeID, $number) {
647
		if ($this->getBuilding($buildingTypeID) == $number) {
648
			return;
649
		}
650
651
		$this->buildings[$buildingTypeID] = $number;
652
		$this->hasChangedBuildings[$buildingTypeID] = true;
653
	}
654
655
	public function increaseBuilding($buildingTypeID, $number) {
656
		$this->setBuilding($buildingTypeID, $this->getBuilding($buildingTypeID) + $number);
657
	}
658
659
	public function destroyBuilding($buildingTypeID, $number) {
660
		if (!$this->hasBuilding($buildingTypeID)) {
661
			throw new Exception('Trying to destroy a nonexistent building');
662
		}
663
		$this->setBuilding($buildingTypeID, $this->getBuilding($buildingTypeID) - $number);
664
	}
665
666
	public function getCurrentlyBuilding() {
667
		if (!isset($this->currentlyBuilding)) {
668
			$this->currentlyBuilding = array();
669
670
			$this->db->query('SELECT * FROM planet_is_building WHERE ' . $this->SQL);
671
			while ($this->db->nextRecord()) {
672
				$this->currentlyBuilding[$this->db->getInt('building_slot_id')] = array(
673
					'BuildingSlotID' => $this->db->getInt('building_slot_id'),
674
					'ConstructionID' => $this->db->getInt('construction_id'),
675
					'ConstructorID' => $this->db->getInt('constructor_id'),
676
					'Finishes' => $this->db->getInt('time_complete'),
677
					'TimeRemaining' => $this->db->getInt('time_complete') - TIME,
678
				);
679
			}
680
681
			// Check if construction has completed
682
			foreach ($this->currentlyBuilding as $id => $building) {
683
				if ($building['TimeRemaining'] <= 0) {
684
					unset($this->currentlyBuilding[$id]);
685
					$expGain = $this->getConstructionExp($building['ConstructionID']);
686
					$player = SmrPlayer::getPlayer($building['ConstructorID'], $this->getGameID());
687
					$player->increaseHOF(1, array('Planet', 'Buildings', 'Built'), HOF_ALLIANCE);
688
					$player->increaseExperience($expGain);
689
					$player->increaseHOF($expGain, array('Planet', 'Buildings', 'Experience'), HOF_ALLIANCE);
690
					$this->hasStoppedBuilding[] = $building['BuildingSlotID'];
691
					$this->increaseBuilding($building['ConstructionID'], 1);
692
693
					// WARNING: The above modifications to the player/planet are dangerous because
694
					// they may not be part of the current sector lock. But since they might not be,
695
					// we may as well just update now to avoid either a) needing to remember to call
696
					// this explicitly in all appropriate engine files or b) inconsistent exp display
697
					// if this is called during the template display only and therefore unsaved.
698
					$player->update();
699
					$this->update();
700
				}
701
			}
702
		}
703
		return $this->currentlyBuilding;
704
	}
705
706
	public function getMaxBuildings($buildingTypeID = false) {
707
		if ($buildingTypeID === false) {
708
			$structs = $this->typeInfo::STRUCTURES;
709
			return array_combine(array_keys($structs),
710
			                     array_column($structs, 'max_amount'));
711
		}
712
		return $this->getStructureTypes($buildingTypeID)->maxAmount();
713
	}
714
	
715
	public function getTypeID() {
716
		return $this->typeID;
717
	}
718
	
719
	public function setTypeID($num) {
720
		if (isset($this->typeID) && $this->typeID == $num) {
721
			return;
722
		}
723
		$this->typeID = $num;
724
		$this->db->query('UPDATE planet SET planet_type_id = ' . $this->db->escapeNumber($num) . ' WHERE ' . $this->SQL);
725
		$this->typeInfo = SmrPlanetType::getTypeInfo($this->getTypeID());
726
		
727
		//trim buildings first
728
		foreach ($this->getBuildings() as $id => $amt) {
729
			if ($this->getMaxBuildings($id) < $amt) {
730
				$this->destroyBuilding($id, $amt - $this->getMaxBuildings($id));
731
			}
732
		}
733
		
734
		//trim excess defenses
735
		$this->checkForExcessDefense();
736
		
737
		$this->hasChanged = true;
738
		$this->update();
739
	}
740
	
741
	public function getTypeImage() {
742
		return $this->typeInfo->imageLink();
743
	}
744
745
	public function getTypeName() {
746
		return $this->typeInfo->name();
747
	}
748
749
	public function getTypeDescription() {
750
		return $this->typeInfo->description();
751
	}
752
753
	public function getMaxAttackers() {
754
		return $this->typeInfo->maxAttackers();
755
	}
756
757
	public function getMaxLanded() {
758
		return $this->typeInfo->maxLanded();
759
	}
760
761
	public function getStructureTypes($structureID = false) {
762
		return $this->typeInfo->structureTypes($structureID);
763
	}
764
765
	public function hasStructureType($structureID) {
766
		return isset($this->getStructureTypes()[$structureID]);
767
	}
768
769
	/**
770
	 * Specifies which menu options the planet has.
771
	 */
772
	public function hasMenuOption($option) {
773
		// We do not set options that are unavailable
774
		return in_array($option, $this->typeInfo->menuOptions());
775
	}
776
777
	public function doDelayedUpdates() {
778
		$this->setShields($this->getShields(true));
779
		$this->delayedShieldsDelta = 0;
780
		$this->setCDs($this->getCDs(true));
781
		$this->delayedCDsDelta = 0;
782
		$this->setArmour($this->getArmour(true));
783
		$this->delayedArmourDelta = 0;
784
	}
785
	
786
	public function update() {
787
		if (!$this->exists()) {
788
			return;
789
		}
790
		$this->doDelayedUpdates();
791
		if ($this->hasChanged) {
792
			$this->db->query('UPDATE planet SET
793
									owner_id = ' . $this->db->escapeNumber($this->ownerID) . ',
794
									password = '.$this->db->escapeString($this->password) . ',
795
									planet_name = ' . $this->db->escapeString($this->planetName) . ',
796
									shields = ' . $this->db->escapeNumber($this->shields) . ',
797
									armour = ' . $this->db->escapeNumber($this->armour) . ',
798
									drones = ' . $this->db->escapeNumber($this->drones) . '
799
								WHERE ' . $this->SQL);
800
			$this->hasChanged = false;
801
		}
802
803
		// Separate update for financial since these can be modified by looking
804
		// at the planet list (i.e. you might not have sector lock and could
805
		// cause a race condition with events happening in the planet sector).
806
		if ($this->hasChangedFinancial) {
807
			$this->db->query('UPDATE planet SET
808
									credits = ' . $this->db->escapeNumber($this->credits) . ',
809
									bonds = ' . $this->db->escapeNumber($this->bonds) . ',
810
									maturity = ' . $this->db->escapeNumber($this->maturity) . '
811
								WHERE ' . $this->SQL);
812
			$this->hasChangedFinancial = false;
813
		}
814
815
		if ($this->hasChangedStockpile) {
816
			// write stockpile info
817
			foreach ($this->getStockpile() as $id => $amount) {
818
				if ($amount != 0) {
819
					$this->db->query('REPLACE INTO planet_has_cargo (game_id, sector_id, good_id, amount) ' .
820
										 'VALUES(' . $this->db->escapeNumber($this->getGameID()) . ', ' . $this->db->escapeNumber($this->getSectorID()) . ', ' . $this->db->escapeNumber($id) . ', ' . $this->db->escapeNumber($amount) . ')');
821
				} else {
822
					$this->db->query('DELETE FROM planet_has_cargo WHERE ' . $this->SQL . '
823
										AND good_id = ' . $this->db->escapeNumber($id));
824
				}
825
			}
826
		}
827
828
		if (count($this->hasChangedWeapons) > 0) {
829
			foreach (array_keys($this->hasChangedWeapons) as $orderID) {
830
				if (isset($this->mountedWeapons[$orderID])) {
831
					$this->db->query('REPLACE INTO planet_has_weapon (game_id, sector_id, order_id, weapon_type_id) VALUES (' . $this->db->escapeNumber($this->getGameID()) . ',' . $this->db->escapeNumber($this->getSectorID()) . ',' . $this->db->escapeNumber($orderID) . ',' . $this->db->escapeNumber($this->mountedWeapons[$orderID]->getWeaponTypeID()) . ')');
832
				} else {
833
					$this->db->query('DELETE FROM planet_has_weapon WHERE ' . $this->SQL . ' AND order_id=' . $this->db->escapeNumber($orderID));
834
				}
835
			}
836
			$this->hasChangedWeapons = [];
837
		}
838
839
		if (count($this->hasStoppedBuilding) > 0) {
840
			$this->db->query('DELETE FROM planet_is_building WHERE ' . $this->SQL . '
841
								AND building_slot_id IN (' . $this->db->escapeArray($this->hasStoppedBuilding) . ') LIMIT ' . count($this->hasStoppedBuilding));
842
			$this->hasStoppedBuilding = array();
843
		}
844
		// write building info
845
		foreach ($this->hasChangedBuildings as $id => $hasChanged) {
846
			if ($hasChanged === true) {
847
				if ($this->hasBuilding($id)) {
848
					$this->db->query('REPLACE INTO planet_has_building (game_id, sector_id, construction_id, amount) ' .
849
										'VALUES(' . $this->db->escapeNumber($this->gameID) . ', ' . $this->db->escapeNumber($this->sectorID) . ', ' . $this->db->escapeNumber($id) . ', ' . $this->db->escapeNumber($this->getBuilding($id)) . ')');
850
				} else {
851
					$this->db->query('DELETE FROM planet_has_building WHERE ' . $this->SQL . '
852
										AND construction_id = ' . $this->db->escapeNumber($id));
853
				}
854
				$this->hasChangedBuildings[$id] = false;
855
			}
856
		}
857
	}
858
859
	public function getLevel() {
860
		return array_sum($this->getBuildings()) / 3;
861
	}
862
	
863
	public function getMaxLevel() {
864
		return array_sum($this->getMaxBuildings()) / 3;
0 ignored issues
show
Bug introduced by
It seems like $this->getMaxBuildings() can also be of type false; however, parameter $array of array_sum() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

864
		return array_sum(/** @scrutinizer ignore-type */ $this->getMaxBuildings()) / 3;
Loading history...
865
	}
866
867
	public function accuracy() {
868
		if ($this->hasWeapons()) {
869
			$weapons = $this->getWeapons();
870
			return $weapons[0]->getModifiedPlanetAccuracy($this);
871
		}
872
		return 0;
873
	}
874
875
	/**
876
	 * Returns the accuracy bonus for mounted weaons (as a percent)
877
	 */
878
	public function getAccuracyBonus() {
879
		return 5 * $this->getBuilding(PLANET_RADAR);
880
	}
881
882
	public function getRemainingStockpile($id) {
883
		return self::MAX_STOCKPILE - $this->getStockpile($id);
884
	}
885
886
	/**
887
	 * Returns true if there is a building in progress
888
	 */
889
	public function hasCurrentlyBuilding() {
890
		return count($this->getCurrentlyBuilding()) > 0;
891
	}
892
893
	public function canBuild(AbstractSmrPlayer $constructor, $constructionID) {
894
		if ($this->hasCurrentlyBuilding()) {
895
			return 'There is already a building in progress!';
896
		}
897
		if ($this->getBuilding($constructionID) >= $this->getMaxBuildings($constructionID)) {
898
			return 'This planet has reached the maximum buildings of that type.';
899
		}
900
		$cost = $this->getStructureTypes($constructionID)->creditCost();
901
		if ($constructor->getCredits() < $cost) {
902
			return 'You do not have enough credits.';
903
		}
904
		foreach ($this->getStructureTypes($constructionID)->hardwareCost() as $hardwareID) {
905
			if (!$constructor->getShip()->getHardware($hardwareID)) {
906
				return 'You do not have the hardware needed for this type of building!';
907
			}
908
		}
909
		// take the goods that are needed
910
		foreach ($this->getStructureTypes($constructionID)->goods() as $goodID => $amount) {
911
			if ($this->getStockpile($goodID) < $amount) {
912
				return 'There are not enough goods available.';
913
			}
914
		}
915
		return true;
916
	}
917
918
	// Modifier for planet building based on the number of buildings.
919
	// The average value of this modifier should roughly be 1.
920
	private function getCompletionModifier($constructionID) {
921
		$currentBuildings = $this->getBuilding($constructionID);
922
		$maxBuildings = $this->getMaxBuildings($constructionID);
923
		return 0.01 + 2.97 * pow($currentBuildings / $maxBuildings, 2);
924
	}
925
926
	// Amount of exp gained to build the next building of this type
927
	private function getConstructionExp($constructionID) {
928
		$expGain = $this->getStructureTypes($constructionID)->expGain();
929
		return $expGain;
930
	}
931
932
	// Amount of time (in seconds) to build the next building of this type
933
	public function getConstructionTime($constructionID) : int {
934
		$baseTime = $this->getStructureTypes($constructionID)->baseTime();
935
		$constructionTime = ICeil($baseTime * $this->getCompletionModifier($constructionID) / $this->getGame()->getGameSpeed());
936
		return $constructionTime;
937
	}
938
	
939
	public function startBuilding(AbstractSmrPlayer $constructor, $constructionID) {
940
		if (($message = $this->canBuild($constructor, $constructionID)) !== true) {
941
			throw new Exception('Unable to start building: ' . $message);
942
		}
943
		$constructor->decreaseCredits($this->getStructureTypes($constructionID)->creditCost());
944
		// take the goods that are needed
945
		foreach ($this->getStructureTypes($constructionID)->goods() as $goodID => $amount) {
946
			$this->decreaseStockpile($goodID, $amount);
947
		}
948
		foreach ($this->getStructureTypes($constructionID)->hardwareCost() as $hardwareID) {
949
			$constructor->getShip()->setHardware($hardwareID, 0);
950
		}
951
	
952
		// gets the time for the buildings
953
		$timeComplete = TIME + $this->getConstructionTime($constructionID);
954
		$this->db->query('INSERT INTO planet_is_building (game_id, sector_id, construction_id, constructor_id, time_complete) ' .
955
						'VALUES (' . $this->db->escapeNumber($this->getGameID()) . ', ' . $this->db->escapeNumber($this->getSectorID()) . ', ' . $this->db->escapeNumber($constructionID) . ', ' . $this->db->escapeNumber($constructor->getAccountID()) . ',' . $this->db->escapeNumber($timeComplete) . ')');
956
957
		$this->currentlyBuilding[$this->db->getInsertID()] = array(
958
			'BuildingSlotID' => $this->db->getInsertID(),
959
			'ConstructionID' => $constructionID,
960
			'ConstructorID' => $constructor->getAccountID(),
961
			'Finishes' => $timeComplete,
962
			'TimeRemaining' => $timeComplete - TIME
963
		);
964
	}
965
966
	public function stopBuilding($constructionID) {
967
		$matchingBuilding = false;
968
		$latestFinish = 0;
969
		foreach ($this->getCurrentlyBuilding() as $key => $building) {
970
			if ($building['ConstructionID'] == $constructionID && $building['Finishes'] > $latestFinish) {
971
				$latestFinish = $building['Finishes'];
972
				$matchingBuilding = $building;
973
			}
974
		}
975
		if ($matchingBuilding) {
976
			$this->hasStoppedBuilding[] = $matchingBuilding['BuildingSlotID'];
977
			unset($this->currentlyBuilding[$matchingBuilding['BuildingSlotID']]);
978
			return true;
979
		}
980
		return false;
981
	}
982
983
	public function setName($name) {
984
		if ($this->planetName == $name) {
985
			return;
986
		}
987
		$this->planetName = $name;
988
		$this->hasChanged = true;
989
	}
990
991
	/**
992
	 * Returns the name of the planet, suitably escaped for HTML display.
993
	 */
994
	public function getDisplayName() {
995
		return htmlentities($this->planetName);
996
	}
997
998
	/**
999
	 * Returns the name of the planet, intended for combat messages.
1000
	 */
1001
	public function getCombatName() {
1002
		return '<span style="color:yellow;font-variant:small-caps">' . $this->getDisplayName() . ' (#' . $this->getSectorID() . ')</span>';
1003
	}
1004
1005
	public function isInhabitable() {
1006
		return $this->inhabitableTime <= TIME;
1007
	}
1008
1009
	public function getInhabitableTime() {
1010
		return $this->inhabitableTime;
1011
	}
1012
1013
	public function isClaimed() {
1014
		return $this->ownerID > 0;
1015
	}
1016
1017
	public function removeClaimed() {
1018
		$this->setOwnerID(0);
1019
	}
1020
1021
	public function getExamineHREF() {
1022
		return SmrSession::getNewHREF(create_container('skeleton.php', 'planet_examine.php'));
1023
	}
1024
1025
	public function getLandHREF() {
1026
		return SmrSession::getNewHREF(create_container('planet_land_processing.php'));
1027
	}
1028
1029
	public function getAttackHREF() {
1030
		return SmrSession::getNewHREF(create_container('planet_attack_processing.php'));
1031
	}
1032
1033
	public function getBuildHREF($structureID) {
1034
		$container = create_container('planet_construction_processing.php');
1035
		$container['construction_id'] = $structureID;
1036
		$container['action'] = 'Build';
1037
		return SmrSession::getNewHREF($container);
1038
	}
1039
1040
	public function getCancelHREF($structureID) {
1041
		$container = create_container('planet_construction_processing.php');
1042
		$container['construction_id'] = $structureID;
1043
		$container['action'] = 'Cancel';
1044
		return SmrSession::getNewHREF($container);
1045
	}
1046
1047
	public function getFinancesHREF() {
1048
		return SmrSession::getNewHREF(create_container('planet_financial_processing.php'));
1049
	}
1050
1051
	public function getBondConfirmationHREF() {
1052
		return SmrSession::getNewHREF(create_container('skeleton.php', 'planet_bond_confirmation.php'));
1053
	}
1054
1055
	public function attackedBy(AbstractSmrPlayer $trigger, array $attackers) {
1056
		$trigger->increaseHOF(1, array('Combat', 'Planet', 'Number Of Triggers'), HOF_PUBLIC);
1057
		foreach ($attackers as $attacker) {
1058
			$attacker->increaseHOF(1, array('Combat', 'Planet', 'Number Of Attacks'), HOF_PUBLIC);
1059
			$this->db->query('REPLACE INTO player_attacks_planet (game_id, account_id, sector_id, time, level) VALUES ' .
1060
					'(' . $this->db->escapeNumber($this->getGameID()) . ', ' . $this->db->escapeNumber($attacker->getAccountID()) . ', ' . $this->db->escapeNumber($this->getSectorID()) . ', ' . $this->db->escapeNumber(TIME) . ', ' . $this->db->escapeNumber($this->getLevel()) . ')');
1061
		}
1062
1063
		// Add each unique attack to news unless it was already added recently.
1064
		// Note: Attack uniqueness determined by planet owner.
1065
		$owner = $this->getOwner();
1066
		$this->db->query('SELECT 1 FROM news WHERE type = \'BREAKING\' AND game_id = ' . $this->db->escapeNumber($trigger->getGameID()) . ' AND dead_id=' . $this->db->escapeNumber($owner->getAccountID()) . ' AND time > ' . $this->db->escapeNumber(TIME - self::TIME_ATTACK_NEWS_COOLDOWN) . ' LIMIT 1');
1067
		if ($this->db->getNumRows() == 0) {
1068
			if (count($attackers) >= 5) {
1069
				$text = count($attackers) . ' members of ' . $trigger->getAllianceBBLink() . ' have been spotted attacking ' .
1070
					$this->getDisplayName() . ' in sector ' . Globals::getSectorBBLink($this->getSectorID()) . '. The planet is owned by ' . $owner->getBBLink();
1071
				if ($owner->hasAlliance()) {
1072
					$text .= ', a member of ' . $owner->getAllianceBBLink();
1073
				}
1074
				$text .= '.';
1075
				$this->db->query('INSERT INTO news (game_id, time, news_message, type,killer_id,killer_alliance,dead_id,dead_alliance) VALUES (' . $this->db->escapeNumber($this->getGameID()) . ', ' . $this->db->escapeNumber(TIME) . ', ' . $this->db->escapeString($text) . ', \'BREAKING\',' . $this->db->escapeNumber($trigger->getAccountID()) . ',' . $this->db->escapeNumber($trigger->getAllianceID()) . ',' . $this->db->escapeNumber($owner->getAccountID()) . ',' . $this->db->escapeNumber($owner->getAllianceID()) . ')');
1076
			}
1077
		}
1078
	}
1079
1080
	
1081
	
1082
	public function getPlayers() {
1083
		return SmrPlayer::getPlanetPlayers($this->getGameID(), $this->getSectorID());
1084
	}
1085
1086
	public function countPlayers() {
1087
		return count($this->getPlayers());
1088
	}
1089
	
1090
	public function hasPlayers() {
1091
		return count($this->getPlayers()) > 0;
1092
	}
1093
1094
	public function getOtherTraders(AbstractSmrPlayer $player) {
1095
		$players = SmrPlayer::getPlanetPlayers($this->getGameID(), $this->getSectorID()); //Do not use & because we unset something and only want that in what we return
1096
		unset($players[$player->getAccountID()]);
1097
		return $players;
1098
	}
1099
1100
	public function hasOtherTraders(AbstractSmrPlayer $player) {
1101
		return count($this->getOtherTraders($player)) > 0;
1102
	}
1103
1104
	public function hasEnemyTraders(AbstractSmrPlayer $player) {
1105
		if (!$this->hasOtherTraders($player)) {
1106
			return false;
1107
		}
1108
		$otherPlayers = $this->getOtherTraders($player);
1109
		foreach ($otherPlayers as $otherPlayer) {
1110
			if (!$player->traderNAPAlliance($otherPlayer)) {
1111
				return true;
1112
			}
1113
		}
1114
		return false;
1115
	}
1116
1117
	public function hasFriendlyTraders(AbstractSmrPlayer $player) {
1118
		if (!$this->hasOtherTraders($player)) {
1119
			return false;
1120
		}
1121
		$otherPlayers = $this->getOtherTraders($player);
1122
		foreach ($otherPlayers as $otherPlayer) {
1123
			if ($player->traderNAPAlliance($otherPlayer)) {
1124
				return true;
1125
			}
1126
		}
1127
		return false;
1128
	}
1129
1130
	public function getWeapons() {
1131
		$weapons = $this->getMountedWeapons();
1132
		for ($i = 0; $i < $this->getBuilding(PLANET_TURRET); ++$i) {
1133
			$weapons[] = SmrWeapon::getWeapon(WEAPON_PLANET_TURRET);
1134
		}
1135
		return $weapons;
1136
	}
1137
1138
	public function hasWeapons() {
1139
		return count($this->getWeapons()) > 0;
1140
	}
1141
1142
	public function &shootPlayer(AbstractSmrPlayer $targetPlayer) {
1143
		return $this->shootPlayers(array($targetPlayer));
1144
	}
1145
1146
	public function &shootPlayers(array $targetPlayers) {
1147
		$results = array('Planet' => $this, 'TotalDamage' => 0, 'TotalDamagePerTargetPlayer' => array());
1148
		foreach ($targetPlayers as $targetPlayer) {
1149
			$results['TotalDamagePerTargetPlayer'][$targetPlayer->getAccountID()] = 0;
1150
		}
1151
		if ($this->isDestroyed()) {
1152
			$results['DeadBeforeShot'] = true;
1153
			return $results;
1154
		}
1155
		$results['DeadBeforeShot'] = false;
1156
		$weapons = $this->getWeapons();
1157
		foreach ($weapons as $orderID => $weapon) {
1158
			$results['Weapons'][$orderID] =& $weapon->shootPlayerAsPlanet($this, $targetPlayers[array_rand($targetPlayers)]);
1159
			if ($results['Weapons'][$orderID]['Hit']) {
1160
				$results['TotalDamage'] += $results['Weapons'][$orderID]['ActualDamage']['TotalDamage'];
1161
				$results['TotalDamagePerTargetPlayer'][$results['Weapons'][$orderID]['TargetPlayer']->getAccountID()] += $results['Weapons'][$orderID]['ActualDamage']['TotalDamage'];
1162
			}
1163
		}
1164
		if ($this->hasCDs()) {
1165
			$thisCDs = new SmrCombatDrones($this->getGameID(), $this->getCDs(), true);
1166
			$results['Drones'] =& $thisCDs->shootPlayerAsPlanet($this, $targetPlayers[array_rand($targetPlayers)]);
1167
			$results['TotalDamage'] += $results['Drones']['ActualDamage']['TotalDamage'];
1168
			$results['TotalDamagePerTargetPlayer'][$results['Drones']['TargetPlayer']->getAccountID()] += $results['Drones']['ActualDamage']['TotalDamage'];
1169
		}
1170
		return $results;
1171
	}
1172
1173
	/**
1174
	 * Returns an array of structure losses due to damage taken.
1175
	 */
1176
	public function checkForDowngrade($damage) : array {
1177
		$results = [];
1178
		// For every 70 damage there is a 15% chance of destroying a structure.
1179
		// Which structure is destroyed depends on the ratio of buildings and
1180
		// the time it takes to build them.
1181
		$numChances = floor($damage / self::DAMAGE_NEEDED_FOR_DOWNGRADE_CHANCE);
1182
		for ($i = 0; $i < $numChances; $i++) {
1183
			// Stop if the planet has no more buildlings
1184
			if ($this->getLevel() == 0) {
1185
				break;
1186
			}
1187
			//15% chance to destroy something
1188
			if (mt_rand(1, 100) <= self::CHANCE_TO_DOWNGRADE) {
1189
				$chanceFactors = [];
1190
				foreach ($this->getStructureTypes() as $structureID => $structure) {
1191
					$chanceFactors[$structureID] = ($this->getBuilding($structureID) / $this->getMaxBuildings($structureID)) / $structure->baseTime();
1192
				}
1193
				$destroyID = getWeightedRandom($chanceFactors);
1194
				$this->destroyBuilding($destroyID, 1);
1195
				$this->checkForExcessDefense();
1196
				if (isset($results[$destroyID])) {
1197
					$results[$destroyID] += 1;
1198
				} else {
1199
					$results[$destroyID] = 1;
1200
				}
1201
			}
1202
		}
1203
		return $results;
1204
	}
1205
1206
	public function &doWeaponDamage(array $damage, $delayed) {
1207
		$alreadyDead = $this->isDestroyed(true);
1208
		$shieldDamage = 0;
1209
		$cdDamage = 0;
1210
		$armourDamage = 0;
1211
		if (!$alreadyDead) {
1212
			if ($damage['Shield'] || !$this->hasShields(true)) {
1213
				$shieldDamage = $this->doShieldDamage(min($damage['MaxDamage'], $damage['Shield']), $delayed);
1214
				$damage['Shield'] -= $shieldDamage;
1215
				$damage['MaxDamage'] -= $shieldDamage;
1216
1217
				if (!$this->hasShields(true) && ($shieldDamage == 0 || $damage['Rollover'])) {
1218
					if ($this->hasCDs(true)) {
1219
						$cdDamage = $this->doCDDamage(min($damage['MaxDamage'], $damage['Armour']), $delayed);
1220
						$damage['Armour'] -= $cdDamage;
1221
						$damage['MaxDamage'] -= $cdDamage;
1222
					}
1223
					if ($this->hasArmour(true) && ($cdDamage == 0 || $damage['Rollover'])) {
1224
						$armourDamage = $this->doArmourDamage(min($damage['MaxDamage'], $damage['Armour']), $delayed);
1225
						$damage['Armour'] -= $armourDamage;
1226
						$damage['MaxDamage'] -= $armourDamage;
1227
					}
1228
				}
1229
1230
			} else { // hit drones behind shields - we should only use this reduced damage branch if we cannot hit shields.
1231
				$cdDamage = $this->doCDDamage(IFloor(min($damage['MaxDamage'], $damage['Armour']) * DRONES_BEHIND_SHIELDS_DAMAGE_PERCENT), $delayed);
1232
			}
1233
		}
1234
1235
		$return = array(
1236
			'KillingShot' => !$alreadyDead && $this->isDestroyed(true),
1237
			'TargetAlreadyDead' => $alreadyDead,
1238
			'Shield' => $shieldDamage,
1239
			'Armour' => $armourDamage,
1240
			'HasShields' => $this->hasShields(true),
1241
			'HasArmour' => $this->hasArmour(true),
1242
			'CDs' => $cdDamage,
1243
			'NumCDs' => $cdDamage / CD_ARMOUR,
1244
			'HasCDs' => $this->hasCDs(true),
1245
			'TotalDamage' => $shieldDamage + $cdDamage + $armourDamage
1246
		);
1247
		return $return;
1248
	}
1249
1250
	protected function doShieldDamage($damage, $delayed) {
1251
		$actualDamage = min($this->getShields(true), $damage);
1252
		$this->decreaseShields($actualDamage, $delayed);
1253
		return $actualDamage;
1254
	}
1255
1256
	protected function doCDDamage($damage, $delayed) {
1257
		$actualDamage = min($this->getCDs(true), IFloor($damage / CD_ARMOUR));
1258
		$this->decreaseCDs($actualDamage, $delayed);
1259
		return $actualDamage * CD_ARMOUR;
1260
	}
1261
	
1262
	protected function doArmourDamage($damage, $delayed) {
1263
		$actualDamage = min($this->getArmour(true), $damage);
1264
		$this->decreaseArmour($actualDamage, $delayed);
1265
		return $actualDamage;
1266
	}
1267
1268
	public function creditCurrentAttackersForKill() {
1269
		//get all players involved for HoF
1270
		$this->db->query('SELECT account_id,level FROM player_attacks_planet WHERE ' . $this->SQL . ' AND time > ' . $this->db->escapeNumber(TIME - self::TIME_TO_CREDIT_BUST));
1271
		while ($this->db->nextRecord()) {
1272
			$currPlayer = SmrPlayer::getPlayer($this->db->getInt('account_id'), $this->getGameID());
1273
			$currPlayer->increaseHOF($this->db->getInt('level'), array('Combat', 'Planet', 'Levels'), HOF_PUBLIC);
1274
			$currPlayer->increaseHOF(1, array('Combat', 'Planet', 'Completed'), HOF_PUBLIC);
1275
		}
1276
		$this->db->query('DELETE FROM player_attacks_planet WHERE ' . $this->SQL);
1277
	}
1278
1279
	public function &killPlanetByPlayer(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

1279
	public function &killPlanetByPlayer(/** @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...
1280
		$return = array();
1281
		$this->creditCurrentAttackersForKill();
1282
1283
		//kick everyone from planet
1284
		$this->db->query('UPDATE player SET land_on_planet = \'FALSE\' WHERE ' . $this->SQL);
1285
		$this->removeClaimed();
1286
		$this->removePassword();
1287
		return $return;
1288
	}
1289
}
1290