Files
TravianZ/GameEngine/Building.php
T
novgorodschi catalin 55e6dd60b5 Refactor + BugFix
1. Fix a bug in Admin Panel that you can edit by yourself your rank, now you cannot edit your rank anymore.

2. Now Alliance Leader can edit his own Position

3. Fix negative value on Demolition Building, now in database at lvl is appear new level not -1

4. Refactor Ajax map, now all is alligned (Ajax folder and Map folder)

5. Fix bug from Palace (when change capital now Automation recount population automaticaly on old capital and new capital)
2026-05-18 09:18:35 +03:00

2025 lines
47 KiB
PHP
Executable File

<?php
#################################################################################
## -= YOU MAY NOT REMOVE OR CHANGE THIS NOTICE =- ##
## --------------------------------------------------------------------------- ##
## Project: TravianZ ##
## Version: 12.05.2026 ##
## Filename: Building.php ##
## Developed by: Dzoki & Dixie ##
## Refactored by: Shadow (cata7007@gmail.com) ##
## Reworked/Fix: ronix ##
## License: TravianZ Project ##
## Copyright: TravianZ (c) 2010-2026. All rights reserved. ##
## ##
## URLs: https://travianz.org ##
## https://github.com/Shadowss/TravianZ ##
## ##
#################################################################################
class Building {
public $NewBuilding = false;
private $maxConcurrent;
private $allocated;
private $basic = 0;
private $inner = 0;
private $plus = 0;
public $buildArray = array();
public function __construct() {
global $session;
$maxConcurrent = BASIC_MAX;
if (ALLOW_ALL_TRIBE || $session->tribe == 1) {
$maxConcurrent += INNER_MAX;
}
if ($session->plus) {
$maxConcurrent += PLUS_MAX;
}
$this->LoadBuilding();
if (!empty($this->buildArray)) {
foreach ($this->buildArray as $build) {
if ($build['master'] == 1) {
$maxConcurrent++;
}
}
}
$this->maxConcurrent = $maxConcurrent;
}
/*****************************************
Function to Allow WW Upgrade
*****************************************/
public function allowWwUpgrade() {
global $database, $village, $session;
static $cached = null;
if ($cached !== null) {
return $cached;
}
$wwHighestLevelFound = (int)$village->resarray['f99'];
// Evităm count() pe array doar pentru existență
$wwBuildingProgress = $database->getBuildingByType($village->wid, 99);
if (!empty($wwBuildingProgress[0]['level'])) {
$queuedLevel = (int)$wwBuildingProgress[0]['level'];
if ($queuedLevel > $wwHighestLevelFound) {
$wwHighestLevelFound = $queuedLevel;
}
}
// Cache natural prin static
$userHasWWConstructionPlans = $database->getWWConstructionPlans($session->uid);
// Nu mai facem query inutil dacă nu avem alianță
$allyHasWWConstructionPlans = false;
if ($session->alliance > 0) {
$allyHasWWConstructionPlans = $database->getWWConstructionPlans(
$session->uid,
$session->alliance
);
}
// Reducem branch-urile
$cached = (
$wwHighestLevelFound < 50
? $userHasWWConstructionPlans
: ($userHasWWConstructionPlans && $allyHasWWConstructionPlans)
);
return $cached;
}
/*****************************************
Function to Process
*****************************************/
public function canProcess($id, $tid) {
global $session, $database, $village;
// Un singur query
$levels = $database->getResourceLevel($village->wid);
// WW restriction early exit
if ($tid == 99 && !$this->allowWwUpgrade()) {
$this->redirect($tid);
}
$fieldTypeKey = 'f'.$tid.'t';
// Mic cache local
$currentFieldType = isset($levels[$fieldTypeKey]) ? (int)$levels[$fieldTypeKey] : 0;
// Validare slot/building
$isValidSlot =
(
($tid >= 1 && $tid <= 18 && $id >= 1 && $id <= 4) ||
($tid >= 19 && $id > 4)
);
// Validare building existent
$isValidFieldType =
($currentFieldType == $id || $currentFieldType == 0);
// Validare zid
$isValidWall =
($tid != 40 || in_array($id, array(31, 32, 33)));
if (
!isset($village->resarray[$fieldTypeKey]) ||
!$isValidSlot ||
!$isValidFieldType ||
!$isValidWall
) {
header('Location: '.$_SERVER['SCRIPT_NAME']);
exit;
}
// Evităm apel dublu inutil
if (!isset($_GET['master'])) {
if ($this->checkResource($id, $tid) != 4) {
$this->redirect($tid);
}
return;
}
// MASTER BUILDER
if ($currentFieldType == 0) {
// build nou
if (!$this->meetRequirement($id)) {
$this->redirect($tid);
}
} else {
// upgrade
$loopLevel = $this->isLoop($tid);
$currentLevel = $this->isCurrent($tid);
if ($this->isMax($id, $tid, $loopLevel + $currentLevel)) {
$this->redirect($tid);
}
}
}
/*****************************************
Function to redirect to dorf1 and dorf2
*****************************************/
private function redirect($tid) {
header('Location: '.($tid >= 19 ? 'dorf2.php' : 'dorf1.php'));
exit;
}
/*****************************************
Function to proc Building
*****************************************/
public function procBuild($get) {
global $session, $village, $database;
// Cache checker comparison
$validChecker = (
isset($get['c']) &&
$get['c'] == $session->checker
);
// REMOVE / UPGRADE EXISTING
if (isset($get['a']) && !isset($get['id']) && $validChecker) {
if ($get['a'] == 0) {
$this->removeBuilding($get['d']);
return;
}
$session->changeChecker();
$fieldType = $village->resarray['f'.$get['a'].'t'];
$this->canProcess($fieldType, $get['a']);
$this->upgradeBuilding($get['a']);
return;
}
// MASTER BUILDER
if (
isset($get['master'], $get['id']) &&
$validChecker &&
$session->gold >= 1 &&
$session->goldclub &&
$village->master == 0
) {
$this->canProcess($get['master'], $get['id']);
$session->changeChecker();
// Un singur query
$level = $database->getResourceLevel($village->wid);
// Un singur calcul
$required = $this->resourceRequired($get['id'], $get['master']);
// Un singur query
$queuedBuildings = $database->getBuildingByField(
$village->wid,
$get['id']
);
$database->addBuilding(
$village->wid,
$get['id'],
$get['master'],
1,
$required['time'],
1,
$level['f'.$get['id']] + 1 + count($queuedBuildings)
);
$this->redirect($get['id']);
}
// CONSTRUCT NEW BUILDING
if (
isset($get['a'], $get['id']) &&
$validChecker
) {
if ($get['id'] > 18 && ($get['id'] < 41 || $get['id'] == 99)) {
$session->changeChecker();
$this->canProcess($get['a'], $get['id']);
$this->constructBuilding($get['id'], $get['a']);
}
return;
}
// FINISH ALL
if (
isset($get['buildingFinish']) &&
$session->gold >= 2 &&
$session->sit == 0
) {
$this->finishAll();
}
}
public function canBuild($id, $tid) {
global $village, $session, $database;
// Query unic
$demolition = $database->getDemolition($village->wid);
if (
isset($demolition[0]['buildnumber']) &&
$demolition[0]['buildnumber'] == $id
) {
return 11;
}
// Cache funcții repetitive
$loop = $this->isLoop($id);
$current = $this->isCurrent($id);
if ($this->isMax($tid, $id)) {
return 1;
}
if (
$this->isMax($tid, $id, 1) &&
($loop || $current)
) {
return 10;
}
if (
$this->isMax($tid, $id, 2) &&
$loop &&
$current
) {
return 10;
}
// Evităm query inutil getMasterJobs()
if (
$loop &&
$current &&
$this->isMax($tid, $id, 3)
) {
$masterJobs = $database->getMasterJobs($village->wid);
if (!empty($masterJobs)) {
return 10;
}
}
if ($this->allocated > $this->maxConcurrent) {
return 2;
}
// Un singur apel
$fieldType = $village->resarray['f'.$id.'t'];
// Un singur apel
$resRequired = $this->resourceRequired($id, $fieldType);
$resRequiredPop = isset($resRequired['pop'])
? $resRequired['pop']
: 0;
// Fallback doar dacă trebuie
if (empty($resRequiredPop)) {
$buildarray = $GLOBALS['bid'.$tid];
$resRequiredPop = $buildarray[1]['pop'];
}
// Un singur query
$jobs = $database->getJobs($village->wid);
$soonPop = 0;
if (!empty($jobs)) {
foreach ($jobs as $j) {
$buildarray = $GLOBALS['bid'.$j['type']];
// Aici era query per job (!)
// Reducem drastic CPU + SQL
static $fieldLevelCache = array();
$cacheKey = $village->wid.'_'.$j['field'];
if (!isset($fieldLevelCache[$cacheKey])) {
$fieldLevelCache[$cacheKey] = $database->getFieldLevel(
$village->wid,
$j['field']
);
}
$soonPop += $buildarray[
$fieldLevelCache[$cacheKey] + 1
]['pop'];
}
}
if (
($village->allcrop - $village->pop - $soonPop - $resRequiredPop) <= 1 &&
$fieldType != 4
) {
return 4;
}
// Un singur apel
$resourceCheck = $this->checkResource($tid, $id);
switch ($resourceCheck) {
case 1:
return 5;
case 2:
return 6;
case 3:
return 7;
case 4:
if ($id >= 19) {
$hasMainBuilding =
(
$session->tribe == 1 ||
ALLOW_ALL_TRIBE
)
? $this->inner
: $this->basic;
if ($hasMainBuilding == 0) {
return 8;
}
if ($session->plus || $tid == 40) {
return ($this->plus == 0 ? 9 : 3);
}
return 2;
}
if ($this->basic == 1) {
if (($session->plus || $tid == 40) && $this->plus == 0) {
return 9;
}
return 3;
}
return 8;
}
}
/*****************************************
Function to wall
*****************************************/
public function walling() {
global $session;
foreach ($this->buildArray as $job) {
// verificăm STRICT tipul clădirii
if (
$job['type'] == 31 ||
$job['type'] == 32 ||
$job['type'] == 33
) {
return $job['type'];
}
}
return false;
}
/*****************************************
Function to rally point
*****************************************/
public function rallying() {
if (empty($this->buildArray)) {
return false;
}
foreach ($this->buildArray as $job) {
// comparație directă mai rapidă
if ((int)$job['type'] === 16) {
return true;
}
}
return false;
}
/*****************************************
Function to proc resource type
*****************************************/
public static function procResType($ref) {
// Cache static -> switch-ul nu mai este evaluat constant
static $types = array(
1 => WOODCUTTER,
2 => CLAYPIT,
3 => IRONMINE,
4 => CROPLAND,
5 => SAWMILL,
6 => BRICKYARD,
7 => IRONFOUNDRY,
8 => GRAINMILL,
9 => BAKERY,
10 => WAREHOUSE,
11 => GRANARY,
12 => BLACKSMITH,
13 => ARMOURY,
14 => TOURNAMENTSQUARE,
15 => MAINBUILDING,
16 => RALLYPOINT,
17 => MARKETPLACE,
18 => EMBASSY,
19 => BARRACKS,
20 => STABLE,
21 => WORKSHOP,
22 => ACADEMY,
23 => CRANNY,
24 => TOWNHALL,
25 => RESIDENCE,
26 => PALACE,
27 => TREASURY,
28 => TRADEOFFICE,
29 => GREATBARRACKS,
30 => GREATSTABLE,
31 => CITYWALL,
32 => EARTHWALL,
33 => PALISADE,
34 => STONEMASON,
35 => BREWERY,
36 => TRAPPER,
37 => HEROSMANSION,
38 => GREATWAREHOUSE,
39 => GREATGRANARY,
40 => WONDER,
41 => HORSEDRINKING,
42 => GREATWORKSHOP
);
return isset($types[$ref]) ? $types[$ref] : 'Error';
}
/*****************************************
Function to load all building
*****************************************/
public function loadBuilding() {
global $database, $village, $session;
$this->basic = 0;
$this->inner = 0;
$this->plus = 0;
// un singur query
$this->buildArray = $database->getJobs($village->wid);
// count() o singură dată
$this->allocated = count($this->buildArray);
if ($this->allocated <= 0) {
$this->NewBuilding = false;
return;
}
$romanQueue = ($session->tribe == 1 || ALLOW_ALL_TRIBE);
foreach ($this->buildArray as $build) {
// master queue
if ((int)$build['loopcon'] === 1) {
$this->plus = 1;
continue;
}
// resource fields
if ($build['field'] <= 18) {
$this->basic++;
continue;
}
// village buildings
if ($romanQueue) {
$this->inner++;
} else {
$this->basic++;
}
}
$this->NewBuilding = true;
}
/*****************************************
Function to remove building
*****************************************/
private function removeBuilding($d) {
global $database, $village, $session;
if (empty($this->buildArray)) {
return;
}
foreach ($this->buildArray as $jobs) {
// early continue
if ($jobs['id'] != $d) {
continue;
}
// calcul doar când chiar trebuie
$uprequire = $this->resourceRequired(
$jobs['field'],
$jobs['type']
);
if (
$database->removeBuilding(
$d,
$session->tribe,
$village->wid,
$village->resarray
)
) {
// refund doar pentru non-master
if ((int)$jobs['master'] === 0) {
$database->modifyResource(
$village->wid,
$uprequire['wood'],
$uprequire['clay'],
$uprequire['iron'],
$uprequire['crop'],
1
);
}
$this->redirect($jobs['field']);
}
// nu mai continuăm foreach inutil
break;
}
}
/*****************************************
Function to upgrade building
*****************************************/
private function upgradeBuilding($id) {
global $database, $village, $session, $logging, ${'bid'.$village->resarray['f'.$id.'t']};
if (!$database->getBuildLock($village->wid)) {
return;
}
try {
$this->loadBuilding();
if ($this->allocated >= $this->maxConcurrent) {
return;
}
$fieldType = $village->resarray['f'.$id.'t'];
// un singur apel
$uprequire = $this->resourceRequired($id, $fieldType);
$time = time() + $uprequire['time'];
// un singur apel
$bindicate = $this->canBuild($id, $fieldType);
// early exit
if (in_array($bindicate, array(1, 2, 3, 10, 11))) {
header('Location: dorf2.php');
exit;
}
$loop = ($bindicate == 9 ? 1 : 0);
$loopsame = 0;
if ($loop == 1) {
foreach ($this->buildArray as $build) {
if ($build['field'] == $id) {
$loopsame++;
// păstrăm logica originală
$uprequire = $this->resourceRequired(
$id,
$fieldType,
($loopsame > 0 ? 2 : 1)
);
}
}
$romanQueue = ($session->tribe == 1 || ALLOW_ALL_TRIBE);
if ($romanQueue) {
if ($id >= 19) {
foreach ($this->buildArray as $build) {
if ($build['field'] >= 19) {
$time = $build['timestamp'] + $uprequire['time'];
}
}
} else {
foreach ($this->buildArray as $build) {
if ($build['field'] <= 18) {
$time = $build['timestamp'] + $uprequire['time'];
}
}
}
} else {
if (isset($this->buildArray[0]['timestamp'])) {
$time = $this->buildArray[0]['timestamp'] + $uprequire['time'];
}
}
}
// un singur query
$level = $database->getResourceLevel($village->wid);
// un singur query
$queuedBuildings = $database->getBuildingByField(
$village->wid,
$id
);
$nextLevel =
$level['f'.$id] +
1 +
count($queuedBuildings);
if (
$database->addBuilding(
$village->wid,
$id,
$fieldType,
$loop,
$time + ($loop == 1 ? ceil(60 / SPEED) : 0),
0,
$nextLevel
)
) {
$database->modifyResource(
$village->wid,
$uprequire['wood'],
$uprequire['clay'],
$uprequire['iron'],
$uprequire['crop'],
0
);
$logging->addBuildLog(
$village->wid,
self::procResType($fieldType),
($village->resarray['f'.$id] + ($loopsame > 0 ? 2 : 1)),
0
);
$this->redirect($id);
}
} finally {
$database->releaseBuildLock($village->wid);
}
}
/*****************************************
Function to downgrade building
*****************************************/
private function downgradeBuilding($id) {
global $database, $village, $session, $logging;
if (!$database->getBuildLock($village->wid)) {
return;
}
try {
$this->loadBuilding();
if ($this->allocated >= $this->maxConcurrent) {
return;
}
$fieldType = $village->resarray['f'.$id.'t'];
$currentLevel = $village->resarray['f'.$id];
$name = 'bid'.$fieldType;
global $$name;
$dataarray = $$name;
// calcul o singură dată
$buildTime = round($dataarray[$currentLevel - 1]['time'] / 4);
$time = time() + $buildTime;
$loop = 0;
// logică identică, branch-uri reduse
if (
($this->inner == 1 || $this->basic == 1) &&
(($session->plus || $fieldType == 40) && $this->plus == 0)
) {
$loop = 1;
}
if ($loop == 1) {
$romanQueue = ($session->tribe == 1 || ALLOW_ALL_TRIBE);
if ($romanQueue) {
if ($id >= 19) {
foreach ($this->buildArray as $build) {
if ($build['field'] >= 19) {
$time = $build['timestamp'] + $buildTime;
}
}
}
} else {
if (isset($this->buildArray[0]['timestamp'])) {
$time = $this->buildArray[0]['timestamp'] + $buildTime;
}
}
}
// un singur query
$level = $database->getResourceLevel($village->wid);
// un singur query
$queuedBuildings = $database->getBuildingByField(
$village->wid,
$id
);
if (
$database->addBuilding(
$village->wid,
$id,
$fieldType,
$loop,
$time,
0,
0,
$level['f'.$id] + 1 + count($queuedBuildings)
)
) {
$logging->addBuildLog(
$village->wid,
self::procResType($fieldType),
($currentLevel - 1),
2
);
header('Location: dorf2.php');
exit();
}
} finally {
$database->releaseBuildLock($village->wid);
}
}
/*****************************************
Function to construct building
*****************************************/
private function constructBuilding($id, $tid) {
global $database, $village, $session, $logging;
if (!$database->getBuildLock($village->wid)) {
return;
}
try {
$this->loadBuilding();
if ($this->allocated >= $this->maxConcurrent) {
header('Location: dorf2.php');
exit;
}
// păstrăm exact logica originală
$buildField = $id;
if ($tid == 16) {
$buildField = 39;
}
elseif ($tid == 31 || $tid == 32 || $tid == 33) {
$buildField = 40;
}
// un singur apel
$uprequire = $this->resourceRequired($buildField, $tid);
$time = time() + $uprequire['time'];
// un singur apel
$bindicate = $this->canBuild($buildField, $tid);
$loop = ($bindicate == 9 ? 1 : 0);
if ($loop == 1) {
$romanQueue = ($session->tribe == 1 || ALLOW_ALL_TRIBE);
foreach ($this->buildArray as $build) {
if (
$build['field'] >= 19 ||
!$romanQueue
) {
$time =
$build['timestamp'] +
ceil(60 / SPEED) +
$uprequire['time'];
}
}
}
// early exit
if (!$this->meetRequirement($tid)) {
header('Location: dorf2.php');
exit;
}
// un singur query
$level = $database->getResourceLevel($village->wid);
// un singur query
$queuedBuildings = $database->getBuildingByField(
$village->wid,
$buildField
);
$nextLevel =
$level['f'.$buildField] +
1 +
count($queuedBuildings);
if (
$database->addBuilding(
$village->wid,
$buildField,
$tid,
$loop,
$time,
0,
$nextLevel
)
) {
$logging->addBuildLog(
$village->wid,
self::procResType($tid),
($village->resarray['f'.$buildField] + 1),
1
);
$database->modifyResource(
$village->wid,
$uprequire['wood'],
$uprequire['clay'],
$uprequire['iron'],
$uprequire['crop'],
0
);
header('Location: dorf2.php');
exit;
}
} finally {
$database->releaseBuildLock($village->wid);
}
}
/*****************************************
Function to Pallace Build ?
*****************************************/
public function isCastleBuilt() {
global $database, $session;
// un singur query
$villages = $database->getProfileVillages($session->uid);
if (empty($villages)) {
return false;
}
// cache local pentru level queries
static $villageLevelCache = array();
foreach ($villages as $vil) {
$wid = $vil['wref'];
if (!isset($villageLevelCache[$wid])) {
$villageLevelCache[$wid] = $database->getResourceLevel($wid);
}
if (in_array(26, $villageLevelCache[$wid])) {
return true;
}
}
return false;
}
/*****************************************
Function to meet requirement
*****************************************/
private function meetRequirement($id) {
global $village, $session, $database;
// cache local enorm de important
static $typeLevelCache = array();
static $typeFieldCache = array();
$getLevel = function($type) use (&$typeLevelCache) {
if (!isset($typeLevelCache[$type])) {
$typeLevelCache[$type] = $this->getTypeLevel($type);
}
return $typeLevelCache[$type];
};
$getField = function($type) use (&$typeFieldCache) {
if (!isset($typeFieldCache[$type])) {
$typeFieldCache[$type] = $this->getTypeField($type);
}
return $typeFieldCache[$type];
};
$isBuilt = $getField($id);
switch ($id) {
case 1:
case 2:
case 3:
case 4:
return true;
case 5:
return $getLevel(1) >= 10 &&
$getLevel(15) >= 5 &&
!$isBuilt;
case 6:
return $getLevel(2) >= 10 &&
$getLevel(15) >= 5 &&
!$isBuilt;
case 7:
return $getLevel(3) >= 10 &&
$getLevel(15) >= 5 &&
!$isBuilt;
case 8:
return $getLevel(4) >= 5 &&
!$isBuilt;
case 9:
return $getLevel(15) >= 5 &&
$getLevel(4) >= 10 &&
$getLevel(8) >= 5 &&
!$isBuilt;
case 10:
case 11:
return $getLevel(15) >= 1 &&
(!$isBuilt || $getLevel($id) == 20);
case 12:
return $getLevel(22) >= 3 &&
$getLevel(15) >= 3 &&
!$isBuilt;
case 13:
return $getLevel(15) >= 3 &&
$getLevel(22) >= 1 &&
!$isBuilt;
case 14:
return $getLevel(16) >= 15 &&
!$isBuilt;
case 15:
case 16:
return !$isBuilt;
case 17:
return $getLevel(15) >= 3 &&
$getLevel(10) >= 1 &&
$getLevel(11) >= 1 &&
!$isBuilt;
case 18:
return $getLevel(15) >= 1 &&
!$isBuilt;
case 19:
return $getLevel(15) >= 3 &&
$getLevel(16) >= 1 &&
!$isBuilt;
case 20:
return $getLevel(12) >= 3 &&
$getLevel(22) >= 5 &&
!$isBuilt;
case 21:
return $getLevel(22) >= 10 &&
$getLevel(15) >= 5 &&
!$isBuilt;
case 22:
return $getLevel(15) >= 3 &&
$getLevel(19) >= 3 &&
!$isBuilt;
case 23:
return !$isBuilt || $getLevel($id) == 10;
case 24:
return $getLevel(22) >= 10 &&
$getLevel(15) >= 10 &&
!$isBuilt;
case 25:
return $getLevel(15) >= 5 &&
!$isBuilt &&
!$getField(26);
case 26:
return $getLevel(18) >= 1 &&
$getLevel(15) >= 5 &&
!$isBuilt &&
!$this->isCastleBuilt() &&
!$getField(25);
case 27:
return $getLevel(15) >= 10 &&
!$isBuilt;
case 28:
return $getLevel(17) == 20 &&
$getLevel(20) >= 10 &&
!$isBuilt;
case 29:
return $getLevel(19) == 20 &&
$village->capital == 0 &&
!$isBuilt;
case 30:
return $getLevel(20) == 20 &&
$village->capital == 0 &&
!$isBuilt;
case 31:
return $session->tribe == 1;
case 32:
return $session->tribe == 2;
case 33:
return $session->tribe == 3;
case 34:
return $getLevel(26) >= 3 &&
$getLevel(15) >= 5 &&
$getLevel(25) == 0 &&
$village->capital != 0 &&
!$isBuilt;
case 35:
return $getLevel(16) >= 10 &&
$getLevel(11) == 20 &&
$session->tribe == 2 &&
$village->capital != 0 &&
!$isBuilt;
case 36:
return $getLevel(16) >= 1 &&
$session->tribe == 3 &&
(!$isBuilt || $getLevel($id) == 20);
case 37:
return $getLevel(15) >= 3 &&
$getLevel(16) >= 1 &&
!$isBuilt;
// Great Warehouse
case 38:
static $greatWarehouseArtefact = null;
if ($greatWarehouseArtefact === null) {
$greatWarehouseArtefact =
(
count($database->getOwnUniqueArtefactInfo2($village->wid, 6, 1, 1)) ||
count($database->getOwnUniqueArtefactInfo2($session->uid, 6, 2, 0))
);
}
return $getLevel(15) >= 10 &&
(!$isBuilt || $getLevel($id) == 20) &&
($village->natar == 1 || $greatWarehouseArtefact);
// Great Granary
case 39:
static $greatGranaryArtefact = null;
if ($greatGranaryArtefact === null) {
$greatGranaryArtefact =
(
count($database->getOwnUniqueArtefactInfo2($village->wid, 6, 1, 1)) ||
count($database->getOwnUniqueArtefactInfo2($session->uid, 6, 2, 0))
);
}
return $getLevel(15) >= 10 &&
(!$isBuilt || $getLevel($id) == 20) &&
($village->natar == 1 || $greatGranaryArtefact);
case 40:
return $this->allowWwUpgrade();
case 41:
return $getLevel(16) >= 10 &&
$getLevel(20) == 20 &&
$session->tribe == 1 &&
!$isBuilt;
case 42:
return GREAT_WKS &&
$getLevel(21) == 20 &&
$village->capital == 0 &&
!$isBuilt;
default:
return false;
}
}
/*****************************************
Function to check resources available
*****************************************/
private function checkResource($tid, $id) {
global $village, $database;
$name = 'bid'.$tid;
global $$name;
$dataarray = $$name;
// evităm foreach inutil lung
$plus = 1;
if (!empty($this->buildArray)) {
foreach ($this->buildArray as $job) {
if (
$job['type'] == $tid &&
$job['field'] == $id
) {
$plus = 2;
break;
}
}
}
// cache local
$nextLevel = $village->resarray['f'.$id] + $plus;
$required = $dataarray[$nextLevel];
$wood = $required['wood'];
$clay = $required['clay'];
$iron = $required['iron'];
$crop = $required['crop'];
// store limit
if (
$wood > $village->maxstore ||
$clay > $village->maxstore ||
$iron > $village->maxstore
) {
return 1;
}
// granary limit
if ($crop > $village->maxcrop) {
return 2;
}
// not enough resources
if (
$wood > $village->awood ||
$clay > $village->aclay ||
$iron > $village->airon ||
$crop > $village->acrop
) {
return 3;
}
return 4;
}
/*****************************************
Function to building is max level ?
*****************************************/
public function isMax($id, $field, $loop = 0) {
global $village, $session;
$name = 'bid'.$id;
global $$name;
$dataarray = $$name;
$currentLevel = $village->resarray['f'.$field];
// special MH case
if ($session->tribe == 0) {
return ($currentLevel == 20);
}
// resource fields
if ($id <= 4) {
$maxLevel = (
$village->capital == 1
? (count($dataarray) - 1 - $loop)
: (count($dataarray) - 11 - $loop)
);
return ($currentLevel == $maxLevel);
}
// normal buildings
return ($currentLevel == (count($dataarray) - $loop));
}
/*****************************************
Function to get type level
*****************************************/
public function getTypeLevel($tid, $vid = 0) {
global $village, $database, $session;
// support account
if ($session->uid == 1) {
return 0;
}
// cache masiv de important
static $resourceCache = array();
static $typeLevelCache = array();
$cacheKey = $tid.'_'.$vid;
if (isset($typeLevelCache[$cacheKey])) {
return $typeLevelCache[$cacheKey];
}
// evităm query-uri repetate
if ($vid == 0) {
$resourcearray = $village->resarray;
} else {
if (!isset($resourceCache[$vid])) {
$resourceCache[$vid] = $database->getResourceLevel($vid);
}
$resourcearray = $resourceCache[$vid];
}
$keyholder = array();
// mai rapid decât array_keys + strpos
foreach ($resourcearray as $key => $value) {
if (
$value == $tid &&
strpos($key, 't') !== false
) {
$keyholder[] = (int)preg_replace('/[^0-9]/', '', $key);
}
}
$element = count($keyholder);
// no building
if ($element == 0) {
$typeLevelCache[$cacheKey] = 0;
return 0;
}
// single building
if ($element == 1) {
$result = $resourcearray['f'.$keyholder[0]];
$typeLevelCache[$cacheKey] = $result;
return $result;
}
// multiple buildings
$target = 0;
// resource fields
if ($tid <= 4) {
$maxLevel = -1;
foreach ($keyholder as $index => $fieldId) {
$level = $resourcearray['f'.$fieldId];
if ($level > $maxLevel) {
$maxLevel = $level;
$target = $index;
}
}
} else {
// village buildings
foreach ($keyholder as $index => $fieldId) {
if (
$resourcearray['f'.$fieldId] >
$resourcearray['f'.$keyholder[$target]]
) {
$target = $index;
}
}
}
$result = isset($keyholder[$target])
? $resourcearray['f'.$keyholder[$target]]
: 0;
$typeLevelCache[$cacheKey] = $result;
return $result;
}
/*****************************************
Function to is current ?
*****************************************/
public function isCurrent($id) {
if (empty($this->buildArray)) {
return false;
}
foreach ($this->buildArray as $build) {
if (
$build['field'] == $id &&
$build['loopcon'] != 1
) {
return true;
}
}
return false;
}
/*****************************************
Function to is loop ?
*****************************************/
public function isLoop($id = 0) {
if (empty($this->buildArray)) {
return false;
}
foreach ($this->buildArray as $build) {
if (
($build['field'] == $id && $build['loopcon']) ||
($build['loopcon'] == 1 && $id == 0)
) {
return true;
}
}
return false;
}
/*****************************************
Function to finish all with gold
*****************************************/
public function finishAll($redirect_url = '') {
global $database, $session, $logging, $village;
global $bid18, $bid10, $bid11, $technology, $_SESSION;
$countPlus2Gold = false;
$countMasterGold = false;
$buildcount = (!empty($this->buildArray)
? count($this->buildArray)
: 0);
$deletIDs = array();
// cache query-uri
static $villageResourceCache = array();
static $villageFieldCache = array();
foreach ($this->buildArray as $jobs) {
if ($jobs['wid'] != $village->wid) {
continue;
}
$wid = $jobs['wid'];
// cache getResourceLevel
if (!isset($villageResourceCache[$wid])) {
$villageResourceCache[$wid] = $database->getResourceLevel($wid);
}
$wwvillage = $villageResourceCache[$wid];
// skip WW
if ($wwvillage['f99t'] == 40) {
continue;
}
$level = $jobs['level'];
// skip excluded
if (
$jobs['type'] == 25 ||
$jobs['type'] == 26 ||
$jobs['type'] == 40
) {
continue;
}
$resource = $this->resourceRequired(
$jobs['field'],
$jobs['type']
);
$jobFinishSuccess = false;
$enought_res = 0;
$exclude_master = false;
// MASTER BUILDER
if ($jobs['master'] != 0) {
if ($this->meetRequirement($jobs['field'])) {
// fix gold edge case
if ($session->gold > 2) {
// cache village fields
if (!isset($villageFieldCache[$wid])) {
$villageFieldCache[$wid] = array(
'wood' => $database->getVillageField($wid, 'wood'),
'clay' => $database->getVillageField($wid, 'clay'),
'iron' => $database->getVillageField($wid, 'iron'),
'crop' => $database->getVillageField($wid, 'crop')
);
}
$villwood = $villageFieldCache[$wid]['wood'];
$villclay = $villageFieldCache[$wid]['clay'];
$villiron = $villageFieldCache[$wid]['iron'];
$villcrop = $villageFieldCache[$wid]['crop'];
$type = $jobs['type'];
$buildarray = $GLOBALS['bid'.$type];
$buildwood = $buildarray[$level]['wood'];
$buildclay = $buildarray[$level]['clay'];
$buildiron = $buildarray[$level]['iron'];
$buildcrop = $buildarray[$level]['crop'];
if (
$buildwood < $villwood &&
$buildclay < $villclay &&
$buildiron < $villiron &&
$buildcrop < $villcrop
) {
$jobFinishSuccess = true;
$countMasterGold = true;
$enought_res = 1;
// scădem resurse doar dacă e nevoie
if ($buildcount > 2) {
$database->setVillageField(
$wid,
array('wood', 'clay', 'iron', 'crop'),
array(
($villwood - $buildwood),
($villclay - $buildclay),
($villiron - $buildiron),
($villcrop - $buildcrop)
)
);
}
}
} else {
$exclude_master = true;
$deletIDs[] = (int)$jobs['id'];
}
}
} else {
// normal build
$countPlus2Gold = true;
$jobFinishSuccess = true;
}
// update building
if ($jobFinishSuccess) {
$q = "
UPDATE ".TB_PREFIX."fdata
SET
f".$jobs['field']." = ".$jobs['level'].",
f".$jobs['field']."t = ".$jobs['type']."
WHERE vref = ".$wid;
if (
!$exclude_master &&
$database->query($q) &&
($enought_res == 1 || $jobs['master'] == 0)
) {
$database->modifyPop(
$wid,
$resource['pop'],
0
);
$deletIDs[] = (int)$jobs['id'];
// embassy update
if ($jobs['type'] == 18) {
$owner = $database->getVillageField(
$wid,
'owner'
);
$max = $bid18[$level]['attri'];
$database->query("UPDATE ".TB_PREFIX."alidata SET max=".$max." WHERE leader=".$owner);
}
}
}
// roman queue
if (
($jobs['field'] >= 19 &&
($session->tribe == 1 || ALLOW_ALL_TRIBE)) ||
(!ALLOW_ALL_TRIBE && $session->tribe != 1)
) {
$innertimestamp = $jobs['timestamp'];
}
}
// single delete query
if (!empty($deletIDs)) {
$database->query("
DELETE FROM ".TB_PREFIX."bdata
WHERE id IN(".implode(',', $deletIDs).")
");
}
$demolition = $database->finishDemolition($village->wid);
$tech = $technology->finishTech();
if ($demolition > 0 || $tech > 0) {
$countPlus2Gold = true;
$logging->goldFinLog($village->wid);
}
// gold update
if ($countMasterGold || $countPlus2Gold) {
$newgold = $session->gold -
(($countMasterGold && $countPlus2Gold) ? 3 : 2);
$database->updateUserField(
$session->uid,
'gold',
$newgold,
1
);
}
// un singur query
$stillbuildingarray = $database->getJobs($village->wid);
if (
count($stillbuildingarray) == 1 &&
$stillbuildingarray[0]['loopcon'] == 1
) {
$database->query("
UPDATE ".TB_PREFIX."bdata
SET loopcon = 0
WHERE id = ".(int)$stillbuildingarray[0]['id']
);
}
self::recountCP($database, $village->wid);
header('Location: '.(
$redirect_url
? $redirect_url
: $session->referrer
));
exit;
}
/*****************************************
Function to recount culture point
*****************************************/
public static function recountCP($database, $vid) {
$vid = (int)$vid;
// un singur query
$fdata = $database->getResourceLevel($vid);
$cpTot = 0;
// micro-optimizare
for ($i = 1; $i <= 40; $i++) {
$building = (int)$fdata['f'.$i.'t'];
// skip rapid
if ($building <= 0) {
continue;
}
$lvl = (int)$fdata['f'.$i];
$cpTot += self::buildingCP($building, $lvl);
}
// evităm string concat multiplu
mysqli_query(
$database->dblink,
"
UPDATE ".TB_PREFIX."vdata
SET cp = ".$cpTot."
WHERE wref = ".$vid
);
}
/*****************************************
Function to building culture point
*****************************************/
public static function buildingCP($f, $lvl) {
// cache static enorm de util
static $cpCache = array();
$cacheKey = $f.'_'.$lvl;
if (isset($cpCache[$cacheKey])) {
return $cpCache[$cacheKey];
}
$name = 'bid'.$f;
global $$name;
$dataarray = $$name;
$cp = (
isset($dataarray[$lvl]['cp'])
? $dataarray[$lvl]['cp']
: 0
);
$cpCache[$cacheKey] = $cp;
return $cp;
}
/*****************************************
Function to ressource required
*****************************************/
public function resourceRequired($id, $tid, $plus = 1) {
global $village, $bid15, $database;
$name = 'bid'.$tid;
global $$name;
// cache static foarte important
static $resourceCache = array();
$cacheKey =
$id.'_'.
$tid.'_'.
$plus.'_'.
$village->wid;
if (isset($resourceCache[$cacheKey])) {
return $resourceCache[$cacheKey];
}
$dataarray = $$name;
// safety
if (!$dataarray) {
$empty = array(
'wood' => 0,
'clay' => 0,
'iron' => 0,
'crop' => 0,
'pop' => 0,
'time' => 0,
'cp' => 0
);
$resourceCache[$cacheKey] = $empty;
return $empty;
}
$level = $village->resarray['f'.$id] + $plus;
// un singur lookup
$required = $dataarray[$level];
$result = array(
'wood' => $required['wood'],
'clay' => $required['clay'],
'iron' => $required['iron'],
'crop' => $required['crop'],
'pop' => $required['pop'],
'time' => $database->getBuildingTime(
$id,
$tid,
$plus,
$village->wid,
$village->resarray
),
'cp' => $required['cp']
);
$resourceCache[$cacheKey] = $result;
return $result;
}
/*****************************************
Function to get type level
*****************************************/
public function getTypeField($type) {
global $village;
// cache static
static $typeFieldCache = array();
if (isset($typeFieldCache[$type])) {
return $typeFieldCache[$type];
}
for ($i = 19; $i <= 40; $i++) {
if ($village->resarray['f'.$i.'t'] == $type) {
$typeFieldCache[$type] = $i;
return $i;
}
}
$typeFieldCache[$type] = false;
return false;
}
/*****************************************
Function to calculate avaliable
*****************************************/
public function calculateAvaliable($id, $tid, $plus = 1) {
global $village, $generator;
// un singur apel
$uprequire = $this->resourceRequired($id, $tid, $plus);
// cache producții
static $prodCache = array();
if (empty($prodCache)) {
$prodCache = array(
'wood' => $village->getProd('wood'),
'clay' => $village->getProd('clay'),
'crop' => $village->getProd('crop'),
'iron' => $village->getProd('iron')
);
}
$rwood = $uprequire['wood'] - $village->awood;
$rclay = $uprequire['clay'] - $village->aclay;
$rcrop = $uprequire['crop'] - $village->acrop;
$riron = $uprequire['iron'] - $village->airon;
// formule identice, branch-uri reduse
$rwtime = (
$rwood > 0 && $prodCache['wood'] > 0
? ($rwood / $prodCache['wood']) * 3600
: 0
);
$rcltime = (
$rclay > 0 && $prodCache['clay'] > 0
? ($rclay / $prodCache['clay']) * 3600
: 0
);
$rctime = (
$rcrop > 0 && $prodCache['crop'] > 0
? ($rcrop / $prodCache['crop']) * 3600
: 0
);
$ritime = (
$riron > 0 && $prodCache['iron'] > 0
? ($riron / $prodCache['iron']) * 3600
: 0
);
$reqtime = max(
$rwtime,
$rctime,
$rcltime,
$ritime
) + time();
return $generator->procMtime($reqtime);
}
};
?>