Compare commits
101
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed3c84aa8e | ||
|
|
f4a1e2258d | ||
|
|
4ffd7b5bc0 | ||
|
|
e7c773709d | ||
|
|
1e30659bdd | ||
|
|
162f198f08 | ||
|
|
4aa09a294e | ||
|
|
191abf83c0 | ||
|
|
edfeae5f0f | ||
|
|
424184a51a | ||
|
|
03a321f95d | ||
|
|
e3615fa6bb | ||
|
|
32991f736d | ||
|
|
8b2748d3d4 | ||
|
|
883080e275 | ||
|
|
ce807e2564 | ||
|
|
9a2ac82373 | ||
|
|
3c35539c16 | ||
|
|
5ab08403c6 | ||
|
|
c1ce478d22 | ||
|
|
d8bf8ba922 | ||
|
|
95f66e4c39 | ||
|
|
4de7ebec17 | ||
|
|
d43dff35fb | ||
|
|
5b13f8bd30 | ||
|
|
e51bc6f711 | ||
|
|
1b08aa0c58 | ||
|
|
f2547fe207 | ||
|
|
cec7726731 | ||
|
|
d679a6fed8 | ||
|
|
6fe156eb7c | ||
|
|
663ddbe76a | ||
|
|
30297454f7 | ||
|
|
bc602722bf | ||
|
|
be8f147216 | ||
|
|
b9495fb64a | ||
|
|
07b217b290 | ||
|
|
42fac46062 | ||
|
|
24bc8985d0 | ||
|
|
76a2d5ff63 | ||
|
|
148f32f78b | ||
|
|
62f5b6597e | ||
|
|
7e810b0279 | ||
|
|
2336b29b65 | ||
|
|
185c0e16a0 | ||
|
|
656baeb9ee | ||
|
|
3e06304dc7 | ||
|
|
4bb940c8c5 | ||
|
|
2b376b6aab | ||
|
|
04df26ff83 | ||
|
|
aca4240b92 | ||
|
|
faf26fa8a2 | ||
|
|
030ab1e7ea | ||
|
|
7f2c1d4782 | ||
|
|
9132138a99 | ||
|
|
84875d60bd | ||
|
|
3cbaf76626 | ||
|
|
f4846d0d66 | ||
|
|
f183dcc72b | ||
|
|
63cc5d8e88 | ||
|
|
f858c32fdf | ||
|
|
60eb127d71 | ||
|
|
ede33f3a37 | ||
|
|
ffd53a2390 | ||
|
|
2591fbde67 | ||
|
|
922d3f1938 | ||
|
|
64522ba8a6 | ||
|
|
7b1eedb574 | ||
|
|
7ec6ca605f | ||
|
|
5a5c613814 | ||
|
|
1a3ef20a35 | ||
|
|
fba966177d | ||
|
|
62c72dfdbe | ||
|
|
1ae1ff9b72 | ||
|
|
c1e12c2737 | ||
|
|
de09a66d6f | ||
|
|
3c2012da46 | ||
|
|
d55be54320 | ||
|
|
dcbefa1a96 | ||
|
|
be8f1fff96 | ||
|
|
6117dbdcc0 | ||
|
|
0a39ba1023 | ||
|
|
dae5f65baa | ||
|
|
080bb30103 | ||
|
|
9e647c7ce5 | ||
|
|
73606b0fb4 | ||
|
|
e62eb36cc2 | ||
|
|
6b81f744d4 | ||
|
|
1a9b3b78cb | ||
|
|
c3cbf956d0 | ||
|
|
91188c555d | ||
|
|
913028dd6c | ||
|
|
dfb3f6478d | ||
|
|
6afc6221d3 | ||
|
|
7b5a02487e | ||
|
|
533b79762e | ||
|
|
53b7dbfdd0 | ||
|
|
fd14c5403b | ||
|
|
dc476e73a1 | ||
|
|
e60150705e | ||
|
|
2869ba5c42 |
@@ -12,7 +12,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"brandonwamboldt/utilphp": "^1.1",
|
|
||||||
"sergeytsalkov/meekrodb": "^2.5",
|
"sergeytsalkov/meekrodb": "^2.5",
|
||||||
"league/plates": "^3.5",
|
"league/plates": "^3.5",
|
||||||
"vlucas/valitron": "^1.4",
|
"vlucas/valitron": "^1.4",
|
||||||
|
|||||||
Generated
+2
-52
@@ -4,58 +4,8 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "deed9afdc95bc42f84784df67d295223",
|
"content-hash": "7edae9b6be35e66ffd0d180f5fac6679",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
|
||||||
"name": "brandonwamboldt/utilphp",
|
|
||||||
"version": "1.1.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/brandonwamboldt/utilphp.git",
|
|
||||||
"reference": "36c32efc4f0679c05163464a550f45c8d83fe683"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/brandonwamboldt/utilphp/zipball/36c32efc4f0679c05163464a550f45c8d83fe683",
|
|
||||||
"reference": "36c32efc4f0679c05163464a550f45c8d83fe683",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.3.3"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"satooshi/php-coveralls": "dev-master"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-0": {
|
|
||||||
"utilphp\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Brandon Wamboldt",
|
|
||||||
"email": "brandon.wamboldt@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "util.php is a collection of useful functions and snippets that you need or could use every day, designed to avoid conflicts with existing projects",
|
|
||||||
"homepage": "https://github.com/brandonwamboldt/utilphp",
|
|
||||||
"keywords": [
|
|
||||||
"collection",
|
|
||||||
"helpers",
|
|
||||||
"php",
|
|
||||||
"utility"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/brandonwamboldt/utilphp/issues",
|
|
||||||
"source": "https://github.com/brandonwamboldt/utilphp/tree/master"
|
|
||||||
},
|
|
||||||
"time": "2015-02-02T17:56:14+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
"version": "0.12.1",
|
"version": "0.12.1",
|
||||||
@@ -5721,5 +5671,5 @@
|
|||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "8.3"
|
"php": "8.3"
|
||||||
},
|
},
|
||||||
"plugin-api-version": "2.3.0"
|
"plugin-api-version": "2.6.0"
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -99,7 +99,10 @@ function logError(string $err, string $errstr, string $errpath, array $trace)
|
|||||||
$err = str_replace(ROOT, '{ROOT}', $err);
|
$err = str_replace(ROOT, '{ROOT}', $err);
|
||||||
$errstr = str_replace(ROOT, '{ROOT}', $errstr);
|
$errstr = str_replace(ROOT, '{ROOT}', $errstr);
|
||||||
$errpath = str_replace(ROOT, '{ROOT}', $errpath);
|
$errpath = str_replace(ROOT, '{ROOT}', $errpath);
|
||||||
$trace = array_map(function (string $text) {
|
$trace = array_map(function (string|array $text) {
|
||||||
|
if (is_array($text)) {
|
||||||
|
$text = Json::encode($text);
|
||||||
|
}
|
||||||
return str_replace(ROOT, '{ROOT}', $text);
|
return str_replace(ROOT, '{ROOT}', $text);
|
||||||
}, $trace);
|
}, $trace);
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -13,6 +13,9 @@ $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"');
|
||||||
?>
|
?>
|
||||||
@@ -30,8 +33,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='분지연'> 최종갱신 : <?=$turntime?><br>
|
시간조정 : <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=minute2><input type=submit name=btn value='토너분당김'><input type=submit name=btn value='토너분지연'> 토너먼트 : <?=$tnmt_time?><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=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>
|
||||||
|
|||||||
+9
-36
@@ -38,21 +38,9 @@ switch ($btn) {
|
|||||||
usleep(500000);
|
usleep(500000);
|
||||||
}
|
}
|
||||||
|
|
||||||
$gameStor->cacheValues(['turntime', 'starttime', 'tnmt_time']);
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
$turntime = (new \DateTimeImmutable($gameStor->turntime))->sub(new \DateInterval("PT{$minute}M"));
|
// 스케줄 전체를 벽시계에서 빼지 않고 논리 현재 tick만 앞으로 이동합니다.
|
||||||
$starttime = (new \DateTimeImmutable($gameStor->starttime))->sub(new \DateInterval("PT{$minute}M"));
|
$clock->advance($gameStor, $clock->ticksFromMinutes($minute));
|
||||||
$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();
|
||||||
}
|
}
|
||||||
@@ -66,34 +54,19 @@ switch ($btn) {
|
|||||||
}
|
}
|
||||||
usleep(500000);
|
usleep(500000);
|
||||||
}
|
}
|
||||||
$gameStor->cacheValues(['turntime', 'starttime', 'tnmt_time']);
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
$turntime = (new \DateTimeImmutable($gameStor->turntime))->add(new \DateInterval("PT{$minute}M"));
|
$clock->advance($gameStor, -$clock->ticksFromMinutes($minute));
|
||||||
$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 "토너분당김":
|
||||||
$tnmt_time = new \DateTime($gameStor->tnmt_time);
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
$tnmt_time->sub(new \DateInterval("PT{$minute2}M"));
|
$gameStor->tnmt_time = Util::toInt($gameStor->tnmt_time) - $clock->ticksFromMinutes($minute2);
|
||||||
$gameStor->tnmt_time = $tnmt_time->format('Y-m-d H:i:s');
|
|
||||||
break;
|
break;
|
||||||
case "토너분지연":
|
case "토너분지연":
|
||||||
$tnmt_time = new \DateTimeImmutable($gameStor->tnmt_time);
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
$tnmt_time->add(new \DateInterval("PT{$minute2}M"));
|
$gameStor->tnmt_time = Util::toInt($gameStor->tnmt_time) + $clock->ticksFromMinutes($minute2);
|
||||||
$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'], 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_display'], 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']?></td>
|
<td width=285> <?=$admin['turntime_display']?> (tick <?=$admin['turntime']?>)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width=110 align=right>턴시간</td>
|
<td width=110 align=right>턴시간</td>
|
||||||
|
|||||||
@@ -43,7 +43,12 @@ switch ($btn) {
|
|||||||
pushGlobalHistoryLog(["<R>★</><S>{$log}</>"]);
|
pushGlobalHistoryLog(["<R>★</><S>{$log}</>"]);
|
||||||
break;
|
break;
|
||||||
case "변경1":
|
case "변경1":
|
||||||
$gameStor->starttime = (new \DateTime($starttime))->format('Y-m-d H:i:s');
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
|
$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;
|
||||||
@@ -78,4 +83,4 @@ switch ($btn) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
header('location:_admin1.php');
|
header('location:_admin1.php');
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ switch ($btn) {
|
|||||||
], '`no` IN %li', $genlist);
|
], '`no` IN %li', $genlist);
|
||||||
break;
|
break;
|
||||||
case "강제 사망":
|
case "강제 사망":
|
||||||
$date = TimeUtil::now(true);
|
$date = GameClock::fromStorage($gameStor)->nowTick();
|
||||||
$db->update('general', [
|
$db->update('general', [
|
||||||
'killturn' => 0,
|
'killturn' => 0,
|
||||||
'turntime' => $date,
|
'turntime' => $date,
|
||||||
|
|||||||
+4
-3
@@ -31,7 +31,7 @@ $queryMap = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
if ($reqQueryType === null || !key_exists($reqQueryType, $queryMap)) {
|
if ($reqQueryType === null || !key_exists($reqQueryType, $queryMap)) {
|
||||||
$reqQueryType = Util::array_first_key($queryMap);
|
$reqQueryType = array_key_first($queryMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
//로그인 검사
|
//로그인 검사
|
||||||
@@ -42,6 +42,7 @@ 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;
|
||||||
@@ -111,7 +112,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($general['turntime'], 14, 5) ?>)</option>
|
<option <?= $gen == $general['no'] ? 'selected' : '' ?> value='<?= $general['no'] ?>'><?= $general['name'] ?> (<?= substr($clock->formatTick(Util::toInt($general['turntime'])), 14, 5) ?>)</option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
<input type=submit name=btn value='조회하기'>
|
<input type=submit name=btn value='조회하기'>
|
||||||
@@ -179,4 +180,4 @@ $generalObj = General::createObjFromDB($gen, null, GeneralQueryMode::FullWithAcc
|
|||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -243,11 +243,14 @@ $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
|
horse, weapon, book, item, aux
|
||||||
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']];
|
||||||
@@ -427,4 +430,4 @@ $templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
|||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -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($gameStor->turntime, 5, 14);
|
$lastExecute = substr(GameClock::fromStorage($gameStor)->formatTick(Util::toInt($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']) ?? [
|
||||||
@@ -537,4 +537,4 @@ $templates = new \League\Plates\Engine('templates');
|
|||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+3
-1
@@ -129,6 +129,7 @@ $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',
|
||||||
@@ -142,6 +143,7 @@ $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']] ?? '-';
|
||||||
|
|
||||||
@@ -284,4 +286,4 @@ $templates = new \League\Plates\Engine('templates');
|
|||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+30
-12
@@ -19,10 +19,10 @@ $userID = Session::getUserID();
|
|||||||
$generalID = $session->generalID;
|
$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);
|
||||||
increaseRefresh("내정보", 1);
|
$nowTick = $clock->nowTick();
|
||||||
|
|
||||||
$me = General::createObjFromDB($generalID, null, GeneralQueryMode::FullWithAccessLog);
|
$me = General::createObjFromDB($generalID, null, GeneralQueryMode::FullWithAccessLog);
|
||||||
|
|
||||||
@@ -41,12 +41,30 @@ $lastRefresh = $db->queryFirstField(
|
|||||||
$generalID
|
$generalID
|
||||||
);
|
);
|
||||||
|
|
||||||
$targetTime = addTurn($lastRefresh, $gameStor->turnterm, GameConst::$minTurnDieOnPrestart);
|
$nextChange = $me->getAuxVar('next_change');
|
||||||
if ($gameStor->turntime <= $gameStor->opentime) {
|
if (!is_int($nextChange)) {
|
||||||
//서버 가오픈시 할 수 있는 행동
|
$nextChange = null;
|
||||||
if ($me->getNPCType() == 0 && $me->getNationID() == 0) {
|
}
|
||||||
|
$nextChangeDisplay = $nextChange === null ? null : $clock->formatTick($nextChange);
|
||||||
|
|
||||||
|
increaseRefresh("내정보", 1);
|
||||||
|
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) {
|
||||||
$showDieOnPrestartBtn = true;
|
$showDieOnPrestartBtn = true;
|
||||||
if ($targetTime <= TimeUtil::now()) {
|
if ($targetTime <= $nowTick) {
|
||||||
$availableDieOnPrestart = true;
|
$availableDieOnPrestart = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,7 +177,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) : ?>
|
||||||
가오픈 기간 내 장수 삭제 (<?= substr($targetTime, 0, 19) ?> 부터)<br>
|
가오픈 기간 내 장수 삭제 (<?= $targetTimeDisplay ?> 부터)<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; ?>
|
||||||
|
|
||||||
@@ -174,7 +192,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) : ?>
|
||||||
다른 장수 선택 (<?= substr($me->getAuxVar('next_change') ?? TimeUtil::now(), 0, 19) ?> 부터)<br>
|
다른 장수 선택 (<?= $nextChangeDisplay ?? '지금' ?>부터)<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; ?>
|
||||||
|
|
||||||
@@ -272,4 +290,4 @@ $changeDefence999Atmos = $me->onCalcDomestic('changeDefenceTrain', "atmos999", $
|
|||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -228,10 +228,10 @@ if($btn == "자동개최설정") {
|
|||||||
$phase = 0;
|
$phase = 0;
|
||||||
startBetting($admin['tnmt_type'], 720);
|
startBetting($admin['tnmt_type'], 720);
|
||||||
} elseif($btn == "베팅마감") {
|
} elseif($btn == "베팅마감") {
|
||||||
$dt = date("Y-m-d H:i:s", time() + 60);
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
$gameStor->tournament=7;
|
$gameStor->tournament=7;
|
||||||
$gameStor->phase=0;
|
$gameStor->phase=0;
|
||||||
$gameStor->tnmt_time = $dt;
|
$gameStor->tnmt_time = $clock->nowTick() + $clock->ticksFromSeconds(60);
|
||||||
} 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강") {
|
||||||
@@ -248,4 +248,4 @@ if($btn == "자동개최설정") {
|
|||||||
$gameStor->tnmt_msg = $msg;
|
$gameStor->tnmt_msg = $msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
header('location:b_tournament.php');
|
header('location:b_tournament.php');
|
||||||
|
|||||||
@@ -51,6 +51,22 @@
|
|||||||
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;
|
||||||
}
|
}
|
||||||
@@ -61,4 +77,4 @@
|
|||||||
|
|
||||||
.custom_stat {
|
.custom_stat {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
+108
-113
@@ -630,7 +630,11 @@ function generalInfo(General $generalObj)
|
|||||||
$injury = "건강";
|
$injury = "건강";
|
||||||
}
|
}
|
||||||
|
|
||||||
$remaining = (new \DateTimeImmutable($generalObj->getTurnTime()))->diff(new \DateTimeImmutable())->i;
|
$clock = GameClock::fromStorage(KVStorage::getStorage(DB::db(), 'game_env'));
|
||||||
|
$remaining = max(0, intdiv(
|
||||||
|
$generalObj->getTurnTick() - $clock->nowTick(),
|
||||||
|
$clock->ticksFromMinutes(1),
|
||||||
|
));
|
||||||
|
|
||||||
if ($nation['color'] == "") {
|
if ($nation['color'] == "") {
|
||||||
$nation['color'] = "#000000";
|
$nation['color'] = "#000000";
|
||||||
@@ -921,45 +925,37 @@ function banner()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTurn($date, int $turnterm, int $turn = 1, bool $withFraction = true)
|
function addTurn(int $tick, int $turnterm, int $turn = 1, bool $withFraction = true): int
|
||||||
{
|
{
|
||||||
$date = new \DateTime($date);
|
return $tick + GameClock::TICKS_PER_TURN * $turn;
|
||||||
$target = $turnterm * $turn;
|
}
|
||||||
$date->add(new \DateInterval("PT{$target}M"));
|
|
||||||
if ($withFraction) {
|
function subTurn(int $tick, int $turnterm, int $turn = 1, bool $withFraction = true): int
|
||||||
return $date->format('Y-m-d H:i:s.u');
|
{
|
||||||
}
|
return $tick - GameClock::TICKS_PER_TURN * $turn;
|
||||||
return $date->format('Y-m-d H:i:s');
|
}
|
||||||
}
|
|
||||||
|
function cutTurn(int $tick, int $turnterm, bool $withFraction = true): int
|
||||||
function subTurn($date, int $turnterm, int $turn = 1, bool $withFraction = true)
|
{
|
||||||
{
|
$remainder = $tick % GameClock::TICKS_PER_TURN;
|
||||||
$date = new \DateTime($date);
|
if ($remainder < 0) {
|
||||||
$target = $turnterm * $turn;
|
$remainder += GameClock::TICKS_PER_TURN;
|
||||||
$date->sub(new \DateInterval("PT{$target}M"));
|
}
|
||||||
if ($withFraction) {
|
return $tick - $remainder;
|
||||||
return $date->format('Y-m-d H:i:s.u');
|
}
|
||||||
}
|
|
||||||
return $date->format('Y-m-d H:i:s');
|
/** 시나리오 초기화 입력인 벽시계를 기존 01:00 기준 월 경계로 정렬합니다. */
|
||||||
}
|
function cutTurnDateTime(string $date, int $turnterm, bool $withFraction = true): string
|
||||||
|
{
|
||||||
function cutTurn($date, int $turnterm, bool $withFraction = true)
|
$dateObj = new \DateTime($date);
|
||||||
{
|
$baseDate = new \DateTime($dateObj->format('Y-m-d'));
|
||||||
$date = new \DateTime($date);
|
$baseDate->sub(new \DateInterval('P1D'));
|
||||||
|
$baseDate->add(new \DateInterval('PT1H'));
|
||||||
$baseDate = new \DateTime($date->format('Y-m-d'));
|
$diffMin = intdiv($dateObj->getTimestamp() - $baseDate->getTimestamp(), 60);
|
||||||
$baseDate->sub(new \DateInterval("P1D"));
|
$diffMin -= $diffMin % $turnterm;
|
||||||
$baseDate->add(new \DateInterval("PT1H"));
|
$baseDate->add(new \DateInterval("PT{$diffMin}M"));
|
||||||
|
return $baseDate->format($withFraction ? 'Y-m-d H:i:s.u' : 'Y-m-d H:i:s');
|
||||||
$diffMin = intdiv($date->getTimeStamp() - $baseDate->getTimeStamp(), 60);
|
}
|
||||||
$diffMin -= $diffMin % $turnterm;
|
|
||||||
|
|
||||||
$baseDate->add(new \DateInterval("PT{$diffMin}M"));
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
@@ -1001,11 +997,9 @@ function increaseRefresh($type = "", $cnt = 1)
|
|||||||
$generalID = $session->generalID;
|
$generalID = $session->generalID;
|
||||||
$userGrade = $session->userGrade;
|
$userGrade = $session->userGrade;
|
||||||
|
|
||||||
$dateObj = new \DateTimeImmutable();
|
$db = DB::db();
|
||||||
$date = TimeUtil::format($dateObj, false);
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$date = GameClock::fromStorage($gameStor)->nowTick();
|
||||||
$db = DB::db();
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
|
||||||
$isunited = $gameStor->isunited;
|
$isunited = $gameStor->isunited;
|
||||||
$opentime = $gameStor->opentime;
|
$opentime = $gameStor->opentime;
|
||||||
|
|
||||||
@@ -1047,7 +1041,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['REMOTE_ADDR'] ?? 'local';
|
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_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', [
|
||||||
@@ -1145,18 +1139,19 @@ function unlock(): bool
|
|||||||
return $db->affectedRows() > 0;
|
return $db->affectedRows() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function timeover(): bool
|
function timeover(): bool
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$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']);
|
||||||
$diff = (new \DateTime())->getTimestamp() - (new \DateTime($turntime))->getTimestamp();
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
|
$diff = $clock->nowTick() - Util::toInt($turntime);
|
||||||
|
|
||||||
$t = min($turnterm, 5);
|
$t = min($turnterm, 5);
|
||||||
|
|
||||||
$term = $diff;
|
$term = $clock->ticksFromSeconds($t);
|
||||||
if ($term >= $t || $term < 0) {
|
if ($diff >= $term || $diff < 0) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -1169,9 +1164,8 @@ function checkDelay()
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
|
||||||
//서버정보
|
//서버정보
|
||||||
$now = new \DateTimeImmutable();
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
$turntime = new \DateTimeImmutable($gameStor->turntime);
|
$timeMinDiff = intdiv($clock->nowTick() - Util::toInt($gameStor->turntime), $clock->ticksFromMinutes(1));
|
||||||
$timeMinDiff = intdiv($now->getTimestamp() - $turntime->getTimestamp(), 60);
|
|
||||||
|
|
||||||
// 1턴이상 갱신 없었으면 서버 지연
|
// 1턴이상 갱신 없었으면 서버 지연
|
||||||
$term = $gameStor->turnterm;
|
$term = $gameStor->turnterm;
|
||||||
@@ -1185,20 +1179,17 @@ function checkDelay()
|
|||||||
//지연 해야할 밀린 턴 횟수
|
//지연 해야할 밀린 턴 횟수
|
||||||
$iter = intdiv($timeMinDiff, $term);
|
$iter = intdiv($timeMinDiff, $term);
|
||||||
if ($iter > $threshold) {
|
if ($iter > $threshold) {
|
||||||
$minute = $iter * $term;
|
$minute = $iter * $term;
|
||||||
$newTurntime = $turntime->add(new \DateInterval("PT{$minute}M"));
|
$delayTick = $clock->ticksFromMinutes($minute);
|
||||||
$newNextTurntime = $turntime->add(new \DateInterval("PT{$term}M"));
|
$gameStor->turntime = Util::toInt($gameStor->turntime) + $delayTick;
|
||||||
$gameStor->turntime = $newTurntime->format('Y-m-d H:i:s');
|
$gameStor->starttime = Util::toInt($gameStor->starttime) + $delayTick;
|
||||||
$gameStor->starttime = (new \DateTimeImmutable($gameStor->starttime))
|
|
||||||
->add(new \DateInterval("PT{$minute}M"))
|
$db->update('general', [
|
||||||
->format('Y-m-d H:i:s');
|
'turntime' => $db->sqleval('turntime + %i', $delayTick)
|
||||||
|
], true);
|
||||||
$db->update('general', [
|
$db->update('ng_auction', [
|
||||||
'turntime' => $db->sqleval('DATE_ADD(turntime, INTERVAL %i MINUTE)', $minute)
|
'close_tick' => $db->sqleval('close_tick + %i', $delayTick)
|
||||||
], 'turntime<=DATE_ADD(turntime, INTERVAL %i MINUTE)', $term);
|
], 'finished = 0');
|
||||||
$db->update('ng_auction', [
|
|
||||||
'close_date' => $db->sqleval('DATE_ADD(close_date, INTERVAL %i MINUTE)', $minute)
|
|
||||||
], 'finished = 0');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1247,17 +1238,15 @@ function updateOnline()
|
|||||||
$gameStor->online_nation = join(', ', $onlineNation);
|
$gameStor->online_nation = join(', ', $onlineNation);
|
||||||
}
|
}
|
||||||
|
|
||||||
function turnDate($curtime)
|
function turnDate($curtime)
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$admin = $gameStor->getValues(['startyear', 'starttime', 'turnterm', 'year', 'month']);
|
$admin = $gameStor->getValues(['startyear', 'starttime', 'turnterm', 'year', 'month']);
|
||||||
|
|
||||||
$turn = $admin['starttime'];
|
$turn = $admin['starttime'];
|
||||||
$curturn = cutTurn($curtime, $admin['turnterm']);
|
$curturn = cutTurn(Util::toInt($curtime), $admin['turnterm']);
|
||||||
$term = $admin['turnterm'];
|
$num = intdiv($curturn - Util::toInt($turn), GameClock::TICKS_PER_TURN);
|
||||||
|
|
||||||
$num = intdiv((strtotime($curturn) - strtotime($turn)), $term * 60);
|
|
||||||
|
|
||||||
$date = $admin['startyear'] * 12;
|
$date = $admin['startyear'] * 12;
|
||||||
$date += $num;
|
$date += $num;
|
||||||
@@ -1401,8 +1390,11 @@ function CheckHall($no)
|
|||||||
|
|
||||||
foreach ($types as [$typeName, $valueType]) {
|
foreach ($types as [$typeName, $valueType]) {
|
||||||
|
|
||||||
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') {
|
||||||
@@ -1702,12 +1694,21 @@ function tryUniqueItemLottery(RandUtil $rng, General $general, string $acquireTy
|
|||||||
return giveRandomUniqueItem($rng, $general, $acquireType);
|
return giveRandomUniqueItem($rng, $general, $acquireType);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAdmin()
|
function getAdmin()
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
return $gameStor->getAll();
|
$admin = $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[] */
|
||||||
function deleteNation(General $lord, bool $applyDB): array
|
function deleteNation(General $lord, bool $applyDB): array
|
||||||
@@ -2196,35 +2197,29 @@ function SabotageInjury(RandUtil $rng, array $cityGeneralList, string $reason):
|
|||||||
return $injuryCount;
|
return $injuryCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRandTurn(RandUtil $rng, $term, ?\DateTimeInterface $baseDateTime = null)
|
function getRandTurn(RandUtil $rng, int $term, ?int $baseTick = null): int
|
||||||
{
|
{
|
||||||
if ($baseDateTime === null) {
|
$db = DB::db();
|
||||||
$baseDateTime = new \DateTimeImmutable();
|
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
||||||
} else if ($baseDateTime instanceof \DateTime) {
|
$baseTick ??= $clock->nowTick();
|
||||||
$baseDateTime = \DateTimeImmutable::createFromMutable($baseDateTime);
|
|
||||||
} else if ($baseDateTime instanceof \DateTimeImmutable) {
|
$randSecond = $rng->nextRangeInt(0, 60 * $term - 1);
|
||||||
//do Nothing
|
$randMicrosecond = $rng->nextRangeInt(0, 999999); // 레거시 RNG 소비 6자리 유지
|
||||||
} else {
|
|
||||||
throw new MustNotBeReachedException();
|
return $baseTick
|
||||||
}
|
+ $clock->ticksFromSeconds($randSecond)
|
||||||
|
+ intdiv($randMicrosecond * $clock->ticksPerSecond(), 1_000_000);
|
||||||
$randSecond = $rng->nextRangeInt(0, 60 * $term - 1);
|
}
|
||||||
$randFraction = $rng->nextRangeInt(0, 999999) / 1000000; //6자리 소수
|
|
||||||
|
function getRandTurn2(RandUtil $rng, int $term, ?int $baseTick = null): int
|
||||||
return TimeUtil::format($baseDateTime->add(TimeUtil::secondsToDateInterval($randSecond + $randFraction)), true);
|
{
|
||||||
}
|
$db = DB::db();
|
||||||
|
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
||||||
function getRandTurn2(RandUtil $rng, $term, ?\DateTimeInterface $baseDateTime = null)
|
$baseTick ??= $clock->nowTick();
|
||||||
{
|
$randSecond = $rng->nextRangeInt(0, 60 * $term - 1);
|
||||||
if ($baseDateTime === null) {
|
$randMicrosecond = $rng->nextRangeInt(0, 999999); // 레거시 RNG 소비 6자리 유지
|
||||||
$baseDateTime = new \DateTimeImmutable();
|
|
||||||
} else if ($baseDateTime instanceof \DateTime) {
|
return $baseTick
|
||||||
$baseDateTime = \DateTimeImmutable::createFromMutable($baseDateTime);
|
- $clock->ticksFromSeconds($randSecond)
|
||||||
} else {
|
- intdiv($randMicrosecond * $clock->ticksPerSecond(), 1_000_000);
|
||||||
throw new MustNotBeReachedException();
|
}
|
||||||
}
|
|
||||||
$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,11 +62,12 @@ function processAuction()
|
|||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$now = TimeUtil::now();
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$nowTick = GameClock::fromStorage($gameStor)->nowTick();
|
||||||
|
|
||||||
$auctionList = $db->queryAllLists(
|
$auctionList = $db->queryAllLists(
|
||||||
'SELECT id, `type` FROM ng_auction WHERE `close_date` <= %s AND finished = 0',
|
'SELECT id, `type` FROM ng_auction WHERE `close_tick` <= %i AND finished = 0',
|
||||||
$now
|
$nowTick
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!$auctionList) {
|
if (!$auctionList) {
|
||||||
|
|||||||
+65
-37
@@ -42,15 +42,21 @@ function pushGeneralCommand(int $generalID, int $turnCnt=1){
|
|||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$db->update('general_turn', [
|
$db->query(
|
||||||
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
|
'UPDATE general_turn AS dst
|
||||||
], 'general_id=%i ORDER BY turn_idx DESC', $generalID);
|
LEFT JOIN general_turn AS src
|
||||||
$db->update('general_turn', [
|
ON src.general_id = dst.general_id
|
||||||
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxTurn),
|
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)
|
||||||
], 'general_id=%i AND turn_idx >= %i', $generalID, GameConst::$maxTurn);
|
WHERE dst.general_id = %i',
|
||||||
|
$turnCnt,
|
||||||
|
'휴식',
|
||||||
|
'{}',
|
||||||
|
'휴식',
|
||||||
|
$generalID
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function pullGeneralCommand(int $generalID, int $turnCnt=1){
|
function pullGeneralCommand(int $generalID, int $turnCnt=1){
|
||||||
@@ -67,15 +73,21 @@ function pullGeneralCommand(int $generalID, int $turnCnt=1){
|
|||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$db->update('general_turn', [
|
$db->query(
|
||||||
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxTurn),
|
'UPDATE general_turn AS dst
|
||||||
'action'=>'휴식',
|
LEFT JOIN general_turn AS src
|
||||||
'arg'=>'{}',
|
ON src.general_id = dst.general_id
|
||||||
'brief'=>'휴식'
|
AND src.turn_idx = dst.turn_idx + %i
|
||||||
], 'general_id=%i AND turn_idx < %i', $generalID, $turnCnt);
|
SET dst.action = IF(src.id IS NULL, %s, src.action),
|
||||||
$db->update('general_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)
|
||||||
], 'general_id=%i ORDER BY turn_idx ASC', $generalID);
|
WHERE dst.general_id = %i',
|
||||||
|
$turnCnt,
|
||||||
|
'휴식',
|
||||||
|
'{}',
|
||||||
|
'휴식',
|
||||||
|
$generalID
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function repeatGeneralCommand(int $generalId, int $turnCnt){
|
function repeatGeneralCommand(int $generalId, int $turnCnt){
|
||||||
@@ -126,15 +138,23 @@ function pushNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
|
|||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$db->update('nation_turn', [
|
$db->query(
|
||||||
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
|
'UPDATE nation_turn AS dst
|
||||||
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx DESC', $nationID, $officerLevel);
|
LEFT JOIN nation_turn AS src
|
||||||
$db->update('nation_turn', [
|
ON src.nation_id = dst.nation_id
|
||||||
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxChiefTurn),
|
AND src.officer_level = dst.officer_level
|
||||||
'action'=>'휴식',
|
AND src.turn_idx = dst.turn_idx - %i
|
||||||
'arg'=>'{}',
|
SET dst.action = IF(src.id IS NULL, %s, src.action),
|
||||||
'brief'=>'휴식'
|
dst.arg = IF(src.id IS NULL, %s, src.arg),
|
||||||
], 'nation_id=%i AND officer_level=%i AND turn_idx >= %i ORDER BY turn_idx ASC', $nationID, $officerLevel, GameConst::$maxChiefTurn);
|
dst.brief = IF(src.id IS NULL, %s, src.brief)
|
||||||
|
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){
|
||||||
@@ -157,15 +177,23 @@ function pullNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
|
|||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
$db->update('nation_turn', [
|
$db->query(
|
||||||
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxChiefTurn),
|
'UPDATE nation_turn AS dst
|
||||||
'action'=>'휴식',
|
LEFT JOIN nation_turn AS src
|
||||||
'arg'=>'{}',
|
ON src.nation_id = dst.nation_id
|
||||||
'brief'=>'휴식',
|
AND src.officer_level = dst.officer_level
|
||||||
], 'nation_id=%i AND officer_level=%i AND turn_idx < %i', $nationID, $officerLevel, $turnCnt);
|
AND src.turn_idx = dst.turn_idx + %i
|
||||||
$db->update('nation_turn', [
|
SET dst.action = IF(src.id IS NULL, %s, src.action),
|
||||||
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
|
dst.arg = IF(src.id IS NULL, %s, src.arg),
|
||||||
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx ASC', $nationID, $officerLevel);
|
dst.brief = IF(src.id IS NULL, %s, src.brief)
|
||||||
|
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){
|
||||||
@@ -494,4 +522,4 @@ function setNationCommand(int $generalID, array $turnList, string $command, ?arr
|
|||||||
'arg_test'=>true,
|
'arg_test'=>true,
|
||||||
'reason'=>'success'
|
'reason'=>'success'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -686,7 +686,7 @@ function TechLimit($startYear, $year, $tech) : bool {
|
|||||||
$relYear = $year - $startYear;
|
$relYear = $year - $startYear;
|
||||||
|
|
||||||
$relMaxTech = Util::valueFit(
|
$relMaxTech = Util::valueFit(
|
||||||
floor($relYear / 5) + 1,
|
floor($relYear / GameConst::$techLevelIncYear) + GameConst::$initialAllowedTechLevel,
|
||||||
1,
|
1,
|
||||||
GameConst::$maxTechLevel
|
GameConst::$maxTechLevel
|
||||||
);
|
);
|
||||||
|
|||||||
+15
-7
@@ -559,7 +559,7 @@ function checkStatistic()
|
|||||||
|
|
||||||
$nationHist = '';
|
$nationHist = '';
|
||||||
foreach (GameConst::$availableNationType as $nationType) {
|
foreach (GameConst::$availableNationType as $nationType) {
|
||||||
if (!Util::array_get($nationHists[$nationType])) {
|
if (!($nationHists[$nationType] ?? null)) {
|
||||||
$nationHists[$nationType] = '-';
|
$nationHists[$nationType] = '-';
|
||||||
}
|
}
|
||||||
$nationHist .= getNationType($nationType) . "({$nationHists[$nationType]}), ";
|
$nationHist .= getNationType($nationType) . "({$nationHists[$nationType]}), ";
|
||||||
@@ -651,16 +651,24 @@ 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']);
|
||||||
return [
|
$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 [
|
||||||
'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' => $general['turntime'],
|
'turntime' => $turnTimeDisplay,
|
||||||
'data' => Json::encode($general)
|
'data' => Json::encode($general)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -734,7 +742,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_date` ASC',
|
'SELECT `id` FROM `ng_auction` WHERE `type` = %s AND `finished` = 0 ORDER BY `close_tick` ASC',
|
||||||
AuctionType::UniqueItem->value
|
AuctionType::UniqueItem->value
|
||||||
);
|
);
|
||||||
foreach($auctionList as $auctionID){
|
foreach($auctionList as $auctionID){
|
||||||
|
|||||||
+6
-2
@@ -4,6 +4,10 @@ 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>
|
||||||
@@ -138,7 +142,7 @@ function JSCitiesBasedOnDistance(int $cityNo, int $maxDistance = 1): array{
|
|||||||
$distanceList = searchDistance($cityNo, $maxDistance, true);
|
$distanceList = searchDistance($cityNo, $maxDistance, true);
|
||||||
$result = [];
|
$result = [];
|
||||||
for ($dist = 1; $dist <= $maxDistance; $dist++) {
|
for ($dist = 1; $dist <= $maxDistance; $dist++) {
|
||||||
$result[$dist] = Util::array_get($distanceList[$dist], []);
|
$result[$dist] = $distanceList[$dist] ?? [];
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
@@ -152,7 +156,7 @@ function printCitiesBasedOnDistance(int $cityNo, int $maxDistance = 1): string
|
|||||||
for ($dist = 1; $dist <= $maxDistance; $dist++) {
|
for ($dist = 1; $dist <= $maxDistance; $dist++) {
|
||||||
$cityList = array_map(function ($cityID) {
|
$cityList = array_map(function ($cityID) {
|
||||||
return CityConst::byID($cityID)->name;
|
return CityConst::byID($cityID)->name;
|
||||||
}, Util::array_get($distanceList[$dist], []));
|
}, $distanceList[$dist] ?? []);
|
||||||
|
|
||||||
$cityStr = join(', ', $cityList);
|
$cityStr = join(', ', $cityList);
|
||||||
|
|
||||||
|
|||||||
@@ -61,8 +61,12 @@ 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})";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-10
@@ -17,10 +17,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']);
|
||||||
$now = new \DateTime();
|
$offset = intdiv($clock->nowTick() - Util::toInt($admin['tnmt_time']), $clock->ticksPerSecond());
|
||||||
$offset = $now->getTimestamp() - (new \DateTime($admin['tnmt_time']))->getTimestamp();
|
|
||||||
|
|
||||||
//수동일땐 무시
|
//수동일땐 무시
|
||||||
if (!$admin['tnmt_auto']) {
|
if (!$admin['tnmt_auto']) {
|
||||||
@@ -122,10 +122,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 = $dt;
|
$gameStor->tnmt_time = Util::toInt($admin['tnmt_time'])
|
||||||
|
+ $clock->ticksFromSeconds($unit * $i + $betTerm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,7 +133,7 @@ function processTournament()
|
|||||||
$second = $unit * $iter;
|
$second = $unit * $iter;
|
||||||
$gameStor->tournament = $tnmt;
|
$gameStor->tournament = $tnmt;
|
||||||
$gameStor->phase = $phase;
|
$gameStor->phase = $phase;
|
||||||
$gameStor->tnmt_time = (new \DateTimeImmutable($admin['tnmt_time']))->add(new \DateInterval("PT{$second}S"))->format('Y-m-d H:i:s');
|
$gameStor->tnmt_time = Util::toInt($admin['tnmt_time']) + $clock->ticksFromSeconds($second);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTournamentTermText(int $turnTerm)
|
function getTournamentTermText(int $turnTerm)
|
||||||
@@ -160,7 +160,8 @@ 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']);
|
||||||
$dt = substr($tnmt_time, 11, 5);
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
|
$dt = substr($clock->formatTick(Util::toInt($tnmt_time)), 11, 5);
|
||||||
switch ($tnmt) {
|
switch ($tnmt) {
|
||||||
case 1:
|
case 1:
|
||||||
$tnmt = "개막시간 {$dt}";
|
$tnmt = "개막시간 {$dt}";
|
||||||
@@ -284,9 +285,11 @@ 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;
|
||||||
$gameStor->tnmt_time = (new \DateTimeImmutable())->add(new \DateInterval("PT{$unit}M"))->format('Y-m-d H:i:s');
|
// 기존 startTournament은 unit을 분으로 더하므로 그 계약을 유지합니다.
|
||||||
|
$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;
|
||||||
@@ -1153,21 +1156,25 @@ function fight($tnmt_type, $tnmt, $phs, $group, $g1, $g2, $type)
|
|||||||
];
|
];
|
||||||
|
|
||||||
//막판 분노
|
//막판 분노
|
||||||
|
$factor1 = 1.0;
|
||||||
|
$factor2 = 1.0;
|
||||||
$ratio = rand() % 300;
|
$ratio = rand() % 300;
|
||||||
if ($e1 / 5 > $energy1 && $damage1 > $damage2 && $gen1[$tp] >= $ratio) {
|
if ($e1 / 5 > $energy1 && $damage1 > $damage2 && $gen1[$tp] >= $ratio) {
|
||||||
$damage2 *= Util::round((rand() % 301 + 200) / 100); // 200 ~ 500%
|
$factor2 = Util::round((rand() % 301 + 200) / 100); // 200 ~ 500%
|
||||||
$critical1 = 1;
|
$critical1 = 1;
|
||||||
$str = Util::choiceRandom($crticialSkillMap[$tnmt_type]);
|
$str = Util::choiceRandom($crticialSkillMap[$tnmt_type]);
|
||||||
$log[] = "<S>●</> <Y>{$gen1['name']}</>의 분노의 <M>{$str}</> 공격!";
|
$log[] = "<S>●</> <Y>{$gen1['name']}</>의 분노의 <M>{$str}</> 공격!";
|
||||||
}
|
}
|
||||||
$ratio = rand() % 300;
|
$ratio = rand() % 300;
|
||||||
if ($e2 / 5 > $energy2 && $damage2 > $damage1 && $gen2[$tp] >= $ratio) {
|
if ($e2 / 5 > $energy2 && $damage2 > $damage1 && $gen2[$tp] >= $ratio) {
|
||||||
$damage1 *= Util::round((rand() % 301 + 200) / 100); // 200 ~ 500%
|
$factor1 = Util::round((rand() % 301 + 200) / 100); // 200 ~ 500%
|
||||||
$critical2 = 1;
|
$critical2 = 1;
|
||||||
|
|
||||||
$str = Util::choiceRandom($crticialSkillMap[$tnmt_type]);
|
$str = Util::choiceRandom($crticialSkillMap[$tnmt_type]);
|
||||||
$log[] = "<S>●</> <Y>{$gen2['name']}</>의 분노의 <M>{$str}</> 공격!";
|
$log[] = "<S>●</> <Y>{$gen2['name']}</>의 분노의 <M>{$str}</> 공격!";
|
||||||
}
|
}
|
||||||
|
$damage1 *= $factor1;
|
||||||
|
$damage2 *= $factor2;
|
||||||
|
|
||||||
//1합 승부
|
//1합 승부
|
||||||
if ($phase == 1) {
|
if ($phase == 1) {
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,10 @@ $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){
|
||||||
@@ -44,15 +42,14 @@ if($npcmode!=1){
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$token = $db->queryFirstRow('SELECT * FROM select_npc_token WHERE `owner`=%i AND `valid_until`>=%s', $userID, $now);
|
$token = $db->queryFirstRow('SELECT * FROM select_npc_token WHERE `owner`=%i AND `valid_until`>=%i', $userID, $now);
|
||||||
$pickResult = [];
|
$pickResult = [];
|
||||||
|
|
||||||
|
|
||||||
if($token && $refresh){
|
if($token && $refresh){
|
||||||
$pickMoreFrom = (new \DateTime($token['pick_more_from']))->getTimestamp();
|
$pickMoreFrom = Util::toInt($token['pick_more_from']);
|
||||||
$nowT = $oNow->getTimestamp();
|
|
||||||
|
|
||||||
if($nowT >= $pickMoreFrom){
|
if($now >= $pickMoreFrom){
|
||||||
$oldPickResult = Json::decode($token['pick_result']);
|
$oldPickResult = Json::decode($token['pick_result']);
|
||||||
|
|
||||||
foreach($keepResult as $keepId){
|
foreach($keepResult as $keepId){
|
||||||
@@ -75,15 +72,14 @@ if($token && $refresh){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($token && !$refresh){
|
if($token && !$refresh){
|
||||||
$pickMoreFrom = (new \DateTime($token['pick_more_from']))->getTimestamp();
|
$pickMoreFrom = Util::toInt($token['pick_more_from']);
|
||||||
$nowT = $oNow->getTimestamp();
|
|
||||||
|
|
||||||
Json::die([
|
Json::die([
|
||||||
'result'=>true,
|
'result'=>true,
|
||||||
'pick'=>Json::decode($token['pick_result']),
|
'pick'=>Json::decode($token['pick_result']),
|
||||||
'pickMoreFrom'=>$token['pick_more_from'],
|
'pickMoreFrom'=>$clock->formatTick($pickMoreFrom),
|
||||||
'pickMoreSeconds'=>$pickMoreFrom-$nowT,
|
'pickMoreSeconds'=>intdiv($pickMoreFrom - $now, $clock->ticksPerSecond()),
|
||||||
'validUntil'=>$token['valid_until']
|
'validUntil'=>$clock->formatTick(Util::toInt($token['valid_until']))
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +96,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 >=%s', $userID, $now) as $reserved){
|
foreach($db->queryFirstColumn('SELECT pick_result FROM select_npc_token WHERE `owner`!=%i AND valid_until >=%i', $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)){
|
||||||
@@ -131,8 +127,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 = $oNow->add(new \DateInterval(sprintf('PT%dS', $validSecond)));
|
$validUntil = $now + $clock->ticksFromSeconds($validSecond);
|
||||||
$pickMoreFrom = $oNow->add(new \DateInterval(sprintf('PT%dS', $pickMoreSecond)));
|
$pickMoreFrom = $now + $clock->ticksFromSeconds($pickMoreSecond);
|
||||||
|
|
||||||
$db->delete('select_npc_token', 'valid_until < %s', $now);
|
$db->delete('select_npc_token', 'valid_until < %s', $now);
|
||||||
|
|
||||||
@@ -140,8 +136,8 @@ $inserted = 0;
|
|||||||
|
|
||||||
if($token){
|
if($token){
|
||||||
$db->update('select_npc_token', [
|
$db->update('select_npc_token', [
|
||||||
'valid_until'=>$validUntil->format('Y-m-d H:i:s'),
|
'valid_until'=>$validUntil,
|
||||||
'pick_more_from'=>$pickMoreFrom->format('Y-m-d H:i:s'),
|
'pick_more_from'=>$pickMoreFrom,
|
||||||
'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']);
|
||||||
@@ -152,8 +148,8 @@ if($token){
|
|||||||
else{
|
else{
|
||||||
$db->insertIgnore('select_npc_token', [
|
$db->insertIgnore('select_npc_token', [
|
||||||
'owner'=>$userID,
|
'owner'=>$userID,
|
||||||
'valid_until'=>$validUntil->format('Y-m-d H:i:s'),
|
'valid_until'=>$validUntil,
|
||||||
'pick_more_from'=>'2000-01-01 01:00:00',
|
'pick_more_from'=>$now,
|
||||||
'pick_result'=>Json::encode($pickResult),
|
'pick_result'=>Json::encode($pickResult),
|
||||||
'nonce'=>$newNonce
|
'nonce'=>$newNonce
|
||||||
]);
|
]);
|
||||||
@@ -173,7 +169,7 @@ if($inserted === 0){
|
|||||||
Json::die([
|
Json::die([
|
||||||
'result'=>true,
|
'result'=>true,
|
||||||
'pick'=>$pickResult,
|
'pick'=>$pickResult,
|
||||||
'pickMoreFrom'=>($inserted===-1)?$pickMoreFrom->format('Y-m-d H:i:s'):'2000-01-01 01:00:00',
|
'pickMoreFrom'=>$clock->formatTick(($inserted===-1)?$pickMoreFrom:$now),
|
||||||
'pickMoreSeconds'=>($inserted===-1)?$pickMoreSecond:0,
|
'pickMoreSeconds'=>($inserted===-1)?$pickMoreSecond:0,
|
||||||
'validUntil'=>$validUntil->format('Y-m-d H:i:s')
|
'validUntil'=>$clock->formatTick($validUntil)
|
||||||
]);
|
]);
|
||||||
|
|||||||
+30
-14
@@ -10,7 +10,23 @@ function sortTokens(&$tokens){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function putInfoText(&$info){
|
function putInfoText(&$info, ?array $currentTargetEnv){
|
||||||
|
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();
|
||||||
@@ -27,14 +43,13 @@ function putInfoText(&$info){
|
|||||||
$session = Session::requireLogin([])->setReadOnly();
|
$session = Session::requireLogin([])->setReadOnly();
|
||||||
$userID = Session::getUserID();
|
$userID = Session::getUserID();
|
||||||
|
|
||||||
$oNow = new \DateTimeImmutable();
|
$db = DB::db();
|
||||||
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
|
$now = $clock->nowTick();
|
||||||
|
|
||||||
$now = $oNow->format('Y-m-d H:i:s');
|
$eventEnv = $gameStor->getValues(['npcmode', 'startyear', 'year', 'month']);
|
||||||
|
$npcmode = $eventEnv['npcmode'];
|
||||||
$db = DB::db();
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
|
||||||
|
|
||||||
$npcmode = $gameStor->getValue('npcmode');
|
|
||||||
if($npcmode!=2){
|
if($npcmode!=2){
|
||||||
Json::die([
|
Json::die([
|
||||||
'result'=>false,
|
'result'=>false,
|
||||||
@@ -42,7 +57,8 @@ 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){
|
||||||
@@ -62,7 +78,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);
|
putInfoText($info, $currentTargetEnv);
|
||||||
$info['uniqueName'] = $token['unique_name'];
|
$info['uniqueName'] = $token['unique_name'];
|
||||||
$pick[] = $info;
|
$pick[] = $info;
|
||||||
}
|
}
|
||||||
@@ -70,7 +86,7 @@ if($tokens){
|
|||||||
Json::die([
|
Json::die([
|
||||||
'result'=>true,
|
'result'=>true,
|
||||||
'pick'=>$pick,
|
'pick'=>$pick,
|
||||||
'validUntil'=>$valid_until
|
'validUntil'=>$clock->formatTick(Util::toInt($valid_until))
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,12 +99,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);
|
putInfoText($info, $currentTargetEnv);
|
||||||
$pick[] = $info;
|
$pick[] = $info;
|
||||||
}
|
}
|
||||||
sortTokens($pick);//좀 무식하지만..
|
sortTokens($pick);//좀 무식하지만..
|
||||||
Json::die([
|
Json::die([
|
||||||
'result'=>true,
|
'result'=>true,
|
||||||
'pick'=>$pick,
|
'pick'=>$pick,
|
||||||
'validUntil'=>$valid_until
|
'validUntil'=>$valid_until === null ? null : $clock->formatTick(Util::toInt($valid_until))
|
||||||
]);
|
]);
|
||||||
|
|||||||
+2
-2
@@ -211,7 +211,7 @@ try{
|
|||||||
$show_img_level,
|
$show_img_level,
|
||||||
!!$tournament_trig,
|
!!$tournament_trig,
|
||||||
$join_mode,
|
$join_mode,
|
||||||
TimeUtil::now(),
|
TimeUtil::format(GameClock::readWallTime(), false),
|
||||||
$autorun_user
|
$autorun_user
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -220,4 +220,4 @@ catch(\Exception $e){
|
|||||||
'result'=>false,
|
'result'=>false,
|
||||||
'reason'=>$e->getMessage()
|
'reason'=>$e->getMessage()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ function do도시임명(General $general, int $cityID, int $targetOfficerLevel):
|
|||||||
return '올바르지 않은 도시입니다';
|
return '올바르지 않은 도시입니다';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($general->getVar(GeneralColumn::officer_level) >= 4 && $myPenalty[PenaltyKey::NoChiefChange->value] ?? false) {
|
if ($general->getVar(GeneralColumn::officer_level) >= 4 && ($myPenalty[PenaltyKey::NoChiefChange->value] ?? false)) {
|
||||||
return '수뇌인 장수를 변경할 수 없는 상태입니다.';
|
return '수뇌인 장수를 변경할 수 없는 상태입니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
$oNow = new \DateTimeImmutable();
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
$now = $oNow->format('Y-m-d H:i:s');
|
$now = $clock->nowTick();
|
||||||
|
|
||||||
$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){
|
||||||
@@ -41,7 +41,7 @@ $penaltyInfo = array_merge($memberPenalty['any'] ?? [], $memberPenalty[DB::prefi
|
|||||||
|
|
||||||
$penalty = [];
|
$penalty = [];
|
||||||
foreach($penaltyInfo as $penaltyKey => $penaltyValue){
|
foreach($penaltyInfo as $penaltyKey => $penaltyValue){
|
||||||
if($penaltyValue['expire'] ?? 0 > TimeUtil::now()){
|
if(($penaltyValue['expire'] ?? 0) > TimeUtil::now()){
|
||||||
$penalty[$penaltyKey] = $penaltyValue['value'];
|
$penalty[$penaltyKey] = $penaltyValue['value'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,4 +139,4 @@ $rootDB->insert('member_log', [
|
|||||||
Json::die([
|
Json::die([
|
||||||
'result'=>true,
|
'result'=>true,
|
||||||
'reason'=>'success'
|
'reason'=>'success'
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -8,10 +8,20 @@ WebUtil::requireAJAX();
|
|||||||
|
|
||||||
$pick = Util::getPost('pick');
|
$pick = Util::getPost('pick');
|
||||||
$leadership = Util::getPost('leadership', 'int', GameConst::$defaultStatMin);
|
$leadership = Util::getPost('leadership', 'int', GameConst::$defaultStatMin);
|
||||||
$strength = Util::getPost('leadership', 'int', GameConst::$defaultStatMin);
|
$isCentennialAllStar = CentennialAllStarGrowthService::isActive();
|
||||||
$intel = Util::getPost('leadership', 'int', GameConst::$defaultStatMin);
|
$strength = Util::getPost(
|
||||||
|
$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){
|
||||||
@@ -27,8 +37,8 @@ $db = DB::db();
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
|
||||||
$rootDB = RootDB::db();
|
$rootDB = RootDB::db();
|
||||||
$oNow = new \DateTimeImmutable();
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
$now = $oNow->format('Y-m-d H:i:s');
|
$now = $clock->nowTick();
|
||||||
|
|
||||||
$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){
|
||||||
@@ -60,16 +70,39 @@ if(!$selectInfo){
|
|||||||
}
|
}
|
||||||
$selectInfo = Json::decode($selectInfo);
|
$selectInfo = Json::decode($selectInfo);
|
||||||
|
|
||||||
$ownerInfo = RootDB::db()->queryFirstRow('SELECT `name`,`picture`,`imgsvr` FROM member WHERE `NO`=%i',$userID);
|
$ownerInfo = RootDB::db()->queryFirstRow(
|
||||||
if(!$ownerInfo){
|
'SELECT `name`,`picture`,`imgsvr`,`grade` FROM member WHERE `NO`=%i',
|
||||||
|
$userID
|
||||||
|
);
|
||||||
|
if(!$ownerInfo){
|
||||||
Json::die([
|
Json::die([
|
||||||
'result'=>false,
|
'result'=>false,
|
||||||
'reason'=>'멤버 정보를 가져오지 못했습니다.'
|
'reason'=>'멤버 정보를 가져오지 못했습니다.'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
if ($isCentennialAllStar) {
|
||||||
|
if (!in_array($pictureSource, ['selected', 'own'], true)) {
|
||||||
$gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2');
|
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');
|
||||||
|
|
||||||
if ($gencount >= $maxgeneral) {
|
if ($gencount >= $maxgeneral) {
|
||||||
Json::die([
|
Json::die([
|
||||||
@@ -80,12 +113,25 @@ if ($gencount >= $maxgeneral) {
|
|||||||
|
|
||||||
$poolClass = getGeneralPoolClass(GameConst::$targetGeneralPool);
|
$poolClass = getGeneralPoolClass(GameConst::$targetGeneralPool);
|
||||||
/** @var AbsGeneralPool */
|
/** @var AbsGeneralPool */
|
||||||
$pickedGeneral = new $poolClass($db, $selectInfo, $now);
|
if ($isCentennialAllStar) {
|
||||||
|
$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'){
|
if($allowOption == 'stat' && !$isCentennialAllStar){
|
||||||
$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);
|
||||||
@@ -98,14 +144,23 @@ foreach(GameConst::$generalPoolAllowOption as $allowOption){
|
|||||||
}
|
}
|
||||||
$builder->setStat($leadership, $strength, $intel);
|
$builder->setStat($leadership, $strength, $intel);
|
||||||
}
|
}
|
||||||
else if($allowOption == 'picture' && $use_own_picture){
|
else if(
|
||||||
$builder->setPicture($ownerInfo['imgsvr'], $ownerInfo['picture']);
|
$allowOption == 'picture'
|
||||||
|
&& (
|
||||||
|
(!$isCentennialAllStar && $use_own_picture)
|
||||||
|
|| ($isCentennialAllStar && $pictureSource === 'own')
|
||||||
|
)
|
||||||
|
){
|
||||||
|
$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);
|
||||||
}
|
}
|
||||||
if(!array_search($personal, GameConst::$availablePersonality)){
|
$invalidPersonal = $isCentennialAllStar
|
||||||
|
? !in_array($personal, GameConst::$availablePersonality, true)
|
||||||
|
: !array_search($personal, GameConst::$availablePersonality);
|
||||||
|
if($invalidPersonal){
|
||||||
Json::die([
|
Json::die([
|
||||||
'result'=>false,
|
'result'=>false,
|
||||||
'reason'=>'올바르지 않은 성격입니다.'
|
'reason'=>'올바르지 않은 성격입니다.'
|
||||||
@@ -113,7 +168,7 @@ foreach(GameConst::$generalPoolAllowOption as $allowOption){
|
|||||||
}
|
}
|
||||||
$builder->setEgo($personal);
|
$builder->setEgo($personal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$userNick = $ownerInfo['name'];
|
$userNick = $ownerInfo['name'];
|
||||||
|
|
||||||
@@ -121,8 +176,29 @@ $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', TimeUtil::nowAddMinutes(12 * $env['turnterm']));
|
$builder->setAuxVar('next_change', $now + GameClock::TICKS_PER_TURN * 12);
|
||||||
|
$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){
|
||||||
@@ -167,4 +243,4 @@ $rootDB->insert('member_log', [
|
|||||||
Json::die([
|
Json::die([
|
||||||
'result'=>true,
|
'result'=>true,
|
||||||
'reason'=>'success'
|
'reason'=>'success'
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ 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(
|
||||||
@@ -75,8 +76,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($admin['opentime'], 5, 11);
|
$admin['starttime'] = substr($clock->formatTick(Util::toInt($admin['opentime'])), 5, 11);
|
||||||
$admin['turntime'] = substr($admin['turntime'], 5, 11);
|
$admin['turntime'] = substr($clock->formatTick(Util::toInt($admin['turntime'])), 5, 11);
|
||||||
unset($admin['npcmode']);
|
unset($admin['npcmode']);
|
||||||
unset($admin['maxgeneral']);
|
unset($admin['maxgeneral']);
|
||||||
unset($admin['turnterm']);
|
unset($admin['turnterm']);
|
||||||
@@ -131,4 +132,4 @@ if($general){
|
|||||||
Json::die([
|
Json::die([
|
||||||
'game'=>$admin,
|
'game'=>$admin,
|
||||||
'me'=>$me?:null
|
'me'=>$me?:null
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ $penaltyInfo = array_merge($memberPenalty['any'] ?? [], $memberPenalty[DB::prefi
|
|||||||
|
|
||||||
$penalty = [];
|
$penalty = [];
|
||||||
foreach ($penaltyInfo as $penaltyKey => $penaltyValue) {
|
foreach ($penaltyInfo as $penaltyKey => $penaltyValue) {
|
||||||
if ($penaltyValue['expire'] ?? 0 > TimeUtil::now()) {
|
if (($penaltyValue['expire'] ?? 0) > TimeUtil::now()) {
|
||||||
$penalty[$penaltyKey] = $penaltyValue['value'];
|
$penalty[$penaltyKey] = $penaltyValue['value'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,8 @@ $month = $query['month'];
|
|||||||
$repeatCnt = $query['repeatCnt'];
|
$repeatCnt = $query['repeatCnt'];
|
||||||
|
|
||||||
$rawAttacker = $query['attackerGeneral'];
|
$rawAttacker = $query['attackerGeneral'];
|
||||||
$rawAttacker['turntime'] = TimeUtil::now();
|
$battleClock = GameClock::fromStorage(KVStorage::getStorage(DB::db(), 'game_env'));
|
||||||
|
$rawAttacker['turntime'] = $battleClock->formatTick($battleClock->nowTick());
|
||||||
$rawAttackerCity = $query['attackerCity'];
|
$rawAttackerCity = $query['attackerCity'];
|
||||||
$rawAttackerNation = $query['attackerNation'];
|
$rawAttackerNation = $query['attackerNation'];
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ 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([
|
||||||
@@ -21,8 +22,8 @@ $db = DB::db();
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
|
||||||
$rootDB = RootDB::db();
|
$rootDB = RootDB::db();
|
||||||
$oNow = new \DateTimeImmutable();
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
$now = $oNow->format('Y-m-d H:i:s');
|
$now = $clock->nowTick();
|
||||||
|
|
||||||
$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){
|
||||||
@@ -35,10 +36,20 @@ if(!$generalID){
|
|||||||
list(
|
list(
|
||||||
$year,
|
$year,
|
||||||
$month,
|
$month,
|
||||||
|
$startYear,
|
||||||
$maxgeneral,
|
$maxgeneral,
|
||||||
$npcmode,
|
$npcmode,
|
||||||
$turnterm
|
$turnterm,
|
||||||
) = $gameStor->getValuesAsArray(['year', 'month', 'maxgeneral', 'npcmode', 'turnterm']);
|
$showImgLevel
|
||||||
|
) = $gameStor->getValuesAsArray([
|
||||||
|
'year',
|
||||||
|
'month',
|
||||||
|
'startyear',
|
||||||
|
'maxgeneral',
|
||||||
|
'npcmode',
|
||||||
|
'turnterm',
|
||||||
|
'show_img_level',
|
||||||
|
]);
|
||||||
|
|
||||||
if($npcmode!=2){
|
if($npcmode!=2){
|
||||||
Json::die([
|
Json::die([
|
||||||
@@ -55,7 +66,10 @@ if(!$info){
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$ownerInfo = RootDB::db()->queryFirstRow('SELECT `name`,`picture`,`imgsvr` FROM member WHERE `NO`=%i',$userID);
|
$ownerInfo = RootDB::db()->queryFirstRow(
|
||||||
|
'SELECT `name`,`picture`,`imgsvr`,`grade` FROM member WHERE `NO`=%i',
|
||||||
|
$userID
|
||||||
|
);
|
||||||
if(!$ownerInfo){
|
if(!$ownerInfo){
|
||||||
Json::die([
|
Json::die([
|
||||||
'result'=>false,
|
'result'=>false,
|
||||||
@@ -64,6 +78,27 @@ 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);
|
||||||
@@ -101,35 +136,52 @@ $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(key_exists('leadership', $info)){
|
if ($isCentennialAllStar) {
|
||||||
$generalObj->updateVar('leadership', $info['leadership']);
|
CentennialAllStarGrowthService::prepareLegacyUserReselection($generalObj);
|
||||||
$generalObj->updateVar('strength', $info['strength']);
|
CentennialAllStarGrowthService::applyTarget($generalObj, $info, [
|
||||||
$generalObj->updateVar('intel', $info['intel']);
|
'startyear' => $startYear,
|
||||||
|
'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(key_exists('picture', $info)){
|
if ($isCentennialAllStar) {
|
||||||
|
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']);
|
||||||
}
|
}
|
||||||
if(key_exists('dex', $info)){
|
$generalObj->setAuxVar('next_change', $now + GameClock::TICKS_PER_TURN * 12);
|
||||||
$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);
|
||||||
@@ -148,4 +200,4 @@ $generalObj->applyDB($db);
|
|||||||
Json::die([
|
Json::die([
|
||||||
'result'=>true,
|
'result'=>true,
|
||||||
'reason'=>'success'
|
'reason'=>'success'
|
||||||
]);
|
]);
|
||||||
|
|||||||
+3
-2
@@ -51,8 +51,9 @@ function MessageBox($str)
|
|||||||
|
|
||||||
function LogText($prefix, $variable)
|
function LogText($prefix, $variable)
|
||||||
{
|
{
|
||||||
$text = sprintf('%s : %s'."\r\n", $prefix, TVarDumper::dump($variable));
|
return;
|
||||||
file_put_contents(ROOT.'/d_log/'.UniqueConst::$serverName.'_dbg_logs.txt', $text, FILE_APPEND);
|
//$text = sprintf('%s : %s'."\r\n", $prefix, TVarDumper::dump($variable));
|
||||||
|
//file_put_contents(ROOT.'/d_log/'.UniqueConst::$serverName.'_dbg_logs.txt', $text, FILE_APPEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareDir(string $dirPath, bool $forceCreate=true):bool{
|
function prepareDir(string $dirPath, bool $forceCreate=true):bool{
|
||||||
|
|||||||
+11
-1
@@ -8,4 +8,14 @@ $session = Session::getInstance()->setReadOnly();
|
|||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
TurnExecutionHelper::executeAllCommand();
|
$updated = false;
|
||||||
|
$locked = false;
|
||||||
|
$lastExecuted = TurnExecutionHelper::executeAllCommand($updated, $locked);
|
||||||
|
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
||||||
|
Json::die([
|
||||||
|
'result' => true,
|
||||||
|
'updated' => $updated,
|
||||||
|
'locked' => $locked,
|
||||||
|
'lastExecutedTick' => $lastExecuted,
|
||||||
|
'lastExecuted' => $clock->formatTick($lastExecuted, true),
|
||||||
|
]);
|
||||||
|
|||||||
+3
-3
@@ -526,7 +526,7 @@ function DeleteConflict($nation)
|
|||||||
function getConquerNation($city): int
|
function getConquerNation($city): int
|
||||||
{
|
{
|
||||||
$conflict = Json::decode($city['conflict']);
|
$conflict = Json::decode($city['conflict']);
|
||||||
return Util::array_first_key($conflict);
|
return array_key_first($conflict);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ConquerCity(array $admin, General $general, array $city, array $defenderCityGeneralList)
|
function ConquerCity(array $admin, General $general, array $city, array $defenderCityGeneralList)
|
||||||
@@ -785,8 +785,8 @@ function ConquerCity(array $admin, General $general, array $city, array $defende
|
|||||||
'officer_set' => 0,
|
'officer_set' => 0,
|
||||||
];
|
];
|
||||||
if ($city['level'] > 3) {
|
if ($city['level'] > 3) {
|
||||||
$query['def'] = 1000;
|
$query['def'] = GameConst::$defaultCityWall;
|
||||||
$query['wall'] = 1000;
|
$query['wall'] = GameConst::$defaultCityWall;
|
||||||
} else {
|
} else {
|
||||||
$query['def'] = $db->sqleval('def_max/2');
|
$query['def'] = $db->sqleval('def_max/2');
|
||||||
$query['wall'] = $db->sqleval('wall_max/2');
|
$query['wall'] = $db->sqleval('wall_max/2');
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class BidUniqueAuction extends \sammo\BaseAPI
|
|||||||
])
|
])
|
||||||
->rule('int', 'amount')
|
->rule('int', 'amount')
|
||||||
->rule('int', 'auctionID')
|
->rule('int', 'auctionID')
|
||||||
->rule('boolean', 'extendCloseDate');
|
->rule('boolean', 'extendCloseTick');
|
||||||
|
|
||||||
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['extendCloseDate'] ?? false;
|
$tryExtendCloseDate = $this->args['extendCloseTick'] ?? false;
|
||||||
|
|
||||||
$generalID = $session->generalID;
|
$generalID = $session->generalID;
|
||||||
$general = General::createObjFromDB($generalID);
|
$general = General::createObjFromDB($generalID);
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ 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;
|
||||||
|
|
||||||
@@ -33,12 +35,13 @@ 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_date` ASC',
|
'SELECT * FROM `ng_auction` WHERE `type` IN %ls AND `finished` = 0 ORDER BY `close_tick` ASC',
|
||||||
[
|
[
|
||||||
AuctionType::BuyRice->value,
|
AuctionType::BuyRice->value,
|
||||||
AuctionType::SellRice->value,
|
AuctionType::SellRice->value,
|
||||||
@@ -87,8 +90,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' => TimeUtil::format($auction->openDate, false),
|
'openDate' => $clock->formatTick($auction->openTick),
|
||||||
'closeDate' => TimeUtil::format($auction->closeDate, false),
|
'closeDate' => $clock->formatTick($auction->closeTick),
|
||||||
'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,6 +14,8 @@ 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;
|
||||||
|
|
||||||
@@ -42,6 +44,7 @@ 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'];
|
||||||
@@ -92,9 +95,11 @@ 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' => TimeUtil::format($auction->closeDate, false),
|
'closeDate' => $clock->formatTick($auction->closeTick),
|
||||||
'remainCloseDateExtensionCnt' => $auction->detail->remainCloseDateExtensionCnt,
|
'remainCloseDateExtensionCnt' => $auction->detail->remainCloseDateExtensionCnt,
|
||||||
'availableLatestBidCloseDate' => TimeUtil::format($auction->detail->availableLatestBidCloseDate, false),
|
'availableLatestBidCloseDate' => $auction->detail->availableLatestBidCloseTick === null
|
||||||
|
? null
|
||||||
|
: $clock->formatTick($auction->detail->availableLatestBidCloseTick),
|
||||||
],
|
],
|
||||||
'bidList' => $responseBid,
|
'bidList' => $responseBid,
|
||||||
'obfuscatedName' => $obfuscatedName,
|
'obfuscatedName' => $obfuscatedName,
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ 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
|
||||||
{
|
{
|
||||||
@@ -28,12 +30,13 @@ 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_date` ASC',
|
'SELECT * FROM `ng_auction` WHERE `type` = %s ORDER BY `close_tick` ASC',
|
||||||
AuctionType::UniqueItem->value
|
AuctionType::UniqueItem->value
|
||||||
) ?? []);
|
) ?? []);
|
||||||
|
|
||||||
@@ -85,9 +88,11 @@ 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' => TimeUtil::format($auction->closeDate, false),
|
'closeDate' => $clock->formatTick($auction->closeTick),
|
||||||
'remainCloseDateExtensionCnt' => $auction->detail->remainCloseDateExtensionCnt,
|
'remainCloseDateExtensionCnt' => $auction->detail->remainCloseDateExtensionCnt,
|
||||||
'availableLatestBidCloseDate' => TimeUtil::format($auction->detail->availableLatestBidCloseDate, false),
|
'availableLatestBidCloseDate' => $auction->detail->availableLatestBidCloseTick === null
|
||||||
|
? null
|
||||||
|
: $clock->formatTick($auction->detail->availableLatestBidCloseTick),
|
||||||
'highestBid' => [
|
'highestBid' => [
|
||||||
'generalName' => $highestBid->aux->generalName,
|
'generalName' => $highestBid->aux->generalName,
|
||||||
'amount' => $highestBid->amount,
|
'amount' => $highestBid->amount,
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ 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;
|
||||||
|
|
||||||
@@ -82,11 +84,12 @@ class GetReservedCommand extends \sammo\BaseAPI
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'result' => true,
|
'result' => true,
|
||||||
'turnTime' => $turnTime,
|
'turnTimeTick' => Util::toInt($turnTime),
|
||||||
|
'turnTime' => GameClock::fromStorage($gameStor)->formatTick(Util::toInt($turnTime)),
|
||||||
'turnTerm' => $turnTerm,
|
'turnTerm' => $turnTerm,
|
||||||
'year' => $year,
|
'year' => $year,
|
||||||
'month' => $month,
|
'month' => $month,
|
||||||
'date' => TimeUtil::now(true),
|
'date' => GameClock::fromStorage($gameStor)->formatTick(GameClock::fromStorage($gameStor)->nowTick(), true),
|
||||||
'turn' => $commandList,
|
'turn' => $commandList,
|
||||||
'autorun_limit' => $generalAux['autorun_limit'] ?? null,
|
'autorun_limit' => $generalAux['autorun_limit'] ?? null,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ use sammo\Session;
|
|||||||
use sammo\General;
|
use sammo\General;
|
||||||
use sammo\JosaUtil;
|
use sammo\JosaUtil;
|
||||||
use sammo\KVStorage;
|
use sammo\KVStorage;
|
||||||
use sammo\TimeUtil;
|
use sammo\GameClock;
|
||||||
|
use sammo\Util;
|
||||||
|
|
||||||
use function sammo\addTurn;
|
use function sammo\addTurn;
|
||||||
use function sammo\increaseRefresh;
|
use function sammo\increaseRefresh;
|
||||||
@@ -37,8 +38,14 @@ 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,
|
||||||
@@ -46,8 +53,9 @@ class DieOnPrestart extends \sammo\BaseAPI
|
|||||||
$general['no']
|
$general['no']
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!$general) {
|
$generalObj = General::createObjFromDB($general['no']);
|
||||||
return '장수가 없습니다';
|
if ($generalObj instanceof DummyGeneral) {
|
||||||
|
trigger_error("올바르지 않은 삭제 프로세스 $userID", E_USER_WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
increaseRefresh("장수 삭제", 1);
|
increaseRefresh("장수 삭제", 1);
|
||||||
@@ -61,16 +69,21 @@ class DieOnPrestart extends \sammo\BaseAPI
|
|||||||
return '이미 국가에 소속되어있습니다.';
|
return '이미 국가에 소속되어있습니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
//서버 가오픈시 할 수 있는 행동
|
$targetTime = $generalObj->getAuxVar('prestart_delete_after');
|
||||||
$targetTime = addTurn($lastRefresh, $gameStor->turnterm, GameConst::$minTurnDieOnPrestart);
|
if (!is_int($targetTime)) {
|
||||||
if ($targetTime > TimeUtil::now()) {
|
$targetTime = addTurn(
|
||||||
$targetTimeShort = substr($targetTime, 0, 19);
|
$lastRefresh === null ? $nowTick : Util::toInt($lastRefresh),
|
||||||
return "아직 삭제할 수 없습니다. {$targetTimeShort} 부터 가능합니다.";
|
$gameStor->turnterm,
|
||||||
|
GameConst::$minTurnDieOnPrestart
|
||||||
|
);
|
||||||
|
$generalObj->setAuxVar('prestart_delete_after', $targetTime);
|
||||||
|
$generalObj->applyDB($db);
|
||||||
}
|
}
|
||||||
|
|
||||||
$generalObj = General::createObjFromDB($general['no']);
|
//서버 가오픈시 할 수 있는 행동
|
||||||
if ($generalObj instanceof DummyGeneral) {
|
if ($targetTime > $nowTick) {
|
||||||
trigger_error("올바르지 않은 삭제 프로세스 $userID", E_USER_WARNING);
|
$targetTimeShort = $clock->formatTick($targetTime);
|
||||||
|
return "아직 삭제할 수 없습니다. {$targetTimeShort} 부터 가능합니다.";
|
||||||
}
|
}
|
||||||
|
|
||||||
$generalName = $generalObj->getName();
|
$generalName = $generalObj->getName();
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ 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;
|
||||||
@@ -105,6 +106,7 @@ 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'];
|
||||||
@@ -158,6 +160,7 @@ 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,
|
||||||
@@ -210,7 +213,8 @@ class GetFrontInfo extends \sammo\BaseAPI
|
|||||||
'month' => $month,
|
'month' => $month,
|
||||||
'autorunUser' => $autorunUser,
|
'autorunUser' => $autorunUser,
|
||||||
'turnterm' => $turnterm,
|
'turnterm' => $turnterm,
|
||||||
'lastExecuted' => $lastExecuted,
|
'lastExecutedTick' => $lastExecuted,
|
||||||
|
'lastExecuted' => $clock->formatTick(Util::toInt($lastExecuted), true),
|
||||||
'lastVoteID' => $lastVoteID,
|
'lastVoteID' => $lastVoteID,
|
||||||
'develCost' => $develCost,
|
'develCost' => $develCost,
|
||||||
'noticeMsg' => $noticeMsg,
|
'noticeMsg' => $noticeMsg,
|
||||||
@@ -224,7 +228,8 @@ class GetFrontInfo extends \sammo\BaseAPI
|
|||||||
'isLocked' => $isLocked,
|
'isLocked' => $isLocked,
|
||||||
'tournamentType' => $tournamentType,
|
'tournamentType' => $tournamentType,
|
||||||
'tournamentState' => $tournamentState,
|
'tournamentState' => $tournamentState,
|
||||||
'tournamentTime' => $tournamentTime,
|
'tournamentTimeTick' => $tournamentTime,
|
||||||
|
'tournamentTime' => $tournamentTime === null ? null : $clock->formatTick(Util::toInt($tournamentTime)),
|
||||||
'genCount' => $globalGenCount,
|
'genCount' => $globalGenCount,
|
||||||
'generalCntLimit' => $generalCntLimit,
|
'generalCntLimit' => $generalCntLimit,
|
||||||
'serverCnt' => $serverCnt,
|
'serverCnt' => $serverCnt,
|
||||||
@@ -361,6 +366,7 @@ 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());
|
||||||
|
|
||||||
@@ -425,8 +431,12 @@ 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;
|
||||||
'turntime' => $general->getVar(GeneralColumn::turntime), // string;
|
'turntimeTick' => $general->getTurnTick(), // number;
|
||||||
'recent_war' => $general->getVar(GeneralColumn::recent_war), // string;
|
'turntime' => $general->getTurnTime(), // 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;
|
||||||
@@ -544,7 +554,7 @@ class GetFrontInfo extends \sammo\BaseAPI
|
|||||||
'result' => false,
|
'result' => false,
|
||||||
'reason' => '접속 제한중입니다.',
|
'reason' => '접속 제한중입니다.',
|
||||||
'recovery' => APIRecoveryType::GameQuota,
|
'recovery' => APIRecoveryType::GameQuota,
|
||||||
'recovery_arg' => $general->getVar('turntime'),
|
'recovery_arg' => $general->getTurnTime(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ 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;
|
||||||
@@ -99,7 +100,7 @@ class Join extends \sammo\BaseAPI
|
|||||||
}
|
}
|
||||||
|
|
||||||
$gameID = UniqueConst::$serverID;
|
$gameID = UniqueConst::$serverID;
|
||||||
$alreadyJoined = $db->queryFirstField('SELECT count(*) FROM `storage` WHERE `namespace` = %s AND `key` LIKE %s', 'inheritance_result', "{$gameID}_{$userID}_%");
|
$alreadyJoined = $db->queryFirstField('SELECT COUNT(*) FROM `inheritance_result` WHERE `server_id` = %s AND `owner` = %i', $gameID, $userID);
|
||||||
if ($alreadyJoined) {
|
if ($alreadyJoined) {
|
||||||
//이미 받았음
|
//이미 받았음
|
||||||
return 0;
|
return 0;
|
||||||
@@ -157,7 +158,7 @@ class Join extends \sammo\BaseAPI
|
|||||||
|
|
||||||
$penalty = [];
|
$penalty = [];
|
||||||
foreach($penaltyInfo as $penaltyKey => $penaltyValue){
|
foreach($penaltyInfo as $penaltyKey => $penaltyValue){
|
||||||
if($penaltyValue['expire'] ?? 0 > TimeUtil::now()){
|
if(($penaltyValue['expire'] ?? 0) > TimeUtil::now()){
|
||||||
$penalty[$penaltyKey] = $penaltyValue['value'];
|
$penalty[$penaltyKey] = $penaltyValue['value'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,6 +166,7 @@ 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');
|
||||||
@@ -222,7 +224,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 = TimeUtil::now(false);
|
$now = $clock->nowTick();
|
||||||
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
|
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
|
||||||
UniqueConst::$hiddenSeed,
|
UniqueConst::$hiddenSeed,
|
||||||
'MakeGeneral',
|
'MakeGeneral',
|
||||||
@@ -360,17 +362,14 @@ class Join extends \sammo\BaseAPI
|
|||||||
|
|
||||||
$userLogger->push(sprintf("턴 시간 %02d:%02d 로 지정", intdiv($inheritTurntime, 60), $inheritTurntime % 60), "inheritPoint");
|
$userLogger->push(sprintf("턴 시간 %02d:%02d 로 지정", intdiv($inheritTurntime, 60), $inheritTurntime % 60), "inheritPoint");
|
||||||
|
|
||||||
$inheritTurntime += $rng->nextRangeInt(0, 999999) / 1000000;
|
$inheritTurnMicrosecond = $rng->nextRangeInt(0, 999999);
|
||||||
|
$turntime = cutTurn(Util::toInt($admin['turntime']), $admin['turnterm'])
|
||||||
$turntime = new \DateTimeImmutable(cutTurn($admin['turntime'], $admin['turnterm']));
|
+ $clock->ticksFromSeconds($inheritTurntime)
|
||||||
$turntime = $turntime->add(TimeUtil::secondsToDateInterval($inheritTurntime));
|
+ intdiv($inheritTurnMicrosecond * $clock->ticksPerSecond(), 1_000_000);
|
||||||
$turntime = TimeUtil::format($turntime, true);
|
|
||||||
} else {
|
} else {
|
||||||
$turntime = getRandTurn($rng, $admin['turnterm'], new \DateTimeImmutable($admin['turntime']));
|
$turntime = getRandTurn($rng, $admin['turnterm'], Util::toInt($admin['turntime']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$now = TimeUtil::now(true);
|
|
||||||
if ($now >= $turntime) {
|
if ($now >= $turntime) {
|
||||||
$turntime = addTurn($turntime, $admin['turnterm']);
|
$turntime = addTurn($turntime, $admin['turnterm']);
|
||||||
}
|
}
|
||||||
@@ -435,6 +434,13 @@ 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,6 +8,8 @@ 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
|
||||||
{
|
{
|
||||||
@@ -35,11 +37,13 @@ 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,
|
||||||
'lastExecuted' => $lastExecuted,
|
'lastExecutedTick' => $lastExecuted,
|
||||||
|
'lastExecuted' => $clock->formatTick($lastExecuted, true),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
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;
|
||||||
@@ -145,7 +146,8 @@ class GeneralList extends \sammo\BaseAPI
|
|||||||
|
|
||||||
|
|
||||||
if (static::$withToken) {
|
if (static::$withToken) {
|
||||||
$now = (new \DateTimeImmutable())->format('Y-m-d H:i:s');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$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,6 +4,7 @@ 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;
|
||||||
@@ -98,6 +99,10 @@ 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');
|
||||||
|
|||||||
@@ -64,13 +64,11 @@ class ResetTurnTime extends \sammo\BaseAPI
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$turnTerm = $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->getTurnTime()
|
$general->getAuxVar('nextTurnTimeBase') ?? $general->getTurnTick()
|
||||||
)));
|
)));
|
||||||
|
|
||||||
$afterTurn = $rng->nextFloat1() * $turnTerm * 60;
|
$afterTurn = $rng->nextFloat1() * $turnTerm * 60;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ 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;
|
||||||
@@ -264,8 +265,11 @@ 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) => substr($rawGeneral['turntime'], 0, 19),
|
'turntime' => fn ($rawGeneral) => GameClock::fromStorage($gameStor)
|
||||||
'recent_war' => fn ($rawGeneral) => substr($rawGeneral['recent_war'], 0, 19),
|
->formatTick(Util::toInt($rawGeneral['turntime'])),
|
||||||
|
'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,6 +8,7 @@ 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;
|
||||||
@@ -51,7 +52,8 @@ 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) {
|
||||||
return "접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 갱신 가능 시각 : {$me['turntime']})";
|
$limitTime = GameClock::fromStorage($gameStor)->formatTick(Util::toInt($me['turntime']), true);
|
||||||
|
return "접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 갱신 가능 시각 : {$limitTime})";
|
||||||
}
|
}
|
||||||
|
|
||||||
$permission = checkSecretPermission($me);
|
$permission = checkSecretPermission($me);
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ 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();
|
||||||
@@ -25,8 +30,9 @@ 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{
|
||||||
$oNow = new \DateTimeImmutable();
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$now = $oNow->format('Y-m-d H:i:s');
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
|
$now = $clock->nowTick();
|
||||||
|
|
||||||
$db->update('select_pool', [
|
$db->update('select_pool', [
|
||||||
'reserved_until'=>null,
|
'reserved_until'=>null,
|
||||||
@@ -36,17 +42,15 @@ 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']);
|
||||||
$dexTotal = array_sum($cand['info']['dex']);
|
$pool[] = [$cand, static::getCandidateWeight($cand['info'], $owner)];
|
||||||
$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 * $gameStor->turnterm);
|
|
||||||
while(count($result) < $pickCnt){
|
while(count($result) < $pickCnt){
|
||||||
$cand = $rng->choiceUsingWeightPair($pool);
|
$cand = $rng->choiceUsingWeightPair($pool);
|
||||||
$poolID = $cand['id'];
|
$poolID = $cand['id'];
|
||||||
@@ -69,4 +73,4 @@ abstract class AbsFromUserPool extends AbsGeneralPool{
|
|||||||
|
|
||||||
return array_values($result);
|
return array_values($result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ abstract class AbsGeneralPool{
|
|||||||
* specialWar
|
* specialWar
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public function __construct(\MeekroDB $db, RandUtil $rng, array $info, string $validUntil)
|
public function __construct(\MeekroDB $db, RandUtil $rng, array $info, int $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():string{
|
public function getValidUntil():int{
|
||||||
return $this->validUntil;
|
return $this->validUntil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,4 +109,4 @@ abstract class AbsGeneralPool{
|
|||||||
|
|
||||||
abstract public static function getPoolName():string;
|
abstract public static function getPoolName():string;
|
||||||
abstract public static function initPool(\MeekroDB $db);
|
abstract public static function initPool(\MeekroDB $db);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class che_척사_오악진형도 extends \sammo\BaseItem{
|
|||||||
|
|
||||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||||
$opposeCrewType = $unit->getOppose()->getCrewType();
|
$opposeCrewType = $unit->getOppose()->getCrewType();
|
||||||
if($opposeCrewType->reqCities || $opposeCrewType->reqRegions){
|
if($opposeCrewType->reqCities() || $opposeCrewType->reqRegions()){
|
||||||
return [1.15, 0.85];
|
return [1.15, 0.85];
|
||||||
}
|
}
|
||||||
return [1, 1];
|
return [1, 1];
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class event_전투특기_공성 extends \sammo\BaseItem{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_SIEGE;
|
$myArmType = 'dex'.GameUnitConst::T_SIEGE;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class event_전투특기_궁병 extends \sammo\BaseItem{
|
|||||||
if($statName === 'warAvoidRatio'){
|
if($statName === 'warAvoidRatio'){
|
||||||
return $value + 0.2;
|
return $value + 0.2;
|
||||||
}
|
}
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_ARCHER;
|
$myArmType = 'dex'.GameUnitConst::T_ARCHER;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class event_전투특기_귀병 extends \sammo\BaseItem{
|
|||||||
if($statName === 'warMagicSuccessProb'){
|
if($statName === 'warMagicSuccessProb'){
|
||||||
return $value + 0.2;
|
return $value + 0.2;
|
||||||
}
|
}
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_WIZARD;
|
$myArmType = 'dex'.GameUnitConst::T_WIZARD;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class event_전투특기_기병 extends \sammo\BaseItem{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_CAVALRY;
|
$myArmType = 'dex'.GameUnitConst::T_CAVALRY;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class event_전투특기_보병 extends \sammo\BaseItem{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_FOOTMAN;
|
$myArmType = 'dex'.GameUnitConst::T_FOOTMAN;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class event_전투특기_척사 extends \sammo\BaseItem{
|
|||||||
|
|
||||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||||
$opposeCrewType = $unit->getOppose()->getCrewType();
|
$opposeCrewType = $unit->getOppose()->getCrewType();
|
||||||
if($opposeCrewType->reqCities || $opposeCrewType->reqRegions){
|
if($opposeCrewType->reqCities() || $opposeCrewType->reqRegions()){
|
||||||
return [1.2, 0.8];
|
return [1.2, 0.8];
|
||||||
}
|
}
|
||||||
return [1, 1];
|
return [1, 1];
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace sammo\ActionScenarioEffect;
|
||||||
|
|
||||||
|
use \sammo\iAction;
|
||||||
|
use sammo\Util;
|
||||||
|
use sammo\WarUnit;
|
||||||
|
use sammo\WarUnitCity;
|
||||||
|
use sammo\WarUnitTrigger\che_전멸시페이즈증가;
|
||||||
|
use sammo\WarUnitTriggerCaller;
|
||||||
|
|
||||||
|
class event_MoreEffect implements iAction
|
||||||
|
{
|
||||||
|
use \sammo\DefaultAction;
|
||||||
|
|
||||||
|
public function getWarPowerMultiplier(WarUnit $unit): array
|
||||||
|
{
|
||||||
|
if ($unit->isAttacker()) {
|
||||||
|
return [1.4, 0.7143];
|
||||||
|
}
|
||||||
|
return [1, 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux = null): float
|
||||||
|
{
|
||||||
|
$scoreMap = [
|
||||||
|
'상업' => 2,
|
||||||
|
'농업' => 2,
|
||||||
|
'치안' => 2,
|
||||||
|
'기술' => 2,
|
||||||
|
'성벽' => 2,
|
||||||
|
'수비' => 2,
|
||||||
|
'인구' => 2,
|
||||||
|
'민심' => 2,
|
||||||
|
];
|
||||||
|
if ($turnType == 'changeDefenceTrain') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ($varType === 'score' && key_exists($turnType, $scoreMap)) {
|
||||||
|
$multiplier = $scoreMap[$turnType];
|
||||||
|
$value *= $multiplier;
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onCalcNationalIncome(string $type, $amount){
|
||||||
|
if($type == 'gold'){
|
||||||
|
return $amount * 2;
|
||||||
|
}
|
||||||
|
if($type == 'rice'){
|
||||||
|
return $amount * 2;
|
||||||
|
}
|
||||||
|
if($type == 'pop' && $amount > 0){
|
||||||
|
return $amount * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
|
||||||
|
{
|
||||||
|
return new WarUnitTriggerCaller(
|
||||||
|
new che_전멸시페이즈증가($unit),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,7 +35,7 @@ class che_event_공성 extends \sammo\BaseSpecial{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_SIEGE;
|
$myArmType = 'dex'.GameUnitConst::T_SIEGE;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class che_event_궁병 extends \sammo\BaseSpecial{
|
|||||||
if($statName === 'warAvoidRatio'){
|
if($statName === 'warAvoidRatio'){
|
||||||
return $value + 0.2;
|
return $value + 0.2;
|
||||||
}
|
}
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_ARCHER;
|
$myArmType = 'dex'.GameUnitConst::T_ARCHER;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class che_event_귀병 extends \sammo\BaseSpecial{
|
|||||||
if($statName === 'warMagicSuccessProb'){
|
if($statName === 'warMagicSuccessProb'){
|
||||||
return $value + 0.2;
|
return $value + 0.2;
|
||||||
}
|
}
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_WIZARD;
|
$myArmType = 'dex'.GameUnitConst::T_WIZARD;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class che_event_기병 extends \sammo\BaseSpecial{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_CAVALRY;
|
$myArmType = 'dex'.GameUnitConst::T_CAVALRY;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class che_event_보병 extends \sammo\BaseSpecial{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_FOOTMAN;
|
$myArmType = 'dex'.GameUnitConst::T_FOOTMAN;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class che_event_척사 extends \sammo\BaseSpecial{
|
|||||||
|
|
||||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||||
$opposeCrewType = $unit->getOppose()->getCrewType();
|
$opposeCrewType = $unit->getOppose()->getCrewType();
|
||||||
if($opposeCrewType->reqCities || $opposeCrewType->reqRegions){
|
if($opposeCrewType->reqCities() || $opposeCrewType->reqRegions()){
|
||||||
return [1.2, 0.8];
|
return [1.2, 0.8];
|
||||||
}
|
}
|
||||||
return [1, 1];
|
return [1, 1];
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class che_공성 extends \sammo\BaseSpecial{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_SIEGE;
|
$myArmType = 'dex'.GameUnitConst::T_SIEGE;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class che_궁병 extends \sammo\BaseSpecial{
|
|||||||
if($statName === 'warAvoidRatio'){
|
if($statName === 'warAvoidRatio'){
|
||||||
return $value + 0.2;
|
return $value + 0.2;
|
||||||
}
|
}
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_ARCHER;
|
$myArmType = 'dex'.GameUnitConst::T_ARCHER;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class che_귀병 extends \sammo\BaseSpecial{
|
|||||||
if($statName === 'warMagicSuccessProb'){
|
if($statName === 'warMagicSuccessProb'){
|
||||||
return $value + 0.2;
|
return $value + 0.2;
|
||||||
}
|
}
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_WIZARD;
|
$myArmType = 'dex'.GameUnitConst::T_WIZARD;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class che_기병 extends \sammo\BaseSpecial{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_CAVALRY;
|
$myArmType = 'dex'.GameUnitConst::T_CAVALRY;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class che_보병 extends \sammo\BaseSpecial{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
if(str_starts_with($statName, 'dex')){
|
||||||
$myArmType = 'dex'.GameUnitConst::T_FOOTMAN;
|
$myArmType = 'dex'.GameUnitConst::T_FOOTMAN;
|
||||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class che_척사 extends \sammo\BaseSpecial{
|
|||||||
|
|
||||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||||
$opposeCrewType = $unit->getOppose()->getCrewType();
|
$opposeCrewType = $unit->getOppose()->getCrewType();
|
||||||
if($opposeCrewType->reqCities || $opposeCrewType->reqRegions){
|
if($opposeCrewType->reqCities() || $opposeCrewType->reqRegions()){
|
||||||
return [1.2, 0.8];
|
return [1.2, 0.8];
|
||||||
}
|
}
|
||||||
return [1, 1];
|
return [1, 1];
|
||||||
|
|||||||
+55
-54
@@ -146,40 +146,35 @@ abstract class Auction
|
|||||||
return $this->info;
|
return $this->info;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function shrinkCloseDate(?DateTimeInterface $date): ?string
|
public function shrinkCloseTick(?int $tick): ?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 extendLatestBidCloseDate(?DateTimeInterface $date): ?string
|
public function extendLatestBidCloseTick(?int $tick): ?string
|
||||||
{
|
{
|
||||||
if ($date === null) {
|
if ($tick === null) {
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
$turnTerm = $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)
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
else{
|
if ($this->info->detail->availableLatestBidCloseTick !== null && $tick < $this->info->detail->availableLatestBidCloseTick) {
|
||||||
$date = DateTimeImmutable::createFromInterface($date);
|
|
||||||
}
|
|
||||||
if ($this->info->detail->availableLatestBidCloseDate !== null && $date < $this->info->detail->availableLatestBidCloseDate) {
|
|
||||||
return '기간보다 짧습니다.';
|
return '기간보다 짧습니다.';
|
||||||
}
|
}
|
||||||
$this->info->detail->availableLatestBidCloseDate = $date;
|
$this->info->detail->availableLatestBidCloseTick = $tick;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function extendCloseDate(DateTimeInterface $date, bool $force = false): ?string
|
public function extendCloseTick(int $tick, bool $force = false): ?string
|
||||||
{
|
{
|
||||||
if (!$force) {
|
if (!$force) {
|
||||||
if ($this->info->detail->remainCloseDateExtensionCnt === null) {
|
if ($this->info->detail->remainCloseDateExtensionCnt === null) {
|
||||||
@@ -193,12 +188,11 @@ abstract class Auction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($date < $this->info->closeDate) {
|
if ($tick < $this->info->closeTick) {
|
||||||
return '종료 기간보다 짧습니다.';
|
return '종료 기간보다 짧습니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
$closeDate = DateTimeImmutable::createFromInterface($date);
|
$this->info->closeTick = $tick;
|
||||||
$this->info->closeDate = $closeDate;
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,12 +239,13 @@ 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,
|
||||||
new DateTime(),
|
DateTime::createFromImmutable($clock->tickToDateTime($clock->nowTick())),
|
||||||
new DateTime('9999-12-31'),
|
new DateTime('9999-12-31'),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
@@ -275,7 +270,12 @@ 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(int $amount, \DateTimeImmutable $now, bool $tryExtendCloseDate): ?string
|
private function bidInheritPoint(
|
||||||
|
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,
|
||||||
$now,
|
$nowDate,
|
||||||
new AuctionBidItemData(
|
new AuctionBidItemData(
|
||||||
$general->getVar('owner_name'),
|
$general->getVar('owner_name'),
|
||||||
$obfuscatedName,
|
$obfuscatedName,
|
||||||
@@ -324,15 +324,16 @@ abstract class Auction
|
|||||||
}
|
}
|
||||||
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$turnTerm = $gameStor->getValue('turnterm');
|
||||||
|
|
||||||
if ($this->info->detail->availableLatestBidCloseDate !== null) {
|
if ($this->info->detail->availableLatestBidCloseTick !== null) {
|
||||||
$extendedCloseDate = $now->add(TimeUtil::secondsToDateInterval(
|
$extendedCloseTick = $nowTick + $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 ($extendedCloseDate > $this->info->closeDate && $this->info->closeDate < $this->info->detail->availableLatestBidCloseDate) {
|
if ($extendedCloseTick > $this->info->closeTick && $this->info->closeTick < $this->info->detail->availableLatestBidCloseTick) {
|
||||||
$this->extendCloseDate(min($extendedCloseDate, $this->info->detail->availableLatestBidCloseDate), true);
|
$this->extendCloseTick(min($extendedCloseTick, $this->info->detail->availableLatestBidCloseTick), true);
|
||||||
$this->applyDB();
|
$this->applyDB();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -356,12 +357,16 @@ abstract class Auction
|
|||||||
return '경매가 이미 끝났습니다.';
|
return '경매가 이미 끝났습니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
$now = new \DateTimeImmutable();
|
$db = DB::db();
|
||||||
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
|
$nowTick = $clock->nowTick();
|
||||||
|
$nowDate = $clock->tickToDateTime($nowTick);
|
||||||
|
|
||||||
if ($auctionInfo->closeDate < $now) {
|
if ($auctionInfo->closeTick < $nowTick) {
|
||||||
return '경매가 이미 끝났습니다.';
|
return '경매가 이미 끝났습니다.';
|
||||||
}
|
}
|
||||||
if ($auctionInfo->openDate > $now) {
|
if ($auctionInfo->openTick > $nowTick) {
|
||||||
return '경매가 아직 시작되지 않았습니다.';
|
return '경매가 아직 시작되지 않았습니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,13 +382,11 @@ abstract class Auction
|
|||||||
|
|
||||||
|
|
||||||
if ($auctionInfo->reqResource === ResourceType::inheritancePoint) {
|
if ($auctionInfo->reqResource === ResourceType::inheritancePoint) {
|
||||||
return $this->bidInheritPoint($amount, $now, $tryExtendCloseDate);
|
return $this->bidInheritPoint($amount, $nowTick, $nowDate, $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) {
|
||||||
@@ -421,7 +424,7 @@ abstract class Auction
|
|||||||
$general->getVar('owner'),
|
$general->getVar('owner'),
|
||||||
$general->getID(),
|
$general->getID(),
|
||||||
$amount,
|
$amount,
|
||||||
$now,
|
$nowDate,
|
||||||
new AuctionBidItemData(
|
new AuctionBidItemData(
|
||||||
$general->getVar('owner_name'),
|
$general->getVar('owner_name'),
|
||||||
$general->getName(),
|
$general->getName(),
|
||||||
@@ -436,14 +439,13 @@ abstract class Auction
|
|||||||
|
|
||||||
$general->increaseVar($resType->value, -$morePoint);
|
$general->increaseVar($resType->value, -$morePoint);
|
||||||
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$turnTerm = $gameStor->getValue('turnterm');
|
||||||
$extendedCloseDate = $now->add(TimeUtil::secondsToDateInterval(
|
$extendedCloseTick = $nowTick + $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 ($extendedCloseDate > $this->info->closeDate) {
|
if ($extendedCloseTick > $this->info->closeTick) {
|
||||||
$this->extendCloseDate($extendedCloseDate, true);
|
$this->extendCloseTick($extendedCloseTick, true);
|
||||||
$this->applyDB();
|
$this->applyDB();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,10 +458,10 @@ abstract class Auction
|
|||||||
|
|
||||||
public function tryFinish(): ?bool
|
public function tryFinish(): ?bool
|
||||||
{
|
{
|
||||||
$now = new DateTimeImmutable();
|
$db = DB::db();
|
||||||
if ($now < $this->info->closeDate) {
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
return null;
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
}
|
if ($clock->nowTick() < $this->info->closeTick) return null;
|
||||||
|
|
||||||
//경매를 닫아야한다.
|
//경매를 닫아야한다.
|
||||||
$highestBid = $this->getHighestBid();
|
$highestBid = $this->getHighestBid();
|
||||||
@@ -469,17 +471,15 @@ abstract class Auction
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($highestBid->aux->tryExtendCloseDate) {
|
if ($highestBid->aux->tryExtendCloseDate) {
|
||||||
$db = DB::db();
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$turnTerm = $gameStor->getValue('turnterm');
|
||||||
|
|
||||||
//연장 요청이 있었다.
|
//연장 요청이 있었다.
|
||||||
$extendedCloseDate = $this->info->closeDate->add(TimeUtil::secondsToDateInterval(
|
$extendedCloseTick = $this->info->closeTick + $clock->ticksFromMinutes(
|
||||||
max(static::MIN_EXTENSION_MINUTES_BY_EXTENSION_QUERY, $turnTerm * static::COEFF_EXTENSION_MINUTES_BY_EXTENSION_QUERY) * 60
|
max(static::MIN_EXTENSION_MINUTES_BY_EXTENSION_QUERY, $turnTerm * static::COEFF_EXTENSION_MINUTES_BY_EXTENSION_QUERY)
|
||||||
));
|
);
|
||||||
|
|
||||||
if ($this->extendCloseDate($extendedCloseDate) === null) {
|
if ($this->extendCloseTick($extendedCloseTick) === null) {
|
||||||
$this->extendLatestBidCloseDate(null);
|
$this->extendLatestBidCloseTick(null);
|
||||||
$this->applyDB();
|
$this->applyDB();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -509,12 +509,13 @@ 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,
|
||||||
new \DateTime(),
|
DateTime::createFromImmutable($clock->tickToDateTime($clock->nowTick())),
|
||||||
new \DateTime('9999-12-31'),
|
new \DateTime('9999-12-31'),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -56,10 +56,11 @@ abstract class AuctionBasicResource extends Auction
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$now = new \DateTimeImmutable();
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
|
$nowTick = $clock->nowTick();
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$turnTerm = $gameStor->getValue('turnterm');
|
||||||
$closeDate = $now->add(TimeUtil::secondsToDateInterval($closeTurnCnt * $turnTerm * 60));
|
$closeTick = $nowTick + GameClock::TICKS_PER_TURN * $closeTurnCnt;
|
||||||
|
|
||||||
$openResult = static::openAuction(new AuctionInfo(
|
$openResult = static::openAuction(new AuctionInfo(
|
||||||
null,
|
null,
|
||||||
@@ -68,8 +69,8 @@ abstract class AuctionBasicResource extends Auction
|
|||||||
"$amount",
|
"$amount",
|
||||||
$general->getId(),
|
$general->getId(),
|
||||||
$bidderRes,
|
$bidderRes,
|
||||||
$now,
|
$nowTick,
|
||||||
$closeDate,
|
$closeTick,
|
||||||
new AuctionInfoDetail(
|
new AuctionInfoDetail(
|
||||||
"{$hostResName} {$amount} 경매",
|
"{$hostResName} {$amount} 경매",
|
||||||
$general->getName(),
|
$general->getName(),
|
||||||
@@ -145,12 +146,13 @@ 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} 경매에 입찰이 없어 취소되었습니다.",
|
||||||
new \DateTime(),
|
\DateTime::createFromImmutable($clock->tickToDateTime($clock->nowTick())),
|
||||||
new \DateTime('9999-12-31'),
|
new \DateTime('9999-12-31'),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
@@ -246,8 +248,8 @@ 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');
|
||||||
$date = (new DateTimeImmutable())->add(TimeUtil::secondsToDateInterval($turnTerm * 60));
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
$this->shrinkCloseDate($date);
|
$this->shrinkCloseTick($clock->nowTick() + GameClock::TICKS_PER_TURN);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -72,16 +72,15 @@ 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);
|
||||||
$closeDate = $now->add(TimeUtil::secondsToDateInterval(
|
$nowTick = $clock->nowTick();
|
||||||
max(static::MIN_AUCTION_CLOSE_MINUTES, $turnTerm * static::COEFF_AUCTION_CLOSE_MINUTES) * 60
|
$closeTick = $nowTick + $clock->ticksFromMinutes(
|
||||||
));
|
max(static::MIN_AUCTION_CLOSE_MINUTES, $turnTerm * static::COEFF_AUCTION_CLOSE_MINUTES)
|
||||||
$availableLatestBidCloseDate = $closeDate->add(TimeUtil::secondsToDateInterval(
|
);
|
||||||
max(static::MIN_EXTENSION_MINUTES_LIMIT_BY_BID, $turnTerm * static::COEFF_EXTENSION_MINUTES_LIMIT_BY_BID) * 60
|
$availableLatestBidCloseTick = $closeTick + $clock->ticksFromMinutes(
|
||||||
));
|
max(static::MIN_EXTENSION_MINUTES_LIMIT_BY_BID, $turnTerm * static::COEFF_EXTENSION_MINUTES_LIMIT_BY_BID)
|
||||||
|
);
|
||||||
|
|
||||||
$info = new AuctionInfo(
|
$info = new AuctionInfo(
|
||||||
null,
|
null,
|
||||||
@@ -90,8 +89,8 @@ class AuctionUniqueItem extends Auction
|
|||||||
$itemKey,
|
$itemKey,
|
||||||
$general->getID(),
|
$general->getID(),
|
||||||
ResourceType::inheritancePoint,
|
ResourceType::inheritancePoint,
|
||||||
$now,
|
$nowTick,
|
||||||
$closeDate,
|
$closeTick,
|
||||||
new AuctionInfoDetail(
|
new AuctionInfoDetail(
|
||||||
"{$item->getName()} 경매",
|
"{$item->getName()} 경매",
|
||||||
static::genObfuscatedName($general->getID()),
|
static::genObfuscatedName($general->getID()),
|
||||||
@@ -100,7 +99,7 @@ class AuctionUniqueItem extends Auction
|
|||||||
$startAmount,
|
$startAmount,
|
||||||
null,
|
null,
|
||||||
1,
|
1,
|
||||||
$availableLatestBidCloseDate,
|
$availableLatestBidCloseTick,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -267,21 +266,22 @@ class AuctionUniqueItem extends Auction
|
|||||||
|
|
||||||
if ($availableEquipUniqueCnt <= 0) {
|
if ($availableEquipUniqueCnt <= 0) {
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$turnTerm = $gameStor->getValue('turnterm');
|
||||||
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
//제한에 걸렸다면 자동 연장
|
//제한에 걸렸다면 자동 연장
|
||||||
$extendedCloseDate = $this->info->closeDate->add(TimeUtil::secondsToDateInterval(
|
$extendedCloseTick = $this->info->closeTick + $clock->ticksFromMinutes(
|
||||||
max(static::MIN_EXTENSION_MINUTES_BY_EXTENSION_QUERY, $turnTerm * static::COEFF_EXTENSION_MINUTES_LIMIT_UNIQUE_CNT) * 60
|
max(static::MIN_EXTENSION_MINUTES_BY_EXTENSION_QUERY, $turnTerm * static::COEFF_EXTENSION_MINUTES_LIMIT_UNIQUE_CNT)
|
||||||
));
|
);
|
||||||
|
|
||||||
if($bidder->getID() != $this->info->hostGeneralID){
|
if($bidder->getID() != $this->info->hostGeneralID){
|
||||||
$this->setHostAsNeutral();
|
$this->setHostAsNeutral();
|
||||||
}
|
}
|
||||||
$this->extendCloseDate($extendedCloseDate, true);
|
$this->extendCloseTick($extendedCloseTick, true);
|
||||||
$this->extendLatestBidCloseDate(null);
|
$this->extendLatestBidCloseTick(null);
|
||||||
$this->applyDB();
|
$this->applyDB();
|
||||||
return '유니크 아이템 소유 제한 상태입니다. 종료 시간이 연장됩니다.';
|
return '유니크 아이템 소유 제한 상태입니다. 종료 시간이 연장됩니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
$isExtendCloseDateRequired = false;
|
$isExtendCloseTickRequired = 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 +291,13 @@ class AuctionUniqueItem extends Auction
|
|||||||
$ownItem = $general->getItem($itemType);
|
$ownItem = $general->getItem($itemType);
|
||||||
if ($ownItem->getRawClassName() == $itemKey) {
|
if ($ownItem->getRawClassName() == $itemKey) {
|
||||||
//FIXME: 이 경우에는 환불이 되던가 해야함.
|
//FIXME: 이 경우에는 환불이 되던가 해야함.
|
||||||
$isExtendCloseDateRequired = true;
|
$isExtendCloseTickRequired = true;
|
||||||
$reasons[] = '이미 그 유니크를 가지고 있습니다.';
|
$reasons[] = '이미 그 유니크를 가지고 있습니다.';
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$ownItem->isBuyable()) {
|
if (!$ownItem->isBuyable()) {
|
||||||
$isExtendCloseDateRequired = true;
|
$isExtendCloseTickRequired = true;
|
||||||
$reasons[] = '이미 다른 유니크를 가지고 있습니다.';
|
$reasons[] = '이미 다른 유니크를 가지고 있습니다.';
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -313,18 +313,19 @@ class AuctionUniqueItem extends Auction
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!$availableItemTypes) {
|
if (!$availableItemTypes) {
|
||||||
if ($isExtendCloseDateRequired) {
|
if ($isExtendCloseTickRequired) {
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$turnTerm = $gameStor->getValue('turnterm');
|
||||||
|
$clock = GameClock::fromStorage($gameStor);
|
||||||
//동일 부위 제한에 걸렸다면 자동 연장
|
//동일 부위 제한에 걸렸다면 자동 연장
|
||||||
$extendedCloseDate = $this->info->closeDate->add(TimeUtil::secondsToDateInterval(
|
$extendedCloseTick = $this->info->closeTick + $clock->ticksFromMinutes(
|
||||||
max(static::MIN_EXTENSION_MINUTES_LIMIT_BY_BID, $turnTerm * static::COEFF_EXTENSION_MINUTES_LIMIT_BY_BID) * 60
|
max(static::MIN_EXTENSION_MINUTES_LIMIT_BY_BID, $turnTerm * static::COEFF_EXTENSION_MINUTES_LIMIT_BY_BID)
|
||||||
));
|
);
|
||||||
|
|
||||||
if($bidder->getID() != $this->info->hostGeneralID){
|
if($bidder->getID() != $this->info->hostGeneralID){
|
||||||
$this->setHostAsNeutral();
|
$this->setHostAsNeutral();
|
||||||
}
|
}
|
||||||
$this->extendCloseDate($extendedCloseDate, true);
|
$this->extendCloseTick($extendedCloseTick, true);
|
||||||
$this->extendLatestBidCloseDate(null);
|
$this->extendLatestBidCloseTick(null);
|
||||||
$this->applyDB();
|
$this->applyDB();
|
||||||
}
|
}
|
||||||
return join(' ', $reasons);
|
return join(' ', $reasons);
|
||||||
|
|||||||
@@ -0,0 +1,640 @@
|
|||||||
|
<?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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ use \sammo\{
|
|||||||
Util, JosaUtil, DB,
|
Util, JosaUtil, DB,
|
||||||
General, GameConst,
|
General, GameConst,
|
||||||
ActionLogger,
|
ActionLogger,
|
||||||
|
Json,
|
||||||
LastTurn,
|
LastTurn,
|
||||||
NotInheritedMethodException,
|
NotInheritedMethodException,
|
||||||
RandUtil
|
RandUtil
|
||||||
@@ -118,6 +119,7 @@ abstract class BaseCommand{
|
|||||||
$nationID = $this->generalObj->getNationID();
|
$nationID = $this->generalObj->getNationID();
|
||||||
if($nationID == 0){
|
if($nationID == 0){
|
||||||
$this->nation = $this->generalObj->getStaticNation();
|
$this->nation = $this->generalObj->getStaticNation();
|
||||||
|
$this->nation['aux'] = [];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +140,8 @@ abstract class BaseCommand{
|
|||||||
'gold'=>0,
|
'gold'=>0,
|
||||||
'rice'=>2000,
|
'rice'=>2000,
|
||||||
'tech'=>0,
|
'tech'=>0,
|
||||||
'gennum'=>1
|
'gennum'=>1,
|
||||||
|
'aux'=>'{}',
|
||||||
];
|
];
|
||||||
|
|
||||||
if($this->nation && $this->nation['nation'] === $nationID){
|
if($this->nation && $this->nation['nation'] === $nationID){
|
||||||
@@ -170,6 +173,10 @@ abstract class BaseCommand{
|
|||||||
else{
|
else{
|
||||||
$this->nation = $nation;
|
$this->nation = $nation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(is_string($this->nation['aux'] ?? null)){
|
||||||
|
$this->nation['aux'] = Json::decode($this->nation['aux']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function setDestGeneral(General $destGeneralObj){
|
protected function setDestGeneral(General $destGeneralObj){
|
||||||
@@ -312,12 +319,12 @@ abstract class BaseCommand{
|
|||||||
|
|
||||||
$this->generalObj->unpackAux();
|
$this->generalObj->unpackAux();
|
||||||
$constraintInput = [
|
$constraintInput = [
|
||||||
'general'=>$this->generalObj->getRaw(),
|
'general'=>$this->generalObj,
|
||||||
'city'=>$this->city,
|
'city'=>$this->city,
|
||||||
'nation'=>$this->nation,
|
'nation'=>$this->nation,
|
||||||
'cmd_arg'=>$this->arg,
|
'cmd_arg'=>$this->arg,
|
||||||
|
|
||||||
'destGeneral'=>$this->destGeneralObj?$this->destGeneralObj->getRaw():null,
|
'destGeneral'=>$this->destGeneralObj??null,
|
||||||
'destCity'=>$this->destCity,
|
'destCity'=>$this->destCity,
|
||||||
'destNation'=>$this->destNation,
|
'destNation'=>$this->destNation,
|
||||||
];
|
];
|
||||||
@@ -346,12 +353,12 @@ abstract class BaseCommand{
|
|||||||
|
|
||||||
$this->generalObj->unpackAux();
|
$this->generalObj->unpackAux();
|
||||||
$constraintInput = [
|
$constraintInput = [
|
||||||
'general'=>$this->generalObj->getRaw(),
|
'general'=>$this->generalObj,
|
||||||
'city'=>$this->city,
|
'city'=>$this->city,
|
||||||
'nation'=>$this->nation,
|
'nation'=>$this->nation,
|
||||||
'cmd_arg'=>$this->arg,
|
'cmd_arg'=>$this->arg,
|
||||||
|
|
||||||
'destGeneral'=>$this->destGeneralObj?$this->destGeneralObj->getRaw():null,
|
'destGeneral'=>$this->destGeneralObj??null,
|
||||||
'destCity'=>$this->destCity,
|
'destCity'=>$this->destCity,
|
||||||
'destNation'=>$this->destNation,
|
'destNation'=>$this->destNation,
|
||||||
];
|
];
|
||||||
@@ -384,12 +391,12 @@ abstract class BaseCommand{
|
|||||||
|
|
||||||
$this->generalObj->unpackAux();
|
$this->generalObj->unpackAux();
|
||||||
$constraintInput = [
|
$constraintInput = [
|
||||||
'general'=>$this->generalObj->getRaw(),
|
'general'=>$this->generalObj,
|
||||||
'city'=>$this->city,
|
'city'=>$this->city,
|
||||||
'nation'=>$this->nation,
|
'nation'=>$this->nation,
|
||||||
'cmd_arg'=>$this->arg,
|
'cmd_arg'=>$this->arg,
|
||||||
|
|
||||||
'destGeneral'=>$this->destGeneralObj?$this->destGeneralObj->getRaw():null,
|
'destGeneral'=>$this->destGeneralObj??null,
|
||||||
'destCity'=>$this->destCity,
|
'destCity'=>$this->destCity,
|
||||||
'destNation'=>$this->destNation,
|
'destNation'=>$this->destNation,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ class che_건국 extends Command\GeneralCommand
|
|||||||
$general->addExperience($exp);
|
$general->addExperience($exp);
|
||||||
$general->addDedication($ded);
|
$general->addDedication($ded);
|
||||||
|
|
||||||
$aux = Json::decode($this->nation['aux']) ?? [];
|
$aux = $this->nation['aux'];
|
||||||
$aux['can_국기변경'] = 1;
|
$aux['can_국기변경'] = 1;
|
||||||
|
|
||||||
$db->update('city', [
|
$db->update('city', [
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ class che_랜덤임관 extends Command\GeneralCommand
|
|||||||
if ($notIn) {
|
if ($notIn) {
|
||||||
|
|
||||||
$rawGeneralsCnt = $db->query(
|
$rawGeneralsCnt = $db->query(
|
||||||
"SELECT g.`nation`, n.`gennum`, n.name, SUM((ra.value + 1000)/(rb.value + 1000)*(CASE WHEN g.`npc` < 2 THEN 1.2 ELSE 1 END)*(CASE WHEN g.`leadership` >= 40 THEN g.`leadership` ELSE 0 END)) AS warpower, SUM(SQRT(g.intel * g.strength) * 2 + g.leadership / 2)/5 AS develpower
|
"SELECT g.`nation`, n.`gennum`, n.name, SUM((ra.value + 50000)/(rb.value + 50000)*(CASE WHEN g.`npc` < 2 THEN 1.15 ELSE 1 END)*(CASE WHEN g.`leadership` >= 40 THEN g.`leadership` ELSE 0 END)) AS warpower, SUM(SQRT(g.intel * g.strength) * 2 + g.leadership / 2)/5 AS develpower
|
||||||
FROM general AS g
|
FROM general AS g
|
||||||
LEFT JOIN `rank_data` AS ra ON g.`no` = ra.general_id AND ra.`type` = 'killcrew_person'
|
LEFT JOIN `rank_data` AS ra ON g.`no` = ra.general_id AND ra.`type` = 'killcrew_person'
|
||||||
LEFT JOIN `rank_data` AS rb ON g.`no` = rb.general_id AND rb.`type` = 'deathcrew_person'
|
LEFT JOIN `rank_data` AS rb ON g.`no` = rb.general_id AND rb.`type` = 'deathcrew_person'
|
||||||
@@ -193,7 +193,7 @@ class che_랜덤임관 extends Command\GeneralCommand
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$rawGeneralsCnt = $db->query(
|
$rawGeneralsCnt = $db->query(
|
||||||
"SELECT g.`nation`, n.`gennum`, n.name, SUM((ra.value + 100)/(rb.value + 100)*(CASE WHEN g.`npc` < 2 THEN 1.2 ELSE 1 END)*(CASE WHEN g.`leadership` >= 40 THEN g.`leadership` ELSE 0 END)) AS warpower, SUM(SQRT(g.intel * g.strength) * 2 + g.leadership / 2)/5 AS develpower
|
"SELECT g.`nation`, n.`gennum`, n.name, SUM((ra.value + 50000)/(rb.value + 50000)*(CASE WHEN g.`npc` < 2 THEN 1.15 ELSE 1 END)*(CASE WHEN g.`leadership` >= 40 THEN g.`leadership` ELSE 0 END)) AS warpower, SUM(SQRT(g.intel * g.strength) * 2 + g.leadership / 2)/5 AS develpower
|
||||||
FROM general AS g
|
FROM general AS g
|
||||||
LEFT JOIN `rank_data` AS ra ON g.`no` = ra.general_id AND ra.`type` = 'killcrew_person'
|
LEFT JOIN `rank_data` AS ra ON g.`no` = ra.general_id AND ra.`type` = 'killcrew_person'
|
||||||
LEFT JOIN `rank_data` AS rb ON g.`no` = rb.general_id AND rb.`type` = 'deathcrew_person'
|
LEFT JOIN `rank_data` AS rb ON g.`no` = rb.general_id AND rb.`type` = 'deathcrew_person'
|
||||||
@@ -208,7 +208,7 @@ class che_랜덤임관 extends Command\GeneralCommand
|
|||||||
foreach ($rawGeneralsCnt as $nation) {
|
foreach ($rawGeneralsCnt as $nation) {
|
||||||
$calcCnt = $nation['warpower'] + $nation['develpower'];
|
$calcCnt = $nation['warpower'] + $nation['develpower'];
|
||||||
|
|
||||||
if ($general->getNPCType() < 2 && Util::starts_with($nation['name'], 'ⓤ')) {
|
if ($general->getNPCType() < 2 && str_starts_with($nation['name'], 'ⓤ')) {
|
||||||
$calcCnt *= 100;
|
$calcCnt *= 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ class che_무작위건국 extends Command\GeneralCommand
|
|||||||
$general->addExperience($exp);
|
$general->addExperience($exp);
|
||||||
$general->addDedication($ded);
|
$general->addDedication($ded);
|
||||||
|
|
||||||
$aux = Json::decode($this->nation['aux']) ?? [];
|
$aux = $this->nation['aux'];
|
||||||
$aux['can_국기변경'] = 1;
|
$aux['can_국기변경'] = 1;
|
||||||
$aux['can_무작위수도이전'] = 1;
|
$aux['can_무작위수도이전'] = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ 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
|
||||||
{
|
{
|
||||||
@@ -157,6 +158,7 @@ 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);
|
||||||
@@ -164,6 +166,19 @@ 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,6 +7,7 @@ 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;
|
||||||
@@ -190,6 +191,12 @@ 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, '라');
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class che_징병 extends Command\GeneralCommand
|
|||||||
protected function init()
|
protected function init()
|
||||||
{
|
{
|
||||||
$this->setCity();
|
$this->setCity();
|
||||||
$this->setNation(['tech']);
|
$this->setNation(['tech', 'aux']);
|
||||||
|
|
||||||
$this->minConditionConstraints = [
|
$this->minConditionConstraints = [
|
||||||
ConstraintHelper::NotBeNeutral(),
|
ConstraintHelper::NotBeNeutral(),
|
||||||
@@ -256,8 +256,11 @@ class che_징병 extends Command\GeneralCommand
|
|||||||
$ownCities = [];
|
$ownCities = [];
|
||||||
$ownRegions = [];
|
$ownRegions = [];
|
||||||
|
|
||||||
foreach (DB::db()->query('SELECT city, region from city where nation = %i', $general->getNationID()) as $city) {
|
foreach (DB::db()->query('SELECT city, region, secu, level from city where nation = %i', $general->getNationID()) as $city) {
|
||||||
$ownCities[$city['city']] = 1;
|
$ownCities[$city['city']] = [
|
||||||
|
'secu' => $city['secu'],
|
||||||
|
'level' => $city['level'],
|
||||||
|
];
|
||||||
$ownRegions[$city['region']] = 1;
|
$ownRegions[$city['region']] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,23 +276,19 @@ class che_징병 extends Command\GeneralCommand
|
|||||||
'values' => [],
|
'values' => [],
|
||||||
];
|
];
|
||||||
|
|
||||||
$crewTypes = [];
|
|
||||||
foreach (GameUnitConst::byType($armType) as $unit) {
|
foreach (GameUnitConst::byType($armType) as $unit) {
|
||||||
$crewObj = new \stdClass;
|
$crewObj = new \stdClass;
|
||||||
|
|
||||||
$crewObj->id = $unit->id;
|
$crewObj->id = $unit->id;
|
||||||
$crewObj->reqTech = $unit->reqTech;
|
/** @var ?\sammo\GameUnitConstraints\ReqTech */
|
||||||
$crewObj->reqYear = $unit->reqYear;
|
$reqTechObj = $unit->reqConstraints['ReqTech'] ?? null;
|
||||||
|
$crewObj->reqTech = $reqTechObj ? $reqTechObj->reqTech : 0;
|
||||||
|
|
||||||
/*
|
/** @var ?\sammo\GameUnitConstraint\ReqMinRelYear */
|
||||||
if ($unit->reqTech == 0) {
|
$reqMinRelYearObj = $unit->reqConstraints['reqMinRelYear'] ?? null;
|
||||||
$crewObj->bgcolor = 'green';
|
$crewObj->reqYear = $reqMinRelYearObj ? $reqMinRelYearObj->reqMinRelYear : 0;
|
||||||
} else {
|
|
||||||
$crewObj->bgcolor = 'limegreen';
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
$crewObj->notAvailable = !$unit->isValid($ownCities, $ownRegions, $relativeYear, $tech);
|
$crewObj->notAvailable = !$unit->isValid($general, $ownCities, $ownRegions, $relativeYear, $tech, $this->nation['aux']);
|
||||||
|
|
||||||
$crewObj->baseRice = $general->onCalcDomestic($this->getName(), 'rice', $unit->riceWithTech($tech), ['armType' => $unit->armType]);
|
$crewObj->baseRice = $general->onCalcDomestic($this->getName(), 'rice', $unit->riceWithTech($tech), ['armType' => $unit->armType]);
|
||||||
$crewObj->baseCost = $general->onCalcDomestic($this->getName(), 'cost', $unit->costWithTech($tech), ['armType' => $unit->armType]);
|
$crewObj->baseCost = $general->onCalcDomestic($this->getName(), 'cost', $unit->costWithTech($tech), ['armType' => $unit->armType]);
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ class che_출병 extends Command\GeneralCommand
|
|||||||
|
|
||||||
$currDist = 999;
|
$currDist = 999;
|
||||||
|
|
||||||
$minDist = Util::array_first_key($distanceList);
|
$minDist = array_key_first($distanceList);
|
||||||
do {
|
do {
|
||||||
//1: 최단 거리 도시 중 공격 대상이 있는가 확인
|
//1: 최단 거리 도시 중 공격 대상이 있는가 확인
|
||||||
//2: 최단 거리 + 1 도시 중 공격 대상이 있는가 확인
|
//2: 최단 거리 + 1 도시 중 공격 대상이 있는가 확인
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ class cr_건국 extends Command\GeneralCommand
|
|||||||
$general->addExperience($exp);
|
$general->addExperience($exp);
|
||||||
$general->addDedication($ded);
|
$general->addDedication($ded);
|
||||||
|
|
||||||
$aux = Json::decode($this->nation['aux']) ?? [];
|
$aux = $this->nation['aux'];
|
||||||
$aux['can_국기변경'] = 1;
|
$aux['can_국기변경'] = 1;
|
||||||
|
|
||||||
$db->update('city', [
|
$db->update('city', [
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ class che_국기변경 extends Command\NationCommand
|
|||||||
$josaYi = JosaUtil::pick($generalName, '이');
|
$josaYi = JosaUtil::pick($generalName, '이');
|
||||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||||
|
|
||||||
$aux = Json::decode($this->nation['aux']);
|
$aux = $this->nation['aux'];
|
||||||
$aux["can_{$actionName}"] = 0;
|
$aux["can_{$actionName}"] = 0;
|
||||||
|
|
||||||
$db->update('nation', [
|
$db->update('nation', [
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ class che_국호변경 extends Command\NationCommand
|
|||||||
$josaYi = JosaUtil::pick($generalName, '이');
|
$josaYi = JosaUtil::pick($generalName, '이');
|
||||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||||
|
|
||||||
$aux = Json::decode($this->nation['aux']);
|
$aux = $this->nation['aux'];
|
||||||
$aux["can_{$actionName}"] = 0;
|
$aux["can_{$actionName}"] = 0;
|
||||||
|
|
||||||
$db->update('nation', [
|
$db->update('nation', [
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ class che_무작위수도이전 extends Command\NationCommand
|
|||||||
$josaYi = JosaUtil::pick($generalName, '이');
|
$josaYi = JosaUtil::pick($generalName, '이');
|
||||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||||
|
|
||||||
$aux = Json::decode($this->nation['aux']);
|
$aux = $this->nation['aux'];
|
||||||
$aux["can_무작위수도이전"] -= 1;
|
$aux["can_무작위수도이전"] -= 1;
|
||||||
|
|
||||||
$db->update('city', [
|
$db->update('city', [
|
||||||
|
|||||||
@@ -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->getTurnTime(), $this->env['turnterm']) != cutTurn($destGeneral->getTurnTime(), $this->env['turnterm'])) {
|
if (cutTurn($general->getTurnTick(), $this->env['turnterm']) != cutTurn($destGeneral->getTurnTick(), $this->env['turnterm'])) {
|
||||||
$yearMonth += 1;
|
$yearMonth += 1;
|
||||||
}
|
}
|
||||||
$destGeneral->setAuxVar('last발령', $yearMonth);
|
$destGeneral->setAuxVar('last발령', $yearMonth);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ 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;
|
||||||
@@ -160,6 +161,12 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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->getTurnTime()];
|
$nationStor->last천도Trial = [$general->getVar('officer_level'), $general->getTurnTick()];
|
||||||
|
|
||||||
if ($lastTurn->getCommand() != $commandName || $lastTurn->getArg() !== $this->arg) {
|
if ($lastTurn->getCommand() != $commandName || $lastTurn->getArg() !== $this->arg) {
|
||||||
$this->setResultTurn(new LastTurn(
|
$this->setResultTurn(new LastTurn(
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ use \sammo\{
|
|||||||
Message,
|
Message,
|
||||||
CityConst,
|
CityConst,
|
||||||
CityInitialDetail,
|
CityInitialDetail,
|
||||||
|
Json,
|
||||||
StaticEventHandler
|
StaticEventHandler
|
||||||
};
|
};
|
||||||
|
|
||||||
use \sammo\Constraint\Constraint;
|
use \sammo\Constraint\Constraint;
|
||||||
use \sammo\Constraint\ConstraintHelper;
|
use \sammo\Constraint\ConstraintHelper;
|
||||||
use sammo\Enums\InheritanceKey;
|
use sammo\Enums\InheritanceKey;
|
||||||
|
use sammo\Enums\NationAuxKey;
|
||||||
use sammo\Event\Action;
|
use sammo\Event\Action;
|
||||||
|
|
||||||
class che_초토화 extends Command\NationCommand{
|
class che_초토화 extends Command\NationCommand{
|
||||||
@@ -52,7 +54,7 @@ class che_초토화 extends Command\NationCommand{
|
|||||||
$env = $this->env;
|
$env = $this->env;
|
||||||
|
|
||||||
$this->setCity();
|
$this->setCity();
|
||||||
$this->setNation(['surlimit', 'gold', 'rice', 'capital']);
|
$this->setNation(['surlimit', 'gold', 'rice', 'capital', 'aux']);
|
||||||
|
|
||||||
$this->minConditionConstraints=[
|
$this->minConditionConstraints=[
|
||||||
ConstraintHelper::OccupiedCity(),
|
ConstraintHelper::OccupiedCity(),
|
||||||
@@ -157,6 +159,11 @@ class che_초토화 extends Command\NationCommand{
|
|||||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||||
|
|
||||||
$amount = $this->calcReturnAmount($destCity);
|
$amount = $this->calcReturnAmount($destCity);
|
||||||
|
$aux = $this->nation['aux'];
|
||||||
|
|
||||||
|
if($destCity['level'] >= 8){
|
||||||
|
$aux[NationAuxKey::did_특성초토화->value] = ($aux[NationAuxKey::did_특성초토화->value] ?? 0) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
$db->update('general', [
|
$db->update('general', [
|
||||||
'experience'=>$db->sqleval('experience * 0.9')
|
'experience'=>$db->sqleval('experience * 0.9')
|
||||||
@@ -184,6 +191,7 @@ class che_초토화 extends Command\NationCommand{
|
|||||||
'gold' => $db->sqleval('gold + %i', $amount),
|
'gold' => $db->sqleval('gold + %i', $amount),
|
||||||
'rice' => $db->sqleval('rice + %i', $amount),
|
'rice' => $db->sqleval('rice + %i', $amount),
|
||||||
'surlimit' => $db->sqleval('surlimit + %i', $this->getPostReqTurn()),
|
'surlimit' => $db->sqleval('surlimit + %i', $this->getPostReqTurn()),
|
||||||
|
'aux' => Json::encode($aux),
|
||||||
], 'nation=%i', $nationID);
|
], 'nation=%i', $nationID);
|
||||||
|
|
||||||
\sammo\refreshNationStaticInfo();
|
\sammo\refreshNationStaticInfo();
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
<?php
|
||||||
|
namespace sammo\Command\Nation;
|
||||||
|
|
||||||
|
use \sammo\Command;
|
||||||
|
use sammo\Constraint\ConstraintHelper;
|
||||||
|
use sammo\DB;
|
||||||
|
use sammo\Enums\InheritanceKey;
|
||||||
|
use sammo\Enums\NationAuxKey;
|
||||||
|
use \sammo\Util;
|
||||||
|
use \sammo\JosaUtil;
|
||||||
|
use sammo\Json;
|
||||||
|
use sammo\LastTurn;
|
||||||
|
use sammo\StaticEventHandler;
|
||||||
|
use sammo\GameConst;
|
||||||
|
|
||||||
|
class event_극병연구 extends Command\NationCommand{
|
||||||
|
static protected $actionName = '극병 연구';
|
||||||
|
static protected $auxType = NationAuxKey::can_극병사용;
|
||||||
|
|
||||||
|
protected function argTest():bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function init(){
|
||||||
|
$this->setCity();
|
||||||
|
$this->setNation(['gold','rice','aux']);
|
||||||
|
$this->fullConditionConstraints=[];
|
||||||
|
|
||||||
|
$name = static::$actionName;
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
|
||||||
|
$this->minConditionConstraints = [
|
||||||
|
ConstraintHelper::OccupiedCity(),
|
||||||
|
ConstraintHelper::BeChief(),
|
||||||
|
ConstraintHelper::ReqNationAuxValue(static::$auxType->value, 0, "<", 1, "{$name}가 이미 완료되었습니다."),
|
||||||
|
ConstraintHelper::ReqNationGold(GameConst::$basegold + $reqGold),
|
||||||
|
ConstraintHelper::ReqNationRice(GameConst::$baserice + $reqRice),
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->fullConditionConstraints = $this->minConditionConstraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommandDetailTitle():string{
|
||||||
|
$name = $this->getName();
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$reqTurn = $this->getPreReqTurn()+1;
|
||||||
|
|
||||||
|
$reqGoldD5 = number_format($reqGold / 10000);
|
||||||
|
$reqRiceD5 = number_format($reqRice / 10000);
|
||||||
|
|
||||||
|
return "{$name}/{$reqTurn}턴(금/쌀 {$reqGoldD5}만)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPreReqTurn():int{
|
||||||
|
return 23;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPostReqTurn():int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCost():array{
|
||||||
|
return [100000, 100000];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(\Sammo\RandUtil $rng):bool{
|
||||||
|
if(!$this->hasFullConditionMet()){
|
||||||
|
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
$general = $this->generalObj;
|
||||||
|
$nationID = $general->getNationID();
|
||||||
|
|
||||||
|
$actionName = static::$actionName;
|
||||||
|
|
||||||
|
$aux = $this->nation['aux'];
|
||||||
|
$aux[static::$auxType->value] = 1;
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
|
||||||
|
$logger = $general->getLogger();
|
||||||
|
|
||||||
|
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
|
||||||
|
$generalName = $general->getName();
|
||||||
|
$josaYi = JosaUtil::pick($generalName, '이');
|
||||||
|
|
||||||
|
$db->update('nation', [
|
||||||
|
'gold' => $db->sqleval('gold - %i', $reqGold),
|
||||||
|
'rice' => $db->sqleval('rice - %i', $reqRice),
|
||||||
|
'aux' => Json::encode($aux),
|
||||||
|
], 'nation=%i', $nationID);
|
||||||
|
|
||||||
|
$logger->pushGeneralActionLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushGeneralHistoryLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <M>{$actionName}</> 완료");
|
||||||
|
|
||||||
|
$general->increaseInheritancePoint(InheritanceKey::active_action, 1);
|
||||||
|
StaticEventHandler::handleEvent($this->generalObj, $this->destGeneralObj, $this::class, $this->env, $this->arg ?? []);
|
||||||
|
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||||
|
$general->applyDB($db);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
namespace sammo\Command\Nation;
|
||||||
|
|
||||||
|
use \sammo\Command;
|
||||||
|
use sammo\Constraint\ConstraintHelper;
|
||||||
|
use sammo\DB;
|
||||||
|
use sammo\Enums\InheritanceKey;
|
||||||
|
use sammo\Enums\NationAuxKey;
|
||||||
|
use \sammo\Util;
|
||||||
|
use \sammo\JosaUtil;
|
||||||
|
use sammo\Json;
|
||||||
|
use sammo\LastTurn;
|
||||||
|
use sammo\StaticEventHandler;
|
||||||
|
use sammo\GameConst;
|
||||||
|
|
||||||
|
class event_대검병연구 extends Command\NationCommand{
|
||||||
|
static protected $actionName = '대검병 연구';
|
||||||
|
static protected $auxType = NationAuxKey::can_대검병사용;
|
||||||
|
|
||||||
|
protected function argTest():bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function init(){
|
||||||
|
$this->setCity();
|
||||||
|
$this->setNation(['gold','rice','aux']);
|
||||||
|
$this->fullConditionConstraints=[];
|
||||||
|
|
||||||
|
$name = static::$actionName;
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$this->minConditionConstraints = [
|
||||||
|
ConstraintHelper::OccupiedCity(),
|
||||||
|
ConstraintHelper::BeChief(),
|
||||||
|
ConstraintHelper::ReqNationAuxValue(static::$auxType->value, 0, "<", 1, "{$name}가 이미 완료되었습니다."),
|
||||||
|
ConstraintHelper::ReqNationGold(GameConst::$basegold + $reqGold),
|
||||||
|
ConstraintHelper::ReqNationRice(GameConst::$baserice + $reqRice),
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->fullConditionConstraints = $this->minConditionConstraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommandDetailTitle():string{
|
||||||
|
$name = $this->getName();
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$reqTurn = $this->getPreReqTurn()+1;
|
||||||
|
|
||||||
|
$reqGoldD5 = number_format($reqGold / 10000);
|
||||||
|
$reqRiceD5 = number_format($reqRice / 10000);
|
||||||
|
|
||||||
|
return "{$name}/{$reqTurn}턴(금/쌀 {$reqGoldD5}만)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPreReqTurn():int{
|
||||||
|
return 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPostReqTurn():int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCost():array{
|
||||||
|
return [50000, 50000];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(\Sammo\RandUtil $rng):bool{
|
||||||
|
if(!$this->hasFullConditionMet()){
|
||||||
|
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
$general = $this->generalObj;
|
||||||
|
$nationID = $general->getNationID();
|
||||||
|
|
||||||
|
$actionName = static::$actionName;
|
||||||
|
|
||||||
|
$aux = $this->nation['aux'];
|
||||||
|
$aux[static::$auxType->value] = 1;
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
|
||||||
|
$logger = $general->getLogger();
|
||||||
|
|
||||||
|
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
|
||||||
|
$generalName = $general->getName();
|
||||||
|
$josaYi = JosaUtil::pick($generalName, '이');
|
||||||
|
|
||||||
|
$db->update('nation', [
|
||||||
|
'gold' => $db->sqleval('gold - %i', $reqGold),
|
||||||
|
'rice' => $db->sqleval('rice - %i', $reqRice),
|
||||||
|
'aux' => Json::encode($aux),
|
||||||
|
], 'nation=%i', $nationID);
|
||||||
|
|
||||||
|
$logger->pushGeneralActionLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushGeneralHistoryLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <M>{$actionName}</> 완료");
|
||||||
|
|
||||||
|
$general->increaseInheritancePoint(InheritanceKey::active_action, 1);
|
||||||
|
StaticEventHandler::handleEvent($this->generalObj, $this->destGeneralObj, $this::class, $this->env, $this->arg ?? []);
|
||||||
|
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||||
|
$general->applyDB($db);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
namespace sammo\Command\Nation;
|
||||||
|
|
||||||
|
use \sammo\Command;
|
||||||
|
use sammo\Constraint\ConstraintHelper;
|
||||||
|
use sammo\DB;
|
||||||
|
use sammo\Enums\InheritanceKey;
|
||||||
|
use sammo\Enums\NationAuxKey;
|
||||||
|
use \sammo\Util;
|
||||||
|
use \sammo\JosaUtil;
|
||||||
|
use sammo\Json;
|
||||||
|
use sammo\LastTurn;
|
||||||
|
use sammo\StaticEventHandler;
|
||||||
|
use sammo\GameConst;
|
||||||
|
|
||||||
|
class event_무희연구 extends Command\NationCommand{
|
||||||
|
static protected $actionName = '무희 연구';
|
||||||
|
static protected $auxType = NationAuxKey::can_무희사용;
|
||||||
|
|
||||||
|
protected function argTest():bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function init(){
|
||||||
|
$this->setCity();
|
||||||
|
$this->setNation(['gold','rice','aux']);
|
||||||
|
$this->fullConditionConstraints=[];
|
||||||
|
|
||||||
|
$name = static::$actionName;
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$this->minConditionConstraints = [
|
||||||
|
ConstraintHelper::OccupiedCity(),
|
||||||
|
ConstraintHelper::BeChief(),
|
||||||
|
ConstraintHelper::ReqNationAuxValue(static::$auxType->value, 0, "<", 1, "{$name}가 이미 완료되었습니다."),
|
||||||
|
ConstraintHelper::ReqNationGold(GameConst::$basegold + $reqGold),
|
||||||
|
ConstraintHelper::ReqNationRice(GameConst::$baserice + $reqRice),
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->fullConditionConstraints = $this->minConditionConstraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommandDetailTitle():string{
|
||||||
|
$name = $this->getName();
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$reqTurn = $this->getPreReqTurn()+1;
|
||||||
|
|
||||||
|
$reqGoldD5 = number_format($reqGold / 10000);
|
||||||
|
$reqRiceD5 = number_format($reqRice / 10000);
|
||||||
|
|
||||||
|
return "{$name}/{$reqTurn}턴(금/쌀 {$reqGoldD5}만)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPreReqTurn():int{
|
||||||
|
return 23;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPostReqTurn():int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCost():array{
|
||||||
|
return [100000, 100000];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(\Sammo\RandUtil $rng):bool{
|
||||||
|
if(!$this->hasFullConditionMet()){
|
||||||
|
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
$general = $this->generalObj;
|
||||||
|
$nationID = $general->getNationID();
|
||||||
|
|
||||||
|
$actionName = static::$actionName;
|
||||||
|
|
||||||
|
$aux = $this->nation['aux'];
|
||||||
|
$aux[static::$auxType->value] = 1;
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
|
||||||
|
$logger = $general->getLogger();
|
||||||
|
|
||||||
|
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
|
||||||
|
$generalName = $general->getName();
|
||||||
|
$josaYi = JosaUtil::pick($generalName, '이');
|
||||||
|
|
||||||
|
$db->update('nation', [
|
||||||
|
'gold' => $db->sqleval('gold - %i', $reqGold),
|
||||||
|
'rice' => $db->sqleval('rice - %i', $reqRice),
|
||||||
|
'aux' => Json::encode($aux),
|
||||||
|
], 'nation=%i', $nationID);
|
||||||
|
|
||||||
|
$logger->pushGeneralActionLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushGeneralHistoryLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <M>{$actionName}</> 완료");
|
||||||
|
|
||||||
|
$general->increaseInheritancePoint(InheritanceKey::active_action, 1);
|
||||||
|
StaticEventHandler::handleEvent($this->generalObj, $this->destGeneralObj, $this::class, $this->env, $this->arg ?? []);
|
||||||
|
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||||
|
$general->applyDB($db);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
namespace sammo\Command\Nation;
|
||||||
|
|
||||||
|
use \sammo\Command;
|
||||||
|
use sammo\Constraint\ConstraintHelper;
|
||||||
|
use sammo\DB;
|
||||||
|
use sammo\Enums\InheritanceKey;
|
||||||
|
use sammo\Enums\NationAuxKey;
|
||||||
|
use \sammo\Util;
|
||||||
|
use \sammo\JosaUtil;
|
||||||
|
use sammo\Json;
|
||||||
|
use sammo\LastTurn;
|
||||||
|
use sammo\StaticEventHandler;
|
||||||
|
use sammo\GameConst;
|
||||||
|
|
||||||
|
class event_산저병연구 extends Command\NationCommand{
|
||||||
|
static protected $actionName = '산저병 연구';
|
||||||
|
static protected $auxType = NationAuxKey::can_산저병사용;
|
||||||
|
|
||||||
|
protected function argTest():bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function init(){
|
||||||
|
$this->setCity();
|
||||||
|
$this->setNation(['gold','rice','aux']);
|
||||||
|
$this->fullConditionConstraints=[];
|
||||||
|
|
||||||
|
$name = static::$actionName;
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$this->minConditionConstraints = [
|
||||||
|
ConstraintHelper::OccupiedCity(),
|
||||||
|
ConstraintHelper::BeChief(),
|
||||||
|
ConstraintHelper::ReqNationAuxValue(static::$auxType->value, 0, "<", 1, "{$name}가 이미 완료되었습니다."),
|
||||||
|
ConstraintHelper::ReqNationGold(GameConst::$basegold + $reqGold),
|
||||||
|
ConstraintHelper::ReqNationRice(GameConst::$baserice + $reqRice),
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->fullConditionConstraints = $this->minConditionConstraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommandDetailTitle():string{
|
||||||
|
$name = $this->getName();
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$reqTurn = $this->getPreReqTurn()+1;
|
||||||
|
|
||||||
|
$reqGoldD5 = number_format($reqGold / 10000);
|
||||||
|
$reqRiceD5 = number_format($reqRice / 10000);
|
||||||
|
|
||||||
|
return "{$name}/{$reqTurn}턴(금/쌀 {$reqGoldD5}만)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPreReqTurn():int{
|
||||||
|
return 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPostReqTurn():int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCost():array{
|
||||||
|
return [50000, 50000];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(\Sammo\RandUtil $rng):bool{
|
||||||
|
if(!$this->hasFullConditionMet()){
|
||||||
|
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
$general = $this->generalObj;
|
||||||
|
$nationID = $general->getNationID();
|
||||||
|
|
||||||
|
$actionName = static::$actionName;
|
||||||
|
|
||||||
|
$aux = $this->nation['aux'];
|
||||||
|
$aux[static::$auxType->value] = 1;
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
|
||||||
|
$logger = $general->getLogger();
|
||||||
|
|
||||||
|
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
|
||||||
|
$generalName = $general->getName();
|
||||||
|
$josaYi = JosaUtil::pick($generalName, '이');
|
||||||
|
|
||||||
|
$db->update('nation', [
|
||||||
|
'gold' => $db->sqleval('gold - %i', $reqGold),
|
||||||
|
'rice' => $db->sqleval('rice - %i', $reqRice),
|
||||||
|
'aux' => Json::encode($aux),
|
||||||
|
], 'nation=%i', $nationID);
|
||||||
|
|
||||||
|
$logger->pushGeneralActionLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushGeneralHistoryLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <M>{$actionName}</> 완료");
|
||||||
|
|
||||||
|
$general->increaseInheritancePoint(InheritanceKey::active_action, 1);
|
||||||
|
StaticEventHandler::handleEvent($this->generalObj, $this->destGeneralObj, $this::class, $this->env, $this->arg ?? []);
|
||||||
|
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||||
|
$general->applyDB($db);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
namespace sammo\Command\Nation;
|
||||||
|
|
||||||
|
use \sammo\Command;
|
||||||
|
use sammo\Constraint\ConstraintHelper;
|
||||||
|
use sammo\DB;
|
||||||
|
use sammo\Enums\InheritanceKey;
|
||||||
|
use sammo\Enums\NationAuxKey;
|
||||||
|
use \sammo\Util;
|
||||||
|
use \sammo\JosaUtil;
|
||||||
|
use sammo\Json;
|
||||||
|
use sammo\LastTurn;
|
||||||
|
use sammo\StaticEventHandler;
|
||||||
|
use sammo\GameConst;
|
||||||
|
|
||||||
|
class event_상병연구 extends Command\NationCommand{
|
||||||
|
static protected $actionName = '상병 연구';
|
||||||
|
static protected $auxType = NationAuxKey::can_상병사용;
|
||||||
|
|
||||||
|
protected function argTest():bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function init(){
|
||||||
|
$this->setCity();
|
||||||
|
$this->setNation(['gold','rice','aux']);
|
||||||
|
$this->fullConditionConstraints=[];
|
||||||
|
|
||||||
|
$name = static::$actionName;
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$this->minConditionConstraints = [
|
||||||
|
ConstraintHelper::OccupiedCity(),
|
||||||
|
ConstraintHelper::BeChief(),
|
||||||
|
ConstraintHelper::ReqNationAuxValue(static::$auxType->value, 0, "<", 1, "{$name}가 이미 완료되었습니다."),
|
||||||
|
ConstraintHelper::ReqNationGold(GameConst::$basegold + $reqGold),
|
||||||
|
ConstraintHelper::ReqNationRice(GameConst::$baserice + $reqRice),
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->fullConditionConstraints = $this->minConditionConstraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommandDetailTitle():string{
|
||||||
|
$name = $this->getName();
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$reqTurn = $this->getPreReqTurn()+1;
|
||||||
|
|
||||||
|
$reqGoldD5 = number_format($reqGold / 10000);
|
||||||
|
$reqRiceD5 = number_format($reqRice / 10000);
|
||||||
|
|
||||||
|
return "{$name}/{$reqTurn}턴(금/쌀 {$reqGoldD5}만)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPreReqTurn():int{
|
||||||
|
return 23;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPostReqTurn():int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCost():array{
|
||||||
|
return [100000, 100000];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(\Sammo\RandUtil $rng):bool{
|
||||||
|
if(!$this->hasFullConditionMet()){
|
||||||
|
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
$general = $this->generalObj;
|
||||||
|
$nationID = $general->getNationID();
|
||||||
|
|
||||||
|
$actionName = static::$actionName;
|
||||||
|
|
||||||
|
$aux = $this->nation['aux'];
|
||||||
|
$aux[static::$auxType->value] = 1;
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
|
||||||
|
$logger = $general->getLogger();
|
||||||
|
|
||||||
|
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
|
||||||
|
$generalName = $general->getName();
|
||||||
|
$josaYi = JosaUtil::pick($generalName, '이');
|
||||||
|
|
||||||
|
$db->update('nation', [
|
||||||
|
'gold' => $db->sqleval('gold - %i', $reqGold),
|
||||||
|
'rice' => $db->sqleval('rice - %i', $reqRice),
|
||||||
|
'aux' => Json::encode($aux),
|
||||||
|
], 'nation=%i', $nationID);
|
||||||
|
|
||||||
|
$logger->pushGeneralActionLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushGeneralHistoryLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <M>{$actionName}</> 완료");
|
||||||
|
|
||||||
|
$general->increaseInheritancePoint(InheritanceKey::active_action, 1);
|
||||||
|
StaticEventHandler::handleEvent($this->generalObj, $this->destGeneralObj, $this::class, $this->env, $this->arg ?? []);
|
||||||
|
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||||
|
$general->applyDB($db);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
namespace sammo\Command\Nation;
|
||||||
|
|
||||||
|
use \sammo\Command;
|
||||||
|
use sammo\Constraint\ConstraintHelper;
|
||||||
|
use sammo\DB;
|
||||||
|
use sammo\Enums\InheritanceKey;
|
||||||
|
use sammo\Enums\NationAuxKey;
|
||||||
|
use \sammo\Util;
|
||||||
|
use \sammo\JosaUtil;
|
||||||
|
use sammo\Json;
|
||||||
|
use sammo\LastTurn;
|
||||||
|
use sammo\StaticEventHandler;
|
||||||
|
use sammo\GameConst;
|
||||||
|
|
||||||
|
class event_원융노병연구 extends Command\NationCommand{
|
||||||
|
static protected $actionName = '원융노병 연구';
|
||||||
|
static protected $auxType = NationAuxKey::can_원융노병사용;
|
||||||
|
|
||||||
|
protected function argTest():bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function init(){
|
||||||
|
$this->setCity();
|
||||||
|
$this->setNation(['gold','rice','aux']);
|
||||||
|
$this->fullConditionConstraints=[];
|
||||||
|
|
||||||
|
$name = static::$actionName;
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$this->minConditionConstraints = [
|
||||||
|
ConstraintHelper::OccupiedCity(),
|
||||||
|
ConstraintHelper::BeChief(),
|
||||||
|
ConstraintHelper::ReqNationAuxValue(static::$auxType->value, 0, "<", 1, "{$name}가 이미 완료되었습니다."),
|
||||||
|
ConstraintHelper::ReqNationGold(GameConst::$basegold + $reqGold),
|
||||||
|
ConstraintHelper::ReqNationRice(GameConst::$baserice + $reqRice),
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->fullConditionConstraints = $this->minConditionConstraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommandDetailTitle():string{
|
||||||
|
$name = $this->getName();
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$reqTurn = $this->getPreReqTurn()+1;
|
||||||
|
|
||||||
|
$reqGoldD5 = number_format($reqGold / 10000);
|
||||||
|
$reqRiceD5 = number_format($reqRice / 10000);
|
||||||
|
|
||||||
|
return "{$name}/{$reqTurn}턴(금/쌀 {$reqGoldD5}만)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPreReqTurn():int{
|
||||||
|
return 23;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPostReqTurn():int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCost():array{
|
||||||
|
return [100000, 100000];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(\Sammo\RandUtil $rng):bool{
|
||||||
|
if(!$this->hasFullConditionMet()){
|
||||||
|
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
$general = $this->generalObj;
|
||||||
|
$nationID = $general->getNationID();
|
||||||
|
|
||||||
|
$actionName = static::$actionName;
|
||||||
|
|
||||||
|
$aux = $this->nation['aux'];
|
||||||
|
$aux[static::$auxType->value] = 1;
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
|
||||||
|
$logger = $general->getLogger();
|
||||||
|
|
||||||
|
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
|
||||||
|
$generalName = $general->getName();
|
||||||
|
$josaYi = JosaUtil::pick($generalName, '이');
|
||||||
|
|
||||||
|
$db->update('nation', [
|
||||||
|
'gold' => $db->sqleval('gold - %i', $reqGold),
|
||||||
|
'rice' => $db->sqleval('rice - %i', $reqRice),
|
||||||
|
'aux' => Json::encode($aux),
|
||||||
|
], 'nation=%i', $nationID);
|
||||||
|
|
||||||
|
$logger->pushGeneralActionLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushGeneralHistoryLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <M>{$actionName}</> 완료");
|
||||||
|
|
||||||
|
$general->increaseInheritancePoint(InheritanceKey::active_action, 1);
|
||||||
|
StaticEventHandler::handleEvent($this->generalObj, $this->destGeneralObj, $this::class, $this->env, $this->arg ?? []);
|
||||||
|
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||||
|
$general->applyDB($db);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
namespace sammo\Command\Nation;
|
||||||
|
|
||||||
|
use \sammo\Command;
|
||||||
|
use sammo\Constraint\ConstraintHelper;
|
||||||
|
use sammo\DB;
|
||||||
|
use sammo\Enums\InheritanceKey;
|
||||||
|
use sammo\Enums\NationAuxKey;
|
||||||
|
use \sammo\Util;
|
||||||
|
use \sammo\JosaUtil;
|
||||||
|
use sammo\Json;
|
||||||
|
use sammo\LastTurn;
|
||||||
|
use sammo\StaticEventHandler;
|
||||||
|
use sammo\GameConst;
|
||||||
|
|
||||||
|
class event_음귀병연구 extends Command\NationCommand{
|
||||||
|
static protected $actionName = '음귀병 연구';
|
||||||
|
static protected $auxType = NationAuxKey::can_음귀병사용;
|
||||||
|
|
||||||
|
protected function argTest():bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function init(){
|
||||||
|
$this->setCity();
|
||||||
|
$this->setNation(['gold','rice','aux']);
|
||||||
|
$this->fullConditionConstraints=[];
|
||||||
|
|
||||||
|
$name = static::$actionName;
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$this->minConditionConstraints = [
|
||||||
|
ConstraintHelper::OccupiedCity(),
|
||||||
|
ConstraintHelper::BeChief(),
|
||||||
|
ConstraintHelper::ReqNationAuxValue(static::$auxType->value, 0, "<", 1, "{$name}가 이미 완료되었습니다."),
|
||||||
|
ConstraintHelper::ReqNationGold(GameConst::$basegold + $reqGold),
|
||||||
|
ConstraintHelper::ReqNationRice(GameConst::$baserice + $reqRice),
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->fullConditionConstraints = $this->minConditionConstraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommandDetailTitle():string{
|
||||||
|
$name = $this->getName();
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$reqTurn = $this->getPreReqTurn()+1;
|
||||||
|
|
||||||
|
$reqGoldD5 = number_format($reqGold / 10000);
|
||||||
|
$reqRiceD5 = number_format($reqRice / 10000);
|
||||||
|
|
||||||
|
return "{$name}/{$reqTurn}턴(금/쌀 {$reqGoldD5}만)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPreReqTurn():int{
|
||||||
|
return 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPostReqTurn():int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCost():array{
|
||||||
|
return [50000, 50000];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(\Sammo\RandUtil $rng):bool{
|
||||||
|
if(!$this->hasFullConditionMet()){
|
||||||
|
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
$general = $this->generalObj;
|
||||||
|
$nationID = $general->getNationID();
|
||||||
|
|
||||||
|
$actionName = static::$actionName;
|
||||||
|
|
||||||
|
$aux = $this->nation['aux'];
|
||||||
|
$aux[static::$auxType->value] = 1;
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
|
||||||
|
$logger = $general->getLogger();
|
||||||
|
|
||||||
|
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
|
||||||
|
$generalName = $general->getName();
|
||||||
|
$josaYi = JosaUtil::pick($generalName, '이');
|
||||||
|
|
||||||
|
$db->update('nation', [
|
||||||
|
'gold' => $db->sqleval('gold - %i', $reqGold),
|
||||||
|
'rice' => $db->sqleval('rice - %i', $reqRice),
|
||||||
|
'aux' => Json::encode($aux),
|
||||||
|
], 'nation=%i', $nationID);
|
||||||
|
|
||||||
|
$logger->pushGeneralActionLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushGeneralHistoryLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <M>{$actionName}</> 완료");
|
||||||
|
|
||||||
|
$general->increaseInheritancePoint(InheritanceKey::active_action, 1);
|
||||||
|
StaticEventHandler::handleEvent($this->generalObj, $this->destGeneralObj, $this::class, $this->env, $this->arg ?? []);
|
||||||
|
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||||
|
$general->applyDB($db);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
namespace sammo\Command\Nation;
|
||||||
|
|
||||||
|
use \sammo\Command;
|
||||||
|
use sammo\Constraint\ConstraintHelper;
|
||||||
|
use sammo\DB;
|
||||||
|
use sammo\Enums\InheritanceKey;
|
||||||
|
use sammo\Enums\NationAuxKey;
|
||||||
|
use \sammo\Util;
|
||||||
|
use \sammo\JosaUtil;
|
||||||
|
use sammo\Json;
|
||||||
|
use sammo\LastTurn;
|
||||||
|
use sammo\StaticEventHandler;
|
||||||
|
use sammo\GameConst;
|
||||||
|
|
||||||
|
class event_화륜차연구 extends Command\NationCommand{
|
||||||
|
static protected $actionName = '화륜차 연구';
|
||||||
|
static protected $auxType = NationAuxKey::can_화륜차사용;
|
||||||
|
|
||||||
|
protected function argTest():bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function init(){
|
||||||
|
$this->setCity();
|
||||||
|
$this->setNation(['gold','rice','aux']);
|
||||||
|
$this->fullConditionConstraints=[];
|
||||||
|
|
||||||
|
$name = static::$actionName;
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$this->minConditionConstraints = [
|
||||||
|
ConstraintHelper::OccupiedCity(),
|
||||||
|
ConstraintHelper::BeChief(),
|
||||||
|
ConstraintHelper::ReqNationAuxValue(static::$auxType->value, 0, "<", 1, "{$name}가 이미 완료되었습니다."),
|
||||||
|
ConstraintHelper::ReqNationGold(GameConst::$basegold + $reqGold),
|
||||||
|
ConstraintHelper::ReqNationRice(GameConst::$baserice + $reqRice),
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->fullConditionConstraints = $this->minConditionConstraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommandDetailTitle():string{
|
||||||
|
$name = $this->getName();
|
||||||
|
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
$reqTurn = $this->getPreReqTurn()+1;
|
||||||
|
|
||||||
|
$reqGoldD5 = number_format($reqGold / 10000);
|
||||||
|
$reqRiceD5 = number_format($reqRice / 10000);
|
||||||
|
|
||||||
|
return "{$name}/{$reqTurn}턴(금/쌀 {$reqGoldD5}만)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPreReqTurn():int{
|
||||||
|
return 23;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPostReqTurn():int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCost():array{
|
||||||
|
return [100000, 100000];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(\Sammo\RandUtil $rng):bool{
|
||||||
|
if(!$this->hasFullConditionMet()){
|
||||||
|
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
$general = $this->generalObj;
|
||||||
|
$nationID = $general->getNationID();
|
||||||
|
|
||||||
|
$actionName = static::$actionName;
|
||||||
|
|
||||||
|
$aux = $this->nation['aux'];
|
||||||
|
$aux[static::$auxType->value] = 1;
|
||||||
|
[$reqGold, $reqRice] = $this->getCost();
|
||||||
|
|
||||||
|
$logger = $general->getLogger();
|
||||||
|
|
||||||
|
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||||
|
|
||||||
|
$generalName = $general->getName();
|
||||||
|
$josaYi = JosaUtil::pick($generalName, '이');
|
||||||
|
|
||||||
|
$db->update('nation', [
|
||||||
|
'gold' => $db->sqleval('gold - %i', $reqGold),
|
||||||
|
'rice' => $db->sqleval('rice - %i', $reqRice),
|
||||||
|
'aux' => Json::encode($aux),
|
||||||
|
], 'nation=%i', $nationID);
|
||||||
|
|
||||||
|
$logger->pushGeneralActionLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushGeneralHistoryLog("<M>{$actionName}</> 완료");
|
||||||
|
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <M>{$actionName}</> 완료");
|
||||||
|
|
||||||
|
$general->increaseInheritancePoint(InheritanceKey::active_action, 1);
|
||||||
|
StaticEventHandler::handleEvent($this->generalObj, $this->destGeneralObj, $this::class, $this->env, $this->arg ?? []);
|
||||||
|
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||||
|
$general->applyDB($db);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user