admin 發表於 2016-8-16 00:23:02

u6 battle engine code research

尚未解讀完成
<?php
//計算戰鬥函數
//參數:攻擊方艦隊資料(陣列),防禦方船艦和防禦資料(陣列),艦隊變渣機率(數字:30),防禦變渣機率(數字:0)
function calculateAttack(&$attackers, &$defenders, $FleetTF, $DefTF)
{
        //全域變數:船艦和防禦造價,船艦和防禦戰鬥參數,資料表欄位
        global $pricelist, $CombatCaps, $resource;

        $TRES         = array('attacker' => 0, 'defender' => 0);
        //攻擊方廢墟
        $ARES         = array('metal' => 0, 'crystal' => 0);
        //防禦方廢墟
        $DRES   = array('metal' => 0, 'crystal' => 0);
        //儲存每回合戰鬥結果的陣列
        $ROUND        = array();
        //船艦和防禦的快速射擊
        $RF                = array();
        //攻擊方資料循環
        foreach ($attackers as $fleetID => $attacker)
        {
                //攻擊方艦隊資料循環,key:船艦編號,vaule:船艦數量
                foreach ($attacker['unit'] as $element => $amount)
                {
                        $ARES['metal']                 += $pricelist[$element]['cost'] * $amount;
                        $ARES['crystal']         += $pricelist[$element]['cost'] * $amount;
                }
        }

        //循環戰鬥資料陣列
        /* $e=擁有速射船艦或防禦的編號
        $t=被快速射擊的船艦防禦編號
        $sd=速射值 */
        foreach($CombatCaps as $e => $arr) {
                //若船艦或防禦沒有速射則跳過
                if(!isset($arr['sd'])) continue;
                //找出快速射擊資料並放到變數裡
                foreach($arr['sd'] as $t => $sd) {
                        //若船艦或防禦沒有速射則跳過
                        if($sd == 0) continue;
                        $RF[$t][$e] = $sd;
                }
        }
       
        $TRES['attacker']        = $ARES['metal'] * 0.25 + $ARES['crystal'] * 0.5;

        foreach ($defenders as $fleetID => $defender)
        {
                foreach ($defender['unit'] as $element => $amount)
                {
                        if ($element < 300) {
                                $DRES['metal']                 += $pricelist[$element]['cost'] * $amount;
                                $DRES['crystal']         += $pricelist[$element]['cost'] * $amount ;

                                $TRES['defender']         += $pricelist[$element]['cost'] * 0.25 * $amount;
                                $TRES['defender']         += $pricelist[$element]['cost'] * 0.5 * $amount;
                        } else {
                                if (!isset($STARTDEF[$element]))
                                        $STARTDEF[$element] = 0;
                               
                                $STARTDEF[$element] += $amount;

                                $TRES['defender']        += $pricelist[$element]['cost'] * 0.25 * $amount;
                                $TRES['defender']        += $pricelist[$element]['cost'] * 0.5 * $amount;
                        }
                }
        }
        //開始戰鬥回合循環(預設為6回合)
        for ($ROUNDC = 0; $ROUNDC <= MAX_ATTACK_ROUNDS; $ROUNDC++)
        {
                //攻擊方傷害值
                $attackDamage= array('total' => 0);
                //攻擊方護盾值
                $attackShield= array('total' => 0);
                //攻擊方船艦數量
                $attackAmount= array('total' => 0);
                //防禦方傷害值
                $defenseDamage = array('total' => 0);
                //防禦方護盾值
                $defenseShield = array('total' => 0);
                //防禦方船艦或防禦數量
                $defenseAmount = array('total' => 0);
                //
                $attArray = array();
                $defArray = array();

                foreach ($attackers as $fleetID => $attacker) {
                        $attackDamage[$fleetID] = 0;
                        $attackShield[$fleetID] = 0;
                        $attackAmount[$fleetID] = 0;

                        $attTech        = (1 + (0.1 * $attacker['player']['military_tech']) + $attacker['player']['factor']['Attack']); //attaque
                        $defTech        = (1 + (0.1 * $attacker['player']['defence_tech']) + $attacker['player']['factor']['Defensive']); //bouclier
                        $shieldTech = (1 + (0.1 * $attacker['player']['shield_tech']) + $attacker['player']['factor']['Shield']); //coque
                        $attackers[$fleetID]['techs'] = array($attTech, $defTech, $shieldTech);
                               
                        foreach ($attacker['unit'] as $element => $amount) {
                                $thisAtt        = $amount * ($CombatCaps[$element]['attack']) * $attTech * (rand(80, 120) / 100); //attaque
                                $thisDef        = $amount * ($CombatCaps[$element]['shield']) * $defTech ; //bouclier
                                $thisShield        = $amount * ($pricelist[$element]['cost'] + $pricelist[$element]['cost']) / 10 * $shieldTech; //coque

                                $attArray[$fleetID][$element] = array('def' => $thisDef, 'shield' => $thisShield, 'att' => $thisAtt);

                                $attackDamage[$fleetID] += $thisAtt;
                                $attackDamage['total'] += $thisAtt;
                                $attackShield[$fleetID] += $thisDef;
                                $attackShield['total'] += $thisDef;
                                $attackAmount[$fleetID] += $amount;
                                $attackAmount['total'] += $amount;
                        }
                }

                foreach ($defenders as $fleetID => $defender) {
                        $defenseDamage[$fleetID] = 0;
                        $defenseShield[$fleetID] = 0;
                        $defenseAmount[$fleetID] = 0;

                        $attTech        = (1 + (0.1 * $defender['player']['military_tech']) + $defender['player']['factor']['Attack']); //attaquue
                        $defTech        = (1 + (0.1 * $defender['player']['defence_tech']) + $defender['player']['factor']['Defensive']); //bouclier
                        $shieldTech = (1 + (0.1 * $defender['player']['shield_tech']) + $defender['player']['factor']['Shield']); //coque
                        $defenders[$fleetID]['techs'] = array($attTech, $defTech, $shieldTech);

                        foreach ($defender['unit'] as $element => $amount) {
                                $thisAtt        = $amount * ($CombatCaps[$element]['attack']) * $attTech * (rand(80, 120) / 100); //attaque
                                $thisDef        = $amount * ($CombatCaps[$element]['shield']) * $defTech ; //bouclier
                                $thisShield        = $amount * ($pricelist[$element]['cost'] + $pricelist[$element]['cost']) / 10 * $shieldTech; //coque

                                if ($element == 407 || $element == 408 || $element == 409) $thisAtt = 0;

                                $defArray[$fleetID][$element] = array('def' => $thisDef, 'shield' => $thisShield, 'att' => $thisAtt);

                                $defenseDamage[$fleetID] += $thisAtt;
                                $defenseDamage['total'] += $thisAtt;
                                $defenseShield[$fleetID] += $thisDef;
                                $defenseShield['total'] += $thisDef;
                                $defenseAmount[$fleetID] += $amount;
                                $defenseAmount['total'] += $amount;
                        }
                }

                $ROUND[$ROUNDC] = array('attackers' => $attackers, 'defenders' => $defenders, 'attackA' => $attackAmount, 'defenseA' => $defenseAmount, 'infoA' => $attArray, 'infoD' => $defArray);

                if ($ROUNDC >= MAX_ATTACK_ROUNDS || $defenseAmount['total'] <= 0 || $attackAmount['total'] <= 0) {
                        break;
                }

                // Calculate hit percentages (ACS only but ok)
                $attackPct = array();
                foreach ($attackAmount as $fleetID => $amount) {
                        if (!is_numeric($fleetID)) continue;
                                $attackPct[$fleetID] = $amount / $attackAmount['total'];
                }

                $defensePct = array();
                foreach ($defenseAmount as $fleetID => $amount) {
                        if (!is_numeric($fleetID)) continue;
                                $defensePct[$fleetID] = $amount / $defenseAmount['total'];
                }

                // CALCUL DES PERTES !!!
                $attacker_n = array();
                $attacker_shield = 0;
                $defenderAttack        = 0;
                foreach ($attackers as $fleetID => $attacker) {
                        $attacker_n[$fleetID] = array();

                        foreach($attacker['unit'] as $element => $amount) {
                                if ($amount <= 0) {
                                        $attacker_n[$fleetID][$element] = 0;
                                        continue;
                                }

                                $defender_moc = $amount * ($defenseDamage['total'] * $attackPct[$fleetID]) / $attackAmount[$fleetID];
                       
                                if(isset($RF[$element])) {
                                        foreach($RF[$element] as $shooter => $shots) {
                                                foreach($defArray as $fID => $rfdef) {
                                                        if(empty($rfdef[$shooter]['att']) || $attackAmount[$fleetID] <= 0) continue;

                                                        $defender_moc += $rfdef[$shooter]['att'] * $shots / ($amount / $attackAmount[$fleetID] * $attackPct[$fleetID]);
                                                        $defenseAmount['total'] += $defenders[$fID]['unit'][$shooter] * $shots;
                                                }
                                        }
                                }
                               
                                $defenderAttack        += $defender_moc;
                               
                                if (($attArray[$fleetID][$element]['def'] / $amount) >= $defender_moc) {
                                        $attacker_n[$fleetID][$element] = round($amount);
                                        $attacker_shield += $defender_moc;
                                        continue;
                                }

                                $max_removePoints = floor($amount * $defenseAmount['total'] / $attackAmount[$fleetID] * $attackPct[$fleetID]);

                                $attacker_shield += min($attArray[$fleetID][$element]['def'], $defender_moc);
                                $defender_moc        -= min($attArray[$fleetID][$element]['def'], $defender_moc);

                                $ile_removePoints = max(min($max_removePoints, $amount * min($defender_moc / $attArray[$fleetID][$element]['shield'] * (rand(0, 200) / 100), 1)), 0);

                                $attacker_n[$fleetID][$element] = max(ceil($amount - $ile_removePoints), 0);
                        }
                }

                $defender_n = array();
                $defender_shield = 0;
                $attackerAttack        = 0;
                foreach ($defenders as $fleetID => $defender) {
                        $defender_n[$fleetID] = array();

                        foreach($defender['unit'] as $element => $amount) {
                                if ($amount <= 0) {
                                        $defender_n[$fleetID][$element] = 0;
                                        continue;
                                }

                                $attacker_moc = $amount * ($attackDamage['total'] * $defensePct[$fleetID]) / $defenseAmount[$fleetID];
                                if (isset($RF[$element])) {
                                        foreach($RF[$element] as $shooter => $shots) {
                                                foreach($attArray as $fID => $rfatt) {
                                                        if (empty($rfatt[$shooter]['att']) || $defenseAmount[$fleetID] <= 0 ) continue;

                                                        $attacker_moc += $rfatt[$shooter]['att'] * $shots / ($amount / $defenseAmount[$fleetID] * $defensePct[$fleetID]);
                                                        $attackAmount['total'] += $attackers[$fID]['unit'][$shooter] * $shots;
                                                }
                                        }
                                }
                               
                                $attackerAttack        += $attacker_moc;
                               
                                if (($defArray[$fleetID][$element]['def'] / $amount) >= $attacker_moc) {
                                        $defender_n[$fleetID][$element] = round($amount);
                                        $defender_shield += $attacker_moc;
                                        continue;
                                }
       
                                $max_removePoints = floor($amount * $attackAmount['total'] / $defenseAmount[$fleetID] * $defensePct[$fleetID]);
                                $defender_shield += min($defArray[$fleetID][$element]['def'], $attacker_moc);
                                $attacker_moc        -= min($defArray[$fleetID][$element]['def'], $attacker_moc);
                               
                                $ile_removePoints = max(min($max_removePoints, $amount * min($attacker_moc / $defArray[$fleetID][$element]['shield'] * (rand(0, 200) / 100), 1)), 0);

                                $defender_n[$fleetID][$element] = max(ceil($amount - $ile_removePoints), 0);
                        }
                }
               
                $ROUND[$ROUNDC]['attack']                 = $attackerAttack;
                $ROUND[$ROUNDC]['defense']                 = $defenderAttack;
                $ROUND[$ROUNDC]['attackShield'] = $attacker_shield;
                $ROUND[$ROUNDC]['defShield']         = $defender_shield;
                foreach ($attackers as $fleetID => $attacker) {
                        $attackers[$fleetID]['unit'] = array_map('round', $attacker_n[$fleetID]);
                }

                foreach ($defenders as $fleetID => $defender) {
                        $defenders[$fleetID]['unit'] = array_map('round', $defender_n[$fleetID]);
                }
        }
       
        if ($attackAmount['total'] <= 0 && $defenseAmount['total'] > 0) {
                $won = "r"; // defender
        } elseif ($attackAmount['total'] > 0 && $defenseAmount['total'] <= 0) {
                $won = "a"; // attacker
        } else {
                $won = "w"; // draw
        }

        // CDR
        foreach ($attackers as $fleetID => $attacker) {                                           // flotte attaquant en CDR
                foreach ($attacker['unit'] as $element => $amount) {
                        $TRES['attacker'] -= $pricelist[$element]['cost'] * 0.25 * $amount ;
                        $TRES['attacker'] -= $pricelist[$element]['cost'] * 0.5 * $amount ;

                        $ARES['metal'] -= $pricelist[$element]['cost'] * $amount ;
                        $ARES['crystal'] -= $pricelist[$element]['cost'] * $amount ;
                }
        }

        $DRESDefs = array('metal' => 0, 'crystal' => 0);

        foreach ($defenders as $fleetID => $defender) {
                foreach ($defender['unit'] as $element => $amount) {
                        if ($element < 300) {                                                        // flotte defenseur en CDR
                                $DRES['metal']        -= $pricelist[$element]['cost'] * $amount ;
                                $DRES['crystal'] -= $pricelist[$element]['cost'] * $amount ;

                                $TRES['defender'] -= $pricelist[$element]['cost'] * 0.25 * $amount ;
                                $TRES['defender'] -= $pricelist[$element]['cost'] * 0.5 * $amount ;
                        } else {                                                                        // defs defenseur en CDR + reconstruction
                                $TRES['defender'] -= $pricelist[$element]['cost'] * 0.25 * $amount ;
                                $TRES['defender'] -= $pricelist[$element]['cost'] * 0.5 * $amount ;

                                $lost = $STARTDEF[$element] - $amount;
                                $giveback = round($lost * (rand(72, 84) / 100));
                                $defenders[$fleetID]['unit'][$element] += $giveback;
                                $DRESDefs['metal']        += $pricelist[$element]['cost'] * ($lost - $giveback) ;
                                $DRESDefs['crystal'] += $pricelist[$element]['cost'] * ($lost - $giveback) ;
                        }
                }
        }
       
        $ARES['metal']                = max($ARES['metal'], 0);
        $ARES['crystal']        = max($ARES['crystal'], 0);
        $DRES['metal']                = max($DRES['metal'], 0);
        $DRES['crystal']        = max($DRES['crystal'], 0);
        $TRES['attacker']        = max($TRES['attacker'], 0);
        $TRES['defender']        = max($TRES['defender'], 0);
       
        $totalLost = array('attacker' => $TRES['attacker'], 'defender' => $TRES['defender']);
        $debAttMet = ($ARES['metal'] * ($FleetTF / 100));
        $debAttCry = ($ARES['crystal'] * ($FleetTF / 100));
        $debDefMet = ($DRES['metal'] * ($FleetTF / 100)) + ($DRESDefs['metal'] * ($DefTF / 100));
        $debDefCry = ($DRES['crystal'] * ($FleetTF / 100)) + ($DRESDefs['crystal'] * ($DefTF / 100));

        return array('won' => $won, 'debris' => array('attacker' => array(901 => $debAttMet, 902 => $debAttCry), 'defender' => array(901 => $debDefMet, 902 => $debDefCry)), 'rw' => $ROUND, 'unitLost' => $totalLost);
}

