버그 수정 시도2

This commit is contained in:
2020-06-02 01:06:00 +09:00
parent bd66871b0e
commit b9664dc710
+1138 -1137
View File
@@ -1,1138 +1,1139 @@
<?php <?php
namespace sammo; namespace sammo;
use sammo\Command\GeneralCommand; use sammo\Command\GeneralCommand;
use sammo\WarUnitTrigger as WarUnitTrigger; use sammo\WarUnitTrigger as WarUnitTrigger;
class General implements iAction{ class General implements iAction{
use LazyVarUpdater; use LazyVarUpdater;
protected $raw = []; protected $raw = [];
protected $rawCity = null; protected $rawCity = null;
protected $rankVarRead = []; protected $rankVarRead = [];
protected $rankVarIncrease = []; protected $rankVarIncrease = [];
protected $rankVarSet = []; protected $rankVarSet = [];
/** @var \sammo\ActionLogger */ /** @var \sammo\ActionLogger */
protected $logger; protected $logger;
protected $activatedSkill = []; protected $activatedSkill = [];
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 = [];
protected $lastTurn = null; protected $lastTurn = null;
protected $resultTurn = null; protected $resultTurn = null;
const RANK_COLUMN = [ const RANK_COLUMN = [
'firenum'=>1, 'warnum'=>1, 'killnum'=>1, 'deathnum'=>1, 'killcrew'=>1, 'deathcrew'=>1, 'firenum'=>1, 'warnum'=>1, 'killnum'=>1, 'deathnum'=>1, 'killcrew'=>1, 'deathcrew'=>1,
'ttw'=>1, 'ttd'=>1, 'ttl'=>1, 'ttg'=>1, 'ttp'=>1, 'ttw'=>1, 'ttd'=>1, 'ttl'=>1, 'ttg'=>1, 'ttp'=>1,
'tlw'=>1, 'tld'=>1, 'tll'=>1, 'tlg'=>1, 'tlp'=>1, 'tlw'=>1, 'tld'=>1, 'tll'=>1, 'tlg'=>1, 'tlp'=>1,
'tsw'=>1, 'tsd'=>1, 'tsl'=>1, 'tsg'=>1, 'tsp'=>1, 'tsw'=>1, 'tsd'=>1, 'tsl'=>1, 'tsg'=>1, 'tsp'=>1,
'tiw'=>1, 'tid'=>1, 'til'=>1, 'tig'=>1, 'tip'=>1, 'tiw'=>1, 'tid'=>1, 'til'=>1, 'tig'=>1, 'tip'=>1,
'betwin'=>1, 'betgold'=>1, 'betwingold'=>1, 'betwin'=>1, 'betgold'=>1, 'betwingold'=>1,
'killcrew_person'=>1, 'deathcrew_person'=>1, 'killcrew_person'=>1, 'deathcrew_person'=>1,
'occupied'=>1, 'occupied'=>1,
]; ];
const TURNTIME_FULL_MS = -1; const TURNTIME_FULL_MS = -1;
const TURNTIME_FULL = 0; const TURNTIME_FULL = 0;
const TURNTIME_HMS = 1; const TURNTIME_HMS = 1;
const TURNTIME_HM = 2; const TURNTIME_HM = 2;
protected $calcCache = []; protected $calcCache = [];
protected static $prohibitedDirectUpdateVars = [ protected static $prohibitedDirectUpdateVars = [
//Reason: iAction //Reason: iAction
'leadership'=>1, 'leadership'=>1,
'power'=>1, 'power'=>1,
'intel'=>1, 'intel'=>1,
'nation'=>2, 'nation'=>2,
'officer_level'=>1, 'officer_level'=>1,
//NOTE: officerLevelObj로 인해 국가의 '레벨'이 바뀌는 것도 조심해야 하나, 국가 레벨의 변경은 월 초/말에만 일어남. //NOTE: officerLevelObj로 인해 국가의 '레벨'이 바뀌는 것도 조심해야 하나, 국가 레벨의 변경은 월 초/말에만 일어남.
'special'=>1, 'special'=>1,
'special2'=>1, 'special2'=>1,
'personal'=>1, 'personal'=>1,
'horse'=>1, 'horse'=>1,
'weapon'=>1, 'weapon'=>1,
'book'=>1, 'book'=>1,
'item'=>1 'item'=>1
]; ];
/** /**
* @param array $raw DB row값. * @param array $raw DB row값.
* @param null|array $city DB city 테이블의 row값 * @param null|array $city DB city 테이블의 row값
* @param int|null $year 게임 연도 * @param int|null $year 게임 연도
* @param int|null $month 게임 월 * @param int|null $month 게임 월
* @param bool $fullConstruct iAction, 및 ActionLogger 초기화 여부, false인 경우 no, name, city, nation, officer_level 정도로 초기화 가능 * @param bool $fullConstruct iAction, 및 ActionLogger 초기화 여부, false인 경우 no, name, city, nation, officer_level 정도로 초기화 가능
*/ */
public function __construct(array $raw, ?array $rawRank, ?array $city, ?array $nation, ?int $year, ?int $month, bool $fullConstruct=true){ public function __construct(array $raw, ?array $rawRank, ?array $city, ?array $nation, ?int $year, ?int $month, bool $fullConstruct=true){
//TODO: 밖에서 가져오도록 하면 버그 확률이 높아짐. 필요한 raw 값을 직접 구해야함. //TODO: 밖에서 가져오도록 하면 버그 확률이 높아짐. 필요한 raw 값을 직접 구해야함.
if($nation === null){ if($nation === null){
$nation = getNationStaticInfo($raw['nation']); $nation = getNationStaticInfo($raw['nation']);
} }
$this->raw = $raw; $this->raw = $raw;
$this->rawCity = $city; $this->rawCity = $city;
if(key_exists('last_turn', $this->raw)){ $this->resultTurn = new LastTurn();
$this->lastTurn = LastTurn::fromJson($this->raw['last_turn']); if(key_exists('last_turn', $this->raw)){
} $this->lastTurn = LastTurn::fromJson($this->raw['last_turn']);
$this->resultTurn = new LastTurn(); $this->resultTurn = $this->lastTurn->duplicate();
}
if($year !== null && $month !== null){
$this->initLogger($year, $month); if($year !== null && $month !== null){
} $this->initLogger($year, $month);
}
if($rawRank){
$this->rankVarRead = $rawRank; if($rawRank){
} $this->rankVarRead = $rawRank;
}
if(!$fullConstruct){
return; if(!$fullConstruct){
} return;
}
$this->nationType = buildNationTypeClass($nation['type']);
$this->officerLevelObj = new TriggerOfficerLevel($this->raw, $nation['level']); $this->nationType = buildNationTypeClass($nation['type']);
$this->officerLevelObj = new TriggerOfficerLevel($this->raw, $nation['level']);
$this->specialDomesticObj = buildGeneralSpecialDomesticClass($raw['special']);
$this->specialWarObj = buildGeneralSpecialWarClass($raw['special2']); $this->specialDomesticObj = buildGeneralSpecialDomesticClass($raw['special']);
$this->specialWarObj = buildGeneralSpecialWarClass($raw['special2']);
$this->personalityObj = buildPersonalityClass($raw['personal']);
$this->personalityObj = buildPersonalityClass($raw['personal']);
$this->itemObjs['horse'] = buildItemClass($raw['horse']);
$this->itemObjs['weapon'] = buildItemClass($raw['weapon']); $this->itemObjs['horse'] = buildItemClass($raw['horse']);
$this->itemObjs['book'] = buildItemClass($raw['book']); $this->itemObjs['weapon'] = buildItemClass($raw['weapon']);
$this->itemObjs['item'] = buildItemClass($raw['item']); $this->itemObjs['book'] = buildItemClass($raw['book']);
} $this->itemObjs['item'] = buildItemClass($raw['item']);
}
function initLogger(int $year, int $month){
$this->logger = new ActionLogger( function initLogger(int $year, int $month){
$this->getVar('no'), $this->logger = new ActionLogger(
$this->getVar('nation'), $this->getVar('no'),
$year, $this->getVar('nation'),
$month, $year,
false $month,
); false
} );
}
function getTurnTime(int $short=self::TURNTIME_FULL_MS){
return [ function getTurnTime(int $short=self::TURNTIME_FULL_MS){
self::TURNTIME_FULL_MS=>function($turntime){return $turntime;}, return [
self::TURNTIME_FULL=>function($turntime){return substr($turntime, 0, 19);}, self::TURNTIME_FULL_MS=>function($turntime){return $turntime;},
self::TURNTIME_HMS=>function($turntime){return substr($turntime, 11, 8);}, self::TURNTIME_FULL=>function($turntime){return substr($turntime, 0, 19);},
self::TURNTIME_HM=>function($turntime){return substr($turntime, 11, 5);}, self::TURNTIME_HMS=>function($turntime){return substr($turntime, 11, 8);},
][$short]($this->getVar('turntime')); self::TURNTIME_HM=>function($turntime){return substr($turntime, 11, 5);},
} ][$short]($this->getVar('turntime'));
}
function setItem(string $itemKey='item', ?string $itemCode){
if($itemCode === null){ function setItem(string $itemKey='item', ?string $itemCode){
$this->deleteItem($itemKey); if($itemCode === null){
} $this->deleteItem($itemKey);
}
$this->setVar($itemKey, $itemCode);
$this->itemObjs[$itemKey] = buildItemClass($itemCode); $this->setVar($itemKey, $itemCode);
} $this->itemObjs[$itemKey] = buildItemClass($itemCode);
}
function deleteItem(string $itemKey='item'){
$this->setVar($itemKey, 'None'); function deleteItem(string $itemKey='item'){
$this->itemObjs[$itemKey] = new ActionItem\None(); $this->setVar($itemKey, 'None');
} $this->itemObjs[$itemKey] = new ActionItem\None();
}
function getItem(string $itemKey='item'):BaseItem{
return $this->itemObjs[$itemKey]; function getItem(string $itemKey='item'):BaseItem{
} return $this->itemObjs[$itemKey];
}
function getNPCType():int{
return $this->raw['npc']; function getNPCType():int{
} return $this->raw['npc'];
}
/** @return BaseItem[] */
function getItems():array{ /** @return BaseItem[] */
return $this->itemObjs; function getItems():array{
} return $this->itemObjs;
}
function getPersonality():iAction{
return $this->personalityObj; function getPersonality():iAction{
} return $this->personalityObj;
}
function getSpecialDomestic():iAction{
return $this->specialDomesticObj; function getSpecialDomestic():iAction{
} return $this->specialDomesticObj;
}
function getSpecialWar():iAction{
return $this->specialWarObj; function getSpecialWar():iAction{
} return $this->specialWarObj;
}
function getLastTurn():LastTurn{
return $this->lastTurn; function getLastTurn():LastTurn{
} return $this->lastTurn;
}
function _setResultTurn(LastTurn $resultTurn){
$this->resultTurn = $resultTurn; function _setResultTurn(LastTurn $resultTurn){
} $this->resultTurn = $resultTurn;
}
function getResultTurn():LastTurn{
return $this->resultTurn; function getResultTurn():LastTurn{
} return $this->resultTurn;
}
function clearActivatedSkill(){
foreach ($this->activatedSkill as $skillName=>$state) { function clearActivatedSkill(){
if (!$state) { foreach ($this->activatedSkill as $skillName=>$state) {
continue; if (!$state) {
} continue;
}
if (!key_exists($skillName, $this->logActivatedSkill)) {
$this->logActivatedSkill[$skillName] = 1; if (!key_exists($skillName, $this->logActivatedSkill)) {
} else { $this->logActivatedSkill[$skillName] = 1;
$this->logActivatedSkill[$skillName] += 1; } else {
} $this->logActivatedSkill[$skillName] += 1;
} }
$this->activatedSkill = []; }
} $this->activatedSkill = [];
}
function getActivatedSkillLog():array{
return $this->logActivatedSkill; function getActivatedSkillLog():array{
} return $this->logActivatedSkill;
}
function hasActivatedSkill(string $skillName):bool{
return $this->activatedSkill[$skillName] ?? false; function hasActivatedSkill(string $skillName):bool{
} return $this->activatedSkill[$skillName] ?? false;
}
function activateSkill(... $skillNames){
foreach($skillNames as $skillName){ function activateSkill(... $skillNames){
$this->activatedSkill[$skillName] = true; foreach($skillNames as $skillName){
} $this->activatedSkill[$skillName] = true;
} }
}
function deactivateSkill(... $skillNames){
foreach($skillNames as $skillName){ function deactivateSkill(... $skillNames){
$this->activatedSkill[$skillName] = false; foreach($skillNames as $skillName){
} $this->activatedSkill[$skillName] = false;
} }
}
function getName():string{
return $this->raw['name']; function getName():string{
} return $this->raw['name'];
}
function getInfo():string{
//iAction용 info로는 적절하지 않음 function getInfo():string{
return ''; //iAction용 info로는 적절하지 않음
} return '';
}
function getID():int{
return $this->raw['no']; function getID():int{
} return $this->raw['no'];
}
function getRawCity():?array{
return $this->rawCity; function getRawCity():?array{
} return $this->rawCity;
}
function setRawCity(?array $city){
$this->rawCity = $city; function setRawCity(?array $city){
} $this->rawCity = $city;
}
function getCityID():int{
return $this->raw['city']; function getCityID():int{
} return $this->raw['city'];
}
function getNationID():int{
return $this->raw['nation']; function getNationID():int{
} return $this->raw['nation'];
}
function getStaticNation():array{
return getNationStaticInfo($this->raw['nation']); function getStaticNation():array{
} return getNationStaticInfo($this->raw['nation']);
}
function getLogger():?ActionLogger{
return $this->logger; function getLogger():?ActionLogger{
} return $this->logger;
}
public function getNationTypeObj():iAction{
return $this->nationType; public function getNationTypeObj():iAction{
} return $this->nationType;
}
public function getOfficerLevelObj():iAction{
return $this->officerLevelObj; public function getOfficerLevelObj():iAction{
} return $this->officerLevelObj;
}
function getCrewTypeObj():GameUnitDetail{
$crewType = GameUnitConst::byID($this->getVar('crewtype')); function getCrewTypeObj():GameUnitDetail{
if($crewType === null){ $crewType = GameUnitConst::byID($this->getVar('crewtype'));
throw new \InvalidArgumentException('Invalid CrewType:'.$this->getVar('crewtype')); if($crewType === null){
} throw new \InvalidArgumentException('Invalid CrewType:'.$this->getVar('crewtype'));
return $crewType; }
} return $crewType;
}
function calcRecentWarTurn(int $turnTerm):int{
$cacheKey = "recent_war_turn_{$turnTerm}"; function calcRecentWarTurn(int $turnTerm):int{
if(key_exists($cacheKey, $this->calcCache)){ $cacheKey = "recent_war_turn_{$turnTerm}";
return $this->calcCache[$cacheKey]; if(key_exists($cacheKey, $this->calcCache)){
} return $this->calcCache[$cacheKey];
if(!$this->getVar('recent_war')){ }
$result = 12*1000; if(!$this->getVar('recent_war')){
$this->calcCache[$cacheKey] = $result; $result = 12*1000;
return $result; $this->calcCache[$cacheKey] = $result;
} return $result;
$recwar = new \DateTimeImmutable($this->getVar('recent_war')); }
$turnNow = new \DateTimeImmutable($this->getVar('turntime')); $recwar = new \DateTimeImmutable($this->getVar('recent_war'));
$secDiff = TimeUtil::DateIntervalToSeconds($recwar->diff($turnNow)); $turnNow = new \DateTimeImmutable($this->getVar('turntime'));
$secDiff = TimeUtil::DateIntervalToSeconds($recwar->diff($turnNow));
if($secDiff <= 0){
$this->calcCache[$cacheKey] = 0; if($secDiff <= 0){
return 0; $this->calcCache[$cacheKey] = 0;
} return 0;
}
$result = intdiv(Util::toInt($secDiff), 60 * $turnTerm);
$this->calcCache[$cacheKey] = $result; $result = intdiv(Util::toInt($secDiff), 60 * $turnTerm);
return $result; $this->calcCache[$cacheKey] = $result;
} return $result;
}
function getReservedTurn(int $turnIdx, array $env):GeneralCommand{
$db = DB::db(); function getReservedTurn(int $turnIdx, array $env):GeneralCommand{
$rawCmd = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id = %i AND turn_idx = %i', $this->getID(), $turnIdx); $db = DB::db();
if(!$rawCmd){ $rawCmd = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id = %i AND turn_idx = %i', $this->getID(), $turnIdx);
return buildGeneralCommandClass(null, $this, $env); if(!$rawCmd){
} return buildGeneralCommandClass(null, $this, $env);
return buildGeneralCommandClass($rawCmd['action'], $this, $env, Json::decode($rawCmd['arg']??null)); }
} return buildGeneralCommandClass($rawCmd['action'], $this, $env, Json::decode($rawCmd['arg']??null));
}
/**
* @param General[] $generalList /**
* @param int $turnIdxFrom [$turnIdxFrom, $turnIdxTo) * @param General[] $generalList
* @param int $turnIdxTo [$turnIdxFrom, $turnIdxTo) * @param int $turnIdxFrom [$turnIdxFrom, $turnIdxTo)
* @param array $env * @param int $turnIdxTo [$turnIdxFrom, $turnIdxTo)
* @return GeneralCommand[] * @param array $env
*/ * @return GeneralCommand[]
public function getReservedTurnList(int $turnIdxFrom, int $turnIdxTo, array $env){ */
if($turnIdxFrom < 0 || $turnIdxFrom >= GameConst::$maxTurn){ public function getReservedTurnList(int $turnIdxFrom, int $turnIdxTo, array $env){
throw new \OutOfRangeException('$turnIdxFrom 범위 초과'.$turnIdxFrom); if($turnIdxFrom < 0 || $turnIdxFrom >= GameConst::$maxTurn){
} throw new \OutOfRangeException('$turnIdxFrom 범위 초과'.$turnIdxFrom);
}
if($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo){
throw new \OutOfRangeException('$turnIdxTo 범위 초과'.$turnIdxTo); if($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo){
} throw new \OutOfRangeException('$turnIdxTo 범위 초과'.$turnIdxTo);
}
$db = DB::db();
$db = DB::db();
$generalID = $this->getID();
$generalID = $this->getID();
$result = [];
$result = [];
$rawCmds = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id = %i AND %i <= turn_idx AND turn_idx < %i ORDER BY turn_idx ASC', $generalID, $turnIdxFrom, $turnIdxTo);
$rawCmds = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id = %i AND %i <= turn_idx AND turn_idx < %i ORDER BY turn_idx ASC', $generalID, $turnIdxFrom, $turnIdxTo);
if(!$rawCmds){
foreach(Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx){ if(!$rawCmds){
$result[$turnIdx] = buildGeneralCommandClass(null, $this, $env); foreach(Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx){
} $result[$turnIdx] = buildGeneralCommandClass(null, $this, $env);
return $result; }
} return $result;
}
foreach($rawCmds as $turnIdx=>$rawCmd){
$result[$turnIdx] = buildGeneralCommandClass($rawCmd['action'], $this, $env, Json::decode($rawCmd['arg']??null)); foreach($rawCmds as $turnIdx=>$rawCmd){
} $result[$turnIdx] = buildGeneralCommandClass($rawCmd['action'], $this, $env, Json::decode($rawCmd['arg']??null));
}
return $result;
} return $result;
}
/**
* 장수의 스탯을 계산해옴 /**
* * 장수의 스탯을 계산해옴
* @param string $statName 스탯값, leadership, strength, intel 가능 *
* @param bool $withInjury 부상값 사용 여부 * @param string $statName 스탯값, leadership, strength, intel 가능
* @param bool $withIActionObj 아이템, 특성, 성격 등 보정치 적용 여부 * @param bool $withInjury 부상값 사용 여부
* @param bool $withStatAdjust 능력치간 보정 사용 여부 * @param bool $withIActionObj 아이템, 특성, 성격 등 보정치 적용 여부
* @param bool $useFloor 내림 사용 여부, false시 float 값을 반환할 수도 있음 * @param bool $withStatAdjust 능력치간 보정 사용 여부
* * @param bool $useFloor 내림 사용 여부, false시 float 값을 반환할 수도 있음
* @return int|float 계산된 능력치 *
*/ * @return int|float 계산된 능력치
*/
protected function getStatValue(string $statName, $withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{
$cKey = "{$statName}_{$withInjury}_{$withIActionObj}_{$withStatAdjust}"; protected function getStatValue(string $statName, $withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{
if(key_exists($cKey, $this->calcCache)){ $cKey = "{$statName}_{$withInjury}_{$withIActionObj}_{$withStatAdjust}";
$statValue = $this->calcCache[$cKey]; if(key_exists($cKey, $this->calcCache)){
if($useFloor){ $statValue = $this->calcCache[$cKey];
return Util::toInt($statValue); if($useFloor){
} return Util::toInt($statValue);
return $statValue; }
} return $statValue;
}
$statValue = $this->getVar($statName);
$statValue = $this->getVar($statName);
if($withInjury){
$statValue *= (100 - $this->getVar('injury')) / 100; if($withInjury){
} $statValue *= (100 - $this->getVar('injury')) / 100;
}
if($withStatAdjust){
if($statName === 'strength'){ if($withStatAdjust){
$statValue += Util::round($this->getStatValue('intel', $withInjury, $withIActionObj, false, false) / 4); if($statName === 'strength'){
} $statValue += Util::round($this->getStatValue('intel', $withInjury, $withIActionObj, false, false) / 4);
else if($statName === 'intel'){ }
$statValue += Util::round($this->getStatValue('strength', $withInjury, $withIActionObj, false, false) / 4); else if($statName === 'intel'){
} $statValue += Util::round($this->getStatValue('strength', $withInjury, $withIActionObj, false, false) / 4);
} }
}
if($withIActionObj){
foreach([ if($withIActionObj){
$this->nationType, foreach([
$this->officerLevelObj, $this->nationType,
$this->specialDomesticObj, $this->officerLevelObj,
$this->specialWarObj, $this->specialDomesticObj,
$this->personalityObj $this->specialWarObj,
] as $actionObj){ $this->personalityObj
if($actionObj !== null){ ] as $actionObj){
$statValue = $actionObj->onCalcStat($this, $statName, $statValue); if($actionObj !== null){
} $statValue = $actionObj->onCalcStat($this, $statName, $statValue);
} }
}
foreach($this->itemObjs as $actionObj){
if($actionObj !== null){ foreach($this->itemObjs as $actionObj){
$statValue = $actionObj->onCalcStat($this, $statName, $statValue); if($actionObj !== null){
} $statValue = $actionObj->onCalcStat($this, $statName, $statValue);
} }
} }
}
$this->calcCache[$cKey] = $statValue;
$this->calcCache[$cKey] = $statValue;
if($useFloor){
return Util::toInt($statValue); if($useFloor){
} return Util::toInt($statValue);
}
return $statValue;
} return $statValue;
}
function getLeadership($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{
return $this->getStatValue('leadership', $withInjury, $withIActionObj, $withStatAdjust, $useFloor); function getLeadership($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{
} return $this->getStatValue('leadership', $withInjury, $withIActionObj, $withStatAdjust, $useFloor);
}
function getStrength($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{
return $this->getStatValue('strength', $withInjury, $withIActionObj, $withStatAdjust, $useFloor); function getStrength($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{
} return $this->getStatValue('strength', $withInjury, $withIActionObj, $withStatAdjust, $useFloor);
}
function getIntel($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{
return $this->getStatValue('intel', $withInjury, $withIActionObj, $withStatAdjust, $useFloor); function getIntel($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{
} return $this->getStatValue('intel', $withInjury, $withIActionObj, $withStatAdjust, $useFloor);
}
function getDex(GameUnitDetail $crewType){
$armType = $crewType->armType; function getDex(GameUnitDetail $crewType){
$armType = $crewType->armType;
if($armType == GameUnitConst::T_CASTLE){
$armType = GameUnitConst::T_SIEGE; if($armType == GameUnitConst::T_CASTLE){
} $armType = GameUnitConst::T_SIEGE;
}
return $this->getVar("dex{$armType}");
} return $this->getVar("dex{$armType}");
}
function addDex(GameUnitDetail $crewType, float $exp, bool $affectTrainAtmos=false){
$armType = $crewType->armType; function addDex(GameUnitDetail $crewType, float $exp, bool $affectTrainAtmos=false){
$armType = $crewType->armType;
if($armType == GameUnitConst::T_CASTLE){
$armType = GameUnitConst::T_SIEGE; if($armType == GameUnitConst::T_CASTLE){
} $armType = GameUnitConst::T_SIEGE;
}
if($armType < 0){
return; if($armType < 0){
} return;
}
if($armType == GameUnitConst::T_WIZARD) {
$exp *= 0.9; if($armType == GameUnitConst::T_WIZARD) {
} $exp *= 0.9;
else if($armType == GameUnitConst::T_SIEGE) { }
$exp *= 0.9; else if($armType == GameUnitConst::T_SIEGE) {
} $exp *= 0.9;
}
if($affectTrainAtmos){
$exp *= ($this->getVar('train') + $this->getVar('atmos')) / 200; if($affectTrainAtmos){
} $exp *= ($this->getVar('train') + $this->getVar('atmos')) / 200;
}
$dexType = "dex{$armType}";
$dexType = "dex{$armType}";
$this->increaseVar($dexType, $exp);
} $this->increaseVar($dexType, $exp);
}
function addExperience(float $experience, bool $affectTrigger=true){
if($affectTrigger){ function addExperience(float $experience, bool $affectTrigger=true){
$experience = $this->onCalcStat($this, 'experience', $experience); if($affectTrigger){
} $experience = $this->onCalcStat($this, 'experience', $experience);
}
$this->increaseVar('experience', $experience);
$nextExpLevel = getExpLevel($this->getVar('experience')); $this->increaseVar('experience', $experience);
$comp = $nextExpLevel <=> $this->getVar('explevel'); $nextExpLevel = getExpLevel($this->getVar('experience'));
if($comp === 0){ $comp = $nextExpLevel <=> $this->getVar('explevel');
return; if($comp === 0){
} return;
}
$this->updateVar('explevel', $nextExpLevel);
$this->updateVar('explevel', $nextExpLevel);
$josaRo = JosaUtil::pick($nextExpLevel, '로');
if($comp > 0){ $josaRo = JosaUtil::pick($nextExpLevel, '로');
$this->getLogger()->pushGeneralActionLog("<C>Lv {$nextExpLevel}</>{$josaRo} <C>레벨업</>!", ActionLogger::PLAIN); if($comp > 0){
} $this->getLogger()->pushGeneralActionLog("<C>Lv {$nextExpLevel}</>{$josaRo} <C>레벨업</>!", ActionLogger::PLAIN);
else{ }
$this->getLogger()->pushGeneralActionLog("<C>Lv {$nextExpLevel}</>{$josaRo} <R>레벨다운</>!", ActionLogger::PLAIN); else{
} $this->getLogger()->pushGeneralActionLog("<C>Lv {$nextExpLevel}</>{$josaRo} <R>레벨다운</>!", ActionLogger::PLAIN);
}
}
}
function addDedication(float $dedication, bool $affectTrigger=true){
if($affectTrigger){ function addDedication(float $dedication, bool $affectTrigger=true){
$dedication = $this->onCalcStat($this, 'dedication', $dedication); if($affectTrigger){
} $dedication = $this->onCalcStat($this, 'dedication', $dedication);
}
$this->increaseVar('dedication', $dedication);
$nextDedLevel = getDedLevel($this->getVar('dedication')); $this->increaseVar('dedication', $dedication);
$comp = $nextDedLevel <=> $this->getVar('dedlevel'); $nextDedLevel = getDedLevel($this->getVar('dedication'));
if($comp === 0){ $comp = $nextDedLevel <=> $this->getVar('dedlevel');
return; if($comp === 0){
} return;
}
$this->updateVar('dedlevel', $nextDedLevel);
$this->updateVar('dedlevel', $nextDedLevel);
$dedLevelText = getDedLevelText($nextDedLevel);
$billText = number_format(getBillByLevel($nextDedLevel)); $dedLevelText = getDedLevelText($nextDedLevel);
$josaRoDed = JosaUtil::pick($dedLevelText, '로'); $billText = number_format(getBillByLevel($nextDedLevel));
$josaRoBill = JosaUtil::pick($billText, '로'); $josaRoDed = JosaUtil::pick($dedLevelText, '로');
if($comp > 0){ $josaRoBill = JosaUtil::pick($billText, '로');
$this->getLogger()->pushGeneralActionLog("<Y>{$dedLevelText}</>{$josaRoDed} <C>승급</>하여 봉록이 <C>{$billText}</>{$josaRoBill} <C>상승</>했습니다!", ActionLogger::PLAIN); if($comp > 0){
} $this->getLogger()->pushGeneralActionLog("<Y>{$dedLevelText}</>{$josaRoDed} <C>승급</>하여 봉록이 <C>{$billText}</>{$josaRoBill} <C>상승</>했습니다!", ActionLogger::PLAIN);
else{ }
$this->getLogger()->pushGeneralActionLog("<Y>{$dedLevelText}</>{$josaRoDed} <R>강등</>되어 봉록이 <C>{$billText}</>{$josaRoBill} <R>하락</>했습니다!", ActionLogger::PLAIN); else{
} $this->getLogger()->pushGeneralActionLog("<Y>{$dedLevelText}</>{$josaRoDed} <R>강등</>되어 봉록이 <C>{$billText}</>{$josaRoBill} <R>하락</>했습니다!", ActionLogger::PLAIN);
}
}
}
function updateVar(string $key, $value){
if(($this->raw[$key]??null) === $value){ function updateVar(string $key, $value){
return; if(($this->raw[$key]??null) === $value){
} return;
if(!key_exists($key, $this->updatedVar)){ }
$this->updatedVar[$key] = true; if(!key_exists($key, $this->updatedVar)){
} $this->updatedVar[$key] = true;
$this->raw[$key] = $value; }
$this->calcCache = []; $this->raw[$key] = $value;
} $this->calcCache = [];
}
/**
* @param \MeekroDB $db /**
*/ * @param \MeekroDB $db
function kill($db, bool $sendDyingMessage=true, ?string $dyingMessage=null){ */
$generalID = $this->getID(); function kill($db, bool $sendDyingMessage=true, ?string $dyingMessage=null){
$logger = $this->getLogger(); $generalID = $this->getID();
$logger = $this->getLogger();
$generalName = $this->getName();
$generalName = $this->getName();
// 군주였으면 유지 이음
$officerLevel = $this->getVar('officer_level'); // 군주였으면 유지 이음
if($officerLevel == 12) { $officerLevel = $this->getVar('officer_level');
nextRuler($this); if($officerLevel == 12) {
$this->setVar('officer_level', 1); nextRuler($this);
} $this->setVar('officer_level', 1);
}
// 부대 처리
$troopLeaderID = $this->getVar('troop'); // 부대 처리
if($troopLeaderID == $generalID){ $troopLeaderID = $this->getVar('troop');
//부대장일 경우 if($troopLeaderID == $generalID){
// 모두 탈퇴 //부대장일 경우
$db->update('general', [ // 모두 탈퇴
'troop'=>0 $db->update('general', [
], 'troop=%i', $troopLeaderID); 'troop'=>0
// 부대 삭제 ], 'troop=%i', $troopLeaderID);
$db->delete('troop', 'troop_leader=%i', $troopLeaderID); // 부대 삭제
} $db->delete('troop', 'troop_leader=%i', $troopLeaderID);
}
if($sendDyingMessage){
if($dyingMessage){ if($sendDyingMessage){
$logger->pushGlobalActionLog($dyingMessage); if($dyingMessage){
} $logger->pushGlobalActionLog($dyingMessage);
else{ }
$dyingMessageObj = new TextDecoration\DyingMessage($this); else{
$logger->pushGlobalActionLog($dyingMessageObj->getText()); $dyingMessageObj = new TextDecoration\DyingMessage($this);
} $logger->pushGlobalActionLog($dyingMessageObj->getText());
$logger->flush(); }
} $logger->flush();
}
$db->delete('general', 'no=%i', $generalID);
$db->delete('general_turn', 'general_id=%i', $generalID); $db->delete('general', 'no=%i', $generalID);
$db->delete('rank_data', 'general_id=%i', $generalID); $db->delete('general_turn', 'general_id=%i', $generalID);
$db->delete('betting', 'general_id=%i', $generalID); $db->delete('rank_data', 'general_id=%i', $generalID);
$this->updatedVar = []; $db->delete('betting', 'general_id=%i', $generalID);
$this->updatedVar = [];
$db->update('nation', [
'gennum'=>$db->sqleval('gennum - 1') $db->update('nation', [
], 'nation=%i', $this->getVar('nation')); 'gennum'=>$db->sqleval('gennum - 1')
} ], 'nation=%i', $this->getVar('nation'));
}
function rebirth(){
$logger = $this->getLogger(); function rebirth(){
$logger = $this->getLogger();
$generalName = $this->getName();
$generalName = $this->getName();
$this->multiplyVarWithLimit('leadership', 0.85, 10);
$this->multiplyVarWithLimit('strength', 0.85, 10); $this->multiplyVarWithLimit('leadership', 0.85, 10);
$this->multiplyVarWithLimit('intel', 0.85, 10); $this->multiplyVarWithLimit('strength', 0.85, 10);
$this->setVar('injury', 0); $this->multiplyVarWithLimit('intel', 0.85, 10);
$this->multiplyVar('experience', 0.5); $this->setVar('injury', 0);
$this->multiplyVar('dedication', 0.5); $this->multiplyVar('experience', 0.5);
$this->setVar('age', 20); $this->multiplyVar('dedication', 0.5);
$this->setVar('specage', 0); $this->setVar('age', 20);
$this->setVar('specage2', 0); $this->setVar('specage', 0);
$this->multiplyVar('dex1', 0.5); $this->setVar('specage2', 0);
$this->multiplyVar('dex2', 0.5); $this->multiplyVar('dex1', 0.5);
$this->multiplyVar('dex3', 0.5); $this->multiplyVar('dex2', 0.5);
$this->multiplyVar('dex4', 0.5); $this->multiplyVar('dex3', 0.5);
$this->multiplyVar('dex5', 0.5); $this->multiplyVar('dex4', 0.5);
$this->multiplyVar('dex5', 0.5);
foreach(array_keys(static::RANK_COLUMN) as $rankKey){
$this->setRankVar($rankKey, 0); foreach(array_keys(static::RANK_COLUMN) as $rankKey){
} $this->setRankVar($rankKey, 0);
}
$josaYi = JosaUtil::pick($generalName, '이');
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <R>은퇴</>하고 그 자손이 유지를 이어받았습니다."); $josaYi = JosaUtil::pick($generalName, '이');
$logger->pushGeneralActionLog('나이가 들어 <R>은퇴</>하고 자손에게 자리를 물려줍니다.', ActionLogger::PLAIN); $logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <R>은퇴</>하고 그 자손이 유지를 이어받았습니다.");
$logger->pushGeneralHistoryLog('나이가 들어 은퇴하고, 자손에게 관직을 물려줌'); $logger->pushGeneralActionLog('나이가 들어 <R>은퇴</>하고 자손에게 자리를 물려줍니다.', ActionLogger::PLAIN);
} $logger->pushGeneralHistoryLog('나이가 들어 은퇴하고, 자손에게 관직을 물려줌');
}
function increaseRankVar(string $key, int $value){
if(!key_exists($key, static::RANK_COLUMN)){ function increaseRankVar(string $key, int $value){
throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key); if(!key_exists($key, static::RANK_COLUMN)){
} throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key);
}
if(key_exists($key, $this->rankVarSet)){
$this->rankVarSet[$key] += $value; if(key_exists($key, $this->rankVarSet)){
return; $this->rankVarSet[$key] += $value;
} return;
}
if(key_exists($key, $this->rankVarRead)){
$this->rankVarSet[$key] = $this->rankVarRead[$key] + $value; if(key_exists($key, $this->rankVarRead)){
unset($this->rankVarRead[$key]); $this->rankVarSet[$key] = $this->rankVarRead[$key] + $value;
return; unset($this->rankVarRead[$key]);
} return;
}
if(key_exists($key, $this->rankVarIncrease)){
$this->rankVarIncrease[$key] += $value; if(key_exists($key, $this->rankVarIncrease)){
return; $this->rankVarIncrease[$key] += $value;
} return;
}
$this->rankVarIncrease[$key] = $value;
} $this->rankVarIncrease[$key] = $value;
}
function setRankVar(string $key, int $value){
if(!key_exists($key, static::RANK_COLUMN)){ function setRankVar(string $key, int $value){
throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key); if(!key_exists($key, static::RANK_COLUMN)){
} throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key);
}
if(key_exists($key, $this->rankVarRead)){
unset($this->rankVarRead[$key]); if(key_exists($key, $this->rankVarRead)){
} unset($this->rankVarRead[$key]);
else if(key_exists($key, $this->rankVarIncrease)){ }
unset($this->rankVarIncrease[$key]); else if(key_exists($key, $this->rankVarIncrease)){
} unset($this->rankVarIncrease[$key]);
$this->rankVarSet[$key]=$value; }
} $this->rankVarSet[$key]=$value;
}
function getRankVar(string $key):int{
if(!key_exists($key, static::RANK_COLUMN)){ function getRankVar(string $key):int{
throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key); if(!key_exists($key, static::RANK_COLUMN)){
} throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key);
}
if(key_exists($key, $this->rankVarSet)){
return $this->rankVarSet[$key]; if(key_exists($key, $this->rankVarSet)){
} return $this->rankVarSet[$key];
}
if(!key_exists($key, $this->rankVarRead)){
throw new \RuntimeException('인자가 없음 : '.$key); if(!key_exists($key, $this->rankVarRead)){
} throw new \RuntimeException('인자가 없음 : '.$key);
}
return $this->rankVarRead[$key];
} return $this->rankVarRead[$key];
}
/**
* @param \MeekroDB $db /**
*/ * @param \MeekroDB $db
function applyDB($db):bool{ */
if($this->lastTurn && $this->getLastTurn() != $this->getResultTurn()){ function applyDB($db):bool{
$this->setVar('last_turn', $this->getResultTurn()->toJson()); if($this->lastTurn && $this->getLastTurn() != $this->getResultTurn()){
} $this->setVar('last_turn', $this->getResultTurn()->toJson());
$updateVals = $this->getUpdatedValues(); }
$updateVals = $this->getUpdatedValues();
$generalID = $this->getID();
$result = false; $generalID = $this->getID();
$result = false;
if($updateVals){
$db->update('general', $updateVals, 'no=%i', $generalID); if($updateVals){
$result |= $db->affectedRows() > 0; $db->update('general', $updateVals, 'no=%i', $generalID);
if(key_exists('nation', $updateVals)){ $result |= $db->affectedRows() > 0;
$db->update('rank_data', [ if(key_exists('nation', $updateVals)){
'nation_id'=>$updateVals['nation'] $db->update('rank_data', [
], 'general_id = %i', $generalID); 'nation_id'=>$updateVals['nation']
$result = true; ], 'general_id = %i', $generalID);
} $result = true;
$this->flushUpdateValues(); }
} $this->flushUpdateValues();
}
if($this->rankVarIncrease){
foreach($this->rankVarIncrease as $rankKey => $rankVal){ if($this->rankVarIncrease){
$db->update('rank_data', [ foreach($this->rankVarIncrease as $rankKey => $rankVal){
'value'=>$db->sqleval('value + %i', $rankVal) $db->update('rank_data', [
], 'general_id = %i AND type = %s', $generalID, $rankKey); 'value'=>$db->sqleval('value + %i', $rankVal)
} ], 'general_id = %i AND type = %s', $generalID, $rankKey);
$result = true; }
} $result = true;
}
if($this->rankVarSet){
foreach($this->rankVarSet as $rankKey => $rankVal){ if($this->rankVarSet){
$db->update('rank_data', [ foreach($this->rankVarSet as $rankKey => $rankVal){
'value'=>$rankVal $db->update('rank_data', [
], 'general_id = %i AND type = %s', $generalID, $rankKey); 'value'=>$rankVal
$this->rankVarRead[$rankKey] = $rankVal; ], 'general_id = %i AND type = %s', $generalID, $rankKey);
} $this->rankVarRead[$rankKey] = $rankVal;
$result = true; }
} $result = true;
}
$this->rankVarIncrease = [];
$this->rankVarSet = []; $this->rankVarIncrease = [];
$this->rankVarSet = [];
$this->getLogger()->flush();
return $result; $this->getLogger()->flush();
} return $result;
}
function checkStatChange():bool{
$logger = $this->getLogger(); function checkStatChange():bool{
$limit = GameConst::$upgradeLimit; $logger = $this->getLogger();
$limit = GameConst::$upgradeLimit;
$table = [
['통솔', 'leadership'], $table = [
['무력', 'strength'], ['통솔', 'leadership'],
['력', 'intel'], ['력', 'strength'],
]; ['지력', 'intel'],
];
$result = false;
$result = false;
foreach($table as [$statNickName, $statName]){
$statExpName = $statName.'_exp'; foreach($table as [$statNickName, $statName]){
$statExpName = $statName.'_exp';
if($this->getVar($statExpName) < 0){
$logger->pushGeneralActionLog("<R>{$statNickName}</>이 <C>1</> 떨어졌습니다!", ActionLogger::PLAIN); if($this->getVar($statExpName) < 0){
$this->increaseVar($statExpName, $limit); $logger->pushGeneralActionLog("<R>{$statNickName}</>이 <C>1</> 떨어졌습니다!", ActionLogger::PLAIN);
$this->increaseVar($statName, -1); $this->increaseVar($statExpName, $limit);
$result = true; $this->increaseVar($statName, -1);
} $result = true;
else if($this->getVar($statExpName) >= $limit){ }
$logger->pushGeneralActionLog("<S>{$statNickName}</>이 <C>1</> 올랐습니다!", ActionLogger::PLAIN); else if($this->getVar($statExpName) >= $limit){
$this->increaseVar($statExpName, -$limit); $logger->pushGeneralActionLog("<S>{$statNickName}</>이 <C>1</> 올랐습니다!", ActionLogger::PLAIN);
$this->increaseVar($statName, 1); $this->increaseVar($statExpName, -$limit);
$result = true; $this->increaseVar($statName, 1);
} $result = true;
} }
}
return $result;
} return $result;
}
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
$caller = new GeneralTriggerCaller(); public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
foreach(array_merge([ $caller = new GeneralTriggerCaller();
$this->nationType, foreach(array_merge([
$this->officerLevelObj, $this->nationType,
$this->specialDomesticObj, $this->officerLevelObj,
$this->specialWarObj, $this->specialDomesticObj,
$this->personalityObj, $this->specialWarObj,
$this->getCrewTypeObj(), $this->personalityObj,
], $this->itemObjs) as $iObj){ $this->getCrewTypeObj(),
], $this->itemObjs) as $iObj){
if(!$iObj){
continue; if(!$iObj){
} continue;
/** @var iAction $iObj */ }
$caller->merge($iObj->getPreTurnExecuteTriggerList($general)); /** @var iAction $iObj */
} $caller->merge($iObj->getPreTurnExecuteTriggerList($general));
}
return $caller;
} return $caller;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ }
foreach(array_merge([ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
$this->nationType, foreach(array_merge([
$this->officerLevelObj, $this->nationType,
$this->specialDomesticObj, $this->officerLevelObj,
$this->specialWarObj, $this->specialDomesticObj,
$this->personalityObj, $this->specialWarObj,
$this->getCrewTypeObj(), $this->personalityObj,
], $this->itemObjs) as $iObj){ $this->getCrewTypeObj(),
if(!$iObj){ ], $this->itemObjs) as $iObj){
continue; if(!$iObj){
} continue;
/** @var iAction $iObj */ }
$value = $iObj->onCalcDomestic($turnType, $varType, $value, $aux); /** @var iAction $iObj */
} $value = $iObj->onCalcDomestic($turnType, $varType, $value, $aux);
return $value; }
} return $value;
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
//xxx: $general? public function onCalcStat(General $general, string $statName, $value, $aux=null){
foreach(array_merge([ //xxx: $general?
$this->nationType, foreach(array_merge([
$this->officerLevelObj, $this->nationType,
$this->specialDomesticObj, $this->officerLevelObj,
$this->specialWarObj, $this->specialDomesticObj,
$this->personalityObj, $this->specialWarObj,
$this->getCrewTypeObj(), $this->personalityObj,
], $this->itemObjs) as $iObj){ $this->getCrewTypeObj(),
if(!$iObj){ ], $this->itemObjs) as $iObj){
continue; if(!$iObj){
} continue;
/** @var iAction $iObj */ }
$value = $iObj->onCalcStat($this, $statName, $value, $aux); /** @var iAction $iObj */
} $value = $iObj->onCalcStat($this, $statName, $value, $aux);
return $value; }
} return $value;
}
public function onCalcStrategic(string $turnType, string $varType, $value){
foreach(array_merge([ public function onCalcStrategic(string $turnType, string $varType, $value){
$this->nationType, foreach(array_merge([
$this->officerLevelObj, $this->nationType,
$this->specialDomesticObj, $this->officerLevelObj,
$this->specialWarObj, $this->specialDomesticObj,
$this->personalityObj, $this->specialWarObj,
$this->getCrewTypeObj(), $this->personalityObj,
], $this->itemObjs) as $iObj){ $this->getCrewTypeObj(),
if(!$iObj){ ], $this->itemObjs) as $iObj){
continue; if(!$iObj){
} continue;
/** @var iAction $iObj */ }
$value = $iObj->onCalcStrategic($turnType, $varType, $value); /** @var iAction $iObj */
} $value = $iObj->onCalcStrategic($turnType, $varType, $value);
return $value; }
} return $value;
}
public function onCalcNationalIncome(string $type, $amount){
foreach(array_merge([ public function onCalcNationalIncome(string $type, $amount){
$this->nationType, foreach(array_merge([
$this->officerLevelObj, $this->nationType,
$this->specialDomesticObj, $this->officerLevelObj,
$this->specialWarObj, $this->specialDomesticObj,
$this->personalityObj, $this->specialWarObj,
$this->getCrewTypeObj(), $this->personalityObj,
], $this->itemObjs) as $iObj){ $this->getCrewTypeObj(),
if(!$iObj){ ], $this->itemObjs) as $iObj){
continue; if(!$iObj){
} continue;
/** @var iAction $iObj */ }
$amount = $iObj->onCalcNationalIncome($type, $amount); /** @var iAction $iObj */
} $amount = $iObj->onCalcNationalIncome($type, $amount);
return $amount; }
} return $amount;
}
public function getWarPowerMultiplier(WarUnit $unit):array{
//xxx:$unit public function getWarPowerMultiplier(WarUnit $unit):array{
$att = 1; //xxx:$unit
$def = 1; $att = 1;
foreach(array_merge([ $def = 1;
$this->nationType, foreach(array_merge([
$this->officerLevelObj, $this->nationType,
$this->specialDomesticObj, $this->officerLevelObj,
$this->specialWarObj, $this->specialDomesticObj,
$this->personalityObj, $this->specialWarObj,
$this->getCrewTypeObj(), $this->personalityObj,
], $this->itemObjs) as $iObj){ $this->getCrewTypeObj(),
if(!$iObj){ ], $this->itemObjs) as $iObj){
continue; if(!$iObj){
} continue;
/** @var iAction $iObj */ }
[$attV, $defV] = $iObj->getWarPowerMultiplier($unit); /** @var iAction $iObj */
$att *= $attV; [$attV, $defV] = $iObj->getWarPowerMultiplier($unit);
$def *= $defV; $att *= $attV;
} $def *= $defV;
return [$att, $def]; }
} return [$att, $def];
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ }
$caller = new WarUnitTriggerCaller(); public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
foreach(array_merge([ $caller = new WarUnitTriggerCaller();
$this->nationType, foreach(array_merge([
$this->officerLevelObj, $this->nationType,
$this->specialDomesticObj, $this->officerLevelObj,
$this->specialWarObj, $this->specialDomesticObj,
$this->personalityObj, $this->specialWarObj,
$this->getCrewTypeObj(), $this->personalityObj,
], $this->itemObjs) as $iObj){ $this->getCrewTypeObj(),
if(!$iObj){ ], $this->itemObjs) as $iObj){
continue; if(!$iObj){
} continue;
/** @var iAction $iObj */ }
$caller->merge($iObj->getBattleInitSkillTriggerList($unit)); /** @var iAction $iObj */
} $caller->merge($iObj->getBattleInitSkillTriggerList($unit));
}
return $caller;
} return $caller;
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ }
$caller = new WarUnitTriggerCaller( public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
new WarUnitTrigger\che_필살시도($unit), $caller = new WarUnitTriggerCaller(
new WarUnitTrigger\che_필살발동($unit), new WarUnitTrigger\che_필살시도($unit),
new WarUnitTrigger\che_회피시도($unit), new WarUnitTrigger\che_필살발동($unit),
new WarUnitTrigger\che_회피발동($unit), new WarUnitTrigger\che_회피시도($unit),
new WarUnitTrigger\che_계략시도($unit), new WarUnitTrigger\che_회피발동($unit),
new WarUnitTrigger\che_계략발동($unit), new WarUnitTrigger\che_계략시도($unit),
new WarUnitTrigger\che_계략실패($unit) new WarUnitTrigger\che_계략발동($unit),
); new WarUnitTrigger\che_계략실패($unit)
foreach(array_merge([ );
$this->nationType, foreach(array_merge([
$this->officerLevelObj, $this->nationType,
$this->specialDomesticObj, $this->officerLevelObj,
$this->specialWarObj, $this->specialDomesticObj,
$this->personalityObj, $this->specialWarObj,
$this->getCrewTypeObj(), $this->personalityObj,
], $this->itemObjs) as $iObj){ $this->getCrewTypeObj(),
if(!$iObj){ ], $this->itemObjs) as $iObj){
continue; if(!$iObj){
} continue;
/** @var iAction $iObj */ }
$caller->merge($iObj->getBattlePhaseSkillTriggerList($unit)); /** @var iAction $iObj */
} $caller->merge($iObj->getBattlePhaseSkillTriggerList($unit));
}
return $caller;
} return $caller;
}
static public function mergeQueryColumn(?array $reqColumns=null, int $constructMode=2):array{
$minimumColumn = ['no', 'name', 'city', 'nation', 'officer_level', 'officer_city']; static public function mergeQueryColumn(?array $reqColumns=null, int $constructMode=2):array{
$defaultEventColumn = [ $minimumColumn = ['no', 'name', 'city', 'nation', 'officer_level', 'officer_city'];
'no', 'name', 'city', 'nation', 'officer_level', 'officer_city', $defaultEventColumn = [
'special', 'special2', 'personal', 'no', 'name', 'city', 'nation', 'officer_level', 'officer_city',
'horse', 'weapon', 'book', 'item', 'last_turn' 'special', 'special2', 'personal',
]; 'horse', 'weapon', 'book', 'item', 'last_turn'
$fullColumn = [ ];
'no', 'name', 'owner_name', 'picture', 'imgsvr', 'nation', 'city', 'troop', 'injury', 'affinity', $fullColumn = [
'leadership', 'leadership_exp', 'strength', 'strength_exp', 'intel', 'intel_exp', 'weapon', 'book', 'horse', 'item', 'no', 'name', 'owner_name', 'picture', 'imgsvr', 'nation', 'city', 'troop', 'injury', 'affinity',
'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'crew', 'crewtype', 'train', 'atmos', 'turntime', 'leadership', 'leadership_exp', 'strength', 'strength_exp', 'intel', 'intel_exp', 'weapon', 'book', 'horse', 'item',
'makelimit', 'killturn', 'block', 'dedlevel', 'explevel', 'age', 'startage', 'belong', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'crew', 'crewtype', 'train', 'atmos', 'turntime',
'personal', 'special', 'special2', 'defence_train', 'tnmt', 'npc', 'npc_org', 'deadyear', 'npcmsg', 'makelimit', 'killturn', 'block', 'dedlevel', 'explevel', 'age', 'startage', 'belong',
'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'betray', 'personal', 'special', 'special2', 'defence_train', 'tnmt', 'npc', 'npc_org', 'deadyear', 'npcmsg',
'recent_war', 'last_turn', 'myset', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'betray',
'specage', 'specage2', 'con', 'connect', 'owner', 'aux', 'lastrefresh', 'recent_war', 'last_turn', 'myset',
]; 'specage', 'specage2', 'con', 'connect', 'owner', 'aux', 'lastrefresh',
];
if($reqColumns === null){
return [$fullColumn, array_keys(static::RANK_COLUMN)]; if($reqColumns === null){
} return [$fullColumn, array_keys(static::RANK_COLUMN)];
}
$rankColumn = [];
$subColumn = []; $rankColumn = [];
foreach($reqColumns as $column){ $subColumn = [];
if(key_exists($column, static::RANK_COLUMN)){ foreach($reqColumns as $column){
$rankColumn[] = $column; if(key_exists($column, static::RANK_COLUMN)){
} $rankColumn[] = $column;
else{ }
$subColumn[] = $column; else{
} $subColumn[] = $column;
} }
}
if($constructMode > 1){
return [array_unique(array_merge($defaultEventColumn, $subColumn)), $rankColumn]; if($constructMode > 1){
} return [array_unique(array_merge($defaultEventColumn, $subColumn)), $rankColumn];
}
return [array_unique(array_merge($minimumColumn, $subColumn)), $rankColumn];
} return [array_unique(array_merge($minimumColumn, $subColumn)), $rankColumn];
}
/**
* @param ?int[] $generalIDList /**
* @param null|string[] $column * @param ?int[] $generalIDList
* @param int $constructMode * @param null|string[] $column
* @return \sammo\General[] * @param int $constructMode
* @throws MustNotBeReachedException * @return \sammo\General[]
*/ * @throws MustNotBeReachedException
static public function createGeneralObjListFromDB(?array $generalIDList, ?array $column=null, int $constructMode=2):array{ */
if($generalIDList === []){ static public function createGeneralObjListFromDB(?array $generalIDList, ?array $column=null, int $constructMode=2):array{
return []; if($generalIDList === []){
} return [];
}
$db = DB::db();
if($constructMode > 0){ $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); if($constructMode > 0){
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']); $gameStor = KVStorage::getStorage($db, 'game_env');
} [$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
else{ }
$year = null; else{
$month = null; $year = null;
} $month = null;
}
[$column, $rankColumn] = static::mergeQueryColumn($column, $constructMode);
[$column, $rankColumn] = static::mergeQueryColumn($column, $constructMode);
if($generalIDList === null){
$rawGenerals = Util::convertArrayToDict( if($generalIDList === null){
$db->query('SELECT %l FROM general WHERE 1', Util::formatListOfBackticks($column)), $rawGenerals = Util::convertArrayToDict(
'no' $db->query('SELECT %l FROM general WHERE 1', Util::formatListOfBackticks($column)),
); 'no'
$generalIDList = array_keys($rawGenerals); );
} $generalIDList = array_keys($rawGenerals);
else{ }
$rawGenerals = Util::convertArrayToDict( else{
$db->query('SELECT %l FROM general WHERE no IN %li', Util::formatListOfBackticks($column), $generalIDList), $rawGenerals = Util::convertArrayToDict(
'no' $db->query('SELECT %l FROM general WHERE no IN %li', Util::formatListOfBackticks($column), $generalIDList),
); 'no'
} );
}
$rawRanks = [];
if($rankColumn){ $rawRanks = [];
$rawValue = $db->queryAllLists( if($rankColumn){
'SELECT `general_id`, `type`, `value` FROM rank_data WHERE general_id IN %li AND `type` IN %ls', $rawValue = $db->queryAllLists(
$generalIDList, 'SELECT `general_id`, `type`, `value` FROM rank_data WHERE general_id IN %li AND `type` IN %ls',
$rankColumn $generalIDList,
); $rankColumn
foreach($rawValue as [$generalID, $rankType, $rankValue]){ );
if(!key_exists($generalID, $rawRanks)){ foreach($rawValue as [$generalID, $rankType, $rankValue]){
$rawRanks[$generalID] = []; if(!key_exists($generalID, $rawRanks)){
} $rawRanks[$generalID] = [];
$rawRanks[$generalID][$rankType] = $rankValue; }
} $rawRanks[$generalID][$rankType] = $rankValue;
} }
}
$result = [];
foreach($generalIDList as $generalID){ $result = [];
if(!key_exists($generalID, $rawGenerals)){ foreach($generalIDList as $generalID){
$result[$generalID] = new DummyGeneral($constructMode > 0); if(!key_exists($generalID, $rawGenerals)){
continue; $result[$generalID] = new DummyGeneral($constructMode > 0);
} continue;
if(key_exists($generalID, $rawRanks) && count($rawRanks[$generalID]??[]) !== count($rankColumn)){ }
throw new \RuntimeException('column의 수가 일치하지 않음 : '.$generalID); if(key_exists($generalID, $rawRanks) && count($rawRanks[$generalID]??[]) !== count($rankColumn)){
} throw new \RuntimeException('column의 수가 일치하지 않음 : '.$generalID);
$result[$generalID] = new static($rawGenerals[$generalID], $rawRanks[$generalID]??null, null, null, $year, $month, $constructMode > 1); }
} $result[$generalID] = new static($rawGenerals[$generalID], $rawRanks[$generalID]??null, null, null, $year, $month, $constructMode > 1);
}
return $result;
} return $result;
}
static public function createGeneralObjFromDB(int $generalID, ?array $column=null, int $constructMode=2):self{
$db = DB::db(); static public function createGeneralObjFromDB(int $generalID, ?array $column=null, int $constructMode=2):self{
if($constructMode > 0){ $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); if($constructMode > 0){
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']); $gameStor = KVStorage::getStorage($db, 'game_env');
} [$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
else{ }
$year = null; else{
$month = null; $year = null;
} $month = null;
}
[$column, $rankColumn] = static::mergeQueryColumn($column, $constructMode);
[$column, $rankColumn] = static::mergeQueryColumn($column, $constructMode);
$rawGeneral = $db->queryFirstRow('SELECT %l FROM general WHERE no = %i', Util::formatListOfBackticks($column), $generalID);
if(!$rawGeneral){ $rawGeneral = $db->queryFirstRow('SELECT %l FROM general WHERE no = %i', Util::formatListOfBackticks($column), $generalID);
return new DummyGeneral($constructMode > 0); if(!$rawGeneral){
} return new DummyGeneral($constructMode > 0);
}
$rawRankValues = [];
if($rankColumn){ $rawRankValues = [];
$rawValue = $db->queryAllLists('SELECT `type`, `value` FROM rank_data WHERE general_id = %i AND `type` IN %ls', $generalID, $rankColumn); if($rankColumn){
foreach($rawValue as [$rankType, $rankValue]){ $rawValue = $db->queryAllLists('SELECT `type`, `value` FROM rank_data WHERE general_id = %i AND `type` IN %ls', $generalID, $rankColumn);
$rawRankValues[$rankType] = $rankValue; foreach($rawValue as [$rankType, $rankValue]){
} $rawRankValues[$rankType] = $rankValue;
} }
}
$general = new static($rawGeneral, $rawRankValues, null, null, $year, $month, $constructMode > 1);
$general = new static($rawGeneral, $rawRankValues, null, null, $year, $month, $constructMode > 1);
return $general;
} return $general;
}
/**
* @param General[] $generalList /**
* @param int $turnIdx * @param General[] $generalList
* @param array $env * @param int $turnIdx
* @return GeneralCommand[] * @param array $env
*/ * @return GeneralCommand[]
static public function getReservedTurnByGeneralList(array $generalList, int $turnIdx, array $env){ */
if(!$generalList){ static public function getReservedTurnByGeneralList(array $generalList, int $turnIdx, array $env){
return []; if(!$generalList){
} return [];
}
$generalIDList = array_map(function(General $general){
return $general->getID(); $generalIDList = array_map(function(General $general){
}, $generalList); return $general->getID();
}, $generalList);
$db = DB::db();
$result = []; $db = DB::db();
$rawCmds = Util::convertArrayToDict($db->query('SELECT * FROM general_turn WHERE general_id IN %li AND turn_idx = %i', $generalIDList, $turnIdx), 'general_id'); $result = [];
foreach($generalList as $general){ $rawCmds = Util::convertArrayToDict($db->query('SELECT * FROM general_turn WHERE general_id IN %li AND turn_idx = %i', $generalIDList, $turnIdx), 'general_id');
$generalID = $general->getID(); foreach($generalList as $general){
if(!key_exists($generalID, $rawCmds)){ $generalID = $general->getID();
$result[$generalID] = buildGeneralCommandClass(null, $general, $env); if(!key_exists($generalID, $rawCmds)){
continue; $result[$generalID] = buildGeneralCommandClass(null, $general, $env);
} continue;
$rawCmd = $rawCmds[$generalID]; }
$result[$generalID] = buildGeneralCommandClass($rawCmd['action'], $general, $env, Json::decode($rawCmd['arg'])); $rawCmd = $rawCmds[$generalID];
} $result[$generalID] = buildGeneralCommandClass($rawCmd['action'], $general, $env, Json::decode($rawCmd['arg']));
return $result; }
} return $result;
}
/**
* @param General[] $generalList /**
* @param int $turnIdxFrom [$turnIdxFrom, $turnIdxTo) * @param General[] $generalList
* @param int $turnIdxTo [$turnIdxFrom, $turnIdxTo) * @param int $turnIdxFrom [$turnIdxFrom, $turnIdxTo)
* @param array $env * @param int $turnIdxTo [$turnIdxFrom, $turnIdxTo)
* @return GeneralCommand[][] * @param array $env
*/ * @return GeneralCommand[][]
static public function getReservedTurnListByGeneralList(array $generalList, int $turnIdxFrom, int $turnIdxTo, array $env){ */
//XXX: static인데 return값이 General이 아니라고?? GeneralCommandHelper같은게 있어야하지 않을까? static public function getReservedTurnListByGeneralList(array $generalList, int $turnIdxFrom, int $turnIdxTo, array $env){
if(!$generalList){ //XXX: static인데 return값이 General이 아니라고?? GeneralCommandHelper같은게 있어야하지 않을까?
return []; if(!$generalList){
} return [];
}
if($turnIdxFrom < 0 || $turnIdxFrom >= GameConst::$maxTurn){
throw new \OutOfRangeException('$turnIdxFrom 범위 초과'.$turnIdxFrom); if($turnIdxFrom < 0 || $turnIdxFrom >= GameConst::$maxTurn){
} throw new \OutOfRangeException('$turnIdxFrom 범위 초과'.$turnIdxFrom);
}
if($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo){
throw new \OutOfRangeException('$turnIdxTo 범위 초과'.$turnIdxTo); if($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo){
} throw new \OutOfRangeException('$turnIdxTo 범위 초과'.$turnIdxTo);
}
$generalIDList = array_map(function(General $general){
return $general->getID(); $generalIDList = array_map(function(General $general){
}, $generalList); return $general->getID();
}, $generalList);
$db = DB::db();
$db = DB::db();
$rawCmds = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id IN %i AND %i <= turn_idx AND turn_idx < %i ORDER BY general_id ASC, turn_idx ASC', $generalIDList, $turnIdxFrom, $turnIdxTo);
$orderedRawCmds = []; $rawCmds = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id IN %i AND %i <= turn_idx AND turn_idx < %i ORDER BY general_id ASC, turn_idx ASC', $generalIDList, $turnIdxFrom, $turnIdxTo);
foreach($rawCmds as $rawCmd){ $orderedRawCmds = [];
$generalID = $rawCmd['general_id']; foreach($rawCmds as $rawCmd){
$turnIdx = $rawCmd['turn_idx']; $generalID = $rawCmd['general_id'];
if(!key_exists($generalID, $orderedRawCmds)){ $turnIdx = $rawCmd['turn_idx'];
$orderedRawCmds[$generalID] = []; if(!key_exists($generalID, $orderedRawCmds)){
} $orderedRawCmds[$generalID] = [];
$orderedRawCmds[$generalID][$turnIdx] = $rawCmd; }
} $orderedRawCmds[$generalID][$turnIdx] = $rawCmd;
}
$result = [];
foreach($generalList as $general){ $result = [];
$generalID = $general->getID(); foreach($generalList as $general){
$result[$generalID] = []; $generalID = $general->getID();
if(!key_exists($generalID, $orderedRawCmds)){ $result[$generalID] = [];
foreach(Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx){ if(!key_exists($generalID, $orderedRawCmds)){
$result[$generalID][$turnIdx] = buildGeneralCommandClass(null, $general, $env); foreach(Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx){
} $result[$generalID][$turnIdx] = buildGeneralCommandClass(null, $general, $env);
continue; }
} continue;
foreach($orderedRawCmds[$generalID] as $turnIdx=>$rawCmd){ }
$result[$generalID][$turnIdx] = buildGeneralCommandClass($rawCmd['action'], $general, $env, Json::decode($rawCmd['arg'])); foreach($orderedRawCmds[$generalID] as $turnIdx=>$rawCmd){
} $result[$generalID][$turnIdx] = buildGeneralCommandClass($rawCmd['action'], $general, $env, Json::decode($rawCmd['arg']));
} }
return $result; }
} return $result;
}
} }