feat,wip: 금,쌀 거래장 관련 로직 조정
This commit is contained in:
+113
-161
@@ -14,7 +14,6 @@ use sammo\RandUtil;
|
||||
|
||||
class AuctionUniqueItem extends Auction
|
||||
{
|
||||
|
||||
static public function genObfuscatedName(int $id): string
|
||||
{
|
||||
$db = DB::db();
|
||||
@@ -63,7 +62,7 @@ class AuctionUniqueItem extends Auction
|
||||
$itemKey = $item->getRawClassName();
|
||||
$db = DB::db();
|
||||
$auctionIDonProgress = $db->queryFirstField(
|
||||
'SELECT `id` FROM ng_auction WHERE `finished` = 0 AND `target` = %s AND `target` = %s',
|
||||
'SELECT `id` FROM ng_auction WHERE `finished` = 0 AND `type` = %s AND `target` = %s',
|
||||
AuctionType::UniqueItem->value,
|
||||
$itemKey
|
||||
);
|
||||
@@ -71,6 +70,15 @@ class AuctionUniqueItem extends Auction
|
||||
return '이미 경매가 진행중입니다.';
|
||||
}
|
||||
|
||||
$prevAuctionID = $db->queryFirstField(
|
||||
'SELECT id FROM ng_auction WHERE opener_general_id = %i AND finished = 0 AND `type` = %s',
|
||||
$general->getID(),
|
||||
AuctionType::UniqueItem->value,
|
||||
);
|
||||
if ($prevAuctionID !== null) {
|
||||
return '아직 경매가 끝나지 않았습니다.';
|
||||
}
|
||||
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$givenUnique = $gameStor->getValue('givenUnique') ?? [];
|
||||
$givenUniqueCnt = $givenUnique[$itemKey] ?? 0;
|
||||
@@ -108,7 +116,8 @@ class AuctionUniqueItem extends Auction
|
||||
new AuctionInfoDetail(
|
||||
"{$item->getName()} 경매",
|
||||
static::genObfuscatedName($general->getID()),
|
||||
|
||||
1,
|
||||
false,
|
||||
$startAmount,
|
||||
null,
|
||||
1,
|
||||
@@ -133,164 +142,9 @@ class AuctionUniqueItem extends Auction
|
||||
return $auction;
|
||||
}
|
||||
|
||||
private function giveUniqueItem(AuctionBidItem $highestBid, General $bidder): ?string
|
||||
protected function rollbackAuction(): void
|
||||
{
|
||||
|
||||
$itemKey = $this->info->target;
|
||||
if ($itemKey === null) {
|
||||
throw new \Exception('아이템 키가 없습니다.');
|
||||
}
|
||||
$itemObj = buildItemClass($itemKey);
|
||||
$general = $bidder;
|
||||
$availableItemTypes = [];
|
||||
$reasons = [];
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
[$startYear, $year] = $gameStor->getValuesAsArray(['startyear', 'year']);
|
||||
$relYear = $year - $startYear;
|
||||
$availableEquipUniqueCnt = 1;
|
||||
foreach (GameConst::$maxUniqueItemLimit as $tmpVals) {
|
||||
[$targetYear, $targetTrialCnt] = $tmpVals;
|
||||
if ($relYear < $targetYear) {
|
||||
break;
|
||||
}
|
||||
$availableEquipUniqueCnt = $targetTrialCnt;
|
||||
}
|
||||
|
||||
$availableEquipUniqueCnt = Util::valueFit($availableEquipUniqueCnt, null, count(GameConst::$allItems));
|
||||
|
||||
foreach ($general->getItems() as $item) {
|
||||
if (!$item->isBuyable()) {
|
||||
$availableEquipUniqueCnt -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($availableEquipUniqueCnt <= 0) {
|
||||
return '유니크 아이템 소유 제한 상태입니다. 종료 시간이 연장됩니다.';
|
||||
}
|
||||
|
||||
foreach (GameConst::$allItems as $itemType => $itemList) {
|
||||
//아직은 그런 경우는 없지만 동일 유니크를 여러 부위에 장착할 수 있을지도 모름
|
||||
if (!key_exists($itemKey, $itemList)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ownItem = $general->getItem($itemType);
|
||||
if ($ownItem->getRawClassName() == $itemKey) {
|
||||
//FIXME: 이 경우에는 환불이 되던가 해야함.
|
||||
$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) {
|
||||
//FIXME: 이 경우에는 환불이 되던가 해야함.
|
||||
$reasons[] = '그 유니크는 모두 점유되었습니다.';
|
||||
continue;
|
||||
}
|
||||
$availableItemTypes[] = $itemType;
|
||||
}
|
||||
|
||||
if (!$availableItemTypes) {
|
||||
return join(' ', $reasons);
|
||||
}
|
||||
|
||||
$itemType = $availableItemTypes[0];
|
||||
|
||||
$general->setVar($itemType, $itemKey);
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$nationName = $general->getStaticNation()['name'];
|
||||
$generalName = $general->getName();
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$itemName = $itemObj->getName();
|
||||
$itemRawName = $itemObj->getRawName();
|
||||
$josaUl = JosaUtil::pick($itemRawName, '을');
|
||||
|
||||
$logger->pushGeneralActionLog("<C>{$itemName}</>{$josaUl} 습득했습니다!");
|
||||
$logger->pushGeneralHistoryLog("<C>{$itemName}</>{$josaUl} 습득");
|
||||
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 습득했습니다!");
|
||||
$logger->pushGlobalHistoryLog("<C><b>【보물발견】</b></><D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 습득했습니다!");
|
||||
|
||||
$general->applyDB($db);
|
||||
|
||||
$givenUnique = $gameStor->getValue('givenUnique') ?? [];
|
||||
$givenUnique[$itemKey] = ($givenUnique[$itemKey] ?? 0) + 1;
|
||||
$gameStor->setValue('givenUnique', $givenUnique);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function checkCloseDate(): ?bool
|
||||
{
|
||||
$now = new DateTimeImmutable();
|
||||
if ($now < $this->info->closeDate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//경매를 닫아야한다.
|
||||
$highestBid = $this->getHighestBid();
|
||||
if ($highestBid === null) {
|
||||
$this->closeAuction();
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($highestBid->data->tryExtendCloseDate) {
|
||||
//연장 요청이 있었다.
|
||||
$extendedCloseDate = $this->info->closeDate->add(TimeUtil::secondsToDateInterval(
|
||||
max(static::MIN_EXTENSION_MINUTES_BY_EXTENSION_QUERY, $this->info->turnTerm * static::COEFF_EXTENSION_MINUTES_BY_EXTENSION_QUERY) * 60
|
||||
));
|
||||
|
||||
if ($this->extendCloseDate($extendedCloseDate) === null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$bidder = General::createGeneralObjFromDB($highestBid->generalID);
|
||||
|
||||
$failReason = $this->giveUniqueItem($highestBid, $bidder);
|
||||
if ($failReason === null) {
|
||||
$this->closeAuction();
|
||||
return true;
|
||||
}
|
||||
|
||||
$staticNation = $bidder->getStaticNation();
|
||||
$src = new MessageTarget(0, '', 0, 'System', '#000000');
|
||||
$dest = new MessageTarget(
|
||||
$bidder->getID(),
|
||||
$bidder->getName(),
|
||||
$bidder->getNationID(),
|
||||
$staticNation['name'],
|
||||
$staticNation['color'],
|
||||
GetImageURL($bidder->getVar('imgsvr'), $bidder->getVar('picture'))
|
||||
);
|
||||
|
||||
//TODO: 전역 알림이 나타나야한다. 일반 메시지보다는 중요하고, 메시지보단 약하게..
|
||||
//TODO: 바로가기를 제공하는 편이 좋을 것 같다.
|
||||
$msg = new Message(
|
||||
Message::MSGTYPE_PRIVATE,
|
||||
$src,
|
||||
$dest,
|
||||
$failReason,
|
||||
new \DateTime(),
|
||||
new \DateTime('9999-12-31'),
|
||||
[]
|
||||
);
|
||||
$msg->send(true);
|
||||
|
||||
//아이템 제한에 걸렸다면 자동 연장
|
||||
$extendedCloseDate = $this->info->closeDate->add(TimeUtil::secondsToDateInterval(
|
||||
max(static::MIN_EXTENSION_MINUTES_BY_EXTENSION_QUERY, $this->info->turnTerm * static::COEFF_EXTENSION_MINUTES_BY_EXTENSION_QUERY) * 60
|
||||
));
|
||||
|
||||
$this->extendCloseDate($extendedCloseDate, true);
|
||||
return false;
|
||||
// 유니크 옥션의 개최자는 운영자이므로 할 일이 없다.
|
||||
}
|
||||
|
||||
public function bid(int $amount, bool $tryExtendCloseDate = false): ?string
|
||||
@@ -349,6 +203,104 @@ class AuctionUniqueItem extends Auction
|
||||
}
|
||||
}
|
||||
|
||||
return parent::bid($amount, $tryExtendCloseDate);
|
||||
return $this->_bid($amount, $tryExtendCloseDate);
|
||||
}
|
||||
|
||||
protected function finishAuction(AuctionBidItem $highestBid, General $bidder): ?string
|
||||
{
|
||||
$itemKey = $this->info->target;
|
||||
if ($itemKey === null) {
|
||||
throw new \Exception('아이템 키가 없습니다.');
|
||||
}
|
||||
$itemObj = buildItemClass($itemKey);
|
||||
$general = $bidder;
|
||||
$availableItemTypes = [];
|
||||
$reasons = [];
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
[$startYear, $year] = $gameStor->getValuesAsArray(['startyear', 'year']);
|
||||
$relYear = $year - $startYear;
|
||||
$availableEquipUniqueCnt = 1;
|
||||
foreach (GameConst::$maxUniqueItemLimit as $tmpVals) {
|
||||
[$targetYear, $targetTrialCnt] = $tmpVals;
|
||||
if ($relYear < $targetYear) {
|
||||
break;
|
||||
}
|
||||
$availableEquipUniqueCnt = $targetTrialCnt;
|
||||
}
|
||||
|
||||
$availableEquipUniqueCnt = Util::valueFit($availableEquipUniqueCnt, null, count(GameConst::$allItems));
|
||||
|
||||
foreach ($general->getItems() as $item) {
|
||||
if (!$item->isBuyable()) {
|
||||
$availableEquipUniqueCnt -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($availableEquipUniqueCnt <= 0) {
|
||||
//제한에 걸렸다면 자동 연장
|
||||
$extendedCloseDate = $this->info->closeDate->add(TimeUtil::secondsToDateInterval(
|
||||
max(static::MIN_EXTENSION_MINUTES_BY_EXTENSION_QUERY, $this->info->turnTerm * static::COEFF_EXTENSION_MINUTES_BY_EXTENSION_QUERY) * 60
|
||||
));
|
||||
|
||||
$this->extendCloseDate($extendedCloseDate, true);
|
||||
return '유니크 아이템 소유 제한 상태입니다. 종료 시간이 연장됩니다.';
|
||||
}
|
||||
|
||||
foreach (GameConst::$allItems as $itemType => $itemList) {
|
||||
//아직은 그런 경우는 없지만 동일 유니크를 여러 부위에 장착할 수 있을지도 모름
|
||||
if (!key_exists($itemKey, $itemList)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ownItem = $general->getItem($itemType);
|
||||
if ($ownItem->getRawClassName() == $itemKey) {
|
||||
//FIXME: 이 경우에는 환불이 되던가 해야함.
|
||||
$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) {
|
||||
//FIXME: 이 경우에는 환불이 되던가 해야함.
|
||||
$reasons[] = '그 유니크는 모두 점유되었습니다.';
|
||||
continue;
|
||||
}
|
||||
$availableItemTypes[] = $itemType;
|
||||
}
|
||||
|
||||
if (!$availableItemTypes) {
|
||||
return join(' ', $reasons);
|
||||
}
|
||||
|
||||
$itemType = $availableItemTypes[0];
|
||||
|
||||
$general->setVar($itemType, $itemKey);
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$nationName = $general->getStaticNation()['name'];
|
||||
$generalName = $general->getName();
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$itemName = $itemObj->getName();
|
||||
$itemRawName = $itemObj->getRawName();
|
||||
$josaUl = JosaUtil::pick($itemRawName, '을');
|
||||
|
||||
$logger->pushGeneralActionLog("<C>{$itemName}</>{$josaUl} 습득했습니다!");
|
||||
$logger->pushGeneralHistoryLog("<C>{$itemName}</>{$josaUl} 습득");
|
||||
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 습득했습니다!");
|
||||
$logger->pushGlobalHistoryLog("<C><b>【보물발견】</b></><D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 습득했습니다!");
|
||||
|
||||
$general->applyDB($db);
|
||||
|
||||
$givenUnique = $gameStor->getValue('givenUnique') ?? [];
|
||||
$givenUnique[$itemKey] = ($givenUnique[$itemKey] ?? 0) + 1;
|
||||
$gameStor->setValue('givenUnique', $givenUnique);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user