feat,wip: 유니크 경매 시작, 입찰 구현
- 누군가는 무작위로 유니크를 하나를 먹을 수 있도록 설계?
This commit is contained in:
+14
-43
@@ -48,54 +48,25 @@ $db = DB::db();
|
|||||||
<font color=red>접속제한</font><br><b style=background-color:red;>블럭회원</b>
|
<font color=red>접속제한</font><br><b style=background-color:red;>블럭회원</b>
|
||||||
</td>
|
</td>
|
||||||
<td width=105 rowspan=12>
|
<td width=105 rowspan=12>
|
||||||
<?php
|
<select name=genlist[] size=20 multiple style='color:white;background-color:black;font-size:14px'>
|
||||||
|
<?php
|
||||||
|
$generalList = $db->query('SELECT `no`, `name`, npc, `block` FROM general ORDER BY npc, binary(`name`)');
|
||||||
|
|
||||||
echo "
|
foreach ($generalList as $general) {
|
||||||
<select name=genlist[] size=20 multiple style='color:white;background-color:black;font-size:14px'>";
|
$style = "style=;";
|
||||||
$generalList = $db->query('SELECT `no`, `name`, npc, `block` FROM general ORDER BY npc, binary(`name`)');
|
if ($general['block'] > 0) {
|
||||||
|
$style .= "background-color:red;";
|
||||||
foreach ($generalList as $general) {
|
|
||||||
$style = "style=;";
|
|
||||||
if ($general['block'] > 0) {
|
|
||||||
$style .= "background-color:red;";
|
|
||||||
}
|
|
||||||
|
|
||||||
$npcColor = getNPCColor($general['npc']);
|
|
||||||
if($npcColor !== null){
|
|
||||||
$style .= "color:{$npcColor};";
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "
|
|
||||||
<option value={$general['no']} $style>{$general['name']}</option>";
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
<td width=100 align=center>아이템 지급</td>
|
|
||||||
<td width=504>
|
|
||||||
<select name=weapon size=1 style='color:white;background-color:black;font-size:14px'>";
|
|
||||||
foreach (GameConst::$allItems as $itemCategories) {
|
|
||||||
foreach ($itemCategories as $item => $cnt) {
|
|
||||||
if ($cnt == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
$itemObj = buildItemClass($item);
|
|
||||||
if ($itemObj->isBuyable()) {
|
$npcColor = getNPCColor($general['npc']);
|
||||||
continue;
|
if ($npcColor !== null) {
|
||||||
|
$style .= "color:{$npcColor};";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
echo "<option value={$general['no']} $style>{$general['name']}</option>";
|
||||||
}
|
}
|
||||||
}
|
?>
|
||||||
for ($i = 0; $i < 27; $i++) {
|
|
||||||
echo "
|
|
||||||
<option value={$i}>{$i}</option>";
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</select>
|
</select>
|
||||||
<input type=submit name=btn value='무기지급'>
|
|
||||||
<input type=submit name=btn value='책지급'>
|
|
||||||
<input type=submit name=btn value='말지급'>
|
|
||||||
<input type=submit name=btn value='도구지급'>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -200,95 +200,6 @@ switch ($btn) {
|
|||||||
$msg->send(true);
|
$msg->send(true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "무기지급":
|
|
||||||
|
|
||||||
if ($item == 'None') {
|
|
||||||
$text = "무기 회수!";
|
|
||||||
} else {
|
|
||||||
$text = getItemName($item) . " 지급!";
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($genlist as $generalID) {
|
|
||||||
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
|
|
||||||
$msg->send(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($item === 'None') {
|
|
||||||
$db->update('general', [
|
|
||||||
'weapon' => 'None'
|
|
||||||
], '`no` IN %li', $genlist);
|
|
||||||
} else {
|
|
||||||
$db->update('general', [
|
|
||||||
'weapon' => $item
|
|
||||||
], '`no` IN %li', $genlist, $item);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "책지급":
|
|
||||||
if ($item == 'None') {
|
|
||||||
$text = "책 회수!";
|
|
||||||
} else {
|
|
||||||
$text = getItemName($item) . " 지급!";
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($genlist as $generalID) {
|
|
||||||
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
|
|
||||||
$msg->send(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($item == 'None') {
|
|
||||||
$db->update('general', [
|
|
||||||
'book' => 'None'
|
|
||||||
], '`no` IN %li', $genlist);
|
|
||||||
} else {
|
|
||||||
$db->update('general', [
|
|
||||||
'book' => $item
|
|
||||||
], '`no` IN %li', $genlist);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "말지급":
|
|
||||||
if ($item == 'None') {
|
|
||||||
$text = "말 회수!";
|
|
||||||
} else {
|
|
||||||
$text = getItemName($item) . " 지급!";
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($genlist as $generalID) {
|
|
||||||
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
|
|
||||||
$msg->send(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($item == 'None') {
|
|
||||||
$db->update('general', [
|
|
||||||
'horse' => 'None'
|
|
||||||
], '`no` IN %li', $genlist);
|
|
||||||
} else {
|
|
||||||
$db->update('general', [
|
|
||||||
'horse' => $item
|
|
||||||
], '`no` IN %li', $genlist);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "도구지급":
|
|
||||||
if ($item == 'None') {
|
|
||||||
$text = "특수도구 회수!";
|
|
||||||
} else {
|
|
||||||
$text = getItemName($item) . " 지급!";
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($genlist as $generalID) {
|
|
||||||
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
|
|
||||||
$msg->send(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($item == 'None') {
|
|
||||||
$db->update('general', [
|
|
||||||
'item' => 'None'
|
|
||||||
], '`no` IN %li', $genlist);
|
|
||||||
} else {
|
|
||||||
$db->update('general', [
|
|
||||||
'item' => $item
|
|
||||||
], '`no` IN %li AND item < %i', $genlist, $item);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "하야입력":
|
case "하야입력":
|
||||||
$db->update('general_turn', [
|
$db->update('general_turn', [
|
||||||
'action' => 'che_하야',
|
'action' => 'che_하야',
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace sammo;
|
namespace sammo;
|
||||||
|
|
||||||
use DateTime;
|
use DateTime;
|
||||||
|
use Ds\Set;
|
||||||
use sammo\Enums\InheritanceKey;
|
use sammo\Enums\InheritanceKey;
|
||||||
use sammo\Enums\RankColumn;
|
use sammo\Enums\RankColumn;
|
||||||
use sammo\Event\Action;
|
use sammo\Event\Action;
|
||||||
@@ -1665,6 +1666,10 @@ function giveRandomUniqueItem(RandUtil $rng, General $general, string $acquireTy
|
|||||||
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 습득했습니다!");
|
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 습득했습니다!");
|
||||||
$logger->pushGlobalHistoryLog("<C><b>【{$acquireType}】</b></><D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 습득했습니다!");
|
$logger->pushGlobalHistoryLog("<C><b>【{$acquireType}】</b></><D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 습득했습니다!");
|
||||||
|
|
||||||
|
$givenUnique =$gameStor->getValue('givenUnique') ?? [];
|
||||||
|
$givenUnique[$itemCode] = ($givenUnique[$itemCode] ?? 0) + 1;
|
||||||
|
$gameStor->setValue('givenUnique', $givenUnique);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1866,6 +1871,11 @@ function tryInheritUniqueItem(RandUtil $rng, General $general, string $acquireTy
|
|||||||
|
|
||||||
$general->applyDB($db);
|
$general->applyDB($db);
|
||||||
|
|
||||||
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$givenUnique =$gameStor->getValue('givenUnique') ?? [];
|
||||||
|
$givenUnique[$ownTarget] = ($givenUnique[$ownTarget] ?? 0) + 1;
|
||||||
|
$gameStor->setValue('givenUnique', $givenUnique);
|
||||||
|
|
||||||
//같은 종류의 유니크를 입찰했을 수 있으니 한번 더 검사한다.
|
//같은 종류의 유니크를 입찰했을 수 있으니 한번 더 검사한다.
|
||||||
tryRollbackInheritUniqueItem($rng, $general);
|
tryRollbackInheritUniqueItem($rng, $general);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace sammo\API\Auction;
|
||||||
|
|
||||||
|
use sammo\Session;
|
||||||
|
use DateTimeInterface;
|
||||||
|
use sammo\AuctionUniqueItem;
|
||||||
|
use sammo\Validator;
|
||||||
|
use sammo\GameConst;
|
||||||
|
use sammo\General;
|
||||||
|
|
||||||
|
use function sammo\buildItemClass;
|
||||||
|
|
||||||
|
class BidUniqueAuction extends \sammo\BaseAPI
|
||||||
|
{
|
||||||
|
public function validateArgs(): ?string
|
||||||
|
{
|
||||||
|
$availableItems = [];
|
||||||
|
foreach (GameConst::$allItems as $items) {
|
||||||
|
foreach ($items as $itemKey => $amount) {
|
||||||
|
if ($amount == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$availableItems[$itemKey] = $amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$v = new Validator($this->args);
|
||||||
|
$v->rule('required', [
|
||||||
|
'auctionID',
|
||||||
|
'amount',
|
||||||
|
])
|
||||||
|
->rule('int', 'amount')
|
||||||
|
->rule('int', 'auctionID')
|
||||||
|
->rule('boolean', 'extendCloseDate');
|
||||||
|
|
||||||
|
if (!$v->validate()) {
|
||||||
|
return $v->errorStr();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRequiredSessionMode(): int
|
||||||
|
{
|
||||||
|
return static::REQ_GAME_LOGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||||
|
{
|
||||||
|
$auctionID = $this->args['auctionID'];
|
||||||
|
$amount = $this->args['amount'];
|
||||||
|
$tryExtendCloseDate = $this->arg['extendCloseDate'] ?? false;
|
||||||
|
|
||||||
|
$generalID = $session->generalID;
|
||||||
|
$general = General::createGeneralObjFromDB($generalID);
|
||||||
|
$auction = new AuctionUniqueItem($auctionID, $general);
|
||||||
|
$result = $auction->bid($amount, $tryExtendCloseDate);
|
||||||
|
|
||||||
|
if (is_string($result)) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,14 +4,12 @@ namespace sammo\API\Auction;
|
|||||||
|
|
||||||
use sammo\Session;
|
use sammo\Session;
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
use sammo\Betting;
|
use sammo\AuctionUniqueItem;
|
||||||
use sammo\DB;
|
|
||||||
use sammo\DTO\BettingItem;
|
|
||||||
use sammo\Validator;
|
use sammo\Validator;
|
||||||
use sammo\GameConst;
|
use sammo\GameConst;
|
||||||
use sammo\KVStorage;
|
use sammo\General;
|
||||||
use sammo\UserLogger;
|
|
||||||
use sammo\Util;
|
use function sammo\buildItemClass;
|
||||||
|
|
||||||
class OpenUniqueAuction extends \sammo\BaseAPI
|
class OpenUniqueAuction extends \sammo\BaseAPI
|
||||||
{
|
{
|
||||||
@@ -34,7 +32,7 @@ class OpenUniqueAuction extends \sammo\BaseAPI
|
|||||||
])
|
])
|
||||||
->rule('int', 'amount')
|
->rule('int', 'amount')
|
||||||
->rule('min', 'amount', GameConst::$inheritItemUniqueMinPoint)
|
->rule('min', 'amount', GameConst::$inheritItemUniqueMinPoint)
|
||||||
->rule('keyExists', 'item', $availableItems);
|
->rule('keyExists', 'itemID', $availableItems);
|
||||||
|
|
||||||
|
|
||||||
if (!$v->validate()) {
|
if (!$v->validate()) {
|
||||||
@@ -50,22 +48,22 @@ class OpenUniqueAuction extends \sammo\BaseAPI
|
|||||||
|
|
||||||
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||||
{
|
{
|
||||||
/** @var int */
|
$itemID = $this->args['itemID'];
|
||||||
$bettingID = $this->args['bettingID'];
|
|
||||||
/** @var int[] */
|
|
||||||
$bettingType = $this->args['bettingType'];
|
|
||||||
/** @var int */
|
|
||||||
$amount = $this->args['amount'];
|
$amount = $this->args['amount'];
|
||||||
|
$generalID = $session->generalID;
|
||||||
|
|
||||||
$bettingHelper = new Betting($bettingID);
|
$itemObj = buildItemClass($itemID);
|
||||||
try {
|
$general = General::createGeneralObjFromDB($generalID);
|
||||||
$bettingHelper->bet($session->generalID, $session->userID, $bettingType, $amount);
|
|
||||||
} catch (\Throwable $e) {
|
$auctionResult = AuctionUniqueItem::openItemAuction($itemObj, $general, $amount);
|
||||||
return $e->getMessage();
|
|
||||||
|
if(is_string($auctionResult)) {
|
||||||
|
return $auctionResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'result' => true
|
'result' => true,
|
||||||
|
'auctionID' => $auctionResult->id,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace sammo\API\General;
|
namespace sammo\API\General;
|
||||||
|
|
||||||
|
use Ds\Set;
|
||||||
use sammo\DB;
|
use sammo\DB;
|
||||||
use sammo\Validator;
|
use sammo\Validator;
|
||||||
|
|
||||||
@@ -9,6 +10,7 @@ use sammo\Session;
|
|||||||
use sammo\GameConst;
|
use sammo\GameConst;
|
||||||
use sammo\General;
|
use sammo\General;
|
||||||
use sammo\JosaUtil;
|
use sammo\JosaUtil;
|
||||||
|
use sammo\KVStorage;
|
||||||
|
|
||||||
class DropItem extends \sammo\BaseAPI
|
class DropItem extends \sammo\BaseAPI
|
||||||
{
|
{
|
||||||
@@ -56,12 +58,30 @@ class DropItem extends \sammo\BaseAPI
|
|||||||
$logger->pushGeneralActionLog("<C>{$itemName}</>{$josaUl} 버렸습니다.");
|
$logger->pushGeneralActionLog("<C>{$itemName}</>{$josaUl} 버렸습니다.");
|
||||||
|
|
||||||
$nationName = $me->getStaticNation()['name'];
|
$nationName = $me->getStaticNation()['name'];
|
||||||
|
$db = DB::db();
|
||||||
if (!$item->isBuyable()) {
|
if (!$item->isBuyable()) {
|
||||||
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 잃었습니다!");
|
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 잃었습니다!");
|
||||||
$logger->pushGlobalHistoryLog("<R><b>【망실】</b></><D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 잃었습니다!");
|
$logger->pushGlobalHistoryLog("<R><b>【망실】</b></><D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 잃었습니다!");
|
||||||
|
|
||||||
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$givenUnique = $gameStor->getValue('givenUnique') ?? [];
|
||||||
|
$itemCode = $item->getRawClassName();
|
||||||
|
if (key_exists($itemCode, $givenUnique)) {
|
||||||
|
$givenUniqueCnt = $givenUnique[$itemCode];
|
||||||
|
$givenUniqueCnt -= 1;
|
||||||
|
if ($givenUniqueCnt <= 0) {
|
||||||
|
unset($givenUnique[$itemCode]);
|
||||||
|
} else {
|
||||||
|
$givenUnique[$itemCode] = $givenUniqueCnt;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//XXX: 처리하지 못한 코드가 있는가?
|
||||||
|
//FIXME: 여기에서 무언가 경고를 내야함
|
||||||
|
}
|
||||||
|
$gameStor->setValue('givenUnique', $givenUnique);
|
||||||
}
|
}
|
||||||
|
|
||||||
$me->applyDB(DB::db());
|
$me->applyDB($db);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -317,8 +317,6 @@ class Auction
|
|||||||
return '입찰에 실패했습니다: DB 오류';
|
return '입찰에 실패했습니다: DB 오류';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$general->setVar($resType->value, $general->getVar($resType->value) - $morePoint);
|
$general->setVar($resType->value, $general->getVar($resType->value) - $morePoint);
|
||||||
|
|
||||||
if ($myPrevBid === null || ($highestBid !== null && $myPrevBid->id !== $highestBid->id)) {
|
if ($myPrevBid === null || ($highestBid !== null && $myPrevBid->id !== $highestBid->id)) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace sammo;
|
namespace sammo;
|
||||||
|
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
|
use Ds\Set;
|
||||||
use sammo\DTO\AuctionBidItem;
|
use sammo\DTO\AuctionBidItem;
|
||||||
use sammo\DTO\AuctionInfo;
|
use sammo\DTO\AuctionInfo;
|
||||||
use sammo\DTO\AuctionInfoDetail;
|
use sammo\DTO\AuctionInfoDetail;
|
||||||
@@ -59,10 +60,33 @@ class AuctionUniqueItem extends Auction
|
|||||||
return '구매할 수 있는 아이템입니다.';
|
return '구매할 수 있는 아이템입니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$itemKey = $item->getRawClassName();
|
||||||
|
$db = DB::db();
|
||||||
|
$auctionIDonProgress = $db->queryFirstField(
|
||||||
|
'SELECT `id` FROM ng_auction WHERE `finished` = 0 AND `target` = %s AND `target` = %s',
|
||||||
|
AuctionType::UniqueItem->value,
|
||||||
|
$itemKey
|
||||||
|
);
|
||||||
|
if ($auctionIDonProgress !== null) {
|
||||||
|
return '이미 경매가 진행중입니다.';
|
||||||
|
}
|
||||||
|
|
||||||
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$givenUnique = $gameStor->getValue('givenUnique') ?? [];
|
||||||
|
$givenUniqueCnt = $givenUnique[$itemKey] ?? 0;
|
||||||
|
$remainUniqueCnt = 0;
|
||||||
|
foreach (GameConst::$allItems as $itemList) {
|
||||||
|
if (!key_exists($itemKey, $itemList)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$remainUniqueCnt += $itemList[$itemKey];
|
||||||
|
}
|
||||||
|
if ($remainUniqueCnt > 1 && $givenUniqueCnt >= $remainUniqueCnt - 1) {
|
||||||
|
return '더이상 이 아이템을 경매로 가져갈 수 없습니다.';
|
||||||
|
}
|
||||||
|
|
||||||
$now = new DateTimeImmutable();
|
$now = new DateTimeImmutable();
|
||||||
|
|
||||||
$db = DB::db();
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$turnTerm = $gameStor->getValue('turnterm');
|
||||||
|
|
||||||
$closeDate = $now->add(TimeUtil::secondsToDateInterval(
|
$closeDate = $now->add(TimeUtil::secondsToDateInterval(
|
||||||
@@ -76,7 +100,7 @@ class AuctionUniqueItem extends Auction
|
|||||||
null,
|
null,
|
||||||
AuctionType::UniqueItem,
|
AuctionType::UniqueItem,
|
||||||
false,
|
false,
|
||||||
$item->getRawClassName(),
|
$itemKey,
|
||||||
$general->getID(),
|
$general->getID(),
|
||||||
ResourceType::inheritancePoint,
|
ResourceType::inheritancePoint,
|
||||||
$now,
|
$now,
|
||||||
@@ -113,6 +137,9 @@ class AuctionUniqueItem extends Auction
|
|||||||
{
|
{
|
||||||
|
|
||||||
$itemKey = $this->info->target;
|
$itemKey = $this->info->target;
|
||||||
|
if ($itemKey === null) {
|
||||||
|
throw new \Exception('아이템 키가 없습니다.');
|
||||||
|
}
|
||||||
$itemObj = buildItemClass($itemKey);
|
$itemObj = buildItemClass($itemKey);
|
||||||
$general = $bidder;
|
$general = $bidder;
|
||||||
$availableItemTypes = [];
|
$availableItemTypes = [];
|
||||||
@@ -192,6 +219,11 @@ class AuctionUniqueItem extends Auction
|
|||||||
$logger->pushGlobalHistoryLog("<C><b>【보물발견】</b></><D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 습득했습니다!");
|
$logger->pushGlobalHistoryLog("<C><b>【보물발견】</b></><D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 습득했습니다!");
|
||||||
|
|
||||||
$general->applyDB($db);
|
$general->applyDB($db);
|
||||||
|
|
||||||
|
$givenUnique = $gameStor->getValue('givenUnique') ?? [];
|
||||||
|
$givenUnique[$itemKey] = ($givenUnique[$itemKey] ?? 0) + 1;
|
||||||
|
$gameStor->setValue('givenUnique', $givenUnique);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +295,60 @@ class AuctionUniqueItem extends Auction
|
|||||||
|
|
||||||
public function bid(int $amount, bool $tryExtendCloseDate = false): ?string
|
public function bid(int $amount, bool $tryExtendCloseDate = false): ?string
|
||||||
{
|
{
|
||||||
//TODO: 입찰 가능 제한확인(다른 경매 진행 등)
|
|
||||||
|
$db = DB::db();
|
||||||
|
/** @var AuctionInfo[] */
|
||||||
|
$openUniqueAuctions = array_map(fn ($raw) => AuctionInfo::fromArray($raw), $db->query(
|
||||||
|
'SELECT * FROM `ng_auction` WHERE `finished` = 0 AND `type`= %s',
|
||||||
|
AuctionType::UniqueItem->value
|
||||||
|
) ?? []);
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
$rawHighestBids = Util::convertArrayToDict($db->queryFirstRow(
|
||||||
|
'SELECT * FROM ng_auction_bid WHERE auction_id IN %i ORDER BY `amount` DESC LIMIT 1',
|
||||||
|
$this->info->id
|
||||||
|
) ?? [], 'auction_id');
|
||||||
|
/** @var array<int,AuctionBidItem> */
|
||||||
|
$highestBids = Util::mapWithKey(
|
||||||
|
fn ($auctionID, $bid) => AuctionBidItem::fromArray($bid),
|
||||||
|
$rawHighestBids
|
||||||
|
);
|
||||||
|
|
||||||
|
$itemCode = $this->info->target;
|
||||||
|
$bidItemTypes = new Set();
|
||||||
|
foreach (GameConst::$allItems as $itemType => $itemList) {
|
||||||
|
if (($itemList[$itemCode] ?? 0) <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$bidItemTypes->add($itemType);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($openUniqueAuctions as $auction) {
|
||||||
|
$auctionID = $auction->id;
|
||||||
|
if (!isset($highestBids[$auctionID])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($auctionID === $this->auctionID) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$bid = $highestBids[$auctionID];
|
||||||
|
if ($bid->generalID !== $this->general->getID()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$itemCodeComp = $auction->target;
|
||||||
|
|
||||||
|
foreach (GameConst::$allItems as $itemType => $itemList) {
|
||||||
|
if (($itemList[$itemCodeComp] ?? 0) <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($bidItemTypes->contains($itemType)) {
|
||||||
|
return '1순위 입찰자인 경매중에 같은 부위가 있습니다.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return parent::bid($amount, $tryExtendCloseDate);
|
return parent::bid($amount, $tryExtendCloseDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ use \sammo\{
|
|||||||
GameConst,
|
GameConst,
|
||||||
GameUnitConst,
|
GameUnitConst,
|
||||||
LastTurn,
|
LastTurn,
|
||||||
Command
|
Command,
|
||||||
|
KVStorage
|
||||||
};
|
};
|
||||||
|
|
||||||
use function \sammo\buildItemClass;
|
use function \sammo\buildItemClass;
|
||||||
@@ -181,12 +182,28 @@ class che_장비매매 extends Command\GeneralCommand
|
|||||||
$general->onArbitraryAction($general, $rng, '장비매매', '판매', ['itemCode' => $itemCode]);
|
$general->onArbitraryAction($general, $rng, '장비매매', '판매', ['itemCode' => $itemCode]);
|
||||||
$general->setItem($itemType, null);
|
$general->setItem($itemType, null);
|
||||||
|
|
||||||
if(!$itemObj->isBuyable()){
|
if (!$itemObj->isBuyable()) {
|
||||||
$generalName = $general->getName();
|
$generalName = $general->getName();
|
||||||
$josaYi = JosaUtil::pick($generalName, '이');
|
$josaYi = JosaUtil::pick($generalName, '이');
|
||||||
$nationName = $general->getStaticNation()['name'];
|
$nationName = $general->getStaticNation()['name'];
|
||||||
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 판매했습니다!");
|
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 판매했습니다!");
|
||||||
$logger->pushGlobalHistoryLog("<R><b>【판매】</b></><D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 판매했습니다!");
|
$logger->pushGlobalHistoryLog("<R><b>【판매】</b></><D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 판매했습니다!");
|
||||||
|
|
||||||
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$givenUnique = $gameStor->getValue('givenUnique') ?? [];
|
||||||
|
if (key_exists($itemCode, $givenUnique)) {
|
||||||
|
$givenUniqueCnt = $givenUnique[$itemCode];
|
||||||
|
$givenUniqueCnt -= 1;
|
||||||
|
if ($givenUniqueCnt <= 0) {
|
||||||
|
unset($givenUnique[$itemCode]);
|
||||||
|
} else {
|
||||||
|
$givenUnique[$itemCode] = $givenUniqueCnt;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//XXX: 처리하지 못한 코드가 있는가?
|
||||||
|
//FIXME: 여기에서 무언가 경고를 내야함
|
||||||
|
}
|
||||||
|
$gameStor->setValue('givenUnique', $givenUnique);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user