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 ( 1adc02...750da7 )
by Dan
23s queued 16s
created

SmrPlayer::doMessageSending()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 48
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 34
c 1
b 0
f 0
nc 8
nop 8
dl 0
loc 48
rs 8.4426

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php declare(strict_types=1);
2
3
// Exception thrown when a player cannot be found in the database
4
class PlayerNotFoundException extends Exception {}
5
6
class SmrPlayer extends AbstractSmrPlayer {
7
	const TIME_FOR_FEDERAL_BOUNTY_ON_PR = 10800;
8
	const TIME_FOR_ALLIANCE_SWITCH = 0;
9
	protected static $CACHE_SECTOR_PLAYERS = array();
10
	protected static $CACHE_PLANET_PLAYERS = array();
11
	protected static $CACHE_ALLIANCE_PLAYERS = array();
12
	protected static $CACHE_PLAYERS = array();
13
14
	protected $db;
15
	protected $SQL;
16
17
	protected $newbieWarning;
18
	protected $tickers;
19
	protected $lastTurnUpdate;
20
	protected $lastNewsUpdate;
21
	protected $attackColour;
22
//	protected $pastKnowledge;
23
	protected $allianceJoinable;
24
	protected $lastPort;
25
	protected $bank;
26
	protected $zoom;
27
	protected $displayMissions;
28
	protected $displayWeapons;
29
	protected $ignoreGlobals;
30
	protected $plottedCourse;
31
	protected $plottedCourseFrom;
32
	protected $nameChanged;
33
	protected $combatDronesKamikazeOnMines;
34
	protected $customShipName;
35
	protected $storedDestinations;
36
37
38
	public static function refreshCache() {
39
		foreach (self::$CACHE_PLAYERS as $gameID => &$gamePlayers) {
40
			foreach ($gamePlayers as $accountID => &$player) {
41
				$player = self::getPlayer($accountID, $gameID, true);
42
			}
43
		}
44
	}
45
46
	public static function clearCache() {
47
		self::$CACHE_PLAYERS = array();
48
		self::$CACHE_SECTOR_PLAYERS = array();
49
	}
50
51
	public static function savePlayers() {
52
		foreach (self::$CACHE_PLAYERS as $gamePlayers) {
53
			foreach ($gamePlayers as $player) {
54
				$player->save();
55
			}
56
		}
57
	}
58
59
	public static function getSectorPlayersByAlliances($gameID, $sectorID, array $allianceIDs, $forceUpdate = false) {
60
		$players = self::getSectorPlayers($gameID, $sectorID, $forceUpdate); // Don't use & as we do an unset
61
		foreach ($players as $accountID => $player) {
62
			if (!in_array($player->getAllianceID(), $allianceIDs)) {
63
				unset($players[$accountID]);
64
			}
65
		}
66
		return $players;
67
	}
68
69
	/**
70
	 * Returns the same players as getSectorPlayers (e.g. not on planets),
71
	 * but for an entire galaxy rather than a single sector. This is useful
72
	 * for reducing the number of queries in galaxy-wide processing.
73
	 */
74
	public static function getGalaxyPlayers($gameID, $galaxyID, $forceUpdate = false) {
75
		$db = new SmrMySqlDatabase();
76
		$db->query('SELECT player.*, sector_id FROM sector LEFT JOIN player USING(game_id, sector_id) WHERE game_id = ' . $db->escapeNumber($gameID) . ' AND land_on_planet = ' . $db->escapeBoolean(false) . ' AND (last_cpl_action > ' . $db->escapeNumber(TIME - TIME_BEFORE_INACTIVE) . ' OR newbie_turns = 0) AND galaxy_id = ' . $db->escapeNumber($galaxyID));
77
		$galaxyPlayers = [];
78
		while ($db->nextRecord()) {
79
			$sectorID = $db->getInt('sector_id');
80
			if (!$db->hasField('account_id')) {
81
				self::$CACHE_SECTOR_PLAYERS[$gameID][$sectorID] = [];
82
			} else {
83
				$accountID = $db->getInt('account_id');
84
				$player = self::getPlayer($accountID, $gameID, $forceUpdate, $db);
85
				self::$CACHE_SECTOR_PLAYERS[$gameID][$sectorID][$accountID] = $player;
86
				$galaxyPlayers[$sectorID][$accountID] = $player;
87
			}
88
		}
89
		return $galaxyPlayers;
90
	}
91
92
	public static function getSectorPlayers($gameID, $sectorID, $forceUpdate = false) {
93
		if ($forceUpdate || !isset(self::$CACHE_SECTOR_PLAYERS[$gameID][$sectorID])) {
94
			$db = new SmrMySqlDatabase();
95
			$db->query('SELECT * FROM player WHERE sector_id = ' . $db->escapeNumber($sectorID) . ' AND game_id=' . $db->escapeNumber($gameID) . ' AND land_on_planet = ' . $db->escapeBoolean(false) . ' AND (last_cpl_action > ' . $db->escapeNumber(TIME - TIME_BEFORE_INACTIVE) . ' OR newbie_turns = 0) AND account_id NOT IN (' . $db->escapeArray(Globals::getHiddenPlayers()) . ') ORDER BY last_cpl_action DESC');
96
			$players = array();
97
			while ($db->nextRecord()) {
98
				$accountID = $db->getInt('account_id');
99
				$players[$accountID] = self::getPlayer($accountID, $gameID, $forceUpdate, $db);
100
			}
101
			self::$CACHE_SECTOR_PLAYERS[$gameID][$sectorID] = $players;
102
		}
103
		return self::$CACHE_SECTOR_PLAYERS[$gameID][$sectorID];
104
	}
105
106
	public static function getPlanetPlayers($gameID, $sectorID, $forceUpdate = false) {
107
		if ($forceUpdate || !isset(self::$CACHE_PLANET_PLAYERS[$gameID][$sectorID])) {
108
			$db = new SmrMySqlDatabase();
109
			$db->query('SELECT * FROM player WHERE sector_id = ' . $db->escapeNumber($sectorID) . ' AND game_id=' . $db->escapeNumber($gameID) . ' AND land_on_planet = ' . $db->escapeBoolean(true) . ' AND account_id NOT IN (' . $db->escapeArray(Globals::getHiddenPlayers()) . ') ORDER BY last_cpl_action DESC');
110
			$players = array();
111
			while ($db->nextRecord()) {
112
				$accountID = $db->getInt('account_id');
113
				$players[$accountID] = self::getPlayer($accountID, $gameID, $forceUpdate, $db);
114
			}
115
			self::$CACHE_PLANET_PLAYERS[$gameID][$sectorID] = $players;
116
		}
117
		return self::$CACHE_PLANET_PLAYERS[$gameID][$sectorID];
118
	}
119
120
	public static function getAlliancePlayers($gameID, $allianceID, $forceUpdate = false) {
121
		if ($forceUpdate || !isset(self::$CACHE_ALLIANCE_PLAYERS[$gameID][$allianceID])) {
122
			$db = new SmrMySqlDatabase();
123
			$db->query('SELECT * FROM player WHERE alliance_id = ' . $db->escapeNumber($allianceID) . ' AND game_id=' . $db->escapeNumber($gameID) . ' ORDER BY experience DESC');
124
			$players = array();
125
			while ($db->nextRecord()) {
126
				$accountID = $db->getInt('account_id');
127
				$players[$accountID] = self::getPlayer($accountID, $gameID, $forceUpdate, $db);
128
			}
129
			self::$CACHE_ALLIANCE_PLAYERS[$gameID][$allianceID] = $players;
130
		}
131
		return self::$CACHE_ALLIANCE_PLAYERS[$gameID][$allianceID];
132
	}
133
134
	public static function getPlayer($accountID, $gameID, $forceUpdate = false, $db = null) {
135
		if ($forceUpdate || !isset(self::$CACHE_PLAYERS[$gameID][$accountID])) {
136
			self::$CACHE_PLAYERS[$gameID][$accountID] = new SmrPlayer($gameID, $accountID, $db);
137
		}
138
		return self::$CACHE_PLAYERS[$gameID][$accountID];
139
	}
140
141
	public static function getPlayerByPlayerID($playerID, $gameID, $forceUpdate = false) {
142
		$db = new SmrMySqlDatabase();
143
		$db->query('SELECT * FROM player WHERE game_id = ' . $db->escapeNumber($gameID) . ' AND player_id = ' . $db->escapeNumber($playerID) . ' LIMIT 1');
144
		if ($db->nextRecord()) {
145
			return self::getPlayer($db->getInt('account_id'), $gameID, $forceUpdate, $db);
146
		}
147
		throw new PlayerNotFoundException('Player ID not found.');
148
	}
149
150
	public static function getPlayerByPlayerName($playerName, $gameID, $forceUpdate = false) {
151
		$db = new SmrMySqlDatabase();
152
		$db->query('SELECT * FROM player WHERE game_id = ' . $db->escapeNumber($gameID) . ' AND player_name = ' . $db->escapeString($playerName) . ' LIMIT 1');
153
		if ($db->nextRecord()) {
154
			return self::getPlayer($db->getInt('account_id'), $gameID, $forceUpdate, $db);
155
		}
156
		throw new PlayerNotFoundException('Player Name not found.');
157
	}
158
159
	protected function __construct($gameID, $accountID, $db = null) {
160
		parent::__construct();
161
		$this->db = new SmrMySqlDatabase();
162
		$this->SQL = 'account_id = ' . $this->db->escapeNumber($accountID) . ' AND game_id = ' . $this->db->escapeNumber($gameID);
163
164
		if (isset($db)) {
165
			$playerExists = true;
166
		} else {
167
			$db = $this->db;
168
			$this->db->query('SELECT * FROM player WHERE ' . $this->SQL . ' LIMIT 1');
169
			$playerExists = $db->nextRecord();
170
		}
171
172
		if ($playerExists) {
173
			$this->accountID = (int)$accountID;
174
			$this->gameID = (int)$gameID;
175
			$this->playerName = $db->getField('player_name');
176
			$this->playerID = $db->getInt('player_id');
177
			$this->sectorID = $db->getInt('sector_id');
178
			$this->lastSectorID = $db->getInt('last_sector_id');
179
			$this->turns = $db->getInt('turns');
180
			$this->lastTurnUpdate = $db->getInt('last_turn_update');
181
			$this->newbieTurns = $db->getInt('newbie_turns');
182
			$this->lastNewsUpdate = $db->getInt('last_news_update');
183
			$this->attackColour = $db->getField('attack_warning');
184
			$this->dead = $db->getBoolean('dead');
185
			$this->npc = $db->getBoolean('npc');
186
			$this->newbieStatus = $db->getBoolean('newbie_status');
187
			$this->landedOnPlanet = $db->getBoolean('land_on_planet');
188
			$this->lastActive = $db->getInt('last_active');
189
			$this->lastCPLAction = $db->getInt('last_cpl_action');
190
			$this->raceID = $db->getInt('race_id');
191
			$this->credits = $db->getInt('credits');
192
			$this->experience = $db->getInt('experience');
193
			$this->alignment = $db->getInt('alignment');
194
			$this->militaryPayment = $db->getInt('military_payment');
195
			$this->allianceID = $db->getInt('alliance_id');
196
			$this->allianceJoinable = $db->getInt('alliance_join');
197
			$this->shipID = $db->getInt('ship_type_id');
198
			$this->kills = $db->getInt('kills');
199
			$this->deaths = $db->getInt('deaths');
200
			$this->assists = $db->getInt('assists');
201
			$this->lastPort = $db->getInt('last_port');
202
			$this->bank = $db->getInt('bank');
203
			$this->zoom = $db->getInt('zoom');
204
			$this->displayMissions = $db->getBoolean('display_missions');
205
			$this->displayWeapons = $db->getBoolean('display_weapons');
206
			$this->forceDropMessages = $db->getBoolean('force_drop_messages');
0 ignored issues
show
Bug Best Practice introduced by
The property forceDropMessages does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
207
			$this->groupScoutMessages = $db->getField('group_scout_messages');
0 ignored issues
show
Bug Best Practice introduced by
The property groupScoutMessages does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
208
			$this->ignoreGlobals = $db->getBoolean('ignore_globals');
209
			$this->newbieWarning = $db->getBoolean('newbie_warning');
210
			$this->nameChanged = $db->getBoolean('name_changed');
211
			$this->combatDronesKamikazeOnMines = $db->getBoolean('combat_drones_kamikaze_on_mines');
212
		} else {
213
			throw new PlayerNotFoundException('Invalid accountID: ' . $accountID . ' OR gameID:' . $gameID);
214
		}
215
	}
216
217
	/**
218
	 * Insert a new player into the database. Returns the new player object.
219
	 */
220
	public static function createPlayer($accountID, $gameID, $playerName, $raceID, $isNewbie, $npc=false) {
221
		// Put the player in a sector with an HQ
222
		$startSectorID = self::getHome($gameID, $raceID);
223
224
		$db = new SmrMySqlDatabase();
225
		$db->lockTable('player');
226
227
		// Escape html elements so the name displays correctly
228
		$playerName = htmlentities($playerName);
229
230
		// Player names must be unique within each game
231
		$db->query('SELECT 1 FROM player WHERE game_id = ' . $db->escapeNumber($gameID) . ' AND player_name = ' . $db->escapeString($playerName) . ' LIMIT 1');
232
		if ($db->nextRecord() > 0) {
233
			$db->unlock();
234
			create_error('The player name already exists.');
235
		}
236
237
		// get last registered player id in that game and increase by one.
238
		$db->query('SELECT MAX(player_id) FROM player WHERE game_id = ' . $db->escapeNumber($gameID));
239
		if ($db->nextRecord()) {
240
			$playerID = $db->getInt('MAX(player_id)') + 1;
241
		} else {
242
			$playerID = 1;
243
		}
244
245
		$db->query('INSERT INTO player (account_id, game_id, player_id, player_name, race_id, sector_id, last_cpl_action, last_active, npc, newbie_status)
246
					VALUES(' . $db->escapeNumber($accountID) . ', ' . $db->escapeNumber($gameID) . ', ' . $db->escapeNumber($playerID) . ', ' . $db->escapeString($playerName) . ', ' . $db->escapeNumber($raceID) . ', ' . $db->escapeNumber($startSectorID) . ', ' . $db->escapeNumber(TIME) . ', ' . $db->escapeNumber(TIME) . ',' . $db->escapeBoolean($npc) . ',' . $db->escapeBoolean($isNewbie) . ')');
247
248
		$db->unlock();
249
250
		return SmrPlayer::getPlayer($accountID, $gameID);
251
	}
252
253
	// Get array of players whose info can be accessed by this player.
254
	// Skips players who are not in the same alliance as this player.
255
	public function getSharingPlayers($forceUpdate = false) {
256
		$results = array($this);
257
258
		// Only return this player if not in an alliance
259
		if (!$this->hasAlliance()) {
260
			return $results;
261
		}
262
263
		// Get other players who are sharing info for this game.
264
		// NOTE: game_id=0 means that player shares info for all games.
265
		$this->db->query('SELECT from_account_id FROM account_shares_info WHERE to_account_id=' . $this->db->escapeNumber($this->getAccountID()) . ' AND (game_id=0 OR game_id=' . $this->db->escapeNumber($this->getGameID()) . ')');
266
		while ($this->db->nextRecord()) {
267
			try {
268
				$otherPlayer = SmrPlayer::getPlayer($this->db->getInt('from_account_id'),
269
				                                    $this->getGameID(), $forceUpdate);
270
			} catch (PlayerNotFoundException $e) {
271
				// Skip players that have not joined this game
272
				continue;
273
			}
274
275
			// players must be in the same alliance
276
			if ($this->sameAlliance($otherPlayer)) {
277
				$results[] = $otherPlayer;
278
			}
279
		}
280
		return $results;
281
	}
282
283
	public function getShip($forceUpdate = false) {
284
		return SmrShip::getShip($this, $forceUpdate);
285
	}
286
287
	public function getAccount() {
288
		return SmrAccount::getAccount($this->getAccountID());
289
	}
290
291
	public function getZoom() {
292
		return $this->zoom;
293
	}
294
295
	protected function setZoom($zoom) {
296
		// Set the zoom level between [1, 9]
297
		$zoom = max(1, min(9, $zoom));
298
		if ($this->zoom == $zoom) {
299
			return;
300
		}
301
		$this->zoom = $zoom;
302
		$this->hasChanged = true;
303
//		$this->db->query('UPDATE player SET zoom = ' . $zoom . ' WHERE ' . $this->SQL . ' LIMIT 1');
304
	}
305
306
	public function increaseZoom($zoom) {
307
		if ($zoom < 0) {
308
			throw new Exception('Trying to increase negative zoom.');
309
		}
310
		$this->setZoom($this->getZoom() + $zoom);
311
	}
312
313
	public function decreaseZoom($zoom) {
314
		if ($zoom < 0) {
315
			throw new Exception('Trying to decrease negative zoom.');
316
		}
317
		$this->setZoom($this->getZoom() - $zoom);
318
	}
319
320
	public function setSectorID($sectorID) {
321
		$port = SmrPort::getPort($this->getGameID(), $this->getSectorID());
322
		$port->addCachePort($this->getAccountID()); //Add port of sector we were just in, to make sure it is left totally up to date.
323
324
		parent::setSectorID($sectorID);
325
326
		$port = SmrPort::getPort($this->getGameID(), $sectorID);
327
		$port->addCachePort($this->getAccountID()); //Add the port of sector we are now in.
328
	}
329
330
	public function setLastSectorID($lastSectorID) {
331
		if ($this->lastSectorID == $lastSectorID) {
332
			return;
333
		}
334
		$this->lastSectorID = $lastSectorID;
335
		$this->hasChanged = true;
336
//		$this->db->query('UPDATE player SET last_sector_id = '.$this->lastSectorID.' WHERE '.$this->SQL.' LIMIT 1');
337
	}
338
339
	public function leaveAlliance(AbstractSmrPlayer $kickedBy = null) {
340
		$allianceID = $this->getAllianceID();
341
		$alliance = $this->getAlliance();
342
		if ($kickedBy != null) {
343
			$kickedBy->sendMessage($this->getAccountID(), MSG_PLAYER, 'You were kicked out of the alliance!', false);
0 ignored issues
show
Bug introduced by
The method sendMessage() does not exist on AbstractSmrPlayer. It seems like you code against a sub-type of AbstractSmrPlayer such as SmrPlayer. ( Ignorable by Annotation )

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

343
			$kickedBy->/** @scrutinizer ignore-call */ 
344
              sendMessage($this->getAccountID(), MSG_PLAYER, 'You were kicked out of the alliance!', false);
Loading history...
344
			$this->actionTaken('PlayerKicked', array('Alliance' => $alliance, 'Player' => $kickedBy));
345
			$kickedBy->actionTaken('KickPlayer', array('Alliance' => $alliance, 'Player' => $this));
346
		} elseif ($this->isAllianceLeader()) {
347
			$this->actionTaken('DisbandAlliance', array('Alliance' => $alliance));
348
		} else {
349
			$this->actionTaken('LeaveAlliance', array('Alliance' => $alliance));
350
			if ($alliance->getLeaderID() != 0 && $alliance->getLeaderID() != ACCOUNT_ID_NHL) {
351
				$this->sendMessage($alliance->getLeaderID(), MSG_PLAYER, 'I left your alliance!', false);
352
			}
353
		}
354
355
		$this->setAllianceID(0);
356
		$this->db->query('DELETE FROM player_has_alliance_role WHERE ' . $this->SQL);
357
358
		if (!$this->isAllianceLeader() && $allianceID != NHA_ID) { // Don't have a delay for switching alliance after leaving NHA, or for disbanding an alliance.
359
			$this->setAllianceJoinable(TIME + self::TIME_FOR_ALLIANCE_SWITCH);
360
			$alliance->getLeader()->setAllianceJoinable(TIME + self::TIME_FOR_ALLIANCE_SWITCH); //We set the joinable time for leader here, that way a single player alliance won't cause a player to wait before switching.
361
		}
362
	}
363
364
	/**
365
	 * Join an alliance (used for both Leader and New Member roles)
366
	 */
367
	public function joinAlliance($allianceID) {
368
		$this->setAllianceID($allianceID);
369
		$alliance = $this->getAlliance();
370
371
		if (!$this->isAllianceLeader()) {
372
			// Do not throw an exception if the NHL account doesn't exist.
373
			try {
374
				$this->sendMessage($alliance->getLeaderID(), MSG_PLAYER, 'I joined your alliance!', false);
375
			} catch (AccountNotFoundException $e) {
376
				if ($alliance->getLeaderID() != ACCOUNT_ID_NHL) {
377
					throw $e;
378
				}
379
			}
380
381
			$roleID = ALLIANCE_ROLE_NEW_MEMBER;
382
		} else {
383
			$roleID = ALLIANCE_ROLE_LEADER;
384
		}
385
		$this->db->query('INSERT INTO player_has_alliance_role (game_id, account_id, role_id, alliance_id) VALUES (' . $this->db->escapeNumber($this->getGameID()) . ', ' . $this->db->escapeNumber($this->getAccountID()) . ', ' . $this->db->escapeNumber($roleID) . ',' . $this->db->escapeNumber($this->getAllianceID()) . ')');
386
387
		$this->actionTaken('JoinAlliance', array('Alliance' => $alliance));
388
	}
389
390
	public function getAllianceJoinable() {
391
		return $this->allianceJoinable;
392
	}
393
394
	private function setAllianceJoinable($time) {
395
		if ($this->allianceJoinable == $time) {
396
			return;
397
		}
398
		$this->allianceJoinable = $time;
399
		$this->hasChanged = true;
400
	}
401
402
	/**
403
	 * Invites player with $accountID to this player's alliance.
404
	 */
405
	public function sendAllianceInvitation(int $accountID, string $message, int $expires) : void {
406
		if (!$this->hasAlliance()) {
407
			throw new Exception('Must be in an alliance to send alliance invitations');
408
		}
409
		// Send message to invited player
410
		$messageID = $this->sendMessage($accountID, MSG_PLAYER, $message, false, true, $expires, true);
411
		SmrInvitation::send($this->getAllianceID(), $this->getGameID(), $accountID, $this->getAccountID(), $messageID, $expires);
412
	}
413
414
	public function getAttackColour() {
415
		return $this->attackColour;
416
	}
417
418
	public function setAttackColour($colour) {
419
		if ($this->attackColour == $colour) {
420
			return;
421
		}
422
		$this->attackColour = $colour;
423
		$this->hasChanged = true;
424
//		$this->db->query('UPDATE player SET attack_warning = ' . $this->db->escapeString($this->attackColour) . ' WHERE ' . $this->SQL . ' LIMIT 1');
425
	}
426
427
	public function getBank() {
428
		return $this->bank;
429
	}
430
431
	public function increaseBank($credits) {
432
		if ($credits < 0) {
433
			throw new Exception('Trying to increase negative credits.');
434
		}
435
		if ($credits == 0) {
436
			return;
437
		}
438
		$credits += $this->bank;
439
		$this->setBank($credits);
440
	}
441
	public function decreaseBank($credits) {
442
		if ($credits < 0) {
443
			throw new Exception('Trying to decrease negative credits.');
444
		}
445
		if ($credits == 0) {
446
			return;
447
		}
448
		$credits = $this->bank - $credits;
449
		$this->setBank($credits);
450
	}
451
	public function setBank($credits) {
452
		if ($this->bank == $credits) {
453
			return;
454
		}
455
		if ($credits < 0) {
456
			throw new Exception('Trying to set negative credits.');
457
		}
458
		if ($credits > MAX_MONEY) {
459
			throw new Exception('Trying to set more than max credits.');
460
		}
461
		$this->bank = $credits;
462
		$this->hasChanged = true;
463
//		$this->db->query('UPDATE player SET bank = '.$this->bank.' WHERE '.$this->SQL.' LIMIT 1');
464
	}
465
466
	public function getLastNewsUpdate() {
467
		return $this->lastNewsUpdate;
468
	}
469
470
	private function setLastNewsUpdate($time) {
471
		if ($this->lastNewsUpdate == $time) {
472
			return;
473
		}
474
		$this->lastNewsUpdate = $time;
475
		$this->hasChanged = true;
476
//		$this->db->query('UPDATE player SET last_news_update = ' . $time . ' WHERE ' . $this->SQL . ' LIMIT 1');
477
	}
478
479
	public function updateLastNewsUpdate() {
480
		$this->setLastNewsUpdate(TIME);
481
	}
482
483
//	function getPastKnowledge() {
484
//		return $this->pastKnowledge;
485
//	}
486
487
	/**
488
	 * Calculate the time in seconds between the given time and when the
489
	 * player will be at max turns.
490
	 */
491
	public function getTimeUntilMaxTurns($time, $forceUpdate = false) {
492
		$timeDiff = $time - $this->getLastTurnUpdate();
493
		$turnsDiff = $this->getMaxTurns() - $this->getTurns();
494
		$ship = $this->getShip($forceUpdate);
495
		$maxTurnsTime = ICeil(($turnsDiff * 3600 / $ship->getRealSpeed())) - $timeDiff;
496
		// If already at max turns, return 0
497
		return max(0, $maxTurnsTime);
498
	}
499
500
	/**
501
	 * Grant the player their starting turns.
502
	 */
503
	public function giveStartingTurns() {
504
		$startTurns = IFloor($this->getShip()->getRealSpeed() * $this->getGame()->getStartTurnHours());
505
		$this->giveTurns($startTurns);
506
		$this->setLastTurnUpdate($this->getGame()->getStartTime());
507
	}
508
509
	// Turns only update when player is active.
510
	// Calculate turns gained between given time and the last turn update
511
	public function getTurnsGained($time, $forceUpdate = false) : int {
512
		$timeDiff = $time - $this->getLastTurnUpdate();
513
		$ship = $this->getShip($forceUpdate);
514
		$extraTurns = IFloor($timeDiff * $ship->getRealSpeed() / 3600);
515
		return $extraTurns;
516
	}
517
518
	public function updateTurns() {
519
		// is account validated?
520
		if (!$this->getAccount()->isValidated()) {
521
			return;
522
		}
523
524
		// how many turns would he get right now?
525
		$extraTurns = $this->getTurnsGained(TIME);
526
527
		// do we have at least one turn to give?
528
		if ($extraTurns > 0) {
529
			// recalc the time to avoid rounding errors
530
			$newLastTurnUpdate = $this->getLastTurnUpdate() + ICeil($extraTurns * 3600 / $this->getShip()->getRealSpeed());
531
			$this->setLastTurnUpdate($newLastTurnUpdate);
532
			$this->giveTurns($extraTurns);
533
		}
534
	}
535
536
	public function isIgnoreGlobals() {
537
		return $this->ignoreGlobals;
538
	}
539
540
	public function setIgnoreGlobals($bool) {
541
		if ($this->ignoreGlobals == $bool) {
542
			return;
543
		}
544
		$this->ignoreGlobals = $bool;
545
		$this->hasChanged = true;
546
//		$this->db->query('UPDATE player SET ignore_globals = '.$this->db->escapeBoolean($bool).' WHERE '.$this->SQL.' LIMIT 1');
547
	}
548
549
550
	public function getLastPort() {
551
		return $this->lastPort;
552
	}
553
554
	public function setLastPort($lastPort) {
555
		if ($this->lastPort == $lastPort) {
556
			return;
557
		}
558
		$this->lastPort = $lastPort;
559
		$this->hasChanged = true;
560
//		$this->db->query('UPDATE player SET last_port = ' . $this->lastPort . ' WHERE ' . $this->SQL . ' LIMIT 1');
561
	}
562
563
	public function isDisplayMissions() {
564
		return $this->displayMissions;
565
	}
566
567
	public function setDisplayMissions($bool) {
568
		if ($this->displayMissions == $bool) {
569
			return;
570
		}
571
		$this->displayMissions = $bool;
572
		$this->hasChanged = true;
573
	}
574
575
	public function isDisplayWeapons() {
576
		return $this->displayWeapons;
577
	}
578
579
	/**
580
	 * Should weapons be displayed in the right panel?
581
	 * This updates the player database directly because it is used with AJAX,
582
	 * which does not acquire a sector lock.
583
	 */
584
	public function setDisplayWeapons($bool) {
585
		if ($this->displayWeapons == $bool) {
586
			return;
587
		}
588
		$this->displayWeapons = $bool;
589
		$this->db->query('UPDATE player SET display_weapons=' . $this->db->escapeBoolean($this->displayWeapons) . ' WHERE ' . $this->SQL);
590
	}
591
592
	public function isForceDropMessages() {
593
		return $this->forceDropMessages;
594
	}
595
596
	public function setForceDropMessages($bool) {
597
		if ($this->forceDropMessages == $bool) {
598
			return;
599
		}
600
		$this->forceDropMessages = $bool;
0 ignored issues
show
Bug Best Practice introduced by
The property forceDropMessages does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
601
		$this->hasChanged = true;
602
	}
603
604
	public function getScoutMessageGroupLimit() {
605
		if ($this->groupScoutMessages == 'ALWAYS') {
606
			return 0;
607
		} elseif ($this->groupScoutMessages == 'AUTO') {
608
			return MESSAGES_PER_PAGE;
609
		} elseif ($this->groupScoutMessages == 'NEVER') {
610
			return PHP_INT_MAX;
611
		}
612
	}
613
614
	public function getGroupScoutMessages() {
615
		return $this->groupScoutMessages;
616
	}
617
618
	public function setGroupScoutMessages($setting) {
619
		if ($this->groupScoutMessages == $setting) {
620
			return;
621
		}
622
		$this->groupScoutMessages = $setting;
0 ignored issues
show
Bug Best Practice introduced by
The property groupScoutMessages does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
623
		$this->hasChanged = true;
624
	}
625
626
	public function getLastTurnUpdate() {
627
		return $this->lastTurnUpdate;
628
	}
629
630
	public function setLastTurnUpdate($time) {
631
		if ($this->lastTurnUpdate == $time) {
632
			return;
633
		}
634
		$this->lastTurnUpdate = $time;
635
		$this->hasChanged = true;
636
//		$sql = $this->db->query('UPDATE player SET last_turn_update = ' . $this->lastTurnUpdate . ' WHERE '. $this->SQL . ' LIMIT 1');
637
	}
638
639
	protected function getPureRelationsData() {
640
		if (!isset($this->pureRelations)) {
641
			//get relations
642
			$RACES = Globals::getRaces();
643
			$this->pureRelations = array();
644
			foreach ($RACES as $raceID => $raceName) {
645
				$this->pureRelations[$raceID] = 0;
646
			}
647
			$this->db->query('SELECT race_id,relation FROM player_has_relation WHERE ' . $this->SQL . ' LIMIT ' . count($RACES));
648
			while ($this->db->nextRecord()) {
649
				$this->pureRelations[$this->db->getInt('race_id')] = $this->db->getInt('relation');
650
			}
651
		}
652
	}
653
654
	/**
655
	 * Increases personal relations from trading $numGoods units with the race
656
	 * of the port given by $raceID.
657
	 */
658
	public function increaseRelationsByTrade($numGoods, $raceID) {
659
		$relations = ICeil(min($numGoods, 300) / 30);
660
		//Cap relations to a max of 1 after 500 have been reached
661
		if ($this->getPureRelation($raceID) + $relations >= 500) {
662
			$relations = max(1, min($relations, 500 - $this->getPureRelation($raceID)));
663
		}
664
		$this->increaseRelations($relations, $raceID);
665
	}
666
667
	public function decreaseRelationsByTrade($numGoods, $raceID) {
668
		$relations = ICeil(min($numGoods, 300) / 30);
669
		$this->decreaseRelations($relations, $raceID);
670
	}
671
672
	public function increaseRelations($relations, $raceID) {
673
		if ($relations < 0) {
674
			throw new Exception('Trying to increase negative relations.');
675
		}
676
		if ($relations == 0) {
677
			return;
678
		}
679
		$relations += $this->getPureRelation($raceID);
680
		$this->setRelations($relations, $raceID);
681
	}
682
	public function decreaseRelations($relations, $raceID) {
683
		if ($relations < 0) {
684
			throw new Exception('Trying to decrease negative relations.');
685
		}
686
		if ($relations == 0) {
687
			return;
688
		}
689
		$relations = $this->getPureRelation($raceID) - $relations;
690
		$this->setRelations($relations, $raceID);
691
	}
692
	public function setRelations($relations, $raceID) {
693
		$this->getRelations();
694
		if ($this->pureRelations[$raceID] == $relations) {
695
			return;
696
		}
697
		if ($relations < MIN_RELATIONS) {
698
			$relations = MIN_RELATIONS;
699
		}
700
		$relationsDiff = IRound($relations - $this->pureRelations[$raceID]);
701
		$this->pureRelations[$raceID] = $relations;
702
		$this->relations[$raceID] += $relationsDiff;
703
		$this->db->query('REPLACE INTO player_has_relation (account_id,game_id,race_id,relation) values (' . $this->db->escapeNumber($this->getAccountID()) . ',' . $this->db->escapeNumber($this->getGameID()) . ',' . $this->db->escapeNumber($raceID) . ',' . $this->db->escapeNumber($this->pureRelations[$raceID]) . ')');
704
	}
705
706
	/**
707
	 * Use this method when the player is changing their own name.
708
	 * This will flag the player as having used their free name change.
709
	 */
710
	public function setPlayerNameByPlayer($playerName) {
711
		$this->playerName = $playerName;
712
		$this->setNameChanged(true);
713
		$this->hasChanged = true;
714
	}
715
716
	public function isNameChanged() {
717
		return $this->nameChanged;
718
	}
719
720
	public function setNameChanged($bool) {
721
		$this->nameChanged = $bool;
722
		$this->hasChanged = true;
723
	}
724
725
	public function hasCustomShipName() {
726
		return $this->getCustomShipName() !== false;
727
	}
728
729
	public function getCustomShipName() {
730
		if (!isset($this->customShipName)) {
731
			$this->db->query('SELECT * FROM ship_has_name WHERE ' . $this->SQL . ' LIMIT 1');
732
			if ($this->db->nextRecord()) {
733
				$this->customShipName = $this->db->getField('ship_name');
734
			} else {
735
				$this->customShipName = false;
736
			}
737
		}
738
		return $this->customShipName;
739
	}
740
741
	public function setCustomShipName(string $name) {
742
		$this->db->query('REPLACE INTO ship_has_name (game_id, account_id, ship_name)
743
			VALUES (' . $this->db->escapeNumber($this->getGameID()) . ', ' . $this->db->escapeNumber($this->getAccountID()) . ', ' . $this->db->escapeString($name) . ')');
744
	}
745
746
	public function getKnowledge($knowledgeType = false) {
747
		if (!isset($this->knowledge)) {
748
			//get players faction knowledge
749
			$this->db->query('SELECT * FROM player_knows_faction WHERE ' . $this->SQL . ' LIMIT 1');
750
			if ($this->db->nextRecord()) {
751
				$this->knowledge['Erebus'] = $this->db->getInt('erebus');
0 ignored issues
show
Bug Best Practice introduced by
The property knowledge does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
752
				$this->knowledge['Aether'] = $this->db->getInt('aether');
753
				$this->knowledge['Tartarus'] = $this->db->getInt('tartarus');
754
				$this->knowledge['Nyx'] = $this->db->getInt('nyx');
755
				$this->knowledge['Federation'] = 0;
756
				$this->knowledge['Underground'] = 0;
757
			} else {
758
				$this->knowledge['Erebus'] = 0;
759
				$this->knowledge['Aether'] = 0;
760
				$this->knowledge['Tartarus'] = 0;
761
				$this->knowledge['Nyx'] = 0;
762
				$this->knowledge['Federation'] = 0;
763
				$this->knowledge['Underground'] = 0;
764
			}
765
		}
766
		if ($knowledgeType === false) {
767
			return $this->knowledge;
768
		}
769
		if (isset($this->knowledge[$knowledgeType])) {
770
			return $this->knowledge[$knowledgeType];
771
		}
772
		return false;
773
	}
774
775
	public function killPlayer($sectorID) {
776
		$sector = SmrSector::getSector($this->getGameID(), $sectorID);
777
		//msg taken care of in trader_att_proc.php
778
		// forget plotted course
779
		$this->deletePlottedCourse();
780
781
		$sector->diedHere($this);
782
783
		// if we are in an alliance we increase their deaths
784
		if ($this->hasAlliance()) {
785
			$this->db->query('UPDATE alliance SET alliance_deaths = alliance_deaths + 1
786
							WHERE game_id = ' . $this->db->escapeNumber($this->getGameID()) . ' AND alliance_id = ' . $this->db->escapeNumber($this->getAllianceID()) . ' LIMIT 1');
787
		}
788
789
		// record death stat
790
		$this->increaseHOF(1, array('Dying', 'Deaths'), HOF_PUBLIC);
791
		//record cost of ship lost
792
		$this->increaseHOF($this->getShip()->getCost(), array('Dying', 'Money', 'Cost Of Ships Lost'), HOF_PUBLIC);
793
		// reset turns since last death
794
		$this->setHOF(0, array('Movement', 'Turns Used', 'Since Last Death'), HOF_ALLIANCE);
795
796
		// 1/4 of ship value -> insurance
797
		$newCredits = IRound($this->getShip()->getCost() / 4);
798
		$old_speed = $this->getShip()->getSpeed();
799
800
		if ($newCredits < 100000) {
801
			$newCredits = 100000;
802
		}
803
		$this->setCredits($newCredits);
804
805
		$this->setSectorID($this::getHome($this->getGameID(), $this->getRaceID()));
806
		$this->increaseDeaths(1);
807
		$this->setLandedOnPlanet(false);
808
		$this->setDead(true);
809
		$this->setNewbieWarning(true);
810
		$this->getShip()->getPod($this->hasNewbieStatus());
811
812
		// Update turns due to ship change
813
		$new_speed = $this->getShip()->getSpeed();
814
		$this->setTurns(IRound($this->turns / $old_speed * $new_speed));
815
		$this->setNewbieTurns(100);
816
	}
817
818
	static public function getHome($gameID, $raceID) {
819
		// get his home sector
820
		$hq_id = GOVERNMENT + $raceID;
821
		$raceHqSectors = SmrSector::getLocationSectors($gameID, $hq_id);
822
		if (!empty($raceHqSectors)) {
823
			// If race has multiple HQ's for some reason, use the first one
824
			return key($raceHqSectors);
825
		} else {
826
			return 1;
827
		}
828
	}
829
830
	public function incrementAllianceVsKills($otherID) {
831
		$values = [$this->getGameID(), $this->getAllianceID(), $otherID, 1];
832
		$this->db->query('INSERT INTO alliance_vs_alliance (game_id, alliance_id_1, alliance_id_2, kills) VALUES (' . $this->db->escapeArray($values) . ') ON DUPLICATE KEY UPDATE kills = kills + 1');
833
	}
834
835
	public function incrementAllianceVsDeaths($otherID) {
836
		$values = [$this->getGameID(), $otherID, $this->getAllianceID(), 1];
837
		$this->db->query('INSERT INTO alliance_vs_alliance (game_id, alliance_id_1, alliance_id_2, kills) VALUES (' . $this->db->escapeArray($values) . ') ON DUPLICATE KEY UPDATE kills = kills + 1');
838
	}
839
840
	public function &killPlayerByPlayer(AbstractSmrPlayer $killer) {
841
		$return = array();
842
		$msg = $this->getBBLink();
843
844
		if ($this->hasCustomShipName()) {
845
			$named_ship = strip_tags($this->getCustomShipName(), '<font><span><img>');
846
			$msg .= ' flying <span class="yellow">' . $named_ship . '</span>';
847
		}
848
		$msg .= ' was destroyed by ' . $killer->getBBLink();
849
		if ($killer->hasCustomShipName()) {
0 ignored issues
show
Bug introduced by
The method hasCustomShipName() does not exist on AbstractSmrPlayer. It seems like you code against a sub-type of AbstractSmrPlayer such as SmrPlayer. ( Ignorable by Annotation )

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

849
		if ($killer->/** @scrutinizer ignore-call */ hasCustomShipName()) {
Loading history...
850
			$named_ship = strip_tags($killer->getCustomShipName(), '<font><span><img>');
0 ignored issues
show
Bug introduced by
The method getCustomShipName() does not exist on AbstractSmrPlayer. It seems like you code against a sub-type of AbstractSmrPlayer such as SmrPlayer. ( Ignorable by Annotation )

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

850
			$named_ship = strip_tags($killer->/** @scrutinizer ignore-call */ getCustomShipName(), '<font><span><img>');
Loading history...
851
			$msg .= ' flying <span class="yellow">' . $named_ship . '</span>';
852
		}
853
		$msg .= ' in Sector&nbsp;' . Globals::getSectorBBLink($this->getSectorID());
854
		$this->getSector()->increaseBattles(1);
855
		$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($msg, true) . ',\'regular\',' . $this->db->escapeNumber($killer->getAccountID()) . ',' . $this->db->escapeNumber($killer->getAllianceID()) . ',' . $this->db->escapeNumber($this->getAccountID()) . ',' . $this->db->escapeNumber($this->getAllianceID()) . ')');
856
857
		self::sendMessageFromFedClerk($this->getGameID(), $this->getAccountID(), 'You were <span class="red">DESTROYED</span> by ' . $killer->getBBLink() . ' in sector ' . Globals::getSectorBBLink($this->getSectorID()));
858
		self::sendMessageFromFedClerk($this->getGameID(), $killer->getAccountID(), 'You <span class="red">DESTROYED</span>&nbsp;' . $this->getBBLink() . ' in sector ' . Globals::getSectorBBLink($this->getSectorID()));
859
860
		// Dead player loses between 5% and 25% experience
861
		$expLossPercentage = 0.15 + 0.10 * ($this->getLevelID() - $killer->getLevelID()) / $this->getMaxLevel();
862
		$return['DeadExp'] = max(0, IFloor($this->getExperience() * $expLossPercentage));
863
		$this->decreaseExperience($return['DeadExp']);
864
865
		// Killer gains 50% of the lost exp
866
		$return['KillerExp'] = max(0, ICeil(0.5 * $return['DeadExp']));
867
		$killer->increaseExperience($return['KillerExp']);
868
869
		$return['KillerCredits'] = $this->getCredits();
870
		$killer->increaseCredits($return['KillerCredits']);
871
872
		// The killer may change alignment
873
		$relations = Globals::getRaceRelations($this->getGameID(), $this->getRaceID());
874
		$relation = $relations[$killer->getRaceID()];
875
876
		$alignChangePerRelation = 0.1;
877
		if ($relation >= RELATIONS_PEACE || $relation <= RELATIONS_WAR) {
878
			$alignChangePerRelation = 0.04;
879
		}
880
881
		$return['KillerAlign'] = -$relation * $alignChangePerRelation; //Lose relations when killing a peaceful race
882
		if ($return['KillerAlign'] > 0) {
883
			$killer->increaseAlignment($return['KillerAlign']);
884
		} else {
885
			$killer->decreaseAlignment(-$return['KillerAlign']);
886
		}
887
		// War setting gives them military pay
888
		if ($relation <= RELATIONS_WAR) {
889
			$killer->increaseMilitaryPayment(-IFloor($relation * 100 * pow($return['KillerExp'] / 2, 0.25)));
890
		}
891
892
		//check for federal bounty being offered for current port raiders;
893
		$this->db->query('DELETE FROM player_attacks_port WHERE time < ' . $this->db->escapeNumber(TIME - self::TIME_FOR_FEDERAL_BOUNTY_ON_PR));
894
		$query = 'SELECT 1
895
					FROM player_attacks_port
896
					JOIN port USING(game_id, sector_id)
897
					JOIN player USING(game_id, account_id)
898
					WHERE armour > 0 AND ' . $this->SQL . ' LIMIT 1';
899
		$this->db->query($query);
900
		if ($this->db->nextRecord()) {
901
			$bounty = IFloor(DEFEND_PORT_BOUNTY_PER_LEVEL * $this->getLevelID());
902
			$this->increaseCurrentBountyAmount('HQ', $bounty);
903
		}
904
905
		// Killer get marked as claimer of podded player's bounties even if they don't exist
906
		$this->setBountiesClaimable($killer);
907
908
		// If the alignment difference is greater than 200 then a bounty may be set
909
		$alignmentDiff = abs($this->getAlignment() - $killer->getAlignment());
910
		$return['BountyGained'] = array(
911
			'Type' => 'None',
912
			'Amount' => 0
913
		);
914
		if ($alignmentDiff >= 200) {
915
			// If the podded players alignment makes them deputy or member then set bounty
916
			if ($this->getAlignment() >= 100) {
917
				$return['BountyGained']['Type'] = 'HQ';
918
			} elseif ($this->getAlignment() <= 100) {
919
				$return['BountyGained']['Type'] = 'UG';
920
			}
921
922
			if ($return['BountyGained']['Type'] != 'None') {
923
				$return['BountyGained']['Amount'] = IFloor(pow($alignmentDiff, 2.56));
924
				$killer->increaseCurrentBountyAmount($return['BountyGained']['Type'], $return['BountyGained']['Amount']);
925
			}
926
		}
927
928
		if ($this->isNPC()) {
929
			$killer->increaseHOF($return['KillerExp'], array('Killing', 'NPC', 'Experience', 'Gained'), HOF_PUBLIC);
930
			$killer->increaseHOF($this->getExperience(), array('Killing', 'NPC', 'Experience', 'Of Traders Killed'), HOF_PUBLIC);
931
932
			$killer->increaseHOF($return['DeadExp'], array('Killing', 'Experience', 'Lost By NPCs Killed'), HOF_PUBLIC);
933
934
			$killer->increaseHOF($return['KillerCredits'], array('Killing', 'NPC', 'Money', 'Lost By Traders Killed'), HOF_PUBLIC);
935
			$killer->increaseHOF($return['KillerCredits'], array('Killing', 'NPC', 'Money', 'Gain'), HOF_PUBLIC);
936
			$killer->increaseHOF($this->getShip()->getCost(), array('Killing', 'NPC', 'Money', 'Cost Of Ships Killed'), HOF_PUBLIC);
937
938
			if ($return['KillerAlign'] > 0) {
939
				$killer->increaseHOF($return['KillerAlign'], array('Killing', 'NPC', 'Alignment', 'Gain'), HOF_PUBLIC);
940
			} else {
941
				$killer->increaseHOF(-$return['KillerAlign'], array('Killing', 'NPC', 'Alignment', 'Loss'), HOF_PUBLIC);
942
			}
943
944
			$killer->increaseHOF($return['BountyGained']['Amount'], array('Killing', 'NPC', 'Money', 'Bounty Gained'), HOF_PUBLIC);
945
946
			$killer->increaseHOF(1, array('Killing', 'NPC Kills'), HOF_PUBLIC);
947
		} else {
948
			$killer->increaseHOF($return['KillerExp'], array('Killing', 'Experience', 'Gained'), HOF_PUBLIC);
949
			$killer->increaseHOF($this->getExperience(), array('Killing', 'Experience', 'Of Traders Killed'), HOF_PUBLIC);
950
951
			$killer->increaseHOF($return['DeadExp'], array('Killing', 'Experience', 'Lost By Traders Killed'), HOF_PUBLIC);
952
953
			$killer->increaseHOF($return['KillerCredits'], array('Killing', 'Money', 'Lost By Traders Killed'), HOF_PUBLIC);
954
			$killer->increaseHOF($return['KillerCredits'], array('Killing', 'Money', 'Gain'), HOF_PUBLIC);
955
			$killer->increaseHOF($this->getShip()->getCost(), array('Killing', 'Money', 'Cost Of Ships Killed'), HOF_PUBLIC);
956
957
			if ($return['KillerAlign'] > 0) {
958
				$killer->increaseHOF($return['KillerAlign'], array('Killing', 'Alignment', 'Gain'), HOF_PUBLIC);
959
			} else {
960
				$killer->increaseHOF(-$return['KillerAlign'], array('Killing', 'Alignment', 'Loss'), HOF_PUBLIC);
961
			}
962
963
			$killer->increaseHOF($return['BountyGained']['Amount'], array('Killing', 'Money', 'Bounty Gained'), HOF_PUBLIC);
964
965
			if ($this->getShip()->getAttackRatingWithMaxCDs() <= MAX_ATTACK_RATING_NEWBIE && $this->hasNewbieStatus() && !$killer->hasNewbieStatus()) { //Newbie kill
966
				$killer->increaseHOF(1, array('Killing', 'Newbie Kills'), HOF_PUBLIC);
967
			} else {
968
				$killer->increaseKills(1);
969
				$killer->increaseHOF(1, array('Killing', 'Kills'), HOF_PUBLIC);
970
971
				if ($killer->hasAlliance()) {
972
					$this->db->query('UPDATE alliance SET alliance_kills=alliance_kills+1 WHERE alliance_id=' . $this->db->escapeNumber($killer->getAllianceID()) . ' AND game_id=' . $this->db->escapeNumber($killer->getGameID()) . ' LIMIT 1');
973
				}
974
975
				// alliance vs. alliance stats
976
				$this->incrementAllianceVsDeaths($killer->getAllianceID());
977
			}
978
		}
979
980
		$this->increaseHOF($return['BountyGained']['Amount'], array('Dying', 'Players', 'Money', 'Bounty Gained By Killer'), HOF_PUBLIC);
981
		$this->increaseHOF($return['KillerExp'], array('Dying', 'Players', 'Experience', 'Gained By Killer'), HOF_PUBLIC);
982
		$this->increaseHOF($return['DeadExp'], array('Dying', 'Experience', 'Lost'), HOF_PUBLIC);
983
		$this->increaseHOF($return['DeadExp'], array('Dying', 'Players', 'Experience', 'Lost'), HOF_PUBLIC);
984
		$this->increaseHOF($return['KillerCredits'], array('Dying', 'Players', 'Money Lost'), HOF_PUBLIC);
985
		$this->increaseHOF($this->getShip()->getCost(), array('Dying', 'Players', 'Money', 'Cost Of Ships Lost'), HOF_PUBLIC);
986
		$this->increaseHOF(1, array('Dying', 'Players', 'Deaths'), HOF_PUBLIC);
987
988
		$this->killPlayer($this->getSectorID());
989
		return $return;
990
	}
991
992
	public function &killPlayerByForces(SmrForce $forces) {
993
		$return = array();
994
		$owner = $forces->getOwner();
995
		// send a message to the person who died
996
		self::sendMessageFromFedClerk($this->getGameID(), $owner->getAccountID(), 'Your forces <span class="red">DESTROYED </span>' . $this->getBBLink() . ' in sector ' . Globals::getSectorBBLink($forces->getSectorID()));
997
		self::sendMessageFromFedClerk($this->getGameID(), $this->getAccountID(), 'You were <span class="red">DESTROYED</span> by ' . $owner->getBBLink() . '\'s forces in sector ' . Globals::getSectorBBLink($this->getSectorID()));
998
999
		$news_message = $this->getBBLink();
1000
		if ($this->hasCustomShipName()) {
1001
			$named_ship = strip_tags($this->getCustomShipName(), '<font><span><img>');
1002
			$news_message .= ' flying <span class="yellow">' . $named_ship . '</span>';
1003
		}
1004
		$news_message .= ' was destroyed by ' . $owner->getBBLink() . '\'s forces in sector ' . Globals::getSectorBBLink($forces->getSectorID());
1005
		// insert the news entry
1006
		$this->db->query('INSERT INTO news (game_id, time, news_message,killer_id,killer_alliance,dead_id,dead_alliance)
1007
						VALUES(' . $this->db->escapeNumber($this->getGameID()) . ', ' . $this->db->escapeNumber(TIME) . ', ' . $this->db->escapeString($news_message) . ',' . $this->db->escapeNumber($owner->getAccountID()) . ',' . $this->db->escapeNumber($owner->getAllianceID()) . ',' . $this->db->escapeNumber($this->getAccountID()) . ',' . $this->db->escapeNumber($this->getAllianceID()) . ')');
1008
1009
		// Player loses 15% experience
1010
		$expLossPercentage = .15;
1011
		$return['DeadExp'] = IFloor($this->getExperience() * $expLossPercentage);
1012
		$this->decreaseExperience($return['DeadExp']);
1013
1014
		$return['LostCredits'] = $this->getCredits();
1015
1016
		// alliance vs. alliance stats
1017
		$this->incrementAllianceVsDeaths(ALLIANCE_VS_FORCES);
1018
		$owner->incrementAllianceVsKills(ALLIANCE_VS_FORCES);
1019
1020
		$this->increaseHOF($return['DeadExp'], array('Dying', 'Experience', 'Lost'), HOF_PUBLIC);
1021
		$this->increaseHOF($return['DeadExp'], array('Dying', 'Forces', 'Experience Lost'), HOF_PUBLIC);
1022
		$this->increaseHOF($return['LostCredits'], array('Dying', 'Forces', 'Money Lost'), HOF_PUBLIC);
1023
		$this->increaseHOF($this->getShip()->getCost(), array('Dying', 'Forces', 'Cost Of Ships Lost'), HOF_PUBLIC);
1024
		$this->increaseHOF(1, array('Dying', 'Forces', 'Deaths'), HOF_PUBLIC);
1025
1026
		$this->killPlayer($forces->getSectorID());
1027
		return $return;
1028
	}
1029
1030
	public function &killPlayerByPort(SmrPort $port) {
1031
		$return = array();
1032
		// send a message to the person who died
1033
		self::sendMessageFromFedClerk($this->getGameID(), $this->getAccountID(), 'You were <span class="red">DESTROYED</span> by the defenses of ' . $port->getDisplayName());
1034
1035
		$news_message = $this->getBBLink();
1036
		if ($this->hasCustomShipName()) {
1037
			$named_ship = strip_tags($this->getCustomShipName(), '<font><span><img>');
1038
			$news_message .= ' flying <span class="yellow">' . $named_ship . '</span>';
1039
		}
1040
		$news_message .= ' was destroyed while invading ' . $port->getDisplayName() . '.';
1041
		// insert the news entry
1042
		$this->db->query('INSERT INTO news (game_id, time, news_message,killer_id,dead_id,dead_alliance)
1043
						VALUES(' . $this->db->escapeNumber($this->getGameID()) . ', ' . $this->db->escapeNumber(TIME) . ', ' . $this->db->escapeString($news_message) . ',' . $this->db->escapeNumber(ACCOUNT_ID_PORT) . ',' . $this->db->escapeNumber($this->getAccountID()) . ',' . $this->db->escapeNumber($this->getAllianceID()) . ')');
1044
1045
		// Player loses between 15% and 20% experience
1046
		$expLossPercentage = .20 - .05 * ($port->getLevel() - 1) / ($port->getMaxLevel() - 1);
1047
		$return['DeadExp'] = max(0, IFloor($this->getExperience() * $expLossPercentage));
1048
		$this->decreaseExperience($return['DeadExp']);
1049
1050
		$return['LostCredits'] = $this->getCredits();
1051
1052
		// alliance vs. alliance stats
1053
		$this->incrementAllianceVsDeaths(ALLIANCE_VS_PORTS);
1054
1055
		$this->increaseHOF($return['DeadExp'], array('Dying', 'Experience', 'Lost'), HOF_PUBLIC);
1056
		$this->increaseHOF($return['DeadExp'], array('Dying', 'Ports', 'Experience Lost'), HOF_PUBLIC);
1057
		$this->increaseHOF($return['LostCredits'], array('Dying', 'Ports', 'Money Lost'), HOF_PUBLIC);
1058
		$this->increaseHOF($this->getShip()->getCost(), array('Dying', 'Ports', 'Cost Of Ships Lost'), HOF_PUBLIC);
1059
		$this->increaseHOF(1, array('Dying', 'Ports', 'Deaths'), HOF_PUBLIC);
1060
1061
		$this->killPlayer($port->getSectorID());
1062
		return $return;
1063
	}
1064
1065
	public function &killPlayerByPlanet(SmrPlanet $planet) {
1066
		$return = array();
1067
		// send a message to the person who died
1068
		$planetOwner = $planet->getOwner();
1069
		self::sendMessageFromFedClerk($this->getGameID(), $planetOwner->getAccountID(), 'Your planet <span class="red">DESTROYED</span>&nbsp;' . $this->getBBLink() . ' in sector ' . Globals::getSectorBBLink($planet->getSectorID()));
1070
		self::sendMessageFromFedClerk($this->getGameID(), $this->getAccountID(), 'You were <span class="red">DESTROYED</span> by the planetary defenses of ' . $planet->getCombatName());
1071
1072
		$news_message = $this->getBBLink();
1073
		if ($this->hasCustomShipName()) {
1074
			$named_ship = strip_tags($this->getCustomShipName(), '<font><span><img>');
1075
			$news_message .= ' flying <span class="yellow">' . $named_ship . '</span>';
1076
		}
1077
		$news_message .= ' was destroyed by ' . $planet->getCombatName() . '\'s planetary defenses in sector ' . Globals::getSectorBBLink($planet->getSectorID()) . '.';
1078
		// insert the news entry
1079
		$this->db->query('INSERT INTO news (game_id, time, news_message,killer_id,killer_alliance,dead_id,dead_alliance)
1080
						VALUES(' . $this->db->escapeNumber($this->getGameID()) . ', ' . $this->db->escapeNumber(TIME) . ', ' . $this->db->escapeString($news_message) . ',' . $this->db->escapeNumber($planetOwner->getAccountID()) . ',' . $this->db->escapeNumber($planetOwner->getAllianceID()) . ',' . $this->db->escapeNumber($this->getAccountID()) . ',' . $this->db->escapeNumber($this->getAllianceID()) . ')');
1081
1082
		// Player loses between 15% and 20% experience
1083
		$expLossPercentage = .20 - .05 * $planet->getLevel() / $planet->getMaxLevel();
1084
		$return['DeadExp'] = max(0, IFloor($this->getExperience() * $expLossPercentage));
1085
		$this->decreaseExperience($return['DeadExp']);
1086
1087
		$return['LostCredits'] = $this->getCredits();
1088
1089
		// alliance vs. alliance stats
1090
		$this->incrementAllianceVsDeaths(ALLIANCE_VS_PLANETS);
1091
		$planetOwner->incrementAllianceVsKills(ALLIANCE_VS_PLANETS);
1092
1093
		$this->increaseHOF($return['DeadExp'], array('Dying', 'Experience', 'Lost'), HOF_PUBLIC);
1094
		$this->increaseHOF($return['DeadExp'], array('Dying', 'Planets', 'Experience Lost'), HOF_PUBLIC);
1095
		$this->increaseHOF($return['LostCredits'], array('Dying', 'Planets', 'Money Lost'), HOF_PUBLIC);
1096
		$this->increaseHOF($this->getShip()->getCost(), array('Dying', 'Planets', 'Cost Of Ships Lost'), HOF_PUBLIC);
1097
		$this->increaseHOF(1, array('Dying', 'Planets', 'Deaths'), HOF_PUBLIC);
1098
1099
		$this->killPlayer($planet->getSectorID());
1100
		return $return;
1101
	}
1102
1103
	public function save() {
1104
		if ($this->hasChanged === true) {
1105
			$this->db->query('UPDATE player SET player_name=' . $this->db->escapeString($this->playerName) .
1106
				', player_id=' . $this->db->escapeNumber($this->playerID) .
1107
				', sector_id=' . $this->db->escapeNumber($this->sectorID) .
1108
				', last_sector_id=' . $this->db->escapeNumber($this->lastSectorID) .
1109
				', turns=' . $this->db->escapeNumber($this->turns) .
1110
				', last_turn_update=' . $this->db->escapeNumber($this->lastTurnUpdate) .
1111
				', newbie_turns=' . $this->db->escapeNumber($this->newbieTurns) .
1112
				', last_news_update=' . $this->db->escapeNumber($this->lastNewsUpdate) .
1113
				', attack_warning=' . $this->db->escapeString($this->attackColour) .
1114
				', dead=' . $this->db->escapeBoolean($this->dead) .
1115
				', newbie_status=' . $this->db->escapeBoolean($this->newbieStatus) .
1116
				', land_on_planet=' . $this->db->escapeBoolean($this->landedOnPlanet) .
1117
				', last_active=' . $this->db->escapeNumber($this->lastActive) .
1118
				', last_cpl_action=' . $this->db->escapeNumber($this->lastCPLAction) .
1119
				', race_id=' . $this->db->escapeNumber($this->raceID) .
1120
				', credits=' . $this->db->escapeNumber($this->credits) .
1121
				', experience=' . $this->db->escapeNumber($this->experience) .
1122
				', alignment=' . $this->db->escapeNumber($this->alignment) .
1123
				', military_payment=' . $this->db->escapeNumber($this->militaryPayment) .
1124
//				', past_knowledge='.$this->db->escapeString($this->pastKnowledge).
1125
				', alliance_id=' . $this->db->escapeNumber($this->allianceID) .
1126
				', alliance_join=' . $this->db->escapeNumber($this->allianceJoinable) .
1127
				', ship_type_id=' . $this->db->escapeNumber($this->shipID) .
1128
				', kills=' . $this->db->escapeNumber($this->kills) .
1129
				', deaths=' . $this->db->escapeNumber($this->deaths) .
1130
				', assists=' . $this->db->escapeNumber($this->assists) .
1131
				', last_port=' . $this->db->escapeNumber($this->lastPort) .
1132
				', bank=' . $this->db->escapeNumber($this->bank) .
1133
				', zoom=' . $this->db->escapeNumber($this->zoom) .
1134
				', display_missions=' . $this->db->escapeBoolean($this->displayMissions) .
1135
				', force_drop_messages=' . $this->db->escapeBoolean($this->forceDropMessages) .
1136
				', group_scout_messages=' . $this->db->escapeString($this->groupScoutMessages) .
1137
				', ignore_globals=' . $this->db->escapeBoolean($this->ignoreGlobals) .
1138
				', newbie_warning = ' . $this->db->escapeBoolean($this->newbieWarning) .
1139
				', name_changed = ' . $this->db->escapeBoolean($this->nameChanged) .
1140
				', combat_drones_kamikaze_on_mines = ' . $this->db->escapeBoolean($this->combatDronesKamikazeOnMines) .
1141
				' WHERE ' . $this->SQL . ' LIMIT 1');
1142
			$this->hasChanged = false;
1143
		}
1144
		foreach ($this->hasBountyChanged as $key => &$bountyChanged) {
1145
			if ($bountyChanged === true) {
1146
				$bountyChanged = false;
1147
				$bounty = $this->getBounty($key);
1148
				if ($bounty['New'] === true) {
1149
					if ($bounty['Amount'] > 0 || $bounty['SmrCredits'] > 0) {
1150
						$this->db->query('INSERT INTO bounty (account_id,game_id,type,amount,smr_credits,claimer_id,time) VALUES (' . $this->db->escapeNumber($this->getAccountID()) . ',' . $this->db->escapeNumber($this->getGameID()) . ',' . $this->db->escapeString($bounty['Type']) . ',' . $this->db->escapeNumber($bounty['Amount']) . ',' . $this->db->escapeNumber($bounty['SmrCredits']) . ',' . $this->db->escapeNumber($bounty['Claimer']) . ',' . $this->db->escapeNumber($bounty['Time']) . ')');
1151
					}
1152
				} else {
1153
					if ($bounty['Amount'] > 0 || $bounty['SmrCredits'] > 0) {
1154
						$this->db->query('UPDATE bounty
1155
							SET amount=' . $this->db->escapeNumber($bounty['Amount']) . ',
1156
							smr_credits=' . $this->db->escapeNumber($bounty['SmrCredits']) . ',
1157
							type=' . $this->db->escapeString($bounty['Type']) . ',
1158
							claimer_id=' . $this->db->escapeNumber($bounty['Claimer']) . ',
1159
							time=' . $this->db->escapeNumber($bounty['Time']) . '
1160
							WHERE bounty_id=' . $this->db->escapeNumber($bounty['ID']) . ' AND ' . $this->SQL . ' LIMIT 1');
1161
					} else {
1162
						$this->db->query('DELETE FROM bounty WHERE bounty_id=' . $this->db->escapeNumber($bounty['ID']) . ' AND ' . $this->SQL . ' LIMIT 1');
1163
					}
1164
				}
1165
			}
1166
		}
1167
		$this->saveHOF();
1168
	}
1169
1170
	public function saveHOF() {
1171
		if ($this->hasHOFChanged !== false) {
1172
			$this->doHOFSave($this->hasHOFChanged);
0 ignored issues
show
Bug introduced by
$this->hasHOFChanged of type true is incompatible with the type array expected by parameter $hasChangedList of SmrPlayer::doHOFSave(). ( Ignorable by Annotation )

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

1172
			$this->doHOFSave(/** @scrutinizer ignore-type */ $this->hasHOFChanged);
Loading history...
1173
		}
1174
		if (!empty(self::$hasHOFVisChanged)) {
1175
			foreach (self::$hasHOFVisChanged as $hofType => $changeType) {
1176
				if ($changeType == self::HOF_NEW) {
1177
					$this->db->query('INSERT INTO hof_visibility (type, visibility) VALUES (' . $this->db->escapeString($hofType) . ',' . $this->db->escapeString(self::$HOFVis[$hofType]) . ')');
1178
				} else {
1179
					$this->db->query('UPDATE hof_visibility SET visibility = ' . $this->db->escapeString(self::$HOFVis[$hofType]) . ' WHERE type = ' . $this->db->escapeString($hofType) . ' LIMIT 1');
1180
				}
1181
				unset(self::$hasHOFVisChanged[$hofType]);
1182
			}
1183
		}
1184
	}
1185
	protected function doHOFSave(array &$hasChangedList, array $typeList = array()) {
1186
		foreach ($hasChangedList as $type => &$hofChanged) {
1187
			$tempTypeList = $typeList;
1188
			$tempTypeList[] = $type;
1189
			if (is_array($hofChanged)) {
1190
				$this->doHOFSave($hofChanged, $tempTypeList);
1191
			} else {
1192
				$amount = $this->getHOF($tempTypeList);
1193
				if ($hofChanged == self::HOF_NEW) {
1194
					if ($amount > 0) {
1195
						$this->db->query('INSERT INTO player_hof (account_id,game_id,type,amount) VALUES (' . $this->db->escapeNumber($this->getAccountID()) . ',' . $this->db->escapeNumber($this->getGameID()) . ',' . $this->db->escapeArray($tempTypeList, false, true, ':', false) . ',' . $this->db->escapeNumber($amount) . ')');
1196
					}
1197
				} elseif ($hofChanged == self::HOF_CHANGED) {
1198
	//				if($amount > 0)
1199
						$this->db->query('UPDATE player_hof
1200
							SET amount=' . $this->db->escapeNumber($amount) . '
1201
							WHERE ' . $this->SQL . ' AND type = ' . $this->db->escapeArray($tempTypeList, false, true, ':', false) . ' LIMIT 1');
1202
	//				else
1203
	//					$this->db->query('DELETE FROM player_hof WHERE account_id=' . $this->getAccountID() . ' AND game_id = ' . $this->getGameID() . ' AND type = ' . $this->db->escapeArray($tempTypeList,false,true,':',false) . ' LIMIT 1');
1204
	//				}
1205
				}
1206
				$hofChanged = false;
1207
			}
1208
		}
1209
	}
1210
1211
	protected function getHOFData() {
1212
		if (!isset($this->HOF)) {
1213
			//Get Player HOF
1214
			$this->db->query('SELECT type,amount FROM player_hof WHERE ' . $this->SQL);
1215
			$this->HOF = array();
1216
			while ($this->db->nextRecord()) {
1217
				$hof =& $this->HOF;
1218
				$typeList = explode(':', $this->db->getField('type'));
1219
				foreach ($typeList as $type) {
1220
					if (!isset($hof[$type])) {
1221
						$hof[$type] = array();
1222
					}
1223
					$hof =& $hof[$type];
1224
				}
1225
				$hof = $this->db->getFloat('amount');
1226
			}
1227
			self::getHOFVis();
1228
		}
1229
	}
1230
1231
	public static function getHOFVis() {
1232
		if (!isset(self::$HOFVis)) {
1233
			//Get Player HOF Vis
1234
			$db = new SmrMySqlDatabase();
1235
			$db->query('SELECT type,visibility FROM hof_visibility');
1236
			self::$HOFVis = array();
1237
			while ($db->nextRecord()) {
1238
				self::$HOFVis[$db->getField('type')] = $db->getField('visibility');
1239
			}
1240
		}
1241
	}
1242
1243
	protected function getBountiesData() {
1244
		if (!isset($this->bounties)) {
1245
			$this->bounties = array();
1246
			$this->db->query('SELECT * FROM bounty WHERE ' . $this->SQL);
1247
			while ($this->db->nextRecord()) {
1248
				$this->bounties[$this->db->getInt('bounty_id')] = array(
1249
							'Amount' => $this->db->getInt('amount'),
1250
							'SmrCredits' => $this->db->getInt('smr_credits'),
1251
							'Type' => $this->db->getField('type'),
1252
							'Claimer' => $this->db->getInt('claimer_id'),
1253
							'Time' => $this->db->getInt('time'),
1254
							'ID' => $this->db->getInt('bounty_id'),
1255
							'New' => false);
1256
			}
1257
		}
1258
	}
1259
1260
	// Get bounties that can be claimed by this player
1261
	// Type must be 'HQ' or 'UG'
1262
	public function getClaimableBounties($type) {
1263
		$bounties = array();
1264
		$this->db->query('SELECT * FROM bounty WHERE claimer_id=' . $this->db->escapeNumber($this->getAccountID()) . ' AND game_id=' . $this->db->escapeNumber($this->getGameID()) . ' AND type=' . $this->db->escapeString($type));
1265
		while ($this->db->nextRecord()) {
1266
			$bounties[] = array(
1267
				'player' => SmrPlayer::getPlayer($this->db->getInt('account_id'), $this->getGameID()),
1268
				'bounty_id' => $this->db->getInt('bounty_id'),
1269
				'credits' => $this->db->getInt('amount'),
1270
				'smr_credits' => $this->db->getInt('smr_credits'),
1271
			);
1272
		}
1273
		return $bounties;
1274
	}
1275
1276
	/**
1277
	 * Has this player been designated as the alliance flagship?
1278
	 */
1279
	public function isFlagship() {
1280
		return $this->hasAlliance() && $this->getAlliance()->getFlagshipID() == $this->getAccountID();
1281
	}
1282
1283
	public function isPresident() {
1284
		return Council::getPresidentID($this->getGameID(), $this->getRaceID()) == $this->getAccountID();
1285
	}
1286
1287
	public function isOnCouncil() {
1288
		return Council::isOnCouncil($this->getGameID(), $this->getRaceID(), $this->getAccountID());
1289
	}
1290
1291
	public function setNewbieWarning($bool) {
1292
		if ($this->newbieWarning == $bool) {
1293
			return;
1294
		}
1295
		$this->newbieWarning = $bool;
1296
		$this->hasChanged = true;
1297
	}
1298
1299
	public function getNewbieWarning() {
1300
		return $this->newbieWarning;
1301
	}
1302
1303
	public function getTickers() {
1304
		if (!isset($this->tickers)) {
1305
			$this->tickers = array();
1306
			//get ticker info
1307
			$this->db->query('SELECT type,time,expires,recent FROM player_has_ticker WHERE ' . $this->SQL . ' AND expires > ' . $this->db->escapeNumber(TIME));
1308
			while ($this->db->nextRecord()) {
1309
				$this->tickers[$this->db->getField('type')] = array('Type' => $this->db->getField('type'),
1310
																				'Time' => $this->db->getInt('time'),
1311
																				'Expires' => $this->db->getInt('expires'),
1312
																				'Recent' => $this->db->getField('recent'));
1313
			}
1314
		}
1315
		return $this->tickers;
1316
	}
1317
1318
	public function hasTickers() {
1319
		return count($this->getTickers()) > 0;
1320
	}
1321
1322
	public function getTicker($tickerType) {
1323
		$tickers = $this->getTickers();
1324
		if (isset($tickers[$tickerType])) {
1325
			return $tickers[$tickerType];
1326
		}
1327
		return false;
1328
	}
1329
1330
	public function hasTicker($tickerType) {
1331
		return $this->getTicker($tickerType) !== false;
1332
	}
1333
1334
	public function getTurnsLevel() {
1335
		if (!$this->hasTurns()) {
1336
			return 'NONE';
1337
		}
1338
		if ($this->getTurns() <= 25) {
1339
			return 'LOW';
1340
		}
1341
		if ($this->getTurns() <= 75) {
1342
			return 'MEDIUM';
1343
		}
1344
		return 'HIGH';
1345
	}
1346
1347
	/**
1348
	 * Returns the CSS class color to use when displaying the player's turns
1349
	 */
1350
	public function getTurnsColor() {
1351
		switch ($this->getTurnsLevel()) {
1352
			case 'NONE':
1353
			case 'LOW':
1354
				return 'red';
1355
			break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1356
			case 'MEDIUM':
1357
				return 'yellow';
1358
			break;
1359
			default:
1360
				return 'green';
1361
		}
1362
	}
1363
1364
	public function update() {
1365
		$this->save();
1366
	}
1367
1368
	protected static function doMessageSending($senderID, $receiverID, $gameID, $messageTypeID, $message, $expires, $senderDelete = false, $unread = true) {
1369
		$message = trim($message);
1370
		$db = new SmrMySqlDatabase();
1371
		// send him the message
1372
		$db->query('INSERT INTO message
1373
			(account_id,game_id,message_type_id,message_text,
1374
			sender_id,send_time,expire_time,sender_delete) VALUES(' .
1375
			$db->escapeNumber($receiverID) . ',' .
1376
			$db->escapeNumber($gameID) . ',' .
1377
			$db->escapeNumber($messageTypeID) . ',' .
1378
			$db->escapeString($message) . ',' .
1379
			$db->escapeNumber($senderID) . ',' .
1380
			$db->escapeNumber(TIME) . ',' .
1381
			$db->escapeNumber($expires) . ',' .
1382
			$db->escapeBoolean($senderDelete) . ')'
1383
		);
1384
		// Keep track of the message_id so it can be returned
1385
		$insertID = $db->getInsertID();
1386
1387
		if ($unread === true) {
1388
			// give him the message icon
1389
			$db->query('REPLACE INTO player_has_unread_messages (game_id, account_id, message_type_id) VALUES
1390
						(' . $db->escapeNumber($gameID) . ', ' . $db->escapeNumber($receiverID) . ', ' . $db->escapeNumber($messageTypeID) . ')');
1391
		}
1392
1393
		switch ($messageTypeID) {
1394
			case MSG_PLAYER:
1395
				$receiverAccount = SmrAccount::getAccount($receiverID);
1396
				if ($receiverAccount->isValidated() && $receiverAccount->isReceivingMessageNotifications($messageTypeID) && !$receiverAccount->isLoggedIn()) {
1397
					require_once(get_file_loc('message.functions.inc'));
1398
					$sender = getMessagePlayer($senderID, $gameID, $messageTypeID);
1399
					if ($sender instanceof SmrPlayer) {
1400
						$sender = $sender->getDisplayName();
1401
					}
1402
					$mail = setupMailer();
1403
					$mail->Subject = 'Message Notification';
1404
					$mail->setFrom('[email protected]', 'SMR Notifications');
1405
					$bbifiedMessage = 'From: ' . $sender . ' Date: ' . date($receiverAccount->getShortDateFormat() . ' ' . $receiverAccount->getShortTimeFormat(), TIME) . "<br/>\r\n<br/>\r\n" . bbifyMessage($message, true);
1406
					$mail->msgHTML($bbifiedMessage);
1407
					$mail->AltBody = strip_tags($bbifiedMessage);
1408
					$mail->addAddress($receiverAccount->getEmail(), $receiverAccount->getHofName());
1409
					$mail->send();
1410
					$receiverAccount->decreaseMessageNotifications($messageTypeID, 1);
1411
				}
1412
			break;
1413
		}
1414
1415
		return $insertID;
1416
	}
1417
1418
	public function sendMessageToBox($boxTypeID, $message) {
1419
		// send him the message
1420
		SmrAccount::doMessageSendingToBox($this->getAccountID(), $boxTypeID, $message, $this->getGameID());
1421
	}
1422
1423
	public function sendGlobalMessage($message, $canBeIgnored = true) {
1424
		if ($canBeIgnored) {
1425
			if ($this->getAccount()->isMailBanned()) {
1426
				create_error('You are currently banned from sending messages');
1427
			}
1428
		}
1429
		$this->sendMessageToBox(BOX_GLOBALS, $message);
1430
1431
		// send to all online player
1432
		$db = new SmrMySqlDatabase();
1433
		$db->query('SELECT account_id
1434
					FROM active_session
1435
					JOIN player USING (game_id, account_id)
1436
					WHERE active_session.last_accessed >= ' . $db->escapeNumber(TIME - SmrSession::TIME_BEFORE_EXPIRY) . '
1437
						AND game_id = ' . $db->escapeNumber($this->getGameID()) . '
1438
						AND ignore_globals = \'FALSE\'
1439
						AND account_id != ' . $db->escapeNumber($this->getAccountID()));
1440
1441
		while ($db->nextRecord()) {
1442
			$this->sendMessage($db->getInt('account_id'), MSG_GLOBAL, $message, $canBeIgnored);
1443
		}
1444
		$this->sendMessage($this->getAccountID(), MSG_GLOBAL, $message, $canBeIgnored, false);
1445
	}
1446
1447
	public function sendMessage($receiverID, $messageTypeID, $message, $canBeIgnored = true, $unread = true, $expires = false, $senderDelete = false) {
1448
		//get expire time
1449
		if ($canBeIgnored) {
1450
			if ($this->getAccount()->isMailBanned()) {
1451
				create_error('You are currently banned from sending messages');
1452
			}
1453
			// Don't send messages to players ignoring us
1454
			$this->db->query('SELECT account_id FROM message_blacklist WHERE account_id=' . $this->db->escapeNumber($receiverID) . ' AND blacklisted_id=' . $this->db->escapeNumber($this->getAccountID()) . ' LIMIT 1');
1455
			if ($this->db->nextRecord()) {
1456
				return;
1457
			}
1458
		}
1459
1460
		$message = word_filter($message);
1461
1462
		// If expires not specified, use default based on message type
1463
		if ($expires === false) {
1464
			switch ($messageTypeID) {
1465
				case MSG_GLOBAL: //We don't send globals to the box here or it gets done loads of times.
1466
					$expires = 3600; // 1h
1467
				break;
1468
				case MSG_PLAYER:
1469
					$expires = 86400 * 31;
1470
				break;
1471
				case MSG_PLANET:
1472
					$expires = 86400 * 7;
1473
				break;
1474
				case MSG_SCOUT:
1475
					$expires = 86400 * 3;
1476
				break;
1477
				case MSG_POLITICAL:
1478
					$expires = 86400 * 31;
1479
				break;
1480
				case MSG_ALLIANCE:
1481
					$expires = 86400 * 31;
1482
				break;
1483
				case MSG_ADMIN:
1484
					$expires = 86400 * 365;
1485
				break;
1486
				case MSG_CASINO:
1487
					$expires = 86400 * 31;
1488
				break;
1489
				default:
1490
					$expires = 86400 * 7;
1491
			}
1492
			$expires += TIME;
1493
		}
1494
1495
		// Do not put scout messages in the sender's sent box
1496
		if ($messageTypeID == MSG_SCOUT) {
1497
			$senderDelete = true;
1498
		}
1499
1500
		// send him the message and return the message_id
1501
		return self::doMessageSending($this->getAccountID(), $receiverID, $this->getGameID(), $messageTypeID, $message, $expires, $senderDelete, $unread);
1502
	}
1503
1504
	public function sendMessageFromOpAnnounce($receiverID, $message, $expires = false) {
1505
		// get expire time if not set
1506
		if ($expires === false) {
1507
			$expires = TIME + 86400 * 14;
1508
		}
1509
		self::doMessageSending(ACCOUNT_ID_OP_ANNOUNCE, $receiverID, $this->getGameID(), MSG_ALLIANCE, $message, $expires);
1510
	}
1511
1512
	public function sendMessageFromAllianceCommand($receiverID, $message) {
1513
		$expires = TIME + 86400 * 365;
1514
		self::doMessageSending(ACCOUNT_ID_ALLIANCE_COMMAND, $receiverID, $this->getGameID(), MSG_PLAYER, $message, $expires);
1515
	}
1516
1517
	public static function sendMessageFromPlanet($gameID, $receiverID, $message) {
1518
		//get expire time
1519
		$expires = TIME + 86400 * 31;
1520
		// send him the message
1521
		self::doMessageSending(ACCOUNT_ID_PLANET, $receiverID, $gameID, MSG_PLANET, $message, $expires);
1522
	}
1523
1524
	public static function sendMessageFromPort($gameID, $receiverID, $message) {
1525
		//get expire time
1526
		$expires = TIME + 86400 * 31;
1527
		// send him the message
1528
		self::doMessageSending(ACCOUNT_ID_PORT, $receiverID, $gameID, MSG_PLAYER, $message, $expires);
1529
	}
1530
1531
	public static function sendMessageFromFedClerk($gameID, $receiverID, $message) {
1532
		$expires = TIME + 86400 * 365;
1533
		self::doMessageSending(ACCOUNT_ID_FED_CLERK, $receiverID, $gameID, MSG_PLAYER, $message, $expires);
1534
	}
1535
1536
	public static function sendMessageFromAdmin($gameID, $receiverID, $message, $expires = false) {
1537
		//get expire time
1538
		if ($expires === false) {
1539
			$expires = TIME + 86400 * 365;
1540
		}
1541
		// send him the message
1542
		self::doMessageSending(ACCOUNT_ID_ADMIN, $receiverID, $gameID, MSG_ADMIN, $message, $expires);
1543
	}
1544
1545
	public static function sendMessageFromAllianceAmbassador($gameID, $receiverID, $message, $expires = false) {
1546
		//get expire time
1547
		if ($expires === false) {
1548
			$expires = TIME + 86400 * 31;
1549
		}
1550
		// send him the message
1551
		self::doMessageSending(ACCOUNT_ID_ALLIANCE_AMBASSADOR, $receiverID, $gameID, MSG_ALLIANCE, $message, $expires);
1552
	}
1553
1554
	public static function sendMessageFromCasino($gameID, $receiverID, $message, $expires = false) {
1555
		//get expire time
1556
		if ($expires === false) {
1557
			$expires = TIME + 86400 * 7;
1558
		}
1559
		// send him the message
1560
		self::doMessageSending(ACCOUNT_ID_CASINO, $receiverID, $gameID, MSG_CASINO, $message, $expires);
1561
	}
1562
1563
	public static function sendMessageFromRace($raceID, $gameID, $receiverID, $message, $expires = false) {
1564
		//get expire time
1565
		if ($expires === false) {
1566
			$expires = TIME + 86400 * 5;
1567
		}
1568
		// send him the message
1569
		self::doMessageSending(ACCOUNT_ID_GROUP_RACES + $raceID, $receiverID, $gameID, MSG_POLITICAL, $message, $expires);
1570
	}
1571
1572
	public function setMessagesRead($messageTypeID) {
1573
		$this->db->query('DELETE FROM player_has_unread_messages
1574
							WHERE '.$this->SQL . ' AND message_type_id = ' . $this->db->escapeNumber($messageTypeID));
1575
	}
1576
1577
	public function getPlottedCourse() {
1578
		if (!isset($this->plottedCourse)) {
1579
			// check if we have a course plotted
1580
			$this->db->query('SELECT course FROM player_plotted_course WHERE ' . $this->SQL . ' LIMIT 1');
1581
1582
			if ($this->db->nextRecord()) {
1583
				// get the course back
1584
				$this->plottedCourse = unserialize($this->db->getField('course'));
1585
			} else {
1586
				$this->plottedCourse = false;
1587
			}
1588
		}
1589
1590
		// Update the plotted course if we have moved since the last query
1591
		if ($this->plottedCourse !== false && (!isset($this->plottedCourseFrom) || $this->plottedCourseFrom != $this->getSectorID())) {
1592
			$this->plottedCourseFrom = $this->getSectorID();
1593
1594
			if ($this->plottedCourse->getNextOnPath() == $this->getSectorID()) {
1595
				// We have walked into the next sector of the course
1596
				$this->plottedCourse->followPath();
1597
				$this->setPlottedCourse($this->plottedCourse);
1598
			} elseif ($this->plottedCourse->isInPath($this->getSectorID())) {
1599
				// We have skipped to some later sector in the course
1600
				$this->plottedCourse->skipToSector($this->getSectorID());
1601
				$this->setPlottedCourse($this->plottedCourse);
1602
			}
1603
		}
1604
		return $this->plottedCourse;
1605
	}
1606
1607
	public function setPlottedCourse(Distance $plottedCourse) {
1608
		$hadPlottedCourse = $this->hasPlottedCourse();
1609
		$this->plottedCourse = $plottedCourse;
1610
		if ($this->plottedCourse->getTotalSectors() > 0) {
1611
			$this->db->query('REPLACE INTO player_plotted_course
1612
				(account_id, game_id, course)
1613
				VALUES(' . $this->db->escapeNumber($this->getAccountID()) . ', ' . $this->db->escapeNumber($this->getGameID()) . ', ' . $this->db->escapeBinary(serialize($this->plottedCourse)) . ')');
1614
		} elseif ($hadPlottedCourse) {
1615
			$this->deletePlottedCourse();
1616
		}
1617
	}
1618
1619
	public function hasPlottedCourse() {
1620
		return $this->getPlottedCourse() !== false;
1621
	}
1622
1623
	public function isPartOfCourse($sectorOrSectorID) {
1624
		if (!$this->hasPlottedCourse()) {
1625
			return false;
1626
		}
1627
		if ($sectorOrSectorID instanceof SmrSector) {
1628
			$sectorID = $sectorOrSectorID->getSectorID();
1629
		} else {
1630
			$sectorID = $sectorOrSectorID;
1631
		}
1632
		return $this->getPlottedCourse()->isInPath($sectorID);
1633
	}
1634
1635
	public function deletePlottedCourse() {
1636
		$this->plottedCourse = false;
1637
		$this->db->query('DELETE FROM player_plotted_course WHERE ' . $this->SQL . ' LIMIT 1');
1638
	}
1639
1640
	// Computes the turn cost and max misjump between current and target sector
1641
	public function getJumpInfo(SmrSector $targetSector) {
1642
		$path = Plotter::findDistanceToX($targetSector, $this->getSector(), true);
1643
		if ($path === false) {
1644
			create_error('Unable to plot from ' . $this->getSectorID() . ' to ' . $targetSector->getSectorID() . '.');
1645
		}
1646
		$distance = $path->getRelativeDistance();
1647
1648
		$turnCost = max(TURNS_JUMP_MINIMUM, IRound($distance * TURNS_PER_JUMP_DISTANCE));
1649
		$maxMisjump = max(0, IRound(($distance - $turnCost) * MISJUMP_DISTANCE_DIFF_FACTOR / (1 + $this->getLevelID() * MISJUMP_LEVEL_FACTOR)));
1650
		return array('turn_cost' => $turnCost, 'max_misjump' => $maxMisjump);
1651
	}
1652
1653
	public function __sleep() {
1654
		return array('accountID', 'gameID', 'sectorID', 'alignment', 'playerID', 'playerName');
1655
	}
1656
1657
	public function &getStoredDestinations() {
1658
		if (!isset($this->storedDestinations)) {
1659
			$this->storedDestinations = array();
1660
			$this->db->query('SELECT * FROM player_stored_sector WHERE ' . $this->SQL);
1661
			while ($this->db->nextRecord()) {
1662
				$this->storedDestinations[] = array(
1663
					'Label' => $this->db->getField('label'),
1664
					'SectorID' => $this->db->getInt('sector_id'),
1665
					'OffsetTop' => $this->db->getInt('offset_top'),
1666
					'OffsetLeft' => $this->db->getInt('offset_left')
1667
				);
1668
			}
1669
		}
1670
		return $this->storedDestinations;
1671
	}
1672
1673
1674
	public function moveDestinationButton($sectorID, $offsetTop, $offsetLeft) {
1675
1676
		if (!is_numeric($offsetLeft) || !is_numeric($offsetTop)) {
1677
			create_error('The position of the saved sector must be numeric!.');
1678
		}
1679
		$offsetTop = round($offsetTop);
1680
		$offsetLeft = round($offsetLeft);
1681
1682
		if ($offsetLeft < 0 || $offsetLeft > 500 || $offsetTop < 0 || $offsetTop > 300) {
1683
			create_error('The saved sector must be in the box!');
1684
		}
1685
1686
		$storedDestinations =& $this->getStoredDestinations();
1687
		foreach ($storedDestinations as &$sd) {
1688
			if ($sd['SectorID'] == $sectorID) {
1689
				$sd['OffsetTop'] = $offsetTop;
1690
				$sd['OffsetLeft'] = $offsetLeft;
1691
				$this->db->query('
1692
					UPDATE player_stored_sector
1693
						SET offset_left = ' . $this->db->escapeNumber($offsetLeft) . ', offset_top=' . $this->db->escapeNumber($offsetTop) . '
1694
					WHERE ' . $this->SQL . ' AND sector_id = ' . $this->db->escapeNumber($sectorID)
1695
				);
1696
				return true;
1697
			}
1698
		}
1699
1700
		create_error('You do not have a saved sector for #' . $sectorID);
1701
	}
1702
1703
	public function addDestinationButton($sectorID, $label) {
1704
1705
		if (!is_numeric($sectorID) || !SmrSector::sectorExists($this->getGameID(), $sectorID)) {
1706
			create_error('You want to add a non-existent sector?');
1707
		}
1708
1709
		// sector already stored ?
1710
		foreach ($this->getStoredDestinations() as $sd) {
1711
			if ($sd['SectorID'] == $sectorID) {
1712
				create_error('Sector already stored!');
1713
			}
1714
		}
1715
1716
		$this->storedDestinations[] = array(
1717
			'Label' => $label,
1718
			'SectorID' => (int)$sectorID,
1719
			'OffsetTop' => 1,
1720
			'OffsetLeft' => 1
1721
		);
1722
1723
		$this->db->query('
1724
			INSERT INTO player_stored_sector (account_id, game_id, sector_id, label, offset_top, offset_left)
1725
			VALUES (' . $this->db->escapeNumber($this->getAccountID()) . ', ' . $this->db->escapeNumber($this->getGameID()) . ', ' . $this->db->escapeNumber($sectorID) . ',' . $this->db->escapeString($label, true) . ',1,1)'
1726
		);
1727
	}
1728
1729
	public function deleteDestinationButton($sectorID) {
1730
		if (!is_numeric($sectorID) || $sectorID < 1) {
1731
			create_error('You want to remove a non-existent sector?');
1732
		}
1733
1734
		foreach ($this->getStoredDestinations() as $key => $sd) {
1735
			if ($sd['SectorID'] == $sectorID) {
1736
				$this->db->query('
1737
					DELETE FROM player_stored_sector
1738
					WHERE ' . $this->SQL . '
1739
					AND sector_id = ' . $this->db->escapeNumber($sectorID)
1740
				);
1741
				unset($this->storedDestinations[$key]);
1742
				return true;
1743
			}
1744
		}
1745
		return false;
1746
	}
1747
1748
	public function getExperienceRank() {
1749
		return $this->computeRanking('experience', $this->getExperience());
1750
	}
1751
	public function getKillsRank() {
1752
		return $this->computeRanking('kills', $this->getKills());
1753
	}
1754
	public function getDeathsRank() {
1755
		return $this->computeRanking('deaths', $this->getDeaths());
1756
	}
1757
	public function getAssistsRank() {
1758
		return $this->computeRanking('assists', $this->getAssists());
1759
	}
1760
	private function computeRanking($dbField, $playerAmount) {
1761
		$this->db->query('SELECT count(*) FROM player
1762
			WHERE game_id = ' . $this->db->escapeNumber($this->getGameID()) . '
1763
			AND (
1764
				'.$dbField . ' > ' . $this->db->escapeNumber($playerAmount) . '
1765
				OR (
1766
					'.$dbField . ' = ' . $this->db->escapeNumber($playerAmount) . '
1767
					AND player_name <= ' . $this->db->escapeString($this->getPlayerName()) . '
1768
				)
1769
			)');
1770
		$this->db->nextRecord();
1771
		$rank = $this->db->getInt('count(*)');
1772
		return $rank;
1773
	}
1774
}
1775