1 ? 2 - pow($x, -1.5) : pow($x, 1.5)) / 2; } /***************************************** Function to proc Simulation *****************************************/ public function procSim($post) { global $form; /****************************************************************** * 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']; /****************************************************************** * TARGET BUILD ******************************************************************/ $target = []; for ($i = 1; $i <= 5; $i++) { if (!empty($post['a2_v'.$i])) { $target[] = $i; } } $_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; } $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]?? 0; $oldWallLevel = $_POST['result'][8]?? 0; /****************************************************************** * 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; } } } /****************************************************************** * DEFENDER INIT ******************************************************************/ $defender = []; $def_ab = []; $defscout = 0; for ($i = 1; $i <= 50; $i++) { $units = (int)($post['a2_'.$i] ?? 0); $ab = (int)($post['f2_'.$i] ?? 0); $defender['u'.$i] = $units; $def_ab[$i] = $units > 0 ? $ab : 0; if ($units > 0 && in_array($i, [4,14,23,44])) { $defscout += $units; } } /****************************************************************** * BASIC VALUES ******************************************************************/ $deftribe = (int)$post['tribe']; $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(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']; } $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']; } } 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); } $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; } } } /****************************************************************** * ATTACKER UNIT CALCULATION ******************************************************************/ $start = ($att_tribe - 1) * 10 + 1; $end = $att_tribe * 10; if ($type == 1) { $abcount = ($att_tribe == 3) ? 3 : 4; $scoutAB = ${'att_ab'.$abcount}; for ($i = $start; $i <= $end; $i++) { $unitAmount = (int)$Attacker['u'.$i]; if ($unitAmount <= 0) { continue; } global ${'u'.$i}; if ($i == 4 || $i == 14 || $i == 23 || $i == 44) { 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; } } $involve += $unitAmount; $units['Att_unit'][$i] = $unitAmount; } $ap *= $attacker_artefact; } else { $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 ]; $abcount = 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++; } /****************************************************************** * HERO OFFENSE ******************************************************************/ if (!empty($Attacker['uhero']) && !empty($atkhero)) { $units['Att_unit']['hero'] = $Attacker['uhero']; $ap *= $atkhero['ob']; $cap *= $atkhero['ob']; $ap += $atkhero['atk']; } if ($offhero > 0 || $hero_strenght > 0) { $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) { $result['casualties_attacker'][11] = 1; 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" ); } } } /****************************************************************** * HERO DAMAGE (DEFENDER) ******************************************************************/ if (!empty($units['Def_unit']['hero']) && !empty($defenderhero['heroid'])) { $hero_id = (int)$defenderhero['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[2]); 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 = " . $hero_id . " LIMIT 1" ); } else { $result['deadherodef'] = 0; mysqli_query( $database->dblink, "UPDATE " . TB_PREFIX . "hero SET health = health - " . (int)$damage_health . " WHERE heroid = " . $hero_id . " LIMIT 1" ); } } } /****************************************************************** * HERO DAMAGE (DEFENDER + REINFORCEMENTS) ******************************************************************/ if (!empty($DefendersAll)) { $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" ); } } } /****************************************************************** * BOUNTY CALCULATION ******************************************************************/ $max_bounty = 0; 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; } 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; } 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; } 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; ?>