mirror of
https://github.com/Shadowss/TravianZ.git
synced 2026-07-21 20:16:11 +00:00
d89ffe4482
### Core Architecture Refactor - Split the `Database.php` class into domain-specific traits under `GameEngine/Database/`. - Split the `Automation` class into domain-specific traits under `GameEngine/Automation/`. - Grouped methods by functional domain for improved maintainability and navigation. - Preserved 100% backward compatibility. - No logic or behavioral changes. - Pure structural refactor.
386 lines
16 KiB
PHP
386 lines
16 KiB
PHP
<?php
|
|
|
|
#################################################################################
|
|
## -= YOU MAY NOT REMOVE OR CHANGE THIS NOTICE =- ##
|
|
## --------------------------------------------------------------------------- ##
|
|
## Project: TravianZ ##
|
|
## Filename: AutomationTroopMovements.php ##
|
|
## Split&Refactor Shadow ##
|
|
## Purpose: Reinforcements, troop returns, settlers ##
|
|
## ##
|
|
## Phase S2: Trait extracted from GameEngine/Automation.php ##
|
|
## (Automation class). ##
|
|
## Methods were moved IDENTICALLY, with no logic changes. ##
|
|
## ##
|
|
## License: TravianZ Project ##
|
|
## Copyright: TravianZ (c) 2010-2026. All rights reserved. ##
|
|
## URLs: https://travianz.org ##
|
|
## https://github.com/Shadowss/TravianZ ##
|
|
#################################################################################
|
|
|
|
trait AutomationTroopMovements {
|
|
|
|
|
|
private function sendreinfunitsComplete() {
|
|
global $bid23, $database, $technology, $battle;
|
|
|
|
$time = time();
|
|
$q = "
|
|
SELECT
|
|
`to`, `from`, moveid,
|
|
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 = 3
|
|
AND
|
|
".TB_PREFIX."attacks.attack_type = 2
|
|
AND
|
|
endtime < $time";
|
|
$dataarray = $database->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);
|
|
|
|
}
|
|
}
|