전특 대 개편

This commit is contained in:
2020-07-15 02:33:21 +09:00
parent 6f9cb12dd8
commit 38a688f918
45 changed files with 1637 additions and 1422 deletions
+17 -1
View File
@@ -439,7 +439,7 @@ var nation = <?=Json::encode($nation)?>;
<?php endforeach; ?> <?php endforeach; ?>
</select> </select>
</div> </div>
<div class="input-group mb-1"> <div class="input-group mb-3">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text">귀병숙련</span> <span class="input-group-text">귀병숙련</span>
</div> </div>
@@ -460,11 +460,27 @@ var nation = <?=Json::encode($nation)?>;
<span class="input-group-text">수비여부</span> <span class="input-group-text">수비여부</span>
</div> </div>
<select class="custom-select form_defence_train only_defender"> <select class="custom-select form_defence_train only_defender">
<option value="90">훈사 90</option>
<option value="80">훈사 80</option> <option value="80">훈사 80</option>
<option value="60">훈사 60</option> <option value="60">훈사 60</option>
<option value="40">훈사 40</option>
<option value="999">안함</option> <option value="999">안함</option>
</select> </select>
</div> </div>
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">전투 수</span>
</div>
<input type="number" class="form-control form_warnum" value="0" step="1">
<div class="input-group-prepend">
<span class="input-group-text">승리 수</span>
</div>
<input type="number" class="form-control form_killnum" value="0" step="1">
<div class="input-group-prepend">
<span class="input-group-text">사살 수</span>
</div>
<input type="number" class="form-control form_killcrew" value="0" step="1">
</div>
</div> </div>
</div> </div>
+16 -2
View File
@@ -32,11 +32,16 @@ $reqColumns = [
'leadership', 'horse', 'strength', 'weapon', 'intel', 'book', 'item', 'leadership', 'horse', 'strength', 'weapon', 'intel', 'book', 'item',
'rice', 'personal', 'special2', 'rice', 'personal', 'special2',
'crew', 'crewtype', 'crew', 'crewtype',
'atmos', 'train', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'defence_train' 'atmos', 'train', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'defence_train',
];
$reqRankColumns = [
'warnum', 'killnum', 'killcrew'
]; ];
$dummyItems = [ $dummyItems = [
'officer_level'=>1, 'officer_level'=>1,
'horse'=>'None',
'weapon'=>'None', 'weapon'=>'None',
'book'=>'None', 'book'=>'None',
'item'=>'None', 'item'=>'None',
@@ -50,7 +55,10 @@ $dummyItems = [
'dex3'=>0, 'dex3'=>0,
'dex4'=>0, 'dex4'=>0,
'dex5'=>0, 'dex5'=>0,
'defence_train'=>80 'defence_train'=>80,
'warnum'=>0,
'killnum'=>0,
'killcrew'=>0,
]; ];
$rawDestGeneral = $db->queryFirstRow('SELECT %l FROM general WHERE no=%i', Util::formatListOfBackticks($reqColumns), $destGeneralID); $rawDestGeneral = $db->queryFirstRow('SELECT %l FROM general WHERE no=%i', Util::formatListOfBackticks($reqColumns), $destGeneralID);
@@ -60,6 +68,12 @@ if($nationID == 0 || $rawDestGeneral['nation'] != $nationID){
$rawDestGeneral[$key] = $val; $rawDestGeneral[$key] = $val;
} }
} }
else{
$rawRankValue = $db->queryAllLists('SELECT `type`, `value` FROM rank_data WHERE general_id = %i AND `type` IN %ls', $destGeneralID, $reqRankColumns);
foreach($rawRankValue as [$rankType, $rankValue]){
$rawDestGeneral[$rankType] = $rankValue;
}
}
foreach(['dex1', 'dex2', 'dex3', 'dex4', 'dex5'] as $dexKey){ foreach(['dex1', 'dex2', 'dex3', 'dex4', 'dex5'] as $dexKey){
$dex = $rawDestGeneral[$dexKey]; $dex = $rawDestGeneral[$dexKey];
+465 -451
View File
@@ -1,451 +1,465 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
WebUtil::requireAJAX(); WebUtil::requireAJAX();
$session = Session::requireLogin([])->setReadOnly(); $session = Session::requireLogin([])->setReadOnly();
$userID = Session::getUserID(); $userID = Session::getUserID();
increaseRefresh("시뮬레이터", 0); increaseRefresh("시뮬레이터", 0);
$query = Util::getPost('query'); $query = Util::getPost('query');
if($query === null){ if($query === null){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'입력값이 없습니다.' 'reason'=>'입력값이 없습니다.'
]); ]);
} }
$action = Util::getPost('action'); $action = Util::getPost('action');
if($action === null || !in_array($action, ['reorder', 'battle'])){ if($action === null || !in_array($action, ['reorder', 'battle'])){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'원하는 동작이 지정되지 않았습니다.' 'reason'=>'원하는 동작이 지정되지 않았습니다.'
]); ]);
} }
$query = Json::decode($query); $query = Json::decode($query);
if($query === null){ if($query === null){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'올바르지 않은 JSON입니다.' 'reason'=>'올바르지 않은 JSON입니다.'
]); ]);
} }
$defaultCheck = [ $defaultCheck = [
'required'=>[ 'required'=>[
'attackerGeneral', 'attackerCity', 'attackerNation', 'attackerGeneral', 'attackerCity', 'attackerNation',
'defenderGenerals', 'defenderCity', 'defenderNation', 'defenderGenerals', 'defenderCity', 'defenderNation',
'year', 'month', 'repeatCnt' 'year', 'month', 'repeatCnt'
], ],
'integer'=>[ 'integer'=>[
'year','month','repeatCnt' 'year','month','repeatCnt'
], ],
'between'=>[ 'between'=>[
['month', [1, 12]] ['month', [1, 12]]
], ],
'in'=>[ 'in'=>[
['repeatCnt', [1, 1000]] ['repeatCnt', [1, 1000]]
], ],
'min'=>[ 'min'=>[
['year', 0] ['year', 0]
], ],
'array'=>[ 'array'=>[
'attackerGeneral', 'attackerCity', 'attackerNation', 'attackerGeneral', 'attackerCity', 'attackerNation',
'defenderGenerals', 'defenderCity', 'defenderNation' 'defenderGenerals', 'defenderCity', 'defenderNation'
], ],
]; ];
$v = new Validator($query); $v = new Validator($query);
$v->rules($defaultCheck); $v->rules($defaultCheck);
if(!$v->validate()){ if(!$v->validate()){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>$v->errorStr() 'reason'=>$v->errorStr()
]); ]);
} }
$year = $query['year']; $year = $query['year'];
$month = $query['month']; $month = $query['month'];
$repeatCnt = $query['repeatCnt']; $repeatCnt = $query['repeatCnt'];
$rawAttacker = $query['attackerGeneral']; $rawAttacker = $query['attackerGeneral'];
$rawAttacker['turntime'] = TimeUtil::now(); $rawAttacker['turntime'] = TimeUtil::now();
$rawAttackerCity = $query['attackerCity']; $rawAttackerCity = $query['attackerCity'];
$rawAttackerNation = $query['attackerNation']; $rawAttackerNation = $query['attackerNation'];
$rawDefenderList = $query['defenderGenerals']; $rawDefenderList = $query['defenderGenerals'];
$rawDefenderCity = $query['defenderCity']; $rawDefenderCity = $query['defenderCity'];
$rawDefenderNation = $query['defenderNation']; $rawDefenderNation = $query['defenderNation'];
$generalCheck = [ $generalCheck = [
'required'=>[ 'required'=>[
'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train', 'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train',
'intel', 'intel_exp', 'book', 'strength', 'strength_exp', 'weapon', 'injury', 'leadership', 'leadership_exp', 'horse', 'item', 'intel', 'intel_exp', 'book', 'strength', 'strength_exp', 'weapon', 'injury', 'leadership', 'leadership_exp', 'horse', 'item',
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
'recent_war' 'recent_war', 'warnum', 'killnum', 'killcrew',
], ],
'integer'=>[ 'integer'=>[
'no', 'nation', 'crew', 'crewtype', 'atmos', 'train', 'no', 'nation', 'crew', 'crewtype', 'atmos', 'train',
'intel', 'intel_exp', 'strength', 'strength_exp', 'injury', 'leadership', 'leadership_exp', 'intel', 'intel_exp', 'strength', 'strength_exp', 'injury', 'leadership', 'leadership_exp',
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
], 'warnum', 'killnum', 'killcrew',
'min'=>[ ],
['no', 1], 'min'=>[
['nation', 1], ['no', 1],
['crew', 0], ['nation', 1],
['intel', 0], ['crew', 0],
['strength', 0], ['intel', 0],
['leadership', 0], ['strength', 0],
['experience', 0], ['leadership', 0],
['gold', 0], ['experience', 0],
['rice', 0], ['gold', 0],
['dex1', 0], ['rice', 0],
['dex2', 0], ['dex1', 0],
['dex3', 0], ['dex2', 0],
['dex4', 0], ['dex3', 0],
['dex5', 0], ['dex4', 0],
], ['dex5', 0],
'between'=>[ ['warnum', 0],
['train', [40, GameConst::$maxTrainByWar]], ['killnum', 0],
['atmos', [40, GameConst::$maxAtmosByWar]], ['killcrew', 0],
['explevel', [0, 300]], ],
['injury', [0, 80]], 'between'=>[
['officer_level', [1, 12]] ['train', [40, GameConst::$maxTrainByWar]],
], ['atmos', [40, GameConst::$maxAtmosByWar]],
'in'=>[ ['explevel', [0, 300]],
['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)], ['injury', [0, 80]],
['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)], ['officer_level', [1, 12]]
['crewtype', array_keys(GameUnitConst::all())], ],
['horse', array_merge(array_keys(GameConst::$allItems['horse']), ['None'])], 'in'=>[
['weapon', array_merge(array_keys(GameConst::$allItems['weapon']), ['None'])], ['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)],
['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])], ['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)],
['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])], ['crewtype', array_keys(GameUnitConst::all())],
] ['horse', array_merge(array_keys(GameConst::$allItems['horse']), ['None'])],
]; ['weapon', array_merge(array_keys(GameConst::$allItems['weapon']), ['None'])],
['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])],
$v = new Validator($rawAttacker); ['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])],
$v->rules($generalCheck); ]
if(!$v->validate()){ ];
Json::die([
'result'=>false, $v = new Validator($rawAttacker);
'reason'=>'[출병자]'.$v->errorStr() $v->rules($generalCheck);
]); if(!$v->validate()){
} Json::die([
'result'=>false,
$defenderList = []; 'reason'=>'[출병자]'.$v->errorStr()
foreach($rawDefenderList as $idx=>$rawDefenderGeneral){ ]);
$v = new Validator($rawDefenderGeneral); }
$v->rules($generalCheck);
if(!$v->validate()){ $defenderList = [];
$idx+=1; foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
Json::die([ $v = new Validator($rawDefenderGeneral);
'result'=>false, $v->rules($generalCheck);
'reason'=>"[수비자{$idx}]".$v->errorStr() if(!$v->validate()){
]); $idx+=1;
} Json::die([
$defenderList[] = new General($rawDefenderGeneral, null, $rawDefenderCity, $rawAttackerNation, $year, $month, true); 'result'=>false,
} 'reason'=>"[수비자{$idx}]".$v->errorStr()
]);
}
$cityCheck = [
'required'=>[ $defenderList[] = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), $rawDefenderCity, $rawAttackerNation, $year, $month, true);
'city', 'nation', 'supply', 'name', }
'pop', 'agri', 'comm', 'secu', 'def', 'wall',
'trust', 'level',
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max', $cityCheck = [
'dead', 'state', 'conflict', 'required'=>[
], 'city', 'nation', 'supply', 'name',
'numeric'=>[ 'pop', 'agri', 'comm', 'secu', 'def', 'wall',
'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead' 'trust', 'level',
], 'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
'integer'=>[ 'dead', 'state', 'conflict',
'city', 'nation', 'supply', ],
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max', 'numeric'=>[
'state', 'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead'
], ],
'min'=>[ 'integer'=>[
['def', 0], 'city', 'nation', 'supply',
['wall', 0], 'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
['trust', 0], 'state',
['pop', 0], ],
['comm', 0], 'min'=>[
['secu', 0], ['def', 0],
['city', 1], ['wall', 0],
['nation', 0] ['trust', 0],
], ['pop', 0],
'in'=>[ ['comm', 0],
['level', array_keys(getCityLevelList())] ['secu', 0],
] ['city', 1],
]; ['nation', 0]
],
$v = new Validator($rawAttackerCity); 'in'=>[
$v->rules($cityCheck); ['level', array_keys(getCityLevelList())]
if(!$v->validate()){ ]
Json::die([ ];
'result'=>false,
'reason'=>'[출병도시]'.$v->errorStr() $v = new Validator($rawAttackerCity);
]); $v->rules($cityCheck);
} if(!$v->validate()){
Json::die([
$v = new Validator($rawDefenderCity); 'result'=>false,
$v->rules($cityCheck); 'reason'=>'[출병도시]'.$v->errorStr()
if(!$v->validate()){ ]);
Json::die([ }
'result'=>false,
'reason'=>'[수비도시]'.$v->errorStr() $v = new Validator($rawDefenderCity);
]); $v->rules($cityCheck);
} if(!$v->validate()){
Json::die([
$nationCheck = [ 'result'=>false,
'required'=>[ 'reason'=>'[수비도시]'.$v->errorStr()
'type', 'tech', 'level', 'capital', ]);
'nation', 'name', 'gold', 'rice', 'gennum' }
],
'integer'=>[ $nationCheck = [
'level', 'capital', 'nation', 'gennum', 'required'=>[
], 'type', 'tech', 'level', 'capital',
'numeric'=>[ 'nation', 'name', 'gold', 'rice', 'gennum'
'tech', 'gold', 'rice' ],
], 'integer'=>[
'min'=>[ 'level', 'capital', 'nation', 'gennum',
['tech', 0], ],
['gold', 0], 'numeric'=>[
['rice', 0], 'tech', 'gold', 'rice'
['gennum', 1], ],
], 'min'=>[
'in'=>[ ['tech', 0],
['type', GameConst::$availableNationType], ['gold', 0],
['level', array_keys(getNationLevelList())] ['rice', 0],
] ['gennum', 1],
]; ],
'in'=>[
$v = new Validator($rawAttackerNation); ['type', GameConst::$availableNationType],
$v->rules($nationCheck); ['level', array_keys(getNationLevelList())]
if(!$v->validate()){ ]
Json::die([ ];
'result'=>false,
'reason'=>'[출병국]'.$v->errorStr() $v = new Validator($rawAttackerNation);
]); $v->rules($nationCheck);
} if(!$v->validate()){
Json::die([
$v = new Validator($rawDefenderNation); 'result'=>false,
$v->rules($nationCheck); 'reason'=>'[출병국]'.$v->errorStr()
if(!$v->validate()){ ]);
Json::die([ }
'result'=>false,
'reason'=>'[수비국]'.$v->errorStr() $v = new Validator($rawDefenderNation);
]); $v->rules($nationCheck);
} if(!$v->validate()){
Json::die([
if($action == 'reorder'){ 'result'=>false,
usort($defenderList, function(General $lhs, General $rhs){ 'reason'=>'[수비국]'.$v->errorStr()
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs)); ]);
}); }
$order = []; if($action == 'reorder'){
foreach($defenderList as $defenderGeneral){ usort($defenderList, function(General $lhs, General $rhs){
$order[] = $defenderGeneral->getID(); return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
} });
Json::die([ $order = [];
'result'=>true, foreach($defenderList as $defenderGeneral){
'reason'=>'success', $order[] = $defenderGeneral->getID();
'order'=>$order }
]);
} Json::die([
'result'=>true,
usort($defenderList, function(General $lhs, General $rhs){ 'reason'=>'success',
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs)); 'order'=>$order
}); ]);
}
$rawDefenderList = array_map(function(General $general){
return $general->getRaw(); usort($defenderList, function(General $lhs, General $rhs){
}, $defenderList); return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
unset($defenderList); });
$db = DB::db(); $rawDefenderList = array_map(function(General $general){
$gameStor = KVStorage::getStorage($db, 'game_env'); return $general->getRaw();
$startYear = $gameStor->startyear; }, $defenderList);
$cityRate = Util::round(($year - $startYear) / 1.5) + 60; unset($defenderList);
$db = DB::db();
function simulateBattle( $gameStor = KVStorage::getStorage($db, 'game_env');
$rawAttacker, $rawAttackerCity, $rawAttackerNation, $startYear = $gameStor->startyear;
$rawDefenderList, $rawDefenderCity, $rawDefenderNation, $cityRate = Util::round(($year - $startYear) / 1.5) + 60;
$startYear, $year, $month, $cityRate
){ function extractRankVar(array $rawVal):array{
$attacker = new WarUnitGeneral( $rankVars = [];
new General($rawAttacker, null, $rawAttackerCity, $rawAttackerNation, $year, $month), foreach($rawVal as $rawKey=>$rawVal){
$rawAttackerNation, if(key_exists($rawKey, General::RANK_COLUMN)){
true $rankVars[$rawKey] = $rawVal;
); }
$city = new WarUnitCity($rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate); }
return $rankVars;
$iterDefender = new \ArrayIterator($rawDefenderList); }
$iterDefender->rewind();
function simulateBattle(
$battleResult = []; $rawAttacker, $rawAttackerCity, $rawAttackerNation,
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$attackerRice = $rawAttacker['rice']; $startYear, $year, $month, $cityRate
$defenderRice = 0; ){
$attacker = new WarUnitGeneral(
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext) new General($rawAttacker, extractRankVar($rawAttacker), $rawAttackerCity, $rawAttackerNation, $year, $month),
use ($iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) { $rawAttackerNation,
if($prevDefender !== null){ true
$prevDefender->getLogger()->rollback(); );
$battleResult[] = $prevDefender; $city = new WarUnitCity($rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
if($prevDefender instanceof WarUnitGeneral){
$defenderRice -= $prevDefender->getVar('rice'); $iterDefender = new \ArrayIterator($rawDefenderList);
} $iterDefender->rewind();
}
$battleResult = [];
if(!$reqNext){
return null; $attackerRice = $rawAttacker['rice'];
} $defenderRice = 0;
if(!$iterDefender->valid()){ $getNextDefender = function(?WarUnit $prevDefender, bool $reqNext)
return null; use ($iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) {
} if($prevDefender !== null){
$prevDefender->getLogger()->rollback();
$defenderObj = new General($iterDefender->current(), null, $rawDefenderCity, $rawDefenderNation, $year, $month); $battleResult[] = $prevDefender;
if(extractBattleOrder($defenderObj) <= 0){ if($prevDefender instanceof WarUnitGeneral){
return null; $defenderRice -= $prevDefender->getVar('rice');
} }
}
$defenderRice += $defenderObj->getVar('rice');
if(!$reqNext){
$retVal = new WarUnitGeneral( return null;
$defenderObj, }
$rawDefenderNation,
false if(!$iterDefender->valid()){
); return null;
$iterDefender->next(); }
return $retVal;
}; $defenderObj = new General($iterDefender->current(), extractRankVar($iterDefender->current()), $rawDefenderCity, $rawDefenderNation, $year, $month);
if(extractBattleOrder($defenderObj) <= 0){
$conquerCity = processWar_NG($attacker, $getNextDefender, $city, $year - $startYear); return null;
}
$rawDefenderCity = $city->getRaw();
$updateAttackerNation = []; $defenderRice += $defenderObj->getVar('rice');
$updateDefenderNation = [];
$retVal = new WarUnitGeneral(
$attackerRice -= $attacker->getVar('rice'); $defenderObj,
$rawDefenderNation,
if($city->getPhase() > 0){ false
$rice = $city->getKilled() / 100 * 0.8; );
$rice *= $city->getCrewType()->rice; $iterDefender->next();
$rice *= getTechCost($rawDefenderNation['tech']); return $retVal;
$rice *= $cityRate / 100 - 0.2; };
Util::setRound($rice);
$conquerCity = processWar_NG($attacker, $getNextDefender, $city, $year - $startYear);
$defenderRice += $rice;
} $rawDefenderCity = $city->getRaw();
$updateAttackerNation = [];
$totalDead = $attacker->getKilled() + $attacker->getDead(); $updateDefenderNation = [];
$attackerCityDead = $totalDead * 0.4;
$defenderCityDead = $totalDead * 0.6; $attackerRice -= $attacker->getVar('rice');
return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice]; if($city->getPhase() > 0){
} $rice = $city->getKilled() / 100 * 0.8;
$rice *= $city->getCrewType()->rice;
$lastWarLog = []; $rice *= getTechCost($rawDefenderNation['tech']);
$rice *= $cityRate / 100 - 0.2;
$attackerKilled = 0; Util::setRound($rice);
$attackerDead = 0;
$defenderRice += $rice;
$attackerMaxKilled = 0; }
$attackerMinKilled = PHP_INT_MAX;
$totalDead = $attacker->getKilled() + $attacker->getDead();
$attackerMaxDead = 0; $attackerCityDead = $totalDead * 0.4;
$attackerMinDead = PHP_INT_MAX; $defenderCityDead = $totalDead * 0.6;
return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice];
$attackerAvgRice = 0; }
$defenderAvgRice = 0;
$lastWarLog = [];
$avgPhase = 0;
$avgWar = 0; $attackerKilled = 0;
$attackerDead = 0;
$attackerActivatedSkills = [];
$defendersActivatedSkills = []; $attackerMaxKilled = 0;
$attackerMinKilled = PHP_INT_MAX;
foreach(Util::range($repeatCnt) as $repeatIdx){
/** @var WarUnit $attacker */ $attackerMaxDead = 0;
[$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle( $attackerMinDead = PHP_INT_MAX;
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$startYear, $year, $month, $cityRate $attackerAvgRice = 0;
); $defenderAvgRice = 0;
$lastWarLog = Util::mapWithKey(function($key, $values){
return ConvertLog(join('<br>', $values)); $avgPhase = 0;
}, $attacker->getLogger()->rollback()); $avgWar = 0;
$avgPhase += $attacker->getPhase() / $repeatCnt; $attackerActivatedSkills = [];
$defendersActivatedSkills = [];
$killed = $attacker->getKilled();
$dead = $attacker->getDead(); foreach(Util::range($repeatCnt) as $repeatIdx){
/** @var WarUnit $attacker */
$attackerKilled += $killed / $repeatCnt; [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle(
$attackerDead += $dead / $repeatCnt; $rawAttacker, $rawAttackerCity, $rawAttackerNation,
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$attackerMaxKilled = max($attackerMaxKilled, $killed); $startYear, $year, $month, $cityRate
$attackerMinKilled = min($attackerMinKilled, $killed); );
$lastWarLog = Util::mapWithKey(function($key, $values){
$attackerMaxDead = max($attackerMaxDead, $dead); return ConvertLog(join('<br>', $values));
$attackerMinDead = min($attackerMinDead, $dead); }, $attacker->getLogger()->rollback());
$attackerAvgRice += $attackerRice / $repeatCnt; $avgPhase += $attacker->getPhase() / $repeatCnt;
$defenderAvgRice += $defenderRice / $repeatCnt;
$killed = $attacker->getKilled();
$avgWar += count($battleResult) / $repeatCnt; $dead = $attacker->getDead();
foreach($attacker->getActivatedSkillLog() as $skillName => $skillCnt){ $attackerKilled += $killed / $repeatCnt;
if(!key_exists($skillName, $attackerActivatedSkills)){ $attackerDead += $dead / $repeatCnt;
$attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt;
} $attackerMaxKilled = max($attackerMaxKilled, $killed);
else{ $attackerMinKilled = min($attackerMinKilled, $killed);
$attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt;
} $attackerMaxDead = max($attackerMaxDead, $dead);
} $attackerMinDead = min($attackerMinDead, $dead);
foreach($battleResult as $idx=>$defender){ $attackerAvgRice += $attackerRice / $repeatCnt;
while($idx >= count($defendersActivatedSkills)){ $defenderAvgRice += $defenderRice / $repeatCnt;
$defendersActivatedSkills[] = [];
} $avgWar += count($battleResult) / $repeatCnt;
$activatedSkills = &$defendersActivatedSkills[$idx]; foreach($attacker->getActivatedSkillLog() as $skillName => $skillCnt){
foreach($defender->getActivatedSkillLog() as $skillName => $skillCnt){ if(!key_exists($skillName, $attackerActivatedSkills)){
if(!key_exists($skillName, $activatedSkills)){ $attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt;
$activatedSkills[$skillName] = $skillCnt / $repeatCnt; }
} else{
else{ $attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt;
$activatedSkills[$skillName] += $skillCnt / $repeatCnt; }
} }
}
foreach($battleResult as $idx=>$defender){
} while($idx >= count($defendersActivatedSkills)){
} $defendersActivatedSkills[] = [];
}
Json::die([
'result'=>true, $activatedSkills = &$defendersActivatedSkills[$idx];
'datetime'=>$rawAttacker['turntime'], foreach($defender->getActivatedSkillLog() as $skillName => $skillCnt){
'reason'=>'success', if(!key_exists($skillName, $activatedSkills)){
'lastWarLog'=>$lastWarLog, $activatedSkills[$skillName] = $skillCnt / $repeatCnt;
'avgWar'=>$avgWar, }
'phase'=>$avgPhase, else{
'killed'=>$attackerKilled, $activatedSkills[$skillName] += $skillCnt / $repeatCnt;
'maxKilled'=>$attackerMaxKilled, }
'minKilled'=>$attackerMinKilled, }
'dead'=>$attackerDead,
'maxDead'=>$attackerMaxDead, }
'minDead'=>$attackerMinDead, }
'attackerRice'=>$attackerAvgRice,
'defenderRice'=>$defenderAvgRice, Json::die([
'attackerSkills'=>$attackerActivatedSkills, 'result'=>true,
'defendersSkills'=>$defendersActivatedSkills, 'datetime'=>$rawAttacker['turntime'],
]); 'reason'=>'success',
'lastWarLog'=>$lastWarLog,
'avgWar'=>$avgWar,
'phase'=>$avgPhase,
'killed'=>$attackerKilled,
'maxKilled'=>$attackerMaxKilled,
'minKilled'=>$attackerMinKilled,
'dead'=>$attackerDead,
'maxDead'=>$attackerMaxDead,
'minDead'=>$attackerMinDead,
'attackerRice'=>$attackerAvgRice,
'defenderRice'=>$defenderAvgRice,
'attackerSkills'=>$attackerActivatedSkills,
'defendersSkills'=>$defendersActivatedSkills,
]);
+10
View File
@@ -207,6 +207,10 @@ jQuery(function($) {
setVal('.form_dex5', data.dex5); setVal('.form_dex5', data.dex5);
setVal('.form_defence_train', data.defence_train); setVal('.form_defence_train', data.defence_train);
setVal('.form_warnum', data.warnum);
setVal('.form_killnum', data.killnum);
setVal('.form_killcrew', data.killcrew);
if (!setGeneralNo($general, data.no)) { if (!setGeneralNo($general, data.no)) {
setGeneralNo($general, generateNewGeneralNo()); setGeneralNo($general, generateNewGeneralNo());
} }
@@ -252,7 +256,13 @@ jQuery(function($) {
dex3: getInt('.form_dex3'), dex3: getInt('.form_dex3'),
dex4: getInt('.form_dex4'), dex4: getInt('.form_dex4'),
dex5: getInt('.form_dex5'), dex5: getInt('.form_dex5'),
defence_train: getInt('.form_defence_train'), defence_train: getInt('.form_defence_train'),
warnum: getInt('.form_warnum'),
killnum: getInt('.form_killnum'),
killcrew: getInt('.form_killcrew'),
}; };
} }
+34 -34
View File
@@ -1,35 +1,35 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\GeneralTrigger; use \sammo\GeneralTrigger;
use \sammo\GeneralTriggerCaller; use \sammo\GeneralTriggerCaller;
use sammo\WarUnitTrigger\che_전투치료발동; use sammo\WarUnitTrigger\che_전투치료발동;
use sammo\WarUnitTrigger\che_전투치료시도; use sammo\WarUnitTrigger\che_전투치료시도;
use sammo\BaseWarUnitTrigger; use sammo\BaseWarUnitTrigger;
use sammo\WarUnitTriggerCaller; use sammo\WarUnitTriggerCaller;
class che_의술_청낭서 extends \sammo\BaseItem{ class che_의술_청낭서 extends \sammo\BaseItem{
protected $id = 23; protected $id = 23;
protected $rawName = '청낭서'; protected $rawName = '청낭서';
protected $name = '청낭서(의술)'; protected $name = '청낭서(의술)';
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)'; protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
protected $cost = 200; protected $cost = 200;
protected $consumable = false; protected $consumable = false;
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{ public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
return new GeneralTriggerCaller( return new GeneralTriggerCaller(
new GeneralTrigger\che_도시치료($general) new GeneralTrigger\che_도시치료($general)
); );
} }
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
{ {
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM), new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM) new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
); );
} }
} }
@@ -1,35 +1,35 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\GeneralTrigger; use \sammo\GeneralTrigger;
use \sammo\GeneralTriggerCaller; use \sammo\GeneralTriggerCaller;
use \sammo\BaseWarUnitTrigger; use \sammo\BaseWarUnitTrigger;
use \sammo\WarUnitTriggerCaller; use \sammo\WarUnitTriggerCaller;
use sammo\WarUnitTrigger\che_전투치료발동; use sammo\WarUnitTrigger\che_전투치료발동;
use sammo\WarUnitTrigger\che_전투치료시도; use sammo\WarUnitTrigger\che_전투치료시도;
class che_의술_태평청령 extends \sammo\BaseItem{ class che_의술_태평청령 extends \sammo\BaseItem{
protected $id = 24; protected $id = 24;
protected $rawName = '태평청령'; protected $rawName = '태평청령';
protected $name = '태평청령(의술)'; protected $name = '태평청령(의술)';
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)'; protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
protected $cost = 200; protected $cost = 200;
protected $consumable = false; protected $consumable = false;
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{ public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
return new GeneralTriggerCaller( return new GeneralTriggerCaller(
new GeneralTrigger\che_도시치료($general) new GeneralTrigger\che_도시치료($general)
); );
} }
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
{ {
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM), new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM) new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
); );
} }
} }
+27 -27
View File
@@ -1,28 +1,28 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\WarUnitTriggerCaller; use \sammo\WarUnitTriggerCaller;
use \sammo\WarUnit; use \sammo\WarUnit;
use \sammo\WarUnitTrigger\che_저격시도; use \sammo\WarUnitTrigger\che_저격시도;
use \sammo\WarUnitTrigger\che_저격발동; use \sammo\WarUnitTrigger\che_저격발동;
use \sammo\BaseWarUnitTrigger; use \sammo\BaseWarUnitTrigger;
class che_저격_수극 extends \sammo\BaseItem{ class che_저격_수극 extends \sammo\BaseItem{
protected $id = 2; protected $id = 2;
protected $rawName = '수극'; protected $rawName = '수극';
protected $name = '수극(저격)'; protected $name = '수극(저격)';
protected $info = '[전투] 전투 개시 전 20% 확률로 저격 시도. 1회용'; protected $info = '[전투] 전투 개시 전 50% 확률로 저격 시도. 1회용';
protected $cost = 1000; protected $cost = 1000;
protected $consumable = true; protected $consumable = true;
protected $buyable = true; protected $buyable = true;
protected $reqSecu = 1000; protected $reqSecu = 1000;
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_저격시도($unit, BaseWarUnitTrigger::TYPE_CONSUMABLE_ITEM, 0.2, 20, 40), new che_저격시도($unit, BaseWarUnitTrigger::TYPE_CONSUMABLE_ITEM, 0.5, 20, 40),
new che_저격발동($unit) new che_저격발동($unit)
); );
} }
} }
@@ -13,7 +13,7 @@ class event_전투특기_격노 extends \sammo\BaseItem{
protected $id = 74; protected $id = 74;
protected $rawName = '비급'; protected $rawName = '비급';
protected $name = '비급(격노)'; protected $name = '비급(격노)';
protected $info = '[전투] 상대방 필살 회피 시도시 일정 확률로 격노(필살) 발동, 공격 시 일정 확률로 진노(1페이즈 추가)'; protected $info = '[전투] 상대방 필살 시 격노(필살) 발동, 회피 시도시 25% 확률로 격노 발동, 공격 시 일정 확률로 진노(1페이즈 추가)';
protected $cost = 100; protected $cost = 100;
protected $buyable = true; protected $buyable = true;
protected $consumable = false; protected $consumable = false;
@@ -12,7 +12,7 @@ class event_전투특기_공성 extends \sammo\BaseItem{
protected $id = 53; protected $id = 53;
protected $rawName = '비급'; protected $rawName = '비급';
protected $name = '비급(공성)'; protected $name = '비급(공성)';
protected $info = '[군사] 차병 계통 징·모병비 -10%<br>[전투] 성벽 공격 시 대미지 +100%'; protected $info = '[군사] 차병 계통 징·모병비 -10%<br>[전투] 성벽 공격 시 대미지 +100%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 차병 숙련을 가산';
protected $cost = 100; protected $cost = 100;
protected $buyable = true; protected $buyable = true;
protected $consumable = false; protected $consumable = false;
@@ -32,4 +32,18 @@ class event_전투특기_공성 extends \sammo\BaseItem{
} }
return [1, 1]; return [1, 1];
} }
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if(\sammo\Util::starts_with($statName, 'dex')){
$myArmType = 'dex'.GameUnitConst::T_CASTLE;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value;
}
} }
@@ -11,7 +11,7 @@ class event_전투특기_궁병 extends \sammo\BaseItem{
protected $id = 51; protected $id = 51;
protected $rawName = '비급'; protected $rawName = '비급';
protected $name = '비급(궁병)'; protected $name = '비급(궁병)';
protected $info = '[군사] 궁병 계통 징·모병비 -10%<br>[전투] 회피 확률 +20%p'; protected $info = '[군사] 궁병 계통 징·모병비 -10%<br>[전투] 회피 확률 +20%p,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 궁병 숙련을 가산';
protected $cost = 100; protected $cost = 100;
protected $buyable = true; protected $buyable = true;
protected $consumable = false; protected $consumable = false;
@@ -29,6 +29,16 @@ class event_전투특기_궁병 extends \sammo\BaseItem{
if($statName === 'warAvoidRatio'){ if($statName === 'warAvoidRatio'){
return $value + 0.2; return $value + 0.2;
} }
if(\sammo\Util::starts_with($statName, 'dex')){
$myArmType = 'dex'.GameUnitConst::T_ARCHER;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value; return $value;
} }
} }
@@ -11,7 +11,7 @@ class event_전투특기_귀병 extends \sammo\BaseItem{
protected $id = 40; protected $id = 40;
protected $rawName = '비급'; protected $rawName = '비급';
protected $name = '비급(귀병)'; protected $name = '비급(귀병)';
protected $info = '[군사] 귀병 계통 징·모병비 -10%<br>[전투] 계략 성공 확률 +20%p'; protected $info = '[군사] 귀병 계통 징·모병비 -10%<br>[전투] 계략 성공 확률 +20%p,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 귀병 숙련을 가산';
protected $cost = 100; protected $cost = 100;
protected $buyable = true; protected $buyable = true;
protected $consumable = false; protected $consumable = false;
@@ -29,6 +29,16 @@ class event_전투특기_귀병 extends \sammo\BaseItem{
if($statName === 'warMagicSuccessProb'){ if($statName === 'warMagicSuccessProb'){
return $value + 0.2; return $value + 0.2;
} }
if(\sammo\Util::starts_with($statName, 'dex')){
$myArmType = 'dex'.GameUnitConst::T_WIZARD;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value; return $value;
} }
} }
@@ -11,7 +11,7 @@ class event_전투특기_기병 extends \sammo\BaseItem{
protected $id = 52; protected $id = 52;
protected $rawName = '비급'; protected $rawName = '비급';
protected $name = '비급(기병)'; protected $name = '비급(기병)';
protected $info = '[군사] 기병 계통 징·모병비 -10%<br>[전투] 수비 시 대미지 +10%, 공격 시 대미지 +20%'; protected $info = '[군사] 기병 계통 징·모병비 -10%<br>[전투] 수비 시 대미지 +10%, 공격 시 대미지 +20%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 기병 숙련을 가산';
protected $cost = 100; protected $cost = 100;
protected $buyable = true; protected $buyable = true;
protected $consumable = false; protected $consumable = false;
@@ -31,4 +31,18 @@ class event_전투특기_기병 extends \sammo\BaseItem{
} }
return [1.1, 1]; return [1.1, 1];
} }
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if(\sammo\Util::starts_with($statName, 'dex')){
$myArmType = 'dex'.GameUnitConst::T_CAVALRY;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value;
}
} }
@@ -7,13 +7,14 @@ use \sammo\WarUnit;
use \sammo\BaseWarUnitTrigger; use \sammo\BaseWarUnitTrigger;
use \sammo\WarUnitTriggerCaller; use \sammo\WarUnitTriggerCaller;
use sammo\WarUnitTrigger\WarActivateSkills; use sammo\WarUnitTrigger\WarActivateSkills;
use \sammo\WarUnitTrigger\che_돌격지속;
class event_전투특기_돌격 extends \sammo\BaseItem{ class event_전투특기_돌격 extends \sammo\BaseItem{
protected $id = 60; protected $id = 60;
protected $rawName = '비급'; protected $rawName = '비급';
protected $name = '비급(돌격)'; protected $name = '비급(돌격)';
protected $info = '[전투] 상대 회피 불가, 공격 시 전투 페이즈 +1, 공격 시 대미지 +10%'; protected $info = '[전투] 공격 시 대등/유리한 병종에게는 퇴각 전까지 전투, 공격 시 페이즈 + 2, 공격 시 대미지 +5%';
protected $cost = 100; protected $cost = 100;
protected $buyable = true; protected $buyable = true;
protected $consumable = false; protected $consumable = false;
@@ -21,21 +22,20 @@ class event_전투특기_돌격 extends \sammo\BaseItem{
public function onCalcStat(General $general, string $statName, $value, $aux=null){ public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'initWarPhase'){ if($statName === 'initWarPhase'){
return $value + 1; return $value + 2;
} }
return $value; return $value;
} }
public function getWarPowerMultiplier(WarUnit $unit):array{ public function getWarPowerMultiplier(WarUnit $unit):array{
if($unit->isAttacker()){ if($unit->isAttacker()){
return [1.1, 1]; return [1.05, 1];
} }
return [1, 1]; return [1, 1];
} }
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
(new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '회피불가'))->setPriority(BaseWarUnitTrigger::PRIORITY_BEGIN + 200) new che_돌격지속($unit)
); );
} }
} }
@@ -4,13 +4,14 @@ use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\WarUnit; use \sammo\WarUnit;
use \sammo\Util;
class event_전투특기_무쌍 extends \sammo\BaseItem{ class event_전투특기_무쌍 extends \sammo\BaseItem{
protected $id = 61; protected $id = 61;
protected $rawName = '비급'; protected $rawName = '비급';
protected $name = '비급(무쌍)'; protected $name = '비급(무쌍)';
protected $info = '[전투] 대미지 +10%, 공격 시 필살 확률 +10%p'; protected $info = '[전투] 대미지 +10%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대50%)';
protected $cost = 100; protected $cost = 100;
protected $buyable = true; protected $buyable = true;
protected $consumable = false; protected $consumable = false;
@@ -24,6 +25,11 @@ class event_전투특기_무쌍 extends \sammo\BaseItem{
} }
public function getWarPowerMultiplier(WarUnit $unit):array{ public function getWarPowerMultiplier(WarUnit $unit):array{
return [1.1, 1]; $attackMultiplier = 1.1;
$defenceMultiplier = 1;
$killnum = $unit->getGeneral()->getRankVar('killnum');
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4);
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.5);
return [$attackMultiplier, $defenceMultiplier];
} }
} }
@@ -15,7 +15,7 @@ class event_전투특기_반계 extends \sammo\BaseItem{
protected $id = 45; protected $id = 45;
protected $rawName = '비급'; protected $rawName = '비급';
protected $name = '비급(반계)'; protected $name = '비급(반계)';
protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림, 반목 성공시 대미지 추가(+60% → +100%)'; protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림, 반목 성공시 대미지 추가(+60% → +150%)';
protected $cost = 100; protected $cost = 100;
protected $buyable = true; protected $buyable = true;
protected $consumable = false; protected $consumable = false;
@@ -23,15 +23,15 @@ class event_전투특기_반계 extends \sammo\BaseItem{
public function onCalcStat(General $general, string $statName, $value, $aux=null){ public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicSuccessDamage' && $aux === '반목'){ if($statName === 'warMagicSuccessDamage' && $aux === '반목'){
return $value + 0.4; return $value + 0.9;
} }
return $value; return $value;
} }
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM, false, '계략약화'), new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '계략약화'),
new che_반계시도($unit, che_반계시도::TYPE_ITEM), new che_반계시도($unit),
new che_반계발동($unit) new che_반계발동($unit)
); );
} }
@@ -11,7 +11,7 @@ class event_전투특기_보병 extends \sammo\BaseItem{
protected $id = 50; protected $id = 50;
protected $rawName = '비급'; protected $rawName = '비급';
protected $name = '비급(보병)'; protected $name = '비급(보병)';
protected $info = '[군사] 보병 계통 징·모병비 -10%<br>[전투] 공격 시 아군 피해 -10%, 수비 시 아군 피해 -20%'; protected $info = '[군사] 보병 계통 징·모병비 -10%<br>[전투] 공격 시 아군 피해 -10%, 수비 시 아군 피해 -20%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 보병 숙련을 가산';
protected $cost = 100; protected $cost = 100;
protected $buyable = true; protected $buyable = true;
protected $consumable = false; protected $consumable = false;
@@ -32,4 +32,18 @@ class event_전투특기_보병 extends \sammo\BaseItem{
} }
return [1, 0.8]; return [1, 0.8];
} }
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if(\sammo\Util::starts_with($statName, 'dex')){
$myArmType = 'dex'.GameUnitConst::T_FOOTMAN;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value;
}
} }
@@ -13,7 +13,7 @@ class event_전투특기_위압 extends \sammo\BaseItem{
protected $id = 63; protected $id = 63;
protected $rawName = '비급'; protected $rawName = '비급';
protected $name = '비급(위압)'; protected $name = '비급(위압)';
protected $info = '[전투] 훈련/사기≥90, 병력≥1,000 일 때 첫 페이즈 위압 발동(적 공격 불가)'; protected $info = '[전투] 첫 페이즈 위압 발동(적 공격, 회피 불가, 사기 5 감소)';
protected $cost = 100; protected $cost = 100;
protected $buyable = true; protected $buyable = true;
protected $consumable = false; protected $consumable = false;
@@ -16,7 +16,7 @@ class event_전투특기_의술 extends \sammo\BaseItem{
protected $id = 73; protected $id = 73;
protected $rawName = '비급'; protected $rawName = '비급';
protected $name = '비급(의술)'; protected $name = '비급(의술)';
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)'; protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
protected $cost = 100; protected $cost = 100;
protected $buyable = true; protected $buyable = true;
protected $consumable = false; protected $consumable = false;
@@ -13,7 +13,7 @@ class event_전투특기_저격 extends \sammo\BaseItem{
protected $id = 70; protected $id = 70;
protected $rawName = '비급'; protected $rawName = '비급';
protected $name = '비급(저격)'; protected $name = '비급(저격)';
protected $info = '[전투] 새로운 상대와 전투 시 1/3 확률로 저격 발동, 성공 시 사기+10'; protected $info = '[전투] 새로운 상대와 전투 시 50% 확률로 저격 발동, 성공 시 사기+10';
protected $cost = 100; protected $cost = 100;
protected $buyable = true; protected $buyable = true;
protected $consumable = false; protected $consumable = false;
@@ -21,7 +21,7 @@ class event_전투특기_저격 extends \sammo\BaseItem{
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM, 1/3, 20, 60), new che_저격시도($unit, che_저격시도::TYPE_ITEM, 0.5, 10, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM) new che_저격발동($unit, che_저격발동::TYPE_ITEM)
); );
} }
@@ -12,7 +12,7 @@ class event_전투특기_필살 extends \sammo\BaseItem{
protected $id = 71; protected $id = 71;
protected $rawName = '비급'; protected $rawName = '비급';
protected $name = '비급(필살)'; protected $name = '비급(필살)';
protected $info = '[전투] 필살 확률 +20%p, 필살 발동시 대상 회피 불가'; protected $info = '[전투] 필살 확률 +25%p, 필살 발동시 대상 회피 불가';
protected $cost = 100; protected $cost = 100;
protected $buyable = true; protected $buyable = true;
protected $consumable = false; protected $consumable = false;
@@ -20,7 +20,7 @@ class event_전투특기_필살 extends \sammo\BaseItem{
public function onCalcStat(General $general, string $statName, $value, $aux=null){ public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warCriticalRatio'){ if($statName === 'warCriticalRatio'){
return $value + 0.2; return $value + 0.25;
} }
return $value; return $value;
} }
+28 -28
View File
@@ -1,29 +1,29 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\WarUnit; use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller; use sammo\WarUnitTriggerCaller;
use sammo\WarUnitTrigger\che_격노시도; use sammo\WarUnitTrigger\che_격노시도;
use sammo\WarUnitTrigger\che_격노발동; use sammo\WarUnitTrigger\che_격노발동;
class che_격노 extends \sammo\BaseSpecial{ class che_격노 extends \sammo\BaseSpecial{
protected $id = 74; protected $id = 74;
protected $name = '격노'; protected $name = '격노';
protected $info = '[전투] 상대방 필살 회피 시도시 일정 확률로 격노(필살) 발동, 공격 시 일정 확률로 진노(1페이즈 추가)'; protected $info = '[전투] 상대방 필살 시 격노(필살) 발동, 회피 시도시 25% 확률로 격노 발동, 공격 시 일정 확률로 진노(1페이즈 추가)';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
static $type = [ static $type = [
SpecialityHelper::STAT_STRENGTH, SpecialityHelper::STAT_STRENGTH,
]; ];
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_격노시도($unit), new che_격노시도($unit),
new che_격노발동($unit) new che_격노발동($unit)
); );
} }
} }
+39 -39
View File
@@ -1,40 +1,40 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\WarUnit; use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller; use sammo\WarUnitTriggerCaller;
use sammo\BaseWarUnitTrigger; use sammo\BaseWarUnitTrigger;
use sammo\WarUnitTrigger\che_부상무효; use sammo\WarUnitTrigger\che_부상무효;
use sammo\WarUnitTrigger\WarActivateSkills; use sammo\WarUnitTrigger\WarActivateSkills;
class che_견고 extends \sammo\BaseSpecial{ class che_견고 extends \sammo\BaseSpecial{
protected $id = 62; protected $id = 62;
protected $name = '견고'; protected $name = '견고';
protected $info = '[전투] 상대 필살, 격노, 위압, 저격 불가, 상대 계략 시도시 성공 확률 -10%p, 부상 없음, 아군 피해 -5%'; protected $info = '[전투] 상대 필살, 저격 불가, 상대 계략 시도시 성공 확률 -10%p, 부상 없음, 아군 피해 -10%';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
static $type = [ static $type = [
SpecialityHelper::STAT_STRENGTH SpecialityHelper::STAT_STRENGTH
]; ];
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_부상무효($unit, BaseWarUnitTrigger::TYPE_NONE), new che_부상무효($unit, BaseWarUnitTrigger::TYPE_NONE),
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '저격불가') new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '저격불가')
); );
} }
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '필살불가', '위압불가', '격노불가', '계략약화', '저격불가') new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '필살불가', '계략약화', '저격불가')
); );
} }
public function getWarPowerMultiplier(WarUnit $unit):array{ public function getWarPowerMultiplier(WarUnit $unit):array{
return [1, 0.95]; return [1, 0.9];
} }
} }
+49 -35
View File
@@ -1,36 +1,50 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\GameUnitConst; use \sammo\GameUnitConst;
use \sammo\WarUnit; use \sammo\WarUnit;
use \sammo\WarUnitCity; use \sammo\WarUnitCity;
class che_공성 extends \sammo\BaseSpecial{ class che_공성 extends \sammo\BaseSpecial{
protected $id = 53; protected $id = 53;
protected $name = '공성'; protected $name = '공성';
protected $info = '[군사] 차병 계통 징·모병비 -10%<br>[전투] 성벽 공격 시 대미지 +100%'; protected $info = '[군사] 차병 계통 징·모병비 -10%<br>[전투] 성벽 공격 시 대미지 +100%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 차병 숙련을 가산';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
static $type = [ static $type = [
SpecialityHelper::STAT_LEADERSHIP | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_SIEGE, SpecialityHelper::STAT_LEADERSHIP | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_SIEGE,
]; ];
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if(in_array($turnType, ['징병', '모병'])){ if(in_array($turnType, ['징병', '모병'])){
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_SIEGE) return $value * 0.9; if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_SIEGE) return $value * 0.9;
} }
return $value; return $value;
} }
public function getWarPowerMultiplier(WarUnit $unit):array{ public function getWarPowerMultiplier(WarUnit $unit):array{
if($unit->getOppose() instanceof WarUnitCity){ if($unit->getOppose() instanceof WarUnitCity){
return [2, 1]; return [2, 1];
} }
return [1, 1]; return [1, 1];
} }
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if(\sammo\Util::starts_with($statName, 'dex')){
$myArmType = 'dex'.GameUnitConst::T_CASTLE;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value;
}
} }
+11 -1
View File
@@ -10,7 +10,7 @@ class che_궁병 extends \sammo\BaseSpecial{
protected $id = 51; protected $id = 51;
protected $name = '궁병'; protected $name = '궁병';
protected $info = '[군사] 궁병 계통 징·모병비 -10%<br>[전투] 회피 확률 +20%p'; protected $info = '[군사] 궁병 계통 징·모병비 -10%<br>[전투] 회피 확률 +20%p,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 궁병 숙련을 가산';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
@@ -31,6 +31,16 @@ class che_궁병 extends \sammo\BaseSpecial{
if($statName === 'warAvoidRatio'){ if($statName === 'warAvoidRatio'){
return $value + 0.2; return $value + 0.2;
} }
if(\sammo\Util::starts_with($statName, 'dex')){
$myArmType = 'dex'.GameUnitConst::T_ARCHER;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value; return $value;
} }
} }
+44 -34
View File
@@ -1,35 +1,45 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\GameUnitConst; use \sammo\GameUnitConst;
use \sammo\WarUnit; use \sammo\WarUnit;
class che_귀병 extends \sammo\BaseSpecial{ class che_귀병 extends \sammo\BaseSpecial{
protected $id = 40; protected $id = 40;
protected $name = '귀병'; protected $name = '귀병';
protected $info = '[군사] 귀병 계통 징·모병비 -10%<br>[전투] 계략 성공 확률 +20%p'; protected $info = '[군사] 귀병 계통 징·모병비 -10%<br>[전투] 계략 성공 확률 +20%p,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 귀병 숙련을 가산';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
static $type = [ static $type = [
SpecialityHelper::STAT_INTEL | SpecialityHelper::ARMY_WIZARD | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::STAT_NOT_STRENGTH SpecialityHelper::STAT_INTEL | SpecialityHelper::ARMY_WIZARD | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::STAT_NOT_STRENGTH
]; ];
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if(in_array($turnType, ['징병', '모병'])){ if(in_array($turnType, ['징병', '모병'])){
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_WIZARD) return $value * 0.9; if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_WIZARD) return $value * 0.9;
} }
return $value; return $value;
} }
public function onCalcStat(General $general, string $statName, $value, $aux=null){ public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicSuccessProb'){ if($statName === 'warMagicSuccessProb'){
return $value + 0.2; return $value + 0.2;
} }
return $value; if(\sammo\Util::starts_with($statName, 'dex')){
} $myArmType = 'dex'.GameUnitConst::T_WIZARD;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value;
}
} }
+49 -35
View File
@@ -1,36 +1,50 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\GameUnitConst; use \sammo\GameUnitConst;
use \sammo\WarUnit; use \sammo\WarUnit;
class che_기병 extends \sammo\BaseSpecial{ class che_기병 extends \sammo\BaseSpecial{
protected $id = 52; protected $id = 52;
protected $name = '기병'; protected $name = '기병';
protected $info = '[군사] 기병 계통 징·모병비 -10%<br>[전투] 수비 시 대미지 +10%, 공격 시 대미지 +20%'; protected $info = '[군사] 기병 계통 징·모병비 -10%<br>[전투] 수비 시 대미지 +10%, 공격 시 대미지 +20%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 기병 숙련을 가산';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
static $type = [ static $type = [
SpecialityHelper::STAT_LEADERSHIP | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_CAVALRY | SpecialityHelper::STAT_NOT_INTEL, SpecialityHelper::STAT_LEADERSHIP | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_CAVALRY | SpecialityHelper::STAT_NOT_INTEL,
SpecialityHelper::STAT_STRENGTH | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_CAVALRY SpecialityHelper::STAT_STRENGTH | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_CAVALRY
]; ];
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if(in_array($turnType, ['징병', '모병'])){ if(in_array($turnType, ['징병', '모병'])){
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_CAVALRY) return $value * 0.9; if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_CAVALRY) return $value * 0.9;
} }
return $value; return $value;
} }
public function getWarPowerMultiplier(WarUnit $unit):array{ public function getWarPowerMultiplier(WarUnit $unit):array{
if($unit->isAttacker()){ if($unit->isAttacker()){
return [1.2, 1]; return [1.2, 1];
} }
return [1.1, 1]; return [1.1, 1];
} }
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if(\sammo\Util::starts_with($statName, 'dex')){
$myArmType = 'dex'.GameUnitConst::T_CAVALRY;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value;
}
} }
+41 -41
View File
@@ -1,42 +1,42 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\WarUnit; use \sammo\WarUnit;
use \sammo\BaseWarUnitTrigger; use \sammo\BaseWarUnitTrigger;
use \sammo\WarUnitTriggerCaller; use \sammo\WarUnitTriggerCaller;
use sammo\WarUnitTrigger\WarActivateSkills; use sammo\WarUnitTrigger\WarActivateSkills;
use \sammo\WarUnitTrigger\che_돌격지속;
class che_돌격 extends \sammo\BaseSpecial{
class che_돌격 extends \sammo\BaseSpecial{
protected $id = 60;
protected $name = '돌격'; protected $id = 60;
protected $info = '[전투] 상대 회피 불가, 공격 시 전투 페이즈 +1, 공격 시 대미지 +10%'; protected $name = '돌격';
protected $info = '[전투] 공격 시 대등/유리한 병종에게는 퇴각 전까지 전투, 공격 시 페이즈 + 2, 공격 시 대미지 +5%';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $type = [ static $selectWeight = 1;
SpecialityHelper::STAT_STRENGTH static $type = [
]; SpecialityHelper::STAT_STRENGTH
];
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'initWarPhase'){ public function onCalcStat(General $general, string $statName, $value, $aux=null){
return $value + 1; if($statName === 'initWarPhase'){
} return $value + 2;
return $value; }
} return $value;
}
public function getWarPowerMultiplier(WarUnit $unit):array{ public function getWarPowerMultiplier(WarUnit $unit):array{
if($unit->isAttacker()){ if($unit->isAttacker()){
return [1.1, 1]; return [1.05, 1];
} }
return [1, 1]; return [1, 1];
} }
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
(new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '회피불가'))->setPriority(BaseWarUnitTrigger::PRIORITY_BEGIN + 200) new che_돌격지속($unit)
); );
} }
} }
+35 -29
View File
@@ -1,30 +1,36 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\WarUnit; use \sammo\WarUnit;
use \sammo\Util;
class che_무쌍 extends \sammo\BaseSpecial{
class che_무쌍 extends \sammo\BaseSpecial{
protected $id = 61;
protected $name = '무쌍'; protected $id = 61;
protected $info = '[전투] 대미지 +10%, 공격 시 필살 확률 +10%p'; protected $name = '무쌍';
protected $info = '[전투] 대미지 +10%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대50%)';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $type = [ static $selectWeight = 1;
SpecialityHelper::STAT_STRENGTH static $type = [
]; SpecialityHelper::STAT_STRENGTH
];
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warCriticalRatio' && $aux['isAttacker']??false){ public function onCalcStat(General $general, string $statName, $value, $aux=null){
return $value += 0.1; if($statName === 'warCriticalRatio' && $aux['isAttacker']??false){
} return $value += 0.1;
return $value; }
} return $value;
}
public function getWarPowerMultiplier(WarUnit $unit):array{
return [1.1, 1]; public function getWarPowerMultiplier(WarUnit $unit):array{
} $attackMultiplier = 1.1;
$defenceMultiplier = 1;
$killnum = $unit->getGeneral()->getRankVar('killnum');
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4);
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.5);
return [$attackMultiplier, $defenceMultiplier];
}
} }
+38 -38
View File
@@ -1,39 +1,39 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\WarUnit; use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller; use sammo\WarUnitTriggerCaller;
use \sammo\BaseWarUnitTrigger; use \sammo\BaseWarUnitTrigger;
use \sammo\WarUnitTrigger\WarActivateSkills; use \sammo\WarUnitTrigger\WarActivateSkills;
use \sammo\WarUnitTrigger\che_반계시도; use \sammo\WarUnitTrigger\che_반계시도;
use \sammo\WarUnitTrigger\che_반계발동; use \sammo\WarUnitTrigger\che_반계발동;
class che_반계 extends \sammo\BaseSpecial{ class che_반계 extends \sammo\BaseSpecial{
protected $id = 45; protected $id = 45;
protected $name = '반계'; protected $name = '반계';
protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림, 반목 성공시 대미지 추가(+60% → +100%)'; protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림, 반목 성공시 대미지 추가(+60% → +150%)';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
static $type = [ static $type = [
SpecialityHelper::STAT_INTEL, SpecialityHelper::STAT_INTEL,
]; ];
public function onCalcStat(General $general, string $statName, $value, $aux=null){ public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicSuccessDamage' && $aux === '반목'){ if($statName === 'warMagicSuccessDamage' && $aux === '반목'){
return $value + 0.4; return $value + 0.9;
} }
return $value; return $value;
} }
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '계략약화'), new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '계략약화'),
new che_반계시도($unit), new che_반계시도($unit),
new che_반계발동($unit) new che_반계발동($unit)
); );
} }
} }
+49 -35
View File
@@ -1,36 +1,50 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\GameUnitConst; use \sammo\GameUnitConst;
use \sammo\WarUnit; use \sammo\WarUnit;
class che_보병 extends \sammo\BaseSpecial{ class che_보병 extends \sammo\BaseSpecial{
protected $id = 50; protected $id = 50;
protected $name = '보병'; protected $name = '보병';
protected $info = '[군사] 보병 계통 징·모병비 -10%<br>[전투] 공격 시 아군 피해 -10%, 수비 시 아군 피해 -20%'; protected $info = '[군사] 보병 계통 징·모병비 -10%<br>[전투] 공격 시 아군 피해 -10%, 수비 시 아군 피해 -20%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 보병 숙련을 가산';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
static $type = [ static $type = [
SpecialityHelper::STAT_LEADERSHIP | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_FOOTMAN | SpecialityHelper::STAT_NOT_INTEL, SpecialityHelper::STAT_LEADERSHIP | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_FOOTMAN | SpecialityHelper::STAT_NOT_INTEL,
SpecialityHelper::STAT_STRENGTH | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_FOOTMAN SpecialityHelper::STAT_STRENGTH | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_FOOTMAN
]; ];
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if(in_array($turnType, ['징병', '모병'])){ if(in_array($turnType, ['징병', '모병'])){
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_FOOTMAN) return $value * 0.9; if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_FOOTMAN) return $value * 0.9;
} }
return $value; return $value;
} }
public function getWarPowerMultiplier(WarUnit $unit):array{ public function getWarPowerMultiplier(WarUnit $unit):array{
if($unit->isAttacker()){ if($unit->isAttacker()){
return [1, 0.9]; return [1, 0.9];
} }
return [1, 0.8]; return [1, 0.8];
} }
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if(\sammo\Util::starts_with($statName, 'dex')){
$myArmType = 'dex'.GameUnitConst::T_FOOTMAN;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value;
}
} }
+28 -31
View File
@@ -1,32 +1,29 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\WarUnit; use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller; use sammo\WarUnitTriggerCaller;
use \sammo\WarUnitTrigger\che_위압시도; use \sammo\WarUnitTrigger\che_위압시도;
use \sammo\WarUnitTrigger\che_위압발동; use \sammo\WarUnitTrigger\che_위압발동;
class che_위압 extends \sammo\BaseSpecial{ class che_위압 extends \sammo\BaseSpecial{
protected $id = 63; protected $id = 63;
protected $name = '위압'; protected $name = '위압';
protected $info = '[전투] 훈련/사기≥90, 병력≥1,000 일 때 첫 페이즈 위압 발동(적 공격 불가)'; protected $info = '[전투] 첫 페이즈 위압 발동(적 공격, 회피 불가, 사기 5 감소)';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
static $type = [ static $type = [
SpecialityHelper::STAT_STRENGTH SpecialityHelper::STAT_STRENGTH
]; ];
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
if($unit->getPhase() != 0){ return new WarUnitTriggerCaller(
return null; new che_위압시도($unit),
} new che_위압발동($unit)
return new WarUnitTriggerCaller( );
new che_위압시도($unit), }
new che_위압발동($unit)
);
}
} }
+41 -41
View File
@@ -1,41 +1,41 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use sammo\BaseGeneralTrigger; use sammo\BaseGeneralTrigger;
use sammo\SpecialityHelper; use sammo\SpecialityHelper;
use \sammo\General; use \sammo\General;
use \sammo\GeneralTrigger; use \sammo\GeneralTrigger;
use \sammo\GeneralTriggerCaller; use \sammo\GeneralTriggerCaller;
use \sammo\WarUnit; use \sammo\WarUnit;
use sammo\WarUnitTrigger\che_전투치료발동; use sammo\WarUnitTrigger\che_전투치료발동;
use sammo\WarUnitTrigger\che_전투치료시도; use sammo\WarUnitTrigger\che_전투치료시도;
use sammo\WarUnitTriggerCaller; use sammo\WarUnitTriggerCaller;
class che_의술 extends \sammo\BaseSpecial{ class che_의술 extends \sammo\BaseSpecial{
protected $id = 73; protected $id = 73;
protected $name = '의술'; protected $name = '의술';
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)'; protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
static $selectWeightType = SpecialityHelper::WEIGHT_PERCENT; static $selectWeightType = SpecialityHelper::WEIGHT_PERCENT;
static $selectWeight = 2; static $selectWeight = 2;
static $type = [ static $type = [
SpecialityHelper::STAT_LEADERSHIP, SpecialityHelper::STAT_LEADERSHIP,
SpecialityHelper::STAT_STRENGTH, SpecialityHelper::STAT_STRENGTH,
SpecialityHelper::STAT_INTEL SpecialityHelper::STAT_INTEL
]; ];
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{ public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
return new GeneralTriggerCaller( return new GeneralTriggerCaller(
new GeneralTrigger\che_도시치료($general) new GeneralTrigger\che_도시치료($general)
); );
} }
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
{ {
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_전투치료시도($unit), new che_전투치료시도($unit),
new che_전투치료발동($unit) new che_전투치료발동($unit)
); );
} }
} }
+30 -30
View File
@@ -1,31 +1,31 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\WarUnit; use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller; use sammo\WarUnitTriggerCaller;
use \sammo\WarUnitTrigger\che_저격시도; use \sammo\WarUnitTrigger\che_저격시도;
use \sammo\WarUnitTrigger\che_저격발동; use \sammo\WarUnitTrigger\che_저격발동;
class che_저격 extends \sammo\BaseSpecial{ class che_저격 extends \sammo\BaseSpecial{
protected $id = 70; protected $id = 70;
protected $name = '저격'; protected $name = '저격';
protected $info = '[전투] 새로운 상대와 전투 시 1/3 확률로 저격 발동, 성공 시 사기+10'; protected $info = '[전투] 새로운 상대와 전투 시 50% 확률로 저격 발동, 성공 시 사기+10';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
static $type = [ static $type = [
SpecialityHelper::STAT_LEADERSHIP, SpecialityHelper::STAT_LEADERSHIP,
SpecialityHelper::STAT_STRENGTH, SpecialityHelper::STAT_STRENGTH,
SpecialityHelper::STAT_INTEL SpecialityHelper::STAT_INTEL
]; ];
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_NONE, 1/3, 20, 60), new che_저격시도($unit, che_저격시도::TYPE_NONE, 0.5, 10, 40),
new che_저격발동($unit) new che_저격발동($unit)
); );
} }
} }
+35 -35
View File
@@ -1,36 +1,36 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\WarUnit; use \sammo\WarUnit;
class che_징병 extends \sammo\BaseSpecial{ class che_징병 extends \sammo\BaseSpecial{
protected $id = 72; protected $id = 72;
protected $name = '징병'; protected $name = '징병';
protected $info = '[군사] 징·모병비 -50%, 통솔 순수 능력치 보정 +15%'; protected $info = '[군사] 징·모병비 -50%, 통솔 순수 능력치 보정 +25%';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
static $type = [ static $type = [
SpecialityHelper::STAT_LEADERSHIP, SpecialityHelper::STAT_LEADERSHIP,
SpecialityHelper::STAT_STRENGTH, SpecialityHelper::STAT_STRENGTH,
SpecialityHelper::STAT_INTEL SpecialityHelper::STAT_INTEL
]; ];
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if(in_array($turnType, ['징병', '모병'])){ if(in_array($turnType, ['징병', '모병'])){
if($varType == 'cost') return $value * 0.5; if($varType == 'cost') return $value * 0.5;
} }
return $value; return $value;
} }
public function onCalcStat(General $general, string $statName, $value, $aux=null){ public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'leadership'){ if($statName === 'leadership'){
return $value *= 1.15; return $value + $general->getVar('leadership') * 0.25;
} }
return $value; return $value;
} }
} }
+28 -28
View File
@@ -1,29 +1,29 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\WarUnit; use \sammo\WarUnit;
class che_척사 extends \sammo\BaseSpecial{ class che_척사 extends \sammo\BaseSpecial{
protected $id = 75; protected $id = 75;
protected $name = '척사'; protected $name = '척사';
protected $info = '[전투] 지역·도시 병종 상대로 대미지 +10%, 아군 피해 -10%'; protected $info = '[전투] 지역·도시 병종 상대로 대미지 +15%, 아군 피해 -15%';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
static $type = [ static $type = [
SpecialityHelper::STAT_LEADERSHIP, SpecialityHelper::STAT_LEADERSHIP,
SpecialityHelper::STAT_STRENGTH, SpecialityHelper::STAT_STRENGTH,
SpecialityHelper::STAT_INTEL SpecialityHelper::STAT_INTEL
]; ];
public function getWarPowerMultiplier(WarUnit $unit):array{ public function getWarPowerMultiplier(WarUnit $unit):array{
$opposeCrewType = $unit->getOppose()->getCrewType(); $opposeCrewType = $unit->getOppose()->getCrewType();
if($opposeCrewType->reqCities || $opposeCrewType->reqRegions){ if($opposeCrewType->reqCities || $opposeCrewType->reqRegions){
return [1.1, 0.9]; return [1.15, 0.85];
} }
return [1, 1]; return [1, 1];
} }
} }
+35 -35
View File
@@ -1,36 +1,36 @@
<?php <?php
namespace sammo\ActionSpecialWar; namespace sammo\ActionSpecialWar;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\SpecialityHelper; use \sammo\SpecialityHelper;
use \sammo\WarUnit; use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller; use sammo\WarUnitTriggerCaller;
use sammo\WarUnitTrigger\che_필살강화_회피불가; use sammo\WarUnitTrigger\che_필살강화_회피불가;
class che_필살 extends \sammo\BaseSpecial{ class che_필살 extends \sammo\BaseSpecial{
protected $id = 71; protected $id = 71;
protected $name = '필살'; protected $name = '필살';
protected $info = '[전투] 필살 확률 +20%p, 필살 발동시 대상 회피 불가'; protected $info = '[전투] 필살 확률 +25%p, 필살 발동시 대상 회피 불가';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
static $type = [ static $type = [
SpecialityHelper::STAT_LEADERSHIP, SpecialityHelper::STAT_LEADERSHIP,
SpecialityHelper::STAT_STRENGTH, SpecialityHelper::STAT_STRENGTH,
SpecialityHelper::STAT_INTEL SpecialityHelper::STAT_INTEL
]; ];
public function onCalcStat(General $general, string $statName, $value, $aux=null){ public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warCriticalRatio'){ if($statName === 'warCriticalRatio'){
return $value + 0.2; return $value + 0.25;
} }
return $value; return $value;
} }
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_필살강화_회피불가($unit) new che_필살강화_회피불가($unit)
); );
} }
} }
+2 -2
View File
@@ -247,9 +247,9 @@ class WarUnit{
$warPower *= $this->getComputedAtmos(); $warPower *= $this->getComputedAtmos();
$warPower /= $oppose->getComputedTrain(); $warPower /= $oppose->getComputedTrain();
$genDexAtt = $this->getDex($this->getCrewType()); $genDexAtt = $this->getDex($this->getCrewType(), true);
$oppDexDef = $oppose->getDex($this->getCrewType()); $oppDexDef = $oppose->getDex($this->getCrewType(), false);
$warPower *= getDexLog($genDexAtt, $oppDexDef); $warPower *= getDexLog($genDexAtt, $oppDexDef);
+164 -164
View File
@@ -1,165 +1,165 @@
<?php <?php
namespace sammo; namespace sammo;
class WarUnitCity extends WarUnit{ class WarUnitCity extends WarUnit{
use LazyVarUpdater; use LazyVarUpdater;
protected $hp; protected $hp;
protected $cityRate; protected $cityRate;
function __construct($raw, $rawNation, int $year, int $month, $cityRate){ function __construct($raw, $rawNation, int $year, int $month, $cityRate){
$general = new DummyGeneral(false); $general = new DummyGeneral(false);
$general->setVar('city', $raw['city']); $general->setVar('city', $raw['city']);
$general->setVar('nation', $raw['nation']); $general->setVar('nation', $raw['nation']);
$general->initLogger($year, $month); $general->initLogger($year, $month);
$this->general = $general; $this->general = $general;
$this->raw = $raw; $this->raw = $raw;
$this->rawNation = $rawNation; $this->rawNation = $rawNation;
$this->isAttacker = false; $this->isAttacker = false;
$this->cityRate = $cityRate; $this->cityRate = $cityRate;
$this->logger = $general->getLogger(); $this->logger = $general->getLogger();
$this->crewType = GameUnitConst::byID(GameUnitConst::CREWTYPE_CASTLE); $this->crewType = GameUnitConst::byID(GameUnitConst::CREWTYPE_CASTLE);
$this->hp = $this->getCityVar('def') * 10; $this->hp = $this->getCityVar('def') * 10;
//수비자 보정 //수비자 보정
if($this->getCityVar('level') == 1){ if($this->getCityVar('level') == 1){
$this->trainBonus += 5; $this->trainBonus += 5;
} }
else if($this->getCityVar('level') == 3){ else if($this->getCityVar('level') == 3){
$this->trainBonus += 5; $this->trainBonus += 5;
} }
} }
function getName():string{ function getName():string{
return $this->getVar('name'); return $this->getVar('name');
} }
function getCityVar(string $key){ function getCityVar(string $key){
return $this->raw[$key]; return $this->raw[$key];
} }
function getComputedAttack(){ function getComputedAttack(){
return ($this->raw['def'] + $this->raw['wall'] * 9) / 500 + 200; return ($this->raw['def'] + $this->raw['wall'] * 9) / 500 + 200;
} }
function getComputedDefence(){ function getComputedDefence(){
return ($this->raw['def'] + $this->raw['wall'] * 9) / 500 + 200; return ($this->raw['def'] + $this->raw['wall'] * 9) / 500 + 200;
} }
function increaseKilled(int $damage):int{ function increaseKilled(int $damage):int{
$this->killed += $damage; $this->killed += $damage;
$this->killedCurr += $damage; $this->killedCurr += $damage;
return $this->killed; return $this->killed;
} }
function getComputedTrain(){ function getComputedTrain(){
return $this->cityRate + $this->trainBonus; return $this->cityRate + $this->trainBonus;
} }
function getComputedAtmos(){ function getComputedAtmos(){
return $this->cityRate + $this->atmosBonus; return $this->cityRate + $this->atmosBonus;
} }
function getHP():int{ function getHP():int{
return $this->hp; return $this->hp;
} }
function getDex(GameUnitDetail $crewType){ function getDex(GameUnitDetail $crewType){
return ($this->cityRate - 60) * 7200; return ($this->cityRate - 60) * 7200;
} }
function decreaseHP(int $damage):int{ function decreaseHP(int $damage):int{
$damage = min($damage, $this->hp); $damage = min($damage, $this->hp);
$this->dead += $damage; $this->dead += $damage;
$this->deadCurr += $damage; $this->deadCurr += $damage;
$this->hp -= $damage; $this->hp -= $damage;
$this->increaseVarWithLimit('wall', -$damage/20, 0); $this->increaseVarWithLimit('wall', -$damage/20, 0);
return $this->hp; return $this->hp;
} }
function continueWar(&$noRice):bool{ function continueWar(&$noRice):bool{
//전투가 가능하면 true //전투가 가능하면 true
$noRice = false; $noRice = false;
if($this->getHP() <= 0){ if($this->getHP() <= 0){
return false; return false;
} }
//도시 성벽은 쌀이 소모된다고 항복하지 않음 //도시 성벽은 쌀이 소모된다고 항복하지 않음
return true; return true;
} }
function heavyDecreaseWealth(){ function heavyDecreaseWealth(){
$this->multiplyVar('agri', 0.5); $this->multiplyVar('agri', 0.5);
$this->multiplyVar('comm', 0.5); $this->multiplyVar('comm', 0.5);
$this->multiplyVar('secu', 0.5); $this->multiplyVar('secu', 0.5);
} }
function finishBattle(){ function finishBattle(){
if($this->isFinished){ if($this->isFinished){
return; return;
} }
$this->clearActivatedSkill(); $this->clearActivatedSkill();
$this->isFinished = true; $this->isFinished = true;
$this->updateVar('def', Util::round($this->getHP() / 10)); $this->updateVar('def', Util::round($this->getHP() / 10));
$this->updateVar('wall', Util::round($this->getVar('wall'))); $this->updateVar('wall', Util::round($this->getVar('wall')));
//NOTE: 전투로 인한 사망자는 여기서 처리하지 않음 //NOTE: 전투로 인한 사망자는 여기서 처리하지 않음
$decWealth = $this->getKilled() / 20; $decWealth = $this->getKilled() / 20;
$this->increaseVarWithLimit('agri', -$decWealth, 0); $this->increaseVarWithLimit('agri', -$decWealth, 0);
$this->increaseVarWithLimit('comm', -$decWealth, 0); $this->increaseVarWithLimit('comm', -$decWealth, 0);
$this->increaseVarWithLimit('secu', -$decWealth, 0); $this->increaseVarWithLimit('secu', -$decWealth, 0);
} }
function addConflict():bool{ function addConflict():bool{
$conflict = Json::decode($this->getVar('conflict')); $conflict = Json::decode($this->getVar('conflict'));
$oppose = $this->getOppose(); $oppose = $this->getOppose();
$nationID = $oppose->getNationVar('nation'); $nationID = $oppose->getNationVar('nation');
$newConflict = false; $newConflict = false;
$dead = max(1, $this->dead); $dead = max(1, $this->dead);
if(!$conflict || $this->getHP() == 0){ // 선타, 막타 보너스 if(!$conflict || $this->getHP() == 0){ // 선타, 막타 보너스
$dead *= 1.05; $dead *= 1.05;
} }
if(!$conflict){ if(!$conflict){
$conflict = [$nationID => $dead]; $conflict = [$nationID => $dead];
} }
else if(key_exists($nationID, $conflict)){ else if(key_exists($nationID, $conflict)){
$conflict[$nationID] += $dead; $conflict[$nationID] += $dead;
arsort($conflict); arsort($conflict);
} }
else{ else{
$conflict[$nationID] = $dead; $conflict[$nationID] = $dead;
arsort($conflict); arsort($conflict);
$newConflict = true; $newConflict = true;
} }
$this->updateVar('conflict', Json::encode($conflict)); $this->updateVar('conflict', Json::encode($conflict));
return $newConflict; return $newConflict;
} }
function applyDB(\MeekroDB $db):bool{ function applyDB(\MeekroDB $db):bool{
$updateVals = $this->getUpdatedValues(); $updateVals = $this->getUpdatedValues();
$this->getLogger()->rollback(); //수비 도시의 로그는 기록하지 않음 $this->getLogger()->rollback(); //수비 도시의 로그는 기록하지 않음
if(!$updateVals){ if(!$updateVals){
return false; return false;
} }
$db->update('city', $updateVals, 'city=%i', $this->raw['city']); $db->update('city', $updateVals, 'city=%i', $this->raw['city']);
$this->flushUpdateValues(); $this->flushUpdateValues();
return $db->affectedRows() > 0; return $db->affectedRows() > 0;
} }
} }
+8 -4
View File
@@ -62,7 +62,7 @@ class WarUnitGeneral extends WarUnit{
function getMaxPhase():int{ function getMaxPhase():int{
$phase = $this->getCrewType()->speed; $phase = $this->getCrewType()->speed;
$phase = $this->general->onCalcStat($this->general, 'initWarPhase', $phase); $phase = $this->general->onCalcStat($this->general, 'initWarPhase', $phase, ['isAttacker'=>$this->isAttacker]);
return $phase + $this->bonusPhase; return $phase + $this->bonusPhase;
} }
@@ -75,12 +75,16 @@ class WarUnitGeneral extends WarUnit{
} }
function getDex(GameUnitDetail $crewType){ function getDex(GameUnitDetail $crewType){
return $this->general->getDex($crewType); $rawDex = $this->general->getDex($crewType);
return $this->general->onCalcStat($this->general, 'dex'.$crewType->armType, $rawDex, [
'isAttacker'=>$this->isAttacker,
'opposeType'=>$this->oppose->getCrewType()
]);
} }
function getComputedTrain(){ function getComputedTrain(){
$train = $this->general->getVar('train'); $train = $this->general->getVar('train');
$train = $this->general->onCalcStat($this->general, 'bonusTrain', $train); $train = $this->general->onCalcStat($this->general, 'bonusTrain', $train, ['isAttacker'=>$this->isAttacker]);
$train += $this->trainBonus; $train += $this->trainBonus;
return $train; return $train;
@@ -88,7 +92,7 @@ class WarUnitGeneral extends WarUnit{
function getComputedAtmos(){ function getComputedAtmos(){
$atmos = $this->general->getVar('atmos'); $atmos = $this->general->getVar('atmos');
$atmos = $this->general->onCalcStat($this->general, 'bonusAtmos', $atmos); $atmos = $this->general->onCalcStat($this->general, 'bonusAtmos', $atmos, ['isAttacker'=>$this->isAttacker]);
$atmos += $this->atmosBonus; $atmos += $this->atmosBonus;
return $atmos; return $atmos;
+37 -40
View File
@@ -1,41 +1,38 @@
<?php <?php
namespace sammo\WarUnitTrigger; namespace sammo\WarUnitTrigger;
use sammo\BaseWarUnitTrigger; use sammo\BaseWarUnitTrigger;
use sammo\WarUnitGeneral; use sammo\WarUnitGeneral;
use sammo\WarUnitCity; use sammo\WarUnitCity;
use sammo\WarUnit; use sammo\WarUnit;
use sammo\GameUnitDetail; use sammo\GameUnitDetail;
use sammo\ObjectTrigger; use sammo\ObjectTrigger;
use sammo\Util; use sammo\Util;
class che_격노시도 extends BaseWarUnitTrigger{ class che_격노시도 extends BaseWarUnitTrigger{
protected $priority = ObjectTrigger::PRIORITY_POST + 300; protected $priority = ObjectTrigger::PRIORITY_POST + 300;
protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool{ protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool{
if(!$oppose->hasActivatedSkill('필살') && !$oppose->hasActivatedSkill('회피')){ if(!$oppose->hasActivatedSkill('필살') && !$oppose->hasActivatedSkill('회피')){
return true; return true;
} }
if($self->hasActivatedSkill('격노불가')){ if($self->hasActivatedSkill('격노불가')){
return true; return true;
} }
if($self->isAttacker()){ if($oppose->hasActivatedSkill('필살')){
if(Util::randBool(1/3)){ $self->activateSkill('격노');
$self->activateSkill('진노', '격노'); $oppose->deactivateSkill('회피');
$oppose->deactivateSkill('회피'); if($self->isAttacker() && Util::randBool(1/3)){
} $self->activateSkill('진노');
else if(Util::randBool(1/4)){ }
$self->activateSkill('격노'); }
$oppose->deactivateSkill('회피'); else if(Util::randBool(1/4)){
} $self->activateSkill('격노');
} $oppose->deactivateSkill('회피');
else{ if($self->isAttacker() && Util::randBool(1/3)){
if(Util::randBool(1/2)){ $self->activateSkill('진노');
$self->activateSkill('격노'); }
$oppose->deactivateSkill('회피'); }
} return true;
} }
return true;
}
} }
@@ -0,0 +1,33 @@
<?php
namespace sammo\WarUnitTrigger;
use sammo\BaseWarUnitTrigger;
use sammo\WarUnitGeneral;
use sammo\WarUnitCity;
use sammo\WarUnit;
use sammo\GameUnitDetail;
use sammo\Util;
use sammo\ObjectTrigger;
use sammo\ActionLogger;
class che_돌격지속 extends BaseWarUnitTrigger{
protected $priority = ObjectTrigger::PRIORITY_POST + 900;
protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool{
/** @var WarUnitGeneral $self */
if($oppose instanceof WarUnitCity){
return true;
}
if(!$self->isAttacker()){
return true;
}
if($self->getPhase() < $self->getMaxPhase() - 1){
return true;
}
$attackCoef = $self->getCrewType()->getAttackCoef($oppose->getCrewType());
if($attackCoef < 1){
return true;
}
$self->addBonusPhase(1);
return true;
}
}
+26 -25
View File
@@ -1,26 +1,27 @@
<?php <?php
namespace sammo\WarUnitTrigger; namespace sammo\WarUnitTrigger;
use sammo\BaseWarUnitTrigger; use sammo\BaseWarUnitTrigger;
use sammo\WarUnitGeneral; use sammo\WarUnitGeneral;
use sammo\WarUnitCity; use sammo\WarUnitCity;
use sammo\WarUnit; use sammo\WarUnit;
use sammo\GameUnitDetail; use sammo\GameUnitDetail;
use sammo\Util; use sammo\Util;
use sammo\ObjectTrigger; use sammo\ObjectTrigger;
use sammo\ActionLogger; use sammo\ActionLogger;
class che_위압발동 extends BaseWarUnitTrigger{ class che_위압발동 extends BaseWarUnitTrigger{
protected $priority = ObjectTrigger::PRIORITY_POST + 700; protected $priority = ObjectTrigger::PRIORITY_POST + 700;
protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool{ protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool{
if(!$self->hasActivatedSkill('위압')){ if(!$self->hasActivatedSkill('위압')){
return true; return true;
} }
$oppose->getLogger()->pushGeneralBattleDetailLog('상대에게 <R>위압</>받았다!</>', ActionLogger::PLAIN); $oppose->getLogger()->pushGeneralBattleDetailLog('상대에게 <R>위압</>받았다!</>', ActionLogger::PLAIN);
$self->getLogger()->pushGeneralBattleDetailLog('상대에게 <C>위압</>을 줬다!</>', ActionLogger::PLAIN); $self->getLogger()->pushGeneralBattleDetailLog('상대에게 <C>위압</>을 줬다!</>', ActionLogger::PLAIN);
$oppose->setWarPowerMultiply(0); $oppose->setWarPowerMultiply(0);
$oppose->increaseVarWithLimit('atmos', -5, 40);
return true;
} return true;
}
} }
+29 -37
View File
@@ -1,38 +1,30 @@
<?php <?php
namespace sammo\WarUnitTrigger; namespace sammo\WarUnitTrigger;
use sammo\BaseWarUnitTrigger; use sammo\BaseWarUnitTrigger;
use sammo\WarUnitGeneral; use sammo\WarUnitGeneral;
use sammo\WarUnitCity; use sammo\WarUnitCity;
use sammo\WarUnit; use sammo\WarUnit;
use sammo\GameUnitDetail; use sammo\GameUnitDetail;
use sammo\ObjectTrigger; use sammo\ObjectTrigger;
class che_위압시도 extends BaseWarUnitTrigger{ class che_위압시도 extends BaseWarUnitTrigger{
protected $priority = ObjectTrigger::PRIORITY_BEGIN + 100; protected $priority = ObjectTrigger::PRIORITY_BEGIN + 100;
protected $woundMin; protected $woundMin;
protected $woundMax; protected $woundMax;
protected $ratio; protected $ratio;
protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool{ protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool{
assert($self instanceof WarUnitGeneral, 'General만 발동 가능'); assert($self instanceof WarUnitGeneral, 'General만 발동 가능');
if($self->getPhase() != 0){ if($self->getPhase() !== 0 && $oppose->getPhase() !== 0){
return true; return true;
} }
if($self->getHP() < 1000){ if($self->hasActivatedSkill('위압불가')){
return true; return true;
} }
if($self->getComputedAtmos() < 90){
return true; $self->activateSkill('위압');
} $oppose->activateSkill('회피불가', '필살불가', '계략불가');
if($self->getComputedTrain() < 90){ return true;
return true; }
}
if($self->hasActivatedSkill('위압불가')){
return true;
}
$self->activateSkill('위압');
return true;
}
} }
@@ -1,34 +1,35 @@
<?php <?php
namespace sammo\WarUnitTrigger; namespace sammo\WarUnitTrigger;
use sammo\BaseWarUnitTrigger; use sammo\BaseWarUnitTrigger;
use sammo\WarUnitGeneral; use sammo\WarUnitGeneral;
use sammo\WarUnitCity; use sammo\WarUnitCity;
use sammo\WarUnit; use sammo\WarUnit;
use sammo\GameUnitDetail; use sammo\GameUnitDetail;
use sammo\Util; use sammo\Util;
use sammo\ObjectTrigger; use sammo\ObjectTrigger;
use sammo\ActionLogger; use sammo\ActionLogger;
class che_전투치료발동 extends BaseWarUnitTrigger{ class che_전투치료발동 extends BaseWarUnitTrigger{
protected $priority = ObjectTrigger::PRIORITY_POST + 300; protected $priority = ObjectTrigger::PRIORITY_POST + 300;
protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool{ protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool{
if(!$self->hasActivatedSkill('치료')){ if(!$self->hasActivatedSkill('치료')){
return true; return true;
} }
if($selfEnv['치료발동']??false){ if($selfEnv['치료발동']??false){
return true; return true;
} }
$selfEnv['치료발동'] = true; $selfEnv['치료발동'] = true;
$oppose->getLogger()->pushGeneralBattleDetailLog("상대가 <C>치료</>했다!", ActionLogger::PLAIN); $oppose->getLogger()->pushGeneralBattleDetailLog("상대가 <C>치료</>했다!", ActionLogger::PLAIN);
$self->getLogger()->pushGeneralBattleDetailLog("<C>치료</>했다!", ActionLogger::PLAIN); $self->getLogger()->pushGeneralBattleDetailLog("<C>치료</>했다!", ActionLogger::PLAIN);
$oppose->multiplyWarPowerMultiply(1/1.5); $oppose->multiplyWarPowerMultiply(0.5);
$self->getGeneral()->setVar('injury', 0);
$this->processConsumableItem();
$this->processConsumableItem();
return true;
} return true;
}
} }
@@ -1,31 +1,31 @@
<?php <?php
namespace sammo\WarUnitTrigger; namespace sammo\WarUnitTrigger;
use sammo\BaseWarUnitTrigger; use sammo\BaseWarUnitTrigger;
use sammo\WarUnitGeneral; use sammo\WarUnitGeneral;
use sammo\WarUnitCity; use sammo\WarUnitCity;
use sammo\WarUnit; use sammo\WarUnit;
use sammo\GameUnitDetail; use sammo\GameUnitDetail;
use sammo\Util; use sammo\Util;
use sammo\ObjectTrigger; use sammo\ObjectTrigger;
class che_전투치료시도 extends BaseWarUnitTrigger{ class che_전투치료시도 extends BaseWarUnitTrigger{
protected $priority = ObjectTrigger::PRIORITY_PRE + 300; protected $priority = ObjectTrigger::PRIORITY_PRE + 300;
protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool{ protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool{
assert($self instanceof WarUnitGeneral, 'General만 발동 가능'); assert($self instanceof WarUnitGeneral, 'General만 발동 가능');
if($self->hasActivatedSkill('치료')){ if($self->hasActivatedSkill('치료')){
return true; return true;
} }
if($self->hasActivatedSkill('치료불가')){ if($self->hasActivatedSkill('치료불가')){
return true; return true;
} }
if(!Util::randBool(1/5)){ if(!Util::randBool(0.4)){
return true; return true;
} }
$self->activateSkill('치료'); $self->activateSkill('치료');
return true; return true;
} }
} }