From cb246e859e8c23a3e592eaeb69bad1eaab1c3c6d Mon Sep 17 00:00:00 2001 From: hide_d Date: Fri, 13 Mar 2020 01:44:18 +0900 Subject: [PATCH] =?UTF-8?q?=EB=93=B1=EC=9A=A9=20=EC=88=98=EB=9D=BD=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD,=20Aux=20=EC=B2=98=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20nations->aux.joinedNations=20dummyGeneral=EC=97=90?= =?UTF-8?q?=20exp,ded=20=EC=B6=94=EA=B0=80=20scheme=EC=97=90=EC=84=9C=20na?= =?UTF-8?q?tions=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/license.txt | 1 - hwe/sammo/Command/BaseCommand.php | 4 +- hwe/sammo/Command/General/che_등용.php | 2 +- hwe/sammo/Command/General/che_등용수락.php | 253 ++++++++++++++++++ hwe/sammo/Command/General/che_랜덤임관.php | 6 +- hwe/sammo/Command/General/che_임관.php | 4 +- hwe/sammo/Constraint/AllowJoinDestNation.php | 17 +- hwe/sammo/Constraint/ConstraintHelper.php | 12 +- hwe/sammo/Constraint/DifferentDestNation.php | 32 +++ .../Constraint/ExistsAllowJoinNation.php | 12 +- hwe/sammo/Constraint/ReqDestNationValue.php | 139 ++++++++++ hwe/sammo/Constraint/ReqGeneralValue.php | 23 +- hwe/sammo/Constraint/ReqNationValue.php | 7 +- hwe/sammo/DummyGeneral.php | 9 +- hwe/sammo/Engine/Personnel.php | 181 ------------- hwe/sammo/General.php | 6 +- hwe/sammo/GeneralAI.php | 2 +- hwe/sammo/LazyVarUpdater.php | 44 ++- hwe/sammo/ScoutMessage.php | 52 ++-- hwe/sql/schema.sql | 1 - 20 files changed, 560 insertions(+), 247 deletions(-) delete mode 100644 hwe/license.txt create mode 100644 hwe/sammo/Command/General/che_등용수락.php create mode 100644 hwe/sammo/Constraint/DifferentDestNation.php create mode 100644 hwe/sammo/Constraint/ReqDestNationValue.php delete mode 100644 hwe/sammo/Engine/Personnel.php diff --git a/hwe/license.txt b/hwe/license.txt deleted file mode 100644 index 642b3e1a..00000000 --- a/hwe/license.txt +++ /dev/null @@ -1 +0,0 @@ -Ok Go! \ No newline at end of file diff --git a/hwe/sammo/Command/BaseCommand.php b/hwe/sammo/Command/BaseCommand.php index 97105ed0..0a08f96d 100644 --- a/hwe/sammo/Command/BaseCommand.php +++ b/hwe/sammo/Command/BaseCommand.php @@ -25,13 +25,15 @@ abstract class BaseCommand{ return $this->getName(); } + /** @var \sammo\General */ protected $generalObj = null; protected $city = null; protected $nation = null; protected $arg = null; protected $env = null; - protected $destGeneralObj = null; + /** @var \sammo\General */ + protected $destGeneralObj = null; protected $destCity = null; protected $destNation = null; diff --git a/hwe/sammo/Command/General/che_등용.php b/hwe/sammo/Command/General/che_등용.php index 3fb78016..50d01b26 100644 --- a/hwe/sammo/Command/General/che_등용.php +++ b/hwe/sammo/Command/General/che_등용.php @@ -147,7 +147,7 @@ class che_등용 extends Command\GeneralCommand{ $general->increaseVar('experience', $exp); $general->increaseVar('dedication', $ded); - $general->increaseVar('intel2', 1); + $general->increaseVar('leadership2', 1); $general->increaseVarWithLimit('gold', -$reqGold, 0); $general->setResultTurn(new LastTurn(static::getName(), $this->arg)); diff --git a/hwe/sammo/Command/General/che_등용수락.php b/hwe/sammo/Command/General/che_등용수락.php new file mode 100644 index 00000000..98f903fd --- /dev/null +++ b/hwe/sammo/Command/General/che_등용수락.php @@ -0,0 +1,253 @@ +arg === null){ + return false; + } + //NOTE: 사망 직전에 '등용' 턴을 넣을 수 있으므로, 존재하지 않는 장수여도 argTest에서 바로 탈락시키지 않음 + if(!key_exists('destGeneralID', $this->arg)){ + return false; + } + $destGeneralID = $this->arg['destGeneralID']; + if(!is_int($destGeneralID)){ + return false; + } + if($destGeneralID <= 0){ + return false; + } + if($destGeneralID == $this->generalObj->getID()){ + return false; + } + $this->arg = [ + 'destGeneralID'=>$destGeneralID + ]; + return true; + } + + protected function init(){ + + $general = $this->generalObj; + $this->setNation(['gennum', 'scout']); + + $destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['nation'], 0); + $this->setDestGeneral($destGeneral); + $this->setDestNation($this->arg['destNationID'], ['gennum', 'scout']); + + $relYear = $this->env['year'] - $this->env['startyear']; + + $this->reservableConstraints = [ + ConstraintHelper::AlwaysFail('예약 불가능 커맨드') + ]; + + $this->runnableConstraints=[ + ConstraintHelper::ReqEnvValue('join_mode', '==', 'onlyRandom', '랜덤 임관만 가능합니다'), + ConstraintHelper::NotOpeningPart($relYear), + ConstraintHelper::ExistsDestNation(), + ConstraintHelper::AllowJoinDestNation($relYear), + ConstraintHelper::ReqDestNationValue('level', '국가규모', '>', 0, '방랑군에는 임관할 수 없습니다.'), + ConstraintHelper::DifferentDestNation(), + ConstraintHelper::ReqGeneralValue('level', '직위', '!=', 12, '군주는 등용장을 수락할 수 없습니다') + ]; + } + + public function getCost():array{ + return [0, 0]; + } + + public function getPreReqTurn():int{ + return 0; + } + + public function getPostReqTurn():int{ + return 0; + } + + public function run():bool{ + if(!$this->isRunnable()){ + throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도'); + } + + $db = DB::db(); + $env = $this->env; + + $general = $this->generalObj; + $generalID = $general->getID(); + $generalName = $general->getName(); + $cityID = $general->getVar('city'); + $nationID = $general->getNationID(); + + $destGeneral = $this->destGeneralObj; + $destNationID = $this->destNation['nation']; + $destNationName = $this->destNation['name']; + + $relYear = $env['year'] - $env['startyear']; + if($general->getVar('npc') == 1 || $relYear >= 3){ + $joinedNations = $general->getAuxVar('joinedNations')??[]; + $joinedNations[] = $destNationID; + $general->setAuxVar('joinedNations', $joinedNations); + } + + $isTroopLeader = ($generalID == $general->getVar('troop')); + + $destGeneral->increaseVar('experience', $destGeneral->onCalcStat($general, 'experience', 100)); + $destGeneral->increaseVar('dedication', $destGeneral->onCalcStat($general, 'dedication', 100)); + + $setOriginalCityValues = []; + $setOriginalNationValues = [ + 'gennum'=>$db->sqleval('gennum - 1') + ]; + + $setScoutNationValues = [ + 'gennum'=>$db->sqleval('gennum + 1') + ]; + + if($nationID != 0){ + // 기본 금액 남기고 환수 + if($general->getVar('gold') > GameConst::$defaultGold){ + $setOriginalNationValues['gold'] = $db->sqleval('gold + %i', $general->getVar('gold') - GameConst::$defaultGold); + $general->setVar('gold', GameConst::$defaultGold); + } + + if($general->getVar('rice') > GameConst::$defaultRice){ + $setOriginalNationValues['rice'] = $db->sqleval('rice + %i', $general->getVar('rice') - GameConst::$defaultRice); + $general->setVar('rice', GameConst::$defaultRice); + } + + $generalLevel = $general->getVar('level'); + if(5 <= $generalLevel && $generalLevel <= 11){ + $setOriginalNationValues["l{$generalLevel}set"] = 0; + } + else if(2 <= $generalLevel && $generalLevel <= 4){ + $setOriginalCityValues['officer'.$generalLevel] = 0; + } + + // 재야가 아니면 명성N*10% 공헌N*10%감소 + $general->setVar('experience', $general->getVar('experience') * (1 - 0.1 * $general->getVar('betray'))); + $general->setVar('dedication', $general->getVar('dedication') * (1 - 0.1 * $general->getVar('betray'))); + $general->increaseVar('betray', 1); + } + else{ + $general->increaseVar('experience', $general->onCalcStat($general, 'experience', 100)); + $general->increaseVar('dedication', $general->onCalcStat($general, 'dedication', 100)); + } + + if($general->getVar('npc') < 2){ + $general->setVar('killturn', $env['killturn']); + } + + + $logger = $general->getLogger(); + $destLogger = $destGeneral->getLogger(); + + $josaRo = JosaUtil::pick($destNationName, '로'); + $josaYi = JosaUtil::pick($generalName, '이'); + $logger->pushGeneralActionLog("{$destNationName}{$josaRo} 망명하여 수도로 이동합니다."); + $destLogger->pushGeneralActionLog("{$generalName} 등용에 성공했습니다."); + + $logger->pushGeneralHistoryLog("{$destNationName}{$josaRo} 망명"); + $destLogger->pushGeneralHistoryLog("{$generalName} 등용에 성공"); + + $logger->pushGlobalActionLog("{$generalName}{$josaYi} {$destNationName}{$josaRo} 망명하였습니다."); + + if($nationID != 0){ + $db->update('nation', $setOriginalNationValues, 'nation=%i', $nationID); + } + $db->update('nation', $setScoutNationValues, 'nation=%i', $destNationID); + if($setOriginalCityValues){ + $db->update('city', $setOriginalCityValues, 'city=%i', $cityID); + } + + + $general->setVar('permission', 'normal'); + $general->setVar('belong', 1); + $general->setVar('level', 1); + $general->setVar('nation', $destNationID); + $general->setVar('city', $this->destNation['capital']); + $general->setVar('troop', 0); + + if($isTroopLeader){ + // 모두 탈퇴 + $db->update('general', [ + 'troop'=>0, + ], 'troop_leader=%i', $generalID); + // 부대 삭제 + $db->delete('troop', 'troop_leader=%i', $generalID); + } + + + $general->applyDB($db); + $destGeneral->applyDB($db); + + return true; + } + + public function getForm(): string + { + $db = DB::db(); + + $destGenerals = []; + $destRawGenerals = $db->query('SELECT no,name,npc,nation FROM general WHERE npc < 2 AND no != %i AND level != 12 ORDER BY npc,binary(name)',$this->generalObj->getID()); + foreach($destRawGenerals as $destGeneral){ + $destNationID = $destGeneral['nation']; + if(!key_exists($destNationID, $destGenerals)){ + $destGenerals[$destNationID] = []; + } + $destGenerals[$destNationID] = [$destGeneral]; + } + + $nationList = array_merge([0=>getNationStaticInfo(0)], getAllNationStaticInfo()); + + ob_start(); +?> +재야나 타국의 장수를 등용합니다.
+서신은 개인 메세지로 전달됩니다.
+등용할 장수를 목록에서 선택하세요.
+
+ getVar('nations')), $this->arg['destNationIDList']); + $notIn = array_merge($general->getAuxVar('joinedNations')??[], $this->arg['destNationIDList']); $destNation = null; @@ -257,9 +257,9 @@ class che_랜덤임관 extends Command\GeneralCommand{ $relYear = $env['year'] - $env['startyear']; if($general->getVar('npc') == 1 || $relYear >= 3){ - $joinedNations = Json::decode($general->getVar('nations')); + $joinedNations = $general->getAuxVar('joinedNations')??[]; $joinedNations[] = $destNationID; - $general->setVar('nations', Json::encode($joinedNations)); + $general->setAuxVar('joinedNations', $joinedNations); } $general->increaseVar('experience', $exp); diff --git a/hwe/sammo/Command/General/che_임관.php b/hwe/sammo/Command/General/che_임관.php index 8ebea4b7..f818a77d 100644 --- a/hwe/sammo/Command/General/che_임관.php +++ b/hwe/sammo/Command/General/che_임관.php @@ -173,9 +173,9 @@ class che_임관 extends Command\GeneralCommand{ $relYear = $env['year'] - $env['startyear']; if($general->getVar('npc') == 1 || $relYear >= 3){ - $joinedNations = Json::decode($general->getVar('nations')); + $joinedNations = $general->getAuxVar('joinedNations')??[]; $joinedNations[] = $destNationID; - $general->setVar('nations', Json::encode($joinedNations)); + $general->setAuxVar('joinedNations', $joinedNations); } $general->increaseVar('experience', $exp); diff --git a/hwe/sammo/Constraint/AllowJoinDestNation.php b/hwe/sammo/Constraint/AllowJoinDestNation.php index c47d76d3..28d21de9 100644 --- a/hwe/sammo/Constraint/AllowJoinDestNation.php +++ b/hwe/sammo/Constraint/AllowJoinDestNation.php @@ -14,6 +14,16 @@ class AllowJoinDestNation extends Constraint{ return false; } + if(!key_exists('auxVar', $this->general)){ + if(!$throwExeception){return false; } + throw new \InvalidArgumentException("require auxVar in general"); + } + + if(!key_exists('joinedNations', $this->general['auxVar'])){ + if(!$throwExeception){return false; } + throw new \InvalidArgumentException("require joinedNations in general['auxVar']"); + } + if(!key_exists('scout', $this->destNation)){ if(!$throwExeception){return false; } throw new \InvalidArgumentException("require scout in nation"); @@ -24,11 +34,6 @@ class AllowJoinDestNation extends Constraint{ throw new \InvalidArgumentException("require gennum in nation"); } - if(!key_exists('nations', $this->general)){ - if(!$throwExeception){return false; } - throw new \InvalidArgumentException("require nations in nation"); - } - $this->relYear = $this->arg; return true; @@ -50,7 +55,7 @@ class AllowJoinDestNation extends Constraint{ return false; } - $joinedNations = \sammo\Json::decode($this->general['nations']); + $joinedNations = $this->general['auxVar']['joinedNations']; if(in_array($this->destNation['nation'], $joinedNations)){ $this->reason = "이미 임관했었던 국가입니다."; return false; diff --git a/hwe/sammo/Constraint/ConstraintHelper.php b/hwe/sammo/Constraint/ConstraintHelper.php index 0152ca51..d332e094 100644 --- a/hwe/sammo/Constraint/ConstraintHelper.php +++ b/hwe/sammo/Constraint/ConstraintHelper.php @@ -68,6 +68,10 @@ class ConstraintHelper{ return [__FUNCTION__]; } + static function DifferentDestNation():array{ + return [__FUNCTION__]; + } + static function DisallowDiplomacyBetweenStatus(array $disallowList):array{ return [__FUNCTION__, $disallowList]; } @@ -176,6 +180,10 @@ class ConstraintHelper{ return [__FUNCTION__, $npcType]; } + static function ReqDestNationValue($key, string $keyNick, string $comp, $reqVal, ?string $errMsg=null):array{ + return [__FUNCTION__, [$key, $keyNick, $comp, $reqVal, $errMsg]]; + } + static function ReqEnvValue($key, string $comp, $reqVal, string $failMessage):array{ return [__FUNCTION__, [$key, $comp, $reqVal, $failMessage]]; } @@ -204,8 +212,8 @@ class ConstraintHelper{ return [__FUNCTION__, $maxTrain]; } - static function ReqGeneralValue($key, string $keyNick, string $comp, $reqVal):array{ - return [__FUNCTION__, [$key, $keyNick, $comp, $reqVal]]; + static function ReqGeneralValue($key, string $keyNick, string $comp, $reqVal, ?string $errMsg=null):array{ + return [__FUNCTION__, [$key, $keyNick, $comp, $reqVal, $errMsg]]; } static function ReqNationGold(int $reqGold):array{ diff --git a/hwe/sammo/Constraint/DifferentDestNation.php b/hwe/sammo/Constraint/DifferentDestNation.php new file mode 100644 index 00000000..f865bd62 --- /dev/null +++ b/hwe/sammo/Constraint/DifferentDestNation.php @@ -0,0 +1,32 @@ +general)){ + if(!$throwExeception){return false; } + throw new \InvalidArgumentException("require nation in general"); + } + + return true; + } + + public function test():bool{ + $this->checkInputValues(); + $this->tested = true; + + if($this->destNation['nation'] != $this->general['nation']){ + return true; + } + + $this->reason = "이미 같은 국가입니다."; + return false; + } +} \ No newline at end of file diff --git a/hwe/sammo/Constraint/ExistsAllowJoinNation.php b/hwe/sammo/Constraint/ExistsAllowJoinNation.php index e1f9e3ee..ebfdfc3a 100644 --- a/hwe/sammo/Constraint/ExistsAllowJoinNation.php +++ b/hwe/sammo/Constraint/ExistsAllowJoinNation.php @@ -3,6 +3,7 @@ namespace sammo\Constraint; use \sammo\DB; use \sammo\GameConst; +use \sammo\Json; class AllowJoinDestNation extends Constraint{ const REQ_VALUES = Constraint::REQ_GENERAL|Constraint::REQ_ARRAY_ARG; @@ -14,9 +15,14 @@ class AllowJoinDestNation extends Constraint{ return false; } - if(!key_exists('nations', $this->general)){ + if(!key_exists('auxVar', $this->general)){ if(!$throwExeception){return false; } - throw new \InvalidArgumentException("require nations in nation"); + throw new \InvalidArgumentException("require auxVar in general"); + } + + if(!key_exists('joinedNations', $this->general['auxVar'])){ + if(!$throwExeception){return false; } + throw new \InvalidArgumentException("require joinedNations in general['auxVar']"); } if(!is_int($this->arg[0])){ @@ -41,7 +47,7 @@ class AllowJoinDestNation extends Constraint{ $db = DB::db(); $relYear = $this->arg[0]; - $notIn = array_merge(Json::decode($this->general['nations']), $this->arg[1]); + $notIn = array_merge($this->general['auxVar']['joinedNations'], $this->arg[1]); //이걸 호출하는 경우 분명 동일한 쿼리를 한번 더 부를 것. 쿼리 캐시를 기대함 $nations = $db->queryFirstColumn( 'SELECT nation, name, gennum, scout FROM nation WHERE scout=0 AND gennum < %i AND no NOT IN %li', diff --git a/hwe/sammo/Constraint/ReqDestNationValue.php b/hwe/sammo/Constraint/ReqDestNationValue.php new file mode 100644 index 00000000..ff3d2e19 --- /dev/null +++ b/hwe/sammo/Constraint/ReqDestNationValue.php @@ -0,0 +1,139 @@ +arg) == 5){ + [$this->key, $this->keyNick, $comp, $this->reqVal, $this->errMsg] = $this->arg; + + if(!in_array($comp, ['>', '>=', '==', '<=', '<', '!=', '===', '!=='])){ + if(!$throwExeception){return false; } + throw new \InvalidArgumentException("invalid comparator"); + } + } + else{ + if(!$throwExeception){return false; } + throw new \InvalidArgumentException("require key, keyNick, comp, reqVal[, errMsg]"); + } + + $this->comp = $comp; + + $this->maxKey = $this->key.'2'; + + if(!key_exists($this->key, $this->destNation)){ + if(!$throwExeception){return false; } + throw new \InvalidArgumentException("require {$this->key} in destNation"); + } + + if(is_numeric($this->reqVal)){ + $this->isPercent = false; + } + else if(is_string($this->reqVal)){ + $this->reqVal = Util::convPercentStrToFloat($this->reqVal); + if($this->reqVal === null){ + if(!$throwExeception){return false; } + throw new \InvalidArgumentException("require valid reqVal(percentStr|numeric) format"); + } + + if(!key_exists($this->maxKey, $this->destNation)){ + if(!$throwExeception){return false; } + throw new \InvalidArgumentException("require {$this->maxKey} in destNation"); + } + $this->isPercent = true; + } + + if($this->errMsg!==null && !is_string($this->errMsg)){ + if(!$throwExeception){return false; } + throw new \InvalidArgumentException("{$this->errMsg} must be string or null"); + } + + return true; + } + + public function test():bool{ + $this->checkInputValues(); + $this->tested = true; + $keyNick = $this->keyNick; + + if ($this->isPercent) { + $reqVal = $this->destNation[$this->maxKey] * $this->reqVal; + } + else{ + $reqVal = $this->reqVal; + } + + $compList = [ + '<'=>function($target, $src){ + return ($target < $src)?true:'너무 많습니다.'; + }, + '<='=>function($target, $src){ + return ($target <= $src)?true:'너무 많습니다.'; + }, + '=='=>function($target, $src)use($keyNick){ + return ($target == $src)?true:"올바르지 않은 {$keyNick} 입니다."; + }, + '!='=>function($target, $src)use($keyNick){ + return ($target != $src)?true:"올바르지 않은 {$keyNick} 입니다."; + }, + '==='=>function($target, $src)use($keyNick){ + return ($target === $src)?true:"올바르지 않은 {$keyNick} 입니다."; + }, + '!=='=>function($target, $src)use($keyNick){ + return ($target !== $src)?true:"올바르지 않은 {$keyNick} 입니다."; + }, + '>='=>function($target, $src){ + if($target >= $src){ + return true; + } + if($src == 1){ + return '없습니다'; + } + return '부족합니다.'; + }, + '>'=>function($target, $src){ + return $target > $src; + if($src == 0){ + return '없습니다'; + } + return '부족합니다.'; + }, + ]; + + $comp = $compList[$this->comp]; + $result = ($comp)($this->destNation[$this->key], $reqVal); + + if($result === true){ + return true; + } + + if($this->errMsg){ + $this->reason = $this->errMsg; + } + else{ + $josaYi = JosaUtil::pick($keyNick, '이'); + $this->reason = "{$keyNick}{$josaYi} {$result}"; + } + + return false; + } +} \ No newline at end of file diff --git a/hwe/sammo/Constraint/ReqGeneralValue.php b/hwe/sammo/Constraint/ReqGeneralValue.php index 489d25e3..4a0d3857 100644 --- a/hwe/sammo/Constraint/ReqGeneralValue.php +++ b/hwe/sammo/Constraint/ReqGeneralValue.php @@ -16,14 +16,15 @@ class ReqGeneralValue extends Constraint{ protected $keyNick; protected $reqVal; protected $comp; + protected $errMsg; public function checkInputValues(bool $throwExeception=true):bool{ if(!parent::checkInputValues($throwExeception) && !$throwExeception){ return false; } - if(count($this->arg) == 4){ - [$this->key, $this->keyNick, $comp, $this->reqVal] = $this->arg; + if(count($this->arg) == 5){ + [$this->key, $this->keyNick, $comp, $this->reqVal, $this->errMsg] = $this->arg; if(!in_array($comp, ['>', '>=', '==', '<=', '<', '!=', '===', '!=='])){ if(!$throwExeception){return false; } @@ -32,7 +33,7 @@ class ReqGeneralValue extends Constraint{ } else{ if(!$throwExeception){return false; } - throw new \InvalidArgumentException("require key, keyNick, comp, reqVal"); + throw new \InvalidArgumentException("require key, keyNick, comp, reqVal[, errMsg]"); } $this->comp = $comp; @@ -47,7 +48,7 @@ class ReqGeneralValue extends Constraint{ if(is_numeric($this->reqVal)){ $this->isPercent = false; } - else if(is_str($this->reqVal)){ + else if(is_string($this->reqVal)){ $this->reqVal = Util::convPercentStrToFloat($this->reqVal); if($this->reqVal === null){ if(!$throwExeception){return false; } @@ -61,6 +62,11 @@ class ReqGeneralValue extends Constraint{ $this->isPercent = true; } + if($this->errMsg!==null && !is_string($this->errMsg)){ + if(!$throwExeception){return false; } + throw new \InvalidArgumentException("{$this->errMsg} must be string or null"); + } + return true; } @@ -120,8 +126,13 @@ class ReqGeneralValue extends Constraint{ return true; } - $josaYi = JosaUtil::pick($keyNick, '이'); - $this->reason = "{$keyNick}{$josaYi} {$result}"; + if($this->errMsg){ + $this->reason = $this->errMsg; + } + else{ + $josaYi = JosaUtil::pick($keyNick, '이'); + $this->reason = "{$keyNick}{$josaYi} {$result}"; + } return false; } diff --git a/hwe/sammo/Constraint/ReqNationValue.php b/hwe/sammo/Constraint/ReqNationValue.php index 58b51bcf..e7dd84ee 100644 --- a/hwe/sammo/Constraint/ReqNationValue.php +++ b/hwe/sammo/Constraint/ReqNationValue.php @@ -62,6 +62,11 @@ class ReqNationValue extends Constraint{ $this->isPercent = true; } + if($this->errMsg!==null && !is_string($this->errMsg)){ + if(!$throwExeception){return false; } + throw new \InvalidArgumentException("{$this->errMsg} must be string or null"); + } + return true; } @@ -121,11 +126,11 @@ class ReqNationValue extends Constraint{ return true; } - $josaYi = JosaUtil::pick($keyNick, '이'); if($this->errMsg){ $this->reason = $this->errMsg; } else{ + $josaYi = JosaUtil::pick($keyNick, '이'); $this->reason = "{$keyNick}{$josaYi} {$result}"; } diff --git a/hwe/sammo/DummyGeneral.php b/hwe/sammo/DummyGeneral.php index e0b4833a..5db5198d 100644 --- a/hwe/sammo/DummyGeneral.php +++ b/hwe/sammo/DummyGeneral.php @@ -10,7 +10,11 @@ class DummyGeneral extends General{ 'nation'=>0, 'level'=>0, 'crewtype'=>-1, - 'turntime'=>'2012-03-04 05:06:07.000000' + 'turntime'=>'2012-03-04 05:06:07.000000', + 'experience'=>0, + 'dedication'=>0, + 'gold'=>0, + 'rice'=>0, ]; $this->raw = $raw; @@ -31,6 +35,9 @@ class DummyGeneral extends General{ } function applyDB($db):bool{ + if($this->logger){ + $this->initLogger(1, 1); + } return true; } } \ No newline at end of file diff --git a/hwe/sammo/Engine/Personnel.php b/hwe/sammo/Engine/Personnel.php deleted file mode 100644 index 7f4e89a7..00000000 --- a/hwe/sammo/Engine/Personnel.php +++ /dev/null @@ -1,181 +0,0 @@ -queryFirstRow( - 'SELECT nation, `name`, `level`, capital, scout FROM nation WHERE nation=%i', - $nationID - ); - - if(!$nation){ - return; - } - - $this->senderID = $senderID; - $this->nation = $nation; - $this->valid = true; - - [ - $this->startYear, - $this->year, - $this->month, - $this->killturn - ] = $gameStor->getValuesAsArray(['startyear', 'year', 'month', 'killturn']); - - } - - public function checkAgreeValidation(array $general){ - - if(!$this->valid){ - return [ScoutMessage::DECLINED, '이미 멸망한 국가입니다.']; - } - - if($this->year < $this->startYear + 3){ - return [ScoutMessage::INVALID, '초반제한 중입니다.']; - } - - if($this->nation['scout']){ - return [ScoutMessage::INVALID, '현재 임관금지 중인 국가입니다.']; - } - - if($this->nation['level'] == 0){ - return [ScoutMessage::DECLINED, '방랑군에는 임관할 수 없습니다.']; - } - - if($this->nation['nation'] == $general['nation']){ - return [ScoutMessage::DECLINED, '이미 같은 국가입니다.']; - } - - if($general['level'] == 12){ - return [ScoutMessage::DECLINED, '군주는 등용장을 수락할 수 없습니다.']; - } - - if(in_array($this->nation['nation'], Json::decode($general['nations']))){ - return [ScoutMessage::DECLINED, '이미 임관했었던 국가입니다.']; - } - - return [ScoutMessage::ACCEPTED, '']; - } - - public function scoutGeneral(int $generalID){ - $db = DB::db(); - - $general = $db->queryFirstRow( - 'SELECT `no`, `name`, nation, nations, city, `level`, troop, npc, gold, rice FROM general WHERE `no`=%i', - $generalID - ); - - list($result, $reason) = $this->checkAgreeValidation($general); - if($result !== ScoutMessage::ACCEPTED){ - return [$result, $reason]; - } - - $isTroopLeader = ($generalID == $general['troop']); - - $joinedNations = Json::decode($general['nations']); - $joinedNations[] = $this->nation['nation']; - - // 국가 변경, 도시 변경, 일반으로, 수도로 - $setValues = [ - 'belong'=>1, - 'level'=>1, - 'nation'=>$this->nation['nation'], - 'city'=>$this->nation['capital'], - 'nations'=>Json::encode($joinedNations), - 'troop'=>0, - ]; - - $setSenderValues = [ - 'experience'=>$db->sqleval('experience + %i', 100),//XXX: 상수. - 'dedication'=>$db->sqleval('dedication + %i', 100) - ]; - - $setOriginalNationValues = [ - 'gennum'=>$db->sqleval('gennum - 1') - ]; - - $setScoutNationValues = [ - 'gennum'=>$db->sqleval('gennum + 1') - ]; - - $setOriginalCityValues = []; - - // 재야가 아니면 명성N*10% 공헌N*10%감소 - if($general['nation'] != 0){ - // 기본 금액 남기고 환수 - if($general['gold'] > GameConst::$defaultGold){ - $setValues['gold'] = GameConst::$defaultGold; - $setOriginalNationValues['gold'] = $db->sqleval('gold + %i', $general['gold'] - GameConst::$defaultGold); - } - - if($general['rice'] > GameConst::$defaultRice){//XXX: 상수. - $setValues['rice'] = GameConst::$defaultRice; - $setOriginalNationValues['rice'] = $db->sqleval('rice + %i', $general['rice'] - GameConst::$defaultRice); - } - - //관직 해제 - if(5 <= $general['level'] && $general['level'] <= 11){ - $setOriginalNationValues["l{$general['level']}set"] = 0; - } - else if(2 <= $general['level'] && $general['level'] <= 4){ - $setOriginalCityValues['officer'.$general['level']] = 0; - } - - $setValues['experience'] = $db->sqleval('experience * (1 - 0.1 * betray)');//XXX: 상수 - $setValues['dedication'] = $db->sqleval('dedication * (1 - 0.1 * betray)');//XXX: 상수 - $setValues['betray'] = $db->sqleval('betray + 1'); - } - else{ - //재야이면 100 100 증가 - $setValues['experience'] = $db->sqleval('experience + %i', 100);//XXX: 상수 - $setValues['dedication'] = $db->sqleval('experience + %i', 100);//XXX: 상수 - } - - if($general['npc'] < 2){ - $setValues['killturn'] = $this->killturn; - } - - $setValues['permission'] = 'normal'; - - $db->update('general', $setValues, 'no=%i', $generalID); - $db->update('general', $setSenderValues, 'no=%i', $this->senderID); - $db->update('nation', $setOriginalNationValues, 'nation=%i', $general['nation']); - $db->update('nation', $setScoutNationValues, 'nation=%i', $this->nation['nation']); - if($setOriginalCityValues){ - $db->update('city', $setOriginalCityValues, 'city=%i', $general['city']); - } - - if($isTroopLeader){ - // 모두 탈퇴 - $db->update('general', [ - 'troop'=>0, - ], 'troop_leader=%i', $generalID); - // 부대 삭제 - $db->delete('troop', 'troop_leader=%i', $generalID); - } - - return [ScoutMessage::ACCEPTED, '']; - } -} \ No newline at end of file diff --git a/hwe/sammo/General.php b/hwe/sammo/General.php index ad9db9df..c7a735c8 100644 --- a/hwe/sammo/General.php +++ b/hwe/sammo/General.php @@ -18,13 +18,13 @@ class General implements iAction{ protected $raw = []; protected $rawCity = null; + /** @var \sammo\ActionLogger */ protected $logger; protected $activatedSkill = []; protected $logActivatedSkill = []; protected $isFinished = false; - protected $nationType = null; protected $levelObj = null; protected $specialDomesticObj = null; @@ -681,14 +681,14 @@ class General implements iAction{ 'horse', 'weapon', 'book', 'item', 'last_turn' ]; $fullColumn = [ - 'no', 'name', 'name2', 'picture', 'imgsvr', 'nation', 'nations', 'city', 'troop', 'injury', 'affinity', + 'no', 'name', 'name2', 'picture', 'imgsvr', 'nation', 'city', 'troop', 'injury', 'affinity', 'leadership', 'leadership2', 'strength', 'strength2', 'intel', 'intel2', 'weapon', 'book', 'horse', 'item', 'experience', 'dedication', 'level', 'gold', 'rice', 'crew', 'crewtype', 'train', 'atmos', 'turntime', 'makelimit', 'killturn', 'block', 'dedlevel', 'explevel', 'age', 'startage', 'belong', 'personal', 'special', 'special2', 'defence_train', 'tnmt', 'npc', 'npc_org', 'deadyear', 'npcmsg', 'dex0', 'dex10', 'dex20', 'dex30', 'dex40', 'warnum', 'firenum', 'killnum', 'deathnum', 'killcrew', 'deathcrew', 'recwar', 'last_turn', 'myset', - 'specage', 'specage2', 'con', 'connect', 'owner' + 'specage', 'specage2', 'con', 'connect', 'owner', 'aux' ]; if($column === null){ diff --git a/hwe/sammo/GeneralAI.php b/hwe/sammo/GeneralAI.php index bb85f264..e293ec9d 100644 --- a/hwe/sammo/GeneralAI.php +++ b/hwe/sammo/GeneralAI.php @@ -1022,7 +1022,7 @@ class GeneralAI{ if($general->getVar('npc') == 9) { $rulerNation = $db->queryFirstField( 'SELECT nation FROM general WHERE `level`=12 AND npc=9 and nation not in %li ORDER BY RAND() limit 1', - Json::decode($general->getVar('nations')) + $general->getAuxVar('joinedNations')??[0] ); if($rulerNation){ diff --git a/hwe/sammo/LazyVarUpdater.php b/hwe/sammo/LazyVarUpdater.php index a6b887dd..5808d910 100644 --- a/hwe/sammo/LazyVarUpdater.php +++ b/hwe/sammo/LazyVarUpdater.php @@ -4,8 +4,13 @@ namespace sammo; trait LazyVarUpdater{ protected $raw = []; protected $updatedVar = []; + protected $auxUpdated = false; - function getRaw():array{ + function getRaw(bool $extractAux=false):array{ + if($extractAux){ + $this->getAuxVar(''); + + } return $this->raw; } @@ -26,10 +31,43 @@ trait LazyVarUpdater{ return true; } + protected function unpackAux(){ + if($this->raw['auxVar']??null === null){ + if(!key_exists('aux', $this->raw)){ + throw new \RuntimeException('aux is not set'); + } + $this->raw['auxVar'] = Json::decode($this->raw['aux']); + } + } + function setVar(string $key, $value){ return $this->updateVar($key, $value); } + function getAuxVar(string $key){ + $this->unpackAux(); + return $this->raw['auxVar'][$key]??null; + } + + function setAuxVar(string $key, $var){ + $oldVar = $this->getAuxVar($key); + + if($var === null){ + if($oldVar === null){ + return; + } + unset($this->auxVar[$key]); + $this->auxUpdated = true; + return; + } + + if($oldVar === $var){ + return; + } + $this->raw['auxVar'][$key] = $var; + $this->auxUpdated = true; + } + function updateVar(string $key, $value){ if(!key_exists($key, $this->updatedVar)){ $this->updatedVar[$key] = $this->raw[$key]; @@ -91,6 +129,10 @@ trait LazyVarUpdater{ } function getUpdatedValues():array { + if($this->auxUpdated){ + $this->setVar('aux', Json::encode($this->raw['auxVar'])); + $this->auxUpdated = false; + } $updateVals = []; foreach(array_keys($this->updatedVar) as $key){ $updateVals[$key] = $this->raw[$key]; diff --git a/hwe/sammo/ScoutMessage.php b/hwe/sammo/ScoutMessage.php index 66f67871..23e341bc 100644 --- a/hwe/sammo/ScoutMessage.php +++ b/hwe/sammo/ScoutMessage.php @@ -59,58 +59,44 @@ class ScoutMessage extends Message{ //NOTE: 올바른 유저가 agreeMessage() 호출을 한건지는 외부에서 체크 필요(Session->userID 등) if(!$this->id){ - throw \RuntimeException('전송되지 않은 메시지에 수락 진행 중'); + throw new \RuntimeException('전송되지 않은 메시지에 수락 진행 중'); } + $gameStor = KVStorage::getStorage(DB::db(), 'game_env'); + $general = \sammo\General::createGeneralObjFromDB($receiverID, ['npc', 'gold', 'rice', 'experience', 'dedication', 'betray', 'troop', 'aux'], 1); + + $logger = $general->getLogger(); + list($result, $reason) = $this->checkScoutMessageValidation($receiverID); if($result !== self::ACCEPTED){ - pushGenLog(['no'=>$receiverID], ["●{$reason} 등용 수락 불가."]); + $logger->pushGeneralActionLog("{$reason} 등용 수락 불가."); if($result === self::DECLINED){ $this->_declineMessage(); } return $result; } - $helper = new Engine\Personnel($this->src->nationID, $this->src->generalID); + $commandObj = buildGeneralCommandClass('che_등용수락', $general, $gameStor->getAll(true), [ + 'destNationID'=>$this->src->nationID, + 'destGeneralID'=>$this->src->generalID, + 'year'=>$this->msgOption['year'], + 'month'=>$this->msgOption['month'] + ]); - list($result, $reason) = $helper->scoutGeneral($receiverID); - - if($result !== self::ACCEPTED){ - pushGenLog(['no'=>$receiverID], ["●{$reason} 등용 수락 불가."]); - if($result === self::DECLINED){ - $this->_declineMessage(); - } - return $result; + if(!$commandObj->isRunnable()){ + $logger->pushGeneralActionLog($commandObj->getFailString()); + return self::DECLINED; } + $commandObj->run(); + //메시지 비 활성화 $this->msgOption['used'] = true; $this->invalidate(); $this->validScout = false; $josaRo = JosaUtil::pick($this->src->nationName, '로'); - $josaYi = JosaUtil::pick($this->dest->generalName, '이'); - pushGenLog( - ['no'=>$this->dest->generalID], - ["{$this->src->nationName}{$josaRo} 망명하여 수도로 이동합니다."]); - pushGenLog( - ['no'=>$this->src->generalID], - ["{$this->dest->generalName} 등용에 성공했습니다."] - ); - pushGeneralHistory( - ['no'=>$this->src->generalID], - "●{$helper->year}년 {$helper->month}월:{$this->dest->generalName} 등용에 성공"); - pushGeneralHistory( - ['no'=>$this->dest->generalID], - "●{$helper->year}년 {$helper->month}월:{$this->src->nationName}{$josaRo} 망명" - ); - pushGeneralPublicRecord( - ["●{$helper->month}월:{$this->dest->generalName}{$josaYi} {$this->src->nationName}{$josaRo} 망명하였습니다."], - $helper->year, - $helper->month - ); - $newMsg = new Message( self::MSGTYPE_PRIVATE, $this->src, @@ -151,7 +137,7 @@ class ScoutMessage extends Message{ public function declineMessage(int $receiverID, string &$reason):int{ if(!$this->id){ - throw \RuntimeException('전송되지 않은 메시지에 거절 진행 중'); + throw new \RuntimeException('전송되지 않은 메시지에 거절 진행 중'); } list($result, $reason) = $this->checkScoutMessageValidation($receiverID); diff --git a/hwe/sql/schema.sql b/hwe/sql/schema.sql index 53b8fc07..fb68888c 100644 --- a/hwe/sql/schema.sql +++ b/hwe/sql/schema.sql @@ -22,7 +22,6 @@ CREATE TABLE `general` ( `name` CHAR(32) NOT NULL COLLATE 'utf8mb4_bin', `name2` CHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_bin', `nation` INT(6) NOT NULL DEFAULT '0', - `nations` VARCHAR(64) NOT NULL DEFAULT '[0]', `city` INT(6) NOT NULL DEFAULT '3', `troop` INT(6) NOT NULL DEFAULT '0', `leadership` INT(3) NOT NULL DEFAULT '50',