forked from devsam/core
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ca07286a4
|
||
|
|
376aed9787
|
||
|
|
246751b4dd
|
||
|
|
7f3a9d69ca
|
||
|
|
a4106f6242
|
||
|
|
f233e8241e | ||
|
|
79dedea47c
|
||
|
|
e106a6a3cf
|
||
|
|
ee3d84d7b0
|
||
|
|
b4f197b7d8
|
||
|
|
e3c89a37aa
|
||
|
|
ad0770d1be
|
||
|
|
161ed97a34
|
||
|
|
f66008da56
|
||
|
|
6b400f76cf
|
||
|
|
758ae06fd9
|
||
|
|
49429e1e7e
|
||
|
|
c9dd873019
|
||
|
|
3ae49456b1
|
||
|
|
9bf7bd0fda
|
||
|
|
a9b51977d4
|
||
|
|
50408ed516
|
||
|
|
b0cdf3ccb5
|
||
|
|
ea80b85b33
|
||
|
|
39ca3e2bb9
|
||
|
|
f8cc0c9c92
|
||
|
|
7a9ef6454c
|
||
|
|
d48c27dccb
|
||
|
|
5a565c2678
|
||
|
|
1e0875ae73
|
||
|
|
33759d24e5
|
||
|
|
033e75de5c
|
||
|
|
f2f8374fd4 | ||
|
|
e891525d56
|
||
|
|
93bc8304ce | ||
|
|
d4218f409c | ||
|
|
462de95866
|
||
|
|
dad477ed14
|
||
|
|
660258f715
|
||
|
|
9f6c7d9489
|
||
|
|
de17d87f47
|
||
|
|
f8ebcf91b1
|
||
|
|
d25d414057
|
||
|
|
96a9254bf8
|
||
|
|
96643567d4 | ||
|
|
0a6db3d21f | ||
|
|
8a4cbbb976
|
||
|
|
696ba0b341
|
||
|
|
4efcbaed6a
|
||
|
|
eda5ecb124
|
||
|
|
0ef69178a5
|
||
|
|
5596eca326
|
||
|
|
af2dec7e2c
|
||
|
|
435dae801f
|
||
|
|
320c8191dc
|
||
|
|
803e18e3c3
|
||
|
|
fbac218c34
|
||
|
|
2e6ea3a00d
|
||
|
|
1f8812c939
|
||
|
|
44c2323883
|
||
|
|
82fb532e4b
|
||
|
|
ae6ca5c1ec
|
||
|
|
30ac7da4d7
|
||
|
|
8c30634fd1
|
||
|
|
59761743dc
|
||
|
|
5952dba533
|
||
|
|
2518ac021d
|
||
|
|
e656c1e567
|
||
|
|
b89c045f85
|
||
|
|
d347054ad0
|
||
|
|
3ebc44ea5a
|
||
|
|
57c8c3f6a4
|
||
|
|
fee769714d
|
||
|
|
9fcb24533a
|
||
|
|
1061632290
|
||
|
|
7dc297a266
|
||
|
|
f019a642a2
|
||
|
|
5554ac3003
|
||
|
|
7f9ad8b7d5
|
||
|
|
82af3a2e2d | ||
|
|
7a4fcb30dc
|
||
|
|
256326f5d4
|
||
|
|
505f615203
|
||
|
|
4e504e9679
|
||
|
|
18f9d87a29
|
||
|
|
2ad0c6e509
|
||
|
|
74b9e0b4a5
|
||
|
|
486ac65767
|
||
|
|
483641bcd5
|
||
|
|
ffdacc2cfb
|
||
|
|
4eac86da58
|
||
|
|
77fc38c899
|
||
|
|
0bf49ebfb9
|
||
|
|
93f0516121
|
||
|
|
36406c8001
|
||
|
|
836adcfe3c
|
||
|
|
71a3ffa21c
|
||
|
|
38f10b5f09
|
||
|
|
da6b1fe7f1
|
||
|
|
034e6374cc
|
||
|
|
9b95163f24
|
||
|
|
91b7934ee3
|
||
|
|
41216893a1
|
||
|
|
3553b87748
|
||
|
|
3e5e584fce
|
||
|
|
afb53d121b
|
||
|
|
1780122936
|
||
|
|
64aa5d041f | ||
|
|
fbccfbb65e | ||
|
|
13eb0d4eae
|
||
|
|
3969c47f07
|
||
|
|
c7e0d6d2cb
|
@@ -69,3 +69,5 @@ gateway/js/*
|
||||
gateway/css/*
|
||||
|
||||
*.db-journal
|
||||
|
||||
d_log/cachegrind.*
|
||||
Vendored
+1
-1
@@ -29,5 +29,5 @@
|
||||
"josa",
|
||||
"sammo"
|
||||
],
|
||||
"editor.tabSize": 2
|
||||
"editor.tabSize": 4
|
||||
}
|
||||
@@ -30,10 +30,10 @@ require(__DIR__ . '/../vendor/autoload.php');
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe 설치</h1>
|
||||
<div class="row justify-content-md-center">
|
||||
<h1 class="row justify-content-lg-center">삼국지 모의전투 HiDCHe 설치</h1>
|
||||
<div class="row justify-content-lg-center">
|
||||
|
||||
<div class="col col-12 col-md-10 col-lg-7">
|
||||
<div class="col col-12 col-lg-10 col-lg-7">
|
||||
<div class="card" id="db_form_card" style="display:none">
|
||||
<h3 class="card-header">
|
||||
설치(DB 설정)
|
||||
|
||||
+1
-22
@@ -74,28 +74,7 @@ switch ($btn) {
|
||||
case "120분턴": $turnterm = 120; break;
|
||||
default: throw new \Exception("알 수 없는 턴 기간");
|
||||
}
|
||||
$oldunit = $admin['turnterm'] * 60;
|
||||
$unit = $turnterm * 60;
|
||||
|
||||
$unitDiff = $unit / $oldunit;
|
||||
|
||||
$servTurnTime = new \DateTimeImmutable($admin['turntime']);
|
||||
foreach ($db->query('SELECT no,turntime FROM general') as $gen) {
|
||||
$genTurnTime = new \DateTimeImmutable($gen['turntime']);
|
||||
$timeDiff = TimeUtil::DateIntervalToSeconds($genTurnTime->diff($servTurnTime));
|
||||
$timeDiff *= $unitDiff;
|
||||
$newGenTurnTime = $servTurnTime->add(TimeUtil::secondsToDateInterval($timeDiff));
|
||||
|
||||
$db->update('general', [
|
||||
'turntime'=>$newGenTurnTime->format('Y-m-d H:i:s.u')
|
||||
], 'no=%i', $gen['no']);
|
||||
}
|
||||
$turn = ($admin['year'] - $admin['startyear']) * 12 + $admin['month'] - 1;
|
||||
$starttime = $servTurnTime->sub(TimeUtil::secondsToDateInterval($turn * $unit))->format('Y-m-d H:i:s');
|
||||
$starttime = cutTurn($starttime, $turnterm, false);
|
||||
$gameStor->turnterm = $turnterm;
|
||||
$gameStor->starttime = $starttime;
|
||||
pushGlobalHistoryLog(["<R>★</>턴시간이 <C>$btn</>으로 변경됩니다."]);
|
||||
ServerTool::changeServerTerm($turnterm);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -38,13 +38,13 @@ if ($genlist) {
|
||||
}
|
||||
switch ($btn) {
|
||||
case "전체 접속허용":
|
||||
$db->update('general', [
|
||||
'con' => 0
|
||||
$db->update('general_access_log', [
|
||||
'refresh_score' => 0
|
||||
], true);
|
||||
break;
|
||||
case "전체 접속제한":
|
||||
$db->update('general', [
|
||||
'con' => 1000
|
||||
$db->update('general_access_log', [
|
||||
'refresh_score' => 1000
|
||||
], true);
|
||||
break;
|
||||
case "블럭 해제":
|
||||
@@ -186,14 +186,14 @@ switch ($btn) {
|
||||
], '`no` IN %li', $genlist);
|
||||
break;
|
||||
case "접속 허용":
|
||||
$db->update('general', [
|
||||
'con' => 0
|
||||
], '`no` IN %li', $genlist);
|
||||
$db->update('general_access_log', [
|
||||
'refresh_score' => 0
|
||||
], '`general_id` IN %li', $genlist);
|
||||
break;
|
||||
case "접속 제한":
|
||||
$db->update('general', [
|
||||
'con' => 1000
|
||||
], '`no` IN %li', $genlist);
|
||||
$db->update('general_access_log', [
|
||||
'refresh_score' => 1000
|
||||
], '`general_id` IN %li', $genlist);
|
||||
break;
|
||||
case "메세지 전달":
|
||||
$text = $msg ?? '';
|
||||
|
||||
-133
@@ -1,133 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin()->setReadOnly();
|
||||
|
||||
if ($session->userGrade < 5) {
|
||||
die(requireAdminPermissionHTML());
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
$conlimit = $gameStor->conlimit;
|
||||
|
||||
$ipGroupList = Util::arrayGroupBy(
|
||||
$db->query(
|
||||
'SELECT name,ip,lastconnect,owner,block,substring_index(ip,".",3) as ip_c from general WHERE ip!="" and npc<2'
|
||||
),
|
||||
'ip_c'
|
||||
);
|
||||
|
||||
function colorBlockedName($general)
|
||||
{
|
||||
if (!$general['blocked']) {
|
||||
return $general['name'];
|
||||
}
|
||||
return "<span style='color:magenta;'>{$general['name']}</span>";
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>멀티관리</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="color-scheme" content="dark">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=1024" />
|
||||
<?= WebUtil::printCSS('../d_shared/common.css') ?>
|
||||
<?= WebUtil::printDist('ts', 'common', true) ?>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr>
|
||||
<td>멀 티 관 리<br><?= backButton() ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
<form name=form1 method=post action=_admin4_submit.php>
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr>
|
||||
<td width=80 align=center rowspan=3>회원선택<br><br>
|
||||
<font color=cyan>NPC</font><br>
|
||||
<font color=skyblue>NPC유저</font><br>
|
||||
<font color=red>접속제한</font><br><b style=background-color:red;>블럭회원</b>
|
||||
</td>
|
||||
<td width=105 rowspan=3>
|
||||
<?php
|
||||
|
||||
echo "
|
||||
<select name=genlist[] size=20 multiple style='color:white;background-color:black;font-size:14px'>";
|
||||
|
||||
foreach ($db->query('SELECT no,name,npc,block,con from general where ip!=\'\' order by npc,ip') as $general) {
|
||||
$style = "style=;";
|
||||
if ($general['block'] > 0) {
|
||||
$style .= "background-color:red;";
|
||||
}
|
||||
|
||||
$npcColor = getNPCColor($general['npc']);
|
||||
if($npcColor !== null){
|
||||
$style .= "color:{$npcColor};";
|
||||
}
|
||||
|
||||
echo "
|
||||
<option value={$general['no']} $style>{$general['name']}</option>";
|
||||
}
|
||||
|
||||
echo "
|
||||
</select>";
|
||||
?>
|
||||
</td>
|
||||
<td width=100 align=center>블럭</td>
|
||||
<td width=504>
|
||||
<input type=submit name=btn value='블럭 해제'><input type=submit name=btn value='1단계 블럭'><input type=submit name=btn value='2단계 블럭'><input type=submit name=btn value='3단계 블럭'><input type=submit name=btn value='무한삭턴'><br>
|
||||
1단계:발언권, 2단계:턴블럭
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=center>강제 사망</td>
|
||||
<td><input type=submit name=btn value='강제 사망'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=center>메세지 전달</td>
|
||||
<td><input type=textarea size=60 maxlength=255 name=msg style=background-color:black;color:white;><input type=submit name=btn value='메세지 전달'></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr>
|
||||
<td align=center width=100>장수명</td>
|
||||
<td align=center width=180>최근로그인</td>
|
||||
<td align=center width=129>IP</td>
|
||||
<td align=center width=100>ID</td>
|
||||
</tr>
|
||||
<?php foreach ($ipGroupList as $ipGroupC => $users) : ?>
|
||||
<tr>
|
||||
<td><?= join('<br>', array_map('\sammo\colorBlockedName', $users)) ?></td>
|
||||
<td><?= join('<br>', array_column($users, 'lastconnect')) ?></td>
|
||||
<td><?= join('<br>', array_column($users, 'ip')) ?></td>
|
||||
<td><?= join('<br>', array_column($users, 'owner')) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
<?php
|
||||
//NOTE: password의 md5 해시가 같은지 확인하는 방식으로는 앞으로 잡아낼 수 없다. 폐기
|
||||
?>
|
||||
</form>
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr>
|
||||
<td><?= backButton() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?= banner() ?> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,86 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
use sammo\Enums\MessageType;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin()->setReadOnly();
|
||||
|
||||
if ($session->userGrade < 5) {
|
||||
header('location:_admin4.php');
|
||||
die();
|
||||
}
|
||||
|
||||
$btn = Util::getPost('btn');
|
||||
$genlist = Util::getPost('genlist', 'array_int');
|
||||
$msg = Util::getPost('msg', 'string', '메시지');
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
//NOTE: 왜 기능이 admin2와 admin4가 같이 있는가?
|
||||
//NOTE: 왜 블럭 시 admin4에선 금쌀을 없애지 않는가?
|
||||
switch ($btn) {
|
||||
case "블럭 해제":
|
||||
DB::db()->query('update general set block=0 where no IN %li', $genlist);
|
||||
break;
|
||||
case "1단계 블럭":
|
||||
$date = TimeUtil::now();
|
||||
$db = DB::db();
|
||||
$db->query('update general set block=1,killturn=24 where no IN %li', $genlist);
|
||||
//FIXME: subquery로 하는게 더 빠를 듯.
|
||||
$uid = $db->queryFirstColumn('select owner from general where no IN %li', $genlist);
|
||||
RootDB::db()->query('update member set block_num=block_num+1,block_date=%s where id IN %ls', $date, $uid);
|
||||
break;
|
||||
case "2단계 블럭":
|
||||
$date = TimeUtil::now();
|
||||
$db = DB::db();
|
||||
$db->query('update general set block=2,killturn=24 where no IN %li', $genlist);
|
||||
$uid = $db->queryFirstColumn('select owner from general where no IN %li', $genlist);
|
||||
RootDB::db()->query('update member set block_num=block_num+1,block_date=%s where id IN %ls', $date, $uid);
|
||||
break;
|
||||
case "3단계 블럭":
|
||||
$date = TimeUtil::now();
|
||||
$db = DB::db();
|
||||
$db->query('update general set block=3,killturn=24 where no IN %li', $genlist);
|
||||
$uid = $db->queryFirstColumn('select owner from general where no IN %li', $genlist);
|
||||
RootDB::db()->query('update member set block_num=block_num+1,block_date=%s where id IN %ls', $date, $uid);
|
||||
break;
|
||||
case "무한삭턴":
|
||||
DB::db()->query('update general set killturn=8000 where no IN %li', $genlist);
|
||||
break;
|
||||
case "강제 사망":
|
||||
$date = TimeUtil::now(true);
|
||||
$db->update('general', [
|
||||
'killturn' => 0,
|
||||
'turntime' => $date,
|
||||
], '`no` IN %li', $genlist);
|
||||
$db->update('general_turn', [
|
||||
'action' => '휴식',
|
||||
'arg' => '{}',
|
||||
'brief' => '휴식'
|
||||
], 'general_id IN %li AND turn_idx = 0', $genlist);
|
||||
break;
|
||||
case "메세지 전달":
|
||||
$date = TimeUtil::now();
|
||||
$src = MessageTarget::buildQuick($session->generalID);
|
||||
foreach($genlist as $generalID){
|
||||
$msgObj = new Message(
|
||||
MessageType::private,
|
||||
$src,
|
||||
MessageTarget::buildQuick($generalID),
|
||||
$msg,
|
||||
new \DateTime(),
|
||||
new \DateTime('9999-12-31'),
|
||||
[]
|
||||
);
|
||||
if ($msgObj) {
|
||||
$msgObj->send(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
header('location:_admin4.php');
|
||||
@@ -66,8 +66,6 @@ $sel2[$type2] = "selected";
|
||||
<option <?= $sel[8] ?? '' ?> value=8>평무</option>
|
||||
<option <?= $sel[9] ?? '' ?> value=9>평지</option>
|
||||
<option <?= $sel[10] ?? '' ?> value=10>평Lv</option>
|
||||
<option <?= $sel[11] ?? '' ?> value=11>접속률</option>
|
||||
<option <?= $sel[12] ?? '' ?> value=12>단기접</option>
|
||||
<option <?= $sel[13] ?? '' ?> value=13>보숙</option>
|
||||
<option <?= $sel[14] ?? '' ?> value=14>궁숙</option>
|
||||
<option <?= $sel[15] ?? '' ?> value=15>기숙</option>
|
||||
@@ -105,8 +103,6 @@ $sel2[$type2] = "selected";
|
||||
<table align=center width=1600 class="tb_layout bg0">
|
||||
<tr class='bg1'>
|
||||
<td align=center>국명</td>
|
||||
<td align=center>접률</td>
|
||||
<td align=center>단접</td>
|
||||
<td align=center>국력</td>
|
||||
<td align=center>장수</td>
|
||||
<td align=center>속령</td>
|
||||
@@ -147,8 +143,6 @@ SELECT
|
||||
A.gold,
|
||||
A.rice,
|
||||
COUNT(B.nation) AS gennum,
|
||||
ROUND(AVG(B.connect), 1) AS connect,
|
||||
ROUND(AVG(B.con), 1) AS con,
|
||||
ROUND(AVG(B.dex1)) AS dex1,
|
||||
ROUND(AVG(B.dex2)) AS dex2,
|
||||
ROUND(AVG(B.dex3)) AS dex3,
|
||||
@@ -193,12 +187,6 @@ GROUP BY B.nation
|
||||
case 10:
|
||||
$query .= " order by avg(B.explevel) desc";
|
||||
break;
|
||||
case 11:
|
||||
$query .= " order by avg(B.connect) desc";
|
||||
break;
|
||||
case 12:
|
||||
$query .= " order by avg(B.con) desc";
|
||||
break;
|
||||
case 13:
|
||||
$query .= " order by avg(B.dex1) desc";
|
||||
break;
|
||||
@@ -240,8 +228,6 @@ from city where nation=%i', $nation['nation']);
|
||||
echo "
|
||||
<tr>
|
||||
<td align=center style=background-color:{$nation['color']};color:" . newColor($nation['color']) . ";>{$nation['name']}</td>
|
||||
<td align=center> {$nation['connect']} </td>
|
||||
<td align=center> {$nation['con']} </td>
|
||||
<td align=center> {$nation['power']} </td>
|
||||
<td align=center> {$gen['cnt']} </td>
|
||||
<td align=center> {$city['cnt']} </td>
|
||||
|
||||
+3
-1
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace sammo;
|
||||
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
@@ -74,7 +76,7 @@ if (!$gen) {
|
||||
$gen = $generalBasicList[0]['no'];
|
||||
}
|
||||
|
||||
$generalObj = General::createGeneralObjFromDB($gen);
|
||||
$generalObj = General::createGeneralObjFromDB($gen, null, GeneralQueryMode::FullWithAccessLog);
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
|
||||
+16
-8
@@ -16,10 +16,13 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
increaseRefresh("장수일람", 2);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT con,turntime FROM general WHERE owner = %i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT refresh_score,turntime FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner = %i', $userID
|
||||
);
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
printLimitMsg($me['turntime']);
|
||||
exit();
|
||||
}
|
||||
@@ -102,7 +105,7 @@ if ($gameStor->isunited) {
|
||||
6 => ['dedication', true],
|
||||
7 => ['officer_level', true],
|
||||
8 => ['killturn', false],
|
||||
9 => ['connect', true],
|
||||
9 => ['refresh_score_total', true],
|
||||
10 => ['experience', true],
|
||||
11 => ['personal', true],
|
||||
12 => ['special', true],
|
||||
@@ -111,7 +114,12 @@ if ($gameStor->isunited) {
|
||||
15 => ['npc', true],
|
||||
][$type];
|
||||
|
||||
$generalList = $db->query('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general order by %b %l', $orderKey, $orderDesc ? 'desc' : '');
|
||||
$generalList = $db->query(
|
||||
'SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,refresh_score_total
|
||||
FROM `general` LEFT JOIN `general_access_log` ON general.no = general_access_log.general_id order by %b %l',
|
||||
$orderKey,
|
||||
$orderDesc ? 'desc' : ''
|
||||
);
|
||||
|
||||
echo "
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
@@ -163,7 +171,7 @@ if ($gameStor->isunited) {
|
||||
$name = $name . '<br><small>(' . $ownerNameList[$general['owner']] . ')</small>';
|
||||
}
|
||||
|
||||
$general['connect'] = Util::round($general['connect'], -1);
|
||||
$general['refresh_score_total'] = Util::round($general['refresh_score_total'], -1);
|
||||
|
||||
$imageTemp = GetImageURL($general['imgsvr']);
|
||||
echo "
|
||||
@@ -192,8 +200,8 @@ if ($gameStor->isunited) {
|
||||
<td align=center>$strength</td>
|
||||
<td align=center>$intel</td>
|
||||
<td align=center>{$general['killturn']}</td>
|
||||
<td align=center>{$general['connect']}";
|
||||
echo "<br>【" . getConnect($general['connect']) . "】</td>
|
||||
<td align=center>" . $general['refresh_score_total'] ?? 0;
|
||||
echo "<br>【" . getRefreshScoreText($general['refresh_score_total'] ?? 0) . "】</td>
|
||||
</tr>";
|
||||
}
|
||||
echo "
|
||||
|
||||
@@ -13,10 +13,13 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$gameStor->cacheValues(['killturn', 'autorun_user', 'turnterm']);
|
||||
increaseRefresh("세력일람", 2);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT refresh_score, turntime FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
printLimitMsg($me['turntime']);
|
||||
exit();
|
||||
}
|
||||
|
||||
+15
-8
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace sammo;
|
||||
|
||||
use sammo\Enums\GeneralAccessLogColumn;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
@@ -23,10 +25,10 @@ $online = [];
|
||||
$curonline = getOnlineNum();
|
||||
foreach ($log as $i => $value) {
|
||||
$parse = Json::decode($value);
|
||||
if(is_array($parse) === false){
|
||||
if (is_array($parse) === false) {
|
||||
continue;
|
||||
}
|
||||
if(count($parse) < 5){
|
||||
if (count($parse) < 5) {
|
||||
continue;
|
||||
}
|
||||
$date[$i] = $parse[0];
|
||||
@@ -193,19 +195,24 @@ if ($admin['maxonline'] < $curonline) {
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
$max_refresh = $db->queryFirstRow('SELECT sum(refresh) as refresh, sum(`connect`) as `connect` from general');
|
||||
$max_refresh['name'] = '접속자 총합';
|
||||
$totalRefresh = [
|
||||
...$db->queryFirstRow('SELECT sum(`refresh`) as `refresh`, sum(`refresh_score_total`) as `refresh_score_total` from general_access_log'),
|
||||
'name' => '접속자 총합'
|
||||
];
|
||||
|
||||
$refresh_result = array_merge([$max_refresh], $db->query('SELECT `name`,refresh,`connect` FROM general ORDER BY refresh DESC LIMIT 5'));
|
||||
$top5Refresh = $db->query(
|
||||
'SELECT `name`, `log`.`refresh`, `refresh_score_total` FROM `general_access_log` AS `log`
|
||||
INNER JOIN `general` ON `log`.`general_id` = `general`.`no` ORDER BY `log`.`refresh` DESC LIMIT 5'
|
||||
);
|
||||
|
||||
foreach ($refresh_result as $i => $user) {
|
||||
$w = round($user['refresh'] / max(1, $max_refresh['refresh']) * 100, 1);
|
||||
foreach (array_merge([$totalRefresh], $top5Refresh) as $i => $user) {
|
||||
$w = round($user['refresh'] / max(1, $totalRefresh['refresh']) * 100, 1);
|
||||
$w2 = round(100 - $w, 1);
|
||||
$color = getTrafficColor($w);
|
||||
?>
|
||||
<tr>
|
||||
<td width=98 align=center><?= $user['name'] ?></td>
|
||||
<td width=98 align=center><?= $user['connect'] ?>(<?= $user['refresh'] ?>)</td>
|
||||
<td width=98 align=center><?= $user['refresh_score_total'] ?>(<?= $user['refresh'] ?>)</td>
|
||||
<td width=798>
|
||||
<?php if ($w == 0) : ?>
|
||||
<?php elseif ($w < 10) : ?>
|
||||
|
||||
+9
-5
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace sammo;
|
||||
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Enums\RankColumn;
|
||||
|
||||
include "lib.php";
|
||||
@@ -21,12 +22,15 @@ $generalID = $session->generalID;
|
||||
|
||||
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no,tournament,con,turntime from general where owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no,tournament,refresh_score,turntime FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id where owner=%i', $userID
|
||||
);
|
||||
|
||||
$admin = $gameStor->getValues(['tournament', 'phase', 'tnmt_type', 'turnterm', 'develcost']);
|
||||
$turnTerm = $admin['turnterm'];
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
printLimitMsg($me['turntime']);
|
||||
exit();
|
||||
}
|
||||
@@ -107,7 +111,7 @@ if ($str3) {
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<?php if ($con == 1) {
|
||||
<?php if ($limitState == 1) {
|
||||
MessageBox("접속제한이 얼마 남지 않았습니다!");
|
||||
} ?>
|
||||
|
||||
@@ -563,7 +567,7 @@ if ($str3) {
|
||||
$tournamentRankerList = General::createGeneralObjListFromDB(
|
||||
$db->queryFirstColumn('SELECT general_id FROM rank_data WHERE `type`= %s ORDER BY value DESC LIMIT 40', $gameColumn->value),
|
||||
[$prizeColumn->value, $gameColumn->value, $winColumn->value, $drawColumn->value, $loseColumn->value, 'leadership', 'strength', 'intel', 'no', 'npc', 'name'],
|
||||
0
|
||||
GeneralQueryMode::Core
|
||||
);
|
||||
usort($tournamentRankerList, function (General $lhs, General $rhs) use ($gameColumn, $winColumn, $drawColumn, $loseColumn) {
|
||||
$result = - ($lhs->getRankVar($gameColumn) <=> $rhs->getRankVar($gameColumn));
|
||||
|
||||
@@ -211,7 +211,7 @@ $templates = new \League\Plates\Engine('templates');
|
||||
$city['trade'] = "- ";
|
||||
}
|
||||
|
||||
$dbColumns = General::mergeQueryColumn(['npc', 'defence_train', 'no', 'picture', 'imgsvr', 'name', 'injury', 'leadership', 'strength', 'intel', 'officer_level', 'nation', 'crewtype', 'crew', 'train', 'atmos'], 2)[0];
|
||||
$dbColumns = General::mergeQueryColumn(['npc', 'defence_train', 'no', 'picture', 'imgsvr', 'name', 'injury', 'leadership', 'strength', 'intel', 'officer_level', 'nation', 'crewtype', 'crew', 'train', 'atmos'])[0];
|
||||
if ($showDetailedInfo) {
|
||||
$generals = $db->query(
|
||||
'SELECT %l from general where city=%i order by turntime',
|
||||
@@ -327,7 +327,7 @@ $templates = new \League\Plates\Engine('templates');
|
||||
|
||||
if ($ourGeneral && !$isNPC) {
|
||||
$turnText = [];
|
||||
$generalObj = new General($general, null, null, null, null, null, false);
|
||||
$generalObj = new General($general, null, null, null, null, null, null, false);
|
||||
foreach ($generalTurnList[$generalObj->getID()] as $turnRawIdx => $turn) {
|
||||
$turnIdx = $turnRawIdx + 1;
|
||||
$turnText[] = "{$turnIdx} : $turn";
|
||||
|
||||
+7
-4
@@ -19,12 +19,15 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
increaseRefresh("암행부", 1);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,permission,penalty from general where owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no,nation,officer_level,refresh_score,turntime,belong,permission,penalty FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
|
||||
$nationLevel = $db->queryFirstField('SELECT level FROM nation WHERE nation=%i', $me['nation']);
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
printLimitMsg($me['turntime']);
|
||||
exit();
|
||||
}
|
||||
@@ -45,7 +48,7 @@ $templates = new \League\Plates\Engine('templates');
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<?php if ($con == 1) {
|
||||
<?php if ($limitState == 1) {
|
||||
MessageBox("접속제한이 얼마 남지 않았습니다!");
|
||||
} ?>
|
||||
|
||||
|
||||
+6
-4
@@ -97,7 +97,7 @@ if ($gameStor->isunited) {
|
||||
7 => ['gold', true],
|
||||
8 => ['rice', true],
|
||||
9 => ['crew', true],
|
||||
10 => ['connect', true],
|
||||
10 => ['refresh_score_total', true],
|
||||
11 => ['personal', true],
|
||||
12 => ['special', true],
|
||||
13 => ['special2', true],
|
||||
@@ -105,7 +105,9 @@ if ($gameStor->isunited) {
|
||||
15 => ['npc', true],
|
||||
][$type];
|
||||
|
||||
$generalList = $db->query('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect,gold,rice,crew,belong from general where nation = %i order by %b %l', $me['nation'], $orderKey, $orderDesc ? 'desc' : '');
|
||||
$generalList = $db->query(
|
||||
'SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,refresh_score_total,gold,rice,crew,belong
|
||||
FROM `general` LEFT JOIN `general_access_log` ON general.no = general_access_log.general_id where nation = %i order by %b %l', $me['nation'], $orderKey, $orderDesc ? 'desc' : '');
|
||||
|
||||
echo "
|
||||
<table align=center class='tb_layout bg0'>
|
||||
@@ -173,8 +175,8 @@ if ($gameStor->isunited) {
|
||||
<td align=center>" . displayCharInfo($general['personal']) . "</td>
|
||||
<td align=center>" . displaySpecialDomesticInfo($general['special']) . " / " . displaySpecialWarInfo($general['special2']) . "</td>
|
||||
<td align=center>{$general['belong']}</td>
|
||||
<td align=center>{$general['connect']}";
|
||||
echo "<br>(" . getConnect($general['connect']) . ")</td>
|
||||
<td align=center>". $general['refresh_score_total'] ?? 0;
|
||||
echo "<br>(" . getRefreshScoreText($general['refresh_score_total'] ?? 0) . ")</td>
|
||||
</tr>";
|
||||
}
|
||||
echo "
|
||||
|
||||
+19
-8
@@ -2,6 +2,10 @@
|
||||
|
||||
namespace sammo;
|
||||
|
||||
use sammo\Enums\GeneralAccessLogColumn;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Enums\TableName;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
@@ -20,7 +24,7 @@ $gameStor->cacheValues(['turntime', 'opentime', 'autorun_user', 'npcmode']);
|
||||
|
||||
increaseRefresh("내정보", 1);
|
||||
|
||||
$me = General::createGeneralObjFromDB($generalID);
|
||||
$me = General::createGeneralObjFromDB($generalID, null, GeneralQueryMode::FullWithAccessLog);
|
||||
|
||||
$myset = $me->getVar('myset');
|
||||
if ($myset > 0) {
|
||||
@@ -29,7 +33,14 @@ if ($myset > 0) {
|
||||
$submit = 'hidden';
|
||||
}
|
||||
|
||||
$targetTime = addTurn($me->getVar('lastrefresh'), $gameStor->turnterm, GameConst::$minTurnDieOnPrestart);
|
||||
$lastRefresh = $db->queryFirstField(
|
||||
'SELECT %b FROM %b WHERE %b = %i',
|
||||
GeneralAccessLogColumn::lastRefresh->value,
|
||||
TableName::generalAccessLog->value,
|
||||
GeneralAccessLogColumn::generalID->value, $generalID
|
||||
);
|
||||
|
||||
$targetTime = addTurn($lastRefresh, $gameStor->turnterm, GameConst::$minTurnDieOnPrestart);
|
||||
if ($gameStor->turntime <= $gameStor->opentime) {
|
||||
//서버 가오픈시 할 수 있는 행동
|
||||
if ($me->getNPCType() == 0 && $me->getNationID() == 0) {
|
||||
@@ -81,13 +92,13 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
|
||||
<div class="col">내 정 보<br><?= backButton() ?></div>
|
||||
</div>
|
||||
<div class="row gx-0">
|
||||
<div class="col col-12 col-md-6">
|
||||
<div class="col col-12 col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col"><?php generalInfo($me); ?><?php generalInfo2($me); ?></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col col-12 col-md-6">
|
||||
<div class="col col-12 col-lg-6">
|
||||
<div class="row mx-0 gx-0">
|
||||
<div class="col" style='padding-left:2ch;'>
|
||||
토너먼트 【
|
||||
@@ -178,7 +189,7 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col col-12 col-md-6">
|
||||
<div class="col col-12 col-lg-6">
|
||||
<div class="row gx-0">
|
||||
<div class="col bg1 text-center">
|
||||
<h4 style='color:skyblue'>개인 기록</h4>
|
||||
@@ -191,7 +202,7 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
|
||||
<button type="button" class="load_old_log btn btn-secondary" data-log_type="generalAction">이전 로그 불러오기</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col col-12 col-md-6">
|
||||
<div class="col col-12 col-lg-6">
|
||||
<div class="row gx-0">
|
||||
<div class="col bg1 text-center">
|
||||
<h4 style='color:orange'>전투 기록</h4>
|
||||
@@ -205,7 +216,7 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col col-12 col-md-6">
|
||||
<div class="col col-12 col-lg-6">
|
||||
<div class="row gx-0">
|
||||
<div class="col bg1 text-center">
|
||||
<h4 style='color:skyblue'>장수 열전</h4>
|
||||
@@ -215,7 +226,7 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
|
||||
<?= formatHistoryToHTML(getGeneralHistoryLogAll($generalID)) ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col col-12 col-md-6">
|
||||
<div class="col col-12 col-lg-6">
|
||||
<div class="row gx-0">
|
||||
<div class="col bg1 text-center">
|
||||
<h4 style='color:orange'>전투 결과</h4>
|
||||
|
||||
@@ -14,14 +14,16 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
increaseRefresh("토너먼트", 1);
|
||||
TurnExecutionHelper::executeAllCommand();
|
||||
|
||||
$me = $db->queryFirstRow('select no,tournament,con,turntime from general where owner=%i', $userID);
|
||||
$generalID = $session->generalID;
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no,tournament,refresh_score,turntime from `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id where owner=%i', $userID
|
||||
);
|
||||
|
||||
$admin = $gameStor->getValues(['tournament', 'phase', 'turnterm', 'tnmt_msg', 'tnmt_type', 'develcost', 'tnmt_trig']);
|
||||
$turnTerm = $admin['turnterm'];
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
printLimitMsg($me['turntime']);
|
||||
exit();
|
||||
}
|
||||
@@ -100,7 +102,7 @@ $globalBetTotal = array_sum($globalBet);
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<?php if ($con == 1) {
|
||||
<?php if ($limitState == 1) {
|
||||
MessageBox("접속제한이 얼마 남지 않았습니다! 제한량이 모자라다면 참여를 해보세요^^");
|
||||
} ?>
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
class ServerEnv extends ServerDefaultEnv {
|
||||
//ServerEnv 기본값을 변경하고 싶다면 orig를 제거한 복사본을 만들고 수정
|
||||
}
|
||||
+75
-65
@@ -5,6 +5,9 @@ namespace sammo;
|
||||
use DateTime;
|
||||
use Ds\Set;
|
||||
use sammo\Enums\AuctionType;
|
||||
use sammo\Enums\GeneralAccessLogColumn;
|
||||
use sammo\Enums\GeneralColumn;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Enums\InheritanceKey;
|
||||
use sammo\Enums\RankColumn;
|
||||
|
||||
@@ -103,10 +106,9 @@ function GetImageURL($imgsvr, $filepath = '')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|int $con 장수의 벌점
|
||||
* @param null|int $conlimit 최대 벌점
|
||||
* @param null|int $refreshScore 장수의 벌점
|
||||
*/
|
||||
function checkLimit($con = null)
|
||||
function checkLimit($refreshScore = null)
|
||||
{
|
||||
$session = Session::getInstance();
|
||||
if ($session->userGrade >= 4) {
|
||||
@@ -116,15 +118,15 @@ function checkLimit($con = null)
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
if ($con === null) {
|
||||
$con = $db->queryFirstField('SELECT con FROM general WHERE `owner`=%i', Session::getUserID());
|
||||
if ($refreshScore === null) {
|
||||
$refreshScore = $db->queryFirstField('SELECT refresh_score FROM general_access_log WHERE `general_id`=%i', Session::getGeneralID());
|
||||
}
|
||||
$conlimit = $gameStor->conlimit;
|
||||
$refreshLimit = $gameStor->refreshLimit;
|
||||
|
||||
if ($con > $conlimit) {
|
||||
if ($refreshScore > $refreshLimit) {
|
||||
return 2;
|
||||
//접속제한 90%이면 경고문구
|
||||
} elseif ($con > $conlimit * 0.9) {
|
||||
} elseif ($refreshScore > $refreshLimit * 0.9) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
@@ -642,7 +644,7 @@ function generalInfo(General $generalObj)
|
||||
$age = "<font color=red>{$age} 세</font>";
|
||||
}
|
||||
|
||||
$connectCnt = round($generalObj->getVar('connect'), -1);
|
||||
$refreshScoreTotal = round($generalObj->getAccessLogVar(GeneralAccessLogColumn::refreshScoreTotal) ?? 0, -1);
|
||||
$specialDomestic = $generalObj->getVar('special') === GameConst::$defaultSpecialDomestic
|
||||
? "{$generalObj->getVar('specage')}세"
|
||||
: "<font color=limegreen>" . displayiActionObjInfo($generalObj->getSpecialDomestic()) . "</font>";
|
||||
@@ -751,7 +753,7 @@ function generalInfo(General $generalObj)
|
||||
<td style='text-align:center;' class='bg1'><b>부대</b></td>
|
||||
<td style='text-align:center;' colspan=3>{$troopInfo}</td>
|
||||
<td style='text-align:center;' class='bg1'><b>벌점</b></td>
|
||||
<td style='text-align:center;' colspan=5>" . getConnect($connectCnt) . " {$connectCnt}({$generalObj->getVar('con')})</td>
|
||||
<td style='text-align:center;' colspan=5>" . getRefreshScoreText($refreshScoreTotal) . " {$refreshScoreTotal}({$generalObj->getAccessLogVar(GeneralAccessLogColumn::refreshScore)})</td>
|
||||
</tr>
|
||||
</table>";
|
||||
}
|
||||
@@ -998,52 +1000,69 @@ function increaseRefresh($type = "", $cnt = 1)
|
||||
$generalID = $session->generalID;
|
||||
$userGrade = $session->userGrade;
|
||||
|
||||
$date = TimeUtil::now();
|
||||
$dateObj = new \DateTimeImmutable();
|
||||
$date = TimeUtil::format($dateObj, false);
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$isunited = $gameStor->isunited;
|
||||
$opentime = $gameStor->opentime;
|
||||
|
||||
if($userGrade == 6){
|
||||
if ($userGrade == 6) {
|
||||
return;
|
||||
}
|
||||
if($isunited == 2){
|
||||
if ($isunited == 2) {
|
||||
return;
|
||||
}
|
||||
if(!$generalID){
|
||||
if (!$generalID) {
|
||||
return;
|
||||
}
|
||||
if($opentime > $date){
|
||||
if ($opentime > $date) {
|
||||
return;
|
||||
}
|
||||
|
||||
$gameStor->refresh = $gameStor->refresh + $cnt; //TODO: +로 증가하는 값은 별도로 분리
|
||||
|
||||
$db->update('general', [
|
||||
'lastrefresh' => $date,
|
||||
'con' => $db->sqleval('con + %i', $cnt),
|
||||
'connect' => $db->sqleval('connect + %i', $cnt),
|
||||
'refcnt' => $db->sqleval('refcnt + %i', $cnt),
|
||||
'refresh' => $db->sqleval('refresh + %i', $cnt)
|
||||
], 'owner=%i', $userID);
|
||||
$db->insertUpdate('general_access_log', [
|
||||
GeneralAccessLogColumn::generalID->value => $generalID,
|
||||
GeneralAccessLogColumn::userID->value => $userID,
|
||||
GeneralAccessLogColumn::lastRefresh->value => $date,
|
||||
GeneralAccessLogColumn::refreshTotal->value => $cnt,
|
||||
GeneralAccessLogColumn::refresh->value => $cnt,
|
||||
GeneralAccessLogColumn::refreshScore->value => $cnt,
|
||||
GeneralAccessLogColumn::refreshScoreTotal->value => $cnt,
|
||||
], [
|
||||
GeneralAccessLogColumn::lastRefresh->value => $date,
|
||||
GeneralAccessLogColumn::refreshTotal->value => $db->sqleval('%b + %i', GeneralAccessLogColumn::refreshTotal->value, $cnt),
|
||||
GeneralAccessLogColumn::refresh->value => $db->sqleval('%b + %i', GeneralAccessLogColumn::refresh->value, $cnt),
|
||||
GeneralAccessLogColumn::refreshScore->value => $db->sqleval('%b + %i', GeneralAccessLogColumn::refreshScore->value, $cnt),
|
||||
GeneralAccessLogColumn::refreshScoreTotal->value => $db->sqleval('%b + %i', GeneralAccessLogColumn::refreshScoreTotal->value, $cnt),
|
||||
]);
|
||||
|
||||
$date = date('Y_m_d H:i:s');
|
||||
$date2 = substr($date, 0, 10);
|
||||
$online = getOnlineNum();
|
||||
file_put_contents(
|
||||
__DIR__ . "/logs/" . UniqueConst::$serverID . "/_{$date2}_refresh.txt",
|
||||
sprintf(
|
||||
"%s, %s, %s, %s, %s, %d\n",
|
||||
$date,
|
||||
$session->userName,
|
||||
$session->generalName,
|
||||
$session->ip,
|
||||
$type,
|
||||
$online
|
||||
),
|
||||
FILE_APPEND
|
||||
);
|
||||
$serverPath = __DIR__;
|
||||
|
||||
$serverID = UniqueConst::$serverID;
|
||||
$logPath = "{$serverPath}/logs/{$serverID}/api_log.db";
|
||||
|
||||
$logDB = FileDB::db($logPath, $serverPath . '/../f_install/sql/api_log.sql');
|
||||
|
||||
$ip = $_SERVER['REMOTE_ADDR'] ?? 'local';
|
||||
$date = date('Y-m-d H:i:s');
|
||||
|
||||
$logDB->insert('api_log', [
|
||||
'user_id' => $session->userID,
|
||||
'ip' => $ip,
|
||||
'date' => $date,
|
||||
'path' => "refresh",
|
||||
'arg' => JSON::encode([
|
||||
'type' => $type,
|
||||
]),
|
||||
'aux' => JSON::encode([
|
||||
'generalID' => $generalID,
|
||||
'generalName' => $session->generalName,
|
||||
'userName' => $session->userName,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
function updateTraffic()
|
||||
@@ -1054,9 +1073,6 @@ function updateTraffic()
|
||||
$admin = $gameStor->getValues(['year', 'month', 'refresh', 'maxonline', 'maxrefresh']);
|
||||
/** @var array{year:int,month:int,refresh:int,maxonline:int,maxrefresh:int} $admin */
|
||||
|
||||
//최다갱신자
|
||||
$user = $db->queryFirstRow('select name,refresh from general order by refresh desc limit 1');
|
||||
|
||||
if ($admin['maxrefresh'] < $admin['refresh']) {
|
||||
$admin['maxrefresh'] = $admin['refresh'];
|
||||
}
|
||||
@@ -1067,22 +1083,7 @@ function updateTraffic()
|
||||
$gameStor->maxrefresh = $admin['maxrefresh'];
|
||||
$gameStor->maxonline = $admin['maxonline'];
|
||||
|
||||
$db->update('general', ['refresh' => 0], true);
|
||||
|
||||
$date = TimeUtil::now();
|
||||
//일시|년|월|총갱신|접속자|최다갱신자
|
||||
file_put_contents(
|
||||
__DIR__ . "/logs/" . UniqueConst::$serverID . "/_traffic.txt",
|
||||
Json::encode([
|
||||
$date,
|
||||
$admin['year'],
|
||||
$admin['month'],
|
||||
$admin['refresh'],
|
||||
$online,
|
||||
$user['name'] . "(" . $user['refresh'] . ")"
|
||||
]) . "\n",
|
||||
FILE_APPEND
|
||||
);
|
||||
$db->update('general_access_log', ['refresh' => 0], true);
|
||||
}
|
||||
|
||||
function CheckOverhead()
|
||||
@@ -1090,13 +1091,13 @@ function CheckOverhead()
|
||||
//서버정보
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
list($turnterm, $conlimit) = $gameStor->getValuesAsArray(['turnterm', 'conlimit']);
|
||||
[$turnterm, $refreshLimit] = $gameStor->getValuesAsArray(['turnterm', 'refreshLimit']);
|
||||
|
||||
$con = Util::round(pow($turnterm, 0.6) * 3) * 10;
|
||||
$nextRefreshLimit = Util::round(pow($turnterm, 0.6) * 3) * 10;
|
||||
|
||||
|
||||
if ($con != $conlimit) {
|
||||
$gameStor->conlimit = $con;
|
||||
if ($nextRefreshLimit != $refreshLimit) {
|
||||
$gameStor->refreshLimit = $nextRefreshLimit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1200,7 +1201,16 @@ function updateOnline()
|
||||
|
||||
//동접수
|
||||
$startTurn = cutTurn($gameStor->turntime, $gameStor->turnterm, false);
|
||||
$onlineUser = $db->query('SELECT no,name,nation FROM general WHERE lastrefresh >= %s AND npc < 2', $startTurn);
|
||||
$onlineUser = $db->query(
|
||||
'SELECT %b, %b, %b FROM `general_access_log` as `log` INNER JOIN `general` ON `log`.%b = `general`.%b WHERE %b >= %s',
|
||||
GeneralColumn::no->value,
|
||||
GeneralColumn::name->value,
|
||||
GeneralColumn::nation->value,
|
||||
GeneralAccessLogColumn::generalID->value,
|
||||
GeneralColumn::no->value,
|
||||
GeneralAccessLogColumn::lastRefresh->value,
|
||||
$startTurn
|
||||
);
|
||||
$onlineNum = count($onlineUser);
|
||||
$onlineNationUsers = Util::arrayGroupBy($onlineUser, 'nation');
|
||||
|
||||
@@ -1314,7 +1324,7 @@ function CheckHall($no)
|
||||
["betrate", 'calc'],
|
||||
];
|
||||
|
||||
$generalObj = General::createGeneralObjFromDB($no, null, 2);
|
||||
$generalObj = General::createGeneralObjFromDB($no);
|
||||
|
||||
$ttw = $generalObj->getRankVar(RankColumn::ttw);
|
||||
$ttd = $generalObj->getRankVar(RankColumn::ttd);
|
||||
@@ -1711,7 +1721,7 @@ function deleteNation(General $lord, bool $applyDB): array
|
||||
$lordID
|
||||
),
|
||||
['npc', 'owner', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'belong', 'aux'],
|
||||
1
|
||||
GeneralQueryMode::Lite,
|
||||
);
|
||||
$nationGeneralList[$lordID] = $lord;
|
||||
|
||||
@@ -1728,7 +1738,7 @@ function deleteNation(General $lord, bool $applyDB): array
|
||||
|
||||
// 전 장수 재야로
|
||||
foreach ($nationGeneralList as $general) {
|
||||
if($general->getNPCType() < 2){
|
||||
if ($general->getNPCType() < 2) {
|
||||
$general->setAuxVar(
|
||||
InheritanceKey::max_belong->value,
|
||||
max(
|
||||
|
||||
+49
-12
@@ -133,19 +133,19 @@ function getNationType(?string $type) {
|
||||
}
|
||||
|
||||
|
||||
function getConnect($con) {
|
||||
if($con < 50) $conname = '안함';
|
||||
elseif($con < 100) $conname = '무관심';
|
||||
elseif($con < 200) $conname = '가끔';
|
||||
elseif($con < 400) $conname = '보통';
|
||||
elseif($con < 800) $conname = '자주';
|
||||
elseif($con < 1600) $conname = '열심';
|
||||
elseif($con < 3200) $conname = '중독';
|
||||
elseif($con < 6400) $conname = '폐인';
|
||||
elseif($con < 12800) $conname = '경고';
|
||||
else $conname = '헐...';
|
||||
function getRefreshScoreText($score) {
|
||||
if($score < 50) $scoreName = '안함';
|
||||
elseif($score < 100) $scoreName = '무관심';
|
||||
elseif($score < 200) $scoreName = '가끔';
|
||||
elseif($score < 400) $scoreName = '보통';
|
||||
elseif($score < 800) $scoreName = '자주';
|
||||
elseif($score < 1600) $scoreName = '열심';
|
||||
elseif($score < 3200) $scoreName = '중독';
|
||||
elseif($score < 6400) $scoreName = '폐인';
|
||||
elseif($score < 12800) $scoreName = '경고';
|
||||
else $scoreName = '헐...';
|
||||
|
||||
return $conname;
|
||||
return $scoreName;
|
||||
}
|
||||
|
||||
function getNationType2(?string $type) {
|
||||
@@ -326,6 +326,41 @@ function buildGeneralSpecialWarClass(?string $type):BaseSpecial{
|
||||
return $obj;
|
||||
}
|
||||
|
||||
function getActionCrewTypeClass(?string $type){
|
||||
if($type === null || $type === ''){
|
||||
$type = 'None';
|
||||
}
|
||||
|
||||
static $basePath = __NAMESPACE__.'\\ActionCrewType\\';
|
||||
$classPath = ($basePath.$type);
|
||||
|
||||
if(class_exists($classPath)){
|
||||
return $classPath;
|
||||
}
|
||||
|
||||
$classPath = ($basePath.'che_'.$type);
|
||||
if(class_exists($classPath)){
|
||||
return $classPath;
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException("{$type}은 올바른 병종 효과가 아님");
|
||||
}
|
||||
|
||||
function buildActionCrewTypeClass(?string $type):iAction{
|
||||
static $cache = [];
|
||||
if($type === null){
|
||||
$type = 'None';
|
||||
}
|
||||
if(key_exists($type, $cache)){
|
||||
return $cache[$type];
|
||||
}
|
||||
$class = getActionCrewTypeClass($type);
|
||||
|
||||
$obj = new $class();
|
||||
$cache[$type]= $obj;
|
||||
return $obj;
|
||||
}
|
||||
|
||||
function getGeneralCommandClass(?string $type){
|
||||
if($type === null || $type === ''){
|
||||
$type = '휴식';
|
||||
@@ -542,6 +577,8 @@ function getExpLevel($experience) {
|
||||
$level = Util::toInt(sqrt($experience/10));
|
||||
}
|
||||
|
||||
$level = Util::clamp($level, 0, GameConst::$maxLevel);
|
||||
|
||||
return $level;
|
||||
}
|
||||
|
||||
|
||||
+34
-5
@@ -202,8 +202,10 @@ function preUpdateMonthly()
|
||||
$admin = $gameStor->getValues(['startyear', 'year', 'month']);
|
||||
|
||||
//접률감소, 건국제한-1
|
||||
$db->update('general_access_log', [
|
||||
'refresh_score_total' => $db->sqleval('floor(refresh_score_total*0.99)'),
|
||||
], true);
|
||||
$db->update('general', [
|
||||
'connect' => $db->sqleval('floor(connect*0.99)'),
|
||||
'makelimit' => $db->sqleval('greatest(0, makelimit - 1)'),
|
||||
], true);
|
||||
//전략제한-1, 외교제한-1, 세율동기화
|
||||
@@ -301,7 +303,6 @@ function postUpdateMonthly(RandUtil $rng)
|
||||
WHERE g.nation = A.nation)
|
||||
+(select round(sum(dex1+dex2+dex3+dex4+dex5)/1000) from general where nation=A.nation)
|
||||
+(select round(sum(experience+dedication)/100) from general where nation=A.nation)
|
||||
+(select round(avg(connect)) from general where nation=A.nation)
|
||||
)/10)
|
||||
as power,
|
||||
(select sum(crew) from general where nation=A.nation) as totalCrew
|
||||
@@ -697,7 +698,7 @@ function checkEmperior()
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
$admin = $gameStor->getValues(['year', 'month', 'isunited', 'conlimit']);
|
||||
$admin = $gameStor->getValues(['year', 'month', 'isunited', 'refreshLimit']);
|
||||
if ($admin['isunited'] != 0) {
|
||||
return;
|
||||
}
|
||||
@@ -759,7 +760,7 @@ function checkEmperior()
|
||||
}
|
||||
|
||||
$gameStor->isunited = 2;
|
||||
$gameStor->conlimit = $gameStor->conlimit * 100;
|
||||
$gameStor->refreshLimit = $gameStor->refreshLimit * 100;
|
||||
|
||||
foreach ($db->queryFirstColumn('SELECT no FROM general WHERE npc<2 AND age>=%i', GameConst::$minPushHallAge) as $hallGeneralNo) {
|
||||
CheckHall($hallGeneralNo);
|
||||
@@ -771,7 +772,7 @@ function checkEmperior()
|
||||
|
||||
$chiefs = Util::convertArrayToDict(
|
||||
$db->query(
|
||||
'SELECT no,name,picture,belong,officer_level FROM general WHERE nation=%i AND officer_level >= 5',
|
||||
'SELECT no,npc,name,picture,belong,officer_level FROM general WHERE nation=%i AND officer_level >= 5',
|
||||
$nationID
|
||||
),
|
||||
'officer_level'
|
||||
@@ -908,6 +909,34 @@ function checkEmperior()
|
||||
|
||||
//연감 월결산
|
||||
LogHistory();
|
||||
|
||||
$availableInvaderGame = false;
|
||||
foreach(CityConst::all() as $city){
|
||||
if($city->level == 4){
|
||||
$availableInvaderGame = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if($availableInvaderGame){
|
||||
$invaderMsgCnt = 2;
|
||||
foreach(range(12, 5, -1) as $chiefLevel){
|
||||
if(!key_exists($chiefLevel, $chiefs)){
|
||||
continue;
|
||||
}
|
||||
$targetChief = $chiefs[$chiefLevel];
|
||||
if($targetChief['npc'] >= 2){
|
||||
continue;
|
||||
}
|
||||
$invaderMsgs = RaiseInvaderMessage::buildRaiseInvaderMessage($targetChief['no']);
|
||||
foreach($invaderMsgs as $invaderMsg){
|
||||
$invaderMsg->send();
|
||||
}
|
||||
$invaderMsgCnt--;
|
||||
if($invaderMsgCnt <= 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateMaxDomesticCritical(General $general, $score)
|
||||
|
||||
@@ -383,7 +383,7 @@ function disaster(RandUtil $rng) {
|
||||
|
||||
$generalList = array_map(
|
||||
function($rawGeneral) use ($city, $year, $month){
|
||||
return new General($rawGeneral, null, $city, null, $year, $month, false);
|
||||
return new General($rawGeneral, null, null, $city, null, $year, $month, false);
|
||||
},
|
||||
$generalListByCity[$city['city']]??[]
|
||||
);
|
||||
|
||||
+2
-2
@@ -39,8 +39,8 @@ if ($session->userGrade < 5 && !$allowReset) {
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe 리셋</h1>
|
||||
<div class="row justify-content-md-center">
|
||||
<h1 class="row justify-content-lg-center">삼국지 모의전투 HiDCHe 리셋</h1>
|
||||
<div class="row justify-content-lg-center">
|
||||
|
||||
<div class="col col-lg-8">
|
||||
<div class="card" id="game_form_card">
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ if ($session->userGrade == 5) {
|
||||
|
||||
<body>
|
||||
<div class="container" style="min-width:720px;">
|
||||
<h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe 리셋</h1>
|
||||
<div class="row justify-content-md-center">
|
||||
<h1 class="row justify-content-lg-center">삼국지 모의전투 HiDCHe 리셋</h1>
|
||||
<div class="row justify-content-lg-center">
|
||||
|
||||
<div class="col col-lg-8">
|
||||
<div class="card" id="db_form_card">
|
||||
|
||||
@@ -17,10 +17,13 @@ $text = Util::getPost('text');
|
||||
|
||||
increaseRefresh("회의실", 1);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no, nation, name, officer_level, permission, con, turntime, belong, penalty, `picture`,`imgsvr` FROM general WHERE owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no, nation, name, officer_level, permission, refresh_score, turntime, belong, penalty, `picture`,`imgsvr` FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'접속 제한입니다.'
|
||||
@@ -50,7 +53,7 @@ if($permission < 0){
|
||||
'result'=>false,
|
||||
'reason'=>'국가에 소속되어있지 않습니다.'
|
||||
]);
|
||||
|
||||
|
||||
}
|
||||
else if ($isSecretBoard && $permission < 2) {
|
||||
Json::die([
|
||||
|
||||
@@ -16,10 +16,13 @@ $text = Util::getPost('text');
|
||||
|
||||
increaseRefresh("회의실", 1);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no, nation, name, officer_level, permission, con, turntime, belong, penalty FROM general WHERE owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no, nation, name, officer_level, permission, refresh_score, turntime, belong, penalty FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'접속 제한입니다.'
|
||||
@@ -58,7 +61,7 @@ if($permission < 0){
|
||||
'result'=>false,
|
||||
'reason'=>'국가에 소속되어있지 않습니다.'
|
||||
]);
|
||||
|
||||
|
||||
}
|
||||
else if ($isSecretBoard && $permission < 2) {
|
||||
Json::die([
|
||||
|
||||
@@ -16,11 +16,14 @@ $isSecretBoard = Util::getPost('isSecret', 'bool', false);
|
||||
|
||||
increaseRefresh("회의실", 1);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no, nation, officer_level, permission, con, turntime, belong, penalty FROM general WHERE owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no, nation, officer_level, permission, refresh_score, turntime, belong, penalty FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'접속 제한입니다.'
|
||||
@@ -33,7 +36,7 @@ if($permission < 0){
|
||||
'result'=>false,
|
||||
'reason'=>'국가에 소속되어있지 않습니다.'
|
||||
]);
|
||||
|
||||
|
||||
}
|
||||
else if ($isSecretBoard && $permission < 2) {
|
||||
Json::die([
|
||||
@@ -72,4 +75,3 @@ Json::die([
|
||||
'articles'=>$articles,
|
||||
'reason'=>'success'
|
||||
]);
|
||||
|
||||
|
||||
@@ -17,10 +17,13 @@ $letterNo = Util::getPost('letterNo', 'int');
|
||||
|
||||
increaseRefresh("외교부", 1);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no, name, nation, officer_level, permission, con, turntime, belong, penalty, picture, imgsvr FROM general WHERE owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no, name, nation, officer_level, permission, refresh_score, turntime, belong, penalty, picture, imgsvr FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'접속 제한입니다.'
|
||||
|
||||
@@ -16,11 +16,14 @@ $isSecretBoard = Util::getPost('isSecret', 'bool', false);
|
||||
|
||||
increaseRefresh("외교부", 1);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no, nation, officer_level, permission, con, turntime, belong, penalty FROM general WHERE owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no, nation, officer_level, permission, refresh_score, turntime, belong, penalty FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'접속 제한입니다.'
|
||||
@@ -33,7 +36,7 @@ if($permission < 0){
|
||||
'result'=>false,
|
||||
'reason'=>'국가에 소속되어있지 않습니다.'
|
||||
]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
$letters = [];
|
||||
@@ -83,4 +86,3 @@ Json::die([
|
||||
'myNationID'=>$me['nation'],
|
||||
'reason'=>'success'
|
||||
]);
|
||||
|
||||
|
||||
@@ -22,10 +22,13 @@ $reason = Util::getPost('reason', 'string', '');
|
||||
|
||||
increaseRefresh("외교부", 1);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no, name, nation, officer_level, permission, con, turntime, belong, penalty, picture, imgsvr FROM general WHERE owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no, name, nation, officer_level, permission, refresh_score, turntime, belong, penalty, picture, imgsvr FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'접속 제한입니다.'
|
||||
|
||||
@@ -17,10 +17,13 @@ $letterNo = Util::getPost('letterNo', 'int');
|
||||
|
||||
increaseRefresh("외교부", 1);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no, name, nation, officer_level, permission, con, turntime, belong, penalty, picture, imgsvr FROM general WHERE owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no, name, nation, officer_level, permission, refresh_score, turntime, belong, penalty, picture, imgsvr FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'접속 제한입니다.'
|
||||
|
||||
@@ -24,10 +24,13 @@ if($prevNo < 1){
|
||||
$prevNo = null;
|
||||
}
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no, name, nation, officer_level, permission, con, turntime, belong, penalty, picture, imgsvr FROM general WHERE owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no, name, nation, officer_level, permission, refresh_score, turntime, belong, penalty, picture, imgsvr FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'접속 제한입니다.'
|
||||
|
||||
@@ -33,12 +33,15 @@ if($generalID <= 0 || $reqTo <= 0){
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,permission,penalty from general where owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no,nation,officer_level,refresh_score,turntime,belong,permission,penalty FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
$nationID = $me['nation'];
|
||||
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'접속 제한입니다.'
|
||||
@@ -61,7 +64,7 @@ if($generalID !== $targetID){
|
||||
'reason'=>'권한이 부족합니다. 수뇌부가 아니거나 사관년도가 부족합니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
if($testGeneralNationID !== $nationID){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Enums\MessageType;
|
||||
|
||||
include "lib.php";
|
||||
@@ -50,7 +51,7 @@ else{
|
||||
'troop','officer_level','npc','picture','imgsvr',
|
||||
'permission','penalty','belong', 'crewtype',
|
||||
'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit', 'aux',
|
||||
], 1);
|
||||
], GeneralQueryMode::Lite);
|
||||
|
||||
if($general instanceof DummyGeneral){
|
||||
Json::die([
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
use sammo\Enums\GeneralAccessLogColumn;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
@@ -86,6 +88,11 @@ $db->update('general', [
|
||||
'owner'=>$userID,
|
||||
'aux'=>Json::encode($genAux)
|
||||
], 'owner <= 0 AND npc = 2 AND no = %i', $pick);
|
||||
$db->insertIgnore('general_access_log', [
|
||||
GeneralAccessLogColumn::generalID->value => $generalID,
|
||||
GeneralAccessLogColumn::userID->value => $userID,
|
||||
GeneralAccessLogColumn::lastRefresh->value => $now,
|
||||
]);
|
||||
|
||||
if(!$db->affectedRows()){
|
||||
Json::die([
|
||||
|
||||
@@ -39,7 +39,10 @@ if (!$data || !is_array($data)) {
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no, name, npc, nation, city, officer_level, con, turntime, belong, permission, penalty FROM general WHERE owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no, name, npc, nation, city, officer_level, refresh_score, turntime, belong, permission, penalty FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
|
||||
|
||||
$nationID = $me['nation'];
|
||||
|
||||
+277
-220
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
use Ds\Map;
|
||||
@@ -15,48 +16,48 @@ $userID = Session::getUserID();
|
||||
increaseRefresh("시뮬레이터", 0);
|
||||
|
||||
$query = Util::getPost('query');
|
||||
if($query === null){
|
||||
if ($query === null) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'입력값이 없습니다.'
|
||||
'result' => false,
|
||||
'reason' => '입력값이 없습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$action = Util::getPost('action');
|
||||
if($action === null || !in_array($action, ['reorder', 'battle'])){
|
||||
if ($action === null || !in_array($action, ['reorder', 'battle'])) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'원하는 동작이 지정되지 않았습니다.'
|
||||
'result' => false,
|
||||
'reason' => '원하는 동작이 지정되지 않았습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$query = Json::decode($query);
|
||||
if($query === null){
|
||||
if ($query === null) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 JSON입니다.'
|
||||
'result' => false,
|
||||
'reason' => '올바르지 않은 JSON입니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$defaultCheck = [
|
||||
'required'=>[
|
||||
'required' => [
|
||||
'attackerGeneral', 'attackerCity', 'attackerNation',
|
||||
'defenderGenerals', 'defenderCity', 'defenderNation',
|
||||
'year', 'month', 'repeatCnt'
|
||||
],
|
||||
'integer'=>[
|
||||
'year','month','repeatCnt'
|
||||
'integer' => [
|
||||
'year', 'month', 'repeatCnt'
|
||||
],
|
||||
'between'=>[
|
||||
'between' => [
|
||||
['month', [1, 12]]
|
||||
],
|
||||
'in'=>[
|
||||
'in' => [
|
||||
['repeatCnt', [1, 1000]]
|
||||
],
|
||||
'min'=>[
|
||||
'min' => [
|
||||
['year', 0]
|
||||
],
|
||||
'array'=>[
|
||||
'array' => [
|
||||
'attackerGeneral', 'attackerCity', 'attackerNation',
|
||||
'defenderGenerals', 'defenderCity', 'defenderNation'
|
||||
],
|
||||
@@ -64,10 +65,10 @@ $defaultCheck = [
|
||||
|
||||
$v = new Validator($query);
|
||||
$v->rules($defaultCheck);
|
||||
if(!$v->validate()){
|
||||
if (!$v->validate()) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$v->errorStr()
|
||||
'result' => false,
|
||||
'reason' => $v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -86,20 +87,110 @@ $rawDefenderNation = $query['defenderNation'];
|
||||
|
||||
$warSeed = $query['seed'] ?? '';
|
||||
|
||||
$cityCheck = [
|
||||
'required' => [
|
||||
'city', 'nation', 'supply', 'name',
|
||||
'pop', 'agri', 'comm', 'secu', 'def', 'wall',
|
||||
'trust', 'level',
|
||||
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
|
||||
'dead', 'state', 'conflict',
|
||||
],
|
||||
'numeric' => [
|
||||
'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead'
|
||||
],
|
||||
'integer' => [
|
||||
'city', 'nation', 'supply',
|
||||
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
|
||||
'state',
|
||||
],
|
||||
'min' => [
|
||||
['def', 0],
|
||||
['wall', 0],
|
||||
['trust', 0],
|
||||
['pop', 0],
|
||||
['comm', 0],
|
||||
['secu', 0],
|
||||
['city', 1],
|
||||
['nation', 0]
|
||||
],
|
||||
'in' => [
|
||||
['level', array_keys(getCityLevelList())]
|
||||
]
|
||||
];
|
||||
|
||||
$v = new Validator($rawAttackerCity);
|
||||
$v->rules($cityCheck);
|
||||
if (!$v->validate()) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => '[출병도시]' . $v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$v = new Validator($rawDefenderCity);
|
||||
$v->rules($cityCheck);
|
||||
if (!$v->validate()) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => '[수비도시]' . $v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$nationCheck = [
|
||||
'required' => [
|
||||
'type', 'tech', 'level', 'capital',
|
||||
'nation', 'name', 'gold', 'rice', 'gennum'
|
||||
],
|
||||
'integer' => [
|
||||
'level', 'capital', 'nation', 'gennum',
|
||||
],
|
||||
'numeric' => [
|
||||
'tech', 'gold', 'rice'
|
||||
],
|
||||
'min' => [
|
||||
['tech', 0],
|
||||
['gold', 0],
|
||||
['rice', 0],
|
||||
['gennum', 1],
|
||||
],
|
||||
'in' => [
|
||||
['type', GameConst::$availableNationType],
|
||||
['level', array_keys(getNationLevelList())]
|
||||
]
|
||||
];
|
||||
|
||||
$v = new Validator($rawAttackerNation);
|
||||
$v->rules($nationCheck);
|
||||
if (!$v->validate()) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => '[출병국]' . $v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$v = new Validator($rawDefenderNation);
|
||||
$v->rules($nationCheck);
|
||||
if (!$v->validate()) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => '[수비국]' . $v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$generalCheck = [
|
||||
'required'=>[
|
||||
'required' => [
|
||||
'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train',
|
||||
'intel', 'intel_exp', 'book', 'strength', 'strength_exp', 'weapon', 'injury', 'leadership', 'leadership_exp', 'horse', 'item',
|
||||
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
|
||||
'recent_war', 'warnum', 'killnum', 'killcrew',
|
||||
],
|
||||
'integer'=>[
|
||||
'integer' => [
|
||||
'no', 'nation', 'crew', 'crewtype', 'atmos', 'train',
|
||||
'intel', 'intel_exp', 'strength', 'strength_exp', 'injury', 'leadership', 'leadership_exp',
|
||||
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
|
||||
'warnum', 'killnum', 'killcrew',
|
||||
],
|
||||
'min'=>[
|
||||
'min' => [
|
||||
['no', 1],
|
||||
['nation', 1],
|
||||
['crew', 0],
|
||||
@@ -118,14 +209,14 @@ $generalCheck = [
|
||||
['killnum', 0],
|
||||
['killcrew', 0],
|
||||
],
|
||||
'between'=>[
|
||||
'between' => [
|
||||
['train', [40, GameConst::$maxTrainByWar]],
|
||||
['atmos', [40, GameConst::$maxAtmosByWar]],
|
||||
['explevel', [0, 300]],
|
||||
['injury', [0, 80]],
|
||||
['officer_level', [1, 12]]
|
||||
],
|
||||
'in'=>[
|
||||
'in' => [
|
||||
['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)],
|
||||
['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)],
|
||||
['crewtype', array_keys(GameUnitConst::all())],
|
||||
@@ -134,11 +225,11 @@ $generalCheck = [
|
||||
['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])],
|
||||
['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])],
|
||||
],
|
||||
'array'=>['inheritBuff'],
|
||||
'array' => ['inheritBuff'],
|
||||
];
|
||||
|
||||
$inheritBuffCheck = [
|
||||
'between'=>[
|
||||
'between' => [
|
||||
[TriggerInheritBuff::WAR_AVOID_RATIO, [0, 5]],
|
||||
[TriggerInheritBuff::WAR_CRITICAL_RATIO, [0, 5]],
|
||||
[TriggerInheritBuff::WAR_MAGIC_TRIAL_PROB, [0, 5]],
|
||||
@@ -149,49 +240,67 @@ $inheritBuffCheck = [
|
||||
]
|
||||
];
|
||||
|
||||
if(!$warSeed){
|
||||
$warSeed = bin2hex(random_bytes(16));
|
||||
}
|
||||
else {
|
||||
$repeatCnt = 1;
|
||||
}
|
||||
$tmpRNG = new RandUtil(new LiteHashDRBG($warSeed));
|
||||
|
||||
$v = new Validator($rawAttacker);
|
||||
$v->rules($generalCheck);
|
||||
if(!$v->validate()){
|
||||
if (!$v->validate()) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[출병자]'.$v->errorStr()
|
||||
'result' => false,
|
||||
'reason' => '[출병자]' . $v->errorStr()
|
||||
]);
|
||||
}
|
||||
$rawAttacker['aux'] = [];
|
||||
if(key_exists('inheritBuff', $rawAttacker)){
|
||||
if (key_exists('inheritBuff', $rawAttacker)) {
|
||||
$v = new Validator($rawAttacker['inheritBuff']);
|
||||
$v->rules($inheritBuffCheck);
|
||||
if(!$v->validate()){
|
||||
if (!$v->validate()) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[출병자]'.$v->errorStr()
|
||||
'result' => false,
|
||||
'reason' => '[출병자]' . $v->errorStr()
|
||||
]);
|
||||
}
|
||||
$rawAttacker['aux']['inheritBuff'] = $rawAttacker['inheritBuff'];
|
||||
}
|
||||
$rawAttacker['aux'] = Json::encode($rawAttacker['aux']);
|
||||
$rawAttacker['owner'] = 0;
|
||||
$attackerGeneral = new General($rawAttacker, extractRankVar($rawAttacker), null, $rawAttackerCity, $rawAttackerNation, $year, $month);
|
||||
$attacker = new WarUnitGeneral(
|
||||
$tmpRNG,
|
||||
$attackerGeneral,
|
||||
$rawAttackerNation,
|
||||
true
|
||||
);
|
||||
|
||||
|
||||
/** @var WarUnit[] */
|
||||
$defenderList = [];
|
||||
foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
|
||||
|
||||
foreach ($rawDefenderList as $idx => $rawDefenderGeneral) {
|
||||
$v = new Validator($rawDefenderGeneral);
|
||||
$v->rules($generalCheck);
|
||||
if(!$v->validate()){
|
||||
$idx+=1;
|
||||
if (!$v->validate()) {
|
||||
$idx += 1;
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>"[수비자{$idx}]".$v->errorStr()
|
||||
'result' => false,
|
||||
'reason' => "[수비자{$idx}]" . $v->errorStr()
|
||||
]);
|
||||
}
|
||||
$rawDefenderGeneral['aux'] = [];
|
||||
if(key_exists('inheritBuff', $rawDefenderGeneral)){
|
||||
if (key_exists('inheritBuff', $rawDefenderGeneral)) {
|
||||
$v = new Validator($rawDefenderGeneral['inheritBuff']);
|
||||
$v->rules($inheritBuffCheck);
|
||||
if(!$v->validate()){
|
||||
$idx+=1;
|
||||
if (!$v->validate()) {
|
||||
$idx += 1;
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>"[수비자{$idx}]".$v->errorStr()
|
||||
'result' => false,
|
||||
'reason' => "[수비자{$idx}]" . $v->errorStr()
|
||||
]);
|
||||
}
|
||||
$rawDefenderGeneral['aux']['inheritBuff'] = $rawDefenderGeneral['inheritBuff'];
|
||||
@@ -199,135 +308,54 @@ foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
|
||||
$rawDefenderGeneral['aux'] = Json::encode($rawDefenderGeneral['aux']);
|
||||
$rawDefenderGeneral['owner'] = 0;
|
||||
|
||||
$defenderList[] = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), $rawDefenderCity, $rawAttackerNation, $year, $month, true);
|
||||
$defenderGeneral = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), null, $rawDefenderCity, $rawAttackerNation, $year, $month, true);
|
||||
|
||||
$defenderList[] = new WarUnitGeneral(
|
||||
$tmpRNG,
|
||||
$defenderGeneral,
|
||||
$rawDefenderNation,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
if ($action == 'reorder') {
|
||||
$noRng = NoRNG::rngInstance();
|
||||
|
||||
$cityCheck = [
|
||||
'required'=>[
|
||||
'city', 'nation', 'supply', 'name',
|
||||
'pop', 'agri', 'comm', 'secu', 'def', 'wall',
|
||||
'trust', 'level',
|
||||
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
|
||||
'dead', 'state', 'conflict',
|
||||
],
|
||||
'numeric'=>[
|
||||
'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead'
|
||||
],
|
||||
'integer'=>[
|
||||
'city', 'nation', 'supply',
|
||||
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
|
||||
'state',
|
||||
],
|
||||
'min'=>[
|
||||
['def', 0],
|
||||
['wall', 0],
|
||||
['trust', 0],
|
||||
['pop', 0],
|
||||
['comm', 0],
|
||||
['secu', 0],
|
||||
['city', 1],
|
||||
['nation', 0]
|
||||
],
|
||||
'in'=>[
|
||||
['level', array_keys(getCityLevelList())]
|
||||
]
|
||||
];
|
||||
|
||||
$v = new Validator($rawAttackerCity);
|
||||
$v->rules($cityCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[출병도시]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$v = new Validator($rawDefenderCity);
|
||||
$v->rules($cityCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[수비도시]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$nationCheck = [
|
||||
'required'=>[
|
||||
'type', 'tech', 'level', 'capital',
|
||||
'nation', 'name', 'gold', 'rice', 'gennum'
|
||||
],
|
||||
'integer'=>[
|
||||
'level', 'capital', 'nation', 'gennum',
|
||||
],
|
||||
'numeric'=>[
|
||||
'tech', 'gold', 'rice'
|
||||
],
|
||||
'min'=>[
|
||||
['tech', 0],
|
||||
['gold', 0],
|
||||
['rice', 0],
|
||||
['gennum', 1],
|
||||
],
|
||||
'in'=>[
|
||||
['type', GameConst::$availableNationType],
|
||||
['level', array_keys(getNationLevelList())]
|
||||
]
|
||||
];
|
||||
|
||||
$v = new Validator($rawAttackerNation);
|
||||
$v->rules($nationCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[출병국]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$v = new Validator($rawDefenderNation);
|
||||
$v->rules($nationCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[수비국]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
if($action == 'reorder'){
|
||||
usort($defenderList, function(General $lhs, General $rhs){
|
||||
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
|
||||
usort($defenderList, function (WarUnit $lhs, WarUnit $rhs) use ($attacker) {
|
||||
return - (extractBattleOrder($lhs, $attacker) <=> extractBattleOrder($rhs, $attacker));
|
||||
});
|
||||
|
||||
$order = [];
|
||||
foreach($defenderList as $defenderGeneral){
|
||||
$order[] = $defenderGeneral->getID();
|
||||
foreach ($defenderList as $defender) {
|
||||
$order[] = $defender->getGeneral()->getID();
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success',
|
||||
'order'=>$order
|
||||
'result' => true,
|
||||
'reason' => 'success',
|
||||
'order' => $order
|
||||
]);
|
||||
}
|
||||
|
||||
usort($defenderList, function(General $lhs, General $rhs){
|
||||
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
|
||||
});
|
||||
|
||||
$rawDefenderList = array_map(function(General $general){
|
||||
return $general->getRaw();
|
||||
}, $defenderList);
|
||||
$rawDefenderList = [];
|
||||
foreach($defenderList as $unit){
|
||||
if(extractBattleOrder($unit, $attacker) <= 0){
|
||||
continue;
|
||||
}
|
||||
$rawDefenderList[] = $unit->getRaw();
|
||||
}
|
||||
unset($defenderList);
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$startYear = $gameStor->startyear;
|
||||
|
||||
function extractRankVar(array $rawVal):Map{
|
||||
function extractRankVar(array $rawVal): Map
|
||||
{
|
||||
$rankVars = new Map;
|
||||
foreach($rawVal as $rawKey=>$rawVal){
|
||||
foreach ($rawVal as $rawKey => $rawVal) {
|
||||
$key = RankColumn::tryFrom($rawKey);
|
||||
if($key === null){
|
||||
if ($key === null) {
|
||||
continue;
|
||||
}
|
||||
$rankVars[$key] = $rawVal;
|
||||
@@ -336,80 +364,104 @@ function extractRankVar(array $rawVal):Map{
|
||||
}
|
||||
|
||||
function simulateBattle(
|
||||
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
|
||||
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
|
||||
$startYear, $year, $month, $warSeed
|
||||
){
|
||||
$rawAttacker,
|
||||
$rawAttackerCity,
|
||||
$rawAttackerNation,
|
||||
$rawDefenderList,
|
||||
$rawDefenderCity,
|
||||
$rawDefenderNation,
|
||||
$startYear,
|
||||
$year,
|
||||
$month,
|
||||
$warSeed
|
||||
) {
|
||||
|
||||
if(!$warSeed){
|
||||
if (!$warSeed) {
|
||||
$warSeed = bin2hex(random_bytes(16));
|
||||
}
|
||||
|
||||
$warRng = new RandUtil(new LiteHashDRBG($warSeed));
|
||||
|
||||
$attackerGeneral = new General($rawAttacker, extractRankVar($rawAttacker), null, $rawAttackerCity, $rawAttackerNation, $year, $month);
|
||||
$attacker = new WarUnitGeneral(
|
||||
$warRng,
|
||||
new General($rawAttacker, extractRankVar($rawAttacker), $rawAttackerCity, $rawAttackerNation, $year, $month),
|
||||
$attackerGeneral,
|
||||
$rawAttackerNation,
|
||||
true
|
||||
);
|
||||
$city = new WarUnitCity($warRng, $rawDefenderCity, $rawDefenderNation, $year, $month, $startYear);
|
||||
|
||||
$iterDefender = new \ArrayIterator($rawDefenderList);
|
||||
/** @var WarUnit[] */
|
||||
$defenderList = [];
|
||||
|
||||
foreach ($rawDefenderList as $rawDefenderGeneral) {
|
||||
$defenderGeneral = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), null, $rawDefenderCity, $rawAttackerNation, $year, $month, true);
|
||||
|
||||
$defenderList[] = new WarUnitGeneral(
|
||||
$warRng,
|
||||
$defenderGeneral,
|
||||
$rawDefenderNation,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
if(count($defenderList) && extractBattleOrder($city, $attacker) > 0){
|
||||
$defenderList[] = $city;
|
||||
}
|
||||
|
||||
usort($defenderList, function (WarUnit $lhs, WarUnit $rhs) use ($attacker) {
|
||||
return - (extractBattleOrder($lhs, $attacker) <=> extractBattleOrder($rhs, $attacker));
|
||||
});
|
||||
|
||||
$iterDefender = new \ArrayIterator($defenderList);
|
||||
$iterDefender->rewind();
|
||||
|
||||
$battleResult = [];
|
||||
|
||||
$attackerRice = $rawAttacker['rice'];
|
||||
$attackerRice = $attacker->getGeneral()->getVar('rice');
|
||||
$defenderRice = 0;
|
||||
|
||||
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext)
|
||||
use ($warRng, $iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) {
|
||||
if($prevDefender !== null){
|
||||
$getNextDefender = function (?WarUnit $prevDefender, bool $reqNext)
|
||||
use ($iterDefender, &$battleResult, &$defenderRice, $attacker): ?WarUnit {
|
||||
if ($prevDefender !== null) {
|
||||
$prevDefender->getLogger()->rollback();
|
||||
$battleResult[] = $prevDefender;
|
||||
if($prevDefender instanceof WarUnitGeneral){
|
||||
if ($prevDefender instanceof WarUnitGeneral) {
|
||||
$defenderRice -= $prevDefender->getVar('rice');
|
||||
}
|
||||
}
|
||||
|
||||
if(!$reqNext){
|
||||
if (!$reqNext) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(!$iterDefender->valid()){
|
||||
if (!$iterDefender->valid()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$defenderObj = new General($iterDefender->current(), extractRankVar($iterDefender->current()), $rawDefenderCity, $rawDefenderNation, $year, $month);
|
||||
if(extractBattleOrder($defenderObj) <= 0){
|
||||
/** @var WarUnit */
|
||||
$defender = $iterDefender->current();
|
||||
|
||||
if (extractBattleOrder($defender, $attacker) <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$defenderRice += $defenderObj->getVar('rice');
|
||||
if($defender instanceof WarUnitGeneral){
|
||||
$defenderRice += $defender->getVar('rice');
|
||||
}
|
||||
|
||||
$retVal = new WarUnitGeneral(
|
||||
$warRng,
|
||||
$defenderObj,
|
||||
$rawDefenderNation,
|
||||
false
|
||||
);
|
||||
$iterDefender->next();
|
||||
return $retVal;
|
||||
return $defender;
|
||||
};
|
||||
|
||||
$conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city, $year - $startYear);
|
||||
|
||||
$rawDefenderCity = $city->getRaw();
|
||||
$updateAttackerNation = [];
|
||||
$updateDefenderNation = [];
|
||||
$conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city);
|
||||
|
||||
$attackerRice -= $attacker->getVar('rice');
|
||||
|
||||
if($city->getPhase() > 0){
|
||||
if ($city->getPhase() > 0) {
|
||||
$rice = $city->getKilled() / 100 * 0.8;
|
||||
$rice *= $city->getCrewType()->rice;
|
||||
$rice *= getTechCost($rawDefenderNation['tech']);
|
||||
$rice *= getTechCost($city->getRawNation()['tech']);
|
||||
$rice *= $city->getCityTrainAtmos() / 100 - 0.2;
|
||||
Util::setRound($rice);
|
||||
|
||||
@@ -417,8 +469,8 @@ function simulateBattle(
|
||||
}
|
||||
|
||||
$totalDead = $attacker->getKilled() + $attacker->getDead();
|
||||
$attackerCityDead = $totalDead * 0.4;
|
||||
$defenderCityDead = $totalDead * 0.6;
|
||||
//$attackerCityDead = $totalDead * 0.4;
|
||||
//$defenderCityDead = $totalDead * 0.6;
|
||||
|
||||
return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice];
|
||||
}
|
||||
@@ -444,18 +496,26 @@ $avgWar = 0;
|
||||
$attackerActivatedSkills = [];
|
||||
$defendersActivatedSkills = [];
|
||||
|
||||
if($warSeed){
|
||||
$repeatCnt = 1;
|
||||
}
|
||||
|
||||
foreach(Util::range($repeatCnt) as $repeatIdx){
|
||||
foreach (Util::range($repeatCnt) as $repeatIdx) {
|
||||
if($repeatIdx > 0){
|
||||
$warSeed = bin2hex(random_bytes(16));
|
||||
}
|
||||
|
||||
/** @var WarUnit $attacker */
|
||||
[$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle(
|
||||
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
|
||||
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
|
||||
$startYear, $year, $month, $warSeed
|
||||
$rawAttacker,
|
||||
$rawAttackerCity,
|
||||
$rawAttackerNation,
|
||||
$rawDefenderList,
|
||||
$rawDefenderCity,
|
||||
$rawDefenderNation,
|
||||
$startYear,
|
||||
$year,
|
||||
$month,
|
||||
$warSeed
|
||||
);
|
||||
$lastWarLog = Util::mapWithKey(function($key, $values){
|
||||
$lastWarLog = Util::mapWithKey(function ($key, $values) {
|
||||
return ConvertLog(join('<br>', $values));
|
||||
}, $attacker->getLogger()->rollback());
|
||||
|
||||
@@ -478,48 +538,45 @@ foreach(Util::range($repeatCnt) as $repeatIdx){
|
||||
|
||||
$avgWar += count($battleResult) / $repeatCnt;
|
||||
|
||||
foreach($attacker->getActivatedSkillLog() as $skillName => $skillCnt){
|
||||
if(!key_exists($skillName, $attackerActivatedSkills)){
|
||||
foreach ($attacker->getActivatedSkillLog() as $skillName => $skillCnt) {
|
||||
if (!key_exists($skillName, $attackerActivatedSkills)) {
|
||||
$attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt;
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($battleResult as $idx=>$defender){
|
||||
while($idx >= count($defendersActivatedSkills)){
|
||||
foreach ($battleResult as $idx => $defender) {
|
||||
while ($idx >= count($defendersActivatedSkills)) {
|
||||
$defendersActivatedSkills[] = [];
|
||||
}
|
||||
|
||||
$activatedSkills = &$defendersActivatedSkills[$idx];
|
||||
foreach($defender->getActivatedSkillLog() as $skillName => $skillCnt){
|
||||
if(!key_exists($skillName, $activatedSkills)){
|
||||
foreach ($defender->getActivatedSkillLog() as $skillName => $skillCnt) {
|
||||
if (!key_exists($skillName, $activatedSkills)) {
|
||||
$activatedSkills[$skillName] = $skillCnt / $repeatCnt;
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$activatedSkills[$skillName] += $skillCnt / $repeatCnt;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'datetime'=>$rawAttacker['turntime'],
|
||||
'reason'=>'success',
|
||||
'lastWarLog'=>$lastWarLog,
|
||||
'avgWar'=>$avgWar,
|
||||
'phase'=>$avgPhase,
|
||||
'killed'=>$attackerKilled,
|
||||
'maxKilled'=>$attackerMaxKilled,
|
||||
'minKilled'=>$attackerMinKilled,
|
||||
'dead'=>$attackerDead,
|
||||
'maxDead'=>$attackerMaxDead,
|
||||
'minDead'=>$attackerMinDead,
|
||||
'attackerRice'=>$attackerAvgRice,
|
||||
'defenderRice'=>$defenderAvgRice,
|
||||
'attackerSkills'=>$attackerActivatedSkills,
|
||||
'defendersSkills'=>$defendersActivatedSkills,
|
||||
'result' => true,
|
||||
'datetime' => $rawAttacker['turntime'],
|
||||
'reason' => 'success',
|
||||
'lastWarLog' => $lastWarLog,
|
||||
'avgWar' => $avgWar,
|
||||
'phase' => $avgPhase,
|
||||
'killed' => $attackerKilled,
|
||||
'maxKilled' => $attackerMaxKilled,
|
||||
'minKilled' => $attackerMinKilled,
|
||||
'dead' => $attackerDead,
|
||||
'maxDead' => $attackerMaxDead,
|
||||
'minDead' => $attackerMinDead,
|
||||
'attackerRice' => $attackerAvgRice,
|
||||
'defenderRice' => $defenderAvgRice,
|
||||
'attackerSkills' => $attackerActivatedSkills,
|
||||
'defendersSkills' => $defendersActivatedSkills,
|
||||
]);
|
||||
|
||||
+30
-28
@@ -3,6 +3,7 @@
|
||||
namespace sammo;
|
||||
|
||||
use sammo\DTO\VoteInfo;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
@@ -29,7 +30,8 @@ if (!$session->isGameLoggedIn()) {
|
||||
}
|
||||
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no,con,turntime,newmsg,newvote,`officer_level` from general where owner = %i',
|
||||
'SELECT no,refresh_score,turntime,newmsg,newvote,`officer_level` FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner = %i',
|
||||
$userID
|
||||
);
|
||||
|
||||
@@ -51,13 +53,13 @@ if ($me['newmsg'] == 1 || $me['newvote'] == 1) {
|
||||
|
||||
$plock = boolval($db->queryFirstField('SELECT plock FROM plock WHERE `type`="GAME" LIMIT 1'));
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
printLimitMsg($me['turntime']);
|
||||
exit();
|
||||
}
|
||||
|
||||
$generalObj = General::createGeneralObjFromDB($me['no']);
|
||||
$generalObj = General::createGeneralObjFromDB($me['no'], null, GeneralQueryMode::FullWithAccessLog);
|
||||
$generalObj->setRawCity($db->queryFirstRow('SELECT * FROM city WHERE city = %i', $generalObj->getCityID()));
|
||||
$scenario = $gameStor->scenario_text;
|
||||
|
||||
@@ -180,44 +182,44 @@ if ($lastVoteID) {
|
||||
</div>
|
||||
|
||||
<div class="row center gx-0">
|
||||
<div class="s-border-t col py-2 col-8 col-md-4" style="color:<?= $color ?>;">
|
||||
<div class="s-border-t col py-2 col-8 col-lg-4" style="color:<?= $color ?>;">
|
||||
<?= $scenario ?>
|
||||
</div>
|
||||
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
|
||||
<div class="s-border-t col py-2 col-4 col-lg-2" style="color:<?= $color ?>;">
|
||||
NPC 수, 상성 : <?= $extend ?>,<?= $fiction ?>
|
||||
</div>
|
||||
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
|
||||
<div class="s-border-t col py-2 col-4 col-lg-2" style="color:<?= $color ?>;">
|
||||
NPC선택 : <?= $npcmode ?>
|
||||
</div>
|
||||
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
|
||||
<div class="s-border-t col py-2 col-4 col-lg-2" style="color:<?= $color ?>;">
|
||||
토너먼트 : <?= getTournamentTermText($gameStor->turnterm) ?>
|
||||
</div>
|
||||
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
|
||||
<div class="s-border-t col py-2 col-4 col-lg-2" style="color:<?= $color ?>;">
|
||||
기타 설정: <?= $otherTextInfo ?>
|
||||
</div>
|
||||
|
||||
<div class="s-border-t col py-2 col-8 col-md-4"><?= info(2) ?></div>
|
||||
<div class="s-border-t col py-2 col-4 col-md-2">전체 접속자 수 : <?= $gameStor->online_user_cnt ?> 명</div>
|
||||
<div class="s-border-t col py-2 col-4 col-md-2">턴당 갱신횟수 : <?= $gameStor->conlimit ?>회</div>
|
||||
<div class="s-border-t col py-2 col-8 col-md-4"><?= info(3) ?></div>
|
||||
<div class="s-border-t py-2 col col-6 col-md-4">
|
||||
<div class="s-border-t col py-2 col-8 col-lg-4"><?= info(2) ?></div>
|
||||
<div class="s-border-t col py-2 col-4 col-lg-2">전체 접속자 수 : <?= $gameStor->online_user_cnt ?> 명</div>
|
||||
<div class="s-border-t col py-2 col-4 col-lg-2">턴당 갱신횟수 : <?= $gameStor->refreshLimit ?>회</div>
|
||||
<div class="s-border-t col py-2 col-8 col-lg-4"><?= info(3) ?></div>
|
||||
<div class="s-border-t py-2 col col-6 col-lg-4">
|
||||
<?php if ($isTournamentActive) : ?>
|
||||
↑<span style='color:cyan'><?= (['전력전', '통솔전', '일기토', '설전',])[$gameStor->tnmt_type] ?? '' ?> <?= getTournament($gameStor->tournament) ?> <?= getTournamentTime() ?></span>↑
|
||||
<?php else : ?>
|
||||
<span style='color:magenta'>현재 토너먼트 경기 없음</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="s-border-t py-2 col col-6 col-md-2">
|
||||
<div class="s-border-t py-2 col col-6 col-lg-2">
|
||||
<div style="display:inline-block;"><?= $plock ? ("<span style='color:magenta;'>동작 시각: " . substr($gameStor->turntime, 5, 14) . "</span>") : ("<span style='color:cyan;'>동작 시각: " . substr($gameStor->turntime, 5, 14) . "</span>") ?></div>
|
||||
</div>
|
||||
<div class="s-border-t py-2 col col-6 col-md-2">
|
||||
<div class="s-border-t py-2 col col-6 col-lg-2">
|
||||
<?php if ($auctionCount > 0) : ?>
|
||||
<span style='color:cyan'><?= $auctionCount ?>건</span> 거래 진행중
|
||||
<?php else : ?>
|
||||
<span style='color:magenta'>진행중 거래 없음</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="s-border-t py-2 col col-6 col-md-4 vote-cell">
|
||||
<div class="s-border-t py-2 col col-6 col-lg-4 vote-cell">
|
||||
<?php
|
||||
?>
|
||||
<?php if ($lastVote === null) : ?>
|
||||
@@ -310,11 +312,11 @@ if ($lastVoteID) {
|
||||
</div>
|
||||
</div>
|
||||
<div class="row gx-0">
|
||||
<div class="col-md-6" id="general_public_record-position">
|
||||
<div class="col-lg-6" id="general_public_record-position">
|
||||
<div class="bg1 center s-border-tb"><b>장수 동향</b></div>
|
||||
<div id="general_public_record" style="text-align:left;"><?= formatHistoryToHTML(getGlobalActionLogRecent(15)) ?></div>
|
||||
</div>
|
||||
<div class="col-md-6" id="general_log-position">
|
||||
<div class="col-lg-6" id="general_log-position">
|
||||
<div class="bg1 center s-border-tb"><b>개인 기록</b></div>
|
||||
<div id="general_log" style="text-align:left;"><?= formatHistoryToHTML(getGeneralActionLogRecent($me['no'], 15)) ?></div>
|
||||
</div>
|
||||
@@ -328,34 +330,34 @@ if ($lastVoteID) {
|
||||
|
||||
<div id="message_board" class="row gx-0">
|
||||
<div class="message_input_form bg0 gx-0 row">
|
||||
<div id="mailbox_list-col" class="col-6 col-md-2 d-grid">
|
||||
<div id="mailbox_list-col" class="col-6 col-lg-2 d-grid">
|
||||
<select id="mailbox_list" size="1" class="form-control bg-dark text-white">
|
||||
</select>
|
||||
</div>
|
||||
<div id="msg_input-col" class="col-12 col-md-8 d-grid">
|
||||
<div id="msg_input-col" class="col-12 col-lg-8 d-grid">
|
||||
<input type="text" id="msg_input" maxlength="99" class="form-control">
|
||||
</div>
|
||||
<div id="msg_submit-col" class="col-6 col-md-2 d-grid"><button id="msg_submit" class="btn btn-primary">서신전달&갱신</button></div>
|
||||
<div id="msg_submit-col" class="col-6 col-lg-2 d-grid"><button id="msg_submit" class="btn btn-primary">서신전달&갱신</button></div>
|
||||
</div>
|
||||
<div class="col-md-6 board_side bg0"><a id="public_talk_position"></a>
|
||||
<div class="col-lg-6 board_side bg0"><a id="public_talk_position"></a>
|
||||
<div class="board_header bg0">전체 메시지(최고99자)</div>
|
||||
<section class="public_message">
|
||||
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="public">이전 메시지 불러오기</button></div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-md-6 board_side bg0"><a id="national_talk_position"></a>
|
||||
<div class="col-lg-6 board_side bg0"><a id="national_talk_position"></a>
|
||||
<div class="board_header bg0">국가 메시지(최고99자)</div>
|
||||
<section class="national_message">
|
||||
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="national">이전 메시지 불러오기</button></div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-md-6 board_side bg0"><a id="private_talk_position"></a>
|
||||
<div class="col-lg-6 board_side bg0"><a id="private_talk_position"></a>
|
||||
<div class="board_header bg0">개인 메시지(최고99자)</div>
|
||||
<section class="private_message">
|
||||
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="private">이전 메시지 불러오기</button></div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-md-6 board_side bg0"><a id="diplomacy_talk_position"></a>
|
||||
<div class="col-lg-6 board_side bg0"><a id="diplomacy_talk_position"></a>
|
||||
<div class="board_header bg0">외교 메시지(최고99자)</div>
|
||||
<section class="diplomacy_message">
|
||||
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="diplomacy">이전 메시지 불러오기</button></div>
|
||||
@@ -367,7 +369,7 @@ if ($lastVoteID) {
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
if ($con == 1) {
|
||||
if ($limitState == 1) {
|
||||
MessageBox("접속제한이 얼마 남지 않았습니다!");
|
||||
}
|
||||
if ($me['newmsg'] == 1) {
|
||||
@@ -379,7 +381,7 @@ if ($lastVoteID) {
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<nav class="navbar navbar-expand fixed-bottom navbar-dark bg-dark d-sm-block d-md-none p-0" id="navbar500">
|
||||
<nav class="navbar navbar-expand fixed-bottom navbar-dark bg-dark d-sm-block d-lg-none p-0" id="navbar500">
|
||||
<div class="container-fluid px-0">
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav me-auto mx-auto">
|
||||
|
||||
+67
-34
@@ -3,6 +3,7 @@
|
||||
namespace sammo;
|
||||
|
||||
use sammo\Enums\EventTarget;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
|
||||
function processWar(string $warSeed, General $attackerGeneral, array $rawAttackerNation, array $rawDefenderCity)
|
||||
{
|
||||
@@ -37,16 +38,32 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
|
||||
$city = new WarUnitCity($rng, $rawDefenderCity, $rawDefenderNation, $year, $month, $startYear);
|
||||
|
||||
$defenderIDList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND city=%i AND nation!=0 and crew > 0 and rice>(crew/100) and train>=defence_train and atmos>=defence_train', $city->getVar('nation'), $city->getVar('city'));
|
||||
$defenderList = General::createGeneralObjListFromDB($defenderIDList, null, 2);
|
||||
$defenderGeneralList = General::createGeneralObjListFromDB($defenderIDList, null);
|
||||
|
||||
usort($defenderList, function (General $lhs, General $rhs) {
|
||||
return - (extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
|
||||
/** @var WarUnit[] */
|
||||
$defenderList = [];
|
||||
foreach($defenderGeneralList as $defenderGeneral){
|
||||
$defenderGeneral->setRawCity($rawDefenderCity);
|
||||
$defenderCandidate = new WarUnitGeneral($rng, $defenderGeneral, $rawDefenderNation, false);
|
||||
if(extractBattleOrder($defenderCandidate, $attacker) <= 0){
|
||||
continue;
|
||||
}
|
||||
|
||||
$defenderList[] = $defenderCandidate;
|
||||
}
|
||||
|
||||
if(count($defenderList) && extractBattleOrder($city, $attacker) > 0){
|
||||
$defenderList[] = $city;
|
||||
}
|
||||
|
||||
usort($defenderList, function (WarUnit $lhs, WarUnit $rhs) use ($attacker) {
|
||||
return - (extractBattleOrder($lhs, $attacker) <=> extractBattleOrder($rhs, $attacker));
|
||||
});
|
||||
|
||||
$iterDefender = new \ArrayIterator($defenderList);
|
||||
$iterDefender->rewind();
|
||||
|
||||
$getNextDefender = function (?WarUnit $prevDefender, bool $reqNext) use ($rng, $iterDefender, $rawDefenderNation, $rawDefenderCity, $db) {
|
||||
$getNextDefender = function (?WarUnit $prevDefender, bool $reqNext) use ($iterDefender, $db, $attacker) {
|
||||
if ($prevDefender !== null) {
|
||||
$prevDefender->applyDB($db);
|
||||
}
|
||||
@@ -59,24 +76,16 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var WarUnit */
|
||||
$nextDefender = $iterDefender->current();
|
||||
$nextDefender->setRawCity($rawDefenderCity);
|
||||
if (extractBattleOrder($nextDefender) <= 0) {
|
||||
if (extractBattleOrder($nextDefender, $attacker) <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
$retVal = new WarUnitGeneral(
|
||||
$rng,
|
||||
$nextDefender,
|
||||
$rawDefenderNation,
|
||||
false
|
||||
);
|
||||
$iterDefender->next();
|
||||
return $retVal;
|
||||
return $nextDefender;
|
||||
};
|
||||
|
||||
$conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city, $year - $startYear);
|
||||
$conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city);
|
||||
|
||||
$attacker->applyDB($db);
|
||||
|
||||
@@ -180,8 +189,17 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
|
||||
], $attacker->getGeneral(), $city->getRaw());
|
||||
}
|
||||
|
||||
function extractBattleOrder(General $general)
|
||||
function extractBattleOrder(WarUnit $defender, WarUnit $attacker)
|
||||
{
|
||||
if($defender instanceof WarUnitCity){
|
||||
if(!($attacker instanceof WarUnitGeneral)){
|
||||
return 0;
|
||||
}
|
||||
$attackerGeneral = $attacker->getGeneral();
|
||||
return $attackerGeneral->onCalcOpposeStat($defender->getGeneral(), 'cityBattleOrder', -1);
|
||||
}
|
||||
|
||||
$general = $defender->getGeneral();
|
||||
if ($general->getVar('crew') == 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -212,7 +230,6 @@ function processWar_NG(
|
||||
WarUnitGeneral $attacker,
|
||||
callable $getNextDefender,
|
||||
WarUnitCity $city,
|
||||
int $relYear
|
||||
): bool {
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
|
||||
@@ -225,6 +242,7 @@ function processWar_NG(
|
||||
$attackerNationUpdate = [];
|
||||
$defenderNationUpdate = [];
|
||||
|
||||
/** @var WarUnit */
|
||||
$defender = ($getNextDefender)(null, true);
|
||||
$conquerCity = false;
|
||||
|
||||
@@ -240,6 +258,7 @@ function processWar_NG(
|
||||
$logWritten = false;
|
||||
if ($defender === null) {
|
||||
$defender = $city;
|
||||
$defender->setSiege();
|
||||
|
||||
if ($city->getNationVar('rice') <= 0 && $city->getVar('supply')) {
|
||||
//병량 패퇴
|
||||
@@ -406,21 +425,28 @@ function processWar_NG(
|
||||
$attacker->logBattleResult();
|
||||
$defender->logBattleResult();
|
||||
|
||||
$attacker->addWin();
|
||||
$defender->addLose();
|
||||
if (!($defender instanceof WarUnitCity) || $defender->isSiege()){
|
||||
$attacker->addWin();
|
||||
$defender->addLose();
|
||||
|
||||
$attacker->tryWound();
|
||||
$defender->tryWound();
|
||||
$attacker->tryWound();
|
||||
$defender->tryWound();
|
||||
|
||||
if ($defender === $city) {
|
||||
$attacker->addLevelExp(1000);
|
||||
$conquerCity = true;
|
||||
break;
|
||||
if ($defender === $city) {
|
||||
$attacker->addLevelExp(1000);
|
||||
$conquerCity = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$josaYi = JosaUtil::pick($defender->getCrewTypeName(), '이');
|
||||
|
||||
if ($noRice) {
|
||||
if ($defender instanceof WarUnitCity && !$defender->isSiege()){
|
||||
//실제 공성을 위해 다시 초기화
|
||||
$defender->setOppose(null);
|
||||
}
|
||||
else if ($noRice) {
|
||||
$logger->pushGlobalActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다.");
|
||||
$attacker->getLogger()->pushGeneralActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다.", ActionLogger::PLAIN);
|
||||
$defender->getLogger()->pushGeneralActionLog("군량 부족으로 패퇴합니다.", ActionLogger::PLAIN);
|
||||
@@ -455,12 +481,18 @@ function processWar_NG(
|
||||
$attacker->finishBattle();
|
||||
$defender->finishBattle();
|
||||
|
||||
if ($defender instanceof WarUnitCity) {
|
||||
$newConflict = $defender->addConflict();
|
||||
if($city->getDead() || $defender instanceof WarUnitCity){
|
||||
if($city !== $defender){
|
||||
$city->setOppose($attacker);
|
||||
$city->setSiege();
|
||||
$city->finishBattle();
|
||||
}
|
||||
|
||||
$newConflict = $city->addConflict();
|
||||
if ($newConflict) {
|
||||
$nationName = $attacker->getNationVar('name');
|
||||
$josaYi = JosaUtil::pick($nationName, '이');
|
||||
$logger->pushGlobalHistoryLog("<M><b>【분쟁】</b></><D><b>{$nationName}</b></>{$josaYi} <G><b>{$defender->getName()}</b></> 공략에 가담하여 분쟁이 발생하고 있습니다.");
|
||||
$logger->pushGlobalHistoryLog("<M><b>【분쟁】</b></><D><b>{$nationName}</b></>{$josaYi} <G><b>{$city->getName()}</b></> 공략에 가담하여 분쟁이 발생하고 있습니다.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -564,10 +596,10 @@ function ConquerCity(array $admin, General $general, array $city)
|
||||
|
||||
$lord = new General($db->queryFirstRow(
|
||||
'SELECT %l FROM general WHERE nation = %i AND officer_level = %i LIMIT 1',
|
||||
Util::formatListOfBackticks(General::mergeQueryColumn(['npc', 'gold', 'rice', 'experience', 'explevel', 'belong', 'dedication', 'dedlevel', 'aux'], 1)[0]),
|
||||
Util::formatListOfBackticks(General::mergeQueryColumn(['npc', 'gold', 'rice', 'experience', 'explevel', 'belong', 'dedication', 'dedlevel', 'aux'], GeneralQueryMode::Lite)[0]),
|
||||
$defenderNationID,
|
||||
12
|
||||
), null, $city, $loseNation, $year, $month, false);
|
||||
), null, null, $city, $loseNation, $year, $month, false);
|
||||
|
||||
$josaUl = JosaUtil::pick($defenderNationName, '을');
|
||||
$attackerLogger->pushNationalHistoryLog("<D><b>{$defenderNationName}</b></>{$josaUl} 정복");
|
||||
@@ -664,11 +696,12 @@ function ConquerCity(array $admin, General $general, array $city)
|
||||
$minCity = findNextCapital($cityID, $defenderNationID);
|
||||
|
||||
$minCityName = CityConst::byID($minCity)->name;
|
||||
$josaRo = JosaUtil::pick($minCityName, '로');
|
||||
|
||||
$josaYi = JosaUtil::pick($defenderNationName, '이');
|
||||
$attackerLogger->pushGlobalHistoryLog("<M><b>【긴급천도】</b></><D><b>{$defenderNationName}</b></>{$josaYi} 수도가 함락되어 <G><b>$minCityName</b></>으로 긴급천도하였습니다.");
|
||||
$attackerLogger->pushGlobalHistoryLog("<M><b>【긴급천도】</b></><D><b>{$defenderNationName}</b></>{$josaYi} 수도가 함락되어 <G><b>$minCityName</b></>{$josaRo} 긴급천도하였습니다.");
|
||||
|
||||
$moveLog = "수도가 함락되어 <G><b>$minCityName</b></>으로 <M>긴급천도</>합니다.";
|
||||
$moveLog = "수도가 함락되어 <G><b>$minCityName</b></>{$josaRo} <M>긴급천도</>합니다.";
|
||||
//아국 수뇌부에게 로그 전달
|
||||
foreach ($db->queryFirstColumn(
|
||||
'SELECT no FROM general WHERE nation=%i AND officer_level>=5',
|
||||
|
||||
@@ -10,6 +10,7 @@ use sammo\DTO\AuctionBidItem;
|
||||
use sammo\DTO\AuctionInfo;
|
||||
use sammo\Enums\APIRecoveryType;
|
||||
use sammo\Enums\AuctionType;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Enums\InheritanceKey;
|
||||
use sammo\InheritancePointManager;
|
||||
use sammo\TimeUtil;
|
||||
@@ -76,7 +77,7 @@ class GetUniqueItemAuctionDetail extends \sammo\BaseAPI
|
||||
$inheritMgr = InheritancePointManager::getInstance();
|
||||
//preveious라서 column을 최대한 비울 수 있다.
|
||||
$remainPoint = $inheritMgr->getInheritancePoint(
|
||||
General::createGeneralObjFromDB($generalID, ['owner'], 0),
|
||||
General::createGeneralObjFromDB($generalID, ['owner'], GeneralQueryMode::Core),
|
||||
InheritanceKey::previous
|
||||
);
|
||||
|
||||
|
||||
@@ -42,9 +42,12 @@ class GetBettingList extends \sammo\BaseAPI
|
||||
$bettingStor = KVStorage::getStorage($db, 'betting');
|
||||
$userID = $session->userID;
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,penalty,permission FROM general WHERE owner=%i', $userID);
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no,nation,officer_level,refresh_score,turntime,belong,penalty,permission FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
return "접속 제한중입니다.";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,332 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\API\City;
|
||||
|
||||
use ArrayObject;
|
||||
use Ds\Set;
|
||||
use sammo\CityConst;
|
||||
use sammo\DB;
|
||||
use sammo\Enums\APIRecoveryType;
|
||||
use sammo\General;
|
||||
use sammo\Json;
|
||||
use sammo\Session;
|
||||
use sammo\Util;
|
||||
use sammo\Validator;
|
||||
|
||||
use function sammo\calcLeadershipBonus;
|
||||
use function sammo\checkLimit;
|
||||
use function sammo\checkSecretPermission;
|
||||
use function sammo\getAllNationStaticInfo;
|
||||
use function sammo\getBillByLevel;
|
||||
use function sammo\getDedLevelText;
|
||||
use function sammo\getHonor;
|
||||
use function sammo\getNationStaticInfo;
|
||||
use function sammo\getOfficerLevelText;
|
||||
use function sammo\increaseRefresh;
|
||||
|
||||
class GetCityInfo extends \sammo\BaseAPI
|
||||
{
|
||||
const FAR_CITY = 0;
|
||||
const NEAR_CITY = 1;
|
||||
const ON_CITY = 2;
|
||||
const OUR_NATION = 3;
|
||||
|
||||
static $viewColumns = [
|
||||
'no' => self::NEAR_CITY,
|
||||
'name' => self::NEAR_CITY,
|
||||
'nation' => self::NEAR_CITY,
|
||||
'npc' => self::NEAR_CITY,
|
||||
'injury' => self::NEAR_CITY,
|
||||
'leadership' => self::NEAR_CITY,
|
||||
'strength' => self::NEAR_CITY,
|
||||
'intel' => self::NEAR_CITY,
|
||||
|
||||
'picture' => self::NEAR_CITY,
|
||||
'imgsvr' => self::NEAR_CITY,
|
||||
|
||||
'city' => self::NEAR_CITY,
|
||||
|
||||
'officer_level' => self::NEAR_CITY,
|
||||
'officer_city' => self::NEAR_CITY,
|
||||
'defence_train' => self::OUR_NATION,
|
||||
'crewtype' => self::OUR_NATION,
|
||||
'crew' => self::ON_CITY,
|
||||
'train' => self::OUR_NATION,
|
||||
'atmos' => self::OUR_NATION,
|
||||
];
|
||||
|
||||
static $columnRemap = [
|
||||
'nation' => 'nationID',
|
||||
];
|
||||
|
||||
static $customViewColumns = [
|
||||
'officerLevel' => self::NEAR_CITY,
|
||||
'officerLevelText' => self::NEAR_CITY,
|
||||
'lbonus' => self::NEAR_CITY,
|
||||
'reservedCommand' => self::OUR_NATION,
|
||||
'isOurNation' => self::NEAR_CITY,
|
||||
];
|
||||
|
||||
public function validateArgs(): ?string
|
||||
{
|
||||
$v = new Validator($this->args);
|
||||
$v->rule('int', 'troopID');
|
||||
|
||||
if (!$v->validate()) {
|
||||
return $v->errorStr();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getRequiredSessionMode(): int
|
||||
{
|
||||
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
|
||||
}
|
||||
|
||||
private function getOfficerLevel($rawGeneral)
|
||||
{
|
||||
$level = $rawGeneral['officer_level'];
|
||||
return $level;
|
||||
}
|
||||
|
||||
private function filterCity(array $rawCity, int $showLevel)
|
||||
{
|
||||
$cityID = $rawCity['city'];
|
||||
$db = DB::db();
|
||||
|
||||
$officerList = $db->query(
|
||||
'SELECT no, npc, name, nation, picture, imgsvr FROM general WHERE city = %i AND 2 <= officer_level AND officer_level <= 4',
|
||||
$cityID
|
||||
);
|
||||
|
||||
$filteredCity = [
|
||||
'city' => $cityID,
|
||||
'name' => $rawCity['name'],
|
||||
'level' => $rawCity['level'],
|
||||
'nation' => $rawCity['nation'],
|
||||
'supply' => $rawCity['supply'],
|
||||
'pop_max' => $rawCity['pop_max'],
|
||||
'agri_max' => $rawCity['agri_max'],
|
||||
'comm_max' => $rawCity['comm_max'],
|
||||
'secu_max' => $rawCity['secu_max'],
|
||||
'trade' => $rawCity['trade'],
|
||||
'def_max' => $rawCity['def_max'],
|
||||
'wall_max' => $rawCity['wall_max'],
|
||||
'region' => $rawCity['region'],
|
||||
'officerList' => $officerList,
|
||||
];
|
||||
|
||||
if ($showLevel >= self::ON_CITY) {
|
||||
$filteredCity = array_merge($filteredCity, [
|
||||
'pop' => $rawCity['pop'],
|
||||
'agri' => $rawCity['agri'],
|
||||
'comm' => $rawCity['comm'],
|
||||
'secu' => $rawCity['secu'],
|
||||
'def' => $rawCity['def'],
|
||||
'wall' => $rawCity['wall'],
|
||||
'officer_set' => $rawCity['officer_set'],
|
||||
]);
|
||||
}
|
||||
|
||||
return $filteredCity;
|
||||
}
|
||||
|
||||
private function getGeneralList(int $cityID, int $nationID, int $showLevel)
|
||||
{
|
||||
if ($showLevel == self::FAR_CITY) {
|
||||
return [
|
||||
'column' => [],
|
||||
'list' => []
|
||||
];
|
||||
}
|
||||
$db = DB::db();
|
||||
|
||||
$nationStaticList = getAllNationStaticInfo();
|
||||
|
||||
$rawGeneralList = Util::convertArrayToDict($db->query('SELECT %l from general WHERE city = %i ORDER BY turntime ASC', Util::formatListOfBackticks(array_keys(static::$viewColumns)), $cityID), 'no');
|
||||
$ourNationGeneralIDList = new Set();
|
||||
foreach ($rawGeneralList as $rawGeneral) {
|
||||
if ($rawGeneral['nation'] == $nationID) {
|
||||
$ourNationGeneralIDList->add($rawGeneral['no']);
|
||||
}
|
||||
}
|
||||
|
||||
$reservedCommand = [];
|
||||
$reservedCommandTargetGeneralIDList = [];
|
||||
|
||||
foreach ($rawGeneralList as $rawGeneral) {
|
||||
if ($rawGeneral['nation'] != $nationID) {
|
||||
continue;
|
||||
}
|
||||
if ($rawGeneral['npc'] < 2) {
|
||||
$reservedCommandTargetGeneralIDList[$rawGeneral['no']] = $rawGeneral['no'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($reservedCommandTargetGeneralIDList) {
|
||||
$rawTurnList = $db->query(
|
||||
'SELECT general_id, turn_idx, action, arg, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id asc, turn_idx asc',
|
||||
array_values($reservedCommandTargetGeneralIDList)
|
||||
);
|
||||
|
||||
foreach ($rawTurnList as $rawTurn) {
|
||||
[
|
||||
'general_id' => $generalID,
|
||||
'action' => $action,
|
||||
'arg' => $arg,
|
||||
'brief' => $brief,
|
||||
] = $rawTurn;
|
||||
if (!key_exists($generalID, $reservedCommand)) {
|
||||
$reservedCommand[$generalID] = [];
|
||||
}
|
||||
$reservedCommand[$generalID][] = [
|
||||
'action' => $action,
|
||||
'arg' => $arg,
|
||||
'brief' => $brief
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$specialViewFilter = [
|
||||
'officerLevel' => fn ($rawGeneral) => $this->getOfficerLevel($rawGeneral),
|
||||
'officerLevelText' => fn ($rawGeneral) => getOfficerLevelText($this->getOfficerLevel($rawGeneral), $nationStaticList[$rawGeneral['nation']]['level']),
|
||||
'lbonus' => fn ($rawGeneral) => calcLeadershipBonus($rawGeneral['officer_level'], $nationStaticList[$rawGeneral['nation']]['level']),
|
||||
'reservedCommand' => fn ($rawGeneral) => $reservedCommand[$rawGeneral['no']] ?? null,
|
||||
'isOurNation' => fn ($rawGeneral) => $rawGeneral['nation'] == $nationID,
|
||||
];
|
||||
|
||||
$showFullColumn = $showLevel == self::OUR_NATION || $ourNationGeneralIDList->count() > 0;
|
||||
|
||||
$resultColumns = [];
|
||||
foreach (static::$viewColumns as $column => $reqShowLevel) {
|
||||
if (!$showFullColumn && $reqShowLevel > $showLevel) {
|
||||
continue;
|
||||
}
|
||||
if (key_exists($column, static::$columnRemap)) {
|
||||
$newColumn = static::$columnRemap[$column];
|
||||
if ($newColumn !== null) {
|
||||
$resultColumns[$newColumn] = $column;
|
||||
}
|
||||
} else {
|
||||
$resultColumns[$column] = $column;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (static::$customViewColumns as $column => $reqShowLevel) {
|
||||
if (!$showFullColumn && $reqShowLevel > $showLevel) {
|
||||
continue;
|
||||
}
|
||||
$resultColumns[$column] = $column;
|
||||
}
|
||||
|
||||
$generalList = [];
|
||||
foreach ($rawGeneralList as $rawGeneral) {
|
||||
$item = [];
|
||||
foreach ($resultColumns as $column) {
|
||||
$reqShowLevel = static::$viewColumns[$column];
|
||||
|
||||
if ($rawGeneral['nation'] != $nationID && $reqShowLevel == self::OUR_NATION) {
|
||||
$item[] = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key_exists($column, $specialViewFilter)) {
|
||||
$value = $specialViewFilter[$column]($rawGeneral);
|
||||
} else {
|
||||
$value = $rawGeneral[$column];
|
||||
}
|
||||
$item[] = $value;
|
||||
}
|
||||
|
||||
$generalList[] = $item;
|
||||
}
|
||||
return [
|
||||
'column' => array_keys($resultColumns),
|
||||
'list' => $generalList,
|
||||
];
|
||||
}
|
||||
|
||||
private function calcShowLevel(int $cityID, int $currentCityID, int $nationID, Set $cityList, bool $isSpyPresent): int
|
||||
{
|
||||
$db = DB::db();
|
||||
if ($cityList->contains($currentCityID)) {
|
||||
return self::OUR_NATION;
|
||||
}
|
||||
if ($cityID == $currentCityID) {
|
||||
return self::ON_CITY;
|
||||
}
|
||||
if ($isSpyPresent) {
|
||||
return self::ON_CITY;
|
||||
}
|
||||
|
||||
$existsGeneralID = $db->queryFirstField(
|
||||
'SELECT no FROM general WHERE city = %i AND nation = %i LIMIT 1',
|
||||
$cityID,
|
||||
$nationID
|
||||
);
|
||||
|
||||
if ($existsGeneralID) {
|
||||
return self::ON_CITY;
|
||||
}
|
||||
|
||||
$cityConstObj = CityConst::byID($cityID);
|
||||
|
||||
$nearCityIDList = array_keys($cityConstObj->path);
|
||||
foreach ($nearCityIDList as $nearCityID) {
|
||||
if ($cityList->contains($nearCityID)) {
|
||||
return self::NEAR_CITY;
|
||||
}
|
||||
}
|
||||
|
||||
return self::FAR_CITY;
|
||||
}
|
||||
|
||||
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
|
||||
{
|
||||
increaseRefresh("도시정보", 1);
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$gameStor = \sammo\KVStorage::getStorage($db, 'game_env');
|
||||
$lastExecuted = $gameStor->getValue('turntime');
|
||||
|
||||
$me = $db->queryFirstRow('SELECT con, turntime, belong, city, nation, officer_level, permission, penalty FROM general WHERE owner=%i', $session->getUserID());
|
||||
|
||||
if (key_exists('cityID', $this->args)) {
|
||||
$cityID = (int)$this->args['cityID'];
|
||||
} else {
|
||||
$cityID = $me['city'];
|
||||
}
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
return '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.';
|
||||
}
|
||||
|
||||
$nationID = $me['nation'];
|
||||
$currentCityID = $me['city'];
|
||||
//TODO: 조건 조사
|
||||
|
||||
$cityList = new Set($db->queryFirstColumn('SELECT city FROM city WHERE nation=%i', $nationID));
|
||||
|
||||
$spyList = JSON::decode($db->queryFirstField('SELECT spy FROM nation WHERE nation=%i', $nationID));
|
||||
$showLevel = $this->calcShowLevel($cityID, $currentCityID, $nationID, $cityList, key_exists($cityID, $spyList));
|
||||
|
||||
$rawCity = $db->queryFirstRow('SELECT * FROM city WHERE city=%i', $cityID);
|
||||
$filteredCity = $this->filterCity($rawCity, $showLevel);
|
||||
|
||||
$result = [
|
||||
'result' => true,
|
||||
'lastExcuted' => $lastExecuted,
|
||||
'cityInfo' => $filteredCity,
|
||||
'spyList' => $spyList,
|
||||
'nationCityList' => $cityList->toArray(),
|
||||
'myGeneralID' => $session->generalID,
|
||||
'currentCityID' => $currentCityID,
|
||||
'showLevel' => $showLevel,
|
||||
'cityGeneralList' => $this->getGeneralList($cityID, $nationID, $showLevel)
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ class BuildNationCandidate extends \sammo\BaseAPI
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$gameStor->cacheValues(['opentime', 'turntime']);
|
||||
|
||||
$general = $db->queryFirstRow('SELECT no,name,nation,owner_name,npc,lastrefresh FROM general WHERE owner=%i', $userID);
|
||||
$general = $db->queryFirstRow('SELECT no,name,nation,owner_name,npc FROM general WHERE owner=%i', $userID);
|
||||
|
||||
if (!$general) {
|
||||
return '장수가 없습니다';
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace sammo\API\General;
|
||||
use sammo\DB;
|
||||
use sammo\DummyGeneral;
|
||||
use sammo\Enums\APIRecoveryType;
|
||||
use sammo\Enums\GeneralAccessLogColumn;
|
||||
use sammo\GameConst;
|
||||
use sammo\Session;
|
||||
use sammo\General;
|
||||
@@ -37,7 +38,13 @@ class DieOnPrestart extends \sammo\BaseAPI
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$gameStor->cacheValues(['turnterm', 'opentime', 'turntime', 'year', 'month']);
|
||||
|
||||
$general = $db->queryFirstRow('SELECT no,name,nation,owner_name,npc,lastrefresh 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);
|
||||
$lastRefresh = $db->queryFirstField(
|
||||
'SELECT %b FROM general_access_log WHERE %b = %i',
|
||||
GeneralAccessLogColumn::lastRefresh->value,
|
||||
GeneralAccessLogColumn::generalID->value,
|
||||
$general['no']
|
||||
);
|
||||
|
||||
if (!$general) {
|
||||
return '장수가 없습니다';
|
||||
@@ -55,7 +62,7 @@ class DieOnPrestart extends \sammo\BaseAPI
|
||||
}
|
||||
|
||||
//서버 가오픈시 할 수 있는 행동
|
||||
$targetTime = addTurn($general['lastrefresh'], $gameStor->turnterm, GameConst::$minTurnDieOnPrestart);
|
||||
$targetTime = addTurn($lastRefresh, $gameStor->turnterm, GameConst::$minTurnDieOnPrestart);
|
||||
if ($targetTime > TimeUtil::now()) {
|
||||
$targetTimeShort = substr($targetTime, 0, 19);
|
||||
return "아직 삭제할 수 없습니다. {$targetTimeShort} 부터 가능합니다.";
|
||||
|
||||
@@ -9,7 +9,9 @@ use sammo\DB;
|
||||
use sammo\DTO\VoteInfo;
|
||||
use sammo\Enums\APIRecoveryType;
|
||||
use sammo\Enums\CityColumn;
|
||||
use sammo\Enums\GeneralAccessLogColumn;
|
||||
use sammo\Enums\GeneralColumn;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Enums\RankColumn;
|
||||
use sammo\GameConst;
|
||||
use sammo\General;
|
||||
@@ -173,7 +175,7 @@ class GetFrontInfo extends \sammo\BaseAPI
|
||||
'online_nation', 'online_user_cnt',
|
||||
'year', 'month', 'startyear',
|
||||
'maxgeneral',
|
||||
'conlimit',
|
||||
'refreshLimit',
|
||||
'server_cnt',
|
||||
]);
|
||||
|
||||
@@ -383,7 +385,8 @@ class GetFrontInfo extends \sammo\BaseAPI
|
||||
'specialWar' => $general->getVar(GeneralColumn::special2), // GameObjClassKey;
|
||||
'personal' => $general->getVar(GeneralColumn::personal), // GameObjClassKey;
|
||||
'belong' => $general->getVar(GeneralColumn::belong), // number;
|
||||
'connect' => $general->getVar(GeneralColumn::connect), // number;
|
||||
|
||||
'refreshScoreTotal' => $general->getAccessLogVar(GeneralAccessLogColumn::refreshScoreTotal, 0), // number;
|
||||
|
||||
'officerLevel' => $general->getVar(GeneralColumn::officer_level), // number;
|
||||
'officerLevelText' => getOfficerLevelText($general->getVar(GeneralColumn::officer_level), $rawNation['level']), // string;
|
||||
@@ -400,7 +403,7 @@ class GetFrontInfo extends \sammo\BaseAPI
|
||||
'troop' => $general->getVar(GeneralColumn::troop), // number;
|
||||
//P0 End
|
||||
|
||||
'con' => $general->getVar(GeneralColumn::con), // number;
|
||||
'refreshScore' => $general->getAccessLogVar(GeneralAccessLogColumn::refreshScore, 0), // number;
|
||||
'specage' => $general->getVar(GeneralColumn::specage), // number;
|
||||
'specage2' => $general->getVar(GeneralColumn::specage2), // number;
|
||||
'leadership_exp' => $general->getVar(GeneralColumn::leadership_exp), // number;
|
||||
@@ -531,12 +534,12 @@ class GetFrontInfo extends \sammo\BaseAPI
|
||||
{
|
||||
$generalID = $session->generalID;
|
||||
//NOTE: 이 경우 staticNation 정보를 조회한다.
|
||||
$general = General::createGeneralObjFromDB($generalID);
|
||||
$general = General::createGeneralObjFromDB($generalID, null, GeneralQueryMode::FullWithAccessLog);
|
||||
$nationID = $general->getNationID();
|
||||
$cityID = $general->getCityID();
|
||||
|
||||
$con = checkLimit($general->getVar('con'));
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($general->getAccessLogVar(GeneralAccessLogColumn::refreshScore, 0));
|
||||
if ($limitState >= 2) {
|
||||
return [
|
||||
'result' => false,
|
||||
'reason' => '접속 제한중입니다.',
|
||||
|
||||
@@ -8,6 +8,7 @@ use sammo\Auction;
|
||||
use sammo\CityConst;
|
||||
use sammo\DB;
|
||||
use sammo\Enums\APIRecoveryType;
|
||||
use sammo\Enums\GeneralAccessLogColumn;
|
||||
use sammo\Enums\RankColumn;
|
||||
use sammo\GameConst;
|
||||
use sammo\GameUnitConst;
|
||||
@@ -414,8 +415,6 @@ class Join extends \sammo\BaseAPI
|
||||
'officer_level' => 0,
|
||||
'turntime' => $turntime,
|
||||
'killturn' => 6,
|
||||
'lastconnect' => $now,
|
||||
'lastrefresh' => $now,
|
||||
'crewtype' => GameUnitConst::DEFAULT_CREWTYPE,
|
||||
'makelimit' => 0,
|
||||
'betray' => $betray,
|
||||
@@ -428,6 +427,11 @@ class Join extends \sammo\BaseAPI
|
||||
'special2' => $special2
|
||||
]);
|
||||
$generalID = $db->insertId();
|
||||
$db->insert('general_access_log', [
|
||||
GeneralAccessLogColumn::generalID->value => $generalID,
|
||||
GeneralAccessLogColumn::userID->value => $userID,
|
||||
GeneralAccessLogColumn::lastRefresh->value => $now,
|
||||
]);
|
||||
|
||||
if($blockCustomGeneralName){
|
||||
//XXX: 클래스가 이게 맞나?
|
||||
|
||||
@@ -42,9 +42,12 @@ class GeneralList extends \sammo\BaseAPI
|
||||
$userID = $session->userID;
|
||||
if ($session->isGameLoggedIn()) {
|
||||
increaseRefresh("장수일람", 2);
|
||||
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT refresh_score, turntime FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
return '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.';
|
||||
}
|
||||
} else {
|
||||
@@ -62,7 +65,8 @@ class GeneralList extends \sammo\BaseAPI
|
||||
$session->setReadOnly();
|
||||
|
||||
|
||||
$rawGeneralList = $db->queryAllLists('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,owner_name as ownerName,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general');
|
||||
$rawGeneralList = $db->queryAllLists(
|
||||
'SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,owner_name as ownerName,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,refresh_score_total from `general` LEFT JOIN `general_access_log` ON general.no = general_access_log.general_id');
|
||||
|
||||
$ownerNameList = [];
|
||||
if ($gameStor->isunited) {
|
||||
@@ -73,7 +77,7 @@ class GeneralList extends \sammo\BaseAPI
|
||||
|
||||
$generalList = [];
|
||||
foreach ($rawGeneralList as $rawGeneral) {
|
||||
[$owner, $no, $picture, $imgsvr, $npc, $age, $nation, $special, $special2, $personal, $name, $ownerName, $injury, $leadership, $strength, $intel, $experience, $dedication, $officerLevel, $killturn, $connectCnt] = $rawGeneral;
|
||||
[$owner, $no, $picture, $imgsvr, $npc, $age, $nation, $special, $special2, $personal, $name, $ownerName, $injury, $leadership, $strength, $intel, $experience, $dedication, $officerLevel, $killturn, $refreshScoreTotal] = $rawGeneral;
|
||||
|
||||
if (key_exists($owner, $ownerNameList)) {
|
||||
$ownerName = $ownerNameList[$owner];
|
||||
@@ -104,7 +108,7 @@ class GeneralList extends \sammo\BaseAPI
|
||||
getDed($dedication),
|
||||
getOfficerLevelText($officerLevel, $nationArr['level']),
|
||||
$killturn,
|
||||
$connectCnt
|
||||
$refreshScoreTotal ?: 0,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -129,6 +133,8 @@ class GeneralList extends \sammo\BaseAPI
|
||||
'honorText',
|
||||
'dedLevelText',
|
||||
'officerLevelText',
|
||||
'killturn',
|
||||
'refreshScoreTotal',
|
||||
];
|
||||
|
||||
$result = [
|
||||
|
||||
@@ -148,13 +148,16 @@ class GetHistory extends \sammo\BaseAPI
|
||||
}
|
||||
increaseRefresh("연감", 1);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner = %i', $session->userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT refresh_score, turntime FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner = %i', $session->userID
|
||||
);
|
||||
if (!$me) {
|
||||
return '장수가 사망했습니다.';
|
||||
}
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
return templateLimitMsg($me['turntime']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ class GetOldMessage extends \sammo\BaseAPI
|
||||
|
||||
|
||||
$db = DB::db();
|
||||
$me = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,penalty,permission FROM general WHERE `owner`=%i', $userID);
|
||||
$me = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`picture`,`imgsvr`,penalty,permission FROM general WHERE `owner`=%i', $userID);
|
||||
|
||||
if ($me === null) {
|
||||
return '장수가 사망했습니다.';
|
||||
|
||||
@@ -73,7 +73,7 @@ class GetRecentMessage extends \sammo\BaseAPI
|
||||
|
||||
|
||||
$db = DB::db();
|
||||
$me = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,penalty,permission FROM general WHERE `owner`=%i', $userID);
|
||||
$me = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`picture`,`imgsvr`,penalty,permission FROM general WHERE `owner`=%i', $userID);
|
||||
|
||||
if ($me === null) {
|
||||
return '장수가 사망했습니다.';
|
||||
|
||||
@@ -108,7 +108,7 @@ class SendMessage extends \sammo\BaseAPI
|
||||
$unlimited = new \DateTime('9999-12-31');
|
||||
|
||||
$db = DB::db();
|
||||
$destUser = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,permission,penalty FROM general WHERE `no`=%i', $destGeneralID);
|
||||
$destUser = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`picture`,`imgsvr`,permission,penalty FROM general WHERE `no`=%i', $destGeneralID);
|
||||
|
||||
if (!$destUser) {
|
||||
return '존재하지 않는 유저입니다.';
|
||||
@@ -160,15 +160,18 @@ class SendMessage extends \sammo\BaseAPI
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$me = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,penalty,permission,belong FROM general WHERE `owner`=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT `no`,`name`,`nation`,`officer_level`,`refresh_score`,`picture`,`imgsvr`,penalty,permission,belong FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE `owner`=%i', $userID
|
||||
);
|
||||
|
||||
if (!$me) {
|
||||
$session->logoutGame();
|
||||
return '장수가 없습니다.';
|
||||
}
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
return '접속 제한입니다.';
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace sammo\API\Nation;
|
||||
use ArrayObject;
|
||||
use sammo\DB;
|
||||
use sammo\Enums\APIRecoveryType;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\General;
|
||||
use sammo\Session;
|
||||
use sammo\Util;
|
||||
@@ -44,12 +45,10 @@ class GeneralList extends \sammo\BaseAPI
|
||||
'special2' => 0,
|
||||
'personal' => 0,
|
||||
'belong' => 0,
|
||||
'connect' => 0,
|
||||
|
||||
'troop' => 0,
|
||||
'city' => 0,
|
||||
|
||||
'con' => 1,
|
||||
'specage' => 0,
|
||||
'specage2' => 0,
|
||||
'leadership_exp' => 1,
|
||||
@@ -83,6 +82,11 @@ class GeneralList extends \sammo\BaseAPI
|
||||
|
||||
'owner_name' => 9, //안씀.
|
||||
|
||||
|
||||
//accessLog
|
||||
'refresh_score_total' => 0,
|
||||
'refresh_score' => 1,
|
||||
|
||||
//RANK
|
||||
'warnum' => 1,
|
||||
'killnum' => 1,
|
||||
@@ -95,6 +99,8 @@ class GeneralList extends \sammo\BaseAPI
|
||||
static $columnRemap = [
|
||||
'special' => 'specialDomestic',
|
||||
'special2' => 'specialWar',
|
||||
'refresh_score_total' => 'refreshScoreTotal',
|
||||
'refresh_score' => 'refreshScore',
|
||||
'aux' => null,
|
||||
];
|
||||
|
||||
@@ -143,9 +149,12 @@ class GeneralList extends \sammo\BaseAPI
|
||||
$gameStor = \sammo\KVStorage::getStorage($db, 'game_env');
|
||||
$env = $gameStor->getValues(['year', 'month', 'turntime', 'turnterm', 'autorun_user', 'killturn']);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT con, turntime, belong, nation, officer_level, permission, penalty FROM general WHERE owner=%i', $session->getUserID());
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT refresh_score, turntime, belong, nation, officer_level, permission, penalty FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $session->getUserID()
|
||||
);
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
return '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.';
|
||||
}
|
||||
|
||||
@@ -156,9 +165,18 @@ class GeneralList extends \sammo\BaseAPI
|
||||
|
||||
|
||||
|
||||
[$queryColumns, $rankColumns] = General::mergeQueryColumn(array_keys(static::$viewColumns), 1);
|
||||
[$queryColumns, $rankColumns, $accessLogColumns] = General::mergeQueryColumn(array_keys(static::$viewColumns), GeneralQueryMode::Lite);
|
||||
|
||||
$rawGeneralList = Util::convertArrayToDict($db->query('SELECT %l from general WHERE nation = %i ORDER BY turntime ASC', Util::formatListOfBackticks($queryColumns), $nationID), 'no');
|
||||
$rawGeneralList = Util::convertArrayToDict(
|
||||
$db->query(
|
||||
'SELECT %l, %l from `general` LEFT JOIN general_access_log
|
||||
ON `general`.`no` = general_access_log.general_id WHERE nation = %i ORDER BY turntime ASC',
|
||||
Util::formatListOfBackticks($queryColumns),
|
||||
Util::formatListOfBackticks($accessLogColumns),
|
||||
$nationID
|
||||
),
|
||||
'no'
|
||||
);
|
||||
|
||||
/** @var ArrayObject[] */
|
||||
$troops = [];
|
||||
@@ -179,19 +197,19 @@ class GeneralList extends \sammo\BaseAPI
|
||||
if ($this->permission >= 1 || count($troops)) {
|
||||
$reservedCommandTargetGeneralIDList = [];
|
||||
|
||||
if($this->permission >= 1){
|
||||
if ($this->permission >= 1) {
|
||||
foreach ($rawGeneralList as $rawGeneral) {
|
||||
if ($rawGeneral['npc'] < 2) {
|
||||
$reservedCommandTargetGeneralIDList[$rawGeneral['no']] = $rawGeneral['no'];
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach($troops as $troop){
|
||||
foreach ($troops as $troop) {
|
||||
$reservedCommandTargetGeneralIDList[$troop['id']] = $troop['id'];
|
||||
}
|
||||
|
||||
|
||||
if($reservedCommandTargetGeneralIDList){
|
||||
if ($reservedCommandTargetGeneralIDList) {
|
||||
$rawTurnList = $db->query(
|
||||
'SELECT general_id, turn_idx, action, arg, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id asc, turn_idx asc',
|
||||
array_values($reservedCommandTargetGeneralIDList)
|
||||
@@ -278,11 +296,11 @@ class GeneralList extends \sammo\BaseAPI
|
||||
$resultColumns[$column] = $column;
|
||||
}
|
||||
|
||||
foreach ($troops as $troop){
|
||||
foreach ($troops as $troop) {
|
||||
$troopLeaderID = $troop['id'];
|
||||
$troop['reservedCommand'] = array_map(function($turnObj){
|
||||
$troop['reservedCommand'] = array_map(function ($turnObj) {
|
||||
$brief = $turnObj['brief'];
|
||||
if($brief == '집합'){
|
||||
if ($brief == '집합') {
|
||||
return $brief;
|
||||
}
|
||||
return '-';
|
||||
|
||||
@@ -109,10 +109,12 @@ class GetGeneralLog extends \sammo\BaseAPI
|
||||
$reqTo = $this->args['reqTo'] ?? null;
|
||||
|
||||
$db = DB::db();
|
||||
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,permission,penalty from general where owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no,nation,officer_level,refresh_score,turntime,belong,permission,penalty FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID);
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
return '접속 제한입니다.';
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace sammo\API\Nation;
|
||||
|
||||
use sammo\DB;
|
||||
use sammo\Enums\APIRecoveryType;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\GameConst;
|
||||
use sammo\General;
|
||||
use sammo\KVStorage;
|
||||
@@ -65,7 +66,7 @@ class GetNationInfo extends \sammo\BaseAPI
|
||||
];
|
||||
}
|
||||
|
||||
$generalObj = General::createGeneralObjFromDB($session->generalID, null, 1);
|
||||
$generalObj = General::createGeneralObjFromDB($session->generalID, null, GeneralQueryMode::FullWithoutIAction);
|
||||
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$gameEnv = $gameStor->getValues(['year', 'month', 'startyear']);
|
||||
|
||||
@@ -6,6 +6,7 @@ use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\DB;
|
||||
use sammo\Enums\APIRecoveryType;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\GameConst;
|
||||
use sammo\General;
|
||||
use sammo\Json;
|
||||
@@ -39,12 +40,15 @@ class GetReservedCommand extends \sammo\BaseAPI
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$userID = $session->userID;
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,penalty,permission FROM general WHERE owner=%i', $userID);
|
||||
$me = $db->queryFirstRow(
|
||||
'SELECT no,nation,officer_level,refresh_score,turntime,belong,penalty,permission FROM `general`
|
||||
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
|
||||
);
|
||||
|
||||
$nationLevel = $db->queryFirstField('SELECT level FROM nation WHERE nation = %i', $me['nation']);
|
||||
$nationID = $me['nation'];
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
$limitState = checkLimit($me['refresh_score']);
|
||||
if ($limitState >= 2) {
|
||||
return "접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 갱신 가능 시각 : {$me['turntime']})";
|
||||
}
|
||||
|
||||
@@ -59,7 +63,7 @@ class GetReservedCommand extends \sammo\BaseAPI
|
||||
|
||||
$generals = [];
|
||||
foreach ($db->query('SELECT no,name,turntime,npc,city,nation,officer_level FROM general WHERE nation = %i AND officer_level >= 5', $nationID) as $rawGeneral) {
|
||||
$generals[$rawGeneral['officer_level']] = new General($rawGeneral, null, null, null, $year, $month, false);
|
||||
$generals[$rawGeneral['officer_level']] = new General($rawGeneral, null, null, null, null, $year, $month, false);
|
||||
}
|
||||
|
||||
$nationTurnList = [];
|
||||
@@ -109,7 +113,7 @@ class GetReservedCommand extends \sammo\BaseAPI
|
||||
];
|
||||
}
|
||||
|
||||
$generalObj = General::createGeneralObjFromDB($session->generalID);
|
||||
$generalObj = General::createGeneralObjFromDB($session->generalID, null, GeneralQueryMode::FullWithoutIAction);
|
||||
|
||||
|
||||
return [
|
||||
|
||||
@@ -6,6 +6,7 @@ use DateTimeInterface;
|
||||
use sammo\DB;
|
||||
use sammo\DTO\VoteComment;
|
||||
use sammo\Enums\APIRecoveryType;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\General;
|
||||
use sammo\Session;
|
||||
use sammo\TimeUtil;
|
||||
@@ -40,7 +41,7 @@ class AddComment extends \sammo\BaseAPI
|
||||
$text = mb_substr($this->args['text'], 0, 200);
|
||||
|
||||
$generalID = $session->generalID;
|
||||
$general = General::createGeneralObjFromDB($generalID, [], 0);
|
||||
$general = General::createGeneralObjFromDB($generalID, null, GeneralQueryMode::Core);
|
||||
$generalName = $general->getName();
|
||||
$nationID = $general->getNationID();
|
||||
$nationName = $general->getStaticNation()['name'];
|
||||
|
||||
@@ -6,6 +6,7 @@ use DateTimeInterface;
|
||||
use sammo\DB;
|
||||
use sammo\DTO\VoteInfo;
|
||||
use sammo\Enums\APIRecoveryType;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\General;
|
||||
use sammo\Json;
|
||||
use sammo\KVStorage;
|
||||
@@ -105,7 +106,7 @@ class Vote extends \sammo\BaseAPI
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$voteReward = $gameStor->getValue('develcost') * 5;
|
||||
|
||||
$general = General::createGeneralObjFromDB($generalID, ['gold', 'horse', 'weapon', 'book', 'item', 'npc', 'imgsvr', 'picture', 'aux'], 2);
|
||||
$general = General::createGeneralObjFromDB($generalID, ['gold', 'horse', 'weapon', 'book', 'item', 'npc', 'imgsvr', 'picture', 'aux'], GeneralQueryMode::Lite);
|
||||
$general->increaseVar('gold', $voteReward);
|
||||
$uniqueRng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
|
||||
UniqueConst::$hiddenSeed,
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
namespace sammo\ActionCrewType;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class None implements iAction{
|
||||
use \sammo\DefaultAction;
|
||||
|
||||
protected $id = -1;
|
||||
protected $name = '-';
|
||||
protected $info = '';
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
namespace sammo\ActionCrewType;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class che_성벽선제 implements iAction{
|
||||
use \sammo\DefaultAction;
|
||||
|
||||
protected $name = '성벽선제';
|
||||
protected $info = '전투 가능한 성벽이라면 선제공격을 합니다.';
|
||||
|
||||
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
|
||||
{
|
||||
if($statName == 'cityBattleOrder'){
|
||||
// battleOrder는 스탯과 유사한 수치를 가지므로, 아주 충분히 높은값을 설정한다.
|
||||
return 10000;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -25,15 +25,15 @@ class che_병가 extends \sammo\BaseNation{
|
||||
if($varType == 'score') return $value * 0.9;
|
||||
if($varType == 'cost') return $value * 1.2;
|
||||
}
|
||||
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onCalcNationalIncome(string $type, $amount):int{
|
||||
if($type == 'pop' && $amount > 0){
|
||||
return Util::toInt($amount * 0.8);
|
||||
return $amount * 0.8;
|
||||
}
|
||||
|
||||
|
||||
return $amount;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ namespace sammo;
|
||||
use Ds\Map;
|
||||
use sammo\DTO\BettingInfo;
|
||||
use sammo\DTO\BettingItem;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Enums\RankColumn;
|
||||
|
||||
class Betting
|
||||
@@ -243,7 +244,7 @@ class Betting
|
||||
return $this->_calcRewardExclusive($winnerType);
|
||||
}
|
||||
|
||||
if ($this->info->isExlusive) {
|
||||
if ($this->info->isExclusive) {
|
||||
return $this->_calcRewardExclusive($winnerType);
|
||||
}
|
||||
//아래는 2개 이상, 복합 보상 옵션
|
||||
@@ -401,7 +402,7 @@ class Betting
|
||||
$userLogger->flush();
|
||||
}
|
||||
} else {
|
||||
$generalList = General::createGeneralObjListFromDB(array_unique(Util::squeezeFromArray($rewardList, 'generalID')), ['gold', 'npc', 'betgold'], 1);
|
||||
$generalList = General::createGeneralObjListFromDB(array_unique(Util::squeezeFromArray($rewardList, 'generalID')), ['gold', 'npc', 'betgold'], GeneralQueryMode::Lite);
|
||||
foreach ($rewardList as $rewardItem) {
|
||||
$gambler = $generalList[$rewardItem['generalID']];
|
||||
$reward = Util::round($rewardItem['amount']);
|
||||
|
||||
@@ -21,7 +21,7 @@ use function \sammo\getNationStaticInfo;
|
||||
use function sammo\tryUniqueItemLottery;
|
||||
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
|
||||
class che_등용 extends Command\GeneralCommand
|
||||
{
|
||||
@@ -77,7 +77,7 @@ class che_등용 extends Command\GeneralCommand
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['nation', 'experience', 'dedication'], 0);
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['nation', 'experience', 'dedication'], GeneralQueryMode::Lite);
|
||||
$this->setDestGeneral($destGeneral);
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
@@ -68,7 +68,7 @@ class che_등용수락 extends Command\GeneralCommand{
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null, 2);
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null);
|
||||
$this->setDestGeneral($destGeneral);
|
||||
$this->setDestNation($this->arg['destNationID'], ['gennum', 'scout']);
|
||||
|
||||
@@ -77,6 +77,7 @@ class che_등용수락 extends Command\GeneralCommand{
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::ReqEnvValue('join_mode', '!=', 'onlyRandom', '랜덤 임관만 가능합니다'),
|
||||
ConstraintHelper::ExistsDestNation(),
|
||||
ConstraintHelper::BeNeutral(),
|
||||
ConstraintHelper::AllowJoinDestNation($relYear),
|
||||
ConstraintHelper::ReqDestNationValue('level', '국가규모', '>', 0, '방랑군에는 임관할 수 없습니다.'),
|
||||
ConstraintHelper::DifferentDestNation(),
|
||||
|
||||
@@ -21,6 +21,7 @@ use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
class che_물자조달 extends Command\GeneralCommand{
|
||||
static protected $actionName = '물자조달';
|
||||
static protected $debuffFront = 0.5;
|
||||
|
||||
protected function argTest():bool{
|
||||
$this->arg = null;
|
||||
@@ -95,10 +96,32 @@ class che_물자조달 extends Command\GeneralCommand{
|
||||
$score = $general->onCalcDomestic('조달', 'score', $score);
|
||||
|
||||
$score = Util::round($score);
|
||||
$scoreText = number_format($score, 0);
|
||||
|
||||
$exp = $score * 0.7 / 3;
|
||||
$ded = $score * 1.0 / 3;
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
if(in_array($this->city['front'], [1, 3])){
|
||||
$debuffFront = static::$debuffFront;
|
||||
|
||||
if($this->nation['capital'] == $this->city['city']){
|
||||
$gameStor = \sammo\KVStorage::getStorage($db, 'game_env');
|
||||
[$year, $startYear] = $gameStor->getValuesAsArray(['year', 'startyear']);
|
||||
$relYear = $year - $startYear;
|
||||
|
||||
if($relYear < 25){
|
||||
$debuffScale = Util::clamp($relYear - 5, 0, 20) * 0.05;
|
||||
$debuffFront = ($debuffScale * $debuffFront) + (1 - $debuffScale);
|
||||
}
|
||||
}
|
||||
|
||||
$score *= $debuffFront;
|
||||
}
|
||||
|
||||
$scoreText = number_format($score, 0);
|
||||
|
||||
|
||||
if($pick == 'fail'){
|
||||
$logger->pushGeneralActionLog("조달을 <span class='ev_failed'>실패</span>하여 {$resName}을 <C>$scoreText</> 조달했습니다. <1>$date</>");
|
||||
}
|
||||
@@ -109,9 +132,6 @@ class che_물자조달 extends Command\GeneralCommand{
|
||||
$logger->pushGeneralActionLog("{$resName}을 <C>$scoreText</> 조달했습니다. <1>$date</>");
|
||||
}
|
||||
|
||||
$exp = $score * 0.7 / 3;
|
||||
$ded = $score * 1.0 / 3;
|
||||
|
||||
$incStat = $rng->choiceUsingWeight([
|
||||
'leadership_exp'=>$general->getLeadership(false, false, false, false),
|
||||
'strength_exp'=>$general->getStrength(false, false, false, false),
|
||||
|
||||
@@ -185,8 +185,21 @@ class che_상업투자 extends Command\GeneralCommand{
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} 하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
|
||||
if(in_array($this->city['front'], [1, 3]) && $this->nation['capital'] != $this->city['city']){
|
||||
$score *= static::$debuffFront;
|
||||
if(in_array($this->city['front'], [1, 3])){
|
||||
$debuffFront = static::$debuffFront;
|
||||
|
||||
if($this->nation['capital'] == $this->city['city']){
|
||||
$gameStor = \sammo\KVStorage::getStorage($db, 'game_env');
|
||||
[$year, $startYear] = $gameStor->getValuesAsArray(['year', 'startyear']);
|
||||
$relYear = $year - $startYear;
|
||||
|
||||
if($relYear < 25){
|
||||
$debuffScale = Util::clamp($relYear - 5, 0, 20) * 0.05;
|
||||
$debuffFront = ($debuffScale * $debuffFront) + (1 - $debuffScale);
|
||||
}
|
||||
}
|
||||
|
||||
$score *= $debuffFront;
|
||||
}
|
||||
|
||||
//NOTE: 내정량 상승시 초과 가능?
|
||||
|
||||
@@ -19,6 +19,7 @@ use function\sammo\tryUniqueItemLottery;
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Enums\InheritanceKey;
|
||||
|
||||
class che_선양 extends Command\GeneralCommand
|
||||
@@ -65,7 +66,7 @@ class che_선양 extends Command\GeneralCommand
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'nation'], 1);
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'nation'], GeneralQueryMode::Lite);
|
||||
$this->setDestGeneral($destGeneral);
|
||||
|
||||
$this->fullConditionConstraints = [
|
||||
|
||||
@@ -17,6 +17,7 @@ use function \sammo\tryUniqueItemLottery;
|
||||
use function \sammo\getNationStaticInfo;
|
||||
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Enums\InheritanceKey;
|
||||
|
||||
class che_장수대상임관 extends Command\GeneralCommand{
|
||||
@@ -83,7 +84,7 @@ class che_장수대상임관 extends Command\GeneralCommand{
|
||||
protected function initWithArg()
|
||||
{
|
||||
$destGeneralID = $this->arg['destGeneralID'];
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['nation'], 0);
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['nation'], GeneralQueryMode::Lite);
|
||||
$this->setDestGeneral($destGeneral);
|
||||
$this->setDestNation($this->destGeneralObj->getVar('nation'), ['gennum', 'scout']);
|
||||
|
||||
|
||||
@@ -87,6 +87,12 @@ class che_전투특기초기화 extends Command\GeneralCommand{
|
||||
$yearMonth = Util::joinYearMonth($env['year'], $env['month']);
|
||||
$oldSpecialList = $general->getAuxVar($oldTypeKey)??[];
|
||||
$oldSpecialList[] = $general->getVar(static::$specialType);
|
||||
if(static::$specialType == 'special' && count($oldSpecialList) == count(GameConst::$availableSpecialDomestic)){
|
||||
$oldSpecialList = [$general->getVar(static::$specialType)];
|
||||
}
|
||||
else if(static::$specialType == 'special2' && count($oldSpecialList) == count(GameConst::$availableSpecialWar)){
|
||||
$oldSpecialList = [$general->getVar(static::$specialType)];
|
||||
}
|
||||
$general->setAuxVar($oldTypeKey, $oldSpecialList);
|
||||
|
||||
$general->setVar(static::$specialType, 'None');
|
||||
|
||||
@@ -15,6 +15,7 @@ use \sammo\Command;
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
|
||||
use function sammo\tryUniqueItemLottery;
|
||||
|
||||
@@ -86,7 +87,7 @@ class che_증여 extends Command\GeneralCommand
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'rice', 'nation'], 1);
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'rice', 'nation'], GeneralQueryMode::Lite);
|
||||
$this->setDestGeneral($destGeneral);
|
||||
|
||||
$this->fullConditionConstraints = [
|
||||
|
||||
@@ -15,6 +15,7 @@ use function \sammo\searchDistance;
|
||||
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\CityConst;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Enums\RankColumn;
|
||||
use sammo\RandUtil;
|
||||
|
||||
@@ -268,7 +269,7 @@ class che_화계 extends Command\GeneralCommand
|
||||
$destCityGeneralList = [];
|
||||
|
||||
$cityGeneralID = $db->queryFirstColumn('SELECT no FROM general WHERE city = %i AND nation = %i', $destCityID, $destNationID);
|
||||
$destCityGeneralList = General::createGeneralObjListFromDB($cityGeneralID, ['name', 'city', 'nation', 'officer_level', 'leadership', 'horse', 'strength', 'weapon', 'intel', 'book', 'item', 'last_turn', 'injury', 'special', 'special2', 'injury', 'crewtype', 'crew', 'atmos', 'train'], 2);
|
||||
$destCityGeneralList = General::createGeneralObjListFromDB($cityGeneralID, ['name', 'city', 'nation', 'officer_level', 'leadership', 'horse', 'strength', 'weapon', 'intel', 'book', 'item', 'last_turn', 'injury', 'special', 'special2', 'injury', 'crewtype', 'crew', 'atmos', 'train']);
|
||||
foreach ($destCityGeneralList as &$destCityGeneral) {
|
||||
$destCityGeneral->setRawCity($this->destCity);
|
||||
unset($destCityGeneral);
|
||||
|
||||
@@ -19,6 +19,7 @@ use function \sammo\GetImageURL;
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Enums\MessageType;
|
||||
|
||||
class che_몰수 extends Command\NationCommand
|
||||
@@ -91,7 +92,7 @@ class che_몰수 extends Command\NationCommand
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'rice', 'npc', 'nation', 'imgsvr', 'picture'], 1);
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'rice', 'npc', 'nation', 'imgsvr', 'picture'], GeneralQueryMode::Lite);
|
||||
$this->setDestGeneral($destGeneral);
|
||||
|
||||
$env = $this->env;
|
||||
@@ -173,7 +174,7 @@ class che_몰수 extends Command\NationCommand
|
||||
$npcTexts = [
|
||||
'몰수를 하다니... 이것이 윗사람이 할 짓이란 말입니까...',
|
||||
'사유재산까지 몰수해가면서 이 나라가 잘 될거라 믿습니까? 정말 이해할 수가 없군요...',
|
||||
'내 돈 내놔라! 내 돈! 몰수가 왠 말이냐!',
|
||||
'내 돈 내놔라! 내 돈! 몰수가 웬 말이냐!',
|
||||
'몰수해간 내 자금... 언젠가 몰래 다시 빼내올 것이다...',
|
||||
'몰수로 인한 사기 저하는 몰수로 얻은 물자보다 더 손해란걸 모른단 말인가!'
|
||||
];
|
||||
@@ -205,8 +206,10 @@ class che_몰수 extends Command\NationCommand
|
||||
$resKey => $db->sqleval('%b + %i', $resKey, $amount)
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
$destGeneral->getLogger()->pushGeneralActionLog("{$resName} {$amountText}을 몰수 당했습니다.", ActionLogger::PLAIN);
|
||||
$logger->pushGeneralActionLog("<Y>{$destGeneral->getName()}</>에게서 {$resName} <C>$amountText</>을 몰수했습니다. <1>$date</>");
|
||||
$josaUl = JosaUtil::pick($amountText, '을');
|
||||
|
||||
$destGeneral->getLogger()->pushGeneralActionLog("{$resName} {$amountText}{$josaUl} 몰수 당했습니다.", ActionLogger::PLAIN);
|
||||
$logger->pushGeneralActionLog("<Y>{$destGeneral->getName()}</>에게서 {$resName} <C>$amountText</>{$josaUl} 몰수했습니다. <1>$date</>");
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->applyDB($db);
|
||||
|
||||
@@ -215,14 +215,16 @@ class che_물자원조 extends Command\NationCommand
|
||||
$chiefLogger->flush();
|
||||
}
|
||||
|
||||
$logger->pushGeneralHistoryLog("<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원");
|
||||
$logger->pushNationalHistoryLog("<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원");
|
||||
$josaUlRiceAmount = JosaUtil::pick($riceAmountText, '을');
|
||||
|
||||
$logger->pushGeneralHistoryLog("<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>{$josaUlRiceAmount} 지원");
|
||||
$logger->pushNationalHistoryLog("<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>{$josaUlRiceAmount} 지원");
|
||||
$logger->pushGlobalHistoryLog("<Y><b>【원조】</b></><D><b>{$nationName}</b></>에서 <D><b>{$destNationName}</b></>{$josaRo} 물자를 지원합니다");
|
||||
|
||||
$logger->pushGeneralActionLog($broadcastMessage);
|
||||
$logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>{$josaRo} 물자를 지원합니다. <1>$date</>", ActionLogger::PLAIN);
|
||||
|
||||
$destBroadcastMessage = $broadcastMessage = "<D><b>{$nationName}</b></>에서 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 원조했습니다.";
|
||||
$destBroadcastMessage = $broadcastMessage = "<D><b>{$nationName}</b></>에서 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>{$josaUlRiceAmount} 원조했습니다.";
|
||||
$destChiefList = $db->queryFirstColumn('SELECT no FROM general WHERE officer_level >= 5 AND nation = %i', $destNationID);
|
||||
foreach ($destChiefList as $destChiefID) {
|
||||
$destChiefLogger = new ActionLogger($destChiefID, $nationID, $year, $month);
|
||||
@@ -232,7 +234,7 @@ class che_물자원조 extends Command\NationCommand
|
||||
|
||||
$josaRoSrc = JosaUtil::pick($nationName, '로');
|
||||
$destNationLogger = new ActionLogger(0, $destNationID, $year, $month);
|
||||
$destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaRoSrc}부터 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원 받음");
|
||||
$destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaRoSrc}부터 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>{$josaUlRiceAmount} 지원 받음");
|
||||
|
||||
$destNationStor = KVStorage::getStorage(DB::db(), $destNationID, 'nation_env');
|
||||
$destRecvAssist = $destNationStor->getValue('recv_assist') ?? [];
|
||||
|
||||
@@ -21,6 +21,7 @@ use function \sammo\cutTurn;
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
|
||||
class che_발령 extends Command\NationCommand
|
||||
{
|
||||
@@ -71,7 +72,7 @@ class che_발령 extends Command\NationCommand
|
||||
{
|
||||
$this->setDestCity($this->arg['destCityID']);
|
||||
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null, 1);
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null, GeneralQueryMode::Lite);
|
||||
$this->setDestGeneral($destGeneral);
|
||||
|
||||
if ($this->arg['destGeneralID'] == $this->getGeneral()->getID()) {
|
||||
|
||||
@@ -20,6 +20,7 @@ use function \sammo\getNationStaticInfo;
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Json;
|
||||
use sammo\KVStorage;
|
||||
use sammo\RandUtil;
|
||||
@@ -103,7 +104,7 @@ class che_불가침수락 extends Command\NationCommand
|
||||
$env = $this->env;
|
||||
$relYear = $env['year'] - $env['startyear'];
|
||||
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], [], 1);
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null, GeneralQueryMode::Lite);
|
||||
$this->setDestGeneral($destGeneral);
|
||||
$this->setDestNation($this->arg['destNationID']);
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@ class che_불가침제의 extends Command\NationCommand
|
||||
$nation = $this->nation;
|
||||
$nationID = $nation['nation'];
|
||||
$nationName = $nation['name'];
|
||||
$josaRo = JosaUtil::pick($nationName, '로');
|
||||
|
||||
$destNation = $this->destNation;
|
||||
$destNationID = $destNation['nation'];
|
||||
@@ -176,7 +177,7 @@ class che_불가침제의 extends Command\NationCommand
|
||||
$logger = $general->getLogger();
|
||||
$destLogger = new ActionLogger(0, $destNationID, $env['year'], $env['month']);
|
||||
|
||||
$logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>으로 불가침 제의 서신을 보냈습니다.<1>$date</>");
|
||||
$logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>{$josaRo} 불가침 제의 서신을 보냈습니다.<1>$date</>");
|
||||
|
||||
// 상대에게 발송
|
||||
$src = new MessageTarget(
|
||||
|
||||
@@ -20,6 +20,7 @@ use function \sammo\getNationStaticInfo;
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\RandUtil;
|
||||
|
||||
class che_불가침파기수락 extends Command\NationCommand
|
||||
@@ -77,7 +78,7 @@ class che_불가침파기수락 extends Command\NationCommand
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], [], 1);
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null, GeneralQueryMode::Lite);
|
||||
$this->setDestGeneral($destGeneral);
|
||||
$this->setDestNation($this->arg['destNationID']);
|
||||
|
||||
|
||||
@@ -122,11 +122,12 @@ class che_불가침파기제의 extends Command\NationCommand{
|
||||
$destNation = $this->destNation;
|
||||
$destNationID = $destNation['nation'];
|
||||
$destNationName = $destNation['name'];
|
||||
$josaRo = JosaUtil::pick($destNationName, '로');
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$destLogger = new ActionLogger(0, $destNationID, $env['year'], $env['month']);
|
||||
|
||||
$logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>으로 불가침 파기 제의 서신을 보냈습니다.<1>$date</>");
|
||||
$logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>{$josaRo} 불가침 파기 제의 서신을 보냈습니다.<1>$date</>");
|
||||
|
||||
// 상대에게 발송
|
||||
$src = new MessageTarget(
|
||||
|
||||
@@ -22,6 +22,7 @@ use function \sammo\getNationStaticInfo;
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
|
||||
class che_종전수락 extends Command\NationCommand
|
||||
{
|
||||
@@ -86,7 +87,7 @@ class che_종전수락 extends Command\NationCommand
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], [], 1);
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null, GeneralQueryMode::Lite);
|
||||
$this->setDestGeneral($destGeneral);
|
||||
$this->setDestNation($this->arg['destNationID']);
|
||||
|
||||
|
||||
@@ -120,11 +120,12 @@ class che_종전제의 extends Command\NationCommand{
|
||||
$destNation = $this->destNation;
|
||||
$destNationID = $destNation['nation'];
|
||||
$destNationName = $destNation['name'];
|
||||
$josaRo = JosaUtil::pick($destNationName, '로');
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$destLogger = new ActionLogger(0, $destNationID, $env['year'], $env['month']);
|
||||
|
||||
$logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>으로 종전 제의 서신을 보냈습니다.<1>$date</>");
|
||||
$logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>{$josaRo} 종전 제의 서신을 보냈습니다.<1>$date</>");
|
||||
|
||||
// 상대에게 발송
|
||||
$src = new MessageTarget(
|
||||
|
||||
@@ -15,6 +15,7 @@ use \sammo\Command;
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
|
||||
class che_포상 extends Command\NationCommand
|
||||
{
|
||||
@@ -81,7 +82,7 @@ class che_포상 extends Command\NationCommand
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'rice', 'nation'], 1);
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'rice', 'nation'], GeneralQueryMode::Lite);
|
||||
$this->setDestGeneral($destGeneral);
|
||||
|
||||
if($this->arg['destGeneralID'] == $this->getGeneral()->getID()){
|
||||
@@ -167,8 +168,10 @@ class che_포상 extends Command\NationCommand
|
||||
$resKey => $db->sqleval('%b - %i', $resKey, $amount)
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
$destGeneral->getLogger()->pushGeneralActionLog("{$resName} <C>{$amountText}</>을 포상으로 받았습니다.", ActionLogger::PLAIN);
|
||||
$logger->pushGeneralActionLog("<Y>{$destGeneral->getName()}</>에게 {$resName} <C>$amountText</>을 수여했습니다. <1>$date</>");
|
||||
$josaUl = JosaUtil::pick($amountText, '을');
|
||||
|
||||
$destGeneral->getLogger()->pushGeneralActionLog("{$resName} <C>{$amountText}</>{$josaUl} 포상으로 받았습니다.", ActionLogger::PLAIN);
|
||||
$logger->pushGeneralActionLog("<Y>{$destGeneral->getName()}</>에게 {$resName} <C>$amountText</>{$josaUl} 수여했습니다. <1>$date</>");
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->applyDB($db);
|
||||
|
||||
@@ -15,6 +15,7 @@ use \sammo\{
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Event\Action;
|
||||
|
||||
class che_필사즉생 extends Command\NationCommand{
|
||||
@@ -94,7 +95,7 @@ class che_필사즉생 extends Command\NationCommand{
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <M>필사즉생</>을 발동하였습니다.";
|
||||
|
||||
$targetGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach(General::createGeneralObjListFromDB($targetGeneralList, ['train', 'atmos'], 1) as $targetGeneral){
|
||||
foreach(General::createGeneralObjListFromDB($targetGeneralList, ['train', 'atmos'], GeneralQueryMode::Lite) as $targetGeneral){
|
||||
$targetGeneral->getLogger()->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
if($targetGeneral->getVar('train') < 100){
|
||||
$targetGeneral->setVar('train', 100);
|
||||
|
||||
@@ -39,7 +39,7 @@ class ReqGeneralCrewMargin extends Constraint{
|
||||
|
||||
//XXX: 왜 General -> obj -> General 변환을 하고 있나?
|
||||
//FIXME: RankVar, city에 따라 통솔이 바뀐다면 이 부분에 문제가 발생.
|
||||
$generalObj = new General($this->general, null, null, null, null, null, true);
|
||||
$generalObj = new General($this->general, null, null, null, null, null, null, true);
|
||||
|
||||
if($reqCrewType->id != $generalObj->getCrewTypeObj()->id){
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\DTO;
|
||||
|
||||
use LDTO\Attr\Convert;
|
||||
use LDTO\Attr\NullIsUndefined;
|
||||
use LDTO\Attr\RawName;
|
||||
use LDTO\Converter\DateTimeConverter;
|
||||
|
||||
class GeneralAccessLog extends \LDTO\DTO
|
||||
{
|
||||
public function __construct(
|
||||
#[NullIsUndefined]
|
||||
public ?int $id,
|
||||
|
||||
#[RawName('general_id')]
|
||||
public int $generalID,
|
||||
|
||||
#[RawName('user_id')]
|
||||
public ?int $userID,
|
||||
|
||||
#[RawName('last_refresh')]
|
||||
#[Convert(DateTimeConverter::class)]
|
||||
public \DateTimeImmutable $lastRefresh,
|
||||
|
||||
public int $refresh,
|
||||
|
||||
#[RawName('refresh_total')]
|
||||
public int $refreshTotal,
|
||||
|
||||
#[RawName('refresh_score')]
|
||||
public int $refreshScore,
|
||||
|
||||
#[RawName('refresh_score_total')]
|
||||
public int $refreshScoreTotal,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Enums\MessageType;
|
||||
|
||||
class DiplomaticMessage extends Message{
|
||||
@@ -75,7 +76,7 @@ class DiplomaticMessage extends Message{
|
||||
|
||||
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
|
||||
|
||||
$destGeneralObj = General::createGeneralObjFromDB($this->dest->generalID, ['picture', 'imgsvr', 'aux'], 1);
|
||||
$destGeneralObj = General::createGeneralObjFromDB($this->dest->generalID, ['picture', 'imgsvr', 'aux'], GeneralQueryMode::Lite);
|
||||
|
||||
$commandObj = buildNationCommandClass('che_불가침수락', $destGeneralObj, $gameStor->getAll(true), new LastTurn(), [
|
||||
'destNationID'=>$this->src->nationID,
|
||||
@@ -99,7 +100,7 @@ class DiplomaticMessage extends Message{
|
||||
protected function cancelNA(){
|
||||
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
|
||||
|
||||
$destGeneralObj = General::createGeneralObjFromDB($this->dest->generalID, ['picture', 'imgsvr', 'aux'], 1);
|
||||
$destGeneralObj = General::createGeneralObjFromDB($this->dest->generalID, ['picture', 'imgsvr', 'aux'], GeneralQueryMode::Lite);
|
||||
|
||||
$commandObj = buildNationCommandClass('che_불가침파기수락', $destGeneralObj, $gameStor->getAll(true), new LastTurn(), [
|
||||
'destNationID'=>$this->src->nationID,
|
||||
@@ -121,7 +122,7 @@ class DiplomaticMessage extends Message{
|
||||
protected function stopWar(){
|
||||
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
|
||||
|
||||
$destGeneralObj = General::createGeneralObjFromDB($this->dest->generalID, ['picture', 'imgsvr', 'aux'], 1);
|
||||
$destGeneralObj = General::createGeneralObjFromDB($this->dest->generalID, ['picture', 'imgsvr', 'aux'], GeneralQueryMode::Lite);
|
||||
|
||||
$commandObj = buildNationCommandClass('che_종전수락', $destGeneralObj, $gameStor->getAll(true), new LastTurn(), [
|
||||
'destNationID'=>$this->src->nationID,
|
||||
|
||||
@@ -37,13 +37,25 @@ class DummyGeneral extends General
|
||||
}
|
||||
}
|
||||
|
||||
public function setCrewType(?GameUnitDetail $crewType){
|
||||
$this->crewType = $crewType;
|
||||
}
|
||||
|
||||
public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
|
||||
{
|
||||
//crewType에만 반응하자
|
||||
if($this->crewType !== null){
|
||||
return $this->crewType->getBattleInitSkillTriggerList($unit);
|
||||
}
|
||||
return new WarUnitTriggerCaller();
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
|
||||
{
|
||||
//crewType에만 반응하자
|
||||
if($this->crewType !== null){
|
||||
return $this->crewType->getBattlePhaseSkillTriggerList($unit);
|
||||
}
|
||||
return new WarUnitTriggerCaller();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Enums;
|
||||
|
||||
enum GeneralAccessLogColumn: string {
|
||||
case id = 'id';
|
||||
case generalID = 'general_id';
|
||||
case userID = 'user_id';
|
||||
case lastRefresh = 'last_refresh';
|
||||
case refresh = 'refresh'; //순간 갱신 횟수(00:00에 초기화)
|
||||
case refreshTotal = 'refresh_total'; //누적 갱신 횟수
|
||||
case refreshScore = 'refresh_score'; //순간 벌점(턴 시간에 초기화)
|
||||
case refreshScoreTotal = 'refresh_score_total'; //누적 벌점(지속적으로 감소, refreshScoreTotal <= refreshTotal)
|
||||
}
|
||||
@@ -15,11 +15,6 @@ enum GeneralColumn: string{
|
||||
case bornyear = 'bornyear';
|
||||
case deadyear = 'deadyear';
|
||||
case newmsg = 'newmsg';
|
||||
case con = 'con';
|
||||
case connect = 'connect';
|
||||
case refresh = 'refresh';
|
||||
case logcnt = 'logcnt';
|
||||
case refcnt = 'refcnt';
|
||||
case picture = 'picture';
|
||||
case imgsvr = 'imgsvr';
|
||||
case name = 'name';
|
||||
@@ -58,8 +53,6 @@ enum GeneralColumn: string{
|
||||
case recent_war = 'recent_war';
|
||||
case makelimit = 'makelimit';
|
||||
case killturn = 'killturn';
|
||||
case lastconnect = 'lastconnect';
|
||||
case lastrefresh = 'lastrefresh';
|
||||
case ip = 'ip';
|
||||
case block = 'block';
|
||||
case dedlevel = 'dedlevel';
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Enums;
|
||||
|
||||
// mergeQueryColumn, createGeneralObjListFromDB, createGeneralObjFromDB 호출시 column 특수 모드 지정
|
||||
enum GeneralQueryMode: int
|
||||
{
|
||||
/** 장수 식별을 위한 최소한의 정보, logger 초기화 없음 */
|
||||
case Core = 0;
|
||||
/** 게임 내에서 필수 이벤트 처리를 위한 정보, iAction 제외 */
|
||||
case Lite = 1;
|
||||
/** 게임 내 모든 이벤트 처리를 위한 정보, iAction 제외 */
|
||||
case FullWithoutIAction = 2;
|
||||
/** 게임 내 모든 이벤트 처리를 위한 정보, iAction 포함 */
|
||||
case Full = 3;
|
||||
/** 접속 정보를 포함한 모든 정보 */
|
||||
case FullWithAccessLog = 4;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
namespace sammo\Enums;
|
||||
|
||||
enum TableName: string {
|
||||
case general = 'general';
|
||||
case generalTurn = 'general_turn';
|
||||
case generalAccessLog = 'general_access_log';
|
||||
|
||||
case userRecord = 'user_record';
|
||||
|
||||
case nation = 'nation';
|
||||
case nationTurn = 'nation_turn';
|
||||
case nationEnv = 'nation_env';
|
||||
|
||||
case board = 'board';
|
||||
case comment = 'comment';
|
||||
|
||||
case city = 'city';
|
||||
|
||||
case troop = 'troop';
|
||||
|
||||
case plock = 'plock';
|
||||
|
||||
case message = 'message';
|
||||
|
||||
case rankData = 'rank_data';
|
||||
case hall = 'hall';
|
||||
|
||||
case oldNations = 'ng_old_nations';
|
||||
case oldGenerals = 'ng_old_generals';
|
||||
|
||||
case emperior = 'emperior';
|
||||
|
||||
case diplomacy = 'diplomacy';
|
||||
case diplomaticNotes = 'ng_diplomacy';
|
||||
|
||||
case tournament = 'tournament';
|
||||
case betting = 'ng_betting';
|
||||
case vote = 'vote';
|
||||
case voteComment = 'vote_comment';
|
||||
|
||||
case auction = 'ng_auction';
|
||||
case auctionBid = 'ng_auction_bid';
|
||||
|
||||
case statistic = 'statistic';
|
||||
|
||||
case history = 'ng_history';
|
||||
case worldHistory = 'world_history';
|
||||
case generalRecord = 'general_record';
|
||||
|
||||
case event = 'event';
|
||||
case storage = 'storage';
|
||||
|
||||
|
||||
case selectNPCToken = 'select_npc_token';
|
||||
case selectPool = 'select_pool';
|
||||
|
||||
case games = 'ng_games';
|
||||
case reservedOpen = 'reserved_open';
|
||||
}
|
||||
@@ -31,29 +31,44 @@ class InvaderEnding extends \sammo\Event\Action{
|
||||
|
||||
$logger = new ActionLogger(0, 0, $env['year'], $env['month']);
|
||||
|
||||
$needStop = false;
|
||||
$userWin = false;
|
||||
$cityCnt = $db->queryFirstField('SELECT count(*) FROM city WHERE nation = 0');
|
||||
if($cityCnt == 0){
|
||||
$needStop = true;
|
||||
$nationName = $db->queryFirstField('SELECT name FROM nation LIMIT 1');
|
||||
if(!\str_starts_with($nationName, 'ⓞ')){
|
||||
$userWin = true;
|
||||
}
|
||||
}
|
||||
else if($cityCnt == count(CityConst::all())){
|
||||
$needStop = true;
|
||||
$userWin = false;
|
||||
}
|
||||
|
||||
if(!$needStop){
|
||||
return [__CLASS__, "On Event"];
|
||||
}
|
||||
|
||||
if($userWin){
|
||||
//천통 엔딩
|
||||
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>이민족을 모두 소탕했습니다!");
|
||||
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>중원은 당분간 태평성대를 누릴 것입니다.");
|
||||
}
|
||||
else if($cityCnt == count(CityConst::all())){
|
||||
else {
|
||||
//이민족 엔딩
|
||||
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>중원은 이민족에 의해 혼란에 빠졌습니다.");
|
||||
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>백성은 언젠가 영웅이 나타나길 기다립니다.");
|
||||
}
|
||||
else{
|
||||
return [__CLASS__, "On Event"];
|
||||
}
|
||||
$gameStor->setValue('isunited', 3);
|
||||
$logger->flush();
|
||||
|
||||
$gameStor->conlimit = $gameStor->conlimit * 100;
|
||||
$gameStor->refreshLimit = $gameStor->refreshLimit * 100;
|
||||
|
||||
$eventID = Util::array_get($env['currentEventID']);
|
||||
$db->delete('event', 'id = %i', $eventID);
|
||||
|
||||
return [__CLASS__, 'Deleted'];
|
||||
return [__CLASS__, 'Deleted'];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,7 @@ class MergeInheritPointRank extends \sammo\Event\Action
|
||||
{
|
||||
$db = DB::db();
|
||||
|
||||
$generals = General::createGeneralObjListFromDB(null, null, 2);
|
||||
$generals = General::createGeneralObjListFromDB(null, null);
|
||||
|
||||
$points = new Map();
|
||||
$points->allocate(count($generals));
|
||||
|
||||
@@ -88,7 +88,7 @@ class ProcessIncome extends \sammo\Event\Action
|
||||
|
||||
// 각 장수들에게 지급
|
||||
foreach ($generalRawList as $rawGeneral) {
|
||||
$generalObj = new General($rawGeneral, null, null, null, $year, $month, false);
|
||||
$generalObj = new General($rawGeneral, null, null, null, null, $year, $month, false);
|
||||
$gold = Util::round(getBill($generalObj->getVar('dedication')) * $ratio);
|
||||
$generalObj->increaseVar('gold', $gold);
|
||||
|
||||
@@ -169,7 +169,7 @@ class ProcessIncome extends \sammo\Event\Action
|
||||
|
||||
// 각 장수들에게 지급
|
||||
foreach ($generalRawList as $rawGeneral) {
|
||||
$generalObj = new General($rawGeneral, null, null, null, $year, $month, false);
|
||||
$generalObj = new General($rawGeneral, null, null, null, null, $year, $month, false);
|
||||
$rice = Util::round(getBill($generalObj->getVar('dedication')) * $ratio);
|
||||
$generalObj->increaseVar('rice', $rice);
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class ProvideNPCTroopLeader extends \sammo\Event\Action
|
||||
|
||||
foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) {
|
||||
$nationID = $nation['nation'];
|
||||
$maxNPCTroopLeaderCnt = self::MaxNPCTroopLeaderCnt[$nation['level']];
|
||||
$maxNPCTroopLeaderCnt = self::MaxNPCTroopLeaderCnt[$nation['level']] ?? 0;
|
||||
$NPCTroopLeaderCnt = $NPCTroopLeaderCntByNation[$nationID] ?? 0;
|
||||
|
||||
if ($NPCTroopLeaderCnt >= $maxNPCTroopLeaderCnt) {
|
||||
|
||||
@@ -131,7 +131,7 @@ class RaiseDisaster extends \sammo\Event\Action
|
||||
|
||||
$generalList = array_map(
|
||||
function ($rawGeneral) use ($city, $year, $month) {
|
||||
return new General($rawGeneral, null, $city, null, $year, $month, false);
|
||||
return new General($rawGeneral, null, null, $city, null, $year, $month, false);
|
||||
},
|
||||
$generalListByCity[$city['city']] ?? []
|
||||
);
|
||||
|
||||
@@ -12,6 +12,8 @@ use sammo\LiteHashDRBG;
|
||||
use sammo\RandUtil;
|
||||
use sammo\Scenario\GeneralBuilder;
|
||||
use sammo\Scenario\Nation;
|
||||
use sammo\ServerEnv;
|
||||
use sammo\ServerTool;
|
||||
use sammo\UniqueConst;
|
||||
use sammo\Util;
|
||||
|
||||
@@ -93,6 +95,7 @@ class RaiseInvader extends \sammo\Event\Action
|
||||
public function run(array $env)
|
||||
{
|
||||
$db = DB::db();
|
||||
|
||||
$npcEachCount = $this->npcEachCount;
|
||||
|
||||
/** @var \sammo\CityInitDetail[] */
|
||||
@@ -104,6 +107,16 @@ class RaiseInvader extends \sammo\Event\Action
|
||||
$cities[] = $cityObj;
|
||||
}
|
||||
|
||||
if(!$cities){
|
||||
return [__CLASS__, 0];
|
||||
}
|
||||
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$gameStor->setValue('isunited', 1);
|
||||
|
||||
$turnterm = $gameStor->turnterm;
|
||||
$generalCnt = $db->queryFirstField('SELECT count(*) FROM general');
|
||||
|
||||
if ($npcEachCount < 0) {
|
||||
$npcEachCount =
|
||||
$db->queryFirstField('SELECT count(no) from general where npc < 4') / count($cities);
|
||||
@@ -111,6 +124,19 @@ class RaiseInvader extends \sammo\Event\Action
|
||||
}
|
||||
$npcEachCount = max(10, Util::toInt($npcEachCount));
|
||||
|
||||
|
||||
$totalGenerals = $npcEachCount * count($cities) + $generalCnt;
|
||||
if ($totalGenerals > ServerEnv::$maxGeneralsPerMinute * $turnterm) {
|
||||
foreach ([1, 2, 5, 10, 20, 30, 60, 120] as $nextTurnterm) {
|
||||
if ($totalGenerals > ServerEnv::$maxGeneralsPerMinute * $nextTurnterm) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ServerTool::changeServerTerm($nextTurnterm, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$specAvg = $this->specAvg;
|
||||
if ($specAvg < 0) {
|
||||
$specAvg = $db->queryFirstField('SELECT avg((`leadership` + `strength` + `intel`)) from general where npc < 4');
|
||||
@@ -140,6 +166,11 @@ class RaiseInvader extends \sammo\Event\Action
|
||||
$month,
|
||||
)));
|
||||
|
||||
$db->update('nation', [
|
||||
'war' => 0,
|
||||
'scout' => 0,
|
||||
], '1');
|
||||
|
||||
$disabledInvaderCity = $this->moveCapital($rng);
|
||||
$serverID = UniqueConst::$serverID;
|
||||
$existNations = $db->queryFirstColumn("SELECT nation FROM `nation`");
|
||||
@@ -260,8 +291,6 @@ class RaiseInvader extends \sammo\Event\Action
|
||||
'secu' => $db->sqleval('secu_max'),
|
||||
], true);
|
||||
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$gameStor->setValue('isunited', 1);
|
||||
refreshNationStaticInfo();
|
||||
|
||||
$logger = new ActionLogger(0, 0, $year, $env['month']);
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace sammo\Event\Action;
|
||||
use sammo\ActionLogger;
|
||||
use sammo\CityConst;
|
||||
use sammo\DB;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\Enums\InheritanceKey;
|
||||
use sammo\GameConst;
|
||||
use sammo\General;
|
||||
@@ -139,7 +140,7 @@ class UpdateNationLevel extends \sammo\Event\Action
|
||||
$nation['nation'],
|
||||
$targetKillTurn
|
||||
);
|
||||
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc', 'aux'], 2);
|
||||
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc', 'aux']);
|
||||
$chiefID = null;
|
||||
|
||||
$uniqueLotteryWeightList = [];
|
||||
@@ -214,7 +215,7 @@ class UpdateNationLevel extends \sammo\Event\Action
|
||||
}
|
||||
|
||||
if ($chiefID) {
|
||||
$chiefObj = General::createGeneralObjFromDB($chiefID, ['belong', 'npc', 'aux'], 2);
|
||||
$chiefObj = General::createGeneralObjFromDB($chiefID, ['belong', 'npc', 'aux'], GeneralQueryMode::Lite);
|
||||
$chiefObj->increaseInheritancePoint(InheritanceKey::unifier, 250 * $levelDiff);
|
||||
$chiefObj->applyDB($db);
|
||||
}
|
||||
|
||||
@@ -83,6 +83,9 @@ class GameConstBase
|
||||
/** @var int 최대 하야 패널티 수 */
|
||||
public static $maxBetrayCnt = 9;
|
||||
|
||||
/** @var int 최대 레벨 */
|
||||
public static $maxLevel = 255;
|
||||
|
||||
/** @var int 최소 인구 증가량 */
|
||||
public static $basePopIncreaseAmount = 5000;
|
||||
/** @var int 증축시 인구 증가량 */
|
||||
|
||||
@@ -41,7 +41,7 @@ class GameUnitConstBase{
|
||||
[],//성벽은 공격할 수 없다.
|
||||
[self::T_FOOTMAN=>1.2],
|
||||
['성벽입니다.','생성할 수 없습니다.'],
|
||||
null, null
|
||||
null, ['che_선제사격시도', 'che_선제사격발동'], null
|
||||
],
|
||||
|
||||
[
|
||||
@@ -51,7 +51,7 @@ class GameUnitConstBase{
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
|
||||
['표준적인 보병입니다.','보병은 방어특화이며,','상대가 회피하기 어렵습니다.'],
|
||||
null, ['che_방어력증가5p']
|
||||
null, ['che_방어력증가5p'], null
|
||||
],
|
||||
[
|
||||
1101, self::T_FOOTMAN, '청주병',
|
||||
@@ -60,7 +60,7 @@ class GameUnitConstBase{
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
|
||||
['저렴하고 튼튼합니다.'],
|
||||
null, ['che_방어력증가5p']
|
||||
null, ['che_방어력증가5p'], null
|
||||
],
|
||||
[
|
||||
1102, self::T_FOOTMAN, '수병',
|
||||
@@ -69,7 +69,7 @@ class GameUnitConstBase{
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
|
||||
['저렴하고 강력합니다.'],
|
||||
null, ['che_방어력증가5p']
|
||||
null, ['che_방어력증가5p'], null
|
||||
],
|
||||
[
|
||||
1103, self::T_FOOTMAN, '자객병',
|
||||
@@ -78,7 +78,7 @@ class GameUnitConstBase{
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
|
||||
['은밀하고 날쌥니다.'],
|
||||
null, ['che_방어력증가5p']
|
||||
null, ['che_방어력증가5p'], null
|
||||
],
|
||||
[
|
||||
1104, self::T_FOOTMAN, '근위병',
|
||||
@@ -87,7 +87,7 @@ class GameUnitConstBase{
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
|
||||
['최강의 보병입니다.'],
|
||||
null, ['che_방어력증가5p']
|
||||
null, ['che_방어력증가5p'], null
|
||||
],
|
||||
[
|
||||
1105, self::T_FOOTMAN, '등갑병',
|
||||
@@ -96,7 +96,7 @@ class GameUnitConstBase{
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
|
||||
['등갑을 두른 보병입니다.'],
|
||||
null, ['che_방어력증가5p']
|
||||
null, ['che_방어력증가5p'], null
|
||||
],
|
||||
[
|
||||
1106, self::T_FOOTMAN, '백이병',
|
||||
@@ -105,7 +105,7 @@ class GameUnitConstBase{
|
||||
[self::T_ARCHER=>1.1, self::T_CAVALRY=>0.9, self::T_SIEGE=>1.1],
|
||||
[self::T_ARCHER=>0.9, self::T_CAVALRY=>1.1, self::T_SIEGE=>0.9],
|
||||
['정예 보병입니다. 불리한 싸움도 버텨냅니다.'],
|
||||
null, ['che_방어력증가5p']
|
||||
null, ['che_방어력증가5p'], null
|
||||
],
|
||||
|
||||
[
|
||||
@@ -115,7 +115,7 @@ class GameUnitConstBase{
|
||||
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
|
||||
['표준적인 궁병입니다.','궁병은 선제사격을 하는 병종입니다.'],
|
||||
null, ['che_선제사격시도', 'che_선제사격발동']
|
||||
null, ['che_선제사격시도', 'che_선제사격발동'], null
|
||||
],
|
||||
[
|
||||
1201, self::T_ARCHER, '궁기병',
|
||||
@@ -124,7 +124,7 @@ class GameUnitConstBase{
|
||||
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.9, self::T_SIEGE=>1.2],
|
||||
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.1, self::T_SIEGE=>0.8],
|
||||
['말을 타고 잘 피합니다. 특히 다른 궁병보다 보병에게 조금 더 강합니다.'],
|
||||
null, ['che_선제사격시도', 'che_선제사격발동']
|
||||
null, ['che_선제사격시도', 'che_선제사격발동'], null
|
||||
],
|
||||
[
|
||||
1202, self::T_ARCHER, '연노병',
|
||||
@@ -133,7 +133,7 @@ class GameUnitConstBase{
|
||||
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
|
||||
['화살을 연사합니다.'],
|
||||
null, ['che_선제사격시도', 'che_선제사격발동']
|
||||
null, ['che_선제사격시도', 'che_선제사격발동'], null
|
||||
],
|
||||
[
|
||||
1203, self::T_ARCHER, '강궁병',
|
||||
@@ -142,7 +142,7 @@ class GameUnitConstBase{
|
||||
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
|
||||
['강건한 궁병입니다.'],
|
||||
null, ['che_선제사격시도', 'che_선제사격발동']
|
||||
null, ['che_선제사격시도', 'che_선제사격발동'], null
|
||||
],
|
||||
[
|
||||
1204, self::T_ARCHER, '석궁병',
|
||||
@@ -151,7 +151,7 @@ class GameUnitConstBase{
|
||||
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
|
||||
['강력한 화살을 쏩니다.'],
|
||||
null, ['che_선제사격시도', 'che_선제사격발동']
|
||||
null, ['che_선제사격시도', 'che_선제사격발동'], null
|
||||
],
|
||||
|
||||
[
|
||||
@@ -161,7 +161,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['표준적인 기병입니다.','기병은 공격특화입니다.'],
|
||||
null, ['che_기병병종전투']
|
||||
null, ['che_기병병종전투'], null
|
||||
],
|
||||
[
|
||||
1301, self::T_CAVALRY, '백마병',
|
||||
@@ -170,7 +170,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['백마의 위용을 보여줍니다.'],
|
||||
null, ['che_기병병종전투']
|
||||
null, ['che_기병병종전투'], null
|
||||
],
|
||||
[
|
||||
1302, self::T_CAVALRY, '중장기병',
|
||||
@@ -179,7 +179,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['갑주를 두른 기병입니다.'],
|
||||
null, ['che_기병병종전투']
|
||||
null, ['che_기병병종전투'], null
|
||||
],
|
||||
[
|
||||
1303, self::T_CAVALRY, '돌격기병',
|
||||
@@ -188,7 +188,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['저돌적으로 공격합니다.'],
|
||||
null, ['che_기병병종전투']
|
||||
null, ['che_기병병종전투'], null
|
||||
],
|
||||
[
|
||||
1304, self::T_CAVALRY, '철기병',
|
||||
@@ -197,7 +197,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['철갑을 두른 기병입니다.'],
|
||||
null, ['che_기병병종전투']
|
||||
null, ['che_기병병종전투'], null
|
||||
],
|
||||
[
|
||||
1305, self::T_CAVALRY, '수렵기병',
|
||||
@@ -206,7 +206,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['날쎄고 빠른 기병입니다.'],
|
||||
null, ['che_기병병종전투']
|
||||
null, ['che_기병병종전투'], null
|
||||
],
|
||||
[
|
||||
1306, self::T_CAVALRY, '맹수병',
|
||||
@@ -215,7 +215,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['어느 누구보다 강력합니다.'],
|
||||
null, ['che_기병병종전투']
|
||||
null, ['che_기병병종전투'], null
|
||||
],
|
||||
[
|
||||
1307, self::T_CAVALRY, '호표기병',
|
||||
@@ -224,7 +224,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['정예 기병입니다.'],
|
||||
null, ['che_기병병종전투']
|
||||
null, ['che_기병병종전투'], null
|
||||
],
|
||||
|
||||
[
|
||||
@@ -234,7 +234,7 @@ class GameUnitConstBase{
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
['계략을 사용하는 병종입니다.'],
|
||||
null, null
|
||||
null, null, null
|
||||
],
|
||||
[
|
||||
1401, self::T_WIZARD, '신귀병',
|
||||
@@ -243,7 +243,7 @@ class GameUnitConstBase{
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
['신출귀몰한 귀병입니다.'],
|
||||
null, null
|
||||
null, null, null
|
||||
],
|
||||
[
|
||||
1402, self::T_WIZARD, '백귀병',
|
||||
@@ -252,7 +252,7 @@ class GameUnitConstBase{
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
['저렴하고 튼튼합니다.'],
|
||||
null, null
|
||||
null, null, null
|
||||
],
|
||||
[
|
||||
1403, self::T_WIZARD, '흑귀병',
|
||||
@@ -261,7 +261,7 @@ class GameUnitConstBase{
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
['저렴하고 강력합니다.'],
|
||||
null, null
|
||||
null, null, null
|
||||
],
|
||||
[
|
||||
1404, self::T_WIZARD, '악귀병',
|
||||
@@ -270,7 +270,7 @@ class GameUnitConstBase{
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
['백병전에도 능숙합니다.'],
|
||||
null, null
|
||||
null, null, null
|
||||
],
|
||||
[
|
||||
1405, self::T_WIZARD, '남귀병',
|
||||
@@ -279,7 +279,7 @@ class GameUnitConstBase{
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
['전투를 포기하고 계략에 몰두합니다.'],
|
||||
null, null
|
||||
null, null, null
|
||||
],
|
||||
[
|
||||
1406, self::T_WIZARD, '황귀병',
|
||||
@@ -288,7 +288,7 @@ class GameUnitConstBase{
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
['고도로 훈련된 귀병입니다.'],
|
||||
null, null
|
||||
null, null, null
|
||||
],
|
||||
[
|
||||
1407, self::T_WIZARD, '천귀병',
|
||||
@@ -297,7 +297,7 @@ class GameUnitConstBase{
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
['갑주를 두른 귀병입니다.'],
|
||||
null, null
|
||||
null, null, null
|
||||
],
|
||||
[
|
||||
1408, self::T_WIZARD, '마귀병',
|
||||
@@ -306,7 +306,7 @@ class GameUnitConstBase{
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
['날카로운 무기를 가진 귀병입니다.'],
|
||||
null, null
|
||||
null, null, null
|
||||
],
|
||||
|
||||
[
|
||||
@@ -314,9 +314,9 @@ class GameUnitConstBase{
|
||||
100, 100, 6, 0, 0, 14, 5,
|
||||
0, null, null, 3,
|
||||
[self::T_FOOTMAN=>1.25, self::T_ARCHER=>1.25, self::T_CAVALRY=>1.25, self::T_WIZARD=>1.25, self::T_CASTLE=>1.8, 1106=>1.112],
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
|
||||
['높은 구조물 위에서 공격합니다.'],
|
||||
['che_성벽부상무효'], ['che_선제사격시도', 'che_선제사격발동']
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2, 1106=>1.067],
|
||||
['높은 구조물 위에서 공격합니다. 첫 공격은 성벽을 향합니다.'],
|
||||
['che_성벽부상무효'], ['che_선제사격시도', 'che_선제사격발동'], ['che_성벽선제']
|
||||
],
|
||||
[
|
||||
1501, self::T_SIEGE, '충차',
|
||||
@@ -325,25 +325,25 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>2.4],
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
|
||||
['엄청난 위력으로 성벽을 부수어버립니다.'],
|
||||
['che_성벽부상무효'], null
|
||||
['che_성벽부상무효'], null, null
|
||||
],
|
||||
[
|
||||
1502, self::T_SIEGE, '벽력거',
|
||||
150, 100, 6, 5, 0, 20, 5,
|
||||
3000, ['업'], null, 0,
|
||||
[self::T_FOOTMAN=>1.25, self::T_ARCHER=>1.25, self::T_CAVALRY=>1.25, self::T_WIZARD=>1.25, self::T_CASTLE=>1.8, 1106=>1.112],
|
||||
[self::T_FOOTMAN=>0.833, self::T_ARCHER=>0.833, self::T_CAVALRY=>0.833, self::T_WIZARD=>0.833, 1106=>0.909],
|
||||
['상대에게 돌덩이를 날립니다.'],
|
||||
['che_성벽부상무효'], ['che_선제사격시도', 'che_선제사격발동']
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2, 1106=>1.067],
|
||||
['상대에게 돌덩이를 날립니다. 첫 공격은 성벽을 향합니다.'],
|
||||
['che_성벽부상무효'], ['che_선제사격시도', 'che_선제사격발동'], ['che_성벽선제']
|
||||
],
|
||||
[
|
||||
1503, self::T_SIEGE, '목우',
|
||||
50, 200, 5, 0, 0, 15, 5,
|
||||
3000, ['성도'], null, 0,
|
||||
[self::T_FOOTMAN=>1.25, self::T_ARCHER=>1.25, self::T_CAVALRY=>1.25, self::T_WIZARD=>1.25, self::T_CASTLE=>1.8, 1106=>1.112],
|
||||
[self::T_FOOTMAN=>1, self::T_ARCHER=>1, self::T_CAVALRY=>1, self::T_WIZARD=>1, self::T_CASTLE=>1.8],
|
||||
[self::T_FOOTMAN=>1, self::T_ARCHER=>1, self::T_CAVALRY=>1, self::T_WIZARD=>1, 1106=>1],
|
||||
['상대를 저지하는 특수병기입니다.'],
|
||||
['che_성벽부상무효'], ['che_저지시도', 'che_저지발동']
|
||||
['che_성벽부상무효'], ['che_저지시도', 'che_저지발동'], null
|
||||
]
|
||||
];
|
||||
|
||||
@@ -466,6 +466,7 @@ class GameUnitConstBase{
|
||||
$info,
|
||||
$initSkillTrigger,
|
||||
$phaseSkillTrigger,
|
||||
$iActionList,
|
||||
] = $rawUnit;
|
||||
|
||||
if($reqYear > 0){
|
||||
@@ -509,7 +510,8 @@ class GameUnitConstBase{
|
||||
$defenceCoef,
|
||||
$info,
|
||||
$initSkillTrigger,
|
||||
$phaseSkillTrigger
|
||||
$phaseSkillTrigger,
|
||||
$iActionList,
|
||||
);
|
||||
|
||||
$constID[$id] = $unit;
|
||||
|
||||
+167
-66
@@ -1,7 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
class GameUnitDetail implements iAction{
|
||||
class GameUnitDetail implements iAction
|
||||
{
|
||||
use DefaultAction;
|
||||
|
||||
public $id;
|
||||
@@ -23,6 +25,8 @@ class GameUnitDetail implements iAction{
|
||||
public $info;
|
||||
public $initSkillTrigger;
|
||||
public $phaseSkillTrigger;
|
||||
/** @var iAction[]|null iActionList */
|
||||
public $iActionList;
|
||||
|
||||
public function __construct(
|
||||
int $id,
|
||||
@@ -43,8 +47,9 @@ class GameUnitDetail implements iAction{
|
||||
array $defenceCoef,
|
||||
array $info,
|
||||
?array $initSkillTrigger,
|
||||
?array $phaseSkillTrigger
|
||||
){
|
||||
?array $phaseSkillTrigger,
|
||||
?array $iActionList,
|
||||
) {
|
||||
$this->id = $id;
|
||||
$this->name = $name;
|
||||
$this->armType = $armType;
|
||||
@@ -64,78 +69,91 @@ class GameUnitDetail implements iAction{
|
||||
$this->info = $info;
|
||||
$this->initSkillTrigger = $initSkillTrigger;
|
||||
$this->phaseSkillTrigger = $phaseSkillTrigger;
|
||||
|
||||
$this->iActionList = [];
|
||||
foreach($iActionList ?? [] as $rawAction){
|
||||
$action = buildActionCrewTypeClass($rawAction);
|
||||
if(!$action){
|
||||
continue;
|
||||
}
|
||||
$this->iActionList[] = $action;
|
||||
}
|
||||
}
|
||||
|
||||
public function getInfo():string{
|
||||
public function getInfo(): string
|
||||
{
|
||||
return join("\n<br>", $this->info);
|
||||
}
|
||||
|
||||
public function getShortName():string{
|
||||
public function getShortName(): string
|
||||
{
|
||||
return StringUtil::subStringForWidth($this->name, 0, 4);
|
||||
}
|
||||
|
||||
public function riceWithTech(int $tech, int $crew=100):float{
|
||||
public function riceWithTech(int $tech, int $crew = 100): float
|
||||
{
|
||||
return $this->rice * getTechCost($tech) * $crew / 100;
|
||||
}
|
||||
|
||||
public function costWithTech(int $tech, int $crew=100):float{
|
||||
public function costWithTech(int $tech, int $crew = 100): float
|
||||
{
|
||||
return $this->cost * getTechCost($tech) * $crew / 100;
|
||||
}
|
||||
|
||||
public function getAttackCoef(GameUnitDetail $opposeCrewType):float{
|
||||
public function getAttackCoef(GameUnitDetail $opposeCrewType): float
|
||||
{
|
||||
$opposeCrewTypeID = $opposeCrewType->id;
|
||||
if(key_exists($opposeCrewTypeID, $this->attackCoef)){
|
||||
if (key_exists($opposeCrewTypeID, $this->attackCoef)) {
|
||||
return $this->attackCoef[$opposeCrewTypeID];
|
||||
}
|
||||
$opposeArmType = $opposeCrewType->armType;
|
||||
return $this->attackCoef[$opposeArmType]??1;
|
||||
return $this->attackCoef[$opposeArmType] ?? 1;
|
||||
}
|
||||
|
||||
public function getDefenceCoef(GameUnitDetail $opposeCrewType):float{
|
||||
public function getDefenceCoef(GameUnitDetail $opposeCrewType): float
|
||||
{
|
||||
$opposeCrewTypeID = $opposeCrewType->id;
|
||||
if(key_exists($opposeCrewTypeID, $this->defenceCoef)){
|
||||
if (key_exists($opposeCrewTypeID, $this->defenceCoef)) {
|
||||
return $this->defenceCoef[$opposeCrewTypeID];
|
||||
}
|
||||
$opposeArmType = $opposeCrewType->armType;
|
||||
return $this->defenceCoef[$opposeArmType]??1;
|
||||
return $this->defenceCoef[$opposeArmType] ?? 1;
|
||||
}
|
||||
|
||||
public function getComputedAttack(General $general, int $tech){
|
||||
if($this->armType == GameUnitConst::T_WIZARD){
|
||||
$ratio = $general->getIntel(true, true, true)*2 - 40;
|
||||
}
|
||||
else if($this->armType == GameUnitConst::T_SIEGE){
|
||||
$ratio = $general->getLeadership(true, true, true)*2 - 40;
|
||||
}
|
||||
else if($this->armType == GameUnitConst::T_MISC){
|
||||
public function getComputedAttack(General $general, int $tech)
|
||||
{
|
||||
if ($this->armType == GameUnitConst::T_WIZARD) {
|
||||
$ratio = $general->getIntel(true, true, true) * 2 - 40;
|
||||
} else if ($this->armType == GameUnitConst::T_SIEGE) {
|
||||
$ratio = $general->getLeadership(true, true, true) * 2 - 40;
|
||||
} else if ($this->armType == GameUnitConst::T_MISC) {
|
||||
$ratio = $general->getIntel(true, true, true) +
|
||||
$general->getLeadership(true, true, true) +
|
||||
$general->getStrength(true, true, true);
|
||||
$ratio = $ratio*2/3 - 40;
|
||||
$ratio = $ratio * 2 / 3 - 40;
|
||||
} else {
|
||||
$ratio = $general->getStrength(true, true, true) * 2 - 40;
|
||||
}
|
||||
else{
|
||||
$ratio = $general->getStrength(true, true, true)*2 - 40;
|
||||
}
|
||||
if($ratio < 10){
|
||||
if ($ratio < 10) {
|
||||
$ratio = 10;
|
||||
}
|
||||
if($ratio > 100){
|
||||
$ratio = 50 + $ratio/2;
|
||||
if ($ratio > 100) {
|
||||
$ratio = 50 + $ratio / 2;
|
||||
}
|
||||
|
||||
$att = $this->attack + getTechAbil($tech);
|
||||
return $att * $ratio / 100;
|
||||
}
|
||||
|
||||
public function getComputedDefence(General $general, int $tech){
|
||||
public function getComputedDefence(General $general, int $tech)
|
||||
{
|
||||
$def = $this->defence + getTechAbil($tech);
|
||||
$crew = ($general->getVar('crew') / (7000 / 30)) + 70;
|
||||
return $def * $crew / 100;
|
||||
}
|
||||
|
||||
public function getCriticalRatio(General $general){
|
||||
if($this->armType == GameUnitConst::T_CASTLE){
|
||||
public function getCriticalRatio(General $general)
|
||||
{
|
||||
if ($this->armType == GameUnitConst::T_CASTLE) {
|
||||
//성벽은 필살을 사용하지 않는다.
|
||||
return 0;
|
||||
}
|
||||
@@ -143,22 +161,19 @@ class GameUnitDetail implements iAction{
|
||||
// 무장 무력 : 65 5%, 70 10%, 75 15%, 80 20%
|
||||
// 지장 지력 : 65 5%, 70 8%, 75 10%, 80 13%
|
||||
//충차장 통솔: 65 5%, 70 8%, 75 10%, 80 13%
|
||||
if($this->armType == GameUnitConst::T_WIZARD){
|
||||
if ($this->armType == GameUnitConst::T_WIZARD) {
|
||||
$mainstat = $general->getIntel(false, true, true, false);
|
||||
$coef = 0.4;
|
||||
}
|
||||
else if($this->armType == GameUnitConst::T_SIEGE){
|
||||
} else if ($this->armType == GameUnitConst::T_SIEGE) {
|
||||
$mainstat = $general->getLeadership(false, true, true, false);
|
||||
$coef = 0.4;
|
||||
}
|
||||
else if($this->armType == GameUnitConst::T_MISC){
|
||||
} else if ($this->armType == GameUnitConst::T_MISC) {
|
||||
$mainstat = $general->getIntel(false, true, true, false) +
|
||||
$general->getLeadership(false, true, true, false) +
|
||||
$general->getStrength(false, true, true, false);
|
||||
$general->getLeadership(false, true, true, false) +
|
||||
$general->getStrength(false, true, true, false);
|
||||
$mainstat /= 3;
|
||||
$coef = 0.4;
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$mainstat = $general->getStrength(false, true, true, false);
|
||||
$coef = 0.5;
|
||||
}
|
||||
@@ -169,7 +184,8 @@ class GameUnitDetail implements iAction{
|
||||
return min(50, $ratio) / 100;
|
||||
}
|
||||
|
||||
public function pickScore($tech){
|
||||
public function pickScore($tech)
|
||||
{
|
||||
$defaultWar = GameConst::$armperphase + $this->attack + $this->defence + getTechAbil($tech) * 2;
|
||||
$defaultWar *= 1 + $this->speed / 2;
|
||||
$defaultWar /= Util::valueFit(1 - $this->avoid / 100, 0.1);
|
||||
@@ -177,40 +193,41 @@ class GameUnitDetail implements iAction{
|
||||
return $defaultWar;
|
||||
}
|
||||
|
||||
public function isValid($ownCities, $ownRegions, $relativeYear, $tech){
|
||||
public function isValid($ownCities, $ownRegions, $relativeYear, $tech)
|
||||
{
|
||||
//음수 없음
|
||||
$relativeYear = max(0, $relativeYear);
|
||||
|
||||
if($relativeYear < $this->reqYear){
|
||||
if ($relativeYear < $this->reqYear) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if($tech < $this->reqTech){
|
||||
if ($tech < $this->reqTech) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->reqCities !== null){
|
||||
if ($this->reqCities !== null) {
|
||||
$valid = false;
|
||||
foreach($this->reqCities as $reqCity){
|
||||
if(\key_exists($reqCity, $ownCities)){
|
||||
foreach ($this->reqCities as $reqCity) {
|
||||
if (\key_exists($reqCity, $ownCities)) {
|
||||
$valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!$valid){
|
||||
if (!$valid) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if($this->reqRegions !== null){
|
||||
if ($this->reqRegions !== null) {
|
||||
$valid = false;
|
||||
foreach($this->reqRegions as $reqRegion){
|
||||
if(\key_exists($reqRegion, $ownRegions)){
|
||||
foreach ($this->reqRegions as $reqRegion) {
|
||||
if (\key_exists($reqRegion, $ownRegions)) {
|
||||
$valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!$valid){
|
||||
if (!$valid) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -219,17 +236,17 @@ class GameUnitDetail implements iAction{
|
||||
}
|
||||
|
||||
//iAction
|
||||
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
if(!$this->initSkillTrigger){
|
||||
public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
|
||||
{
|
||||
if (!$this->initSkillTrigger) {
|
||||
return null;
|
||||
}
|
||||
$triggerList = [];
|
||||
foreach($this->initSkillTrigger as $triggerArgs){
|
||||
if(is_string($triggerArgs)){
|
||||
foreach ($this->initSkillTrigger as $triggerArgs) {
|
||||
if (is_string($triggerArgs)) {
|
||||
$typeName = $triggerArgs;
|
||||
$triggerList[] = buildWarUnitTriggerClass($typeName, $unit);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$typeName = $triggerArgs[0];
|
||||
//WarUnit 다음 인자는 $raiseType이며, 0이어야할 것이다
|
||||
$triggerArgs[0] = 0;
|
||||
@@ -238,17 +255,17 @@ class GameUnitDetail implements iAction{
|
||||
}
|
||||
return new WarUnitTriggerCaller(...$triggerList);
|
||||
}
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
if(!$this->phaseSkillTrigger){
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
|
||||
{
|
||||
if (!$this->phaseSkillTrigger) {
|
||||
return null;
|
||||
}
|
||||
$triggerList = [];
|
||||
foreach($this->phaseSkillTrigger as $triggerArgs){
|
||||
if(is_string($triggerArgs)){
|
||||
foreach ($this->phaseSkillTrigger as $triggerArgs) {
|
||||
if (is_string($triggerArgs)) {
|
||||
$typeName = $triggerArgs;
|
||||
$triggerList[] = buildWarUnitTriggerClass($typeName, $unit);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$typeName = $triggerArgs[0];
|
||||
//WarUnit 다음 인자는 $raiseType이며, 0이어야할 것이다
|
||||
$triggerArgs[0] = 0;
|
||||
@@ -256,6 +273,90 @@ class GameUnitDetail implements iAction{
|
||||
}
|
||||
}
|
||||
return new WarUnitTriggerCaller(...$triggerList);
|
||||
}
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux = null): float
|
||||
{
|
||||
if (!$this->iActionList) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
foreach ($this->iActionList as $iAction) {
|
||||
$value = $iAction->onCalcDomestic($turnType, $varType, $value, $aux);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux = null)
|
||||
{
|
||||
if (!$this->iActionList) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
foreach ($this->iActionList as $iAction) {
|
||||
$value = $iAction->onCalcStat($general, $statName, $value, $aux);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
|
||||
{
|
||||
if (!$this->iActionList) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
foreach ($this->iActionList as $iAction) {
|
||||
$value = $iAction->onCalcOpposeStat($general, $statName, $value, $aux);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
public function onCalcStrategic(string $turnType, string $varType, $value)
|
||||
{
|
||||
if (!$this->iActionList) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
foreach ($this->iActionList as $iAction) {
|
||||
$value = $iAction->onCalcStrategic($turnType, $varType, $value);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
public function onCalcNationalIncome(string $type, $amount)
|
||||
{
|
||||
if (!$this->iActionList) {
|
||||
return $amount;
|
||||
}
|
||||
|
||||
foreach ($this->iActionList as $iAction) {
|
||||
$amount = $iAction->onCalcNationalIncome($type, $amount);
|
||||
}
|
||||
return $amount;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit): array
|
||||
{
|
||||
if (!$this->iActionList) {
|
||||
return [1, 1];
|
||||
}
|
||||
|
||||
$attack = 1;
|
||||
$defence = 1;
|
||||
foreach ($this->iActionList as $iAction) {
|
||||
$attack *= $iAction->getWarPowerMultiplier($unit)[0];
|
||||
$defence *= $iAction->getWarPowerMultiplier($unit)[1];
|
||||
}
|
||||
return [$attack, $defence];
|
||||
}
|
||||
|
||||
public function onArbitraryAction(General $general, RandUtil $rng, string $actionType, ?string $phase = null, ?array $aux = null): null|array
|
||||
{
|
||||
if (!$this->iActionList) {
|
||||
return $aux;
|
||||
}
|
||||
|
||||
foreach ($this->iActionList as $iAction) {
|
||||
$aux = $iAction->onArbitraryAction($general, $rng, $actionType, $phase, $aux);
|
||||
}
|
||||
return $aux;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user