query_return($q); if ($dataarray && count($dataarray)) { // preload village data $vilIDs = []; $tos = []; $froms = []; foreach($dataarray as $data) { $vilIDs[$data['from']] = true; $vilIDs[$data['to']] = true; $tos[$data['to']] = true; $froms[$data['from']] = true; } $vilIDs = array_keys($vilIDs); $database->getProfileVillages($vilIDs, 5); $database->getUnit($vilIDs); $database->getEnforce(array_keys($tos), array_keys($froms)); $database->getVillageByWorldID($vilIDs); // calculate reinforcements data foreach($dataarray as $data) { if (!$this->claimMovementRecord($data['moveid'])) { continue; } $isoasis = $database->isVillageOases($data['to']); if($isoasis == 0){ $to = $database->getMInfo($data['to']); $toF = $database->getVillage($data['to']); $DefenderID = $to['owner']; $targettribe = $database->getUserField($DefenderID, "tribe", 0); $conqureby = 0; }else{ $to = $database->getOMInfo($data['to']); $toF = $database->getOasisV($data['to']); $DefenderID = $to['owner']; $targettribe = $database->getUserField($DefenderID, "tribe", 0); $conqureby = $toF['conqured']; } if($data['from'] == 0){ // flow 1: a "village of the elders" reinforcement returning home $this->completeReinforcementFromElders($data, $to); }else{ // flow 2: a standard reinforcement delivery (hero transfer + enforce merge + report) $this->completeReinforcementDelivery($data, $to, $isoasis, $DefenderID); } //Update starvation data $database->addStarvationData($data['to']); //check empty reinforcement in rally point $e_units = ''; for ($i = 1; $i <= 90; $i++) $e_units.= 'u'.$i.'= 0 AND '; $e_units.= 'hero = 0'; $q = "DELETE FROM ".TB_PREFIX."enforcement WHERE ".$e_units." AND (vref=".(int) $data['to']." OR `from`=".(int) $data['to'].")"; $database->query($q); } } } // Flow 1 of sendreinfunitsComplete(): a "village of the elders" reinforcement // (from = 0) returning home. $targetally / $AttackArrivalTime are intentionally // left undefined here, exactly as in the original inline code. private function completeReinforcementFromElders($data, $to) { global $database; $DefenderID = $database->getVillageField($data['to'], "owner"); $database->addEnforce(['from' => $data['from'], 'to' => $data['to'], 't1' => 0, 't2' => 0, 't3' => 0, 't4' => 0, 't5' => 0, 't6' => 0, 't7' => 0, 't8' => 0, 't9' => 0, 't10' => 0, 't11' => 0]); $reinf = $database->getEnforce($data['to'], $data['from']); $database->modifyEnforce($reinf['id'], 31, 1, 1); $data_fail = '0,0,4,1,0,0,0,0,0,0,0,0,0,0'; $database->addNotice($to['owner'], $to['wref'], (isset($targetally) ? $targetally : 0), 8, 'village of the elders reinforcement ' . addslashes($to['name']), $data_fail, isset($AttackArrivalTime) ? $AttackArrivalTime : time()); } // Flow 2 of sendreinfunitsComplete(): a standard reinforcement delivery. Handles // the lone-hero transfer between own villages, the enforcement merge-or-create, // and the reinforcement notices. $ownally / $targetally / $AttackArrivalTime are // intentionally left undefined (guarded by isset()), exactly as in the original. private function completeReinforcementDelivery($data, $to, $isoasis, $DefenderID) { global $database; //set base things $from = $database->getMInfo($data['from']); $fromF = $database->getVillage($data['from']); $AttackerID = $from['owner']; $owntribe = $database->getUserField($AttackerID,"tribe",0); $HeroTransfer = $troopsPresent = 0; for($i = 1;$i <= 10; $i++) { if($data['t'.$i] > 0) { $troopsPresent = 1; break; } } //check if the hero is present and we're not sending him to an occupied oasis //only add hero if we're sending him alone if($data['t11'] > 0 && !$isoasis && !$troopsPresent) { //check if we're sending a hero between own villages if($AttackerID == $DefenderID) { //check if there's a Mansion at target village if($this->getTypeLevel(37, $data['to']) > 0){ //don't reinforce, addunit instead $database->modifyUnit($data['to'], ["hero"], [1], [1]); $heroid = $database->getHeroField($DefenderID, 'heroid'); $database->modifyHero("wref", $data['to'], $heroid); $HeroTransfer = 1; } } } if($data['t11'] > 0 || $troopsPresent) { $this->mergeOrCreateEnforcement($data, $owntribe, $HeroTransfer); } //send rapport $unitssend_att = ''.$data['t1'].','.$data['t2'].','.$data['t3'].','.$data['t4'].','.$data['t5'].','.$data['t6'].','.$data['t7'].','.$data['t8'].','.$data['t9'].','.$data['t10'].','.$data['t11'].''; $data_fail = ''.$from['wref'].','.$from['owner'].','.$owntribe.','.$unitssend_att.''; if($isoasis == 0) $to_name = $to['name']; else $to_name = "Oasis ".$database->getVillageField($to['conqured'],"name"); $database->addNotice($from['owner'],$from['wref'],(isset($ownally) ? $ownally : 0),8,''.addslashes($from['name']).' reinforcement '.addslashes($to_name).'',$data_fail,(isset($AttackArrivalTime) ? $AttackArrivalTime : time())); if($from['owner'] != $to['owner']) { $database->addNotice($to['owner'],$to['wref'],(isset($targetally) ? $targetally : 0),8,''.addslashes($from['name']).' reinforcement '.addslashes($to_name).'',$data_fail,(isset($AttackArrivalTime) ? $AttackArrivalTime : time())); } } // Flow 3 of sendreinfunitsComplete(): merge the incoming troops into an existing // enforcement record at the target, or create a new one. When the hero was already // transferred as a unit ($HeroTransfer), his t11 is temporarily zeroed for the // merge and restored afterwards, exactly as in the original. private function mergeOrCreateEnforcement($data, $owntribe, $HeroTransfer) { global $database; $temphero = $data['t11']; if ($HeroTransfer) $data['t11'] = 0; //check if there is defence from town in to town $check = $database->getEnforce($data['to'], $data['from']); if (!isset($check['id'])) $database->addEnforce($data); else { //yes $start = ($owntribe - 1) * 10 + 1; $end = ($owntribe * 10); //add unit. $t_units = ''; for($i = $start, $j = 1; $i <= $end; $i++, $j++) { $t_units .= "u".$i." = u".$i." + ".$data['t'.$j].(($j > 9) ? '' : ', '); } $q = "UPDATE ".TB_PREFIX."enforcement set $t_units where id =".(int) $check['id']; $database->query($q); $database->modifyEnforce($check['id'], 'hero', $data['t11'], 1); } $data['t11'] = $temphero; } private function returnunitsComplete() { global $database, $technology; $time = time(); $q = " SELECT `to`, `from`, moveid, starttime, endtime, wood, clay, iron, crop, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11 FROM ".TB_PREFIX."movement, ".TB_PREFIX."attacks WHERE ".TB_PREFIX."movement.ref = ".TB_PREFIX."attacks.id AND ".TB_PREFIX."movement.proc = 0 AND ".TB_PREFIX."movement.sort_type = 4 AND endtime < $time"; $dataarray = $database->query_return($q); if ($dataarray && count($dataarray)) { // preload village data $vilIDs = []; foreach($dataarray as $data) { $vilIDs[$data['from']] = true; $vilIDs[$data['to']] = true; } $database->getProfileVillages(array_keys($vilIDs), 5); $database->getOasisEnforce($vilIDs, 0); $database->getOasisEnforce($vilIDs, 1); foreach($dataarray as $data) { if (!$this->claimMovementRecord($data['moveid'])) { continue; } $tribe = $database->getUserField($database->getVillageField($data['to'], "owner"), "tribe", 0); $u = $tribe == 1 ? "" : $tribe - 1; $database->modifyUnit( $data['to'], [$u."1", $u."2", $u."3", $u."4", $u."5", $u."6", $u."7", $u."8", $u."9", $tribe."0", "hero"], [$data['t1'], $data['t2'], $data['t3'], $data['t4'], $data['t5'], $data['t6'], $data['t7'], $data['t8'], $data['t9'], $data['t10'], $data['t11']], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ); //If there's at least 1 resource, add it to the village if($data['wood'] + $data['clay'] + $data['iron'] + $data['crop'] > 0){ $database->modifyResource($data['to'], $data['wood'], $data['clay'], $data['iron'], $data['crop'], 1); } //Update starvation data $database->addStarvationData($data['to']); } $this->pruneResource(); } // Settlers $q = "SELECT `to`, moveid FROM ".TB_PREFIX."movement where ref = 0 and proc = '0' and sort_type = '4' and endtime < $time"; $dataarray = $database->query_return($q); if ($dataarray && count($dataarray)) { foreach($dataarray as $data) { if (!$this->claimMovementRecord($data['moveid'])) { continue; } $tribe = $database->getUserField($database->getVillageField($data['to'], "owner"), "tribe", 0); $database->modifyUnit($data['to'], [$tribe."0"], [3], [1]); //If a settling is canceled, add 750 for each resource type $database->modifyResource($data['to'], 750, 750, 750, 750, 1); } } } private function sendSettlersComplete() { global $database; $time = microtime(true); $q = "SELECT `to`, `from`, moveid, starttime, ref FROM ".TB_PREFIX."movement where proc = 0 and sort_type = 5 and endtime < $time"; $dataarray = $database->query_return($q); $fieldIDs = []; $addUnitsWrefs = []; $addTechWrefs = []; $addABTechWrefs = []; $time = microtime(true); $types = []; $froms = []; $tos = []; $refs = []; $times = []; $endtimes = []; // preload village data $vilIDs = []; foreach($dataarray as $data) { $vilIDs[$data['from']] = true; $vilIDs[$data['to']] = true; } $vilIDs = array_keys($vilIDs); $database->getProfileVillages($vilIDs, 5); $database->getVillageByWorldID($vilIDs); foreach($dataarray as $data) { if (!$this->claimMovementRecord($data['moveid'])) { continue; } $ownerID = $database->getUserField($database->getVillageField($data['from'], "owner"), "id", 0); $to = $database->getMInfo($data['from']); $user = addslashes($database->getUserField($to['owner'], 'username', 0)); $taken = $database->getVillageState($data['to']); if($taken != 1){ $fieldIDs[] = $data['to']; $database->addVillage($data['to'], $to['owner'], $user, '0'); $database->addResourceFields($data['to'], $database->getVillageType($data['to'])); $addUnitsWrefs[] = $data['to']; $addTechWrefs[] = $data['to']; $addABTechWrefs[] = $data['to']; $exp1 = $database->getVillageField($data['from'], 'exp1'); $exp2 = $database->getVillageField($data['from'], 'exp2'); $exp3 = $database->getVillageField($data['from'], 'exp3'); if($exp1 == 0){ $exp = 'exp1'; $value = $data['to']; }elseif($exp2 == 0){ $exp = 'exp2'; $value = $data['to']; }else{ $exp = 'exp3'; $value = $data['to']; } $database->setVillageField($data['from'], $exp, $value); // Report: new village founded (issue #178) $ncoor = $database->getCoor($data['to']); $database->addNotice($to['owner'], $data['to'], 0, 24, 'New village founded', ($ncoor['x'] ?? 0) . ',' . ($ncoor['y'] ?? 0), time()); // Milestone: first player ever to settle their 2nd village. // Checked right after the new village row exists, so the // COUNT below already includes it. if (defined('NEW_FUNCTIONS_MILESTONES') && NEW_FUNCTIONS_MILESTONES) { $villageCount = $database->countVillages($to['owner']); if ($villageCount == 2) { $database->recordMilestoneIfFirst('second_village', $to['owner'], $data['to']); } if ($villageCount == 5) { $database->recordMilestoneIfFirst('five_villages', $to['owner'], $data['to']); } } }else{ // here must come movement from returning settlers $types[] = 4; $froms[] = $data['to']; $tos[] = $data['from']; $refs[] = $data['ref']; $times[] = $time; $endtimes[] = $time + ($time - $data['starttime']); // Report: valley already occupied, settlers returning (issue #178) $fcoor = $database->getCoor($data['to']); $database->addNotice($to['owner'], $data['to'], 0, 25, 'Settlers returned - valley occupied', ($fcoor['x'] ?? 0) . ',' . ($fcoor['y'] ?? 0), time()); } } $database->addMovement($types, $froms, $tos, $refs, $times, $endtimes); $database->setFieldTaken($fieldIDs); $database->addUnits($addUnitsWrefs); $database->addTech($addTechWrefs); $database->addABTech($addABTechWrefs); } }