Compare commits

..
3 Commits
Author SHA1 Message Date
Hide_D 3762d9050c fix: GetCityInfo에서 출력됨 2023-03-26 02:55:42 +09:00
Hide_D 75d88d48b6 feat,wip: GetCityInfo 2023-03-26 02:43:33 +09:00
Hide_D 633defcb21 feat: wip, 도시정보 2023-03-26 01:04:09 +09:00
34 changed files with 1087 additions and 875 deletions
-37
View File
@@ -326,41 +326,6 @@ function buildGeneralSpecialWarClass(?string $type):BaseSpecial{
return $obj; return $obj;
} }
function getActionCrewTypeClass(?string $type){
if($type === null || $type === ''){
$type = 'None';
}
static $basePath = __NAMESPACE__.'\\ActionCrewType\\';
$classPath = ($basePath.$type);
if(class_exists($classPath)){
return $classPath;
}
$classPath = ($basePath.'che_'.$type);
if(class_exists($classPath)){
return $classPath;
}
throw new \InvalidArgumentException("{$type}은 올바른 병종 효과가 아님");
}
function buildActionCrewTypeClass(?string $type):iAction{
static $cache = [];
if($type === null){
$type = 'None';
}
if(key_exists($type, $cache)){
return $cache[$type];
}
$class = getActionCrewTypeClass($type);
$obj = new $class();
$cache[$type]= $obj;
return $obj;
}
function getGeneralCommandClass(?string $type){ function getGeneralCommandClass(?string $type){
if($type === null || $type === ''){ if($type === null || $type === ''){
$type = '휴식'; $type = '휴식';
@@ -577,8 +542,6 @@ function getExpLevel($experience) {
$level = Util::toInt(sqrt($experience/10)); $level = Util::toInt(sqrt($experience/10));
} }
$level = Util::clamp($level, 0, GameConst::$maxLevel);
return $level; return $level;
} }
+223 -280
View File
@@ -1,5 +1,4 @@
<?php <?php
namespace sammo; namespace sammo;
use Ds\Map; use Ds\Map;
@@ -16,48 +15,48 @@ $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'
], ],
@@ -65,10 +64,10 @@ $defaultCheck = [
$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()
]); ]);
} }
@@ -87,110 +86,20 @@ $rawDefenderNation = $query['defenderNation'];
$warSeed = $query['seed'] ?? ''; $warSeed = $query['seed'] ?? '';
$cityCheck = [
'required' => [
'city', 'nation', 'supply', 'name',
'pop', 'agri', 'comm', 'secu', 'def', 'wall',
'trust', 'level',
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
'dead', 'state', 'conflict',
],
'numeric' => [
'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead'
],
'integer' => [
'city', 'nation', 'supply',
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
'state',
],
'min' => [
['def', 0],
['wall', 0],
['trust', 0],
['pop', 0],
['comm', 0],
['secu', 0],
['city', 1],
['nation', 0]
],
'in' => [
['level', array_keys(getCityLevelList())]
]
];
$v = new Validator($rawAttackerCity);
$v->rules($cityCheck);
if (!$v->validate()) {
Json::die([
'result' => false,
'reason' => '[출병도시]' . $v->errorStr()
]);
}
$v = new Validator($rawDefenderCity);
$v->rules($cityCheck);
if (!$v->validate()) {
Json::die([
'result' => false,
'reason' => '[수비도시]' . $v->errorStr()
]);
}
$nationCheck = [
'required' => [
'type', 'tech', 'level', 'capital',
'nation', 'name', 'gold', 'rice', 'gennum'
],
'integer' => [
'level', 'capital', 'nation', 'gennum',
],
'numeric' => [
'tech', 'gold', 'rice'
],
'min' => [
['tech', 0],
['gold', 0],
['rice', 0],
['gennum', 1],
],
'in' => [
['type', GameConst::$availableNationType],
['level', array_keys(getNationLevelList())]
]
];
$v = new Validator($rawAttackerNation);
$v->rules($nationCheck);
if (!$v->validate()) {
Json::die([
'result' => false,
'reason' => '[출병국]' . $v->errorStr()
]);
}
$v = new Validator($rawDefenderNation);
$v->rules($nationCheck);
if (!$v->validate()) {
Json::die([
'result' => false,
'reason' => '[수비국]' . $v->errorStr()
]);
}
$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', 'warnum', 'killnum', 'killcrew', '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', 'warnum', 'killnum', 'killcrew',
], ],
'min' => [ 'min'=>[
['no', 1], ['no', 1],
['nation', 1], ['nation', 1],
['crew', 0], ['crew', 0],
@@ -209,14 +118,14 @@ $generalCheck = [
['killnum', 0], ['killnum', 0],
['killcrew', 0], ['killcrew', 0],
], ],
'between' => [ 'between'=>[
['train', [40, GameConst::$maxTrainByWar]], ['train', [40, GameConst::$maxTrainByWar]],
['atmos', [40, GameConst::$maxAtmosByWar]], ['atmos', [40, GameConst::$maxAtmosByWar]],
['explevel', [0, 300]], ['explevel', [0, 300]],
['injury', [0, 80]], ['injury', [0, 80]],
['officer_level', [1, 12]] ['officer_level', [1, 12]]
], ],
'in' => [ 'in'=>[
['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)], ['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)],
['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)], ['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)],
['crewtype', array_keys(GameUnitConst::all())], ['crewtype', array_keys(GameUnitConst::all())],
@@ -225,11 +134,11 @@ $generalCheck = [
['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])], ['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])],
['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])], ['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])],
], ],
'array' => ['inheritBuff'], 'array'=>['inheritBuff'],
]; ];
$inheritBuffCheck = [ $inheritBuffCheck = [
'between' => [ 'between'=>[
[TriggerInheritBuff::WAR_AVOID_RATIO, [0, 5]], [TriggerInheritBuff::WAR_AVOID_RATIO, [0, 5]],
[TriggerInheritBuff::WAR_CRITICAL_RATIO, [0, 5]], [TriggerInheritBuff::WAR_CRITICAL_RATIO, [0, 5]],
[TriggerInheritBuff::WAR_MAGIC_TRIAL_PROB, [0, 5]], [TriggerInheritBuff::WAR_MAGIC_TRIAL_PROB, [0, 5]],
@@ -240,67 +149,49 @@ $inheritBuffCheck = [
] ]
]; ];
if(!$warSeed){
$warSeed = bin2hex(random_bytes(16));
}
else {
$repeatCnt = 1;
}
$tmpRNG = new RandUtil(new LiteHashDRBG($warSeed));
$v = new Validator($rawAttacker); $v = new Validator($rawAttacker);
$v->rules($generalCheck); $v->rules($generalCheck);
if (!$v->validate()) { if(!$v->validate()){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => '[출병자]' . $v->errorStr() 'reason'=>'[출병자]'.$v->errorStr()
]); ]);
} }
$rawAttacker['aux'] = []; $rawAttacker['aux'] = [];
if (key_exists('inheritBuff', $rawAttacker)) { if(key_exists('inheritBuff', $rawAttacker)){
$v = new Validator($rawAttacker['inheritBuff']); $v = new Validator($rawAttacker['inheritBuff']);
$v->rules($inheritBuffCheck); $v->rules($inheritBuffCheck);
if (!$v->validate()) { if(!$v->validate()){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => '[출병자]' . $v->errorStr() 'reason'=>'[출병자]'.$v->errorStr()
]); ]);
} }
$rawAttacker['aux']['inheritBuff'] = $rawAttacker['inheritBuff']; $rawAttacker['aux']['inheritBuff'] = $rawAttacker['inheritBuff'];
} }
$rawAttacker['aux'] = Json::encode($rawAttacker['aux']); $rawAttacker['aux'] = Json::encode($rawAttacker['aux']);
$rawAttacker['owner'] = 0; $rawAttacker['owner'] = 0;
$attackerGeneral = new General($rawAttacker, extractRankVar($rawAttacker), $rawAttackerCity, $rawAttackerNation, $year, $month);
$attacker = new WarUnitGeneral(
$tmpRNG,
$attackerGeneral,
$rawAttackerNation,
true
);
/** @var WarUnit[] */
$defenderList = []; $defenderList = [];
foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
foreach ($rawDefenderList as $idx => $rawDefenderGeneral) {
$v = new Validator($rawDefenderGeneral); $v = new Validator($rawDefenderGeneral);
$v->rules($generalCheck); $v->rules($generalCheck);
if (!$v->validate()) { if(!$v->validate()){
$idx += 1; $idx+=1;
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => "[수비자{$idx}]" . $v->errorStr() 'reason'=>"[수비자{$idx}]".$v->errorStr()
]); ]);
} }
$rawDefenderGeneral['aux'] = []; $rawDefenderGeneral['aux'] = [];
if (key_exists('inheritBuff', $rawDefenderGeneral)) { if(key_exists('inheritBuff', $rawDefenderGeneral)){
$v = new Validator($rawDefenderGeneral['inheritBuff']); $v = new Validator($rawDefenderGeneral['inheritBuff']);
$v->rules($inheritBuffCheck); $v->rules($inheritBuffCheck);
if (!$v->validate()) { if(!$v->validate()){
$idx += 1; $idx+=1;
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => "[수비자{$idx}]" . $v->errorStr() 'reason'=>"[수비자{$idx}]".$v->errorStr()
]); ]);
} }
$rawDefenderGeneral['aux']['inheritBuff'] = $rawDefenderGeneral['inheritBuff']; $rawDefenderGeneral['aux']['inheritBuff'] = $rawDefenderGeneral['inheritBuff'];
@@ -308,54 +199,135 @@ foreach ($rawDefenderList as $idx => $rawDefenderGeneral) {
$rawDefenderGeneral['aux'] = Json::encode($rawDefenderGeneral['aux']); $rawDefenderGeneral['aux'] = Json::encode($rawDefenderGeneral['aux']);
$rawDefenderGeneral['owner'] = 0; $rawDefenderGeneral['owner'] = 0;
$defenderGeneral = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), $rawDefenderCity, $rawAttackerNation, $year, $month, true); $defenderList[] = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), $rawDefenderCity, $rawAttackerNation, $year, $month, true);
$defenderList[] = new WarUnitGeneral(
$tmpRNG,
$defenderGeneral,
$rawDefenderNation,
false
);
} }
if ($action == 'reorder') {
$noRng = NoRNG::rngInstance();
usort($defenderList, function (WarUnit $lhs, WarUnit $rhs) use ($attacker) { $cityCheck = [
return - (extractBattleOrder($lhs, $attacker) <=> extractBattleOrder($rhs, $attacker)); 'required'=>[
}); 'city', 'nation', 'supply', 'name',
'pop', 'agri', 'comm', 'secu', 'def', 'wall',
$order = []; 'trust', 'level',
foreach ($defenderList as $defender) { 'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
$order[] = $defender->getGeneral()->getID(); 'dead', 'state', 'conflict',
} ],
'numeric'=>[
'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead'
],
'integer'=>[
'city', 'nation', 'supply',
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
'state',
],
'min'=>[
['def', 0],
['wall', 0],
['trust', 0],
['pop', 0],
['comm', 0],
['secu', 0],
['city', 1],
['nation', 0]
],
'in'=>[
['level', array_keys(getCityLevelList())]
]
];
$v = new Validator($rawAttackerCity);
$v->rules($cityCheck);
if(!$v->validate()){
Json::die([ Json::die([
'result' => true, 'result'=>false,
'reason' => 'success', 'reason'=>'[출병도시]'.$v->errorStr()
'order' => $order
]); ]);
} }
$rawDefenderList = []; $v = new Validator($rawDefenderCity);
foreach($defenderList as $unit){ $v->rules($cityCheck);
if(extractBattleOrder($unit, $attacker) <= 0){ if(!$v->validate()){
continue; Json::die([
} 'result'=>false,
$rawDefenderList[] = $unit->getRaw(); 'reason'=>'[수비도시]'.$v->errorStr()
]);
} }
$nationCheck = [
'required'=>[
'type', 'tech', 'level', 'capital',
'nation', 'name', 'gold', 'rice', 'gennum'
],
'integer'=>[
'level', 'capital', 'nation', 'gennum',
],
'numeric'=>[
'tech', 'gold', 'rice'
],
'min'=>[
['tech', 0],
['gold', 0],
['rice', 0],
['gennum', 1],
],
'in'=>[
['type', GameConst::$availableNationType],
['level', array_keys(getNationLevelList())]
]
];
$v = new Validator($rawAttackerNation);
$v->rules($nationCheck);
if(!$v->validate()){
Json::die([
'result'=>false,
'reason'=>'[출병국]'.$v->errorStr()
]);
}
$v = new Validator($rawDefenderNation);
$v->rules($nationCheck);
if(!$v->validate()){
Json::die([
'result'=>false,
'reason'=>'[수비국]'.$v->errorStr()
]);
}
if($action == 'reorder'){
usort($defenderList, function(General $lhs, General $rhs){
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
});
$order = [];
foreach($defenderList as $defenderGeneral){
$order[] = $defenderGeneral->getID();
}
Json::die([
'result'=>true,
'reason'=>'success',
'order'=>$order
]);
}
usort($defenderList, function(General $lhs, General $rhs){
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
});
$rawDefenderList = array_map(function(General $general){
return $general->getRaw();
}, $defenderList);
unset($defenderList); unset($defenderList);
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$startYear = $gameStor->startyear; $startYear = $gameStor->startyear;
function extractRankVar(array $rawVal): Map function extractRankVar(array $rawVal):Map{
{
$rankVars = new Map; $rankVars = new Map;
foreach ($rawVal as $rawKey => $rawVal) { foreach($rawVal as $rawKey=>$rawVal){
$key = RankColumn::tryFrom($rawKey); $key = RankColumn::tryFrom($rawKey);
if ($key === null) { if($key === null){
continue; continue;
} }
$rankVars[$key] = $rawVal; $rankVars[$key] = $rawVal;
@@ -364,104 +336,80 @@ function extractRankVar(array $rawVal): Map
} }
function simulateBattle( function simulateBattle(
$rawAttacker, $rawAttacker, $rawAttackerCity, $rawAttackerNation,
$rawAttackerCity, $rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$rawAttackerNation, $startYear, $year, $month, $warSeed
$rawDefenderList, ){
$rawDefenderCity,
$rawDefenderNation,
$startYear,
$year,
$month,
$warSeed
) {
if (!$warSeed) { if(!$warSeed){
$warSeed = bin2hex(random_bytes(16)); $warSeed = bin2hex(random_bytes(16));
} }
$warRng = new RandUtil(new LiteHashDRBG($warSeed)); $warRng = new RandUtil(new LiteHashDRBG($warSeed));
$attackerGeneral = new General($rawAttacker, extractRankVar($rawAttacker), $rawAttackerCity, $rawAttackerNation, $year, $month);
$attacker = new WarUnitGeneral( $attacker = new WarUnitGeneral(
$warRng, $warRng,
$attackerGeneral, new General($rawAttacker, extractRankVar($rawAttacker), $rawAttackerCity, $rawAttackerNation, $year, $month),
$rawAttackerNation, $rawAttackerNation,
true true
); );
$city = new WarUnitCity($warRng, $rawDefenderCity, $rawDefenderNation, $year, $month, $startYear); $city = new WarUnitCity($warRng, $rawDefenderCity, $rawDefenderNation, $year, $month, $startYear);
/** @var WarUnit[] */ $iterDefender = new \ArrayIterator($rawDefenderList);
$defenderList = [];
foreach ($rawDefenderList as $rawDefenderGeneral) {
$defenderGeneral = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), $rawDefenderCity, $rawAttackerNation, $year, $month, true);
$defenderList[] = new WarUnitGeneral(
$warRng,
$defenderGeneral,
$rawDefenderNation,
false
);
}
if(count($defenderList) && extractBattleOrder($city, $attacker) > 0){
$defenderList[] = $city;
}
usort($defenderList, function (WarUnit $lhs, WarUnit $rhs) use ($attacker) {
return - (extractBattleOrder($lhs, $attacker) <=> extractBattleOrder($rhs, $attacker));
});
$iterDefender = new \ArrayIterator($defenderList);
$iterDefender->rewind(); $iterDefender->rewind();
$battleResult = []; $battleResult = [];
$attackerRice = $attacker->getGeneral()->getVar('rice'); $attackerRice = $rawAttacker['rice'];
$defenderRice = 0; $defenderRice = 0;
$getNextDefender = function (?WarUnit $prevDefender, bool $reqNext) $getNextDefender = function(?WarUnit $prevDefender, bool $reqNext)
use ($iterDefender, &$battleResult, &$defenderRice, $attacker): ?WarUnit { use ($warRng, $iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) {
if ($prevDefender !== null) { if($prevDefender !== null){
$prevDefender->getLogger()->rollback(); $prevDefender->getLogger()->rollback();
$battleResult[] = $prevDefender; $battleResult[] = $prevDefender;
if ($prevDefender instanceof WarUnitGeneral) { if($prevDefender instanceof WarUnitGeneral){
$defenderRice -= $prevDefender->getVar('rice'); $defenderRice -= $prevDefender->getVar('rice');
} }
} }
if (!$reqNext) { if(!$reqNext){
return null; return null;
} }
if (!$iterDefender->valid()) { if(!$iterDefender->valid()){
return null; return null;
} }
/** @var WarUnit */ $defenderObj = new General($iterDefender->current(), extractRankVar($iterDefender->current()), $rawDefenderCity, $rawDefenderNation, $year, $month);
$defender = $iterDefender->current(); if(extractBattleOrder($defenderObj) <= 0){
if (extractBattleOrder($defender, $attacker) <= 0) {
return null; return null;
} }
if($defender instanceof WarUnitGeneral){ $defenderRice += $defenderObj->getVar('rice');
$defenderRice += $defender->getVar('rice');
}
$retVal = new WarUnitGeneral(
$warRng,
$defenderObj,
$rawDefenderNation,
false
);
$iterDefender->next(); $iterDefender->next();
return $defender; return $retVal;
}; };
$conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city); $conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city, $year - $startYear);
$rawDefenderCity = $city->getRaw();
$updateAttackerNation = [];
$updateDefenderNation = [];
$attackerRice -= $attacker->getVar('rice'); $attackerRice -= $attacker->getVar('rice');
if ($city->getPhase() > 0) { if($city->getPhase() > 0){
$rice = $city->getKilled() / 100 * 0.8; $rice = $city->getKilled() / 100 * 0.8;
$rice *= $city->getCrewType()->rice; $rice *= $city->getCrewType()->rice;
$rice *= getTechCost($city->getRawNation()['tech']); $rice *= getTechCost($rawDefenderNation['tech']);
$rice *= $city->getCityTrainAtmos() / 100 - 0.2; $rice *= $city->getCityTrainAtmos() / 100 - 0.2;
Util::setRound($rice); Util::setRound($rice);
@@ -469,8 +417,8 @@ function simulateBattle(
} }
$totalDead = $attacker->getKilled() + $attacker->getDead(); $totalDead = $attacker->getKilled() + $attacker->getDead();
//$attackerCityDead = $totalDead * 0.4; $attackerCityDead = $totalDead * 0.4;
//$defenderCityDead = $totalDead * 0.6; $defenderCityDead = $totalDead * 0.6;
return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice]; return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice];
} }
@@ -496,26 +444,18 @@ $avgWar = 0;
$attackerActivatedSkills = []; $attackerActivatedSkills = [];
$defendersActivatedSkills = []; $defendersActivatedSkills = [];
if($warSeed){
$repeatCnt = 1;
}
foreach (Util::range($repeatCnt) as $repeatIdx) { foreach(Util::range($repeatCnt) as $repeatIdx){
if($repeatIdx > 0){
$warSeed = bin2hex(random_bytes(16));
}
/** @var WarUnit $attacker */ /** @var WarUnit $attacker */
[$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle( [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle(
$rawAttacker, $rawAttacker, $rawAttackerCity, $rawAttackerNation,
$rawAttackerCity, $rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$rawAttackerNation, $startYear, $year, $month, $warSeed
$rawDefenderList,
$rawDefenderCity,
$rawDefenderNation,
$startYear,
$year,
$month,
$warSeed
); );
$lastWarLog = Util::mapWithKey(function ($key, $values) { $lastWarLog = Util::mapWithKey(function($key, $values){
return ConvertLog(join('<br>', $values)); return ConvertLog(join('<br>', $values));
}, $attacker->getLogger()->rollback()); }, $attacker->getLogger()->rollback());
@@ -538,45 +478,48 @@ foreach (Util::range($repeatCnt) as $repeatIdx) {
$avgWar += count($battleResult) / $repeatCnt; $avgWar += count($battleResult) / $repeatCnt;
foreach ($attacker->getActivatedSkillLog() as $skillName => $skillCnt) { foreach($attacker->getActivatedSkillLog() as $skillName => $skillCnt){
if (!key_exists($skillName, $attackerActivatedSkills)) { if(!key_exists($skillName, $attackerActivatedSkills)){
$attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt; $attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt;
} else { }
else{
$attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt; $attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt;
} }
} }
foreach ($battleResult as $idx => $defender) { foreach($battleResult as $idx=>$defender){
while ($idx >= count($defendersActivatedSkills)) { while($idx >= count($defendersActivatedSkills)){
$defendersActivatedSkills[] = []; $defendersActivatedSkills[] = [];
} }
$activatedSkills = &$defendersActivatedSkills[$idx]; $activatedSkills = &$defendersActivatedSkills[$idx];
foreach ($defender->getActivatedSkillLog() as $skillName => $skillCnt) { foreach($defender->getActivatedSkillLog() as $skillName => $skillCnt){
if (!key_exists($skillName, $activatedSkills)) { if(!key_exists($skillName, $activatedSkills)){
$activatedSkills[$skillName] = $skillCnt / $repeatCnt; $activatedSkills[$skillName] = $skillCnt / $repeatCnt;
} else { }
else{
$activatedSkills[$skillName] += $skillCnt / $repeatCnt; $activatedSkills[$skillName] += $skillCnt / $repeatCnt;
} }
} }
} }
} }
Json::die([ Json::die([
'result' => true, 'result'=>true,
'datetime' => $rawAttacker['turntime'], 'datetime'=>$rawAttacker['turntime'],
'reason' => 'success', 'reason'=>'success',
'lastWarLog' => $lastWarLog, 'lastWarLog'=>$lastWarLog,
'avgWar' => $avgWar, 'avgWar'=>$avgWar,
'phase' => $avgPhase, 'phase'=>$avgPhase,
'killed' => $attackerKilled, 'killed'=>$attackerKilled,
'maxKilled' => $attackerMaxKilled, 'maxKilled'=>$attackerMaxKilled,
'minKilled' => $attackerMinKilled, 'minKilled'=>$attackerMinKilled,
'dead' => $attackerDead, 'dead'=>$attackerDead,
'maxDead' => $attackerMaxDead, 'maxDead'=>$attackerMaxDead,
'minDead' => $attackerMinDead, 'minDead'=>$attackerMinDead,
'attackerRice' => $attackerAvgRice, 'attackerRice'=>$attackerAvgRice,
'defenderRice' => $defenderAvgRice, 'defenderRice'=>$defenderAvgRice,
'attackerSkills' => $attackerActivatedSkills, 'attackerSkills'=>$attackerActivatedSkills,
'defendersSkills' => $defendersActivatedSkills, 'defendersSkills'=>$defendersActivatedSkills,
]); ]);
+27 -57
View File
@@ -37,32 +37,16 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
$city = new WarUnitCity($rng, $rawDefenderCity, $rawDefenderNation, $year, $month, $startYear); $city = new WarUnitCity($rng, $rawDefenderCity, $rawDefenderNation, $year, $month, $startYear);
$defenderIDList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND city=%i AND nation!=0 and crew > 0 and rice>(crew/100) and train>=defence_train and atmos>=defence_train', $city->getVar('nation'), $city->getVar('city')); $defenderIDList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND city=%i AND nation!=0 and crew > 0 and rice>(crew/100) and train>=defence_train and atmos>=defence_train', $city->getVar('nation'), $city->getVar('city'));
$defenderGeneralList = General::createGeneralObjListFromDB($defenderIDList, null, 2); $defenderList = General::createGeneralObjListFromDB($defenderIDList, null, 2);
/** @var WarUnit[] */ usort($defenderList, function (General $lhs, General $rhs) {
$defenderList = []; return - (extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
foreach($defenderGeneralList as $defenderGeneral){
$defenderCandidate = new WarUnitGeneral($rng, $defenderGeneral, $rawDefenderNation, false);
if(extractBattleOrder($defenderCandidate, $attacker) <= 0){
continue;
}
$defenderList[] = $defenderCandidate;
}
if(count($defenderList) && extractBattleOrder($city, $attacker) > 0){
$defenderList[] = $city;
}
usort($defenderList, function (WarUnit $lhs, WarUnit $rhs) use ($attacker) {
return - (extractBattleOrder($lhs, $attacker) <=> extractBattleOrder($rhs, $attacker));
}); });
$iterDefender = new \ArrayIterator($defenderList); $iterDefender = new \ArrayIterator($defenderList);
$iterDefender->rewind(); $iterDefender->rewind();
$getNextDefender = function (?WarUnit $prevDefender, bool $reqNext) use ($iterDefender, $db, $attacker) { $getNextDefender = function (?WarUnit $prevDefender, bool $reqNext) use ($rng, $iterDefender, $rawDefenderNation, $rawDefenderCity, $db) {
if ($prevDefender !== null) { if ($prevDefender !== null) {
$prevDefender->applyDB($db); $prevDefender->applyDB($db);
} }
@@ -75,16 +59,24 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
return null; return null;
} }
/** @var WarUnit */
$nextDefender = $iterDefender->current(); $nextDefender = $iterDefender->current();
if (extractBattleOrder($nextDefender, $attacker) <= 0) { $nextDefender->setRawCity($rawDefenderCity);
if (extractBattleOrder($nextDefender) <= 0) {
return null; return null;
} }
$retVal = new WarUnitGeneral(
$rng,
$nextDefender,
$rawDefenderNation,
false
);
$iterDefender->next(); $iterDefender->next();
return $nextDefender; return $retVal;
}; };
$conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city); $conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city, $year - $startYear);
$attacker->applyDB($db); $attacker->applyDB($db);
@@ -188,17 +180,8 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
], $attacker->getGeneral(), $city->getRaw()); ], $attacker->getGeneral(), $city->getRaw());
} }
function extractBattleOrder(WarUnit $defender, WarUnit $attacker) function extractBattleOrder(General $general)
{ {
if($defender instanceof WarUnitCity){
if(!($attacker instanceof WarUnitGeneral)){
return 0;
}
$attackerGeneral = $attacker->getGeneral();
return $attackerGeneral->onCalcOpposeStat($defender->getGeneral(), 'cityBattleOrder', -1);
}
$general = $defender->getGeneral();
if ($general->getVar('crew') == 0) { if ($general->getVar('crew') == 0) {
return 0; return 0;
} }
@@ -229,6 +212,7 @@ function processWar_NG(
WarUnitGeneral $attacker, WarUnitGeneral $attacker,
callable $getNextDefender, callable $getNextDefender,
WarUnitCity $city, WarUnitCity $city,
int $relYear
): bool { ): bool {
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
@@ -241,7 +225,6 @@ function processWar_NG(
$attackerNationUpdate = []; $attackerNationUpdate = [];
$defenderNationUpdate = []; $defenderNationUpdate = [];
/** @var WarUnit */
$defender = ($getNextDefender)(null, true); $defender = ($getNextDefender)(null, true);
$conquerCity = false; $conquerCity = false;
@@ -257,7 +240,6 @@ function processWar_NG(
$logWritten = false; $logWritten = false;
if ($defender === null) { if ($defender === null) {
$defender = $city; $defender = $city;
$defender->setSiege();
if ($city->getNationVar('rice') <= 0 && $city->getVar('supply')) { if ($city->getNationVar('rice') <= 0 && $city->getVar('supply')) {
//병량 패퇴 //병량 패퇴
@@ -424,28 +406,21 @@ function processWar_NG(
$attacker->logBattleResult(); $attacker->logBattleResult();
$defender->logBattleResult(); $defender->logBattleResult();
if (!($defender instanceof WarUnitCity) || $defender->isSiege()){ $attacker->addWin();
$attacker->addWin(); $defender->addLose();
$defender->addLose();
$attacker->tryWound(); $attacker->tryWound();
$defender->tryWound(); $defender->tryWound();
if ($defender === $city) { if ($defender === $city) {
$attacker->addLevelExp(1000); $attacker->addLevelExp(1000);
$conquerCity = true; $conquerCity = true;
break; break;
}
} }
$josaYi = JosaUtil::pick($defender->getCrewTypeName(), '이'); $josaYi = JosaUtil::pick($defender->getCrewTypeName(), '이');
if ($defender instanceof WarUnitCity && !$defender->isSiege()){ if ($noRice) {
//실제 공성을 위해 다시 초기화
$defender->setOppose(null);
}
else if ($noRice) {
$logger->pushGlobalActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다."); $logger->pushGlobalActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다.");
$attacker->getLogger()->pushGeneralActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다.", ActionLogger::PLAIN); $attacker->getLogger()->pushGeneralActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다.", ActionLogger::PLAIN);
$defender->getLogger()->pushGeneralActionLog("군량 부족으로 패퇴합니다.", ActionLogger::PLAIN); $defender->getLogger()->pushGeneralActionLog("군량 부족으로 패퇴합니다.", ActionLogger::PLAIN);
@@ -480,11 +455,6 @@ function processWar_NG(
$attacker->finishBattle(); $attacker->finishBattle();
$defender->finishBattle(); $defender->finishBattle();
if($city->getDead()){
$city->setSiege();
$city->finishBattle();
}
if ($defender instanceof WarUnitCity) { if ($defender instanceof WarUnitCity) {
$newConflict = $defender->addConflict(); $newConflict = $defender->addConflict();
if ($newConflict) { if ($newConflict) {
+332
View File
@@ -0,0 +1,332 @@
<?php
namespace sammo\API\City;
use ArrayObject;
use Ds\Set;
use sammo\CityConst;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\General;
use sammo\Json;
use sammo\Session;
use sammo\Util;
use sammo\Validator;
use function sammo\calcLeadershipBonus;
use function sammo\checkLimit;
use function sammo\checkSecretPermission;
use function sammo\getAllNationStaticInfo;
use function sammo\getBillByLevel;
use function sammo\getDedLevelText;
use function sammo\getHonor;
use function sammo\getNationStaticInfo;
use function sammo\getOfficerLevelText;
use function sammo\increaseRefresh;
class GetCityInfo extends \sammo\BaseAPI
{
const FAR_CITY = 0;
const NEAR_CITY = 1;
const ON_CITY = 2;
const OUR_NATION = 3;
static $viewColumns = [
'no' => self::NEAR_CITY,
'name' => self::NEAR_CITY,
'nation' => self::NEAR_CITY,
'npc' => self::NEAR_CITY,
'injury' => self::NEAR_CITY,
'leadership' => self::NEAR_CITY,
'strength' => self::NEAR_CITY,
'intel' => self::NEAR_CITY,
'picture' => self::NEAR_CITY,
'imgsvr' => self::NEAR_CITY,
'city' => self::NEAR_CITY,
'officer_level' => self::NEAR_CITY,
'officer_city' => self::NEAR_CITY,
'defence_train' => self::OUR_NATION,
'crewtype' => self::OUR_NATION,
'crew' => self::ON_CITY,
'train' => self::OUR_NATION,
'atmos' => self::OUR_NATION,
];
static $columnRemap = [
'nation' => 'nationID',
];
static $customViewColumns = [
'officerLevel' => self::NEAR_CITY,
'officerLevelText' => self::NEAR_CITY,
'lbonus' => self::NEAR_CITY,
'reservedCommand' => self::OUR_NATION,
'isOurNation' => self::NEAR_CITY,
];
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('int', 'troopID');
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
private function getOfficerLevel($rawGeneral)
{
$level = $rawGeneral['officer_level'];
return $level;
}
private function filterCity(array $rawCity, int $showLevel)
{
$cityID = $rawCity['city'];
$db = DB::db();
$officerList = $db->query(
'SELECT no, npc, name, nation, picture, imgsvr FROM general WHERE city = %i AND 2 <= officer_level AND officer_level <= 4',
$cityID
);
$filteredCity = [
'city' => $cityID,
'name' => $rawCity['name'],
'level' => $rawCity['level'],
'nation' => $rawCity['nation'],
'supply' => $rawCity['supply'],
'pop_max' => $rawCity['pop_max'],
'agri_max' => $rawCity['agri_max'],
'comm_max' => $rawCity['comm_max'],
'secu_max' => $rawCity['secu_max'],
'trade' => $rawCity['trade'],
'def_max' => $rawCity['def_max'],
'wall_max' => $rawCity['wall_max'],
'region' => $rawCity['region'],
'officerList' => $officerList,
];
if ($showLevel >= self::ON_CITY) {
$filteredCity = array_merge($filteredCity, [
'pop' => $rawCity['pop'],
'agri' => $rawCity['agri'],
'comm' => $rawCity['comm'],
'secu' => $rawCity['secu'],
'def' => $rawCity['def'],
'wall' => $rawCity['wall'],
'officer_set' => $rawCity['officer_set'],
]);
}
return $filteredCity;
}
private function getGeneralList(int $cityID, int $nationID, int $showLevel)
{
if ($showLevel == self::FAR_CITY) {
return [
'column' => [],
'list' => []
];
}
$db = DB::db();
$nationStaticList = getAllNationStaticInfo();
$rawGeneralList = Util::convertArrayToDict($db->query('SELECT %l from general WHERE city = %i ORDER BY turntime ASC', Util::formatListOfBackticks(array_keys(static::$viewColumns)), $cityID), 'no');
$ourNationGeneralIDList = new Set();
foreach ($rawGeneralList as $rawGeneral) {
if ($rawGeneral['nation'] == $nationID) {
$ourNationGeneralIDList->add($rawGeneral['no']);
}
}
$reservedCommand = [];
$reservedCommandTargetGeneralIDList = [];
foreach ($rawGeneralList as $rawGeneral) {
if ($rawGeneral['nation'] != $nationID) {
continue;
}
if ($rawGeneral['npc'] < 2) {
$reservedCommandTargetGeneralIDList[$rawGeneral['no']] = $rawGeneral['no'];
}
}
if ($reservedCommandTargetGeneralIDList) {
$rawTurnList = $db->query(
'SELECT general_id, turn_idx, action, arg, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id asc, turn_idx asc',
array_values($reservedCommandTargetGeneralIDList)
);
foreach ($rawTurnList as $rawTurn) {
[
'general_id' => $generalID,
'action' => $action,
'arg' => $arg,
'brief' => $brief,
] = $rawTurn;
if (!key_exists($generalID, $reservedCommand)) {
$reservedCommand[$generalID] = [];
}
$reservedCommand[$generalID][] = [
'action' => $action,
'arg' => $arg,
'brief' => $brief
];
}
}
$specialViewFilter = [
'officerLevel' => fn ($rawGeneral) => $this->getOfficerLevel($rawGeneral),
'officerLevelText' => fn ($rawGeneral) => getOfficerLevelText($this->getOfficerLevel($rawGeneral), $nationStaticList[$rawGeneral['nation']]['level']),
'lbonus' => fn ($rawGeneral) => calcLeadershipBonus($rawGeneral['officer_level'], $nationStaticList[$rawGeneral['nation']]['level']),
'reservedCommand' => fn ($rawGeneral) => $reservedCommand[$rawGeneral['no']] ?? null,
'isOurNation' => fn ($rawGeneral) => $rawGeneral['nation'] == $nationID,
];
$showFullColumn = $showLevel == self::OUR_NATION || $ourNationGeneralIDList->count() > 0;
$resultColumns = [];
foreach (static::$viewColumns as $column => $reqShowLevel) {
if (!$showFullColumn && $reqShowLevel > $showLevel) {
continue;
}
if (key_exists($column, static::$columnRemap)) {
$newColumn = static::$columnRemap[$column];
if ($newColumn !== null) {
$resultColumns[$newColumn] = $column;
}
} else {
$resultColumns[$column] = $column;
}
}
foreach (static::$customViewColumns as $column => $reqShowLevel) {
if (!$showFullColumn && $reqShowLevel > $showLevel) {
continue;
}
$resultColumns[$column] = $column;
}
$generalList = [];
foreach ($rawGeneralList as $rawGeneral) {
$item = [];
foreach ($resultColumns as $column) {
$reqShowLevel = static::$viewColumns[$column];
if ($rawGeneral['nation'] != $nationID && $reqShowLevel == self::OUR_NATION) {
$item[] = null;
continue;
}
if (key_exists($column, $specialViewFilter)) {
$value = $specialViewFilter[$column]($rawGeneral);
} else {
$value = $rawGeneral[$column];
}
$item[] = $value;
}
$generalList[] = $item;
}
return [
'column' => array_keys($resultColumns),
'list' => $generalList,
];
}
private function calcShowLevel(int $cityID, int $currentCityID, int $nationID, Set $cityList, bool $isSpyPresent): int
{
$db = DB::db();
if ($cityList->contains($currentCityID)) {
return self::OUR_NATION;
}
if ($cityID == $currentCityID) {
return self::ON_CITY;
}
if ($isSpyPresent) {
return self::ON_CITY;
}
$existsGeneralID = $db->queryFirstField(
'SELECT no FROM general WHERE city = %i AND nation = %i LIMIT 1',
$cityID,
$nationID
);
if ($existsGeneralID) {
return self::ON_CITY;
}
$cityConstObj = CityConst::byID($cityID);
$nearCityIDList = array_keys($cityConstObj->path);
foreach ($nearCityIDList as $nearCityID) {
if ($cityList->contains($nearCityID)) {
return self::NEAR_CITY;
}
}
return self::FAR_CITY;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
increaseRefresh("도시정보", 1);
$db = DB::db();
$gameStor = \sammo\KVStorage::getStorage($db, 'game_env');
$lastExecuted = $gameStor->getValue('turntime');
$me = $db->queryFirstRow('SELECT con, turntime, belong, city, nation, officer_level, permission, penalty FROM general WHERE owner=%i', $session->getUserID());
if (key_exists('cityID', $this->args)) {
$cityID = (int)$this->args['cityID'];
} else {
$cityID = $me['city'];
}
$con = checkLimit($me['con']);
if ($con >= 2) {
return '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.';
}
$nationID = $me['nation'];
$currentCityID = $me['city'];
//TODO: 조건 조사
$cityList = new Set($db->queryFirstColumn('SELECT city FROM city WHERE nation=%i', $nationID));
$spyList = JSON::decode($db->queryFirstField('SELECT spy FROM nation WHERE nation=%i', $nationID));
$showLevel = $this->calcShowLevel($cityID, $currentCityID, $nationID, $cityList, key_exists($cityID, $spyList));
$rawCity = $db->queryFirstRow('SELECT * FROM city WHERE city=%i', $cityID);
$filteredCity = $this->filterCity($rawCity, $showLevel);
$result = [
'result' => true,
'lastExcuted' => $lastExecuted,
'cityInfo' => $filteredCity,
'spyList' => $spyList,
'nationCityList' => $cityList->toArray(),
'myGeneralID' => $session->generalID,
'currentCityID' => $currentCityID,
'showLevel' => $showLevel,
'cityGeneralList' => $this->getGeneralList($cityID, $nationID, $showLevel)
];
return $result;
}
}
-12
View File
@@ -1,12 +0,0 @@
<?php
namespace sammo\ActionCrewType;
use \sammo\iAction;
use \sammo\General;
class None implements iAction{
use \sammo\DefaultAction;
protected $id = -1;
protected $name = '-';
protected $info = '';
}
@@ -1,20 +0,0 @@
<?php
namespace sammo\ActionCrewType;
use \sammo\iAction;
use \sammo\General;
class che_성벽선제 implements iAction{
use \sammo\DefaultAction;
protected $name = '성벽선제';
protected $info = '전투 가능한 성벽이라면 선제공격을 합니다.';
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
if($statName == 'cityBattleOrder'){
// battleOrder는 스탯과 유사한 수치를 가지므로, 아주 충분히 높은값을 설정한다.
return 10000;
}
return $value;
}
}
+1 -1
View File
@@ -243,7 +243,7 @@ class Betting
return $this->_calcRewardExclusive($winnerType); return $this->_calcRewardExclusive($winnerType);
} }
if ($this->info->isExclusive) { if ($this->info->isExlusive) {
return $this->_calcRewardExclusive($winnerType); return $this->_calcRewardExclusive($winnerType);
} }
//아래는 2개 이상, 복합 보상 옵션 //아래는 2개 이상, 복합 보상 옵션
+4 -24
View File
@@ -21,7 +21,6 @@ use \sammo\Constraint\ConstraintHelper;
class che_물자조달 extends Command\GeneralCommand{ class che_물자조달 extends Command\GeneralCommand{
static protected $actionName = '물자조달'; static protected $actionName = '물자조달';
static protected $debuffFront = 0.5;
protected function argTest():bool{ protected function argTest():bool{
$this->arg = null; $this->arg = null;
@@ -96,31 +95,9 @@ class che_물자조달 extends Command\GeneralCommand{
$score = $general->onCalcDomestic('조달', 'score', $score); $score = $general->onCalcDomestic('조달', 'score', $score);
$score = Util::round($score); $score = Util::round($score);
$exp = $score * 0.7 / 3;
$ded = $score * 1.0 / 3;
$logger = $general->getLogger();
if(in_array($this->city['front'], [1, 3])){
$debuffFront = static::$debuffFront;
if($this->nation['capital'] == $this->city['city']){
$gameStor = \sammo\KVStorage::getStorage($db, 'game_env');
[$year, $startYear] = $gameStor->getValuesAsArray(['year', 'startyear']);
$relYear = $year - $startYear;
if($relYear < 25){
$debuffScale = Util::clamp($relYear - 5, 0, 20) * 0.05;
$debuffFront = ($debuffScale * $debuffFront) + (1 - $debuffScale);
}
}
$score *= $debuffFront;
}
$scoreText = number_format($score, 0); $scoreText = number_format($score, 0);
$logger = $general->getLogger();
if($pick == 'fail'){ if($pick == 'fail'){
$logger->pushGeneralActionLog("조달을 <span class='ev_failed'>실패</span>하여 {$resName}을 <C>$scoreText</> 조달했습니다. <1>$date</>"); $logger->pushGeneralActionLog("조달을 <span class='ev_failed'>실패</span>하여 {$resName}을 <C>$scoreText</> 조달했습니다. <1>$date</>");
@@ -132,6 +109,9 @@ class che_물자조달 extends Command\GeneralCommand{
$logger->pushGeneralActionLog("{$resName}을 <C>$scoreText</> 조달했습니다. <1>$date</>"); $logger->pushGeneralActionLog("{$resName}을 <C>$scoreText</> 조달했습니다. <1>$date</>");
} }
$exp = $score * 0.7 / 3;
$ded = $score * 1.0 / 3;
$incStat = $rng->choiceUsingWeight([ $incStat = $rng->choiceUsingWeight([
'leadership_exp'=>$general->getLeadership(false, false, false, false), 'leadership_exp'=>$general->getLeadership(false, false, false, false),
'strength_exp'=>$general->getStrength(false, false, false, false), 'strength_exp'=>$general->getStrength(false, false, false, false),
+2 -15
View File
@@ -185,21 +185,8 @@ class che_상업투자 extends Command\GeneralCommand{
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} 하여 <C>$scoreText</> 상승했습니다. <1>$date</>"); $logger->pushGeneralActionLog(static::$actionName."{$josaUl} 하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
} }
if(in_array($this->city['front'], [1, 3])){ if(in_array($this->city['front'], [1, 3]) && $this->nation['capital'] != $this->city['city']){
$debuffFront = static::$debuffFront; $score *= static::$debuffFront;
if($this->nation['capital'] == $this->city['city']){
$gameStor = \sammo\KVStorage::getStorage($db, 'game_env');
[$year, $startYear] = $gameStor->getValuesAsArray(['year', 'startyear']);
$relYear = $year - $startYear;
if($relYear < 25){
$debuffScale = Util::clamp($relYear - 5, 0, 20) * 0.05;
$debuffFront = ($debuffScale * $debuffFront) + (1 - $debuffScale);
}
}
$score *= $debuffFront;
} }
//NOTE: 내정량 상승시 초과 가능? //NOTE: 내정량 상승시 초과 가능?
@@ -87,12 +87,6 @@ class che_전투특기초기화 extends Command\GeneralCommand{
$yearMonth = Util::joinYearMonth($env['year'], $env['month']); $yearMonth = Util::joinYearMonth($env['year'], $env['month']);
$oldSpecialList = $general->getAuxVar($oldTypeKey)??[]; $oldSpecialList = $general->getAuxVar($oldTypeKey)??[];
$oldSpecialList[] = $general->getVar(static::$specialType); $oldSpecialList[] = $general->getVar(static::$specialType);
if(static::$specialType == 'special' && count($oldSpecialList) == count(GameConst::$availableSpecialDomestic)){
$oldSpecialList = [$general->getVar(static::$specialType)];
}
else if(static::$specialType == 'special2' && count($oldSpecialList) == count(GameConst::$availableSpecialWar)){
$oldSpecialList = [$general->getVar(static::$specialType)];
}
$general->setAuxVar($oldTypeKey, $oldSpecialList); $general->setAuxVar($oldTypeKey, $oldSpecialList);
$general->setVar(static::$specialType, 'None'); $general->setVar(static::$specialType, 'None');
-12
View File
@@ -37,25 +37,13 @@ class DummyGeneral extends General
} }
} }
public function setCrewType(?GameUnitDetail $crewType){
$this->crewType = $crewType;
}
public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
{ {
//crewType에만 반응하자
if($this->crewType !== null){
return $this->crewType->getBattleInitSkillTriggerList($unit);
}
return new WarUnitTriggerCaller(); return new WarUnitTriggerCaller();
} }
public function getBattlePhaseSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller public function getBattlePhaseSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
{ {
//crewType에만 반응하자
if($this->crewType !== null){
return $this->crewType->getBattlePhaseSkillTriggerList($unit);
}
return new WarUnitTriggerCaller(); return new WarUnitTriggerCaller();
} }
-3
View File
@@ -83,9 +83,6 @@ class GameConstBase
/** @var int 최대 하야 패널티 수 */ /** @var int 최대 하야 패널티 수 */
public static $maxBetrayCnt = 9; public static $maxBetrayCnt = 9;
/** @var int 최대 레벨 */
public static $maxLevel = 255;
/** @var int 최소 인구 증가량 */ /** @var int 최소 인구 증가량 */
public static $basePopIncreaseAmount = 5000; public static $basePopIncreaseAmount = 5000;
/** @var int 증축시 인구 증가량 */ /** @var int 증축시 인구 증가량 */
+40 -42
View File
@@ -41,7 +41,7 @@ class GameUnitConstBase{
[],//성벽은 공격할 수 없다. [],//성벽은 공격할 수 없다.
[self::T_FOOTMAN=>1.2], [self::T_FOOTMAN=>1.2],
['성벽입니다.','생성할 수 없습니다.'], ['성벽입니다.','생성할 수 없습니다.'],
null, ['che_선제사격시도', 'che_선제사격발동'], null null, null
], ],
[ [
@@ -51,7 +51,7 @@ class GameUnitConstBase{
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
['표준적인 보병입니다.','보병은 방어특화이며,','상대가 회피하기 어렵습니다.'], ['표준적인 보병입니다.','보병은 방어특화이며,','상대가 회피하기 어렵습니다.'],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
1101, self::T_FOOTMAN, '청주병', 1101, self::T_FOOTMAN, '청주병',
@@ -60,7 +60,7 @@ class GameUnitConstBase{
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
['저렴하고 튼튼합니다.'], ['저렴하고 튼튼합니다.'],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
1102, self::T_FOOTMAN, '수병', 1102, self::T_FOOTMAN, '수병',
@@ -69,7 +69,7 @@ class GameUnitConstBase{
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
['저렴하고 강력합니다.'], ['저렴하고 강력합니다.'],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
1103, self::T_FOOTMAN, '자객병', 1103, self::T_FOOTMAN, '자객병',
@@ -78,7 +78,7 @@ class GameUnitConstBase{
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
['은밀하고 날쌥니다.'], ['은밀하고 날쌥니다.'],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
1104, self::T_FOOTMAN, '근위병', 1104, self::T_FOOTMAN, '근위병',
@@ -87,7 +87,7 @@ class GameUnitConstBase{
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
['최강의 보병입니다.'], ['최강의 보병입니다.'],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
1105, self::T_FOOTMAN, '등갑병', 1105, self::T_FOOTMAN, '등갑병',
@@ -96,7 +96,7 @@ class GameUnitConstBase{
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
['등갑을 두른 보병입니다.'], ['등갑을 두른 보병입니다.'],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
1106, self::T_FOOTMAN, '백이병', 1106, self::T_FOOTMAN, '백이병',
@@ -105,7 +105,7 @@ class GameUnitConstBase{
[self::T_ARCHER=>1.1, self::T_CAVALRY=>0.9, self::T_SIEGE=>1.1], [self::T_ARCHER=>1.1, self::T_CAVALRY=>0.9, self::T_SIEGE=>1.1],
[self::T_ARCHER=>0.9, self::T_CAVALRY=>1.1, self::T_SIEGE=>0.9], [self::T_ARCHER=>0.9, self::T_CAVALRY=>1.1, self::T_SIEGE=>0.9],
['정예 보병입니다. 불리한 싸움도 버텨냅니다.'], ['정예 보병입니다. 불리한 싸움도 버텨냅니다.'],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
@@ -115,7 +115,7 @@ class GameUnitConstBase{
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2], [self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8], [self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
['표준적인 궁병입니다.','궁병은 선제사격을 하는 병종입니다.'], ['표준적인 궁병입니다.','궁병은 선제사격을 하는 병종입니다.'],
null, ['che_선제사격시도', 'che_선제사격발동'], null null, ['che_선제사격시도', 'che_선제사격발동']
], ],
[ [
1201, self::T_ARCHER, '궁기병', 1201, self::T_ARCHER, '궁기병',
@@ -124,7 +124,7 @@ class GameUnitConstBase{
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.9, self::T_SIEGE=>1.2], [self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.9, self::T_SIEGE=>1.2],
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.1, self::T_SIEGE=>0.8], [self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.1, self::T_SIEGE=>0.8],
['말을 타고 잘 피합니다. 특히 다른 궁병보다 보병에게 조금 더 강합니다.'], ['말을 타고 잘 피합니다. 특히 다른 궁병보다 보병에게 조금 더 강합니다.'],
null, ['che_선제사격시도', 'che_선제사격발동'], null null, ['che_선제사격시도', 'che_선제사격발동']
], ],
[ [
1202, self::T_ARCHER, '연노병', 1202, self::T_ARCHER, '연노병',
@@ -133,7 +133,7 @@ class GameUnitConstBase{
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2], [self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8], [self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
['화살을 연사합니다.'], ['화살을 연사합니다.'],
null, ['che_선제사격시도', 'che_선제사격발동'], null null, ['che_선제사격시도', 'che_선제사격발동']
], ],
[ [
1203, self::T_ARCHER, '강궁병', 1203, self::T_ARCHER, '강궁병',
@@ -142,7 +142,7 @@ class GameUnitConstBase{
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2], [self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8], [self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
['강건한 궁병입니다.'], ['강건한 궁병입니다.'],
null, ['che_선제사격시도', 'che_선제사격발동'], null null, ['che_선제사격시도', 'che_선제사격발동']
], ],
[ [
1204, self::T_ARCHER, '석궁병', 1204, self::T_ARCHER, '석궁병',
@@ -151,7 +151,7 @@ class GameUnitConstBase{
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2], [self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8], [self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
['강력한 화살을 쏩니다.'], ['강력한 화살을 쏩니다.'],
null, ['che_선제사격시도', 'che_선제사격발동'], null null, ['che_선제사격시도', 'che_선제사격발동']
], ],
[ [
@@ -161,7 +161,7 @@ class GameUnitConstBase{
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2], [self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8], [self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['표준적인 기병입니다.','기병은 공격특화입니다.'], ['표준적인 기병입니다.','기병은 공격특화입니다.'],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
1301, self::T_CAVALRY, '백마병', 1301, self::T_CAVALRY, '백마병',
@@ -170,7 +170,7 @@ class GameUnitConstBase{
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2], [self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8], [self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['백마의 위용을 보여줍니다.'], ['백마의 위용을 보여줍니다.'],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
1302, self::T_CAVALRY, '중장기병', 1302, self::T_CAVALRY, '중장기병',
@@ -179,7 +179,7 @@ class GameUnitConstBase{
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2], [self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8], [self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['갑주를 두른 기병입니다.'], ['갑주를 두른 기병입니다.'],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
1303, self::T_CAVALRY, '돌격기병', 1303, self::T_CAVALRY, '돌격기병',
@@ -188,7 +188,7 @@ class GameUnitConstBase{
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2], [self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8], [self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['저돌적으로 공격합니다.'], ['저돌적으로 공격합니다.'],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
1304, self::T_CAVALRY, '철기병', 1304, self::T_CAVALRY, '철기병',
@@ -197,7 +197,7 @@ class GameUnitConstBase{
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2], [self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8], [self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['철갑을 두른 기병입니다.'], ['철갑을 두른 기병입니다.'],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
1305, self::T_CAVALRY, '수렵기병', 1305, self::T_CAVALRY, '수렵기병',
@@ -206,7 +206,7 @@ class GameUnitConstBase{
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2], [self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8], [self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['날쎄고 빠른 기병입니다.'], ['날쎄고 빠른 기병입니다.'],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
1306, self::T_CAVALRY, '맹수병', 1306, self::T_CAVALRY, '맹수병',
@@ -215,7 +215,7 @@ class GameUnitConstBase{
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2], [self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8], [self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['어느 누구보다 강력합니다.'], ['어느 누구보다 강력합니다.'],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
1307, self::T_CAVALRY, '호표기병', 1307, self::T_CAVALRY, '호표기병',
@@ -224,7 +224,7 @@ class GameUnitConstBase{
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2], [self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8], [self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['정예 기병입니다.'], ['정예 기병입니다.'],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
@@ -234,7 +234,7 @@ class GameUnitConstBase{
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
['계략을 사용하는 병종입니다.'], ['계략을 사용하는 병종입니다.'],
null, null, null null, null
], ],
[ [
1401, self::T_WIZARD, '신귀병', 1401, self::T_WIZARD, '신귀병',
@@ -243,7 +243,7 @@ class GameUnitConstBase{
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
['신출귀몰한 귀병입니다.'], ['신출귀몰한 귀병입니다.'],
null, null, null null, null
], ],
[ [
1402, self::T_WIZARD, '백귀병', 1402, self::T_WIZARD, '백귀병',
@@ -252,7 +252,7 @@ class GameUnitConstBase{
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
['저렴하고 튼튼합니다.'], ['저렴하고 튼튼합니다.'],
null, null, null null, null
], ],
[ [
1403, self::T_WIZARD, '흑귀병', 1403, self::T_WIZARD, '흑귀병',
@@ -261,7 +261,7 @@ class GameUnitConstBase{
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
['저렴하고 강력합니다.'], ['저렴하고 강력합니다.'],
null, null, null null, null
], ],
[ [
1404, self::T_WIZARD, '악귀병', 1404, self::T_WIZARD, '악귀병',
@@ -270,7 +270,7 @@ class GameUnitConstBase{
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
['백병전에도 능숙합니다.'], ['백병전에도 능숙합니다.'],
null, null, null null, null
], ],
[ [
1405, self::T_WIZARD, '남귀병', 1405, self::T_WIZARD, '남귀병',
@@ -279,7 +279,7 @@ class GameUnitConstBase{
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
['전투를 포기하고 계략에 몰두합니다.'], ['전투를 포기하고 계략에 몰두합니다.'],
null, null, null null, null
], ],
[ [
1406, self::T_WIZARD, '황귀병', 1406, self::T_WIZARD, '황귀병',
@@ -288,7 +288,7 @@ class GameUnitConstBase{
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
['고도로 훈련된 귀병입니다.'], ['고도로 훈련된 귀병입니다.'],
null, null, null null, null
], ],
[ [
1407, self::T_WIZARD, '천귀병', 1407, self::T_WIZARD, '천귀병',
@@ -297,7 +297,7 @@ class GameUnitConstBase{
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
['갑주를 두른 귀병입니다.'], ['갑주를 두른 귀병입니다.'],
null, null, null null, null
], ],
[ [
1408, self::T_WIZARD, '마귀병', 1408, self::T_WIZARD, '마귀병',
@@ -306,7 +306,7 @@ class GameUnitConstBase{
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
['날카로운 무기를 가진 귀병입니다.'], ['날카로운 무기를 가진 귀병입니다.'],
null, null, null null, null
], ],
[ [
@@ -314,9 +314,9 @@ class GameUnitConstBase{
100, 100, 6, 0, 0, 14, 5, 100, 100, 6, 0, 0, 14, 5,
0, null, null, 3, 0, null, null, 3,
[self::T_FOOTMAN=>1.25, self::T_ARCHER=>1.25, self::T_CAVALRY=>1.25, self::T_WIZARD=>1.25, self::T_CASTLE=>1.8, 1106=>1.112], [self::T_FOOTMAN=>1.25, self::T_ARCHER=>1.25, self::T_CAVALRY=>1.25, self::T_WIZARD=>1.25, self::T_CASTLE=>1.8, 1106=>1.112],
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2, 1106=>1.067], [self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
['높은 구조물 위에서 공격합니다. 첫 공격은 성벽을 향합니다.'], ['높은 구조물 위에서 공격합니다.'],
['che_성벽부상무효'], ['che_선제사격시도', 'che_선제사격발동'], ['che_성벽선제'] ['che_성벽부상무효'], ['che_선제사격시도', 'che_선제사격발동']
], ],
[ [
1501, self::T_SIEGE, '충차', 1501, self::T_SIEGE, '충차',
@@ -325,25 +325,25 @@ class GameUnitConstBase{
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>2.4], [self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>2.4],
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2], [self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
['엄청난 위력으로 성벽을 부수어버립니다.'], ['엄청난 위력으로 성벽을 부수어버립니다.'],
['che_성벽부상무효'], null, null ['che_성벽부상무효'], null
], ],
[ [
1502, self::T_SIEGE, '벽력거', 1502, self::T_SIEGE, '벽력거',
150, 100, 6, 5, 0, 20, 5, 150, 100, 6, 5, 0, 20, 5,
3000, ['업'], null, 0, 3000, ['업'], null, 0,
[self::T_FOOTMAN=>1.25, self::T_ARCHER=>1.25, self::T_CAVALRY=>1.25, self::T_WIZARD=>1.25, self::T_CASTLE=>1.8, 1106=>1.112], [self::T_FOOTMAN=>1.25, self::T_ARCHER=>1.25, self::T_CAVALRY=>1.25, self::T_WIZARD=>1.25, self::T_CASTLE=>1.8, 1106=>1.112],
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2, 1106=>1.067], [self::T_FOOTMAN=>0.833, self::T_ARCHER=>0.833, self::T_CAVALRY=>0.833, self::T_WIZARD=>0.833, 1106=>0.909],
['상대에게 돌덩이를 날립니다. 첫 공격은 성벽을 향합니다.'], ['상대에게 돌덩이를 날립니다.'],
['che_성벽부상무효'], ['che_선제사격시도', 'che_선제사격발동'], ['che_성벽선제'] ['che_성벽부상무효'], ['che_선제사격시도', 'che_선제사격발동']
], ],
[ [
1503, self::T_SIEGE, '목우', 1503, self::T_SIEGE, '목우',
50, 200, 5, 0, 0, 15, 5, 50, 200, 5, 0, 0, 15, 5,
3000, ['성도'], null, 0, 3000, ['성도'], null, 0,
[self::T_FOOTMAN=>1, self::T_ARCHER=>1, self::T_CAVALRY=>1, self::T_WIZARD=>1, self::T_CASTLE=>1.8], [self::T_FOOTMAN=>1.25, self::T_ARCHER=>1.25, self::T_CAVALRY=>1.25, self::T_WIZARD=>1.25, self::T_CASTLE=>1.8, 1106=>1.112],
[self::T_FOOTMAN=>1, self::T_ARCHER=>1, self::T_CAVALRY=>1, self::T_WIZARD=>1, 1106=>1], [self::T_FOOTMAN=>1, self::T_ARCHER=>1, self::T_CAVALRY=>1, self::T_WIZARD=>1, 1106=>1],
['상대를 저지하는 특수병기입니다.'], ['상대를 저지하는 특수병기입니다.'],
['che_성벽부상무효'], ['che_저지시도', 'che_저지발동'], null ['che_성벽부상무효'], ['che_저지시도', 'che_저지발동']
] ]
]; ];
@@ -466,7 +466,6 @@ class GameUnitConstBase{
$info, $info,
$initSkillTrigger, $initSkillTrigger,
$phaseSkillTrigger, $phaseSkillTrigger,
$iActionList,
] = $rawUnit; ] = $rawUnit;
if($reqYear > 0){ if($reqYear > 0){
@@ -510,8 +509,7 @@ class GameUnitConstBase{
$defenceCoef, $defenceCoef,
$info, $info,
$initSkillTrigger, $initSkillTrigger,
$phaseSkillTrigger, $phaseSkillTrigger
$iActionList,
); );
$constID[$id] = $unit; $constID[$id] = $unit;
+65 -166
View File
@@ -1,9 +1,7 @@
<?php <?php
namespace sammo; namespace sammo;
class GameUnitDetail implements iAction class GameUnitDetail implements iAction{
{
use DefaultAction; use DefaultAction;
public $id; public $id;
@@ -25,8 +23,6 @@ class GameUnitDetail implements iAction
public $info; public $info;
public $initSkillTrigger; public $initSkillTrigger;
public $phaseSkillTrigger; public $phaseSkillTrigger;
/** @var iAction[]|null iActionList */
public $iActionList;
public function __construct( public function __construct(
int $id, int $id,
@@ -47,9 +43,8 @@ class GameUnitDetail implements iAction
array $defenceCoef, array $defenceCoef,
array $info, array $info,
?array $initSkillTrigger, ?array $initSkillTrigger,
?array $phaseSkillTrigger, ?array $phaseSkillTrigger
?array $iActionList, ){
) {
$this->id = $id; $this->id = $id;
$this->name = $name; $this->name = $name;
$this->armType = $armType; $this->armType = $armType;
@@ -69,91 +64,78 @@ class GameUnitDetail implements iAction
$this->info = $info; $this->info = $info;
$this->initSkillTrigger = $initSkillTrigger; $this->initSkillTrigger = $initSkillTrigger;
$this->phaseSkillTrigger = $phaseSkillTrigger; $this->phaseSkillTrigger = $phaseSkillTrigger;
$this->iActionList = [];
foreach($iActionList ?? [] as $rawAction){
$action = buildActionCrewTypeClass($rawAction);
if(!$action){
continue;
}
$this->iActionList[] = $action;
}
} }
public function getInfo(): string public function getInfo():string{
{
return join("\n<br>", $this->info); return join("\n<br>", $this->info);
} }
public function getShortName(): string public function getShortName():string{
{
return StringUtil::subStringForWidth($this->name, 0, 4); return StringUtil::subStringForWidth($this->name, 0, 4);
} }
public function riceWithTech(int $tech, int $crew = 100): float public function riceWithTech(int $tech, int $crew=100):float{
{
return $this->rice * getTechCost($tech) * $crew / 100; return $this->rice * getTechCost($tech) * $crew / 100;
} }
public function costWithTech(int $tech, int $crew = 100): float public function costWithTech(int $tech, int $crew=100):float{
{
return $this->cost * getTechCost($tech) * $crew / 100; return $this->cost * getTechCost($tech) * $crew / 100;
} }
public function getAttackCoef(GameUnitDetail $opposeCrewType): float public function getAttackCoef(GameUnitDetail $opposeCrewType):float{
{
$opposeCrewTypeID = $opposeCrewType->id; $opposeCrewTypeID = $opposeCrewType->id;
if (key_exists($opposeCrewTypeID, $this->attackCoef)) { if(key_exists($opposeCrewTypeID, $this->attackCoef)){
return $this->attackCoef[$opposeCrewTypeID]; return $this->attackCoef[$opposeCrewTypeID];
} }
$opposeArmType = $opposeCrewType->armType; $opposeArmType = $opposeCrewType->armType;
return $this->attackCoef[$opposeArmType] ?? 1; return $this->attackCoef[$opposeArmType]??1;
} }
public function getDefenceCoef(GameUnitDetail $opposeCrewType): float public function getDefenceCoef(GameUnitDetail $opposeCrewType):float{
{
$opposeCrewTypeID = $opposeCrewType->id; $opposeCrewTypeID = $opposeCrewType->id;
if (key_exists($opposeCrewTypeID, $this->defenceCoef)) { if(key_exists($opposeCrewTypeID, $this->defenceCoef)){
return $this->defenceCoef[$opposeCrewTypeID]; return $this->defenceCoef[$opposeCrewTypeID];
} }
$opposeArmType = $opposeCrewType->armType; $opposeArmType = $opposeCrewType->armType;
return $this->defenceCoef[$opposeArmType] ?? 1; return $this->defenceCoef[$opposeArmType]??1;
} }
public function getComputedAttack(General $general, int $tech) public function getComputedAttack(General $general, int $tech){
{ if($this->armType == GameUnitConst::T_WIZARD){
if ($this->armType == GameUnitConst::T_WIZARD) { $ratio = $general->getIntel(true, true, true)*2 - 40;
$ratio = $general->getIntel(true, true, true) * 2 - 40; }
} else if ($this->armType == GameUnitConst::T_SIEGE) { else if($this->armType == GameUnitConst::T_SIEGE){
$ratio = $general->getLeadership(true, true, true) * 2 - 40; $ratio = $general->getLeadership(true, true, true)*2 - 40;
} else if ($this->armType == GameUnitConst::T_MISC) { }
else if($this->armType == GameUnitConst::T_MISC){
$ratio = $general->getIntel(true, true, true) + $ratio = $general->getIntel(true, true, true) +
$general->getLeadership(true, true, true) + $general->getLeadership(true, true, true) +
$general->getStrength(true, true, true); $general->getStrength(true, true, true);
$ratio = $ratio * 2 / 3 - 40; $ratio = $ratio*2/3 - 40;
} else {
$ratio = $general->getStrength(true, true, true) * 2 - 40;
} }
if ($ratio < 10) { else{
$ratio = $general->getStrength(true, true, true)*2 - 40;
}
if($ratio < 10){
$ratio = 10; $ratio = 10;
} }
if ($ratio > 100) { if($ratio > 100){
$ratio = 50 + $ratio / 2; $ratio = 50 + $ratio/2;
} }
$att = $this->attack + getTechAbil($tech); $att = $this->attack + getTechAbil($tech);
return $att * $ratio / 100; return $att * $ratio / 100;
} }
public function getComputedDefence(General $general, int $tech) public function getComputedDefence(General $general, int $tech){
{
$def = $this->defence + getTechAbil($tech); $def = $this->defence + getTechAbil($tech);
$crew = ($general->getVar('crew') / (7000 / 30)) + 70; $crew = ($general->getVar('crew') / (7000 / 30)) + 70;
return $def * $crew / 100; return $def * $crew / 100;
} }
public function getCriticalRatio(General $general) public function getCriticalRatio(General $general){
{ if($this->armType == GameUnitConst::T_CASTLE){
if ($this->armType == GameUnitConst::T_CASTLE) {
//성벽은 필살을 사용하지 않는다. //성벽은 필살을 사용하지 않는다.
return 0; return 0;
} }
@@ -161,19 +143,22 @@ class GameUnitDetail implements iAction
// 무장 무력 : 65 5%, 70 10%, 75 15%, 80 20% // 무장 무력 : 65 5%, 70 10%, 75 15%, 80 20%
// 지장 지력 : 65 5%, 70 8%, 75 10%, 80 13% // 지장 지력 : 65 5%, 70 8%, 75 10%, 80 13%
//충차장 통솔: 65 5%, 70 8%, 75 10%, 80 13% //충차장 통솔: 65 5%, 70 8%, 75 10%, 80 13%
if ($this->armType == GameUnitConst::T_WIZARD) { if($this->armType == GameUnitConst::T_WIZARD){
$mainstat = $general->getIntel(false, true, true, false); $mainstat = $general->getIntel(false, true, true, false);
$coef = 0.4; $coef = 0.4;
} else if ($this->armType == GameUnitConst::T_SIEGE) { }
else if($this->armType == GameUnitConst::T_SIEGE){
$mainstat = $general->getLeadership(false, true, true, false); $mainstat = $general->getLeadership(false, true, true, false);
$coef = 0.4; $coef = 0.4;
} else if ($this->armType == GameUnitConst::T_MISC) { }
else if($this->armType == GameUnitConst::T_MISC){
$mainstat = $general->getIntel(false, true, true, false) + $mainstat = $general->getIntel(false, true, true, false) +
$general->getLeadership(false, true, true, false) + $general->getLeadership(false, true, true, false) +
$general->getStrength(false, true, true, false); $general->getStrength(false, true, true, false);
$mainstat /= 3; $mainstat /= 3;
$coef = 0.4; $coef = 0.4;
} else { }
else{
$mainstat = $general->getStrength(false, true, true, false); $mainstat = $general->getStrength(false, true, true, false);
$coef = 0.5; $coef = 0.5;
} }
@@ -184,8 +169,7 @@ class GameUnitDetail implements iAction
return min(50, $ratio) / 100; return min(50, $ratio) / 100;
} }
public function pickScore($tech) public function pickScore($tech){
{
$defaultWar = GameConst::$armperphase + $this->attack + $this->defence + getTechAbil($tech) * 2; $defaultWar = GameConst::$armperphase + $this->attack + $this->defence + getTechAbil($tech) * 2;
$defaultWar *= 1 + $this->speed / 2; $defaultWar *= 1 + $this->speed / 2;
$defaultWar /= Util::valueFit(1 - $this->avoid / 100, 0.1); $defaultWar /= Util::valueFit(1 - $this->avoid / 100, 0.1);
@@ -193,41 +177,40 @@ class GameUnitDetail implements iAction
return $defaultWar; return $defaultWar;
} }
public function isValid($ownCities, $ownRegions, $relativeYear, $tech) public function isValid($ownCities, $ownRegions, $relativeYear, $tech){
{
//음수 없음 //음수 없음
$relativeYear = max(0, $relativeYear); $relativeYear = max(0, $relativeYear);
if ($relativeYear < $this->reqYear) { if($relativeYear < $this->reqYear){
return false; return false;
} }
if ($tech < $this->reqTech) { if($tech < $this->reqTech){
return false; return false;
} }
if ($this->reqCities !== null) { if($this->reqCities !== null){
$valid = false; $valid = false;
foreach ($this->reqCities as $reqCity) { foreach($this->reqCities as $reqCity){
if (\key_exists($reqCity, $ownCities)) { if(\key_exists($reqCity, $ownCities)){
$valid = true; $valid = true;
break; break;
} }
} }
if (!$valid) { if(!$valid){
return false; return false;
} }
} }
if ($this->reqRegions !== null) { if($this->reqRegions !== null){
$valid = false; $valid = false;
foreach ($this->reqRegions as $reqRegion) { foreach($this->reqRegions as $reqRegion){
if (\key_exists($reqRegion, $ownRegions)) { if(\key_exists($reqRegion, $ownRegions)){
$valid = true; $valid = true;
break; break;
} }
} }
if (!$valid) { if(!$valid){
return false; return false;
} }
} }
@@ -236,17 +219,17 @@ class GameUnitDetail implements iAction
} }
//iAction //iAction
public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
{ if(!$this->initSkillTrigger){
if (!$this->initSkillTrigger) {
return null; return null;
} }
$triggerList = []; $triggerList = [];
foreach ($this->initSkillTrigger as $triggerArgs) { foreach($this->initSkillTrigger as $triggerArgs){
if (is_string($triggerArgs)) { if(is_string($triggerArgs)){
$typeName = $triggerArgs; $typeName = $triggerArgs;
$triggerList[] = buildWarUnitTriggerClass($typeName, $unit); $triggerList[] = buildWarUnitTriggerClass($typeName, $unit);
} else { }
else{
$typeName = $triggerArgs[0]; $typeName = $triggerArgs[0];
//WarUnit 다음 인자는 $raiseType이며, 0이어야할 것이다 //WarUnit 다음 인자는 $raiseType이며, 0이어야할 것이다
$triggerArgs[0] = 0; $triggerArgs[0] = 0;
@@ -255,17 +238,17 @@ class GameUnitDetail implements iAction
} }
return new WarUnitTriggerCaller(...$triggerList); return new WarUnitTriggerCaller(...$triggerList);
} }
public function getBattlePhaseSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
{ if(!$this->phaseSkillTrigger){
if (!$this->phaseSkillTrigger) {
return null; return null;
} }
$triggerList = []; $triggerList = [];
foreach ($this->phaseSkillTrigger as $triggerArgs) { foreach($this->phaseSkillTrigger as $triggerArgs){
if (is_string($triggerArgs)) { if(is_string($triggerArgs)){
$typeName = $triggerArgs; $typeName = $triggerArgs;
$triggerList[] = buildWarUnitTriggerClass($typeName, $unit); $triggerList[] = buildWarUnitTriggerClass($typeName, $unit);
} else { }
else{
$typeName = $triggerArgs[0]; $typeName = $triggerArgs[0];
//WarUnit 다음 인자는 $raiseType이며, 0이어야할 것이다 //WarUnit 다음 인자는 $raiseType이며, 0이어야할 것이다
$triggerArgs[0] = 0; $triggerArgs[0] = 0;
@@ -273,90 +256,6 @@ class GameUnitDetail implements iAction
} }
} }
return new WarUnitTriggerCaller(...$triggerList); return new WarUnitTriggerCaller(...$triggerList);
}
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux = null): float
{
if (!$this->iActionList) {
return $value;
}
foreach ($this->iActionList as $iAction) {
$value = $iAction->onCalcDomestic($turnType, $varType, $value, $aux);
}
return $value;
}
public function onCalcStat(General $general, string $statName, $value, $aux = null)
{
if (!$this->iActionList) {
return $value;
}
foreach ($this->iActionList as $iAction) {
$value = $iAction->onCalcStat($general, $statName, $value, $aux);
}
return $value;
}
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
if (!$this->iActionList) {
return $value;
}
foreach ($this->iActionList as $iAction) {
$value = $iAction->onCalcOpposeStat($general, $statName, $value, $aux);
}
return $value;
}
public function onCalcStrategic(string $turnType, string $varType, $value)
{
if (!$this->iActionList) {
return $value;
}
foreach ($this->iActionList as $iAction) {
$value = $iAction->onCalcStrategic($turnType, $varType, $value);
}
return $value;
}
public function onCalcNationalIncome(string $type, $amount)
{
if (!$this->iActionList) {
return $amount;
}
foreach ($this->iActionList as $iAction) {
$amount = $iAction->onCalcNationalIncome($type, $amount);
}
return $amount;
}
public function getWarPowerMultiplier(WarUnit $unit): array
{
if (!$this->iActionList) {
return [1, 1];
}
$attack = 1;
$defence = 1;
foreach ($this->iActionList as $iAction) {
$attack *= $iAction->getWarPowerMultiplier($unit)[0];
$defence *= $iAction->getWarPowerMultiplier($unit)[1];
}
return [$attack, $defence];
}
public function onArbitraryAction(General $general, RandUtil $rng, string $actionType, ?string $phase = null, ?array $aux = null): null|array
{
if (!$this->iActionList) {
return $aux;
}
foreach ($this->iActionList as $iAction) {
$aux = $iAction->onArbitraryAction($general, $rng, $actionType, $phase, $aux);
}
return $aux;
} }
} }
+99 -40
View File
@@ -30,22 +30,20 @@ class General implements iAction
protected $logActivatedSkill = []; protected $logActivatedSkill = [];
protected $isFinished = false; protected $isFinished = false;
/** @var ?iAction */ /** @var iAction */
protected $nationType = null; protected $nationType = null;
/** @var ?iAction */ /** @var iAction */
protected $officerLevelObj = null; protected $officerLevelObj = null;
/** @var ?iAction */ /** @var iAction */
protected $specialDomesticObj = null; protected $specialDomesticObj = null;
/** @var ?iAction */ /** @var iAction */
protected $specialWarObj = null; protected $specialWarObj = null;
/** @var ?iAction */ /** @var iAction */
protected $personalityObj = null; protected $personalityObj = null;
/** @var ?iAction[] */ /** @var iAction[] */
protected $itemObjs = []; protected $itemObjs = [];
/** @var ?iAction */ /** @var iAction */
protected $inheritBuffObj = null; protected $inheritBuffObj = null;
/** @var ?GameUnitDetail */
protected $crewType = null;
protected $lastTurn = null; protected $lastTurn = null;
protected $resultTurn = null; protected $resultTurn = null;
@@ -124,8 +122,6 @@ class General implements iAction
$this->personalityObj = buildPersonalityClass($raw['personal']); $this->personalityObj = buildPersonalityClass($raw['personal']);
$this->crewType = GameUnitConst::byID($raw['crewtype'] ?? GameUnitConst::DEFAULT_CREWTYPE);
$this->itemObjs['horse'] = buildItemClass($raw['horse']); $this->itemObjs['horse'] = buildItemClass($raw['horse']);
$this->itemObjs['weapon'] = buildItemClass($raw['weapon']); $this->itemObjs['weapon'] = buildItemClass($raw['weapon']);
$this->itemObjs['book'] = buildItemClass($raw['book']); $this->itemObjs['book'] = buildItemClass($raw['book']);
@@ -329,10 +325,11 @@ class General implements iAction
function getCrewTypeObj(): GameUnitDetail function getCrewTypeObj(): GameUnitDetail
{ {
if($this->crewType === null) { $crewType = GameUnitConst::byID($this->getVar('crewtype'));
if ($crewType === null) {
throw new \InvalidArgumentException('Invalid CrewType:' . $this->getVar('crewtype')); throw new \InvalidArgumentException('Invalid CrewType:' . $this->getVar('crewtype'));
} }
return $this->crewType; return $crewType;
} }
function calcRecentWarTurn(int $turnTerm): int function calcRecentWarTurn(int $turnTerm): int
@@ -446,8 +443,6 @@ class General implements iAction
} }
} }
$statValue = Util::clamp($statValue, 0, GameConst::$maxLevel);
if ($withIActionObj) { if ($withIActionObj) {
foreach ([ foreach ([
$this->nationType, $this->nationType,
@@ -471,8 +466,6 @@ class General implements iAction
$this->calcCache[$cKey] = $statValue; $this->calcCache[$cKey] = $statValue;
$statValue = Util::clamp($statValue, 0, GameConst::$maxLevel);
if ($useFloor) { if ($useFloor) {
return Util::toInt($statValue); return Util::toInt($statValue);
} }
@@ -844,11 +837,9 @@ class General implements iAction
$this->increaseVar($statName, -1); $this->increaseVar($statName, -1);
$result = true; $result = true;
} else if ($this->getVar($statExpName) >= $limit) { } else if ($this->getVar($statExpName) >= $limit) {
if($this->getVar($statName) < GameConst::$maxLevel) { $logger->pushGeneralActionLog("<S>{$statNickName}</>이 <C>1</> 올랐습니다!", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("<S>{$statNickName}</>이 <C>1</> 올랐습니다!", ActionLogger::PLAIN);
$this->increaseVar($statName, 1);
}
$this->increaseVar($statExpName, -$limit); $this->increaseVar($statExpName, -$limit);
$this->increaseVar($statName, 1);
$result = true; $result = true;
} }
} }
@@ -856,22 +847,18 @@ class General implements iAction
return $result; return $result;
} }
protected function getActionList(): array{ public function getPreTurnExecuteTriggerList(General $general): ?GeneralTriggerCaller
return array_merge([ {
$caller = new GeneralTriggerCaller();
foreach (array_merge([
$this->nationType, $this->nationType,
$this->officerLevelObj, $this->officerLevelObj,
$this->specialDomesticObj, $this->specialDomesticObj,
$this->specialWarObj, $this->specialWarObj,
$this->personalityObj, $this->personalityObj,
$this->crewType, $this->getCrewTypeObj(),
$this->inheritBuffObj, $this->inheritBuffObj,
], $this->itemObjs); ], $this->itemObjs) as $iObj) {
}
public function getPreTurnExecuteTriggerList(General $general): ?GeneralTriggerCaller
{
$caller = new GeneralTriggerCaller();
foreach ($this->getActionList() as $iObj) {
if (!$iObj) { if (!$iObj) {
continue; continue;
@@ -884,7 +871,15 @@ class General implements iAction
} }
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux = null): float public function onCalcDomestic(string $turnType, string $varType, float $value, $aux = null): float
{ {
foreach ($this->getActionList() as $iObj) { foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) { if (!$iObj) {
continue; continue;
} }
@@ -897,7 +892,15 @@ class General implements iAction
public function onCalcStat(General $general, string $statName, $value, $aux = null) public function onCalcStat(General $general, string $statName, $value, $aux = null)
{ {
//xxx: $general? //xxx: $general?
foreach ($this->getActionList() as $iObj) { foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) { if (!$iObj) {
continue; continue;
} }
@@ -910,7 +913,15 @@ class General implements iAction
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null) public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{ {
//xxx: $general? //xxx: $general?
foreach ($this->getActionList() as $iObj) { foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) { if (!$iObj) {
continue; continue;
} }
@@ -922,7 +933,15 @@ class General implements iAction
public function onCalcStrategic(string $turnType, string $varType, $value) public function onCalcStrategic(string $turnType, string $varType, $value)
{ {
foreach ($this->getActionList() as $iObj) { foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) { if (!$iObj) {
continue; continue;
} }
@@ -934,7 +953,15 @@ class General implements iAction
public function onCalcNationalIncome(string $type, $amount) public function onCalcNationalIncome(string $type, $amount)
{ {
foreach ($this->getActionList() as $iObj) { foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) { if (!$iObj) {
continue; continue;
} }
@@ -946,7 +973,15 @@ class General implements iAction
public function onArbitraryAction(General $general, RandUtil $rng, string $actionType, ?string $phase = null, $aux = null): null|array public function onArbitraryAction(General $general, RandUtil $rng, string $actionType, ?string $phase = null, $aux = null): null|array
{ {
foreach ($this->getActionList() as $iObj) { foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) { if (!$iObj) {
continue; continue;
} }
@@ -961,7 +996,15 @@ class General implements iAction
//xxx:$unit //xxx:$unit
$att = 1; $att = 1;
$def = 1; $def = 1;
foreach ($this->getActionList() as $iObj) { foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) { if (!$iObj) {
continue; continue;
} }
@@ -975,7 +1018,15 @@ class General implements iAction
public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
{ {
$caller = new WarUnitTriggerCaller(); $caller = new WarUnitTriggerCaller();
foreach ($this->getActionList() as $iObj) { foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) { if (!$iObj) {
continue; continue;
} }
@@ -996,7 +1047,15 @@ class General implements iAction
new WarUnitTrigger\che_계략발동($unit), new WarUnitTrigger\che_계략발동($unit),
new WarUnitTrigger\che_계략실패($unit) new WarUnitTrigger\che_계략실패($unit)
); );
foreach ($this->getActionList() as $iObj) { foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) { if (!$iObj) {
continue; continue;
} }
+2 -10
View File
@@ -198,7 +198,6 @@ class SpecialityHelper{
public static function pickSpecialDomestic(RandUtil $rng, array $general, array $prevSpecials=[]) : string{ public static function pickSpecialDomestic(RandUtil $rng, array $general, array $prevSpecials=[]) : string{
$pAbs = []; $pAbs = [];
$pRel = []; $pRel = [];
$id = null;
$myCond = static::calcCondGeneric($general); $myCond = static::calcCondGeneric($general);
@@ -241,10 +240,7 @@ class SpecialityHelper{
} }
} }
if($pRel){ $id = $rng->choiceUsingWeight($pRel);
$id = $rng->choiceUsingWeight($pRel);
}
if($id){ if($id){
return $id; return $id;
} }
@@ -260,7 +256,6 @@ class SpecialityHelper{
$reqDex = []; $reqDex = [];
$pAbs = []; $pAbs = [];
$pRel = []; $pRel = [];
$id = null;
$myCond = static::calcCondGeneric($general); $myCond = static::calcCondGeneric($general);
$myCond |= static::calcCondDexterity($rng, $general); $myCond |= static::calcCondDexterity($rng, $general);
@@ -312,10 +307,7 @@ class SpecialityHelper{
} }
} }
if($pRel){ $id = $rng->choiceUsingWeight($pRel);
$id = $rng->choiceUsingWeight($pRel);
}
if($id){ if($id){
return $id; return $id;
} }
+1 -23
View File
@@ -7,7 +7,6 @@ class WarUnitCity extends WarUnit{
protected $hp; protected $hp;
protected $cityTrainAtmos; protected $cityTrainAtmos;
protected $onSiege = false;
function __construct(public readonly RandUtil $rng, $raw, $rawNation, int $year, int $month, int $startYear){ function __construct(public readonly RandUtil $rng, $raw, $rawNation, int $year, int $month, int $startYear){
$general = new DummyGeneral(false); $general = new DummyGeneral(false);
@@ -25,7 +24,6 @@ class WarUnitCity extends WarUnit{
$this->logger = $general->getLogger(); $this->logger = $general->getLogger();
$this->crewType = GameUnitConst::byID(GameUnitConst::CREWTYPE_CASTLE); $this->crewType = GameUnitConst::byID(GameUnitConst::CREWTYPE_CASTLE);
$general->setCrewType($this->crewType);
$this->hp = $this->getCityVar('def') * 10; $this->hp = $this->getCityVar('def') * 10;
@@ -79,20 +77,6 @@ class WarUnitCity extends WarUnit{
return $this->hp; return $this->hp;
} }
function setSiege(){
$this->onSiege = true;
$this->currPhase = 0;
$this->prePhase = 0;
$this->bonusPhase = 0;
/** @var DummyGeneral $general */
$general = $this->general;
$general->setCrewType(null);
}
function isSiege(): bool{
return $this->onSiege;
}
function getDex(GameUnitDetail $crewType){ function getDex(GameUnitDetail $crewType){
return ($this->cityTrainAtmos - 60) * 7200; return ($this->cityTrainAtmos - 60) * 7200;
} }
@@ -110,12 +94,6 @@ class WarUnitCity extends WarUnit{
function continueWar(&$noRice):bool{ function continueWar(&$noRice):bool{
//전투가 가능하면 true //전투가 가능하면 true
$noRice = false; $noRice = false;
//본 공성이 아닌 경우에는 한대만 맞아줌
if(!$this->onSiege){
return false;
}
if($this->getHP() <= 0){ if($this->getHP() <= 0){
return false; return false;
} }
@@ -131,7 +109,7 @@ class WarUnitCity extends WarUnit{
} }
function finishBattle(){ function finishBattle(){
if($this->isFinished || !$this->onSiege){ if($this->isFinished){
return; return;
} }
$this->clearActivatedSkill(); $this->clearActivatedSkill();
+4 -11
View File
@@ -262,8 +262,11 @@ class WarUnitGeneral extends WarUnit
return $general->getVar('crew'); return $general->getVar('crew');
} }
function calcRiceConsumption(int $damage): float function increaseKilled(int $damage): int
{ {
$general = $this->general;
$this->addLevelExp($damage / 50);
$rice = $damage / 100; $rice = $damage / 100;
if (!$this->isAttacker) { if (!$this->isAttacker) {
$rice *= 0.8; $rice *= 0.8;
@@ -276,16 +279,6 @@ class WarUnitGeneral extends WarUnit
$rice *= getTechCost($this->getNationVar('tech')); $rice *= getTechCost($this->getNationVar('tech'));
$rice = $this->general->onCalcStat($this->general, 'killRice', $rice); $rice = $this->general->onCalcStat($this->general, 'killRice', $rice);
return $rice;
}
function increaseKilled(int $damage): int
{
$general = $this->general;
$this->addLevelExp($damage / 50);
$rice = $this->calcRiceConsumption($damage);
$general->increaseVarWithLimit('rice', -$rice, 0); $general->increaseVarWithLimit('rice', -$rice, 0);
$addDex = $damage; $addDex = $damage;
@@ -9,8 +9,6 @@ use sammo\Util;
use sammo\ObjectTrigger; use sammo\ObjectTrigger;
use sammo\ActionLogger; use sammo\ActionLogger;
use function sammo\getTechCost;
class che_저지발동 extends BaseWarUnitTrigger{ class che_저지발동 extends BaseWarUnitTrigger{
protected $priority = ObjectTrigger::PRIORITY_POST; //최우선 순위 protected $priority = ObjectTrigger::PRIORITY_POST; //최우선 순위
@@ -27,15 +25,10 @@ class che_저지발동 extends BaseWarUnitTrigger{
$self->getLogger()->pushGeneralBattleDetailLog("상대를 <C>저지</>했다!", ActionLogger::PLAIN); $self->getLogger()->pushGeneralBattleDetailLog("상대를 <C>저지</>했다!", ActionLogger::PLAIN);
$oppose->getLogger()->pushGeneralBattleDetailLog("저지</>당했다!", ActionLogger::PLAIN); $oppose->getLogger()->pushGeneralBattleDetailLog("저지</>당했다!", ActionLogger::PLAIN);
$calcDamage = $oppose->getWarPower() * 0.9;
$self->getGeneral()->addDex($oppose->getCrewType(), $oppose->getWarPower() * 0.9); $self->getGeneral()->addDex($oppose->getCrewType(), $oppose->getWarPower() * 0.9);
$self->getGeneral()->addDex($self->getCrewType(), $calcDamage); $self->getGeneral()->addDex($self->getCrewType(), $self->getWarPower() * 0.9);
if($self instanceof WarUnitGeneral){ if($self instanceof WarUnitGeneral){
$self->addLevelExp($calcDamage / 50); $self->addLevelExp($self->getWarPower() * 0.9 / 50);
$rice = $self->calcRiceConsumption($calcDamage);
$rice *= 0.25;
$self->getGeneral()->increaseVarWithLimit('rice', -$rice, 0);
} }
$self->setWarPowerMultiply(0); $self->setWarPowerMultiply(0);
+8 -8
View File
@@ -13,7 +13,7 @@ class GameUnitConst extends GameUnitConstBase
[],//성벽은 공격할 수 없다. [],//성벽은 공격할 수 없다.
[self::T_FOOTMAN=>1.2], [self::T_FOOTMAN=>1.2],
['성벽입니다.','생성할 수 없습니다.'], ['성벽입니다.','생성할 수 없습니다.'],
null, null, null null, null
], ],
[ [
@@ -23,7 +23,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
['표준적인 보병입니다.','보병은 방어특화이며,','상대가 회피하기 어렵습니다.'], ['표준적인 보병입니다.','보병은 방어특화이며,','상대가 회피하기 어렵습니다.'],
null, null, null null, null
], ],
[ [
@@ -33,7 +33,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2], [self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8], [self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
['표준적인 궁병입니다.','궁병은 회피특화입니다.'], ['표준적인 궁병입니다.','궁병은 회피특화입니다.'],
null, null, null null, null
], ],
[ [
@@ -43,7 +43,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2], [self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8], [self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['표준적인 기병입니다.','기병은 공격특화입니다.'], ['표준적인 기병입니다.','기병은 공격특화입니다.'],
null, null, null null, null
], ],
[ [
@@ -53,7 +53,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
['계략을 사용하는 병종입니다.'], ['계략을 사용하는 병종입니다.'],
null, null, null null, null
], ],
[ [
1405, self::T_WIZARD, '남귀병', 1405, self::T_WIZARD, '남귀병',
@@ -62,7 +62,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
['전투를 포기하고 계략에 몰두합니다.'], ['전투를 포기하고 계략에 몰두합니다.'],
null, null, null null, null
], ],
[ [
@@ -72,7 +72,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>1.8], [self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>1.8],
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2], [self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
['높은 구조물 위에서 공격합니다.'], ['높은 구조물 위에서 공격합니다.'],
['che_성벽부상무효'], null, ['che_성벽선제'] ['che_성벽부상무효'], null
], ],
[ [
1501, self::T_SIEGE, '충차', 1501, self::T_SIEGE, '충차',
@@ -81,7 +81,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>2.4], [self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>2.4],
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2], [self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
['엄청난 위력으로 성벽을 부수어버립니다.'], ['엄청난 위력으로 성벽을 부수어버립니다.'],
['che_성벽부상무효'], null, null ['che_성벽부상무효'], null
] ]
]; ];
} }
+22 -22
View File
@@ -14,7 +14,7 @@ class GameUnitConst extends GameUnitConstBase
[], //성벽은 공격할 수 없다. [], //성벽은 공격할 수 없다.
[self::T_FOOTMAN => 1.2], [self::T_FOOTMAN => 1.2],
['성벽입니다.', '생성할 수 없습니다.'], ['성벽입니다.', '생성할 수 없습니다.'],
null, null, null null, null
], ],
[ [
@@ -24,7 +24,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER => 1.2, self::T_CAVALRY => 0.8, self::T_SIEGE => 1.2], [self::T_ARCHER => 1.2, self::T_CAVALRY => 0.8, self::T_SIEGE => 1.2],
[self::T_ARCHER => 0.8, self::T_CAVALRY => 1.2, self::T_SIEGE => 0.8], [self::T_ARCHER => 0.8, self::T_CAVALRY => 1.2, self::T_SIEGE => 0.8],
['표준적인 보병입니다.', '보병은 방어특화이며,', '상대가 회피하기 어렵습니다.'], ['표준적인 보병입니다.', '보병은 방어특화이며,', '상대가 회피하기 어렵습니다.'],
null, null, null null, null
], ],
[ [
1200, self::T_ARCHER, '궁병', 1200, self::T_ARCHER, '궁병',
@@ -33,7 +33,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_CAVALRY => 1.2, self::T_FOOTMAN => 0.8, self::T_SIEGE => 1.2], [self::T_CAVALRY => 1.2, self::T_FOOTMAN => 0.8, self::T_SIEGE => 1.2],
[self::T_CAVALRY => 0.8, self::T_FOOTMAN => 1.2, self::T_SIEGE => 0.8], [self::T_CAVALRY => 0.8, self::T_FOOTMAN => 1.2, self::T_SIEGE => 0.8],
['표준적인 궁병입니다.', '궁병은 선제사격을 하는 병종입니다.'], ['표준적인 궁병입니다.', '궁병은 선제사격을 하는 병종입니다.'],
null, ['che_선제사격시도', 'che_선제사격발동'], null null, ['che_선제사격시도', 'che_선제사격발동']
], ],
[ [
1300, self::T_CAVALRY, '기병', 1300, self::T_CAVALRY, '기병',
@@ -42,7 +42,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_FOOTMAN => 1.2, self::T_ARCHER => 0.8, self::T_SIEGE => 1.2], [self::T_FOOTMAN => 1.2, self::T_ARCHER => 0.8, self::T_SIEGE => 1.2],
[self::T_FOOTMAN => 0.8, self::T_ARCHER => 1.2, self::T_SIEGE => 0.8], [self::T_FOOTMAN => 0.8, self::T_ARCHER => 1.2, self::T_SIEGE => 0.8],
['표준적인 기병입니다.', '기병은 공격특화입니다.'], ['표준적인 기병입니다.', '기병은 공격특화입니다.'],
null, null, null null, null
], ],
[ [
1104, self::T_FOOTMAN, '근위병', 1104, self::T_FOOTMAN, '근위병',
@@ -51,7 +51,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER => 1.2, self::T_CAVALRY => 0.8, self::T_SIEGE => 1.2], [self::T_ARCHER => 1.2, self::T_CAVALRY => 0.8, self::T_SIEGE => 1.2],
[self::T_ARCHER => 0.8, self::T_CAVALRY => 1.2, self::T_SIEGE => 0.8], [self::T_ARCHER => 0.8, self::T_CAVALRY => 1.2, self::T_SIEGE => 0.8],
['최강의 보병입니다.'], ['최강의 보병입니다.'],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
1106, self::T_FOOTMAN, '백이병', 1106, self::T_FOOTMAN, '백이병',
@@ -60,7 +60,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER => 1.1, self::T_CAVALRY => 0.9, self::T_SIEGE => 1.1], [self::T_ARCHER => 1.1, self::T_CAVALRY => 0.9, self::T_SIEGE => 1.1],
[self::T_ARCHER => 0.9, self::T_CAVALRY => 1.1, self::T_SIEGE => 0.9], [self::T_ARCHER => 0.9, self::T_CAVALRY => 1.1, self::T_SIEGE => 0.9],
['정예 보병입니다. 불리한 싸움도 버텨냅니다.'], ['정예 보병입니다. 불리한 싸움도 버텨냅니다.'],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
97201, self::T_ARCHER, '화랑', 97201, self::T_ARCHER, '화랑',
@@ -69,7 +69,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_CAVALRY => 1.2, self::T_FOOTMAN => 0.9, self::T_SIEGE => 1.2], [self::T_CAVALRY => 1.2, self::T_FOOTMAN => 0.9, self::T_SIEGE => 1.2],
[self::T_CAVALRY => 0.8, self::T_FOOTMAN => 1.1, self::T_SIEGE => 0.8], [self::T_CAVALRY => 0.8, self::T_FOOTMAN => 1.1, self::T_SIEGE => 0.8],
['특수한 궁병입니다.'], ['특수한 궁병입니다.'],
null, ['che_선제사격시도', 'che_선제사격발동'], null null, ['che_선제사격시도', 'che_선제사격발동']
], ],
[ [
1204, self::T_ARCHER, '석궁병', 1204, self::T_ARCHER, '석궁병',
@@ -78,7 +78,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_CAVALRY => 1.2, self::T_FOOTMAN => 0.8, self::T_SIEGE => 1.2], [self::T_CAVALRY => 1.2, self::T_FOOTMAN => 0.8, self::T_SIEGE => 1.2],
[self::T_CAVALRY => 0.8, self::T_FOOTMAN => 1.2, self::T_SIEGE => 0.8], [self::T_CAVALRY => 0.8, self::T_FOOTMAN => 1.2, self::T_SIEGE => 0.8],
['강력한 화살을 쏩니다.'], ['강력한 화살을 쏩니다.'],
null, ['che_선제사격시도', 'che_선제사격발동'], null null, ['che_선제사격시도', 'che_선제사격발동']
], ],
[ [
1303, self::T_CAVALRY, '돌격기병', 1303, self::T_CAVALRY, '돌격기병',
@@ -87,7 +87,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_FOOTMAN => 1.2, self::T_ARCHER => 0.8, self::T_SIEGE => 1.2], [self::T_FOOTMAN => 1.2, self::T_ARCHER => 0.8, self::T_SIEGE => 1.2],
[self::T_FOOTMAN => 0.8, self::T_ARCHER => 1.2, self::T_SIEGE => 0.8], [self::T_FOOTMAN => 0.8, self::T_ARCHER => 1.2, self::T_SIEGE => 0.8],
['저돌적으로 공격합니다.'], ['저돌적으로 공격합니다.'],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
1307, self::T_CAVALRY, '호표기병', 1307, self::T_CAVALRY, '호표기병',
@@ -96,7 +96,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_FOOTMAN => 1.2, self::T_ARCHER => 0.8, self::T_SIEGE => 1.2], [self::T_FOOTMAN => 1.2, self::T_ARCHER => 0.8, self::T_SIEGE => 1.2],
[self::T_FOOTMAN => 0.8, self::T_ARCHER => 1.2, self::T_SIEGE => 0.8], [self::T_FOOTMAN => 0.8, self::T_ARCHER => 1.2, self::T_SIEGE => 0.8],
['정예 기병입니다.'], ['정예 기병입니다.'],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
1306, self::T_CAVALRY, '맹수병', 1306, self::T_CAVALRY, '맹수병',
@@ -105,7 +105,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_FOOTMAN => 1.2, self::T_ARCHER => 0.8, self::T_SIEGE => 1.2], [self::T_FOOTMAN => 1.2, self::T_ARCHER => 0.8, self::T_SIEGE => 1.2],
[self::T_FOOTMAN => 0.8, self::T_ARCHER => 1.2, self::T_SIEGE => 0.8], [self::T_FOOTMAN => 0.8, self::T_ARCHER => 1.2, self::T_SIEGE => 0.8],
['어느 누구보다 강력합니다.'], ['어느 누구보다 강력합니다.'],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
1400, self::T_WIZARD, '귀병', 1400, self::T_WIZARD, '귀병',
@@ -114,7 +114,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE => 1.2], [self::T_SIEGE => 1.2],
[self::T_SIEGE => 0.8], [self::T_SIEGE => 0.8],
['계략을 사용하는 병종입니다.'], ['계략을 사용하는 병종입니다.'],
null, null, null null, null
], ],
[ [
1405, self::T_WIZARD, '남귀병', 1405, self::T_WIZARD, '남귀병',
@@ -123,7 +123,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE => 1.2], [self::T_SIEGE => 1.2],
[self::T_SIEGE => 0.8], [self::T_SIEGE => 0.8],
['전투를 포기하고 계략에 몰두합니다.'], ['전투를 포기하고 계략에 몰두합니다.'],
null, null, null null, null
], ],
[ [
1404, self::T_WIZARD, '악귀병', 1404, self::T_WIZARD, '악귀병',
@@ -132,7 +132,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE => 1.2], [self::T_SIEGE => 1.2],
[self::T_SIEGE => 0.8], [self::T_SIEGE => 0.8],
['백병전에도 능숙합니다.'], ['백병전에도 능숙합니다.'],
null, null, null null, null
], ],
[ [
1407, self::T_WIZARD, '천귀병', 1407, self::T_WIZARD, '천귀병',
@@ -141,7 +141,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE => 1.2], [self::T_SIEGE => 1.2],
[self::T_SIEGE => 0.8], [self::T_SIEGE => 0.8],
['갑주를 두른 귀병입니다.'], ['갑주를 두른 귀병입니다.'],
null, null, null null, null
], ],
[ [
1500, self::T_SIEGE, '정란', 1500, self::T_SIEGE, '정란',
@@ -150,7 +150,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_FOOTMAN => 1.25, self::T_ARCHER => 1.25, self::T_CAVALRY => 1.25, self::T_WIZARD => 1.25, self::T_CASTLE => 1.8, 1106 => 1.112], [self::T_FOOTMAN => 1.25, self::T_ARCHER => 1.25, self::T_CAVALRY => 1.25, self::T_WIZARD => 1.25, self::T_CASTLE => 1.8, 1106 => 1.112],
[self::T_FOOTMAN => 1.2, self::T_ARCHER => 1.2, self::T_CAVALRY => 1.2, self::T_WIZARD => 1.2], [self::T_FOOTMAN => 1.2, self::T_ARCHER => 1.2, self::T_CAVALRY => 1.2, self::T_WIZARD => 1.2],
['높은 구조물 위에서 공격합니다.'], ['높은 구조물 위에서 공격합니다.'],
['che_성벽부상무효'], ['che_선제사격시도', 'che_선제사격발동'], null ['che_성벽부상무효'], ['che_선제사격시도', 'che_선제사격발동']
], ],
[ [
1501, self::T_SIEGE, '충차', 1501, self::T_SIEGE, '충차',
@@ -159,7 +159,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_FOOTMAN => 0.8, self::T_ARCHER => 0.8, self::T_CAVALRY => 0.8, self::T_WIZARD => 0.8, self::T_CASTLE => 2.4], [self::T_FOOTMAN => 0.8, self::T_ARCHER => 0.8, self::T_CAVALRY => 0.8, self::T_WIZARD => 0.8, self::T_CASTLE => 2.4],
[self::T_FOOTMAN => 1.2, self::T_ARCHER => 1.2, self::T_CAVALRY => 1.2, self::T_WIZARD => 1.2], [self::T_FOOTMAN => 1.2, self::T_ARCHER => 1.2, self::T_CAVALRY => 1.2, self::T_WIZARD => 1.2],
['엄청난 위력으로 성벽을 부수어버립니다.'], ['엄청난 위력으로 성벽을 부수어버립니다.'],
['che_성벽부상무효'], null, null ['che_성벽부상무효'], null
], ],
[ [
1502, self::T_SIEGE, '벽력거', 1502, self::T_SIEGE, '벽력거',
@@ -168,7 +168,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_FOOTMAN => 1.25, self::T_ARCHER => 1.25, self::T_CAVALRY => 1.25, self::T_WIZARD => 1.25, self::T_CASTLE => 1.8, 1106 => 1.112], [self::T_FOOTMAN => 1.25, self::T_ARCHER => 1.25, self::T_CAVALRY => 1.25, self::T_WIZARD => 1.25, self::T_CASTLE => 1.8, 1106 => 1.112],
[self::T_FOOTMAN => 0.833, self::T_ARCHER => 0.833, self::T_CAVALRY => 0.833, self::T_WIZARD => 0.833, 1106 => 0.909], [self::T_FOOTMAN => 0.833, self::T_ARCHER => 0.833, self::T_CAVALRY => 0.833, self::T_WIZARD => 0.833, 1106 => 0.909],
['상대에게 돌덩이를 날립니다.'], ['상대에게 돌덩이를 날립니다.'],
['che_성벽부상무효'], ['che_선제사격시도', 'che_선제사격발동'], null ['che_성벽부상무효'], ['che_선제사격시도', 'che_선제사격발동']
], ],
[ [
97101, self::T_FOOTMAN, '중장보병', 97101, self::T_FOOTMAN, '중장보병',
@@ -177,7 +177,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER => 1.2, self::T_CAVALRY => 0.8, self::T_SIEGE => 1.2], [self::T_ARCHER => 1.2, self::T_CAVALRY => 0.8, self::T_SIEGE => 1.2],
[self::T_ARCHER => 0.8, self::T_CAVALRY => 1.2, self::T_SIEGE => 0.8], [self::T_ARCHER => 0.8, self::T_CAVALRY => 1.2, self::T_SIEGE => 0.8],
['전천후 보병입니다.'], ['전천후 보병입니다.'],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
1202, self::T_ARCHER, '연노병', 1202, self::T_ARCHER, '연노병',
@@ -186,7 +186,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_CAVALRY => 1.2, self::T_FOOTMAN => 0.8, self::T_SIEGE => 1.2], [self::T_CAVALRY => 1.2, self::T_FOOTMAN => 0.8, self::T_SIEGE => 1.2],
[self::T_CAVALRY => 0.8, self::T_FOOTMAN => 1.2, self::T_SIEGE => 0.8], [self::T_CAVALRY => 0.8, self::T_FOOTMAN => 1.2, self::T_SIEGE => 0.8],
['화살을 연사합니다.'], ['화살을 연사합니다.'],
null, ['che_선제사격시도', 'che_선제사격발동'], null null, ['che_선제사격시도', 'che_선제사격발동']
], ],
[ [
1304, self::T_CAVALRY, '철기병', 1304, self::T_CAVALRY, '철기병',
@@ -195,7 +195,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_FOOTMAN => 1.2, self::T_ARCHER => 0.8, self::T_SIEGE => 1.2], [self::T_FOOTMAN => 1.2, self::T_ARCHER => 0.8, self::T_SIEGE => 1.2],
[self::T_FOOTMAN => 0.8, self::T_ARCHER => 1.2, self::T_SIEGE => 0.8], [self::T_FOOTMAN => 0.8, self::T_ARCHER => 1.2, self::T_SIEGE => 0.8],
['철갑을 두른 기병입니다.'], ['철갑을 두른 기병입니다.'],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
1401, self::T_WIZARD, '신귀병', 1401, self::T_WIZARD, '신귀병',
@@ -204,7 +204,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE => 1.2], [self::T_SIEGE => 1.2],
[self::T_SIEGE => 0.8], [self::T_SIEGE => 0.8],
['신출귀몰한 귀병입니다.'], ['신출귀몰한 귀병입니다.'],
null, null, null null, null
], ],
]; ];
} }
+46 -46
View File
@@ -21,7 +21,7 @@ class GameUnitConst extends GameUnitConstBase
[],//성벽은 공격할 수 없다. [],//성벽은 공격할 수 없다.
[self::T_FOOTMAN=>1.2], [self::T_FOOTMAN=>1.2],
['성벽입니다.','생성할 수 없습니다.'], ['성벽입니다.','생성할 수 없습니다.'],
null, null, null null, null
], ],
[ [
@@ -31,7 +31,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["표준적인 보병입니다. 보병은 방어특화입니다."], ["표준적인 보병입니다. 보병은 방어특화입니다."],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
217101, self::T_FOOTMAN, '마물병', 217101, self::T_FOOTMAN, '마물병',
@@ -40,7 +40,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["마군 지역 기본병종입니다. 조금더 강하지만 쌀을 많이 소비합니다."], ["마군 지역 기본병종입니다. 조금더 강하지만 쌀을 많이 소비합니다."],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
217102, self::T_FOOTMAN, '중장보병', 217102, self::T_FOOTMAN, '중장보병',
@@ -49,7 +49,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["헬만 특유의 견고한 보병입니다."], ["헬만 특유의 견고한 보병입니다."],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
217103, self::T_FOOTMAN, '흑의 군 보병', 217103, self::T_FOOTMAN, '흑의 군 보병',
@@ -58,7 +58,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["흑의 군 전통의 체계적인 훈련으로 공격력을 보완했습니다."], ["흑의 군 전통의 체계적인 훈련으로 공격력을 보완했습니다."],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
217104, self::T_FOOTMAN, '용병', 217104, self::T_FOOTMAN, '용병',
@@ -67,7 +67,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["일반 보병보다 비싸지만 받은 만큼은 일해줍니다."], ["일반 보병보다 비싸지만 받은 만큼은 일해줍니다."],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
217105, self::T_FOOTMAN, '사메라이', 217105, self::T_FOOTMAN, '사메라이',
@@ -76,7 +76,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["검으로 난무를 가하는 몬스터 보병입니다."], ["검으로 난무를 가하는 몬스터 보병입니다."],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
217106, self::T_FOOTMAN, '템플나이트병', 217106, self::T_FOOTMAN, '템플나이트병',
@@ -85,7 +85,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["공격을 포기하고 오직 방어에만 집중합니다."], ["공격을 포기하고 오직 방어에만 집중합니다."],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
217107, self::T_FOOTMAN, '메이드병', 217107, self::T_FOOTMAN, '메이드병',
@@ -94,7 +94,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["켓셀링크 휘하의 날렵한 전투메이드입니다."], ["켓셀링크 휘하의 날렵한 전투메이드입니다."],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
217108, self::T_FOOTMAN, '요괴병', 217108, self::T_FOOTMAN, '요괴병',
@@ -103,7 +103,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["단단한 육체를 믿고 적진을 돌파합니다."], ["단단한 육체를 믿고 적진을 돌파합니다."],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
217109, self::T_FOOTMAN, '리자스 친위병', 217109, self::T_FOOTMAN, '리자스 친위병',
@@ -112,7 +112,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["여왕을 수호하는 리자스 최강의 보병 정예보병입니다."], ["여왕을 수호하는 리자스 최강의 보병 정예보병입니다."],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
217110, self::T_FOOTMAN, '케이브리스 마물병', 217110, self::T_FOOTMAN, '케이브리스 마물병',
@@ -121,7 +121,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["케이브리스 직속의 마물 정예 전투보병입니다."], ["케이브리스 직속의 마물 정예 전투보병입니다."],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
217111, self::T_FOOTMAN, '투신', 217111, self::T_FOOTMAN, '투신',
@@ -130,7 +130,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["성마교단 유적에서 발굴된 사상 최강의 보병입니다."], ["성마교단 유적에서 발굴된 사상 최강의 보병입니다."],
null, ['che_방어력증가5p'], null null, ['che_방어력증가5p']
], ],
[ [
@@ -140,7 +140,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
["표준적인 궁병입니다. 궁병은 회피특화입니다."], ["표준적인 궁병입니다. 궁병은 회피특화입니다."],
null, null, null null, null
], ],
[ [
217201, self::T_ARCHER, '투척마물병', 217201, self::T_ARCHER, '투척마물병',
@@ -149,7 +149,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
["날렵함을 포기하고 도끼를 투척합니다."], ["날렵함을 포기하고 도끼를 투척합니다."],
null, null, null null, null
], ],
[ [
217202, self::T_ARCHER, '백의 군 궁병', 217202, self::T_ARCHER, '백의 군 궁병',
@@ -158,7 +158,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
["전략을 활용하여 치고 빠지기에 능합니다."], ["전략을 활용하여 치고 빠지기에 능합니다."],
null, null, null null, null
], ],
[ [
217203, self::T_ARCHER, '벌레술사병', 217203, self::T_ARCHER, '벌레술사병',
@@ -167,7 +167,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
["벌레들을 부려 몸을 보호하는 궁병입니다."], ["벌레들을 부려 몸을 보호하는 궁병입니다."],
null, null, null null, null
], ],
[ [
217204, self::T_ARCHER, '저격암살병', 217204, self::T_ARCHER, '저격암살병',
@@ -176,7 +176,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
["독을 바른 탄환으로 적의 목숨을 앗아갑니다."], ["독을 바른 탄환으로 적의 목숨을 앗아갑니다."],
null, null, null null, null
], ],
[ [
217205, self::T_ARCHER, '호루스병', 217205, self::T_ARCHER, '호루스병',
@@ -185,7 +185,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
["민첩하게 파고드는 호루스족 궁병입니다."], ["민첩하게 파고드는 호루스족 궁병입니다."],
null, null, null null, null
], ],
[ [
217206, self::T_ARCHER, '튤립병', 217206, self::T_ARCHER, '튤립병',
@@ -194,7 +194,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
["최첨단병기 튤립으로 적을 폭격합니다."], ["최첨단병기 튤립으로 적을 폭격합니다."],
null, null, null null, null
], ],
[ [
217207, self::T_ARCHER, '아이스플레임 궁병', 217207, self::T_ARCHER, '아이스플레임 궁병',
@@ -203,7 +203,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
["혁명을 성공으로 이끈 정예 게릴라 궁병입니다."], ["혁명을 성공으로 이끈 정예 게릴라 궁병입니다."],
null, null, null null, null
], ],
[ [
217208, self::T_ARCHER, '카라 궁병', 217208, self::T_ARCHER, '카라 궁병',
@@ -212,7 +212,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
["선조의 힘을 이어받은 최강의 카라 정예 궁병입니다."], ["선조의 힘을 이어받은 최강의 카라 정예 궁병입니다."],
null, null, null null, null
], ],
[ [
@@ -222,7 +222,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["표준적인 기동병입니다. 기동병은 공격특화입니다."], ["표준적인 기동병입니다. 기동병은 공격특화입니다."],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
217301, self::T_CAVALRY, '하치온나', 217301, self::T_CAVALRY, '하치온나',
@@ -231,7 +231,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["작은 몸으로 회피하며 따끔한 일격을 먹이는 몬스터 기동병입니다."], ["작은 몸으로 회피하며 따끔한 일격을 먹이는 몬스터 기동병입니다."],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
217302, self::T_CAVALRY, '적의 군 기동병', 217302, self::T_CAVALRY, '적의 군 기동병',
@@ -240,7 +240,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["리자스군의 자랑인 기동부대입니다."], ["리자스군의 자랑인 기동부대입니다."],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
217303, self::T_CAVALRY, '안드로이드 기동병', 217303, self::T_CAVALRY, '안드로이드 기동병',
@@ -249,7 +249,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["파이아르가 개발한 최첨단 안드로이드 기동병입니다."], ["파이아르가 개발한 최첨단 안드로이드 기동병입니다."],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
217304, self::T_CAVALRY, '파란쵸 기동병', 217304, self::T_CAVALRY, '파란쵸 기동병',
@@ -258,7 +258,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["적진을 일점돌파하는 파란쵸왕국의 돌격 기동병입니다. "], ["적진을 일점돌파하는 파란쵸왕국의 돌격 기동병입니다. "],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
217305, self::T_CAVALRY, '비행마물병', 217305, self::T_CAVALRY, '비행마물병',
@@ -267,7 +267,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["비행마물에 올라탄 기동마물병입니다."], ["비행마물에 올라탄 기동마물병입니다."],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
217306, self::T_CAVALRY, '마물조련사병', 217306, self::T_CAVALRY, '마물조련사병',
@@ -276,7 +276,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["무시무시한 몬스터에 올라타서 싸우는 극강의 기동병입니다."], ["무시무시한 몬스터에 올라타서 싸우는 극강의 기동병입니다."],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
217307, self::T_CAVALRY, '기마병', 217307, self::T_CAVALRY, '기마병',
@@ -285,7 +285,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["JAPAN 특유의 기마에 올라타 적을 짓밟는 기동병입니다."], ["JAPAN 특유의 기마에 올라타 적을 짓밟는 기동병입니다."],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
217308, self::T_CAVALRY, '엔젤나이트', 217308, self::T_CAVALRY, '엔젤나이트',
@@ -294,7 +294,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1], [ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1], [ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
["신의 명령으로 파멸을 내리기 위해 강림했습니다."], ["신의 명령으로 파멸을 내리기 위해 강림했습니다."],
null, ['che_기병병종전투'], null null, ['che_기병병종전투']
], ],
[ [
@@ -304,7 +304,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
["마법을 사용하는 병종입니다."], ["마법을 사용하는 병종입니다."],
null, null, null null, null
], ],
[ [
217401, self::T_WIZARD, '마물 마법병', 217401, self::T_WIZARD, '마물 마법병',
@@ -313,7 +313,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
["마군 지역 기본병종입니다. 조금더 강하지만 금을 많이 소비합니다."], ["마군 지역 기본병종입니다. 조금더 강하지만 금을 많이 소비합니다."],
null, null, null null, null
], ],
[ [
217402, self::T_WIZARD, '카라 마법병', 217402, self::T_WIZARD, '카라 마법병',
@@ -322,7 +322,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
["신속히 움직이며 카라의 저주로 적을 공격합니다."], ["신속히 움직이며 카라의 저주로 적을 공격합니다."],
null, null, null null, null
], ],
[ [
217403, self::T_WIZARD, '제스 마법병', 217403, self::T_WIZARD, '제스 마법병',
@@ -331,7 +331,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
["마법국가 제스의 전통있는 마법병입니다."], ["마법국가 제스의 전통있는 마법병입니다."],
null, null, null null, null
], ],
[ [
217404, self::T_WIZARD, '무녀', 217404, self::T_WIZARD, '무녀',
@@ -340,7 +340,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
["신마법과 함께 신통한 춤으로 활력을 불어넣는 마법병입니다."], ["신마법과 함께 신통한 춤으로 활력을 불어넣는 마법병입니다."],
null, null, null null, null
], ],
[ [
217405, self::T_WIZARD, '프로즌', 217405, self::T_WIZARD, '프로즌',
@@ -349,7 +349,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
["백병전에 불리한 연약한 몸으로 마법 사용에 집중하는 몬스터입니다."], ["백병전에 불리한 연약한 몸으로 마법 사용에 집중하는 몬스터입니다."],
null, null, null null, null
], ],
[ [
217406, self::T_WIZARD, '마소한 마법병', 217406, self::T_WIZARD, '마소한 마법병',
@@ -358,7 +358,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
["로브를 여러겹 둘러입은 마물마법병입니다. 직접 전투보단 마법에 집중합니다."], ["로브를 여러겹 둘러입은 마물마법병입니다. 직접 전투보단 마법에 집중합니다."],
null, null, null null, null
], ],
[ [
217407, self::T_WIZARD, '신관병', 217407, self::T_WIZARD, '신관병',
@@ -367,7 +367,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
["AL교의 전투신관입니다. 몸을 보호하는 성스러운 마법을 사용합니다."], ["AL교의 전투신관입니다. 몸을 보호하는 성스러운 마법을 사용합니다."],
null, null, null null, null
], ],
[ [
217408, self::T_WIZARD, '중장마법병', 217408, self::T_WIZARD, '중장마법병',
@@ -376,7 +376,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
["두터운 로브를 입고 불길한 주문을 읊습니다."], ["두터운 로브를 입고 불길한 주문을 읊습니다."],
null, null, null null, null
], ],
[ [
217409, self::T_WIZARD, '악마병', 217409, self::T_WIZARD, '악마병',
@@ -385,7 +385,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
["고대 제스 왕가의 계약에 따라 소환된 흑마법병입니다."], ["고대 제스 왕가의 계약에 따라 소환된 흑마법병입니다."],
null, null, null null, null
], ],
[ [
217410, self::T_WIZARD, '호넷 마물병', 217410, self::T_WIZARD, '호넷 마물병',
@@ -394,7 +394,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
["호넷 직속의 최강 마물 마법병입니다."], ["호넷 직속의 최강 마물 마법병입니다."],
null, null, null null, null
], ],
[ [
217411, self::T_WIZARD, 'Z가디언', 217411, self::T_WIZARD, 'Z가디언',
@@ -403,7 +403,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_SIEGE=>1.2], [self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8], [self::T_SIEGE=>0.8],
["제스의 기술력이 집약된 최고의 마법병기입니다."], ["제스의 기술력이 집약된 최고의 마법병기입니다."],
null, null, null null, null
], ],
[ [
@@ -413,7 +413,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>1.8], [ self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>1.8],
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2], [ self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
["높은 구조물 위에서 공격합니다."], ["높은 구조물 위에서 공격합니다."],
['che_성벽부상무효'], null, null ['che_성벽부상무효'], null
], ],
[ [
217501, self::T_SIEGE, '충차', 217501, self::T_SIEGE, '충차',
@@ -422,7 +422,7 @@ class GameUnitConst extends GameUnitConstBase
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>2.4], [ self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>2.4],
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2], [ self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
["엄청난 위력으로 성벽을 부수어버립니다."], ["엄청난 위력으로 성벽을 부수어버립니다."],
['che_성벽부상무효'], null, null ['che_성벽부상무효'], null
], ],
[ [
217502, self::T_SIEGE, '튤립3호', 217502, self::T_SIEGE, '튤립3호',
@@ -431,7 +431,7 @@ class GameUnitConst extends GameUnitConstBase
[ ], [ ],
[ ], [ ],
["파괴적인 위력과 정말 파괴적인 비용을 자랑하는 전차입니다. "], ["파괴적인 위력과 정말 파괴적인 비용을 자랑하는 전차입니다. "],
['che_성벽부상무효'], null, null ['che_성벽부상무효'], null
], ],
+10 -10
View File
@@ -13,7 +13,7 @@ class GameUnitConst extends GameUnitConstBase
[],//성벽은 공격할 수 없다. [],//성벽은 공격할 수 없다.
[self::T_FOOTMAN=>1.2], [self::T_FOOTMAN=>1.2],
['성벽입니다.','생성할 수 없습니다.'], ['성벽입니다.','생성할 수 없습니다.'],
null, null, null null, null
], ],
[ [
1100, self::T_FOOTMAN, '보병', 1100, self::T_FOOTMAN, '보병',
@@ -22,7 +22,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8], [self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2], [self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2],
['표준적인 보병입니다.','보병은 방어특화이며,','상대가 회피하기 어렵습니다.'], ['표준적인 보병입니다.','보병은 방어특화이며,','상대가 회피하기 어렵습니다.'],
null, null, null null, null
], ],
[ [
@@ -32,7 +32,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8], [self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8],
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2], [self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2],
['표준적인 궁병입니다.','궁병은 회피특화입니다.'], ['표준적인 궁병입니다.','궁병은 회피특화입니다.'],
null, null, null null, null
], ],
[ [
@@ -42,7 +42,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8], [self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2], [self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2],
['표준적인 기병입니다.','기병은 공격특화입니다.'], ['표준적인 기병입니다.','기병은 공격특화입니다.'],
null, null, null null, null
], ],
[ [
@@ -52,7 +52,7 @@ class GameUnitConst extends GameUnitConstBase
[], [],
[], [],
['계략을 사용하는 병종입니다.'], ['계략을 사용하는 병종입니다.'],
null, null, null null, null
], ],
[ [
1405, self::T_WIZARD, '남귀병', 1405, self::T_WIZARD, '남귀병',
@@ -61,7 +61,7 @@ class GameUnitConst extends GameUnitConstBase
[], [],
[], [],
['전투를 포기하고 계략에 몰두합니다.'], ['전투를 포기하고 계략에 몰두합니다.'],
null, null, null null, null
], ],
[ [
@@ -71,7 +71,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_CASTLE=>1.8], [self::T_CASTLE=>1.8],
[], [],
['높은 구조물 위에서 공격합니다.'], ['높은 구조물 위에서 공격합니다.'],
['che_성벽부상무효'], null, null ['che_성벽부상무효'], null
], ],
[ [
1501, self::T_SIEGE, '충차', 1501, self::T_SIEGE, '충차',
@@ -80,7 +80,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_CASTLE=>2.4], [self::T_CASTLE=>2.4],
[], [],
['엄청난 위력으로 성벽을 부수어버립니다.'], ['엄청난 위력으로 성벽을 부수어버립니다.'],
['che_성벽부상무효'], null, null ['che_성벽부상무효'], null
], ],
[ [
1502, self::T_SIEGE, '벽력거', 1502, self::T_SIEGE, '벽력거',
@@ -89,7 +89,7 @@ class GameUnitConst extends GameUnitConstBase
[self::T_CASTLE=>1.8], [self::T_CASTLE=>1.8],
[], [],
['상대에게 돌덩이를 날립니다.'], ['상대에게 돌덩이를 날립니다.'],
['che_성벽부상무효'], null, null ['che_성벽부상무효'], null
], ],
[ [
1503, self::T_SIEGE, '목우', 1503, self::T_SIEGE, '목우',
@@ -98,7 +98,7 @@ class GameUnitConst extends GameUnitConstBase
[], [],
[], [],
['상대를 저지하는 특수병기입니다.'], ['상대를 저지하는 특수병기입니다.'],
['che_성벽부상무효'], null, null ['che_성벽부상무효'], null
] ]
]; ];
} }
+6
View File
@@ -1,5 +1,11 @@
@charset 'utf-8'; @charset 'utf-8';
.map_title_tooltiptext .tooltip-inner {
max-width: 220px;
width: 220px;
text-align: left;
}
.map_title_text { .map_title_text {
margin: auto; margin: auto;
text-align: center; text-align: center;
+4 -8
View File
@@ -130,12 +130,12 @@ const targetGeneralLogs = ref<GeneralLogs>();
const nationInfo = ref<NationStaticItem>(); const nationInfo = ref<NationStaticItem>();
watch([generalList, targetGeneralID], async ([generalList, generalID]) => { watch([generalList, targetGeneralID], async ([generalList, targetGeneralID]) => {
if (!generalID) { if (targetGeneralID === undefined) {
targetGeneral.value = undefined; targetGeneral.value = undefined;
return; return;
} }
targetGeneral.value = generalList.get(generalID); targetGeneral.value = generalList.get(targetGeneralID);
const logs: GeneralLogs = { const logs: GeneralLogs = {
generalHistory: new Map(), generalHistory: new Map(),
@@ -148,12 +148,8 @@ watch([generalList, targetGeneralID], async ([generalList, generalID]) => {
for (const reqType of ["generalHistory", "battleResult", "battleDetail", "generalAction"] as const) { for (const reqType of ["generalHistory", "battleResult", "battleDetail", "generalAction"] as const) {
waiter.push( waiter.push(
SammoAPI.Nation.GetGeneralLog({ generalID: generalID, reqType }).then( SammoAPI.Nation.GetGeneralLog({ generalID: targetGeneralID, reqType }).then(
(res) => { (res) => {
if(res.generalID !== targetGeneralID.value){
return;
}
const rawLogs: [number, string][] = Object.entries(res.log).map(([key, value]) => [ const rawLogs: [number, string][] = Object.entries(res.log).map(([key, value]) => [
Number(key), Number(key),
formatLog(value), formatLog(value),
+17
View File
@@ -0,0 +1,17 @@
<template>
<div>
<div>도시 정보</div>
<div>{{cityID}}</div>
</div>
</template>
<script lang="ts">
</script>
<script lang="ts" setup>
import { toRef } from 'vue';
const props = defineProps<{
cityID?: number
}>()
const cityID = toRef(props, 'cityID');
</script>
+1
View File
@@ -27,6 +27,7 @@
"v_board": "v_board.ts", "v_board": "v_board.ts",
"v_cachedMap": "v_cachedMap", "v_cachedMap": "v_cachedMap",
"v_chiefCenter": "v_chiefCenter.ts", "v_chiefCenter": "v_chiefCenter.ts",
"v_cityInfo": "v_cityInfo.ts",
"v_NPCControl": "v_NPCControl.ts", "v_NPCControl": "v_NPCControl.ts",
"v_join": "v_join.ts", "v_join": "v_join.ts",
"v_main": "v_main.ts", "v_main": "v_main.ts",
+1 -1
View File
@@ -37,7 +37,7 @@
<span style="color: cyan">NPC {{ createdNPCCnt.toLocaleString() }} </span> <span style="color: cyan">NPC {{ createdNPCCnt.toLocaleString() }} </span>
</div> </div>
<div class="s-border-t py-2 col col-6 col-md-4 subTournamentState"> <div class="s-border-t py-2 col col-6 col-md-4 subTournamentState">
<span v-if="frontInfo.global.isTournamentActive"> <span v-if="frontInfo.global.tournamentType">
<a v-if="tournamentStep.availableJoin" href="b_tournament.php" target="_blank"> <a v-if="tournamentStep.availableJoin" href="b_tournament.php" target="_blank">
<span style="color: cyan" <span style="color: cyan"
>{{ formatTournamentType(frontInfo.global.tournamentType) }} >{{ formatTournamentType(frontInfo.global.tournamentType) }}
+3 -4
View File
@@ -80,7 +80,7 @@ import type { GeneralListItem, GeneralListItemP1, GeneralListItemP2, GeneralList
import { getIconPath } from "@/util/getIconPath"; import { getIconPath } from "@/util/getIconPath";
import { inject, ref, watch, type PropType, type Ref, type StyleValue } from "vue"; import { inject, ref, watch, type PropType, type Ref, type StyleValue } from "vue";
import { AgGridVue } from "ag-grid-vue3"; import { AgGridVue } from "ag-grid-vue3";
import { import type {
Column, Column,
CellClassParams, CellClassParams,
CellStyle, CellStyle,
@@ -92,7 +92,6 @@ import {
GridReadyEvent, GridReadyEvent,
CellClickedEvent, CellClickedEvent,
IRowNode, IRowNode,
NumberFilter,
} from "ag-grid-community"; } from "ag-grid-community";
import { ProvidedColumnGroup } from "ag-grid-community"; import { ProvidedColumnGroup } from "ag-grid-community";
import { getNPCColor } from "@/utilGame"; import { getNPCColor } from "@/utilGame";
@@ -484,7 +483,7 @@ const sortableNumber: Omit<GenColDef, "colId" | "headerName"> = {
sortable: true, sortable: true,
comparator: (a, b, _a, _b, _desc) => a - b, comparator: (a, b, _a, _b, _desc) => a - b,
sortingOrder: ["desc", "asc", null], sortingOrder: ["desc", "asc", null],
filter: NumberFilter, filter: "number",
cellClass: rightAlignClass, cellClass: rightAlignClass,
}; };
const defaultColDef = ref<ColDef>({ const defaultColDef = ref<ColDef>({
@@ -670,7 +669,7 @@ const columnRawDefs = ref<Partial<Record<headerType, GenColDef | GenColGroupDef>
return (_a.data?.dedlevel??0) - (_b.data?.dedlevel??0); return (_a.data?.dedlevel??0) - (_b.data?.dedlevel??0);
}, },
sortingOrder: ["desc", "asc", null], sortingOrder: ["desc", "asc", null],
filter: true, filter: "text",
cellClass: centerCellClass, cellClass: centerCellClass,
columnGroupShow: "open", columnGroupShow: "open",
}, },
+8 -5
View File
@@ -13,9 +13,11 @@
]" ]"
> >
<div <div
v-b-tooltip.hover.top="titleTooltip" v-my-tooltip.hover.top="{
:title="titleTooltip" class: 'map_title_tooltiptext',
}"
class="map_title" class="map_title"
:title="getTitleTooltip()"
> >
<!-- eslint-disable-next-line vue/max-attributes-per-line --> <!-- eslint-disable-next-line vue/max-attributes-per-line -->
<span class="map_title_text" :style="{ color: getTitleColor() }" <span class="map_title_text" :style="{ color: getTitleColor() }"
@@ -163,11 +165,12 @@ export type CityPositionMap = {
</script> </script>
<script lang="ts" setup> <script lang="ts" setup>
import "@/../scss/map.scss"; import "@/../scss/map.scss";
import { type PropType, toRef, inject, type Ref, ref, watch, type ComponentPublicInstance, computed } from "vue"; import { type PropType, toRef, inject, type Ref, ref, watch, type ComponentPublicInstance } from "vue";
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import { CURRENT_MAP_VERSION, type MapResult } from "@/defs"; import { CURRENT_MAP_VERSION, type MapResult } from "@/defs";
import { joinYearMonth } from "@/util/joinYearMonth"; import { joinYearMonth } from "@/util/joinYearMonth";
import { parseYearMonth } from "@/util/parseYearMonth"; import { parseYearMonth } from "@/util/parseYearMonth";
import vMyTooltip from "@/directives/vMyTooltip";
import type { GameConstStore } from "@/GameConstStore"; import type { GameConstStore } from "@/GameConstStore";
import { unwrap_err } from "@/util/unwrap_err"; import { unwrap_err } from "@/util/unwrap_err";
import { getMaxRelativeTechLevel, TECH_LEVEL_YEAR_GAP } from "@/utilGame/techLevel"; import { getMaxRelativeTechLevel, TECH_LEVEL_YEAR_GAP } from "@/utilGame/techLevel";
@@ -279,7 +282,7 @@ function getBeginGameLimitTooltip(): string | undefined {
return `초반제한 기간 : ${remainYear}${remainMonth > 0 ? ` ${remainMonth}개월` : ""} (${startYear + 3}년)`; return `초반제한 기간 : ${remainYear}${remainMonth > 0 ? ` ${remainMonth}개월` : ""} (${startYear + 3}년)`;
} }
const titleTooltip = computed(()=>{ function getTitleTooltip(): string {
const result: string[] = []; const result: string[] = [];
const beginLimit = getBeginGameLimitTooltip(); const beginLimit = getBeginGameLimitTooltip();
if (beginLimit) { if (beginLimit) {
@@ -299,7 +302,7 @@ const titleTooltip = computed(()=>{
} }
return result.join("<br>"); return result.join("<br>");
}); }
function getMapSeasonClassName(): string { function getMapSeasonClassName(): string {
const { month } = mapData.value; const { month } = mapData.value;
+97
View File
@@ -0,0 +1,97 @@
import type { Directive, DirectiveBinding } from 'vue'
import Tooltip from 'bootstrap/js/dist/tooltip'
function resolveTrigger(modifiers: DirectiveBinding['modifiers']): Tooltip.Options['trigger'] {
if (modifiers.manual) {
return 'manual'
}
const trigger: string[] = []
if (modifiers.click) {
trigger.push('click')
}
if (modifiers.hover) {
trigger.push('hover')
}
if (modifiers.focus) {
trigger.push('focus')
}
if (trigger.length > 0) {
return trigger.join(' ') as Tooltip.Options['trigger']
}
return 'hover focus'
}
function resolvePlacement(modifiers: DirectiveBinding['modifiers']): Tooltip.Options['placement'] {
if (modifiers.left) {
return 'left'
}
if (modifiers.right) {
return 'right'
}
if (modifiers.bottom) {
return 'bottom'
}
return 'top'
}
function resolveDelay(values: TooltipOptions): Tooltip.Options['delay'] {
if (values?.delay) {
return values.delay
}
return 0
}
type TooltipOptions = {
delay?: number,
class?: string
} | undefined;
const vMyTooltip: Directive<HTMLElement, TooltipOptions> = {
beforeMount(el, binding) {
el.setAttribute('data-bs-toogle', 'tooltip')
const isHtml = /<("[^"]*"|'[^']*'|[^'">])*>/.test(el.title)
const trigger = resolveTrigger(binding.modifiers)
const placement = resolvePlacement(binding.modifiers)
const delay = resolveDelay(binding.value)
const options: Partial<Tooltip.Options> = {
trigger,
placement,
delay,
html: isHtml,
}
const customClass = binding.value?.class;
if (customClass) {
options.customClass = customClass;
}
new Tooltip(el, options)
},
updated(el) {
const title = el.getAttribute('title')
if (title !== '') {
const instance = Tooltip.getInstance(el)
instance?.hide()
el.setAttribute('data-bs-original-title', title || '')
el.setAttribute('title', '')
}
},
unmounted(el) {
const instance = Tooltip.getInstance(el)
instance?.dispose()
},
}
export default vMyTooltip
+16
View File
@@ -0,0 +1,16 @@
import { createApp } from 'vue'
import { auto500px } from './util/auto500px';
import { htmlReady } from './util/htmlReady';
import { insertCustomCSS } from './util/customCSS';
import PageCityInfo from './PageCityInfo.vue';
import { installVue3Components } from './util/installVue3Components';
auto500px();
declare const query: {
cityID?: number
};
htmlReady(() => {
insertCustomCSS();
});
installVue3Components(createApp(PageCityInfo, query)).mount('#app');
+43
View File
@@ -0,0 +1,43 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$session = Session::requireGameLogin()->setReadOnly();
$cityID = Util::getReq('cityID', 'int');
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" />
<title><?= UniqueConst::$serverName ?>: 도시 정보</title>
<?= WebUtil::printStaticValues([
'staticValues' => [
'serverName' => UniqueConst::$serverName,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'mapName' => GameConst::$mapName,
'unitSet' => GameConst::$unitSet,
],
'query' => [
'cityID' => $cityID,
]
], false) ?>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('vue', 'v_cityInfo', true) ?>
</head>
<body>
<div id="app"></div>
</body>
</html>
+1 -1
View File
@@ -193,7 +193,7 @@ class KakaoUtil
$refreshTokenValidUntil = TimeUtil::nowAddSeconds($refreshResult['refresh_token_expires_in']); $refreshTokenValidUntil = TimeUtil::nowAddSeconds($refreshResult['refresh_token_expires_in']);
$oauthInfo['refreshToken'] = $refreshToken; $oauthInfo['refreshToken'] = $refreshToken;
$oauthInfo['refreshTokenValidUntil'] = $refreshTokenValidUntil; $oauthInfo['refresh_token_expires_in'] = $refreshTokenValidUntil;
} }
RootDB::db()->update('member', [ RootDB::db()->update('member', [