mirror of
https://github.com/Shadowss/TravianZ.git
synced 2026-07-14 16:46:08 +00:00
25c8925ef6
NEW TRIBES ENHANCEMENT (Huns, Egipteans, Spartans & Vikings) #327 Please be advised, is not fully tested so if you activate on install maybe is not fully working
929 lines
40 KiB
PHP
Executable File
929 lines
40 KiB
PHP
Executable File
<?php
|
|
|
|
#################################################################################
|
|
## -= YOU MAY NOT REMOVE OR CHANGE THIS NOTICE =- ##
|
|
## --------------------------------------------------------------------------- ##
|
|
## Filename : Units.php ##
|
|
## Type : Units System Backend ##
|
|
## --------------------------------------------------------------------------- ##
|
|
## Developed by : Dzoki ##
|
|
## Refactored by : Shadow & Ferywir ##
|
|
## Thanks to : ronix, InCube, Akakori, Elmar & Kirilloid ##
|
|
## --------------------------------------------------------------------------- ##
|
|
## Contact : cata7007@gmail.com ##
|
|
## Project : TravianZ ##
|
|
## URLs: : https://travianz.org ##
|
|
## GitHub : https://github.com/Shadowss/TravianZ ##
|
|
## --------------------------------------------------------------------------- ##
|
|
## License : TravianZ Project ##
|
|
## Copyright : TravianZ (c) 2010-2026. All rights reserved. ##
|
|
## --------------------------------------------------------------------------- ##
|
|
#################################################################################
|
|
|
|
class Units {
|
|
public $sending, $recieving, $return = [];
|
|
|
|
public function procUnits($post) {
|
|
if(isset($post['c'])) {
|
|
if (!isset($post['disabled'])) $post['disabled'] = '';
|
|
|
|
switch($post['c']) {
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
if (isset($post['a']) && $post['a'] == 533374 && empty($post['disabled'])) $this->sendTroops($post);
|
|
else
|
|
{
|
|
$post = $this->loadUnits($post);
|
|
return $post;
|
|
}
|
|
break;
|
|
|
|
case 5:
|
|
if (isset($post['a']) && $post['a'] == "new") $this->Settlers($post);
|
|
else
|
|
{
|
|
$post = $this->loadUnits($post);
|
|
return $post;
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
$this->sendTroopsBack($post);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private function loadUnits($post) {
|
|
global $form;
|
|
|
|
if(!empty($error = $this->checkErrors($post))) {
|
|
$form->addError("error", $error);
|
|
$_SESSION['errorarray'] = $form->getErrors();
|
|
$_SESSION['valuearray'] = $_POST;
|
|
header("Location: a2b.php");
|
|
exit;
|
|
}
|
|
else return $post;
|
|
}
|
|
|
|
/**
|
|
* Gets an error if the user did a mistake
|
|
*
|
|
* @param array $post The array containing all of the needed informations
|
|
* @return string Returns the errors, or empty if no errors was found
|
|
*/
|
|
|
|
public function checkErrors(&$post){
|
|
global $database, $generator;
|
|
|
|
if(($error = $this->parseCoordinates($post)) !== "") return $error;
|
|
|
|
$this->resolveTarget($post, $disabled, $disabledr, $isOasis);
|
|
|
|
if(!empty($disabledr) && $post['c'] == 2) return "You can't reinforce this village/oasis";
|
|
if(!empty($disabled) && $post['c'] == 3) return "You can't attack this village/oasis with normal attack";
|
|
if($post['c'] < 2 || $post['c'] > 4) return "Invalid attack type.";
|
|
|
|
//check if at least one troops has been selected
|
|
$selectedTroops = 0;
|
|
for($i = 1; $i <= 11; $i++) $selectedTroops += empty($post['t'.$i]) ? 0 : $post['t'.$i];
|
|
if($selectedTroops == 0) return "You need to select min. one troop";
|
|
|
|
if(!empty($post['dname']) && $post['x'] != "" && $post['y'] != "") return "Insert name or coordinates";
|
|
|
|
if(isset($post['dname']) && !empty($post['dname'])) {
|
|
$id = $database->getVillageByName(stripslashes($post['dname']));
|
|
|
|
if (!isset($id)) return "Village doesn't exist";
|
|
else $coor = $database->getCoor($id);
|
|
}
|
|
|
|
// People search by coordinates
|
|
// We confirm and seek coordinate coordinates Village
|
|
if(isset($post['x']) && isset($post['y']) && $post['x'] != "" && $post['y'] != "") {
|
|
$coor = ['x' => $post['x'], 'y' => $post['y']];
|
|
$id = $generator->getBaseID($coor['x'], $coor['y']);
|
|
|
|
if (!$database->getVillageState($id)) return "Coordinates do not exist";
|
|
}
|
|
|
|
if (!empty($coor)) {
|
|
if(($error = $this->validateTroopSelection($post)) !== "") return $error;
|
|
}
|
|
|
|
if(isset($id)) {
|
|
if(($error = $this->validateTargetPlayer($id, $isOasis, $villageInfo)) !== "") return $error;
|
|
}
|
|
|
|
//no errors, we can add the additional information to the post array
|
|
array_push($post, $id, $villageInfo['name'], $villageInfo['owner'], 0);
|
|
|
|
return "";
|
|
}
|
|
|
|
/**
|
|
* Trims, validates and normalises the x/y coordinates in $post.
|
|
*
|
|
* @param array $post The request array (modified in place)
|
|
* @return string An error message, or "" if the coordinates are valid
|
|
*/
|
|
private function parseCoordinates(&$post) {
|
|
if(isset($post['x'])) $post['x'] = trim($post['x']);
|
|
if(isset($post['y'])) $post['y'] = trim($post['y']);
|
|
|
|
if(isset($post['x']) && isset($post['y']) && $post['x'] !== "" && $post['y'] !== ""){
|
|
if(!preg_match('/^-?\d+$/', $post['x']) || !preg_match('/^-?\d+$/', $post['y'])) return "Invalid coordinates";
|
|
|
|
$post['x'] = (int) $post['x'];
|
|
$post['y'] = (int) $post['y'];
|
|
|
|
if(abs($post['x']) > WORLD_MAX || abs($post['y']) > WORLD_MAX) return "Coordinates do not exist";
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
/**
|
|
* Resolves the target village from coordinates or name and derives the
|
|
* reinforce/attack "disabled" flags and whether the target is an oasis.
|
|
*
|
|
* @param array $post The request array (dname may be unset)
|
|
* @param string $disabled Out: "disabled=disabled" when normal attack is forbidden
|
|
* @param string $disabledr Out: "disabled=disabled" when reinforcing is forbidden
|
|
* @param mixed $isOasis Out: truthy when the target is an oasis
|
|
*/
|
|
private function resolveTarget(&$post, &$disabled, &$disabledr, &$isOasis) {
|
|
global $database, $session;
|
|
|
|
// Search by town name
|
|
// Coordinates and look confirm name people
|
|
if(isset($post['x']) && isset($post['y']) && $post['x'] != "" && $post['y'] != "") {
|
|
$vid = $database->getVilWref($post['x'], $post['y']);
|
|
unset($post['dname']);
|
|
}
|
|
else if(isset($post['dname']) && !empty($post['dname'])) $vid = $database->getVillageByName(stripslashes($post['dname']));
|
|
|
|
if (!empty($vid)) {
|
|
if($isOasis = $database->isVillageOases($vid)){
|
|
$too = $database->getOasisField($vid, "conqured");
|
|
if($too == 0) $disabled = $disabledr ="disabled=disabled";
|
|
else
|
|
{
|
|
$disabledr = "";
|
|
if($session->sit == 0) $disabled = "";
|
|
else $disabled ="disabled=disabled";
|
|
}
|
|
}else{
|
|
$too = $database->getVillage($vid);
|
|
if($too['owner'] == 3){
|
|
$disabledr = "disabled=disabled";
|
|
$disabled = "";
|
|
}else{
|
|
$disabledr = "";
|
|
if($session->sit == 0) $disabled = "";
|
|
else $disabled ="disabled=disabled";
|
|
}
|
|
}
|
|
}else{
|
|
$disabledr = "";
|
|
if($session->sit == 0) $disabled = "";
|
|
else $disabled ="disabled=disabled";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validates the selected troop amounts against what the village owns.
|
|
*
|
|
* @param array $post The request array
|
|
* @return string An error message, or "" if the selection is valid
|
|
*/
|
|
private function validateTroopSelection($post) {
|
|
global $village, $session;
|
|
|
|
$Gtribe = $session->tribe == 1 ? "" : $session->tribe - 1;
|
|
for($i = 1; $i < 12; $i++){
|
|
if(isset($post['t'.$i])){
|
|
if($i < 10) $troophave = $village->unitarray['u'.$Gtribe.$i];
|
|
if($i == 10) $troophave = $village->unitarray['u'.floor(intval($Gtribe) + 1) * $i];
|
|
if($i == 11) $troophave = $village->unitarray['hero'];
|
|
|
|
if(intval($post['t'.$i]) > $troophave) return "You can't send more units than you have";
|
|
if(intval($post['t'.$i]) < 0) return "You can't send negative units.";
|
|
if(preg_match('/[^0-9]/',$post['t'.$i])) return "Special characters can't entered";
|
|
}
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
/**
|
|
* Validates the target player (beginners protection, ban/admin, vacation,
|
|
* self-attack) and loads the target village/oasis info.
|
|
*
|
|
* @param int $id The target base id
|
|
* @param mixed $isOasis Whether the target is an oasis
|
|
* @param array $villageInfo Out: the resolved village/oasis row
|
|
* @return string An error message, or "" if the target can be attacked
|
|
*/
|
|
private function validateTargetPlayer($id, $isOasis, &$villageInfo) {
|
|
global $database, $village;
|
|
|
|
//check if the attacked village/oasis' owner is under beginners protection
|
|
if($database->hasBeginnerProtection($id) == 1) return "Player is under beginners protection. You can't attack him";
|
|
|
|
//check if it's an oasis or not
|
|
$villageInfo = (!$isOasis) ? $database->getVillage($id) : $database->getOasisV($id);
|
|
|
|
//check if banned/admin:
|
|
$villageOwner = $villageInfo['owner'];
|
|
$userAccess = $database->getUserField($villageOwner, 'access', 0);
|
|
$userID = $database->getUserField($villageOwner, 'id', 0);
|
|
//check if he's an Admin and if he's attackable
|
|
if($userAccess == 0 || ($userAccess == MULTIHUNTER && $userID == 5) || (!ADMIN_ALLOW_INCOMING_RAIDS && $userAccess == ADMIN)){
|
|
return "Player is Banned. You can't attack him";
|
|
}
|
|
|
|
//check if the user' is on the vacation mode:
|
|
if($database->getvacmodexy($id)) return "User is on vacation mode";
|
|
|
|
//check if attacking same village that units are in
|
|
if($id == $village->wid) return "You cant attack same village you are sending from.";
|
|
|
|
return "";
|
|
}
|
|
|
|
public function returnTroops($wref, $mode = 0) {
|
|
global $database;
|
|
|
|
if(!$mode){
|
|
$getenforce = $database->getEnforceVillage($wref, 0);
|
|
foreach($getenforce as $enforce) $this->processReturnTroops($enforce);
|
|
}
|
|
|
|
// check oasis
|
|
$getenforce1 = $database->getOasisEnforce($wref, 1);
|
|
foreach($getenforce1 as $enforce) $this->processReturnTroops($enforce);
|
|
|
|
// set oasis to default
|
|
if(count($getenforce1) > 0) $database->regenerateOasisUnits($getenforce1[0]['vref']);
|
|
}
|
|
|
|
private function processReturnTroops($enforce) {
|
|
global $database;
|
|
|
|
$to = $database->getVillage($enforce['from']);
|
|
$tribe = $database->getUserField($to['owner'], 'tribe', 0);
|
|
$start = ($tribe - 1) * 10 + 1;
|
|
|
|
$troopsTime = $this->getWalkingTroopsTime($enforce['from'], $enforce['vref'], $to['owner'], $tribe, $enforce, 1);
|
|
$time = $database->getArtifactsValueInfluence($from['owner'], $enforce['from'], 2, $troopsTime);
|
|
|
|
$reference = $database->addAttack($enforce['from'], $enforce['u'.$start], $enforce['u'.($start + 1)], $enforce['u'.($start + 2)], $enforce['u'.($start + 3)], $enforce['u'.($start + 4)], $enforce['u'.($start + 5)], $enforce['u'.($start + 6)], $enforce['u'.($start + 7)], $enforce['u'.($start + 8)], $enforce['u'.($start + 9)], $enforce['hero'], 2, 0, 0, 0, 0);
|
|
$database->addMovement(4, $enforce['vref'], $enforce['from'], $reference, time(), ($time + time()));
|
|
$database->deleteReinf($enforce['id']);
|
|
}
|
|
|
|
private function sendTroops($post) {
|
|
global $form, $database, $village, $session;
|
|
|
|
$data = $database->getA2b($post['timestamp_checksum']);
|
|
$Gtribe = ($session->tribe == 1) ? "" : $session->tribe - 1;
|
|
|
|
for ($i = 1; $i < 10; $i++) {
|
|
if (isset($data['u'.$i])) {
|
|
if ($data['u'.$i] > $village->unitarray['u'.$Gtribe.$i]) {
|
|
$form->addError("error", "You can't send more units than you have");
|
|
break;
|
|
}
|
|
|
|
if ($data['u'.$i] < 0) {
|
|
$form->addError("error", "You can't send negative units.");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if($data['u11'] > $village->unitarray['hero']) $form->addError("error", "You can't send more units than you have");
|
|
if($data['u11'] < 0) $form->addError("error", "You can't send negative units.");
|
|
if($data['type'] != 1) $post['spy'] = 0; else $post['spy'] = $post['spy']?? 0;
|
|
|
|
if($form->returnErrors() > 0){
|
|
$_SESSION['errorarray'] = $form->getErrors();
|
|
$_SESSION['valuearray'] = $_POST;
|
|
header( "Location: a2b.php" );
|
|
exit;
|
|
}else{
|
|
if (empty($data['id']) || !$database->claimA2b((int)$data['id'], $post['timestamp_checksum'])) {
|
|
$form->addError("error", "This troop send request was already processed. Please try again.");
|
|
$_SESSION['errorarray'] = $form->getErrors();
|
|
$_SESSION['valuearray'] = $_POST;
|
|
header("Location: a2b.php");
|
|
exit;
|
|
}
|
|
|
|
$u = ($session->tribe == 1) ? "" : $session->tribe - 1;
|
|
|
|
$database->modifyUnit(
|
|
$village->wid,
|
|
[
|
|
$u . "1",
|
|
$u . "2",
|
|
$u . "3",
|
|
$u . "4",
|
|
$u . "5",
|
|
$u . "6",
|
|
$u . "7",
|
|
$u . "8",
|
|
$u . "9",
|
|
$session->tribe . "0",
|
|
"hero"
|
|
],
|
|
[
|
|
$data['u1'],
|
|
$data['u2'],
|
|
$data['u3'],
|
|
$data['u4'],
|
|
$data['u5'],
|
|
$data['u6'],
|
|
$data['u7'],
|
|
$data['u8'],
|
|
$data['u9'],
|
|
$data['u10'],
|
|
$data['u11']
|
|
],
|
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
);
|
|
|
|
$troopsTime = $this->getWalkingTroopsTime($village->wid, $data['to_vid'], $session->uid, $session->tribe, $data, 1, 'u');
|
|
$time = $database->getArtifactsValueInfluence($session->uid, $village->wid, 2, $troopsTime);
|
|
|
|
$this->resolveCatapultTargets($post, $data);
|
|
|
|
if(!isset($post['spy'])) $post['spy'] = 0;
|
|
|
|
$abdata = $database->getABTech($village->wid);
|
|
$reference = $database->addAttack(($village->wid), $data['u1'], $data['u2'], $data['u3'], $data['u4'], $data['u5'], $data['u6'], $data['u7'], $data['u8'], $data['u9'], $data['u10'], $data['u11'], $data['type'], $post['ctar1'], $post['ctar2'], $post['spy'], $abdata['b1'], $abdata['b2'], $abdata['b3'], $abdata['b4'], $abdata['b5'], $abdata['b6'], $abdata['b7'], $abdata['b8']);
|
|
$checkexist = $database->checkVilExist($data['to_vid']);
|
|
$checkoexist = $database->checkOasisExist($data['to_vid']);
|
|
if($checkexist || $checkoexist) {
|
|
$database->addMovement(3, $village->wid, $data['to_vid'], $reference, time(), ($time + time()));
|
|
if ($database->hasBeginnerProtection($village->wid) == 1 && $checkexist) {
|
|
mysqli_query($database->dblink, "UPDATE " . TB_PREFIX . "users SET protect = 0 WHERE id = ".(int) $session->uid);
|
|
}
|
|
}
|
|
|
|
if($form->returnErrors() > 0) {
|
|
$_SESSION['errorarray'] = $form->getErrors();
|
|
$_SESSION['valuearray'] = $_POST;
|
|
header("Location: a2b.php" );
|
|
exit;
|
|
}
|
|
|
|
header("Location: build.php?id=39");
|
|
exit;
|
|
}
|
|
}
|
|
|
|
private function resolveCatapultTargets(&$post, $data) {
|
|
global $database, $village, $session;
|
|
|
|
// Check if have WW owner have artefact Rivals great confusion or Artefact of the unique fool with that effect
|
|
// If is a WW village you can target on WW , if is not a WW village catapults will target randomly.
|
|
// Like it says : Exceptions are the WW which can always be targeted and the treasure chamber which can always be targeted, except with the unique artifact.
|
|
// Fixed by Advocaite and Shadow - Optimized by iopietro
|
|
|
|
$to_owner = $database->getVillageField($data['to_vid'], "owner");
|
|
$rivalsGreatConfusion = $database->getArtifactsSumByKind($to_owner, $data['to_vid'], 7);
|
|
|
|
$rallyPointLevel = ($village->resarray)['f39'];
|
|
$invalidBuildings = [];
|
|
|
|
// fill the array with the invalid buildings
|
|
if($rallyPointLevel >= 3 && $rallyPointLevel < 5){
|
|
for($i = 1; $i <= 50; $i++){
|
|
if(!in_array($i, [10, 11])) $invalidBuildings[] = $i;
|
|
}
|
|
}
|
|
else if($rallyPointLevel >= 5 && $rallyPointLevel < 10){
|
|
for($i = 12; $i <= 50; $i++) $invalidBuildings[] = $i;
|
|
}
|
|
else if($rallyPointLevel >= 10){
|
|
// zidurile nu pot fi tinta directa (31,32,33 + cele noi 42,43,47,50)
|
|
$invalidBuildings = [23, 31, 32, 33, 34, 36, 42, 43, 47, 50];
|
|
}
|
|
|
|
if(isset($post['ctar1']) && $post['ctar1'] != 0){
|
|
// check if the player has selected a valid building
|
|
if($rallyPointLevel < 3 || $data['u8'] == 0 || in_array($post['ctar1'], $invalidBuildings) || $post['ctar1'] < 0 || $post['ctar1'] > 50){
|
|
$post['ctar1'] = 0;
|
|
}
|
|
}
|
|
|
|
if(isset($post['ctar2']) && $post['ctar2'] != 0){
|
|
// check if there are atleast 20 catapults
|
|
if($data['u8'] < 20 || $rallyPointLevel != 20){
|
|
$post['ctar2'] = 0;
|
|
}else{
|
|
// check if the player has selected a valid building
|
|
if(in_array($post['ctar2'], $invalidBuildings) || ($post['ctar2'] < 0 || $post['ctar2'] > 50 && $post['ctar2'] != 99)){
|
|
$post['ctar2'] = 99;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Bug fix: Brewery (35) is Teuton-only, capital-only, but empire-wide —
|
|
// the catapult-randomization side effect must be checked on the SENDER'S
|
|
// CAPITAL (not $village->wid, the village the rally point belongs to,
|
|
// which may not be the capital), and only while a Mead-Festival is
|
|
// actually active there — not simply because the Brewery is built.
|
|
$hasActiveBrewery = false;
|
|
if ($session->tribe == 2) {
|
|
$senderCapital = $database->getVillage($session->uid, 3);
|
|
$hasActiveBrewery = $senderCapital
|
|
&& (int)$senderCapital['festival'] > time()
|
|
&& $database->getFieldLevelInVillage($senderCapital['wref'], 35) > 0;
|
|
}
|
|
|
|
if(isset($post['ctar1'])) {
|
|
//Is the Mead-Festival active?
|
|
if(!$hasActiveBrewery){
|
|
if($rivalsGreatConfusion['totals'] > 0) {
|
|
if($post['ctar1'] != 40 && ($post['ctar1'] != 27 || ($post['ctar1'] == 27 && $rivalsGreatConfusion['unique'] > 0))) {
|
|
$post['ctar1'] = 0;
|
|
}
|
|
}
|
|
}
|
|
else $post['ctar1'] = 0;
|
|
}
|
|
else $post['ctar1'] = 0;
|
|
|
|
if(isset($post['ctar2']) && $post['ctar2'] > 0) {
|
|
//Is the Mead-Festival active?
|
|
if(!$hasActiveBrewery){
|
|
if($rivalsGreatConfusion['totals'] > 0) {
|
|
if ($post['ctar2'] != 40 && ($post['ctar2'] != 27 || ($post['ctar2'] == 27 && $rivalsGreatConfusion['unique'] > 0))) {
|
|
$post['ctar2'] = 99;
|
|
}
|
|
}
|
|
}
|
|
else $post['ctar2'] = 99;
|
|
}
|
|
else $post['ctar2'] = 0;
|
|
}
|
|
|
|
private function sendTroopsBack($post) {
|
|
global $form, $database, $village, $session, $technology;
|
|
|
|
if (!$database->getEnforceLock($post['ckey'])) return;
|
|
try {
|
|
// Re-fetch after lock to prevent TOCTOU race condition
|
|
$enforce = $database->getEnforceArray( $post['ckey'], 0 );
|
|
$enforceoasis = $database->getOasisEnforceArray( $post['ckey'], 0 );
|
|
if ( ( $enforce['from'] == $village->wid ) || ( $enforce['vref'] == $village->wid ) || ( $enforceoasis['conqured'] == $village->wid ) ) {
|
|
$to = $database->getVillage( $enforce['from'] );
|
|
$Gtribe = ($ownerTribe = $database->getUserField( $to['owner'], 'tribe', 0)) == 1 ? "" : $ownerTribe - 1;
|
|
|
|
for ( $i = 1; $i < 10; $i ++ ) {
|
|
if ( isset( $post[ 't' . $i ] ) ) {
|
|
if ( $i != 10 ) {
|
|
if ( $post[ 't' . $i ] > $enforce[ 'u' . $Gtribe . $i ] ) {
|
|
$form->addError( "error", "You can't send back more units than you have" );
|
|
break;
|
|
}
|
|
|
|
if ( $post[ 't' . $i ] < 0 ) {
|
|
$form->addError( "error", "You can't send back negative units." );
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
$post[ 't' . $i . '' ] = '0';
|
|
}
|
|
}
|
|
if ( isset( $post['t11'] ) ) {
|
|
if ( $post['t11'] > $enforce['hero'] ) {
|
|
$form->addError( "error", "You can't send back more units than you have" );
|
|
}
|
|
|
|
if ( $post['t11'] < 0 ) {
|
|
$form->addError( "error", "You can't send back negative units." );
|
|
}
|
|
} else {
|
|
$post['t11'] = '0';
|
|
}
|
|
|
|
if ( $form->returnErrors() > 0 ) {
|
|
$_SESSION['errorarray'] = $form->getErrors();
|
|
$_SESSION['valuearray'] = $_POST;
|
|
$database->releaseEnforceLock($post['ckey']);
|
|
header( "Location: a2b.php" );
|
|
exit;
|
|
} else {
|
|
|
|
//change units
|
|
$tribe = $database->getUserField($to['owner'], 'tribe', 0);
|
|
$start = ($tribe - 1 ) * 10 + 1;
|
|
$end = $tribe * 10 ;
|
|
|
|
$units = [];
|
|
$amounts = [];
|
|
$modes = [];
|
|
|
|
$j = 1;
|
|
for ( $i = $start; $i <= $end; $i ++ ) {
|
|
$units[] = $i;
|
|
$amounts[] = $post[ 't' . $j . '' ];
|
|
$modes[] = 0;
|
|
$j ++;
|
|
}
|
|
|
|
$units[] = 'hero';
|
|
$amounts[] = $post['t11'];
|
|
$modes[] = 0;
|
|
|
|
$database->modifyEnforce($post['ckey'], $units, $amounts, $modes);
|
|
$j++;
|
|
|
|
$troopsTime = $this->getWalkingTroopsTime($enforce['from'], $enforce['vref'], $to['owner'], $tribe, $post, 1, 't');
|
|
$time = $database->getArtifactsValueInfluence($session->uid, $village->wid, 2, $troopsTime);
|
|
|
|
$reference = $database->addAttack($enforce['from'], $post['t1'], $post['t2'], $post['t3'], $post['t4'], $post['t5'], $post['t6'], $post['t7'], $post['t8'], $post['t9'], $post['t10'], $post['t11'], 2, 0, 0, 0, 0);
|
|
$database->addMovement(4, $village->wid, $enforce['from'], $reference, time(), ($time + time()));
|
|
$technology->checkReinf($post['ckey'], false);
|
|
|
|
$database->releaseEnforceLock($post['ckey']);
|
|
header("Location: build.php?id=39&refresh=1");
|
|
exit();
|
|
}
|
|
}else{
|
|
$form->addError("error", "You cant change someones troops.");
|
|
if($form->returnErrors() > 0){
|
|
$_SESSION['errorarray'] = $form->getErrors();
|
|
$_SESSION['valuearray'] = $_POST;
|
|
$database->releaseEnforceLock($post['ckey']);
|
|
header("Location: a2b.php");
|
|
exit();
|
|
}
|
|
}
|
|
} finally {
|
|
$database->releaseEnforceLock($post['ckey']);
|
|
}
|
|
}
|
|
|
|
public function Settlers($post) {
|
|
global $form, $database, $village, $session;
|
|
|
|
$mode = CP;
|
|
$total = count($database->getProfileVillages($session->uid));
|
|
$need_cps = ${'cp'.$mode}[$total + 1];
|
|
$cps = $session->cp;
|
|
$rallypoint = $database->getResourceLevel($village->wid);
|
|
|
|
//-- Prevent user from founding a new village if there are not enough settlers or the player put an invalid village ID or an already occupied one
|
|
//-- fix by AL-Kateb - Semplified and additions by iopietro
|
|
if ($rallypoint['f39'] > 0 && $village->unitarray['u'.$session->tribe.'0'] >= 3 && isset($post['s']) && ($newvillage = $database->getMInfo($post['s']))['id'] > 0 && $newvillage['occupied'] == 0 && $newvillage['oasistype'] == 0) {
|
|
if ($cps >= $need_cps) {
|
|
$troopsTime = $this->getWalkingTroopsTime($village->wid, $newvillage['id'], 0, 0, [300], 0);
|
|
$time = $database->getArtifactsValueInfluence($session->uid, $village->wid, 2, $troopsTime);
|
|
|
|
$unit = ($session->tribe * 10);
|
|
$database->modifyResource($village->wid, 750, 750, 750, 750, 0);
|
|
$database->modifyUnit($village->wid, [$unit], [3], [0]);
|
|
$database->addMovement(5, $village->wid, $post['s'], 0, time(), time() + $time);
|
|
}
|
|
header("Location: build.php?id=39");
|
|
exit;
|
|
} else {
|
|
header("Location: dorf1.php");
|
|
exit;
|
|
}
|
|
}
|
|
|
|
public function Hero($uid, $all = 0, $include_dead = false) {
|
|
global $database;
|
|
$heroarray = $database->getHero($uid, $all, $include_dead);
|
|
$herodata = false;
|
|
$singleHeroArrayID = 0;
|
|
|
|
// no hero data found
|
|
if (!count($heroarray)) {
|
|
return false;
|
|
}
|
|
|
|
// check all heroes and load hero data for the one,
|
|
// whose data were updated more recently - if we're not getting all of them
|
|
if (!$all) {
|
|
foreach ($heroarray as $id => $hero) {
|
|
// try to load a hero who's alive first
|
|
if (!$herodata && $hero['dead'] != 1) {
|
|
// this global value comes from GameEngine/Data/unitdata.php
|
|
$herodata = $GLOBALS["h".$hero['unit']];
|
|
$singleHeroArrayID = $id;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// if we couldn't get a living hero,
|
|
// resort to loading the first one from the list,
|
|
// as that would be the one most recently updated/used
|
|
if (!$herodata) {
|
|
// this global value comes from GameEngine/Data/unitdata.php
|
|
$herodata = $GLOBALS["h".$heroarray[0]['unit']];
|
|
}
|
|
|
|
return $this->buildHeroStats($heroarray[$singleHeroArrayID], $herodata);
|
|
} else {
|
|
// build up a full array of heroes and their stats
|
|
$heroes = [];
|
|
foreach ($heroarray as $id => $hero) {
|
|
$herodata = $GLOBALS["h".$heroarray[$id]['unit']];
|
|
$heroes[] = $this->buildHeroStats($heroarray[$id], $herodata);
|
|
}
|
|
|
|
return $heroes;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Builds the stat array for a single hero entry, deriving atk/di/dc/ob/db
|
|
* from the unit's base data ($herodata) and the hero's own attack/defence.
|
|
*
|
|
* @param array $hero One entry from the getHero() result
|
|
* @param array $herodata The unit base data ($GLOBALS["h".$hero['unit']])
|
|
* @return array The hero stats array
|
|
*/
|
|
private function buildHeroStats($hero, $herodata) {
|
|
$h_atk = $herodata['atk'] + 5 * floor($hero['attack'] * $herodata['atkp'] / 5);
|
|
$h_di = $herodata['di'] + 5 * floor($hero['defence'] * $herodata['dip'] / 5);
|
|
$h_dc = $herodata['dc'] + 5 * floor($hero['defence'] * $herodata['dcp'] / 5);
|
|
$h_ob = 1 + 0.002 * $hero['attackbonus'];
|
|
$h_db = 1 + 0.002 * $hero['defencebonus'];
|
|
|
|
return [
|
|
'heroid' => $hero['heroid'],
|
|
'unit' => $hero['unit'],
|
|
'name' => $hero['name'],
|
|
'inrevive' => $hero['inrevive'],
|
|
'intraining' => $hero['intraining'],
|
|
'trainingtime' => $hero['trainingtime'],
|
|
'level' => $hero['level'],
|
|
'attack' => $hero['attack'],
|
|
'atk' => $h_atk,
|
|
'defence' => $hero['defence'],
|
|
'di' => $h_di,
|
|
'dc' => $h_dc,
|
|
'attackbonus' => $hero['attackbonus'],
|
|
'ob' => $h_ob,
|
|
'defencebonus' => $hero['defencebonus'],
|
|
'db' => $h_db,
|
|
'regeneration' => $hero['regeneration'],
|
|
'health' => $hero['health'],
|
|
'dead' => $hero['dead'],
|
|
'points' => $hero['points'],
|
|
'experience' => $hero['experience']
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Function to kill/release prisoners
|
|
*
|
|
* @param int the ID of the prisoners you want to release
|
|
*/
|
|
|
|
/**
|
|
* T4 hero port: destroy a NATURE enforcement row (captured oasis animals,
|
|
* `from` = 0) stationed in the CURRENT village. Mirrors deletePrisoners'
|
|
* ownership model: the row must belong to the village the player is
|
|
* viewing, which the session already validated as theirs. Nature rows
|
|
* never travel back (no owner village to walk to) - releasing kills them.
|
|
*/
|
|
public function releaseNatureEnforcement($id){
|
|
global $village, $database;
|
|
|
|
$id = (int) $id;
|
|
if ($id <= 0) {
|
|
return false;
|
|
}
|
|
|
|
$stmt = $database->dblink->prepare(
|
|
"DELETE FROM " . TB_PREFIX . "enforcement
|
|
WHERE id = ? AND `from` = 0 AND vref = ? LIMIT 1"
|
|
);
|
|
$wid = (int) $village->wid;
|
|
$stmt->bind_param('ii', $id, $wid);
|
|
$stmt->execute();
|
|
$ok = $stmt->affected_rows > 0;
|
|
$stmt->close();
|
|
return $ok;
|
|
}
|
|
|
|
public function deletePrisoners($id){
|
|
global $village, $database, $session, $building, $bid19, $u99;
|
|
|
|
$prisoner = $database->getPrisonersByID($id);
|
|
$troops = 0;
|
|
if($prisoner['wref'] == $village->wid){
|
|
$p_owner = $database->getVillageField($prisoner['from'], "owner");
|
|
$p_tribe = $database->getUserField($p_owner, "tribe", 0);
|
|
|
|
$troopsTime = $this->getWalkingTroopsTime($prisoner['from'], $prisoner['wref'], $p_owner, $p_tribe, $prisoner, 1, 't');
|
|
$p_time = $database->getArtifactsValueInfluence($p_owner, $prisoner['from'], 2, $troopsTime);
|
|
|
|
$p_reference = $database->addAttack($prisoner['from'], $prisoner['t1'],$prisoner['t2'], $prisoner['t3'], $prisoner['t4'], $prisoner['t5'], $prisoner['t6'], $prisoner['t7'], $prisoner['t8'], $prisoner['t9'], $prisoner['t10'], $prisoner['t11'], 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
$database->addMovement(4, $prisoner['wref'], $prisoner['from'], $p_reference, time(), ($p_time + time()));
|
|
|
|
for($i = 1; $i <= 11; $i++) $troops += $prisoner['t'.$i];
|
|
|
|
//Reset traps
|
|
$database->modifyUnit($village->wid, ["99", "99o"], [$troops, $troops], [0, 0]);
|
|
$repairDuration = $database->getArtifactsValueInfluence($session->uid, $village->wid, 5, round(($bid19[max($building->getTypeLevel(36, $village->wid), 1)]['attri'] / 100) * $u99['time'] / SPEED));
|
|
$database->trainUnit($village->wid, 99, $troops, $u99['pop'], $repairDuration, 0);
|
|
|
|
$database->deletePrisoners($prisoner['id']);
|
|
}else if($prisoner['from'] == $village->wid){
|
|
$prisonersToOwner = $database->getVillageField($prisoner['wref'], "owner");
|
|
|
|
for($i = 1; $i <= 11; $i++) $troops += $prisoner['t'.$i];
|
|
|
|
if($prisoner['t11'] > 0){
|
|
$p_owner = $database->getVillageField($prisoner['from'], "owner");
|
|
mysqli_query($database->dblink, "UPDATE ".TB_PREFIX."hero SET `dead` = '1', `health` = '0' WHERE `uid` = '".$p_owner."' AND dead = 0");
|
|
}
|
|
|
|
//Reset traps
|
|
$database->modifyUnit($prisoner['wref'], ["99", "99o"], [$troops, $troops], [0, 0]);
|
|
|
|
if(($troops = round($troops / 3)) > 0){
|
|
$repairDuration = $database->getArtifactsValueInfluence($prisonersToOwner, $prisoner['wref'], 5, round(($bid19[max($building->getTypeLevel(36, $prisoner['wref']), 1)]['attri'] / 100) * $u99['time'] / SPEED));
|
|
$database->trainUnit($prisoner['wref'], 99, $troops, $u99['pop'], $repairDuration, 0);
|
|
}
|
|
|
|
$database->deletePrisoners($prisoner['id']);
|
|
}
|
|
|
|
header("Location: build.php?id=39");
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Get how much time troops spend to walk from a village to another
|
|
*
|
|
* @param int $from The start village ID
|
|
* @param int $to The target village ID
|
|
* @param int $owner The owner of the troops
|
|
* @param int $tribe The tribe of the owner's troops
|
|
* @param array $unitArray The array containing troops count if mode is 0, otherwise it'll contains the troop speed
|
|
* @param int $mode How the time should be calculated
|
|
* @return int Returns the time troops take to walk from a village to another
|
|
*/
|
|
|
|
public function getWalkingTroopsTime($from, $to, $owner, $tribe, $unitArray, $mode, $unit = ""){
|
|
global $generator, $database;
|
|
|
|
$fromCoor = $database->getCoor($from);
|
|
$toCoor = $database->getCoor($to);
|
|
$fromCor = ['x' => $fromCoor['x'], 'y' => $fromCoor['y']];
|
|
$toCor = ['x' => $toCoor['x'], 'y' => $toCoor['y']];
|
|
|
|
if(!$mode) return $generator->procDistanceTime($fromCor, $toCor, $unitArray[0], $mode, $from);
|
|
|
|
$start = ($tribe - 1) * 10 + 1;
|
|
$end = $tribe * 10;
|
|
|
|
$speeds = [];
|
|
|
|
//Find slowest unit
|
|
if(!empty($unit)){
|
|
for($i = 1; $i <= 11; $i++){
|
|
if(isset($unitArray[$unit.$i]) && $unitArray[$unit.$i] > 0) $unitArray[$i - 1] = $unitArray[$unit.$i];
|
|
else $unitArray[$i - 1] = 0;
|
|
}
|
|
}else{
|
|
for($i = $start; $i <= $end; $i++){
|
|
if(isset($unitArray['u'.$i]) && $unitArray['u'.$i] > 0) $unitArray[$i - $start] = $unitArray['u'.$i];
|
|
else $unitArray[$i - $start] = 0;
|
|
}
|
|
|
|
if(isset($unitArray['hero']) && $unitArray['hero'] > 0){
|
|
$unitArray[10] = $unitArray['hero'];
|
|
}
|
|
else $unitArray[10] = 0;
|
|
}
|
|
|
|
for($i = 0; $i <= 9; $i++){
|
|
if(isset($unitArray[$i]) && $unitArray[$i] > 0){
|
|
$speeds[] = $GLOBALS['u'.($i + $start)]['speed'];
|
|
}
|
|
}
|
|
|
|
if(isset($unitArray[10]) && $unitArray[10] > 0){
|
|
$heroUnit = $database->getHeroField($owner, 'unit');
|
|
$speeds[] = $GLOBALS['u'.$heroUnit]['speed'];
|
|
}
|
|
|
|
// Defensive: the tribe-offset loop above only inspects the owner's
|
|
// own 10 unit columns, so an army made purely of foreign/nature units
|
|
// (e.g. captured oasis animals) yields no speeds and min() would
|
|
// fatal (the "Send back" crash). Unreachable through normal flows
|
|
// now that nature rows disable Send back, but never crash movement
|
|
// creation - fall back to the slowest common speed.
|
|
if (empty($speeds)) {
|
|
$speeds[] = 3;
|
|
}
|
|
|
|
$walkTime = $generator->procDistanceTime($fromCor, $toCor, min($speeds), $mode, $from);
|
|
|
|
// T4 hero port (Phase 5): boots (>20 tiles), pennant (own villages)
|
|
// and standard (ally villages) shorten the trip when the hero rides
|
|
// along. Returns the input unchanged when NEW_FUNCTIONS_HERO_T4 is off.
|
|
return HeroBattleBonus::adjustTravelTime($owner, $unitArray[10] ?? 0, $from, $to, $walkTime);
|
|
}
|
|
|
|
public function startRaidList($post){
|
|
global $database, $generator, $session;
|
|
|
|
$slots = $post['slot'] ?? [];
|
|
if(empty($slots)){
|
|
header("Location: build.php?id=39&t=99");
|
|
exit();
|
|
}
|
|
|
|
$tribe = $session->tribe;
|
|
|
|
foreach($slots as $slot){
|
|
$raidList = $database->getRaidList($slot);
|
|
$getFLData = $database->getFLData($raidList['lid']);
|
|
|
|
//Check if we're trying to start our raidlists or other players raidlist
|
|
if($getFLData['owner'] != $session->uid) continue;
|
|
|
|
//Get the units in the village
|
|
$villageUnits = $database->getUnit($getFLData['wref'], false);
|
|
|
|
$sid = $raidList['id'];
|
|
$wref = $raidList['towref'];
|
|
|
|
for($i = 1; $i <= 6; $i++) ${'t'.$i} = $raidList['t'.$i];
|
|
|
|
if(!$database->isVillageOases($wref)) $villageOwner = $database->getVillageField($wref, 'owner');
|
|
else $villageOwner = $database->getOasisField($wref, 'owner');
|
|
|
|
$userAccess = $database->getUserField($villageOwner, 'access', 0);
|
|
$userID = $database->getUserField($villageOwner, 'id', 0);
|
|
|
|
if($userAccess != 0 && !($userAccess == MULTIHUNTER && $userID == 5) && ($userAccess != ADMIN || (ADMIN_ALLOW_INCOMING_RAIDS && $userAccess == ADMIN))){
|
|
|
|
//Start = the first troop of the player's tribe
|
|
//End = the last selectable troop of the player's tribe
|
|
$start = ($session->tribe - 1) * 10 + 1;
|
|
$end = $start + 5;
|
|
|
|
//Check if we've enough troops
|
|
$canSend = true;
|
|
for($i = $start; $i <= $end; $i++){
|
|
if($villageUnits['u'.$i] < ${'t'.($i - $start + 1)}){
|
|
$canSend = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Send the attack
|
|
if($canSend){
|
|
$ckey = $generator->generateRandStr(6);
|
|
$id = $database->addA2b($ckey, 0, $wref, $t1, $t2, $t3, $t4, $t5, $t6, 0, 0, 0, 0, 0, 4);
|
|
$data = $database->getA2b($ckey);
|
|
|
|
$troopsTime = $this->getWalkingTroopsTime($getFLData['wref'], $data['to_vid'], $session->uid, $session->tribe, $data, 1, 'u');
|
|
$time = $database->getArtifactsValueInfluence($getFLData['owner'], $getFLData['wref'], 2, $troopsTime);
|
|
|
|
$abdata = $database->getABTech($getFLData['wref']);
|
|
$reference = $database->addAttack(($getFLData['wref']), $data['u1'], $data['u2'], $data['u3'], $data['u4'], $data['u5'], $data['u6'], 0, 0, 0, 0, 0, $data['type'], 0, 0, 0, $abdata['b1'], $abdata['b2'], $abdata['b3'], $abdata['b4'], $abdata['b5'], $abdata['b6'], $abdata['b7'], $abdata['b8']);
|
|
|
|
$troops = [];
|
|
$amounts = [];
|
|
$modes = [];
|
|
|
|
for($u = $start; $u <= $end; $u++){
|
|
$troops[] = $u;
|
|
$amounts[] = $data['u'.($u - $start + 1)];
|
|
$modes[] = 0;
|
|
}
|
|
|
|
$database->modifyUnit($getFLData['wref'], $troops, $amounts, $modes);
|
|
$database->addMovement(3, $getFLData['wref'], $data['to_vid'], $reference, time(), ($time + time()));
|
|
|
|
//Prevent re-use of the same attack via re-POSTing the same data
|
|
$database->remA2b($id);
|
|
}
|
|
}
|
|
}
|
|
header("Location: build.php?id=39&t=99");
|
|
exit();
|
|
}
|
|
};
|
|
$units = new Units;
|
|
|
|
?>
|