등용 수락 변경, Aux 처리 추가

nations->aux.joinedNations
dummyGeneral에 exp,ded 추가
scheme에서 nations 제거
This commit is contained in:
2020-03-13 01:44:18 +09:00
parent 3d6b99c004
commit cb246e859e
20 changed files with 560 additions and 247 deletions
-1
View File
@@ -1 +0,0 @@
Ok Go!
+3 -1
View File
@@ -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;
+1 -1
View File
@@ -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));
@@ -0,0 +1,253 @@
<?php
namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
General, DummyGeneral,
ActionLogger,
GameConst,
LastTurn,
Json,
GameUnitConst,
Command,
ScoutMessage
};
use function \sammo\{
getDomesticExpLevelBonus,
CriticalRatioDomestic,
CriticalScoreEx,
tryUniqueItemLottery,
getAllNationStaticInfo,
getNationStaticInfo
};
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
class che_등용수락 extends Command\GeneralCommand{
static protected $actionName = '등용 수락';
static public $reqArg = true;
protected function argTest():bool{
if($this->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("<D>{$destNationName}</>{$josaRo} 망명하여 수도로 이동합니다.");
$destLogger->pushGeneralActionLog("<Y>{$generalName}</> 등용에 성공했습니다.");
$logger->pushGeneralHistoryLog("<D>{$destNationName}</>{$josaRo} 망명");
$destLogger->pushGeneralHistoryLog("<Y>{$generalName}</> 등용에 성공");
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <D><b>{$destNationName}</b></>{$josaRo} <S>망명</>하였습니다.");
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();
?>
재야나 타국의 장수를 등용합니다.<br>
서신은 개인 메세지로 전달됩니다.<br>
등용할 장수를 목록에서 선택하세요.<br>
<select class='formInput' name="destGeneralID" id="destGeneralID" size='1' style='color:white;background-color:black;'>
<?php foreach($nationList as $destNation): ?>
<optgroup style='color:<?=$destNation['color']?>'>【<?=$destNation['name']?>】
<?php foreach($destGenerals[$destNation['nation']]??[] as $destGeneral):
$nameColor = \sammo\getNameColor($destGeneral['npc']);
if($nameColor){
$nameColor = " style='color:{$nameColor}'";
}
?>
<option value='<?=$destGeneral['no']?>' <?=$nameColor?>><?=$destGeneral['name']?></option>
<?php endforeach; ?>
</optgroup>
<?php endforeach; ?>
</select> <input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
<?php
return ob_get_clean();
}
}
@@ -103,7 +103,7 @@ class che_랜덤임관 extends Command\GeneralCommand{
$relYear = $env['year'] - $env['startyear'];
$notIn = array_merge(Json::decode($general->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);
+2 -2
View File
@@ -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);
+11 -6
View File
@@ -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;
+10 -2
View File
@@ -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{
@@ -0,0 +1,32 @@
<?php
namespace sammo\Constraint;
class DifferentDestNation extends Constraint{
const REQ_VALUES = Constraint::REQ_GENERAL|Constraint::REQ_DEST_NATION;
public function checkInputValues(bool $throwExeception=true):bool{
if(!parent::checkInputValues($throwExeception) && !$throwExeception){
return false;
}
if(!key_exists('nation', $this->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;
}
}
@@ -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',
+139
View File
@@ -0,0 +1,139 @@
<?php
namespace sammo\Constraint;
use \sammo\JosaUtil;
use \sammo\Util;
/**
* 범용으로 사용 가능한 국가 변수 검사도구
*/
class ReqDestNationValue extends Constraint{
const REQ_VALUES = Constraint::REQ_DEST_NATION|Constraint::REQ_ARRAY_ARG;
protected $key;
protected $maxKey;
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) == 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;
}
}
+17 -6
View File
@@ -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;
}
+6 -1
View File
@@ -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}";
}
+8 -1
View File
@@ -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;
}
}
-181
View File
@@ -1,181 +0,0 @@
<?php
namespace sammo\Engine;
use \sammo\DB;
use \sammo\ScoutMessage;
use \sammo\KVStorage;
use \sammo\Json;
use \sammo\GameConst;
/**
* 인사(등용, 추방, 임명, 망명) 헬퍼 클래스?
* Nation 클래스가 있고 그걸 상속한 구조가 더 나을지도?
*/
class Personnel{
protected $nation = null;//TODO: 상속체로 변경.
protected $senderID = null;
public $valid = false;
public $startYear = 0;
public $year = 0;
public $month = 0;
public $killturn = 0;
public function __construct(int $nationID, int $senderID){
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$nation = $db->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, ''];
}
}
+3 -3
View File
@@ -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){
+1 -1
View File
@@ -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){
+43 -1
View File
@@ -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];
+19 -33
View File
@@ -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], ["<C>●</>{$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], ["<C>●</>{$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],
["<C>●</><D>{$this->src->nationName}</>{$josaRo} 망명하여 수도로 이동합니다."]);
pushGenLog(
['no'=>$this->src->generalID],
["<C>●</><Y>{$this->dest->generalName}</> 등용에 성공했습니다."]
);
pushGeneralHistory(
['no'=>$this->src->generalID],
"<C>●</>{$helper->year}{$helper->month}월:<Y>{$this->dest->generalName}</> 등용에 성공");
pushGeneralHistory(
['no'=>$this->dest->generalID],
"<C>●</>{$helper->year}{$helper->month}월:<D>{$this->src->nationName}</>{$josaRo} 망명"
);
pushGeneralPublicRecord(
["<C>●</>{$helper->month}월:<Y>{$this->dest->generalName}</>{$josaYi} <D><b>{$this->src->nationName}</b></>{$josaRo} <S>망명</>하였습니다."],
$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);
-1
View File
@@ -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',