feat: 메인 페이지를 반응형 페이지로 변경 #197

Merged
Hide_D merged 31 commits from reactive_main into devel 2021-12-03 23:06:53 +09:00
44 changed files with 2905 additions and 1114 deletions
-2
View File
@@ -101,13 +101,11 @@ return [
'hwe/j_export_simulator_object.php',
'hwe/j_general_log_old.php',
'hwe/j_general_set_permission.php',
'hwe/j_general_turn.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',
'hwe/j_get_reserved_command.php',
'hwe/j_get_select_npc_token.php',
'hwe/j_get_select_pool.php',
'hwe/j_image_upload.php',
-4
View File
@@ -1,7 +1,3 @@
@charset "UTF-8";
/* font-boostring Block */
html * {
max-height: 1000000px;
}
-100
View File
@@ -1,100 +0,0 @@
@charset "UTF-8";
body {
color:white;
background-color:black;
border-width:1px;
border-color:gray; background-position:center; background-repeat:repeat-y;
}
#container {
width:1000px;
margin: 0 auto;
}
.buttonPlate{
width:1000px;
height:60px;
}
.toolbarButton {
float:left;
background-color:#225500;
color:white;
width:125px;
height:30px;
font-weight:bold;
font-size:13px;
margin:0;
display:block;
}
.commandButton {
float:left;
width:100px;
height:30px;
font-weight:bold;
font-size:13px;
margin:0;
display:block;
}
.commandButton:disabled::before{
content:'【'
}
.commandButton:disabled::after{
content:'】'
}
.commandButton:disabled{
background-color:transparent !important;
color:gray !important;
border-color:transparent !important;
}
.toolbarButton2 {
float:left;
background-color:#225500;
color:magenta;
width:125px;
height:30px;
font-weight:bold;
font-size:13px;
margin:0;
display:block;
}
.nation_info td{
height:18px;
}
#generalTurnSelector{
width:50px;
color:white;
background-color:black;
font-size:13px;
}
#sidebar{
position:fixed;
right:0;
top: 50%;
transform: translateY(-50%);
}
#sidebar button{
/*width:100px;*/
}
.turn_pad{
white-space:nowrap;
font-weight:lighter;
max-width: 162px;
width: 162px;
}
.turn_pad .turn_text{
display:inline-block;
}
+9 -2
View File
@@ -5,6 +5,7 @@
background:black;
font-size:13px;
color:white;
position: relative;
}
.map_title{
@@ -33,6 +34,7 @@
width:700px;
height:500px;
position:relative;
overflow: hidden;
}
.map_body .map_bglayer1{
@@ -88,7 +90,7 @@
.world_map .city_tooltip{
position: absolute;
z-index:6;
z-index:16;
display:none;
min-width:120px;
border: 0.02em gray solid;
@@ -99,7 +101,7 @@
z-index: 6;
line-height:15px;
height:15px;
}
.world_map .nation_name{
background-color: rgb(30, 164, 255);
@@ -491,4 +493,9 @@
.map_basic .city_base .city_state.city_state_good{
background-color:blue;
}
.btn.btn-minimum{
padding-top: 1px;
padding-bottom: 1px;
}
-202
View File
@@ -1,202 +0,0 @@
@charset "UTF-8";
/*임시용 */
#container{
width:1000px;
margin:auto;
font-size:13px;
}
/*임시용 끝*/
#message_board{
height:1370px;
position:relative;
}
#message_board section{
overflow-y:auto;
overflow-x:hidden;
}
.msg_plate{
width:100%;
outline-style:solid;
outline-width:1px;
outline-color: gray;
min-height:64px;
font-size:12px;
word-break:break-all;
color:white;
}
.msg_plate_private{
background-color:#5d1e1a;
}
.msg_plate_private.msg_plate_dest{
background-color:#5d461a;
}
.msg_plate_public{
background-color:#141c65;
}
.msg_plate_national, .msg_plate_diplomacy{
background-color:#00582c;
}
.msg_plate_national.msg_plate_dest, .msg_plate_diplomacy.msg_plate_dest {
background-color:#704615;
}
.msg_plate_national.msg_plate_src, .msg_plate_diplomacy.msg_plate_src {
background-color:#70153b;
}
.public_message{
height:667px;
}
.diplomacy_message{
flex: 1;
}
.national_message{
height:667px;
}
.private_message{
flex: 1;
}
.msg_icon{
float:left;
width:64px;
height:64px;
border-right:solid 1px gray;
}
.msg_time{
font-size:0.75em;
font-weight:normal;
}
.msg_header{
font-weight: bold;
margin-bottom:3px;
color:white;
position: relative;
}
.message_input_form{
position:relative;
}
#msg_input{
color:white;
background-color:black;
font-size:12px;
width:715px;
margin:0 2px;
height:20px;
border:solid 1px gray;
}
#msg_submit{
position:absolute;
right:0;
margin-right:2px;
}
#mailbox_list{
float:left;
color:white;
background-color:black;
font-size:12px;
width:160px;
height:20px;
}
.board_header{
color:white;
outline-style:solid;
outline-width:1px;
outline-color: gray;
}
.board_side{
position:absolute;
height:1370px;
width:50%;
overflow-y: hidden;
outline-style:solid;
outline-width:1px;
outline-color: gray;
display: flex;
flex-wrap: wrap;
flex-direction: column;
}
.board_side > div{
height: 1.2em;
}
.msg_invalid{
color:rgba(255,255,255,0.5);
}
.msg_body{
padding-left:64px;
}
.msg_target{
margin:2px 2px 0 2px;
padding:2px 3px;
display:inline-block;
box-shadow: 2px 2px black;
border-radius: 3px;
}
.btn-delete-msg{
position: absolute;
right: 0;
top: 0;
margin:2px 2px 0 2px;
font-size:8px;
}
/*
.public_message .msg_target{
box-shadow: 2px 2px darkslategrey;
}
*/
.msg_target.msg_bright{
color:black;
}
.msg_target.msg_dark{
color:white;
}
.msg_from_to{
display:inline-block;
}
.msg_content{
margin-left:10px;
margin-right:5px;
overflow:hidden;
}
.msg_prompt{
text-align:right;
margin-top:5px;
margin-right:5px;
}
#mailbox_list option{
color:white;
background-color:black;
}
+1 -5
View File
@@ -1,5 +1,4 @@
<div class="buttonPlate bg1">
<div>
<div class="buttonPlate">
<a href="a_status.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">세력도</button></a>
<a href="a_kingdomList.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">세력일람</button></a>
<a href="a_genList.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">장수일람</button></a>
@@ -8,8 +7,6 @@
<a href="a_hallOfFame.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">명예의전당</button></a>
<a href="a_emperior.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">왕조일람</button></a>
<a href="a_traffic.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">접속량정보</button></a>
</div>
<div>
<a href="/bbs/board" target="_blank"><button type="button" class="toolbarButton2">삼모게시판</button></a>
<a href="/bbs/tip" target="_blank"><button type="button" class="toolbarButton">팁/강좌</button></a>
<a href="/bbs/news" target="_blank"><button type="button" class="toolbarButton">삼국 일보</button></a>
@@ -18,5 +15,4 @@
<a href="/bbs/patch" target="_blank"><button type="button" class="toolbarButton">패치 내역</button></a>
<a href="battle_simulator.php" target="_blank"><button type="button" class="toolbarButton">전투 시뮬레이터</button></a>
<a href="<?=$site?>" target="_blank" class="open-window"><button type="button" class="toolbarButton"><?=$call?></button></a>
</div>
</div>
+31
View File
@@ -461,6 +461,37 @@ function commandGroup($typename, $type = 0)
}
}
function getCommandTable(General $general){
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->turnOnCache();
$env = $gameStor->getAll();
$result = [];
foreach (GameConst::$availableGeneralCommand as $commandCategory => $commandList) {
$subList = [];
foreach ($commandList as $commandClassName) {
$commandObj = buildGeneralCommandClass($commandClassName, $general, $env);
if (!$commandObj->canDisplay()) {
continue;
}
$subList[Util::getClassNameFromObj($commandObj)] = [
'compansation'=>$commandObj->getCompensationStyle(),
'possible'=>$commandObj->hasMinConditionMet(),
'title'=>$commandObj->getCommandDetailTitle(),
'reqArg'=>$commandObj::$reqArg,
];
}
$result[] = [
'category'=>$commandCategory,
'values'=>$subList
];
}
return $result;
}
function printCommandTable(General $generalObj)
{
$db = DB::db();
+5 -5
View File
@@ -63,7 +63,7 @@ function pullGeneralCommand(int $generalID, int $turnCnt=1){
if($turnCnt >= GameConst::$maxTurn){
return;
}
$db = DB::db();
$db->update('general_turn', [
@@ -96,7 +96,7 @@ function repeatGeneralCommand(int $generalId, int $turnCnt){
foreach($turnList as $turnItem){
$turnIdx = $turnItem['turn_idx'];
$turnTarget = iterator_to_array(Util::range($turnIdx+$turnCnt, GameConst::$maxTurn, $turnCnt));
$db->update('general_turn', [
'action'=>$turnItem['action'],
'arg'=>$turnItem['arg'],
@@ -116,7 +116,7 @@ function pushNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
return;
}
if($turnCnt < 0){
pullNationCommand($nationID, $officerLevel, -$turnCnt);
pullNationCommand($nationID, $officerLevel, -$turnCnt);
return;
}
if($turnCnt >= GameConst::$maxChiefTurn){
@@ -153,7 +153,7 @@ function pullNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
if($turnCnt >= GameConst::$maxChiefTurn){
return;
}
$db = DB::db();
$db->update('nation_turn', [
@@ -269,7 +269,7 @@ function checkCommandArg(?array $arg):?string{
}
function setGeneralCommand(int $generalID, array $rawTurnList, string $command, ?array $arg = null):array{
$turnList = [];
foreach($rawTurnList as $turnIdx){
if(!is_int($turnIdx) || $turnIdx < -3 || $turnIdx >= GameConst::$maxTurn){
+37 -24
View File
@@ -5,7 +5,7 @@ namespace sammo;
/**
* 템플릿 생성과 관련된 함수들을 모아두는 파일
*
*
* NOTE: 아직 converter와 명확한 구분이 되어있지 않음.
* TODO: legacy template들을 전부 template 폴더로 모아둘 필요 있음
* TODO: side effect를 제거
@@ -13,7 +13,7 @@ namespace sammo;
/**
* 관리자 권한이 필요함을 출력.
* @return void
* @return void
*/
function requireAdminPermissionHTML()
{
@@ -41,28 +41,6 @@ function requireAdminPermissionHTML()
return ob_get_clean();
}
function turnTable()
{
$turnList = [];
$turnList[] = "<option selected value='0'>1턴</option>";
foreach (Util::range(1, GameConst::$maxTurn) as $turnIdx) {
$turnText = $turnIdx + 1;
$turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>";
}
$turnText = join("\n", $turnList);
return "
<select id='generalTurnSelector' name=turn[] size=11 multiple>
<option value='-3'>전체</option>
<option value='-1'>홀턴</option>
<option value='-2'>짝턴</option>
{$turnText}
</select>
";
}
function chiefTurnTable()
{
$turnList = [];
@@ -272,3 +250,38 @@ function getInvitationList(array $nationList)
'nationList' => $nationList
]);
}
function getAutorunInfo($autorunOption){
$templates = new \League\Plates\Engine(__DIR__.'/templates');
$auto_info = [];
foreach($autorunOption['options'] as $auto_option => $value){
assert($value);
switch($auto_option){
case 'develop': $auto_info['내정'] = '내정'; break;
case 'warp': $auto_info['순간이동'] = '순간이동'; break;
case 'recruit': $auto_info['징병'] = $auto_info['징병']??'징병'; break;
case 'recruit_high': $auto_info['징병'] = '모병'; break;
case 'train': $auto_info['훈사'] = '훈련/사기진작'; break;
case 'battle': $auto_info['출병'] = '출병'; break;
case 'chief': $auto_info['사령턴'] = '사령턴'; break;
}
}
$limit = Util::toInt($autorunOption['limit_minutes']);
if($limit >= 43200){
$auto_info['제한'] = '항상 유효';
}
else if($limit % 60 == 0){
$auto_info['제한'] = ($limit/60).'시간 유효';
}
else{
$auto_info['제한'] = ($limit).'분 유효';
}
$auto_info = join(', ', array_values($auto_info));
return $templates->render('tooltip', [
'text'=>'자율행동',
'info'=>$auto_info,
'style'=>'text-decoration:underline',
'copyable_info'=>true
]);
}
+11 -11
View File
@@ -156,17 +156,17 @@ function getTournamentTime() {
function getTournament(int $tnmt) {
return [
"<font color=magenta>경기 없음</font>",
"<font color=orange>참가 모집중</font>",
"<font color=orange>예선 진행중</font>",
"<font color=orange>본선 추첨중</font>",
"<font color=orange>본선 진행중</font>",
"<font color=orange>16강 배정중</font>",
"<font color=orange>베팅 진행중</font>",
"<font color=orange>16강 진행중</font>",
"<font color=orange>8강 진행중</font>",
"<font color=orange>4강 진행중</font>",
"<font color=orange>결승 진행중</font>",
"<span style='color:magenta;'>경기 없음</span>",
"<span style='color:orange;'>참가 모집중</span>",
"<span style='color:orange;'>예선 진행중</span>",
"<span style='color:orange;'>본선 추첨중</span>",
"<span style='color:orange;'>본선 진행중</span>",
"<span style='color:orange;'>16강 배정중</span>",
"<span style='color:orange;'>베팅 진행중</span>",
"<span style='color:orange;'>16강 진행중</span>",
"<span style='color:orange;'>8강 진행중</span>",
"<span style='color:orange;'>4강 진행중</span>",
"<span style='color:orange;'>결승 진행중</span>",
][$tnmt]??"TOURNAMENT_TYPE_ERR_{$tnmt}";
}
+271 -278
View File
@@ -1,4 +1,5 @@
<?php
namespace sammo;
include "lib.php";
@@ -20,7 +21,7 @@ if (!$userID) {
//턴 실행.
TurnExecutionHelper::executeAllCommand();
if(!$session->isGameLoggedIn()){
if (!$session->isGameLoggedIn()) {
header('Location:..');
die();
}
@@ -41,8 +42,8 @@ $gameStor->cacheAll(true);
if ($me['newmsg'] == 1 || $me['newvote'] == 1) {
$db->update('general', [
'newmsg'=>0,
'newvote'=>0
'newmsg' => 0,
'newvote' => 0
], 'owner=%i', $userID);
}
@@ -59,29 +60,25 @@ $generalObj->setRawCity($db->queryFirstRow('SELECT * FROM city WHERE city = %i',
$scenario = $gameStor->scenario_text;
$nationID = $generalObj->getNationID();
if($nationID){
if ($nationID) {
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->cacheAll();
}
$valid = 0;
if ($gameStor->extended_general == 0) {
$extend = "표준";
} else {
$extend = "확장";
$valid = 1;
}
if ($gameStor->fiction == 0) {
$fiction = "사실";
} else {
$fiction = "가상";
$valid = 1;
}
if ($gameStor->npcmode == 0) {
$npcmode = "불가능";
} else if($gameStor->npcmode == 1){
} else if ($gameStor->npcmode == 1) {
$npcmode = "가능";
$valid = 1;
} else {
$npcmode = "선택 생성";
}
@@ -89,285 +86,281 @@ $color = "cyan";
$mapTheme = $gameStor->map_theme;
$serverName = UniqueConst::$serverName;
$serverCnt = $gameStor->server_cnt;
$auctionCount = $db->queryFirstField('SELECT count(`no`) FROM auction');
$myNationStatic = getNationStaticInfo($generalObj->getNationID());
$nationColorType = substr($myNationStatic['color'] ?? '#000000', 1);
$autorunUser = ($gameStor->autorun_user) ?? [];
$otherTextInfo = [];
if ($gameStor->join_mode == 'onlyRandom') {
$otherTextInfo[] = '랜덤 임관 전용';
}
if ($autorunUser['limit_minutes'] ?? false) {
$otherTextInfo[] = getAutorunInfo($autorunUser);
}
if (!$otherTextInfo) {
$otherTextInfo = '표준';
} else {
$otherTextInfo = join(', ', $otherTextInfo);
}
?>
<!DOCTYPE html>
<html>
<head>
<title><?=$serverName?>: 메인</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('d_shared/base_map.js')?>
<?=WebUtil::printJS('dist_js/main.js')?>
<script>
window.serverNick = '<?=DB::prefix()?>';
window.serverID = '<?=UniqueConst::$serverID?>';
$(function(){
reloadWorldMap({
hrefTemplate:'b_currentCity.php?citylist={0}',
useCachedMap:true
});
setInterval(function(){
refreshMsg();
}, 5000);
});
</script>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/main.css')?>
<?=WebUtil::printCSS('css/map.css')?>
<?=WebUtil::printCSS('css/msg.css')?>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Nanum+Gothic|Nanum+Myeongjo|Nanum+Pen+Script" rel="stylesheet">
<head>
<title><?= $serverName ?>: 메인</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS('dist_js/vendors.js') ?>
<?= WebUtil::printJS('d_shared/base_map.js') ?>
<?= WebUtil::printJS('dist_js/vendors_vue.js', true) ?>
<?= WebUtil::printJS('dist_js/v_main.js', true) ?>
<?= WebUtil::printJS('dist_js/main.js') ?>
<script>
window.serverNick = '<?= DB::prefix() ?>';
window.serverID = '<?= UniqueConst::$serverID ?>';
$(function() {
reloadWorldMap({
hrefTemplate: 'b_currentCity.php?citylist={0}',
useCachedMap: true
});
setInterval(function() {
refreshMsg();
}, 5000);
});
</script>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printCSS('dist_css/common.css') ?>
<?= WebUtil::printCSS('dist_css/common_vue.css') ?>
<?= WebUtil::printCSS('dist_css/main.css') ?>
<?= WebUtil::printCSS('css/map.css') ?>
<?= WebUtil::printStaticValues([
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'commandList' => getCommandTable($generalObj),
'serverNow' => TimeUtil::now(false),
'baseColor2' => GameConst::$basecolor2,
]) ?>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Nanum+Gothic|Nanum+Myeongjo|Nanum+Pen+Script" rel="stylesheet">
</head>
<body class="img_back">
<div id="container">
<div><?=allButton($gameStor->npcmode==1)?></div>
<table class="tb_layout bg0" style="width:1000px;">
<tr height=50>
<td colspan=5 id="server_title" align=center><font size=4>삼국지 모의전투 HiDCHe <?=$serverName.$serverCnt?>기 (<font color=cyan><?=$scenario?></font>)</font></td>
</tr>
<?php if ($valid == 1): ?>
<tr height=30>
<td width=398 colspan=2 align=center><font color=<?=$color?>><?=$scenario?></font></td>
<td width=198 align=center><font color=<?=$color?>>NPC수 : <?=$extend?></font></td>
<td width=198 align=center><font color=<?=$color?>>NPC상성 : <?=$fiction?></font></td>
<td width=198 align=center><font color=<?=$color?>>NPC선택 : <?=$npcmode?></font></td>
</tr>
<?php endif; ?>
<tr height=30>
<td width=198><?=info(2)?></td>
<td width=198>전체 접속자 수 : <?=$gameStor->online_user_cnt?> 명</td>
<td width=198>턴당 갱신횟수 : <?=$gameStor->conlimit?>회</td>
<td width=398 colspan=2><?=info(3)?></td>
</tr>
<tr height=30>
<td style='text-align:center;'>
<?php
if (!$plock) {
echo "<span style='color:cyan;'>동작 시각: ".substr($gameStor->turntime, 5, 14)."</span>";
} else {
echo "<span style='color:magenta;'>동작 시각: ".substr($gameStor->turntime, 5, 14)."</span>";
}
echo "
</td>
<td align=center>
";
if ($gameStor->tournament == 0) {
echo "<font color=magenta>현재 토너먼트 경기 없음</font>";
} else {
switch ($gameStor->tnmt_type) {
case 0: $str = "전력전"; break;
case 1: $str = "통솔전"; break;
case 2: $str = "일기토"; break;
case 3: $str = "설전"; break;
}
$str2 = getTournament($gameStor->tournament);
$str3 = getTournamentTime();
echo "<marquee scrollamount=2>↑<font color=cyan>{$str}</font> {$str2} {$str3}↑</marquee>";
}
echo "
</td>
<td align=center>
";
$auctionCount = $db->queryFirstField('SELECT count(`no`) FROM auction');
if ($auctionCount > 0) {
echo "<marquee scrollamount=2><font color=cyan>{$auctionCount}건</font> 거래 진행중</marquee>";
} else {
echo "<font color=magenta>진행중 거래 없음</font>";
}
echo "
</td>
<td colspan=2 align=center>
";
$vote = $gameStor->vote?:[''];
$vote_title = Tag2Code($gameStor->vote_title??'-');
if ($vote[0] == "") {
echo "<font color=magenta>진행중 설문 없음</font>";
} else {
echo "<marquee scrollamount=3><font color=cyan>설문 진행중</font> : $vote_title</marquee>";
}
echo "
</td>
</tr>";
?>
<tr><td colspan=5 style="text-align:left;">접속중인 국가: <?=$gameStor->online_nation?></td></tr>
<tr><td colspan=5 style="text-align:left;">운영자 메세지 : <span style='color:yellow;'><?=$gameStor->msg?></span></td></tr>
<tr><td colspan=5 style="text-align:left;"><div>【 국가방침 】</div><div><?=nationMsg($generalObj)?></div></td></tr>
<tr><td colspan=5 style="text-align:left;">【 접속자 】<?=onlinegen($generalObj)?></td></tr>
<?php
if ($session->userGrade >= 5) {
?>
<tr><td colspan=5>
<a href='_admin1.php' target='_blank'><button type='button'>게임관리</button></a>
<a href='_admin2.php' target='_blank'><button type='button'>회원관리</button></a>
<a href='_admin4.php' target='_blank'><button type='button'>멀티관리</button></a>
<a href='_admin5.php' target='_blank'><button type='button'>일제정보</button></a>
<a href='_admin7.php' target='_blank'><button type='button'>로그정보</button></a>
<a href='_admin8.php' target='_blank'><button type='button'>외교정보</button></a>
<a href='_119.php' target='_blank'><button type='button'>119</button></a>
</td></tr>
<?php
}
else if($session->userGrade == 4){
?>
<tr><td colspan=5>
<a href='_119.php' target='_blank'><button type='button'>119</button></a>
</td></tr>
<?php
}
?>
</table>
<table class="tb_layout bg0" style="width:1000px;" id='map_position'>
<tr>
<td style='width:700px;height:520px;' colspan=2>
<?=getMapHtml($mapTheme)?>
</td>
<td style='width:300px;vertical-align:top;' rowspan=4>
<div id="reservedCommandList" style='overflow-y:scroll;height:700px;'>
<table width="300" class="tb_layout b2">
<thead>
<tr height="24"><td colspan="4" class="center bg0"
><strong>- 명령 목록 - </strong><input value="<?=TimeUtil::now(false)?>" type="text" id="clock" size="19" style="background-color:black;color:white;border-style:none;"
></td></tr>
</thead>
<tbody class="center" style="font-weight:bold">
<?php for($turnIdx = 0; $turnIdx < GameConst::$maxTurn; $turnIdx++): ?>
<tr height='28' id="command_<?=$turnIdx?>"
><td width="24" class='idx_pad center bg0'><?=$turnIdx+1?></td
><td height='24' class='month_pad center bg1' style='min-width:70px;white-space:nowrap;overflow:hidden;'></td
><td width='42' class='time_pad center' style='background-color:black;white-space:nowrap;overflow:hidden;'></td
><td width='165' class='turn_pad center bg2'><span class='turn_text'></span></td
></tr>
<?php endfor; ?>
</tbody>
</table>
<body class="img_back sam-color-<?= $nationColorType ?>">
<div id="container" class="bg0">
<div class="row toolbars gx-0"><?= allButton($gameStor->npcmode == 1) ?></div>
<div class="tb_layout row gx-0">
<div id="server_title" class="row py-2 center">
<h3>삼국지 모의전투 HiDCHe <?= $serverName . $serverCnt ?>기 <span class="avoid-wrap">(<font color=cyan><?= $scenario ?></font>)</span></h3>
</div>
</td>
</tr>
<tr>
<td rowspan=3 width=50 valign=top><?=turnTable()?></td>
<td style="width:650px;border:none;text-align:center;"><?=cityInfo($generalObj)?></td>
</tr>
<tr>
<td style='width:650px;' align=right>
<font color=cyan><b>←</b> Ctrl, Shift, 드래그로 복수선택 가능  반복&amp;수정<b>→</b></font>
<select id='repeatAmount' name=sel size=1 style=color:white;background-color:black;font-size:13px;>
<option value=1>1턴</option>
<option value=2>2턴</option>
<option value=3>3턴</option>
<option value=4>4턴</option>
<option value=5>5턴</option>
<option value=6>6턴</option>
<option value=7>7턴</option>
<option value=8>8턴</option>
<option value=9>9턴</option>
<option value=10>10턴</option>
<option value=11>11턴</option>
<option value=12>12턴</option>
</select
><input type=button value='반복' id='repeatTurn'
style='background-color:<?=GameConst::$basecolor2?>;color:white;width:70px;font-size:13px;margin-left:1ch;margin-right:2ch;'
><input type=button value='▼미루기' id='pushTurn'
style='background-color:<?=GameConst::$basecolor2?>;color:white;width:80px;font-size:13px;'
><input type=button value='▲당기기' id='pullTurn'
style='background-color:<?=GameConst::$basecolor2?>;color:white;width:80px;font-size:13px;'
></td>
</tr>
<tr>
<td align=right style="width:650px;border:none;"><br>
<?php printCommandTable($generalObj)?>
<input type=button value='실 행' id="reserveTurn"
style='background-color:<?=GameConst::$basecolor2?>;color:white;width:110px;font-size:13px;'
><input type=button value='갱 신' id='refreshPage'
style='background-color:<?=GameConst::$basecolor2?>;color:white;width:110px;font-size:13px;'
><input type=button value='로비로' onclick="location.replace('../')"
style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;font-size:13px;
>
</td>
</tr>
</table>
<table class="tb_layout bg0" style="width:1000px;">
<tr>
<td width=498 style="border:none;"><?php myNationInfo($generalObj); ?></td>
<td width=498 style="border:none;"><?php generalInfo($generalObj); ?></td>
</tr>
<tr><td colspan=2><?=commandButton()?></td></tr>
</table>
<table class="tb_layout bg0" id='history_position'>
<tr>
<td width=498 class='bg1 center'><b>장수 동향</b></td>
<td width=498 class='bg1 center'><b>개인 기록</b></td>
</tr>
<tr>
<td width=498 id="general_public_record" style="text-align:left;"><?=formatHistoryToHTML(getGlobalActionLogRecent(15))?></td>
<td width=498 id="general_log" style="text-align:left;"><?=formatHistoryToHTML(getGeneralActionLogRecent($me['no'], 15))?></td>
</tr>
<tr><td width=998 colspan=2 class='bg1 center'><b>중원 정세</b></td></tr>
<tr><td width=998 id="world_history" colspan=2 style="text-align:left;"><?=formatHistoryToHTML(getGlobalHistoryLogRecent(15))?></td></tr>
</table>
<div class="message_input_form bg0">
<select id="mailbox_list" size="1">
<select name="genlist" size="1" style="color:white;background-color:black;font-size:13px">
<div class="row center gx-0">
<div class="s-border-t col py-2 col-8 col-md-4" style="color:<?= $color ?>;">
<?= $scenario ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
NPC수 : <?= $extend ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
NPC상성 : <?= $fiction ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
NPC선택 : <?= $npcmode ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
기타 설정: <?= $otherTextInfo ?>
</div>
<div class="s-border-t col py-2 col-8 col-md-4"><?= info(2) ?></div>
<div class="s-border-t col py-2 col-4 col-md-2">전체 접속자 수 : <?= $gameStor->online_user_cnt ?> 명</div>
<div class="s-border-t col py-2 col-4 col-md-2">턴당 갱신횟수 : <?= $gameStor->conlimit ?>회</div>
<div class="s-border-t col py-2 col-8 col-md-4"><?= info(3) ?></div>
<div class="s-border-t py-2 col col-6 col-md-4"><?php if ($gameStor->tournament == 0) : ?>
<span style='color:magenta'>현재 토너먼트 경기 없음</span>
<?php else : ?>
↑<span style='color:cyan'><?=
([
'전력전', '통솔전', '일기토', '설전',
])[$gameStor->tnmt_type] ?? '' ?> <?= getTournament($gameStor->tournament) ?> <?= getTournamentTime() ?></span>↑
<?php endif; ?>
</div>
<div class="s-border-t py-2 col col-6 col-md-2">
<div style="display:inline-block;"><?= !$plock ? ("<span style='color:cyan;'>동작 시각: " . substr($gameStor->turntime, 5, 14) . "</span>") : ("<span style='color:magenta;'>동작 시각: " . substr($gameStor->turntime, 5, 14) . "</span>") ?></div>
</div>
<div class="s-border-t py-2 col col-6 col-md-2">
<?php if ($auctionCount > 0) : ?>
<span style='color:cyan'><?= $auctionCount ?>건</span> 거래 진행중
<?php else : ?>
<span style='color:magenta'>진행중 거래 없음</span>
<?php endif; ?>
</div>
<div class="s-border-t py-2 col col-6 col-md-4 vote-cell">
<?php
$vote = $gameStor->vote ?: [''];
$vote_title = Tag2Code($gameStor->vote_title ?? '-');
?>
<?php if ($vote[0] == "") : ?>
<span style='color:magenta'>진행중 설문 없음</span>
<?php else : ?>
<span style='color:cyan'>설문 진행중</span> : <span><?= $vote_title ?></span>
<?php endif; ?>
</div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">접속중인 국가: <?= $gameStor->online_nation ?></div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">운영자 메세지 : <span style='color:yellow;'><?= $gameStor->msg ?></span></div>
</div>
<div class="row gx-0">
<div class="col s-border-t py-2" id="nation-msg-position">
<div class="px-2">【 국가방침 】</div>
<div id='nation-msg-box'>
<div id='nation-msg'><?= nationMsg($generalObj) ?></div>
</div>
</div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">
【 접속자 】<?= onlinegen($generalObj) ?>
</div>
</div>
<?php if ($session->userGrade >= 5) : ?>
<div class="row">
<div class="col">
<a href='_admin1.php' target='_blank'><button type='button'>게임관리</button></a>
<a href='_admin2.php' target='_blank'><button type='button'>회원관리</button></a>
<a href='_admin4.php' target='_blank'><button type='button'>멀티관리</button></a>
<a href='_admin5.php' target='_blank'><button type='button'>일제정보</button></a>
<a href='_admin7.php' target='_blank'><button type='button'>로그정보</button></a>
<a href='_admin8.php' target='_blank'><button type='button'>외교정보</button></a>
<a href='_119.php' target='_blank'><button type='button'>119</button></a>
</div>
</div>
<?php elseif ($session->userGrade == 4) : ?>
<div class="row">
<div class="col">
<a href='_119.php' target='_blank'><button type='button'>119</button></a>
</div>
</div>
<?php endif; ?>
<div id="map_view" class="gx-0">
<div id="mapZone" class="view-item"><?= getMapHtml($mapTheme) ?></div>
<div class="view-item" id="reservedCommandList"></div>
<div id="cityInfo" class="view-item" style="border:none;text-align:center;"><?= cityInfo($generalObj) ?></div>
<div id="routeButtons" class="view-item row justify-content-center"><button type='button' class='btn btn-sammo-base2 col-2 refreshPage'>갱 신</button><button type='button' class='btn btn-sammo-base2 col-3' onclick="location.replace('../')">로비로</button></div>
</div>
<div class="row gx-0">
<div class="col-md-6" id="nation-position"><?php myNationInfo($generalObj); ?></div>
<div class="col-md-6" id="general-position"><?php generalInfo($generalObj); ?></div>
</div>
<div class="row gx-0"><?= commandButton() ?></div>
<div class="row gx-0">
<div class="col-md-6" id="general_public_record-position">
<div class="bg1 center s-border-tb"><b>장수 동향</b></div>
<div id="general_public_record" style="text-align:left;"><?= formatHistoryToHTML(getGlobalActionLogRecent(15)) ?></div>
</div>
<div class="col-md-6" id="general_log-position">
<div class="bg1 center s-border-tb"><b>개인 기록</b></div>
<div id="general_log" style="text-align:left;"><?= formatHistoryToHTML(getGeneralActionLogRecent($me['no'], 15)) ?></div>
</div>
<div class="col-12" id="world_history-position">
<div class="bg1 center s-border-tb"><b>중원 정세</b></div>
<div id="world_history" colspan=2 style="text-align:left;"><?= formatHistoryToHTML(getGlobalHistoryLogRecent(15)) ?></div>
</div>
</div>
<div class="row toolbars gx-0"><?= allButton($gameStor->npcmode == 1) ?></div>
<div class="message_input_form bg0 gx-0 row">
<div id="mailbox_list-col" class="col-6 col-md-2 d-grid">
<select id="mailbox_list" size="1" class="form-control bg-dark text-white">
</select>
</div>
<div id="msg_input-col" class="col-12 col-md-8 d-grid">
<input type="text" id="msg_input" maxlength="99" class="form-control">
</div>
<div id="msg_submit-col" class="col-6 col-md-2 d-grid"><button id="msg_submit" class="btn btn-primary">서신전달&amp;갱신</button></div>
</div>
<div id="message_board" class="row gx-0">
<div class="col-md-6 board_side bg0" id='public_talk_position'>
<div class="board_header bg0">전체 메시지(최고99자)</div>
<section class="public_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="public">이전 메시지 불러오기</button></div>
</section>
</div>
<div class="col-md-6 board_side bg0" id='national_talk_position'>
<div class="board_header bg0">국가 메시지(최고99자)</div>
<section class="national_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="national">이전 메시지 불러오기</button></div>
</section>
</div>
</select>
<input type="textarea" id="msg_input" maxlength="99">
<button id="msg_submit">서신전달&amp;갱신</button><br>
내용 없이 '서신전달&amp;갱신'을 누르면 메세지창이 갱신됩니다.
</div>
<div><?=allButton($gameStor->npcmode==1)?></div>
<div id="message_board"><div style="left:0;" class="board_side bg0">
<div class="board_header bg0" id='public_talk_position'>전체 메시지(최고99자)</div>
<section class="public_message">
<button type="button" class="load_old_message btn btn-secondary btn-block" data-msg_type="public">이전 메시지 불러오기</button>
</section>
<div class="board_header bg0" id='secret_talk_position'>개인 메시지(최고99자)</div>
<section class="private_message">
<button type="button" class="load_old_message btn btn-secondary btn-block" data-msg_type="private">이전 메시지 불러오기</button>
</section>
</div><div style="right:0;" class="board_side bg0">
<div class="board_header bg0">국가 메시지(최고99자)</div>
<section class="national_message">
<button type="button" class="load_old_message btn btn-secondary btn-block" data-msg_type="national">이전 메시지 불러오기</button>
</section>
<div class="board_header bg0">외교 메시지(최고99자)</div>
<section class="diplomacy_message">
<button type="button" class="load_old_message btn btn-secondary btn-block" data-msg_type="diplomacy">이전 메시지 불러오기</button>
</section>
</div></div>
<div style="clear:left;"><?=allButton($gameStor->npcmode==1)?><?=banner()?></div>
</div>
<?php
if ($con == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다!");
}
if ($me['newmsg'] == 1) {
MessageBox("새로운 서신이 도착했습니다!");
}
if ($me['newvote'] == 1) {
$develcost = $gameStor->develcost*5;
MessageBox("설문조사에 참여하시면 금{$develcost}과 유니크템을 드립니다! (우측 상단 설문조사 메뉴)");
}
?>
<div class="col-md-6 board_side bg0" id='private_talk_position'>
<div class="board_header bg0">개인 메시지(최고99자)</div>
<section class="private_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="private">이전 메시지 불러오기</button></div>
</section>
</div>
<div class="col-md-6 board_side bg0" id='diplomacy_talk_position'>
<div class="board_header bg0">외교 메시지(최고99자)</div>
<section class="diplomacy_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="diplomacy">이전 메시지 불러오기</button></div>
</section>
</div>
</div>
</div>
<div class="row toolbars gx-0"><?= allButton($gameStor->npcmode == 1) ?><?= banner() ?></div>
</div>
<?php
if ($con == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다!");
}
if ($me['newmsg'] == 1) {
MessageBox("새로운 서신이 도착했습니다!");
}
if ($me['newvote'] == 1) {
$develcost = $gameStor->develcost * 5;
MessageBox("설문조사에 참여하시면 금{$develcost}과 유니크템을 드립니다! (우측 상단 설문조사 메뉴)");
}
?>
<div id="float-tabs">
<div class="btn-group-vertical">
<a href="#nation-msg-position" class="btn btn-sammo-nation">방침</a>
<a href="#mapZone" class="btn btn-sammo-nation">지도</a>
<a href="#reservedCommandList" class="btn btn-sammo-nation">명령</a>
<a href="#cityInfo" class="btn btn-sammo-nation">도시</a>
<a href="#nation-position" class="btn btn-sammo-nation">국가</a>
<a href="#general-position" class="btn btn-sammo-nation">장수</a>
</div>
<div class="btn-group-vertical">
<a href="#general_public_record-position" class="btn btn-secondary">동향</a>
<a href="#general_log-position" class="btn btn-secondary">개인</a>
<a href="#world_history-position" class="btn btn-secondary">정세</a>
</div>
<div class="btn-group-vertical">
<a href="#public_talk_position" class="btn btn-light active">전체</a>
<a href="#national_talk_position" class="btn btn-light">국가</a>
<a href="#private_talk_position" class="btn btn-light">개인</a>
<a href="#diplomacy_talk_position" class="btn btn-light">외교</a>
</div>
<div class="btn-group-vertical">
<button type='button' class='btn btn-sammo-base2 refreshPage'>갱 신</button>
<button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button>
</div>
</div>
</body>
</html>
</html>
-42
View File
@@ -1,42 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$session = Session::requireGameLogin([])->setReadOnly();
$generalID = $session->generalID;
$turnAmount = Util::getPost('amount', 'int');
$isRepeat = Util::getPost('is_repeat', 'bool', false);
if($turnAmount == null){
Json::die([
'result'=>false,
'reason'=>'턴이 입력되지 않았습니다.',
]);
}
if(abs($turnAmount) >= GameConst::$maxTurn){
Json::die([
'result'=>false,
'reason'=>'턴 숫자가 올바르지 않습니다.',
]);
}
if($isRepeat){
repeatGeneralCommand($generalID, $turnAmount);
}
else{
pushGeneralCommand($generalID, $turnAmount);
}
Json::die([
'result'=>true,
'reason'=>'success',
]);
-49
View File
@@ -1,49 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$session = Session::requireGameLogin([])->setReadOnly();
$db = DB::db();
$commandList = [];
$gameStor = KVStorage::getStorage($db, 'game_env');
$generalID = $session->generalID;
$rawTurn = $db->queryAllLists('SELECT turn_idx, action, arg, brief FROM general_turn WHERE general_id = %i ORDER BY turn_idx ASC', $generalID);
foreach($rawTurn as [$turn_idx, $action, $arg, $brief]){
$commandList[$turn_idx] = [
'action'=>$action,
'brief'=>$brief,
'arg'=>Json::decode($arg)
];
}
[$turnTerm, $year, $month, $lastExecute] = $gameStor->getValuesAsArray(['turnterm', 'year', 'month', 'turntime']);
[$turnTime, $rawGeneralAux] = $db->queryFirstList('SELECT turntime, aux FROM general WHERE no=%i', $generalID);
$generalAux = Json::decode($rawGeneralAux??'{}');
if(cutTurn($turnTime, $turnTerm) > cutTurn($lastExecute, $turnTerm)){
//이미 이번달에 실행된 턴이다.
$month++;
if($month >= 13){
$month -= 12;
$year += 1;
}
}
Json::die([
'result'=>true,
'turnTime'=>$turnTime,
'turnTerm'=>$turnTerm,
'year'=>$year,
'month'=>$month,
'date'=>TimeUtil::now(true),
'turn'=>$commandList,
'autorun_limit'=> $generalAux['autorun_limit']??null,
]);
+5 -5
View File
@@ -40,7 +40,7 @@ if(count($lastMsgGet) >= 10){
}
catch(\Exception $e){
$lastMsgGet = [];
}
}
}
$lastMsgGet[] = $now;
$session->lastMsgGet = Json::encode($lastMsgGet);
@@ -83,7 +83,7 @@ if($reqType == 'private'){
$nextSequence = $msg->id;
}
return $msg->toArray();
}, Message::getMessagesFromMailBoxOld($generalID, Message::MSGTYPE_PRIVATE, $reqTo, 20));
}, Message::getMessagesFromMailBoxOld($generalID, Message::MSGTYPE_PRIVATE, $reqTo, 15));
}
else if($reqType == 'public'){
$result['public'] = array_map(function(Message $msg)use (&$nextSequence){
@@ -91,7 +91,7 @@ else if($reqType == 'public'){
$nextSequence = $msg->id;
}
return $msg->toArray();
}, Message::getMessagesFromMailBoxOld(Message::MAILBOX_PUBLIC, Message::MSGTYPE_PUBLIC, $reqTo, 20));
}, Message::getMessagesFromMailBoxOld(Message::MAILBOX_PUBLIC, Message::MSGTYPE_PUBLIC, $reqTo, 15));
}
else if($reqType == 'national'){
$result['national'] = array_map(function(Message $msg)use (&$nextSequence){
@@ -99,7 +99,7 @@ else if($reqType == 'national'){
$nextSequence = $msg->id;
}
return $msg->toArray();
}, Message::getMessagesFromMailBoxOld(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_NATIONAL, $reqTo, 20));
}, Message::getMessagesFromMailBoxOld(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_NATIONAL, $reqTo, 15));
}
else{
$result['diplomacy'] = array_map(function(Message $msg)use (&$nextSequence, $permission){
@@ -112,7 +112,7 @@ else{
$values['option']['invalid'] = true;
}
return $values;
}, Message::getMessagesFromMailBoxOld(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_DIPLOMACY, $reqTo, 20));
}, Message::getMessagesFromMailBoxOld(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_DIPLOMACY, $reqTo, 15));
}
Json::die($result);
+5 -5
View File
@@ -26,7 +26,7 @@ if(count($lastMsgGet) >= 10){
}
catch(\Exception $e){
$lastMsgGet = [];
}
}
}
$lastMsgGet[] = TimeUtil::now();
$session->lastMsgGet = Json::encode($lastMsgGet);
@@ -66,7 +66,7 @@ $result['private'] = array_map(function(Message $msg) use (&$nextSequence, &$min
$lastType = 'private';
}
return $msg->toArray();
}, Message::getMessagesFromMailBox($generalID, Message::MSGTYPE_PRIVATE, 20, $reqSequence));
}, Message::getMessagesFromMailBox($generalID, Message::MSGTYPE_PRIVATE, 15, $reqSequence));
$result['public'] = array_map(function(Message $msg)use (&$nextSequence, &$minSequence, &$lastType){
if($msg->id > $nextSequence){
@@ -77,7 +77,7 @@ $result['public'] = array_map(function(Message $msg)use (&$nextSequence, &$minSe
$lastType = 'public';
}
return $msg->toArray();
}, Message::getMessagesFromMailBox(Message::MAILBOX_PUBLIC, Message::MSGTYPE_PUBLIC, 20, $reqSequence));
}, Message::getMessagesFromMailBox(Message::MAILBOX_PUBLIC, Message::MSGTYPE_PUBLIC, 15, $reqSequence));
$result['national'] = array_map(function(Message $msg)use (&$nextSequence, &$minSequence, &$lastType){
if($msg->id > $nextSequence){
@@ -88,7 +88,7 @@ $result['national'] = array_map(function(Message $msg)use (&$nextSequence, &$min
$lastType = 'national';
}
return $msg->toArray();
}, Message::getMessagesFromMailBox(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_NATIONAL, 20, $reqSequence));
}, Message::getMessagesFromMailBox(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_NATIONAL, 15, $reqSequence));
$result['diplomacy']= array_map(function(Message $msg)use (&$nextSequence, &$minSequence, &$lastType, $permission){
if($msg->id > $nextSequence){
@@ -104,7 +104,7 @@ $result['diplomacy']= array_map(function(Message $msg)use (&$nextSequence, &$min
$values['option']['invalid'] = true;
}
return $values;
}, Message::getMessagesFromMailBox(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_DIPLOMACY, 20, $reqSequence));
}, Message::getMessagesFromMailBox(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_DIPLOMACY, 15, $reqSequence));
if($lastType !== null){
array_pop($result[$lastType]);
+1 -36
View File
@@ -2,42 +2,7 @@
namespace sammo;
include "lib.php";
$templates = new \League\Plates\Engine(__DIR__.'/templates');
function getAutorunInfo($autorunOption){
global $templates;
$auto_info = [];
foreach($autorunOption['options'] as $auto_option => $value){
assert($value);
switch($auto_option){
case 'develop': $auto_info['내정'] = '내정'; break;
case 'warp': $auto_info['순간이동'] = '순간이동'; break;
case 'recruit': $auto_info['징병'] = $auto_info['징병']??'징병'; break;
case 'recruit_high': $auto_info['징병'] = '모병'; break;
case 'train': $auto_info['훈사'] = '훈련/사기진작'; break;
case 'battle': $auto_info['출병'] = '출병'; break;
case 'chief': $auto_info['사령턴'] = '사령턴'; break;
}
}
$limit = Util::toInt($autorunOption['limit_minutes']);
if($limit >= 43200){
$auto_info['제한'] = '항상 유효';
}
else if($limit % 60 == 0){
$auto_info['제한'] = ($limit/60).'시간 유효';
}
else{
$auto_info['제한'] = ($limit).'분 유효';
}
$auto_info = join(', ', array_values($auto_info));
return $templates->render('tooltip', [
'text'=>'자율행동',
'info'=>$auto_info,
'style'=>'text-decoration:underline',
'copyable_info'=>true
]);
}
include "func_template.php";
$session = Session::requireLogin([
'game'=>null,
@@ -0,0 +1,69 @@
<?php
namespace sammo\API\Command;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Json;
use sammo\KVStorage;
use sammo\TimeUtil;
use function sammo\cutTurn;
class GetReservedCommand extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$db = DB::db();
$commandList = [];
$gameStor = KVStorage::getStorage($db, 'game_env');
$generalID = $session->generalID;
$rawTurn = $db->queryAllLists('SELECT turn_idx, action, arg, brief FROM general_turn WHERE general_id = %i ORDER BY turn_idx ASC', $generalID);
foreach ($rawTurn as [$turn_idx, $action, $arg, $brief]) {
$commandList[$turn_idx] = [
'action' => $action,
'brief' => $brief,
'arg' => Json::decode($arg)
];
}
[$turnTerm, $year, $month, $lastExecute] = $gameStor->getValuesAsArray(['turnterm', 'year', 'month', 'turntime']);
[$turnTime, $rawGeneralAux] = $db->queryFirstList('SELECT turntime, aux FROM general WHERE no=%i', $generalID);
$generalAux = Json::decode($rawGeneralAux ?? '{}');
if (cutTurn($turnTime, $turnTerm) > cutTurn($lastExecute, $turnTerm)) {
//이미 이번달에 실행된 턴이다.
$month++;
if ($month >= 13) {
$month -= 12;
$year += 1;
}
}
return [
'result' => true,
'turnTime' => $turnTime,
'turnTerm' => $turnTerm,
'year' => $year,
'month' => $month,
'date' => TimeUtil::now(true),
'turn' => $commandList,
'autorun_limit' => $generalAux['autorun_limit'] ?? null,
];
}
}
+47
View File
@@ -0,0 +1,47 @@
<?php
namespace sammo\API\Command;
use sammo\Session;
use DateTimeInterface;
use sammo\Validator;
use function sammo\cutTurn;
use function sammo\pushGeneralCommand;
class PushCommand extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('required', [
'amount',
])
->rule('integer', 'amount')
->rule('min', 'amount', -12)
->rule('max', 'amount', 12);
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'];
if($amount == 0){
return '0은 불가능합니다';
}
pushGeneralCommand($session->generalID, $amount);
return [
'result'=>true
];
}
}
+45
View File
@@ -0,0 +1,45 @@
<?php
namespace sammo\API\Command;
use sammo\Session;
use DateTimeInterface;
use sammo\Validator;
use function sammo\cutTurn;
use function sammo\repeatGeneralCommand;
class RepeatCommand 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', 12);
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'];
repeatGeneralCommand($session->generalID, $amount);
return [
'result'=>true
];
}
}
+56
View File
@@ -0,0 +1,56 @@
<?php
namespace sammo\API\Command;
use sammo\Session;
use DateTimeInterface;
use sammo\GameConst;
use sammo\Util;
use sammo\Validator;
use function sammo\setGeneralCommand;
class ReserveCommand extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('required', [
'action',
'turnList'
])
->rule('lengthMin', 'action', 1)
->rule('integerArray', 'turnList');
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)
{
$action = $this->args['action'];
$turnList = $this->args['turnList'];
$arg = $this->args['arg']??[];
if(!$turnList){
return '턴이 입력되지 않았습니다';
}
if(!in_array($action, Util::array_flatten(GameConst::$availableGeneralCommand))){
return '사용할 수 없는 커맨드입니다.';
}
if(!is_array($arg)){
'올바른 arg 형태가 아닙니다.';
}
return setGeneralCommand($session->generalID, $turnList, $action, $arg);
}
}
+4 -2
View File
@@ -7,6 +7,8 @@ $input-color: #303030;
@import url("https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css");
@import "../../node_modules/bootswatch/dist/darkly/_variables.scss";
@import "./variables.scss";
@import "./bootswatch_custom_variables.scss";
@import "../../node_modules/bootstrap5/scss/bootstrap.scss";
@import "../../node_modules/bootswatch/dist/darkly/_bootswatch.scss";
@import "./bootswatch_custom.scss";
@import "./bootstrap_sammo.scss";
+67
View File
@@ -0,0 +1,67 @@
@function frontColor($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%);
}
}
}
.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);
&:hover,
&:active,
&:focus {
background-color: $color;
}
&,
&:not(.disabled):hover,
&:not(.disabled):active,
&:focus {
border-color: shade-color($color, 10%);
}
}
}
+329
View File
@@ -0,0 +1,329 @@
// Lumen 5.1.3
// Bootswatch
// Variables
$web-font-path: "https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400&display=swap" !default;
@if $web-font-path {
@import url($web-font-path);
}
// Mixins
@mixin shadow($width: 4px){
border-style: solid;
border-width: 0 1px $width 1px;
}
// Navbar
.navbar {
@include shadow();
@each $color, $value in $theme-colors {
&.bg-#{$color} {
border-color: shade-color($value, 10%);
}
}
}
// Buttons
.btn {
@include shadow();
text-transform: uppercase;
&:not(.disabled):hover {
margin-top: 1px;
border-bottom-width: 3px;
}
&:not(.disabled):active {
margin-top: 2px;
border-bottom-width: 2px;
@include box-shadow(none);
}
@each $color, $value in $theme-colors {
&-#{$color} {
&:hover,
&:active,
&:focus {
background-color: $value;
}
&,
&:not(.disabled):hover,
&:not(.disabled):active,
&:focus {
border-color: shade-color($value, 10%);
}
}
}
}
[class*="btn-outline"] {
border-top-width: 1px;
}
.btn-group-vertical {
.btn + .btn {
&:hover {
margin-top: -1px;
border-top-width: 1px;
}
&:active {
margin-top: -1px;
border-top-width: 2px;
}
}
}
// Typography
.text-secondary {
color: $gray-700 !important;
}
.blockquote-footer {
color: $gray-600;
}
// Forms
.form-control {
box-shadow: inset 0 2px 0 rgba(0, 0, 0, .075);
}
// Navs
.nav {
.open > a,
.open > a:hover,
.open > a:focus {
border-color: transparent;
}
}
.nav-tabs {
.nav-link {
color: $body-color;
&,
&.disabled,
&.disabled:hover,
&.disabled:focus {
margin-top: 6px;
border-color: $nav-tabs-border-color;
transition: padding-bottom .2s ease-in-out, margin-top .2s ease-in-out, border-bottom .2s ease-in-out;
}
&:not(.disabled):hover,
&:not(.disabled):focus,
&.active {
padding-bottom: add(.5rem, 6px);
border-bottom-color: transparent;
margin-top: 0;
}
}
&.nav-justified > li {
vertical-align: bottom;
}
}
.dropdown-menu {
margin-top: 0;
@include shadow();
border-top-width: 1px;
@include box-shadow(none);
}
.breadcrumb {
border-color: shade-color($breadcrumb-bg, 10%);
@include shadow();
}
.pagination {
a:hover {
text-decoration: none;
}
}
.pagination {
> li > a,
> li > span {
position: relative;
top: 0;
@include shadow();
color: $pagination-color;
font-weight: 700;
text-transform: uppercase;
&:hover,
&:focus {
top: 1px;
border-bottom-width: 3px;
text-decoration: none;
}
&:active {
top: 2px;
border-bottom-width: 2px;
}
}
> .disabled > a,
> .disabled > span {
&:hover {
top: 0;
@include shadow();
}
&:active {
top: 0;
@include shadow();
}
}
}
.pager {
> li > a,
> li > span,
> .disabled > a,
> .disabled > span {
&,
&:hover,
&:active {
border-left-width: 2px;
border-right-width: 2px;
}
}
}
// Indicators
.btn-close {
text-decoration: none;
opacity: .4;
&:hover,
&:focus {
opacity: 1;
}
}
.alert {
color: $white;
@include shadow();
&-primary {
background-color: $primary;
border-color: shade-color($primary, 10%);
}
&-secondary {
background-color: $secondary;
border-color: shade-color($secondary, 10%);
}
&-success {
background-color: $success;
border-color: shade-color($success, 10%);
}
&-info {
background-color: $info;
border-color: shade-color($info, 10%);
}
&-danger {
background-color: $danger;
border-color: shade-color($danger, 10%);
}
&-warning {
background-color: $warning;
border-color: shade-color($warning, 10%);
}
&-dark {
background-color: $dark;
border-color: shade-color($dark, 10%);
}
&-light {
background-color: $light;
border-color: shade-color($light, 10%);
}
.alert-link {
font-weight: 400;
color: $white;
text-decoration: underline;
}
&-secondary,
&-light {
&,
a,
.alert-link {
color: $body-color;
}
}
}
.badge {
&.bg-secondary,
&.bg-light {
color: $dark;
}
}
// Containers
a.list-group-item {
&-success {
&.active {
background-color: $success;
}
&.active:hover,
&.active:focus {
background-color: shade-color($success, 10%);
}
}
&-warning {
&.active {
background-color: $warning;
}
&.active:hover,
&.active:focus {
background-color: shade-color($warning, 10%);
}
}
&-danger {
&.active {
background-color: $danger;
}
&.active:hover,
&.active:focus {
background-color: shade-color($danger, 10%);
}
}
}
.modal,
.toast {
.btn-close {
background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'><path d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/></svg>");
}
}
+177
View File
@@ -0,0 +1,177 @@
// Darkly 5.1.3
// Bootswatch
$theme: "darkly" !default;
//
// Color system
//
$white: #fff !default;
$gray-100: #f8f9fa !default;
$gray-200: #ebebeb !default;
$gray-300: #dee2e6 !default;
$gray-400: #ced4da !default;
$gray-500: #adb5bd !default;
$gray-600: #888 !default;
$gray-700: #444 !default;
$gray-800: #303030 !default;
$gray-900: #222 !default;
$black: #000 !default;
$blue: #375a7f !default;
$indigo: #6610f2 !default;
$purple: #6f42c1 !default;
$pink: #e83e8c !default;
$red: #e74c3c !default;
$orange: #fd7e14 !default;
$yellow: #f39c12 !default;
$green: #00bc8c !default;
$teal: #20c997 !default;
$cyan: #3498db !default;
$primary: $blue !default;
$secondary: $gray-700 !default;
$success: $green !default;
$info: $cyan !default;
$warning: $yellow !default;
$danger: $red !default;
$light: $gray-500 !default;
$dark: $gray-800 !default;
$min-contrast-ratio: 1.9 !default;
// Body
$body-bg: $gray-900 !default;
$body-color: $white !default;
// Links
$link-color: $success !default;
// Fonts
// stylelint-disable-next-line value-keyword-case
$font-family-sans-serif: Lato, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default;
$h1-font-size: 3rem !default;
$h2-font-size: 2.5rem !default;
$h3-font-size: 2rem !default;
$text-muted: $gray-600 !default;
// Tables
$table-border-color: $gray-700 !default;
$table-bg-scale: 0 !default;
// Buttons
$btn-font-weight: 700 !default;
// Forms
$input-bg: $white !default;
$input-color: $gray-800 !default;
$input-border-color: $body-bg !default;
$input-group-addon-color: $gray-500 !default;
$input-group-addon-bg: $gray-700 !default;
$form-check-input-bg: $white !default;
$form-check-input-border: none !default;
$form-file-button-color: $white !default;
// Dropdowns
$dropdown-bg: $gray-900 !default;
$dropdown-border-color: $gray-700 !default;
$dropdown-divider-bg: $gray-700 !default;
$dropdown-link-color: $white !default;
$dropdown-link-hover-color: $white !default;
$dropdown-link-hover-bg: $primary !default;
// Navs
$nav-link-padding-x: 2rem !default;
$nav-link-disabled-color: $gray-500 !default;
$nav-tabs-border-color: $gray-700 !default;
$nav-tabs-link-hover-border-color: $nav-tabs-border-color $nav-tabs-border-color transparent !default;
$nav-tabs-link-active-color: $white !default;
$nav-tabs-link-active-border-color: $nav-tabs-border-color $nav-tabs-border-color transparent !default;
// Navbar
$navbar-padding-y: 1rem !default;
$navbar-dark-color: rgba($white, .6) !default;
$navbar-dark-hover-color: $white !default;
$navbar-light-color: rgba($gray-900, .7) !default;
$navbar-light-hover-color: $gray-900 !default;
$navbar-light-active-color: $gray-900 !default;
$navbar-light-toggler-border-color: rgba($gray-900, .1) !default;
// Pagination
$pagination-color: $white !default;
$pagination-bg: $success !default;
$pagination-border-width: 0 !default;
$pagination-border-color: transparent !default;
$pagination-hover-color: $white !default;
$pagination-hover-bg: lighten($success, 10%) !default;
$pagination-hover-border-color: transparent !default;
$pagination-active-bg: $pagination-hover-bg !default;
$pagination-active-border-color: transparent !default;
$pagination-disabled-color: $white !default;
$pagination-disabled-bg: darken($success, 15%) !default;
$pagination-disabled-border-color: transparent !default;
// Cards
$card-cap-bg: $gray-700 !default;
$card-bg: $gray-800 !default;
// Popovers
$popover-bg: $gray-800 !default;
$popover-header-bg: $gray-700 !default;
// Toasts
$toast-background-color: $gray-700 !default;
$toast-header-background-color: $gray-800 !default;
// Modals
$modal-content-bg: $gray-800 !default;
$modal-content-border-color: $gray-700 !default;
$modal-header-border-color: $gray-700 !default;
// Progress bars
$progress-bg: $gray-700 !default;
// List group
$list-group-color: $body-color !default;
$list-group-bg: $gray-800 !default;
$list-group-border-color: $gray-700 !default;
$list-group-hover-bg: $gray-700 !default;
$list-group-action-hover-color: $list-group-color !default;
$list-group-action-active-bg: $gray-900 !default;
// Breadcrumbs
$breadcrumb-padding-y: .375rem !default;
$breadcrumb-padding-x: .75rem !default;
$breadcrumb-bg: $gray-700 !default;
$breadcrumb-border-radius: .25rem !default;
// Close
$btn-close-color: $white !default;
$btn-close-opacity: .4 !default;
$btn-close-hover-opacity: 1 !default;
// Code
$pre-color: inherit !default;
+16
View File
@@ -0,0 +1,16 @@
$container-max-widths: (
sm: 500px,
md: 500px,
lg: 1020px,
xl: 1140px,
xxl: 1320px
) !default;
$grid-breakpoints: (
xs: 0,
sm: 520px,
md: 900px,
lg: 992px,
xl: 1200px,
xxl: 1400px
);
+286
View File
@@ -0,0 +1,286 @@
@import "./bootstrap5.scss";
html * {
max-height: 1000000px;
}
html,
body {
background-color: black;
color: white;
line-height: 1.3;
font-family: '맑은 고딕';
font-size: 13px;
}
table {
font-family: '맑은 고딕';
}
font {
font-family: '맑은 고딕';
}
input {
font-family: '맑은 고딕';
font-size: 13px;
}
select {
font-family: '굴림';
line-height: 100%;
}
.center {
text-align: center;
}
table.mimic_flex {
border-collapse: collapse;
border: none;
padding: 0;
}
.mimic_flex td,
.mimic_flex th {
border: none !important;
padding: 0px;
word-break: break-all;
}
table.tb_layout {
border-collapse: collapse;
padding: 0px;
font-size: 13px;
word-break: break-all;
font-family: '맑은 고딕';
}
.tb_layout td,
.tb_layout th {
border: solid 1px gray;
padding: 0px;
word-break: break-all;
font-family: '맑은 고딕';
;
}
div.bar_out {
position: relative;
border-top: solid 1px #888888;
border-bottom: solid 1px #333333;
padding: 0;
margin: 0;
width: 100%;
overflow: hidden;
}
div.bar_out div {
position: absolute;
left: 0;
top: 0;
height: 100%;
}
div.bar_out div.bar_in {
width: 100%;
}
/* */
.ev_warning {
color: orangered;
}
.ev_notice {
color: orangered;
}
.ev_succes {
color: lightgreen;
}
.ev_sell {
color: orange;
}
.ev_failed {
color: orangered;
}
.ev_highlight {
color: orangered;
}
/* TODO: 색상값이 아니라 의미에 따라 클래스 지정 */
.o_bullet::before {
color: cyan;
content: "";
}
.o_diamond::before {
color: orangered;
content: "";
}
.small_war_log {
display: inline-block;
}
.small_war_log .war_type_attack {
color: cyan;
}
.small_war_log .war_type_defense {
color: magenta;
}
.small_war_log .war_type_siege {
color: white;
}
.small_war_log .name_plate {
font-size: 0.75em;
}
.small_war_log .name_plate_cover {
color: yellow;
}
.small_war_log .crew_plate {
color: orangered;
font-size: 90%;
}
.t_date {
font-size: 0.75em;
}
.t_red {
color: red;
}
.t_blue {
color: blue;
}
.t_green {
color: green;
}
.t_magenta {
color: magenta;
}
.t_cyan {
color: cyan;
}
.t_limegreen {
color: limegreen;
}
.t_skyblue {
color: skyblue;
}
.t_orangered {
color: orangered;
}
.t_yellow {
color: yellow;
}
.t_white {
color: white;
}
.float_left {
float: left;
}
.tooltip {
font-size: 12px;
font-family: '맑은 고딕';
}
.tooltip_copyable_info .tooltiptext {
display: inline;
color: rgba(0, 0, 0, 0);
font-size: 0;
}
.tooltiptext {
display: none;
}
.hidden_but_copyable {
color: rgba(0, 0, 0, 0);
font-size: 0;
}
.btn-group-xs>.btn,
.btn-xs {
padding: .25rem .4rem;
font-size: .875rem;
line-height: .5;
border-radius: .2rem;
}
.edit_form.viewer {
max-height: 200px;
overflow-y: auto;
}
.trumbowyg-box {
margin: 0;
border-left: none;
border-right: none;
}
.edit_form.trumbowyg-editor {
margin: 0;
padding: 0;
}
.commandBasic {
background-color: black;
color: white;
}
.compensatePositive {
color: skyblue;
}
.compensateNegative {
color: orange;
}
.compensateNeutral {
color: white;
}
.commandBasic.commandImpossible {
background-color: red;
color: white;
}
.select2-selection--single.simple-select2-align-center .select2-selection__rendered {
text-align: center;
}
.select2-dropdown.simple-select2-align-center li.select2-results__option {
text-align: center;
}
.select2-container--bootstrap4 .select2-selection--single.text-secondary .select2-selection__rendered {
color: white;
}
.select2-container--bootstrap4 .text-secondary .select2-results__option[aria-selected=false] {
color: white;
}
-2
View File
@@ -1,5 +1,3 @@
@charset "UTF-8";
@import url('https://fonts.googleapis.com/css2?family=Nanum+Gothic:wght@400;700&display=swap');
@import '../../d_shared/common.css';
+545
View File
@@ -0,0 +1,545 @@
@import "./break_500px.scss";
@import "./bootstrap5.scss";
body {
color: white;
background-color: black;
border-width: 1px;
border-color: gray;
background-position: center;
background-repeat: repeat-y;
}
@include media-breakpoint-up(md) {
#container {
width: 1000px;
margin: 0 auto;
}
}
@include media-breakpoint-down(md) {
body {
overflow-x: hidden;
}
#container {
width: 500px;
margin: 0 auto;
}
}
.avoid-wrap {
display: inline-block;
}
#map_view {
display: grid;
}
.mainCityInfo {
display: grid;
border-right: solid 1px gray;
border-bottom: solid 1px gray;
.gPanel {
display: grid;
grid-template-columns: 1fr 2fr;
border-top: solid 1px gray;
border-left: solid 1px gray;
.gHead {
display: flex;
justify-content: center;
align-items: center;
}
}
.cityNamePanel,
.nationNamePanel {
font-weight: bold;
text-align: center;
border-top: solid 1px gray;
border-left: solid 1px gray;
}
.popPanel {
grid-column: 1 / 3;
grid-template-columns: 1fr 5fr;
}
}
.vote-cell {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
@include media-breakpoint-up(md) {
#map_view {
grid-template-columns: 700px 300px;
grid-template-rows: 520px 130px auto;
}
#mapZone {
height: 520px;
grid-column: 1 / 2;
grid-row: 1 / 2;
}
#cityInfo {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
#routeButtons {
grid-column: 1 / 3;
grid-row: 3 / 4;
}
#reservedCommandList {
width: 300px;
grid-column: 2 / 3;
grid-row: 1 / 3;
position: relative;
}
.commandPad {
position: absolute;
z-index: 7;
}
.buttonPlate {
display: grid;
grid-template-columns: repeat(10, 1fr);
padding: 0;
}
.toolbars>.buttonPlate {
grid-template-columns: repeat(8, 1fr);
}
.buttonPlate>a {
display: block;
text-decoration: none;
}
.commandButton {
width: 100%;
font-weight: bold;
font-size: 13px;
display: block;
}
.mainCityInfo {
grid-template-columns: 1fr 1fr 1fr 1fr;
.cityNamePanel,
.nationNamePanel {
grid-column: 1 / 5;
}
.officer4Panel {
grid-column: 4 / 5;
grid-row: 3 / 4;
}
.officer3Panel {
grid-column: 4 / 5;
grid-row: 4 / 5;
}
.officer2Panel {
grid-column: 4 / 5;
grid-row: 5 / 6;
}
}
}
#nation-msg-box {
position: relative;
overflow: hidden;
}
@include media-breakpoint-down(md) {
.buttonPlate {
display: grid;
grid-template-columns: repeat(5, 1fr);
padding: 0;
}
.toolbars>.buttonPlate {
grid-template-columns: repeat(4, 1fr);
}
.buttonPlate>a {
display: block;
text-decoration: none;
}
.commandButton {
width: 100%;
font-weight: bold;
font-size: 13px;
display: block;
}
#nation-msg {
transform-origin: 0px 0px;
width: 1000px;
transform: scale(0.5);
}
#mapZone {
grid-column: 1 / 2;
grid-row: 1 / 2;
.world_map {
width: 500px;
height: calc((500px + 20px) * 500 / 700);
}
.map_title {
transform-origin: 0px 0px;
transform: scale(calc(500 / 700));
margin-bottom: calc(-20px * 200 / 700);
}
.map_body {
transform-origin: 0px 0px;
transform: scale(calc(500 / 700));
}
}
#reservedCommandList {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
#routeButtons {
grid-column: 1 / 2;
grid-row: 3 / 4;
}
#cityInfo {
grid-column: 1 / 2;
grid-row: 4 / 5;
}
.mainCityInfo {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
.cityNamePanel,
.nationNamePanel {
grid-column: 1 / 4;
}
}
}
.toolbarButton {
@extend .btn;
@extend .btn-sammo-base2;
width: 100%;
font-weight: bold;
font-size: 13px;
}
.toolbarButton2 {
@extend .btn;
@extend .btn-sammo-base2;
color: magenta;
width: 100%;
font-weight: bold;
font-size: 13px;
&:hover,
&:focus,
&:active {
color: magenta;
}
}
.nation_info td {
height: 18px;
}
#sidebar {
position: fixed;
right: 0;
top: 50%;
transform: translateY(-50%);
}
/*임시용 */
#container {
/*width:1000px;*/
margin: auto;
font-size: 13px;
}
/*임시용 끝*/
#message_board {
position: relative;
}
/*
#message_board section{
overflow-y:auto;
overflow-x:hidden;
}
*/
.msg_plate {
width: 100%;
outline-style: solid;
outline-width: 1px;
outline-color: gray;
min-height: 64px;
font-size: 12px;
word-break: break-all;
color: white;
}
.msg_plate_private {
background-color: #5d1e1a;
}
.msg_plate_private.msg_plate_dest {
background-color: #5d461a;
}
.msg_plate_public {
background-color: #141c65;
}
@include media-breakpoint-up(md) {
#message_board section {
overflow-y: auto;
overflow-x: hidden;
height: 650px;
}
.public_message,
.diplomacy_message,
.national_message,
.private_message {
min-height: 300px;
}
}
@include media-breakpoint-down(md) {
.public_message,
.diplomacy_message,
.national_message,
.private_message {
min-height: 150px;
}
}
.msg_plate_national,
.msg_plate_diplomacy {
background-color: #00582c;
}
.msg_plate_national.msg_plate_dest,
.msg_plate_diplomacy.msg_plate_dest {
background-color: #704615;
}
.msg_plate_national.msg_plate_src,
.msg_plate_diplomacy.msg_plate_src {
background-color: #70153b;
}
.msg_icon {
float: left;
width: 64px;
height: 64px;
border-right: solid 1px gray;
}
.msg_time {
font-size: 0.75em;
font-weight: normal;
}
.msg_header {
font-weight: bold;
margin-bottom: 3px;
color: white;
position: relative;
}
.message_input_form {
position: relative;
}
#mailbox_list {
font-weight: bold;
}
.board_header {
color: white;
outline-style: solid;
outline-width: 1px;
outline-color: gray;
}
/*
.board_side{
position:absolute;
height:1370px;
width:50%;
overflow-y: hidden;
outline-style:solid;
outline-width:1px;
outline-color: gray;
display: flex;
flex-wrap: wrap;
flex-direction: column;
}
.board_side > div{
height: 1.2em;
}
*/
.msg_invalid {
color: rgba(255, 255, 255, 0.5);
}
.msg_body {
padding-left: 64px;
}
.msg_target {
margin: 2px 2px 0 2px;
padding: 2px 3px;
display: inline-block;
box-shadow: 2px 2px black;
border-radius: 3px;
}
.btn-delete-msg {
position: absolute;
right: 0;
top: 0;
margin: 2px 2px 0 2px;
font-size: 8px;
}
@include media-breakpoint-down(md) {
#mailbox_list-col {
order: 1;
}
#msg_submit-col {
order: 2;
}
#msg_input-col {
order: 3;
}
}
/*
.public_message .msg_target{
box-shadow: 2px 2px darkslategrey;
}
*/
.msg_target.msg_bright {
color: black;
}
.msg_target.msg_dark {
color: white;
}
.msg_from_to {
display: inline-block;
}
.msg_content {
margin-left: 10px;
margin-right: 5px;
overflow: hidden;
}
.msg_prompt {
text-align: right;
margin-top: 5px;
margin-right: 5px;
}
#mailbox_list option {
color: white;
background-color: black;
}
@include media-breakpoint-up(md) {
#float-tabs {
display: none;
}
}
@include media-breakpoint-down(md) {
#float-tabs {
position: fixed;
right: -1rem;
top: 10%;
width: 3rem;
.btn-group-vertical {
margin-bottom: 0.5em;
}
.btn {
padding-left: 0.5em;
padding-right: 1.5rem;
line-height: 1em;
}
}
}
@media (max-width: 560px) {
#float-tabs {
.btn {
opacity: 0.7;
}
.btn.active {
opacity: 1.0;
}
.btn:active {
opacity: 0.7;
}
}
}
.s-border-t {
border-top: gray solid 1px;
}
.s-border-b {
border-bottom: gray solid 1px;
}
.s-border-tb {
border-top: gray solid 1px;
border-bottom: gray solid 1px;
}
-2
View File
@@ -1,5 +1,3 @@
@charset "UTF-8";
#troop_list .cityText{
display:none;
}
+49
View File
@@ -0,0 +1,49 @@
$base1color: #141c65;
$base2color: #00582c;
$base3color: #704615;
$base4color: #70153b;
$sammoColors: (
'base1': $base1color,
'base2': $base2color,
'base3': $base3color,
'base4': $base4color,
);
$nationColors: (
"000000": #000000,
"FF0000": #FF0000,
"800000": #800000,
"A0522D": #A0522D,
"FF6347": #FF6347,
"FFA500": #FFA500,
"FFDAB9": #FFDAB9,
"FFD700": #FFD700,
"FFFF00": #FFFF00,
"7CFC00": #7CFC00,
"00FF00": #00FF00,
"808000": #808000,
"008000": #008000,
"2E8B57": #2E8B57,
"008080": #008080,
"20B2AA": #20B2AA,
"6495ED": #6495ED,
"7FFFD4": #7FFFD4,
"AFEEEE": #AFEEEE,
"87CEEB": #87CEEB,
"00FFFF": #00FFFF,
"00BFFF": #00BFFF,
"0000FF": #0000FF,
"000080": #000080,
"483D8B": #483D8B,
"7B68EE": #7B68EE,
"BA55D3": #BA55D3,
"800080": #800080,
"FF00FF": #FF00FF,
"FFC0CB": #FFC0CB,
"F5F5DC": #F5F5DC,
"E0FFFF": #E0FFFF,
"FFFFFF": #FFFFFF,
"A9A9A9": #A9A9A9,
"330000": #330000,
);
+18 -22
View File
@@ -1,22 +1,18 @@
<div class="buttonPlate bg1">
<div>
<a href="a_status.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">세력</button></a>
<a href="a_kingdomList.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">세력일람</button></a>
<a href="a_genList.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">일람</button></a>
<a href="a_bestGeneral.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">명장일람</button></a>
<a href="a_history.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">연감</button></a>
<a href="a_hallOfFame.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">명예의전당</button></a>
<a href="a_emperior.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">왕조일람</button></a>
<a href="a_traffic.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">접속량정보</button></a>
</div>
<div>
<a href="/bbs/board" target="_blank"><button type="button" class="toolbarButton2">삼모게시판</button></a>
<a href="/bbs/tip" target="_blank"><button type="button" class="toolbarButton">/강좌</button></a>
<a href="/bbs/news" target="_blank"><button type="button" class="toolbarButton">삼국 일보</button></a>
<a href="/bbs/history2" target="_blank"><button type="button" class="toolbarButton">개인 열전</button></a>
<a href="/bbs/history3" target="_blank"><button type="button" class="toolbarButton">국가 열전</button></a>
<a href="/bbs/patch" target="_blank"><button type="button" class="toolbarButton">패치 내역</button></a>
<a href="battle_simulator.php" target="_blank"><button type="button" class="toolbarButton">전투 시뮬레이터</button></a>
<a href="<?=$site?>" target="_blank" class="open-window"><button type="button" class="toolbarButton"><?=$call?></button></a>
</div>
</div>
<div class="buttonPlate">
<a href="a_status.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">세력도</button></a>
<a href="a_kingdomList.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">세력일람</button></a>
<a href="a_genList.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">장수일람</button></a>
<a href="a_bestGeneral.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">장일람</button></a>
<a href="a_history.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">연감</button></a>
<a href="a_hallOfFame.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">명예의전당</button></a>
<a href="a_emperior.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">왕조일람</button></a>
<a href="a_traffic.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">접속량정보</button></a>
<a href="/bbs/board" target="_blank"><button type="button" class="toolbarButton2">삼모게시판</button></a>
<a href="/bbs/tip" target="_blank"><button type="button" class="toolbarButton">/강좌</button></a>
<a href="/bbs/news" target="_blank"><button type="button" class="toolbarButton">삼국 일보</button></a>
<a href="/bbs/history2" target="_blank"><button type="button" class="toolbarButton">개인 열전</button></a>
<a href="/bbs/history3" target="_blank"><button type="button" class="toolbarButton">국가 열전</button></a>
<a href="/bbs/patch" target="_blank"><button type="button" class="toolbarButton">패치 내역</button></a>
<a href="battle_simulator.php" target="_blank"><button type="button" class="toolbarButton">전투 시뮬레이터</button></a>
<a href="<?= $site ?>" target="_blank" class="open-window"><button type="button" class="toolbarButton"><?= $call ?></button></a>
</div>
+20 -23
View File
@@ -1,25 +1,22 @@
<div class='buttonPlate bg2'>
<div>
<a href='v_board.php'><button type="button" class='commandButton' <?=$meLevel>=1?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>회 의 실</button></a>
<a href='v_board.php?isSecret=true'><button type="button" class='commandButton' <?=$permission>=2?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>기 밀 실</button></a>
<a href='b_troop.php'><button type="button" class='commandButton' <?=($meLevel>=1&&$nationLevel>=1)?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>부대 편성</button></a>
<a href='t_diplomacy.php'><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>외 교 부</button></a>
<a href='b_myBossInfo.php'><button type="button" class='commandButton' <?=$meLevel>=1?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>인 사 부</button></a>
<a href='b_dipcenter.php'><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>내 무 부</button></a>
<a href='b_chiefcenter.php'><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>사 령 부</button></a>
<a href='v_NPCControl.php'><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>NPC 정책</button></a>
<a href='b_genList.php' target='_blank' class="open-window"><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>암 행 부</button></a>
<a href='b_tournament.php' target='_blank' class="open-window"><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>토 너 먼 트</button></a>
<a href='b_myKingdomInfo.php'><button type="button" class='commandButton' <?=$meLevel>=1?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>세력 정보</button></a>
<a href='b_myCityInfo.php'><button type="button" class='commandButton' <?=($meLevel>=1&&$nationLevel>=1)?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>세력 도시</button></a>
<a href='b_myGenInfo.php'><button type="button" class='commandButton' <?=$meLevel>=1?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>세력 장수</button></a>
<a href='b_diplomacy.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>중원 정보</button></a>
<a href='b_currentCity.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>현재 도시</button></a>
<a href='b_battleCenter.php' target='_blank' class="open-window"><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>감 찰 부</button></a>
<a href='v_inheritPoint.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>유산 관리</button></a>
<a href='b_myPage.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>내 정보&amp;설정</button></a>
<a href='b_auction.php' target='_blank' class="open-window"><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>거 래 장</button></a>
<a href='b_betting.php' target='_blank' class="open-window"><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>베 팅 장</button></a>
</div>
<a href='v_board.php' class='commandButton btn btn-sammo-nation' <?=$meLevel>=1?'':'disabled'?>>회 의 실</a>
<a href='v_board.php?isSecret=true' class='commandButton btn btn-sammo-nation disabled'>기 밀 실</a>
<a href='b_troop.php' class='commandButton btn btn-sammo-nation <?=($meLevel>=1&&$nationLevel>=1)?'':'disabled'?>'>부대 편성</a>
<a href='t_diplomacy.php' class='commandButton btn btn-sammo-nation <?=$showSecret?'':'disabled'?>'>외 교 부</a>
<a href='b_myBossInfo.php' class='commandButton btn btn-sammo-nation <?=$meLevel>=1?'':'disabled'?>'>인 사 부</a>
<a href='b_dipcenter.php' class='commandButton btn btn-sammo-nation <?=$showSecret?'':'disabled'?>'>내 무 부</a>
<a href='b_chiefcenter.php' class='commandButton btn btn-sammo-nation <?=$showSecret?'':'disabled'?>'>사 령 부</a>
<a href='v_NPCControl.php' class='commandButton btn btn-sammo-nation <?=$showSecret?'':'disabled'?>'>NPC 정책</a>
<a href='b_genList.php' target='_blank' class='open-window commandButton btn btn-sammo-nation <?=$showSecret?'':'disabled'?>'>암 행 부</a>
<a href='b_tournament.php' target='_blank' class='open-window commandButton btn btn-sammo-nation'>토 너 먼 트</a>
<a href='b_myKingdomInfo.php' class='commandButton btn btn-sammo-nation <?=$meLevel>=1?'':'disabled'?>'>세력 정보</a>
<a href='b_myCityInfo.php' class='commandButton btn btn-sammo-nation <?=($meLevel>=1&&$nationLevel>=1)?'':'disabled'?>'>세력 도시</a>
<a href='b_myGenInfo.php' class='commandButton btn btn-sammo-nation <?=$meLevel>=1?'':'disabled'?>'>세력 장수</a>
<a href='b_diplomacy.php' class='commandButton btn btn-sammo-nation'>중원 정보</a>
<a href='b_currentCity.php' class='commandButton btn btn-sammo-nation'>현재 도시</a>
<a href='b_battleCenter.php' target='_blank' class='open-window commandButton btn btn-sammo-nation <?=$showSecret?'':'disabled'?>'>감 찰 부</a>
<a href='v_inheritPoint.php' class='commandButton btn btn-sammo-nation'>유산 관리</a>
<a href='b_myPage.php' class='commandButton btn btn-sammo-nation'>내 정보&amp;설정</a>
<a href='b_auction.php' target='_blank' class='open-window commandButton btn btn-sammo-nation'>거 래 장</a>
<a href='b_betting.php' target='_blank' class='open-window commandButton btn btn-sammo-nation'>베 팅 장</a>
</div>
+48 -47
View File
@@ -1,47 +1,48 @@
<table style='width:100%;' class='tb_layout bg2'>
<tr><td colspan=8 style='text-align:center;height:20px;color:<?=$nationTextColor?>;background-color:<?=$nationColor?>;font-weight:bold;font-size:13px;'> <?=$region?> | <?=$levelText?> 】 <?=$name?></td></tr>
<tr><td colspan=8 style='text-align:center;height:20px;color:<?=$nationTextColor?>;background-color:<?=$nationColor?>'><b><?=$nationName?"지배 국가 【 {$nationName} 】":'공 백 지'?></b></td>
</tr>
<tr>
<td rowspan=2 style='text-align:center;' class='bg1'><b>주민</b></td>
<td height=7 colspan=3><?=$this->bar($pop/$pop_max*100)?></td>
<td rowspan=2 style='text-align:center;' class='bg1'><b>민심</b></td>
<td height=7><?=$this->bar($trust)?></td>
<td rowspan=2 style='text-align:center;' class='bg1'><b>태수</b></td>
<td rowspan=2 style='text-align:center;'><?=$officerName[4]?></td>
</tr>
<tr>
<td colspan=3 style='text-align:center;'><?=$pop?>/<?=$pop_max?></td>
<td style='text-align:center;'><?=round($trust, 1)?></td>
</tr>
<tr>
<td width=50 rowspan=2 style='text-align:center;' class='bg1'><b>농업</b></td>
<td width=100 height=7><?=$this->bar($agri/$agri_max*100)?></td>
<td width=50 rowspan=2 style='text-align:center;' class='bg1'><b>상업</b></td>
<td width=100 height=7><?=$this->bar($comm/$comm_max*100)?></td>
<td width=50 rowspan=2 style='text-align:center;' class='bg1'><b>치안</b></td>
<td width=100 height=7><?=$this->bar($secu/$secu_max*100)?></td>
<td width=50 rowspan=2 style='text-align:center;' class='bg1'><b>군사</b></td>
<td rowspan=2 style='text-align:center;'><?=$officerName[3]?></td>
</tr>
<tr>
<td style='text-align:center;'><?=$agri?>/<?=$agri_max?></td>
<td style='text-align:center;'><?=$comm?>/<?=$comm_max?></td>
<td style='text-align:center;'><?=$secu?>/<?=$secu_max?></td>
</tr>
<tr>
<td rowspan=2 style='text-align:center;' class='bg1'><b>수비</b></td>
<td height=7><?=$this->bar($def/$def_max*100)?></td>
<td rowspan=2 style='text-align:center;' class='bg1'><b>성벽</b></td>
<td height=7><?=$this->bar($wall/$wall_max*100)?></td>
<td rowspan=2 style='text-align:center;' class='bg1'><b>시세</b></td>
<td height=7><?=$this->bar(($trade-95)*10)?></td>
<td rowspan=2 style='text-align:center;' class='bg1'><b>종사</b></td>
<td rowspan=2 style='text-align:center;'><?=$officerName[2]?></td>
</tr>
<tr>
<td style='text-align:center;'><?=$def?>/<?=$def_max?></td>
<td style='text-align:center;'><?=$wall?>/<?=$wall_max?></td>
<td style='text-align:center;'><?=$trade?"{$trade}%":'상인없음'?></td>
</tr>
</table>
<div style='width:100%;' class='tb_layout bg2 mainCityInfo'>
<div class="cityNamePanel" style="color:<?= $nationTextColor ?>;background-color:<?= $nationColor ?>;"><div> <?= $region ?> | <?= $levelText ?> 】 <?= $name ?></div></div>
<div class="nationNamePanel" style="color:<?= $nationTextColor ?>;background-color:<?= $nationColor ?>;"><?= $nationName ? "지배 국가 【 {$nationName} 】" : '공 백 지' ?></div>
<div class="gPanel popPanel">
<div class="gHead bg1">주민</div>
<div class="gBody"><?= $this->bar($pop / $pop_max * 100) ?><?= $pop ?>/<?= $pop_max ?></div>
</div>
<div class="gPanel trustPanel">
<div class="gHead bg1">민심</div>
<div class="gBody"><?= $this->bar($trust) ?><?= round($trust, 1) ?></div>
</div>
<div class="gPanel agriPanel">
<div class="gHead bg1">농업</div>
<div class="gBody"><?= $this->bar($agri / $agri_max * 100) ?><?= $agri ?>/<?= $agri_max ?></div>
</div>
<div class="gPanel commPanel">
<div class="gHead bg1">상업</div>
<div class="gBody"><?= $this->bar($comm / $comm_max * 100) ?><?= $comm ?>/<?= $comm_max ?></div>
</div>
<div class="gPanel secuPanel">
<div class="gHead bg1">치안</div>
<div class="gBody"><?= $this->bar($secu / $secu_max * 100) ?><?= $secu ?>/<?= $secu_max ?></div>
</div>
<div class="gPanel defPanel">
<div class="gHead bg1">수비</div>
<div class="gBody"><?= $this->bar($def / $def_max * 100) ?><?= $def ?>/<?= $def_max ?></div>
</div>
<div class="gPanel wallPanel">
<div class="gHead bg1">성벽</div>
<div class="gBody"><?= $this->bar($wall / $wall_max * 100) ?><?= $wall ?>/<?= $wall_max ?></div>
</div>
<div class="gPanel tradePanel">
<div class="gHead bg1">시세</div>
<div class="gBody"><?= $this->bar(($trade - 95) * 10) ?><?= $trade ? "{$trade}%" : '상인없음' ?></div>
</div>
<div class="gPanel officer4Panel">
<div class="gHead bg1">태수</div>
<div class="gBody"><?= $officerName[4] ?></div>
</div>
<div class="gPanel officer3Panel">
<div class="gHead bg1">군사</div>
<div class="gBody"><?= $officerName[3] ?></div>
</div>
<div class="gPanel officer2Panel">
<div class="gHead bg1">종사</div>
<div class="gBody"><?= $officerName[2] ?></div>
</div>
</div>
+12 -12
View File
@@ -1,4 +1,4 @@
<div class="world_map map_theme_<?=$mapTheme?> draw_required">
<div class="world_map map_theme_<?= $mapTheme ?> draw_required">
<div class="map_title obj_tooltip" data-toggle="tooltip" data-placement="top" data-tooltip-class="map_title_tooltiptext">
<span class="map_title_text ">
</span>
@@ -9,20 +9,20 @@
<div class="map_bglayer2"></div>
<div class="map_bgroad"></div>
<div class="map_button_stack">
<button type="button" class="btn btn-primary map_toggle_cityname btn-xs" data-toggle="button" aria-pressed="false" autocomplete="off">
도시명 표기
</button><br>
<button type="button" class="btn btn-secondary map_toggle_single_tap btn-xs" data-toggle="button" aria-pressed="false" autocomplete="off">
두번 도시 이동
</button>
<button type="button" class="btn btn-primary map_toggle_cityname btn-sm btn-minimum" data-toggle="button" aria-pressed="false" autocomplete="off">
도시명 표기
</button><br>
<button type="button" class="btn btn-secondary map_toggle_single_tap btn-sm btn-minimum" data-toggle="button" aria-pressed="false" autocomplete="off">
두번 도시 이동
</button>
</div>
<div class="city_tooltip">
<div class="city_name">
</div>
<div class="city_tooltip">
<div class="city_name">
</div>
<div class="nation_name">
</div>
<div class="nation_name">
</div>
</div>
</div>
</div>
+516
View File
@@ -0,0 +1,516 @@
<template>
<div class="commandPad">
<div class="col alert alert-dark m-0 p-1 center">
<h4 class="m-0">명령 목록</h4>
</div>
<div class="row gx-1">
<div class="col d-grid">
<b-dropdown right split text="당기기" @click="pullGeneralCommandSingle">
<b-dropdown-item
v-for="turnIdx in maxPushTurn"
:key="turnIdx"
@click="pushGeneralCommand(-turnIdx)"
>{{ turnIdx }}
</b-dropdown-item>
</b-dropdown>
</div>
<div
class="col alert alert-primary m-0 p-0"
style="
text-align: center;
display: flex;
justify-content: center;
align-items: center;
"
>
{{ serverNow }}
</div>
<div class="col d-grid">
<b-dropdown right text="반복">
<b-dropdown-item
v-for="turnIdx in maxPushTurn"
:key="turnIdx"
@click="repeatGeneralCommand(turnIdx)"
>{{ turnIdx }}
</b-dropdown-item>
</b-dropdown>
</div>
</div>
<div class="commandTable">
<template
v-for="(turnObj, turnIdx) in reservedCommandList.slice(
0,
Math.min(maxTurn, viewMaxTurn)
)"
:key="turnIdx"
height="28"
:id="`command_${turnIdx}`"
:class="pressed[turnIdx] ? 'pressed' : ''"
>
<div class="idx_pad center d-grid" @click="toggleTurn(turnIdx)">
<b-button
size="sm"
:variant="pressed[turnIdx] ? 'info' : 'primary'"
>{{ turnIdx + 1 }}</b-button
>
</div>
<div
@click="selectTurn(turnIdx)"
height="24"
class="month_pad center"
:style="{
'white-space': 'nowrap',
'font-size': `${Math.min(
14,
(70 / (`${turnObj.year ?? 1}`.length + 8)) * 1.8
)}px`,
overflow: 'hidden',
}"
>
{{ turnObj.year ? `${turnObj.year}年` : "" }}
{{ turnObj.month ? `${turnObj.month}月` : "" }}
</div>
<div
class="time_pad center"
style="background-color: black; white-space: nowrap; overflow: hidden"
>
{{ turnObj.time }}
</div>
<div class="turn_pad center">
<span
class="turn_text"
:style="turnObj.style"
v-b-tooltip.hover
:title="turnObj.tooltip"
v-html="turnObj.brief"
></span>
</div>
</template>
</div>
<div class="row gx-1">
<div class="col d-grid">
<b-dropdown right split text="미루기" @click="pushGeneralCommandSingle">
<b-dropdown-item
v-for="turnIdx in maxPushTurn"
:key="turnIdx"
@click="pushGeneralCommand(turnIdx)"
>{{ turnIdx }}턴
</b-dropdown-item>
</b-dropdown>
</div>
<div class="col d-grid">
<b-dropdown right split @click="selectAll" text="전체선택">
<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>
<b-dropdown-divider></b-dropdown-divider>
<b-dropdown-text v-for="spanIdx in [3, 4, 5, 6, 7]" :key="spanIdx">
{{ spanIdx }}턴 간격<br />
<b-button-group>
<b-button
class="ignoreMe"
v-for="beginIdx in spanIdx"
:key="beginIdx"
@click="selectStep(beginIdx - 1, spanIdx)"
>{{ beginIdx }}</b-button
>
</b-button-group>
</b-dropdown-text>
</b-dropdown>
</div>
<div class="col d-grid">
<b-button @click="toggleViewMaxTurn">{{
flippedMaxTurn == viewMaxTurn ? "펼치기" : "접기"
}}</b-button>
</div>
</div>
<div class="row gx-0">
<div class="col-10 d-grid">
<b-form-select v-model="selectedCommand"
><b-form-select-option-group
v-for="cgroup in commandList"
:key="cgroup['category']"
:label="cgroup['category']"
><b-form-select-option
v-for="(citem, ckey) in cgroup['values']"
:value="ckey"
:key="ckey"
>{{ citem.title
}}{{ citem.possible ? "" : "(불가)" }}</b-form-select-option
>
</b-form-select-option-group></b-form-select
>
</div>
<div class="col-2 d-grid">
<b-button @click="reserveCommand()" variant="primary">실행</b-button>
</div>
</div>
</div>
</template>
<script lang="ts">
import addMilliseconds from "date-fns/esm/addMilliseconds";
import addMinutes from "date-fns/esm/addMinutes";
import { range } from "lodash";
import { stringifyUrl } from "query-string";
import { defineComponent } from "vue";
import { formatTime } from "./util/formatTime";
import { joinYearMonth } from "./util/joinYearMonth";
import { parseTime } from "./util/parseTime";
import { parseYearMonth } from "./util/parseYearMonth";
import { sammoAPI } from "./util/sammoAPI";
import { unwrap_any } from "./util/unwrap_any";
type commandItem = {
title: string;
compensation: number;
possible: boolean;
reqArg: boolean;
};
declare const maxTurn: number;
declare const maxPushTurn: number;
declare const commandList: {
category: string;
values: Record<string, commandItem>;
}[];
declare const serverNow: string;
type TurnObj = {
action: string;
brief: string;
arg: null | [] | Record<string, number | string | number[] | string[]>;
};
type TurnObjWithTime = TurnObj & {
time: string;
year?: number;
month?: number;
tooltip?: string;
style?: Record<string, unknown>;
};
type ReservedCommandResponse = {
result: true;
turnTime: string;
turnTerm: number;
year: number;
month: number;
date: string;
turn: TurnObj[];
autorun_limit: null | number;
};
const listReqArgCommand = new Set<string>();
for (const commandCategories of commandList) {
if (!commandCategories.values) {
continue;
}
for (const [commandName, commandObj] of Object.entries(
commandCategories.values
)) {
if (!commandObj.reqArg) {
continue;
}
listReqArgCommand.add(commandName);
}
}
function isDropdownChildren(e?: Event): boolean {
if (!e) {
return false;
}
if (!e.target) {
return false;
}
if (
(e.target as HTMLElement).classList.contains("dropdown-item") ||
(e.target as HTMLElement).classList.contains("dropdown-toggle-split") ||
(e.target as HTMLElement).classList.contains("ignoreMe")
) {
return true;
}
return false;
}
export default defineComponent({
name: "ReservedCommand",
methods: {
updateNow() {
const serverNow = addMilliseconds(new Date(), this.timeDiff);
this.serverNow = formatTime(serverNow, "HH:mm:ss");
setTimeout(() => {
this.updateNow();
}, 250);
},
toggleTurn(turnIdx: number) {
this.pressed[turnIdx] = !this.pressed[turnIdx];
},
selectTurn(turnIdx: number) {
this.pressed.fill(false);
this.pressed[turnIdx] = true;
},
selectAll(e: Event | true) {
//NOTE: split 구현에 버그가 있어서, 수동으로 구분해야함
if (e !== true && isDropdownChildren(e)) {
return;
}
let pressedCnt = 0;
for (const pressed of this.pressed) {
if (pressed) {
pressedCnt += 1;
}
}
if (pressedCnt * 3 > this.maxTurn) {
this.pressed.fill(false);
} else {
this.pressed.fill(true);
}
},
selectStep(begin: number, step: number) {
for (const idx of range(0, maxTurn)) {
if ((idx - begin) % step == 0) {
this.pressed[idx] = true;
} else {
this.pressed[idx] = false;
}
}
},
toggleViewMaxTurn() {
if (this.viewMaxTurn == this.flippedMaxTurn) {
this.viewMaxTurn = this.maxTurn;
} else {
this.viewMaxTurn = this.flippedMaxTurn;
}
},
async repeatGeneralCommand(amount: number) {
try {
await sammoAPI(`Command/RepeatCommand`, { amount });
} catch (e) {
console.error(e);
alert(`실패했습니다: ${e}`);
return;
}
await this.reloadCommandList();
},
async pushGeneralCommand(amount: number) {
try {
await sammoAPI("Command/PushCommand", { amount });
} catch (e) {
console.error(e);
alert(`실패했습니다: ${e}`);
return;
}
await this.reloadCommandList();
},
pushGeneralCommandSingle(e: Event) {
//NOTE: split 구현에 버그가 있어서, 수동으로 구분해야함
if (isDropdownChildren(e)) {
return;
}
void this.pushGeneralCommand(1);
},
pullGeneralCommandSingle(e: Event) {
//NOTE: split 구현에 버그가 있어서, 수동으로 구분해야함
if (isDropdownChildren(e)) {
return;
}
void this.pushGeneralCommand(-1);
},
async reloadCommandList() {
let result: ReservedCommandResponse;
try {
result = await sammoAPI("Command/GetReservedCommand");
} catch (e) {
console.error(e);
alert(`실패했습니다: ${e}`);
return;
}
const reservedCommandList: TurnObjWithTime[] = [];
let yearMonth = joinYearMonth(result.year, result.month);
const turnTime = parseTime(result.turnTime);
let nextTurnTime = new Date(turnTime);
const autorunLimitYearMonth = result.autorun_limit ?? yearMonth - 1;
const [autorunLimitYear, autorunLimitMonth] = parseYearMonth(
autorunLimitYearMonth
);
for (const obj of result.turn) {
const [year, month] = parseYearMonth(yearMonth);
let tooltip: string | undefined = undefined;
let style: Record<string, unknown> = {};
if (yearMonth <= autorunLimitYearMonth) {
if (obj.brief == "휴식") {
obj.brief = "휴식<small>(자율 행동)</small>";
}
style.color = "#aaffff";
tooltip = `자율 행동 기간: ${autorunLimitYear}년 ${autorunLimitMonth}월까지`;
}
reservedCommandList.push({
...obj,
year,
month,
time: formatTime(nextTurnTime, "HH:mm"),
tooltip,
style,
});
yearMonth += 1;
nextTurnTime = addMinutes(nextTurnTime, result.turnTerm);
}
this.reservedCommandList = reservedCommandList;
const serverNowObj = parseTime(result.date);
const clientNowObj = new Date();
const timeDiff = serverNowObj.getTime() - clientNowObj.getTime();
this.timeDiff = timeDiff;
},
async reserveCommand() {
const turnList: number[] = [];
for (const [turnIdx, pressed] of this.pressed.entries()) {
if (!pressed) {
continue;
}
turnList.push(turnIdx);
}
if (listReqArgCommand.has(this.selectedCommand)) {
document.location.href = stringifyUrl({
url: "b_processing.php",
query: {
command: unwrap_any<string>(this.selectedCommand),
turnList: turnList.join("_"),
},
});
return;
}
try {
await sammoAPI("Command/ReserveCommand", {
turnList,
action: this.selectedCommand,
});
} catch (e) {
console.error(e);
alert(`실패했습니다: ${e}`);
return;
}
await this.reloadCommandList();
},
},
data() {
const serverNowObj = parseTime(serverNow);
const clientNowObj = new Date();
const timeDiff = serverNowObj.getTime() - clientNowObj.getTime();
setTimeout(() => {
this.updateNow();
}, 250);
const pressed = Array.from<boolean>({ length: maxTurn }).fill(false);
pressed[0] = true;
const selectedCommand = "휴식";
const emptyTurn: TurnObjWithTime[] = Array.from<TurnObjWithTime>({
length: maxTurn,
}).fill({
arg: null,
brief: "",
action: "",
year: undefined,
month: undefined,
time: "",
});
return {
maxTurn,
flippedMaxTurn: 18,
viewMaxTurn: 18,
maxPushTurn,
commandList,
serverNow: formatTime(serverNowObj, "HH:mm:ss"),
timeDiff,
pressed,
selectedCommand,
reservedCommandList: emptyTurn,
autorun_limit: null as null | number,
};
},
mounted() {
void this.reloadCommandList();
},
});
</script>
<style lang="scss">
@import "../scss/break_500px.scss";
@import "../scss/variables.scss";
@import "../scss/bootswatch_custom_variables.scss";
@import "../../node_modules/bootstrap5/scss/bootstrap-utilities.scss";
.commandPad {
background-color: $gray-900;
}
.commandTable {
width: 100%;
display: grid;
grid-template-columns: minmax(30px, 1fr) minmax(70px, 2.5fr) minmax(40px, 1fr) 5fr;
//30, 70, 37.65, 160
}
@include media-breakpoint-up(md) {
.commandPad {
margin-left: 10px;
}
}
@include media-breakpoint-down(md) {
.dropdown-item {
padding: 8px;
}
.commandPad {
margin-top: 10px;
margin-bottom: 10px;
}
.month_pad,
.time_pad,
.turn_pad {
padding: 6px;
}
}
.month_pad:hover{
text-decoration: underline;
cursor: pointer;
}
.month_pad,
.time_pad,
.turn_pad {
display: flex;
justify-content: center;
align-items: center;
}
.turn_pad {
white-space: nowrap;
font-weight: lighter;
background-color: rgba($base1color, 0.5);
}
.turn_pad .turn_text {
display: inline-block;
}
</style>
+4 -3
View File
@@ -13,7 +13,6 @@
"bossInfo": "bossInfo.ts",
"myPage": "myPage.ts",
"extExpandCity": "extExpandCity.ts",
"main": "main.ts",
"dipcenter": "dipcenter.ts",
"diplomacy": "diplomacy.ts",
"currentCity": "currentCity.ts",
@@ -21,12 +20,14 @@
"history": "history.ts",
"select_general_from_pool": "select_general_from_pool.ts",
"extKingdoms": "extKingdoms.ts",
"common": "common_deprecated.ts"
"common": "common_deprecated.ts",
"main": "main.ts"
},
"ingame_vue": {
"v_inheritPoint": "v_inheritPoint.ts",
"v_board": "v_board.ts",
"v_NPCControl": "v_NPCControl.ts",
"v_join": "v_join.ts"
"v_join": "v_join.ts",
"v_main": "v_main.ts"
}
}
+3
View File
@@ -10,6 +10,9 @@ 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;
+2
View File
@@ -11,6 +11,8 @@ import Popper from 'popper.js';
exportWindow(Popper, 'Popper');//XXX: 왜 popper를 이렇게 불러야 하는가?
import 'bootstrap';
import "../scss/common_legacy.scss";
exportWindow(jQuery, '$');
exportWindow(jQuery, 'jQuery');
-1
View File
@@ -1,7 +1,6 @@
import $ from "jquery";
import axios from "axios";
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
/**
* object의 array를 id를 key로 삼는 object로 재 변환
*/
+141 -196
View File
@@ -2,213 +2,30 @@ import $ from 'jquery';
import Popper from 'popper.js';
exportWindow(Popper, 'Popper');//XXX: 왜 popper를 이렇게 불러야 하는가?
import 'bootstrap';
import { parseTime } from './util/parseTime';
import { addMilliseconds, addMinutes, differenceInMilliseconds } from 'date-fns';
import { formatTime } from './util/formatTime';
import { unwrap_any } from './util/unwrap_any';
import { activateFlip, errUnknown, initTooltip } from './common_legacy';
import { unwrap } from './util/unwrap';
import { setAxiosXMLHttpRequest } from './util/setAxiosXMLHttpRequest';
import { activateFlip, initTooltip } from './common_legacy';
import './msg.ts';
import './map.ts';
import { exportWindow } from './util/exportWindow';
import {stringifyUrl} from 'query-string';
import { joinYearMonth } from './util/joinYearMonth';
import { parseYearMonth } from './util/parseYearMonth';
exportWindow($, '$');
type TurnArg = {
//TODO: 채울것
}
type TurnItem = {
action: string,
brief: string,
arg: TurnArg,
}
type ReservedTurnResponse = {
result: true,
turnTime: string,
turnTerm: number,
year: number,
month: number,
date: string,
turn: TurnItem[],
autorun_limit: number|null,
}
import '../scss/main.scss';
import { unwrap } from './util/unwrap';
import { number } from 'vue-types';
$(function ($) {
setAxiosXMLHttpRequest();
$('#refreshPage').click(function () {
$('.refreshPage').click(function () {
document.location.reload();
return false;
});
function reloadCommandList() {
void $.get({
url: 'j_get_reserved_command.php',
dataType: 'json',
cache: false,
}).then(function (data: ReservedTurnResponse) {
if (!data) {
return;
}
if (!data.result) {
return;
}
const game_clock = parseTime(data.date);
const now_clock = new Date();
const $clock = $('#clock');
$clock.data('time-diff', differenceInMilliseconds(game_clock, now_clock));
$clock.val(formatTime(game_clock));
const turnTime = parseTime(data.turnTime);
let nextTurnTime = new Date(turnTime);
let nowYearMonth = joinYearMonth(data.year, data.month);
const autorunLimitYearMonth = data.autorun_limit ?? nowYearMonth - 1;
const [autorunLimitYear, autorunLimitMonth] = parseYearMonth(autorunLimitYearMonth);
for (const [turnIdx, turnInfo] of Object.entries(data.turn)) {
const [year, month] = parseYearMonth(nowYearMonth);
const $tr = $(`#command_${turnIdx}`);
$tr.find('.time_pad').text(formatTime(nextTurnTime, 'HH:mm'));
$tr.find('.month_pad').text(`${year}${month}`);
const $turn_pad = $tr.find('.turn_pad');
const $turn_text = $turn_pad.find('.turn_text');
$turn_text.text(turnInfo.brief).css('font-size', '13px');
if(nowYearMonth <= autorunLimitYearMonth){
const brief = turnInfo.brief != '휴식'? turnInfo.brief :'휴식<small>(자율 행동)</small>';
const autorunTooltip = `<span class="obj_tooltip" data-toggle="tooltip" data-placement="top"
><span style='color:#aaffff;'>${brief}</span
><span class="tooltiptext">자율 행동 기간: ${autorunLimitYear}${autorunLimitMonth}월까지</span
></span>`;
$turn_text.html(autorunTooltip);
initTooltip($turn_text);
}
const oWidth = unwrap($turn_pad.innerWidth());
const iWidth = unwrap($turn_text.outerWidth());
if (iWidth > oWidth * 0.95) {
const newFontSize = 13 * oWidth / iWidth * 0.9;
$turn_text.css('font-size', `${newFontSize}px`);
}
nextTurnTime = addMinutes(nextTurnTime, data.turnTerm);
nowYearMonth += 1;
}
console.log(data);
});
}
function myclock() {
const $clock = $('#clock');
const now_clock = new Date();
const rawTimeDiff = $clock.data('time-diff');
if (rawTimeDiff === null || rawTimeDiff === undefined) {
return;
}
const timeDiff = unwrap_any<number>(rawTimeDiff);
const gameClock = addMilliseconds(now_clock, timeDiff);
$('#clock').val(formatTime(gameClock));
}
function pushTurn(pushAmount: number) {
$.post({
url: 'j_general_turn.php',
dataType: 'json',
data: {
amount: pushAmount
}
}).then(function (data) {
if (!data.result) {
alert(data.reason);
}
reloadCommandList();
}, errUnknown);
}
function repeatTurn(repeatAmount: number) {
$.post({
url: 'j_general_turn.php',
dataType: 'json',
data: {
amount: repeatAmount,
is_repeat: true
}
}).then(function (data) {
if (!data.result) {
alert(data.reason);
}
reloadCommandList();
}, errUnknown);
}
$('#pullTurn').click(function () {
pushTurn(-parseInt(unwrap_any<string>($('#repeatAmount').val())));
});
$('#pushTurn').click(function () {
pushTurn(parseInt(unwrap_any<string>($('#repeatAmount').val())));
});
$('#repeatTurn').click(function () {
repeatTurn(parseInt(unwrap_any<string>($('#repeatAmount').val())));
});
function reserveTurn(turnList: number[], command: string) {
console.log(turnList, command);
$.post({
url: 'j_set_general_command.php',
dataType: 'json',
data: {
action: command,
turnList: turnList
}
}).then(function (data) {
if (!data.result) {
alert(data.reason);
}
reloadCommandList();
}, errUnknown);
}
$('#reserveTurn').click(function () {
const turnList = unwrap_any<string[]>($('#generalTurnSelector').val()).map(v => parseInt(v));
const $command = $('#generalCommandList option:selected');
if ($command.data('reqarg')) {
document.location.href = stringifyUrl({
url: 'b_processing.php',
query: {
command: unwrap_any<string>($command.val()),
turnList: turnList.join('_')
}
});
}
else {
reserveTurn(turnList, unwrap_any<string>($command.val()));
}
return false;
})
$('.open-window').on('click', function(e){
$('.open-window').on('click', function (e) {
e.preventDefault();
let target = $(e.target as HTMLAnchorElement);
while(target.attr('href') === undefined){
while (target.attr('href') === undefined) {
target = target.parent('a');
if(target.length == 0){
if (target.length == 0) {
return;
}
}
@@ -216,8 +33,136 @@ $(function ($) {
window.open(href);
});
setInterval(myclock, 500);
reloadCommandList();
activateFlip();
initTooltip();
});
});
function ready(fn: () => unknown) {
if (document.readyState != 'loading') {
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
(() => {
let finInit = false;
const objects: {
target: HTMLElement,
button: HTMLAnchorElement,
}[] = [];
let nationMsgBox!: HTMLElement;
let nationMsg!: HTMLElement;
let nationMsgHeight : number|undefined = undefined;
let commandSelector!: HTMLElement;
let deviceWidth = -1;
let viewportMeta! : HTMLMetaElement;
function init() {
const buttons = document.querySelectorAll<HTMLAnchorElement>('#float-tabs a.btn');
if (!buttons) {
return false;
}
finInit = true;
for (const button of buttons) {
const targetQuery = button.href.split('#');
if (!targetQuery || targetQuery.length < 2) {
continue;
}
const target = document.getElementById(targetQuery[1]);
if (!target) {
continue;
}
objects.push({ target, button });
}
nationMsgBox = unwrap(document.getElementById('nation-msg-box'));
nationMsg = unwrap(document.getElementById('nation-msg'));
commandSelector = unwrap(document.getElementById('reservedCommandList'));
viewportMeta = unwrap(document.querySelector<HTMLMetaElement>("meta[name=viewport]"));
}
function adjustViewportWidth() {
if(deviceWidth == window.screen.availWidth){
return;
}
deviceWidth = window.screen.availWidth;
const innerHeight = window.innerHeight;
const selectorHeight = commandSelector.offsetHeight*1.1;
if(deviceWidth < 500){
viewportMeta.content = 'width=500, initial-scale=1';
console.log(`2`);
return;
}
if(innerHeight < selectorHeight){
const maybeNextWidth = deviceWidth / innerHeight * selectorHeight;
if(maybeNextWidth >= 750){
viewportMeta.content = 'width=1000, initial-scale=1';
}
else{
viewportMeta.content = `height=${Math.ceil(selectorHeight)}, initial-scale=1`;
}
return;
}
}
function onScroll() {
if (!finInit && !init()) return;
for (const { button } of objects) {
button.classList.remove('active');
}
const screenHeight = window.innerHeight
for (const { target, button } of objects) {
const { top, bottom, height } = target.getBoundingClientRect();
if (top >= 0 && bottom <= screenHeight) {
//valid
}
else if (top <= 0 && bottom >= screenHeight) {
//valid
}
else if (top < 0) {
if (bottom / height < 0.8) {
continue;
}
}
else if (bottom > screenHeight) {
if ((screenHeight - top) / height < 0.8) {
continue;
}
}
button.classList.add('active');
}
if(nationMsgBox.offsetWidth < nationMsg.offsetWidth){
if(nationMsgHeight === undefined){
nationMsgHeight = nationMsgBox.offsetHeight;
nationMsgBox.style.height = `${nationMsgHeight / 2}px`;
}
}
else{
if(nationMsgBox.style.height){
nationMsgHeight = undefined;
nationMsgBox.style.height = '';
}
}
adjustViewportWidth();
}
ready(() => {
init();
onScroll();
window.addEventListener('scroll', onScroll, true);
window.addEventListener('orientationchange', onScroll, true);
});
})();
+35 -31
View File
@@ -18,7 +18,7 @@ declare global {
interface Window {
sam_toggleSingleTap?: boolean,
getCityPosition: () => CityPositionMap;
formatCityInfo: (city: MapCityParsedRaw)=>MapCityParsedRegionLevelText
formatCityInfo: (city: MapCityParsedRaw) => MapCityParsedRegionLevelText
}
}
@@ -323,7 +323,7 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
};
}
function mergeNationInfo(city: MapCityParsedName):MapCityParsedNation{
function mergeNationInfo(city: MapCityParsedName): MapCityParsedNation {
//nationID 값으로 isCapital, color, nation을 통합
const nationID = city.nationID;
@@ -343,7 +343,7 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
};
}
function mergeClickable(city:MapCityParsedNation): MapCityParsedClickable {
function mergeClickable(city: MapCityParsedNation): MapCityParsedClickable {
//clickable = (defaultCity << 4 ) | (remainSpy << 3) | (ourCity << 2) | (shownByGeneral << 1) | clickableAll
const id = city.id;
const nationID = city.nationID;
@@ -436,7 +436,7 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
});
if(myCity){
if (myCity) {
$world_map.find(`.city_base_${myCity} .city_filler`).addClass('my_city');
}
@@ -444,7 +444,7 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
return obj;
}
function drawBasicWorldMap(obj:MapCityDrawable) {
function drawBasicWorldMap(obj: MapCityDrawable) {
const $map_body = $(`${drawTarget} .map_body`);
@@ -496,7 +496,7 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
$map_body.append($cityObj);
});
if(myCity){
if (myCity) {
$world_map.find(`.city_base_${myCity} .city_filler`).addClass('my_city');
}
@@ -504,7 +504,7 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
return obj;
}
function setMouseWork(obj:MapCityDrawable) {
function setMouseWork(obj: MapCityDrawable) {
const $tooltip = $(drawTarget + ' .city_tooltip');
const $tooltip_city = $tooltip.find('.city_name');
const $tooltip_nation = $tooltip.find('.nation_name');
@@ -552,16 +552,17 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
$tooltip_nation.html('').hide();
}
let left = position.left;
let top = position.top;
const left = position.left;
const top = position.top;
const scale = $map_body.data('scale');
if (scale) {
left /= scale;
top /= scale;
const tooltipWidth = unwrap($tooltip.width());
if (left + tooltipWidth + 35 > window.innerWidth) {
$tooltip.css({ 'top': top + 45, 'left': left - tooltipWidth - 10 }).show();
}
else {
$tooltip.css({ 'top': top + 45, 'left': left + 35 }).show();
}
$tooltip.css({ 'top': top + 25, 'left': left + 35 }).show();
const touchMode = $this.data('touchMode') as number;
if (touchMode <= 1) {
@@ -590,16 +591,19 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
}
const rect = this.getBoundingClientRect();
let left = (e.clientX - rect.left - this.clientLeft + this.scrollLeft);
let top = (e.clientY - rect.top - this.clientTop + this.scrollTop);
const left = (e.clientX - rect.left - this.clientLeft + this.scrollLeft);
const top = (e.clientY - rect.top - this.clientTop + this.scrollTop);
const scale = $map_body.data('scale');
if (scale) {
left /= scale;
top /= scale;
const tooltipWidth = unwrap($tooltip.width());
if (e.clientX + rect.left + tooltipWidth + 10 > window.innerWidth) {
$tooltip.css({ 'top': top + 30, 'left': left - tooltipWidth - 10 });
}
else {
$tooltip.css({ 'top': top + 30, 'left': left + 10 });
}
$tooltip.css({ 'top': top + 10, 'left': left + 10 });
});
$objs.on('mouseenter', function () {
@@ -627,7 +631,7 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
$objs.on('click', function () {
//xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다.
const touchMode = $(this).data('touchMode') as number|undefined;
const touchMode = $(this).data('touchMode') as number | undefined;
if (touchMode === undefined) {
return;
}
@@ -641,7 +645,7 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
return obj;
}
function setCityClickable(obj:MapCityDrawable) {
function setCityClickable(obj: MapCityDrawable) {
obj.cityList.forEach(function (city) {
const $cityLink = $world_map.find(`.city_base_${city.id} .city_link`);
@@ -746,7 +750,7 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
if ($world_map.hasClass('draw_required')) {
if (useCachedMap) {
//일단 불러옴
await (async ()=>{
await (async () => {
const rawStoredMap = localStorage.getItem(storedOldMapKey);
if (!rawStoredMap) {
return;
@@ -757,14 +761,14 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
}
await setMapBackground(storedMap)
.then(convertCityObjs)
.then(isDetailMap?drawDetailWorldMap:drawBasicWorldMap)
.then(setMouseWork)
.then(setCityClickable)
.then(saveCityInfo);
.then(convertCityObjs)
.then(isDetailMap ? drawDetailWorldMap : drawBasicWorldMap)
.then(setMouseWork)
.then(setCityClickable)
.then(saveCityInfo);
})();
} else if (option.year && option.month) {
const rawStartYear = localStorage.getItem(storedStartYear) as string|undefined;
const rawStartYear = localStorage.getItem(storedStartYear) as string | undefined;
let startYear: number;
if (rawStartYear) {
startYear = JSON.parse(rawStartYear);
+28
View File
@@ -0,0 +1,28 @@
import axios from "axios";
import { isArray } from "lodash";
import { InvalidResponse } from "../defs";
type ValidResponse = {
result: true
}
export async function sammoAPI<ResultType extends ValidResponse>(path: string | string[], args?: Record<string, unknown>): Promise<ResultType> {
if (isArray(path)) {
path = path.join('/');
}
const response = await axios({
url: "api.php",
method: "post",
responseType: "json",
data: {
path,
args,
},
});
const result: InvalidResponse | ResultType = response.data;
if (!result.result) {
throw result.reason;
}
return result;
}
+9
View File
@@ -0,0 +1,9 @@
import { createApp } from 'vue'
import ReservedCommand from './ReservedCommand.vue';
import BootstrapVue3 from 'bootstrap-vue-3'
import { setAxiosXMLHttpRequest } from './util/setAxiosXMLHttpRequest';
setAxiosXMLHttpRequest();
createApp(ReservedCommand).use(BootstrapVue3).mount('#reservedCommandList')
+3 -3
View File
@@ -26,7 +26,7 @@
"async-validator": "^4.0.3",
"axios": "^0.21.4",
"bootstrap": "^4.6.0",
"bootstrap5": "npm:bootstrap@^5.1.1",
"bootstrap5": "npm:bootstrap@^5.1.3",
"core-js": "^3.17.3",
"date-fns": "^2.24.0",
"downloadjs": "^1.4.7",
@@ -58,8 +58,8 @@
"@vue/eslint-config-typescript": "^7.0.0",
"babel-plugin-lodash": "^3.3.4",
"babel-preset-modern-browsers": "^15.0.2",
"bootstrap-vue-3": "^0.0.3",
"bootswatch": "^5.1.1",
"bootstrap-vue-3": "^0.0.5",
"bootswatch": "^5.1.3",
"clean-terminal-webpack-plugin": "^3.0.0",
"css-loader": "^6.2.0",
"esbuild-loader": "^2.15.1",