Dexterclub 發表於 2016-8-16 10:10:59

戰鬥模擬器有將速射計算在內嗎?

admin 發表於 2016-8-16 11:08:55

Dexterclub 發表於 2016-8-16 10:10 AM
戰鬥模擬器有將速射計算在內嗎?

戰鬥模擬器的資料傳入戰鬥引擎後
就會開始進行戰鬥計算

也就是說
戰鬥模擬器跟實際戰鬥
都是用同一個檔案(戰鬥引擎)

戰鬥引擎裡面有包含速射
那麼模擬結果自然會包含速射
....
               
                require_once('includes/classes/missions/calculateAttack.php');
                require_once('includes/classes/missions/calculateSteal.php');
                require_once('includes/classes/missions/GenerateReport.php');
               
                $combatResult      = calculateAttack($attackers, $defenders, Config::get('Fleet_Cdr'), Config::get('Defs_Cdr'));
      

Dexterclub 發表於 2016-8-16 11:22:58

a950216t 發表於 2016-8-15 07:08 PM
戰鬥模擬器的資料傳入戰鬥引擎後
就會開始進行戰鬥計算



原來有包含速射啊
原先以為實際戰鬥結果 跟 戰鬥模擬器的模擬結果 差距過大 是因為沒計算速射
看來我錯了


