We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.
| Total Complexity | 333 | 
| Total Lines | 1414 | 
| Duplicated Lines | 0 % | 
| Changes | 5 | ||
| Bugs | 1 | Features | 0 | 
Complex classes like AbstractSmrPlayer often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use AbstractSmrPlayer, and based on these observations, apply Extract Interface, too.
| 1 | <?php declare(strict_types=1); | ||
| 4 | abstract class AbstractSmrPlayer { | ||
| 5 | protected $db; | ||
| 6 | |||
| 7 | const HOF_CHANGED = 1; | ||
| 8 | const HOF_NEW = 2; | ||
| 9 | |||
| 10 | protected $accountID; | ||
| 11 | protected $gameID; | ||
| 12 | protected $playerName; // This is escaped with htmlentities in the db | ||
| 13 | protected $playerID; | ||
| 14 | protected $sectorID; | ||
| 15 | protected $lastSectorID; | ||
| 16 | protected $newbieTurns; | ||
| 17 | protected $dead; | ||
| 18 | protected $npc; | ||
| 19 | protected $newbieStatus; | ||
| 20 | protected $landedOnPlanet; | ||
| 21 | protected $lastActive; | ||
| 22 | protected $raceID; | ||
| 23 | protected $credits; | ||
| 24 | protected $alignment; | ||
| 25 | protected $experience; | ||
| 26 | protected $level; | ||
| 27 | protected $allianceID; | ||
| 28 | protected $shipID; | ||
| 29 | protected $kills; | ||
| 30 | protected $deaths; | ||
| 31 | protected $assists; | ||
| 32 | protected $stats; | ||
| 33 | protected $pureRelations; | ||
| 34 | protected $relations; | ||
| 35 | protected $militaryPayment; | ||
| 36 | protected $bounties; | ||
| 37 | protected $turns; | ||
| 38 | protected $lastCPLAction; | ||
| 39 | protected $missions; | ||
| 40 | |||
| 41 | protected $visitedSectors; | ||
| 42 | protected $allianceRoles = array( | ||
| 43 | 0 => 0 | ||
| 44 | ); | ||
| 45 | |||
| 46 | protected $draftLeader; | ||
| 47 | protected $gpWriter; | ||
| 48 | protected $HOF; | ||
| 49 | protected static $HOFVis; | ||
| 50 | |||
| 51 | protected $hasChanged = false; | ||
| 52 | protected $hasHOFChanged = false; | ||
| 53 | protected static $hasHOFVisChanged = array(); | ||
| 54 | protected $hasBountyChanged = array(); | ||
| 55 | |||
| 56 | 	protected function __construct() { | ||
| 57 | } | ||
| 58 | |||
| 59 | 	public function getAccountID() { | ||
| 60 | return $this->accountID; | ||
| 61 | } | ||
| 62 | |||
| 63 | 	public function getGameID() { | ||
| 64 | return $this->gameID; | ||
| 65 | } | ||
| 66 | |||
| 67 | 	public function getGame() { | ||
| 68 | return SmrGame::getGame($this->gameID); | ||
| 69 | } | ||
| 70 | |||
| 71 | 	public function getNewbieTurns() { | ||
| 72 | return $this->newbieTurns; | ||
| 73 | } | ||
| 74 | |||
| 75 | 	public function hasNewbieTurns() { | ||
| 76 | return $this->getNewbieTurns() > 0; | ||
| 77 | } | ||
| 78 | 	public function setNewbieTurns($newbieTurns) { | ||
| 79 | 		if ($this->newbieTurns == $newbieTurns) { | ||
| 80 | return; | ||
| 81 | } | ||
| 82 | $this->newbieTurns = $newbieTurns; | ||
| 83 | $this->hasChanged = true; | ||
| 84 | } | ||
| 85 | |||
| 86 | 	public function getShipTypeID() { | ||
| 88 | } | ||
| 89 | |||
| 90 | 	public function setShipTypeID($shipID) { | ||
| 91 | 		if ($this->shipID == $shipID) { | ||
| 92 | return; | ||
| 93 | } | ||
| 94 | $this->shipID = $shipID; | ||
| 95 | $this->hasChanged = true; | ||
| 96 | } | ||
| 97 | |||
| 98 | /** | ||
| 99 | * Get planet owned by this player. | ||
| 100 | * Returns false if this player does not own a planet. | ||
| 101 | */ | ||
| 102 | 	public function getPlanet() { | ||
| 103 | 		$this->db->query('SELECT * FROM planet WHERE game_id=' . $this->db->escapeNumber($this->getGameID()) . ' AND owner_id=' . $this->db->escapeNumber($this->getAccountID())); | ||
| 104 | 		if ($this->db->nextRecord()) { | ||
| 105 | 			return SmrPlanet::getPlanet($this->getGameID(), $this->db->getInt('sector_id'), false, $this->db); | ||
| 106 | 		} else { | ||
| 107 | return false; | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | 	public function getSectorPlanet() { | ||
| 112 | return SmrPlanet::getPlanet($this->getGameID(), $this->getSectorID()); | ||
| 113 | } | ||
| 114 | |||
| 115 | 	public function getSectorPort() { | ||
| 116 | return SmrPort::getPort($this->getGameID(), $this->getSectorID()); | ||
| 117 | } | ||
| 118 | |||
| 119 | 	public function getSectorID() { | ||
| 120 | return $this->sectorID; | ||
| 121 | } | ||
| 122 | |||
| 123 | 	public function getSector() { | ||
| 124 | return SmrSector::getSector($this->getGameID(), $this->getSectorID()); | ||
| 125 | } | ||
| 126 | |||
| 127 | 	public function setSectorID($sectorID) { | ||
| 128 | $this->lastSectorID = $this->getSectorID(); | ||
| 129 | 		$this->actionTaken('LeaveSector', array('Sector'=>$this->getSector())); | ||
| 130 | $this->sectorID = $sectorID; | ||
| 131 | 		$this->actionTaken('EnterSector', array('Sector'=>$this->getSector())); | ||
| 132 | $this->hasChanged = true; | ||
| 133 | } | ||
| 134 | |||
| 135 | 	public function getLastSectorID() { | ||
| 136 | return $this->lastSectorID; | ||
| 137 | } | ||
| 138 | |||
| 139 | 	public function isDead() { | ||
| 140 | return $this->dead; | ||
| 141 | } | ||
| 142 | |||
| 143 | 	public function isNPC() { | ||
| 144 | return $this->npc; | ||
| 145 | } | ||
| 146 | |||
| 147 | /** | ||
| 148 | * Does the player have Newbie status? | ||
| 149 | */ | ||
| 150 | 	public function hasNewbieStatus() { | ||
| 151 | return $this->newbieStatus; | ||
| 152 | } | ||
| 153 | |||
| 154 | /** | ||
| 155 | * Update the player's newbie status if it has changed. | ||
| 156 | * This function queries the account, so use sparingly. | ||
| 157 | */ | ||
| 158 | 	public function updateNewbieStatus() { | ||
| 159 | $accountNewbieStatus = !$this->getAccount()->isVeteran(); | ||
|  | |||
| 160 | 		if ($this->newbieStatus != $accountNewbieStatus) { | ||
| 161 | $this->newbieStatus = $accountNewbieStatus; | ||
| 162 | $this->hasChanged = true; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | 	public function isDraftLeader() { | ||
| 167 | 		if (!isset($this->draftLeader)) { | ||
| 168 | $this->draftLeader = false; | ||
| 169 | 			$this->db->query('SELECT 1 FROM draft_leaders WHERE ' . $this->SQL . ' LIMIT 1'); | ||
| 170 | 			if ($this->db->nextRecord()) { | ||
| 171 | $this->draftLeader = true; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | return $this->draftLeader; | ||
| 175 | } | ||
| 176 | |||
| 177 | 	public function getGPWriter() { | ||
| 178 | 		if (!isset($this->gpWriter)) { | ||
| 179 | $this->gpWriter = false; | ||
| 180 | 			$this->db->query('SELECT position FROM galactic_post_writer WHERE ' . $this->SQL); | ||
| 181 | 			if ($this->db->nextRecord()) { | ||
| 182 | 				$this->gpWriter = $this->db->getField('position'); | ||
| 183 | } | ||
| 184 | } | ||
| 185 | return $this->gpWriter; | ||
| 186 | } | ||
| 187 | |||
| 188 | 	public function isGPEditor() { | ||
| 189 | return $this->getGPWriter() == 'editor'; | ||
| 190 | } | ||
| 191 | |||
| 192 | 	public function getSafeAttackRating() { | ||
| 193 | return max(0, min(8, $this->getAlignment() / 150 + 4)); | ||
| 194 | } | ||
| 195 | |||
| 196 | 	public function hasFederalProtection() { | ||
| 197 | $sector = SmrSector::getSector($this->getGameID(), $this->getSectorID()); | ||
| 198 | 		if (!$sector->offersFederalProtection()) { | ||
| 199 | return false; | ||
| 200 | } | ||
| 201 | |||
| 202 | $ship = $this->getShip(); | ||
| 203 | 		if ($ship->hasIllegalGoods()) { | ||
| 204 | return false; | ||
| 205 | } | ||
| 206 | |||
| 207 | 		if ($ship->getAttackRating() <= $this->getSafeAttackRating()) { | ||
| 208 | 			foreach ($sector->getFedRaceIDs() as $fedRaceID) { | ||
| 209 | 				if ($this->canBeProtectedByRace($fedRaceID)) { | ||
| 210 | return true; | ||
| 211 | } | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | return false; | ||
| 216 | } | ||
| 217 | |||
| 218 | 	public function canBeProtectedByRace($raceID) { | ||
| 219 | 		if (!isset($this->canFed)) { | ||
| 220 | $this->canFed = array(); | ||
| 221 | $RACES = Globals::getRaces(); | ||
| 222 | 			foreach ($RACES as $raceID2 => $raceName) { | ||
| 223 | $this->canFed[$raceID2] = $this->getRelation($raceID2) >= ALIGN_FED_PROTECTION; | ||
| 224 | } | ||
| 225 | 			$this->db->query('SELECT race_id, allowed FROM player_can_fed | ||
| 226 | WHERE ' . $this->SQL . ' AND expiry > ' . $this->db->escapeNumber(TIME)); | ||
| 227 | 			while ($this->db->nextRecord()) { | ||
| 228 | 				$this->canFed[$this->db->getInt('race_id')] = $this->db->getBoolean('allowed'); | ||
| 229 | } | ||
| 230 | } | ||
| 231 | return $this->canFed[$raceID]; | ||
| 232 | } | ||
| 233 | |||
| 234 | /** | ||
| 235 | * Returns a boolean identifying if the player can currently | ||
| 236 | * participate in battles. | ||
| 237 | */ | ||
| 238 | 	public function canFight() { | ||
| 239 | return !($this->hasNewbieTurns() || | ||
| 240 | $this->isDead() || | ||
| 241 | $this->isLandedOnPlanet() || | ||
| 242 | $this->hasFederalProtection()); | ||
| 243 | } | ||
| 244 | |||
| 245 | 	public function setDead($bool) { | ||
| 246 | 		if ($this->dead == $bool) { | ||
| 247 | return; | ||
| 248 | } | ||
| 249 | $this->dead = $bool; | ||
| 250 | $this->hasChanged = true; | ||
| 251 | } | ||
| 252 | |||
| 253 | 	public function getKills() { | ||
| 254 | return $this->kills; | ||
| 255 | } | ||
| 256 | |||
| 257 | 	public function increaseKills($kills) { | ||
| 258 | 		if ($kills < 0) { | ||
| 259 | 			throw new Exception('Trying to increase negative kills.'); | ||
| 260 | } | ||
| 261 | $this->setKills($this->kills + $kills); | ||
| 262 | } | ||
| 263 | |||
| 264 | 	public function setKills($kills) { | ||
| 265 | 		if ($this->kills == $kills) { | ||
| 266 | return; | ||
| 267 | } | ||
| 268 | $this->kills = $kills; | ||
| 269 | $this->hasChanged = true; | ||
| 270 | } | ||
| 271 | |||
| 272 | 	public function getDeaths() { | ||
| 273 | return $this->deaths; | ||
| 274 | } | ||
| 275 | |||
| 276 | 	public function increaseDeaths($deaths) { | ||
| 277 | 		if ($deaths < 0) { | ||
| 278 | 			throw new Exception('Trying to increase negative deaths.'); | ||
| 279 | } | ||
| 280 | $this->setDeaths($this->getDeaths() + $deaths); | ||
| 281 | } | ||
| 282 | |||
| 283 | 	public function setDeaths($deaths) { | ||
| 284 | 		if ($this->deaths == $deaths) { | ||
| 285 | return; | ||
| 286 | } | ||
| 287 | $this->deaths = $deaths; | ||
| 288 | $this->hasChanged = true; | ||
| 289 | } | ||
| 290 | |||
| 291 | 	public function getAssists() { | ||
| 292 | return $this->assists; | ||
| 293 | } | ||
| 294 | |||
| 295 | 	public function increaseAssists($assists) { | ||
| 296 | 		if ($assists < 1) { | ||
| 297 | 			throw new Exception('Must increase by a positive number.'); | ||
| 298 | } | ||
| 299 | $this->assists += $assists; | ||
| 300 | $this->hasChanged = true; | ||
| 301 | } | ||
| 302 | |||
| 303 | 	public function getAlignment() { | ||
| 304 | return $this->alignment; | ||
| 305 | } | ||
| 306 | |||
| 307 | 	public function increaseAlignment($align) { | ||
| 308 | 		if ($align < 0) { | ||
| 309 | 			throw new Exception('Trying to increase negative align.'); | ||
| 310 | } | ||
| 311 | 		if ($align == 0) { | ||
| 312 | return; | ||
| 313 | } | ||
| 314 | $align += $this->alignment; | ||
| 315 | $this->setAlignment($align); | ||
| 316 | } | ||
| 317 | 	public function decreaseAlignment($align) { | ||
| 318 | 		if ($align < 0) { | ||
| 319 | 			throw new Exception('Trying to decrease negative align.'); | ||
| 320 | } | ||
| 321 | 		if ($align == 0) { | ||
| 322 | return; | ||
| 323 | } | ||
| 324 | $align = $this->alignment - $align; | ||
| 325 | $this->setAlignment($align); | ||
| 326 | } | ||
| 327 | 	public function setAlignment($align) { | ||
| 328 | 		if ($this->alignment == $align) { | ||
| 329 | return; | ||
| 330 | } | ||
| 331 | $this->alignment = $align; | ||
| 332 | $this->hasChanged = true; | ||
| 333 | } | ||
| 334 | |||
| 335 | 	public function getCredits() { | ||
| 336 | return $this->credits; | ||
| 337 | } | ||
| 338 | |||
| 339 | 	public function getExperience() { | ||
| 340 | return $this->experience; | ||
| 341 | } | ||
| 342 | |||
| 343 | /** | ||
| 344 | * Returns the percent progress towards the next level. | ||
| 345 | * This value is rounded because it is used primarily in HTML img widths. | ||
| 346 | */ | ||
| 347 | 	public function getNextLevelPercentAcquired() : int { | ||
| 348 | 		if ($this->getNextLevelExperience() == $this->getThisLevelExperience()) { | ||
| 349 | return 100; | ||
| 350 | } | ||
| 351 | return max(0, min(100, IRound(($this->getExperience() - $this->getThisLevelExperience()) / ($this->getNextLevelExperience() - $this->getThisLevelExperience()) * 100))); | ||
| 352 | } | ||
| 353 | |||
| 354 | 	public function getNextLevelPercentRemaining() { | ||
| 355 | return 100 - $this->getNextLevelPercentAcquired(); | ||
| 356 | } | ||
| 357 | |||
| 358 | 	public function getNextLevelExperience() { | ||
| 364 | } | ||
| 365 | |||
| 366 | 	public function getThisLevelExperience() { | ||
| 367 | $LEVELS_REQUIREMENTS = Globals::getLevelRequirements(); | ||
| 368 | return $LEVELS_REQUIREMENTS[$this->getLevelID()]['Requirement']; | ||
| 369 | } | ||
| 370 | |||
| 371 | 	public function setExperience($experience) { | ||
| 372 | 		if ($this->experience == $experience) { | ||
| 373 | return; | ||
| 374 | } | ||
| 375 | 		if ($experience < MIN_EXPERIENCE) { | ||
| 376 | $experience = MIN_EXPERIENCE; | ||
| 377 | } | ||
| 378 | 		if ($experience > MAX_EXPERIENCE) { | ||
| 379 | $experience = MAX_EXPERIENCE; | ||
| 380 | } | ||
| 381 | $this->experience = $experience; | ||
| 382 | $this->hasChanged = true; | ||
| 383 | |||
| 384 | // Since exp has changed, invalidate the player level so that it can | ||
| 385 | // be recomputed next time it is queried (in case it has changed). | ||
| 386 | $this->level = null; | ||
| 387 | } | ||
| 388 | |||
| 389 | 	public function increaseCredits($credits) { | ||
| 390 | 		if ($credits < 0) { | ||
| 391 | 			throw new Exception('Trying to increase negative credits.'); | ||
| 392 | } | ||
| 393 | 		if ($credits == 0) { | ||
| 394 | return; | ||
| 395 | } | ||
| 396 | $credits += $this->credits; | ||
| 397 | $this->setCredits($credits); | ||
| 398 | } | ||
| 399 | 	public function decreaseCredits($credits) { | ||
| 400 | 		if ($credits < 0) { | ||
| 401 | 			throw new Exception('Trying to decrease negative credits.'); | ||
| 402 | } | ||
| 403 | 		if ($credits == 0) { | ||
| 404 | return; | ||
| 405 | } | ||
| 406 | $credits = $this->credits - $credits; | ||
| 407 | $this->setCredits($credits); | ||
| 408 | } | ||
| 409 | 	public function setCredits($credits) { | ||
| 410 | 		if ($this->credits == $credits) { | ||
| 411 | return; | ||
| 412 | } | ||
| 413 | 		if ($credits < 0) { | ||
| 414 | 			throw new Exception('Trying to set negative credits.'); | ||
| 415 | } | ||
| 416 | 		if ($credits > MAX_MONEY) { | ||
| 417 | $credits = MAX_MONEY; | ||
| 418 | } | ||
| 419 | $this->credits = $credits; | ||
| 420 | $this->hasChanged = true; | ||
| 421 | } | ||
| 422 | |||
| 423 | 	public function increaseExperience($experience) { | ||
| 433 | } | ||
| 434 | 	public function decreaseExperience($experience) { | ||
| 435 | 		if ($experience < 0) { | ||
| 436 | 			throw new Exception('Trying to decrease negative experience.'); | ||
| 437 | } | ||
| 438 | 		if ($experience == 0) { | ||
| 439 | return; | ||
| 440 | } | ||
| 441 | $newExperience = $this->experience - $experience; | ||
| 442 | $this->setExperience($newExperience); | ||
| 443 | 		$this->decreaseHOF($experience, array('Experience', 'Total', 'Loss'), HOF_PUBLIC); | ||
| 444 | } | ||
| 445 | |||
| 446 | 	public function isLandedOnPlanet() { | ||
| 447 | return $this->landedOnPlanet; | ||
| 448 | } | ||
| 449 | |||
| 450 | 	public function setLandedOnPlanet($bool) { | ||
| 451 | 		if ($this->landedOnPlanet == $bool) { | ||
| 452 | return; | ||
| 453 | } | ||
| 454 | $this->landedOnPlanet = $bool; | ||
| 455 | $this->hasChanged = true; | ||
| 456 | } | ||
| 457 | |||
| 458 | /** | ||
| 459 | * Returns the numerical level of the player (e.g. 1-50). | ||
| 460 | */ | ||
| 461 | 	public function getLevelID() { | ||
| 462 | // The level is cached for performance reasons unless `setExperience` | ||
| 463 | // is called and the player's experience changes. | ||
| 464 | 		if ($this->level === null) { | ||
| 465 | $LEVELS_REQUIREMENTS = Globals::getLevelRequirements(); | ||
| 466 | 			foreach ($LEVELS_REQUIREMENTS as $level_id => $require) { | ||
| 467 | 				if ($this->getExperience() >= $require['Requirement']) { | ||
| 468 | continue; | ||
| 469 | } | ||
| 470 | $this->level = $level_id - 1; | ||
| 471 | return $this->level; | ||
| 472 | } | ||
| 473 | $this->level = max(array_keys($LEVELS_REQUIREMENTS)); | ||
| 474 | } | ||
| 475 | return $this->level; | ||
| 476 | } | ||
| 477 | |||
| 478 | 	public function getLevelName() { | ||
| 479 | $level_name = Globals::getLevelRequirements()[$this->getLevelID()]['Name']; | ||
| 480 | 		if ($this->isPresident()) { | ||
| 481 | $level_name = '<img src="images/council_president.png" title="' . Globals::getRaceName($this->getRaceID()) . ' President" height="12" width="16" /> ' . $level_name; | ||
| 482 | } | ||
| 483 | return $level_name; | ||
| 484 | } | ||
| 485 | |||
| 486 | 	public function getMaxLevel() { | ||
| 487 | return max(array_keys(Globals::getLevelRequirements())); | ||
| 488 | } | ||
| 489 | |||
| 490 | 	public function getPlayerID() { | ||
| 491 | return $this->playerID; | ||
| 492 | } | ||
| 493 | |||
| 494 | 	public function getPlayerName() { | ||
| 495 | return $this->playerName; | ||
| 496 | } | ||
| 497 | |||
| 498 | 	public function setPlayerName($name) { | ||
| 499 | $this->playerName = $name; | ||
| 500 | $this->hasChanged = true; | ||
| 501 | } | ||
| 502 | |||
| 503 | 	public function getDisplayName($includeAlliance = false) { | ||
| 504 | 		$return = get_colored_text($this->getAlignment(), $this->playerName . ' (' . $this->getPlayerID() . ')'); | ||
| 505 | 		if ($this->isNPC()) { | ||
| 506 | $return .= ' <span class="npcColour">[NPC]</span>'; | ||
| 507 | } | ||
| 508 | 		if ($includeAlliance) { | ||
| 509 | 			$return .= ' (' . $this->getAllianceDisplayName() . ')'; | ||
| 510 | } | ||
| 511 | return $return; | ||
| 512 | } | ||
| 513 | |||
| 514 | 	public function getBBLink() { | ||
| 515 | return '[player=' . $this->getPlayerID() . ']'; | ||
| 516 | } | ||
| 517 | |||
| 518 | 	public function getLinkedDisplayName($includeAlliance = true) { | ||
| 519 | $return = '<a href="' . $this->getTraderSearchHREF() . '">' . $this->getDisplayName() . '</a>'; | ||
| 520 | 		if ($includeAlliance) { | ||
| 521 | 			$return .= ' (' . $this->getAllianceDisplayName(true) . ')'; | ||
| 522 | } | ||
| 523 | return $return; | ||
| 524 | } | ||
| 525 | |||
| 526 | 	public function getRaceID() { | ||
| 527 | return $this->raceID; | ||
| 528 | } | ||
| 529 | |||
| 530 | 	public function getRaceName() { | ||
| 532 | } | ||
| 533 | |||
| 534 | 	public static function getColouredRaceNameOrDefault($otherRaceID, AbstractSmrPlayer $player = null, $linked = false) { | ||
| 535 | $relations = 0; | ||
| 536 | 		if ($player !== null) { | ||
| 537 | $relations = $player->getRelation($otherRaceID); | ||
| 538 | } | ||
| 539 | return Globals::getColouredRaceName($otherRaceID, $relations, $linked); | ||
| 540 | } | ||
| 541 | |||
| 542 | 	public function getColouredRaceName($otherRaceID, $linked = false) { | ||
| 543 | return self::getColouredRaceNameOrDefault($otherRaceID, $this, $linked); | ||
| 544 | } | ||
| 545 | |||
| 546 | 	public function setRaceID($raceID) { | ||
| 547 | 		if ($this->raceID == $raceID) { | ||
| 548 | return; | ||
| 549 | } | ||
| 550 | $this->raceID = $raceID; | ||
| 551 | $this->hasChanged = true; | ||
| 552 | } | ||
| 553 | |||
| 554 | 	public function isAllianceLeader($forceUpdate = false) { | ||
| 555 | return $this->getAccountID() == $this->getAlliance($forceUpdate)->getLeaderID(); | ||
| 556 | } | ||
| 557 | |||
| 558 | 	public function getAlliance($forceUpdate = false) { | ||
| 559 | return SmrAlliance::getAlliance($this->getAllianceID(), $this->getGameID(), $forceUpdate); | ||
| 560 | } | ||
| 561 | |||
| 562 | 	public function getAllianceID() { | ||
| 563 | return $this->allianceID; | ||
| 564 | } | ||
| 565 | |||
| 566 | 	public function hasAlliance() { | ||
| 567 | return $this->getAllianceID() != 0; | ||
| 568 | } | ||
| 569 | |||
| 570 | 	protected function setAllianceID($ID) { | ||
| 571 | 		if ($this->allianceID == $ID) { | ||
| 572 | return; | ||
| 573 | } | ||
| 574 | $this->allianceID = $ID; | ||
| 575 | 		if ($this->allianceID != 0) { | ||
| 576 | $status = $this->hasNewbieStatus() ? 'NEWBIE' : 'VETERAN'; | ||
| 577 | 			$this->db->query('INSERT IGNORE INTO player_joined_alliance (account_id,game_id,alliance_id,status) ' . | ||
| 578 | 				'VALUES (' . $this->db->escapeNumber($this->getAccountID()) . ',' . $this->db->escapeNumber($this->getGameID()) . ',' . $this->db->escapeNumber($this->getAllianceID()) . ',' . $this->db->escapeString($status) . ')'); | ||
| 579 | } | ||
| 580 | $this->hasChanged = true; | ||
| 581 | } | ||
| 582 | |||
| 583 | 	public function getAllianceBBLink() { | ||
| 584 | return $this->hasAlliance() ? $this->getAlliance()->getAllianceBBLink() : $this->getAllianceDisplayName(); | ||
| 585 | } | ||
| 586 | |||
| 587 | 	public function getAllianceDisplayName($linked = false, $includeAllianceID = false) { | ||
| 588 | 		if ($this->hasAlliance()) { | ||
| 589 | return $this->getAlliance()->getAllianceDisplayName($linked, $includeAllianceID); | ||
| 590 | 		} else { | ||
| 591 | return 'No Alliance'; | ||
| 592 | } | ||
| 593 | } | ||
| 594 | |||
| 595 | 	public function getAllianceRole($allianceID = false) { | ||
| 596 | 		if ($allianceID === false) { | ||
| 597 | $allianceID = $this->getAllianceID(); | ||
| 598 | } | ||
| 599 | 		if (!isset($this->allianceRoles[$allianceID])) { | ||
| 600 | $this->allianceRoles[$allianceID] = 0; | ||
| 601 | 			$this->db->query('SELECT role_id | ||
| 602 | FROM player_has_alliance_role | ||
| 603 | WHERE ' . $this->SQL . ' | ||
| 604 | AND alliance_id=' . $this->db->escapeNumber($allianceID) . ' | ||
| 605 | LIMIT 1'); | ||
| 606 | 			if ($this->db->nextRecord()) { | ||
| 607 | 				$this->allianceRoles[$allianceID] = $this->db->getInt('role_id'); | ||
| 608 | } | ||
| 609 | } | ||
| 610 | return $this->allianceRoles[$allianceID]; | ||
| 611 | } | ||
| 612 | |||
| 613 | 	public function isCombatDronesKamikazeOnMines() { | ||
| 614 | return $this->combatDronesKamikazeOnMines; | ||
| 615 | } | ||
| 616 | |||
| 617 | 	public function setCombatDronesKamikazeOnMines($bool) { | ||
| 618 | 		if ($this->combatDronesKamikazeOnMines == $bool) { | ||
| 619 | return; | ||
| 620 | } | ||
| 621 | $this->combatDronesKamikazeOnMines = $bool; | ||
| 622 | $this->hasChanged = true; | ||
| 623 | } | ||
| 624 | |||
| 625 | protected abstract function getPureRelationsData(); | ||
| 626 | |||
| 627 | 	public function getPureRelations() { | ||
| 628 | $this->getPureRelationsData(); | ||
| 629 | return $this->pureRelations; | ||
| 630 | } | ||
| 631 | |||
| 632 | /** | ||
| 633 | * Get personal relations with a race | ||
| 634 | */ | ||
| 635 | 	public function getPureRelation($raceID) { | ||
| 636 | $rels = $this->getPureRelations(); | ||
| 637 | return $rels[$raceID]; | ||
| 638 | } | ||
| 639 | |||
| 640 | 	public function getRelations() { | ||
| 641 | 		if (!isset($this->relations)) { | ||
| 642 | //get relations | ||
| 643 | $RACES = Globals::getRaces(); | ||
| 644 | $raceRelations = Globals::getRaceRelations($this->getGameID(), $this->getRaceID()); | ||
| 645 | $pureRels = $this->getPureRelations(); // make sure they're initialised. | ||
| 646 | $this->relations = array(); | ||
| 647 | 			foreach ($RACES as $raceID => $raceName) { | ||
| 648 | $this->relations[$raceID] = $pureRels[$raceID] + $raceRelations[$raceID]; | ||
| 649 | } | ||
| 650 | } | ||
| 651 | return $this->relations; | ||
| 652 | } | ||
| 653 | |||
| 654 | /** | ||
| 655 | * Get total relations with a race (personal + political) | ||
| 656 | */ | ||
| 657 | 	public function getRelation($raceID) { | ||
| 658 | $rels = $this->getRelations(); | ||
| 659 | return $rels[$raceID]; | ||
| 660 | } | ||
| 661 | |||
| 662 | abstract public function getShip(); | ||
| 663 | |||
| 664 | 	public function &shootPlayer(AbstractSmrPlayer $targetPlayer) { | ||
| 665 | return $this->getShip()->shootPlayer($targetPlayer); | ||
| 666 | } | ||
| 667 | |||
| 668 | 	public function &shootForces(SmrForce $forces) { | ||
| 669 | return $this->getShip()->shootForces($forces); | ||
| 670 | } | ||
| 671 | |||
| 672 | 	public function &shootPort(SmrPort $port) { | ||
| 673 | return $this->getShip()->shootPort($port); | ||
| 674 | } | ||
| 675 | |||
| 676 | 	public function &shootPlanet(SmrPlanet $planet, $delayed) { | ||
| 677 | return $this->getShip()->shootPlanet($planet, $delayed); | ||
| 678 | } | ||
| 679 | |||
| 680 | 	public function &shootPlayers(array $targetPlayers) { | ||
| 681 | return $this->getShip()->shootPlayers($targetPlayers); | ||
| 682 | } | ||
| 683 | |||
| 684 | 	public function getMilitaryPayment() { | ||
| 685 | return $this->militaryPayment; | ||
| 686 | } | ||
| 687 | |||
| 688 | 	public function hasMilitaryPayment() { | ||
| 690 | } | ||
| 691 | |||
| 692 | 	public function setMilitaryPayment($amount) { | ||
| 698 | } | ||
| 699 | |||
| 700 | 	public function increaseMilitaryPayment($amount) { | ||
| 701 | 		if ($amount < 0) { | ||
| 702 | 			throw new Exception('Trying to increase negative military payment.'); | ||
| 703 | } | ||
| 704 | $this->setMilitaryPayment($this->getMilitaryPayment() + $amount); | ||
| 705 | } | ||
| 706 | |||
| 707 | 	public function decreaseMilitaryPayment($amount) { | ||
| 708 | 		if ($amount < 0) { | ||
| 709 | 			throw new Exception('Trying to decrease negative military payment.'); | ||
| 710 | } | ||
| 711 | $this->setMilitaryPayment($this->getMilitaryPayment() - $amount); | ||
| 712 | } | ||
| 713 | |||
| 714 | abstract protected function getBountiesData(); | ||
| 715 | |||
| 716 | 	public function getBounties() : array { | ||
| 719 | } | ||
| 720 | |||
| 721 | 	public function hasBounties() : bool { | ||
| 723 | } | ||
| 724 | |||
| 725 | 	protected function getBounty(int $bountyID) : array { | ||
| 726 | 		if (!$this->hasBounty($bountyID)) { | ||
| 727 | 			throw new Exception('BountyID does not exist: ' . $bountyID); | ||
| 728 | } | ||
| 729 | return $this->bounties[$bountyID]; | ||
| 730 | } | ||
| 731 | |||
| 732 | 	public function hasBounty(int $bountyID) : bool { | ||
| 733 | $bounties = $this->getBounties(); | ||
| 734 | return isset($bounties[$bountyID]); | ||
| 735 | } | ||
| 736 | |||
| 737 | 	protected function getBountyAmount(int $bountyID) : int { | ||
| 738 | $bounty = $this->getBounty($bountyID); | ||
| 739 | return $bounty['Amount']; | ||
| 740 | } | ||
| 741 | |||
| 742 | 	protected function createBounty(string $type) : array { | ||
| 743 | 		$bounty = array('Amount' => 0, | ||
| 744 | 'SmrCredits' => 0, | ||
| 745 | 'Type' => $type, | ||
| 746 | 'Claimer' => 0, | ||
| 747 | 'Time' => TIME, | ||
| 748 | 'ID' => $this->getNextBountyID(), | ||
| 752 | } | ||
| 753 | |||
| 754 | 	protected function getNextBountyID() : int { | ||
| 755 | $keys = array_keys($this->getBounties()); | ||
| 756 | 		if (count($keys) > 0) { | ||
| 757 | return max($keys) + 1; | ||
| 758 | 		} else { | ||
| 759 | return 0; | ||
| 760 | } | ||
| 761 | } | ||
| 762 | |||
| 763 | 	protected function setBounty(array $bounty) : void { | ||
| 766 | } | ||
| 767 | |||
| 768 | 	protected function setBountyAmount(int $bountyID, int $amount) : void { | ||
| 769 | $bounty = $this->getBounty($bountyID); | ||
| 772 | } | ||
| 773 | |||
| 774 | 	public function getCurrentBounty(string $type) : array { | ||
| 775 | $bounties = $this->getBounties(); | ||
| 776 | 		foreach ($bounties as $bounty) { | ||
| 777 | 			if ($bounty['Claimer'] == 0 && $bounty['Type'] == $type) { | ||
| 778 | return $bounty; | ||
| 779 | } | ||
| 780 | } | ||
| 781 | return $this->createBounty($type); | ||
| 782 | } | ||
| 783 | |||
| 784 | 	public function hasCurrentBounty(string $type) : bool { | ||
| 785 | $bounties = $this->getBounties(); | ||
| 786 | 		foreach ($bounties as $bounty) { | ||
| 787 | 			if ($bounty['Claimer'] == 0 && $bounty['Type'] == $type) { | ||
| 788 | return true; | ||
| 789 | } | ||
| 790 | } | ||
| 791 | return false; | ||
| 792 | } | ||
| 793 | |||
| 794 | 	protected function getCurrentBountyAmount(string $type) : int { | ||
| 795 | $bounty = $this->getCurrentBounty($type); | ||
| 796 | return $bounty['Amount']; | ||
| 797 | } | ||
| 798 | |||
| 799 | 	protected function setCurrentBountyAmount(string $type, int $amount) : void { | ||
| 800 | $bounty = $this->getCurrentBounty($type); | ||
| 801 | 		if ($bounty['Amount'] == $amount) { | ||
| 802 | return; | ||
| 803 | } | ||
| 804 | $bounty['Amount'] = $amount; | ||
| 805 | $this->setBounty($bounty); | ||
| 806 | } | ||
| 807 | |||
| 808 | 	public function increaseCurrentBountyAmount(string $type, int $amount) : void { | ||
| 809 | 		if ($amount < 0) { | ||
| 810 | 			throw new Exception('Trying to increase negative current bounty.'); | ||
| 811 | } | ||
| 812 | $this->setCurrentBountyAmount($type, $this->getCurrentBountyAmount($type) + $amount); | ||
| 813 | } | ||
| 814 | |||
| 815 | 	public function decreaseCurrentBountyAmount(string $type, int $amount) : void { | ||
| 816 | 		if ($amount < 0) { | ||
| 817 | 			throw new Exception('Trying to decrease negative current bounty.'); | ||
| 818 | } | ||
| 819 | $this->setCurrentBountyAmount($type, $this->getCurrentBountyAmount($type) - $amount); | ||
| 820 | } | ||
| 821 | |||
| 822 | 	protected function getCurrentBountySmrCredits(string $type) : int { | ||
| 823 | $bounty = $this->getCurrentBounty($type); | ||
| 824 | return $bounty['SmrCredits']; | ||
| 825 | } | ||
| 826 | |||
| 827 | 	protected function setCurrentBountySmrCredits(string $type, int $credits) : void { | ||
| 828 | $bounty = $this->getCurrentBounty($type); | ||
| 829 | 		if ($bounty['SmrCredits'] == $credits) { | ||
| 830 | return; | ||
| 831 | } | ||
| 832 | $bounty['SmrCredits'] = $credits; | ||
| 833 | $this->setBounty($bounty); | ||
| 834 | } | ||
| 835 | |||
| 836 | 	public function increaseCurrentBountySmrCredits(string $type, int $credits) : void { | ||
| 837 | 		if ($credits < 0) { | ||
| 838 | 			throw new Exception('Trying to increase negative current bounty.'); | ||
| 839 | } | ||
| 840 | $this->setCurrentBountySmrCredits($type, $this->getCurrentBountySmrCredits($type) + $credits); | ||
| 841 | } | ||
| 842 | |||
| 843 | 	public function decreaseCurrentBountySmrCredits(string $type, int $credits) : void { | ||
| 844 | 		if ($credits < 0) { | ||
| 845 | 			throw new Exception('Trying to decrease negative current bounty.'); | ||
| 846 | } | ||
| 847 | $this->setCurrentBountySmrCredits($type, $this->getCurrentBountySmrCredits($type) - $credits); | ||
| 848 | } | ||
| 849 | |||
| 850 | 	public function setBountiesClaimable(AbstractSmrPlayer $claimer) : void { | ||
| 851 | 		foreach ($this->getBounties() as $bounty) { | ||
| 852 | 			if ($bounty['Claimer'] == 0) { | ||
| 853 | $bounty['Claimer'] = $claimer->getAccountID(); | ||
| 854 | $this->setBounty($bounty); | ||
| 855 | } | ||
| 856 | } | ||
| 857 | } | ||
| 858 | |||
| 859 | |||
| 860 | abstract protected function getHOFData(); | ||
| 861 | |||
| 862 | 	public function getHOF(array $typeList = null) { | ||
| 863 | $this->getHOFData(); | ||
| 864 | 		if ($typeList == null) { | ||
| 865 | return $this->HOF; | ||
| 866 | } | ||
| 867 | $hof = $this->HOF; | ||
| 868 | 		foreach ($typeList as $type) { | ||
| 869 | 			if (!isset($hof[$type])) { | ||
| 870 | return 0; | ||
| 871 | } | ||
| 872 | $hof = $hof[$type]; | ||
| 873 | } | ||
| 874 | return $hof; | ||
| 875 | } | ||
| 876 | |||
| 877 | 	public function increaseHOF($amount, array $typeList, $visibility) { | ||
| 878 | 		if ($amount < 0) { | ||
| 879 | 			throw new Exception('Trying to increase negative HOF: ' . implode(':', $typeList)); | ||
| 880 | } | ||
| 881 | 		if ($amount == 0) { | ||
| 882 | return; | ||
| 883 | } | ||
| 884 | $this->setHOF($this->getHOF($typeList) + $amount, $typeList, $visibility); | ||
| 885 | } | ||
| 886 | |||
| 887 | 	public function decreaseHOF($amount, array $typeList, $visibility) { | ||
| 888 | 		if ($amount < 0) { | ||
| 889 | 			throw new Exception('Trying to decrease negative HOF: ' . implode(':', $typeList)); | ||
| 890 | } | ||
| 891 | 		if ($amount == 0) { | ||
| 892 | return; | ||
| 893 | } | ||
| 894 | $this->setHOF($this->getHOF($typeList) - $amount, $typeList, $visibility); | ||
| 895 | } | ||
| 896 | |||
| 897 | 	public function setHOF($amount, array $typeList, $visibility) { | ||
| 898 | 		if (is_array($this->getHOF($typeList))) { | ||
| 899 | 			throw new Exception('Trying to overwrite a HOF type: ' . implode(':', $typeList)); | ||
| 900 | } | ||
| 901 | 		if ($this->isNPC()) { | ||
| 902 | // Don't store HOF for NPCs. | ||
| 903 | return; | ||
| 904 | } | ||
| 905 | 		if ($this->getHOF($typeList) == $amount) { | ||
| 906 | return; | ||
| 907 | } | ||
| 908 | 		if ($amount < 0) { | ||
| 909 | $amount = 0; | ||
| 910 | } | ||
| 911 | $this->getHOF(); | ||
| 912 | |||
| 913 | 		$hofType = implode(':', $typeList); | ||
| 914 | 		if (!isset(self::$HOFVis[$hofType])) { | ||
| 915 | self::$hasHOFVisChanged[$hofType] = self::HOF_NEW; | ||
| 916 | 		} elseif (self::$HOFVis[$hofType] != $visibility) { | ||
| 917 | self::$hasHOFVisChanged[$hofType] = self::HOF_CHANGED; | ||
| 918 | } | ||
| 919 | self::$HOFVis[$hofType] = $visibility; | ||
| 920 | |||
| 921 | $hof =& $this->HOF; | ||
| 922 | $hofChanged =& $this->hasHOFChanged; | ||
| 923 | $new = false; | ||
| 924 | 		foreach ($typeList as $type) { | ||
| 925 | 			if (!isset($hofChanged[$type])) { | ||
| 926 | $hofChanged[$type] = array(); | ||
| 927 | } | ||
| 928 | 			if (!isset($hof[$type])) { | ||
| 929 | $hof[$type] = array(); | ||
| 930 | $new = true; | ||
| 931 | } | ||
| 932 | $hof =& $hof[$type]; | ||
| 933 | $hofChanged =& $hofChanged[$type]; | ||
| 934 | } | ||
| 935 | 		if ($hofChanged == null) { | ||
| 936 | $hofChanged = self::HOF_CHANGED; | ||
| 937 | 			if ($new) { | ||
| 938 | $hofChanged = self::HOF_NEW; | ||
| 939 | } | ||
| 940 | } | ||
| 941 | $hof = $amount; | ||
| 942 | } | ||
| 943 | |||
| 944 | abstract public function killPlayer($sectorID); | ||
| 945 | abstract public function &killPlayerByPlayer(AbstractSmrPlayer $killer); | ||
| 946 | abstract public function &killPlayerByForces(SmrForce $forces); | ||
| 947 | abstract public function &killPlayerByPort(SmrPort $port); | ||
| 948 | abstract public function &killPlayerByPlanet(SmrPlanet $planet); | ||
| 949 | |||
| 950 | |||
| 951 | 	public function getTurns() { | ||
| 952 | return $this->turns; | ||
| 953 | } | ||
| 954 | |||
| 955 | 	public function hasTurns() { | ||
| 956 | return $this->turns > 0; | ||
| 957 | } | ||
| 958 | |||
| 959 | 	public function getMaxTurns() { | ||
| 960 | return $this->getGame()->getMaxTurns(); | ||
| 961 | } | ||
| 962 | |||
| 963 | 	public function setTurns($turns) { | ||
| 964 | 		if ($this->turns == $turns) { | ||
| 965 | return; | ||
| 966 | } | ||
| 967 | // Make sure turns are in range [0, MaxTurns] | ||
| 968 | $this->turns = max(0, min($turns, $this->getMaxTurns())); | ||
| 969 | $this->hasChanged = true; | ||
| 970 | } | ||
| 971 | |||
| 972 | 	public function takeTurns($take, $takeNewbie = 0) { | ||
| 973 | 		if ($take < 0 || $takeNewbie < 0) { | ||
| 974 | 			throw new Exception('Trying to take negative turns.'); | ||
| 975 | } | ||
| 976 | $take = ICeil($take); | ||
| 977 | // Only take up to as many newbie turns as we have remaining | ||
| 978 | $takeNewbie = min($this->getNewbieTurns(), $takeNewbie); | ||
| 979 | |||
| 980 | $this->setTurns($this->getTurns() - $take); | ||
| 981 | $this->setNewbieTurns($this->getNewbieTurns() - $takeNewbie); | ||
| 982 | 		$this->increaseHOF($take, array('Movement', 'Turns Used', 'Since Last Death'), HOF_ALLIANCE); | ||
| 983 | 		$this->increaseHOF($take, array('Movement', 'Turns Used', 'Total'), HOF_ALLIANCE); | ||
| 984 | 		$this->increaseHOF($takeNewbie, array('Movement', 'Turns Used', 'Newbie'), HOF_ALLIANCE); | ||
| 985 | |||
| 986 | // Player has taken an action | ||
| 987 | $this->setLastActive(TIME); | ||
| 988 | $this->updateLastCPLAction(); | ||
| 989 | } | ||
| 990 | |||
| 991 | 	public function giveTurns(int $give, $giveNewbie = 0) { | ||
| 992 | 		if ($give < 0 || $giveNewbie < 0) { | ||
| 993 | 			throw new Exception('Trying to give negative turns.'); | ||
| 994 | } | ||
| 995 | $this->setTurns($this->getTurns() + $give); | ||
| 996 | $this->setNewbieTurns($this->getNewbieTurns() + $giveNewbie); | ||
| 997 | } | ||
| 998 | |||
| 999 | 	public function getLastActive() { | ||
| 1000 | return $this->lastActive; | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | 	public function setLastActive($lastActive) { | ||
| 1004 | 		if ($this->lastActive == $lastActive) { | ||
| 1005 | return; | ||
| 1006 | } | ||
| 1007 | $this->lastActive = $lastActive; | ||
| 1008 | $this->hasChanged = true; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | 	public function getLastCPLAction() { | ||
| 1012 | return $this->lastCPLAction; | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | 	public function setLastCPLAction($time) { | ||
| 1016 | 		if ($this->lastCPLAction == $time) { | ||
| 1017 | return; | ||
| 1018 | } | ||
| 1019 | $this->lastCPLAction = $time; | ||
| 1020 | $this->hasChanged = true; | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | 	public function updateLastCPLAction() { | ||
| 1024 | $this->setLastCPLAction(TIME); | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | 	public function getMissions() { | ||
| 1028 | 		if (!isset($this->missions)) { | ||
| 1029 | 			$this->db->query('SELECT * FROM player_has_mission WHERE ' . $this->SQL); | ||
| 1030 | $this->missions = array(); | ||
| 1031 | 			while ($this->db->nextRecord()) { | ||
| 1032 | 				$missionID = $this->db->getInt('mission_id'); | ||
| 1033 | $this->missions[$missionID] = array( | ||
| 1034 | 					'On Step' => $this->db->getInt('on_step'), | ||
| 1035 | 					'Progress' => $this->db->getInt('progress'), | ||
| 1036 | 					'Unread' => $this->db->getBoolean('unread'), | ||
| 1037 | 					'Expires' => $this->db->getInt('step_fails'), | ||
| 1038 | 					'Sector' => $this->db->getInt('mission_sector'), | ||
| 1039 | 					'Starting Sector' => $this->db->getInt('starting_sector') | ||
| 1040 | ); | ||
| 1041 | $this->rebuildMission($missionID); | ||
| 1042 | } | ||
| 1043 | } | ||
| 1044 | return $this->missions; | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | 	public function getActiveMissions() { | ||
| 1048 | $missions = $this->getMissions(); | ||
| 1049 | 		foreach ($missions as $missionID => $mission) { | ||
| 1050 | 			if ($mission['On Step'] >= count(MISSIONS[$missionID]['Steps'])) { | ||
| 1051 | unset($missions[$missionID]); | ||
| 1052 | } | ||
| 1053 | } | ||
| 1054 | return $missions; | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | 	protected function getMission($missionID) { | ||
| 1058 | $missions = $this->getMissions(); | ||
| 1059 | 		if (isset($missions[$missionID])) { | ||
| 1060 | return $missions[$missionID]; | ||
| 1061 | } | ||
| 1062 | return false; | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | 	protected function hasMission($missionID) { | ||
| 1066 | return $this->getMission($missionID) !== false; | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | 	protected function updateMission($missionID) { | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | 	private function setupMissionStep($missionID) { | ||
| 1089 | $mission =& $this->missions[$missionID]; | ||
| 1090 | 		if ($mission['On Step'] >= count(MISSIONS[$missionID]['Steps'])) { | ||
| 1091 | // Nothing to do if this mission is already completed | ||
| 1092 | return; | ||
| 1093 | } | ||
| 1094 | $step = MISSIONS[$missionID]['Steps'][$mission['On Step']]; | ||
| 1095 | 		if (isset($step['PickSector'])) { | ||
| 1096 | $realX = Plotter::getX($step['PickSector']['Type'], $step['PickSector']['X'], $this->getGameID()); | ||
| 1097 | 			if ($realX === false) { | ||
| 1098 | 				throw new Exception('Invalid PickSector definition in mission: ' . $missionID); | ||
| 1099 | } | ||
| 1100 | $path = Plotter::findDistanceToX($realX, $this->getSector(), true, null, $this); | ||
| 1101 | 			if ($path === false) { | ||
| 1102 | 				throw new Exception('Cannot find location: ' . $missionID); | ||
| 1103 | } | ||
| 1104 | $mission['Sector'] = $path->getEndSectorID(); | ||
| 1105 | } | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | /** | ||
| 1109 | * Declining a mission will permanently hide it from the player | ||
| 1110 | * by adding it in its completed state. | ||
| 1111 | */ | ||
| 1112 | 	public function declineMission($missionID) { | ||
| 1113 | $finishedStep = count(MISSIONS[$missionID]['Steps']); | ||
| 1114 | $this->addMission($missionID, $finishedStep); | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | 	public function addMission($missionID, $step = 0) { | ||
| 1118 | $this->getMissions(); | ||
| 1119 | |||
| 1120 | 		if (isset($this->missions[$missionID])) { | ||
| 1121 | return; | ||
| 1122 | } | ||
| 1123 | $sector = 0; | ||
| 1124 | |||
| 1125 | $mission = array( | ||
| 1126 | 'On Step' => $step, | ||
| 1127 | 'Progress' => 0, | ||
| 1128 | 'Unread' => true, | ||
| 1129 | 'Expires' => (TIME + 86400), | ||
| 1130 | 'Sector' => $sector, | ||
| 1131 | 'Starting Sector' => $this->getSectorID() | ||
| 1132 | ); | ||
| 1133 | |||
| 1134 | $this->missions[$missionID] =& $mission; | ||
| 1135 | $this->setupMissionStep($missionID); | ||
| 1136 | $this->rebuildMission($missionID); | ||
| 1137 | |||
| 1138 | 		$this->db->query(' | ||
| 1139 | REPLACE INTO player_has_mission (game_id,account_id,mission_id,on_step,progress,unread,starting_sector,mission_sector,step_fails) | ||
| 1140 | 			VALUES ('.$this->db->escapeNumber($this->gameID) . ',' . $this->db->escapeNumber($this->accountID) . ',' . $this->db->escapeNumber($missionID) . ',' . $this->db->escapeNumber($mission['On Step']) . ',' . $this->db->escapeNumber($mission['Progress']) . ',' . $this->db->escapeBoolean($mission['Unread']) . ',' . $this->db->escapeNumber($mission['Starting Sector']) . ',' . $this->db->escapeNumber($mission['Sector']) . ',' . $this->db->escapeNumber($mission['Expires']) . ')' | ||
| 1141 | ); | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | 	private function rebuildMission($missionID) { | ||
| 1145 | $mission = $this->missions[$missionID]; | ||
| 1146 | $this->missions[$missionID]['Name'] = MISSIONS[$missionID]['Name']; | ||
| 1147 | |||
| 1148 | 		if ($mission['On Step'] >= count(MISSIONS[$missionID]['Steps'])) { | ||
| 1149 | // If we have completed this mission just use false to indicate no current task. | ||
| 1150 | $currentStep = false; | ||
| 1151 | 		} else { | ||
| 1152 | $currentStep = MISSIONS[$missionID]['Steps'][$mission['On Step']]; | ||
| 1153 | 			$currentStep['Text'] = str_replace(array('<Race>', '<Sector>', '<Starting Sector>', '<trader>'), array($this->getRaceID(), $mission['Sector'], $mission['Starting Sector'], $this->playerName), $currentStep['Text']); | ||
| 1154 | 			if (isset($currentStep['Task'])) { | ||
| 1155 | 				$currentStep['Task'] = str_replace(array('<Race>', '<Sector>', '<Starting Sector>', '<trader>'), array($this->getRaceID(), $mission['Sector'], $mission['Starting Sector'], $this->playerName), $currentStep['Task']); | ||
| 1156 | } | ||
| 1157 | 			if (isset($currentStep['Level'])) { | ||
| 1158 | 				$currentStep['Level'] = str_replace('<Player Level>', $this->getLevelID(), $currentStep['Level']); | ||
| 1159 | 			} else { | ||
| 1160 | $currentStep['Level'] = 0; | ||
| 1161 | } | ||
| 1162 | } | ||
| 1163 | $this->missions[$missionID]['Task'] = $currentStep; | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | 	public function deleteMission($missionID) { | ||
| 1167 | $this->getMissions(); | ||
| 1168 | 		if (isset($this->missions[$missionID])) { | ||
| 1169 | unset($this->missions[$missionID]); | ||
| 1170 | 			$this->db->query('DELETE FROM player_has_mission WHERE ' . $this->SQL . ' AND mission_id = ' . $this->db->escapeNumber($missionID) . ' LIMIT 1'); | ||
| 1171 | return true; | ||
| 1172 | } | ||
| 1173 | return false; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | 	public function markMissionsRead() { | ||
| 1177 | $this->getMissions(); | ||
| 1178 | $unreadMissions = array(); | ||
| 1179 | 		foreach ($this->missions as $missionID => &$mission) { | ||
| 1180 | 			if ($mission['Unread']) { | ||
| 1181 | $unreadMissions[] = $missionID; | ||
| 1182 | $mission['Unread'] = false; | ||
| 1183 | $this->updateMission($missionID); | ||
| 1184 | } | ||
| 1185 | } | ||
| 1186 | return $unreadMissions; | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | 	public function claimMissionReward($missionID) { | ||
| 1190 | $this->getMissions(); | ||
| 1191 | $mission =& $this->missions[$missionID]; | ||
| 1192 | 		if ($mission === false) { | ||
| 1193 | 			throw new Exception('Unknown mission: ' . $missionID); | ||
| 1194 | } | ||
| 1195 | 		if ($mission['Task'] === false || $mission['Task']['Step'] != 'Claim') { | ||
| 1196 | 			throw new Exception('Cannot claim mission: ' . $missionID . ', for step: ' . $mission['On Step']); | ||
| 1197 | } | ||
| 1198 | $mission['On Step']++; | ||
| 1199 | $mission['Unread'] = true; | ||
| 1200 | 		foreach ($mission['Task']['Rewards'] as $rewardItem => $amount) { | ||
| 1201 | 			switch ($rewardItem) { | ||
| 1202 | case 'Credits': | ||
| 1203 | $this->increaseCredits($amount); | ||
| 1204 | break; | ||
| 1205 | case 'Experience': | ||
| 1206 | $this->increaseExperience($amount); | ||
| 1207 | break; | ||
| 1208 | } | ||
| 1209 | } | ||
| 1210 | $rewardText = $mission['Task']['Rewards']['Text']; | ||
| 1211 | 		if ($mission['On Step'] < count(MISSIONS[$missionID]['Steps'])) { | ||
| 1212 | // If we haven't finished the mission yet then | ||
| 1213 | $this->setupMissionStep($missionID); | ||
| 1214 | } | ||
| 1215 | $this->rebuildMission($missionID); | ||
| 1216 | $this->updateMission($missionID); | ||
| 1217 | return $rewardText; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | 	public function getAvailableMissions() { | ||
| 1221 | $availableMissions = array(); | ||
| 1222 | 		foreach (MISSIONS as $missionID => $mission) { | ||
| 1223 | 			if ($this->hasMission($missionID)) { | ||
| 1224 | continue; | ||
| 1225 | } | ||
| 1226 | $realX = Plotter::getX($mission['HasX']['Type'], $mission['HasX']['X'], $this->getGameID()); | ||
| 1227 | 			if ($realX === false) { | ||
| 1228 | 				throw new Exception('Invalid HasX definition in mission: ' . $missionID); | ||
| 1229 | } | ||
| 1230 | 			if ($this->getSector()->hasX($realX)) { | ||
| 1231 | $availableMissions[$missionID] = $mission; | ||
| 1232 | } | ||
| 1233 | } | ||
| 1234 | return $availableMissions; | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | 	public function actionTaken($actionID, array $values) { | ||
| 1238 | 		if (!in_array($actionID, MISSION_ACTIONS)) { | ||
| 1239 | 			throw new Exception('Unknown action: ' . $actionID); | ||
| 1240 | } | ||
| 1241 | // TODO: Reenable this once tested. if($this->getAccount()->isLoggingEnabled()) | ||
| 1242 | 			switch ($actionID) { | ||
| 1243 | case 'WalkSector': | ||
| 1244 | $this->getAccount()->log(LOG_TYPE_MOVEMENT, 'Walks to sector: ' . $values['Sector']->getSectorID(), $this->getSectorID()); | ||
| 1245 | break; | ||
| 1246 | case 'JoinAlliance': | ||
| 1247 | $this->getAccount()->log(LOG_TYPE_ALLIANCE, 'joined alliance: ' . $values['Alliance']->getAllianceName(), $this->getSectorID()); | ||
| 1248 | break; | ||
| 1249 | case 'LeaveAlliance': | ||
| 1250 | $this->getAccount()->log(LOG_TYPE_ALLIANCE, 'left alliance: ' . $values['Alliance']->getAllianceName(), $this->getSectorID()); | ||
| 1251 | break; | ||
| 1252 | case 'DisbandAlliance': | ||
| 1253 | $this->getAccount()->log(LOG_TYPE_ALLIANCE, 'disbanded alliance ' . $values['Alliance']->getAllianceName(), $this->getSectorID()); | ||
| 1254 | break; | ||
| 1255 | case 'KickPlayer': | ||
| 1256 | 					$this->getAccount()->log(LOG_TYPE_ALLIANCE, 'kicked ' . $values['Player']->getAccount()->getLogin() . ' (' . $values['Player']->getPlayerName() . ') from alliance ' . $values['Alliance']->getAllianceName(), 0); | ||
| 1257 | break; | ||
| 1258 | case 'PlayerKicked': | ||
| 1259 | 					$this->getAccount()->log(LOG_TYPE_ALLIANCE, 'was kicked from alliance ' . $values['Alliance']->getAllianceName() . ' by ' . $values['Player']->getAccount()->getLogin() . ' (' . $values['Player']->getPlayerName() . ')', 0); | ||
| 1260 | break; | ||
| 1261 | |||
| 1262 | } | ||
| 1263 | $this->getMissions(); | ||
| 1264 | 		foreach ($this->missions as $missionID => &$mission) { | ||
| 1265 | 			if ($mission['Task'] !== false && $mission['Task']['Step'] == $actionID) { | ||
| 1266 | 				if (checkMissionRequirements($values, $mission, $this) === true) { | ||
| 1267 | $mission['On Step']++; | ||
| 1268 | $mission['Unread'] = true; | ||
| 1269 | $this->setupMissionStep($missionID); | ||
| 1270 | $this->rebuildMission($missionID); | ||
| 1271 | $this->updateMission($missionID); | ||
| 1272 | } | ||
| 1273 | } | ||
| 1274 | } | ||
| 1275 | } | ||
| 1276 | |||
| 1277 | 	public function canSeeAny(array $otherPlayerArray) { | ||
| 1278 | 		foreach ($otherPlayerArray as $otherPlayer) { | ||
| 1279 | 			if ($this->canSee($otherPlayer)) { | ||
| 1280 | return true; | ||
| 1281 | } | ||
| 1282 | } | ||
| 1283 | return false; | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | 	public function canSee(AbstractSmrPlayer $otherPlayer) { | ||
| 1287 | 		if (!$otherPlayer->getShip()->isCloaked()) { | ||
| 1288 | return true; | ||
| 1289 | } | ||
| 1290 | 		if ($this->sameAlliance($otherPlayer)) { | ||
| 1291 | return true; | ||
| 1292 | } | ||
| 1293 | 		if ($this->getExperience() >= $otherPlayer->getExperience()) { | ||
| 1294 | return true; | ||
| 1295 | } | ||
| 1296 | return false; | ||
| 1297 | } | ||
| 1298 | |||
| 1299 | 	public function equals(AbstractSmrPlayer $otherPlayer = null) { | ||
| 1300 | return $otherPlayer !== null && $this->getAccountID() == $otherPlayer->getAccountID() && $this->getGameID() == $otherPlayer->getGameID(); | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | 	public function sameAlliance(AbstractSmrPlayer $otherPlayer = null) { | ||
| 1304 | return $this->equals($otherPlayer) || (!is_null($otherPlayer) && $this->getGameID() == $otherPlayer->getGameID() && $this->hasAlliance() && $this->getAllianceID() == $otherPlayer->getAllianceID()); | ||
| 1305 | } | ||
| 1306 | |||
| 1307 | 	public function sharedForceAlliance(AbstractSmrPlayer $otherPlayer = null) { | ||
| 1308 | return $this->sameAlliance($otherPlayer); | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | 	public function forceNAPAlliance(AbstractSmrPlayer $otherPlayer = null) { | ||
| 1312 | return $this->sameAlliance($otherPlayer); | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | 	public function planetNAPAlliance(AbstractSmrPlayer $otherPlayer = null) { | ||
| 1316 | return $this->sameAlliance($otherPlayer); | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | 	public function traderNAPAlliance(AbstractSmrPlayer $otherPlayer = null) { | ||
| 1321 | } | ||
| 1322 | |||
| 1323 | 	public function traderMAPAlliance(AbstractSmrPlayer $otherPlayer = null) { | ||
| 1324 | return $this->traderAttackTraderAlliance($otherPlayer) && $this->traderDefendTraderAlliance($otherPlayer); | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | 	public function traderAttackTraderAlliance(AbstractSmrPlayer $otherPlayer = null) { | ||
| 1328 | return $this->sameAlliance($otherPlayer); | ||
| 1329 | } | ||
| 1330 | |||
| 1331 | 	public function traderDefendTraderAlliance(AbstractSmrPlayer $otherPlayer = null) { | ||
| 1332 | return $this->sameAlliance($otherPlayer); | ||
| 1333 | } | ||
| 1334 | |||
| 1335 | 	public function traderAttackForceAlliance(AbstractSmrPlayer $otherPlayer = null) { | ||
| 1336 | return $this->sameAlliance($otherPlayer); | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | 	public function traderAttackPortAlliance(AbstractSmrPlayer $otherPlayer = null) { | ||
| 1340 | return $this->sameAlliance($otherPlayer); | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | 	public function traderAttackPlanetAlliance(AbstractSmrPlayer $otherPlayer = null) { | ||
| 1344 | return $this->sameAlliance($otherPlayer); | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | 	public function meetsAlignmentRestriction($restriction) { | ||
| 1348 | 		if ($restriction < 0) { | ||
| 1349 | return $this->getAlignment() <= $restriction; | ||
| 1350 | } | ||
| 1351 | 		if ($restriction > 0) { | ||
| 1352 | return $this->getAlignment() >= $restriction; | ||
| 1353 | } | ||
| 1354 | return true; | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | // Get an array of goods that are visible to the player | ||
| 1358 | 	public function getVisibleGoods() { | ||
| 1359 | $goods = Globals::getGoods(); | ||
| 1360 | $visibleGoods = array(); | ||
| 1361 | 		foreach ($goods as $key => $good) { | ||
| 1362 | 			if ($this->meetsAlignmentRestriction($good['AlignRestriction'])) { | ||
| 1363 | $visibleGoods[$key] = $good; | ||
| 1364 | } | ||
| 1365 | } | ||
| 1366 | return $visibleGoods; | ||
| 1367 | } | ||
| 1368 | |||
| 1369 | /** | ||
| 1370 | * Will retrieve all visited sectors, use only when you are likely to check a large number of these | ||
| 1371 | */ | ||
| 1372 | 	public function hasVisitedSector($sectorID) { | ||
| 1373 | 		if (!isset($this->visitedSectors)) { | ||
| 1374 | $this->visitedSectors = array(); | ||
| 1375 | 			$this->db->query('SELECT sector_id FROM player_visited_sector WHERE ' . $this->SQL); | ||
| 1376 | 			while ($this->db->nextRecord()) { | ||
| 1377 | 				$this->visitedSectors[$this->db->getInt('sector_id')] = false; | ||
| 1378 | } | ||
| 1379 | } | ||
| 1380 | return !isset($this->visitedSectors[$sectorID]); | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | 	public function getLeaveNewbieProtectionHREF() { | ||
| 1384 | 		return SmrSession::getNewHREF(create_container('leave_newbie_processing.php')); | ||
| 1385 | } | ||
| 1386 | |||
| 1387 | 	public function getExamineTraderHREF() { | ||
| 1391 | } | ||
| 1392 | |||
| 1393 | 	public function getAttackTraderHREF() { | ||
| 1394 | return Globals::getAttackTraderHREF($this->getAccountID()); | ||
| 1395 | } | ||
| 1396 | |||
| 1397 | 	public function getPlanetKickHREF() { | ||
| 1398 | 		$container = create_container('planet_kick_processing.php', 'trader_attack_processing.php'); | ||
| 1399 | $container['account_id'] = $this->getAccountID(); | ||
| 1400 | return SmrSession::getNewHREF($container); | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | 	public function getTraderSearchHREF() { | ||
| 1407 | } | ||
| 1408 | |||
| 1409 | 	public function getAllianceRosterHREF() { | ||
| 1410 | return Globals::getAllianceRosterHREF($this->getAllianceID()); | ||
| 1411 | } | ||
| 1412 | |||
| 1413 | 	public function getToggleWeaponHidingHREF($ajax = false) { | ||
| 1418 | } | ||
| 1419 | } | ||
| 1420 | 
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.