lib = $lib; $this->game = $this->lib->game; $this->db = $this->game->db; } public function run() { // Get the current status (used later to send messages) $initialStatus = $this->getStatus(); $this->grace = ($initialStatus[0] != 'nohold') ? (3600 * $this->game->params['v2grace']) : 0; // Get the list of all target systems $q = $this->db->query("SELECT * FROM ctf_target"); $targets = array(); while ($r = dbFetchHash($q)) { array_push($targets, $r); } // For each target, check the system's status foreach ($targets as $target) { $this->checkTargetStatus($target); } // Get the new status $newStatus = $this->getStatus(); // Check status changes $this->checkStatusChanges($initialStatus, $newStatus); } private function getStatus() { // Get the target count $q = $this->db->query("SELECT COUNT(*) FROM ctf_target"); list($tCount) = dbFetchArray($q); // For each team, get the count of targets held without grace $q = $this->db->query( "SELECT held_by, COUNT(*) FROM ctf_target " . "WHERE held_by IS NOT NULL AND grace_expires IS NULL " . "GROUP BY held_by" ); if (dbCount($q) == 1) { list($team, $hCount) = dbFetchArray($q); if ($hCount == $tCount) { $q = $this->db->query("SELECT MAX(held_since) FROM ctf_target"); list($heldSince) = dbFetchArray($q); return array('held', $team, $heldSince); } } // For each team, get the count of targets held $q = $this->db->query( "SELECT held_by, COUNT(*) FROM ctf_target " . "WHERE held_by IS NOT NULL " . "GROUP BY held_by" ); if (dbCount($q) == 1) { list($team, $gCount) = dbFetchArray($q); if ($gCount == $tCount) { $q = $this->db->query("SELECT MIN(grace_expires) FROM ctf_target"); list($graceExpires) = dbFetchArray($q); return array('grace', $team, $graceExpires); } } return array('nohold'); } private function checkTargetStatus($target) { // Get the team for each planet in the system $q = $this->db->query( "SELECT y.alliance FROM planet p, player y " . "WHERE y.id = p.owner AND p.system = {$target['system']}" ); // If all planets are being held, list the alliances $teams = array(); $teamPlanets = array(); while ($r = dbFetchArray($q)) { if (array_key_exists($r[0], $teamPlanets)) { $teamPlanets[$r[0]] ++; } else { $teamPlanets[$r[0]] = 1; array_push($teams, $r[0]); } } if (count($teams) == 1 && $teamPlanets[$teams[0]] == 6) { // One team is holding the whole system $this->heldByTeam($target, $teams[0]); } else { // The system is not being held by any particular team $this->notHeld($target); } } private function heldByTeam($target, $team) { $tid = $target['system']; if (is_null($target['held_by'])) { // If only one team is holding the planets and the system was // not marked as being held, mark it logText("Target #$tid now held by team #$team"); $this->assignTarget($target['system'], $team); } elseif ($target['held_by'] == $team && ! is_null($target['grace_expires'])) { // If the target was being held by the team but had a grace expiration, // cancel grace period expiration and increase held_by accordingly logText("Target #$tid held by team #$team again, grace cancelled"); $gracePeriod = time() - $target['grace_expires'] + $this->grace; $this->db->query( "UPDATE ctf_target " . "SET grace_expires = NULL, held_since = held_since + $gracePeriod " . "WHERE system = {$target['system']}" ); } elseif ($target['held_by'] != $team && $this->grace > 0) { // The target is now being held by another team and the game // has support for grace periods if (is_null($target['grace_expires'])) { // No grace was set - set it logText("Target #$tid held by team #$team, setting grace for previous holder #" . $target['held_by']); $this->setGrace($target['system'], $this->grace); } elseif ($target['grace_expires'] <= time()) { // Grace has expired, but a new team is holding the system logText("Target #$tid now held by team #$team, grace ended for previous holder #" . $target['held_by']); $this->assignTarget($target['system'], $team); } } elseif ($target['held_by'] != $team) { // The target is now being held by another team, and there is no // grace period logText("Target #$tid now held by team #$team, no grace for previous holder #" . $target['held_by']); $this->assignTarget($target['system'], $team); } } private function notHeld($target) { // If the target wasn't being held before, we're done if (is_null($target['held_by'])) { return; } $tid = $target['system']; if ($this->grace > 0) { // If there is support for grace periods if (is_null($target['grace_expires'])) { // Grace period wasn't set - set it $this->setGrace($target['system'], $this->grace); logText("Target #$tid no longer held by team #{$target['held_by']}, setting grace"); } elseif ($target['grace_expires'] <= time()) { // Grace period expired, no-one's holding the system logText("Target #$tid no longer held by team #{$target['held_by']}, grace ended"); $this->unassignTarget($target['system']); } } else { // No grace periods, no-one's holding the system logText("Target #$tid no longer held by team #{$target['held_by']}, no grace"); $this->unassignTarget($target['system']); } } private function assignTarget($target, $team) { $this->db->query( "UPDATE ctf_target " . "SET held_by = $team, " . "held_since = UNIX_TIMESTAMP(NOW()), " . "grace_expires = NULL " . "WHERE system = $target" ); } private function setGrace($target, $grace) { $this->db->query( "UPDATE ctf_target SET grace_expires = UNIX_TIMESTAMP(NOW()) + $grace WHERE system = $target" ); } private function unassignTarget($target) { $this->db->query( "UPDATE ctf_target " . "SET held_by = NULL, held_since = NULL, grace_expires = NULL " . "WHERE system = $target" ); } private function checkStatusChanges($initialStatus, $newStatus) { $winTime = $this->game->params['v2time'] * 3600; // Status hasn't changed if ($initialStatus[0] == $newStatus[0] && $initialStatus[1] == $newStatus[1]) { // Check for victory / halfway to victory if ($initialStatus[0] == 'held') { $halfWay = $initialStatus[2] + $winTime / 2; $victory = $initialStatus[2] + $winTime; $now = time(); if ($now >= $halfWay && $now < $halfWay + 21) { $this->statusMessage(10, 11, $newStatus[1], $victory); } elseif ($now >= $victory) { // If the game is finished, we shouldn't be here anyways $this->lib->call('resetGame', $newStatus[1]); } } return; } // Status changed, send messages logText("CTF Status: (" . join(',',$initialStatus) . ") -> (" . join(',',$newStatus) . ")"); if ($initialStatus[0] == 'nohold' && $newStatus[0] == 'held') { // The targets are now being held by a team $this->statusMessage(2, 3, $newStatus[1], $newStatus[2] + $winTime); } elseif ($initialStatus[0] == 'grace' && $newStatus[0] == 'nohold') { // Targets are no longer being held (no grace period) $this->statusMessage(6, 9, $initialStatus[1]); $this->cancelAllGraces(); } elseif ($initialStatus[0] == 'held' && $newStatus[0] == 'nohold') { // Targets are no longer being held (no grace period) $this->statusMessage(5, 8, $initialStatus[1]); } elseif ($initialStatus[0] == 'held' && $newStatus[0] == 'grace') { // Targets are no longer being held (with grace period) $this->statusMessage(4, 7, $initialStatus[1], $newStatus[2]); } elseif ($initialStatus[0] == 'held' && $newStatus[0] == 'held') { // Targets are now held by another team $this->statusMessage(5, 8, $initialStatus[1]); $this->statusMessage(2, 3, $newStatus[1], $newStatus[2] + $winTime); } elseif ($initialStatus[0] == 'grace' && $newStatus[0] == 'held') { if ($initialStatus[1] != $newStatus[1]) { // Other team gained control $this->statusMessage(6, 9, $initialStatus[1]); } $this->statusMessage(2, 3, $newStatus[1], $newStatus[2] + $winTime); } } private function statusMessage($toTeam, $toOthers, $team, $timestamp = null) { $q = $this->db->query("SELECT id,alliance FROM player"); while ($r = dbFetchArray($q)) { $this->lib->call('message', $r[0], $r[1] == $team ? $toTeam : $toOthers, $team, $timestamp); } } private function cancelAllGraces() { $this->db->query("UPDATE ctf_target SET grace_expires = NULL"); } } ?>