上一篇文章,我主要是從全局的一個角度,架構了戰鬥系統,這裏我將詳細分析具體的實現細節。
這場戰鬥中,我們需要關注的點:戰鬥前期準備,單次戰鬥結算, 技能釋放,戰鬥結算。
戰鬥前期
戰鬥技能
// 如果攻船正處於“封印”狀態,則不能發動技能
if (Model_Battle_InSkill::isSealed($attackerShip)) {
$skillId = 0;
}
// 否則可以觸發攻船的戰鬥內技能
else {
// 返回0表示觸發失敗,觸發成功則返回技能Id
$skillId = Model_Battle_InSkill::triggerSkill($attacker, $attackerShip);
}
如果技能觸發成功了後,我就會實例化這個技能:
// 創建本次技能實例
$skill = Model_Battle_InSkill::factory($skillId);
創建了技能之後,我們就要明白技能到底是如何工作的。該buff是良性or惡性
影響比例(小於100%表示減少,大於表示增加)
// 設置己方艦隊
public function setSelfShips(array $ships)
{
$this->_selfShips = $ships;
}
// 設置對方艦隊
public function setEnemyShips(array $ships)
{
$this->_enemyShips = $ships;
}
設置作用對象 技能的作用對象都是存在表中。
// 設置受技能對象(們)
public function setTargetShips()
{
$targetConfig = explode(':', $this->_prop['target_config']);
// 攻擊哪方
$targetSide = isset($targetConfig[0]) ? $targetConfig[0] : null;
// 攻擊規則
$targetRule = isset($targetConfig[1]) ? $targetConfig[1] : null;
// 攻擊範圍
$targetNum = isset($targetConfig[2]) ? $targetConfig[2] : null;
// 受技能方的艦隊信息
$ships = $targetSide == 'SELF' ? $this->_selfShips : $this->_enemyShips;
switch ($targetRule) {
// 全體
case 'ALL':
$this->_targetShips = $ships;
break;
// 隨機定位
case 'RAND':
// 隨機定位1艘存活的船
if ($targetNum == 1) {
$this->_targetShips = array(Model_Battle_Util::findRandAliveShip($ships, 1));
}
// 隨機定位N艘存活的船
else {
$this->_targetShips = Model_Battle_Util::findRandAliveShip($ships, $targetNum);
}
break;
// 隨機定位敵方一艘存活的帶有戰鬥內技能的船
case 'RAND_SKILLED':
$targetShip = Model_Battle_Util::findRandAliveShipWithSkillIn($shipss, 1);
// 如果敵方沒有一艘船是有技能的
if (! $targetShip) {
// 那麼隨機定位敵方一艘存活的船
$targetShip = Model_Battle_Util::findRandAliveShip($ships, 1);
}
$this->_targetShips = array($targetShip);
break;
// 缺省爲艦隊中存活的第一艘船
default:
$this->_targetShips = array(Model_Battle_Util::findFirstAliveShip($ships));
break;
}
}
// 設置船隻buffs
public function setBuffs()
{
if (! $buffType = $this->_prop['buff_type']) {
return null;
}
switch ($buffType) {
// 影響攻擊力
case 'offense':
// 中毒
case 'poisoned':
foreach ($this->getTargetShips() as $ship) {
$ship->buffs[$buffType] = array(
'rounds' => $this->_prop['buff_rounds'], // 該buff持續回合數
'status' => $this->_prop['buff_status'], // 該buff是良性or惡性
'rate' => $this->_prop['buff_effect_rate'], // 影響比例(小於100%表示減少,大於表示增加)
);
}
break;
// 冰凍
case 'frozen':
// 封印
case 'sealed':
foreach ($this->getTargetShips() as $ship) {
$ship->buffs[$buffType] = array(
'rounds' => $this->_prop['buff_rounds'],
'status' => $this->_prop['buff_status'],
);
}
break;
// 清除良性buff
case 'clear_good':
foreach ($this->getTargetShips() as $ship) {
foreach ($ship->buffs as $key => $buff) {
if ($buff['status'] == 'good') {
unset($ship->buffs[$key]);
}
}
}
break;
// 清除惡性buff
case 'clear_bad':
foreach ($this->getTargetShips() as $ship) {
foreach ($ship->buffs as $key => $buff) {
if ($buff['status'] == 'bad') {
unset($ship->buffs[$key]);
}
}
}
break;
}
}
這裏,給某艘船隻施加技能效果的主要做法是,給船隻數組添加新技能的屬性,或者刪除舊技能屬性。
單次戰鬥結算
public function execute()
{
if (! $this->_attackerShip || ! $this->_defenderShip) {
return null;
}
// 應用buff並返回處理結果(攻/防/暴/閃/命/抗暴的增減益)
$oddsData = Model_Battle_InSkill::applyShipBuff($this->_attackerShip, $this->_defenderShip);
// 應用單次行動前的屬性影響
if ($this->_skill) {
$oddsData = Model_Battle_InSkill::applySingleActEffect($oddsData, $this->_skill);
}
// 導出數組變量
extract($oddsData);
// 應用炮甲相剋對守船防禦力造成的折扣
if ($this->_attackerShip['cannon_id'] && $this->_defenderShip['armor_id']) {
$defenderDefense *= self::getCannonVsArmorEffectRatio($this->_attackerShip['cannon'], $this->_defenderShip['armor']);
}
// 計算本次傷害點數
$damage = $this->_calcDamagePoint($attackerOffense, $defenderDefense, $attackerHitOdds, $defenderAvoidOdds, $attackerCritOdds, $defenderAntiCritOdds);
// 執行扣血
if ($damage > 0) {
self::deductShipHp($this->_defenderShip, $damage);
}
// 記錄本次的傷害數值
$this->_logger->setDamage($damage);
}
注意,類的職能的劃分很重要,主要extract()函數的使用,妙。下面是具體的應用buff的實現。
/**
* 應用buff生效
*/
public static function applyShipBuff(Model_Ship $attackerShip, Model_Ship $defenderShip)
{
$attackerOffense = $attackerShip['offense']; // 攻船攻擊力
$attackerHitOdds = $attackerShip['hit_odds']; // 攻船命中率
$attackerCritOdds = $attackerShip['crit_odds']; // 攻船暴擊率
$defenderDefense = $defenderShip['defense']; // 守船防禦力
$defenderAvoidOdds = $defenderShip['avoid_odds']; // 守船閃避力
$defenderAntiCritOdds = $defenderShip['anti_crit_odds']; // 守船抗暴擊率
// 應用攻船的buff
if (isset($attackerShip->buffs) && $attackerShip->buffs) {
foreach ($attackerShip->buffs as $buffType => $buff) {
// 如果是攻擊力增強、減弱狀態
if ($buffType == 'offense') {
$attackerOffense = floor($attackerOffense * $buff['rate']);
}
// 如果是命中率增強、減弱狀態
elseif ($buffType == 'hit') {
$attackerHitOdds = floor($attackerHitOdds * $buff['rate']);
}
// 如果是暴擊率增強、減弱狀態
elseif ($buffType == 'crit') {
$attackerCritOdds = floor($attackerCritOdds * $buff['rate']);
}
}
}
// 應用守船的buff
if (isset($defenderShip->buffs) && $defenderShip->buffs) {
foreach ($defenderShip->buffs as $buffType => $buff) {
// 如果是防禦力增強、減弱狀態
if ($buffType == 'defense') {
$defenderDefense = floor($defenderDefense * $buff['rate']);
}
// 如果是閃避率增強、減弱狀態
elseif ($buffType == 'avoid') {
$defenderAvoidOdds = floor($defenderAvoidOdds * $buff['rate']);
}
// 如果是抗暴擊率增強、減弱狀態
elseif ($buffType == 'anti_crit') {
$defenderAntiCritOdds = floor($defenderAntiCritOdds * $buff['rate']);
}
}
}
return array(
'attackerOffense' => $attackerOffense,
'attackerHitOdds' => $attackerHitOdds,
'attackerCritOdds' => $attackerCritOdds,
'defenderDefense' => $defenderDefense,
'defenderAvoidOdds' => $defenderAvoidOdds,
'defenderAntiCritOdds' => $defenderAntiCritOdds,
);
}