diff --git a/LICENSE b/LICENSE index f44828e6..774cd674 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2020 Hide_D, 62che +Copyright (c) 2021 Hide_D, 62che Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/api.php b/api.php new file mode 100644 index 00000000..a6d67bae --- /dev/null +++ b/api.php @@ -0,0 +1,8 @@ +getMessage()); -} - -if (!key_exists('path', $input)) { - Json::dieWithReason('path가 지정되지 않았습니다.'); -} - -if (key_exists('args', $input) && !is_array($input['args'])) { - Json::dieWithReason('args가 array가 아닙니다.' . gettype($input['args'])); -} - -try { - $obj = buildAPIExecutorClass($input['path'], $input['args'] ?? []); - $api = - $validateResult = $obj->validateArgs(); - if ($validateResult !== null) { - Json::dieWithReason($validateResult); - } - - $sessionMode = $obj->getRequiredSessionMode(); - if ($sessionMode === BaseAPI::NO_SESSION) { - $session = null; - } else { - if ($sessionMode & BaseAPI::REQ_GAME_LOGIN) { - $session = Session::requireGameLogin(); - } else if ($sessionMode & BaseAPI::REQ_LOGIN) { - $session = Session::requireLogin(); - } else { - Json::dieWithReason("올바르지 않은 SessionMode: {$sessionMode}"); - } - - if ($sessionMode & BaseAPI::REQ_READ_ONLY) { - $session->setReadOnly(); - } - } - - $modifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) - ? new \DateTimeImmutable($_SERVER['HTTP_IF_MODIFIED_SINCE'], new \DateTimeZone("UTC")) - : null; - $reqEtags = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? trim($_SERVER['HTTP_IF_NONE_MATCH']) : null; - - $result = $obj->launch($session, $modifiedSince, $reqEtags); - if (is_string($result)) { - Json::dieWithReason($result); - } - - $cacheResult = $obj->tryCache(); - if ($cacheResult !== null) { - /** @var \DateTimeInterface $lastModified */ - [$lastModified, $etag] = $cacheResult; - - if ($lastModified !== null) { - header("Last-Modified: " . gmdate("D, d M Y H:i:s", TimeUtil::DateTimeToSeconds($lastModified, true)) . " GMT"); - } - if ($etag !== null) { - header("Etag: $etag"); - } - - if ($modifiedSince !== null && $lastModified !== null && TimeUtil::DateIntervalToSeconds($modifiedSince->diff($lastModified)) == 0) { - header("HTTP/1.1 304 Not Modified"); - die(); - } - if ($reqEtags !== null && $reqEtags === $etag) { - header("HTTP/1.1 304 Not Modified"); - die(); - } - } - - if ($result === null) { - Json::die([ - 'result' => true, - 'reason' => 'success' - ], $cacheResult === null ? Json::NO_CACHE : 0); - } - Json::die($result, $cacheResult === null ? Json::NO_CACHE : 0); -} catch (\Exception $e) { - Json::dieWithReason($e->getMessage()); -} catch (mixed $e) { - Json::dieWithReason($e); -} +APIHelper::launch(dirname(__FILE__)); \ No newline at end of file diff --git a/hwe/func.php b/hwe/func.php index 68ac8331..24d3a532 100644 --- a/hwe/func.php +++ b/hwe/func.php @@ -2,6 +2,7 @@ namespace sammo; +use DateTime; use sammo\Event\Action; require_once 'process_war.php'; @@ -189,7 +190,7 @@ function myNationInfo(General $generalObj) $templates = new \League\Plates\Engine(__DIR__ . '/templates'); $nationID = $generalObj->getNationID(); - $nation = $db->queryFirstRow('SELECT * FROM nation WHERE nation = %i', $nationID)??getNationStaticInfo(0); + $nation = $db->queryFirstRow('SELECT * FROM nation WHERE nation = %i', $nationID) ?? getNationStaticInfo(0); $city = $db->queryFirstRow( 'SELECT COUNT(*) as cnt, SUM(pop) as totpop, SUM(pop_max) as maxpop from city where nation=%i', $nationID @@ -198,16 +199,16 @@ function myNationInfo(General $generalObj) $topChiefs = Util::convertArrayToDict($db->query('SELECT officer_level, no, name, npc FROM general WHERE nation = %i AND officer_level >= 11', $nationID), 'officer_level'); - $level12Name = key_exists(12, $topChiefs)?getColoredName($topChiefs[12]['name'], $topChiefs[12]['npc']):'-'; - $level11Name = key_exists(11, $topChiefs)?getColoredName($topChiefs[11]['name'], $topChiefs[11]['npc']):'-'; + $level12Name = key_exists(12, $topChiefs) ? getColoredName($topChiefs[12]['name'], $topChiefs[12]['npc']) : '-'; + $level11Name = key_exists(11, $topChiefs) ? getColoredName($topChiefs[11]['name'], $topChiefs[11]['npc']) : '-'; $impossibleStrategicCommandLists = []; $strategicCommandLists = GameConst::$availableChiefCommand['전략']; $yearMonth = Util::joinYearMonth($admin['year'], $admin['month']); - foreach($strategicCommandLists as $command){ + foreach ($strategicCommandLists as $command) { $cmd = buildNationCommandClass($command, $generalObj, $admin, new LastTurn()); $nextAvailableTurn = $cmd->getNextAvailableTurn(); - if($nextAvailableTurn > $yearMonth){ + if ($nextAvailableTurn > $yearMonth) { $impossibleStrategicCommandLists[] = [$cmd->getName(), $nextAvailableTurn - $yearMonth]; } } @@ -239,28 +240,28 @@ function myNationInfo(General $generalObj) 총주민 "; - echo $nationID===0 ? "해당 없음" : "{$city['totpop']}/{$city['maxpop']}"; + echo $nationID === 0 ? "해당 없음" : "{$city['totpop']}/{$city['maxpop']}"; echo " 총병사 "; - echo $nationID===0 ? "해당 없음" : "{$general['totcrew']}/{$general['maxcrew']}"; + echo $nationID === 0 ? "해당 없음" : "{$general['totcrew']}/{$general['maxcrew']}"; echo " 국 고 "; - echo $nationID===0 ? "해당 없음" : "{$nation['gold']}"; + echo $nationID === 0 ? "해당 없음" : "{$nation['gold']}"; echo " 병 량 "; - echo $nationID===0 ? "해당 없음" : "{$nation['rice']}"; + echo $nationID === 0 ? "해당 없음" : "{$nation['rice']}"; echo " 지급률 "; - if ($nationID===0) { + if ($nationID === 0) { echo "해당 없음"; } else { echo $nation['bill'] == 0 ? "0 %" : "{$nation['bill']} %"; @@ -269,7 +270,7 @@ function myNationInfo(General $generalObj) 세 율 "; - if ($nationID===0) { + if ($nationID === 0) { echo "해당 없음"; } else { echo $nation['rate'] == 0 ? "0 %" : "{$nation['rate']} %"; @@ -285,7 +286,7 @@ function myNationInfo(General $generalObj) $nation['tech'] = "$techCall / {$nation['tech']}"; - if ($nationID===0) { + if ($nationID === 0) { $nation['strategic_cmd_limit'] = "해당 없음"; $nation['surlimit'] = "해당 없음"; $nation['scout'] = "해당 없음"; @@ -294,20 +295,20 @@ function myNationInfo(General $generalObj) } else { if ($nation['strategic_cmd_limit'] != 0) { $nation['strategic_cmd_limit'] = "{$nation['strategic_cmd_limit']}턴"; - } else if($impossibleStrategicCommandLists) { + } else if ($impossibleStrategicCommandLists) { $nation['strategic_cmd_limit'] = "가 능"; - } else{ + } else { $nation['strategic_cmd_limit'] = "가 능"; } - if($impossibleStrategicCommandLists){ + if ($impossibleStrategicCommandLists) { $text = []; - foreach($impossibleStrategicCommandLists as [$cmdName, $remainTurn]){ + foreach ($impossibleStrategicCommandLists as [$cmdName, $remainTurn]) { $text[] = "{$cmdName}: {$remainTurn}턴 뒤"; } $nation['strategic_cmd_limit'] = $templates->render('tooltip', [ - 'text'=>''.$nation['strategic_cmd_limit'].'', - 'info'=>''.join('
', $text).'
', + 'text' => '' . $nation['strategic_cmd_limit'] . '', + 'info' => '' . join('
', $text) . '
', ]); } @@ -336,11 +337,11 @@ function myNationInfo(General $generalObj) 속 령 "; - echo $nationID===0 ? "-" : "{$city['cnt']}"; + echo $nationID === 0 ? "-" : "{$city['cnt']}"; echo " 장 수 "; - echo $nationID===0 ? "-" : "{$general['cnt']}"; + echo $nationID === 0 ? "-" : "{$general['cnt']}"; echo " @@ -348,7 +349,7 @@ function myNationInfo(General $generalObj) {$nation['power']} 기술력 "; - echo $nationID===0 ? "-" : "{$nation['tech']}"; + echo $nationID === 0 ? "-" : "{$nation['tech']}"; echo " @@ -904,7 +905,7 @@ function nationMsg(General $general) $nationID = $general->getNationID(); $nationStor = KVStorage::getStorage($db, $nationID, 'nation_env'); - return $nationStor->notice??''; + return $nationStor->notice ?? ''; } function banner() @@ -1227,13 +1228,13 @@ function updateOnline() $onlineNum = count($onlineUser); $onlineNationUsers = Util::arrayGroupBy($onlineUser, 'nation'); - uasort($onlineNationUsers, function(array $lhs, array $rhs){ - return -(count($lhs)<=>count($rhs)); + uasort($onlineNationUsers, function (array $lhs, array $rhs) { + return - (count($lhs) <=> count($rhs)); }); $onlineNation = []; - foreach($onlineNationUsers as $nationID=>$rawOnlineUser){ + foreach ($onlineNationUsers as $nationID => $rawOnlineUser) { $nationName = getNationStaticInfo($nationID)['name']; $onlineNation[] = "【{$nationName}】"; $userList = join(', ', Util::squeezeFromArray($rawOnlineUser, 'name')); @@ -1265,7 +1266,7 @@ function addAge() $generalID = $general['no']; $special = SpecialityHelper::pickSpecialDomestic( $general, - (Json::decode($general['aux'])['prev_types_special'])??[] + (Json::decode($general['aux'])['prev_types_special']) ?? [] ); $specialClass = buildGeneralSpecialDomesticClass($special); $specialText = $specialClass->getName(); @@ -1282,16 +1283,26 @@ function addAge() foreach ($db->query('SELECT no,name,nation,leadership,strength,intel,npc,dex1,dex2,dex3,dex4,dex5,aux from general where specage2<=age and special2=%s', GameConst::$defaultSpecialWar) as $general) { $generalID = $general['no']; - $special2 = SpecialityHelper::pickSpecialWar( - $general, - (Json::decode($general['aux'])['prev_types_special2'])??[] - ); + $generalAux = Json::decode($general['aux']); + + $updateVars = []; + if(key_exists('inheritSpecificSpecialWar', $generalAux)){ + $special2 = $generalAux['inheritSpecificSpecialWar']; + unset($generalAux['inheritSpecificSpecialWar']); + $updateVars['aux'] = Json::encode($generalAux); + } + else{ + $special2 = SpecialityHelper::pickSpecialWar( + $general, + ($generalAux['prev_types_special2']) ?? [] + ); + } + $specialClass = buildGeneralSpecialWarClass($special2); $specialText = $specialClass->getName(); - $db->update('general', [ - 'special2' => $special2 - ], 'no=%i', $general['no']); + $updateVars['special2'] = $special2; + $db->update('general', $updateVars, 'no=%i', $general['no']); $logger = new ActionLogger($generalID, $general['nation'], $year, $month); @@ -1537,15 +1548,15 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool $occupiedUnique = []; $invalidItemType = []; - foreach(array_keys(GameConst::$allItems) as $itemType){ - $ownItem = $general->getItems()[$itemType]??null; - if($ownItem !== null && !$ownItem->isBuyable()){ + foreach (array_keys(GameConst::$allItems) as $itemType) { + $ownItem = $general->getItems()[$itemType] ?? null; + if ($ownItem !== null && !$ownItem->isBuyable()) { $invalidItemType[$itemType] = true; } } foreach (array_keys(GameConst::$allItems) as $itemType) { - if(key_exists($itemType, $invalidItemType)){ + if (key_exists($itemType, $invalidItemType)) { continue; } foreach ($db->queryAllLists('SELECT %b, count(*) as cnt FROM general GROUP BY %b', $itemType, $itemType) as [$itemCode, $cnt]) { @@ -1561,11 +1572,11 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool } foreach (GameConst::$allItems as $itemType => $itemCategories) { - if(key_exists($itemType, $invalidItemType)){ + if (key_exists($itemType, $invalidItemType)) { continue; } foreach ($itemCategories as $itemCode => $cnt) { - if($cnt == 0){ + if ($cnt == 0) { continue; } if (!key_exists($itemCode, $occupiedUnique)) { @@ -1607,6 +1618,192 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool return true; } +function rollbackInheritUniqueTrial(General $general, string $itemKey, string $reason) +{ + + $ownerID = $general->getVar('owner'); + + $db = DB::db(); + + $itemTrials = $general->getAuxVar('inheritUniqueTrial'); + LogText("선택유니크 롤백:{$ownerID}", [$itemKey, $itemTrials]); + unset($itemTrials[$itemKey]); + $general->setAuxVar('inheritUniqueTrial', $itemTrials); + + + $trialStor = KVStorage::getStorage($db, "ut_{$itemKey}"); + $ownTrial = $trialStor->getValue("u{$ownerID}"); + + if ($ownTrial) { + //두 값이 general, KVStorage 둘다 있고, 이중에선 KVStorage 값을 기준으로 하자 따르자 + [,, $amount] = $ownTrial; + $trialStor->deleteValue("u{$ownerID}"); + $general->increaseInheritancePoint('previous', $amount); + LogText("선택유니크 롤백포인트:{$ownerID}", $amount); + } + + $itemObj = buildItemClass($itemKey); + $itemName = $itemObj->getName(); + //메시지 + + $staticNation = $general->getStaticNation(); + + $unlimited = new \DateTime('9999-12-31'); + $src = new MessageTarget(0, '', 0, 'System', '#000000'); + $dest = new MessageTarget($general->getID(), $general->getName(), $general->getNationID(), $staticNation['name'], $staticNation['color'], GetImageURL($general->getVar('imgsvr'), $general->getVar('picture'))); + $josaUl = JosaUtil::pick($itemName, '을'); + $msg = new Message( + Message::MSGTYPE_PRIVATE, + $src, + $dest, + "{$itemName}{$josaUl} 얻지 못했습니다. {$reason}", + new DateTime(), + $unlimited, + [] + ); + + $msg->send(true); + $general->applyDB($db); +} + +function tryInheritUniqueItem(General $general, string $acquireType = '아이템'): bool +{ + $ownerID = $general->getVar('owner'); + if (!$ownerID) { + LogText("선택유니크 실패???: {$ownerID}", $general->getName()); + return false; + } + + $itemTrials = $general->getAuxVar('inheritUniqueTrial') ?? []; + arsort($itemTrials); + LogText("선택유니크항목: {$ownerID}", $itemTrials); + + $db = DB::db(); + + $ownTarget = null; + $ownType = null; + + foreach ($itemTrials as $itemKey => $amount) { + $availableItemTypes = []; + $reasons = []; + foreach (GameConst::$allItems as $itemType => $itemList) { + //아직은 그런 경우는 없지만 동일 유니크를 여러 부위에 장착할 수 있을지도 모름 + if (!key_exists($itemKey, $itemList)) { + continue; + } + + $ownItem = $general->getItem($itemType); + if ($ownItem->getRawClassName() == $itemKey) { + $reasons[] = '이미 그 유니크를 가지고 있습니다.'; + continue; + } + /* + if (!$ownItem->isBuyable()) { + $reasons[] = '이미 다른 유니크를 가지고 있습니다.'; + continue; + } + */ + + $availableCnt = $itemList[$itemKey]; + $occupiedCnt = $db->queryFirstField('SELECT count(*) FROM general WHERE %b = %s', $itemType, $itemKey); + if ($occupiedCnt >= $availableCnt) { + $reasons[] = '그 유니크는 모두 점유되었습니다.'; + continue; + } + $availableItemTypes[] = $itemType; + } + + if (!$availableItemTypes) { + rollbackInheritUniqueTrial($general, $itemKey, join(' ', $reasons)); + continue; + } + $reasons = []; + + $itemType = Util::choiceRandom($availableItemTypes); + + $trialStor = KVStorage::getStorage($db, "ut_{$itemKey}"); //혹시 itemKey의 크기가 37이 넘을 수 있을까? + $anyTrials = $trialStor->getAll(); + if (!$anyTrials) { + //순서가 꼬였던 모양, 실제 값은 storage를 우선시하자 + rollbackInheritUniqueTrial($general, $itemKey, '절차상의 오류입니다.'); + continue; + } + + //XXX: 정렬할 필요 없지 않나? + usort($anyTrials, function ($lhsTrial, $rhsTrial) { + [,, $lhsAmount] = $lhsTrial; + [,, $rhsAmount] = $rhsTrial; + return $rhsAmount <=> $lhsAmount; //큰 값이 앞에 오도록 + }); + + LogText("선택유니크상태 {$ownerID} {$itemKey}", $anyTrials); + + //공동 1등인데 본인이 있을 수도 있다. + [,, $topAmount] = $anyTrials[0]; + if ($amount < $topAmount) { + $compAmount = $topAmount / $amount; + if ($compAmount > 2.0) { + $compText = '엄청난 차이로 '; + } else if ($compAmount > 1.2) { + $compText = '큰 차이로 '; + } else if ($compAmount > 1.05) { + $compText = ''; + } else { + $compText = '아슬아슬한 차이로 '; + } + rollbackInheritUniqueTrial($general, $itemKey, "{$compText}상위 입찰한 장수가 있습니다."); + continue; + } + + //내가 1위다 + if ($ownTarget !== null) { + //이미 다른 아이템을 얻기로 되어있다. + continue; + } + $ownTarget = $itemKey; + $ownType = $itemType; + } + unset($itemKey); + unset($itemType); + + if ($ownTarget === null) { + return false; + } + + LogText("선택유니크획득{$ownerID}", $ownTarget); + + $trialStor = KVStorage::getStorage($db, "ut_{$ownTarget}"); + $trialStor->deleteValue("u{$ownerID}"); + + //rollbackInheritUniqueTrial 과정 때문에 새로 받아와야함 + $itemTrials = $general->getAuxVar('inheritUniqueTrial'); + unset($itemTrials[$ownTarget]); + $general->setAuxVar('inheritUniqueTrial', $itemTrials); + + $nationName = $general->getStaticNation()['name']; + $generalName = $general->getName(); + $josaYi = JosaUtil::pick($generalName, '이'); + $itemObj = buildItemClass($ownTarget); + $itemName = $itemObj->getName(); + $itemRawName = $itemObj->getRawName(); + $josaUl = JosaUtil::pick($itemRawName, '을'); + + + $general->setVar($ownType, $ownTarget); + + + $logger = $general->getLogger(); + + $logger->pushGeneralActionLog("{$itemName}{$josaUl} 습득했습니다!"); + $logger->pushGeneralHistoryLog("{$itemName}{$josaUl} 습득"); + $logger->pushGlobalActionLog("{$generalName}{$josaYi} {$itemName}{$josaUl} 습득했습니다!"); + $logger->pushGlobalHistoryLog("【{$acquireType}】{$nationName}{$generalName}{$josaYi} {$itemName}{$josaUl} 습득했습니다!"); + + $general->applyDB($db); + + return true; +} + function tryUniqueItemLottery(General $general, string $acquireType = '아이템'): bool { $db = DB::db(); @@ -1616,8 +1813,13 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템 return false; } - if ($general->getNPCType() > 6) { - return false; + $inheritUnique = $general->getAuxVar('inheritUniqueTrial'); + if ($inheritUnique && count($inheritUnique)) { + LogText("유니크 준비?? {$general->getID()}", $inheritUnique); + $trialResult = tryInheritUniqueItem($general, $acquireType); + if ($trialResult) { + return true; + } } $itemTypeCnt = count(GameConst::$allItems); @@ -1629,7 +1831,7 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템 } } - if($trialCnt <= 0){ + if ($trialCnt <= 0) { LogText("{$general->getName()}, {$general->getID()} 모든 아이템", $trialCnt); return false; } @@ -1653,18 +1855,27 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템 $prob = 1 / ($genCount * $itemTypeCnt / 10 / 4); // 건국시 4개(20%) 등장(200명시 20국 정도 됨) } - $prob = Util::valueFit($prob, null, 1 / 4);//최대치 감소 + $prob = Util::valueFit($prob, null, 1 / 4); //최대치 감소 $result = false; + $prob /= sqrt(2); + $moreProb = pow(2, 1/4); + if($general->getAuxVar('inheritRandomUnique')){ + //포인트로 랜덤 유니크 획득 + $prob = 1; + LogText("{$general->getName()}, {$general->getID()} 유산 포인트 유니크", $prob); + $general->setAuxVar('inheritRandomUnique', null); + } - foreach(Util::range($trialCnt) as $_idx){ + foreach (Util::range($trialCnt) as $_idx) { if (Util::randBool($prob)) { $result = true; break; } + $prob *= $moreProb; } - if(!$result){ + if (!$result) { LogText("{$general->getName()}, {$general->getID()} 유니크 실패 {$trialCnt}", $prob); return false; } @@ -1681,7 +1892,7 @@ function getAdmin() } /** @return General[] */ -function deleteNation(General $lord, bool $applyDB):array +function deleteNation(General $lord, bool $applyDB): array { $lordID = $lord->getID(); $nationID = $lord->getNationID(); @@ -1706,7 +1917,8 @@ function deleteNation(General $lord, bool $applyDB):array $nationID, $lordID ), - ['npc', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'belong', 'aux'], 1 + ['npc', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'belong', 'aux'], + 1 ); $nationGeneralList[$lordID] = $lord; @@ -1722,11 +1934,12 @@ function deleteNation(General $lord, bool $applyDB):array $destroyHistoryLog = "{$nationName}{$josaYi} 멸망"; // 전 장수 재야로 - foreach($nationGeneralList as $general){ - $general->setAuxVar('max_belong', + foreach ($nationGeneralList as $general) { + $general->setAuxVar( + 'max_belong', max( $general->getVar('belong'), - $general->getAuxVar('max_belong')??0 + $general->getAuxVar('max_belong') ?? 0 ) ); $general->setVar('belong', 0); @@ -1739,7 +1952,7 @@ function deleteNation(General $lord, bool $applyDB):array $logger->pushGeneralActionLog($destroyLog, ActionLogger::PLAIN); $logger->pushGeneralHistoryLog($destroyHistoryLog); - if($applyDB){ + if ($applyDB) { $general->applyDB($db); } } @@ -2158,7 +2371,7 @@ function getRandTurn($term, ?\DateTimeInterface $baseDateTime = null) $randSecond = Util::randRangeInt(0, 60 * $term - 1); $randFraction = Util::randRangeInt(0, 999999) / 1000000; //6자리 소수 - return $baseDateTime->add(TimeUtil::secondsToDateInterval($randSecond + $randFraction))->format('Y-m-d H:i:s.u'); + return TimeUtil::format($baseDateTime->add(TimeUtil::secondsToDateInterval($randSecond + $randFraction)), true); } function getRandTurn2($term, ?\DateTimeInterface $baseDateTime = null) diff --git a/hwe/func_converter.php b/hwe/func_converter.php index 9508b13a..4d0f3716 100644 --- a/hwe/func_converter.php +++ b/hwe/func_converter.php @@ -369,7 +369,7 @@ function getAPIExecutorClass($path){ throw new \InvalidArgumentException("{$path}는 올바른 API 지시자가 아님"); } - $classPath = ($basePath.$path); + $classPath = str_replace('/', '\\', $basePath.$path); if(class_exists($classPath)){ return $classPath; @@ -377,9 +377,9 @@ function getAPIExecutorClass($path){ throw new \InvalidArgumentException("{$path}는 올바른 API 경로가 아님"); } -function buildAPIExecutorClass(string $type, array $args):\sammo\BaseAPI{ +function buildAPIExecutorClass($type, string $rootPath, array $args):\sammo\BaseAPI{ $class = getAPIExecutorClass($type); - return new $class($args); + return new $class($rootPath, $args); } function getWarUnitTriggerClass(string $type){ diff --git a/hwe/func_gamerule.php b/hwe/func_gamerule.php index a6faafe4..a4d9b355 100644 --- a/hwe/func_gamerule.php +++ b/hwe/func_gamerule.php @@ -623,7 +623,7 @@ function updateNationState() $nation['nation'], $targetKillTurn ); - $nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc'], 2); + $nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc', 'aux'], 2); $chiefObj = null; $uniqueLotteryWeightList = []; @@ -1158,13 +1158,13 @@ function resetInheritanceUser(int $userID, bool $isRebirth=false):float{ $inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}"); $totalPoint = 0; $allPoints = $inheritStor->getAll(); - if(count($allPoints) == 0){ + if(!$allPoints || count($allPoints) == 0){ //비었으므로 리셋 안함 return 0; } if(count($allPoints) == 1 && key_exists('previous', $allPoints)){ //이미 리셋되었으므로 리셋 안함 - return $allPoints['previous']; + return $allPoints['previous'][0]; } foreach($allPoints as $key=>[$value,]){ if($isRebirth && key_exists($key, $rebirthDegraded)){ diff --git a/hwe/join.php b/hwe/join.php deleted file mode 100644 index 5d08dabd..00000000 --- a/hwe/join.php +++ /dev/null @@ -1,182 +0,0 @@ -setReadOnly(); -$userID = Session::getUserID(); - -if (!$userID) { - MessageBox("잘못된 접근입니다!!!"); - echo ""; - exit(1); -} - -//회원 테이블에서 정보확인 -$member = RootDB::db()->queryFirstRow("select no,name,picture,imgsvr,grade from member where no= %i", $userID); - -if (!$member) { - MessageBox("잘못된 접근입니다!!!"); - echo ""; - exit(1); -} - -$db = DB::db(); -$gameStor = KVStorage::getStorage($db, 'game_env'); -$admin = $gameStor->getValues(['block_general_create','show_img_level','maxgeneral']); -if($admin['block_general_create']){ - MessageBox("잘못된 접근입니다!!!"); - echo ""; - exit(1); -} -?> - - - -<?=UniqueConst::$serverName?>: 장수생성 - - - - - - - - - - - - - - - - -
장 수 생 성
- - -
-queryFirstField('SELECT count(no) FROM general WHERE npc<2'); - -if ($gencount >= $admin['maxgeneral']) { - echo ""; - echo ""; - exit(); -} - -$nationList = $db->query('SELECT nation,`name`,color,scout FROM nation'); -shuffle($nationList); -$nationList = Util::convertArrayToDict($nationList, 'nation'); -//NOTE: join 안할것임 -$scoutMsgs = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'scout_msg'); -foreach($scoutMsgs as $nationID=>$scoutMsg){ - $nationList[$nationID]['scoutmsg'] = $scoutMsg; -} - -echo getInvitationList($nationList); -?> - -
- - - - - - - - -= 1 && $member['grade'] >= 1 && $member['picture'] != "") { - $imageTemp = GetImageURL($member['imgsvr']); - echo " - - - - - - "; -} -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
장수 생성
장수명 - (전각 9글자, 반각 18글자 이내) -
전콘 사용 여부 - - - 사용 -
- 계정관리에서 자신만을 표현할 수 있는 아이콘을 업로드 해보세요! -
성격 - -
통솔
무력
지력
능력치 조정 - - - - -
- 모든 능력치는 ( <= 능력치 <= ) 사이로 잡으셔야 합니다.
- 그 외의 능력치는 가입되지 않습니다.
-
- 능력치의 총합은 입니다. 가입후 0~10의 능력치 보너스를 받게 됩니다.
- 임의의 도시에서 재야로 시작하며 건국과 임관은 게임 내에서 실행합니다. -
-
- - - -
- - diff --git a/hwe/join_post.php b/hwe/join_post.php deleted file mode 100644 index e9fb0d22..00000000 --- a/hwe/join_post.php +++ /dev/null @@ -1,410 +0,0 @@ -"; - exit(1); -} - -$v = new Validator($_POST); -$v - ->rule('required', [ - 'name', - 'leadership', - 'strength', - 'intel' - ]) - ->rule('integer', [ - 'leadership', - 'strength', - 'intel', - ]) - ->rule('stringWidthBetween', 'name', 1, 18) - ->rule('min', [ - 'leadership', - 'strength', - 'intel' - ], GameConst::$defaultStatMin) - ->rule('max', [ - 'leadership', - 'strength', - 'intel' - ], GameConst::$defaultStatMax) - ->rule('in', 'character', array_merge(GameConst::$availablePersonality, ['Random'])) - ->rule('in', 'inheritSpecial', GameConst::$availableSpecialWar) - ->rule('integer', 'inheritTurntime') - ->rule('min', 'inheritTurntime', 0) - ->rule('in', 'inheritCity', array_keys(CityConst::all())) - ->rule('integerArray', 'inheritBonusStat'); - -if (!$v->validate()) { - dieMsg($v->errorStr()); -} - -$session = Session::requireLogin()->setReadOnly(); -$userID = Session::getUserID(); -//NOTE: 이 페이지에서는 세션에 데이터를 등록하지 않음. 로그인은 이후에. - -$name = Util::getPost('name'); -$name = htmlspecialchars($name); -$name = StringUtil::removeSpecialCharacter($name); -$name = WebUtil::htmlPurify($name); -$name = StringUtil::textStrip($name); -$pic = (int)Util::getPost('pic', 'bool', 0); -$character = Util::getPost('character'); - -$leadership = Util::getPost('leadership', 'int', 50); -$strength = Util::getPost('strength', 'int', 50); -$intel = Util::getPost('intel', 'int', 50); - -$inheritSpecial = Util::getPost('inheritSpecial'); -$inheritTurntime = Util::getPost('inheritTurntime', 'int'); -$inheritCity = Util::getPost('inheritCity', 'int'); -$inheritBonusStat = Util::getPost('inheritBonusStat', 'array_int'); - -$join = Util::getPost('join'); //쓸모 없음 - -$rootDB = RootDB::db(); -//회원 테이블에서 정보확인 -$member = $rootDB->queryFirstRow('SELECT `no`, id, picture, grade, `name`, imgsvr FROM member WHERE no=%i', $userID); - -if (!$member) { - dieMsg("잘못된 접근입니다!!!"); -} - -$db = DB::db(); -$gameStor = KVStorage::getStorage($db, 'game_env'); -$gameStor->cacheValues(['year', 'month', 'maxgeneral', 'scenario', 'show_img_level', 'turnterm', 'turntime', 'genius', 'npcmode']); -########## 동일 정보 존재여부 확인. ########## - -$gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2'); -$oldGeneral = $db->queryFirstField('SELECT `no` FROM general WHERE `owner`=%i', $userID); -$oldName = $db->queryFirstField('SELECT `no` FROM general WHERE `name`=%s', $name); - -if ($oldGeneral) { - dieMsg("이미 등록하셨습니다!"); -} -if ($oldName) { - dieMsg("이미 있는 장수입니다. 다른 이름으로 등록해 주세요!"); -} -if ($gameStor->maxgeneral <= $gencount) { - dieMsg("더이상 등록할 수 없습니다!"); -} -if ($name == '') { - dieMsg("이름이 짧습니다. 다시 가입해주세요!"); -} -if (mb_strwidth($name) > 18) { - dieMsg("이름이 유효하지 않습니다. 다시 가입해주세요!"); -} -if ($leadership + $strength + $intel > GameConst::$defaultStatTotal) { - dieMsg("능력치가 " . GameConst::$defaultStatTotal . "을 넘어섰습니다. 다시 가입해주세요!"); -} - -if ($inheritBonusStat) { - if (count($inheritBonusStat) != 3) { - dieMsg("보너스 능력치가 잘못 지정되었습니다. 다시 가입해주세요!"); - } - $sum = array_sum($inheritBonusStat); - if ($sum < 3 || $sum > 5) { - dieMsg("보너스 능력치 합이 잘못 지정되었습니다. 다시 가입해주세요!"); - } - foreach ($inheritBonusStat as $stat) { - if ($stat < 0) { - dieMsg("보너스 능력치가 음수입니다. 다시 가입해주세요!"); - } - } -} - -$admin = $gameStor->getValues(['scenario', 'turnterm', 'turntime', 'show_img_level', 'startyear', 'year']); - -$inheritTotalPoint = resetInheritanceUser($userID); -$inheritRequiredPoint = 0; - -if ($inheritCity !== null) { - $inheritRequiredPoint += GameConst::$inheritBornCityPoint; -} -if ($inheritBonusStat !== null) { - $inheritRequiredPoint += GameConst::$inheritBornMaxBonusStat; -} -if ($inheritSpecial !== null) { - $inheritRequiredPoint += GameConst::$inheritBornSpecialPoint; -} -if ($inheritTurntime !== null) { - $inheritRequiredPoint += GameConst::$inheritBornTurntimePoint; -} - -if ($inheritTotalPoint < $inheritRequiredPoint) { - dieMsg("유산 포인트가 부족합니다. 다시 가입해주세요!"); -} - -if ($inheritSpecial !== null && $gameStor->genius == 0) { - dieMsg("이미 천재가 모두 나타났습니다. 다시 가입해주세요!"); -} - -if ($inheritCity !== null && !key_exists($inheritCity, CityConst::all())) { - dieMsg("도시가 잘못 지정되었습니다. 다시 가입해주세요!"); -} - -if ($inheritSpecial) { - $genius = true; -} else { - // 현재 1% - $genius = Util::randBool(0.01); -} - -if ($genius && $gameStor->genius > 0) { - $gameStor->genius = $gameStor->genius - 1; -} else { - $genius = false; -} - -if ($inheritCity !== null) { - $city = $inheritCity; -} else { - // 공백지에서만 태어나게 - $city = $db->queryFirstField("select city from city where level>=5 and level<=6 and nation=0 order by rand() limit 0,1"); - if (!$city) { - $city = $db->queryFirstField("select city from city where level>=5 and level<=6 order by rand() limit 0,1"); - } -} - -if ($inheritBonusStat) { - [$pleadership, $pstrength, $pintel] = $inheritBonusStat; -} else { - $pleadership = 0; - $pstrength = 0; - $pintel = 0; - foreach (Util::range(Util::randRangeInt(3, 5)) as $statIdx) { - switch (Util::choiceRandomUsingWeight([$leadership, $strength, $intel])) { - case 0: - $pleadership++; - break; - case 1: - $pstrength++; - break; - case 2: - $pintel++; - break; - } - } -} - -$leadership = $leadership + $pleadership; -$strength = $strength + $pstrength; -$intel = $intel + $pintel; - -$relYear = Util::valueFit($admin['year'] - $admin['startyear'], 0); - -$age = 20 + ($pleadership + $pstrength + $pintel) * 2 - (mt_rand(0, 1)); -// 아직 남았고 천재등록상태이면 특기 부여 -if ($genius) { - $specage2 = $age; - if ($inheritSpecial) { - $special2 = $inheritSpecial; - } else { - $special2 = SpecialityHelper::pickSpecialWar([ - 'leadership' => $leadership, - 'strength' => $strength, - 'intel' => $intel, - 'dex1' => 0, - 'dex2' => 0, - 'dex3' => 0, - 'dex4' => 0, - 'dex5' => 0 - ]); - } -} else { - $specage2 = Util::valueFit(Util::round((GameConst::$retirementYear - $age) / 6 - $relYear / 2), 3) + $age; - $special2 = GameConst::$defaultSpecialWar; -} -//내특 -$specage = Util::valueFit(Util::round((GameConst::$retirementYear - $age) / 12 - $relYear / 2), 3) + $age; -$special = GameConst::$defaultSpecialDomestic; - -if ($admin['scenario'] >= 1000) { - $specage2 = $age + 3; - $specage = $age + 3; -} - -if ($relYear < 3) { - $experience = 0; -} else { - $expGenCount = $db->queryFirstField('SELECT count(*) FROM general WHERE nation != 0 AND npc < 4'); - $targetGenOrder = Util::round($expGenCount * 0.2); - $experience = $db->queryFirstField( - 'SELECT experience FROM general WHERE nation != 0 AND npc < 4 ORDER BY experience ASC LIMIT %i, 1', - $targetGenOrder - 1 - ); - $experience *= 0.8; -} - -if ($inheritTurntime === null) { - $inheritTurntime = $inheritTurntime % ($gameStor->turnterm * 60); - $inheritTurntime += Util::randRangeInt(0, 999999) / 1000000; - $turntime = cutTurn($admin['turntime'], $admin['turnterm']); - $turntime = TimeUtil::nowAddSeconds($inheritTurntime, true); -} else { - $turntime = getRandTurn($admin['turnterm'], new \DateTimeImmutable($admin['turntime'])); -} - - -$now = TimeUtil::now(true); -if ($now >= $turntime) { - $turntime = addTurn($turntime, $admin['turnterm']); -} - -//특회 전콘 -if ($admin['show_img_level'] >= 1 && $member['grade'] >= 1 && $member['picture'] != "" && $pic) { - $face = $member['picture']; - $imgsvr = $member['imgsvr']; -} else { - $face = "default.jpg"; - $imgsvr = 0; -} - -//성격 랜덤시 -if (!in_array($character, GameConst::$availablePersonality)) { - $character = Util::choiceRandom(GameConst::$availablePersonality); -} -//상성 랜덤 -$affinity = rand() % 150 + 1; - -########## 회원정보 테이블에 입력값을 등록한다. ########## -$db->insert('general', [ - 'owner' => $userID, - 'name' => $name, - 'owner_name' => $member['name'], - 'picture' => $face, - 'imgsvr' => $imgsvr, - 'nation' => 0, - 'city' => $city, - 'troop' => 0, - 'affinity' => $affinity, - 'leadership' => $leadership, - 'strength' => $strength, - 'intel' => $intel, - 'experience' => $experience, - 'dedication' => 0, - 'gold' => GameConst::$defaultGold, - 'rice' => GameConst::$defaultRice, - 'crew' => 0, - 'train' => 0, - 'atmos' => 0, - 'officer_level' => 0, - 'turntime' => $turntime, - 'killturn' => 6, - 'lastconnect' => $now, - 'lastrefresh' => $now, - 'crewtype' => GameUnitConst::DEFAULT_CREWTYPE, - 'makelimit' => 0, - 'age' => $age, - 'startage' => $age, - 'personal' => $character, - 'specage' => $specage, - 'special' => $special, - 'specage2' => $specage2, - 'special2' => $special2 -]); -$generalID = $db->insertId(); -$turnRows = []; -foreach (Util::range(GameConst::$maxTurn) as $turnIdx) { - $turnRows[] = [ - 'general_id' => $generalID, - 'turn_idx' => $turnIdx, - 'action' => '휴식', - 'arg' => null, - 'brief' => '휴식' - ]; -} -$db->insert('general_turn', $turnRows); - -$rank_data = []; -foreach (array_keys(General::RANK_COLUMN) as $rankColumn) { - $rank_data[] = [ - 'general_id' => $generalID, - 'nation_id' => 0, - 'type' => $rankColumn, - 'value' => 0 - ]; -} -$db->insert('rank_data', $rank_data); -$db->insert('betting', [ - 'general_id' => $generalID, -]); -$cityname = CityConst::byID($city)->name; - -$me = [ - 'no' => $generalID -]; - -$log = []; -$mylog = []; - -$logger = new ActionLogger($generalID, 0, $gameStor->year, $gameStor->month); - -$josaRa = JosaUtil::pick($name, '라'); -$speicalText = getGeneralSpecialWarName($special2); -if ($genius) { - - $logger->pushGlobalActionLog("{$cityname}에서 {$name}{$josaRa}는 기재가 천하에 이름을 알립니다."); - $logger->pushGlobalActionLog("{$speicalText} 특기를 가진 천재의 등장으로 온 천하가 떠들썩합니다."); - $logger->pushGlobalHistoryLog("【천재】{$cityname}에 천재가 등장했습니다."); -} else { - $logger->pushGlobalActionLog("{$cityname}에서 {$name}{$josaRa}는 호걸이 천하에 이름을 알립니다."); -} - -$logger->pushGeneralHistoryLog("{$name}, {$cityname}에서 큰 뜻을 품다."); -$logger->pushGeneralActionLog("삼국지 모의전투 PHP의 세계에 오신 것을 환영합니다 ^o^", ActionLogger::PLAIN); -$logger->pushGeneralActionLog("처음 하시는 경우에는 도움말을 참고하시고,", ActionLogger::PLAIN); -$logger->pushGeneralActionLog("문의사항이 있으시면 게시판에 글을 남겨주시면 되겠네요~", ActionLogger::PLAIN); -$logger->pushGeneralActionLog("부디 즐거운 삼모전 되시길 바랍니다 ^^", ActionLogger::PLAIN); -$logger->pushGeneralActionLog("통솔 $pleadership 무력 $pstrength 지력 $pintel 의 보너스를 받으셨습니다.", ActionLogger::PLAIN); -$logger->pushGeneralActionLog("연령은 $age세로 시작합니다.", ActionLogger::PLAIN); - -if ($genius) { - $logger->pushGeneralActionLog("축하합니다! 천재로 태어나 처음부터 {$speicalText} 특기를 가지게 됩니다!", ActionLogger::PLAIN); - $logger->pushGeneralHistoryLog("{$speicalText} 특기를 가진 천재로 탄생."); -} - -$logger->flush(); - -pushAdminLog(["가입 : {$userID} // {$name} // {$generalID}" . getenv("REMOTE_ADDR")]); - -$rootDB->insert('member_log', [ - 'member_no' => $userID, - 'date' => TimeUtil::now(), - 'action_type' => 'make_general', - 'action' => Json::encode([ - 'server' => DB::prefix(), - 'type' => 'general', - 'generalID' => $generalID, - 'generalName' => $name - ]) -]); - -?> - - - - - - - - - - - \ No newline at end of file diff --git a/hwe/sammo/API/General/Join.php b/hwe/sammo/API/General/Join.php index 63d1ab8f..a467c605 100644 --- a/hwe/sammo/API/General/Join.php +++ b/hwe/sammo/API/General/Join.php @@ -78,12 +78,8 @@ class Join extends \sammo\BaseAPI return static::REQ_LOGIN | static::REQ_READ_ONLY; } - public function launch(?Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag) + public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag) { - if($session === null){ - throw "invalid session"; - } - $userID = $session->userID; $name = $this->args['name']; @@ -98,10 +94,10 @@ class Join extends \sammo\BaseAPI $strength = $this->args['strength']; $intel = $this->args['intel']; - $inheritSpecial = $this->args['inheritSpecial']??null; - $inheritTurntime =$this->args['inheritTurntime']??null; - $inheritCity = $this->args['inheritCity']??null; - $inheritBonusStat = $this->args['inheritBonusStat']??null; + $inheritSpecial = $this->args['inheritSpecial'] ?? null; + $inheritTurntime = $this->args['inheritTurntime'] ?? null; + $inheritCity = $this->args['inheritCity'] ?? null; + $inheritBonusStat = $this->args['inheritBonusStat'] ?? null; $rootDB = RootDB::db(); //회원 테이블에서 정보확인 @@ -143,15 +139,17 @@ class Join extends \sammo\BaseAPI if (count($inheritBonusStat) != 3) { return "보너스 능력치가 잘못 지정되었습니다. 다시 가입해주세요!"; } - $sum = array_sum($inheritBonusStat); - if ($sum < 3 || $sum > 5) { - return "보너스 능력치 합이 잘못 지정되었습니다. 다시 가입해주세요!"; - } foreach ($inheritBonusStat as $stat) { if ($stat < 0) { return "보너스 능력치가 음수입니다. 다시 가입해주세요!"; } } + $sum = array_sum($inheritBonusStat); + if ($sum == 0) { + $inheritBonusStat = null; + } else if ($sum < 3 || $sum > 5) { + return "보너스 능력치 합이 잘못 지정되었습니다. 다시 가입해주세요!"; + } } $admin = $gameStor->getValues(['scenario', 'turnterm', 'turntime', 'show_img_level', 'startyear', 'year']); @@ -163,7 +161,7 @@ class Join extends \sammo\BaseAPI $inheritRequiredPoint += GameConst::$inheritBornCityPoint; } if ($inheritBonusStat !== null) { - $inheritRequiredPoint += GameConst::$inheritBornMaxBonusStat; + $inheritRequiredPoint += GameConst::$inheritBornStatPoint; } if ($inheritSpecial !== null) { $inheritRequiredPoint += GameConst::$inheritBornSpecialPoint; @@ -277,11 +275,13 @@ class Join extends \sammo\BaseAPI $experience *= 0.8; } - if ($inheritTurntime === null) { - $inheritTurntime = $inheritTurntime % ($gameStor->turnterm * 60); + if ($inheritTurntime !== null) { + //FIXME: 오동작함 + $inheritTurntime = $inheritTurntime % ($admin['turnterm'] * 60); $inheritTurntime += Util::randRangeInt(0, 999999) / 1000000; - $turntime = cutTurn($admin['turntime'], $admin['turnterm']); - $turntime = TimeUtil::nowAddSeconds($inheritTurntime, true); + $turntime = new \DateTimeImmutable(cutTurn($admin['turntime'], $admin['turnterm'])); + $turntime = $turntime->add(TimeUtil::secondsToDateInterval($inheritTurntime)); + $turntime = TimeUtil::format($turntime, true); } else { $turntime = getRandTurn($admin['turnterm'], new \DateTimeImmutable($admin['turntime'])); } @@ -372,6 +372,11 @@ class Join extends \sammo\BaseAPI ]); $cityname = CityConst::byID($city)->name; + if ($inheritRequiredPoint > 0) { + $inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}"); + $inheritStor->setValue('previous', [$inheritTotalPoint - $inheritRequiredPoint, null]); + } + $me = [ 'no' => $generalID ]; diff --git a/hwe/sammo/API/InheritAction/BuyHiddenBuff.php b/hwe/sammo/API/InheritAction/BuyHiddenBuff.php new file mode 100644 index 00000000..964a9010 --- /dev/null +++ b/hwe/sammo/API/InheritAction/BuyHiddenBuff.php @@ -0,0 +1,79 @@ +args); + $v->rule('required', [ + 'type', + 'level', + ]) + ->rule('integer', 'level') + ->rule('min', 'level', 1) + ->rule('max', 'level', TriggerInheritBuff::MAX_STEP) + ->rule('keyExists', 'type', TriggerInheritBuff::BUFF_KEY_TEXT); + + if (!$v->validate()) { + return $v->errorStr(); + } + return null; + } + + public function getRequiredSessionMode(): int + { + //General.aux 쓰므로 lock; + return static::REQ_GAME_LOGIN; + } + + public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag) + { + $userID = $session->userID; + $generalID = $session->generalID; + + $type = $this->args['type']; + $level = $this->args['level']; + + $general = General::createGeneralObjFromDB($generalID); + if ($userID != $general->getVar('owner')) { + return '로그인 상태가 이상합니다. 다시 로그인해 주세요.'; + } + + $inheritBuffList = $general->getAuxVar('inheritBuff') ?? []; + $prevLevel = $inheritBuffList[$type] ?? 0; + + if ($prevLevel == $level) { + return '이미 구입했습니다.'; + } + if ($prevLevel > $level) { + return '이미 더 높은 등급을 구입했습니다.'; + } + + $reqAmount = GameConst::$inheritBuffPoints[$level] - GameConst::$inheritBuffPoints[$prevLevel]; + + $db = DB::db(); + $inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}"); + $previousPoint = ($inheritStor->getValue('previous') ?? [0,0])[0]; + if ($previousPoint < $reqAmount) { + return '충분한 유산 포인트를 가지고 있지 않습니다.'; + } + + $inheritBuffList[$type] = $level; + $general->setAuxVar('inheritBuff', $inheritBuffList); + $inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]); + $general->applyDB($db); + return null; + } +} diff --git a/hwe/sammo/API/InheritAction/BuyRandomUnique.php b/hwe/sammo/API/InheritAction/BuyRandomUnique.php new file mode 100644 index 00000000..a0e56e97 --- /dev/null +++ b/hwe/sammo/API/InheritAction/BuyRandomUnique.php @@ -0,0 +1,52 @@ +userID; + $generalID = $session->generalID; + + $general = General::createGeneralObjFromDB($generalID); + if($userID != $general->getVar('owner')){ + return '로그인 상태가 이상합니다. 다시 로그인해 주세요.'; + } + + if($general->getAuxVar('inheritRandomUnique') !== null){ + return '이미 구입 명령을 내렸습니다. 다음 턴까지 기다려주세요.'; + } + + $db = DB::db(); + $inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}"); + $previousPoint = ($inheritStor->getValue('previous')??[0, 0])[0]; + if($previousPoint < GameConst::$inheritItemRandomPoint){ + return '충분한 유산 포인트를 가지고 있지 않습니다.'; + } + + $general->setAuxVar('inheritRandomUnique', TimeUtil::now()); + $inheritStor->setValue('previous', [$previousPoint - GameConst::$inheritItemRandomPoint, null]); + $general->applyDB($db); + return null; + } +} diff --git a/hwe/sammo/API/InheritAction/BuySpecificUnique.php b/hwe/sammo/API/InheritAction/BuySpecificUnique.php new file mode 100644 index 00000000..f833b010 --- /dev/null +++ b/hwe/sammo/API/InheritAction/BuySpecificUnique.php @@ -0,0 +1,80 @@ + $amount) { + if ($amount == 0) { + continue; + } + $availableItems[$itemKey] = $amount; + } + } + + $v = new Validator($this->args); + $v->rule('required', [ + 'item', + 'amount', + ]) + ->rule('integer', 'amount') + ->rule('min', 'amount', GameConst::$inheritItemUniqueMinPoint) + ->rule('keyExists', 'item', $availableItems); + + if (!$v->validate()) { + return $v->errorStr(); + } + return null; + } + + public function getRequiredSessionMode(): int + { + //KVStrorage, General.aux 모두 쓰므로 lock; + return static::REQ_GAME_LOGIN; + } + + public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag) + { + $itemKey = $this->args['item']; + $amount = $this->args['amount']; + + $userID = $session->userID; + $generalID = $session->generalID; + + $general = General::createGeneralObjFromDB($generalID); + if ($userID != $general->getVar('owner')) { + return '로그인 상태가 이상합니다. 다시 로그인해 주세요.'; + } + + $itemTrials = $general->getAuxVar('inheritUniqueTrial') ?? []; + if (key_exists($itemKey, $itemTrials)) { + return '이미 입찰한 아이템입니다. 다음 턴에 시도해 주세요.'; + } + + $db = DB::db(); + $inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}"); + $trialStor = KVStorage::getStorage($db, "ut_{$itemKey}"); + $previousPoint = ($inheritStor->getValue('previous') ?? [0, 0])[0]; + if ($previousPoint < $amount) { + return '충분한 유산 포인트를 가지고 있지 않습니다.'; + } + + $itemTrials[$itemKey] = $amount; + $general->setAuxVar('inheritUniqueTrial', $itemTrials); + $inheritStor->setValue('previous', [$previousPoint - $amount, null]); + $trialStor->setValue("u{$userID}", [$userID, $generalID, $amount]); + $general->applyDB($db); + return null; + } +} diff --git a/hwe/sammo/API/InheritAction/ResetSpecialWar.php b/hwe/sammo/API/InheritAction/ResetSpecialWar.php new file mode 100644 index 00000000..4d833694 --- /dev/null +++ b/hwe/sammo/API/InheritAction/ResetSpecialWar.php @@ -0,0 +1,69 @@ +userID; + $generalID = $session->generalID; + + $general = General::createGeneralObjFromDB($generalID); + if ($userID != $general->getVar('owner')) { + return '로그인 상태가 이상합니다. 다시 로그인해 주세요.'; + } + + + $currentSpecialWar = $general->getVar('special2'); + if ($currentSpecialWar === null || $currentSpecialWar == 'None') { + return '이미 전투 특기가 공란입니다.'; + } + + $currentLevel = $general->getAuxVar('inheritResetSpecialWar') ?? -1; + $nextLevel = $currentLevel + 1; + while (count(GameConst::$inheritResetAttrPointBase) <= $nextLevel) { + $baseLen = count(GameConst::$inheritResetAttrPointBase); + GameConst::$inheritResetAttrPointBase[] = GameConst::$inheritResetAttrPointBase[$baseLen - 1] + GameConst::$inheritResetAttrPointBase[$baseLen - 2]; + } + + $reqPoint = GameConst::$inheritResetAttrPointBase[$nextLevel]; + + $db = DB::db(); + $inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}"); + $previousPoint = ($inheritStor->getValue('previous') ?? [0, 0])[0]; + if ($previousPoint < $reqPoint) { + return '충분한 유산 포인트를 가지고 있지 않습니다.'; + } + + $oldTypeKey = 'prev_types_special2'; + $oldSpecialList = $general->getAuxVar($oldTypeKey) ?? []; + $oldSpecialList[] = $currentSpecialWar; + $general->setAuxVar($oldTypeKey, $oldSpecialList); + + $general->setAuxVar('inheritResetSpecialWar', $nextLevel); + $general->setVar('special2', 'None'); + $inheritStor->setValue('previous', [$previousPoint - $reqPoint, null]); + $general->applyDB($db); + return null; + } +} diff --git a/hwe/sammo/API/InheritAction/ResetTurnTime.php b/hwe/sammo/API/InheritAction/ResetTurnTime.php new file mode 100644 index 00000000..8cb2f692 --- /dev/null +++ b/hwe/sammo/API/InheritAction/ResetTurnTime.php @@ -0,0 +1,73 @@ +userID; + $generalID = $session->generalID; + + $general = General::createGeneralObjFromDB($generalID); + if ($userID != $general->getVar('owner')) { + return '로그인 상태가 이상합니다. 다시 로그인해 주세요.'; + } + + $currentLevel = $general->getAuxVar('inheritResetTurnTime') ?? -1; + $nextLevel = $currentLevel + 1; + while (count(GameConst::$inheritResetAttrPointBase) <= $nextLevel) { + $baseLen = count(GameConst::$inheritResetAttrPointBase); + GameConst::$inheritResetAttrPointBase[] = GameConst::$inheritResetAttrPointBase[$baseLen - 1] + GameConst::$inheritResetAttrPointBase[$baseLen - 2]; + } + + $reqPoint = GameConst::$inheritResetAttrPointBase[$nextLevel]; + + $db = DB::db(); + $inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}"); + $previousPoint = ($inheritStor->getValue('previous') ?? [0, 0])[0]; + if ($previousPoint < $reqPoint) { + return '충분한 유산 포인트를 가지고 있지 않습니다.'; + } + + $gameStor = new KVStorage($db, 'game_env'); + [$turnTerm, $serverTurnTime] = $gameStor->getValuesAsArray(['turnterm', 'turntime']); + + $currTurnTime = new DateTimeImmutable($general->getTurnTime()); + $serverTurnTimeObj = new DateTimeImmutable($serverTurnTime); + + $afterTurn = Util::randRange($turnTerm * -60 / 2, $turnTerm * 60 / 2); + + $turnTime = $currTurnTime->add(TimeUtil::secondsToDateInterval($afterTurn)); + if ($turnTime <= $serverTurnTimeObj && $serverTurnTimeObj <= $currTurnTime) { + $turnTime = $turnTime->add(TimeUtil::secondsToDateInterval($turnTerm * 60)); + } + + $general->setVar('turntime', TimeUtil::format($turnTime, true)); + $general->setAuxVar('inheritResetTurnTime', $nextLevel); + $inheritStor->setValue('previous', [$previousPoint - $reqPoint, null]); + $general->applyDB($db); + return null; + } +} diff --git a/hwe/sammo/API/InheritAction/SetNextSpecialWar.php b/hwe/sammo/API/InheritAction/SetNextSpecialWar.php new file mode 100644 index 00000000..f21f36c5 --- /dev/null +++ b/hwe/sammo/API/InheritAction/SetNextSpecialWar.php @@ -0,0 +1,75 @@ +args); + $v->rule('required', [ + 'type', + ]) + ->rule('in', 'type', GameConst::$availableSpecialWar); + + if (!$v->validate()) { + return $v->errorStr(); + } + return null; + } + + public function getRequiredSessionMode(): int + { + //General.aux 쓰므로 lock; + return static::REQ_GAME_LOGIN; + } + + public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag) + { + $userID = $session->userID; + $generalID = $session->generalID; + + $type = $this->args['type']; + + $general = General::createGeneralObjFromDB($generalID); + if ($userID != $general->getVar('owner')) { + return '로그인 상태가 이상합니다. 다시 로그인해 주세요.'; + } + + $inheritSpecificSpecialWar = $general->getAuxVar('inheritSpecificSpecialWar'); + $currentSpecialWar = $general->getVar('special2'); + + if ($currentSpecialWar == $type) { + return '이미 그 특기를 보유하고 있습니다.'; + } + if ($inheritSpecificSpecialWar == $type) { + return '이미 그 특기를 예약하였습니다.'; + } + + if ($inheritSpecificSpecialWar !== null) { + return '이미 예약한 특기가 있습니다.'; + } + + $reqAmount = GameConst::$inheritSpecificSpecialPoint; + + $db = DB::db(); + $inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}"); + $previousPoint = ($inheritStor->getValue('previous') ?? [0, 0])[0]; + if ($previousPoint < $reqAmount) { + return '충분한 유산 포인트를 가지고 있지 않습니다.'; + } + + $general->setAuxVar('inheritSpecificSpecialWar', $type); + $inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]); + $general->applyDB($db); + return null; + } +} diff --git a/hwe/sammo/ActionItem/che_반계_백우선.php b/hwe/sammo/ActionItem/che_반계_백우선.php index 4e10f5c4..4a38e014 100644 --- a/hwe/sammo/ActionItem/che_반계_백우선.php +++ b/hwe/sammo/ActionItem/che_반계_백우선.php @@ -19,9 +19,16 @@ class che_반계_백우선 extends \sammo\BaseItem{ protected $cost = 200; protected $consumable = false; + public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null) + { + $debuff = [ + 'warMagicSuccessProb' => 0.1, + ][$statName] ?? 0; + return $value - $debuff; + } + public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ return new WarUnitTriggerCaller( - new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*301, false, '계략약화'), new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*301), new che_반계발동($unit) ); diff --git a/hwe/sammo/ActionItem/che_반계_파초선.php b/hwe/sammo/ActionItem/che_반계_파초선.php index 5c19edfd..3a277e3e 100644 --- a/hwe/sammo/ActionItem/che_반계_파초선.php +++ b/hwe/sammo/ActionItem/che_반계_파초선.php @@ -19,9 +19,16 @@ class che_반계_파초선 extends \sammo\BaseItem{ protected $cost = 200; protected $consumable = false; + public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null) + { + $debuff = [ + 'warMagicSuccessProb' => 0.1, + ][$statName] ?? 0; + return $value - $debuff; + } + public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ return new WarUnitTriggerCaller( - new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*302, false, '계략약화'), new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*302), new che_반계발동($unit) ); diff --git a/hwe/sammo/ActionItem/che_서적_07_논어.php b/hwe/sammo/ActionItem/che_서적_07_논어.php index c92a5bd8..0212b932 100644 --- a/hwe/sammo/ActionItem/che_서적_07_논어.php +++ b/hwe/sammo/ActionItem/che_서적_07_논어.php @@ -18,9 +18,11 @@ class che_서적_07_논어 extends \sammo\BaseStatItem{ $this->info .= "
[전투] 상대의 계략 성공 확률 -10%p"; } - public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ - return new WarUnitTriggerCaller( - new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*207, false, '계략약화') - ); + public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null) + { + $debuff = [ + 'warMagicSuccessProb' => 0.1, + ][$statName] ?? 0; + return $value - $debuff; } } \ No newline at end of file diff --git a/hwe/sammo/ActionItem/che_서적_11_춘추전.php b/hwe/sammo/ActionItem/che_서적_11_춘추전.php index 0fa0ca84..7dc51ae5 100644 --- a/hwe/sammo/ActionItem/che_서적_11_춘추전.php +++ b/hwe/sammo/ActionItem/che_서적_11_춘추전.php @@ -18,9 +18,11 @@ class che_서적_11_춘추전 extends \sammo\BaseStatItem{ $this->info .= "
[전투] 상대의 계략 성공 확률 -10%p"; } - public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ - return new WarUnitTriggerCaller( - new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*211, false, '계략약화') - ); + public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null) + { + $debuff = [ + 'warMagicSuccessProb' => 0.1, + ][$statName] ?? 0; + return $value - $debuff; } } \ No newline at end of file diff --git a/hwe/sammo/ActionItem/che_치트_HideD의_사인검.php b/hwe/sammo/ActionItem/che_치트_HideD의_사인검.php index e95310c9..820c372e 100644 --- a/hwe/sammo/ActionItem/che_치트_HideD의_사인검.php +++ b/hwe/sammo/ActionItem/che_치트_HideD의_사인검.php @@ -1,5 +1,7 @@ 30, - 'bonusAtmos'=>30, - 'leadership'=>100, - 'strength'=>100, - 'intel'=>100, - 'warMagicSuccessProb'=>1, - ][$statName]??0; + 'bonusTrain' => 30, + 'bonusAtmos' => 30, + 'leadership' => 100, + 'strength' => 100, + 'intel' => 100, + 'warMagicSuccessProb' => 1, + ][$statName] ?? 0; return $bonus + $value; } - public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{ + public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null) + { + $debuff = [ + 'warMagicSuccessProb' => 0.1, + ][$statName] ?? 0; + return $value - $debuff; + } + + public function getPreTurnExecuteTriggerList(General $general): ?GeneralTriggerCaller + { return new GeneralTriggerCaller( new GeneralTrigger\che_도시치료($general) ); } - public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ + public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller + { return new WarUnitTriggerCaller( new che_부상무효($unit, BaseWarUnitTrigger::TYPE_NONE), new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '저격불가') @@ -73,10 +88,10 @@ EOT; public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller { return new WarUnitTriggerCaller( - new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '필살불가', '위압불가', '격노불가', '계략약화', '저격불가'), + new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '필살불가', '위압불가', '격노불가', '저격불가'), new che_전투치료시도($unit), new che_전투치료발동($unit), - new che_저격시도($unit, che_저격시도::TYPE_NONE, 1/2, 20, 60), + new che_저격시도($unit, che_저격시도::TYPE_NONE, 1 / 2, 20, 60), new che_저격발동($unit), new che_격노시도($unit), new che_격노발동($unit), @@ -84,8 +99,8 @@ EOT; ); } - public function getWarPowerMultiplier(WarUnit $unit):array{ + public function getWarPowerMultiplier(WarUnit $unit): array + { return [1, 0.95]; } - -} \ No newline at end of file +} diff --git a/hwe/sammo/ActionItem/event_전투특기_반계.php b/hwe/sammo/ActionItem/event_전투특기_반계.php index 372d4de1..3e2da17a 100644 --- a/hwe/sammo/ActionItem/event_전투특기_반계.php +++ b/hwe/sammo/ActionItem/event_전투특기_반계.php @@ -28,9 +28,16 @@ class event_전투특기_반계 extends \sammo\BaseItem{ return $value; } + public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null) + { + $debuff = [ + 'warMagicSuccessProb' => 0.1, + ][$statName] ?? 0; + return $value - $debuff; + } + public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ return new WarUnitTriggerCaller( - new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM + BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*401, false, '계략약화'), new che_반계시도($unit), new che_반계발동($unit) ); diff --git a/hwe/sammo/ActionSpecialDomestic/che_event_견고.php b/hwe/sammo/ActionSpecialDomestic/che_event_견고.php index 902682da..1cd1131d 100644 --- a/hwe/sammo/ActionSpecialDomestic/che_event_견고.php +++ b/hwe/sammo/ActionSpecialDomestic/che_event_견고.php @@ -21,6 +21,14 @@ class che_event_견고 extends \sammo\BaseSpecial{ SpecialityHelper::STAT_STRENGTH ]; + public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null) + { + $debuff = [ + 'warMagicSuccessProb' => 0.1, + ][$statName] ?? 0; + return $value - $debuff; + } + public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ return new WarUnitTriggerCaller( new che_부상무효($unit, BaseWarUnitTrigger::TYPE_ITEM), @@ -30,7 +38,7 @@ class che_event_견고 extends \sammo\BaseSpecial{ public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ return new WarUnitTriggerCaller( - new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM + BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*402, false, '필살불가', '계략약화', '저격불가') + new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM + BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*402, false, '필살불가', '저격불가') ); } diff --git a/hwe/sammo/ActionSpecialDomestic/che_event_반계.php b/hwe/sammo/ActionSpecialDomestic/che_event_반계.php index ec5b6c28..4bf5256d 100644 --- a/hwe/sammo/ActionSpecialDomestic/che_event_반계.php +++ b/hwe/sammo/ActionSpecialDomestic/che_event_반계.php @@ -33,10 +33,17 @@ class che_event_반계 extends \sammo\BaseSpecial return $value; } + public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null) + { + $debuff = [ + 'warMagicSuccessProb' => 0.1, + ][$statName] ?? 0; + return $value - $debuff; + } + public function getBattlePhaseSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller { return new WarUnitTriggerCaller( - new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM + BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE * 403, false, '계략약화'), new che_반계시도($unit), new che_반계발동($unit) ); diff --git a/hwe/sammo/ActionSpecialWar/che_견고.php b/hwe/sammo/ActionSpecialWar/che_견고.php index 3e3e0d5b..ed8bd76c 100644 --- a/hwe/sammo/ActionSpecialWar/che_견고.php +++ b/hwe/sammo/ActionSpecialWar/che_견고.php @@ -24,6 +24,14 @@ class che_견고 extends \sammo\BaseSpecial SpecialityHelper::STAT_STRENGTH ]; + public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null) + { + $debuff = [ + 'warMagicSuccessProb' => 0.1, + ][$statName] ?? 0; + return $value - $debuff; + } + public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller { return new WarUnitTriggerCaller( @@ -35,7 +43,7 @@ class che_견고 extends \sammo\BaseSpecial public function getBattlePhaseSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller { return new WarUnitTriggerCaller( - new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM + BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE * 404, false, '필살불가', '계략약화', '저격불가') + new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM + BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE * 404, false, '필살불가', '저격불가') ); } diff --git a/hwe/sammo/ActionSpecialWar/che_반계.php b/hwe/sammo/ActionSpecialWar/che_반계.php index 4d2117d5..2239a6df 100644 --- a/hwe/sammo/ActionSpecialWar/che_반계.php +++ b/hwe/sammo/ActionSpecialWar/che_반계.php @@ -29,9 +29,16 @@ class che_반계 extends \sammo\BaseSpecial{ return $value; } + public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null) + { + $debuff = [ + 'warMagicSuccessProb' => 0.1, + ][$statName] ?? 0; + return $value - $debuff; + } + public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ return new WarUnitTriggerCaller( - new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM + BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE * 406, false, '계략약화'), new che_반계시도($unit), new che_반계발동($unit) ); diff --git a/hwe/sammo/BaseAPI.php b/hwe/sammo/BaseAPI.php index 32f6d512..784a1193 100644 --- a/hwe/sammo/BaseAPI.php +++ b/hwe/sammo/BaseAPI.php @@ -10,15 +10,17 @@ abstract class BaseAPI const REQ_READ_ONLY = 4; protected array $args; - public function __construct(array $args) + protected string $rootPath; + public function __construct(string $rootPath, array $args) { + $this->rootPath = $rootPath; $this->args = $args; } abstract public function getRequiredSessionMode(): int; abstract function validateArgs(): ?string; /** @return null|string|array */ - abstract function launch(?Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag); + abstract function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag); public function tryCache():?string{ return null; diff --git a/hwe/sammo/Command/General/che_강행.php b/hwe/sammo/Command/General/che_강행.php index 426b7a75..392698f0 100644 --- a/hwe/sammo/Command/General/che_강행.php +++ b/hwe/sammo/Command/General/che_강행.php @@ -13,6 +13,7 @@ use \sammo\LastTurn; use \sammo\Command; use function \sammo\printCitiesBasedOnDistance; +use function sammo\tryUniqueItemLottery; use \sammo\Constraint\Constraint; use \sammo\Constraint\ConstraintHelper; @@ -161,6 +162,8 @@ class che_강행 extends Command\GeneralCommand $general->increaseVar('leadership_exp', 1); $this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $general->checkStatChange(); + tryUniqueItemLottery($general); + $general->applyDB($db); return true; diff --git a/hwe/sammo/Command/General/che_거병.php b/hwe/sammo/Command/General/che_거병.php index 02c3262d..c2dafdca 100644 --- a/hwe/sammo/Command/General/che_거병.php +++ b/hwe/sammo/Command/General/che_거병.php @@ -3,7 +3,7 @@ namespace sammo\Command\General; use \sammo\{ DB, Util, JosaUtil, - General, + General, ActionLogger, GameConst, GameUnitConst, LastTurn, @@ -16,13 +16,12 @@ use \sammo\Constraint\ConstraintHelper; use sammo\CityConst; use function sammo\refreshNationStaticInfo; use function sammo\getAllNationStaticInfo; - - +use function sammo\tryUniqueItemLottery; class che_거병 extends Command\GeneralCommand{ static protected $actionName = '거병'; - protected function argTest():bool{ + protected function argTest():bool{ $this->arg = []; return true; @@ -38,7 +37,7 @@ class che_거병 extends Command\GeneralCommand{ $this->setNation(); $relYear = $env['year'] - $env['startyear']; - + $this->fullConditionConstraints=[ ConstraintHelper::BeNeutral(), ConstraintHelper::BeOpeningPart($relYear+1), @@ -49,7 +48,7 @@ class che_거병 extends Command\GeneralCommand{ public function getCost():array{ return [0, 0]; } - + public function getPreReqTurn():int{ return 0; } @@ -93,15 +92,15 @@ class che_거병 extends Command\GeneralCommand{ DB::db()->insert('nation', [ 'name'=>$nationName, - 'color'=>'#330000', - 'gold'=>0, - 'rice'=>GameConst::$baserice, - 'rate'=>20, - 'bill'=>100, - 'strategic_cmd_limit'=>12, - 'surlimit'=>72, + 'color'=>'#330000', + 'gold'=>0, + 'rice'=>GameConst::$baserice, + 'rate'=>20, + 'bill'=>100, + 'strategic_cmd_limit'=>12, + 'surlimit'=>72, 'secretlimit'=>$secretlimit, - 'type'=>GameConst::$neutralNationType, + 'type'=>GameConst::$neutralNationType, 'gennum'=>1 ]); $nationID = DB::db()->insertId(); @@ -114,7 +113,7 @@ class che_거병 extends Command\GeneralCommand{ if($nationID == $destNationID){ continue; } - + $diplomacyInit[] = [ 'me'=>$destNationID, 'you'=>$nationID, @@ -132,9 +131,9 @@ class che_거병 extends Command\GeneralCommand{ if($diplomacyInit){ $db->insert('diplomacy', $diplomacyInit); } - - + + $turnRows = []; foreach([12, 11] as $chiefLevel){ foreach(Util::range(GameConst::$maxChiefTurn) as $turnIdx){ @@ -147,7 +146,7 @@ class che_거병 extends Command\GeneralCommand{ 'brief'=>'휴식', ]; } - + } $db->insert('nation_turn', $turnRows); @@ -172,10 +171,12 @@ class che_거병 extends Command\GeneralCommand{ $this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $general->checkStatChange(); + tryUniqueItemLottery($general); + $general->applyDB($db); return true; } - + } \ No newline at end of file diff --git a/hwe/sammo/Command/General/che_견문.php b/hwe/sammo/Command/General/che_견문.php index 480f955f..c7903fd5 100644 --- a/hwe/sammo/Command/General/che_견문.php +++ b/hwe/sammo/Command/General/che_견문.php @@ -3,7 +3,7 @@ namespace sammo\Command\General; use \sammo\{ DB, Util, JosaUtil, - General, + General, ActionLogger, GameConst, GameUnitConst, LastTurn, @@ -14,10 +14,11 @@ use \sammo\Constraint\Constraint; use \sammo\Constraint\ConstraintHelper; use \sammo\TextDecoration\SightseeingMessage; +use function sammo\tryUniqueItemLottery; class che_견문 extends Command\GeneralCommand{ static protected $actionName = '견문'; - + protected function argTest():bool{ $this->arg = null; return true; @@ -41,7 +42,7 @@ class che_견문 extends Command\GeneralCommand{ public function getCost():array{ return [0, 0]; } - + public function getPreReqTurn():int{ return 0; } @@ -111,10 +112,12 @@ class che_견문 extends Command\GeneralCommand{ $general->addExperience($exp); $this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $general->checkStatChange(); + tryUniqueItemLottery($general); + $general->applyDB($db); return true; } - + } \ No newline at end of file diff --git a/hwe/sammo/Command/General/che_군량매매.php b/hwe/sammo/Command/General/che_군량매매.php index 91e723cc..052d5b17 100644 --- a/hwe/sammo/Command/General/che_군량매매.php +++ b/hwe/sammo/Command/General/che_군량매매.php @@ -5,7 +5,7 @@ namespace sammo\Command\General; use \sammo\{ DB, Util, JosaUtil, - General, + General, ActionLogger, GameConst, GameUnitConst, LastTurn, @@ -16,6 +16,8 @@ use \sammo\Constraint\Constraint; use \sammo\Constraint\ConstraintHelper; use sammo\MustNotBeReachedException; +use function sammo\tryUniqueItemLottery; + class che_군량매매 extends Command\GeneralCommand{ static protected $actionName = '군량매매'; static public $reqArg = true; @@ -57,7 +59,7 @@ class che_군량매매 extends Command\GeneralCommand{ $general = $this->generalObj; $this->setCity(); - $this->setNation(); + $this->setNation(); $this->minConditionConstraints=[ ConstraintHelper::ReqCityTrader($general->getNPCType()), @@ -69,7 +71,7 @@ class che_군량매매 extends Command\GeneralCommand{ protected function initWithArg() { $general = $this->generalObj; - + $this->fullConditionConstraints=[ ConstraintHelper::ReqCityTrader($general->getNPCType()), ConstraintHelper::OccupiedCity(true), @@ -87,7 +89,7 @@ class che_군량매매 extends Command\GeneralCommand{ public function getCost():array{ return [0, 0]; } - + public function getPreReqTurn():int{ return 0; } @@ -120,7 +122,7 @@ class che_군량매매 extends Command\GeneralCommand{ else{ $tradeRate /= 100; } - + if($buyRice){ $buyKey = 'rice'; $sellKey = 'gold'; @@ -153,7 +155,7 @@ class che_군량매매 extends Command\GeneralCommand{ else{ $logger->pushGeneralActionLog("군량 {$sellAmountText}을 팔아 자금 {$buyAmountText}을 얻었습니다. <1>$date"); } - + $general->increaseVar($buyKey, $buyAmount); $general->increaseVarWithLimit($sellKey, -$sellAmount, 0); @@ -163,7 +165,7 @@ class che_군량매매 extends Command\GeneralCommand{ $exp = 30; $ded = 50; - + $incStat = Util::choiceRandomUsingWeight([ 'leadership_exp'=>$general->getLeadership(false, false, false, false), 'strength_exp'=>$general->getStrength(false, false, false, false), @@ -176,6 +178,8 @@ class che_군량매매 extends Command\GeneralCommand{ $this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $general->checkStatChange(); + tryUniqueItemLottery($general); + $general->applyDB($db); return true; @@ -199,5 +203,5 @@ class che_군량매매 extends Command\GeneralCommand{ return ob_get_clean(); } - + } \ No newline at end of file diff --git a/hwe/sammo/Command/General/che_귀환.php b/hwe/sammo/Command/General/che_귀환.php index b8c97942..7ca7c1f4 100644 --- a/hwe/sammo/Command/General/che_귀환.php +++ b/hwe/sammo/Command/General/che_귀환.php @@ -3,7 +3,7 @@ namespace sammo\Command\General; use \sammo\{ DB, Util, JosaUtil, - General, + General, ActionLogger, GameConst, GameUnitConst, LastTurn, @@ -14,7 +14,7 @@ use \sammo\Constraint\Constraint; use \sammo\Constraint\ConstraintHelper; use sammo\CityConst; - +use function sammo\tryUniqueItemLottery; class che_귀환 extends Command\GeneralCommand{ static protected $actionName = '귀환'; @@ -33,7 +33,7 @@ class che_귀환 extends Command\GeneralCommand{ $this->setNation(); [$reqGold, $reqRice] = $this->getCost(); - + $this->fullConditionConstraints=[ ConstraintHelper::NotBeNeutral(), ConstraintHelper::NotWanderingNation(), @@ -49,7 +49,7 @@ class che_귀환 extends Command\GeneralCommand{ public function getCost():array{ return [0, 0]; } - + public function getPreReqTurn():int{ return 0; } @@ -87,7 +87,7 @@ class che_귀환 extends Command\GeneralCommand{ $exp = 70; $ded = 100; - + $general->setVar('city', $destCityID); $general->addExperience($exp); @@ -95,10 +95,12 @@ class che_귀환 extends Command\GeneralCommand{ $general->increaseVar('leadership_exp', 1); $this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $general->checkStatChange(); + tryUniqueItemLottery($general); + $general->applyDB($db); return true; } - + } \ No newline at end of file diff --git a/hwe/sammo/Command/General/che_등용.php b/hwe/sammo/Command/General/che_등용.php index ec6b9949..72a4cc77 100644 --- a/hwe/sammo/Command/General/che_등용.php +++ b/hwe/sammo/Command/General/che_등용.php @@ -15,6 +15,7 @@ use \sammo\{ use function \sammo\getAllNationStaticInfo; use function \sammo\getNationStaticInfo; use function \sammo\newColor; +use function sammo\tryUniqueItemLottery; use \sammo\Constraint\Constraint; use \sammo\Constraint\ConstraintHelper; @@ -64,7 +65,7 @@ class che_등용 extends Command\GeneralCommand{ $this->minConditionConstraints=[ ConstraintHelper::ReqEnvValue('join_mode', '!=', 'onlyRandom', '랜덤 임관만 가능합니다'), - ConstraintHelper::NotBeNeutral(), + ConstraintHelper::NotBeNeutral(), ConstraintHelper::OccupiedCity(), ConstraintHelper::SuppliedCity(), ]; @@ -80,7 +81,7 @@ class che_등용 extends Command\GeneralCommand{ $this->fullConditionConstraints=[ ConstraintHelper::ReqEnvValue('join_mode', '!=', 'onlyRandom', '랜덤 임관만 가능합니다'), - ConstraintHelper::NotBeNeutral(), + ConstraintHelper::NotBeNeutral(), ConstraintHelper::OccupiedCity(), ConstraintHelper::SuppliedCity(), ConstraintHelper::ExistsDestGeneral(), @@ -110,7 +111,7 @@ class che_등용 extends Command\GeneralCommand{ ) * 10; return [$reqGold, 0]; } - + public function getPreReqTurn():int{ return 0; } @@ -141,7 +142,7 @@ class che_등용 extends Command\GeneralCommand{ $destGeneralName = $this->destGeneralObj->getName(); $destGeneralID = $this->destGeneralObj->getID(); - + $msg = ScoutMessage::buildScoutMessage($general->getID(), $destGeneralID, $reason, new \DateTime($general->getTurnTime())); if($msg){ @@ -164,6 +165,8 @@ class che_등용 extends Command\GeneralCommand{ $this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $general->checkStatChange(); + tryUniqueItemLottery($general); + $general->applyDB($db); return true; diff --git a/hwe/sammo/Command/General/che_물자조달.php b/hwe/sammo/Command/General/che_물자조달.php index 6123c5a1..ed63bc7b 100644 --- a/hwe/sammo/Command/General/che_물자조달.php +++ b/hwe/sammo/Command/General/che_물자조달.php @@ -3,7 +3,7 @@ namespace sammo\Command\General; use \sammo\{ DB, Util, JosaUtil, - General, + General, ActionLogger, GameConst, LastTurn, @@ -13,6 +13,7 @@ use \sammo\{ use function \sammo\getDomesticExpLevelBonus; use function \sammo\CriticalScoreEx; +use function sammo\tryUniqueItemLottery; use \sammo\Constraint\Constraint; use \sammo\Constraint\ConstraintHelper; @@ -33,9 +34,9 @@ class che_물자조달 extends Command\GeneralCommand{ $this->setCity(); $this->setNation(); - + $this->fullConditionConstraints=[ - ConstraintHelper::NotBeNeutral(), + ConstraintHelper::NotBeNeutral(), ConstraintHelper::NotWanderingNation(), ConstraintHelper::OccupiedCity(), ConstraintHelper::SuppliedCity() @@ -50,7 +51,7 @@ class che_물자조달 extends Command\GeneralCommand{ public function getCost():array{ return [0, 0]; } - + public function getPreReqTurn():int{ return 0; } @@ -84,11 +85,11 @@ class che_물자조달 extends Command\GeneralCommand{ 'normal'=>0.6 ]); $score *= CriticalScoreEx($pick); - + $score = Util::round($score); $scoreText = number_format($score, 0); - + $logger = $general->getLogger(); if($pick == 'fail'){ @@ -120,10 +121,12 @@ class che_물자조달 extends Command\GeneralCommand{ $this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $general->checkStatChange(); + tryUniqueItemLottery($general); + $general->applyDB($db); return true; } - + } \ No newline at end of file diff --git a/hwe/sammo/Command/General/che_이동.php b/hwe/sammo/Command/General/che_이동.php index 34fed929..db4fc213 100644 --- a/hwe/sammo/Command/General/che_이동.php +++ b/hwe/sammo/Command/General/che_이동.php @@ -13,6 +13,7 @@ use \sammo\LastTurn; use \sammo\Command; use function \sammo\printCitiesBasedOnDistance; +use function sammo\tryUniqueItemLottery; use \sammo\Constraint\Constraint; use \sammo\Constraint\ConstraintHelper; @@ -169,6 +170,8 @@ class che_이동 extends Command\GeneralCommand $general->increaseVar('leadership_exp', 1); $this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $general->checkStatChange(); + tryUniqueItemLottery($general); + $general->applyDB($db); return true; diff --git a/hwe/sammo/Command/General/che_장비매매.php b/hwe/sammo/Command/General/che_장비매매.php index 29879470..9904a40a 100644 --- a/hwe/sammo/Command/General/che_장비매매.php +++ b/hwe/sammo/Command/General/che_장비매매.php @@ -5,7 +5,7 @@ namespace sammo\Command\General; use \sammo\{ DB, Util, JosaUtil, - General, + General, ActionLogger, GameConst, GameUnitConst, LastTurn, @@ -13,6 +13,7 @@ use \sammo\{ }; use function \sammo\buildItemClass; +use function sammo\tryUniqueItemLottery; use \sammo\Constraint\Constraint; use \sammo\Constraint\ConstraintHelper; @@ -97,14 +98,14 @@ class che_장비매매 extends Command\GeneralCommand{ if(!$this->isArgValid){ return [0, 0]; } - + $itemCode = $this->arg['itemCode']; $itemObj = buildItemClass($itemCode); $reqGold = $itemObj->getCost(); return [$reqGold, 0]; } - + public function getPreReqTurn():int{ return 0; } @@ -176,6 +177,7 @@ class che_장비매매 extends Command\GeneralCommand{ $general->addExperience($exp); $this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $general->checkStatChange(); + tryUniqueItemLottery($general); $general->applyDB($db); return true; @@ -208,7 +210,7 @@ $('#customSubmit').click(function(){ 현재 구입 불가능한 것은 붉은색으로 표시됩니다.
현재 도시 치안 :    현재 자금 :
장비 :