From 432b92220f21eba4b00278136533f5d3e5573dbc Mon Sep 17 00:00:00 2001 From: lietuvis10 <50807912+lietuvis10@users.noreply.github.com> Date: Thu, 23 Oct 2025 19:46:45 +0300 Subject: [PATCH 01/24] Update Database.php fixed query. --- GameEngine/Database.php | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/GameEngine/Database.php b/GameEngine/Database.php index e4f19f62..203c3997 100755 --- a/GameEngine/Database.php +++ b/GameEngine/Database.php @@ -619,26 +619,25 @@ class MYSQLi_DB implements IDbConnection { References: lietuvis10 ***************************/ - public function getBestOasisCropBonus($x, $y) { - $x = (int)$x; - $y = (int)$y; - - // Adjust oasis type codes if your fork differs: - // - 50% crop only: type IN (12) - // - 25% crop (pure or mixed w/ wood/clay/iron): type IN (4,9,10,11) - - $sql = "SELECT COALESCE(SUM(bonus), 0) AS total FROM (SELECT CASE - WHEN o.type IN (12) THEN 50 WHEN o.type IN (4,9,10,11) THEN 25 ELSE 0 - END AS bonus FROM " . TB_PREFIX . "wdata w JOIN " . TB_PREFIX . "odata o ON o.wref = w.id - WHERE w.fieldtype = 0 AND ABS(w.x - $x) <= 3 AND ABS(w.y - $y) <= 3 - AND o.type IN (12,4,9,10,11) -- only crop-giving oases ORDER BY bonus DESC LIMIT 3) t"; +public function getBestOasisCropBonus($x, $y) { + $x = (int)$x; + $y = (int)$y; - $q = mysqli_query($this->dblink, $sql); - $row = mysqli_fetch_assoc($q); - $total = (int)($row['total'] ?? 0); - if ($total > 150) $total = 150; // safety cap - return $total; - } + // Adjust oasis type codes if your fork differs: + // - 50% crop only: type IN (12) + // - 25% crop (pure or mixed w/ wood/clay/iron): type IN (4,9,10,11) + $sql = "SELECT COALESCE(SUM(bonus), 0) AS total FROM (SELECT CASE + WHEN o.type IN (12) THEN 50 WHEN o.type IN (4,9,10,11) THEN 25 ELSE 0 + END AS bonus FROM " . TB_PREFIX . "wdata w JOIN " . TB_PREFIX . "odata o ON o.wref = w.id + WHERE w.fieldtype = 0 AND ABS(w.x - $x) <= 3 AND ABS(w.y - $y) <= 3 AND o.type IN (12,4,9,10,11) + ORDER BY bonus DESC LIMIT 3) t"; + + $q = mysqli_query($this->dblink, $sql); + $row = mysqli_fetch_assoc($q); + $total = (int)($row['total'] ?? 0); + if ($total > 150) $total = 150; // safety cap + return $total; +} /*************************** Function to process MYSQLi->fetch_all (Only exist in MYSQL) From 6aaba1b3db5bb943b8c62136995898cec271c19e Mon Sep 17 00:00:00 2001 From: lietuvis10 <50807912+lietuvis10@users.noreply.github.com> Date: Fri, 24 Oct 2025 23:27:04 +0300 Subject: [PATCH 02/24] Update unx.js For cookies to work in center village. --- unx.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/unx.js b/unx.js index 7605361d..d61cf7c3 100644 --- a/unx.js +++ b/unx.js @@ -897,13 +897,13 @@ if(_i.cookie){var date=new Date();date.setTime(date.getTime()+300000);document.c if(_i.fest&&he('dorf2')){document.getElementById('content').innerHTML+=_i.fest;} window.setTimeout(ti,30);} function he(bj){return window.location.href.indexOf(bj+'.php')!=-1;} -function vil_levels_toggle(){var cj=$('levels'),dj=$('lswitch');cj.toggleClass('on');dj.toggleClass('on');if(cj.hasClass('on')){document.cookie='t3l=1; expires=Wed, 1 Jan 2020 00:00:00 GMT';} +function vil_levels_toggle(){var cj=$('levels'),dj=$('lswitch');cj.toggleClass('on');dj.toggleClass('on');if(cj.hasClass('on')){document.cookie='t3l=1; expires=Wed, 1 Jan 2030 00:00:00 GMT';} else{document.cookie='t3l=1; expires=Thu, 01-Jan-1970 00:00:01 GMT';} } -function gmwd(){if(is_ff2&&document.getElementById("gmwi").offsetWidth<50){document.cookie="a3=2; expires=Wed, 1 Jan 2020 00:00:00 GMT";} -else{document.cookie="a3=1; expires=Wed, 1 Jan 2020 00:00:00 GMT";} +function gmwd(){if(is_ff2&&document.getElementById("gmwi").offsetWidth<50){document.cookie="a3=2; expires=Wed, 1 Jan 2030 00:00:00 GMT";} +else{document.cookie="a3=1; expires=Wed, 1 Jan 2030 00:00:00 GMT";} } -function gmc(){document.getElementById("gmw").style.display="none";document.cookie="a3=3; expires=Wed, 1 Jan 2020 00:00:00 GMT";} +function gmc(){document.getElementById("gmw").style.display="none";document.cookie="a3=3; expires=Wed, 1 Jan 2030 00:00:00 GMT";} function documentWidth() { return Math.max( document.documentElement.clientWidth, @@ -922,4 +922,4 @@ function documentHeight() { document.body.offsetHeight, document.documentElement.offsetHeight ); -} \ No newline at end of file +} From fcbaefc90eebb09372e28577fc3bec5dd851af67 Mon Sep 17 00:00:00 2001 From: lietuvis10 <50807912+lietuvis10@users.noreply.github.com> Date: Mon, 27 Oct 2025 14:18:57 +0200 Subject: [PATCH 03/24] Update mapviewlarge.tpl Updated mapviewlarge to not go over WORLD_MAX or -WORLD_MAX. Now when you go to WORLD_MAX it works same like smaller map that goes from lets say 50;50 to x axis -50;50 or y axis 50;50 to 50;-50 (WORLD_MAX 50x50 in this example). --- Templates/Map/mapviewlarge.tpl | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/Templates/Map/mapviewlarge.tpl b/Templates/Map/mapviewlarge.tpl index 1602498e..03d4a544 100644 --- a/Templates/Map/mapviewlarge.tpl +++ b/Templates/Map/mapviewlarge.tpl @@ -1,20 +1,5 @@ getCoor($_GET['z']); $y = $currentcoor['y']; @@ -316,8 +301,7 @@ $targetalliance=$donnees["aliance_id"]; $friendarray=$database->getAllianceAlly($donnees["aliance_id"],1); $neutralarray=$database->getAllianceAlly($donnees["aliance_id"],2); $enemyarray=$database->getAllianceWar2($donnees["aliance_id"]); -//var_dump($friendarray); -//echo "(".$friendarray[0]['alli1'].">0 or ".$donnees["aliance_id"].">0) and (".$friendarray[0]['alli1']."==".$donnees["aliance_id"]." or ".$friendarray[0]['alli2']."==".$donnees["aliance_id"].") and (".$session->alliance." != ".$targetalliance." and ".$session->alliance." and ".$targetalliance.")
\n"; + if (isset($friendarray[0])) { $friend = (($friendarray[0]['alli1']>0 and $friendarray[0]['alli2']>0 and $donnees["aliance_id"]>0) and ($friendarray[0]['alli1']==$session->alliance or $friendarray[0]['alli2']==$session->alliance) and ($session->alliance != $targetalliance and $session->alliance and $targetalliance)) ? '1':'0'; }else $friend='0'; @@ -328,11 +312,6 @@ if (isset($neutralarray[0])) { $neutral = (($neutralarray[0]['alli1']>0 and $neutralarray[0]['alli2']>0 and $donnees["aliance_id"]>0) and ($neutralarray[0]['alli1']==$session->alliance or $neutralarray[0]['alli2']==$session->alliance) and ($session->alliance != $targetalliance and $session->alliance and $targetalliance)) ? '1':'0'; }else $neutral='0'; -//echo $targetalliance.">>"; -//var_dump($friendarray); -//echo"|||
"; -//var_dump($arraydiplo); -//echo in_array($targetalliance,$friendarray); $image = ($donnees['map_occupied'] == 1 && $donnees['map_fieldtype'] > 0)?(($donnees['ville_user'] == $session->uid)? ($donnees['ville_pop']>=100? $donnees['ville_pop']>= 250?$donnees['ville_pop']>=500? 'b30': 'b20' :'b10' : 'b00') : (($targetalliance != 0)? ($friend==1? ($donnees['ville_pop']>=100? $donnees['ville_pop']>= 250?$donnees['ville_pop']>=500? 'b31': 'b21' :'b11' : 'b01') : ($war==1? ($donnees['ville_pop']>=100? $donnees['ville_pop']>= 250?$donnees['ville_pop']>=500? 'b32': 'b22' :'b12' : 'b02') : ($neutral==1? ($donnees['ville_pop']>=100? $donnees['ville_pop']>= 250?$donnees['ville_pop']>=500? 'b35': 'b25' :'b15' : 'b05') : ($targetalliance == $session->alliance? ($donnees['ville_pop']>=100? $donnees['ville_pop']>= 250?$donnees['ville_pop']>=500? 'b33': 'b23' :'b13' : 'b03') : ($donnees['ville_pop']>=100? $donnees['ville_pop']>= 250?$donnees['ville_pop']>=500? 'b34': 'b24' :'b14' : 'b04'))))) : ($donnees['ville_pop']>=100? $donnees['ville_pop']>= 250?$donnees['ville_pop']>=500? 'b34': 'b24' :'b14' : 'b04'))) : $donnees['map_image']; // Map Attacks by Shadow and MisterX - Fixed by iopietro @@ -441,6 +420,7 @@ if (isset($neutralarray[0])) { m_c.ad = [[]; m_c.z = {"x":,"y":}; m_c.size = 13; + m_c.world_max = ; //lietuvis10 fix var mdim = {"x":13,"y":13,"rad":6} var mmode = 0; function init_local(){map_init();} From bc296fb25185abe700411e975e854036f538156e Mon Sep 17 00:00:00 2001 From: lietuvis10 <50807912+lietuvis10@users.noreply.github.com> Date: Mon, 27 Oct 2025 17:15:43 +0200 Subject: [PATCH 04/24] Update Database.php Functions for automated Crop Finder population. --- GameEngine/Database.php | 135 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/GameEngine/Database.php b/GameEngine/Database.php index 203c3997..e7b597d7 100755 --- a/GameEngine/Database.php +++ b/GameEngine/Database.php @@ -6995,6 +6995,141 @@ References: User ID/Message ID, Mode return true; } + + /*** Build/rebuild the croppers precompute table from wdata. */ + + public function TotalCroppers(): int { + $TBP = defined('TB_PREFIX') ? TB_PREFIX : 's1_'; + $WDATA = $TBP . 'wdata'; + + $res = mysqli_query($this->dblink, "SELECT COUNT(*) AS cnt FROM `$WDATA` WHERE fieldtype IN (1,6)"); + if (!$res) { + throw new Exception('Count query failed: ' . mysqli_error($this->dblink)); + } + + $row = mysqli_fetch_assoc($res); + return (int)($row['cnt'] ?? 0); + } + + public function populateCroppers(int $countTotal = 0, bool $truncateFirst = false, int $batch = 20000, ?callable $reporter = null ): array { + + @set_time_limit(0); + @ini_set('memory_limit', '1G'); + + $TBP = defined('TB_PREFIX') ? TB_PREFIX : 's1_'; + $CROP_TABLE = $TBP . 'croppers'; + $WDATA = $TBP . 'wdata'; + + // Count once if caller didn't + if ($countTotal <= 0) { + $row = mysqli_fetch_assoc(mysqli_query($this->dblink, + "SELECT COUNT(*) cnt FROM `$WDATA` WHERE fieldtype IN (1,6)")); + $countTotal = (int)($row['cnt'] ?? 0); + } + + if ($truncateFirst) { + if (!mysqli_query($this->dblink, "TRUNCATE TABLE `$CROP_TABLE`")) { + return ['ok'=>false,'msg'=>'TRUNCATE failed: '.mysqli_error($this->dblink)]; + } + } + + // Session-level speed knobs (local to this connection) + @mysqli_query($this->dblink, "SET innodb_flush_log_at_trx_commit=2"); + @mysqli_query($this->dblink, "SET sync_binlog=0"); + @mysqli_query($this->dblink, "SET unique_checks=0"); + @mysqli_query($this->dblink, "SET foreign_key_checks=0"); + + // Read big windows; write in safe slices to avoid max_allowed_packet + if ($batch < 1000) $batch = 1000; + if ($batch > 100000) $batch = 100000; + if($countTotal < 1000) $sliceSize = 200; + elseif($countTotal < 5000) $sliceSize = 500; + elseif($countTotal > 5000) $sliceSize = 1000; + + $total = 0; + $lastId = 0; + + // Cursor pagination (no OFFSET) + while (true) { + $res = mysqli_query( + $this->dblink, + "SELECT id AS wref, x, y, fieldtype + FROM `$WDATA` + WHERE fieldtype IN (1,6) AND id > $lastId + ORDER BY id ASC + LIMIT $batch" + ); + if (!$res) { + return ['ok'=>false,'msg'=>'SELECT failed: '.mysqli_error($this->dblink),'processed'=>$total,'target'=>$countTotal]; + } + + $rows = []; + while ($r = mysqli_fetch_assoc($res)) { $rows[] = $r; } + if (!$rows) break; + + mysqli_begin_transaction($this->dblink); + + $n = count($rows); + for ($i = 0; $i < $n; $i += $sliceSize) { + $chunk = array_slice($rows, $i, $sliceSize); + $values = []; + + foreach ($chunk as $r) { + $x = (int)$r['x']; + $y = (int)$r['y']; + + // Your existing helper: + $bonus = (int)$this->getBestOasisCropBonus($x, $y); + if ($bonus < 0) $bonus = 0; + if ($bonus > 150) $bonus = 150; + + $values[] = sprintf("(%d,%d,%d,%d,%d)", + (int)$r['wref'], $x, $y, (int)$r['fieldtype'], $bonus + ); + } + + if ($values) { + // ODKU is cheaper than REPLACE (no DELETE) + $sql = "INSERT INTO `$CROP_TABLE` + (`wref`,`x`,`y`,`fieldtype`,`best_oasis_bonus`) + VALUES ".implode(',', $values)." + ON DUPLICATE KEY UPDATE + `x`=VALUES(`x`), + `y`=VALUES(`y`), + `fieldtype`=VALUES(`fieldtype`), + `best_oasis_bonus`=VALUES(`best_oasis_bonus`)"; + if (!mysqli_query($this->dblink, $sql)) { + mysqli_rollback($this->dblink); + return ['ok'=>false,'msg'=>'INSERT failed: '.mysqli_error($this->dblink),'processed'=>$total,'target'=>$countTotal]; + } + } + + // progress after each slice + $total += count($chunk); + if ($reporter) { + $pct = $countTotal ? min(100, (int)floor(($total / $countTotal) * 100)) : 0; + $reporter($total, $countTotal, $pct); + } + } + + mysqli_commit($this->dblink); + + // advance cursor + $lastId = (int)$rows[$n - 1]['wref']; + } + + // Restore checks (optional) + @mysqli_query($this->dblink, "SET unique_checks=1"); + @mysqli_query($this->dblink, "SET foreign_key_checks=1"); + + // Analyze once at the end + @mysqli_query($this->dblink, "ANALYZE TABLE `$CROP_TABLE`"); + + if ($reporter) { $reporter($total, $countTotal, 100); } + return ['ok'=>true,'msg'=>'Croppers populated','processed'=>$total,'target'=>$countTotal]; + } + + // no need to cache, not used in any loops or more than once for each page load public function getAvailableExpansionTraining() { global $building, $session, $technology, $village; From d2a4d34d29c205869189612b46a93ba10864ab97 Mon Sep 17 00:00:00 2001 From: lietuvis10 <50807912+lietuvis10@users.noreply.github.com> Date: Mon, 27 Oct 2025 17:16:55 +0200 Subject: [PATCH 05/24] Create ajax_croppers.php Ajax for cropper population info in step 3 installation. --- install/ajax_croppers.php | 88 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 install/ajax_croppers.php diff --git a/install/ajax_croppers.php b/install/ajax_croppers.php new file mode 100644 index 00000000..5d2e9d28 --- /dev/null +++ b/install/ajax_croppers.php @@ -0,0 +1,88 @@ + 0) { @ob_end_flush(); } +ob_implicit_flush(true); + +// If any installer/session code might lock the session, release it +if (session_status() === PHP_SESSION_ACTIVE) { + @session_write_close(); +} + +function sse_send(array $payload) { + echo "data: " . json_encode($payload, JSON_UNESCAPED_SLASHES) . "\n\n"; + @flush(); + @ob_flush(); +} + +function sse_ping() { + // Comment line per SSE spec, keeps connection alive + echo ":\n\n"; + @flush(); + @ob_flush(); +} + +global $database; + +// 1) Count total croppers +try { + $total = $database->TotalCroppers(); +} catch (Throwable $e) { + sse_send(['pct'=>0,'done'=>0,'total'=>0,'msg'=>'Count failed: '.$e->getMessage()]); + exit; +} + +sse_send(['pct'=>0,'done'=>0,'total'=>$total,'msg'=>"Starting croppers build (found $total tiles)…"]); + +// 2) Build with live reporter (pings to keep proxies happy) +$lastPing = time(); +$reporter = function($done, $target, $pct) use (&$lastPing) { + sse_send(['pct'=>(int)$pct,'done'=>(int)$done,'total'=>(int)$target]); + // send keep-alive every ~10s + if (time() - $lastPing >= 10) { + sse_ping(); + $lastPing = time(); + } + if (connection_aborted()) { exit; } // client left +}; + +// Run it (fresh world => truncateFirst=true; big batch on dedicated server) +$out = $database->populateCroppers($total, true, 20000, $reporter); + +if (!empty($out['ok'])) { + sse_send([ + 'pct'=>100, + 'done'=>(int)$out['processed'], + 'total'=>(int)$out['target'], + 'msg'=>'Done building croppers.' + ]); +} else { + sse_send([ + 'pct'=>0, + 'done'=>0, + 'total'=>(int)$total, + 'msg'=>'Error: '.($out['msg'] ?? 'unknown') + ]); +} +exit; From 48b14cbd6c2b0e2406fa82a9b2bf2b8fa647f5ff Mon Sep 17 00:00:00 2001 From: lietuvis10 <50807912+lietuvis10@users.noreply.github.com> Date: Mon, 27 Oct 2025 17:18:08 +0200 Subject: [PATCH 06/24] Update process.php Update Croppers part for process Crop finder automation. --- install/process.php | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/install/process.php b/install/process.php index 2e947fc6..61385cf2 100644 --- a/install/process.php +++ b/install/process.php @@ -207,26 +207,26 @@ class Process { /** * Generates map data and populates it with oasis. */ - function createWdata() { - global $database; + function createWdata() { + global $database; - include ("../GameEngine/config.php"); - include ("../GameEngine/Database.php"); - include ("../GameEngine/Admin/database.php"); + include ("../GameEngine/config.php"); + include ("../GameEngine/Database.php"); + include ("../GameEngine/Admin/database.php"); - // populate world data - $result = $database->populateWorldData(); - if ($result === false) { - header("Location: index.php?s=3&err=1"); - exit; - } else if ($result === -1) { - header("Location: index.php?s=3&c=1"); - exit; - } + // 1) Populate world data + $result = $database->populateWorldData(); + if ($result === false) { + header("Location: index.php?s=3&err=1"); + exit; + } else if ($result === -1) { + header("Location: index.php?s=3&c=1"); + exit; + } - header("Location: index.php?s=4"); - exit; - } + header("Location: index.php?s=3&startCroppers=1"); + exit; + } } ; From 027527cef3a4546d4c289b51858fb2f4bdb6870f Mon Sep 17 00:00:00 2001 From: lietuvis10 <50807912+lietuvis10@users.noreply.github.com> Date: Mon, 27 Oct 2025 17:19:02 +0200 Subject: [PATCH 07/24] Update wdata.tpl Last change to automate Crop finder automation. --- install/templates/wdata.tpl | 179 +++++++++++++++++++++++++++--------- 1 file changed, 135 insertions(+), 44 deletions(-) diff --git a/install/templates/wdata.tpl b/install/templates/wdata.tpl index 514aae08..83329e47 100644 --- a/install/templates/wdata.tpl +++ b/install/templates/wdata.tpl @@ -1,54 +1,145 @@

Error creating wdata. Check configuration or file.


"; +if (isset($_GET['c']) && $_GET['c'] == '1') { + echo '


Error creating wdata. Check configuration or file.


'; +} +if (isset($_GET['err']) && $_GET['err'] == '1') { + echo '


Existing World Data found in the database! Please empty tables ' + . TB_PREFIX . 'odata, ' . TB_PREFIX . 'units, ' . TB_PREFIX . 'vdata, ' . TB_PREFIX . 'wdata before continuing.


'; } -if(isset($_GET['err']) && $_GET['err'] == 1) { -echo "


Existing World Data found in the database! Please empty tables ".TB_PREFIX."odata, ".TB_PREFIX."units, ".TB_PREFIX."vdata, ".TB_PREFIX."wdata before continuing.


"; -} +$autoStartCroppers = isset($_GET['startCroppers']) && $_GET['startCroppers'] === '1'; ?> +
- - -

- Create World Data - - - - - - - - -
- Warning: This can take some time. Please wait until the next page has been loaded. Click Create to proceed... -
-
-
-
- -
-
-
-
-

+ + +

+ Create World Data + + + + + +
+ Warning: This can take some time. Please wait until the next page has been loaded. + Click Create to proceed... +

+ + +
+
+ +

+
+
+ + +
+
Building croppers…
+ +
+ +
+
+ +
Starting…
+ +

+
+                        
+						
+                    
+ + + +
+

From d4a87a74c8d19faa8af31cf518e91737a33a375f Mon Sep 17 00:00:00 2001 From: Catalin Novgorodschi <1140613+Shadowss@users.noreply.github.com> Date: Tue, 28 Oct 2025 08:17:31 +0200 Subject: [PATCH 08/24] Update mapviewlarge.tpl --- Templates/Map/mapviewlarge.tpl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Templates/Map/mapviewlarge.tpl b/Templates/Map/mapviewlarge.tpl index 03d4a544..2f14bb95 100644 --- a/Templates/Map/mapviewlarge.tpl +++ b/Templates/Map/mapviewlarge.tpl @@ -1,3 +1,18 @@ +################################################################################# +## -= YOU MAY NOT REMOVE OR CHANGE THIS NOTICE =- ## +## --------------------------------------------------------------------------- ## +## Project: TravianZ ## +## Version: 01.09.2013 ## +## Filename mapview.php ## +## Developed by: Advocaite , yi12345 , Shadow , MisterX ## +## Fixed by: Shadow & MisterX - Attack image view on map ## +## License: TravianZ Project ## +## Copyright: TravianZ (c) 2010-2013. All rights reserved. ## +## URLs: http://travian.shadowss.ro ## +## Source code: http://github.com/Shadowss/TravianZ/ ## +## ## +################################################################################# + Date: Tue, 28 Oct 2025 08:18:24 +0200 Subject: [PATCH 09/24] Update wdata.tpl --- install/templates/wdata.tpl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/install/templates/wdata.tpl b/install/templates/wdata.tpl index 83329e47..6bcd5293 100644 --- a/install/templates/wdata.tpl +++ b/install/templates/wdata.tpl @@ -1,3 +1,20 @@ + +################################################################################# +## -= YOU MAY NOT REMOVE OR CHANGE THIS NOTICE =- ## +## --------------------------------------------------------------------------- ## +## Project: TravianZ ## +## Version: 22.06.2015 ## +## Filename wdata.tpl ## +## Developed by: Mr.php , Advocaite , brainiacX , yi12345 , Shadow , ronix ## +## Fixed by: Shadow - STARVATION , HERO FIXED COMPL. ## +## Fixed by: InCube - double troops ## +## License: TravianZ Project ## +## Copyright: TravianZ (c) 2010-2015. All rights reserved. ## +## URLs: http://travian.shadowss.ro ## +## Source code: https://github.com/Shadowss/TravianZ ## +## ## +################################################################################# + Date: Tue, 28 Oct 2025 21:28:23 +0200 Subject: [PATCH 10/24] Update wdata.tpl fixed notice in installation, added some credit :) --- install/templates/wdata.tpl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/install/templates/wdata.tpl b/install/templates/wdata.tpl index 6bcd5293..8d86ec67 100644 --- a/install/templates/wdata.tpl +++ b/install/templates/wdata.tpl @@ -1,21 +1,23 @@ + Date: Wed, 29 Oct 2025 11:38:28 +0200 Subject: [PATCH 11/24] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c59d48d2..578db5f8 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,11 @@ [![Code Triagers Badge](https://www.codetriage.com/shadowss/travianz/badges/users.svg)](https://www.codetriage.com/shadowss/travianz) -[![Maintenance](https://img.shields.io/maintenance/yes/2024.svg)](https://github.com/Shadowss/TravianZ) +[![Maintenance](https://img.shields.io/maintenance/yes/2025.svg)](https://github.com/Shadowss/TravianZ) [![GitHub Release](https://img.shields.io/github/release/Shadowss/TravianZ/all.svg)](https://github.com/Shadowss/TravianZ) [![Github All Releases](https://img.shields.io/github/downloads/Shadowss/TravianZ/total.svg)](https://github.com/Shadowss/TravianZ) [![GitHub contributors](https://img.shields.io/github/contributors/Shadowss/TravianZ.svg)](https://github.com/Shadowss/TravianZ) [![license](https://img.shields.io/github/license/Shadowss/TravianZ.svg)](https://github.com/Shadowss/TravianZ) [![GitHub last commit](https://img.shields.io/github/last-commit/Shadowss/TravianZ.svg)](https://github.com/Shadowss/TravianZ) [![Proudly Coded in PHPStorm](https://img.shields.io/badge/coded%20in-PHPStorm-BD5CF3.svg)](https://www.jetbrains.com/buy/opensource/?product=phpstorm) -[![Donate to this project on LiberaPay](https://img.shields.io/badge/LiberaPay-donate-F6C915.svg)](https://liberapay.com/Shadowss/donate) [![Join the chat at https://gitter.im/TravianZ-V8/Lobby](https://badges.gitter.im/TravianZ-V8/Lobby.svg)](https://gitter.im/TravianZ-V8/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Watch how this was made on YouTube](https://img.shields.io/badge/The%20making%20of...-YouTube-FF0000.svg)](https://www.youtube.com/watch?v=1XiHhpGUmQg&list=PLzV5avt1FFHorlIeoL9YX0pdb9bj-FO84) ====== @@ -17,7 +16,7 @@ [![Twitter URL](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/cata7007) ====== -TravianZ Version **v.8.3.5** +TravianZ Version **v.8.3.5** - BETA 1 ====== **Note:** this game is still in a pre-release state, although at this point it is very playable, tested and found to be fairly stable @@ -54,6 +53,7 @@ or you have a feature request to be included in the play. **The team** * [Shadowss](https://github.com/Shadowss) - project owner and an occasional developer / tester +* [lietuvis10](https://github.com/lietuvis10) - active developer * [iopietro](https://github.com/iopietro) - alumni developer * [AL-Kateb](https://github.com/AL-Kateb) - alumni developer * [martinambrus](https://github.com/martinambrus) - alumni developer From 7b411e908cd27f50554ed80bb83932bece8bcbaa Mon Sep 17 00:00:00 2001 From: lietuvis10 <50807912+lietuvis10@users.noreply.github.com> Date: Sun, 2 Nov 2025 23:41:12 +0200 Subject: [PATCH 12/24] Update map.tpl Updated map UI, allows to scroll in, scroll out, move around map and click on user to open either village or his profile. --- Admin/Templates/map.tpl | 526 +++++++++++++++++++++++++++++++--------- 1 file changed, 410 insertions(+), 116 deletions(-) diff --git a/Admin/Templates/map.tpl b/Admin/Templates/map.tpl index d320c8ac..a3ff13a4 100644 --- a/Admin/Templates/map.tpl +++ b/Admin/Templates/map.tpl @@ -10,8 +10,10 @@ ## ## ################################################################################# +// ----------------- PHP (logic unchanged, except $pixelDiv = 255) ----------------- $check1 = $check2 = $check3 = ""; $includeSize = true; +$criteria = ""; if (isset($_POST['show1']) || isset($_POST['show2']) || isset($_POST['show3'])) { $check1 = isset($_POST['show1']) ? "checked " : ""; @@ -44,127 +46,419 @@ if (isset($_POST['show1']) || isset($_POST['show2']) || isset($_POST['show3'])) } } if ($check1 == "" && $check2 == "" && $check3 == "") $criteria = ""; - ?> + + + + +<?php echo SERVER_NAME; ?> Map -
-
-

Map!

-
-

This is the map of . Search and find players.

-

Show Option

-
- - - - - - -
- value="1">Players - - value="2"> - - value="2">Artifacts - - -
-
-
+ + + + +
+

Map!

+

This is the map of . Search and find players.

+ +

Show Option

+
+ + + + + +
value="1">Players value="2"> value="2">Artifacts
+
+
+ +
+
+ +
+ + 100% + + +
+ +
+ - + + + - + (0,0) +
+
+
+ + +
+ + + + query_return($q); + + foreach ($player_info as $p_array) { + $p_name = htmlspecialchars($p_array['username'], ENT_QUOTES); + $p_village= htmlspecialchars($p_array['name'], ENT_QUOTES); + $p_pop = (int)$p_array['pop']; + $p_tribe = $array_tribe[$p_array['tribe']]; + $did = (int)$p_array['wref']; + $uid = (int)$p_array['owner']; + $x = (int)$p_array['x']; + $y = (int)$p_array['y']; + + $imgName = "../img/admin/map_".(isset($p_array['size']) ? "1".$p_array['size'] : ($p_array['access'] != ADMIN ? $p_array['tribe'] : 0)).".gif"; + + // world to pixels (510x510 world; center 255,255) + $pixelDiv = 255; + $xdiv = $pixelDiv / WORLD_MAX; + $p_x = $pixelDiv + ($x * $xdiv); + $p_y = $pixelDiv - ($y * $xdiv); + + // Tooltip HTML (shared by hover & sticky) + $tooltip = "
    "; + $tooltip .= "
  • Player name: {$p_name}
  • "; + $tooltip .= "
  • Village name : {$p_village}
  • "; + $tooltip .= "
  • Coordinate: ({$x}|{$y})
  • "; + $tooltip .= "
  • Population: {$p_pop}
  • "; + $tooltip .= "
  • Tribe: {$p_tribe}
  • "; + if ($check3 != "" && isset($p_array['size'])) { + $tooltip .= "
  • Artifact effect: ".$artifactsEffect[$p_array['size']]."
  • "; + } + $tooltip .= "
"; + $tooltip .= "
" + . "Open village" + . "Open profile" + . "
"; + + // JS string version for hover (escape quotes and backslashes) + $tooltipHover = str_replace(["\\", "'"], ["\\\\", "\\'"], $tooltip); + // Attribute version for sticky (HTML-encode quotes) + $tooltipAttr = htmlspecialchars($tooltip, ENT_QUOTES); + + echo '
' + . '' + . '
'; + } + } + ?> +
+ + +
+
+
+ +
+
+

Legend

+
+
+ + + + + + +
Multihunters
+
+
+
+ +
+
+

Artifacts Legend

+
+
+ + + + +
+
+
+
+
+ + + + + + From 833cc2f7443cf4c555a0da22fd56768e821c6442 Mon Sep 17 00:00:00 2001 From: lietuvis10 <50807912+lietuvis10@users.noreply.github.com> Date: Tue, 4 Nov 2025 10:30:25 +0200 Subject: [PATCH 13/24] Update en.php Cranny description update, scale with cranny capacity. --- GameEngine/Lang/en.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GameEngine/Lang/en.php b/GameEngine/Lang/en.php index b006d0d0..147d9dae 100755 --- a/GameEngine/Lang/en.php +++ b/GameEngine/Lang/en.php @@ -1031,7 +1031,7 @@ define('CRANNY', 'Cranny'); define('CURRENT_HIDDEN_UNITS', 'Currently hidden units per resource:'); define('HIDDEN_UNITS_LEVEL', 'Hidden units per resource at level'); define('UNITS', 'units'); -define('CRANNY_DESC', 'The cranny hides some of your resources in case the village gets attacked. These resources cannot get stolen.
At level 1 the cranny can hold 200 of each resource. The capacity of Gallic crannies is 1.5 times larger.
If a Teutonic hero attacks a village, crannies can hide only 80% of their normal capacity'); +define('CRANNY_DESC', 'The cranny hides some of your resources in case the village gets attacked. These resources cannot get stolen.
At level 1 the cranny can hold '.(100*((int)CRANNY_CAPACITY)).' of each resource. The capacity of Gallic crannies is 1.5 times larger.
If a Teutonic hero attacks a village, crannies can hide only 80% of their normal capacity'); define('TOWNHALL', 'Town Hall'); define('CELEBRATIONS_COMMENCE_TOWNHALL', 'Celebrations can commence when the town hall is completed.'); From 277f67c2f55db6d1f59273e6ff3b080220a9bf5d Mon Sep 17 00:00:00 2001 From: kiliczsh Date: Wed, 12 Nov 2025 21:29:11 +0300 Subject: [PATCH 14/24] Adds Docker support for TravianZ Introduces Docker Compose configuration for simplified deployment. Includes a Dockerfile to build the application image and necessary configurations for running TravianZ in a containerized environment. Provides documentation for setup and usage in `DOCKER_README.md`. --- .dockerignore | 37 ++++++ .env.example | 11 ++ .gitignore | 3 + DOCKER_README.md | 314 +++++++++++++++++++++++++++++++++++++++++++++ Dockerfile | 44 +++++++ README.md | 22 +++- docker-compose.yml | 62 +++++++++ 7 files changed, 492 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 .env.example create mode 100644 DOCKER_README.md create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..6f89d4ed --- /dev/null +++ b/.dockerignore @@ -0,0 +1,37 @@ +# Git files +.git +.gitignore +.gitattributes + +# Docker files +Dockerfile +docker-compose.yml +.dockerignore +.env +.env.example + +# Documentation +README.md +DOCKER_README.md +CODE_OF_CONDUCT.md +CONTRIBUTING.md +ISSUE_TEMPLATE.md +LICENSE + +# IDE and editor files +.idea +.vscode +*.swp +*.swo +*~ + +# OS files +.DS_Store +Thumbs.db + +# Logs +*.log + +# Temporary files +tmp/ +temp/ diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..deebbeb7 --- /dev/null +++ b/.env.example @@ -0,0 +1,11 @@ +# MySQL Database Configuration +MYSQL_ROOT_PASSWORD=rootpassword +MYSQL_DATABASE=travian +MYSQL_USER=travianz +MYSQL_PASSWORD=travianzpass + +# Application Configuration +# These values will be used during the installation wizard +# Hostname for database connection (use 'db' when running in Docker) +DB_HOST=db +DB_PORT=3306 diff --git a/.gitignore b/.gitignore index b9944138..fff5ce94 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,6 @@ GameEngine/Admin/Mods/constant_format.tpl # These 2 files change frequently on the server but not in the repository code. Templates/text.tpl var/log/access.log + +# Docker environment file with sensitive credentials +.env diff --git a/DOCKER_README.md b/DOCKER_README.md new file mode 100644 index 00000000..4541a471 --- /dev/null +++ b/DOCKER_README.md @@ -0,0 +1,314 @@ +# TravianZ Docker Setup + +This guide will help you set up TravianZ using Docker and Docker Compose for easy deployment. + +## Prerequisites + +- Docker Engine 20.10 or higher +- Docker Compose 1.29 or higher +- At least 2GB of free RAM +- At least 5GB of free disk space + +## Quick Start + +### 1. Clone the Repository + +```bash +git clone https://github.com/Shadowss/TravianZ.git +cd TravianZ +``` + +### 2. Configure Environment Variables + +Copy the example environment file and customize it if needed: + +```bash +cp .env.example .env +``` + +Edit `.env` file to set your database credentials: + +```env +MYSQL_ROOT_PASSWORD=yourStrongRootPassword +MYSQL_DATABASE=travian +MYSQL_USER=travianz +MYSQL_PASSWORD=yourStrongPassword +``` + +### 3. Start the Containers + +```bash +docker-compose up -d +``` + +This command will: +- Build the TravianZ web application container +- Start a MySQL 5.7 database container +- Start a phpMyAdmin container for database management +- Set up a network for all containers to communicate + +### 4. Access the Installation Wizard + +Once the containers are running, open your browser and navigate to: + +``` +http://localhost:8080/install +``` + +### 5. Complete the Installation + +During the installation wizard, use these database settings: + +- **SQL Hostname:** `db` (this is the Docker container name) +- **Port:** `3306` +- **Username:** `travianz` (or the value from your `.env` file) +- **Password:** `travianzpass` (or the value from your `.env` file) +- **DB name:** `travian` (or the value from your `.env` file) +- **Prefix:** `s1_` (or customize as needed) +- **Type:** `MYSQLi` + +Complete the rest of the installation wizard with your preferred server settings. + +## Services and Ports + +After starting the containers, the following services will be available: + +- **TravianZ Web Application:** http://localhost:8080 +- **phpMyAdmin:** http://localhost:8081 +- **MySQL Database:** localhost:3306 (for external connections) + +## Container Management + +### View Running Containers + +```bash +docker-compose ps +``` + +### View Logs + +```bash +# All containers +docker-compose logs + +# Specific container +docker-compose logs web +docker-compose logs db +docker-compose logs phpmyadmin + +# Follow logs in real-time +docker-compose logs -f web +``` + +### Stop Containers + +```bash +docker-compose down +``` + +### Stop and Remove All Data + +**WARNING:** This will delete all database data! + +```bash +docker-compose down -v +``` + +### Restart Containers + +```bash +docker-compose restart +``` + +### Rebuild Containers + +If you make changes to the Dockerfile or application code: + +```bash +docker-compose down +docker-compose up -d --build +``` + +## Accessing the Containers + +### Access Web Container Shell + +```bash +docker exec -it travianz-web bash +``` + +### Access MySQL Container + +```bash +docker exec -it travianz-db mysql -u root -p +``` + +Enter the root password from your `.env` file. + +## Troubleshooting + +### Installation Files Not Writable + +If you get permission errors during installation: + +```bash +docker exec -it travianz-web chown -R www-data:www-data /var/www/html +docker exec -it travianz-web chmod -R 777 /var/www/html/var +``` + +### Database Connection Failed + +1. Make sure the database container is running: + ```bash + docker-compose ps + ``` + +2. Check database logs: + ```bash + docker-compose logs db + ``` + +3. Verify the hostname is set to `db` (not `localhost` or `127.0.0.1`) + +### Reset Installation + +If you need to start the installation over: + +1. Stop containers: + ```bash + docker-compose down -v + ``` + +2. Remove the installed flag: + ```bash + rm -f var/installed + rm -f GameEngine/config.php + ``` + +3. Start containers again: + ```bash + docker-compose up -d + ``` + +4. Access the installation wizard again at http://localhost:8080/install + +### Port Already in Use + +If port 8080 or 8081 is already in use, edit `docker-compose.yml` and change the ports: + +```yaml +services: + web: + ports: + - "9080:80" # Change 8080 to any available port + phpmyadmin: + ports: + - "9081:80" # Change 8081 to any available port +``` + +## Backup and Restore + +### Backup Database + +```bash +docker exec travianz-db mysqldump -u root -p travian > backup_$(date +%Y%m%d).sql +``` + +### Restore Database + +```bash +docker exec -i travianz-db mysql -u root -p travian < backup_20231125.sql +``` + +### Backup Application Files + +```bash +tar -czf travianz_backup_$(date +%Y%m%d).tar.gz \ + --exclude='./var/db' \ + --exclude='./.git' \ + . +``` + +## Production Deployment + +For production environments, consider the following: + +1. **Use Strong Passwords:** Change all default passwords in `.env` + +2. **Use SSL/TLS:** Set up a reverse proxy (nginx/traefik) with Let's Encrypt + +3. **Limit Database Access:** Remove the database port exposure in `docker-compose.yml` + +4. **Regular Backups:** Set up automated backup scripts + +5. **Resource Limits:** Add resource constraints to containers: + +```yaml +services: + web: + deploy: + resources: + limits: + cpus: '1.0' + memory: 1G +``` + +6. **Monitoring:** Consider adding monitoring tools like Prometheus and Grafana + +## Performance Optimization + +### MySQL Tuning + +Edit `docker-compose.yml` to add MySQL configuration: + +```yaml +services: + db: + command: > + --default-authentication-plugin=mysql_native_password + --sql_mode="" + --max_connections=200 + --innodb_buffer_pool_size=512M + --query_cache_size=32M + --query_cache_limit=2M +``` + +### PHP Tuning + +Create a custom PHP configuration file `php-custom.ini`: + +```ini +memory_limit = 256M +upload_max_filesize = 20M +post_max_size = 20M +max_execution_time = 300 +``` + +Then mount it in `docker-compose.yml`: + +```yaml +services: + web: + volumes: + - ./php-custom.ini:/usr/local/etc/php/conf.d/custom.ini +``` + +## Updates + +To update TravianZ to the latest version: + +```bash +git pull origin main +docker-compose down +docker-compose up -d --build +``` + +## Support + +For issues and questions: +- GitHub Issues: https://github.com/Shadowss/TravianZ/issues +- Gitter Chat: https://gitter.im/TravianZ-V8/Lobby + +## License + +TravianZ Project - See LICENSE file for details diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..8c0959ff --- /dev/null +++ b/Dockerfile @@ -0,0 +1,44 @@ +FROM php:7.4-apache + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + libpng-dev \ + libjpeg-dev \ + libfreetype6-dev \ + libzip-dev \ + zip \ + unzip \ + git \ + && rm -rf /var/lib/apt/lists/* + +# Configure and install PHP extensions +RUN docker-php-ext-configure gd --with-freetype --with-jpeg \ + && docker-php-ext-install -j$(nproc) \ + gd \ + mysqli \ + pdo \ + pdo_mysql \ + zip + +# Enable Apache modules +RUN a2enmod rewrite headers + +# Set working directory +WORKDIR /var/www/html + +# Copy application files +COPY . /var/www/html/ + +# Set permissions +RUN chown -R www-data:www-data /var/www/html \ + && chmod -R 755 /var/www/html \ + && chmod -R 777 /var/www/html/var + +# Configure Apache to use /var/www/html as DocumentRoot +RUN sed -i 's!/var/www/html!/var/www/html!g' /etc/apache2/sites-available/000-default.conf + +# Expose port 80 +EXPOSE 80 + +# Start Apache +CMD ["apache2-foreground"] diff --git a/README.md b/README.md index 578db5f8..205ede99 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,29 @@ TravianZ Version **v.8.3.5** - BETA 1 ====== **Note:** this game is still in a pre-release state, although at this point it is very playable, tested and found to be fairly stable -**WARNING:** please note that ***this is in no way an upgrade*** from the old 8.3.2 version, so please ***do not try to just copy your files over***, +**WARNING:** please note that ***this is in no way an upgrade*** from the old 8.3.2 version, so please ***do not try to just copy your files over***, since the installer logic has changed and you would just crash your old version +**Docker Quick Start:** + +Get up and running quickly with Docker: + +```bash +# Clone the repository +git clone https://github.com/Shadowss/TravianZ.git +cd TravianZ + +# Copy environment file +cp .env.example .env + +# Start containers +docker-compose up -d + +# Open browser to http://localhost:8080/install +``` + +For detailed Docker setup instructions, see [DOCKER_README.md](DOCKER_README.md) + **Quick links:** * [Download and Updates](https://github.com/Shadowss/TravianZ) »» https://github.com/Shadowss/TravianZ * [Wiki](https://github.com/Shadowss/TravianZ/wiki) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..1edb3c95 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,62 @@ +version: '3.8' + +services: + web: + build: + context: . + dockerfile: Dockerfile + container_name: travianz-web + ports: + - "8080:80" + volumes: + - ./:/var/www/html + - ./var:/var/www/html/var + environment: + - APACHE_DOCUMENT_ROOT=/var/www/html + depends_on: + - db + networks: + - travianz-network + restart: unless-stopped + + db: + image: mysql:5.7 + container_name: travianz-db + environment: + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-rootpassword} + MYSQL_DATABASE: ${MYSQL_DATABASE:-travian} + MYSQL_USER: ${MYSQL_USER:-travianz} + MYSQL_PASSWORD: ${MYSQL_PASSWORD:-travianzpass} + volumes: + - db-data:/var/lib/mysql + - ./var/db:/docker-entrypoint-initdb.d:ro + ports: + - "3306:3306" + networks: + - travianz-network + restart: unless-stopped + command: --default-authentication-plugin=mysql_native_password --sql_mode="" + + phpmyadmin: + image: phpmyadmin/phpmyadmin:latest + container_name: travianz-phpmyadmin + environment: + PMA_HOST: db + PMA_PORT: 3306 + PMA_USER: root + PMA_PASSWORD: ${MYSQL_ROOT_PASSWORD:-rootpassword} + ports: + - "8081:80" + depends_on: + - db + networks: + - travianz-network + restart: unless-stopped + +volumes: + db-data: + driver: local + +networks: + travianz-network: + driver: bridge From f3d31328e001f32824023b52cc5a6719bad20d2a Mon Sep 17 00:00:00 2001 From: kiliczsh Date: Fri, 14 Nov 2025 09:56:16 +0300 Subject: [PATCH 15/24] Fix PHP opening tag in mapviewlarge.tpl --- Templates/Map/mapviewlarge.tpl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Templates/Map/mapviewlarge.tpl b/Templates/Map/mapviewlarge.tpl index 2f14bb95..e37e567c 100644 --- a/Templates/Map/mapviewlarge.tpl +++ b/Templates/Map/mapviewlarge.tpl @@ -1,3 +1,5 @@ +getCoor($_GET['z']); From 371e78936ac5b6417c957abd01c8f53618cfb32a Mon Sep 17 00:00:00 2001 From: lietuvis10 <50807912+lietuvis10@users.noreply.github.com> Date: Mon, 8 Dec 2025 13:50:54 +0200 Subject: [PATCH 16/24] Update wdata.tpl Updated for fail-safe switch so if there is 3 connection hiccup's we skip populating croppers. --- install/templates/wdata.tpl | 57 +++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/install/templates/wdata.tpl b/install/templates/wdata.tpl index 8d86ec67..73c0297b 100644 --- a/install/templates/wdata.tpl +++ b/install/templates/wdata.tpl @@ -18,6 +18,7 @@ ## ## ################################################################################# + 0) { + plog.textContent += "Reconnected to server.\n"; + plog.scrollTop = plog.scrollHeight; + } + }; + es.onmessage = function (e) { // Ignore non-JSON messages (pings / blanks) if (!e.data || e.data.charCodeAt(0) !== 123 /* '{' */) return; try { var d = JSON.parse(e.data); - var pct = (d.pct || 0)|0; - var done = (d.done || 0)|0; - var total = (d.total|| 0)|0; + var pct = (d.pct || 0) | 0; + var done = (d.done || 0) | 0; + var total = (d.total|| 0) | 0; // If we've already finished, ignore further events if (finished) return; + // Valid data received -> reset retry counter + retries = 0; + pbar.style.width = pct + '%'; pinfo.textContent = done + ' / ' + total + ' (' + pct + '%)'; @@ -133,6 +151,16 @@ $autoStartCroppers = isset($_GET['startCroppers']) && $_GET['startCroppers'] === if (pct >= 100) { finished = true; plog.textContent += "✅ Completed!\n"; + plog.scrollTop = plog.scrollHeight; + es.close(); + startCountdown(); + } + + // Optional: handle explicit error flag from server if you ever send it + if (d.error) { + finished = true; + plog.textContent += "❌ " + (d.msg || "Server reported an error.") + "\n"; + plog.scrollTop = plog.scrollHeight; es.close(); startCountdown(); } @@ -143,9 +171,21 @@ $autoStartCroppers = isset($_GET['startCroppers']) && $_GET['startCroppers'] === }; es.onerror = function () { - // Don’t spam after we’re done; otherwise let EventSource reconnect silently - if (!finished) { - plog.textContent += "Connection hiccup, retrying…\n"; + // Don’t spam after we’re done + if (finished) return; + + retries++; + plog.textContent += "⚠ Connection hiccup (" + retries + "/" + MAX_RETRIES + "), retrying…\n"; + plog.scrollTop = plog.scrollHeight; + + // EventSource will auto-reconnect by itself; we just decide when to give up + if (retries >= MAX_RETRIES) { + finished = true; + plog.textContent += "❌ Too many connection failures — skipping croppers build.\n"; + plog.scrollTop = plog.scrollHeight; + es.close(); + // Reuse the same countdown UI to move on + startCountdown(); } }; } @@ -156,6 +196,7 @@ $autoStartCroppers = isset($_GET['startCroppers']) && $_GET['startCroppers'] === })(); + From 038465fe9afbc25b12f51a67bdffffb33edfad2a Mon Sep 17 00:00:00 2001 From: lietuvis10 <50807912+lietuvis10@users.noreply.github.com> Date: Sun, 14 Dec 2025 15:27:46 +0200 Subject: [PATCH 17/24] Update Database.php Fixed chieftain training issue: when player reinforced their chiefs to other villages they could train more so no more unlimited chieftains :) --- GameEngine/Database.php | 152 +++++++++++++++++++++------------------- 1 file changed, 80 insertions(+), 72 deletions(-) diff --git a/GameEngine/Database.php b/GameEngine/Database.php index e7b597d7..15a9af43 100755 --- a/GameEngine/Database.php +++ b/GameEngine/Database.php @@ -7134,90 +7134,98 @@ References: User ID/Message ID, Mode public function getAvailableExpansionTraining() { global $building, $session, $technology, $village; - $vilData = $this->getVillage($village->wid); - $maxslots = (($vilData['exp1'] == 0 ? 1 : 0) + ($vilData['exp2'] == 0 ? 1 : 0) + ($vilData['exp3'] == 0 ? 1 : 0)); - $residence = $building->getTypeLevel(25); - $palace = $building->getTypeLevel(26); + $vilData = $this->getVillage($village->wid); + $maxslots = (($vilData['exp1'] == 0 ? 1 : 0) + ($vilData['exp2'] == 0 ? 1 : 0) + ($vilData['exp3'] == 0 ? 1 : 0)); + $residence = $building->getTypeLevel(25); + $palace = $building->getTypeLevel(26); - if($residence > 0) { - $maxslots -= (3 - floor($residence / 10)); - } + if($residence > 0) { + $maxslots -= (3 - floor($residence / 10)); + } - if($palace > 0) { - $maxslots -= (3 - floor(($palace - 5) / 5)); - } + if($palace > 0) { + $maxslots -= (3 - floor(($palace - 5) / 5)); + } - $q = "SELECT (u10+u20+u30) as R1, (u9+u19+u29) as R2 FROM " . TB_PREFIX . "units WHERE vref = ". (int) $village->wid; - $result = mysqli_query($this->dblink,$q); - $row = mysqli_fetch_array($result, MYSQLI_ASSOC); - $settlers = $row['R1']; - $chiefs = $row['R2']; + // Units at home + $q = "SELECT (u10+u20+u30) as R1, (u9+u19+u29) as R2 + FROM " . TB_PREFIX . "units + WHERE vref = " . (int)$village->wid; + $result = mysqli_query($this->dblink,$q); + $row = mysqli_fetch_array($result, MYSQLI_ASSOC); + $settlers = (int)$row['R1']; + $chiefs = (int)$row['R2']; - $settlers += 3 * count($this->getMovement(5, $village->wid, 0)); - - $current_movement = $this->getMovement(3, $village->wid, 0); - if(!empty($current_movement)) { - foreach($current_movement as $build) { - $settlers += $build['t10']; - $chiefs += $build['t9']; - } - } + // Movements + $settlers += 3 * count($this->getMovement(5, $village->wid, 0)); - $current_movement = $this->getMovement(4, $village->wid, 1); - if(!empty($current_movement)) { - foreach($current_movement as $build) { - $settlers += $build['t10']; - $chiefs += $build['t9']; - } - } + $current_movement = $this->getMovement(3, $village->wid, 0); + if(!empty($current_movement)) { + foreach($current_movement as $build) { + $settlers += (int)$build['t10']; + $chiefs += (int)$build['t9']; + } + } - $q = "SELECT (u10+u20+u30) FROM " . TB_PREFIX . "enforcement WHERE `from` = ".(int) $village->wid; - $result = mysqli_query($this->dblink,$q); - $row = mysqli_fetch_row($result); - if(!empty($row)) { - foreach($row as $reinf) { - $settlers += $reinf[0]; - } - } + $current_movement = $this->getMovement(4, $village->wid, 1); + if(!empty($current_movement)) { + foreach($current_movement as $build) { + $settlers += (int)$build['t10']; + $chiefs += (int)$build['t9']; + } + } - $q = "SELECT (u9+u19+u29) FROM " . TB_PREFIX . "enforcement WHERE `from` = ".(int) $village->wid; - $result = mysqli_query($this->dblink,$q); - $row = mysqli_fetch_row($result); - if(!empty($row)) { - foreach($row as $reinf) { - $chiefs += $reinf[0]; - } - } + // FIX: Count ALL reinforcements properly (SUM over ALL rows) + $q = "SELECT COALESCE(SUM(u10+u20+u30),0) AS s + FROM " . TB_PREFIX . "enforcement + WHERE `from` = " . (int)$village->wid; + $result = mysqli_query($this->dblink,$q); + $row = mysqli_fetch_array($result, MYSQLI_ASSOC); + $settlers += (int)$row['s']; - $trainlist = $technology->getTrainingList(4); - if(!empty($trainlist)) { - foreach($trainlist as $train) { - if($train['unit'] % 10 == 0) { - $settlers += $train['amt']; - } - if($train['unit'] % 10 == 9) { - $chiefs += $train['amt']; - } - } - } + $q = "SELECT COALESCE(SUM(u9+u19+u29),0) AS c + FROM " . TB_PREFIX . "enforcement + WHERE `from` = " . (int)$village->wid; + $result = mysqli_query($this->dblink,$q); + $row = mysqli_fetch_array($result, MYSQLI_ASSOC); + $chiefs += (int)$row['c']; - $trappedTroops = $this->getPrisoners($village->wid, 1); - if(!empty($trappedTroops)){ - foreach($trappedTroops as $trapped){ - $settlers += $trapped['t10']; - $chiefs += $trapped['t9']; - } - } + // Training queue (your existing logic) + $trainlist = $technology->getTrainingList(4); + if(!empty($trainlist)) { + foreach($trainlist as $train) { + if($train['unit'] % 10 == 0) { + $settlers += (int)$train['amt']; + } + if($train['unit'] % 10 == 9) { + $chiefs += (int)$train['amt']; + } + } + } - $settlerslots = ($maxslots * 3) - ($chiefs * 3) - $settlers; - $chiefslots = $maxslots - $chiefs - floor(($settlers + 2) / 3); + // Trapped troops + $trappedTroops = $this->getPrisoners($village->wid, 1); + if(!empty($trappedTroops)){ + foreach($trappedTroops as $trapped){ + $settlers += (int)$trapped['t10']; + $chiefs += (int)$trapped['t9']; + } + } - if(!$technology->getTech(($session->tribe - 1) * 10 + 9)) { - $chiefslots = 0; - } + // Slot math (unchanged, but clamp to 0 to avoid negatives) + $settlerslots = ($maxslots * 3) - ($chiefs * 3) - $settlers; + $chiefslots = $maxslots - $chiefs - floor(($settlers + 2) / 3); + + if(!$technology->getTech(($session->tribe - 1) * 10 + 9)) { + $chiefslots = 0; + } + + if ($settlerslots < 0) $settlerslots = 0; + if ($chiefslots < 0) $chiefslots = 0; + + return ["chiefs" => $chiefslots, "settlers" => $settlerslots]; +} - return ["chiefs" => $chiefslots, "settlers" => $settlerslots]; - } /** * Calculates how much artifacts affect troops speed, cranny efficency, etc. From 7f182ff7e7d8bec4eb916152e0554c444bca2f65 Mon Sep 17 00:00:00 2001 From: haki99 Date: Wed, 17 Dec 2025 17:07:42 +0100 Subject: [PATCH 18/24] Added missing tag --- install/templates/wdata.tpl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/install/templates/wdata.tpl b/install/templates/wdata.tpl index 73c0297b..f7bc384d 100644 --- a/install/templates/wdata.tpl +++ b/install/templates/wdata.tpl @@ -1,6 +1,5 @@ + Date: Wed, 17 Dec 2025 17:10:11 +0100 Subject: [PATCH 19/24] Adjust unit growth calculations with player metrics Updated unit growth calculations based on player progression and growth factor. --- var/db/datagen-oasis-troops-regen.sql | 94 +++++++++++++++------------ 1 file changed, 53 insertions(+), 41 deletions(-) diff --git a/var/db/datagen-oasis-troops-regen.sql b/var/db/datagen-oasis-troops-regen.sql index 6cd3efe0..a7c0f491 100644 --- a/var/db/datagen-oasis-troops-regen.sql +++ b/var/db/datagen-oasis-troops-regen.sql @@ -33,25 +33,37 @@ INSERT INTO %PREFIX%oids VALUES %VILLAGEID%; SET @noVillage = ((SELECT id FROM %PREFIX%oids LIMIT 1) = -1); +-- Get the number of players +SELECT COUNT(*) INTO @playerCount FROM %PREFIX%users WHERE tribe != 0; +-- Calculate average progression for all real players (owner > 6) from culture points (CP) and population of villages (pop) +SELECT AVG(pop + cp) INTO @avgPlayerProgress FROM %PREFIX%vdata WHERE owner > 6; +-- ---------------------------------------------------------------- +-- Calculate growth factor based on player progression +-- Scale between 0.3 and 3.0 +-- ---------------------------------------------------------------- +SET @growthFactor = LEAST(3.0, GREATEST(0.3, @avgPlayerProgress / 1000)); -- faster access to first oasis ID, so we don't need to reselect all the time below SET @firstVillage = (SELECT id FROM %PREFIX%oids LIMIT 1); -- minimum and maximum number of units for oasis with "high" field set to 0 -SET @minUnitsForOasis0 = 15; -SET @maxUnitsForOasis0 = 30; +SET @minUnitsForOasis0 = GREATEST(5, FLOOR(5 * @growthFactor)); +SET @maxUnitsForOasis0 = LEAST(FLOOR(@minUnitsForOasis0 + 5 + (@playerCount * 1.5) * @growthFactor), 30); -- minimum and maximum number of units for oasis with "high" field set to 1 -SET @minUnitsForOasis1 = 50; -SET @maxUnitsForOasis1 = 70; +SET @minUnitsForOasis1 = GREATEST(10, FLOOR(10 * @growthFactor)); +SET @maxUnitsForOasis1 = LEAST(FLOOR(@minUnitsForOasis1 + 10 + (@playerCount * 2) * @growthFactor), 60); -- minimum and maximum number of units for oasis with "high" field set to 2 -SET @minUnitsForOasis2 = 90; -SET @maxUnitsForOasis2 = 120; - +SET @minUnitsForOasis2 = GREATEST(20, FLOOR(20 * @growthFactor)); +SET @maxUnitsForOasis2 = LEAST(FLOOR(@minUnitsForOasis2 + 15 + (@playerCount * 3) * @growthFactor), 90); +-- Setting a maximum for every type of Oasis so large servers won't turn oasis into fortresses +SET @maxUnitsForOasis0 = LEAST(@maxUnitsForOasis0, 30); +SET @maxUnitsForOasis1 = LEAST(@maxUnitsForOasis1, 60); +SET @maxUnitsForOasis2 = LEAST(@maxUnitsForOasis2, 90); -- ---------------------------------------- -- reset oasis data (conquered > unoccupied) @@ -109,9 +121,9 @@ UPDATE %PREFIX%units u JOIN %PREFIX%odata o ON u.vref = o.wref SET - u.u35 = u.u35 + (FLOOR(5 + RAND() * 10)), - u36 = u36 + (FLOOR(0 + RAND() * 5)), - u37 = u37 + (FLOOR(0 + RAND() * 5)) + u.u35 = u.u35 + FLOOR((5 + RAND() * 10) * @growthFactor), + u36 = u36 + FLOOR((0 + RAND() * 5) * @growthFactor), + u37 = u37 + FLOOR((0 + RAND() * 5) * @growthFactor) WHERE ( ( @@ -163,11 +175,11 @@ UPDATE %PREFIX%units u JOIN %PREFIX%odata o ON u.vref = o.wref SET - u35 = u35 + (FLOOR(5 + RAND() * 15)), - u36 = u36 + (FLOOR(0 + RAND() * 5)), - u37 = u37 + (FLOOR(0 + RAND() * 5)), - u38 = u38 + (FLOOR(0 + RAND() * 5)), - u40 = u40 + (FLOOR(0 + RAND() * 3)) + u35 = u35 + FLOOR((5 + RAND() * 15) * @growthFactor), + u36 = u36 + FLOOR((0 + RAND() * 5) * @growthFactor), + u37 = u37 + FLOOR((0 + RAND() * 5) * @growthFactor), + u38 = u38 + FLOOR((0 + RAND() * 5) * @growthFactor), + u40 = u40 + FLOOR((0 + RAND() * 3) * @growthFactor) WHERE ( ( @@ -219,9 +231,9 @@ UPDATE %PREFIX%units u JOIN %PREFIX%odata o ON u.vref = o.wref SET - u31 = u31 + (FLOOR(10 + RAND() * 15)), - u32 = u32 + (FLOOR(5 + RAND() * 15)), - u35 = u35 + (FLOOR(0 + RAND() * 10)) + u31 = u31 + FLOOR((10 + RAND() * 15) * @growthFactor), + u32 = u32 + FLOOR((5 + RAND() * 15) * @growthFactor), + u35 = u35 + FLOOR((0 + RAND() * 10) * @growthFactor) WHERE ( ( @@ -270,10 +282,10 @@ UPDATE %PREFIX%units u JOIN %PREFIX%odata o ON u.vref = o.wref SET - u31 = u31 + (FLOOR(15 + RAND() * 20)), - u32 = u32 + (FLOOR(10 + RAND() * 15)), - u35 = u35 + (FLOOR(0 + RAND() * 10)), - u40 = u40 + (FLOOR(0 + RAND() * 3)) + u31 = u31 + FLOOR((15 + RAND() * 20) * @growthFactor), + u32 = u32 + FLOOR((10 + RAND() * 15) * @growthFactor), + u35 = u35 + FLOOR((0 + RAND() * 10) * @growthFactor), + u40 = u40 + FLOOR((0 + RAND() * 3) * @growthFactor) WHERE ( ( @@ -322,9 +334,9 @@ UPDATE %PREFIX%units u JOIN %PREFIX%odata o ON u.vref = o.wref SET - u31 = u31 + (FLOOR(10 + RAND() * 15)), - u32 = u32 + (FLOOR(5 + RAND() * 15)), - u34 = u34 + (FLOOR(0 + RAND() * 10)) + u31 = u31 + FLOOR((10 + RAND() * 15) * @growthFactor), + u32 = u32 + FLOOR((5 + RAND() * 15) * @growthFactor), + u34 = u34 + FLOOR((0 + RAND() * 10) * @growthFactor) WHERE ( ( @@ -373,10 +385,10 @@ UPDATE %PREFIX%units u JOIN %PREFIX%odata o ON u.vref = o.wref SET - u31 = u31 + (FLOOR(15 + RAND() * 20)), - u32 = u32 + (FLOOR(10 + RAND() * 15)), - u34 = u34 + (FLOOR(0 + RAND() * 10)), - u39 = u39 + (FLOOR(0 + RAND() * 3)) + u31 = u31 + FLOOR((15 + RAND() * 20) * @growthFactor), + u32 = u32 + FLOOR((10 + RAND() * 15) * @growthFactor), + u34 = u34 + FLOOR((0 + RAND() * 10) * @growthFactor), + u39 = u39 + FLOOR((0 + RAND() * 3) * @growthFactor) WHERE ( ( @@ -425,11 +437,11 @@ UPDATE %PREFIX%units u JOIN %PREFIX%odata o ON u.vref = o.wref SET - u31 = u31 + (FLOOR(5 + RAND() * 15)), - u33 = u33 + (FLOOR(5 + RAND() * 10)), - u37 = u37 + (FLOOR(0 + RAND() * 10)), - u38 = u38 + (FLOOR(0 + RAND() * 5)), - u39 = u39 + (FLOOR(0 + RAND() * 5)) + u31 = u31 + FLOOR((5 + RAND() * 15) * @growthFactor), + u33 = u33 + FLOOR((5 + RAND() * 10) * @growthFactor), + u37 = u37 + FLOOR((0 + RAND() * 10) * @growthFactor), + u38 = u38 + FLOOR((0 + RAND() * 5) * @growthFactor), + u39 = u39 + FLOOR((0 + RAND() * 5) * @growthFactor) WHERE ( ( @@ -485,12 +497,12 @@ UPDATE %PREFIX%units u JOIN %PREFIX%odata o ON u.vref = o.wref SET - u31 = u31 + (FLOOR(10 + RAND() * 15)), - u33 = u33 + (FLOOR(5 + RAND() * 10)), - u37 = u37 + (FLOOR(0 + RAND() * 10)), - u38 = u38 + (FLOOR(0 + RAND() * 5)), - u39 = u39 + (FLOOR(0 + RAND() * 5)), - u40 = u40 + (FLOOR(0 + RAND() * 3)) + u31 = u31 + FLOOR((10 + RAND() * 15) * @growthFactor), + u33 = u33 + FLOOR((5 + RAND() * 10) * @growthFactor), + u37 = u37 + FLOOR((0 + RAND() * 10) * @growthFactor), + u38 = u38 + FLOOR((0 + RAND() * 5) * @growthFactor), + u39 = u39 + FLOOR((0 + RAND() * 5) * @growthFactor), + u40 = u40 + FLOOR((0 + RAND() * 3) * @growthFactor) WHERE ( ( @@ -546,4 +558,4 @@ UPDATE %PREFIX%units u WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) END - ); \ No newline at end of file + ); From 4e30e49475578ed87a2296a4447513944df3952a Mon Sep 17 00:00:00 2001 From: haki99 Date: Fri, 19 Dec 2025 22:17:21 +0100 Subject: [PATCH 20/24] Update SQL queries for player count and progression --- var/db/datagen-oasis-troops-regen.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/var/db/datagen-oasis-troops-regen.sql b/var/db/datagen-oasis-troops-regen.sql index a7c0f491..7b45027b 100644 --- a/var/db/datagen-oasis-troops-regen.sql +++ b/var/db/datagen-oasis-troops-regen.sql @@ -34,10 +34,10 @@ INSERT INTO %PREFIX%oids VALUES %VILLAGEID%; SET @noVillage = ((SELECT id FROM %PREFIX%oids LIMIT 1) = -1); -- Get the number of players -SELECT COUNT(*) INTO @playerCount FROM %PREFIX%users WHERE tribe != 0; +SELECT COUNT(*) INTO @playerCount FROM %PREFIX%users WHERE id > 6; -- Calculate average progression for all real players (owner > 6) from culture points (CP) and population of villages (pop) -SELECT AVG(pop + cp) INTO @avgPlayerProgress FROM %PREFIX%vdata WHERE owner > 6; +SELECT IFNULL(AVG(pop + cp), 0) INTO @avgPlayerProgress FROM %PREFIX%vdata WHERE owner > 6; -- ---------------------------------------------------------------- -- Calculate growth factor based on player progression From 510421e4eda633c8a0d5fbc62629848e0433405e Mon Sep 17 00:00:00 2001 From: haki99 Date: Fri, 19 Dec 2025 22:57:21 +0100 Subject: [PATCH 21/24] Refactor oasis regeneration SQL script Refactor oasis regeneration SQL script to improve clarity and maintainability. --- var/db/datagen-oasis-troops-regen.sql | 691 ++++++++++---------------- 1 file changed, 270 insertions(+), 421 deletions(-) diff --git a/var/db/datagen-oasis-troops-regen.sql b/var/db/datagen-oasis-troops-regen.sql index 7b45027b..38dff816 100644 --- a/var/db/datagen-oasis-troops-regen.sql +++ b/var/db/datagen-oasis-troops-regen.sql @@ -2,7 +2,8 @@ -- oasis regeneration script -- used during installation, server reset, oasis reset & automation (nature repopulation) -- --- author: martinambrus +-- original author: martinambrus +-- revised and improved: haki99 -- ---------------------------------------------------------------------------------------- @@ -118,444 +119,292 @@ WHERE -- +25% lumber oasis UPDATE %PREFIX%units u - JOIN %PREFIX%odata o - ON u.vref = o.wref - SET - u.u35 = u.u35 + FLOOR((5 + RAND() * 10) * @growthFactor), - u36 = u36 + FLOOR((0 + RAND() * 5) * @growthFactor), - u37 = u37 + FLOOR((0 + RAND() * 5) * @growthFactor) - WHERE - ( - ( - @firstVillage = -1 - AND - vref IN( - SELECT - id - FROM - %PREFIX%wdata - WHERE - oasistype IN(1,2) - ) - ) - OR - ( - @firstVillage > -1 - AND - vref IN ( SELECT id FROM %PREFIX%oids ) - ) - ) - AND - ( - u35 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - OR u36 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - OR u37 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - ); +JOIN %PREFIX%odata o ON u.vref = o.wref +SET + u.u35 = LEAST( + u.u35 + FLOOR((5 + RAND() * 10) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END + ), + u.u36 = LEAST( + u.u36 + FLOOR((0 + RAND() * 5) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END + ), + u.u37 = LEAST( + u.u37 + FLOOR((0 + RAND() * 5) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END + ) +WHERE +( + (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype IN (1,2))) + OR + (@firstVillage > -1 AND u.vref IN (SELECT id FROM %PREFIX%oids)) +); -- +25% lumber and +25% crop oasis UPDATE %PREFIX%units u - JOIN %PREFIX%odata o - ON u.vref = o.wref - SET - u35 = u35 + FLOOR((5 + RAND() * 15) * @growthFactor), - u36 = u36 + FLOOR((0 + RAND() * 5) * @growthFactor), - u37 = u37 + FLOOR((0 + RAND() * 5) * @growthFactor), - u38 = u38 + FLOOR((0 + RAND() * 5) * @growthFactor), - u40 = u40 + FLOOR((0 + RAND() * 3) * @growthFactor) - WHERE - ( - ( - @firstVillage = -1 - AND - vref IN( - SELECT - id - FROM - %PREFIX%wdata - WHERE - oasistype IN(3) - ) - ) - OR - ( - @firstVillage > -1 - AND - vref IN ( SELECT id FROM %PREFIX%oids ) - ) - ) - AND - ( - u36 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - OR u37 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - OR u38 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - ); +JOIN %PREFIX%odata o ON u.vref = o.wref +SET + u35 = LEAST(u35 + FLOOR((5 + RAND() * 15) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u36 = LEAST(u36 + FLOOR((0 + RAND() * 5) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u37 = LEAST(u37 + FLOOR((0 + RAND() * 5) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u38 = LEAST(u38 + FLOOR((0 + RAND() * 5) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u40 = LEAST(u40 + FLOOR((0 + RAND() * 3) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), +WHERE +( + (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype = 3)) + OR + (@firstVillage > -1 AND u.vref IN (SELECT id FROM %PREFIX%oids)) +); -- +25% clay oasis UPDATE %PREFIX%units u - JOIN %PREFIX%odata o - ON u.vref = o.wref - SET - u31 = u31 + FLOOR((10 + RAND() * 15) * @growthFactor), - u32 = u32 + FLOOR((5 + RAND() * 15) * @growthFactor), - u35 = u35 + FLOOR((0 + RAND() * 10) * @growthFactor) - WHERE - ( - ( - @firstVillage = -1 - AND - vref IN( - SELECT - id - FROM - %PREFIX%wdata - WHERE - oasistype IN(4,5) - ) - ) - OR - ( - @firstVillage > -1 - AND - vref IN ( SELECT id FROM %PREFIX%oids ) - ) - ) - AND u31 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u32 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u35 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ); +JOIN %PREFIX%odata o ON u.vref = o.wref +SET + u31 = LEAST(u31 + FLOOR((10 + RAND() * 15) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u32 = LEAST(u32 + FLOOR((5 + RAND() * 15) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u35 = LEAST(u35 + FLOOR((0 + RAND() * 10) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), +WHERE +( + (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype IN (4,5))) + OR + (@firstVillage > -1 AND u.vref IN (SELECT id FROM %PREFIX%oids)) +); -- +25% clay and +25% crop oasis UPDATE %PREFIX%units u - JOIN %PREFIX%odata o - ON u.vref = o.wref - SET - u31 = u31 + FLOOR((15 + RAND() * 20) * @growthFactor), - u32 = u32 + FLOOR((10 + RAND() * 15) * @growthFactor), - u35 = u35 + FLOOR((0 + RAND() * 10) * @growthFactor), - u40 = u40 + FLOOR((0 + RAND() * 3) * @growthFactor) - WHERE - ( - ( - @firstVillage = -1 - AND - vref IN( - SELECT - id - FROM - %PREFIX%wdata - WHERE - oasistype IN(6) - ) - ) - OR - ( - @firstVillage > -1 - AND - vref IN ( SELECT id FROM %PREFIX%oids ) - ) - ) - AND u31 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u32 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u35 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ); +JOIN %PREFIX%odata o ON u.vref = o.wref +SET + u31 = LEAST(u31 + FLOOR((15 + RAND() * 20) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u32 = LEAST(u32 + FLOOR((10 + RAND() * 15) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u35 = LEAST(u35 + FLOOR((0 + RAND() * 10) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u40 = LEAST(u40 + FLOOR((0 + RAND() * 3) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), +WHERE +( + (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype = 6)) + OR + (@firstVillage > -1 AND u.vref IN (SELECT id FROM %PREFIX%oids)) +); -- +25% iron oasis UPDATE %PREFIX%units u - JOIN %PREFIX%odata o - ON u.vref = o.wref - SET - u31 = u31 + FLOOR((10 + RAND() * 15) * @growthFactor), - u32 = u32 + FLOOR((5 + RAND() * 15) * @growthFactor), - u34 = u34 + FLOOR((0 + RAND() * 10) * @growthFactor) - WHERE - ( - ( - @firstVillage = -1 - AND - vref IN( - SELECT - id - FROM - %PREFIX%wdata - WHERE - oasistype IN(7,8) - ) - ) - OR - ( - @firstVillage > -1 - AND - vref IN ( SELECT id FROM %PREFIX%oids ) - ) - ) - AND u31 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u32 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u34 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ); +JOIN %PREFIX%odata o ON u.vref = o.wref +SET + u31 = LEAST(u31 + FLOOR((10 + RAND() * 15) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u32 = LEAST(u32 + FLOOR((5 + RAND() * 15) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u34 = LEAST(u34 + FLOOR((0 + RAND() * 10) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), +WHERE +( + (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype IN (7,8))) + OR + (@firstVillage > -1 AND u.vref IN (SELECT id FROM %PREFIX%oids)) +); -- +25% iron and +25% crop oasis UPDATE %PREFIX%units u - JOIN %PREFIX%odata o - ON u.vref = o.wref - SET - u31 = u31 + FLOOR((15 + RAND() * 20) * @growthFactor), - u32 = u32 + FLOOR((10 + RAND() * 15) * @growthFactor), - u34 = u34 + FLOOR((0 + RAND() * 10) * @growthFactor), - u39 = u39 + FLOOR((0 + RAND() * 3) * @growthFactor) - WHERE - ( - ( - @firstVillage = -1 - AND - vref IN( - SELECT - id - FROM - %PREFIX%wdata - WHERE - oasistype IN(9) - ) - ) - OR - ( - @firstVillage > -1 - AND - vref IN ( SELECT id FROM %PREFIX%oids ) - ) - ) - AND u31 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u32 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u34 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ); +JOIN %PREFIX%odata o ON u.vref = o.wref +SET + u31 = LEAST(u31 + FLOOR((15 + RAND() * 20) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u32 = LEAST(u32 + FLOOR((10 + RAND() * 15) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u34 = LEAST(u34 + FLOOR((0 + RAND() * 10) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u39 = LEAST(u39 + FLOOR((0 + RAND() * 3) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), +WHERE +( + (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype = 9)) + OR + (@firstVillage > -1 AND u.vref IN (SELECT id FROM %PREFIX%oids)) +); -- +25% crop oasis UPDATE %PREFIX%units u - JOIN %PREFIX%odata o - ON u.vref = o.wref - SET - u31 = u31 + FLOOR((5 + RAND() * 15) * @growthFactor), - u33 = u33 + FLOOR((5 + RAND() * 10) * @growthFactor), - u37 = u37 + FLOOR((0 + RAND() * 10) * @growthFactor), - u38 = u38 + FLOOR((0 + RAND() * 5) * @growthFactor), - u39 = u39 + FLOOR((0 + RAND() * 5) * @growthFactor) - WHERE - ( - ( - @firstVillage = -1 - AND - vref IN( - SELECT - id - FROM - %PREFIX%wdata - WHERE - oasistype IN(10,11) - ) - ) - OR - ( - @firstVillage > -1 - AND - vref IN ( SELECT id FROM %PREFIX%oids ) - ) - ) - AND u31 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u33 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u37 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u38 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ); +JOIN %PREFIX%odata o ON u.vref = o.wref +SET + u31 = LEAST(u31 + FLOOR((5 + RAND() * 15) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u33 = LEAST(u33 + FLOOR((5 + RAND() * 10) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u37 = LEAST(u37 + FLOOR((0 + RAND() * 10) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u38 = LEAST(u38 + FLOOR((0 + RAND() * 5) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u39 = LEAST(u39 + FLOOR((0 + RAND() * 5) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), +WHERE +( + (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype IN (10,11))) + OR + (@firstVillage > -1 AND u.vref IN (SELECT id FROM %PREFIX%oids)) +); -- +50% crop oasis UPDATE %PREFIX%units u - JOIN %PREFIX%odata o - ON u.vref = o.wref - SET - u31 = u31 + FLOOR((10 + RAND() * 15) * @growthFactor), - u33 = u33 + FLOOR((5 + RAND() * 10) * @growthFactor), - u37 = u37 + FLOOR((0 + RAND() * 10) * @growthFactor), - u38 = u38 + FLOOR((0 + RAND() * 5) * @growthFactor), - u39 = u39 + FLOOR((0 + RAND() * 5) * @growthFactor), - u40 = u40 + FLOOR((0 + RAND() * 3) * @growthFactor) - WHERE - ( - ( - @firstVillage = -1 - AND - vref IN( - SELECT - id - FROM - %PREFIX%wdata - WHERE - oasistype IN(12) - ) - ) - OR - ( - @firstVillage > -1 - AND - vref IN ( SELECT id FROM %PREFIX%oids ) - ) - ) - AND u31 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u33 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u37 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u38 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ) - AND u39 <= ( - CASE o.high - WHEN 0 THEN (FLOOR(@minUnitsForOasis0 + RAND() * @maxUnitsForOasis0)) - WHEN 1 THEN (FLOOR(@minUnitsForOasis1 + RAND() * @maxUnitsForOasis1)) - WHEN 2 THEN (FLOOR(@minUnitsForOasis2 + RAND() * @maxUnitsForOasis2)) - END - ); +JOIN %PREFIX%odata o ON u.vref = o.wref +SET + u31 = LEAST(u31 + FLOOR((10 + RAND() * 15) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u33 = LEAST(u33 + FLOOR((5 + RAND() * 10) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u37 = LEAST(u37 + FLOOR((0 + RAND() * 10) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u38 = LEAST(u38 + FLOOR((0 + RAND() * 5) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u39 = LEAST(u39 + FLOOR((0 + RAND() * 5) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), + u40 = LEAST(u40 + FLOOR((0 + RAND() * 3) * @growthFactor), + CASE o.high + WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) + WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) + WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) + END), +WHERE +( + (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype = 12)) + OR + (@firstVillage > -1 AND u.vref IN (SELECT id FROM %PREFIX%oids)) +); From 6a555c7f391c1923c1202e47f81815aee86c3954 Mon Sep 17 00:00:00 2001 From: haki99 Date: Fri, 19 Dec 2025 23:53:06 +0100 Subject: [PATCH 22/24] Fix SQL syntax by removing parentheses --- var/db/datagen-oasis-troops-regen.sql | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/var/db/datagen-oasis-troops-regen.sql b/var/db/datagen-oasis-troops-regen.sql index 38dff816..d954d594 100644 --- a/var/db/datagen-oasis-troops-regen.sql +++ b/var/db/datagen-oasis-troops-regen.sql @@ -185,7 +185,7 @@ SET WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) - END), + END) WHERE ( (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype = 3)) @@ -249,7 +249,7 @@ SET WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) - END), + END) WHERE ( (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype = 6)) @@ -278,7 +278,7 @@ SET WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) - END), + END) WHERE ( (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype IN (7,8))) @@ -313,7 +313,7 @@ SET WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) - END), + END) WHERE ( (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype = 9)) @@ -354,7 +354,7 @@ SET WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) - END), + END) WHERE ( (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype IN (10,11))) @@ -401,7 +401,7 @@ SET WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) - END), + END) WHERE ( (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype = 12)) From 0f083fe4ed2e4e85a41ab32af014b4ef6f58cf10 Mon Sep 17 00:00:00 2001 From: haki99 Date: Fri, 19 Dec 2025 23:54:38 +0100 Subject: [PATCH 23/24] Refactor SQL --- var/db/datagen-oasis-troops-regen.sql | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/var/db/datagen-oasis-troops-regen.sql b/var/db/datagen-oasis-troops-regen.sql index d954d594..81c76126 100644 --- a/var/db/datagen-oasis-troops-regen.sql +++ b/var/db/datagen-oasis-troops-regen.sql @@ -121,30 +121,24 @@ WHERE UPDATE %PREFIX%units u JOIN %PREFIX%odata o ON u.vref = o.wref SET - u.u35 = LEAST( - u.u35 + FLOOR((5 + RAND() * 10) * @growthFactor), + u.u35 = LEAST(u.u35 + FLOOR((5 + RAND() * 10) * @growthFactor), CASE o.high WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) - END - ), - u.u36 = LEAST( - u.u36 + FLOOR((0 + RAND() * 5) * @growthFactor), + END), + u.u36 = LEAST(u.u36 + FLOOR((0 + RAND() * 5) * @growthFactor), CASE o.high WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) - END - ), - u.u37 = LEAST( - u.u37 + FLOOR((0 + RAND() * 5) * @growthFactor), + END), + u.u37 = LEAST(u.u37 + FLOOR((0 + RAND() * 5) * @growthFactor), CASE o.high WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) - END - ) + END) WHERE ( (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype IN (1,2))) @@ -214,7 +208,7 @@ SET WHEN 0 THEN FLOOR(@minUnitsForOasis0 + RAND() * (@maxUnitsForOasis0 - @minUnitsForOasis0)) WHEN 1 THEN FLOOR(@minUnitsForOasis1 + RAND() * (@maxUnitsForOasis1 - @minUnitsForOasis1)) WHEN 2 THEN FLOOR(@minUnitsForOasis2 + RAND() * (@maxUnitsForOasis2 - @minUnitsForOasis2)) - END), + END) WHERE ( (@firstVillage = -1 AND u.vref IN (SELECT id FROM %PREFIX%wdata WHERE oasistype IN (4,5))) From 70f911996d373d53a94500bfd9f71f6ffeaee2bd Mon Sep 17 00:00:00 2001 From: AlinV2V <157997483+AlinV2V@users.noreply.github.com> Date: Sat, 24 Jan 2026 00:44:54 +0200 Subject: [PATCH 24/24] Update Battle.php Fixed hero stacking deff bonus % if multiple heroes are reinforcing same village, now the deff bonus will apply only to the units that came with the hero. --- GameEngine/Battle.php | 46 +++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/GameEngine/Battle.php b/GameEngine/Battle.php index c90da0a6..aed840bf 100755 --- a/GameEngine/Battle.php +++ b/GameEngine/Battle.php @@ -279,18 +279,20 @@ class Battle { $cdp += $datadefScout['cdp']; $involve = $datadefScout['involve']; if(!$detected && $datadefScout['detect']) $detected = $datadefScout['detect']; - }else{ + }else{ $datadef = $this->getDataDef($Defender, $def_ab); - $dp += $datadef['dp']; - $cdp += $datadef['cdp']; + $own_dp = $datadef['dp']; + $own_cdp = $datadef['cdp']; $involve = $datadef['involve']; if(isset($Defender['hero']) && $Defender['hero'] != 0){ $units['Def_unit']['hero'] = $Defender['hero']; - $cdp += $defenderhero['dc']; - $dp += $defenderhero['di']; - $dp *= $defenderhero['db']; - $cdp *= $defenderhero['db']; + $own_cdp += $defenderhero['dc']; + $own_dp += $defenderhero['di']; + $own_dp *= $defenderhero['db']; + $own_cdp *= $defenderhero['db']; } + $dp += $own_dp; + $cdp += $own_cdp; } $DefendersAll = (!is_null($defReinforcements) ? $database->getEnforceVillage($DefenderWref, 0) : $defReinforcements); @@ -329,21 +331,23 @@ class Battle { $cdp += $datadefScout['cdp']; $involve = $datadefScout['involve']; if(!$detected && $datadefScout['detect']) $detected = $datadefScout['detect']; - }else{ + }else{ $datadef = $this->getDataDef($defenders, $def_ab); - $dp += $datadef['dp']; - $cdp += $datadef['cdp']; - $involve = $datadef['involve']; - } - $reinfowner = $database->getVillageField($fromvillage, "owner"); - $defhero = $this->getBattleHero($reinfowner); - - //calculate def hero from enforcement - if($defenders['hero'] != 0){ - $cdp += $defhero['dc']; - $dp += $defhero['di']; - $dp *= $defhero['db']; - $cdp *= $defhero['db']; + $reinf_dp = $datadef['dp']; + $reinf_cdp = $datadef['cdp']; + $involve += $datadef['involve']; + $reinfowner = $database->getVillageField($fromvillage, "owner"); + $defhero = $this->getBattleHero($reinfowner); + + + if($defenders['hero'] != 0 && $type != 1){ + $reinf_cdp += $defhero['dc']; + $reinf_dp += $defhero['di']; + $reinf_dp *= $defhero['db']; + $reinf_cdp *= $defhero['db']; + } + $dp += $reinf_dp; + $cdp += $reinf_cdp; } } }