Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4f110dbd5 | ||
|
|
cde6d86e1b | ||
|
|
1492666d3a | ||
|
|
de2ee02b3b | ||
|
|
4f65f6870b | ||
|
|
7801e5fd81 | ||
|
|
b7c7d6ffce | ||
|
|
d5b2d4e1f2 | ||
|
|
d1e5c2105e | ||
|
|
acd73fc63e | ||
|
|
76ea61f751 | ||
|
|
8dc5231118 | ||
|
|
45fa74573a |
+2
-5
@@ -13,9 +13,6 @@ $db = DB::db();
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
|
||||||
[$turntime, $tnmt_time] = $gameStor->getValuesAsArray(['turntime','tnmt_time']);
|
[$turntime, $tnmt_time] = $gameStor->getValuesAsArray(['turntime','tnmt_time']);
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
$turntimeDisplay = $clock->formatTick(Util::toInt($turntime), true);
|
|
||||||
$tnmtTimeDisplay = $tnmt_time === null ? '-' : $clock->formatTick(Util::toInt($tnmt_time), true);
|
|
||||||
|
|
||||||
$plock = $db->queryFirstField('SELECT plock FROM plock WHERE `type` ="GAME"');
|
$plock = $db->queryFirstField('SELECT plock FROM plock WHERE `type` ="GAME"');
|
||||||
?>
|
?>
|
||||||
@@ -33,8 +30,8 @@ $plock = $db->queryFirstField('SELECT plock FROM plock WHERE `type` ="GAME"');
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<form action=_119_b.php method=post>
|
<form action=_119_b.php method=post>
|
||||||
시간조정 : <input type=text size=3 name=minute><input type=submit name=btn value='분당김'><input type=submit name=btn value='분지연'> 최종갱신 : <?=$turntimeDisplay?> (tick <?=$turntime?>)<br>
|
시간조정 : <input type=text size=3 name=minute><input type=submit name=btn value='분당김'><input type=submit name=btn value='분지연'> 최종갱신 : <?=$turntime?><br>
|
||||||
시간조정 : <input type=text size=3 name=minute2><input type=submit name=btn value='토너분당김'><input type=submit name=btn value='토너분지연'> 토너먼트 : <?=$tnmtTimeDisplay?> (tick <?=$tnmt_time?>)<br>
|
시간조정 : <input type=text size=3 name=minute2><input type=submit name=btn value='토너분당김'><input type=submit name=btn value='토너분지연'> 토너먼트 : <?=$tnmt_time?><br>
|
||||||
봉급지급 : <input type=submit name=btn value='금지급'><input type=submit name=btn value='쌀지급'><br>
|
봉급지급 : <input type=submit name=btn value='금지급'><input type=submit name=btn value='쌀지급'><br>
|
||||||
락 풀 기 : <input type=submit name=btn value='락걸기'><input type=submit name=btn value='락풀기'> 현재 : <?=$plock>0?"동결중":"가동중"?><br>
|
락 풀 기 : <input type=submit name=btn value='락걸기'><input type=submit name=btn value='락풀기'> 현재 : <?=$plock>0?"동결중":"가동중"?><br>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
+36
-9
@@ -38,9 +38,21 @@ switch ($btn) {
|
|||||||
usleep(500000);
|
usleep(500000);
|
||||||
}
|
}
|
||||||
|
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$gameStor->cacheValues(['turntime', 'starttime', 'tnmt_time']);
|
||||||
// 스케줄 전체를 벽시계에서 빼지 않고 논리 현재 tick만 앞으로 이동합니다.
|
$turntime = (new \DateTimeImmutable($gameStor->turntime))->sub(new \DateInterval("PT{$minute}M"));
|
||||||
$clock->advance($gameStor, $clock->ticksFromMinutes($minute));
|
$starttime = (new \DateTimeImmutable($gameStor->starttime))->sub(new \DateInterval("PT{$minute}M"));
|
||||||
|
$tnmt_time = (new \DateTimeImmutable($gameStor->tnmt_time))->sub(new \DateInterval("PT{$minute}M"));
|
||||||
|
|
||||||
|
$gameStor->turntime = $turntime->format('Y-m-d H:i:s.u');
|
||||||
|
$gameStor->starttime = $starttime->format('Y-m-d H:i:s');
|
||||||
|
$gameStor->tnmt_time = $tnmt_time->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
|
$db->update('general', [
|
||||||
|
'turntime' => $db->sqleval('DATE_SUB(turntime, INTERVAL %i MINUTE)', $minute)
|
||||||
|
], true);
|
||||||
|
$db->update('ng_auction', [
|
||||||
|
'close_date' => $db->sqleval('DATE_SUB(close_date, INTERVAL %i MINUTE)', $minute)
|
||||||
|
], 'finished = 0');
|
||||||
if ($locked) {
|
if ($locked) {
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
@@ -54,19 +66,34 @@ switch ($btn) {
|
|||||||
}
|
}
|
||||||
usleep(500000);
|
usleep(500000);
|
||||||
}
|
}
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$gameStor->cacheValues(['turntime', 'starttime', 'tnmt_time']);
|
||||||
$clock->advance($gameStor, -$clock->ticksFromMinutes($minute));
|
$turntime = (new \DateTimeImmutable($gameStor->turntime))->add(new \DateInterval("PT{$minute}M"));
|
||||||
|
$starttime = (new \DateTimeImmutable($gameStor->starttime))->add(new \DateInterval("PT{$minute}M"));
|
||||||
|
$tnmt_time = (new \DateTimeImmutable($gameStor->tnmt_time))->add(new \DateInterval("PT{$minute}M"));
|
||||||
|
|
||||||
|
$gameStor->turntime = $turntime->format('Y-m-d H:i:s.u');
|
||||||
|
$gameStor->starttime = $starttime->format('Y-m-d H:i:s');
|
||||||
|
$gameStor->tnmt_time = $tnmt_time->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
|
$db->update('general', [
|
||||||
|
'turntime' => $db->sqleval('DATE_ADD(turntime, INTERVAL %i MINUTE)', $minute)
|
||||||
|
], true);
|
||||||
|
$db->update('ng_auction', [
|
||||||
|
'close_date' => $db->sqleval('DATE_ADD(close_date, INTERVAL %i MINUTE)', $minute)
|
||||||
|
], 'finished = 0');
|
||||||
if ($locked) {
|
if ($locked) {
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "토너분당김":
|
case "토너분당김":
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$tnmt_time = new \DateTime($gameStor->tnmt_time);
|
||||||
$gameStor->tnmt_time = Util::toInt($gameStor->tnmt_time) - $clock->ticksFromMinutes($minute2);
|
$tnmt_time->sub(new \DateInterval("PT{$minute2}M"));
|
||||||
|
$gameStor->tnmt_time = $tnmt_time->format('Y-m-d H:i:s');
|
||||||
break;
|
break;
|
||||||
case "토너분지연":
|
case "토너분지연":
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$tnmt_time = new \DateTimeImmutable($gameStor->tnmt_time);
|
||||||
$gameStor->tnmt_time = Util::toInt($gameStor->tnmt_time) + $clock->ticksFromMinutes($minute2);
|
$tnmt_time->add(new \DateInterval("PT{$minute2}M"));
|
||||||
|
$gameStor->tnmt_time = $tnmt_time->format('Y-m-d H:i:s');
|
||||||
break;
|
break;
|
||||||
case "금지급":
|
case "금지급":
|
||||||
processGoldIncome();
|
processGoldIncome();
|
||||||
|
|||||||
+2
-2
@@ -40,7 +40,7 @@ $admin = getAdmin();
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width=110 align=right>시작시간변경</td>
|
<td width=110 align=right>시작시간변경</td>
|
||||||
<td width=285><input type=text size=20 maxlength=20 style=color:white;background-color:black;text-align:right; name=starttime value='<?=substr($admin['starttime_display'], 0, 19)?>'><input type=submit name=btn value=변경1></td>
|
<td width=285><input type=text size=20 maxlength=20 style=color:white;background-color:black;text-align:right; name=starttime value='<?=substr($admin['starttime'], 0, 19)?>'><input type=submit name=btn value=변경1></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width=110 align=right>최대 장수</td>
|
<td width=110 align=right>최대 장수</td>
|
||||||
@@ -52,7 +52,7 @@ $admin = getAdmin();
|
|||||||
<td width=110 align=right>시작 년도</td>
|
<td width=110 align=right>시작 년도</td>
|
||||||
<td width=285><input type=text size=3 maxlength=3 style=color:white;background-color:black;text-align:right; name=startyear value='<?=$admin['startyear']?>'><input type=submit name=btn value=변경4></td>
|
<td width=285><input type=text size=3 maxlength=3 style=color:white;background-color:black;text-align:right; name=startyear value='<?=$admin['startyear']?>'><input type=submit name=btn value=변경4></td>
|
||||||
<td width=110 align=right>최근 갱신 시간</td>
|
<td width=110 align=right>최근 갱신 시간</td>
|
||||||
<td width=285> <?=$admin['turntime_display']?> (tick <?=$admin['turntime']?>)</td>
|
<td width=285> <?=$admin['turntime']?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width=110 align=right>턴시간</td>
|
<td width=110 align=right>턴시간</td>
|
||||||
|
|||||||
@@ -43,12 +43,7 @@ switch ($btn) {
|
|||||||
pushGlobalHistoryLog(["<R>★</><S>{$log}</>"]);
|
pushGlobalHistoryLog(["<R>★</><S>{$log}</>"]);
|
||||||
break;
|
break;
|
||||||
case "변경1":
|
case "변경1":
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$gameStor->starttime = (new \DateTime($starttime))->format('Y-m-d H:i:s');
|
||||||
$gameStor->clock_base_time = TimeUtil::format(GameClock::baseTimeForProjection(
|
|
||||||
new \DateTimeImmutable($starttime),
|
|
||||||
Util::toInt($gameStor->starttime),
|
|
||||||
$clock->getTurnTermMinutes(),
|
|
||||||
), true);
|
|
||||||
break;
|
break;
|
||||||
case "변경2":
|
case "변경2":
|
||||||
$gameStor->maxgeneral = $maxgeneral;
|
$gameStor->maxgeneral = $maxgeneral;
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ switch ($btn) {
|
|||||||
], '`no` IN %li', $genlist);
|
], '`no` IN %li', $genlist);
|
||||||
break;
|
break;
|
||||||
case "강제 사망":
|
case "강제 사망":
|
||||||
$date = GameClock::fromStorage($gameStor)->nowTick();
|
$date = TimeUtil::now(true);
|
||||||
$db->update('general', [
|
$db->update('general', [
|
||||||
'killturn' => 0,
|
'killturn' => 0,
|
||||||
'turntime' => $date,
|
'turntime' => $date,
|
||||||
|
|||||||
+1
-2
@@ -42,7 +42,6 @@ if ($session->userGrade < 6) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
|
||||||
|
|
||||||
if ($btn == '정렬하기') {
|
if ($btn == '정렬하기') {
|
||||||
$gen = 0;
|
$gen = 0;
|
||||||
@@ -112,7 +111,7 @@ $generalObj = General::createObjFromDB($gen, null, GeneralQueryMode::FullWithAcc
|
|||||||
대상장수 :
|
대상장수 :
|
||||||
<select name=gen size=1>
|
<select name=gen size=1>
|
||||||
<?php foreach ($generalBasicList as $general) : ?>
|
<?php foreach ($generalBasicList as $general) : ?>
|
||||||
<option <?= $gen == $general['no'] ? 'selected' : '' ?> value='<?= $general['no'] ?>'><?= $general['name'] ?> (<?= substr($clock->formatTick(Util::toInt($general['turntime'])), 14, 5) ?>)</option>
|
<option <?= $gen == $general['no'] ? 'selected' : '' ?> value='<?= $general['no'] ?>'><?= $general['name'] ?> (<?= substr($general['turntime'], 14, 5) ?>)</option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
<input type=submit name=btn value='조회하기'>
|
<input type=submit name=btn value='조회하기'>
|
||||||
|
|||||||
@@ -243,14 +243,11 @@ $templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
|||||||
"SELECT nation,no,name,owner_name as ownerName, owner, picture, imgsvr,
|
"SELECT nation,no,name,owner_name as ownerName, owner, picture, imgsvr,
|
||||||
experience, dedication,
|
experience, dedication,
|
||||||
dex1, dex2, dex3, dex4, dex5,
|
dex1, dex2, dex3, dex4, dex5,
|
||||||
horse, weapon, book, item, aux
|
horse, weapon, book, item
|
||||||
FROM general WHERE %l",
|
FROM general WHERE %l",
|
||||||
$btn == "NPC 보기" ? "npc>=2" : "npc<2"
|
$btn == "NPC 보기" ? "npc>=2" : "npc<2"
|
||||||
) as $general) {
|
) as $general) {
|
||||||
$generalID = $general['no'];
|
$generalID = $general['no'];
|
||||||
foreach (['dex1', 'dex2', 'dex3', 'dex4', 'dex5'] as $dexKey) {
|
|
||||||
$general[$dexKey] = CentennialAllStarGrowthService::recordableRawValue($general, $dexKey);
|
|
||||||
}
|
|
||||||
$general['bgColor'] = $nationColor[$general['nation']] ?? GameConst::$basecolor4;
|
$general['bgColor'] = $nationColor[$general['nation']] ?? GameConst::$basecolor4;
|
||||||
$general['fgColor'] = newColor($general['bgColor']);
|
$general['fgColor'] = newColor($general['bgColor']);
|
||||||
$general['nationName'] = $nationName[$general['nation']];
|
$general['nationName'] = $nationName[$general['nation']];
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ $db = DB::db();
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
increaseRefresh("현재도시", 1);
|
increaseRefresh("현재도시", 1);
|
||||||
|
|
||||||
$lastExecute = substr(GameClock::fromStorage($gameStor)->formatTick(Util::toInt($gameStor->turntime)), 5, 14);
|
$lastExecute = substr($gameStor->turntime, 5, 14);
|
||||||
|
|
||||||
$me = $db->queryFirstRow('SELECT no,nation,officer_level,city from general where owner=%i', $userID);
|
$me = $db->queryFirstRow('SELECT no,nation,officer_level,city from general where owner=%i', $userID);
|
||||||
$myNation = $db->queryFirstRow('SELECT nation,level,spy FROM nation WHERE nation=%i', $me['nation']) ?? [
|
$myNation = $db->queryFirstRow('SELECT nation,level,spy FROM nation WHERE nation=%i', $me['nation']) ?? [
|
||||||
|
|||||||
@@ -129,7 +129,6 @@ $templates = new \League\Plates\Engine('templates');
|
|||||||
);
|
);
|
||||||
|
|
||||||
$generalTurnList = [];
|
$generalTurnList = [];
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
|
|
||||||
foreach ($db->queryAllLists(
|
foreach ($db->queryAllLists(
|
||||||
'SELECT general_id, turn_idx, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id ASC, turn_idx ASC',
|
'SELECT general_id, turn_idx, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id ASC, turn_idx ASC',
|
||||||
@@ -143,7 +142,6 @@ $templates = new \League\Plates\Engine('templates');
|
|||||||
|
|
||||||
$genCntEff = 0;
|
$genCntEff = 0;
|
||||||
foreach ($generals as &$general) {
|
foreach ($generals as &$general) {
|
||||||
$general['turntime'] = $clock->formatTick(Util::toInt($general['turntime']), true);
|
|
||||||
$general['cityText'] = CityConst::byID($general['city'])->name;
|
$general['cityText'] = CityConst::byID($general['city'])->name;
|
||||||
$general['troopText'] = $troopName[$general['troop']] ?? '-';
|
$general['troopText'] = $troopName[$general['troop']] ?? '-';
|
||||||
|
|
||||||
|
|||||||
+6
-24
@@ -21,8 +21,8 @@ $generalID = $session->generalID;
|
|||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$gameStor->cacheValues(['turntime', 'opentime', 'autorun_user', 'npcmode']);
|
$gameStor->cacheValues(['turntime', 'opentime', 'autorun_user', 'npcmode']);
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
$nowTick = $clock->nowTick();
|
increaseRefresh("내정보", 1);
|
||||||
|
|
||||||
$me = General::createObjFromDB($generalID, null, GeneralQueryMode::FullWithAccessLog);
|
$me = General::createObjFromDB($generalID, null, GeneralQueryMode::FullWithAccessLog);
|
||||||
|
|
||||||
@@ -41,30 +41,12 @@ $lastRefresh = $db->queryFirstField(
|
|||||||
$generalID
|
$generalID
|
||||||
);
|
);
|
||||||
|
|
||||||
$nextChange = $me->getAuxVar('next_change');
|
$targetTime = addTurn($lastRefresh, $gameStor->turnterm, GameConst::$minTurnDieOnPrestart);
|
||||||
if (!is_int($nextChange)) {
|
|
||||||
$nextChange = null;
|
|
||||||
}
|
|
||||||
$nextChangeDisplay = $nextChange === null ? null : $clock->formatTick($nextChange);
|
|
||||||
|
|
||||||
increaseRefresh("내정보", 1);
|
|
||||||
if ($gameStor->turntime <= $gameStor->opentime) {
|
if ($gameStor->turntime <= $gameStor->opentime) {
|
||||||
$targetTime = $me->getAuxVar('prestart_delete_after');
|
|
||||||
if (!is_int($targetTime)) {
|
|
||||||
$targetTime = addTurn(
|
|
||||||
$lastRefresh === null ? $nowTick : Util::toInt($lastRefresh),
|
|
||||||
$gameStor->turnterm,
|
|
||||||
GameConst::$minTurnDieOnPrestart
|
|
||||||
);
|
|
||||||
$me->setAuxVar('prestart_delete_after', $targetTime);
|
|
||||||
$me->applyDB($db);
|
|
||||||
}
|
|
||||||
$targetTimeDisplay = $clock->formatTick($targetTime);
|
|
||||||
|
|
||||||
//서버 가오픈시 할 수 있는 행동
|
//서버 가오픈시 할 수 있는 행동
|
||||||
if ($me->getNPCType() == 0 && $me->getNationID() == 0) {
|
if ($me->getNPCType() == 0 && $me->getNationID() == 0) {
|
||||||
$showDieOnPrestartBtn = true;
|
$showDieOnPrestartBtn = true;
|
||||||
if ($targetTime <= $nowTick) {
|
if ($targetTime <= TimeUtil::now()) {
|
||||||
$availableDieOnPrestart = true;
|
$availableDieOnPrestart = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,7 +159,7 @@ $changeDefence999Atmos = $me->onCalcDomestic('changeDefenceTrain', "atmos999", $
|
|||||||
<a href="b_myPage.php?detachNPC=1"><button type="button" style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>빙의 해체 요청</button></a>-->
|
<a href="b_myPage.php?detachNPC=1"><button type="button" style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>빙의 해체 요청</button></a>-->
|
||||||
|
|
||||||
<?php if ($showDieOnPrestartBtn) : ?>
|
<?php if ($showDieOnPrestartBtn) : ?>
|
||||||
가오픈 기간 내 장수 삭제 (<?= $targetTimeDisplay ?> 부터)<br>
|
가오픈 기간 내 장수 삭제 (<?= substr($targetTime, 0, 19) ?> 부터)<br>
|
||||||
<button type="button" id='dieOnPrestart' style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>장수 삭제</button><br><br>
|
<button type="button" id='dieOnPrestart' style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>장수 삭제</button><br><br>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
@@ -192,7 +174,7 @@ $changeDefence999Atmos = $me->onCalcDomestic('changeDefenceTrain', "atmos999", $
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if ($gameStor->npcmode == 2 && $me->getNPCType() == 0) : ?>
|
<?php if ($gameStor->npcmode == 2 && $me->getNPCType() == 0) : ?>
|
||||||
다른 장수 선택 (<?= $nextChangeDisplay ?? '지금' ?>부터)<br>
|
다른 장수 선택 (<?= substr($me->getAuxVar('next_change') ?? TimeUtil::now(), 0, 19) ?> 부터)<br>
|
||||||
<a href="select_general_from_pool.php" id='select_general_from_pool'><button type="button" style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>다른 장수 선택</button></a><br><br>
|
<a href="select_general_from_pool.php" id='select_general_from_pool'><button type="button" style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>다른 장수 선택</button></a><br><br>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|||||||
@@ -228,10 +228,10 @@ if($btn == "자동개최설정") {
|
|||||||
$phase = 0;
|
$phase = 0;
|
||||||
startBetting($admin['tnmt_type'], 720);
|
startBetting($admin['tnmt_type'], 720);
|
||||||
} elseif($btn == "베팅마감") {
|
} elseif($btn == "베팅마감") {
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$dt = date("Y-m-d H:i:s", time() + 60);
|
||||||
$gameStor->tournament=7;
|
$gameStor->tournament=7;
|
||||||
$gameStor->phase=0;
|
$gameStor->phase=0;
|
||||||
$gameStor->tnmt_time = $clock->nowTick() + $clock->ticksFromSeconds(60);
|
$gameStor->tnmt_time = $dt;
|
||||||
} elseif($btn == "16강") {
|
} elseif($btn == "16강") {
|
||||||
finalFight($admin['tnmt_type'], $admin['tournament'], $admin['phase'], 16);
|
finalFight($admin['tnmt_type'], $admin['tournament'], $admin['phase'], 16);
|
||||||
} elseif($btn == "8강") {
|
} elseif($btn == "8강") {
|
||||||
|
|||||||
@@ -51,22 +51,6 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.picture_choice {
|
|
||||||
margin: 8px auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.picture_choice label,
|
|
||||||
.event_picture label {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
margin: 4px 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.picture_choice img {
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom_picture {
|
.custom_picture {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
+124
-75
@@ -630,11 +630,7 @@ function generalInfo(General $generalObj)
|
|||||||
$injury = "건강";
|
$injury = "건강";
|
||||||
}
|
}
|
||||||
|
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage(DB::db(), 'game_env'));
|
$remaining = (new \DateTimeImmutable($generalObj->getTurnTime()))->diff(new \DateTimeImmutable())->i;
|
||||||
$remaining = max(0, intdiv(
|
|
||||||
$generalObj->getTurnTick() - $clock->nowTick(),
|
|
||||||
$clock->ticksFromMinutes(1),
|
|
||||||
));
|
|
||||||
|
|
||||||
if ($nation['color'] == "") {
|
if ($nation['color'] == "") {
|
||||||
$nation['color'] = "#000000";
|
$nation['color'] = "#000000";
|
||||||
@@ -925,40 +921,72 @@ function banner()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTurn(int $tick, int $turnterm, int $turn = 1, bool $withFraction = true): int
|
function addTurn($date, int $turnterm, int $turn = 1, bool $withFraction = true)
|
||||||
{
|
{
|
||||||
return $tick + GameClock::TICKS_PER_TURN * $turn;
|
if($turnterm < 0){
|
||||||
}
|
if($turnterm == -60){
|
||||||
|
return VarTurn60::fromDatetime(new \DateTimeImmutable(($date)))->addTurn($turn )->toDateStr($withFraction);
|
||||||
function subTurn(int $tick, int $turnterm, int $turn = 1, bool $withFraction = true): int
|
}
|
||||||
{
|
throw new \Exception("InvalidTurnTerm".$turnterm);
|
||||||
return $tick - GameClock::TICKS_PER_TURN * $turn;
|
|
||||||
}
|
|
||||||
|
|
||||||
function cutTurn(int $tick, int $turnterm, bool $withFraction = true): int
|
|
||||||
{
|
|
||||||
$remainder = $tick % GameClock::TICKS_PER_TURN;
|
|
||||||
if ($remainder < 0) {
|
|
||||||
$remainder += GameClock::TICKS_PER_TURN;
|
|
||||||
}
|
}
|
||||||
return $tick - $remainder;
|
|
||||||
|
$date = new \DateTime($date);
|
||||||
|
$target = $turnterm * $turn;
|
||||||
|
$date->add(new \DateInterval("PT{$target}M"));
|
||||||
|
if ($withFraction) {
|
||||||
|
return $date->format('Y-m-d H:i:s.u');
|
||||||
|
}
|
||||||
|
return $date->format('Y-m-d H:i:s');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 시나리오 초기화 입력인 벽시계를 기존 01:00 기준 월 경계로 정렬합니다. */
|
function subTurn($date, int $turnterm, int $turn = 1, bool $withFraction = true)
|
||||||
function cutTurnDateTime(string $date, int $turnterm, bool $withFraction = true): string
|
|
||||||
{
|
{
|
||||||
$dateObj = new \DateTime($date);
|
if($turnterm < 0){
|
||||||
$baseDate = new \DateTime($dateObj->format('Y-m-d'));
|
if($turnterm == -60){
|
||||||
$baseDate->sub(new \DateInterval('P1D'));
|
return VarTurn60::fromDatetime(new \DateTimeImmutable(($date)))->addTurn($turn * -1)->toDateStr($withFraction);
|
||||||
$baseDate->add(new \DateInterval('PT1H'));
|
}
|
||||||
$diffMin = intdiv($dateObj->getTimestamp() - $baseDate->getTimestamp(), 60);
|
throw new \Exception("InvalidTurnTerm".$turnterm);
|
||||||
|
}
|
||||||
|
|
||||||
|
$date = new \DateTime($date);
|
||||||
|
$target = $turnterm * $turn;
|
||||||
|
$date->sub(new \DateInterval("PT{$target}M"));
|
||||||
|
if ($withFraction) {
|
||||||
|
return $date->format('Y-m-d H:i:s.u');
|
||||||
|
}
|
||||||
|
return $date->format('Y-m-d H:i:s');
|
||||||
|
}
|
||||||
|
|
||||||
|
function cutTurn($date, int $turnterm, bool $withFraction = true)
|
||||||
|
{
|
||||||
|
if($turnterm < 0){
|
||||||
|
if($turnterm == -60){
|
||||||
|
[$baseDate, ] = VarTurn60::fromDatetime(new \DateTimeImmutable(($date)))->cutTurn($withFraction);
|
||||||
|
return $baseDate;
|
||||||
|
}
|
||||||
|
throw new \Exception("InvalidTurnTerm".$turnterm);
|
||||||
|
}
|
||||||
|
|
||||||
|
$date = new \DateTime($date);
|
||||||
|
|
||||||
|
$baseDate = new \DateTime($date->format('Y-m-d'));
|
||||||
|
$baseDate->sub(new \DateInterval("P1D"));
|
||||||
|
$baseDate->add(new \DateInterval("PT1H"));
|
||||||
|
|
||||||
|
$diffMin = intdiv($date->getTimeStamp() - $baseDate->getTimeStamp(), 60);
|
||||||
$diffMin -= $diffMin % $turnterm;
|
$diffMin -= $diffMin % $turnterm;
|
||||||
|
|
||||||
$baseDate->add(new \DateInterval("PT{$diffMin}M"));
|
$baseDate->add(new \DateInterval("PT{$diffMin}M"));
|
||||||
return $baseDate->format($withFraction ? 'Y-m-d H:i:s.u' : 'Y-m-d H:i:s');
|
if ($withFraction) {
|
||||||
|
return $baseDate->format('Y-m-d H:i:s.u');
|
||||||
|
}
|
||||||
|
return $baseDate->format('Y-m-d H:i:s');
|
||||||
}
|
}
|
||||||
|
|
||||||
function cutDay($date, int $turnterm, bool $withFraction = true)
|
function cutDay($date, int $turnterm, bool $withFraction = true)
|
||||||
{
|
{
|
||||||
|
assert($turnterm > 0);
|
||||||
|
|
||||||
$date = new \DateTime($date);
|
$date = new \DateTime($date);
|
||||||
|
|
||||||
$baseDate = new \DateTime($date->format('Y-m-d'));
|
$baseDate = new \DateTime($date->format('Y-m-d'));
|
||||||
@@ -997,9 +1025,11 @@ function increaseRefresh($type = "", $cnt = 1)
|
|||||||
$generalID = $session->generalID;
|
$generalID = $session->generalID;
|
||||||
$userGrade = $session->userGrade;
|
$userGrade = $session->userGrade;
|
||||||
|
|
||||||
|
$dateObj = new \DateTimeImmutable();
|
||||||
|
$date = TimeUtil::format($dateObj, false);
|
||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$date = GameClock::fromStorage($gameStor)->nowTick();
|
|
||||||
$isunited = $gameStor->isunited;
|
$isunited = $gameStor->isunited;
|
||||||
$opentime = $gameStor->opentime;
|
$opentime = $gameStor->opentime;
|
||||||
|
|
||||||
@@ -1041,7 +1071,7 @@ function increaseRefresh($type = "", $cnt = 1)
|
|||||||
|
|
||||||
$logDB = FileDB::db($logPath, $serverPath . '/../f_install/sql/api_log.sql');
|
$logDB = FileDB::db($logPath, $serverPath . '/../f_install/sql/api_log.sql');
|
||||||
|
|
||||||
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? 'local';
|
$ip = $_SERVER['REMOTE_ADDR'] ?? 'local';
|
||||||
$date = date('Y-m-d H:i:s');
|
$date = date('Y-m-d H:i:s');
|
||||||
|
|
||||||
$logDB->insert('api_log', [
|
$logDB->insert('api_log', [
|
||||||
@@ -1100,6 +1130,7 @@ function CheckOverhead()
|
|||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
[$turnterm, $refreshLimit] = $gameStor->getValuesAsArray(['turnterm', 'refreshLimit']);
|
[$turnterm, $refreshLimit] = $gameStor->getValuesAsArray(['turnterm', 'refreshLimit']);
|
||||||
|
$turnterm = abs($turnterm);
|
||||||
|
|
||||||
$nextRefreshLimit = Util::round(pow($turnterm, 0.6) * 3) * GameConst::$refreshLimitCoef;
|
$nextRefreshLimit = Util::round(pow($turnterm, 0.6) * 3) * GameConst::$refreshLimitCoef;
|
||||||
|
|
||||||
@@ -1145,13 +1176,12 @@ function timeover(): bool
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
|
||||||
list($turnterm, $turntime) = $gameStor->getValuesAsArray(['turnterm', 'turntime']);
|
list($turnterm, $turntime) = $gameStor->getValuesAsArray(['turnterm', 'turntime']);
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$diff = (new \DateTime())->getTimestamp() - (new \DateTime($turntime))->getTimestamp();
|
||||||
$diff = $clock->nowTick() - Util::toInt($turntime);
|
|
||||||
|
|
||||||
$t = min($turnterm, 5);
|
$t = min(abs($turnterm), 5);
|
||||||
|
|
||||||
$term = $clock->ticksFromSeconds($t);
|
$term = $diff;
|
||||||
if ($diff >= $term || $diff < 0) {
|
if ($term >= $t || $term < 0) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -1164,11 +1194,18 @@ function checkDelay()
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
|
||||||
//서버정보
|
//서버정보
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$now = new \DateTimeImmutable();
|
||||||
$timeMinDiff = intdiv($clock->nowTick() - Util::toInt($gameStor->turntime), $clock->ticksFromMinutes(1));
|
$turntime = new \DateTimeImmutable($gameStor->turntime);
|
||||||
|
$timeMinDiff = intdiv($now->getTimestamp() - $turntime->getTimestamp(), 60);
|
||||||
|
|
||||||
// 1턴이상 갱신 없었으면 서버 지연
|
// 1턴이상 갱신 없었으면 서버 지연
|
||||||
$term = $gameStor->turnterm;
|
$term = $gameStor->turnterm;
|
||||||
|
|
||||||
|
if($term < 0){
|
||||||
|
//가변 턴에는 수행 안함!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ($term >= 20) {
|
if ($term >= 20) {
|
||||||
$threshold = 1;
|
$threshold = 1;
|
||||||
} else if ($term >= 10) {
|
} else if ($term >= 10) {
|
||||||
@@ -1180,15 +1217,18 @@ function checkDelay()
|
|||||||
$iter = intdiv($timeMinDiff, $term);
|
$iter = intdiv($timeMinDiff, $term);
|
||||||
if ($iter > $threshold) {
|
if ($iter > $threshold) {
|
||||||
$minute = $iter * $term;
|
$minute = $iter * $term;
|
||||||
$delayTick = $clock->ticksFromMinutes($minute);
|
$newTurntime = $turntime->add(new \DateInterval("PT{$minute}M"));
|
||||||
$gameStor->turntime = Util::toInt($gameStor->turntime) + $delayTick;
|
$newNextTurntime = $turntime->add(new \DateInterval("PT{$term}M"));
|
||||||
$gameStor->starttime = Util::toInt($gameStor->starttime) + $delayTick;
|
$gameStor->turntime = $newTurntime->format('Y-m-d H:i:s');
|
||||||
|
$gameStor->starttime = (new \DateTimeImmutable($gameStor->starttime))
|
||||||
|
->add(new \DateInterval("PT{$minute}M"))
|
||||||
|
->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
$db->update('general', [
|
$db->update('general', [
|
||||||
'turntime' => $db->sqleval('turntime + %i', $delayTick)
|
'turntime' => $db->sqleval('DATE_ADD(turntime, INTERVAL %i MINUTE)', $minute)
|
||||||
], true);
|
], 'turntime<=DATE_ADD(turntime, INTERVAL %i MINUTE)', $term);
|
||||||
$db->update('ng_auction', [
|
$db->update('ng_auction', [
|
||||||
'close_tick' => $db->sqleval('close_tick + %i', $delayTick)
|
'close_date' => $db->sqleval('DATE_ADD(close_date, INTERVAL %i MINUTE)', $minute)
|
||||||
], 'finished = 0');
|
], 'finished = 0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1245,8 +1285,14 @@ function turnDate($curtime)
|
|||||||
$admin = $gameStor->getValues(['startyear', 'starttime', 'turnterm', 'year', 'month']);
|
$admin = $gameStor->getValues(['startyear', 'starttime', 'turnterm', 'year', 'month']);
|
||||||
|
|
||||||
$turn = $admin['starttime'];
|
$turn = $admin['starttime'];
|
||||||
$curturn = cutTurn(Util::toInt($curtime), $admin['turnterm']);
|
$term = $admin['turnterm'];
|
||||||
$num = intdiv($curturn - Util::toInt($turn), GameClock::TICKS_PER_TURN);
|
if($term == -60){
|
||||||
|
$num = VarTurn60::calcTurnDiff(new \DateTimeImmutable($turn), new \DateTimeImmutable($curtime));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$curturn = cutTurn($curtime, $admin['turnterm']);
|
||||||
|
$num = intdiv((strtotime($curturn) - strtotime($turn)), $term * 60);
|
||||||
|
}
|
||||||
|
|
||||||
$date = $admin['startyear'] * 12;
|
$date = $admin['startyear'] * 12;
|
||||||
$date += $num;
|
$date += $num;
|
||||||
@@ -1392,9 +1438,6 @@ function CheckHall($no)
|
|||||||
|
|
||||||
if ($valueType === 'natural') {
|
if ($valueType === 'natural') {
|
||||||
$value = $generalObj->getVar($typeName);
|
$value = $generalObj->getVar($typeName);
|
||||||
if (in_array($typeName, ['dex1', 'dex2', 'dex3', 'dex4', 'dex5'], true)) {
|
|
||||||
$value = CentennialAllStarGrowthService::recordableValue($generalObj, $typeName);
|
|
||||||
}
|
|
||||||
} else if ($valueType === 'rank') {
|
} else if ($valueType === 'rank') {
|
||||||
$value = $generalObj->getRankVar(RankColumn::from($typeName));
|
$value = $generalObj->getRankVar(RankColumn::from($typeName));
|
||||||
} else if ($valueType === 'calc') {
|
} else if ($valueType === 'calc') {
|
||||||
@@ -1698,16 +1741,7 @@ function getAdmin()
|
|||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$admin = $gameStor->getAll();
|
return $gameStor->getAll();
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
foreach (['turntime', 'starttime', 'opentime', 'tnmt_time'] as $key) {
|
|
||||||
if (($admin[$key] ?? null) !== null) {
|
|
||||||
$admin["{$key}_display"] = $clock->formatTick(Util::toInt($admin[$key]), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$admin['clock_now_tick'] = $clock->nowTick();
|
|
||||||
$admin['clock_now_display'] = $clock->formatTick($admin['clock_now_tick'], true);
|
|
||||||
return $admin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return General[] */
|
/** @return General[] */
|
||||||
@@ -2197,29 +2231,44 @@ function SabotageInjury(RandUtil $rng, array $cityGeneralList, string $reason):
|
|||||||
return $injuryCount;
|
return $injuryCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRandTurn(RandUtil $rng, int $term, ?int $baseTick = null): int
|
function getRandTurn(RandUtil $rng, $term, ?\DateTimeInterface $baseDateTime = null)
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
if ($baseDateTime === null) {
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
$baseDateTime = new \DateTimeImmutable();
|
||||||
$baseTick ??= $clock->nowTick();
|
} else if ($baseDateTime instanceof \DateTime) {
|
||||||
|
$baseDateTime = \DateTimeImmutable::createFromMutable($baseDateTime);
|
||||||
|
} else if ($baseDateTime instanceof \DateTimeImmutable) {
|
||||||
|
//do Nothing
|
||||||
|
} else {
|
||||||
|
throw new MustNotBeReachedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if($term == -60){
|
||||||
|
[, $term] = VarTurn60::fromDatetime($baseDateTime)->cutTurn();
|
||||||
|
}
|
||||||
|
|
||||||
$randSecond = $rng->nextRangeInt(0, 60 * $term - 1);
|
$randSecond = $rng->nextRangeInt(0, 60 * $term - 1);
|
||||||
$randMicrosecond = $rng->nextRangeInt(0, 999999); // 레거시 RNG 소비 6자리 유지
|
$randFraction = $rng->nextRangeInt(0, 999999) / 1000000; //6자리 소수
|
||||||
|
|
||||||
return $baseTick
|
return TimeUtil::format($baseDateTime->add(TimeUtil::secondsToDateInterval($randSecond + $randFraction)), true);
|
||||||
+ $clock->ticksFromSeconds($randSecond)
|
|
||||||
+ intdiv($randMicrosecond * $clock->ticksPerSecond(), 1_000_000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRandTurn2(RandUtil $rng, int $term, ?int $baseTick = null): int
|
function getRandTurn2(RandUtil $rng, $term, ?\DateTimeInterface $baseDateTime = null)
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
if ($baseDateTime === null) {
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
$baseDateTime = new \DateTimeImmutable();
|
||||||
$baseTick ??= $clock->nowTick();
|
} else if ($baseDateTime instanceof \DateTime) {
|
||||||
$randSecond = $rng->nextRangeInt(0, 60 * $term - 1);
|
$baseDateTime = \DateTimeImmutable::createFromMutable($baseDateTime);
|
||||||
$randMicrosecond = $rng->nextRangeInt(0, 999999); // 레거시 RNG 소비 6자리 유지
|
} else {
|
||||||
|
throw new MustNotBeReachedException();
|
||||||
|
}
|
||||||
|
|
||||||
return $baseTick
|
if($term == -60){
|
||||||
- $clock->ticksFromSeconds($randSecond)
|
[, $term] = VarTurn60::fromDatetime($baseDateTime)->cutTurn();
|
||||||
- intdiv($randMicrosecond * $clock->ticksPerSecond(), 1_000_000);
|
}
|
||||||
|
|
||||||
|
$randSecond = $rng->nextRangeInt(0, 60 * $term - 1);
|
||||||
|
$randFraction = $rng->nextRangeInt(0, 999999) / 1000000; //6자리 소수
|
||||||
|
|
||||||
|
return $baseDateTime->sub(TimeUtil::secondsToDateInterval($randSecond + $randFraction))->format('Y-m-d H:i:s.u');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,12 +62,11 @@ function processAuction()
|
|||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$now = TimeUtil::now();
|
||||||
$nowTick = GameClock::fromStorage($gameStor)->nowTick();
|
|
||||||
|
|
||||||
$auctionList = $db->queryAllLists(
|
$auctionList = $db->queryAllLists(
|
||||||
'SELECT id, `type` FROM ng_auction WHERE `close_tick` <= %i AND finished = 0',
|
'SELECT id, `type` FROM ng_auction WHERE `close_date` <= %s AND finished = 0',
|
||||||
$nowTick
|
$now
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!$auctionList) {
|
if (!$auctionList) {
|
||||||
|
|||||||
+36
-64
@@ -42,21 +42,15 @@ function pushGeneralCommand(int $generalID, int $turnCnt=1){
|
|||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$db->query(
|
$db->update('general_turn', [
|
||||||
'UPDATE general_turn AS dst
|
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
|
||||||
LEFT JOIN general_turn AS src
|
], 'general_id=%i ORDER BY turn_idx DESC', $generalID);
|
||||||
ON src.general_id = dst.general_id
|
$db->update('general_turn', [
|
||||||
AND src.turn_idx = dst.turn_idx - %i
|
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxTurn),
|
||||||
SET dst.action = IF(src.id IS NULL, %s, src.action),
|
'action'=>'휴식',
|
||||||
dst.arg = IF(src.id IS NULL, %s, src.arg),
|
'arg'=>'{}',
|
||||||
dst.brief = IF(src.id IS NULL, %s, src.brief)
|
'brief'=>'휴식'
|
||||||
WHERE dst.general_id = %i',
|
], 'general_id=%i AND turn_idx >= %i', $generalID, GameConst::$maxTurn);
|
||||||
$turnCnt,
|
|
||||||
'휴식',
|
|
||||||
'{}',
|
|
||||||
'휴식',
|
|
||||||
$generalID
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function pullGeneralCommand(int $generalID, int $turnCnt=1){
|
function pullGeneralCommand(int $generalID, int $turnCnt=1){
|
||||||
@@ -73,21 +67,15 @@ function pullGeneralCommand(int $generalID, int $turnCnt=1){
|
|||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$db->query(
|
$db->update('general_turn', [
|
||||||
'UPDATE general_turn AS dst
|
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxTurn),
|
||||||
LEFT JOIN general_turn AS src
|
'action'=>'휴식',
|
||||||
ON src.general_id = dst.general_id
|
'arg'=>'{}',
|
||||||
AND src.turn_idx = dst.turn_idx + %i
|
'brief'=>'휴식'
|
||||||
SET dst.action = IF(src.id IS NULL, %s, src.action),
|
], 'general_id=%i AND turn_idx < %i', $generalID, $turnCnt);
|
||||||
dst.arg = IF(src.id IS NULL, %s, src.arg),
|
$db->update('general_turn', [
|
||||||
dst.brief = IF(src.id IS NULL, %s, src.brief)
|
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
|
||||||
WHERE dst.general_id = %i',
|
], 'general_id=%i ORDER BY turn_idx ASC', $generalID);
|
||||||
$turnCnt,
|
|
||||||
'휴식',
|
|
||||||
'{}',
|
|
||||||
'휴식',
|
|
||||||
$generalID
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function repeatGeneralCommand(int $generalId, int $turnCnt){
|
function repeatGeneralCommand(int $generalId, int $turnCnt){
|
||||||
@@ -138,23 +126,15 @@ function pushNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
|
|||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$db->query(
|
$db->update('nation_turn', [
|
||||||
'UPDATE nation_turn AS dst
|
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
|
||||||
LEFT JOIN nation_turn AS src
|
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx DESC', $nationID, $officerLevel);
|
||||||
ON src.nation_id = dst.nation_id
|
$db->update('nation_turn', [
|
||||||
AND src.officer_level = dst.officer_level
|
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxChiefTurn),
|
||||||
AND src.turn_idx = dst.turn_idx - %i
|
'action'=>'휴식',
|
||||||
SET dst.action = IF(src.id IS NULL, %s, src.action),
|
'arg'=>'{}',
|
||||||
dst.arg = IF(src.id IS NULL, %s, src.arg),
|
'brief'=>'휴식'
|
||||||
dst.brief = IF(src.id IS NULL, %s, src.brief)
|
], 'nation_id=%i AND officer_level=%i AND turn_idx >= %i ORDER BY turn_idx ASC', $nationID, $officerLevel, GameConst::$maxChiefTurn);
|
||||||
WHERE dst.nation_id = %i AND dst.officer_level = %i',
|
|
||||||
$turnCnt,
|
|
||||||
'휴식',
|
|
||||||
'{}',
|
|
||||||
'휴식',
|
|
||||||
$nationID,
|
|
||||||
$officerLevel
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function pullNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
|
function pullNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
|
||||||
@@ -177,23 +157,15 @@ function pullNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
|
|||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$db->query(
|
$db->update('nation_turn', [
|
||||||
'UPDATE nation_turn AS dst
|
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxChiefTurn),
|
||||||
LEFT JOIN nation_turn AS src
|
'action'=>'휴식',
|
||||||
ON src.nation_id = dst.nation_id
|
'arg'=>'{}',
|
||||||
AND src.officer_level = dst.officer_level
|
'brief'=>'휴식',
|
||||||
AND src.turn_idx = dst.turn_idx + %i
|
], 'nation_id=%i AND officer_level=%i AND turn_idx < %i', $nationID, $officerLevel, $turnCnt);
|
||||||
SET dst.action = IF(src.id IS NULL, %s, src.action),
|
$db->update('nation_turn', [
|
||||||
dst.arg = IF(src.id IS NULL, %s, src.arg),
|
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
|
||||||
dst.brief = IF(src.id IS NULL, %s, src.brief)
|
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx ASC', $nationID, $officerLevel);
|
||||||
WHERE dst.nation_id = %i AND dst.officer_level = %i',
|
|
||||||
$turnCnt,
|
|
||||||
'휴식',
|
|
||||||
'{}',
|
|
||||||
'휴식',
|
|
||||||
$nationID,
|
|
||||||
$officerLevel
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function repeatNationCommand(int $nationID, int $officerLevel, int $turnCnt){
|
function repeatNationCommand(int $nationID, int $officerLevel, int $turnCnt){
|
||||||
|
|||||||
+2
-10
@@ -654,21 +654,13 @@ function checkStatistic()
|
|||||||
function convForOldGeneral(array $general, int $year, int $month)
|
function convForOldGeneral(array $general, int $year, int $month)
|
||||||
{
|
{
|
||||||
$general['history'] = getGeneralHistoryLogAll($general['no']);
|
$general['history'] = getGeneralHistoryLogAll($general['no']);
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage(DB::db(), 'game_env'));
|
|
||||||
$turnTimeDisplay = $clock->formatTick(Util::toInt($general['turntime']), true);
|
|
||||||
$general['turntime_tick'] = Util::toInt($general['turntime']);
|
|
||||||
$general['turntime'] = $turnTimeDisplay;
|
|
||||||
if ($general['recent_war'] !== null) {
|
|
||||||
$general['recent_war_tick'] = Util::toInt($general['recent_war']);
|
|
||||||
$general['recent_war'] = $clock->formatTick(Util::toInt($general['recent_war']), true);
|
|
||||||
}
|
|
||||||
return [
|
return [
|
||||||
'server_id' => UniqueConst::$serverID,
|
'server_id' => UniqueConst::$serverID,
|
||||||
'general_no' => $general['no'],
|
'general_no' => $general['no'],
|
||||||
'owner' => $general['owner'],
|
'owner' => $general['owner'],
|
||||||
'name' => $general['name'],
|
'name' => $general['name'],
|
||||||
'last_yearmonth' => $year * 100 + $month,
|
'last_yearmonth' => $year * 100 + $month,
|
||||||
'turntime' => $turnTimeDisplay,
|
'turntime' => $general['turntime'],
|
||||||
'data' => Json::encode($general)
|
'data' => Json::encode($general)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -742,7 +734,7 @@ function checkEmperior()
|
|||||||
|
|
||||||
/** @var int[] */
|
/** @var int[] */
|
||||||
$auctionList = $db->queryFirstColumn(
|
$auctionList = $db->queryFirstColumn(
|
||||||
'SELECT `id` FROM `ng_auction` WHERE `type` = %s AND `finished` = 0 ORDER BY `close_tick` ASC',
|
'SELECT `id` FROM `ng_auction` WHERE `type` = %s AND `finished` = 0 ORDER BY `close_date` ASC',
|
||||||
AuctionType::UniqueItem->value
|
AuctionType::UniqueItem->value
|
||||||
);
|
);
|
||||||
foreach($auctionList as $auctionID){
|
foreach($auctionList as $auctionID){
|
||||||
|
|||||||
+6
-5
@@ -4,10 +4,6 @@ namespace sammo;
|
|||||||
|
|
||||||
function printLimitMsg($turntime)
|
function printLimitMsg($turntime)
|
||||||
{
|
{
|
||||||
if (is_int($turntime) || (is_string($turntime) && ctype_digit(ltrim($turntime, '-')))) {
|
|
||||||
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
|
|
||||||
$turntime = GameClock::fromStorage($gameStor)->formatTick(Util::toInt($turntime), true);
|
|
||||||
}
|
|
||||||
//FIXME: template로 이동.
|
//FIXME: template로 이동.
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@@ -185,7 +181,12 @@ function info($type = 0)
|
|||||||
|
|
||||||
$admin = $gameStor->getValues(['year', 'month', 'turnterm', 'maxgeneral']);
|
$admin = $gameStor->getValues(['year', 'month', 'turnterm', 'maxgeneral']);
|
||||||
|
|
||||||
$termtype = "{$admin['turnterm']}분 턴";
|
$turnTermText = $admin['turnterm'].'분';
|
||||||
|
if($admin['turnterm'] < 0){
|
||||||
|
$turnTermText = "가변 {$admin['turnterm']}분";
|
||||||
|
}
|
||||||
|
|
||||||
|
$termtype = "{$turnTermText}분 턴";
|
||||||
|
|
||||||
$gencount = $db->queryFirstField('SELECT count(no) FROM general WHERE npc < 2');
|
$gencount = $db->queryFirstField('SELECT count(no) FROM general WHERE npc < 2');
|
||||||
$npccount = $db->queryFirstField('SELECT count(no) FROM general WHERE npc >= 2');
|
$npccount = $db->queryFirstField('SELECT count(no) FROM general WHERE npc >= 2');
|
||||||
|
|||||||
@@ -63,10 +63,6 @@ function chiefTurnTable()
|
|||||||
|
|
||||||
function templateLimitMsg(string $turntime): string
|
function templateLimitMsg(string $turntime): string
|
||||||
{
|
{
|
||||||
if (ctype_digit(ltrim($turntime, '-'))) {
|
|
||||||
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
|
|
||||||
$turntime = GameClock::fromStorage($gameStor)->formatTick(Util::toInt($turntime), true);
|
|
||||||
}
|
|
||||||
return "이미 너무 많은 접속을 하셨습니다. 다음 턴에 다시 시도해주세요. (턴시간: {$turntime})";
|
return "이미 너무 많은 접속을 하셨습니다. 다음 턴에 다시 시도해주세요. (턴시간: {$turntime})";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-11
@@ -10,6 +10,7 @@ use sammo\Enums\InheritanceKey;
|
|||||||
* @return int 토너먼트 초 단위
|
* @return int 토너먼트 초 단위
|
||||||
*/
|
*/
|
||||||
function calcTournamentTerm(int $turnTerm): int{
|
function calcTournamentTerm(int $turnTerm): int{
|
||||||
|
$turnTerm = abs($turnTerm);
|
||||||
return Util::valueFit($turnTerm, 5, 120);
|
return Util::valueFit($turnTerm, 5, 120);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,10 +18,10 @@ function processTournament()
|
|||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
|
|
||||||
$admin = $gameStor->getValues(['tournament', 'phase', 'tnmt_type', 'tnmt_auto', 'tnmt_time', 'turnterm', 'last_tournament_betting_id']);
|
$admin = $gameStor->getValues(['tournament', 'phase', 'tnmt_type', 'tnmt_auto', 'tnmt_time', 'turnterm', 'last_tournament_betting_id']);
|
||||||
$offset = intdiv($clock->nowTick() - Util::toInt($admin['tnmt_time']), $clock->ticksPerSecond());
|
$now = new \DateTime();
|
||||||
|
$offset = $now->getTimestamp() - (new \DateTime($admin['tnmt_time']))->getTimestamp();
|
||||||
|
|
||||||
//수동일땐 무시
|
//수동일땐 무시
|
||||||
if (!$admin['tnmt_auto']) {
|
if (!$admin['tnmt_auto']) {
|
||||||
@@ -122,10 +123,10 @@ function processTournament()
|
|||||||
if ($tnmt == 6) {
|
if ($tnmt == 6) {
|
||||||
$betTerm = Util::valueFit($unit * 60, null, 3600);
|
$betTerm = Util::valueFit($unit * 60, null, 3600);
|
||||||
//처리 초 더한 날짜
|
//처리 초 더한 날짜
|
||||||
|
$dt = date("Y-m-d H:i:s", strtotime($admin['tnmt_time']) + $unit * $i + $betTerm);
|
||||||
$gameStor->tournament = $tnmt;
|
$gameStor->tournament = $tnmt;
|
||||||
$gameStor->phase = $phase;
|
$gameStor->phase = $phase;
|
||||||
$gameStor->tnmt_time = Util::toInt($admin['tnmt_time'])
|
$gameStor->tnmt_time = $dt;
|
||||||
+ $clock->ticksFromSeconds($unit * $i + $betTerm);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,11 +134,12 @@ function processTournament()
|
|||||||
$second = $unit * $iter;
|
$second = $unit * $iter;
|
||||||
$gameStor->tournament = $tnmt;
|
$gameStor->tournament = $tnmt;
|
||||||
$gameStor->phase = $phase;
|
$gameStor->phase = $phase;
|
||||||
$gameStor->tnmt_time = Util::toInt($admin['tnmt_time']) + $clock->ticksFromSeconds($second);
|
$gameStor->tnmt_time = (new \DateTimeImmutable($admin['tnmt_time']))->add(new \DateInterval("PT{$second}S"))->format('Y-m-d H:i:s');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTournamentTermText(int $turnTerm)
|
function getTournamentTermText(int $turnTerm)
|
||||||
{
|
{
|
||||||
|
$turnTerm = abs($turnTerm);
|
||||||
$term = calcTournamentTerm($turnTerm);
|
$term = calcTournamentTerm($turnTerm);
|
||||||
|
|
||||||
if ($term % 60 === 0) {
|
if ($term % 60 === 0) {
|
||||||
@@ -160,8 +162,7 @@ function getTournamentTime()
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
|
||||||
list($tnmt, $tnmt_time) = $gameStor->getValuesAsArray(['tournament', 'tnmt_time']);
|
list($tnmt, $tnmt_time) = $gameStor->getValuesAsArray(['tournament', 'tnmt_time']);
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$dt = substr($tnmt_time, 11, 5);
|
||||||
$dt = substr($clock->formatTick(Util::toInt($tnmt_time)), 11, 5);
|
|
||||||
switch ($tnmt) {
|
switch ($tnmt) {
|
||||||
case 1:
|
case 1:
|
||||||
$tnmt = "개막시간 {$dt}";
|
$tnmt = "개막시간 {$dt}";
|
||||||
@@ -285,11 +286,9 @@ function startTournament($type)
|
|||||||
$admin = $gameStor->getValues(['year', 'month', 'turnterm']);
|
$admin = $gameStor->getValues(['year', 'month', 'turnterm']);
|
||||||
$turnTerm = $admin['turnterm'];
|
$turnTerm = $admin['turnterm'];
|
||||||
$unit = calcTournamentTerm($turnTerm);
|
$unit = calcTournamentTerm($turnTerm);
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
|
|
||||||
$gameStor->tnmt_auto = true;
|
$gameStor->tnmt_auto = true;
|
||||||
// 기존 startTournament은 unit을 분으로 더하므로 그 계약을 유지합니다.
|
$gameStor->tnmt_time = (new \DateTimeImmutable())->add(new \DateInterval("PT{$unit}M"))->format('Y-m-d H:i:s');
|
||||||
$gameStor->tnmt_time = $clock->nowTick() + $clock->ticksFromMinutes($unit);
|
|
||||||
$gameStor->tournament = 1;
|
$gameStor->tournament = 1;
|
||||||
$gameStor->tnmt_type = $type;
|
$gameStor->tnmt_type = $type;
|
||||||
$gameStor->last_tournament_betting_id = 0;
|
$gameStor->last_tournament_betting_id = 0;
|
||||||
@@ -345,7 +344,7 @@ function startBetting($type)
|
|||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
[$year, $month, $startyear, $turnterm] = $gameStor->getValuesAsArray(['year', 'month', 'startyear', 'turnterm']);
|
[$year, $month, $startyear] = $gameStor->getValuesAsArray(['year', 'month', 'startyear']);
|
||||||
pushGlobalHistoryLog([
|
pushGlobalHistoryLog([
|
||||||
"<S>◆</>{$year}년 {$month}월:<B><b>【대회】</b></>우승자를 예상하는 <C>내기</>가 진행중입니다! 호사가의 참여를 기다립니다!"
|
"<S>◆</>{$year}년 {$month}월:<B><b>【대회】</b></>우승자를 예상하는 <C>내기</>가 진행중입니다! 호사가의 참여를 기다립니다!"
|
||||||
], $year, $month);
|
], $year, $month);
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ if ($session->userGrade < 5 && !$allowReset) {
|
|||||||
<label for="turnterm" class="col-sm-3 col-form-label">턴 시간(분)</label>
|
<label for="turnterm" class="col-sm-3 col-form-label">턴 시간(분)</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div id="turnterm" class="btn-group btn-group-toggle" data-bs-toggle="buttons">
|
<div id="turnterm" class="btn-group btn-group-toggle" data-bs-toggle="buttons">
|
||||||
|
<input type="radio" class="btn-check" name="turnterm" id="turnterm_var60" value="-60" checked><label for="turnterm_var60" class="btn btn-secondary">가변60</label>
|
||||||
<input type="radio" class="btn-check" name="turnterm" id="turnterm_120" value="120"><label for="turnterm_120" class="btn btn-secondary">120</label>
|
<input type="radio" class="btn-check" name="turnterm" id="turnterm_120" value="120"><label for="turnterm_120" class="btn btn-secondary">120</label>
|
||||||
<input type="radio" class="btn-check" name="turnterm" id="turnterm_60" value="60" checked><label for="turnterm_60" class="btn btn-secondary">60</label>
|
<input type="radio" class="btn-check" name="turnterm" id="turnterm_60" value="60" checked><label for="turnterm_60" class="btn btn-secondary">60</label>
|
||||||
<input type="radio" class="btn-check" name="turnterm" id="turnterm_30" value="30"><label for="turnterm_30" class="btn btn-secondary">30</label>
|
<input type="radio" class="btn-check" name="turnterm" id="turnterm_30" value="30"><label for="turnterm_30" class="btn btn-secondary">30</label>
|
||||||
|
|||||||
@@ -16,10 +16,12 @@ $session = Session::requireLogin([])->setReadOnly();
|
|||||||
$userID = Session::getUserID();
|
$userID = Session::getUserID();
|
||||||
|
|
||||||
|
|
||||||
|
$oNow = new \DateTimeImmutable();
|
||||||
|
|
||||||
|
$now = $oNow->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
$now = $clock->nowTick();
|
|
||||||
|
|
||||||
$oldGeneral = $db->queryFirstField('SELECT `no` FROM general WHERE `owner`=%i', $userID);
|
$oldGeneral = $db->queryFirstField('SELECT `no` FROM general WHERE `owner`=%i', $userID);
|
||||||
if($oldGeneral !== null){
|
if($oldGeneral !== null){
|
||||||
@@ -34,6 +36,7 @@ list(
|
|||||||
$turnterm,
|
$turnterm,
|
||||||
$npcmode
|
$npcmode
|
||||||
) = $gameStor->getValuesAsArray(['maxgeneral', 'turnterm', 'npcmode']);
|
) = $gameStor->getValuesAsArray(['maxgeneral', 'turnterm', 'npcmode']);
|
||||||
|
$turnterm = abs($turnterm);
|
||||||
|
|
||||||
if($npcmode!=1){
|
if($npcmode!=1){
|
||||||
Json::die([
|
Json::die([
|
||||||
@@ -42,14 +45,15 @@ if($npcmode!=1){
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$token = $db->queryFirstRow('SELECT * FROM select_npc_token WHERE `owner`=%i AND `valid_until`>=%i', $userID, $now);
|
$token = $db->queryFirstRow('SELECT * FROM select_npc_token WHERE `owner`=%i AND `valid_until`>=%s', $userID, $now);
|
||||||
$pickResult = [];
|
$pickResult = [];
|
||||||
|
|
||||||
|
|
||||||
if($token && $refresh){
|
if($token && $refresh){
|
||||||
$pickMoreFrom = Util::toInt($token['pick_more_from']);
|
$pickMoreFrom = (new \DateTime($token['pick_more_from']))->getTimestamp();
|
||||||
|
$nowT = $oNow->getTimestamp();
|
||||||
|
|
||||||
if($now >= $pickMoreFrom){
|
if($nowT >= $pickMoreFrom){
|
||||||
$oldPickResult = Json::decode($token['pick_result']);
|
$oldPickResult = Json::decode($token['pick_result']);
|
||||||
|
|
||||||
foreach($keepResult as $keepId){
|
foreach($keepResult as $keepId){
|
||||||
@@ -72,14 +76,15 @@ if($token && $refresh){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($token && !$refresh){
|
if($token && !$refresh){
|
||||||
$pickMoreFrom = Util::toInt($token['pick_more_from']);
|
$pickMoreFrom = (new \DateTime($token['pick_more_from']))->getTimestamp();
|
||||||
|
$nowT = $oNow->getTimestamp();
|
||||||
|
|
||||||
Json::die([
|
Json::die([
|
||||||
'result'=>true,
|
'result'=>true,
|
||||||
'pick'=>Json::decode($token['pick_result']),
|
'pick'=>Json::decode($token['pick_result']),
|
||||||
'pickMoreFrom'=>$clock->formatTick($pickMoreFrom),
|
'pickMoreFrom'=>$token['pick_more_from'],
|
||||||
'pickMoreSeconds'=>intdiv($pickMoreFrom - $now, $clock->ticksPerSecond()),
|
'pickMoreSeconds'=>$pickMoreFrom-$nowT,
|
||||||
'validUntil'=>$clock->formatTick(Util::toInt($token['valid_until']))
|
'validUntil'=>$token['valid_until']
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +101,7 @@ foreach($db->query('SELECT `no`, `name`, leadership, strength, intel, nation, im
|
|||||||
$weight[$general['no']] = pow($allStat, 1.5);
|
$weight[$general['no']] = pow($allStat, 1.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($db->queryFirstColumn('SELECT pick_result FROM select_npc_token WHERE `owner`!=%i AND valid_until >=%i', $userID, $now) as $reserved){
|
foreach($db->queryFirstColumn('SELECT pick_result FROM select_npc_token WHERE `owner`!=%i AND valid_until >=%s', $userID, $now) as $reserved){
|
||||||
$reserved = Json::decode($reserved);
|
$reserved = Json::decode($reserved);
|
||||||
foreach(array_keys($reserved) as $reservedNPC){
|
foreach(array_keys($reserved) as $reservedNPC){
|
||||||
if(key_exists($reservedNPC, $weight)){
|
if(key_exists($reservedNPC, $weight)){
|
||||||
@@ -127,8 +132,8 @@ $newNonce = random_int(0, 0xfffffff);
|
|||||||
$validSecond = max(VALID_SECOND, $turnterm*40);
|
$validSecond = max(VALID_SECOND, $turnterm*40);
|
||||||
$pickMoreSecond = max(PICK_MORE_SECOND, Util::round(pow($turnterm, 0.672)*8));
|
$pickMoreSecond = max(PICK_MORE_SECOND, Util::round(pow($turnterm, 0.672)*8));
|
||||||
|
|
||||||
$validUntil = $now + $clock->ticksFromSeconds($validSecond);
|
$validUntil = $oNow->add(new \DateInterval(sprintf('PT%dS', $validSecond)));
|
||||||
$pickMoreFrom = $now + $clock->ticksFromSeconds($pickMoreSecond);
|
$pickMoreFrom = $oNow->add(new \DateInterval(sprintf('PT%dS', $pickMoreSecond)));
|
||||||
|
|
||||||
$db->delete('select_npc_token', 'valid_until < %s', $now);
|
$db->delete('select_npc_token', 'valid_until < %s', $now);
|
||||||
|
|
||||||
@@ -136,8 +141,8 @@ $inserted = 0;
|
|||||||
|
|
||||||
if($token){
|
if($token){
|
||||||
$db->update('select_npc_token', [
|
$db->update('select_npc_token', [
|
||||||
'valid_until'=>$validUntil,
|
'valid_until'=>$validUntil->format('Y-m-d H:i:s'),
|
||||||
'pick_more_from'=>$pickMoreFrom,
|
'pick_more_from'=>$pickMoreFrom->format('Y-m-d H:i:s'),
|
||||||
'pick_result'=>Json::encode($pickResult),
|
'pick_result'=>Json::encode($pickResult),
|
||||||
'nonce'=>$newNonce
|
'nonce'=>$newNonce
|
||||||
], 'owner = %i AND nonce = %i', $userID, $token['nonce']);
|
], 'owner = %i AND nonce = %i', $userID, $token['nonce']);
|
||||||
@@ -148,8 +153,8 @@ if($token){
|
|||||||
else{
|
else{
|
||||||
$db->insertIgnore('select_npc_token', [
|
$db->insertIgnore('select_npc_token', [
|
||||||
'owner'=>$userID,
|
'owner'=>$userID,
|
||||||
'valid_until'=>$validUntil,
|
'valid_until'=>$validUntil->format('Y-m-d H:i:s'),
|
||||||
'pick_more_from'=>$now,
|
'pick_more_from'=>'2000-01-01 01:00:00',
|
||||||
'pick_result'=>Json::encode($pickResult),
|
'pick_result'=>Json::encode($pickResult),
|
||||||
'nonce'=>$newNonce
|
'nonce'=>$newNonce
|
||||||
]);
|
]);
|
||||||
@@ -169,7 +174,7 @@ if($inserted === 0){
|
|||||||
Json::die([
|
Json::die([
|
||||||
'result'=>true,
|
'result'=>true,
|
||||||
'pick'=>$pickResult,
|
'pick'=>$pickResult,
|
||||||
'pickMoreFrom'=>$clock->formatTick(($inserted===-1)?$pickMoreFrom:$now),
|
'pickMoreFrom'=>($inserted===-1)?$pickMoreFrom->format('Y-m-d H:i:s'):'2000-01-01 01:00:00',
|
||||||
'pickMoreSeconds'=>($inserted===-1)?$pickMoreSecond:0,
|
'pickMoreSeconds'=>($inserted===-1)?$pickMoreSecond:0,
|
||||||
'validUntil'=>$clock->formatTick($validUntil)
|
'validUntil'=>$validUntil->format('Y-m-d H:i:s')
|
||||||
]);
|
]);
|
||||||
+10
-26
@@ -10,23 +10,7 @@ function sortTokens(&$tokens){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function putInfoText(&$info, ?array $currentTargetEnv){
|
function putInfoText(&$info){
|
||||||
if (($info['event100Growth'] ?? false) === true) {
|
|
||||||
if ($currentTargetEnv === null) {
|
|
||||||
$displayStats = CentennialAllStarGrowthService::calculateUserInitialStats($info);
|
|
||||||
$info['selectionStatLabel'] = '시작 능력치';
|
|
||||||
} else {
|
|
||||||
$displayStats = CentennialAllStarGrowthService::calculateUserCurrentTargetStats(
|
|
||||||
$info,
|
|
||||||
$currentTargetEnv
|
|
||||||
);
|
|
||||||
$info['selectionStatLabel'] = '현재 변경 기준 능력치';
|
|
||||||
}
|
|
||||||
$info['selectionLeadership'] = $displayStats['leadership'];
|
|
||||||
$info['selectionStrength'] = $displayStats['strength'];
|
|
||||||
$info['selectionIntel'] = $displayStats['intel'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(key_exists('specialDomestic', $info)){
|
if(key_exists('specialDomestic', $info)){
|
||||||
$class = buildGeneralSpecialDomesticClass($info['specialDomestic']);
|
$class = buildGeneralSpecialDomesticClass($info['specialDomestic']);
|
||||||
$info['specialDomesticName'] = $class->getName();
|
$info['specialDomesticName'] = $class->getName();
|
||||||
@@ -43,13 +27,14 @@ function putInfoText(&$info, ?array $currentTargetEnv){
|
|||||||
$session = Session::requireLogin([])->setReadOnly();
|
$session = Session::requireLogin([])->setReadOnly();
|
||||||
$userID = Session::getUserID();
|
$userID = Session::getUserID();
|
||||||
|
|
||||||
|
$oNow = new \DateTimeImmutable();
|
||||||
|
|
||||||
|
$now = $oNow->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
$now = $clock->nowTick();
|
|
||||||
|
|
||||||
$eventEnv = $gameStor->getValues(['npcmode', 'startyear', 'year', 'month']);
|
$npcmode = $gameStor->getValue('npcmode');
|
||||||
$npcmode = $eventEnv['npcmode'];
|
|
||||||
if($npcmode!=2){
|
if($npcmode!=2){
|
||||||
Json::die([
|
Json::die([
|
||||||
'result'=>false,
|
'result'=>false,
|
||||||
@@ -58,7 +43,6 @@ if($npcmode!=2){
|
|||||||
}
|
}
|
||||||
|
|
||||||
$rawGeneral = $db->queryFirstRow('SELECT no, aux FROM general WHERE `owner` = %i', $userID);
|
$rawGeneral = $db->queryFirstRow('SELECT no, aux FROM general WHERE `owner` = %i', $userID);
|
||||||
$currentTargetEnv = $rawGeneral ? $eventEnv : null;
|
|
||||||
if($rawGeneral){
|
if($rawGeneral){
|
||||||
$generalAux = Json::decode($rawGeneral['aux']);
|
$generalAux = Json::decode($rawGeneral['aux']);
|
||||||
if(key_exists('next_change', $generalAux)&& $generalAux['next_change'] > $now){
|
if(key_exists('next_change', $generalAux)&& $generalAux['next_change'] > $now){
|
||||||
@@ -78,7 +62,7 @@ if($tokens){
|
|||||||
foreach($tokens as $token){
|
foreach($tokens as $token){
|
||||||
$valid_until = $token['reserved_until'];
|
$valid_until = $token['reserved_until'];
|
||||||
$info = Json::decode($token['info']);
|
$info = Json::decode($token['info']);
|
||||||
putInfoText($info, $currentTargetEnv);
|
putInfoText($info);
|
||||||
$info['uniqueName'] = $token['unique_name'];
|
$info['uniqueName'] = $token['unique_name'];
|
||||||
$pick[] = $info;
|
$pick[] = $info;
|
||||||
}
|
}
|
||||||
@@ -86,7 +70,7 @@ if($tokens){
|
|||||||
Json::die([
|
Json::die([
|
||||||
'result'=>true,
|
'result'=>true,
|
||||||
'pick'=>$pick,
|
'pick'=>$pick,
|
||||||
'validUntil'=>$clock->formatTick(Util::toInt($valid_until))
|
'validUntil'=>$valid_until
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,12 +83,12 @@ $valid_until = null;
|
|||||||
foreach(pickGeneralFromPool($db, $rng, $userID, 14) as $pickObj){
|
foreach(pickGeneralFromPool($db, $rng, $userID, 14) as $pickObj){
|
||||||
$valid_until = $pickObj->getValidUntil();
|
$valid_until = $pickObj->getValidUntil();
|
||||||
$info = $pickObj->getInfo();
|
$info = $pickObj->getInfo();
|
||||||
putInfoText($info, $currentTargetEnv);
|
putInfoText($info);
|
||||||
$pick[] = $info;
|
$pick[] = $info;
|
||||||
}
|
}
|
||||||
sortTokens($pick);//좀 무식하지만..
|
sortTokens($pick);//좀 무식하지만..
|
||||||
Json::die([
|
Json::die([
|
||||||
'result'=>true,
|
'result'=>true,
|
||||||
'pick'=>$pick,
|
'pick'=>$pick,
|
||||||
'validUntil'=>$valid_until === null ? null : $clock->formatTick(Util::toInt($valid_until))
|
'validUntil'=>$valid_until
|
||||||
]);
|
]);
|
||||||
+1
-1
@@ -211,7 +211,7 @@ try{
|
|||||||
$show_img_level,
|
$show_img_level,
|
||||||
!!$tournament_trig,
|
!!$tournament_trig,
|
||||||
$join_mode,
|
$join_mode,
|
||||||
TimeUtil::format(GameClock::readWallTime(), false),
|
TimeUtil::now(),
|
||||||
$autorun_user
|
$autorun_user
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ $db = DB::db();
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$rootDB = RootDB::db();
|
$rootDB = RootDB::db();
|
||||||
|
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$oNow = new \DateTimeImmutable();
|
||||||
$now = $clock->nowTick();
|
$now = $oNow->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
$member = $rootDB->queryFirstRow('SELECT `name`, `penalty` FROM member WHERE `NO`=%i', $userID);
|
$member = $rootDB->queryFirstRow('SELECT `name`, `penalty` FROM member WHERE `NO`=%i', $userID);
|
||||||
if(!$member){
|
if(!$member){
|
||||||
|
|||||||
@@ -8,20 +8,10 @@ WebUtil::requireAJAX();
|
|||||||
|
|
||||||
$pick = Util::getPost('pick');
|
$pick = Util::getPost('pick');
|
||||||
$leadership = Util::getPost('leadership', 'int', GameConst::$defaultStatMin);
|
$leadership = Util::getPost('leadership', 'int', GameConst::$defaultStatMin);
|
||||||
$isCentennialAllStar = CentennialAllStarGrowthService::isActive();
|
$strength = Util::getPost('leadership', 'int', GameConst::$defaultStatMin);
|
||||||
$strength = Util::getPost(
|
$intel = Util::getPost('leadership', 'int', GameConst::$defaultStatMin);
|
||||||
$isCentennialAllStar ? 'strength' : 'leadership',
|
|
||||||
'int',
|
|
||||||
GameConst::$defaultStatMin
|
|
||||||
);
|
|
||||||
$intel = Util::getPost(
|
|
||||||
$isCentennialAllStar ? 'intel' : 'leadership',
|
|
||||||
'int',
|
|
||||||
GameConst::$defaultStatMin
|
|
||||||
);
|
|
||||||
$personal = Util::getPost('personal', 'string', null);
|
$personal = Util::getPost('personal', 'string', null);
|
||||||
$use_own_picture = Util::getPost('use_own_picture', 'bool', false);
|
$use_own_picture = Util::getPost('use_own_picture', 'bool', false);
|
||||||
$pictureSource = Util::getPost('picture_source', 'string', 'selected');
|
|
||||||
|
|
||||||
|
|
||||||
if(!$pick){
|
if(!$pick){
|
||||||
@@ -37,8 +27,8 @@ $db = DB::db();
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
|
||||||
$rootDB = RootDB::db();
|
$rootDB = RootDB::db();
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$oNow = new \DateTimeImmutable();
|
||||||
$now = $clock->nowTick();
|
$now = $oNow->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
$hasGeneralID = $db->queryFirstField('SELECT no FROM general WHERE owner = %i', $userID);
|
$hasGeneralID = $db->queryFirstField('SELECT no FROM general WHERE owner = %i', $userID);
|
||||||
if($hasGeneralID){
|
if($hasGeneralID){
|
||||||
@@ -70,36 +60,13 @@ if(!$selectInfo){
|
|||||||
}
|
}
|
||||||
$selectInfo = Json::decode($selectInfo);
|
$selectInfo = Json::decode($selectInfo);
|
||||||
|
|
||||||
$ownerInfo = RootDB::db()->queryFirstRow(
|
$ownerInfo = RootDB::db()->queryFirstRow('SELECT `name`,`picture`,`imgsvr` FROM member WHERE `NO`=%i',$userID);
|
||||||
'SELECT `name`,`picture`,`imgsvr`,`grade` FROM member WHERE `NO`=%i',
|
|
||||||
$userID
|
|
||||||
);
|
|
||||||
if(!$ownerInfo){
|
if(!$ownerInfo){
|
||||||
Json::die([
|
Json::die([
|
||||||
'result'=>false,
|
'result'=>false,
|
||||||
'reason'=>'멤버 정보를 가져오지 못했습니다.'
|
'reason'=>'멤버 정보를 가져오지 못했습니다.'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
if ($isCentennialAllStar) {
|
|
||||||
if (!in_array($pictureSource, ['selected', 'own'], true)) {
|
|
||||||
Json::die([
|
|
||||||
'result' => false,
|
|
||||||
'reason' => '올바르지 않은 전콘 선택입니다.',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
if ($pictureSource === 'own') {
|
|
||||||
$canUseOwnPicture = in_array('picture', GameConst::$generalPoolAllowOption, true)
|
|
||||||
&& $env['show_img_level'] >= 1
|
|
||||||
&& $ownerInfo['grade'] >= 1
|
|
||||||
&& $ownerInfo['picture'] !== '';
|
|
||||||
if (!$canUseOwnPicture) {
|
|
||||||
Json::die([
|
|
||||||
'result' => false,
|
|
||||||
'reason' => '사용할 수 있는 내 전콘이 없습니다.',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2');
|
$gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2');
|
||||||
@@ -113,25 +80,12 @@ if ($gencount >= $maxgeneral) {
|
|||||||
|
|
||||||
$poolClass = getGeneralPoolClass(GameConst::$targetGeneralPool);
|
$poolClass = getGeneralPoolClass(GameConst::$targetGeneralPool);
|
||||||
/** @var AbsGeneralPool */
|
/** @var AbsGeneralPool */
|
||||||
if ($isCentennialAllStar) {
|
$pickedGeneral = new $poolClass($db, $selectInfo, $now);
|
||||||
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
|
|
||||||
UniqueConst::$hiddenSeed,
|
|
||||||
'selectPickedGeneral',
|
|
||||||
$userID,
|
|
||||||
$pick
|
|
||||||
)));
|
|
||||||
$pickedGeneral = new $poolClass($db, $rng, $selectInfo, $now);
|
|
||||||
} else {
|
|
||||||
$pickedGeneral = new $poolClass($db, $selectInfo, $now);
|
|
||||||
}
|
|
||||||
|
|
||||||
$builder = $pickedGeneral->getGeneralBuilder();
|
$builder = $pickedGeneral->getGeneralBuilder();
|
||||||
if ($isCentennialAllStar) {
|
|
||||||
CentennialAllStarGrowthService::prepareInitialUser($builder, $selectInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(GameConst::$generalPoolAllowOption as $allowOption){
|
foreach(GameConst::$generalPoolAllowOption as $allowOption){
|
||||||
if($allowOption == 'stat' && !$isCentennialAllStar){
|
if($allowOption == 'stat'){
|
||||||
$leadership = Util::valueFit($leadership, GameConst::$defaultStatMin, GameConst::$defaultStatMax);
|
$leadership = Util::valueFit($leadership, GameConst::$defaultStatMin, GameConst::$defaultStatMax);
|
||||||
$strength = Util::valueFit($strength, GameConst::$defaultStatMin, GameConst::$defaultStatMax);
|
$strength = Util::valueFit($strength, GameConst::$defaultStatMin, GameConst::$defaultStatMax);
|
||||||
$intel = Util::valueFit($intel, GameConst::$defaultStatMin, GameConst::$defaultStatMax);
|
$intel = Util::valueFit($intel, GameConst::$defaultStatMin, GameConst::$defaultStatMax);
|
||||||
@@ -144,23 +98,14 @@ foreach(GameConst::$generalPoolAllowOption as $allowOption){
|
|||||||
}
|
}
|
||||||
$builder->setStat($leadership, $strength, $intel);
|
$builder->setStat($leadership, $strength, $intel);
|
||||||
}
|
}
|
||||||
else if(
|
else if($allowOption == 'picture' && $use_own_picture){
|
||||||
$allowOption == 'picture'
|
|
||||||
&& (
|
|
||||||
(!$isCentennialAllStar && $use_own_picture)
|
|
||||||
|| ($isCentennialAllStar && $pictureSource === 'own')
|
|
||||||
)
|
|
||||||
){
|
|
||||||
$builder->setPicture($ownerInfo['imgsvr'], $ownerInfo['picture']);
|
$builder->setPicture($ownerInfo['imgsvr'], $ownerInfo['picture']);
|
||||||
}
|
}
|
||||||
else if($allowOption == 'ego'){
|
else if($allowOption == 'ego'){
|
||||||
if(!$personal || $personal == 'Random'){
|
if(!$personal || $personal == 'Random'){
|
||||||
$personal = Util::choiceRandom(GameConst::$availablePersonality);
|
$personal = Util::choiceRandom(GameConst::$availablePersonality);
|
||||||
}
|
}
|
||||||
$invalidPersonal = $isCentennialAllStar
|
if(!array_search($personal, GameConst::$availablePersonality)){
|
||||||
? !in_array($personal, GameConst::$availablePersonality, true)
|
|
||||||
: !array_search($personal, GameConst::$availablePersonality);
|
|
||||||
if($invalidPersonal){
|
|
||||||
Json::die([
|
Json::die([
|
||||||
'result'=>false,
|
'result'=>false,
|
||||||
'reason'=>'올바르지 않은 성격입니다.'
|
'reason'=>'올바르지 않은 성격입니다.'
|
||||||
@@ -176,29 +121,8 @@ $builder->setOwner($userID);
|
|||||||
$builder->setOwnerName($userNick);
|
$builder->setOwnerName($userNick);
|
||||||
$builder->setKillturn(5);
|
$builder->setKillturn(5);
|
||||||
$builder->setNPCType(0);
|
$builder->setNPCType(0);
|
||||||
$builder->setAuxVar('next_change', $now + GameClock::TICKS_PER_TURN * 12);
|
$builder->setAuxVar('next_change', TimeUtil::nowAddMinutes(12 * abs($env['turnterm'])));
|
||||||
$builder->setAuxVar(
|
|
||||||
'prestart_delete_after',
|
|
||||||
addTurn($now, $env['turnterm'], GameConst::$minTurnDieOnPrestart)
|
|
||||||
);
|
|
||||||
$builder->fillRemainSpecAsZero($env);
|
$builder->fillRemainSpecAsZero($env);
|
||||||
if ($isCentennialAllStar) {
|
|
||||||
$candidateCities = $db->queryFirstColumn(
|
|
||||||
'SELECT city FROM city WHERE level >= 5 AND level <= 6 AND nation = 0'
|
|
||||||
);
|
|
||||||
if (!$candidateCities) {
|
|
||||||
$candidateCities = $db->queryFirstColumn(
|
|
||||||
'SELECT city FROM city WHERE level >= 5 AND level <= 6'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!$candidateCities) {
|
|
||||||
Json::die([
|
|
||||||
'result' => false,
|
|
||||||
'reason' => '장수를 생성할 소·중성이 없습니다.',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
$builder->setCityID($rng->choice($candidateCities));
|
|
||||||
}
|
|
||||||
$builder->build($env);
|
$builder->build($env);
|
||||||
$generalID = $builder->getGeneralID();
|
$generalID = $builder->getGeneralID();
|
||||||
if(!$generalID){
|
if(!$generalID){
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ if(!class_exists('\\sammo\\DB')){
|
|||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
|
|
||||||
if(file_exists(__DIR__.'/.htaccess')){
|
if(file_exists(__DIR__.'/.htaccess')){
|
||||||
$reserved = $db->queryFirstRow(
|
$reserved = $db->queryFirstRow(
|
||||||
@@ -76,8 +75,8 @@ $admin['maxUserCnt'] = $admin['maxgeneral'];
|
|||||||
$admin['npcMode'] = $admin['npcmode'];
|
$admin['npcMode'] = $admin['npcmode'];
|
||||||
$admin['turnTerm'] = $admin['turnterm'];
|
$admin['turnTerm'] = $admin['turnterm'];
|
||||||
$admin['isUnited'] = $admin['isunited'];
|
$admin['isUnited'] = $admin['isunited'];
|
||||||
$admin['starttime'] = substr($clock->formatTick(Util::toInt($admin['opentime'])), 5, 11);
|
$admin['starttime'] = substr($admin['opentime'], 5, 11);
|
||||||
$admin['turntime'] = substr($clock->formatTick(Util::toInt($admin['turntime'])), 5, 11);
|
$admin['turntime'] = substr($admin['turntime'], 5, 11);
|
||||||
unset($admin['npcmode']);
|
unset($admin['npcmode']);
|
||||||
unset($admin['maxgeneral']);
|
unset($admin['maxgeneral']);
|
||||||
unset($admin['turnterm']);
|
unset($admin['turnterm']);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ $me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn);
|
|||||||
$me->setVar('tnmt', $tnmt);
|
$me->setVar('tnmt', $tnmt);
|
||||||
|
|
||||||
if ($me->getNPCType() == 1 && $detachNPC) {
|
if ($me->getNPCType() == 1 && $detachNPC) {
|
||||||
$turnterm = $gameStor->turnterm;
|
$turnterm = abs($gameStor->turnterm);
|
||||||
|
|
||||||
if ($turnterm < 10) {
|
if ($turnterm < 10) {
|
||||||
$targetKillTurn = 30 / $turnterm;
|
$targetKillTurn = 30 / $turnterm;
|
||||||
|
|||||||
@@ -77,8 +77,7 @@ $month = $query['month'];
|
|||||||
$repeatCnt = $query['repeatCnt'];
|
$repeatCnt = $query['repeatCnt'];
|
||||||
|
|
||||||
$rawAttacker = $query['attackerGeneral'];
|
$rawAttacker = $query['attackerGeneral'];
|
||||||
$battleClock = GameClock::fromStorage(KVStorage::getStorage(DB::db(), 'game_env'));
|
$rawAttacker['turntime'] = TimeUtil::now();
|
||||||
$rawAttacker['turntime'] = $battleClock->formatTick($battleClock->nowTick());
|
|
||||||
$rawAttackerCity = $query['attackerCity'];
|
$rawAttackerCity = $query['attackerCity'];
|
||||||
$rawAttackerNation = $query['attackerNation'];
|
$rawAttackerNation = $query['attackerNation'];
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ include "func.php";
|
|||||||
WebUtil::requireAJAX();
|
WebUtil::requireAJAX();
|
||||||
|
|
||||||
$pick = Util::getPost('pick');
|
$pick = Util::getPost('pick');
|
||||||
$pictureSource = Util::getPost('picture_source', 'string', 'selected');
|
|
||||||
|
|
||||||
if(!$pick){
|
if(!$pick){
|
||||||
Json::die([
|
Json::die([
|
||||||
@@ -22,8 +21,8 @@ $db = DB::db();
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
|
||||||
$rootDB = RootDB::db();
|
$rootDB = RootDB::db();
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$oNow = new \DateTimeImmutable();
|
||||||
$now = $clock->nowTick();
|
$now = $oNow->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
$generalID = $db->queryFirstField('SELECT no FROM general WHERE owner = %i', $userID);
|
$generalID = $db->queryFirstField('SELECT no FROM general WHERE owner = %i', $userID);
|
||||||
if(!$generalID){
|
if(!$generalID){
|
||||||
@@ -36,20 +35,11 @@ if(!$generalID){
|
|||||||
list(
|
list(
|
||||||
$year,
|
$year,
|
||||||
$month,
|
$month,
|
||||||
$startYear,
|
|
||||||
$maxgeneral,
|
$maxgeneral,
|
||||||
$npcmode,
|
$npcmode,
|
||||||
$turnterm,
|
$turnterm
|
||||||
$showImgLevel
|
) = $gameStor->getValuesAsArray(['year', 'month', 'maxgeneral', 'npcmode', 'turnterm']);
|
||||||
) = $gameStor->getValuesAsArray([
|
$turnterm = abs($turnterm);
|
||||||
'year',
|
|
||||||
'month',
|
|
||||||
'startyear',
|
|
||||||
'maxgeneral',
|
|
||||||
'npcmode',
|
|
||||||
'turnterm',
|
|
||||||
'show_img_level',
|
|
||||||
]);
|
|
||||||
|
|
||||||
if($npcmode!=2){
|
if($npcmode!=2){
|
||||||
Json::die([
|
Json::die([
|
||||||
@@ -66,10 +56,7 @@ if(!$info){
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$ownerInfo = RootDB::db()->queryFirstRow(
|
$ownerInfo = RootDB::db()->queryFirstRow('SELECT `name`,`picture`,`imgsvr` FROM member WHERE `NO`=%i',$userID);
|
||||||
'SELECT `name`,`picture`,`imgsvr`,`grade` FROM member WHERE `NO`=%i',
|
|
||||||
$userID
|
|
||||||
);
|
|
||||||
if(!$ownerInfo){
|
if(!$ownerInfo){
|
||||||
Json::die([
|
Json::die([
|
||||||
'result'=>false,
|
'result'=>false,
|
||||||
@@ -78,27 +65,6 @@ if(!$ownerInfo){
|
|||||||
}
|
}
|
||||||
|
|
||||||
$info = Json::decode($info);
|
$info = Json::decode($info);
|
||||||
$isCentennialAllStar = CentennialAllStarGrowthService::isActive();
|
|
||||||
if ($isCentennialAllStar) {
|
|
||||||
if (!in_array($pictureSource, ['current', 'own', 'selected'], true)) {
|
|
||||||
Json::die([
|
|
||||||
'result' => false,
|
|
||||||
'reason' => '올바르지 않은 전콘 선택입니다.',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
if ($pictureSource === 'own') {
|
|
||||||
$canUseOwnPicture = in_array('picture', GameConst::$generalPoolAllowOption, true)
|
|
||||||
&& $showImgLevel >= 1
|
|
||||||
&& $ownerInfo['grade'] >= 1
|
|
||||||
&& $ownerInfo['picture'] !== '';
|
|
||||||
if (!$canUseOwnPicture) {
|
|
||||||
Json::die([
|
|
||||||
'result' => false,
|
|
||||||
'reason' => '사용할 수 있는 내 전콘이 없습니다.',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$generalObj = General::createObjFromDB($generalID);
|
$generalObj = General::createObjFromDB($generalID);
|
||||||
@@ -136,52 +102,35 @@ $db->update('select_pool',[
|
|||||||
'reserved_until'=>null,
|
'reserved_until'=>null,
|
||||||
], '(owner=%i or reserved_until < %s) AND general_id is NULL', $userID, $now);
|
], '(owner=%i or reserved_until < %s) AND general_id is NULL', $userID, $now);
|
||||||
|
|
||||||
if ($isCentennialAllStar) {
|
if(key_exists('leadership', $info)){
|
||||||
CentennialAllStarGrowthService::prepareLegacyUserReselection($generalObj);
|
$generalObj->updateVar('leadership', $info['leadership']);
|
||||||
CentennialAllStarGrowthService::applyTarget($generalObj, $info, [
|
$generalObj->updateVar('strength', $info['strength']);
|
||||||
'startyear' => $startYear,
|
$generalObj->updateVar('intel', $info['intel']);
|
||||||
'year' => $year,
|
|
||||||
'month' => $month,
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
if(key_exists('leadership', $info)){
|
|
||||||
$generalObj->updateVar('leadership', $info['leadership']);
|
|
||||||
$generalObj->updateVar('strength', $info['strength']);
|
|
||||||
$generalObj->updateVar('intel', $info['intel']);
|
|
||||||
}
|
|
||||||
if(key_exists('dex', $info)){
|
|
||||||
$generalObj->updateVar('dex1', $info['dex'][0]);
|
|
||||||
$generalObj->updateVar('dex2', $info['dex'][1]);
|
|
||||||
$generalObj->updateVar('dex3', $info['dex'][2]);
|
|
||||||
$generalObj->updateVar('dex4', $info['dex'][3]);
|
|
||||||
$generalObj->updateVar('dex5', $info['dex'][4]);
|
|
||||||
}
|
|
||||||
if(key_exists('ego', $info)){
|
|
||||||
$generalObj->updateVar('personal', $info['ego']);
|
|
||||||
}
|
|
||||||
if(key_exists('specialDomestic', $info)){
|
|
||||||
$generalObj->updateVar('special', $info['specialDomestic']);
|
|
||||||
}
|
|
||||||
if(key_exists('specialWar', $info)){
|
|
||||||
$generalObj->updateVar('special2', $info['specialWar']);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ($isCentennialAllStar) {
|
if(key_exists('picture', $info)){
|
||||||
if ($pictureSource === 'own') {
|
|
||||||
$generalObj->updateVar('imgsvr', $ownerInfo['imgsvr']);
|
|
||||||
$generalObj->updateVar('picture', $ownerInfo['picture']);
|
|
||||||
} elseif ($pictureSource === 'selected' && key_exists('picture', $info)) {
|
|
||||||
$generalObj->updateVar('imgsvr', $info['imgsvr']);
|
|
||||||
$generalObj->updateVar('picture', $info['picture']);
|
|
||||||
}
|
|
||||||
} elseif(key_exists('picture', $info)){
|
|
||||||
$generalObj->updateVar('imgsvr', $info['imgsvr']);
|
$generalObj->updateVar('imgsvr', $info['imgsvr']);
|
||||||
$generalObj->updateVar('picture', $info['picture']);
|
$generalObj->updateVar('picture', $info['picture']);
|
||||||
}
|
}
|
||||||
if(key_exists('generalName', $info)){
|
if(key_exists('generalName', $info)){
|
||||||
$generalObj->updateVar('name', $info['generalName']);
|
$generalObj->updateVar('name', $info['generalName']);
|
||||||
}
|
}
|
||||||
$generalObj->setAuxVar('next_change', $now + GameClock::TICKS_PER_TURN * 12);
|
if(key_exists('dex', $info)){
|
||||||
|
$generalObj->updateVar('dex1', $info['dex'][0]);
|
||||||
|
$generalObj->updateVar('dex2', $info['dex'][1]);
|
||||||
|
$generalObj->updateVar('dex3', $info['dex'][2]);
|
||||||
|
$generalObj->updateVar('dex4', $info['dex'][3]);
|
||||||
|
$generalObj->updateVar('dex5', $info['dex'][4]);
|
||||||
|
}
|
||||||
|
if(key_exists('ego', $info)){
|
||||||
|
$generalObj->updateVar('personal', $info['ego']);
|
||||||
|
}
|
||||||
|
if(key_exists('specialDomestic', $info)){
|
||||||
|
$generalObj->updateVar('special', $info['specialDomestic']);
|
||||||
|
}
|
||||||
|
if(key_exists('specialWar', $info)){
|
||||||
|
$generalObj->updateVar('special2', $info['specialWar']);
|
||||||
|
}
|
||||||
|
$generalObj->setAuxVar('next_change', TimeUtil::nowAddMinutes(12 * $turnterm));
|
||||||
|
|
||||||
$userNick = $ownerInfo['name'];
|
$userNick = $ownerInfo['name'];
|
||||||
$generalObj->setVar('owner_name', $userNick);
|
$generalObj->setVar('owner_name', $userNick);
|
||||||
|
|||||||
+1
-3
@@ -11,11 +11,9 @@ $db = DB::db();
|
|||||||
$updated = false;
|
$updated = false;
|
||||||
$locked = false;
|
$locked = false;
|
||||||
$lastExecuted = TurnExecutionHelper::executeAllCommand($updated, $locked);
|
$lastExecuted = TurnExecutionHelper::executeAllCommand($updated, $locked);
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
|
||||||
Json::die([
|
Json::die([
|
||||||
'result' => true,
|
'result' => true,
|
||||||
'updated' => $updated,
|
'updated' => $updated,
|
||||||
'locked' => $locked,
|
'locked' => $locked,
|
||||||
'lastExecutedTick' => $lastExecuted,
|
'lastExecuted' => $lastExecuted,
|
||||||
'lastExecuted' => $clock->formatTick($lastExecuted, true),
|
|
||||||
]);
|
]);
|
||||||
@@ -21,7 +21,7 @@ class BidUniqueAuction extends \sammo\BaseAPI
|
|||||||
])
|
])
|
||||||
->rule('int', 'amount')
|
->rule('int', 'amount')
|
||||||
->rule('int', 'auctionID')
|
->rule('int', 'auctionID')
|
||||||
->rule('boolean', 'extendCloseTick');
|
->rule('boolean', 'extendCloseDate');
|
||||||
|
|
||||||
if (!$v->validate()) {
|
if (!$v->validate()) {
|
||||||
return $v->errorStr();
|
return $v->errorStr();
|
||||||
@@ -38,7 +38,7 @@ class BidUniqueAuction extends \sammo\BaseAPI
|
|||||||
{
|
{
|
||||||
$auctionID = $this->args['auctionID'];
|
$auctionID = $this->args['auctionID'];
|
||||||
$amount = $this->args['amount'];
|
$amount = $this->args['amount'];
|
||||||
$tryExtendCloseDate = $this->args['extendCloseTick'] ?? false;
|
$tryExtendCloseDate = $this->args['extendCloseDate'] ?? false;
|
||||||
|
|
||||||
$generalID = $session->generalID;
|
$generalID = $session->generalID;
|
||||||
$general = General::createObjFromDB($generalID);
|
$general = General::createObjFromDB($generalID);
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ use sammo\General;
|
|||||||
use sammo\Json;
|
use sammo\Json;
|
||||||
use sammo\TimeUtil;
|
use sammo\TimeUtil;
|
||||||
use sammo\Util;
|
use sammo\Util;
|
||||||
use sammo\GameClock;
|
|
||||||
use sammo\KVStorage;
|
|
||||||
|
|
||||||
use function sammo\getAuctionLogRecent;
|
use function sammo\getAuctionLogRecent;
|
||||||
|
|
||||||
@@ -35,13 +33,12 @@ class GetActiveResourceAuctionList extends \sammo\BaseAPI
|
|||||||
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
|
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
|
||||||
|
|
||||||
$buyRiceList = [];
|
$buyRiceList = [];
|
||||||
$sellRiceList = [];
|
$sellRiceList = [];
|
||||||
/** @var AuctionInfo[] */
|
/** @var AuctionInfo[] */
|
||||||
$auctions = array_map(fn ($raw) => AuctionInfo::fromArray($raw), $db->query(
|
$auctions = array_map(fn ($raw) => AuctionInfo::fromArray($raw), $db->query(
|
||||||
'SELECT * FROM `ng_auction` WHERE `type` IN %ls AND `finished` = 0 ORDER BY `close_tick` ASC',
|
'SELECT * FROM `ng_auction` WHERE `type` IN %ls AND `finished` = 0 ORDER BY `close_date` ASC',
|
||||||
[
|
[
|
||||||
AuctionType::BuyRice->value,
|
AuctionType::BuyRice->value,
|
||||||
AuctionType::SellRice->value,
|
AuctionType::SellRice->value,
|
||||||
@@ -90,8 +87,8 @@ class GetActiveResourceAuctionList extends \sammo\BaseAPI
|
|||||||
'type' => $auction->type->value,
|
'type' => $auction->type->value,
|
||||||
'hostGeneralID' => $auction->hostGeneralID,
|
'hostGeneralID' => $auction->hostGeneralID,
|
||||||
'hostName' => $auction->detail->hostName,
|
'hostName' => $auction->detail->hostName,
|
||||||
'openDate' => $clock->formatTick($auction->openTick),
|
'openDate' => TimeUtil::format($auction->openDate, false),
|
||||||
'closeDate' => $clock->formatTick($auction->closeTick),
|
'closeDate' => TimeUtil::format($auction->closeDate, false),
|
||||||
'amount' => $auction->detail->amount,
|
'amount' => $auction->detail->amount,
|
||||||
'startBidAmount' => $auction->detail->startBidAmount,
|
'startBidAmount' => $auction->detail->startBidAmount,
|
||||||
'finishBidAmount' => $auction->detail->finishBidAmount,
|
'finishBidAmount' => $auction->detail->finishBidAmount,
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ use sammo\Enums\GeneralQueryMode;
|
|||||||
use sammo\Enums\InheritanceKey;
|
use sammo\Enums\InheritanceKey;
|
||||||
use sammo\InheritancePointManager;
|
use sammo\InheritancePointManager;
|
||||||
use sammo\TimeUtil;
|
use sammo\TimeUtil;
|
||||||
use sammo\GameClock;
|
|
||||||
use sammo\KVStorage;
|
|
||||||
use sammo\Validator;
|
use sammo\Validator;
|
||||||
use sammo\General;
|
use sammo\General;
|
||||||
|
|
||||||
@@ -44,7 +42,6 @@ class GetUniqueItemAuctionDetail extends \sammo\BaseAPI
|
|||||||
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
|
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
|
||||||
|
|
||||||
$generalID = $session->generalID;
|
$generalID = $session->generalID;
|
||||||
$auctionID = $this->args['auctionID'];
|
$auctionID = $this->args['auctionID'];
|
||||||
@@ -95,11 +92,9 @@ class GetUniqueItemAuctionDetail extends \sammo\BaseAPI
|
|||||||
'target' => $auction->target,
|
'target' => $auction->target,
|
||||||
'isCallerHost' => $auction->hostGeneralID === $generalID,
|
'isCallerHost' => $auction->hostGeneralID === $generalID,
|
||||||
'hostName' => $auction->detail->hostName,
|
'hostName' => $auction->detail->hostName,
|
||||||
'closeDate' => $clock->formatTick($auction->closeTick),
|
'closeDate' => TimeUtil::format($auction->closeDate, false),
|
||||||
'remainCloseDateExtensionCnt' => $auction->detail->remainCloseDateExtensionCnt,
|
'remainCloseDateExtensionCnt' => $auction->detail->remainCloseDateExtensionCnt,
|
||||||
'availableLatestBidCloseDate' => $auction->detail->availableLatestBidCloseTick === null
|
'availableLatestBidCloseDate' => TimeUtil::format($auction->detail->availableLatestBidCloseDate, false),
|
||||||
? null
|
|
||||||
: $clock->formatTick($auction->detail->availableLatestBidCloseTick),
|
|
||||||
],
|
],
|
||||||
'bidList' => $responseBid,
|
'bidList' => $responseBid,
|
||||||
'obfuscatedName' => $obfuscatedName,
|
'obfuscatedName' => $obfuscatedName,
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ use sammo\Enums\APIRecoveryType;
|
|||||||
use sammo\Enums\AuctionType;
|
use sammo\Enums\AuctionType;
|
||||||
use sammo\TimeUtil;
|
use sammo\TimeUtil;
|
||||||
use sammo\Util;
|
use sammo\Util;
|
||||||
use sammo\GameClock;
|
|
||||||
use sammo\KVStorage;
|
|
||||||
|
|
||||||
class GetUniqueItemAuctionList extends \sammo\BaseAPI
|
class GetUniqueItemAuctionList extends \sammo\BaseAPI
|
||||||
{
|
{
|
||||||
@@ -30,13 +28,12 @@ class GetUniqueItemAuctionList extends \sammo\BaseAPI
|
|||||||
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
|
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
|
||||||
|
|
||||||
$generalID = $session->generalID;
|
$generalID = $session->generalID;
|
||||||
|
|
||||||
/** @var AuctionInfo[] */
|
/** @var AuctionInfo[] */
|
||||||
$auctions = array_map(fn($raw)=>AuctionInfo::fromArray($raw), $db->query(
|
$auctions = array_map(fn($raw)=>AuctionInfo::fromArray($raw), $db->query(
|
||||||
'SELECT * FROM `ng_auction` WHERE `type` = %s ORDER BY `close_tick` ASC',
|
'SELECT * FROM `ng_auction` WHERE `type` = %s ORDER BY `close_date` ASC',
|
||||||
AuctionType::UniqueItem->value
|
AuctionType::UniqueItem->value
|
||||||
) ?? []);
|
) ?? []);
|
||||||
|
|
||||||
@@ -88,11 +85,9 @@ class GetUniqueItemAuctionList extends \sammo\BaseAPI
|
|||||||
'target' => $auction->target,
|
'target' => $auction->target,
|
||||||
'isCallerHost' => $auction->hostGeneralID === $generalID,
|
'isCallerHost' => $auction->hostGeneralID === $generalID,
|
||||||
'hostName' => $auction->detail->hostName,
|
'hostName' => $auction->detail->hostName,
|
||||||
'closeDate' => $clock->formatTick($auction->closeTick),
|
'closeDate' => TimeUtil::format($auction->closeDate, false),
|
||||||
'remainCloseDateExtensionCnt' => $auction->detail->remainCloseDateExtensionCnt,
|
'remainCloseDateExtensionCnt' => $auction->detail->remainCloseDateExtensionCnt,
|
||||||
'availableLatestBidCloseDate' => $auction->detail->availableLatestBidCloseTick === null
|
'availableLatestBidCloseDate' => TimeUtil::format($auction->detail->availableLatestBidCloseDate, false),
|
||||||
? null
|
|
||||||
: $clock->formatTick($auction->detail->availableLatestBidCloseTick),
|
|
||||||
'highestBid' => [
|
'highestBid' => [
|
||||||
'generalName' => $highestBid->aux->generalName,
|
'generalName' => $highestBid->aux->generalName,
|
||||||
'amount' => $highestBid->amount,
|
'amount' => $highestBid->amount,
|
||||||
|
|||||||
@@ -7,11 +7,9 @@ use DateTimeInterface;
|
|||||||
use sammo\DB;
|
use sammo\DB;
|
||||||
use sammo\Enums\APIRecoveryType;
|
use sammo\Enums\APIRecoveryType;
|
||||||
use sammo\GameConst;
|
use sammo\GameConst;
|
||||||
use sammo\GameClock;
|
|
||||||
use sammo\Json;
|
use sammo\Json;
|
||||||
use sammo\KVStorage;
|
use sammo\KVStorage;
|
||||||
use sammo\TimeUtil;
|
use sammo\TimeUtil;
|
||||||
use sammo\Util;
|
|
||||||
|
|
||||||
use function sammo\cutTurn;
|
use function sammo\cutTurn;
|
||||||
|
|
||||||
@@ -84,12 +82,11 @@ class GetReservedCommand extends \sammo\BaseAPI
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'result' => true,
|
'result' => true,
|
||||||
'turnTimeTick' => Util::toInt($turnTime),
|
'turnTime' => $turnTime,
|
||||||
'turnTime' => GameClock::fromStorage($gameStor)->formatTick(Util::toInt($turnTime)),
|
|
||||||
'turnTerm' => $turnTerm,
|
'turnTerm' => $turnTerm,
|
||||||
'year' => $year,
|
'year' => $year,
|
||||||
'month' => $month,
|
'month' => $month,
|
||||||
'date' => GameClock::fromStorage($gameStor)->formatTick(GameClock::fromStorage($gameStor)->nowTick(), true),
|
'date' => TimeUtil::now(true),
|
||||||
'turn' => $commandList,
|
'turn' => $commandList,
|
||||||
'autorun_limit' => $generalAux['autorun_limit'] ?? null,
|
'autorun_limit' => $generalAux['autorun_limit'] ?? null,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ use sammo\Session;
|
|||||||
use sammo\General;
|
use sammo\General;
|
||||||
use sammo\JosaUtil;
|
use sammo\JosaUtil;
|
||||||
use sammo\KVStorage;
|
use sammo\KVStorage;
|
||||||
use sammo\GameClock;
|
use sammo\TimeUtil;
|
||||||
use sammo\Util;
|
|
||||||
|
|
||||||
use function sammo\addTurn;
|
use function sammo\addTurn;
|
||||||
use function sammo\increaseRefresh;
|
use function sammo\increaseRefresh;
|
||||||
@@ -38,14 +37,8 @@ class DieOnPrestart extends \sammo\BaseAPI
|
|||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$gameStor->cacheValues(['turnterm', 'opentime', 'turntime', 'year', 'month']);
|
$gameStor->cacheValues(['turnterm', 'opentime', 'turntime', 'year', 'month']);
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
$nowTick = $clock->nowTick();
|
|
||||||
|
|
||||||
$general = $db->queryFirstRow('SELECT no,name,nation,owner_name,npc FROM general WHERE owner=%i AND npc = 0', $userID);
|
$general = $db->queryFirstRow('SELECT no,name,nation,owner_name,npc FROM general WHERE owner=%i AND npc = 0', $userID);
|
||||||
if (!$general) {
|
|
||||||
return '장수가 없습니다';
|
|
||||||
}
|
|
||||||
|
|
||||||
$lastRefresh = $db->queryFirstField(
|
$lastRefresh = $db->queryFirstField(
|
||||||
'SELECT %b FROM general_access_log WHERE %b = %i',
|
'SELECT %b FROM general_access_log WHERE %b = %i',
|
||||||
GeneralAccessLogColumn::lastRefresh->value,
|
GeneralAccessLogColumn::lastRefresh->value,
|
||||||
@@ -53,9 +46,8 @@ class DieOnPrestart extends \sammo\BaseAPI
|
|||||||
$general['no']
|
$general['no']
|
||||||
);
|
);
|
||||||
|
|
||||||
$generalObj = General::createObjFromDB($general['no']);
|
if (!$general) {
|
||||||
if ($generalObj instanceof DummyGeneral) {
|
return '장수가 없습니다';
|
||||||
trigger_error("올바르지 않은 삭제 프로세스 $userID", E_USER_WARNING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
increaseRefresh("장수 삭제", 1);
|
increaseRefresh("장수 삭제", 1);
|
||||||
@@ -69,21 +61,16 @@ class DieOnPrestart extends \sammo\BaseAPI
|
|||||||
return '이미 국가에 소속되어있습니다.';
|
return '이미 국가에 소속되어있습니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
$targetTime = $generalObj->getAuxVar('prestart_delete_after');
|
//서버 가오픈시 할 수 있는 행동
|
||||||
if (!is_int($targetTime)) {
|
$targetTime = addTurn($lastRefresh, $gameStor->turnterm, GameConst::$minTurnDieOnPrestart);
|
||||||
$targetTime = addTurn(
|
if ($targetTime > TimeUtil::now()) {
|
||||||
$lastRefresh === null ? $nowTick : Util::toInt($lastRefresh),
|
$targetTimeShort = substr($targetTime, 0, 19);
|
||||||
$gameStor->turnterm,
|
return "아직 삭제할 수 없습니다. {$targetTimeShort} 부터 가능합니다.";
|
||||||
GameConst::$minTurnDieOnPrestart
|
|
||||||
);
|
|
||||||
$generalObj->setAuxVar('prestart_delete_after', $targetTime);
|
|
||||||
$generalObj->applyDB($db);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//서버 가오픈시 할 수 있는 행동
|
$generalObj = General::createObjFromDB($general['no']);
|
||||||
if ($targetTime > $nowTick) {
|
if ($generalObj instanceof DummyGeneral) {
|
||||||
$targetTimeShort = $clock->formatTick($targetTime);
|
trigger_error("올바르지 않은 삭제 프로세스 $userID", E_USER_WARNING);
|
||||||
return "아직 삭제할 수 없습니다. {$targetTimeShort} 부터 가능합니다.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$generalName = $generalObj->getName();
|
$generalName = $generalObj->getName();
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ use sammo\Enums\GeneralColumn;
|
|||||||
use sammo\Enums\GeneralQueryMode;
|
use sammo\Enums\GeneralQueryMode;
|
||||||
use sammo\Enums\RankColumn;
|
use sammo\Enums\RankColumn;
|
||||||
use sammo\GameConst;
|
use sammo\GameConst;
|
||||||
use sammo\GameClock;
|
|
||||||
use sammo\General;
|
use sammo\General;
|
||||||
use sammo\KVStorage;
|
use sammo\KVStorage;
|
||||||
use sammo\LastTurn;
|
use sammo\LastTurn;
|
||||||
@@ -106,7 +105,6 @@ class GetFrontInfo extends \sammo\BaseAPI
|
|||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
$gameStor->cacheValues(['isunited', 'opentime', 'refresh']);
|
$gameStor->cacheValues(['isunited', 'opentime', 'refresh']);
|
||||||
|
|
||||||
$lastHistoryID = $this->args['lastWorldHistoryID'];
|
$lastHistoryID = $this->args['lastWorldHistoryID'];
|
||||||
@@ -160,7 +158,6 @@ class GetFrontInfo extends \sammo\BaseAPI
|
|||||||
private function generateGlobalInfo(MeekroDB $db): array
|
private function generateGlobalInfo(MeekroDB $db): array
|
||||||
{
|
{
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
|
|
||||||
[
|
[
|
||||||
$scenarioText, $extendedGeneral, $isFiction, $npcMode,
|
$scenarioText, $extendedGeneral, $isFiction, $npcMode,
|
||||||
@@ -213,8 +210,7 @@ class GetFrontInfo extends \sammo\BaseAPI
|
|||||||
'month' => $month,
|
'month' => $month,
|
||||||
'autorunUser' => $autorunUser,
|
'autorunUser' => $autorunUser,
|
||||||
'turnterm' => $turnterm,
|
'turnterm' => $turnterm,
|
||||||
'lastExecutedTick' => $lastExecuted,
|
'lastExecuted' => $lastExecuted,
|
||||||
'lastExecuted' => $clock->formatTick(Util::toInt($lastExecuted), true),
|
|
||||||
'lastVoteID' => $lastVoteID,
|
'lastVoteID' => $lastVoteID,
|
||||||
'develCost' => $develCost,
|
'develCost' => $develCost,
|
||||||
'noticeMsg' => $noticeMsg,
|
'noticeMsg' => $noticeMsg,
|
||||||
@@ -228,8 +224,7 @@ class GetFrontInfo extends \sammo\BaseAPI
|
|||||||
'isLocked' => $isLocked,
|
'isLocked' => $isLocked,
|
||||||
'tournamentType' => $tournamentType,
|
'tournamentType' => $tournamentType,
|
||||||
'tournamentState' => $tournamentState,
|
'tournamentState' => $tournamentState,
|
||||||
'tournamentTimeTick' => $tournamentTime,
|
'tournamentTime' => $tournamentTime,
|
||||||
'tournamentTime' => $tournamentTime === null ? null : $clock->formatTick(Util::toInt($tournamentTime)),
|
|
||||||
'genCount' => $globalGenCount,
|
'genCount' => $globalGenCount,
|
||||||
'generalCntLimit' => $generalCntLimit,
|
'generalCntLimit' => $generalCntLimit,
|
||||||
'serverCnt' => $serverCnt,
|
'serverCnt' => $serverCnt,
|
||||||
@@ -366,7 +361,6 @@ class GetFrontInfo extends \sammo\BaseAPI
|
|||||||
|
|
||||||
public function generateGeneralInfo(MeekroDB $db, General $general, array $rawNation): array
|
public function generateGeneralInfo(MeekroDB $db, General $general, array $rawNation): array
|
||||||
{
|
{
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
|
||||||
|
|
||||||
$permission = checkSecretPermission($general->getRaw());
|
$permission = checkSecretPermission($general->getRaw());
|
||||||
|
|
||||||
@@ -431,12 +425,8 @@ class GetFrontInfo extends \sammo\BaseAPI
|
|||||||
'crew' => $general->getVar(GeneralColumn::crew), // number;
|
'crew' => $general->getVar(GeneralColumn::crew), // number;
|
||||||
'train' => $general->getVar(GeneralColumn::train), // number;
|
'train' => $general->getVar(GeneralColumn::train), // number;
|
||||||
'atmos' => $general->getVar(GeneralColumn::atmos), // number;
|
'atmos' => $general->getVar(GeneralColumn::atmos), // number;
|
||||||
'turntimeTick' => $general->getTurnTick(), // number;
|
'turntime' => $general->getVar(GeneralColumn::turntime), // string;
|
||||||
'turntime' => $general->getTurnTime(), // string;
|
'recent_war' => $general->getVar(GeneralColumn::recent_war), // string;
|
||||||
'recent_war_tick' => $general->getVar(GeneralColumn::recent_war), // number|null;
|
|
||||||
'recent_war' => $general->getVar(GeneralColumn::recent_war) === null
|
|
||||||
? null
|
|
||||||
: $clock->formatTick(Util::toInt($general->getVar(GeneralColumn::recent_war)), true), // string|null;
|
|
||||||
'horse' => $general->getVar(GeneralColumn::horse), // GameObjClassKey;
|
'horse' => $general->getVar(GeneralColumn::horse), // GameObjClassKey;
|
||||||
'weapon' => $general->getVar(GeneralColumn::weapon), // GameObjClassKey;
|
'weapon' => $general->getVar(GeneralColumn::weapon), // GameObjClassKey;
|
||||||
'book' => $general->getVar(GeneralColumn::book), // GameObjClassKey;
|
'book' => $general->getVar(GeneralColumn::book), // GameObjClassKey;
|
||||||
@@ -554,7 +544,7 @@ class GetFrontInfo extends \sammo\BaseAPI
|
|||||||
'result' => false,
|
'result' => false,
|
||||||
'reason' => '접속 제한중입니다.',
|
'reason' => '접속 제한중입니다.',
|
||||||
'recovery' => APIRecoveryType::GameQuota,
|
'recovery' => APIRecoveryType::GameQuota,
|
||||||
'recovery_arg' => $general->getTurnTime(),
|
'recovery_arg' => $general->getVar('turntime'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ use sammo\Enums\APIRecoveryType;
|
|||||||
use sammo\Enums\GeneralAccessLogColumn;
|
use sammo\Enums\GeneralAccessLogColumn;
|
||||||
use sammo\Enums\RankColumn;
|
use sammo\Enums\RankColumn;
|
||||||
use sammo\GameConst;
|
use sammo\GameConst;
|
||||||
use sammo\GameClock;
|
|
||||||
use sammo\GameUnitConst;
|
use sammo\GameUnitConst;
|
||||||
use sammo\General;
|
use sammo\General;
|
||||||
use sammo\InheritancePointManager;
|
use sammo\InheritancePointManager;
|
||||||
@@ -29,6 +28,7 @@ use sammo\UniqueConst;
|
|||||||
use sammo\UserLogger;
|
use sammo\UserLogger;
|
||||||
use sammo\Util;
|
use sammo\Util;
|
||||||
use sammo\Validator;
|
use sammo\Validator;
|
||||||
|
use sammo\VarTurn60;
|
||||||
use sammo\WebUtil;
|
use sammo\WebUtil;
|
||||||
|
|
||||||
use function sammo\addTurn;
|
use function sammo\addTurn;
|
||||||
@@ -166,7 +166,6 @@ class Join extends \sammo\BaseAPI
|
|||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$gameStor->cacheValues(['year', 'month', 'maxgeneral', 'scenario', 'show_img_level', 'block_general_create', 'turnterm', 'turntime', 'genius', 'npcmode']);
|
$gameStor->cacheValues(['year', 'month', 'maxgeneral', 'scenario', 'show_img_level', 'block_general_create', 'turnterm', 'turntime', 'genius', 'npcmode']);
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
########## 동일 정보 존재여부 확인. ##########
|
########## 동일 정보 존재여부 확인. ##########
|
||||||
|
|
||||||
$block_general_create = $gameStor->getValue('block_general_create');
|
$block_general_create = $gameStor->getValue('block_general_create');
|
||||||
@@ -224,7 +223,7 @@ class Join extends \sammo\BaseAPI
|
|||||||
|
|
||||||
$userLogger = new UserLogger($userID, $admin['year'], $admin['month'], false);
|
$userLogger = new UserLogger($userID, $admin['year'], $admin['month'], false);
|
||||||
|
|
||||||
$now = $clock->nowTick();
|
$now = TimeUtil::now(false);
|
||||||
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
|
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
|
||||||
UniqueConst::$hiddenSeed,
|
UniqueConst::$hiddenSeed,
|
||||||
'MakeGeneral',
|
'MakeGeneral',
|
||||||
@@ -357,19 +356,30 @@ class Join extends \sammo\BaseAPI
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($inheritTurntimeZone !== null) {
|
if ($inheritTurntimeZone !== null) {
|
||||||
$inheritTurntime = $inheritTurntimeZone * $admin['turnterm'];
|
$turnterm = abs($admin['turnterm']);
|
||||||
$inheritTurntime += $rng->nextRangeInt(0, Util::clamp($admin['turnterm'] - 1, 0));
|
$inheritTurntime = $inheritTurntimeZone * $turnterm;
|
||||||
|
$inheritTurntime += $rng->nextRangeInt(0, Util::clamp($turnterm - 1, 0));
|
||||||
|
|
||||||
$userLogger->push(sprintf("턴 시간 %02d:%02d 로 지정", intdiv($inheritTurntime, 60), $inheritTurntime % 60), "inheritPoint");
|
$userLogger->push(sprintf("턴 시간 %02d:%02d 로 지정", intdiv($inheritTurntime, 60), $inheritTurntime % 60), "inheritPoint");
|
||||||
|
|
||||||
$inheritTurnMicrosecond = $rng->nextRangeInt(0, 999999);
|
$inheritTurntime += $rng->nextRangeInt(0, 999999) / 1000000;
|
||||||
$turntime = cutTurn(Util::toInt($admin['turntime']), $admin['turnterm'])
|
|
||||||
+ $clock->ticksFromSeconds($inheritTurntime)
|
$turntime = new \DateTimeImmutable(cutTurn($admin['turntime'], $turnterm));
|
||||||
+ intdiv($inheritTurnMicrosecond * $clock->ticksPerSecond(), 1_000_000);
|
$turntime = $turntime->add(TimeUtil::secondsToDateInterval($inheritTurntime));
|
||||||
|
$turntime = TimeUtil::format($turntime, true);
|
||||||
} else {
|
} else {
|
||||||
$turntime = getRandTurn($rng, $admin['turnterm'], Util::toInt($admin['turntime']));
|
$turntime = getRandTurn($rng, abs($admin['turnterm']), new \DateTimeImmutable($admin['turntime']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($admin['turnterm'] == -60){
|
||||||
|
$baseObj = VarTurn60::fromDatetime(new \DateTimeImmutable($admin['turntime']));
|
||||||
|
$userTurnObj = VarTurn60::fromDatetime(new \DateTimeImmutable($turntime));
|
||||||
|
if($baseObj->turnIdx != $userTurnObj->turnIdx){
|
||||||
|
$turntime = $userTurnObj->addTurn(-1)->toDateStr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$now = TimeUtil::now(true);
|
||||||
if ($now >= $turntime) {
|
if ($now >= $turntime) {
|
||||||
$turntime = addTurn($turntime, $admin['turnterm']);
|
$turntime = addTurn($turntime, $admin['turnterm']);
|
||||||
}
|
}
|
||||||
@@ -434,13 +444,6 @@ class Join extends \sammo\BaseAPI
|
|||||||
'specage2' => $specage2,
|
'specage2' => $specage2,
|
||||||
'special2' => $special2,
|
'special2' => $special2,
|
||||||
'penalty' => Json::encode($penalty),
|
'penalty' => Json::encode($penalty),
|
||||||
'aux' => Json::encode([
|
|
||||||
'prestart_delete_after' => addTurn(
|
|
||||||
$now,
|
|
||||||
$admin['turnterm'],
|
|
||||||
GameConst::$minTurnDieOnPrestart
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
]);
|
]);
|
||||||
$generalID = $db->insertId();
|
$generalID = $db->insertId();
|
||||||
$db->insert('general_access_log', [
|
$db->insert('general_access_log', [
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ use DateTimeInterface;
|
|||||||
use sammo\Enums\APIRecoveryType;
|
use sammo\Enums\APIRecoveryType;
|
||||||
use sammo\TurnExecutionHelper;
|
use sammo\TurnExecutionHelper;
|
||||||
use sammo\UniqueConst;
|
use sammo\UniqueConst;
|
||||||
use sammo\GameClock;
|
|
||||||
use sammo\KVStorage;
|
|
||||||
|
|
||||||
class ExecuteEngine extends \sammo\BaseAPI
|
class ExecuteEngine extends \sammo\BaseAPI
|
||||||
{
|
{
|
||||||
@@ -37,13 +35,11 @@ class ExecuteEngine extends \sammo\BaseAPI
|
|||||||
$updated = false;
|
$updated = false;
|
||||||
$locked = false;
|
$locked = false;
|
||||||
$lastExecuted = TurnExecutionHelper::executeAllCommand($updated, $locked);
|
$lastExecuted = TurnExecutionHelper::executeAllCommand($updated, $locked);
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage(DB::db(), 'game_env'));
|
|
||||||
return [
|
return [
|
||||||
'result' => true,
|
'result' => true,
|
||||||
'updated' => $updated,
|
'updated' => $updated,
|
||||||
'locked' => $locked,
|
'locked' => $locked,
|
||||||
'lastExecutedTick' => $lastExecuted,
|
'lastExecuted' => $lastExecuted,
|
||||||
'lastExecuted' => $clock->formatTick($lastExecuted, true),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
namespace sammo\API\Global;
|
namespace sammo\API\Global;
|
||||||
|
|
||||||
use sammo\DB;
|
use sammo\DB;
|
||||||
use sammo\GameClock;
|
|
||||||
use sammo\Enums\APIRecoveryType;
|
use sammo\Enums\APIRecoveryType;
|
||||||
use sammo\Json;
|
use sammo\Json;
|
||||||
use sammo\KVStorage;
|
use sammo\KVStorage;
|
||||||
@@ -146,8 +145,7 @@ class GeneralList extends \sammo\BaseAPI
|
|||||||
|
|
||||||
|
|
||||||
if (static::$withToken) {
|
if (static::$withToken) {
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$now = (new \DateTimeImmutable())->format('Y-m-d H:i:s');
|
||||||
$now = GameClock::fromStorage($gameStor)->nowTick();
|
|
||||||
$tokens = [];
|
$tokens = [];
|
||||||
foreach ($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token) {
|
foreach ($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token) {
|
||||||
$validUntil = $token['valid_until'];
|
$validUntil = $token['valid_until'];
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ namespace sammo\API\InheritAction;
|
|||||||
|
|
||||||
use sammo\Session;
|
use sammo\Session;
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
use sammo\CentennialAllStarGrowthService;
|
|
||||||
use sammo\DB;
|
use sammo\DB;
|
||||||
use sammo\Enums\APIRecoveryType;
|
use sammo\Enums\APIRecoveryType;
|
||||||
use sammo\Enums\RankColumn;
|
use sammo\Enums\RankColumn;
|
||||||
@@ -99,10 +98,6 @@ class ResetStat extends \sammo\BaseAPI
|
|||||||
return 'NPC는 능력치 초기화를 할 수 없습니다.';
|
return 'NPC는 능력치 초기화를 할 수 없습니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CentennialAllStarGrowthService::isStatResetAllowed()) {
|
|
||||||
return '100기 올스타 장수는 능력치 초기화를 사용할 수 없습니다.';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
|||||||
@@ -62,13 +62,15 @@ class ResetTurnTime extends \sammo\BaseAPI
|
|||||||
}
|
}
|
||||||
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$turnTerm = abs($gameStor->getValue('turnterm'));
|
||||||
|
|
||||||
|
$currTurnTime = new DateTimeImmutable($general->getTurnTime());
|
||||||
|
|
||||||
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
|
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
|
||||||
UniqueConst::$hiddenSeed,
|
UniqueConst::$hiddenSeed,
|
||||||
'ResetTurnTime',
|
'ResetTurnTime',
|
||||||
$userID,
|
$userID,
|
||||||
$general->getAuxVar('nextTurnTimeBase') ?? $general->getTurnTick()
|
$general->getAuxVar('nextTurnTimeBase') ?? $general->getTurnTime()
|
||||||
)));
|
)));
|
||||||
|
|
||||||
$afterTurn = $rng->nextFloat1() * $turnTerm * 60;
|
$afterTurn = $rng->nextFloat1() * $turnTerm * 60;
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ use sammo\Enums\APIRecoveryType;
|
|||||||
use sammo\Enums\GeneralLiteQueryMode;
|
use sammo\Enums\GeneralLiteQueryMode;
|
||||||
use sammo\Enums\GeneralQueryMode;
|
use sammo\Enums\GeneralQueryMode;
|
||||||
use sammo\General;
|
use sammo\General;
|
||||||
use sammo\GameClock;
|
|
||||||
use sammo\GeneralLite;
|
use sammo\GeneralLite;
|
||||||
use sammo\Session;
|
use sammo\Session;
|
||||||
use sammo\Util;
|
use sammo\Util;
|
||||||
@@ -265,11 +264,8 @@ class GeneralList extends \sammo\BaseAPI
|
|||||||
'honorText' => fn ($rawGeneral) => getHonor($rawGeneral['experience']),
|
'honorText' => fn ($rawGeneral) => getHonor($rawGeneral['experience']),
|
||||||
'dedLevelText' => fn ($rawGeneral) => getDedLevelText($rawGeneral['dedlevel']),
|
'dedLevelText' => fn ($rawGeneral) => getDedLevelText($rawGeneral['dedlevel']),
|
||||||
//'0000-00-00 11:23';
|
//'0000-00-00 11:23';
|
||||||
'turntime' => fn ($rawGeneral) => GameClock::fromStorage($gameStor)
|
'turntime' => fn ($rawGeneral) => substr($rawGeneral['turntime'], 0, 19),
|
||||||
->formatTick(Util::toInt($rawGeneral['turntime'])),
|
'recent_war' => fn ($rawGeneral) => substr($rawGeneral['recent_war'], 0, 19),
|
||||||
'recent_war' => fn ($rawGeneral) => $rawGeneral['recent_war'] === null
|
|
||||||
? null
|
|
||||||
: GameClock::fromStorage($gameStor)->formatTick(Util::toInt($rawGeneral['recent_war'])),
|
|
||||||
'bill' => fn ($rawGeneral) => getBillByLevel($rawGeneral['dedlevel']),
|
'bill' => fn ($rawGeneral) => getBillByLevel($rawGeneral['dedlevel']),
|
||||||
'reservedCommand' => fn ($rawGeneral) => $reservedCommand[$rawGeneral['no']] ?? null,
|
'reservedCommand' => fn ($rawGeneral) => $reservedCommand[$rawGeneral['no']] ?? null,
|
||||||
'autorun_limit' => fn ($rawGeneral) => ($rawGeneral['aux'] ?? [])['autorun_limit'] ?? 0,
|
'autorun_limit' => fn ($rawGeneral) => ($rawGeneral['aux'] ?? [])['autorun_limit'] ?? 0,
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ use sammo\DB;
|
|||||||
use sammo\Enums\APIRecoveryType;
|
use sammo\Enums\APIRecoveryType;
|
||||||
use sammo\Enums\GeneralQueryMode;
|
use sammo\Enums\GeneralQueryMode;
|
||||||
use sammo\GameConst;
|
use sammo\GameConst;
|
||||||
use sammo\GameClock;
|
|
||||||
use sammo\General;
|
use sammo\General;
|
||||||
use sammo\Json;
|
use sammo\Json;
|
||||||
use sammo\KVStorage;
|
use sammo\KVStorage;
|
||||||
@@ -52,8 +51,7 @@ class GetReservedCommand extends \sammo\BaseAPI
|
|||||||
$nationID = $me['nation'];
|
$nationID = $me['nation'];
|
||||||
$limitState = checkLimit($me['refresh_score']);
|
$limitState = checkLimit($me['refresh_score']);
|
||||||
if ($limitState >= 2) {
|
if ($limitState >= 2) {
|
||||||
$limitTime = GameClock::fromStorage($gameStor)->formatTick(Util::toInt($me['turntime']), true);
|
return "접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 갱신 가능 시각 : {$me['turntime']})";
|
||||||
return "접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 갱신 가능 시각 : {$limitTime})";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$permission = checkSecretPermission($me);
|
$permission = checkSecretPermission($me);
|
||||||
|
|||||||
@@ -8,11 +8,6 @@ use sammo\Util;
|
|||||||
|
|
||||||
abstract class AbsFromUserPool extends AbsGeneralPool{
|
abstract class AbsFromUserPool extends AbsGeneralPool{
|
||||||
|
|
||||||
protected static function getCandidateWeight(array $info, int $owner): int|float
|
|
||||||
{
|
|
||||||
return array_sum($info['dex'] ?? []);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function occupyGeneralName(): bool
|
public function occupyGeneralName(): bool
|
||||||
{
|
{
|
||||||
$generalID = $this->getGeneralBuilder()->getGeneralID();
|
$generalID = $this->getGeneralBuilder()->getGeneralID();
|
||||||
@@ -30,9 +25,8 @@ abstract class AbsFromUserPool extends AbsGeneralPool{
|
|||||||
}
|
}
|
||||||
|
|
||||||
static public function pickGeneralFromPool(\MeekroDB $db, RandUtil $rng, int $owner, int $pickCnt, ?string $prefix=null):array{
|
static public function pickGeneralFromPool(\MeekroDB $db, RandUtil $rng, int $owner, int $pickCnt, ?string $prefix=null):array{
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$oNow = new \DateTimeImmutable();
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$now = $oNow->format('Y-m-d H:i:s');
|
||||||
$now = $clock->nowTick();
|
|
||||||
|
|
||||||
$db->update('select_pool', [
|
$db->update('select_pool', [
|
||||||
'reserved_until'=>null,
|
'reserved_until'=>null,
|
||||||
@@ -42,15 +36,17 @@ abstract class AbsFromUserPool extends AbsGeneralPool{
|
|||||||
$pool = [];
|
$pool = [];
|
||||||
foreach($db->query('SELECT id, unique_name, info FROM select_pool WHERE reserved_until IS NULL AND general_id IS NULL', $pickCnt) as $cand){
|
foreach($db->query('SELECT id, unique_name, info FROM select_pool WHERE reserved_until IS NULL AND general_id IS NULL', $pickCnt) as $cand){
|
||||||
$cand['info'] = Json::decode($cand['info']);
|
$cand['info'] = Json::decode($cand['info']);
|
||||||
$pool[] = [$cand, static::getCandidateWeight($cand['info'], $owner)];
|
$dexTotal = array_sum($cand['info']['dex']);
|
||||||
|
$pool[] = [$cand, $dexTotal];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(count($pool) < $pickCnt){
|
if(count($pool) < $pickCnt){
|
||||||
throw new \RuntimeException('pool 부족');
|
throw new \RuntimeException('pool 부족');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$result = [];
|
$result = [];
|
||||||
$validUntil = $now + GameClock::TICKS_PER_TURN * 2;
|
$validUntil = TimeUtil::nowAddMinutes(2 * abs($gameStor->turnterm));
|
||||||
while(count($result) < $pickCnt){
|
while(count($result) < $pickCnt){
|
||||||
$cand = $rng->choiceUsingWeightPair($pool);
|
$cand = $rng->choiceUsingWeightPair($pool);
|
||||||
$poolID = $cand['id'];
|
$poolID = $cand['id'];
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ abstract class AbsGeneralPool{
|
|||||||
* specialWar
|
* specialWar
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public function __construct(\MeekroDB $db, RandUtil $rng, array $info, int $validUntil)
|
public function __construct(\MeekroDB $db, RandUtil $rng, array $info, string $validUntil)
|
||||||
{
|
{
|
||||||
$this->db = $db;
|
$this->db = $db;
|
||||||
$this->info = $info;
|
$this->info = $info;
|
||||||
@@ -92,7 +92,7 @@ abstract class AbsGeneralPool{
|
|||||||
return $this->builder;
|
return $this->builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getValidUntil():int{
|
public function getValidUntil():string{
|
||||||
return $this->validUntil;
|
return $this->validUntil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+58
-59
@@ -146,35 +146,40 @@ abstract class Auction
|
|||||||
return $this->info;
|
return $this->info;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function shrinkCloseTick(?int $tick): ?string
|
public function shrinkCloseDate(?DateTimeInterface $date): ?string
|
||||||
{
|
{
|
||||||
|
if ($date === null) {
|
||||||
|
$date = new DateTimeImmutable();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info->closeDate = $date;
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
|
||||||
$this->info->closeTick = $tick ?? $clock->nowTick();
|
|
||||||
$db->update('ng_auction', $this->info->toArray('id'), 'id = %i', $this->info->id);
|
$db->update('ng_auction', $this->info->toArray('id'), 'id = %i', $this->info->id);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function extendLatestBidCloseTick(?int $tick): ?string
|
public function extendLatestBidCloseDate(?DateTimeInterface $date): ?string
|
||||||
{
|
{
|
||||||
if ($tick === null) {
|
if ($date === null) {
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$turnTerm = abs($gameStor->getValue('turnterm'));
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$date = $this->info->closeDate->add(TimeUtil::secondsToDateInterval(
|
||||||
$tick = $this->info->closeTick + $clock->ticksFromMinutes(
|
max(static::MIN_EXTENSION_MINUTES_PER_BID, $turnTerm * static::COEFF_EXTENSION_MINUTES_PER_BID) * 60
|
||||||
max(static::MIN_EXTENSION_MINUTES_PER_BID, $turnTerm * static::COEFF_EXTENSION_MINUTES_PER_BID)
|
));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if ($this->info->detail->availableLatestBidCloseTick !== null && $tick < $this->info->detail->availableLatestBidCloseTick) {
|
else{
|
||||||
|
$date = DateTimeImmutable::createFromInterface($date);
|
||||||
|
}
|
||||||
|
if ($this->info->detail->availableLatestBidCloseDate !== null && $date < $this->info->detail->availableLatestBidCloseDate) {
|
||||||
return '기간보다 짧습니다.';
|
return '기간보다 짧습니다.';
|
||||||
}
|
}
|
||||||
$this->info->detail->availableLatestBidCloseTick = $tick;
|
$this->info->detail->availableLatestBidCloseDate = $date;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function extendCloseTick(int $tick, bool $force = false): ?string
|
public function extendCloseDate(DateTimeInterface $date, bool $force = false): ?string
|
||||||
{
|
{
|
||||||
if (!$force) {
|
if (!$force) {
|
||||||
if ($this->info->detail->remainCloseDateExtensionCnt === null) {
|
if ($this->info->detail->remainCloseDateExtensionCnt === null) {
|
||||||
@@ -188,11 +193,12 @@ abstract class Auction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($tick < $this->info->closeTick) {
|
if ($date < $this->info->closeDate) {
|
||||||
return '종료 기간보다 짧습니다.';
|
return '종료 기간보다 짧습니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->info->closeTick = $tick;
|
$closeDate = DateTimeImmutable::createFromInterface($date);
|
||||||
|
$this->info->closeDate = $closeDate;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,13 +245,12 @@ abstract class Auction
|
|||||||
|
|
||||||
//TODO: 전역 알림이 나타나야한다. 일반 메시지보다는 중요하고, 메시지보단 약하게..
|
//TODO: 전역 알림이 나타나야한다. 일반 메시지보다는 중요하고, 메시지보단 약하게..
|
||||||
//TODO: 바로가기를 제공하는 편이 좋을 것 같다.
|
//TODO: 바로가기를 제공하는 편이 좋을 것 같다.
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
|
||||||
$msg = new Message(
|
$msg = new Message(
|
||||||
MessageType::private,
|
MessageType::private,
|
||||||
$src,
|
$src,
|
||||||
$dest,
|
$dest,
|
||||||
$reason,
|
$reason,
|
||||||
DateTime::createFromImmutable($clock->tickToDateTime($clock->nowTick())),
|
new DateTime(),
|
||||||
new DateTime('9999-12-31'),
|
new DateTime('9999-12-31'),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
@@ -270,12 +275,7 @@ abstract class Auction
|
|||||||
$db->update('ng_auction', $this->info->toArray('id'), 'id = %i', $this->info->id);
|
$db->update('ng_auction', $this->info->toArray('id'), 'id = %i', $this->info->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function bidInheritPoint(
|
private function bidInheritPoint(int $amount, \DateTimeImmutable $now, bool $tryExtendCloseDate): ?string
|
||||||
int $amount,
|
|
||||||
int $nowTick,
|
|
||||||
\DateTimeImmutable $nowDate,
|
|
||||||
bool $tryExtendCloseDate,
|
|
||||||
): ?string
|
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
@@ -311,7 +311,7 @@ abstract class Auction
|
|||||||
$general->getVar('owner'),
|
$general->getVar('owner'),
|
||||||
$general->getID(),
|
$general->getID(),
|
||||||
$amount,
|
$amount,
|
||||||
$nowDate,
|
$now,
|
||||||
new AuctionBidItemData(
|
new AuctionBidItemData(
|
||||||
$general->getVar('owner_name'),
|
$general->getVar('owner_name'),
|
||||||
$obfuscatedName,
|
$obfuscatedName,
|
||||||
@@ -324,16 +324,15 @@ abstract class Auction
|
|||||||
}
|
}
|
||||||
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$turnTerm = abs($gameStor->getValue('turnterm'));
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
|
||||||
|
|
||||||
if ($this->info->detail->availableLatestBidCloseTick !== null) {
|
if ($this->info->detail->availableLatestBidCloseDate !== null) {
|
||||||
$extendedCloseTick = $nowTick + $clock->ticksFromMinutes(
|
$extendedCloseDate = $now->add(TimeUtil::secondsToDateInterval(
|
||||||
max(static::MIN_EXTENSION_MINUTES_PER_BID, $turnTerm * static::COEFF_EXTENSION_MINUTES_PER_BID)
|
max(static::MIN_EXTENSION_MINUTES_PER_BID, $turnTerm * static::COEFF_EXTENSION_MINUTES_PER_BID) * 60
|
||||||
);
|
));
|
||||||
|
|
||||||
if ($extendedCloseTick > $this->info->closeTick && $this->info->closeTick < $this->info->detail->availableLatestBidCloseTick) {
|
if ($extendedCloseDate > $this->info->closeDate && $this->info->closeDate < $this->info->detail->availableLatestBidCloseDate) {
|
||||||
$this->extendCloseTick(min($extendedCloseTick, $this->info->detail->availableLatestBidCloseTick), true);
|
$this->extendCloseDate(min($extendedCloseDate, $this->info->detail->availableLatestBidCloseDate), true);
|
||||||
$this->applyDB();
|
$this->applyDB();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,16 +356,12 @@ abstract class Auction
|
|||||||
return '경매가 이미 끝났습니다.';
|
return '경매가 이미 끝났습니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
$db = DB::db();
|
$now = new \DateTimeImmutable();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
$nowTick = $clock->nowTick();
|
|
||||||
$nowDate = $clock->tickToDateTime($nowTick);
|
|
||||||
|
|
||||||
if ($auctionInfo->closeTick < $nowTick) {
|
if ($auctionInfo->closeDate < $now) {
|
||||||
return '경매가 이미 끝났습니다.';
|
return '경매가 이미 끝났습니다.';
|
||||||
}
|
}
|
||||||
if ($auctionInfo->openTick > $nowTick) {
|
if ($auctionInfo->openDate > $now) {
|
||||||
return '경매가 아직 시작되지 않았습니다.';
|
return '경매가 아직 시작되지 않았습니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,11 +377,13 @@ abstract class Auction
|
|||||||
|
|
||||||
|
|
||||||
if ($auctionInfo->reqResource === ResourceType::inheritancePoint) {
|
if ($auctionInfo->reqResource === ResourceType::inheritancePoint) {
|
||||||
return $this->bidInheritPoint($amount, $nowTick, $nowDate, $tryExtendCloseDate);
|
return $this->bidInheritPoint($amount, $now, $tryExtendCloseDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
//reqResource는 말 그대로 '구매자가 내야하는 자원'이다.
|
//reqResource는 말 그대로 '구매자가 내야하는 자원'이다.
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
|
||||||
$highestBid = $this->getHighestBid();
|
$highestBid = $this->getHighestBid();
|
||||||
if (!$auctionInfo->detail->isReverse) {
|
if (!$auctionInfo->detail->isReverse) {
|
||||||
if ($highestBid !== null && $amount <= $highestBid->amount) {
|
if ($highestBid !== null && $amount <= $highestBid->amount) {
|
||||||
@@ -424,7 +421,7 @@ abstract class Auction
|
|||||||
$general->getVar('owner'),
|
$general->getVar('owner'),
|
||||||
$general->getID(),
|
$general->getID(),
|
||||||
$amount,
|
$amount,
|
||||||
$nowDate,
|
$now,
|
||||||
new AuctionBidItemData(
|
new AuctionBidItemData(
|
||||||
$general->getVar('owner_name'),
|
$general->getVar('owner_name'),
|
||||||
$general->getName(),
|
$general->getName(),
|
||||||
@@ -439,13 +436,14 @@ abstract class Auction
|
|||||||
|
|
||||||
$general->increaseVar($resType->value, -$morePoint);
|
$general->increaseVar($resType->value, -$morePoint);
|
||||||
|
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$extendedCloseTick = $nowTick + $clock->ticksFromMinutes(
|
$turnTerm = abs($gameStor->getValue('turnterm'));
|
||||||
max(static::MIN_EXTENSION_MINUTES_PER_BID, $turnTerm * static::COEFF_EXTENSION_MINUTES_PER_BID)
|
$extendedCloseDate = $now->add(TimeUtil::secondsToDateInterval(
|
||||||
);
|
max(static::MIN_EXTENSION_MINUTES_PER_BID, $turnTerm * static::COEFF_EXTENSION_MINUTES_PER_BID) * 60
|
||||||
|
));
|
||||||
|
|
||||||
if ($extendedCloseTick > $this->info->closeTick) {
|
if ($extendedCloseDate > $this->info->closeDate) {
|
||||||
$this->extendCloseTick($extendedCloseTick, true);
|
$this->extendCloseDate($extendedCloseDate, true);
|
||||||
$this->applyDB();
|
$this->applyDB();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,10 +456,10 @@ abstract class Auction
|
|||||||
|
|
||||||
public function tryFinish(): ?bool
|
public function tryFinish(): ?bool
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
$now = new DateTimeImmutable();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
if ($now < $this->info->closeDate) {
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
return null;
|
||||||
if ($clock->nowTick() < $this->info->closeTick) return null;
|
}
|
||||||
|
|
||||||
//경매를 닫아야한다.
|
//경매를 닫아야한다.
|
||||||
$highestBid = $this->getHighestBid();
|
$highestBid = $this->getHighestBid();
|
||||||
@@ -471,15 +469,17 @@ abstract class Auction
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($highestBid->aux->tryExtendCloseDate) {
|
if ($highestBid->aux->tryExtendCloseDate) {
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$db = DB::db();
|
||||||
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$turnTerm = abs($gameStor->getValue('turnterm'));
|
||||||
|
|
||||||
//연장 요청이 있었다.
|
//연장 요청이 있었다.
|
||||||
$extendedCloseTick = $this->info->closeTick + $clock->ticksFromMinutes(
|
$extendedCloseDate = $this->info->closeDate->add(TimeUtil::secondsToDateInterval(
|
||||||
max(static::MIN_EXTENSION_MINUTES_BY_EXTENSION_QUERY, $turnTerm * static::COEFF_EXTENSION_MINUTES_BY_EXTENSION_QUERY)
|
max(static::MIN_EXTENSION_MINUTES_BY_EXTENSION_QUERY, $turnTerm * static::COEFF_EXTENSION_MINUTES_BY_EXTENSION_QUERY) * 60
|
||||||
);
|
));
|
||||||
|
|
||||||
if ($this->extendCloseTick($extendedCloseTick) === null) {
|
if ($this->extendCloseDate($extendedCloseDate) === null) {
|
||||||
$this->extendLatestBidCloseTick(null);
|
$this->extendLatestBidCloseDate(null);
|
||||||
$this->applyDB();
|
$this->applyDB();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -509,13 +509,12 @@ abstract class Auction
|
|||||||
|
|
||||||
//TODO: 전역 알림이 나타나야한다. 일반 메시지보다는 중요하고, 메시지보단 약하게..
|
//TODO: 전역 알림이 나타나야한다. 일반 메시지보다는 중요하고, 메시지보단 약하게..
|
||||||
//TODO: 바로가기를 제공하는 편이 좋을 것 같다.
|
//TODO: 바로가기를 제공하는 편이 좋을 것 같다.
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
|
||||||
$msg = new Message(
|
$msg = new Message(
|
||||||
MessageType::private,
|
MessageType::private,
|
||||||
$src,
|
$src,
|
||||||
$dest,
|
$dest,
|
||||||
$failReason,
|
$failReason,
|
||||||
DateTime::createFromImmutable($clock->tickToDateTime($clock->nowTick())),
|
new \DateTime(),
|
||||||
new \DateTime('9999-12-31'),
|
new \DateTime('9999-12-31'),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -56,11 +56,10 @@ abstract class AuctionBasicResource extends Auction
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$now = new \DateTimeImmutable();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$turnTerm = abs($gameStor->getValue('turnterm'));
|
||||||
$nowTick = $clock->nowTick();
|
$closeDate = $now->add(TimeUtil::secondsToDateInterval($closeTurnCnt * $turnTerm * 60));
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
|
||||||
$closeTick = $nowTick + GameClock::TICKS_PER_TURN * $closeTurnCnt;
|
|
||||||
|
|
||||||
$openResult = static::openAuction(new AuctionInfo(
|
$openResult = static::openAuction(new AuctionInfo(
|
||||||
null,
|
null,
|
||||||
@@ -69,8 +68,8 @@ abstract class AuctionBasicResource extends Auction
|
|||||||
"$amount",
|
"$amount",
|
||||||
$general->getId(),
|
$general->getId(),
|
||||||
$bidderRes,
|
$bidderRes,
|
||||||
$nowTick,
|
$now,
|
||||||
$closeTick,
|
$closeDate,
|
||||||
new AuctionInfoDetail(
|
new AuctionInfoDetail(
|
||||||
"{$hostResName} {$amount} 경매",
|
"{$hostResName} {$amount} 경매",
|
||||||
$general->getName(),
|
$general->getName(),
|
||||||
@@ -146,13 +145,12 @@ abstract class AuctionBasicResource extends Auction
|
|||||||
|
|
||||||
//TODO: 전역 알림이 나타나야한다. 일반 메시지보다는 중요하고, 메시지보단 약하게..
|
//TODO: 전역 알림이 나타나야한다. 일반 메시지보다는 중요하고, 메시지보단 약하게..
|
||||||
//TODO: 바로가기를 제공하는 편이 좋을 것 같다.
|
//TODO: 바로가기를 제공하는 편이 좋을 것 같다.
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage(DB::db(), 'game_env'));
|
|
||||||
$msg = new Message(
|
$msg = new Message(
|
||||||
MessageType::private,
|
MessageType::private,
|
||||||
$src,
|
$src,
|
||||||
$dest,
|
$dest,
|
||||||
"{$this->auctionID}번 {$hostResName} 경매에 입찰이 없어 취소되었습니다.",
|
"{$this->auctionID}번 {$hostResName} 경매에 입찰이 없어 취소되었습니다.",
|
||||||
\DateTime::createFromImmutable($clock->tickToDateTime($clock->nowTick())),
|
new \DateTime(),
|
||||||
new \DateTime('9999-12-31'),
|
new \DateTime('9999-12-31'),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
@@ -248,8 +246,14 @@ abstract class AuctionBasicResource extends Auction
|
|||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$turnTerm = $gameStor->getValue('turnterm');
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
if($turnTerm == -60){
|
||||||
$this->shrinkCloseTick($clock->nowTick() + GameClock::TICKS_PER_TURN);
|
$date = VarTurn60::fromDatetime(new \DateTimeImmutable())->addTurn(1)->toDateStr();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$date = (new DateTimeImmutable())->add(TimeUtil::secondsToDateInterval($turnTerm * 60));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->shrinkCloseDate($date);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -72,15 +72,17 @@ class AuctionUniqueItem extends Auction
|
|||||||
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
|
||||||
|
$now = new DateTimeImmutable();
|
||||||
|
|
||||||
[$turnTerm, $year, $month] = $gameStor->getValuesAsArray(['turnterm', 'year', 'month']);
|
[$turnTerm, $year, $month] = $gameStor->getValuesAsArray(['turnterm', 'year', 'month']);
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
$turnTerm = abs($turnTerm);
|
||||||
$nowTick = $clock->nowTick();
|
|
||||||
$closeTick = $nowTick + $clock->ticksFromMinutes(
|
$closeDate = $now->add(TimeUtil::secondsToDateInterval(
|
||||||
max(static::MIN_AUCTION_CLOSE_MINUTES, $turnTerm * static::COEFF_AUCTION_CLOSE_MINUTES)
|
max(static::MIN_AUCTION_CLOSE_MINUTES, $turnTerm * static::COEFF_AUCTION_CLOSE_MINUTES) * 60
|
||||||
);
|
));
|
||||||
$availableLatestBidCloseTick = $closeTick + $clock->ticksFromMinutes(
|
$availableLatestBidCloseDate = $closeDate->add(TimeUtil::secondsToDateInterval(
|
||||||
max(static::MIN_EXTENSION_MINUTES_LIMIT_BY_BID, $turnTerm * static::COEFF_EXTENSION_MINUTES_LIMIT_BY_BID)
|
max(static::MIN_EXTENSION_MINUTES_LIMIT_BY_BID, $turnTerm * static::COEFF_EXTENSION_MINUTES_LIMIT_BY_BID) * 60
|
||||||
);
|
));
|
||||||
|
|
||||||
$info = new AuctionInfo(
|
$info = new AuctionInfo(
|
||||||
null,
|
null,
|
||||||
@@ -89,8 +91,8 @@ class AuctionUniqueItem extends Auction
|
|||||||
$itemKey,
|
$itemKey,
|
||||||
$general->getID(),
|
$general->getID(),
|
||||||
ResourceType::inheritancePoint,
|
ResourceType::inheritancePoint,
|
||||||
$nowTick,
|
$now,
|
||||||
$closeTick,
|
$closeDate,
|
||||||
new AuctionInfoDetail(
|
new AuctionInfoDetail(
|
||||||
"{$item->getName()} 경매",
|
"{$item->getName()} 경매",
|
||||||
static::genObfuscatedName($general->getID()),
|
static::genObfuscatedName($general->getID()),
|
||||||
@@ -99,7 +101,7 @@ class AuctionUniqueItem extends Auction
|
|||||||
$startAmount,
|
$startAmount,
|
||||||
null,
|
null,
|
||||||
1,
|
1,
|
||||||
$availableLatestBidCloseTick,
|
$availableLatestBidCloseDate,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -265,23 +267,22 @@ class AuctionUniqueItem extends Auction
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($availableEquipUniqueCnt <= 0) {
|
if ($availableEquipUniqueCnt <= 0) {
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$turnTerm = abs($gameStor->getValue('turnterm'));
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
//제한에 걸렸다면 자동 연장
|
//제한에 걸렸다면 자동 연장
|
||||||
$extendedCloseTick = $this->info->closeTick + $clock->ticksFromMinutes(
|
$extendedCloseDate = $this->info->closeDate->add(TimeUtil::secondsToDateInterval(
|
||||||
max(static::MIN_EXTENSION_MINUTES_BY_EXTENSION_QUERY, $turnTerm * static::COEFF_EXTENSION_MINUTES_LIMIT_UNIQUE_CNT)
|
max(static::MIN_EXTENSION_MINUTES_BY_EXTENSION_QUERY, $turnTerm * static::COEFF_EXTENSION_MINUTES_LIMIT_UNIQUE_CNT) * 60
|
||||||
);
|
));
|
||||||
|
|
||||||
if($bidder->getID() != $this->info->hostGeneralID){
|
if($bidder->getID() != $this->info->hostGeneralID){
|
||||||
$this->setHostAsNeutral();
|
$this->setHostAsNeutral();
|
||||||
}
|
}
|
||||||
$this->extendCloseTick($extendedCloseTick, true);
|
$this->extendCloseDate($extendedCloseDate, true);
|
||||||
$this->extendLatestBidCloseTick(null);
|
$this->extendLatestBidCloseDate(null);
|
||||||
$this->applyDB();
|
$this->applyDB();
|
||||||
return '유니크 아이템 소유 제한 상태입니다. 종료 시간이 연장됩니다.';
|
return '유니크 아이템 소유 제한 상태입니다. 종료 시간이 연장됩니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
$isExtendCloseTickRequired = false;
|
$isExtendCloseDateRequired = false;
|
||||||
foreach (GameConst::$allItems as $itemType => $itemList) {
|
foreach (GameConst::$allItems as $itemType => $itemList) {
|
||||||
//아직은 그런 경우는 없지만 동일 유니크를 여러 부위에 장착할 수 있을지도 모름
|
//아직은 그런 경우는 없지만 동일 유니크를 여러 부위에 장착할 수 있을지도 모름
|
||||||
if (!key_exists($itemKey, $itemList)) {
|
if (!key_exists($itemKey, $itemList)) {
|
||||||
@@ -291,13 +292,13 @@ class AuctionUniqueItem extends Auction
|
|||||||
$ownItem = $general->getItem($itemType);
|
$ownItem = $general->getItem($itemType);
|
||||||
if ($ownItem->getRawClassName() == $itemKey) {
|
if ($ownItem->getRawClassName() == $itemKey) {
|
||||||
//FIXME: 이 경우에는 환불이 되던가 해야함.
|
//FIXME: 이 경우에는 환불이 되던가 해야함.
|
||||||
$isExtendCloseTickRequired = true;
|
$isExtendCloseDateRequired = true;
|
||||||
$reasons[] = '이미 그 유니크를 가지고 있습니다.';
|
$reasons[] = '이미 그 유니크를 가지고 있습니다.';
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$ownItem->isBuyable()) {
|
if (!$ownItem->isBuyable()) {
|
||||||
$isExtendCloseTickRequired = true;
|
$isExtendCloseDateRequired = true;
|
||||||
$reasons[] = '이미 다른 유니크를 가지고 있습니다.';
|
$reasons[] = '이미 다른 유니크를 가지고 있습니다.';
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -313,19 +314,18 @@ class AuctionUniqueItem extends Auction
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!$availableItemTypes) {
|
if (!$availableItemTypes) {
|
||||||
if ($isExtendCloseTickRequired) {
|
if ($isExtendCloseDateRequired) {
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$turnTerm = abs($gameStor->getValue('turnterm'));
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
|
||||||
//동일 부위 제한에 걸렸다면 자동 연장
|
//동일 부위 제한에 걸렸다면 자동 연장
|
||||||
$extendedCloseTick = $this->info->closeTick + $clock->ticksFromMinutes(
|
$extendedCloseDate = $this->info->closeDate->add(TimeUtil::secondsToDateInterval(
|
||||||
max(static::MIN_EXTENSION_MINUTES_LIMIT_BY_BID, $turnTerm * static::COEFF_EXTENSION_MINUTES_LIMIT_BY_BID)
|
max(static::MIN_EXTENSION_MINUTES_LIMIT_BY_BID, $turnTerm * static::COEFF_EXTENSION_MINUTES_LIMIT_BY_BID) * 60
|
||||||
);
|
));
|
||||||
|
|
||||||
if($bidder->getID() != $this->info->hostGeneralID){
|
if($bidder->getID() != $this->info->hostGeneralID){
|
||||||
$this->setHostAsNeutral();
|
$this->setHostAsNeutral();
|
||||||
}
|
}
|
||||||
$this->extendCloseTick($extendedCloseTick, true);
|
$this->extendCloseDate($extendedCloseDate, true);
|
||||||
$this->extendLatestBidCloseTick(null);
|
$this->extendLatestBidCloseDate(null);
|
||||||
$this->applyDB();
|
$this->applyDB();
|
||||||
}
|
}
|
||||||
return join(' ', $reasons);
|
return join(' ', $reasons);
|
||||||
|
|||||||
@@ -1,640 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace sammo;
|
|
||||||
|
|
||||||
use sammo\Scenario\GeneralBuilder;
|
|
||||||
|
|
||||||
final class CentennialAllStarGrowthService
|
|
||||||
{
|
|
||||||
public const POOL_CLASS = 'SPoolUnderU100';
|
|
||||||
public const AUX_KEY = 'event100_allstar';
|
|
||||||
public const TRAIT_UNLOCK_PROGRESS = 0.4;
|
|
||||||
public const NPC_PROGRESS_MULTIPLIER = 0.9;
|
|
||||||
|
|
||||||
private const STAT_KEYS = ['leadership', 'strength', 'intel'];
|
|
||||||
private const DEX_KEYS = ['dex1', 'dex2', 'dex3', 'dex4', 'dex5'];
|
|
||||||
|
|
||||||
public static function isActive(): bool
|
|
||||||
{
|
|
||||||
return GameConst::$targetGeneralPool === self::POOL_CLASS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function isStatResetAllowed(): bool
|
|
||||||
{
|
|
||||||
return !self::isActive();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function initialAux(array $targetInfo, ?array $userInitialStats = null): array
|
|
||||||
{
|
|
||||||
$granted = array_fill_keys(array_merge(self::STAT_KEYS, self::DEX_KEYS), 0);
|
|
||||||
if ($userInitialStats !== null) {
|
|
||||||
foreach (self::STAT_KEYS as $key) {
|
|
||||||
$initial = (int) ($userInitialStats[$key] ?? GameConst::$defaultStatMin);
|
|
||||||
$granted[$key] = max(0, $initial - min($initial, GameConst::$defaultStatMin));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
'targetId' => (string) ($targetInfo['uniqueName'] ?? ''),
|
|
||||||
'granted' => $granted,
|
|
||||||
'dexConsumed' => array_fill_keys(self::DEX_KEYS, 0),
|
|
||||||
'dexFloor' => array_fill_keys(self::DEX_KEYS, 0),
|
|
||||||
'progressMonth' => -1,
|
|
||||||
'milestone' => 0,
|
|
||||||
'naturalSpecialDomestic' => null,
|
|
||||||
'eventSpecialDomestic' => null,
|
|
||||||
'userInitialStats' => $userInitialStats,
|
|
||||||
'dexTargetRatio' => 1.0,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function attachInitialTarget(GeneralBuilder $builder, array $targetInfo): void
|
|
||||||
{
|
|
||||||
$builder->setAuxVar(self::AUX_KEY, self::initialAux($targetInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds an ordinary-user stat total while preserving the selected
|
|
||||||
* candidate's relative strengths as closely as integer stats allow.
|
|
||||||
*
|
|
||||||
* @return array{leadership:int,strength:int,intel:int}
|
|
||||||
*/
|
|
||||||
public static function calculateUserInitialStats(array $targetInfo): array
|
|
||||||
{
|
|
||||||
$targets = [];
|
|
||||||
$bases = [];
|
|
||||||
foreach (self::STAT_KEYS as $key) {
|
|
||||||
$target = min(
|
|
||||||
GameConst::$defaultStatMax,
|
|
||||||
max(0, (int) ($targetInfo[$key] ?? 0))
|
|
||||||
);
|
|
||||||
$targets[$key] = $target;
|
|
||||||
$bases[$key] = min($target, GameConst::$defaultStatMin);
|
|
||||||
}
|
|
||||||
|
|
||||||
$targetTotal = array_sum($targets);
|
|
||||||
$desiredTotal = min(GameConst::$defaultStatTotal, $targetTotal);
|
|
||||||
$baseTotal = array_sum($bases);
|
|
||||||
$capacityTotal = $targetTotal - $baseTotal;
|
|
||||||
if ($capacityTotal <= 0 || $desiredTotal <= $baseTotal) {
|
|
||||||
return $bases;
|
|
||||||
}
|
|
||||||
|
|
||||||
$ratio = ($desiredTotal - $baseTotal) / $capacityTotal;
|
|
||||||
$result = [];
|
|
||||||
$fractions = [];
|
|
||||||
foreach (self::STAT_KEYS as $idx => $key) {
|
|
||||||
$raw = $bases[$key] + ($targets[$key] - $bases[$key]) * $ratio;
|
|
||||||
$result[$key] = (int) floor($raw);
|
|
||||||
$fractions[] = [
|
|
||||||
'key' => $key,
|
|
||||||
'fraction' => $raw - $result[$key],
|
|
||||||
'order' => $idx,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
usort($fractions, static function (array $lhs, array $rhs): int {
|
|
||||||
$fractionOrder = $rhs['fraction'] <=> $lhs['fraction'];
|
|
||||||
return $fractionOrder !== 0 ? $fractionOrder : $lhs['order'] <=> $rhs['order'];
|
|
||||||
});
|
|
||||||
$remainder = $desiredTotal - array_sum($result);
|
|
||||||
foreach ($fractions as $fraction) {
|
|
||||||
if ($remainder <= 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$key = $fraction['key'];
|
|
||||||
if ($result[$key] >= $targets[$key]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$result[$key]++;
|
|
||||||
$remainder--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the event stat baseline that a newly selected target receives at
|
|
||||||
* the supplied game date. Organic growth can still leave the actual stat
|
|
||||||
* above this baseline.
|
|
||||||
*
|
|
||||||
* @return array{leadership:int,strength:int,intel:int}
|
|
||||||
*/
|
|
||||||
public static function calculateUserCurrentTargetStats(
|
|
||||||
array $targetInfo,
|
|
||||||
array $env
|
|
||||||
): array {
|
|
||||||
$initialStats = self::calculateUserInitialStats($targetInfo);
|
|
||||||
$progress = self::calculateProgress(
|
|
||||||
(int) $env['startyear'],
|
|
||||||
(int) $env['year'],
|
|
||||||
(int) $env['month']
|
|
||||||
);
|
|
||||||
$result = [];
|
|
||||||
foreach (self::STAT_KEYS as $key) {
|
|
||||||
$target = min(
|
|
||||||
GameConst::$maxLevel,
|
|
||||||
max(0, (int) ($targetInfo[$key] ?? 0))
|
|
||||||
);
|
|
||||||
$result[$key] = max(
|
|
||||||
$initialStats[$key],
|
|
||||||
CentennialAllStarGrowth::statFloor(
|
|
||||||
$target,
|
|
||||||
GameConst::$defaultStatMin,
|
|
||||||
$progress
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function prepareInitialUser(
|
|
||||||
GeneralBuilder $builder,
|
|
||||||
array $targetInfo
|
|
||||||
): void {
|
|
||||||
$initialStats = self::calculateUserInitialStats($targetInfo);
|
|
||||||
$builder->setStat(
|
|
||||||
$initialStats['leadership'],
|
|
||||||
$initialStats['strength'],
|
|
||||||
$initialStats['intel']
|
|
||||||
);
|
|
||||||
$builder->setAuxVar(
|
|
||||||
self::AUX_KEY,
|
|
||||||
self::initialAux($targetInfo, $initialStats)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Old 100th-season characters did not distinguish their form-entered
|
|
||||||
* initial stats from organic growth. Before their first reselection, treat
|
|
||||||
* the ordinary creation range as the replaceable initial allocation.
|
|
||||||
*/
|
|
||||||
public static function prepareLegacyUserReselection(General $general): void
|
|
||||||
{
|
|
||||||
$aux = $general->getAuxVar(self::AUX_KEY);
|
|
||||||
if (!is_array($aux) || is_array($aux['userInitialStats'] ?? null)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$granted = is_array($aux['granted'] ?? null)
|
|
||||||
? $aux['granted']
|
|
||||||
: array_fill_keys(array_merge(self::STAT_KEYS, self::DEX_KEYS), 0);
|
|
||||||
$legacyInitialStats = [];
|
|
||||||
foreach (self::STAT_KEYS as $key) {
|
|
||||||
$current = (int) $general->getVar($key);
|
|
||||||
$granted[$key] = self::calculateLegacyUserGrant(
|
|
||||||
$current,
|
|
||||||
(int) ($granted[$key] ?? 0)
|
|
||||||
);
|
|
||||||
$beforeEventGrant = max(
|
|
||||||
0,
|
|
||||||
$current - max(0, (int) ($aux['granted'][$key] ?? 0))
|
|
||||||
);
|
|
||||||
$legacyInitialStats[$key] = min(
|
|
||||||
$beforeEventGrant,
|
|
||||||
GameConst::$defaultStatMax
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$aux['granted'] = $granted;
|
|
||||||
$aux['userInitialStats'] = $legacyInitialStats;
|
|
||||||
$general->setAuxVar(self::AUX_KEY, $aux);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function calculateLegacyUserGrant(int $current, int $eventGrant): int
|
|
||||||
{
|
|
||||||
$eventGrant = max(0, $eventGrant);
|
|
||||||
$beforeEventGrant = max(0, $current - $eventGrant);
|
|
||||||
$replaceableInitialGrant = max(
|
|
||||||
0,
|
|
||||||
min($beforeEventGrant, GameConst::$defaultStatMax)
|
|
||||||
- min($beforeEventGrant, GameConst::$defaultStatMin)
|
|
||||||
);
|
|
||||||
return $eventGrant + $replaceableInitialGrant;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function calculateProgress(
|
|
||||||
int $startYear,
|
|
||||||
int $year,
|
|
||||||
int $month,
|
|
||||||
float $progressMultiplier = 1.0
|
|
||||||
): float {
|
|
||||||
if ($progressMultiplier < 0 || $progressMultiplier > 1) {
|
|
||||||
throw new \InvalidArgumentException('progress multiplier must be between 0 and 1');
|
|
||||||
}
|
|
||||||
return min(
|
|
||||||
1,
|
|
||||||
CentennialAllStarGrowth::progress($startYear, $year, $month)
|
|
||||||
* $progressMultiplier
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function calculateDexTargetFloor(
|
|
||||||
int $target,
|
|
||||||
array $env,
|
|
||||||
float $targetRatio = 1.0
|
|
||||||
): int {
|
|
||||||
if ($targetRatio < 0 || $targetRatio > 1) {
|
|
||||||
throw new \InvalidArgumentException('dex target ratio must be between 0 and 1');
|
|
||||||
}
|
|
||||||
$target = min(GameConst::$dexLimit, max(0, $target));
|
|
||||||
$scaledTarget = (int) floor($target * $targetRatio);
|
|
||||||
$progress = self::calculateProgress(
|
|
||||||
(int) $env['startyear'],
|
|
||||||
(int) $env['year'],
|
|
||||||
(int) $env['month']
|
|
||||||
);
|
|
||||||
return CentennialAllStarGrowth::dexFloor($scaledTarget, $progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mutates the General object but leaves persistence to the caller.
|
|
||||||
*
|
|
||||||
* @return array{progress:float,milestone:int,previousMilestone:int,targetChanged:bool,changed:bool}
|
|
||||||
*/
|
|
||||||
public static function applyTarget(
|
|
||||||
General $general,
|
|
||||||
array $targetInfo,
|
|
||||||
array $env,
|
|
||||||
float $progressMultiplier = 1.0,
|
|
||||||
float $dexTargetRatio = 1.0
|
|
||||||
): array
|
|
||||||
{
|
|
||||||
$startYear = (int) $env['startyear'];
|
|
||||||
$year = (int) $env['year'];
|
|
||||||
$month = (int) $env['month'];
|
|
||||||
$progress = self::calculateProgress(
|
|
||||||
$startYear,
|
|
||||||
$year,
|
|
||||||
$month,
|
|
||||||
$progressMultiplier
|
|
||||||
);
|
|
||||||
$progressMonth = (int) floor(
|
|
||||||
max(0, ($year - $startYear) * 12 + $month - 1)
|
|
||||||
* $progressMultiplier
|
|
||||||
);
|
|
||||||
$targetId = (string) ($targetInfo['uniqueName'] ?? '');
|
|
||||||
|
|
||||||
$aux = $general->getAuxVar(self::AUX_KEY);
|
|
||||||
if (!is_array($aux)) {
|
|
||||||
$aux = self::initialAux($targetInfo);
|
|
||||||
}
|
|
||||||
$granted = is_array($aux['granted'] ?? null)
|
|
||||||
? $aux['granted']
|
|
||||||
: array_fill_keys(array_merge(self::STAT_KEYS, self::DEX_KEYS), 0);
|
|
||||||
$targetChanged = ($aux['targetId'] ?? '') !== $targetId;
|
|
||||||
$dexConsumed = is_array($aux['dexConsumed'] ?? null)
|
|
||||||
? $aux['dexConsumed']
|
|
||||||
: array_fill_keys(self::DEX_KEYS, 0);
|
|
||||||
if ($targetChanged) {
|
|
||||||
$dexConsumed = array_fill_keys(self::DEX_KEYS, 0);
|
|
||||||
}
|
|
||||||
$dexFloor = is_array($aux['dexFloor'] ?? null)
|
|
||||||
? $aux['dexFloor']
|
|
||||||
: array_fill_keys(self::DEX_KEYS, 0);
|
|
||||||
$isUserTarget = is_array($aux['userInitialStats'] ?? null);
|
|
||||||
$nextUserInitialStats = $targetChanged && $isUserTarget
|
|
||||||
? self::calculateUserInitialStats($targetInfo)
|
|
||||||
: ($aux['userInitialStats'] ?? null);
|
|
||||||
$previousDexTargetRatio = is_numeric($aux['dexTargetRatio'] ?? null)
|
|
||||||
? (float) $aux['dexTargetRatio']
|
|
||||||
: 1.0;
|
|
||||||
$dexTargetRatioChanged = $previousDexTargetRatio !== $dexTargetRatio;
|
|
||||||
$userCurrentTargetStats = $isUserTarget
|
|
||||||
? self::calculateUserCurrentTargetStats($targetInfo, $env)
|
|
||||||
: null;
|
|
||||||
$changed = $dexTargetRatioChanged;
|
|
||||||
|
|
||||||
foreach (self::STAT_KEYS as $key) {
|
|
||||||
if (!array_key_exists($key, $targetInfo)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$target = min(GameConst::$maxLevel, max(0, (int) $targetInfo[$key]));
|
|
||||||
$floor = CentennialAllStarGrowth::statFloor(
|
|
||||||
$target,
|
|
||||||
GameConst::$defaultStatMin,
|
|
||||||
$progress
|
|
||||||
);
|
|
||||||
if ($userCurrentTargetStats !== null) {
|
|
||||||
$floor = $userCurrentTargetStats[$key];
|
|
||||||
}
|
|
||||||
$current = (int) $general->getVar($key);
|
|
||||||
if ($targetChanged) {
|
|
||||||
$result = CentennialAllStarGrowth::replaceTarget(
|
|
||||||
$current,
|
|
||||||
(int) ($granted[$key] ?? 0),
|
|
||||||
$floor
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$result = CentennialAllStarGrowth::advance(
|
|
||||||
$current,
|
|
||||||
(int) ($granted[$key] ?? 0),
|
|
||||||
$floor
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ($result['value'] !== $current) {
|
|
||||||
$general->updateVar($key, $result['value']);
|
|
||||||
$changed = true;
|
|
||||||
}
|
|
||||||
$granted[$key] = $result['granted'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$targetDex = $targetInfo['dex'] ?? [];
|
|
||||||
foreach (self::DEX_KEYS as $idx => $key) {
|
|
||||||
if (!array_key_exists($idx, $targetDex)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$floor = max(
|
|
||||||
0,
|
|
||||||
self::calculateDexTargetFloor(
|
|
||||||
(int) $targetDex[$idx],
|
|
||||||
$env,
|
|
||||||
$dexTargetRatio
|
|
||||||
) - max(0, (int) ($dexConsumed[$key] ?? 0))
|
|
||||||
);
|
|
||||||
$dexFloor[$key] = $floor;
|
|
||||||
$current = (int) $general->getVar($key);
|
|
||||||
if ($targetChanged || $dexTargetRatioChanged) {
|
|
||||||
$result = CentennialAllStarGrowth::replaceTarget(
|
|
||||||
$current,
|
|
||||||
(int) ($granted[$key] ?? 0),
|
|
||||||
$floor
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$result = CentennialAllStarGrowth::advance(
|
|
||||||
$current,
|
|
||||||
(int) ($granted[$key] ?? 0),
|
|
||||||
$floor
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ($result['value'] !== $current) {
|
|
||||||
$general->updateVar($key, $result['value']);
|
|
||||||
$changed = true;
|
|
||||||
}
|
|
||||||
$granted[$key] = $result['granted'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$oldEventSpecial = $aux['eventSpecialDomestic'] ?? null;
|
|
||||||
if ($targetChanged && $oldEventSpecial !== null
|
|
||||||
&& $general->getVar('special') === $oldEventSpecial
|
|
||||||
) {
|
|
||||||
$general->updateVar(
|
|
||||||
'special',
|
|
||||||
$aux['naturalSpecialDomestic'] ?? GameConst::$defaultSpecialDomestic
|
|
||||||
);
|
|
||||||
$changed = true;
|
|
||||||
$aux['eventSpecialDomestic'] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$targetSpecial = $targetInfo['specialDomestic'] ?? null;
|
|
||||||
if ($progress >= self::TRAIT_UNLOCK_PROGRESS && is_string($targetSpecial) && $targetSpecial !== '') {
|
|
||||||
if (($aux['naturalSpecialDomestic'] ?? null) === null) {
|
|
||||||
$aux['naturalSpecialDomestic'] = $general->getVar('special');
|
|
||||||
}
|
|
||||||
if ($general->getVar('special') !== $targetSpecial) {
|
|
||||||
$general->updateVar('special', $targetSpecial);
|
|
||||||
$changed = true;
|
|
||||||
}
|
|
||||||
$aux['eventSpecialDomestic'] = $targetSpecial;
|
|
||||||
}
|
|
||||||
|
|
||||||
$previousMilestone = (int) ($aux['milestone'] ?? 0);
|
|
||||||
$milestone = min(5, (int) floor($progress * 5 + 0.0000001));
|
|
||||||
$aux['targetId'] = $targetId;
|
|
||||||
$aux['granted'] = $granted;
|
|
||||||
$aux['dexConsumed'] = $dexConsumed;
|
|
||||||
$aux['dexFloor'] = $dexFloor;
|
|
||||||
$aux['progressMonth'] = max((int) ($aux['progressMonth'] ?? -1), $progressMonth);
|
|
||||||
$aux['milestone'] = max($previousMilestone, $milestone);
|
|
||||||
$aux['userInitialStats'] = $nextUserInitialStats;
|
|
||||||
$aux['dexTargetRatio'] = $dexTargetRatio;
|
|
||||||
$general->setAuxVar(self::AUX_KEY, $aux);
|
|
||||||
|
|
||||||
return [
|
|
||||||
'progress' => $progress,
|
|
||||||
'milestone' => $milestone,
|
|
||||||
'previousMilestone' => $previousMilestone,
|
|
||||||
'targetChanged' => $targetChanged,
|
|
||||||
'changed' => $changed || $targetChanged || $milestone > $previousMilestone,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function progressMultiplierFor(General $general): float
|
|
||||||
{
|
|
||||||
return self::progressMultiplierForNPCType($general->getNPCType());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function progressMultiplierForNPCType(int $npcType): float
|
|
||||||
{
|
|
||||||
return in_array($npcType, [3, 4], true)
|
|
||||||
? self::NPC_PROGRESS_MULTIPLIER
|
|
||||||
: 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function dexTargetRatioForNPCType(int $npcType): float
|
|
||||||
{
|
|
||||||
return in_array($npcType, [3, 4], true)
|
|
||||||
? GameConst::$centennialNpcDexTargetRatio
|
|
||||||
: 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function applyCurrentTargetToBuiltNPC(
|
|
||||||
\MeekroDB $db,
|
|
||||||
GeneralBuilder $builder,
|
|
||||||
array $targetInfo,
|
|
||||||
array $env
|
|
||||||
): ?array {
|
|
||||||
if (!self::isActive()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$general = General::createObjFromDB($builder->getGeneralID());
|
|
||||||
if (!in_array($general->getNPCType(), [3, 4], true)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
self::initializeGeneratedNPC($general, $targetInfo);
|
|
||||||
$result = self::applyTarget(
|
|
||||||
$general,
|
|
||||||
$targetInfo,
|
|
||||||
$env,
|
|
||||||
self::NPC_PROGRESS_MULTIPLIER,
|
|
||||||
GameConst::$centennialNpcDexTargetRatio
|
|
||||||
);
|
|
||||||
$general->applyDB($db);
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Keeps the ordinary M/G-general stat total while aligning its strong,
|
|
||||||
* middle, and weak stats with the selected all-star target. The target's
|
|
||||||
* creation-date growth floor is applied immediately afterwards.
|
|
||||||
*/
|
|
||||||
public static function initializeGeneratedNPC(
|
|
||||||
General $general,
|
|
||||||
array $targetInfo
|
|
||||||
): void {
|
|
||||||
$generatedStats = [];
|
|
||||||
foreach (self::STAT_KEYS as $key) {
|
|
||||||
$generatedStats[$key] = (int) $general->getVar($key);
|
|
||||||
}
|
|
||||||
$initialStats = self::calculateGeneratedNPCInitialStats(
|
|
||||||
$targetInfo,
|
|
||||||
$generatedStats
|
|
||||||
);
|
|
||||||
foreach (self::STAT_KEYS as $key) {
|
|
||||||
$general->updateVar($key, $initialStats[$key]);
|
|
||||||
}
|
|
||||||
foreach (self::DEX_KEYS as $key) {
|
|
||||||
$general->updateVar($key, 0);
|
|
||||||
}
|
|
||||||
$general->setAuxVar(self::AUX_KEY, self::initialAux($targetInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array<string, mixed> $targetInfo
|
|
||||||
* @param array{leadership:int,strength:int,intel:int} $generatedStats
|
|
||||||
* @return array{leadership:int,strength:int,intel:int}
|
|
||||||
*/
|
|
||||||
public static function calculateGeneratedNPCInitialStats(
|
|
||||||
array $targetInfo,
|
|
||||||
array $generatedStats
|
|
||||||
): array {
|
|
||||||
$targetOrder = self::STAT_KEYS;
|
|
||||||
$keyOrder = array_flip(self::STAT_KEYS);
|
|
||||||
usort(
|
|
||||||
$targetOrder,
|
|
||||||
static function (string $lhs, string $rhs) use ($targetInfo, $keyOrder): int {
|
|
||||||
$targetCompare = (int) ($targetInfo[$rhs] ?? 0)
|
|
||||||
<=> (int) ($targetInfo[$lhs] ?? 0);
|
|
||||||
return $targetCompare !== 0
|
|
||||||
? $targetCompare
|
|
||||||
: $keyOrder[$lhs] <=> $keyOrder[$rhs];
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$generatedValues = array_map(
|
|
||||||
static fn (string $key): int => (int) ($generatedStats[$key] ?? 0),
|
|
||||||
self::STAT_KEYS
|
|
||||||
);
|
|
||||||
rsort($generatedValues, SORT_NUMERIC);
|
|
||||||
|
|
||||||
$result = array_fill_keys(self::STAT_KEYS, 0);
|
|
||||||
foreach ($targetOrder as $idx => $key) {
|
|
||||||
$result[$key] = $generatedValues[$idx];
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves the event-backed part of a dex conversion with the converted
|
|
||||||
* value and consumes any guaranteed floor crossed by the source value.
|
|
||||||
* This keeps the monthly floor from refilling points already converted.
|
|
||||||
*/
|
|
||||||
public static function reconcileDexConversion(
|
|
||||||
General $general,
|
|
||||||
string $sourceKey,
|
|
||||||
string $destinationKey,
|
|
||||||
int $sourceBefore,
|
|
||||||
int $sourceAfter,
|
|
||||||
int $destinationBefore,
|
|
||||||
int $destinationAfter,
|
|
||||||
float $convertCoeff
|
|
||||||
): void {
|
|
||||||
if (!in_array($sourceKey, self::DEX_KEYS, true)
|
|
||||||
|| !in_array($destinationKey, self::DEX_KEYS, true)
|
|
||||||
|| $sourceKey === $destinationKey
|
|
||||||
) {
|
|
||||||
throw new \InvalidArgumentException('invalid dex conversion keys');
|
|
||||||
}
|
|
||||||
if ($convertCoeff < 0 || $convertCoeff > 1) {
|
|
||||||
throw new \InvalidArgumentException('dex conversion coefficient must be between 0 and 1');
|
|
||||||
}
|
|
||||||
|
|
||||||
$sourceDecrease = max(0, $sourceBefore - $sourceAfter);
|
|
||||||
$destinationIncrease = max(0, $destinationAfter - $destinationBefore);
|
|
||||||
if ($sourceDecrease === 0 && $destinationIncrease === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$aux = $general->getAuxVar(self::AUX_KEY);
|
|
||||||
if (!is_array($aux)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$granted = is_array($aux['granted'] ?? null)
|
|
||||||
? $aux['granted']
|
|
||||||
: array_fill_keys(array_merge(self::STAT_KEYS, self::DEX_KEYS), 0);
|
|
||||||
$dexConsumed = is_array($aux['dexConsumed'] ?? null)
|
|
||||||
? $aux['dexConsumed']
|
|
||||||
: array_fill_keys(self::DEX_KEYS, 0);
|
|
||||||
$dexFloor = is_array($aux['dexFloor'] ?? null)
|
|
||||||
? $aux['dexFloor']
|
|
||||||
: [];
|
|
||||||
|
|
||||||
$sourceGrantedBefore = min(
|
|
||||||
max(0, $sourceBefore),
|
|
||||||
max(0, (int) ($granted[$sourceKey] ?? 0))
|
|
||||||
);
|
|
||||||
/*
|
|
||||||
* A dex value can contain both organic and event-backed points. Split
|
|
||||||
* the actual command deltas by their share of the source total instead
|
|
||||||
* of consuming either bucket first. This keeps the combined ownership
|
|
||||||
* stable when conversion and target reselection are interleaved.
|
|
||||||
*/
|
|
||||||
$eventGrantRemoved = $sourceBefore > 0
|
|
||||||
? intdiv($sourceDecrease * $sourceGrantedBefore, $sourceBefore)
|
|
||||||
: 0;
|
|
||||||
$sourceGrantedAfter = max(0, $sourceGrantedBefore - $eventGrantRemoved);
|
|
||||||
|
|
||||||
$destinationGrantedBefore = min(
|
|
||||||
max(0, $destinationBefore),
|
|
||||||
max(0, (int) ($granted[$destinationKey] ?? 0))
|
|
||||||
);
|
|
||||||
$eventGrantTransferred = $sourceBefore > 0
|
|
||||||
? intdiv($destinationIncrease * $sourceGrantedBefore, $sourceBefore)
|
|
||||||
: 0;
|
|
||||||
$eventGrantTransferred = min(
|
|
||||||
$destinationIncrease,
|
|
||||||
$eventGrantRemoved,
|
|
||||||
$eventGrantTransferred
|
|
||||||
);
|
|
||||||
$granted[$sourceKey] = $sourceGrantedAfter;
|
|
||||||
$granted[$destinationKey] = min(
|
|
||||||
max(0, $destinationAfter),
|
|
||||||
$destinationGrantedBefore + $eventGrantTransferred
|
|
||||||
);
|
|
||||||
|
|
||||||
$sourceFloor = max(
|
|
||||||
0,
|
|
||||||
(int) ($dexFloor[$sourceKey] ?? $sourceBefore)
|
|
||||||
);
|
|
||||||
$gapBefore = max(0, $sourceFloor - $sourceBefore);
|
|
||||||
$gapAfter = max(0, $sourceFloor - $sourceAfter);
|
|
||||||
$dexConsumed[$sourceKey] = max(
|
|
||||||
0,
|
|
||||||
(int) ($dexConsumed[$sourceKey] ?? 0)
|
|
||||||
+ max(0, $gapAfter - $gapBefore)
|
|
||||||
);
|
|
||||||
|
|
||||||
$aux['granted'] = $granted;
|
|
||||||
$aux['dexConsumed'] = $dexConsumed;
|
|
||||||
$general->setAuxVar(self::AUX_KEY, $aux);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function recordableValue(General $general, string $key): int
|
|
||||||
{
|
|
||||||
$aux = $general->getAuxVar(self::AUX_KEY);
|
|
||||||
$granted = is_array($aux) && is_array($aux['granted'] ?? null)
|
|
||||||
? (int) ($aux['granted'][$key] ?? 0)
|
|
||||||
: 0;
|
|
||||||
return CentennialAllStarGrowth::recordableValue((int) $general->getVar($key), $granted);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function recordableRawValue(array $general, string $key): int
|
|
||||||
{
|
|
||||||
$aux = Json::decode($general['aux'] ?? '{}');
|
|
||||||
$eventAux = is_array($aux[self::AUX_KEY] ?? null) ? $aux[self::AUX_KEY] : [];
|
|
||||||
$granted = is_array($eventAux['granted'] ?? null)
|
|
||||||
? (int) ($eventAux['granted'][$key] ?? 0)
|
|
||||||
: 0;
|
|
||||||
return CentennialAllStarGrowth::recordableValue((int) ($general[$key] ?? 0), $granted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,6 @@ use function \sammo\tryUniqueItemLottery;
|
|||||||
|
|
||||||
use \sammo\Constraint\ConstraintHelper;
|
use \sammo\Constraint\ConstraintHelper;
|
||||||
use sammo\StaticEventHandler;
|
use sammo\StaticEventHandler;
|
||||||
use sammo\CentennialAllStarGrowthService;
|
|
||||||
|
|
||||||
class che_숙련전환 extends Command\GeneralCommand
|
class che_숙련전환 extends Command\GeneralCommand
|
||||||
{
|
{
|
||||||
@@ -158,7 +157,6 @@ class che_숙련전환 extends Command\GeneralCommand
|
|||||||
$logger = $general->getLogger();
|
$logger = $general->getLogger();
|
||||||
|
|
||||||
$srcDex = $general->getVar('dex' . $this->srcArmType);
|
$srcDex = $general->getVar('dex' . $this->srcArmType);
|
||||||
$destDex = $general->getVar('dex' . $this->destArmType);
|
|
||||||
$cutDex = Util::toInt($srcDex * static::$decreaseCoeff);
|
$cutDex = Util::toInt($srcDex * static::$decreaseCoeff);
|
||||||
$cutDexText = number_format($cutDex);
|
$cutDexText = number_format($cutDex);
|
||||||
$addDex = Util::toInt($cutDex * static::$convertCoeff);
|
$addDex = Util::toInt($cutDex * static::$convertCoeff);
|
||||||
@@ -166,19 +164,6 @@ class che_숙련전환 extends Command\GeneralCommand
|
|||||||
|
|
||||||
$general->increaseVar('dex' . $this->srcArmType, -$cutDex);
|
$general->increaseVar('dex' . $this->srcArmType, -$cutDex);
|
||||||
$general->increaseVar('dex' . $this->destArmType, $addDex);
|
$general->increaseVar('dex' . $this->destArmType, $addDex);
|
||||||
// 100기 이벤트 지급분을 목적 숙련으로 옮기고 소비한 성장 하한은 다시 채우지 않는다.
|
|
||||||
if (CentennialAllStarGrowthService::isActive()) {
|
|
||||||
CentennialAllStarGrowthService::reconcileDexConversion(
|
|
||||||
$general,
|
|
||||||
'dex' . $this->srcArmType,
|
|
||||||
'dex' . $this->destArmType,
|
|
||||||
$srcDex,
|
|
||||||
$general->getVar('dex' . $this->srcArmType),
|
|
||||||
$destDex,
|
|
||||||
$general->getVar('dex' . $this->destArmType),
|
|
||||||
static::$convertCoeff
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$josaUl = JosaUtil::pick($cutDex, '을');
|
$josaUl = JosaUtil::pick($cutDex, '을');
|
||||||
$josaRo = JosaUtil::pick($addDex, '로');
|
$josaRo = JosaUtil::pick($addDex, '로');
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ use \sammo\Util;
|
|||||||
use \sammo\JosaUtil;
|
use \sammo\JosaUtil;
|
||||||
use \sammo\General;
|
use \sammo\General;
|
||||||
use \sammo\ActionLogger;
|
use \sammo\ActionLogger;
|
||||||
use \sammo\CentennialAllStarGrowthService;
|
|
||||||
use \sammo\GameConst;
|
use \sammo\GameConst;
|
||||||
use \sammo\LastTurn;
|
use \sammo\LastTurn;
|
||||||
use \sammo\GameUnitConst;
|
use \sammo\GameUnitConst;
|
||||||
@@ -191,12 +190,6 @@ class che_인재탐색 extends Command\GeneralCommand
|
|||||||
$newNPC->fillRemainSpecAsRandom($pickTypeList, $avgGen, $env);
|
$newNPC->fillRemainSpecAsRandom($pickTypeList, $avgGen, $env);
|
||||||
|
|
||||||
$newNPC->build($this->env);
|
$newNPC->build($this->env);
|
||||||
CentennialAllStarGrowthService::applyCurrentTargetToBuiltNPC(
|
|
||||||
$db,
|
|
||||||
$newNPC,
|
|
||||||
$pickedNPC->getInfo(),
|
|
||||||
$this->env
|
|
||||||
);
|
|
||||||
$pickedNPC->occupyGeneralName();
|
$pickedNPC->occupyGeneralName();
|
||||||
$npcName = $newNPC->getGeneralName();
|
$npcName = $newNPC->getGeneralName();
|
||||||
$josaRa = JosaUtil::pick($npcName, '라');
|
$josaRa = JosaUtil::pick($npcName, '라');
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ class che_발령 extends Command\NationCommand
|
|||||||
$destGeneral->getLogger()->pushGeneralActionLog("<Y>{$generalName}</>에 의해 <G><b>{$destCityName}</b></>{$josaRo} 발령됐습니다. <1>$date</>");
|
$destGeneral->getLogger()->pushGeneralActionLog("<Y>{$generalName}</>에 의해 <G><b>{$destCityName}</b></>{$josaRo} 발령됐습니다. <1>$date</>");
|
||||||
|
|
||||||
$yearMonth = Util::joinYearMonth($this->env['year'], $this->env['month']);
|
$yearMonth = Util::joinYearMonth($this->env['year'], $this->env['month']);
|
||||||
if (cutTurn($general->getTurnTick(), $this->env['turnterm']) != cutTurn($destGeneral->getTurnTick(), $this->env['turnterm'])) {
|
if (cutTurn($general->getTurnTime(), $this->env['turnterm']) != cutTurn($destGeneral->getTurnTime(), $this->env['turnterm'])) {
|
||||||
$yearMonth += 1;
|
$yearMonth += 1;
|
||||||
}
|
}
|
||||||
$destGeneral->setAuxVar('last발령', $yearMonth);
|
$destGeneral->setAuxVar('last발령', $yearMonth);
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ class che_불가침제의 extends Command\NationCommand
|
|||||||
|
|
||||||
$now = new \DateTime($date);
|
$now = new \DateTime($date);
|
||||||
$validUntil = new \DateTime($date);
|
$validUntil = new \DateTime($date);
|
||||||
$validMinutes = max(30, $env['turnterm'] * 3);
|
$validMinutes = max(30, abs($env['turnterm']) * 3);
|
||||||
$validUntil->add(new \DateInterval("PT{$validMinutes}M"));
|
$validUntil->add(new \DateInterval("PT{$validMinutes}M"));
|
||||||
|
|
||||||
$josaWa = JosaUtil::pick($nationName, '와');
|
$josaWa = JosaUtil::pick($nationName, '와');
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ class che_불가침파기제의 extends Command\NationCommand{
|
|||||||
|
|
||||||
$now = new \DateTime($date);
|
$now = new \DateTime($date);
|
||||||
$validUntil = new \DateTime($date);
|
$validUntil = new \DateTime($date);
|
||||||
$validMinutes = max(30, $env['turnterm']*3);
|
$validMinutes = max(30, abs($env['turnterm'])*3);
|
||||||
$validUntil->add(new \DateInterval("PT{$validMinutes}M"));
|
$validUntil->add(new \DateInterval("PT{$validMinutes}M"));
|
||||||
|
|
||||||
$msg = new DiplomaticMessage(
|
$msg = new DiplomaticMessage(
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ use \sammo\Util;
|
|||||||
use \sammo\JosaUtil;
|
use \sammo\JosaUtil;
|
||||||
use \sammo\General;
|
use \sammo\General;
|
||||||
use \sammo\ActionLogger;
|
use \sammo\ActionLogger;
|
||||||
use \sammo\CentennialAllStarGrowthService;
|
|
||||||
use \sammo\GameConst;
|
use \sammo\GameConst;
|
||||||
use \sammo\LastTurn;
|
use \sammo\LastTurn;
|
||||||
use \sammo\GameUnitConst;
|
use \sammo\GameUnitConst;
|
||||||
@@ -161,12 +160,6 @@ class che_의병모집 extends Command\NationCommand
|
|||||||
$newNPC->fillRemainSpecAsRandom($pickTypeList, $avgGen, $env);
|
$newNPC->fillRemainSpecAsRandom($pickTypeList, $avgGen, $env);
|
||||||
|
|
||||||
$newNPC->build($this->env);
|
$newNPC->build($this->env);
|
||||||
CentennialAllStarGrowthService::applyCurrentTargetToBuiltNPC(
|
|
||||||
$db,
|
|
||||||
$newNPC,
|
|
||||||
$pickedNPC->getInfo(),
|
|
||||||
$this->env
|
|
||||||
);
|
|
||||||
$pickedNPC->occupyGeneralName();
|
$pickedNPC->occupyGeneralName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ class che_종전제의 extends Command\NationCommand{
|
|||||||
|
|
||||||
$now = new \DateTime($date);
|
$now = new \DateTime($date);
|
||||||
$validUntil = new \DateTime($date);
|
$validUntil = new \DateTime($date);
|
||||||
$validMinutes = max(30, $env['turnterm']*3);
|
$validMinutes = max(30, abs($env['turnterm'])*3);
|
||||||
$validUntil->add(new \DateInterval("PT{$validMinutes}M"));
|
$validUntil->add(new \DateInterval("PT{$validMinutes}M"));
|
||||||
|
|
||||||
$msg = new DiplomaticMessage(
|
$msg = new DiplomaticMessage(
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ class che_천도 extends Command\NationCommand
|
|||||||
$nationID = $general->getNationID();
|
$nationID = $general->getNationID();
|
||||||
$nationStor = \sammo\KVStorage::getStorage(DB::db(), $nationID, 'nation_env');
|
$nationStor = \sammo\KVStorage::getStorage(DB::db(), $nationID, 'nation_env');
|
||||||
|
|
||||||
$nationStor->last천도Trial = [$general->getVar('officer_level'), $general->getTurnTick()];
|
$nationStor->last천도Trial = [$general->getVar('officer_level'), $general->getTurnTime()];
|
||||||
|
|
||||||
if ($lastTurn->getCommand() != $commandName || $lastTurn->getArg() !== $this->arg) {
|
if ($lastTurn->getCommand() != $commandName || $lastTurn->getArg() !== $this->arg) {
|
||||||
$this->setResultTurn(new LastTurn(
|
$this->setResultTurn(new LastTurn(
|
||||||
|
|||||||
@@ -0,0 +1,204 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace sammo\Command\Nation;
|
||||||
|
|
||||||
|
use \sammo\DB;
|
||||||
|
use \sammo\Util;
|
||||||
|
use \sammo\JosaUtil;
|
||||||
|
use \sammo\General;
|
||||||
|
use \sammo\DummyGeneral;
|
||||||
|
use \sammo\ActionLogger;
|
||||||
|
use \sammo\GameConst;
|
||||||
|
use \sammo\LastTurn;
|
||||||
|
use \sammo\GameUnitConst;
|
||||||
|
use \sammo\Command;
|
||||||
|
|
||||||
|
use \sammo\Constraint\Constraint;
|
||||||
|
use \sammo\Constraint\ConstraintHelper;
|
||||||
|
use sammo\Enums\GeneralQueryMode;
|
||||||
|
use sammo\StaticEventHandler;
|
||||||
|
|
||||||
|
use function sammo\pullGeneralCommand;
|
||||||
|
use function sammo\pushGeneralCommand;
|
||||||
|
|
||||||
|
class che_행동지시 extends Command\NationCommand
|
||||||
|
{
|
||||||
|
static protected $actionName = '행동 지시';
|
||||||
|
static public $reqArg = true;
|
||||||
|
|
||||||
|
protected function argTest(): bool
|
||||||
|
{
|
||||||
|
if ($this->arg === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!key_exists('isPull', $this->arg)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!key_exists('amount', $this->arg)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!key_exists('destGeneralID', $this->arg)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$isPull = $this->arg['isPull'];
|
||||||
|
$amount = $this->arg['amount'];
|
||||||
|
$destGeneralID = $this->arg['destGeneralID'];
|
||||||
|
if (!is_numeric($amount)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($amount <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_bool($isPull)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_int($destGeneralID)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($destGeneralID <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$amount = Util::clamp($amount, 1, 5);
|
||||||
|
|
||||||
|
$this->arg = [
|
||||||
|
'isPull' => $isPull,
|
||||||
|
'amount' => $amount,
|
||||||
|
'destGeneralID' => $destGeneralID
|
||||||
|
];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function init()
|
||||||
|
{
|
||||||
|
$general = $this->generalObj;
|
||||||
|
|
||||||
|
$this->setCity();
|
||||||
|
$this->setNation();
|
||||||
|
|
||||||
|
$this->minConditionConstraints = [
|
||||||
|
ConstraintHelper::NotBeNeutral(),
|
||||||
|
ConstraintHelper::OccupiedCity(),
|
||||||
|
ConstraintHelper::BeChief(),
|
||||||
|
ConstraintHelper::SuppliedCity(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function initWithArg()
|
||||||
|
{
|
||||||
|
$destGeneral = General::createObjFromDB($this->arg['destGeneralID']);
|
||||||
|
$this->setDestGeneral($destGeneral);
|
||||||
|
|
||||||
|
if($this->arg['destGeneralID'] == $this->getGeneral()->getID()){
|
||||||
|
$this->fullConditionConstraints=[
|
||||||
|
ConstraintHelper::AlwaysFail('본인입니다')
|
||||||
|
];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->fullConditionConstraints = [
|
||||||
|
ConstraintHelper::NotBeNeutral(),
|
||||||
|
ConstraintHelper::OccupiedCity(),
|
||||||
|
ConstraintHelper::BeChief(),
|
||||||
|
ConstraintHelper::SuppliedCity(),
|
||||||
|
ConstraintHelper::ExistsDestGeneral(),
|
||||||
|
ConstraintHelper::FriendlyDestGeneral()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCost(): array
|
||||||
|
{
|
||||||
|
return [0, 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPreReqTurn(): int
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPostReqTurn(): int
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBrief(): string
|
||||||
|
{
|
||||||
|
$isPull = $this->arg['isPull'];
|
||||||
|
$amount = $this->arg['amount'];
|
||||||
|
$actSpecificName = $isPull ? '당기기' : '미루기';
|
||||||
|
$destGeneral = $this->destGeneralObj;
|
||||||
|
return "【{$destGeneral->getName()}】 {$amount}턴 {$actSpecificName}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function run(\Sammo\RandUtil $rng): bool
|
||||||
|
{
|
||||||
|
if (!$this->hasFullConditionMet()) {
|
||||||
|
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
|
||||||
|
$general = $this->generalObj;
|
||||||
|
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||||
|
|
||||||
|
$isPull = $this->arg['isPull'];
|
||||||
|
$amount = $this->arg['amount'];
|
||||||
|
$destGeneral = $this->destGeneralObj;
|
||||||
|
|
||||||
|
if($isPull){
|
||||||
|
pullGeneralCommand($destGeneral->getID(), $amount);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
pushGeneralCommand($destGeneral->getID(), $amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
$logger = $general->getLogger();
|
||||||
|
|
||||||
|
$actDestText = $isPull ? '당겼습니다.' : '미루었습니다.';
|
||||||
|
$actText = $isPull ? '당기도록' : '미루도록';
|
||||||
|
$destGeneral->getLogger()->pushGeneralActionLog("<Y>{$general->getName()}</>의 지시로 <C>{$amount}</>턴을 {$actDestText}", ActionLogger::PLAIN);
|
||||||
|
$logger->pushGeneralActionLog("<Y>{$destGeneral->getName()}</>에게 <C>{$amount}</>턴을 {$actText} 지시했습니다. <1>$date</>");
|
||||||
|
|
||||||
|
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||||
|
StaticEventHandler::handleEvent($this->generalObj, $this->destGeneralObj, $this::class, $this->env, $this->arg ?? []);
|
||||||
|
$general->applyDB($db);
|
||||||
|
$destGeneral->applyDB($db);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exportJSVars(): array
|
||||||
|
{
|
||||||
|
$db = DB::db();
|
||||||
|
$nationID = $this->getNationID();
|
||||||
|
$troops = Util::convertArrayToDict($db->query('SELECT * FROM troop WHERE nation=%i', $nationID), 'troop_leader');
|
||||||
|
$destRawGenerals = Util::convertArrayToDict($db->queryAllLists('SELECT no,name,officer_level,npc,gold,rice,leadership,strength,intel,city,crew,train,atmos,troop FROM general WHERE nation = %i ORDER BY npc,binary(name)', $nationID), 0);
|
||||||
|
|
||||||
|
if($destRawGenerals){
|
||||||
|
foreach ($db->queryAllLists(
|
||||||
|
'SELECT general_id, brief FROM general_turn WHERE general_id IN %li AND turn_idx = 0',
|
||||||
|
array_keys($destRawGenerals)
|
||||||
|
) as [$generalID, $brief]) {
|
||||||
|
if (!key_exists($generalID, $destRawGenerals)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$destRawGenerals[$generalID][] = $brief;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return [
|
||||||
|
'procRes' => [
|
||||||
|
'troops' => $troops,
|
||||||
|
'generals' => array_values($destRawGenerals),
|
||||||
|
'generalsKey' => ['no', 'name', 'officerLevel', 'npc', 'gold', 'rice', 'leadership', 'strength', 'intel', 'cityID', 'crew', 'train', 'atmos', 'troopID', 'turn0Brief'],
|
||||||
|
'cities' => \sammo\JSOptionsForCities(),
|
||||||
|
'amountGuide' => [1, 2, 3, 4, 5],
|
||||||
|
'minAmount' => 1,
|
||||||
|
'maxAmount' => 5,
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,9 +2,11 @@
|
|||||||
|
|
||||||
namespace sammo\DTO;
|
namespace sammo\DTO;
|
||||||
|
|
||||||
|
use LDTO\Attr\Convert;
|
||||||
use LDTO\Attr\JsonString;
|
use LDTO\Attr\JsonString;
|
||||||
use LDTO\Attr\NullIsUndefined;
|
use LDTO\Attr\NullIsUndefined;
|
||||||
use LDTO\Attr\RawName;
|
use LDTO\Attr\RawName;
|
||||||
|
use LDTO\Converter\DateTimeConverter;
|
||||||
use sammo\Enums\AuctionType;
|
use sammo\Enums\AuctionType;
|
||||||
use sammo\Enums\ResourceType;
|
use sammo\Enums\ResourceType;
|
||||||
|
|
||||||
@@ -21,10 +23,12 @@ class AuctionInfo extends \LDTO\DTO
|
|||||||
#[RawName('req_resource')]
|
#[RawName('req_resource')]
|
||||||
public ResourceType $reqResource,
|
public ResourceType $reqResource,
|
||||||
|
|
||||||
#[RawName('open_tick')]
|
#[RawName('open_date')]
|
||||||
public int $openTick,
|
#[Convert(DateTimeConverter::class)]
|
||||||
#[RawName('close_tick')]
|
public \DateTimeImmutable $openDate,
|
||||||
public int $closeTick,
|
#[RawName('close_date')]
|
||||||
|
#[Convert(DateTimeConverter::class)]
|
||||||
|
public \DateTimeImmutable $closeDate,
|
||||||
|
|
||||||
#[JsonString]
|
#[JsonString]
|
||||||
public AuctionInfoDetail $detail,
|
public AuctionInfoDetail $detail,
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
namespace sammo\DTO;
|
namespace sammo\DTO;
|
||||||
|
|
||||||
|
use LDTO\Attr\Convert;
|
||||||
use LDTO\Attr\NullIsUndefined;
|
use LDTO\Attr\NullIsUndefined;
|
||||||
|
use LDTO\Converter\DateTimeConverter;
|
||||||
|
|
||||||
class AuctionInfoDetail extends \LDTO\DTO
|
class AuctionInfoDetail extends \LDTO\DTO
|
||||||
{
|
{
|
||||||
@@ -19,7 +21,8 @@ class AuctionInfoDetail extends \LDTO\DTO
|
|||||||
#[NullIsUndefined]
|
#[NullIsUndefined]
|
||||||
public ?int $remainCloseDateExtensionCnt,
|
public ?int $remainCloseDateExtensionCnt,
|
||||||
#[NullIsUndefined]
|
#[NullIsUndefined]
|
||||||
public ?int $availableLatestBidCloseTick,
|
#[Convert(DateTimeConverter::class)]
|
||||||
|
public ?\DateTimeImmutable $availableLatestBidCloseDate,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
namespace sammo\DTO;
|
namespace sammo\DTO;
|
||||||
|
|
||||||
|
use LDTO\Attr\Convert;
|
||||||
use LDTO\Attr\NullIsUndefined;
|
use LDTO\Attr\NullIsUndefined;
|
||||||
use LDTO\Attr\RawName;
|
use LDTO\Attr\RawName;
|
||||||
|
use LDTO\Converter\DateTimeConverter;
|
||||||
|
|
||||||
class GeneralAccessLog extends \LDTO\DTO
|
class GeneralAccessLog extends \LDTO\DTO
|
||||||
{
|
{
|
||||||
@@ -18,7 +20,8 @@ class GeneralAccessLog extends \LDTO\DTO
|
|||||||
public ?int $userID,
|
public ?int $userID,
|
||||||
|
|
||||||
#[RawName('last_refresh')]
|
#[RawName('last_refresh')]
|
||||||
public ?int $lastRefresh,
|
#[Convert(DateTimeConverter::class)]
|
||||||
|
public \DateTimeImmutable $lastRefresh,
|
||||||
|
|
||||||
public int $refresh,
|
public int $refresh,
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class DiplomaticMessage extends Message{
|
|||||||
$this->validDiplomacy = false;
|
$this->validDiplomacy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->validUntil < $this->date){
|
if($this->validUntil < (new \DateTime())){
|
||||||
$this->validDiplomacy = false;
|
$this->validDiplomacy = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace sammo\Event\Action;
|
|
||||||
|
|
||||||
use sammo\ActionLogger;
|
|
||||||
use sammo\CentennialAllStarGrowthService;
|
|
||||||
use sammo\DB;
|
|
||||||
use sammo\General;
|
|
||||||
use sammo\Json;
|
|
||||||
|
|
||||||
class AdvanceCentennialAllStar extends \sammo\Event\Action
|
|
||||||
{
|
|
||||||
public function run(array $env)
|
|
||||||
{
|
|
||||||
if (!CentennialAllStarGrowthService::isActive()) {
|
|
||||||
return [__CLASS__, 0];
|
|
||||||
}
|
|
||||||
|
|
||||||
$db = DB::db();
|
|
||||||
$updated = 0;
|
|
||||||
foreach ($db->query(
|
|
||||||
'SELECT general.no, select_pool.info
|
|
||||||
FROM general
|
|
||||||
JOIN select_pool ON select_pool.general_id = general.no'
|
|
||||||
) as $row) {
|
|
||||||
$general = General::createObjFromDB((int) $row['no']);
|
|
||||||
$targetInfo = Json::decode($row['info']);
|
|
||||||
$result = CentennialAllStarGrowthService::applyTarget(
|
|
||||||
$general,
|
|
||||||
$targetInfo,
|
|
||||||
$env,
|
|
||||||
CentennialAllStarGrowthService::progressMultiplierFor($general),
|
|
||||||
CentennialAllStarGrowthService::dexTargetRatioForNPCType(
|
|
||||||
$general->getNPCType()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($result['milestone'] > $result['previousMilestone']) {
|
|
||||||
$percent = $result['milestone'] * 20;
|
|
||||||
$general->getLogger()->pushGeneralActionLog(
|
|
||||||
"<L>올스타 동조율</>이 <C>{$percent}%</>에 도달했습니다!",
|
|
||||||
ActionLogger::PLAIN
|
|
||||||
);
|
|
||||||
$general->getLogger()->pushGeneralHistoryLog(
|
|
||||||
"<L>올스타 동조율 {$percent}% 달성</>"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ($general->applyDB($db)) {
|
|
||||||
$updated++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [__CLASS__, $updated];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,6 @@ namespace sammo\Event\Action;
|
|||||||
use \sammo\GameConst;
|
use \sammo\GameConst;
|
||||||
use \sammo\Util;
|
use \sammo\Util;
|
||||||
use \sammo\DB;
|
use \sammo\DB;
|
||||||
use sammo\CentennialAllStarGrowthService;
|
|
||||||
use sammo\LiteHashDRBG;
|
use sammo\LiteHashDRBG;
|
||||||
use sammo\RandUtil;
|
use sammo\RandUtil;
|
||||||
use sammo\UniqueConst;
|
use sammo\UniqueConst;
|
||||||
@@ -36,8 +35,7 @@ class CreateManyNPC extends \sammo\Event\Action
|
|||||||
)));
|
)));
|
||||||
|
|
||||||
$result = [];
|
$result = [];
|
||||||
$db = DB::db();
|
foreach (pickGeneralFromPool(DB::db(), $rng, 0, $cnt) as $pickedNPC) {
|
||||||
foreach (pickGeneralFromPool($db, $rng, 0, $cnt) as $pickedNPC) {
|
|
||||||
$age = $rng->nextRangeInt(20, 25);
|
$age = $rng->nextRangeInt(20, 25);
|
||||||
$birthYear = $env['year'] - $age;
|
$birthYear = $env['year'] - $age;
|
||||||
$deathYear = $env['year'] + $rng->nextRangeInt(10, 50);
|
$deathYear = $env['year'] + $rng->nextRangeInt(10, 50);
|
||||||
@@ -52,12 +50,6 @@ class CreateManyNPC extends \sammo\Event\Action
|
|||||||
}
|
}
|
||||||
$newNPC->fillRemainSpecAsZero($env);
|
$newNPC->fillRemainSpecAsZero($env);
|
||||||
$newNPC->build($env);
|
$newNPC->build($env);
|
||||||
CentennialAllStarGrowthService::applyCurrentTargetToBuiltNPC(
|
|
||||||
$db,
|
|
||||||
$newNPC,
|
|
||||||
$pickedNPC->getInfo(),
|
|
||||||
$env
|
|
||||||
);
|
|
||||||
$pickedNPC->occupyGeneralName();
|
$pickedNPC->occupyGeneralName();
|
||||||
$result[] = [
|
$result[] = [
|
||||||
$newNPC->getGeneralName(), $newNPC->getGeneralID()
|
$newNPC->getGeneralName(), $newNPC->getGeneralID()
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ class RaiseInvader extends \sammo\Event\Action
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$gameStor->setValue('isunited', 1);
|
$gameStor->setValue('isunited', 1);
|
||||||
|
|
||||||
$turnterm = $gameStor->turnterm;
|
$turnterm = abs($gameStor->turnterm);
|
||||||
$generalCnt = $db->queryFirstField('SELECT count(*) FROM general');
|
$generalCnt = $db->queryFirstField('SELECT count(*) FROM general');
|
||||||
|
|
||||||
if ($npcEachCount < 0) {
|
if ($npcEachCount < 0) {
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ class UpdateNationLevel extends \sammo\Event\Action
|
|||||||
if ($levelDiff) {
|
if ($levelDiff) {
|
||||||
//유니크 아이템 하나 돌리자
|
//유니크 아이템 하나 돌리자
|
||||||
$targetKillTurn = $env['killturn'];
|
$targetKillTurn = $env['killturn'];
|
||||||
$targetKillTurn -= 24 * 60 / $env['turnterm'];
|
$targetKillTurn -= 24 * 60 / abs($env['turnterm']);
|
||||||
$nationGenIDList = $db->queryFirstColumn(
|
$nationGenIDList = $db->queryFirstColumn(
|
||||||
'SELECT no FROM general WHERE nation = %i AND killturn >= %i AND npc < 2',
|
'SELECT no FROM general WHERE nation = %i AND killturn >= %i AND npc < 2',
|
||||||
$nation['nation'],
|
$nation['nation'],
|
||||||
|
|||||||
@@ -184,10 +184,6 @@ class GameConstBase
|
|||||||
/** @var array 선택할 수 없으나 게임 내에 유효한 장수 내정 특기 */
|
/** @var array 선택할 수 없으나 게임 내에 유효한 장수 내정 특기 */
|
||||||
public static $optionalSpecialDomestic = [
|
public static $optionalSpecialDomestic = [
|
||||||
'None',
|
'None',
|
||||||
'che_event_귀병', 'che_event_신산', 'che_event_환술', 'che_event_집중', 'che_event_신중',
|
|
||||||
'che_event_반계', 'che_event_보병', 'che_event_궁병', 'che_event_기병', 'che_event_공성',
|
|
||||||
'che_event_돌격', 'che_event_무쌍', 'che_event_견고', 'che_event_위압', 'che_event_저격',
|
|
||||||
'che_event_필살', 'che_event_징병', 'che_event_의술', 'che_event_격노', 'che_event_척사',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/** @var string 기본 전투 특기 */
|
/** @var string 기본 전투 특기 */
|
||||||
@@ -388,6 +384,7 @@ class GameConstBase
|
|||||||
'che_포상',
|
'che_포상',
|
||||||
'che_몰수',
|
'che_몰수',
|
||||||
'che_부대탈퇴지시',
|
'che_부대탈퇴지시',
|
||||||
|
'che_행동지시',
|
||||||
],
|
],
|
||||||
'외교' => [
|
'외교' => [
|
||||||
'che_물자원조',
|
'che_물자원조',
|
||||||
@@ -420,8 +417,6 @@ class GameConstBase
|
|||||||
public static $retirementYear = 80;
|
public static $retirementYear = 80;
|
||||||
|
|
||||||
public static $targetGeneralPool = 'RandomNameGeneral';
|
public static $targetGeneralPool = 'RandomNameGeneral';
|
||||||
/** @var float 100기 올스타 NPC의 원본 목표 대비 최종 숙련 비율 */
|
|
||||||
public static $centennialNpcDexTargetRatio = 0.4;
|
|
||||||
public static $generalPoolAllowOption = ['stat', 'ego', 'picture'];
|
public static $generalPoolAllowOption = ['stat', 'ego', 'picture'];
|
||||||
|
|
||||||
public static $randGenFirstName = [
|
public static $randGenFirstName = [
|
||||||
|
|||||||
+29
-66
@@ -281,13 +281,23 @@ class General extends GeneralBase implements iAction
|
|||||||
$this->calcCache[$cacheKey] = $result;
|
$this->calcCache[$cacheKey] = $result;
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
$tickDiff = Util::toInt($this->getVar('turntime')) - Util::toInt($this->getVar('recent_war'));
|
$recwar = new \DateTimeImmutable($this->getVar('recent_war'));
|
||||||
if ($tickDiff <= 0) {
|
$turnNow = new \DateTimeImmutable($this->getVar('turntime'));
|
||||||
|
|
||||||
|
$secDiff = TimeUtil::DateIntervalToSeconds($recwar->diff($turnNow));
|
||||||
|
|
||||||
|
if ($secDiff <= 0) {
|
||||||
$this->calcCache[$cacheKey] = 0;
|
$this->calcCache[$cacheKey] = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = intdiv($tickDiff, GameClock::TICKS_PER_TURN);
|
if($turnTerm == -60){
|
||||||
|
$turnDiff = VarTurn60::calcTurnDiff($recwar, $turnNow);
|
||||||
|
$this->calcCache[$cacheKey] = $turnDiff;
|
||||||
|
return $turnDiff;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = intdiv(Util::toInt($secDiff), 60 * $turnTerm);
|
||||||
$this->calcCache[$cacheKey] = $result;
|
$this->calcCache[$cacheKey] = $result;
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
@@ -1042,64 +1052,18 @@ class General extends GeneralBase implements iAction
|
|||||||
|
|
||||||
/** @var Map<GeneralAccessLog,int>|null */
|
/** @var Map<GeneralAccessLog,int>|null */
|
||||||
$rawAccessLog = null;
|
$rawAccessLog = null;
|
||||||
$rankColumnValues = array_map(fn (\BackedEnum $e) => $e->value, $rankColumn);
|
|
||||||
|
|
||||||
if (!$accessLogColumn) {
|
if (!$accessLogColumn) {
|
||||||
if ($rankColumn) {
|
$rawGeneral = $db->queryFirstRow('SELECT %l FROM general WHERE no = %i', Util::formatListOfBackticks($column), $generalID);
|
||||||
$rawGeneral = $db->queryFirstRow(
|
|
||||||
'SELECT %l, (
|
|
||||||
SELECT GROUP_CONCAT(
|
|
||||||
CONCAT(`type`, CHAR(61), `value`)
|
|
||||||
ORDER BY `type`
|
|
||||||
)
|
|
||||||
FROM rank_data
|
|
||||||
WHERE rank_data.general_id = general.no
|
|
||||||
AND `type` IN %ls
|
|
||||||
) AS `_rank_values`
|
|
||||||
FROM general WHERE no = %i',
|
|
||||||
Util::formatListOfBackticks($column),
|
|
||||||
$rankColumnValues,
|
|
||||||
$generalID
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$rawGeneral = $db->queryFirstRow(
|
|
||||||
'SELECT %l FROM general WHERE no = %i',
|
|
||||||
Util::formatListOfBackticks($column),
|
|
||||||
$generalID
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if ($rankColumn) {
|
$rawGeneral = $db->queryFirstRow(
|
||||||
$rawGeneral = $db->queryFirstRow(
|
'SELECT %l, %l FROM `general` LEFT JOIN general_access_log
|
||||||
'SELECT %l, %l, (
|
ON general.no = general_access_log.general_id WHERE no = %i',
|
||||||
SELECT GROUP_CONCAT(
|
Util::formatListOfBackticks($column),
|
||||||
CONCAT(`type`, CHAR(61), `value`)
|
Util::formatListOfBackticks($accessLogColumn),
|
||||||
ORDER BY `type`
|
$generalID
|
||||||
)
|
);
|
||||||
FROM rank_data
|
|
||||||
WHERE rank_data.general_id = general.no
|
|
||||||
AND `type` IN %ls
|
|
||||||
) AS `_rank_values`
|
|
||||||
FROM `general` LEFT JOIN general_access_log
|
|
||||||
ON general.no = general_access_log.general_id
|
|
||||||
WHERE no = %i',
|
|
||||||
Util::formatListOfBackticks($column),
|
|
||||||
Util::formatListOfBackticks($accessLogColumn),
|
|
||||||
$rankColumnValues,
|
|
||||||
$generalID
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$rawGeneral = $db->queryFirstRow(
|
|
||||||
'SELECT %l, %l FROM `general` LEFT JOIN general_access_log
|
|
||||||
ON general.no = general_access_log.general_id WHERE no = %i',
|
|
||||||
Util::formatListOfBackticks($column),
|
|
||||||
Util::formatListOfBackticks($accessLogColumn),
|
|
||||||
$generalID
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($accessLogColumn) {
|
|
||||||
$rawAccessLog = new Map();
|
$rawAccessLog = new Map();
|
||||||
foreach ($accessLogColumn as $accessLogKey) {
|
foreach ($accessLogColumn as $accessLogKey) {
|
||||||
if (!key_exists($accessLogKey->value, $rawGeneral)) {
|
if (!key_exists($accessLogKey->value, $rawGeneral)) {
|
||||||
@@ -1119,16 +1083,15 @@ class General extends GeneralBase implements iAction
|
|||||||
|
|
||||||
$rawRankValues = new Map();
|
$rawRankValues = new Map();
|
||||||
if ($rankColumn) {
|
if ($rankColumn) {
|
||||||
$rawRankPairs = $rawGeneral['_rank_values'];
|
$rawValue = $db->queryAllLists(
|
||||||
foreach ($rawRankPairs === null || $rawRankPairs === ''
|
'SELECT `type`, `value` FROM rank_data WHERE general_id = %i AND `type` IN %ls',
|
||||||
? []
|
$generalID,
|
||||||
: explode(',', $rawRankPairs) as $rawRankPair
|
array_map(fn (\BackedEnum $e) => $e->value, $rankColumn)
|
||||||
) {
|
);
|
||||||
[$rawRankType, $rankValue] = explode('=', $rawRankPair, 2);
|
foreach ($rawValue as [$rawRankType, $rankValue]) {
|
||||||
$rankType = RankColumn::from($rawRankType);
|
$rankType = RankColumn::tryFrom($rawRankType);
|
||||||
$rawRankValues->put($rankType, (int) $rankValue);
|
$rawRankValues->put($rankType, $rankValue);
|
||||||
}
|
}
|
||||||
unset($rawGeneral['_rank_values']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+19
-16
@@ -302,7 +302,7 @@ class GeneralAI
|
|||||||
$this->calcWarRoute();
|
$this->calcWarRoute();
|
||||||
$troopCandidate = [];
|
$troopCandidate = [];
|
||||||
|
|
||||||
$chiefTurn = cutTurn($this->general->getTurnTick(), $this->env['turnterm']);
|
$chiefTurn = cutTurn($this->general->getTurnTime(), $this->env['turnterm']);
|
||||||
$yearMonth = Util::joinYearMonth($this->env['year'], $this->env['month']);
|
$yearMonth = Util::joinYearMonth($this->env['year'], $this->env['month']);
|
||||||
|
|
||||||
foreach ($this->troopLeaders as $troopLeader) {
|
foreach ($this->troopLeaders as $troopLeader) {
|
||||||
@@ -319,7 +319,7 @@ class GeneralAI
|
|||||||
|
|
||||||
$last발령 = $troopLeader->getAuxVar('last발령');
|
$last발령 = $troopLeader->getAuxVar('last발령');
|
||||||
if ($last발령) {
|
if ($last발령) {
|
||||||
$leaderTurn = cutTurn($troopLeader->getTurnTick(), $this->env['turnterm']);
|
$leaderTurn = cutTurn($troopLeader->getTurnTime(), $this->env['turnterm']);
|
||||||
$compYearMonth = $yearMonth;
|
$compYearMonth = $yearMonth;
|
||||||
if ($chiefTurn < $leaderTurn) {
|
if ($chiefTurn < $leaderTurn) {
|
||||||
$compYearMonth += 1;
|
$compYearMonth += 1;
|
||||||
@@ -405,7 +405,7 @@ class GeneralAI
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$chiefTurn = cutTurn($this->general->getTurnTick(), $this->env['turnterm']);
|
$chiefTurn = cutTurn($this->general->getTurnTime(), $this->env['turnterm']);
|
||||||
$yearMonth = Util::joinYearMonth($this->env['year'], $this->env['month']);
|
$yearMonth = Util::joinYearMonth($this->env['year'], $this->env['month']);
|
||||||
|
|
||||||
$troopCandidate = [];
|
$troopCandidate = [];
|
||||||
@@ -428,7 +428,7 @@ class GeneralAI
|
|||||||
|
|
||||||
$last발령 = $troopLeader->getAuxVar('last발령');
|
$last발령 = $troopLeader->getAuxVar('last발령');
|
||||||
if ($last발령) {
|
if ($last발령) {
|
||||||
$leaderTurn = cutTurn($troopLeader->getTurnTick(), $this->env['turnterm']);
|
$leaderTurn = cutTurn($troopLeader->getTurnTime(), $this->env['turnterm']);
|
||||||
$compYearMonth = $yearMonth;
|
$compYearMonth = $yearMonth;
|
||||||
if ($chiefTurn < $leaderTurn) {
|
if ($chiefTurn < $leaderTurn) {
|
||||||
$compYearMonth += 1;
|
$compYearMonth += 1;
|
||||||
@@ -586,8 +586,8 @@ class GeneralAI
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$generalTurnTime = $userGeneral->getTurnTick();
|
$generalTurnTime = $userGeneral->getTurnTime();
|
||||||
$troopTurnTime = $troopLeader->getTurnTick();
|
$troopTurnTime = $troopLeader->getTurnTime();
|
||||||
|
|
||||||
if ($generalTurnTime < $troopTurnTime) { //NOTE: 어차피 수뇌 턴이 제일 빠르다
|
if ($generalTurnTime < $troopTurnTime) { //NOTE: 어차피 수뇌 턴이 제일 빠르다
|
||||||
$generalCadidates[$generalID] = $userGeneral;
|
$generalCadidates[$generalID] = $userGeneral;
|
||||||
@@ -782,7 +782,7 @@ class GeneralAI
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
key_exists($troopLeader->getCityID(), $this->supplyCities) &&
|
key_exists($troopLeader->getCityID(), $this->supplyCities) &&
|
||||||
$this->troopLeaders[$troopID]->getTurnTick() < $lostGeneral->getTurnTick()
|
$this->troopLeaders[$troopID]->getTurnTime() < $lostGeneral->getTurnTime()
|
||||||
) {
|
) {
|
||||||
//이미 탈출 가능한 부대를 탔다
|
//이미 탈출 가능한 부대를 탔다
|
||||||
continue;
|
continue;
|
||||||
@@ -1980,13 +1980,13 @@ class GeneralAI
|
|||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$nationStor = KVStorage::getStorage($db, $general->getNationID(), 'nation_env');
|
$nationStor = KVStorage::getStorage($db, $general->getNationID(), 'nation_env');
|
||||||
$turnTerm = $this->env['turnterm'];
|
$turnTerm = abs($this->env['turnterm']);
|
||||||
|
|
||||||
//천도를 한턴 넣었다면 계속 넣는다.
|
//천도를 한턴 넣었다면 계속 넣는다.
|
||||||
if ($lastTurn->getCommand() === '천도' && $lastTurn->getArg()['destCityID'] != $this->nation['capital']) {
|
if ($lastTurn->getCommand() === '천도' && $lastTurn->getArg()['destCityID'] != $this->nation['capital']) {
|
||||||
$cmd = buildNationCommandClass('che_천도', $this->general, $this->env, $lastTurn, $lastTurn->getArg());
|
$cmd = buildNationCommandClass('che_천도', $this->general, $this->env, $lastTurn, $lastTurn->getArg());
|
||||||
if ($cmd->hasFullConditionMet()) {
|
if ($cmd->hasFullConditionMet()) {
|
||||||
$nationStor->last천도Trial = [$general->getVar('officer_level'), $general->getTurnTick()];
|
$nationStor->last천도Trial = [$general->getVar('officer_level'), $general->getTurnTime()];
|
||||||
$this->reqUpdateInstance = true;
|
$this->reqUpdateInstance = true;
|
||||||
return $cmd;
|
return $cmd;
|
||||||
}
|
}
|
||||||
@@ -1995,9 +1995,12 @@ class GeneralAI
|
|||||||
$lastTrial = $nationStor->last천도Trial;
|
$lastTrial = $nationStor->last천도Trial;
|
||||||
if ($lastTrial) {
|
if ($lastTrial) {
|
||||||
[$lastTrialLevel, $lastTrialTurnTime] = $lastTrial;
|
[$lastTrialLevel, $lastTrialTurnTime] = $lastTrial;
|
||||||
$timeDiffTick = abs($general->getTurnTick() - Util::toInt($lastTrialTurnTime));
|
$timeDiffSeconds = TimeUtil::DateIntervalToSeconds(
|
||||||
if ($timeDiffTick < intdiv(GameClock::TICKS_PER_TURN, 2)
|
date_create_immutable($lastTrialTurnTime)->diff(
|
||||||
&& $lastTrialLevel !== $general->getVar('officer_level')) { //0.5Turn
|
date_create_immutable($general->getTurnTime())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if ($timeDiffSeconds < $turnTerm * 30 && $lastTrialLevel !== $general->getVar('officer_level')) { //0.5Turn
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2106,7 +2109,7 @@ class GeneralAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$nationStor->last천도Trial = [$general->getVar('officer_level'), $general->getTurnTick()];
|
$nationStor->last천도Trial = [$general->getVar('officer_level'), $general->getTurnTime()];
|
||||||
$this->reqUpdateInstance = true;
|
$this->reqUpdateInstance = true;
|
||||||
return $cmd;
|
return $cmd;
|
||||||
}
|
}
|
||||||
@@ -3131,7 +3134,7 @@ class GeneralAI
|
|||||||
$rawCity = $db->queryFirstRow('SELECT * FROM city WHERE city = %i', $this->general->getCityID());
|
$rawCity = $db->queryFirstRow('SELECT * FROM city WHERE city = %i', $this->general->getCityID());
|
||||||
$this->general->setRawCity($rawCity);
|
$this->general->setRawCity($rawCity);
|
||||||
}
|
}
|
||||||
if (in_array($this->general->getRawCity()['level'], [5, 6])) {
|
if (!in_array($this->general->getRawCity()['level'], [5, 6])) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3712,7 +3715,7 @@ class GeneralAI
|
|||||||
$this->updateInstance();
|
$this->updateInstance();
|
||||||
|
|
||||||
//특별 메세지 있는 경우 출력
|
//특별 메세지 있는 경우 출력
|
||||||
$term = $this->env['turnterm'];
|
$term = abs($this->env['turnterm']);
|
||||||
if ($general->getVar('npcmsg') && $this->rng->nextBool(GameConst::$npcMessageFreqByDay * $term / (60 * 24))) {
|
if ($general->getVar('npcmsg') && $this->rng->nextBool(GameConst::$npcMessageFreqByDay * $term / (60 * 24))) {
|
||||||
$src = new MessageTarget(
|
$src = new MessageTarget(
|
||||||
$general->getID(),
|
$general->getID(),
|
||||||
@@ -3982,7 +3985,7 @@ class GeneralAI
|
|||||||
|
|
||||||
$userChiefCnt = 0;
|
$userChiefCnt = 0;
|
||||||
|
|
||||||
$minUserKillturn = $this->env['killturn'] - Util::toInt(240 / $this->env['turnterm']);
|
$minUserKillturn = $this->env['killturn'] - Util::toInt(240 / abs($this->env['turnterm']));
|
||||||
$minNPCKillturn = 36;
|
$minNPCKillturn = 36;
|
||||||
|
|
||||||
foreach (Util::range($minChiefLevel, 12) as $chiefLevel) {
|
foreach (Util::range($minChiefLevel, 12) as $chiefLevel) {
|
||||||
|
|||||||
@@ -60,16 +60,6 @@ abstract class GeneralBase
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$rawTurnTime = $this->getVar('turntime');
|
|
||||||
// 비교용 Dummy와 과거 fixture는 문자열을 잠시 허용하되 제품 DB는 tick만 사용합니다.
|
|
||||||
if (is_string($rawTurnTime) && !ctype_digit(ltrim($rawTurnTime, '-'))) {
|
|
||||||
$formattedTurnTime = $rawTurnTime;
|
|
||||||
} else {
|
|
||||||
$db = DB::db();
|
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
|
||||||
$formattedTurnTime = $clock->formatTick(Util::toInt($rawTurnTime), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
self::TURNTIME_FULL_MS => function ($turntime) {
|
self::TURNTIME_FULL_MS => function ($turntime) {
|
||||||
return $turntime;
|
return $turntime;
|
||||||
@@ -83,20 +73,7 @@ abstract class GeneralBase
|
|||||||
self::TURNTIME_HM => function ($turntime) {
|
self::TURNTIME_HM => function ($turntime) {
|
||||||
return substr($turntime, 11, 5);
|
return substr($turntime, 11, 5);
|
||||||
},
|
},
|
||||||
][$short]($formattedTurnTime);
|
][$short]($this->getVar('turntime'));
|
||||||
}
|
|
||||||
|
|
||||||
function getTurnTick(): ?int
|
|
||||||
{
|
|
||||||
if (!key_exists('turntime', $this->raw)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
$rawTurnTime = $this->getVar('turntime');
|
|
||||||
if (is_string($rawTurnTime) && !ctype_digit(ltrim($rawTurnTime, '-'))) {
|
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage(DB::db(), 'game_env'));
|
|
||||||
return $clock->dateTimeToTick(new \DateTimeImmutable($rawTurnTime));
|
|
||||||
}
|
|
||||||
return Util::toInt($rawTurnTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNPCType(): int
|
function getNPCType(): int
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -59,7 +59,7 @@ class RandomNameGeneral extends AbsGeneralPool{
|
|||||||
'generalName'=>$generalName,
|
'generalName'=>$generalName,
|
||||||
'imgsvr'=>0,
|
'imgsvr'=>0,
|
||||||
'picture'=>null
|
'picture'=>null
|
||||||
], PHP_INT_MAX);
|
], '9999-12-31 12:00:00');
|
||||||
}
|
}
|
||||||
|
|
||||||
static public function pickGeneralFromPool(MeekroDB $db, RandUtil $rng, int $owner, int $pickCnt, ?string $prefix = null): array
|
static public function pickGeneralFromPool(MeekroDB $db, RandUtil $rng, int $owner, int $pickCnt, ?string $prefix = null): array
|
||||||
@@ -68,25 +68,26 @@ class RandomNameGeneral extends AbsGeneralPool{
|
|||||||
$result = [];
|
$result = [];
|
||||||
$dbInsert = [];
|
$dbInsert = [];
|
||||||
|
|
||||||
|
$oNow = new \DateTimeImmutable();
|
||||||
|
|
||||||
|
|
||||||
for($i=0;$i<$pickCnt;$i++){
|
for($i=0;$i<$pickCnt;$i++){
|
||||||
$result[] = static::pickGeneral1FromPool($db, $rng, $owner, $prefix);
|
$result[] = static::pickGeneral1FromPool($db, $rng, $owner, $prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($owner){
|
if($owner){
|
||||||
$gameStor = \sammo\KVStorage::getStorage($db, 'game_env');
|
$now = $oNow->format('Y-m-d H:i:s');
|
||||||
$clock = \sammo\GameClock::fromStorage($gameStor);
|
|
||||||
$now = $clock->nowTick();
|
|
||||||
$db->delete('select_pool', [
|
$db->delete('select_pool', [
|
||||||
'reserved_until'=>null,
|
'reserved_until'=>null,
|
||||||
'owner'=>null,
|
'owner'=>null,
|
||||||
],'(reserved_until < %s OR reserved_until IS NULL) AND general_id IS null', $now);
|
],'(reserved_until < %s OR reserved_until IS NULL) AND general_id IS null', $now);
|
||||||
$validUntil = $now + $clock->ticksFromSeconds(30);
|
$validUntil = $oNow->add(new \DateInterval(sprintf('PT%dS', 30)));
|
||||||
foreach($result as $pickedGeneral){
|
foreach($result as $pickedGeneral){
|
||||||
$dbInsert[] = [
|
$dbInsert[] = [
|
||||||
'owner'=>$owner,
|
'owner'=>$owner,
|
||||||
'uniqueName'=>$pickedGeneral->getUniqueName(),
|
'uniqueName'=>$pickedGeneral->getUniqueName(),
|
||||||
'info'=>$pickedGeneral->getInfo(),
|
'info'=>$pickedGeneral->getInfo(),
|
||||||
'reserved_until'=>$validUntil
|
'reserved_until'=>$validUntil->format(('Y-m-d H:i:s'))
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
$db->insert('select_pool', $dbInsert);
|
$db->insert('select_pool', $dbInsert);
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace sammo\GeneralPool;
|
|
||||||
|
|
||||||
use sammo\AbsFromUserPool;
|
|
||||||
use sammo\CentennialAllStarGrowthService;
|
|
||||||
use sammo\Json;
|
|
||||||
use sammo\RandUtil;
|
|
||||||
|
|
||||||
class SPoolUnderU100 extends AbsFromUserPool
|
|
||||||
{
|
|
||||||
private const MIN_DEX_WEIGHT = 100000;
|
|
||||||
private const STAT_BONUS_MIN_TOTAL = 160;
|
|
||||||
private const STAT_BONUS_MAX_TOTAL = 190;
|
|
||||||
private const STAT_BONUS_MAX_MULTIPLIER = 1.5;
|
|
||||||
|
|
||||||
public function __construct(\MeekroDB $db, RandUtil $rng, array $info, int $validUntil)
|
|
||||||
{
|
|
||||||
$targetInfo = $info;
|
|
||||||
$initialInfo = $info;
|
|
||||||
foreach ([
|
|
||||||
'leadership',
|
|
||||||
'strength',
|
|
||||||
'intel',
|
|
||||||
'experience',
|
|
||||||
'dedication',
|
|
||||||
'dex',
|
|
||||||
'specialDomestic',
|
|
||||||
'specialWar',
|
|
||||||
] as $targetKey) {
|
|
||||||
unset($initialInfo[$targetKey]);
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct($db, $rng, $initialInfo, $validUntil);
|
|
||||||
$this->info = $targetInfo;
|
|
||||||
CentennialAllStarGrowthService::attachInitialTarget($this->builder, $targetInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getPoolName(): string
|
|
||||||
{
|
|
||||||
return '100기 올스타 클래식';
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function getCandidateWeight(array $info, int $owner): int|float
|
|
||||||
{
|
|
||||||
$dexWeight = max(
|
|
||||||
self::MIN_DEX_WEIGHT,
|
|
||||||
array_sum($info['dex'] ?? [])
|
|
||||||
);
|
|
||||||
if ($owner <= 0) {
|
|
||||||
return $dexWeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
$statTotal = array_sum([
|
|
||||||
(int) ($info['leadership'] ?? 0),
|
|
||||||
(int) ($info['strength'] ?? 0),
|
|
||||||
(int) ($info['intel'] ?? 0),
|
|
||||||
]);
|
|
||||||
$normalizedStat = min(1, max(
|
|
||||||
0,
|
|
||||||
($statTotal - self::STAT_BONUS_MIN_TOTAL)
|
|
||||||
/ (self::STAT_BONUS_MAX_TOTAL - self::STAT_BONUS_MIN_TOTAL)
|
|
||||||
));
|
|
||||||
$statMultiplier = 1
|
|
||||||
+ (self::STAT_BONUS_MAX_MULTIPLIER - 1) * $normalizedStat;
|
|
||||||
|
|
||||||
return $dexWeight * $statMultiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function initPool(\MeekroDB $db)
|
|
||||||
{
|
|
||||||
$jsonData = Json::decode(file_get_contents(__DIR__ . '/Pool/UnderS100.json'));
|
|
||||||
$columns = $jsonData['columns'];
|
|
||||||
$sqlValues = [];
|
|
||||||
foreach ($jsonData['data'] as $idx => $rawItem) {
|
|
||||||
if (count($rawItem) !== count($columns)) {
|
|
||||||
throw new \RuntimeException(($rawItem[0] ?? (string) $idx) . ' Error');
|
|
||||||
}
|
|
||||||
$item = array_combine($columns, $rawItem);
|
|
||||||
$uniqueName = sprintf('A100%04d', $idx + 1);
|
|
||||||
$item['uniqueName'] = $uniqueName;
|
|
||||||
$item['event100Growth'] = true;
|
|
||||||
$sqlValues[] = [
|
|
||||||
'unique_name' => $uniqueName,
|
|
||||||
'info' => Json::encode($item),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$db->insert('select_pool', $sqlValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+15
-32
@@ -104,7 +104,6 @@ class Message
|
|||||||
|
|
||||||
public static function buildFromArray(array $row) : Message
|
public static function buildFromArray(array $row) : Message
|
||||||
{
|
{
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage(DB::db(), 'game_env'));
|
|
||||||
$dbMessage = Json::decode($row['message']);
|
$dbMessage = Json::decode($row['message']);
|
||||||
|
|
||||||
$msgType = MessageType::from($row['type']);
|
$msgType = MessageType::from($row['type']);
|
||||||
@@ -117,8 +116,8 @@ class Message
|
|||||||
$src,
|
$src,
|
||||||
$dest,
|
$dest,
|
||||||
$dbMessage['text'],
|
$dbMessage['text'],
|
||||||
\DateTime::createFromImmutable($clock->tickToDateTime(Util::toInt($row['time']))),
|
new \DateTime($row['time']),
|
||||||
\DateTime::createFromImmutable($clock->tickToDateTime(Util::toInt($row['valid_until']))),
|
new \DateTime($row['valid_until']),
|
||||||
$option
|
$option
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -152,12 +151,9 @@ class Message
|
|||||||
public static function getMessageByID(int $messageID) : ?Message
|
public static function getMessageByID(int $messageID) : ?Message
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
$now = new \DateTime();
|
||||||
$row = $db->queryFirstRow(
|
$row = $db->queryFirstRow('SELECT * FROM `message` WHERE `id` = %i AND valid_until', $messageID);
|
||||||
'SELECT * FROM `message` WHERE `id` = %i AND valid_until > %i',
|
//FIXME: $now가 들어가야 하는데 안 들어가있는데?
|
||||||
$messageID,
|
|
||||||
$clock->nowTick(),
|
|
||||||
);
|
|
||||||
if (!$row) {
|
if (!$row) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -175,12 +171,12 @@ class Message
|
|||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$date = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'))->nowTick();
|
$date = (new \DateTime())->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
$where = new \WhereClause('and');
|
$where = new \WhereClause('and');
|
||||||
$where->add('mailbox = %i', $mailbox);
|
$where->add('mailbox = %i', $mailbox);
|
||||||
$where->add('type = %s', $msgType->value);
|
$where->add('type = %s', $msgType->value);
|
||||||
$where->add('valid_until > %i', $date);
|
$where->add('valid_until > %s', $date);
|
||||||
if ($fromSeq > 0) {
|
if ($fromSeq > 0) {
|
||||||
$where->add('id >= %i', $fromSeq);
|
$where->add('id >= %i', $fromSeq);
|
||||||
}
|
}
|
||||||
@@ -207,12 +203,12 @@ class Message
|
|||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$date = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'))->nowTick();
|
$date = (new \DateTime())->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
$where = new \WhereClause('and');
|
$where = new \WhereClause('and');
|
||||||
$where->add('mailbox = %i', $mailbox);
|
$where->add('mailbox = %i', $mailbox);
|
||||||
$where->add('type = %s', $msgType->value);
|
$where->add('type = %s', $msgType->value);
|
||||||
$where->add('valid_until > %i', $date);
|
$where->add('valid_until > %s', $date);
|
||||||
$where->add('id < %i', $toSeq);
|
$where->add('id < %i', $toSeq);
|
||||||
|
|
||||||
if ($limit > 0) {
|
if ($limit > 0) {
|
||||||
@@ -240,8 +236,7 @@ class Message
|
|||||||
return '시스템 외교 메시지는 삭제할 수 없습니다.';
|
return '시스템 외교 메시지는 삭제할 수 없습니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage(DB::db(), 'game_env'));
|
$prev5min = new \DateTime();
|
||||||
$prev5min = \DateTime::createFromImmutable($clock->tickToDateTime($clock->nowTick()));
|
|
||||||
$prev5min->sub(new \DateInterval('PT5M'));
|
$prev5min->sub(new \DateInterval('PT5M'));
|
||||||
|
|
||||||
if($msgObj->date < $prev5min){
|
if($msgObj->date < $prev5min){
|
||||||
@@ -270,15 +265,14 @@ class Message
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$now = \DateTime::createFromImmutable($clock->tickToDateTime($clock->nowTick()));
|
$in1min = new \DateTime();
|
||||||
$in1min = clone $now;
|
|
||||||
$in1min->add(new \DateInterval('PT1M'));
|
$in1min->add(new \DateInterval('PT1M'));
|
||||||
$newMsg = new Message(
|
$newMsg = new Message(
|
||||||
$msgObj->msgType,
|
$msgObj->msgType,
|
||||||
$msgObj->src,
|
$msgObj->src,
|
||||||
$msgObj->dest,
|
$msgObj->dest,
|
||||||
"req_del_msg",
|
"req_del_msg",
|
||||||
$now,
|
new \DateTime(),
|
||||||
$in1min,
|
$in1min,
|
||||||
$msgOption
|
$msgOption
|
||||||
);
|
);
|
||||||
@@ -306,23 +300,13 @@ class Message
|
|||||||
|
|
||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
|
||||||
$timeTick = $clock->nowTick();
|
|
||||||
if (Util::toInt($this->validUntil->format('Y')) >= 9000) {
|
|
||||||
$validUntilTick = GameClock::MAX_SAFE_TICK;
|
|
||||||
} else {
|
|
||||||
$validitySeconds = $this->validUntil->getTimestamp() - $this->date->getTimestamp();
|
|
||||||
$validUntilTick = $timeTick + $clock->ticksFromSeconds($validitySeconds);
|
|
||||||
}
|
|
||||||
$this->date = \DateTime::createFromImmutable($clock->tickToDateTime($timeTick));
|
|
||||||
$this->validUntil = \DateTime::createFromImmutable($clock->tickToDateTime($validUntilTick));
|
|
||||||
$db->insert('message', [
|
$db->insert('message', [
|
||||||
'mailbox' => $mailbox,
|
'mailbox' => $mailbox,
|
||||||
'type' => $this->msgType->value,
|
'type' => $this->msgType->value,
|
||||||
'src' => $src_id,
|
'src' => $src_id,
|
||||||
'dest' => $dest_id,
|
'dest' => $dest_id,
|
||||||
'time' => $timeTick,
|
'time' => $this->date->format('Y-m-d H:i:s'),
|
||||||
'valid_until' => $validUntilTick,
|
'valid_until' => $this->validUntil->format('Y-m-d H:i:s'),
|
||||||
'message' => Json::encode([
|
'message' => Json::encode([
|
||||||
'src'=>($this->src)?($this->src->toArray()):[],
|
'src'=>($this->src)?($this->src->toArray()):[],
|
||||||
'dest'=>($this->dest)?($this->dest->toArray()):[],
|
'dest'=>($this->dest)?($this->dest->toArray()):[],
|
||||||
@@ -505,8 +489,7 @@ class Message
|
|||||||
'text' => $this->msg,
|
'text' => $this->msg,
|
||||||
'option' => $this->msgOption
|
'option' => $this->msgOption
|
||||||
]),
|
]),
|
||||||
'valid_until'=>GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'))
|
'valid_until'=>$this->validUntil->format('Y-m-d H:i:s'),
|
||||||
->dateTimeToTick($this->validUntil),
|
|
||||||
], 'id=%i', $this->id);
|
], 'id=%i', $this->id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-27
@@ -245,16 +245,23 @@ class ResetHelper{
|
|||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
$requestedTime = new \DateTimeImmutable($turntime);
|
if($turnterm == -60){
|
||||||
if($sync == 0) {
|
[$starttime, $yearPulled, $month] = VarTurn60::fromDatetime(new \DateTimeImmutable($turntime))->cutDay();
|
||||||
|
if($yearPulled){
|
||||||
|
$year = $startyear-1;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$year = $startyear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if($sync == 0) {
|
||||||
// 현재 시간을 1월로 맞춤
|
// 현재 시간을 1월로 맞춤
|
||||||
$baseTime = new \DateTimeImmutable(cutTurnDateTime($turntime, $turnterm));
|
$starttime = cutTurn($turntime, $turnterm);
|
||||||
$month = 1;
|
$month = 1;
|
||||||
$year = $startyear;
|
$year = $startyear;
|
||||||
} else {
|
} else {
|
||||||
// 현재 시간과 동기화
|
// 현재 시간과 동기화
|
||||||
[$baseTimeString, $yearPulled, $month] = cutDay($turntime, $turnterm);
|
[$starttime, $yearPulled, $month] = cutDay($turntime, $turnterm);
|
||||||
$baseTime = new \DateTimeImmutable($baseTimeString);
|
|
||||||
if($yearPulled){
|
if($yearPulled){
|
||||||
$year = $startyear-1;
|
$year = $startyear-1;
|
||||||
}
|
}
|
||||||
@@ -263,19 +270,7 @@ class ResetHelper{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$wallNow = GameClock::readWallTime();
|
$killturn = 4800 / abs($turnterm);
|
||||||
$initialClock = new GameClock(
|
|
||||||
$baseTime,
|
|
||||||
$turnterm,
|
|
||||||
0,
|
|
||||||
GameClock::MODE_REALTIME,
|
|
||||||
$wallNow,
|
|
||||||
fn (): \DateTimeImmutable => $wallNow,
|
|
||||||
);
|
|
||||||
$requestedTick = $initialClock->dateTimeToTick($requestedTime);
|
|
||||||
$currentTick = $initialClock->dateTimeToTick($wallNow);
|
|
||||||
|
|
||||||
$killturn = 4800 / $turnterm;
|
|
||||||
if($npcmode == 1) { $killturn = intdiv($killturn, 3); }
|
if($npcmode == 1) { $killturn = intdiv($killturn, 3); }
|
||||||
|
|
||||||
$develcost = ($year - $startyear + 10) * 2;
|
$develcost = ($year - $startyear + 10) * 2;
|
||||||
@@ -297,14 +292,10 @@ class ResetHelper{
|
|||||||
'maxnation'=>GameConst::$defaultMaxNation,
|
'maxnation'=>GameConst::$defaultMaxNation,
|
||||||
'refreshLimit'=>30000,
|
'refreshLimit'=>30000,
|
||||||
'develcost'=>$develcost,
|
'develcost'=>$develcost,
|
||||||
'turntime'=>$requestedTick,
|
'turntime'=>$turntime,
|
||||||
'starttime'=>0,
|
'starttime'=>$starttime,
|
||||||
'opentime'=>$requestedTick,
|
'opentime'=>$turntime,
|
||||||
'turnterm'=>$turnterm,
|
'turnterm'=>$turnterm,
|
||||||
'clock_base_time'=>TimeUtil::format($baseTime, true),
|
|
||||||
'clock_tick'=>$currentTick,
|
|
||||||
'clock_mode'=>GameClock::MODE_REALTIME,
|
|
||||||
'clock_wall_anchor'=>TimeUtil::format($wallNow, true),
|
|
||||||
'killturn'=>$killturn,
|
'killturn'=>$killturn,
|
||||||
'genius'=>GameConst::$defaultMaxGenius,
|
'genius'=>GameConst::$defaultMaxGenius,
|
||||||
'show_img_level'=>$show_img_level,
|
'show_img_level'=>$show_img_level,
|
||||||
@@ -326,7 +317,7 @@ class ResetHelper{
|
|||||||
'name'=>$admin['name'],
|
'name'=>$admin['name'],
|
||||||
'picture'=>$admin['picture'],
|
'picture'=>$admin['picture'],
|
||||||
'imgsvr'=>$admin['imgsvr'],
|
'imgsvr'=>$admin['imgsvr'],
|
||||||
'turntime'=>$requestedTick,
|
'turntime'=>$turntime,
|
||||||
'killturn'=>9999,
|
'killturn'=>9999,
|
||||||
'crewtype'=>GameUnitConst::DEFAULT_CREWTYPE
|
'crewtype'=>GameUnitConst::DEFAULT_CREWTYPE
|
||||||
]);
|
]);
|
||||||
@@ -362,7 +353,7 @@ class ResetHelper{
|
|||||||
|
|
||||||
$db->insert('ng_games', [
|
$db->insert('ng_games', [
|
||||||
'server_id'=>$serverID,
|
'server_id'=>$serverID,
|
||||||
'date'=>TimeUtil::format($requestedTime, false),
|
'date'=>$turntime,
|
||||||
'winner_nation'=>null,
|
'winner_nation'=>null,
|
||||||
'map'=>$scenarioObj->getMapTheme(),
|
'map'=>$scenarioObj->getMapTheme(),
|
||||||
'season'=>$seasonIdx,
|
'season'=>$seasonIdx,
|
||||||
|
|||||||
@@ -653,7 +653,7 @@ class GeneralBuilder{
|
|||||||
$officerLevel = $nationID?1:0;
|
$officerLevel = $nationID?1:0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$turntime = \sammo\getRandTurn($this->rng, $env['turnterm'], Util::toInt($env['turntime']));
|
$turntime = \sammo\getRandTurn($this->rng, $env['turnterm'], new \DateTimeImmutable($env['turntime']));
|
||||||
|
|
||||||
if($this->killturn){
|
if($this->killturn){
|
||||||
$killturn = $this->killturn;
|
$killturn = $this->killturn;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class ScoutMessage extends Message
|
|||||||
$this->validScout = false;
|
$this->validScout = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->validUntil <= $this->date) {
|
if ($this->validUntil <= new \DateTime()) {
|
||||||
$this->validScout = false;
|
$this->validScout = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,11 +122,11 @@ class ScoutMessage extends Message
|
|||||||
public static function invalidateAll(int $generalID, ?int $exceptMsgID = null)
|
public static function invalidateAll(int $generalID, ?int $exceptMsgID = null)
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$now = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'))->nowTick();
|
$now = TimeUtil::now();
|
||||||
//XXX: 뭔가 기존 쿼리가 애매하다. invalid 관련해서 다른 옵션이 가능한가?
|
//XXX: 뭔가 기존 쿼리가 애매하다. invalid 관련해서 다른 옵션이 가능한가?
|
||||||
$rawMsgList = Util::convertArrayToDict($db->query(
|
$rawMsgList = Util::convertArrayToDict($db->query(
|
||||||
'SELECT * FROM `message` WHERE
|
'SELECT * FROM `message` WHERE
|
||||||
`mailbox` = %i AND `type` = "private" AND `dest` = `mailbox` AND `valid_until` > %i AND
|
`mailbox` = %i AND `type` = "private" AND `dest` = `mailbox` AND `valid_until` > %s AND
|
||||||
JSON_VALUE(message, "$.option.action") = %s',
|
JSON_VALUE(message, "$.option.action") = %s',
|
||||||
$generalID,
|
$generalID,
|
||||||
$now,
|
$now,
|
||||||
|
|||||||
+28
-14
@@ -20,6 +20,17 @@ final class ServerTool
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$admin = $gameStor->getValues(['turntime', 'turnterm', 'year', 'startyear', 'month', 'isunited']);
|
$admin = $gameStor->getValues(['turntime', 'turnterm', 'year', 'startyear', 'month', 'isunited']);
|
||||||
|
|
||||||
|
$oldunit = $admin['turnterm'] * 60;
|
||||||
|
$unit = $turnterm * 60;
|
||||||
|
|
||||||
|
if($unit == $oldunit){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($oldunit < 0 || $unit < 0){
|
||||||
|
return 'variable_turnterm';
|
||||||
|
}
|
||||||
|
|
||||||
$reqGameLock = $admin['isunited'] != 2 && !$ignoreLock;
|
$reqGameLock = $admin['isunited'] != 2 && !$ignoreLock;
|
||||||
|
|
||||||
$locked = false;
|
$locked = false;
|
||||||
@@ -40,22 +51,25 @@ final class ServerTool
|
|||||||
$locked = tryLock();
|
$locked = tryLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if($turnterm == $admin['turnterm']){
|
|
||||||
if($locked){
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$oldClock = GameClock::fromStorage($gameStor);
|
$unitDiff = $unit / $oldunit;
|
||||||
$currentTick = $oldClock->nowTick();
|
|
||||||
$currentDisplay = $oldClock->tickToDateTime($currentTick);
|
$servTurnTime = new \DateTimeImmutable($admin['turntime']);
|
||||||
$oldClock->persistTick($gameStor, $currentTick);
|
foreach ($db->query('SELECT no,turntime FROM general') as $gen) {
|
||||||
|
$genTurnTime = new \DateTimeImmutable($gen['turntime']);
|
||||||
|
$timeDiff = TimeUtil::DateIntervalToSeconds($genTurnTime->diff($servTurnTime));
|
||||||
|
$timeDiff *= $unitDiff;
|
||||||
|
$newGenTurnTime = $servTurnTime->add(TimeUtil::secondsToDateInterval($timeDiff));
|
||||||
|
|
||||||
|
$db->update('general', [
|
||||||
|
'turntime' => $newGenTurnTime->format('Y-m-d H:i:s.u')
|
||||||
|
], 'no=%i', $gen['no']);
|
||||||
|
}
|
||||||
|
$turn = ($admin['year'] - $admin['startyear']) * 12 + $admin['month'] - 1;
|
||||||
|
$starttime = $servTurnTime->sub(TimeUtil::secondsToDateInterval($turn * $unit))->format('Y-m-d H:i:s');
|
||||||
|
$starttime = cutTurn($starttime, $turnterm, false);
|
||||||
$gameStor->turnterm = $turnterm;
|
$gameStor->turnterm = $turnterm;
|
||||||
$gameStor->clock_base_time = TimeUtil::format(
|
$gameStor->starttime = $starttime;
|
||||||
GameClock::baseTimeForProjection($currentDisplay, $currentTick, $turnterm),
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
pushGlobalHistoryLog(["<R>★</>턴시간이 <C>{$turnterm}분</>으로 변경됩니다."]);
|
pushGlobalHistoryLog(["<R>★</>턴시간이 <C>{$turnterm}분</>으로 변경됩니다."]);
|
||||||
|
|
||||||
if($locked){
|
if($locked){
|
||||||
|
|||||||
@@ -215,21 +215,31 @@ class TurnExecutionHelper
|
|||||||
$general->rebirth();
|
$general->rebirth();
|
||||||
}
|
}
|
||||||
|
|
||||||
$turntime = addTurn($general->getTurnTick(), $gameStor->turnterm);
|
$turntime = addTurn($general->getTurnTime(), $gameStor->turnterm);
|
||||||
|
|
||||||
$nextTurnTimeBase = $general->getAuxVar('nextTurnTimeBase');
|
$nextTurnTimeBase = $general->getAuxVar('nextTurnTimeBase');
|
||||||
if($nextTurnTimeBase !== null){
|
if($nextTurnTimeBase !== null){
|
||||||
$turntime = cutTurn($turntime, $gameStor->turnterm);
|
if($gameStor->turnterm == -60){
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
[$turntime, $nextTurnterm] = VarTurn60::fromDatetime(new \DateTimeImmutable($turntime))->cutTurn();
|
||||||
$turntime += $clock->ticksFromSeconds($nextTurnTimeBase);
|
$turntimeObj = new \DateTimeImmutable($turntime);
|
||||||
$general->setAuxVar('nextTurnTimeBase', null);
|
$turntimeObj = $turntimeObj->add(TimeUtil::secondsToDateInterval($nextTurnTimeBase * $nextTurnterm / 60));
|
||||||
|
$turntime = TimeUtil::format($turntimeObj, true);
|
||||||
|
$general->setAuxVar('nextTurnTimeBase', null);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$turntime = cutTurn($turntime, $gameStor->turnterm);
|
||||||
|
$turntimeObj = new \DateTimeImmutable($turntime);
|
||||||
|
$turntimeObj = $turntimeObj->add(TimeUtil::secondsToDateInterval($nextTurnTimeBase));
|
||||||
|
$turntime = TimeUtil::format($turntimeObj, true);
|
||||||
|
$general->setAuxVar('nextTurnTimeBase', null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$general->setVar('turntime', $turntime);
|
$general->setVar('turntime', $turntime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static public function executeGeneralCommandUntil(int $date, \DateTimeInterface $limitActionTime, int $year, int $month)
|
static public function executeGeneralCommandUntil(string $date, \DateTimeInterface $limitActionTime, int $year, int $month)
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$generalsTodo = $db->query(
|
$generalsTodo = $db->query(
|
||||||
@@ -243,7 +253,7 @@ class TurnExecutionHelper
|
|||||||
$autorun_user = $gameStor->autorun_user;
|
$autorun_user = $gameStor->autorun_user;
|
||||||
|
|
||||||
foreach ($generalsTodo as $rawGeneral) {
|
foreach ($generalsTodo as $rawGeneral) {
|
||||||
$currActionTime = GameClock::readWallTime();
|
$currActionTime = new \DateTimeImmutable();
|
||||||
if ($currActionTime > $limitActionTime) {
|
if ($currActionTime > $limitActionTime) {
|
||||||
return [true, $currentTurn];
|
return [true, $currentTurn];
|
||||||
}
|
}
|
||||||
@@ -349,12 +359,12 @@ class TurnExecutionHelper
|
|||||||
pullNationCommand($general->getVar('nation'), $general->getVar('officer_level'));
|
pullNationCommand($general->getVar('nation'), $general->getVar('officer_level'));
|
||||||
pullGeneralCommand($general->getID());
|
pullGeneralCommand($general->getID());
|
||||||
|
|
||||||
$currentTurn = $general->getTurnTick();
|
$currentTurn = $general->getTurnTime();
|
||||||
$general->increaseVarWithLimit('myset', GameConst::$incDefSettingChange, null, GameConst::$maxDefSettingChange);
|
$general->increaseVarWithLimit('myset', GameConst::$incDefSettingChange, null, GameConst::$maxDefSettingChange);
|
||||||
|
|
||||||
if (($autorun_user['limit_minutes'] ?? false) && $general->getNPCType() < 2 && $hasReservedTurn) {
|
if (($autorun_user['limit_minutes'] ?? false) && $general->getNPCType() < 2 && $hasReservedTurn) {
|
||||||
$autorun_limit = Util::joinYearMonth($year, $month);
|
$autorun_limit = Util::joinYearMonth($year, $month);
|
||||||
$autorun_limit += intdiv($autorun_user['limit_minutes'], $turnterm);
|
$autorun_limit += intdiv($autorun_user['limit_minutes'], abs($turnterm));
|
||||||
|
|
||||||
$general->setAuxVar('autorun_limit', $autorun_limit);
|
$general->setAuxVar('autorun_limit', $autorun_limit);
|
||||||
}
|
}
|
||||||
@@ -389,14 +399,13 @@ class TurnExecutionHelper
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public function executeAllCommand(&$executed = false, &$locked = false): int
|
static public function executeAllCommand(&$executed = false, &$locked = false): string
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
|
||||||
$clock = GameClock::fromStorage($gameStor);
|
if (TimeUtil::now(true) < $gameStor->turntime) {
|
||||||
if ($clock->nowTick() < $gameStor->turntime) {
|
|
||||||
//턴 시각 이전이면 아무것도 하지 않음
|
//턴 시각 이전이면 아무것도 하지 않음
|
||||||
return $gameStor->turntime;
|
return $gameStor->turntime;
|
||||||
}
|
}
|
||||||
@@ -420,7 +429,7 @@ class TurnExecutionHelper
|
|||||||
//접속자 수 따라서 갱신제한 변경
|
//접속자 수 따라서 갱신제한 변경
|
||||||
CheckOverhead();
|
CheckOverhead();
|
||||||
|
|
||||||
$date = $clock->nowTick();
|
$date = TimeUtil::now(true);
|
||||||
// 최종 처리 월턴의 다음 월턴시간 구함
|
// 최종 처리 월턴의 다음 월턴시간 구함
|
||||||
//$lastExecuted = $gameStor->turntime;
|
//$lastExecuted = $gameStor->turntime;
|
||||||
$prevTurn = cutTurn($gameStor->turntime, $gameStor->turnterm);
|
$prevTurn = cutTurn($gameStor->turntime, $gameStor->turnterm);
|
||||||
@@ -433,7 +442,7 @@ class TurnExecutionHelper
|
|||||||
$maxActionTime = max($maxActionTime * 2 / 3, $maxActionTime - 10);
|
$maxActionTime = max($maxActionTime * 2 / 3, $maxActionTime - 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
$limitActionTime = GameClock::readWallTime()->add(TimeUtil::secondsToDateInterval($maxActionTime));
|
$limitActionTime = (new \DateTimeImmutable())->add(TimeUtil::secondsToDateInterval($maxActionTime));
|
||||||
|
|
||||||
// 현재 턴 이전 월턴까지 모두처리.
|
// 현재 턴 이전 월턴까지 모두처리.
|
||||||
//최종 처리 이후 다음 월턴이 현재 시간보다 전이라면
|
//최종 처리 이후 다음 월턴이 현재 시간보다 전이라면
|
||||||
|
|||||||
@@ -0,0 +1,191 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace sammo;
|
||||||
|
|
||||||
|
class VarTurn60
|
||||||
|
{
|
||||||
|
const MonthAdjustOffset = 2;
|
||||||
|
|
||||||
|
static array $min30ToTurn = [
|
||||||
|
[0, 0, 120], //00:00 2
|
||||||
|
[0, 30, 120], //00:30
|
||||||
|
[0, 60, 120], //01:00
|
||||||
|
[0, 90, 120], //01:30
|
||||||
|
[1, 0, 120], //02:00 3
|
||||||
|
[1, 30, 120], //02:30
|
||||||
|
[1, 60, 120], //03:00
|
||||||
|
[1, 90, 120], //03:30
|
||||||
|
[2, 0, 120], //04:00 4
|
||||||
|
[2, 30, 120], //04:30
|
||||||
|
[2, 60, 120], //05:00
|
||||||
|
[2, 90, 120], //05:30
|
||||||
|
[3, 0, 60], //06:00 5
|
||||||
|
[3, 30, 60], //06:30
|
||||||
|
[4, 0, 60], //07:00 6
|
||||||
|
[4, 30, 60], //07:30
|
||||||
|
[5, 0, 60], //08:00 7
|
||||||
|
[5, 30, 60], //08:30
|
||||||
|
[6, 0, 60], //09:00 8
|
||||||
|
[6, 30, 60], //09:30
|
||||||
|
[7, 0, 60], //10:00 9
|
||||||
|
[7, 30, 60], //10:30
|
||||||
|
[8, 0, 60], //11:00 10
|
||||||
|
[8, 30, 60], //11:30
|
||||||
|
[9, 0, 60], //12:00 11
|
||||||
|
[9, 30, 60], //12:30
|
||||||
|
[10, 0, 60], //13:00 0(12)
|
||||||
|
[10, 30, 60], //13:30
|
||||||
|
[11, 0, 60], //14:00 1(13)
|
||||||
|
[11, 30, 60], //14:30
|
||||||
|
[12, 0, 60], //15:00 2(14)
|
||||||
|
[12, 30, 60], //15:30
|
||||||
|
[13, 0, 60], //16:00 3(15)
|
||||||
|
[13, 30, 60], //16:30
|
||||||
|
[14, 0, 60], //17:00 4(16)
|
||||||
|
[14, 30, 60], //17:30
|
||||||
|
[15, 0, 60], //18:00 5(17)
|
||||||
|
[15, 30, 60], //18:30
|
||||||
|
[16, 0, 30], //19:00 6(18)
|
||||||
|
[17, 0, 30], //19:30 7(19)
|
||||||
|
[18, 0, 30], //20:00 8(20)
|
||||||
|
[19, 0, 30], //20:30 9(21)
|
||||||
|
[20, 0, 30], //21:00 10(22)
|
||||||
|
[21, 0, 30], //21:30 11(23)
|
||||||
|
[22, 0, 60], //22:00 0
|
||||||
|
[22, 30, 60], //22:30
|
||||||
|
[23, 0, 60], //23:00 1
|
||||||
|
[23, 30, 60], //23:30
|
||||||
|
//[24, 0, 60], //24:00 2
|
||||||
|
];
|
||||||
|
|
||||||
|
static array $turnToHM = [
|
||||||
|
[0, 0, 120], //0
|
||||||
|
[2, 0, 120], //1
|
||||||
|
[4, 0, 120], //2
|
||||||
|
[6, 0, 60], //3
|
||||||
|
[7, 0, 60], //4
|
||||||
|
[8, 0, 60], //5
|
||||||
|
[9, 0, 60], //6
|
||||||
|
[10, 0, 60], //7
|
||||||
|
[11, 0, 60], //8
|
||||||
|
[12, 0, 60], //9
|
||||||
|
[13, 0, 60], //10
|
||||||
|
[14, 0, 60], //11
|
||||||
|
[15, 0, 60], //12
|
||||||
|
[16, 0, 60], //13
|
||||||
|
[17, 0, 60], //14
|
||||||
|
[18, 0, 60], //15
|
||||||
|
[19, 0, 30], //16
|
||||||
|
[19, 30, 30],//17
|
||||||
|
[20, 0, 30], //18
|
||||||
|
[20, 30, 30],//19
|
||||||
|
[21, 0, 30], //20
|
||||||
|
[21, 30, 30],//21
|
||||||
|
[22, 0, 60], //22
|
||||||
|
[23, 0, 60], //23
|
||||||
|
//[24, 0, 60], //24(?)
|
||||||
|
];
|
||||||
|
|
||||||
|
function __construct(
|
||||||
|
public \DateTimeImmutable $baseDay,
|
||||||
|
public int $turnIdx, //0~23
|
||||||
|
public float $secOffset, ///turnTerm에 따라 최대치가 30*60, 60*60, 120*60 가변
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static function fromDatetime(\DateTimeInterface $date): self {
|
||||||
|
$baseDay = new \DateTimeImmutable($date->format('Y-m-d'));
|
||||||
|
$totalSec = $date->getTimestamp() - $baseDay->getTimestamp();
|
||||||
|
|
||||||
|
$min30 = intdiv($totalSec, 60 * 30);
|
||||||
|
|
||||||
|
assert($min30 < 48);
|
||||||
|
|
||||||
|
[$turnIdx, $minOffset, ] = static::$min30ToTurn[$min30];
|
||||||
|
|
||||||
|
$secOffset = $totalSec - 60 * 30 * $min30 + $minOffset * 60;
|
||||||
|
return new static($baseDay, $turnIdx, $secOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// $b - $a 의 턴차
|
||||||
|
static function calcTurnDiff(\DateTimeInterface $a, \DateTimeInterface $b): int{
|
||||||
|
$aObj = static::fromDatetime($a);
|
||||||
|
$bObj = static::fromDatetime($b);
|
||||||
|
|
||||||
|
$resDays = $aObj->baseDay->diff($bObj->baseDay)->days; //놀랍게도 절대값
|
||||||
|
if($aObj->baseDay > $bObj->baseDay){
|
||||||
|
$resDays *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$res = $resDays * 24 + $bObj->turnIdx - $aObj->turnIdx;
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cutTurn($withFraction = true): array{
|
||||||
|
[$hour, $minOffset, $turnTerm] = static::$turnToHM[$this->turnIdx];
|
||||||
|
$date = $this->baseDay->add(TimeUtil::secondsToDateInterval(($hour * 60 + $minOffset) * 60));
|
||||||
|
return [TimeUtil::format($date, $withFraction), $turnTerm];
|
||||||
|
}
|
||||||
|
|
||||||
|
function toDateStr($withFraction = true): string{
|
||||||
|
[$hour, $minOffset, ] = static::$turnToHM[$this->turnIdx];
|
||||||
|
$date = $this->baseDay->add(TimeUtil::secondsToDateInterval(($hour * 60 + $minOffset) * 60 + $this->secOffset));
|
||||||
|
return TimeUtil::format($date, $withFraction);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cutDay($withFraction = true): array{
|
||||||
|
//고정 시간 기준 cutDay()의 이식
|
||||||
|
//상수 테이블이 이미 13:00에 1월이 되도록 맞춰져 있음.
|
||||||
|
//다만 20:00인 경우 8월이 아니라 9월이 됨 ^^;
|
||||||
|
$newMonth = ($this->turnIdx + static::MonthAdjustOffset) % 12 + 1;
|
||||||
|
|
||||||
|
$yearPulled = $newMonth > 3;
|
||||||
|
|
||||||
|
$obj = $yearPulled ? $this->addTurn(12): $this;
|
||||||
|
[$date, ] = $obj->addTurn(-($newMonth - 1))->cutTurn($withFraction);
|
||||||
|
|
||||||
|
|
||||||
|
return [$date, $yearPulled, $newMonth];
|
||||||
|
}
|
||||||
|
|
||||||
|
function addTurn(int $moreTurn): self{
|
||||||
|
$dayDiff = intdiv($moreTurn, 24);
|
||||||
|
$moreTurn %= 24;
|
||||||
|
|
||||||
|
$nextTurnIdx = $this->turnIdx + $moreTurn;
|
||||||
|
if($nextTurnIdx < 0){
|
||||||
|
$dayDiff -= 1;
|
||||||
|
$nextTurnIdx += 24;
|
||||||
|
}
|
||||||
|
else if($nextTurnIdx >= 24){
|
||||||
|
$dayDiff += 1;
|
||||||
|
$nextTurnIdx -= 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
[, , $oldTurnTerm] = static::$turnToHM[$this->turnIdx];
|
||||||
|
[, , $nextTurnTerm] = static::$turnToHM[$nextTurnIdx];
|
||||||
|
|
||||||
|
$nextSecOffset = $this->secOffset;
|
||||||
|
if($oldTurnTerm != $nextTurnTerm){
|
||||||
|
$nextSecOffset *= $nextTurnTerm;
|
||||||
|
$nextSecOffset /= $oldTurnTerm;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($dayDiff == 0){
|
||||||
|
return new static($this->baseDay, $nextTurnIdx, $nextSecOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($dayDiff > 0){
|
||||||
|
$nextBaseDay = $this->baseDay->add(new \DateInterval("P{$dayDiff}D"));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$dayAbsDiff = abs($dayDiff);
|
||||||
|
$nextBaseDay = $this->baseDay->sub(new \DateInterval("P{$dayAbsDiff}D"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new static($nextBaseDay, $nextTurnIdx, $nextSecOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -57,16 +57,16 @@ class WarUnitGeneral extends WarUnit
|
|||||||
$this->general->increaseRankVar(RankColumn::warnum, 1);
|
$this->general->increaseRankVar(RankColumn::warnum, 1);
|
||||||
|
|
||||||
if ($this->isAttacker) {
|
if ($this->isAttacker) {
|
||||||
$semiTurn = $general->getTurnTick();
|
$semiTurn = $general->getTurnTime();
|
||||||
} else if ($oppose !== null) {
|
} else if ($oppose !== null) {
|
||||||
$semiTurn = $oppose->getGeneral()->getTurnTick();
|
$semiTurn = $oppose->getGeneral()->getTurnTime();
|
||||||
} else {
|
} else {
|
||||||
LogText("WarUnitGeneral::setOppose", "defender인데 oppose가 null {$general->getID()}, {$general->getTurnTime()}");
|
LogText("WarUnitGeneral::setOppose", "defender인데 oppose가 null {$general->getID()}, {$general->getTurnTime()}");
|
||||||
$semiTurn = $general->getTurnTick();
|
$semiTurn = $general->getTurnTime();
|
||||||
}
|
}
|
||||||
$phase = $this->getRealPhase();
|
$phase = $this->getRealPhase();
|
||||||
$semiTurn -= $semiTurn % 100;
|
$semiTurn = substr($semiTurn, 0, strlen($semiTurn) - 2);
|
||||||
$semiTurn += Util::valueFit($phase, 0, 99);
|
$semiTurn .= sprintf("%02d", Util::valueFit($phase, 0, 99));
|
||||||
$general->setVar('recent_war', $semiTurn);
|
$general->setVar('recent_war', $semiTurn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,6 +81,13 @@
|
|||||||
["RaiseNPCNation"],
|
["RaiseNPCNation"],
|
||||||
["DeleteEvent"]
|
["DeleteEvent"]
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"month", 1000,
|
||||||
|
true,
|
||||||
|
["ChangeCity", "all", {
|
||||||
|
"trade":100
|
||||||
|
}]
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"month", 999,
|
"month", 999,
|
||||||
["Date", "==", 181, 1],
|
["Date", "==", 181, 1],
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
{
|
|
||||||
"title":"【공백지】 요양 ",
|
|
||||||
"startYear":180,
|
|
||||||
"map":{
|
|
||||||
"mapName":"miniche"
|
|
||||||
},
|
|
||||||
"history":[
|
|
||||||
"<C>●</>180년 1월:<L><b>【이벤트】</b></>쉬었다 가는 깃수입니다."
|
|
||||||
],
|
|
||||||
"const": {
|
|
||||||
"joinRuinedNPCProp":0,
|
|
||||||
"npcBanMessageProb":0.005,
|
|
||||||
"defaultMaxGeneral": 800,
|
|
||||||
"allItems":{
|
|
||||||
"horse":{
|
|
||||||
"che_명마_01_노기":0, "che_명마_02_조랑":0, "che_명마_03_노새":0,
|
|
||||||
"che_명마_04_나귀":0, "che_명마_05_갈색마":0, "che_명마_06_흑색마":0,
|
|
||||||
|
|
||||||
"che_명마_07_백마" : 2, "che_명마_07_기주마" : 2, "che_명마_07_오환마" : 2, "che_명마_07_백상" : 2,
|
|
||||||
"che_명마_08_양주마" : 2, "che_명마_08_흉노마" : 2, "che_명마_09_과하마" : 2, "che_명마_09_의남백마" : 2,
|
|
||||||
"che_명마_10_대완마" : 2, "che_명마_10_옥추마" : 2, "che_명마_11_서량마" : 2, "che_명마_11_화종마" : 2,
|
|
||||||
"che_명마_12_사륜거" : 2, "che_명마_12_옥란백용구": 2, "che_명마_13_절영" : 2, "che_명마_13_적로" : 2,
|
|
||||||
"che_명마_14_적란마" : 2, "che_명마_14_조황비전" : 2, "che_명마_15_한혈마" : 2, "che_명마_15_적토마" : 2
|
|
||||||
},
|
|
||||||
"weapon":{
|
|
||||||
"che_무기_01_단도":0, "che_무기_02_단궁":0, "che_무기_03_단극":0,
|
|
||||||
"che_무기_04_목검":0, "che_무기_05_죽창":0, "che_무기_06_소부":0,
|
|
||||||
|
|
||||||
"che_무기_07_동추":2, "che_무기_07_철편":2, "che_무기_07_철쇄":2, "che_무기_07_맥궁":2,
|
|
||||||
"che_무기_08_유성추":2, "che_무기_08_철질여골":2, "che_무기_09_쌍철극":2, "che_무기_09_동호비궁":2,
|
|
||||||
"che_무기_10_삼첨도":2, "che_무기_10_대부":2, "che_무기_11_고정도":2, "che_무기_11_이광궁":2,
|
|
||||||
"che_무기_12_철척사모":2, "che_무기_12_칠성검":2, "che_무기_13_사모":2, "che_무기_13_양유기궁":2,
|
|
||||||
"che_무기_14_언월도":2, "che_무기_14_방천화극":2, "che_무기_15_청홍검":2, "che_무기_15_의천검":2
|
|
||||||
},
|
|
||||||
"book":{
|
|
||||||
"che_서적_01_효경전":0, "che_서적_02_회남자":0, "che_서적_03_변도론":0,
|
|
||||||
"che_서적_04_건상역주":0, "che_서적_05_여씨춘추":0, "che_서적_06_사민월령":0,
|
|
||||||
|
|
||||||
"che_서적_07_위료자":2, "che_서적_07_사마법":2, "che_서적_07_한서":2, "che_서적_07_논어":2,
|
|
||||||
"che_서적_08_전론":2, "che_서적_08_사기":2, "che_서적_09_장자":2, "che_서적_09_역경":2,
|
|
||||||
"che_서적_10_시경":2, "che_서적_10_구국론":2, "che_서적_11_상군서":2, "che_서적_11_춘추전":2,
|
|
||||||
"che_서적_12_산해경":2, "che_서적_12_맹덕신서":2, "che_서적_13_관자":2, "che_서적_13_병법24편":2,
|
|
||||||
"che_서적_14_한비자":2, "che_서적_14_오자병법":2, "che_서적_15_노자":2, "che_서적_15_손자병법":2
|
|
||||||
},
|
|
||||||
"item":{
|
|
||||||
"che_치료_환약":0, "che_저격_수극":0, "che_사기_탁주":0,
|
|
||||||
"che_훈련_청주":0, "che_계략_이추":0, "che_계략_향낭":0,
|
|
||||||
|
|
||||||
"event_전투특기_격노":0, "event_전투특기_견고":0, "event_전투특기_공성":0, "event_전투특기_궁병":0,
|
|
||||||
"event_전투특기_귀병":0, "event_전투특기_기병":0, "event_전투특기_돌격":0, "event_전투특기_무쌍":0,
|
|
||||||
"event_전투특기_반계":0, "event_전투특기_보병":0, "event_전투특기_신산":0, "event_전투특기_신중":0,
|
|
||||||
"event_전투특기_위압":0, "event_전투특기_의술":0, "event_전투특기_저격":0, "event_전투특기_집중":0,
|
|
||||||
"event_전투특기_징병":0, "event_전투특기_척사":0, "event_전투특기_필살":0, "event_전투특기_환술":0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"events":[
|
|
||||||
[
|
|
||||||
"month", 1000,
|
|
||||||
["or", ["Date", "==", null, 12], ["Date", "==", null, 6]],
|
|
||||||
["CreateManyNPC", 15, 10],
|
|
||||||
["DeleteEvent"]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"month", 1000,
|
|
||||||
["Date", "==", 181, 1],
|
|
||||||
["RaiseNPCNation"],
|
|
||||||
["DeleteEvent"]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"month", 999,
|
|
||||||
["Date", "==", 181, 1],
|
|
||||||
["OpenNationBetting", 4, 5000],
|
|
||||||
["OpenNationBetting", 1, 2000],
|
|
||||||
["DeleteEvent"]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"month", 1000,
|
|
||||||
["Date", "==", null, 1],
|
|
||||||
["ChangeCity", "all", {
|
|
||||||
"trade":100
|
|
||||||
}]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"month", 1000,
|
|
||||||
["Date", "==", null, 7],
|
|
||||||
["ChangeCity", "all", {
|
|
||||||
"trade":100
|
|
||||||
}]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "【공백지】 100기 올스타 클래식",
|
|
||||||
"startYear": 180,
|
|
||||||
"map": {
|
|
||||||
"mapName": "miniche",
|
|
||||||
"targetGeneralPool": "SPoolUnderU100",
|
|
||||||
"generalPoolAllowOption": ["stat", "ego", "picture"],
|
|
||||||
"centennialNpcDexTargetRatio": 0.4
|
|
||||||
},
|
|
||||||
"history": [
|
|
||||||
"<C>●</>180년 1월:<L><b>【100기 이벤트】</b></> 역대 장수들이 평범한 능력으로 다시 모여, 지난 전성기의 힘과 서서히 동조하기 시작했다!"
|
|
||||||
],
|
|
||||||
"const": {
|
|
||||||
"npcBanMessageProb":0.005,
|
|
||||||
"defaultMaxGeneral": 800,
|
|
||||||
"uniqueTrialCoef": 2
|
|
||||||
},
|
|
||||||
"events": [
|
|
||||||
[
|
|
||||||
"month", 8000,
|
|
||||||
true,
|
|
||||||
["AdvanceCentennialAllStar"]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"month", 1000,
|
|
||||||
["Date", "==", null, 12],
|
|
||||||
["CreateManyNPC", 100, 0],
|
|
||||||
["DeleteEvent"]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"month", 1000,
|
|
||||||
["Date", "==", 181, 1],
|
|
||||||
["RaiseNPCNation"],
|
|
||||||
["DeleteEvent"]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"destroy_nation", 1000,
|
|
||||||
["and",
|
|
||||||
["Date", ">=", 183, 1],
|
|
||||||
["RemainNation", "==", 1]
|
|
||||||
],
|
|
||||||
["BlockScoutAction"],
|
|
||||||
["DeleteEvent"]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"month", 999,
|
|
||||||
["Date", "==", 181, 1],
|
|
||||||
["OpenNationBetting", 4, 5000],
|
|
||||||
["OpenNationBetting", 1, 2000],
|
|
||||||
["DeleteEvent"]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"month", 999,
|
|
||||||
["and",
|
|
||||||
["Date", ">=", 183, 1],
|
|
||||||
["RemainNation", "<=", 8]
|
|
||||||
],
|
|
||||||
["OpenNationBetting", 1, 1000],
|
|
||||||
["DeleteEvent"]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"destroy_nation", 1000,
|
|
||||||
["and",
|
|
||||||
["Date", ">=", 183, 1],
|
|
||||||
["RemainNation", "==", 1]
|
|
||||||
],
|
|
||||||
["BlockScoutAction"],
|
|
||||||
["DeleteEvent"]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -19,16 +19,8 @@ if ($admin['npcmode'] != 2) {
|
|||||||
|
|
||||||
$member = RootDB::db()->queryFirstRow("SELECT no,name,picture,imgsvr,grade from member where no= %i", $userID);
|
$member = RootDB::db()->queryFirstRow("SELECT no,name,picture,imgsvr,grade from member where no= %i", $userID);
|
||||||
|
|
||||||
$currentGeneral = $db->queryFirstRow(
|
$generalID = $db->queryFirstField('SELECT no FROM general WHERE owner = %i', $userID);
|
||||||
'SELECT no,picture,imgsvr FROM general WHERE owner = %i',
|
|
||||||
$userID
|
|
||||||
);
|
|
||||||
$generalID = $currentGeneral['no'] ?? null;
|
|
||||||
$gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2');
|
$gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2');
|
||||||
$isCentennialAllStar = CentennialAllStarGrowthService::isActive();
|
|
||||||
$canUseOwnPicture = $admin['show_img_level'] >= 1
|
|
||||||
&& $member['grade'] >= 1
|
|
||||||
&& $member['picture'] != "";
|
|
||||||
|
|
||||||
$nationList = $db->query('SELECT nation,`name`,color,scout FROM nation');
|
$nationList = $db->query('SELECT nation,`name`,color,scout FROM nation');
|
||||||
shuffle($nationList);
|
shuffle($nationList);
|
||||||
@@ -62,7 +54,6 @@ foreach (getCharacterList(false) as $id => [$name, $info]) {
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
var hasGeneralID = <?= $generalID === null ? 'false' : 'true' ?>;
|
var hasGeneralID = <?= $generalID === null ? 'false' : 'true' ?>;
|
||||||
var isCentennialAllStar = <?= $isCentennialAllStar ? 'true' : 'false' ?>;
|
|
||||||
var defaultStatTotal = <?= GameConst::$defaultStatTotal ?>;
|
var defaultStatTotal = <?= GameConst::$defaultStatTotal ?>;
|
||||||
var defaultStatMin = <?= GameConst::$defaultStatMin ?>;
|
var defaultStatMin = <?= GameConst::$defaultStatMin ?>;
|
||||||
var defaultStatMax = <?= GameConst::$defaultStatMax ?>;
|
var defaultStatMax = <?= GameConst::$defaultStatMax ?>;
|
||||||
@@ -113,27 +104,6 @@ if ($gencount >= $admin['maxgeneral']) {
|
|||||||
<small id="valid_until">(<span id="valid_until_text"></span>까지 유효)</small><small id="outdate_token">- 만료 -</small><br>
|
<small id="valid_until">(<span id="valid_until_text"></span>까지 유효)</small><small id="outdate_token">- 만료 -</small><br>
|
||||||
<form class="card_holder">
|
<form class="card_holder">
|
||||||
</form>
|
</form>
|
||||||
<?php if ($isCentennialAllStar && $generalID !== null) : ?>
|
|
||||||
<div id="reselect_picture_plate" class="picture_choice">
|
|
||||||
<strong>변경 후 전콘</strong>
|
|
||||||
<label>
|
|
||||||
<input type="radio" name="reselect_picture_source" value="selected" checked>
|
|
||||||
새로 선택할 장수 전콘
|
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
<input type="radio" name="reselect_picture_source" value="current">
|
|
||||||
<img width="32" height="32" src="<?= GetImageURL($currentGeneral['imgsvr']) ?>/<?= $currentGeneral['picture'] ?>" border="0">
|
|
||||||
현재 장수 전콘
|
|
||||||
</label>
|
|
||||||
<?php if ($canUseOwnPicture) : ?>
|
|
||||||
<label>
|
|
||||||
<input type="radio" name="reselect_picture_source" value="own">
|
|
||||||
<img width="32" height="32" src="<?= GetImageURL($member['imgsvr']) ?>/<?= $member['picture'] ?>" border="0">
|
|
||||||
내 원래 전콘
|
|
||||||
</label>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -147,28 +117,7 @@ if ($gencount >= $admin['maxgeneral']) {
|
|||||||
<form id='custom_form'>
|
<form id='custom_form'>
|
||||||
<table class='tb_layout' style='width:100%;text-align:left;'>
|
<table class='tb_layout' style='width:100%;text-align:left;'>
|
||||||
<?php
|
<?php
|
||||||
if ($isCentennialAllStar) {
|
if ($admin['show_img_level'] >= 1 && $member['grade'] >= 1 && $member['picture'] != "") {
|
||||||
echo "
|
|
||||||
<tr class='event_picture'>
|
|
||||||
<td align=right class='bg1'>전콘 선택</td>
|
|
||||||
<td colspan=2>
|
|
||||||
<label><input type=radio name=picture_source value=selected checked> 선택한 장수 전콘</label>
|
|
||||||
";
|
|
||||||
if ($canUseOwnPicture) {
|
|
||||||
$imageTemp = GetImageURL($member['imgsvr']);
|
|
||||||
echo "
|
|
||||||
<label>
|
|
||||||
<input type=radio name=picture_source value=own>
|
|
||||||
<img width='64' height='64' src='{$imageTemp}/{$member['picture']}' border='0'>
|
|
||||||
내 전콘
|
|
||||||
</label>
|
|
||||||
";
|
|
||||||
}
|
|
||||||
echo "
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
";
|
|
||||||
} elseif ($canUseOwnPicture) {
|
|
||||||
$imageTemp = GetImageURL($member['imgsvr']);
|
$imageTemp = GetImageURL($member['imgsvr']);
|
||||||
echo "
|
echo "
|
||||||
<tr class='custom_picture'>
|
<tr class='custom_picture'>
|
||||||
@@ -195,42 +144,36 @@ if ($gencount >= $admin['maxgeneral']) {
|
|||||||
</select> <span id="charInfoText"></span>
|
</select> <span id="charInfoText"></span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php if (!$isCentennialAllStar) : ?>
|
<tr class='custom_stat'>
|
||||||
<tr class='custom_stat'>
|
<td align=right class='bg1'>통솔</td>
|
||||||
<td align=right class='bg1'>통솔</td>
|
<td colspan=2><input type="number" name="leadership" id="leadership" value="50"></td>
|
||||||
<td colspan=2><input type="number" name="leadership" id="leadership" value="50"></td>
|
</tr>
|
||||||
</tr>
|
<tr class='custom_stat'>
|
||||||
<tr class='custom_stat'>
|
<td align=right class='bg1'>무력</td>
|
||||||
<td align=right class='bg1'>무력</td>
|
<td colspan=2><input type="number" name="strength" id="strength" value="50"></td>
|
||||||
<td colspan=2><input type="number" name="strength" id="strength" value="50"></td>
|
</tr>
|
||||||
</tr>
|
<tr class='custom_stat'>
|
||||||
<tr class='custom_stat'>
|
<td align=right class='bg1'>지력</td>
|
||||||
<td align=right class='bg1'>지력</td>
|
<td colspan=2><input type="number" name="intel" id="intel" value="50"></td>
|
||||||
<td colspan=2><input type="number" name="intel" id="intel" value="50"></td>
|
</tr>
|
||||||
</tr>
|
<tr class='custom_stat'>
|
||||||
<tr class='custom_stat'>
|
<td align=right class='bg1'>능력치 조정</td>
|
||||||
<td align=right class='bg1'>능력치 조정</td>
|
<td colspan=2>
|
||||||
<td colspan=2>
|
<input type=button value=랜덤형 onclick=abilityRand()>
|
||||||
<input type=button value=랜덤형 onclick=abilityRand()>
|
<input type=button value=통솔무력형 onclick=abilityLeadpow()>
|
||||||
<input type=button value=통솔무력형 onclick=abilityLeadpow()>
|
<input type=button value=통솔지력형 onclick=abilityLeadint()>
|
||||||
<input type=button value=통솔지력형 onclick=abilityLeadint()>
|
<input type=button value=무력지력형 onclick=abilityPowint()>
|
||||||
<input type=button value=무력지력형 onclick=abilityPowint()>
|
</td>
|
||||||
</td>
|
</tr>
|
||||||
</tr>
|
<tr class='custom_stat'>
|
||||||
<tr class='custom_stat'>
|
<td align=center colspan=3>
|
||||||
<td align=center colspan=3>
|
<font color=orange>모든 능력치는 ( <?= GameConst::$defaultStatMin ?> <= 능력치 <=<?= GameConst::$defaultStatMax ?> ) 사이로 잡으셔야 합니다.<br>
|
||||||
<font color=orange>모든 능력치는 ( <?= GameConst::$defaultStatMin ?> <= 능력치 <=<?= GameConst::$defaultStatMax ?> ) 사이로 잡으셔야 합니다.<br>
|
그 외의 능력치는 가입되지 않습니다.</font>
|
||||||
그 외의 능력치는 가입되지 않습니다.</font>
|
</td>
|
||||||
</td>
|
</tr>
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td align=center colspan=3>
|
<td align=center colspan=3>
|
||||||
<?php if ($isCentennialAllStar) : ?>
|
<span class='custom_stat'>능력치의 총합은 <?= GameConst::$defaultStatTotal ?>입니다. 가입후 0~10의 능력치 보너스를 받게 됩니다.<br></span>
|
||||||
선택한 장수의 최종 능력치 비율을 반영한 약화 능력치로 시작합니다.<br>
|
|
||||||
<?php else : ?>
|
|
||||||
<span class='custom_stat'>능력치의 총합은 <?= GameConst::$defaultStatTotal ?>입니다. 가입후 0~10의 능력치 보너스를 받게 됩니다.<br></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
임의의 도시에서 재야로 시작하며 건국과 임관은 게임 내에서 실행합니다.
|
임의의 도시에서 재야로 시작하며 건국과 임관은 게임 내에서 실행합니다.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
+11
-11
@@ -45,8 +45,8 @@ CREATE TABLE `general` (
|
|||||||
`book` VARCHAR(20) NOT NULL DEFAULT 'None',
|
`book` VARCHAR(20) NOT NULL DEFAULT 'None',
|
||||||
`horse` VARCHAR(20) NOT NULL DEFAULT 'None',
|
`horse` VARCHAR(20) NOT NULL DEFAULT 'None',
|
||||||
`item` VARCHAR(20) NOT NULL DEFAULT 'None',
|
`item` VARCHAR(20) NOT NULL DEFAULT 'None',
|
||||||
`turntime` BIGINT NOT NULL,
|
`turntime` DATETIME(6) NOT NULL,
|
||||||
`recent_war` BIGINT NULL DEFAULT NULL,
|
`recent_war` DATETIME(6) NULL DEFAULT NULL,
|
||||||
`makelimit` INT(2) NULL DEFAULT '0',
|
`makelimit` INT(2) NULL DEFAULT '0',
|
||||||
`killturn` INT(3) NULL DEFAULT NULL,
|
`killturn` INT(3) NULL DEFAULT NULL,
|
||||||
`block` INT(1) NULL DEFAULT '0',
|
`block` INT(1) NULL DEFAULT '0',
|
||||||
@@ -97,7 +97,7 @@ CREATE TABLE `general_access_log` (
|
|||||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||||
`general_id` INT(11) NOT NULL,
|
`general_id` INT(11) NOT NULL,
|
||||||
`user_id` INT(11) NULL DEFAULT NULL,
|
`user_id` INT(11) NULL DEFAULT NULL,
|
||||||
`last_refresh` BIGINT NULL DEFAULT NULL,
|
`last_refresh` DATETIME NULL DEFAULT NULL,
|
||||||
`refresh` INT(11) NOT NULL DEFAULT '0',
|
`refresh` INT(11) NOT NULL DEFAULT '0',
|
||||||
`refresh_total` INT(11) NOT NULL DEFAULT '0',
|
`refresh_total` INT(11) NOT NULL DEFAULT '0',
|
||||||
`refresh_score` INT(11) NOT NULL DEFAULT '0',
|
`refresh_score` INT(11) NOT NULL DEFAULT '0',
|
||||||
@@ -244,8 +244,8 @@ CREATE TABLE `message` (
|
|||||||
`type` ENUM('private', 'national', 'public', 'diplomacy') NOT NULL,
|
`type` ENUM('private', 'national', 'public', 'diplomacy') NOT NULL,
|
||||||
`src` INT(11) NOT NULL,
|
`src` INT(11) NOT NULL,
|
||||||
`dest` INT(11) NOT NULL,
|
`dest` INT(11) NOT NULL,
|
||||||
`time` BIGINT NOT NULL,
|
`time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
`valid_until` BIGINT NOT NULL,
|
`valid_until` DATETIME NOT NULL DEFAULT '9999-12-31 23:59:59',
|
||||||
`message` TEXT NOT NULL COLLATE 'utf8mb4_bin',
|
`message` TEXT NOT NULL COLLATE 'utf8mb4_bin',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
INDEX `by_mailbox` (`mailbox`, `type`, `id`),
|
INDEX `by_mailbox` (`mailbox`, `type`, `id`),
|
||||||
@@ -536,8 +536,8 @@ CREATE TABLE IF NOT EXISTS `reserved_open` (
|
|||||||
CREATE TABLE `select_npc_token` (
|
CREATE TABLE `select_npc_token` (
|
||||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||||
`owner` INT(11) NOT NULL,
|
`owner` INT(11) NOT NULL,
|
||||||
`valid_until` BIGINT NOT NULL,
|
`valid_until` DATETIME NOT NULL,
|
||||||
`pick_more_from` BIGINT NOT NULL,
|
`pick_more_from` DATETIME NOT NULL,
|
||||||
`pick_result` TEXT NOT NULL COLLATE 'utf8mb4_bin',
|
`pick_result` TEXT NOT NULL COLLATE 'utf8mb4_bin',
|
||||||
`nonce` INT(11) NOT NULL,
|
`nonce` INT(11) NOT NULL,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
@@ -553,7 +553,7 @@ CREATE TABLE `select_pool` (
|
|||||||
`unique_name` VARCHAR(20) NOT NULL,
|
`unique_name` VARCHAR(20) NOT NULL,
|
||||||
`owner` INT(11) NULL DEFAULT NULL,
|
`owner` INT(11) NULL DEFAULT NULL,
|
||||||
`general_id` INT(11) NULL DEFAULT NULL,
|
`general_id` INT(11) NULL DEFAULT NULL,
|
||||||
`reserved_until` BIGINT NULL DEFAULT NULL,
|
`reserved_until` DATETIME NULL DEFAULT NULL,
|
||||||
`info` TEXT NOT NULL,
|
`info` TEXT NOT NULL,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE INDEX `unique_name` (`unique_name`),
|
UNIQUE INDEX `unique_name` (`unique_name`),
|
||||||
@@ -694,11 +694,11 @@ CREATE TABLE `ng_auction` (
|
|||||||
`target` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_bin',
|
`target` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_bin',
|
||||||
`host_general_id` INT(11) NOT NULL,
|
`host_general_id` INT(11) NOT NULL,
|
||||||
`req_resource` ENUM('gold','rice','inheritPoint') NOT NULL COLLATE 'utf8mb4_bin',
|
`req_resource` ENUM('gold','rice','inheritPoint') NOT NULL COLLATE 'utf8mb4_bin',
|
||||||
`open_tick` BIGINT NOT NULL,
|
`open_date` DATETIME NOT NULL,
|
||||||
`close_tick` BIGINT NOT NULL,
|
`close_date` DATETIME NOT NULL,
|
||||||
`detail` LONGTEXT NOT NULL COLLATE 'utf8mb4_bin',
|
`detail` LONGTEXT NOT NULL COLLATE 'utf8mb4_bin',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
INDEX `by_close` (`finished`, `type`, `close_tick`) USING BTREE,
|
INDEX `by_close` (`finished`, `type`, `close_date`) USING BTREE,
|
||||||
INDEX `by_general_id` (`host_general_id`, `type`, `finished`) USING BTREE,
|
INDEX `by_general_id` (`host_general_id`, `type`, `finished`) USING BTREE,
|
||||||
CONSTRAINT `detail` CHECK (json_valid(`detail`))
|
CONSTRAINT `detail` CHECK (json_valid(`detail`))
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ import { formatTime } from "@/util/formatTime";
|
|||||||
import { mb_strwidth } from "@/util/mb_strwidth";
|
import { mb_strwidth } from "@/util/mb_strwidth";
|
||||||
import { parseTime } from "@/util/parseTime";
|
import { parseTime } from "@/util/parseTime";
|
||||||
import type { StoredActionsHelper } from "@/util/StoredActionsHelper";
|
import type { StoredActionsHelper } from "@/util/StoredActionsHelper";
|
||||||
import addMinutes from "date-fns/esm/addMinutes/index";
|
import { addMinutes } from "date-fns/addMinutes";
|
||||||
import { range } from "lodash-es";
|
import { range } from "lodash-es";
|
||||||
import { inject, onMounted, ref, type PropType } from "vue";
|
import { inject, onMounted, ref, type PropType } from "vue";
|
||||||
import VueTypes from "vue-types";
|
import VueTypes from "vue-types";
|
||||||
@@ -76,6 +76,7 @@ import DragSelect from "@/components/DragSelect.vue";
|
|||||||
import { BButton } from "bootstrap-vue-next";
|
import { BButton } from "bootstrap-vue-next";
|
||||||
import { QueryActionHelper } from "@/util/QueryActionHelper";
|
import { QueryActionHelper } from "@/util/QueryActionHelper";
|
||||||
import type { ChiefResponse } from "@/defs/API/NationCommand";
|
import type { ChiefResponse } from "@/defs/API/NationCommand";
|
||||||
|
import { VarTurn60 } from "@/varTurn60";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
style: VueTypes.object.isRequired,
|
style: VueTypes.object.isRequired,
|
||||||
@@ -198,10 +199,21 @@ if (!props.officer || !props.officer.turnTime) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const baseTurnTime = parseTime(props.officer.turnTime);
|
const baseTurnTime = parseTime(props.officer.turnTime);
|
||||||
for (const idx of range(props.officer.turn.length)) {
|
if(props.turnTerm == -60){
|
||||||
turnTimes.value.push(
|
const baseTurnTimeObj = VarTurn60.fromDatetime(baseTurnTime);
|
||||||
formatTime(addMinutes(baseTurnTime, idx * props.turnTerm), props.turnTerm >= 5 ? "HH:mm" : "mm:ss")
|
for (const idx of range(props.officer.turn.length)) {
|
||||||
);
|
turnTimes.value.push(
|
||||||
|
formatTime(baseTurnTimeObj.addTurn(idx).toDate(), "HH:mm")
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
for (const idx of range(props.officer.turn.length)) {
|
||||||
|
turnTimes.value.push(
|
||||||
|
formatTime(addMinutes(baseTurnTime, idx * props.turnTerm), props.turnTerm >= 5 ? "HH:mm" : "mm:ss")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -172,7 +172,7 @@
|
|||||||
<BButton class="col-6 offset-6" variant="primary" @click="checkOwner"> 소유자 찾기 </BButton>
|
<BButton class="col-6 offset-6" variant="primary" @click="checkOwner"> 소유자 찾기 </BButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="canResetStat" class="col col-lg-4 col-sm-6 col-12 py-2">
|
<div class="col col-lg-4 col-sm-6 col-12 py-2">
|
||||||
<div class="row px-4">
|
<div class="row px-4">
|
||||||
<div class="a-right col-6 align-self-center">능력치 초기화</div>
|
<div class="a-right col-6 align-self-center">능력치 초기화</div>
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
@@ -222,17 +222,6 @@
|
|||||||
<BButton class="col-6 offset-6" variant="primary" @click="resetStat"> 능력치 초기화</BButton>
|
<BButton class="col-6 offset-6" variant="primary" @click="resetStat"> 능력치 초기화</BButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="col col-lg-4 col-sm-6 col-12 py-2">
|
|
||||||
<div class="row px-4">
|
|
||||||
<div class="a-right col-6 align-self-center">능력치 초기화</div>
|
|
||||||
<div class="col-6 align-self-center">사용 불가</div>
|
|
||||||
</div>
|
|
||||||
<div class="a-right">
|
|
||||||
<small class="form-text text-muted">
|
|
||||||
100기 올스타 장수는 장수 전환 시 능력치 성장 기록을 보존하기 위해 능력치 초기화를 사용할 수 없습니다.
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
@@ -308,7 +297,6 @@ declare const staticValues: {
|
|||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
availableTargetGeneral: Record<number, string>;
|
availableTargetGeneral: Record<number, string>;
|
||||||
canResetStat: boolean;
|
|
||||||
currentStat: {
|
currentStat: {
|
||||||
leadership: number;
|
leadership: number;
|
||||||
strength: number;
|
strength: number;
|
||||||
@@ -322,14 +310,13 @@ declare const staticValues: {
|
|||||||
import { reactive, ref, watch } from "vue";
|
import { reactive, ref, watch } from "vue";
|
||||||
import "@scss/game_bg.scss";
|
import "@scss/game_bg.scss";
|
||||||
import TopBackBar from "@/components/TopBackBar.vue";
|
import TopBackBar from "@/components/TopBackBar.vue";
|
||||||
import _ from "lodash-es";
|
import { sum } from "lodash-es";
|
||||||
import NumberInputWithInfo from "@/components/NumberInputWithInfo.vue";
|
import NumberInputWithInfo from "@/components/NumberInputWithInfo.vue";
|
||||||
import { SammoAPI } from "./SammoAPI";
|
import { SammoAPI } from "./SammoAPI";
|
||||||
import { InheritResetStat, type inheritBuffType, type InheritPointLogItem } from "./defs/API/InheritAction";
|
import { InheritResetStat, type inheritBuffType, type InheritPointLogItem } from "./defs/API/InheritAction";
|
||||||
import * as JosaUtil from "@/util/JosaUtil";
|
import * as JosaUtil from "@/util/JosaUtil";
|
||||||
import { BButton } from "bootstrap-vue-next";
|
import { BButton } from "bootstrap-vue-next";
|
||||||
import { unwrap } from "./util/unwrap";
|
import { unwrap } from "./util/unwrap";
|
||||||
import { add as dateAdd } from 'date-fns';
|
|
||||||
|
|
||||||
const inheritanceViewText: Record<InheritanceViewType, { title: string; info: string }> = {
|
const inheritanceViewText: Record<InheritanceViewType, { title: string; info: string }> = {
|
||||||
sum: {
|
sum: {
|
||||||
@@ -440,7 +427,7 @@ const title = "유산 관리";
|
|||||||
|
|
||||||
const items = ref(
|
const items = ref(
|
||||||
(() => {
|
(() => {
|
||||||
const totalPoint = Math.floor(_.sum(Object.values(staticValues.items)));
|
const totalPoint = Math.floor(sum(Object.values(staticValues.items)));
|
||||||
const previousPoint = Math.floor(staticValues.items["previous"]);
|
const previousPoint = Math.floor(staticValues.items["previous"]);
|
||||||
const newPoint = Math.floor(totalPoint - previousPoint);
|
const newPoint = Math.floor(totalPoint - previousPoint);
|
||||||
const result: Record<InheritanceViewType, number> = {
|
const result: Record<InheritanceViewType, number> = {
|
||||||
@@ -459,7 +446,6 @@ const {
|
|||||||
availableSpecialWar,
|
availableSpecialWar,
|
||||||
availableUnique,
|
availableUnique,
|
||||||
availableTargetGeneral,
|
availableTargetGeneral,
|
||||||
canResetStat,
|
|
||||||
currentStat
|
currentStat
|
||||||
} = staticValues;
|
} = staticValues;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -485,7 +485,7 @@ watch(inheritCity, (newValue: undefined | number) => {
|
|||||||
const inheritTurnTimeZone = ref<number>();
|
const inheritTurnTimeZone = ref<number>();
|
||||||
const turnTimeZoneList: string[] = (()=>{
|
const turnTimeZoneList: string[] = (()=>{
|
||||||
const result: string[] = [];
|
const result: string[] = [];
|
||||||
const zoneSec = turnterm; // * 60 / 60
|
const zoneSec = Math.abs(turnterm); // * 60 / 60
|
||||||
let zoneCur = 0;
|
let zoneCur = 0;
|
||||||
for(const idx of range(60)){
|
for(const idx of range(60)){
|
||||||
const zoneNext = zoneCur + zoneSec;
|
const zoneNext = zoneCur + zoneSec;
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ declare const staticValues: {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import addMinutes from "date-fns/esm/addMinutes";
|
import { addMinutes } from "date-fns/addMinutes";
|
||||||
import { isString, range, trim } from "lodash-es";
|
import { isString, range, trim } from "lodash-es";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import { onMounted, ref, watch } from "vue";
|
import { onMounted, ref, watch } from "vue";
|
||||||
@@ -297,6 +297,7 @@ import { QueryActionHelper } from "./util/QueryActionHelper";
|
|||||||
import SimpleClock from "./components/SimpleClock.vue";
|
import SimpleClock from "./components/SimpleClock.vue";
|
||||||
import type { ReservedCommandResponse } from "./defs/API/Command";
|
import type { ReservedCommandResponse } from "./defs/API/Command";
|
||||||
import { unwrap } from "./util/unwrap";
|
import { unwrap } from "./util/unwrap";
|
||||||
|
import { VarTurn60 } from "./varTurn60";
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
updateCommandTable,
|
updateCommandTable,
|
||||||
@@ -544,7 +545,13 @@ async function reloadCommandList() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
yearMonth += 1;
|
yearMonth += 1;
|
||||||
nextTurnTime = addMinutes(nextTurnTime, result.turnTerm);
|
if(result.turnTerm == -60){
|
||||||
|
nextTurnTime = VarTurn60.fromDatetime(nextTurnTime).addTurn(1).toDate();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
nextTurnTime = addMinutes(nextTurnTime, result.turnTerm);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
serverNow.value = parseTime(result.date);
|
serverNow.value = parseTime(result.date);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { AutoLoginFailed, AutoLoginNonceResponse, AutoLoginResponse, LoginFailed, LoginResponse } from "./defs/API/Login";
|
import type { AutoLoginFailed, AutoLoginNonceResponse, AutoLoginResponse, LoginFailed, LoginResponse } from "./defs/API/Login";
|
||||||
import { APIPathGen } from "./util/APIPathGen";
|
import { APIPathGen } from "./util/APIPathGen";
|
||||||
import { callSammoAPI, extractHttpMethod, POST, type APICallT, type APITail, type InvalidResponse, type RawArgType, type ValidResponse } from "./util/callSammoAPI";
|
import { callSammoAPI, extractHttpMethod, GET, POST, type APICallT, type APITail, type InvalidResponse, type RawArgType, type ValidResponse } from "./util/callSammoAPI";
|
||||||
export type { ValidResponse, InvalidResponse };
|
export type { ValidResponse, InvalidResponse };
|
||||||
|
|
||||||
const apiRealPath = {
|
const apiRealPath = {
|
||||||
@@ -18,7 +18,7 @@ const apiRealPath = {
|
|||||||
hashedToken: string,
|
hashedToken: string,
|
||||||
token_id: number,
|
token_id: number,
|
||||||
}, AutoLoginResponse, AutoLoginFailed>,
|
}, AutoLoginResponse, AutoLoginFailed>,
|
||||||
ReqNonce: POST as APICallT<undefined, AutoLoginNonceResponse, AutoLoginFailed>
|
ReqNonce: GET as APICallT<undefined, AutoLoginNonceResponse, AutoLoginFailed>
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
|||||||
@@ -256,7 +256,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import addMinutes from "date-fns/esm/addMinutes";
|
import { addMinutes } from "date-fns/addMinutes";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import { onMounted, ref, watch, type PropType, inject, type Ref } from "vue";
|
import { onMounted, ref, watch, type PropType, inject, type Ref } from "vue";
|
||||||
import { formatTime } from "@util/formatTime";
|
import { formatTime } from "@util/formatTime";
|
||||||
@@ -282,6 +282,7 @@ import { unwrap_err } from "@/util/unwrap_err";
|
|||||||
import type { GameConstStore } from "@/GameConstStore";
|
import type { GameConstStore } from "@/GameConstStore";
|
||||||
import { postFilterNationCommandGen } from "@/utilGame/postFilterNationCommandGen";
|
import { postFilterNationCommandGen } from "@/utilGame/postFilterNationCommandGen";
|
||||||
import { unwrap } from "@/util/unwrap";
|
import { unwrap } from "@/util/unwrap";
|
||||||
|
import { VarTurn60 } from "@/varTurn60";
|
||||||
|
|
||||||
const toasts = unwrap(useToast());
|
const toasts = unwrap(useToast());
|
||||||
|
|
||||||
@@ -536,13 +537,19 @@ function updateCommandList() {
|
|||||||
...obj,
|
...obj,
|
||||||
year,
|
year,
|
||||||
month,
|
month,
|
||||||
time: formatTime(nextTurnTime, props.turnTerm >= 5 ? "HH:mm" : "mm:ss"),
|
time: formatTime(nextTurnTime, Math.abs(props.turnTerm) >= 5 ? "HH:mm" : "mm:ss"),
|
||||||
tooltip: tooltip.length == 0 ? undefined : tooltip.join("\n"),
|
tooltip: tooltip.length == 0 ? undefined : tooltip.join("\n"),
|
||||||
style,
|
style,
|
||||||
});
|
});
|
||||||
|
|
||||||
yearMonth += 1;
|
yearMonth += 1;
|
||||||
nextTurnTime = addMinutes(nextTurnTime, props.turnTerm);
|
|
||||||
|
if(props.turnTerm == -60){
|
||||||
|
nextTurnTime = VarTurn60.fromDatetime(nextTurnTime).addTurn(1).toDate();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
nextTurnTime = addMinutes(nextTurnTime, props.turnTerm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
reservedCommandList.value = _reservedCommandList;
|
reservedCommandList.value = _reservedCommandList;
|
||||||
updated.value = true;
|
updated.value = true;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<AutorunInfo :autorunMode="globalInfo.autorunUser" />
|
<AutorunInfo :autorunMode="globalInfo.autorunUser" />
|
||||||
</div>
|
</div>
|
||||||
<div class="s-border-t col py-2 col-8 col-lg-4 subYearMonth">
|
<div class="s-border-t col py-2 col-8 col-lg-4 subYearMonth">
|
||||||
현재: {{ globalInfo.year }}年 {{ globalInfo.month }}月 ({{ globalInfo.turnterm }}분 턴 서버)
|
현재: {{ globalInfo.year }}年 {{ globalInfo.month }}月 ({{ globalInfo.turnterm == -60 ? '가변 60' : globalInfo.turnterm }}분 턴 서버)
|
||||||
</div>
|
</div>
|
||||||
<div class="s-border-t col py-2 col-4 col-lg-2 subOnlineUserCnt">
|
<div class="s-border-t col py-2 col-4 col-lg-2 subOnlineUserCnt">
|
||||||
전체 접속자 수: {{ (globalInfo.onlineUserCnt ?? 0).toLocaleString() }}명
|
전체 접속자 수: {{ (globalInfo.onlineUserCnt ?? 0).toLocaleString() }}명
|
||||||
|
|||||||
@@ -175,8 +175,9 @@ import { clamp } from "lodash-es";
|
|||||||
import { formatCityName } from "@/utilGame/formatCityName";
|
import { formatCityName } from "@/utilGame/formatCityName";
|
||||||
import { isValidObjKey } from "@/utilGame/isValidObjKey";
|
import { isValidObjKey } from "@/utilGame/isValidObjKey";
|
||||||
import { calcInjury } from "@/utilGame/calcInjury";
|
import { calcInjury } from "@/utilGame/calcInjury";
|
||||||
import { addMinutes } from "date-fns/esm";
|
import { addMinutes } from "date-fns/addMinutes";
|
||||||
import type { GameIActionInfo } from "@/defs/GameObj";
|
import type { GameIActionInfo } from "@/defs/GameObj";
|
||||||
|
import { VarTurn60 } from "@/varTurn60";
|
||||||
const imagePath = window.pathConfig.gameImage;
|
const imagePath = window.pathConfig.gameImage;
|
||||||
const gameConstStore = unwrap(inject<Ref<GameConstStore>>("gameConstStore"));
|
const gameConstStore = unwrap(inject<Ref<GameConstStore>>("gameConstStore"));
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -278,7 +279,12 @@ watch(
|
|||||||
() => {
|
() => {
|
||||||
let turnTime = parseTime(general.value.turntime);
|
let turnTime = parseTime(general.value.turntime);
|
||||||
if (turnTime.getTime() < props.lastExecuted.getTime()) {
|
if (turnTime.getTime() < props.lastExecuted.getTime()) {
|
||||||
turnTime = addMinutes(turnTime, props.turnTerm);
|
if(props.turnTerm == -60){
|
||||||
|
turnTime = VarTurn60.fromDatetime(turnTime).addTurn(1).toDate();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
turnTime = addMinutes(turnTime, props.turnTerm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
nextExecuteMinute.value = Math.floor(clamp((turnTime.getTime() - props.lastExecuted.getTime()) / 60000, 0, 999));
|
nextExecuteMinute.value = Math.floor(clamp((turnTime.getTime() - props.lastExecuted.getTime()) / 60000, 0, 999));
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -127,7 +127,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { MsgItem, MsgTarget, MsgType } from "@/defs/API/Message";
|
import type { MsgItem, MsgTarget, MsgType } from "@/defs/API/Message";
|
||||||
import { parseTime } from "@/util/parseTime";
|
import { parseTime } from "@/util/parseTime";
|
||||||
import { differenceInMilliseconds, addMinutes } from "date-fns/esm";
|
import { addMinutes, differenceInMilliseconds } from "date-fns";
|
||||||
import { computed, onMounted, ref, toRef, watch, type ComputedRef, type Ref } from "vue";
|
import { computed, onMounted, ref, toRef, watch, type ComputedRef, type Ref } from "vue";
|
||||||
import linkifyStr from "linkify-string";
|
import linkifyStr from "linkify-string";
|
||||||
import { SammoAPI } from "@/SammoAPI";
|
import { SammoAPI } from "@/SammoAPI";
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ $(function () {
|
|||||||
const runAnalysis = async function () {
|
const runAnalysis = async function () {
|
||||||
let realKillturn = killturn;
|
let realKillturn = killturn;
|
||||||
if(autorun_user && autorun_user.limit_minutes){
|
if(autorun_user && autorun_user.limit_minutes){
|
||||||
realKillturn -= autorun_user.limit_minutes / turnterm;
|
realKillturn -= autorun_user.limit_minutes / Math.abs(turnterm);
|
||||||
}
|
}
|
||||||
const $content = $('#on_mover .content');
|
const $content = $('#on_mover .content');
|
||||||
try {
|
try {
|
||||||
|
|||||||
+33
-48
@@ -37,16 +37,14 @@ function regNextToken(tokenInfo: [number, string]) {
|
|||||||
function getToken(): [number, string] | undefined {
|
function getToken(): [number, string] | undefined {
|
||||||
const trialToken = localStorage.getItem(LOGIN_TOKEN_KEY);
|
const trialToken = localStorage.getItem(LOGIN_TOKEN_KEY);
|
||||||
if (!trialToken) {
|
if (!trialToken) {
|
||||||
console.log('no token');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const tokenItems = JSON.parse(trialToken) as [number, [number, string], number];
|
const tokenItems = JSON.parse(trialToken) as [number, [number, string], string];
|
||||||
if (tokenItems[0] != TOKEN_VERSION) {
|
if (tokenItems[0] != TOKEN_VERSION) {
|
||||||
console.log(tokenItems);
|
console.log(tokenItems);
|
||||||
resetToken();
|
resetToken();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.debug(localStorage.getItem(LOGIN_TOKEN_KEY));
|
|
||||||
const [, token,] = tokenItems;
|
const [, token,] = tokenItems;
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
@@ -64,54 +62,39 @@ async function tryAutoLogin() {
|
|||||||
|
|
||||||
const [tokenID, token] = tokenInfo;
|
const [tokenID, token] = tokenInfo;
|
||||||
|
|
||||||
for (let attempt = 0; attempt < 2; attempt++) {
|
const result = await SammoRootAPI.Login.ReqNonce(undefined, true);
|
||||||
const reqNonceStartAt = Date.now();
|
|
||||||
const nonceResult = await SammoRootAPI.Login.ReqNonce(undefined, true);
|
|
||||||
|
|
||||||
if (!nonceResult) {
|
if (!result) {
|
||||||
//api 에러.
|
//api 에러.
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nonceResult.result) {
|
|
||||||
resetToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nonce = nonceResult.loginNonce;
|
|
||||||
console.debug(
|
|
||||||
'try auto login with token',
|
|
||||||
tokenID,
|
|
||||||
`attempt:${attempt + 1}`,
|
|
||||||
`reqNonceElapsed:${Date.now() - reqNonceStartAt}ms`
|
|
||||||
);
|
|
||||||
|
|
||||||
const hashedToken = sha512(token + nonce);
|
|
||||||
const loginResult = await SammoRootAPI.Login.LoginByToken({
|
|
||||||
'hashedToken': hashedToken,
|
|
||||||
'token_id': tokenID,
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
if (!loginResult.result) {
|
|
||||||
if (loginResult.reason === '자동 로그인: 절차 오류' && attempt === 0) {
|
|
||||||
console.warn('auto login failed by procedure error. retrying once.');
|
|
||||||
await delay(150);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!loginResult.silent) {
|
|
||||||
alert(loginResult.reason);
|
|
||||||
}
|
|
||||||
console.error(loginResult.reason);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loginResult.nextToken) {
|
|
||||||
regNextToken(loginResult.nextToken);
|
|
||||||
}
|
|
||||||
window.location.href = "./";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!result.result) {
|
||||||
|
resetToken();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nonce = result.loginNonce;
|
||||||
|
|
||||||
|
const hashedToken = sha512(token + nonce);
|
||||||
|
const loginResult = await SammoRootAPI.Login.LoginByToken({
|
||||||
|
'hashedToken': hashedToken,
|
||||||
|
'token_id': tokenID,
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
if (!loginResult.result) {
|
||||||
|
if (!loginResult.silent) {
|
||||||
|
alert(loginResult.reason);
|
||||||
|
}
|
||||||
|
console.error(loginResult.reason);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loginResult.nextToken) {
|
||||||
|
regNextToken(loginResult.nextToken);
|
||||||
|
}
|
||||||
|
window.location.href = "./";
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (isString(e)) {
|
if (isString(e)) {
|
||||||
@@ -120,6 +103,8 @@ async function tryAutoLogin() {
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOAuthToken(mode: string, scope_list?: string[] | string) {
|
function getOAuthToken(mode: string, scope_list?: string[] | string) {
|
||||||
|
|||||||
+1
-1
@@ -147,7 +147,7 @@ const descriptor: NamedRules<InstallFormType> = {
|
|||||||
turnterm: {
|
turnterm: {
|
||||||
required: true,
|
required: true,
|
||||||
type: "enum",
|
type: "enum",
|
||||||
enum: [1, 2, 5, 10, 20, 30, 60, 120],
|
enum: [1, 2, 5, 10, 20, 30, 60, 120, -60],
|
||||||
transform: parseInt,
|
transform: parseInt,
|
||||||
},
|
},
|
||||||
sync: {
|
sync: {
|
||||||
|
|||||||
+3
-3
@@ -6,7 +6,7 @@ import axios from 'axios';
|
|||||||
import { convertFormData } from '@util/convertFormData';
|
import { convertFormData } from '@util/convertFormData';
|
||||||
import { isBrightColor } from "@util/isBrightColor";
|
import { isBrightColor } from "@util/isBrightColor";
|
||||||
import { unwrap } from '@util/unwrap';
|
import { unwrap } from '@util/unwrap';
|
||||||
import _, { isError, isString } from 'lodash-es';
|
import { isError, isString, last, trim } from 'lodash-es';
|
||||||
import { addMinutes } from 'date-fns';
|
import { addMinutes } from 'date-fns';
|
||||||
import { parseTime } from '@util/parseTime';
|
import { parseTime } from '@util/parseTime';
|
||||||
import { formatTime } from '@util/formatTime';
|
import { formatTime } from '@util/formatTime';
|
||||||
@@ -234,7 +234,7 @@ function redrawMsg(msgResponse: MsgResponse, addFront: boolean): MsgResponse {
|
|||||||
if (!msgList || msgList.length == 0) {
|
if (!msgList || msgList.length == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const lastMsg = unwrap(_.last(msgList));
|
const lastMsg = unwrap(last(msgList));
|
||||||
minMsgSeq[msgType] = Math.min(minMsgSeq[msgType], lastMsg.id);
|
minMsgSeq[msgType] = Math.min(minMsgSeq[msgType], lastMsg.id);
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
@@ -605,7 +605,7 @@ function activateMessageForm() {
|
|||||||
|
|
||||||
$msgSubmit.on('click', async function () {
|
$msgSubmit.on('click', async function () {
|
||||||
|
|
||||||
const text = _.trim(unwrap_any<string>($msgInput.val()));
|
const text = trim(unwrap_any<string>($msgInput.val()));
|
||||||
$msgInput.val('').trigger('focus');
|
$msgInput.val('').trigger('focus');
|
||||||
|
|
||||||
const targetMailbox = unwrap_any<string>($mailboxList.val());
|
const targetMailbox = unwrap_any<string>($mailboxList.val());
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user