From 160946ef74bde0d1d182cfcbbc4931d55f277894 Mon Sep 17 00:00:00 2001 From: hide_d Date: Sun, 12 Sep 2021 00:50:56 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=95=84=EC=9D=B4=ED=85=9C=20=EC=9C=A0?= =?UTF-8?q?=EC=82=B0=ED=8F=AC=EC=9D=B8=ED=8A=B8=EB=A1=9C=20=EC=9E=85?= =?UTF-8?q?=EC=B0=B0=ED=95=9C=20=EA=B2=BD=EC=9A=B0=20=EC=B5=9C=EC=A2=85?= =?UTF-8?q?=EC=A0=81=EC=9C=BC=EB=A1=9C=20=EC=96=BB=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/func.php | 268 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 223 insertions(+), 45 deletions(-) diff --git a/hwe/func.php b/hwe/func.php index 68ac8331..1c495f6a 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(); @@ -1284,7 +1285,7 @@ function addAge() $generalID = $general['no']; $special2 = SpecialityHelper::pickSpecialWar( $general, - (Json::decode($general['aux'])['prev_types_special2'])??[] + (Json::decode($general['aux'])['prev_types_special2']) ?? [] ); $specialClass = buildGeneralSpecialWarClass($special2); $specialText = $specialClass->getName(); @@ -1537,15 +1538,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 +1562,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 +1608,177 @@ 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'); + 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); + } + + $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'], $general->getVar('icon')); + $josaUl = JosaUtil::pick($itemName, '을'); + $msg = new Message( + Message::MSGTYPE_PRIVATE, + $src, + $dest, + "{$itemName}{$josaUl} 얻지 못했습니다. {$reason}", + new DateTime(), + $unlimited, + [] + ); + + $msg->send(true); +} + +function tryInheritUniqueItem(General $general, string $acquireType = '아이템'): bool +{ + $ownerID = $general->getVar('owner'); + if (!$ownerID) { + return false; + } + + $itemTrials = $general->getAuxVar('inheritUniqueTrial') ?? []; + arsort($itemTrials); + + $db = DB::db(); + + $acquireTarget = null; + $acquireType = 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; + } + usort($anyTrials, function ($lhsTrial, $rhsTrial) { + [,, $lhsAmount] = $lhsTrial; + [,, $rhsAmount] = $rhsTrial; + return $rhsAmount <=> $lhsAmount; //큰 값이 앞에 오도록 + }); + + //공동 1등인데 본인이 있을 수도 있다. + [,, $topAmount] = $anyTrials; + 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 (!$acquireTarget) { + //이미 다른 아이템을 얻기로 되어있다. + continue; + } + $acquireTarget = $itemKey; + $acquireType = $itemType; + } + unset($itemKey); + unset($itemType); + + if (!$acquireTarget) { + return false; + } + + $trialStor = KVStorage::getStorage($db, "ut_{$acquireTarget}"); + $trialStor->deleteValue("u{$ownerID}"); + + //rollbackInheritUniqueTrial 과정 때문에 새로 받아와야함 + $itemTrials = $general->getAuxVar('inheritUniqueTrial'); + unset($itemTrials[$acquireTarget]); + $general->setAuxVar('inheritUniqueTrial', $itemTrials); + + $nationName = $general->getStaticNation()['name']; + $generalName = $general->getName(); + $josaYi = JosaUtil::pick($generalName, '이'); + $itemObj = buildItemClass($acquireTarget); + $itemName = $itemObj->getName(); + $itemRawName = $itemObj->getRawName(); + $josaUl = JosaUtil::pick($itemRawName, '을'); + + + $general->setVar($acquireType, $acquireTarget); + + + $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} 습득했습니다!"); + + return true; +} + function tryUniqueItemLottery(General $general, string $acquireType = '아이템'): bool { $db = DB::db(); @@ -1616,8 +1788,12 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템 return false; } - if ($general->getNPCType() > 6) { - return false; + $inheritUnique = $general->getAuxVar('inheritUniqueTrial'); + if (count($inheritUnique)) { + $trialResult = tryInheritUniqueItem($general, $acquireType); + if ($trialResult) { + return true; + } } $itemTypeCnt = count(GameConst::$allItems); @@ -1629,7 +1805,7 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템 } } - if($trialCnt <= 0){ + if ($trialCnt <= 0) { LogText("{$general->getName()}, {$general->getID()} 모든 아이템", $trialCnt); return false; } @@ -1653,18 +1829,18 @@ 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; - foreach(Util::range($trialCnt) as $_idx){ + foreach (Util::range($trialCnt) as $_idx) { if (Util::randBool($prob)) { $result = true; break; } } - if(!$result){ + if (!$result) { LogText("{$general->getName()}, {$general->getID()} 유니크 실패 {$trialCnt}", $prob); return false; } @@ -1681,7 +1857,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 +1882,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 +1899,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 +1917,7 @@ function deleteNation(General $lord, bool $applyDB):array $logger->pushGeneralActionLog($destroyLog, ActionLogger::PLAIN); $logger->pushGeneralHistoryLog($destroyHistoryLog); - if($applyDB){ + if ($applyDB) { $general->applyDB($db); } }