lib = $lib; $this->game = $this->lib->game; $this->db = $this->game->db; $this->main = $this->game->getLib(); $this->bq = $this->game->getLib('beta5/bq'); $this->fleets = $this->game->getLib('beta5/fleet'); $this->msg = $this->game->getLib('beta5/msg'); $this->planets = $this->game->getLib('beta5/planet'); $this->players = $this->game->getLib('beta5/player'); $this->rankings = $this->game->getLib('main/rankings'); $this->rules = $this->game->getLib('beta5/rules'); $this->sales = $this->game->getLib('beta5/sale'); $this->standby = $this->game->getLib('beta5/standby'); } public function runTick() { // Planetary events l::debug("Handling planetary events"); $handledSystems = 0; do { $increase = $this->db->safeTransaction( array($this, 'handleSystemGroup'), $handledSystems ); $handledSystems += $increase; } while ($increase > 0); // Abandon planets $this->db->safeTransaction(array($this, "handleAbandon")); // Stuck fleets $this->db->safeTransaction(array($this, 'unstickFleets')); // Fleets waiting in hyperspace $this->db->safeTransaction(array($this, 'hyperspaceStandby')); // Fleet sales $this->db->safeTransaction(array($this, 'fleetSales')); // Update happiness $this->db->safeTransaction(array($this, 'updateHappiness')); // Increase inflicted damage points for WHSN'd fleets if (count($this->idrInc)) { $this->db->safeTransaction(array($this, 'updateIDR')); } // Check victory status on CTF games if ($this->game->params['victory'] == 2) { $this->db->safeTransaction(array($this, 'updateCTF')); } // Update rankings $this->db->safeTransaction(array($this->main, 'call'), 'updateRankings'); } public function handleSystemGroup($startAt) { $q = $this->db->query("SELECT id,nebula FROM system ORDER BY id ASC LIMIT 5 OFFSET $startAt"); $n = dbCount($q); while ($r = dbFetchArray($q)) { $this->handleSystem($r[0], $r[1]); } return $n; } public function unstickFleets() { l::debug("Unsticking fleets"); $this->db->query("UPDATE fleet SET can_move = 'Y' WHERE can_move = 'H'"); } public function hyperspaceStandby() { $q = $this->db->query("SELECT id,owner,waiting FROM fleet WHERE waiting IS NOT NULL"); $fWait = array(); while ($r = dbFetchArray($q)) { $fWait[$r[2]] = array($r[0],$r[1]); } if (!count($fWait)) { return; } l::debug("Handling hyperspace stand-by"); $q = $this->db->query( "SELECT * FROM hs_wait WHERE id IN (" . join(',', array_keys($fWait)) . ")" ); while ($r = dbFetchHash($q)) { $r['fleet'] = $fWait[$r['id']][0]; $r['player'] = $fWait[$r['id']][1]; $fWait[$r['id']] = $r; } $losses = array(); $planets = array(); foreach ($fWait as $fw) { if ($this->handleWait($fw, &$losses)) { array_push($planets, $fw['drop_point']); } } foreach ($planets as $planetID) { $this->planets->call('detectFleets', $planetID); } $tm = time(); foreach ($losses as $pid => $locs) { foreach ($locs as $plid => $fl) { $pinf = $this->planets->call('byId', $plid); $hsLosses = array(); foreach ($fl as $f) { array_push($hsLosses, array( "p_id" => $plid, "p_name" => $pinf['name'], "f_name" => $f[0], "gaships" => $f[1], "fighters" => $f[2], "cruisers" => $f[3], "bcruisers" => $f[4], "power" => $f[5] )); } $this->msg->call('send', $pid, 'hsloss', $hsLosses); } } $this->fleets->call('sendMoveMessages'); } public function fleetSales() { $q = $this->db->query("SELECT id FROM fleet WHERE sale IS NOT NULL"); if (! dbCount($q)) { return; } l::debug("Handling fleet sales"); while ($r = dbFetchArray($q)) { $f = $this->fleets->call('get', $r[0]); l::trace("FSALE: found fleet {$r[0]}"); if (!is_null($f['sale_info']['sale']['planet'])) { l::trace("FSALE({$r[0]}): fleet is bundled with a planet, skipping"); continue; } if ($f['sale'] > 0) { l::debug("FSALE({$f['id']}): fleet isn't ready yet ({$f['sale']}h remaining)"); $this->db->query("UPDATE fleet SET sale=sale-1 WHERE id={$f['id']}"); continue; } $q2 = $this->db->query( "SELECT id,sold_to FROM sale WHERE player={$f['owner']} AND fleet={$f['id']}" . " AND finalized IS NOT NULL ORDER BY finalized DESC LIMIT 1" ); list($oid,$to) = dbFetchArray($q2); l::trace("FSALE({$f['id']}): offer #$oid, buyer #$to"); // Read data required to send the messages $fps = $this->fleets->call('getPower', $f['owner'], $f['gaships'], $f['fighters'], $f['cruisers'], $f['bcruisers']); $fpb = $this->fleets->call('getPower', $to, $f['gaships'], $f['fighters'], $f['cruisers'], $f['bcruisers']); l::trace("FSALE({$f['id']}): fps= $fps, fpb= $fpb"); // Send messages $this->msg->call('send', $f['owner'], 'sale', array( 'f_name' => $f['name'], 'f_power' => $fps, 'pl_id' => $to, 'pl_name' => $this->players->call('getName', $to), 'is_sale' => 'TRUE' )); $this->msg->call('send', $to, 'sale', array( 'f_name' => $f['name'], 'f_power' => $fpb, 'pl_id' => $f['owner'], 'pl_name' => $this->players->call('getName', $f['owner']), 'is_sale' => 'FALSE' )); l::trace("FSALE({$f['id']}): messages sent"); // Transfer control $this->db->query("UPDATE fleet SET sale=NULL,owner=$to WHERE id={$f['id']}"); $this->fleets->call('invCache', $f['id']); // FIXME: add history $this->db->query("DELETE FROM sale WHERE id=$oid"); l::debug("FSALE({$f['id']}): control transfered"); } } public function updateIDR() { l::debug("Updating IDR"); $rt = $this->rankings->call('getType', 'p_idr'); $rl = $this->rankings->call('getAll', $rt); $idr = array(); foreach ($rl as $r) { $idr[$r['id']] = $r['points']; } foreach ($this->idrInc as $n => $inc) { $idr[$n] += $inc; } $idrR = array(); foreach ($idr as $n => $p) { if (!is_array($idrR[$p])) { $idrR[$p] = array(); } array_push($idrR[$p], $n); } $this->rankings->call('update', $rt, $idrR); } public function updateCTF() { if (! $this->game->getLib()->call('isFinished')) { $this->game->getLib('beta5/ctf')->call('checkTargets'); } } public function updateHappiness() { l::debug("Updating planetary happiness"); $q = $this->db->query("SELECT id,owner FROM planet WHERE status=0"); $destroy = array(); while ($r = dbFetchArray($q)) { $nHap = $this->planets->call('updateHappiness', $r[0]); // Handle revolts if ($nHap < 20 && !in_array($r[0], $this->oChange)) { if (!is_null($r[1]) && is_null($destroy[$r[1]])) { $destroy[$r[1]] = array(); } $pDestr = $this->planetRevolt($r[0], $nHap); if (!is_null($r[1])) { array_push($destroy[$r[1]], $pDestr); } $this->planets->call('updateHappiness', $r[0]); } } // Send damage reports for revolts $tm = time() + 1; foreach ($destroy as $player => $plist) { $report = array(); foreach ($plist as $data) { array_push($report, array( "planet" => $data[0], "pname" => $data[1], "ifact" => $data[2], "mfact" => $data[3], "turrets" => $data[4] )); } $this->msg->call('send', $player, 'revdmg', $report); } } private function buildFleets($plId, $ownId, $g, $f, $c, $b) { if ($g + $f + $c + $b == 0) { return; } $q = $this->db->query("SELECT id FROM fleet WHERE can_move='Y' AND LOWER(name)='no name' AND location=$plId AND owner=$ownId AND sale IS NULL LIMIT 1"); if (dbCount($q)) { list($id) = dbFetchArray($q); $this->db->query("UPDATE fleet SET gaships=gaships+$g,fighters=fighters+$f,cruisers=cruisers+$c,bcruisers=bcruisers+$b WHERE id=$id"); } else { $qs = "INSERT INTO fleet(owner,location,gaships,fighters,cruisers,bcruisers)VALUES($ownId,$plId,$g,$f,$c,$b)"; $this->db->query($qs); } } private function planetBuildQueue($planet, $rules) { static $types = array('turret', 'gaship', 'fighter', 'cruiser', 'bcruiser'); $units = $rules['mf_productivity'] * $rules['mf_productivity_factor'] * $planet['mfact']; $cl = $planet['corruption'] / 32000; if ($cl > .1) { $units = $units * (1.1 - $cl); } $vac = $this->players->call('isOnVacation', $planet['owner']); if ($vac) { $units = $units / 4; } $prot = $this->players->call('getProtectionLevel', $planet['owner']); if ($prot) { $units = $units * 1.15; } $units = round($units); $bq = $this->bq->call('get', $planet['id']); $prod = array(0, 0, 0, 0, 0); $move = 0; while (count($bq) && $units > 0) { if ($bq[0]['units'] <= $units) { $units -= $bq[0]['units']; $prod[$bq[0]['type']] += $bq[0]['quantity']; $this->db->query("DELETE FROM buildqueue WHERE planet=".$planet['id']." AND bq_order=$move"); $move ++; array_shift($bq); } else { $units += $bq[0]['workunits']; $wuCost = $rules['workunits_'.$types[$bq[0]['type']]]; $mod = $units % $wuCost; $nBuild = ($units - $mod) / $wuCost; $prod[$bq[0]['type']] += $nBuild; $nQt = $bq[0]['quantity'] - $nBuild; $this->db->query("UPDATE buildqueue SET quantity=$nQt,workunits=$mod WHERE planet=".$planet['id']." AND bq_order=$move"); $units = 0; } } if ($move) { $this->bq->call('reorder', $planet['id']); } if ($prod[0] > 0) { $this->db->query("UPDATE planet SET turrets=turrets+".$prod[0]." WHERE id=".$planet['id']); $tm = time(); $this->db->query("DELETE FROM turhist WHERE $tm-moment>86400"); $this->db->query("INSERT INTO turhist VALUES({$planet['id']},$tm,$prod[0])"); } $this->buildFleets($planet['id'], $planet['owner'], $prod[1], $prod[2], $prod[3], $prod[4]); $this->planets->call('updateMilStatus', $planet['id']); } private function planetSale(&$planet) { l::trace("SALE: handling planet {$planet['id']}"); if ($planet['sale'] > 0) { l::debug("SALE({$planet['id']}): not ready for sale yet ({$planet['sale']}h remaining)"); $this->db->query("UPDATE planet SET sale=sale-1 WHERE id=".$planet['id']); $q = $this->db->query( "SELECT fleet FROM sale WHERE player=".$planet['owner']." AND planet=".$planet['id'] . " AND finalized IS NOT NULL ORDER BY finalized DESC LIMIT 1" ); list($fleet) = dbFetchArray($q); if (!is_null($fleet)) { l::trace("SALE({$planet['id']}): fleet $fleet bundled"); $this->db->query("UPDATE fleet SET sale=sale-1 WHERE id=$fleet"); } } else { l::trace("SALE({$planet['id']}): running sale code"); $q = $this->db->query( "SELECT id,sold_to,fleet FROM sale WHERE player=".$planet['owner']." AND planet=".$planet['id'] . " AND finalized IS NOT NULL ORDER BY finalized DESC LIMIT 1" ); if (!dbCount($q)) { l::warn("***** BUG: planet {$planet['id']} has sale field set to 0, but no " . "sales were found"); $this->db->query("UPDATE planet SET sale=NULL WHERE id={$planet['id']}"); return; } list($oid,$to,$fleet) = dbFetchArray($q); l::trace("SALE({$planet['id']}): offer #$oid, sold to player #$to (bundled fleet: " . (is_null($fleet) ? "none" : "#$fleet") . ")"); // Read data required to send the messages $tn = addslashes($this->players->call('getName', $to)); $fn = addslashes($this->players->call('getName', $planet['owner'])); l::trace("SALE({$planet['id']}): original owner '$tn', new owner '$fn'"); if (is_null($fleet)) { $fqs = $fqb = "NULL,NULL"; } else { $q = $this->db->query("SELECT * FROM fleet WHERE id=$fleet"); $fd = dbFetchHash($q); $fps = $this->fleets->call('getPower', $fd['owner'], $fd['gaships'], $fd['fighters'], $fd['cruisers'], $fd['bcruisers']); $fpb = $this->fleets->call('getPower', $to, $fd['gaships'], $fd['fighters'], $fd['cruisers'], $fd['bcruisers']); $fqs = "'" . addslashes($fd['name']) . "',$fps"; $fqb = "'" . addslashes($fd['name']) . "',$fpb"; } l::trace("SALE({$planet['id']}): fqs: $fqs"); l::trace("SALE({$planet['id']}): fqb: $fqb"); // Send messages // FIXME: message API $tm = time(); $this->db->query("INSERT INTO message(player,sent_on,mtype,ftype,is_new) VALUES({$planet['owner']},$tm,'sale','INT',TRUE)"); $q = $this->db->query("SELECT id FROM message WHERE player={$planet['owner']} AND sent_on=$tm AND mtype='sale' ORDER BY id DESC LIMIT 1"); list($mid) = dbFetchArray($q); $this->db->query("INSERT INTO msg_sale VALUES($mid,{$planet['id']},'".addslashes($planet['name'])."',$fqs,$to,'$tn',TRUE)"); $this->db->query("INSERT INTO message(player,sent_on,mtype,ftype,is_new) VALUES($to,$tm,'sale','INT',TRUE)"); $q = $this->db->query("SELECT id FROM message WHERE player=$to AND sent_on=$tm AND mtype='sale' ORDER BY id DESC LIMIT 1"); list($mid) = dbFetchArray($q); $this->db->query("INSERT INTO msg_sale VALUES($mid,{$planet['id']},'".addslashes($planet['name'])."',$fqb,{$planet['owner']},'$fn',FALSE)"); l::trace("SALE({$planet['id']}): messages sent"); // Check for vacation mode $vac = $this->players->call('isOnVacation', $to); if ($vac) { $q = $this->db->query("SELECT COUNT(*) FROM fleet WHERE location={$planet['id']} AND attacking"); list($c) = dbFetchArray(); if ($c) { $vm = 'PEND'; } else { $vm = 'YES'; } } else { $vm = 'NO'; } l::trace("SALE({$planet['id']}): vacation mode for target player: $vm"); // Sell the planet $this->players->call('losePlanet', $planet['owner'], $planet['id']); $this->players->call('takePlanet', $to, $planet['id']); $nVal = $this->planets->call('ownerChange', $planet['id'], $to, $vm); if ($nVal > 0) { $planet['max_pop'] = $nVal; } $this->db->query("UPDATE player SET bh_unhappiness=bh_unhappiness+1 WHERE id={$planet['owner']} AND bh_unhappiness<15"); if (!is_null($fleet)) { $this->db->query("UPDATE fleet SET sale=NULL,owner=$to WHERE id=$fleet"); } $planet['owner'] = $to; // FIXME: add history $this->db->query("DELETE FROM sale WHERE id=$oid"); l::debug("SALE({$planet['id']}) completed"); } } private function whsnPreparation(&$planet) { if ($planet['bh_prep'] > 0) { // WHSN is not ready yet $this->db->query("UPDATE planet SET bh_prep=bh_prep-1 WHERE id=".$planet['id']); $this->db->query("UPDATE player SET bh_unhappiness=bh_unhappiness+1 WHERE id={$planet['owner']} AND bh_unhappiness<15"); return false; } // Get fleet statistics to send messages $players = array( $planet['owner'] => array( "was_owner" => dbBool(true), "attacking" => false, "power" => 0, "fleets" => array(), ) ); $q = $this->db->query("SELECT * FROM fleet WHERE location=".$planet['id']); $aPower = $dPower = 0; while ($r = dbFetchHash($q)) { if (is_null($players[$r['owner']])) { $players[$r['owner']] = array( "was_owner" => dbBool(false), "attacking" => ($r['attacking'] == 't'), "power" => 0, "fleets" => array(), ); } $f = array( "name" => $r['name'], "gaships" => $r['gaships'], "fighters" => $r['fighters'], "cruisers" => $r['cruisers'], "bcruisers" => $r['bcruisers'], ); $power = $this->fleets->call('getPower', $r['owner'], $r['gaships'], $r['fighters'], $r['cruisers'], $r['bcruisers']); $players[$r['owner']]["power"] += ($f['power'] = $power); array_push($players[$r['owner']]['fleets'], $f); if ($players[$r['owner']]['attacking']) { $aPower += $power; } else { $dPower += $power; } // Cancel fleet sales $qfs = $this->db->query("SELECT id,player,finalized FROM sale WHERE fleet={$r['id']}"); if (dbCount($qfs)) { list($saleId, $seller, $saleFin) = dbFetchArray($qfs); if (is_null($saleFin)) { $ga = "cancel"; } else { $ga = "cancelTransfer"; } $this->sales->call($ga, $seller, $saleId); } } // Send the messages // FIXME: message API $tm = time(); foreach ($players as $pId => $data) { $this->db->query("INSERT INTO message(player,sent_on,mtype,ftype,is_new) VALUES($pId,$tm,'whsn','INT',TRUE)"); $q = $this->db->query("SELECT id FROM message WHERE player=$pId AND sent_on=$tm AND mtype='whsn' ORDER BY id DESC LIMIT 1"); list($mid) = dbFetchArray($q); if ($data['attacking']) { $pow = $aPower - $data['power']; $fPower = $pow; $ePower = $dPower; } else { $pow = $dPower - $data['power']; $fPower = $pow; $ePower = $aPower; } $this->db->query("INSERT INTO msg_whsn VALUES($mid,{$planet['id']},'" . addslashes($planet['name']) . "'," . $data['was_owner'] . ",$fPower,$ePower)"); foreach ($data['fleets'] as $f) $this->db->query("INSERT INTO whsn_fleet VALUES($mid,'" . addslashes($f['name']) . "',{$f['gaships']},{$f['fighters']},{$f['cruisers']}," . "{$f['bcruisers']},{$f['power']})"); } // Check for IDR points $pow = $aPower - $dPower; if ($pow > 0) { $pn = $this->players->call('getName', $planet['owner']); if (is_null($this->idrInc[$pn])) { $this->idrInc[$pn] = $pow; } else { $this->idrInc[$pn] += $pow; } } // Destroy the planet and anything around it $this->players->call('losePlanet', $planet['owner'], $planet['id']); $this->bq->call('flush', $planet['id']); $this->db->query("DELETE FROM fleet WHERE location=".$planet['id']); do { $rn = strtoupper(substr(md5(uniqid(rand())), 0, 10)); $q = $this->db->query("SELECT id FROM planet WHERE name='PR-[$rn]'"); } while(dbCount($q)); $this->db->query( "UPDATE planet " . "SET pop = 0, max_pop = 0, happiness = 0, mfact = 0, ifact = 0, beacon = 0, " . "built_probe = FALSE, probe_policy = NULL, bh_prep = NULL, owner = NULL, " . "sale = NULL, status = 1, bh_unhappiness = 0, vacation = 'NO', " . "name = 'PR-[$rn]', abandon = NULL " . "WHERE id = {$planet['id']}" ); $this->db->query( "UPDATE planet " . "SET bh_unhappiness = bh_unhappiness + 4 " . "WHERE system={$planet['system']} AND id <> {$planet['id']} " . "AND status = 0 AND bh_unhappiness < 12" ); $this->db->query("DELETE FROM planet_abandon_time WHERE id = {$planet['id']}"); // Raise the empire-wide unhappiness for the planet's owner $q = $this->db->query("SELECT bh_unhappiness FROM player WHERE id={$planet['owner']}"); list($bhu) = dbFetchArray($q); $nuh = max($bhu + 4, 15); $this->db->query("UPDATE player SET bh_unhappiness=$nuh WHERE id={$planet['owner']}"); return true; } private function planetTaken(&$planet) { if ($planet['turrets'] > 0) { return false; } // Check if the planet was in vacation mode before the attacking ships arrived // If it was, it can't be taken if ($planet['vacation'] == 'YES ') { return false; } // List fleets at location $q = $this->db->query("SELECT owner,gaships,attacking,time_spent FROM fleet WHERE location={$planet['id']}"); $players = array(); while ($r = dbFetchArray($q)) { // If there are defending fleets, forget it if ($r[2] == 'f') { if ($r[3] > 5) { return false; } continue; } elseif ($r[3] < 15) { continue; } // Count GA Ships per player $players[$r[0]] += $r[1]; } // Get the highest GA efficiency $maxGAPower = $maxGAPlayer = -1; foreach ($players as $id => $gas) { $rules = $this->rules->call('get', $id); $gaPower = $gas * $rules['gaship_pop']; if ($gaPower > $maxGAPower) { $maxGAPower = $gaPower; $maxGAPlayer = $id; } } // Check whether the player can actually take the planet if ($maxGAPlayer == -1 || $maxGAPower < $planet['pop']) { return false; } // A player has taken control on the planet if (!is_null($planet['owner'])) { // If the planet had an owner, flush build queue and cancel sales $this->bq->call('flush', $planet['id']); $q = $this->db->query("SELECT id,finalized,sold_to FROM sale WHERE planet={$planet['id']}"); if (dbCount($q)) { // Cancel sale list($sId,$fin,$to) = dbFetchArray($q); if (is_null($fin)) { $ga = 'cancel'; } else { $ga = 'cancelTransfer'; // Send message // FIXME ... $tm = time(); $this->db->query("INSERT INTO message(player,sent_on,mtype,ftype,is_new) VALUES($to,$tm,'plsc','INT',TRUE)"); $q = $this->db->query("SELECT id FROM message WHERE player=$to AND sent_on=$tm AND mtype='plsc' ORDER BY id DESC LIMIT 1"); list($mid) = dbFetchArray($q); $this->db->query("INSERT INTO msg_plsc VALUES($mid,{$planet['owner']},$maxGAPlayer,{$planet['id']},'" . addslashes($planet['name']) . "')"); } $this->sales->call($ga, $planet['owner'], $sId); } $rqs = ",renamed=".time(); } else { $rqs = ""; } // Check for vacation mode $vm = $this->players->call('isOnVacation', $maxGAPlayer) ? 'YES' : 'NO'; // Transfer control $this->players->call('losePlanet', $planet['owner'], $planet['id']); $this->players->call('takePlanet', $maxGAPlayer, $planet['id']); $nVal = $this->planets->call('ownerChange', $planet['id'], $maxGAPlayer, $vm); if ($nVal > 0) { $planet['max_pop'] = $nVal; } // Update a potential abandon log entry $tm = time(); $this->db->query("UPDATE abandon_log SET retake_owner=$maxGAPlayer,retake_time=$tm WHERE planet={$planet['id']} AND retake_time IS NULL"); // Get the list of the new owner's enemies $q = $this->db->query("SELECT enemy FROM enemy_player WHERE player=$maxGAPlayer"); $enemies = array(); while ($r = dbFetchArray($q)) { array_push($enemies, $r[0]); } $q = $this->db->query("SELECT p.id FROM player p,enemy_alliance e WHERE p.alliance=e.alliance AND p.a_status='IN' AND e.player=$maxGAPlayer"); while ($r = dbFetchArray($q)) { array_push($enemies, $r[0]); } $enemies = array_unique($enemies); // Switch attacking fleets to defense unless they belong to an enemy $qs = "UPDATE fleet SET attacking=FALSE,can_move='Y' WHERE location={$planet['id']}"; if (count($enemies)) { $qs .= " AND owner NOT IN (".join(',',$enemies).")"; } $this->db->query($qs); // Send messages to the former owner and the new owner $pn = addslashes($planet['name']); $noMsg = array($maxGAPlayer); $mData = array( 'p_id' => $planet['id'], 'p_name' => $planet['name'], 'owner' => $planet['owner'], 'status' => 'TAKE' ); $this->msg->call('send', $maxGAPlayer, 'ownerch', $mData); $mData['owner'] = $maxGAPlayer; if (!is_null($planet['owner'])) { $mData['status'] = 'LOSE'; array_push($noMsg, $pid = $planet['owner']); $this->msg->call('send', $pid, 'ownerch', $mData); } // Get the list of other players and send them a message as well $q2 = $this->db->query("SELECT DISTINCT owner FROM fleet WHERE location={$planet['id']} AND owner NOT IN (" . join(',', $noMsg) . ")"); $mData['status'] = 'VIEW'; while ($r = dbFetchArray($q2)) { $this->msg->call('send', $r[0], 'ownerch', $mData); } return true; } private function handlePlanet($planet) { // WHSN preparation if (!is_null($planet['bh_prep']) && $this->whsnPreparation($planet)) { return false; } // Check for owner change if ($this->planetTaken($planet)) { $this->planets->call('updateMilStatus', $planet['id']); return true; } // Planet sale if (!is_null($planet['sale'])) { $this->planetSale($planet); } // No build queues or revolts on neutral planets if (is_null($planet['owner'])) { return false; } // Load owner rules $rules = $this->rules->call('get', $planet['owner']); // Build queue $this->planetBuildQueue($planet, $rules); return false; } private function handleSystem($sid, $neb) { if ($neb) { return; } l::trace("Handling system #$sid"); $q = $this->db->query("SELECT * FROM planet WHERE system=$sid"); while ($planet = dbFetchHash($q)) { if ($neb || $planet['status'] == 1) { continue; } if ($this->handlePlanet($planet)) { array_push($this->oChange, $planet['id']); } } } private function handleWait($fw, &$losses) { $canDestroy = $this->standby->call('canDestroy', $fw['drop_point'], $fw['player']); // If we can destroy fleets, find out whether we must do so if ($canDestroy) { $prob = $this->standby->call('getLossProb', $fw['time_spent']); l::debug("HSSB({$fw['fleet']}): at planet #{$fw['drop_point']}, loss probability = " . "$prob (time spent: {$fw['time_spent']}h)"); if (rand(1,100) <= $prob) { l::debug("HSSB({$fw['fleet']}): applying fleet losses"); // Destroy a part of the fleet $amount = rand(5,round(10+$prob/10)); $fleet = $this->fleets->call('get', $fw['fleet']); $rules = $this->rules->call('get', $fw['player']); $fcLoss = ceil(($fleet['cruisers'] / 100) * $amount); $fbLoss = ceil(($fleet['bcruisers'] / 100) * $amount); l::trace("HSSB({$fw['fleet']}): cruisers lost: $fcLoss; battle cruisers lost: $fbLoss"); // Compute the amount of transported ships to be destroyed $gaSpace = $fleet['gaships'] * $rules['gaship_space']; $fSpace = $fleet['fighters'] * $rules['fighter_space']; $tSpace = $gaSpace + $fSpace; if ($tSpace > 0) { $haul = $fleet['cruisers'] * $rules['cruiser_haul'] + $fleet['bcruisers'] * $rules['bcruiser_haul']; $haulUsed = $tSpace / $haul; $lHaul = $fcLoss * $rules['cruiser_haul'] + $fbLoss * $rules['bcruiser_haul']; $lSpace = $haulUsed * $lHaul; $gaLSpace = ($lSpace / $tSpace) * $gaSpace; $fLSpace = ($lSpace / $tSpace) * $fSpace; $fgLoss = min($fleet['gaships'], ceil($gaLSpace / $rules['gaship_space'])); $ffLoss = min($fleet['fighters'], ceil($fLSpace / $rules['fighter_space'])); } else { $fgLoss = $ffLoss = 0; } l::trace("HSSB({$fw['fleet']}): fighters lost: $ffLoss; GA ships lost: $fgLoss"); // Add details to the $losses array if (!is_array($losses[$fleet['owner']])) { $losses[$fleet['owner']] = array(); } if (!is_array($losses[$fleet['owner']][$fw['drop_point']])) { $losses[$fleet['owner']][$fw['drop_point']] = array(); } array_push($losses[$fleet['owner']][$fw['drop_point']], array( addslashes($fleet['name']), $fgLoss, $ffLoss, $fcLoss, $fbLoss, $this->fleets->call('getPower', $fleet['owner'], $fgLoss, $ffLoss, $fcLoss, $fbLoss) )); if ($fcLoss == $fleet['cruisers'] && $fbLoss == $fleet['bcruisers'] && $ffLoss == $fleet['fighters'] && $fgLoss == $fleet['gaships']) { $this->fleets->call('disband',$fw['fleet'],true); l::trace("HSSB({$fw['fleet']}): fleet disbanded"); } elseif ($fcLoss + $fbLoss + $ffLoss + $fgLoss > 0) { $this->db->query( "UPDATE fleet SET gaships = gaships - $fgLoss, " . "fighters = fighters - $ffLoss, " . "cruisers = cruisers - $fcLoss, " . "bcruisers = bcruisers - $fbLoss " . "WHERE id = {$fw['fleet']}" ); } } } if ($fw['time_left'] == 1) { // Fleet arrival $this->fleets->call('arrival', $fw['fleet'], $fw['drop_point'], $fw['origin']); // Destroy wait entry $this->db->query("DELETE FROM hs_wait WHERE id={$fw['id']}"); } else { // Update wait entry $this->db->query( "UPDATE hs_wait SET time_left = time_left - 1, time_spent = time_spent + 1 " . "WHERE id={$fw['id']}" ); } return !($fw['time_left'] == 1); } private function planetRevolt($id, $hap) { $q = $this->db->query("SELECT name,ifact,mfact,turrets FROM planet WHERE id=$id"); list($n, $if, $mf, $tr) = dbFetchArray($q); $pdestr = 30 - $hap; $pdestr += rand(-floor($pdestr/2),floor($pdestr/2)); $pdestr /= 150; $dInd = round($if * $pdestr); $dMil = round($mf * $pdestr); $dTur = round($tr * $pdestr); if ($dInd + $dMil + $dTur != 0) { $this->db->query( "UPDATE planet SET ifact = ifact - $dInd, mfact = mfact - $dMil, " . "turrets = turrets - $dTur " . "WHERE id = $id" ); } return array($id, $n, $dInd, $dMil, $dTur); } public function handleAbandon() { l::debug("Handling planets being abandonned"); // Decrease time to abandon $this->db->query("UPDATE planet SET abandon = abandon - 1 WHERE abandon IS NOT NULL"); // Get the list of planets to abandon at this tick $q = $this->db->query("SELECT id, owner FROM planet WHERE abandon = 0"); $oList = array(); while ($r = dbFetchArray($q)) { if (is_null($r[1])) { l::warn("****** BUG: planet {$r[0]} is being abandoned and has no owner"); continue; } $this->abandonPlanet($r[0], $r[1]); if (!is_array($oList[$r[1]])) { $oList[$r[1]] = array(); } array_push($oList[$r[1]], $r[0]); } foreach ($oList as $pid => $aPl) { // Send the message $message = array(); foreach ($aPl as $plId) { $planet = $this->planets->call('byId', $plId); array_push($message, array("p_id" => $plId, "p_name" => $planet['name'])); } $this->msg->call('send', $pid, 'abandon', $message); // Update other planets' happiness $this->players->call('updateHappiness', $pid); } } private function abandonPlanet($pid, $oid) { // Insert log entry $this->db->query( "INSERT INTO abandon_log(planet,abandon_time,former_owner) " . "VALUES ($pid," . time() . ",$oid)" ); // Make the planet neutral $this->planets->call('ownerChange', $pid); $this->players->call('losePlanet', $oid, $pid); } } ?>