那速射效果有一種情形是 兩軍交戰低階砲灰的數量太少的那一方低階砲灰爆炸後 速射的連環效應還沒結束 會拖累高階戰艦or防禦設施一起爆炸
不知道這種情形 戰鬥模擬器有沒有計算在內?

admin 發表於 2016-8-17 00:23:25

Dexterclub 發表於 2016-8-16 11:22 AM
原來有包含速射啊
原先以為實際戰鬥結果 跟 戰鬥模擬器的模擬結果 差距過大 是因為沒計算速射
看來我錯了 ...

魔鬼藏在細節之中

上面那段代碼
包含了所有答案
那段就是戰鬥的關鍵

不懂沒關係
之後會逐行解釋
並做個總結
再不懂就畫圖說明


遊戲的關鍵點
遲早會被破解

lindaren 發表於 2016-8-17 16:55:35

战斗这块真是核心中的核心,目前U6的模拟器和实际战斗结果不一样

admin 發表於 2016-8-17 18:52:34

lindaren 發表於 2016-8-17 04:55 PM
战斗这块真是核心中的核心,目前U6的模拟器和实际战斗结果不一样

探险机制都已经通了这个战斗计算其实不远了

系统如何运作的?

其实很简单

首先要有数据,数据是最重要的

攻击方船舰种类和数量,科技加成,事务官加成,商店加成
防御方船舰/防御种类和数量,科技加成,事务官加成,商店加成
然后就是一连串的计算后 产生结果
頁: [1]
檢視完整版本: u6 battle engine code research