Compare commits

..
Author SHA1 Message Date
sars f71aa79b0d Merge branch 'devel' into asia_scenario 2022-08-02 16:20:18 +09:00
sars 15cf23dd4d 아시아 명장전 시나리오(비급) 추가 2022-08-02 00:17:37 -07:00
661 changed files with 15755 additions and 35997 deletions
+15
View File
@@ -0,0 +1,15 @@
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3,
"modules": false
}
]
],
"plugins": [
"lodash"
]
}
-7
View File
@@ -10,10 +10,8 @@
*.log *.log
logs/*.txt logs/*.txt
api_log.db
d_log/*.txt d_log/*.txt
d_log/*.zip d_log/*.zip
d_log/*.db
sess_* sess_*
*/logs/*.txt */logs/*.txt
*/logs/*/*.txt */logs/*/*.txt
@@ -29,7 +27,6 @@ d_pic/*.jpg
d_pic/*.gif d_pic/*.gif
d_pic/*.png d_pic/*.png
d_pic/*.webp d_pic/*.webp
d_pic/*.avif
d_pic/uploaded_image d_pic/uploaded_image
/dist_js /dist_js
@@ -68,7 +65,3 @@ ingame/js/*
ingame/css/* ingame/css/*
gateway/js/* gateway/js/*
gateway/css/* gateway/css/*
*.db-journal
d_log/cachegrind.*
+12 -2
View File
@@ -15,8 +15,9 @@ return [
// Note that the **only** effect of choosing `'5.6'` is to infer // Note that the **only** effect of choosing `'5.6'` is to infer
// that functions removed in php 7.0 exist. // that functions removed in php 7.0 exist.
// (See `backward_compatibility_checks` for additional options) // (See `backward_compatibility_checks` for additional options)
"target_php_version" => '8.2', "target_php_version" => '8.1',
"minimum_target_php_version" => '8.2', "minimum_target_php_version" => '8.1',
'backward_compatibility_checks ' => true,
'minimum_severity' => \Phan\Issue::SEVERITY_NORMAL, 'minimum_severity' => \Phan\Issue::SEVERITY_NORMAL,
'file_list' => [ 'file_list' => [
@@ -28,6 +29,8 @@ return [
'hwe/_admin1_submit.php', 'hwe/_admin1_submit.php',
'hwe/_admin2.php', 'hwe/_admin2.php',
'hwe/_admin2_submit.php', 'hwe/_admin2_submit.php',
'hwe/_admin4.php',
'hwe/_admin4_submit.php',
'hwe/_admin5.php', 'hwe/_admin5.php',
'hwe/_admin5_submit.php', 'hwe/_admin5_submit.php',
'hwe/_admin7.php', 'hwe/_admin7.php',
@@ -95,6 +98,12 @@ return [
'hwe/j_load_scenarios.php', 'hwe/j_load_scenarios.php',
'hwe/j_map.php', 'hwe/j_map.php',
'hwe/j_map_recent.php', 'hwe/j_map_recent.php',
'hwe/j_msg_contact_list.php',
'hwe/j_msg_decide_opt.php',
'hwe/j_msg_delete.php',
'hwe/j_msg_get_old.php',
'hwe/j_msg_get_recent.php',
'hwe/j_msg_submit.php',
'hwe/j_myBossInfo.php', 'hwe/j_myBossInfo.php',
'hwe/j_raise_event.php', 'hwe/j_raise_event.php',
'hwe/j_select_npc.php', 'hwe/j_select_npc.php',
@@ -103,6 +112,7 @@ return [
'hwe/j_set_my_setting.php', 'hwe/j_set_my_setting.php',
'hwe/j_set_npc_control.php', 'hwe/j_set_npc_control.php',
'hwe/j_simulate_battle.php', 'hwe/j_simulate_battle.php',
'hwe/j_troop.php',
'hwe/j_update_picked_general.php', 'hwe/j_update_picked_general.php',
'hwe/j_vacation.php', 'hwe/j_vacation.php',
'hwe/lib.php', 'hwe/lib.php',
+1 -1
View File
@@ -29,5 +29,5 @@
"josa", "josa",
"sammo" "sammo"
], ],
"editor.tabSize": 4 "editor.tabSize": 2
} }
-1
View File
@@ -2,7 +2,6 @@
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="color-scheme" content="dark">
<title>닫혀 있습니다.</title> <title>닫혀 있습니다.</title>
<script> <script>
setTimeout(function(){ setTimeout(function(){
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License The MIT License
Copyright (c) 2023 Hide_D, 62che Copyright (c) 2022 Hide_D, 62che
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+13 -13
View File
@@ -8,26 +8,26 @@
], ],
"config": { "config": {
"platform": { "platform": {
"php": "8.3" "php": "8.1"
} }
}, },
"require": { "require": {
"brandonwamboldt/utilphp": "^1.1", "brandonwamboldt/utilphp": "^1.1",
"sergeytsalkov/meekrodb": "^2.5", "sergeytsalkov/meekrodb": "^2.3",
"league/plates": "^3.5", "league/plates": "^3.3",
"vlucas/valitron": "^1.4", "vlucas/valitron": "^1.4",
"php-extended/php-tail": "^5.0", "php-extended/php-tail": "^2.1",
"symfony/lock": "^6.2", "pguardiario/phpuri": "^1.0",
"symfony/lock": "^6.0",
"ezyang/htmlpurifier": "^4.10", "ezyang/htmlpurifier": "^4.10",
"xemlock/htmlpurifier-html5": "^0.1.7", "xemlock/htmlpurifier-html5": "^0.1.7",
"catfan/medoo": "^2.1", "catfan/medoo": "^2.1",
"phan/phan": "^5.4", "phan/phan": "^5.3",
"nette/caching": "^3.3", "nette/caching": "^3.0",
"illuminate/database": "^10.0", "illuminate/database": "^9.12",
"illuminate/events": "^10.0", "illuminate/events": "^9.12",
"php-ds/php-ds": "^1.5", "spatie/data-transfer-object": "^3.7",
"hided62/ldto": "^1.0", "php-ds/php-ds": "^1.4"
"league/uri": "^6.8"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@@ -48,6 +48,6 @@
] ]
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^10.0" "phpunit/phpunit": "^9.5"
} }
} }
Generated
+1065 -1449
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+3 -4
View File
@@ -10,7 +10,6 @@ require(__DIR__ . '/../vendor/autoload.php');
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<title>설치</title> <title>설치</title>
@@ -30,10 +29,10 @@ require(__DIR__ . '/../vendor/autoload.php');
<body> <body>
<div class="container"> <div class="container">
<h1 class="row justify-content-lg-center">삼국지 모의전투 HiDCHe 설치</h1> <h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe 설치</h1>
<div class="row justify-content-lg-center"> <div class="row justify-content-md-center">
<div class="col col-12 col-lg-10 col-lg-7"> <div class="col col-12 col-md-10 col-lg-7">
<div class="card" id="db_form_card" style="display:none"> <div class="card" id="db_form_card" style="display:none">
<h3 class="card-header"> <h3 class="card-header">
설치(DB 설정) 설치(DB 설정)
+1 -1
View File
@@ -56,7 +56,7 @@ $rootDB->insert('member', [
'token_valid_until' => '2999-01-01 00:00:00', 'token_valid_until' => '2999-01-01 00:00:00',
'pw' => $finalPassword, 'pw' => $finalPassword,
'salt' => $userSalt, 'salt' => $userSalt,
'grade' => 7, 'grade' => 6,
'name' => $nickname, 'name' => $nickname,
'reg_date' => $nowDate 'reg_date' => $nowDate
]); ]);
+9 -2
View File
@@ -17,11 +17,18 @@ if (!class_exists('\\sammo\\RootDB')) {
$rootDB = RootDB::db(); $rootDB = RootDB::db();
$rootDB->addHook('run_failed', function ($params) { $rootDB->throw_exception_on_nonsql_error = false;
$rootDB->nonsql_error_handler = function ($params) {
Json::die([
'step' => 'conn_fail'
]);
};
$rootDB->error_handler = function ($params) {
Json::die([ Json::die([
'step' => 'sql_fail' 'step' => 'sql_fail'
]); ]);
}); };
$memberCnt = $rootDB->queryFirstField('SELECT count(`NO`) from member'); $memberCnt = $rootDB->queryFirstField('SELECT count(`NO`) from member');
if ($memberCnt == 0) { if ($memberCnt == 0) {
+15 -7
View File
@@ -90,19 +90,19 @@ if (
//기본 파일 생성 //기본 파일 생성
if (!file_exists(AppConf::getUserIconPathFS())) { if (!file_exists(AppConf::getUserIconPathFS())) {
mkdir(AppConf::getUserIconPathFS(), 0775); mkdir(AppConf::getUserIconPathFS());
} }
if (!file_exists(ROOT . '/d_log')) { if (!file_exists(ROOT . '/d_log')) {
mkdir(ROOT . '/d_log', 0775); mkdir(ROOT . '/d_log');
} }
if (!file_exists(ROOT . '/d_setting')) { if (!file_exists(ROOT . '/d_setting')) {
mkdir(ROOT . '/d_setting', 0775); mkdir(ROOT . '/d_setting');
} }
if (!file_exists(ROOT . '/d_shared')) { if (!file_exists(ROOT . '/d_shared')) {
mkdir(ROOT . '/d_shared', 0775); mkdir(ROOT . '/d_shared');
} }
} }
@@ -150,12 +150,20 @@ if (!file_exists(ROOT . '/d_setting/.htaccess')) {
$rootDB = new \MeekroDB($host, $username, $password, $dbName, $port, 'utf8mb4'); $rootDB = new \MeekroDB($host, $username, $password, $dbName, $port, 'utf8mb4');
$rootDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true; $rootDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$rootDB->addHook('run_failed', function ($args) { $rootDB->throw_exception_on_nonsql_error = false;
$rootDB->nonsql_error_handler = function ($params) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => '에러.'. $args['error'] 'reason' => 'DB 접속에 실패했습니다.'
]); ]);
}); };
$rootDB->error_handler = function ($params) {
Json::die([
'result' => false,
'reason' => 'SQL을 제대로 실행하지 못했습니다. DB상태를 확인해 주세요.'
]);
};
$mysqli_obj = $rootDB->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨. $mysqli_obj = $rootDB->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
-17
View File
@@ -1,17 +0,0 @@
CREATE TABLE IF NOT EXISTS "api_log" (
"id" INTEGER NOT NULL,
"user_id" INTEGER NOT NULL,
"ip" TEXT NOT NULL,
"date" TEXT NOT NULL,
"path" TEXT NOT NULL,
"arg" TEXT,
"aux" TEXT,
PRIMARY KEY("id" AUTOINCREMENT)
);
CREATE INDEX IF NOT EXISTS "by_date" ON "api_log" (
"date" DESC
);
CREATE INDEX IF NOT EXISTS "by_user" ON "api_log" (
"user_id" ASC,
"date" DESC
);
+1 -11
View File
@@ -92,14 +92,4 @@ CREATE TABLE `login_token` (
INDEX `by_date` (`user_id`, `expire_date`) INDEX `by_date` (`user_id`, `expire_date`)
) )
COLLATE='utf8mb4_general_ci' COLLATE='utf8mb4_general_ci'
ENGINE=Aria; ENGINE=Aria;
CREATE TABLE `banned_member` (
`no` INT NOT NULL AUTO_INCREMENT,
`hashed_email` VARCHAR(128) NOT NULL COLLATE 'utf8mb4_general_ci' COMMENT 'SHA512(salt | email | salt )',
`info` TEXT NULL COLLATE 'utf8mb4_general_ci' COMMENT '부가정보',
PRIMARY KEY (`no`),
UNIQUE INDEX `email` (`hashed_email`(128))
)
COLLATE='utf8mb4_general_ci'
ENGINE = Aria;
+5
View File
@@ -61,6 +61,11 @@ class RootDB
if (self::$uDB === null) { if (self::$uDB === null) {
self::$uDB = new \MeekroDB(self::$host, self::$user, self::$password, self::$dbName, self::$port, self::$encoding); self::$uDB = new \MeekroDB(self::$host, self::$user, self::$password, self::$dbName, self::$port, self::$encoding);
self::$uDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true; self::$uDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
self::$uDB->error_handler = function () {
};
self::$uDB->throw_exception_on_error = true;
self::$uDB->throw_exception_on_nonsql_error = true;
} }
return self::$uDB; return self::$uDB;
} }
-58
View File
@@ -165,61 +165,3 @@
background: url('_tK_gameImagePath_/map/pokemon_v1/back_pal8.png') no-repeat; background: url('_tK_gameImagePath_/map/pokemon_v1/back_pal8.png') no-repeat;
background-size: 700px 500px; background-size: 700px 500px;
} }
/*CR 지도*/
.map_theme_cr .map_bglayer1{
background: url('_tK_gameImagePath_/map/cr/bg-fs8.png') no-repeat;
background-size: 700px 500px;
}
.map_theme_cr.map_detail .city_base .city_bg {
background-image: none !important;
width: 39.5px !important;
height: 39.5px !important;
left: 1px !important;
top: -4px !important;
opacity: 0.5;
}
.map_theme_cr.map_detail.small_width_map .city_base .city_bg {
background-image: none !important;
width: 28.5px !important;
height: 28.5px !important;
left: 6px !important;
top: 4px !important;
opacity: 0.5;
}
.map_theme_cr.map_detail .city_bg.bFF0000 { background-color: #FF0000; }
.map_theme_cr.map_detail .city_bg.b800000 { background-color: #800000; }
.map_theme_cr.map_detail .city_bg.bA0522D { background-color: #A0522D; }
.map_theme_cr.map_detail .city_bg.bFF6347 { background-color: #FF6347; }
.map_theme_cr.map_detail .city_bg.bFFA500 { background-color: #FFA500; }
.map_theme_cr.map_detail .city_bg.bFFDAB9 { background-color: #FFDAB9; }
.map_theme_cr.map_detail .city_bg.bFFD700 { background-color: #FFD700; }
.map_theme_cr.map_detail .city_bg.bFFFF00 { background-color: #FFFF00; }
.map_theme_cr.map_detail .city_bg.b7CFC00 { background-color: #7CFC00; }
.map_theme_cr.map_detail .city_bg.b00FF00 { background-color: #00FF00; }
.map_theme_cr.map_detail .city_bg.b808000 { background-color: #808000; }
.map_theme_cr.map_detail .city_bg.b008000 { background-color: #008000; }
.map_theme_cr.map_detail .city_bg.b2E8B57 { background-color: #2E8B57; }
.map_theme_cr.map_detail .city_bg.b008080 { background-color: #008080; }
.map_theme_cr.map_detail .city_bg.b20B2AA { background-color: #20B2AA; }
.map_theme_cr.map_detail .city_bg.b6495ED { background-color: #6495ED; }
.map_theme_cr.map_detail .city_bg.b7FFFD4 { background-color: #7FFFD4; }
.map_theme_cr.map_detail .city_bg.bAFEEEE { background-color: #AFEEEE; }
.map_theme_cr.map_detail .city_bg.b87CEEB { background-color: #87CEEB; }
.map_theme_cr.map_detail .city_bg.b00FFFF { background-color: #00FFFF; }
.map_theme_cr.map_detail .city_bg.b00BFFF { background-color: #00BFFF; }
.map_theme_cr.map_detail .city_bg.b0000FF { background-color: #0000FF; }
.map_theme_cr.map_detail .city_bg.b000080 { background-color: #000080; }
.map_theme_cr.map_detail .city_bg.b483D8B { background-color: #483D8B; }
.map_theme_cr.map_detail .city_bg.b7B68EE { background-color: #7B68EE; }
.map_theme_cr.map_detail .city_bg.bBA55D3 { background-color: #BA55D3; }
.map_theme_cr.map_detail .city_bg.b800080 { background-color: #800080; }
.map_theme_cr.map_detail .city_bg.bFF00FF { background-color: #FF00FF; }
.map_theme_cr.map_detail .city_bg.bFFC0CB { background-color: #FFC0CB; }
.map_theme_cr.map_detail .city_bg.bF5F5DC { background-color: #F5F5DC; }
.map_theme_cr.map_detail .city_bg.bE0FFFF { background-color: #E0FFFF; }
.map_theme_cr.map_detail .city_bg.bFFFFFF { background-color: #FFFFFF; }
.map_theme_cr.map_detail .city_bg.bA9A9A9 { background-color: #A9A9A9; }
-1
View File
@@ -21,7 +21,6 @@ $plock = $db->queryFirstField('SELECT plock FROM plock WHERE `type` ="GAME"');
<head> <head>
<title>삼국지 모의전투 HiDCHe</title> <title>삼국지 모의전투 HiDCHe</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?> <?=WebUtil::printCSS('../d_shared/common.css')?>
+3 -2
View File
@@ -6,7 +6,7 @@ include "func.php";
//로그인 검사 //로그인 검사
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
if($session->userGrade < 6) { if($session->userGrade < 5) {
die(requireAdminPermissionHTML()); die(requireAdminPermissionHTML());
} }
@@ -19,7 +19,6 @@ $admin = getAdmin();
<head> <head>
<title>게임관리</title> <title>게임관리</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?> <?=WebUtil::printCSS('../d_shared/common.css')?>
@@ -41,6 +40,8 @@ $admin = getAdmin();
<tr> <tr>
<td width=110 align=right>시작시간변경</td> <td width=110 align=right>시작시간변경</td>
<td width=285><input type=text size=20 maxlength=20 style=color:white;background-color:black;text-align:right; name=starttime value='<?=substr($admin['starttime'], 0, 19)?>'><input type=submit name=btn value=변경1></td> <td width=285><input type=text size=20 maxlength=20 style=color:white;background-color:black;text-align:right; name=starttime value='<?=substr($admin['starttime'], 0, 19)?>'><input type=submit name=btn value=변경1></td>
<td width=110 align=right>현재도시훈사</td>
<td width=285><?=$admin['city_rate']?></td>
</tr> </tr>
<tr> <tr>
<td width=110 align=right>최대 장수</td> <td width=110 align=right>최대 장수</td>
+23 -2
View File
@@ -6,7 +6,7 @@ include "func.php";
//로그인 검사 //로그인 검사
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
if ($session->userGrade < 6) { if ($session->userGrade < 5) {
header('location:_admin1.php'); header('location:_admin1.php');
die(); die();
} }
@@ -74,7 +74,28 @@ switch ($btn) {
case "120분턴": $turnterm = 120; break; case "120분턴": $turnterm = 120; break;
default: throw new \Exception("알 수 없는 턴 기간"); default: throw new \Exception("알 수 없는 턴 기간");
} }
ServerTool::changeServerTerm($turnterm); $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</>으로 변경됩니다."]);
break; break;
} }
+1 -2
View File
@@ -7,7 +7,7 @@ include "func.php";
//로그인 검사 //로그인 검사
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
if ($session->userGrade < 6) { if ($session->userGrade < 5) {
die(requireAdminPermissionHTML()); die(requireAdminPermissionHTML());
} }
@@ -20,7 +20,6 @@ $db = DB::db();
<head> <head>
<title>회원관리</title> <title>회원관리</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?> <?= WebUtil::printCSS('../d_shared/common.css') ?>
+20 -22
View File
@@ -2,8 +2,6 @@
namespace sammo; namespace sammo;
use sammo\Enums\MessageType;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
@@ -15,7 +13,7 @@ $msg = Util::getPost('msg', 'string');
//로그인 검사 //로그인 검사
$session = Session::requireLogin()->loginGame()->setReadOnly(); $session = Session::requireLogin()->loginGame()->setReadOnly();
if ($session->userGrade < 6) { if ($session->userGrade < 5) {
header('location:_admin2.php'); header('location:_admin2.php');
} }
@@ -33,18 +31,18 @@ $src = MessageTarget::buildQuick($session->generalID);
$genObjList = []; $genObjList = [];
$env = []; $env = [];
if ($genlist) { if ($genlist) {
$genObjList = General::createObjListFromDB($genlist); $genObjList = General::createGeneralObjListFromDB($genlist);
$env = $gameStor->cacheAll(); $env = $gameStor->cacheAll();
} }
switch ($btn) { switch ($btn) {
case "전체 접속허용": case "전체 접속허용":
$db->update('general_access_log', [ $db->update('general', [
'refresh_score' => 0 'con' => 0
], true); ], true);
break; break;
case "전체 접속제한": case "전체 접속제한":
$db->update('general_access_log', [ $db->update('general', [
'refresh_score' => 1000 'con' => 1000
], true); ], true);
break; break;
case "블럭 해제": case "블럭 해제":
@@ -113,7 +111,7 @@ switch ($btn) {
case "경험치1000": case "경험치1000":
$text = $btn . " 지급!"; $text = $btn . " 지급!";
foreach ($genlist as $generalID) { foreach ($genlist as $generalID) {
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []); $msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true); $msg->send(true);
} }
$db->update('general', [ $db->update('general', [
@@ -124,7 +122,7 @@ switch ($btn) {
case "공헌치1000": case "공헌치1000":
$text = $btn . " 지급!"; $text = $btn . " 지급!";
foreach ($genlist as $generalID) { foreach ($genlist as $generalID) {
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []); $msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true); $msg->send(true);
} }
$db->update('general', [ $db->update('general', [
@@ -135,7 +133,7 @@ switch ($btn) {
case "보숙10000": case "보숙10000":
$text = "보병숙련도+10000 지급!"; $text = "보병숙련도+10000 지급!";
foreach ($genlist as $generalID) { foreach ($genlist as $generalID) {
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []); $msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true); $msg->send(true);
} }
$db->update('general', [ $db->update('general', [
@@ -145,7 +143,7 @@ switch ($btn) {
case "궁숙10000": case "궁숙10000":
$text = "궁병숙련도+10000 지급!"; $text = "궁병숙련도+10000 지급!";
foreach ($genlist as $generalID) { foreach ($genlist as $generalID) {
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []); $msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true); $msg->send(true);
} }
$db->update('general', [ $db->update('general', [
@@ -156,7 +154,7 @@ switch ($btn) {
$src = MessageTarget::buildQuick($session->generalID); $src = MessageTarget::buildQuick($session->generalID);
$text = "기병숙련도+10000 지급!"; $text = "기병숙련도+10000 지급!";
foreach ($genlist as $generalID) { foreach ($genlist as $generalID) {
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []); $msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true); $msg->send(true);
} }
$db->update('general', [ $db->update('general', [
@@ -167,7 +165,7 @@ switch ($btn) {
$src = MessageTarget::buildQuick($session->generalID); $src = MessageTarget::buildQuick($session->generalID);
$text = "귀병숙련도+10000 지급!"; $text = "귀병숙련도+10000 지급!";
foreach ($genlist as $generalID) { foreach ($genlist as $generalID) {
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []); $msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true); $msg->send(true);
} }
$db->update('general', [ $db->update('general', [
@@ -178,7 +176,7 @@ switch ($btn) {
$src = MessageTarget::buildQuick($session->generalID); $src = MessageTarget::buildQuick($session->generalID);
$text = "차병숙련도+10000 지급!"; $text = "차병숙련도+10000 지급!";
foreach ($genlist as $generalID) { foreach ($genlist as $generalID) {
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []); $msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true); $msg->send(true);
} }
$db->update('general', [ $db->update('general', [
@@ -186,19 +184,19 @@ switch ($btn) {
], '`no` IN %li', $genlist); ], '`no` IN %li', $genlist);
break; break;
case "접속 허용": case "접속 허용":
$db->update('general_access_log', [ $db->update('general', [
'refresh_score' => 0 'con' => 0
], '`general_id` IN %li', $genlist); ], '`no` IN %li', $genlist);
break; break;
case "접속 제한": case "접속 제한":
$db->update('general_access_log', [ $db->update('general', [
'refresh_score' => 1000 'con' => 1000
], '`general_id` IN %li', $genlist); ], '`no` IN %li', $genlist);
break; break;
case "메세지 전달": case "메세지 전달":
$text = $msg ?? ''; $text = $msg ?? '';
foreach ($genlist as $generalID) { foreach ($genlist as $generalID) {
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []); $msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true); $msg->send(true);
} }
break; break;
+132
View File
@@ -0,0 +1,132 @@
<?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 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>
+84
View File
@@ -0,0 +1,84 @@
<?php
namespace sammo;
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(
Message::MSGTYPE_PRIVATE,
$src,
MessageTarget::buildQuick($generalID),
$msg,
new \DateTime(),
new \DateTime('9999-12-31'),
[]
);
if ($msgObj) {
$msgObj->send(true);
}
}
break;
}
header('location:_admin4.php');
+15 -2
View File
@@ -20,7 +20,7 @@ if ($type2 < 0 || $type2 > 6) {
//로그인 검사 //로그인 검사
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
if ($session->userGrade < 6) { if ($session->userGrade < 5) {
die(requireAdminPermissionHTML()); die(requireAdminPermissionHTML());
} }
@@ -38,7 +38,6 @@ $sel2[$type2] = "selected";
<head> <head>
<title>일제정보</title> <title>일제정보</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?> <?= WebUtil::printCSS('../d_shared/common.css') ?>
@@ -66,6 +65,8 @@ $sel2[$type2] = "selected";
<option <?= $sel[8] ?? '' ?> value=8>평무</option> <option <?= $sel[8] ?? '' ?> value=8>평무</option>
<option <?= $sel[9] ?? '' ?> value=9>평지</option> <option <?= $sel[9] ?? '' ?> value=9>평지</option>
<option <?= $sel[10] ?? '' ?> value=10>평Lv</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[13] ?? '' ?> value=13>보숙</option>
<option <?= $sel[14] ?? '' ?> value=14>궁숙</option> <option <?= $sel[14] ?? '' ?> value=14>궁숙</option>
<option <?= $sel[15] ?? '' ?> value=15>기숙</option> <option <?= $sel[15] ?? '' ?> value=15>기숙</option>
@@ -103,6 +104,8 @@ $sel2[$type2] = "selected";
<table align=center width=1600 class="tb_layout bg0"> <table align=center width=1600 class="tb_layout bg0">
<tr class='bg1'> <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>
<td align=center>장수</td> <td align=center>장수</td>
<td align=center>속령</td> <td align=center>속령</td>
@@ -143,6 +146,8 @@ SELECT
A.gold, A.gold,
A.rice, A.rice,
COUNT(B.nation) AS gennum, 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.dex1)) AS dex1,
ROUND(AVG(B.dex2)) AS dex2, ROUND(AVG(B.dex2)) AS dex2,
ROUND(AVG(B.dex3)) AS dex3, ROUND(AVG(B.dex3)) AS dex3,
@@ -187,6 +192,12 @@ GROUP BY B.nation
case 10: case 10:
$query .= " order by avg(B.explevel) desc"; $query .= " order by avg(B.explevel) desc";
break; break;
case 11:
$query .= " order by avg(B.connect) desc";
break;
case 12:
$query .= " order by avg(B.con) desc";
break;
case 13: case 13:
$query .= " order by avg(B.dex1) desc"; $query .= " order by avg(B.dex1) desc";
break; break;
@@ -228,6 +239,8 @@ from city where nation=%i', $nation['nation']);
echo " echo "
<tr> <tr>
<td align=center style=background-color:{$nation['color']};color:" . newColor($nation['color']) . ";>{$nation['name']}</td> <td align=center style=background-color:{$nation['color']};color:" . newColor($nation['color']) . ";>{$nation['name']}</td>
<td align=center>&nbsp;{$nation['connect']}&nbsp;</td>
<td align=center>&nbsp;{$nation['con']}&nbsp;</td>
<td align=center>&nbsp;{$nation['power']}&nbsp;</td> <td align=center>&nbsp;{$nation['power']}&nbsp;</td>
<td align=center>&nbsp;{$gen['cnt']}&nbsp;</td> <td align=center>&nbsp;{$gen['cnt']}&nbsp;</td>
<td align=center>&nbsp;{$city['cnt']}&nbsp;</td> <td align=center>&nbsp;{$city['cnt']}&nbsp;</td>
+1 -1
View File
@@ -12,7 +12,7 @@ $nation = Util::getPost('nation', 'int');
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID(); $userID = Session::getUserID();
if ($session->userGrade < 6) { if ($session->userGrade < 5) {
header('location:_admin5.php'); header('location:_admin5.php');
die(); die();
} }
+2 -5
View File
@@ -2,8 +2,6 @@
namespace sammo; namespace sammo;
use sammo\Enums\GeneralQueryMode;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
@@ -37,7 +35,7 @@ if ($reqQueryType === null || !key_exists($reqQueryType, $queryMap)) {
//로그인 검사 //로그인 검사
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
if ($session->userGrade < 6) { if ($session->userGrade < 5) {
die(requireAdminPermissionHTML()); die(requireAdminPermissionHTML());
} }
@@ -76,7 +74,7 @@ if (!$gen) {
$gen = $generalBasicList[0]['no']; $gen = $generalBasicList[0]['no'];
} }
$generalObj = General::createObjFromDB($gen, null, GeneralQueryMode::FullWithAccessLog); $generalObj = General::createGeneralObjFromDB($gen);
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
@@ -85,7 +83,6 @@ $generalObj = General::createObjFromDB($gen, null, GeneralQueryMode::FullWithAcc
<head> <head>
<title>로그정보</title> <title>로그정보</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?> <?= WebUtil::printCSS('../d_shared/common.css') ?>
+1 -2
View File
@@ -12,7 +12,7 @@ $type = 0;
//로그인 검사 //로그인 검사
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
if ($session->userGrade < 6) { if ($session->userGrade < 5) {
die(requireAdminPermissionHTML()); die(requireAdminPermissionHTML());
} }
@@ -30,7 +30,6 @@ $sel[$type] = "selected";
<head> <head>
<title>외교정보</title> <title>외교정보</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?> <?= WebUtil::printCSS('../d_shared/common.css') ?>
+4 -3
View File
@@ -7,7 +7,7 @@ include "func.php";
//로그인 검사 //로그인 검사
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
if ($session->userGrade < 6) { if ($session->userGrade < 5) {
die('권한 부족'); die('권한 부족');
} }
@@ -26,7 +26,8 @@ foreach ($db->queryFirstColumn(
} }
$inheritPointManager = InheritancePointManager::getInstance(); $inheritPointManager = InheritancePointManager::getInstance();
foreach(General::createObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc = 0')) as $genObj){ foreach(General::createGeneralObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc = 0')) as $genObj){
$inheritPointManager->mergeTotalInheritancePoint($genObj); $inheritPointManager->mergeTotalInheritancePoint($genObj, true);
$inheritPointManager->applyInheritanceUser($genObj->getVar('owner')); $inheritPointManager->applyInheritanceUser($genObj->getVar('owner'));
$inheritPointManager->clearInheritancePoint($genObj);
} }
-1
View File
@@ -28,7 +28,6 @@ $templates = new \League\Plates\Engine(__DIR__ . '/templates');
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" /> <meta name="viewport" content="width=500" />
<title><?= UniqueConst::$serverName ?>: 명장일람</title> <title><?= UniqueConst::$serverName ?>: 명장일람</title>
-1
View File
@@ -14,7 +14,6 @@ increaseRefresh("왕조일람", 1);
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 왕조일람</title> <title><?= UniqueConst::$serverName ?>: 왕조일람</title>
-1
View File
@@ -24,7 +24,6 @@ $serverID = $emperior['server_id'] ?? ($emperior['serverID'] ?? null);
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 왕조일람</title> <title><?= UniqueConst::$serverName ?>: 왕조일람</title>
+8 -17
View File
@@ -16,13 +16,10 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("장수일람", 2); increaseRefresh("장수일람", 2);
$me = $db->queryFirstRow( $me = $db->queryFirstRow('SELECT con,turntime FROM general WHERE owner = %i', $userID);
'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']); $con = checkLimit($me['con']);
if ($limitState >= 2) { if ($con >= 2) {
printLimitMsg($me['turntime']); printLimitMsg($me['turntime']);
exit(); exit();
} }
@@ -44,7 +41,6 @@ if ($gameStor->isunited) {
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 장수일람</title> <title><?= UniqueConst::$serverName ?>: 장수일람</title>
@@ -105,7 +101,7 @@ if ($gameStor->isunited) {
6 => ['dedication', true], 6 => ['dedication', true],
7 => ['officer_level', true], 7 => ['officer_level', true],
8 => ['killturn', false], 8 => ['killturn', false],
9 => ['refresh_score_total', true], 9 => ['connect', true],
10 => ['experience', true], 10 => ['experience', true],
11 => ['personal', true], 11 => ['personal', true],
12 => ['special', true], 12 => ['special', true],
@@ -114,12 +110,7 @@ if ($gameStor->isunited) {
15 => ['npc', true], 15 => ['npc', true],
][$type]; ][$type];
$generalList = $db->query( $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' : '');
'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 " echo "
<table align=center width=1000 class='tb_layout bg0'> <table align=center width=1000 class='tb_layout bg0'>
@@ -171,7 +162,7 @@ if ($gameStor->isunited) {
$name = $name . '<br><small>(' . $ownerNameList[$general['owner']] . ')</small>'; $name = $name . '<br><small>(' . $ownerNameList[$general['owner']] . ')</small>';
} }
$general['refresh_score_total'] = Util::round($general['refresh_score_total'], -1); $general['connect'] = Util::round($general['connect'], -1);
$imageTemp = GetImageURL($general['imgsvr']); $imageTemp = GetImageURL($general['imgsvr']);
echo " echo "
@@ -200,8 +191,8 @@ if ($gameStor->isunited) {
<td align=center>$strength</td> <td align=center>$strength</td>
<td align=center>$intel</td> <td align=center>$intel</td>
<td align=center>{$general['killturn']}</td> <td align=center>{$general['killturn']}</td>
<td align=center>" . $general['refresh_score_total'] ?? 0; <td align=center>{$general['connect']}";
echo "<br>【" . getRefreshScoreText($general['refresh_score_total'] ?? 0) . "】</td> echo "<br>【" . getConnect($general['connect']) . "】</td>
</tr>"; </tr>";
} }
echo " echo "
-1
View File
@@ -43,7 +43,6 @@ if ($scenarioIdx && key_exists($scenarioIdx, $scenarioList[$seasonIdx] ?? [])) {
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" /> <meta name="viewport" content="width=500" />
<title><?= UniqueConst::$serverName ?>: 명예의 전당</title> <title><?= UniqueConst::$serverName ?>: 명예의 전당</title>
+3 -7
View File
@@ -13,13 +13,10 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['killturn', 'autorun_user', 'turnterm']); $gameStor->cacheValues(['killturn', 'autorun_user', 'turnterm']);
increaseRefresh("세력일람", 2); increaseRefresh("세력일람", 2);
$me = $db->queryFirstRow( $me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
'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']); $con = checkLimit($me['con']);
if ($limitState >= 2) { if ($con >= 2) {
printLimitMsg($me['turntime']); printLimitMsg($me['turntime']);
exit(); exit();
} }
@@ -29,7 +26,6 @@ if ($limitState >= 2) {
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 세력일람</title> <title><?= UniqueConst::$serverName ?>: 세력일람</title>
-1
View File
@@ -24,7 +24,6 @@ $sel[$type] = "selected";
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 빙의일람</title> <title><?= UniqueConst::$serverName ?>: 빙의일람</title>
+34 -33
View File
@@ -2,29 +2,36 @@
namespace sammo; namespace sammo;
use sammo\Enums\GeneralAccessLogColumn;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("갱신정보", 1); increaseRefresh("갱신정보", 2);
$admin = $gameStor->getValues(['year', 'month', 'refresh', 'maxrefresh', 'maxonline', 'recentTraffic']); $admin = $gameStor->getValues(['year', 'month', 'refresh', 'maxrefresh', 'maxonline']);
$recentTraffic = $admin['recentTraffic'] ?? []; $log = getRawFileLogRecent(__DIR__ . '/logs/' . UniqueConst::$serverID . '/_traffic.txt', 11, 100);
$date = [];
$year = [];
$month = [];
$refresh = [];
$online = [];
$curonline = getOnlineNum(); $curonline = getOnlineNum();
foreach ($log as $i => $value) {
$recentTraffic[] = [ $parse = Json::decode($value);
'year' => $admin['year'], $date[$i] = $parse[0];
'month' => $admin['month'], $year[$i] = $parse[1];
'refresh' => $admin['refresh'], $month[$i] = $parse[2];
'online' => $curonline, $refresh[$i] = $parse[3];
'date' => TimeUtil::now() $online[$i] = $parse[4];
]; }
$year[] = $admin['year'];
$month[] = $admin['month'];
$date[] = TimeUtil::now();
if ($admin['maxrefresh'] == 0) { if ($admin['maxrefresh'] == 0) {
$admin['maxrefresh'] = 1; $admin['maxrefresh'] = 1;
@@ -45,7 +52,6 @@ if ($admin['maxonline'] < $curonline) {
<head> <head>
<title><?= UniqueConst::$serverName ?>: 트래픽정보</title> <title><?= UniqueConst::$serverName ?>: 트래픽정보</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?> <?= WebUtil::printCSS('../d_shared/common.css') ?>
@@ -98,13 +104,13 @@ if ($admin['maxonline'] < $curonline) {
</td> </td>
</tr> </tr>
<?php <?php
foreach ($recentTraffic as $trafficItem) { $refresh[] = $admin['refresh'];
$value = $trafficItem['refresh']; foreach ($refresh as $i => $value) {
$w = round($value / $admin['maxrefresh'] * 100, 1); $w = round($value / $admin['maxrefresh'] * 100, 1);
$color = getTrafficColor($w); $color = getTrafficColor($w);
$dt = substr($trafficItem['date'], 11, 5); ?> $dt = substr($date[$i], 11, 5); ?>
<tr height=30> <tr height=30>
<td width=100 align=center><?= $trafficItem['year'] ?>년 <?= $trafficItem['month'] ?>월</td> <td width=100 align=center><?= $year[$i] ?>년 <?= $month[$i] ?>월</td>
<td width=60 align=center class='bg2'><?= $dt ?></td> <td width=60 align=center class='bg2'><?= $dt ?></td>
<td width=2 align=center class='bg1'></td> <td width=2 align=center class='bg1'></td>
<td width=320> <td width=320>
@@ -139,13 +145,13 @@ if ($admin['maxonline'] < $curonline) {
</td> </td>
</tr> </tr>
<?php <?php
foreach ($recentTraffic as $trafficItem) { $online[] = $curonline;
$value = $trafficItem['online']; foreach ($online as $i => $value) {
$w = round($value / $admin['maxonline'] * 100, 1); $w = round($value / $admin['maxonline'] * 100, 1);
$color = getTrafficColor($w); $color = getTrafficColor($w);
$dt = substr($trafficItem['date'], 11, 5); ?> $dt = substr($date[$i], 11, 5); ?>
<tr height=30> <tr height=30>
<td width=100 align=center><?= $trafficItem['year'] ?>년 <?= $trafficItem['month'] ?>월</td> <td width=100 align=center><?= $year[$i] ?>년 <?= $month[$i] ?>월</td>
<td width=60 align=center class='bg2'><?= $dt ?></td> <td width=60 align=center class='bg2'><?= $dt ?></td>
<td width=2 align=center class='bg1'></td> <td width=2 align=center class='bg1'></td>
<td width=320> <td width=320>
@@ -180,24 +186,19 @@ if ($admin['maxonline'] < $curonline) {
</td> </td>
</tr> </tr>
<?php <?php
$totalRefresh = [ $max_refresh = $db->queryFirstRow('SELECT sum(refresh) as refresh, sum(`connect`) as `connect` from general');
...$db->queryFirstRow('SELECT sum(`refresh`) as `refresh`, sum(`refresh_score_total`) as `refresh_score_total` from general_access_log'), $max_refresh['name'] = '접속자 총합';
'name' => '접속자 총합'
];
$top5Refresh = $db->query( $refresh_result = array_merge([$max_refresh], $db->query('SELECT `name`,refresh,`connect` FROM general ORDER BY refresh DESC LIMIT 5'));
'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 (array_merge([$totalRefresh], $top5Refresh) as $i => $user) { foreach ($refresh_result as $i => $user) {
$w = round($user['refresh'] / max(1, $totalRefresh['refresh']) * 100, 1); $w = round($user['refresh'] / max(1, $max_refresh['refresh']) * 100, 1);
$w2 = round(100 - $w, 1); $w2 = round(100 - $w, 1);
$color = getTrafficColor($w); $color = getTrafficColor($w);
?> ?>
<tr> <tr>
<td width=98 align=center><?= $user['name'] ?></td> <td width=98 align=center><?= $user['name'] ?></td>
<td width=98 align=center><?= $user['refresh_score_total'] ?>(<?= $user['refresh'] ?>)</td> <td width=98 align=center><?= $user['connect'] ?>(<?= $user['refresh'] ?>)</td>
<td width=798> <td width=798>
<?php if ($w == 0) : ?> <?php if ($w == 0) : ?>
<?php elseif ($w < 10) : ?> <?php elseif ($w < 10) : ?>
+11 -17
View File
@@ -2,8 +2,6 @@
namespace sammo; namespace sammo;
use sammo\Enums\GeneralLiteQueryMode;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\RankColumn; use sammo\Enums\RankColumn;
include "lib.php"; include "lib.php";
@@ -23,15 +21,12 @@ $generalID = $session->generalID;
$me = $db->queryFirstRow( $me = $db->queryFirstRow('SELECT no,tournament,con,turntime from general where owner=%i', $userID);
'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']); $admin = $gameStor->getValues(['tournament', 'phase', 'tnmt_type', 'turnterm', 'develcost']);
$turnTerm = $admin['turnterm']; $turnTerm = $admin['turnterm'];
$limitState = checkLimit($me['refresh_score']); $con = checkLimit($me['con']);
if ($limitState >= 2) { if ($con >= 2) {
printLimitMsg($me['turntime']); printLimitMsg($me['turntime']);
exit(); exit();
} }
@@ -112,13 +107,12 @@ if ($str3) {
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<?php if ($limitState == 1) { <?php if ($con == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다!"); MessageBox("접속제한이 얼마 남지 않았습니다!");
} ?> } ?>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 베팅장</title> <title><?= UniqueConst::$serverName ?>: 베팅장</title>
@@ -507,28 +501,28 @@ if ($str3) {
$tournamentType = [ $tournamentType = [
'전 력 전' => [ '전 력 전' => [
'종합', '종합',
function (GeneralLite $general) { function (General $general) {
return $general->getVar('leadership') + $general->getVar('strength') + $general->getVar('intel'); return $general->getVar('leadership') + $general->getVar('strength') + $general->getVar('intel');
}, },
'tt', 'tt',
], ],
'통 솔 전' => [ '통 솔 전' => [
'통솔', '통솔',
function (GeneralLite $general) { function (General $general) {
return $general->getVar('leadership'); return $general->getVar('leadership');
}, },
'tl', 'tl',
], ],
'일 기 토' => [ '일 기 토' => [
'무력', '무력',
function (GeneralLite $general) { function (General $general) {
return $general->getVar('strength'); return $general->getVar('strength');
}, },
'ts', 'ts',
], ],
'설 전' => [ '설 전' => [
'지력', '지력',
function (GeneralLite $general) { function (General $general) {
return $general->getVar('intel'); return $general->getVar('intel');
}, },
'ti', 'ti',
@@ -565,12 +559,12 @@ if ($str3) {
$winColumn = RankColumn::from("{$rankColumn}w"); $winColumn = RankColumn::from("{$rankColumn}w");
$drawColumn = RankColumn::from("{$rankColumn}d"); $drawColumn = RankColumn::from("{$rankColumn}d");
$loseColumn = RankColumn::from("{$rankColumn}l"); $loseColumn = RankColumn::from("{$rankColumn}l");
$tournamentRankerList = GeneralLite::createObjListFromDB( $tournamentRankerList = General::createGeneralObjListFromDB(
$db->queryFirstColumn('SELECT general_id FROM rank_data WHERE `type`= %s ORDER BY value DESC LIMIT 40', $gameColumn->value), $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'], [$prizeColumn->value, $gameColumn->value, $winColumn->value, $drawColumn->value, $loseColumn->value, 'leadership', 'strength', 'intel', 'no', 'npc', 'name'],
GeneralLiteQueryMode::Core 0
); );
usort($tournamentRankerList, function (GeneralLite $lhs, GeneralLite $rhs) use ($gameColumn, $winColumn, $drawColumn, $loseColumn) { usort($tournamentRankerList, function (General $lhs, General $rhs) use ($gameColumn, $winColumn, $drawColumn, $loseColumn) {
$result = - ($lhs->getRankVar($gameColumn) <=> $rhs->getRankVar($gameColumn)); $result = - ($lhs->getRankVar($gameColumn) <=> $rhs->getRankVar($gameColumn));
if ($result !== 0) return $result; if ($result !== 0) return $result;
$result = - ( $result = - (
+5 -5
View File
@@ -34,7 +34,6 @@ $templates = new \League\Plates\Engine('templates');
<head> <head>
<title><?= UniqueConst::$serverName ?>: 도시정보</title> <title><?= UniqueConst::$serverName ?>: 도시정보</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?> <?= WebUtil::printJS('../d_shared/common_path.js') ?>
@@ -177,7 +176,7 @@ $templates = new \League\Plates\Engine('templates');
$valid = 1; $valid = 1;
} }
if ($userGrade >= 6) { if ($userGrade >= 5) {
$valid = true; $valid = true;
$showDetailedInfo = true; $showDetailedInfo = true;
} }
@@ -211,7 +210,7 @@ $templates = new \League\Plates\Engine('templates');
$city['trade'] = "- "; $city['trade'] = "- ";
} }
$dbColumns = General::mergeQueryColumn(['npc', 'defence_train', 'no', 'picture', 'imgsvr', 'name', 'injury', 'leadership', 'strength', 'intel', 'officer_level', 'nation', 'crewtype', 'crew', 'train', 'atmos'])[0]; $dbColumns = General::mergeQueryColumn(['npc', 'defence_train', 'no', 'picture', 'imgsvr', 'name', 'injury', 'leadership', 'strength', 'intel', 'officer_level', 'nation', 'crewtype', 'crew', 'train', 'atmos'], 2)[0];
if ($showDetailedInfo) { if ($showDetailedInfo) {
$generals = $db->query( $generals = $db->query(
'SELECT %l from general where city=%i order by turntime', 'SELECT %l from general where city=%i order by turntime',
@@ -275,7 +274,7 @@ $templates = new \League\Plates\Engine('templates');
$ourGeneral = false; $ourGeneral = false;
} }
if ($userGrade == 7) { if ($userGrade == 6) {
$ourGeneral = true; $ourGeneral = true;
} }
@@ -327,7 +326,8 @@ $templates = new \League\Plates\Engine('templates');
if ($ourGeneral && !$isNPC) { if ($ourGeneral && !$isNPC) {
$turnText = []; $turnText = [];
foreach ($generalTurnList[$general['no']] as $turnRawIdx => $turn) { $generalObj = new General($general, null, null, null, null, null, false);
foreach ($generalTurnList[$generalObj->getID()] as $turnRawIdx => $turn) {
$turnIdx = $turnRawIdx + 1; $turnIdx = $turnRawIdx + 1;
$turnText[] = "{$turnIdx} : $turn"; $turnText[] = "{$turnIdx} : $turn";
} }
+4 -8
View File
@@ -19,15 +19,12 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("암행부", 1); increaseRefresh("암행부", 1);
$me = $db->queryFirstRow( $me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,permission,penalty from general where owner=%i', $userID);
'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']); $nationLevel = $db->queryFirstField('SELECT level FROM nation WHERE nation=%i', $me['nation']);
$limitState = checkLimit($me['refresh_score']); $con = checkLimit($me['con']);
if ($limitState >= 2) { if ($con >= 2) {
printLimitMsg($me['turntime']); printLimitMsg($me['turntime']);
exit(); exit();
} }
@@ -48,13 +45,12 @@ $templates = new \League\Plates\Engine('templates');
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<?php if ($limitState == 1) { <?php if ($con == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다!"); MessageBox("접속제한이 얼마 남지 않았습니다!");
} ?> } ?>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 암행부</title> <title><?= UniqueConst::$serverName ?>: 암행부</title>
-1
View File
@@ -42,7 +42,6 @@ if ($meLevel >= 5) {
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 인사부</title> <title><?= UniqueConst::$serverName ?>: 인사부</title>
-1
View File
@@ -33,7 +33,6 @@ $sel = [$type => "selected"];
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 세력도시</title> <title><?= UniqueConst::$serverName ?>: 세력도시</title>
+4 -7
View File
@@ -42,7 +42,6 @@ if ($gameStor->isunited) {
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 세력장수</title> <title><?= UniqueConst::$serverName ?>: 세력장수</title>
@@ -97,7 +96,7 @@ if ($gameStor->isunited) {
7 => ['gold', true], 7 => ['gold', true],
8 => ['rice', true], 8 => ['rice', true],
9 => ['crew', true], 9 => ['crew', true],
10 => ['refresh_score_total', true], 10 => ['connect', true],
11 => ['personal', true], 11 => ['personal', true],
12 => ['special', true], 12 => ['special', true],
13 => ['special2', true], 13 => ['special2', true],
@@ -105,9 +104,7 @@ if ($gameStor->isunited) {
15 => ['npc', true], 15 => ['npc', true],
][$type]; ][$type];
$generalList = $db->query( $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' : '');
'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 " echo "
<table align=center class='tb_layout bg0'> <table align=center class='tb_layout bg0'>
@@ -175,8 +172,8 @@ if ($gameStor->isunited) {
<td align=center>" . displayCharInfo($general['personal']) . "</td> <td align=center>" . displayCharInfo($general['personal']) . "</td>
<td align=center>" . displaySpecialDomesticInfo($general['special']) . " / " . displaySpecialWarInfo($general['special2']) . "</td> <td align=center>" . displaySpecialDomesticInfo($general['special']) . " / " . displaySpecialWarInfo($general['special2']) . "</td>
<td align=center>{$general['belong']}</td> <td align=center>{$general['belong']}</td>
<td align=center>". $general['refresh_score_total'] ?? 0; <td align=center>{$general['connect']}";
echo "<br>(" . getRefreshScoreText($general['refresh_score_total'] ?? 0) . ")</td> echo "<br>(" . getConnect($general['connect']) . ")</td>
</tr>"; </tr>";
} }
echo " echo "
-1
View File
@@ -25,7 +25,6 @@ if ($nationID == 0) {
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 세력정보</title> <title><?= UniqueConst::$serverName ?>: 세력정보</title>
+11 -46
View File
@@ -2,10 +2,6 @@
namespace sammo; namespace sammo;
use sammo\Enums\GeneralAccessLogColumn;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\TableName;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
@@ -24,7 +20,7 @@ $gameStor->cacheValues(['turntime', 'opentime', 'autorun_user', 'npcmode']);
increaseRefresh("내정보", 1); increaseRefresh("내정보", 1);
$me = General::createObjFromDB($generalID, null, GeneralQueryMode::FullWithAccessLog); $me = General::createGeneralObjFromDB($generalID);
$myset = $me->getVar('myset'); $myset = $me->getVar('myset');
if ($myset > 0) { if ($myset > 0) {
@@ -33,15 +29,7 @@ if ($myset > 0) {
$submit = 'hidden'; $submit = 'hidden';
} }
$lastRefresh = $db->queryFirstField( $targetTime = addTurn($me->getVar('lastrefresh'), $gameStor->turnterm, 2);
'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 ($gameStor->turntime <= $gameStor->opentime) {
//서버 가오픈시 할 수 있는 행동 //서버 가오픈시 할 수 있는 행동
if ($me->getNPCType() == 0 && $me->getNationID() == 0) { if ($me->getNPCType() == 0 && $me->getNationID() == 0) {
@@ -51,26 +39,19 @@ if ($gameStor->turntime <= $gameStor->opentime) {
} }
} }
if ($me->getNationID() == 0) { if($me->getNationID() == 0){
$showBuildNationCandidateBtn = true; $showBuildNationCandidateBtn = true;
} }
} }
$use_treatment = $me->getAuxVar('use_treatment') ?? 10; $use_treatment = $me->getAuxVar('use_treatment') ?? 10;
$use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1; $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
$changeDefence999Train = -3;
$changeDefence999Atmos = -6;
$changeDefence999Train = $me->onCalcDomestic('changeDefenceTrain', "train999", $changeDefence999Train);
$changeDefence999Atmos = $me->onCalcDomestic('changeDefenceTrain', "atmos999", $changeDefence999Atmos);
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" /> <meta name="viewport" content="width=500" />
<title><?= UniqueConst::$serverName ?>: 내정보</title> <title><?= UniqueConst::$serverName ?>: 내정보</title>
@@ -99,13 +80,13 @@ $changeDefence999Atmos = $me->onCalcDomestic('changeDefenceTrain', "atmos999", $
<div class="col">내 정 보<br><?= backButton() ?></div> <div class="col">내 정 보<br><?= backButton() ?></div>
</div> </div>
<div class="row gx-0"> <div class="row gx-0">
<div class="col col-12 col-lg-6"> <div class="col col-12 col-md-6">
<div class="row"> <div class="row">
<div class="col"><?php generalInfo($me); ?><?php generalInfo2($me); ?></div> <div class="col"><?php generalInfo($me); ?><?php generalInfo2($me); ?></div>
</div> </div>
</div> </div>
<div class="col col-12 col-lg-6"> <div class="col col-12 col-md-6">
<div class="row mx-0 gx-0"> <div class="row mx-0 gx-0">
<div class="col" style='padding-left:2ch;'> <div class="col" style='padding-left:2ch;'>
토너먼트 【 토너먼트 【
@@ -135,22 +116,11 @@ $changeDefence999Atmos = $me->onCalcDomestic('changeDefenceTrain', "atmos999", $
<?php foreach ([90, 80, 60, 40] as $targetDefenceTrain) : ?> <?php foreach ([90, 80, 60, 40] as $targetDefenceTrain) : ?>
<option value='<?= $targetDefenceTrain ?>' <?= $me->getVar('defence_train') == $targetDefenceTrain ? "selected" : ""; ?>><?= formatDefenceTrain($targetDefenceTrain) ?>(훈사<?= $targetDefenceTrain ?>)</option> <option value='<?= $targetDefenceTrain ?>' <?= $me->getVar('defence_train') == $targetDefenceTrain ? "selected" : ""; ?>><?= formatDefenceTrain($targetDefenceTrain) ?>(훈사<?= $targetDefenceTrain ?>)</option>
<?php endforeach; ?> <?php endforeach; ?>
<option value=999 <?= $me->getVar('defence_train') == 999 ? "selected" : ""; ?>><?= formatDefenceTrain(999) ?> <option value=999 <?= $me->getVar('defence_train') == 999 ? "selected" : ""; ?>><?= formatDefenceTrain(999) ?>[훈련, 사기 -3]</option>
<?php if ($changeDefence999Train != 0 || $changeDefence999Train != 0) :
?>[<?= $changeDefence999Train != 0 ? "훈련 {$changeDefence999Train}," : '' ?><?= $changeDefence999Atmos != 0 ? "사기 {$changeDefence999Atmos}" : ''
?>]<?php endif ?></option>
</select> </select>
】<br><br> 】<br><br>
<input type=<?= $submit ?> id='set_my_setting' name=btn style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px; value=설정저장><br> <input type=<?= $submit ?> id='set_my_setting' name=btn style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px; value=설정저장><br>
∞<span style='color:orange'>설정저장은 이달중 <?= $myset ?>회 남았습니다.</span><br><br> ∞<span style='color:orange'>설정저장은 이달중 <?= $myset ?>회 남았습니다.</span><br><br>
<?php if ($me->getPenaltyList()->count()) : ?>
징계 목록(저장 시 갱신)<br>
<?php foreach ($me->getPenaltyList() as $penaltyKey => $penalty) : ?>
<span style='color:red'><?= $penaltyKey->getHelptext() ?> : <?= $penalty ?></span><br>
<?php endforeach; ?>
<br />
<?php endif; ?>
<?php if (!($gameStor->autorun_user['limit_minutes'] ?? false)) : ?> <?php if (!($gameStor->autorun_user['limit_minutes'] ?? false)) : ?>
휴 가 신 청<br> 휴 가 신 청<br>
<button type="button" id='vacation' style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>휴가 신청</button><br><br> <button type="button" id='vacation' style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>휴가 신청</button><br><br>
@@ -168,11 +138,6 @@ $changeDefence999Atmos = $me->onCalcDomestic('changeDefenceTrain', "atmos999", $
<button type="button" id='buildNationCandidate' style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>사전 거병</button><br><br> <button type="button" id='buildNationCandidate' style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>사전 거병</button><br><br>
<?php endif; ?> <?php endif; ?>
<?php if (GameConst::$availableInstantAction['instantRetreat'] ?? false) : ?>
거리 3칸 이내 아국 도시로 즉시 이동<br>
<button type="button" id='instantRetreat' style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>접경 귀환</button><br><br>
<?php endif; ?>
<?php if ($gameStor->npcmode == 2 && $me->getNPCType() == 0) : ?> <?php if ($gameStor->npcmode == 2 && $me->getNPCType() == 0) : ?>
다른 장수 선택 (<?= substr($me->getAuxVar('next_change') ?? TimeUtil::now(), 0, 19) ?> 부터)<br> 다른 장수 선택 (<?= substr($me->getAuxVar('next_change') ?? TimeUtil::now(), 0, 19) ?> 부터)<br>
<a href="select_general_from_pool.php" id='select_general_from_pool'><button type="button" style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>다른 장수 선택</button></a><br><br> <a href="select_general_from_pool.php" id='select_general_from_pool'><button type="button" style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>다른 장수 선택</button></a><br><br>
@@ -201,7 +166,7 @@ $changeDefence999Atmos = $me->onCalcDomestic('changeDefenceTrain', "atmos999", $
<div class="row mx-1"> <div class="row mx-1">
<div class="btn-group" role="group"> <div class="btn-group" role="group">
<?php foreach ($me->getItems() as $itemKey => $item) : ?> <?php foreach ($me->getItems() as $itemKey => $item) : ?>
<button type="button" data-item-type='<?= $itemKey ?>' class="drop-item-btn btn btn-primary <?= $item->getName() == '-' ? 'disabled' : '' ?>"><?= $item->getName() ?></button> <button type="button" data-item-type='<?=$itemKey?>' class="drop-item-btn btn btn-primary <?= $item->getName() == '-' ? 'disabled' : '' ?>"><?= $item->getName() ?></button>
<?php endforeach; ?> <?php endforeach; ?>
</div> </div>
</div> </div>
@@ -212,7 +177,7 @@ $changeDefence999Atmos = $me->onCalcDomestic('changeDefenceTrain', "atmos999", $
</div> </div>
</div> </div>
</div> </div>
<div class="col col-12 col-lg-6"> <div class="col col-12 col-md-6">
<div class="row gx-0"> <div class="row gx-0">
<div class="col bg1 text-center"> <div class="col bg1 text-center">
<h4 style='color:skyblue'>개인 기록</h4> <h4 style='color:skyblue'>개인 기록</h4>
@@ -225,7 +190,7 @@ $changeDefence999Atmos = $me->onCalcDomestic('changeDefenceTrain', "atmos999", $
<button type="button" class="load_old_log btn btn-secondary" data-log_type="generalAction">이전 로그 불러오기</button> <button type="button" class="load_old_log btn btn-secondary" data-log_type="generalAction">이전 로그 불러오기</button>
</div> </div>
</div> </div>
<div class="col col-12 col-lg-6"> <div class="col col-12 col-md-6">
<div class="row gx-0"> <div class="row gx-0">
<div class="col bg1 text-center"> <div class="col bg1 text-center">
<h4 style='color:orange'>전투 기록</h4> <h4 style='color:orange'>전투 기록</h4>
@@ -239,7 +204,7 @@ $changeDefence999Atmos = $me->onCalcDomestic('changeDefenceTrain', "atmos999", $
</div> </div>
</div> </div>
<div class="col col-12 col-lg-6"> <div class="col col-12 col-md-6">
<div class="row gx-0"> <div class="row gx-0">
<div class="col bg1 text-center"> <div class="col bg1 text-center">
<h4 style='color:skyblue'>장수 열전</h4> <h4 style='color:skyblue'>장수 열전</h4>
@@ -249,7 +214,7 @@ $changeDefence999Atmos = $me->onCalcDomestic('changeDefenceTrain', "atmos999", $
<?= formatHistoryToHTML(getGeneralHistoryLogAll($generalID)) ?> <?= formatHistoryToHTML(getGeneralHistoryLogAll($generalID)) ?>
</div> </div>
</div> </div>
<div class="col col-12 col-lg-6"> <div class="col col-12 col-md-6">
<div class="row gx-0"> <div class="row gx-0">
<div class="col bg1 text-center"> <div class="col bg1 text-center">
<h4 style='color:orange'>전투 결과</h4> <h4 style='color:orange'>전투 결과</h4>
+63 -10
View File
@@ -14,16 +14,14 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("토너먼트", 1); increaseRefresh("토너먼트", 1);
TurnExecutionHelper::executeAllCommand(); TurnExecutionHelper::executeAllCommand();
$me = $db->queryFirstRow( $me = $db->queryFirstRow('select no,tournament,con,turntime from general where owner=%i', $userID);
'SELECT no,tournament,refresh_score,turntime from `general` $generalID = $session->generalID;
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id where owner=%i', $userID
);
$generalID = $me['no'];
$admin = $gameStor->getValues(['tournament', 'phase', 'turnterm', 'tnmt_msg', 'tnmt_type', 'develcost', 'tnmt_trig']); $admin = $gameStor->getValues(['tournament', 'phase', 'turnterm', 'tnmt_msg', 'tnmt_type', 'develcost', 'tnmt_trig']);
$turnTerm = $admin['turnterm']; $turnTerm = $admin['turnterm'];
$limitState = checkLimit($me['refresh_score']); $con = checkLimit($me['con']);
if ($limitState >= 2) { if ($con >= 2) {
printLimitMsg($me['turntime']); printLimitMsg($me['turntime']);
exit(); exit();
} }
@@ -102,13 +100,12 @@ $globalBetTotal = array_sum($globalBet);
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<?php if ($limitState == 1) { <?php if ($con == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다! 제한량이 모자라다면 참여를 해보세요^^"); MessageBox("접속제한이 얼마 남지 않았습니다! 제한량이 모자라다면 참여를 해보세요^^");
} ?> } ?>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 토너먼트</title> <title><?= UniqueConst::$serverName ?>: 토너먼트</title>
@@ -125,7 +122,63 @@ $globalBetTotal = array_sum($globalBet);
</tr> </tr>
</table> </table>
<table align=center class='tb_layout bg0'> <table align=center class='tb_layout bg0'>
<?php if ($me['no'] > 0 && $me['tournament'] == 0 && $admin['tournament'] == 1) : ?> <?php if ($session->userGrade >= 5) : ?>
<form method=post action=c_tournament.php>
<tr>
<td colspan=8><input type=textarea size=150 style=color:white;background-color:black; name=msg><input type=submit name=btn value='메시지'></td>
</tr>
<tr>
<td colspan=8>
<button type="button" class="btn btn-secondary" onclick='location.reload()'>갱신</button>
<?php if ($admin['tournament'] == 0) : ?>
<select name=auto size=1 style=color:white;background-color:black;>
<option style=color:white; value=0 <?= !$admin['tnmt_trig'] ? 'selected' : '' ?>>수동진행</option>
<option style=color:white; value=1 <?= $admin['tnmt_trig'] ? 'selected' : '' ?>>자동진행</option>
</select>
<input type=submit name=btn value='자동개최설정'>
<?php else : ?>
<input type=submit name=btn value='중단' onclick='return confirm("진짜 중단하시겠습니까?")'>
<?php endif; ?>
<?php switch ($admin['tournament']) {
case 1:
echo "<input type=submit name=btn value='랜덤투입'>";
echo "<input type=submit name=btn value='랜덤전부투입'>";
break;
case 2:
echo "<input type=submit name=btn value='예선'><input type=submit name=btn value='예선전부'>";
break;
case 3:
echo "<input type=submit name=btn value='추첨'><input type=submit name=btn value='추첨전부'>";
break;
case 4:
echo "<input type=submit name=btn value='본선'><input type=submit name=btn value='본선전부'>";
break;
case 5:
echo "<input type=submit name=btn value='배정'>";
break;
case 6:
echo "<input type=submit name=btn value='베팅마감'>";
break;
case 7:
echo "<input type=submit name=btn value='16강'>";
break;
case 8:
echo "<input type=submit name=btn value='8강'>";
break;
case 9:
echo "<input type=submit name=btn value='4강'>";
break;
case 10:
echo "<input type=submit name=btn value='결승'>";
break;
} ?>
</td>
</tr>
</form>
<?php elseif ($me['no'] > 0 && $me['tournament'] == 0 && $admin['tournament'] == 1) : ?>
<form method=post action=c_tournament.php> <form method=post action=c_tournament.php>
<tr> <tr>
<td colspan=8><button type="button" class="btn btn-secondary" onclick='location.reload()'>갱신</button><button type="submit" class="btn btn-sammo-base2" onclick='return confirm("참가비 금<?= $admin['develcost'] ?>이 필요합니다. 참가하시겠습니까?")'>참가</button><input type='hidden' name='btn' value='참가'/></td> <td colspan=8><button type="button" class="btn btn-secondary" onclick='location.reload()'>갱신</button><button type="submit" class="btn btn-sammo-base2" onclick='return confirm("참가비 금<?= $admin['develcost'] ?>이 필요합니다. 참가하시겠습니까?")'>참가</button><input type='hidden' name='btn' value='참가'/></td>
+3 -31
View File
@@ -43,7 +43,6 @@ if ($nationID) {
<head> <head>
<title><?= UniqueConst::$serverName ?>: 전투 시뮬레이터</title> <title><?= UniqueConst::$serverName ?>: 전투 시뮬레이터</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1100" /> <meta name="viewport" content="width=1100" />
<?= WebUtil::printCSS('../d_shared/common.css') ?> <?= WebUtil::printCSS('../d_shared/common.css') ?>
@@ -66,8 +65,8 @@ if ($nationID) {
전역 설정 전역 설정
</div> </div>
<div class="card-body dragpad_battle"> <div class="card-body dragpad_battle">
<div class="row gx-0"> <div class="row">
<div class="col-sm-4"> <div class="col-sm-6">
<div class="input-group"> <div class="input-group">
<input type="number" class="form-control" aria-describedby="text_year" value="<?= $startYear ?>" disabled> <input type="number" class="form-control" aria-describedby="text_year" value="<?= $startYear ?>" disabled>
<div class="input-group-text"> 년 시작 </div> <div class="input-group-text"> 년 시작 </div>
@@ -77,13 +76,9 @@ if ($nationID) {
<div class="input-group-text"> 월 </div> <div class="input-group-text"> 월 </div>
</div> </div>
</div> </div>
<div class="col-sm-5 px-2"> <div class="col-sm-6">
<div class="btn-toolbar" role="toolbar"> <div class="btn-toolbar" role="toolbar">
<div class="input-group me-2" role="group"> <div class="input-group me-2" role="group">
<div class="input-group-text">
시드
</div>
<input type="text" class="form-control" id="seed" aria-describedby="text_seed">
<div class="input-group-text"> <div class="input-group-text">
반복 횟수 반복 횟수
</div> </div>
@@ -92,10 +87,6 @@ if ($nationID) {
<option value="1000">1000회 (요약 표기)</option> <option value="1000">1000회 (요약 표기)</option>
</select> </select>
</div> </div>
</div>
</div>
<div class="col-sm-3">
<div class="btn-toolbar" role="toolbar">
<div class="btn-group me-2" role="group"> <div class="btn-group me-2" role="group">
<button type="button" class="btn btn-danger btn-begin_battle">전투</button> <button type="button" class="btn btn-danger btn-begin_battle">전투</button>
</div> </div>
@@ -435,25 +426,6 @@ if ($nationID) {
</div> </div>
<input type="number" class="form-control form_killcrew" value="0" step="1"> <input type="number" class="form-control form_killcrew" value="0" step="1">
</div> </div>
<div class="input-group mb-0">
<div class="input-group-text">자신</div>
<div class="input-group-text">회피 확률</div>
<input type="number" class="form-control form_war_avoid_ratio" value="0" step="1" min="0" max="5">
<div class="input-group-text">필살 확률</div>
<input type="number" class="form-control form_war_critical_ratio" value="0" step="1" min="0" max="5">
<div class="input-group-text">계략 시도 확률</div>
<input type="number" class="form-control form_war_magic_trial_prob" value="0" step="1" min="0" max="5">
</div>
<div class="input-group mb-1">
<div class="input-group-text">상대</div>
<div class="input-group-text">회피 확률</div>
<input type="number" class="form-control form_oppose_war_avoid_ratio" value="0" step="1" min="0" max="5">
<div class="input-group-text">필살 확률</div>
<input type="number" class="form-control form_oppose_war_critical_ratio" value="0" step="1" min="0" max="5">
<div class="input-group-text">계략 시도 확률</div>
<input type="number" class="form-control form_oppose_war_magic_trial_prob" value="0" step="1" min="0" max="5">
</div>
</div> </div>
</div> </div>
+7 -2
View File
@@ -52,8 +52,8 @@ class DB
/** /**
* DB 객체 생성 * DB 객체 생성
* *
* @return \MeekroDB * @return \MeekroDB
* @suppress PhanTypeMismatchProperty * @suppress PhanTypeMismatchProperty
*/ */
public static function db() public static function db()
@@ -61,6 +61,11 @@ class DB
if (self::$uDB === null) { if (self::$uDB === null) {
self::$uDB = new \MeekroDB(self::$host, self::$user, self::$password, self::$dbName, self::$port, self::$encoding); self::$uDB = new \MeekroDB(self::$host, self::$user, self::$password, self::$dbName, self::$port, self::$encoding);
self::$uDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true; self::$uDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
self::$uDB->error_handler = function () {
};
self::$uDB->throw_exception_on_error = true;
self::$uDB->throw_exception_on_nonsql_error = true;
} }
return self::$uDB; return self::$uDB;
} }
-53
View File
@@ -1,53 +0,0 @@
<?php
namespace sammo;
use sammo\DTO\MenuItem;
use sammo\DTO\MenuMulti;
use sammo\DTO\MenuSplit;
//변경을 원한다면 파일을 복제 후 수정
class GlobalMenu {
/** @var (MenuItem|MenuMulti|MenuSplit)[] */
const version = 3;
static ?array $menu = null;
public static function getMenu(): array{
if(static::$menu !== null){
return static::$menu;
}
static::$menu = [
new MenuItem('천통국 베팅', 'v_nationBetting.php', condHighlightVar: 'nationBetting'),
new MenuMulti('게임정보', [
new MenuItem('세력일람', 'a_kingdomList.php', newTab: true),
new MenuItem('장수일람', 'a_genList.php', newTab: true),
new MenuItem('명장일람', 'a_bestGeneral.php', newTab: true),
new MenuItem('명예의전당', 'a_hallOfFame.php', newTab: true),
new MenuItem('왕조일람', 'a_emperior.php', newTab: true),
]),
new MenuItem('연감', 'v_history.php', newTab: true),
new MenuSplit(
new MenuItem('게시판', '/board/community', newTab: true),
[
new MenuItem('건의/제안', '/board/request', newTab: true),
new MenuItem('팁/강좌', '/board/tip', newTab: true),
new MenuItem('패치 내역', '/board/patch', newTab: true),
]
),
new MenuSplit(
new MenuItem('공식 오픈 톡', 'https://open.kakao.com/o/', newTab: true),
[
new MenuItem('잡담 오픈 톡', 'https://open.kakao.com/o/', newTab: true)
],
),
new MenuItem('전투 시뮬레이터', 'battle_simulator.php', newTab: true),
new MenuMulti('기타 정보', [
new MenuItem('접속량정보', 'a_traffic.php', newTab: true),
new MenuItem('빙의일람', 'a_npcList', newTab: true, condShowVar: 'npcMode'),
]),
new MenuItem('설문조사', 'v_vote.php', newTab: true, condHighlightVar: 'vote'),
];
return static::$menu;
}
}
-6
View File
@@ -1,6 +0,0 @@
<?php
namespace sammo;
class ServerEnv extends ServerDefaultEnv {
//ServerEnv 기본값을 변경하고 싶다면 orig를 제거한 복사본을 만들고 수정
}
+194 -126
View File
@@ -5,12 +5,9 @@ namespace sammo;
use DateTime; use DateTime;
use Ds\Set; use Ds\Set;
use sammo\Enums\AuctionType; use sammo\Enums\AuctionType;
use sammo\Enums\GeneralAccessLogColumn;
use sammo\Enums\GeneralColumn;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\InheritanceKey; use sammo\Enums\InheritanceKey;
use sammo\Enums\PenaltyKey;
use sammo\Enums\RankColumn; use sammo\Enums\RankColumn;
use sammo\Event\Action;
require_once 'process_war.php'; require_once 'process_war.php';
require_once 'func_gamerule.php'; require_once 'func_gamerule.php';
@@ -107,27 +104,28 @@ function GetImageURL($imgsvr, $filepath = '')
} }
/** /**
* @param null|int $refreshScore 장수의 벌점 * @param null|int $con 장수의 벌점
* @param null|int $conlimit 최대 벌점
*/ */
function checkLimit($refreshScore = null) function checkLimit($con = null)
{ {
$session = Session::getInstance(); $session = Session::getInstance();
if ($session->userGrade >= 6) { if ($session->userGrade >= 4) {
return 0; return 0;
} }
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
if ($refreshScore === null) { if ($con === null) {
$refreshScore = $db->queryFirstField('SELECT refresh_score FROM general_access_log WHERE `general_id`=%i', Session::getGeneralID()); $con = $db->queryFirstField('SELECT con FROM general WHERE `owner`=%i', Session::getUserID());
} }
$refreshLimit = $gameStor->refreshLimit; $conlimit = $gameStor->conlimit;
if ($refreshScore > $refreshLimit) { if ($con > $conlimit) {
return 2; return 2;
//접속제한 90%이면 경고문구 //접속제한 90%이면 경고문구
} elseif ($refreshScore > $refreshLimit * 0.9) { } elseif ($con > $conlimit * 0.9) {
return 1; return 1;
} else { } else {
return 0; return 0;
@@ -150,7 +148,7 @@ function getRandGenName(RandUtil $rng)
function cityInfo(GeneralLite $generalObj) function cityInfo(General $generalObj)
{ {
$db = DB::db(); $db = DB::db();
@@ -377,11 +375,11 @@ function myNationInfo(General $generalObj)
function checkSecretMaxPermission($penalty) function checkSecretMaxPermission($penalty)
{ {
$secretMax = 4; $secretMax = 4;
if ($penalty[PenaltyKey::NoTopSecret->value] ?? false) { if ($penalty['noTopSecret'] ?? false) {
$secretMax = 1; $secretMax = 1;
} else if ($penalty[PenaltyKey::NoChief->value] ?? false) { } else if ($penalty['noChief'] ?? false) {
$secretMax = 1; $secretMax = 1;
} else if ($penalty[PenaltyKey::NoAmbassador->value] ?? false) { } else if ($penalty['noAmbassador'] ?? false) {
$secretMax = 2; $secretMax = 2;
} }
return $secretMax; return $secretMax;
@@ -404,19 +402,19 @@ function checkSecretPermission(array $me, $checkSecretLimit = true)
} }
if ($penalty[PenaltyKey::NoChief->value] ?? false) { if ($penalty['noSecret'] ?? false) {
return 0; return 0;
} }
$secretMin = 0; $secretMin = 0;
$secretMax = checkSecretMaxPermission($penalty); $secretMax = checkSecretMaxPermission($me, $penalty);
if ($me['officer_level'] == 12) { if ($me['officer_level'] == 12) {
$secretMin = 4; $secretMin = 4;
} else if ($permission == 'ambassador') { } else if ($me['permission'] == 'ambassador') {
$secretMin = 4; $secretMin = 4;
} else if ($permission == 'auditor') { } else if ($me['permission'] == 'auditor') {
$secretMin = 3; $secretMin = 3;
} else if ($me['officer_level'] >= 5) { } else if ($me['officer_level'] >= 5) {
$secretMin = 2; $secretMin = 2;
@@ -645,7 +643,7 @@ function generalInfo(General $generalObj)
$age = "<font color=red>{$age} 세</font>"; $age = "<font color=red>{$age} 세</font>";
} }
$refreshScoreTotal = round($generalObj->getAccessLogVar(GeneralAccessLogColumn::refreshScoreTotal) ?? 0, -1); $connectCnt = round($generalObj->getVar('connect'), -1);
$specialDomestic = $generalObj->getVar('special') === GameConst::$defaultSpecialDomestic $specialDomestic = $generalObj->getVar('special') === GameConst::$defaultSpecialDomestic
? "{$generalObj->getVar('specage')}세" ? "{$generalObj->getVar('specage')}세"
: "<font color=limegreen>" . displayiActionObjInfo($generalObj->getSpecialDomestic()) . "</font>"; : "<font color=limegreen>" . displayiActionObjInfo($generalObj->getSpecialDomestic()) . "</font>";
@@ -754,7 +752,7 @@ function generalInfo(General $generalObj)
<td style='text-align:center;' class='bg1'><b>부대</b></td> <td style='text-align:center;' class='bg1'><b>부대</b></td>
<td style='text-align:center;' colspan=3>{$troopInfo}</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;' class='bg1'><b>벌점</b></td>
<td style='text-align:center;' colspan=5>" . getRefreshScoreText($refreshScoreTotal) . " {$refreshScoreTotal}({$generalObj->getAccessLogVar(GeneralAccessLogColumn::refreshScore)})</td> <td style='text-align:center;' colspan=5>" . getConnect($connectCnt) . " {$connectCnt}({$generalObj->getVar('con')})</td>
</tr> </tr>
</table>"; </table>";
} }
@@ -888,7 +886,7 @@ function generalInfo2(General $generalObj)
function getOnlineNum(): int function getOnlineNum(): int
{ {
return KVStorage::getStorage(DB::db(), 'game_env')->getValue('online_user_cnt') ?? 0; return KVStorage::getStorage(DB::db(), 'game_env')->getValue('online') ?? 0;
} }
function onlinegen(General $general) function onlinegen(General $general)
@@ -908,7 +906,7 @@ function nationMsg(General $general)
$nationID = $general->getNationID(); $nationID = $general->getNationID();
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env'); $nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
return $nationStor->nationNotice['msg'] ?? ''; return $nationStor->notice ?? '';
} }
function banner() function banner()
@@ -1001,69 +999,76 @@ function increaseRefresh($type = "", $cnt = 1)
$generalID = $session->generalID; $generalID = $session->generalID;
$userGrade = $session->userGrade; $userGrade = $session->userGrade;
$dateObj = new \DateTimeImmutable(); $date = TimeUtil::now();
$date = TimeUtil::format($dateObj, false);
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->refresh = $gameStor->refresh + $cnt; //TODO: +로 증가하는 값은 별도로 분리
$isunited = $gameStor->isunited; $isunited = $gameStor->isunited;
$opentime = $gameStor->opentime; $opentime = $gameStor->opentime;
if ($userGrade >= 6) { if ($isunited != 2 && $generalID && $userGrade < 6 && $opentime <= TimeUtil::now()) {
return; $db->update('general', [
} 'lastrefresh' => $date,
if ($isunited == 2) { 'con' => $db->sqleval('con + %i', $cnt),
return; 'connect' => $db->sqleval('connect + %i', $cnt),
} 'refcnt' => $db->sqleval('refcnt + %i', $cnt),
if (!$generalID) { 'refresh' => $db->sqleval('refresh + %i', $cnt)
return; ], 'owner=%i', $userID);
}
if ($opentime > $date) {
return;
} }
$gameStor->refresh = $gameStor->refresh + $cnt; //TODO: +로 증가하는 값은 별도로 분리 $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
);
$db->insertUpdate('general_access_log', [ $proxy_headers = array(
GeneralAccessLogColumn::generalID->value => $generalID, 'HTTP_VIA',
GeneralAccessLogColumn::userID->value => $userID, 'HTTP_X_FORWARDED_FOR',
GeneralAccessLogColumn::lastRefresh->value => $date, 'HTTP_FORWARDED_FOR',
GeneralAccessLogColumn::refreshTotal->value => $cnt, 'HTTP_X_FORWARDED',
GeneralAccessLogColumn::refresh->value => $cnt, 'HTTP_FORWARDED',
GeneralAccessLogColumn::refreshScore->value => $cnt, 'HTTP_CLIENT_IP',
GeneralAccessLogColumn::refreshScoreTotal->value => $cnt, 'HTTP_FORWARDED_FOR_IP',
], [ 'VIA',
GeneralAccessLogColumn::lastRefresh->value => $date, 'X_FORWARDED_FOR',
GeneralAccessLogColumn::refreshTotal->value => $db->sqleval('%b + %i', GeneralAccessLogColumn::refreshTotal->value, $cnt), 'FORWARDED_FOR',
GeneralAccessLogColumn::refresh->value => $db->sqleval('%b + %i', GeneralAccessLogColumn::refresh->value, $cnt), 'X_FORWARDED',
GeneralAccessLogColumn::refreshScore->value => $db->sqleval('%b + %i', GeneralAccessLogColumn::refreshScore->value, $cnt), 'FORWARDED',
GeneralAccessLogColumn::refreshScoreTotal->value => $db->sqleval('%b + %i', GeneralAccessLogColumn::refreshScoreTotal->value, $cnt), 'CLIENT_IP',
]); 'FORWARDED_FOR_IP',
'HTTP_PROXY_CONNECTION'
);
$serverPath = __DIR__; $str = "";
foreach ($proxy_headers as $x) {
$serverID = UniqueConst::$serverID; if (isset($_SERVER[$x])) $str .= "//{$x}:{$_SERVER[$x]}";
$logPath = "{$serverPath}/logs/{$serverID}/api_log.db"; }
if ($str != "") {
$logDB = FileDB::db($logPath, $serverPath . '/../f_install/sql/api_log.sql'); file_put_contents(
__DIR__ . "/logs/" . UniqueConst::$serverID . "/_{$date2}_ipcheck.txt",
$ip = $_SERVER['REMOTE_ADDR'] ?? 'local'; sprintf(
$date = date('Y-m-d H:i:s'); "%s, %s, %s%s\n",
$session->userName,
$logDB->insert('api_log', [ $session->generalName,
'user_id' => $session->userID, $_SERVER['REMOTE_ADDR'],
'ip' => $ip, $str
'date' => $date, ),
'path' => "refresh", FILE_APPEND
'arg' => Json::encode([ );
'type' => $type, }
]),
'aux' => Json::encode([
'generalID' => $generalID,
'generalName' => $session->generalName,
'userName' => $session->userName,
]),
]);
} }
function updateTraffic() function updateTraffic()
@@ -1071,9 +1076,12 @@ function updateTraffic()
$online = getOnlineNum(); $online = getOnlineNum();
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['year', 'month', 'refresh', 'maxonline', 'maxrefresh', 'recentTraffic']); $admin = $gameStor->getValues(['year', 'month', 'refresh', 'maxonline', 'maxrefresh']);
/** @var array{year:int,month:int,refresh:int,maxonline:int,maxrefresh:int} $admin */ /** @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']) { if ($admin['maxrefresh'] < $admin['refresh']) {
$admin['maxrefresh'] = $admin['refresh']; $admin['maxrefresh'] = $admin['refresh'];
} }
@@ -1084,20 +1092,22 @@ function updateTraffic()
$gameStor->maxrefresh = $admin['maxrefresh']; $gameStor->maxrefresh = $admin['maxrefresh'];
$gameStor->maxonline = $admin['maxonline']; $gameStor->maxonline = $admin['maxonline'];
$recentTraffic = $admin['recentTraffic'] ?? []; $db->update('general', ['refresh' => 0], true);
if(count($recentTraffic) >= 5){
array_shift($recentTraffic);
}
$recentTraffic[] = [
'year'=>$admin['year'],
'month' => $admin['month'],
'refresh' => $admin['refresh'],
'online' => $online,
'date' => TimeUtil::now(),
];
$gameStor->recentTraffic = $recentTraffic;
$db->update('general_access_log', ['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
);
} }
function CheckOverhead() function CheckOverhead()
@@ -1105,13 +1115,13 @@ function CheckOverhead()
//서버정보 //서버정보
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
[$turnterm, $refreshLimit] = $gameStor->getValuesAsArray(['turnterm', 'refreshLimit']); list($turnterm, $conlimit) = $gameStor->getValuesAsArray(['turnterm', 'conlimit']);
$nextRefreshLimit = Util::round(pow($turnterm, 0.6) * 3) * GameConst::$refreshLimitCoef; $con = Util::round(pow($turnterm, 0.6) * 3) * 10;
if ($nextRefreshLimit != $refreshLimit) { if ($con != $conlimit) {
$gameStor->refreshLimit = $nextRefreshLimit; $gameStor->conlimit = $con;
} }
} }
@@ -1213,18 +1223,10 @@ function updateOnline()
$nationname[$nation['nation']] = $nation['name']; $nationname[$nation['nation']] = $nation['name'];
} }
//동접수 //동접수
$startTurn = cutTurn($gameStor->turntime, $gameStor->turnterm, false); $before5Min = TimeUtil::nowAddMinutes(-5);
$onlineUser = $db->query( $onlineUser = $db->query('SELECT no,name,nation FROM general WHERE lastrefresh > %s AND npc < 2', $before5Min);
'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); $onlineNum = count($onlineUser);
$onlineNationUsers = Util::arrayGroupBy($onlineUser, 'nation'); $onlineNationUsers = Util::arrayGroupBy($onlineUser, 'nation');
@@ -1247,6 +1249,76 @@ function updateOnline()
$gameStor->online_nation = join(', ', $onlineNation); $gameStor->online_nation = join(', ', $onlineNation);
} }
function addAge(RandUtil $rng)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
//나이와 호봉 증가
$db->update('general', [
'age' => $db->sqleval('age+1'),
], true);
$db->update('general', [
'belong' => $db->sqleval('belong+1')
], 'nation != 0');
[$startYear, $year, $month] = $gameStor->getValuesAsArray(['startyear', 'year', 'month']);
if ($year >= $startYear + 3) {
foreach ($db->query('SELECT no,name,nation,leadership,strength,intel,aux from general where specage<=age and special=%s', GameConst::$defaultSpecialDomestic) as $general) {
$generalID = $general['no'];
$special = SpecialityHelper::pickSpecialDomestic(
$rng,
$general,
(Json::decode($general['aux'])['prev_types_special']) ?? []
);
$specialClass = buildGeneralSpecialDomesticClass($special);
$specialText = $specialClass->getName();
$db->update('general', [
'special' => $special
], 'no=%i', $generalID);
$logger = new ActionLogger($generalID, $general['nation'], $year, $month);
$josaUl = JosaUtil::pick($specialText, '을');
$logger->pushGeneralActionLog("특기 【<b><L>{$specialText}</></b>】{$josaUl} 익혔습니다!", ActionLogger::PLAIN);
$logger->pushGeneralHistoryLog("특기 【<b><C>{$specialText}</></b>】{$josaUl} 습득");
}
foreach ($db->query('SELECT no,name,nation,leadership,strength,intel,npc,dex1,dex2,dex3,dex4,dex5,aux from general where specage2<=age and special2=%s', GameConst::$defaultSpecialWar) as $general) {
$generalID = $general['no'];
$generalAux = Json::decode($general['aux']);
$updateVars = [];
if (key_exists('inheritSpecificSpecialWar', $generalAux)) {
$special2 = $generalAux['inheritSpecificSpecialWar'];
unset($generalAux['inheritSpecificSpecialWar']);
$updateVars['aux'] = Json::encode($generalAux);
} else {
$special2 = SpecialityHelper::pickSpecialWar(
$rng,
$general,
($generalAux['prev_types_special2']) ?? []
);
}
$specialClass = buildGeneralSpecialWarClass($special2);
$specialText = $specialClass->getName();
$updateVars['special2'] = $special2;
$db->update('general', $updateVars, 'no=%i', $general['no']);
$logger = new ActionLogger($generalID, $general['nation'], $year, $month);
$josaUl = JosaUtil::pick($specialText, '을');
$logger->pushGeneralActionLog("특기 【<b><L>{$specialText}</></b>】{$josaUl} 익혔습니다!", ActionLogger::PLAIN);
$logger->pushGeneralHistoryLog("특기 【<b><C>{$specialText}</></b>】{$josaUl} 습득");
}
}
}
function turnDate($curtime) function turnDate($curtime)
{ {
$db = DB::db(); $db = DB::db();
@@ -1338,7 +1410,7 @@ function CheckHall($no)
["betrate", 'calc'], ["betrate", 'calc'],
]; ];
$generalObj = General::createObjFromDB($no); $generalObj = General::createGeneralObjFromDB($no, null, 2);
$ttw = $generalObj->getRankVar(RankColumn::ttw); $ttw = $generalObj->getRankVar(RankColumn::ttw);
$ttd = $generalObj->getRankVar(RankColumn::ttd); $ttd = $generalObj->getRankVar(RankColumn::ttd);
@@ -1669,10 +1741,11 @@ function tryUniqueItemLottery(RandUtil $rng, General $general, string $acquireTy
$prob = 1 / ($genCount * $itemTypeCnt * 0.7 / 3); // 투표율 70%, 설문조사 한번에 2~3개 등장 $prob = 1 / ($genCount * $itemTypeCnt * 0.7 / 3); // 투표율 70%, 설문조사 한번에 2~3개 등장
} else if ($acquireType == '랜덤 임관') { } else if ($acquireType == '랜덤 임관') {
$prob = 1 / ($genCount * $itemTypeCnt / 10 / 2); // 랜임시 2개(10%) 등장(200명중 20명 랜임시도?) $prob = 1 / ($genCount * $itemTypeCnt / 10 / 2); // 랜임시 2개(10%) 등장(200명중 20명 랜임시도?)
} else if ($acquireType == '건국') {
$prob = 1 / ($genCount * $itemTypeCnt / 10 / 4); // 건국시 4개(20%) 등장(200명시 20국 정도 됨)
} }
$prob *= GameConst::$uniqueTrialCoef; $prob = Util::valueFit($prob, null, 1 / 4); //최대치 감소
$prob = Util::valueFit($prob, null, GameConst::$maxUniqueTrialProb); //최대치 감소
$result = false; $result = false;
$prob /= sqrt(7); $prob /= sqrt(7);
@@ -1682,9 +1755,6 @@ function tryUniqueItemLottery(RandUtil $rng, General $general, string $acquireTy
//포인트로 랜덤 유니크 획득 //포인트로 랜덤 유니크 획득
$prob = 1; $prob = 1;
} }
else if ($acquireType == '건국') {
$prob = 1; // 건국시 100%
}
foreach (Util::range($maxCnt) as $_idx) { foreach (Util::range($maxCnt) as $_idx) {
if ($rng->nextBool($prob)) { if ($rng->nextBool($prob)) {
@@ -1729,21 +1799,22 @@ function deleteNation(General $lord, bool $applyDB): array
$logger->pushGlobalHistoryLog("<R><b>【멸망】</b></><D><b>{$nationName}</b></>{$josaUn} <R>멸망</>했습니다."); $logger->pushGlobalHistoryLog("<R><b>【멸망】</b></><D><b>{$nationName}</b></>{$josaUn} <R>멸망</>했습니다.");
$nationGeneralList = General::createObjListFromDB( $nationGeneralList = General::createGeneralObjListFromDB(
$db->queryFirstColumn( $db->queryFirstColumn(
'SELECT `no` FROM general WHERE nation=%i AND no != %i', 'SELECT `no` FROM general WHERE nation=%i AND no != %i',
$nationID, $nationID,
$lordID $lordID
), ),
['npc', 'owner', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'belong', 'aux'], ['npc', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'belong', 'aux'],
1
); );
$nationGeneralList[$lordID] = $lord; $nationGeneralList[$lordID] = $lord;
$nation['generals'] = array_keys($nationGeneralList); $nation['generals'] = array_keys($nationGeneralList);
$nation['aux'] = Json::decode($nation['aux']); $nation['aux'] = Json::decode($nation['aux']);
$nation['msg'] = $nationStor->nationNotice['msg'] ?? ''; $nation['msg'] = $nationStor->notice;
$nation['scout_msg'] = $nationStor->scout_msg; $nation['scout_msg'] = $nationStor->scout_msg;
$nation['aux'] += $nationStor->max_power ?? []; $nation['aux'] += $nationStor->max_power;
$nation['history'] = getNationHistoryLogAll($nationID); $nation['history'] = getNationHistoryLogAll($nationID);
$josaYi = JosaUtil::pick($nationName, '이'); $josaYi = JosaUtil::pick($nationName, '이');
@@ -1752,16 +1823,13 @@ function deleteNation(General $lord, bool $applyDB): array
// 전 장수 재야로 // 전 장수 재야로
foreach ($nationGeneralList as $general) { foreach ($nationGeneralList as $general) {
if ($general->getNPCType() < 2) { $general->setAuxVar(
$general->setAuxVar( InheritanceKey::max_belong->value,
InheritanceKey::max_belong->value, max(
max( $general->getVar('belong'),
$general->getVar('belong'), $general->getAuxVar(InheritanceKey::max_belong->value) ?? 0
$general->getAuxVar(InheritanceKey::max_belong->value) ?? 0 )
) );
);
}
$general->setVar('belong', 0); $general->setVar('belong', 0);
$general->setVar('troop', 0); $general->setVar('troop', 0);
$general->setVar('officer_level', 0); $general->setVar('officer_level', 0);
+4 -19
View File
@@ -3,7 +3,6 @@ namespace sammo;
use sammo\Command\GeneralCommand; use sammo\Command\GeneralCommand;
use sammo\Command\NationCommand; use sammo\Command\NationCommand;
use sammo\Enums\PenaltyKey;
function getGeneralTurnBrief(General $generalObj, array $turnList) { function getGeneralTurnBrief(General $generalObj, array $turnList) {
$result = []; $result = [];
@@ -214,7 +213,7 @@ function _setGeneralCommand(GeneralCommand $command, array $turnList):void {
$db->update('general_turn', [ $db->update('general_turn', [
'action'=>$commandName, 'action'=>$commandName,
'arg'=>Json::encode($arg, Json::EMPTY_ARRAY_IS_DICT), 'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
'brief'=>$brief 'brief'=>$brief
], 'general_id = %i AND turn_idx IN %li', $generalID, $turnList); ], 'general_id = %i AND turn_idx IN %li', $generalID, $turnList);
} }
@@ -234,7 +233,7 @@ function _setNationCommand(NationCommand $command, array $turnList):void {
$db->update('nation_turn', [ $db->update('nation_turn', [
'action'=>$commandName, 'action'=>$commandName,
'arg'=>Json::encode($arg, Json::EMPTY_ARRAY_IS_DICT), 'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
'brief'=>$brief 'brief'=>$brief
], 'nation_id = %i AND officer_level = %i AND turn_idx IN %li', $nationID, $officerLevel, $turnList); ], 'nation_id = %i AND officer_level = %i AND turn_idx IN %li', $nationID, $officerLevel, $turnList);
} }
@@ -351,7 +350,7 @@ function setGeneralCommand(int $generalID, array $rawTurnList, string $command,
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getAll(); $env = $gameStor->getAll();
$general = General::createObjFromDB($generalID); $general = General::createGeneralObjFromDB($generalID);
try{ try{
$commandObj = buildGeneralCommandClass($command, $general, $env, $arg); $commandObj = buildGeneralCommandClass($command, $general, $env, $arg);
@@ -426,7 +425,7 @@ function setNationCommand(int $generalID, array $turnList, string $command, ?arr
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getAll(); $env = $gameStor->getAll();
$general = General::createObjFromDB($generalID); $general = General::createGeneralObjFromDB($generalID);
if($general->getVar('officer_level') < 5){ if($general->getVar('officer_level') < 5){
return [ return [
@@ -435,13 +434,6 @@ function setNationCommand(int $generalID, array $turnList, string $command, ?arr
]; ];
} }
if($general->hasPenalty(PenaltyKey::NoChiefTurnInput)){
return [
'result'=>false,
'reason'=>'수뇌 턴 입력 불가능'
];
}
try{ try{
$commandObj = buildNationCommandClass($command, $general, $env, $general->getLastTurn(), $arg); $commandObj = buildNationCommandClass($command, $general, $env, $general->getLastTurn(), $arg);
} }
@@ -481,13 +473,6 @@ function setNationCommand(int $generalID, array $turnList, string $command, ?arr
} }
_setNationCommand($commandObj, $turnList); _setNationCommand($commandObj, $turnList);
if($general->getNPCType() < 2){
//유저장인 경우에는 턴 리필
$general->updateVarWithLimit('killturn', $env['killturn'], $general->getVar('killturn'));
$general->applyDB($db);
}
return [ return [
'result'=>true, 'result'=>true,
'brief'=>$commandObj->getBrief(), 'brief'=>$commandObj->getBrief(),
+12 -107
View File
@@ -133,19 +133,19 @@ function getNationType(?string $type) {
} }
function getRefreshScoreText($score) { function getConnect($con) {
if($score < 50) $scoreName = '안함'; if($con < 50) $conname = '안함';
elseif($score < 100) $scoreName = '무관심'; elseif($con < 100) $conname = '무관심';
elseif($score < 200) $scoreName = '가끔'; elseif($con < 200) $conname = '가끔';
elseif($score < 400) $scoreName = '보통'; elseif($con < 400) $conname = '보통';
elseif($score < 800) $scoreName = '자주'; elseif($con < 800) $conname = '자주';
elseif($score < 1600) $scoreName = '열심'; elseif($con < 1600) $conname = '열심';
elseif($score < 3200) $scoreName = '중독'; elseif($con < 3200) $conname = '중독';
elseif($score < 6400) $scoreName = '폐인'; elseif($con < 6400) $conname = '폐인';
elseif($score < 12800) $scoreName = '경고'; elseif($con < 12800) $conname = '경고';
else $scoreName = '헐...'; else $conname = '헐...';
return $scoreName; return $conname;
} }
function getNationType2(?string $type) { function getNationType2(?string $type) {
@@ -256,41 +256,6 @@ function buildItemClass(?string $type):BaseItem{
return $obj; return $obj;
} }
function getScenarioEffectClass(?string $type){
if($type === null || $type === ''){
$type = 'None';
}
static $basePath = __NAMESPACE__.'\\ActionScenarioEffect\\';
$classPath = ($basePath.$type);
if(class_exists($classPath)){
return $classPath;
}
$classPath = ($basePath.'che_'.$type);
if(class_exists($classPath)){
return $classPath;
}
throw new \InvalidArgumentException("{$type}은 시나리오 효과 클래스가 아님");
}
function buildScenarioEffectClass(?string $type):iAction{
static $cache = [];
if($type === null){
$type = 'None';
}
if(key_exists($type, $cache)){
return $cache[$type];
}
$class = getScenarioEffectClass($type);
$obj = new $class();
$cache[$type]= $obj;
return $obj;
}
function getGeneralSpecialDomesticClass(?string $type){ function getGeneralSpecialDomesticClass(?string $type){
if($type === null || $type === ''){ if($type === null || $type === ''){
$type = GameConst::$defaultSpecialDomestic; $type = GameConst::$defaultSpecialDomestic;
@@ -361,41 +326,6 @@ function buildGeneralSpecialWarClass(?string $type):BaseSpecial{
return $obj; 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){ function getGeneralCommandClass(?string $type){
if($type === null || $type === ''){ if($type === null || $type === ''){
$type = '휴식'; $type = '휴식';
@@ -457,29 +387,6 @@ function buildWarUnitTriggerClass(?string $type, WarUnit $unit, ?array $args = n
return $class->newInstanceArgs(array_merge([$unit], $args)); return $class->newInstanceArgs(array_merge([$unit], $args));
} }
function getStaticEventClass(string $type){
static $basePath = __NAMESPACE__.'\\StaticEvent\\';
$classPath = ($basePath.$type);
if(class_exists($classPath)){
return $classPath;
}
throw new \InvalidArgumentException("{$type}은 StaticEvent가 아님");
}
function buildStaticEventClass(?string $type):BaseStaticEvent{
static $cache = [];
if(key_exists($type, $cache)){
return $cache[$type];
}
$class = getStaticEventClass($type);
$obj = new $class();
$cache[$type] = $obj;
return $obj;
}
function getGeneralPoolClass(string $type){ function getGeneralPoolClass(string $type){
static $basePath = __NAMESPACE__.'\\GeneralPool\\'; static $basePath = __NAMESPACE__.'\\GeneralPool\\';
$classPath = ($basePath.$type); $classPath = ($basePath.$type);
@@ -635,8 +542,6 @@ function getExpLevel($experience) {
$level = Util::toInt(sqrt($experience/10)); $level = Util::toInt(sqrt($experience/10));
} }
$level = Util::clamp($level, 0, GameConst::$maxLevel);
return $level; return $level;
} }
+344 -61
View File
@@ -4,7 +4,6 @@ namespace sammo;
use sammo\DTO\AuctionInfo; use sammo\DTO\AuctionInfo;
use sammo\Enums\AuctionType; use sammo\Enums\AuctionType;
use sammo\Enums\EventTarget;
use sammo\Enums\InheritanceKey; use sammo\Enums\InheritanceKey;
use sammo\Enums\RankColumn; use sammo\Enums\RankColumn;
@@ -185,6 +184,27 @@ function updateGeneralNumber()
refreshNationStaticInfo(); refreshNationStaticInfo();
} }
function updateYearly()
{
//통계
checkStatistic();
}
//관직 변경 해제
function updateQuaterly()
{
$db = DB::db();
//천도 제한 해제, 관직 변경 제한 해제
$db->update('nation', [
'chief_set' => 0,
], true);
//관직 변경 제한 해제
$db->update('city', [
'officer_set' => 0,
], true);
}
// 벌점 감소와 건국제한-1 전턴제한-1 외교제한-1, 1달마다 실행, 병사 있는 장수의 군량 감소, 수입비율 조정 // 벌점 감소와 건국제한-1 전턴제한-1 외교제한-1, 1달마다 실행, 병사 있는 장수의 군량 감소, 수입비율 조정
function preUpdateMonthly() function preUpdateMonthly()
{ {
@@ -200,12 +220,62 @@ function preUpdateMonthly()
$admin = $gameStor->getValues(['startyear', 'year', 'month']); $admin = $gameStor->getValues(['startyear', 'year', 'month']);
$logger = new ActionLogger(0, 0, $admin['year'], $admin['month']);
//보급선 체크
checkSupply();
//미보급도시 10% 감소
$db->update('city', [
'pop' => $db->sqleval('pop * 0.9'),
'trust' => $db->sqleval('trust * 0.9'),
'agri' => $db->sqleval('agri * 0.9'),
'comm' => $db->sqleval('comm * 0.9'),
'secu' => $db->sqleval('secu * 0.9'),
'def' => $db->sqleval('def * 0.9'),
'wall' => $db->sqleval('wall * 0.9'),
], 'supply = 0');
//미보급도시 장수 병 훈 사 5%감소
//NOTE: update inner join도 가능하지만, meekrodb 기준으로 깔끔하게.
$unsuppliedCities = $db->query('SELECT city, nation, trust, name FROM city WHERE supply = 0');
foreach (Util::arrayGroupBy($unsuppliedCities, 'nation') as $nationID => $cityList) {
$cityIDList = Util::squeezeFromArray($cityList, 'city');
$db->update('general', [
'crew' => $db->sqleval('crew*0.95'),
'atmos' => $db->sqleval('atmos*0.95'),
'train' => $db->sqleval('train*0.95'),
], 'city IN %li AND nation = %i', $cityIDList, $nationID);
}
//민심30이하 공백지 처리
$lostCities = [];
foreach ($unsuppliedCities as $unsuppliedCity) {
if ($unsuppliedCity['trust'] >= 30) {
continue;
}
$lostCities[$unsuppliedCity['city']] = $unsuppliedCity;
}
if ($lostCities) {
foreach ($lostCities as $lostCity) {
$josaYi = JosaUtil::pick($lostCity['name'], '이');
$logger->pushGlobalHistoryLog("<R><b>【고립】</b></><G><b>{$lostCity['name']}</b></>{$josaYi} 보급이 끊겨 <R>미지배</> 도시가 되었습니다.");
}
$db->update('general', [
'officer_level' => 1,
'officer_city' => 0
], 'officer_city IN %li', array_keys($lostCities));
$db->update('city', [
'nation' => 0,
'officer_set' => 0,
'conflict' => '{}',
'term' => 0,
'front' => 0
], 'city IN %li', array_keys($lostCities));
}
//접률감소, 건국제한-1 //접률감소, 건국제한-1
$db->update('general_access_log', [
'refresh_score_total' => $db->sqleval('floor(refresh_score_total*0.99)'),
], true);
$db->update('general', [ $db->update('general', [
'connect' => $db->sqleval('floor(connect*0.99)'),
'makelimit' => $db->sqleval('greatest(0, makelimit - 1)'), 'makelimit' => $db->sqleval('greatest(0, makelimit - 1)'),
], true); ], true);
//전략제한-1, 외교제한-1, 세율동기화 //전략제한-1, 외교제한-1, 세율동기화
@@ -215,10 +285,18 @@ function preUpdateMonthly()
'rate_tmp' => $db->sqleval('rate') 'rate_tmp' => $db->sqleval('rate')
], true); ], true);
//도시훈사 180년 60, 220년 87, 240년 100
$rate = Util::round(($admin['year'] - $admin['startyear']) / 1.5) + 60;
if ($rate > 100) $rate = 100;
// 20 ~ 140원 // 20 ~ 140원
$develcost = ($admin['year'] - $admin['startyear'] + 10) * 2; $develcost = ($admin['year'] - $admin['startyear'] + 10) * 2;
$gameStor->city_rate = $rate;
$gameStor->develcost = $develcost; $gameStor->develcost = $develcost;
//매달 사망자 수입 결산
processWarIncome();
//계략, 전쟁표시 해제 //계략, 전쟁표시 해제
$db->update('city', [ $db->update('city', [
'state' => $db->sqleval(<<<EOD 'state' => $db->sqleval(<<<EOD
@@ -303,6 +381,7 @@ function postUpdateMonthly(RandUtil $rng)
WHERE g.nation = A.nation) WHERE g.nation = A.nation)
+(select round(sum(dex1+dex2+dex3+dex4+dex5)/1000) from general where 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(sum(experience+dedication)/100) from general where nation=A.nation)
+(select round(avg(connect)) from general where nation=A.nation)
)/10) )/10)
as power, as power,
(select sum(crew) from general where nation=A.nation) as totalCrew (select sum(crew) from general where nation=A.nation) as totalCrew
@@ -372,7 +451,7 @@ function postUpdateMonthly(RandUtil $rng)
continue; continue;
} }
//양측 기간 모두 0이 되는 상황이면 //양측 기간 모두 0이 되는 상황이면
$nation1 = getNationStaticInfo($me); $nation1 = getNationStaticInfo($me);
$name1 = $nation1['name']; $name1 = $nation1['name'];
$nation2 = getNationStaticInfo($you); $nation2 = getNationStaticInfo($you);
@@ -381,7 +460,7 @@ function postUpdateMonthly(RandUtil $rng)
$josaWa = JosaUtil::pick($name1, '와'); $josaWa = JosaUtil::pick($name1, '와');
$josaYi = JosaUtil::pick($name2, '이'); $josaYi = JosaUtil::pick($name2, '이');
$globalLogger->pushGlobalHistoryLog("<R><b>【전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <S>전</>합니다."); $globalLogger->pushGlobalHistoryLog("<R><b>【전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <S>전</>합니다.");
$db->update('diplomacy', [ $db->update('diplomacy', [
'state' => 2, 'state' => 2,
'term' => 0, 'term' => 0,
@@ -424,6 +503,8 @@ function postUpdateMonthly(RandUtil $rng)
if ($admin['year'] >= $admin['startyear'] + 2) { if ($admin['year'] >= $admin['startyear'] + 2) {
checkWander($rng); checkWander($rng);
} }
// 작위 업데이트
updateNationState();
updateGeneralNumber(); updateGeneralNumber();
refreshNationStaticInfo(); refreshNationStaticInfo();
// 천통여부 검사 // 천통여부 검사
@@ -451,7 +532,7 @@ function checkWander(RandUtil $rng)
$wanderers = $db->queryFirstColumn('SELECT general.`no` FROM general LEFT JOIN nation ON general.nation = nation.nation WHERE nation.`level` = 0 AND general.`officer_level` = 12'); $wanderers = $db->queryFirstColumn('SELECT general.`no` FROM general LEFT JOIN nation ON general.nation = nation.nation WHERE nation.`level` = 0 AND general.`officer_level` = 12');
foreach (General::createObjListFromDB($wanderers) as $wanderer) { foreach (General::createGeneralObjListFromDB($wanderers) as $wanderer) {
$wanderCmd = buildGeneralCommandClass('che_해산', $wanderer, $admin); $wanderCmd = buildGeneralCommandClass('che_해산', $wanderer, $admin);
if ($wanderCmd->hasFullConditionMet()) { if ($wanderCmd->hasFullConditionMet()) {
$logger = $wanderer->getLogger(); $logger = $wanderer->getLogger();
@@ -466,6 +547,248 @@ function checkWander(RandUtil $rng)
} }
} }
function updateNationState()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$history = array();
$admin = $gameStor->getValues(['killturn', 'year', 'month', 'fiction', 'startyear', 'show_img_level', 'turnterm', 'turntime']);
$year = $admin['year'];
$month = $admin['month'];
$startYear = $admin['startyear'];
$assemblerCnts = [];
foreach ($db->queryAllLists('SELECT nation,count(no) FROM general WHERE npc = 5 GROUP BY nation') as [$nationID, $assemblerCnt]) {
$assemblerCnts[$nationID] = $assemblerCnt;
};
foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) {
//TODO: level이 진관수이소중대특 체계를 벗어날 수 있음
$nationID = $nation['nation'];
$citycount = $db->queryFirstField('SELECT count(*) FROM city WHERE nation=%i AND level>=4', $nationID);
if ($citycount == 0) {
$nationlevel = 0; // 방랑군
} elseif ($citycount == 1) {
$nationlevel = 1; // 호족
} elseif ($citycount <= 4) {
$nationlevel = 2; // 군벌
} elseif ($citycount <= 7) {
$nationlevel = 3; // 주자사
} elseif ($citycount <= 10) {
$nationlevel = 4; // 주목
} elseif ($citycount <= 15) {
$nationlevel = 5; // 공
} elseif ($citycount <= 20) {
$nationlevel = 6; // 왕
} else {
$nationlevel = 7; // 황제
}
if ($nationlevel > $nation['level']) {
$levelDiff = $nationlevel - $nation['level'];
$oldLevel = $nation['level'];
$nation['level'] = $nationlevel;
$updateVals = [
'level' => $nationlevel,
'gold' => $db->sqleval('gold + %i', $nationlevel * 1000),
'rice' => $db->sqleval('rice + %i', $nationlevel * 1000),
];
switch ($nationlevel) {
case 7:
$josaUl = JosaUtil::pick(getNationLevel($nationlevel), '을');
$history[] = "<C>●</>{$year}{$month}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭하였습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭"]);
$auxVal = Json::decode($nation['aux']);
$auxVal['can_국기변경'] = 1;
$auxVal['can_국호변경'] = 1;
$updateVals['aux'] = Json::encode($auxVal);
break;
case 6:
$history[] = "<C>●</>{$year}{$month}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극하였습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극"]);
break;
case 5:
case 4:
case 3:
$history[] = "<C>●</>{$year}{$month}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명되었습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명됨"]);
break;
case 2:
$history[] = "<C>●</>{$year}{$month}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 독립하여 <Y>" . getNationLevel($nationlevel) . "</>로 나섰습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>로 나서다"]);
break;
}
$db->update('nation', $updateVals, 'nation=%i', $nation['nation']);
$turnRows = [];
foreach (Util::range(getNationChiefLevel($nation['level']), 12) as $chiefLevel) {
foreach (Util::range(GameConst::$maxChiefTurn) as $turnIdx) {
$turnRows[] = [
'nation_id' => $nation['nation'],
'officer_level' => $chiefLevel,
'turn_idx' => $turnIdx,
'action' => '휴식',
'arg' => null,
'brief' => '휴식'
];
}
}
$db->insertIgnore('nation_turn', $turnRows);
if ($levelDiff) {
//유니크 아이템 하나 돌리자
$targetKillTurn = $admin['killturn'];
$targetKillTurn -= 24 * 60 / $admin['turnterm'];
$nationGenIDList = $db->queryFirstColumn(
'SELECT no FROM general WHERE nation = %i AND killturn >= %i AND npc < 2',
$nation['nation'],
$targetKillTurn
);
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc', 'aux'], 2);
$chiefID = null;
$uniqueLotteryWeightList = [];
$relYear = $year - $startYear;
$maxTrialCountByYear = 1;
foreach (GameConst::$maxUniqueItemLimit as $tmpVals) {
[$targetYear, $targetTrialCnt] = $tmpVals;
if ($relYear < $targetYear) {
break;
}
$maxTrialCountByYear = $targetTrialCnt;
}
foreach ($nationGenList as $nationGen) {
if ($nationGen->getVar('officer_level') == 12) {
$chiefID = $nationGen->getID();
}
$trialCnt = min($maxTrialCountByYear, count(GameConst::$allItems));
foreach ($nationGen->getItems() as $item) {
if (!$item->isBuyable()) {
$trialCnt -= 1;
}
}
if ($trialCnt <= 0) {
continue;
}
$score = $nationGen->getVar('belong') + 10;
if ($nationGen->getVar('officer_level') == 12) {
$score += 60;
} else if ($nationGen->getVar('officer_level') == 11) {
$score += 30;
} else if ($nationGen->getVar('officer_level') > 4) {
$score += 15;
}
$score *= 2 ** $trialCnt;
$uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score];
}
$nationLevelUpRNG = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'nationLevelUp',
$year,
$month,
$nationID
)));
foreach (Util::range($levelDiff) as $idx) {
if (!$uniqueLotteryWeightList) {
break;
}
/** @var General */
$winnerObj = $nationLevelUpRNG->choiceUsingWeightPair($uniqueLotteryWeightList);
unset($uniqueLotteryWeightList[$winnerObj->getID()]);
$givenUniqueRNG = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'givenUnique',
$year,
$month,
$nationID,
$winnerObj->getID(),
)));
giveRandomUniqueItem($givenUniqueRNG, $winnerObj, '작위보상');
$winnerObj->applyDB($db);
}
if ($chiefID) {
$chiefObj = General::createGeneralObjFromDB($chiefID, ['belong', 'npc', 'aux'], 2);
$chiefObj->increaseInheritancePoint(InheritanceKey::unifier, 250 * $levelDiff);
$chiefObj->applyDB($db);
}
}
}
$assemblerCnt = $assemblerCnts[$nation['nation']] ?? 0;
$maxAssemblerCnt = [
1 => 0,
2 => 1,
3 => 3,
4 => 4,
5 => 6,
6 => 7,
7 => 9
][$nationlevel] ?? 0;
if ($assemblerCnt < $maxAssemblerCnt) {
$lastAssemblerID = $gameStor->assembler_id ?? 0;
$troopLeaderRng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'troopLeader',
$year,
$month,
$nationID
)));
while ($assemblerCnt < $maxAssemblerCnt) {
$lastAssemblerID += 1;
$npcObj = new Scenario\GeneralBuilder(
$troopLeaderRng,
sprintf('부대장%4d', $lastAssemblerID),
false,
null,
$nation['nation']
);
$npcObj->setAffinity(999)->setStat(10, 10, 10)
->setSpecialSingle('척사')->setEgo('che_은둔')
->setKillturn(70)->setGoldRice(0, 0)
->setNPCType(5)->fillRemainSpecAsZero($admin);
$npcObj->build($admin);
$npcID = $npcObj->getGeneralID();
$db->insert('troop', [
'troop_leader' => $npcID,
'name' => $npcObj->getGeneralName(),
'nation' => $nation['nation'],
]);
$db->update('general', [
'troop' => $npcID
], 'no=%i', $npcID);
$cmd = buildGeneralCommandClass('che_집합', General::createGeneralObjFromDB($npcID), $admin);
_setGeneralCommand($cmd, iterator_to_array(Util::range(GameConst::$maxTurn)));
$assemblerCnt += 1;
$gameStor->assembler_id = $lastAssemblerID;
}
}
}
pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
}
function checkStatistic() function checkStatistic()
{ {
$db = DB::db(); $db = DB::db();
@@ -698,7 +1021,7 @@ function checkEmperior()
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['year', 'month', 'isunited', 'refreshLimit']); $admin = $gameStor->getValues(['year', 'month', 'isunited', 'conlimit']);
if ($admin['isunited'] != 0) { if ($admin['isunited'] != 0) {
return; return;
} }
@@ -743,7 +1066,7 @@ function checkEmperior()
} }
$inheritPointManager = InheritancePointManager::getInstance(); $inheritPointManager = InheritancePointManager::getInstance();
$allUserGenerals = General::createObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc < 2')); $allUserGenerals = General::createGeneralObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc < 2'));
foreach ($allUserGenerals as $genObj) { foreach ($allUserGenerals as $genObj) {
if ($genObj->getNationID() == $nationID) { if ($genObj->getNationID() == $nationID) {
if ($genObj->getVar('officer_level') > 4) { if ($genObj->getVar('officer_level') > 4) {
@@ -751,16 +1074,15 @@ function checkEmperior()
}; };
} }
} }
processSumInheritPointRank();
TurnExecutionHelper::runEventHandler($db, $gameStor, EventTarget::United);
foreach ($allUserGenerals as $genObj) { foreach ($allUserGenerals as $genObj) {
$inheritPointManager->mergeTotalInheritancePoint($genObj); $inheritPointManager->mergeTotalInheritancePoint($genObj, true);
$inheritPointManager->applyInheritanceUser($genObj->getVar('owner')); $inheritPointManager->applyInheritanceUser($genObj->getVar('owner'));
$inheritPointManager->clearInheritancePoint($genObj);
} }
$gameStor->isunited = 2; $gameStor->isunited = 2;
$gameStor->refreshLimit = $gameStor->refreshLimit * 100; $gameStor->conlimit = $gameStor->conlimit * 100;
foreach ($db->queryFirstColumn('SELECT no FROM general WHERE npc<2 AND age>=%i', GameConst::$minPushHallAge) as $hallGeneralNo) { foreach ($db->queryFirstColumn('SELECT no FROM general WHERE npc<2 AND age>=%i', GameConst::$minPushHallAge) as $hallGeneralNo) {
CheckHall($hallGeneralNo); CheckHall($hallGeneralNo);
@@ -772,7 +1094,7 @@ function checkEmperior()
$chiefs = Util::convertArrayToDict( $chiefs = Util::convertArrayToDict(
$db->query( $db->query(
'SELECT no,npc,name,picture,belong,officer_level FROM general WHERE nation=%i AND officer_level >= 5', 'SELECT no,name,picture,belong,officer_level FROM general WHERE nation=%i AND officer_level >= 5',
$nationID $nationID
), ),
'officer_level' 'officer_level'
@@ -825,9 +1147,9 @@ function checkEmperior()
$nation = $nation; $nation = $nation;
$nation['generals'] = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nation['nation']); $nation['generals'] = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nation['nation']);
$nation['aux'] = Json::decode($nation['aux']); $nation['aux'] = Json::decode($nation['aux']);
$nation['msg'] = $nationStor->nationNotice['msg'] ?? '';; $nation['msg'] = $nationStor->notice;
$nation['scout_msg'] = $nationStor->scout_msg; $nation['scout_msg'] = $nationStor->scout_msg;
$nation['aux'] += $nationStor->max_power ?? []; $nation['aux'] += $nationStor->max_power;
$nation['history'] = getNationHistoryLogAll($nation['nation']); $nation['history'] = getNationHistoryLogAll($nation['nation']);
storeOldGenerals(0, $admin['year'], $admin['month']); storeOldGenerals(0, $admin['year'], $admin['month']);
@@ -899,44 +1221,16 @@ function checkEmperior()
'tiger' => $tigerstr, 'tiger' => $tigerstr,
'eagle' => $eaglestr, 'eagle' => $eaglestr,
'gen' => $gen, 'gen' => $gen,
'history' => Json::encode($nationHistory), 'history' => JSON::encode($nationHistory),
'aux' => $statGeneral['aux'] 'aux' => $statGeneral['aux']
]); ]);
$hiddenSeed = UniqueConst::$hiddenSeed; $hiddenSeed = UniqueConst::$hiddenSeed;
$history = ["<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다. <span class='hidden_but_copyable'>(서버시드: {$hiddenSeed})</span>"]; $history = ["<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다. <span class='hidden_but_copyable'>(서버시드: $hiddenSeed})</span>"];
pushGlobalHistoryLog($history, $admin['year'], $admin['month']); pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
//연감 월결산 //연감 월결산
LogHistory(); 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) function updateMaxDomesticCritical(General $general, $score)
@@ -951,19 +1245,8 @@ function updateMaxDomesticCritical(General $general, $score)
} }
} }
function genGenericUniqueRNG(int $year, int $month, int $generalID, ?string $reason = null): RandUtil function genGenericUniqueRNG(int $year, int $month, int $generalID): RandUtil
{ {
if($reason){
return new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'unique',
$year,
$month,
$generalID,
$reason
)));
}
return new RandUtil(new LiteHashDRBG(Util::simpleSerialize( return new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed, UniqueConst::$hiddenSeed,
'unique', 'unique',
@@ -973,7 +1256,7 @@ function genGenericUniqueRNG(int $year, int $month, int $generalID, ?string $rea
))); )));
} }
function genGenericUniqueRNGFromGeneral(General $general, string $reason): RandUtil function genGenericUniqueRNGFromGeneral(General $general): RandUtil
{ {
$logger = $general->getLogger(); $logger = $general->getLogger();
if (!$logger) { if (!$logger) {
@@ -982,5 +1265,5 @@ function genGenericUniqueRNGFromGeneral(General $general, string $reason): RandU
$year = $logger->getYear(); $year = $logger->getYear();
$month = $logger->getMonth(); $month = $logger->getMonth();
$generalID = $general->getID(); $generalID = $general->getID();
return genGenericUniqueRNG($year, $month, $generalID, $reason); return genGenericUniqueRNG($year, $month, $generalID);
} }
-6
View File
@@ -12,7 +12,6 @@ function printLimitMsg($turntime)
<head> <head>
<title>접속제한</title> <title>접속제한</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?> <?= WebUtil::printCSS('../d_shared/common.css') ?>
@@ -119,11 +118,6 @@ function backButton()
return "<button type='button' class='btn btn-primary back_btn' onclick=location.replace('./')>돌아가기</button><br>"; return "<button type='button' class='btn btn-primary back_btn' onclick=location.replace('./')>돌아가기</button><br>";
} }
function gatewayButton()
{
return "<button type='button' class='btn btn-primary back_btn' onclick=location.replace('../')>돌아가기</button><br>";
}
function CoreBackButton() function CoreBackButton()
{ {
return "<button type='button' class='btn btn-primary back_btn' onclick=location.replace('v_chiefCenter.php')>돌아가기</button><br>"; return "<button type='button' class='btn btn-primary back_btn' onclick=location.replace('v_chiefCenter.php')>돌아가기</button><br>";
+57 -1
View File
@@ -25,7 +25,6 @@ function requireAdminPermissionHTML()
<head> <head>
<title>관리메뉴</title> <title>관리메뉴</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?> <?= WebUtil::printCSS('../d_shared/common.css') ?>
@@ -148,6 +147,63 @@ function allButton(bool $seizeNPCMode, array $opts = [])
], $opts)); ], $opts));
} }
function commandButton(array $opts = [])
{
$session = Session::getInstance();
$userID = Session::getUserID();
if (!$session->isGameLoggedIn()) {
return '';
}
$db = DB::db();
$me = $db->queryFirstRow("select no,nation,officer_level,belong,permission,penalty from general where owner=%i", $userID);
$nation = $db->queryFirstRow("select nation,level,color,secretlimit from nation where nation=%i", $me['nation']) ?? [
'nation' => 0,
'level' => 0,
'secretlimit' => 99,
'color' => '#000000'
];
$bgColor = $nation['color'] ?? '#000000';
$fgColor = newColor($bgColor);
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
$showSecret = false;
$permission = checkSecretPermission($me);
$btnClassForTournament = $opts['btnClass'];
if ($opts['isTournamentApplicationOpen']) {
if ($btnClassForTournament != 'dropdown-item') {
$btnClassForTournament = 'toolbarButton2';
}
}
$btnClassForBetting = $opts['btnClass'];
if ($opts['isBettingActive']) {
if ($btnClassForTournament != 'dropdown-item') {
$btnClassForBetting = 'toolbarButton2';
}
}
if ($permission >= 1) {
$showSecret = true;
} else if ($me['officer_level'] == 0) {
$showSecret = false;
}
return $templates->render('commandButton', array_merge([
'bgColor' => $bgColor,
'fgColor' => $fgColor,
'meLevel' => $me['officer_level'],
'nationLevel' => $nation['level'],
'showSecret' => $showSecret,
'permission' => $permission,
'btnClassForTournament' => $btnClassForTournament,
'btnClassForBetting' => $btnClassForBetting,
], $opts));
}
function formatWounded(int $value, int $wound): string function formatWounded(int $value, int $wound): string
{ {
if ($wound == 0) { if ($wound == 0) {
+283 -25
View File
@@ -4,32 +4,173 @@ namespace sammo;
use sammo\Enums\InheritanceKey; use sammo\Enums\InheritanceKey;
use sammo\Enums\RankColumn; use sammo\Enums\RankColumn;
use Ds\Map; use Ds\Map;
use sammo\Enums\ResourceType;
use sammo\Event\Action;
/** /**
* 시간 단위로 일어나는 이벤트들에 대한 함수 모음 * 시간 단위로 일어나는 이벤트들에 대한 함수 모음
*/ */
/** @deprecated */
function processSumInheritPointRank(){ function processSumInheritPointRank(){
$db = DB::db(); $db = DB::db();
$generals = General::createGeneralObjListFromDB(null, null, 2);
$points = new Map();
$points->allocate(count($generals));
foreach($generals as $general){
$generalID = $general->getID();
$points[$generalID] = 0;
}
foreach(InheritanceKey::cases() as $key){
if($key === InheritanceKey::previous){
continue;
}
$subPoints = InheritancePointManager::getInstance()->getInheritancePointFromAll($generals, $key);
foreach($generals as $general){
$generalID = $general->getID();
$points[$generalID] += $subPoints[$generalID] ?? 0;
}
}
$pointsPairs = [];
foreach($points as $generalID => $point){
$pointsPairs[] = [
'nation_id' => $generals[$generalID]->getNationID(),
'general_id' => $generalID,
'type' => RankColumn::inherit_point_earned_by_merge->value,
'value' => $point,
];
}
//XXX: multiple batch update가 제공되지 않으므로..
$db->delete('rank_data', '`type` = %s', RankColumn::inherit_point_earned_by_merge->value);
$db->insert('rank_data', $pointsPairs);
$db->query(
'UPDATE `rank_data` D SET `value` = (SELECT SUM(`value`) FROM `rank_data` S WHERE S.general_id = D.general_id AND S.`type` IN %ls) WHERE D.`type` = %s',
[RankColumn::inherit_point_earned_by_action->value, RankColumn::inherit_point_earned_by_merge->value],
RankColumn::inherit_point_earned->value
);
$db->query(
'UPDATE `rank_data` D SET `value` = (SELECT `value` FROM `rank_data` S WHERE S.general_id = D.general_id AND S.`type` = %s) WHERE D.`type` = %s',
RankColumn::inherit_point_spent_dynamic->value,
RankColumn::inherit_point_spent->value
);
}
//1월마다 실행
function processSpring() {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$e_env = $gameStor->getValues(['startyear', 'year', 'month']); // 1월엔 무조건 내정 1% 감소
$e_env['currentEventID'] = 0; $db->update('city',[
Action::build(["ProcessIncome", ResourceType::rice->value])->run($e_env); 'dead'=>0,
'agri'=>$db->sqleval('agri * 0.99'),
'comm'=>$db->sqleval('comm * 0.99'),
'secu'=>$db->sqleval('secu * 0.99'),
'def'=>$db->sqleval('def * 0.99'),
'wall'=>$db->sqleval('wall * 0.99'),
],true);
//인구 증가
popIncrease();
// > 10000 유지비 3%, > 1000 유지비 1%
// 유지비 1%
$db->update('general', [
'gold'=>$db->sqleval('IF(gold > 10000, gold * 0.97, gold * 0.99)')
], 'gold > 1000');
// > 100000 유지비 5%, > 100000 유지비 3%, > 1000 유지비 1%
$db->update('nation', [
'gold'=>$db->sqleval('IF(gold > 100000, gold * 0.95, IF(gold > 10000, gold * 0.97, gold * 0.99))')
], 'gold > 1000');
$admin = $gameStor->getValues(['year', 'month']);
pushGlobalHistoryLog(["<R>★</>{$admin['year']}{$admin['month']}월: <S>모두들 즐거운 게임 하고 계신가요? ^^ <Y>매너 있는 플레이</> 부탁드리고, <M>지나친 훼접</>은 삼가주세요~</>"], $admin['year'], $admin['month']);
} }
/** @deprecated */
function processGoldIncome() { function processGoldIncome() {
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$e_env = $gameStor->getValues(['startyear', 'year', 'month']); [$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
$e_env['currentEventID'] = 0; $adminLog = [];
Action::build(["ProcessIncome", ResourceType::gold->value])->run($e_env);
$nationList = $db->query('SELECT name,nation,capital,gold,level,rate_tmp,bill,type from nation');
$cityListByNation = Util::arrayGroupBy($db->query('SELECT * FROM city'), 'nation');
$generalRawListByNation = Util::arrayGroupBy($db->query('SELECT no,name,nation,gold,officer_level,dedication,city FROM general WHERE npc != 5'), 'nation');
//국가별 처리
foreach($nationList as $nation) {
$nationID = $nation['nation'];
$generalRawList = $generalRawListByNation[$nationID];
$income = getGoldIncome($nationID, $nation['level'], $nation['rate_tmp'], $nation['capital'], $nation['type'], $cityListByNation[$nationID]??[]);
$originoutcome = getOutcome(100, $generalRawList);
$outcome= Util::round($nation['bill'] / 100 * $originoutcome);
// 실제 지급량 계산
$nation['gold'] += $income;
// 기본량도 안될경우
if($nation['gold'] < GameConst::$basegold) {
$realoutcome = 0;
// 실지급률
$ratio = 0;
//기본량은 넘지만 요구량이 안될경우
} elseif($nation['gold'] - GameConst::$basegold < $outcome) {
$realoutcome = $nation['gold'] - GameConst::$basegold;
$nation['gold'] = GameConst::$basegold;
// 실지급률
$ratio = $realoutcome / $originoutcome;
} else {
$realoutcome = $outcome;
$nation['gold'] -= $realoutcome;
// 실지급률
$ratio = $realoutcome / $originoutcome;
}
$nation['gold'] = Util::valueFit($nation['gold'], GameConst::$basegold);
$adminLog[] = StringUtil::padStringAlignRight((string)$nation['name'],12," ")
." // 세금 : ".StringUtil::padStringAlignRight((string)$income,6," ")
." // 세출 : ".StringUtil::padStringAlignRight((string)$originoutcome,6," ")
." // 실제 : ".tab2((string)$realoutcome,6," ")
." // 지급률 : ".tab2((string)round($ratio*100,2),5," ")
." % // 결과금 : ".tab2((string)$nation['gold'],6," ");
$incomeText = number_format($income);
$incomeLog = "이번 수입은 금 <C>$incomeText</>입니다.";
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->prev_income_gold = $income;
$db->update('nation', [
'gold'=>$nation['gold']
], 'nation=%i', $nationID);
// 각 장수들에게 지급
foreach ($generalRawList as $rawGeneral) {
$generalObj = new General($rawGeneral, null, null, null, $year, $month, false);
$gold = Util::round(getBill($generalObj->getVar('dedication'))*$ratio);
$generalObj->increaseVar('gold', $gold);
$logger = $generalObj->getLogger();
if($generalObj->getVar('officer_level') > 4){
$logger->pushGeneralActionLog($incomeLog, $logger::PLAIN);
}
$goldText = number_format($gold);
$logger->pushGeneralActionLog("봉급으로 금 <C>$goldText</>을 받았습니다.", $logger::PLAIN);
$generalObj->applyDB($db);
}
}
$logger = new ActionLogger(0, 0, $year, $month);
$logger->pushGlobalHistoryLog('<W><b>【지급】</b></>봄이 되어 봉록에 따라 자금이 지급됩니다.');
$logger->flush();
pushAdminLog($adminLog);
} }
function popIncrease() { function popIncrease() {
@@ -163,6 +304,29 @@ function getGoldIncome(int $nationID, int $nationLevel, float $taxRate, int $cap
return $cityIncome; return $cityIncome;
} }
function processWarIncome() {
$db = DB::db();
$cityListByNation = Util::arrayGroupBy($db->query('SELECT * FROM city'), 'nation');
foreach(getAllNationStaticInfo() as $nation){
if($nation['level'] <= 0){
continue;
}
$nationID = $nation['nation'];
$income = getWarGoldIncome($nation['type'], $cityListByNation[$nationID]??[]);
$db->update('nation', [
'gold'=>$db->sqleval('gold + %i', $income)
], 'nation=%i', $nationID);
}
// 10%수입, 20%부상병
$db->update('city', [
'pop'=>$db->sqleval('pop + dead * %d', 0.2),
'dead'=>0
], true);
}
function getWarGoldIncome(string $nationType, array $cityList){ function getWarGoldIncome(string $nationType, array $cityList){
$nationTypeObj = buildNationTypeClass($nationType); $nationTypeObj = buildNationTypeClass($nationType);
@@ -174,14 +338,115 @@ function getWarGoldIncome(string $nationType, array $cityList){
return $cityIncome; return $cityIncome;
} }
/** @deprecated */
//7월마다 실행
function processFall() {
$db = DB::db();
// 7월엔 무조건 내정 1% 감소
$db->update('city',[
'dead'=>0,
'agri'=>$db->sqleval('agri * 0.99'),
'comm'=>$db->sqleval('comm * 0.99'),
'secu'=>$db->sqleval('secu * 0.99'),
'def'=>$db->sqleval('def * 0.99'),
'wall'=>$db->sqleval('wall * 0.99'),
],true);
//인구 증가
popIncrease();
// > 10000 유지비 3%, > 1000 유지비 1%
// 유지비 1%
$db->update('general', [
'rice'=>$db->sqleval('IF(rice > 10000, rice * 0.97, rice * 0.99)')
], 'rice > 1000');
// > 100000 유지비 5%, > 100000 유지비 3%, > 1000 유지비 1%
$db->update('nation', [
'rice'=>$db->sqleval('IF(rice > 100000, rice * 0.95, IF(rice > 10000, rice * 0.97, rice * 0.99))')
], 'rice > 1000');
}
function processRiceIncome() { function processRiceIncome() {
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$e_env = $gameStor->getValues(['startyear', 'year', 'month']); [$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
$e_env['currentEventID'] = 0; $adminLog = [];
Action::build(["ProcessIncome", ResourceType::rice->value])->run($e_env);
$nationList = $db->query('SELECT name,level,nation,capital,rice,rate_tmp,bill,type from nation');
$cityListByNation = Util::arrayGroupBy($db->query('SELECT * FROM city'), 'nation');
$generalRawListByNation = Util::arrayGroupBy($db->query('SELECT no,name,nation,rice,officer_level,dedication,city FROM general WHERE npc != 5'), 'nation');
//국가별 처리
foreach($nationList as $nation) {
$nationID = $nation['nation'];
$generalRawList = $generalRawListByNation[$nationID];
$income = getRiceIncome($nation['nation'], $nation['level'], $nation['rate_tmp'], $nation['capital'], $nation['type'], $cityListByNation[$nationID]??[]);
$income += getWallIncome($nation['nation'], $nation['level'], $nation['rate_tmp'], $nation['capital'], $nation['type'], $cityListByNation[$nationID]??[]);
$originoutcome = getOutcome(100, $generalRawList);
$outcome= Util::round($nation['bill'] / 100 * $originoutcome);
// 실제 지급량 계산
$nation['rice'] += $income;
// 기본량도 안될경우
if($nation['rice'] < GameConst::$baserice) {
$realoutcome = 0;
// 실지급률
$ratio = 0;
//기본량은 넘지만 요구량이 안될경우
} elseif($nation['rice'] - GameConst::$baserice < $outcome) {
$realoutcome = $nation['rice'] - GameConst::$baserice;
$nation['rice'] = GameConst::$baserice;
// 실지급률
$ratio = $realoutcome / $originoutcome;
} else {
$realoutcome = $outcome;
$nation['rice'] -= $realoutcome;
// 실지급률
$ratio = $realoutcome / $originoutcome;
}
$nation['rice'] = Util::valueFit($nation['rice'], GameConst::$baserice);
$adminLog[] = StringUtil::padStringAlignRight($nation['name'],12," ")
." // 세곡 : ".StringUtil::padStringAlignRight((string)$income,6," ")
." // 세출 : ".StringUtil::padStringAlignRight((string)$originoutcome,6," ")
." // 실제 : ".tab2((string)$realoutcome,6," ")
." // 지급률 : ".tab2((string)round($ratio*100,2),5," ")
." % // 결과곡 : ".tab2((string)$nation['rice'],6," ");
$incomeText = number_format($income);
$incomeLog = "이번 수입은 쌀 <C>$incomeText</>입니다.";
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->prev_income_rice = $income;
$db->update('nation', [
'rice'=>$nation['rice']
], 'nation=%i', $nationID);
// 각 장수들에게 지급
foreach ($generalRawList as $rawGeneral) {
$generalObj = new General($rawGeneral, null, null, null, $year, $month, false);
$rice = Util::round(getBill($generalObj->getVar('dedication'))*$ratio);
$generalObj->increaseVar('rice', $rice);
$logger = $generalObj->getLogger();
if($generalObj->getVar('officer_level') > 4){
$logger->pushGeneralActionLog($incomeLog, $logger::PLAIN);
}
$riceText = number_format($rice);
$logger->pushGeneralActionLog("봉급으로 쌀 <C>$riceText</>을 받았습니다.", $logger::PLAIN);
$generalObj->applyDB($db);
}
}
$logger = new ActionLogger(0, 0, $year, $month);
$logger->pushGlobalHistoryLog('<W><b>【지급】</b></>가을이 되어 봉록에 따라 군량이 지급됩니다.');
$logger->flush();
pushAdminLog($adminLog);
} }
function getRiceIncome(int $nationID, int $nationLevel, float $taxRate, int $capitalID, string $nationType, ?array $cityList) { function getRiceIncome(int $nationID, int $nationLevel, float $taxRate, int $capitalID, string $nationType, ?array $cityList) {
@@ -364,14 +629,7 @@ function disaster(RandUtil $rng) {
$logger->flush(); $logger->flush();
if (!$isGood) { if (!$isGood) {
[$queryColumns,,] = General::mergeQueryColumn(); $generalListByCity = Util::arrayGroupBy($db->query('SELECT no, name, nation, city, officer_level, injury, leadership, strength, intel, horse, weapon, book, item, crew, crewtype, atmos, train, special, special2 FROM general WHERE city IN %li', Util::squeezeFromArray($targetCityList, 'city')), 'city');
$generalListByCity = Util::arrayGroupBy(
$db->query(
'SELECT %l FROM general WHERE city IN %li',
Util::formatListOfBackticks($queryColumns),
Util::squeezeFromArray($targetCityList, 'city')
),
'city');
//NOTE: 쿼리 1번이지만 복잡하기 vs 쿼리 여러번이지만 조금 더 깔끔하기 //NOTE: 쿼리 1번이지만 복잡하기 vs 쿼리 여러번이지만 조금 더 깔끔하기
foreach ($targetCityList as $city) { foreach ($targetCityList as $city) {
$affectRatio = Util::valueFit($city['secu'] / $city['secu_max'] / 0.8, 0, 1); $affectRatio = Util::valueFit($city['secu'] / $city['secu_max'] / 0.8, 0, 1);
@@ -390,7 +648,7 @@ function disaster(RandUtil $rng) {
$generalList = array_map( $generalList = array_map(
function($rawGeneral) use ($city, $year, $month){ function($rawGeneral) use ($city, $year, $month){
return new General($rawGeneral, null, null, $city, null, $year, $month, false); return new General($rawGeneral, null, $city, null, $year, $month, false);
}, },
$generalListByCity[$city['city']]??[] $generalListByCity[$city['city']]??[]
); );
+2 -2
View File
@@ -882,7 +882,7 @@ function setGift($tnmt_type, $tnmt, $phase)
//포상 장수 이름, 금액 //포상 장수 이름, 금액
$resultHelper[$generalID]['reward'] += $cost; $resultHelper[$generalID]['reward'] += $cost;
$resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>4강 진출</span>"; $resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>4강 진출</span>";
General::createObjFromDB($generalID)->increaseInheritancePoint(InheritanceKey::tournament, 10); General::createGeneralObjFromDB($generalID)->increaseInheritancePoint(InheritanceKey::tournament, 10);
} }
//결승자 명성 돈 //결승자 명성 돈
$cost = $admin['develcost'] * 6; $cost = $admin['develcost'] * 6;
@@ -946,7 +946,7 @@ function setGift($tnmt_type, $tnmt, $phase)
$winnerLogger->pushGlobalHistoryLog("<B><b>【대회】</b></><C>{$tp}</> 대회에서 <Y>{$winner['name']}</>{$josaYiWinner} <C>우승</>, <Y>{$runnerUp['name']}</>{$josaYiRunnerUp} <C>준우승</>을 차지하여 천하에 이름을 떨칩니다!", ActionLogger::EVENT_YEAR_MONTH); $winnerLogger->pushGlobalHistoryLog("<B><b>【대회】</b></><C>{$tp}</> 대회에서 <Y>{$winner['name']}</>{$josaYiWinner} <C>우승</>, <Y>{$runnerUp['name']}</>{$josaYiRunnerUp} <C>준우승</>을 차지하여 천하에 이름을 떨칩니다!", ActionLogger::EVENT_YEAR_MONTH);
$winnerLogger->pushGlobalHistoryLog("<B><b>【대회】</b></><C>{$tp}</> 대회의 <S>우승자</>에게는 <C>{$winnerRewardText}</>, <S>준우승자</>에겐 <C>{$runnerUpRewardText}</>의 <S>상금</>과 약간의 <S>명성</>이 주어집니다!", ActionLogger::EVENT_YEAR_MONTH); $winnerLogger->pushGlobalHistoryLog("<B><b>【대회】</b></><C>{$tp}</> 대회의 <S>우승자</>에게는 <C>{$winnerRewardText}</>, <S>준우승자</>에겐 <C>{$runnerUpRewardText}</>의 <S>상금</>과 약간의 <S>명성</>이 주어집니다!", ActionLogger::EVENT_YEAR_MONTH);
$generalObjList = General::createObjListFromDB(array_keys($resultHelper)); $generalObjList = General::createGeneralObjListFromDB(array_keys($resultHelper));
foreach ($resultHelper as $generalID => $general) { foreach ($resultHelper as $generalID => $general) {
$rewardText = number_format($general['reward']); $rewardText = number_format($general['reward']);
+429 -21
View File
@@ -2,44 +2,452 @@
namespace sammo; namespace sammo;
use sammo\DTO\VoteInfo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
Session::requireLogin()->loginGame()->setReadOnly();
$mapName = GameConst::$mapName; $session = Session::requireLogin()->loginGame()->setReadOnly();
$userID = Session::getUserID();
increaseRefresh("메인", 1);
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
if (!$userID) {
header('Location:..');
die();
}
//턴 실행.
TurnExecutionHelper::executeAllCommand();
if (!$session->isGameLoggedIn()) {
header('Location:..');
die();
}
$me = $db->queryFirstRow(
'SELECT no,con,turntime,newmsg,newvote,`officer_level` from general where owner = %i',
$userID
);
//그새 사망이면
if ($me === null) {
$session->logoutGame();
header('Location: ../');
die();
}
$gameStor->cacheAll(true);
if ($me['newmsg'] == 1 || $me['newvote'] == 1) {
$db->update('general', [
'newmsg' => 0,
'newvote' => 0
], 'owner=%i', $userID);
}
$plock = boolval($db->queryFirstField('SELECT plock FROM plock WHERE `type`="GAME" LIMIT 1'));
$con = checkLimit($me['con']);
if ($con >= 2) {
printLimitMsg($me['turntime']);
exit();
}
$generalObj = General::createGeneralObjFromDB($me['no']);
$generalObj->setRawCity($db->queryFirstRow('SELECT * FROM city WHERE city = %i', $generalObj->getCityID()));
$scenario = $gameStor->scenario_text;
$nationID = $generalObj->getNationID();
if ($nationID) {
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->cacheAll();
}
if ($gameStor->extended_general == 0) {
$extend = "표준";
} else {
$extend = "확장";
}
if ($gameStor->fiction == 0) {
$fiction = "사실";
} else {
$fiction = "가상";
}
if ($gameStor->npcmode == 0) {
$npcmode = "불가능";
} else if ($gameStor->npcmode == 1) {
$npcmode = "가능";
} else {
$npcmode = "선택 생성";
}
$color = "cyan";
$serverName = UniqueConst::$serverName;
$serverCnt = $gameStor->server_cnt;
$auctionCount = $db->queryFirstField('SELECT count(*) FROM ng_auction WHERE finished = 0');
$isTournamentActive = $gameStor->tournament > 0;
$isTournamentApplicationOpen = $gameStor->tournament == 1;
$isBettingActive = $gameStor->tournament == 6;
$myNationStatic = getNationStaticInfo($generalObj->getNationID());
$nationColorType = substr($myNationStatic['color'] ?? '#000000', 1);
$autorunUser = ($gameStor->autorun_user) ?? [];
$otherTextInfo = [];
if ($gameStor->join_mode == 'onlyRandom') {
$otherTextInfo[] = '랜덤 임관 전용';
}
if ($autorunUser['limit_minutes'] ?? false) {
$otherTextInfo[] = getAutorunInfo($autorunUser);
}
if (!$otherTextInfo) {
$otherTextInfo = '표준';
} else {
$otherTextInfo = join(', ', $otherTextInfo);
}
$lastVoteID = $gameStor->lastVote;
$lastVote = null;
if ($lastVoteID) {
$voteStor = KVStorage::getStorage($db, 'vote');
$lastVote = VoteInfo::fromArray($voteStor->getValue("vote_{$lastVoteID}"));
if ($lastVote->endDate && $lastVote->endDate < TimeUtil::now()) {
$lastVote = null;
}
}
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title><?= $serverName ?>: 메인</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" /> <meta name="viewport" content="width=500" />
<title><?= UniqueConst::$serverName ?>: 메인</title>
<?= WebUtil::printStaticValues([
'staticValues' => [
'serverName' => UniqueConst::$serverName,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'mapName' => GameConst::$mapName,
'unitSet' => GameConst::$unitSet,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'serverNow' => TimeUtil::now(false),
]
], false) ?>
<?= WebUtil::printJS('../d_shared/common_path.js') ?> <?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS("js/map/theme_{$mapName}.js") ?> <?= WebUtil::printJS('d_shared/base_map.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?> <?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printDist('vue', 'v_main', true) ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" /> <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('vue', 'v_front', true) ?> <?= WebUtil::printCSS('css/map.css') ?>
<?= WebUtil::printStaticValues([
//deprecated, staticValues를 이용할 것
'serverName' => $serverName,
'serverCnt' => $serverCnt,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'serverNow' => TimeUtil::now(false),
'lastExecuted' => $gameStor->turntime,
'isLocked' => $plock,
'isTournamentActive' => $isTournamentActive,
'isBettingActive' => $isBettingActive,
'staticValues' => [
'serverName' => $serverName,
'serverCnt' => $serverCnt,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'commandList' => getCommandTable($generalObj),
'serverNow' => TimeUtil::now(false),
'lastExecuted' => $gameStor->turntime,
'isLocked' => $plock,
'isTournamentActive' => $isTournamentActive,
'isBettingActive' => $isBettingActive,
'mapName' => GameConst::$mapName,
'unitSet' => GameConst::$unitSet,
]
]) ?>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
</head> </head>
<body> <body class="img_back sam-color-<?= $nationColorType ?>">
<div id="app"></div> <div id="container" class="bg0">
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></button></div>
</div>
<div class="tb_layout row gx-0">
<div id="server_title" class="row py-2 center">
<h3>삼국지 모의전투 HiDCHe <?= $serverName . $serverCnt ?>기 <span class="avoid-wrap">(<font color=cyan><?= $scenario ?></font>)</span></h3>
</div>
<div class="row center gx-0">
<div class="s-border-t col py-2 col-8 col-md-4" style="color:<?= $color ?>;">
<?= $scenario ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
NPC 수, 상성 : <?= $extend ?>,<?= $fiction ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
NPC선택 : <?= $npcmode ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
토너먼트 : <?= getTournamentTermText($gameStor->turnterm) ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-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">
<?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 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">
<?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">
<?php
?>
<?php if ($lastVote === null) : ?>
<span style='color:magenta'>진행중 설문 없음</span>
<?php else : ?>
<span style='color:cyan'>설문 진행중</span> : <span><?= $lastVote->title ?></span>
<?php endif; ?>
</div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">접속중인 국가: <?= $gameStor->online_nation ?></div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">운영자 메세지 : <span style='color:yellow;'><?= $gameStor->msg ?></span></div>
</div>
<div class="row gx-0">
<div class="col s-border-t py-2" id="nation-msg-position">
<div class="px-2">【 국가방침 】</div>
<div id='nation-msg-box'>
<div id='nation-msg'><?= nationMsg($generalObj) ?></div>
</div>
</div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">
【 접속자 】<?= onlinegen($generalObj) ?>
</div>
</div>
<?php if ($session->userGrade >= 5) : ?>
<div class="row">
<div class="col">
<a href='_admin1.php' target='_blank'><button type='button'>게임관리</button></a>
<a href='_admin2.php' target='_blank'><button type='button'>회원관리</button></a>
<a href='_admin4.php' target='_blank'><button type='button'>멀티관리</button></a>
<a href='_admin5.php' target='_blank'><button type='button'>일제정보</button></a>
<a href='_admin7.php' target='_blank'><button type='button'>로그정보</button></a>
<a href='_admin8.php' target='_blank'><button type='button'>외교정보</button></a>
<a href='_119.php' target='_blank'><button type='button'>119</button></a>
</div>
</div>
<?php elseif ($session->userGrade == 4) : ?>
<div class="row">
<div class="col">
<a href='_119.php' target='_blank'><button type='button'>119</button></a>
</div>
</div>
<?php endif; ?>
<div id="map_view" class="gx-0">
<div id="mapZone" class="view-item"><?= getMapHtml() ?></div>
<div class="view-item" id="reservedCommandZone">
<div id="reservedCommandList"></div>
<div id="actionMiniPlate" class="gx-0 row">
<div class="col">
<div class="gx-1 row">
<div class="col-8 d-grid"><button type='button' class='btn btn-sammo-base2 refreshPage'>갱 신</button></div>
<div class="col-4 d-grid"><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></div>
</div>
</div>
</div>
</div>
<div id="cityInfo" class="view-item" style="border:none;text-align:center;"><?= cityInfo($generalObj) ?></div>
<div id="nation-position"><?php myNationInfo($generalObj); ?></div>
<div id="general-position"><?php generalInfo($generalObj); ?></div>
<div id="generalCommandButton" class="row gx-0">
<div class="buttonPlate bg2">
<?= commandButton([
'splitBtnBegin' => '<div class="btn-group">',
'splitBtnEnd' => '</div>',
'splitZoneSign' => '<button type="button" class="btn btn-sammo-nation dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"><span class="visually-hidden">Toggle Dropdown</span></button>',
'splitZoneBegin' => '<ul class="dropdown-menu dropdown-menu-end">',
'splitZoneEnd' => '</ul>',
'splitSubBtnBegin' => '<li>',
'splitSubBtnEnd' => '</li>',
'btnClass' => 'btn btn-sammo-nation',
'btnSplitClass' => 'dropdown-item',
'isTournamentApplicationOpen' => $isTournamentApplicationOpen,
'isBettingActive' => $isBettingActive
])
?></div>
</div>
</div>
</div>
<div id="actionMiniPlateSub" class="gx-0 row">
<div class="col">
<div class="gx-1 row">
<div class="col-3 d-grid"><button type='button' class="btn btn-dark" onclick="scrollHardTo('reservedCommandList')">명령으로</button></div>
<div class="col-5 d-grid"><button type='button' class='btn btn-sammo-base2 refreshPage'>갱 신</button></div>
<div class="col-4 d-grid"><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></div>
</div>
</div>
</div>
<div class="row gx-0">
<div class="col-md-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="bg1 center s-border-tb"><b>개인 기록</b></div>
<div id="general_log" style="text-align:left;"><?= formatHistoryToHTML(getGeneralActionLogRecent($me['no'], 15)) ?></div>
</div>
<div class="col-12" id="world_history-position">
<div class="bg1 center s-border-tb"><b>중원 정세</b></div>
<div id="world_history" colspan=2 style="text-align:left;"><?= formatHistoryToHTML(getGlobalHistoryLogRecent(15)) ?></div>
</div>
</div>
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></div>
<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">
<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">
<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">서신전달&amp;갱신</button></div>
</div>
<div class="col-md-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="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="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="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>
</section>
</div>
</div>
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></div><?= banner() ?>
</div>
</div>
<?php
if ($con == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다!");
}
if ($me['newmsg'] == 1) {
MessageBox("새로운 서신이 도착했습니다!");
}
if ($me['newvote'] == 1) {
$develcost = $gameStor->develcost * 5;
MessageBox("설문조사에 참여하시면 금{$develcost}과 유니크템을 드립니다! (우측 상단 설문조사 메뉴)");
}
?>
</div>
<nav class="navbar navbar-expand fixed-bottom navbar-dark bg-dark d-sm-block d-md-none p-0" id="navbar500">
<div class="container-fluid px-0">
<div class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mx-auto">
<li class="nav-item dropup">
<div class="dropdown-toggle text-white btn btn-sammo-base2" id="navbarGlobal" role="button" data-bs-toggle="dropdown" aria-expanded="false">
외부 메뉴
</div>
<ul class="dropdown-menu dropdown-menu-start" aria-labelledby="navbarGlobal" id="navbarGlobalItems">
<?= allButton($gameStor->npcmode == 1, ['btnBegin' => '<li>', 'btnEnd' => '</li>', 'btnClass' => 'dropdown-item']) ?>
</ul>
</li>
<li class="nav-item dropup">
<div class="dropdown-toggle btn btn-sammo-nation" id="navbarNation" role="button" data-bs-toggle="dropdown" aria-expanded="false">
국가 메뉴
</div>
<ul class="dropdown-menu" aria-labelledby="navbarNation" id="navbarNationItems">
<?= commandButton([
'btnBegin' => '<li>',
'btnEnd' => '</li>',
'splitMainBegin' => '<div class="d-none">',
'splitMainEnd' => '</div>',
'splitSubBtnBegin' => '<li>',
'splitSubBtnEnd' => '</li>',
'btnClass' => 'dropdown-item',
'btnSplitClass' => 'dropdown-item',
'isTournamentApplicationOpen' => $isTournamentApplicationOpen,
'isBettingActive' => $isBettingActive
]) ?>
</ul>
</li>
<li class="nav-item dropup">
<div class="dropdown-toggle text-white btn btn-dark" id="navbarQuick" role="button" data-bs-toggle="dropdown" aria-expanded="false">
빠른 이동
</div>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown" id="navbarQuickItems">
<li><a class="dropdown-item disabled">국가 정보</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('nation-msg-position')" class="dropdown-item">방침</button></li>
<li><button type="button" onclick="scrollHardTo('reservedCommandList')" class="dropdown-item">명령</button></li>
<li><button type="button" onclick="scrollHardTo('nation-position')" class="dropdown-item">국가</button></li>
<li><button type="button" onclick="scrollHardTo('general-position')" class="dropdown-item">장수</button></li>
<li><button type="button" onclick="scrollHardTo('cityInfo')" class="dropdown-item">도시</button></li>
<li><a class="dropdown-item disabled">동향 정보</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('mapZone')" class="dropdown-item">지도</button></li>
<li><button type="button" onclick="scrollHardTo('general_public_record-position')" class="dropdown-item">동향</button></li>
<li><button type="button" onclick="scrollHardTo('general_log-position')" class="dropdown-item">개인</button></li>
<li><button type="button" onclick="scrollHardTo('world_history-position')" class="dropdown-item">정세</button></li>
<li><span>&nbsp;</span></li>
<li><a class="dropdown-item disabled">메시지</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('public_talk_position')" class="dropdown-item">전체</button></li>
<li><button type="button" onclick="scrollHardTo('national_talk_position')" class="dropdown-item">국가</button></li>
<li><button type="button" onclick="scrollHardTo('private_talk_position')" class="dropdown-item">개인</button></li>
<li><button type="button" onclick="scrollHardTo('diplomacy_talk_position')" class="dropdown-item">외교</button></li>
<li><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></li>
</ul>
</li>
<li class="nav-item">
<a class="refreshPage btn btn-sammo-base2 text-white" role="button">갱신</a>
</li>
</ul>
</div>
</div>
</nav>
</body> </body>
</html> </html>
+12 -14
View File
@@ -28,7 +28,6 @@ if ($session->userGrade < 5 && !$allowReset) {
<head> <head>
<title>설치</title> <title>설치</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?> <?= WebUtil::printJS('../d_shared/common_path.js') ?>
@@ -39,8 +38,8 @@ if ($session->userGrade < 5 && !$allowReset) {
<body> <body>
<div class="container"> <div class="container">
<h1 class="row justify-content-lg-center">삼국지 모의전투 HiDCHe 리셋</h1> <h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe 리셋</h1>
<div class="row justify-content-lg-center"> <div class="row justify-content-md-center">
<div class="col col-lg-8"> <div class="col col-lg-8">
<div class="card" id="game_form_card"> <div class="card" id="game_form_card">
@@ -94,8 +93,8 @@ if ($session->userGrade < 5 && !$allowReset) {
<label for="fiction" class="col-sm-3 col-form-label">NPC 상성</label> <label for="fiction" class="col-sm-3 col-form-label">NPC 상성</label>
<div class="col-sm-9"> <div class="col-sm-9">
<div id="fiction" class="btn-group btn-group-toggle" data-bs-toggle="buttons"> <div id="fiction" class="btn-group btn-group-toggle" data-bs-toggle="buttons">
<input type="radio" id="fiction_0" class="btn-check" name="fiction" value="0"><label for="fiction_0" class="btn btn-secondary"> 연의 </label> <input type="radio" id="fiction_0" class="btn-check" name="fiction" value="0" checked><label for="fiction_0" class="btn btn-secondary"> 연의 </label>
<input type="radio" id="fiction_1" class="btn-check" name="fiction" value="1" checked><label for="fiction_1" class="btn btn-secondary"> 가상 </label> <input type="radio" id="fiction_1" class="btn-check" name="fiction" value="1"><label for="fiction_1" class="btn btn-secondary"> 가상 </label>
</div> </div>
</div> </div>
</div> </div>
@@ -115,7 +114,6 @@ if ($session->userGrade < 5 && !$allowReset) {
<div class="col-sm-9"> <div class="col-sm-9">
<div id="block_general_create" class="btn-group btn-group-toggle" data-bs-toggle="buttons"> <div id="block_general_create" class="btn-group btn-group-toggle" data-bs-toggle="buttons">
<input type="radio" class="btn-check" id="block_general_create_0" name="block_general_create" value="0" checked><label for="block_general_create_0" class="btn btn-secondary">가능</label> <input type="radio" class="btn-check" id="block_general_create_0" name="block_general_create" value="0" checked><label for="block_general_create_0" class="btn btn-secondary">가능</label>
<input type="radio" class="btn-check" id="block_general_create_2" name="block_general_create" value="2"><label for="block_general_create_2" class="btn btn-secondary">장수명무작위</label>
<input type="radio" class="btn-check" id="block_general_create_1" name="block_general_create" value="1"><label for="block_general_create_1" class="btn btn-secondary">불가</label> <input type="radio" class="btn-check" id="block_general_create_1" name="block_general_create" value="1"><label for="block_general_create_1" class="btn btn-secondary">불가</label>
</div> </div>
</div> </div>
@@ -137,13 +135,13 @@ if ($session->userGrade < 5 && !$allowReset) {
<div class="col-sm-9"> <div class="col-sm-9">
<div class="input-group"> <div class="input-group">
<div class="btn-group btn-group-toggle" data-bs-toggle="buttons"> <div class="btn-group btn-group-toggle" data-bs-toggle="buttons">
<input type="checkbox" id="autorun_develop" class="autorun_user_chk btn-check" data-key="develop" name="autorun_user[]" value="develop" checked><label class="btn btn-secondary" for="autorun_develop">내정</label> <input type="checkbox" id="autorun_develop" class="autorun_user_chk btn-check" data-key="develop" name="autorun_user[]" value="develop"><label class="btn btn-secondary" for="autorun_develop">내정</label>
<input type="checkbox" id="autorun_warp" class="autorun_user_chk btn-check" data-key="warp" name="autorun_user[]" value="warp" checked><label class="btn btn-secondary" for="autorun_warp">순간이동</label> <input type="checkbox" id="autorun_warp" class="autorun_user_chk btn-check" data-key="warp" name="autorun_user[]" value="warp"><label class="btn btn-secondary" for="autorun_warp">순간이동</label>
<input type="checkbox" id="autorun_recruit" class="autorun_user_chk btn-check" data-key="recruit" name="autorun_user[]" value="recruit" checked><label class="btn btn-secondary" for="autorun_recruit">징병</label> <input type="checkbox" id="autorun_recruit" class="autorun_user_chk btn-check" data-key="recruit" name="autorun_user[]" value="recruit"><label class="btn btn-secondary" for="autorun_recruit">징병</label>
<input type="checkbox" id="autorun_recruit_high" class="autorun_user_chk btn-check" data-key="recruit_high" name="autorun_user[]" value="recruit_high" checked><label class="btn btn-secondary" for="autorun_recruit_high">모병</label> <input type="checkbox" id="autorun_recruit_high" class="autorun_user_chk btn-check" data-key="recruit_high" name="autorun_user[]" value="recruit_high"><label class="btn btn-secondary" for="autorun_recruit_high">모병</label>
<input type="checkbox" id="autorun_train" class="autorun_user_chk btn-check" data-key="train" name="autorun_user[]" value="train" checked><label class="btn btn-secondary" for="autorun_train">훈사</label> <input type="checkbox" id="autorun_train" class="autorun_user_chk btn-check" data-key="train" name="autorun_user[]" value="train"><label class="btn btn-secondary" for="autorun_train">훈사</label>
<input type="checkbox" id="autorun_battle" class="autorun_user_chk btn-check" data-key="battle" name="autorun_user[]" value="battle" checked><label class="btn btn-secondary" for="autorun_battle">출병</label> <input type="checkbox" id="autorun_battle" class="autorun_user_chk btn-check" data-key="battle" name="autorun_user[]" value="battle"><label class="btn btn-secondary" for="autorun_battle">출병</label>
<input type="checkbox" id="autorun_chief" class="autorun_user_chk btn-check" data-key="chief" name="autorun_user[]" value="chief" checked><label class="btn btn-secondary" for="autorun_chief">기본 사령턴</label> <input type="checkbox" id="autorun_chief" class="autorun_user_chk btn-check" data-key="chief" name="autorun_user[]" value="chief"><label class="btn btn-secondary" for="autorun_chief">기본 사령턴</label>
</div> </div>
</div> </div>
</div> </div>
@@ -165,7 +163,7 @@ if ($session->userGrade < 5 && !$allowReset) {
<option value="480">8시간</option> <option value="480">8시간</option>
<option value="600">10시간</option> <option value="600">10시간</option>
<option value="720">12시간</option> <option value="720">12시간</option>
<option value="1440" selected>24시간</option> <option value="1440">24시간</option>
<option value="2160">36시간</option> <option value="2160">36시간</option>
<option value="2880">48시간</option> <option value="2880">48시간</option>
<option value="3600">60시간</option> <option value="3600">60시간</option>
+4 -5
View File
@@ -7,10 +7,10 @@ include "func.php";
$session = Session::requireLogin(); $session = Session::requireLogin();
if ($session->userGrade < 6) { if ($session->userGrade < 5) {
die('관리자 아님'); die('관리자 아님');
} }
if ($session->userGrade == 6) { if ($session->userGrade == 5) {
die('DB 리셋 권한을 가지고 있지 않습니다.'); die('DB 리셋 권한을 가지고 있지 않습니다.');
} }
@@ -21,7 +21,6 @@ if ($session->userGrade == 6) {
<head> <head>
<title>설치</title> <title>설치</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?> <?= WebUtil::printJS('../d_shared/common_path.js') ?>
@@ -32,8 +31,8 @@ if ($session->userGrade == 6) {
<body> <body>
<div class="container" style="min-width:720px;"> <div class="container" style="min-width:720px;">
<h1 class="row justify-content-lg-center">삼국지 모의전투 HiDCHe 리셋</h1> <h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe 리셋</h1>
<div class="row justify-content-lg-center"> <div class="row justify-content-md-center">
<div class="col col-lg-8"> <div class="col col-lg-8">
<div class="card" id="db_form_card"> <div class="card" id="db_form_card">
+4 -7
View File
@@ -17,13 +17,10 @@ $text = Util::getPost('text');
increaseRefresh("회의실", 1); increaseRefresh("회의실", 1);
$me = $db->queryFirstRow( $me = $db->queryFirstRow('SELECT no, nation, name, officer_level, permission, con, turntime, belong, penalty, `picture`,`imgsvr` FROM general WHERE owner=%i', $userID);
'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
);
$limitState = checkLimit($me['refresh_score']); $con = checkLimit($me['con']);
if ($limitState >= 2) { if ($con >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
@@ -53,7 +50,7 @@ if($permission < 0){
'result'=>false, 'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.' 'reason'=>'국가에 소속되어있지 않습니다.'
]); ]);
} }
else if ($isSecretBoard && $permission < 2) { else if ($isSecretBoard && $permission < 2) {
Json::die([ Json::die([
+4 -7
View File
@@ -16,13 +16,10 @@ $text = Util::getPost('text');
increaseRefresh("회의실", 1); increaseRefresh("회의실", 1);
$me = $db->queryFirstRow( $me = $db->queryFirstRow('SELECT no, nation, name, officer_level, permission, con, turntime, belong, penalty FROM general WHERE owner=%i', $userID);
'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
);
$limitState = checkLimit($me['refresh_score']); $con = checkLimit($me['con']);
if ($limitState >= 2) { if ($con >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
@@ -61,7 +58,7 @@ if($permission < 0){
'result'=>false, 'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.' 'reason'=>'국가에 소속되어있지 않습니다.'
]); ]);
} }
else if ($isSecretBoard && $permission < 2) { else if ($isSecretBoard && $permission < 2) {
Json::die([ Json::die([
+5 -7
View File
@@ -16,14 +16,11 @@ $isSecretBoard = Util::getPost('isSecret', 'bool', false);
increaseRefresh("회의실", 1); increaseRefresh("회의실", 1);
$me = $db->queryFirstRow( $me = $db->queryFirstRow('SELECT no, nation, officer_level, permission, con, turntime, belong, penalty FROM general WHERE owner=%i', $userID);
'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
);
$limitState = checkLimit($me['refresh_score']); $con = checkLimit($me['con']);
if ($limitState >= 2) { if ($con >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
@@ -36,7 +33,7 @@ if($permission < 0){
'result'=>false, 'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.' 'reason'=>'국가에 소속되어있지 않습니다.'
]); ]);
} }
else if ($isSecretBoard && $permission < 2) { else if ($isSecretBoard && $permission < 2) {
Json::die([ Json::die([
@@ -75,3 +72,4 @@ Json::die([
'articles'=>$articles, 'articles'=>$articles,
'reason'=>'success' 'reason'=>'success'
]); ]);
+6 -11
View File
@@ -1,8 +1,6 @@
<?php <?php
namespace sammo; namespace sammo;
use sammo\Enums\MessageType;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
@@ -17,13 +15,10 @@ $letterNo = Util::getPost('letterNo', 'int');
increaseRefresh("외교부", 1); increaseRefresh("외교부", 1);
$me = $db->queryFirstRow( $me = $db->queryFirstRow('SELECT no, name, nation, officer_level, permission, con, turntime, belong, penalty, picture, imgsvr FROM general WHERE owner=%i', $userID);
'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
);
$limitState = checkLimit($me['refresh_score']); $con = checkLimit($me['con']);
if ($limitState >= 2) { if ($con >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
@@ -105,7 +100,7 @@ if(in_array($stateOpt, ['try_destroy_src', 'try_destroy_dest'])){
'reason'=>'파기' 'reason'=>'파기'
]; ];
} }
$msgText = "외교 서신(#{$letterNo})을 파기했습니다."; $msgText = "외교 서신 #{$letterNo} 파기했습니다.";
$lastState = 'cancelled'; $lastState = 'cancelled';
} }
else{ else{
@@ -119,12 +114,12 @@ else{
'aux'=>Json::encode($aux) 'aux'=>Json::encode($aux)
], 'no=%i', $letterNo); ], 'no=%i', $letterNo);
$msgText = "외교 서신(#{$letterNo})을 파기 요청합니다."; $msgText = "외교 서신 #{$letterNo} 파기 요청합니다.";
$lastState = 'activated'; $lastState = 'activated';
} }
$msg = new Message( $msg = new Message(
MessageType::diplomacy, Message::MSGTYPE_DIPLOMACY,
$src, $src,
$dest, $dest,
$msgText, $msgText,
+5 -7
View File
@@ -16,14 +16,11 @@ $isSecretBoard = Util::getPost('isSecret', 'bool', false);
increaseRefresh("외교부", 1); increaseRefresh("외교부", 1);
$me = $db->queryFirstRow( $me = $db->queryFirstRow('SELECT no, nation, officer_level, permission, con, turntime, belong, penalty FROM general WHERE owner=%i', $userID);
'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
);
$limitState = checkLimit($me['refresh_score']); $con = checkLimit($me['con']);
if ($limitState >= 2) { if ($con >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
@@ -36,7 +33,7 @@ if($permission < 0){
'result'=>false, 'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.' 'reason'=>'국가에 소속되어있지 않습니다.'
]); ]);
} }
$letters = []; $letters = [];
@@ -86,3 +83,4 @@ Json::die([
'myNationID'=>$me['nation'], 'myNationID'=>$me['nation'],
'reason'=>'success' 'reason'=>'success'
]); ]);
+7 -12
View File
@@ -1,8 +1,6 @@
<?php <?php
namespace sammo; namespace sammo;
use sammo\Enums\MessageType;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
@@ -22,13 +20,10 @@ $reason = Util::getPost('reason', 'string', '');
increaseRefresh("외교부", 1); increaseRefresh("외교부", 1);
$me = $db->queryFirstRow( $me = $db->queryFirstRow('SELECT no, name, nation, officer_level, permission, con, turntime, belong, penalty, picture, imgsvr FROM general WHERE owner=%i', $userID);
'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
);
$limitState = checkLimit($me['refresh_score']); $con = checkLimit($me['con']);
if ($limitState >= 2) { if ($con >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
@@ -90,7 +85,7 @@ if($isAgree){
], 'no=%i', $prevLetterNo); ], 'no=%i', $prevLetterNo);
$prevLetterNo = $db->queryFirstField('SELECT prev_no FROM ng_diplomacy WHERE state != \'cancelled\' AND no = %i', $prevLetterNo); $prevLetterNo = $db->queryFirstField('SELECT prev_no FROM ng_diplomacy WHERE state != \'cancelled\' AND no = %i', $prevLetterNo);
} }
$msgText = "외교 서신( #{$letterNo})이 승인되었습니다."; $msgText = "외교 서신 #{$letterNo} 승인되었습니다.";
} }
else{ else{
$aux['reason'] = [ $aux['reason'] = [
@@ -102,14 +97,14 @@ else{
'state'=>'cancelled', 'state'=>'cancelled',
'aux'=>Json::encode($aux) 'aux'=>Json::encode($aux)
], 'no=%i', $letterNo); ], 'no=%i', $letterNo);
$msgText = "외교 서신(#{$letterNo})이 거부되었습니다."; $msgText = "외교 서신 #{$letterNo} 거부되었습니다.";
if($reason){ if($reason){
$msgText .= ' 이유 : '.$reason; $msgText .= ' 이유 : '.$reason;
} }
} }
$msg = new Message( $msg = new Message(
MessageType::diplomacy, Message::MSGTYPE_DIPLOMACY,
$src, $src,
$dest, $dest,
$msgText, $msgText,
@@ -120,7 +115,7 @@ $msg = new Message(
$msgID = $msg->send(); $msgID = $msg->send();
$msg = new Message( $msg = new Message(
MessageType::national, Message::MSGTYPE_NATIONAL,
$src, $src,
$dest, $dest,
$msgText, $msgText,
+5 -10
View File
@@ -1,8 +1,6 @@
<?php <?php
namespace sammo; namespace sammo;
use sammo\Enums\MessageType;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
@@ -17,13 +15,10 @@ $letterNo = Util::getPost('letterNo', 'int');
increaseRefresh("외교부", 1); increaseRefresh("외교부", 1);
$me = $db->queryFirstRow( $me = $db->queryFirstRow('SELECT no, name, nation, officer_level, permission, con, turntime, belong, penalty, picture, imgsvr FROM general WHERE owner=%i', $userID);
'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
);
$limitState = checkLimit($me['refresh_score']); $con = checkLimit($me['con']);
if ($limitState >= 2) { if ($con >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
@@ -75,10 +70,10 @@ $db->update('ng_diplomacy', [
'state'=>'cancelled', 'state'=>'cancelled',
'aux'=>Json::encode($aux) 'aux'=>Json::encode($aux)
], 'no=%i', $letterNo); ], 'no=%i', $letterNo);
$msgText = "외교 서신(#{$letterNo})이 회수되었습니다."; $msgText = "외교 서신 #{$letterNo} 회수되었습니다.";
$msg = new Message( $msg = new Message(
MessageType::diplomacy, Message::MSGTYPE_DIPLOMACY,
$src, $src,
$dest, $dest,
$msgText, $msgText,
+4 -9
View File
@@ -1,8 +1,6 @@
<?php <?php
namespace sammo; namespace sammo;
use sammo\Enums\MessageType;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
@@ -24,13 +22,10 @@ if($prevNo < 1){
$prevNo = null; $prevNo = null;
} }
$me = $db->queryFirstRow( $me = $db->queryFirstRow('SELECT no, name, nation, officer_level, permission, con, turntime, belong, penalty, picture, imgsvr FROM general WHERE owner=%i', $userID);
'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
);
$limitState = checkLimit($me['refresh_score']); $con = checkLimit($me['con']);
if ($limitState >= 2) { if ($con >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
@@ -181,7 +176,7 @@ else{
$msg = new Message( $msg = new Message(
MessageType::diplomacy, Message::MSGTYPE_DIPLOMACY,
$src, $src,
$dest, $dest,
$msgText, $msgText,
+4 -7
View File
@@ -33,15 +33,12 @@ if($generalID <= 0 || $reqTo <= 0){
$db = DB::db(); $db = DB::db();
$me = $db->queryFirstRow( $me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,permission,penalty from general where owner=%i', $userID);
'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']; $nationID = $me['nation'];
$limitState = checkLimit($me['refresh_score']); $con = checkLimit($me['con']);
if ($limitState >= 2) { if ($con >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
@@ -64,7 +61,7 @@ if($generalID !== $targetID){
'reason'=>'권한이 부족합니다. 수뇌부가 아니거나 사관년도가 부족합니다.' 'reason'=>'권한이 부족합니다. 수뇌부가 아니거나 사관년도가 부족합니다.'
]); ]);
} }
if($testGeneralNationID !== $nationID){ if($testGeneralNationID !== $nationID){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
+1 -1
View File
@@ -18,7 +18,7 @@ else{
$availableNextCall = $session->availableNextCallGetCityList??'2000-01-01 00:00:00'; $availableNextCall = $session->availableNextCallGetCityList??'2000-01-01 00:00:00';
$now = new \DateTimeImmutable(); $now = new \DateTimeImmutable();
if($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 6){ if($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>"도시 목록은 10초에 한번 갱신 가능합니다.\n다음 시간 : ".$availableNextCall 'reason'=>"도시 목록은 10초에 한번 갱신 가능합니다.\n다음 시간 : ".$availableNextCall
+15 -23
View File
@@ -109,7 +109,7 @@ $scenario = (int)$_POST['scenario'];
$fiction = (int)$_POST['fiction']; $fiction = (int)$_POST['fiction'];
$extend = (int)$_POST['extend']; $extend = (int)$_POST['extend'];
$npcmode = (int)$_POST['npcmode']; $npcmode = (int)$_POST['npcmode'];
$block_general_create = (int)$_POST['block_general_create']; $block_general_create = (bool)$_POST['block_general_create'];
$show_img_level = (int)$_POST['show_img_level']; $show_img_level = (int)$_POST['show_img_level'];
$tournament_trig = !!(int)$_POST['tournament_trig']; $tournament_trig = !!(int)$_POST['tournament_trig'];
$join_mode = $_POST['join_mode']; $join_mode = $_POST['join_mode'];
@@ -199,25 +199,17 @@ if($reserve_open){
]); ]);
} }
try{ Json::die(ResetHelper::buildScenario(
Json::die(ResetHelper::buildScenario( $turnterm,
$turnterm, $sync,
$sync, $scenario,
$scenario, $fiction,
$fiction, $extend,
$extend, $block_general_create,
$block_general_create, $npcmode,
$npcmode, $show_img_level,
$show_img_level, !!$tournament_trig,
!!$tournament_trig, $join_mode,
$join_mode, TimeUtil::now(),
TimeUtil::now(), $autorun_user
$autorun_user ));
));
}
catch(\Exception $e){
Json::die([
'result'=>false,
'reason'=>$e->getMessage()
]);
}
+14 -29
View File
@@ -53,17 +53,22 @@ if($fullReset){
} }
} }
$db = new \MeekroDB($host,$username,$password,$dbName,$port,'utf8mb4'); function dbConnFail($params){
$db->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$db->addHook('run_failed', function(){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'DB 접속에 실패했습니다.' 'reason'=>'DB 접속에 실패했습니다.'
]); ]);
}); }
$mysqli_obj = $db->get();
$db = new \MeekroDB($host,$username,$password,$dbName,$port,'utf8mb4');
$db->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$db->throw_exception_on_nonsql_error = false;
$db->nonsql_error_handler = 'dbConnFail';
$mysqli_obj = $db->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
$prefix = basename(__DIR__); $prefix = basename(__DIR__);
@@ -79,6 +84,8 @@ $result = Util::generateFileUsingSimpleTemplate(
], true ], true
); );
if($result !== true){ if($result !== true){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
@@ -86,29 +93,7 @@ if($result !== true){
]); ]);
} }
//최소한의 테이블 처리를 위해 수동으로 초기화하도록 하자 ResetHelper::clearDB();
if($mysqli_obj->multi_query(file_get_contents(__DIR__.'/sql/reset.sql'))){
while(true){
if (!$mysqli_obj->more_results()) {
break;
}
if(!$mysqli_obj->next_result()){
break;
}
}
}
if($mysqli_obj->multi_query(file_get_contents(__DIR__.'/sql/schema.sql'))){
while(true){
if (!$mysqli_obj->more_results()) {
break;
}
if(!$mysqli_obj->next_result()){
break;
}
}
}
ServConfig::getServerList()[$prefix]->closeServer(); ServConfig::getServerList()[$prefix]->closeServer();
+1 -9
View File
@@ -19,15 +19,7 @@ if(!prepareDir('data/file_cache')){
]); ]);
} }
$absolutePath = realpath('data/file_cache'); $storage = new \Nette\Caching\Storages\FileStorage('data/file_cache');
if(!$absolutePath){
Json::die([
'result'=>false,
'reason'=>'cache 불가'
]);
}
$storage = new \Nette\Caching\Storages\FileStorage($absolutePath);
$cache = new Cache($storage); $cache = new Cache($storage);
$serverID = UniqueConst::$serverID; $serverID = UniqueConst::$serverID;
+19
View File
@@ -0,0 +1,19 @@
<?php
namespace sammo;
include('lib.php');
include('func.php');
$session = Session::requireGameLogin([])->setReadOnly();
if(!Session::getInstance()->generalID){
Json::die([
"nation"=>[]
]);
}
//NOTE: 모든 국가, 모든 장수에 대해서 같은 결과라면 캐싱 가능하지 않을까?
Json::die([
"nation"=>getMailboxList()
]);
+63
View File
@@ -0,0 +1,63 @@
<?php
namespace sammo;
include 'lib.php';
include 'func.php';
WebUtil::requireAJAX();
//{msgID: 1206, response: true}
$session = Session::requireGameLogin([])->setReadOnly();
$generalID = Session::getInstance()->generalID;
if (!$generalID) {
Json::die([
'result'=>false,
'reason'=>'로그인하지 않음'
]);
}
$jsonPost = Json::decode(Util::getPost('data', 'string', '{}'));
$msgID = Util::toInt($jsonPost['msgID']??null);
$msgResponse = $jsonPost['response']??null;
if ($msgID === null || !is_bool($msgResponse)) {
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 인자'
]);
}
$general = DB::db()->queryFirstRow('SELECT `no`, `name`, `nation`, `officer_level`, `npc`, `gold`, `rice`, `troop`, `aux` from `general` where `no` = %i', $generalID);
if(!$general){
Json::die([
'result'=>false,
'reason'=>'존재하지 않는 장수'
]);
}
$msg = Message::getMessageByID($msgID);
if($msg === null){
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 메시지'
]);
}
$reason = 'success';
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
$gameStor->cacheAll();
if($msgResponse){
$result = $msg->agreeMessage($general['no'], $reason);
}
else{
$result = $msg->declineMessage($general['no'], $reason);
}
Json::die([
'result' => $result!==DiplomaticMessage::INVALID,
'reason' => $reason
]);
+74
View File
@@ -0,0 +1,74 @@
<?php
namespace sammo;
include('lib.php');
include('func.php');
WebUtil::requireAJAX();
$session = Session::requireGameLogin([]);
$userID = Session::getUserID();
$msgID = Util::getPost('msgID', 'int');
if($msgID === null){
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 범위 입니다.'
]);
}
$lastMsgGet = Json::decode($session->lastMsgGet)??[];
$now = new \DateTime();
$delayTime = false;
if(count($lastMsgGet) >= 10){
try{
if($lastMsgGet[0] !== 'string'){
throw new \Exception('Why not string?');
}
$first = new \DateTime($lastMsgGet[0]);
$diff = $first->diff($now);
if($diff->days == 0 && $diff->h > 0 && $diff->i == 0 && $diff->s <= 5){
$delayTime = true;
}
array_shift($lastMsgGet);
}
catch(\Exception $e){
$lastMsgGet = [];
}
}
$lastMsgGet[] = $now;
$session->lastMsgGet = Json::encode($lastMsgGet);
if($delayTime){
sleep(1);
}
$session->setReadOnly();
list($generalID, $nationID, $generalName) = DB::db()->queryFirstList(
'select `no`, `nation`, `name` from `general` where owner = %i',
$userID
);
if($nationID === null){
Json::die([
'result'=>false,
'reason'=>'장수가 사망했습니다.'
]);
}
$reason = Message::deleteMsg($msgID, $generalID);
if($reason === null){
$result = [
'result'=>true,
'reason'=>'success'
];
}
else{
$result = [
'result'=>false,
'reason'=>$reason
];
}
Json::die($result);
+118
View File
@@ -0,0 +1,118 @@
<?php
namespace sammo;
include('lib.php');
include('func.php');
$session = Session::requireGameLogin([]);
$userID = Session::getUserID();
$reqTo = Util::getPost('to', 'int');
$reqType = Util::getPost('type', 'string');
if($reqTo === null){
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 범위 입니다.'
]);
}
if($reqType === null || !in_array($reqType, ['private', 'public', 'national', 'diplomacy'])){
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 타입입니다.'
]);
}
$lastMsgGet = Json::decode($session->lastMsgGet)??[];
$now = new \DateTime();
$delayTime = false;
if(count($lastMsgGet) >= 10){
try{
if($lastMsgGet[0] !== 'string'){
throw new \Exception('Why not string?');
}
$first = new \DateTime($lastMsgGet[0]);
$diff = $first->diff($now);
if($diff->days == 0 && $diff->h > 0 && $diff->i == 0 && $diff->s <= 1){
$delayTime = true;
}
array_shift($lastMsgGet);
}
catch(\Exception $e){
$lastMsgGet = [];
}
}
$lastMsgGet[] = $now;
$session->lastMsgGet = Json::encode($lastMsgGet);
if($delayTime){
sleep(1);
}
$session->setReadOnly();
$me = DB::db()->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,penalty,permission FROM general WHERE `owner`=%i', $userID);
if($me === null){
Json::die([
'result'=>false,
'reason'=>'장수가 사망했습니다.'
]);
}
[$generalID, $nationID, $generalName] = [$me['no'], $me['nation'], $me['name']];
$permission = checkSecretPermission($me, false);
$result = [
'private'=>[],
'public'=>[],
'national'=>[],
'diplomacy'=>[],
'result'=>true,
'keepRecent'=>true,
'sequence'=>0,
'nationID'=>$nationID,
'generalName'=>$generalName,
];
$result['result'] = true;
$nextSequence = $reqTo;
if($reqType == 'private'){
$result['private'] = array_map(function(Message $msg) use (&$nextSequence){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
return $msg->toArray();
}, Message::getMessagesFromMailBoxOld($generalID, Message::MSGTYPE_PRIVATE, $reqTo, 15));
}
else if($reqType == 'public'){
$result['public'] = array_map(function(Message $msg)use (&$nextSequence){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
return $msg->toArray();
}, Message::getMessagesFromMailBoxOld(Message::MAILBOX_PUBLIC, Message::MSGTYPE_PUBLIC, $reqTo, 15));
}
else if($reqType == 'national'){
$result['national'] = array_map(function(Message $msg)use (&$nextSequence){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
return $msg->toArray();
}, Message::getMessagesFromMailBoxOld(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_NATIONAL, $reqTo, 15));
}
else{
$result['diplomacy'] = array_map(function(Message $msg)use (&$nextSequence, $permission){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
$values = $msg->toArray();
if($msg->dest->nationID != 0 && $permission < 3){
$values['text'] = '(외교 메시지입니다)';//TODO: 외교서신이라 읽을 수 없음을 보여줘야함
$values['option']['invalid'] = true;
}
return $values;
}, Message::getMessagesFromMailBoxOld(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_DIPLOMACY, $reqTo, 15));
}
Json::die($result);
+120
View File
@@ -0,0 +1,120 @@
<?php
namespace sammo;
include('lib.php');
include('func.php');
$session = Session::requireGameLogin([]);
$userID = Session::getUserID();
$reqSequence = Util::getPost('sequence', 'int', -1);
$lastMsgGet = Json::decode($session->lastMsgGet)??[];
$now = new \DateTime();
$delayTime = false;
if(count($lastMsgGet) >= 10){
try{
if(!is_string($lastMsgGet[0])){
throw new \Exception('Why not string?');
}
$first = new \DateTime($lastMsgGet[0]);
$diff = $first->diff($now);
if($diff->days == 0 && $diff->h > 0 && $diff->i == 0 && $diff->s <= 1){
$delayTime = true;
}
array_shift($lastMsgGet);
}
catch(\Exception $e){
$lastMsgGet = [];
}
}
$lastMsgGet[] = TimeUtil::now();
$session->lastMsgGet = Json::encode($lastMsgGet);
if($delayTime){
usleep(200);
}
$session->setReadOnly();
$db = DB::db();
$me = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,penalty,permission FROM general WHERE `owner`=%i', $userID);
if($me === null){
Json::die([
'result'=>false,
'reason'=>'장수가 사망했습니다.'
]);
}
[$generalID, $nationID, $generalName] = [$me['no'], $me['nation'], $me['name']];
$permission = checkSecretPermission($me, false);
$result = [];
$result['result'] = true;
$result['keepRecent'] = false;
$nextSequence = $reqSequence;
$minSequence = $reqSequence;
$lastType = null;
$result['private'] = array_map(function(Message $msg) use (&$nextSequence, &$minSequence, &$lastType){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
if($msg->id <= $minSequence){
$minSequence = $msg->id;
$lastType = 'private';
}
return $msg->toArray();
}, Message::getMessagesFromMailBox($generalID, Message::MSGTYPE_PRIVATE, 15, $reqSequence));
$result['public'] = array_map(function(Message $msg)use (&$nextSequence, &$minSequence, &$lastType){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
if($msg->id <= $minSequence){
$minSequence = $msg->id;
$lastType = 'public';
}
return $msg->toArray();
}, Message::getMessagesFromMailBox(Message::MAILBOX_PUBLIC, Message::MSGTYPE_PUBLIC, 15, $reqSequence));
$result['national'] = array_map(function(Message $msg)use (&$nextSequence, &$minSequence, &$lastType){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
if($msg->id <= $minSequence){
$minSequence = $msg->id;
$lastType = 'national';
}
return $msg->toArray();
}, Message::getMessagesFromMailBox(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_NATIONAL, 15, $reqSequence));
$result['diplomacy']= array_map(function(Message $msg)use (&$nextSequence, &$minSequence, &$lastType, $permission){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
if($msg->id <= $minSequence){
$minSequence = $msg->id;
$lastType = 'diplomacy';
}
$values = $msg->toArray();
if($msg->dest->nationID != 0 && $permission < 3){
$values['text'] = '(외교 메시지입니다)';//TODO: 외교서신이라 읽을 수 없음을 보여줘야함
$values['option']['invalid'] = true;
}
return $values;
}, Message::getMessagesFromMailBox(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_DIPLOMACY, 15, $reqSequence));
if($lastType !== null){
array_pop($result[$lastType]);
$result['keepRecent'] = true;
}
else if($reqSequence <= 0){
$result['keepRecent'] = true;
}
$result['sequence'] = $nextSequence;
$result['nationID'] = $nationID;
$result['generalName'] = $generalName;
Json::die($result);
+206
View File
@@ -0,0 +1,206 @@
<?php
namespace sammo;
include 'lib.php';
include 'func.php';
WebUtil::requireAJAX();
$post = Json::decode(Util::getPost('data', 'string', '{}'));
'@phan-var mixed[] $post';
$v = new Validator($post);
$v->rule('required', ['mailbox','text']);
$v->rule('integer', 'mailbox');
$v->rule('lengthMin', 'text', 1);
if(!$v->validate()){
Json::die([
'result'=>false,
'reason'=>$v->errorStr(),
'msgID'=>null
]);
}
$mailbox = (int)$post['mailbox'];
$text = trim(StringUtil::cutStringForWidth($post['text'], 199, ''));
$session = Session::requireGameLogin([
'msgID'=>null
]);
$userID = Session::getUserID();
//NOTE: 전송 메시지 시간 계산을 위해 Session을 쓰기 가능 상태로 열어둠.
increaseRefresh('서신전달', 1);
if(getBlockLevel() == 1 || getBlockLevel() == 3) {
Json::die([
'result' => false,
'reason' => '차단되었습니다.',
'msgID'=>null
]);
}
/**
* 메시지 전송 코드.
*
* TODO: 장기적으로 ajax는 한곳에 모을 필요가 있을 듯.
*/
$now = new \DateTime();
$unlimited = new \DateTime('9999-12-31');
$db = DB::db();
$me = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,penalty,permission,belong FROM general WHERE `owner`=%i', $userID);
if(!$me){
$session->logoutGame();
Json::die([
'result' => false,
'reason' => '로그인되지 않았습니다.',
'msgID' => null
]);
}
$con = checkLimit($me['con']);
if($con >= 2) {
Json::die([
'result' => false,
'reason' => '접속 제한입니다.',
'msgID' => null
]);
}
$me['icon'] = GetImageURL($me['imgsvr'], $me['picture']);
$permission = checkSecretPermission($me);
$srcNation = getNationStaticInfo($me['nation']);
$src = new MessageTarget($me['no'], $me['name'], $srcNation['nation'], $srcNation['name'], $srcNation['color'], $me['icon']);
// 전체 메세지
if($mailbox == Message::MAILBOX_PUBLIC) {
$msg = new Message(
Message::MSGTYPE_PUBLIC,
$src,
$src,
$text,
$now,
$unlimited,
[]
);
$msgID = $msg->send();
Json::die([
'result' => true,
'reason' => 'SUCCESS',
'msgID' => $msgID
]);
}
// 국가 메세지
if($mailbox >= Message::MAILBOX_NATIONAL) {
if($permission < 4){
$destNationID = $me['nation'];
}
else{
$destNationID = $mailbox - Message::MAILBOX_NATIONAL;
}
if($destNationID == $me['nation']){
$msgType = Message::MSGTYPE_NATIONAL;
}
else{
$msgType = Message::MSGTYPE_DIPLOMACY;
}
$destNation = getNationStaticInfo($destNationID);
$dest = new MessageTarget(0, '', $destNation['nation'], $destNation['name'], $destNation['color']);
$msg = new Message(
$msgType,
$src,
$dest,
$text,
$now,
$unlimited,
[]
);
$msgID = $msg->send();
Json::die([
'result' => true,
'reason' => 'SUCCESS',
'msgID' => $msgID
]);
}
// 개인 메세지
if($mailbox > 0) {
$lastMsg = new \DateTime($session->lastMsg??'0000-00-00');
$msg_interval = $now->getTimestamp() - $lastMsg->getTimestamp();
//NOTE: 여기서 유저 레벨을 구별할 코드가 필요할까?
if($msg_interval < 2){
Json::die([
'result' => false,
'reason' => '개인메세지는 2초당 1건만 보낼 수 있습니다!',
'msgID' => null
]);
}
$session->lastMsg = $now->format('Y-m-d H:i:s');
$destUser = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,permission,penalty FROM general WHERE `no`=%i',$mailbox);
if(!$destUser){
Json::die([
'result' => false,
'reason' => '존재하지 않는 유저입니다.',
'msgID' => null
]);
}
$destPermission = checkSecretPermission($destUser, false);
if($permission == 4 && $destPermission == 4 && $destUser['nation'] != $me['nation']){
Json::die([
'result' => false,
'reason' => '외교권자끼리는 메시지를 보낼 수 없습니다.',
'msgID' => null
]);
}
$destNation = getNationStaticInfo($destUser['nation']);
$dest = new MessageTarget(
$destUser['no'],
$destUser['name'],
$destNation['nation'],
$destNation['name'],
$destNation['color'],
GetImageURL($destUser['imgsvr'], $destUser['picture'])
);
$msg = new Message(
Message::MSGTYPE_PRIVATE,
$src,
$dest,
$text,
$now,
$unlimited,
[]
);
$msgID = $msg->send();
Json::die([
'result' => true,
'reason' => 'SUCCESS',
'msgID' => $msgID
]);
}
Json::die([
'result' => false,
'reason' => '알 수 없는 에러',
'msgID' => null
]);
+105 -135
View File
@@ -1,13 +1,6 @@
<?php <?php
namespace sammo; namespace sammo;
use sammo\Enums\GeneralColumn;
use sammo\Enums\GeneralLiteQueryMode;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\MessageType;
use sammo\Enums\PenaltyKey;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
@@ -24,99 +17,97 @@ $userID = Session::getUserID();
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['startyear', 'year', 'month', 'scenario', 'killturn']); $gameStor->cacheValues(['startyear','year','month','scenario']);
$me = $db->queryFirstRow('SELECT no,npc,nation,officer_level,penalty from general where owner=%i', $userID); $me = $db->queryFirstRow('SELECT no,nation,officer_level from general where owner=%i', $userID);
$myOfficerLevel = $me['officer_level']; $myOfficerLevel = $me['officer_level'];
$nationID = $me['nation']; $nationID = $me['nation'];
$myPenalty = Json::decode($me['penalty'] ?? '{}');
//수뇌가 아니면 아무것도 할 수 없음 //수뇌가 아니면 아무것도 할 수 없음
if ($myOfficerLevel < 5) { if($myOfficerLevel < 5){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => '수뇌가 아닙니다.' 'reason'=>'수뇌가 아닙니다.'
]); ]);
} }
if ($action === '추방' && $destGeneralID == 0) { if($action === '추방' && $destGeneralID==0){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => '장수가 지정되지 않았습니다.' 'reason'=>'장수가 지정되지 않았습니다.'
]); ]);
} }
if ($destGeneralID == 0) { if($destGeneralID==0){
$general = new DummyGeneral(true); $general = new DummyGeneral(true);
$general->setVar('nation', $nationID); $general->setVar('nation', $nationID);
} else { }
$general = General::createObjFromDB($destGeneralID); else{
$general = General::createGeneralObjFromDB($destGeneralID, [
'name', 'leadership', 'strength', 'intel', 'gold','rice',
'troop','officer_level','npc','picture','imgsvr',
'permission','penalty','belong', 'crewtype',
'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit', 'aux',
], 1);
if ($general instanceof DummyGeneral) { if($general instanceof DummyGeneral){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => '올바르지 않은 장수입니다.' 'reason'=>'올바르지 않은 장수입니다.'
]); ]);
} }
if ($nationID != $general->getNationID()) { if($nationID != $general->getNationID()){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => '아국 장수가 아닙니다' 'reason'=>'아국 장수가 아닙니다'
]); ]);
} }
} }
if ($officerLevel == 12) { if($officerLevel == 12){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => '군주를 대상으로 할 수 없습니다.' 'reason'=>'군주를 대상으로 할 수 없습니다.'
]); ]);
} }
function do수뇌임명(General $general, int $targetOfficerLevel): ?string function do수뇌임명(General $general, int $targetOfficerLevel):?string{
{
global $myPenalty;
if ($myPenalty[PenaltyKey::NoChiefChange->value] ?? false) {
return '수뇌를 임명할 수 없는 상태입니다.';
}
$generalID = $general->getID(); $generalID = $general->getID();
$nationID = $general->getNationID(); $nationID = $general->getNationID();
if($general->hasPenalty(PenaltyKey::NoChief)){
return '수뇌가 될 수 없는 상태입니다.';
}
$db = DB::db(); $db = DB::db();
[$chiefSet, $nationLevel] = $db->queryFirstList('SELECT chief_set,level FROM nation WHERE nation = %i', $nationID); [$chiefSet, $nationLevel] = $db->queryFirstList('SELECT chief_set,level FROM nation WHERE nation = %i',$nationID);
// 임명가능 레벨 // 임명가능 레벨
$lv = getNationChiefLevel($nationLevel); $lv = getNationChiefLevel($nationLevel);
if ($targetOfficerLevel < $lv) { if($targetOfficerLevel < $lv){
return '임명불가능한 관직입니다.'; return '임명불가능한 관직입니다.';
} }
if (isOfficerSet($chiefSet, $targetOfficerLevel)) { if(isOfficerSet($chiefSet, $targetOfficerLevel)){
return '지금은 임명할 수 없습니다.'; return '지금은 임명할 수 없습니다.';
} }
//기존 장수 일반으로 //기존 장수 일반으로
$db->update('general', [ $db->update('general', [
'officer_level' => 1, 'officer_level'=>1,
'officer_city' => 0, 'officer_city'=>0,
], 'nation=%i AND officer_level=%i AND no!=%i', $nationID, $targetOfficerLevel, $generalID); ], 'nation=%i AND officer_level=%i AND no!=%i', $nationID, $targetOfficerLevel, $generalID);
if ($targetOfficerLevel === 11) { if($targetOfficerLevel === 11){
} else if ($targetOfficerLevel % 2 == 0) {
if ($general->getVar('strength') < GameConst::$chiefStatMin) { }
else if($targetOfficerLevel % 2 == 0){
if($general->getVar('strength') < GameConst::$chiefStatMin){
return '무력이 부족합니다.'; return '무력이 부족합니다.';
} }
} else {
if ($general->getVar('intel') < GameConst::$chiefStatMin) { }
else{
if($general->getVar('intel') < GameConst::$chiefStatMin){
return '지력이 부족합니다.'; return '지력이 부족합니다.';
} }
} }
@@ -125,59 +116,52 @@ function do수뇌임명(General $general, int $targetOfficerLevel): ?string
$general->setVar('officer_level', $targetOfficerLevel); $general->setVar('officer_level', $targetOfficerLevel);
$general->setVar('officer_city', 0); $general->setVar('officer_city', 0);
$db->update('nation', [ $db->update('nation', [
'chief_set' => $db->sqleval('chief_set | %i', doOfficerSet(0, $targetOfficerLevel)), 'chief_set'=> $db->sqleval('chief_set | %i', doOfficerSet(0, $targetOfficerLevel)),
], 'nation=%i', $nationID); ], 'nation=%i', $nationID);
$general->applyDB($db); $general->applyDB($db);
return null; return null;
} }
function do도시임명(General $general, int $cityID, int $targetOfficerLevel): ?string function do도시임명(General $general, int $cityID, int $targetOfficerLevel):?string{
{
global $myPenalty;
$nationID = $general->getNationID(); $nationID = $general->getNationID();
$db = DB::db(); $db = DB::db();
if (CityConst::byID($cityID) === null) { if(CityConst::byID($cityID) === null){
return '올바르지 않은 도시입니다'; return '올바르지 않은 도시입니다';
} }
if ($general->getVar(GeneralColumn::officer_level) >= 4 && $myPenalty[PenaltyKey::NoChiefChange->value] ?? false) {
return '수뇌인 장수를 변경할 수 없는 상태입니다.';
}
$officerSet = $db->queryFirstField('SELECT officer_set FROM city WHERE nation=%i AND city=%i', $nationID, $cityID); $officerSet = $db->queryFirstField('SELECT officer_set FROM city WHERE nation=%i AND city=%i', $nationID, $cityID);
if ($officerSet === null) { if($officerSet === null){
return '아국 도시가 아닙니다'; return '아국 도시가 아닙니다';
} }
if (isOfficerSet($officerSet, $targetOfficerLevel)) { if(isOfficerSet($officerSet, $targetOfficerLevel)){
return '이미 다른 장수가 임명되어있습니다'; return '이미 다른 장수가 임명되어있습니다';
} }
//기존 장수 일반으로 //기존 장수 일반으로
$db->update('general', [ $db->update('general', [
'officer_level' => 1, 'officer_level'=>1,
'officer_city' => 0, 'officer_city'=>0,
], 'officer_level=%i AND officer_city=%i AND no!=%i', $targetOfficerLevel, $cityID, $general->getID()); ], 'officer_level=%i AND officer_city=%i AND no!=%i', $targetOfficerLevel, $cityID, $general->getID());
if ($general instanceof DummyGeneral) { if($general instanceof DummyGeneral){
return null; return null;
} }
if ($targetOfficerLevel === 4 && $general->getVar('strength') < GameConst::$chiefStatMin) { if($targetOfficerLevel === 4 && $general->getVar('strength') < GameConst::$chiefStatMin){
return '무력이 부족합니다.'; return '무력이 부족합니다.';
} }
if ($targetOfficerLevel === 3 && $general->getVar('intel') < GameConst::$chiefStatMin) { if($targetOfficerLevel === 3 && $general->getVar('intel') < GameConst::$chiefStatMin){
return '지력이 부족합니다.'; return '지력이 부족합니다.';
} }
//신임 장수 //신임 장수
$db->update('city', [ $db->update('city', [
'officer_set' => $db->sqleval('officer_set | %i', doOfficerSet(0, $targetOfficerLevel)), 'officer_set'=>$db->sqleval('officer_set | %i', doOfficerSet(0, $targetOfficerLevel)),
], 'city=%i AND nation=%i', $cityID, $nationID); ], 'city=%i AND nation=%i', $cityID, $nationID);
$general->setVar('officer_level', $targetOfficerLevel); $general->setVar('officer_level', $targetOfficerLevel);
$general->setVar('officer_city', $cityID); $general->setVar('officer_city', $cityID);
@@ -186,25 +170,22 @@ function do도시임명(General $general, int $cityID, int $targetOfficerLevel):
return null; return null;
} }
function do추방(General $general, int $myOfficerLevel): ?string function do추방(General $general, int $myOfficerLevel):?string{
{
$generalID = $general->getID(); $generalID = $general->getID();
$generalName = $general->getVar('name'); $generalName = $general->getVar('name');
$nationID = $general->getNationID(); $nationID = $general->getNationID();
if ($myPenalty[PenaltyKey::NoBanGeneral->value] ?? false) {
return '추방할 수 없는 상태입니다.';
}
//추방할사람이 외교권자이면 불가 //추방할사람이 외교권자이면 불가
$permission = checkSecretPermission($general->getRaw()); $permission = checkSecretPermission($general->getRaw());
if ($permission == 4) { if($permission == 4){
return '외교권자는 추방할 수 없습니다.'; return '외교권자는 추방할 수 없습니다.';
} }
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getValues(['startyear', 'year', 'month', 'scenario']); $env = $gameStor->getValues(['startyear','year','month','scenario']);
$nation = $db->queryFirstRow('SELECT name,chief_set,color FROM nation WHERE nation=%i', $nationID); $nation = $db->queryFirstRow('SELECT name,chief_set,color FROM nation WHERE nation=%i', $nationID);
$nationName = $nation['name']; $nationName = $nation['name'];
@@ -212,17 +193,17 @@ function do추방(General $general, int $myOfficerLevel): ?string
$logger = $general->getLogger(); $logger = $general->getLogger();
//이미 지정했다면 무시 //이미 지정했다면 무시
if (isOfficerSet($nation['chief_set'], $myOfficerLevel) || ($myOfficerLevel == 0 && $myOfficerLevel == 12)) { if(isOfficerSet($nation['chief_set'], $myOfficerLevel) || ($myOfficerLevel == 0 && $myOfficerLevel == 12)) {
return '이미 추방 권한을 사용했습니다.'; return '이미 추방 권한을 사용했습니다.';
} }
$gold = 0; $gold = 0;
$rice = 0; $rice = 0;
// 금쌀1000이상은 남김 // 금쌀1000이상은 남김
if ($general->getVar('gold') > GameConst::$defaultGold) { if($general->getVar('gold') > GameConst::$defaultGold) {
$gold = $general->getVar('gold') - GameConst::$defaultGold; $gold = $general->getVar('gold') - GameConst::$defaultGold;
$general->setVar('gold', GameConst::$defaultGold); $general->setVar('gold', GameConst::$defaultGold);
} }
if ($general->getVar('rice') > GameConst::$defaultRice) { if($general->getVar('rice') > GameConst::$defaultRice) {
$rice = $general->getVar('rice') - GameConst::$defaultRice; $rice = $general->getVar('rice') - GameConst::$defaultRice;
$general->setVar('rice', GameConst::$defaultRice); $general->setVar('rice', GameConst::$defaultRice);
} }
@@ -240,26 +221,27 @@ function do추방(General $general, int $myOfficerLevel): ?string
$logger->pushGeneralActionLog("<D><b>{$nationName}</b></>에서 <R>추방</>당했습니다.", ActionLogger::PLAIN); $logger->pushGeneralActionLog("<D><b>{$nationName}</b></>에서 <R>추방</>당했습니다.", ActionLogger::PLAIN);
// 명성/공헌 N*10%감소 // 명성/공헌 N*10%감소
if ($env['year'] <= $env['startyear'] && $general->getNPCType() < 2) { if($env['year'] <= $env['startyear'] && $general->getNPCType() < 2){
$general->setVar('makelimit', $oldMakeLimit); $general->setVar('makelimit', $oldMakeLimit);
} else { }
else{
$betrayCnt = $general->getVar('betray'); $betrayCnt = $general->getVar('betray');
$general->addExperience(-$general->getVar('experience') * 0.15 * $betrayCnt); $general->addExperience(-$general->getVar('experience')*0.1*$betrayCnt);
$general->addDedication(-$general->getVar('dedication') * 0.15 * $betrayCnt); $general->addDedication(-$general->getVar('dedication')*0.1*$betrayCnt);
$general->increaseVarWithLimit('betray', 1, null, GameConst::$maxBetrayCnt); $general->increaseVarWithLimit('betray', 1, null, GameConst::$maxBetrayCnt);
} }
//부대장일 경우 //부대장일 경우
if ($general->getVar('troop') == $generalID) { if($general->getVar('troop') == $generalID){
// 모두 탈퇴 // 모두 탈퇴
$db->update('general', [ $db->update('general', [
'troop' => 0, 'troop'=>0,
], 'troop = %i', $generalID); ], 'troop = %i', $generalID);
$db->delete('troop', 'troop_leader=%i', $generalID); $db->delete('troop', 'troop_leader=%i', $generalID);
} }
$general->setVar('troop', 0); $general->setVar('troop', 0);
if ($general->getNPCType() >= 2) { if($general->getNPCType() >= 2){
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize( $rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed, UniqueConst::$hiddenSeed,
'BanNPC', 'BanNPC',
@@ -286,7 +268,7 @@ function do추방(General $general, int $myOfficerLevel): ?string
GetImageURL($general->getVar('imgsvr'), $general->getVar('picture')) GetImageURL($general->getVar('imgsvr'), $general->getVar('picture'))
); );
$msg = new Message( $msg = new Message(
MessageType::public, Message::MSGTYPE_PUBLIC,
$src, $src,
$src, $src,
$str, $str,
@@ -298,24 +280,24 @@ function do추방(General $general, int $myOfficerLevel): ?string
} }
} }
if ($env['year'] < $env['startyear'] + 3) { if($env['year'] < $env['startyear']+3) {
//초반엔 군주 부상 증가(엔장 임관지양) //초반엔 군주 부상 증가(엔장 임관지양)
$db->update('general', [ $db->update('general', [
'injury' => $db->sqleval('least(injury + 1, %i)', 80), 'injury'=>$db->sqleval('least(injury + 1, %i)', 80),
], 'nation=%i AND officer_level=12', $nationID); ], 'nation=%i AND officer_level=12', $nationID);
$db->update('nation', [ $db->update('nation', [
'gennum' => $db->sqleval('gennum - %i', $general->getNPCType() != 5 ? 1 : 0), 'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0),
'gold' => $db->sqleval('gold + %i', $gold), 'gold'=>$db->sqleval('gold + %i', $gold),
'rice' => $db->sqleval('rice + %i', $rice), 'rice'=>$db->sqleval('rice + %i', $rice),
], 'nation = %i', $nationID); ], 'nation = %i', $nationID);
} else { } else {
//이번분기는 추방불가(초반 제외) //이번분기는 추방불가(초반 제외)
$db->update('nation', [ $db->update('nation', [
'chief_set' => $db->sqleval('chief_set | %i', doOfficerSet(0, $myOfficerLevel)), 'chief_set'=>$db->sqleval('chief_set | %i', doOfficerSet(0, $myOfficerLevel)),
'gennum' => $db->sqleval('gennum - %i', $general->getNPCType() != 5 ? 1 : 0), 'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0),
'gold' => $db->sqleval('gold + %i', $gold), 'gold'=>$db->sqleval('gold + %i', $gold),
'rice' => $db->sqleval('rice + %i', $rice), 'rice'=>$db->sqleval('rice + %i', $rice),
], 'nation = %i', $nationID); ], 'nation = %i', $nationID);
} }
@@ -327,74 +309,62 @@ function do추방(General $general, int $myOfficerLevel): ?string
if ($action == "임명") { if($action == "임명") {
if (2 <= $officerLevel && $officerLevel <= 4) { if(2 <= $officerLevel && $officerLevel <= 4){
if (!$destCityID) { if(!$destCityID){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => '도시가 지정되지 않았습니다.' 'reason'=>'도시가 지정되지 않았습니다.'
]); ]);
} }
$result = do도시임명($general, $destCityID, $officerLevel); $result = do도시임명($general, $destCityID, $officerLevel);
if ($result !== null) { if($result !== null){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => $result 'reason'=>$result
]); ]);
} }
//수뇌의 삭턴 리필
$db->update('general', [
'killturn' => $db->sqleval('GREATEST(%b, %i)', 'killturn', $gameStor->getValue('killturn')),
], 'no=%i', $me['no']);
Json::die([ Json::die([
'result' => true, 'result'=>true,
'reason' => 'success' 'reason'=>'success'
]); ]);
} }
if (5 <= $officerLevel && $officerLevel < 12) { if(5 <= $officerLevel && $officerLevel < 12){
$result = do수뇌임명($general, $officerLevel); $result = do수뇌임명($general, $officerLevel);
if ($result !== null) { if($result !== null){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => $result 'reason'=>$result
]); ]);
} }
//수뇌의 삭턴 리필
$db->update('general', [
'killturn' => $db->sqleval('GREATEST(%b, %i)', 'killturn', $gameStor->getValue('killturn')),
], 'no=%i', $me['no']);
Json::die([ Json::die([
'result' => true, 'result'=>true,
'reason' => 'success' 'reason'=>'success'
]); ]);
} }
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => '올바르지 않은 지정입니다.' 'reason'=>'올바르지 않은 지정입니다.'
]); ]);
} }
if ($action == "추방") { if($action == "추방") {
$result = do추방($general, $myOfficerLevel); $result = do추방($general, $myOfficerLevel);
if ($result !== null) { if($result !== null){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => $result 'reason'=>$result
]); ]);
} }
//수뇌의 삭턴 리필
$db->update('general', [
'killturn' => $db->sqleval('GREATEST(%b, %i)', 'killturn', $gameStor->getValue('killturn')),
], 'no=%i', $me['no']);
Json::die([ Json::die([
'result' => true, 'result'=>true,
'reason' => 'success' 'reason'=>'success'
]); ]);
} }
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => '올바르지 않은 명령입니다.' 'reason'=>'올바르지 않은 명령입니다.'
]); ]);
+1 -1
View File
@@ -8,7 +8,7 @@ include('func.php');
$session = Session::requireLogin([])->setReadOnly(); $session = Session::requireLogin([])->setReadOnly();
if(Session::getInstance()->userGrade < 6){ if(Session::getInstance()->userGrade < 5){
Json::die([ Json::die([
'reason'=>'권한이 부족합니다.' 'reason'=>'권한이 부족합니다.'
]); ]);
+3 -22
View File
@@ -1,8 +1,6 @@
<?php <?php
namespace sammo; namespace sammo;
use sammo\Enums\GeneralAccessLogColumn;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
@@ -27,25 +25,14 @@ $rootDB = RootDB::db();
$oNow = new \DateTimeImmutable(); $oNow = new \DateTimeImmutable();
$now = $oNow->format('Y-m-d H:i:s'); $now = $oNow->format('Y-m-d H:i:s');
$member = $rootDB->queryFirstRow('SELECT `name`, `penalty` FROM member WHERE `NO`=%i', $userID); $userNick = RootDB::db()->queryFirstField('SELECT `NAME` FROM member WHERE `NO`=%i',$userID);
if(!$member){ if(!$userNick){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'멤버 정보를 가져오지 못했습니다.' 'reason'=>'멤버 정보를 가져오지 못했습니다.'
]); ]);
} }
$userNick = $member['name'];
$memberPenalty = Json::decode($member['penalty'] ?? '{}');
$penaltyInfo = array_merge($memberPenalty['any'] ?? [], $memberPenalty[DB::prefix()] ?? []);
$penalty = [];
foreach($penaltyInfo as $penaltyKey => $penaltyValue){
if($penaltyValue['expire'] ?? 0 > TimeUtil::now()){
$penalty[$penaltyKey] = $penaltyValue['value'];
}
}
$pickResult = $db->queryFirstField('SELECT pick_result FROM select_npc_token WHERE `owner`=%i AND `valid_until`>=%s', $userID, $now); $pickResult = $db->queryFirstField('SELECT pick_result FROM select_npc_token WHERE `owner`=%i AND `valid_until`>=%s', $userID, $now);
if(!$pickResult){ if(!$pickResult){
Json::die([ Json::die([
@@ -97,14 +84,8 @@ $db->update('general', [
'defence_train'=>80, 'defence_train'=>80,
'permission'=>'normal', 'permission'=>'normal',
'owner'=>$userID, 'owner'=>$userID,
'aux'=>Json::encode($genAux), 'aux'=>Json::encode($genAux)
'penalty'=>Json::encode($penalty),
], 'owner <= 0 AND npc = 2 AND no = %i', $pick); ], 'owner <= 0 AND npc = 2 AND no = %i', $pick);
$db->insertIgnore('general_access_log', [
GeneralAccessLogColumn::generalID->value => $pick,
GeneralAccessLogColumn::userID->value => $userID,
GeneralAccessLogColumn::lastRefresh->value => $now,
]);
if(!$db->affectedRows()){ if(!$db->affectedRows()){
Json::die([ Json::die([
+2 -2
View File
@@ -56,7 +56,7 @@ if(file_exists(__DIR__.'/.htaccess')){
'scenarioName'=>$options['scenarioName'], 'scenarioName'=>$options['scenarioName'],
'turnterm'=>$options['turnterm'], 'turnterm'=>$options['turnterm'],
'fictionMode'=>($options['fiction']?'가상':'사실'), 'fictionMode'=>($options['fiction']?'가상':'사실'),
'block_general_create'=>Util::toInt($options['block_general_create']), 'block_general_create'=>(!!$options['block_general_create']),
'npcMode'=>([0=>'불가',1=>'가능',2=>'선택 생성'][$options['npcmode']]), 'npcMode'=>([0=>'불가',1=>'가능',2=>'선택 생성'][$options['npcmode']]),
'openDatetime'=>$reserved['date'], 'openDatetime'=>$reserved['date'],
'starttime'=>$options['starttime'], 'starttime'=>$options['starttime'],
@@ -90,7 +90,7 @@ $admin['scenario'] = $admin['scenario_text'];
$admin['userCnt'] = $genCnt; $admin['userCnt'] = $genCnt;
$admin['npcCnt'] = $npcCnt; $admin['npcCnt'] = $npcCnt;
$admin['nationCnt'] = $nationCnt; $admin['nationCnt'] = $nationCnt;
$admin['block_general_create'] = $admin['block_general_create']; $admin['block_general_create'] = !!$admin['block_general_create'];
$admin['npcMode'] = [0=>'불가',1=>'가능',2=>'선택 생성'][$admin['npcMode']]; $admin['npcMode'] = [0=>'불가',1=>'가능',2=>'선택 생성'][$admin['npcMode']];
$admin['fictionMode'] = $admin['fiction']?'가상':'사실'; $admin['fictionMode'] = $admin['fiction']?'가상':'사실';
+18 -44
View File
@@ -1,5 +1,4 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
@@ -25,31 +24,29 @@ if ($defence_train <= 40) {
$defence_train = 40; $defence_train = 40;
} }
if ($defence_train <= 90) { if($defence_train <= 90){
$defence_train = Util::round($defence_train, -1); $defence_train = Util::round($defence_train, -1);
} else { }
else{
$defence_train = 999; $defence_train = 999;
} }
if ($tnmt < 0 || $tnmt > 1) { if($tnmt < 0 || $tnmt > 1){
$tnmt = 1; $tnmt = 1;
} }
$db = DB::db(); $db = DB::db();
$me = General::createObjFromDB($generalID); $me = General::createGeneralObjFromDB($generalID);
if ($defence_train !== $me->getVar('defence_train')) { if($defence_train !== $me->getVar('defence_train')){
if ($defence_train == 999) { if($defence_train == 999){
$me->increaseVar('myset', -1); $me->increaseVar('myset', -1);
$me->setVar('defence_train', $defence_train); $me->setVar('defence_train', $defence_train);
$affectedTrain = -3; $me->increaseVarWithLimit('train', -3, 20);
$affectedAtmos = -6; $me->increaseVarWithLimit('atmos', -3, 20);
$affectedTrain = $me->onCalcDomestic('changeDefenceTrain', "train{$defence_train}", $affectedTrain); }
$affectedAtmos = $me->onCalcDomestic('changeDefenceTrain', "atmos{$defence_train}", $affectedAtmos); else{
$me->increaseVarWithLimit('train', $affectedTrain, 20, GameConst::$maxTrainByWar);
$me->increaseVarWithLimit('atmos', $affectedAtmos, 20, GameConst::$maxAtmosByWar);
} else {
$me->increaseVar('myset', -1); $me->increaseVar('myset', -1);
$me->setVar('defence_train', $defence_train); $me->setVar('defence_train', $defence_train);
} }
@@ -59,44 +56,21 @@ $me->setAuxVar('use_treatment', Util::valueFit($use_treatment, 10, 100));
$me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn); $me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn);
$me->setVar('tnmt', $tnmt); $me->setVar('tnmt', $tnmt);
if ($me->getNPCType() == 1 && $detachNPC) { if($me->getNPCType() == 1 && $detachNPC){
$turnterm = $gameStor->turnterm; $turnterm = $gameStor->turnterm;
if ($turnterm < 10) { if($turnterm < 10){
$targetKillTurn = 30 / $turnterm; $targetKillTurn = 30 / $turnterm;
} else { }
else{
$targetKillTurn = 60 / $turnterm; $targetKillTurn = 60 / $turnterm;
} }
$me->setVar('killturn', $targetKillTurn); $me->setVar('killturn', $targetKillTurn);
} }
$rootDB = RootDB::db();
//회원 테이블에서 정보확인
$member = $rootDB->queryFirstRow('SELECT `no`, id, picture, grade, `name`, imgsvr, `penalty` FROM member WHERE no=%i', $userID);
if (!$member) {
//이런 경우가 있나?
//TODO: 로그 남겨둘 것
Json::die([
'result' => false,
'reason' => '회원 정보를 찾을 수 없습니다.'
]);
}
$memberPenalty = Json::decode($member['penalty'] ?? "{}");
$penaltyInfo = array_merge($memberPenalty['any'] ?? [], $memberPenalty[DB::prefix()] ?? []);
$penalty = [];
foreach ($penaltyInfo as $penaltyKey => $penaltyValue) {
if ($penaltyValue['expire'] ?? 0 > TimeUtil::now()) {
$penalty[$penaltyKey] = $penaltyValue['value'];
}
}
$me->setVar('penalty', Json::encode($penalty));
$me->applyDB($db); $me->applyDB($db);
Json::die([ Json::die([
'result' => true, 'result'=>true,
'reason' => 'success' 'reason'=>'success'
]); ]);
+2 -5
View File
@@ -39,10 +39,7 @@ if (!$data || !is_array($data)) {
$db = DB::db(); $db = DB::db();
$me = $db->queryFirstRow( $me = $db->queryFirstRow('SELECT no, name, npc, nation, city, officer_level, con, turntime, belong, permission, penalty FROM general WHERE owner=%i', $userID);
'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']; $nationID = $me['nation'];
@@ -85,7 +82,7 @@ function applyNationPolicy($policy, $nationID, $generalName): ?string
return "{$troopID}는 국가의 부대가 아닙니다."; return "{$troopID}는 국가의 부대가 아닙니다.";
} }
if ($troopCache[$troopID] != 'Neutral') { if ($troopCache[$troopID] != 'Neutral') {
return "부대({$troopID})는 하나의 역할만 지정할 수 있습니다."; return "부대({$troopID}는 하나의 역할만 지정할 수 있습니다.";
} }
if (!is_array($troopTarget) || count($troopTarget) != 2) { if (!is_array($troopTarget) || count($troopTarget) != 2) {
return "{$troopID}의 입력양식이 올바르지 않습니다."; return "{$troopID}의 입력양식이 올바르지 않습니다.";
+209 -313
View File
@@ -1,5 +1,4 @@
<?php <?php
namespace sammo; namespace sammo;
use Ds\Map; use Ds\Map;
@@ -16,48 +15,48 @@ $userID = Session::getUserID();
increaseRefresh("시뮬레이터", 0); increaseRefresh("시뮬레이터", 0);
$query = Util::getPost('query'); $query = Util::getPost('query');
if ($query === null) { if($query === null){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => '입력값이 없습니다.' 'reason'=>'입력값이 없습니다.'
]); ]);
} }
$action = Util::getPost('action'); $action = Util::getPost('action');
if ($action === null || !in_array($action, ['reorder', 'battle'])) { if($action === null || !in_array($action, ['reorder', 'battle'])){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => '원하는 동작이 지정되지 않았습니다.' 'reason'=>'원하는 동작이 지정되지 않았습니다.'
]); ]);
} }
$query = Json::decode($query); $query = Json::decode($query);
if ($query === null) { if($query === null){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => '올바르지 않은 JSON입니다.' 'reason'=>'올바르지 않은 JSON입니다.'
]); ]);
} }
$defaultCheck = [ $defaultCheck = [
'required' => [ 'required'=>[
'attackerGeneral', 'attackerCity', 'attackerNation', 'attackerGeneral', 'attackerCity', 'attackerNation',
'defenderGenerals', 'defenderCity', 'defenderNation', 'defenderGenerals', 'defenderCity', 'defenderNation',
'year', 'month', 'repeatCnt' 'year', 'month', 'repeatCnt'
], ],
'integer' => [ 'integer'=>[
'year', 'month', 'repeatCnt' 'year','month','repeatCnt'
], ],
'between' => [ 'between'=>[
['month', [1, 12]] ['month', [1, 12]]
], ],
'in' => [ 'in'=>[
['repeatCnt', [1, 1000]] ['repeatCnt', [1, 1000]]
], ],
'min' => [ 'min'=>[
['year', 0] ['year', 0]
], ],
'array' => [ 'array'=>[
'attackerGeneral', 'attackerCity', 'attackerNation', 'attackerGeneral', 'attackerCity', 'attackerNation',
'defenderGenerals', 'defenderCity', 'defenderNation' 'defenderGenerals', 'defenderCity', 'defenderNation'
], ],
@@ -65,10 +64,10 @@ $defaultCheck = [
$v = new Validator($query); $v = new Validator($query);
$v->rules($defaultCheck); $v->rules($defaultCheck);
if (!$v->validate()) { if(!$v->validate()){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => $v->errorStr() 'reason'=>$v->errorStr()
]); ]);
} }
@@ -85,112 +84,21 @@ $rawDefenderList = $query['defenderGenerals'];
$rawDefenderCity = $query['defenderCity']; $rawDefenderCity = $query['defenderCity'];
$rawDefenderNation = $query['defenderNation']; $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 = [ $generalCheck = [
'required' => [ 'required'=>[
'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train', 'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train',
'intel', 'intel_exp', 'book', 'strength', 'strength_exp', 'weapon', 'injury', 'leadership', 'leadership_exp', 'horse', 'item', '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', 'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
'recent_war', 'warnum', 'killnum', 'killcrew', 'recent_war', 'warnum', 'killnum', 'killcrew',
], ],
'integer' => [ 'integer'=>[
'no', 'nation', 'crew', 'crewtype', 'atmos', 'train', 'no', 'nation', 'crew', 'crewtype', 'atmos', 'train',
'intel', 'intel_exp', 'strength', 'strength_exp', 'injury', 'leadership', 'leadership_exp', 'intel', 'intel_exp', 'strength', 'strength_exp', 'injury', 'leadership', 'leadership_exp',
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
'warnum', 'killnum', 'killcrew', 'warnum', 'killnum', 'killcrew',
], ],
'min' => [ 'min'=>[
['no', 1], ['no', 1],
['nation', 1], ['nation', 1],
['crew', 0], ['crew', 0],
@@ -209,14 +117,14 @@ $generalCheck = [
['killnum', 0], ['killnum', 0],
['killcrew', 0], ['killcrew', 0],
], ],
'between' => [ 'between'=>[
['train', [40, GameConst::$maxTrainByWar]], ['train', [40, GameConst::$maxTrainByWar]],
['atmos', [40, GameConst::$maxAtmosByWar]], ['atmos', [40, GameConst::$maxAtmosByWar]],
['explevel', [0, 300]], ['explevel', [0, 300]],
['injury', [0, 80]], ['injury', [0, 80]],
['officer_level', [1, 12]] ['officer_level', [1, 12]]
], ],
'in' => [ 'in'=>[
['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)], ['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)],
['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)], ['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)],
['crewtype', array_keys(GameUnitConst::all())], ['crewtype', array_keys(GameUnitConst::all())],
@@ -224,138 +132,162 @@ $generalCheck = [
['weapon', array_merge(array_keys(GameConst::$allItems['weapon']), ['None'])], ['weapon', array_merge(array_keys(GameConst::$allItems['weapon']), ['None'])],
['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])], ['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])],
['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])], ['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])],
],
'array' => ['inheritBuff'],
];
$inheritBuffCheck = [
'between' => [
[TriggerInheritBuff::WAR_AVOID_RATIO, [0, 5]],
[TriggerInheritBuff::WAR_CRITICAL_RATIO, [0, 5]],
[TriggerInheritBuff::WAR_MAGIC_TRIAL_PROB, [0, 5]],
[TriggerInheritBuff::OPPOSE_WAR_AVOID_RATIO, [0, 5]],
[TriggerInheritBuff::OPPOSE_WAR_CRITICAL_RATIO, [0, 5]],
[TriggerInheritBuff::OPPOSE_WAR_MAGIC_TRIAL_PROB, [0, 5]],
] ]
]; ];
if(!$warSeed){
$warSeed = bin2hex(random_bytes(16));
}
else {
$repeatCnt = 1;
}
$tmpRNG = new RandUtil(new LiteHashDRBG($warSeed));
$v = new Validator($rawAttacker); $v = new Validator($rawAttacker);
$v->rules($generalCheck); $v->rules($generalCheck);
if (!$v->validate()) { if(!$v->validate()){
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => '[출병자]' . $v->errorStr() 'reason'=>'[출병자]'.$v->errorStr()
]); ]);
} }
$rawAttacker['aux'] = [];
if (key_exists('inheritBuff', $rawAttacker)) {
$v = new Validator($rawAttacker['inheritBuff']);
$v->rules($inheritBuffCheck);
if (!$v->validate()) {
Json::die([
'result' => false,
'reason' => '[출병자]' . $v->errorStr()
]);
}
$rawAttacker['aux']['inheritBuff'] = $rawAttacker['inheritBuff'];
}
$rawAttacker['aux'] = Json::encode($rawAttacker['aux']);
$rawAttacker['owner'] = 0; $rawAttacker['owner'] = 0;
$attackerGeneral = new General($rawAttacker, extractRankVar($rawAttacker), null, $rawAttackerCity, $rawAttackerNation, $year, $month);
$attacker = new WarUnitGeneral(
$tmpRNG,
$attackerGeneral,
$rawAttackerNation,
true
);
/** @var WarUnit[] */
$defenderList = []; $defenderList = [];
foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
foreach ($rawDefenderList as $idx => $rawDefenderGeneral) {
$v = new Validator($rawDefenderGeneral); $v = new Validator($rawDefenderGeneral);
$v->rules($generalCheck); $v->rules($generalCheck);
if (!$v->validate()) { if(!$v->validate()){
$idx += 1; $idx+=1;
Json::die([ Json::die([
'result' => false, 'result'=>false,
'reason' => "[수비자{$idx}]" . $v->errorStr() 'reason'=>"[수비자{$idx}]".$v->errorStr()
]); ]);
} }
$rawDefenderGeneral['aux'] = [];
if (key_exists('inheritBuff', $rawDefenderGeneral)) {
$v = new Validator($rawDefenderGeneral['inheritBuff']);
$v->rules($inheritBuffCheck);
if (!$v->validate()) {
$idx += 1;
Json::die([
'result' => false,
'reason' => "[수비자{$idx}]" . $v->errorStr()
]);
}
$rawDefenderGeneral['aux']['inheritBuff'] = $rawDefenderGeneral['inheritBuff'];
}
$rawDefenderGeneral['aux'] = Json::encode($rawDefenderGeneral['aux']);
$rawDefenderGeneral['owner'] = 0; $rawDefenderGeneral['owner'] = 0;
$defenderGeneral = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), null, $rawDefenderCity, $rawAttackerNation, $year, $month, true); $defenderList[] = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), $rawDefenderCity, $rawAttackerNation, $year, $month, true);
$defenderList[] = new WarUnitGeneral(
$tmpRNG,
$defenderGeneral,
$rawDefenderNation,
false
);
} }
if ($action == 'reorder') {
$noRng = NoRNG::rngInstance();
usort($defenderList, function (WarUnit $lhs, WarUnit $rhs) use ($attacker) { $cityCheck = [
return - (extractBattleOrder($lhs, $attacker) <=> extractBattleOrder($rhs, $attacker)); '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));
}); });
$order = []; $order = [];
foreach ($defenderList as $defender) { foreach($defenderList as $defenderGeneral){
$order[] = $defender->getGeneral()->getID(); $order[] = $defenderGeneral->getID();
} }
Json::die([ Json::die([
'result' => true, 'result'=>true,
'reason' => 'success', 'reason'=>'success',
'order' => $order 'order'=>$order
]); ]);
} }
$rawDefenderList = []; usort($defenderList, function(General $lhs, General $rhs){
foreach($defenderList as $unit){ return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
if(extractBattleOrder($unit, $attacker) <= 0){ });
continue;
} $rawDefenderList = array_map(function(General $general){
$rawDefenderList[] = $unit->getRaw(); return $general->getRaw();
} }, $defenderList);
unset($defenderList); unset($defenderList);
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$startYear = $gameStor->startyear; $startYear = $gameStor->startyear;
$cityRate = Util::round(($year - $startYear) / 1.5) + 60;
function extractRankVar(array $rawVal): Map function extractRankVar(array $rawVal):Map{
{
$rankVars = new Map; $rankVars = new Map;
foreach ($rawVal as $rawKey => $rawVal) { foreach($rawVal as $rawKey=>$rawVal){
$key = RankColumn::tryFrom($rawKey); $key = RankColumn::tryFrom($rawKey);
if ($key === null) { if($key === null){
continue; continue;
} }
$rankVars[$key] = $rawVal; $rankVars[$key] = $rawVal;
@@ -364,113 +296,86 @@ function extractRankVar(array $rawVal): Map
} }
function simulateBattle( function simulateBattle(
$rawAttacker, $rawAttacker, $rawAttackerCity, $rawAttackerNation,
$rawAttackerCity, $rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$rawAttackerNation, $startYear, $year, $month, $cityRate
$rawDefenderList, ){
$rawDefenderCity,
$rawDefenderNation,
$startYear,
$year,
$month,
$warSeed
) {
if (!$warSeed) {
$warSeed = bin2hex(random_bytes(16));
}
$warSeed = bin2hex(random_bytes(16));
$warRng = new RandUtil(new LiteHashDRBG($warSeed)); $warRng = new RandUtil(new LiteHashDRBG($warSeed));
$attackerGeneral = new General($rawAttacker, extractRankVar($rawAttacker), null, $rawAttackerCity, $rawAttackerNation, $year, $month);
$attacker = new WarUnitGeneral( $attacker = new WarUnitGeneral(
$warRng, $warRng,
$attackerGeneral, new General($rawAttacker, extractRankVar($rawAttacker), $rawAttackerCity, $rawAttackerNation, $year, $month),
$rawAttackerNation, $rawAttackerNation,
true true
); );
$city = new WarUnitCity($warRng, $rawDefenderCity, $rawDefenderNation, $year, $month, $startYear); $city = new WarUnitCity($warRng, $rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
/** @var WarUnit[] */ $iterDefender = new \ArrayIterator($rawDefenderList);
$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(); $iterDefender->rewind();
$battleResult = []; $battleResult = [];
$attackerRice = $attacker->getGeneral()->getVar('rice'); $attackerRice = $rawAttacker['rice'];
$defenderRice = 0; $defenderRice = 0;
$getNextDefender = function (?WarUnit $prevDefender, bool $reqNext) $getNextDefender = function(?WarUnit $prevDefender, bool $reqNext)
use ($iterDefender, &$battleResult, &$defenderRice, $attacker): ?WarUnit { use ($warRng, $iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) {
if ($prevDefender !== null) { if($prevDefender !== null){
$prevDefender->getLogger()->rollback(); $prevDefender->getLogger()->rollback();
$battleResult[] = $prevDefender; $battleResult[] = $prevDefender;
if ($prevDefender instanceof WarUnitGeneral) { if($prevDefender instanceof WarUnitGeneral){
$defenderRice -= $prevDefender->getVar('rice'); $defenderRice -= $prevDefender->getVar('rice');
} }
} }
if (!$reqNext) { if(!$reqNext){
return null; return null;
} }
if (!$iterDefender->valid()) { if(!$iterDefender->valid()){
return null; return null;
} }
/** @var WarUnit */ $defenderObj = new General($iterDefender->current(), extractRankVar($iterDefender->current()), $rawDefenderCity, $rawDefenderNation, $year, $month);
$defender = $iterDefender->current(); if(extractBattleOrder($defenderObj) <= 0){
if (extractBattleOrder($defender, $attacker) <= 0) {
return null; return null;
} }
if($defender instanceof WarUnitGeneral){ $defenderRice += $defenderObj->getVar('rice');
$defenderRice += $defender->getVar('rice');
}
$retVal = new WarUnitGeneral(
$warRng,
$defenderObj,
$rawDefenderNation,
false
);
$iterDefender->next(); $iterDefender->next();
return $defender; return $retVal;
}; };
$conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city); $conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city, $year - $startYear);
$rawDefenderCity = $city->getRaw();
$updateAttackerNation = [];
$updateDefenderNation = [];
$attackerRice -= $attacker->getVar('rice'); $attackerRice -= $attacker->getVar('rice');
if ($city->getPhase() > 0) { if($city->getPhase() > 0){
$rice = $city->getKilled() / 100 * 0.8; $rice = $city->getKilled() / 100 * 0.8;
$rice *= $city->getCrewType()->rice; $rice *= $city->getCrewType()->rice;
$rice *= getTechCost($city->getRawNation()['tech']); $rice *= getTechCost($rawDefenderNation['tech']);
$rice *= $city->getCityTrainAtmos() / 100 - 0.2; $rice *= $cityRate / 100 - 0.2;
Util::setRound($rice); Util::setRound($rice);
$defenderRice += $rice; $defenderRice += $rice;
} }
$totalDead = $attacker->getKilled() + $attacker->getDead(); $totalDead = $attacker->getKilled() + $attacker->getDead();
//$attackerCityDead = $totalDead * 0.4; $attackerCityDead = $totalDead * 0.4;
//$defenderCityDead = $totalDead * 0.6; $defenderCityDead = $totalDead * 0.6;
return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice]; return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice];
} }
@@ -496,26 +401,14 @@ $avgWar = 0;
$attackerActivatedSkills = []; $attackerActivatedSkills = [];
$defendersActivatedSkills = []; $defendersActivatedSkills = [];
foreach(Util::range($repeatCnt) as $repeatIdx){
foreach (Util::range($repeatCnt) as $repeatIdx) {
if($repeatIdx > 0){
$warSeed = bin2hex(random_bytes(16));
}
/** @var WarUnit $attacker */ /** @var WarUnit $attacker */
[$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle( [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle(
$rawAttacker, $rawAttacker, $rawAttackerCity, $rawAttackerNation,
$rawAttackerCity, $rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$rawAttackerNation, $startYear, $year, $month, $cityRate
$rawDefenderList,
$rawDefenderCity,
$rawDefenderNation,
$startYear,
$year,
$month,
$warSeed
); );
$lastWarLog = Util::mapWithKey(function ($key, $values) { $lastWarLog = Util::mapWithKey(function($key, $values){
return ConvertLog(join('<br>', $values)); return ConvertLog(join('<br>', $values));
}, $attacker->getLogger()->rollback()); }, $attacker->getLogger()->rollback());
@@ -538,45 +431,48 @@ foreach (Util::range($repeatCnt) as $repeatIdx) {
$avgWar += count($battleResult) / $repeatCnt; $avgWar += count($battleResult) / $repeatCnt;
foreach ($attacker->getActivatedSkillLog() as $skillName => $skillCnt) { foreach($attacker->getActivatedSkillLog() as $skillName => $skillCnt){
if (!key_exists($skillName, $attackerActivatedSkills)) { if(!key_exists($skillName, $attackerActivatedSkills)){
$attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt; $attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt;
} else { }
else{
$attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt; $attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt;
} }
} }
foreach ($battleResult as $idx => $defender) { foreach($battleResult as $idx=>$defender){
while ($idx >= count($defendersActivatedSkills)) { while($idx >= count($defendersActivatedSkills)){
$defendersActivatedSkills[] = []; $defendersActivatedSkills[] = [];
} }
$activatedSkills = &$defendersActivatedSkills[$idx]; $activatedSkills = &$defendersActivatedSkills[$idx];
foreach ($defender->getActivatedSkillLog() as $skillName => $skillCnt) { foreach($defender->getActivatedSkillLog() as $skillName => $skillCnt){
if (!key_exists($skillName, $activatedSkills)) { if(!key_exists($skillName, $activatedSkills)){
$activatedSkills[$skillName] = $skillCnt / $repeatCnt; $activatedSkills[$skillName] = $skillCnt / $repeatCnt;
} else { }
else{
$activatedSkills[$skillName] += $skillCnt / $repeatCnt; $activatedSkills[$skillName] += $skillCnt / $repeatCnt;
} }
} }
} }
} }
Json::die([ Json::die([
'result' => true, 'result'=>true,
'datetime' => $rawAttacker['turntime'], 'datetime'=>$rawAttacker['turntime'],
'reason' => 'success', 'reason'=>'success',
'lastWarLog' => $lastWarLog, 'lastWarLog'=>$lastWarLog,
'avgWar' => $avgWar, 'avgWar'=>$avgWar,
'phase' => $avgPhase, 'phase'=>$avgPhase,
'killed' => $attackerKilled, 'killed'=>$attackerKilled,
'maxKilled' => $attackerMaxKilled, 'maxKilled'=>$attackerMaxKilled,
'minKilled' => $attackerMinKilled, 'minKilled'=>$attackerMinKilled,
'dead' => $attackerDead, 'dead'=>$attackerDead,
'maxDead' => $attackerMaxDead, 'maxDead'=>$attackerMaxDead,
'minDead' => $attackerMinDead, 'minDead'=>$attackerMinDead,
'attackerRice' => $attackerAvgRice, 'attackerRice'=>$attackerAvgRice,
'defenderRice' => $defenderAvgRice, 'defenderRice'=>$defenderAvgRice,
'attackerSkills' => $attackerActivatedSkills, 'attackerSkills'=>$attackerActivatedSkills,
'defendersSkills' => $defendersActivatedSkills, 'defendersSkills'=>$defendersActivatedSkills,
]); ]);
+146
View File
@@ -0,0 +1,146 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
// $btn, $name, $troop
$action = Util::getPost('action');
$name = Util::getPost('name');
$gen = Util::getPost('gen', 'int');
$troop = Util::getPost('troop', 'int');
//로그인 검사
$session = Session::requireGameLogin([])->setReadOnly();
$userID = $session::getUserID();
increaseRefresh("부대명령", 0);
$db = DB::db();
$me = $db->queryFirstRow('SELECT `no`, name, nation, troop FROM general WHERE `owner`=%i', $userID);
$generalID = $me['no'];
$nationID = $me['nation'];
if($action == '부대창설'){
$name = StringUtil::neutralize($name);
if(!$name){
Json::die([
'result'=>false,
'reason'=>'부대 이름이 없습니다.'
]);
}
if($me['troop'] != 0){
Json::die([
'result'=>false,
'reason'=>'이미 부대에 가입해있습니다.'
]);
}
$db->insert('troop',[
'troop_leader'=>$generalID,
'name'=>$name,
'nation'=>$nationID,
]);
$db->update('general', [
'troop'=>$generalID,
], 'no=%i',$generalID);
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
if($action == '부대추방'){
if (!$gen){
Json::die([
'result'=>false,
'reason'=>'장수를 지정해야 합니다.'
]);
}
$db->update('general', [
'troop'=>0
], 'no=%i AND troop = %i', $gen, $generalID);
if($db->affectedRows() == 0){
Json::die([
'result'=>false,
'reason'=>'부대장이 아니거나, 장수를 잘못 지정했습니다.'
]);
}
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
if ($action == '부대가입') {
if(!$troop){
Json::die([
'result'=>false,
'reason'=>'부대를 지정해야 합니다.'
]);
}
if($me['troop'] === $generalID){
Json::die([
'result'=>false,
'reason'=>'부대장입니다.'
]);
}
$troopExists = $db->queryFirstField('SELECT `troop_leader` FROM `troop` WHERE `troop_leader` = %i AND `nation` = %i', $troop, $nationID);
if (!$troopExists) {
Json::die([
'result'=>false,
'reason'=>'올바른 부대장이 아닙니다.'
]);
}
$db->update('general', [
'troop'=>$troop
], 'no=%i', $generalID);
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
if($action == "부대탈퇴") {
if($me['troop'] == 0){
Json::die([
'result'=>false,
'reason'=>'부대에 속해있지 않습니다.'
]);
}
//부대장일 경우
if($me['troop'] === $generalID){
$db->update('general', [
'troop'=>0
], 'troop=%i',$generalID);
$db->delete('troop', 'troop_leader=%i', $generalID);
}
else{
$db->update('general', [
'troop'=>0
], 'no=%i', $generalID);
}
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 명령입니다.'
]);
+1 -1
View File
@@ -66,7 +66,7 @@ if(!$ownerInfo){
$info = Json::decode($info); $info = Json::decode($info);
$generalObj = General::createObjFromDB($generalID); $generalObj = General::createGeneralObjFromDB($generalID);
$oldGeneralName = $generalObj->getName(); $oldGeneralName = $generalObj->getName();
$db->update('select_pool', [ $db->update('select_pool', [
'general_id'=>-$generalID, 'general_id'=>-$generalID,
-22
View File
@@ -1,22 +0,0 @@
function getCityPosition(){
return {"1":["서량",127,101],"2":["무도",127,222],"3":["성도",127,344],"4":["건녕",127,384],"5":["안정",167,141],"6":["한중",167,222],"7":["검각",167,263],"8":["자동",167,303],"9":["강주",167,344],"10":["장안",208,182],"11":["영안",208,384],"12":["홍농",248,182],"13":["완",248,222],"14":["양양",248,303],"15":["강릉",248,344],"16":["무릉",248,384],"17":["영릉",248,425],"18":["낙양",289,182],"19":["신야",289,263],"20":["강하",289,344],"21":["장사",289,384],"22":["계양",289,425],"23":["남해",289,465],"24":["업",329,101],"25":["진유",329,141],"26":["허창",329,182],"27":["여남",329,222],"28":["시상",329,344],"29":["평원",370,60],"30":["복양",370,101],"31":["초",370,141],"32":["수춘",370,222],"33":["단양",370,263],"34":["여강",370,303],"35":["계",410,20],"36":["남피",410,60],"37":["소패",410,141],"38":["건업",410,222],"39":["북평",451,20],"40":["북해",451,101],"41":["하비",451,141],"42":["광릉",451,182],"43":["오",451,263],"44":["회계",451,303],"45":["양평",491,20],"46":["국내",532,20],"47":["한",532,60],"48":["사비",532,101],"49":["매소",572,60],"50":["서라벌",572,101],"51":["운남",127,425],"52":["천수",127,182],"53":["졸본",572,20]};
}
function formatCityInfo(city) {
var regionMap = {"하북":1,"1":"하북","중원":2,"2":"중원","서북":3,"3":"서북","서촉":4,"4":"서촉","남중":5,"5":"남중","초":6,"6":"초","오월":7,"7":"오월","동이":8,"8":"동이"};
var levelMap = {"수":1,"1":"수","진":2,"2":"진","관":3,"3":"관","이":4,"4":"이","소":5,"5":"소","중":6,"6":"중","대":7,"7":"대","특":8,"8":"특"};
var region_str = regionMap[city.region];
var level_str = levelMap[city.level];
city.text = '【' + region_str + '|' + level_str + '】' + city.name;
city.region_str = region_str;
city.level_str = level_str;
return city;
}
+2 -5
View File
@@ -9,9 +9,6 @@ $loader->addClassMap((function () {
$d_settingMap = []; $d_settingMap = [];
foreach (glob(__DIR__.'/d_setting/*.orig.php') as $filepath) { foreach (glob(__DIR__.'/d_setting/*.orig.php') as $filepath) {
$filepath = str_replace('.orig.php', '.php', $filepath); $filepath = str_replace('.orig.php', '.php', $filepath);
if(!file_exists($filepath)) {
continue;
}
$filename = basename($filepath); $filename = basename($filepath);
$classname = explode('.', $filename)[0]; $classname = explode('.', $filename)[0];
$d_settingMap['sammo\\'.$classname] = $filepath; $d_settingMap['sammo\\'.$classname] = $filepath;
@@ -66,8 +63,8 @@ function prepareDir(string $dirPath, bool $forceCreate=true):bool{
if(!unlink($dirPath)){ if(!unlink($dirPath)){
return false; return false;
} }
return mkdir($dirPath, 0775); return mkdir($dirPath);
} }
return mkdir($dirPath, 0775, true); return mkdir($dirPath, 0777, true);
} }
+83 -106
View File
@@ -2,8 +2,6 @@
namespace sammo; namespace sammo;
use sammo\Enums\EventTarget;
use sammo\Enums\GeneralQueryMode;
function processWar(string $warSeed, General $attackerGeneral, array $rawAttackerNation, array $rawDefenderCity) function processWar(string $warSeed, General $attackerGeneral, array $rawAttackerNation, array $rawDefenderCity)
{ {
@@ -31,39 +29,23 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
} }
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
[$startYear, $year, $month, $joinMode] = $gameStor->getValuesAsArray(['startyear', 'year', 'month', 'join_mode']); [$startYear, $year, $month, $cityRate, $joinMode] = $gameStor->getValuesAsArray(['startyear', 'year', 'month', 'city_rate', 'join_mode']);
$attacker = new WarUnitGeneral($rng, $attackerGeneral,$rawAttackerNation, true); $attacker = new WarUnitGeneral($rng, $attackerGeneral,$rawAttackerNation, true);
$city = new WarUnitCity($rng, $rawDefenderCity, $rawDefenderNation, $year, $month, $startYear); $city = new WarUnitCity($rng, $rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
$defenderCityGeneralIDList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND city=%i AND nation!=0', $city->getVar('nation'), $city->getVar('city')); $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'));
$defenderCityGeneralList = General::createObjListFromDB($defenderCityGeneralIDList, null); $defenderList = General::createGeneralObjListFromDB($defenderIDList, null, 2);
/** @var WarUnit[] */ usort($defenderList, function (General $lhs, General $rhs) {
$defenderList = []; return - (extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
foreach($defenderCityGeneralList 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 = new \ArrayIterator($defenderList);
$iterDefender->rewind(); $iterDefender->rewind();
$getNextDefender = function (?WarUnit $prevDefender, bool $reqNext) use ($iterDefender, $db, $attacker) { $getNextDefender = function (?WarUnit $prevDefender, bool $reqNext) use ($rng, $iterDefender, $rawDefenderNation, $rawDefenderCity, $db) {
if ($prevDefender !== null) { if ($prevDefender !== null) {
$prevDefender->applyDB($db); $prevDefender->applyDB($db);
} }
@@ -76,16 +58,24 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
return null; return null;
} }
/** @var WarUnit */
$nextDefender = $iterDefender->current(); $nextDefender = $iterDefender->current();
if (extractBattleOrder($nextDefender, $attacker) <= 0) { $nextDefender->setRawCity($rawDefenderCity);
if (extractBattleOrder($nextDefender) <= 0) {
return null; return null;
} }
$retVal = new WarUnitGeneral(
$rng,
$nextDefender,
$rawDefenderNation,
false
);
$iterDefender->next(); $iterDefender->next();
return $nextDefender; return $retVal;
}; };
$conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city); $conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city, $year - $startYear);
$attacker->applyDB($db); $attacker->applyDB($db);
@@ -100,7 +90,7 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
$rice = $city->getKilled() / 100 * 0.8; $rice = $city->getKilled() / 100 * 0.8;
$rice *= $city->getCrewType()->rice; $rice *= $city->getCrewType()->rice;
$rice *= getTechCost($rawDefenderNation['tech']); $rice *= getTechCost($rawDefenderNation['tech']);
$rice *= $city->getCityTrainAtmos() / 100 - 0.2; $rice *= $cityRate / 100 - 0.2;
Util::setRound($rice); Util::setRound($rice);
$updateDefenderNation['rice'] = max(0, $rawDefenderNation['rice'] - $rice); $updateDefenderNation['rice'] = max(0, $rawDefenderNation['rice'] - $rice);
@@ -123,8 +113,8 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
'dead' => $db->sqleval('dead + %i', $totalDead * 0.6) 'dead' => $db->sqleval('dead + %i', $totalDead * 0.6)
], 'city=%i', $rawDefenderCity['city']); ], 'city=%i', $rawDefenderCity['city']);
$attackerIncTech = buildNationTypeClass($rawAttackerNation['type'])->onCalcDomestic('기술', 'score', $attacker->getDead() * 0.012); $attackerIncTech = buildNationTypeClass($rawAttackerNation['type'])->onCalcDomestic('기술', 'score', $attacker->getDead() * 0.01);
$defenderIncTech = buildNationTypeClass($rawDefenderNation['type'])->onCalcDomestic('기술', 'score', $attacker->getKilled() * 0.009); $defenderIncTech = buildNationTypeClass($rawDefenderNation['type'])->onCalcDomestic('기술', 'score', $attacker->getKilled() * 0.01);
$attackerGenCnt = $rawAttackerNation['gennum']; $attackerGenCnt = $rawAttackerNation['gennum'];
$defenderGenCnt = $rawDefenderNation['gennum']; $defenderGenCnt = $rawDefenderNation['gennum'];
@@ -185,21 +175,13 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
'startyear' => $startYear, 'startyear' => $startYear,
'year' => $year, 'year' => $year,
'month' => $month, 'month' => $month,
'city_rate' => $cityRate,
'join_mode' => $joinMode, 'join_mode' => $joinMode,
], $attacker->getGeneral(), $city->getRaw(), $defenderCityGeneralList); ], $attacker->getGeneral(), $city->getRaw());
} }
function extractBattleOrder(WarUnit $defender, WarUnit $attacker) function extractBattleOrder(General $general)
{ {
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) { if ($general->getVar('crew') == 0) {
return 0; return 0;
} }
@@ -230,6 +212,7 @@ function processWar_NG(
WarUnitGeneral $attacker, WarUnitGeneral $attacker,
callable $getNextDefender, callable $getNextDefender,
WarUnitCity $city, WarUnitCity $city,
int $relYear
): bool { ): bool {
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
@@ -242,7 +225,6 @@ function processWar_NG(
$attackerNationUpdate = []; $attackerNationUpdate = [];
$defenderNationUpdate = []; $defenderNationUpdate = [];
/** @var WarUnit */
$defender = ($getNextDefender)(null, true); $defender = ($getNextDefender)(null, true);
$conquerCity = false; $conquerCity = false;
@@ -258,7 +240,6 @@ function processWar_NG(
$logWritten = false; $logWritten = false;
if ($defender === null) { if ($defender === null) {
$defender = $city; $defender = $city;
$defender->setSiege();
if ($city->getNationVar('rice') <= 0 && $city->getVar('supply')) { if ($city->getNationVar('rice') <= 0 && $city->getVar('supply')) {
//병량 패퇴 //병량 패퇴
@@ -425,28 +406,21 @@ function processWar_NG(
$attacker->logBattleResult(); $attacker->logBattleResult();
$defender->logBattleResult(); $defender->logBattleResult();
if (!($defender instanceof WarUnitCity) || $defender->isSiege()){ $attacker->addWin();
$attacker->addWin(); $defender->addLose();
$defender->addLose();
$attacker->tryWound(); $attacker->tryWound();
$defender->tryWound(); $defender->tryWound();
if ($defender === $city) { if ($defender === $city) {
$attacker->addLevelExp(1000); $attacker->addLevelExp(1000);
$conquerCity = true; $conquerCity = true;
break; break;
}
} }
$josaYi = JosaUtil::pick($defender->getCrewTypeName(), '이'); $josaYi = JosaUtil::pick($defender->getCrewTypeName(), '이');
if ($defender instanceof WarUnitCity && !$defender->isSiege()){ if ($noRice) {
//실제 공성을 위해 다시 초기화
$defender->setOppose(null);
}
else if ($noRice) {
$logger->pushGlobalActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다."); $logger->pushGlobalActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다.");
$attacker->getLogger()->pushGeneralActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다.", ActionLogger::PLAIN); $attacker->getLogger()->pushGeneralActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다.", ActionLogger::PLAIN);
$defender->getLogger()->pushGeneralActionLog("군량 부족으로 패퇴합니다.", ActionLogger::PLAIN); $defender->getLogger()->pushGeneralActionLog("군량 부족으로 패퇴합니다.", ActionLogger::PLAIN);
@@ -481,18 +455,12 @@ function processWar_NG(
$attacker->finishBattle(); $attacker->finishBattle();
$defender->finishBattle(); $defender->finishBattle();
if($city->getDead() || $defender instanceof WarUnitCity){ if ($defender instanceof WarUnitCity) {
if($city !== $defender){ $newConflict = $defender->addConflict();
$city->setOppose($attacker);
$city->setSiege();
$city->finishBattle();
}
$newConflict = $city->addConflict();
if ($newConflict) { if ($newConflict) {
$nationName = $attacker->getNationVar('name'); $nationName = $attacker->getNationVar('name');
$josaYi = JosaUtil::pick($nationName, '이'); $josaYi = JosaUtil::pick($nationName, '이');
$logger->pushGlobalHistoryLog("<M><b>【분쟁】</b></><D><b>{$nationName}</b></>{$josaYi} <G><b>{$city->getName()}</b></> 공략에 가담하여 분쟁이 발생하고 있습니다."); $logger->pushGlobalHistoryLog("<M><b>【분쟁】</b></><D><b>{$nationName}</b></>{$josaYi} <G><b>{$defender->getName()}</b></> 공략에 가담하여 분쟁이 발생하고 있습니다.");
} }
} }
@@ -529,9 +497,8 @@ function getConquerNation($city): int
return Util::array_first_key($conflict); return Util::array_first_key($conflict);
} }
function ConquerCity(array $admin, General $general, array $city, array $defenderCityGeneralList) function ConquerCity(array $admin, General $general, array $city)
{ {
/** @var General[] $defenderCityGeneralList */
$db = DB::db(); $db = DB::db();
$year = $admin['year']; $year = $admin['year'];
@@ -583,25 +550,23 @@ function ConquerCity(array $admin, General $general, array $city, array $defende
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
// 이벤트 핸들러 동작 // 이벤트 핸들러 동작
if(TurnExecutionHelper::runEventHandler($db, $gameStor, EventTarget::OccupyCity)){ $e_env = null;
$gameStor->cacheAll(); foreach (DB::db()->query('SELECT * FROM event WHERE target = "OCCUPY_CITY" ORDER BY `priority` DESC, `id` ASC') as $rawEvent) {
} if ($e_env === null) {
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize( $e_env = $gameStor->getAll(false);
UniqueConst::$hiddenSeed, }
'ConquerCity', $eventID = $rawEvent['id'];
$year, $cond = Json::decode($rawEvent['condition']);
$month, $action = Json::decode($rawEvent['action']);
$attackerNationID, $event = new Event\EventHandler($cond, $action);
$attackerID, $e_env['currentEventID'] = $eventID;
$cityID
))); $event->tryRunEvent($e_env);
foreach($defenderCityGeneralList as $defenderCityGeneral){
$defenderCityGeneral->onArbitraryAction($defenderCityGeneral, $rng, 'ConquerCity', null, [
'attacker' => $general
]);
$defenderCityGeneral->applyDB($db);
} }
if ($e_env !== null) {
$gameStor->resetCache();
}
// 국가 멸망시 // 국가 멸망시
if ($defenderNationID && $db->queryFirstField('SELECT count(city) FROM city WHERE nation = %i', $defenderNationID) === 1) { if ($defenderNationID && $db->queryFirstField('SELECT count(city) FROM city WHERE nation = %i', $defenderNationID) === 1) {
@@ -612,10 +577,10 @@ function ConquerCity(array $admin, General $general, array $city, array $defende
$lord = new General($db->queryFirstRow( $lord = new General($db->queryFirstRow(
'SELECT %l FROM general WHERE nation = %i AND officer_level = %i LIMIT 1', 'SELECT %l FROM general WHERE nation = %i AND officer_level = %i LIMIT 1',
Util::formatListOfBackticks(General::mergeQueryColumn()[0]), Util::formatListOfBackticks(General::mergeQueryColumn(['npc', 'gold', 'rice', 'experience', 'explevel', 'belong', 'dedication', 'dedlevel', 'aux'], 1)[0]),
$defenderNationID, $defenderNationID,
12 12
), null, null, $city, $loseNation, $year, $month); ), null, $city, $loseNation, $year, $month, false);
$josaUl = JosaUtil::pick($defenderNationName, '을'); $josaUl = JosaUtil::pick($defenderNationName, '을');
$attackerLogger->pushNationalHistoryLog("<D><b>{$defenderNationName}</b></>{$josaUl} 정복"); $attackerLogger->pushNationalHistoryLog("<D><b>{$defenderNationName}</b></>{$josaUl} 정복");
@@ -697,11 +662,27 @@ function ConquerCity(array $admin, General $general, array $city, array $defende
} }
// 이벤트 핸들러 동작 // 이벤트 핸들러 동작
TurnExecutionHelper::runEventHandler($db, $gameStor, EventTarget::DestroyNation); $e_env = null;
foreach (DB::db()->query('SELECT * FROM event WHERE target = "DESTROY_NATION" ORDER BY `priority` DESC, `id` ASC') as $rawEvent) {
if ($e_env === null) {
$e_env = $gameStor->getAll(false);
}
$eventID = $rawEvent['id'];
$cond = Json::decode($rawEvent['condition']);
$action = Json::decode($rawEvent['action']);
$event = new Event\EventHandler($cond, $action);
$e_env['currentEventID'] = $eventID;
$event->tryRunEvent($e_env);
}
if ($e_env !== null) {
$gameStor->resetCache();
}
// 멸망이 아니면 // 멸망이 아니면
} else { } else {
// 태수,군사,종사 일반으로... // 태수,군사,종사 일반으로...
$db->update('general', [ $db->update('general', [
'officer_level' => 1, 'officer_level' => 1,
'officer_city' => 0, 'officer_city' => 0,
@@ -712,23 +693,19 @@ function ConquerCity(array $admin, General $general, array $city, array $defende
$minCity = findNextCapital($cityID, $defenderNationID); $minCity = findNextCapital($cityID, $defenderNationID);
$minCityName = CityConst::byID($minCity)->name; $minCityName = CityConst::byID($minCity)->name;
$josaRo = JosaUtil::pick($minCityName, '로');
$josaYi = JosaUtil::pick($defenderNationName, '이'); $josaYi = JosaUtil::pick($defenderNationName, '이');
$attackerLogger->pushGlobalHistoryLog("<M><b>【긴급천도】</b></><D><b>{$defenderNationName}</b></>{$josaYi} 수도가 함락되어 <G><b>$minCityName</b></>{$josaRo} 긴급천도하였습니다."); $attackerLogger->pushGlobalHistoryLog("<M><b>【긴급천도】</b></><D><b>{$defenderNationName}</b></>{$josaYi} 수도가 함락되어 <G><b>$minCityName</b></>으로 긴급천도하였습니다.");
$moveLog = "수도가 함락되어 <G><b>$minCityName</b></>{$josaRo} <M>긴급천도</>합니다."; $moveLog = "수도가 함락되어 <G><b>$minCityName</b></>으로 <M>긴급천도</>합니다.";
foreach ($db->queryAllLists( //아국 수뇌부에게 로그 전달
'SELECT no, officer_level FROM general WHERE nation=%i', foreach ($db->queryFirstColumn(
'SELECT no FROM general WHERE nation=%i AND officer_level>=5',
$defenderNationID $defenderNationID
) as [$defenderGeneralID, $defenderGeneralChiefLevel]) { ) as $defenderChiefID) {
$defenderLogger = new ActionLogger($defenderGeneralID, $defenderNationID, $year, $month); $chiefLogger = new ActionLogger($defenderChiefID, $defenderNationID, $year, $month);
$defenderLogger->pushGeneralActionLog($moveLog, ActionLogger::PLAIN); $chiefLogger->pushGeneralActionLog($moveLog, ActionLogger::PLAIN);
if($defenderGeneralChiefLevel >= 5){ $chiefLogger->flush();
$defenderLogger->pushGeneralActionLog("수뇌는 <G><b>{$minCityName}</b></>{$josaRo} 집합되었습니다.");
}
$defenderLogger->flush();
} }
//천도 //천도
-1
View File
@@ -11,7 +11,6 @@ include "func.php";
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<title>최근 지도</title> <title>최근 지도</title>
+2 -3
View File
@@ -6,7 +6,6 @@ use sammo\Session;
use DateTimeInterface; use DateTimeInterface;
use sammo\AuctionBuyRice; use sammo\AuctionBuyRice;
use sammo\AuctionUniqueItem; use sammo\AuctionUniqueItem;
use sammo\Enums\APIRecoveryType;
use sammo\Validator; use sammo\Validator;
use sammo\General; use sammo\General;
@@ -33,13 +32,13 @@ class BidBuyRiceAuction extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN; return static::REQ_GAME_LOGIN;
} }
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{ {
$auctionID = $this->args['auctionID']; $auctionID = $this->args['auctionID'];
$amount = $this->args['amount']; $amount = $this->args['amount'];
$generalID = $session->generalID; $generalID = $session->generalID;
$general = General::createObjFromDB($generalID); $general = General::createGeneralObjFromDB($generalID);
$auction = new AuctionBuyRice($auctionID, $general); $auction = new AuctionBuyRice($auctionID, $general);
$result = $auction->bid($amount, true); $result = $auction->bid($amount, true);
+2 -3
View File
@@ -5,7 +5,6 @@ namespace sammo\API\Auction;
use sammo\Session; use sammo\Session;
use DateTimeInterface; use DateTimeInterface;
use sammo\AuctionSellRice; use sammo\AuctionSellRice;
use sammo\Enums\APIRecoveryType;
use sammo\Validator; use sammo\Validator;
use sammo\General; use sammo\General;
@@ -32,13 +31,13 @@ class BidSellRiceAuction extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN; return static::REQ_GAME_LOGIN;
} }
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{ {
$auctionID = $this->args['auctionID']; $auctionID = $this->args['auctionID'];
$amount = $this->args['amount']; $amount = $this->args['amount'];
$generalID = $session->generalID; $generalID = $session->generalID;
$general = General::createObjFromDB($generalID); $general = General::createGeneralObjFromDB($generalID);
$auction = new AuctionSellRice($auctionID, $general); $auction = new AuctionSellRice($auctionID, $general);
$result = $auction->bid($amount, true); $result = $auction->bid($amount, true);
+2 -3
View File
@@ -5,7 +5,6 @@ namespace sammo\API\Auction;
use sammo\Session; use sammo\Session;
use DateTimeInterface; use DateTimeInterface;
use sammo\AuctionUniqueItem; use sammo\AuctionUniqueItem;
use sammo\Enums\APIRecoveryType;
use sammo\Validator; use sammo\Validator;
use sammo\GameConst; use sammo\GameConst;
use sammo\General; use sammo\General;
@@ -34,14 +33,14 @@ class BidUniqueAuction extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN; return static::REQ_GAME_LOGIN;
} }
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{ {
$auctionID = $this->args['auctionID']; $auctionID = $this->args['auctionID'];
$amount = $this->args['amount']; $amount = $this->args['amount'];
$tryExtendCloseDate = $this->args['extendCloseDate'] ?? false; $tryExtendCloseDate = $this->args['extendCloseDate'] ?? false;
$generalID = $session->generalID; $generalID = $session->generalID;
$general = General::createObjFromDB($generalID); $general = General::createGeneralObjFromDB($generalID);
$auction = new AuctionUniqueItem($auctionID, $general); $auction = new AuctionUniqueItem($auctionID, $general);
$result = $auction->bid($amount, $tryExtendCloseDate); $result = $auction->bid($amount, $tryExtendCloseDate);
@@ -8,7 +8,6 @@ use sammo\AuctionSellRice;
use sammo\DB; use sammo\DB;
use sammo\DTO\AuctionBidItem; use sammo\DTO\AuctionBidItem;
use sammo\DTO\AuctionInfo; use sammo\DTO\AuctionInfo;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\AuctionType; use sammo\Enums\AuctionType;
use sammo\Validator; use sammo\Validator;
use sammo\General; use sammo\General;
@@ -30,7 +29,7 @@ class GetActiveResourceAuctionList extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN; return static::REQ_GAME_LOGIN;
} }
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{ {
$db = DB::db(); $db = DB::db();
@@ -8,9 +8,7 @@ use sammo\AuctionUniqueItem;
use sammo\DB; use sammo\DB;
use sammo\DTO\AuctionBidItem; use sammo\DTO\AuctionBidItem;
use sammo\DTO\AuctionInfo; use sammo\DTO\AuctionInfo;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\AuctionType; use sammo\Enums\AuctionType;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\InheritanceKey; use sammo\Enums\InheritanceKey;
use sammo\InheritancePointManager; use sammo\InheritancePointManager;
use sammo\TimeUtil; use sammo\TimeUtil;
@@ -39,7 +37,7 @@ class GetUniqueItemAuctionDetail extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN; return static::REQ_GAME_LOGIN;
} }
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{ {
$db = DB::db(); $db = DB::db();
@@ -77,7 +75,7 @@ class GetUniqueItemAuctionDetail extends \sammo\BaseAPI
$inheritMgr = InheritancePointManager::getInstance(); $inheritMgr = InheritancePointManager::getInstance();
//preveious라서 column을 최대한 비울 수 있다. //preveious라서 column을 최대한 비울 수 있다.
$remainPoint = $inheritMgr->getInheritancePoint( $remainPoint = $inheritMgr->getInheritancePoint(
General::createObjFromDB($generalID), General::createGeneralObjFromDB($generalID, ['owner'], 0),
InheritanceKey::previous InheritanceKey::previous
); );
@@ -8,7 +8,6 @@ use sammo\AuctionUniqueItem;
use sammo\DB; use sammo\DB;
use sammo\DTO\AuctionBidItem; use sammo\DTO\AuctionBidItem;
use sammo\DTO\AuctionInfo; use sammo\DTO\AuctionInfo;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\AuctionType; use sammo\Enums\AuctionType;
use sammo\TimeUtil; use sammo\TimeUtil;
use sammo\Util; use sammo\Util;
@@ -25,7 +24,7 @@ class GetUniqueItemAuctionList extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN; return static::REQ_GAME_LOGIN;
} }
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{ {
$db = DB::db(); $db = DB::db();
+2 -3
View File
@@ -6,7 +6,6 @@ use sammo\Session;
use DateTimeInterface; use DateTimeInterface;
use sammo\AuctionBuyRice; use sammo\AuctionBuyRice;
use sammo\DB; use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Validator; use sammo\Validator;
use sammo\GameConst; use sammo\GameConst;
use sammo\General; use sammo\General;
@@ -53,7 +52,7 @@ class OpenBuyRiceAuction extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN; return static::REQ_GAME_LOGIN;
} }
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{ {
/** @var int */ /** @var int */
$amount = $this->args['amount']; $amount = $this->args['amount'];
@@ -66,7 +65,7 @@ class OpenBuyRiceAuction extends \sammo\BaseAPI
$finishBidAmount = $this->args['finishBidAmount']; $finishBidAmount = $this->args['finishBidAmount'];
$generalID = $session->generalID; $generalID = $session->generalID;
$general = General::createObjFromDB($generalID); $general = General::createGeneralObjFromDB($generalID);
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');

Some files were not shown because too many files have changed in this diff Show More