forked from devsam/core
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f6259c157 | ||
|
|
8908e12c59 | ||
|
|
a7d6bc2c5c | ||
|
|
97fd807c2c | ||
|
|
b31f7d64ec | ||
|
|
bdd574161e | ||
|
|
e23e36cbfa | ||
|
|
fb796e21e4 | ||
|
|
dd46c02f09 | ||
|
|
d1835c71b7 | ||
|
|
55332864ad | ||
|
|
96a8ef3bcc | ||
|
|
79cfbfe83b | ||
|
|
e7fa95ce8f | ||
|
|
a819dde71c | ||
|
|
281cfd366b | ||
|
|
f1ba7e76f3 | ||
|
|
2da72d9b1a | ||
|
|
4cdc18fe7e | ||
|
|
4400116bdd | ||
|
|
086d6d1ab5 | ||
|
|
02e86fd2e9 | ||
|
|
7310aa6971 | ||
|
|
4927a26c92 | ||
|
|
ee6bec2e0d | ||
|
|
def230bf30 | ||
|
|
0a4d568b06 | ||
|
|
69f8e1f1bd | ||
|
|
6f2cb4e05e | ||
|
|
db1fbb700c | ||
|
|
842a37eb7b | ||
|
|
76ff38ed10 | ||
|
|
db6b2be101 | ||
|
|
a998500839 | ||
|
|
dd5e686d03 | ||
|
|
c9f28e27d2 | ||
|
|
1bbeb4f50d | ||
|
|
410f6b261e |
+1
-1
@@ -5,7 +5,7 @@ module.exports = {
|
||||
"browser": true,
|
||||
"es2021": true
|
||||
},
|
||||
ignorePatterns: ['*.test.ts', '.eslintrc.cjs', 'webpack.config.cjs', '*.js'],
|
||||
ignorePatterns: ['*.test.ts', '.eslintrc.cjs', 'postcss.config.cjs', 'webpack.config.cjs', '*.js'],
|
||||
overrides: [{
|
||||
files: ['*.ts', '*.tsx', "*.vue"],
|
||||
}],
|
||||
|
||||
@@ -43,6 +43,7 @@ d_pic/uploaded_image
|
||||
|
||||
d_setting/*.php
|
||||
*/d_setting/*.php
|
||||
*/d_setting/*.json
|
||||
*/d_setting/templates/*.php
|
||||
!*.orig.php
|
||||
|
||||
|
||||
+1
-6
@@ -52,7 +52,7 @@ return [
|
||||
'hwe/b_betting.php',
|
||||
'hwe/v_chiefCenter.php',
|
||||
'hwe/b_currentCity.php',
|
||||
'hwe/b_dipcenter.php',
|
||||
'hwe/v_nationStratFinan.php',
|
||||
'hwe/b_diplomacy.php',
|
||||
'hwe/b_genList.php',
|
||||
'hwe/b_myBossInfo.php',
|
||||
@@ -64,7 +64,6 @@ return [
|
||||
'hwe/b_tournament.php',
|
||||
'hwe/b_troop.php',
|
||||
'hwe/c_auction.php',
|
||||
'hwe/c_dipcenter.php',
|
||||
'hwe/c_tournament.php',
|
||||
'hwe/c_vote.php',
|
||||
'hwe/func_auction.php',
|
||||
@@ -91,7 +90,6 @@ return [
|
||||
'hwe/j_board_article_add.php',
|
||||
'hwe/j_board_comment_add.php',
|
||||
'hwe/j_board_get_articles.php',
|
||||
'hwe/j_chief_turn.php',
|
||||
'hwe/j_die_immediately.php',
|
||||
'hwe/j_diplomacy_destroy_letter.php',
|
||||
'hwe/j_diplomacy_get_letter.php',
|
||||
@@ -102,7 +100,6 @@ return [
|
||||
'hwe/j_general_log_old.php',
|
||||
'hwe/j_general_set_permission.php',
|
||||
'hwe/j_get_basic_general_list.php',
|
||||
'hwe/j_getChiefTurn.php',
|
||||
'hwe/j_get_city_list.php',
|
||||
'hwe/j_get_general_list.php',
|
||||
'hwe/j_get_nation_general_list.php',
|
||||
@@ -126,8 +123,6 @@ return [
|
||||
'hwe/j_select_npc.php',
|
||||
'hwe/j_select_picked_general.php',
|
||||
'hwe/j_server_basic_info.php',
|
||||
'hwe/j_set_chief_command.php',
|
||||
'hwe/j_set_general_command.php',
|
||||
'hwe/j_set_my_setting.php',
|
||||
'hwe/j_set_npc_control.php',
|
||||
'hwe/j_simulate_battle.php',
|
||||
|
||||
@@ -1,269 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin()->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
increaseRefresh("내무부", 1);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no, nation, officer_level, con, turntime, belong, permission, penalty FROM general WHERE owner=%i', $userID);
|
||||
|
||||
$nationID = $me['nation'];
|
||||
$nation = $db->queryFirstRow('SELECT nation,level,name,color,type,gold,rice,bill,rate,scout,war,secretlimit,capital FROM nation WHERE nation = %i', $nationID);
|
||||
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
printLimitMsg($me['turntime']);
|
||||
exit();
|
||||
}
|
||||
|
||||
$permission = checkSecretPermission($me);
|
||||
if ($permission < 0) {
|
||||
echo '국가에 소속되어있지 않습니다.';
|
||||
die();
|
||||
} else if ($permission < 1) {
|
||||
echo "권한이 부족합니다. 수뇌부가 아니거나 사관년도가 부족합니다.";
|
||||
die();
|
||||
}
|
||||
|
||||
if ($me['officer_level'] >= 5) {
|
||||
$btn = "submit";
|
||||
$read = "";
|
||||
} else {
|
||||
$btn = "hidden";
|
||||
$read = "readonly";
|
||||
}
|
||||
|
||||
$nationStor->cacheValues(['notice', 'scout_msg', 'available_war_setting_cnt']);
|
||||
|
||||
?>
|
||||
<!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::printStaticValues([
|
||||
'editable' => ($me['officer_level'] >= 5 || $permission == 4),
|
||||
'nationMsg' => $nationStor->notice ?? '',
|
||||
'scoutMsg' => $nationStor->scout_msg ?? '',
|
||||
]) ?>
|
||||
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
|
||||
<?= WebUtil::printCSS('../d_shared/common.css') ?>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
|
||||
<?= WebUtil::printDist('vue', 'v_dipcenter', true) ?>
|
||||
</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 colspan=9 align=center bgcolor=blue>외 교 관 계</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width=130 align=center class=bg1>국 가 명</td>
|
||||
<td width=50 align=center class=bg1>국력</td>
|
||||
<td width=40 align=center class=bg1>장수</td>
|
||||
<td width=40 align=center class=bg1>속령</td>
|
||||
<td width=80 align=center class=bg1>상태</td>
|
||||
<td width=60 align=center class=bg1>기간</td>
|
||||
<td width=100 align=center class=bg1>종 료 시 점</td>
|
||||
</tr>
|
||||
<?php
|
||||
$admin = $gameStor->getValues(['year', 'month']);
|
||||
|
||||
$cityCntList = Util::convertPairArrayToDict($db->queryAllLists('SELECT nation, count(city) FROM city GROUP BY nation'));
|
||||
$dipStateList = Util::convertArrayToDict($db->query('SELECT you,state,term FROM diplomacy WHERE me = %i', $nationID), 'you');
|
||||
|
||||
$nationsList = getAllNationStaticInfo();
|
||||
uasort($nationsList, function (array $lhs, array $rhs) {
|
||||
return - ($lhs['power'] <=> $rhs['power']);
|
||||
});
|
||||
|
||||
foreach ($nationsList as $staticNation) :
|
||||
//속령수
|
||||
$staticNationID = $staticNation['nation'];
|
||||
$cityCnt = $cityCntList[$staticNation['nation']] ?? 0;
|
||||
|
||||
$dipStateText = '-';
|
||||
$dipTermText = '-';
|
||||
$dipEndDateText = '-';
|
||||
if ($staticNationID !== $nationID) {
|
||||
$diplomacyState = $dipStateList[$staticNationID];
|
||||
|
||||
$dipStateText = [
|
||||
0 => "<font color=red>교 전</font>",
|
||||
1 => "<font color=magenta>선포중</font>",
|
||||
2 => "통 상",
|
||||
7 => "<font color=green>불가침</font>",
|
||||
][$diplomacyState['state']];
|
||||
|
||||
if ($diplomacyState['term']) {
|
||||
$dipEndMonth = $admin['month'] + $diplomacyState['term'] - 1;
|
||||
$dipEndYear = $admin['year'] + intdiv($dipEndMonth, 12);
|
||||
$dipEndMonth = $dipEndMonth % 12 + 1;
|
||||
|
||||
$dipTermText = $diplomacyState['term'] . '개월';
|
||||
$dipEndDateText = "{$dipEndYear}年 {$dipEndMonth}月";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td class='center' style='color:<?= newColor($staticNation['color']) ?>;background-color:<?= $staticNation['color'] ?>'><?= $staticNation['name'] ?></td>
|
||||
<td class='center'><?= $staticNation['power'] ?></td>
|
||||
<td class='center'><?= $staticNation['gennum'] ?></td>
|
||||
<td class='center'><?= $cityCnt ?></td>
|
||||
<td class='center'><?= $dipStateText ?></td>
|
||||
<td class='center'><?= $dipTermText ?></td>
|
||||
<td class='center'><?= $dipEndDateText ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
|
||||
<?php
|
||||
// 수입 연산
|
||||
$cityList = $db->query('SELECT * FROM city WHERE nation=%i', $nationID);
|
||||
$dedicationList = $db->query('SELECT dedication FROM general WHERE nation=%i AND npc!=5', $nationID);
|
||||
|
||||
$goldIncome = getGoldIncome($nation['nation'], $nation['level'], $nation['rate'], $nation['capital'], $nation['type'], $cityList);
|
||||
$warIncome = getWarGoldIncome($nation['type'], $cityList);
|
||||
$totalGoldIncome = $goldIncome + $warIncome;
|
||||
|
||||
$riceIncome = getRiceIncome($nation['nation'], $nation['level'], $nation['rate'], $nation['capital'], $nation['type'], $cityList);
|
||||
$wallIncome = getWallIncome($nation['nation'], $nation['level'], $nation['rate'], $nation['capital'], $nation['type'], $cityList);
|
||||
$totalRiceIncome = $riceIncome + $wallIncome;
|
||||
|
||||
$outcome = getOutcome($nation['bill'], $dedicationList);
|
||||
|
||||
$budgetgold = $nation['gold'] + $totalGoldIncome - $outcome;
|
||||
$budgetrice = $nation['rice'] + $totalRiceIncome - $outcome;
|
||||
$budgetgolddiff = $totalGoldIncome - $outcome;
|
||||
$budgetricediff = $totalRiceIncome - $outcome;
|
||||
|
||||
if ($budgetgolddiff > 0) {
|
||||
$budgetgolddiff = '+' . number_format($budgetgolddiff);
|
||||
} else {
|
||||
$budgetgolddiff = number_format($budgetgolddiff);
|
||||
}
|
||||
if ($budgetricediff > 0) {
|
||||
$budgetricediff = '+' . number_format($budgetricediff);
|
||||
} else {
|
||||
$budgetricediff = number_format($budgetricediff);
|
||||
}
|
||||
|
||||
?>
|
||||
<div class='tb_layout bg0' style='margin:auto;width: 1000px;' id="editorForm">
|
||||
|
||||
</div>
|
||||
<table class="tb_layout bg0" style="margin:auto;">
|
||||
<form name=form1 method=post action=c_dipcenter.php>
|
||||
|
||||
<tr>
|
||||
<td colspan=2 align=center bgcolor=green>예 산 & 정 책</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=2>
|
||||
<table width=998 class='tb_layout bg0'>
|
||||
<tr>
|
||||
<td colspan=2 align=center class=bg1>자금 예산</td>
|
||||
<td colspan=2 align=center class=bg1>병량 예산</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width=248 align=right class=bg1>현 재 </td>
|
||||
<td width=248 align=center><?= number_format($nation['gold']) ?></td>
|
||||
<td width=248 align=right class=bg1>현 재 </td>
|
||||
<td width=248 align=center><?= number_format($nation['rice']) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=right class=bg1>단기수입 </td>
|
||||
<td align=center>+<?= number_format($warIncome) ?></td>
|
||||
<td align=right class=bg1>둔전수입 </td>
|
||||
<td align=center>+<?= number_format($wallIncome) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=right class=bg1>세 금 </td>
|
||||
<td align=center>+<?= number_format($goldIncome) ?></td>
|
||||
<td align=right class=bg1>세 곡 </td>
|
||||
<td align=center>+<?= number_format($riceIncome) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=right class=bg1>수입 / 지출 </td>
|
||||
<td align=center>+<?= number_format($totalGoldIncome) ?> / -<?= number_format($outcome) ?></td>
|
||||
<td align=right class=bg1>수입 / 지출 </td>
|
||||
<td align=center>+<?= number_format($totalRiceIncome) ?> / -<?= number_format($outcome) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=right class=bg1>국고 예산 </td>
|
||||
<td align=center><?= number_format($budgetgold) ?> (<?= $budgetgolddiff ?>)</td>
|
||||
<td align=right class=bg1>병량 예산 </td>
|
||||
<td align=center><?= number_format($budgetrice) ?> (<?= $budgetricediff ?>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=right class=bg1>세율 (5 ~ 30%) </td>
|
||||
<td align=center><input type=text <?= $read ?> name=rate style=text-align:right;color:white;background-color:black; size=3 maxlength=3 value=<?= $nation['rate'] ?>>% <input type=<?= $btn ?> name=btn value=세율></td>
|
||||
<td align=right class=bg1>봉급 지급률 (20 ~ 200%) </td>
|
||||
<td align=center><input type=text <?= $read ?> name=bill style=text-align:right;color:white;background-color:black; size=3 maxlength=3 value=<?= $nation['bill'] ?>>% <input type=<?= $btn ?> name=btn value=지급률></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align=right class=bg1>기밀 권한 (1 ~ 99년) </td>
|
||||
<td align=center><input type=text <?= $read ?> name=secretlimit style=text-align:right;color:white;background-color:black; size=3 maxlength=3 value=<?= $nation['secretlimit'] ?>>년 <input type=<?= $btn ?> name=btn value=기밀권한></td>
|
||||
<td align=right class=bg1>전쟁 허용/금지 변경 가능</td>
|
||||
<td align=center><?= $nationStor->getValue('available_war_setting_cnt') ?>회(월 +<?= GameConst::$incAvailableWarSettingCnt ?>회, 최대<?= GameConst::$maxAvailableWarSettingCnt ?>회)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=4 align=center>
|
||||
<?php
|
||||
if ($nation['scout'] == 0) {
|
||||
echo "
|
||||
<input type=$btn name=btn value='임관 금지'>";
|
||||
} else {
|
||||
echo "
|
||||
<input type=$btn name=btn value='임관 허가'>";
|
||||
}
|
||||
|
||||
if ($nation['war'] == 0) {
|
||||
echo "
|
||||
<input type=$btn name=btn value='전쟁 금지'>";
|
||||
} else {
|
||||
echo "
|
||||
<input type=$btn name=btn value='전쟁 허가'>";
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<tr>
|
||||
<td colspan=2>기밀 권한이란, 암행부를 열람할 수 있는 일반 장수의 최소 사관 년수를 의미합니다.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=2 height=10></td>
|
||||
</tr>
|
||||
</form>
|
||||
</table>
|
||||
<table align=center width=1000 class='tb_layout bg0'>
|
||||
<tr>
|
||||
<td><?= backButton() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?= banner() ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -94,6 +94,8 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
|
||||
<option value=0 <?= (!$use_auto_nation_turn) ? "selected" : ""; ?>>허용 안함</option>
|
||||
</select>】<br>
|
||||
∞<span style='color:orange'>수뇌가 되었을 때 휴식 턴이어도 적당한 턴을 알아서 넣는 것을 허용합니다.</span><br><br>
|
||||
<?php else: ?>
|
||||
<input type="hidden" id='use_auto_nation_turn' name='use_auto_nation_turn' value="1"/>
|
||||
<?php endif; ?>
|
||||
수비 【<select id='defence_train' name='defence_train'>
|
||||
<?php foreach ([90, 80, 60, 40] as $targetDefenceTrain) : ?>
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
// $btn, $msg, $scoutmsg, $rate, $bill, $secretlimit
|
||||
|
||||
$btn = Util::getPost('btn');
|
||||
//$msg = Util::getPost('msg');
|
||||
//$scoutmsg = Util::getPost('scoutMsg');
|
||||
$rate = Util::getPost('rate', 'int');
|
||||
$bill = Util::getPost('bill', 'int');
|
||||
$secretlimit = Util::getPost('secretlimit', 'int');
|
||||
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin()->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$me = $db->queryFirstRow('SELECT `no`,nation,`officer_level`,permission,penalty FROM general WHERE `owner`=%i', $userID);
|
||||
|
||||
//내가 수뇌부이어야함
|
||||
$permission = checkSecretPermission($me);
|
||||
if ($permission < 0) {
|
||||
header('location:b_myBossInfo.php', true, 303);
|
||||
exit();
|
||||
} else if ($me['officer_level'] < 5 && $permission != 4) {
|
||||
header('location:b_myBossInfo.php', true, 303);
|
||||
exit();
|
||||
}
|
||||
|
||||
$nationID = $me['nation'];
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
|
||||
/*if ($btn == "국가방침 수정") {
|
||||
$msg = mb_substr($msg, 0, 16384);
|
||||
//$msg = StringUtil::
|
||||
$nationStor->notice = WebUtil::htmlPurify($msg);
|
||||
} elseif ($btn == "임관 권유문 수정") {
|
||||
$scoutmsg = mb_substr($scoutmsg, 0, 1000);
|
||||
$nationStor->scout_msg = WebUtil::htmlPurify($scoutmsg);
|
||||
} else*/if ($btn == "세율") {
|
||||
$rate = Util::valueFit($rate, 5, 30);
|
||||
$db->update('nation', [
|
||||
'rate' => $rate,
|
||||
], 'nation=%i', $nationID);
|
||||
} elseif ($btn == "지급률") {
|
||||
$bill = Util::valueFit($bill, 20, 200);
|
||||
$db->update('nation', [
|
||||
'bill' => $bill
|
||||
], 'nation=%i', $nationID);
|
||||
} elseif ($btn == "기밀권한") {
|
||||
$secretlimit = Util::valueFit($secretlimit, 1, 99);
|
||||
$db->update('nation', [
|
||||
'secretlimit' => $secretlimit
|
||||
], 'nation=%i', $nationID);
|
||||
} elseif ($btn == "임관 금지") {
|
||||
$db->update('nation', [
|
||||
'scout' => 1
|
||||
], 'nation=%i', $nationID);
|
||||
} elseif ($btn == "임관 허가") {
|
||||
$db->update('nation', [
|
||||
'scout' => 0
|
||||
], 'nation=%i', $nationID);
|
||||
} elseif ($btn == "전쟁 금지") {
|
||||
$avilableCnt = $nationStor->getValue('available_war_setting_cnt') ?? 0;
|
||||
if ($avilableCnt > 0) {
|
||||
$db->update('nation', [
|
||||
'war' => 1
|
||||
], 'nation=%i', $nationID);
|
||||
$nationStor->setValue('available_war_setting_cnt', $avilableCnt - 1);
|
||||
}
|
||||
} elseif ($btn == "전쟁 허가") {
|
||||
$avilableCnt = $nationStor->getValue('available_war_setting_cnt') ?? 0;
|
||||
if ($avilableCnt > 0) {
|
||||
$db->update('nation', [
|
||||
'war' => 0
|
||||
], 'nation=%i', $nationID);
|
||||
$nationStor->setValue('available_war_setting_cnt', $avilableCnt - 1);
|
||||
}
|
||||
}
|
||||
|
||||
header('location:b_dipcenter.php');
|
||||
@@ -1581,6 +1581,18 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
|
||||
}
|
||||
}
|
||||
|
||||
foreach($db->queryAllLists('SELECT namespace, count(*) as cnt FROM `storage` WHERE namespace LIKE "ut_%" GROUP BY namespace') as [$uniqueNS, $cnt]){
|
||||
$itemCode = substr($uniqueNS, 3);
|
||||
$itemClass = buildItemClass($itemCode);
|
||||
if (!$itemClass) {
|
||||
continue;
|
||||
}
|
||||
if ($itemClass->isBuyable()) {
|
||||
continue;
|
||||
}
|
||||
$occupiedUnique[$itemCode] = ($occupiedUnique[$itemCode]??0) + $cnt;
|
||||
}
|
||||
|
||||
foreach (GameConst::$allItems as $itemType => $itemCategories) {
|
||||
if (key_exists($itemType, $invalidItemType)) {
|
||||
continue;
|
||||
|
||||
@@ -513,7 +513,7 @@ function fillLowGenAll($tnmt_type)
|
||||
'SELECT no,npc,name,leadership,strength,intel,explevel,horse,weapon,book from general where tnmt=1 and tournament=0',
|
||||
) as $gen){
|
||||
$score = $scoringCandFunction($gen);
|
||||
$freeJoinerCandidate[$gen['no']] = [$gen, $score**2];
|
||||
$freeJoinerCandidate[$gen['no']] = [$gen, $score**1.5];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin()->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
|
||||
$turnAmount = Util::getPost('amount', 'int');
|
||||
|
||||
$db = DB::db();
|
||||
$me = $db->queryFirstRow('SELECT no,nation,officer_level FROM general WHERE owner=%i', $userID);
|
||||
|
||||
if($me['nation'] == 0){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'국가에 소속되어 있지 않습니다.',
|
||||
]);
|
||||
}
|
||||
|
||||
if($me['officer_level'] < 5){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'수뇌가 아닙니다.',
|
||||
]);
|
||||
}
|
||||
|
||||
if($turnAmount > 0){
|
||||
pushNationCommand($me['nation'], $me['officer_level']);
|
||||
}
|
||||
else{
|
||||
pullNationCommand($me['nation'], $me['officer_level']);
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success',
|
||||
]);
|
||||
@@ -1,103 +0,0 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin()->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
increaseRefresh("사령부", 1);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,penalty,permission FROM general WHERE owner=%i', $userID);
|
||||
|
||||
$nationLevel = $db->queryFirstField('SELECT level FROM nation WHERE nation = %i', $me['nation']);
|
||||
$nationID = $me['nation'];
|
||||
$con = checkLimit($me['con']);
|
||||
if($con >= 2) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>"접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 접속 가능 시각 : {$me['turntime']})"
|
||||
]);
|
||||
}
|
||||
|
||||
$permission = checkSecretPermission($me);
|
||||
if($permission < 0){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'국가에 소속되어있지 않습니다.'
|
||||
]);
|
||||
echo '국가에 소속되어있지 않습니다.';
|
||||
die();
|
||||
}
|
||||
else if ($permission < 1) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'수뇌부가 아니거나 사관년도가 부족합니다.'
|
||||
]);
|
||||
die();
|
||||
}
|
||||
|
||||
$date = TimeUtil::now();
|
||||
|
||||
// 명령 목록
|
||||
[$year, $month, $turnterm] = $gameStor->getValuesAsArray(['year', 'month', 'turnterm']);
|
||||
$lv = getNationChiefLevel($nationLevel);
|
||||
$turn = [];
|
||||
|
||||
$generals = [];
|
||||
foreach($db->query('SELECT no,name,turntime,npc,city,nation,officer_level FROM general WHERE nation = %i AND officer_level >= 5',$nationID) as $rawGeneral){
|
||||
$generals[$rawGeneral['officer_level']] = new General($rawGeneral, null, null, null, $year, $month, false);
|
||||
}
|
||||
|
||||
$nationTurnList = [];
|
||||
|
||||
foreach(
|
||||
$db->queryAllLists(
|
||||
'SELECT officer_level, turn_idx, action, arg, brief FROM nation_turn WHERE nation_id = %i ORDER BY officer_level DESC, turn_idx ASC',
|
||||
$me['nation']
|
||||
) as [$officer_level, $turn_idx, $action, $arg, $brief]
|
||||
){
|
||||
if(!key_exists($officer_level, $nationTurnList)){
|
||||
$nationTurnList[$officer_level] = [];
|
||||
}
|
||||
$nationTurnList[$officer_level][$turn_idx] = $brief;
|
||||
}
|
||||
|
||||
$nationTurnBrief = [];
|
||||
foreach($nationTurnList as $officer_level=>$turnBrief){
|
||||
if(!key_exists($officer_level, $generals)){
|
||||
$nationTurnBrief[$officer_level] = [
|
||||
'name'=>null,
|
||||
'turnTime'=>null,
|
||||
'officerLevelText'=>getOfficerLevelText($officer_level, $nationLevel),
|
||||
'npcType'=>null,
|
||||
'turn'=>$turnBrief
|
||||
];
|
||||
continue;
|
||||
}
|
||||
$general = $generals[$officer_level];
|
||||
$nationTurnBrief[$officer_level] = [
|
||||
'name'=>$general->getName(),
|
||||
'turnTime'=>$general->getTurnTime($general::TURNTIME_FULL),
|
||||
'officerLevel'=>$general->getVar('officer_level'),
|
||||
'officerLevelText'=>getOfficerLevelText($general->getVar('officer_level'), $nationLevel),
|
||||
'npcType'=>$general->getNPCType(),
|
||||
'turn'=>$turnBrief,
|
||||
];
|
||||
}
|
||||
|
||||
$date = substr(TimeUtil::now(), 14);
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success',
|
||||
'date'=>$date,
|
||||
'nationTurnBrief'=>$nationTurnBrief,
|
||||
'isChief'=>($me['officer_level'] > 4),
|
||||
'officerLevel'=>$me['officer_level'],
|
||||
'turnTerm'=>$turnterm
|
||||
]);
|
||||
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
|
||||
$session = Session::requireGameLogin([])->setReadOnly();
|
||||
|
||||
increaseRefresh("사령턴 입력", 0);
|
||||
|
||||
$generalID = $session->generalID;
|
||||
|
||||
|
||||
$action = Util::getPost('action', 'string');
|
||||
$arg = Json::decode(Util::getPost('arg', 'string'));
|
||||
$turnList = Util::getPost('turnList', 'array_int');
|
||||
|
||||
if(!is_array($turnList) || !$turnList){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'턴이 입력되지 않았습니다.',
|
||||
'test'=>'post',
|
||||
]);
|
||||
}
|
||||
|
||||
if(!$action){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'action이 입력되지 않았습니다.',
|
||||
'test'=>'post'
|
||||
]);
|
||||
}
|
||||
|
||||
if(!in_array($action, Util::array_flatten(GameConst::$availableChiefCommand))){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'사용할 수 없는 커맨드입니다.',
|
||||
'test'=>'post'
|
||||
]);
|
||||
}
|
||||
|
||||
if($arg === null){
|
||||
$arg = [];
|
||||
}
|
||||
|
||||
if(!is_array($arg)){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바른 arg 형태가 아닙니다.',
|
||||
'test'=>'post'
|
||||
]);
|
||||
}
|
||||
|
||||
$result = setNationCommand($generalID, $turnList, $action, $arg);
|
||||
if(!key_exists('result', $result)){
|
||||
$result['result'] = false;
|
||||
}
|
||||
if(!key_exists('arg_test', $result)){
|
||||
$result['arg_test'] = false;
|
||||
}
|
||||
if(!key_exists('reason', $result)){
|
||||
throw new MustNotBeReachedException('reason이 왜 없어?');
|
||||
}
|
||||
Json::die($result);
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
|
||||
$session = Session::requireGameLogin([])->setReadOnly();
|
||||
|
||||
increaseRefresh("턴 입력", 0);
|
||||
|
||||
$generalID = $session->generalID;
|
||||
|
||||
$action = Util::getPost('action', 'string');
|
||||
$arg = Json::decode(Util::getPost('arg', 'string'));
|
||||
$turnList = Util::getPost('turnList', 'array_int');
|
||||
|
||||
if(!is_array($turnList) || !$turnList){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'턴이 입력되지 않았습니다.',
|
||||
'test'=>'post',
|
||||
]);
|
||||
}
|
||||
|
||||
if(!$action){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'action이 입력되지 않았습니다.',
|
||||
'test'=>'post'
|
||||
]);
|
||||
}
|
||||
|
||||
if(!in_array($action, Util::array_flatten(GameConst::$availableGeneralCommand))){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'사용할 수 없는 커맨드입니다.',
|
||||
'test'=>'post'
|
||||
]);
|
||||
}
|
||||
|
||||
if($arg === null){
|
||||
$arg = [];
|
||||
}
|
||||
|
||||
if(!is_array($arg)){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바른 arg 형태가 아닙니다.',
|
||||
'test'=>'post'
|
||||
]);
|
||||
}
|
||||
|
||||
Json::die(setGeneralCommand($generalID, $turnList, $action, $arg));
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\API\Nation;
|
||||
|
||||
use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\DB;
|
||||
use sammo\KVStorage;
|
||||
use sammo\Validator;
|
||||
use sammo\WebUtil;
|
||||
|
||||
use function sammo\checkSecretPermission;
|
||||
|
||||
class SetBill extends \sammo\BaseAPI
|
||||
{
|
||||
public function validateArgs(): ?string
|
||||
{
|
||||
$v = new Validator($this->args);
|
||||
$v->rule('required', [
|
||||
'amount',
|
||||
])
|
||||
->rule('integer', 'amount')
|
||||
->rule('min', 'amount', 20)
|
||||
->rule('max', 'amount', 200);
|
||||
|
||||
if (!$v->validate()) {
|
||||
return $v->errorStr();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getRequiredSessionMode(): int
|
||||
{
|
||||
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
|
||||
}
|
||||
|
||||
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||
{
|
||||
$amount = $this->args['amount'];
|
||||
$userID = $session->userID;
|
||||
$db = DB::db();
|
||||
$me = $db->queryFirstRow('SELECT `no`,nation,`officer_level`,permission,penalty FROM general WHERE `owner`=%i', $userID);
|
||||
|
||||
$permission = checkSecretPermission($me, false);
|
||||
if($permission < 0){
|
||||
return "권한이 부족합니다.";
|
||||
}
|
||||
if ($me['officer_level'] < 5 && $permission != 4){
|
||||
return "권한이 부족합니다.";
|
||||
}
|
||||
|
||||
|
||||
$nationID = $me['nation'];
|
||||
|
||||
$db->update('nation', [
|
||||
'bill' => $amount
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
return [
|
||||
'result' => true
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\API\Nation;
|
||||
|
||||
use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\DB;
|
||||
use sammo\KVStorage;
|
||||
use sammo\Validator;
|
||||
use sammo\WebUtil;
|
||||
|
||||
use function sammo\checkSecretPermission;
|
||||
|
||||
class SetBlockScout extends \sammo\BaseAPI
|
||||
{
|
||||
public function validateArgs(): ?string
|
||||
{
|
||||
$v = new Validator($this->args);
|
||||
$v->rule('required', [
|
||||
'value',
|
||||
])
|
||||
->rule('boolean', 'value');
|
||||
|
||||
if (!$v->validate()) {
|
||||
return $v->errorStr();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getRequiredSessionMode(): int
|
||||
{
|
||||
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
|
||||
}
|
||||
|
||||
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||
{
|
||||
$value = $this->args['value'];
|
||||
$userID = $session->userID;
|
||||
$db = DB::db();
|
||||
$me = $db->queryFirstRow('SELECT `no`,nation,`officer_level`,permission,penalty FROM general WHERE `owner`=%i', $userID);
|
||||
|
||||
$permission = checkSecretPermission($me, false);
|
||||
if($permission < 0){
|
||||
return "권한이 부족합니다.";
|
||||
}
|
||||
if ($me['officer_level'] < 5 && $permission != 4){
|
||||
return "권한이 부족합니다.";
|
||||
}
|
||||
|
||||
|
||||
$nationID = $me['nation'];
|
||||
|
||||
$db->update('nation', [
|
||||
'scout' => $value?1:0,
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
return [
|
||||
'result' => true
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\API\Nation;
|
||||
|
||||
use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\DB;
|
||||
use sammo\KVStorage;
|
||||
use sammo\Validator;
|
||||
use sammo\WebUtil;
|
||||
|
||||
use function sammo\checkSecretPermission;
|
||||
|
||||
class SetBlockWar extends \sammo\BaseAPI
|
||||
{
|
||||
public function validateArgs(): ?string
|
||||
{
|
||||
$v = new Validator($this->args);
|
||||
$v->rule('required', [
|
||||
'value',
|
||||
])
|
||||
->rule('boolean', 'value');
|
||||
|
||||
if (!$v->validate()) {
|
||||
return $v->errorStr();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getRequiredSessionMode(): int
|
||||
{
|
||||
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
|
||||
}
|
||||
|
||||
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||
{
|
||||
$value = $this->args['value'];
|
||||
$userID = $session->userID;
|
||||
$db = DB::db();
|
||||
$me = $db->queryFirstRow('SELECT `no`,nation,`officer_level`,permission,penalty FROM general WHERE `owner`=%i', $userID);
|
||||
|
||||
$permission = checkSecretPermission($me, false);
|
||||
if($permission < 0){
|
||||
return "권한이 부족합니다.";
|
||||
}
|
||||
if ($me['officer_level'] < 5 && $permission != 4){
|
||||
return "권한이 부족합니다.";
|
||||
}
|
||||
|
||||
$nationID = $me['nation'];
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
|
||||
|
||||
$avilableCnt = $nationStor->getValue('available_war_setting_cnt') ?? 0;
|
||||
if ($avilableCnt <= 0){
|
||||
return "잔여 횟수가 부족합니다.";
|
||||
}
|
||||
|
||||
|
||||
$db->update('nation', [
|
||||
'war' => $value?1:0,
|
||||
], 'nation=%i', $nationID);
|
||||
$nationStor->setValue('available_war_setting_cnt', $avilableCnt - 1);
|
||||
|
||||
return [
|
||||
'result' => true,
|
||||
'availableCnt' => $avilableCnt - 1,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\API\Nation;
|
||||
|
||||
use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\DB;
|
||||
use sammo\KVStorage;
|
||||
use sammo\Validator;
|
||||
use sammo\WebUtil;
|
||||
|
||||
use function sammo\checkSecretPermission;
|
||||
|
||||
class SetRate extends \sammo\BaseAPI
|
||||
{
|
||||
public function validateArgs(): ?string
|
||||
{
|
||||
$v = new Validator($this->args);
|
||||
$v->rule('required', [
|
||||
'amount',
|
||||
])
|
||||
->rule('integer', 'amount')
|
||||
->rule('min', 'amount', 5)
|
||||
->rule('max', 'amount', 30);
|
||||
|
||||
if (!$v->validate()) {
|
||||
return $v->errorStr();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getRequiredSessionMode(): int
|
||||
{
|
||||
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
|
||||
}
|
||||
|
||||
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||
{
|
||||
$amount = $this->args['amount'];
|
||||
$userID = $session->userID;
|
||||
$db = DB::db();
|
||||
$me = $db->queryFirstRow('SELECT `no`,nation,`officer_level`,permission,penalty FROM general WHERE `owner`=%i', $userID);
|
||||
|
||||
$permission = checkSecretPermission($me, false);
|
||||
if($permission < 0){
|
||||
return "권한이 부족합니다.";
|
||||
}
|
||||
if ($me['officer_level'] < 5 && $permission != 4){
|
||||
return "권한이 부족합니다.";
|
||||
}
|
||||
|
||||
|
||||
$nationID = $me['nation'];
|
||||
|
||||
$db->update('nation', [
|
||||
'rate' => $amount
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
return [
|
||||
'result' => true
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\API\Nation;
|
||||
|
||||
use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\DB;
|
||||
use sammo\KVStorage;
|
||||
use sammo\Validator;
|
||||
use sammo\WebUtil;
|
||||
|
||||
use function sammo\checkSecretPermission;
|
||||
|
||||
class SetSecretLimit extends \sammo\BaseAPI
|
||||
{
|
||||
public function validateArgs(): ?string
|
||||
{
|
||||
$v = new Validator($this->args);
|
||||
$v->rule('required', [
|
||||
'amount',
|
||||
])
|
||||
->rule('integer', 'amount')
|
||||
->rule('min', 'amount', 1)
|
||||
->rule('max', 'amount', 99);
|
||||
|
||||
if (!$v->validate()) {
|
||||
return $v->errorStr();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getRequiredSessionMode(): int
|
||||
{
|
||||
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
|
||||
}
|
||||
|
||||
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||
{
|
||||
$amount = $this->args['amount'];
|
||||
$userID = $session->userID;
|
||||
$db = DB::db();
|
||||
$me = $db->queryFirstRow('SELECT `no`,nation,`officer_level`,permission,penalty FROM general WHERE `owner`=%i', $userID);
|
||||
|
||||
$permission = checkSecretPermission($me, false);
|
||||
if($permission < 0){
|
||||
return "권한이 부족합니다.";
|
||||
}
|
||||
if ($me['officer_level'] < 5 && $permission != 4){
|
||||
return "권한이 부족합니다.";
|
||||
}
|
||||
|
||||
|
||||
$nationID = $me['nation'];
|
||||
|
||||
$db->update('nation', [
|
||||
'bill' => $amount
|
||||
], 'nation=%i', $nationID);
|
||||
|
||||
return [
|
||||
'result' => true
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
use sammo\WarUnit;
|
||||
|
||||
class che_명마_07_백상 extends \sammo\BaseStatItem{
|
||||
protected $cost = 200;
|
||||
protected $buyable = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->info .= "<br>[전투] 공격력 +20%, 소모 군량 +10%, 공격 시 페이즈 -1";
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
$value = parent::onCalcStat($general, $statName, $value, $aux);
|
||||
if($statName == 'killRice'){
|
||||
return $value * 1.1;
|
||||
}
|
||||
if($statName === 'initWarPhase'){
|
||||
return $value - 1;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit): array
|
||||
{
|
||||
return [1.2, 1];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
|
||||
class che_명마_07_오환마 extends \sammo\BaseStatItem{
|
||||
protected $cost = 200;
|
||||
protected $buyable = false;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
|
||||
class che_명마_08_흉노마 extends \sammo\BaseStatItem{
|
||||
protected $cost = 200;
|
||||
protected $buyable = false;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class che_명마_09_의남백마 extends \sammo\BaseStatItem{
|
||||
protected $cost = 200;
|
||||
protected $buyable = false;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class che_명마_10_옥추마 extends \sammo\BaseStatItem{
|
||||
protected $cost = 200;
|
||||
protected $buyable = false;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class che_명마_11_화종마 extends \sammo\BaseStatItem{
|
||||
protected $cost = 200;
|
||||
protected $buyable = false;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace sammo\ActionItem;
|
||||
use \sammo\iAction;
|
||||
use \sammo\General;
|
||||
|
||||
class che_명마_12_옥란백용구 extends \sammo\BaseStatItem{
|
||||
protected $cost = 200;
|
||||
protected $buyable = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->info .= "<br>[전투] 남은 병력에 따라 회피 확률 증가. 최대 +30%p";
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux = null)
|
||||
{
|
||||
$value = parent::onCalcStat($general, $statName, $value, $aux);
|
||||
if($statName == 'warAvoidRatio'){
|
||||
$leadership = $general->getLeadership(true, true, true, false);
|
||||
$crewL = $general->getVar('crew') / 100;
|
||||
|
||||
return $value + \sammo\Util::valueFit((1 - $crewL / $leadership) * 0.3, 0, 0.3);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ class che_무기_02_단궁 extends \sammo\BaseStatItem{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->info .= "<br>[전투] 새로운 상대와 전투 시 1% 확률로 저격 발동, 성공 시 사기+10";
|
||||
$this->info .= "<br>[전투] 새로운 상대와 전투 시 1% 확률로 저격 발동, 성공 시 사기+20";
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
|
||||
@@ -14,7 +14,7 @@ class che_무기_07_맥궁 extends \sammo\BaseStatItem{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->info .= "<br>[전투] 새로운 상대와 전투 시 20% 확률로 저격 발동, 성공 시 사기+10";
|
||||
$this->info .= "<br>[전투] 새로운 상대와 전투 시 20% 확률로 저격 발동, 성공 시 사기+20";
|
||||
}
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
|
||||
@@ -28,7 +28,7 @@ class che_치트_HideD의_사인검 extends \sammo\BaseItem
|
||||
통솔 +100,무력 +100, 지력 +100<br>
|
||||
[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>
|
||||
[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)<br>
|
||||
[전투] 새로운 상대와 전투 시 1/2 확률로 저격 발동, 성공 시 사기+10<br>
|
||||
[전투] 새로운 상대와 전투 시 1/2 확률로 저격 발동, 성공 시 사기+20<br>
|
||||
[전투] 훈련 보정 +30, 사기 보정 +30<br>
|
||||
[전투] 상대방 필살 및 회피 시도시 일정 확률로 격노(필살) 발동, 공격 시 일정 확률로 진노(1페이즈 추가)<br>
|
||||
[전투] 상대 필살, 격노, 위압, 저격 불가, 상대 계략 시도시 성공 확률 -10%p, 부상 없음, 아군 피해 -5%<br>
|
||||
|
||||
@@ -27,7 +27,7 @@ class event_전투특기_격노 extends \sammo\BaseItem{
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_격노시도($unit, che_격노시도::TYPE_ITEM),
|
||||
new che_격노발동($unit, che_격노발동::TYPE_ITEM)
|
||||
new che_격노발동($unit)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -200,8 +200,8 @@ class che_임관 extends Command\GeneralCommand
|
||||
|
||||
$rawNationList = Util::convertArrayToDict($db->query('SELECT nation,`name`,color,gennum,`power` FROM nation'), 'nation');
|
||||
$scoutMsgs = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'scout_msg');
|
||||
foreach ($scoutMsgs as $nationID => $scoutMsg) {
|
||||
$rawNationList[$nationID]['scoutmsg'] = $scoutMsg;
|
||||
foreach ($scoutMsgs as $destNationID => $scoutMsg) {
|
||||
$rawNationList[$destNationID]['scoutmsg'] = $scoutMsg;
|
||||
}
|
||||
foreach ($rawNationList as $destNation) {
|
||||
$testCommand = new static($generalObj, $this->env, ['destNationID' => $destNation['nation']]);
|
||||
@@ -216,7 +216,7 @@ class che_임관 extends Command\GeneralCommand
|
||||
if (!$testCommand->hasFullConditionMet()) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
if ($destNation['id'] == $nationID) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -150,6 +150,7 @@ class che_징병 extends Command\GeneralCommand
|
||||
$reqGold = $this->generalObj->onCalcDomestic('징병', 'cost', $reqGold, ['armType' => $this->reqCrewType->armType]);
|
||||
$reqGold *= static::$costOffset;
|
||||
$reqRice = $this->maxCrew / 100;
|
||||
$reqRice = $this->generalObj->onCalcDomestic('징병', 'rice', $reqRice, ['armType' => $this->reqCrewType->armType]);
|
||||
|
||||
$reqGold = Util::round($reqGold);
|
||||
$reqRice = Util::round($reqRice);
|
||||
|
||||
@@ -171,7 +171,7 @@ class che_급습 extends Command\NationCommand
|
||||
|
||||
$broadcastMessage = "아국에 <M>{$commandName}</>{$josaYiCommand} 발동되었습니다.";
|
||||
|
||||
$destNationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
$destNationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i', $destNationID);
|
||||
foreach ($destNationGeneralList as $destNationGeneralID) {
|
||||
$destNationGeneralLogger = new ActionLogger($destNationGeneralID, $destNationID, $year, $month);
|
||||
$destNationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
@@ -214,7 +214,7 @@ class che_급습 extends Command\NationCommand
|
||||
if (!$testCommand->hasFullConditionMet()) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
if ($destNation['id'] == $nationID) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ class che_불가침제의 extends Command\NationCommand
|
||||
if (!$testCommand->hasFullConditionMet()) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
if ($destNation['id'] == $nationID) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ class che_불가침파기제의 extends Command\NationCommand{
|
||||
if($diplomacyStatus[$destNation['nation']]['state'] != 7){
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
if ($destNation['id'] == $nationID) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ class che_선전포고 extends Command\NationCommand
|
||||
if (!$testCommand->hasFullConditionMet()) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
if ($destNation['id'] == $nationID) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ class che_이호경식 extends Command\NationCommand
|
||||
|
||||
$broadcastMessage = "아국에 <M>{$commandName}</>{$josaYiCommand} 발동되었습니다.";
|
||||
|
||||
$destNationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $destNationID, $generalID);
|
||||
$destNationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i', $destNationID);
|
||||
foreach ($destNationGeneralList as $destNationGeneralID) {
|
||||
$destNationGeneralLogger = new ActionLogger($destNationGeneralID, $destNationID, $year, $month);
|
||||
$destNationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
@@ -217,7 +217,7 @@ class che_이호경식 extends Command\NationCommand
|
||||
if (!$testCommand->hasFullConditionMet()) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
if ($destNation['id'] == $nationID) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ class che_종전제의 extends Command\NationCommand{
|
||||
if (!$testCommand->hasFullConditionMet()) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
if ($destNation['id'] == $nationID) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ class che_피장파장 extends Command\NationCommand
|
||||
|
||||
$broadcastMessage = "아국에 <G><b>{$cmd->getName()}</b></> 전략의 <M>{$commandName}</>{$josaYiCommand} 발동되었습니다.";
|
||||
|
||||
$destNationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $destNationID, $generalID);
|
||||
$destNationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i', $destNationID);
|
||||
foreach ($destNationGeneralList as $destNationGeneralID) {
|
||||
$destNationGeneralLogger = new ActionLogger($destNationGeneralID, $destNationID, $year, $month);
|
||||
$destNationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
@@ -255,7 +255,7 @@ class che_피장파장 extends Command\NationCommand
|
||||
if (!$testCommand->hasFullConditionMet()) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
if ($destNation['id'] == $nationID) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ class AllowJoinDestNation extends Constraint{
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->general['npc']??2 < 2 && \sammo\Util::starts_with($this->destNation['name'], 'ⓤ')){
|
||||
if(($this->general['npc']??2 < 2) && \str_starts_with($this->destNation['name'], 'ⓤ')){
|
||||
$this->reason = "유저장은 태수국에 임관할 수 없습니다.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class RaiseNPCNation extends \sammo\Event\Action
|
||||
}
|
||||
|
||||
const CITY_KEYS = ['pop', 'agri', 'comm', 'secu', 'def', 'wall'];
|
||||
const MIN_DIST_USERNATION = 4;
|
||||
const MIN_DIST_USERNATION = 3;
|
||||
const MIN_DIST_NPCNATION = 2;
|
||||
|
||||
private function calcAvgNationCity(array $cities)
|
||||
|
||||
+15
-13
@@ -221,29 +221,31 @@ class GameConstBase
|
||||
'che_명마_01_노기' => 0, 'che_명마_02_조랑' => 0, 'che_명마_03_노새' => 0,
|
||||
'che_명마_04_나귀' => 0, 'che_명마_05_갈색마' => 0, 'che_명마_06_흑색마' => 0,
|
||||
|
||||
'che_명마_07_백마' => 2, 'che_명마_07_기주마' => 2,
|
||||
'che_명마_08_양주마' => 2, 'che_명마_09_과하마' => 2,
|
||||
'che_명마_10_대완마' => 2, 'che_명마_11_서량마' => 2,
|
||||
'che_명마_12_사륜거' => 2, 'che_명마_13_절영' => 1, 'che_명마_13_적로' => 1,
|
||||
'che_명마_14_적란마' => 1, 'che_명마_14_조황비전' => 1, 'che_명마_15_한혈마' => 1, 'che_명마_15_적토마' => 1,
|
||||
'che_명마_07_백마' => 2, 'che_명마_07_기주마' => 2, 'che_명마_07_오환마' => 2, 'che_명마_07_백상' => 2,
|
||||
'che_명마_08_양주마' => 2, 'che_명마_08_흉노마' => 2, 'che_명마_09_과하마' => 2, 'che_명마_09_의남백마' => 2,
|
||||
'che_명마_10_대완마' => 2, 'che_명마_10_옥추마' => 2, 'che_명마_11_서량마' => 2, 'che_명마_11_화종마' => 2,
|
||||
'che_명마_12_사륜거' => 2, 'che_명마_12_옥란백용구'=> 2, 'che_명마_13_절영' => 2, 'che_명마_13_적로' => 2,
|
||||
'che_명마_14_적란마' => 2, 'che_명마_14_조황비전' => 2, 'che_명마_15_한혈마' => 2, 'che_명마_15_적토마' => 2,
|
||||
],
|
||||
'weapon' => [
|
||||
'che_무기_01_단도' => 0, 'che_무기_02_단궁' => 0, 'che_무기_03_단극' => 0,
|
||||
'che_무기_04_목검' => 0, 'che_무기_05_죽창' => 0, 'che_무기_06_소부' => 0,
|
||||
|
||||
'che_무기_07_동추' => 1, 'che_무기_07_철편' => 1, 'che_무기_07_철쇄' => 1, 'che_무기_07_맥궁' => 1,
|
||||
'che_무기_08_유성추' => 1, 'che_무기_08_철질여골' => 1, 'che_무기_09_쌍철극' => 1, 'che_무기_09_동호비궁' => 1, 'che_무기_10_삼첨도' => 1, 'che_무기_10_대부' => 1, 'che_무기_11_고정도' => 1, 'che_무기_11_이광궁' => 1, 'che_무기_12_철척사모' => 1, 'che_무기_12_칠성검' => 1, 'che_무기_13_사모' => 1, 'che_무기_13_양유기궁' => 1,
|
||||
'che_무기_14_언월도' => 1, 'che_무기_14_방천화극' => 1, 'che_무기_15_청홍검' => 1, 'che_무기_15_의천검' => 1
|
||||
'che_무기_07_동추' => 2, 'che_무기_07_철편' => 2, 'che_무기_07_철쇄' => 2, 'che_무기_07_맥궁' => 2,
|
||||
'che_무기_08_유성추' => 2, 'che_무기_08_철질여골' => 2, 'che_무기_09_쌍철극' => 2, 'che_무기_09_동호비궁' => 2,
|
||||
'che_무기_10_삼첨도' => 2, 'che_무기_10_대부' => 2, 'che_무기_11_고정도' => 2, 'che_무기_11_이광궁' => 2,
|
||||
'che_무기_12_철척사모' => 2, 'che_무기_12_칠성검' => 2, 'che_무기_13_사모' => 2, 'che_무기_13_양유기궁' => 2,
|
||||
'che_무기_14_언월도' => 2, 'che_무기_14_방천화극' => 2, 'che_무기_15_청홍검' => 2, 'che_무기_15_의천검' => 2
|
||||
],
|
||||
'book' => [
|
||||
'che_서적_01_효경전' => 0, 'che_서적_02_회남자' => 0, 'che_서적_03_변도론' => 0,
|
||||
'che_서적_04_건상역주' => 0, 'che_서적_05_여씨춘추' => 0, 'che_서적_06_사민월령' => 0,
|
||||
|
||||
'che_서적_07_위료자' => 1, 'che_서적_07_사마법' => 1, 'che_서적_07_한서' => 1, 'che_서적_07_논어' => 1,
|
||||
'che_서적_08_전론' => 1, 'che_서적_08_사기' => 1, 'che_서적_09_장자' => 1, 'che_서적_09_역경' => 1,
|
||||
'che_서적_10_시경' => 1, 'che_서적_10_구국론' => 1, 'che_서적_11_상군서' => 1, 'che_서적_11_춘추전' => 1,
|
||||
'che_서적_12_산해경' => 1, 'che_서적_12_맹덕신서' => 1, 'che_서적_13_관자' => 1, 'che_서적_13_병법24편' => 1,
|
||||
'che_서적_14_한비자' => 1, 'che_서적_14_오자병법' => 1, 'che_서적_15_노자' => 1, 'che_서적_15_손자병법' => 1,
|
||||
'che_서적_07_위료자' => 2, 'che_서적_07_사마법' => 2, 'che_서적_07_한서' => 2, 'che_서적_07_논어' => 2,
|
||||
'che_서적_08_전론' => 2, 'che_서적_08_사기' => 2, 'che_서적_09_장자' => 2, 'che_서적_09_역경' => 2,
|
||||
'che_서적_10_시경' => 2, 'che_서적_10_구국론' => 2, 'che_서적_11_상군서' => 2, 'che_서적_11_춘추전' => 2,
|
||||
'che_서적_12_산해경' => 2, 'che_서적_12_맹덕신서' => 2, 'che_서적_13_관자' => 2, 'che_서적_13_병법24편' => 2,
|
||||
'che_서적_14_한비자' => 2, 'che_서적_14_오자병법' => 2, 'che_서적_15_노자' => 2, 'che_서적_15_손자병법' => 2,
|
||||
],
|
||||
'item' => [
|
||||
'che_치료_환약' => 0, 'che_저격_수극' => 0, 'che_사기_탁주' => 0,
|
||||
|
||||
@@ -161,7 +161,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['표준적인 기병입니다.','기병은 공격특화입니다.'],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
1301, self::T_CAVALRY, '백마병',
|
||||
@@ -170,7 +170,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['백마의 위용을 보여줍니다.'],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
1302, self::T_CAVALRY, '중장기병',
|
||||
@@ -179,7 +179,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['갑주를 두른 기병입니다.'],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
1303, self::T_CAVALRY, '돌격기병',
|
||||
@@ -188,7 +188,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['저돌적으로 공격합니다.'],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
1304, self::T_CAVALRY, '철기병',
|
||||
@@ -197,7 +197,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['철갑을 두른 기병입니다.'],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
1305, self::T_CAVALRY, '수렵기병',
|
||||
@@ -206,7 +206,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['날쎄고 빠른 기병입니다.'],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
1306, self::T_CAVALRY, '맹수병',
|
||||
@@ -215,7 +215,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['어느 누구보다 강력합니다.'],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
1307, self::T_CAVALRY, '호표기병',
|
||||
@@ -224,7 +224,7 @@ class GameUnitConstBase{
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['정예 기병입니다.'],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
|
||||
[
|
||||
|
||||
@@ -286,6 +286,7 @@ class WarUnitGeneral extends WarUnit
|
||||
|
||||
$rice *= $this->crewType->rice;
|
||||
$rice *= getTechCost($this->getNationVar('tech'));
|
||||
$rice = $this->general->onCalcStat($this->general, 'killRice', $rice);
|
||||
|
||||
$general->increaseVarWithLimit('rice', -$rice, 0);
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
namespace sammo\WarUnitTrigger;
|
||||
use sammo\BaseWarUnitTrigger;
|
||||
use sammo\WarUnitGeneral;
|
||||
use sammo\WarUnitCity;
|
||||
use sammo\WarUnit;
|
||||
use sammo\GameUnitDetail;
|
||||
use sammo\Util;
|
||||
use sammo\ObjectTrigger;
|
||||
|
||||
class che_기병병종전투 extends BaseWarUnitTrigger{
|
||||
protected $priority = ObjectTrigger::PRIORITY_FINAL; //최후미
|
||||
|
||||
protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool{
|
||||
if(!$self->isAttacker()){
|
||||
$oppose->multiplyWarPowerMultiply(1/0.95);
|
||||
$self->multiplyWarPowerMultiply(0.95);
|
||||
}
|
||||
if($oppose instanceof WarUnitCity){
|
||||
$self->multiplyWarPowerMultiply(0.9);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -26,19 +26,26 @@
|
||||
"che_명마_05_갈색마": 0,
|
||||
"che_명마_06_흑색마": 0,
|
||||
|
||||
"che_명마_07_백마": 2,
|
||||
"che_명마_07_기주마": 2,
|
||||
"che_명마_08_양주마": 2,
|
||||
"che_명마_09_과하마": 2,
|
||||
"che_명마_10_대완마": 2,
|
||||
"che_명마_11_서량마": 2,
|
||||
"che_명마_12_사륜거": 2,
|
||||
"che_명마_13_절영": 1,
|
||||
"che_명마_13_적로": 1,
|
||||
"che_명마_14_적란마": 1,
|
||||
"che_명마_14_조황비전": 1,
|
||||
"che_명마_15_한혈마": 1,
|
||||
"che_명마_15_적토마": 1
|
||||
"che_명마_07_백마" : 2,
|
||||
"che_명마_07_기주마" : 2,
|
||||
"che_명마_07_오환마" : 2,
|
||||
"che_명마_07_백상" : 2,
|
||||
"che_명마_08_양주마" : 2,
|
||||
"che_명마_08_흉노마" : 2,
|
||||
"che_명마_09_과하마" : 2,
|
||||
"che_명마_09_의남백마" : 2,
|
||||
"che_명마_10_대완마" : 2,
|
||||
"che_명마_10_옥추마" : 2,
|
||||
"che_명마_11_서량마" : 2,
|
||||
"che_명마_11_화종마" : 2,
|
||||
"che_명마_12_사륜거" : 2,
|
||||
"che_명마_12_옥란백용구": 2,
|
||||
"che_명마_13_절영" : 2,
|
||||
"che_명마_13_적로" : 2,
|
||||
"che_명마_14_적란마" : 2,
|
||||
"che_명마_14_조황비전" : 2,
|
||||
"che_명마_15_한혈마" : 2,
|
||||
"che_명마_15_적토마" : 2
|
||||
},
|
||||
"weapon": {
|
||||
"che_무기_01_단도": 0,
|
||||
@@ -48,26 +55,26 @@
|
||||
"che_무기_05_죽창": 0,
|
||||
"che_무기_06_소부": 0,
|
||||
|
||||
"che_무기_07_동추": 1,
|
||||
"che_무기_07_철편": 1,
|
||||
"che_무기_07_철쇄": 1,
|
||||
"che_무기_07_맥궁": 1,
|
||||
"che_무기_08_유성추": 1,
|
||||
"che_무기_08_철질여골": 1,
|
||||
"che_무기_09_쌍철극": 1,
|
||||
"che_무기_09_동호비궁": 1,
|
||||
"che_무기_10_삼첨도": 1,
|
||||
"che_무기_10_대부": 1,
|
||||
"che_무기_11_고정도": 1,
|
||||
"che_무기_11_이광궁": 1,
|
||||
"che_무기_12_철척사모": 1,
|
||||
"che_무기_12_칠성검": 1,
|
||||
"che_무기_13_사모": 1,
|
||||
"che_무기_13_양유기궁": 1,
|
||||
"che_무기_14_언월도": 1,
|
||||
"che_무기_14_방천화극": 1,
|
||||
"che_무기_15_청홍검": 1,
|
||||
"che_무기_15_의천검": 1
|
||||
"che_무기_07_동추": 2,
|
||||
"che_무기_07_철편": 2,
|
||||
"che_무기_07_철쇄": 2,
|
||||
"che_무기_07_맥궁": 2,
|
||||
"che_무기_08_유성추": 2,
|
||||
"che_무기_08_철질여골": 2,
|
||||
"che_무기_09_쌍철극": 2,
|
||||
"che_무기_09_동호비궁": 2,
|
||||
"che_무기_10_삼첨도": 2,
|
||||
"che_무기_10_대부": 2,
|
||||
"che_무기_11_고정도": 2,
|
||||
"che_무기_11_이광궁": 2,
|
||||
"che_무기_12_철척사모": 2,
|
||||
"che_무기_12_칠성검": 2,
|
||||
"che_무기_13_사모": 2,
|
||||
"che_무기_13_양유기궁": 2,
|
||||
"che_무기_14_언월도": 2,
|
||||
"che_무기_14_방천화극": 2,
|
||||
"che_무기_15_청홍검": 2,
|
||||
"che_무기_15_의천검": 2
|
||||
},
|
||||
"book": {
|
||||
"che_서적_01_효경전": 0,
|
||||
@@ -77,26 +84,26 @@
|
||||
"che_서적_05_여씨춘추": 0,
|
||||
"che_서적_06_사민월령": 0,
|
||||
|
||||
"che_서적_07_위료자": 1,
|
||||
"che_서적_07_사마법": 1,
|
||||
"che_서적_07_한서": 1,
|
||||
"che_서적_07_논어": 1,
|
||||
"che_서적_08_전론": 1,
|
||||
"che_서적_08_사기": 1,
|
||||
"che_서적_09_장자": 1,
|
||||
"che_서적_09_역경": 1,
|
||||
"che_서적_10_시경": 1,
|
||||
"che_서적_10_구국론": 1,
|
||||
"che_서적_11_상군서": 1,
|
||||
"che_서적_11_춘추전": 1,
|
||||
"che_서적_12_산해경": 1,
|
||||
"che_서적_12_맹덕신서": 1,
|
||||
"che_서적_13_관자": 1,
|
||||
"che_서적_13_병법24편": 1,
|
||||
"che_서적_14_한비자": 1,
|
||||
"che_서적_14_오자병법": 1,
|
||||
"che_서적_15_노자": 1,
|
||||
"che_서적_15_손자병법": 1
|
||||
"che_서적_07_위료자": 2,
|
||||
"che_서적_07_사마법": 2,
|
||||
"che_서적_07_한서": 2,
|
||||
"che_서적_07_논어": 2,
|
||||
"che_서적_08_전론": 2,
|
||||
"che_서적_08_사기": 2,
|
||||
"che_서적_09_장자": 2,
|
||||
"che_서적_09_역경": 2,
|
||||
"che_서적_10_시경": 2,
|
||||
"che_서적_10_구국론": 2,
|
||||
"che_서적_11_상군서": 2,
|
||||
"che_서적_11_춘추전": 2,
|
||||
"che_서적_12_산해경": 2,
|
||||
"che_서적_12_맹덕신서": 2,
|
||||
"che_서적_13_관자": 2,
|
||||
"che_서적_13_병법24편": 2,
|
||||
"che_서적_14_한비자": 2,
|
||||
"che_서적_14_오자병법": 2,
|
||||
"che_서적_15_노자": 2,
|
||||
"che_서적_15_손자병법": 2
|
||||
},
|
||||
"item": {
|
||||
"che_치료_환약": 0,
|
||||
@@ -129,7 +136,7 @@
|
||||
}
|
||||
},
|
||||
"iconPath": ".",
|
||||
"fiction": 1,
|
||||
"fiction": 2,
|
||||
"nation": [],
|
||||
"diplomacy": [],
|
||||
"general": [
|
||||
@@ -281,7 +288,7 @@
|
||||
[0, "오반", null, 0, null, 74, 71, 50, 0, 160, 300, null, null],
|
||||
[0, "고옹", null, 0, null, 52, 18, 81, 0, 160, 300, null, null],
|
||||
[0, "오란", null, 0, null, 68, 80, 35, 0, 160, 300, null, null],
|
||||
[0, "채화", null, 0, null, 39, 50, 1, 0, 160, 300, null, null],
|
||||
[0, "채화", null, 0, null, 39, 50, 2, 0, 160, 300, null, null],
|
||||
[0, "채중", null, 0, null, 40, 54, 2, 0, 160, 300, null, null],
|
||||
[0, "채모", null, 0, null, 70, 55, 77, 0, 160, 300, null, null],
|
||||
[0, "착융", null, 0, null, 60, 69, 38, 0, 160, 300, null, null],
|
||||
@@ -694,7 +701,7 @@
|
||||
[0, "성만", null, 0, null, 61, 68, 46, 0, 160, 300, null, null],
|
||||
[0, "오연", null, 0, null, 66, 73, 42, 0, 160, 300, null, null],
|
||||
[0, "맹충", null, 0, null, 47, 28, 72, 0, 160, 300, null, null],
|
||||
[0, "잠혼", null, 0, null, 1, 1, 22, 0, 160, 300, null, null],
|
||||
[0, "잠혼", null, 0, null, 2, 2, 22, 0, 160, 300, null, null],
|
||||
[0, "사정", null, 0, null, 64, 76, 34, 0, 160, 300, null, null],
|
||||
[0, "심영", null, 0, null, 70, 77, 55, 0, 160, 300, null, null],
|
||||
[0, "도준", null, 0, null, 65, 66, 46, 0, 160, 300, null, null],
|
||||
|
||||
@@ -19,31 +19,31 @@
|
||||
"che_명마_01_노기":0, "che_명마_02_조랑":0, "che_명마_03_노새":0,
|
||||
"che_명마_04_나귀":0, "che_명마_05_갈색마":0, "che_명마_06_흑색마":0,
|
||||
|
||||
"che_명마_07_백마":2, "che_명마_07_기주마":2,
|
||||
"che_명마_08_양주마":2, "che_명마_09_과하마":2,
|
||||
"che_명마_10_대완마":2, "che_명마_11_서량마":2,
|
||||
"che_명마_12_사륜거":2, "che_명마_13_절영":1, "che_명마_13_적로":1,
|
||||
"che_명마_14_적란마":1, "che_명마_14_조황비전":1, "che_명마_15_한혈마":1, "che_명마_15_적토마":1
|
||||
"che_명마_07_백마" : 2, "che_명마_07_기주마" : 2, "che_명마_07_오환마" : 2, "che_명마_07_백상" : 2,
|
||||
"che_명마_08_양주마" : 2, "che_명마_08_흉노마" : 2, "che_명마_09_과하마" : 2, "che_명마_09_의남백마" : 2,
|
||||
"che_명마_10_대완마" : 2, "che_명마_10_옥추마" : 2, "che_명마_11_서량마" : 2, "che_명마_11_화종마" : 2,
|
||||
"che_명마_12_사륜거" : 2, "che_명마_12_옥란백용구": 2, "che_명마_13_절영" : 2, "che_명마_13_적로" : 2,
|
||||
"che_명마_14_적란마" : 2, "che_명마_14_조황비전" : 2, "che_명마_15_한혈마" : 2, "che_명마_15_적토마" : 2
|
||||
},
|
||||
"weapon":{
|
||||
"che_무기_01_단도":0, "che_무기_02_단궁":0, "che_무기_03_단극":0,
|
||||
"che_무기_04_목검":0, "che_무기_05_죽창":0, "che_무기_06_소부":0,
|
||||
|
||||
"che_무기_07_동추":1, "che_무기_07_철편":1, "che_무기_07_철쇄":1, "che_무기_07_맥궁":1,
|
||||
"che_무기_08_유성추":1, "che_무기_08_철질여골":1, "che_무기_09_쌍철극":1, "che_무기_09_동호비궁":1,
|
||||
"che_무기_10_삼첨도":1, "che_무기_10_대부":1, "che_무기_11_고정도":1, "che_무기_11_이광궁":1,
|
||||
"che_무기_12_철척사모":1, "che_무기_12_칠성검":1, "che_무기_13_사모":1, "che_무기_13_양유기궁":1,
|
||||
"che_무기_14_언월도":1, "che_무기_14_방천화극":1, "che_무기_15_청홍검":1, "che_무기_15_의천검":1
|
||||
"che_무기_07_동추":2, "che_무기_07_철편":2, "che_무기_07_철쇄":2, "che_무기_07_맥궁":2,
|
||||
"che_무기_08_유성추":2, "che_무기_08_철질여골":2, "che_무기_09_쌍철극":2, "che_무기_09_동호비궁":2,
|
||||
"che_무기_10_삼첨도":2, "che_무기_10_대부":2, "che_무기_11_고정도":2, "che_무기_11_이광궁":2,
|
||||
"che_무기_12_철척사모":2, "che_무기_12_칠성검":2, "che_무기_13_사모":2, "che_무기_13_양유기궁":2,
|
||||
"che_무기_14_언월도":2, "che_무기_14_방천화극":2, "che_무기_15_청홍검":2, "che_무기_15_의천검":2
|
||||
},
|
||||
"book":{
|
||||
"che_서적_01_효경전":0, "che_서적_02_회남자":0, "che_서적_03_변도론":0,
|
||||
"che_서적_04_건상역주":0, "che_서적_05_여씨춘추":0, "che_서적_06_사민월령":0,
|
||||
|
||||
"che_서적_07_위료자":1, "che_서적_07_사마법":1, "che_서적_07_한서":1, "che_서적_07_논어":1,
|
||||
"che_서적_08_전론":1, "che_서적_08_사기":1, "che_서적_09_장자":1, "che_서적_09_역경":1,
|
||||
"che_서적_10_시경":1, "che_서적_10_구국론":1, "che_서적_11_상군서":1, "che_서적_11_춘추전":1,
|
||||
"che_서적_12_산해경":1, "che_서적_12_맹덕신서":1, "che_서적_13_관자":1, "che_서적_13_병법24편":1,
|
||||
"che_서적_14_한비자":1, "che_서적_14_오자병법":1, "che_서적_15_노자":1, "che_서적_15_손자병법":1
|
||||
"che_서적_07_위료자":2, "che_서적_07_사마법":2, "che_서적_07_한서":2, "che_서적_07_논어":2,
|
||||
"che_서적_08_전론":2, "che_서적_08_사기":2, "che_서적_09_장자":2, "che_서적_09_역경":2,
|
||||
"che_서적_10_시경":2, "che_서적_10_구국론":2, "che_서적_11_상군서":2, "che_서적_11_춘추전":2,
|
||||
"che_서적_12_산해경":2, "che_서적_12_맹덕신서":2, "che_서적_13_관자":2, "che_서적_13_병법24편":2,
|
||||
"che_서적_14_한비자":2, "che_서적_14_오자병법":2, "che_서적_15_노자":2, "che_서적_15_손자병법":2
|
||||
},
|
||||
"item":{
|
||||
"che_치료_환약":0, "che_저격_수극":0, "che_사기_탁주":0,
|
||||
|
||||
+295
-295
@@ -16,420 +16,420 @@ class GameUnitConst extends GameUnitConstBase
|
||||
protected static $_buildData = [
|
||||
[
|
||||
1000, self::T_CASTLE, '성벽',
|
||||
100, 100, 7, 0, 0, 99, 9,
|
||||
999999, null, null, 999999,
|
||||
100, 100, 7, 0, 0, 99, 9,
|
||||
999999, null, null, 999999,
|
||||
[],//성벽은 공격할 수 없다.
|
||||
[self::T_FOOTMAN=>1.2],
|
||||
['성벽입니다.','생성할 수 없습니다.'],
|
||||
null, null
|
||||
],
|
||||
|
||||
[
|
||||
217100, self::T_FOOTMAN, '보병',
|
||||
100, 150, 7, 10, 0, 9, 9,
|
||||
0, null, null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
|
||||
[
|
||||
217100, self::T_FOOTMAN, '보병',
|
||||
100, 150, 7, 10, 0, 9, 9,
|
||||
0, null, null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["표준적인 보병입니다. 보병은 방어특화입니다."],
|
||||
null, null
|
||||
null, ['che_방어력증가5p']
|
||||
],
|
||||
[
|
||||
217101, self::T_FOOTMAN, '마물병',
|
||||
110, 160, 7, 10, 0, 9, 10,
|
||||
0, null, ["호넷 마인령","케이브리스 마인령"], 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217101, self::T_FOOTMAN, '마물병',
|
||||
110, 160, 7, 10, 0, 9, 10,
|
||||
0, null, ["호넷 마인령","케이브리스 마인령"], 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["마군 지역 기본병종입니다. 조금더 강하지만 쌀을 많이 소비합니다."],
|
||||
null, null
|
||||
null, ['che_방어력증가5p']
|
||||
],
|
||||
[
|
||||
217102, self::T_FOOTMAN, '중장보병',
|
||||
100, 250, 7, 5, 0, 13, 10,
|
||||
1000, null, ["헬만 동부"], 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217102, self::T_FOOTMAN, '중장보병',
|
||||
100, 250, 7, 5, 0, 13, 10,
|
||||
1000, null, ["헬만 동부"], 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["헬만 특유의 견고한 보병입니다."],
|
||||
null, null
|
||||
null, ['che_방어력증가5p']
|
||||
],
|
||||
[
|
||||
217103, self::T_FOOTMAN, '흑의 군 보병',
|
||||
150, 150, 7, 10, 0, 12, 11,
|
||||
1000, null, ["리자스 남부","리자스 북부"], 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217103, self::T_FOOTMAN, '흑의 군 보병',
|
||||
150, 150, 7, 10, 0, 12, 11,
|
||||
1000, null, ["리자스 남부","리자스 북부"], 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["흑의 군 전통의 체계적인 훈련으로 공격력을 보완했습니다."],
|
||||
null, null
|
||||
null, ['che_방어력증가5p']
|
||||
],
|
||||
[
|
||||
217104, self::T_FOOTMAN, '용병',
|
||||
125, 175, 7, 10, 0, 12, 11,
|
||||
1000, null, ["자유도시 동부"], 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217104, self::T_FOOTMAN, '용병',
|
||||
125, 175, 7, 10, 0, 12, 11,
|
||||
1000, null, ["자유도시 동부"], 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["일반 보병보다 비싸지만 받은 만큼은 일해줍니다."],
|
||||
null, null
|
||||
null, ['che_방어력증가5p']
|
||||
],
|
||||
[
|
||||
217105, self::T_FOOTMAN, '사메라이',
|
||||
175, 150, 7, 0, 0, 11, 10,
|
||||
1000, null, ["제스 남부"], 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217105, self::T_FOOTMAN, '사메라이',
|
||||
175, 150, 7, 0, 0, 11, 10,
|
||||
1000, null, ["제스 남부"], 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["검으로 난무를 가하는 몬스터 보병입니다."],
|
||||
null, null
|
||||
null, ['che_방어력증가5p']
|
||||
],
|
||||
[
|
||||
217106, self::T_FOOTMAN, '템플나이트병',
|
||||
75, 275, 7, 0, 0, 11, 12,
|
||||
1000, null, ["AL교"], 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217106, self::T_FOOTMAN, '템플나이트병',
|
||||
75, 275, 7, 0, 0, 11, 12,
|
||||
1000, null, ["AL교"], 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["공격을 포기하고 오직 방어에만 집중합니다."],
|
||||
null, null
|
||||
null, ['che_방어력증가5p']
|
||||
],
|
||||
[
|
||||
217107, self::T_FOOTMAN, '메이드병',
|
||||
150, 150, 7, 20, 0, 13, 11,
|
||||
2000, ["메이드의 묘지"], null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217107, self::T_FOOTMAN, '메이드병',
|
||||
150, 150, 7, 20, 0, 13, 11,
|
||||
2000, ["메이드의 묘지"], null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["켓셀링크 휘하의 날렵한 전투메이드입니다."],
|
||||
null, null
|
||||
null, ['che_방어력증가5p']
|
||||
],
|
||||
[
|
||||
217108, self::T_FOOTMAN, '요괴병',
|
||||
150, 150, 8, 0, 0, 11, 13,
|
||||
2000, ["오슈"], null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217108, self::T_FOOTMAN, '요괴병',
|
||||
150, 150, 8, 0, 0, 11, 13,
|
||||
2000, ["오슈"], null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["단단한 육체를 믿고 적진을 돌파합니다."],
|
||||
null, null
|
||||
null, ['che_방어력증가5p']
|
||||
],
|
||||
[
|
||||
217109, self::T_FOOTMAN, '리자스 친위병',
|
||||
150, 200, 7, 10, 0, 12, 12,
|
||||
3000, ["리자스성"], null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217109, self::T_FOOTMAN, '리자스 친위병',
|
||||
150, 200, 7, 10, 0, 12, 12,
|
||||
3000, ["리자스성"], null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["여왕을 수호하는 리자스 최강의 보병 정예보병입니다."],
|
||||
null, null
|
||||
null, ['che_방어력증가5p']
|
||||
],
|
||||
[
|
||||
217110, self::T_FOOTMAN, '케이브리스 마물병',
|
||||
200, 150, 7, 5, 0, 13, 14,
|
||||
3000, ["케이브리스의 성"], null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217110, self::T_FOOTMAN, '케이브리스 마물병',
|
||||
200, 150, 7, 5, 0, 13, 14,
|
||||
3000, ["케이브리스의 성"], null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["케이브리스 직속의 마물 정예 전투보병입니다."],
|
||||
null, null
|
||||
null, ['che_방어력증가5p']
|
||||
],
|
||||
[
|
||||
217111, self::T_FOOTMAN, '투신',
|
||||
200, 300, 7, 5, 0, 28, 23,
|
||||
5000, ["투신도시"], null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217111, self::T_FOOTMAN, '투신',
|
||||
200, 300, 7, 5, 0, 28, 23,
|
||||
5000, ["투신도시"], null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["성마교단 유적에서 발굴된 사상 최강의 보병입니다."],
|
||||
null, null
|
||||
null, ['che_방어력증가5p']
|
||||
],
|
||||
|
||||
[
|
||||
217200, self::T_ARCHER, '궁병',
|
||||
100, 100, 7, 20, 0, 10, 10,
|
||||
0, null, null, 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217200, self::T_ARCHER, '궁병',
|
||||
100, 100, 7, 20, 0, 10, 10,
|
||||
0, null, null, 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["표준적인 궁병입니다. 궁병은 회피특화입니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217201, self::T_ARCHER, '투척마물병',
|
||||
150, 100, 7, 10, 0, 11, 12,
|
||||
1000, null, ["호넷 마인령"], 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217201, self::T_ARCHER, '투척마물병',
|
||||
150, 100, 7, 10, 0, 11, 12,
|
||||
1000, null, ["호넷 마인령"], 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["날렵함을 포기하고 도끼를 투척합니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217202, self::T_ARCHER, '백의 군 궁병',
|
||||
100, 100, 8, 30, 0, 11, 11,
|
||||
1000, null, ["리자스 남부"], 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217202, self::T_ARCHER, '백의 군 궁병',
|
||||
100, 100, 8, 30, 0, 11, 11,
|
||||
1000, null, ["리자스 남부"], 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["전략을 활용하여 치고 빠지기에 능합니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217203, self::T_ARCHER, '벌레술사병',
|
||||
100, 150, 7, 20, 0, 12, 12,
|
||||
2000, ["호박성"], null, 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217203, self::T_ARCHER, '벌레술사병',
|
||||
100, 150, 7, 20, 0, 12, 12,
|
||||
2000, ["호박성"], null, 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["벌레들을 부려 몸을 보호하는 궁병입니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217204, self::T_ARCHER, '저격암살병',
|
||||
225, 75, 5, 10, 0, 14, 11,
|
||||
2000, ["블라디보스토크"], null, 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217204, self::T_ARCHER, '저격암살병',
|
||||
225, 75, 5, 10, 0, 14, 11,
|
||||
2000, ["블라디보스토크"], null, 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["독을 바른 탄환으로 적의 목숨을 앗아갑니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217205, self::T_ARCHER, '호루스병',
|
||||
150, 100, 8, 20, 0, 11, 12,
|
||||
2000, ["거대전함"], null, 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217205, self::T_ARCHER, '호루스병',
|
||||
150, 100, 8, 20, 0, 11, 12,
|
||||
2000, ["거대전함"], null, 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["민첩하게 파고드는 호루스족 궁병입니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217206, self::T_ARCHER, '튤립병',
|
||||
200, 100, 7, 20, 0, 13, 13,
|
||||
3000, ["커스텀"], null, 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217206, self::T_ARCHER, '튤립병',
|
||||
200, 100, 7, 20, 0, 13, 13,
|
||||
3000, ["커스텀"], null, 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["최첨단병기 튤립으로 적을 폭격합니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217207, self::T_ARCHER, '아이스플레임 궁병',
|
||||
150, 150, 7, 20, 0, 13, 13,
|
||||
3000, ["라그나로크 아크"], null, 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217207, self::T_ARCHER, '아이스플레임 궁병',
|
||||
150, 150, 7, 20, 0, 13, 13,
|
||||
3000, ["라그나로크 아크"], null, 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["혁명을 성공으로 이끈 정예 게릴라 궁병입니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217208, self::T_ARCHER, '카라 궁병',
|
||||
225, 225, 7, 30, 0, 25, 25,
|
||||
5000, ["펜실 카우"], null, 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217208, self::T_ARCHER, '카라 궁병',
|
||||
225, 225, 7, 30, 0, 25, 25,
|
||||
5000, ["펜실 카우"], null, 0,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["선조의 힘을 이어받은 최강의 카라 정예 궁병입니다."],
|
||||
null, null
|
||||
],
|
||||
|
||||
[
|
||||
217300, self::T_CAVALRY, '기동병',
|
||||
150, 100, 7, 5, 0, 11, 11,
|
||||
0, null, null, 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217300, self::T_CAVALRY, '기동병',
|
||||
150, 100, 7, 5, 0, 11, 11,
|
||||
0, null, null, 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["표준적인 기동병입니다. 기동병은 공격특화입니다."],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
217301, self::T_CAVALRY, '하치온나',
|
||||
175, 100, 7, 15, 0, 12, 12,
|
||||
1000, null, ["자유도시 서부"], 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217301, self::T_CAVALRY, '하치온나',
|
||||
175, 100, 7, 15, 0, 12, 12,
|
||||
1000, null, ["자유도시 서부"], 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["작은 몸으로 회피하며 따끔한 일격을 먹이는 몬스터 기동병입니다."],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
217302, self::T_CAVALRY, '적의 군 기동병',
|
||||
200, 100, 7, 5, 0, 12, 13,
|
||||
1000, null, ["리자스 북부"], 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217302, self::T_CAVALRY, '적의 군 기동병',
|
||||
200, 100, 7, 5, 0, 12, 13,
|
||||
1000, null, ["리자스 북부"], 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["리자스군의 자랑인 기동부대입니다."],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
217303, self::T_CAVALRY, '안드로이드 기동병',
|
||||
175, 150, 7, 10, 0, 13, 12,
|
||||
2000, ["악의 탑"], null, 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217303, self::T_CAVALRY, '안드로이드 기동병',
|
||||
175, 150, 7, 10, 0, 13, 12,
|
||||
2000, ["악의 탑"], null, 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["파이아르가 개발한 최첨단 안드로이드 기동병입니다."],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
217304, self::T_CAVALRY, '파란쵸 기동병',
|
||||
200, 100, 8, 5, 0, 13, 11,
|
||||
2000, ["파란쵸 왕국"], null, 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217304, self::T_CAVALRY, '파란쵸 기동병',
|
||||
200, 100, 8, 5, 0, 13, 11,
|
||||
2000, ["파란쵸 왕국"], null, 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["적진을 일점돌파하는 파란쵸왕국의 돌격 기동병입니다. "],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
217305, self::T_CAVALRY, '비행마물병',
|
||||
150, 100, 8, 15, 0, 12, 12,
|
||||
2000, ["죽음의 대지"], null, 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217305, self::T_CAVALRY, '비행마물병',
|
||||
150, 100, 8, 15, 0, 12, 12,
|
||||
2000, ["죽음의 대지"], null, 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["비행마물에 올라탄 기동마물병입니다."],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
217306, self::T_CAVALRY, '마물조련사병',
|
||||
250, 200, 6, 0, 0, 16, 16,
|
||||
3000, ["랑그바우"], null, 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217306, self::T_CAVALRY, '마물조련사병',
|
||||
250, 200, 6, 0, 0, 16, 16,
|
||||
3000, ["랑그바우"], null, 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["무시무시한 몬스터에 올라타서 싸우는 극강의 기동병입니다."],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
217307, self::T_CAVALRY, '기마병',
|
||||
200, 150, 7, 5, 0, 14, 14,
|
||||
3000, ["오와리"], null, 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217307, self::T_CAVALRY, '기마병',
|
||||
200, 150, 7, 5, 0, 14, 14,
|
||||
3000, ["오와리"], null, 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["JAPAN 특유의 기마에 올라타 적을 짓밟는 기동병입니다."],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
[
|
||||
217308, self::T_CAVALRY, '엔젤나이트',
|
||||
300, 200, 7, 5, 0, 25, 25,
|
||||
5000, ["떨어진 궁도"], null, 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
[
|
||||
217308, self::T_CAVALRY, '엔젤나이트',
|
||||
300, 200, 7, 5, 0, 25, 25,
|
||||
5000, ["떨어진 궁도"], null, 0,
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2, 217502=>1],
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8, 217502=>1],
|
||||
["신의 명령으로 파멸을 내리기 위해 강림했습니다."],
|
||||
null, null
|
||||
null, ['che_기병병종전투']
|
||||
],
|
||||
|
||||
[
|
||||
217400, self::T_WIZARD, '마법병',
|
||||
80, 80, 7, 5, 0.6, 9, 9,
|
||||
0, null, null, 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
[
|
||||
217400, self::T_WIZARD, '마법병',
|
||||
80, 80, 7, 5, 0.6, 9, 9,
|
||||
0, null, null, 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
["마법을 사용하는 병종입니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217401, self::T_WIZARD, '마물 마법병',
|
||||
90, 90, 7, 0, 0.6, 11, 9,
|
||||
0, null, ["호넷 마인령","케이브리스 마인령"], 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
[
|
||||
217401, self::T_WIZARD, '마물 마법병',
|
||||
90, 90, 7, 0, 0.6, 11, 9,
|
||||
0, null, ["호넷 마인령","케이브리스 마인령"], 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
["마군 지역 기본병종입니다. 조금더 강하지만 금을 많이 소비합니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217402, self::T_WIZARD, '카라 마법병',
|
||||
80, 80, 7, 20, 0.6, 10, 10,
|
||||
1000, null, ["카라의 숲"], 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
[
|
||||
217402, self::T_WIZARD, '카라 마법병',
|
||||
80, 80, 7, 20, 0.6, 10, 10,
|
||||
1000, null, ["카라의 숲"], 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
["신속히 움직이며 카라의 저주로 적을 공격합니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217403, self::T_WIZARD, '제스 마법병',
|
||||
100, 100, 7, 0, 0.6, 10, 10,
|
||||
1000, null, ["제스 북부"], 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
[
|
||||
217403, self::T_WIZARD, '제스 마법병',
|
||||
100, 100, 7, 0, 0.6, 10, 10,
|
||||
1000, null, ["제스 북부"], 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
["마법국가 제스의 전통있는 마법병입니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217404, self::T_WIZARD, '무녀',
|
||||
80, 80, 8, 10, 0.6, 10, 10,
|
||||
1000, null, ["JAPAN"], 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
[
|
||||
217404, self::T_WIZARD, '무녀',
|
||||
80, 80, 8, 10, 0.6, 10, 10,
|
||||
1000, null, ["JAPAN"], 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
["신마법과 함께 신통한 춤으로 활력을 불어넣는 마법병입니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217405, self::T_WIZARD, '프로즌',
|
||||
90, 70, 7, 10, 0.8, 10, 10,
|
||||
1000, null, ["헬만 서부"], 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
[
|
||||
217405, self::T_WIZARD, '프로즌',
|
||||
90, 70, 7, 10, 0.8, 10, 10,
|
||||
1000, null, ["헬만 서부"], 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
["백병전에 불리한 연약한 몸으로 마법 사용에 집중하는 몬스터입니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217406, self::T_WIZARD, '마소한 마법병',
|
||||
70, 90, 7, 10, 0.8, 11, 10,
|
||||
1000, null, ["케이브리스 마인령"], 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
[
|
||||
217406, self::T_WIZARD, '마소한 마법병',
|
||||
70, 90, 7, 10, 0.8, 11, 10,
|
||||
1000, null, ["케이브리스 마인령"], 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
["로브를 여러겹 둘러입은 마물마법병입니다. 직접 전투보단 마법에 집중합니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217407, self::T_WIZARD, '신관병',
|
||||
80, 130, 7, 5, 0.6, 9, 11,
|
||||
2000, ["카이즈"], null, 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
[
|
||||
217407, self::T_WIZARD, '신관병',
|
||||
80, 130, 7, 5, 0.6, 9, 11,
|
||||
2000, ["카이즈"], null, 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
["AL교의 전투신관입니다. 몸을 보호하는 성스러운 마법을 사용합니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217408, self::T_WIZARD, '중장마법병',
|
||||
80, 130, 7, 15, 0.6, 11, 12,
|
||||
3000, ["로제스그라드"], null, 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
[
|
||||
217408, self::T_WIZARD, '중장마법병',
|
||||
80, 130, 7, 15, 0.6, 11, 12,
|
||||
3000, ["로제스그라드"], null, 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
["두터운 로브를 입고 불길한 주문을 읊습니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217409, self::T_WIZARD, '악마병',
|
||||
130, 80, 7, 15, 0.6, 11, 12,
|
||||
3000, ["올드제스"], null, 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
[
|
||||
217409, self::T_WIZARD, '악마병',
|
||||
130, 80, 7, 15, 0.6, 11, 12,
|
||||
3000, ["올드제스"], null, 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
["고대 제스 왕가의 계약에 따라 소환된 흑마법병입니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217410, self::T_WIZARD, '호넷 마물병',
|
||||
130, 130, 7, 0, 0.6, 12, 12,
|
||||
3000, ["구 마왕성"], null, 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
[
|
||||
217410, self::T_WIZARD, '호넷 마물병',
|
||||
130, 130, 7, 0, 0.6, 12, 12,
|
||||
3000, ["구 마왕성"], null, 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
["호넷 직속의 최강 마물 마법병입니다."],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
217411, self::T_WIZARD, 'Z가디언',
|
||||
180, 180, 7, 0, 0.7, 28, 20,
|
||||
5000, ["라그나로크 아크"], null, 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
[
|
||||
217411, self::T_WIZARD, 'Z가디언',
|
||||
180, 180, 7, 0, 0.7, 28, 20,
|
||||
5000, ["라그나로크 아크"], null, 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
["제스의 기술력이 집약된 최고의 마법병기입니다."],
|
||||
null, null
|
||||
],
|
||||
|
||||
[
|
||||
217500, self::T_SIEGE, '정란',
|
||||
150, 150, 6, 0, 0, 15, 5,
|
||||
0, null, null, 3,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>1.8],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
|
||||
|
||||
[
|
||||
217500, self::T_SIEGE, '정란',
|
||||
150, 150, 6, 0, 0, 15, 5,
|
||||
0, null, null, 3,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>1.8],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
|
||||
["높은 구조물 위에서 공격합니다."],
|
||||
['che_성벽부상무효'], null
|
||||
],
|
||||
[
|
||||
217501, self::T_SIEGE, '충차',
|
||||
150, 100, 6, 0, 0, 20, 5,
|
||||
1000, null, null, 3,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>2.4],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
|
||||
[
|
||||
217501, self::T_SIEGE, '충차',
|
||||
150, 100, 6, 0, 0, 20, 5,
|
||||
1000, null, null, 3,
|
||||
[ self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>2.4],
|
||||
[ self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
|
||||
["엄청난 위력으로 성벽을 부수어버립니다."],
|
||||
['che_성벽부상무효'], null
|
||||
],
|
||||
[
|
||||
217502, self::T_SIEGE, '튤립3호',
|
||||
275, 300, 6, 0, 0, 35, 15,
|
||||
5000, ["커스텀"], null, 0,
|
||||
[ ],
|
||||
[ ],
|
||||
[
|
||||
217502, self::T_SIEGE, '튤립3호',
|
||||
275, 300, 6, 0, 0, 35, 15,
|
||||
5000, ["커스텀"], null, 0,
|
||||
[ ],
|
||||
[ ],
|
||||
["파괴적인 위력과 정말 파괴적인 비용을 자랑하는 전차입니다. "],
|
||||
['che_성벽부상무효'], null
|
||||
],
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
@import "./common/bootstrap5.scss";
|
||||
@import "@scss/game_bg.scss";
|
||||
@import "./common_legacy.scss";
|
||||
@import "../../css/config.css";
|
||||
@import "./util.scss";
|
||||
|
||||
|
||||
@include media-1000px {
|
||||
#container {
|
||||
width: 1000px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-500px {
|
||||
#container {
|
||||
width: 500px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.date{
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.authorName,
|
||||
.authorIcon,
|
||||
.inputCommentHeader {
|
||||
flex: 0 0 auto;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
#newArticle {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.titleInput {
|
||||
width: 100%;
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
margin: 1px 5px;
|
||||
}
|
||||
|
||||
.contentInput {
|
||||
width: 100%;
|
||||
min-height: 3em;
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
padding: 1px 5px;
|
||||
}
|
||||
|
||||
.articleFrame {
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
.commentText {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.text {
|
||||
text-align: left;
|
||||
padding: 1px 5px;
|
||||
}
|
||||
|
||||
.submitComment {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.commentText {
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
padding: 1px 5px;
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
@import "@scss/common/variables.scss";
|
||||
@import "@scss/common/bootswatch_custom_variables.scss";
|
||||
@import "@scss/game_bg.scss";
|
||||
@import "@scss/util.scss";
|
||||
|
||||
$modcolor2: color.adjust($nbase2color, $lightness: -5%);
|
||||
|
||||
@@ -86,6 +87,12 @@ $modcolor2: color.adjust($nbase2color, $lightness: -5%);
|
||||
background-color: $modcolor2;
|
||||
}
|
||||
}
|
||||
|
||||
#bottomBar{
|
||||
width: 1000px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-500px {
|
||||
@@ -183,4 +190,10 @@ $modcolor2: color.adjust($nbase2color, $lightness: -5%);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
#bottomBar {
|
||||
width: 500px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
Vendored
+59
-54
@@ -1,67 +1,72 @@
|
||||
|
||||
|
||||
@function frontColor($color) {
|
||||
@return color-contrast($color);
|
||||
@return color-contrast($color);
|
||||
}
|
||||
|
||||
@each $colorType, $color in $nationColors {
|
||||
.sam-color-#{$colorType} {
|
||||
.sam-nation-own-bgcolor{
|
||||
background-color: $color;
|
||||
color: frontColor($color);
|
||||
}
|
||||
|
||||
.btn-sammo-nation{
|
||||
@include button-variant($color, $color);
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
background-color: $color;
|
||||
}
|
||||
|
||||
&,
|
||||
&:not(.disabled):hover,
|
||||
&:not(.disabled):active,
|
||||
&:focus {
|
||||
border-color: shade-color($color, 10%);
|
||||
}
|
||||
}
|
||||
@each $colorType,
|
||||
$color in $nationColors {
|
||||
.sam-color-#{$colorType} {
|
||||
.sam-nation-own-bgcolor {
|
||||
background-color: $color;
|
||||
color: frontColor($color);
|
||||
}
|
||||
|
||||
.btn-sammo-nation-#{$colorType}{
|
||||
@include button-variant($color, $color);
|
||||
.btn-sammo-nation {
|
||||
@include button-variant($color, $color);
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
background-color: $color;
|
||||
}
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
background-color: $color;
|
||||
}
|
||||
|
||||
&,
|
||||
&:not(.disabled):hover,
|
||||
&:not(.disabled):active,
|
||||
&:focus {
|
||||
border-color: shade-color($color, 10%);
|
||||
}
|
||||
&,
|
||||
&:not(.disabled):hover,
|
||||
&:not(.disabled):active,
|
||||
&:focus {
|
||||
border-color: shade-color($color, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sam-nation-bg-#{$colorType} {
|
||||
background-color: $color;
|
||||
color: frontColor($color);
|
||||
}
|
||||
|
||||
.btn-sammo-nation-#{$colorType} {
|
||||
@include button-variant($color, $color);
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
background-color: $color;
|
||||
}
|
||||
|
||||
&,
|
||||
&:not(.disabled):hover,
|
||||
&:not(.disabled):active,
|
||||
&:focus {
|
||||
border-color: shade-color($color, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@each $colorType, $color in $sammoColors {
|
||||
.btn-sammo-#{$colorType}{
|
||||
@include button-variant($color, $color);
|
||||
@each $colorType,
|
||||
$color in $sammoColors {
|
||||
.btn-sammo-#{$colorType} {
|
||||
@include button-variant($color, $color);
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
background-color: $color;
|
||||
}
|
||||
|
||||
&,
|
||||
&:not(.disabled):hover,
|
||||
&:not(.disabled):active,
|
||||
&:focus {
|
||||
border-color: shade-color($color, 10%);
|
||||
}
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
background-color: $color;
|
||||
}
|
||||
|
||||
&,
|
||||
&:not(.disabled):hover,
|
||||
&:not(.disabled):active,
|
||||
&:focus {
|
||||
border-color: shade-color($color, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
@import '@scss/common/bootstrap5.scss';
|
||||
|
||||
#scoutMsgForm .viewer{
|
||||
max-height:200px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.note-editor.card {
|
||||
background:inherit;
|
||||
color:inherit;
|
||||
border:none;
|
||||
}
|
||||
|
||||
.note-editor.note-frame .note-editing-area .note-editable {
|
||||
background:inherit;
|
||||
color:inherit;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.note-editor.note-frame .note-statusbar{
|
||||
background-color:#444444;
|
||||
border-top: 1px solid rgba(0,0,0,0.125);
|
||||
}
|
||||
@@ -215,6 +215,10 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
#nation-msg{
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
#nation-msg-box {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
@import '@scss/common/bootstrap5.scss';
|
||||
@import "@scss/game_bg.scss";
|
||||
@import "@scss/util.scss";
|
||||
@import "@scss/editor_component.scss";
|
||||
@import "@scss/common_legacy.scss";
|
||||
|
||||
.diplomacyTitle {
|
||||
background-color: $blue;
|
||||
text-align: center;
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
.noticeTitle {
|
||||
background-color: $white;
|
||||
text-align: center;
|
||||
color: black;
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
.financeTitle{
|
||||
background-color: $green;
|
||||
text-align: center;
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
#app {
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.tiptap-editor{
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#scoutMsgForm .ProseMirror{
|
||||
max-height: 200px;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
@include media-1000px {
|
||||
#container {
|
||||
width: 1000px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-500px {
|
||||
#container {
|
||||
position: relative;
|
||||
width: 500px;
|
||||
margin: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#noticeForm .ProseMirror {
|
||||
transform: scale(0.5);
|
||||
transform-origin: left top;
|
||||
width: 1000px;
|
||||
}
|
||||
|
||||
#scoutMsgForm .ProseMirror {
|
||||
transform: scale(calc(500/ 870));
|
||||
transform-origin: left top;
|
||||
width: 870px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.diplomacyTable {
|
||||
.tRow {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(130px, 3fr) 1.5fr 1fr 1fr 2fr 1fr 2fr;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.note-editor.card {
|
||||
background: inherit;
|
||||
color: inherit;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.note-editor.note-frame .note-editing-area .note-editable {
|
||||
background: inherit;
|
||||
color: inherit;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.note-editor.note-frame .note-statusbar {
|
||||
background-color: #444444;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.125);
|
||||
}
|
||||
+9
-3
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
.s-border-t {
|
||||
border-top: gray solid 1px;
|
||||
}
|
||||
@@ -11,4 +9,12 @@
|
||||
.s-border-tb {
|
||||
border-top: gray solid 1px;
|
||||
border-bottom: gray solid 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.avoid-wrap {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ shuffle($nationList);
|
||||
$nationList = Util::convertArrayToDict($nationList, 'nation');
|
||||
//NOTE: join 안할것임
|
||||
$scoutMsgs = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'scout_msg');
|
||||
foreach ($scoutMsgs as $nationID => $scoutMsg) {
|
||||
$nationList[$nationID]['scoutmsg'] = $scoutMsg;
|
||||
foreach ($scoutMsgs as $destNationID => $scoutMsg) {
|
||||
$nationList[$destNationID]['scoutmsg'] = $scoutMsg;
|
||||
}
|
||||
|
||||
$characterAll = []; //선택용
|
||||
|
||||
+2
-2
@@ -24,8 +24,8 @@ shuffle($nationList);
|
||||
$nationList = Util::convertArrayToDict($nationList, 'nation');
|
||||
//NOTE: join 안할것임
|
||||
$scoutMsgs = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'scout_msg');
|
||||
foreach ($scoutMsgs as $nationID => $scoutMsg) {
|
||||
$nationList[$nationID]['scoutmsg'] = $scoutMsg;
|
||||
foreach ($scoutMsgs as $destNationID => $scoutMsg) {
|
||||
$nationList[$destNationID]['scoutmsg'] = $scoutMsg;
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<?=$btnBegin??''?><a href='b_troop.php' class='commandButton <?= ($meLevel >= 1 && $nationLevel >= 1) ? '' : 'disabled' ?> <?=$btnClass??""?>'>부대 편성</a><?=$btnEnd??''?>
|
||||
<?=$btnBegin??''?><a href='t_diplomacy.php' class='commandButton <?= $showSecret ? '' : 'disabled' ?> <?=$btnClass??""?>'>외 교 부</a><?=$btnEnd??''?>
|
||||
<?=$btnBegin??''?><a href='b_myBossInfo.php' class='commandButton <?= $meLevel >= 1 ? '' : 'disabled' ?> <?=$btnClass??""?>'>인 사 부</a><?=$btnEnd??''?>
|
||||
<?=$btnBegin??''?><a href='b_dipcenter.php' class='commandButton <?= $showSecret ? '' : 'disabled' ?> <?=$btnClass??""?>'>내 무 부</a><?=$btnEnd??''?>
|
||||
<?=$btnBegin??''?><a href='v_nationStratFinan.php' class='commandButton <?= $showSecret ? '' : 'disabled' ?> <?=$btnClass??""?>'>내 무 부</a><?=$btnEnd??''?>
|
||||
<?=$btnBegin??''?><a href='v_chiefCenter.php' class='commandButton <?= $showSecret ? '' : 'disabled' ?> <?=$btnClass??""?>'>사 령 부</a><?=$btnEnd??''?>
|
||||
<?=$btnBegin??''?><a href='v_NPCControl.php' class='commandButton <?= $showSecret ? '' : 'disabled' ?> <?=$btnClass??""?>'>NPC 정책</a><?=$btnEnd??''?>
|
||||
<?=$btnBegin??''?><a href='b_genList.php' target='_blank' class='open-window commandButton <?=$btnClass??""?> <?= $showSecret ? '' : 'disabled' ?>'>암 행 부</a><?=$btnEnd??''?>
|
||||
|
||||
+37
-109
@@ -1,18 +1,12 @@
|
||||
<template>
|
||||
<top-back-bar :title="title" />
|
||||
<div id="container">
|
||||
<TopBackBar :title="title" />
|
||||
|
||||
<table id="newArticle" class="bg0">
|
||||
<thead>
|
||||
<tr>
|
||||
<td colspan="2" class="newArticleHeader bg2">새 게시물 작성</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="bg1" style="width: 66px">
|
||||
<span class="articleTitle">제목</span>
|
||||
</th>
|
||||
<td>
|
||||
<div id="newArticle" class="bg0">
|
||||
<div class="newArticleHeader bg2 center">새 게시물 작성</div>
|
||||
<div class="row gx-0">
|
||||
<div class="col-2 col-md-1 articleTitle bg1 center">제목</div>
|
||||
<div class="col-10 col-md-11">
|
||||
<input
|
||||
class="titleInput"
|
||||
type="text"
|
||||
@@ -20,11 +14,11 @@
|
||||
placeholder="제목"
|
||||
v-model="newArticle.title"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="bg1">내용</th>
|
||||
<td class="boardArticle">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row gx-0">
|
||||
<div class="col-2 col-md-1 bg1 center">내용</div>
|
||||
<div class="col-10 col-md-11">
|
||||
<textarea
|
||||
class="contentInput autosize"
|
||||
ref="newArticleTextForm"
|
||||
@@ -32,40 +26,35 @@
|
||||
v-model="newArticle.text"
|
||||
@input="autoResizeTextarea"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<button type="button" id="submitArticle" @click="submitArticle">
|
||||
등록
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-8 col-md-10"></div>
|
||||
<div class="col-4 col-md-2 d-grid">
|
||||
<b-button id="submitArticle" @click="submitArticle"> 등록 </b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="board">
|
||||
<template v-if="articles && articles.length">
|
||||
<board-article
|
||||
v-for="article in articles"
|
||||
:key="article.no"
|
||||
:article="article"
|
||||
@submit-comment="reloadArticles"
|
||||
/>
|
||||
</template>
|
||||
<template v-else> 게시물이 없습니다. </template>
|
||||
</div>
|
||||
|
||||
<div id="board">
|
||||
<template v-if="articles && articles.length">
|
||||
<board-article
|
||||
v-for="article in articles"
|
||||
:key="article.no"
|
||||
:article="article"
|
||||
@submit-comment="reloadArticles"
|
||||
/>
|
||||
</template>
|
||||
<template v-else> 게시물이 없습니다. </template>
|
||||
<BottomBar/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import "@scss/common/bootstrap5.scss";
|
||||
import "@scss/game_bg.scss";
|
||||
import "../../css/config.css";
|
||||
|
||||
import { defineComponent, onMounted, reactive, ref } from "vue";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import BoardArticle from "@/components/BoardArticle.vue";
|
||||
import { convertFormData } from "@util/convertFormData";
|
||||
import axios from "axios";
|
||||
@@ -105,6 +94,7 @@ export default defineComponent({
|
||||
name: "PageBoard",
|
||||
components: {
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
BoardArticle,
|
||||
},
|
||||
props: {
|
||||
@@ -155,7 +145,7 @@ export default defineComponent({
|
||||
|
||||
this.newArticle = { title: "", text: "" };
|
||||
const newArticleTextForm = unwrap(this.newArticleTextForm);
|
||||
newArticleTextForm.style.height = 'auto';
|
||||
newArticleTextForm.style.height = "auto";
|
||||
|
||||
await this.reloadArticles();
|
||||
},
|
||||
@@ -188,7 +178,6 @@ export default defineComponent({
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
articles.length = 0;
|
||||
articles.push(...Object.values(boardResponse.articles));
|
||||
articles.reverse();
|
||||
@@ -205,65 +194,4 @@ export default defineComponent({
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
#newArticle {
|
||||
width: 1000px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.titleInput {
|
||||
width: 100%;
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
margin: 1px 5px;
|
||||
}
|
||||
|
||||
.contentInput {
|
||||
width: 100%;
|
||||
min-height: 3em;
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
padding: 1px 5px;
|
||||
}
|
||||
|
||||
.articleFrame {
|
||||
width: 1000px;
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
.commentText {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.authorName,
|
||||
.comment .author {
|
||||
width: 110px;
|
||||
font-size: 85%;
|
||||
}
|
||||
|
||||
.date {
|
||||
width: 125px;
|
||||
font-size: 85%;
|
||||
}
|
||||
|
||||
.text {
|
||||
text-align: left;
|
||||
padding: 1px 5px;
|
||||
}
|
||||
|
||||
.submitComment {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.commentText {
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
padding: 1px 5px;
|
||||
}
|
||||
</style>
|
||||
</script>
|
||||
+18
-10
@@ -88,6 +88,9 @@
|
||||
</div>
|
||||
|
||||
<b-dropdown class="col-md-4" left text="턴 선택">
|
||||
<b-dropdown-item @click="selectNone()"
|
||||
>해제</b-dropdown-item
|
||||
>
|
||||
<b-dropdown-item @click="selectAll(true)"
|
||||
>모든턴</b-dropdown-item
|
||||
>
|
||||
@@ -227,6 +230,9 @@
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottomBar">
|
||||
<BottomBar />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import "@scss/common/bootstrap5.scss";
|
||||
@@ -236,10 +242,10 @@ import "../../css/config.css";
|
||||
import { computed, defineComponent, reactive, ref, toRefs, watch } from "vue";
|
||||
import ChiefReservedCommand from "@/components/ChiefReservedCommand.vue";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import VueTypes from "vue-types";
|
||||
import { isString, range } from "lodash";
|
||||
import { mb_strwidth } from "./util/mb_strwidth";
|
||||
import { sammoAPI } from "./util/sammoAPI";
|
||||
import { entriesWithType } from "./util/entriesWithType";
|
||||
import { addMilliseconds } from "date-fns";
|
||||
import { formatTime } from "./util/formatTime";
|
||||
@@ -248,6 +254,7 @@ import { getNpcColor } from "./common_legacy";
|
||||
import TopItem from "@/ChiefCenter/TopItem.vue";
|
||||
import BottomItem from "@/ChiefCenter/BottomItem.vue";
|
||||
import { ChiefResponse, OptionalFull } from "./defs";
|
||||
import { SammoAPI } from "./SammoAPI";
|
||||
|
||||
function isDropdownChildren(e?: Event): boolean {
|
||||
if (!e) {
|
||||
@@ -269,6 +276,7 @@ function isDropdownChildren(e?: Event): boolean {
|
||||
export default defineComponent({
|
||||
components: {
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
ChiefReservedCommand,
|
||||
TopItem,
|
||||
BottomItem,
|
||||
@@ -293,6 +301,9 @@ export default defineComponent({
|
||||
this.turnList.clear();
|
||||
this.turnList.add(turnIdx);
|
||||
},
|
||||
selectNone() {
|
||||
this.turnList.clear();
|
||||
},
|
||||
selectAll(e: Event | true) {
|
||||
//NOTE: split 구현에 버그가 있어서, 수동으로 구분해야함
|
||||
if (e !== true && isDropdownChildren(e)) {
|
||||
@@ -317,7 +328,7 @@ export default defineComponent({
|
||||
},
|
||||
async repeatNationCommand(amount: number) {
|
||||
try {
|
||||
await sammoAPI(`NationCommand/RepeatCommand`, { amount });
|
||||
await SammoAPI.NationCommand.RepeatCommand({ amount });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
@@ -327,7 +338,7 @@ export default defineComponent({
|
||||
},
|
||||
async pushNationCommand(amount: number) {
|
||||
try {
|
||||
await sammoAPI("NationCommand/PushCommand", { amount });
|
||||
await SammoAPI.NationCommand.PushCommand({ amount });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
@@ -384,9 +395,8 @@ export default defineComponent({
|
||||
|
||||
async function reloadTable(): Promise<void> {
|
||||
try {
|
||||
const response = await sammoAPI<ChiefResponse>(
|
||||
"NationCommand/GetReservedCommand"
|
||||
);
|
||||
const response =
|
||||
await SammoAPI.NationCommand.GetReservedCommand<ChiefResponse>();
|
||||
console.log(response);
|
||||
for (const [key, value] of entriesWithType(response)) {
|
||||
if (key === "result") {
|
||||
@@ -411,13 +421,11 @@ export default defineComponent({
|
||||
timeDiff.value = serverNowObj.getTime() - clientNowObj.getTime();
|
||||
|
||||
if (viewTarget.value === undefined) {
|
||||
if(!tableObj.officerLevel){
|
||||
if (!tableObj.officerLevel) {
|
||||
viewTarget.value = 12;
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
viewTarget.value = tableObj.officerLevel;
|
||||
}
|
||||
|
||||
}
|
||||
} catch (e) {
|
||||
if (isString(e)) {
|
||||
|
||||
@@ -262,10 +262,8 @@ import "@scss/common/bootstrap5.scss";
|
||||
import "@scss/game_bg.scss";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import _ from "lodash";
|
||||
import { InvalidResponse } from "@/defs";
|
||||
import axios from "axios";
|
||||
import NumberInputWithInfo from "@/components/NumberInputWithInfo.vue";
|
||||
import { sammoAPI } from "./util/sammoAPI";
|
||||
import { SammoAPI } from "./SammoAPI";
|
||||
|
||||
type InheritanceType =
|
||||
| "previous"
|
||||
@@ -507,7 +505,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
try {
|
||||
await sammoAPI("InheritAction/BuyHiddenBuff", {
|
||||
await SammoAPI.InheritAction.BuyHiddenBuff({
|
||||
type: buffKey,
|
||||
level,
|
||||
});
|
||||
@@ -550,7 +548,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
try {
|
||||
await sammoAPI(`InheritAction/${type}`, {});
|
||||
await SammoAPI.InheritAction[type]({});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
@@ -584,7 +582,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
try {
|
||||
await sammoAPI(`InheritAction/SetNextSpecialWar`, {
|
||||
await SammoAPI.InheritAction.SetNextSpecialWar({
|
||||
type: this.nextSpecialWar,
|
||||
});
|
||||
} catch (e) {
|
||||
@@ -616,7 +614,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
try {
|
||||
await sammoAPI(`InheritAction/BuySpecificUnique`, {
|
||||
await SammoAPI.InheritAction.BuySpecificUnique({
|
||||
item: this.specificUnique,
|
||||
amount,
|
||||
});
|
||||
|
||||
+5
-5
@@ -315,10 +315,8 @@ import {
|
||||
abilityRand,
|
||||
} from "@util/generalStats";
|
||||
import { clone, shuffle, sum } from "lodash";
|
||||
import axios from "axios";
|
||||
import { InvalidResponse } from "@/defs";
|
||||
import NumberInputWithInfo from "@/components/NumberInputWithInfo.vue";
|
||||
import { sammoAPI } from "./util/sammoAPI";
|
||||
import { SammoAPI } from "./SammoAPI";
|
||||
|
||||
declare const nationList: {
|
||||
nation: number;
|
||||
@@ -536,7 +534,7 @@ export default defineComponent({
|
||||
//검증은 언제 되어야 하는가?
|
||||
const args = clone(this.args);
|
||||
try {
|
||||
await sammoAPI(["General", "Join"], args);
|
||||
await SammoAPI.General.Join(args);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
@@ -551,7 +549,9 @@ export default defineComponent({
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
<style lang="scss">
|
||||
@import "@scss/common/bootstrap5.scss";
|
||||
@import "@scss/editor_component.scss";
|
||||
#container {
|
||||
width: 100%;
|
||||
max-width: 1000px;
|
||||
|
||||
@@ -0,0 +1,655 @@
|
||||
<template>
|
||||
<MyToast v-model="toasts" />
|
||||
<div id="container" class="pageNationStratFinan bg0">
|
||||
<TopBackBar title="내무부" />
|
||||
<div class="diplomacyTitle">외교관계</div>
|
||||
<div class="diplomacyTable">
|
||||
<div class="diplomacyHeader tRow bg1">
|
||||
<div>국가명</div>
|
||||
<div>국력</div>
|
||||
<div>장수</div>
|
||||
<div>속령</div>
|
||||
<div>상태</div>
|
||||
<div>기간</div>
|
||||
<div>종료 시점</div>
|
||||
</div>
|
||||
<div
|
||||
:class="['diplomacyItem', 'tRow', 's-border-b']"
|
||||
v-for="nation in nationsList"
|
||||
:key="nation.nation"
|
||||
>
|
||||
<div :class="`sam-nation-bg-${nation.color.slice(1)}`">
|
||||
{{ nation.name }}
|
||||
</div>
|
||||
<div>{{ nation.power.toLocaleString() }}</div>
|
||||
<div>{{ nation.gennum.toLocaleString() }}</div>
|
||||
<div>{{ nation.cityCnt.toLocaleString() }}</div>
|
||||
<template v-if="nation.nation == nationID">
|
||||
<div>-</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div
|
||||
:style="{
|
||||
color:
|
||||
diplomacyStateInfo[nation.diplomacy.state].color ?? undefined,
|
||||
}"
|
||||
>
|
||||
{{ diplomacyStateInfo[nation.diplomacy.state].name }}
|
||||
</div>
|
||||
<div>
|
||||
{{
|
||||
nation.diplomacy.term == 0 ? "-" : `${nation.diplomacy.term}개월`
|
||||
}}
|
||||
</div>
|
||||
<div
|
||||
v-for="([endYear, endMonth], _idx) in [
|
||||
parseYearMonth(
|
||||
joinYearMonth(year, month) + nation.diplomacy.term
|
||||
),
|
||||
]"
|
||||
:key="_idx"
|
||||
>
|
||||
{{
|
||||
nation.diplomacy.term == 0 ? "-" : `${endYear}년 ${endMonth}월`
|
||||
}}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="noticeTitle">국가 방침 & 임관 권유 메시지</div>
|
||||
<div id="noticeForm">
|
||||
<div class="bg1" style="display: flex; justify-content: space-around">
|
||||
<div style="flex: 1 1 auto">국가 방침</div>
|
||||
<div>
|
||||
<b-button
|
||||
@click="enableEditNationMsg"
|
||||
v-if="editable && !inEditNationMsg"
|
||||
>국가방침 수정</b-button
|
||||
>
|
||||
<b-button @click="saveNationMsg" v-if="editable && inEditNationMsg"
|
||||
>저장</b-button
|
||||
>
|
||||
<b-button
|
||||
v-if="editable && inEditNationMsg"
|
||||
@click="rollbackNationMsg"
|
||||
>취소</b-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<TipTap
|
||||
v-model="nationMsg"
|
||||
:editable="inEditNationMsg"
|
||||
@ready="trackNationMsgHeight"
|
||||
@update:modelValue="trackNationMsgHeight"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="scoutMsgForm">
|
||||
<div class="bg1" style="display: flex; justify-content: space-around">
|
||||
<div style="flex: 1 1 auto">임관 권유</div>
|
||||
<div>
|
||||
<b-button
|
||||
@click="enableEditScoutMsg"
|
||||
v-if="editable && !inEditScoutMsg"
|
||||
>임관 권유문 수정</b-button
|
||||
>
|
||||
<b-button @click="saveScoutMsg" v-if="editable && inEditScoutMsg"
|
||||
>저장</b-button
|
||||
>
|
||||
<b-button v-if="editable && inEditScoutMsg" @click="rollbackScoutMsg"
|
||||
>취소</b-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div style="border-bottom: solid gray 0.5px">
|
||||
870px x 200px를 넘어서는 내용은 표시되지 않습니다.
|
||||
</div>
|
||||
<div style="width: 870px; margin-left: auto">
|
||||
<TipTap
|
||||
v-model="scoutMsg"
|
||||
:editable="inEditScoutMsg"
|
||||
@ready="trackScoutMsgHeight"
|
||||
@update:modelValue="trackScoutMsgHeight"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="financeTitle">예산&정책</div>
|
||||
<div class="row gx-0 center">
|
||||
<div class="col-6">
|
||||
<div class="row gx-0">
|
||||
<div class="col-12 bg2">자금 예산</div>
|
||||
<div class="col-4 bg1">현 재</div>
|
||||
<div class="col-8">{{ gold.toLocaleString() }}</div>
|
||||
<div class="col-4 bg1">단기수입</div>
|
||||
<div class="col-8">{{ income.gold.war.toLocaleString() }}</div>
|
||||
<div class="col-4 bg1">세 금</div>
|
||||
<div class="col-8">
|
||||
{{ Math.floor(incomeGoldCity).toLocaleString() }}
|
||||
</div>
|
||||
<div class="col-4 bg1">수입/지출</div>
|
||||
<div class="col-8">
|
||||
+{{ Math.floor(incomeGold).toLocaleString() }} /
|
||||
{{ Math.floor(-outcomeByBill).toLocaleString() }}
|
||||
</div>
|
||||
<div class="col-4 bg1">국고 예산</div>
|
||||
<div class="col-8">
|
||||
{{ Math.floor(gold + incomeGold - outcomeByBill).toLocaleString() }}
|
||||
({{ incomeGold >= outcomeByBill ? "+" : ""
|
||||
}}{{ Math.floor(incomeGold - outcomeByBill).toLocaleString() }})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="row gx-0">
|
||||
<div class="col-12 bg2">군량 예산</div>
|
||||
<div class="col-4 bg1">현 재</div>
|
||||
<div class="col-8">{{ rice.toLocaleString() }}</div>
|
||||
<div class="col-4 bg1">둔전수입</div>
|
||||
<div class="col-8">
|
||||
{{ Math.floor(incomeRiceWall).toLocaleString() }}
|
||||
</div>
|
||||
<div class="col-4 bg1">세 금</div>
|
||||
<div class="col-8">
|
||||
{{ Math.floor(incomeRiceCity).toLocaleString() }}
|
||||
</div>
|
||||
<div class="col-4 bg1">수입/지출</div>
|
||||
<div class="col-8">
|
||||
+{{ Math.floor(incomeRice).toLocaleString() }} /
|
||||
{{ Math.floor(-outcomeByBill).toLocaleString() }}
|
||||
</div>
|
||||
<div class="col-4 bg1">국고 예산</div>
|
||||
<div class="col-8">
|
||||
{{ Math.floor(rice + incomeRice - outcomeByBill).toLocaleString() }}
|
||||
({{ incomeRice >= outcomeByBill ? "+" : ""
|
||||
}}{{ Math.floor(incomeRice - outcomeByBill).toLocaleString() }})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="row gx-0">
|
||||
<div class="col-4 bg1 d-grid">
|
||||
<div class="align-self-center">
|
||||
세율 <span class="avoid-wrap">(5 ~ 30%)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-8 row gx-0">
|
||||
<div class="col-md-6 offset-md-3 align-self-center">
|
||||
<div class="input-group my-0">
|
||||
<input
|
||||
type="number"
|
||||
class="form-control py-1 f_tnum px-0 text-end"
|
||||
v-model="policy.rate"
|
||||
min="5"
|
||||
max="30"
|
||||
/><span class="input-group-text py-1 f_tnum">%</span
|
||||
><b-button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
@click="setRate"
|
||||
v-if="editable"
|
||||
>변경</b-button
|
||||
><b-button size="sm" @click="rollbackRate" v-if="editable"
|
||||
>취소</b-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="row gx-0">
|
||||
<div class="col-4 bg1 d-grid">
|
||||
<div class="align-self-center">
|
||||
지급률 <span class="avoid-wrap">(20 ~ 200%)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-8 row gx-0">
|
||||
<div class="col-md-6 offset-md-3 align-self-center">
|
||||
<div class="input-group my-0">
|
||||
<input
|
||||
type="number"
|
||||
class="form-control py-1 f_tnum px-0 text-end"
|
||||
v-model="policy.bill"
|
||||
min="20"
|
||||
max="200"
|
||||
/><span class="input-group-text py-1 f_tnum">%</span
|
||||
><b-button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
@click="setBill"
|
||||
v-if="editable"
|
||||
>변경</b-button
|
||||
><b-button size="sm" @click="rollbackBill" v-if="editable"
|
||||
>취소</b-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="row gx-0">
|
||||
<div class="col-4 bg1 d-grid">
|
||||
<div class="align-self-center">
|
||||
기밀 권한 <span class="avoid-wrap">(1 ~ 99년)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-8 row gx-0">
|
||||
<div class="col-md-6 offset-md-3 align-self-center">
|
||||
<div class="input-group my-0">
|
||||
<input
|
||||
type="number"
|
||||
class="form-control py-1 f_tnum px-0 text-end"
|
||||
v-model="policy.secretLimit"
|
||||
min="1"
|
||||
max="99"
|
||||
/><span class="input-group-text py-1 f_tnum">년</span
|
||||
><b-button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
@click="setSecretLimit"
|
||||
v-if="editable"
|
||||
>변경</b-button
|
||||
><b-button
|
||||
size="sm"
|
||||
@click="rollbackSecretLimit"
|
||||
v-if="editable"
|
||||
>취소</b-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 d-grid">
|
||||
<div class="row gx-0">
|
||||
<div class="col-4 bg1 d-grid">
|
||||
<div class="align-self-center">전쟁 금지 설정</div>
|
||||
</div>
|
||||
<div class="col-8 d-grid">
|
||||
<div class="align-self-center">{{warSettingCnt.remain}} 회(월 +{{warSettingCnt.inc}}회, 최대{{warSettingCnt.max}}회)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3 col-md-4"></div>
|
||||
<div class="col-3 col-md-2 row gx-0">
|
||||
<div class="col-9 col-md-8 text-end p-2">전쟁 금지</div>
|
||||
<div class="col-3 col-md-4 py-2">
|
||||
<b-form-checkbox
|
||||
v-model="policy.blockWar"
|
||||
@change="setBlockWar"
|
||||
switch
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3 col-md-2 row gx-0">
|
||||
<div class="col-9 col-md-8 text-end p-2">임관 금지</div>
|
||||
<div class="col-3 col-md-4 py-2">
|
||||
<b-form-checkbox
|
||||
v-model="policy.blockScout"
|
||||
@change="setBlockScout"
|
||||
switch
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>추가 설정</div>
|
||||
<BottomBar title="내무부" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import TipTap from "./components/TipTap.vue";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import { computed, defineComponent, reactive, ref, toRefs } from "vue";
|
||||
import { isString } from "lodash";
|
||||
import {
|
||||
diplomacyState,
|
||||
diplomacyStateInfo,
|
||||
NationStaticItem,
|
||||
ToastType,
|
||||
} from "./defs";
|
||||
import { SammoAPI } from "./SammoAPI";
|
||||
import { joinYearMonth } from "@/util/joinYearMonth";
|
||||
import { parseYearMonth } from "@/util/parseYearMonth";
|
||||
import MyToast from "@/components/MyToast.vue";
|
||||
import { ValidResponse } from "./util/callSammoAPI";
|
||||
|
||||
type NationItem = NationStaticItem & {
|
||||
cityCnt: number;
|
||||
diplomacy: {
|
||||
state: diplomacyState;
|
||||
term: number | null;
|
||||
};
|
||||
};
|
||||
|
||||
type SetBlockWarResponse = ValidResponse & {
|
||||
availableCnt: number;
|
||||
}
|
||||
declare const staticValues: {
|
||||
editable: boolean;
|
||||
nationMsg: string;
|
||||
scoutMsg: string;
|
||||
nationID: number;
|
||||
officerLevel: number;
|
||||
year: number;
|
||||
month: number;
|
||||
nationsList: Record<number, NationItem>;
|
||||
|
||||
gold: number;
|
||||
rice: number;
|
||||
income: {
|
||||
gold: {
|
||||
city: number;
|
||||
war: number;
|
||||
};
|
||||
rice: {
|
||||
city: number;
|
||||
wall: number;
|
||||
};
|
||||
};
|
||||
outcome: number;
|
||||
|
||||
policy: {
|
||||
rate: number;
|
||||
bill: number;
|
||||
secretLimit: number;
|
||||
blockScout: boolean;
|
||||
blockWar: boolean;
|
||||
};
|
||||
warSettingCnt: {
|
||||
remain: number;
|
||||
inc: number;
|
||||
max: number;
|
||||
};
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
MyToast,
|
||||
TipTap,
|
||||
},
|
||||
setup() {
|
||||
const toasts = ref<ToastType[]>([]);
|
||||
const self = reactive(staticValues);
|
||||
|
||||
let oldNationMsg = staticValues.nationMsg;
|
||||
const inEditNationMsg = ref(false);
|
||||
|
||||
function enableEditNationMsg() {
|
||||
inEditNationMsg.value = true;
|
||||
}
|
||||
|
||||
function rollbackNationMsg() {
|
||||
inEditNationMsg.value = false;
|
||||
self.nationMsg = oldNationMsg;
|
||||
}
|
||||
|
||||
async function saveNationMsg() {
|
||||
const msg = self.nationMsg;
|
||||
try {
|
||||
await SammoAPI.Nation.SetNotice({
|
||||
msg,
|
||||
});
|
||||
oldNationMsg = msg;
|
||||
inEditNationMsg.value = false;
|
||||
toasts.value.push({
|
||||
title: "변경",
|
||||
content: "국가 방침을 변경했습니다.",
|
||||
});
|
||||
} catch (e) {
|
||||
if (isString(e)) {
|
||||
toasts.value.push({
|
||||
title: "에러",
|
||||
content: e,
|
||||
type: "danger",
|
||||
});
|
||||
}
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
let oldScoutMsg = staticValues.scoutMsg;
|
||||
const inEditScoutMsg = ref(false);
|
||||
|
||||
function enableEditScoutMsg() {
|
||||
inEditScoutMsg.value = true;
|
||||
}
|
||||
function rollbackScoutMsg() {
|
||||
inEditScoutMsg.value = false;
|
||||
self.scoutMsg = oldScoutMsg;
|
||||
}
|
||||
async function saveScoutMsg() {
|
||||
const msg = self.scoutMsg;
|
||||
try {
|
||||
await SammoAPI.Nation.SetScoutMsg({
|
||||
msg,
|
||||
});
|
||||
oldScoutMsg = msg;
|
||||
inEditScoutMsg.value = false;
|
||||
toasts.value.push({
|
||||
title: "변경",
|
||||
content: "임관 권유문을 변경했습니다.",
|
||||
});
|
||||
} catch (e) {
|
||||
if (isString(e)) {
|
||||
toasts.value.push({
|
||||
title: "에러",
|
||||
content: e,
|
||||
type: "danger",
|
||||
});
|
||||
}
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
const trackTiptapFormHeight = (target: string) => {
|
||||
let form: HTMLElement | null = null;
|
||||
let outerForm: HTMLElement | null = null;
|
||||
function handler() {
|
||||
if (!form) {
|
||||
form = document.querySelector(`${target} .ProseMirror`);
|
||||
}
|
||||
if (!outerForm) {
|
||||
outerForm = document.querySelector(`${target} .tiptap-editor`);
|
||||
}
|
||||
if (!form || !outerForm) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { height: clientHeight } = form.getBoundingClientRect();
|
||||
const { height: parentHeight } = outerForm.getBoundingClientRect();
|
||||
|
||||
if (parentHeight != clientHeight) {
|
||||
outerForm.style.height = `${clientHeight}px`;
|
||||
}
|
||||
}
|
||||
window.addEventListener("orientationchange", handler, true);
|
||||
|
||||
return handler;
|
||||
};
|
||||
|
||||
const incomeGoldCity = computed(() => {
|
||||
return (self.income.gold.city * self.policy.rate) / 100;
|
||||
});
|
||||
|
||||
const incomeGold = computed(() => {
|
||||
return incomeGoldCity.value + self.income.gold.war;
|
||||
});
|
||||
|
||||
const incomeRiceCity = computed(() => {
|
||||
return (self.income.rice.city * self.policy.rate) / 100;
|
||||
});
|
||||
|
||||
const incomeRiceWall = computed(() => {
|
||||
return (self.income.rice.wall * self.policy.rate) / 100;
|
||||
});
|
||||
|
||||
const incomeRice = computed(() => {
|
||||
return incomeRiceCity.value + incomeRiceWall.value;
|
||||
});
|
||||
|
||||
const outcomeByBill = computed(() => {
|
||||
return (self.outcome * self.policy.bill) / 100;
|
||||
});
|
||||
|
||||
let oldRate = staticValues.policy.rate;
|
||||
async function setRate() {
|
||||
const rate = self.policy.rate;
|
||||
try {
|
||||
await SammoAPI.Nation.SetRate({ amount: rate });
|
||||
oldRate = rate;
|
||||
toasts.value.push({
|
||||
title: "변경",
|
||||
content: "세율을 변경했습니다.",
|
||||
});
|
||||
} catch (e) {
|
||||
if (isString(e)) {
|
||||
toasts.value.push({
|
||||
title: "에러",
|
||||
content: e,
|
||||
type: "danger",
|
||||
});
|
||||
}
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
function rollbackRate() {
|
||||
self.policy.rate = oldRate;
|
||||
}
|
||||
|
||||
let oldBill = staticValues.policy.bill;
|
||||
async function setBill() {
|
||||
const bill = self.policy.bill;
|
||||
try {
|
||||
await SammoAPI.Nation.SetBill({ amount: bill });
|
||||
oldBill = bill;
|
||||
toasts.value.push({
|
||||
title: "변경",
|
||||
content: "지급률을 변경했습니다.",
|
||||
});
|
||||
} catch (e) {
|
||||
if (isString(e)) {
|
||||
toasts.value.push({
|
||||
title: "에러",
|
||||
content: e,
|
||||
type: "danger",
|
||||
});
|
||||
}
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
function rollbackBill() {
|
||||
self.policy.bill = oldBill;
|
||||
}
|
||||
|
||||
let oldSecretLimit = staticValues.policy.secretLimit;
|
||||
async function setSecretLimit() {
|
||||
const secretLimit = self.policy.secretLimit;
|
||||
try {
|
||||
await SammoAPI.Nation.SetSecretLimit({ amount: secretLimit });
|
||||
oldSecretLimit = secretLimit;
|
||||
toasts.value.push({
|
||||
title: "변경",
|
||||
content: "기밀 권한을 변경했습니다.",
|
||||
});
|
||||
} catch (e) {
|
||||
if (isString(e)) {
|
||||
toasts.value.push({
|
||||
title: "에러",
|
||||
content: e,
|
||||
type: "danger",
|
||||
});
|
||||
}
|
||||
self.policy.secretLimit = oldSecretLimit;
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
function rollbackSecretLimit() {
|
||||
self.policy.secretLimit = oldSecretLimit;
|
||||
}
|
||||
|
||||
async function setBlockWar() {
|
||||
try {
|
||||
const result = await SammoAPI.Nation.SetBlockWar<SetBlockWarResponse>({ value: self.policy.blockWar });
|
||||
self.warSettingCnt.remain = result.availableCnt;
|
||||
toasts.value.push({
|
||||
title: "변경",
|
||||
content: "전쟁 금지 설정을 변경했습니다.",
|
||||
});
|
||||
} catch (e) {
|
||||
if (isString(e)) {
|
||||
toasts.value.push({
|
||||
title: "에러",
|
||||
content: e,
|
||||
type: "danger",
|
||||
});
|
||||
}
|
||||
self.policy.blockWar = !self.policy.blockWar;
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
async function setBlockScout() {
|
||||
try {
|
||||
await SammoAPI.Nation.SetBlockScout({ value: self.policy.blockScout });
|
||||
toasts.value.push({
|
||||
title: "변경",
|
||||
content: "임관 설정을 변경했습니다.",
|
||||
});
|
||||
} catch (e) {
|
||||
if (isString(e)) {
|
||||
toasts.value.push({
|
||||
title: "에러",
|
||||
content: e,
|
||||
type: "danger",
|
||||
});
|
||||
}
|
||||
self.policy.blockScout = !self.policy.blockScout;
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
toasts,
|
||||
|
||||
...toRefs(self),
|
||||
inEditNationMsg,
|
||||
inEditScoutMsg,
|
||||
enableEditNationMsg,
|
||||
rollbackNationMsg,
|
||||
saveNationMsg,
|
||||
enableEditScoutMsg,
|
||||
rollbackScoutMsg,
|
||||
saveScoutMsg,
|
||||
diplomacyStateInfo,
|
||||
joinYearMonth,
|
||||
parseYearMonth,
|
||||
|
||||
trackNationMsgHeight: trackTiptapFormHeight("#noticeForm"),
|
||||
trackScoutMsgHeight: trackTiptapFormHeight("#scoutMsgForm"),
|
||||
|
||||
incomeGoldCity,
|
||||
incomeGold,
|
||||
incomeRiceCity,
|
||||
incomeRiceWall,
|
||||
incomeRice,
|
||||
outcomeByBill,
|
||||
|
||||
setRate,
|
||||
rollbackRate,
|
||||
setBill,
|
||||
rollbackBill,
|
||||
setSecretLimit,
|
||||
rollbackSecretLimit,
|
||||
|
||||
setBlockWar,
|
||||
setBlockScout,
|
||||
};
|
||||
},
|
||||
methods: {},
|
||||
});
|
||||
</script>
|
||||
@@ -1,124 +0,0 @@
|
||||
<template>
|
||||
<div>국 가 방 침 & 임관 권유 메시지</div>
|
||||
<div id="noticeForm">
|
||||
<div class="bg1" style="display: flex; justify-content: space-around">
|
||||
<div style="flex: 1 1 auto">국가 방침</div>
|
||||
<div>
|
||||
<b-button
|
||||
@click="enableEditNationMsg"
|
||||
v-if="editable && !inEditNationMsg"
|
||||
>국가방침 수정</b-button
|
||||
>
|
||||
<b-button @click="saveNationMsg" v-if="editable && inEditNationMsg"
|
||||
>저장</b-button
|
||||
>
|
||||
<b-button v-if="editable && inEditNationMsg" @click="rollbackNationMsg"
|
||||
>취소</b-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<TipTap v-model="nationMsg" :editable="inEditNationMsg" />
|
||||
</div>
|
||||
|
||||
<div id="scoutMsgForm">
|
||||
<div class="bg1" style="display: flex; justify-content: space-around">
|
||||
<div style="flex: 1 1 auto">임관 권유</div>
|
||||
<div>
|
||||
<b-button
|
||||
@click="enableEditScoutMsg"
|
||||
v-if="editable && !inEditScoutMsg"
|
||||
>임관 권유문 수정</b-button
|
||||
>
|
||||
<b-button @click="saveScoutMsg" v-if="editable && inEditScoutMsg"
|
||||
>저장</b-button
|
||||
>
|
||||
<b-button v-if="editable && inEditScoutMsg" @click="rollbackScoutMsg"
|
||||
>취소</b-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div style="border-bottom: solid gray 0.5px">
|
||||
870px x 200px를 넘어서는 내용은 표시되지 않습니다.
|
||||
</div>
|
||||
<div style="width: 870px; margin-left: auto">
|
||||
<TipTap v-model="scoutMsg" :editable="inEditScoutMsg" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import "@scss/dipcenter.scss";
|
||||
import "@scss/common_legacy.scss";
|
||||
import "@scss/editor_component.scss";
|
||||
import TipTap from "./components/TipTap.vue";
|
||||
import { defineComponent } from "vue";
|
||||
import { sammoAPI } from "./util/sammoAPI";
|
||||
import { isString } from "lodash";
|
||||
declare const editable: boolean;
|
||||
declare const nationMsg: string;
|
||||
declare const scoutMsg: string;
|
||||
|
||||
export default defineComponent({
|
||||
name: "PartialDipcenter",
|
||||
components: {
|
||||
TipTap,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editable,
|
||||
oldNationMsg: nationMsg,
|
||||
oldScoutMsg: scoutMsg,
|
||||
nationMsg,
|
||||
scoutMsg,
|
||||
inEditNationMsg: false,
|
||||
inEditScoutMsg: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
enableEditNationMsg() {
|
||||
this.inEditNationMsg = true;
|
||||
},
|
||||
rollbackNationMsg() {
|
||||
this.inEditNationMsg = false;
|
||||
this.nationMsg = this.oldNationMsg;
|
||||
},
|
||||
async saveNationMsg() {
|
||||
const msg = this.nationMsg;
|
||||
try {
|
||||
await sammoAPI("Nation/SetNotice", {
|
||||
msg,
|
||||
});
|
||||
this.oldNationMsg = msg;
|
||||
this.inEditNationMsg = false;
|
||||
} catch (e) {
|
||||
if (isString(e)) {
|
||||
alert(e);
|
||||
}
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
|
||||
enableEditScoutMsg() {
|
||||
this.inEditScoutMsg = true;
|
||||
},
|
||||
rollbackScoutMsg() {
|
||||
this.inEditScoutMsg = false;
|
||||
this.scoutMsg = this.oldScoutMsg;
|
||||
},
|
||||
async saveScoutMsg() {
|
||||
const msg = this.scoutMsg;
|
||||
try {
|
||||
await sammoAPI("Nation/SetScoutMsg", {
|
||||
msg,
|
||||
});
|
||||
this.oldScoutMsg = msg;
|
||||
this.inEditScoutMsg = false;
|
||||
} catch (e) {
|
||||
if (isString(e)) {
|
||||
alert(e);
|
||||
}
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -7,6 +7,7 @@
|
||||
<div class="row gx-1">
|
||||
<div class="col d-grid">
|
||||
<b-dropdown left text="턴 선택">
|
||||
<b-dropdown-item @click="selectTurn()">해제</b-dropdown-item>
|
||||
<b-dropdown-item @click="selectAll(true)">모든턴</b-dropdown-item>
|
||||
<b-dropdown-item @click="selectStep(0, 2)">홀수턴</b-dropdown-item>
|
||||
<b-dropdown-item @click="selectStep(1, 2)">짝수턴</b-dropdown-item>
|
||||
@@ -50,17 +51,29 @@
|
||||
</div>
|
||||
|
||||
<div class="commandTable">
|
||||
<template
|
||||
v-for="(turnObj, turnIdx) in reservedCommandList.slice(
|
||||
0,
|
||||
Math.min(maxTurn, viewMaxTurn)
|
||||
)"
|
||||
:key="turnIdx"
|
||||
<DragSelect
|
||||
:style="rowGridStyle"
|
||||
attribute="turnIdx"
|
||||
@dragStart="isDragToggle = true"
|
||||
@dragDone="
|
||||
isDragToggle = false;
|
||||
toggleTurn(...$event);
|
||||
"
|
||||
v-slot="{ selected }"
|
||||
>
|
||||
<div class="idx_pad center d-grid" @click="toggleTurn(turnIdx)">
|
||||
<div
|
||||
v-for="(turnObj, turnIdx) in reservedCommandList.slice(
|
||||
0,
|
||||
viewMaxTurn
|
||||
)"
|
||||
:turnIdx="turnIdx"
|
||||
:key="turnIdx"
|
||||
class="idx_pad center d-grid"
|
||||
>
|
||||
<b-button
|
||||
size="sm"
|
||||
:variant="
|
||||
(isDragToggle && selected.has(`${turnIdx}`))?'light':
|
||||
turnList.has(turnIdx)
|
||||
? 'info'
|
||||
: turnList.size == 0 && prevTurnList.has(turnIdx)
|
||||
@@ -70,10 +83,26 @@
|
||||
>{{ turnIdx + 1 }}</b-button
|
||||
>
|
||||
</div>
|
||||
</DragSelect>
|
||||
<DragSelect
|
||||
:style="rowGridStyle"
|
||||
attribute="turnIdx"
|
||||
@dragStart="isDragSingle = true"
|
||||
@dragDone="
|
||||
isDragSingle = false;
|
||||
selectTurn(...$event);
|
||||
"
|
||||
v-slot="{ selected }"
|
||||
>
|
||||
<div
|
||||
@click="selectTurn(turnIdx)"
|
||||
v-for="(turnObj, turnIdx) in reservedCommandList.slice(
|
||||
0,
|
||||
viewMaxTurn
|
||||
)"
|
||||
:key="turnIdx"
|
||||
height="24"
|
||||
class="month_pad center"
|
||||
:turnIdx="turnIdx"
|
||||
:style="{
|
||||
'white-space': 'nowrap',
|
||||
'font-size': `${Math.min(
|
||||
@@ -81,18 +110,41 @@
|
||||
(75 / (`${turnObj.year ?? 1}`.length + 8)) * 1.8
|
||||
)}px`,
|
||||
overflow: 'hidden',
|
||||
color:
|
||||
isDragSingle && selected.has(`${turnIdx}`) ? 'cyan' : undefined,
|
||||
}"
|
||||
>
|
||||
{{ turnObj.year ? `${turnObj.year}年` : "" }}
|
||||
{{ turnObj.month ? `${turnObj.month}月` : "" }}
|
||||
</div>
|
||||
</DragSelect>
|
||||
<div :style="rowGridStyle">
|
||||
<div
|
||||
v-for="(turnObj, turnIdx) in reservedCommandList.slice(
|
||||
0,
|
||||
viewMaxTurn
|
||||
)"
|
||||
:key="turnIdx"
|
||||
class="time_pad center"
|
||||
style="background-color: black; white-space: nowrap; overflow: hidden"
|
||||
:style="{
|
||||
backgroundColor: 'black',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
}"
|
||||
>
|
||||
{{ turnObj.time }}
|
||||
</div>
|
||||
<div class="turn_pad center">
|
||||
</div>
|
||||
<div :style="rowGridStyle">
|
||||
<div
|
||||
v-for="(turnObj, turnIdx) in reservedCommandList.slice(
|
||||
0,
|
||||
viewMaxTurn
|
||||
)"
|
||||
:key="turnIdx"
|
||||
class="turn_pad center"
|
||||
@click="chooseCommand(turnObj.action)"
|
||||
>
|
||||
<span
|
||||
class="turn_text"
|
||||
:style="turnObj.style"
|
||||
@@ -101,7 +153,7 @@
|
||||
v-html="turnObj.brief"
|
||||
></span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row gx-1">
|
||||
<div class="col d-grid">
|
||||
@@ -200,16 +252,18 @@
|
||||
<script lang="ts">
|
||||
import addMilliseconds from "date-fns/esm/addMilliseconds";
|
||||
import addMinutes from "date-fns/esm/addMinutes";
|
||||
import { range } from "lodash";
|
||||
import { isString, range } from "lodash";
|
||||
import { stringifyUrl } from "query-string";
|
||||
import { defineComponent } from "vue";
|
||||
import { defineComponent, ref, watch } from "vue";
|
||||
import { formatTime } from "@util/formatTime";
|
||||
import { joinYearMonth } from "@util/joinYearMonth";
|
||||
import { mb_strwidth } from "@util/mb_strwidth";
|
||||
import { parseTime } from "@util/parseTime";
|
||||
import { parseYearMonth } from "@util/parseYearMonth";
|
||||
import { sammoAPI } from "@util/sammoAPI";
|
||||
import { convertSearch초성 } from "./util/convertSearch초성";
|
||||
import DragSelect from "@/components/DragSelect.vue";
|
||||
import { SammoAPI } from "./SammoAPI";
|
||||
|
||||
type commandItem = {
|
||||
value: string;
|
||||
title: string;
|
||||
@@ -286,7 +340,9 @@ const searchModeKey = `sammo_searchModeOn`;
|
||||
|
||||
export default defineComponent({
|
||||
name: "PartialReservedCommand",
|
||||
|
||||
components: {
|
||||
DragSelect,
|
||||
},
|
||||
methods: {
|
||||
updateNow() {
|
||||
const serverNow = addMilliseconds(new Date(), this.timeDiff);
|
||||
@@ -295,16 +351,27 @@ export default defineComponent({
|
||||
this.updateNow();
|
||||
}, 1000 - serverNow.getMilliseconds());
|
||||
},
|
||||
toggleTurn(turnIdx: number) {
|
||||
if (this.turnList.has(turnIdx)) {
|
||||
this.turnList.delete(turnIdx);
|
||||
} else {
|
||||
this.turnList.add(turnIdx);
|
||||
toggleTurn(...turnList: number[] | string[]) {
|
||||
for (let turnIdx of turnList) {
|
||||
if (isString(turnIdx)) {
|
||||
turnIdx = parseInt(turnIdx);
|
||||
}
|
||||
if (this.turnList.has(turnIdx)) {
|
||||
this.turnList.delete(turnIdx);
|
||||
} else {
|
||||
this.turnList.add(turnIdx);
|
||||
}
|
||||
}
|
||||
},
|
||||
selectTurn(turnIdx: number) {
|
||||
selectTurn(...turnList: number[] | string[]) {
|
||||
this.turnList.clear();
|
||||
this.turnList.add(turnIdx);
|
||||
for (const turnIdx of turnList) {
|
||||
if (isString(turnIdx)) {
|
||||
this.turnList.add(parseInt(turnIdx));
|
||||
} else {
|
||||
this.turnList.add(turnIdx);
|
||||
}
|
||||
}
|
||||
},
|
||||
selectAll(e: Event | true) {
|
||||
//NOTE: split 구현에 버그가 있어서, 수동으로 구분해야함
|
||||
@@ -337,7 +404,7 @@ export default defineComponent({
|
||||
},
|
||||
async repeatGeneralCommand(amount: number) {
|
||||
try {
|
||||
await sammoAPI(`Command/RepeatCommand`, { amount });
|
||||
await SammoAPI.Command.RepeatCommand({ amount });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
@@ -347,7 +414,7 @@ export default defineComponent({
|
||||
},
|
||||
async pushGeneralCommand(amount: number) {
|
||||
try {
|
||||
await sammoAPI("Command/PushCommand", { amount });
|
||||
await SammoAPI.Command.PushCommand({ amount });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
@@ -372,7 +439,7 @@ export default defineComponent({
|
||||
async reloadCommandList() {
|
||||
let result: ReservedCommandResponse;
|
||||
try {
|
||||
result = await sammoAPI("Command/GetReservedCommand");
|
||||
result = await SammoAPI.Command.GetReservedCommand();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
@@ -457,7 +524,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
try {
|
||||
await sammoAPI("Command/ReserveCommand", {
|
||||
await SammoAPI.Command.ReserveCommand({
|
||||
turnList,
|
||||
action: commandName,
|
||||
});
|
||||
@@ -481,6 +548,9 @@ export default defineComponent({
|
||||
this.searchModeOn = searchModeOn;
|
||||
localStorage.setItem(searchModeKey, searchModeOn ? "1" : "0");
|
||||
},
|
||||
chooseCommand(val: string){
|
||||
this.selectedCommand = this.invCommandMap[val];
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const serverNowObj = parseTime(serverNow);
|
||||
@@ -519,8 +589,7 @@ export default defineComponent({
|
||||
|
||||
return {
|
||||
maxTurn,
|
||||
flippedMaxTurn: 15,
|
||||
viewMaxTurn: 15,
|
||||
|
||||
maxPushTurn,
|
||||
commandList,
|
||||
serverNow: formatTime(serverNowObj, "HH:mm:ss"),
|
||||
@@ -533,6 +602,37 @@ export default defineComponent({
|
||||
searchModeOn,
|
||||
};
|
||||
},
|
||||
setup() {
|
||||
const flippedMaxTurn = 15;
|
||||
const viewMaxTurn = ref(flippedMaxTurn);
|
||||
const rowGridStyle = ref({
|
||||
display: "grid",
|
||||
gridTemplateRows: `repeat(${viewMaxTurn.value}, 29.4px)`,
|
||||
});
|
||||
|
||||
watch(viewMaxTurn, (val) => {
|
||||
rowGridStyle.value.gridTemplateRows = `repeat(${val}, 29.4px)`;
|
||||
});
|
||||
|
||||
const isDragSingle = ref(false);
|
||||
const isDragToggle = ref(false);
|
||||
|
||||
const invCommandMap: Record<string, commandItem> = {};
|
||||
for(const category of commandList){
|
||||
for(const command of category.values){
|
||||
invCommandMap[command.value] = command;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
isDragSingle,
|
||||
isDragToggle,
|
||||
flippedMaxTurn,
|
||||
viewMaxTurn,
|
||||
rowGridStyle,
|
||||
invCommandMap,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
void this.reloadCommandList();
|
||||
},
|
||||
@@ -618,7 +718,7 @@ export default defineComponent({
|
||||
background-color: $nbase2color;
|
||||
}
|
||||
|
||||
.turn_pad:nth-child(8n) {
|
||||
.turn_pad:nth-child(2n) {
|
||||
background-color: color.adjust($nbase2color, $lightness: -5%);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { InvalidResponse } from "./defs";
|
||||
import { APIPathGen } from "./util/APIPathGen";
|
||||
import { callSammoAPI, ValidResponse } from "./util/callSammoAPI";
|
||||
export type { ValidResponse, InvalidResponse };
|
||||
|
||||
async function done<ResultType extends ValidResponse>(args?: Record<string, unknown>): Promise<ResultType>;
|
||||
async function done<ResultType extends ValidResponse>(args: Record<string, unknown> | undefined, returnError: false): Promise<ResultType>;
|
||||
async function done<ResultType extends ValidResponse, ErrorType extends InvalidResponse>(args: Record<string, unknown> | undefined, returnError: true): Promise<ResultType | ErrorType>;
|
||||
|
||||
async function done<ResultType extends ValidResponse, ErrorType extends InvalidResponse>(args?: Record<string, unknown>, returnError = false): Promise<ResultType | ErrorType> {
|
||||
console.error(`Can't directly call. ${args}, ${returnError}. Use auto-generated path API.`);
|
||||
return callSammoAPI<ResultType, ErrorType>([], args, true);
|
||||
}
|
||||
|
||||
const apiRealPath = {
|
||||
Command: {
|
||||
GetReservedCommand: done,
|
||||
PushCommand: done,
|
||||
RepeatCommand: done,
|
||||
ReserveCommand: done,
|
||||
},
|
||||
General: {
|
||||
Join: done,
|
||||
},
|
||||
InheritAction: {
|
||||
BuyHiddenBuff: done,
|
||||
BuyRandomUnique: done,
|
||||
BuySpecificUnique: done,
|
||||
ResetSpecialWar: done,
|
||||
ResetTurnTime: done,
|
||||
SetNextSpecialWar: done,
|
||||
},
|
||||
Misc: { UploadImage: done },
|
||||
NationCommand: {
|
||||
GetReservedCommand: done,
|
||||
PushCommand: done,
|
||||
RepeatCommand: done,
|
||||
ReserveCommand: done,
|
||||
},
|
||||
Nation: {
|
||||
SetNotice: done,
|
||||
SetScoutMsg: done,
|
||||
SetBill: done,
|
||||
SetRate: done,
|
||||
SetSecretLimit: done,
|
||||
SetBlockWar: done,
|
||||
SetBlockScout: done,
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const SammoAPI = APIPathGen<typeof done, typeof apiRealPath>(apiRealPath, (path: string[]) => {
|
||||
return (args?: Record<string, unknown>, returnError?: boolean) => {
|
||||
if (returnError) {
|
||||
return callSammoAPI(path.join('/'), args, true);
|
||||
}
|
||||
return callSammoAPI(path.join('/'), args);
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
import { InvalidResponse } from "./defs";
|
||||
import { APIPathGen } from "./util/APIPathGen";
|
||||
import { callSammoAPI, ValidResponse } from "./util/callSammoAPI";
|
||||
export type { ValidResponse, InvalidResponse };
|
||||
|
||||
async function done<ResultType extends ValidResponse>(args?: Record<string, unknown>): Promise<ResultType>;
|
||||
async function done<ResultType extends ValidResponse>(args: Record<string, unknown> | undefined, returnError: false): Promise<ResultType>;
|
||||
async function done<ResultType extends ValidResponse, ErrorType extends InvalidResponse>(args: Record<string, unknown> | undefined, returnError: true): Promise<ResultType | ErrorType>;
|
||||
|
||||
async function done<ResultType extends ValidResponse, ErrorType extends InvalidResponse>(args?: Record<string, unknown>, returnError = false): Promise<ResultType | ErrorType>{
|
||||
console.error(`Can't directly call. ${args}, ${returnError}. Use auto-generated path API.`);
|
||||
return callSammoAPI<ResultType, ErrorType>([], args, true);
|
||||
}
|
||||
|
||||
const apiRealPath = {
|
||||
Login: {
|
||||
LoginByID: done,
|
||||
LoginByToken: done,
|
||||
ReqNonce: done,
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const SammoRootAPI = APIPathGen<typeof done, typeof apiRealPath>(apiRealPath, (path: string[]) => {
|
||||
return (args?: Record<string, unknown>, returnError?: boolean) => {
|
||||
if (returnError) {
|
||||
return callSammoAPI(path.join('/'), args, true);
|
||||
}
|
||||
return callSammoAPI(path.join('/'), args);
|
||||
};
|
||||
});
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"ingame": {
|
||||
"chiefCenter": "chiefCenter.ts",
|
||||
"troop": "troop.ts",
|
||||
"map": "map.ts",
|
||||
"install_db": "install_db.ts",
|
||||
@@ -27,7 +26,7 @@
|
||||
"v_NPCControl": "v_NPCControl.ts",
|
||||
"v_join": "v_join.ts",
|
||||
"v_main": "v_main.ts",
|
||||
"v_dipcenter": "v_dipcenter.ts",
|
||||
"v_nationStratFinan": "v_nationStratFinan.ts",
|
||||
"v_processing": "v_processing.ts"
|
||||
}
|
||||
}
|
||||
@@ -1,264 +0,0 @@
|
||||
import axios from 'axios';
|
||||
import $ from 'jquery';
|
||||
import { range } from 'lodash';
|
||||
import { addMinutes } from 'date-fns';
|
||||
import { errUnknown, getNpcColor } from '@/common_legacy';
|
||||
import { InvalidResponse } from '@/defs';
|
||||
import { unwrap } from "@util/unwrap";
|
||||
import { convertFormData } from '@util/convertFormData';
|
||||
import { unwrap_any } from "@util/unwrap_any";
|
||||
import { parseTime } from '@util/parseTime';
|
||||
import { formatTime } from '@util/formatTime';
|
||||
import { stringifyUrl } from 'query-string';
|
||||
import { setAxiosXMLHttpRequest } from '@util/setAxiosXMLHttpRequest';
|
||||
|
||||
setAxiosXMLHttpRequest();
|
||||
|
||||
declare const maxChiefTurn: number;
|
||||
|
||||
type TurnDOMObj = {
|
||||
turnTime: JQuery<HTMLElement>,
|
||||
turnPad: JQuery<HTMLElement>,
|
||||
turnText: JQuery<HTMLElement>
|
||||
};
|
||||
|
||||
type TableObj = {
|
||||
btns: JQuery<HTMLElement>;
|
||||
[key: number]: {
|
||||
officerLevelText: JQuery<HTMLElement>,
|
||||
name: JQuery<HTMLElement>,
|
||||
turn: TurnDOMObj[],
|
||||
}
|
||||
}
|
||||
|
||||
type ChiefResponse = InvalidResponse | {
|
||||
result: true,
|
||||
date: string,
|
||||
nationTurnBrief: {
|
||||
name: string | null,
|
||||
turnTime: string | null,
|
||||
officerLevelText: string,
|
||||
npcType: number,
|
||||
turn: string
|
||||
}[],
|
||||
isChief: boolean,
|
||||
turnTerm: number
|
||||
}
|
||||
|
||||
let filledChiefList: Record<number, boolean> = {};
|
||||
let chiefTableObj: TableObj = undefined as unknown as TableObj;//TODO: 매우 지저분하다. class 기반으로 고치던가 할 것
|
||||
|
||||
/*
|
||||
function clearTable() {
|
||||
$('.chiefLevelText').html('-');
|
||||
$('.chiefTurnTime, .chiefTurnText, .chiefName').html(' ');
|
||||
}
|
||||
*/
|
||||
|
||||
function genChiefTableObj(): TableObj {
|
||||
const objTable: TableObj = {
|
||||
btns: $('#turnPush,#turnPull,#setCommand')
|
||||
};
|
||||
|
||||
for (const chiefIdx of range(5, 13)) {
|
||||
const $plate = $(`#chief_${chiefIdx}`);
|
||||
const $officerLevelText = $plate.find('.chiefLevelText');
|
||||
const $name = $plate.find('.chiefName');
|
||||
const turn: TurnDOMObj[] = [];
|
||||
for (const turnIdx of range(maxChiefTurn)) {
|
||||
const $turn = $plate.find(`.turn${turnIdx}`);
|
||||
const $turnTime = $turn.find('.chiefTurnTime');
|
||||
const $turnPad = $turn.find('.chiefTurnPad');
|
||||
const $turnText = $turn.find('.chiefTurnText');
|
||||
turn.push({ turnTime: $turnTime, turnPad: $turnPad, turnText: $turnText });
|
||||
}
|
||||
objTable[chiefIdx] = {
|
||||
officerLevelText: $officerLevelText,
|
||||
name: $name,
|
||||
turn: turn
|
||||
};
|
||||
}
|
||||
|
||||
return objTable;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function clearChief(chiefIdx: number): void {
|
||||
const $plate = $(`#chief_${chiefIdx}`);
|
||||
$plate.find('.chiefLevelText').html('-');
|
||||
$plate.find('.chiefTurnTime, .chiefTurnText, .chiefName').html(' ');
|
||||
}
|
||||
|
||||
async function reloadTable() {
|
||||
|
||||
const data: ChiefResponse = await (async () => {
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_getChiefTurn.php',
|
||||
responseType: 'json'
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
errUnknown();
|
||||
}
|
||||
})();
|
||||
|
||||
if (!data.result) {
|
||||
alert(data.reason);
|
||||
return;
|
||||
}
|
||||
const turnTerm = data.turnTerm;
|
||||
const tmpFilledChiefList: Record<number, boolean> = {};
|
||||
|
||||
if (data.isChief) {
|
||||
chiefTableObj.btns.css('visibility', 'visible');
|
||||
}
|
||||
else {
|
||||
chiefTableObj.btns.css('visibility', 'hidden');
|
||||
}
|
||||
$.each(data.nationTurnBrief, function (chiefIdx, chiefInfo) {
|
||||
tmpFilledChiefList[chiefIdx] = true;
|
||||
filledChiefList[chiefIdx] = true;
|
||||
|
||||
const plateObj = chiefTableObj[chiefIdx];
|
||||
if (chiefInfo.name) {
|
||||
const $name = $(`<span>${chiefInfo.name}</span>`);
|
||||
const nameColor = getNpcColor(chiefInfo.npcType);
|
||||
if (nameColor) {
|
||||
$name.css('color', nameColor);
|
||||
}
|
||||
plateObj.name.empty().append($name);
|
||||
}
|
||||
else {
|
||||
plateObj.name.html('');
|
||||
}
|
||||
|
||||
plateObj.officerLevelText.text(chiefInfo.officerLevelText);
|
||||
|
||||
let turnTimeObj: Date | undefined;
|
||||
|
||||
if (chiefInfo.turnTime) {
|
||||
turnTimeObj = parseTime(chiefInfo.turnTime);
|
||||
}
|
||||
|
||||
const turnList = plateObj.turn;
|
||||
$.each(chiefInfo.turn, function (turnIdx, turnText) {
|
||||
if (turnTimeObj) {
|
||||
turnList[turnIdx].turnTime.text(formatTime(turnTimeObj, 'HH:mm'));
|
||||
}
|
||||
else {
|
||||
turnList[turnIdx].turnTime.text('');
|
||||
}
|
||||
|
||||
turnList[turnIdx].turnText.html(turnText).css('font-size', '14px');
|
||||
const oWidth = unwrap(turnList[turnIdx].turnPad.innerWidth());
|
||||
const iWidth = unwrap(turnList[turnIdx].turnText.outerWidth());
|
||||
if (iWidth > oWidth * 0.95) {
|
||||
const newFontSize = 14 * oWidth / iWidth * 0.9;
|
||||
turnList[turnIdx].turnText.css('font-size', `${newFontSize}px`);
|
||||
}
|
||||
if (turnTimeObj) {
|
||||
turnTimeObj = addMinutes(turnTimeObj, turnTerm);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
for (const idx of range(5, 13)) {
|
||||
if (idx in tmpFilledChiefList) {
|
||||
continue;
|
||||
}
|
||||
if (idx in filledChiefList) {
|
||||
clearChief(idx);
|
||||
}
|
||||
}
|
||||
filledChiefList = tmpFilledChiefList;
|
||||
}
|
||||
|
||||
async function reserveTurn(turnList: number[], command: string) {
|
||||
console.log(turnList, command);
|
||||
try {
|
||||
|
||||
const response = await axios({
|
||||
url: 'j_set_chief_command.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
data: convertFormData({
|
||||
turnList,
|
||||
action: command
|
||||
})
|
||||
});
|
||||
|
||||
const data: InvalidResponse = response.data;
|
||||
|
||||
if (!data.result) {
|
||||
alert(data.reason);
|
||||
}
|
||||
await reloadTable();
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
errUnknown();
|
||||
}
|
||||
}
|
||||
|
||||
async function pushTurn(turnCnt: number) {
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_chief_turn.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
data: convertFormData({
|
||||
amount: turnCnt
|
||||
})
|
||||
});
|
||||
const data = response.data;
|
||||
if (!data.result) {
|
||||
alert(data.reason);
|
||||
}
|
||||
await reloadTable();
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
errUnknown();
|
||||
}
|
||||
}
|
||||
|
||||
$(function ($) {
|
||||
|
||||
chiefTableObj = genChiefTableObj();
|
||||
void reloadTable();
|
||||
$('#reloadTable').on('click', reloadTable);
|
||||
$('#setCommand').on('click', function () {
|
||||
const turnList = unwrap_any<string[]>($('#chiefTurnSelector').val()).map(function (v) { return parseInt(v); });
|
||||
const $command = $('#chiefCommandList option:selected');
|
||||
if ($command.data('reqarg')) {
|
||||
document.location.href = stringifyUrl({
|
||||
url: 'v_processing.php',
|
||||
query: {
|
||||
command: unwrap_any<string>($command.val()),
|
||||
turnList: turnList.join('_'),
|
||||
is_chief: true
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
void reserveTurn(turnList, unwrap_any<string>($command.val()));
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#turnPush').on('click', function () {
|
||||
void pushTurn(1);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#turnPull').on('click', function () {
|
||||
void pushTurn(-1);
|
||||
return false;
|
||||
});
|
||||
|
||||
})
|
||||
@@ -1,53 +1,49 @@
|
||||
<template>
|
||||
<table class="articleFrame bg0">
|
||||
<thead>
|
||||
<tr class="bg1">
|
||||
<th class="authorName">{{ article.author }}</th>
|
||||
<th class="articleTitle">{{ article.title }}</th>
|
||||
<th class="date">{{ article.date }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<img
|
||||
class="authorIcon generalIcon"
|
||||
width="64"
|
||||
height="64"
|
||||
:src="article.author_icon"
|
||||
/>
|
||||
</td>
|
||||
<td class="text" colspan="2">{{ article.text }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody class="commentList">
|
||||
<div class="articleFrame bg0">
|
||||
<div class="bg1 row gx-0">
|
||||
<div class="authorName center">{{ article.author }}</div>
|
||||
<div class="col articleTitle center">{{ article.title }}</div>
|
||||
<div class="col-2 col-md-1 date center">{{ article.date.slice(5, 16) }}</div>
|
||||
</div>
|
||||
<div class="row gx-0 s-border-b">
|
||||
<div class="col-2 col-md-1 authorIcon center">
|
||||
<img
|
||||
class="generalIcon"
|
||||
width="64"
|
||||
height="64"
|
||||
:src="article.author_icon"
|
||||
/>
|
||||
</div>
|
||||
<div class="col text">{{ article.text }}</div>
|
||||
</div>
|
||||
<div class="commentList">
|
||||
<board-comment
|
||||
v-for="comment in article.comment"
|
||||
:key="comment.no"
|
||||
:comment="comment"
|
||||
/>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td class="bg2 inputCommentHeader">댓글 달기</td>
|
||||
<td>
|
||||
<input
|
||||
class="commentText"
|
||||
type="text"
|
||||
maxlength="250"
|
||||
placeholder="새 댓글 내용"
|
||||
v-model.trim="newCommentText"
|
||||
@keyup.enter="submitComment"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="submitComment" @click="submitComment">
|
||||
등록
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<div class="row gx-0">
|
||||
<div class="bg2 inputCommentHeader center d-grid">
|
||||
<div class="align-self-center">댓글 달기</div>
|
||||
</div>
|
||||
<div class="col d-grid">
|
||||
<input
|
||||
class="commentText"
|
||||
type="text"
|
||||
maxlength="250"
|
||||
placeholder="새 댓글 내용"
|
||||
v-model.trim="newCommentText"
|
||||
@keyup.enter="submitComment"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-2 col-md-1 d-grid">
|
||||
<b-button class="submitComment" @click="submitComment" size="sm"
|
||||
>등록</b-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { BoardArticleItem } from "@/PageBoard.vue";
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<template>
|
||||
<tr class="comment">
|
||||
<th class="author">{{ comment.author }}</th>
|
||||
<td class="text">{{ comment.text }}</td>
|
||||
<td class="date">{{ comment.date }}</td>
|
||||
<!-- 삭제도 나중에 추가? -->
|
||||
</tr>
|
||||
<div class="row gx-0 comment s-border-b">
|
||||
<div class="authorName center d-grid"><div class="align-self-center">{{ comment.author }}</div></div>
|
||||
<div class="col text">{{ comment.text }}</div>
|
||||
<div class="col-2 col-md-1 date center d-grid"><div class="align-self-center">{{ comment.date.slice(5, 16) }}</div></div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { BoardCommentItem } from "@/PageBoard.vue";
|
||||
|
||||
@@ -12,7 +12,6 @@ import { defineComponent, PropType } from "vue";
|
||||
import "@scss/game_bg.scss";
|
||||
|
||||
export default defineComponent({
|
||||
name: "TopBackBar",
|
||||
methods: {
|
||||
back(){
|
||||
if(this.type === 'normal'){
|
||||
@@ -28,10 +27,6 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String as PropType<"normal"|"chief"|"close">,
|
||||
default: "normal",
|
||||
|
||||
@@ -1,22 +1,54 @@
|
||||
<template>
|
||||
<div class="commandPad chiefReservedCommand">
|
||||
<div class="commandTable">
|
||||
<template
|
||||
v-for="(turnObj, turnIdx) in reservedCommandList"
|
||||
:key="turnIdx"
|
||||
<DragSelect
|
||||
:style="rowGridStyle"
|
||||
attribute="turnIdx"
|
||||
@dragStart="isDragSingle = true"
|
||||
@dragDone="
|
||||
isDragSingle = false;
|
||||
selectTurn(...$event);
|
||||
"
|
||||
v-slot="{ selected }"
|
||||
>
|
||||
<div
|
||||
@click="selectTurn(turnIdx)"
|
||||
v-for="(turnObj, turnIdx) in reservedCommandList"
|
||||
:key="turnIdx"
|
||||
:turnIdx="turnIdx"
|
||||
class="time_pad center f_tnum"
|
||||
style="background-color: black; white-space: nowrap; overflow: hidden"
|
||||
:style="{
|
||||
backgroundColor: 'black',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
color:
|
||||
isDragSingle && selected.has(`${turnIdx}`) ? 'cyan' : undefined,
|
||||
}"
|
||||
>
|
||||
{{ turnObj.time }}
|
||||
</div>
|
||||
<div class="idx_pad center d-grid" @click="toggleTurn(turnIdx)">
|
||||
</DragSelect>
|
||||
<DragSelect
|
||||
:style="rowGridStyle"
|
||||
attribute="turnIdx"
|
||||
@dragStart="isDragToggle = true"
|
||||
@dragDone="
|
||||
isDragToggle = false;
|
||||
toggleTurn(...$event);
|
||||
"
|
||||
v-slot="{ selected }"
|
||||
>
|
||||
<div
|
||||
v-for="(turnObj, turnIdx) in reservedCommandList"
|
||||
:key="turnIdx"
|
||||
:turnIdx="turnIdx"
|
||||
class="idx_pad center d-grid"
|
||||
>
|
||||
<b-button
|
||||
size="sm"
|
||||
:variant="
|
||||
turnList.has(turnIdx)
|
||||
isDragToggle && selected.has(`${turnIdx}`)
|
||||
? 'light'
|
||||
: turnList.has(turnIdx)
|
||||
? 'info'
|
||||
: turnList.size == 0 && prevTurnList.has(turnIdx)
|
||||
? 'success'
|
||||
@@ -25,7 +57,14 @@
|
||||
>{{ turnIdx + 1 }}</b-button
|
||||
>
|
||||
</div>
|
||||
<div class="turn_pad center">
|
||||
</DragSelect>
|
||||
<div :style="rowGridStyle">
|
||||
<div
|
||||
v-for="(turnObj, turnIdx) in reservedCommandList"
|
||||
:key="turnIdx"
|
||||
class="turn_pad center"
|
||||
@click="chooseCommand(turnObj.action)"
|
||||
>
|
||||
<span
|
||||
class="turn_text"
|
||||
:style="turnObj.style"
|
||||
@@ -34,7 +73,7 @@
|
||||
v-html="turnObj.brief"
|
||||
></span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row gx-0">
|
||||
<div class="col-2 d-grid">
|
||||
@@ -112,9 +151,12 @@ import { joinYearMonth } from "@util/joinYearMonth";
|
||||
import { mb_strwidth } from "@util/mb_strwidth";
|
||||
import { parseTime } from "@util/parseTime";
|
||||
import { parseYearMonth } from "@util/parseYearMonth";
|
||||
import { sammoAPI } from "@util/sammoAPI";
|
||||
import { convertSearch초성 } from "@util/convertSearch초성";
|
||||
import VueTypes from "vue-types";
|
||||
import DragSelect from "@/components/DragSelect.vue";
|
||||
import { isString } from "lodash";
|
||||
import { SammoAPI } from "@/SammoAPI";
|
||||
|
||||
type commandItem = {
|
||||
value: string;
|
||||
title: string;
|
||||
@@ -147,6 +189,9 @@ const searchModeKey = `sammo_searchModeOn`;
|
||||
|
||||
export default defineComponent({
|
||||
name: "NationReservedCommand",
|
||||
components: {
|
||||
DragSelect
|
||||
},
|
||||
props: {
|
||||
maxTurn: VueTypes.integer.isRequired,
|
||||
maxPushTurn: VueTypes.integer.isRequired,
|
||||
@@ -218,17 +263,28 @@ export default defineComponent({
|
||||
this.updateCommandList();
|
||||
}, 1);
|
||||
},
|
||||
toggleTurn(val: number) {
|
||||
if (this.turnList.has(val)) {
|
||||
this.turnList.delete(val);
|
||||
} else {
|
||||
this.turnList.add(val);
|
||||
toggleTurn(...turnList: number[] | string[]) {
|
||||
for (let turnIdx of turnList) {
|
||||
if (isString(turnIdx)) {
|
||||
turnIdx = parseInt(turnIdx);
|
||||
}
|
||||
if (this.turnList.has(turnIdx)) {
|
||||
this.turnList.delete(turnIdx);
|
||||
} else {
|
||||
this.turnList.add(turnIdx);
|
||||
}
|
||||
}
|
||||
this.$emit("update:selectedTurn", this.turnList);
|
||||
},
|
||||
selectTurn(val: number) {
|
||||
selectTurn(...turnList: number[] | string[]) {
|
||||
this.turnList.clear();
|
||||
this.turnList.add(val);
|
||||
for (const turnIdx of turnList) {
|
||||
if (isString(turnIdx)) {
|
||||
this.turnList.add(parseInt(turnIdx));
|
||||
} else {
|
||||
this.turnList.add(turnIdx);
|
||||
}
|
||||
}
|
||||
this.$emit("update:selectedTurn", this.turnList);
|
||||
},
|
||||
updateCommandList() {
|
||||
@@ -319,7 +375,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
try {
|
||||
await sammoAPI("NationCommand/ReserveCommand", {
|
||||
await SammoAPI.NationCommand.ReserveCommand({
|
||||
turnList,
|
||||
action: commandName,
|
||||
});
|
||||
@@ -343,6 +399,9 @@ export default defineComponent({
|
||||
this.searchModeOn = searchModeOn;
|
||||
localStorage.setItem(searchModeKey, searchModeOn ? "1" : "0");
|
||||
},
|
||||
chooseCommand(val: string){
|
||||
this.selectedCommand = this.invCommandMap[val];
|
||||
},
|
||||
},
|
||||
data() {
|
||||
const serverNowObj = parseTime(this.date);
|
||||
@@ -372,6 +431,13 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
const invCommandMap: Record<string, commandItem> = {};
|
||||
for(const category of this.commandList){
|
||||
for(const command of category.values){
|
||||
invCommandMap[command.value] = command;
|
||||
}
|
||||
}
|
||||
|
||||
const searchModeOn = (localStorage.getItem(searchModeKey) ?? "0") != "0";
|
||||
|
||||
const emptyTurn: TurnObjWithTime[] = Array.from<TurnObjWithTime>({
|
||||
@@ -387,6 +453,11 @@ export default defineComponent({
|
||||
|
||||
const prevTurnList = new Set([0]);
|
||||
|
||||
const rowGridStyle = {
|
||||
display: "grid",
|
||||
gridTemplateRows: `repeat(${this.maxTurn}, 30px)`,
|
||||
};
|
||||
|
||||
return {
|
||||
updated: false,
|
||||
listReqArgCommand,
|
||||
@@ -398,6 +469,10 @@ export default defineComponent({
|
||||
reservedCommandList: emptyTurn,
|
||||
autorun_limit: null as null | number,
|
||||
searchModeOn,
|
||||
rowGridStyle,
|
||||
isDragSingle: false,
|
||||
isDragToggle: false,
|
||||
invCommandMap,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
<template>
|
||||
<div
|
||||
ref="container"
|
||||
style="
|
||||
position: relative;
|
||||
user-select: none;
|
||||
overflow: hidden;
|
||||
touch-action: none;
|
||||
"
|
||||
>
|
||||
<slot :selected="intersected" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
/// https://github.com/andi23rosca/drag-select-vue/blob/master/src/DragSelect.vue
|
||||
import {
|
||||
defineComponent,
|
||||
ref,
|
||||
watch,
|
||||
onMounted,
|
||||
onBeforeUnmount,
|
||||
PropType,
|
||||
} from "vue";
|
||||
import VueTypes from "vue-types";
|
||||
|
||||
function getDimensions(p1: coord, p2: coord): rect {
|
||||
return {
|
||||
width: Math.abs(p1.x - p2.x),
|
||||
height: Math.abs(p1.y - p2.y),
|
||||
};
|
||||
}
|
||||
function collisionCheck(node1: DOMRect, node2: DOMRect): boolean {
|
||||
return (
|
||||
node1.left < node2.left + node2.width &&
|
||||
node1.left + node1.width > node2.left &&
|
||||
node1.top < node2.top + node2.height &&
|
||||
node1.top + node1.height > node2.top
|
||||
);
|
||||
}
|
||||
|
||||
type coord = { x: number; y: number };
|
||||
type rect = { width: number; height: number };
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
attribute: VueTypes.string.isRequired,
|
||||
color: {
|
||||
...VueTypes.string.def("#4299E1"),
|
||||
required: false,
|
||||
},
|
||||
opacity: {
|
||||
...VueTypes.number.def(0.7),
|
||||
required: false,
|
||||
},
|
||||
modelValue: {
|
||||
type: Object as PropType<Set<string>>,
|
||||
required: false,
|
||||
default: () => ref(new Set()),
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue", "dragDone", "dragStart"],
|
||||
setup(props, { emit }) {
|
||||
const intersected = ref<Set<string>>(props.modelValue);
|
||||
const container = ref<HTMLElement>();
|
||||
|
||||
watch(intersected, (val) => {
|
||||
emit("update:modelValue", val);
|
||||
});
|
||||
watch(props.modelValue, (val) => {
|
||||
if (intersected.value === val) {
|
||||
return;
|
||||
}
|
||||
intersected.value = val;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (!container.value) {
|
||||
console.error(`Container is not referenced.`);
|
||||
return;
|
||||
}
|
||||
const uContainer = container.value;
|
||||
let containerRect = uContainer.getBoundingClientRect();
|
||||
|
||||
function getCoords(e: MouseEvent | Touch): coord {
|
||||
return {
|
||||
x: e.clientX - containerRect.left,
|
||||
y: e.clientY - containerRect.top,
|
||||
};
|
||||
}
|
||||
let children: HTMLCollection;
|
||||
let box = document.createElement("div");
|
||||
box.setAttribute("data-drag-box-component", "");
|
||||
box.style.position = "absolute";
|
||||
box.style.backgroundColor = props.color;
|
||||
box.style.opacity = `${props.opacity}`;
|
||||
let start = { x: 0, y: 0 };
|
||||
let end = { x: 0, y: 0 };
|
||||
function intersection() {
|
||||
const rect = box.getBoundingClientRect();
|
||||
const localIntersected = new Set<string>();
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
if (collisionCheck(rect, children[i].getBoundingClientRect())) {
|
||||
const attr = children[i].getAttribute(props.attribute);
|
||||
if (children[i].hasAttribute(props.attribute)) {
|
||||
localIntersected.add(attr as string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let dismatch = false;
|
||||
for (const oldVal of intersected.value) {
|
||||
if (!localIntersected.has(oldVal)) {
|
||||
dismatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dismatch) {
|
||||
for (const newVal of localIntersected) {
|
||||
if (!intersected.value.has(newVal)) {
|
||||
dismatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dismatch) {
|
||||
intersected.value = localIntersected;
|
||||
}
|
||||
}
|
||||
function touchStart(e: TouchEvent) {
|
||||
e.preventDefault();
|
||||
startDrag(e.touches[0]);
|
||||
}
|
||||
function touchMove(e: TouchEvent) {
|
||||
e.preventDefault();
|
||||
drag(e.touches[0]);
|
||||
}
|
||||
|
||||
let isMine = false;
|
||||
function startDrag(e: MouseEvent | Touch) {
|
||||
containerRect = uContainer.getBoundingClientRect();
|
||||
children = uContainer.children;
|
||||
start = getCoords(e);
|
||||
end = start;
|
||||
document.addEventListener("mousemove", drag);
|
||||
document.addEventListener("touchmove", touchMove);
|
||||
box.style.top = start.y + "px";
|
||||
box.style.left = start.x + "px";
|
||||
uContainer.prepend(box);
|
||||
intersection();
|
||||
isMine = true;
|
||||
emit("dragStart");
|
||||
}
|
||||
function drag(e: MouseEvent | Touch) {
|
||||
end = getCoords(e);
|
||||
const dimensions = getDimensions(start, end);
|
||||
if (end.x < start.x) {
|
||||
box.style.left = end.x + "px";
|
||||
}
|
||||
if (end.y < start.y) {
|
||||
box.style.top = end.y + "px";
|
||||
}
|
||||
box.style.width = dimensions.width + "px";
|
||||
box.style.height = dimensions.height + "px";
|
||||
intersection();
|
||||
}
|
||||
function endDrag() {
|
||||
start = { x: 0, y: 0 };
|
||||
end = { x: 0, y: 0 };
|
||||
box.style.width = "0";
|
||||
box.style.height = "0";
|
||||
document.removeEventListener("mousemove", drag);
|
||||
document.removeEventListener("touchmove", touchMove);
|
||||
box.remove();
|
||||
if(isMine){
|
||||
emit("dragDone", intersected.value);
|
||||
}
|
||||
isMine = false;
|
||||
}
|
||||
|
||||
uContainer.addEventListener("mousedown", startDrag);
|
||||
uContainer.addEventListener("touchstart", touchStart);
|
||||
document.addEventListener("mouseup", endDrag);
|
||||
document.addEventListener("touchend", endDrag);
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
uContainer.removeEventListener("mousedown", startDrag);
|
||||
uContainer.removeEventListener("touchstart", touchStart);
|
||||
document.removeEventListener("mouseup", endDrag);
|
||||
document.removeEventListener("touchend", endDrag);
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
intersected,
|
||||
container,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -1,34 +1,34 @@
|
||||
<template>
|
||||
<CToaster class="z99" placement="top-end">
|
||||
<CToast
|
||||
v-for="(toast, index) in modelValue"
|
||||
:key="index"
|
||||
:delay="toast.delay??delay"
|
||||
>
|
||||
<CToastHeader
|
||||
:class="['text-white', `bg-${toast.type ?? 'primary'}`]"
|
||||
close
|
||||
>
|
||||
<span class="me-auto fw-bold">{{ toast.title }}</span>
|
||||
</CToastHeader>
|
||||
<CToastBody>
|
||||
{{ toast.content }}
|
||||
</CToastBody>
|
||||
</CToast>
|
||||
<CToaster class="my-toaster" placement="top-end" v-if="toasts.length > 0">
|
||||
<template v-for="(toast, index) in toasts" :key="index">
|
||||
<CToast :delay="toast.delay ?? delay">
|
||||
<CToastHeader :class="['text-white', `bg-${toast.type ?? 'primary'}`]">
|
||||
<span class="me-auto fw-bold">{{ toast.title }}</span>
|
||||
<CToastClose class="my-close" color="secondary" size="sm" />
|
||||
</CToastHeader>
|
||||
<CToastBody> {{ toast.content }} {{ toast.visible }} </CToastBody>
|
||||
</CToast>
|
||||
</template>
|
||||
</CToaster>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType } from "vue";
|
||||
import { defineComponent, PropType, ref, watch } from "vue";
|
||||
import { ToastType } from "@/defs";
|
||||
import { CToaster, CToast, CToastHeader, CToastBody } from "@coreui/vue/src/components/toast";
|
||||
import {
|
||||
CToaster,
|
||||
CToast,
|
||||
CToastHeader,
|
||||
CToastBody,
|
||||
CToastClose,
|
||||
} from "@coreui/vue/src/components/toast";
|
||||
|
||||
export default defineComponent({
|
||||
name: "MyToast",
|
||||
components: {
|
||||
CToaster,
|
||||
CToast,
|
||||
CToastHeader,
|
||||
CToastBody,
|
||||
CToastClose,
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
props: {
|
||||
@@ -37,15 +37,67 @@ export default defineComponent({
|
||||
required: true,
|
||||
},
|
||||
delay: {
|
||||
type: Number,
|
||||
required:false,
|
||||
default:5000,
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 5000,
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
let doneCnt = 0;
|
||||
const doneMap = new Map<ToastType, boolean>();
|
||||
let toasts = ref(props.modelValue);
|
||||
|
||||
function onClose(toast: ToastType) {
|
||||
const status = doneMap.get(toast);
|
||||
if (status === undefined) {
|
||||
return;
|
||||
}
|
||||
if (status) {
|
||||
return;
|
||||
}
|
||||
doneCnt -= 1;
|
||||
|
||||
if (doneCnt != 0) {
|
||||
doneMap.set(toast, true);
|
||||
return;
|
||||
}
|
||||
|
||||
doneMap.clear();
|
||||
toasts.value.length = 0;
|
||||
emit("update:modelValue", toasts);
|
||||
}
|
||||
|
||||
watch(props.modelValue, (values) => {
|
||||
for (const item of values) {
|
||||
if (!doneMap.has(item)) {
|
||||
doneMap.set(item, false);
|
||||
doneCnt += 1;
|
||||
|
||||
setTimeout(() => {
|
||||
onClose(item);
|
||||
}, (item.delay ?? props.delay) + 1000);
|
||||
}
|
||||
}
|
||||
if (toasts.value !== values) {
|
||||
toasts.value = values;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
onClose,
|
||||
toasts,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.z99 {
|
||||
<style>
|
||||
.my-toaster {
|
||||
z-index: 199;
|
||||
}
|
||||
.my-toaster .btn.btn-close.my-close,
|
||||
.my-toaster .btn.btn-close.my-close:hover,
|
||||
.my-toaster .btn.btn-close.my-close:active {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -223,7 +223,9 @@
|
||||
</b-button-group>
|
||||
<b-button-group class="mx-1">
|
||||
<b-button
|
||||
@click="editor.chain().focus().setImage({ align: 'float-left' }).run()"
|
||||
@click="
|
||||
editor.chain().focus().setImage({ align: 'float-left' }).run()
|
||||
"
|
||||
:class="{
|
||||
'is-active': editor.isActive('custom-image', {
|
||||
float: 'float-left',
|
||||
@@ -267,7 +269,9 @@
|
||||
><i class="bi bi-align-end"></i
|
||||
></b-button>
|
||||
<b-button
|
||||
@click="editor.chain().focus().setImage({ align: 'float-right' }).run()"
|
||||
@click="
|
||||
editor.chain().focus().setImage({ align: 'float-right' }).run()
|
||||
"
|
||||
:class="{
|
||||
'is-active': editor.isActive('custom-image', {
|
||||
float: 'float-right',
|
||||
@@ -280,7 +284,7 @@
|
||||
</b-button-group>
|
||||
</b-button-toolbar>
|
||||
</bubble-menu>
|
||||
<editor-content :editor="editor" />
|
||||
<editor-content :editor="editor" class="tiptap-editor" />
|
||||
<b-modal
|
||||
v-model="showImageModal"
|
||||
title="이미지 추가"
|
||||
@@ -351,9 +355,9 @@ import {
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { getBase64FromFileObject } from "@/util/getBase64FromFileObject";
|
||||
import { sammoAPI } from "@/util/sammoAPI";
|
||||
import { isObject, isString } from "lodash";
|
||||
import { AxiosError } from "axios";
|
||||
import { SammoAPI } from "@/SammoAPI";
|
||||
|
||||
const compoment = defineComponent({
|
||||
components: {
|
||||
@@ -367,6 +371,7 @@ const compoment = defineComponent({
|
||||
BDropdownItem,
|
||||
BDropdownDivider,
|
||||
},
|
||||
emits: ["ready", "update:modelValue"],
|
||||
methods: {
|
||||
chooseImage(e: Event) {
|
||||
const target = unwrap(e.target) as HTMLInputElement;
|
||||
@@ -403,7 +408,7 @@ const compoment = defineComponent({
|
||||
};
|
||||
try {
|
||||
const base64Binary = await getBase64FromFileObject(targetImage);
|
||||
imageResult = await sammoAPI("Misc/UploadImage", {
|
||||
imageResult = await SammoAPI.Misc.UploadImage({
|
||||
imageData: base64Binary,
|
||||
});
|
||||
} catch (e) {
|
||||
@@ -515,6 +520,9 @@ const compoment = defineComponent({
|
||||
onUpdate: () => {
|
||||
this.$emit("update:modelValue", this.editor.getHTML());
|
||||
},
|
||||
onCreate: () => {
|
||||
this.$emit("ready");
|
||||
}
|
||||
});
|
||||
this.editor = editor;
|
||||
},
|
||||
|
||||
+16
-3
@@ -163,11 +163,11 @@ export const NoneValue = 'None' as const;
|
||||
|
||||
export type Optional<Type> = {
|
||||
[Property in keyof Type]+?: Type[Property];
|
||||
};
|
||||
};
|
||||
|
||||
export type OptionalFull<Type> = {
|
||||
[Property in keyof Type]: Type[Property]|undefined;
|
||||
};
|
||||
[Property in keyof Type]: Type[Property] | undefined;
|
||||
};
|
||||
|
||||
export type commandItem = {
|
||||
value: string;
|
||||
@@ -210,3 +210,16 @@ export type ChiefResponse = {
|
||||
values: commandItem[];
|
||||
}[];
|
||||
};
|
||||
|
||||
|
||||
type diplomacyInfo = {
|
||||
name: string,
|
||||
color?: string,
|
||||
}
|
||||
export type diplomacyState = 0 | 1 | 2 | 7;
|
||||
export const diplomacyStateInfo: Record<diplomacyState, diplomacyInfo> = {
|
||||
0: { name: '교전', color: 'red' },
|
||||
1: { name: '선포중', color: 'magenta' },
|
||||
2: { name: '통상' },
|
||||
7: { name: '불가침', color: 'green' },
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ import { InvalidResponse } from '@/defs';
|
||||
import { delay } from '@util/delay';
|
||||
import { Modal } from 'bootstrap';
|
||||
import '@/gateway/common';
|
||||
import { sammoAPI } from '@/util/sammoAPI';
|
||||
import { isString } from 'lodash';
|
||||
import { SammoRootAPI } from '@/SammoRootAPI';
|
||||
|
||||
type LoginResponse = {
|
||||
result: true,
|
||||
@@ -101,7 +101,7 @@ async function tryAutoLogin() {
|
||||
|
||||
const [tokenID, token] = tokenInfo;
|
||||
|
||||
const result = await sammoAPI<AutoLoginNonceResponse, AutoLoginFailed>(["Login", "ReqNonce"], {}, true);
|
||||
const result = await SammoRootAPI.Login.ReqNonce<AutoLoginNonceResponse, AutoLoginFailed>({}, true);
|
||||
|
||||
if (!result) {
|
||||
//api 에러.
|
||||
@@ -116,7 +116,7 @@ async function tryAutoLogin() {
|
||||
const nonce = result.loginNonce;
|
||||
|
||||
const hashedToken = sha512(token + nonce);
|
||||
const loginResult = await sammoAPI<AutoLoginResponse, AutoLoginFailed>(["Login", "LoginByToken"], {
|
||||
const loginResult = await SammoRootAPI.Login.LoginByToken<AutoLoginResponse, AutoLoginFailed>({
|
||||
'hashedToken': hashedToken,
|
||||
'token_id': tokenID,
|
||||
}, true);
|
||||
@@ -312,7 +312,7 @@ $(async function ($) {
|
||||
let result: LoginResponse | LoginFailed;
|
||||
|
||||
try {
|
||||
result = await sammoAPI<LoginResponse, LoginFailed>(["Login", "LoginByID"], {
|
||||
result = await SammoRootAPI.Login.LoginByID<LoginResponse, LoginFailed>({
|
||||
username: values.username,
|
||||
password: hash_pw,
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
type SubValue<V extends (...args: unknown[]) => unknown> = V | { [property: string]: SubValue<V> };
|
||||
|
||||
export function APIPathGen<V extends () => unknown, T extends { [property: string]: SubValue<V> }>(obj: T, callback: (path: string[]) => V, path?: string[]): T {
|
||||
return new Proxy(obj, {
|
||||
get(target, key: string) {
|
||||
let nextPath: string[];
|
||||
if (path === undefined) {
|
||||
nextPath = [key];
|
||||
}
|
||||
else {
|
||||
nextPath = path;
|
||||
nextPath.push(key);
|
||||
}
|
||||
|
||||
if (!(key in target)) {
|
||||
throw `${nextPath} is not exists`;
|
||||
}
|
||||
|
||||
const next = target[key];
|
||||
if (typeof (next) === 'function') {
|
||||
return callback(nextPath);
|
||||
}
|
||||
return APIPathGen(next, callback, nextPath);
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import axios from "axios";
|
||||
import { isArray } from "lodash";
|
||||
import { InvalidResponse } from '@/defs';
|
||||
|
||||
export type ValidResponse = {
|
||||
result: true
|
||||
}
|
||||
|
||||
export async function callSammoAPI<ResultType extends ValidResponse>(path: string | string[], args?: Record<string, unknown>): Promise<ResultType>;
|
||||
export async function callSammoAPI<ResultType extends ValidResponse>(path: string | string[], args: Record<string, unknown> | undefined, returnError: false): Promise<ResultType>;
|
||||
export async function callSammoAPI<ResultType extends ValidResponse, ErrorType extends InvalidResponse>(path: string | string[], args: Record<string, unknown> | undefined, returnError: true): Promise<ResultType | ErrorType>;
|
||||
|
||||
export async function callSammoAPI<ResultType extends ValidResponse, ErrorType extends InvalidResponse>(path: string | string[], args?: Record<string, unknown>, returnError = false): Promise<ResultType | ErrorType> {
|
||||
if (isArray(path)) {
|
||||
path = path.join('/');
|
||||
}
|
||||
|
||||
const response = await axios({
|
||||
url: "api.php",
|
||||
method: "post",
|
||||
responseType: "json",
|
||||
data: {
|
||||
path,
|
||||
args,
|
||||
},
|
||||
});
|
||||
const result: ErrorType | ResultType = response.data;
|
||||
if (!result.result) {
|
||||
if (returnError) {
|
||||
return result;
|
||||
}
|
||||
throw result.reason;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import axios from "axios";
|
||||
import { isArray } from "lodash";
|
||||
import { InvalidResponse } from '@/defs';
|
||||
|
||||
export type ValidResponse = {
|
||||
result: true
|
||||
}
|
||||
|
||||
export async function sammoAPI<ResultType extends ValidResponse>(path: string | string[], args?: Record<string, unknown>): Promise<ResultType>;
|
||||
export async function sammoAPI<ResultType extends ValidResponse>(path: string | string[], args: Record<string, unknown> | undefined, returnError: false): Promise<ResultType>;
|
||||
export async function sammoAPI<ResultType extends ValidResponse, ErrorType extends InvalidResponse>(path: string | string[], args: Record<string, unknown> | undefined, returnError: true): Promise<ResultType | ErrorType>;
|
||||
|
||||
export async function sammoAPI<ResultType extends ValidResponse, ErrorType extends InvalidResponse>(path: string | string[], args?: Record<string, unknown>, returnError = false): Promise<ResultType | ErrorType> {
|
||||
if (isArray(path)) {
|
||||
path = path.join('/');
|
||||
}
|
||||
|
||||
const response = await axios({
|
||||
url: "api.php",
|
||||
method: "post",
|
||||
responseType: "json",
|
||||
data: {
|
||||
path,
|
||||
args,
|
||||
},
|
||||
});
|
||||
const result: ErrorType | ResultType = response.data;
|
||||
if (!result.result) {
|
||||
if (returnError) {
|
||||
return result;
|
||||
}
|
||||
throw result.reason;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
+5
-2
@@ -1,14 +1,17 @@
|
||||
import "@scss/board.scss";
|
||||
import { createApp } from 'vue'
|
||||
import PageBoard from '@/PageBoard.vue';
|
||||
import BootstrapVue3 from 'bootstrap-vue-3'
|
||||
import "@scss/common/bootstrap5.scss";
|
||||
import 'bootstrap-vue-3/dist/bootstrap-vue-3.css'
|
||||
import { setAxiosXMLHttpRequest } from '@util/setAxiosXMLHttpRequest';
|
||||
import { auto500px } from "./util/auto500px";
|
||||
|
||||
declare const isSecretBoard: boolean;
|
||||
|
||||
|
||||
|
||||
setAxiosXMLHttpRequest();
|
||||
auto500px();
|
||||
|
||||
createApp(PageBoard, {
|
||||
isSecretBoard
|
||||
}).use(BootstrapVue3).mount('#app')
|
||||
@@ -1,16 +0,0 @@
|
||||
import { createApp } from 'vue'
|
||||
import PartialDipcenter from '@/PartialDipcenter.vue';
|
||||
import BootstrapVue3 from 'bootstrap-vue-3';
|
||||
import { htmlReady } from './util/htmlReady';
|
||||
//import { activateFlip } from './legacy/activateFlip';
|
||||
//import { activateFlip } from "@/legacy/activateFlip";
|
||||
import { setAxiosXMLHttpRequest } from '@util/setAxiosXMLHttpRequest';
|
||||
//import { htmlReady } from './util/htmlReady';
|
||||
|
||||
createApp(PartialDipcenter).use(BootstrapVue3).mount('#editorForm');
|
||||
setAxiosXMLHttpRequest();
|
||||
|
||||
|
||||
htmlReady(function(){
|
||||
//activateFlip();
|
||||
})
|
||||
@@ -1,7 +1,5 @@
|
||||
import { createApp } from 'vue'
|
||||
import PageJoin from '@/PageJoin.vue';
|
||||
import BootstrapVue3 from 'bootstrap-vue-3'
|
||||
import "@scss/common/bootstrap5.scss";
|
||||
import "@scss/editor_component.scss";
|
||||
|
||||
createApp(PageJoin).use(BootstrapVue3).mount('#app')
|
||||
@@ -0,0 +1,12 @@
|
||||
import "@scss/nationStratFinan.scss";
|
||||
|
||||
import { createApp } from 'vue'
|
||||
import PageNationStratFinan from '@/PageNationStratFinan.vue';
|
||||
import BootstrapVue3 from 'bootstrap-vue-3';
|
||||
import { auto500px } from './util/auto500px';
|
||||
|
||||
|
||||
|
||||
|
||||
auto500px();
|
||||
createApp(PageNationStratFinan).use(BootstrapVue3).mount('#app');
|
||||
@@ -9,12 +9,12 @@ import { App, createApp } from 'vue';
|
||||
import { auto500px } from './util/auto500px';
|
||||
import { isString } from 'lodash';
|
||||
import { Args, testSubmitArgs } from './processing/args';
|
||||
import { sammoAPI, ValidResponse } from './util/sammoAPI';
|
||||
import { SammoAPI, ValidResponse } from './SammoAPI';
|
||||
|
||||
declare const turnList: number[];
|
||||
|
||||
async function submitCommand<T extends ValidResponse>(isChiefTurn: boolean, turnList: number[], action: string, arg: Args): Promise<T> {
|
||||
const target = isChiefTurn ? 'NationCommand/ReserveCommand' : 'Command/ReserveCommand';
|
||||
const targetAPI = isChiefTurn ? SammoAPI.NationCommand.ReserveCommand : SammoAPI.Command.ReserveCommand;
|
||||
|
||||
try {
|
||||
const testResult = testSubmitArgs(arg);
|
||||
@@ -22,7 +22,7 @@ async function submitCommand<T extends ValidResponse>(isChiefTurn: boolean, turn
|
||||
throw new TypeError(`Invalied Type ${testResult[0]}, ${testResult[2]} should be ${testResult[1]}`);
|
||||
}
|
||||
console.log('trySubmit', arg);
|
||||
const response = await sammoAPI(target, {
|
||||
const response = await targetAPI({
|
||||
action,
|
||||
turnList,
|
||||
arg,
|
||||
|
||||
+2
-2
@@ -44,8 +44,8 @@ $nationList = $db->query('SELECT nation,`name`,color,scout FROM nation');
|
||||
$nationList = Util::convertArrayToDict($nationList, 'nation');
|
||||
//NOTE: join 안할것임
|
||||
$scoutMsgs = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'scout_msg');
|
||||
foreach ($scoutMsgs as $nationID => $scoutMsg) {
|
||||
$nationList[$nationID]['scoutmsg'] = $scoutMsg;
|
||||
foreach ($scoutMsgs as $destNationID => $scoutMsg) {
|
||||
$nationList[$destNationID]['scoutmsg'] = $scoutMsg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin()->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
increaseRefresh("내무부", 1);
|
||||
|
||||
$me = $db->queryFirstRow('SELECT no, nation, officer_level, con, turntime, belong, permission, penalty FROM general WHERE owner=%i', $userID);
|
||||
|
||||
$con = checkLimit($me['con']);
|
||||
if ($con >= 2) {
|
||||
printLimitMsg($me['turntime']);
|
||||
exit();
|
||||
}
|
||||
|
||||
$permission = checkSecretPermission($me);
|
||||
if ($permission < 0) {
|
||||
echo '국가에 소속되어있지 않습니다.';
|
||||
die();
|
||||
} else if ($permission < 1) {
|
||||
echo "권한이 부족합니다. 수뇌부가 아니거나 사관년도가 부족합니다.";
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
$nationID = $me['nation'];
|
||||
$nation = $db->queryFirstRow('SELECT nation,level,name,color,type,gold,rice,bill,rate,scout,war,secretlimit,capital FROM nation WHERE nation = %i', $nationID);
|
||||
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
|
||||
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
|
||||
$nationStor->cacheValues(['notice', 'scout_msg', 'available_war_setting_cnt']);
|
||||
|
||||
$cityCntList = Util::convertPairArrayToDict($db->queryAllLists('SELECT nation, count(city) FROM city GROUP BY nation'));
|
||||
$dipStateList = Util::convertArrayToDict($db->query('SELECT you,state,term FROM diplomacy WHERE me = %i', $nationID), 'you');
|
||||
|
||||
$nationsList = getAllNationStaticInfo();
|
||||
|
||||
$cityList = $db->query('SELECT * FROM city WHERE nation=%i', $nationID);
|
||||
$dedicationList = $db->query('SELECT dedication FROM general WHERE nation=%i AND npc!=5', $nationID);
|
||||
|
||||
|
||||
foreach ($nationsList as &$nationItem) {
|
||||
|
||||
$staticNationID = $nationItem['nation'];
|
||||
//속령수
|
||||
$nationItem['cityCnt'] = $cityCntList[$staticNationID] ?? 0;
|
||||
if ($staticNationID !== $nationID) {
|
||||
$diplomacyItem = $dipStateList[$staticNationID];
|
||||
|
||||
$nationItem['diplomacy'] = [
|
||||
'state' => $diplomacyItem['state'],
|
||||
'term' => $diplomacyItem['term'],
|
||||
];
|
||||
} else {
|
||||
$nationItem['diplomacy'] = [
|
||||
'state' => 7,
|
||||
'term' => null,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 수입 연산
|
||||
$goldIncome = getGoldIncome(
|
||||
$nation['nation'],
|
||||
$nation['level'],
|
||||
100,
|
||||
$nation['capital'],
|
||||
$nation['type'],
|
||||
$cityList
|
||||
);
|
||||
$warIncome = getWarGoldIncome($nation['type'], $cityList);
|
||||
|
||||
$riceIncome = getRiceIncome(
|
||||
$nation['nation'],
|
||||
$nation['level'],
|
||||
100,
|
||||
$nation['capital'],
|
||||
$nation['type'],
|
||||
$cityList
|
||||
);
|
||||
$wallIncome = getWallIncome(
|
||||
$nation['nation'],
|
||||
$nation['level'],
|
||||
100,
|
||||
$nation['capital'],
|
||||
$nation['type'],
|
||||
$cityList
|
||||
);
|
||||
|
||||
$income = [
|
||||
'gold' => [
|
||||
'city' => $goldIncome,
|
||||
'war' => $warIncome,
|
||||
],
|
||||
'rice' => [
|
||||
'city' => $riceIncome,
|
||||
'wall' => $wallIncome,
|
||||
],
|
||||
];
|
||||
|
||||
$outcome = getOutcome(100, $dedicationList);
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=500" />
|
||||
<title><?= UniqueConst::$serverName ?>: 내무부</title>
|
||||
<?= WebUtil::printStaticValues([
|
||||
'staticValues' => [
|
||||
'editable' => ($me['officer_level'] >= 5 || $permission == 4),
|
||||
'nationMsg' => $nationStor->notice ?? '',
|
||||
'scoutMsg' => $nationStor->scout_msg ?? '',
|
||||
'nationID' => $nationID,
|
||||
'officerLevel' => $me['officer_level'],
|
||||
'year' => $year,
|
||||
'month' => $month,
|
||||
'nationsList' => $nationsList,
|
||||
|
||||
'gold' => $nation['gold'],
|
||||
'rice' => $nation['rice'],
|
||||
'income' => $income,
|
||||
'outcome' => $outcome,
|
||||
|
||||
'policy' => [
|
||||
'rate' => $nation['rate'],
|
||||
'bill' => $nation['bill'],
|
||||
'secretLimit' => $nation['secretlimit'],
|
||||
'blockScout' => $nation['scout'] != 0,
|
||||
'blockWar' => $nation['war'] != 0,
|
||||
],
|
||||
'warSettingCnt' => [
|
||||
'remain' => $nationStor->getValue('available_war_setting_cnt'),
|
||||
'inc' => GameConst::$incAvailableWarSettingCnt,
|
||||
'max' => GameConst::$maxAvailableWarSettingCnt
|
||||
],
|
||||
]
|
||||
], false) ?>
|
||||
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
|
||||
<?= WebUtil::printCSS('../d_shared/common.css') ?>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
|
||||
<?= WebUtil::printDist('vue', 'v_nationStratFinan', true) ?>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+3
-3
@@ -5,9 +5,9 @@ set_time_limit(600);
|
||||
|
||||
function tryNpmInstall()
|
||||
{
|
||||
$npmResultPath = '../npm_recent.json.log';
|
||||
$packageJsonPath = '../package.json';
|
||||
$packageJsonLockPath = '../package-lock.json';
|
||||
$npmResultPath = 'npm_recent.json.log';
|
||||
$packageJsonPath = 'package.json';
|
||||
$packageJsonLockPath = 'package-lock.json';
|
||||
|
||||
$packageJsonHash = hash_file('sha512', $packageJsonPath);
|
||||
$timestamp = time();
|
||||
|
||||
@@ -68,16 +68,21 @@
|
||||
"@typescript-eslint/parser": "^5.8.0",
|
||||
"@vue/compiler-sfc": "^3.2.26",
|
||||
"@vue/eslint-config-typescript": "^10.0.0",
|
||||
"autoprefixer": "^10.4.1",
|
||||
"babel-plugin-lodash": "^3.3.4",
|
||||
"babel-preset-modern-browsers": "^15.0.2",
|
||||
"bootswatch": "^5.1.3",
|
||||
"clean-terminal-webpack-plugin": "^3.0.0",
|
||||
"css-loader": "^6.5.1",
|
||||
"cssnano": "^5.0.14",
|
||||
"esbuild-loader": "^2.18.0",
|
||||
"eslint": "^8.5.0",
|
||||
"eslint-plugin-vue": "^8.2.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"mini-css-extract-plugin": "^2.4.5",
|
||||
"postcss-discard-duplicates": "^5.0.1",
|
||||
"postcss-import": "^14.0.2",
|
||||
"postcss-loader": "^6.2.1",
|
||||
"pre-commit": "^1.2.2",
|
||||
"sass": "^1.45.1",
|
||||
"sass-loader": "^12.4.0",
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('postcss-import'),
|
||||
require('postcss-discard-duplicates'),
|
||||
require('autoprefixer'),
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
//TODO: API 경로를 읽어서 SammoAPI.ts, SammoRootAPI에 쉽게 채울 수 있도록 값 만들어주기
|
||||
export {}
|
||||
|
||||
console.log('Hello World!');
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
"noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
"isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
+1
-1
@@ -1000,7 +1000,7 @@ class util
|
||||
*/
|
||||
public static function starts_with($string, $starts_with)
|
||||
{
|
||||
return strpos($string, $starts_with) === 0;
|
||||
return str_starts_with($string, $starts_with);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+4
-4
@@ -160,11 +160,11 @@ module.exports = (env, argv) => {
|
||||
},
|
||||
{
|
||||
test: /\.vue\.(s?[ac]ss)$/,
|
||||
use: ['vue-style-loader', 'css-loader', 'sass-loader']
|
||||
use: ['vue-style-loader', 'css-loader', 'postcss-loader', 'sass-loader']
|
||||
},
|
||||
{
|
||||
test: /(?<!\.vue)\.(s?[ac]ss)$/,
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader']
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|webp)$/,
|
||||
@@ -261,7 +261,7 @@ module.exports = (env, argv) => {
|
||||
},
|
||||
{
|
||||
test: /.(s?[ac]ss)$/,
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader']
|
||||
},]
|
||||
},
|
||||
plugins: [
|
||||
@@ -342,7 +342,7 @@ module.exports = (env, argv) => {
|
||||
]
|
||||
}, {
|
||||
test: /.(s?[ac]ss)$/,
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader']
|
||||
}]
|
||||
},
|
||||
plugins: [
|
||||
|
||||
Reference in New Issue
Block a user