Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
923cac5408 | ||
|
|
23505326c7 | ||
|
|
5f1a48f523 | ||
|
|
a607d39030 | ||
|
|
96d108729e | ||
|
|
ef15adaaf8 | ||
|
|
f190b74a7e | ||
|
|
edbc2b88b6 | ||
|
|
dc000cecf1 | ||
|
|
7c95a483df | ||
|
|
27e5d73da1 | ||
|
|
6306dae92d | ||
|
|
a427ddff83 | ||
|
|
b62ee6e820 | ||
|
|
3c18666080 | ||
|
|
40968b301a | ||
|
|
05904d31fd | ||
|
|
75aeaf4ee7 | ||
|
|
ff4e67a9f6 | ||
|
|
5f672d5bd1 | ||
|
|
5cb39eba8b | ||
|
|
4d8c3c75d6 | ||
|
|
8bdd19fc06 | ||
|
|
0ec99d8ba1 | ||
|
|
929d2db5a5 | ||
|
|
a7ad77f433 | ||
|
|
9cd47d5deb | ||
|
|
3cb5691aae | ||
|
|
dce63919fa | ||
|
|
1cdbedcb96 | ||
|
|
1586712ce5 | ||
|
|
f059186494 | ||
|
|
0af0be57b0 | ||
|
|
dad2b03212 | ||
|
|
b6e307660f | ||
|
|
c21c14825a | ||
|
|
39f9c986e9 | ||
|
|
393683aebc | ||
|
|
a87fcb44a6 | ||
|
|
0a6496ddfb | ||
|
|
fa2841fac6 | ||
|
|
861e45419b | ||
|
|
15fd943456 | ||
|
|
b538bfc27e | ||
|
|
e0f32eddc4 | ||
|
|
75a704c196 | ||
|
|
6565fdbe7e | ||
|
|
6248d72852 | ||
|
|
00d1797b96 | ||
|
|
911194eba8 | ||
|
|
0fad3ae31d | ||
|
|
b6988d866a | ||
|
|
e30959a656 | ||
|
|
52eeff3466 | ||
|
|
a06ded552d | ||
|
|
e9b8a84243 | ||
|
|
1fc3cfd1f2 |
+52
-50
@@ -1,50 +1,52 @@
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
|
||||
|
||||
|
||||
# 체섭 ignore
|
||||
*.log
|
||||
|
||||
logs/*.txt
|
||||
d_log/*.txt
|
||||
d_log/*.zip
|
||||
sess_*
|
||||
*/logs/*.txt
|
||||
*/logs/*/*.txt
|
||||
*/logs/preserved
|
||||
err.txt
|
||||
che/.htaccess
|
||||
kwe/.htaccess
|
||||
pwe/.htaccess
|
||||
twe/.htaccess
|
||||
hwe/.htaccess
|
||||
|
||||
d_shared
|
||||
|
||||
d_pic/*.jpg
|
||||
d_pic/*.gif
|
||||
d_pic/*.png
|
||||
d_pic/uploaded_image
|
||||
|
||||
d_setting/*.php
|
||||
*/d_setting/*.php
|
||||
*/d_setting/templates/*.php
|
||||
|
||||
**/old/*
|
||||
test.php
|
||||
|
||||
/che
|
||||
/kwe
|
||||
/pwe
|
||||
/nya
|
||||
/pya
|
||||
/twe
|
||||
|
||||
phpinfo.php
|
||||
vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/*
|
||||
*.sqlite3
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
|
||||
|
||||
|
||||
# 체섭 ignore
|
||||
*.log
|
||||
|
||||
logs/*.txt
|
||||
d_log/*.txt
|
||||
d_log/*.zip
|
||||
sess_*
|
||||
*/logs/*.txt
|
||||
*/logs/*/*.txt
|
||||
*/logs/preserved
|
||||
err.txt
|
||||
che/.htaccess
|
||||
kwe/.htaccess
|
||||
pwe/.htaccess
|
||||
twe/.htaccess
|
||||
hwe/.htaccess
|
||||
|
||||
d_shared
|
||||
|
||||
d_pic/*.jpg
|
||||
d_pic/*.gif
|
||||
d_pic/*.png
|
||||
d_pic/uploaded_image
|
||||
|
||||
d_setting/*.php
|
||||
*/d_setting/*.php
|
||||
*/d_setting/templates/*.php
|
||||
|
||||
*/data/file_cache
|
||||
|
||||
**/old/*
|
||||
test.php
|
||||
|
||||
/che
|
||||
/kwe
|
||||
/pwe
|
||||
/nya
|
||||
/pya
|
||||
/twe
|
||||
|
||||
phpinfo.php
|
||||
vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/*
|
||||
*.sqlite3
|
||||
|
||||
+2
-1
@@ -27,7 +27,8 @@
|
||||
"xemlock/htmlpurifier-html5": "^0.1.7",
|
||||
"catfan/medoo": "^1.5",
|
||||
"phan/phan": "^2.7",
|
||||
"erusev/parsedown-extra": "^0.8.1"
|
||||
"erusev/parsedown-extra": "^0.8.1",
|
||||
"nette/caching": "^3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
Generated
+208
-1
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "1c2e0182ebdf9bfe795e52a5d7fc6abd",
|
||||
"content-hash": "ab1175c8592ba7f7756d5f02a3aa051c",
|
||||
"packages": [
|
||||
{
|
||||
"name": "brandonwamboldt/utilphp",
|
||||
@@ -843,6 +843,213 @@
|
||||
"description": "Map nested JSON structures onto PHP classes",
|
||||
"time": "2020-04-16T18:48:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/caching",
|
||||
"version": "v3.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/caching.git",
|
||||
"reference": "b9ecbf920f240bd1ab14900d9a77876924ad7fb4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/caching/zipball/b9ecbf920f240bd1ab14900d9a77876924ad7fb4",
|
||||
"reference": "b9ecbf920f240bd1ab14900d9a77876924ad7fb4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nette/finder": "^2.4 || ^3.0",
|
||||
"nette/utils": "^2.4 || ^3.0",
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"latte/latte": "^2.4",
|
||||
"nette/di": "^v3.0",
|
||||
"nette/tester": "^2.0",
|
||||
"tracy/tracy": "^2.4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause",
|
||||
"GPL-2.0",
|
||||
"GPL-3.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"description": "⏱ Nette Caching: library with easy-to-use API and many cache backends.",
|
||||
"homepage": "https://nette.org",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"journal",
|
||||
"memcached",
|
||||
"nette",
|
||||
"sqlite"
|
||||
],
|
||||
"time": "2019-11-19T18:41:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/finder",
|
||||
"version": "v2.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/finder.git",
|
||||
"reference": "4ad2c298eb8c687dd0e74ae84206a4186eeaed50"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/finder/zipball/4ad2c298eb8c687dd0e74ae84206a4186eeaed50",
|
||||
"reference": "4ad2c298eb8c687dd0e74ae84206a4186eeaed50",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nette/utils": "^2.4 || ^3.0",
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"conflict": {
|
||||
"nette/nette": "<2.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"nette/tester": "^2.0",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"tracy/tracy": "^2.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.5-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause",
|
||||
"GPL-2.0",
|
||||
"GPL-3.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"description": "🔍 Nette Finder: find files and directories with an intuitive API.",
|
||||
"homepage": "https://nette.org",
|
||||
"keywords": [
|
||||
"filesystem",
|
||||
"glob",
|
||||
"iterator",
|
||||
"nette"
|
||||
],
|
||||
"time": "2020-01-03T20:35:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/utils",
|
||||
"version": "v3.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/utils.git",
|
||||
"reference": "488f58378bba71767e7831c83f9e0fa808bf83b9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/utils/zipball/488f58378bba71767e7831c83f9e0fa808bf83b9",
|
||||
"reference": "488f58378bba71767e7831c83f9e0fa808bf83b9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"nette/tester": "~2.0",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"tracy/tracy": "^2.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gd": "to use Image",
|
||||
"ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()",
|
||||
"ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()",
|
||||
"ext-json": "to use Nette\\Utils\\Json",
|
||||
"ext-mbstring": "to use Strings::lower() etc...",
|
||||
"ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()",
|
||||
"ext-xml": "to use Strings::length() etc. when mbstring is not available"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause",
|
||||
"GPL-2.0-only",
|
||||
"GPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
|
||||
"homepage": "https://nette.org",
|
||||
"keywords": [
|
||||
"array",
|
||||
"core",
|
||||
"datetime",
|
||||
"images",
|
||||
"json",
|
||||
"nette",
|
||||
"paginator",
|
||||
"password",
|
||||
"slugify",
|
||||
"string",
|
||||
"unicode",
|
||||
"utf-8",
|
||||
"utility",
|
||||
"validation"
|
||||
],
|
||||
"time": "2020-05-27T09:58:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pguardiario/phpuri",
|
||||
"version": "1.0",
|
||||
|
||||
+131
-130
@@ -1,131 +1,132 @@
|
||||
body, html{
|
||||
height: 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.main{
|
||||
margin-top: 70px;
|
||||
}
|
||||
|
||||
h1.title {
|
||||
font-size: 50px;
|
||||
font-family: 'Passion One', cursive;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
hr{
|
||||
width: 10%;
|
||||
/*color: #fff;*/
|
||||
}
|
||||
|
||||
.form-group{
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
label{
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
input,
|
||||
input::-webkit-input-placeholder {
|
||||
font-size: 11px;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
.main-login{
|
||||
/*background-color: #fff;*/
|
||||
/* shadows and rounded borders */
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
|
||||
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
|
||||
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
|
||||
|
||||
}
|
||||
|
||||
.main-center{
|
||||
margin-top: 30px;
|
||||
margin: 0 auto;
|
||||
max-width: 330px;
|
||||
padding: 40px 40px;
|
||||
|
||||
}
|
||||
|
||||
.login_btn_group{
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.login-register{
|
||||
font-size: 11px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.col-form-label{
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.terms{
|
||||
max-height: 200px; overflow-y: auto;
|
||||
}
|
||||
|
||||
.terms pre{
|
||||
width:100%;
|
||||
white-space: pre-wrap; /* Since CSS 2.1 */
|
||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
|
||||
.vertical-center {
|
||||
min-height: 100%; /* Fallback for browsers do NOT support vh unit */
|
||||
min-height: 100vh; /* These two lines are counted as one :-) */
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.full-content {
|
||||
position:fixed;
|
||||
left:0;
|
||||
top:0;
|
||||
width:100%;
|
||||
height:100%;
|
||||
margin:0;
|
||||
padding:0;
|
||||
z-index:800;
|
||||
}
|
||||
|
||||
#login_card{
|
||||
z-index:801;
|
||||
}
|
||||
|
||||
#btn_kakao_login{
|
||||
cursor: pointer;
|
||||
height:46px;
|
||||
width:116px;
|
||||
background-color: transparent;
|
||||
color:transparent;
|
||||
border:0;
|
||||
background-size: 100%; /* To fill the dimensions of container (button), or */
|
||||
background-repeat: no-repeat;
|
||||
background-position: bottom center;
|
||||
margin-top:5px;
|
||||
background-image:url('../oauth_kakao/kakao_login_join.png');
|
||||
}
|
||||
|
||||
#btn_kakao_login:hover {
|
||||
background-image:url('../oauth_kakao/kakao_login_join_ov.png');
|
||||
}
|
||||
|
||||
#bottom_box{
|
||||
position:fixed;
|
||||
bottom:0;
|
||||
width:100%;
|
||||
left:0;
|
||||
}
|
||||
#bottom_box .container{
|
||||
text-align:center;
|
||||
body,
|
||||
html {
|
||||
height: 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.main {
|
||||
margin-top: 70px;
|
||||
}
|
||||
|
||||
h1.title {
|
||||
font-size: 50px;
|
||||
font-family: 'Passion One', cursive;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
hr {
|
||||
width: 10%;
|
||||
/*color: #fff;*/
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
input,
|
||||
input::-webkit-input-placeholder {
|
||||
font-size: 11px;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
.main-login {
|
||||
/*background-color: #fff;*/
|
||||
/* shadows and rounded borders */
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
|
||||
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
|
||||
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.main-center {
|
||||
margin-top: 30px;
|
||||
margin: 0 auto;
|
||||
max-width: 330px;
|
||||
padding: 40px 40px;
|
||||
}
|
||||
|
||||
.login_btn_group {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.login-register {
|
||||
font-size: 11px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.col-form-label {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.terms {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.terms pre {
|
||||
width: 100%;
|
||||
white-space: pre-wrap;
|
||||
/* Since CSS 2.1 */
|
||||
white-space: -moz-pre-wrap;
|
||||
/* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap;
|
||||
/* Opera 4-6 */
|
||||
white-space: -o-pre-wrap;
|
||||
/* Opera 7 */
|
||||
word-wrap: break-word;
|
||||
/* Internet Explorer 5.5+ */
|
||||
}
|
||||
|
||||
.vertical-center {
|
||||
min-height: 100%;
|
||||
/* Fallback for browsers do NOT support vh unit */
|
||||
min-height: 100vh;
|
||||
/* These two lines are counted as one :-) */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#login_card {
|
||||
z-index: 801;
|
||||
}
|
||||
|
||||
#btn_kakao_login {
|
||||
cursor: pointer;
|
||||
height: 46px;
|
||||
width: 116px;
|
||||
background-color: transparent;
|
||||
color: transparent;
|
||||
border: 0;
|
||||
background-size: 100%;
|
||||
/* To fill the dimensions of container (button), or */
|
||||
background-repeat: no-repeat;
|
||||
background-position: bottom center;
|
||||
margin-top: 5px;
|
||||
background-image: url('../oauth_kakao/kakao_login_join.png');
|
||||
}
|
||||
|
||||
#btn_kakao_login:hover {
|
||||
background-image: url('../oauth_kakao/kakao_login_join_ov.png');
|
||||
}
|
||||
|
||||
#bottom_box .container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-group-xs>.btn,
|
||||
.btn-xs {
|
||||
padding: .25rem .4rem;
|
||||
font-size: .875rem;
|
||||
line-height: .5;
|
||||
border-radius: .2rem;
|
||||
}
|
||||
|
||||
#running_map {
|
||||
margin-top: 20px;
|
||||
}
|
||||
+313
-305
@@ -1,305 +1,313 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
require(__DIR__ . '/../vendor/autoload.php');
|
||||
|
||||
$host = Util::getPost('db_host');
|
||||
$port = Util::getPost('db_port', 'int');
|
||||
$username = Util::getPost('db_id');
|
||||
$password = Util::getPost('db_pw');
|
||||
$dbName = Util::getPost('db_name');
|
||||
$servHost = Util::getPost('serv_host');
|
||||
$sharedIconPath = Util::getPost('shared_icon_path');
|
||||
$gameImagePath = Util::getPost('game_image_path');
|
||||
$imageRequestKey = Util::getPost('image_request_key');
|
||||
|
||||
$kakaoRESTKey = Util::getPost('kakao_rest_key', 'string', '');
|
||||
$kakaoAdminKey = Util::getPost('kakao_admin_key', 'string', '');
|
||||
|
||||
|
||||
if (!$host || !$port || !$username || !$password || !$dbName || !$servHost || !$sharedIconPath || !$gameImagePath) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => '입력 값이 올바르지 않습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (!filter_var($servHost, FILTER_VALIDATE_URL)) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => '접속 경로가 올바르지 않습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if (file_exists(ROOT . '/d_setting/RootDB.php') && is_dir(ROOT . '/d_setting/RootDB.php')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'd_setting/RootDB.php 가 디렉토리입니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (class_exists('\\sammo\\RootDB')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => '이미 RootDB.php 파일이 있습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
//파일 권한 검사
|
||||
if (file_exists(AppConf::getUserIconPathFS()) && !is_dir(AppConf::getUserIconPathFS())) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => AppConf::$userIconPath . ' 이 디렉토리가 아닙니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (file_exists(ROOT . '/d_log') && !is_dir(ROOT . '/d_log')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'd_log 가 디렉토리가 아닙니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (file_exists(ROOT . '/d_shared') && !is_dir(ROOT . '/d_shared')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'd_shared 가 디렉토리가 아닙니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (file_exists(ROOT . '/d_setting') && !is_dir(ROOT . '/d_setting')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'd_shared 가 디렉토리가 아닙니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (
|
||||
!file_exists(ROOT . '/d_log')
|
||||
|| !file_exists(ROOT . '/d_shared')
|
||||
|| !file_exists(ROOT . '/d_setting')
|
||||
|| !file_exists(AppConf::getUserIconPathFS())
|
||||
) {
|
||||
if (!is_writable(ROOT)) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => '하위 디렉토리 생성 권한이 없습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
//기본 파일 생성
|
||||
if (!file_exists(AppConf::getUserIconPathFS())) {
|
||||
mkdir(AppConf::getUserIconPathFS());
|
||||
}
|
||||
|
||||
if (!file_exists(ROOT . '/d_log')) {
|
||||
mkdir(ROOT . '/d_log');
|
||||
}
|
||||
|
||||
if (!file_exists(ROOT . '/d_setting')) {
|
||||
mkdir(ROOT . '/d_setting');
|
||||
}
|
||||
|
||||
if (!file_exists(ROOT . '/d_shared')) {
|
||||
mkdir(ROOT . '/d_shared');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!is_writable(AppConf::getUserIconPathFS())) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => AppConf::$userIconPath . ' 디렉토리의 쓰기 권한이 없습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (!is_writable(ROOT . '/d_log')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'd_log 디렉토리의 쓰기 권한이 없습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (!is_writable(ROOT . '/d_shared')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'd_shared 디렉토리의 쓰기 권한이 없습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (!is_writable(ROOT . '/d_setting')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'd_setting 디렉토리의 쓰기 권한이 없습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!file_exists(ROOT . '/d_log/.htaccess')) {
|
||||
@file_put_contents(ROOT . '/d_log/.htaccess', 'Deny from all');
|
||||
}
|
||||
|
||||
if (!file_exists(ROOT . '/d_setting/.htaccess')) {
|
||||
@file_put_contents(ROOT . '/d_setting/.htaccess', 'Deny from all');
|
||||
}
|
||||
|
||||
//DB 접근 권한 검사
|
||||
|
||||
$rootDB = new \MeekroDB($host, $username, $password, $dbName, $port, 'utf8mb4');
|
||||
$rootDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
|
||||
|
||||
$rootDB->throw_exception_on_nonsql_error = false;
|
||||
$rootDB->nonsql_error_handler = function ($params) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'DB 접속에 실패했습니다.'
|
||||
]);
|
||||
};
|
||||
|
||||
$rootDB->error_handler = function ($params) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'SQL을 제대로 실행하지 못했습니다. DB상태를 확인해 주세요.'
|
||||
]);
|
||||
};
|
||||
|
||||
$mysqli_obj = $rootDB->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
|
||||
|
||||
if ($mysqli_obj->multi_query(file_get_contents(__DIR__ . '/sql/common_schema.sql'))) {
|
||||
while (true) {
|
||||
if (!$mysqli_obj->more_results()) {
|
||||
break;
|
||||
}
|
||||
if (!$mysqli_obj->next_result()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$rootDB->insert('system', array(
|
||||
'REG' => 'N',
|
||||
'LOGIN' => 'N',
|
||||
'CRT_DATE' => TimeUtil::now(),
|
||||
'MDF_DATE' => TimeUtil::now()
|
||||
));
|
||||
|
||||
$globalSalt = bin2hex(random_bytes(16));
|
||||
|
||||
'@phan-var-force string $servHost';
|
||||
'@phan-var-force string $sharedIconPath';
|
||||
'@phan-var-force string $gameImagePath';
|
||||
|
||||
$sharedIconPath = WebUtil::resolveRelativePath($sharedIconPath, $servHost);
|
||||
$gameImagePath = WebUtil::resolveRelativePath($gameImagePath, $servHost);
|
||||
$imageRequestPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/git_pull.php', $servHost);
|
||||
$imageKeyInstallPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/InstallKey.php', $servHost);
|
||||
|
||||
$result = Util::generateFileUsingSimpleTemplate(
|
||||
__DIR__ . '/templates/ServConfig.orig.php',
|
||||
ROOT . '/d_setting/ServConfig.php',
|
||||
[
|
||||
'serverBasePath' => $servHost,
|
||||
'sharedIconPath' => $sharedIconPath,
|
||||
'gameImagePath' => $gameImagePath,
|
||||
'imageRequestPath' => $imageRequestPath,
|
||||
'imageRequestKey' => $imageRequestKey
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
if ($imageRequestKey) {
|
||||
@file_get_contents($imageKeyInstallPath . '?key=' . $imageRequestKey);
|
||||
}
|
||||
|
||||
if ($result !== true) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => $result
|
||||
]);
|
||||
}
|
||||
|
||||
$result = Util::generateFileUsingSimpleTemplate(
|
||||
__DIR__ . '/templates/common_path.orig.js',
|
||||
ROOT . '/d_shared/common_path.js',
|
||||
[
|
||||
'serverBasePath' => $servHost,
|
||||
'sharedIconPath' => $sharedIconPath,
|
||||
'gameImagePath' => $gameImagePath
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
$result = Util::generateFileUsingSimpleTemplate(
|
||||
__DIR__ . '/templates/menu.orig.json',
|
||||
ROOT . '/d_shared/menu.json',
|
||||
[],
|
||||
true
|
||||
);
|
||||
|
||||
if ($result !== true) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => $result
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
$result = Util::generateFileUsingSimpleTemplate(
|
||||
__DIR__ . '/templates/common.orig.css',
|
||||
ROOT . '/d_shared/common.css',
|
||||
[
|
||||
'serverBasePath' => $servHost,
|
||||
'sharedIconPath' => $sharedIconPath,
|
||||
'gameImagePath' => $gameImagePath
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
if ($result !== true) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => $result
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
$result = Util::generateFileUsingSimpleTemplate(
|
||||
__DIR__ . '/templates/RootDB.orig.php',
|
||||
ROOT . '/d_setting/RootDB.php',
|
||||
[
|
||||
'host' => $host,
|
||||
'user' => $username,
|
||||
'password' => $password,
|
||||
'dbName' => $dbName,
|
||||
'port' => $port,
|
||||
'globalSalt' => $globalSalt,
|
||||
]
|
||||
);
|
||||
|
||||
$kakaoRedirectURI = WebUtil::resolveRelativePath('oauth_kakao/oauth.php', $servHost . '/');
|
||||
|
||||
Util::generateFileUsingSimpleTemplate(
|
||||
__DIR__ . '/templates/KakaoKey.orig.php',
|
||||
ROOT . '/d_setting/KakaoKey.php',
|
||||
[
|
||||
'REST_API_KEY' => $kakaoRESTKey,
|
||||
'ADMIN_KEY' => $kakaoAdminKey,
|
||||
'REDIRECT_URI' => $kakaoRedirectURI
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
if ($result !== true) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => $result
|
||||
]);
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result' => true,
|
||||
'reason' => 'success',
|
||||
'globalSalt' => $globalSalt
|
||||
]);
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
require(__DIR__ . '/../vendor/autoload.php');
|
||||
|
||||
$host = Util::getPost('db_host');
|
||||
$port = Util::getPost('db_port', 'int');
|
||||
$username = Util::getPost('db_id');
|
||||
$password = Util::getPost('db_pw');
|
||||
$dbName = Util::getPost('db_name');
|
||||
$servHost = Util::getPost('serv_host');
|
||||
$sharedIconPath = Util::getPost('shared_icon_path');
|
||||
$gameImagePath = Util::getPost('game_image_path');
|
||||
$imageRequestKey = Util::getPost('image_request_key');
|
||||
|
||||
$kakaoRESTKey = Util::getPost('kakao_rest_key', 'string', '');
|
||||
$kakaoAdminKey = Util::getPost('kakao_admin_key', 'string', '');
|
||||
|
||||
|
||||
if (!$host || !$port || !$username || !$password || !$dbName || !$servHost || !$sharedIconPath || !$gameImagePath) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => '입력 값이 올바르지 않습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (!filter_var($servHost, FILTER_VALIDATE_URL)) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => '접속 경로가 올바르지 않습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if (file_exists(ROOT . '/d_setting/RootDB.php') && is_dir(ROOT . '/d_setting/RootDB.php')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'd_setting/RootDB.php 가 디렉토리입니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (class_exists('\\sammo\\RootDB')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => '이미 RootDB.php 파일이 있습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
//파일 권한 검사
|
||||
if (file_exists(AppConf::getUserIconPathFS()) && !is_dir(AppConf::getUserIconPathFS())) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => AppConf::$userIconPath . ' 이 디렉토리가 아닙니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (file_exists(ROOT . '/d_log') && !is_dir(ROOT . '/d_log')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'd_log 가 디렉토리가 아닙니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (file_exists(ROOT . '/d_shared') && !is_dir(ROOT . '/d_shared')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'd_shared 가 디렉토리가 아닙니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (file_exists(ROOT . '/d_setting') && !is_dir(ROOT . '/d_setting')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'd_shared 가 디렉토리가 아닙니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (
|
||||
!file_exists(ROOT . '/d_log')
|
||||
|| !file_exists(ROOT . '/d_shared')
|
||||
|| !file_exists(ROOT . '/d_setting')
|
||||
|| !file_exists(AppConf::getUserIconPathFS())
|
||||
) {
|
||||
if (!is_writable(ROOT)) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => '하위 디렉토리 생성 권한이 없습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
//기본 파일 생성
|
||||
if (!file_exists(AppConf::getUserIconPathFS())) {
|
||||
mkdir(AppConf::getUserIconPathFS());
|
||||
}
|
||||
|
||||
if (!file_exists(ROOT . '/d_log')) {
|
||||
mkdir(ROOT . '/d_log');
|
||||
}
|
||||
|
||||
if (!file_exists(ROOT . '/d_setting')) {
|
||||
mkdir(ROOT . '/d_setting');
|
||||
}
|
||||
|
||||
if (!file_exists(ROOT . '/d_shared')) {
|
||||
mkdir(ROOT . '/d_shared');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!is_writable(AppConf::getUserIconPathFS())) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => AppConf::$userIconPath . ' 디렉토리의 쓰기 권한이 없습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (!is_writable(ROOT . '/d_log')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'd_log 디렉토리의 쓰기 권한이 없습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (!is_writable(ROOT . '/d_shared')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'd_shared 디렉토리의 쓰기 권한이 없습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if (!is_writable(ROOT . '/d_setting')) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'd_setting 디렉토리의 쓰기 권한이 없습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!file_exists(ROOT . '/d_log/.htaccess')) {
|
||||
@file_put_contents(ROOT . '/d_log/.htaccess', 'Deny from all');
|
||||
}
|
||||
|
||||
if (!file_exists(ROOT . '/d_setting/.htaccess')) {
|
||||
@file_put_contents(ROOT . '/d_setting/.htaccess', 'Deny from all');
|
||||
}
|
||||
|
||||
//DB 접근 권한 검사
|
||||
|
||||
$rootDB = new \MeekroDB($host, $username, $password, $dbName, $port, 'utf8mb4');
|
||||
$rootDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
|
||||
|
||||
$rootDB->throw_exception_on_nonsql_error = false;
|
||||
$rootDB->nonsql_error_handler = function ($params) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'DB 접속에 실패했습니다.'
|
||||
]);
|
||||
};
|
||||
|
||||
$rootDB->error_handler = function ($params) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => 'SQL을 제대로 실행하지 못했습니다. DB상태를 확인해 주세요.'
|
||||
]);
|
||||
};
|
||||
|
||||
$mysqli_obj = $rootDB->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
|
||||
|
||||
if ($mysqli_obj->multi_query(file_get_contents(__DIR__ . '/sql/common_schema.sql'))) {
|
||||
while (true) {
|
||||
if (!$mysqli_obj->more_results()) {
|
||||
break;
|
||||
}
|
||||
if (!$mysqli_obj->next_result()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$rootDB->insert('system', array(
|
||||
'REG' => 'N',
|
||||
'LOGIN' => 'N',
|
||||
'CRT_DATE' => TimeUtil::now(),
|
||||
'MDF_DATE' => TimeUtil::now()
|
||||
));
|
||||
|
||||
$globalSalt = bin2hex(random_bytes(16));
|
||||
|
||||
'@phan-var-force string $servHost';
|
||||
'@phan-var-force string $sharedIconPath';
|
||||
'@phan-var-force string $gameImagePath';
|
||||
|
||||
$sharedIconPath = WebUtil::resolveRelativePath($sharedIconPath, $servHost);
|
||||
$gameImagePath = WebUtil::resolveRelativePath($gameImagePath, $servHost);
|
||||
$imageRequestPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/git_pull.php', $servHost);
|
||||
$imageKeyInstallPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/InstallKey.php', $servHost);
|
||||
|
||||
$result = Util::generateFileUsingSimpleTemplate(
|
||||
__DIR__ . '/templates/ServConfig.orig.php',
|
||||
ROOT . '/d_setting/ServConfig.php',
|
||||
[
|
||||
'serverBasePath' => $servHost,
|
||||
'sharedIconPath' => $sharedIconPath,
|
||||
'gameImagePath' => $gameImagePath,
|
||||
'imageRequestPath' => $imageRequestPath,
|
||||
'imageRequestKey' => $imageRequestKey,
|
||||
'serverList' => [
|
||||
['che', '체', 'white'],
|
||||
['kwe', '퀘', 'yellow'],
|
||||
['pwe', '풰', 'orange'],
|
||||
['twe', '퉤', 'magenta'],
|
||||
['nya', '냐', '#e67e22'],
|
||||
['pya', '퍄', '#9b59b6']
|
||||
]
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
if ($imageRequestKey) {
|
||||
@file_get_contents($imageKeyInstallPath . '?key=' . $imageRequestKey);
|
||||
}
|
||||
|
||||
if ($result !== true) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => $result
|
||||
]);
|
||||
}
|
||||
|
||||
$result = Util::generateFileUsingSimpleTemplate(
|
||||
__DIR__ . '/templates/common_path.orig.js',
|
||||
ROOT . '/d_shared/common_path.js',
|
||||
[
|
||||
'serverBasePath' => $servHost,
|
||||
'sharedIconPath' => $sharedIconPath,
|
||||
'gameImagePath' => $gameImagePath
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
$result = Util::generateFileUsingSimpleTemplate(
|
||||
__DIR__ . '/templates/menu.orig.json',
|
||||
ROOT . '/d_shared/menu.json',
|
||||
[],
|
||||
true
|
||||
);
|
||||
|
||||
if ($result !== true) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => $result
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
$result = Util::generateFileUsingSimpleTemplate(
|
||||
__DIR__ . '/templates/common.orig.css',
|
||||
ROOT . '/d_shared/common.css',
|
||||
[
|
||||
'serverBasePath' => $servHost,
|
||||
'sharedIconPath' => $sharedIconPath,
|
||||
'gameImagePath' => $gameImagePath
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
if ($result !== true) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => $result
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
$result = Util::generateFileUsingSimpleTemplate(
|
||||
__DIR__ . '/templates/RootDB.orig.php',
|
||||
ROOT . '/d_setting/RootDB.php',
|
||||
[
|
||||
'host' => $host,
|
||||
'user' => $username,
|
||||
'password' => $password,
|
||||
'dbName' => $dbName,
|
||||
'port' => $port,
|
||||
'globalSalt' => $globalSalt,
|
||||
]
|
||||
);
|
||||
|
||||
$kakaoRedirectURI = WebUtil::resolveRelativePath('oauth_kakao/oauth.php', $servHost . '/');
|
||||
|
||||
Util::generateFileUsingSimpleTemplate(
|
||||
__DIR__ . '/templates/KakaoKey.orig.php',
|
||||
ROOT . '/d_setting/KakaoKey.php',
|
||||
[
|
||||
'REST_API_KEY' => $kakaoRESTKey,
|
||||
'ADMIN_KEY' => $kakaoAdminKey,
|
||||
'REDIRECT_URI' => $kakaoRedirectURI
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
if ($result !== true) {
|
||||
Json::die([
|
||||
'result' => false,
|
||||
'reason' => $result
|
||||
]);
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result' => true,
|
||||
'reason' => 'success',
|
||||
'globalSalt' => $globalSalt
|
||||
]);
|
||||
|
||||
@@ -1,55 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
class ServConfig
|
||||
{
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static $serverWebPath = '_tK_serverBasePath_';
|
||||
public static $sharedIconPath = '_tK_sharedIconPath_';
|
||||
public static $gameImagePath = "_tK_gameImagePath_";
|
||||
public static $imageRequestPath = "_tK_imageRequestPath_";
|
||||
public static $imageRequestKey = '_tK_imageRequestKey_';
|
||||
|
||||
public static function getSharedIconPath(string $filepath = ''): string
|
||||
{
|
||||
if ($filepath) {
|
||||
return static::$sharedIconPath . "/{$filepath}";
|
||||
}
|
||||
return static::$sharedIconPath;
|
||||
}
|
||||
|
||||
public static function getUserIconPath(string $filepath = ''): string
|
||||
{
|
||||
return AppConf::getUserIconPathWeb($filepath);
|
||||
}
|
||||
|
||||
public static function getGameImagePath(string $filepath = ''): string
|
||||
{
|
||||
if ($filepath) {
|
||||
return static::$gameImagePath . "/{$filepath}";
|
||||
}
|
||||
return static::$gameImagePath;
|
||||
}
|
||||
|
||||
public static function getImagePullURI(): string
|
||||
{
|
||||
$now = time();
|
||||
$req_hash = Util::hashPassword(sprintf("%016x", $now), static::$imageRequestKey);
|
||||
return static::$imageRequestPath . "?req={$req_hash}&time={$now}";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 서버 주소 반환. 서버의 경로가 하부 디렉토리인 경우에 하부 디렉토리까지 포함
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getServerBasepath(): string
|
||||
{
|
||||
return self::$serverWebPath;
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
class ServConfig
|
||||
{
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static $serverWebPath = '_tK_serverBasePath_';
|
||||
public static $sharedIconPath = '_tK_sharedIconPath_';
|
||||
public static $gameImagePath = "_tK_gameImagePath_";
|
||||
public static $imageRequestPath = "_tK_imageRequestPath_";
|
||||
public static $imageRequestKey = '_tK_imageRequestKey_';
|
||||
private static $serverList = null;
|
||||
|
||||
public static function getSharedIconPath(string $filepath = ''): string
|
||||
{
|
||||
if ($filepath) {
|
||||
return static::$sharedIconPath . "/{$filepath}";
|
||||
}
|
||||
return static::$sharedIconPath;
|
||||
}
|
||||
|
||||
public static function getUserIconPath(string $filepath = ''): string
|
||||
{
|
||||
return AppConf::getUserIconPathWeb($filepath);
|
||||
}
|
||||
|
||||
public static function getGameImagePath(string $filepath = ''): string
|
||||
{
|
||||
if ($filepath) {
|
||||
return static::$gameImagePath . "/{$filepath}";
|
||||
}
|
||||
return static::$gameImagePath;
|
||||
}
|
||||
|
||||
public static function getImagePullURI(): string
|
||||
{
|
||||
$now = time();
|
||||
$req_hash = Util::hashPassword(sprintf("%016x", $now), static::$imageRequestKey);
|
||||
return static::$imageRequestPath . "?req={$req_hash}&time={$now}";
|
||||
}
|
||||
|
||||
/**
|
||||
* 서버 설정 반환
|
||||
*
|
||||
* @return \sammo\Setting[]
|
||||
*/
|
||||
public static function getServerList(): array{
|
||||
$servKeyList = [/*_tK_serverList_*/];
|
||||
$servKeyList[] = ['hwe', '훼', 'red'];
|
||||
|
||||
if (self::$serverList === null) {
|
||||
self::$serverList = [];
|
||||
foreach($servKeyList as [$servKey, $servNick, $servColor]){
|
||||
self::$serverList[$servKey] = new Setting(ROOT.'/'.$servKey, $servNick, $servColor);
|
||||
}
|
||||
}
|
||||
return self::$serverList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 서버 주소 반환. 서버의 경로가 하부 디렉토리인 경우에 하부 디렉토리까지 포함
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getServerBasepath(): string
|
||||
{
|
||||
return self::$serverWebPath;
|
||||
}
|
||||
}
|
||||
|
||||
+215
-215
@@ -1,215 +1,215 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
$type = Util::getReq('type', 'int', 9);
|
||||
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin()->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
increaseRefresh("장수일람", 2);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT con,turntime FROM general WHERE owner = %i', $userID);
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
printLimitMsg($me['turntime']);
|
||||
exit();
|
||||
}
|
||||
|
||||
if ($type <= 0 || $type > 15) {
|
||||
$type = 9;
|
||||
}
|
||||
|
||||
$ownerNameList = [];
|
||||
if($gameStor->isunited){
|
||||
foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){
|
||||
$ownerNameList[$ownerID] = $ownerName;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=1024" />
|
||||
<title><?=UniqueConst::$serverName?>: 장수일람</title>
|
||||
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
|
||||
<?=WebUtil::printCSS('../d_shared/common.css')?>
|
||||
<?=WebUtil::printCSS('css/common.css')?>
|
||||
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
|
||||
<?=WebUtil::printJS('../d_shared/common_path.js')?>
|
||||
<?=WebUtil::printJS('js/common.js')?>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr><td>장 수 일 람<br><?=closeButton()?></td></tr>
|
||||
<tr><td><form name=form1 method=post>정렬순서 :
|
||||
<select id='viewType' name='type' size=1>
|
||||
<option value=1>국가</option>
|
||||
<option value=2>통솔</option>
|
||||
<option value=3>무력</option>
|
||||
<option value=4>지력</option>
|
||||
<option value=5>명성</option>
|
||||
<option value=6>계급</option>
|
||||
<option value=7>관직</option>
|
||||
<option value=8>삭턴</option>
|
||||
<option value=9>벌점</option>
|
||||
<option value=10>Lv</option>
|
||||
<option value=11>성격</option>
|
||||
<option value=12>내특</option>
|
||||
<option value=13>전특</option>
|
||||
<option value=14>연령</option>
|
||||
<option value=15>NPC</option>
|
||||
</select>
|
||||
<input type=submit value='정렬하기'></form>
|
||||
</td></tr>
|
||||
</table>
|
||||
<?php
|
||||
$nationname = [];
|
||||
$nationlevel = [];
|
||||
$nationname[0] = "-";
|
||||
foreach (getAllNationStaticInfo() as $nation) {
|
||||
$nationname[$nation['nation']] = $nation['name'];
|
||||
$nationlevel[$nation['nation']] = $nation['level'];
|
||||
}
|
||||
|
||||
|
||||
[$orderKey, $orderDesc] = [
|
||||
1=>['nation', false],
|
||||
2=>['leadership', true],
|
||||
3=>['strength', true],
|
||||
4=>['intel', true],
|
||||
5=>['experience', true],
|
||||
6=>['dedication', true],
|
||||
7=>['officer_level', true],
|
||||
8=>['killturn', false],
|
||||
9=>['connect', true],
|
||||
10=>['experience', true],
|
||||
11=>['personal', true],
|
||||
12=>['special', true],
|
||||
13=>['special2', true],
|
||||
14=>['age', true],
|
||||
15=>['npc', true],
|
||||
][$type];
|
||||
|
||||
$generalList = $db->query('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general order by %b %l', $orderKey, $orderDesc?'desc':'');
|
||||
|
||||
echo"
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr>
|
||||
<td width=64 align=center id=bg1>얼 굴</td>
|
||||
<td width=140 align=center id=bg1>이 름</td>
|
||||
<td width=45 align=center id=bg1>연령</td>
|
||||
<td width=45 align=center id=bg1>성격</td>
|
||||
<td width=80 align=center id=bg1>특기</td>
|
||||
<td width=45 align=center id=bg1>레 벨</td>
|
||||
<td width=140 align=center id=bg1>국 가</td>
|
||||
<td width=55 align=center id=bg1>명 성</td>
|
||||
<td width=55 align=center id=bg1>계 급</td>
|
||||
<td width=75 align=center id=bg1>관 직</td>
|
||||
<td width=45 align=center id=bg1>통솔</td>
|
||||
<td width=45 align=center id=bg1>무력</td>
|
||||
<td width=45 align=center id=bg1>지력</td>
|
||||
<td width=45 align=center id=bg1>삭턴</td>
|
||||
<td width=70 align=center id=bg1>벌점</td>
|
||||
</tr>";
|
||||
foreach($generalList as $general){
|
||||
$nation = $nationname[$general['nation']];
|
||||
|
||||
$lbonus = calcLeadershipBonus($general['officer_level'], $nationlevel[$general['nation']]??0);
|
||||
if ($lbonus > 0) {
|
||||
$lbonusText = "<font color=cyan>+{$lbonus}</font>";
|
||||
} else {
|
||||
$lbonusText = "";
|
||||
}
|
||||
|
||||
if ($general['injury'] > 0) {
|
||||
$leadership = intdiv($general['leadership'] * (100 - $general['injury']), 100);
|
||||
$strength = intdiv($general['strength'] * (100 - $general['injury']), 100);
|
||||
$intel = intdiv($general['intel'] * (100 - $general['injury']), 100);
|
||||
$leadership = "<font color=red>{$leadership}</font>{$lbonusText}";
|
||||
$strength = "<font color=red>{$strength}</font>";
|
||||
$intel = "<font color=red>{$intel}</font>";
|
||||
} else {
|
||||
$leadership = "{$general['leadership']}{$lbonusText}";
|
||||
$strength = "{$general['strength']}";
|
||||
$intel = "{$general['intel']}";
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($general['npc'] >= 2) {
|
||||
$name = "<font color=cyan>{$general['name']}</font>";
|
||||
} elseif ($general['npc'] == 1) {
|
||||
$name = "<font color=skyblue>{$general['name']}</font>";
|
||||
} else {
|
||||
$name = "{$general['name']}";
|
||||
}
|
||||
|
||||
if(key_exists($general['owner'], $ownerNameList)){
|
||||
$name = $name.'<br><small>('.$ownerNameList[$general['owner']].')</small>';
|
||||
}
|
||||
|
||||
$general['connect'] = Util::round($general['connect'], -1);
|
||||
|
||||
$imageTemp = GetImageURL($general['imgsvr']);
|
||||
echo "
|
||||
<tr data-general-id='{$general['no']}'
|
||||
data-general-wounded='{$general['injury']}'
|
||||
data-general-leadership='{$general['leadership']}'
|
||||
data-general-leadership-bonus='{$lbonus}'
|
||||
data-general-strength='{$general['strength']}'
|
||||
data-general-intel='{$general['intel']}'
|
||||
data-is-npc='".($general['npc']>=2?'true':'false')."'
|
||||
>
|
||||
<td align=center><img class='generalIcon' width='64' height='64' src='{$imageTemp}/{$general['picture']}'></img></td>
|
||||
<td align=center>$name</td>
|
||||
<td align=center>{$general['age']}세</td>
|
||||
<td align=center>".displayCharInfo($general['personal'])."</td>
|
||||
<td align=center>".displaySpecialDomesticInfo($general['special'])." / ".displaySpecialWarInfo($general['special2'])."</td>
|
||||
<td align=center>Lv ".getExpLevel($general['experience'])."</td>
|
||||
<td align=center>{$nation}</td>
|
||||
<td align=center>".getHonor($general['experience'])."</td>
|
||||
<td align=center>".getDed($general['dedication'])."</td>
|
||||
<td align=center>";
|
||||
echo getOfficerLevelText($general['officer_level']);
|
||||
echo "</td>
|
||||
<td align=center>$leadership</td>
|
||||
<td align=center>$strength</td>
|
||||
<td align=center>$intel</td>
|
||||
<td align=center>{$general['killturn']}</td>
|
||||
<td align=center>{$general['connect']}";
|
||||
echo "<br>【".getConnect($general['connect'])."】</td>
|
||||
</tr>";
|
||||
}
|
||||
echo "
|
||||
</table>
|
||||
";
|
||||
|
||||
?>
|
||||
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr><td><?=closeButton()?></td></tr>
|
||||
<tr><td><?=banner()?></td></tr>
|
||||
</table>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$("#viewType").val("<?=$type?>").attr("selected", "selected");
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
$type = Util::getReq('type', 'int', 9);
|
||||
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin()->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
increaseRefresh("장수일람", 2);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT con,turntime FROM general WHERE owner = %i', $userID);
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
printLimitMsg($me['turntime']);
|
||||
exit();
|
||||
}
|
||||
|
||||
if ($type <= 0 || $type > 15) {
|
||||
$type = 9;
|
||||
}
|
||||
|
||||
$ownerNameList = [];
|
||||
if($gameStor->isunited){
|
||||
foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){
|
||||
$ownerNameList[$ownerID] = $ownerName;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=1024" />
|
||||
<title><?=UniqueConst::$serverName?>: 장수일람</title>
|
||||
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
|
||||
<?=WebUtil::printCSS('../d_shared/common.css')?>
|
||||
<?=WebUtil::printCSS('css/common.css')?>
|
||||
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
|
||||
<?=WebUtil::printJS('../d_shared/common_path.js')?>
|
||||
<?=WebUtil::printJS('js/common.js')?>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr><td>장 수 일 람<br><?=closeButton()?></td></tr>
|
||||
<tr><td><form name=form1 method=post>정렬순서 :
|
||||
<select id='viewType' name='type' size=1>
|
||||
<option value=1>국가</option>
|
||||
<option value=2>통솔</option>
|
||||
<option value=3>무력</option>
|
||||
<option value=4>지력</option>
|
||||
<option value=5>명성</option>
|
||||
<option value=6>계급</option>
|
||||
<option value=7>관직</option>
|
||||
<option value=8>삭턴</option>
|
||||
<option value=9>벌점</option>
|
||||
<option value=10>Lv</option>
|
||||
<option value=11>성격</option>
|
||||
<option value=12>내특</option>
|
||||
<option value=13>전특</option>
|
||||
<option value=14>연령</option>
|
||||
<option value=15>NPC</option>
|
||||
</select>
|
||||
<input type=submit value='정렬하기'></form>
|
||||
</td></tr>
|
||||
</table>
|
||||
<?php
|
||||
$nationname = [];
|
||||
$nationlevel = [];
|
||||
$nationname[0] = "-";
|
||||
foreach (getAllNationStaticInfo() as $nation) {
|
||||
$nationname[$nation['nation']] = $nation['name'];
|
||||
$nationlevel[$nation['nation']] = $nation['level'];
|
||||
}
|
||||
|
||||
|
||||
[$orderKey, $orderDesc] = [
|
||||
1=>['nation', false],
|
||||
2=>['leadership', true],
|
||||
3=>['strength', true],
|
||||
4=>['intel', true],
|
||||
5=>['experience', true],
|
||||
6=>['dedication', true],
|
||||
7=>['officer_level', true],
|
||||
8=>['killturn', false],
|
||||
9=>['connect', true],
|
||||
10=>['experience', true],
|
||||
11=>['personal', true],
|
||||
12=>['special', true],
|
||||
13=>['special2', true],
|
||||
14=>['age', true],
|
||||
15=>['npc', true],
|
||||
][$type];
|
||||
|
||||
$generalList = $db->query('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general order by %b %l', $orderKey, $orderDesc?'desc':'');
|
||||
|
||||
echo"
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr>
|
||||
<td width=64 align=center id=bg1>얼 굴</td>
|
||||
<td width=140 align=center id=bg1>이 름</td>
|
||||
<td width=45 align=center id=bg1>연령</td>
|
||||
<td width=45 align=center id=bg1>성격</td>
|
||||
<td width=80 align=center id=bg1>특기</td>
|
||||
<td width=45 align=center id=bg1>레 벨</td>
|
||||
<td width=140 align=center id=bg1>국 가</td>
|
||||
<td width=55 align=center id=bg1>명 성</td>
|
||||
<td width=55 align=center id=bg1>계 급</td>
|
||||
<td width=75 align=center id=bg1>관 직</td>
|
||||
<td width=45 align=center id=bg1>통솔</td>
|
||||
<td width=45 align=center id=bg1>무력</td>
|
||||
<td width=45 align=center id=bg1>지력</td>
|
||||
<td width=45 align=center id=bg1>삭턴</td>
|
||||
<td width=70 align=center id=bg1>벌점</td>
|
||||
</tr>";
|
||||
foreach($generalList as $general){
|
||||
$nation = $nationname[$general['nation']];
|
||||
|
||||
$lbonus = calcLeadershipBonus($general['officer_level'], $nationlevel[$general['nation']]??0);
|
||||
if ($lbonus > 0) {
|
||||
$lbonusText = "<font color=cyan>+{$lbonus}</font>";
|
||||
} else {
|
||||
$lbonusText = "";
|
||||
}
|
||||
|
||||
if ($general['injury'] > 0) {
|
||||
$leadership = intdiv($general['leadership'] * (100 - $general['injury']), 100);
|
||||
$strength = intdiv($general['strength'] * (100 - $general['injury']), 100);
|
||||
$intel = intdiv($general['intel'] * (100 - $general['injury']), 100);
|
||||
$leadership = "<font color=red>{$leadership}</font>{$lbonusText}";
|
||||
$strength = "<font color=red>{$strength}</font>";
|
||||
$intel = "<font color=red>{$intel}</font>";
|
||||
} else {
|
||||
$leadership = "{$general['leadership']}{$lbonusText}";
|
||||
$strength = "{$general['strength']}";
|
||||
$intel = "{$general['intel']}";
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($general['npc'] >= 2) {
|
||||
$name = "<font color=cyan>{$general['name']}</font>";
|
||||
} elseif ($general['npc'] == 1) {
|
||||
$name = "<font color=skyblue>{$general['name']}</font>";
|
||||
} else {
|
||||
$name = "{$general['name']}";
|
||||
}
|
||||
|
||||
if(key_exists($general['owner'], $ownerNameList)){
|
||||
$name = $name.'<br><small>('.$ownerNameList[$general['owner']].')</small>';
|
||||
}
|
||||
|
||||
$general['connect'] = Util::round($general['connect'], -1);
|
||||
|
||||
$imageTemp = GetImageURL($general['imgsvr']);
|
||||
echo "
|
||||
<tr data-general-id='{$general['no']}'
|
||||
data-general-wounded='{$general['injury']}'
|
||||
data-general-leadership='{$general['leadership']}'
|
||||
data-general-leadership-bonus='{$lbonus}'
|
||||
data-general-strength='{$general['strength']}'
|
||||
data-general-intel='{$general['intel']}'
|
||||
data-is-npc='".($general['npc']>=2?'true':'false')."'
|
||||
>
|
||||
<td align=center><img class='generalIcon' width='64' height='64' src='{$imageTemp}/{$general['picture']}'></img></td>
|
||||
<td align=center>$name</td>
|
||||
<td align=center>{$general['age']}세</td>
|
||||
<td align=center>".displayCharInfo($general['personal'])."</td>
|
||||
<td align=center>".displaySpecialDomesticInfo($general['special'])." / ".displaySpecialWarInfo($general['special2'])."</td>
|
||||
<td align=center>Lv ".getExpLevel($general['experience'])."</td>
|
||||
<td align=center>{$nation}</td>
|
||||
<td align=center>".getHonor($general['experience'])."</td>
|
||||
<td align=center>".getDed($general['dedication'])."</td>
|
||||
<td align=center>";
|
||||
echo getOfficerLevelText($general['officer_level']);
|
||||
echo "</td>
|
||||
<td align=center>$leadership</td>
|
||||
<td align=center>$strength</td>
|
||||
<td align=center>$intel</td>
|
||||
<td align=center>{$general['killturn']}</td>
|
||||
<td align=center>{$general['connect']}";
|
||||
echo "<br>【".getConnect($general['connect'])."】</td>
|
||||
</tr>";
|
||||
}
|
||||
echo "
|
||||
</table>
|
||||
";
|
||||
|
||||
?>
|
||||
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr><td><?=closeButton()?></td></tr>
|
||||
<tr><td><?=banner()?></td></tr>
|
||||
</table>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$("#viewType").val("<?=$type?>").attr("selected", "selected");
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
+160
-154
@@ -1,154 +1,160 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
$showDieImmediatelyBtn = false;
|
||||
$availableDieImmediately = false;
|
||||
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin()->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
$generalID = $session->generalID;
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
increaseRefresh("내정보", 1);
|
||||
|
||||
$me = General::createGeneralObjFromDB($generalID);
|
||||
|
||||
$myset = $me->getVar('myset');
|
||||
if ($myset > 0) {
|
||||
$submit = 'button';
|
||||
} else {
|
||||
$submit = 'hidden';
|
||||
}
|
||||
|
||||
$targetTime = addTurn($me->getVar('lastrefresh'), $gameStor->turnterm, 2);
|
||||
if($gameStor->turntime <= $gameStor->opentime){
|
||||
//서버 가오픈시 할 수 있는 행동
|
||||
if($me->getNPCType() == 0){
|
||||
$showDieImmediatelyBtn = true;
|
||||
if($targetTime <= TimeUtil::now()){
|
||||
$availableDieImmediately = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$use_treatment = $me->getAuxVar('use_treatment')??10;
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=1024" />
|
||||
<title><?=UniqueConst::$serverName?>: 내정보</title>
|
||||
<script>
|
||||
var availableDieImmediately = <?=$availableDieImmediately?'true':'false'?>;
|
||||
</script>
|
||||
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
|
||||
<?=WebUtil::printJS('js/common.js')?>
|
||||
<?=WebUtil::printJS('js/myPage.js')?>
|
||||
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
|
||||
<?=WebUtil::printCSS('../d_shared/common.css')?>
|
||||
<?=WebUtil::printCSS('css/common.css')?>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr><td>내 정 보<br><?=backButton()?></td></tr>
|
||||
</table>
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr>
|
||||
<td width=50%>
|
||||
<?php generalInfo($me); ?>
|
||||
<?php generalInfo2($me); ?>
|
||||
</td>
|
||||
<td width=50% valign=top style="padding-left:4ch;">
|
||||
토너먼트 【
|
||||
<input type=radio class='tnmt' name=tnmt value=0 <?=$me->getVar('tnmt')==0?"checked":""; ?>>수동참여
|
||||
<input type=radio class='tnmt' name=tnmt value=1 <?=$me->getVar('tnmt')==1?"checked":""; ?>>자동참여
|
||||
】<br>
|
||||
∞<span style='color:orange'>개막직전 남는자리가 있을경우 랜덤하게 참여합니다.</span><br><br>
|
||||
|
||||
환약 사용 【<select id='use_treatment' name='use_treatment'>
|
||||
<option value=10 <?=$use_treatment==10?"selected":""; ?>>경상</option>
|
||||
<option value=20 <?=$use_treatment==21?"selected":""; ?>>중상</option>
|
||||
<option value=40 <?=$use_treatment==41?"selected":""; ?>>심각</option>
|
||||
<option value=60 <?=$use_treatment==61?"selected":""; ?>>위독</option>
|
||||
<option value=100 <?=$use_treatment==100?"selected":""; ?>>사용안함</option>
|
||||
</select>】<br>
|
||||
∞<span style='color:orange'>부상을 입었을 때 환약을 사용하는 기준입니다.</span><br><br>
|
||||
|
||||
수비 【<select id='defence_train' name='defence_train'>
|
||||
<option value=90 <?=$me->getVar('defence_train')==90?"selected":""; ?>>☆(훈사90)</option>
|
||||
<option value=80 <?=$me->getVar('defence_train')==80?"selected":""; ?>>◎(훈사80)</option>
|
||||
<option value=60 <?=$me->getVar('defence_train')==60?"selected":""; ?>>○(훈사60)</option>
|
||||
<option value=40 <?=$me->getVar('defence_train')==40?"selected":""; ?>>△(훈사40)</option>
|
||||
<option value=999 <?=$me->getVar('defence_train')==999?"selected":""; ?>>×[훈련, 사기 -3]</option>
|
||||
</select>
|
||||
】<br><br>
|
||||
<input type=<?=$submit?> id='set_my_setting' name=btn style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px; value=설정저장><br>
|
||||
∞<span style='color:orange'>설정저장은 이달중 <?=$myset?>회 남았습니다.</span><br><br>
|
||||
<?php if(!($gameStor->autorun_user['limit_minutes']??false)): ?>
|
||||
휴 가 신 청<br>
|
||||
<button type="button" id='vacation' style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>휴가 신청</button><br><br>
|
||||
<?php endif; ?>
|
||||
<!--빙의 해제용 삭턴 조절<br>
|
||||
<a href="b_myPage.php?detachNPC=1"><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>빙의 해체 요청</button></a>-->
|
||||
|
||||
<?php if($showDieImmediatelyBtn): ?>
|
||||
가오픈 기간 내 장수 삭제 (<?=substr($targetTime, 0, 19)?> 부터)<br>
|
||||
<a href="c_die_immediately.php" id='die_immediately'><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>장수 삭제</button></a><br><br>
|
||||
<?php endif; ?>
|
||||
|
||||
개인용 CSS<br>
|
||||
<textarea id='custom_css' style='color:white;background-color:black;width:420px;height:150px;'></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=center id=bg1><font color=skyblue size=3>개인 기록</font></td>
|
||||
<td align=center id=bg1><font color=orange size=3>전투 기록</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign=top>
|
||||
<div id='generalActionPlate'>
|
||||
<?=formatHistoryToHTML(getGeneralActionLogRecent($generalID, 24), 'generalAction')?>
|
||||
</div>
|
||||
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="generalAction">이전 로그 불러오기</button>
|
||||
</td>
|
||||
<td valign=top>
|
||||
<div id='battleDetailPlate'>
|
||||
<?=formatHistoryToHTML(getBattleDetailLogRecent($generalID, 24), 'battleDetail')?>
|
||||
</div>
|
||||
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleDetail">이전 로그 불러오기</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=center id=bg1><font color=skyblue size=3>장수 열전</font></td>
|
||||
<td align=center id=bg1><font color=orange size=3>전투 결과</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign=top>
|
||||
<?=formatHistoryToHTML(getGeneralHistoryLogAll($generalID))?>
|
||||
</td>
|
||||
<td valign=top>
|
||||
<div id='battleResultPlate'>
|
||||
<?=formatHistoryToHTML(getBattleResultRecent($generalID, 24), 'battleResult')?>
|
||||
</div>
|
||||
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleResult">이전 로그 불러오기</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr><td><?=backButton()?></td></tr>
|
||||
<tr><td><?=banner()?></td></tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
$showDieImmediatelyBtn = false;
|
||||
$availableDieImmediately = false;
|
||||
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin()->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
$generalID = $session->generalID;
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$gameStor->cacheValues(['turntime', 'opentime', 'autorun_user']);
|
||||
|
||||
increaseRefresh("내정보", 1);
|
||||
|
||||
$me = General::createGeneralObjFromDB($generalID);
|
||||
|
||||
$myset = $me->getVar('myset');
|
||||
if ($myset > 0) {
|
||||
$submit = 'button';
|
||||
} else {
|
||||
$submit = 'hidden';
|
||||
}
|
||||
|
||||
$targetTime = addTurn($me->getVar('lastrefresh'), $gameStor->turnterm, 2);
|
||||
if($gameStor->turntime <= $gameStor->opentime){
|
||||
//서버 가오픈시 할 수 있는 행동
|
||||
if($me->getNPCType() == 0){
|
||||
$showDieImmediatelyBtn = true;
|
||||
if($targetTime <= TimeUtil::now()){
|
||||
$availableDieImmediately = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$use_treatment = $me->getAuxVar('use_treatment')??10;
|
||||
$use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn')??1;
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=1024" />
|
||||
<title><?=UniqueConst::$serverName?>: 내정보</title>
|
||||
<script>
|
||||
var availableDieImmediately = <?=$availableDieImmediately?'true':'false'?>;
|
||||
</script>
|
||||
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
|
||||
<?=WebUtil::printJS('js/common.js')?>
|
||||
<?=WebUtil::printJS('js/myPage.js')?>
|
||||
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
|
||||
<?=WebUtil::printCSS('../d_shared/common.css')?>
|
||||
<?=WebUtil::printCSS('css/common.css')?>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr><td>내 정 보<br><?=backButton()?></td></tr>
|
||||
</table>
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr>
|
||||
<td width=50%>
|
||||
<?php generalInfo($me); ?>
|
||||
<?php generalInfo2($me); ?>
|
||||
</td>
|
||||
<td width=50% valign=top style="padding-left:4ch;">
|
||||
토너먼트 【
|
||||
<input type=radio class='tnmt' name=tnmt value=0 <?=$me->getVar('tnmt')==0?"checked":""; ?>>수동참여
|
||||
<input type=radio class='tnmt' name=tnmt value=1 <?=$me->getVar('tnmt')==1?"checked":""; ?>>자동참여
|
||||
】<br>
|
||||
∞<span style='color:orange'>개막직전 남는자리가 있을경우 랜덤하게 참여합니다.</span><br><br>
|
||||
|
||||
환약 사용 【<select id='use_treatment' name='use_treatment'>
|
||||
<option value=10 <?=($use_treatment==10)?"selected":""; ?>>경상</option>
|
||||
<option value=21 <?=($use_treatment==21)?"selected":""; ?>>중상</option>
|
||||
<option value=41 <?=($use_treatment==41)?"selected":""; ?>>심각</option>
|
||||
<option value=61 <?=($use_treatment==61)?"selected":""; ?>>위독</option>
|
||||
<option value=100 <?=($use_treatment==100)?"selected":""; ?>>사용안함</option>
|
||||
</select>】<br>
|
||||
∞<span style='color:orange'>부상을 입었을 때 환약을 사용하는 기준입니다.</span><br><br>
|
||||
<?php if(($gameStor->autorun_user['options']['chief'])??false) : ?>
|
||||
자동 사령턴 허용 【<select id='use_auto_nation_turn' name='use_auto_nation_turn'>
|
||||
<option value=1 <?=$use_auto_nation_turn?"selected":""; ?>>허용</option>
|
||||
<option value=0 <?=(!$use_auto_nation_turn)?"selected":""; ?>>허용 안함</option>
|
||||
</select>】<br>
|
||||
∞<span style='color:orange'>수뇌가 되었을 때 휴식 턴이어도 적당한 턴을 알아서 넣는 것을 허용합니다.</span><br><br>
|
||||
<?php endif; ?>
|
||||
수비 【<select id='defence_train' name='defence_train'>
|
||||
<?php foreach([90, 80, 60, 40] as $targetDefenceTrain): ?>
|
||||
<option value='<?=$targetDefenceTrain?>' <?=$me->getVar('defence_train')==$targetDefenceTrain?"selected":""; ?>><?=formatDefenceTrain($targetDefenceTrain)?>(훈사<?=$targetDefenceTrain?>)</option>
|
||||
<?php endforeach; ?>
|
||||
<option value=999 <?=$me->getVar('defence_train')==999?"selected":""; ?>><?=formatDefenceTrain(999)?>[훈련, 사기 -3]</option>
|
||||
</select>
|
||||
】<br><br>
|
||||
<input type=<?=$submit?> id='set_my_setting' name=btn style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px; value=설정저장><br>
|
||||
∞<span style='color:orange'>설정저장은 이달중 <?=$myset?>회 남았습니다.</span><br><br>
|
||||
<?php if(!($gameStor->autorun_user['limit_minutes']??false)): ?>
|
||||
휴 가 신 청<br>
|
||||
<button type="button" id='vacation' style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>휴가 신청</button><br><br>
|
||||
<?php endif; ?>
|
||||
<!--빙의 해제용 삭턴 조절<br>
|
||||
<a href="b_myPage.php?detachNPC=1"><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>빙의 해체 요청</button></a>-->
|
||||
|
||||
<?php if($showDieImmediatelyBtn): ?>
|
||||
가오픈 기간 내 장수 삭제 (<?=substr($targetTime, 0, 19)?> 부터)<br>
|
||||
<a href="c_die_immediately.php" id='die_immediately'><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>장수 삭제</button></a><br><br>
|
||||
<?php endif; ?>
|
||||
|
||||
개인용 CSS<br>
|
||||
<textarea id='custom_css' style='color:white;background-color:black;width:420px;height:150px;'></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=center id=bg1><font color=skyblue size=3>개인 기록</font></td>
|
||||
<td align=center id=bg1><font color=orange size=3>전투 기록</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign=top>
|
||||
<div id='generalActionPlate'>
|
||||
<?=formatHistoryToHTML(getGeneralActionLogRecent($generalID, 24), 'generalAction')?>
|
||||
</div>
|
||||
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="generalAction">이전 로그 불러오기</button>
|
||||
</td>
|
||||
<td valign=top>
|
||||
<div id='battleDetailPlate'>
|
||||
<?=formatHistoryToHTML(getBattleDetailLogRecent($generalID, 24), 'battleDetail')?>
|
||||
</div>
|
||||
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleDetail">이전 로그 불러오기</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=center id=bg1><font color=skyblue size=3>장수 열전</font></td>
|
||||
<td align=center id=bg1><font color=orange size=3>전투 결과</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign=top>
|
||||
<?=formatHistoryToHTML(getGeneralHistoryLogAll($generalID))?>
|
||||
</td>
|
||||
<td valign=top>
|
||||
<div id='battleResultPlate'>
|
||||
<?=formatHistoryToHTML(getBattleResultRecent($generalID, 24), 'battleResult')?>
|
||||
</div>
|
||||
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleResult">이전 로그 불러오기</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr><td><?=backButton()?></td></tr>
|
||||
<tr><td><?=banner()?></td></tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
+551
-480
@@ -1,481 +1,552 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
$session = Session::requireLogin()->setReadOnly();
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
$startYear = $gameStor->getValue('startyear');
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title><?=UniqueConst::$serverName?>: 전투 시뮬레이터</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=1100" />
|
||||
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
|
||||
<?=WebUtil::printCSS('../d_shared/common.css')?>
|
||||
<?=WebUtil::printCSS('css/common.css')?>
|
||||
<?=WebUtil::printCSS('css/battle_simulator.css')?>
|
||||
<?=WebUtil::printJS('../d_shared/common_path.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/moment.min.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/download2.js')?>
|
||||
<?=WebUtil::printJS('js/common.js')?>
|
||||
<script>
|
||||
var defaultSpecialDomestic = '<?=GameConst::$defaultSpecialDomestic?>';
|
||||
</script>
|
||||
<?=WebUtil::printJS('js/battle_simulator.js')?>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
전역 설정
|
||||
</div>
|
||||
<div class="card-body dragpad_battle">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control" aria-describedby="text_year" value="<?=$startYear?>" disabled>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">년 시작</span>
|
||||
</div>
|
||||
<input type="number" class="form-control" id="year" value="<?=$startYear+3?>" min="<?=$startYear?>">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">년</span>
|
||||
</div>
|
||||
<input type="number" class="form-control" id="month" value="1" min="1" max="12">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">월</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
<div class="input-group mr-2" role="group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">반복 횟수</span>
|
||||
</div>
|
||||
<select class="custom-select" id="repeat_cnt">
|
||||
<option value="1">1회 (로그 표기)</option>
|
||||
<option value="1000">1000회 (요약 표기)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="btn-group mr-2" role="group">
|
||||
<button type="button" class="btn btn-danger btn-begin_battle">전투</button>
|
||||
</div>
|
||||
<div class="btn-group mr-2" role="group">
|
||||
<button type="button" class="btn btn-info btn-battle-save">모두 저장</button>
|
||||
<input type="file" class="form_load_battle_file" accept=".json" style="display: none;" />
|
||||
<button type="button" class="btn btn-primary btn-battle-load">모두 불러오기</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<div class="card mb-2 attacker_nation">
|
||||
<div class="card-header">
|
||||
출병국 설정
|
||||
</div>
|
||||
<div class="card-body nation_detail dragpad_battle">
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">국가 성향</span>
|
||||
</div>
|
||||
<select class="custom-select form_nation_type" style="width:25ch;">
|
||||
<?php foreach(GameConst::$availableNationType as $typeID): ?>
|
||||
<?php $nationTypeClass = buildNationTypeClass($typeID) ?>
|
||||
<option value="<?=$typeID?>"><?=$nationTypeClass->getName()?> (<?=$nationTypeClass::$pros?>, <?=$nationTypeClass::$cons?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">기술</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_tech" value="1" min="0" max="12">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">등급</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">국가 규모</span>
|
||||
</div>
|
||||
<select class="custom-select form_nation_level">
|
||||
<?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?>
|
||||
<option value="<?=$nationLevel?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">도시 규모</span>
|
||||
</div>
|
||||
<select class="custom-select form_city_level">
|
||||
<?php foreach(getCityLevelList() as $levelID => $name): ?>
|
||||
<option value="<?=$levelID?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">수도</span>
|
||||
</div>
|
||||
<div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons">
|
||||
<label class="btn btn-secondary">
|
||||
<input type="radio" name="is_attacker_capital" class="form_is_capital" value="1" autocomplete="off">Y
|
||||
</label>
|
||||
<label class="btn btn-secondary active">
|
||||
<input type="radio" name="is_attacker_capital" class="form_is_capital" value="2" autocomplete="off" checked>N
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-2 attacker_form general_form" data-general_no='1'>
|
||||
<div class="card-header">
|
||||
<div class="float-sm-left" style="line-height:25px;">출병자 설정</div>
|
||||
<div class="float-sm-right btn-toolbar" role="toolbar">
|
||||
<div class="btn-group btn-group-sm mr-2" role="group">
|
||||
<button type="button" class="btn btn-info btn-general-save">저장</button>
|
||||
<input type="file" class="form_load_general_file" accept=".json" style="display: none;" />
|
||||
<button type="button" class="btn btn-primary btn-general-load">불러오기</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- <div class="col-sm"> -->
|
||||
<div class="col-sm defender-column">
|
||||
<div class="card mb-2 defender_nation">
|
||||
<div class="card-header">
|
||||
수비국 설정
|
||||
</div>
|
||||
<div class="card-body dragpad_battle">
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">국가 성향</span>
|
||||
</div>
|
||||
<select class="custom-select form_nation_type" style="width:25ch;">
|
||||
<?php foreach(GameConst::$availableNationType as $typeID): ?>
|
||||
<?php $nationTypeObj = buildNationTypeClass($typeID) ?>
|
||||
<option value="<?=$typeID?>"><?=$nationTypeObj->getName()?> (<?=$nationTypeObj::$pros?>, <?=$nationTypeObj::$cons?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">기술</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_tech" value="1" min="0" max="12">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">등급</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">국가 규모</span>
|
||||
</div>
|
||||
<select class="custom-select form_nation_level">
|
||||
<?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?>
|
||||
<option value="<?=$nationLevel?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">도시 규모</span>
|
||||
</div>
|
||||
<select class="custom-select form_city_level">
|
||||
<?php foreach(getCityLevelList() as $levelID => $name): ?>
|
||||
<option value="<?=$levelID?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">수도</span>
|
||||
</div>
|
||||
<div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons">
|
||||
<label class="btn btn-secondary">
|
||||
<input type="radio" name="is_defender_capital" class="form_is_capital" value="1" autocomplete="off">Y
|
||||
</label>
|
||||
<label class="btn btn-secondary active">
|
||||
<input type="radio" name="is_defender_capital" class="form_is_capital" value="0" autocomplete="off" checked>N
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">수비</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_def" id="city_def" value="1000" min="10" step="10">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">성벽</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_wall" id="city_wall" value="1000" min="0" step="10">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-2 defender_add_form">
|
||||
<div class="card-header">
|
||||
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
|
||||
<div class="float-sm-right btn-toolbar" role="toolbar">
|
||||
<div class="btn-group btn-group-sm mr-2" role="group">
|
||||
<button type="button" class="btn btn-dark btn-reorder_defender">수비 순서대로 정렬</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button type="button" class="btn btn-success add-defender">추가</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-2 form_sample">
|
||||
<div class="card-header">
|
||||
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
|
||||
<div class="float-sm-right btn-toolbar" role="toolbar">
|
||||
<div class="btn-group btn-group-sm mr-2" role="group">
|
||||
<button type="button" class="btn btn-info btn-general-save">저장</button>
|
||||
<input type="file" class="form_load_general_file" accept=".json" style="display: none;" />
|
||||
<button type="button" class="btn btn-primary btn-general-load">불러오기</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button type="button" class="btn btn-warning copy-defender">복제</button>
|
||||
<button type="button" class="btn btn-danger delete-defender">제거</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body general_detail">
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">이름</span>
|
||||
</div>
|
||||
<input type="text" class="form-control form_general_name" value="무명" style="width:15ch;">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">직위</span>
|
||||
</div>
|
||||
<select class="custom-select form_officer_level" style="width:8ch;">
|
||||
<option value="1">일반</option>
|
||||
<option value="4">태수</option>
|
||||
<option value="3">군사</option>
|
||||
<option value="2">종사</option>
|
||||
<option value="10">무장 수뇌</option>
|
||||
<option value="9">지장 수뇌</option>
|
||||
<option value="11">참모</option>
|
||||
<option value="12">군주</option>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">Level</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_exp_level" value="20" min="0" max="300" step="1">
|
||||
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">통솔</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_leadership" value="50" min="1" max="300" step="1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">무력</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_strength" value="50" min="1" max="300" step="1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">지력</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_intel" value="50" min="1" max="300" step="1">
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">명마</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_horse">
|
||||
<option value='None'>-</option>
|
||||
<?php foreach(GameConst::$allItems['horse'] as $horseID=>$cnt): ?>
|
||||
<option value="<?=$horseID?>"><?=getItemName($horseID)?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">무기</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_weap">
|
||||
<option value='None'>-</option>
|
||||
<?php foreach(GameConst::$allItems['weapon'] as $weaponID=>$cnt): ?>
|
||||
<option value="<?=$weaponID?>"><?=getItemName($weaponID)?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">서적</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_book">
|
||||
<option value='None'>-</option>
|
||||
<?php foreach(GameConst::$allItems['book'] as $bookID=>$cnt): ?>
|
||||
<option value="<?=$bookID?>"><?=getItemName($bookID)?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">부상</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_injury" value="0" min="0" max="80" step="1">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">%(<span class="injury_helptext">건강</span>)</span>
|
||||
</div>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">군량</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_rice" value="5000" min="50" max="40000" step="50">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">도구</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_item">
|
||||
<option value='None'>-</option>
|
||||
<?php foreach(GameConst::$allItems['item'] as $itemID=>$cnt): ?>
|
||||
<option value="<?=$itemID?>"><?=getItemName($itemID)?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">병종</span>
|
||||
</div>
|
||||
<select class="custom-select form_crewtype">
|
||||
<?php foreach(GameUnitConst::all() as $crewTypeID => $crewType): ?>
|
||||
<?php if($crewType->armType === GameUnitConst::T_CASTLE){ continue; } ?>
|
||||
<option value="<?=$crewTypeID?>"><?=$crewType->name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">병사</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_crew" value="7000" min="100" step="100">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">성격</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_character">
|
||||
<?php foreach(getCharacterList(false) as $characterID => [$name,$info]): ?>
|
||||
<option value="<?=$characterID?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">훈련</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_train" value="100" min="40" max="<?=GameConst::$maxTrainByWar?>" step="1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">사기</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_atmos" value="100" min="40" max="<?=GameConst::$maxAtmosByWar?>" step="1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">전특</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_special_war">
|
||||
<?php foreach(SpecialityHelper::getSpecialWarList(false) as $specialWarID =>$specialObj): ?>
|
||||
<option value="<?=$specialWarID?>"><?=$specialObj->getName()?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">보병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex1">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">궁병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex2">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">기병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex3">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">귀병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex4">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">차병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex5">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend only_defender">
|
||||
<span class="input-group-text">수비여부</span>
|
||||
</div>
|
||||
<select class="custom-select form_defence_train only_defender">
|
||||
<option value="80">훈사 80</option>
|
||||
<option value="60">훈사 60</option>
|
||||
<option value="999">안함</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div><!-- <div class="col-sm"> -->
|
||||
</div>
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
전투 요약
|
||||
</div>
|
||||
<table class="table">
|
||||
<tbody id="battle_result_summary">
|
||||
<tr><th style='width:18ch;'>전투 일시</th><td id='result_datetime'></td></tr>
|
||||
<tr><th>전투 횟수</th><td id='result_warcnt'></td></tr>
|
||||
<tr><th>전투 페이즈</th><td id='result_phase'></td></tr>
|
||||
<tr><th>준 피해</th><td><span id='result_killed'>0</span><span id='result_varKilled'> (<span id='result_minKilled'>0</span> ~ <span id='result_maxKilled'>0</span>)</span></td></tr>
|
||||
<tr><th>받은 피해</th><td><span id='result_dead'>0</span><span id='result_varDead'> (<span id='result_minDead'>0</span> ~ <span id='result_maxDead'>0</span>)</span></td></tr>
|
||||
<tr><th>출병자 군량 소모</th><td id='result_attackerRice'></td></tr>
|
||||
<tr><th>수비자 군량 소모</th><td id='result_defenderRice'></td></tr>
|
||||
<tr><th>공격자 스킬</th><td id='result_attackerSkills'></td></tr>
|
||||
<tr class='result_defenderSkills'><th>수비자1 스킬</th><td></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
마지막 전투 로그
|
||||
</div>
|
||||
<div class="card-body" id="generalBattleResultLog">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
마지막 전투 상세 로그
|
||||
</div>
|
||||
<div class="card-body" id="generalBattleDetailLog">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
$session = Session::requireLogin()->setReadOnly();
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
$gameStor->cacheValues(['startyear', 'year']);
|
||||
$startYear = $gameStor->startyear;
|
||||
$year = $gameStor->year;
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no, nation, city FROM general WHERE owner =%i', Session::getUserID());
|
||||
|
||||
if($me){
|
||||
$generalID = $me['no'];
|
||||
$nationID = $me['nation'];
|
||||
$city = $db->queryFirstRow('SELECT city, level, def, wall FROM city WHERE city = %i', $me['city']);
|
||||
}
|
||||
else{
|
||||
$generalID = 0;
|
||||
$nationID = 0;
|
||||
$city = [
|
||||
'city'=>0,
|
||||
'level'=>5,
|
||||
'def'=>1000,
|
||||
'wall'=>1000,
|
||||
];
|
||||
}
|
||||
|
||||
if($nationID){
|
||||
$nation = $db->queryFirstRow('SELECT level, type, tech, capital FROM nation WHERE nation = %i', $nationID);
|
||||
}
|
||||
else{
|
||||
$nation = null;
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title><?=UniqueConst::$serverName?>: 전투 시뮬레이터</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=1100" />
|
||||
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
|
||||
<?=WebUtil::printCSS('../d_shared/common.css')?>
|
||||
<?=WebUtil::printCSS('css/common.css')?>
|
||||
<?=WebUtil::printCSS('css/battle_simulator.css')?>
|
||||
<?=WebUtil::printJS('../d_shared/common_path.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/moment.min.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/download2.js')?>
|
||||
<?=WebUtil::printJS('js/common.js')?>
|
||||
<script>
|
||||
var defaultSpecialDomestic = '<?=GameConst::$defaultSpecialDomestic?>';
|
||||
var city = <?=Json::encode($city)?>;
|
||||
var nation = <?=Json::encode($nation)?>;
|
||||
</script>
|
||||
<?=WebUtil::printJS('js/battle_simulator.js')?>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
전역 설정
|
||||
</div>
|
||||
<div class="card-body dragpad_battle">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control" aria-describedby="text_year" value="<?=$startYear?>" disabled>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">년 시작</span>
|
||||
</div>
|
||||
<input type="number" class="form-control" id="year" value="<?=$year?>" min="<?=$startYear?>">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">년</span>
|
||||
</div>
|
||||
<input type="number" class="form-control" id="month" value="1" min="1" max="12">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">월</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
<div class="input-group mr-2" role="group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">반복 횟수</span>
|
||||
</div>
|
||||
<select class="custom-select" id="repeat_cnt">
|
||||
<option value="1">1회 (로그 표기)</option>
|
||||
<option value="1000">1000회 (요약 표기)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="btn-group mr-2" role="group">
|
||||
<button type="button" class="btn btn-danger btn-begin_battle">전투</button>
|
||||
</div>
|
||||
<div class="btn-group mr-2" role="group">
|
||||
<button type="button" class="btn btn-info btn-battle-save">모두 저장</button>
|
||||
<input type="file" class="form_load_battle_file" accept=".json" style="display: none;" />
|
||||
<button type="button" class="btn btn-primary btn-battle-load">모두 불러오기</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<div class="card mb-2 attacker_nation">
|
||||
<div class="card-header">
|
||||
출병국 설정
|
||||
</div>
|
||||
<div class="card-body nation_detail dragpad_battle">
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">국가 성향</span>
|
||||
</div>
|
||||
<select class="custom-select form_nation_type" style="width:25ch;">
|
||||
<?php foreach(GameConst::$availableNationType as $typeID): ?>
|
||||
<?php $nationTypeClass = buildNationTypeClass($typeID) ?>
|
||||
<option value="<?=$typeID?>"><?=$nationTypeClass->getName()?> (<?=$nationTypeClass::$pros?>, <?=$nationTypeClass::$cons?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">기술</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_tech" value="1" min="0" max="12">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">등급</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">국가 규모</span>
|
||||
</div>
|
||||
<select class="custom-select form_nation_level">
|
||||
<?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?>
|
||||
<option value="<?=$nationLevel?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">도시 규모</span>
|
||||
</div>
|
||||
<select class="custom-select form_city_level">
|
||||
<?php foreach(getCityLevelList() as $levelID => $name): ?>
|
||||
<option value="<?=$levelID?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">수도</span>
|
||||
</div>
|
||||
<div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons">
|
||||
<label class="btn btn-secondary">
|
||||
<input type="radio" name="is_attacker_capital" class="form_is_capital" value="1" autocomplete="off">Y
|
||||
</label>
|
||||
<label class="btn btn-secondary active">
|
||||
<input type="radio" name="is_attacker_capital" class="form_is_capital" value="0" autocomplete="off">N
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-2 attacker_form general_form" data-general_no='1'>
|
||||
<div class="card-header">
|
||||
<div class="float-sm-left" style="line-height:25px;">출병자 설정</div>
|
||||
<div class="float-sm-right btn-toolbar" role="toolbar">
|
||||
<div class="btn-group btn-group-sm mr-2" role="group">
|
||||
<button type="button" class="btn btn-success btn-general-import-server">서버에서 가져오기</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm mr-2" role="group">
|
||||
<button type="button" class="btn btn-info btn-general-save">저장</button>
|
||||
<input type="file" class="form_load_general_file" accept=".json" style="display: none;" />
|
||||
<button type="button" class="btn btn-primary btn-general-load">불러오기</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- <div class="col-sm"> -->
|
||||
<div class="col-sm defender-column">
|
||||
<div class="card mb-2 defender_nation">
|
||||
<div class="card-header">
|
||||
수비국 설정
|
||||
</div>
|
||||
<div class="card-body dragpad_battle">
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">국가 성향</span>
|
||||
</div>
|
||||
<select class="custom-select form_nation_type" style="width:25ch;">
|
||||
<?php foreach(GameConst::$availableNationType as $typeID): ?>
|
||||
<?php $nationTypeObj = buildNationTypeClass($typeID) ?>
|
||||
<option value="<?=$typeID?>"><?=$nationTypeObj->getName()?> (<?=$nationTypeObj::$pros?>, <?=$nationTypeObj::$cons?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">기술</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_tech" value="1" min="0" max="12">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">등급</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">국가 규모</span>
|
||||
</div>
|
||||
<select class="custom-select form_nation_level">
|
||||
<?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?>
|
||||
<option value="<?=$nationLevel?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">도시 규모</span>
|
||||
</div>
|
||||
<select class="custom-select form_city_level">
|
||||
<?php foreach(getCityLevelList() as $levelID => $name): ?>
|
||||
<option value="<?=$levelID?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">수도</span>
|
||||
</div>
|
||||
<div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons">
|
||||
<label class="btn btn-secondary">
|
||||
<input type="radio" name="is_defender_capital" class="form_is_capital" value="1" autocomplete="off">Y
|
||||
</label>
|
||||
<label class="btn btn-secondary active">
|
||||
<input type="radio" name="is_defender_capital" class="form_is_capital" value="0" autocomplete="off">N
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">수비</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_def" id="city_def" value="1000" min="10" step="10">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">성벽</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_wall" id="city_wall" value="1000" min="0" step="10">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-2 defender_add_form">
|
||||
<div class="card-header">
|
||||
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
|
||||
<div class="float-sm-right btn-toolbar" role="toolbar">
|
||||
<div class="btn-group btn-group-sm mr-2" role="group">
|
||||
<button type="button" class="btn btn-dark btn-reorder_defender">수비 순서대로 정렬</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button type="button" class="btn btn-success add-defender">추가</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-2 form_sample">
|
||||
<div class="card-header">
|
||||
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
|
||||
<div class="float-sm-right btn-toolbar" role="toolbar">
|
||||
<div class="btn-group btn-group-sm mr-2" role="group">
|
||||
<button type="button" class="btn btn-success btn-general-import-server">서버에서 가져오기</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm mr-2" role="group">
|
||||
<button type="button" class="btn btn-info btn-general-save">저장</button>
|
||||
<input type="file" class="form_load_general_file" accept=".json" style="display: none;" />
|
||||
<button type="button" class="btn btn-primary btn-general-load">불러오기</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button type="button" class="btn btn-warning copy-defender">복제</button>
|
||||
<button type="button" class="btn btn-danger delete-defender">제거</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body general_detail">
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">이름</span>
|
||||
</div>
|
||||
<input type="text" class="form-control form_general_name" value="무명" style="width:15ch;">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">직위</span>
|
||||
</div>
|
||||
<select class="custom-select form_officer_level" style="width:8ch;">
|
||||
<option value="1">일반</option>
|
||||
<option value="4">태수</option>
|
||||
<option value="3">군사</option>
|
||||
<option value="2">종사</option>
|
||||
<option value="10">무장 수뇌</option>
|
||||
<option value="9">지장 수뇌</option>
|
||||
<option value="11">참모</option>
|
||||
<option value="12">군주</option>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">Level</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_exp_level" value="20" min="0" max="300" step="1">
|
||||
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">통솔</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_leadership" value="50" min="1" max="300" step="1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">무력</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_strength" value="50" min="1" max="300" step="1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">지력</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_intel" value="50" min="1" max="300" step="1">
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">명마</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_horse">
|
||||
<option value='None'>-</option>
|
||||
<?php foreach(GameConst::$allItems['horse'] as $horseID=>$cnt): ?>
|
||||
<option value="<?=$horseID?>"><?=getItemName($horseID)?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">무기</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_weap">
|
||||
<option value='None'>-</option>
|
||||
<?php foreach(GameConst::$allItems['weapon'] as $weaponID=>$cnt): ?>
|
||||
<option value="<?=$weaponID?>"><?=getItemName($weaponID)?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">서적</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_book">
|
||||
<option value='None'>-</option>
|
||||
<?php foreach(GameConst::$allItems['book'] as $bookID=>$cnt): ?>
|
||||
<option value="<?=$bookID?>"><?=getItemName($bookID)?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">부상</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_injury" value="0" min="0" max="80" step="1">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">%(<span class="injury_helptext">건강</span>)</span>
|
||||
</div>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">군량</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_rice" value="5000" min="50" max="40000" step="50">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">도구</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_item">
|
||||
<option value='None'>-</option>
|
||||
<?php foreach(GameConst::$allItems['item'] as $itemID=>$cnt): ?>
|
||||
<option value="<?=$itemID?>"><?=getItemName($itemID)?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">병종</span>
|
||||
</div>
|
||||
<select class="custom-select form_crewtype">
|
||||
<?php foreach(GameUnitConst::all() as $crewTypeID => $crewType): ?>
|
||||
<?php if($crewType->armType === GameUnitConst::T_CASTLE){ continue; } ?>
|
||||
<option value="<?=$crewTypeID?>"><?=$crewType->name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">병사</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_crew" value="7000" min="100" step="100">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">성격</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_character">
|
||||
<?php foreach(getCharacterList(false) as $characterID => [$name,$info]): ?>
|
||||
<option value="<?=$characterID?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">훈련</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_train" value="100" min="40" max="<?=GameConst::$maxTrainByWar?>" step="1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">사기</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_atmos" value="100" min="40" max="<?=GameConst::$maxAtmosByWar?>" step="1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">전특</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_special_war">
|
||||
<?php foreach(SpecialityHelper::getSpecialWarList(false) as $specialWarID =>$specialObj): ?>
|
||||
<option value="<?=$specialWarID?>"><?=$specialObj->getName()?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">보병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex1">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">궁병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex2">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">기병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex3">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">귀병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex4">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">차병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex5">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend only_defender">
|
||||
<span class="input-group-text">수비여부</span>
|
||||
</div>
|
||||
<select class="custom-select form_defence_train only_defender">
|
||||
<option value="90">훈사 90</option>
|
||||
<option value="80">훈사 80</option>
|
||||
<option value="60">훈사 60</option>
|
||||
<option value="40">훈사 40</option>
|
||||
<option value="999">안함</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">전투 수</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_warnum" value="0" step="1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">승리 수</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_killnum" value="0" step="1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">사살 수</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_killcrew" value="0" step="1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div><!-- <div class="col-sm"> -->
|
||||
</div>
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
전투 요약
|
||||
</div>
|
||||
<table class="table">
|
||||
<tbody id="battle_result_summary">
|
||||
<tr><th style='width:18ch;'>전투 일시</th><td id='result_datetime'></td></tr>
|
||||
<tr><th>전투 횟수</th><td id='result_warcnt'></td></tr>
|
||||
<tr><th>전투 페이즈</th><td id='result_phase'></td></tr>
|
||||
<tr><th>준 피해</th><td><span id='result_killed'>0</span><span id='result_varKilled'> (<span id='result_minKilled'>0</span> ~ <span id='result_maxKilled'>0</span>)</span></td></tr>
|
||||
<tr><th>받은 피해</th><td><span id='result_dead'>0</span><span id='result_varDead'> (<span id='result_minDead'>0</span> ~ <span id='result_maxDead'>0</span>)</span></td></tr>
|
||||
<tr><th>출병자 군량 소모</th><td id='result_attackerRice'></td></tr>
|
||||
<tr><th>수비자 군량 소모</th><td id='result_defenderRice'></td></tr>
|
||||
<tr><th>공격자 스킬</th><td id='result_attackerSkills'></td></tr>
|
||||
<tr class='result_defenderSkills'><th>수비자1 스킬</th><td></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
마지막 전투 로그
|
||||
</div>
|
||||
<div class="card-body" id="generalBattleResultLog">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
마지막 전투 상세 로그
|
||||
</div>
|
||||
<div class="card-body" id="generalBattleDetailLog">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="importModal" class="modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">장수 목록</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<select id="modalSelector"></select>
|
||||
<p>타국 장수를 선택한 경우 숙련과 아이템은 0으로 초기화됩니다.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" id='importFromDB'>가져오기</button>
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">닫기</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
+2137
-2112
File diff suppressed because it is too large
Load Diff
+447
-447
@@ -1,448 +1,448 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
use sammo\Command\GeneralCommand;
|
||||
use sammo\Command\NationCommand;
|
||||
|
||||
function getGeneralTurnBrief(General $generalObj, array $turnList) {
|
||||
$result = [];
|
||||
|
||||
foreach($turnList as $turnIdx => [$action, $arg]){
|
||||
$commandObj = buildGeneralCommandClass($action, $generalObj, [], $arg);
|
||||
$turnText = $commandObj->getBrief();
|
||||
$result[$turnIdx] = $turnText;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function getNationTurnBrief(General $generalObj, array $turnList) {
|
||||
$result = [];
|
||||
|
||||
$tmpTurn = new LastTurn();
|
||||
foreach($turnList as $turnIdx => [$action, $arg]){
|
||||
$commandObj = buildNationCommandClass($action, $generalObj, [], $tmpTurn, $arg);
|
||||
$turnText = $commandObj->getBrief();
|
||||
$result[$turnIdx] = $turnText;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function pushGeneralCommand(int $generalID, int $turnCnt=1){
|
||||
if($turnCnt == 0){
|
||||
return;
|
||||
}
|
||||
if($turnCnt < 0){
|
||||
pullGeneralCommand($generalID, -$turnCnt);
|
||||
return;
|
||||
}
|
||||
if($turnCnt >= GameConst::$maxTurn){
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$db->update('general_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
|
||||
], 'general_id=%i ORDER BY turn_idx DESC', $generalID);
|
||||
$db->update('general_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxTurn),
|
||||
'action'=>'휴식',
|
||||
'arg'=>'{}',
|
||||
'brief'=>'휴식'
|
||||
], 'general_id=%i AND turn_idx >= %i', $generalID, GameConst::$maxTurn);
|
||||
}
|
||||
|
||||
function pullGeneralCommand(int $generalID, int $turnCnt=1){
|
||||
if($turnCnt == 0){
|
||||
return;
|
||||
}
|
||||
if($turnCnt < 0){
|
||||
pushGeneralCommand($generalID, -$turnCnt);
|
||||
return;
|
||||
}
|
||||
if($turnCnt >= GameConst::$maxTurn){
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$db->update('general_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxTurn),
|
||||
'action'=>'휴식',
|
||||
'arg'=>'{}',
|
||||
'brief'=>'휴식'
|
||||
], 'general_id=%i AND turn_idx < %i', $generalID, $turnCnt);
|
||||
$db->update('general_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
|
||||
], 'general_id=%i ORDER BY turn_idx ASC', $generalID);
|
||||
}
|
||||
|
||||
function repeatGeneralCommand(int $generalId, int $turnCnt){
|
||||
if($turnCnt <= 0){
|
||||
return;
|
||||
}
|
||||
if($turnCnt >= GameConst::$maxTurn){
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$reqTurn = $turnCnt;
|
||||
if($turnCnt * 2 > GameConst::$maxTurn){
|
||||
$reqTurn = GameConst::$maxTurn - $turnCnt;
|
||||
}
|
||||
|
||||
$turnList = $db->query('SELECT turn_idx, `action`, arg, brief FROM general_turn WHERE general_id=%i AND turn_idx < %i', $generalId, $reqTurn);
|
||||
foreach($turnList as $turnItem){
|
||||
$turnIdx = $turnItem['turn_idx'];
|
||||
$turnTarget = iterator_to_array(Util::range($turnIdx+$turnCnt, GameConst::$maxTurn, $turnCnt));
|
||||
|
||||
$db->update('general_turn', [
|
||||
'action'=>$turnItem['action'],
|
||||
'arg'=>$turnItem['arg'],
|
||||
'brief'=>$turnItem['brief']
|
||||
], 'general_id=%i AND turn_idx IN %li', $generalId, $turnTarget);
|
||||
}
|
||||
}
|
||||
|
||||
function pushNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
|
||||
if($nationID == 0){
|
||||
return;
|
||||
}
|
||||
if($officerLevel < 5){
|
||||
return;
|
||||
}
|
||||
if($turnCnt == 0){
|
||||
return;
|
||||
}
|
||||
if($turnCnt < 0){
|
||||
pullNationCommand($nationID, $officerLevel, -$turnCnt);
|
||||
return;
|
||||
}
|
||||
if($turnCnt >= GameConst::$maxChiefTurn){
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$db->update('nation_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
|
||||
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx DESC', $nationID, $officerLevel);
|
||||
$db->update('nation_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxChiefTurn),
|
||||
'action'=>'휴식',
|
||||
'arg'=>'{}',
|
||||
'brief'=>'휴식'
|
||||
], 'nation_id=%i AND officer_level=%i AND turn_idx >= %i ORDER BY turn_idx ASC', $nationID, $officerLevel, GameConst::$maxChiefTurn);
|
||||
}
|
||||
|
||||
function pullNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
|
||||
if($nationID == 0){
|
||||
return;
|
||||
}
|
||||
if($officerLevel < 5){
|
||||
return;
|
||||
}
|
||||
if($turnCnt == 0){
|
||||
return;
|
||||
}
|
||||
if($turnCnt < 0){
|
||||
pushNationCommand($nationID, $officerLevel, -$turnCnt);
|
||||
return;
|
||||
}
|
||||
if($turnCnt >= GameConst::$maxChiefTurn){
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$db->update('nation_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxChiefTurn),
|
||||
'action'=>'휴식',
|
||||
'arg'=>'{}',
|
||||
'brief'=>'휴식',
|
||||
], 'nation_id=%i AND officer_level=%i AND turn_idx < %i', $nationID, $officerLevel, $turnCnt);
|
||||
$db->update('nation_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
|
||||
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx ASC', $nationID, $officerLevel);
|
||||
}
|
||||
|
||||
function _setGeneralCommand(GeneralCommand $command, array $turnList):void {
|
||||
if(!$turnList){
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$generalID = $command->getGeneral()->getID();
|
||||
$commandName = $command->getRawClassName();
|
||||
$arg = $command->getArg();
|
||||
$brief = $command->getBrief();
|
||||
|
||||
$db->update('general_turn', [
|
||||
'action'=>$commandName,
|
||||
'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
|
||||
'brief'=>$brief
|
||||
], 'general_id = %i AND turn_idx IN %li', $generalID, $turnList);
|
||||
}
|
||||
|
||||
function _setNationCommand(NationCommand $command, array $turnList):void {
|
||||
if(!$turnList){
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$nationID = $command->getNationID();
|
||||
$officerLevel = $command->getOfficerLevel();
|
||||
$commandName = $command->getRawClassName();
|
||||
$arg = $command->getArg();
|
||||
$brief = $command->getBrief();
|
||||
|
||||
$db->update('nation_turn', [
|
||||
'action'=>$commandName,
|
||||
'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
|
||||
'brief'=>$brief
|
||||
], 'nation_id = %i AND officer_level = %i AND turn_idx IN %li', $nationID, $officerLevel, $turnList);
|
||||
}
|
||||
|
||||
function sanitizeArg(?array $args):?array{
|
||||
if($args === null){
|
||||
return $args;
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach($args as $key=>$value){
|
||||
if(is_array($value)){
|
||||
$result[$key] = sanitizeArg($value);
|
||||
}
|
||||
else if(is_string($value)){
|
||||
$result[$key] = StringUtil::neutralize(StringUtil::removeSpecialCharacter($value));
|
||||
}
|
||||
else{
|
||||
$result[$key] = $value;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function checkCommandArg(?array $arg):?string{
|
||||
if($arg === null){
|
||||
return null;
|
||||
}
|
||||
$defaultCheck = [
|
||||
/*'string'=>[
|
||||
'nationName', 'optionText', 'itemType', 'nationType'
|
||||
],*/
|
||||
'integer'=>[
|
||||
'crewType', 'destGeneralID', 'destCityID', 'destNationID',
|
||||
'amount', 'colorType',
|
||||
'srcArmType', 'destArmType', //숙련전환 전용
|
||||
],
|
||||
'boolean'=>[
|
||||
'isGold', 'buyRice',
|
||||
],
|
||||
'between'=>[
|
||||
['month', [1, 12]]
|
||||
],
|
||||
'min'=>[
|
||||
['year', 0],
|
||||
['destGeneralID', 1],
|
||||
['destCityID', 1],
|
||||
['destNationID', 1],
|
||||
['amount', 1],
|
||||
['crewType', 0]
|
||||
],
|
||||
'integerArray'=>[
|
||||
'destNationIDList', 'destGeneralIDList', 'amountList'
|
||||
],
|
||||
'stringWidthBetween'=>[
|
||||
['nationName', 1, 18]
|
||||
]
|
||||
];
|
||||
$v = new Validator($arg);
|
||||
$v->rules($defaultCheck);
|
||||
if (!$v->validate()){
|
||||
return $v->errorStr();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function setGeneralCommand(int $generalID, array $rawTurnList, string $command, ?array $arg = null):array{
|
||||
|
||||
$turnList = [];
|
||||
foreach($rawTurnList as $turnIdx){
|
||||
if(!is_int($turnIdx) || $turnIdx < -3 || $turnIdx >= GameConst::$maxTurn){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx,
|
||||
'test'=>'turnIdx',
|
||||
'target'=>$turnIdx,
|
||||
];
|
||||
}
|
||||
if($turnIdx >= 0){
|
||||
$turnList[$turnIdx] = true;
|
||||
}
|
||||
else if($turnIdx == -1){
|
||||
//홀수
|
||||
foreach(Util::range(1, GameConst::$maxTurn, 2) as $subIdx){
|
||||
$turnList[$subIdx] = true;
|
||||
}
|
||||
}
|
||||
else if($turnIdx == -2){
|
||||
//짝수
|
||||
foreach(Util::range(0, GameConst::$maxTurn, 2) as $subIdx){
|
||||
$turnList[$subIdx] = true;
|
||||
}
|
||||
}
|
||||
else if($turnIdx == -3){
|
||||
//모두
|
||||
foreach(Util::range(GameConst::$maxTurn) as $subIdx){
|
||||
$turnList[$subIdx] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$turnList = array_keys($turnList);
|
||||
|
||||
$arg = sanitizeArg($arg);
|
||||
$argBasicTestResult = checkCommandArg($arg);
|
||||
if($argBasicTestResult !== null){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'턴이 입력되지 않았습니다.',
|
||||
'test'=>'checkCommandArg',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$env = $gameStor->getAll();
|
||||
$general = General::createGeneralObjFromDB($generalID);
|
||||
|
||||
try{
|
||||
$commandObj = buildGeneralCommandClass($command, $general, $env, $arg);
|
||||
}
|
||||
catch (\InvalidArgumentException $e){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>$e->getMessage(),
|
||||
'test'=>'build',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
catch (\Exception $e){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>$e->getCode().$e->getMessage(),
|
||||
'test'=>'build',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
|
||||
if(!$commandObj->isArgValid()){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 argument',
|
||||
'test'=>'isArgValid',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
|
||||
if(!$commandObj->hasPermissionToReserve()){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(),
|
||||
'test'=>'hasPermissionToReserve',
|
||||
'target'=>'command'
|
||||
];
|
||||
}
|
||||
|
||||
_setGeneralCommand($commandObj, $turnList);
|
||||
return [
|
||||
'result'=>true,
|
||||
'reason'=>'success'
|
||||
];
|
||||
}
|
||||
|
||||
function setNationCommand(int $generalID, array $turnList, string $command, ?array $arg = null):array{
|
||||
$turnList = array_unique($turnList);
|
||||
foreach($turnList as $turnIdx){
|
||||
if(!is_int($turnIdx) || $turnIdx < 0 || $turnIdx >= GameConst::$maxChiefTurn){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx,
|
||||
'test'=>'turnIdx',
|
||||
'target'=>$turnIdx,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$arg = sanitizeArg($arg);
|
||||
$argBasicTestResult = checkCommandArg($arg);
|
||||
if($argBasicTestResult !== null){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'턴이 입력되지 않았습니다.',
|
||||
'test'=>'checkCommandArg',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$env = $gameStor->getAll();
|
||||
$general = General::createGeneralObjFromDB($generalID);
|
||||
|
||||
if($general->getVar('officer_level') < 5){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'수뇌가 아닙니다'
|
||||
];
|
||||
}
|
||||
|
||||
try{
|
||||
$commandObj = buildNationCommandClass($command, $general, $env, $general->getLastTurn(), $arg);
|
||||
}
|
||||
catch (\InvalidArgumentException $e){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>$e->getMessage(),
|
||||
'test'=>'build',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
catch (\Exception $e){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>$e->getCode().$e->getMessage(),
|
||||
'test'=>'build',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
|
||||
if(!$commandObj->isArgValid()){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 argument',
|
||||
'test'=>'isArgValid',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
|
||||
if(!$commandObj->hasPermissionToReserve()){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(),
|
||||
'test'=>'hasPermissionToReserve',
|
||||
'target'=>'command'
|
||||
];
|
||||
}
|
||||
|
||||
_setNationCommand($commandObj, $turnList);
|
||||
return [
|
||||
'result'=>true,
|
||||
'arg_test'=>true,
|
||||
'reason'=>'success'
|
||||
];
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
use sammo\Command\GeneralCommand;
|
||||
use sammo\Command\NationCommand;
|
||||
|
||||
function getGeneralTurnBrief(General $generalObj, array $turnList) {
|
||||
$result = [];
|
||||
|
||||
foreach($turnList as $turnIdx => [$action, $arg]){
|
||||
$commandObj = buildGeneralCommandClass($action, $generalObj, [], $arg);
|
||||
$turnText = $commandObj->getBrief();
|
||||
$result[$turnIdx] = $turnText;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function getNationTurnBrief(General $generalObj, array $turnList) {
|
||||
$result = [];
|
||||
|
||||
$tmpTurn = new LastTurn();
|
||||
foreach($turnList as $turnIdx => [$action, $arg]){
|
||||
$commandObj = buildNationCommandClass($action, $generalObj, [], $tmpTurn, $arg);
|
||||
$turnText = $commandObj->getBrief();
|
||||
$result[$turnIdx] = $turnText;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function pushGeneralCommand(int $generalID, int $turnCnt=1){
|
||||
if($turnCnt == 0){
|
||||
return;
|
||||
}
|
||||
if($turnCnt < 0){
|
||||
pullGeneralCommand($generalID, -$turnCnt);
|
||||
return;
|
||||
}
|
||||
if($turnCnt >= GameConst::$maxTurn){
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$db->update('general_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
|
||||
], 'general_id=%i ORDER BY turn_idx DESC', $generalID);
|
||||
$db->update('general_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxTurn),
|
||||
'action'=>'휴식',
|
||||
'arg'=>'{}',
|
||||
'brief'=>'휴식'
|
||||
], 'general_id=%i AND turn_idx >= %i', $generalID, GameConst::$maxTurn);
|
||||
}
|
||||
|
||||
function pullGeneralCommand(int $generalID, int $turnCnt=1){
|
||||
if($turnCnt == 0){
|
||||
return;
|
||||
}
|
||||
if($turnCnt < 0){
|
||||
pushGeneralCommand($generalID, -$turnCnt);
|
||||
return;
|
||||
}
|
||||
if($turnCnt >= GameConst::$maxTurn){
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$db->update('general_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxTurn),
|
||||
'action'=>'휴식',
|
||||
'arg'=>'{}',
|
||||
'brief'=>'휴식'
|
||||
], 'general_id=%i AND turn_idx < %i', $generalID, $turnCnt);
|
||||
$db->update('general_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
|
||||
], 'general_id=%i ORDER BY turn_idx ASC', $generalID);
|
||||
}
|
||||
|
||||
function repeatGeneralCommand(int $generalId, int $turnCnt){
|
||||
if($turnCnt <= 0){
|
||||
return;
|
||||
}
|
||||
if($turnCnt >= GameConst::$maxTurn){
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$reqTurn = $turnCnt;
|
||||
if($turnCnt * 2 > GameConst::$maxTurn){
|
||||
$reqTurn = GameConst::$maxTurn - $turnCnt;
|
||||
}
|
||||
|
||||
$turnList = $db->query('SELECT turn_idx, `action`, arg, brief FROM general_turn WHERE general_id=%i AND turn_idx < %i', $generalId, $reqTurn);
|
||||
foreach($turnList as $turnItem){
|
||||
$turnIdx = $turnItem['turn_idx'];
|
||||
$turnTarget = iterator_to_array(Util::range($turnIdx+$turnCnt, GameConst::$maxTurn, $turnCnt));
|
||||
|
||||
$db->update('general_turn', [
|
||||
'action'=>$turnItem['action'],
|
||||
'arg'=>$turnItem['arg'],
|
||||
'brief'=>$turnItem['brief']
|
||||
], 'general_id=%i AND turn_idx IN %li', $generalId, $turnTarget);
|
||||
}
|
||||
}
|
||||
|
||||
function pushNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
|
||||
if($nationID == 0){
|
||||
return;
|
||||
}
|
||||
if($officerLevel < 5){
|
||||
return;
|
||||
}
|
||||
if($turnCnt == 0){
|
||||
return;
|
||||
}
|
||||
if($turnCnt < 0){
|
||||
pullNationCommand($nationID, $officerLevel, -$turnCnt);
|
||||
return;
|
||||
}
|
||||
if($turnCnt >= GameConst::$maxChiefTurn){
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$db->update('nation_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
|
||||
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx DESC', $nationID, $officerLevel);
|
||||
$db->update('nation_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxChiefTurn),
|
||||
'action'=>'휴식',
|
||||
'arg'=>'{}',
|
||||
'brief'=>'휴식'
|
||||
], 'nation_id=%i AND officer_level=%i AND turn_idx >= %i ORDER BY turn_idx ASC', $nationID, $officerLevel, GameConst::$maxChiefTurn);
|
||||
}
|
||||
|
||||
function pullNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
|
||||
if($nationID == 0){
|
||||
return;
|
||||
}
|
||||
if($officerLevel < 5){
|
||||
return;
|
||||
}
|
||||
if($turnCnt == 0){
|
||||
return;
|
||||
}
|
||||
if($turnCnt < 0){
|
||||
pushNationCommand($nationID, $officerLevel, -$turnCnt);
|
||||
return;
|
||||
}
|
||||
if($turnCnt >= GameConst::$maxChiefTurn){
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$db->update('nation_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxChiefTurn),
|
||||
'action'=>'휴식',
|
||||
'arg'=>'{}',
|
||||
'brief'=>'휴식',
|
||||
], 'nation_id=%i AND officer_level=%i AND turn_idx < %i', $nationID, $officerLevel, $turnCnt);
|
||||
$db->update('nation_turn', [
|
||||
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
|
||||
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx ASC', $nationID, $officerLevel);
|
||||
}
|
||||
|
||||
function _setGeneralCommand(GeneralCommand $command, array $turnList):void {
|
||||
if(!$turnList){
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$generalID = $command->getGeneral()->getID();
|
||||
$commandName = $command->getRawClassName();
|
||||
$arg = $command->getArg();
|
||||
$brief = $command->getBrief();
|
||||
|
||||
$db->update('general_turn', [
|
||||
'action'=>$commandName,
|
||||
'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
|
||||
'brief'=>$brief
|
||||
], 'general_id = %i AND turn_idx IN %li', $generalID, $turnList);
|
||||
}
|
||||
|
||||
function _setNationCommand(NationCommand $command, array $turnList):void {
|
||||
if(!$turnList){
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$nationID = $command->getNationID();
|
||||
$officerLevel = $command->getOfficerLevel();
|
||||
$commandName = $command->getRawClassName();
|
||||
$arg = $command->getArg();
|
||||
$brief = $command->getBrief();
|
||||
|
||||
$db->update('nation_turn', [
|
||||
'action'=>$commandName,
|
||||
'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
|
||||
'brief'=>$brief
|
||||
], 'nation_id = %i AND officer_level = %i AND turn_idx IN %li', $nationID, $officerLevel, $turnList);
|
||||
}
|
||||
|
||||
function sanitizeArg(?array $args):?array{
|
||||
if($args === null){
|
||||
return $args;
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach($args as $key=>$value){
|
||||
if(is_array($value)){
|
||||
$result[$key] = sanitizeArg($value);
|
||||
}
|
||||
else if(is_string($value)){
|
||||
$result[$key] = StringUtil::neutralize(StringUtil::removeSpecialCharacter($value));
|
||||
}
|
||||
else{
|
||||
$result[$key] = $value;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function checkCommandArg(?array $arg):?string{
|
||||
if($arg === null){
|
||||
return null;
|
||||
}
|
||||
$defaultCheck = [
|
||||
/*'string'=>[
|
||||
'nationName', 'optionText', 'itemType', 'nationType', 'commandType',
|
||||
],*/
|
||||
'integer'=>[
|
||||
'crewType', 'destGeneralID', 'destCityID', 'destNationID',
|
||||
'amount', 'colorType',
|
||||
'srcArmType', 'destArmType', //숙련전환 전용
|
||||
],
|
||||
'boolean'=>[
|
||||
'isGold', 'buyRice',
|
||||
],
|
||||
'between'=>[
|
||||
['month', [1, 12]]
|
||||
],
|
||||
'min'=>[
|
||||
['year', 0],
|
||||
['destGeneralID', 1],
|
||||
['destCityID', 1],
|
||||
['destNationID', 1],
|
||||
['amount', 1],
|
||||
['crewType', 0]
|
||||
],
|
||||
'integerArray'=>[
|
||||
'destNationIDList', 'destGeneralIDList', 'amountList'
|
||||
],
|
||||
'stringWidthBetween'=>[
|
||||
['nationName', 1, 18]
|
||||
]
|
||||
];
|
||||
$v = new Validator($arg);
|
||||
$v->rules($defaultCheck);
|
||||
if (!$v->validate()){
|
||||
return $v->errorStr();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function setGeneralCommand(int $generalID, array $rawTurnList, string $command, ?array $arg = null):array{
|
||||
|
||||
$turnList = [];
|
||||
foreach($rawTurnList as $turnIdx){
|
||||
if(!is_int($turnIdx) || $turnIdx < -3 || $turnIdx >= GameConst::$maxTurn){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx,
|
||||
'test'=>'turnIdx',
|
||||
'target'=>$turnIdx,
|
||||
];
|
||||
}
|
||||
if($turnIdx >= 0){
|
||||
$turnList[$turnIdx] = true;
|
||||
}
|
||||
else if($turnIdx == -1){
|
||||
//홀수, 0부터 맞다.
|
||||
foreach(Util::range(0, GameConst::$maxTurn, 2) as $subIdx){
|
||||
$turnList[$subIdx] = true;
|
||||
}
|
||||
}
|
||||
else if($turnIdx == -2){
|
||||
//짝수, 1부터 맞다.
|
||||
foreach(Util::range(1, GameConst::$maxTurn, 2) as $subIdx){
|
||||
$turnList[$subIdx] = true;
|
||||
}
|
||||
}
|
||||
else if($turnIdx == -3){
|
||||
//모두
|
||||
foreach(Util::range(GameConst::$maxTurn) as $subIdx){
|
||||
$turnList[$subIdx] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$turnList = array_keys($turnList);
|
||||
|
||||
$arg = sanitizeArg($arg);
|
||||
$argBasicTestResult = checkCommandArg($arg);
|
||||
if($argBasicTestResult !== null){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'턴이 입력되지 않았습니다.',
|
||||
'test'=>'checkCommandArg',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$env = $gameStor->getAll();
|
||||
$general = General::createGeneralObjFromDB($generalID);
|
||||
|
||||
try{
|
||||
$commandObj = buildGeneralCommandClass($command, $general, $env, $arg);
|
||||
}
|
||||
catch (\InvalidArgumentException $e){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>$e->getMessage(),
|
||||
'test'=>'build',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
catch (\Exception $e){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>$e->getCode().$e->getMessage(),
|
||||
'test'=>'build',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
|
||||
if(!$commandObj->isArgValid()){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 argument',
|
||||
'test'=>'isArgValid',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
|
||||
if(!$commandObj->hasPermissionToReserve()){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(),
|
||||
'test'=>'hasPermissionToReserve',
|
||||
'target'=>'command'
|
||||
];
|
||||
}
|
||||
|
||||
_setGeneralCommand($commandObj, $turnList);
|
||||
return [
|
||||
'result'=>true,
|
||||
'reason'=>'success'
|
||||
];
|
||||
}
|
||||
|
||||
function setNationCommand(int $generalID, array $turnList, string $command, ?array $arg = null):array{
|
||||
$turnList = array_unique($turnList);
|
||||
foreach($turnList as $turnIdx){
|
||||
if(!is_int($turnIdx) || $turnIdx < 0 || $turnIdx >= GameConst::$maxChiefTurn){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx,
|
||||
'test'=>'turnIdx',
|
||||
'target'=>$turnIdx,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$arg = sanitizeArg($arg);
|
||||
$argBasicTestResult = checkCommandArg($arg);
|
||||
if($argBasicTestResult !== null){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'턴이 입력되지 않았습니다.',
|
||||
'test'=>'checkCommandArg',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$env = $gameStor->getAll();
|
||||
$general = General::createGeneralObjFromDB($generalID);
|
||||
|
||||
if($general->getVar('officer_level') < 5){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'수뇌가 아닙니다'
|
||||
];
|
||||
}
|
||||
|
||||
try{
|
||||
$commandObj = buildNationCommandClass($command, $general, $env, $general->getLastTurn(), $arg);
|
||||
}
|
||||
catch (\InvalidArgumentException $e){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>$e->getMessage(),
|
||||
'test'=>'build',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
catch (\Exception $e){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>$e->getCode().$e->getMessage(),
|
||||
'test'=>'build',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
|
||||
if(!$commandObj->isArgValid()){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 argument',
|
||||
'test'=>'isArgValid',
|
||||
'target'=>'arg'
|
||||
];
|
||||
}
|
||||
|
||||
if(!$commandObj->hasPermissionToReserve()){
|
||||
return [
|
||||
'result'=>false,
|
||||
'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(),
|
||||
'test'=>'hasPermissionToReserve',
|
||||
'target'=>'command'
|
||||
];
|
||||
}
|
||||
|
||||
_setNationCommand($commandObj, $turnList);
|
||||
return [
|
||||
'result'=>true,
|
||||
'arg_test'=>true,
|
||||
'reason'=>'success'
|
||||
];
|
||||
}
|
||||
+1139
-1138
@@ -1,1138 +1,1139 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* 게임 룰에 해당하는 함수 모음
|
||||
*/
|
||||
|
||||
function getNationLevelList(): array
|
||||
{
|
||||
$table = [
|
||||
0 => ['방랑군', 2, 0],
|
||||
1 => ['호족', 2, 1],
|
||||
2 => ['군벌', 4, 2],
|
||||
3 => ['주자사', 4, 5],
|
||||
4 => ['주목', 6, 8],
|
||||
5 => ['공', 6, 11],
|
||||
6 => ['왕', 8, 16],
|
||||
7 => ['황제', 8, 21],
|
||||
];
|
||||
return $table;
|
||||
}
|
||||
|
||||
function getCityLevelList(): array
|
||||
{
|
||||
return [
|
||||
1 => '수',
|
||||
2 => '진',
|
||||
3 => '관',
|
||||
4 => '이',
|
||||
5 => '소',
|
||||
6 => '중',
|
||||
7 => '대',
|
||||
8 => '특'
|
||||
];
|
||||
}
|
||||
|
||||
//한국가의 전체 전방 설정
|
||||
function SetNationFront($nationNo)
|
||||
{
|
||||
if (!$nationNo) {
|
||||
return;
|
||||
}
|
||||
// 도시소유 국가와 선포,교전중인 국가
|
||||
|
||||
$adj3 = [];
|
||||
$adj2 = [];
|
||||
$adj1 = [];
|
||||
|
||||
$db = DB::db();
|
||||
foreach ($db->queryFirstColumn(
|
||||
'SELECT city FROM city JOIN diplomacy ON diplomacy.you = city.nation WHERE diplomacy.state = 0 AND me = %i',
|
||||
$nationNo
|
||||
) as $city) {
|
||||
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
|
||||
$adj3[$adjKey] = $adjVal;
|
||||
}
|
||||
};
|
||||
foreach ($db->queryFirstColumn(
|
||||
'SELECT city FROM city JOIN diplomacy ON diplomacy.you = city.nation WHERE diplomacy.state = 1 AND diplomacy.term <= 5 AND me = %i',
|
||||
$nationNo
|
||||
) as $city) {
|
||||
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
|
||||
$adj1[$adjKey] = $adjVal;
|
||||
}
|
||||
}
|
||||
if (!$adj3 && !$adj1) {
|
||||
//평시이면 공백지
|
||||
//NOTE: if, else일 경우 NPC는 전쟁시에는 공백지로 출병하지 않는다는 뜻이 된다.
|
||||
foreach ($db->queryFirstColumn('SELECT city from city where nation=0') as $city) {
|
||||
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
|
||||
$adj2[$adjKey] = $adjVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$db->update('city', [
|
||||
'front' => 0
|
||||
], 'nation=%i', $nationNo);
|
||||
|
||||
if ($adj1) {
|
||||
$db->update('city', [
|
||||
'front' => 1,
|
||||
], 'nation=%i and city in %li', $nationNo, array_keys($adj1));
|
||||
}
|
||||
if ($adj2) {
|
||||
$db->update('city', [
|
||||
'front' => 2,
|
||||
], 'nation=%i and city in %li', $nationNo, array_keys($adj2));
|
||||
}
|
||||
if ($adj3) {
|
||||
$db->update('city', [
|
||||
'front' => 3,
|
||||
], 'nation=%i and city in %li', $nationNo, array_keys($adj3));
|
||||
}
|
||||
}
|
||||
|
||||
function checkSupply()
|
||||
{
|
||||
$db = DB::db();
|
||||
|
||||
$cities = [];
|
||||
foreach ($db->query('SELECT city, nation FROM city WHERE nation != 0') as $city) {
|
||||
$newCity = new \stdClass();
|
||||
$newCity->id = Util::toInt($city['city']);
|
||||
$newCity->nation = Util::toInt($city['nation']);
|
||||
$newCity->supply = false;
|
||||
|
||||
$cities[$newCity->id] = $newCity;
|
||||
}
|
||||
|
||||
$queue = new \SplQueue();
|
||||
foreach ($db->queryAllLists('SELECT capital, nation FROM nation WHERE `level` > 0') as list($capitalID, $nationID)) {
|
||||
if (!key_exists($capitalID, $cities)) {
|
||||
continue;
|
||||
}
|
||||
$city = $cities[$capitalID];
|
||||
if ($nationID != $city->nation) {
|
||||
continue;
|
||||
}
|
||||
$city->supply = true;
|
||||
$queue->enqueue($city);
|
||||
}
|
||||
|
||||
while (!$queue->isEmpty()) {
|
||||
$cityLink = $queue->dequeue();
|
||||
$city = CityConst::byID($cityLink->id);
|
||||
|
||||
foreach (array_keys($city->path) as $connCityID) {
|
||||
if (!key_exists($connCityID, $cities)) {
|
||||
continue;
|
||||
}
|
||||
$connCity = $cities[$connCityID];
|
||||
if ($connCity->nation != $cityLink->nation) {
|
||||
continue;
|
||||
}
|
||||
if ($connCity->supply) {
|
||||
continue;
|
||||
}
|
||||
$connCity->supply = true;
|
||||
$queue->enqueue($connCity);
|
||||
}
|
||||
}
|
||||
|
||||
$db->update('city', [
|
||||
'supply' => 1
|
||||
], 'nation=0');
|
||||
|
||||
$db->update('city', [
|
||||
'supply' => 0
|
||||
], 'nation!=0');
|
||||
|
||||
$supply = [];
|
||||
|
||||
foreach ($cities as $city) {
|
||||
if ($city->supply) {
|
||||
$supply[] = $city->id;
|
||||
}
|
||||
}
|
||||
|
||||
if ($supply) {
|
||||
$db->update('city', [
|
||||
'supply' => 1
|
||||
], 'city IN %li', $supply);
|
||||
}
|
||||
}
|
||||
|
||||
function updateGeneralNumber(){
|
||||
$db = DB::db();
|
||||
foreach($db->queryAllLists('SELECT nation, count(*) FROM general WHERE npc != 5 GROUP BY nation') as [$nationID, $gennum]){
|
||||
if($nationID === 0){
|
||||
continue;
|
||||
}
|
||||
$db->update('nation', [
|
||||
'gennum'=>$gennum
|
||||
], 'nation=%i', $nationID);
|
||||
}
|
||||
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달마다 실행, 병사 있는 장수의 군량 감소, 수입비율 조정
|
||||
function preUpdateMonthly()
|
||||
{
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
//연감 월결산
|
||||
$result = LogHistory();
|
||||
|
||||
if ($result == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$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
|
||||
$db->update('general', [
|
||||
'connect' => $db->sqleval('floor(connect*0.99)'),
|
||||
'makelimit' => $db->sqleval('greatest(0, makelimit - 1)'),
|
||||
], true);
|
||||
//전략제한-1, 외교제한-1, 세율동기화
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $db->sqleval('greatest(0, strategic_cmd_limit - 1)'),
|
||||
'surlimit' => $db->sqleval('greatest(0, surlimit - 1)'),
|
||||
'rate_tmp' => $db->sqleval('rate')
|
||||
], true);
|
||||
|
||||
//도시훈사 180년 60, 220년 87, 240년 100
|
||||
$rate = Util::round(($admin['year'] - $admin['startyear']) / 1.5) + 60;
|
||||
if ($rate > 100) $rate = 100;
|
||||
|
||||
// 20 ~ 140원
|
||||
$develcost = ($admin['year'] - $admin['startyear'] + 10) * 2;
|
||||
$gameStor->city_rate = $rate;
|
||||
$gameStor->develcost = $develcost;
|
||||
|
||||
//매달 사망자 수입 결산
|
||||
processWarIncome();
|
||||
|
||||
//계략, 전쟁표시 해제
|
||||
$db->update('city', [
|
||||
'state' => $db->sqleval(<<<EOD
|
||||
(CASE
|
||||
WHEN state=31 THEN 0
|
||||
WHEN state=32 THEN 31
|
||||
WHEN state=33 THEN 0
|
||||
WHEN state=34 THEN 33
|
||||
WHEN state=41 THEN 0
|
||||
WHEN state=42 THEN 41
|
||||
WHEN state=43 THEN 42
|
||||
ELSE state END)
|
||||
EOD),
|
||||
'term' => $db->sqleval('greatest(0, term - 1)'),
|
||||
'conflict' => $db->sqleval('if(term = 0,%s,conflict)', '{}'),
|
||||
], true);
|
||||
|
||||
//첩보-1
|
||||
foreach ($db->queryAllLists("SELECT nation, spy FROM nation WHERE spy!='' AND spy!='{}'") as [$nationNo, $rawSpy]) {
|
||||
$spyInfo = Json::decode($rawSpy);
|
||||
|
||||
foreach ($spyInfo as $cityNo => $remainMonth) {
|
||||
if ($remainMonth <= 1) {
|
||||
unset($spyInfo[$cityNo]);
|
||||
} else {
|
||||
$spyInfo[$cityNo] -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
$db->update('nation', [
|
||||
'spy' => Json::encode($spyInfo, Json::EMPTY_ARRAY_IS_DICT)
|
||||
], 'nation=%i', $nationNo);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 외교 로그처리, 외교 상태 처리
|
||||
function postUpdateMonthly()
|
||||
{
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
$admin = $gameStor->getValues(['startyear', 'year', 'month', 'scenario']);
|
||||
$globalLogger = new ActionLogger(0, 0, $admin['year'], $admin['month']);
|
||||
|
||||
//도시 수 측정
|
||||
$cityNations = [];
|
||||
foreach ($db->queryAllLists('SELECT city, name, nation FROM city') as [$cityID, $cityName, $cityNation]) {
|
||||
if (!key_exists($cityNation, $cityNations)) {
|
||||
$cityNations[$cityNation] = [];
|
||||
}
|
||||
$cityNations[$cityNation][] = $cityName;
|
||||
}
|
||||
|
||||
//각 국가 전월 장수수 대비 당월 장수수로 단합도 산정
|
||||
//각 국가 장수수를 구하고 국력 산정
|
||||
// $query = "select nation,gennum from nation where level>0";
|
||||
// 국력=
|
||||
// 자원(국가/장수의 금,쌀)
|
||||
// 기술력
|
||||
// 인구수*내정%
|
||||
// 장수능력
|
||||
// 접속률
|
||||
// 숙련도
|
||||
// 명성,공헌
|
||||
$nations = Util::convertArrayToDict($db->query('SELECT
|
||||
A.nation,
|
||||
A.gennum,
|
||||
round((
|
||||
round(((A.gold+A.rice)+(select sum(gold+rice) from general where nation=A.nation))/100)
|
||||
+A.tech
|
||||
+if(A.level=0,0,(
|
||||
select round(
|
||||
sum(pop)*sum(pop+agri+comm+secu+wall+def)/sum(pop_max+agri_max+comm_max+secu_max+wall_max+def_max)/100
|
||||
) from city where nation=A.nation and supply=1
|
||||
))
|
||||
+(select sum(leadership+strength+intel) 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(avg(connect)) from general where nation=A.nation)
|
||||
)/10)
|
||||
as power,
|
||||
(select sum(crew) from general where nation=A.nation) as totalCrew
|
||||
from nation A
|
||||
group by A.nation'), 'nation');
|
||||
$maxPowerValues = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'max_power');
|
||||
|
||||
foreach ($nations as $nation) {
|
||||
$nationID = $nation['nation'];
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
$genNum[$nationID] = $nation['gennum'];
|
||||
|
||||
$powerValues = $maxPowerValues[$nationID]??[];
|
||||
|
||||
//약간의 랜덤치 부여 (95% ~ 105%)
|
||||
|
||||
$nation['power'] = Util::round($nation['power'] * (rand() % 101 + 950) / 1000);
|
||||
$powerValues['maxPower'] = max($powerValues['maxPower'] ?? 0, $nation['power']);
|
||||
$powerValues['maxCrew'] = max($powerValues['maxCrew'] ?? 0, Util::toInt($nation['totalCrew']));
|
||||
|
||||
if (count($cityNations[$nationID] ?? []) > count($powerValues['maxCities'] ?? [])) {
|
||||
$powerValues['maxCities'] = $cityNations[$nationID];
|
||||
}
|
||||
|
||||
$db->update('nation', [
|
||||
'power' => $nation['power']
|
||||
], 'nation=%i', $nationID);
|
||||
$nationStor->max_power = $powerValues;
|
||||
}
|
||||
|
||||
// 전쟁기한 세팅
|
||||
foreach($db->query('SELECT me, you, dead, term FROM diplomacy WHERE state = 0') as $dip) {
|
||||
$genCount = $genNum[$dip['me']];
|
||||
// 25% 참여율일때 두당 10턴에 4000명 소모한다고 계산
|
||||
// 4000 / 10 * 0.25 = 100
|
||||
$term = floor($dip['dead'] / 100 / $genCount);
|
||||
$dip['dead'] -= $term * 100 * $genCount;
|
||||
$term = Util::valueFit($dip['term'] + $term, 0, 13);
|
||||
|
||||
$db->update('diplomacy', [
|
||||
'term' => $term,
|
||||
'dead' => $dip['dead'],
|
||||
], 'me = %i AND you = %i', $dip['me'], $dip['you']);
|
||||
}
|
||||
|
||||
//개전국 로그
|
||||
foreach($db->query('SELECT me, you FROM diplomacy WHERE state = 1 AND term <= 1 AND me < you') as $dip){
|
||||
$nation1 = getNationStaticInfo($dip['me']);
|
||||
$name1 = $nation1['name'];
|
||||
$nation2 = getNationStaticInfo($dip['you']);
|
||||
$name2 = $nation2['name'];
|
||||
|
||||
$josaYi = JosaUtil::pick($name2, '이');
|
||||
$josaWa = JosaUtil::pick($name1, '와');
|
||||
$globalLogger->pushGlobalHistoryLog("<R><b>【개전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <R>전쟁</>을 시작합니다.");
|
||||
}
|
||||
//휴전국 로그
|
||||
$stopWarList = [];
|
||||
foreach($db->queryAllLists('SELECT me,you FROM diplomacy WHERE state=0 AND term <= 1 ORDER BY me desc, you desc') as [$me, $you]){
|
||||
if($me < $you){
|
||||
$key = "{$me}_{$you}";
|
||||
}
|
||||
else{
|
||||
$key = "{$you}_{$me}";
|
||||
}
|
||||
if(!key_exists($key, $stopWarList)){
|
||||
$stopWarList[$key] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
//양측 기간 모두 0이 되는 상황이면 휴전
|
||||
$nation1 = getNationStaticInfo($me);
|
||||
$name1 = $nation1['name'];
|
||||
$nation2 = getNationStaticInfo($you);
|
||||
$name2 = $nation2['name'];
|
||||
|
||||
$josaWa = JosaUtil::pick($name1, '와');
|
||||
$josaYi = JosaUtil::pick($name2, '이');
|
||||
|
||||
$globalLogger->pushGlobalHistoryLog("<R><b>【휴전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <S>휴전</>합니다.");
|
||||
$db->update('diplomacy', [
|
||||
'state'=>2,
|
||||
'term'=>0,
|
||||
], '(me=%i AND you=%i) OR (you=%i AND me=%i)', $me, $you, $me, $you);
|
||||
}
|
||||
|
||||
$globalLogger->flush();
|
||||
|
||||
//사상자 초기화, 외교 기한-1
|
||||
$db->update('diplomacy', [
|
||||
'dead'=>$db->sqleval('if(state!=0, 0, dead)'),
|
||||
'term'=>$db->sqleval('greatest(0, term-1)'),
|
||||
], true);
|
||||
//불가침 끝나면 통상으로
|
||||
$db->update('diplomacy', [
|
||||
'state'=>2,
|
||||
], 'state = 7 AND term = 0');
|
||||
//선포 끝나면 교전으로
|
||||
$db->update('diplomacy', [
|
||||
'state'=>0,
|
||||
'term'=>6,
|
||||
], 'state = 1 AND term = 0');
|
||||
|
||||
//초반이후 방랑군 자동 해체
|
||||
if ($admin['year'] >= $admin['startyear'] + 2) {
|
||||
checkWander();
|
||||
}
|
||||
// 작위 업데이트
|
||||
updateNationState();
|
||||
updateGeneralNumber();
|
||||
refreshNationStaticInfo();
|
||||
// 천통여부 검사
|
||||
checkEmperior();
|
||||
//토너먼트 개시
|
||||
triggerTournament();
|
||||
// 시스템 거래건 등록
|
||||
registerAuction();
|
||||
//전방설정
|
||||
foreach (getAllNationStaticInfo() as $nation) {
|
||||
if ($nation['level'] <= 0) {
|
||||
continue;
|
||||
}
|
||||
SetNationFront($nation['nation']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function checkWander()
|
||||
{
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
$admin = $gameStor->getValues(['year', 'month']);
|
||||
|
||||
$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::createGeneralObjListFromDB($wanderers) as $wanderer) {
|
||||
$wanderCmd = buildGeneralCommandClass('che_해산', $wanderer, $admin);
|
||||
if ($wanderCmd->hasFullConditionMet()) {
|
||||
$logger = $wanderer->getLogger();
|
||||
$logger->pushGeneralActionLog('초반 제한후 방랑군은 자동 해산됩니다.', ActionLogger::PLAIN);
|
||||
$wanderCmd->run();
|
||||
}
|
||||
}
|
||||
|
||||
if ($wanderers) {
|
||||
refreshNationStaticInfo();
|
||||
}
|
||||
}
|
||||
|
||||
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']);
|
||||
|
||||
$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이 진관수이소중대특 체계를 벗어날 수 있음
|
||||
$citycount = $db->queryFirstField('SELECT count(*) FROM city WHERE nation=%i AND level>=4', $nation['nation']);
|
||||
|
||||
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>●</>{$admin['year']}년 {$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭하였습니다.";
|
||||
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}년 {$admin['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>●</>{$admin['year']}년 {$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극하였습니다.";
|
||||
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}년 {$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극"]);
|
||||
break;
|
||||
case 5:
|
||||
case 4:
|
||||
case 3:
|
||||
$history[] = "<C>●</>{$admin['year']}년 {$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명되었습니다.";
|
||||
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}년 {$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명됨"]);
|
||||
break;
|
||||
case 2:
|
||||
$history[] = "<C>●</>{$admin['year']}년 {$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 독립하여 <Y>" . getNationLevel($nationlevel) . "</>로 나섰습니다.";
|
||||
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}년 {$admin['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'], 2);
|
||||
|
||||
$uniqueLotteryWeightList = [];
|
||||
foreach ($nationGenList as $nationGen) {
|
||||
$hasUnique = false;
|
||||
foreach ($nationGen->getItems() as $item) {
|
||||
if (!$item->isBuyable()) {
|
||||
$hasUnique = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($hasUnique) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$score = $nationGen->getVar('belong') + 5;
|
||||
|
||||
if ($nationGen->getVar('officer_level') == 12) {
|
||||
$score += 200; //NOTE: 꼬우면 군주하세요.
|
||||
} else if ($nationGen->getVar('officer_level') == 11) {
|
||||
$score += 70;
|
||||
} else if ($nationGen->getVar('officer_level') > 4) {
|
||||
$score += 35;
|
||||
}
|
||||
$uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score];
|
||||
}
|
||||
|
||||
foreach (Util::range($levelDiff) as $idx) {
|
||||
if (!$uniqueLotteryWeightList) {
|
||||
break;
|
||||
}
|
||||
|
||||
/** @var General */
|
||||
$winnerObj = Util::choiceRandomUsingWeightPair($uniqueLotteryWeightList);
|
||||
unset($uniqueLotteryWeightList[$winnerObj->getID()]);
|
||||
giveRandomUniqueItem($winnerObj, '작위보상');
|
||||
$winnerObj->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;
|
||||
|
||||
while ($assemblerCnt < $maxAssemblerCnt) {
|
||||
$lastAssemblerID += 1;
|
||||
$npcObj = new Scenario\NPC(
|
||||
999,
|
||||
sprintf('부대장%4d', $lastAssemblerID),
|
||||
null,
|
||||
$nation['nation'],
|
||||
null,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
1,
|
||||
$admin['year'] - 15,
|
||||
$admin['year'] + 15,
|
||||
'은둔',
|
||||
'척사'
|
||||
);
|
||||
$npcObj->killturn = 70;
|
||||
$npcObj->gold = 0;
|
||||
$npcObj->rice = 0;
|
||||
$npcObj->npc = 5;
|
||||
$npcObj->build($admin);
|
||||
$npcID = $npcObj->generalID;
|
||||
|
||||
$db->insert('troop', [
|
||||
'troop_leader' => $npcID,
|
||||
'name' => $npcObj->realName,
|
||||
'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()
|
||||
{
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
$admin = $gameStor->getValues(['year', 'month']);
|
||||
|
||||
$nationHists = [];
|
||||
$specialHists = [];
|
||||
$personalHists = [];
|
||||
$specialHists2 = [];
|
||||
$crewtypeHists = [];
|
||||
|
||||
$etc = '';
|
||||
|
||||
$auxData = [
|
||||
'generals' => [],
|
||||
'nations' => [],
|
||||
];
|
||||
|
||||
$avgGeneral = $db->queryFirstRow(
|
||||
'SELECT avg(gold) as avggold, avg(rice) as avgrice, avg(dex1+dex2+dex3+dex4) as avgdex,
|
||||
max(dex1+dex2+dex3+dex4) as maxdex, avg(experience+dedication) as avgexpded, max(experience+dedication) as maxexpded
|
||||
FROM general'
|
||||
);
|
||||
$auxData['generals']['avg'] = $avgGeneral;
|
||||
|
||||
$avgGeneral['avggold'] = Util::round($avgGeneral['avggold']);
|
||||
$avgGeneral['avgrice'] = Util::round($avgGeneral['avgrice']);
|
||||
$avgGeneral['avgdex'] = Util::round($avgGeneral['avgdex']);
|
||||
$avgGeneral['avgexpded'] = Util::round($avgGeneral['avgexpded']);
|
||||
$etc .= "평균 금/쌀 ({$avgGeneral['avggold']}/{$avgGeneral['avgrice']}), 평균/최고 숙련({$avgGeneral['avgdex']}/{$avgGeneral['maxdex']}), 평균/최고 경험공헌({$avgGeneral['avgexpded']}/{$avgGeneral['maxexpded']}), ";
|
||||
|
||||
$avgNation = $db->queryFirstRow(
|
||||
'SELECT min(tech) as mintech, max(tech) as maxtech, avg(tech) as avgtech,
|
||||
min(power) as minpower, max(power) as maxpower, avg(power) as avgpower from nation where level>0'
|
||||
);
|
||||
$auxData['nations']['avg'] = $avgNation;
|
||||
|
||||
$avgNation['mintech'] = floor($avgNation['mintech']);
|
||||
$avgNation['maxtech'] = floor($avgNation['maxtech']);
|
||||
$avgNation['avgtech'] = Util::round($avgNation['avgtech']);
|
||||
$avgNation['avgpower'] = Util::round($avgNation['avgpower']);
|
||||
$etc .= "최저/평균/최고 기술({$avgNation['mintech']}/{$avgNation['avgtech']}/{$avgNation['maxtech']}), ";
|
||||
$etc .= "최저/평균/최고 국력({$avgNation['minpower']}/{$avgNation['avgpower']}/{$avgNation['maxpower']}), ";
|
||||
|
||||
$nationName = '';
|
||||
$powerHist = '';
|
||||
|
||||
$nations = Util::convertArrayToDict(
|
||||
$db->query(
|
||||
'SELECT nation,name,type,power,gennum,gold+rice as goldrice from nation where level>0 order by power desc',
|
||||
'nation'
|
||||
),
|
||||
'nation'
|
||||
);
|
||||
$nationCount = count($nations);
|
||||
|
||||
$nationGeneralInfos = Util::convertArrayToDict(
|
||||
$db->query(
|
||||
'SELECT nation, sum(leadership+strength+intel) as abil,sum(gold+rice) as goldrice,
|
||||
sum(dex1+dex2+dex3+dex4) as dex,sum(experience+dedication) as expded
|
||||
from general GROUP BY nation'
|
||||
),
|
||||
'nation'
|
||||
);
|
||||
|
||||
$nationCityInfos = Util::convertArrayToDict(
|
||||
$db->query('SELECT nation, count(*) as cnt, sum(pop) as pop,sum(pop_max) as pop_max from city GROUP BY nation'),
|
||||
'nation'
|
||||
);
|
||||
|
||||
foreach ($nations as $nationNo => &$nation) {
|
||||
$general = $nationGeneralInfos[$nationNo];
|
||||
$city = $nationCityInfos[$nationNo];
|
||||
|
||||
$nation['generalInfo'] = $general;
|
||||
$nation['cityInfo'] = $city;
|
||||
|
||||
$nationName .= $nation['name'] . '(' . getNationType($nation['type']) . '), ';
|
||||
$powerHist .= "{$nation['name']}({$nation['power']}/{$nation['gennum']}/{$city['cnt']}/{$city['pop']}/{$city['pop_max']}/{$nation['goldrice']}/{$general['goldrice']}/{$general['abil']}/{$general['dex']}/{$general['expded']}), ";
|
||||
|
||||
if (!isset($nationHists[$nation['type']])) {
|
||||
$nationHists[$nation['type']] = 0;
|
||||
}
|
||||
$nationHists[$nation['type']]++;
|
||||
}
|
||||
unset($nation);
|
||||
|
||||
$auxData['nations']['all'] = $nations;
|
||||
|
||||
$nationHist = '';
|
||||
foreach (GameConst::$availableNationType as $nationType) {
|
||||
if (!Util::array_get($nationHists[$nationType])) {
|
||||
$nationHists[$nationType] = '-';
|
||||
}
|
||||
$nationHist .= getNationType($nationType) . "({$nationHists[$nationType]}), ";
|
||||
}
|
||||
|
||||
$generals = $db->query('SELECT `no`,npc,personal,special,special2,crewtype FROM general');
|
||||
|
||||
$genCount = 0;
|
||||
$npcCount = 0;
|
||||
$generalCount = count($generals);
|
||||
|
||||
foreach ($generals as $general) {
|
||||
if (!isset($personalHists[$general['personal']])) {
|
||||
$personalHists[$general['personal']] = 0;
|
||||
}
|
||||
|
||||
if (!isset($specialHists[$general['special']])) {
|
||||
$specialHists[$general['special']] = 0;
|
||||
}
|
||||
|
||||
if (!isset($specialHists2[$general['special2']])) {
|
||||
$specialHists2[$general['special2']] = 0;
|
||||
}
|
||||
|
||||
if ($general['npc'] < 2) {
|
||||
$genCount += 1;
|
||||
} else {
|
||||
$npcCount += 1;
|
||||
}
|
||||
|
||||
$personalHists[$general['personal']]++;
|
||||
$specialHists[$general['special']]++;
|
||||
$specialHists2[$general['special2']]++;
|
||||
}
|
||||
|
||||
foreach ($db->queryAllLists(
|
||||
'SELECT crewtype, count(crewtype) AS cnt FROM general WHERE recent_war != NULL GROUP BY crewtype'
|
||||
) as [$crewtype, $cnt]) {
|
||||
$crewtypeHists[$crewtype] = $cnt;
|
||||
}
|
||||
|
||||
$auxData['generals']['hists'] = [
|
||||
'personal' => $personalHists,
|
||||
'special' => $specialHists,
|
||||
'special2' => $specialHists2,
|
||||
'crewtype' => $crewtypeHists,
|
||||
'userCnt' => $genCount,
|
||||
'npcCnt' => $npcCount,
|
||||
];
|
||||
|
||||
$generalCountStr = "{$generalCount}({$genCount}+{$npcCount})";
|
||||
|
||||
$personalHistStr = join(', ', array_map(function ($histPair) {
|
||||
[$histKey, $cnt] = $histPair;
|
||||
return getGenChar($histKey) . '(' . $cnt . ')';
|
||||
}, Util::convertDictToArray($personalHists)));
|
||||
|
||||
$specialHistsStr = join(', ', array_map(function ($histPair) {
|
||||
[$histKey, $cnt] = $histPair;
|
||||
return getGeneralSpecialDomesticName($histKey) . '(' . $cnt . ')';
|
||||
}, Util::convertDictToArray($specialHists)));
|
||||
|
||||
$specialHists2Str = join(', ', array_map(function ($histPair) {
|
||||
[$histKey, $cnt] = $histPair;
|
||||
return getGeneralSpecialWarName($histKey) . '(' . $cnt . ')';
|
||||
}, Util::convertDictToArray($specialHists2)));
|
||||
|
||||
$specialHistsAllStr = "$specialHistsStr // $specialHists2Str";
|
||||
|
||||
$crewtypeHistsStr = join(', ', array_map(function ($histPair) {
|
||||
[$histKey, $cnt] = $histPair;
|
||||
return GameUnitConst::byID($histKey)->getShortName() . '(' . $cnt . ')';
|
||||
}, Util::convertDictToArray($crewtypeHists)));
|
||||
|
||||
$db->insert('statistic', [
|
||||
'year' => $admin['year'],
|
||||
'month' => $admin['month'],
|
||||
'nation_count' => $nationCount,
|
||||
'nation_name' => $nationName,
|
||||
'nation_hist' => $nationHist,
|
||||
'gen_count' => $generalCountStr,
|
||||
'personal_hist' => $personalHistStr,
|
||||
'special_hist' => $specialHistsAllStr,
|
||||
'power_hist' => $powerHist,
|
||||
'crewtype' => $crewtypeHistsStr,
|
||||
'etc' => $etc,
|
||||
'aux' => Json::encode($auxData)
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
function convForOldGeneral(array $general, int $year, int $month)
|
||||
{
|
||||
$general['history'] = getGeneralHistoryLogAll($general['no']);
|
||||
return [
|
||||
'server_id' => UniqueConst::$serverID,
|
||||
'general_no' => $general['no'],
|
||||
'owner' => $general['owner'],
|
||||
'name' => $general['name'],
|
||||
'last_yearmonth' => $year * 100 + $month,
|
||||
'turntime' => $general['turntime'],
|
||||
'data' => Json::encode($general)
|
||||
];
|
||||
}
|
||||
|
||||
function storeOldGeneral(int $no, int $year, int $month)
|
||||
{
|
||||
$db = DB::db();
|
||||
$general = $db->queryFirstRow('SELECT * FROM general WHERE `no` = %i', $no);
|
||||
if (!$general) {
|
||||
return;
|
||||
}
|
||||
$data = convForOldGeneral($general, $year, $month);
|
||||
$db->insertUpdate(
|
||||
'ng_old_generals',
|
||||
$data,
|
||||
$data
|
||||
);
|
||||
}
|
||||
|
||||
function storeOldGenerals(int $nation, int $year, int $month)
|
||||
{
|
||||
$db = DB::db();
|
||||
foreach ($db->query('SELECT * FROM general WHERE nation = %i', $nation) as $general) {
|
||||
$data = convForOldGeneral($general, $year, $month);
|
||||
$db->insertUpdate(
|
||||
'ng_old_generals',
|
||||
$data,
|
||||
$data
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function checkEmperior()
|
||||
{
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
$admin = $gameStor->getValues(['year', 'month', 'isunited', 'conlimit']);
|
||||
if ($admin['isunited'] != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$remainNations = $db->queryFirstColumn('SELECT nation FROM nation WHERE level > 0 LIMIT 2');
|
||||
|
||||
if (!$remainNations || count($remainNations) != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$nationID = $remainNations[0];
|
||||
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
|
||||
$cityCnt = $db->queryFirstField('SELECT count(city) FROM city WHERE nation=%i', $nationID);
|
||||
if (!$cityCnt) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($cityCnt != count(CityConst::all())) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkStatistic();
|
||||
|
||||
$nation = $db->queryFirstRow('SELECT * FROM nation WHERE nation=%i', $nationID);
|
||||
$nationName = $nation['name'];
|
||||
|
||||
$josaYi = JosaUtil::pick($nationName, '이');
|
||||
|
||||
$nationLogger = new ActionLogger(0, $nationID, $admin['year'], $admin['month']);
|
||||
$nationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일");
|
||||
|
||||
$gameStor->isunited = 2;
|
||||
$gameStor->conlimit = $gameStor->conlimit * 100;
|
||||
|
||||
foreach ($db->queryFirstColumn('SELECT no FROM general WHERE npc<2 AND age>=%i', GameConst::$minPushHallAge) as $hallGeneralNo) {
|
||||
CheckHall($hallGeneralNo);
|
||||
}
|
||||
|
||||
[$totalPop, $totalMaxPop] = $db->queryFirstList('SELECT SUM(pop), SUM(pop_max) FROM city');
|
||||
$pop = "{$totalPop} / {$totalMaxPop}";
|
||||
$poprate = round($totalPop / $totalMaxPop * 100, 2). " %";
|
||||
|
||||
$chiefs = Util::convertArrayToDict(
|
||||
$db->query(
|
||||
'SELECT no,name,picture,belong,officer_level FROM general WHERE nation=%i AND officer_level >= 5',
|
||||
$nationID
|
||||
),
|
||||
'officer_level'
|
||||
);
|
||||
|
||||
$nationGenerals = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nationID);
|
||||
$nation['generals'] = $nationGenerals;
|
||||
|
||||
$tigers = $db->query(
|
||||
'SELECT value, name
|
||||
FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no
|
||||
WHERE rank_data.nation_id = %i AND rank_data.type = "killnum" AND value > 0 ORDER BY value DESC LIMIT 5',
|
||||
$nationID
|
||||
); // 오호장군
|
||||
|
||||
$tigerstr = join(', ', array_map(function ($arr) {
|
||||
$number = number_format($arr['value']);
|
||||
return "{$arr['name']}【{$number}】";
|
||||
}, $tigers));
|
||||
|
||||
$eagles = $db->query(
|
||||
'SELECT value, name
|
||||
FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no
|
||||
WHERE rank_data.nation_id = %i AND rank_data.type = "firenum" AND value > 0 ORDER BY value DESC LIMIT 7',
|
||||
$nationID
|
||||
); // 건안칠자
|
||||
|
||||
$eaglestr = join(', ', array_map(function ($arr) {
|
||||
$number = number_format($arr['value']);
|
||||
return "{$arr['name']}【{$number}】";
|
||||
}, $eagles));
|
||||
|
||||
$rawGeneralList = $db->query('SELECT no, name, npc, owner FROM general WHERE nation=%i ORDER BY dedication DESC', $nationID);
|
||||
foreach ($rawGeneralList as $rawGeneral) {
|
||||
$generalLogger = new ActionLogger($rawGeneral['no'], $nationID, $admin['year'], $admin['month']);
|
||||
$generalLogger->pushGeneralActionLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일하였습니다.", ActionLogger::YEAR_MONTH);
|
||||
$generalLogger->flush();
|
||||
}
|
||||
|
||||
$gen = join(', ', array_column($rawGeneral, 'name'));
|
||||
|
||||
$stat = $db->queryFirstRow('SELECT max(nation_count) as nc, max(gen_count) as gc FROM statistic');
|
||||
$genCnt = $db->queryFirstField('SELECT count(*) FROM general');
|
||||
|
||||
$statNC = "1 / {$stat['nc']}";
|
||||
$statGC = "{$genCnt} / {$stat['gc']}";
|
||||
$statNation = $db->queryFirstRow('SELECT nation_count,nation_name,nation_hist from statistic where nation_count=%i LIMIT 1', $stat['nc']);
|
||||
$statGeneral = $db->queryFirstRow('SELECT gen_count,personal_hist,special_hist,aux from statistic order by no desc LIMIT 1');
|
||||
|
||||
$nation = $nation;
|
||||
$nation['generals'] = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nation['nation']);
|
||||
$nation['aux'] = Json::decode($nation['aux']);
|
||||
$nation['msg'] = $nationStor->notice;
|
||||
$nation['scout_msg'] = $nationStor->scout_msg;
|
||||
$nation['aux'] += $nationStor->max_power;
|
||||
$nation['history'] = getNationHistoryLogAll($nation['nation']);
|
||||
|
||||
storeOldGenerals(0, $admin['year'], $admin['month']);
|
||||
storeOldGenerals($nation['nation'], $admin['year'], $admin['month']);
|
||||
|
||||
$db->insert('ng_old_nations', [
|
||||
'server_id' => UniqueConst::$serverID,
|
||||
'nation' => $nation['nation'],
|
||||
'data' => Json::encode($nation)
|
||||
]);
|
||||
|
||||
$noNationGeneral = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=0');
|
||||
$db->insert('ng_old_nations', [
|
||||
'server_id' => UniqueConst::$serverID,
|
||||
'nation' => 0,
|
||||
'data' => Json::encode([
|
||||
'nation' => 0,
|
||||
'name' => '재야',
|
||||
'generals' => $noNationGeneral
|
||||
])
|
||||
]);
|
||||
|
||||
$nationHistory = getNationHistoryLogAll($nation['nation']);
|
||||
|
||||
$serverCnt = $db->queryFirstField('SELECT count(*) FROM ng_games');
|
||||
$serverName = UniqueConst::$serverName;
|
||||
|
||||
$db->update('ng_games', [
|
||||
'winner_nation' => $nation['nation']
|
||||
], 'server_id=%s', UniqueConst::$serverID);
|
||||
|
||||
$db->insert('emperior', [
|
||||
'phase' => $serverName . $serverCnt . '기',
|
||||
'server_id' => UniqueConst::$serverID,
|
||||
'nation_count' => $statNC,
|
||||
'nation_name' => $statNation['nation_name'],
|
||||
'nation_hist' => $statNation['nation_hist'],
|
||||
'gen_count' => $statGC,
|
||||
'personal_hist' => $statGeneral['personal_hist'],
|
||||
'special_hist' => $statGeneral['special_hist'],
|
||||
'name' => $nation['name'],
|
||||
'type' => $nation['type'],
|
||||
'color' => $nation['color'],
|
||||
'year' => $admin['year'],
|
||||
'month' => $admin['month'],
|
||||
'power' => $nation['power'],
|
||||
'gennum' => $nation['gennum'],
|
||||
'citynum' => $cityCnt,
|
||||
'pop' => $pop,
|
||||
'poprate' => $poprate,
|
||||
'gold' => $nation['gold'],
|
||||
'rice' => $nation['rice'],
|
||||
'l12name' => $chiefs[12]['name'],
|
||||
'l12pic' => $chiefs[12]['picture'],
|
||||
'l11name' => $chiefs[11]['name'],
|
||||
'l11pic' => $chiefs[11]['picture'],
|
||||
'l10name' => $chiefs[10]['name'],
|
||||
'l10pic' => $chiefs[10]['picture'],
|
||||
'l9name' => $chiefs[9]['name'],
|
||||
'l9pic' => $chiefs[9]['picture'],
|
||||
'l8name' => $chiefs[8]['name'],
|
||||
'l8pic' => $chiefs[8]['picture'],
|
||||
'l7name' => $chiefs[7]['name'],
|
||||
'l7pic' => $chiefs[7]['picture'],
|
||||
'l6name' => $chiefs[6]['name'],
|
||||
'l6pic' => $chiefs[6]['picture'],
|
||||
'l5name' => $chiefs[5]['name'],
|
||||
'l5pic' => $chiefs[5]['picture'],
|
||||
'tiger' => $tigerstr,
|
||||
'eagle' => $eaglestr,
|
||||
'gen' => $gen,
|
||||
'history' => JSON::encode($nationHistory),
|
||||
'aux' => $statGeneral['aux']
|
||||
]);
|
||||
|
||||
$history = ["<C>●</>{$admin['year']}년 {$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다."];
|
||||
pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
|
||||
|
||||
//연감 월결산
|
||||
LogHistory();
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* 게임 룰에 해당하는 함수 모음
|
||||
*/
|
||||
|
||||
function getNationLevelList(): array
|
||||
{
|
||||
$table = [
|
||||
0 => ['방랑군', 2, 0],
|
||||
1 => ['호족', 2, 1],
|
||||
2 => ['군벌', 4, 2],
|
||||
3 => ['주자사', 4, 5],
|
||||
4 => ['주목', 6, 8],
|
||||
5 => ['공', 6, 11],
|
||||
6 => ['왕', 8, 16],
|
||||
7 => ['황제', 8, 21],
|
||||
];
|
||||
return $table;
|
||||
}
|
||||
|
||||
function getCityLevelList(): array
|
||||
{
|
||||
return [
|
||||
1 => '수',
|
||||
2 => '진',
|
||||
3 => '관',
|
||||
4 => '이',
|
||||
5 => '소',
|
||||
6 => '중',
|
||||
7 => '대',
|
||||
8 => '특'
|
||||
];
|
||||
}
|
||||
|
||||
//한국가의 전체 전방 설정
|
||||
function SetNationFront($nationNo)
|
||||
{
|
||||
if (!$nationNo) {
|
||||
return;
|
||||
}
|
||||
// 도시소유 국가와 선포,교전중인 국가
|
||||
|
||||
$adj3 = [];
|
||||
$adj2 = [];
|
||||
$adj1 = [];
|
||||
|
||||
$db = DB::db();
|
||||
foreach ($db->queryFirstColumn(
|
||||
'SELECT city FROM city JOIN diplomacy ON diplomacy.you = city.nation WHERE diplomacy.state = 0 AND me = %i',
|
||||
$nationNo
|
||||
) as $city) {
|
||||
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
|
||||
$adj3[$adjKey] = $adjVal;
|
||||
}
|
||||
};
|
||||
foreach ($db->queryFirstColumn(
|
||||
'SELECT city FROM city JOIN diplomacy ON diplomacy.you = city.nation WHERE diplomacy.state = 1 AND diplomacy.term <= 5 AND me = %i',
|
||||
$nationNo
|
||||
) as $city) {
|
||||
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
|
||||
$adj1[$adjKey] = $adjVal;
|
||||
}
|
||||
}
|
||||
if (!$adj3 && !$adj1) {
|
||||
//평시이면 공백지
|
||||
//NOTE: if, else일 경우 NPC는 전쟁시에는 공백지로 출병하지 않는다는 뜻이 된다.
|
||||
foreach ($db->queryFirstColumn('SELECT city from city where nation=0') as $city) {
|
||||
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
|
||||
$adj2[$adjKey] = $adjVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$db->update('city', [
|
||||
'front' => 0
|
||||
], 'nation=%i', $nationNo);
|
||||
|
||||
if ($adj1) {
|
||||
$db->update('city', [
|
||||
'front' => 1,
|
||||
], 'nation=%i and city in %li', $nationNo, array_keys($adj1));
|
||||
}
|
||||
if ($adj2) {
|
||||
$db->update('city', [
|
||||
'front' => 2,
|
||||
], 'nation=%i and city in %li', $nationNo, array_keys($adj2));
|
||||
}
|
||||
if ($adj3) {
|
||||
$db->update('city', [
|
||||
'front' => 3,
|
||||
], 'nation=%i and city in %li', $nationNo, array_keys($adj3));
|
||||
}
|
||||
}
|
||||
|
||||
function checkSupply()
|
||||
{
|
||||
$db = DB::db();
|
||||
|
||||
$cities = [];
|
||||
foreach ($db->query('SELECT city, nation FROM city WHERE nation != 0') as $city) {
|
||||
$newCity = new \stdClass();
|
||||
$newCity->id = Util::toInt($city['city']);
|
||||
$newCity->nation = Util::toInt($city['nation']);
|
||||
$newCity->supply = false;
|
||||
|
||||
$cities[$newCity->id] = $newCity;
|
||||
}
|
||||
|
||||
$queue = new \SplQueue();
|
||||
foreach ($db->queryAllLists('SELECT capital, nation FROM nation WHERE `level` > 0') as list($capitalID, $nationID)) {
|
||||
if (!key_exists($capitalID, $cities)) {
|
||||
continue;
|
||||
}
|
||||
$city = $cities[$capitalID];
|
||||
if ($nationID != $city->nation) {
|
||||
continue;
|
||||
}
|
||||
$city->supply = true;
|
||||
$queue->enqueue($city);
|
||||
}
|
||||
|
||||
while (!$queue->isEmpty()) {
|
||||
$cityLink = $queue->dequeue();
|
||||
$city = CityConst::byID($cityLink->id);
|
||||
|
||||
foreach (array_keys($city->path) as $connCityID) {
|
||||
if (!key_exists($connCityID, $cities)) {
|
||||
continue;
|
||||
}
|
||||
$connCity = $cities[$connCityID];
|
||||
if ($connCity->nation != $cityLink->nation) {
|
||||
continue;
|
||||
}
|
||||
if ($connCity->supply) {
|
||||
continue;
|
||||
}
|
||||
$connCity->supply = true;
|
||||
$queue->enqueue($connCity);
|
||||
}
|
||||
}
|
||||
|
||||
$db->update('city', [
|
||||
'supply' => 1
|
||||
], 'nation=0');
|
||||
|
||||
$db->update('city', [
|
||||
'supply' => 0
|
||||
], 'nation!=0');
|
||||
|
||||
$supply = [];
|
||||
|
||||
foreach ($cities as $city) {
|
||||
if ($city->supply) {
|
||||
$supply[] = $city->id;
|
||||
}
|
||||
}
|
||||
|
||||
if ($supply) {
|
||||
$db->update('city', [
|
||||
'supply' => 1
|
||||
], 'city IN %li', $supply);
|
||||
}
|
||||
}
|
||||
|
||||
function updateGeneralNumber(){
|
||||
$db = DB::db();
|
||||
foreach($db->queryAllLists('SELECT nation, count(*) FROM general WHERE npc != 5 GROUP BY nation') as [$nationID, $gennum]){
|
||||
if($nationID === 0){
|
||||
continue;
|
||||
}
|
||||
$db->update('nation', [
|
||||
'gennum'=>$gennum
|
||||
], 'nation=%i', $nationID);
|
||||
}
|
||||
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달마다 실행, 병사 있는 장수의 군량 감소, 수입비율 조정
|
||||
function preUpdateMonthly()
|
||||
{
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
//연감 월결산
|
||||
$result = LogHistory();
|
||||
|
||||
if ($result == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$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
|
||||
$db->update('general', [
|
||||
'connect' => $db->sqleval('floor(connect*0.99)'),
|
||||
'makelimit' => $db->sqleval('greatest(0, makelimit - 1)'),
|
||||
], true);
|
||||
//전략제한-1, 외교제한-1, 세율동기화
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $db->sqleval('greatest(0, strategic_cmd_limit - 1)'),
|
||||
'surlimit' => $db->sqleval('greatest(0, surlimit - 1)'),
|
||||
'rate_tmp' => $db->sqleval('rate')
|
||||
], true);
|
||||
|
||||
//도시훈사 180년 60, 220년 87, 240년 100
|
||||
$rate = Util::round(($admin['year'] - $admin['startyear']) / 1.5) + 60;
|
||||
if ($rate > 100) $rate = 100;
|
||||
|
||||
// 20 ~ 140원
|
||||
$develcost = ($admin['year'] - $admin['startyear'] + 10) * 2;
|
||||
$gameStor->city_rate = $rate;
|
||||
$gameStor->develcost = $develcost;
|
||||
|
||||
//매달 사망자 수입 결산
|
||||
processWarIncome();
|
||||
|
||||
//계략, 전쟁표시 해제
|
||||
$db->update('city', [
|
||||
'state' => $db->sqleval(<<<EOD
|
||||
(CASE
|
||||
WHEN state=31 THEN 0
|
||||
WHEN state=32 THEN 31
|
||||
WHEN state=33 THEN 0
|
||||
WHEN state=34 THEN 33
|
||||
WHEN state=41 THEN 0
|
||||
WHEN state=42 THEN 41
|
||||
WHEN state=43 THEN 42
|
||||
ELSE state END)
|
||||
EOD),
|
||||
'term' => $db->sqleval('greatest(0, term - 1)'),
|
||||
'conflict' => $db->sqleval('if(term = 0,%s,conflict)', '{}'),
|
||||
], true);
|
||||
|
||||
//첩보-1
|
||||
foreach ($db->queryAllLists("SELECT nation, spy FROM nation WHERE spy!='' AND spy!='{}'") as [$nationNo, $rawSpy]) {
|
||||
$spyInfo = Json::decode($rawSpy);
|
||||
|
||||
foreach ($spyInfo as $cityNo => $remainMonth) {
|
||||
if ($remainMonth <= 1) {
|
||||
unset($spyInfo[$cityNo]);
|
||||
} else {
|
||||
$spyInfo[$cityNo] -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
$db->update('nation', [
|
||||
'spy' => Json::encode($spyInfo, Json::EMPTY_ARRAY_IS_DICT)
|
||||
], 'nation=%i', $nationNo);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 외교 로그처리, 외교 상태 처리
|
||||
function postUpdateMonthly()
|
||||
{
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
$admin = $gameStor->getValues(['startyear', 'year', 'month', 'scenario']);
|
||||
$globalLogger = new ActionLogger(0, 0, $admin['year'], $admin['month']);
|
||||
|
||||
//도시 수 측정
|
||||
$cityNations = [];
|
||||
foreach ($db->queryAllLists('SELECT city, name, nation FROM city') as [$cityID, $cityName, $cityNation]) {
|
||||
if (!key_exists($cityNation, $cityNations)) {
|
||||
$cityNations[$cityNation] = [];
|
||||
}
|
||||
$cityNations[$cityNation][] = $cityName;
|
||||
}
|
||||
|
||||
//각 국가 전월 장수수 대비 당월 장수수로 단합도 산정
|
||||
//각 국가 장수수를 구하고 국력 산정
|
||||
// $query = "select nation,gennum from nation where level>0";
|
||||
// 국력=
|
||||
// 자원(국가/장수의 금,쌀)
|
||||
// 기술력
|
||||
// 인구수*내정%
|
||||
// 장수능력
|
||||
// 접속률
|
||||
// 숙련도
|
||||
// 명성,공헌
|
||||
$nations = Util::convertArrayToDict($db->query('SELECT
|
||||
A.nation,
|
||||
A.gennum,
|
||||
round((
|
||||
round(((A.gold+A.rice)+(select sum(gold+rice) from general where nation=A.nation))/100)
|
||||
+A.tech
|
||||
+if(A.level=0,0,(
|
||||
select round(
|
||||
sum(pop)*sum(pop+agri+comm+secu+wall+def)/sum(pop_max+agri_max+comm_max+secu_max+wall_max+def_max)/100
|
||||
) from city where nation=A.nation and supply=1
|
||||
))
|
||||
+(select sum(leadership+strength+intel) 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(avg(connect)) from general where nation=A.nation)
|
||||
)/10)
|
||||
as power,
|
||||
(select sum(crew) from general where nation=A.nation) as totalCrew
|
||||
from nation A
|
||||
group by A.nation'), 'nation');
|
||||
$maxPowerValues = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'max_power');
|
||||
|
||||
foreach ($nations as $nation) {
|
||||
$nationID = $nation['nation'];
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
$genNum[$nationID] = $nation['gennum'];
|
||||
|
||||
$powerValues = $maxPowerValues[$nationID]??[];
|
||||
|
||||
//약간의 랜덤치 부여 (95% ~ 105%)
|
||||
|
||||
$nation['power'] = Util::round($nation['power'] * (rand() % 101 + 950) / 1000);
|
||||
$powerValues['maxPower'] = max($powerValues['maxPower'] ?? 0, $nation['power']);
|
||||
$powerValues['maxCrew'] = max($powerValues['maxCrew'] ?? 0, Util::toInt($nation['totalCrew']));
|
||||
|
||||
if (count($cityNations[$nationID] ?? []) > count($powerValues['maxCities'] ?? [])) {
|
||||
$powerValues['maxCities'] = $cityNations[$nationID];
|
||||
}
|
||||
|
||||
$db->update('nation', [
|
||||
'power' => $nation['power']
|
||||
], 'nation=%i', $nationID);
|
||||
$nationStor->max_power = $powerValues;
|
||||
}
|
||||
|
||||
// 전쟁기한 세팅
|
||||
foreach($db->query('SELECT me, you, dead, term FROM diplomacy WHERE state = 0') as $dip) {
|
||||
$genCount = $genNum[$dip['me']];
|
||||
// 25% 참여율일때 두당 10턴에 4000명 소모한다고 계산
|
||||
// 4000 / 10 * 0.25 = 100
|
||||
$term = floor($dip['dead'] / 100 / $genCount);
|
||||
$dip['dead'] -= $term * 100 * $genCount;
|
||||
$term = Util::valueFit($dip['term'] + $term, 0, 13);
|
||||
|
||||
$db->update('diplomacy', [
|
||||
'term' => $term,
|
||||
'dead' => $dip['dead'],
|
||||
], 'me = %i AND you = %i', $dip['me'], $dip['you']);
|
||||
}
|
||||
|
||||
//개전국 로그
|
||||
foreach($db->query('SELECT me, you FROM diplomacy WHERE state = 1 AND term <= 1 AND me < you') as $dip){
|
||||
$nation1 = getNationStaticInfo($dip['me']);
|
||||
$name1 = $nation1['name'];
|
||||
$nation2 = getNationStaticInfo($dip['you']);
|
||||
$name2 = $nation2['name'];
|
||||
|
||||
$josaYi = JosaUtil::pick($name2, '이');
|
||||
$josaWa = JosaUtil::pick($name1, '와');
|
||||
$globalLogger->pushGlobalHistoryLog("<R><b>【개전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <R>전쟁</>을 시작합니다.");
|
||||
}
|
||||
//휴전국 로그
|
||||
$stopWarList = [];
|
||||
foreach($db->queryAllLists('SELECT me,you FROM diplomacy WHERE state=0 AND term <= 1 ORDER BY me desc, you desc') as [$me, $you]){
|
||||
if($me < $you){
|
||||
$key = "{$me}_{$you}";
|
||||
}
|
||||
else{
|
||||
$key = "{$you}_{$me}";
|
||||
}
|
||||
if(!key_exists($key, $stopWarList)){
|
||||
$stopWarList[$key] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
//양측 기간 모두 0이 되는 상황이면 휴전
|
||||
$nation1 = getNationStaticInfo($me);
|
||||
$name1 = $nation1['name'];
|
||||
$nation2 = getNationStaticInfo($you);
|
||||
$name2 = $nation2['name'];
|
||||
|
||||
$josaWa = JosaUtil::pick($name1, '와');
|
||||
$josaYi = JosaUtil::pick($name2, '이');
|
||||
|
||||
$globalLogger->pushGlobalHistoryLog("<R><b>【휴전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <S>휴전</>합니다.");
|
||||
$db->update('diplomacy', [
|
||||
'state'=>2,
|
||||
'term'=>0,
|
||||
], '(me=%i AND you=%i) OR (you=%i AND me=%i)', $me, $you, $me, $you);
|
||||
}
|
||||
|
||||
$globalLogger->flush();
|
||||
|
||||
//사상자 초기화, 외교 기한-1
|
||||
$db->update('diplomacy', [
|
||||
'dead'=>$db->sqleval('if(state!=0, 0, dead)'),
|
||||
'term'=>$db->sqleval('greatest(0, term-1)'),
|
||||
], true);
|
||||
//불가침 끝나면 통상으로
|
||||
$db->update('diplomacy', [
|
||||
'state'=>2,
|
||||
], 'state = 7 AND term = 0');
|
||||
//선포 끝나면 교전으로
|
||||
$db->update('diplomacy', [
|
||||
'state'=>0,
|
||||
'term'=>6,
|
||||
], 'state = 1 AND term = 0');
|
||||
|
||||
//초반이후 방랑군 자동 해체
|
||||
if ($admin['year'] >= $admin['startyear'] + 2) {
|
||||
checkWander();
|
||||
}
|
||||
// 작위 업데이트
|
||||
updateNationState();
|
||||
updateGeneralNumber();
|
||||
refreshNationStaticInfo();
|
||||
// 천통여부 검사
|
||||
checkEmperior();
|
||||
//토너먼트 개시
|
||||
triggerTournament();
|
||||
// 시스템 거래건 등록
|
||||
registerAuction();
|
||||
//전방설정
|
||||
foreach (getAllNationStaticInfo() as $nation) {
|
||||
if ($nation['level'] <= 0) {
|
||||
continue;
|
||||
}
|
||||
SetNationFront($nation['nation']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function checkWander()
|
||||
{
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
$admin = $gameStor->getValues(['year', 'month']);
|
||||
|
||||
$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::createGeneralObjListFromDB($wanderers) as $wanderer) {
|
||||
$wanderCmd = buildGeneralCommandClass('che_해산', $wanderer, $admin);
|
||||
if ($wanderCmd->hasFullConditionMet()) {
|
||||
$logger = $wanderer->getLogger();
|
||||
$logger->pushGeneralActionLog('초반 제한후 방랑군은 자동 해산됩니다.', ActionLogger::PLAIN);
|
||||
$wanderCmd->run();
|
||||
$wanderCmd->setNextAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
if ($wanderers) {
|
||||
refreshNationStaticInfo();
|
||||
}
|
||||
}
|
||||
|
||||
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']);
|
||||
|
||||
$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이 진관수이소중대특 체계를 벗어날 수 있음
|
||||
$citycount = $db->queryFirstField('SELECT count(*) FROM city WHERE nation=%i AND level>=4', $nation['nation']);
|
||||
|
||||
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>●</>{$admin['year']}년 {$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭하였습니다.";
|
||||
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}년 {$admin['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>●</>{$admin['year']}년 {$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극하였습니다.";
|
||||
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}년 {$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극"]);
|
||||
break;
|
||||
case 5:
|
||||
case 4:
|
||||
case 3:
|
||||
$history[] = "<C>●</>{$admin['year']}년 {$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명되었습니다.";
|
||||
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}년 {$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명됨"]);
|
||||
break;
|
||||
case 2:
|
||||
$history[] = "<C>●</>{$admin['year']}년 {$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 독립하여 <Y>" . getNationLevel($nationlevel) . "</>로 나섰습니다.";
|
||||
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}년 {$admin['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'], 2);
|
||||
|
||||
$uniqueLotteryWeightList = [];
|
||||
foreach ($nationGenList as $nationGen) {
|
||||
$hasUnique = false;
|
||||
foreach ($nationGen->getItems() as $item) {
|
||||
if (!$item->isBuyable()) {
|
||||
$hasUnique = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($hasUnique) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$score = $nationGen->getVar('belong') + 5;
|
||||
|
||||
if ($nationGen->getVar('officer_level') == 12) {
|
||||
$score += 200; //NOTE: 꼬우면 군주하세요.
|
||||
} else if ($nationGen->getVar('officer_level') == 11) {
|
||||
$score += 70;
|
||||
} else if ($nationGen->getVar('officer_level') > 4) {
|
||||
$score += 35;
|
||||
}
|
||||
$uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score];
|
||||
}
|
||||
|
||||
foreach (Util::range($levelDiff) as $idx) {
|
||||
if (!$uniqueLotteryWeightList) {
|
||||
break;
|
||||
}
|
||||
|
||||
/** @var General */
|
||||
$winnerObj = Util::choiceRandomUsingWeightPair($uniqueLotteryWeightList);
|
||||
unset($uniqueLotteryWeightList[$winnerObj->getID()]);
|
||||
giveRandomUniqueItem($winnerObj, '작위보상');
|
||||
$winnerObj->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;
|
||||
|
||||
while ($assemblerCnt < $maxAssemblerCnt) {
|
||||
$lastAssemblerID += 1;
|
||||
$npcObj = new Scenario\NPC(
|
||||
999,
|
||||
sprintf('부대장%4d', $lastAssemblerID),
|
||||
null,
|
||||
$nation['nation'],
|
||||
null,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
1,
|
||||
$admin['year'] - 15,
|
||||
$admin['year'] + 15,
|
||||
'은둔',
|
||||
'척사'
|
||||
);
|
||||
$npcObj->killturn = 70;
|
||||
$npcObj->gold = 0;
|
||||
$npcObj->rice = 0;
|
||||
$npcObj->npc = 5;
|
||||
$npcObj->build($admin);
|
||||
$npcID = $npcObj->generalID;
|
||||
|
||||
$db->insert('troop', [
|
||||
'troop_leader' => $npcID,
|
||||
'name' => $npcObj->realName,
|
||||
'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()
|
||||
{
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
$admin = $gameStor->getValues(['year', 'month']);
|
||||
|
||||
$nationHists = [];
|
||||
$specialHists = [];
|
||||
$personalHists = [];
|
||||
$specialHists2 = [];
|
||||
$crewtypeHists = [];
|
||||
|
||||
$etc = '';
|
||||
|
||||
$auxData = [
|
||||
'generals' => [],
|
||||
'nations' => [],
|
||||
];
|
||||
|
||||
$avgGeneral = $db->queryFirstRow(
|
||||
'SELECT avg(gold) as avggold, avg(rice) as avgrice, avg(dex1+dex2+dex3+dex4) as avgdex,
|
||||
max(dex1+dex2+dex3+dex4) as maxdex, avg(experience+dedication) as avgexpded, max(experience+dedication) as maxexpded
|
||||
FROM general'
|
||||
);
|
||||
$auxData['generals']['avg'] = $avgGeneral;
|
||||
|
||||
$avgGeneral['avggold'] = Util::round($avgGeneral['avggold']);
|
||||
$avgGeneral['avgrice'] = Util::round($avgGeneral['avgrice']);
|
||||
$avgGeneral['avgdex'] = Util::round($avgGeneral['avgdex']);
|
||||
$avgGeneral['avgexpded'] = Util::round($avgGeneral['avgexpded']);
|
||||
$etc .= "평균 금/쌀 ({$avgGeneral['avggold']}/{$avgGeneral['avgrice']}), 평균/최고 숙련({$avgGeneral['avgdex']}/{$avgGeneral['maxdex']}), 평균/최고 경험공헌({$avgGeneral['avgexpded']}/{$avgGeneral['maxexpded']}), ";
|
||||
|
||||
$avgNation = $db->queryFirstRow(
|
||||
'SELECT min(tech) as mintech, max(tech) as maxtech, avg(tech) as avgtech,
|
||||
min(power) as minpower, max(power) as maxpower, avg(power) as avgpower from nation where level>0'
|
||||
);
|
||||
$auxData['nations']['avg'] = $avgNation;
|
||||
|
||||
$avgNation['mintech'] = floor($avgNation['mintech']);
|
||||
$avgNation['maxtech'] = floor($avgNation['maxtech']);
|
||||
$avgNation['avgtech'] = Util::round($avgNation['avgtech']);
|
||||
$avgNation['avgpower'] = Util::round($avgNation['avgpower']);
|
||||
$etc .= "최저/평균/최고 기술({$avgNation['mintech']}/{$avgNation['avgtech']}/{$avgNation['maxtech']}), ";
|
||||
$etc .= "최저/평균/최고 국력({$avgNation['minpower']}/{$avgNation['avgpower']}/{$avgNation['maxpower']}), ";
|
||||
|
||||
$nationName = '';
|
||||
$powerHist = '';
|
||||
|
||||
$nations = Util::convertArrayToDict(
|
||||
$db->query(
|
||||
'SELECT nation,name,type,power,gennum,gold+rice as goldrice from nation where level>0 order by power desc',
|
||||
'nation'
|
||||
),
|
||||
'nation'
|
||||
);
|
||||
$nationCount = count($nations);
|
||||
|
||||
$nationGeneralInfos = Util::convertArrayToDict(
|
||||
$db->query(
|
||||
'SELECT nation, sum(leadership+strength+intel) as abil,sum(gold+rice) as goldrice,
|
||||
sum(dex1+dex2+dex3+dex4) as dex,sum(experience+dedication) as expded
|
||||
from general GROUP BY nation'
|
||||
),
|
||||
'nation'
|
||||
);
|
||||
|
||||
$nationCityInfos = Util::convertArrayToDict(
|
||||
$db->query('SELECT nation, count(*) as cnt, sum(pop) as pop,sum(pop_max) as pop_max from city GROUP BY nation'),
|
||||
'nation'
|
||||
);
|
||||
|
||||
foreach ($nations as $nationNo => &$nation) {
|
||||
$general = $nationGeneralInfos[$nationNo];
|
||||
$city = $nationCityInfos[$nationNo];
|
||||
|
||||
$nation['generalInfo'] = $general;
|
||||
$nation['cityInfo'] = $city;
|
||||
|
||||
$nationName .= $nation['name'] . '(' . getNationType($nation['type']) . '), ';
|
||||
$powerHist .= "{$nation['name']}({$nation['power']}/{$nation['gennum']}/{$city['cnt']}/{$city['pop']}/{$city['pop_max']}/{$nation['goldrice']}/{$general['goldrice']}/{$general['abil']}/{$general['dex']}/{$general['expded']}), ";
|
||||
|
||||
if (!isset($nationHists[$nation['type']])) {
|
||||
$nationHists[$nation['type']] = 0;
|
||||
}
|
||||
$nationHists[$nation['type']]++;
|
||||
}
|
||||
unset($nation);
|
||||
|
||||
$auxData['nations']['all'] = $nations;
|
||||
|
||||
$nationHist = '';
|
||||
foreach (GameConst::$availableNationType as $nationType) {
|
||||
if (!Util::array_get($nationHists[$nationType])) {
|
||||
$nationHists[$nationType] = '-';
|
||||
}
|
||||
$nationHist .= getNationType($nationType) . "({$nationHists[$nationType]}), ";
|
||||
}
|
||||
|
||||
$generals = $db->query('SELECT `no`,npc,personal,special,special2,crewtype FROM general');
|
||||
|
||||
$genCount = 0;
|
||||
$npcCount = 0;
|
||||
$generalCount = count($generals);
|
||||
|
||||
foreach ($generals as $general) {
|
||||
if (!isset($personalHists[$general['personal']])) {
|
||||
$personalHists[$general['personal']] = 0;
|
||||
}
|
||||
|
||||
if (!isset($specialHists[$general['special']])) {
|
||||
$specialHists[$general['special']] = 0;
|
||||
}
|
||||
|
||||
if (!isset($specialHists2[$general['special2']])) {
|
||||
$specialHists2[$general['special2']] = 0;
|
||||
}
|
||||
|
||||
if ($general['npc'] < 2) {
|
||||
$genCount += 1;
|
||||
} else {
|
||||
$npcCount += 1;
|
||||
}
|
||||
|
||||
$personalHists[$general['personal']]++;
|
||||
$specialHists[$general['special']]++;
|
||||
$specialHists2[$general['special2']]++;
|
||||
}
|
||||
|
||||
foreach ($db->queryAllLists(
|
||||
'SELECT crewtype, count(crewtype) AS cnt FROM general WHERE recent_war != NULL GROUP BY crewtype'
|
||||
) as [$crewtype, $cnt]) {
|
||||
$crewtypeHists[$crewtype] = $cnt;
|
||||
}
|
||||
|
||||
$auxData['generals']['hists'] = [
|
||||
'personal' => $personalHists,
|
||||
'special' => $specialHists,
|
||||
'special2' => $specialHists2,
|
||||
'crewtype' => $crewtypeHists,
|
||||
'userCnt' => $genCount,
|
||||
'npcCnt' => $npcCount,
|
||||
];
|
||||
|
||||
$generalCountStr = "{$generalCount}({$genCount}+{$npcCount})";
|
||||
|
||||
$personalHistStr = join(', ', array_map(function ($histPair) {
|
||||
[$histKey, $cnt] = $histPair;
|
||||
return getGenChar($histKey) . '(' . $cnt . ')';
|
||||
}, Util::convertDictToArray($personalHists)));
|
||||
|
||||
$specialHistsStr = join(', ', array_map(function ($histPair) {
|
||||
[$histKey, $cnt] = $histPair;
|
||||
return getGeneralSpecialDomesticName($histKey) . '(' . $cnt . ')';
|
||||
}, Util::convertDictToArray($specialHists)));
|
||||
|
||||
$specialHists2Str = join(', ', array_map(function ($histPair) {
|
||||
[$histKey, $cnt] = $histPair;
|
||||
return getGeneralSpecialWarName($histKey) . '(' . $cnt . ')';
|
||||
}, Util::convertDictToArray($specialHists2)));
|
||||
|
||||
$specialHistsAllStr = "$specialHistsStr // $specialHists2Str";
|
||||
|
||||
$crewtypeHistsStr = join(', ', array_map(function ($histPair) {
|
||||
[$histKey, $cnt] = $histPair;
|
||||
return GameUnitConst::byID($histKey)->getShortName() . '(' . $cnt . ')';
|
||||
}, Util::convertDictToArray($crewtypeHists)));
|
||||
|
||||
$db->insert('statistic', [
|
||||
'year' => $admin['year'],
|
||||
'month' => $admin['month'],
|
||||
'nation_count' => $nationCount,
|
||||
'nation_name' => $nationName,
|
||||
'nation_hist' => $nationHist,
|
||||
'gen_count' => $generalCountStr,
|
||||
'personal_hist' => $personalHistStr,
|
||||
'special_hist' => $specialHistsAllStr,
|
||||
'power_hist' => $powerHist,
|
||||
'crewtype' => $crewtypeHistsStr,
|
||||
'etc' => $etc,
|
||||
'aux' => Json::encode($auxData)
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
function convForOldGeneral(array $general, int $year, int $month)
|
||||
{
|
||||
$general['history'] = getGeneralHistoryLogAll($general['no']);
|
||||
return [
|
||||
'server_id' => UniqueConst::$serverID,
|
||||
'general_no' => $general['no'],
|
||||
'owner' => $general['owner'],
|
||||
'name' => $general['name'],
|
||||
'last_yearmonth' => $year * 100 + $month,
|
||||
'turntime' => $general['turntime'],
|
||||
'data' => Json::encode($general)
|
||||
];
|
||||
}
|
||||
|
||||
function storeOldGeneral(int $no, int $year, int $month)
|
||||
{
|
||||
$db = DB::db();
|
||||
$general = $db->queryFirstRow('SELECT * FROM general WHERE `no` = %i', $no);
|
||||
if (!$general) {
|
||||
return;
|
||||
}
|
||||
$data = convForOldGeneral($general, $year, $month);
|
||||
$db->insertUpdate(
|
||||
'ng_old_generals',
|
||||
$data,
|
||||
$data
|
||||
);
|
||||
}
|
||||
|
||||
function storeOldGenerals(int $nation, int $year, int $month)
|
||||
{
|
||||
$db = DB::db();
|
||||
foreach ($db->query('SELECT * FROM general WHERE nation = %i', $nation) as $general) {
|
||||
$data = convForOldGeneral($general, $year, $month);
|
||||
$db->insertUpdate(
|
||||
'ng_old_generals',
|
||||
$data,
|
||||
$data
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function checkEmperior()
|
||||
{
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
$admin = $gameStor->getValues(['year', 'month', 'isunited', 'conlimit']);
|
||||
if ($admin['isunited'] != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$remainNations = $db->queryFirstColumn('SELECT nation FROM nation WHERE level > 0 LIMIT 2');
|
||||
|
||||
if (!$remainNations || count($remainNations) != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$nationID = $remainNations[0];
|
||||
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
|
||||
$cityCnt = $db->queryFirstField('SELECT count(city) FROM city WHERE nation=%i', $nationID);
|
||||
if (!$cityCnt) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($cityCnt != count(CityConst::all())) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkStatistic();
|
||||
|
||||
$nation = $db->queryFirstRow('SELECT * FROM nation WHERE nation=%i', $nationID);
|
||||
$nationName = $nation['name'];
|
||||
|
||||
$josaYi = JosaUtil::pick($nationName, '이');
|
||||
|
||||
$nationLogger = new ActionLogger(0, $nationID, $admin['year'], $admin['month']);
|
||||
$nationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일");
|
||||
|
||||
$gameStor->isunited = 2;
|
||||
$gameStor->conlimit = $gameStor->conlimit * 100;
|
||||
|
||||
foreach ($db->queryFirstColumn('SELECT no FROM general WHERE npc<2 AND age>=%i', GameConst::$minPushHallAge) as $hallGeneralNo) {
|
||||
CheckHall($hallGeneralNo);
|
||||
}
|
||||
|
||||
[$totalPop, $totalMaxPop] = $db->queryFirstList('SELECT SUM(pop), SUM(pop_max) FROM city');
|
||||
$pop = "{$totalPop} / {$totalMaxPop}";
|
||||
$poprate = round($totalPop / $totalMaxPop * 100, 2). " %";
|
||||
|
||||
$chiefs = Util::convertArrayToDict(
|
||||
$db->query(
|
||||
'SELECT no,name,picture,belong,officer_level FROM general WHERE nation=%i AND officer_level >= 5',
|
||||
$nationID
|
||||
),
|
||||
'officer_level'
|
||||
);
|
||||
|
||||
$nationGenerals = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nationID);
|
||||
$nation['generals'] = $nationGenerals;
|
||||
|
||||
$tigers = $db->query(
|
||||
'SELECT value, name
|
||||
FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no
|
||||
WHERE rank_data.nation_id = %i AND rank_data.type = "killnum" AND value > 0 ORDER BY value DESC LIMIT 5',
|
||||
$nationID
|
||||
); // 오호장군
|
||||
|
||||
$tigerstr = join(', ', array_map(function ($arr) {
|
||||
$number = number_format($arr['value']);
|
||||
return "{$arr['name']}【{$number}】";
|
||||
}, $tigers));
|
||||
|
||||
$eagles = $db->query(
|
||||
'SELECT value, name
|
||||
FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no
|
||||
WHERE rank_data.nation_id = %i AND rank_data.type = "firenum" AND value > 0 ORDER BY value DESC LIMIT 7',
|
||||
$nationID
|
||||
); // 건안칠자
|
||||
|
||||
$eaglestr = join(', ', array_map(function ($arr) {
|
||||
$number = number_format($arr['value']);
|
||||
return "{$arr['name']}【{$number}】";
|
||||
}, $eagles));
|
||||
|
||||
$rawGeneralList = $db->query('SELECT no, name, npc, owner FROM general WHERE nation=%i ORDER BY dedication DESC', $nationID);
|
||||
foreach ($rawGeneralList as $rawGeneral) {
|
||||
$generalLogger = new ActionLogger($rawGeneral['no'], $nationID, $admin['year'], $admin['month']);
|
||||
$generalLogger->pushGeneralActionLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일하였습니다.", ActionLogger::YEAR_MONTH);
|
||||
$generalLogger->flush();
|
||||
}
|
||||
|
||||
$gen = join(', ', array_column($rawGeneral, 'name'));
|
||||
|
||||
$stat = $db->queryFirstRow('SELECT max(nation_count) as nc, max(gen_count) as gc FROM statistic');
|
||||
$genCnt = $db->queryFirstField('SELECT count(*) FROM general');
|
||||
|
||||
$statNC = "1 / {$stat['nc']}";
|
||||
$statGC = "{$genCnt} / {$stat['gc']}";
|
||||
$statNation = $db->queryFirstRow('SELECT nation_count,nation_name,nation_hist from statistic where nation_count=%i LIMIT 1', $stat['nc']);
|
||||
$statGeneral = $db->queryFirstRow('SELECT gen_count,personal_hist,special_hist,aux from statistic order by no desc LIMIT 1');
|
||||
|
||||
$nation = $nation;
|
||||
$nation['generals'] = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nation['nation']);
|
||||
$nation['aux'] = Json::decode($nation['aux']);
|
||||
$nation['msg'] = $nationStor->notice;
|
||||
$nation['scout_msg'] = $nationStor->scout_msg;
|
||||
$nation['aux'] += $nationStor->max_power;
|
||||
$nation['history'] = getNationHistoryLogAll($nation['nation']);
|
||||
|
||||
storeOldGenerals(0, $admin['year'], $admin['month']);
|
||||
storeOldGenerals($nation['nation'], $admin['year'], $admin['month']);
|
||||
|
||||
$db->insert('ng_old_nations', [
|
||||
'server_id' => UniqueConst::$serverID,
|
||||
'nation' => $nation['nation'],
|
||||
'data' => Json::encode($nation)
|
||||
]);
|
||||
|
||||
$noNationGeneral = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=0');
|
||||
$db->insert('ng_old_nations', [
|
||||
'server_id' => UniqueConst::$serverID,
|
||||
'nation' => 0,
|
||||
'data' => Json::encode([
|
||||
'nation' => 0,
|
||||
'name' => '재야',
|
||||
'generals' => $noNationGeneral
|
||||
])
|
||||
]);
|
||||
|
||||
$nationHistory = getNationHistoryLogAll($nation['nation']);
|
||||
|
||||
$serverCnt = $db->queryFirstField('SELECT count(*) FROM ng_games');
|
||||
$serverName = UniqueConst::$serverName;
|
||||
|
||||
$db->update('ng_games', [
|
||||
'winner_nation' => $nation['nation']
|
||||
], 'server_id=%s', UniqueConst::$serverID);
|
||||
|
||||
$db->insert('emperior', [
|
||||
'phase' => $serverName . $serverCnt . '기',
|
||||
'server_id' => UniqueConst::$serverID,
|
||||
'nation_count' => $statNC,
|
||||
'nation_name' => $statNation['nation_name'],
|
||||
'nation_hist' => $statNation['nation_hist'],
|
||||
'gen_count' => $statGC,
|
||||
'personal_hist' => $statGeneral['personal_hist'],
|
||||
'special_hist' => $statGeneral['special_hist'],
|
||||
'name' => $nation['name'],
|
||||
'type' => $nation['type'],
|
||||
'color' => $nation['color'],
|
||||
'year' => $admin['year'],
|
||||
'month' => $admin['month'],
|
||||
'power' => $nation['power'],
|
||||
'gennum' => $nation['gennum'],
|
||||
'citynum' => $cityCnt,
|
||||
'pop' => $pop,
|
||||
'poprate' => $poprate,
|
||||
'gold' => $nation['gold'],
|
||||
'rice' => $nation['rice'],
|
||||
'l12name' => $chiefs[12]['name'],
|
||||
'l12pic' => $chiefs[12]['picture'],
|
||||
'l11name' => $chiefs[11]['name'],
|
||||
'l11pic' => $chiefs[11]['picture'],
|
||||
'l10name' => $chiefs[10]['name'],
|
||||
'l10pic' => $chiefs[10]['picture'],
|
||||
'l9name' => $chiefs[9]['name'],
|
||||
'l9pic' => $chiefs[9]['picture'],
|
||||
'l8name' => $chiefs[8]['name'],
|
||||
'l8pic' => $chiefs[8]['picture'],
|
||||
'l7name' => $chiefs[7]['name'],
|
||||
'l7pic' => $chiefs[7]['picture'],
|
||||
'l6name' => $chiefs[6]['name'],
|
||||
'l6pic' => $chiefs[6]['picture'],
|
||||
'l5name' => $chiefs[5]['name'],
|
||||
'l5pic' => $chiefs[5]['picture'],
|
||||
'tiger' => $tigerstr,
|
||||
'eagle' => $eaglestr,
|
||||
'gen' => $gen,
|
||||
'history' => JSON::encode($nationHistory),
|
||||
'aux' => $statGeneral['aux']
|
||||
]);
|
||||
|
||||
$history = ["<C>●</>{$admin['year']}년 {$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다."];
|
||||
pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
|
||||
|
||||
//연감 월결산
|
||||
LogHistory();
|
||||
}
|
||||
|
||||
+274
-270
@@ -1,270 +1,274 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
|
||||
/**
|
||||
* 템플릿 생성과 관련된 함수들을 모아두는 파일
|
||||
*
|
||||
* NOTE: 아직 converter와 명확한 구분이 되어있지 않음.
|
||||
* TODO: legacy template들을 전부 template 폴더로 모아둘 필요 있음
|
||||
* TODO: side effect를 제거
|
||||
*/
|
||||
|
||||
/**
|
||||
* 관리자 권한이 필요함을 출력.
|
||||
* @return void
|
||||
*/
|
||||
function requireAdminPermissionHTML()
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<!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::printCSS('css/common.css') ?>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
관리자가 아닙니다.<br>
|
||||
<?= banner() ?>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
function turnTable()
|
||||
{
|
||||
|
||||
$turnList = [];
|
||||
$turnList[] = "<option selected value='0'>1턴</option>";
|
||||
foreach (Util::range(1, GameConst::$maxTurn) as $turnIdx) {
|
||||
$turnText = $turnIdx + 1;
|
||||
$turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>";
|
||||
}
|
||||
|
||||
$turnText = join("\n", $turnList);
|
||||
|
||||
return "
|
||||
<select id='generalTurnSelector' name=turn[] size=11 multiple>
|
||||
<option value='-3'>전체</option>
|
||||
<option value='-1'>홀턴</option>
|
||||
<option value='-2'>짝턴</option>
|
||||
{$turnText}
|
||||
</select>
|
||||
";
|
||||
}
|
||||
|
||||
function chiefTurnTable()
|
||||
{
|
||||
$turnList = [];
|
||||
$turnList[] = "<option selected value='0'>1턴</option>";
|
||||
foreach (Util::range(1, GameConst::$maxChiefTurn) as $turnIdx) {
|
||||
$turnText = $turnIdx + 1;
|
||||
$turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>";
|
||||
}
|
||||
|
||||
$turnText = join("\n", $turnList);
|
||||
|
||||
return "
|
||||
<select id='chiefTurnSelector' name=turn[] size=6 multiple>
|
||||
{$turnText}
|
||||
</select>
|
||||
";
|
||||
}
|
||||
|
||||
function displayiActionObjInfo(?iAction $action)
|
||||
{
|
||||
if ($action === null) {
|
||||
$info = '';
|
||||
$text = '-';
|
||||
} else {
|
||||
$info = $action->getInfo();
|
||||
$text = $action->getName();
|
||||
}
|
||||
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
|
||||
return $templates->render('tooltip', [
|
||||
'text' => $text,
|
||||
'info' => $info,
|
||||
]);
|
||||
}
|
||||
function displayCharInfo(string $type): string
|
||||
{
|
||||
$class = buildPersonalityClass($type);
|
||||
$info = $class->getInfo();
|
||||
$text = $class->getName();
|
||||
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
|
||||
return $templates->render('tooltip', [
|
||||
'text' => $text,
|
||||
'info' => $info,
|
||||
]);
|
||||
}
|
||||
|
||||
function displaySpecialWarInfo(?string $type): string
|
||||
{
|
||||
$class = buildGeneralSpecialWarClass($type);
|
||||
$info = $class->getInfo();
|
||||
$name = $class->getName();
|
||||
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
|
||||
return $templates->render('tooltip', [
|
||||
'text' => $name,
|
||||
'info' => $info,
|
||||
]);
|
||||
}
|
||||
|
||||
function displaySpecialDomesticInfo(?string $type): string
|
||||
{
|
||||
$class = buildGeneralSpecialDomesticClass($type);
|
||||
$info = $class->getInfo();
|
||||
$name = $class->getName();
|
||||
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
|
||||
return $templates->render('tooltip', [
|
||||
'text' => $name,
|
||||
'info' => $info,
|
||||
]);
|
||||
}
|
||||
|
||||
function allButton(bool $seizeNPCMode)
|
||||
{
|
||||
if ($seizeNPCMode) {
|
||||
$site = "a_npcList.php";
|
||||
$call = "빙의일람";
|
||||
} else {
|
||||
$site = "a_vote.php";
|
||||
$call = "설문조사";
|
||||
}
|
||||
|
||||
if (\file_exists(__DIR__ . "/d_setting/templates/allButton.php")) {
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/d_setting/templates');
|
||||
} else {
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
}
|
||||
|
||||
|
||||
return $templates->render('allButton', [
|
||||
'call' => $call,
|
||||
'site' => $site
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
function commandButton()
|
||||
{
|
||||
$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 = Util::array_get($nation['color']) ?: '#000000';
|
||||
$fgColor = newColor($bgColor);
|
||||
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
$showSecret = false;
|
||||
$permission = checkSecretPermission($me);
|
||||
if ($permission >= 1) {
|
||||
$showSecret = true;
|
||||
} else if ($me['officer_level'] == 0) {
|
||||
$showSecret = false;
|
||||
}
|
||||
|
||||
return $templates->render('commandButton', [
|
||||
'bgColor' => $bgColor,
|
||||
'fgColor' => $fgColor,
|
||||
'meLevel' => $me['officer_level'],
|
||||
'nationLevel' => $nation['level'],
|
||||
'showSecret' => $showSecret,
|
||||
'permission' => $permission,
|
||||
]);
|
||||
}
|
||||
|
||||
function formatWounded(int $value, int $wound): string
|
||||
{
|
||||
if ($wound == 0) {
|
||||
return "$value";
|
||||
}
|
||||
$woundedValue = intdiv($value * (100 - $wound), 100);
|
||||
return "<font color=red>$woundedValue</font>";
|
||||
}
|
||||
|
||||
function formatDefenceTrain(int $value): string
|
||||
{
|
||||
if ($value === 999) {
|
||||
return "×";
|
||||
} else if ($value >= 80) {
|
||||
return "◎";
|
||||
} else {
|
||||
return "○";
|
||||
}
|
||||
}
|
||||
|
||||
function formatLeadershipBonus(int $value): string
|
||||
{
|
||||
if ($value == 0) {
|
||||
return '';
|
||||
}
|
||||
return "<font color=cyan>+{$value}</font>";
|
||||
}
|
||||
|
||||
function formatName(string $name, int $npc): string
|
||||
{
|
||||
if ($npc == 1) {
|
||||
$name = "<font color='skyblue'>$name</font>";
|
||||
} else if ($npc > 1) {
|
||||
$name = "<font color='cyan'>$name</font>";
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
function getMapHtml(?string $mapTheme = null)
|
||||
{
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
|
||||
if ($mapTheme === null) {
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$mapTheme = $gameStor->map_theme ?? 'che';
|
||||
}
|
||||
|
||||
return $templates->render('map', [
|
||||
'mapTheme' => $mapTheme
|
||||
]);
|
||||
}
|
||||
|
||||
function getInvitationList(array $nationList)
|
||||
{
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
|
||||
foreach ($nationList as &$nation) {
|
||||
$nation['textColor'] = newColor($nation['color']);
|
||||
}
|
||||
return $templates->render('invitationList', [
|
||||
'nationList' => $nationList
|
||||
]);
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
|
||||
/**
|
||||
* 템플릿 생성과 관련된 함수들을 모아두는 파일
|
||||
*
|
||||
* NOTE: 아직 converter와 명확한 구분이 되어있지 않음.
|
||||
* TODO: legacy template들을 전부 template 폴더로 모아둘 필요 있음
|
||||
* TODO: side effect를 제거
|
||||
*/
|
||||
|
||||
/**
|
||||
* 관리자 권한이 필요함을 출력.
|
||||
* @return void
|
||||
*/
|
||||
function requireAdminPermissionHTML()
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<!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::printCSS('css/common.css') ?>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
관리자가 아닙니다.<br>
|
||||
<?= banner() ?>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
function turnTable()
|
||||
{
|
||||
|
||||
$turnList = [];
|
||||
$turnList[] = "<option selected value='0'>1턴</option>";
|
||||
foreach (Util::range(1, GameConst::$maxTurn) as $turnIdx) {
|
||||
$turnText = $turnIdx + 1;
|
||||
$turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>";
|
||||
}
|
||||
|
||||
$turnText = join("\n", $turnList);
|
||||
|
||||
return "
|
||||
<select id='generalTurnSelector' name=turn[] size=11 multiple>
|
||||
<option value='-3'>전체</option>
|
||||
<option value='-1'>홀턴</option>
|
||||
<option value='-2'>짝턴</option>
|
||||
{$turnText}
|
||||
</select>
|
||||
";
|
||||
}
|
||||
|
||||
function chiefTurnTable()
|
||||
{
|
||||
$turnList = [];
|
||||
$turnList[] = "<option selected value='0'>1턴</option>";
|
||||
foreach (Util::range(1, GameConst::$maxChiefTurn) as $turnIdx) {
|
||||
$turnText = $turnIdx + 1;
|
||||
$turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>";
|
||||
}
|
||||
|
||||
$turnText = join("\n", $turnList);
|
||||
|
||||
return "
|
||||
<select id='chiefTurnSelector' name=turn[] size=6 multiple>
|
||||
{$turnText}
|
||||
</select>
|
||||
";
|
||||
}
|
||||
|
||||
function displayiActionObjInfo(?iAction $action)
|
||||
{
|
||||
if ($action === null) {
|
||||
$info = '';
|
||||
$text = '-';
|
||||
} else {
|
||||
$info = $action->getInfo();
|
||||
$text = $action->getName();
|
||||
}
|
||||
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
|
||||
return $templates->render('tooltip', [
|
||||
'text' => $text,
|
||||
'info' => $info,
|
||||
]);
|
||||
}
|
||||
function displayCharInfo(string $type): string
|
||||
{
|
||||
$class = buildPersonalityClass($type);
|
||||
$info = $class->getInfo();
|
||||
$text = $class->getName();
|
||||
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
|
||||
return $templates->render('tooltip', [
|
||||
'text' => $text,
|
||||
'info' => $info,
|
||||
]);
|
||||
}
|
||||
|
||||
function displaySpecialWarInfo(?string $type): string
|
||||
{
|
||||
$class = buildGeneralSpecialWarClass($type);
|
||||
$info = $class->getInfo();
|
||||
$name = $class->getName();
|
||||
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
|
||||
return $templates->render('tooltip', [
|
||||
'text' => $name,
|
||||
'info' => $info,
|
||||
]);
|
||||
}
|
||||
|
||||
function displaySpecialDomesticInfo(?string $type): string
|
||||
{
|
||||
$class = buildGeneralSpecialDomesticClass($type);
|
||||
$info = $class->getInfo();
|
||||
$name = $class->getName();
|
||||
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
|
||||
return $templates->render('tooltip', [
|
||||
'text' => $name,
|
||||
'info' => $info,
|
||||
]);
|
||||
}
|
||||
|
||||
function allButton(bool $seizeNPCMode)
|
||||
{
|
||||
if ($seizeNPCMode) {
|
||||
$site = "a_npcList.php";
|
||||
$call = "빙의일람";
|
||||
} else {
|
||||
$site = "a_vote.php";
|
||||
$call = "설문조사";
|
||||
}
|
||||
|
||||
if (\file_exists(__DIR__ . "/d_setting/templates/allButton.php")) {
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/d_setting/templates');
|
||||
} else {
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
}
|
||||
|
||||
|
||||
return $templates->render('allButton', [
|
||||
'call' => $call,
|
||||
'site' => $site
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
function commandButton()
|
||||
{
|
||||
$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 = Util::array_get($nation['color']) ?: '#000000';
|
||||
$fgColor = newColor($bgColor);
|
||||
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
$showSecret = false;
|
||||
$permission = checkSecretPermission($me);
|
||||
if ($permission >= 1) {
|
||||
$showSecret = true;
|
||||
} else if ($me['officer_level'] == 0) {
|
||||
$showSecret = false;
|
||||
}
|
||||
|
||||
return $templates->render('commandButton', [
|
||||
'bgColor' => $bgColor,
|
||||
'fgColor' => $fgColor,
|
||||
'meLevel' => $me['officer_level'],
|
||||
'nationLevel' => $nation['level'],
|
||||
'showSecret' => $showSecret,
|
||||
'permission' => $permission,
|
||||
]);
|
||||
}
|
||||
|
||||
function formatWounded(int $value, int $wound): string
|
||||
{
|
||||
if ($wound == 0) {
|
||||
return "$value";
|
||||
}
|
||||
$woundedValue = intdiv($value * (100 - $wound), 100);
|
||||
return "<font color=red>$woundedValue</font>";
|
||||
}
|
||||
|
||||
function formatDefenceTrain(int $value): string
|
||||
{
|
||||
if ($value === 999) {
|
||||
return "×";
|
||||
} else if ($value >= 90){
|
||||
return "☆";
|
||||
} else if ($value >= 80) {
|
||||
return "◎";
|
||||
} else if ($value >= 60) {
|
||||
return "○";
|
||||
} else{
|
||||
return "△";
|
||||
}
|
||||
}
|
||||
|
||||
function formatLeadershipBonus(int $value): string
|
||||
{
|
||||
if ($value == 0) {
|
||||
return '';
|
||||
}
|
||||
return "<font color=cyan>+{$value}</font>";
|
||||
}
|
||||
|
||||
function formatName(string $name, int $npc): string
|
||||
{
|
||||
if ($npc == 1) {
|
||||
$name = "<font color='skyblue'>$name</font>";
|
||||
} else if ($npc > 1) {
|
||||
$name = "<font color='cyan'>$name</font>";
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
function getMapHtml(?string $mapTheme = null)
|
||||
{
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
|
||||
if ($mapTheme === null) {
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$mapTheme = $gameStor->map_theme ?? 'che';
|
||||
}
|
||||
|
||||
return $templates->render('map', [
|
||||
'mapTheme' => $mapTheme
|
||||
]);
|
||||
}
|
||||
|
||||
function getInvitationList(array $nationList)
|
||||
{
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
|
||||
foreach ($nationList as &$nation) {
|
||||
$nation['textColor'] = newColor($nation['color']);
|
||||
}
|
||||
return $templates->render('invitationList', [
|
||||
'nationList' => $nationList
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -523,7 +523,7 @@ function selection($tnmt_type, $tnmt, $phase) {
|
||||
if($phase < 31) {
|
||||
$gameStor->phase+=1;
|
||||
} else {
|
||||
$gameStor->tournamemt = 4;
|
||||
$gameStor->tournament = 4;
|
||||
$gameStor->phase=0;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ $scenario = $gameStor->scenario_text;
|
||||
$nationID = $generalObj->getNationID();
|
||||
if($nationID){
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
$nationStor->cacheValues(['notice', 'online_genenerals']);
|
||||
$nationStor->cacheAll();
|
||||
}
|
||||
|
||||
$valid = 0;
|
||||
|
||||
+100
-100
@@ -1,101 +1,101 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include 'lib.php';
|
||||
include "func.php";
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) {
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'affected'=>0,
|
||||
'status'=>'no_reserved_table'
|
||||
]);
|
||||
}
|
||||
|
||||
$reserved = $db->queryFirstRow('SELECT `date`, options FROM reserved_open ORDER BY `date` ASC LIMIT 1');
|
||||
|
||||
if(!$reserved){
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'affected'=>0,
|
||||
'status'=>'no_reserved'
|
||||
]);
|
||||
}
|
||||
|
||||
$reservedDate = new \DateTime($reserved['date']);
|
||||
$now = new \DateTime();
|
||||
|
||||
|
||||
$status = 'not_yet';
|
||||
|
||||
list($isUnited, $lastTurn) = $gameStor->getValuesAsArray(['isunited', 'turntime']);
|
||||
if($isUnited === null || $lastTurn === null){
|
||||
$isUnited = 2;
|
||||
$lastTurn = '2000-01-01';
|
||||
}
|
||||
|
||||
if($lastTurn !== null){
|
||||
$lastTurn = new \DateTime($lastTurn);
|
||||
}
|
||||
|
||||
if($lastTurn === null){
|
||||
//이미 리셋된 상태임
|
||||
}
|
||||
else if(file_exists(__DIR__.'/.htaccess')){
|
||||
//일단 서버는 닫혀 있음
|
||||
}
|
||||
else if(
|
||||
$isUnited == 2 &&
|
||||
$now->getTimestamp() - $lastTurn->getTimestamp() > $reservedDate->getTimestamp() - $now->getTimestamp()
|
||||
){
|
||||
//정지 상태 & 중간 넘음
|
||||
AppConf::getList()[DB::prefix()]->closeServer();
|
||||
$status = 'closed';
|
||||
}
|
||||
else if(
|
||||
$isUnited > 0 &&
|
||||
$now->getTimestamp() - $lastTurn->getTimestamp() > ($reservedDate->getTimestamp() - $now->getTimestamp()) * 2
|
||||
){
|
||||
//천통 & 비정지 상태 & 2/3 넘음
|
||||
AppConf::getList()[DB::prefix()]->closeServer();
|
||||
$status = 'closed';
|
||||
}
|
||||
else if($reservedDate->getTimestamp() - $now->getTimestamp() <= 60*10){
|
||||
//어쨌든 간에 10분 남았다면.
|
||||
AppConf::getList()[DB::prefix()]->closeServer();
|
||||
$status = 'closed';
|
||||
}
|
||||
|
||||
if($now < $reservedDate){
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'affected'=>0,
|
||||
'status'=>$status
|
||||
]);
|
||||
}
|
||||
|
||||
$options = Json::decode($reserved['options']);
|
||||
|
||||
$result = ResetHelper::buildScenario(
|
||||
$options['turnterm'],
|
||||
$options['sync'],
|
||||
$options['scenario'],
|
||||
$options['fiction'],
|
||||
$options['extend'],
|
||||
$options['npcmode'],
|
||||
$options['show_img_level'],
|
||||
$options['tournament_trig'],
|
||||
$options['join_mode'],
|
||||
$options['starttime'],
|
||||
$options['autorun_user']?:null
|
||||
);
|
||||
|
||||
$result['affected']=1;
|
||||
|
||||
$prefix = DB::prefix();
|
||||
AppConf::getList()[$prefix]->openServer();
|
||||
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include 'lib.php';
|
||||
include "func.php";
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) {
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'affected'=>0,
|
||||
'status'=>'no_reserved_table'
|
||||
]);
|
||||
}
|
||||
|
||||
$reserved = $db->queryFirstRow('SELECT `date`, options FROM reserved_open ORDER BY `date` ASC LIMIT 1');
|
||||
|
||||
if(!$reserved){
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'affected'=>0,
|
||||
'status'=>'no_reserved'
|
||||
]);
|
||||
}
|
||||
|
||||
$reservedDate = new \DateTime($reserved['date']);
|
||||
$now = new \DateTime();
|
||||
|
||||
|
||||
$status = 'not_yet';
|
||||
|
||||
list($isUnited, $lastTurn) = $gameStor->getValuesAsArray(['isunited', 'turntime']);
|
||||
if($isUnited === null || $lastTurn === null){
|
||||
$isUnited = 2;
|
||||
$lastTurn = '2000-01-01';
|
||||
}
|
||||
|
||||
if($lastTurn !== null){
|
||||
$lastTurn = new \DateTime($lastTurn);
|
||||
}
|
||||
|
||||
if($lastTurn === null){
|
||||
//이미 리셋된 상태임
|
||||
}
|
||||
else if(file_exists(__DIR__.'/.htaccess')){
|
||||
//일단 서버는 닫혀 있음
|
||||
}
|
||||
else if(
|
||||
$isUnited == 2 &&
|
||||
$now->getTimestamp() - $lastTurn->getTimestamp() > $reservedDate->getTimestamp() - $now->getTimestamp()
|
||||
){
|
||||
//정지 상태 & 중간 넘음
|
||||
ServConfig::getServerList()[DB::prefix()]->closeServer();
|
||||
$status = 'closed';
|
||||
}
|
||||
else if(
|
||||
$isUnited > 0 &&
|
||||
$now->getTimestamp() - $lastTurn->getTimestamp() > ($reservedDate->getTimestamp() - $now->getTimestamp()) * 2
|
||||
){
|
||||
//천통 & 비정지 상태 & 2/3 넘음
|
||||
ServConfig::getServerList()[DB::prefix()]->closeServer();
|
||||
$status = 'closed';
|
||||
}
|
||||
else if($reservedDate->getTimestamp() - $now->getTimestamp() <= 60*10){
|
||||
//어쨌든 간에 10분 남았다면.
|
||||
ServConfig::getServerList()[DB::prefix()]->closeServer();
|
||||
$status = 'closed';
|
||||
}
|
||||
|
||||
if($now < $reservedDate){
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'affected'=>0,
|
||||
'status'=>$status
|
||||
]);
|
||||
}
|
||||
|
||||
$options = Json::decode($reserved['options']);
|
||||
|
||||
$result = ResetHelper::buildScenario(
|
||||
$options['turnterm'],
|
||||
$options['sync'],
|
||||
$options['scenario'],
|
||||
$options['fiction'],
|
||||
$options['extend'],
|
||||
$options['npcmode'],
|
||||
$options['show_img_level'],
|
||||
$options['tournament_trig'],
|
||||
$options['join_mode'],
|
||||
$options['starttime'],
|
||||
$options['autorun_user']?:null
|
||||
);
|
||||
|
||||
$result['affected']=1;
|
||||
|
||||
$prefix = DB::prefix();
|
||||
ServConfig::getServerList()[$prefix]->openServer();
|
||||
|
||||
Json::die($result);
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
|
||||
$destGeneralID = Util::getPost('destGeneralID', 'int', 0);
|
||||
|
||||
if(!$destGeneralID || $destGeneralID <= 0){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 장수 코드입니다'
|
||||
]);
|
||||
}
|
||||
|
||||
$session = Session::requireGameLogin([])->setReadOnly();
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
increaseRefresh("시뮬레이터 추출", 1);
|
||||
|
||||
$userID = Session::getUserID();
|
||||
$me = $db->queryFirstRow('SELECT no,nation from general where owner=%i', $userID);
|
||||
$nationID = $me['nation'];
|
||||
|
||||
$reqColumns = [
|
||||
'nation',
|
||||
'name', 'officer_level', 'explevel', 'injury',
|
||||
'leadership', 'horse', 'strength', 'weapon', 'intel', 'book', 'item',
|
||||
'rice', 'personal', 'special2',
|
||||
'crew', 'crewtype',
|
||||
'atmos', 'train', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'defence_train',
|
||||
];
|
||||
|
||||
$reqRankColumns = [
|
||||
'warnum', 'killnum', 'killcrew'
|
||||
];
|
||||
|
||||
$dummyItems = [
|
||||
'officer_level'=>1,
|
||||
'horse'=>'None',
|
||||
'weapon'=>'None',
|
||||
'book'=>'None',
|
||||
'item'=>'None',
|
||||
'crew'=>0,
|
||||
'crewtype'=>GameUnitConst::DEFAULT_CREWTYPE,
|
||||
'rice'=>10000,
|
||||
'train'=>GameConst::$maxTrainByCommand,
|
||||
'atmos'=>GameConst::$maxTrainByCommand,
|
||||
'dex1'=>0,
|
||||
'dex2'=>0,
|
||||
'dex3'=>0,
|
||||
'dex4'=>0,
|
||||
'dex5'=>0,
|
||||
'defence_train'=>80,
|
||||
'warnum'=>0,
|
||||
'killnum'=>0,
|
||||
'killcrew'=>0,
|
||||
];
|
||||
|
||||
$rawDestGeneral = $db->queryFirstRow('SELECT %l FROM general WHERE no=%i', Util::formatListOfBackticks($reqColumns), $destGeneralID);
|
||||
|
||||
if($nationID == 0 || $rawDestGeneral['nation'] != $nationID){
|
||||
foreach($dummyItems as $key=>$val){
|
||||
$rawDestGeneral[$key] = $val;
|
||||
}
|
||||
}
|
||||
else{
|
||||
$rawRankValue = $db->queryAllLists('SELECT `type`, `value` FROM rank_data WHERE general_id = %i AND `type` IN %ls', $destGeneralID, $reqRankColumns);
|
||||
foreach($rawRankValue as [$rankType, $rankValue]){
|
||||
$rawDestGeneral[$rankType] = $rankValue;
|
||||
}
|
||||
}
|
||||
|
||||
foreach(['dex1', 'dex2', 'dex3', 'dex4', 'dex5'] as $dexKey){
|
||||
$dex = $rawDestGeneral[$dexKey];
|
||||
$rawDestGeneral[$dexKey] = getDexLevelList()[getDexLevel($dex)][0];
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success',
|
||||
'general'=>$rawDestGeneral,
|
||||
]);
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin([]);
|
||||
$generalID = Session::getGeneralID();
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$rawList = Util::convertArrayToDict($db->query('SELECT no, name, npc, nation FROM general'), 'no');
|
||||
$nationID = $rawList[$generalID]['nation'];
|
||||
|
||||
|
||||
$result = [
|
||||
'result'=>true,
|
||||
'reason'=>'success',
|
||||
'nationID'=>$nationID,
|
||||
'generalID'=>$generalID,
|
||||
'column'=>['no', 'name', 'npc']
|
||||
];
|
||||
|
||||
$resultItem = [];
|
||||
foreach(Util::arrayGroupBy($rawList, 'nation') as $subNationID=>$generals){
|
||||
$subNation = [];
|
||||
foreach($generals as $general){
|
||||
$subNation[] = [$general['no'], $general['name'], $general['npc']];
|
||||
}
|
||||
$resultItem[$subNationID] = $subNation;
|
||||
}
|
||||
|
||||
$result['list'] = $resultItem;
|
||||
$result['nation'] = Util::convertArrayToDict($db->query('SELECT nation, name, color FROM nation'), 'nation');
|
||||
Json::die($result);
|
||||
+109
-109
@@ -1,109 +1,109 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
|
||||
//로그인 검사
|
||||
$session = Session::requireLogin();
|
||||
$userID = Session::getUserID();
|
||||
|
||||
$db = DB::db();
|
||||
$withToken = Util::getPost('with_token', 'bool', false);
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
if($session->isGameLoggedIn()){
|
||||
increaseRefresh("장수일람", 2);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'
|
||||
]);
|
||||
}
|
||||
}
|
||||
else{
|
||||
$availableNextCall = $session->availableNextCallGetGeneralList??'2000-01-01 00:00:00';
|
||||
$now = new \DateTimeImmutable();
|
||||
|
||||
if($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>"장수 리스트는 10초에 한번 갱신 가능합니다.\n다음 시간 : ".$availableNextCall
|
||||
]);
|
||||
}
|
||||
|
||||
$availableNextCall = $now->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s');
|
||||
$session->availableNextCallGetGeneralList = $availableNextCall;
|
||||
}
|
||||
|
||||
$session->setReadOnly();
|
||||
|
||||
$rawGeneralList = $db->queryAllLists('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,owner_name as ownerName,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general');
|
||||
|
||||
$ownerNameList = [];
|
||||
if($gameStor->isunited){
|
||||
foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){
|
||||
$ownerNameList[$ownerID] = $ownerName;
|
||||
}
|
||||
}
|
||||
|
||||
$generalList = [];
|
||||
foreach($rawGeneralList as $rawGeneral){
|
||||
[$owner,$no,$picture,$imgsvr,$npc,$age,$nation,$special,$special2,$personal,$name,$ownerName,$injury,$leadership,$strength,$intel,$experience,$dedication,$officerLevel,$killturn,$connectCnt] = $rawGeneral;
|
||||
|
||||
if(key_exists($owner, $ownerNameList)){
|
||||
$ownerName = $ownerNameList[$owner];
|
||||
}
|
||||
|
||||
$nationArr = getNationStaticInfo($nation);
|
||||
$lbonus = calcLeadershipBonus($officerLevel, $nationArr['level']);
|
||||
|
||||
$generalList[] = [
|
||||
$no,
|
||||
$picture,
|
||||
$imgsvr,
|
||||
$npc,
|
||||
$age,
|
||||
$nationArr['name'],
|
||||
getGeneralSpecialDomesticName($special),
|
||||
getGeneralSpecialWarName($special2),
|
||||
getGenChar($personal),
|
||||
$name,
|
||||
$npc==1?$ownerName:null,
|
||||
$injury,
|
||||
$leadership,
|
||||
$lbonus,
|
||||
$strength,
|
||||
$intel,
|
||||
getExpLevel($experience),
|
||||
getHonor($experience),
|
||||
getDed($dedication),
|
||||
getOfficerLevelText($officerLevel, $nationArr['level']),
|
||||
$killturn,
|
||||
$connectCnt
|
||||
];
|
||||
}
|
||||
|
||||
$result = [
|
||||
'result'=>'true',
|
||||
'list'=>$generalList,
|
||||
];
|
||||
|
||||
if($withToken){
|
||||
$now = (new \DateTimeImmutable())->format('Y-m-d H:i:s');
|
||||
$tokens = [];
|
||||
foreach($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token){
|
||||
$validUntil = $token['valid_until'];
|
||||
|
||||
foreach(Json::decode($token['pick_result']) as $pickResult){
|
||||
$tokens[$pickResult['no']]=$pickResult['keepCnt'];
|
||||
}
|
||||
}
|
||||
$result['token'] = $tokens;
|
||||
}
|
||||
|
||||
Json::die($result);
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
|
||||
//로그인 검사
|
||||
$session = Session::requireLogin([]);
|
||||
$userID = Session::getUserID();
|
||||
|
||||
$db = DB::db();
|
||||
$withToken = Util::getPost('with_token', 'bool', false);
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
if($session->isGameLoggedIn()){
|
||||
increaseRefresh("장수일람", 2);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'
|
||||
]);
|
||||
}
|
||||
}
|
||||
else{
|
||||
$availableNextCall = $session->availableNextCallGetGeneralList??'2000-01-01 00:00:00';
|
||||
$now = new \DateTimeImmutable();
|
||||
|
||||
if($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>"장수 리스트는 10초에 한번 갱신 가능합니다.\n다음 시간 : ".$availableNextCall
|
||||
]);
|
||||
}
|
||||
|
||||
$availableNextCall = $now->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s');
|
||||
$session->availableNextCallGetGeneralList = $availableNextCall;
|
||||
}
|
||||
|
||||
$session->setReadOnly();
|
||||
|
||||
$rawGeneralList = $db->queryAllLists('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,owner_name as ownerName,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general');
|
||||
|
||||
$ownerNameList = [];
|
||||
if($gameStor->isunited){
|
||||
foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){
|
||||
$ownerNameList[$ownerID] = $ownerName;
|
||||
}
|
||||
}
|
||||
|
||||
$generalList = [];
|
||||
foreach($rawGeneralList as $rawGeneral){
|
||||
[$owner,$no,$picture,$imgsvr,$npc,$age,$nation,$special,$special2,$personal,$name,$ownerName,$injury,$leadership,$strength,$intel,$experience,$dedication,$officerLevel,$killturn,$connectCnt] = $rawGeneral;
|
||||
|
||||
if(key_exists($owner, $ownerNameList)){
|
||||
$ownerName = $ownerNameList[$owner];
|
||||
}
|
||||
|
||||
$nationArr = getNationStaticInfo($nation);
|
||||
$lbonus = calcLeadershipBonus($officerLevel, $nationArr['level']);
|
||||
|
||||
$generalList[] = [
|
||||
$no,
|
||||
$picture,
|
||||
$imgsvr,
|
||||
$npc,
|
||||
$age,
|
||||
$nationArr['name'],
|
||||
getGeneralSpecialDomesticName($special),
|
||||
getGeneralSpecialWarName($special2),
|
||||
getGenChar($personal),
|
||||
$name,
|
||||
$npc==1?$ownerName:null,
|
||||
$injury,
|
||||
$leadership,
|
||||
$lbonus,
|
||||
$strength,
|
||||
$intel,
|
||||
getExpLevel($experience),
|
||||
getHonor($experience),
|
||||
getDed($dedication),
|
||||
getOfficerLevelText($officerLevel, $nationArr['level']),
|
||||
$killturn,
|
||||
$connectCnt
|
||||
];
|
||||
}
|
||||
|
||||
$result = [
|
||||
'result'=>'true',
|
||||
'list'=>$generalList,
|
||||
];
|
||||
|
||||
if($withToken){
|
||||
$now = (new \DateTimeImmutable())->format('Y-m-d H:i:s');
|
||||
$tokens = [];
|
||||
foreach($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token){
|
||||
$validUntil = $token['valid_until'];
|
||||
|
||||
foreach(Json::decode($token['pick_result']) as $pickResult){
|
||||
$tokens[$pickResult['no']]=$pickResult['keepCnt'];
|
||||
}
|
||||
}
|
||||
$result['token'] = $tokens;
|
||||
}
|
||||
|
||||
Json::die($result);
|
||||
|
||||
+208
-208
@@ -1,209 +1,209 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
|
||||
$session = Session::requireLogin([])->setReadOnly();
|
||||
|
||||
if(!class_exists('\\sammo\\DB')){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'DB리셋 필요'
|
||||
]);
|
||||
}
|
||||
|
||||
$serverName = DB::prefix();
|
||||
$serverAcl = $session->acl[$serverName]??[];
|
||||
$allowReset = in_array('reset', $serverAcl);
|
||||
$allowFullReset = in_array('fullReset',$serverAcl);
|
||||
$allowReset |= $allowFullReset;
|
||||
|
||||
$reserve_open = Util::getPost('reserve_open');
|
||||
if($reserve_open && $reserve_open < date('Y-m-d H:i')){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'현재 시간보다 이전 시간대를 예약 시간으로 지정했습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$pre_reserve_open = Util::getPost('pre_reserve_open');
|
||||
if($pre_reserve_open && !$reserve_open){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'가오픈 예약을 위해선 오픈 예약을 지정해야합니다.'
|
||||
]);
|
||||
}
|
||||
if($pre_reserve_open && $pre_reserve_open >= $reserve_open){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'가오픈 시간이 오픈 예약 시점보다 이전이어야 합니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if($session->userGrade < 5 && !$allowReset){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'관리자 아님'
|
||||
]);
|
||||
}
|
||||
|
||||
$v = new Validator($_POST);
|
||||
$v->rule('required', [
|
||||
'turnterm',
|
||||
'sync',
|
||||
'scenario',
|
||||
'fiction',
|
||||
'extend',
|
||||
'join_mode',
|
||||
'npcmode',
|
||||
'show_img_level',
|
||||
'autorun_user_minutes'
|
||||
])->rule('integer', [
|
||||
'turnterm',
|
||||
'sync',
|
||||
'scenario',
|
||||
'fiction',
|
||||
'extend',
|
||||
'npcmode',
|
||||
'show_img_level',
|
||||
'tournament_trig',
|
||||
'autorun_user_minutes'
|
||||
])->rule('in', 'join_mode', ['onlyRandom', 'full']);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$allowReset = true;
|
||||
if($session->userGrade < 5 && !$allowFullReset){
|
||||
//리셋 가능한 조건인지 테스트
|
||||
$allowReset = false;
|
||||
|
||||
if(file_exists(__DIR__.'/.htaccess')){
|
||||
$allowReset = true;
|
||||
}
|
||||
else{
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
if($gameStor->isunited){
|
||||
$allowReset = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!$allowReset){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'부족한 권한: 서버가 닫혀있거나, 천통되어 있을 경우에만 리셋 가능합니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$turnterm = (int)$_POST['turnterm'];
|
||||
$sync = (int)$_POST['sync'];
|
||||
$scenario = (int)$_POST['scenario'];
|
||||
$fiction = (int)$_POST['fiction'];
|
||||
$extend = (int)$_POST['extend'];
|
||||
$npcmode = (int)$_POST['npcmode'];
|
||||
$show_img_level = (int)$_POST['show_img_level'];
|
||||
$tournament_trig = (int)$_POST['tournament_trig'];
|
||||
$join_mode = $_POST['join_mode'];
|
||||
$autorun_user_minutes = (int)$_POST['autorun_user_minutes'];
|
||||
$autorun_user_options = [];
|
||||
foreach(Util::getPost('autorun_user', 'array_string', []) as $autorun_option){
|
||||
$autorun_user_options[$autorun_option] = 1;
|
||||
}
|
||||
|
||||
if($autorun_user_minutes > 0 && !$autorun_user_options){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'적어도 자동 행동 중 하나는 선택을 해야합니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if($autorun_user_minutes < 0){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'자동 행동 기한이 0보다 작을 수 없습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$autorun_user = $autorun_user_minutes?[
|
||||
'limit_minutes'=>$autorun_user_minutes,
|
||||
'options'=>$autorun_user_options
|
||||
]:null;
|
||||
|
||||
if($reserve_open){
|
||||
$reserve_open = new \DateTime($reserve_open);
|
||||
$db = DB::db();
|
||||
|
||||
if (!$db->queryFirstField("SHOW TABLES LIKE 'storage'")) {
|
||||
$clearResult = ResetHelper::clearDB();
|
||||
if(!$clearResult['result']){
|
||||
Json::die($clearResult);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'예약 테이블이 없음!'
|
||||
]);
|
||||
}
|
||||
|
||||
$scenarioObj = new Scenario($scenario, true);
|
||||
$open_date = $reserve_open->format('Y-m-d H:i:s');
|
||||
|
||||
$reserveInfo = [
|
||||
'turnterm'=>$turnterm,
|
||||
'sync'=>$sync,
|
||||
'scenario'=>$scenario,
|
||||
'scenarioName'=>$scenarioObj->getTitle(),
|
||||
'fiction'=>$fiction,
|
||||
'extend'=>$extend,
|
||||
'npcmode'=>$npcmode,
|
||||
'show_img_level'=>$show_img_level,
|
||||
'tournament_trig'=>$tournament_trig,
|
||||
'gameConf'=>$scenarioObj->getGameConf(),
|
||||
'join_mode'=>$join_mode,
|
||||
'starttime'=>$open_date,
|
||||
'autorun_user'=>$autorun_user
|
||||
];
|
||||
|
||||
|
||||
if($pre_reserve_open){
|
||||
$pre_reserve_open = new \DateTime($pre_reserve_open);
|
||||
$open_date = $pre_reserve_open->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
|
||||
|
||||
$db->delete('reserved_open', true);
|
||||
$db->insert('reserved_open', [
|
||||
'options'=>Json::encode($reserveInfo),
|
||||
'date'=>$open_date
|
||||
]);
|
||||
AppConf::getList()[DB::prefix()]->closeServer();
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'예약'
|
||||
]);
|
||||
}
|
||||
|
||||
Json::die(ResetHelper::buildScenario(
|
||||
$turnterm,
|
||||
$sync,
|
||||
$scenario,
|
||||
$fiction,
|
||||
$extend,
|
||||
$npcmode,
|
||||
$show_img_level,
|
||||
$tournament_trig,
|
||||
$join_mode,
|
||||
TimeUtil::now(),
|
||||
$autorun_user
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
|
||||
$session = Session::requireLogin([])->setReadOnly();
|
||||
|
||||
if(!class_exists('\\sammo\\DB')){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'DB리셋 필요'
|
||||
]);
|
||||
}
|
||||
|
||||
$serverName = DB::prefix();
|
||||
$serverAcl = $session->acl[$serverName]??[];
|
||||
$allowReset = in_array('reset', $serverAcl);
|
||||
$allowFullReset = in_array('fullReset',$serverAcl);
|
||||
$allowReset |= $allowFullReset;
|
||||
|
||||
$reserve_open = Util::getPost('reserve_open');
|
||||
if($reserve_open && $reserve_open < date('Y-m-d H:i')){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'현재 시간보다 이전 시간대를 예약 시간으로 지정했습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$pre_reserve_open = Util::getPost('pre_reserve_open');
|
||||
if($pre_reserve_open && !$reserve_open){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'가오픈 예약을 위해선 오픈 예약을 지정해야합니다.'
|
||||
]);
|
||||
}
|
||||
if($pre_reserve_open && $pre_reserve_open >= $reserve_open){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'가오픈 시간이 오픈 예약 시점보다 이전이어야 합니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if($session->userGrade < 5 && !$allowReset){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'관리자 아님'
|
||||
]);
|
||||
}
|
||||
|
||||
$v = new Validator($_POST);
|
||||
$v->rule('required', [
|
||||
'turnterm',
|
||||
'sync',
|
||||
'scenario',
|
||||
'fiction',
|
||||
'extend',
|
||||
'join_mode',
|
||||
'npcmode',
|
||||
'show_img_level',
|
||||
'autorun_user_minutes'
|
||||
])->rule('integer', [
|
||||
'turnterm',
|
||||
'sync',
|
||||
'scenario',
|
||||
'fiction',
|
||||
'extend',
|
||||
'npcmode',
|
||||
'show_img_level',
|
||||
'tournament_trig',
|
||||
'autorun_user_minutes'
|
||||
])->rule('in', 'join_mode', ['onlyRandom', 'full']);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$allowReset = true;
|
||||
if($session->userGrade < 5 && !$allowFullReset){
|
||||
//리셋 가능한 조건인지 테스트
|
||||
$allowReset = false;
|
||||
|
||||
if(file_exists(__DIR__.'/.htaccess')){
|
||||
$allowReset = true;
|
||||
}
|
||||
else{
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
if($gameStor->isunited){
|
||||
$allowReset = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!$allowReset){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'부족한 권한: 서버가 닫혀있거나, 천통되어 있을 경우에만 리셋 가능합니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$turnterm = (int)$_POST['turnterm'];
|
||||
$sync = (int)$_POST['sync'];
|
||||
$scenario = (int)$_POST['scenario'];
|
||||
$fiction = (int)$_POST['fiction'];
|
||||
$extend = (int)$_POST['extend'];
|
||||
$npcmode = (int)$_POST['npcmode'];
|
||||
$show_img_level = (int)$_POST['show_img_level'];
|
||||
$tournament_trig = (int)$_POST['tournament_trig'];
|
||||
$join_mode = $_POST['join_mode'];
|
||||
$autorun_user_minutes = (int)$_POST['autorun_user_minutes'];
|
||||
$autorun_user_options = [];
|
||||
foreach(Util::getPost('autorun_user', 'array_string', []) as $autorun_option){
|
||||
$autorun_user_options[$autorun_option] = 1;
|
||||
}
|
||||
|
||||
if($autorun_user_minutes > 0 && !$autorun_user_options){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'적어도 자동 행동 중 하나는 선택을 해야합니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if($autorun_user_minutes < 0){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'자동 행동 기한이 0보다 작을 수 없습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$autorun_user = $autorun_user_minutes?[
|
||||
'limit_minutes'=>$autorun_user_minutes,
|
||||
'options'=>$autorun_user_options
|
||||
]:null;
|
||||
|
||||
if($reserve_open){
|
||||
$reserve_open = new \DateTime($reserve_open);
|
||||
$db = DB::db();
|
||||
|
||||
if (!$db->queryFirstField("SHOW TABLES LIKE 'storage'")) {
|
||||
$clearResult = ResetHelper::clearDB();
|
||||
if(!$clearResult['result']){
|
||||
Json::die($clearResult);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'예약 테이블이 없음!'
|
||||
]);
|
||||
}
|
||||
|
||||
$scenarioObj = new Scenario($scenario, true);
|
||||
$open_date = $reserve_open->format('Y-m-d H:i:s');
|
||||
|
||||
$reserveInfo = [
|
||||
'turnterm'=>$turnterm,
|
||||
'sync'=>$sync,
|
||||
'scenario'=>$scenario,
|
||||
'scenarioName'=>$scenarioObj->getTitle(),
|
||||
'fiction'=>$fiction,
|
||||
'extend'=>$extend,
|
||||
'npcmode'=>$npcmode,
|
||||
'show_img_level'=>$show_img_level,
|
||||
'tournament_trig'=>$tournament_trig,
|
||||
'gameConf'=>$scenarioObj->getGameConf(),
|
||||
'join_mode'=>$join_mode,
|
||||
'starttime'=>$open_date,
|
||||
'autorun_user'=>$autorun_user
|
||||
];
|
||||
|
||||
|
||||
if($pre_reserve_open){
|
||||
$pre_reserve_open = new \DateTime($pre_reserve_open);
|
||||
$open_date = $pre_reserve_open->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
|
||||
|
||||
$db->delete('reserved_open', true);
|
||||
$db->insert('reserved_open', [
|
||||
'options'=>Json::encode($reserveInfo),
|
||||
'date'=>$open_date
|
||||
]);
|
||||
ServConfig::getServerList()[DB::prefix()]->closeServer();
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'예약'
|
||||
]);
|
||||
}
|
||||
|
||||
Json::die(ResetHelper::buildScenario(
|
||||
$turnterm,
|
||||
$sync,
|
||||
$scenario,
|
||||
$fiction,
|
||||
$extend,
|
||||
$npcmode,
|
||||
$show_img_level,
|
||||
$tournament_trig,
|
||||
$join_mode,
|
||||
TimeUtil::now(),
|
||||
$autorun_user
|
||||
));
|
||||
+102
-102
@@ -1,103 +1,103 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
|
||||
$session = Session::requireLogin([])->setReadOnly();
|
||||
if($session->userGrade < 6){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'관리자 아님'
|
||||
]);
|
||||
}
|
||||
|
||||
$fullReset = Util::getPost('full_reset', 'bool', false);
|
||||
$host = Util::getPost('db_host');
|
||||
$port = Util::getPost('db_port', 'int');
|
||||
$username = Util::getPost('db_id');
|
||||
$password = Util::getPost('db_pw');
|
||||
$dbName = Util::getPost('db_name');
|
||||
|
||||
if(!$host || !$port || !$username || !$password || !$dbName){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'입력 값이 올바르지 않습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if($fullReset && class_exists('\\sammo\\DB')){
|
||||
$mysqli_obj = DB::db()->get();
|
||||
|
||||
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($fullReset){
|
||||
FileUtil::delInDir(__DIR__."/logs");
|
||||
FileUtil::delInDir(__DIR__."/data");
|
||||
if(file_exists(__DIR__.'/d_setting/DB.php')){
|
||||
@unlink(__DIR__.'/d_setting/DB.php');
|
||||
}
|
||||
if(file_exists(__DIR__.'/d_setting/UniqueConst.php')){
|
||||
@unlink(__DIR__.'/d_setting/UniqueConst.php');
|
||||
}
|
||||
}
|
||||
|
||||
function dbConnFail($params){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'DB 접속에 실패했습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
$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__);
|
||||
|
||||
$result = Util::generateFileUsingSimpleTemplate(
|
||||
__DIR__.'/d_setting/DB.orig.php',
|
||||
__DIR__.'/d_setting/DB.php',[
|
||||
'host'=>$host,
|
||||
'user'=>$username,
|
||||
'password'=>$password,
|
||||
'dbName'=>$dbName,
|
||||
'port'=>$port,
|
||||
'prefix'=>$prefix
|
||||
], true
|
||||
);
|
||||
|
||||
|
||||
|
||||
if($result !== true){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$result
|
||||
]);
|
||||
}
|
||||
|
||||
ResetHelper::clearDB();
|
||||
|
||||
AppConf::getList()[$prefix]->closeServer();
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success'
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
|
||||
$session = Session::requireLogin([])->setReadOnly();
|
||||
if($session->userGrade < 6){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'관리자 아님'
|
||||
]);
|
||||
}
|
||||
|
||||
$fullReset = Util::getPost('full_reset', 'bool', false);
|
||||
$host = Util::getPost('db_host');
|
||||
$port = Util::getPost('db_port', 'int');
|
||||
$username = Util::getPost('db_id');
|
||||
$password = Util::getPost('db_pw');
|
||||
$dbName = Util::getPost('db_name');
|
||||
|
||||
if(!$host || !$port || !$username || !$password || !$dbName){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'입력 값이 올바르지 않습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
if($fullReset && class_exists('\\sammo\\DB')){
|
||||
$mysqli_obj = DB::db()->get();
|
||||
|
||||
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($fullReset){
|
||||
FileUtil::delInDir(__DIR__."/logs");
|
||||
FileUtil::delInDir(__DIR__."/data");
|
||||
if(file_exists(__DIR__.'/d_setting/DB.php')){
|
||||
@unlink(__DIR__.'/d_setting/DB.php');
|
||||
}
|
||||
if(file_exists(__DIR__.'/d_setting/UniqueConst.php')){
|
||||
@unlink(__DIR__.'/d_setting/UniqueConst.php');
|
||||
}
|
||||
}
|
||||
|
||||
function dbConnFail($params){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'DB 접속에 실패했습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
$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__);
|
||||
|
||||
$result = Util::generateFileUsingSimpleTemplate(
|
||||
__DIR__.'/d_setting/DB.orig.php',
|
||||
__DIR__.'/d_setting/DB.php',[
|
||||
'host'=>$host,
|
||||
'user'=>$username,
|
||||
'password'=>$password,
|
||||
'dbName'=>$dbName,
|
||||
'port'=>$port,
|
||||
'prefix'=>$prefix
|
||||
], true
|
||||
);
|
||||
|
||||
|
||||
|
||||
if($result !== true){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$result
|
||||
]);
|
||||
}
|
||||
|
||||
ResetHelper::clearDB();
|
||||
|
||||
ServConfig::getServerList()[$prefix]->closeServer();
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success'
|
||||
]);
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
use Nette\Caching\Cache;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
if(!class_exists('\\sammo\\UniqueConst')){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'서버 초기화되지 않음'
|
||||
]);
|
||||
}
|
||||
|
||||
if(!prepareDir('data/file_cache')){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'cache 불가'
|
||||
]);
|
||||
}
|
||||
|
||||
$storage = new \Nette\Caching\Storages\FileStorage('data/file_cache');
|
||||
$cache = new Cache($storage);
|
||||
$serverID = UniqueConst::$serverID;
|
||||
|
||||
$mapInfo = $cache->load("recent_map");
|
||||
//로그인 검사
|
||||
|
||||
$now = time();
|
||||
|
||||
if($mapInfo && ($now - $mapInfo['timestamp'] < 600)){
|
||||
$mapEtag = $mapInfo['etag'];
|
||||
$mapModified = $mapInfo['timestamp'];
|
||||
|
||||
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $mapModified)." GMT");
|
||||
header("Etag: $mapEtag");
|
||||
|
||||
if (
|
||||
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']??'2000-01-01') === $mapModified ||
|
||||
trim($_SERVER['HTTP_IF_NONE_MATCH']??'') === $mapEtag
|
||||
) {
|
||||
header("HTTP/1.1 304 Not Modified");
|
||||
die();
|
||||
}
|
||||
|
||||
Json::die($mapInfo['data'], 0);
|
||||
}
|
||||
|
||||
$defaultPost = [
|
||||
'year' => null,
|
||||
'month' => null,
|
||||
'aux' => null,
|
||||
'neutralView' => true,
|
||||
'showMe' => false,
|
||||
];
|
||||
|
||||
$history = formatHistoryToHTML(getGlobalHistoryLogRecent(10));
|
||||
$rawMap = getWorldMap([
|
||||
'year' => null,
|
||||
'month' => null,
|
||||
'aux' => null,
|
||||
'neutralView' => true,
|
||||
'showMe' => false,
|
||||
]);
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$mapTheme = $gameStor->map_theme ?? 'che';
|
||||
|
||||
$rawMap['history'] = $history;
|
||||
$rawMap['theme'] = $mapTheme;
|
||||
|
||||
$etag = hash('sha256', $serverID.$now);
|
||||
$map = [
|
||||
'etag'=>$etag,
|
||||
'timestamp'=>$now,
|
||||
'data'=>$rawMap,
|
||||
];
|
||||
$cache->save("recent_map", $map);
|
||||
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $now)." GMT");
|
||||
header("Etag: $etag");
|
||||
|
||||
Json::die($map['data'], 0);
|
||||
+360
-359
@@ -1,360 +1,361 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
|
||||
$action = Util::getPost('action');
|
||||
$officerLevel = Util::getPost('officerLevel', 'int');
|
||||
$destGeneralID = Util::getPost('destGeneralID', 'int');
|
||||
$destCityID = Util::getPost('destCityID', 'int');
|
||||
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin()->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$gameStor->cacheValues(['startyear','year','month','scenario']);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no,nation,officer_level from general where owner=%i', $userID);
|
||||
$myOfficerLevel = $me['officer_level'];
|
||||
$nationID = $me['nation'];
|
||||
|
||||
//수뇌가 아니면 아무것도 할 수 없음
|
||||
if($myOfficerLevel < 5){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'수뇌가 아닙니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if($action === '추방' && $destGeneralID==0){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'장수가 지정되지 않았습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if($destGeneralID==0){
|
||||
$general = new DummyGeneral(true);
|
||||
}
|
||||
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',
|
||||
], 1);
|
||||
|
||||
if($general instanceof DummyGeneral){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 장수입니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if($nationID != $general->getNationID()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'아국 장수가 아닙니다'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if($officerLevel == 12){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'군주를 대상으로 할 수 없습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
function do수뇌임명(General $general, int $targetOfficerLevel):?string{
|
||||
$generalID = $general->getID();
|
||||
$nationID = $general->getNationID();
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
[$chiefSet, $nationLevel] = $db->queryFirstList('SELECT chief_set,level FROM nation WHERE nation = %i',$nationID);
|
||||
|
||||
// 임명가능 레벨
|
||||
$lv = getNationChiefLevel($nationLevel);
|
||||
|
||||
if($targetOfficerLevel < $lv){
|
||||
return '임명불가능한 관직입니다.';
|
||||
}
|
||||
|
||||
if(isOfficerSet($chiefSet, $targetOfficerLevel)){
|
||||
return '지금은 임명할 수 없습니다.';
|
||||
}
|
||||
|
||||
//기존 장수 일반으로
|
||||
$db->update('general', [
|
||||
'officer_level'=>1,
|
||||
'officer_city'=>0,
|
||||
], 'nation=%i AND officer_level=%i AND no!=%i', $nationID, $targetOfficerLevel, $generalID);
|
||||
|
||||
if($targetOfficerLevel === 11){
|
||||
|
||||
}
|
||||
else if($targetOfficerLevel % 2 == 0){
|
||||
if($general->getVar('strength') < GameConst::$chiefStatMin){
|
||||
return '무력이 부족합니다.';
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
if($general->getVar('intel') < GameConst::$chiefStatMin){
|
||||
return '지력이 부족합니다.';
|
||||
}
|
||||
}
|
||||
|
||||
//신임 장수
|
||||
$general->setVar('officer_level', $targetOfficerLevel);
|
||||
$general->setVar('officer_city', 0);
|
||||
$db->update('nation', [
|
||||
'chief_set'=> $db->sqleval('chief_set | %i', doOfficerSet(0, $targetOfficerLevel)),
|
||||
], 'nation=%i', $nationID);
|
||||
$general->applyDB($db);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function do도시임명(General $general, int $cityID, int $targetOfficerLevel):?string{
|
||||
$nationID = $general->getNationID();
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
if(CityConst::byID($cityID) === null){
|
||||
return '올바르지 않은 도시입니다';
|
||||
}
|
||||
|
||||
$officerSet = $db->queryFirstField('SELECT officer_set FROM city WHERE nation=%i AND city=%i', $nationID, $cityID);
|
||||
if($officerSet === null){
|
||||
return '아국 도시가 아닙니다';
|
||||
}
|
||||
|
||||
if(isOfficerSet($officerSet, $targetOfficerLevel)){
|
||||
return '이미 다른 장수가 임명되어있습니다';
|
||||
}
|
||||
|
||||
//기존 장수 일반으로
|
||||
$db->update('general', [
|
||||
'officer_level'=>1,
|
||||
'officer_city'=>0,
|
||||
], 'officer_level=%i AND officer_city=%i AND no!=%i', $targetOfficerLevel, $cityID, $general->getID());
|
||||
|
||||
if($general instanceof DummyGeneral){
|
||||
return null;
|
||||
}
|
||||
|
||||
if($targetOfficerLevel === 4 && $general->getVar('strength') < GameConst::$chiefStatMin){
|
||||
return '무력이 부족합니다.';
|
||||
}
|
||||
|
||||
if($targetOfficerLevel === 3 && $general->getVar('intel') < GameConst::$chiefStatMin){
|
||||
return '지력이 부족합니다.';
|
||||
}
|
||||
|
||||
//신임 장수
|
||||
$db->update('city', [
|
||||
'officer_set'=>$db->sqleval('officer_set | %i', doOfficerSet(0, $targetOfficerLevel)),
|
||||
], 'city=%i AND nation=%i', $cityID, $nationID);
|
||||
$general->setVar('officer_level', $targetOfficerLevel);
|
||||
$general->setVar('officer_city', $cityID);
|
||||
$general->applyDB($db);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function do추방(General $general, int $myOfficerLevel):?string{
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getVar('name');
|
||||
$nationID = $general->getNationID();
|
||||
|
||||
|
||||
|
||||
//추방할사람이 외교권자이면 불가
|
||||
$permission = checkSecretPermission($general->getRaw());
|
||||
if($permission == 4){
|
||||
return '외교권자는 추방할 수 없습니다.';
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$env = $gameStor->getValues(['startyear','year','month','scenario']);
|
||||
|
||||
$nation = $db->queryFirstRow('SELECT name,chief_set,color FROM nation WHERE nation=%i', $nationID);
|
||||
$nationName = $nation['name'];
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
//이미 지정했다면 무시
|
||||
if(isOfficerSet($nation['chief_set'], $myOfficerLevel) || ($myOfficerLevel == 0 && $myOfficerLevel == 12)) {
|
||||
return '이미 추방 권한을 사용했습니다.';
|
||||
}
|
||||
$gold = 0;
|
||||
$rice = 0;
|
||||
// 금쌀1000이상은 남김
|
||||
if($general->getVar('gold') > GameConst::$defaultGold) {
|
||||
$gold = $general->getVar('gold') - GameConst::$defaultGold;
|
||||
$general->setVar('gold', GameConst::$defaultGold);
|
||||
}
|
||||
if($general->getVar('rice') > GameConst::$defaultRice) {
|
||||
$rice = $general->getVar('rice') - GameConst::$defaultRice;
|
||||
$general->setVar('rice', GameConst::$defaultRice);
|
||||
}
|
||||
|
||||
$general->setVar('nation', 0);
|
||||
$general->setVar('officer_level', 0);
|
||||
$general->setVar('officer_city', 0);
|
||||
$general->setVar('belong', 0);
|
||||
$oldMakeLimit = $general->getVar('makelimit');
|
||||
$general->setVar('makelimit', 12);
|
||||
$general->setVar('permission', 'normal');
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <D><b>{$nationName}</b></>에서 <R>추방</>당했습니다.");
|
||||
$logger->pushGeneralActionLog("<D><b>{$nationName}</b></>에서 <R>추방</>당했습니다.", ActionLogger::PLAIN);
|
||||
|
||||
// 명성/공헌 N*10%감소
|
||||
if($env['year'] <= $env['startyear'] && $general->getNPCType() < 2){
|
||||
$general->setVar('makelimit', $oldMakeLimit);
|
||||
}
|
||||
else{
|
||||
$betrayCnt = $general->getVar('betray');
|
||||
$general->addExperience(-$general->getVar('experience')*0.1*$betrayCnt);
|
||||
$general->addDedication(-$general->getVar('dedication')*0.1*$betrayCnt);
|
||||
$general->increaseVarWithLimit('betray', 1, null, GameConst::$maxBetrayCnt);
|
||||
}
|
||||
|
||||
//부대장일 경우
|
||||
if($general->getVar('troop') == $generalID){
|
||||
// 모두 탈퇴
|
||||
$db->update('general', [
|
||||
'troop'=>0,
|
||||
], 'troop = %i', $generalID);
|
||||
$db->delete('troop', 'troop_leader=%i', $generalID);
|
||||
}
|
||||
$general->setVar('troop', 0);
|
||||
|
||||
if($general->getNPCType() >= 2 && ($env['scenario'] < 100 || Util::randBool(0.01))) {
|
||||
|
||||
$str = Util::choiceRandom([
|
||||
'날 버리다니... 곧 전장에서 복수해주겠다...',
|
||||
'추방이라... 내가 무얼 잘못했단 말인가...',
|
||||
'어디 추방해가면서 잘되나 보자... 꼭 복수하겠다...',
|
||||
'인덕이 제일이거늘... 추방이 웬말인가... 저주한다!',
|
||||
'날 추방했으니 그 복수로 적국에 정보를 팔아 넘겨야겠군요. 그럼 이만.'
|
||||
]);
|
||||
|
||||
$src = new MessageTarget(
|
||||
$generalID,
|
||||
$generalName,
|
||||
$nationID,
|
||||
$nation['name'],
|
||||
$nation['color'],
|
||||
GetImageURL($general->getVar('imgsvr'), $general->getVar('picture'))
|
||||
);
|
||||
$msg = new Message(
|
||||
Message::MSGTYPE_PUBLIC,
|
||||
$src,
|
||||
$src,
|
||||
$str,
|
||||
new \DateTime(),
|
||||
new \DateTime('9999-12-31'),
|
||||
[]
|
||||
);
|
||||
$msg->send();
|
||||
}
|
||||
|
||||
if($env['year'] < $env['startyear']+3) {
|
||||
//초반엔 군주 부상 증가(엔장 임관지양)
|
||||
$db->update('general', [
|
||||
'injury'=>$db->sqleval('least(injury + 1, %i)', 80),
|
||||
], 'nation=%i AND officer_level=12', $nationID);
|
||||
|
||||
$db->update('nation', [
|
||||
'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0),
|
||||
'gold'=>$db->sqleval('gold + %i', $gold),
|
||||
'rice'=>$db->sqleval('rice + %i', $rice),
|
||||
], 'nation = %i', $nationID);
|
||||
} else {
|
||||
//이번분기는 추방불가(초반 제외)
|
||||
$db->update('nation', [
|
||||
'chief_set'=>$db->sqleval('chief_set | %i', doOfficerSet(0, $myOfficerLevel)),
|
||||
'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0),
|
||||
'gold'=>$db->sqleval('gold + %i', $gold),
|
||||
'rice'=>$db->sqleval('rice + %i', $rice),
|
||||
], 'nation = %i', $nationID);
|
||||
}
|
||||
|
||||
$logger->pushGeneralHistoryLog("<D>{$nation['name']}</>에서 추방됨");
|
||||
$general->applyDB($db);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($action == "임명") {
|
||||
if(2 <= $officerLevel && $officerLevel <= 4){
|
||||
if(!$destCityID){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'도시가 지정되지 않았습니다.'
|
||||
]);
|
||||
}
|
||||
$result = do도시임명($general, $destCityID, $officerLevel);
|
||||
if($result !== null){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$result
|
||||
]);
|
||||
}
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success'
|
||||
]);
|
||||
}
|
||||
|
||||
if(5 <= $officerLevel && $officerLevel < 12){
|
||||
$result = do수뇌임명($general, $officerLevel);
|
||||
if($result !== null){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$result
|
||||
]);
|
||||
}
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success'
|
||||
]);
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 지정입니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if($action == "추방") {
|
||||
$result = do추방($general, $myOfficerLevel);
|
||||
if($result !== null){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$result
|
||||
]);
|
||||
}
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success'
|
||||
]);
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 명령입니다.'
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
|
||||
$action = Util::getPost('action');
|
||||
$officerLevel = Util::getPost('officerLevel', 'int');
|
||||
$destGeneralID = Util::getPost('destGeneralID', 'int');
|
||||
$destCityID = Util::getPost('destCityID', 'int');
|
||||
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin()->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$gameStor->cacheValues(['startyear','year','month','scenario']);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no,nation,officer_level from general where owner=%i', $userID);
|
||||
$myOfficerLevel = $me['officer_level'];
|
||||
$nationID = $me['nation'];
|
||||
|
||||
//수뇌가 아니면 아무것도 할 수 없음
|
||||
if($myOfficerLevel < 5){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'수뇌가 아닙니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if($action === '추방' && $destGeneralID==0){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'장수가 지정되지 않았습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if($destGeneralID==0){
|
||||
$general = new DummyGeneral(true);
|
||||
$general->setVar('nation', $nationID);
|
||||
}
|
||||
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',
|
||||
], 1);
|
||||
|
||||
if($general instanceof DummyGeneral){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 장수입니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if($nationID != $general->getNationID()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'아국 장수가 아닙니다'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if($officerLevel == 12){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'군주를 대상으로 할 수 없습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
function do수뇌임명(General $general, int $targetOfficerLevel):?string{
|
||||
$generalID = $general->getID();
|
||||
$nationID = $general->getNationID();
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
[$chiefSet, $nationLevel] = $db->queryFirstList('SELECT chief_set,level FROM nation WHERE nation = %i',$nationID);
|
||||
|
||||
// 임명가능 레벨
|
||||
$lv = getNationChiefLevel($nationLevel);
|
||||
|
||||
if($targetOfficerLevel < $lv){
|
||||
return '임명불가능한 관직입니다.';
|
||||
}
|
||||
|
||||
if(isOfficerSet($chiefSet, $targetOfficerLevel)){
|
||||
return '지금은 임명할 수 없습니다.';
|
||||
}
|
||||
|
||||
//기존 장수 일반으로
|
||||
$db->update('general', [
|
||||
'officer_level'=>1,
|
||||
'officer_city'=>0,
|
||||
], 'nation=%i AND officer_level=%i AND no!=%i', $nationID, $targetOfficerLevel, $generalID);
|
||||
|
||||
if($targetOfficerLevel === 11){
|
||||
|
||||
}
|
||||
else if($targetOfficerLevel % 2 == 0){
|
||||
if($general->getVar('strength') < GameConst::$chiefStatMin){
|
||||
return '무력이 부족합니다.';
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
if($general->getVar('intel') < GameConst::$chiefStatMin){
|
||||
return '지력이 부족합니다.';
|
||||
}
|
||||
}
|
||||
|
||||
//신임 장수
|
||||
$general->setVar('officer_level', $targetOfficerLevel);
|
||||
$general->setVar('officer_city', 0);
|
||||
$db->update('nation', [
|
||||
'chief_set'=> $db->sqleval('chief_set | %i', doOfficerSet(0, $targetOfficerLevel)),
|
||||
], 'nation=%i', $nationID);
|
||||
$general->applyDB($db);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function do도시임명(General $general, int $cityID, int $targetOfficerLevel):?string{
|
||||
$nationID = $general->getNationID();
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
if(CityConst::byID($cityID) === null){
|
||||
return '올바르지 않은 도시입니다';
|
||||
}
|
||||
|
||||
$officerSet = $db->queryFirstField('SELECT officer_set FROM city WHERE nation=%i AND city=%i', $nationID, $cityID);
|
||||
if($officerSet === null){
|
||||
return '아국 도시가 아닙니다';
|
||||
}
|
||||
|
||||
if(isOfficerSet($officerSet, $targetOfficerLevel)){
|
||||
return '이미 다른 장수가 임명되어있습니다';
|
||||
}
|
||||
|
||||
//기존 장수 일반으로
|
||||
$db->update('general', [
|
||||
'officer_level'=>1,
|
||||
'officer_city'=>0,
|
||||
], 'officer_level=%i AND officer_city=%i AND no!=%i', $targetOfficerLevel, $cityID, $general->getID());
|
||||
|
||||
if($general instanceof DummyGeneral){
|
||||
return null;
|
||||
}
|
||||
|
||||
if($targetOfficerLevel === 4 && $general->getVar('strength') < GameConst::$chiefStatMin){
|
||||
return '무력이 부족합니다.';
|
||||
}
|
||||
|
||||
if($targetOfficerLevel === 3 && $general->getVar('intel') < GameConst::$chiefStatMin){
|
||||
return '지력이 부족합니다.';
|
||||
}
|
||||
|
||||
//신임 장수
|
||||
$db->update('city', [
|
||||
'officer_set'=>$db->sqleval('officer_set | %i', doOfficerSet(0, $targetOfficerLevel)),
|
||||
], 'city=%i AND nation=%i', $cityID, $nationID);
|
||||
$general->setVar('officer_level', $targetOfficerLevel);
|
||||
$general->setVar('officer_city', $cityID);
|
||||
$general->applyDB($db);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function do추방(General $general, int $myOfficerLevel):?string{
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getVar('name');
|
||||
$nationID = $general->getNationID();
|
||||
|
||||
|
||||
|
||||
//추방할사람이 외교권자이면 불가
|
||||
$permission = checkSecretPermission($general->getRaw());
|
||||
if($permission == 4){
|
||||
return '외교권자는 추방할 수 없습니다.';
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$env = $gameStor->getValues(['startyear','year','month','scenario']);
|
||||
|
||||
$nation = $db->queryFirstRow('SELECT name,chief_set,color FROM nation WHERE nation=%i', $nationID);
|
||||
$nationName = $nation['name'];
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
//이미 지정했다면 무시
|
||||
if(isOfficerSet($nation['chief_set'], $myOfficerLevel) || ($myOfficerLevel == 0 && $myOfficerLevel == 12)) {
|
||||
return '이미 추방 권한을 사용했습니다.';
|
||||
}
|
||||
$gold = 0;
|
||||
$rice = 0;
|
||||
// 금쌀1000이상은 남김
|
||||
if($general->getVar('gold') > GameConst::$defaultGold) {
|
||||
$gold = $general->getVar('gold') - GameConst::$defaultGold;
|
||||
$general->setVar('gold', GameConst::$defaultGold);
|
||||
}
|
||||
if($general->getVar('rice') > GameConst::$defaultRice) {
|
||||
$rice = $general->getVar('rice') - GameConst::$defaultRice;
|
||||
$general->setVar('rice', GameConst::$defaultRice);
|
||||
}
|
||||
|
||||
$general->setVar('nation', 0);
|
||||
$general->setVar('officer_level', 0);
|
||||
$general->setVar('officer_city', 0);
|
||||
$general->setVar('belong', 0);
|
||||
$oldMakeLimit = $general->getVar('makelimit');
|
||||
$general->setVar('makelimit', 12);
|
||||
$general->setVar('permission', 'normal');
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <D><b>{$nationName}</b></>에서 <R>추방</>당했습니다.");
|
||||
$logger->pushGeneralActionLog("<D><b>{$nationName}</b></>에서 <R>추방</>당했습니다.", ActionLogger::PLAIN);
|
||||
|
||||
// 명성/공헌 N*10%감소
|
||||
if($env['year'] <= $env['startyear'] && $general->getNPCType() < 2){
|
||||
$general->setVar('makelimit', $oldMakeLimit);
|
||||
}
|
||||
else{
|
||||
$betrayCnt = $general->getVar('betray');
|
||||
$general->addExperience(-$general->getVar('experience')*0.1*$betrayCnt);
|
||||
$general->addDedication(-$general->getVar('dedication')*0.1*$betrayCnt);
|
||||
$general->increaseVarWithLimit('betray', 1, null, GameConst::$maxBetrayCnt);
|
||||
}
|
||||
|
||||
//부대장일 경우
|
||||
if($general->getVar('troop') == $generalID){
|
||||
// 모두 탈퇴
|
||||
$db->update('general', [
|
||||
'troop'=>0,
|
||||
], 'troop = %i', $generalID);
|
||||
$db->delete('troop', 'troop_leader=%i', $generalID);
|
||||
}
|
||||
$general->setVar('troop', 0);
|
||||
|
||||
if($general->getNPCType() >= 2 && ($env['scenario'] < 100 || Util::randBool(0.01))) {
|
||||
|
||||
$str = Util::choiceRandom([
|
||||
'날 버리다니... 곧 전장에서 복수해주겠다...',
|
||||
'추방이라... 내가 무얼 잘못했단 말인가...',
|
||||
'어디 추방해가면서 잘되나 보자... 꼭 복수하겠다...',
|
||||
'인덕이 제일이거늘... 추방이 웬말인가... 저주한다!',
|
||||
'날 추방했으니 그 복수로 적국에 정보를 팔아 넘겨야겠군요. 그럼 이만.'
|
||||
]);
|
||||
|
||||
$src = new MessageTarget(
|
||||
$generalID,
|
||||
$generalName,
|
||||
$nationID,
|
||||
$nation['name'],
|
||||
$nation['color'],
|
||||
GetImageURL($general->getVar('imgsvr'), $general->getVar('picture'))
|
||||
);
|
||||
$msg = new Message(
|
||||
Message::MSGTYPE_PUBLIC,
|
||||
$src,
|
||||
$src,
|
||||
$str,
|
||||
new \DateTime(),
|
||||
new \DateTime('9999-12-31'),
|
||||
[]
|
||||
);
|
||||
$msg->send();
|
||||
}
|
||||
|
||||
if($env['year'] < $env['startyear']+3) {
|
||||
//초반엔 군주 부상 증가(엔장 임관지양)
|
||||
$db->update('general', [
|
||||
'injury'=>$db->sqleval('least(injury + 1, %i)', 80),
|
||||
], 'nation=%i AND officer_level=12', $nationID);
|
||||
|
||||
$db->update('nation', [
|
||||
'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0),
|
||||
'gold'=>$db->sqleval('gold + %i', $gold),
|
||||
'rice'=>$db->sqleval('rice + %i', $rice),
|
||||
], 'nation = %i', $nationID);
|
||||
} else {
|
||||
//이번분기는 추방불가(초반 제외)
|
||||
$db->update('nation', [
|
||||
'chief_set'=>$db->sqleval('chief_set | %i', doOfficerSet(0, $myOfficerLevel)),
|
||||
'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0),
|
||||
'gold'=>$db->sqleval('gold + %i', $gold),
|
||||
'rice'=>$db->sqleval('rice + %i', $rice),
|
||||
], 'nation = %i', $nationID);
|
||||
}
|
||||
|
||||
$logger->pushGeneralHistoryLog("<D>{$nation['name']}</>에서 추방됨");
|
||||
$general->applyDB($db);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($action == "임명") {
|
||||
if(2 <= $officerLevel && $officerLevel <= 4){
|
||||
if(!$destCityID){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'도시가 지정되지 않았습니다.'
|
||||
]);
|
||||
}
|
||||
$result = do도시임명($general, $destCityID, $officerLevel);
|
||||
if($result !== null){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$result
|
||||
]);
|
||||
}
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success'
|
||||
]);
|
||||
}
|
||||
|
||||
if(5 <= $officerLevel && $officerLevel < 12){
|
||||
$result = do수뇌임명($general, $officerLevel);
|
||||
if($result !== null){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$result
|
||||
]);
|
||||
}
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success'
|
||||
]);
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 지정입니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if($action == "추방") {
|
||||
$result = do추방($general, $myOfficerLevel);
|
||||
if($result !== null){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$result
|
||||
]);
|
||||
}
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success'
|
||||
]);
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 명령입니다.'
|
||||
]);
|
||||
+81
-76
@@ -1,77 +1,82 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
|
||||
$session = Session::requireGameLogin([])->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
$generalID = $session->generalID;
|
||||
|
||||
increaseRefresh("내정보 수정", 0);
|
||||
|
||||
$action = Util::getPost('action');
|
||||
$tnmt = Util::getPost('tnmt', 'int', 1);
|
||||
$defence_train = Util::getPost('defence_train', 'int', 80);
|
||||
$use_treatment = Util::getPost('use_treatment', 'int', 10);
|
||||
//$detachNPC = Util::getPost('detachNPC', 'bool');
|
||||
$detachNPC = false;
|
||||
|
||||
if ($defence_train <= 40) {
|
||||
$defence_train = 40;
|
||||
}
|
||||
|
||||
if($defence_train <= 90){
|
||||
$defence_train = Util::round($defence_train, -1);
|
||||
}
|
||||
else{
|
||||
$defence_train = 999;
|
||||
}
|
||||
|
||||
if($tnmt < 0 || $tnmt > 1){
|
||||
$tnmt = 1;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$me = General::createGeneralObjFromDB($generalID);
|
||||
|
||||
|
||||
if($defence_train != $me->getVar('defence_train')){
|
||||
if($defence_train == 999){
|
||||
$me->increaseVar('myset', -1);
|
||||
$me->setVar('defence_train', $defence_train);
|
||||
$me->increaseVar('train', -3);
|
||||
$me->increaseVar('atmos', -3);
|
||||
}
|
||||
else{
|
||||
$me->increaseVar('myset', -1);
|
||||
$me->setVar('defence_train', $defence_train);
|
||||
}
|
||||
}
|
||||
|
||||
$me->setAuxVar('use_treatment', Util::valueFit($use_treatment, 10, 100));
|
||||
|
||||
if($me->getVar('tnmt') != $tnmt){
|
||||
$me->setVar('tnmt', $tnmt);
|
||||
}
|
||||
|
||||
if($me->getNPCType() == 1 && $detachNPC){
|
||||
$turnterm = $gameStor->turnterm;
|
||||
|
||||
if($turnterm < 10){
|
||||
$targetKillTurn = 30 / $turnterm;
|
||||
}
|
||||
else{
|
||||
$targetKillTurn = 60 / $turnterm;
|
||||
}
|
||||
$me->setVar('killturn', $targetKillTurn);
|
||||
}
|
||||
|
||||
$me->applyDB($db);
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success'
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
|
||||
$session = Session::requireGameLogin([])->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
$generalID = $session->generalID;
|
||||
|
||||
increaseRefresh("내정보 수정", 0);
|
||||
|
||||
$action = Util::getPost('action');
|
||||
$tnmt = Util::getPost('tnmt', 'int', 1);
|
||||
$defence_train = Util::getPost('defence_train', 'int', 80);
|
||||
$use_treatment = Util::getPost('use_treatment', 'int', 10);
|
||||
$use_auto_nation_turn = Util::getPost('use_auto_nation_turn', 'int', 1);
|
||||
//$detachNPC = Util::getPost('detachNPC', 'bool');
|
||||
$detachNPC = false;
|
||||
|
||||
if ($defence_train <= 40) {
|
||||
$defence_train = 40;
|
||||
}
|
||||
|
||||
if($defence_train <= 90){
|
||||
$defence_train = Util::round($defence_train, -1);
|
||||
}
|
||||
else{
|
||||
$defence_train = 999;
|
||||
}
|
||||
|
||||
if($tnmt < 0 || $tnmt > 1){
|
||||
$tnmt = 1;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$me = General::createGeneralObjFromDB($generalID);
|
||||
|
||||
|
||||
if($defence_train != $me->getVar('defence_train')){
|
||||
if($defence_train == 999){
|
||||
$me->increaseVar('myset', -1);
|
||||
$me->setVar('defence_train', $defence_train);
|
||||
$me->increaseVar('train', -3);
|
||||
$me->increaseVar('atmos', -3);
|
||||
}
|
||||
else{
|
||||
$me->increaseVar('myset', -1);
|
||||
$me->setVar('defence_train', $defence_train);
|
||||
}
|
||||
}
|
||||
|
||||
$me->setAuxVar('use_treatment', Util::valueFit($use_treatment, 10, 100));
|
||||
|
||||
if($use_auto_nation_turn != $me->getAuxVar('use_auto_nation_turn')){
|
||||
$me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn);
|
||||
}
|
||||
|
||||
if($me->getVar('tnmt') != $tnmt){
|
||||
$me->setVar('tnmt', $tnmt);
|
||||
}
|
||||
|
||||
if($me->getNPCType() == 1 && $detachNPC){
|
||||
$turnterm = $gameStor->turnterm;
|
||||
|
||||
if($turnterm < 10){
|
||||
$targetKillTurn = 30 / $turnterm;
|
||||
}
|
||||
else{
|
||||
$targetKillTurn = 60 / $turnterm;
|
||||
}
|
||||
$me->setVar('killturn', $targetKillTurn);
|
||||
}
|
||||
|
||||
$me->applyDB($db);
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success'
|
||||
]);
|
||||
+465
-451
@@ -1,451 +1,465 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
|
||||
$session = Session::requireLogin([])->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
|
||||
increaseRefresh("시뮬레이터", 0);
|
||||
|
||||
$query = Util::getPost('query');
|
||||
if($query === null){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'입력값이 없습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$action = Util::getPost('action');
|
||||
if($action === null || !in_array($action, ['reorder', 'battle'])){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'원하는 동작이 지정되지 않았습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$query = Json::decode($query);
|
||||
if($query === null){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 JSON입니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$defaultCheck = [
|
||||
'required'=>[
|
||||
'attackerGeneral', 'attackerCity', 'attackerNation',
|
||||
'defenderGenerals', 'defenderCity', 'defenderNation',
|
||||
'year', 'month', 'repeatCnt'
|
||||
],
|
||||
'integer'=>[
|
||||
'year','month','repeatCnt'
|
||||
],
|
||||
'between'=>[
|
||||
['month', [1, 12]]
|
||||
],
|
||||
'in'=>[
|
||||
['repeatCnt', [1, 1000]]
|
||||
],
|
||||
'min'=>[
|
||||
['year', 0]
|
||||
],
|
||||
'array'=>[
|
||||
'attackerGeneral', 'attackerCity', 'attackerNation',
|
||||
'defenderGenerals', 'defenderCity', 'defenderNation'
|
||||
],
|
||||
];
|
||||
|
||||
$v = new Validator($query);
|
||||
$v->rules($defaultCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$year = $query['year'];
|
||||
$month = $query['month'];
|
||||
$repeatCnt = $query['repeatCnt'];
|
||||
|
||||
$rawAttacker = $query['attackerGeneral'];
|
||||
$rawAttacker['turntime'] = TimeUtil::now();
|
||||
$rawAttackerCity = $query['attackerCity'];
|
||||
$rawAttackerNation = $query['attackerNation'];
|
||||
|
||||
$rawDefenderList = $query['defenderGenerals'];
|
||||
$rawDefenderCity = $query['defenderCity'];
|
||||
$rawDefenderNation = $query['defenderNation'];
|
||||
|
||||
|
||||
$generalCheck = [
|
||||
'required'=>[
|
||||
'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train',
|
||||
'intel', 'intel_exp', 'book', 'strength', 'strength_exp', 'weapon', 'injury', 'leadership', 'leadership_exp', 'horse', 'item',
|
||||
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
|
||||
'recent_war'
|
||||
],
|
||||
'integer'=>[
|
||||
'no', 'nation', 'crew', 'crewtype', 'atmos', 'train',
|
||||
'intel', 'intel_exp', 'strength', 'strength_exp', 'injury', 'leadership', 'leadership_exp',
|
||||
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
|
||||
],
|
||||
'min'=>[
|
||||
['no', 1],
|
||||
['nation', 1],
|
||||
['crew', 0],
|
||||
['intel', 0],
|
||||
['strength', 0],
|
||||
['leadership', 0],
|
||||
['experience', 0],
|
||||
['gold', 0],
|
||||
['rice', 0],
|
||||
['dex1', 0],
|
||||
['dex2', 0],
|
||||
['dex3', 0],
|
||||
['dex4', 0],
|
||||
['dex5', 0],
|
||||
],
|
||||
'between'=>[
|
||||
['train', [40, GameConst::$maxTrainByWar]],
|
||||
['atmos', [40, GameConst::$maxAtmosByWar]],
|
||||
['explevel', [0, 300]],
|
||||
['injury', [0, 80]],
|
||||
['officer_level', [1, 12]]
|
||||
],
|
||||
'in'=>[
|
||||
['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)],
|
||||
['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)],
|
||||
['crewtype', array_keys(GameUnitConst::all())],
|
||||
['horse', array_merge(array_keys(GameConst::$allItems['horse']), ['None'])],
|
||||
['weapon', array_merge(array_keys(GameConst::$allItems['weapon']), ['None'])],
|
||||
['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])],
|
||||
['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])],
|
||||
]
|
||||
];
|
||||
|
||||
$v = new Validator($rawAttacker);
|
||||
$v->rules($generalCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[출병자]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$defenderList = [];
|
||||
foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
|
||||
$v = new Validator($rawDefenderGeneral);
|
||||
$v->rules($generalCheck);
|
||||
if(!$v->validate()){
|
||||
$idx+=1;
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>"[수비자{$idx}]".$v->errorStr()
|
||||
]);
|
||||
}
|
||||
$defenderList[] = new General($rawDefenderGeneral, null, $rawDefenderCity, $rawAttackerNation, $year, $month, true);
|
||||
}
|
||||
|
||||
|
||||
$cityCheck = [
|
||||
'required'=>[
|
||||
'city', 'nation', 'supply', 'name',
|
||||
'pop', 'agri', 'comm', 'secu', 'def', 'wall',
|
||||
'trust', 'level',
|
||||
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
|
||||
'dead', 'state', 'conflict',
|
||||
],
|
||||
'numeric'=>[
|
||||
'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead'
|
||||
],
|
||||
'integer'=>[
|
||||
'city', 'nation', 'supply',
|
||||
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
|
||||
'state',
|
||||
],
|
||||
'min'=>[
|
||||
['def', 0],
|
||||
['wall', 0],
|
||||
['trust', 0],
|
||||
['pop', 0],
|
||||
['comm', 0],
|
||||
['secu', 0],
|
||||
['city', 1],
|
||||
['nation', 0]
|
||||
],
|
||||
'in'=>[
|
||||
['level', array_keys(getCityLevelList())]
|
||||
]
|
||||
];
|
||||
|
||||
$v = new Validator($rawAttackerCity);
|
||||
$v->rules($cityCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[출병도시]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$v = new Validator($rawDefenderCity);
|
||||
$v->rules($cityCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[수비도시]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$nationCheck = [
|
||||
'required'=>[
|
||||
'type', 'tech', 'level', 'capital',
|
||||
'nation', 'name', 'gold', 'rice', 'gennum'
|
||||
],
|
||||
'integer'=>[
|
||||
'level', 'capital', 'nation', 'gennum',
|
||||
],
|
||||
'numeric'=>[
|
||||
'tech', 'gold', 'rice'
|
||||
],
|
||||
'min'=>[
|
||||
['tech', 0],
|
||||
['gold', 0],
|
||||
['rice', 0],
|
||||
['gennum', 1],
|
||||
],
|
||||
'in'=>[
|
||||
['type', GameConst::$availableNationType],
|
||||
['level', array_keys(getNationLevelList())]
|
||||
]
|
||||
];
|
||||
|
||||
$v = new Validator($rawAttackerNation);
|
||||
$v->rules($nationCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[출병국]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$v = new Validator($rawDefenderNation);
|
||||
$v->rules($nationCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[수비국]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
if($action == 'reorder'){
|
||||
usort($defenderList, function(General $lhs, General $rhs){
|
||||
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
|
||||
});
|
||||
|
||||
$order = [];
|
||||
foreach($defenderList as $defenderGeneral){
|
||||
$order[] = $defenderGeneral->getID();
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success',
|
||||
'order'=>$order
|
||||
]);
|
||||
}
|
||||
|
||||
usort($defenderList, function(General $lhs, General $rhs){
|
||||
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
|
||||
});
|
||||
|
||||
$rawDefenderList = array_map(function(General $general){
|
||||
return $general->getRaw();
|
||||
}, $defenderList);
|
||||
unset($defenderList);
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$startYear = $gameStor->startyear;
|
||||
$cityRate = Util::round(($year - $startYear) / 1.5) + 60;
|
||||
|
||||
|
||||
function simulateBattle(
|
||||
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
|
||||
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
|
||||
$startYear, $year, $month, $cityRate
|
||||
){
|
||||
$attacker = new WarUnitGeneral(
|
||||
new General($rawAttacker, null, $rawAttackerCity, $rawAttackerNation, $year, $month),
|
||||
$rawAttackerNation,
|
||||
true
|
||||
);
|
||||
$city = new WarUnitCity($rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
|
||||
|
||||
$iterDefender = new \ArrayIterator($rawDefenderList);
|
||||
$iterDefender->rewind();
|
||||
|
||||
$battleResult = [];
|
||||
|
||||
$attackerRice = $rawAttacker['rice'];
|
||||
$defenderRice = 0;
|
||||
|
||||
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext)
|
||||
use ($iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) {
|
||||
if($prevDefender !== null){
|
||||
$prevDefender->getLogger()->rollback();
|
||||
$battleResult[] = $prevDefender;
|
||||
if($prevDefender instanceof WarUnitGeneral){
|
||||
$defenderRice -= $prevDefender->getVar('rice');
|
||||
}
|
||||
}
|
||||
|
||||
if(!$reqNext){
|
||||
return null;
|
||||
}
|
||||
|
||||
if(!$iterDefender->valid()){
|
||||
return null;
|
||||
}
|
||||
|
||||
$defenderObj = new General($iterDefender->current(), null, $rawDefenderCity, $rawDefenderNation, $year, $month);
|
||||
if(extractBattleOrder($defenderObj) <= 0){
|
||||
return null;
|
||||
}
|
||||
|
||||
$defenderRice += $defenderObj->getVar('rice');
|
||||
|
||||
$retVal = new WarUnitGeneral(
|
||||
$defenderObj,
|
||||
$rawDefenderNation,
|
||||
false
|
||||
);
|
||||
$iterDefender->next();
|
||||
return $retVal;
|
||||
};
|
||||
|
||||
$conquerCity = processWar_NG($attacker, $getNextDefender, $city, $year - $startYear);
|
||||
|
||||
$rawDefenderCity = $city->getRaw();
|
||||
$updateAttackerNation = [];
|
||||
$updateDefenderNation = [];
|
||||
|
||||
$attackerRice -= $attacker->getVar('rice');
|
||||
|
||||
if($city->getPhase() > 0){
|
||||
$rice = $city->getKilled() / 100 * 0.8;
|
||||
$rice *= $city->getCrewType()->rice;
|
||||
$rice *= getTechCost($rawDefenderNation['tech']);
|
||||
$rice *= $cityRate / 100 - 0.2;
|
||||
Util::setRound($rice);
|
||||
|
||||
$defenderRice += $rice;
|
||||
}
|
||||
|
||||
$totalDead = $attacker->getKilled() + $attacker->getDead();
|
||||
$attackerCityDead = $totalDead * 0.4;
|
||||
$defenderCityDead = $totalDead * 0.6;
|
||||
|
||||
return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice];
|
||||
}
|
||||
|
||||
$lastWarLog = [];
|
||||
|
||||
$attackerKilled = 0;
|
||||
$attackerDead = 0;
|
||||
|
||||
$attackerMaxKilled = 0;
|
||||
$attackerMinKilled = PHP_INT_MAX;
|
||||
|
||||
$attackerMaxDead = 0;
|
||||
$attackerMinDead = PHP_INT_MAX;
|
||||
|
||||
|
||||
$attackerAvgRice = 0;
|
||||
$defenderAvgRice = 0;
|
||||
|
||||
$avgPhase = 0;
|
||||
$avgWar = 0;
|
||||
|
||||
$attackerActivatedSkills = [];
|
||||
$defendersActivatedSkills = [];
|
||||
|
||||
foreach(Util::range($repeatCnt) as $repeatIdx){
|
||||
/** @var WarUnit $attacker */
|
||||
[$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle(
|
||||
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
|
||||
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
|
||||
$startYear, $year, $month, $cityRate
|
||||
);
|
||||
$lastWarLog = Util::mapWithKey(function($key, $values){
|
||||
return ConvertLog(join('<br>', $values));
|
||||
}, $attacker->getLogger()->rollback());
|
||||
|
||||
$avgPhase += $attacker->getPhase() / $repeatCnt;
|
||||
|
||||
$killed = $attacker->getKilled();
|
||||
$dead = $attacker->getDead();
|
||||
|
||||
$attackerKilled += $killed / $repeatCnt;
|
||||
$attackerDead += $dead / $repeatCnt;
|
||||
|
||||
$attackerMaxKilled = max($attackerMaxKilled, $killed);
|
||||
$attackerMinKilled = min($attackerMinKilled, $killed);
|
||||
|
||||
$attackerMaxDead = max($attackerMaxDead, $dead);
|
||||
$attackerMinDead = min($attackerMinDead, $dead);
|
||||
|
||||
$attackerAvgRice += $attackerRice / $repeatCnt;
|
||||
$defenderAvgRice += $defenderRice / $repeatCnt;
|
||||
|
||||
$avgWar += count($battleResult) / $repeatCnt;
|
||||
|
||||
foreach($attacker->getActivatedSkillLog() as $skillName => $skillCnt){
|
||||
if(!key_exists($skillName, $attackerActivatedSkills)){
|
||||
$attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt;
|
||||
}
|
||||
else{
|
||||
$attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($battleResult as $idx=>$defender){
|
||||
while($idx >= count($defendersActivatedSkills)){
|
||||
$defendersActivatedSkills[] = [];
|
||||
}
|
||||
|
||||
$activatedSkills = &$defendersActivatedSkills[$idx];
|
||||
foreach($defender->getActivatedSkillLog() as $skillName => $skillCnt){
|
||||
if(!key_exists($skillName, $activatedSkills)){
|
||||
$activatedSkills[$skillName] = $skillCnt / $repeatCnt;
|
||||
}
|
||||
else{
|
||||
$activatedSkills[$skillName] += $skillCnt / $repeatCnt;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'datetime'=>$rawAttacker['turntime'],
|
||||
'reason'=>'success',
|
||||
'lastWarLog'=>$lastWarLog,
|
||||
'avgWar'=>$avgWar,
|
||||
'phase'=>$avgPhase,
|
||||
'killed'=>$attackerKilled,
|
||||
'maxKilled'=>$attackerMaxKilled,
|
||||
'minKilled'=>$attackerMinKilled,
|
||||
'dead'=>$attackerDead,
|
||||
'maxDead'=>$attackerMaxDead,
|
||||
'minDead'=>$attackerMinDead,
|
||||
'attackerRice'=>$attackerAvgRice,
|
||||
'defenderRice'=>$defenderAvgRice,
|
||||
'attackerSkills'=>$attackerActivatedSkills,
|
||||
'defendersSkills'=>$defendersActivatedSkills,
|
||||
]);
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
|
||||
$session = Session::requireLogin([])->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
|
||||
increaseRefresh("시뮬레이터", 0);
|
||||
|
||||
$query = Util::getPost('query');
|
||||
if($query === null){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'입력값이 없습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$action = Util::getPost('action');
|
||||
if($action === null || !in_array($action, ['reorder', 'battle'])){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'원하는 동작이 지정되지 않았습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$query = Json::decode($query);
|
||||
if($query === null){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 JSON입니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$defaultCheck = [
|
||||
'required'=>[
|
||||
'attackerGeneral', 'attackerCity', 'attackerNation',
|
||||
'defenderGenerals', 'defenderCity', 'defenderNation',
|
||||
'year', 'month', 'repeatCnt'
|
||||
],
|
||||
'integer'=>[
|
||||
'year','month','repeatCnt'
|
||||
],
|
||||
'between'=>[
|
||||
['month', [1, 12]]
|
||||
],
|
||||
'in'=>[
|
||||
['repeatCnt', [1, 1000]]
|
||||
],
|
||||
'min'=>[
|
||||
['year', 0]
|
||||
],
|
||||
'array'=>[
|
||||
'attackerGeneral', 'attackerCity', 'attackerNation',
|
||||
'defenderGenerals', 'defenderCity', 'defenderNation'
|
||||
],
|
||||
];
|
||||
|
||||
$v = new Validator($query);
|
||||
$v->rules($defaultCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$year = $query['year'];
|
||||
$month = $query['month'];
|
||||
$repeatCnt = $query['repeatCnt'];
|
||||
|
||||
$rawAttacker = $query['attackerGeneral'];
|
||||
$rawAttacker['turntime'] = TimeUtil::now();
|
||||
$rawAttackerCity = $query['attackerCity'];
|
||||
$rawAttackerNation = $query['attackerNation'];
|
||||
|
||||
$rawDefenderList = $query['defenderGenerals'];
|
||||
$rawDefenderCity = $query['defenderCity'];
|
||||
$rawDefenderNation = $query['defenderNation'];
|
||||
|
||||
|
||||
$generalCheck = [
|
||||
'required'=>[
|
||||
'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train',
|
||||
'intel', 'intel_exp', 'book', 'strength', 'strength_exp', 'weapon', 'injury', 'leadership', 'leadership_exp', 'horse', 'item',
|
||||
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
|
||||
'recent_war', 'warnum', 'killnum', 'killcrew',
|
||||
],
|
||||
'integer'=>[
|
||||
'no', 'nation', 'crew', 'crewtype', 'atmos', 'train',
|
||||
'intel', 'intel_exp', 'strength', 'strength_exp', 'injury', 'leadership', 'leadership_exp',
|
||||
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
|
||||
'warnum', 'killnum', 'killcrew',
|
||||
],
|
||||
'min'=>[
|
||||
['no', 1],
|
||||
['nation', 1],
|
||||
['crew', 0],
|
||||
['intel', 0],
|
||||
['strength', 0],
|
||||
['leadership', 0],
|
||||
['experience', 0],
|
||||
['gold', 0],
|
||||
['rice', 0],
|
||||
['dex1', 0],
|
||||
['dex2', 0],
|
||||
['dex3', 0],
|
||||
['dex4', 0],
|
||||
['dex5', 0],
|
||||
['warnum', 0],
|
||||
['killnum', 0],
|
||||
['killcrew', 0],
|
||||
],
|
||||
'between'=>[
|
||||
['train', [40, GameConst::$maxTrainByWar]],
|
||||
['atmos', [40, GameConst::$maxAtmosByWar]],
|
||||
['explevel', [0, 300]],
|
||||
['injury', [0, 80]],
|
||||
['officer_level', [1, 12]]
|
||||
],
|
||||
'in'=>[
|
||||
['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)],
|
||||
['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)],
|
||||
['crewtype', array_keys(GameUnitConst::all())],
|
||||
['horse', array_merge(array_keys(GameConst::$allItems['horse']), ['None'])],
|
||||
['weapon', array_merge(array_keys(GameConst::$allItems['weapon']), ['None'])],
|
||||
['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])],
|
||||
['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])],
|
||||
]
|
||||
];
|
||||
|
||||
$v = new Validator($rawAttacker);
|
||||
$v->rules($generalCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[출병자]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$defenderList = [];
|
||||
foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
|
||||
$v = new Validator($rawDefenderGeneral);
|
||||
$v->rules($generalCheck);
|
||||
if(!$v->validate()){
|
||||
$idx+=1;
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>"[수비자{$idx}]".$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$defenderList[] = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), $rawDefenderCity, $rawAttackerNation, $year, $month, true);
|
||||
}
|
||||
|
||||
|
||||
$cityCheck = [
|
||||
'required'=>[
|
||||
'city', 'nation', 'supply', 'name',
|
||||
'pop', 'agri', 'comm', 'secu', 'def', 'wall',
|
||||
'trust', 'level',
|
||||
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
|
||||
'dead', 'state', 'conflict',
|
||||
],
|
||||
'numeric'=>[
|
||||
'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead'
|
||||
],
|
||||
'integer'=>[
|
||||
'city', 'nation', 'supply',
|
||||
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
|
||||
'state',
|
||||
],
|
||||
'min'=>[
|
||||
['def', 0],
|
||||
['wall', 0],
|
||||
['trust', 0],
|
||||
['pop', 0],
|
||||
['comm', 0],
|
||||
['secu', 0],
|
||||
['city', 1],
|
||||
['nation', 0]
|
||||
],
|
||||
'in'=>[
|
||||
['level', array_keys(getCityLevelList())]
|
||||
]
|
||||
];
|
||||
|
||||
$v = new Validator($rawAttackerCity);
|
||||
$v->rules($cityCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[출병도시]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$v = new Validator($rawDefenderCity);
|
||||
$v->rules($cityCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[수비도시]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$nationCheck = [
|
||||
'required'=>[
|
||||
'type', 'tech', 'level', 'capital',
|
||||
'nation', 'name', 'gold', 'rice', 'gennum'
|
||||
],
|
||||
'integer'=>[
|
||||
'level', 'capital', 'nation', 'gennum',
|
||||
],
|
||||
'numeric'=>[
|
||||
'tech', 'gold', 'rice'
|
||||
],
|
||||
'min'=>[
|
||||
['tech', 0],
|
||||
['gold', 0],
|
||||
['rice', 0],
|
||||
['gennum', 1],
|
||||
],
|
||||
'in'=>[
|
||||
['type', GameConst::$availableNationType],
|
||||
['level', array_keys(getNationLevelList())]
|
||||
]
|
||||
];
|
||||
|
||||
$v = new Validator($rawAttackerNation);
|
||||
$v->rules($nationCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[출병국]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$v = new Validator($rawDefenderNation);
|
||||
$v->rules($nationCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[수비국]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
if($action == 'reorder'){
|
||||
usort($defenderList, function(General $lhs, General $rhs){
|
||||
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
|
||||
});
|
||||
|
||||
$order = [];
|
||||
foreach($defenderList as $defenderGeneral){
|
||||
$order[] = $defenderGeneral->getID();
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success',
|
||||
'order'=>$order
|
||||
]);
|
||||
}
|
||||
|
||||
usort($defenderList, function(General $lhs, General $rhs){
|
||||
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
|
||||
});
|
||||
|
||||
$rawDefenderList = array_map(function(General $general){
|
||||
return $general->getRaw();
|
||||
}, $defenderList);
|
||||
unset($defenderList);
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$startYear = $gameStor->startyear;
|
||||
$cityRate = Util::round(($year - $startYear) / 1.5) + 60;
|
||||
|
||||
function extractRankVar(array $rawVal):array{
|
||||
$rankVars = [];
|
||||
foreach($rawVal as $rawKey=>$rawVal){
|
||||
if(key_exists($rawKey, General::RANK_COLUMN)){
|
||||
$rankVars[$rawKey] = $rawVal;
|
||||
}
|
||||
}
|
||||
return $rankVars;
|
||||
}
|
||||
|
||||
function simulateBattle(
|
||||
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
|
||||
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
|
||||
$startYear, $year, $month, $cityRate
|
||||
){
|
||||
$attacker = new WarUnitGeneral(
|
||||
new General($rawAttacker, extractRankVar($rawAttacker), $rawAttackerCity, $rawAttackerNation, $year, $month),
|
||||
$rawAttackerNation,
|
||||
true
|
||||
);
|
||||
$city = new WarUnitCity($rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
|
||||
|
||||
$iterDefender = new \ArrayIterator($rawDefenderList);
|
||||
$iterDefender->rewind();
|
||||
|
||||
$battleResult = [];
|
||||
|
||||
$attackerRice = $rawAttacker['rice'];
|
||||
$defenderRice = 0;
|
||||
|
||||
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext)
|
||||
use ($iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) {
|
||||
if($prevDefender !== null){
|
||||
$prevDefender->getLogger()->rollback();
|
||||
$battleResult[] = $prevDefender;
|
||||
if($prevDefender instanceof WarUnitGeneral){
|
||||
$defenderRice -= $prevDefender->getVar('rice');
|
||||
}
|
||||
}
|
||||
|
||||
if(!$reqNext){
|
||||
return null;
|
||||
}
|
||||
|
||||
if(!$iterDefender->valid()){
|
||||
return null;
|
||||
}
|
||||
|
||||
$defenderObj = new General($iterDefender->current(), extractRankVar($iterDefender->current()), $rawDefenderCity, $rawDefenderNation, $year, $month);
|
||||
if(extractBattleOrder($defenderObj) <= 0){
|
||||
return null;
|
||||
}
|
||||
|
||||
$defenderRice += $defenderObj->getVar('rice');
|
||||
|
||||
$retVal = new WarUnitGeneral(
|
||||
$defenderObj,
|
||||
$rawDefenderNation,
|
||||
false
|
||||
);
|
||||
$iterDefender->next();
|
||||
return $retVal;
|
||||
};
|
||||
|
||||
$conquerCity = processWar_NG($attacker, $getNextDefender, $city, $year - $startYear);
|
||||
|
||||
$rawDefenderCity = $city->getRaw();
|
||||
$updateAttackerNation = [];
|
||||
$updateDefenderNation = [];
|
||||
|
||||
$attackerRice -= $attacker->getVar('rice');
|
||||
|
||||
if($city->getPhase() > 0){
|
||||
$rice = $city->getKilled() / 100 * 0.8;
|
||||
$rice *= $city->getCrewType()->rice;
|
||||
$rice *= getTechCost($rawDefenderNation['tech']);
|
||||
$rice *= $cityRate / 100 - 0.2;
|
||||
Util::setRound($rice);
|
||||
|
||||
$defenderRice += $rice;
|
||||
}
|
||||
|
||||
$totalDead = $attacker->getKilled() + $attacker->getDead();
|
||||
$attackerCityDead = $totalDead * 0.4;
|
||||
$defenderCityDead = $totalDead * 0.6;
|
||||
|
||||
return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice];
|
||||
}
|
||||
|
||||
$lastWarLog = [];
|
||||
|
||||
$attackerKilled = 0;
|
||||
$attackerDead = 0;
|
||||
|
||||
$attackerMaxKilled = 0;
|
||||
$attackerMinKilled = PHP_INT_MAX;
|
||||
|
||||
$attackerMaxDead = 0;
|
||||
$attackerMinDead = PHP_INT_MAX;
|
||||
|
||||
|
||||
$attackerAvgRice = 0;
|
||||
$defenderAvgRice = 0;
|
||||
|
||||
$avgPhase = 0;
|
||||
$avgWar = 0;
|
||||
|
||||
$attackerActivatedSkills = [];
|
||||
$defendersActivatedSkills = [];
|
||||
|
||||
foreach(Util::range($repeatCnt) as $repeatIdx){
|
||||
/** @var WarUnit $attacker */
|
||||
[$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle(
|
||||
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
|
||||
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
|
||||
$startYear, $year, $month, $cityRate
|
||||
);
|
||||
$lastWarLog = Util::mapWithKey(function($key, $values){
|
||||
return ConvertLog(join('<br>', $values));
|
||||
}, $attacker->getLogger()->rollback());
|
||||
|
||||
$avgPhase += $attacker->getPhase() / $repeatCnt;
|
||||
|
||||
$killed = $attacker->getKilled();
|
||||
$dead = $attacker->getDead();
|
||||
|
||||
$attackerKilled += $killed / $repeatCnt;
|
||||
$attackerDead += $dead / $repeatCnt;
|
||||
|
||||
$attackerMaxKilled = max($attackerMaxKilled, $killed);
|
||||
$attackerMinKilled = min($attackerMinKilled, $killed);
|
||||
|
||||
$attackerMaxDead = max($attackerMaxDead, $dead);
|
||||
$attackerMinDead = min($attackerMinDead, $dead);
|
||||
|
||||
$attackerAvgRice += $attackerRice / $repeatCnt;
|
||||
$defenderAvgRice += $defenderRice / $repeatCnt;
|
||||
|
||||
$avgWar += count($battleResult) / $repeatCnt;
|
||||
|
||||
foreach($attacker->getActivatedSkillLog() as $skillName => $skillCnt){
|
||||
if(!key_exists($skillName, $attackerActivatedSkills)){
|
||||
$attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt;
|
||||
}
|
||||
else{
|
||||
$attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($battleResult as $idx=>$defender){
|
||||
while($idx >= count($defendersActivatedSkills)){
|
||||
$defendersActivatedSkills[] = [];
|
||||
}
|
||||
|
||||
$activatedSkills = &$defendersActivatedSkills[$idx];
|
||||
foreach($defender->getActivatedSkillLog() as $skillName => $skillCnt){
|
||||
if(!key_exists($skillName, $activatedSkills)){
|
||||
$activatedSkills[$skillName] = $skillCnt / $repeatCnt;
|
||||
}
|
||||
else{
|
||||
$activatedSkills[$skillName] += $skillCnt / $repeatCnt;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'datetime'=>$rawAttacker['turntime'],
|
||||
'reason'=>'success',
|
||||
'lastWarLog'=>$lastWarLog,
|
||||
'avgWar'=>$avgWar,
|
||||
'phase'=>$avgPhase,
|
||||
'killed'=>$attackerKilled,
|
||||
'maxKilled'=>$attackerMaxKilled,
|
||||
'minKilled'=>$attackerMinKilled,
|
||||
'dead'=>$attackerDead,
|
||||
'maxDead'=>$attackerMaxDead,
|
||||
'minDead'=>$attackerMinDead,
|
||||
'attackerRice'=>$attackerAvgRice,
|
||||
'defenderRice'=>$defenderAvgRice,
|
||||
'attackerSkills'=>$attackerActivatedSkills,
|
||||
'defendersSkills'=>$defendersActivatedSkills,
|
||||
]);
|
||||
|
||||
+931
-799
@@ -1,800 +1,932 @@
|
||||
jQuery(function($){
|
||||
|
||||
|
||||
var $generalForm = $('.form_sample .general_detail');
|
||||
var $defenderHeaderForm = $('.form_sample .card-header');
|
||||
var $defenderColumn = $('.defender-column');
|
||||
|
||||
var defenderNoList = {};
|
||||
|
||||
var $attackerCard = $('.attacker_form');
|
||||
|
||||
var initBasicEvent = function(){
|
||||
|
||||
$('.form_injury').change(function(){
|
||||
var $this = $(this);
|
||||
var $general = getGeneralDetail($this);
|
||||
var $helptext = $general.find('.injury_helptext');
|
||||
|
||||
var injury = parseInt($this.val());
|
||||
//FIXME: PHP 코드와 항상 일치하도록 변경
|
||||
var text = '건강';
|
||||
var color = 'white';
|
||||
if(injury > 60){
|
||||
text = '위독';
|
||||
color = 'red';
|
||||
}
|
||||
else if(injury > 40){
|
||||
text = '심각';
|
||||
color = 'magenta';
|
||||
}
|
||||
else if(injury > 20){
|
||||
text = '중상';
|
||||
color = 'orange';
|
||||
}
|
||||
else if(injury > 0){
|
||||
text = '경상';
|
||||
color = 'yellow';
|
||||
}
|
||||
$helptext.html(text).css('color', color);
|
||||
});
|
||||
|
||||
$('.export_general').click(function(){
|
||||
var $btn = $(this);
|
||||
var $general = getGeneralDetail($btn);
|
||||
|
||||
var values = exportGeneralInfo($general);
|
||||
console.log(values);
|
||||
});
|
||||
$('.delete-defender').click(function(){
|
||||
var $card = getGeneralFrame($(this));
|
||||
deleteDefender($card);
|
||||
});
|
||||
$('.copy-defender').click(function(){
|
||||
var $card = getGeneralFrame($(this));
|
||||
copyDefender($card);
|
||||
});
|
||||
|
||||
$('.add-defender').click(function(){
|
||||
addDefender();
|
||||
});
|
||||
|
||||
$('.btn-general-load').click(function(){
|
||||
var $file = $(this).prev();
|
||||
$file[0].click();
|
||||
})
|
||||
|
||||
$('.form_load_general_file').on('change', function(e){
|
||||
e.preventDefault();
|
||||
var $this = $(this);
|
||||
var $card = getGeneralFrame($this);
|
||||
|
||||
var files = e.target.files;
|
||||
|
||||
importGeneralInfoByFile(files, $card);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.btn-general-save').click(function(){
|
||||
var $this = $(this);
|
||||
var $general = getGeneralDetail($this);
|
||||
var generalData = exportGeneralInfo($general);
|
||||
|
||||
var filename = "general_{0}.json".format(generalData.name);
|
||||
var saveData = JSON.stringify({
|
||||
objType:'general',
|
||||
data:generalData
|
||||
}, null, 4);
|
||||
|
||||
download(saveData, filename, 'application/json');
|
||||
});
|
||||
|
||||
$('.btn-battle-load').click(function(){
|
||||
var $file = $(this).prev();
|
||||
$file[0].click();
|
||||
})
|
||||
|
||||
$('.form_load_battle_file').on('change', function(e){
|
||||
e.preventDefault();
|
||||
var $this = $(this);
|
||||
var files = e.target.files;
|
||||
|
||||
importBattleInfoByFile(files);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.btn-battle-save').click(function(){
|
||||
var battleData = exportAllData();
|
||||
var filename = "battle_{0}.json".format(moment().format('YYYYMMDD_hhmmss'));
|
||||
var saveData = JSON.stringify({
|
||||
objType:'battle',
|
||||
data:battleData
|
||||
}, null, 4);
|
||||
|
||||
download(saveData, filename, 'application/json');
|
||||
})
|
||||
|
||||
var $generals = $('.general_detail');
|
||||
$generals.bind('dragover dragleave', function(e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
})
|
||||
$generals.bind('drop', function(e){
|
||||
e.preventDefault();
|
||||
var $this = $(this);
|
||||
var $card = getGeneralFrame($this);
|
||||
|
||||
var files = e.originalEvent.dataTransfer.files;
|
||||
|
||||
importGeneralInfoByFile(files, $card);
|
||||
return false;
|
||||
});
|
||||
|
||||
var $battlePad = $('.dragpad_battle');
|
||||
$battlePad.bind('dragover dragleave', function(e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
})
|
||||
$battlePad.bind('drop', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
var files = e.originalEvent.dataTransfer.files;
|
||||
|
||||
importBattleInfoByFile(files);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
var importGeneralInfo = function($general, data){
|
||||
var setVal = function(query, val){
|
||||
$general.find(query).val(val).change();
|
||||
}
|
||||
|
||||
setVal('.form_general_name', data.name);
|
||||
|
||||
setVal('.form_officer_level', data.officer_level);
|
||||
setVal('.form_exp_level', data.explevel);
|
||||
setVal('.form_injury', data.injury);
|
||||
|
||||
setVal('.form_leadership', data.leadership);
|
||||
setVal('.form_general_horse', data.horse);
|
||||
setVal('.form_strength', data.strength);
|
||||
setVal('.form_general_weap', data.weapon);
|
||||
setVal('.form_intel', data.intel);
|
||||
setVal('.form_general_book', data.book);
|
||||
setVal('.form_general_item', data.item);
|
||||
|
||||
setVal('.form_injury', data.injury);
|
||||
|
||||
setVal('.form_rice', data.rice);
|
||||
|
||||
setVal('.form_general_character', data.personal);
|
||||
setVal('.form_general_special_war', data.special2);
|
||||
|
||||
setVal('.form_crew', data.crew);
|
||||
setVal('.form_crewtype', data.crewtype);
|
||||
setVal('.form_atmos', data.atmos);
|
||||
setVal('.form_train', data.train);
|
||||
|
||||
setVal('.form_dex1', data.dex1);
|
||||
setVal('.form_dex2', data.dex2);
|
||||
setVal('.form_dex3', data.dex3);
|
||||
setVal('.form_dex4', data.dex4);
|
||||
setVal('.form_dex5', data.dex5);
|
||||
setVal('.form_defence_train', data.defence_train);
|
||||
|
||||
if(!setGeneralNo($general, data.no)){
|
||||
setGeneralNo($general, generateNewGeneralNo());
|
||||
}
|
||||
}
|
||||
|
||||
var exportGeneralInfo = function($general){
|
||||
var getInt = function(query){
|
||||
return parseInt($general.find(query).val());
|
||||
}
|
||||
|
||||
var getVal = function(query){
|
||||
return $general.find(query).val();
|
||||
}
|
||||
|
||||
return {
|
||||
no:getGeneralNo($general),
|
||||
name:getVal('.form_general_name'),
|
||||
officer_level:getInt('.form_officer_level'),
|
||||
explevel:getInt('.form_exp_level'),
|
||||
|
||||
leadership:getInt('.form_leadership'),
|
||||
horse:getVal('.form_general_horse'),
|
||||
strength:getInt('.form_strength'),
|
||||
weapon:getVal('.form_general_weap'),
|
||||
intel:getInt('.form_intel'),
|
||||
book:getVal('.form_general_book'),
|
||||
item:getVal('.form_general_item'),
|
||||
|
||||
injury:getInt('.form_injury'),
|
||||
|
||||
rice:getInt('.form_rice'),
|
||||
|
||||
personal:getVal('.form_general_character'),
|
||||
special2:getVal('.form_general_special_war'),
|
||||
|
||||
crew:getInt('.form_crew'),
|
||||
crewtype:getInt('.form_crewtype'),
|
||||
atmos:getInt('.form_atmos'),
|
||||
train:getInt('.form_train'),
|
||||
|
||||
dex1:getInt('.form_dex1'),
|
||||
dex2:getInt('.form_dex2'),
|
||||
dex3:getInt('.form_dex3'),
|
||||
dex4:getInt('.form_dex4'),
|
||||
dex5:getInt('.form_dex5'),
|
||||
defence_train:getInt('.form_defence_train'),
|
||||
};
|
||||
}
|
||||
|
||||
var importBattleInfoByFile = function(files){
|
||||
if(files === null){
|
||||
alert('파일 에러!');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(files.length < 1){
|
||||
alert("파일 에러!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
var file = files[0];
|
||||
if(file.size > 1024*1024){
|
||||
alert('파일이 너무 큽니다!');
|
||||
return false;
|
||||
}
|
||||
if(file.type === ''){
|
||||
alert('폴더를 업로드할 수 없습니다!');
|
||||
return false;
|
||||
}
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(){
|
||||
var battleData = {};
|
||||
try {
|
||||
battleData = JSON.parse(reader.result);
|
||||
} catch(e) {
|
||||
alert('올바르지 않은 파일 형식입니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!('objType' in battleData)){
|
||||
alert('파일 형식을 확인할 수 없습니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(battleData.objType != 'battle'){
|
||||
alert('전투 데이터가 아닙니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
importBattleInfo(battleData.data);
|
||||
return true;
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
reader.readAsText(file);
|
||||
}
|
||||
catch(e) {
|
||||
alert('파일을 읽는데 실패했습니다.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var importGeneralInfoByFile = function(files, $card){
|
||||
if($card === undefined){
|
||||
$card = addDefender();
|
||||
}
|
||||
|
||||
if(files === null){
|
||||
alert('파일 에러!');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(files.length < 1){
|
||||
alert("파일 에러!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
var file = files[0];
|
||||
if(file.size > 1024*1024){
|
||||
alert('파일이 너무 큽니다!');
|
||||
return false;
|
||||
}
|
||||
if(file.type === ''){
|
||||
alert('폴더를 업로드할 수 없습니다!');
|
||||
return false;
|
||||
}
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(){
|
||||
var generalData = {};
|
||||
try {
|
||||
generalData = JSON.parse(reader.result);
|
||||
} catch(e) {
|
||||
alert('올바르지 않은 파일 형식입니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!('objType' in generalData)){
|
||||
alert('파일 형식을 확인할 수 없습니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(generalData.objType == 'battle'){
|
||||
importBattleInfo(generalData.data);
|
||||
return true;
|
||||
}
|
||||
if(generalData.objType != 'general'){
|
||||
alert('장수 데이터가 아닙니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
$card.find('.form_load_general_file').val('');
|
||||
|
||||
importGeneralInfo($card, generalData.data);
|
||||
return true;
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
reader.readAsText(file);
|
||||
}
|
||||
catch(e) {
|
||||
alert('파일을 읽는데 실패했습니다.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var extendGeneralInfoForDB = function(generalData){
|
||||
|
||||
var dbVal = {
|
||||
nation: (generalData.no)<=1 ? 1 : 2,
|
||||
city: (generalData.no)<=1 ? 1 : 3,
|
||||
turntime:'2018-08-26 12:00',
|
||||
special:defaultSpecialDomestic,
|
||||
leadership_exp:0,
|
||||
strength_exp:0,
|
||||
intel_exp:0,
|
||||
|
||||
gold:10000,
|
||||
|
||||
dedication:0,
|
||||
|
||||
recent_war:'2018-08-26 12:00',
|
||||
experience:Math.pow(generalData.explevel, 2),
|
||||
};
|
||||
|
||||
return $.extend({}, generalData, dbVal);
|
||||
}
|
||||
|
||||
var getGeneralFrame = function($btn){
|
||||
var $card = $btn.closest('.general_form');
|
||||
return $card;
|
||||
}
|
||||
|
||||
var getGeneralDetail = function($btn){
|
||||
var $card = getGeneralFrame($btn);
|
||||
var $general = $card.find('.general_detail');
|
||||
return $general;
|
||||
}
|
||||
|
||||
var getGeneralNo = function($btn){
|
||||
return parseInt(getGeneralFrame($btn).data('general_no'));
|
||||
}
|
||||
|
||||
var setGeneralNo = function($btn, value){
|
||||
if(value == 1){
|
||||
//1번은 무조건 공격자임
|
||||
return false;
|
||||
}
|
||||
if(value in defenderNoList){
|
||||
return false;
|
||||
}
|
||||
var $card = getGeneralFrame($btn);
|
||||
$card.data('general_no', value);
|
||||
defenderNoList[value] = $card;
|
||||
return true;
|
||||
}
|
||||
|
||||
var generateNewGeneralNo = function(){
|
||||
while(true){
|
||||
var newGeneralNo = parseInt(Math.random()*(1<<24))+2;
|
||||
if(newGeneralNo in defenderNoList){
|
||||
continue;
|
||||
}
|
||||
return newGeneralNo;
|
||||
}
|
||||
}
|
||||
|
||||
var deleteGeneralNo = function($btn){
|
||||
var $card = getGeneralFrame($btn);
|
||||
$card.removeData('general_no');
|
||||
var generalNo = getGeneralNo($card);
|
||||
delete defenderNoList[generalNo];
|
||||
}
|
||||
|
||||
var addDefender = function($cardAfter){
|
||||
var $newCard = $('<div class="card mb-2 defender_form general_form"></div>');
|
||||
|
||||
if($cardAfter === undefined){
|
||||
$defenderColumn.append($newCard);
|
||||
}
|
||||
else{
|
||||
$cardAfter.after($newCard);
|
||||
}
|
||||
|
||||
$newCard.append($defenderHeaderForm.clone(true,true));
|
||||
$newCard.append($generalForm.clone(true,true));
|
||||
|
||||
$newGeneral = getGeneralDetail($newCard);
|
||||
setGeneralNo($newCard, generateNewGeneralNo());
|
||||
|
||||
return $newCard;
|
||||
}
|
||||
|
||||
var deleteDefender = function($card){
|
||||
deleteGeneralNo($card);
|
||||
$card.detach();
|
||||
}
|
||||
|
||||
var copyDefender = function($card){
|
||||
var $general = getGeneralDetail($card);
|
||||
|
||||
var generalData = exportGeneralInfo($general);
|
||||
var $newObj = addDefender($card);
|
||||
importGeneralInfo(getGeneralDetail($newObj), generalData);
|
||||
}
|
||||
|
||||
var importBattleInfo = function(battleData){
|
||||
|
||||
$('.form_load_battle_file').val('');
|
||||
console.log(battleData);
|
||||
|
||||
var $attackerNation = $('.attacker_nation');
|
||||
var $defenderNation = $('.defender_nation');
|
||||
|
||||
var attackerGeneral = battleData.attackerGeneral;
|
||||
var attackerCity = battleData.attackerCity;
|
||||
var attackerNation = battleData.attackerNation;
|
||||
|
||||
var defenderGenerals = battleData.defenderGenerals;
|
||||
var defenderCity = battleData.defenderCity;
|
||||
var defenderNation = battleData.defenderNation;
|
||||
|
||||
$('#year').val(battleData.year);
|
||||
$('#month').val(battleData.month);
|
||||
$('#repeat_cnt').val(battleData.repeatCnt);
|
||||
|
||||
$('.delete-defender').click();
|
||||
|
||||
$attackerNation.find('.form_nation_type').val(attackerNation.type);
|
||||
$attackerNation.find('.form_tech').val(Math.floor(attackerNation.tech/1000));
|
||||
$attackerNation.find('.form_nation_level').val(attackerNation.level);
|
||||
if(attackerNation.capital == 1){
|
||||
$attackerNation.find('.form_is_capital:first').click();
|
||||
}
|
||||
else{
|
||||
$attackerNation.find('.form_is_capital:last').click();
|
||||
}
|
||||
$attackerNation.find('.form_city_level').val(attackerCity.level);
|
||||
|
||||
importGeneralInfo($('.attacker_form'), attackerGeneral);
|
||||
|
||||
$defenderNation.find('.form_nation_type').val(defenderNation.type);
|
||||
$defenderNation.find('.form_tech').val(Math.floor(defenderNation.tech/1000));
|
||||
$defenderNation.find('.form_nation_level').val(defenderNation.level);
|
||||
if(defenderNation.capital == 1){
|
||||
$defenderNation.find('.form_is_capital:first').click();
|
||||
}
|
||||
else{
|
||||
$defenderNation.find('.form_is_capital:last').click();
|
||||
}
|
||||
$defenderNation.find('.form_city_level').val(defenderCity.level);
|
||||
$('#city_def').val(defenderCity.def);
|
||||
$('#city_wall').val(defenderCity.wall);
|
||||
|
||||
$.each(defenderGenerals, function(idx, defenderGeneral){
|
||||
var $card = addDefender();
|
||||
importGeneralInfo($card, defenderGeneral);
|
||||
});
|
||||
}
|
||||
|
||||
var exportAllData = function(){
|
||||
var $attackerNation = $('.attacker_nation');
|
||||
var $defenderNation = $('.defender_nation');
|
||||
|
||||
var attackerGeneral = exportGeneralInfo($('.attacker_form'));
|
||||
|
||||
var attackerCity = {
|
||||
level:parseInt($attackerNation.find('.form_city_level').val()),
|
||||
};
|
||||
|
||||
var attackerNation = {
|
||||
type:$attackerNation.find('.form_nation_type').val(),
|
||||
tech:parseInt($attackerNation.find('.form_tech').val()) * 1000,
|
||||
level:parseInt($attackerNation.find('.form_nation_level').val()),
|
||||
capital:$attackerNation.find('.form_is_capital:checked').val()=='1'?1:2,
|
||||
}
|
||||
|
||||
var defenderGenerals = $('.defender_form').map(function(){
|
||||
return exportGeneralInfo($(this));
|
||||
}).toArray();
|
||||
|
||||
var defenderCity = {
|
||||
def: parseInt($('#city_def').val()),
|
||||
wall: parseInt($('#city_wall').val()),
|
||||
level:parseInt($defenderNation.find('.form_city_level').val()),
|
||||
};
|
||||
|
||||
var defenderNation = {
|
||||
type:$defenderNation.find('.form_nation_type').val(),
|
||||
tech:parseInt($defenderNation.find('.form_tech').val()) * 1000,
|
||||
level:parseInt($defenderNation.find('.form_nation_level').val()),
|
||||
capital:$defenderNation.find('.form_is_capital:checked').val()=='1'?3:4,
|
||||
}
|
||||
|
||||
var year = parseInt($('#year').val());
|
||||
var month = parseInt($('#month').val());
|
||||
var repeatCnt = parseInt($('#repeat_cnt').val());
|
||||
|
||||
return {
|
||||
attackerGeneral:attackerGeneral,
|
||||
attackerCity:attackerCity,
|
||||
attackerNation:attackerNation,
|
||||
|
||||
defenderGenerals:defenderGenerals,
|
||||
defenderCity:defenderCity,
|
||||
defenderNation:defenderNation,
|
||||
|
||||
year:year,
|
||||
month:month,
|
||||
repeatCnt:repeatCnt,
|
||||
};
|
||||
}
|
||||
|
||||
var extendAllDataForDB = function(allData){
|
||||
var defaultNation = {
|
||||
nation:0,
|
||||
name:'재야',
|
||||
capital:0,
|
||||
level:0,
|
||||
gold:0,
|
||||
rice:2000,
|
||||
type:'None',
|
||||
tech:0,
|
||||
gennum:200,
|
||||
};
|
||||
|
||||
var defaultCity = {
|
||||
nation:0,
|
||||
supply:1,
|
||||
name:'도시',
|
||||
|
||||
pop:500000,
|
||||
agri:10000,
|
||||
comm:10000,
|
||||
secu:10000,
|
||||
def:1000,
|
||||
wall:1000,
|
||||
|
||||
trust:100,
|
||||
|
||||
pop_max:600000,
|
||||
agri_max:12000,
|
||||
comm_max:12000,
|
||||
secu_max:10000,
|
||||
def_max:12000,
|
||||
wall_max:12000,
|
||||
|
||||
dead:0,
|
||||
|
||||
state:0,
|
||||
|
||||
conflict:'{}',
|
||||
};
|
||||
|
||||
var attackerNation = $.extend({}, defaultNation, allData.attackerNation);
|
||||
attackerNation.nation = 1;
|
||||
attackerNation.name = '출병국';
|
||||
|
||||
var attackerCity = $.extend({}, defaultCity, allData.attackerCity);
|
||||
attackerCity.nation = 1;
|
||||
attackerCity.city = 1;
|
||||
|
||||
var attackerGeneral = extendGeneralInfoForDB(allData.attackerGeneral);
|
||||
if(2 <= attackerGeneral.officer_level && attackerGeneral.officer_level <= 4){
|
||||
attackerGeneral.officer_city = 1;
|
||||
}
|
||||
else{
|
||||
attackerGeneral.officer_city = 0;
|
||||
}
|
||||
|
||||
var defenderNation = $.extend({}, defaultNation, allData.defenderNation);
|
||||
defenderNation.nation = 2;
|
||||
defenderNation.name = '수비국';
|
||||
|
||||
var defenderCity = $.extend({}, defaultCity, allData.defenderCity);
|
||||
defenderCity.nation = 2;
|
||||
defenderCity.city = 3;
|
||||
defenderCity.wall_max = defenderCity.wall/5*6;
|
||||
defenderCity.def_max = defenderCity.def/5*6;
|
||||
|
||||
var defenderGenerals = [];
|
||||
$.each(allData.defenderGenerals, function(){
|
||||
var defenderGeneral = extendGeneralInfoForDB(this);
|
||||
if(2 <= defenderGeneral.officer_level && defenderGeneral.officer_level <= 4){
|
||||
defenderGeneral.officer_city = 3;
|
||||
}
|
||||
else{
|
||||
defenderGeneral.officer_city = 0;
|
||||
}
|
||||
|
||||
defenderGenerals.push(defenderGeneral);
|
||||
});
|
||||
|
||||
|
||||
return $.extend({}, allData, {
|
||||
attackerGeneral:attackerGeneral,
|
||||
attackerCity:attackerCity,
|
||||
attackerNation:attackerNation,
|
||||
|
||||
defenderGenerals:defenderGenerals,
|
||||
defenderCity:defenderCity,
|
||||
defenderNation:defenderNation,
|
||||
});
|
||||
}
|
||||
|
||||
var parseSkillCount = function(skills){
|
||||
var result = [];
|
||||
$.each(skills, function(key, value){
|
||||
result.push("{0}({1}회)".format(key, toPretty(value)));
|
||||
})
|
||||
|
||||
if(result.length == 0){
|
||||
return '-';
|
||||
}
|
||||
return result.join(', ');
|
||||
}
|
||||
|
||||
var toPretty = function(number){
|
||||
if(isInt(number)){
|
||||
number = parseInt(number);
|
||||
}
|
||||
else{
|
||||
number = parseFloat(number).toFixed(2);
|
||||
}
|
||||
return numberWithCommas(number);
|
||||
}
|
||||
|
||||
var showBattleResult = function(result){
|
||||
$('#result_datetime').html(result.datetime);
|
||||
$('#result_warcnt').html(toPretty(result.avgWar));
|
||||
$('#result_phase').html(toPretty(result.phase));
|
||||
$('#result_killed').html(toPretty(result.killed));
|
||||
if(result.minKilled != result.maxKilled){
|
||||
$('#result_maxKilled').html(toPretty(result.maxKilled));
|
||||
$('#result_minKilled').html(toPretty(result.minKilled));
|
||||
$('#result_varKilled').show();
|
||||
}
|
||||
else{
|
||||
$('#result_varKilled').hide();
|
||||
}
|
||||
$('#result_dead').html(toPretty(result.dead));
|
||||
if(result.minDead != result.maxDead){
|
||||
$('#result_maxDead').html(toPretty(result.maxDead));
|
||||
$('#result_minDead').html(toPretty(result.minDead));
|
||||
$('#result_varDead').show();
|
||||
}
|
||||
else{
|
||||
$('#result_varDead').hide();
|
||||
}
|
||||
|
||||
$('#result_attackerRice').html(toPretty(result.attackerRice));
|
||||
$('#result_defenderRice').html(toPretty(result.defenderRice));
|
||||
$('#result_attackerSkills').html(parseSkillCount(result.attackerSkills));
|
||||
|
||||
$('.result_defenderSkills').detach();
|
||||
|
||||
var $summary = $('#battle_result_summary');
|
||||
|
||||
$.each(result.defendersSkills, function(idx, defenderSkills){
|
||||
console.log(defenderSkills);
|
||||
var $result = $("<tr class='result_defenderSkills'><th>수비자{0} 스킬</th><td></td></tr>".format(idx + 1));
|
||||
$result.find('td').html(parseSkillCount(defenderSkills));
|
||||
$summary.append($result);
|
||||
});
|
||||
|
||||
$('#generalBattleResultLog').html(result.lastWarLog.generalBattleResultLog);
|
||||
$('#generalBattleDetailLog').html(result.lastWarLog.generalBattleDetailLog);
|
||||
|
||||
}
|
||||
|
||||
var beginBattle = function(){
|
||||
var data = extendAllDataForDB(exportAllData());
|
||||
console.log(data);
|
||||
$.ajax({
|
||||
type:'post',
|
||||
url:'j_simulate_battle.php',
|
||||
dataType:'json',
|
||||
data:{
|
||||
action:'battle',
|
||||
query:JSON.stringify(data),
|
||||
}
|
||||
}).then(function(result){
|
||||
console.log(result);
|
||||
if(!result.result){
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
showBattleResult(result);
|
||||
|
||||
}, function(result){
|
||||
alert('전투 개시 실패!');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var reorderDefender = function(defenderOrder){
|
||||
$.each(defenderOrder, function(idx, generalNo){
|
||||
|
||||
if(!(generalNo in defenderNoList)){
|
||||
//음..?
|
||||
alert("{0}이 수비자 리스트에 없습니다. 버그인 듯 합니다.".format(generalNo));
|
||||
return true;
|
||||
}
|
||||
|
||||
var $defenderObj = defenderNoList[generalNo];
|
||||
$defenderObj.detach();
|
||||
$defenderColumn.append($defenderObj);
|
||||
})
|
||||
}
|
||||
|
||||
var requestReorderDefender = function(){
|
||||
var data = extendAllDataForDB(exportAllData());
|
||||
console.log(data);
|
||||
$.ajax({
|
||||
type:'post',
|
||||
url:'j_simulate_battle.php',
|
||||
dataType:'json',
|
||||
data:{
|
||||
action:'reorder',
|
||||
query:JSON.stringify(data),
|
||||
}
|
||||
}).then(function(result){
|
||||
console.log(result);
|
||||
if(!result.result){
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
reorderDefender(result.order);
|
||||
|
||||
}, function(result){
|
||||
alert('재정렬 실패!');
|
||||
});
|
||||
}
|
||||
|
||||
initBasicEvent();
|
||||
$attackerCard.append($generalForm.clone(true,true));
|
||||
addDefender();
|
||||
|
||||
$('.btn-begin_battle').click(function(){
|
||||
beginBattle();
|
||||
});
|
||||
|
||||
$('.btn-reorder_defender').click(function(){
|
||||
requestReorderDefender();
|
||||
})
|
||||
jQuery(function($) {
|
||||
|
||||
|
||||
var $generalForm = $('.form_sample .general_detail');
|
||||
var $defenderHeaderForm = $('.form_sample .card-header');
|
||||
var $defenderColumn = $('.defender-column');
|
||||
|
||||
var defenderNoList = {};
|
||||
|
||||
var $attackerCard = $('.attacker_form');
|
||||
|
||||
var initBasicEvent = function() {
|
||||
|
||||
if (window.nation) {
|
||||
$('.form_city_level').val(window.city.level);
|
||||
$('.form_def').val(parseInt(window.city.def));
|
||||
$('.form_wall').val(parseInt(window.city.wall));
|
||||
$('.form_nation_type').val(window.nation.type);
|
||||
$('.form_nation_level').val(window.nation.level);
|
||||
$('.form_tech').val(parseInt(window.nation.tech / 1000));
|
||||
if (window.nation.capital == window.city.city) {
|
||||
$('.attacker_nation .form_is_capital:first').click();
|
||||
$('.defender_nation .form_is_capital:first').click();
|
||||
} else {
|
||||
$('.attacker_nation .form_is_capital:last').click();
|
||||
$('.defender_nation .form_is_capital:last').click();
|
||||
}
|
||||
} else {
|
||||
$('.attacker_nation .form_is_capital:last').click();
|
||||
$('.defender_nation .form_is_capital:last').click();
|
||||
}
|
||||
|
||||
$('.form_injury').change(function() {
|
||||
var $this = $(this);
|
||||
var $general = getGeneralDetail($this);
|
||||
var $helptext = $general.find('.injury_helptext');
|
||||
|
||||
var injury = parseInt($this.val());
|
||||
//FIXME: PHP 코드와 항상 일치하도록 변경
|
||||
var text = '건강';
|
||||
var color = 'white';
|
||||
if (injury > 60) {
|
||||
text = '위독';
|
||||
color = 'red';
|
||||
} else if (injury > 40) {
|
||||
text = '심각';
|
||||
color = 'magenta';
|
||||
} else if (injury > 20) {
|
||||
text = '중상';
|
||||
color = 'orange';
|
||||
} else if (injury > 0) {
|
||||
text = '경상';
|
||||
color = 'yellow';
|
||||
}
|
||||
$helptext.html(text).css('color', color);
|
||||
});
|
||||
|
||||
$('.export_general').click(function() {
|
||||
var $btn = $(this);
|
||||
var $general = getGeneralDetail($btn);
|
||||
|
||||
var values = exportGeneralInfo($general);
|
||||
console.log(values);
|
||||
});
|
||||
$('.delete-defender').click(function() {
|
||||
var $card = getGeneralFrame($(this));
|
||||
deleteDefender($card);
|
||||
});
|
||||
$('.copy-defender').click(function() {
|
||||
var $card = getGeneralFrame($(this));
|
||||
copyDefender($card);
|
||||
});
|
||||
|
||||
$('.add-defender').click(function() {
|
||||
addDefender();
|
||||
});
|
||||
|
||||
$('.btn-general-load').click(function() {
|
||||
var $file = $(this).prev();
|
||||
$file[0].click();
|
||||
})
|
||||
|
||||
$('.form_load_general_file').on('change', function(e) {
|
||||
e.preventDefault();
|
||||
var $this = $(this);
|
||||
var $card = getGeneralFrame($this);
|
||||
|
||||
var files = e.target.files;
|
||||
|
||||
importGeneralInfoByFile(files, $card);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.btn-general-import-server').click(function() {
|
||||
var $this = $(this);
|
||||
var $card = getGeneralFrame($this);
|
||||
|
||||
var $modal = $('#importModal');
|
||||
$modal.data('target', $card);
|
||||
$modal.modal('show');
|
||||
});
|
||||
|
||||
$('.btn-general-save').click(function() {
|
||||
var $this = $(this);
|
||||
var $general = getGeneralDetail($this);
|
||||
var generalData = exportGeneralInfo($general);
|
||||
|
||||
var filename = "general_{0}.json".format(generalData.name);
|
||||
var saveData = JSON.stringify({
|
||||
objType: 'general',
|
||||
data: generalData
|
||||
}, null, 4);
|
||||
|
||||
download(saveData, filename, 'application/json');
|
||||
});
|
||||
|
||||
$('.btn-battle-load').click(function() {
|
||||
var $file = $(this).prev();
|
||||
$file[0].click();
|
||||
})
|
||||
|
||||
$('.form_load_battle_file').on('change', function(e) {
|
||||
e.preventDefault();
|
||||
var $this = $(this);
|
||||
var files = e.target.files;
|
||||
|
||||
importBattleInfoByFile(files);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.btn-battle-save').click(function() {
|
||||
var battleData = exportAllData();
|
||||
var filename = "battle_{0}.json".format(moment().format('YYYYMMDD_hhmmss'));
|
||||
var saveData = JSON.stringify({
|
||||
objType: 'battle',
|
||||
data: battleData
|
||||
}, null, 4);
|
||||
|
||||
download(saveData, filename, 'application/json');
|
||||
})
|
||||
|
||||
var $generals = $('.general_detail');
|
||||
$generals.bind('dragover dragleave', function(e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
})
|
||||
$generals.bind('drop', function(e) {
|
||||
e.preventDefault();
|
||||
var $this = $(this);
|
||||
var $card = getGeneralFrame($this);
|
||||
|
||||
var files = e.originalEvent.dataTransfer.files;
|
||||
|
||||
importGeneralInfoByFile(files, $card);
|
||||
return false;
|
||||
});
|
||||
|
||||
var $battlePad = $('.dragpad_battle');
|
||||
$battlePad.bind('dragover dragleave', function(e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
})
|
||||
$battlePad.bind('drop', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var files = e.originalEvent.dataTransfer.files;
|
||||
|
||||
importBattleInfoByFile(files);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
var importGeneralInfo = function($general, data) {
|
||||
var setVal = function(query, val) {
|
||||
$general.find(query).val(val).change();
|
||||
}
|
||||
|
||||
setVal('.form_general_name', data.name);
|
||||
|
||||
setVal('.form_officer_level', data.officer_level);
|
||||
setVal('.form_exp_level', data.explevel);
|
||||
|
||||
setVal('.form_leadership', data.leadership);
|
||||
setVal('.form_general_horse', data.horse);
|
||||
setVal('.form_strength', data.strength);
|
||||
setVal('.form_general_weap', data.weapon);
|
||||
setVal('.form_intel', data.intel);
|
||||
setVal('.form_general_book', data.book);
|
||||
setVal('.form_general_item', data.item);
|
||||
|
||||
setVal('.form_injury', data.injury);
|
||||
|
||||
setVal('.form_rice', data.rice);
|
||||
|
||||
setVal('.form_general_character', data.personal);
|
||||
setVal('.form_general_special_war', data.special2);
|
||||
|
||||
setVal('.form_crew', data.crew);
|
||||
setVal('.form_crewtype', data.crewtype);
|
||||
setVal('.form_atmos', data.atmos);
|
||||
setVal('.form_train', data.train);
|
||||
|
||||
setVal('.form_dex1', data.dex1);
|
||||
setVal('.form_dex2', data.dex2);
|
||||
setVal('.form_dex3', data.dex3);
|
||||
setVal('.form_dex4', data.dex4);
|
||||
setVal('.form_dex5', data.dex5);
|
||||
setVal('.form_defence_train', data.defence_train);
|
||||
|
||||
setVal('.form_warnum', data.warnum);
|
||||
setVal('.form_killnum', data.killnum);
|
||||
setVal('.form_killcrew', data.killcrew);
|
||||
|
||||
if (!setGeneralNo($general, data.no)) {
|
||||
setGeneralNo($general, generateNewGeneralNo());
|
||||
}
|
||||
}
|
||||
|
||||
var exportGeneralInfo = function($general) {
|
||||
var getInt = function(query) {
|
||||
return parseInt($general.find(query).val());
|
||||
}
|
||||
|
||||
var getVal = function(query) {
|
||||
return $general.find(query).val();
|
||||
}
|
||||
|
||||
return {
|
||||
no: getGeneralNo($general),
|
||||
name: getVal('.form_general_name'),
|
||||
officer_level: getInt('.form_officer_level'),
|
||||
explevel: getInt('.form_exp_level'),
|
||||
|
||||
leadership: getInt('.form_leadership'),
|
||||
horse: getVal('.form_general_horse'),
|
||||
strength: getInt('.form_strength'),
|
||||
weapon: getVal('.form_general_weap'),
|
||||
intel: getInt('.form_intel'),
|
||||
book: getVal('.form_general_book'),
|
||||
item: getVal('.form_general_item'),
|
||||
|
||||
injury: getInt('.form_injury'),
|
||||
|
||||
rice: getInt('.form_rice'),
|
||||
|
||||
personal: getVal('.form_general_character'),
|
||||
special2: getVal('.form_general_special_war'),
|
||||
|
||||
crew: getInt('.form_crew'),
|
||||
crewtype: getInt('.form_crewtype'),
|
||||
atmos: getInt('.form_atmos'),
|
||||
train: getInt('.form_train'),
|
||||
|
||||
dex1: getInt('.form_dex1'),
|
||||
dex2: getInt('.form_dex2'),
|
||||
dex3: getInt('.form_dex3'),
|
||||
dex4: getInt('.form_dex4'),
|
||||
dex5: getInt('.form_dex5'),
|
||||
|
||||
defence_train: getInt('.form_defence_train'),
|
||||
|
||||
warnum: getInt('.form_warnum'),
|
||||
killnum: getInt('.form_killnum'),
|
||||
killcrew: getInt('.form_killcrew'),
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
var importBattleInfoByFile = function(files) {
|
||||
if (files === null) {
|
||||
alert('파일 에러!');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (files.length < 1) {
|
||||
alert("파일 에러!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
var file = files[0];
|
||||
if (file.size > 1024 * 1024) {
|
||||
alert('파일이 너무 큽니다!');
|
||||
return false;
|
||||
}
|
||||
if (file.type === '') {
|
||||
alert('폴더를 업로드할 수 없습니다!');
|
||||
return false;
|
||||
}
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function() {
|
||||
var battleData = {};
|
||||
try {
|
||||
battleData = JSON.parse(reader.result);
|
||||
} catch (e) {
|
||||
alert('올바르지 않은 파일 형식입니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!('objType' in battleData)) {
|
||||
alert('파일 형식을 확인할 수 없습니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (battleData.objType != 'battle') {
|
||||
alert('전투 데이터가 아닙니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
importBattleInfo(battleData.data);
|
||||
return true;
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
reader.readAsText(file);
|
||||
} catch (e) {
|
||||
alert('파일을 읽는데 실패했습니다.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var importGeneralInfoByFile = function(files, $card) {
|
||||
if ($card === undefined) {
|
||||
$card = addDefender();
|
||||
}
|
||||
|
||||
if (files === null) {
|
||||
alert('파일 에러!');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (files.length < 1) {
|
||||
alert("파일 에러!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
var file = files[0];
|
||||
if (file.size > 1024 * 1024) {
|
||||
alert('파일이 너무 큽니다!');
|
||||
return false;
|
||||
}
|
||||
if (file.type === '') {
|
||||
alert('폴더를 업로드할 수 없습니다!');
|
||||
return false;
|
||||
}
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function() {
|
||||
var generalData = {};
|
||||
try {
|
||||
generalData = JSON.parse(reader.result);
|
||||
} catch (e) {
|
||||
alert('올바르지 않은 파일 형식입니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!('objType' in generalData)) {
|
||||
alert('파일 형식을 확인할 수 없습니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (generalData.objType == 'battle') {
|
||||
importBattleInfo(generalData.data);
|
||||
return true;
|
||||
}
|
||||
if (generalData.objType != 'general') {
|
||||
alert('장수 데이터가 아닙니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
$card.find('.form_load_general_file').val('');
|
||||
|
||||
importGeneralInfo($card, generalData.data);
|
||||
return true;
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
reader.readAsText(file);
|
||||
} catch (e) {
|
||||
alert('파일을 읽는데 실패했습니다.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var extendGeneralInfoForDB = function(generalData) {
|
||||
|
||||
var dbVal = {
|
||||
nation: (generalData.no) <= 1 ? 1 : 2,
|
||||
city: (generalData.no) <= 1 ? 1 : 3,
|
||||
turntime: '2018-08-26 12:00',
|
||||
special: defaultSpecialDomestic,
|
||||
leadership_exp: 0,
|
||||
strength_exp: 0,
|
||||
intel_exp: 0,
|
||||
|
||||
gold: 10000,
|
||||
|
||||
dedication: 0,
|
||||
|
||||
recent_war: '2018-08-26 12:00',
|
||||
experience: Math.pow(generalData.explevel, 2),
|
||||
};
|
||||
|
||||
return $.extend({}, generalData, dbVal);
|
||||
}
|
||||
|
||||
var getGeneralFrame = function($btn) {
|
||||
var $card = $btn.closest('.general_form');
|
||||
return $card;
|
||||
}
|
||||
|
||||
var getGeneralDetail = function($btn) {
|
||||
var $card = getGeneralFrame($btn);
|
||||
var $general = $card.find('.general_detail');
|
||||
return $general;
|
||||
}
|
||||
|
||||
var getGeneralNo = function($btn) {
|
||||
return parseInt(getGeneralFrame($btn).data('general_no'));
|
||||
}
|
||||
|
||||
var setGeneralNo = function($btn, value) {
|
||||
if (value == 1) {
|
||||
//1번은 무조건 공격자임
|
||||
return false;
|
||||
}
|
||||
if (value in defenderNoList) {
|
||||
return false;
|
||||
}
|
||||
var $card = getGeneralFrame($btn);
|
||||
$card.data('general_no', value);
|
||||
defenderNoList[value] = $card;
|
||||
return true;
|
||||
}
|
||||
|
||||
var generateNewGeneralNo = function() {
|
||||
while (true) {
|
||||
var newGeneralNo = parseInt(Math.random() * (1 << 24)) + 2;
|
||||
if (newGeneralNo in defenderNoList) {
|
||||
continue;
|
||||
}
|
||||
return newGeneralNo;
|
||||
}
|
||||
}
|
||||
|
||||
var deleteGeneralNo = function($btn) {
|
||||
var $card = getGeneralFrame($btn);
|
||||
$card.removeData('general_no');
|
||||
var generalNo = getGeneralNo($card);
|
||||
delete defenderNoList[generalNo];
|
||||
}
|
||||
|
||||
var addDefender = function($cardAfter) {
|
||||
var $newCard = $('<div class="card mb-2 defender_form general_form"></div>');
|
||||
|
||||
if ($cardAfter === undefined) {
|
||||
$defenderColumn.append($newCard);
|
||||
} else {
|
||||
$cardAfter.after($newCard);
|
||||
}
|
||||
|
||||
$newCard.append($defenderHeaderForm.clone(true, true));
|
||||
$newCard.append($generalForm.clone(true, true));
|
||||
|
||||
$newGeneral = getGeneralDetail($newCard);
|
||||
setGeneralNo($newCard, generateNewGeneralNo());
|
||||
|
||||
return $newCard;
|
||||
}
|
||||
|
||||
var deleteDefender = function($card) {
|
||||
deleteGeneralNo($card);
|
||||
$card.detach();
|
||||
}
|
||||
|
||||
var copyDefender = function($card) {
|
||||
var $general = getGeneralDetail($card);
|
||||
|
||||
var generalData = exportGeneralInfo($general);
|
||||
var $newObj = addDefender($card);
|
||||
importGeneralInfo(getGeneralDetail($newObj), generalData);
|
||||
}
|
||||
|
||||
var importBattleInfo = function(battleData) {
|
||||
|
||||
$('.form_load_battle_file').val('');
|
||||
console.log(battleData);
|
||||
|
||||
var $attackerNation = $('.attacker_nation');
|
||||
var $defenderNation = $('.defender_nation');
|
||||
|
||||
var attackerGeneral = battleData.attackerGeneral;
|
||||
var attackerCity = battleData.attackerCity;
|
||||
var attackerNation = battleData.attackerNation;
|
||||
|
||||
var defenderGenerals = battleData.defenderGenerals;
|
||||
var defenderCity = battleData.defenderCity;
|
||||
var defenderNation = battleData.defenderNation;
|
||||
|
||||
$('#year').val(battleData.year);
|
||||
$('#month').val(battleData.month);
|
||||
$('#repeat_cnt').val(battleData.repeatCnt);
|
||||
|
||||
$('.delete-defender').click();
|
||||
|
||||
$attackerNation.find('.form_nation_type').val(attackerNation.type);
|
||||
$attackerNation.find('.form_tech').val(Math.floor(attackerNation.tech / 1000));
|
||||
$attackerNation.find('.form_nation_level').val(attackerNation.level);
|
||||
if (attackerNation.capital == 1) {
|
||||
$attackerNation.find('.form_is_capital:first').click();
|
||||
} else {
|
||||
$attackerNation.find('.form_is_capital:last').click();
|
||||
}
|
||||
$attackerNation.find('.form_city_level').val(attackerCity.level);
|
||||
|
||||
importGeneralInfo($('.attacker_form'), attackerGeneral);
|
||||
|
||||
$defenderNation.find('.form_nation_type').val(defenderNation.type);
|
||||
$defenderNation.find('.form_tech').val(Math.floor(defenderNation.tech / 1000));
|
||||
$defenderNation.find('.form_nation_level').val(defenderNation.level);
|
||||
if (defenderNation.capital == 1) {
|
||||
$defenderNation.find('.form_is_capital:first').click();
|
||||
} else {
|
||||
$defenderNation.find('.form_is_capital:last').click();
|
||||
}
|
||||
$defenderNation.find('.form_city_level').val(defenderCity.level);
|
||||
$('#city_def').val(defenderCity.def);
|
||||
$('#city_wall').val(defenderCity.wall);
|
||||
|
||||
$.each(defenderGenerals, function(idx, defenderGeneral) {
|
||||
var $card = addDefender();
|
||||
importGeneralInfo($card, defenderGeneral);
|
||||
});
|
||||
}
|
||||
|
||||
var exportAllData = function() {
|
||||
var $attackerNation = $('.attacker_nation');
|
||||
var $defenderNation = $('.defender_nation');
|
||||
|
||||
var attackerGeneral = exportGeneralInfo($('.attacker_form'));
|
||||
|
||||
var attackerCity = {
|
||||
level: parseInt($attackerNation.find('.form_city_level').val()),
|
||||
};
|
||||
|
||||
var attackerNation = {
|
||||
type: $attackerNation.find('.form_nation_type').val(),
|
||||
tech: parseInt($attackerNation.find('.form_tech').val()) * 1000,
|
||||
level: parseInt($attackerNation.find('.form_nation_level').val()),
|
||||
capital: $attackerNation.find('.form_is_capital:checked').val() == '1' ? 1 : 2,
|
||||
}
|
||||
|
||||
var defenderGenerals = $('.defender_form').map(function() {
|
||||
return exportGeneralInfo($(this));
|
||||
}).toArray();
|
||||
|
||||
var defenderCity = {
|
||||
def: parseInt($('#city_def').val()),
|
||||
wall: parseInt($('#city_wall').val()),
|
||||
level: parseInt($defenderNation.find('.form_city_level').val()),
|
||||
};
|
||||
|
||||
var defenderNation = {
|
||||
type: $defenderNation.find('.form_nation_type').val(),
|
||||
tech: parseInt($defenderNation.find('.form_tech').val()) * 1000,
|
||||
level: parseInt($defenderNation.find('.form_nation_level').val()),
|
||||
capital: $defenderNation.find('.form_is_capital:checked').val() == '1' ? 3 : 4,
|
||||
}
|
||||
|
||||
var year = parseInt($('#year').val());
|
||||
var month = parseInt($('#month').val());
|
||||
var repeatCnt = parseInt($('#repeat_cnt').val());
|
||||
|
||||
return {
|
||||
attackerGeneral: attackerGeneral,
|
||||
attackerCity: attackerCity,
|
||||
attackerNation: attackerNation,
|
||||
|
||||
defenderGenerals: defenderGenerals,
|
||||
defenderCity: defenderCity,
|
||||
defenderNation: defenderNation,
|
||||
|
||||
year: year,
|
||||
month: month,
|
||||
repeatCnt: repeatCnt,
|
||||
};
|
||||
}
|
||||
|
||||
var extendAllDataForDB = function(allData) {
|
||||
var defaultNation = {
|
||||
nation: 0,
|
||||
name: '재야',
|
||||
capital: 0,
|
||||
level: 0,
|
||||
gold: 0,
|
||||
rice: 2000,
|
||||
type: 'None',
|
||||
tech: 0,
|
||||
gennum: 200,
|
||||
};
|
||||
|
||||
var defaultCity = {
|
||||
nation: 0,
|
||||
supply: 1,
|
||||
name: '도시',
|
||||
|
||||
pop: 500000,
|
||||
agri: 10000,
|
||||
comm: 10000,
|
||||
secu: 10000,
|
||||
def: 1000,
|
||||
wall: 1000,
|
||||
|
||||
trust: 100,
|
||||
|
||||
pop_max: 600000,
|
||||
agri_max: 12000,
|
||||
comm_max: 12000,
|
||||
secu_max: 10000,
|
||||
def_max: 12000,
|
||||
wall_max: 12000,
|
||||
|
||||
dead: 0,
|
||||
|
||||
state: 0,
|
||||
|
||||
conflict: '{}',
|
||||
};
|
||||
|
||||
var attackerNation = $.extend({}, defaultNation, allData.attackerNation);
|
||||
attackerNation.nation = 1;
|
||||
attackerNation.name = '출병국';
|
||||
|
||||
var attackerCity = $.extend({}, defaultCity, allData.attackerCity);
|
||||
attackerCity.nation = 1;
|
||||
attackerCity.city = 1;
|
||||
|
||||
var attackerGeneral = extendGeneralInfoForDB(allData.attackerGeneral);
|
||||
if (2 <= attackerGeneral.officer_level && attackerGeneral.officer_level <= 4) {
|
||||
attackerGeneral.officer_city = 1;
|
||||
} else {
|
||||
attackerGeneral.officer_city = 0;
|
||||
}
|
||||
|
||||
var defenderNation = $.extend({}, defaultNation, allData.defenderNation);
|
||||
defenderNation.nation = 2;
|
||||
defenderNation.name = '수비국';
|
||||
|
||||
var defenderCity = $.extend({}, defaultCity, allData.defenderCity);
|
||||
defenderCity.nation = 2;
|
||||
defenderCity.city = 3;
|
||||
defenderCity.wall_max = parseInt(defenderCity.wall / 5 * 6);
|
||||
defenderCity.def_max = parseInt(defenderCity.def / 5 * 6);
|
||||
|
||||
var defenderGenerals = [];
|
||||
$.each(allData.defenderGenerals, function() {
|
||||
var defenderGeneral = extendGeneralInfoForDB(this);
|
||||
if (2 <= defenderGeneral.officer_level && defenderGeneral.officer_level <= 4) {
|
||||
defenderGeneral.officer_city = 3;
|
||||
} else {
|
||||
defenderGeneral.officer_city = 0;
|
||||
}
|
||||
|
||||
defenderGenerals.push(defenderGeneral);
|
||||
});
|
||||
|
||||
|
||||
return $.extend({}, allData, {
|
||||
attackerGeneral: attackerGeneral,
|
||||
attackerCity: attackerCity,
|
||||
attackerNation: attackerNation,
|
||||
|
||||
defenderGenerals: defenderGenerals,
|
||||
defenderCity: defenderCity,
|
||||
defenderNation: defenderNation,
|
||||
});
|
||||
}
|
||||
|
||||
var parseSkillCount = function(skills) {
|
||||
var result = [];
|
||||
$.each(skills, function(key, value) {
|
||||
result.push("{0}({1}회)".format(key, toPretty(value)));
|
||||
})
|
||||
|
||||
if (result.length == 0) {
|
||||
return '-';
|
||||
}
|
||||
return result.join(', ');
|
||||
}
|
||||
|
||||
var toPretty = function(number) {
|
||||
if (isInt(number)) {
|
||||
number = parseInt(number);
|
||||
} else {
|
||||
number = parseFloat(number).toFixed(2);
|
||||
}
|
||||
return numberWithCommas(number);
|
||||
}
|
||||
|
||||
var showBattleResult = function(result) {
|
||||
$('#result_datetime').html(result.datetime);
|
||||
$('#result_warcnt').html(toPretty(result.avgWar));
|
||||
$('#result_phase').html(toPretty(result.phase));
|
||||
$('#result_killed').html(toPretty(result.killed));
|
||||
if (result.minKilled != result.maxKilled) {
|
||||
$('#result_maxKilled').html(toPretty(result.maxKilled));
|
||||
$('#result_minKilled').html(toPretty(result.minKilled));
|
||||
$('#result_varKilled').show();
|
||||
} else {
|
||||
$('#result_varKilled').hide();
|
||||
}
|
||||
$('#result_dead').html(toPretty(result.dead));
|
||||
if (result.minDead != result.maxDead) {
|
||||
$('#result_maxDead').html(toPretty(result.maxDead));
|
||||
$('#result_minDead').html(toPretty(result.minDead));
|
||||
$('#result_varDead').show();
|
||||
} else {
|
||||
$('#result_varDead').hide();
|
||||
}
|
||||
|
||||
$('#result_attackerRice').html(toPretty(result.attackerRice));
|
||||
$('#result_defenderRice').html(toPretty(result.defenderRice));
|
||||
$('#result_attackerSkills').html(parseSkillCount(result.attackerSkills));
|
||||
|
||||
$('.result_defenderSkills').detach();
|
||||
|
||||
var $summary = $('#battle_result_summary');
|
||||
|
||||
$.each(result.defendersSkills, function(idx, defenderSkills) {
|
||||
console.log(defenderSkills);
|
||||
var $result = $("<tr class='result_defenderSkills'><th>수비자{0} 스킬</th><td></td></tr>".format(idx + 1));
|
||||
$result.find('td').html(parseSkillCount(defenderSkills));
|
||||
$summary.append($result);
|
||||
});
|
||||
|
||||
$('#generalBattleResultLog').html(result.lastWarLog.generalBattleResultLog);
|
||||
$('#generalBattleDetailLog').html(result.lastWarLog.generalBattleDetailLog);
|
||||
|
||||
}
|
||||
|
||||
var beginBattle = function() {
|
||||
var data = extendAllDataForDB(exportAllData());
|
||||
console.log(data);
|
||||
$.ajax({
|
||||
type: 'post',
|
||||
url: 'j_simulate_battle.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
action: 'battle',
|
||||
query: JSON.stringify(data),
|
||||
}
|
||||
}).then(function(result) {
|
||||
console.log(result);
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
showBattleResult(result);
|
||||
|
||||
}, function(result) {
|
||||
alert('전투 개시 실패!');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var reorderDefender = function(defenderOrder) {
|
||||
$.each(defenderOrder, function(idx, generalNo) {
|
||||
|
||||
if (!(generalNo in defenderNoList)) {
|
||||
//음..?
|
||||
alert("{0}이 수비자 리스트에 없습니다. 버그인 듯 합니다.".format(generalNo));
|
||||
return true;
|
||||
}
|
||||
|
||||
var $defenderObj = defenderNoList[generalNo];
|
||||
$defenderObj.detach();
|
||||
$defenderColumn.append($defenderObj);
|
||||
})
|
||||
}
|
||||
|
||||
var requestReorderDefender = function() {
|
||||
var data = extendAllDataForDB(exportAllData());
|
||||
console.log(data);
|
||||
$.ajax({
|
||||
type: 'post',
|
||||
url: 'j_simulate_battle.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
action: 'reorder',
|
||||
query: JSON.stringify(data),
|
||||
}
|
||||
}).then(function(result) {
|
||||
console.log(result);
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
reorderDefender(result.order);
|
||||
|
||||
}, function(result) {
|
||||
alert('재정렬 실패!');
|
||||
});
|
||||
}
|
||||
|
||||
var initGeneralList = false;
|
||||
|
||||
$('#importFromDB').click(function() {
|
||||
var generalID = $('#modalSelector').val();
|
||||
console.log(generalID);
|
||||
|
||||
|
||||
$.post({
|
||||
url: 'j_export_simulator_object.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
destGeneralID: generalID
|
||||
}
|
||||
}).then(function(data) {
|
||||
|
||||
if (!data.result) {
|
||||
alert(data.reason);
|
||||
return false;
|
||||
}
|
||||
|
||||
var $modal = $('#importModal');
|
||||
var $card = $modal.data('target');
|
||||
importGeneralInfo($card, data.general);
|
||||
|
||||
$modal.modal('hide');
|
||||
}, errUnknown);
|
||||
|
||||
|
||||
});
|
||||
|
||||
$('#importModal').on('show.bs.modal', function(e) {
|
||||
if (!initGeneralList) {
|
||||
var $list = $('#modalSelector');
|
||||
|
||||
var addNation = function(generalList, nationName, color) {
|
||||
|
||||
generalList.sort(function(lhs, rhs) {
|
||||
if (lhs.npc != rhs.npc) {
|
||||
return lhs.npc - rhs.npc;
|
||||
}
|
||||
if (lhs.name < rhs.name) {
|
||||
return -1;
|
||||
}
|
||||
if (lhs.name > rhs.name) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
})
|
||||
var $optGroup = $('<optgroup label="{0}"></optgroup>'.format(nationName));
|
||||
$optGroup.css('background-color', color);
|
||||
$optGroup.css('color', isBrightColor(color) ? 'black' : 'white');
|
||||
|
||||
$.each(generalList, function(idx, general) {
|
||||
$item = $('<option value="{0}">{1}</option>'.format(general.no, general.name));
|
||||
if (general.npc) {
|
||||
$item.css('color', getNpcColor(general.npc));
|
||||
} else {
|
||||
$item.css('color', 'white');
|
||||
}
|
||||
$item.css('background-color', 'black');
|
||||
$optGroup.append($item);
|
||||
|
||||
});
|
||||
$list.append($optGroup);
|
||||
}
|
||||
$.post({
|
||||
url: 'j_get_basic_general_list.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
req: 2,
|
||||
}
|
||||
}).then(function(data) {
|
||||
if (!data.result) {
|
||||
alert(data.reason);
|
||||
$('#importModal').modal('hide');
|
||||
return false;
|
||||
}
|
||||
|
||||
var nations = data.nation;
|
||||
var myNationID = data.nationID;
|
||||
|
||||
$list.empty();
|
||||
//자국 먼저
|
||||
|
||||
if (0 in data.list) {
|
||||
nations[0] = {
|
||||
nation: 0,
|
||||
name: '재야',
|
||||
color: '#000000'
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
addNation(combineArray(data.list[myNationID], data.column), nations[myNationID].name, nations[myNationID].color);
|
||||
|
||||
for (var nationID in data.list) {
|
||||
if (nationID == myNationID) {
|
||||
continue;
|
||||
}
|
||||
addNation(combineArray(data.list[nationID], data.column), nations[nationID].name, nations[nationID].color);
|
||||
}
|
||||
initGeneralList = true;
|
||||
}, errUnknown);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
initBasicEvent();
|
||||
$attackerCard.append($generalForm.clone(true, true));
|
||||
addDefender();
|
||||
|
||||
$('.btn-begin_battle').click(function() {
|
||||
beginBattle();
|
||||
});
|
||||
|
||||
$('.btn-reorder_defender').click(function() {
|
||||
requestReorderDefender();
|
||||
})
|
||||
});
|
||||
+194
-200
@@ -1,201 +1,195 @@
|
||||
function changePermission(isAmbassador, rawGeneralList){
|
||||
console.log(isAmbassador);
|
||||
console.log(rawGeneralList);
|
||||
|
||||
var generalList = [];
|
||||
$.each(rawGeneralList, function(idx, value){
|
||||
generalList.push(parseInt(value.id));
|
||||
})
|
||||
|
||||
$.post({
|
||||
url:'j_general_set_permission.php',
|
||||
dataType:'json',
|
||||
data:{
|
||||
isAmbassador:isAmbassador,
|
||||
genlist:generalList
|
||||
},
|
||||
}).then(function(data){
|
||||
if(!data){
|
||||
alert('변경하지 못했습니다.');
|
||||
return false;
|
||||
}
|
||||
if(!data.result){
|
||||
alert('변경하지 못했습니다. : '+data.reason);
|
||||
return false;
|
||||
}
|
||||
alert('변경했습니다.');
|
||||
location.reload();
|
||||
}, errUnknown);
|
||||
}
|
||||
|
||||
$(function(){
|
||||
$('#selectAmbassador').select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: "",
|
||||
allowClear: true,
|
||||
language: "ko",
|
||||
width:300,
|
||||
maximumSelectionLength: 2,
|
||||
containerCss: {
|
||||
display: "inline-block !important;",
|
||||
color: 'white !important'
|
||||
},
|
||||
data:candidateAmbassadors,
|
||||
//containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
});
|
||||
|
||||
$('#selectAuditor').select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: "",
|
||||
allowClear: true,
|
||||
language: "ko",
|
||||
width:300,
|
||||
maximumSelectionLength: 2,
|
||||
containerCss: {
|
||||
display: "inline-block !important;",
|
||||
color: 'white !important'
|
||||
},
|
||||
data:candidateAuditors,
|
||||
//containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
});
|
||||
|
||||
$('#changeAmbassador').click(function(){
|
||||
if(!confirm('외교권자를 변경할까요?')){
|
||||
return false;
|
||||
}
|
||||
|
||||
changePermission(true, $('#selectAmbassador').select2('data'));
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#changeAuditor').click(function(){
|
||||
if(!confirm('조언자를 변경할까요?')){
|
||||
return false;
|
||||
}
|
||||
|
||||
changePermission(false, $('#selectAuditor').select2('data'));
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#btn_kick').click(function(){
|
||||
var $kickSelect = $('#genlist_kick option:selected');
|
||||
var generalID = $kickSelect.val();
|
||||
if(!generalID){
|
||||
alert('장수를 선택해주세요');
|
||||
return false;
|
||||
}
|
||||
var generalName = $kickSelect.data('name');
|
||||
if(!confirm('{0}를 추방하시겠습니까?'.format(generalName))){
|
||||
return false;
|
||||
}
|
||||
$.post({
|
||||
url:'j_myBossInfo.php',
|
||||
dataType:'json',
|
||||
data:{
|
||||
action:'추방',
|
||||
destGeneralID:generalID
|
||||
},
|
||||
}).then(function(data){
|
||||
if(!data){
|
||||
alert('추방하지 못했습니다.');
|
||||
return false;
|
||||
}
|
||||
if(!data.result){
|
||||
alert('추방하지 못했습니다. : '+data.reason);
|
||||
return false;
|
||||
}
|
||||
alert('{0}를 추방했습니다.'.format(generalName));
|
||||
location.reload();
|
||||
}, errUnknown);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.btn_appoint').click(function(){
|
||||
var $btn = $(this);
|
||||
var officerLevel = $btn.data('officer_level');
|
||||
var officerLevelText = $btn.data('officer_level_text');
|
||||
var cityID = 0;
|
||||
var cityName = '_';
|
||||
var $generalSelect = $('#genlist_{0} option:selected'.format(officerLevel));
|
||||
var $citySelect = $('#citylist_{0} option:selected'.format(officerLevel));
|
||||
|
||||
var generalID = $generalSelect.val();
|
||||
var generalName = $generalSelect.data('name');
|
||||
var generalOfficerLevel = $generalSelect.data('officer_level');
|
||||
|
||||
|
||||
if(officerLevel >= 5){
|
||||
if(generalID == 0){
|
||||
if(!confirm('{0}직을 비우시겠습니까?'.format(officerLevelText))){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(generalOfficerLevel >= 5){
|
||||
if(!confirm('이미 수뇌인 {0}을(를) {1}직에 임명하시겠습니까?'.format(generalName, officerLevelText))){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(!confirm('{0}을(를) {1}직에 임명하시겠습니까?'.format(generalName, officerLevelText))){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
cityID = $citySelect.val();
|
||||
if(!cityID){
|
||||
alert('도시를 선택해주세요');
|
||||
return false;
|
||||
}
|
||||
cityName = $citySelect.find('option:selected .name_field').text();
|
||||
|
||||
if(generalID == 0){
|
||||
if(!confirm('{0} {1}직을 비우시겠습니까?'.format(cityName, officerLevelText))){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(generalOfficerLevel >= 5){
|
||||
if(!confirm('수뇌인 {0}을(를) {1} {2}직에 임명하시겠습니까?'.format(generalName, cityName, officerLevelText))){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(!confirm('{0}을(를) {1} {2}직에 임명하시겠습니까?'.format(generalName, cityName, officerLevelText))){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$.post({
|
||||
url:'j_myBossInfo.php',
|
||||
dataType:'json',
|
||||
data:{
|
||||
action:'임명',
|
||||
destGeneralID:generalID,
|
||||
destCityID:cityID,
|
||||
officerLevel:officerLevel
|
||||
},
|
||||
}).then(function(data){
|
||||
if(!data){
|
||||
alert('임명하지 못했습니다.');
|
||||
return false;
|
||||
}
|
||||
if(!data.result){
|
||||
alert('임명하지 못했습니다. : '+data.reason);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(generalID){
|
||||
alert('{0}을(를) 임명했습니다.'.format(generalName));
|
||||
}
|
||||
else{
|
||||
alert('관직을 비웠습니다.');
|
||||
}
|
||||
|
||||
location.reload();
|
||||
}, errUnknown);
|
||||
|
||||
})
|
||||
function changePermission(isAmbassador, rawGeneralList) {
|
||||
console.log(isAmbassador);
|
||||
console.log(rawGeneralList);
|
||||
|
||||
var generalList = [];
|
||||
$.each(rawGeneralList, function(idx, value) {
|
||||
generalList.push(parseInt(value.id));
|
||||
})
|
||||
|
||||
$.post({
|
||||
url: 'j_general_set_permission.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
isAmbassador: isAmbassador,
|
||||
genlist: generalList
|
||||
},
|
||||
}).then(function(data) {
|
||||
if (!data) {
|
||||
alert('변경하지 못했습니다.');
|
||||
return false;
|
||||
}
|
||||
if (!data.result) {
|
||||
alert('변경하지 못했습니다. : ' + data.reason);
|
||||
return false;
|
||||
}
|
||||
alert('변경했습니다.');
|
||||
location.reload();
|
||||
}, errUnknown);
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$('#selectAmbassador').select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: "",
|
||||
allowClear: true,
|
||||
language: "ko",
|
||||
width: 300,
|
||||
maximumSelectionLength: 2,
|
||||
containerCss: {
|
||||
display: "inline-block !important;",
|
||||
color: 'white !important'
|
||||
},
|
||||
data: candidateAmbassadors,
|
||||
//containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
});
|
||||
|
||||
$('#selectAuditor').select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: "",
|
||||
allowClear: true,
|
||||
language: "ko",
|
||||
width: 300,
|
||||
maximumSelectionLength: 2,
|
||||
containerCss: {
|
||||
display: "inline-block !important;",
|
||||
color: 'white !important'
|
||||
},
|
||||
data: candidateAuditors,
|
||||
//containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
});
|
||||
|
||||
$('#changeAmbassador').click(function() {
|
||||
if (!confirm('외교권자를 변경할까요?')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
changePermission(true, $('#selectAmbassador').select2('data'));
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#changeAuditor').click(function() {
|
||||
if (!confirm('조언자를 변경할까요?')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
changePermission(false, $('#selectAuditor').select2('data'));
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#btn_kick').click(function() {
|
||||
var $kickSelect = $('#genlist_kick option:selected');
|
||||
var generalID = $kickSelect.val();
|
||||
if (!generalID) {
|
||||
alert('장수를 선택해주세요');
|
||||
return false;
|
||||
}
|
||||
var generalName = $kickSelect.data('name');
|
||||
if (!confirm('{0}를 추방하시겠습니까?'.format(generalName))) {
|
||||
return false;
|
||||
}
|
||||
$.post({
|
||||
url: 'j_myBossInfo.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
action: '추방',
|
||||
destGeneralID: generalID
|
||||
},
|
||||
}).then(function(data) {
|
||||
if (!data) {
|
||||
alert('추방하지 못했습니다.');
|
||||
return false;
|
||||
}
|
||||
if (!data.result) {
|
||||
alert('추방하지 못했습니다. : ' + data.reason);
|
||||
return false;
|
||||
}
|
||||
alert('{0}를 추방했습니다.'.format(generalName));
|
||||
location.reload();
|
||||
}, errUnknown);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.btn_appoint').click(function() {
|
||||
var $btn = $(this);
|
||||
var officerLevel = $btn.data('officer_level');
|
||||
var officerLevelText = $btn.data('officer_level_text');
|
||||
var cityID = 0;
|
||||
var cityName = '_';
|
||||
var $generalSelect = $('#genlist_{0} option:selected'.format(officerLevel));
|
||||
var $citySelect = $('#citylist_{0} option:selected'.format(officerLevel));
|
||||
|
||||
var generalID = parseInt($generalSelect.val());
|
||||
var generalName = $generalSelect.data('name');
|
||||
var generalOfficerLevel = $generalSelect.data('officer_level');
|
||||
|
||||
|
||||
if (officerLevel >= 5) {
|
||||
if (generalID == 0) {
|
||||
if (!confirm('{0}직을 비우시겠습니까?'.format(officerLevelText))) {
|
||||
return false;
|
||||
}
|
||||
} else if (generalOfficerLevel >= 5) {
|
||||
if (!confirm('이미 수뇌인 {0}을(를) {1}직에 임명하시겠습니까?'.format(generalName, officerLevelText))) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!confirm('{0}을(를) {1}직에 임명하시겠습니까?'.format(generalName, officerLevelText))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cityID = $citySelect.val();
|
||||
if (!cityID) {
|
||||
alert('도시를 선택해주세요');
|
||||
return false;
|
||||
}
|
||||
cityName = $citySelect.find('option:selected .name_field').text();
|
||||
|
||||
if (generalID == 0) {
|
||||
if (!confirm('{0} {1}직을 비우시겠습니까?'.format(cityName, officerLevelText))) {
|
||||
return false;
|
||||
}
|
||||
} else if (generalOfficerLevel >= 5) {
|
||||
if (!confirm('수뇌인 {0}을(를) {1} {2}직에 임명하시겠습니까?'.format(generalName, cityName, officerLevelText))) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!confirm('{0}을(를) {1} {2}직에 임명하시겠습니까?'.format(generalName, cityName, officerLevelText))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$.post({
|
||||
url: 'j_myBossInfo.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
action: '임명',
|
||||
destGeneralID: generalID,
|
||||
destCityID: cityID,
|
||||
officerLevel: officerLevel
|
||||
},
|
||||
}).then(function(data) {
|
||||
if (!data) {
|
||||
alert('임명하지 못했습니다.');
|
||||
return false;
|
||||
}
|
||||
if (!data.result) {
|
||||
alert('임명하지 못했습니다. : ' + data.reason);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (generalID) {
|
||||
alert('{0}을(를) 임명했습니다.'.format(generalName));
|
||||
} else {
|
||||
alert('관직을 비웠습니다.');
|
||||
}
|
||||
|
||||
location.reload();
|
||||
}, errUnknown);
|
||||
|
||||
})
|
||||
})
|
||||
+129
-103
@@ -3,8 +3,8 @@
|
||||
* @see https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
|
||||
* @param {string} string escape하고자 하는 문자열
|
||||
* @returns {string}
|
||||
*/
|
||||
var escapeHtml = (function (string) {
|
||||
*/
|
||||
var escapeHtml = (function(string) {
|
||||
var entityMap = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
@@ -32,58 +32,70 @@ function isInt(n) {
|
||||
return +n === n && !(n % 1);
|
||||
}
|
||||
|
||||
;(function(ns){
|
||||
;
|
||||
(function(ns) {
|
||||
//https://gist.github.com/demouth/3217440
|
||||
/**
|
||||
* mb_strwidth
|
||||
* @param String
|
||||
* @return int
|
||||
* @see http://php.net/manual/ja/function.mb-strwidth.php
|
||||
*/
|
||||
var mb_strwidth = function(str){
|
||||
var i=0,l=str.length,c='',length=0;
|
||||
for(;i<l;i++){
|
||||
c=str.charCodeAt(i);
|
||||
if(0x0000<=c&&c<=0x0019){
|
||||
length += 0;
|
||||
}else if(0x0020<=c&&c<=0x1FFF){
|
||||
length += 1;
|
||||
}else if(0x2000<=c&&c<=0xFF60){
|
||||
length += 2;
|
||||
}else if(0xFF61<=c&&c<=0xFF9F){
|
||||
length += 1;
|
||||
}else if(0xFFA0<=c){
|
||||
length += 2;
|
||||
}
|
||||
}
|
||||
return length;
|
||||
};
|
||||
|
||||
/**
|
||||
* mb_strimwidth
|
||||
* @param String
|
||||
* @param int
|
||||
* @param int
|
||||
* @param String
|
||||
* @return String
|
||||
* @see http://www.php.net/manual/ja/function.mb-strimwidth.php
|
||||
*/
|
||||
var mb_strimwidth = function(str,start,width,trimmarker){
|
||||
if(typeof trimmarker === 'undefined') trimmarker='';
|
||||
var trimmakerWidth = mb_strwidth(trimmarker),i=start,l=str.length,trimmedLength=0,trimmedStr='';
|
||||
for(;i<l;i++){
|
||||
var charCode=str.charCodeAt(i),c=str.charAt(i),charWidth=mb_strwidth(c),next=str.charAt(i+1),nextWidth=mb_strwidth(next);
|
||||
trimmedLength += charWidth;
|
||||
trimmedStr += c;
|
||||
if(trimmedLength+trimmakerWidth+nextWidth>width){
|
||||
trimmedStr += trimmarker;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return trimmedStr;
|
||||
};
|
||||
ns.mb_strwidth = mb_strwidth;
|
||||
ns.mb_strimwidth = mb_strimwidth;
|
||||
/**
|
||||
* mb_strwidth
|
||||
* @param String
|
||||
* @return int
|
||||
* @see http://php.net/manual/ja/function.mb-strwidth.php
|
||||
*/
|
||||
var mb_strwidth = function(str) {
|
||||
var i = 0,
|
||||
l = str.length,
|
||||
c = '',
|
||||
length = 0;
|
||||
for (; i < l; i++) {
|
||||
c = str.charCodeAt(i);
|
||||
if (0x0000 <= c && c <= 0x0019) {
|
||||
length += 0;
|
||||
} else if (0x0020 <= c && c <= 0x1FFF) {
|
||||
length += 1;
|
||||
} else if (0x2000 <= c && c <= 0xFF60) {
|
||||
length += 2;
|
||||
} else if (0xFF61 <= c && c <= 0xFF9F) {
|
||||
length += 1;
|
||||
} else if (0xFFA0 <= c) {
|
||||
length += 2;
|
||||
}
|
||||
}
|
||||
return length;
|
||||
};
|
||||
|
||||
/**
|
||||
* mb_strimwidth
|
||||
* @param String
|
||||
* @param int
|
||||
* @param int
|
||||
* @param String
|
||||
* @return String
|
||||
* @see http://www.php.net/manual/ja/function.mb-strimwidth.php
|
||||
*/
|
||||
var mb_strimwidth = function(str, start, width, trimmarker) {
|
||||
if (typeof trimmarker === 'undefined') trimmarker = '';
|
||||
var trimmakerWidth = mb_strwidth(trimmarker),
|
||||
i = start,
|
||||
l = str.length,
|
||||
trimmedLength = 0,
|
||||
trimmedStr = '';
|
||||
for (; i < l; i++) {
|
||||
var charCode = str.charCodeAt(i),
|
||||
c = str.charAt(i),
|
||||
charWidth = mb_strwidth(c),
|
||||
next = str.charAt(i + 1),
|
||||
nextWidth = mb_strwidth(next);
|
||||
trimmedLength += charWidth;
|
||||
trimmedStr += c;
|
||||
if (trimmedLength + trimmakerWidth + nextWidth > width) {
|
||||
trimmedStr += trimmarker;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return trimmedStr;
|
||||
};
|
||||
ns.mb_strwidth = mb_strwidth;
|
||||
ns.mb_strimwidth = mb_strimwidth;
|
||||
})(window);
|
||||
|
||||
/**
|
||||
@@ -93,7 +105,7 @@ function isInt(n) {
|
||||
*/
|
||||
function convertDictById(arr) {
|
||||
var result = {};
|
||||
arr.forEach(function (v, i) {
|
||||
arr.forEach(function(v, i) {
|
||||
result[v.id] = v;
|
||||
});
|
||||
return result;
|
||||
@@ -106,7 +118,7 @@ function convertDictById(arr) {
|
||||
*/
|
||||
function convertSet(arr) {
|
||||
var result = {};
|
||||
arr.forEach(function (v) {
|
||||
arr.forEach(function(v) {
|
||||
result[v] = true;
|
||||
});
|
||||
return result;
|
||||
@@ -115,10 +127,10 @@ function convertSet(arr) {
|
||||
|
||||
/**
|
||||
* {0}, {1}, {2}형태로 포맷해주는 함수
|
||||
*/
|
||||
*/
|
||||
String.prototype.format = function() {
|
||||
var args = arguments;
|
||||
return this.replace(/{(\d+)}/g, function(match, number) {
|
||||
return this.replace(/{(\d+)}/g, function(match, number) {
|
||||
return (typeof args[number] != 'undefined') ? args[number] : match;
|
||||
});
|
||||
};
|
||||
@@ -134,12 +146,11 @@ function hexToRgb(hex) {
|
||||
}
|
||||
|
||||
|
||||
function isBrightColor(color){
|
||||
function isBrightColor(color) {
|
||||
color = hexToRgb(color);
|
||||
if ((color.r*0.299 + color.g*0.587 + color.b*0.114) > 140){
|
||||
if ((color.r * 0.299 + color.g * 0.587 + color.b * 0.114) > 140) {
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -177,7 +188,7 @@ function numberWithCommas(x) {
|
||||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
|
||||
function linkifyStrWithOpt(text){
|
||||
function linkifyStrWithOpt(text) {
|
||||
return linkifyStr(text, {});
|
||||
}
|
||||
|
||||
@@ -188,14 +199,14 @@ function linkifyStrWithOpt(text){
|
||||
* @param {object} options
|
||||
* @returns {string}
|
||||
*/
|
||||
var TemplateEngine = function (html, options) {
|
||||
var TemplateEngine = function(html, options) {
|
||||
var re = /<%(.+?)%>/g,
|
||||
reExp = /(^( )?(var|if|for|else|switch|case|break|{|}|;))(.*)?/g,
|
||||
code = 'with(obj) { var r=[];\n',
|
||||
cursor = 0,
|
||||
result,
|
||||
match;
|
||||
var add = function (line, js) {
|
||||
var add = function(line, js) {
|
||||
js ? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') :
|
||||
(code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');
|
||||
return add;
|
||||
@@ -208,82 +219,97 @@ var TemplateEngine = function (html, options) {
|
||||
}
|
||||
add(html.substr(cursor, html.length - cursor));
|
||||
code = (code + 'return r.join(""); }').replace(/[\r\t\n]/g, ' ');
|
||||
try { result = new Function('obj', code).apply(options, [options]); }
|
||||
catch (err) { console.error("'" + err.message + "'", " in \n\nCode:\n", code, "\n"); }
|
||||
try { result = new Function('obj', code).apply(options, [options]); } catch (err) { console.error("'" + err.message + "'", " in \n\nCode:\n", code, "\n"); }
|
||||
return result;
|
||||
}
|
||||
|
||||
function getIconPath(imgsvr, picture){
|
||||
function getIconPath(imgsvr, picture) {
|
||||
// ../d_shared/common_path.js 필요
|
||||
if(!imgsvr){
|
||||
return pathConfig.sharedIcon+'/'+picture;
|
||||
}
|
||||
else{
|
||||
return pathConfig.root+'/d_pic/'+picture;
|
||||
if (!imgsvr) {
|
||||
return pathConfig.sharedIcon + '/' + picture;
|
||||
} else {
|
||||
return pathConfig.root + '/d_pic/' + picture;
|
||||
}
|
||||
}
|
||||
|
||||
function activeFlip($obj){
|
||||
function activeFlip($obj) {
|
||||
var $result;
|
||||
if($obj === undefined){
|
||||
if ($obj === undefined) {
|
||||
$result = $('img[data-flip]');
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$result = $obj.find('img[data-flip]');
|
||||
}
|
||||
|
||||
$result.each(function(){
|
||||
$result.each(function() {
|
||||
activeFlipItem($(this));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function activeFlipItem($img){
|
||||
function combineObject(item, columnList) {
|
||||
var newItem = {};
|
||||
for (var columnIdx in columnList) {
|
||||
var columnName = columnList[columnIdx];
|
||||
newItem[columnName] = item[columnIdx];
|
||||
}
|
||||
return newItem;
|
||||
}
|
||||
|
||||
function combineArray(array, columnList) {
|
||||
var result = [];
|
||||
for (var key in array) {
|
||||
var item = array[key];
|
||||
result[key] = combineObject(item, columnList);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function activeFlipItem($img) {
|
||||
var imageList = [];
|
||||
imageList.push($img.attr('src'));
|
||||
$.each($img.data('flip').split(','), function(idx, value){
|
||||
$.each($img.data('flip').split(','), function(idx, value) {
|
||||
var value = $.trim(value);
|
||||
if(!value){
|
||||
if (!value) {
|
||||
return true;
|
||||
}
|
||||
imageList.push(value);
|
||||
});
|
||||
if(imageList.length <= 1){
|
||||
if (imageList.length <= 1) {
|
||||
return;
|
||||
}
|
||||
$img.data('computed_flip_array', imageList);
|
||||
$img.data('computed_flip_idx', 0);
|
||||
|
||||
$img.click(function(){
|
||||
$img.click(function() {
|
||||
var arr = $img.data('computed_flip_array');
|
||||
var idx = $img.data('computed_flip_idx');
|
||||
idx = (idx + 1)%(arr.length);
|
||||
idx = (idx + 1) % (arr.length);
|
||||
$img.attr('src', arr[idx]);
|
||||
$img.data('computed_flip_idx', idx);
|
||||
});
|
||||
$img.css('cursor','pointer');
|
||||
$img.css('cursor', 'pointer');
|
||||
}
|
||||
|
||||
jQuery(function($){
|
||||
$('.obj_tooltip').mouseover(function(){
|
||||
jQuery(function($) {
|
||||
$('.obj_tooltip').mouseover(function() {
|
||||
var $objTooltip = $(this);
|
||||
if($objTooltip.data('setObjTooltip')){
|
||||
if ($objTooltip.data('setObjTooltip')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var tooltipClassText = $objTooltip.data('tooltip-class');
|
||||
if(!tooltipClassText){
|
||||
if (!tooltipClassText) {
|
||||
tooltipClassText = '';
|
||||
}
|
||||
var template = '<div class="tooltip {0}" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>'
|
||||
.format(tooltipClassText);
|
||||
|
||||
$objTooltip.tooltip({
|
||||
title:function(){
|
||||
title: function() {
|
||||
return $.trim($(this).find('.tooltiptext').html());
|
||||
},
|
||||
template:template,
|
||||
html:true
|
||||
template: template,
|
||||
html: true
|
||||
}).tooltip('show');
|
||||
|
||||
$objTooltip.data('setObjTooltip', true);
|
||||
@@ -297,21 +323,21 @@ jQuery(function($){
|
||||
activeFlip();
|
||||
|
||||
var customCSS = localStorage.getItem('sam_customCSS');
|
||||
if(customCSS){
|
||||
if (customCSS) {
|
||||
var $style = $('<style type="text/css"></style>');
|
||||
$style.text(customCSS);
|
||||
$style.text(customCSS);
|
||||
$style.appendTo($('head'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
function errUnknown(){
|
||||
function errUnknown() {
|
||||
alert('작업을 실패했습니다.');
|
||||
}
|
||||
|
||||
function errUnknownToast(){
|
||||
function errUnknownToast() {
|
||||
$.toast({
|
||||
title: '에러!',
|
||||
content: '작업을 실패했습니다.',
|
||||
@@ -320,8 +346,8 @@ function errUnknownToast(){
|
||||
});
|
||||
}
|
||||
|
||||
function quickReject(errMsg){
|
||||
if(errMsg === undefined){
|
||||
function quickReject(errMsg) {
|
||||
if (errMsg === undefined) {
|
||||
errMsg = '작업을 실패했습니다.';
|
||||
}
|
||||
var deferred = $.Deferred();
|
||||
@@ -329,8 +355,8 @@ function quickReject(errMsg){
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
function nl2br(text){
|
||||
return text.replace(/\n/g,"<br>");
|
||||
function nl2br(text) {
|
||||
return text.replace(/\n/g, "<br>");
|
||||
}
|
||||
/*
|
||||
function br2nl (text) {
|
||||
@@ -338,11 +364,11 @@ function br2nl (text) {
|
||||
}
|
||||
*/
|
||||
|
||||
function getNpcColor(npcType){
|
||||
if(npcType >= 2){
|
||||
function getNpcColor(npcType) {
|
||||
if (npcType >= 2) {
|
||||
return 'cyan';
|
||||
}
|
||||
if(npcType == 1){
|
||||
if (npcType == 1) {
|
||||
return 'skyblue';
|
||||
}
|
||||
return null;
|
||||
|
||||
+685
-653
@@ -1,654 +1,686 @@
|
||||
|
||||
function is_touch_device() {
|
||||
var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
|
||||
var mq = function(query) {
|
||||
return window.matchMedia(query).matches;
|
||||
}
|
||||
|
||||
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
|
||||
// https://git.io/vznFH
|
||||
var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
|
||||
return mq(query);
|
||||
}
|
||||
|
||||
function reloadWorldMap(option){
|
||||
var $world_map = $('.world_map');
|
||||
|
||||
if($world_map.length == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
var defaultOption = {
|
||||
isDetailMap:true, //복잡 지도, 단순 지도
|
||||
clickableAll:false, //어떤 경우든 클릭을 가능하게 함. 해당 동작의 동작 가능성 여부와는 별도.
|
||||
selectCallback:null, //callback을 지정시 clickable과 관계 없이 해당 함수를 실행.
|
||||
hrefTemplate:'#', //도시가 클릭가능할 경우 지정할 href값. {0}은 도시 id로 변환됨
|
||||
useCachedMap:false, //맵 캐시를 사용
|
||||
|
||||
//아래부터는 post query에 들어갈 녀석
|
||||
year:null, //year값, 연감등에 사용
|
||||
month:null, //month값, 연감등에 사용
|
||||
aux:null, //기타 넣고 싶은 값을 입력
|
||||
neutralView:false, //clickable, 소속 국가, 첩보 여부 등을 반환여부를 설정
|
||||
showMe:true, //반환 값에 본인이 위치한 도시 값을 반환하도록 설정. neutralView와 별개
|
||||
targetJson:'j_map.php',
|
||||
|
||||
//기타 보조 값
|
||||
startYear:null,
|
||||
};
|
||||
|
||||
option = $.extend(defaultOption, option);
|
||||
|
||||
var useCachedMap = option.useCachedMap;
|
||||
var isDetailMap = option.isDetailMap;
|
||||
var clickableAll = option.clickableAll;
|
||||
var selectCallback = option.selectCallback;
|
||||
var hrefTemplate = option.hrefTemplate;
|
||||
|
||||
var cityPosition = getCityPosition();
|
||||
|
||||
var storedOldMapKey = 'sam.{0}.map'.format(serverNick);
|
||||
var storedStartYear = 'sam.{0}.startYear'.format(serverNick);
|
||||
//OBJ : startYear, year, month, cityList, nationList, spyList, shownByGeneralList, myCity
|
||||
|
||||
function checkReturnObject(obj){
|
||||
if(!obj.result){
|
||||
var obj = $.Deferred();
|
||||
obj.reject('fail');
|
||||
return obj.promise();
|
||||
}
|
||||
|
||||
if(!$.isNumeric(obj.startYear)
|
||||
||!$.isNumeric(obj.year)
|
||||
||!$.isNumeric(obj.month)
|
||||
){
|
||||
var obj = $.Deferred();
|
||||
obj.reject('fail');
|
||||
return obj.promise();
|
||||
}
|
||||
|
||||
if(useCachedMap){
|
||||
localStorage.setItem(storedOldMapKey, JSON.stringify([serverID, obj]));
|
||||
localStorage.setItem(storedStartYear, JSON.stringify(obj.startYear));
|
||||
}
|
||||
|
||||
$world_map.removeClass('draw_required');
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function setMapBackground(obj){
|
||||
var startYear = obj.startYear;
|
||||
var year = obj.year;
|
||||
var month = obj.month;
|
||||
|
||||
if(isDetailMap){
|
||||
$world_map.addClass('map_detail').removeClass('map_basic');
|
||||
}
|
||||
else{
|
||||
$world_map.addClass('map_basic').removeClass('map_detail');
|
||||
}
|
||||
|
||||
var $map_title = $('.map_title_text');
|
||||
if(year < startYear + 1){
|
||||
$map_title.css('color', 'magenta');
|
||||
}
|
||||
else if(year < startYear + 2){
|
||||
$map_title.css('color', 'orange');
|
||||
}
|
||||
else if(year < startYear + 3){
|
||||
$map_title.css('color', 'yellow');
|
||||
}
|
||||
|
||||
$map_title_tooltip = $('.map_title .tooltiptext');
|
||||
$map_title_tooltip.empty();
|
||||
|
||||
var tooltipTexts = [];
|
||||
if(year < startYear + 3){
|
||||
var startYearText = [];
|
||||
var remainYear = startYear + 3 - year;
|
||||
var remainMonth = 12 - month + 1;
|
||||
if(remainMonth > 0){
|
||||
remainYear -= 1;
|
||||
}
|
||||
if(remainYear){
|
||||
startYearText.push('{0}년'.format(remainYear));
|
||||
}
|
||||
if(remainMonth){
|
||||
startYearText.push('{0}개월'.format(remainMonth));
|
||||
}
|
||||
|
||||
tooltipTexts.push('초반제한 기간 : {0} ({1}년)'.format(startYearText.join(' '), startYear + 3));
|
||||
}
|
||||
|
||||
var currentTechLimit = Math.floor(Math.max(0, year - startYear) / 5) + 1;
|
||||
var nextTechLimitYear = currentTechLimit * 5 + startYear;
|
||||
|
||||
tooltipTexts.push('기술등급 제한 : {0}등급 ({1}년 해제)'.format(currentTechLimit, nextTechLimitYear, currentTechLimit+1));
|
||||
$map_title_tooltip.html(tooltipTexts.join('<br>'));
|
||||
|
||||
$world_map.removeClass('map_string map_summer map_fall map_winter');
|
||||
if(month <= 3){
|
||||
$world_map.addClass('map_spring');
|
||||
}
|
||||
else if(month <= 6){
|
||||
$world_map.addClass('map_summer');
|
||||
}
|
||||
else if(month <= 9){
|
||||
$world_map.addClass('map_fall');
|
||||
}
|
||||
else{
|
||||
$world_map.addClass('map_winter');
|
||||
}
|
||||
|
||||
$map_title.html('{0}年 {1}月'.format(year, month));
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function convertCityObjs(obj){
|
||||
//원본 Obj는 굉장히 간소하게 온다, Object 형태로 변환해서 사용한다.
|
||||
|
||||
function toCityObj(arr){
|
||||
return {
|
||||
id:arr[0],
|
||||
level:arr[1],
|
||||
state:arr[2],
|
||||
nationId:(arr[3]>0)?arr[3]:null,
|
||||
region:arr[4],
|
||||
supply:(arr[5]!=0)
|
||||
};
|
||||
}
|
||||
|
||||
function toNationObj(arr){
|
||||
return {
|
||||
id:arr[0],
|
||||
name:arr[1],
|
||||
color:arr[2],
|
||||
capital:arr[3]
|
||||
};
|
||||
}
|
||||
|
||||
var cityList = obj.cityList.map(toCityObj);
|
||||
var nationList = obj.nationList.map(toNationObj);
|
||||
nationList = convertDictById(nationList); //array of object -> dict
|
||||
|
||||
var spyList = obj.spyList;
|
||||
var shownByGeneralList = convertSet(obj.shownByGeneralList);//Array -> Set
|
||||
|
||||
var myCity = obj.myCity;
|
||||
var myNation = obj.myNation;
|
||||
|
||||
|
||||
function mergePositionInfo(city){
|
||||
var id = city.id;
|
||||
if(!(id in cityPosition)){
|
||||
return city;
|
||||
}
|
||||
var xy_val = cityPosition[id];
|
||||
city.name = xy_val[0];
|
||||
city.x = xy_val[1];
|
||||
city.y = xy_val[2];
|
||||
return city;
|
||||
}
|
||||
|
||||
function mergeNationInfo(city){
|
||||
//nationId 값으로 isCapital, color, nation을 통합
|
||||
|
||||
var nationId = city.nationId;
|
||||
if(nationId === null || !(nationId in nationList)){
|
||||
city.nationId = null;
|
||||
city.nation = null;
|
||||
city.color = null;
|
||||
city.isCapital = false;
|
||||
return city;
|
||||
}
|
||||
|
||||
var nationObj = nationList[nationId];
|
||||
city.nation = nationObj.name;
|
||||
city.color = nationObj.color;
|
||||
city.isCapital = (nationObj.capital == city.id);
|
||||
|
||||
return city;
|
||||
}
|
||||
|
||||
function mergeClickable(city){
|
||||
//clickable = (remainSpy << 3) | (ourCity << 2) | (shownByGeneral << 1) | clickableAll
|
||||
var id = city.id;
|
||||
var nationId = city.nationId;
|
||||
var clickable = 0;
|
||||
if(id in spyList){
|
||||
clickable |= spyList[id] << 3;
|
||||
}
|
||||
if(myNation !== null && nationId == myNation){
|
||||
clickable |= 4;
|
||||
}
|
||||
if(shownByGeneralList.hasOwnProperty(id)){
|
||||
clickable |= 2;
|
||||
}
|
||||
if(myCity !== null && id == myCity){
|
||||
clickable |= 2;
|
||||
}
|
||||
if(clickableAll){
|
||||
clickable |= 1;
|
||||
}
|
||||
|
||||
|
||||
city.clickable = clickable;
|
||||
return city;
|
||||
}
|
||||
|
||||
cityList = cityList
|
||||
.map(mergePositionInfo)
|
||||
.map(mergeNationInfo)
|
||||
.map(mergeClickable)
|
||||
.map(formatCityInfo);
|
||||
|
||||
return {
|
||||
'cityList' : cityList,
|
||||
'myCity' : myCity
|
||||
};
|
||||
}
|
||||
|
||||
function drawDetailWorldMap(obj){
|
||||
|
||||
var $map_body = $('.world_map .map_body');
|
||||
|
||||
var cityList = obj.cityList;
|
||||
var myCity = obj.myCity;
|
||||
|
||||
cityList.forEach(function(city){
|
||||
var id = city.id;
|
||||
$('.city_base_{0}'.format(id)).detach();
|
||||
//이전 도시는 지운다.
|
||||
|
||||
var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id));
|
||||
$cityObj.addClass('city_level_{0}'.format(city.level));
|
||||
$cityObj.data('obj', city).css({'left':city.x-20,'top':city.y-15});
|
||||
|
||||
if('color' in city && city.color !== null){
|
||||
var $bgObj = $('<div class="city_bg"></div>');
|
||||
$cityObj.append($bgObj);
|
||||
$bgObj.css({'background-image':'url({0}/b{1}.png)'.format(pathConfig.gameImage, convColorValue(city.color))});
|
||||
}
|
||||
|
||||
var $linkObj = $('<a class="city_link"></a>');
|
||||
$linkObj.data({'text':city.text,'nation':city.nation,'id':city.id});
|
||||
$cityObj.append($linkObj);
|
||||
|
||||
var $imgObj = $('<div class="city_img"><img src="{0}/cast_{1}.gif"><div class="city_filler"></div></div>'.format(pathConfig.gameImage, city.level));
|
||||
$linkObj.append($imgObj);
|
||||
|
||||
|
||||
|
||||
if(city.state > 0){
|
||||
var $stateObj = $('<div class="city_state"><img src="{0}/event{1}.gif"></div>'.format(pathConfig.gameImage, city.state));
|
||||
$linkObj.append($stateObj);
|
||||
}
|
||||
|
||||
if(city.nationId && city.nationId > 0){
|
||||
var flagType = city.supply?'f':'d';
|
||||
var $flagObj = $('<div class="city_flag"><img src="{0}/{1}{2}.gif"></div>'.format(pathConfig.gameImage, flagType, convColorValue(city.color)));
|
||||
if(city.isCapital){
|
||||
var $capitalObj = $('<div class="city_capital"><img src="{0}/event51.gif"></div>'.format(pathConfig.gameImage));
|
||||
$flagObj.append($capitalObj);
|
||||
}
|
||||
$imgObj.append($flagObj);
|
||||
}
|
||||
|
||||
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
|
||||
$imgObj.append($nameObj);
|
||||
|
||||
|
||||
$map_body.append($cityObj);
|
||||
|
||||
|
||||
});
|
||||
|
||||
$world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city');
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function drawBasicWorldMap(obj){
|
||||
|
||||
var $map_body = $('.world_map .map_body');
|
||||
|
||||
var cityList = obj.cityList;
|
||||
var myCity = obj.myCity;
|
||||
|
||||
cityList.forEach(function(city){
|
||||
var id = city.id;
|
||||
$('.city_base_{0}'.format(id)).detach();
|
||||
//이전 도시는 지운다.
|
||||
|
||||
var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id));
|
||||
$cityObj.addClass('city_level_{0}'.format(city.level));
|
||||
$cityObj.data('obj', city).css({'left':city.x-20,'top':city.y-15});
|
||||
|
||||
var $linkObj = $('<a class="city_link"></a>');
|
||||
$linkObj.data({'text':city.text,'nation':city.nation,'id':city.id});
|
||||
$cityObj.append($linkObj);
|
||||
|
||||
var $imgObj = $('<div class="city_img"><div class="city_filler"></div></div>');
|
||||
if('color' in city && city.color !== null){
|
||||
$imgObj.css({'background-color':city.color});
|
||||
}
|
||||
$linkObj.append($imgObj);
|
||||
|
||||
if(city.state > 0){
|
||||
var state_text = 'wrong';
|
||||
if(city.state < 10){
|
||||
state_text = 'good';
|
||||
}
|
||||
else if(city.state < 40){
|
||||
state_text = 'bad';
|
||||
}
|
||||
else if(city.state < 50){
|
||||
state_text = 'war';
|
||||
}
|
||||
|
||||
var $stateObj = $('<div class="city_state city_state_{0}"></div>'.format(state_text));
|
||||
$imgObj.append($stateObj);
|
||||
}
|
||||
|
||||
//단순 표기에서는 깃발 여부가 없음
|
||||
if(city.isCapital){
|
||||
var $capitalObj = $('<div class="city_capital"></div>');
|
||||
$imgObj.append($capitalObj);
|
||||
}
|
||||
|
||||
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
|
||||
$imgObj.append($nameObj);
|
||||
|
||||
$map_body.append($cityObj);
|
||||
});
|
||||
|
||||
$world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city');
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function setMouseWork(obj){
|
||||
var $tooltip = $('.world_map .city_tooltip');
|
||||
var $tooltip_city = $tooltip.find('.city_name');
|
||||
var $tooltip_nation = $tooltip.find('.nation_name');
|
||||
|
||||
var $objs = $('.world_map .city_link');
|
||||
|
||||
var $map_body = $('.world_map .map_body');
|
||||
|
||||
//터치스크린 탭
|
||||
|
||||
if(!option.neutralView && is_touch_device()){
|
||||
$objs.on('touchstart', function(e){
|
||||
if(window.sam_toggleSingleTap){
|
||||
return true;
|
||||
}
|
||||
var $this = $(this);
|
||||
|
||||
var touchMode = $this.data('touchMode');
|
||||
if($tooltip_city.data('target') != $this.data('id')){
|
||||
$this.data('touchMode', 1);
|
||||
}
|
||||
else if(touchMode === undefined){
|
||||
$this.data('touchMode', 1);
|
||||
}
|
||||
else{
|
||||
$this.data('touchMode', touchMode + 1);
|
||||
}
|
||||
$map_body.data('touchMode', 1);
|
||||
|
||||
$tooltip_city.data('target', $this.data('id'));
|
||||
|
||||
|
||||
});
|
||||
|
||||
$objs.on('touchend', function(e){
|
||||
if(window.sam_toggleSingleTap){
|
||||
return true;
|
||||
}
|
||||
var $this = $(this);
|
||||
var position = $this.parent().position();
|
||||
$tooltip_city.html($this.data('text'));
|
||||
|
||||
var nation_text = $this.data('nation');
|
||||
if(nation_text){
|
||||
$tooltip_nation.html(nation_text).show();
|
||||
}
|
||||
else{
|
||||
$tooltip_nation.html('').hide();
|
||||
}
|
||||
|
||||
$tooltip.css({'top': position.top + 25, 'left': position.left + 35}).show();
|
||||
|
||||
var touchMode = $this.data('touchMode');
|
||||
if(touchMode <= 1){
|
||||
return false;
|
||||
}
|
||||
|
||||
//xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다.
|
||||
$this.data('touchMode', 0);
|
||||
});
|
||||
|
||||
$map_body.on('touchend',function(e){
|
||||
if(window.sam_toggleSingleTap){
|
||||
return true;
|
||||
}
|
||||
//위의 touchend bind에 해당하지 않는 경우 -> 빈 지도 터치
|
||||
$tooltip.hide();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//Mouse over 모드 작동
|
||||
|
||||
$map_body.on('mousemove', function(e){
|
||||
if($(this).data('touchMode')){
|
||||
return true;
|
||||
}
|
||||
|
||||
var parentOffset = $map_body.offset();
|
||||
var relX = e.pageX - parentOffset.left;
|
||||
var relY = e.pageY - parentOffset.top;
|
||||
|
||||
$tooltip.css({'top': relY + 10, 'left': relX + 10});
|
||||
});
|
||||
|
||||
$objs.on('mouseenter', function(e){
|
||||
if($map_body.data('touchMode')){
|
||||
return true;
|
||||
}
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
$tooltip_city.data('target', $this.data('id'));
|
||||
$tooltip_city.html($this.data('text'));
|
||||
var nation_text = $this.data('nation');
|
||||
if(nation_text){
|
||||
$tooltip_nation.html(nation_text).show();
|
||||
}
|
||||
else{
|
||||
$tooltip_nation.html('').hide();
|
||||
}
|
||||
|
||||
$tooltip.show();
|
||||
});
|
||||
|
||||
$objs.on('mouseleave', function(event){
|
||||
$tooltip.hide();
|
||||
});
|
||||
|
||||
$objs.on('click', function(e){
|
||||
//xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다.
|
||||
var touchMode = $(this).data('touchMode');
|
||||
if(touchMode === undefined){
|
||||
return;
|
||||
}
|
||||
|
||||
if(touchMode === 1){
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function setCityClickable(obj){
|
||||
|
||||
obj.cityList.forEach(function(city){
|
||||
var $cityLink = $world_map.find('.city_base_{0} .city_link'.format(city.id));
|
||||
|
||||
if('clickable' in city && city.clickable > 0){
|
||||
$cityLink.attr('href',hrefTemplate.format(city.id));
|
||||
}
|
||||
|
||||
if(selectCallback){
|
||||
$cityLink.click(function(){
|
||||
return selectCallback(city);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function saveCityInfo(obj){
|
||||
$world_map.data('cityInfo', obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
var $hideCityNameBtn = $world_map.find('.map_toggle_cityname');
|
||||
if(localStorage.getItem('sam.hideMapCityName') == 'yes'){
|
||||
$world_map.addClass('hide_cityname');
|
||||
$hideCityNameBtn.addClass('active').attr('aria-pressed', 'true');
|
||||
}
|
||||
|
||||
$hideCityNameBtn.click(function(){
|
||||
//이전 상태 확인
|
||||
var state = !$hideCityNameBtn.hasClass('active');
|
||||
if(state){
|
||||
$world_map.addClass('hide_cityname');
|
||||
localStorage.setItem('sam.hideMapCityName', 'yes');
|
||||
}
|
||||
else{
|
||||
$world_map.removeClass('hide_cityname');
|
||||
localStorage.setItem('sam.hideMapCityName', 'no');
|
||||
}
|
||||
});
|
||||
|
||||
var $toggleSingleTapBtn = $world_map.find('.map_toggle_single_tap');
|
||||
if(localStorage.getItem('sam.toggleSingleTap') == 'yes'){
|
||||
window.sam_toggleSingleTap = true;
|
||||
$toggleSingleTapBtn.addClass('active').attr('aria-pressed', 'true');
|
||||
}
|
||||
else{
|
||||
window.sam_toggleSingleTap = false;
|
||||
}
|
||||
|
||||
var $map_body = $('.world_map .map_body');
|
||||
|
||||
$toggleSingleTapBtn.click(function(){
|
||||
//이전 상태 확인
|
||||
var state = !$toggleSingleTapBtn.hasClass('active');
|
||||
if(state){
|
||||
$map_body.removeData('touchMode');
|
||||
localStorage.setItem('sam.toggleSingleTap', 'yes');
|
||||
window.sam_toggleSingleTap = true;
|
||||
}
|
||||
else{
|
||||
localStorage.setItem('sam.toggleSingleTap', 'no');
|
||||
window.sam_toggleSingleTap = false;
|
||||
}
|
||||
});
|
||||
|
||||
if(isDetailMap){
|
||||
$world_map.addClass('map_detail');
|
||||
}
|
||||
else{
|
||||
$world_map.removeClass('map_datail');
|
||||
}
|
||||
|
||||
//deferred mode of jQuery. != promise-then.
|
||||
var deferred = $.ajax({
|
||||
url: option.targetJson,
|
||||
type: 'post',
|
||||
dataType:'json',
|
||||
data: {
|
||||
data: JSON.stringify({
|
||||
neutralView:option.neutralView,
|
||||
year:option.year,
|
||||
month:option.month,
|
||||
showMe:option.showMe,
|
||||
aux:option.aux
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
deferred
|
||||
.then(checkReturnObject)
|
||||
.then(setMapBackground)
|
||||
.then(convertCityObjs)
|
||||
.then(isDetailMap?drawDetailWorldMap:drawBasicWorldMap)
|
||||
.then(setMouseWork)
|
||||
.then(setCityClickable)
|
||||
.then(saveCityInfo);
|
||||
|
||||
if($world_map.hasClass('draw_required')){
|
||||
if(useCachedMap){
|
||||
//일단 불러옴
|
||||
do{
|
||||
var storedMap = localStorage.getItem(storedOldMapKey);
|
||||
if(!storedMap){
|
||||
break;
|
||||
}
|
||||
storedMap = JSON.parse(storedMap);
|
||||
var storedServerID = storedMap[0];
|
||||
if(storedServerID != serverID){
|
||||
break;
|
||||
}
|
||||
|
||||
storedMap = storedMap[1];
|
||||
storedMap = setMapBackground(storedMap);
|
||||
storedMap = convertCityObjs(storedMap);
|
||||
if(isDetailMap){
|
||||
storedMap = drawDetailWorldMap(storedMap);
|
||||
}
|
||||
else{
|
||||
storedMap = drawBasicWorldMap(storedMap);
|
||||
}
|
||||
storedMap = setMouseWork(storedMap);
|
||||
storedMap = setCityClickable(storedMap);
|
||||
storedMap = saveCityInfo(storedMap);
|
||||
}while(false);
|
||||
}
|
||||
else if(option.year && option.month){
|
||||
var startYear = localStorage.getItem(storedStartYear);
|
||||
if(startYear){
|
||||
startYear = JSON.parse(startYear);
|
||||
}
|
||||
else{
|
||||
startYear = option.year;
|
||||
}
|
||||
var tmp = {
|
||||
year : option.year,
|
||||
month : option.month,
|
||||
startYear : startYear
|
||||
};
|
||||
setMapBackground(tmp);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
$(function(){
|
||||
if(is_touch_device()){
|
||||
$('.map_body .map_toggle_single_tap').show();
|
||||
}
|
||||
function is_touch_device() {
|
||||
var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
|
||||
var mq = function(query) {
|
||||
return window.matchMedia(query).matches;
|
||||
}
|
||||
|
||||
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
|
||||
// https://git.io/vznFH
|
||||
var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
|
||||
return mq(query);
|
||||
}
|
||||
|
||||
function reloadWorldMap(option, drawTarget) {
|
||||
if (drawTarget === undefined || drawTarget === null) {
|
||||
drawTarget = '.world_map'
|
||||
}
|
||||
var $world_map = $(drawTarget);
|
||||
|
||||
if ($world_map.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var defaultOption = {
|
||||
isDetailMap: true, //복잡 지도, 단순 지도
|
||||
clickableAll: false, //어떤 경우든 클릭을 가능하게 함. 해당 동작의 동작 가능성 여부와는 별도.
|
||||
selectCallback: null, //callback을 지정시 clickable과 관계 없이 해당 함수를 실행.
|
||||
hrefTemplate: '#', //도시가 클릭가능할 경우 지정할 href값. {0}은 도시 id로 변환됨
|
||||
useCachedMap: false, //맵 캐시를 사용
|
||||
|
||||
//아래부터는 post query에 들어갈 녀석
|
||||
year: null, //year값, 연감등에 사용
|
||||
month: null, //month값, 연감등에 사용
|
||||
aux: null, //기타 넣고 싶은 값을 입력
|
||||
neutralView: false, //clickable, 소속 국가, 첩보 여부 등을 반환여부를 설정
|
||||
showMe: true, //반환 값에 본인이 위치한 도시 값을 반환하도록 설정. neutralView와 별개
|
||||
|
||||
targetJson: 'j_map.php',
|
||||
reqType: 'post',
|
||||
dynamicMapTheme: false,
|
||||
callback: null,
|
||||
|
||||
//기타 보조 값
|
||||
startYear: null,
|
||||
};
|
||||
|
||||
option = $.extend(defaultOption, option);
|
||||
|
||||
var useCachedMap = option.useCachedMap;
|
||||
var isDetailMap = option.isDetailMap;
|
||||
var clickableAll = option.clickableAll;
|
||||
var selectCallback = option.selectCallback;
|
||||
var hrefTemplate = option.hrefTemplate;
|
||||
|
||||
var cityPosition = getCityPosition();
|
||||
|
||||
var storedOldMapKey = 'sam.{0}.map'.format(serverNick);
|
||||
var storedStartYear = 'sam.{0}.startYear'.format(serverNick);
|
||||
//OBJ : startYear, year, month, cityList, nationList, spyList, shownByGeneralList, myCity
|
||||
|
||||
function checkReturnObject(obj) {
|
||||
if (!obj.result) {
|
||||
var obj = $.Deferred();
|
||||
obj.reject('fail');
|
||||
return obj.promise();
|
||||
}
|
||||
|
||||
if (!$.isNumeric(obj.startYear) ||
|
||||
!$.isNumeric(obj.year) ||
|
||||
!$.isNumeric(obj.month)
|
||||
) {
|
||||
var obj = $.Deferred();
|
||||
obj.reject('fail');
|
||||
return obj.promise();
|
||||
}
|
||||
|
||||
if (useCachedMap) {
|
||||
localStorage.setItem(storedOldMapKey, JSON.stringify([serverID, obj]));
|
||||
localStorage.setItem(storedStartYear, JSON.stringify(obj.startYear));
|
||||
}
|
||||
|
||||
$world_map.removeClass('draw_required');
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function setMapBackground(obj) {
|
||||
function setTheme() {
|
||||
var oldTheme = $world_map.data('currentTheme');
|
||||
var newTheme = obj.theme;
|
||||
if (oldTheme === newTheme) {
|
||||
return;
|
||||
}
|
||||
if (oldTheme) {
|
||||
$world_map.removeClass('map_theme_' + oldTheme);
|
||||
}
|
||||
$world_map.addClass('map_theme_' + newTheme);
|
||||
$world_map.data('currentTheme', newTheme);
|
||||
}
|
||||
if (option.dynamicMapTheme) {
|
||||
setTheme();
|
||||
}
|
||||
var startYear = obj.startYear;
|
||||
var year = obj.year;
|
||||
var month = obj.month;
|
||||
|
||||
if (isDetailMap) {
|
||||
$world_map.addClass('map_detail').removeClass('map_basic');
|
||||
} else {
|
||||
$world_map.addClass('map_basic').removeClass('map_detail');
|
||||
}
|
||||
|
||||
var $map_title = $('.map_title_text');
|
||||
if (year < startYear + 1) {
|
||||
$map_title.css('color', 'magenta');
|
||||
} else if (year < startYear + 2) {
|
||||
$map_title.css('color', 'orange');
|
||||
} else if (year < startYear + 3) {
|
||||
$map_title.css('color', 'yellow');
|
||||
}
|
||||
|
||||
$map_title_tooltip = $('.map_title .tooltiptext');
|
||||
$map_title_tooltip.empty();
|
||||
|
||||
var tooltipTexts = [];
|
||||
if (year < startYear + 3) {
|
||||
var startYearText = [];
|
||||
var remainYear = startYear + 3 - year;
|
||||
var remainMonth = 12 - month + 1;
|
||||
if (remainMonth > 0) {
|
||||
remainYear -= 1;
|
||||
}
|
||||
if (remainYear) {
|
||||
startYearText.push('{0}년'.format(remainYear));
|
||||
}
|
||||
if (remainMonth) {
|
||||
startYearText.push('{0}개월'.format(remainMonth));
|
||||
}
|
||||
|
||||
tooltipTexts.push('초반제한 기간 : {0} ({1}년)'.format(startYearText.join(' '), startYear + 3));
|
||||
}
|
||||
|
||||
var currentTechLimit = Math.floor(Math.max(0, year - startYear) / 5) + 1;
|
||||
var nextTechLimitYear = currentTechLimit * 5 + startYear;
|
||||
|
||||
tooltipTexts.push('기술등급 제한 : {0}등급 ({1}년 해제)'.format(currentTechLimit, nextTechLimitYear, currentTechLimit + 1));
|
||||
$map_title_tooltip.html(tooltipTexts.join('<br>'));
|
||||
|
||||
$world_map.removeClass('map_string map_summer map_fall map_winter');
|
||||
if (month <= 3) {
|
||||
$world_map.addClass('map_spring');
|
||||
} else if (month <= 6) {
|
||||
$world_map.addClass('map_summer');
|
||||
} else if (month <= 9) {
|
||||
$world_map.addClass('map_fall');
|
||||
} else {
|
||||
$world_map.addClass('map_winter');
|
||||
}
|
||||
|
||||
$map_title.html('{0}年 {1}月'.format(year, month));
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function convertCityObjs(obj) {
|
||||
//원본 Obj는 굉장히 간소하게 온다, Object 형태로 변환해서 사용한다.
|
||||
|
||||
function toCityObj(arr) {
|
||||
return {
|
||||
id: arr[0],
|
||||
level: arr[1],
|
||||
state: arr[2],
|
||||
nationId: (arr[3] > 0) ? arr[3] : null,
|
||||
region: arr[4],
|
||||
supply: (arr[5] != 0)
|
||||
};
|
||||
}
|
||||
|
||||
function toNationObj(arr) {
|
||||
return {
|
||||
id: arr[0],
|
||||
name: arr[1],
|
||||
color: arr[2],
|
||||
capital: arr[3]
|
||||
};
|
||||
}
|
||||
|
||||
var cityList = obj.cityList.map(toCityObj);
|
||||
var nationList = obj.nationList.map(toNationObj);
|
||||
nationList = convertDictById(nationList); //array of object -> dict
|
||||
|
||||
var spyList = obj.spyList;
|
||||
var shownByGeneralList = convertSet(obj.shownByGeneralList); //Array -> Set
|
||||
|
||||
var myCity = obj.myCity;
|
||||
var myNation = obj.myNation;
|
||||
|
||||
|
||||
function mergePositionInfo(city) {
|
||||
var id = city.id;
|
||||
if (!(id in cityPosition)) {
|
||||
return city;
|
||||
}
|
||||
var xy_val = cityPosition[id];
|
||||
city.name = xy_val[0];
|
||||
city.x = xy_val[1];
|
||||
city.y = xy_val[2];
|
||||
return city;
|
||||
}
|
||||
|
||||
function mergeNationInfo(city) {
|
||||
//nationId 값으로 isCapital, color, nation을 통합
|
||||
|
||||
var nationId = city.nationId;
|
||||
if (nationId === null || !(nationId in nationList)) {
|
||||
city.nationId = null;
|
||||
city.nation = null;
|
||||
city.color = null;
|
||||
city.isCapital = false;
|
||||
return city;
|
||||
}
|
||||
|
||||
var nationObj = nationList[nationId];
|
||||
city.nation = nationObj.name;
|
||||
city.color = nationObj.color;
|
||||
city.isCapital = (nationObj.capital == city.id);
|
||||
|
||||
return city;
|
||||
}
|
||||
|
||||
function mergeClickable(city) {
|
||||
//clickable = (remainSpy << 3) | (ourCity << 2) | (shownByGeneral << 1) | clickableAll
|
||||
var id = city.id;
|
||||
var nationId = city.nationId;
|
||||
var clickable = 0;
|
||||
if (id in spyList) {
|
||||
clickable |= spyList[id] << 3;
|
||||
}
|
||||
if (myNation !== null && nationId == myNation) {
|
||||
clickable |= 4;
|
||||
}
|
||||
if (shownByGeneralList.hasOwnProperty(id)) {
|
||||
clickable |= 2;
|
||||
}
|
||||
if (myCity !== null && id == myCity) {
|
||||
clickable |= 2;
|
||||
}
|
||||
if (clickableAll) {
|
||||
clickable |= 1;
|
||||
}
|
||||
|
||||
|
||||
city.clickable = clickable;
|
||||
return city;
|
||||
}
|
||||
|
||||
cityList = cityList
|
||||
.map(mergePositionInfo)
|
||||
.map(mergeNationInfo)
|
||||
.map(mergeClickable)
|
||||
.map(formatCityInfo);
|
||||
|
||||
return {
|
||||
'cityList': cityList,
|
||||
'myCity': myCity
|
||||
};
|
||||
}
|
||||
|
||||
function drawDetailWorldMap(obj) {
|
||||
|
||||
var $map_body = $(drawTarget + ' .map_body');
|
||||
|
||||
var cityList = obj.cityList;
|
||||
var myCity = obj.myCity;
|
||||
|
||||
cityList.forEach(function(city) {
|
||||
var id = city.id;
|
||||
$('.city_base_{0}'.format(id)).detach();
|
||||
//이전 도시는 지운다.
|
||||
|
||||
var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id));
|
||||
$cityObj.addClass('city_level_{0}'.format(city.level));
|
||||
$cityObj.data('obj', city).css({ 'left': city.x - 20, 'top': city.y - 15 });
|
||||
|
||||
if ('color' in city && city.color !== null) {
|
||||
var $bgObj = $('<div class="city_bg"></div>');
|
||||
$cityObj.append($bgObj);
|
||||
$bgObj.css({ 'background-image': 'url({0}/b{1}.png)'.format(pathConfig.gameImage, convColorValue(city.color)) });
|
||||
}
|
||||
|
||||
var $linkObj = $('<a class="city_link"></a>');
|
||||
$linkObj.data({ 'text': city.text, 'nation': city.nation, 'id': city.id });
|
||||
$cityObj.append($linkObj);
|
||||
|
||||
var $imgObj = $('<div class="city_img"><img src="{0}/cast_{1}.gif"><div class="city_filler"></div></div>'.format(pathConfig.gameImage, city.level));
|
||||
$linkObj.append($imgObj);
|
||||
|
||||
|
||||
|
||||
if (city.state > 0) {
|
||||
var $stateObj = $('<div class="city_state"><img src="{0}/event{1}.gif"></div>'.format(pathConfig.gameImage, city.state));
|
||||
$linkObj.append($stateObj);
|
||||
}
|
||||
|
||||
if (city.nationId && city.nationId > 0) {
|
||||
var flagType = city.supply ? 'f' : 'd';
|
||||
var $flagObj = $('<div class="city_flag"><img src="{0}/{1}{2}.gif"></div>'.format(pathConfig.gameImage, flagType, convColorValue(city.color)));
|
||||
if (city.isCapital) {
|
||||
var $capitalObj = $('<div class="city_capital"><img src="{0}/event51.gif"></div>'.format(pathConfig.gameImage));
|
||||
$flagObj.append($capitalObj);
|
||||
}
|
||||
$imgObj.append($flagObj);
|
||||
}
|
||||
|
||||
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
|
||||
$imgObj.append($nameObj);
|
||||
|
||||
|
||||
$map_body.append($cityObj);
|
||||
|
||||
|
||||
});
|
||||
|
||||
$world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city');
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function drawBasicWorldMap(obj) {
|
||||
|
||||
var $map_body = $(drawTarget + ' .map_body');
|
||||
|
||||
var cityList = obj.cityList;
|
||||
var myCity = obj.myCity;
|
||||
|
||||
cityList.forEach(function(city) {
|
||||
var id = city.id;
|
||||
$('.city_base_{0}'.format(id)).detach();
|
||||
//이전 도시는 지운다.
|
||||
|
||||
var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id));
|
||||
$cityObj.addClass('city_level_{0}'.format(city.level));
|
||||
$cityObj.data('obj', city).css({ 'left': city.x - 20, 'top': city.y - 15 });
|
||||
|
||||
var $linkObj = $('<a class="city_link"></a>');
|
||||
$linkObj.data({ 'text': city.text, 'nation': city.nation, 'id': city.id });
|
||||
$cityObj.append($linkObj);
|
||||
|
||||
var $imgObj = $('<div class="city_img"><div class="city_filler"></div></div>');
|
||||
if ('color' in city && city.color !== null) {
|
||||
$imgObj.css({ 'background-color': city.color });
|
||||
}
|
||||
$linkObj.append($imgObj);
|
||||
|
||||
if (city.state > 0) {
|
||||
var state_text = 'wrong';
|
||||
if (city.state < 10) {
|
||||
state_text = 'good';
|
||||
} else if (city.state < 40) {
|
||||
state_text = 'bad';
|
||||
} else if (city.state < 50) {
|
||||
state_text = 'war';
|
||||
}
|
||||
|
||||
var $stateObj = $('<div class="city_state city_state_{0}"></div>'.format(state_text));
|
||||
$imgObj.append($stateObj);
|
||||
}
|
||||
|
||||
//단순 표기에서는 깃발 여부가 없음
|
||||
if (city.isCapital) {
|
||||
var $capitalObj = $('<div class="city_capital"></div>');
|
||||
$imgObj.append($capitalObj);
|
||||
}
|
||||
|
||||
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
|
||||
$imgObj.append($nameObj);
|
||||
|
||||
$map_body.append($cityObj);
|
||||
});
|
||||
|
||||
$world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city');
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function setMouseWork(obj) {
|
||||
var $tooltip = $(drawTarget + ' .city_tooltip');
|
||||
var $tooltip_city = $tooltip.find('.city_name');
|
||||
var $tooltip_nation = $tooltip.find('.nation_name');
|
||||
|
||||
var $objs = $(drawTarget + ' .city_link');
|
||||
|
||||
var $map_body = $(drawTarget + ' .map_body');
|
||||
|
||||
//터치스크린 탭
|
||||
|
||||
if (!option.neutralView && is_touch_device()) {
|
||||
$objs.on('touchstart', function(e) {
|
||||
if (window.sam_toggleSingleTap) {
|
||||
return true;
|
||||
}
|
||||
var $this = $(this);
|
||||
|
||||
var touchMode = $this.data('touchMode');
|
||||
if ($tooltip_city.data('target') != $this.data('id')) {
|
||||
$this.data('touchMode', 1);
|
||||
} else if (touchMode === undefined) {
|
||||
$this.data('touchMode', 1);
|
||||
} else {
|
||||
$this.data('touchMode', touchMode + 1);
|
||||
}
|
||||
$map_body.data('touchMode', 1);
|
||||
|
||||
$tooltip_city.data('target', $this.data('id'));
|
||||
|
||||
|
||||
});
|
||||
|
||||
$objs.on('touchend', function(e) {
|
||||
if (window.sam_toggleSingleTap) {
|
||||
return true;
|
||||
}
|
||||
var $this = $(this);
|
||||
var position = $this.parent().position();
|
||||
$tooltip_city.html($this.data('text'));
|
||||
|
||||
var nation_text = $this.data('nation');
|
||||
if (nation_text) {
|
||||
$tooltip_nation.html(nation_text).show();
|
||||
} else {
|
||||
$tooltip_nation.html('').hide();
|
||||
}
|
||||
|
||||
var left = position.left;
|
||||
var top = position.top;
|
||||
|
||||
var scale = $map_body.data('scale');
|
||||
if (scale) {
|
||||
left /= scale;
|
||||
top /= scale;
|
||||
}
|
||||
|
||||
$tooltip.css({ 'top': top + 25, 'left': left + 35 }).show();
|
||||
|
||||
var touchMode = $this.data('touchMode');
|
||||
if (touchMode <= 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다.
|
||||
$this.data('touchMode', 0);
|
||||
});
|
||||
|
||||
$map_body.on('touchend', function(e) {
|
||||
if (window.sam_toggleSingleTap) {
|
||||
return true;
|
||||
}
|
||||
//위의 touchend bind에 해당하지 않는 경우 -> 빈 지도 터치
|
||||
$tooltip.hide();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//Mouse over 모드 작동
|
||||
|
||||
$map_body.on('mousemove', function(e) {
|
||||
if ($(this).data('touchMode')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var rect = this.getBoundingClientRect();
|
||||
var left = (e.clientX - rect.left - this.clientLeft + this.scrollLeft);
|
||||
var top = (e.clientY - rect.top - this.clientTop + this.scrollTop);
|
||||
|
||||
var scale = $map_body.data('scale');
|
||||
if (scale) {
|
||||
left /= scale;
|
||||
top /= scale;
|
||||
}
|
||||
|
||||
$tooltip.css({ 'top': top + 10, 'left': left + 10 });
|
||||
});
|
||||
|
||||
$objs.on('mouseenter', function(e) {
|
||||
if ($map_body.data('touchMode')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
$tooltip_city.data('target', $this.data('id'));
|
||||
$tooltip_city.html($this.data('text'));
|
||||
var nation_text = $this.data('nation');
|
||||
if (nation_text) {
|
||||
$tooltip_nation.html(nation_text).show();
|
||||
} else {
|
||||
$tooltip_nation.html('').hide();
|
||||
}
|
||||
|
||||
$tooltip.show();
|
||||
});
|
||||
|
||||
$objs.on('mouseleave', function(event) {
|
||||
$tooltip.hide();
|
||||
});
|
||||
|
||||
$objs.on('click', function(e) {
|
||||
//xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다.
|
||||
var touchMode = $(this).data('touchMode');
|
||||
if (touchMode === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (touchMode === 1) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function setCityClickable(obj) {
|
||||
|
||||
obj.cityList.forEach(function(city) {
|
||||
var $cityLink = $world_map.find('.city_base_{0} .city_link'.format(city.id));
|
||||
|
||||
if ('clickable' in city && city.clickable > 0) {
|
||||
$cityLink.attr('href', hrefTemplate.format(city.id));
|
||||
}
|
||||
|
||||
if (selectCallback) {
|
||||
$cityLink.click(function() {
|
||||
return selectCallback(city);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function saveCityInfo(obj) {
|
||||
$world_map.data('cityInfo', obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
var $hideCityNameBtn = $world_map.find('.map_toggle_cityname');
|
||||
if (localStorage.getItem('sam.hideMapCityName') == 'yes') {
|
||||
$world_map.addClass('hide_cityname');
|
||||
$hideCityNameBtn.addClass('active').attr('aria-pressed', 'true');
|
||||
}
|
||||
|
||||
$hideCityNameBtn.click(function() {
|
||||
//이전 상태 확인
|
||||
var state = !$hideCityNameBtn.hasClass('active');
|
||||
if (state) {
|
||||
$world_map.addClass('hide_cityname');
|
||||
localStorage.setItem('sam.hideMapCityName', 'yes');
|
||||
} else {
|
||||
$world_map.removeClass('hide_cityname');
|
||||
localStorage.setItem('sam.hideMapCityName', 'no');
|
||||
}
|
||||
});
|
||||
|
||||
var $toggleSingleTapBtn = $world_map.find('.map_toggle_single_tap');
|
||||
if (localStorage.getItem('sam.toggleSingleTap') == 'yes') {
|
||||
window.sam_toggleSingleTap = true;
|
||||
$toggleSingleTapBtn.addClass('active').attr('aria-pressed', 'true');
|
||||
} else {
|
||||
window.sam_toggleSingleTap = false;
|
||||
}
|
||||
|
||||
var $map_body = $(drawTarget + ' .map_body');
|
||||
|
||||
$toggleSingleTapBtn.click(function() {
|
||||
//이전 상태 확인
|
||||
var state = !$toggleSingleTapBtn.hasClass('active');
|
||||
if (state) {
|
||||
$map_body.removeData('touchMode');
|
||||
localStorage.setItem('sam.toggleSingleTap', 'yes');
|
||||
window.sam_toggleSingleTap = true;
|
||||
} else {
|
||||
localStorage.setItem('sam.toggleSingleTap', 'no');
|
||||
window.sam_toggleSingleTap = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (isDetailMap) {
|
||||
$world_map.addClass('map_detail');
|
||||
} else {
|
||||
$world_map.removeClass('map_datail');
|
||||
}
|
||||
|
||||
//deferred mode of jQuery. != promise-then.
|
||||
var deferred = $.ajax({
|
||||
url: option.targetJson,
|
||||
type: option.reqType,
|
||||
dataType: 'json',
|
||||
ifModified: true,
|
||||
data: {
|
||||
data: JSON.stringify({
|
||||
neutralView: option.neutralView,
|
||||
year: option.year,
|
||||
month: option.month,
|
||||
showMe: option.showMe,
|
||||
aux: option.aux
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
var rawObject = null;
|
||||
|
||||
deferred
|
||||
.then(function(data) {
|
||||
rawObject = data;
|
||||
return data;
|
||||
})
|
||||
.then(checkReturnObject)
|
||||
.then(setMapBackground)
|
||||
.then(convertCityObjs)
|
||||
.then(isDetailMap ? drawDetailWorldMap : drawBasicWorldMap)
|
||||
.then(setMouseWork)
|
||||
.then(setCityClickable)
|
||||
.then(saveCityInfo)
|
||||
.then(function(data) {
|
||||
if (option.callback) {
|
||||
option.callback(data, rawObject);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if ($world_map.hasClass('draw_required')) {
|
||||
if (useCachedMap) {
|
||||
//일단 불러옴
|
||||
do {
|
||||
var storedMap = localStorage.getItem(storedOldMapKey);
|
||||
if (!storedMap) {
|
||||
break;
|
||||
}
|
||||
storedMap = JSON.parse(storedMap);
|
||||
var storedServerID = storedMap[0];
|
||||
if (storedServerID != serverID) {
|
||||
break;
|
||||
}
|
||||
|
||||
storedMap = storedMap[1];
|
||||
storedMap = setMapBackground(storedMap);
|
||||
storedMap = convertCityObjs(storedMap);
|
||||
if (isDetailMap) {
|
||||
storedMap = drawDetailWorldMap(storedMap);
|
||||
} else {
|
||||
storedMap = drawBasicWorldMap(storedMap);
|
||||
}
|
||||
storedMap = setMouseWork(storedMap);
|
||||
storedMap = setCityClickable(storedMap);
|
||||
storedMap = saveCityInfo(storedMap);
|
||||
} while (false);
|
||||
} else if (option.year && option.month) {
|
||||
var startYear = localStorage.getItem(storedStartYear);
|
||||
if (startYear) {
|
||||
startYear = JSON.parse(startYear);
|
||||
} else {
|
||||
startYear = option.year;
|
||||
}
|
||||
var tmp = {
|
||||
year: option.year,
|
||||
month: option.month,
|
||||
startYear: startYear
|
||||
};
|
||||
setMapBackground(tmp);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
$(function() {
|
||||
if (is_touch_device()) {
|
||||
$('.map_body .map_toggle_single_tap').show();
|
||||
}
|
||||
})
|
||||
+166
-165
@@ -1,166 +1,167 @@
|
||||
jQuery(function($){
|
||||
|
||||
|
||||
var initCustomCSSForm = function(){
|
||||
var lastTimeOut = null;
|
||||
var $obj = $('#custom_css');
|
||||
var key = 'sam_customCSS';
|
||||
|
||||
var text = localStorage.getItem(key);
|
||||
if(text){
|
||||
$obj.val(text);
|
||||
console.log(text);
|
||||
}
|
||||
|
||||
if($obj.on('change keyup paste', function(){
|
||||
var newText = $obj.val();
|
||||
if(text == newText){
|
||||
return;
|
||||
}
|
||||
if(lastTimeOut){
|
||||
clearTimeout(lastTimeOut);
|
||||
}
|
||||
$obj.css('background-color', '#222222');
|
||||
lastTimeOut = setTimeout(function(){
|
||||
text = $obj.val();
|
||||
localStorage.setItem(key, text);
|
||||
$obj.css('background-color', 'black');
|
||||
}, 500);
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
$('.load_old_log').click(function(){
|
||||
var $thisBtn = $(this);
|
||||
var logType = $thisBtn.data('log_type');
|
||||
var $last = $('.log_{0}:last'.format(logType));
|
||||
var reqTo = null;
|
||||
if($last.length){
|
||||
reqTo = $last.data('seq');
|
||||
}
|
||||
|
||||
$.post({
|
||||
url:'j_general_log_old.php',
|
||||
dataType:'json',
|
||||
data:{
|
||||
to:reqTo,
|
||||
type:logType
|
||||
}
|
||||
}).then(function(data){
|
||||
if(!data){
|
||||
return quickReject('로그를 받아오지 못했습니다.');
|
||||
}
|
||||
if(!data.result){
|
||||
return quickReject('로그를 받아오지 못했습니다. : '+data.reason);
|
||||
}
|
||||
|
||||
var keys = Object.keys(data.log);
|
||||
if(keys.length > 1 && keys[0] < keys[1]){
|
||||
keys.reverse();
|
||||
}
|
||||
|
||||
if(keys == 0){
|
||||
$thisBtn.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
var html = [];
|
||||
$.each(keys, function(_, key){
|
||||
if($('#log_{0}_{1}'.format(logType, key)).length){
|
||||
return true;
|
||||
}
|
||||
var item = data.log[key];
|
||||
html.push("<div class='log_{0}' id='log_{0}_{1}' data-seq='{1}'>{2}</div>".format(logType, key, item));
|
||||
});
|
||||
|
||||
$('#{0}Plate'.format(logType)).append(html);
|
||||
}, errUnknown)
|
||||
.fail(function(reason){
|
||||
alert(reason);
|
||||
location.reload();
|
||||
});
|
||||
})
|
||||
|
||||
initCustomCSSForm();
|
||||
|
||||
|
||||
$('#die_immediately').click(function(){
|
||||
if(!confirm('정말로 삭제하시겠습니까?')){
|
||||
return false;
|
||||
}
|
||||
$.post({
|
||||
url:'j_die_immediately.php',
|
||||
dataType:'json',
|
||||
}).then(function(data){
|
||||
if(!data){
|
||||
return quickReject('실패했습니다.');
|
||||
}
|
||||
if(!data.result){
|
||||
return quickReject(data.reason);
|
||||
}
|
||||
|
||||
location.replace('..');
|
||||
|
||||
}, errUnknown)
|
||||
.fail(function(reason){
|
||||
alert(reason);
|
||||
location.reload();
|
||||
});
|
||||
return false;
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#vacation').click(function(){
|
||||
if(!confirm('휴가 기능을 신청할까요?')){
|
||||
return false;
|
||||
}
|
||||
$.post({
|
||||
url:'j_vacation.php',
|
||||
dataType:'json',
|
||||
}).then(function(data){
|
||||
if(!data){
|
||||
return quickReject('실패했습니다.');
|
||||
}
|
||||
if(!data.result){
|
||||
return quickReject(data.reason);
|
||||
}
|
||||
|
||||
location.reload();
|
||||
|
||||
}, errUnknown)
|
||||
.fail(function(reason){
|
||||
alert(reason);
|
||||
location.reload();
|
||||
});
|
||||
return false;
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#set_my_setting').click(function(){
|
||||
$.post({
|
||||
url:'j_set_my_setting.php',
|
||||
dataType:'json',
|
||||
data:{
|
||||
tnmt:$('.tnmt:checked').val(),
|
||||
defence_train:$('#defence_train').val(),
|
||||
use_treatment:$('#use_treatment').val(),
|
||||
}
|
||||
}).then(function(data){
|
||||
if(!data){
|
||||
return quickReject('실패했습니다.');
|
||||
}
|
||||
if(!data.result){
|
||||
return quickReject(data.reason);
|
||||
}
|
||||
|
||||
location.reload();
|
||||
|
||||
}, errUnknown)
|
||||
.fail(function(reason){
|
||||
alert(reason);
|
||||
location.reload();
|
||||
});
|
||||
return false;
|
||||
return false;
|
||||
});
|
||||
jQuery(function($) {
|
||||
|
||||
|
||||
var initCustomCSSForm = function() {
|
||||
var lastTimeOut = null;
|
||||
var $obj = $('#custom_css');
|
||||
var key = 'sam_customCSS';
|
||||
|
||||
var text = localStorage.getItem(key);
|
||||
if (text) {
|
||||
$obj.val(text);
|
||||
console.log(text);
|
||||
}
|
||||
|
||||
if ($obj.on('change keyup paste', function() {
|
||||
var newText = $obj.val();
|
||||
if (text == newText) {
|
||||
return;
|
||||
}
|
||||
if (lastTimeOut) {
|
||||
clearTimeout(lastTimeOut);
|
||||
}
|
||||
$obj.css('background-color', '#222222');
|
||||
lastTimeOut = setTimeout(function() {
|
||||
text = $obj.val();
|
||||
localStorage.setItem(key, text);
|
||||
$obj.css('background-color', 'black');
|
||||
}, 500);
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
$('.load_old_log').click(function() {
|
||||
var $thisBtn = $(this);
|
||||
var logType = $thisBtn.data('log_type');
|
||||
var $last = $('.log_{0}:last'.format(logType));
|
||||
var reqTo = null;
|
||||
if ($last.length) {
|
||||
reqTo = $last.data('seq');
|
||||
}
|
||||
|
||||
$.post({
|
||||
url: 'j_general_log_old.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
to: reqTo,
|
||||
type: logType
|
||||
}
|
||||
}).then(function(data) {
|
||||
if (!data) {
|
||||
return quickReject('로그를 받아오지 못했습니다.');
|
||||
}
|
||||
if (!data.result) {
|
||||
return quickReject('로그를 받아오지 못했습니다. : ' + data.reason);
|
||||
}
|
||||
|
||||
var keys = Object.keys(data.log);
|
||||
if (keys.length > 1 && keys[0] < keys[1]) {
|
||||
keys.reverse();
|
||||
}
|
||||
|
||||
if (keys == 0) {
|
||||
$thisBtn.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
var html = [];
|
||||
$.each(keys, function(_, key) {
|
||||
if ($('#log_{0}_{1}'.format(logType, key)).length) {
|
||||
return true;
|
||||
}
|
||||
var item = data.log[key];
|
||||
html.push("<div class='log_{0}' id='log_{0}_{1}' data-seq='{1}'>{2}</div>".format(logType, key, item));
|
||||
});
|
||||
|
||||
$('#{0}Plate'.format(logType)).append(html);
|
||||
}, errUnknown)
|
||||
.fail(function(reason) {
|
||||
alert(reason);
|
||||
location.reload();
|
||||
});
|
||||
})
|
||||
|
||||
initCustomCSSForm();
|
||||
|
||||
|
||||
$('#die_immediately').click(function() {
|
||||
if (!confirm('정말로 삭제하시겠습니까?')) {
|
||||
return false;
|
||||
}
|
||||
$.post({
|
||||
url: 'j_die_immediately.php',
|
||||
dataType: 'json',
|
||||
}).then(function(data) {
|
||||
if (!data) {
|
||||
return quickReject('실패했습니다.');
|
||||
}
|
||||
if (!data.result) {
|
||||
return quickReject(data.reason);
|
||||
}
|
||||
|
||||
location.replace('..');
|
||||
|
||||
}, errUnknown)
|
||||
.fail(function(reason) {
|
||||
alert(reason);
|
||||
location.reload();
|
||||
});
|
||||
return false;
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#vacation').click(function() {
|
||||
if (!confirm('휴가 기능을 신청할까요?')) {
|
||||
return false;
|
||||
}
|
||||
$.post({
|
||||
url: 'j_vacation.php',
|
||||
dataType: 'json',
|
||||
}).then(function(data) {
|
||||
if (!data) {
|
||||
return quickReject('실패했습니다.');
|
||||
}
|
||||
if (!data.result) {
|
||||
return quickReject(data.reason);
|
||||
}
|
||||
|
||||
location.reload();
|
||||
|
||||
}, errUnknown)
|
||||
.fail(function(reason) {
|
||||
alert(reason);
|
||||
location.reload();
|
||||
});
|
||||
return false;
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#set_my_setting').click(function() {
|
||||
$.post({
|
||||
url: 'j_set_my_setting.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
tnmt: $('.tnmt:checked').val(),
|
||||
defence_train: $('#defence_train').val(),
|
||||
use_treatment: $('#use_treatment').val(),
|
||||
use_auto_nation_turn: $('#use_auto_nation_turn').val(),
|
||||
}
|
||||
}).then(function(data) {
|
||||
if (!data) {
|
||||
return quickReject('실패했습니다.');
|
||||
}
|
||||
if (!data.result) {
|
||||
return quickReject(data.reason);
|
||||
}
|
||||
|
||||
location.reload();
|
||||
|
||||
}, errUnknown)
|
||||
.fail(function(reason) {
|
||||
alert(reason);
|
||||
location.reload();
|
||||
});
|
||||
return false;
|
||||
return false;
|
||||
});
|
||||
});
|
||||
@@ -35,7 +35,7 @@ jQuery(function($) {
|
||||
//checkCommandArg 참고
|
||||
var availableArgumentList = {
|
||||
'string': [
|
||||
'nationName', 'optionText', 'itemType', 'nationType', 'itemCode',
|
||||
'nationName', 'optionText', 'itemType', 'nationType', 'itemCode', 'commandType',
|
||||
],
|
||||
'int': [
|
||||
'crewType', 'destGeneralID', 'destCityID', 'destNationID',
|
||||
@@ -73,9 +73,11 @@ jQuery(function($) {
|
||||
}
|
||||
},
|
||||
'integerArray': function($obj) {
|
||||
return $obj.map(function() {
|
||||
return parseInt($(this).val());
|
||||
var result = [];
|
||||
$obj.each(function() {
|
||||
result.push(parseInt($(this).val()));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+352
-359
@@ -1,360 +1,353 @@
|
||||
var templateGeneralCard =
|
||||
'<div class="general_card">\
|
||||
<h4 class="bg1 with_border"><%name%></h4>\
|
||||
<h4><img src="<%iconPath%>" height=64 width=64></h4>\
|
||||
<p><%leadership%> / <%strength%> / <%intel%><br>\
|
||||
<%nation%><br>\
|
||||
<%personalText%><br>\
|
||||
<%specialText%> / <%special2Text%></p>\
|
||||
<button type="subject" class="with_skin with_border select_btn" data-name="<%name%>" value="<%no%>" name="pick">빙의하기</button>\
|
||||
<label><input <%keepCnt?"":disabled="disabled"%> type="checkbox" value="<%no%>" name="keep[]" class="keep_select">보관(<%keepCnt%>회)</label>\
|
||||
</div>';
|
||||
|
||||
var templateSpecial =
|
||||
'<span class="obj_tooltip" data-toggle="tooltip" data-placement="top"><%text%>\
|
||||
<span class="tooltiptext">\
|
||||
<%info%>\
|
||||
</span>\
|
||||
</span>\
|
||||
';
|
||||
|
||||
var templateGeneralRow =
|
||||
'<tr>\
|
||||
<td><img class="generalIcon" width="64" height="64" src="<%iconPath%>"></td>\
|
||||
<td style="<%userCSS%>"><%name%><%nameAux%></td>\
|
||||
<td><%age%>세</td>\
|
||||
<td><%personalWithTooltip%></td>\
|
||||
<td><%specialDomesticWithTooltip%> / <%speicalWarWithTooltip%></td>\
|
||||
<td>Lv <%explevel%></td>\
|
||||
<td><%nation%></td>\
|
||||
<td><%experience%></td>\
|
||||
<td><%dedication%></td>\
|
||||
<td><%officerLevel%></td>\
|
||||
<td><%total%></td>\
|
||||
<td><%leadership%></td>\
|
||||
<td><%strength%></td>\
|
||||
<td><%intel%></td>\
|
||||
<td><%killturn%></td>\
|
||||
</tr>';
|
||||
|
||||
function pickGeneral(){
|
||||
$btn = $(this);
|
||||
|
||||
if (!confirm('빙의할까요? : {0}'.format($btn.data('name')))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$.post({
|
||||
url:'j_select_npc.php',
|
||||
dataType:'json',
|
||||
data:{
|
||||
pick:$btn.val()
|
||||
}
|
||||
}).then(function(result){
|
||||
if(!result.result){
|
||||
alert(result.reason);
|
||||
location.refresh();
|
||||
}
|
||||
|
||||
alert('빙의에 성공했습니다.');
|
||||
location.href = './';
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateOutdateTimer(){
|
||||
var $validUntilText = $('#valid_until_text');
|
||||
var now = Date.now();
|
||||
var validUntil = $validUntilText.data('until');
|
||||
if(validUntil <= 0){
|
||||
return;
|
||||
}
|
||||
else if(validUntil < now){
|
||||
$validUntilText.data('until',0);
|
||||
$('#valid_until').hide();
|
||||
$('#outdate_token').show();
|
||||
return;
|
||||
}
|
||||
else if(validUntil - now <= 30000){
|
||||
$validUntilText.css('color', "rgb(255, {0}, {0})".format(255*(validUntil - now)/30000));
|
||||
}
|
||||
|
||||
setTimeout(updateOutdateTimer, 1000);
|
||||
}
|
||||
|
||||
function updatePickMoreTimer(){
|
||||
var $btn = $('#btn_pick_more');
|
||||
|
||||
var now = Date.now();
|
||||
var remain = ($btn.data('available') - now) / 1000;
|
||||
if(remain <= 0){
|
||||
$btn.prop('disabled', false)
|
||||
$btn.html('다른 장수 보기');
|
||||
return;
|
||||
}
|
||||
|
||||
$btn.html('다른 장수 보기({0}초)'.format(Math.ceil(remain)));
|
||||
|
||||
setTimeout(updatePickMoreTimer, 250);
|
||||
}
|
||||
|
||||
function printGenerals(value){
|
||||
$('.card_holder').empty();
|
||||
$('#valid_until').show();
|
||||
$('#valid_until_text').html(value.validUntil).data('until', (new Date(value.validUntil)).getTime()).css('color','white');
|
||||
$('#outdate_token').hide();
|
||||
var time = Date.now() + value.pickMoreSeconds*1000;
|
||||
$('#btn_pick_more').data('available', time).prop('disabled',true);
|
||||
|
||||
var pick = $.map(value.pick, function(value, key) {
|
||||
return value;
|
||||
});
|
||||
|
||||
pick.sort(function(lhs, rhs){
|
||||
var lsum = lhs.leadership+lhs.strength+lhs.intel;
|
||||
var rsum = rhs.leadership+rhs.strength+rhs.intel;
|
||||
return lsum - rsum;
|
||||
});
|
||||
|
||||
$.each(pick, function(idx, cardData){
|
||||
cardData.iconPath = getIconPath(cardData.imgsvr, cardData.picture);
|
||||
if(cardData.special in specialInfo){
|
||||
cardData.specialText = TemplateEngine(templateSpecial, {
|
||||
text:cardData.special,
|
||||
info:specialInfo[cardData.special]
|
||||
});
|
||||
}
|
||||
else{
|
||||
cardData.specialText = cardData.special;
|
||||
}
|
||||
|
||||
if(cardData.special2 in specialInfo){
|
||||
cardData.special2Text = TemplateEngine(templateSpecial, {
|
||||
text:cardData.special2,
|
||||
info:specialInfo[cardData.special2]
|
||||
});
|
||||
}
|
||||
else{
|
||||
cardData.special2Text = cardData.special2;
|
||||
}
|
||||
|
||||
if(cardData.personal in characterInfo){
|
||||
cardData.personalText = TemplateEngine(templateSpecial, {
|
||||
text:cardData.personal,
|
||||
info:characterInfo[cardData.personal]
|
||||
});
|
||||
}
|
||||
else{
|
||||
cardData.personalText = cardData.personal;
|
||||
}
|
||||
|
||||
|
||||
var $card = $(TemplateEngine(templateGeneralCard, cardData));
|
||||
|
||||
$('.card_holder').append($card);
|
||||
$card.find('.select_btn').click(pickGeneral);
|
||||
$card.find('.obj_tooltip').tooltip({
|
||||
title:function(){
|
||||
return $.trim($(this).find('.tooltiptext').html());
|
||||
},
|
||||
html:true
|
||||
});
|
||||
});
|
||||
|
||||
updatePickMoreTimer();
|
||||
updateOutdateTimer();
|
||||
}
|
||||
|
||||
function printGeneralList(value){
|
||||
var tokenList = value.token;
|
||||
var generalList = $.map(value.list, function(general){
|
||||
general = {
|
||||
no:general[0],
|
||||
picture:general[1],
|
||||
imgsvr:general[2],
|
||||
npc:general[3],
|
||||
age:general[4],
|
||||
nation:general[5],
|
||||
special:general[6],
|
||||
special2:general[7],
|
||||
personal:general[8],
|
||||
name:general[9],
|
||||
ownerName:general[10],
|
||||
injury:general[11],
|
||||
leadership:general[12],
|
||||
lbonus:general[13],
|
||||
strength:general[14],
|
||||
intel:general[15],
|
||||
explevel:general[16],
|
||||
experience:general[17],
|
||||
dedication:general[18],
|
||||
officerLevel:general[19],
|
||||
killturn:general[20],
|
||||
connect:general[21],
|
||||
reserved:0
|
||||
};
|
||||
if(general.npc < 2){
|
||||
general.reserved = 2;
|
||||
}
|
||||
if(general.no in tokenList){
|
||||
general.reserved = 1;
|
||||
}
|
||||
|
||||
general.userCSS = "";
|
||||
general.nameAux = "";
|
||||
|
||||
if(general.reserved == 1){
|
||||
general.userCSS = 'color:violet';
|
||||
}
|
||||
else if(general.npc >= 2){
|
||||
general.userCSS = 'color:cyan';
|
||||
}
|
||||
else if(general.npc == 1){
|
||||
general.userCSS = 'color:skyblue';
|
||||
}
|
||||
|
||||
if(general.ownerName){
|
||||
general.nameAux += '<br><small>({0})</small>'.format(general.ownerName);
|
||||
}
|
||||
|
||||
if(general.reserved == 1){
|
||||
general.nameAux += '<br><small>({0}회)</small>'.format(tokenList[general.no]);
|
||||
}
|
||||
|
||||
|
||||
general.total = general.leadership + general.strength + general.intel;
|
||||
general.iconPath = getIconPath(general.imgsvr, general.picture);
|
||||
|
||||
general.specialDomesticWithTooltip = TemplateEngine(templateSpecial, {
|
||||
text:general.special,
|
||||
info:specialInfo[general.special]
|
||||
});
|
||||
|
||||
general.speicalWarWithTooltip = TemplateEngine(templateSpecial, {
|
||||
text:general.special2,
|
||||
info:specialInfo[general.special2]
|
||||
});
|
||||
|
||||
general.personalWithTooltip = TemplateEngine(templateSpecial, {
|
||||
text:general.personal,
|
||||
info:characterInfo[general.personal]
|
||||
});
|
||||
|
||||
return general;
|
||||
});
|
||||
|
||||
generalList.sort(function(lhs, rhs){
|
||||
if(lhs.reserved > rhs.reserved){
|
||||
return -1;
|
||||
}
|
||||
if(lhs.reserved < rhs.reserved){
|
||||
return 1;
|
||||
}
|
||||
if(lhs.total != rhs.total){
|
||||
return rhs.total - lhs.total;
|
||||
}
|
||||
if(lhs.leadership != rhs.leadership){
|
||||
return rhs.leadership - lhs.total;
|
||||
}
|
||||
|
||||
if(lhs.name < rhs.name){
|
||||
return -1;
|
||||
}
|
||||
if(lhs.name > rhs.name){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
window.generalList = generalList;
|
||||
_printGeneralList(true);
|
||||
}
|
||||
|
||||
function _printGeneralList(clear){
|
||||
var $generalTable = $('#general_list');
|
||||
if(clear){
|
||||
$generalTable.empty();
|
||||
$generalTable.data('lastIdx', 0);
|
||||
$('#row_print_more').show();
|
||||
}
|
||||
|
||||
generalList = window.generalList;
|
||||
|
||||
var idxFrom = $generalTable.data('lastIdx');
|
||||
var idxTo = Math.min(idxFrom + 50, generalList.length);
|
||||
$generalTable.data('lastIdx', idxTo);
|
||||
|
||||
for(var idx = idxFrom; idx < idxFrom + 50; idx++){
|
||||
var general = generalList[idx];
|
||||
$generalTable.append(TemplateEngine(templateGeneralRow, general));
|
||||
}
|
||||
|
||||
if(idxTo == generalList.length){
|
||||
$('#row_print_more').hide();
|
||||
}
|
||||
|
||||
$generalTable.find('.obj_tooltip').tooltip({
|
||||
title:function(){
|
||||
return $.trim($(this).find('.tooltiptext').html());
|
||||
},
|
||||
html:true
|
||||
});
|
||||
$('#tb_general_list').show();
|
||||
}
|
||||
|
||||
$(function($){
|
||||
window.generalList = [];
|
||||
|
||||
$.post('j_get_select_npc_token.php').then(function(value){
|
||||
if(!value.result){
|
||||
alert(value.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(value);
|
||||
printGenerals(value);
|
||||
});
|
||||
|
||||
$('#btn_pick_more').click(function(){
|
||||
var generals = $.map($('.keep_select:checked'), function(value){
|
||||
return $(value).val();
|
||||
});
|
||||
console.log(generals);
|
||||
$.post({
|
||||
url:'j_get_select_npc_token.php',
|
||||
dataType:'json',
|
||||
data:{
|
||||
refresh:true,
|
||||
keep:generals
|
||||
}
|
||||
}).then(function(result){
|
||||
if(!result.result){
|
||||
alert(result.reason);
|
||||
location.refresh();
|
||||
}
|
||||
console.log(result);
|
||||
printGenerals(result);
|
||||
});
|
||||
});
|
||||
|
||||
$('#btn_load_general_list').click(function(){
|
||||
$.post({
|
||||
url:'j_get_general_list.php',
|
||||
dataType:'json',
|
||||
data:{
|
||||
with_token:true
|
||||
}
|
||||
}).then(function(result){
|
||||
if(!result.result){
|
||||
alert(result.reason);
|
||||
return false;
|
||||
}
|
||||
printGeneralList(result);
|
||||
});
|
||||
});
|
||||
|
||||
$('#btn_print_more').click(function(){
|
||||
_printGeneralList();
|
||||
})
|
||||
|
||||
var templateGeneralCard =
|
||||
'<div class="general_card">\
|
||||
<h4 class="bg1 with_border"><%name%></h4>\
|
||||
<h4><img src="<%iconPath%>" height=64 width=64></h4>\
|
||||
<p><%leadership%> / <%strength%> / <%intel%><br>\
|
||||
<%nation%><br>\
|
||||
<%personalText%><br>\
|
||||
<%specialText%> / <%special2Text%></p>\
|
||||
<button type="subject" class="with_skin with_border select_btn" data-name="<%name%>" value="<%no%>" name="pick">빙의하기</button>\
|
||||
<label><input <%keepCnt?"":disabled="disabled"%> type="checkbox" value="<%no%>" name="keep[]" class="keep_select">보관(<%keepCnt%>회)</label>\
|
||||
</div>';
|
||||
|
||||
var templateSpecial =
|
||||
'<span class="obj_tooltip" data-toggle="tooltip" data-placement="top"><%text%>\
|
||||
<span class="tooltiptext">\
|
||||
<%info%>\
|
||||
</span>\
|
||||
</span>\
|
||||
';
|
||||
|
||||
var templateGeneralRow =
|
||||
'<tr>\
|
||||
<td><img class="generalIcon" width="64" height="64" src="<%iconPath%>"></td>\
|
||||
<td style="<%userCSS%>"><%name%><%nameAux%></td>\
|
||||
<td><%age%>세</td>\
|
||||
<td><%personalWithTooltip%></td>\
|
||||
<td><%specialDomesticWithTooltip%> / <%speicalWarWithTooltip%></td>\
|
||||
<td>Lv <%explevel%></td>\
|
||||
<td><%nation%></td>\
|
||||
<td><%experience%></td>\
|
||||
<td><%dedication%></td>\
|
||||
<td><%officerLevel%></td>\
|
||||
<td><%total%></td>\
|
||||
<td><%leadership%></td>\
|
||||
<td><%strength%></td>\
|
||||
<td><%intel%></td>\
|
||||
<td><%killturn%></td>\
|
||||
</tr>';
|
||||
|
||||
function pickGeneral() {
|
||||
$btn = $(this);
|
||||
|
||||
if (!confirm('빙의할까요? : {0}'.format($btn.data('name')))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$.post({
|
||||
url: 'j_select_npc.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
pick: $btn.val()
|
||||
}
|
||||
}).then(function(result) {
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
location.refresh();
|
||||
}
|
||||
|
||||
alert('빙의에 성공했습니다.');
|
||||
location.href = './';
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateOutdateTimer() {
|
||||
var $validUntilText = $('#valid_until_text');
|
||||
var now = Date.now();
|
||||
var validUntil = $validUntilText.data('until');
|
||||
if (validUntil <= 0) {
|
||||
return;
|
||||
} else if (validUntil < now) {
|
||||
$validUntilText.data('until', 0);
|
||||
$('#valid_until').hide();
|
||||
$('#outdate_token').show();
|
||||
return;
|
||||
} else if (validUntil - now <= 30000) {
|
||||
$validUntilText.css('color', "rgb(255, {0}, {0})".format(255 * (validUntil - now) / 30000));
|
||||
}
|
||||
|
||||
setTimeout(updateOutdateTimer, 1000);
|
||||
}
|
||||
|
||||
function updatePickMoreTimer() {
|
||||
var $btn = $('#btn_pick_more');
|
||||
|
||||
var now = Date.now();
|
||||
var remain = ($btn.data('available') - now) / 1000;
|
||||
if (remain <= 0) {
|
||||
$btn.prop('disabled', false)
|
||||
$btn.html('다른 장수 보기');
|
||||
return;
|
||||
}
|
||||
|
||||
$btn.html('다른 장수 보기({0}초)'.format(Math.ceil(remain)));
|
||||
|
||||
setTimeout(updatePickMoreTimer, 250);
|
||||
}
|
||||
|
||||
function printGenerals(value) {
|
||||
$('.card_holder').empty();
|
||||
$('#valid_until').show();
|
||||
$('#valid_until_text').html(value.validUntil).data('until', (new Date(value.validUntil)).getTime()).css('color', 'white');
|
||||
$('#outdate_token').hide();
|
||||
var time = Date.now() + value.pickMoreSeconds * 1000;
|
||||
$('#btn_pick_more').data('available', time).prop('disabled', true);
|
||||
|
||||
var pick = $.map(value.pick, function(value, key) {
|
||||
return value;
|
||||
});
|
||||
|
||||
pick.sort(function(lhs, rhs) {
|
||||
var lsum = lhs.leadership + lhs.strength + lhs.intel;
|
||||
var rsum = rhs.leadership + rhs.strength + rhs.intel;
|
||||
return lsum - rsum;
|
||||
});
|
||||
|
||||
$.each(pick, function(idx, cardData) {
|
||||
cardData.iconPath = getIconPath(cardData.imgsvr, cardData.picture);
|
||||
if (cardData.special in specialInfo) {
|
||||
cardData.specialText = TemplateEngine(templateSpecial, {
|
||||
text: cardData.special,
|
||||
info: specialInfo[cardData.special]
|
||||
});
|
||||
} else {
|
||||
cardData.specialText = cardData.special;
|
||||
}
|
||||
|
||||
if (cardData.special2 in specialInfo) {
|
||||
cardData.special2Text = TemplateEngine(templateSpecial, {
|
||||
text: cardData.special2,
|
||||
info: specialInfo[cardData.special2]
|
||||
});
|
||||
} else {
|
||||
cardData.special2Text = cardData.special2;
|
||||
}
|
||||
|
||||
if (cardData.personal in characterInfo) {
|
||||
cardData.personalText = TemplateEngine(templateSpecial, {
|
||||
text: cardData.personal,
|
||||
info: characterInfo[cardData.personal]
|
||||
});
|
||||
} else {
|
||||
cardData.personalText = cardData.personal;
|
||||
}
|
||||
|
||||
|
||||
var $card = $(TemplateEngine(templateGeneralCard, cardData));
|
||||
|
||||
$('.card_holder').append($card);
|
||||
$card.find('.select_btn').click(pickGeneral);
|
||||
$card.find('.obj_tooltip').tooltip({
|
||||
title: function() {
|
||||
return $.trim($(this).find('.tooltiptext').html());
|
||||
},
|
||||
html: true
|
||||
});
|
||||
});
|
||||
|
||||
updatePickMoreTimer();
|
||||
updateOutdateTimer();
|
||||
}
|
||||
|
||||
function printGeneralList(value) {
|
||||
var tokenList = value.token;
|
||||
var generalList = $.map(value.list, function(general) {
|
||||
general = {
|
||||
no: general[0],
|
||||
picture: general[1],
|
||||
imgsvr: general[2],
|
||||
npc: general[3],
|
||||
age: general[4],
|
||||
nation: general[5],
|
||||
special: general[6],
|
||||
special2: general[7],
|
||||
personal: general[8],
|
||||
name: general[9],
|
||||
ownerName: general[10],
|
||||
injury: general[11],
|
||||
leadership: general[12],
|
||||
lbonus: general[13],
|
||||
strength: general[14],
|
||||
intel: general[15],
|
||||
explevel: general[16],
|
||||
experience: general[17],
|
||||
dedication: general[18],
|
||||
officerLevel: general[19],
|
||||
killturn: general[20],
|
||||
connect: general[21],
|
||||
reserved: 0
|
||||
};
|
||||
if (general.npc < 2) {
|
||||
general.reserved = 2;
|
||||
}
|
||||
if (general.no in tokenList) {
|
||||
general.reserved = 1;
|
||||
}
|
||||
|
||||
general.userCSS = "";
|
||||
general.nameAux = "";
|
||||
|
||||
if (general.reserved == 1) {
|
||||
general.userCSS = 'color:violet';
|
||||
} else if (general.npc >= 2) {
|
||||
general.userCSS = 'color:cyan';
|
||||
} else if (general.npc == 1) {
|
||||
general.userCSS = 'color:skyblue';
|
||||
}
|
||||
|
||||
if (general.ownerName) {
|
||||
general.nameAux += '<br><small>({0})</small>'.format(general.ownerName);
|
||||
}
|
||||
|
||||
if (general.reserved == 1) {
|
||||
general.nameAux += '<br><small>({0}회)</small>'.format(tokenList[general.no]);
|
||||
}
|
||||
|
||||
|
||||
general.total = general.leadership + general.strength + general.intel;
|
||||
general.iconPath = getIconPath(general.imgsvr, general.picture);
|
||||
|
||||
general.specialDomesticWithTooltip = TemplateEngine(templateSpecial, {
|
||||
text: general.special,
|
||||
info: specialInfo[general.special]
|
||||
});
|
||||
|
||||
general.speicalWarWithTooltip = TemplateEngine(templateSpecial, {
|
||||
text: general.special2,
|
||||
info: specialInfo[general.special2]
|
||||
});
|
||||
|
||||
general.personalWithTooltip = TemplateEngine(templateSpecial, {
|
||||
text: general.personal,
|
||||
info: characterInfo[general.personal]
|
||||
});
|
||||
|
||||
return general;
|
||||
});
|
||||
|
||||
generalList.sort(function(lhs, rhs) {
|
||||
if (lhs.reserved > rhs.reserved) {
|
||||
return -1;
|
||||
}
|
||||
if (lhs.reserved < rhs.reserved) {
|
||||
return 1;
|
||||
}
|
||||
if (lhs.total != rhs.total) {
|
||||
return rhs.total - lhs.total;
|
||||
}
|
||||
if (lhs.leadership != rhs.leadership) {
|
||||
return rhs.leadership - lhs.total;
|
||||
}
|
||||
|
||||
if (lhs.name < rhs.name) {
|
||||
return -1;
|
||||
}
|
||||
if (lhs.name > rhs.name) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
window.generalList = generalList;
|
||||
_printGeneralList(true);
|
||||
}
|
||||
|
||||
function _printGeneralList(clear) {
|
||||
var $generalTable = $('#general_list');
|
||||
if (clear) {
|
||||
$generalTable.empty();
|
||||
$generalTable.data('lastIdx', 0);
|
||||
$('#row_print_more').show();
|
||||
}
|
||||
|
||||
generalList = window.generalList;
|
||||
|
||||
var idxFrom = $generalTable.data('lastIdx');
|
||||
var idxTo = Math.min(idxFrom + 50, generalList.length);
|
||||
$generalTable.data('lastIdx', idxTo);
|
||||
|
||||
for (var idx = idxFrom; idx < idxFrom + 50; idx++) {
|
||||
var general = generalList[idx];
|
||||
$generalTable.append(TemplateEngine(templateGeneralRow, general));
|
||||
}
|
||||
|
||||
if (idxTo == generalList.length) {
|
||||
$('#row_print_more').hide();
|
||||
}
|
||||
|
||||
$generalTable.find('.obj_tooltip').tooltip({
|
||||
title: function() {
|
||||
return $.trim($(this).find('.tooltiptext').html());
|
||||
},
|
||||
html: true
|
||||
});
|
||||
$('#tb_general_list').show();
|
||||
}
|
||||
|
||||
$(function($) {
|
||||
window.generalList = [];
|
||||
|
||||
$.post('j_get_select_npc_token.php').then(function(value) {
|
||||
if (!value.result) {
|
||||
alert(value.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(value);
|
||||
printGenerals(value);
|
||||
});
|
||||
|
||||
$('#btn_pick_more').click(function() {
|
||||
var generals = $.map($('.keep_select:checked'), function(value) {
|
||||
return $(value).val();
|
||||
});
|
||||
console.log(generals);
|
||||
$.post({
|
||||
url: 'j_get_select_npc_token.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
refresh: true,
|
||||
keep: generals
|
||||
}
|
||||
}).then(function(result) {
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
location.refresh();
|
||||
}
|
||||
console.log(result);
|
||||
printGenerals(result);
|
||||
});
|
||||
});
|
||||
|
||||
$('#btn_load_general_list').click(function() {
|
||||
$.post({
|
||||
url: 'j_get_general_list.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
with_token: true
|
||||
}
|
||||
}).then(function(result) {
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
return false;
|
||||
}
|
||||
printGeneralList(result);
|
||||
});
|
||||
});
|
||||
|
||||
$('#btn_print_more').click(function() {
|
||||
_printGeneralList();
|
||||
})
|
||||
|
||||
});
|
||||
+74
-57
@@ -1,57 +1,74 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
/** @var \Composer\Autoload\ClassLoader $loader */
|
||||
$loader = require __DIR__.'/../vendor/autoload.php';
|
||||
$loader->addPsr4('sammo\\', __DIR__.'/sammo', true);
|
||||
|
||||
$loader->addClassMap((function () {
|
||||
$d_settingMap = [];
|
||||
foreach (glob(__DIR__.'/d_setting/*.orig.php') as $filepath) {
|
||||
$filepath = str_replace('.orig.php', '.php', $filepath);
|
||||
$filename = basename($filepath);
|
||||
$classname = explode('.', $filename)[0];
|
||||
$d_settingMap['sammo\\'.$classname] = $filepath;
|
||||
};
|
||||
return $d_settingMap;
|
||||
})());
|
||||
|
||||
|
||||
//디버그용 매크로
|
||||
ini_set("session.cache_expire", 10080); // minutes
|
||||
|
||||
// 각종 변수
|
||||
define('STEP_LOG', true);
|
||||
define('PROCESS_LOG', true);
|
||||
|
||||
ob_start();
|
||||
|
||||
// 에러 메세지 출력
|
||||
function Error($message='', $url="")
|
||||
{
|
||||
if (!$url) {
|
||||
$url = $_SERVER['REQUEST_URI'];
|
||||
}
|
||||
$e = new \Exception();
|
||||
logError("aux_err", $message, '', getExceptionTraceAsString($e));
|
||||
|
||||
$templates = new \League\Plates\Engine(__DIR__.'/templates');
|
||||
|
||||
ob_get_flush();
|
||||
WebUtil::setHeaderNoCache();
|
||||
|
||||
die($templates->render('error', [
|
||||
'message' => $message
|
||||
]));
|
||||
}
|
||||
|
||||
function MessageBox($str)
|
||||
{
|
||||
echo "<script>alert('$str');</script>";
|
||||
}
|
||||
|
||||
function LogText($prefix, $variable)
|
||||
{
|
||||
$text = sprintf('%s : %s'."\r\n", $prefix, TVarDumper::dump($variable));
|
||||
file_put_contents(ROOT.'/d_log/'.UniqueConst::$serverName.'_dbg_logs.txt', $text, FILE_APPEND);
|
||||
}
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
/** @var \Composer\Autoload\ClassLoader $loader */
|
||||
$loader = require __DIR__.'/../vendor/autoload.php';
|
||||
$loader->addPsr4('sammo\\', __DIR__.'/sammo', true);
|
||||
|
||||
$loader->addClassMap((function () {
|
||||
$d_settingMap = [];
|
||||
foreach (glob(__DIR__.'/d_setting/*.orig.php') as $filepath) {
|
||||
$filepath = str_replace('.orig.php', '.php', $filepath);
|
||||
$filename = basename($filepath);
|
||||
$classname = explode('.', $filename)[0];
|
||||
$d_settingMap['sammo\\'.$classname] = $filepath;
|
||||
};
|
||||
return $d_settingMap;
|
||||
})());
|
||||
|
||||
|
||||
//디버그용 매크로
|
||||
ini_set("session.cache_expire", 10080); // minutes
|
||||
|
||||
// 각종 변수
|
||||
define('STEP_LOG', true);
|
||||
define('PROCESS_LOG', true);
|
||||
|
||||
ob_start();
|
||||
|
||||
// 에러 메세지 출력
|
||||
function Error($message='', $url="")
|
||||
{
|
||||
if (!$url) {
|
||||
$url = $_SERVER['REQUEST_URI'];
|
||||
}
|
||||
$e = new \Exception();
|
||||
logError("aux_err", $message, '', getExceptionTraceAsString($e));
|
||||
|
||||
$templates = new \League\Plates\Engine(__DIR__.'/templates');
|
||||
|
||||
ob_get_flush();
|
||||
WebUtil::setHeaderNoCache();
|
||||
|
||||
die($templates->render('error', [
|
||||
'message' => $message
|
||||
]));
|
||||
}
|
||||
|
||||
function MessageBox($str)
|
||||
{
|
||||
echo "<script>alert('$str');</script>";
|
||||
}
|
||||
|
||||
function LogText($prefix, $variable)
|
||||
{
|
||||
$text = sprintf('%s : %s'."\r\n", $prefix, TVarDumper::dump($variable));
|
||||
file_put_contents(ROOT.'/d_log/'.UniqueConst::$serverName.'_dbg_logs.txt', $text, FILE_APPEND);
|
||||
}
|
||||
|
||||
function prepareDir(string $dirPath, bool $forceCreate=true):bool{
|
||||
if(file_exists($dirPath)){
|
||||
if(is_dir($dirPath)){
|
||||
return true;
|
||||
}
|
||||
if(!$forceCreate){
|
||||
throw new \RuntimeException('이미 파일이 있습니다');
|
||||
}
|
||||
if(!unlink($dirPath)){
|
||||
return false;
|
||||
}
|
||||
return mkdir($dirPath);
|
||||
}
|
||||
|
||||
return mkdir($dirPath, 0777, true);
|
||||
}
|
||||
@@ -1,22 +1,32 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class che_계략_삼략 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 22;
|
||||
protected $rawName = '삼략';
|
||||
protected $name = '삼략(계략)';
|
||||
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if($turnType == '계략'){
|
||||
if($varType == 'success') return $value + 0.2;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class che_계략_삼략 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 22;
|
||||
protected $rawName = '삼략';
|
||||
protected $name = '삼략(계략)';
|
||||
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p<br>[전투] 계략 시도 확률 +10%p, 계략 성공 확률 +10%p';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if($turnType == '계략'){
|
||||
if($varType == 'success') return $value + 0.2;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'warMagicTrialProb'){
|
||||
return $value + 0.1;
|
||||
}
|
||||
if($statName === 'warMagicSuccessProb'){
|
||||
return $value + 0.1;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,32 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class che_계략_육도 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 21;
|
||||
protected $rawName = '육도';
|
||||
protected $name = '육도(계략)';
|
||||
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if($turnType == '계략'){
|
||||
if($varType == 'success') return $value + 0.2;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class che_계략_육도 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 21;
|
||||
protected $rawName = '육도';
|
||||
protected $name = '육도(계략)';
|
||||
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p<br>[전투] 계략 시도 확률 +10%p, 계략 성공 확률 +10%p';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if($turnType == '계략'){
|
||||
if($varType == 'success') return $value + 0.2;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'warMagicTrialProb'){
|
||||
return $value + 0.1;
|
||||
}
|
||||
if($statName === 'warMagicSuccessProb'){
|
||||
return $value + 0.1;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,31 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class che_계략_이추 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 5;
|
||||
protected $rawName = '이추';
|
||||
protected $name = '이추(계략)';
|
||||
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +10%p';
|
||||
protected $cost = 1000;
|
||||
protected $consumable = true;
|
||||
protected $buyable = true;
|
||||
protected $reqSecu = 1000;
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if($turnType == '계략'){
|
||||
if($varType == 'success') return $value + 0.1;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
function isConsumableNow(string $actionType, string $command):bool{
|
||||
if($actionType == 'GeneralCommand' && $command == '계략'){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class che_계략_이추 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 5;
|
||||
protected $rawName = '이추';
|
||||
protected $name = '이추(계략)';
|
||||
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p';
|
||||
protected $cost = 1000;
|
||||
protected $consumable = true;
|
||||
protected $buyable = true;
|
||||
protected $reqSecu = 1000;
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if($turnType == '계략'){
|
||||
if($varType == 'success') return $value + 0.2;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
function isConsumableNow(string $actionType, string $command):bool{
|
||||
if($actionType == 'GeneralCommand' && $command == '계략'){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,31 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class che_계략_향낭 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 5;
|
||||
protected $rawName = '항냥';
|
||||
protected $name = '항냥(계략)';
|
||||
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p';
|
||||
protected $cost = 3000;
|
||||
protected $consumable = true;
|
||||
protected $buyable = true;
|
||||
protected $reqSecu = 2000;
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if($turnType == '계략'){
|
||||
if($varType == 'success') return $value + 0.2;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
function isConsumableNow(string $actionType, string $command):bool{
|
||||
if($actionType == 'GeneralCommand' && $command == '계략'){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class che_계략_향낭 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 5;
|
||||
protected $rawName = '항냥';
|
||||
protected $name = '항냥(계략)';
|
||||
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +50%p';
|
||||
protected $cost = 3000;
|
||||
protected $consumable = true;
|
||||
protected $buyable = true;
|
||||
protected $reqSecu = 2000;
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if($turnType == '계략'){
|
||||
if($varType == 'success') return $value + 0.5;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
function isConsumableNow(string $actionType, string $command):bool{
|
||||
if($actionType == 'GeneralCommand' && $command == '계략'){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use \sammo\BaseWarUnitTrigger;
|
||||
use \sammo\WarUnitTrigger\WarActivateSkills;
|
||||
use \sammo\WarUnitTrigger\che_반계시도;
|
||||
use \sammo\WarUnitTrigger\che_반계발동;
|
||||
|
||||
class che_반계_백우선 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 45;
|
||||
protected $rawName = '백우선';
|
||||
protected $name = '백우선(반계)';
|
||||
protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '계략약화'),
|
||||
new che_반계시도($unit),
|
||||
new che_반계발동($unit)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use \sammo\BaseWarUnitTrigger;
|
||||
use \sammo\WarUnitTrigger\WarActivateSkills;
|
||||
use \sammo\WarUnitTrigger\che_반계시도;
|
||||
use \sammo\WarUnitTrigger\che_반계발동;
|
||||
|
||||
class che_반계_파초선 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 45;
|
||||
protected $rawName = '파초선';
|
||||
protected $name = '파초선(반계)';
|
||||
protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '계략약화'),
|
||||
new che_반계시도($unit),
|
||||
new che_반계발동($unit)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\GeneralTrigger;
|
||||
use \sammo\GeneralTriggerCaller;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use sammo\BaseWarUnitTrigger;
|
||||
use sammo\WarUnitTrigger\che_부상무효;
|
||||
use sammo\WarUnitTrigger\WarActivateSkills;
|
||||
|
||||
class che_부적_태현청생부 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 9;
|
||||
protected $rawName = '태현청생부';
|
||||
protected $name = '태현청생부(부적)';
|
||||
protected $info = '[전투] 저격 불가, 부상 없음';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_부상무효($unit, BaseWarUnitTrigger::TYPE_NONE),
|
||||
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '저격불가')
|
||||
);
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '저격불가')
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\GeneralTrigger;
|
||||
use \sammo\GeneralTriggerCaller;
|
||||
use \sammo\BaseWarUnitTrigger;
|
||||
use \sammo\WarUnitTriggerCaller;
|
||||
use sammo\WarUnitTrigger\che_전투치료발동;
|
||||
use sammo\WarUnitTrigger\che_전투치료시도;
|
||||
|
||||
class che_의술_상한잡병론 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 24;
|
||||
protected $rawName = '상한잡병론';
|
||||
protected $name = '상한잡병론(의술)';
|
||||
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
|
||||
return new GeneralTriggerCaller(
|
||||
new GeneralTrigger\che_도시치료($general)
|
||||
);
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
|
||||
{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
|
||||
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,35 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\GeneralTrigger;
|
||||
use \sammo\GeneralTriggerCaller;
|
||||
use sammo\WarUnitTrigger\che_전투치료발동;
|
||||
use sammo\WarUnitTrigger\che_전투치료시도;
|
||||
use sammo\BaseWarUnitTrigger;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
|
||||
class che_의술_청낭서 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 23;
|
||||
protected $rawName = '청낭서';
|
||||
protected $name = '청낭서(의술)';
|
||||
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
|
||||
return new GeneralTriggerCaller(
|
||||
new GeneralTrigger\che_도시치료($general)
|
||||
);
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
|
||||
{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
|
||||
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
|
||||
|
||||
);
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\GeneralTrigger;
|
||||
use \sammo\GeneralTriggerCaller;
|
||||
use sammo\WarUnitTrigger\che_전투치료발동;
|
||||
use sammo\WarUnitTrigger\che_전투치료시도;
|
||||
use sammo\BaseWarUnitTrigger;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
|
||||
class che_의술_청낭서 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 23;
|
||||
protected $rawName = '청낭서';
|
||||
protected $name = '청낭서(의술)';
|
||||
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
|
||||
return new GeneralTriggerCaller(
|
||||
new GeneralTrigger\che_도시치료($general)
|
||||
);
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
|
||||
{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
|
||||
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,35 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\GeneralTrigger;
|
||||
use \sammo\GeneralTriggerCaller;
|
||||
use \sammo\BaseWarUnitTrigger;
|
||||
use \sammo\WarUnitTriggerCaller;
|
||||
use sammo\WarUnitTrigger\che_전투치료발동;
|
||||
use sammo\WarUnitTrigger\che_전투치료시도;
|
||||
|
||||
class che_의술_태평청령 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 24;
|
||||
protected $rawName = '태평청령';
|
||||
protected $name = '태평청령(의술)';
|
||||
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
|
||||
return new GeneralTriggerCaller(
|
||||
new GeneralTrigger\che_도시치료($general)
|
||||
);
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
|
||||
{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
|
||||
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
|
||||
|
||||
);
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\GeneralTrigger;
|
||||
use \sammo\GeneralTriggerCaller;
|
||||
use \sammo\BaseWarUnitTrigger;
|
||||
use \sammo\WarUnitTriggerCaller;
|
||||
use sammo\WarUnitTrigger\che_전투치료발동;
|
||||
use sammo\WarUnitTrigger\che_전투치료시도;
|
||||
|
||||
class che_의술_태평청령 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 24;
|
||||
protected $rawName = '태평청령';
|
||||
protected $name = '태평청령(의술)';
|
||||
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
|
||||
return new GeneralTriggerCaller(
|
||||
new GeneralTrigger\che_도시치료($general)
|
||||
);
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
|
||||
{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
|
||||
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use \sammo\WarUnitTrigger\che_저격시도;
|
||||
use \sammo\WarUnitTrigger\che_저격발동;
|
||||
|
||||
class che_저격_매화수전 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 70;
|
||||
protected $rawName = '매화수전';
|
||||
protected $name = '매화수전(저격)';
|
||||
protected $info = '[전투] 새로운 상대와 전투 시 50% 확률로 저격 발동, 성공 시 사기+10';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_저격시도($unit, che_저격시도::TYPE_ITEM, 0.5, 20, 40),
|
||||
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use \sammo\WarUnitTrigger\che_저격시도;
|
||||
use \sammo\WarUnitTrigger\che_저격발동;
|
||||
|
||||
class che_저격_비도 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 70;
|
||||
protected $rawName = '비도';
|
||||
protected $name = '비도(저격)';
|
||||
protected $info = '[전투] 새로운 상대와 전투 시 50% 확률로 저격 발동, 성공 시 사기+10';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_저격시도($unit, che_저격시도::TYPE_ITEM, 0.5, 20, 40),
|
||||
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,28 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\WarUnitTriggerCaller;
|
||||
use \sammo\WarUnit;
|
||||
use \sammo\WarUnitTrigger\che_저격시도;
|
||||
use \sammo\WarUnitTrigger\che_저격발동;
|
||||
use \sammo\BaseWarUnitTrigger;
|
||||
|
||||
class che_저격_수극 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 2;
|
||||
protected $rawName = '수극';
|
||||
protected $name = '수극(저격)';
|
||||
protected $info = '[전투] 전투 개시 전 20% 확률로 저격 시도. 1회용';
|
||||
protected $cost = 1000;
|
||||
protected $consumable = true;
|
||||
protected $buyable = true;
|
||||
protected $reqSecu = 1000;
|
||||
|
||||
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_저격시도($unit, BaseWarUnitTrigger::TYPE_CONSUMABLE_ITEM, 0.2, 20, 40),
|
||||
new che_저격발동($unit)
|
||||
);
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\WarUnitTriggerCaller;
|
||||
use \sammo\WarUnit;
|
||||
use \sammo\WarUnitTrigger\che_저격시도;
|
||||
use \sammo\WarUnitTrigger\che_저격발동;
|
||||
use \sammo\BaseWarUnitTrigger;
|
||||
|
||||
class che_저격_수극 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 2;
|
||||
protected $rawName = '수극';
|
||||
protected $name = '수극(저격)';
|
||||
protected $info = '[전투] 전투 개시 전 50% 확률로 저격 시도. 1회용';
|
||||
protected $cost = 1000;
|
||||
protected $consumable = true;
|
||||
protected $buyable = true;
|
||||
protected $reqSecu = 1000;
|
||||
|
||||
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_저격시도($unit, BaseWarUnitTrigger::TYPE_CONSUMABLE_ITEM, 0.5, 20, 40),
|
||||
new che_저격발동($unit)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class che_행동_서촉지형도 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 22;
|
||||
protected $rawName = '서촉지형도';
|
||||
protected $name = '서촉지형도(행동)';
|
||||
protected $info = '[전투] 공격 시 페이즈 + 2';
|
||||
protected $cost = 200;
|
||||
protected $consumable = false;
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'initWarPhase'){
|
||||
return $value + 2;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ class event_전투특기_격노 extends \sammo\BaseItem{
|
||||
protected $id = 74;
|
||||
protected $rawName = '비급';
|
||||
protected $name = '비급(격노)';
|
||||
protected $info = '[전투] 상대방 필살 및 회피 시도시 일정 확률로 격노(필살) 발동, 공격 시 일정 확률로 진노(1페이즈 추가)';
|
||||
protected $info = '[전투] 상대방 필살 시 격노(필살) 발동, 회피 시도시 25% 확률로 격노 발동, 공격 시 일정 확률로 진노(1페이즈 추가)';
|
||||
protected $cost = 100;
|
||||
protected $buyable = true;
|
||||
protected $consumable = false;
|
||||
|
||||
@@ -12,7 +12,7 @@ class event_전투특기_공성 extends \sammo\BaseItem{
|
||||
protected $id = 53;
|
||||
protected $rawName = '비급';
|
||||
protected $name = '비급(공성)';
|
||||
protected $info = '[군사] 차병 계통 징·모병비 -10%<br>[전투] 성벽 공격 시 대미지 +100%';
|
||||
protected $info = '[군사] 차병 계통 징·모병비 -10%<br>[전투] 성벽 공격 시 대미지 +100%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 차병 숙련을 가산';
|
||||
protected $cost = 100;
|
||||
protected $buyable = true;
|
||||
protected $consumable = false;
|
||||
@@ -32,4 +32,18 @@ class event_전투특기_공성 extends \sammo\BaseItem{
|
||||
}
|
||||
return [1, 1];
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
||||
$myArmType = 'dex'.GameUnitConst::T_SIEGE;
|
||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
if(!$aux['isAttacker'] && $myArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ class event_전투특기_궁병 extends \sammo\BaseItem{
|
||||
protected $id = 51;
|
||||
protected $rawName = '비급';
|
||||
protected $name = '비급(궁병)';
|
||||
protected $info = '[군사] 궁병 계통 징·모병비 -10%<br>[전투] 회피 확률 +20%p';
|
||||
protected $info = '[군사] 궁병 계통 징·모병비 -10%<br>[전투] 회피 확률 +20%p,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 궁병 숙련을 가산';
|
||||
protected $cost = 100;
|
||||
protected $buyable = true;
|
||||
protected $consumable = false;
|
||||
@@ -29,6 +29,16 @@ class event_전투특기_궁병 extends \sammo\BaseItem{
|
||||
if($statName === 'warAvoidRatio'){
|
||||
return $value + 0.2;
|
||||
}
|
||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
||||
$myArmType = 'dex'.GameUnitConst::T_ARCHER;
|
||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
if(!$aux['isAttacker'] && $myArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ class event_전투특기_귀병 extends \sammo\BaseItem{
|
||||
protected $id = 40;
|
||||
protected $rawName = '비급';
|
||||
protected $name = '비급(귀병)';
|
||||
protected $info = '[군사] 귀병 계통 징·모병비 -10%<br>[전투] 계략 성공 확률 +20%p';
|
||||
protected $info = '[군사] 귀병 계통 징·모병비 -10%<br>[전투] 계략 성공 확률 +20%p,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 귀병 숙련을 가산';
|
||||
protected $cost = 100;
|
||||
protected $buyable = true;
|
||||
protected $consumable = false;
|
||||
@@ -29,6 +29,16 @@ class event_전투특기_귀병 extends \sammo\BaseItem{
|
||||
if($statName === 'warMagicSuccessProb'){
|
||||
return $value + 0.2;
|
||||
}
|
||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
||||
$myArmType = 'dex'.GameUnitConst::T_WIZARD;
|
||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
if(!$aux['isAttacker'] && $myArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ class event_전투특기_기병 extends \sammo\BaseItem{
|
||||
protected $id = 52;
|
||||
protected $rawName = '비급';
|
||||
protected $name = '비급(기병)';
|
||||
protected $info = '[군사] 기병 계통 징·모병비 -10%<br>[전투] 수비 시 대미지 +10%, 공격 시 대미지 +20%';
|
||||
protected $info = '[군사] 기병 계통 징·모병비 -10%<br>[전투] 수비 시 대미지 +10%, 공격 시 대미지 +20%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 기병 숙련을 가산';
|
||||
protected $cost = 100;
|
||||
protected $buyable = true;
|
||||
protected $consumable = false;
|
||||
@@ -31,4 +31,18 @@ class event_전투특기_기병 extends \sammo\BaseItem{
|
||||
}
|
||||
return [1.1, 1];
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
||||
$myArmType = 'dex'.GameUnitConst::T_CAVALRY;
|
||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
if(!$aux['isAttacker'] && $myArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -7,13 +7,14 @@ use \sammo\WarUnit;
|
||||
use \sammo\BaseWarUnitTrigger;
|
||||
use \sammo\WarUnitTriggerCaller;
|
||||
use sammo\WarUnitTrigger\WarActivateSkills;
|
||||
use \sammo\WarUnitTrigger\che_돌격지속;
|
||||
|
||||
class event_전투특기_돌격 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 60;
|
||||
protected $rawName = '비급';
|
||||
protected $name = '비급(돌격)';
|
||||
protected $info = '[전투] 상대 회피 불가, 공격 시 전투 페이즈 +1, 공격 시 대미지 +10%';
|
||||
protected $info = '[전투] 공격 시 대등/유리한 병종에게는 퇴각 전까지 전투, 공격 시 페이즈 + 2, 공격 시 대미지 +5%';
|
||||
protected $cost = 100;
|
||||
protected $buyable = true;
|
||||
protected $consumable = false;
|
||||
@@ -21,21 +22,20 @@ class event_전투특기_돌격 extends \sammo\BaseItem{
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'initWarPhase'){
|
||||
return $value + 1;
|
||||
return $value + 2;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
if($unit->isAttacker()){
|
||||
return [1.1, 1];
|
||||
return [1.05, 1];
|
||||
}
|
||||
return [1, 1];
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
(new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '회피불가'))->setPriority(BaseWarUnitTrigger::PRIORITY_BEGIN + 200)
|
||||
new che_돌격지속($unit)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,13 +4,14 @@ use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use \sammo\Util;
|
||||
|
||||
class event_전투특기_무쌍 extends \sammo\BaseItem{
|
||||
|
||||
protected $id = 61;
|
||||
protected $rawName = '비급';
|
||||
protected $name = '비급(무쌍)';
|
||||
protected $info = '[전투] 대미지 +10%, 공격 시 필살 확률 +10%p';
|
||||
protected $info = '[전투] 대미지 +10%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대50%)';
|
||||
protected $cost = 100;
|
||||
protected $buyable = true;
|
||||
protected $consumable = false;
|
||||
@@ -24,6 +25,11 @@ class event_전투특기_무쌍 extends \sammo\BaseItem{
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
return [1.1, 1];
|
||||
$attackMultiplier = 1.1;
|
||||
$defenceMultiplier = 1;
|
||||
$killnum = $unit->getGeneral()->getRankVar('killnum');
|
||||
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4);
|
||||
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.5);
|
||||
return [$attackMultiplier, $defenceMultiplier];
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ class event_전투특기_반계 extends \sammo\BaseItem{
|
||||
protected $id = 45;
|
||||
protected $rawName = '비급';
|
||||
protected $name = '비급(반계)';
|
||||
protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림, 반목 성공시 대미지 추가(+60% → +100%)';
|
||||
protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림, 반목 성공시 대미지 추가(+60% → +150%)';
|
||||
protected $cost = 100;
|
||||
protected $buyable = true;
|
||||
protected $consumable = false;
|
||||
@@ -23,15 +23,15 @@ class event_전투특기_반계 extends \sammo\BaseItem{
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'warMagicSuccessDamage' && $aux === '반목'){
|
||||
return $value + 0.4;
|
||||
return $value + 0.9;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM, false, '계략약화'),
|
||||
new che_반계시도($unit, che_반계시도::TYPE_ITEM),
|
||||
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '계략약화'),
|
||||
new che_반계시도($unit),
|
||||
new che_반계발동($unit)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ class event_전투특기_보병 extends \sammo\BaseItem{
|
||||
protected $id = 50;
|
||||
protected $rawName = '비급';
|
||||
protected $name = '비급(보병)';
|
||||
protected $info = '[군사] 보병 계통 징·모병비 -10%<br>[전투] 공격 시 아군 피해 -10%, 수비 시 아군 피해 -20%';
|
||||
protected $info = '[군사] 보병 계통 징·모병비 -10%<br>[전투] 공격 시 아군 피해 -10%, 수비 시 아군 피해 -20%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 보병 숙련을 가산';
|
||||
protected $cost = 100;
|
||||
protected $buyable = true;
|
||||
protected $consumable = false;
|
||||
@@ -32,4 +32,18 @@ class event_전투특기_보병 extends \sammo\BaseItem{
|
||||
}
|
||||
return [1, 0.8];
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
||||
$myArmType = 'dex'.GameUnitConst::T_FOOTMAN;
|
||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
if(!$aux['isAttacker'] && $myArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ class event_전투특기_위압 extends \sammo\BaseItem{
|
||||
protected $id = 63;
|
||||
protected $rawName = '비급';
|
||||
protected $name = '비급(위압)';
|
||||
protected $info = '[전투] 훈련/사기≥90, 병력≥1,000 일 때 첫 페이즈 위압 발동(적 공격 불가)';
|
||||
protected $info = '[전투] 첫 페이즈 위압 발동(적 공격, 회피 불가, 사기 5 감소)';
|
||||
protected $cost = 100;
|
||||
protected $buyable = true;
|
||||
protected $consumable = false;
|
||||
|
||||
@@ -16,7 +16,7 @@ class event_전투특기_의술 extends \sammo\BaseItem{
|
||||
protected $id = 73;
|
||||
protected $rawName = '비급';
|
||||
protected $name = '비급(의술)';
|
||||
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)';
|
||||
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
|
||||
protected $cost = 100;
|
||||
protected $buyable = true;
|
||||
protected $consumable = false;
|
||||
|
||||
@@ -13,7 +13,7 @@ class event_전투특기_저격 extends \sammo\BaseItem{
|
||||
protected $id = 70;
|
||||
protected $rawName = '비급';
|
||||
protected $name = '비급(저격)';
|
||||
protected $info = '[전투] 새로운 상대와 전투 시 1/3 확률로 저격 발동, 성공 시 사기+10';
|
||||
protected $info = '[전투] 새로운 상대와 전투 시 50% 확률로 저격 발동, 성공 시 사기+10';
|
||||
protected $cost = 100;
|
||||
protected $buyable = true;
|
||||
protected $consumable = false;
|
||||
@@ -21,7 +21,7 @@ class event_전투특기_저격 extends \sammo\BaseItem{
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_저격시도($unit, che_저격시도::TYPE_ITEM, 1/3, 20, 60),
|
||||
new che_저격시도($unit, che_저격시도::TYPE_ITEM, 0.5, 20, 40),
|
||||
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class event_전투특기_필살 extends \sammo\BaseItem{
|
||||
protected $id = 71;
|
||||
protected $rawName = '비급';
|
||||
protected $name = '비급(필살)';
|
||||
protected $info = '[전투] 필살 확률 +20%p, 필살 발동시 대상 회피 불가';
|
||||
protected $info = '[전투] 필살 확률 +30%p, 필살 발동시 대상 회피 불가';
|
||||
protected $cost = 100;
|
||||
protected $buyable = true;
|
||||
protected $consumable = false;
|
||||
@@ -20,7 +20,7 @@ class event_전투특기_필살 extends \sammo\BaseItem{
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'warCriticalRatio'){
|
||||
return $value + 0.2;
|
||||
return $value + 0.3;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
@@ -1,42 +1,45 @@
|
||||
<?php
|
||||
namespace sammo\ActionNationType;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\Util;
|
||||
|
||||
class che_종횡가 extends \sammo\BaseNation{
|
||||
|
||||
protected $name = '종횡가';
|
||||
protected $info = '';
|
||||
static $pros = '전략↑ 수성↑';
|
||||
static $cons = '금수입↓ 내정↓';
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if($turnType == '수비' || $turnType == '성벽'){
|
||||
if($varType == 'score') return $value * 1.1;
|
||||
if($varType == 'cost') return $value * 0.8;
|
||||
}
|
||||
|
||||
else if($turnType == '농업' || $turnType == '상업'){
|
||||
if($varType == 'score') return $value * 0.9;
|
||||
if($varType == 'cost') return $value * 1.2;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onCalcNationalIncome(string $type, $amount){
|
||||
if($type == 'gold'){
|
||||
return $amount * 0.9;
|
||||
}
|
||||
|
||||
return $amount;
|
||||
}
|
||||
|
||||
public function onCalcStrategic(string $turnType, string $varType, $value){
|
||||
if($varType == 'delay'){
|
||||
return Util::round($value / 2);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionNationType;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\Util;
|
||||
|
||||
class che_종횡가 extends \sammo\BaseNation{
|
||||
|
||||
protected $name = '종횡가';
|
||||
protected $info = '';
|
||||
static $pros = '전략↑ 수성↑';
|
||||
static $cons = '금수입↓ 내정↓';
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if($turnType == '수비' || $turnType == '성벽'){
|
||||
if($varType == 'score') return $value * 1.1;
|
||||
if($varType == 'cost') return $value * 0.8;
|
||||
}
|
||||
|
||||
else if($turnType == '농업' || $turnType == '상업'){
|
||||
if($varType == 'score') return $value * 0.9;
|
||||
if($varType == 'cost') return $value * 1.2;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onCalcNationalIncome(string $type, $amount){
|
||||
if($type == 'gold'){
|
||||
return $amount * 0.9;
|
||||
}
|
||||
|
||||
return $amount;
|
||||
}
|
||||
|
||||
public function onCalcStrategic(string $turnType, string $varType, $value){
|
||||
if($varType == 'delay'){
|
||||
return Util::round($value / 2);
|
||||
}
|
||||
if($varType == 'globalDelay'){
|
||||
return Util::round($value / 2);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,34 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use sammo\WarUnitTrigger\che_격노시도;
|
||||
use sammo\WarUnitTrigger\che_격노발동;
|
||||
|
||||
class che_격노 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 74;
|
||||
protected $name = '격노';
|
||||
protected $info = '[전투] 상대방 필살 및 회피 시도시 일정 확률로 격노(필살) 발동, 공격 시 일정 확률로 진노(1페이즈 추가)';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_STRENGTH,
|
||||
];
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_격노시도($unit),
|
||||
new che_격노발동($unit)
|
||||
);
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use sammo\WarUnitTrigger\che_격노시도;
|
||||
use sammo\WarUnitTrigger\che_격노발동;
|
||||
|
||||
class che_격노 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 74;
|
||||
protected $name = '격노';
|
||||
protected $info = '[전투] 상대방 필살 시 격노(필살) 발동, 회피 시도시 25% 확률로 격노 발동, 공격 시 일정 확률로 진노(1페이즈 추가), 격노마다 대미지 20% 추가 중첩';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_STRENGTH,
|
||||
];
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
$activatedCnt = $unit->hasActivatedSkillOnLog('격노');
|
||||
return [1 + 0.2*$activatedCnt, 1];
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_격노시도($unit),
|
||||
new che_격노발동($unit)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,40 +1,40 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use sammo\BaseWarUnitTrigger;
|
||||
use sammo\WarUnitTrigger\che_부상무효;
|
||||
use sammo\WarUnitTrigger\WarActivateSkills;
|
||||
|
||||
class che_견고 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 62;
|
||||
protected $name = '견고';
|
||||
protected $info = '[전투] 상대 필살, 격노, 위압, 저격 불가, 상대 계략 시도시 성공 확률 -10%p, 부상 없음, 아군 피해 -5%';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_STRENGTH
|
||||
];
|
||||
|
||||
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_부상무효($unit, BaseWarUnitTrigger::TYPE_NONE),
|
||||
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '저격불가')
|
||||
);
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '필살불가', '위압불가', '격노불가', '계략약화', '저격불가')
|
||||
);
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
return [1, 0.95];
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use sammo\BaseWarUnitTrigger;
|
||||
use sammo\WarUnitTrigger\che_부상무효;
|
||||
use sammo\WarUnitTrigger\WarActivateSkills;
|
||||
|
||||
class che_견고 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 62;
|
||||
protected $name = '견고';
|
||||
protected $info = '[전투] 상대 필살, 저격 불가, 상대 계략 시도시 성공 확률 -10%p, 부상 없음, 아군 피해 -10%';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_STRENGTH
|
||||
];
|
||||
|
||||
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_부상무효($unit, BaseWarUnitTrigger::TYPE_NONE),
|
||||
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '저격불가')
|
||||
);
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '필살불가', '계략약화', '저격불가')
|
||||
);
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
return [1, 0.9];
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,50 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\GameUnitConst;
|
||||
use \sammo\WarUnit;
|
||||
use \sammo\WarUnitCity;
|
||||
|
||||
class che_공성 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 53;
|
||||
protected $name = '공성';
|
||||
protected $info = '[군사] 차병 계통 징·모병비 -10%<br>[전투] 성벽 공격 시 대미지 +100%';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_SIEGE,
|
||||
];
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if(in_array($turnType, ['징병', '모병'])){
|
||||
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_SIEGE) return $value * 0.9;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
if($unit->getOppose() instanceof WarUnitCity){
|
||||
return [2, 1];
|
||||
}
|
||||
return [1, 1];
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\GameUnitConst;
|
||||
use \sammo\WarUnit;
|
||||
use \sammo\WarUnitCity;
|
||||
|
||||
class che_공성 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 53;
|
||||
protected $name = '공성';
|
||||
protected $info = '[군사] 차병 계통 징·모병비 -10%<br>[전투] 성벽 공격 시 대미지 +100%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 차병 숙련을 가산';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_SIEGE,
|
||||
];
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if(in_array($turnType, ['징병', '모병'])){
|
||||
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_SIEGE) return $value * 0.9;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
if($unit->getOppose() instanceof WarUnitCity){
|
||||
return [2, 1];
|
||||
}
|
||||
return [1, 1];
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
||||
$myArmType = 'dex'.GameUnitConst::T_SIEGE;
|
||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
if(!$aux['isAttacker'] && $myArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ class che_궁병 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 51;
|
||||
protected $name = '궁병';
|
||||
protected $info = '[군사] 궁병 계통 징·모병비 -10%<br>[전투] 회피 확률 +20%p';
|
||||
protected $info = '[군사] 궁병 계통 징·모병비 -10%<br>[전투] 회피 확률 +20%p,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 궁병 숙련을 가산';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
@@ -31,6 +31,16 @@ class che_궁병 extends \sammo\BaseSpecial{
|
||||
if($statName === 'warAvoidRatio'){
|
||||
return $value + 0.2;
|
||||
}
|
||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
||||
$myArmType = 'dex'.GameUnitConst::T_ARCHER;
|
||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
if(!$aux['isAttacker'] && $myArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,45 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\GameUnitConst;
|
||||
use \sammo\WarUnit;
|
||||
|
||||
class che_귀병 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 40;
|
||||
protected $name = '귀병';
|
||||
protected $info = '[군사] 귀병 계통 징·모병비 -10%<br>[전투] 계략 성공 확률 +20%p';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_INTEL | SpecialityHelper::ARMY_WIZARD | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::STAT_NOT_STRENGTH
|
||||
];
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if(in_array($turnType, ['징병', '모병'])){
|
||||
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_WIZARD) return $value * 0.9;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'warMagicSuccessProb'){
|
||||
return $value + 0.2;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\GameUnitConst;
|
||||
use \sammo\WarUnit;
|
||||
|
||||
class che_귀병 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 40;
|
||||
protected $name = '귀병';
|
||||
protected $info = '[군사] 귀병 계통 징·모병비 -10%<br>[전투] 계략 성공 확률 +20%p,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 귀병 숙련을 가산';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_INTEL | SpecialityHelper::ARMY_WIZARD | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::STAT_NOT_STRENGTH
|
||||
];
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if(in_array($turnType, ['징병', '모병'])){
|
||||
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_WIZARD) return $value * 0.9;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'warMagicSuccessProb'){
|
||||
return $value + 0.2;
|
||||
}
|
||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
||||
$myArmType = 'dex'.GameUnitConst::T_WIZARD;
|
||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
if(!$aux['isAttacker'] && $myArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,50 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\GameUnitConst;
|
||||
use \sammo\WarUnit;
|
||||
|
||||
class che_기병 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 52;
|
||||
protected $name = '기병';
|
||||
protected $info = '[군사] 기병 계통 징·모병비 -10%<br>[전투] 수비 시 대미지 +10%, 공격 시 대미지 +20%';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_CAVALRY | SpecialityHelper::STAT_NOT_INTEL,
|
||||
SpecialityHelper::STAT_STRENGTH | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_CAVALRY
|
||||
];
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if(in_array($turnType, ['징병', '모병'])){
|
||||
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_CAVALRY) return $value * 0.9;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
if($unit->isAttacker()){
|
||||
return [1.2, 1];
|
||||
}
|
||||
return [1.1, 1];
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\GameUnitConst;
|
||||
use \sammo\WarUnit;
|
||||
|
||||
class che_기병 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 52;
|
||||
protected $name = '기병';
|
||||
protected $info = '[군사] 기병 계통 징·모병비 -10%<br>[전투] 수비 시 대미지 +10%, 공격 시 대미지 +20%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 기병 숙련을 가산';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_CAVALRY | SpecialityHelper::STAT_NOT_INTEL,
|
||||
SpecialityHelper::STAT_STRENGTH | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_CAVALRY
|
||||
];
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if(in_array($turnType, ['징병', '모병'])){
|
||||
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_CAVALRY) return $value * 0.9;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
if($unit->isAttacker()){
|
||||
return [1.2, 1];
|
||||
}
|
||||
return [1.1, 1];
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
||||
$myArmType = 'dex'.GameUnitConst::T_CAVALRY;
|
||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
if(!$aux['isAttacker'] && $myArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,42 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use \sammo\BaseWarUnitTrigger;
|
||||
use \sammo\WarUnitTriggerCaller;
|
||||
use sammo\WarUnitTrigger\WarActivateSkills;
|
||||
|
||||
class che_돌격 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 60;
|
||||
protected $name = '돌격';
|
||||
protected $info = '[전투] 상대 회피 불가, 공격 시 전투 페이즈 +1, 공격 시 대미지 +10%';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_STRENGTH
|
||||
];
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'initWarPhase'){
|
||||
return $value + 1;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
if($unit->isAttacker()){
|
||||
return [1.1, 1];
|
||||
}
|
||||
return [1, 1];
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
(new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '회피불가'))->setPriority(BaseWarUnitTrigger::PRIORITY_BEGIN + 200)
|
||||
);
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use \sammo\BaseWarUnitTrigger;
|
||||
use \sammo\WarUnitTriggerCaller;
|
||||
use sammo\WarUnitTrigger\WarActivateSkills;
|
||||
use \sammo\WarUnitTrigger\che_돌격지속;
|
||||
|
||||
class che_돌격 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 60;
|
||||
protected $name = '돌격';
|
||||
protected $info = '[전투] 공격 시 대등/유리한 병종에게는 퇴각 전까지 전투, 공격 시 페이즈 + 2, 공격 시 대미지 +5%';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_STRENGTH
|
||||
];
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'initWarPhase'){
|
||||
return $value + 2;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
if($unit->isAttacker()){
|
||||
return [1.05, 1];
|
||||
}
|
||||
return [1, 1];
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_돌격지속($unit)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,36 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
|
||||
class che_무쌍 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 61;
|
||||
protected $name = '무쌍';
|
||||
protected $info = '[전투] 대미지 +10%, 공격 시 필살 확률 +10%p';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_STRENGTH
|
||||
];
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'warCriticalRatio' && $aux['isAttacker']??false){
|
||||
return $value += 0.1;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
return [1.1, 1];
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use \sammo\Util;
|
||||
|
||||
class che_무쌍 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 61;
|
||||
protected $name = '무쌍';
|
||||
protected $info = '[전투] 대미지 +10%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대50%)';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_STRENGTH
|
||||
];
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'warCriticalRatio' && $aux['isAttacker']??false){
|
||||
return $value += 0.1;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
$attackMultiplier = 1.1;
|
||||
$defenceMultiplier = 1;
|
||||
$killnum = $unit->getGeneral()->getRankVar('killnum');
|
||||
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4);
|
||||
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.5);
|
||||
return [$attackMultiplier, $defenceMultiplier];
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,39 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use \sammo\BaseWarUnitTrigger;
|
||||
use \sammo\WarUnitTrigger\WarActivateSkills;
|
||||
use \sammo\WarUnitTrigger\che_반계시도;
|
||||
use \sammo\WarUnitTrigger\che_반계발동;
|
||||
|
||||
class che_반계 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 45;
|
||||
protected $name = '반계';
|
||||
protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림, 반목 성공시 대미지 추가(+60% → +100%)';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_INTEL,
|
||||
];
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'warMagicSuccessDamage' && $aux === '반목'){
|
||||
return $value + 0.4;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '계략약화'),
|
||||
new che_반계시도($unit),
|
||||
new che_반계발동($unit)
|
||||
);
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use \sammo\BaseWarUnitTrigger;
|
||||
use \sammo\WarUnitTrigger\WarActivateSkills;
|
||||
use \sammo\WarUnitTrigger\che_반계시도;
|
||||
use \sammo\WarUnitTrigger\che_반계발동;
|
||||
|
||||
class che_반계 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 45;
|
||||
protected $name = '반계';
|
||||
protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림, 반목 성공시 대미지 추가(+60% → +150%)';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_INTEL,
|
||||
];
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'warMagicSuccessDamage' && $aux === '반목'){
|
||||
return $value + 0.9;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '계략약화'),
|
||||
new che_반계시도($unit),
|
||||
new che_반계발동($unit)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,50 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\GameUnitConst;
|
||||
use \sammo\WarUnit;
|
||||
|
||||
class che_보병 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 50;
|
||||
protected $name = '보병';
|
||||
protected $info = '[군사] 보병 계통 징·모병비 -10%<br>[전투] 공격 시 아군 피해 -10%, 수비 시 아군 피해 -20%';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_FOOTMAN | SpecialityHelper::STAT_NOT_INTEL,
|
||||
SpecialityHelper::STAT_STRENGTH | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_FOOTMAN
|
||||
];
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if(in_array($turnType, ['징병', '모병'])){
|
||||
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_FOOTMAN) return $value * 0.9;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
if($unit->isAttacker()){
|
||||
return [1, 0.9];
|
||||
}
|
||||
return [1, 0.8];
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\GameUnitConst;
|
||||
use \sammo\WarUnit;
|
||||
|
||||
class che_보병 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 50;
|
||||
protected $name = '보병';
|
||||
protected $info = '[군사] 보병 계통 징·모병비 -10%<br>[전투] 공격 시 아군 피해 -10%, 수비 시 아군 피해 -20%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 보병 숙련을 가산';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_FOOTMAN | SpecialityHelper::STAT_NOT_INTEL,
|
||||
SpecialityHelper::STAT_STRENGTH | SpecialityHelper::REQ_DEXTERITY | SpecialityHelper::ARMY_FOOTMAN
|
||||
];
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if(in_array($turnType, ['징병', '모병'])){
|
||||
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_FOOTMAN) return $value * 0.9;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
if($unit->isAttacker()){
|
||||
return [1, 0.9];
|
||||
}
|
||||
return [1, 0.8];
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if(\sammo\Util::starts_with($statName, 'dex')){
|
||||
$myArmType = 'dex'.GameUnitConst::T_FOOTMAN;
|
||||
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
|
||||
if($aux['isAttacker'] && $opposeArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
if(!$aux['isAttacker'] && $myArmType === $statName){
|
||||
return $value + $general->getVar($myArmType);
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,29 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use \sammo\WarUnitTrigger\che_위압시도;
|
||||
use \sammo\WarUnitTrigger\che_위압발동;
|
||||
|
||||
class che_위압 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 63;
|
||||
protected $name = '위압';
|
||||
protected $info = '[전투] 훈련/사기≥90, 병력≥1,000 일 때 첫 페이즈 위압 발동(적 공격 불가)';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_STRENGTH
|
||||
];
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
if($unit->getPhase() != 0){
|
||||
return null;
|
||||
}
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_위압시도($unit),
|
||||
new che_위압발동($unit)
|
||||
);
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use \sammo\WarUnitTrigger\che_위압시도;
|
||||
use \sammo\WarUnitTrigger\che_위압발동;
|
||||
|
||||
class che_위압 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 63;
|
||||
protected $name = '위압';
|
||||
protected $info = '[전투] 첫 페이즈 위압 발동(적 공격, 회피 불가, 사기 5 감소)';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_STRENGTH
|
||||
];
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_위압시도($unit),
|
||||
new che_위압발동($unit)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,41 +1,41 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use sammo\BaseGeneralTrigger;
|
||||
use sammo\SpecialityHelper;
|
||||
use \sammo\General;
|
||||
use \sammo\GeneralTrigger;
|
||||
use \sammo\GeneralTriggerCaller;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTrigger\che_전투치료발동;
|
||||
use sammo\WarUnitTrigger\che_전투치료시도;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
|
||||
class che_의술 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 73;
|
||||
protected $name = '의술';
|
||||
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_PERCENT;
|
||||
static $selectWeight = 2;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP,
|
||||
SpecialityHelper::STAT_STRENGTH,
|
||||
SpecialityHelper::STAT_INTEL
|
||||
];
|
||||
|
||||
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
|
||||
return new GeneralTriggerCaller(
|
||||
new GeneralTrigger\che_도시치료($general)
|
||||
);
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
|
||||
{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_전투치료시도($unit),
|
||||
new che_전투치료발동($unit)
|
||||
);
|
||||
}
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use sammo\BaseGeneralTrigger;
|
||||
use sammo\SpecialityHelper;
|
||||
use \sammo\General;
|
||||
use \sammo\GeneralTrigger;
|
||||
use \sammo\GeneralTriggerCaller;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTrigger\che_전투치료발동;
|
||||
use sammo\WarUnitTrigger\che_전투치료시도;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
|
||||
class che_의술 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 73;
|
||||
protected $name = '의술';
|
||||
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_PERCENT;
|
||||
static $selectWeight = 2;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP,
|
||||
SpecialityHelper::STAT_STRENGTH,
|
||||
SpecialityHelper::STAT_INTEL
|
||||
];
|
||||
|
||||
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
|
||||
return new GeneralTriggerCaller(
|
||||
new GeneralTrigger\che_도시치료($general)
|
||||
);
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
|
||||
{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_전투치료시도($unit),
|
||||
new che_전투치료발동($unit)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use \sammo\WarUnitTrigger\che_저격시도;
|
||||
use \sammo\WarUnitTrigger\che_저격발동;
|
||||
|
||||
class che_저격 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 70;
|
||||
protected $name = '저격';
|
||||
protected $info = '[전투] 새로운 상대와 전투 시 1/3 확률로 저격 발동, 성공 시 사기+10';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP,
|
||||
SpecialityHelper::STAT_STRENGTH,
|
||||
SpecialityHelper::STAT_INTEL
|
||||
];
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_저격시도($unit, che_저격시도::TYPE_NONE, 1/3, 20, 60),
|
||||
new che_저격발동($unit)
|
||||
);
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use \sammo\WarUnitTrigger\che_저격시도;
|
||||
use \sammo\WarUnitTrigger\che_저격발동;
|
||||
|
||||
class che_저격 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 70;
|
||||
protected $name = '저격';
|
||||
protected $info = '[전투] 새로운 상대와 전투 시 50% 확률로 저격 발동, 성공 시 사기+10';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP,
|
||||
SpecialityHelper::STAT_STRENGTH,
|
||||
SpecialityHelper::STAT_INTEL
|
||||
];
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_저격시도($unit, che_저격시도::TYPE_NONE, 0.5, 20, 40),
|
||||
new che_저격발동($unit)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,36 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
|
||||
class che_징병 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 72;
|
||||
protected $name = '징병';
|
||||
protected $info = '[군사] 징·모병비 -50%, 통솔 순수 능력치 보정 +15%';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP,
|
||||
SpecialityHelper::STAT_STRENGTH,
|
||||
SpecialityHelper::STAT_INTEL
|
||||
];
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if(in_array($turnType, ['징병', '모병'])){
|
||||
if($varType == 'cost') return $value * 0.5;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'leadership'){
|
||||
return $value *= 1.15;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
|
||||
class che_징병 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 72;
|
||||
protected $name = '징병';
|
||||
protected $info = '[군사] 징·모병비 -50%, 통솔 순수 능력치 보정 +25%';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP,
|
||||
SpecialityHelper::STAT_STRENGTH,
|
||||
SpecialityHelper::STAT_INTEL
|
||||
];
|
||||
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
if(in_array($turnType, ['징병', '모병'])){
|
||||
if($varType == 'cost') return $value * 0.5;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'leadership'){
|
||||
return $value + $general->getVar('leadership') * 0.25;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,29 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
|
||||
class che_척사 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 75;
|
||||
protected $name = '척사';
|
||||
protected $info = '[전투] 지역·도시 병종 상대로 대미지 +10%, 아군 피해 -10%';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP,
|
||||
SpecialityHelper::STAT_STRENGTH,
|
||||
SpecialityHelper::STAT_INTEL
|
||||
];
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
$opposeCrewType = $unit->getOppose()->getCrewType();
|
||||
if($opposeCrewType->reqCities || $opposeCrewType->reqRegions){
|
||||
return [1.1, 0.9];
|
||||
}
|
||||
return [1, 1];
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
|
||||
class che_척사 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 75;
|
||||
protected $name = '척사';
|
||||
protected $info = '[전투] 지역·도시 병종 상대로 대미지 +15%, 아군 피해 -15%';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP,
|
||||
SpecialityHelper::STAT_STRENGTH,
|
||||
SpecialityHelper::STAT_INTEL
|
||||
];
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
$opposeCrewType = $unit->getOppose()->getCrewType();
|
||||
if($opposeCrewType->reqCities || $opposeCrewType->reqRegions){
|
||||
return [1.15, 0.85];
|
||||
}
|
||||
return [1, 1];
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,36 @@
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use sammo\WarUnitTrigger\che_필살강화_회피불가;
|
||||
|
||||
class che_필살 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 71;
|
||||
protected $name = '필살';
|
||||
protected $info = '[전투] 필살 확률 +20%p, 필살 발동시 대상 회피 불가';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP,
|
||||
SpecialityHelper::STAT_STRENGTH,
|
||||
SpecialityHelper::STAT_INTEL
|
||||
];
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'warCriticalRatio'){
|
||||
return $value + 0.2;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_필살강화_회피불가($unit)
|
||||
);
|
||||
}
|
||||
<?php
|
||||
namespace sammo\ActionSpecialWar;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use \sammo\SpecialityHelper;
|
||||
use \sammo\WarUnit;
|
||||
use sammo\WarUnitTriggerCaller;
|
||||
use sammo\WarUnitTrigger\che_필살강화_회피불가;
|
||||
|
||||
class che_필살 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 71;
|
||||
protected $name = '필살';
|
||||
protected $info = '[전투] 필살 확률 +30%p, 필살 발동시 대상 회피 불가';
|
||||
|
||||
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
|
||||
static $selectWeight = 1;
|
||||
static $type = [
|
||||
SpecialityHelper::STAT_LEADERSHIP,
|
||||
SpecialityHelper::STAT_STRENGTH,
|
||||
SpecialityHelper::STAT_INTEL
|
||||
];
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
if($statName === 'warCriticalRatio'){
|
||||
return $value + 0.30;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_필살강화_회피불가($unit)
|
||||
);
|
||||
}
|
||||
}
|
||||
+104
-104
@@ -1,104 +1,104 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
abstract class BaseWarUnitTrigger extends ObjectTrigger{
|
||||
/** @var WarUnit $object */
|
||||
|
||||
const TYPE_NONE = 0;
|
||||
const TYPE_ITEM = 1;
|
||||
const TYPE_CONSUMABLE_ITEM = 1 | 2;
|
||||
|
||||
protected $raiseType = self::TYPE_NONE;
|
||||
|
||||
public function __construct(WarUnit $unit, int $raiseType = 0){
|
||||
$this->object = $unit;
|
||||
$this->raiseType = $raiseType;
|
||||
}
|
||||
|
||||
public function getUniqueID():string{
|
||||
$priority = $this->priority;
|
||||
$fqn = static::class;
|
||||
if($this->object === null){
|
||||
$objID = '';
|
||||
}
|
||||
else{
|
||||
$objID = spl_object_id($this->object);
|
||||
}
|
||||
return "{$priority}_{$fqn}_{$objID}_{$this->raiseType}";
|
||||
}
|
||||
|
||||
public function action(?array $env=null, $arg=null):?array{
|
||||
if($env === null){
|
||||
$env = [];
|
||||
}
|
||||
if(!key_exists('e_attacker', $env)){
|
||||
$env['e_attacker'] = [];
|
||||
}
|
||||
if(!key_exists('e_defender', $env)){
|
||||
$env['e_defender'] = [];
|
||||
}
|
||||
|
||||
if($env['stopNextAction']??false){
|
||||
return $env;
|
||||
}
|
||||
|
||||
/** @var WarUnitGeneral $attacker */
|
||||
/** @var WarUnit $defender */
|
||||
[$attacker, $defender] = $arg;
|
||||
|
||||
/** @var WarUnit $self */
|
||||
$self = $this->object;
|
||||
$isAttacker = $self->isAttacker();
|
||||
$oppose = $isAttacker?$defender:$attacker;
|
||||
|
||||
$selfEnv = $isAttacker?$env['e_attacker']:$env['e_defender'];
|
||||
$opposeEnv = $isAttacker?$env['e_defender']:$env['e_attacker'];
|
||||
|
||||
$callNextAction = $this->actionWar($self, $oppose, $selfEnv, $opposeEnv);
|
||||
|
||||
$env['e_attacker'] = $isAttacker?$selfEnv:$opposeEnv;
|
||||
$env['e_defender'] = $isAttacker?$opposeEnv:$selfEnv;
|
||||
|
||||
if(!$callNextAction){
|
||||
$env['stopNextAction'] = true;
|
||||
}
|
||||
|
||||
return $env;
|
||||
}
|
||||
|
||||
abstract protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool;
|
||||
|
||||
public function processConsumableItem():bool{
|
||||
if(!($this->raiseType & static::TYPE_ITEM)){
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var WarUnit $self */
|
||||
$self = $this->object;
|
||||
|
||||
if($self->hasActivatedSkill('아이템사용')){
|
||||
return false;
|
||||
}
|
||||
|
||||
$self->activateSkill('아이템사용');
|
||||
$item = $self->getGeneral()->getItem();
|
||||
$itemName = $item->getName();
|
||||
$itemRawName = $item->getRawName();
|
||||
$self->activateSkill($itemName);
|
||||
|
||||
if (!($this->raiseType & static::TYPE_CONSUMABLE_ITEM)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if($self->hasActivatedSkill('아이템소모')){
|
||||
return false;
|
||||
}
|
||||
|
||||
$self->activateSkill('아이템소모');
|
||||
$josaUl = JosaUtil::pick($itemRawName, '을');
|
||||
$self->getLogger()->pushGeneralActionLog("<C>{$itemName}</>{$josaUl} 사용!", ActionLogger::PLAIN);
|
||||
$self->getGeneral()->deleteItem();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
abstract class BaseWarUnitTrigger extends ObjectTrigger{
|
||||
/** @var WarUnit $object */
|
||||
|
||||
const TYPE_NONE = 0;
|
||||
const TYPE_ITEM = 1;
|
||||
const TYPE_CONSUMABLE_ITEM = 1 | 2;
|
||||
|
||||
protected $raiseType = self::TYPE_NONE;
|
||||
|
||||
public function __construct(WarUnit $unit, int $raiseType = 0){
|
||||
$this->object = $unit;
|
||||
$this->raiseType = $raiseType;
|
||||
}
|
||||
|
||||
public function getUniqueID():string{
|
||||
$priority = $this->priority;
|
||||
$fqn = static::class;
|
||||
if($this->object === null){
|
||||
$objID = '';
|
||||
}
|
||||
else{
|
||||
$objID = spl_object_id($this->object);
|
||||
}
|
||||
return "{$priority}_{$fqn}_{$objID}_{$this->raiseType}";
|
||||
}
|
||||
|
||||
public function action(?array $env=null, $arg=null):?array{
|
||||
if($env === null){
|
||||
$env = [];
|
||||
}
|
||||
if(!key_exists('e_attacker', $env)){
|
||||
$env['e_attacker'] = [];
|
||||
}
|
||||
if(!key_exists('e_defender', $env)){
|
||||
$env['e_defender'] = [];
|
||||
}
|
||||
|
||||
if($env['stopNextAction']??false){
|
||||
return $env;
|
||||
}
|
||||
|
||||
/** @var WarUnitGeneral $attacker */
|
||||
/** @var WarUnit $defender */
|
||||
[$attacker, $defender] = $arg;
|
||||
|
||||
/** @var WarUnit $self */
|
||||
$self = $this->object;
|
||||
$isAttacker = $self->isAttacker();
|
||||
$oppose = $isAttacker?$defender:$attacker;
|
||||
|
||||
$selfEnv = $isAttacker?$env['e_attacker']:$env['e_defender'];
|
||||
$opposeEnv = $isAttacker?$env['e_defender']:$env['e_attacker'];
|
||||
|
||||
$callNextAction = $this->actionWar($self, $oppose, $selfEnv, $opposeEnv);
|
||||
|
||||
$env['e_attacker'] = $isAttacker?$selfEnv:$opposeEnv;
|
||||
$env['e_defender'] = $isAttacker?$opposeEnv:$selfEnv;
|
||||
|
||||
if(!$callNextAction){
|
||||
$env['stopNextAction'] = true;
|
||||
}
|
||||
|
||||
return $env;
|
||||
}
|
||||
|
||||
abstract protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool;
|
||||
|
||||
public function processConsumableItem():bool{
|
||||
if(!($this->raiseType & static::TYPE_ITEM)){
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var WarUnit $self */
|
||||
$self = $this->object;
|
||||
|
||||
if($self->hasActivatedSkill('아이템사용')){
|
||||
return false;
|
||||
}
|
||||
|
||||
$self->activateSkill('아이템사용');
|
||||
$item = $self->getGeneral()->getItem();
|
||||
$itemName = $item->getName();
|
||||
$itemRawName = $item->getRawName();
|
||||
$self->activateSkill($itemName);
|
||||
|
||||
if ($this->raiseType != static::TYPE_CONSUMABLE_ITEM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if($self->hasActivatedSkill('아이템소모')){
|
||||
return false;
|
||||
}
|
||||
|
||||
$self->activateSkill('아이템소모');
|
||||
$josaUl = JosaUtil::pick($itemRawName, '을');
|
||||
$self->getLogger()->pushGeneralActionLog("<C>{$itemName}</>{$josaUl} 사용!", ActionLogger::PLAIN);
|
||||
$self->getGeneral()->deleteItem();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ use \sammo\Constraint\ConstraintHelper;
|
||||
abstract class BaseCommand{
|
||||
static protected $actionName = 'CommandName';
|
||||
static public $reqArg = false;
|
||||
static protected $isLazyCalcReqTurn = false;
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
return $this->getName();
|
||||
@@ -54,7 +55,6 @@ abstract class BaseCommand{
|
||||
|
||||
static protected $isInitStatic = true;
|
||||
protected static function initStatic(){
|
||||
|
||||
}
|
||||
|
||||
public function __construct(General $generalObj, array $env, $arg = null){
|
||||
@@ -271,6 +271,29 @@ abstract class BaseCommand{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
abstract public function getNextExecuteKey():string;
|
||||
abstract public function getNextAvailableTurn():?int;
|
||||
abstract public function setNextAvailable(?int $yearMonth=null);
|
||||
|
||||
protected function testPostReqTurn():?array{
|
||||
if(!$this->getPostReqTurn()){
|
||||
return null;
|
||||
}
|
||||
|
||||
$nextAvailableTurn = $this->getNextAvailableTurn();
|
||||
if($nextAvailableTurn === null){
|
||||
return null;
|
||||
}
|
||||
|
||||
$yearMonth = Util::joinYearMonth($this->env['year'], $this->env['month']);
|
||||
$remainTurn = $nextAvailableTurn - $yearMonth;
|
||||
if($remainTurn <= 0){
|
||||
return null;
|
||||
}
|
||||
|
||||
return ['testPostReqTurn', "{$remainTurn}턴 더 기다려야 합니다"];
|
||||
}
|
||||
|
||||
public function testPermissionToReserve():?string{
|
||||
if($this->cachedPermissionToReserve){
|
||||
return $this->reasonNoPermissionToReserve;
|
||||
@@ -331,6 +354,11 @@ abstract class BaseCommand{
|
||||
];
|
||||
|
||||
[$this->reasonConstraint, $this->reasonNotMinConditionMet] = Constraint::testAll($this->minConditionConstraints??[], $constraintInput, $this->env);
|
||||
|
||||
if($this->reasonNotMinConditionMet === null && !self::$isLazyCalcReqTurn){
|
||||
[$this->reasonConstraint, $this->reasonNotMinConditionMet] = $this->testPostReqTurn();
|
||||
}
|
||||
|
||||
$this->cachedMinConditionMet = true;
|
||||
return $this->reasonNotMinConditionMet;
|
||||
|
||||
@@ -364,6 +392,11 @@ abstract class BaseCommand{
|
||||
];
|
||||
|
||||
[$this->reasonConstraint, $this->reasonNotFullConditionMet] = Constraint::testAll($this->fullConditionConstraints??[], $constraintInput, $this->env);
|
||||
|
||||
if($this->reasonNotFullConditionMet === null){
|
||||
[$this->reasonConstraint, $this->reasonNotFullConditionMet] = $this->testPostReqTurn();
|
||||
}
|
||||
|
||||
$this->cachedFullConditionMet = true;
|
||||
return $this->reasonNotFullConditionMet;
|
||||
|
||||
|
||||
@@ -1,137 +1,137 @@
|
||||
<?php
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
LastTurn,
|
||||
Command, GameConst
|
||||
};
|
||||
|
||||
use function sammo\{
|
||||
TechLimit,
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
class che_기술연구 extends che_상업투자{
|
||||
static protected $statKey = 'intel';
|
||||
static protected $actionKey = '기술';
|
||||
static protected $actionName = '기술 연구';
|
||||
|
||||
protected function argTest():bool{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['tech']);
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::NotWanderingNation(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice)
|
||||
];
|
||||
|
||||
$this->reqGold = $reqGold;
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$trust = Util::valueFit($this->city['trust'], 50);
|
||||
|
||||
$score = Util::valueFit($this->calcBaseScore(), 1);
|
||||
|
||||
['success'=>$successRatio, 'fail'=>$failRatio] = CriticalRatioDomestic($general, static::$statKey);
|
||||
if($trust < 80){
|
||||
$successRatio *= $trust / 80;
|
||||
}
|
||||
$successRatio = $general->onCalcDomestic(static::$cityKey, 'success', $successRatio);
|
||||
$failRatio = $general->onCalcDomestic(static::$cityKey, 'fail', $failRatio);
|
||||
|
||||
$successRatio = Util::valueFit($successRatio, 0, 1);
|
||||
$failRatio = Util::valueFit($failRatio, 0, 1 - $successRatio);
|
||||
$normalRatio = 1 - $failRatio - $successRatio;
|
||||
|
||||
$pick = Util::choiceRandomUsingWeight([
|
||||
'fail'=>$failRatio,
|
||||
'success'=>$successRatio,
|
||||
'normal'=>$normalRatio
|
||||
]);
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$score *= CriticalScoreEx($pick);
|
||||
$score = Util::round($score);
|
||||
|
||||
$exp = $score * 0.7;
|
||||
$ded = $score * 1.0;
|
||||
|
||||
$scoreText = number_format($score, 0);
|
||||
|
||||
$josaUl = JosaUtil::pick(static::$actionName, '을');
|
||||
if($pick == 'fail'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <span class='ev_failed'>실패</span>하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
else if($pick == 'success'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <S>성공</>하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
else{
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} 하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
|
||||
if(TechLimit($this->env['startyear'], $this->env['year'], $this->nation['tech'])){
|
||||
$score /= 4;
|
||||
}
|
||||
|
||||
$genCount = Util::valueFit(
|
||||
$db->queryFirstField('SELECT gennum FROM nation WHERE nation=%i', $general->getVar('nation')),
|
||||
GameConst::$initialNationGenLimit
|
||||
);
|
||||
|
||||
$nationUpdated = [
|
||||
'tech' => $this->nation['tech'] + $score/$genCount
|
||||
];
|
||||
$db->update('nation', $nationUpdated, 'nation=%i', $general->getVar('nation'));
|
||||
|
||||
$general->increaseVarWithLimit('gold', -$this->reqGold, 0);
|
||||
$general->addExperience($exp);
|
||||
$general->addDedication($ded);
|
||||
$general->increaseVar(static::$statKey.'_exp', 1);
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
<?php
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
LastTurn,
|
||||
Command, GameConst
|
||||
};
|
||||
|
||||
use function sammo\{
|
||||
TechLimit,
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
class che_기술연구 extends che_상업투자{
|
||||
static protected $statKey = 'intel';
|
||||
static protected $actionKey = '기술';
|
||||
static protected $actionName = '기술 연구';
|
||||
|
||||
protected function argTest():bool{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['tech']);
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::NotWanderingNation(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice)
|
||||
];
|
||||
|
||||
$this->reqGold = $reqGold;
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$trust = Util::valueFit($this->city['trust'], 50);
|
||||
|
||||
$score = Util::valueFit($this->calcBaseScore(), 1);
|
||||
|
||||
['success'=>$successRatio, 'fail'=>$failRatio] = CriticalRatioDomestic($general, static::$statKey);
|
||||
if($trust < 80){
|
||||
$successRatio *= $trust / 80;
|
||||
}
|
||||
$successRatio = $general->onCalcDomestic(static::$actionKey, 'success', $successRatio);
|
||||
$failRatio = $general->onCalcDomestic(static::$actionKey, 'fail', $failRatio);
|
||||
|
||||
$successRatio = Util::valueFit($successRatio, 0, 1);
|
||||
$failRatio = Util::valueFit($failRatio, 0, 1 - $successRatio);
|
||||
$normalRatio = 1 - $failRatio - $successRatio;
|
||||
|
||||
$pick = Util::choiceRandomUsingWeight([
|
||||
'fail'=>$failRatio,
|
||||
'success'=>$successRatio,
|
||||
'normal'=>$normalRatio
|
||||
]);
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$score *= CriticalScoreEx($pick);
|
||||
$score = Util::round($score);
|
||||
|
||||
$exp = $score * 0.7;
|
||||
$ded = $score * 1.0;
|
||||
|
||||
$scoreText = number_format($score, 0);
|
||||
|
||||
$josaUl = JosaUtil::pick(static::$actionName, '을');
|
||||
if($pick == 'fail'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <span class='ev_failed'>실패</span>하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
else if($pick == 'success'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <S>성공</>하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
else{
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} 하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
|
||||
if(TechLimit($this->env['startyear'], $this->env['year'], $this->nation['tech'])){
|
||||
$score /= 4;
|
||||
}
|
||||
|
||||
$genCount = Util::valueFit(
|
||||
$db->queryFirstField('SELECT gennum FROM nation WHERE nation=%i', $general->getVar('nation')),
|
||||
GameConst::$initialNationGenLimit
|
||||
);
|
||||
|
||||
$nationUpdated = [
|
||||
'tech' => $this->nation['tech'] + $score/$genCount
|
||||
];
|
||||
$db->update('nation', $nationUpdated, 'nation=%i', $general->getVar('nation'));
|
||||
|
||||
$general->increaseVarWithLimit('gold', -$this->reqGold, 0);
|
||||
$general->addExperience($exp);
|
||||
$general->addDedication($ded);
|
||||
$general->increaseVar(static::$statKey.'_exp', 1);
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,208 +1,208 @@
|
||||
<?php
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
class che_상업투자 extends Command\GeneralCommand{
|
||||
static protected $cityKey = 'comm';
|
||||
static protected $statKey = 'intel';
|
||||
static protected $actionKey = '상업';
|
||||
static protected $actionName = '상업 투자';
|
||||
static protected $debuffFront = 0.5;
|
||||
|
||||
protected $reqGold;
|
||||
|
||||
protected function argTest():bool{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation();
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::NotWanderingNation(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice),
|
||||
ConstraintHelper::RemainCityCapacity(static::$cityKey, static::$actionName)
|
||||
];
|
||||
|
||||
$this->reqGold = $reqGold;
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
$statTypeBase = [
|
||||
'leadership'=>'통솔경험',
|
||||
'strength'=>'무력경험',
|
||||
'intel'=>'지력경험',
|
||||
];
|
||||
$statType = $statTypeBase[static::$statKey];
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$title = "{$name}({$statType}";
|
||||
if($reqGold > 0){
|
||||
$title .= ", 자금{$reqGold}";
|
||||
}
|
||||
if($reqRice > 0){
|
||||
$title .= ", 군량{$reqRice}";
|
||||
}
|
||||
$title .= ')';
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
$develCost = $this->env['develcost'];
|
||||
$reqGold = Util::round($this->generalObj->onCalcDomestic(static::$actionKey, 'cost', $develCost));
|
||||
$reqRice = 0;
|
||||
|
||||
return [$reqGold, $reqRice];
|
||||
}
|
||||
|
||||
|
||||
public function getCompensationStyle():?int{
|
||||
return $this->generalObj->onCalcDomestic(static::$actionKey, 'score', 100)<=>100;
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function calcBaseScore():float{
|
||||
$trust = Util::valueFit($this->city['trust'], 50);
|
||||
$general = $this->generalObj;
|
||||
|
||||
if(static::$statKey == 'intel'){
|
||||
$score = $general->getIntel(true, true, true, false);
|
||||
}
|
||||
else if(static::$statKey == 'strength'){
|
||||
$score = $general->getStrength(true, true, true, false);
|
||||
}
|
||||
else if(static::$statKey == 'leadership'){
|
||||
$score = $general->getLeadership(true, true, true, false);
|
||||
}
|
||||
else{
|
||||
throw new \sammo\MustNotBeReachedException();
|
||||
}
|
||||
|
||||
$score *= $trust / 100;
|
||||
$score *= getDomesticExpLevelBonus($general->getVar('explevel'));
|
||||
$score *= Util::randRange(0.8, 1.2);
|
||||
$score = $general->onCalcDomestic(static::$actionKey, 'score', $score);
|
||||
|
||||
return $score;
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$trust = Util::valueFit($this->city['trust'], 50);
|
||||
|
||||
$score = Util::valueFit($this->calcBaseScore(), 1);
|
||||
|
||||
['success'=>$successRatio, 'fail'=>$failRatio] = CriticalRatioDomestic($general, static::$statKey);
|
||||
if($trust < 80){
|
||||
$successRatio *= $trust / 80;
|
||||
}
|
||||
$successRatio = $general->onCalcDomestic(static::$cityKey, 'success', $successRatio);
|
||||
$failRatio = $general->onCalcDomestic(static::$cityKey, 'fail', $failRatio);
|
||||
|
||||
$successRatio = Util::valueFit($successRatio, 0, 1);
|
||||
$failRatio = Util::valueFit($failRatio, 0, 1 - $successRatio);
|
||||
$normalRatio = 1 - $failRatio - $successRatio;
|
||||
|
||||
$pick = Util::choiceRandomUsingWeight([
|
||||
'fail'=>$failRatio,
|
||||
'success'=>$successRatio,
|
||||
'normal'=>$normalRatio
|
||||
]);
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$score *= CriticalScoreEx($pick);
|
||||
$score = Util::round($score);
|
||||
|
||||
$exp = $score * 0.7;
|
||||
$ded = $score * 1.0;
|
||||
|
||||
$scoreText = number_format($score, 0);
|
||||
|
||||
$josaUl = JosaUtil::pick(static::$actionName, '을');
|
||||
if($pick == 'fail'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <span class='ev_failed'>실패</span>하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
else if($pick == 'success'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <S>성공</>하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
else{
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} 하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
|
||||
if(in_array($this->city['front'], [1, 3]) && $this->nation['capital'] != $this->city['city']){
|
||||
$score *= static::$debuffFront;
|
||||
}
|
||||
|
||||
//NOTE: 내정량 상승시 초과 가능?
|
||||
$cityUpdated = [
|
||||
static::$cityKey => Util::valueFit(
|
||||
$this->city[static::$cityKey] + $score,
|
||||
0,
|
||||
$this->city[static::$cityKey.'_max']
|
||||
)
|
||||
];
|
||||
$db->update('city', $cityUpdated, 'city=%i', $general->getVar('city'));
|
||||
|
||||
$general->increaseVarWithLimit('gold', -$this->reqGold, 0);
|
||||
$general->addExperience($exp);
|
||||
$general->addDedication($ded);
|
||||
$general->increaseVar(static::$statKey.'_exp', 1);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
<?php
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
class che_상업투자 extends Command\GeneralCommand{
|
||||
static protected $cityKey = 'comm';
|
||||
static protected $statKey = 'intel';
|
||||
static protected $actionKey = '상업';
|
||||
static protected $actionName = '상업 투자';
|
||||
static protected $debuffFront = 0.5;
|
||||
|
||||
protected $reqGold;
|
||||
|
||||
protected function argTest():bool{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation();
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::NotWanderingNation(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice),
|
||||
ConstraintHelper::RemainCityCapacity(static::$cityKey, static::$actionName)
|
||||
];
|
||||
|
||||
$this->reqGold = $reqGold;
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
$statTypeBase = [
|
||||
'leadership'=>'통솔경험',
|
||||
'strength'=>'무력경험',
|
||||
'intel'=>'지력경험',
|
||||
];
|
||||
$statType = $statTypeBase[static::$statKey];
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$title = "{$name}({$statType}";
|
||||
if($reqGold > 0){
|
||||
$title .= ", 자금{$reqGold}";
|
||||
}
|
||||
if($reqRice > 0){
|
||||
$title .= ", 군량{$reqRice}";
|
||||
}
|
||||
$title .= ')';
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
$develCost = $this->env['develcost'];
|
||||
$reqGold = Util::round($this->generalObj->onCalcDomestic(static::$actionKey, 'cost', $develCost));
|
||||
$reqRice = 0;
|
||||
|
||||
return [$reqGold, $reqRice];
|
||||
}
|
||||
|
||||
|
||||
public function getCompensationStyle():?int{
|
||||
return $this->generalObj->onCalcDomestic(static::$actionKey, 'score', 100)<=>100;
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function calcBaseScore():float{
|
||||
$trust = Util::valueFit($this->city['trust'], 50);
|
||||
$general = $this->generalObj;
|
||||
|
||||
if(static::$statKey == 'intel'){
|
||||
$score = $general->getIntel(true, true, true, false);
|
||||
}
|
||||
else if(static::$statKey == 'strength'){
|
||||
$score = $general->getStrength(true, true, true, false);
|
||||
}
|
||||
else if(static::$statKey == 'leadership'){
|
||||
$score = $general->getLeadership(true, true, true, false);
|
||||
}
|
||||
else{
|
||||
throw new \sammo\MustNotBeReachedException();
|
||||
}
|
||||
|
||||
$score *= $trust / 100;
|
||||
$score *= getDomesticExpLevelBonus($general->getVar('explevel'));
|
||||
$score *= Util::randRange(0.8, 1.2);
|
||||
$score = $general->onCalcDomestic(static::$actionKey, 'score', $score);
|
||||
|
||||
return $score;
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$trust = Util::valueFit($this->city['trust'], 50);
|
||||
|
||||
$score = Util::valueFit($this->calcBaseScore(), 1);
|
||||
|
||||
['success'=>$successRatio, 'fail'=>$failRatio] = CriticalRatioDomestic($general, static::$statKey);
|
||||
if($trust < 80){
|
||||
$successRatio *= $trust / 80;
|
||||
}
|
||||
$successRatio = $general->onCalcDomestic(static::$actionKey, 'success', $successRatio);
|
||||
$failRatio = $general->onCalcDomestic(static::$actionKey, 'fail', $failRatio);
|
||||
|
||||
$successRatio = Util::valueFit($successRatio, 0, 1);
|
||||
$failRatio = Util::valueFit($failRatio, 0, 1 - $successRatio);
|
||||
$normalRatio = 1 - $failRatio - $successRatio;
|
||||
|
||||
$pick = Util::choiceRandomUsingWeight([
|
||||
'fail'=>$failRatio,
|
||||
'success'=>$successRatio,
|
||||
'normal'=>$normalRatio
|
||||
]);
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$score *= CriticalScoreEx($pick);
|
||||
$score = Util::round($score);
|
||||
|
||||
$exp = $score * 0.7;
|
||||
$ded = $score * 1.0;
|
||||
|
||||
$scoreText = number_format($score, 0);
|
||||
|
||||
$josaUl = JosaUtil::pick(static::$actionName, '을');
|
||||
if($pick == 'fail'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <span class='ev_failed'>실패</span>하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
else if($pick == 'success'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <S>성공</>하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
else{
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} 하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
|
||||
if(in_array($this->city['front'], [1, 3]) && $this->nation['capital'] != $this->city['city']){
|
||||
$score *= static::$debuffFront;
|
||||
}
|
||||
|
||||
//NOTE: 내정량 상승시 초과 가능?
|
||||
$cityUpdated = [
|
||||
static::$cityKey => Util::valueFit(
|
||||
$this->city[static::$cityKey] + $score,
|
||||
0,
|
||||
$this->city[static::$cityKey.'_max']
|
||||
)
|
||||
];
|
||||
$db->update('city', $cityUpdated, 'city=%i', $general->getVar('city'));
|
||||
|
||||
$general->increaseVarWithLimit('gold', -$this->reqGold, 0);
|
||||
$general->addExperience($exp);
|
||||
$general->addDedication($ded);
|
||||
$general->increaseVar(static::$statKey.'_exp', 1);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,242 +1,242 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use\sammo\{
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
Session,
|
||||
KVStorage,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
GameUnitConst,
|
||||
LastTurn,
|
||||
Command,
|
||||
ServConfig
|
||||
};
|
||||
|
||||
|
||||
use function\sammo\{
|
||||
getDexCall,
|
||||
getTechCall,
|
||||
tryUniqueItemLottery,
|
||||
getTechAbil
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
|
||||
class che_숙련전환 extends Command\GeneralCommand
|
||||
{
|
||||
static protected $actionName = '숙련전환';
|
||||
static public $reqArg = true;
|
||||
|
||||
/** @var int */
|
||||
protected $srcArmType;
|
||||
/** @var string */
|
||||
protected $srcArmTypeName;
|
||||
/** @var int */
|
||||
protected $destArmType;
|
||||
/** @var string */
|
||||
protected $destArmTypeName;
|
||||
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
if (!key_exists('srcArmType', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
if (!key_exists('destArmType', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
$srcArmType = $this->arg['srcArmType'];
|
||||
$destArmType = $this->arg['destArmType'];
|
||||
|
||||
if (!is_int($srcArmType)) {
|
||||
return false;
|
||||
}
|
||||
if (!key_exists($srcArmType, GameUnitConst::allType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_int($destArmType)) {
|
||||
return false;
|
||||
}
|
||||
if (!key_exists($destArmType, GameUnitConst::allType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($srcArmType === $destArmType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->arg = [
|
||||
'srcArmType' => $srcArmType,
|
||||
'destArmType' => $destArmType
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation();
|
||||
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice),
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$this->srcArmType = $this->arg['srcArmType'];
|
||||
$this->srcArmTypeName = GameUnitConst::allType()[$this->srcArmType];
|
||||
$this->destArmType = $this->arg['destArmType'];
|
||||
$this->destArmTypeName = GameUnitConst::allType()[$this->destArmType];
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice),
|
||||
];
|
||||
}
|
||||
|
||||
public function getBrief(): string
|
||||
{
|
||||
return "【{$this->srcArmTypeName}】숙련을 【{$this->destArmTypeName}】숙련으로 전환";
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$name = $this->getName();
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$title = "{$name}(통솔경험";
|
||||
if ($reqGold > 0) {
|
||||
$title .= ", 자금{$reqGold}";
|
||||
}
|
||||
if ($reqRice > 0) {
|
||||
$title .= ", 군량{$reqRice}";
|
||||
}
|
||||
$title .= ')';
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getCost(): array
|
||||
{
|
||||
$env = $this->env;
|
||||
return [$env['develcost'], $env['develcost']];
|
||||
}
|
||||
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$srcDex = $general->getVar('dex' . $this->srcArmType);
|
||||
$cutDex = Util::toInt($srcDex * 0.25);
|
||||
$cutDexText = number_format($cutDex);
|
||||
$addDex = Util::toInt($cutDex * 9 / 10);
|
||||
$addDexText = number_format($addDex);
|
||||
|
||||
$general->increaseVar('dex' . $this->srcArmType, -$cutDex);
|
||||
$general->increaseVar('dex' . $this->destArmType, $addDex);
|
||||
|
||||
$josaUl = JosaUtil::pick($cutDex, '을');
|
||||
$josaRo = JosaUtil::pick($addDex, '로');
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$logger->pushGeneralActionLog("{$this->srcArmTypeName} 숙련 {$cutDexText}{$josaUl} {$this->destArmTypeName} 숙련 {$addDexText}{$josaRo} 전환했습니다. <1>$date</>");
|
||||
|
||||
$general->addExperience(10);
|
||||
$general->increaseVarWithLimit('gold', -$reqGold, 0);
|
||||
$general->increaseVarWithLimit('rice', -$reqRice, 0);
|
||||
$general->increaseVar('leadership_exp', 2);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$dexSrcTexts = [];
|
||||
$dexDestTexts = [];
|
||||
foreach (GameUnitConst::allType() as $armType => $armName) {
|
||||
$dexVal = $general->getVar('dex' . $armType);
|
||||
$dexValText = number_format($dexVal);
|
||||
$cutDex = Util::toInt($dexVal * 0.25);
|
||||
$addDex = Util::toInt($cutDex * 9 / 10);
|
||||
$addDexText = number_format($addDex);
|
||||
$newDex = $dexVal - $cutDex;
|
||||
$beforeDexLevel = getDexCall($dexVal);
|
||||
$afterDexLevel = getDexCall($newDex);
|
||||
|
||||
$dexSrcTexts[$armType] = "{$armName} ({$beforeDexLevel} ⇒ {$afterDexLevel}, {$addDexText} 전환)";
|
||||
$dexDestTexts[$armType] = "{$armName} ({$dexValText})";
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
본인의 특정 병종 숙련을 25% 줄이고, 줄어든 숙련 중 9/10(90%p)를 다른 병종 숙련으로 전환합니다.<br>
|
||||
|
||||
<select class='formInput' name="srcArmType" id="srcArmType" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($dexSrcTexts as $armType => $infoText) : ?>
|
||||
<option value="<?= $armType ?>"><?= $infoText ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
숙련을
|
||||
|
||||
<select class='formInput' name="destArmType" id="destArmType" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($dexDestTexts as $armType => $infoText) : ?>
|
||||
<option value="<?= $armType ?>"><?= $infoText ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
숙련으로 <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use\sammo\{
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
Session,
|
||||
KVStorage,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
GameUnitConst,
|
||||
LastTurn,
|
||||
Command,
|
||||
ServConfig
|
||||
};
|
||||
|
||||
|
||||
use function\sammo\{
|
||||
getDexCall,
|
||||
getTechCall,
|
||||
tryUniqueItemLottery,
|
||||
getTechAbil
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
|
||||
class che_숙련전환 extends Command\GeneralCommand
|
||||
{
|
||||
static protected $actionName = '숙련전환';
|
||||
static public $reqArg = true;
|
||||
|
||||
/** @var int */
|
||||
protected $srcArmType;
|
||||
/** @var string */
|
||||
protected $srcArmTypeName;
|
||||
/** @var int */
|
||||
protected $destArmType;
|
||||
/** @var string */
|
||||
protected $destArmTypeName;
|
||||
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
if (!key_exists('srcArmType', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
if (!key_exists('destArmType', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
$srcArmType = $this->arg['srcArmType'];
|
||||
$destArmType = $this->arg['destArmType'];
|
||||
|
||||
if (!is_int($srcArmType)) {
|
||||
return false;
|
||||
}
|
||||
if (!key_exists($srcArmType, GameUnitConst::allType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_int($destArmType)) {
|
||||
return false;
|
||||
}
|
||||
if (!key_exists($destArmType, GameUnitConst::allType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($srcArmType === $destArmType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->arg = [
|
||||
'srcArmType' => $srcArmType,
|
||||
'destArmType' => $destArmType
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation();
|
||||
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice),
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$this->srcArmType = $this->arg['srcArmType'];
|
||||
$this->srcArmTypeName = GameUnitConst::allType()[$this->srcArmType];
|
||||
$this->destArmType = $this->arg['destArmType'];
|
||||
$this->destArmTypeName = GameUnitConst::allType()[$this->destArmType];
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice),
|
||||
];
|
||||
}
|
||||
|
||||
public function getBrief(): string
|
||||
{
|
||||
return "【{$this->srcArmTypeName}】숙련을 【{$this->destArmTypeName}】숙련으로 전환";
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$name = $this->getName();
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$title = "{$name}(통솔경험";
|
||||
if ($reqGold > 0) {
|
||||
$title .= ", 자금{$reqGold}";
|
||||
}
|
||||
if ($reqRice > 0) {
|
||||
$title .= ", 군량{$reqRice}";
|
||||
}
|
||||
$title .= ')';
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getCost(): array
|
||||
{
|
||||
$env = $this->env;
|
||||
return [$env['develcost'], $env['develcost']];
|
||||
}
|
||||
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$srcDex = $general->getVar('dex' . $this->srcArmType);
|
||||
$cutDex = Util::toInt($srcDex * 0.4);
|
||||
$cutDexText = number_format($cutDex);
|
||||
$addDex = Util::toInt($cutDex * 9 / 10);
|
||||
$addDexText = number_format($addDex);
|
||||
|
||||
$general->increaseVar('dex' . $this->srcArmType, -$cutDex);
|
||||
$general->increaseVar('dex' . $this->destArmType, $addDex);
|
||||
|
||||
$josaUl = JosaUtil::pick($cutDex, '을');
|
||||
$josaRo = JosaUtil::pick($addDex, '로');
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$logger->pushGeneralActionLog("{$this->srcArmTypeName} 숙련 {$cutDexText}{$josaUl} {$this->destArmTypeName} 숙련 {$addDexText}{$josaRo} 전환했습니다. <1>$date</>");
|
||||
|
||||
$general->addExperience(10);
|
||||
$general->increaseVarWithLimit('gold', -$reqGold, 0);
|
||||
$general->increaseVarWithLimit('rice', -$reqRice, 0);
|
||||
$general->increaseVar('leadership_exp', 2);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$dexSrcTexts = [];
|
||||
$dexDestTexts = [];
|
||||
foreach (GameUnitConst::allType() as $armType => $armName) {
|
||||
$dexVal = $general->getVar('dex' . $armType);
|
||||
$dexValText = number_format($dexVal);
|
||||
$cutDex = Util::toInt($dexVal * 0.4);
|
||||
$addDex = Util::toInt($cutDex * 9 / 10);
|
||||
$addDexText = number_format($addDex);
|
||||
$newDex = $dexVal - $cutDex;
|
||||
$beforeDexLevel = getDexCall($dexVal);
|
||||
$afterDexLevel = getDexCall($newDex);
|
||||
|
||||
$dexSrcTexts[$armType] = "{$armName} ({$beforeDexLevel} ⇒ {$afterDexLevel}, {$addDexText} 전환)";
|
||||
$dexDestTexts[$armType] = "{$armName} ({$dexValText})";
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
본인의 특정 병종 숙련을 40% 줄이고, 줄어든 숙련 중 9/10(90%p)를 다른 병종 숙련으로 전환합니다.<br>
|
||||
|
||||
<select class='formInput' name="srcArmType" id="srcArmType" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($dexSrcTexts as $armType => $infoText) : ?>
|
||||
<option value="<?= $armType ?>"><?= $infoText ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
숙련을
|
||||
|
||||
<select class='formInput' name="destArmType" id="destArmType" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($dexDestTexts as $armType => $infoText) : ?>
|
||||
<option value="<?= $armType ?>"><?= $infoText ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
숙련으로 <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,300 +1,292 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use\sammo\{
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command
|
||||
};
|
||||
|
||||
use function\sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery,
|
||||
getAllNationStaticInfo
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
class che_인재탐색 extends Command\GeneralCommand
|
||||
{
|
||||
static protected $actionName = '인재탐색';
|
||||
|
||||
protected function argTest(): bool
|
||||
{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setNation();
|
||||
$env = $this->env;
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$db = DB::db();
|
||||
$env = $this->env;
|
||||
|
||||
$maxGenCnt = $env['maxgeneral'];
|
||||
$totalGenCnt = $db->queryFirstField('SELECT count(no) FROM general WHERE npc <= 2');
|
||||
$totalNpcCnt = $db->queryFirstField('SELECT count(`no`) FROM general WHERE 3 <= npc AND npc <= 4');
|
||||
|
||||
$name = $this->getName();
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$foundProp = $this->calcFoundProp($maxGenCnt, $totalGenCnt, $totalNpcCnt);
|
||||
$foundPropText = number_format($foundProp * 100, 1);
|
||||
|
||||
$title = "{$name}(랜덤경험";
|
||||
if ($reqGold > 0) {
|
||||
$title .= ", 자금{$reqGold}";
|
||||
}
|
||||
if ($reqRice > 0) {
|
||||
$title .= ", 군량{$reqRice}";
|
||||
}
|
||||
|
||||
$title .= ", 확률 {$foundPropText}%)";
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getCost(): array
|
||||
{
|
||||
return [$this->env['develcost'], 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function calcFoundProp(int $maxGenCnt, int $totalGenCnt, int $totalNpcCnt): float
|
||||
{
|
||||
|
||||
|
||||
$currCnt = Util::toInt($totalGenCnt + $totalNpcCnt / 2);
|
||||
$remainSlot = $maxGenCnt - $currCnt;
|
||||
if ($remainSlot < 0) {
|
||||
$remainSlot = 0;
|
||||
}
|
||||
|
||||
$foundPropMain = pow($remainSlot / $maxGenCnt, 6);
|
||||
$foundPropSmall = 1 / ($totalNpcCnt / 3 + 1);
|
||||
$foundPropBig = 1 / $maxGenCnt;
|
||||
|
||||
if ($totalNpcCnt < 50) {
|
||||
$foundProp = max($foundPropMain, $foundPropSmall);
|
||||
} else {
|
||||
$foundProp = max($foundPropMain, $foundPropBig);
|
||||
}
|
||||
return $foundProp;
|
||||
}
|
||||
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$env = $this->env;
|
||||
$relYear = $env['year'] - $env['startyear'];
|
||||
|
||||
$general = $this->generalObj;
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$nationID = $general->getNationID();
|
||||
|
||||
$nationCnt = count(getAllNationStaticInfo());
|
||||
|
||||
$totalGenCnt = $db->queryFirstField('SELECT count(no) FROM general WHERE npc <= 2');
|
||||
$totalNpcCnt = $db->queryFirstField('SELECT count(`no`) FROM general WHERE 3 <= npc AND npc <= 4');
|
||||
|
||||
$genCnt = $db->queryFirstField('SELECT count(no) FROM general WHERE nation=%i AND npc < 2', $nationID);
|
||||
$npcCnt = $db->queryFirstField('SELECT count(no) FROM general WHERE nation=%i AND 3 <= npc AND npc <= 4', $nationID);
|
||||
|
||||
$currCnt = Util::toInt($totalGenCnt + $totalNpcCnt / 2);
|
||||
$avgCnt = $currCnt / $nationCnt;
|
||||
|
||||
$foundNpc = Util::randBool($this->calcFoundProp($env['maxgeneral'], $totalGenCnt, $totalNpcCnt));
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
if (!$foundNpc) {
|
||||
$logger->pushGeneralActionLog("인재를 찾을 수 없었습니다. <1>$date</>");
|
||||
|
||||
$incStat = Util::choiceRandomUsingWeight([
|
||||
'leadership_exp' => $general->getLeadership(false, false, false, false),
|
||||
'strength_exp' => $general->getStrength(false, false, false, false),
|
||||
'intel_exp' => $general->getIntel(false, false, false, false)
|
||||
]);
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$exp = 100;
|
||||
$ded = 70;
|
||||
|
||||
$general->increaseVarWithLimit('gold', -$reqGold, 0);
|
||||
$general->increaseVarWithLimit('rice', -$reqRice, 0);
|
||||
$general->addExperience($exp);
|
||||
$general->addDedication($ded);
|
||||
$general->increaseVar($incStat, 1);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
return true;
|
||||
}
|
||||
//인간적으로 너무 길어서 끊었다!
|
||||
|
||||
$exp = 200;
|
||||
$ded = 300;
|
||||
|
||||
$pickTypeList = ['무' => 6, '지' => 6, '무지' => 3];
|
||||
|
||||
$pickType = Util::choiceRandomUsingWeight($pickTypeList);
|
||||
|
||||
$totalStat = GameConst::$defaultStatNPCTotal;
|
||||
$minStat = GameConst::$defaultStatNPCMin;
|
||||
$mainStat = GameConst::$defaultStatNPCMax - Util::randRangeInt(0, GameConst::$defaultStatNPCMin);
|
||||
$otherStat = $minStat + Util::randRangeInt(0, Util::toInt(GameConst::$defaultStatNPCMin/2));
|
||||
$subStat = $totalStat - $mainStat - $otherStat;
|
||||
if ($subStat < $minStat) {
|
||||
$subStat = $otherStat;
|
||||
$otherStat = $minStat;
|
||||
$mainStat = $totalStat - $subStat - $otherStat;
|
||||
if ($mainStat) {
|
||||
throw new \LogicException('기본 스탯 설정값이 잘못되어 있음');
|
||||
}
|
||||
}
|
||||
|
||||
$avgGen = $db->queryFirstRow(
|
||||
'SELECT avg(dedication) as ded,avg(experience) as exp,
|
||||
avg(dex1+dex2+dex3+dex4) as dex_t, avg(age) as age, avg(dex5) as dex5
|
||||
from general where npc < 5',
|
||||
$nationID
|
||||
);
|
||||
$dexTotal = $avgGen['dex_t'];
|
||||
|
||||
if ($pickType == '무') {
|
||||
$leadership = $subStat;
|
||||
$strength = $mainStat;
|
||||
$intel = $otherStat;
|
||||
$dexVal = Util::choiceRandom([
|
||||
[$dexTotal * 5 / 8, $dexTotal / 8, $dexTotal / 8, $dexTotal / 8],
|
||||
[$dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8, $dexTotal / 8],
|
||||
[$dexTotal / 8, $dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8],
|
||||
]);
|
||||
} else if ($pickType == '지') {
|
||||
$leadership = $subStat;
|
||||
$strength = $otherStat;
|
||||
$intel = $mainStat;
|
||||
$dexVal = [$dexTotal / 8, $dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8];
|
||||
} else {
|
||||
$leadership = $otherStat;
|
||||
$strength = $subStat;
|
||||
$intel = $mainStat;
|
||||
$dexVal = [$dexTotal / 4, $dexTotal / 4, $dexTotal / 4, $dexTotal / 4];
|
||||
}
|
||||
|
||||
$leadership = Util::round($leadership);
|
||||
$strength = Util::round($strength);
|
||||
$intel = Util::round($intel);
|
||||
|
||||
$scoutType = "발견";
|
||||
$scoutLevel = 0;
|
||||
$scoutNation = 0;
|
||||
|
||||
$age = Util::randRangeInt(20, 25);
|
||||
$birthYear = $env['year'] - $age;
|
||||
$deathYear = $env['year'] + Util::randRangeInt(10, 50);
|
||||
|
||||
$cityID = Util::choiceRandom(array_keys(\sammo\CityConst::all()));
|
||||
$newNPC = new \sammo\Scenario\NPC(
|
||||
Util::randRangeInt(1, 150),
|
||||
\sammo\getRandGenName(),
|
||||
null,
|
||||
$scoutNation,
|
||||
$cityID,
|
||||
$leadership,
|
||||
$strength,
|
||||
$intel,
|
||||
$scoutLevel,
|
||||
$birthYear,
|
||||
$deathYear,
|
||||
null,
|
||||
null
|
||||
);
|
||||
$newNPC->npc = 3;
|
||||
$newNPC->setMoney(1000, 1000);
|
||||
$newNPC->setExpDed($avgGen['exp'], $avgGen['ded']);
|
||||
$newNPC->setSpecYear(
|
||||
Util::round((GameConst::$retirementYear - $age) / 12) + $age,
|
||||
Util::round((GameConst::$retirementYear - $age) / 6) + $age
|
||||
);
|
||||
$newNPC->setDex(
|
||||
$dexVal[0],
|
||||
$dexVal[1],
|
||||
$dexVal[2],
|
||||
$dexVal[3],
|
||||
$avgGen['dex5']
|
||||
);
|
||||
|
||||
$newNPC->build($this->env);
|
||||
$npcName = $newNPC->realName;
|
||||
$josaRa = JosaUtil::pick($npcName, '라');
|
||||
|
||||
$generalName = $general->getName();
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
|
||||
$logger->pushGeneralActionLog("<Y>$npcName</>{$josaRa}는 <C>인재</>를 {$scoutType}하였습니다! <1>$date</>");
|
||||
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <Y>$npcName</>{$josaRa}는 <C>인재</>를 {$scoutType}하였습니다!");
|
||||
$logger->pushGeneralHistoryLog("<Y>$npcName</>{$josaRa}는 <C>인재</>를 {$scoutType}");
|
||||
|
||||
$incStat = Util::choiceRandomUsingWeight([
|
||||
'leadership_exp' => $general->getLeadership(false, false, false, false),
|
||||
'strength_exp' => $general->getStrength(false, false, false, false),
|
||||
'intel_exp' => $general->getIntel(false, false, false, false)
|
||||
]);
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$exp = 200;
|
||||
$ded = 300;
|
||||
|
||||
$general->increaseVarWithLimit('gold', -$reqGold, 0);
|
||||
$general->increaseVarWithLimit('rice', -$reqRice, 0);
|
||||
$general->addExperience($exp);
|
||||
$general->addDedication($ded);
|
||||
$general->increaseVar($incStat, 3);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use\sammo\{
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command
|
||||
};
|
||||
|
||||
use function\sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery,
|
||||
getAllNationStaticInfo
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
class che_인재탐색 extends Command\GeneralCommand
|
||||
{
|
||||
static protected $actionName = '인재탐색';
|
||||
|
||||
protected function argTest(): bool
|
||||
{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setNation();
|
||||
$env = $this->env;
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$db = DB::db();
|
||||
$env = $this->env;
|
||||
|
||||
$maxGenCnt = $env['maxgeneral'];
|
||||
$totalGenCnt = $db->queryFirstField('SELECT count(no) FROM general WHERE npc <= 2');
|
||||
$totalNpcCnt = $db->queryFirstField('SELECT count(`no`) FROM general WHERE 3 <= npc AND npc <= 4');
|
||||
|
||||
$name = $this->getName();
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$foundProp = $this->calcFoundProp($maxGenCnt, $totalGenCnt, $totalNpcCnt);
|
||||
$foundPropText = number_format($foundProp * 100, 1);
|
||||
|
||||
$title = "{$name}(랜덤경험";
|
||||
if ($reqGold > 0) {
|
||||
$title .= ", 자금{$reqGold}";
|
||||
}
|
||||
if ($reqRice > 0) {
|
||||
$title .= ", 군량{$reqRice}";
|
||||
}
|
||||
|
||||
$title .= ", 확률 {$foundPropText}%)";
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getCost(): array
|
||||
{
|
||||
return [$this->env['develcost'], 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function calcFoundProp(int $maxGenCnt, int $totalGenCnt, int $totalNpcCnt): float
|
||||
{
|
||||
|
||||
|
||||
$currCnt = Util::toInt($totalGenCnt + $totalNpcCnt / 2);
|
||||
$remainSlot = $maxGenCnt - $currCnt;
|
||||
if ($remainSlot < 0) {
|
||||
$remainSlot = 0;
|
||||
}
|
||||
|
||||
$foundPropMain = pow($remainSlot / $maxGenCnt, 6);
|
||||
$foundPropSmall = 1 / ($totalNpcCnt / 3 + 1);
|
||||
$foundPropBig = 1 / $maxGenCnt;
|
||||
|
||||
if ($totalNpcCnt < 50) {
|
||||
$foundProp = max($foundPropMain, $foundPropSmall);
|
||||
} else {
|
||||
$foundProp = max($foundPropMain, $foundPropBig);
|
||||
}
|
||||
return $foundProp;
|
||||
}
|
||||
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$env = $this->env;
|
||||
$relYear = $env['year'] - $env['startyear'];
|
||||
|
||||
$general = $this->generalObj;
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$nationID = $general->getNationID();
|
||||
|
||||
$totalGenCnt = $db->queryFirstField('SELECT count(no) FROM general WHERE npc <= 2');
|
||||
$totalNpcCnt = $db->queryFirstField('SELECT count(`no`) FROM general WHERE 3 <= npc AND npc <= 4');
|
||||
|
||||
$foundNpc = Util::randBool($this->calcFoundProp($env['maxgeneral'], $totalGenCnt, $totalNpcCnt));
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
if (!$foundNpc) {
|
||||
$logger->pushGeneralActionLog("인재를 찾을 수 없었습니다. <1>$date</>");
|
||||
|
||||
$incStat = Util::choiceRandomUsingWeight([
|
||||
'leadership_exp' => $general->getLeadership(false, false, false, false),
|
||||
'strength_exp' => $general->getStrength(false, false, false, false),
|
||||
'intel_exp' => $general->getIntel(false, false, false, false)
|
||||
]);
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$exp = 100;
|
||||
$ded = 70;
|
||||
|
||||
$general->increaseVarWithLimit('gold', -$reqGold, 0);
|
||||
$general->increaseVarWithLimit('rice', -$reqRice, 0);
|
||||
$general->addExperience($exp);
|
||||
$general->addDedication($ded);
|
||||
$general->increaseVar($incStat, 1);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
return true;
|
||||
}
|
||||
//인간적으로 너무 길어서 끊었다!
|
||||
|
||||
$exp = 200;
|
||||
$ded = 300;
|
||||
|
||||
$pickTypeList = ['무' => 6, '지' => 6, '무지' => 3];
|
||||
|
||||
$pickType = Util::choiceRandomUsingWeight($pickTypeList);
|
||||
|
||||
$totalStat = GameConst::$defaultStatNPCTotal;
|
||||
$minStat = GameConst::$defaultStatNPCMin;
|
||||
$mainStat = GameConst::$defaultStatNPCMax - Util::randRangeInt(0, GameConst::$defaultStatNPCMin);
|
||||
$otherStat = $minStat + Util::randRangeInt(0, Util::toInt(GameConst::$defaultStatNPCMin/2));
|
||||
$subStat = $totalStat - $mainStat - $otherStat;
|
||||
if ($subStat < $minStat) {
|
||||
$subStat = $otherStat;
|
||||
$otherStat = $minStat;
|
||||
$mainStat = $totalStat - $subStat - $otherStat;
|
||||
if ($mainStat) {
|
||||
throw new \LogicException('기본 스탯 설정값이 잘못되어 있음');
|
||||
}
|
||||
}
|
||||
|
||||
$avgGen = $db->queryFirstRow(
|
||||
'SELECT avg(dedication) as ded,avg(experience) as exp,
|
||||
avg(dex1+dex2+dex3+dex4) as dex_t, avg(age) as age, avg(dex5) as dex5
|
||||
from general where npc < 5',
|
||||
$nationID
|
||||
);
|
||||
$dexTotal = $avgGen['dex_t'];
|
||||
|
||||
if ($pickType == '무') {
|
||||
$leadership = $subStat;
|
||||
$strength = $mainStat;
|
||||
$intel = $otherStat;
|
||||
$dexVal = Util::choiceRandom([
|
||||
[$dexTotal * 5 / 8, $dexTotal / 8, $dexTotal / 8, $dexTotal / 8],
|
||||
[$dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8, $dexTotal / 8],
|
||||
[$dexTotal / 8, $dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8],
|
||||
]);
|
||||
} else if ($pickType == '지') {
|
||||
$leadership = $subStat;
|
||||
$strength = $otherStat;
|
||||
$intel = $mainStat;
|
||||
$dexVal = [$dexTotal / 8, $dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8];
|
||||
} else {
|
||||
$leadership = $otherStat;
|
||||
$strength = $subStat;
|
||||
$intel = $mainStat;
|
||||
$dexVal = [$dexTotal / 4, $dexTotal / 4, $dexTotal / 4, $dexTotal / 4];
|
||||
}
|
||||
|
||||
$leadership = Util::round($leadership);
|
||||
$strength = Util::round($strength);
|
||||
$intel = Util::round($intel);
|
||||
|
||||
$scoutType = "발견";
|
||||
$scoutLevel = 0;
|
||||
$scoutNation = 0;
|
||||
|
||||
$age = Util::randRangeInt(20, 25);
|
||||
$birthYear = $env['year'] - $age;
|
||||
$deathYear = $env['year'] + Util::randRangeInt(10, 50);
|
||||
|
||||
$cityID = Util::choiceRandom(array_keys(\sammo\CityConst::all()));
|
||||
$newNPC = new \sammo\Scenario\NPC(
|
||||
Util::randRangeInt(1, 150),
|
||||
\sammo\getRandGenName(),
|
||||
null,
|
||||
$scoutNation,
|
||||
$cityID,
|
||||
$leadership,
|
||||
$strength,
|
||||
$intel,
|
||||
$scoutLevel,
|
||||
$birthYear,
|
||||
$deathYear,
|
||||
null,
|
||||
null
|
||||
);
|
||||
$newNPC->npc = 3;
|
||||
$newNPC->setMoney(1000, 1000);
|
||||
$newNPC->setExpDed($avgGen['exp'], $avgGen['ded']);
|
||||
$newNPC->setSpecYear(
|
||||
Util::round((GameConst::$retirementYear - $age) / 12) + $age,
|
||||
Util::round((GameConst::$retirementYear - $age) / 6) + $age
|
||||
);
|
||||
$newNPC->setDex(
|
||||
$dexVal[0],
|
||||
$dexVal[1],
|
||||
$dexVal[2],
|
||||
$dexVal[3],
|
||||
$avgGen['dex5']
|
||||
);
|
||||
|
||||
$newNPC->build($this->env);
|
||||
$npcName = $newNPC->realName;
|
||||
$josaRa = JosaUtil::pick($npcName, '라');
|
||||
|
||||
$generalName = $general->getName();
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
|
||||
$logger->pushGeneralActionLog("<Y>$npcName</>{$josaRa}는 <C>인재</>를 {$scoutType}하였습니다! <1>$date</>");
|
||||
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <Y>$npcName</>{$josaRa}는 <C>인재</>를 {$scoutType}하였습니다!");
|
||||
$logger->pushGeneralHistoryLog("<Y>$npcName</>{$josaRa}는 <C>인재</>를 {$scoutType}");
|
||||
|
||||
$incStat = Util::choiceRandomUsingWeight([
|
||||
'leadership_exp' => $general->getLeadership(false, false, false, false),
|
||||
'strength_exp' => $general->getStrength(false, false, false, false),
|
||||
'intel_exp' => $general->getIntel(false, false, false, false)
|
||||
]);
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$exp = 200;
|
||||
$ded = 300;
|
||||
|
||||
$general->increaseVarWithLimit('gold', -$reqGold, 0);
|
||||
$general->increaseVarWithLimit('rice', -$reqRice, 0);
|
||||
$general->addExperience($exp);
|
||||
$general->addDedication($ded);
|
||||
$general->increaseVar($incStat, 3);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,130 +1,110 @@
|
||||
<?php
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst, GameUnitConst,
|
||||
LastTurn,
|
||||
Command
|
||||
};
|
||||
|
||||
|
||||
use function \sammo\{
|
||||
tryUniqueItemLottery
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
|
||||
class che_전투특기초기화 extends Command\GeneralCommand{
|
||||
static protected $actionName = '전투 특기 초기화';
|
||||
static protected $specialType = 'special2';
|
||||
static protected $speicalAge = 'specage2';
|
||||
static protected $specialText = '전투 특기';
|
||||
|
||||
protected function argTest():bool{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
|
||||
$general = $this->generalObj;
|
||||
$env = $this->env;
|
||||
$yearMonth = Util::joinYearMonth($env['year'], $env['month']);
|
||||
$auxYearMonth = $general->getAuxVar('used_'.$this->getName())??-999;
|
||||
|
||||
if($yearMonth < $auxYearMonth + 60){
|
||||
$this->minConditionConstraints=[
|
||||
ConstraintHelper::AlwaysFail('초기화한 지 5년이 지나야합니다')
|
||||
];
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::AlwaysFail('초기화한 지 5년이 지나야합니다')
|
||||
];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
ConstraintHelper::ReqGeneralValue(static::$specialType, static::$specialText, '!=', 'None', '특기가 없습니다.'),
|
||||
];
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::ReqGeneralValue(static::$specialType, static::$specialText, '!=', 'None', '특기가 없습니다.')
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
if($this->getPreReqTurn()){
|
||||
$reqTurn = ($this->getPreReqTurn()+1).'턴, ';
|
||||
}
|
||||
else{
|
||||
$reqTurn = 0;
|
||||
}
|
||||
|
||||
$title = "{$name}({$reqTurn}5년마다 1회)";
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getTermString():string{
|
||||
$term = $this->getResultTurn()->getTerm();
|
||||
$termMax = $this->getPreReqTurn() + 1;
|
||||
return "새로운 적성을 찾는 중... ({$term}/{$termMax})";
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$oldTypeKey = 'prev_types_'.static::$specialType;
|
||||
$specialName = static::$specialText;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$yearMonth = Util::joinYearMonth($env['year'], $env['month']);
|
||||
$oldSpecialList = $general->getAuxVar($oldTypeKey)??[];
|
||||
$oldSpecialList[] = $general->getVar(static::$specialType);
|
||||
$general->setAuxVar($oldTypeKey, $oldSpecialList);
|
||||
|
||||
$general->setVar(static::$specialType, 'None');
|
||||
$general->setVar(static::$speicalAge, $general->getVar('age') + 1);
|
||||
$general->setAuxVar('used_'.$this->getName(), $yearMonth);
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$logger->pushGeneralActionLog("새로운 {$specialName}를 가질 준비가 되었습니다. <1>$date</>");
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
<?php
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst, GameUnitConst,
|
||||
LastTurn,
|
||||
Command
|
||||
};
|
||||
|
||||
|
||||
use function \sammo\{
|
||||
tryUniqueItemLottery
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
|
||||
class che_전투특기초기화 extends Command\GeneralCommand{
|
||||
static protected $actionName = '전투 특기 초기화';
|
||||
static protected $specialType = 'special2';
|
||||
static protected $speicalAge = 'specage2';
|
||||
static protected $specialText = '전투 특기';
|
||||
|
||||
protected function argTest():bool{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
$this->minConditionConstraints=[
|
||||
ConstraintHelper::ReqGeneralValue(static::$specialType, static::$specialText, '!=', 'None', '특기가 없습니다.'),
|
||||
];
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::ReqGeneralValue(static::$specialType, static::$specialText, '!=', 'None', '특기가 없습니다.')
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
if($this->getPreReqTurn()){
|
||||
$reqTurn = ($this->getPreReqTurn()+1).'턴, ';
|
||||
}
|
||||
else{
|
||||
$reqTurn = 0;
|
||||
}
|
||||
|
||||
$title = "{$name}({$reqTurn}5년마다 1회)";
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
return 60;
|
||||
}
|
||||
|
||||
public function getTermString():string{
|
||||
$term = $this->getResultTurn()->getTerm();
|
||||
$termMax = $this->getPreReqTurn() + 1;
|
||||
return "새로운 적성을 찾는 중... ({$term}/{$termMax})";
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$oldTypeKey = 'prev_types_'.static::$specialType;
|
||||
$specialName = static::$specialText;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$yearMonth = Util::joinYearMonth($env['year'], $env['month']);
|
||||
$oldSpecialList = $general->getAuxVar($oldTypeKey)??[];
|
||||
$oldSpecialList[] = $general->getVar(static::$specialType);
|
||||
$general->setAuxVar($oldTypeKey, $oldSpecialList);
|
||||
|
||||
$general->setVar(static::$specialType, 'None');
|
||||
$general->setVar(static::$speicalAge, $general->getVar('age') + 1);
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$logger->pushGeneralActionLog("새로운 {$specialName}를 가질 준비가 되었습니다. <1>$date</>");
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,191 +1,191 @@
|
||||
<?php
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
class che_정착장려 extends Command\GeneralCommand{
|
||||
static protected $cityKey = 'pop';
|
||||
static protected $statKey = 'leadership';
|
||||
static protected $actionKey = '인구';
|
||||
static protected $actionName = '정착 장려';
|
||||
|
||||
protected $reqRice;
|
||||
|
||||
protected function argTest():bool{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation();
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::NotWanderingNation(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice),
|
||||
ConstraintHelper::RemainCityCapacity(static::$cityKey, static::$actionName)
|
||||
];
|
||||
|
||||
$this->reqRice = $reqRice;
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
$statTypeBase = [
|
||||
'leadership'=>'통솔경험',
|
||||
'strength'=>'무력경험',
|
||||
'intel'=>'지력경험',
|
||||
];
|
||||
$statType = $statTypeBase[static::$statKey];
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$title = "{$name}({$statType}";
|
||||
if($reqGold > 0){
|
||||
$title .= ", 자금{$reqGold}";
|
||||
}
|
||||
if($reqRice > 0){
|
||||
$title .= ", 군량{$reqRice}";
|
||||
}
|
||||
$title .= ')';
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
$develCost = $this->env['develcost'] * 2;
|
||||
$reqGold = 0;
|
||||
$reqRice = Util::round($this->generalObj->onCalcDomestic(static::$actionKey, 'cost', $develCost));
|
||||
|
||||
return [$reqGold, $reqRice];
|
||||
}
|
||||
|
||||
public function getCompensationStyle():?int{
|
||||
return $this->generalObj->onCalcDomestic(static::$actionKey, 'score', 100)<=>100;
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function calcBaseScore():float{
|
||||
$general = $this->generalObj;
|
||||
|
||||
if(static::$statKey == 'leadership'){
|
||||
$score = $general->getLeadership(true, true, true, false);
|
||||
}
|
||||
else{
|
||||
throw new \sammo\MustNotBeReachedException();
|
||||
}
|
||||
|
||||
$score *= getDomesticExpLevelBonus($general->getVar('explevel'));
|
||||
$score *= Util::randRange(0.8, 1.2);
|
||||
$score = $general->onCalcDomestic(static::$actionKey, 'score', $score);
|
||||
|
||||
return $score;
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$score = Util::valueFit($this->calcBaseScore(), 1);
|
||||
|
||||
['success'=>$successRatio, 'fail'=>$failRatio] = CriticalRatioDomestic($general, static::$statKey);
|
||||
$successRatio = $general->onCalcDomestic(static::$cityKey, 'success', $successRatio);
|
||||
$failRatio = $general->onCalcDomestic(static::$cityKey, 'fail', $failRatio);
|
||||
|
||||
$successRatio = Util::valueFit($successRatio, 0, 1);
|
||||
$failRatio = Util::valueFit($failRatio, 0, 1 - $successRatio);
|
||||
$normalRatio = 1 - $failRatio - $successRatio;
|
||||
|
||||
$pick = Util::choiceRandomUsingWeight([
|
||||
'fail'=>$failRatio,
|
||||
'success'=>$successRatio,
|
||||
'normal'=>$normalRatio
|
||||
]);
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$score *= CriticalScoreEx($pick);
|
||||
$score = Util::round($score);
|
||||
|
||||
$exp = $score * 0.7;
|
||||
$ded = $score * 1.0;
|
||||
|
||||
$score *= 10;
|
||||
|
||||
$scoreText = number_format($score, 0);
|
||||
|
||||
$josaUl = JosaUtil::pick(static::$actionName, '을');
|
||||
if($pick == 'fail'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <span class='ev_failed'>실패</span>하여 주민이 <C>$scoreText</>명 증가했습니다. <1>$date</>");
|
||||
}
|
||||
else if($pick == 'success'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <S>성공</>하여 주민이 <C>$scoreText</>명 증가했습니다. <1>$date</>");
|
||||
}
|
||||
else{
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} 하여 주민이 <C>$scoreText</>명 증가했습니다. <1>$date</>");
|
||||
}
|
||||
|
||||
//NOTE: 내정량 상승시 초과 가능?
|
||||
$cityUpdated = [
|
||||
static::$cityKey => Util::valueFit(
|
||||
$this->city[static::$cityKey] + $score,
|
||||
0,
|
||||
$this->city[static::$cityKey.'_max']
|
||||
)
|
||||
];
|
||||
$db->update('city', $cityUpdated, 'city=%i', $general->getVar('city'));
|
||||
|
||||
$general->increaseVarWithLimit('rice', -$this->reqRice, 0);
|
||||
$general->addExperience($exp);
|
||||
$general->addDedication($ded);
|
||||
$general->increaseVar(static::$statKey.'_exp', 1);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
<?php
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
class che_정착장려 extends Command\GeneralCommand{
|
||||
static protected $cityKey = 'pop';
|
||||
static protected $statKey = 'leadership';
|
||||
static protected $actionKey = '인구';
|
||||
static protected $actionName = '정착 장려';
|
||||
|
||||
protected $reqRice;
|
||||
|
||||
protected function argTest():bool{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation();
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::NotWanderingNation(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice),
|
||||
ConstraintHelper::RemainCityCapacity(static::$cityKey, static::$actionName)
|
||||
];
|
||||
|
||||
$this->reqRice = $reqRice;
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
$statTypeBase = [
|
||||
'leadership'=>'통솔경험',
|
||||
'strength'=>'무력경험',
|
||||
'intel'=>'지력경험',
|
||||
];
|
||||
$statType = $statTypeBase[static::$statKey];
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$title = "{$name}({$statType}";
|
||||
if($reqGold > 0){
|
||||
$title .= ", 자금{$reqGold}";
|
||||
}
|
||||
if($reqRice > 0){
|
||||
$title .= ", 군량{$reqRice}";
|
||||
}
|
||||
$title .= ')';
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
$develCost = $this->env['develcost'] * 2;
|
||||
$reqGold = 0;
|
||||
$reqRice = Util::round($this->generalObj->onCalcDomestic(static::$actionKey, 'cost', $develCost));
|
||||
|
||||
return [$reqGold, $reqRice];
|
||||
}
|
||||
|
||||
public function getCompensationStyle():?int{
|
||||
return $this->generalObj->onCalcDomestic(static::$actionKey, 'score', 100)<=>100;
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function calcBaseScore():float{
|
||||
$general = $this->generalObj;
|
||||
|
||||
if(static::$statKey == 'leadership'){
|
||||
$score = $general->getLeadership(true, true, true, false);
|
||||
}
|
||||
else{
|
||||
throw new \sammo\MustNotBeReachedException();
|
||||
}
|
||||
|
||||
$score *= getDomesticExpLevelBonus($general->getVar('explevel'));
|
||||
$score *= Util::randRange(0.8, 1.2);
|
||||
$score = $general->onCalcDomestic(static::$actionKey, 'score', $score);
|
||||
|
||||
return $score;
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$score = Util::valueFit($this->calcBaseScore(), 1);
|
||||
|
||||
['success'=>$successRatio, 'fail'=>$failRatio] = CriticalRatioDomestic($general, static::$statKey);
|
||||
$successRatio = $general->onCalcDomestic(static::$actionKey, 'success', $successRatio);
|
||||
$failRatio = $general->onCalcDomestic(static::$actionKey, 'fail', $failRatio);
|
||||
|
||||
$successRatio = Util::valueFit($successRatio, 0, 1);
|
||||
$failRatio = Util::valueFit($failRatio, 0, 1 - $successRatio);
|
||||
$normalRatio = 1 - $failRatio - $successRatio;
|
||||
|
||||
$pick = Util::choiceRandomUsingWeight([
|
||||
'fail'=>$failRatio,
|
||||
'success'=>$successRatio,
|
||||
'normal'=>$normalRatio
|
||||
]);
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$score *= CriticalScoreEx($pick);
|
||||
$score = Util::round($score);
|
||||
|
||||
$exp = $score * 0.7;
|
||||
$ded = $score * 1.0;
|
||||
|
||||
$score *= 10;
|
||||
|
||||
$scoreText = number_format($score, 0);
|
||||
|
||||
$josaUl = JosaUtil::pick(static::$actionName, '을');
|
||||
if($pick == 'fail'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <span class='ev_failed'>실패</span>하여 주민이 <C>$scoreText</>명 증가했습니다. <1>$date</>");
|
||||
}
|
||||
else if($pick == 'success'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <S>성공</>하여 주민이 <C>$scoreText</>명 증가했습니다. <1>$date</>");
|
||||
}
|
||||
else{
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} 하여 주민이 <C>$scoreText</>명 증가했습니다. <1>$date</>");
|
||||
}
|
||||
|
||||
//NOTE: 내정량 상승시 초과 가능?
|
||||
$cityUpdated = [
|
||||
static::$cityKey => Util::valueFit(
|
||||
$this->city[static::$cityKey] + $score,
|
||||
0,
|
||||
$this->city[static::$cityKey.'_max']
|
||||
)
|
||||
];
|
||||
$db->update('city', $cityUpdated, 'city=%i', $general->getVar('city'));
|
||||
|
||||
$general->increaseVarWithLimit('rice', -$this->reqRice, 0);
|
||||
$general->addExperience($exp);
|
||||
$general->addDedication($ded);
|
||||
$general->increaseVar(static::$statKey.'_exp', 1);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,191 +1,191 @@
|
||||
<?php
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
class che_주민선정 extends Command\GeneralCommand{
|
||||
static protected $cityKey = 'trust';
|
||||
static protected $statKey = 'leadership';
|
||||
static protected $actionKey = '민심';
|
||||
static protected $actionName = '주민 선정';
|
||||
|
||||
protected $reqRice;
|
||||
|
||||
protected function argTest():bool{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation();
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::NotWanderingNation(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice),
|
||||
ConstraintHelper::RemainCityTrust(static::$actionName)
|
||||
];
|
||||
|
||||
$this->reqRice = $reqRice;
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
$statTypeBase = [
|
||||
'leadership'=>'통솔경험',
|
||||
'strength'=>'무력경험',
|
||||
'intel'=>'지력경험',
|
||||
];
|
||||
$statType = $statTypeBase[static::$statKey];
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$title = "{$name}({$statType}";
|
||||
if($reqGold > 0){
|
||||
$title .= ", 자금{$reqGold}";
|
||||
}
|
||||
if($reqRice > 0){
|
||||
$title .= ", 군량{$reqRice}";
|
||||
}
|
||||
$title .= ')';
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
$develCost = $this->env['develcost'] * 2;
|
||||
$reqGold = 0;
|
||||
$reqRice = $this->generalObj->onCalcDomestic(static::$actionKey, 'cost', $develCost);
|
||||
|
||||
return [$reqGold, Util::round($reqRice)];
|
||||
}
|
||||
|
||||
public function getCompensationStyle():?int{
|
||||
return $this->generalObj->onCalcDomestic(static::$actionKey, 'score', 100)<=>100;
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function calcBaseScore():float{
|
||||
$general = $this->generalObj;
|
||||
|
||||
if(static::$statKey == 'leadership'){
|
||||
$score = $general->getLeadership(true, true, true, false);
|
||||
}
|
||||
else{
|
||||
throw new \sammo\MustNotBeReachedException();
|
||||
}
|
||||
|
||||
$score *= getDomesticExpLevelBonus($general->getVar('explevel'));
|
||||
$score *= Util::randRange(0.8, 1.2);
|
||||
$score = $general->onCalcDomestic(static::$actionKey, 'score', $score);
|
||||
$score = Util::valueFit($score, 1);
|
||||
|
||||
return $score;
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$score = Util::valueFit($this->calcBaseScore(), 1);
|
||||
|
||||
['success'=>$successRatio, 'fail'=>$failRatio] = CriticalRatioDomestic($general, static::$statKey);
|
||||
$successRatio = $general->onCalcDomestic(static::$cityKey, 'success', $successRatio);
|
||||
$failRatio = $general->onCalcDomestic(static::$cityKey, 'fail', $failRatio);
|
||||
|
||||
$successRatio = Util::valueFit($successRatio, 0, 1);
|
||||
$failRatio = Util::valueFit($failRatio, 0, 1 - $successRatio);
|
||||
$normalRatio = 1 - $failRatio - $successRatio;
|
||||
|
||||
$pick = Util::choiceRandomUsingWeight([
|
||||
'fail'=>$failRatio,
|
||||
'success'=>$successRatio,
|
||||
'normal'=>$normalRatio
|
||||
]);
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$score *= CriticalScoreEx($pick);
|
||||
|
||||
$exp = $score * 0.7;
|
||||
$ded = $score * 1.0;
|
||||
|
||||
$score /= 10;
|
||||
|
||||
$scoreText = number_format($score, 1);
|
||||
|
||||
$josaUl = JosaUtil::pick(static::$actionName, '을');
|
||||
if($pick == 'fail'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <span class='ev_failed'>실패</span>하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
else if($pick == 'success'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <S>성공</>하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
else{
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} 하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
|
||||
//NOTE: 내정량 상승시 초과 가능?
|
||||
$cityUpdated = [
|
||||
static::$cityKey => Util::valueFit(
|
||||
$this->city[static::$cityKey] + $score,
|
||||
0,
|
||||
100
|
||||
)
|
||||
];
|
||||
$db->update('city', $cityUpdated, 'city=%i', $general->getVar('city'));
|
||||
|
||||
$general->increaseVarWithLimit('rice', -$this->reqRice, 0);
|
||||
$general->addExperience($exp);
|
||||
$general->addDedication($ded);
|
||||
$general->increaseVar(static::$statKey.'_exp', 1);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
<?php
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
class che_주민선정 extends Command\GeneralCommand{
|
||||
static protected $cityKey = 'trust';
|
||||
static protected $statKey = 'leadership';
|
||||
static protected $actionKey = '민심';
|
||||
static protected $actionName = '주민 선정';
|
||||
|
||||
protected $reqRice;
|
||||
|
||||
protected function argTest():bool{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation();
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::NotWanderingNation(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice),
|
||||
ConstraintHelper::RemainCityTrust(static::$actionName)
|
||||
];
|
||||
|
||||
$this->reqRice = $reqRice;
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
$statTypeBase = [
|
||||
'leadership'=>'통솔경험',
|
||||
'strength'=>'무력경험',
|
||||
'intel'=>'지력경험',
|
||||
];
|
||||
$statType = $statTypeBase[static::$statKey];
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$title = "{$name}({$statType}";
|
||||
if($reqGold > 0){
|
||||
$title .= ", 자금{$reqGold}";
|
||||
}
|
||||
if($reqRice > 0){
|
||||
$title .= ", 군량{$reqRice}";
|
||||
}
|
||||
$title .= ')';
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
$develCost = $this->env['develcost'] * 2;
|
||||
$reqGold = 0;
|
||||
$reqRice = $this->generalObj->onCalcDomestic(static::$actionKey, 'cost', $develCost);
|
||||
|
||||
return [$reqGold, Util::round($reqRice)];
|
||||
}
|
||||
|
||||
public function getCompensationStyle():?int{
|
||||
return $this->generalObj->onCalcDomestic(static::$actionKey, 'score', 100)<=>100;
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function calcBaseScore():float{
|
||||
$general = $this->generalObj;
|
||||
|
||||
if(static::$statKey == 'leadership'){
|
||||
$score = $general->getLeadership(true, true, true, false);
|
||||
}
|
||||
else{
|
||||
throw new \sammo\MustNotBeReachedException();
|
||||
}
|
||||
|
||||
$score *= getDomesticExpLevelBonus($general->getVar('explevel'));
|
||||
$score *= Util::randRange(0.8, 1.2);
|
||||
$score = $general->onCalcDomestic(static::$actionKey, 'score', $score);
|
||||
$score = Util::valueFit($score, 1);
|
||||
|
||||
return $score;
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$score = Util::valueFit($this->calcBaseScore(), 1);
|
||||
|
||||
['success'=>$successRatio, 'fail'=>$failRatio] = CriticalRatioDomestic($general, static::$statKey);
|
||||
$successRatio = $general->onCalcDomestic(static::$actionKey, 'success', $successRatio);
|
||||
$failRatio = $general->onCalcDomestic(static::$actionKey, 'fail', $failRatio);
|
||||
|
||||
$successRatio = Util::valueFit($successRatio, 0, 1);
|
||||
$failRatio = Util::valueFit($failRatio, 0, 1 - $successRatio);
|
||||
$normalRatio = 1 - $failRatio - $successRatio;
|
||||
|
||||
$pick = Util::choiceRandomUsingWeight([
|
||||
'fail'=>$failRatio,
|
||||
'success'=>$successRatio,
|
||||
'normal'=>$normalRatio
|
||||
]);
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$score *= CriticalScoreEx($pick);
|
||||
|
||||
$exp = $score * 0.7;
|
||||
$ded = $score * 1.0;
|
||||
|
||||
$score /= 10;
|
||||
|
||||
$scoreText = number_format($score, 1);
|
||||
|
||||
$josaUl = JosaUtil::pick(static::$actionName, '을');
|
||||
if($pick == 'fail'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <span class='ev_failed'>실패</span>하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
else if($pick == 'success'){
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} <S>성공</>하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
else{
|
||||
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} 하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
|
||||
}
|
||||
|
||||
//NOTE: 내정량 상승시 초과 가능?
|
||||
$cityUpdated = [
|
||||
static::$cityKey => Util::valueFit(
|
||||
$this->city[static::$cityKey] + $score,
|
||||
0,
|
||||
100
|
||||
)
|
||||
];
|
||||
$db->update('city', $cityUpdated, 'city=%i', $general->getVar('city'));
|
||||
|
||||
$general->increaseVarWithLimit('rice', -$this->reqRice, 0);
|
||||
$general->addExperience($exp);
|
||||
$general->addDedication($ded);
|
||||
$general->increaseVar(static::$statKey.'_exp', 1);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryUniqueItemLottery($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,6 +1,37 @@
|
||||
<?php
|
||||
namespace sammo\Command;
|
||||
|
||||
abstract class GeneralCommand extends BaseCommand{
|
||||
|
||||
<?php
|
||||
namespace sammo\Command;
|
||||
use \sammo\Util;
|
||||
|
||||
abstract class GeneralCommand extends BaseCommand{
|
||||
|
||||
public function getNextExecuteKey():string{
|
||||
$turnKey = static::$actionName;
|
||||
$generalID = $this->getGeneral()->getID();
|
||||
$executeKey = "next_execute_{$generalID}_{$turnKey}";
|
||||
return $executeKey;
|
||||
}
|
||||
|
||||
public function getNextAvailableTurn():?int{
|
||||
if($this->isArgValid && !$this->getPostReqTurn()){
|
||||
return null;
|
||||
}
|
||||
$db = \sammo\DB::db();
|
||||
$lastExecuteStor = \sammo\KVStorage::getStorage($db, 'next_execute');
|
||||
return $lastExecuteStor->getValue($this->getNextExecuteKey());
|
||||
}
|
||||
|
||||
public function setNextAvailable(?int $yearMonth=null){
|
||||
if(!$this->getPostReqTurn()){
|
||||
return;
|
||||
}
|
||||
if($yearMonth === null){
|
||||
$yearMonth = Util::joinYearMonth($this->env['year'], $this->env['month'])
|
||||
+ $this->getPostReqTurn() - $this->getPreReqTurn();
|
||||
}
|
||||
|
||||
$db = \sammo\DB::db();
|
||||
$lastExecuteStor = \sammo\KVStorage::getStorage($db, 'next_execute');
|
||||
$lastExecuteStor->setValue($this->getNextExecuteKey(), $yearMonth);
|
||||
}
|
||||
|
||||
};
|
||||
+251
-251
@@ -1,251 +1,251 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use\sammo\{
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
Message,
|
||||
MessageTarget
|
||||
};
|
||||
|
||||
use function\sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
getAllNationStaticInfo,
|
||||
getNationStaticInfo,
|
||||
GetImageURL
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
class che_급습 extends Command\NationCommand
|
||||
{
|
||||
static protected $actionName = '급습';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
//NOTE: 멸망 직전에 턴을 넣을 수 있으므로, 존재하지 않는 국가여도 argTest에서 바로 탈락시키지 않음
|
||||
if (!key_exists('destNationID', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
$destNationID = $this->arg['destNationID'];
|
||||
|
||||
if (!is_int($destNationID)) {
|
||||
return false;
|
||||
}
|
||||
if ($destNationID < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->arg = [
|
||||
'destNationID' => $destNationID
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
|
||||
|
||||
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$this->setDestNation($this->arg['destNationID'], null);
|
||||
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::ExistsDestNation(),
|
||||
ConstraintHelper::AllowDiplomacyWithTerm(
|
||||
1,
|
||||
12,
|
||||
'선포 12개월 이상인 상대국에만 가능합니다.'
|
||||
),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn() + 1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(전략$postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount * 16) * 10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function getBrief(): string
|
||||
{
|
||||
$commandName = $this->getName();
|
||||
$destNationName = getNationStaticInfo($this->arg['destNationID'])['name'];
|
||||
return "【{$destNationName}】에 {$commandName}";
|
||||
}
|
||||
|
||||
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$env = $this->env;
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$year = $this->env['year'];
|
||||
$month = $this->env['month'];
|
||||
|
||||
$nation = $this->nation;
|
||||
$nationID = $nation['nation'];
|
||||
$nationName = $nation['name'];
|
||||
|
||||
$destNation = $this->destNation;
|
||||
$destNationID = $destNation['nation'];
|
||||
$destNationName = $destNation['name'];
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||
|
||||
$commandName = $this->getName();
|
||||
$josaUl = JosaUtil::pick($commandName, '을');
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$logger->pushGeneralActionLog("{$commandName} 발동! <1>$date</>");
|
||||
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <G><b>{$destNationName}</b></>에 <M>{$commandName}</>{$josaUl} 발동하였습니다.";
|
||||
|
||||
$nationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach ($nationGeneralList as $nationGeneralID) {
|
||||
$nationGeneralLogger = new ActionLogger($nationGeneralID, $nationID, $year, $month);
|
||||
$nationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$nationGeneralLogger->flush();
|
||||
}
|
||||
|
||||
$josaYiCommand = JosaUtil::pick($commandName, '이');
|
||||
|
||||
$broadcastMessage = "아국에 <M>{$commandName}</>{$josaYiCommand} 발동되었습니다.";
|
||||
|
||||
$destNationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach ($destNationGeneralList as $destNationGeneralID) {
|
||||
$destNationGeneralLogger = new ActionLogger($destNationGeneralID, $destNationID, $year, $month);
|
||||
$destNationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$destNationGeneralLogger->flush();
|
||||
}
|
||||
|
||||
$destNationLogger = new ActionLogger(0, $destNationID, $year, $month);
|
||||
$destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} 아국에 <M>{$commandName}</>{$josaUl} 발동");
|
||||
$destNationLogger->flush();
|
||||
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <D><b>{$destNationName}</b></>에 <M>{$commandName}</>{$josaUl} 발동");
|
||||
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $this->getPostReqTurn()
|
||||
], 'nation=%i', $nationID);
|
||||
$db->update('diplomacy', [
|
||||
'term' => $db->sqleval('`term` - %i', 3),
|
||||
], '(me = %i AND you = %i) OR (you = %i AND me = %i)', $nationID, $destNationID, $nationID, $destNationID);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSFiles(): array
|
||||
{
|
||||
return [
|
||||
'js/defaultSelectNationByMap.js'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationID = $generalObj->getNationID();
|
||||
$nationList = [];
|
||||
$testTurn = new LastTurn($this->getName(), null, $this->getPreReqTurn());
|
||||
foreach (getAllNationStaticInfo() as $destNation) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$testTurn->setArg(['destNationID' => $destNation['nation']]);
|
||||
$testCommand = new static($generalObj, $this->env, $testTurn, ['destNationID' => $destNation['nation']]);
|
||||
if ($testCommand->hasFullConditionMet()) {
|
||||
$destNation['availableCommand'] = true;
|
||||
} else {
|
||||
$destNation['availableCommand'] = false;
|
||||
}
|
||||
|
||||
$nationList[] = $destNation;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 국가에 급습을 발동합니다.<br>
|
||||
선포, 전쟁중인 상대국에만 가능합니다.<br>
|
||||
상대 국가를 목록에서 선택하세요.<br>
|
||||
배경색은 현재 급습 불가능 국가는 <font color=red>붉은색</font>으로 표시됩니다.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($nationList as $nation) : ?>
|
||||
<option value='<?= $nation['nation'] ?>' style='color:<?= $nation['color'] ?>;<?= $nation['availableCommand'] ? '' : 'background-color:red;' ?>'>【<?= $nation['name'] ?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
<input type=button id="commonSubmit" value="<?= $this->getName() ?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use\sammo\{
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
Message,
|
||||
MessageTarget
|
||||
};
|
||||
|
||||
use function\sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
getAllNationStaticInfo,
|
||||
getNationStaticInfo,
|
||||
GetImageURL
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
class che_급습 extends Command\NationCommand
|
||||
{
|
||||
static protected $actionName = '급습';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
//NOTE: 멸망 직전에 턴을 넣을 수 있으므로, 존재하지 않는 국가여도 argTest에서 바로 탈락시키지 않음
|
||||
if (!key_exists('destNationID', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
$destNationID = $this->arg['destNationID'];
|
||||
|
||||
if (!is_int($destNationID)) {
|
||||
return false;
|
||||
}
|
||||
if ($destNationID < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->arg = [
|
||||
'destNationID' => $destNationID
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
|
||||
|
||||
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$this->setDestNation($this->arg['destNationID'], null);
|
||||
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::ExistsDestNation(),
|
||||
ConstraintHelper::AllowDiplomacyWithTerm(
|
||||
1,
|
||||
12,
|
||||
'선포 12개월 이상인 상대국에만 가능합니다.'
|
||||
),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn() + 1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(재사용 대기 $postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount * 16) * 10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function getBrief(): string
|
||||
{
|
||||
$commandName = $this->getName();
|
||||
$destNationName = getNationStaticInfo($this->arg['destNationID'])['name'];
|
||||
return "【{$destNationName}】에 {$commandName}";
|
||||
}
|
||||
|
||||
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$env = $this->env;
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$year = $this->env['year'];
|
||||
$month = $this->env['month'];
|
||||
|
||||
$nation = $this->nation;
|
||||
$nationID = $nation['nation'];
|
||||
$nationName = $nation['name'];
|
||||
|
||||
$destNation = $this->destNation;
|
||||
$destNationID = $destNation['nation'];
|
||||
$destNationName = $destNation['name'];
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||
|
||||
$commandName = $this->getName();
|
||||
$josaUl = JosaUtil::pick($commandName, '을');
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$logger->pushGeneralActionLog("{$commandName} 발동! <1>$date</>");
|
||||
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <G><b>{$destNationName}</b></>에 <M>{$commandName}</>{$josaUl} 발동하였습니다.";
|
||||
|
||||
$nationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach ($nationGeneralList as $nationGeneralID) {
|
||||
$nationGeneralLogger = new ActionLogger($nationGeneralID, $nationID, $year, $month);
|
||||
$nationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$nationGeneralLogger->flush();
|
||||
}
|
||||
|
||||
$josaYiCommand = JosaUtil::pick($commandName, '이');
|
||||
|
||||
$broadcastMessage = "아국에 <M>{$commandName}</>{$josaYiCommand} 발동되었습니다.";
|
||||
|
||||
$destNationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach ($destNationGeneralList as $destNationGeneralID) {
|
||||
$destNationGeneralLogger = new ActionLogger($destNationGeneralID, $destNationID, $year, $month);
|
||||
$destNationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$destNationGeneralLogger->flush();
|
||||
}
|
||||
|
||||
$destNationLogger = new ActionLogger(0, $destNationID, $year, $month);
|
||||
$destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} 아국에 <M>{$commandName}</>{$josaUl} 발동");
|
||||
$destNationLogger->flush();
|
||||
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <D><b>{$destNationName}</b></>에 <M>{$commandName}</>{$josaUl} 발동");
|
||||
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $this->generalObj->onCalcStrategic($this->getName(), 'globalDelay', 9)
|
||||
], 'nation=%i', $nationID);
|
||||
$db->update('diplomacy', [
|
||||
'term' => $db->sqleval('`term` - %i', 3),
|
||||
], '(me = %i AND you = %i) OR (you = %i AND me = %i)', $nationID, $destNationID, $nationID, $destNationID);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSFiles(): array
|
||||
{
|
||||
return [
|
||||
'js/defaultSelectNationByMap.js'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationID = $generalObj->getNationID();
|
||||
$nationList = [];
|
||||
$testTurn = new LastTurn($this->getName(), null, $this->getPreReqTurn());
|
||||
foreach (getAllNationStaticInfo() as $destNation) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$testTurn->setArg(['destNationID' => $destNation['nation']]);
|
||||
$testCommand = new static($generalObj, $this->env, $testTurn, ['destNationID' => $destNation['nation']]);
|
||||
if ($testCommand->hasFullConditionMet()) {
|
||||
$destNation['availableCommand'] = true;
|
||||
} else {
|
||||
$destNation['availableCommand'] = false;
|
||||
}
|
||||
|
||||
$nationList[] = $destNation;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 국가에 급습을 발동합니다.<br>
|
||||
선포, 전쟁중인 상대국에만 가능합니다.<br>
|
||||
상대 국가를 목록에서 선택하세요.<br>
|
||||
배경색은 현재 급습 불가능 국가는 <font color=red>붉은색</font>으로 표시됩니다.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($nationList as $nation) : ?>
|
||||
<option value='<?= $nation['nation'] ?>' style='color:<?= $nation['color'] ?>;<?= $nation['availableCommand'] ? '' : 'background-color:red;' ?>'>【<?= $nation['name'] ?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
<input type=button id="commonSubmit" value="<?= $this->getName() ?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,282 +1,291 @@
|
||||
<?php
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
StringUtil
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
getAllNationStaticInfo,
|
||||
getNationStaticInfo
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
class che_물자원조 extends Command\NationCommand{
|
||||
static protected $actionName = '원조';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!key_exists('destNationID', $this->arg)){
|
||||
return false;
|
||||
}
|
||||
$destNationID = $this->arg['destNationID'];
|
||||
if(!is_int($destNationID)){
|
||||
return false;
|
||||
}
|
||||
if($destNationID < 1){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!key_exists('amountList', $this->arg)){
|
||||
return false;
|
||||
}
|
||||
$amountList = $this->arg['amountList'];
|
||||
if(!is_array($amountList)){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(count($amountList) != 2){
|
||||
return false;
|
||||
}
|
||||
|
||||
[$goldAmount, $riceAmount] = $amountList;
|
||||
|
||||
if(!is_int($goldAmount) || !is_int($riceAmount)){
|
||||
return false;
|
||||
}
|
||||
if($goldAmount < 0 || $riceAmount < 0){
|
||||
return false;
|
||||
}
|
||||
if($goldAmount == 0 && $riceAmount == 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->arg = [
|
||||
'destNationID'=>$destNationID,
|
||||
'amountList'=>[$goldAmount, $riceAmount]
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['gold', 'rice', 'surlimit']);
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqNationValue('surlimit', '외교제한', '==', 0, '외교제한중입니다.'),
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$destNationID = $this->arg['destNationID'];
|
||||
$this->setDestNation($destNationID, ['gold', 'rice', 'surlimit']);
|
||||
|
||||
[$goldAmount, $riceAmount] = $this->arg['amountList'];
|
||||
$limit = $this->nation['level'] * GameConst::$coefAidAmount;
|
||||
|
||||
if($goldAmount > $limit || $riceAmount > $limit){
|
||||
$this->fullConditionConstraints[
|
||||
ConstraintHelper::AlwaysFail('작위 제한량 이상은 보낼 수 없습니다.')
|
||||
];
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::ExistsDestNation(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqNationGold(GameConst::$basegold+(($goldAmount>0)?1:0)),
|
||||
ConstraintHelper::ReqNationRice(GameConst::$baserice+(($riceAmount>0)?1:0)),
|
||||
ConstraintHelper::ReqNationValue('surlimit', '외교제한', '==', 0, '외교제한중입니다.'),
|
||||
ConstraintHelper::ReqDestNationValue('surlimit', '외교제한', '==', 0, '상대국이 외교제한중입니다.'),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
return 12;
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
[$goldAmount, $riceAmount] = $this->arg['amountList'];
|
||||
$goldAmountText = number_format($goldAmount);
|
||||
$riceAmountText = number_format($riceAmount);
|
||||
$destNationName = $this->destNation['name'];
|
||||
$commandName = $this->getName();
|
||||
return "【{$destNationName}】에게 국고 {$goldAmountText} 병량 {$riceAmountText} {$commandName}";
|
||||
}
|
||||
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$nation = $this->nation;
|
||||
$nationID = $nation['nation'];
|
||||
$nationName = $nation['name'];
|
||||
|
||||
$destNationID = $this->destNation['nation'];
|
||||
$destNationName = $this->destNation['name'];
|
||||
|
||||
|
||||
[$goldAmount, $riceAmount] = $this->arg['amountList'];
|
||||
|
||||
|
||||
$goldAmount = Util::valueFit(
|
||||
$goldAmount,
|
||||
0,
|
||||
$nation['gold'] - GameConst::$basegold
|
||||
);
|
||||
|
||||
$riceAmount = Util::valueFit(
|
||||
$riceAmount,
|
||||
0,
|
||||
$nation['rice'] - GameConst::$baserice
|
||||
);
|
||||
|
||||
$goldAmountText = number_format($goldAmount);
|
||||
$riceAmountText = number_format($riceAmount);
|
||||
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$year = $this->env['year'];
|
||||
$month = $this->env['month'];
|
||||
|
||||
|
||||
|
||||
$josaRo = JosaUtil::pick($destNationName, '로');
|
||||
|
||||
|
||||
|
||||
$broadcastMessage = "<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원했습니다.";
|
||||
|
||||
$chiefList = $db->queryFirstColumn('SELECT no FROM general WHERE officer_level >= 5 AND no != %i AND nation = %i', $generalID, $nationID);
|
||||
foreach($chiefList as $chiefID){
|
||||
$chiefLogger = new ActionLogger($chiefID, $nationID, $year, $month);
|
||||
$chiefLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$chiefLogger->flush();
|
||||
}
|
||||
|
||||
$logger->pushGeneralHistoryLog("<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원");
|
||||
$logger->pushNationalHistoryLog("<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원");
|
||||
$logger->pushGlobalHistoryLog("<Y><b>【원조】</b></><D><b>{$nationName}</b></>에서 <D><b>{$destNationName}</b></>{$josaRo} 물자를 지원합니다");
|
||||
|
||||
$logger->pushGeneralActionLog($broadcastMessage);
|
||||
$logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>{$josaRo} 물자를 지원합니다. <1>$date</>", ActionLogger::PLAIN);
|
||||
|
||||
$destBroadcastMessage = $broadcastMessage = "<D><b>{$nationName}</b></>에서 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 원조했습니다.";
|
||||
$destChiefList = $db->queryFirstColumn('SELECT no FROM general WHERE officer_level >= 5 AND nation = %i', $destNationID);
|
||||
foreach($destChiefList as $destChiefID){
|
||||
$destChiefLogger = new ActionLogger($destChiefID, $nationID, $year, $month);
|
||||
$destChiefLogger->pushGeneralActionLog($destBroadcastMessage, ActionLogger::PLAIN);
|
||||
$destChiefLogger->flush();
|
||||
}
|
||||
|
||||
$josaRoSrc = JosaUtil::pick($nationName, '로');
|
||||
$destNationLogger = new ActionLogger(0, $destChiefID, $year, $month);
|
||||
$destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaRoSrc}부터 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원 받음");
|
||||
|
||||
|
||||
|
||||
$db->update('nation', [
|
||||
'gold'=>$db->sqleval('gold - %i', $goldAmount),
|
||||
'rice'=>$db->sqleval('rice - %i', $riceAmount),
|
||||
'surlimit'=>$db->sqleval('surlimit + %i', $this->getPostReqTurn())
|
||||
], 'nation = %i', $nationID);
|
||||
|
||||
$db->update('nation', [
|
||||
'gold'=>$db->sqleval('gold + %i', $goldAmount),
|
||||
'rice'=>$db->sqleval('rice + %i', $riceAmount),
|
||||
], 'nation = %i', $destNationID);
|
||||
|
||||
$general->addExperience(5);
|
||||
$general->addDedication(5);
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSFiles(): array
|
||||
{
|
||||
return [
|
||||
'js/defaultSelectNationByMap.js'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$currentNationLevel = getNationStaticInfo($this->generalObj->getNationID())['level'];
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
타국에게 원조합니다.<br>
|
||||
작위별로 금액 제한이 있습니다.<br>
|
||||
<?php foreach(\sammo\getNationLevelList() as $level => [$levelText,,]): ?>
|
||||
<?=StringUtil::padStringAlignRight($levelText, 10)?>: <?=number_format($level*GameConst::$coefAidAmount)?><br>
|
||||
<?php endforeach; ?>
|
||||
원조할 국가를 목록에서 선택하세요.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach(getAllNationStaticInfo() as $nation): ?>
|
||||
<option
|
||||
value='<?=$nation['nation']?>'
|
||||
style='color:<?=$nation['color']?>;'
|
||||
>【<?=$nation['name']?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
국고 <select class='formInput' name="amountList[]" class="amountList" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach(Util::range($currentNationLevel+1) as $nationLevel): ?>
|
||||
<option value='<?=$nationLevel*GameConst::$coefAidAmount?>'><?=$nationLevel*GameConst::$coefAidAmount?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
병량 <select class='formInput' name="amountList[]" class="amountList" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach(Util::range($currentNationLevel+1) as $nationLevel): ?>
|
||||
<option value='<?=$nationLevel*GameConst::$coefAidAmount?>'><?=$nationLevel*GameConst::$coefAidAmount?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
<?php
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
StringUtil
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
getAllNationStaticInfo,
|
||||
getNationStaticInfo
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
class che_물자원조 extends Command\NationCommand{
|
||||
static protected $actionName = '원조';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!key_exists('destNationID', $this->arg)){
|
||||
return false;
|
||||
}
|
||||
$destNationID = $this->arg['destNationID'];
|
||||
if(!is_int($destNationID)){
|
||||
return false;
|
||||
}
|
||||
if($destNationID < 1){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!key_exists('amountList', $this->arg)){
|
||||
return false;
|
||||
}
|
||||
$amountList = $this->arg['amountList'];
|
||||
if(!is_array($amountList)){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(count($amountList) != 2){
|
||||
return false;
|
||||
}
|
||||
|
||||
[$goldAmount, $riceAmount] = $amountList;
|
||||
|
||||
if(!is_int($goldAmount) || !is_int($riceAmount)){
|
||||
return false;
|
||||
}
|
||||
if($goldAmount < 0 || $riceAmount < 0){
|
||||
return false;
|
||||
}
|
||||
if($goldAmount == 0 && $riceAmount == 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->arg = [
|
||||
'destNationID'=>$destNationID,
|
||||
'amountList'=>[$goldAmount, $riceAmount]
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['gold', 'rice', 'surlimit']);
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqNationValue('surlimit', '외교제한', '==', 0, '외교제한중입니다.'),
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$destNationID = $this->arg['destNationID'];
|
||||
$this->setDestNation($destNationID, ['gold', 'rice', 'surlimit']);
|
||||
|
||||
[$goldAmount, $riceAmount] = $this->arg['amountList'];
|
||||
$limit = $this->nation['level'] * GameConst::$coefAidAmount;
|
||||
|
||||
if($goldAmount > $limit || $riceAmount > $limit){
|
||||
$this->fullConditionConstraints[
|
||||
ConstraintHelper::AlwaysFail('작위 제한량 이상은 보낼 수 없습니다.')
|
||||
];
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::ExistsDestNation(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqNationGold(GameConst::$basegold+(($goldAmount>0)?1:0)),
|
||||
ConstraintHelper::ReqNationRice(GameConst::$baserice+(($riceAmount>0)?1:0)),
|
||||
ConstraintHelper::ReqNationValue('surlimit', '외교제한', '==', 0, '외교제한중입니다.'),
|
||||
ConstraintHelper::ReqDestNationValue('surlimit', '외교제한', '==', 0, '상대국이 외교제한중입니다.'),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
//NOTE: 자체 postReqTurn 사용
|
||||
return 12;
|
||||
}
|
||||
|
||||
public function getNextAvailableTurn():?int{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setNextAvailable(?int $yearMonth=null){
|
||||
return;
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
[$goldAmount, $riceAmount] = $this->arg['amountList'];
|
||||
$goldAmountText = number_format($goldAmount);
|
||||
$riceAmountText = number_format($riceAmount);
|
||||
$destNationName = $this->destNation['name'];
|
||||
$commandName = $this->getName();
|
||||
return "【{$destNationName}】에게 국고 {$goldAmountText} 병량 {$riceAmountText} {$commandName}";
|
||||
}
|
||||
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$nation = $this->nation;
|
||||
$nationID = $nation['nation'];
|
||||
$nationName = $nation['name'];
|
||||
|
||||
$destNationID = $this->destNation['nation'];
|
||||
$destNationName = $this->destNation['name'];
|
||||
|
||||
|
||||
[$goldAmount, $riceAmount] = $this->arg['amountList'];
|
||||
|
||||
|
||||
$goldAmount = Util::valueFit(
|
||||
$goldAmount,
|
||||
0,
|
||||
$nation['gold'] - GameConst::$basegold
|
||||
);
|
||||
|
||||
$riceAmount = Util::valueFit(
|
||||
$riceAmount,
|
||||
0,
|
||||
$nation['rice'] - GameConst::$baserice
|
||||
);
|
||||
|
||||
$goldAmountText = number_format($goldAmount);
|
||||
$riceAmountText = number_format($riceAmount);
|
||||
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$year = $this->env['year'];
|
||||
$month = $this->env['month'];
|
||||
|
||||
|
||||
|
||||
$josaRo = JosaUtil::pick($destNationName, '로');
|
||||
|
||||
|
||||
|
||||
$broadcastMessage = "<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원했습니다.";
|
||||
|
||||
$chiefList = $db->queryFirstColumn('SELECT no FROM general WHERE officer_level >= 5 AND no != %i AND nation = %i', $generalID, $nationID);
|
||||
foreach($chiefList as $chiefID){
|
||||
$chiefLogger = new ActionLogger($chiefID, $nationID, $year, $month);
|
||||
$chiefLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$chiefLogger->flush();
|
||||
}
|
||||
|
||||
$logger->pushGeneralHistoryLog("<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원");
|
||||
$logger->pushNationalHistoryLog("<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원");
|
||||
$logger->pushGlobalHistoryLog("<Y><b>【원조】</b></><D><b>{$nationName}</b></>에서 <D><b>{$destNationName}</b></>{$josaRo} 물자를 지원합니다");
|
||||
|
||||
$logger->pushGeneralActionLog($broadcastMessage);
|
||||
$logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>{$josaRo} 물자를 지원합니다. <1>$date</>", ActionLogger::PLAIN);
|
||||
|
||||
$destBroadcastMessage = $broadcastMessage = "<D><b>{$nationName}</b></>에서 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 원조했습니다.";
|
||||
$destChiefList = $db->queryFirstColumn('SELECT no FROM general WHERE officer_level >= 5 AND nation = %i', $destNationID);
|
||||
foreach($destChiefList as $destChiefID){
|
||||
$destChiefLogger = new ActionLogger($destChiefID, $nationID, $year, $month);
|
||||
$destChiefLogger->pushGeneralActionLog($destBroadcastMessage, ActionLogger::PLAIN);
|
||||
$destChiefLogger->flush();
|
||||
}
|
||||
|
||||
$josaRoSrc = JosaUtil::pick($nationName, '로');
|
||||
$destNationLogger = new ActionLogger(0, $destChiefID, $year, $month);
|
||||
$destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaRoSrc}부터 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원 받음");
|
||||
|
||||
|
||||
|
||||
$db->update('nation', [
|
||||
'gold'=>$db->sqleval('gold - %i', $goldAmount),
|
||||
'rice'=>$db->sqleval('rice - %i', $riceAmount),
|
||||
'surlimit'=>$db->sqleval('surlimit + %i', $this->getPostReqTurn())
|
||||
], 'nation = %i', $nationID);
|
||||
|
||||
$db->update('nation', [
|
||||
'gold'=>$db->sqleval('gold + %i', $goldAmount),
|
||||
'rice'=>$db->sqleval('rice + %i', $riceAmount),
|
||||
], 'nation = %i', $destNationID);
|
||||
|
||||
$general->addExperience(5);
|
||||
$general->addDedication(5);
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSFiles(): array
|
||||
{
|
||||
return [
|
||||
'js/defaultSelectNationByMap.js'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$currentNationLevel = getNationStaticInfo($this->generalObj->getNationID())['level'];
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
타국에게 원조합니다.<br>
|
||||
작위별로 금액 제한이 있습니다.<br>
|
||||
<?php foreach(\sammo\getNationLevelList() as $level => [$levelText,,]): ?>
|
||||
<?=StringUtil::padStringAlignRight($levelText, 10)?>: <?=number_format($level*GameConst::$coefAidAmount)?><br>
|
||||
<?php endforeach; ?>
|
||||
원조할 국가를 목록에서 선택하세요.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach(getAllNationStaticInfo() as $nation): ?>
|
||||
<option
|
||||
value='<?=$nation['nation']?>'
|
||||
style='color:<?=$nation['color']?>;'
|
||||
>【<?=$nation['name']?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
국고 <select class='formInput amountList' name="amountList[]" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach(Util::range($currentNationLevel+1) as $nationLevel): ?>
|
||||
<option value='<?=$nationLevel*GameConst::$coefAidAmount?>'><?=$nationLevel*GameConst::$coefAidAmount?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
병량 <select class='formInput amountList' name="amountList[]" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach(Util::range($currentNationLevel+1) as $nationLevel): ?>
|
||||
<option value='<?=$nationLevel*GameConst::$coefAidAmount?>'><?=$nationLevel*GameConst::$coefAidAmount?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
@@ -1,196 +1,193 @@
|
||||
<?php
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
MessageTarget,
|
||||
Message,
|
||||
CityConst
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
GetImageURL,
|
||||
getNationStaticInfo
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Event\Action;
|
||||
|
||||
class che_백성동원 extends Command\NationCommand{
|
||||
static protected $actionName = '백성동원';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!key_exists('destCityID', $this->arg)){
|
||||
return false;
|
||||
}
|
||||
if(CityConst::byID($this->arg['destCityID']) === null){
|
||||
return false;
|
||||
}
|
||||
$destCityID = $this->arg['destCityID'];
|
||||
|
||||
$this->arg = [
|
||||
'destCityID'=>$destCityID,
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::AvailableStrategicCommand()
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$this->setDestCity($this->arg['destCityID']);
|
||||
$this->setDestNation($this->destCity['nation']);
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::AllowDiplomacyStatus($this->generalObj->getNationID(), [
|
||||
0, 1
|
||||
], '전쟁중이 아닙니다.'),
|
||||
ConstraintHelper::OccupiedDestCity(),
|
||||
ConstraintHelper::AvailableStrategicCommand()
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn()+1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(전략$postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount*4)*10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
$commandName = $this->getName();
|
||||
$destCityName = CityConst::byID($this->arg['destCityID'])->name;
|
||||
return "【{$destCityName}】에 {$commandName}";
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$year = $this->env['year'];
|
||||
$month = $this->env['month'];
|
||||
|
||||
$destCity = $this->destCity;
|
||||
$destCityID = $destCity['city'];
|
||||
$destCityName = $destCity['name'];
|
||||
|
||||
$nationID = $general->getNationID();
|
||||
$nationName = $this->nation['name'];
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$logger->pushGeneralActionLog("백성동원 발동! <1>$date</>");
|
||||
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <G><b>{$destCityName}</b></>에 <M>백성동원</>을 하였습니다.";
|
||||
|
||||
$targetGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach($targetGeneralList as $targetGeneralID){
|
||||
$targetLogger = new ActionLogger($targetGeneralID, $nationID, $year, $month);
|
||||
$targetLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$targetLogger->flush();
|
||||
}
|
||||
|
||||
$db->update('city', [
|
||||
'def' => $db->sqleval('GREATEST(def_max * 0.8, def)'),
|
||||
'wall' => $db->sqleval('GREATEST(wall_max * 0.8, wall)'),
|
||||
], 'city=%i', $destCityID);
|
||||
|
||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||
|
||||
|
||||
$logger->pushGeneralHistoryLog('<M>백성동원</>을 발동');
|
||||
$logger->pushNationalHistoryLog("<L><b>【전략】</b></><D><b>{$nationName}</b></>{$josaYiNation} <G><b>{$destCityName}</b></>에 <M>백성동원</>을 하였습니다.");
|
||||
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $this->getPostReqTurn()
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSFiles(): array
|
||||
{
|
||||
return [
|
||||
'js/defaultSelectCityByMap.js'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
선택된 도시에 백성을 동원해 성벽을 쌓습니다.<br>
|
||||
아국 도시만 가능합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'>
|
||||
<?=\sammo\optionsForCities()?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
<?php
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
MessageTarget,
|
||||
Message,
|
||||
CityConst
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
GetImageURL,
|
||||
getNationStaticInfo
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Event\Action;
|
||||
|
||||
class che_백성동원 extends Command\NationCommand{
|
||||
static protected $actionName = '백성동원';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!key_exists('destCityID', $this->arg)){
|
||||
return false;
|
||||
}
|
||||
if(CityConst::byID($this->arg['destCityID']) === null){
|
||||
return false;
|
||||
}
|
||||
$destCityID = $this->arg['destCityID'];
|
||||
|
||||
$this->arg = [
|
||||
'destCityID'=>$destCityID,
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::AvailableStrategicCommand()
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$this->setDestCity($this->arg['destCityID']);
|
||||
$this->setDestNation($this->destCity['nation']);
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::OccupiedDestCity(),
|
||||
ConstraintHelper::AvailableStrategicCommand()
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn()+1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(재사용 대기 $postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount*4)*10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
$commandName = $this->getName();
|
||||
$destCityName = CityConst::byID($this->arg['destCityID'])->name;
|
||||
return "【{$destCityName}】에 {$commandName}";
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$year = $this->env['year'];
|
||||
$month = $this->env['month'];
|
||||
|
||||
$destCity = $this->destCity;
|
||||
$destCityID = $destCity['city'];
|
||||
$destCityName = $destCity['name'];
|
||||
|
||||
$nationID = $general->getNationID();
|
||||
$nationName = $this->nation['name'];
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$logger->pushGeneralActionLog("백성동원 발동! <1>$date</>");
|
||||
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <G><b>{$destCityName}</b></>에 <M>백성동원</>을 하였습니다.";
|
||||
|
||||
$targetGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach($targetGeneralList as $targetGeneralID){
|
||||
$targetLogger = new ActionLogger($targetGeneralID, $nationID, $year, $month);
|
||||
$targetLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$targetLogger->flush();
|
||||
}
|
||||
|
||||
$db->update('city', [
|
||||
'def' => $db->sqleval('GREATEST(def_max * 0.8, def)'),
|
||||
'wall' => $db->sqleval('GREATEST(wall_max * 0.8, wall)'),
|
||||
], 'city=%i', $destCityID);
|
||||
|
||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||
|
||||
|
||||
$logger->pushGeneralHistoryLog('<M>백성동원</>을 발동');
|
||||
$logger->pushNationalHistoryLog("<L><b>【전략】</b></><D><b>{$nationName}</b></>{$josaYiNation} <G><b>{$destCityName}</b></>에 <M>백성동원</>을 하였습니다.");
|
||||
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $this->generalObj->onCalcStrategic($this->getName(), 'globalDelay', 9)
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSFiles(): array
|
||||
{
|
||||
return [
|
||||
'js/defaultSelectCityByMap.js'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
선택된 도시에 백성을 동원해 성벽을 쌓습니다.<br>
|
||||
아국 도시만 가능합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'>
|
||||
<?=\sammo\optionsForCities()?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ class che_수몰 extends Command\NationCommand{
|
||||
$reqTurn = $this->getPreReqTurn()+1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(전략$postReqTurn)";
|
||||
return "{$name}/{$reqTurn}턴(재사용 대기 $postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
@@ -179,7 +179,7 @@ class che_수몰 extends Command\NationCommand{
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <G><b>{$destCityName}</b></>에 <M>수몰</>을 발동");
|
||||
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $this->getPostReqTurn()
|
||||
'strategic_cmd_limit' => $this->generalObj->onCalcStrategic($this->getName(), 'globalDelay', 9)
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||
|
||||
@@ -1,243 +1,243 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use\sammo\{
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
KVStorage
|
||||
};
|
||||
|
||||
use function\sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
class che_의병모집 extends Command\NationCommand
|
||||
{
|
||||
static protected $actionName = '의병모집';
|
||||
|
||||
protected function argTest(): bool
|
||||
{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
$this->setCity();
|
||||
$env = $this->env;
|
||||
$relYear = $env['year'] - $env['startyear'];
|
||||
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
ConstraintHelper::NotOpeningPart($relYear),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn() + 1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(전략$postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount * 10) * 10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$env = $this->env;
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$year = $this->env['year'];
|
||||
$month = $this->env['month'];
|
||||
|
||||
$nation = $this->nation;
|
||||
$nationID = $nation['nation'];
|
||||
$nationName = $nation['name'];
|
||||
|
||||
$commandName = $this->getName();
|
||||
$josaUl = JosaUtil::pick($commandName, '을');
|
||||
|
||||
$genCount = $db->queryFirstField('SELECT count(no) FROM general WHERE nation=%i AND npc < 2', $nationID);
|
||||
$npcCount = $db->queryFirstField('SELECT count(no) FROM general WHERE nation=%i AND npc = 3', $nationID);
|
||||
$npcOtherCount = $db->queryFirstField('SELECT count(no) FROM general WHERE nation!=%i AND npc = 3', $nationID);
|
||||
|
||||
|
||||
$genCount = Util::valueFit($genCount, 1);
|
||||
$npcCount = Util::valueFit($npcCount, 1);
|
||||
$npcOtherCountScore = Util::round(sqrt($npcOtherCount + 1)) - 1;
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$logger->pushGeneralActionLog("{$commandName} 발동! <1>$date</>");
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <M>{$commandName}</>{$josaUl} 발동하였습니다.";
|
||||
|
||||
$nationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach ($nationGeneralList as $nationGeneralID) {
|
||||
$nationGeneralLogger = new ActionLogger($nationGeneralID, $nationID, $year, $month);
|
||||
$nationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$nationGeneralLogger->flush();
|
||||
}
|
||||
|
||||
$logger->pushGeneralHistoryLog("<M>{$commandName}</>{$josaUl} 발동");
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <M>{$commandName}</>{$josaUl} 발동");
|
||||
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env'); //TODO: 차라리 env가 이거여야..?
|
||||
|
||||
$avgGenCnt = $db->queryFirstField('SELECT avg(gennum) FROM nation WHERE level > 0');
|
||||
$createGenCnt = 5 + Util::round($avgGenCnt / 10);
|
||||
$createGenIdx = $gameStor->npccount + 1;
|
||||
$lastCreatGenIdx = $createGenIdx + $createGenCnt;
|
||||
|
||||
$pickTypeList = ['무' => 5, '지' => 5];
|
||||
|
||||
$avgGen = $db->queryFirstRow(
|
||||
'SELECT avg(dedication) as ded,avg(experience) as exp,
|
||||
avg(dex1+dex2+dex3+dex4) as dex_t, avg(age) as age, avg(dex5) as dex5
|
||||
from general where nation=%i',
|
||||
$nationID
|
||||
);
|
||||
$dexTotal = $avgGen['dex_t'];
|
||||
|
||||
for (; $createGenIdx <= $lastCreatGenIdx; $createGenIdx++) {
|
||||
$pickType = Util::choiceRandomUsingWeight($pickTypeList);
|
||||
|
||||
$totalStat = GameConst::$defaultStatNPCMax * 2 + 10;
|
||||
$minStat = 10;
|
||||
$mainStat = GameConst::$defaultStatNPCMax - Util::randRangeInt(0, 10);
|
||||
//TODO: defaultStatNPCTotal, defaultStatNPCMin 추가
|
||||
$otherStat = $minStat + Util::randRangeInt(0, 5);
|
||||
$subStat = $totalStat - $mainStat - $otherStat;
|
||||
if ($subStat < $minStat) {
|
||||
$subStat = $otherStat;
|
||||
$otherStat = $minStat;
|
||||
$mainStat = $totalStat - $subStat - $otherStat;
|
||||
if ($mainStat) {
|
||||
throw new \LogicException('기본 스탯 설정값이 잘못되어 있음');
|
||||
}
|
||||
}
|
||||
|
||||
if ($pickType == '무') {
|
||||
$leadership = $subStat;
|
||||
$strength = $mainStat;
|
||||
$intel = $otherStat;
|
||||
$dexVal = Util::choiceRandom([
|
||||
[$dexTotal * 5 / 8, $dexTotal / 8, $dexTotal / 8, $dexTotal / 8],
|
||||
[$dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8, $dexTotal / 8],
|
||||
[$dexTotal / 8, $dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8],
|
||||
]);
|
||||
} else if ($pickType == '지') {
|
||||
$leadership = $subStat;
|
||||
$strength = $otherStat;
|
||||
$intel = $mainStat;
|
||||
$dexVal = [$dexTotal / 8, $dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8];
|
||||
} else {
|
||||
$leadership = $otherStat;
|
||||
$strength = $subStat;
|
||||
$intel = $mainStat;
|
||||
$dexVal = [$dexTotal / 4, $dexTotal / 4, $dexTotal / 4, $dexTotal / 4];
|
||||
}
|
||||
|
||||
$leadership = Util::round($leadership);
|
||||
$strength = Util::round($strength);
|
||||
$intel = Util::round($intel);
|
||||
|
||||
$age = $avgGen['age'];
|
||||
|
||||
$newNPC = new \sammo\Scenario\NPC(
|
||||
Util::randRangeInt(1, 150),
|
||||
"의병장{$createGenIdx}",
|
||||
null,
|
||||
$nationID,
|
||||
$general->getCityID(),
|
||||
$leadership,
|
||||
$strength,
|
||||
$intel,
|
||||
1,
|
||||
$env['year'] - 20,
|
||||
$env['year'] + 6,
|
||||
null,
|
||||
null
|
||||
);
|
||||
$newNPC->killturn = Util::randRangeInt(64, 70);
|
||||
$newNPC->npc = 4;
|
||||
$newNPC->setMoney(1000, 1000);
|
||||
$newNPC->setExpDed($avgGen['exp'], $avgGen['ded']);
|
||||
$newNPC->setDex(
|
||||
$dexVal[0],
|
||||
$dexVal[1],
|
||||
$dexVal[2],
|
||||
$dexVal[3],
|
||||
$avgGen['dex5']
|
||||
);
|
||||
|
||||
$newNPC->build($this->env);
|
||||
}
|
||||
|
||||
$gameStor->npccount = $lastCreatGenIdx;
|
||||
$db->update('nation', [
|
||||
'gennum' => $db->sqleval('gennum + %i', $createGenCnt),
|
||||
'strategic_cmd_limit' => $this->getPostReqTurn()
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use\sammo\{
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
KVStorage
|
||||
};
|
||||
|
||||
use function\sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
class che_의병모집 extends Command\NationCommand
|
||||
{
|
||||
static protected $actionName = '의병모집';
|
||||
|
||||
protected function argTest(): bool
|
||||
{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
$this->setCity();
|
||||
$env = $this->env;
|
||||
$relYear = $env['year'] - $env['startyear'];
|
||||
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
ConstraintHelper::NotOpeningPart($relYear),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn() + 1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(재사용 대기 $postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount * 10) * 10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$env = $this->env;
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$year = $this->env['year'];
|
||||
$month = $this->env['month'];
|
||||
|
||||
$nation = $this->nation;
|
||||
$nationID = $nation['nation'];
|
||||
$nationName = $nation['name'];
|
||||
|
||||
$commandName = $this->getName();
|
||||
$josaUl = JosaUtil::pick($commandName, '을');
|
||||
|
||||
$genCount = $db->queryFirstField('SELECT count(no) FROM general WHERE nation=%i AND npc < 2', $nationID);
|
||||
$npcCount = $db->queryFirstField('SELECT count(no) FROM general WHERE nation=%i AND npc = 3', $nationID);
|
||||
$npcOtherCount = $db->queryFirstField('SELECT count(no) FROM general WHERE nation!=%i AND npc = 3', $nationID);
|
||||
|
||||
|
||||
$genCount = Util::valueFit($genCount, 1);
|
||||
$npcCount = Util::valueFit($npcCount, 1);
|
||||
$npcOtherCountScore = Util::round(sqrt($npcOtherCount + 1)) - 1;
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$logger->pushGeneralActionLog("{$commandName} 발동! <1>$date</>");
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <M>{$commandName}</>{$josaUl} 발동하였습니다.";
|
||||
|
||||
$nationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach ($nationGeneralList as $nationGeneralID) {
|
||||
$nationGeneralLogger = new ActionLogger($nationGeneralID, $nationID, $year, $month);
|
||||
$nationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$nationGeneralLogger->flush();
|
||||
}
|
||||
|
||||
$logger->pushGeneralHistoryLog("<M>{$commandName}</>{$josaUl} 발동");
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <M>{$commandName}</>{$josaUl} 발동");
|
||||
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env'); //TODO: 차라리 env가 이거여야..?
|
||||
|
||||
$avgGenCnt = $db->queryFirstField('SELECT avg(gennum) FROM nation WHERE level > 0');
|
||||
$createGenCnt = 5 + Util::round($avgGenCnt / 10);
|
||||
$createGenIdx = $gameStor->npccount + 1;
|
||||
$lastCreatGenIdx = $createGenIdx + $createGenCnt;
|
||||
|
||||
$pickTypeList = ['무' => 5, '지' => 5];
|
||||
|
||||
$avgGen = $db->queryFirstRow(
|
||||
'SELECT avg(dedication) as ded,avg(experience) as exp,
|
||||
avg(dex1+dex2+dex3+dex4) as dex_t, avg(age) as age, avg(dex5) as dex5
|
||||
from general where nation=%i',
|
||||
$nationID
|
||||
);
|
||||
$dexTotal = $avgGen['dex_t'];
|
||||
|
||||
for (; $createGenIdx <= $lastCreatGenIdx; $createGenIdx++) {
|
||||
$pickType = Util::choiceRandomUsingWeight($pickTypeList);
|
||||
|
||||
$totalStat = GameConst::$defaultStatNPCMax * 2 + 10;
|
||||
$minStat = 10;
|
||||
$mainStat = GameConst::$defaultStatNPCMax - Util::randRangeInt(0, 10);
|
||||
//TODO: defaultStatNPCTotal, defaultStatNPCMin 추가
|
||||
$otherStat = $minStat + Util::randRangeInt(0, 5);
|
||||
$subStat = $totalStat - $mainStat - $otherStat;
|
||||
if ($subStat < $minStat) {
|
||||
$subStat = $otherStat;
|
||||
$otherStat = $minStat;
|
||||
$mainStat = $totalStat - $subStat - $otherStat;
|
||||
if ($mainStat) {
|
||||
throw new \LogicException('기본 스탯 설정값이 잘못되어 있음');
|
||||
}
|
||||
}
|
||||
|
||||
if ($pickType == '무') {
|
||||
$leadership = $subStat;
|
||||
$strength = $mainStat;
|
||||
$intel = $otherStat;
|
||||
$dexVal = Util::choiceRandom([
|
||||
[$dexTotal * 5 / 8, $dexTotal / 8, $dexTotal / 8, $dexTotal / 8],
|
||||
[$dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8, $dexTotal / 8],
|
||||
[$dexTotal / 8, $dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8],
|
||||
]);
|
||||
} else if ($pickType == '지') {
|
||||
$leadership = $subStat;
|
||||
$strength = $otherStat;
|
||||
$intel = $mainStat;
|
||||
$dexVal = [$dexTotal / 8, $dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8];
|
||||
} else {
|
||||
$leadership = $otherStat;
|
||||
$strength = $subStat;
|
||||
$intel = $mainStat;
|
||||
$dexVal = [$dexTotal / 4, $dexTotal / 4, $dexTotal / 4, $dexTotal / 4];
|
||||
}
|
||||
|
||||
$leadership = Util::round($leadership);
|
||||
$strength = Util::round($strength);
|
||||
$intel = Util::round($intel);
|
||||
|
||||
$age = $avgGen['age'];
|
||||
|
||||
$newNPC = new \sammo\Scenario\NPC(
|
||||
Util::randRangeInt(1, 150),
|
||||
"의병장{$createGenIdx}",
|
||||
null,
|
||||
$nationID,
|
||||
$general->getCityID(),
|
||||
$leadership,
|
||||
$strength,
|
||||
$intel,
|
||||
1,
|
||||
$env['year'] - 20,
|
||||
$env['year'] + 6,
|
||||
null,
|
||||
null
|
||||
);
|
||||
$newNPC->killturn = Util::randRangeInt(64, 70);
|
||||
$newNPC->npc = 4;
|
||||
$newNPC->setMoney(1000, 1000);
|
||||
$newNPC->setExpDed($avgGen['exp'], $avgGen['ded']);
|
||||
$newNPC->setDex(
|
||||
$dexVal[0],
|
||||
$dexVal[1],
|
||||
$dexVal[2],
|
||||
$dexVal[3],
|
||||
$avgGen['dex5']
|
||||
);
|
||||
|
||||
$newNPC->build($this->env);
|
||||
}
|
||||
|
||||
$gameStor->npccount = $lastCreatGenIdx;
|
||||
$db->update('nation', [
|
||||
'gennum' => $db->sqleval('gennum + %i', $createGenCnt),
|
||||
'strategic_cmd_limit' => $this->generalObj->onCalcStrategic($this->getName(), 'globalDelay', 9)
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,250 +1,250 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use\sammo\{
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
Message,
|
||||
MessageTarget
|
||||
};
|
||||
|
||||
use function\sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
getAllNationStaticInfo,
|
||||
getNationStaticInfo,
|
||||
GetImageURL
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
class che_이호경식 extends Command\NationCommand
|
||||
{
|
||||
static protected $actionName = '이호경식';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
//NOTE: 멸망 직전에 턴을 넣을 수 있으므로, 존재하지 않는 국가여도 argTest에서 바로 탈락시키지 않음
|
||||
if (!key_exists('destNationID', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
$destNationID = $this->arg['destNationID'];
|
||||
|
||||
if (!is_int($destNationID)) {
|
||||
return false;
|
||||
}
|
||||
if ($destNationID < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->arg = [
|
||||
'destNationID' => $destNationID
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$this->setDestNation($this->arg['destNationID'], null);
|
||||
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::ExistsDestNation(),
|
||||
ConstraintHelper::AllowDiplomacyBetweenStatus(
|
||||
[0, 1],
|
||||
'선포, 전쟁중인 상대국에게만 가능합니다.'
|
||||
),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn() + 1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(전략$postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount * 16) * 10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function getBrief(): string
|
||||
{
|
||||
$commandName = $this->getName();
|
||||
$destNationName = getNationStaticInfo($this->arg['destNationID'])['name'];
|
||||
return "【{$destNationName}】에 {$commandName}";
|
||||
}
|
||||
|
||||
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$env = $this->env;
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$year = $this->env['year'];
|
||||
$month = $this->env['month'];
|
||||
|
||||
$nation = $this->nation;
|
||||
$nationID = $nation['nation'];
|
||||
$nationName = $nation['name'];
|
||||
|
||||
$destNation = $this->destNation;
|
||||
$destNationID = $destNation['nation'];
|
||||
$destNationName = $destNation['name'];
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||
|
||||
$commandName = $this->getName();
|
||||
$josaUl = JosaUtil::pick($commandName, '을');
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$logger->pushGeneralActionLog("{$commandName} 발동! <1>$date</>");
|
||||
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <G><b>{$destNationName}</b></>에 <M>{$commandName}</>{$josaUl} 발동하였습니다.";
|
||||
|
||||
$nationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach ($nationGeneralList as $nationGeneralID) {
|
||||
$nationGeneralLogger = new ActionLogger($nationGeneralID, $nationID, $year, $month);
|
||||
$nationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$nationGeneralLogger->flush();
|
||||
}
|
||||
|
||||
$josaYiCommand = JosaUtil::pick($commandName, '이');
|
||||
|
||||
$broadcastMessage = "아국에 <M>{$commandName}</>{$josaYiCommand} 발동되었습니다.";
|
||||
|
||||
$destNationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach ($destNationGeneralList as $destNationGeneralID) {
|
||||
$destNationGeneralLogger = new ActionLogger($destNationGeneralID, $destNationID, $year, $month);
|
||||
$destNationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$destNationGeneralLogger->flush();
|
||||
}
|
||||
|
||||
$destNationLogger = new ActionLogger(0, $destNationID, $year, $month);
|
||||
$destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} 아국에 <M>{$commandName}</>{$josaUl} 발동");
|
||||
$destNationLogger->flush();
|
||||
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <D><b>{$destNationName}</b></>에 <M>{$commandName}</>{$josaUl} 발동");
|
||||
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $this->getPostReqTurn()
|
||||
], 'nation=%i', $nationID);
|
||||
$db->update('diplomacy', [
|
||||
'term' => $db->sqleval('IF(`state`=0, %i, `term`+ %i)', 3, 3),
|
||||
'state' => 1,
|
||||
], '(me = %i AND you = %i) OR (you = %i AND me = %i)', $nationID, $destNationID, $nationID, $destNationID);
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSFiles(): array
|
||||
{
|
||||
return [
|
||||
'js/defaultSelectNationByMap.js'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationID = $generalObj->getNationID();
|
||||
$nationList = [];
|
||||
$testTurn = new LastTurn($this->getName(), null, $this->getPreReqTurn());
|
||||
foreach (getAllNationStaticInfo() as $destNation) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$testTurn->setArg(['destNationID' => $destNation['nation']]);
|
||||
$testCommand = new static($generalObj, $this->env, $testTurn, ['destNationID' => $destNation['nation']]);
|
||||
if ($testCommand->hasFullConditionMet()) {
|
||||
$destNation['availableCommand'] = true;
|
||||
} else {
|
||||
$destNation['availableCommand'] = false;
|
||||
}
|
||||
|
||||
$nationList[] = $destNation;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 국가에 이호경식을 발동합니다.<br>
|
||||
선포, 전쟁중인 상대국에만 가능합니다.<br>
|
||||
상대 국가를 목록에서 선택하세요.<br>
|
||||
배경색은 현재 이호경식 불가능 국가는 <font color=red>붉은색</font>으로 표시됩니다.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($nationList as $nation) : ?>
|
||||
<option value='<?= $nation['nation'] ?>' style='color:<?= $nation['color'] ?>;<?= $nation['availableCommand'] ? '' : 'background-color:red;' ?>'>【<?= $nation['name'] ?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
<input type=button id="commonSubmit" value="<?= $this->getName() ?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use\sammo\{
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
Message,
|
||||
MessageTarget
|
||||
};
|
||||
|
||||
use function\sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
getAllNationStaticInfo,
|
||||
getNationStaticInfo,
|
||||
GetImageURL
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
class che_이호경식 extends Command\NationCommand
|
||||
{
|
||||
static protected $actionName = '이호경식';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
//NOTE: 멸망 직전에 턴을 넣을 수 있으므로, 존재하지 않는 국가여도 argTest에서 바로 탈락시키지 않음
|
||||
if (!key_exists('destNationID', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
$destNationID = $this->arg['destNationID'];
|
||||
|
||||
if (!is_int($destNationID)) {
|
||||
return false;
|
||||
}
|
||||
if ($destNationID < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->arg = [
|
||||
'destNationID' => $destNationID
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$this->setDestNation($this->arg['destNationID'], null);
|
||||
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::ExistsDestNation(),
|
||||
ConstraintHelper::AllowDiplomacyBetweenStatus(
|
||||
[0, 1],
|
||||
'선포, 전쟁중인 상대국에게만 가능합니다.'
|
||||
),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn() + 1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(재사용 대기 $postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount * 16) * 10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function getBrief(): string
|
||||
{
|
||||
$commandName = $this->getName();
|
||||
$destNationName = getNationStaticInfo($this->arg['destNationID'])['name'];
|
||||
return "【{$destNationName}】에 {$commandName}";
|
||||
}
|
||||
|
||||
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$env = $this->env;
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$year = $this->env['year'];
|
||||
$month = $this->env['month'];
|
||||
|
||||
$nation = $this->nation;
|
||||
$nationID = $nation['nation'];
|
||||
$nationName = $nation['name'];
|
||||
|
||||
$destNation = $this->destNation;
|
||||
$destNationID = $destNation['nation'];
|
||||
$destNationName = $destNation['name'];
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||
|
||||
$commandName = $this->getName();
|
||||
$josaUl = JosaUtil::pick($commandName, '을');
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$logger->pushGeneralActionLog("{$commandName} 발동! <1>$date</>");
|
||||
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <G><b>{$destNationName}</b></>에 <M>{$commandName}</>{$josaUl} 발동하였습니다.";
|
||||
|
||||
$nationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach ($nationGeneralList as $nationGeneralID) {
|
||||
$nationGeneralLogger = new ActionLogger($nationGeneralID, $nationID, $year, $month);
|
||||
$nationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$nationGeneralLogger->flush();
|
||||
}
|
||||
|
||||
$josaYiCommand = JosaUtil::pick($commandName, '이');
|
||||
|
||||
$broadcastMessage = "아국에 <M>{$commandName}</>{$josaYiCommand} 발동되었습니다.";
|
||||
|
||||
$destNationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach ($destNationGeneralList as $destNationGeneralID) {
|
||||
$destNationGeneralLogger = new ActionLogger($destNationGeneralID, $destNationID, $year, $month);
|
||||
$destNationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$destNationGeneralLogger->flush();
|
||||
}
|
||||
|
||||
$destNationLogger = new ActionLogger(0, $destNationID, $year, $month);
|
||||
$destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} 아국에 <M>{$commandName}</>{$josaUl} 발동");
|
||||
$destNationLogger->flush();
|
||||
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <D><b>{$destNationName}</b></>에 <M>{$commandName}</>{$josaUl} 발동");
|
||||
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $this->generalObj->onCalcStrategic($this->getName(), 'globalDelay', 9)
|
||||
], 'nation=%i', $nationID);
|
||||
$db->update('diplomacy', [
|
||||
'term' => $db->sqleval('IF(`state`=0, %i, `term`+ %i)', 3, 3),
|
||||
'state' => 1,
|
||||
], '(me = %i AND you = %i) OR (you = %i AND me = %i)', $nationID, $destNationID, $nationID, $destNationID);
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSFiles(): array
|
||||
{
|
||||
return [
|
||||
'js/defaultSelectNationByMap.js'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationID = $generalObj->getNationID();
|
||||
$nationList = [];
|
||||
$testTurn = new LastTurn($this->getName(), null, $this->getPreReqTurn());
|
||||
foreach (getAllNationStaticInfo() as $destNation) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$testTurn->setArg(['destNationID' => $destNation['nation']]);
|
||||
$testCommand = new static($generalObj, $this->env, $testTurn, ['destNationID' => $destNation['nation']]);
|
||||
if ($testCommand->hasFullConditionMet()) {
|
||||
$destNation['availableCommand'] = true;
|
||||
} else {
|
||||
$destNation['availableCommand'] = false;
|
||||
}
|
||||
|
||||
$nationList[] = $destNation;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 국가에 이호경식을 발동합니다.<br>
|
||||
선포, 전쟁중인 상대국에만 가능합니다.<br>
|
||||
상대 국가를 목록에서 선택하세요.<br>
|
||||
배경색은 현재 이호경식 불가능 국가는 <font color=red>붉은색</font>으로 표시됩니다.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($nationList as $nation) : ?>
|
||||
<option value='<?= $nation['nation'] ?>' style='color:<?= $nation['color'] ?>;<?= $nation['availableCommand'] ? '' : 'background-color:red;' ?>'>【<?= $nation['name'] ?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
<input type=button id="commonSubmit" value="<?= $this->getName() ?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,232 +1,240 @@
|
||||
<?php
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
MessageTarget,
|
||||
Message,
|
||||
CityConst,
|
||||
CityInitialDetail
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
GetImageURL,
|
||||
getNationStaticInfo
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Event\Action;
|
||||
|
||||
class che_초토화 extends Command\NationCommand{
|
||||
static protected $actionName = '초토화';
|
||||
static public $reqArg = true;
|
||||
|
||||
private $cachedDist = null;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!key_exists('destCityID', $this->arg)){
|
||||
return false;
|
||||
}
|
||||
if(CityConst::byID($this->arg['destCityID']) === null){
|
||||
return false;
|
||||
}
|
||||
$destCityID = $this->arg['destCityID'];
|
||||
|
||||
$this->arg = [
|
||||
'destCityID'=>$destCityID,
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['surlimit', 'gold', 'rice', 'capital']);
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqNationValue('surlimit', '제한 턴', '==', 0, '외교제한 턴이 남아있습니다.'),
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$this->setDestCity($this->arg['destCityID']);
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::OccupiedDestCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::SuppliedDestCity(),
|
||||
ConstraintHelper::ReqNationValue('capital', '수도', '!=', $this->destCity['city'], '수도입니다.'),
|
||||
ConstraintHelper::ReqNationValue('surlimit', '제한 턴', '==', 0, '외교제한 턴이 남아있습니다.'),
|
||||
ConstraintHelper::DisallowDiplomacyStatus($this->generalObj->getNationID(), [
|
||||
0 => '평시에만 가능합니다.',
|
||||
1 => '평시에만 가능합니다.'
|
||||
], ),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
return 24;
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
|
||||
$reqTurn = $this->getPreReqTurn()+1;
|
||||
|
||||
return "{$name}/{$reqTurn}턴(공백지화, 금쌀 회수, 수뇌진 명성하락)";
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
$commandName = $this->getName();
|
||||
$destCityName = CityConst::byID($this->arg['destCityID'])->name;
|
||||
$josaUl = JosaUtil::pick($destCityName, '을');
|
||||
return "【{$destCityName}】{$josaUl} {$commandName}";
|
||||
}
|
||||
|
||||
public function calcReturnAmount(array $destCity):int{
|
||||
$amount = $destCity['pop'] / 5;
|
||||
foreach(['agri', 'comm', 'secu'] as $cityRes){
|
||||
$cityResMax = "{$cityRes}_max";
|
||||
$amount *= (($destCity[$cityRes] - $destCity[$cityResMax] * 0.5) / $destCity[$cityResMax]) + 0.8;
|
||||
}
|
||||
return Util::toInt($amount);
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$destCity = $this->destCity;
|
||||
$destCityID = $destCity['city'];
|
||||
$destCityName = $destCity['name'];
|
||||
|
||||
$nationID = $general->getNationID();
|
||||
$nationName = $this->nation['name'];
|
||||
|
||||
$josaUl = JosaUtil::pick($destCityName, '을');
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
|
||||
$general->addExperience(-$general->getVar('experience') * 0.1, false);
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||
|
||||
$amount = $this->calcReturnAmount($destCity);
|
||||
|
||||
$db->update('general', [
|
||||
'experience'=>$db->sqleval('experience * 0.9')
|
||||
], 'nation = %i AND officer_level >= 5 AND no!=%i', $nationID, $generalID);
|
||||
|
||||
$db->update('general', [
|
||||
'betray'=>$db->sqleval('betray + 1')
|
||||
], 'nation = %i AND no!=%i', $nationID, $generalID);
|
||||
$general->increaseVar('betray', 1);
|
||||
|
||||
$db->update('city', [
|
||||
'trust'=>$db->sqleval('greatest(50, trust)'),
|
||||
'pop'=>$db->sqleval('greatest(pop_max*0.1, pop*0.2)'),
|
||||
'agri'=>$db->sqleval('greatest(agri_max*0.1, agri*0.2)'),
|
||||
'comm'=>$db->sqleval('greatest(comm_max*0.1, comm*0.2)'),
|
||||
'nation'=>0,
|
||||
'front'=>0,
|
||||
'conflict'=>'{}'
|
||||
], 'city=%i', $destCityID);
|
||||
|
||||
$db->update('nation', [
|
||||
'gold' => $db->sqleval('gold + %i', $amount),
|
||||
'rice' => $db->sqleval('rice + %i', $amount),
|
||||
'surlimit' => $db->sqleval('surlimit + %i', $this->getPostReqTurn()),
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
\sammo\refreshNationStaticInfo();
|
||||
\sammo\SetNationFront($nationID);
|
||||
|
||||
$logger->pushGeneralActionLog("<G><b>{$destCityName}</b></>{$josaUl} 초토화했습니다. <1>$date</>");
|
||||
$logger->pushGeneralHistoryLog("<G><b>{$destCityName}</b></>{$josaUl} <M>초토화</> 명령");
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <G><b>{$destCityName}</b></>{$josaUl} <M>초토화</> 명령");
|
||||
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <G><b>{$destCityName}</b></>{$josaUl} <M>초토화</>하였습니다.");
|
||||
$logger->pushGlobalHistoryLog("<S><b>【초토화】</b></><D><b>{$nationName}</b></>{$josaYiNation} <G><b>{$destCityName}</b></>{$josaUl} <M>초토화</>하였습니다.");
|
||||
|
||||
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||
$general->applyDB($db);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSFiles(): array
|
||||
{
|
||||
return [
|
||||
'js/defaultSelectCityByMap.js'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
|
||||
$cities = Util::convertArrayToDict(DB::db()->query('SELECT * FROM city WHERE nation =%i', $this->generalObj->getNationID()), 'city');
|
||||
$calc = function(CityInitialDetail $constCity)use($cities){
|
||||
if(!key_exists($constCity->id, $cities)){
|
||||
return null;
|
||||
}
|
||||
$amount = $this->calcReturnAmount($cities[$constCity->id]);
|
||||
$amountText = number_format($amount);
|
||||
return "금쌀 각 {$amountText} 회수";
|
||||
};
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
선택된 도시를 초토화 시킵니다.<br>
|
||||
도시가 공백지가 되며, 도시의 인구, 내정 상태에 따라 상당량의 국고가 확보됩니다.<br>
|
||||
국가의 수뇌들은 명성을 잃고, 모든 장수들은 배신 수치가 1 증가합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'>
|
||||
<?=\sammo\optionsForCities($calc)?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
<?php
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
MessageTarget,
|
||||
Message,
|
||||
CityConst,
|
||||
CityInitialDetail
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
GetImageURL,
|
||||
getNationStaticInfo
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Event\Action;
|
||||
|
||||
class che_초토화 extends Command\NationCommand{
|
||||
static protected $actionName = '초토화';
|
||||
static public $reqArg = true;
|
||||
|
||||
private $cachedDist = null;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!key_exists('destCityID', $this->arg)){
|
||||
return false;
|
||||
}
|
||||
if(CityConst::byID($this->arg['destCityID']) === null){
|
||||
return false;
|
||||
}
|
||||
$destCityID = $this->arg['destCityID'];
|
||||
|
||||
$this->arg = [
|
||||
'destCityID'=>$destCityID,
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['surlimit', 'gold', 'rice', 'capital']);
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqNationValue('surlimit', '제한 턴', '==', 0, '외교제한 턴이 남아있습니다.'),
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$this->setDestCity($this->arg['destCityID']);
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::OccupiedDestCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::SuppliedDestCity(),
|
||||
ConstraintHelper::ReqNationValue('capital', '수도', '!=', $this->destCity['city'], '수도입니다.'),
|
||||
ConstraintHelper::ReqNationValue('surlimit', '제한 턴', '==', 0, '외교제한 턴이 남아있습니다.'),
|
||||
ConstraintHelper::DisallowDiplomacyStatus($this->generalObj->getNationID(), [
|
||||
0 => '평시에만 가능합니다.',
|
||||
], ),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
//NOTE: 자체 postReqTurn 사용
|
||||
return 24;
|
||||
}
|
||||
|
||||
public function getNextAvailableTurn():?int{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setNextAvailable(?int $yearMonth=null){
|
||||
return;
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
|
||||
$reqTurn = $this->getPreReqTurn()+1;
|
||||
|
||||
return "{$name}/{$reqTurn}턴(공백지화, 금쌀 회수, 수뇌진 명성하락)";
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
$commandName = $this->getName();
|
||||
$destCityName = CityConst::byID($this->arg['destCityID'])->name;
|
||||
$josaUl = JosaUtil::pick($destCityName, '을');
|
||||
return "【{$destCityName}】{$josaUl} {$commandName}";
|
||||
}
|
||||
|
||||
public function calcReturnAmount(array $destCity):int{
|
||||
$amount = $destCity['pop'] / 5;
|
||||
foreach(['agri', 'comm', 'secu'] as $cityRes){
|
||||
$cityResMax = "{$cityRes}_max";
|
||||
$amount *= (($destCity[$cityRes] - $destCity[$cityResMax] * 0.5) / $destCity[$cityResMax]) + 0.8;
|
||||
}
|
||||
return Util::toInt($amount);
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$destCity = $this->destCity;
|
||||
$destCityID = $destCity['city'];
|
||||
$destCityName = $destCity['name'];
|
||||
|
||||
$nationID = $general->getNationID();
|
||||
$nationName = $this->nation['name'];
|
||||
|
||||
$josaUl = JosaUtil::pick($destCityName, '을');
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
|
||||
$general->addExperience(-$general->getVar('experience') * 0.1, false);
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||
|
||||
$amount = $this->calcReturnAmount($destCity);
|
||||
|
||||
$db->update('general', [
|
||||
'experience'=>$db->sqleval('experience * 0.9')
|
||||
], 'nation = %i AND officer_level >= 5 AND no!=%i', $nationID, $generalID);
|
||||
|
||||
$db->update('general', [
|
||||
'betray'=>$db->sqleval('betray + 1')
|
||||
], 'nation = %i AND no!=%i', $nationID, $generalID);
|
||||
$general->increaseVar('betray', 1);
|
||||
|
||||
$db->update('city', [
|
||||
'trust'=>$db->sqleval('greatest(50, trust)'),
|
||||
'pop'=>$db->sqleval('greatest(pop_max*0.1, pop*0.2)'),
|
||||
'agri'=>$db->sqleval('greatest(agri_max*0.1, agri*0.2)'),
|
||||
'comm'=>$db->sqleval('greatest(comm_max*0.1, comm*0.2)'),
|
||||
'nation'=>0,
|
||||
'front'=>0,
|
||||
'conflict'=>'{}'
|
||||
], 'city=%i', $destCityID);
|
||||
|
||||
$db->update('nation', [
|
||||
'gold' => $db->sqleval('gold + %i', $amount),
|
||||
'rice' => $db->sqleval('rice + %i', $amount),
|
||||
'surlimit' => $db->sqleval('surlimit + %i', $this->getPostReqTurn()),
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
\sammo\refreshNationStaticInfo();
|
||||
\sammo\SetNationFront($nationID);
|
||||
|
||||
$logger->pushGeneralActionLog("<G><b>{$destCityName}</b></>{$josaUl} 초토화했습니다. <1>$date</>");
|
||||
$logger->pushGeneralHistoryLog("<G><b>{$destCityName}</b></>{$josaUl} <M>초토화</> 명령");
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <G><b>{$destCityName}</b></>{$josaUl} <M>초토화</> 명령");
|
||||
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <G><b>{$destCityName}</b></>{$josaUl} <M>초토화</>하였습니다.");
|
||||
$logger->pushGlobalHistoryLog("<S><b>【초토화】</b></><D><b>{$nationName}</b></>{$josaYiNation} <G><b>{$destCityName}</b></>{$josaUl} <M>초토화</>하였습니다.");
|
||||
|
||||
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||
$general->applyDB($db);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSFiles(): array
|
||||
{
|
||||
return [
|
||||
'js/defaultSelectCityByMap.js'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
|
||||
$cities = Util::convertArrayToDict(DB::db()->query('SELECT * FROM city WHERE nation =%i', $this->generalObj->getNationID()), 'city');
|
||||
$calc = function(CityInitialDetail $constCity)use($cities){
|
||||
if(!key_exists($constCity->id, $cities)){
|
||||
return null;
|
||||
}
|
||||
$amount = $this->calcReturnAmount($cities[$constCity->id]);
|
||||
$amountText = number_format($amount);
|
||||
return "금쌀 각 {$amountText} 회수";
|
||||
};
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
선택된 도시를 초토화 시킵니다.<br>
|
||||
도시가 공백지가 되며, 도시의 인구, 내정 상태에 따라 상당량의 국고가 확보됩니다.<br>
|
||||
국가의 수뇌들은 명성을 잃고, 모든 장수들은 배신 수치가 1 증가합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'>
|
||||
<?=\sammo\optionsForCities($calc)?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
@@ -1,239 +1,302 @@
|
||||
<?php
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
Message, MessageTarget
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
getAllNationStaticInfo,
|
||||
getNationStaticInfo,
|
||||
GetImageURL
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
class che_피장파장 extends Command\NationCommand{
|
||||
static protected $actionName = '피장파장';
|
||||
static public $reqArg = true;
|
||||
static public $delayCnt = 60;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
return false;
|
||||
}
|
||||
//NOTE: 멸망 직전에 턴을 넣을 수 있으므로, 존재하지 않는 국가여도 argTest에서 바로 탈락시키지 않음
|
||||
if(!key_exists('destNationID', $this->arg)){
|
||||
return false;
|
||||
}
|
||||
$destNationID = $this->arg['destNationID'];
|
||||
|
||||
if(!is_int($destNationID)){
|
||||
return false;
|
||||
}
|
||||
if($destNationID < 1){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->arg = [
|
||||
'destNationID'=>$destNationID
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$this->setDestNation($this->arg['destNationID'], null);
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::ExistsDestNation(),
|
||||
ConstraintHelper::AllowDiplomacyBetweenStatus(
|
||||
[0, 1],
|
||||
'선포, 전쟁중인 상대국에게만 가능합니다.'
|
||||
),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn()+1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(전략$postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount*2)*10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
$commandName = $this->getName();
|
||||
$destNationName = getNationStaticInfo($this->arg['destNationID'])['name'];
|
||||
return "【{$destNationName}】에 {$commandName}";
|
||||
}
|
||||
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$env = $this->env;
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$year = $this->env['year'];
|
||||
$month = $this->env['month'];
|
||||
|
||||
$nation = $this->nation;
|
||||
$nationID = $nation['nation'];
|
||||
$nationName = $nation['name'];
|
||||
|
||||
$destNation = $this->destNation;
|
||||
$destNationID = $destNation['nation'];
|
||||
$destNationName = $destNation['name'];
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||
|
||||
$commandName = $this->getName();
|
||||
$josaUl = JosaUtil::pick($commandName, '을');
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$logger->pushGeneralActionLog("{$commandName} 발동! <1>$date</>");
|
||||
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <G><b>{$destNationName}</b></>에 <M>{$commandName}</>{$josaUl} 발동하였습니다.";
|
||||
|
||||
$nationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach($nationGeneralList as $nationGeneralID){
|
||||
$nationGeneralLogger = new ActionLogger($nationGeneralID, $nationID, $year, $month);
|
||||
$nationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$nationGeneralLogger->flush();
|
||||
}
|
||||
|
||||
$josaYiCommand = JosaUtil::pick($commandName, '이');
|
||||
|
||||
$broadcastMessage = "아국에 <M>{$commandName}</>{$josaYiCommand} 발동되었습니다.";
|
||||
|
||||
$destNationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach($destNationGeneralList as $destNationGeneralID){
|
||||
$destNationGeneralLogger = new ActionLogger($destNationGeneralID, $destNationID, $year, $month);
|
||||
$destNationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$destNationGeneralLogger->flush();
|
||||
}
|
||||
|
||||
$destNationLogger = new ActionLogger(0, $destNationID, $year, $month);
|
||||
$destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} 아국에 <M>{$commandName}</>{$josaUl} 발동");
|
||||
$destNationLogger->flush();
|
||||
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <D><b>{$destNationName}</b></>에 <M>{$commandName}</>{$josaUl} 발동");
|
||||
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $this->getPostReqTurn()
|
||||
], 'nation=%i', $nationID);
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $db->sqleval('strategic_cmd_limit + %i', static::$delayCnt)
|
||||
], 'nation = %i', $destNationID);
|
||||
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSFiles(): array
|
||||
{
|
||||
return [
|
||||
'js/defaultSelectNationByMap.js'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationID = $generalObj->getNationID();
|
||||
$nationList = [];
|
||||
$testTurn = new LastTurn($this->getName(), null, $this->getPreReqTurn());
|
||||
foreach(getAllNationStaticInfo() as $destNation){
|
||||
if($destNation['nation'] == $nationID){
|
||||
continue;
|
||||
}
|
||||
|
||||
$testTurn->setArg(['destNationID'=>$destNation['nation']]);
|
||||
$testCommand = new static($generalObj, $this->env, $testTurn, ['destNationID'=>$destNation['nation']]);
|
||||
if($testCommand->hasFullConditionMet()){
|
||||
$destNation['availableCommand'] = true;
|
||||
}
|
||||
else{
|
||||
$destNation['availableCommand'] = false;
|
||||
}
|
||||
|
||||
$nationList[] = $destNation;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
선택된 국가에 피장파장을 발동합니다.<br>
|
||||
선포, 전쟁중인 상대국에만 가능합니다.<br>
|
||||
상대 국가를 목록에서 선택하세요.<br>
|
||||
배경색은 현재 피장파장 불가능 국가는 <font color=red>붉은색</font>으로 표시됩니다.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach($nationList as $nation): ?>
|
||||
<option
|
||||
value='<?=$nation['nation']?>'
|
||||
style='color:<?=$nation['color']?>;<?=$nation['availableCommand']?'':'background-color:red;'?>'
|
||||
>【<?=$nation['name']?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
<input type=button id="commonSubmit" value="<?=$this->getName()?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
<?php
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
KVStorage,
|
||||
Message, MessageTarget
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
buildNationCommandClass,
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
getAllNationStaticInfo,
|
||||
getNationStaticInfo,
|
||||
GetImageURL
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
class che_피장파장 extends Command\NationCommand{
|
||||
static protected $actionName = '피장파장';
|
||||
static public $reqArg = true;
|
||||
static public $delayCnt = 60;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
return false;
|
||||
}
|
||||
//NOTE: 멸망 직전에 턴을 넣을 수 있으므로, 존재하지 않는 국가여도 argTest에서 바로 탈락시키지 않음
|
||||
if(!key_exists('destNationID', $this->arg)){
|
||||
return false;
|
||||
}
|
||||
$destNationID = $this->arg['destNationID'];
|
||||
$commandType = $this->arg['commandType'];
|
||||
|
||||
if(!is_int($destNationID)){
|
||||
return false;
|
||||
}
|
||||
if($destNationID < 1){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!is_string($commandType)){
|
||||
return false;
|
||||
}
|
||||
if(!in_array($commandType, GameConst::$availableChiefCommand['전략'])){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$this->arg = [
|
||||
'destNationID'=>$destNationID,
|
||||
'commandType'=>$commandType
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation();
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$this->setDestNation($this->arg['destNationID'], null);
|
||||
|
||||
if($this->getNationID() == 0){
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity()
|
||||
];
|
||||
return;
|
||||
}
|
||||
|
||||
$cmd = buildNationCommandClass($this->arg['commandType'], $this->generalObj, $this->env, new LastTurn());
|
||||
|
||||
$currYearMonth = Util::joinYearMonth($this->env['year'], $this->env['month']);
|
||||
$nextAvailableTurn = $cmd->getNextAvailableTurn();
|
||||
if($currYearMonth < $nextAvailableTurn){
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::AlwaysFail('해당 전략을 아직 사용할 수 없습니다')
|
||||
];
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::ExistsDestNation(),
|
||||
ConstraintHelper::AllowDiplomacyBetweenStatus(
|
||||
[0, 1],
|
||||
'선포, 전쟁중인 상대국에게만 가능합니다.'
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn()+1;
|
||||
|
||||
return "{$name}/{$reqTurn}턴(대상 재사용 대기 {$this->getTargetPostReqTurn()})";
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getTargetPostReqTurn():int{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount*2)*10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
$commandName = $this->getName();
|
||||
$cmd = buildNationCommandClass($this->arg['commandType'], $this->generalObj, $this->env, new LastTurn());
|
||||
$targetCommandName = $cmd->getName();
|
||||
$destNationName = getNationStaticInfo($this->arg['destNationID'])['name'];
|
||||
return "【{$destNationName}】에 【{$targetCommandName}】 {$commandName}";
|
||||
}
|
||||
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$env = $this->env;
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$year = $this->env['year'];
|
||||
$month = $this->env['month'];
|
||||
|
||||
$nation = $this->nation;
|
||||
$nationID = $nation['nation'];
|
||||
$nationName = $nation['name'];
|
||||
|
||||
$destNation = $this->destNation;
|
||||
$destNationID = $destNation['nation'];
|
||||
$destNationName = $destNation['name'];
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||
|
||||
$commandName = $this->getName();
|
||||
$josaUl = JosaUtil::pick($commandName, '을');
|
||||
|
||||
$cmd = buildNationCommandClass($this->arg['commandType'], $this->generalObj, $this->env, new LastTurn());
|
||||
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$logger->pushGeneralActionLog("<G><b>{$cmd->getName()}</b></> 전략의 {$commandName} 발동! <1>$date</>");
|
||||
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <G><b>{$destNationName}</b></>에 <G><b>{$cmd->getName()}</b></> 전략의 <M>{$commandName}</>{$josaUl} 발동하였습니다.";
|
||||
|
||||
$nationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach($nationGeneralList as $nationGeneralID){
|
||||
$nationGeneralLogger = new ActionLogger($nationGeneralID, $nationID, $year, $month);
|
||||
$nationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$nationGeneralLogger->flush();
|
||||
}
|
||||
|
||||
$josaYiCommand = JosaUtil::pick($commandName, '이');
|
||||
|
||||
$broadcastMessage = "아국에 <G><b>{$cmd->getName()}</b></> 전략의 <M>{$commandName}</>{$josaYiCommand} 발동되었습니다.";
|
||||
|
||||
$destNationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach($destNationGeneralList as $destNationGeneralID){
|
||||
$destNationGeneralLogger = new ActionLogger($destNationGeneralID, $destNationID, $year, $month);
|
||||
$destNationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$destNationGeneralLogger->flush();
|
||||
}
|
||||
|
||||
$destNationLogger = new ActionLogger(0, $destNationID, $year, $month);
|
||||
$destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} 아국에 <G><b>{$cmd->getName()}</b></> <M>{$commandName}</>{$josaUl} 발동");
|
||||
$destNationLogger->flush();
|
||||
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <D><b>{$destNationName}</b></>에 <G><b>{$cmd->getName()}</b></> <M>{$commandName}</>{$josaUl} 발동");
|
||||
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
$destNationStor = KVStorage::getStorage($db, $destNationID, 'nation_env');
|
||||
|
||||
$yearMonth = Util::joinYearMonth($env['year'], $env['month']);
|
||||
$nationStor->setValue($cmd->getNextExecuteKey(), $yearMonth + $this->getTargetPostReqTurn());
|
||||
$destNationStor->setValue($cmd->getNextExecuteKey(), $yearMonth + static::$delayCnt);
|
||||
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSFiles(): array
|
||||
{
|
||||
return [
|
||||
'js/defaultSelectNationByMap.js'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationID = $generalObj->getNationID();
|
||||
$nationList = [];
|
||||
$testTurn = new LastTurn($this->getName(), null, $this->getPreReqTurn());
|
||||
foreach(getAllNationStaticInfo() as $destNation){
|
||||
if($destNation['nation'] == $nationID){
|
||||
continue;
|
||||
}
|
||||
|
||||
$testTurn->setArg(['destNationID'=>$destNation['nation']]);
|
||||
$testCommand = new static($generalObj, $this->env, $testTurn, ['destNationID'=>$destNation['nation']]);
|
||||
if($testCommand->hasFullConditionMet()){
|
||||
$destNation['availableCommand'] = true;
|
||||
}
|
||||
else{
|
||||
$destNation['availableCommand'] = false;
|
||||
}
|
||||
|
||||
$nationList[] = $destNation;
|
||||
}
|
||||
|
||||
$availableCommandTypeList = [];
|
||||
$currYearMonth = Util::joinYearMonth($this->env['year'], $this->env['month']);
|
||||
foreach(GameConst::$availableChiefCommand['전략'] as $commandType){
|
||||
$cmd = buildNationCommandClass($commandType, $generalObj, $this->env, new LastTurn());
|
||||
$cmdName = $cmd->getName();
|
||||
$remainTurn = 0;
|
||||
$nextAvailableTurn = $cmd->getNextAvailableTurn();
|
||||
|
||||
if($nextAvailableTurn !== null && $currYearMonth < $nextAvailableTurn){
|
||||
$remainTurn = $nextAvailableTurn - $currYearMonth;
|
||||
}
|
||||
$availableCommandTypeList[$commandType] = [$cmdName, $remainTurn];
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
선택된 국가에 피장파장을 발동합니다.<br>
|
||||
지정한 전략을 상대국이 <?=static::$delayCnt?>턴 동안 사용할 수 없게됩니다.<br>
|
||||
대신 아국은 지정한 전략을<?=$this->getTargetPostReqTurn()?>턴 동안 사용할 수 없습니다.<br>
|
||||
선포, 전쟁중인 상대국에만 가능합니다.<br>
|
||||
상대 국가를 목록에서 선택하세요.<br>
|
||||
배경색은 현재 피장파장 불가능 국가는 <font color=red>붉은색</font>으로 표시됩니다.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach($nationList as $nation): ?>
|
||||
<option
|
||||
value='<?=$nation['nation']?>'
|
||||
style='color:<?=$nation['color']?>;<?=$nation['availableCommand']?'':'background-color:red;'?>'
|
||||
>【<?=$nation['name']?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
</select>에
|
||||
<select class='formInput' name="commandType" id="commandType" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach($availableCommandTypeList as $commandType=>[$cmdName, $cmdRemainTurn]):
|
||||
/** @var \sammo\Command\NationCommand $cmdObj */
|
||||
?>
|
||||
<option
|
||||
value='<?=$commandType?>'
|
||||
style='color:white;<?=$cmdRemainTurn?'background-color:red;':''?>'
|
||||
><?=$cmdName?><?=$cmdRemainTurn?"({$cmdRemainTurn}턴 뒤)":''?></option>
|
||||
<?php endforeach; ?>
|
||||
</select> 전략을
|
||||
<input type=button id="commonSubmit" value="<?=$this->getName()?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
@@ -1,134 +1,134 @@
|
||||
<?php
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
MessageTarget,
|
||||
Message
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
GetImageURL
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Event\Action;
|
||||
|
||||
class che_필사즉생 extends Command\NationCommand{
|
||||
static protected $actionName = '필사즉생';
|
||||
|
||||
protected function argTest():bool{
|
||||
$this->arg = [];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::AllowDiplomacyStatus($this->generalObj->getNationID(), [
|
||||
0
|
||||
], '전쟁중이 아닙니다.'),
|
||||
ConstraintHelper::AvailableStrategicCommand()
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn()+1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(전략$postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount*8)*10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$nationID = $general->getNationID();
|
||||
$nationName = $this->nation['name'];
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$logger->pushGeneralActionLog("필사즉생 발동! <1>$date</>");
|
||||
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <M>필사즉생</>을 발동하였습니다.";
|
||||
|
||||
$targetGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach(General::createGeneralObjListFromDB($targetGeneralList, ['train', 'atmos'], 1) as $targetGeneral){
|
||||
$targetGeneral->getLogger()->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
if($targetGeneral->getVar('train') < 100){
|
||||
$targetGeneral->setVar('train', 100);
|
||||
}
|
||||
if($targetGeneral->getVar('atmos') < 100){
|
||||
$targetGeneral->setVar('atmos', 100);
|
||||
}
|
||||
|
||||
$targetGeneral->applyDB($db);
|
||||
}
|
||||
|
||||
if($general->getVar('train') < 100){
|
||||
$general->setVar('train', 100);
|
||||
}
|
||||
if($general->getVar('atmos') < 100){
|
||||
$general->setVar('atmos', 100);
|
||||
}
|
||||
$logger->pushGeneralHistoryLog('<M>필사즉생</>을 발동');
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <M>필사즉생</>을 발동");
|
||||
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $this->getPostReqTurn()
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
<?php
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
MessageTarget,
|
||||
Message
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
GetImageURL
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Event\Action;
|
||||
|
||||
class che_필사즉생 extends Command\NationCommand{
|
||||
static protected $actionName = '필사즉생';
|
||||
|
||||
protected function argTest():bool{
|
||||
$this->arg = [];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::AllowDiplomacyStatus($this->generalObj->getNationID(), [
|
||||
0
|
||||
], '전쟁중이 아닙니다.'),
|
||||
ConstraintHelper::AvailableStrategicCommand()
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn()+1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(재사용 대기 $postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount*8)*10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$nationID = $general->getNationID();
|
||||
$nationName = $this->nation['name'];
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$logger->pushGeneralActionLog("필사즉생 발동! <1>$date</>");
|
||||
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <M>필사즉생</>을 발동하였습니다.";
|
||||
|
||||
$targetGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach(General::createGeneralObjListFromDB($targetGeneralList, ['train', 'atmos'], 1) as $targetGeneral){
|
||||
$targetGeneral->getLogger()->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
if($targetGeneral->getVar('train') < 100){
|
||||
$targetGeneral->setVar('train', 100);
|
||||
}
|
||||
if($targetGeneral->getVar('atmos') < 100){
|
||||
$targetGeneral->setVar('atmos', 100);
|
||||
}
|
||||
|
||||
$targetGeneral->applyDB($db);
|
||||
}
|
||||
|
||||
if($general->getVar('train') < 100){
|
||||
$general->setVar('train', 100);
|
||||
}
|
||||
if($general->getVar('atmos') < 100){
|
||||
$general->setVar('atmos', 100);
|
||||
}
|
||||
$logger->pushGeneralHistoryLog('<M>필사즉생</>을 발동');
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <M>필사즉생</>을 발동");
|
||||
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $this->generalObj->onCalcStrategic($this->getName(), 'globalDelay', 9)
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+239
-239
@@ -1,239 +1,239 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use\sammo\{
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
MessageTarget,
|
||||
Message,
|
||||
CityConst
|
||||
};
|
||||
|
||||
use function\sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
GetImageURL,
|
||||
getNationStaticInfo
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Event\Action;
|
||||
|
||||
class che_허보 extends Command\NationCommand
|
||||
{
|
||||
static protected $actionName = '허보';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
if (!key_exists('destCityID', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
if (CityConst::byID($this->arg['destCityID']) === null) {
|
||||
return false;
|
||||
}
|
||||
$destCityID = $this->arg['destCityID'];
|
||||
|
||||
$this->arg = [
|
||||
'destCityID' => $destCityID,
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$this->setDestCity($this->arg['destCityID']);
|
||||
$this->setDestNation($this->destCity['nation']);
|
||||
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::NotNeutralDestCity(),
|
||||
ConstraintHelper::NotOccupiedDestCity(),
|
||||
ConstraintHelper::AllowDiplomacyBetweenStatus(
|
||||
[0, 1],
|
||||
'선포, 전쟁중인 상대국에게만 가능합니다.'
|
||||
),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn() + 1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(전략$postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount * 4) * 10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function getBrief(): string
|
||||
{
|
||||
$commandName = $this->getName();
|
||||
$destCityName = CityConst::byID($this->arg['destCityID'])->name;
|
||||
return "【{$destCityName}】에 {$commandName}";
|
||||
}
|
||||
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$year = $this->env['year'];
|
||||
$month = $this->env['month'];
|
||||
|
||||
$destCity = $this->destCity;
|
||||
$destCityID = $destCity['city'];
|
||||
$destCityName = $destCity['name'];
|
||||
|
||||
$destNationID = $destCity['nation'];
|
||||
$destNationName = getNationStaticInfo($destNationID)['name'];
|
||||
|
||||
$nationID = $general->getNationID();
|
||||
$nationName = $this->nation['name'];
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$logger->pushGeneralActionLog("허보 발동! <1>$date</>");
|
||||
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <G><b>{$destCityName}</b></>에 <M>허보</>를 발동하였습니다.";
|
||||
|
||||
$targetGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach ($targetGeneralList as $targetGeneralID) {
|
||||
$targetLogger = new ActionLogger($targetGeneralID, $nationID, $year, $month);
|
||||
$targetLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$targetLogger->flush();
|
||||
}
|
||||
|
||||
$destBroadcastMessage = "상대의 <M>허보</>에 당했다! <1>$date</>";
|
||||
$destNationCityList = $db->queryFirstColumn('SELECT city FROM city WHERE nation = %i AND supply = 1', $destNationID);
|
||||
|
||||
$targetGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND city=%i', $destNationID, $destCityID);
|
||||
foreach (General::createGeneralObjListFromDB($targetGeneralList) as $targetGeneralID => $targetGeneral) {
|
||||
$targetLogger = $targetGeneral->getLogger();
|
||||
$targetLogger->pushGeneralActionLog($destBroadcastMessage, ActionLogger::PLAIN);
|
||||
|
||||
$moveCityID = Util::choiceRandom($destNationCityList);
|
||||
if ($moveCityID == $destCityID) {
|
||||
//현재도시면 다시 랜덤 추첨
|
||||
$moveCityID = Util::choiceRandom($destNationCityList);
|
||||
}
|
||||
|
||||
$targetGeneral->setVar('city', $moveCityID);
|
||||
$targetGeneral->applyDB($db);
|
||||
}
|
||||
|
||||
$destNationLogger = new ActionLogger(0, $destNationID, $year, $month);
|
||||
$destNationLogger->pushNationalHistoryLog(
|
||||
"<D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} 아국의 <G><b>{$destCityName}</b></>에 <M>허보</>를 발동",
|
||||
ActionLogger::PLAIN
|
||||
);
|
||||
$destNationLogger->flush();
|
||||
|
||||
|
||||
$db->update('city', [
|
||||
'def' => $db->sqleval('def * 0.2'),
|
||||
'wall' => $db->sqleval('wall * 0.2'),
|
||||
], 'city=%i', $destCityID);
|
||||
|
||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||
|
||||
$logger->pushGeneralHistoryLog("<G><b>{$destCityName}</b></>에 <M>허보</>를 발동");
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <G><b>{$destCityName}</b></>에 <M>허보</>를 발동");
|
||||
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $this->getPostReqTurn()
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSFiles(): array
|
||||
{
|
||||
return [
|
||||
'js/defaultSelectCityByMap.js'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 도시에 허보를 발동합니다.<br>
|
||||
전쟁중인 상대국 도시만 가능합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'>
|
||||
<?= \sammo\optionsForCities() ?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use\sammo\{
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
MessageTarget,
|
||||
Message,
|
||||
CityConst
|
||||
};
|
||||
|
||||
use function\sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
GetImageURL,
|
||||
getNationStaticInfo
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Event\Action;
|
||||
|
||||
class che_허보 extends Command\NationCommand
|
||||
{
|
||||
static protected $actionName = '허보';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
if (!key_exists('destCityID', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
if (CityConst::byID($this->arg['destCityID']) === null) {
|
||||
return false;
|
||||
}
|
||||
$destCityID = $this->arg['destCityID'];
|
||||
|
||||
$this->arg = [
|
||||
'destCityID' => $destCityID,
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function initWithArg()
|
||||
{
|
||||
$this->setDestCity($this->arg['destCityID']);
|
||||
$this->setDestNation($this->destCity['nation']);
|
||||
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::NotNeutralDestCity(),
|
||||
ConstraintHelper::NotOccupiedDestCity(),
|
||||
ConstraintHelper::AllowDiplomacyBetweenStatus(
|
||||
[0, 1],
|
||||
'선포, 전쟁중인 상대국에게만 가능합니다.'
|
||||
),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn() + 1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(재사용 대기 $postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount * 4) * 10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function getBrief(): string
|
||||
{
|
||||
$commandName = $this->getName();
|
||||
$destCityName = CityConst::byID($this->arg['destCityID'])->name;
|
||||
return "【{$destCityName}】에 {$commandName}";
|
||||
}
|
||||
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$generalID = $general->getID();
|
||||
$generalName = $general->getName();
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
$year = $this->env['year'];
|
||||
$month = $this->env['month'];
|
||||
|
||||
$destCity = $this->destCity;
|
||||
$destCityID = $destCity['city'];
|
||||
$destCityName = $destCity['name'];
|
||||
|
||||
$destNationID = $destCity['nation'];
|
||||
$destNationName = getNationStaticInfo($destNationID)['name'];
|
||||
|
||||
$nationID = $general->getNationID();
|
||||
$nationName = $this->nation['name'];
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$logger->pushGeneralActionLog("허보 발동! <1>$date</>");
|
||||
|
||||
$general->addExperience(5 * ($this->getPreReqTurn() + 1));
|
||||
$general->addDedication(5 * ($this->getPreReqTurn() + 1));
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <G><b>{$destCityName}</b></>에 <M>허보</>를 발동하였습니다.";
|
||||
|
||||
$targetGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach ($targetGeneralList as $targetGeneralID) {
|
||||
$targetLogger = new ActionLogger($targetGeneralID, $nationID, $year, $month);
|
||||
$targetLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$targetLogger->flush();
|
||||
}
|
||||
|
||||
$destBroadcastMessage = "상대의 <M>허보</>에 당했다! <1>$date</>";
|
||||
$destNationCityList = $db->queryFirstColumn('SELECT city FROM city WHERE nation = %i AND supply = 1', $destNationID);
|
||||
|
||||
$targetGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND city=%i', $destNationID, $destCityID);
|
||||
foreach (General::createGeneralObjListFromDB($targetGeneralList) as $targetGeneralID => $targetGeneral) {
|
||||
$targetLogger = $targetGeneral->getLogger();
|
||||
$targetLogger->pushGeneralActionLog($destBroadcastMessage, ActionLogger::PLAIN);
|
||||
|
||||
$moveCityID = Util::choiceRandom($destNationCityList);
|
||||
if ($moveCityID == $destCityID) {
|
||||
//현재도시면 다시 랜덤 추첨
|
||||
$moveCityID = Util::choiceRandom($destNationCityList);
|
||||
}
|
||||
|
||||
$targetGeneral->setVar('city', $moveCityID);
|
||||
$targetGeneral->applyDB($db);
|
||||
}
|
||||
|
||||
$destNationLogger = new ActionLogger(0, $destNationID, $year, $month);
|
||||
$destNationLogger->pushNationalHistoryLog(
|
||||
"<D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} 아국의 <G><b>{$destCityName}</b></>에 <M>허보</>를 발동",
|
||||
ActionLogger::PLAIN
|
||||
);
|
||||
$destNationLogger->flush();
|
||||
|
||||
|
||||
$db->update('city', [
|
||||
'def' => $db->sqleval('def * 0.2'),
|
||||
'wall' => $db->sqleval('wall * 0.2'),
|
||||
], 'city=%i', $destCityID);
|
||||
|
||||
$josaYiNation = JosaUtil::pick($nationName, '이');
|
||||
|
||||
$logger->pushGeneralHistoryLog("<G><b>{$destCityName}</b></>에 <M>허보</>를 발동");
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <G><b>{$destCityName}</b></>에 <M>허보</>를 발동");
|
||||
|
||||
$db->update('nation', [
|
||||
'strategic_cmd_limit' => $this->generalObj->onCalcStrategic($this->getName(), 'globalDelay', 9)
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
$this->setResultTurn(new LastTurn($this->getName(), $this->arg, 0));
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSFiles(): array
|
||||
{
|
||||
return [
|
||||
'js/defaultSelectCityByMap.js'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 도시에 허보를 발동합니다.<br>
|
||||
전쟁중인 상대국 도시만 가능합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'>
|
||||
<?= \sammo\optionsForCities() ?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,59 @@
|
||||
<?php
|
||||
namespace sammo\Command;
|
||||
use \sammo\General;
|
||||
use \sammo\LastTurn;
|
||||
|
||||
abstract class NationCommand extends BaseCommand{
|
||||
protected $lastTurn;
|
||||
protected $resultTurn;
|
||||
|
||||
public function __construct(General $generalObj, array $env, LastTurn $lastTurn, $arg = null){
|
||||
$this->lastTurn = $lastTurn;
|
||||
$this->resultTurn = $lastTurn->duplicate();
|
||||
parent::__construct($generalObj, $env, $arg);
|
||||
}
|
||||
|
||||
public function getLastTurn():LastTurn{
|
||||
return $this->lastTurn;
|
||||
}
|
||||
|
||||
public function setResultTurn(LastTurn $lastTurn){
|
||||
$this->resultTurn = $lastTurn;
|
||||
}
|
||||
|
||||
public function getResultTurn():LastTurn{
|
||||
return $this->resultTurn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
<?php
|
||||
namespace sammo\Command;
|
||||
use \sammo\General;
|
||||
use sammo\KVStorage;
|
||||
use \sammo\LastTurn;
|
||||
use \sammo\Util;
|
||||
|
||||
abstract class NationCommand extends BaseCommand{
|
||||
protected $lastTurn;
|
||||
protected $resultTurn;
|
||||
|
||||
public function __construct(General $generalObj, array $env, LastTurn $lastTurn, $arg = null){
|
||||
$this->lastTurn = $lastTurn;
|
||||
$this->resultTurn = $lastTurn->duplicate();
|
||||
parent::__construct($generalObj, $env, $arg);
|
||||
}
|
||||
|
||||
public function getLastTurn():LastTurn{
|
||||
return $this->lastTurn;
|
||||
}
|
||||
|
||||
public function setResultTurn(LastTurn $lastTurn){
|
||||
$this->resultTurn = $lastTurn;
|
||||
}
|
||||
|
||||
public function getResultTurn():LastTurn{
|
||||
return $this->resultTurn;
|
||||
}
|
||||
|
||||
public function getNextExecuteKey():string{
|
||||
$turnKey = static::$actionName;
|
||||
$executeKey = "next_execute_{$turnKey}";
|
||||
return $executeKey;
|
||||
}
|
||||
|
||||
public function getNextAvailableTurn():?int{
|
||||
if($this->isArgValid && !$this->getPostReqTurn()){
|
||||
return null;
|
||||
}
|
||||
$db = \sammo\DB::db();
|
||||
$nationStor = \sammo\KVStorage::getStorage($db, $this->getNationID(), 'nation_env');
|
||||
return $nationStor->getValue($this->getNextExecuteKey());
|
||||
}
|
||||
|
||||
public function setNextAvailable(?int $yearMonth=null){
|
||||
if(!$this->getPostReqTurn()){
|
||||
return;
|
||||
}
|
||||
if($yearMonth === null){
|
||||
$yearMonth = Util::joinYearMonth($this->env['year'], $this->env['month'])
|
||||
+ $this->getPostReqTurn() - $this->getPreReqTurn();
|
||||
}
|
||||
|
||||
$db = \sammo\DB::db();
|
||||
$nationStor = \sammo\KVStorage::getStorage($db, $this->getNationID(), 'nation_env');
|
||||
$nationStor->setValue($this->getNextExecuteKey(), $yearMonth);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,32 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Constraint;
|
||||
|
||||
class AvailableStrategicCommand extends Constraint{
|
||||
const REQ_VALUES = Constraint::REQ_NATION;
|
||||
|
||||
public function checkInputValues(bool $throwExeception=true):bool{
|
||||
if(!parent::checkInputValues($throwExeception) && !$throwExeception){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!key_exists('strategic_cmd_limit', $this->nation)){
|
||||
if(!$throwExeception){return false; }
|
||||
throw new \InvalidArgumentException("require strategic_cmd_limit in nation");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function test():bool{
|
||||
$this->checkInputValues();
|
||||
$this->tested = true;
|
||||
|
||||
if($this->nation['strategic_cmd_limit'] == 0){
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->reason = "전략기한이 남았습니다.";
|
||||
return false;
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace sammo\Constraint;
|
||||
|
||||
class AvailableStrategicCommand extends Constraint{
|
||||
const REQ_VALUES = Constraint::REQ_NATION | Constraint::REQ_INT_ARG;
|
||||
|
||||
public function checkInputValues(bool $throwExeception=true):bool{
|
||||
if(!parent::checkInputValues($throwExeception) && !$throwExeception){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!key_exists('strategic_cmd_limit', $this->nation)){
|
||||
if(!$throwExeception){return false; }
|
||||
throw new \InvalidArgumentException("require strategic_cmd_limit in nation");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function test():bool{
|
||||
$this->checkInputValues();
|
||||
$this->tested = true;
|
||||
|
||||
if($this->nation['strategic_cmd_limit'] <= $this->arg){
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->reason = "전략기한이 남았습니다.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,274 +1,274 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Constraint;
|
||||
|
||||
class ConstraintHelper{
|
||||
|
||||
static function AdhocCallback(callable $callback):array{
|
||||
return [__FUNCTION__, $callback];
|
||||
}
|
||||
|
||||
static function AllowDiplomacyStatus(int $nationID, array $allowList, string $errMsg):array{
|
||||
return [__FUNCTION__, [$nationID, $allowList, $errMsg]];
|
||||
}
|
||||
|
||||
static function AllowDiplomacyBetweenStatus(array $allowDipCodeList, string $errMsg):array{
|
||||
return [__FUNCTION__, [$allowDipCodeList, $errMsg]];
|
||||
}
|
||||
|
||||
static function AllowDiplomacyWithTerm(int $allowDipCode, int $allowMinTerm, string $errMsg):array{
|
||||
return [__FUNCTION__, [$allowDipCode, $allowMinTerm, $errMsg]];
|
||||
}
|
||||
|
||||
static function AllowJoinAction():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function AllowJoinDestNation(int $relYear):array{
|
||||
return [__FUNCTION__, $relYear];
|
||||
}
|
||||
|
||||
static function AllowRebellion():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function AllowWar():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function AlwaysFail(string $failMessage):array{
|
||||
return [__FUNCTION__, $failMessage];
|
||||
}
|
||||
|
||||
static function AvailableRecruitCrewType(int $crewTypeID):array{
|
||||
return [__FUNCTION__, $crewTypeID];
|
||||
}
|
||||
|
||||
static function AvailableStrategicCommand():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function BattleGroundCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function BeChief():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function BeLord():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function BeNeutral():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function BeOpeningPart(int $relYear):array{
|
||||
return [__FUNCTION__, $relYear];
|
||||
}
|
||||
|
||||
static function CheckNationNameDuplicate(string $nationName):array{
|
||||
return [__FUNCTION__, $nationName];
|
||||
}
|
||||
|
||||
static function ConstructableCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function DifferentNationDestGeneral():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function DifferentDestNation():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function DisallowDiplomacyBetweenStatus(array $disallowList):array{
|
||||
return [__FUNCTION__, $disallowList];
|
||||
}
|
||||
|
||||
static function DisallowDiplomacyStatus(int $nationID, array $disallowList):array{
|
||||
return [__FUNCTION__, [$nationID, $disallowList]];
|
||||
}
|
||||
|
||||
static function ExistsAllowJoinNation(int $relYear, array $excludeNationList):array{
|
||||
return [__FUNCTION__, [$relYear, $excludeNationList]];
|
||||
}
|
||||
|
||||
static function ExistsDestGeneral():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function ExistsDestNation():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function FriendlyDestGeneral():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function HasRoute():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function HasRouteWithEnemy():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function MustBeNPC():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function MustBeTroopLeader():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NearCity(int $distance):array{
|
||||
return [__FUNCTION__, $distance];
|
||||
}
|
||||
|
||||
static function NearNation():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NotBeNeutral():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NotCapital(bool $ignoreOfficer=false):array{
|
||||
return [__FUNCTION__, $ignoreOfficer];
|
||||
}
|
||||
|
||||
static function NotChief():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NotLord():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NotNeutralDestCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NotOccupiedDestCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NotOpeningPart(int $relYear):array{
|
||||
return [__FUNCTION__, $relYear];
|
||||
}
|
||||
|
||||
static function NotSameDestCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NotWanderingNation():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function OccupiedCity(bool $allowNeutral=false):array{
|
||||
return [__FUNCTION__, $allowNeutral];
|
||||
}
|
||||
|
||||
static function OccupiedDestCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function RemainCityCapacity($key, string $actionName):array{
|
||||
return [__FUNCTION__, [$key, $actionName]];
|
||||
}
|
||||
|
||||
static function RemainCityTrust(string $actionName):array{
|
||||
return [__FUNCTION__, $actionName];
|
||||
}
|
||||
|
||||
static function ReqCityCapacity($key, string $keyNick, $reqVal):array{
|
||||
return [__FUNCTION__, [$key, $keyNick, $reqVal]];
|
||||
}
|
||||
|
||||
static function ReqCityTrust(float $minTrust):array{
|
||||
return [__FUNCTION__, $minTrust];
|
||||
}
|
||||
|
||||
static function ReqCityValue($key, string $keyNick, string $comp, $reqVal, ?string $errMsg=null):array{
|
||||
return [__FUNCTION__, [$key, $keyNick, $comp, $reqVal, $errMsg]];
|
||||
}
|
||||
|
||||
static function ReqDestCityValue($key, string $keyNick, string $comp, $reqVal, ?string $errMsg=null):array{
|
||||
return [__FUNCTION__, [$key, $keyNick, $comp, $reqVal, $errMsg]];
|
||||
}
|
||||
|
||||
static function ReqCityTrader(int $npcType):array{
|
||||
return [__FUNCTION__, $npcType];
|
||||
}
|
||||
|
||||
static function ReqDestNationValue($key, string $keyNick, string $comp, $reqVal, ?string $errMsg=null):array{
|
||||
return [__FUNCTION__, [$key, $keyNick, $comp, $reqVal, $errMsg]];
|
||||
}
|
||||
|
||||
static function ReqEnvValue($key, string $comp, $reqVal, string $failMessage):array{
|
||||
return [__FUNCTION__, [$key, $comp, $reqVal, $failMessage]];
|
||||
}
|
||||
|
||||
static function ReqGeneralAtmosMargin(int $maxAtmos):array{
|
||||
return [__FUNCTION__, $maxAtmos];
|
||||
}
|
||||
|
||||
static function ReqGeneralCrew():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function ReqGeneralCrewMargin(int $crewTypeID):array{
|
||||
return [__FUNCTION__, $crewTypeID];
|
||||
}
|
||||
|
||||
static function ReqGeneralGold(int $reqGold):array{
|
||||
return [__FUNCTION__, $reqGold];
|
||||
}
|
||||
|
||||
static function ReqGeneralRice(int $reqRice):array{
|
||||
return [__FUNCTION__, $reqRice];
|
||||
}
|
||||
|
||||
static function ReqGeneralTrainMargin(int $maxTrain):array{
|
||||
return [__FUNCTION__, $maxTrain];
|
||||
}
|
||||
|
||||
static function ReqGeneralValue($key, string $keyNick, string $comp, $reqVal, ?string $errMsg=null):array{
|
||||
return [__FUNCTION__, [$key, $keyNick, $comp, $reqVal, $errMsg]];
|
||||
}
|
||||
|
||||
static function ReqNationGold(int $reqGold):array{
|
||||
return [__FUNCTION__, $reqGold];
|
||||
}
|
||||
|
||||
static function ReqNationRice(int $reqRice):array{
|
||||
return [__FUNCTION__, $reqRice];
|
||||
}
|
||||
|
||||
static function ReqNationValue($key, string $keyNick, string $comp, $reqVal, ?string $errMsg=null):array{
|
||||
return [__FUNCTION__, [$key, $keyNick, $comp, $reqVal, $errMsg]];
|
||||
}
|
||||
|
||||
static function ReqNationAuxValue($key, $defaultValue, string $comp, $reqVal, string $errMsg):array{
|
||||
return [__FUNCTION__, [$key, $defaultValue, $comp, $reqVal, $errMsg]];
|
||||
}
|
||||
|
||||
static function ReqTroopMembers():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function SuppliedCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function SuppliedDestCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function WanderingNation():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace sammo\Constraint;
|
||||
|
||||
class ConstraintHelper{
|
||||
|
||||
static function AdhocCallback(callable $callback):array{
|
||||
return [__FUNCTION__, $callback];
|
||||
}
|
||||
|
||||
static function AllowDiplomacyStatus(int $nationID, array $allowList, string $errMsg):array{
|
||||
return [__FUNCTION__, [$nationID, $allowList, $errMsg]];
|
||||
}
|
||||
|
||||
static function AllowDiplomacyBetweenStatus(array $allowDipCodeList, string $errMsg):array{
|
||||
return [__FUNCTION__, [$allowDipCodeList, $errMsg]];
|
||||
}
|
||||
|
||||
static function AllowDiplomacyWithTerm(int $allowDipCode, int $allowMinTerm, string $errMsg):array{
|
||||
return [__FUNCTION__, [$allowDipCode, $allowMinTerm, $errMsg]];
|
||||
}
|
||||
|
||||
static function AllowJoinAction():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function AllowJoinDestNation(int $relYear):array{
|
||||
return [__FUNCTION__, $relYear];
|
||||
}
|
||||
|
||||
static function AllowRebellion():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function AllowWar():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function AlwaysFail(string $failMessage):array{
|
||||
return [__FUNCTION__, $failMessage];
|
||||
}
|
||||
|
||||
static function AvailableRecruitCrewType(int $crewTypeID):array{
|
||||
return [__FUNCTION__, $crewTypeID];
|
||||
}
|
||||
|
||||
static function AvailableStrategicCommand(int $allowTurnCnt=0):array{
|
||||
return [__FUNCTION__, $allowTurnCnt];
|
||||
}
|
||||
|
||||
static function BattleGroundCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function BeChief():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function BeLord():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function BeNeutral():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function BeOpeningPart(int $relYear):array{
|
||||
return [__FUNCTION__, $relYear];
|
||||
}
|
||||
|
||||
static function CheckNationNameDuplicate(string $nationName):array{
|
||||
return [__FUNCTION__, $nationName];
|
||||
}
|
||||
|
||||
static function ConstructableCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function DifferentNationDestGeneral():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function DifferentDestNation():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function DisallowDiplomacyBetweenStatus(array $disallowList):array{
|
||||
return [__FUNCTION__, $disallowList];
|
||||
}
|
||||
|
||||
static function DisallowDiplomacyStatus(int $nationID, array $disallowList):array{
|
||||
return [__FUNCTION__, [$nationID, $disallowList]];
|
||||
}
|
||||
|
||||
static function ExistsAllowJoinNation(int $relYear, array $excludeNationList):array{
|
||||
return [__FUNCTION__, [$relYear, $excludeNationList]];
|
||||
}
|
||||
|
||||
static function ExistsDestGeneral():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function ExistsDestNation():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function FriendlyDestGeneral():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function HasRoute():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function HasRouteWithEnemy():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function MustBeNPC():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function MustBeTroopLeader():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NearCity(int $distance):array{
|
||||
return [__FUNCTION__, $distance];
|
||||
}
|
||||
|
||||
static function NearNation():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NotBeNeutral():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NotCapital(bool $ignoreOfficer=false):array{
|
||||
return [__FUNCTION__, $ignoreOfficer];
|
||||
}
|
||||
|
||||
static function NotChief():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NotLord():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NotNeutralDestCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NotOccupiedDestCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NotOpeningPart(int $relYear):array{
|
||||
return [__FUNCTION__, $relYear];
|
||||
}
|
||||
|
||||
static function NotSameDestCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function NotWanderingNation():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function OccupiedCity(bool $allowNeutral=false):array{
|
||||
return [__FUNCTION__, $allowNeutral];
|
||||
}
|
||||
|
||||
static function OccupiedDestCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function RemainCityCapacity($key, string $actionName):array{
|
||||
return [__FUNCTION__, [$key, $actionName]];
|
||||
}
|
||||
|
||||
static function RemainCityTrust(string $actionName):array{
|
||||
return [__FUNCTION__, $actionName];
|
||||
}
|
||||
|
||||
static function ReqCityCapacity($key, string $keyNick, $reqVal):array{
|
||||
return [__FUNCTION__, [$key, $keyNick, $reqVal]];
|
||||
}
|
||||
|
||||
static function ReqCityTrust(float $minTrust):array{
|
||||
return [__FUNCTION__, $minTrust];
|
||||
}
|
||||
|
||||
static function ReqCityValue($key, string $keyNick, string $comp, $reqVal, ?string $errMsg=null):array{
|
||||
return [__FUNCTION__, [$key, $keyNick, $comp, $reqVal, $errMsg]];
|
||||
}
|
||||
|
||||
static function ReqDestCityValue($key, string $keyNick, string $comp, $reqVal, ?string $errMsg=null):array{
|
||||
return [__FUNCTION__, [$key, $keyNick, $comp, $reqVal, $errMsg]];
|
||||
}
|
||||
|
||||
static function ReqCityTrader(int $npcType):array{
|
||||
return [__FUNCTION__, $npcType];
|
||||
}
|
||||
|
||||
static function ReqDestNationValue($key, string $keyNick, string $comp, $reqVal, ?string $errMsg=null):array{
|
||||
return [__FUNCTION__, [$key, $keyNick, $comp, $reqVal, $errMsg]];
|
||||
}
|
||||
|
||||
static function ReqEnvValue($key, string $comp, $reqVal, string $failMessage):array{
|
||||
return [__FUNCTION__, [$key, $comp, $reqVal, $failMessage]];
|
||||
}
|
||||
|
||||
static function ReqGeneralAtmosMargin(int $maxAtmos):array{
|
||||
return [__FUNCTION__, $maxAtmos];
|
||||
}
|
||||
|
||||
static function ReqGeneralCrew():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function ReqGeneralCrewMargin(int $crewTypeID):array{
|
||||
return [__FUNCTION__, $crewTypeID];
|
||||
}
|
||||
|
||||
static function ReqGeneralGold(int $reqGold):array{
|
||||
return [__FUNCTION__, $reqGold];
|
||||
}
|
||||
|
||||
static function ReqGeneralRice(int $reqRice):array{
|
||||
return [__FUNCTION__, $reqRice];
|
||||
}
|
||||
|
||||
static function ReqGeneralTrainMargin(int $maxTrain):array{
|
||||
return [__FUNCTION__, $maxTrain];
|
||||
}
|
||||
|
||||
static function ReqGeneralValue($key, string $keyNick, string $comp, $reqVal, ?string $errMsg=null):array{
|
||||
return [__FUNCTION__, [$key, $keyNick, $comp, $reqVal, $errMsg]];
|
||||
}
|
||||
|
||||
static function ReqNationGold(int $reqGold):array{
|
||||
return [__FUNCTION__, $reqGold];
|
||||
}
|
||||
|
||||
static function ReqNationRice(int $reqRice):array{
|
||||
return [__FUNCTION__, $reqRice];
|
||||
}
|
||||
|
||||
static function ReqNationValue($key, string $keyNick, string $comp, $reqVal, ?string $errMsg=null):array{
|
||||
return [__FUNCTION__, [$key, $keyNick, $comp, $reqVal, $errMsg]];
|
||||
}
|
||||
|
||||
static function ReqNationAuxValue($key, $defaultValue, string $comp, $reqVal, string $errMsg):array{
|
||||
return [__FUNCTION__, [$key, $defaultValue, $comp, $reqVal, $errMsg]];
|
||||
}
|
||||
|
||||
static function ReqTroopMembers():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function SuppliedCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function SuppliedDestCity():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
|
||||
static function WanderingNation():array{
|
||||
return [__FUNCTION__];
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user