Merge branch 'g38_ui' into devel
This commit is contained in:
@@ -9,6 +9,7 @@ body {
|
||||
color: white;
|
||||
line-height: 1.3;
|
||||
font-size: 14px;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
input {
|
||||
|
||||
+467
-341
@@ -1,165 +1,228 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
.world_map{
|
||||
width:700px;
|
||||
background:black;
|
||||
font-size:14px;
|
||||
color:white;
|
||||
.world_map {
|
||||
width: 700px;
|
||||
background: black;
|
||||
font-size: 14px;
|
||||
color: white;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.map_title{
|
||||
width:700px;
|
||||
height:20px;
|
||||
text-align:center;
|
||||
.map_title {
|
||||
width: 700px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.map_title_tooltiptext .tooltip-inner{
|
||||
max-width:220px;
|
||||
width:220px;
|
||||
.map_title_tooltiptext .tooltip-inner {
|
||||
max-width: 220px;
|
||||
width: 220px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.map_title_text{
|
||||
margin:auto;
|
||||
text-align:center;
|
||||
width:160px;
|
||||
display:block;
|
||||
line-height:20px;
|
||||
font-size:14px;
|
||||
font-weight:bold;
|
||||
.map_title_text {
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
width: 160px;
|
||||
display: block;
|
||||
line-height: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.map_body{
|
||||
width:700px;
|
||||
height:500px;
|
||||
position:relative;
|
||||
.map_body {
|
||||
width: 700px;
|
||||
height: 500px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.map_body .map_bglayer1{
|
||||
width:100%;
|
||||
height:100%;
|
||||
position:absolute;
|
||||
left:0;
|
||||
top:0;
|
||||
}
|
||||
|
||||
.map_body .map_bglayer2{
|
||||
width:100%;
|
||||
height:100%;
|
||||
position:absolute;
|
||||
left:0;
|
||||
top:0;
|
||||
}
|
||||
|
||||
.map_body .map_bgroad{
|
||||
width:100%;
|
||||
height:100%;
|
||||
position:absolute;
|
||||
left:0;
|
||||
top:0;
|
||||
}
|
||||
|
||||
.map_body .map_button_stack{
|
||||
position:absolute;
|
||||
right:0;
|
||||
bottom:0;
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
.map_body .map_toggle_cityname::after{
|
||||
content: "끄기"
|
||||
}
|
||||
|
||||
.map_body .map_toggle_cityname.active::after{
|
||||
content: "켜기"
|
||||
}
|
||||
|
||||
.map_body .map_toggle_single_tap{
|
||||
display:none;
|
||||
}
|
||||
|
||||
.map_body .map_toggle_single_tap::after{
|
||||
content: "끄기"
|
||||
}
|
||||
|
||||
.map_body .map_toggle_single_tap.active::after{
|
||||
content: "켜기"
|
||||
}
|
||||
|
||||
.world_map .city_tooltip{
|
||||
.map_body .map_bglayer1 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
z-index:16;
|
||||
display:none;
|
||||
min-width:120px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.map_body .map_bglayer2 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.map_body .map_bgroad {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.map_body .map_button_stack {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.map_body .map_toggle_cityname::after {
|
||||
content: "끄기"
|
||||
}
|
||||
|
||||
.map_body .map_toggle_cityname.active::after {
|
||||
content: "켜기"
|
||||
}
|
||||
|
||||
.map_body .map_toggle_single_tap {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.map_body .map_toggle_single_tap::after {
|
||||
content: "끄기"
|
||||
}
|
||||
|
||||
.map_body .map_toggle_single_tap.active::after {
|
||||
content: "켜기"
|
||||
}
|
||||
|
||||
.world_map .city_tooltip {
|
||||
position: absolute;
|
||||
z-index: 16;
|
||||
display: none;
|
||||
min-width: 120px;
|
||||
border: 0.02em gray solid;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.world_map .city_name{
|
||||
|
||||
.world_map .city_name {
|
||||
background-color: rgb(30, 164, 255);
|
||||
z-index: 6;
|
||||
line-height:15px;
|
||||
height:15px;
|
||||
line-height: 15px;
|
||||
height: 15px;
|
||||
|
||||
}
|
||||
.world_map .nation_name{
|
||||
|
||||
.world_map .nation_name {
|
||||
background-color: rgb(30, 164, 255);
|
||||
z-index: 6;
|
||||
line-height:15px;
|
||||
height:15px;
|
||||
line-height: 15px;
|
||||
height: 15px;
|
||||
border-top: 0.02em gray solid;
|
||||
text-align:right;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.world_map .map_flag{
|
||||
width:12px;
|
||||
height:12px;
|
||||
.world_map .map_flag {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.world_map.map_detail .my_city{
|
||||
border:solid 1px red;
|
||||
outline:dotted 4px red;
|
||||
border-radius: 33%;
|
||||
}
|
||||
|
||||
.world_map.map_detail .my_city:before {
|
||||
content: "";
|
||||
top: -2px;
|
||||
left: -2px;
|
||||
right: -2px;
|
||||
bottom: -2px;
|
||||
position: absolute;
|
||||
border-radius: 33%;
|
||||
overflow: hidden;
|
||||
|
||||
animation-duration: 3.9s;
|
||||
animation-name: blink-my-city-d1;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
|
||||
.world_map.map_detail .city_filler{
|
||||
position:absolute;
|
||||
width:calc(100% + 2px);
|
||||
height:calc(100% + 2px);
|
||||
left:-1px;
|
||||
top:-1px;
|
||||
background:transparent;
|
||||
.world_map.map_detail .my_city:after {
|
||||
content: "";
|
||||
top: -2px;
|
||||
left: -2px;
|
||||
right: -2px;
|
||||
bottom: -2px;
|
||||
position: absolute;
|
||||
border-radius: 33%;
|
||||
overflow: hidden;
|
||||
|
||||
animation-duration: 3.9s;
|
||||
animation-name: blink-my-city-d2;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
.world_map .city_detail_name{
|
||||
background-color:rgba(0,0,0,0.5);
|
||||
font-size:10px;
|
||||
position:absolute;
|
||||
white-space:nowrap;
|
||||
left:70%;
|
||||
bottom:-10px;
|
||||
color:white;
|
||||
|
||||
@keyframes blink-my-city-d1 {
|
||||
0% {
|
||||
outline: solid 4px transparent;
|
||||
}
|
||||
|
||||
50% {
|
||||
outline: solid 4px rgba(255, 0, 0, 1);
|
||||
}
|
||||
|
||||
100% {
|
||||
|
||||
outline: solid 4px transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.world_map.hide_cityname .city_detail_name{
|
||||
display:none;
|
||||
@keyframes blink-my-city-d2 {
|
||||
0% {
|
||||
outline: double 4px transparent;
|
||||
}
|
||||
|
||||
50% {
|
||||
outline: double 4px rgba(192, 192, 192, 1);
|
||||
}
|
||||
|
||||
100% {
|
||||
|
||||
outline: double 4px transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.city_base{
|
||||
position:absolute;
|
||||
width:40px;
|
||||
height:30px;
|
||||
|
||||
.world_map.map_detail .city_filler {
|
||||
position: absolute;
|
||||
width: calc(100% + 2px);
|
||||
height: calc(100% + 2px);
|
||||
left: -1px;
|
||||
top: -1px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.city_base .city_bg{
|
||||
z-index:1;
|
||||
position:absolute;
|
||||
.world_map .city_detail_name {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
font-size: 10px;
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
left: 70%;
|
||||
bottom: -10px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.world_map.hide_cityname .city_detail_name {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.city_base {
|
||||
position: absolute;
|
||||
width: 40px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.city_base .city_bg {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.city_base div{
|
||||
z-index:2;
|
||||
.city_base div {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -173,80 +236,80 @@
|
||||
}
|
||||
*/
|
||||
|
||||
.map_detail .city_base.city_level_1 .city_bg{
|
||||
.map_detail .city_base.city_level_1 .city_bg {
|
||||
/*수*/
|
||||
width:48px;
|
||||
height:45px;
|
||||
background-size:48px 45px;
|
||||
left:-4px;
|
||||
top:-7.5px;
|
||||
width: 48px;
|
||||
height: 45px;
|
||||
background-size: 48px 45px;
|
||||
left: -4px;
|
||||
top: -7.5px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_2 .city_bg{
|
||||
.map_detail .city_base.city_level_2 .city_bg {
|
||||
/*진*/
|
||||
width:60px;
|
||||
height:42px;
|
||||
background-size:60px 42px;
|
||||
left:-10px;
|
||||
top:-6px;
|
||||
width: 60px;
|
||||
height: 42px;
|
||||
background-size: 60px 42px;
|
||||
left: -10px;
|
||||
top: -6px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_3 .city_bg{
|
||||
.map_detail .city_base.city_level_3 .city_bg {
|
||||
/*관*/
|
||||
width:42px;
|
||||
height:42px;
|
||||
background-size:42px 42px;
|
||||
left:-1px;
|
||||
top:-6px;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
background-size: 42px 42px;
|
||||
left: -1px;
|
||||
top: -6px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_4 .city_bg{
|
||||
.map_detail .city_base.city_level_4 .city_bg {
|
||||
/*이*/
|
||||
width:60px;
|
||||
height:45px;
|
||||
background-size:60px 45px;
|
||||
left:-10px;
|
||||
top:-7.5px;
|
||||
width: 60px;
|
||||
height: 45px;
|
||||
background-size: 60px 45px;
|
||||
left: -10px;
|
||||
top: -7.5px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_5 .city_bg{
|
||||
.map_detail .city_base.city_level_5 .city_bg {
|
||||
/*소*/
|
||||
width:72px;
|
||||
height:48px;
|
||||
background-size:72px 48px;
|
||||
left:-16px;
|
||||
top:-9px;
|
||||
width: 72px;
|
||||
height: 48px;
|
||||
background-size: 72px 48px;
|
||||
left: -16px;
|
||||
top: -9px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_6 .city_bg{
|
||||
.map_detail .city_base.city_level_6 .city_bg {
|
||||
/*중*/
|
||||
width:78px;
|
||||
height:54px;
|
||||
background-size:78px 54px;
|
||||
left:-19px;
|
||||
top:-12px;
|
||||
width: 78px;
|
||||
height: 54px;
|
||||
background-size: 78px 54px;
|
||||
left: -19px;
|
||||
top: -12px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_7 .city_bg{
|
||||
.map_detail .city_base.city_level_7 .city_bg {
|
||||
/*대*/
|
||||
width:84px;
|
||||
height:60px;
|
||||
background-size:84px 60px;
|
||||
left:-22px;
|
||||
top:-15px;
|
||||
width: 84px;
|
||||
height: 60px;
|
||||
background-size: 84px 60px;
|
||||
left: -22px;
|
||||
top: -15px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_8 .city_bg{
|
||||
.map_detail .city_base.city_level_8 .city_bg {
|
||||
/*특*/
|
||||
width:96px;
|
||||
height:72px;
|
||||
background-size:96px 72px;
|
||||
left:-28px;
|
||||
top:-21px;
|
||||
width: 96px;
|
||||
height: 72px;
|
||||
background-size: 96px 72px;
|
||||
left: -28px;
|
||||
top: -21px;
|
||||
}
|
||||
|
||||
.city_img{
|
||||
position:absolute;
|
||||
.city_img {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -261,241 +324,304 @@
|
||||
*/
|
||||
|
||||
|
||||
.map_detail .city_base.city_level_1 .city_img{
|
||||
width:16px;
|
||||
height:15px;
|
||||
left:12px;
|
||||
top:7.5px;
|
||||
.map_detail .city_base.city_level_1 .city_img {
|
||||
width: 16px;
|
||||
height: 15px;
|
||||
left: 12px;
|
||||
top: 7.5px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_2 .city_img{
|
||||
width:20px;
|
||||
height:14px;
|
||||
left:10px;
|
||||
top:8px;
|
||||
.map_detail .city_base.city_level_2 .city_img {
|
||||
width: 20px;
|
||||
height: 14px;
|
||||
left: 10px;
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_3 .city_img{
|
||||
width:14px;
|
||||
height:14px;
|
||||
left:13px;
|
||||
top:8px;
|
||||
.map_detail .city_base.city_level_3 .city_img {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
left: 13px;
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_4 .city_img{
|
||||
width:20px;
|
||||
height:15px;
|
||||
left:10px;
|
||||
top:7.5px;
|
||||
.map_detail .city_base.city_level_4 .city_img {
|
||||
width: 20px;
|
||||
height: 15px;
|
||||
left: 10px;
|
||||
top: 7.5px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_5 .city_img{
|
||||
width:24px;
|
||||
height:16px;
|
||||
left:8px;
|
||||
top:7px;
|
||||
.map_detail .city_base.city_level_5 .city_img {
|
||||
width: 24px;
|
||||
height: 16px;
|
||||
left: 8px;
|
||||
top: 7px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_6 .city_img{
|
||||
width:26px;
|
||||
height:18px;
|
||||
left:7px;
|
||||
top:6px;
|
||||
.map_detail .city_base.city_level_6 .city_img {
|
||||
width: 26px;
|
||||
height: 18px;
|
||||
left: 7px;
|
||||
top: 6px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_7 .city_img{
|
||||
width:28px;
|
||||
height:20px;
|
||||
left:6px;
|
||||
top:5px;
|
||||
.map_detail .city_base.city_level_7 .city_img {
|
||||
width: 28px;
|
||||
height: 20px;
|
||||
left: 6px;
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_8 .city_img{
|
||||
width:32px;
|
||||
height:24px;
|
||||
left:4px;
|
||||
top:3px;
|
||||
.map_detail .city_base.city_level_8 .city_img {
|
||||
width: 32px;
|
||||
height: 24px;
|
||||
left: 4px;
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
.map_detail .city_base .city_state{
|
||||
.map_detail .city_base .city_state {
|
||||
position: absolute;
|
||||
top:5px; /*TODO:도시 레벨 별로 다르게 위치 설정해볼 것*/
|
||||
left:0;
|
||||
top: 5px;
|
||||
/*TODO:도시 레벨 별로 다르게 위치 설정해볼 것*/
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.map_detail .city_base .city_flag{
|
||||
.map_detail .city_base .city_flag {
|
||||
position: absolute;
|
||||
width:12px;
|
||||
height:12px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.map_detail .city_base .city_flag > img{
|
||||
width:12px;
|
||||
height:12px;
|
||||
.map_detail .city_base .city_flag>img {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_1 .city_flag{
|
||||
right:-8px;
|
||||
top:-4px;
|
||||
.map_detail .city_base.city_level_1 .city_flag {
|
||||
right: -8px;
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_2 .city_flag{
|
||||
right:-8px;
|
||||
top:-4px;
|
||||
.map_detail .city_base.city_level_2 .city_flag {
|
||||
right: -8px;
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_3 .city_flag{
|
||||
right:-8px;
|
||||
top:-4px;
|
||||
.map_detail .city_base.city_level_3 .city_flag {
|
||||
right: -8px;
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_4 .city_flag{
|
||||
right:-6px;
|
||||
top:-3px;
|
||||
.map_detail .city_base.city_level_4 .city_flag {
|
||||
right: -6px;
|
||||
top: -3px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_5 .city_flag{
|
||||
right:-6px;
|
||||
top:-4px;
|
||||
.map_detail .city_base.city_level_5 .city_flag {
|
||||
right: -6px;
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_6 .city_flag{
|
||||
right:-6px;
|
||||
top:-4px;
|
||||
.map_detail .city_base.city_level_6 .city_flag {
|
||||
right: -6px;
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_7 .city_flag{
|
||||
right:-6px;
|
||||
top:-4px;
|
||||
.map_detail .city_base.city_level_7 .city_flag {
|
||||
right: -6px;
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
.map_detail .city_base.city_level_8 .city_flag{
|
||||
right:-6px;
|
||||
top:-3px;
|
||||
.map_detail .city_base.city_level_8 .city_flag {
|
||||
right: -6px;
|
||||
top: -3px;
|
||||
}
|
||||
|
||||
.map_detail .city_base .city_flag .city_capital{
|
||||
.map_detail .city_base .city_flag .city_capital {
|
||||
position: absolute;
|
||||
width:10px;
|
||||
height:10px;
|
||||
top:0;
|
||||
right:-1px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
top: 0;
|
||||
right: -1px;
|
||||
}
|
||||
|
||||
.map_detail .city_base .city_flag .city_capital > img{
|
||||
width:10px;
|
||||
height:10px;
|
||||
.map_detail .city_base .city_flag .city_capital>img {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
/* Basic */
|
||||
|
||||
|
||||
|
||||
.world_map.map_basic .city_filler{
|
||||
position:absolute;
|
||||
width:100%;
|
||||
height:100%;
|
||||
left:0;
|
||||
top:0;
|
||||
background:transparent;
|
||||
}
|
||||
|
||||
.world_map.map_basic .my_city{
|
||||
outline:dotted 4px red;
|
||||
}
|
||||
|
||||
.map_basic .city_base .city_img{
|
||||
background-color:white;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_1 .city_img{
|
||||
width:12px;
|
||||
height:12px;
|
||||
left:14px;
|
||||
top:9px;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_2 .city_img{
|
||||
width:12px;
|
||||
height:12px;
|
||||
left:14px;
|
||||
top:9px;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_3 .city_img{
|
||||
width:14px;
|
||||
height:14px;
|
||||
left:13px;
|
||||
top:8px;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_4 .city_img{
|
||||
width:16px;
|
||||
height:14px;
|
||||
left:12px;
|
||||
top:8px;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_5 .city_img{
|
||||
width:18px;
|
||||
height:16px;
|
||||
left:11px;
|
||||
top:7px;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_6 .city_img{
|
||||
width:20px;
|
||||
height:16px;
|
||||
left:10px;
|
||||
top:7px;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_7 .city_img{
|
||||
width:22px;
|
||||
height:18px;
|
||||
left:9px;
|
||||
top:6px;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_8 .city_img{
|
||||
width:24px;
|
||||
height:18px;
|
||||
left:8px;
|
||||
top:6px;
|
||||
}
|
||||
|
||||
|
||||
.map_basic .city_base .city_capital{
|
||||
.world_map.map_basic .city_filler {
|
||||
position: absolute;
|
||||
width:5px;
|
||||
height:5px;
|
||||
top:-2px;
|
||||
right:-2px;
|
||||
background-color:yellow;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.map_basic .city_base .city_state{
|
||||
/*
|
||||
.world_map.map_basic .my_city {
|
||||
|
||||
}*/
|
||||
|
||||
|
||||
.world_map.map_basic .my_city:before {
|
||||
content: "";
|
||||
top: -2px;
|
||||
left: -2px;
|
||||
right: -2px;
|
||||
bottom: -2px;
|
||||
position: absolute;
|
||||
width:10px;
|
||||
height:10px;
|
||||
top:-2px;
|
||||
left:-4px;
|
||||
background-color:white;
|
||||
|
||||
animation-duration: 2s;
|
||||
animation-name: blink-my-city;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
.map_basic .city_base .city_state.city_state_war{
|
||||
background-color:red;
|
||||
|
||||
.world_map.map_basic .my_city:after {
|
||||
content: "";
|
||||
top: -2px;
|
||||
left: -2px;
|
||||
right: -2px;
|
||||
bottom: -2px;
|
||||
position: absolute;
|
||||
|
||||
animation-duration: 2s;
|
||||
animation-name: blink-my-city2;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
.map_basic .city_base .city_state.city_state_bad{
|
||||
background-color:orange;
|
||||
|
||||
@keyframes blink-my-city {
|
||||
0% {
|
||||
outline: dashed 5px transparent;
|
||||
}
|
||||
|
||||
50% {
|
||||
outline: dashed 5px white;
|
||||
}
|
||||
|
||||
100% {
|
||||
|
||||
outline: dashed 5px transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.map_basic .city_base .city_state.city_state_good{
|
||||
background-color:blue;
|
||||
@keyframes blink-my-city2 {
|
||||
0% {
|
||||
outline: dashed 4px transparent;
|
||||
}
|
||||
|
||||
50% {
|
||||
outline: dashed 4px red;
|
||||
}
|
||||
|
||||
100% {
|
||||
|
||||
outline: dashed 4px transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.btn.btn-minimum{
|
||||
|
||||
|
||||
.map_basic .city_base .city_img {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_1 .city_img {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
left: 14px;
|
||||
top: 9px;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_2 .city_img {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
left: 14px;
|
||||
top: 9px;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_3 .city_img {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
left: 13px;
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_4 .city_img {
|
||||
width: 16px;
|
||||
height: 14px;
|
||||
left: 12px;
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_5 .city_img {
|
||||
width: 18px;
|
||||
height: 16px;
|
||||
left: 11px;
|
||||
top: 7px;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_6 .city_img {
|
||||
width: 20px;
|
||||
height: 16px;
|
||||
left: 10px;
|
||||
top: 7px;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_7 .city_img {
|
||||
width: 22px;
|
||||
height: 18px;
|
||||
left: 9px;
|
||||
top: 6px;
|
||||
}
|
||||
|
||||
.map_basic .city_base.city_level_8 .city_img {
|
||||
width: 24px;
|
||||
height: 18px;
|
||||
left: 8px;
|
||||
top: 6px;
|
||||
}
|
||||
|
||||
|
||||
.map_basic .city_base .city_capital {
|
||||
position: absolute;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
top: -2px;
|
||||
right: -2px;
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
.map_basic .city_base .city_state {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
top: -2px;
|
||||
left: -4px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.map_basic .city_base .city_state.city_state_war {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.map_basic .city_base .city_state.city_state_bad {
|
||||
background-color: orange;
|
||||
}
|
||||
|
||||
.map_basic .city_base .city_state.city_state_good {
|
||||
background-color: blue;
|
||||
}
|
||||
|
||||
.btn.btn-minimum {
|
||||
padding-top: 1px;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#amount {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
#colorType {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.no-padding .select2-results__option {
|
||||
padding: 0;
|
||||
}
|
||||
@@ -52,6 +52,18 @@ function bar($per, $h = 7)
|
||||
return $str;
|
||||
}
|
||||
|
||||
function JSOptionsForCities(callable $infoCall = null){
|
||||
$result = [];
|
||||
foreach (CityConst::all() as $city) {
|
||||
$item = [$city->id, $city->name];
|
||||
|
||||
if($infoCall){
|
||||
$item[2] = $infoCall($city);
|
||||
}
|
||||
$result[] = $item;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function optionsForCities(callable $infoCall = null)
|
||||
{
|
||||
@@ -116,6 +128,15 @@ function closeButton()
|
||||
return "<button type='button' class='btn btn-primary back_btn' onclick=window.close()>창 닫기</button><br>";
|
||||
}
|
||||
|
||||
function JSCitiesBasedOnDistance(int $cityNo, int $maxDistance = 1): array{
|
||||
$distanceList = searchDistance($cityNo, $maxDistance, true);
|
||||
$result = [];
|
||||
for ($dist = 1; $dist <= $maxDistance; $dist++) {
|
||||
$result[$dist] = Util::array_get($distanceList[$dist], []);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
function printCitiesBasedOnDistance(int $cityNo, int $maxDistance = 1): string
|
||||
{
|
||||
|
||||
@@ -225,6 +225,14 @@ function formatName(string $name, int $npc): string
|
||||
return $name;
|
||||
}
|
||||
|
||||
function getMapTheme(): string
|
||||
{
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$mapTheme = $gameStor->map_theme ?? 'che';
|
||||
return $mapTheme;
|
||||
}
|
||||
|
||||
function getMapHtml(?string $mapTheme = null)
|
||||
{
|
||||
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
|
||||
|
||||
+1
-1
@@ -337,7 +337,7 @@ if (!$otherTextInfo) {
|
||||
?>
|
||||
</div>
|
||||
<nav class="navbar navbar-expand fixed-bottom navbar-dark bg-dark d-sm-block d-md-none p-0" id="navbar500">
|
||||
<div class="container-fluid">
|
||||
<div class="container-fluid px-0">
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav me-auto mx-auto">
|
||||
<li class="nav-item dropup">
|
||||
|
||||
@@ -475,15 +475,9 @@ abstract class BaseCommand{
|
||||
|
||||
abstract public function run():bool;
|
||||
|
||||
public function getJSPlugins():array {
|
||||
public function exportJSVars():array {
|
||||
return [];
|
||||
}
|
||||
public function getCSSFiles():array {
|
||||
return [];
|
||||
}
|
||||
public function getForm():string{
|
||||
throw new \sammo\MustNotBeReachedException();
|
||||
}
|
||||
|
||||
public function getLastTurn():LastTurn{
|
||||
return $this->generalObj->getLastTurn();
|
||||
|
||||
@@ -12,6 +12,7 @@ use \sammo\GameUnitConst;
|
||||
use \sammo\LastTurn;
|
||||
use \sammo\Command;
|
||||
|
||||
use function sammo\getMapTheme;
|
||||
use function \sammo\printCitiesBasedOnDistance;
|
||||
use function sammo\tryUniqueItemLottery;
|
||||
|
||||
@@ -169,31 +170,14 @@ class che_강행 extends Command\GeneralCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectCityByMap'
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'cities' => \sammo\JSOptionsForCities(),
|
||||
'distanceList' => \sammo\JSCitiesBasedOnDistance($this->generalObj->getCityID(), 3),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$currentCityID = $this->generalObj->getCityID();
|
||||
$currentCityName = CityConst::byID($currentCityID)->name;
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 도시로 강행합니다.<br>
|
||||
최대 3칸내 도시로만 강행이 가능합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<?= $currentCityName ?> => <select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'><br>
|
||||
<?= \sammo\optionsForCities() ?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<br>
|
||||
<br>
|
||||
<?= printCitiesBasedOnDistance($currentCityID, 3) ?>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,7 +169,7 @@ class che_건국 extends Command\GeneralCommand
|
||||
$general->addExperience($exp);
|
||||
$general->addDedication($ded);
|
||||
|
||||
$aux = Json::decode($this->nation['aux'])??[];
|
||||
$aux = Json::decode($this->nation['aux']) ?? [];
|
||||
$aux['can_국기변경'] = 1;
|
||||
|
||||
$db->update('city', [
|
||||
@@ -197,87 +197,25 @@ class che_건국 extends Command\GeneralCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$nationTypes = [];
|
||||
foreach (GameConst::$availableNationType as $nationType) {
|
||||
$nationClass = buildNationTypeClass($nationType);
|
||||
$nationTypes[$nationType] = [
|
||||
'type' => $nationType,
|
||||
'name' => $nationClass->getName(),
|
||||
'pros' => $nationClass::$pros,
|
||||
'cons' => $nationClass::$cons
|
||||
];
|
||||
}
|
||||
return [
|
||||
'colorSelect'
|
||||
'procRes' => [
|
||||
'available건국' => count(getAllNationStaticInfo()) < $this->env['maxnation'],
|
||||
'nationTypes' => $nationTypes,
|
||||
'colors' => GetNationColors(),
|
||||
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
|
||||
if (count(getAllNationStaticInfo()) >= $this->env['maxnation']) {
|
||||
return '더 이상 건국은 불가능합니다.';
|
||||
}
|
||||
|
||||
|
||||
//NOTE: 새로운 방법이 생기기 전까진 아무색이나 선택 가능하도록 하자.
|
||||
/*
|
||||
foreach(GetNationColors() as $color){
|
||||
$colorUsed[$color] = 0;
|
||||
}
|
||||
|
||||
foreach(getAllNationStaticInfo() as $nation){
|
||||
if($nation['level'] <= 0){
|
||||
continue;
|
||||
}
|
||||
$colorUsed[$nation['color']]++;
|
||||
}
|
||||
|
||||
$colorUsedCnt = 0;
|
||||
foreach($colorUsed as $color=>$used){
|
||||
if($used){
|
||||
continue;
|
||||
}
|
||||
$colorUsedCnt += 1;
|
||||
}
|
||||
|
||||
//색깔이 다 쓰였으면 그냥 모두 허용
|
||||
if($colorUsedCnt === count($colorUsed)){
|
||||
foreach(array_keys($colorUsed) as $color){
|
||||
$colorUsed[$color] = 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
현재 도시에서 나라를 세웁니다. 중, 소도시에서만 가능합니다.<br>
|
||||
|
||||
<?php foreach (GameConst::$availableNationType as $nationType) :
|
||||
$nationClass = buildNationTypeClass($nationType);
|
||||
|
||||
[$name, $pros, $cons] = [$nationClass->getName(), $nationClass::$pros, $nationClass::$cons];
|
||||
?>
|
||||
|
||||
- <?= $name ?> : <span style='color:cyan;'><?= $pros ?></span> <span style='color:magenta;'><?= $cons ?></span><br>
|
||||
<?php endforeach; ?>
|
||||
<br>
|
||||
국명 : <input type='text' class='formInput' name="nationName" id="nationName" size='18' maxlength='18' style='color:white;background-color:black;'>
|
||||
색상 : <select class='formInput' name='colorType' id='colorType' size='1'>
|
||||
|
||||
<?php foreach (GetNationColors() as $idx => $color) :
|
||||
/*
|
||||
if($colorUsed[$color] > 0){
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
?>
|
||||
<option value="<?= $idx ?>" data-color="<?= $color ?>" data-font-color="<?=newColor($color)?>" style='background-color:<?= $color ?>;color:<?= newColor($color) ?>;'>국가명(<?=$color?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
성향 : <select class='formInput' name='nationType' id='nationType' size='1'>
|
||||
|
||||
<?php foreach (GameConst::$availableNationType as $nationType) :
|
||||
$nationTypeName = buildNationTypeClass($nationType)->getName();
|
||||
?>
|
||||
<option value='<?= $nationType ?>' style=background-color:black;color:white;><?= $nationTypeName ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<input type=button id="commonSubmit" value="<?= $this->getName() ?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,23 +185,14 @@ class che_군량매매 extends Command\GeneralCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
자신의 군량을 사거나 팝니다.<br>
|
||||
<select id='buyRice' name="buyRice" size=1 style=color:white;background-color:black>
|
||||
<option value='false'>팜</option>
|
||||
<option value='true'>삼</option>
|
||||
</select>
|
||||
<select name=amount id='amount' size=1 style=text-align:right;color:white;background-color:black>
|
||||
<?php foreach(GameConst::$resourceActionAmountGuide as $amount): ?>
|
||||
<option value='<?=$amount?>'><?=$amount?></option>
|
||||
<?php endforeach; ?>
|
||||
</select> <input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
return [
|
||||
'procRes' => [
|
||||
'minAmount' => 100,
|
||||
'maxAmount' => GameConst::$maxResourceActionAmount,
|
||||
'amountGuide' => GameConst::$resourceActionAmountGuide,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
@@ -21,30 +25,32 @@ use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
class che_등용 extends Command\GeneralCommand{
|
||||
class che_등용 extends Command\GeneralCommand
|
||||
{
|
||||
static protected $actionName = '등용';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
//NOTE: 사망 직전에 '등용' 턴을 넣을 수 있으므로, 존재하지 않는 장수여도 argTest에서 바로 탈락시키지 않음
|
||||
if(!key_exists('destGeneralID', $this->arg)){
|
||||
if (!key_exists('destGeneralID', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
$destGeneralID = $this->arg['destGeneralID'];
|
||||
if(!is_int($destGeneralID)){
|
||||
if (!is_int($destGeneralID)) {
|
||||
return false;
|
||||
}
|
||||
if($destGeneralID <= 0){
|
||||
if ($destGeneralID <= 0) {
|
||||
return false;
|
||||
}
|
||||
if($destGeneralID == $this->generalObj->getID()){
|
||||
if ($destGeneralID == $this->generalObj->getID()) {
|
||||
return false;
|
||||
}
|
||||
$this->arg = [
|
||||
'destGeneralID'=>$destGeneralID
|
||||
'destGeneralID' => $destGeneralID
|
||||
];
|
||||
return true;
|
||||
}
|
||||
@@ -59,11 +65,11 @@ class che_등용 extends Command\GeneralCommand{
|
||||
|
||||
$relYear = $this->env['year'] - $this->env['startyear'];
|
||||
|
||||
$this->permissionConstraints=[
|
||||
$this->permissionConstraints = [
|
||||
ConstraintHelper::ReqEnvValue('join_mode', '!=', 'onlyRandom', '랜덤 임관만 가능합니다'),
|
||||
];
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::ReqEnvValue('join_mode', '!=', 'onlyRandom', '랜덤 임관만 가능합니다'),
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
@@ -79,7 +85,7 @@ class che_등용 extends Command\GeneralCommand{
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
$relYear = $this->env['year'] - $this->env['startyear'];
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::ReqEnvValue('join_mode', '!=', 'onlyRandom', '랜덤 임관만 가능합니다'),
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
@@ -90,33 +96,37 @@ class che_등용 extends Command\GeneralCommand{
|
||||
ConstraintHelper::ReqGeneralRice($reqRice),
|
||||
];
|
||||
|
||||
if($this->destGeneralObj->getVar('officer_level') == 12){
|
||||
if ($this->destGeneralObj->getVar('officer_level') == 12) {
|
||||
$this->fullConditionConstraints[] = ConstraintHelper::AlwaysFail('군주에게는 등용장을 보낼 수 없습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
public function canDisplay():bool{
|
||||
public function canDisplay(): bool
|
||||
{
|
||||
return $this->env['join_mode'] !== 'onlyRandom';
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
public function getCost(): array
|
||||
{
|
||||
$env = $this->env;
|
||||
if(!$this->isArgValid){
|
||||
if (!$this->isArgValid) {
|
||||
return [$env['develcost'], 0];
|
||||
}
|
||||
$destGeneral = $this->destGeneralObj;
|
||||
$reqGold = Util::round(
|
||||
$env['develcost'] +
|
||||
($destGeneral->getVar('experience') + $destGeneral->getVar('dedication')) / 1000
|
||||
($destGeneral->getVar('experience') + $destGeneral->getVar('dedication')) / 1000
|
||||
) * 10;
|
||||
return [$reqGold, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -124,12 +134,13 @@ class che_등용 extends Command\GeneralCommand{
|
||||
{
|
||||
$destGeneralName = $this->destGeneralObj->getName();
|
||||
$name = $this->getName();
|
||||
$josaUl = JosaUtil::pick($name, '을');
|
||||
$josaUl = JosaUtil::pick($destGeneralName, '을');
|
||||
return "【{$destGeneralName}】{$josaUl} {$name}";
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
@@ -145,11 +156,10 @@ class che_등용 extends Command\GeneralCommand{
|
||||
|
||||
|
||||
$msg = ScoutMessage::buildScoutMessage($general->getID(), $destGeneralID, $reason, new \DateTime($general->getTurnTime()));
|
||||
if($msg){
|
||||
if ($msg) {
|
||||
$logger->pushGeneralActionLog("<Y>{$destGeneralName}</>에게 등용 권유 서신을 보냈습니다. <1>$date</>");
|
||||
$msg->send(true);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$logger->pushGeneralActionLog("<Y>{$destGeneralName}</>에게 등용 권유 서신을 보내지 못했습니다. {$reason} <1>$date</>");
|
||||
}
|
||||
|
||||
@@ -172,43 +182,27 @@ class che_등용 extends Command\GeneralCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$db = DB::db();
|
||||
$destRawGenerals = $db->queryAllLists('SELECT no,name,nation,officer_level,npc,leadership,strength,intel FROM general WHERE npc < 2 AND officer_level != 12 AND no != %i ORDER BY npc,binary(name)', $this->generalObj->getID());
|
||||
$nationList = [];
|
||||
|
||||
$destGenerals = [];
|
||||
$destRawGenerals = $db->query('SELECT no,name,npc,nation FROM general WHERE npc < 2 AND no != %i AND officer_level != 12 ORDER BY npc,binary(name)',$this->generalObj->getID());
|
||||
foreach($destRawGenerals as $destGeneral){
|
||||
$destNationID = $destGeneral['nation'];
|
||||
if(!key_exists($destNationID, $destGenerals)){
|
||||
$destGenerals[$destNationID] = [];
|
||||
}
|
||||
$destGenerals[$destNationID][] = $destGeneral;
|
||||
foreach ([getNationStaticInfo(0), ...getAllNationStaticInfo()] as $destNation) {
|
||||
$nationList[] = [
|
||||
'id' => $destNation['nation'],
|
||||
'name' => $destNation['name'],
|
||||
'color' => $destNation['color'],
|
||||
'power' => $destNation['power'],
|
||||
];
|
||||
}
|
||||
|
||||
$nationList = array_merge([0=>getNationStaticInfo(0)], getAllNationStaticInfo());
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
재야나 타국의 장수를 등용합니다.<br>
|
||||
서신은 개인 메세지로 전달됩니다.<br>
|
||||
등용할 장수를 목록에서 선택하세요.<br>
|
||||
<select class='formInput' name="destGeneralID" id="destGeneralID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach($nationList as $destNation): ?>
|
||||
<optgroup style='background-color:<?=$destNation['color']?>;color:<?=newColor($destNation['color'])?>;' label="【<?=$destNation['name']?>】" >
|
||||
<?php foreach($destGenerals[$destNation['nation']]??[] as $destGeneral):
|
||||
$nameColor = \sammo\getNameColor($destGeneral['npc']);
|
||||
if($nameColor){
|
||||
$nameColor = " style='color:{$nameColor}'";
|
||||
}
|
||||
?>
|
||||
<option style="background-color:black;color:white" value='<?=$destGeneral['no']?>' <?=$nameColor?>><?=$destGeneral['name']?></option>
|
||||
<?php endforeach; ?>
|
||||
</optgroup>
|
||||
<?php endforeach; ?>
|
||||
|
||||
</select> <input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
return [
|
||||
'procRes' => [
|
||||
'nationList' => $nationList,
|
||||
'generals' => $destRawGenerals,
|
||||
'generalsKey' => ['no', 'name', 'nationID', 'officerLevel', 'npc', 'leadership', 'strength', 'intel']
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,44 +218,4 @@ class che_등용수락 extends Command\GeneralCommand{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$db = DB::db();
|
||||
|
||||
$destGenerals = [];
|
||||
$destRawGenerals = $db->query('SELECT no,name,npc,nation FROM general WHERE npc < 2 AND no != %i AND officer_level != 12 ORDER BY npc,binary(name)',$this->generalObj->getID());
|
||||
foreach($destRawGenerals as $destGeneral){
|
||||
$destNationID = $destGeneral['nation'];
|
||||
if(!key_exists($destNationID, $destGenerals)){
|
||||
$destGenerals[$destNationID] = [];
|
||||
}
|
||||
$destGenerals[$destNationID] = [$destGeneral];
|
||||
}
|
||||
|
||||
$nationList = array_merge([0=>getNationStaticInfo(0)], getAllNationStaticInfo());
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
재야나 타국의 장수를 등용합니다.<br>
|
||||
서신은 개인 메세지로 전달됩니다.<br>
|
||||
등용할 장수를 목록에서 선택하세요.<br>
|
||||
<select class='formInput' name="destGeneralID" id="destGeneralID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach($nationList as $destNation): ?>
|
||||
<optgroup style='color:<?=$destNation['color']?>'>【<?=$destNation['name']?>】
|
||||
<?php foreach($destGenerals[$destNation['nation']]??[] as $destGeneral):
|
||||
$nameColor = \sammo\getNameColor($destGeneral['npc']);
|
||||
if($nameColor){
|
||||
$nameColor = " style='color:{$nameColor}'";
|
||||
}
|
||||
?>
|
||||
<option value='<?=$destGeneral['no']?>' <?=$nameColor?>><?=$destGeneral['name']?></option>
|
||||
<?php endforeach; ?>
|
||||
</optgroup>
|
||||
<?php endforeach; ?>
|
||||
|
||||
</select> <input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
@@ -145,31 +145,17 @@ class che_선양 extends Command\GeneralCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
//TODO: 암행부처럼 보여야...
|
||||
$db = DB::db();
|
||||
|
||||
$destRawGenerals = $db->query('SELECT no,name,officer_level,npc FROM general WHERE nation != 0 AND nation = %i AND no != %i ORDER BY npc,binary(name)', $this->generalObj->getNationID(), $this->generalObj->getID());
|
||||
ob_start();
|
||||
?>
|
||||
군주의 자리를 다른 장수에게 물려줍니다.<br>
|
||||
장수를 선택하세요.<br>
|
||||
<select class='formInput' name="destGeneralID" id="destGeneralID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($destRawGenerals as $destGeneral) :
|
||||
$color = \sammo\getNameColor($destGeneral['npc']);
|
||||
if ($color) {
|
||||
$color = " style='color:{$color}'";
|
||||
}
|
||||
$name = $destGeneral['name'];
|
||||
if ($destGeneral['officer_level'] >= 5) {
|
||||
$name = "*{$name}*";
|
||||
}
|
||||
?>
|
||||
<option value='<?= $destGeneral['no'] ?>' <?= $color ?>><?= $name ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$db = DB::db();
|
||||
$destRawGenerals = $db->queryAllLists('SELECT no,name,officer_level,npc,leadership,strength,intel FROM general WHERE nation != 0 AND nation = %i AND no != %i ORDER BY npc,binary(name)', $this->generalObj->getNationID(), $this->generalObj->getID());
|
||||
|
||||
return [
|
||||
'procRes' => [
|
||||
'generals' => $destRawGenerals,
|
||||
'generalsKey' => ['no', 'name', 'officerLevel', 'npc', 'leadership', 'strength', 'intel']
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ use \sammo\Command;
|
||||
use \sammo\ServConfig;
|
||||
|
||||
use function \sammo\getDexCall;
|
||||
use function sammo\getDexLevelList;
|
||||
use function \sammo\tryUniqueItemLottery;
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
@@ -37,6 +38,9 @@ class che_숙련전환 extends Command\GeneralCommand
|
||||
/** @var string */
|
||||
protected $destArmTypeName;
|
||||
|
||||
static $decreaseCoeff = 0.4;
|
||||
static $convertCoeff = 0.9;
|
||||
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
@@ -162,9 +166,9 @@ class che_숙련전환 extends Command\GeneralCommand
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$srcDex = $general->getVar('dex' . $this->srcArmType);
|
||||
$cutDex = Util::toInt($srcDex * 0.4);
|
||||
$cutDex = Util::toInt($srcDex * static::$decreaseCoeff);
|
||||
$cutDexText = number_format($cutDex);
|
||||
$addDex = Util::toInt($cutDex * 9 / 10);
|
||||
$addDex = Util::toInt($cutDex * static::$convertCoeff);
|
||||
$addDexText = number_format($addDex);
|
||||
|
||||
$general->increaseVar('dex' . $this->srcArmType, -$cutDex);
|
||||
@@ -189,47 +193,33 @@ class che_숙련전환 extends Command\GeneralCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$dexSrcTexts = [];
|
||||
$dexDestTexts = [];
|
||||
$ownDexList = [];
|
||||
foreach (GameUnitConst::allType() as $armType => $armName) {
|
||||
$dexVal = $general->getVar('dex' . $armType);
|
||||
$dexValText = number_format($dexVal);
|
||||
$cutDex = Util::toInt($dexVal * 0.4);
|
||||
$addDex = Util::toInt($cutDex * 9 / 10);
|
||||
$addDexText = number_format($addDex);
|
||||
$newDex = $dexVal - $cutDex;
|
||||
$beforeDexLevel = getDexCall($dexVal);
|
||||
$afterDexLevel = getDexCall($newDex);
|
||||
|
||||
$dexSrcTexts[$armType] = "{$armName} ({$beforeDexLevel} ⇒ {$afterDexLevel}, {$addDexText} 전환)";
|
||||
$dexDestTexts[$armType] = "{$armName} ({$dexValText})";
|
||||
$ownDexList[] = [
|
||||
'armType' => $armType,
|
||||
'name' => $armName,
|
||||
'amount' => $general->getVar('dex' . $armType),
|
||||
];
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
본인의 특정 병종 숙련을 40% 줄이고, 줄어든 숙련 중 9/10(90%p)를 다른 병종 숙련으로 전환합니다.<br>
|
||||
|
||||
<select class='formInput' name="srcArmType" id="srcArmType" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($dexSrcTexts as $armType => $infoText) : ?>
|
||||
<option value="<?= $armType ?>"><?= $infoText ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
숙련을
|
||||
|
||||
<select class='formInput' name="destArmType" id="destArmType" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($dexDestTexts as $armType => $infoText) : ?>
|
||||
<option value="<?= $armType ?>"><?= $infoText ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
숙련으로 <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
$dexLevelList = [];
|
||||
foreach(getDexLevelList() as [$dexKey, $color, $name]){
|
||||
$dexLevelList[] = [
|
||||
'amount'=>$dexKey,
|
||||
'color'=>$color,
|
||||
'name'=>$name
|
||||
];
|
||||
}
|
||||
return [
|
||||
'procRes' => [
|
||||
'ownDexList' => $ownDexList,
|
||||
'dexLevelList' => $dexLevelList,
|
||||
'decreaseCoeff' => static::$decreaseCoeff,
|
||||
'convertCoeff' => static::$convertCoeff,
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ use \sammo\GameUnitConst;
|
||||
use \sammo\LastTurn;
|
||||
use \sammo\Command;
|
||||
|
||||
use function sammo\getMapTheme;
|
||||
use function \sammo\printCitiesBasedOnDistance;
|
||||
use function sammo\tryUniqueItemLottery;
|
||||
|
||||
@@ -177,31 +178,14 @@ class che_이동 extends Command\GeneralCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectCityByMap'
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'cities' => \sammo\JSOptionsForCities(),
|
||||
'distanceList' => \sammo\JSCitiesBasedOnDistance($this->generalObj->getCityID(), 1),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$currentCityID = $this->generalObj->getCityID();
|
||||
$currentCityName = CityConst::byID($currentCityID)->name;
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 도시로 이동합니다.<br>
|
||||
인접 도시로만 이동이 가능합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<?= $currentCityName ?> => <select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'><br>
|
||||
<?= \sammo\optionsForCities() ?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<br>
|
||||
<br>
|
||||
<?= printCitiesBasedOnDistance($currentCityID, 1) ?>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst, GameUnitConst,
|
||||
GameConst,
|
||||
GameUnitConst,
|
||||
LastTurn,
|
||||
Command,
|
||||
Json,
|
||||
@@ -22,24 +26,26 @@ use sammo\CityConst;
|
||||
|
||||
|
||||
|
||||
class che_임관 extends Command\GeneralCommand{
|
||||
class che_임관 extends Command\GeneralCommand
|
||||
{
|
||||
static protected $actionName = '임관';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
$destNationID = $this->arg['destNationID']??null;
|
||||
$destNationID = $this->arg['destNationID'] ?? null;
|
||||
|
||||
if($destNationID === null){
|
||||
if ($destNationID === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!is_int($destNationID)){
|
||||
if (!is_int($destNationID)) {
|
||||
return false;
|
||||
}
|
||||
if($destNationID < 1){
|
||||
if ($destNationID < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -50,7 +56,8 @@ class che_임관 extends Command\GeneralCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
protected function init()
|
||||
{
|
||||
|
||||
$general = $this->generalObj;
|
||||
$env = $this->env;
|
||||
@@ -60,23 +67,24 @@ class che_임관 extends Command\GeneralCommand{
|
||||
|
||||
$relYear = $env['year'] - $env['startyear'];
|
||||
|
||||
$this->permissionConstraints=[
|
||||
$this->permissionConstraints = [
|
||||
ConstraintHelper::ReqEnvValue('join_mode', '!=', 'onlyRandom', '랜덤 임관만 가능합니다')
|
||||
];
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::ReqEnvValue('join_mode', '!=', 'onlyRandom', '랜덤 임관만 가능합니다'),
|
||||
ConstraintHelper::BeNeutral(),
|
||||
ConstraintHelper::AllowJoinAction()
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
return '지정한 국가로 임관';
|
||||
}
|
||||
|
||||
public function canDisplay():bool{
|
||||
public function canDisplay(): bool
|
||||
{
|
||||
return $this->env['join_mode'] !== 'onlyRandom';
|
||||
}
|
||||
|
||||
@@ -87,7 +95,7 @@ class che_임관 extends Command\GeneralCommand{
|
||||
|
||||
$env = $this->env;
|
||||
$relYear = $env['year'] - $env['startyear'];
|
||||
$this->fullConditionConstraints=[
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::ReqEnvValue('join_mode', '!=', 'onlyRandom', '랜덤 임관만 가능합니다'),
|
||||
ConstraintHelper::BeNeutral(),
|
||||
ConstraintHelper::ExistsDestNation(),
|
||||
@@ -96,27 +104,32 @@ class che_임관 extends Command\GeneralCommand{
|
||||
];
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
public function getBrief(): string
|
||||
{
|
||||
$commandName = $this->getName();
|
||||
$destNationName = getNationStaticInfo($this->arg['destNationID'])['name'];
|
||||
$josaRo = JosaUtil::pick($destNationName, '로');
|
||||
return "【{$destNationName}】{$josaRo} {$commandName}";
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
@@ -139,10 +152,9 @@ class che_임관 extends Command\GeneralCommand{
|
||||
$logger->pushGeneralHistoryLog("<D><b>{$destNationName}</b></>에 임관");
|
||||
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <D><b>{$destNationName}</b></>에 <S>임관</>했습니다.");
|
||||
|
||||
if($gennum < GameConst::$initialNationGenLimit) {
|
||||
if ($gennum < GameConst::$initialNationGenLimit) {
|
||||
$exp = 700;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$exp = 100;
|
||||
}
|
||||
|
||||
@@ -151,22 +163,21 @@ class che_임관 extends Command\GeneralCommand{
|
||||
$general->setVar('officer_city', 0);
|
||||
$general->setVar('belong', 1);
|
||||
|
||||
if($this->destGeneralObj !== null){
|
||||
if ($this->destGeneralObj !== null) {
|
||||
$general->setVar('city', $this->destGeneralObj->getCityID());
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$targetCityID = $db->queryFirstField('SELECT city FROM general WHERE nation = %i AND officer_level=12', $destNationID);
|
||||
$general->setVar('city', $targetCityID);
|
||||
}
|
||||
|
||||
$db->update('nation', [
|
||||
'gennum'=>$db->sqleval('gennum + 1')
|
||||
'gennum' => $db->sqleval('gennum + 1')
|
||||
], 'nation=%i', $destNationID);
|
||||
\sammo\refreshNationStaticInfo();
|
||||
|
||||
$relYear = $env['year'] - $env['startyear'];
|
||||
if($general->getNPCType() == 1 || $relYear >= 3){
|
||||
$joinedNations = $general->getAuxVar('joinedNations')??[];
|
||||
if ($general->getNPCType() == 1 || $relYear >= 3) {
|
||||
$joinedNations = $general->getAuxVar('joinedNations') ?? [];
|
||||
$joinedNations[] = $destNationID;
|
||||
$general->setAuxVar('joinedNations', $joinedNations);
|
||||
}
|
||||
@@ -181,64 +192,42 @@ class che_임관 extends Command\GeneralCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationID = $generalObj->getNationID();
|
||||
$db = DB::db();
|
||||
|
||||
$generalObj = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$joinedNations = $generalObj->getAuxVar('joinedNations')??[];
|
||||
|
||||
$nationList = $db->query('SELECT nation,`name`,color,scout,gennum FROM nation');
|
||||
shuffle($nationList);
|
||||
$nationList = Util::convertArrayToDict($nationList, 'nation');
|
||||
//NOTE: join 안할것임
|
||||
$rawNationList = Util::convertArrayToDict($db->query('SELECT nation,`name`,color,gennum,`power` FROM nation'), 'nation');
|
||||
$scoutMsgs = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'scout_msg');
|
||||
foreach($scoutMsgs as $nationID=>$scoutMsg){
|
||||
$nationList[$nationID]['scoutmsg'] = $scoutMsg;
|
||||
foreach ($scoutMsgs as $nationID => $scoutMsg) {
|
||||
$rawNationList[$nationID]['scoutmsg'] = $scoutMsg;
|
||||
}
|
||||
foreach ($rawNationList as $destNation) {
|
||||
$testCommand = new static($generalObj, $this->env, ['destNationID' => $destNation['nation']]);
|
||||
|
||||
$hiddenItems = [];
|
||||
|
||||
foreach($nationList as &$nation){
|
||||
if($env['year'] < $env['startyear']+3 && $nation['gennum'] >= GameConst::$initialNationGenLimit){
|
||||
$nation['availableJoin'] = false;
|
||||
$nationTarget = [
|
||||
'id' => $destNation['nation'],
|
||||
'name' => $destNation['name'],
|
||||
'color' => $destNation['color'],
|
||||
'power' => $destNation['power'],
|
||||
'scoutMsg' => $destNation['scoutmsg'] ?? ' ',
|
||||
];
|
||||
if (!$testCommand->hasFullConditionMet()) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
else if($nation['scout'] == 1) {
|
||||
$nation['availableJoin'] = false;
|
||||
}
|
||||
else{
|
||||
$nation['availableJoin'] = true;
|
||||
if ($destNation['id'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
if(in_array($nation['nation'], $joinedNations)){
|
||||
$nation['availableJoin'] = false;
|
||||
}
|
||||
|
||||
if(Util::starts_with($nation['name'], 'ⓤ')){
|
||||
$hiddenItems[$nation['nation']] = $nation['nation'];
|
||||
}
|
||||
$nationList[] = $nationTarget;
|
||||
}
|
||||
unset($nation);
|
||||
ob_start();
|
||||
?>
|
||||
국가에 임관합니다.<br>
|
||||
이미 임관/등용되었던 국가는 다시 임관할 수 없습니다.<br>
|
||||
바로 군주의 위치로 이동합니다.<br>
|
||||
임관할 국가를 목록에서 선택하세요.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach($nationList as $nation): ?>
|
||||
<?php if(key_exists($nation['nation'], $hiddenItems)){ continue; } ?>
|
||||
<option
|
||||
value='<?=$nation['nation']?>'
|
||||
style='<?=$nation['availableJoin']?'':'background-color:red;'?>'
|
||||
>【<?=$nation['name']?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
<input type=button id="commonSubmit" value="<?=$this->getName()?>">
|
||||
<?=getInvitationList($nationList)?>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
return [
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'nationList' => $nationList,
|
||||
'startYear' => $this->env['startyear'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\General;
|
||||
|
||||
//TODO: 아이템 클래스 재확정 후 재 구현!
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst, GameUnitConst,
|
||||
GameConst,
|
||||
GameUnitConst,
|
||||
LastTurn,
|
||||
Command
|
||||
};
|
||||
@@ -18,49 +22,52 @@ use function sammo\tryUniqueItemLottery;
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
class che_장비매매 extends Command\GeneralCommand{
|
||||
class che_장비매매 extends Command\GeneralCommand
|
||||
{
|
||||
static protected $actionName = '장비매매';
|
||||
static public $reqArg = true;
|
||||
|
||||
static $itemMap = [
|
||||
'horse'=>'명마',
|
||||
'weapon'=>'무기',
|
||||
'book'=>'서적',
|
||||
'item'=>'도구',
|
||||
'horse' => '명마',
|
||||
'weapon' => '무기',
|
||||
'book' => '서적',
|
||||
'item' => '도구',
|
||||
];
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
$itemType = $this->arg['itemType']??null;
|
||||
if(!in_array($itemType, array_keys(static::$itemMap))){
|
||||
$itemType = $this->arg['itemType'] ?? null;
|
||||
if (!in_array($itemType, array_keys(static::$itemMap))) {
|
||||
return false;
|
||||
}
|
||||
$itemCode = $this->arg['itemCode']??null;
|
||||
if(!key_exists($itemCode, GameConst::$allItems[$itemType]) && $itemCode !== 'None'){
|
||||
$itemCode = $this->arg['itemCode'] ?? null;
|
||||
if (!key_exists($itemCode, GameConst::$allItems[$itemType]) && $itemCode !== 'None') {
|
||||
return false;
|
||||
}
|
||||
$itemClass = buildItemClass($itemCode);
|
||||
if(!$itemClass->isBuyable()){
|
||||
if (!$itemClass->isBuyable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->arg = [
|
||||
'itemType'=>$itemType,
|
||||
'itemCode'=>$itemCode
|
||||
'itemType' => $itemType,
|
||||
'itemCode' => $itemCode
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
protected function init()
|
||||
{
|
||||
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation();
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::ReqCityTrader($general->getNPCType()),
|
||||
];
|
||||
}
|
||||
@@ -76,26 +83,25 @@ class che_장비매매 extends Command\GeneralCommand{
|
||||
|
||||
[$reqGold, $reqRice] = $this->getCost();
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::ReqCityTrader($general->getNPCType()),
|
||||
ConstraintHelper::ReqCityCapacity('secu', '치안 수치', $itemClass->getReqSecu()),
|
||||
ConstraintHelper::ReqGeneralGold($reqGold),
|
||||
ConstraintHelper::ReqGeneralRice($reqRice),
|
||||
];
|
||||
|
||||
if($itemCode === 'None'){
|
||||
if ($itemCode === 'None') {
|
||||
$this->fullConditionConstraints[] = ConstraintHelper::ReqGeneralValue($itemType, $itemTypeName, '!=', 'None');
|
||||
}
|
||||
else if($itemCode == $general->getVar($itemType)){
|
||||
} else if ($itemCode == $general->getVar($itemType)) {
|
||||
$this->fullConditionConstraints[] = ConstraintHelper::AlwaysFail('이미 가지고 있습니다.');
|
||||
}
|
||||
else if(!buildItemClass($general->getVar($itemType))->isBuyable()){
|
||||
} else if (!buildItemClass($general->getVar($itemType))->isBuyable()) {
|
||||
$this->fullConditionConstraints[] = ConstraintHelper::AlwaysFail('이미 진귀한 것을 가지고 있습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
if(!$this->isArgValid){
|
||||
public function getCost(): array
|
||||
{
|
||||
if (!$this->isArgValid) {
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
@@ -106,19 +112,22 @@ class che_장비매매 extends Command\GeneralCommand{
|
||||
return [$reqGold, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
public function getBrief(): string
|
||||
{
|
||||
$itemType = $this->arg['itemType'];
|
||||
$itemCode = $this->arg['itemCode'];
|
||||
|
||||
if($itemCode === 'None'){
|
||||
if ($itemCode === 'None') {
|
||||
$itemTypeName = static::$itemMap[$itemType];
|
||||
$josaUl = JosaUtil::pick($itemTypeName, '을');
|
||||
return "{$itemTypeName}{$josaUl} 판매";
|
||||
@@ -132,8 +141,9 @@ class che_장비매매 extends Command\GeneralCommand{
|
||||
return "【{$itemName}】{$josaUl} 구입";
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
@@ -145,11 +155,10 @@ class che_장비매매 extends Command\GeneralCommand{
|
||||
$itemType = $this->arg['itemType'];
|
||||
$itemCode = $this->arg['itemCode'];
|
||||
|
||||
if($itemCode === 'None'){
|
||||
if ($itemCode === 'None') {
|
||||
$buying = false;
|
||||
$itemCode = $general->getVar($itemType);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$buying = true;
|
||||
}
|
||||
$itemObj = buildItemClass($itemCode);
|
||||
@@ -161,12 +170,11 @@ class che_장비매매 extends Command\GeneralCommand{
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
if($buying){
|
||||
if ($buying) {
|
||||
$logger->pushGeneralActionLog("<C>{$itemName}</>{$josaUl} 구입했습니다. <1>$date</>");
|
||||
$general->increaseVarWithLimit('gold', -$cost, 0);
|
||||
$general->setVar($itemType, $itemCode);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$logger->pushGeneralActionLog("<C>{$itemName}</>{$josaUl} 판매했습니다. <1>$date</>");
|
||||
$general->increaseVarWithLimit('gold', $cost / 2);
|
||||
$general->deleteItem($itemType);
|
||||
@@ -183,6 +191,60 @@ class che_장비매매 extends Command\GeneralCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$general = $this->generalObj;
|
||||
$db = DB::db();
|
||||
$citySecu = $db->queryFirstField('SELECT secu FROM city WHERE city = %i', $this->generalObj->getCityID());
|
||||
$itemList = [];
|
||||
foreach (GameConst::$allItems as $itemType => $itemCategories) {
|
||||
$typeName = static::$itemMap[$itemType];
|
||||
$values = [];
|
||||
foreach ($itemCategories as $itemCode => $cnt) {
|
||||
if ($cnt > 0) {
|
||||
continue;
|
||||
}
|
||||
$item = buildItemClass($itemCode);
|
||||
if (!$item->isBuyable()) {
|
||||
continue;
|
||||
}
|
||||
$values[] = [
|
||||
'id'=>$itemCode,
|
||||
'name'=>$item->getName(),
|
||||
'reqSecu'=>$item->getReqSecu(),
|
||||
'cost'=>$item->getCost(),
|
||||
'info'=>$item->getInfo(),
|
||||
'isBuyable'=>$item->isBuyable(),//항상 true지만, 일관성을 위해
|
||||
];
|
||||
}
|
||||
$itemList[$itemType] = [
|
||||
'typeName'=>$typeName,
|
||||
'values'=>$values
|
||||
];
|
||||
}
|
||||
|
||||
$ownItem = [];
|
||||
foreach($general->getItems() as $itemType => $item){
|
||||
$ownItem[$itemType] = [
|
||||
'id'=>$item->getRawClassName(),
|
||||
'name'=>$item->getName(),
|
||||
'reqSecu'=>$item->getReqSecu(),
|
||||
'cost'=>$item->getCost(),
|
||||
'info'=>$item->getInfo(),
|
||||
'isBuyable'=>$item->isBuyable(),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'procRes' => [
|
||||
'citySecu'=>$citySecu,
|
||||
'gold'=>$general->getVar('gold'),
|
||||
'itemList'=>$itemList,
|
||||
'ownItem'=>$ownItem,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$form = [];
|
||||
@@ -194,49 +256,49 @@ class che_장비매매 extends Command\GeneralCommand{
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<script>
|
||||
function updateItemType(){
|
||||
$('#itemType').val($('#itemCode option:selected').data('item_type'));
|
||||
}
|
||||
$(function(){
|
||||
$('#customSubmit').click(function(){
|
||||
updateItemType();
|
||||
submitAction();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<input type="hidden" class="formInput" name="itemType" id="itemType" value="item">
|
||||
장비를 구입하거나 매각합니다.<br>
|
||||
현재 구입 불가능한 것은 <font color=red>붉은색</font>으로 표시됩니다.<br>
|
||||
현재 도시 치안 : <?=$citySecu?> 현재 자금 : <?=$gold?><br>
|
||||
장비 : <select class='formInput' name="itemCode" id="itemCode" onchange='updateItemType();' size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach(GameConst::$allItems as $itemType=>$itemCategories):
|
||||
//매각
|
||||
$typeName = static::$itemMap[$itemType];
|
||||
?>
|
||||
<option value='None' data-item_type='<?=$itemType?>' style='color:skyblue'>_____<?=$typeName?>매각(반값)____</option>
|
||||
<?php foreach($itemCategories as $itemCode=>$cnt) :
|
||||
if($cnt > 0){
|
||||
continue;
|
||||
<script>
|
||||
function updateItemType() {
|
||||
$('#itemType').val($('#itemCode option:selected').data('item_type'));
|
||||
}
|
||||
$itemClass = buildItemClass($itemCode);
|
||||
if(!$itemClass->isBuyable()){
|
||||
continue;
|
||||
}
|
||||
$itemName = $itemClass->getName();
|
||||
$reqSecu = $itemClass->getReqSecu();
|
||||
$reqGold = $itemClass->getCost();
|
||||
$css = '';
|
||||
if($reqSecu > $citySecu){
|
||||
$css = 'color:red;';
|
||||
}
|
||||
?>
|
||||
<option value='<?=$itemCode?>' data-item_type='<?=$itemType?>' style='<?=$css?>'><?=$itemName?> 가격: <?=$reqGold?></option>
|
||||
<?php endforeach; ?>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<input type=button id="customSubmit" value="<?=$this->getName()?>"><br>
|
||||
$(function() {
|
||||
$('#customSubmit').click(function() {
|
||||
updateItemType();
|
||||
submitAction();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<input type="hidden" class="formInput" name="itemType" id="itemType" value="item">
|
||||
장비를 구입하거나 매각합니다.<br>
|
||||
현재 구입 불가능한 것은 <font color=red>붉은색</font>으로 표시됩니다.<br>
|
||||
현재 도시 치안 : <?= $citySecu ?> 현재 자금 : <?= $gold ?><br>
|
||||
장비 : <select class='formInput' name="itemCode" id="itemCode" onchange='updateItemType();' size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach (GameConst::$allItems as $itemType => $itemCategories) :
|
||||
//매각
|
||||
$typeName = static::$itemMap[$itemType];
|
||||
?>
|
||||
<option value='None' data-item_type='<?= $itemType ?>' style='color:skyblue'>_____<?= $typeName ?>매각(반값)____</option>
|
||||
<?php foreach ($itemCategories as $itemCode => $cnt) :
|
||||
if ($cnt > 0) {
|
||||
continue;
|
||||
}
|
||||
$itemClass = buildItemClass($itemCode);
|
||||
if (!$itemClass->isBuyable()) {
|
||||
continue;
|
||||
}
|
||||
$itemName = $itemClass->getName();
|
||||
$reqSecu = $itemClass->getReqSecu();
|
||||
$reqGold = $itemClass->getCost();
|
||||
$css = '';
|
||||
if ($reqSecu > $citySecu) {
|
||||
$css = 'color:red;';
|
||||
}
|
||||
?>
|
||||
<option value='<?= $itemCode ?>' data-item_type='<?= $itemType ?>' style='<?= $css ?>'><?= $itemName ?> 가격: <?= $reqGold ?></option>
|
||||
<?php endforeach; ?>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<input type=button id="customSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ use \sammo\{
|
||||
KVStorage
|
||||
};
|
||||
|
||||
use function sammo\getAllNationStaticInfo;
|
||||
use function \sammo\getColoredName;
|
||||
use function \sammo\tryUniqueItemLottery;
|
||||
use function \sammo\getInvitationList;
|
||||
@@ -21,8 +22,6 @@ use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\CityConst;
|
||||
|
||||
|
||||
|
||||
class che_장수대상임관 extends Command\GeneralCommand{
|
||||
static protected $actionName = '장수를 따라 임관';
|
||||
static public $reqArg = true;
|
||||
@@ -186,65 +185,29 @@ class che_장수대상임관 extends Command\GeneralCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$db = DB::db();
|
||||
|
||||
$generalObj = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
|
||||
$joinedNations = $generalObj->getAuxVar('joinedNations')??[];
|
||||
$generalList = $db->query('SELECT no,name,nation,npc FROM general WHERE no!=%i ORDER BY name ASC', $generalObj->getID());
|
||||
|
||||
|
||||
$nationList = $db->query('SELECT nation,`name`,color,scout,gennum FROM nation');
|
||||
shuffle($nationList);
|
||||
$nationList = Util::convertArrayToDict($nationList, 'nation');
|
||||
//NOTE: join 안할것임
|
||||
$destRawGenerals = $db->queryAllLists('SELECT no,name,nation,officer_level,npc,leadership,strength,intel FROM general WHERE no != %i ORDER BY npc,binary(name)', $this->generalObj->getID());
|
||||
$nationList = [];
|
||||
$scoutMsgs = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'scout_msg');
|
||||
foreach($scoutMsgs as $nationID=>$scoutMsg){
|
||||
$nationList[$nationID]['scoutmsg'] = $scoutMsg;
|
||||
|
||||
foreach ([getNationStaticInfo(0), ...getAllNationStaticInfo()] as $destNation) {
|
||||
$nationList[] = [
|
||||
'id' => $destNation['nation'],
|
||||
'name' => $destNation['name'],
|
||||
'color' => $destNation['color'],
|
||||
'power' => $destNation['power'],
|
||||
'scoutMsg' => $scoutMsgs[$destNation['nation']]??' '
|
||||
];
|
||||
}
|
||||
|
||||
$hiddenItems = [];
|
||||
|
||||
foreach($nationList as &$nation){
|
||||
$nation['hideen'] = false;
|
||||
if($env['year'] < $env['startyear']+3 && $nation['gennum'] >= GameConst::$initialNationGenLimit){
|
||||
$nation['availableJoin'] = false;
|
||||
}
|
||||
else if($nation['scout'] == 1) {
|
||||
$nation['availableJoin'] = false;
|
||||
}
|
||||
else{
|
||||
$nation['availableJoin'] = true;
|
||||
}
|
||||
|
||||
if(in_array($nation['nation'], $joinedNations)){
|
||||
$nation['availableJoin'] = false;
|
||||
}
|
||||
|
||||
if(Util::starts_with($nation['name'], 'ⓤ')){
|
||||
$hiddenItems[$nation['nation']] = $nation['nation'];
|
||||
}
|
||||
}
|
||||
unset($nation);
|
||||
ob_start();
|
||||
?>
|
||||
장수를 따라 임관합니다.<br>
|
||||
이미 임관/등용되었던 국가는 다시 임관할 수 없습니다.<br>
|
||||
바로 군주의 위치로 이동합니다.<br>
|
||||
임관할 국가를 목록에서 선택하세요.<br>
|
||||
<select class='formInput' name="destGeneralID" id="destGeneralID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach($generalList as $targetGeneral): ?>
|
||||
<?php if(key_exists($targetGeneral['nation'], $hiddenItems)){ continue; } ?>
|
||||
<option value='<?=$targetGeneral['no']?>'><?=getColoredName($targetGeneral['name'],$targetGeneral['npc'])?>【<?=getNationStaticInfo($targetGeneral['nation'])['name']??'재야'?>】</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<input type=button id="commonSubmit" value="<?=$this->getName()?>">
|
||||
<?=getInvitationList($nationList)?>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
return [
|
||||
'procRes' => [
|
||||
'nationList' => $nationList,
|
||||
'generals' => $destRawGenerals,
|
||||
'generalsKey' => ['no', 'name', 'nationID', 'officerLevel', 'npc', 'leadership', 'strength', 'intel']
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -177,40 +177,22 @@ class che_증여 extends Command\GeneralCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
//TODO: 암행부처럼 보여야...
|
||||
$db = DB::db();
|
||||
|
||||
$destRawGenerals = $db->query('SELECT no,name,officer_level,npc,gold,rice FROM general WHERE nation != 0 AND nation = %i AND no != %i ORDER BY npc,binary(name)', $this->generalObj->getNationID(), $this->generalObj->getID());
|
||||
ob_start();
|
||||
?>
|
||||
자신의 자금이나 군량을 다른 장수에게 증여합니다.<br>
|
||||
장수를 선택하세요.<br>
|
||||
<select class='formInput' name="destGeneralID" id="destGeneralID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($destRawGenerals as $destGeneral) :
|
||||
$color = \sammo\getNameColor($destGeneral['npc']);
|
||||
if ($color) {
|
||||
$color = " style='color:{$color}'";
|
||||
}
|
||||
$name = $destGeneral['name'];
|
||||
if ($destGeneral['officer_level'] >= 5) {
|
||||
$name = "*{$name}*";
|
||||
}
|
||||
?>
|
||||
<option value='<?= $destGeneral['no'] ?>' <?= $color ?>><?= $name ?>(금:<?= $destGeneral['gold'] ?>, 쌀:<?= $destGeneral['rice'] ?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<select class='formInput' name="isGold" id="isGold" size='1' style='color:white;background-color:black;'>
|
||||
<option value="true">금</option>
|
||||
<option value="false">쌀</option>
|
||||
</select>
|
||||
<select class='formInput' name="amount" id="amount" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach (GameConst::$resourceActionAmountGuide as $amount) : ?>
|
||||
<option value='<?= $amount ?>'><?= $amount ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
$nationID = $this->getNationID();
|
||||
$troops = Util::convertArrayToDict($db->query('SELECT * FROM troop WHERE nation=%i', $nationID), 'troop_leader');
|
||||
$destRawGenerals = $db->queryAllLists('SELECT no,name,officer_level,npc,gold,rice,leadership,strength,intel,city,crew,train,atmos,troop FROM general WHERE nation = %i ORDER BY npc,binary(name)', $nationID);
|
||||
return [
|
||||
'procRes' => [
|
||||
'troops' => $troops,
|
||||
'generals' => $destRawGenerals,
|
||||
'generalsKey' => ['no', 'name', 'officerLevel', 'npc', 'gold', 'rice', 'leadership', 'strength', 'intel', 'cityID', 'crew', 'train', 'atmos', 'troopID'],
|
||||
'cities' => \sammo\JSOptionsForCities(),
|
||||
'minAmount' => 100,
|
||||
'maxAmount' => GameConst::$maxResourceActionAmount,
|
||||
'amountGuide' => GameConst::$resourceActionAmountGuide,
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ use \sammo\ServConfig;
|
||||
use function \sammo\getTechCall;
|
||||
use function \sammo\tryUniqueItemLottery;
|
||||
use function \sammo\getTechAbil;
|
||||
use function sammo\getTechLevel;
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
@@ -231,18 +232,10 @@ class che_징병 extends Command\GeneralCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
return [
|
||||
'recruitCrewForm'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$db = DB::db();
|
||||
|
||||
$general = $this->generalObj;
|
||||
$db = DB::db();
|
||||
|
||||
[$nationLevel, $tech] = $db->queryFirstList('SELECT level,tech FROM nation WHERE nation=%i', $general->getNationID());
|
||||
if (!$nationLevel) {
|
||||
@@ -253,13 +246,13 @@ class che_징병 extends Command\GeneralCommand
|
||||
$tech = 0;
|
||||
}
|
||||
|
||||
$ownCities = [];
|
||||
$ownRegions = [];
|
||||
$year = $this->env['year'];
|
||||
$startyear = $this->env['startyear'];
|
||||
|
||||
$relativeYear = $year - $startyear;
|
||||
|
||||
$ownCities = [];
|
||||
$ownRegions = [];
|
||||
|
||||
foreach (DB::db()->query('SELECT city, region from city where nation = %i', $general->getNationID()) as $city) {
|
||||
$ownCities[$city['city']] = 1;
|
||||
$ownRegions[$city['region']] = 1;
|
||||
@@ -269,27 +262,31 @@ class che_징병 extends Command\GeneralCommand
|
||||
$fullLeadership = $general->getLeadership(false);
|
||||
$abil = getTechAbil($tech);
|
||||
|
||||
$armTypes = [];
|
||||
|
||||
$armCrewTypes = [];
|
||||
foreach (GameUnitConst::allType() as $armType => $armName) {
|
||||
$armTypeCrews = [];
|
||||
$armCrewType = [
|
||||
'armType' => $armType,
|
||||
'armName' => $armName,
|
||||
'values' => [],
|
||||
];
|
||||
|
||||
$crewTypes = [];
|
||||
foreach (GameUnitConst::byType($armType) as $unit) {
|
||||
$crewObj = new \stdClass;
|
||||
$crewObj->showDefault = 'true';
|
||||
|
||||
$crewObj->id = $unit->id;
|
||||
$crewObj->reqTech = $unit->reqTech;
|
||||
$crewObj->reqYear = $unit->reqYear;
|
||||
|
||||
/*
|
||||
if ($unit->reqTech == 0) {
|
||||
$crewObj->bgcolor = 'green';
|
||||
} else {
|
||||
$crewObj->bgcolor = 'limegreen';
|
||||
}
|
||||
*/
|
||||
|
||||
if (!$unit->isValid($ownCities, $ownRegions, $relativeYear, $tech)) {
|
||||
$crewObj->showDefault = 'false';
|
||||
$crewObj->bgcolor = 'red';
|
||||
}
|
||||
$crewObj->notAvailable = !$unit->isValid($ownCities, $ownRegions, $relativeYear, $tech);
|
||||
|
||||
$crewObj->baseRice = $general->onCalcDomestic($this->getName(), 'rice', $unit->riceWithTech($tech), ['armType' => $unit->armType]);
|
||||
$crewObj->baseCost = $general->onCalcDomestic($this->getName(), 'cost', $unit->costWithTech($tech), ['armType' => $unit->armType]);
|
||||
@@ -305,111 +302,34 @@ class che_징병 extends Command\GeneralCommand
|
||||
$crewObj->img = ServConfig::$gameImagePath . "/crewtype" . $unit->id . ".png";
|
||||
}
|
||||
|
||||
$crewObj->baseRiceShort = round($crewObj->baseRice, 1);
|
||||
$crewObj->baseCostShort = round($crewObj->baseCost, 1);
|
||||
$crewObj->info = $unit->info;
|
||||
|
||||
$crewObj->info = join('<br>', $unit->info);
|
||||
|
||||
|
||||
$armTypeCrews[] = $crewObj;
|
||||
$armCrewType['values'][] = $crewObj;
|
||||
}
|
||||
$armTypes[] = [$armName, $armTypeCrews];
|
||||
}
|
||||
$commandName = $this->getName();
|
||||
|
||||
$techLevelText = getTechCall($tech);
|
||||
|
||||
$armCrewTypes[] = $armCrewType;
|
||||
}
|
||||
|
||||
$crew = $general->getVar('crew');
|
||||
$gold = $general->getVar('gold');
|
||||
$crewTypeObj = $general->getCrewTypeObj();
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
|
||||
<font size=2>병사를 모집합니다.
|
||||
<?php if ($commandName == '징병') : ?>
|
||||
훈련과 사기치는 낮지만 가격이 저렴합니다.<br>
|
||||
<?php else : ?>
|
||||
훈련과 사기치는 높지만 자금이 많이 듭니다.
|
||||
<?php endif; ?>
|
||||
가능한 수보다 많게 입력하면 가능한 최대 병사를 모집합니다.<br>
|
||||
이미 병사가 있는 경우 추가<?= $commandName ?>되며, 병종이 다를경우는 기존의 병사는 소집해제됩니다.<br>
|
||||
현재 <?= $commandName ?> 가능한 병종은 <font color=green>녹색</font>으로 표시되며,<br>
|
||||
현재 <?= $commandName ?> 가능한 특수병종은 <font color=limegreen>초록색</font>으로 표시됩니다.<br>
|
||||
|
||||
<table class='tb_layout' style='margin:auto;'>
|
||||
<thead>
|
||||
<tr>
|
||||
<td colspan=11>
|
||||
<div style='float:right'><input type='checkbox' id="show_unavailable_troops">불가능한 병종 표시</input></div>
|
||||
<?php if ($commandName == '모병') : ?>
|
||||
<div style='text-align:center;'>모병은 가격 2배의 자금이 소요됩니다.</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=11 align=center class='bg2'>
|
||||
현재 기술력 : <?= $techLevelText ?>
|
||||
현재 통솔 : <?= $leadership ?><?= ($leadership != $fullLeadership) ? "({$fullLeadership})" : '' ?>
|
||||
현재 병종 : <?= $crewTypeObj->name ?>
|
||||
현재 병사 : <?= $crew ?>
|
||||
현재 자금 : <?= $gold ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width=64 align=center class='bg1'>사진</td>
|
||||
<td width=64 align=center class='bg1'>병종</td>
|
||||
<td width=40 align=center class='bg1'>공격</td>
|
||||
<td width=40 align=center class='bg1'>방어</td>
|
||||
<td width=40 align=center class='bg1'>기동</td>
|
||||
<td width=40 align=center class='bg1'>회피</td>
|
||||
<td width=40 align=center class='bg1'>가격</td>
|
||||
<td width=40 align=center class='bg1'>군량</td>
|
||||
<td width=180 align=center class='bg1'>병사수</td>
|
||||
<td width=50 align=center class='bg1'>행동</td>
|
||||
<td width=300 align=center class='bg1'>특징</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($armTypes as [$armName, $armTypeCrews]) : ?>
|
||||
<tr>
|
||||
<td colspan=11><?= $armName ?> 계열</td>
|
||||
</tr>
|
||||
<?php foreach ($armTypeCrews as $crewObj) : ?>
|
||||
<tr id="crewType<?= $crewObj->id ?>" class="show_default_<?= $crewObj->showDefault ?>" style='height:64px;background-color:<?= $crewObj->bgcolor ?>' data-rice="<?= $crewObj->baseRice ?>" data-cost="<?= $crewObj->baseCost ?>">
|
||||
<td style='background:#222222 no-repeat center url("<?= $crewObj->img ?>");background-size:64px'></td>
|
||||
<td style='text-align:center;vertical-align:middle;'><?= $crewObj->name ?></td>
|
||||
<td style='text-align:center;vertical-align:middle;'><?= $crewObj->attack ?></td>
|
||||
<td style='text-align:center;vertical-align:middle;'><?= $crewObj->defence ?></td>
|
||||
<td style='text-align:center;vertical-align:middle;'><?= $crewObj->speed ?></td>
|
||||
<td style='text-align:center;vertical-align:middle;'><?= $crewObj->avoid ?></td>
|
||||
<td style='text-align:center;vertical-align:middle;'><?= $crewObj->baseCostShort ?></td>
|
||||
<td style='text-align:center;vertical-align:middle;'><?= $crewObj->baseRiceShort ?></td>
|
||||
<td style='text-align:center;vertical-align:middle;' class='input_form' data-crewtype='<?= $crewObj->id ?>'>
|
||||
<input type=button value='절반' class='btn_half'><input type=button value='채우기' class='btn_fill'><input type=button value='가득' class='btn_full'><br>
|
||||
<input type=text data-crewtype='<?= $crewObj->id ?>' class=form_double name=double maxlength=3 size=3 style=text-align:right;color:white;background-color:black>00명
|
||||
<input type=text class=form_cost name=cost maxlength=5 size=5 readonly style=text-align:right;color:white;background-color:black>원
|
||||
|
||||
</td>
|
||||
<td style='position:relative;height:64px;'><input type=submit value='<?= $commandName ?>' class='submit_btn' style='width:100%;height:44px;margin:10px 0;display:block;position: absolute;left:0;top:0;'></td>
|
||||
<td><?= $crewObj->info ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<input type='hidden' id='amount' value='1'>
|
||||
<input type='hidden' id='crewType' value='<?= $crewTypeObj->id ?>'>
|
||||
<script>
|
||||
window.currentTech = <?= $tech ?>;
|
||||
window.leadership = <?= $leadership ?>;
|
||||
window.fullLeadership = <?= $fullLeadership ?>;
|
||||
window.currentCrewType = <?= $crewTypeObj->id ?>;
|
||||
window.currentCrew = <?= $crew ?>;
|
||||
window.currentGold = <?= $gold ?>;
|
||||
window.is모병 = <?= ($this->getName() == '모병') ? 'true' : 'false' ?>;
|
||||
</script>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
return [
|
||||
'procRes' => [
|
||||
'relYear' => $relativeYear,
|
||||
'year' => $year,
|
||||
'tech' => $tech,
|
||||
'techLevel' => getTechLevel($tech),
|
||||
'startYear' => $startyear,
|
||||
'goldCoeff' => static::$costOffset,
|
||||
'leadership' => $leadership,
|
||||
'fullLeadership' => $fullLeadership,
|
||||
'armCrewTypes' => $armCrewTypes,
|
||||
'currentCrewType' => $crewTypeObj->id,
|
||||
'crew' => $crew,
|
||||
'gold' => $gold,
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,29 +225,14 @@ class che_첩보 extends Command\GeneralCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectCityByMap'
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'cities' => \sammo\JSOptionsForCities(),
|
||||
'distanceList' => \sammo\JSCitiesBasedOnDistance($this->generalObj->getCityID(), 3),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$currentCityID = $this->generalObj->getCityID();
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 도시에 첩보를 실행합니다.<br>
|
||||
인접도시일 경우 많은 정보를 얻을 수 있습니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'><br>
|
||||
<?= \sammo\optionsForCities() ?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<br>
|
||||
<br>
|
||||
<?= printCitiesBasedOnDistance($currentCityID, 3) ?>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use phpDocumentor\Reflection\Types\Object_;
|
||||
use \sammo\DB;
|
||||
use \sammo\Util;
|
||||
use \sammo\JosaUtil;
|
||||
@@ -240,27 +241,15 @@ class che_출병 extends Command\GeneralCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectCityByMap'
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'cities' => \sammo\JSOptionsForCities(),
|
||||
'distanceList' => \sammo\JSCitiesBasedOnDistance($this->generalObj->getCityID(), 1),
|
||||
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$srcCityName = \sammo\CityConst::byID($this->generalObj->getCityID())->name;
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 도시를 향해 침공을 합니다.<br>
|
||||
침공 경로에 적군의 도시가 있다면 전투를 벌입니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<?= $srcCityName ?> =><select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'>
|
||||
<?= \sammo\optionsForCities() ?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,21 +152,14 @@ class che_헌납 extends Command\GeneralCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
자신의 자금이나 군량을 국가 재산으로 헌납합니다.<br>
|
||||
<select id='isGold' name="isGold" size=1 style=color:white;background-color:black>
|
||||
<option value='true'>금</option>
|
||||
<option value='false'>쌀</option>
|
||||
</select>
|
||||
<select name=amount id='amount' size=1 style=text-align:right;color:white;background-color:black>
|
||||
<?php foreach (GameConst::$resourceActionAmountGuide as $amount) : ?>
|
||||
<option value='<?= $amount ?>'><?= $amount ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
return [
|
||||
'procRes' => [
|
||||
'minAmount' => 100,
|
||||
'maxAmount' => GameConst::$maxResourceActionAmount,
|
||||
'amountGuide' => GameConst::$resourceActionAmountGuide,
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,31 +335,14 @@ class che_화계 extends Command\GeneralCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectCityByMap'
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'cities' => \sammo\JSOptionsForCities(),
|
||||
'distanceList' => \sammo\JSCitiesBasedOnDistance($this->generalObj->getCityID(), 3),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$currentCityID = $this->generalObj->getCityID();
|
||||
$commandName = $this->getName();
|
||||
$josaUl = JosaUtil::pick($commandName, '을');
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 도시에 <?= $commandName ?><?= $josaUl ?> 실행합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'><br>
|
||||
<?= \sammo\optionsForCities() ?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<br>
|
||||
<br>
|
||||
<?= printCitiesBasedOnDistance($currentCityID, 2) ?>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,32 +152,12 @@ class che_국기변경 extends Command\NationCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
return [
|
||||
'colorSelect'
|
||||
'procRes' => [
|
||||
'colors' => GetNationColors(),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
국기를 변경합니다. 단 1회 가능합니다.<br>
|
||||
색상 : <select class='formInput' name='colorType' id='colorType' size='1'>
|
||||
|
||||
<?php foreach (GetNationColors() as $idx => $color) :
|
||||
/*
|
||||
if($colorUsed[$color] > 0){
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
?>
|
||||
<option value="<?= $idx ?>" data-color=<?=$color?> data-font-color="<?=newColor($color)?>" style='background-color:<?= $color ?>;color:<?= newColor($color) ?>;'>국가명(<?=$color?>)</option>
|
||||
<?php endforeach; ?> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,23 +157,4 @@ class che_국호변경 extends Command\NationCommand
|
||||
$general->applyDB($db);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
{
|
||||
return [
|
||||
'colorSelect'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
나라의 이름을 바꿉니다. 황제가 된 후 1회 가능합니다.<br>
|
||||
국명 : <input type='text' class='formInput' name="nationName" id="nationName" size='18' maxlength='18' style='color:white;background-color:black;'> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,48 +196,39 @@ class che_급습 extends Command\NationCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectNationByMap'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationID = $generalObj->getNationID();
|
||||
$nationList = [];
|
||||
$testTurn = new LastTurn($this->getName(), null, $this->getPreReqTurn());
|
||||
foreach (getAllNationStaticInfo() as $destNation) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$testTurn->setArg(['destNationID' => $destNation['nation']]);
|
||||
$testCommand = new static($generalObj, $this->env, $testTurn, ['destNationID' => $destNation['nation']]);
|
||||
if ($testCommand->hasFullConditionMet()) {
|
||||
$destNation['availableCommand'] = true;
|
||||
} else {
|
||||
$destNation['availableCommand'] = false;
|
||||
|
||||
$nationTarget = [
|
||||
'id' => $destNation['nation'],
|
||||
'name' => $destNation['name'],
|
||||
'color' => $destNation['color'],
|
||||
'power' => $destNation['power'],
|
||||
];
|
||||
if (!$testCommand->hasFullConditionMet()) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
if ($destNation['id'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
$nationList[] = $destNation;
|
||||
$nationList[] = $nationTarget;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 국가에 급습을 발동합니다.<br>
|
||||
선포, 전쟁중인 상대국에만 가능합니다.<br>
|
||||
상대 국가를 목록에서 선택하세요.<br>
|
||||
배경색은 현재 급습 불가능 국가는 <font color=red>붉은색</font>으로 표시됩니다.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($nationList as $nation) : ?>
|
||||
<option value='<?= $nation['nation'] ?>' style='color:<?= $nation['color'] ?>;<?= $nation['availableCommand'] ? '' : 'background-color:red;' ?>'>【<?= $nation['name'] ?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
<input type=button id="commonSubmit" value="<?= $this->getName() ?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
return [
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'nationList' => $nationList,
|
||||
'startYear' => $this->env['startyear'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -214,53 +214,22 @@ class che_몰수 extends Command\NationCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
//TODO: 암행부처럼 보여야...
|
||||
$db = DB::db();
|
||||
|
||||
$destRawGenerals = $db->query('SELECT no,name,officer_level,npc,gold,rice FROM general WHERE nation = %i ORDER BY npc,binary(name)', $this->generalObj->getNationID());
|
||||
$destGeneralList = [];
|
||||
foreach ($destRawGenerals as $destGeneral) {
|
||||
$nameColor = \sammo\getNameColor($destGeneral['npc']);
|
||||
if ($nameColor) {
|
||||
$nameColor = " style='color:{$nameColor}'";
|
||||
}
|
||||
|
||||
$name = $destGeneral['name'];
|
||||
if ($destGeneral['officer_level'] >= 5) {
|
||||
$name = "*{$name}*";
|
||||
}
|
||||
|
||||
$destGeneralList[] = [
|
||||
'no' => $destGeneral['no'],
|
||||
'color' => $nameColor,
|
||||
'name' => $name,
|
||||
'gold' => $destGeneral['gold'],
|
||||
'rice' => $destGeneral['rice']
|
||||
];
|
||||
}
|
||||
ob_start();
|
||||
?>
|
||||
장수의 자금이나 군량을 몰수합니다.<br>
|
||||
몰수한것은 국가재산으로 귀속됩니다.<br>
|
||||
<select class='formInput' name="destGeneralID" id="destGeneralID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($destGeneralList as $destGeneral) : ?>
|
||||
<option value='<?= $destGeneral['no'] ?>' <?= $destGeneral['color'] ?>><?= $destGeneral['name'] ?>(금:<?= $destGeneral['gold'] ?>, 쌀:<?= $destGeneral['rice'] ?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<select class='formInput' name="isGold" id="isGold" size='1' style='color:white;background-color:black;'>
|
||||
<option value="true">금</option>
|
||||
<option value="false">쌀</option>
|
||||
</select>
|
||||
</select>
|
||||
<select class='formInput' name="amount" id="amount" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach (GameConst::$resourceActionAmountGuide as $amount) : ?>
|
||||
<option value='<?= $amount ?>'><?= $amount ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
$nationID = $this->getNationID();
|
||||
$troops = Util::convertArrayToDict($db->query('SELECT * FROM troop WHERE nation=%i', $nationID), 'troop_leader');
|
||||
$destRawGenerals = $db->queryAllLists('SELECT no,name,officer_level,npc,gold,rice,leadership,strength,intel,city,crew,train,atmos,troop FROM general WHERE nation = %i ORDER BY npc,binary(name)', $nationID);
|
||||
return [
|
||||
'procRes' => [
|
||||
'troops' => $troops,
|
||||
'generals' => $destRawGenerals,
|
||||
'generalsKey' => ['no', 'name', 'officerLevel', 'npc', 'gold', 'rice', 'leadership', 'strength', 'intel', 'cityID', 'crew', 'train', 'atmos', 'troopID'],
|
||||
'cities' => \sammo\JSOptionsForCities(),
|
||||
'minAmount' => 100,
|
||||
'maxAmount' => GameConst::$maxResourceActionAmount,
|
||||
'amountGuide' => GameConst::$resourceActionAmountGuide,
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
@@ -21,64 +25,67 @@ use function \sammo\getNationStaticInfo;
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
class che_물자원조 extends Command\NationCommand{
|
||||
class che_물자원조 extends Command\NationCommand
|
||||
{
|
||||
static protected $actionName = '원조';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!key_exists('destNationID', $this->arg)){
|
||||
if (!key_exists('destNationID', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
$destNationID = $this->arg['destNationID'];
|
||||
if(!is_int($destNationID)){
|
||||
if (!is_int($destNationID)) {
|
||||
return false;
|
||||
}
|
||||
if($destNationID < 1){
|
||||
if ($destNationID < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!key_exists('amountList', $this->arg)){
|
||||
if (!key_exists('amountList', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
$amountList = $this->arg['amountList'];
|
||||
if(!is_array($amountList)){
|
||||
if (!is_array($amountList)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(count($amountList) != 2){
|
||||
if (count($amountList) != 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
[$goldAmount, $riceAmount] = $amountList;
|
||||
|
||||
if(!is_int($goldAmount) || !is_int($riceAmount)){
|
||||
if (!is_int($goldAmount) || !is_int($riceAmount)) {
|
||||
return false;
|
||||
}
|
||||
if($goldAmount < 0 || $riceAmount < 0){
|
||||
if ($goldAmount < 0 || $riceAmount < 0) {
|
||||
return false;
|
||||
}
|
||||
if($goldAmount == 0 && $riceAmount == 0){
|
||||
if ($goldAmount == 0 && $riceAmount == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->arg = [
|
||||
'destNationID'=>$destNationID,
|
||||
'amountList'=>[$goldAmount, $riceAmount]
|
||||
'destNationID' => $destNationID,
|
||||
'amountList' => [$goldAmount, $riceAmount]
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
protected function init()
|
||||
{
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation(['gold', 'rice', 'surlimit']);
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
@@ -94,47 +101,51 @@ class che_물자원조 extends Command\NationCommand{
|
||||
[$goldAmount, $riceAmount] = $this->arg['amountList'];
|
||||
$limit = $this->nation['level'] * GameConst::$coefAidAmount;
|
||||
|
||||
if($goldAmount > $limit || $riceAmount > $limit){
|
||||
$this->fullConditionConstraints[
|
||||
ConstraintHelper::AlwaysFail('작위 제한량 이상은 보낼 수 없습니다.')
|
||||
];
|
||||
if ($goldAmount > $limit || $riceAmount > $limit) {
|
||||
$this->fullConditionConstraints[ConstraintHelper::AlwaysFail('작위 제한량 이상은 보낼 수 없습니다.')];
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::ExistsDestNation(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::SuppliedCity(),
|
||||
ConstraintHelper::ReqNationGold(GameConst::$basegold+(($goldAmount>0)?1:0)),
|
||||
ConstraintHelper::ReqNationRice(GameConst::$baserice+(($riceAmount>0)?1:0)),
|
||||
ConstraintHelper::ReqNationGold(GameConst::$basegold + (($goldAmount > 0) ? 1 : 0)),
|
||||
ConstraintHelper::ReqNationRice(GameConst::$baserice + (($riceAmount > 0) ? 1 : 0)),
|
||||
ConstraintHelper::ReqNationValue('surlimit', '외교제한', '==', 0, '외교제한중입니다.'),
|
||||
ConstraintHelper::ReqDestNationValue('surlimit', '외교제한', '==', 0, '상대국이 외교제한중입니다.'),
|
||||
];
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
//NOTE: 자체 postReqTurn 사용
|
||||
return 12;
|
||||
}
|
||||
|
||||
public function getNextAvailableTurn():?int{
|
||||
public function getNextAvailableTurn(): ?int
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setNextAvailable(?int $yearMonth=null){
|
||||
public function setNextAvailable(?int $yearMonth = null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
public function getBrief(): string
|
||||
{
|
||||
[$goldAmount, $riceAmount] = $this->arg['amountList'];
|
||||
$goldAmountText = number_format($goldAmount);
|
||||
$riceAmountText = number_format($riceAmount);
|
||||
@@ -144,8 +155,9 @@ class che_물자원조 extends Command\NationCommand{
|
||||
}
|
||||
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
@@ -196,7 +208,7 @@ class che_물자원조 extends Command\NationCommand{
|
||||
$broadcastMessage = "<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원했습니다.";
|
||||
|
||||
$chiefList = $db->queryFirstColumn('SELECT no FROM general WHERE officer_level >= 5 AND no != %i AND nation = %i', $generalID, $nationID);
|
||||
foreach($chiefList as $chiefID){
|
||||
foreach ($chiefList as $chiefID) {
|
||||
$chiefLogger = new ActionLogger($chiefID, $nationID, $year, $month);
|
||||
$chiefLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$chiefLogger->flush();
|
||||
@@ -211,7 +223,7 @@ class che_물자원조 extends Command\NationCommand{
|
||||
|
||||
$destBroadcastMessage = $broadcastMessage = "<D><b>{$nationName}</b></>에서 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 원조했습니다.";
|
||||
$destChiefList = $db->queryFirstColumn('SELECT no FROM general WHERE officer_level >= 5 AND nation = %i', $destNationID);
|
||||
foreach($destChiefList as $destChiefID){
|
||||
foreach ($destChiefList as $destChiefID) {
|
||||
$destChiefLogger = new ActionLogger($destChiefID, $nationID, $year, $month);
|
||||
$destChiefLogger->pushGeneralActionLog($destBroadcastMessage, ActionLogger::PLAIN);
|
||||
$destChiefLogger->flush();
|
||||
@@ -222,19 +234,19 @@ class che_물자원조 extends Command\NationCommand{
|
||||
$destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaRoSrc}부터 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원 받음");
|
||||
|
||||
$destNationStor = KVStorage::getStorage(DB::db(), $destNationID, 'nation_env');
|
||||
$destRecvAssist = $destNationStor->getValue('recv_assist')??[];
|
||||
$destRecvAssist["n{$nationID}"] = [$nationID, ($destRecvAssist["n{$nationID}"][1]??0) + $goldAmount + $riceAmount];
|
||||
$destRecvAssist = $destNationStor->getValue('recv_assist') ?? [];
|
||||
$destRecvAssist["n{$nationID}"] = [$nationID, ($destRecvAssist["n{$nationID}"][1] ?? 0) + $goldAmount + $riceAmount];
|
||||
$destNationStor->setValue('recv_assist', $destRecvAssist);
|
||||
|
||||
$db->update('nation', [
|
||||
'gold'=>$db->sqleval('gold - %i', $goldAmount),
|
||||
'rice'=>$db->sqleval('rice - %i', $riceAmount),
|
||||
'surlimit'=>$db->sqleval('surlimit + %i', $this->getPostReqTurn())
|
||||
'gold' => $db->sqleval('gold - %i', $goldAmount),
|
||||
'rice' => $db->sqleval('rice - %i', $riceAmount),
|
||||
'surlimit' => $db->sqleval('surlimit + %i', $this->getPostReqTurn())
|
||||
], 'nation = %i', $nationID);
|
||||
|
||||
$db->update('nation', [
|
||||
'gold'=>$db->sqleval('gold + %i', $goldAmount),
|
||||
'rice'=>$db->sqleval('rice + %i', $riceAmount),
|
||||
'gold' => $db->sqleval('gold + %i', $goldAmount),
|
||||
'rice' => $db->sqleval('rice + %i', $riceAmount),
|
||||
], 'nation = %i', $destNationID);
|
||||
|
||||
$general->addExperience(5);
|
||||
@@ -246,47 +258,48 @@ class che_물자원조 extends Command\NationCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationList = [];
|
||||
foreach (getAllNationStaticInfo() as $destNation) {
|
||||
$nationTarget = [
|
||||
'id' => $destNation['nation'],
|
||||
'name' => $destNation['name'],
|
||||
'color' => $destNation['color'],
|
||||
'power' => $destNation['power'],
|
||||
];
|
||||
|
||||
//TODO: 물자원조 자체가 가능한지도 검사?
|
||||
|
||||
if ($nationTarget['id'] == $generalObj->getNationID()) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
$nationList[] = $nationTarget;
|
||||
}
|
||||
$currentNationLevel = getNationStaticInfo($this->generalObj->getNationID())['level'];
|
||||
|
||||
$levelInfo = [];
|
||||
foreach (\sammo\getNationLevelList() as $level => [$levelText,,]) {
|
||||
$levelInfo[$level] = ['text' => $levelText, 'amount' => $level * GameConst::$coefAidAmount];
|
||||
}
|
||||
|
||||
$amountGuide = [];
|
||||
foreach (Util::range(1, $currentNationLevel + 1) as $nationLevel) {
|
||||
$amountGuide[] = $nationLevel * GameConst::$coefAidAmount;
|
||||
}
|
||||
|
||||
return [
|
||||
'defaultSelectNationByMap'
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'nationList' => $nationList,
|
||||
'currentNationLevel' => $currentNationLevel,
|
||||
'levelInfo' => $levelInfo,
|
||||
'minAmount' => 1000,
|
||||
'maxAmount' => Util::array_last($amountGuide),
|
||||
'amountGuide' => $amountGuide,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
$currentNationLevel = getNationStaticInfo($this->generalObj->getNationID())['level'];
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
타국에게 원조합니다.<br>
|
||||
작위별로 금액 제한이 있습니다.<br>
|
||||
<?php foreach(\sammo\getNationLevelList() as $level => [$levelText,,]): ?>
|
||||
<?=StringUtil::padStringAlignRight($levelText, 10)?>: <?=number_format($level*GameConst::$coefAidAmount)?><br>
|
||||
<?php endforeach; ?>
|
||||
원조할 국가를 목록에서 선택하세요.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach(getAllNationStaticInfo() as $nation): ?>
|
||||
<option
|
||||
value='<?=$nation['nation']?>'
|
||||
style='color:<?=$nation['color']?>;'
|
||||
>【<?=$nation['name']?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
국고 <select class='formInput amountList' name="amountList[]" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach(Util::range($currentNationLevel+1) as $nationLevel): ?>
|
||||
<option value='<?=$nationLevel*GameConst::$coefAidAmount?>'><?=$nationLevel*GameConst::$coefAidAmount?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
병량 <select class='formInput amountList' name="amountList[]" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach(Util::range($currentNationLevel+1) as $nationLevel): ?>
|
||||
<option value='<?=$nationLevel*GameConst::$coefAidAmount?>'><?=$nationLevel*GameConst::$coefAidAmount?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
@@ -18,41 +22,44 @@ use function \sammo\cutTurn;
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
class che_발령 extends Command\NationCommand{
|
||||
class che_발령 extends Command\NationCommand
|
||||
{
|
||||
static protected $actionName = '발령';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
//NOTE: 사망 직전에 턴을 넣을 수 있으므로, 존재하지 않는 장수여도 argTest에서 바로 탈락시키지 않음
|
||||
if(!key_exists('destGeneralID', $this->arg)){
|
||||
if (!key_exists('destGeneralID', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
if(!key_exists('destCityID', $this->arg)){
|
||||
if (!key_exists('destCityID', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
if(CityConst::byID($this->arg['destCityID']) === null){
|
||||
if (CityConst::byID($this->arg['destCityID']) === null) {
|
||||
return false;
|
||||
}
|
||||
$destGeneralID = $this->arg['destGeneralID'];
|
||||
$destCityID = $this->arg['destCityID'];
|
||||
|
||||
$this->arg = [
|
||||
'destGeneralID'=>$destGeneralID,
|
||||
'destCityID'=>$destCityID,
|
||||
'destGeneralID' => $destGeneralID,
|
||||
'destCityID' => $destCityID,
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
protected function init()
|
||||
{
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation();
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
@@ -67,14 +74,14 @@ class che_발령 extends Command\NationCommand{
|
||||
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null, 1);
|
||||
$this->setDestGeneral($destGeneral);
|
||||
|
||||
if($this->arg['destGeneralID'] == $this->getGeneral()->getID()){
|
||||
$this->fullConditionConstraints=[
|
||||
if ($this->arg['destGeneralID'] == $this->getGeneral()->getID()) {
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::AlwaysFail('본인입니다')
|
||||
];
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
@@ -86,29 +93,34 @@ class che_발령 extends Command\NationCommand{
|
||||
];
|
||||
}
|
||||
|
||||
public function getFailString():string{
|
||||
public function getFailString(): string
|
||||
{
|
||||
$commandName = $this->getName();
|
||||
$failReason = $this->testFullConditionMet();
|
||||
if($failReason === null){
|
||||
if ($failReason === null) {
|
||||
throw new \RuntimeException('실행 가능한 커맨드에 대해 실패 이유를 수집');
|
||||
}
|
||||
$destGeneralName = $this->destGeneralObj->getName();
|
||||
return "{$failReason} <Y>{$destGeneralName}</> {$commandName} 실패.";
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
public function getBrief(): string
|
||||
{
|
||||
$commandName = $this->getName();
|
||||
$destGeneralName = $this->destGeneralObj->getName();
|
||||
$destCityName = CityConst::byID($this->arg['destCityID'])->name;
|
||||
@@ -117,8 +129,9 @@ class che_발령 extends Command\NationCommand{
|
||||
}
|
||||
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
@@ -144,8 +157,8 @@ class che_발령 extends Command\NationCommand{
|
||||
$destGeneral->getLogger()->pushGeneralActionLog("<Y>{$generalName}</>에 의해 <G><b>{$destCityName}</b></>{$josaRo} 발령됐습니다. <1>$date</>");
|
||||
|
||||
$yearMonth = Util::joinYearMonth($this->env['year'], $this->env['month']);
|
||||
if(cutTurn($general->getTurnTime(), $this->env['turnterm']) != cutTurn($destGeneral->getTurnTime(), $this->env['turnterm'])){
|
||||
$yearMonth+=1;
|
||||
if (cutTurn($general->getTurnTime(), $this->env['turnterm']) != cutTurn($destGeneral->getTurnTime(), $this->env['turnterm'])) {
|
||||
$yearMonth += 1;
|
||||
}
|
||||
$destGeneral->setAuxVar('last발령', $yearMonth);
|
||||
$logger->pushGeneralActionLog("<Y>{$destGeneralName}</>{$josaUl} <G><b>{$destCityName}</b></>{$josaRo} 발령했습니다. <1>$date</>");
|
||||
@@ -157,56 +170,21 @@ class che_발령 extends Command\NationCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectCityByMap'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$db = DB::db();
|
||||
|
||||
$nationID = $this->generalObj->getNationID();
|
||||
|
||||
$nationID = $this->getNationID();
|
||||
$troops = Util::convertArrayToDict($db->query('SELECT * FROM troop WHERE nation=%i', $nationID), 'troop_leader');
|
||||
$destRawGenerals = $db->query('SELECT no,name,officer_level,npc,gold,rice,leadership,strength,intel,city,crew,train,atmos,troop FROM general WHERE nation = %i ORDER BY npc,binary(name)',$nationID);
|
||||
$destGeneralList = [];
|
||||
foreach($destRawGenerals as $destGeneral){
|
||||
$nameColor = \sammo\getNameColor($destGeneral['npc']);
|
||||
if($nameColor){
|
||||
$nameColor = " style='color:{$nameColor}'";
|
||||
}
|
||||
|
||||
$name = $destGeneral['name'];
|
||||
if($destGeneral['officer_level'] >= 5){
|
||||
$name = "*{$name}*";
|
||||
}
|
||||
|
||||
$destGeneral['name'] = $name;
|
||||
$destGeneral['color'] = $nameColor;
|
||||
$destGeneralList[] = $destGeneral;
|
||||
}
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
선택된 도시로 아국 장수를 발령합니다.<br>
|
||||
아국 도시로만 발령이 가능합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<select class='formInput' name="destGeneralID" id="destGeneralID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach($destGeneralList as $destGeneral): ?>
|
||||
<option value='<?=$destGeneral['no']?>' <?=$destGeneral['color']?>><?=$destGeneral['name']?>[<?=CityConst::byID($destGeneral['city'])->name?>]
|
||||
(<?=$destGeneral['leadership']?>/<?=$destGeneral['strength']?>/<?=$destGeneral['intel']?>)
|
||||
<병<?=number_format($destGeneral['crew'])?>/훈<?=$destGeneral['train']?>/사<?=$destGeneral['atmos']?>/<?=$destGeneral['troop']?$troops[$destGeneral['troop']]['name']:'-'?>>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'>
|
||||
<?=\sammo\optionsForCities()?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
$destRawGenerals = $db->queryAllLists('SELECT no,name,officer_level,npc,gold,rice,leadership,strength,intel,city,crew,train,atmos,troop FROM general WHERE nation = %i ORDER BY npc,binary(name)', $nationID);
|
||||
return [
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'distanceList' => \sammo\JSCitiesBasedOnDistance($this->generalObj->getCityID(), 1),
|
||||
'cities' => \sammo\JSOptionsForCities(),
|
||||
'troops' => $troops,
|
||||
'generals' => $destRawGenerals,
|
||||
'generalsKey' => ['no', 'name', 'officerLevel', 'npc', 'gold', 'rice', 'leadership', 'strength', 'intel', 'cityID', 'crew', 'train', 'atmos', 'troopID']
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
@@ -18,30 +22,33 @@ use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Event\Action;
|
||||
|
||||
class che_백성동원 extends Command\NationCommand{
|
||||
class che_백성동원 extends Command\NationCommand
|
||||
{
|
||||
static protected $actionName = '백성동원';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!key_exists('destCityID', $this->arg)){
|
||||
if (!key_exists('destCityID', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
if(CityConst::byID($this->arg['destCityID']) === null){
|
||||
if (CityConst::byID($this->arg['destCityID']) === null) {
|
||||
return false;
|
||||
}
|
||||
$destCityID = $this->arg['destCityID'];
|
||||
|
||||
$this->arg = [
|
||||
'destCityID'=>$destCityID,
|
||||
'destCityID' => $destCityID,
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
protected function init()
|
||||
{
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
@@ -49,7 +56,7 @@ class che_백성동원 extends Command\NationCommand{
|
||||
$this->setCity();
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::AvailableStrategicCommand()
|
||||
@@ -61,7 +68,7 @@ class che_백성동원 extends Command\NationCommand{
|
||||
$this->setDestCity($this->arg['destCityID']);
|
||||
$this->setDestNation($this->destCity['nation']);
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::OccupiedDestCity(),
|
||||
@@ -69,38 +76,44 @@ class che_백성동원 extends Command\NationCommand{
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn()+1;
|
||||
$reqTurn = $this->getPreReqTurn() + 1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(재사용 대기 $postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount*4)*10);
|
||||
$nextTerm = Util::round(sqrt($genCount * 4) * 10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
public function getBrief(): string
|
||||
{
|
||||
$commandName = $this->getName();
|
||||
$destCityName = CityConst::byID($this->arg['destCityID'])->name;
|
||||
return "【{$destCityName}】에 {$commandName}";
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
@@ -132,7 +145,7 @@ class che_백성동원 extends Command\NationCommand{
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <G><b>{$destCityName}</b></>에 <M>백성동원</>을 하였습니다.";
|
||||
|
||||
$targetGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach($targetGeneralList as $targetGeneralID){
|
||||
foreach ($targetGeneralList as $targetGeneralID) {
|
||||
$targetLogger = new ActionLogger($targetGeneralID, $nationID, $year, $month);
|
||||
$targetLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$targetLogger->flush();
|
||||
@@ -159,27 +172,14 @@ class che_백성동원 extends Command\NationCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectCityByMap'
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'cities' => \sammo\JSOptionsForCities(),
|
||||
'distanceList' => new \stdClass(),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
선택된 도시에 백성을 동원해 성벽을 쌓습니다.<br>
|
||||
아국 도시만 가능합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'>
|
||||
<?=\sammo\optionsForCities()?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,74 +223,46 @@ class che_불가침제의 extends Command\NationCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectNationByMap'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationID = $generalObj->getNationID();
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
$nationList = [];
|
||||
$testTurn = new LastTurn($this->getName(), null, $this->getPreReqTurn());
|
||||
$currYear = $this->env['year'];
|
||||
|
||||
$diplomacyStatus = Util::convertArrayToDict(
|
||||
$db->query('SELECT * FROM diplomacy WHERE me = %i', $nationID),
|
||||
'you'
|
||||
);
|
||||
|
||||
$nationList = [];
|
||||
foreach (getAllNationStaticInfo() as $destNation) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$testCommand = new static($generalObj, $this->env, $this->getLastTurn(), [
|
||||
$testCommand = new static($generalObj, $this->env, $testTurn, [
|
||||
'destNationID' => $destNation['nation'],
|
||||
'year' => $currYear + 1,
|
||||
'month' => 12
|
||||
'year' => $currYear + 2,
|
||||
'month' => 1
|
||||
]);
|
||||
|
||||
$nationTarget = [
|
||||
'id' => $destNation['nation'],
|
||||
'name' => $destNation['name'],
|
||||
'color' => $destNation['color'],
|
||||
'power' => $destNation['power'],
|
||||
];
|
||||
if (!$testCommand->hasFullConditionMet()) {
|
||||
$destNation['cssBgColor'] = 'background-color:red;';
|
||||
} else if ($diplomacyStatus[$destNation['nation']]['state'] == 7) {
|
||||
$destNation['cssBgColor'] = 'background-color:blue;';
|
||||
} else {
|
||||
$destNation['cssBgColor'] = '';
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
if ($destNation['id'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
$nationList[] = $destNation;
|
||||
$nationList[] = $nationTarget;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
타국에게 불가침을 제의합니다.<br>
|
||||
제의할 국가를 목록에서 선택하세요.<br>
|
||||
불가침 기한 다음 달부터 선포 가능합니다.<br>
|
||||
배경색은 현재 제의가 불가능한 국가는 <font color=red>붉은색</font>, 현재 불가침중인 국가는 <font color=blue>푸른색</font>으로 표시됩니다.<br>
|
||||
<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($nationList as $nation) : ?>
|
||||
<option value='<?= $nation['nation'] ?>' style='color:<?= $nation['color'] ?>;<?= $nation['cssBgColor'] ?>'>【<?= $nation['name'] ?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
</select>에게
|
||||
<select class='formInput' name="year" id="year" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach (Util::range($currYear + 1, $currYear + 20 + 1) as $formYear) : ?>
|
||||
<option value='<?= $formYear ?>'><?= $formYear ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>년
|
||||
<select class='formInput' name="month" id="month" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach (Util::range(1, 12 + 1) as $formMonth) : ?>
|
||||
<option value='<?= $formMonth ?>'><?= $formMonth ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>월까지
|
||||
<input type=button id="commonSubmit" value="<?= $this->getName() ?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
return [
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'nationList' => $nationList,
|
||||
'startYear' => $this->env['startyear'],
|
||||
'minYear' => $this->env['year'] + 1,
|
||||
'maxYear' => $this->env['year'] + 20,
|
||||
'month' => $this->env['month'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,17 +170,11 @@ class che_불가침파기제의 extends Command\NationCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectNationByMap'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationID = $generalObj->getNationID();
|
||||
$nationList = [];
|
||||
|
||||
$db = DB::db();
|
||||
$diplomacyStatus = Util::convertArrayToDict(
|
||||
@@ -188,39 +182,29 @@ class che_불가침파기제의 extends Command\NationCommand{
|
||||
'you'
|
||||
);
|
||||
|
||||
$nationList = [];
|
||||
foreach(getAllNationStaticInfo() as $destNation){
|
||||
if($destNation['nation'] == $nationID){
|
||||
continue;
|
||||
}
|
||||
foreach (getAllNationStaticInfo() as $destNation) {
|
||||
$nationTarget = [
|
||||
'id' => $destNation['nation'],
|
||||
'name' => $destNation['name'],
|
||||
'color' => $destNation['color'],
|
||||
'power' => $destNation['power'],
|
||||
];
|
||||
|
||||
if($diplomacyStatus[$destNation['nation']]['state'] != 7){
|
||||
$destNation['cssBgColor'] = 'background-color:red;';
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
else{
|
||||
$destNation['cssBgColor'] = '';
|
||||
if ($destNation['id'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
$nationList[] = $destNation;
|
||||
$nationList[] = $nationTarget;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
불가침중인 국가에 조약 파기를 제의합니다.<br>
|
||||
제의할 국가를 목록에서 선택하세요.<br>
|
||||
배경색은 현재 제의가 불가능한 국가는 <font color=red>붉은색</font>으로 표시됩니다.<br>
|
||||
<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach($nationList as $nation): ?>
|
||||
<option
|
||||
value='<?=$nation['nation']?>'
|
||||
style='color:<?=$nation['color']?>;<?=$nation['cssBgColor']?>'
|
||||
>【<?=$nation['name']?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
</select>에게
|
||||
<input type=button id="commonSubmit" value="<?=$this->getName()?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
return [
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'nationList' => $nationList,
|
||||
'startYear' => $this->env['startyear'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -192,50 +192,38 @@ class che_선전포고 extends Command\NationCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectNationByMap'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationID = $generalObj->getNationID();
|
||||
$startYear = $this->env['startyear'];
|
||||
$availableYear = $startYear + 1;
|
||||
$nationList = [];
|
||||
$testTurn = new LastTurn($this->getName(), null, $this->getPreReqTurn());
|
||||
foreach (getAllNationStaticInfo() as $destNation) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
continue;
|
||||
$testTurn->setArg(['destNationID' => $destNation['nation']]);
|
||||
$testCommand = new static($generalObj, $this->env, $testTurn, ['destNationID' => $destNation['nation']]);
|
||||
|
||||
$nationTarget = [
|
||||
'id' => $destNation['nation'],
|
||||
'name' => $destNation['name'],
|
||||
'color' => $destNation['color'],
|
||||
'power' => $destNation['power'],
|
||||
];
|
||||
if (!$testCommand->hasFullConditionMet()) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
if ($destNation['id'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
$testCommand = new static($generalObj, $this->env, $this->getLastTurn(), ['destNationID' => $destNation['nation']]);
|
||||
if ($testCommand->hasFullConditionMet()) {
|
||||
$destNation['availableWar'] = true;
|
||||
} else {
|
||||
$destNation['availableWar'] = false;
|
||||
}
|
||||
|
||||
$nationList[] = $destNation;
|
||||
$nationList[] = $nationTarget;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
타국에게 선전 포고합니다.<br>
|
||||
선전 포고할 국가를 목록에서 선택하세요.<br>
|
||||
고립되지 않은 아국 도시에서 인접한 국가에 선포 가능합니다.<br>
|
||||
초반제한 해제 2년전부터 선포가 가능합니다. (<?= $availableYear ?>년 1월부터 가능)<br>
|
||||
현재 선포가 불가능한 국가는 배경색이 <font color=red>붉은색</font>으로 표시됩니다.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($nationList as $nation) : ?>
|
||||
<option value='<?= $nation['nation'] ?>' style='color:<?= $nation['color'] ?>;<?= $nation['availableWar'] ? '' : 'background-color:red;' ?>'>【<?= $nation['name'] ?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<input type=button id="commonSubmit" value="<?= $this->getName() ?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
return [
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'nationList' => $nationList,
|
||||
'startYear' => $this->env['startyear'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
@@ -20,30 +24,33 @@ use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Event\Action;
|
||||
|
||||
class che_수몰 extends Command\NationCommand{
|
||||
class che_수몰 extends Command\NationCommand
|
||||
{
|
||||
static protected $actionName = '수몰';
|
||||
static public $reqArg = true;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
if(!key_exists('destCityID', $this->arg)){
|
||||
if (!key_exists('destCityID', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
if(CityConst::byID($this->arg['destCityID']) === null){
|
||||
if (CityConst::byID($this->arg['destCityID']) === null) {
|
||||
return false;
|
||||
}
|
||||
$destCityID = $this->arg['destCityID'];
|
||||
|
||||
$this->arg = [
|
||||
'destCityID'=>$destCityID,
|
||||
'destCityID' => $destCityID,
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
protected function init()
|
||||
{
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
@@ -51,7 +58,7 @@ class che_수몰 extends Command\NationCommand{
|
||||
$this->setCity();
|
||||
$this->setNation(['strategic_cmd_limit']);
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::AvailableStrategicCommand(),
|
||||
@@ -63,7 +70,7 @@ class che_수몰 extends Command\NationCommand{
|
||||
$this->setDestCity($this->arg['destCityID']);
|
||||
$this->setDestNation($this->destCity['nation']);
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::NotNeutralDestCity(),
|
||||
@@ -73,39 +80,45 @@ class che_수몰 extends Command\NationCommand{
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn()+1;
|
||||
$reqTurn = $this->getPreReqTurn() + 1;
|
||||
$postReqTurn = $this->getPostReqTurn();
|
||||
|
||||
return "{$name}/{$reqTurn}턴(재사용 대기 $postReqTurn)";
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount*4)*10);
|
||||
$nextTerm = Util::round(sqrt($genCount * 4) * 10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
public function getBrief(): string
|
||||
{
|
||||
$commandName = $this->getName();
|
||||
$destCityName = CityConst::byID($this->arg['destCityID'])->name;
|
||||
$josaUl = JosaUtil::pick($destCityName, '을');
|
||||
return "【{$destCityName}】{$josaUl} {$commandName}";
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
@@ -140,7 +153,7 @@ class che_수몰 extends Command\NationCommand{
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <G><b>{$destCityName}</b></>에 <M>수몰</>을 발동하였습니다.";
|
||||
|
||||
$targetGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach($targetGeneralList as $targetGeneralID){
|
||||
foreach ($targetGeneralList as $targetGeneralID) {
|
||||
$targetLogger = new ActionLogger($targetGeneralID, $nationID, $year, $month);
|
||||
$targetLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$targetLogger->flush();
|
||||
@@ -150,12 +163,13 @@ class che_수몰 extends Command\NationCommand{
|
||||
|
||||
$targetGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i', $destNationID);
|
||||
$destNationLogged = false;
|
||||
foreach($targetGeneralList as $targetGeneralID){
|
||||
foreach ($targetGeneralList as $targetGeneralID) {
|
||||
$targetLogger = new ActionLogger($targetGeneralID, $destNationID, $year, $month);
|
||||
$targetLogger->pushGeneralActionLog($destBroadcastMessage, ActionLogger::PLAIN);
|
||||
if(!$destNationLogged){
|
||||
if (!$destNationLogged) {
|
||||
$targetLogger->pushNationalHistoryLog(
|
||||
"<D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} 아국의 <G><b>{$destCityName}</b></>에 <M>수몰</>을 발동", ActionLogger::PLAIN
|
||||
"<D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} 아국의 <G><b>{$destCityName}</b></>에 <M>수몰</>을 발동",
|
||||
ActionLogger::PLAIN
|
||||
);
|
||||
$destNationLogged = true;
|
||||
}
|
||||
@@ -182,27 +196,14 @@ class che_수몰 extends Command\NationCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectCityByMap'
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'cities' => \sammo\JSOptionsForCities(),
|
||||
'distanceList' => new \stdClass(),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
선택된 도시에 수몰을 발동합니다.<br>
|
||||
전쟁중인 상대국 도시만 가능합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'>
|
||||
<?=\sammo\optionsForCities()?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,48 +199,36 @@ class che_이호경식 extends Command\NationCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectNationByMap'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationID = $generalObj->getNationID();
|
||||
$nationList = [];
|
||||
$testTurn = new LastTurn($this->getName(), null, $this->getPreReqTurn());
|
||||
foreach (getAllNationStaticInfo() as $destNation) {
|
||||
if ($destNation['nation'] == $nationID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$testTurn->setArg(['destNationID' => $destNation['nation']]);
|
||||
$testCommand = new static($generalObj, $this->env, $testTurn, ['destNationID' => $destNation['nation']]);
|
||||
if ($testCommand->hasFullConditionMet()) {
|
||||
$destNation['availableCommand'] = true;
|
||||
} else {
|
||||
$destNation['availableCommand'] = false;
|
||||
|
||||
$nationTarget = [
|
||||
'id' => $destNation['nation'],
|
||||
'name' => $destNation['name'],
|
||||
'color' => $destNation['color'],
|
||||
'power' => $destNation['power'],
|
||||
];
|
||||
if (!$testCommand->hasFullConditionMet()) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
if ($destNation['id'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
$nationList[] = $destNation;
|
||||
$nationList[] = $nationTarget;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 국가에 이호경식을 발동합니다.<br>
|
||||
선포, 전쟁중인 상대국에만 가능합니다.<br>
|
||||
상대 국가를 목록에서 선택하세요.<br>
|
||||
배경색은 현재 이호경식 불가능 국가는 <font color=red>붉은색</font>으로 표시됩니다.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($nationList as $nation) : ?>
|
||||
<option value='<?= $nation['nation'] ?>' style='color:<?= $nation['color'] ?>;<?= $nation['availableCommand'] ? '' : 'background-color:red;' ?>'>【<?= $nation['name'] ?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
<input type=button id="commonSubmit" value="<?= $this->getName() ?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
return [
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'nationList' => $nationList,
|
||||
'startYear' => $this->env['startyear'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,57 +168,36 @@ class che_종전제의 extends Command\NationCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectNationByMap'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationID = $generalObj->getNationID();
|
||||
|
||||
$db = DB::db();
|
||||
$diplomacyStatus = Util::convertArrayToDict(
|
||||
$db->query('SELECT * FROM diplomacy WHERE me = %i', $nationID),
|
||||
'you'
|
||||
);
|
||||
|
||||
$nationList = [];
|
||||
foreach(getAllNationStaticInfo() as $destNation){
|
||||
if($destNation['nation'] == $nationID){
|
||||
continue;
|
||||
$testTurn = new LastTurn($this->getName(), null, $this->getPreReqTurn());
|
||||
foreach (getAllNationStaticInfo() as $destNation) {
|
||||
$testCommand = new static($generalObj, $this->env, $testTurn, ['destNationID' => $destNation['nation']]);
|
||||
|
||||
$nationTarget = [
|
||||
'id' => $destNation['nation'],
|
||||
'name' => $destNation['name'],
|
||||
'color' => $destNation['color'],
|
||||
'power' => $destNation['power'],
|
||||
];
|
||||
if (!$testCommand->hasFullConditionMet()) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
if ($destNation['id'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
if(!in_array($diplomacyStatus[$destNation['nation']]['state'], [0, 1])){
|
||||
$destNation['cssBgColor'] = 'background-color:red;';
|
||||
}
|
||||
else{
|
||||
$destNation['cssBgColor'] = '';
|
||||
}
|
||||
|
||||
$nationList[] = $destNation;
|
||||
$nationList[] = $nationTarget;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
전쟁중인 국가에 종전을 제의합니다.<br>
|
||||
제의할 국가를 목록에서 선택하세요.<br>
|
||||
배경색은 현재 제의가 불가능한 국가는 <font color=red>붉은색</font>으로 표시됩니다.<br>
|
||||
<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach($nationList as $nation): ?>
|
||||
<option
|
||||
value='<?=$nation['nation']?>'
|
||||
style='color:<?=$nation['color']?>;<?=$nation['cssBgColor']?>'
|
||||
>【<?=$nation['name']?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
</select>에게
|
||||
<input type=button id="commonSubmit" value="<?=$this->getName()?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
return [
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'nationList' => $nationList,
|
||||
'startYear' => $this->env['startyear'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -230,27 +230,14 @@ class che_천도 extends Command\NationCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectCityByMap'
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'cities' => \sammo\JSOptionsForCities(),
|
||||
'distanceList' => new \stdClass(),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 도시로 천도합니다.<br>
|
||||
현재 수도에서 연결된 도시만 가능하며, 1+2×거리만큼의 턴이 필요합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'>
|
||||
<?= \sammo\optionsForCities() ?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,38 +196,14 @@ class che_초토화 extends Command\NationCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectCityByMap'
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'cities' => \sammo\JSOptionsForCities(),
|
||||
'distanceList' => new \stdClass(),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
|
||||
$cities = Util::convertArrayToDict(DB::db()->query('SELECT * FROM city WHERE nation =%i', $this->generalObj->getNationID()), 'city');
|
||||
$calc = function(CityInitialDetail $constCity)use($cities){
|
||||
if(!key_exists($constCity->id, $cities)){
|
||||
return null;
|
||||
}
|
||||
$amount = $this->calcReturnAmount($cities[$constCity->id]);
|
||||
$amountText = number_format($amount);
|
||||
return "금쌀 각 {$amountText} 회수";
|
||||
};
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
선택된 도시를 초토화 시킵니다.<br>
|
||||
도시가 공백지가 되며, 도시의 인구, 내정 상태에 따라 상당량의 국고가 확보됩니다.<br>
|
||||
국가의 수뇌들은 명성을 잃고, 모든 장수들은 배신 수치가 1 증가합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'>
|
||||
<?=\sammo\optionsForCities($calc)?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?=$this->getName()?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
@@ -177,53 +177,22 @@ class che_포상 extends Command\NationCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
//TODO: 암행부처럼 보여야...
|
||||
$db = DB::db();
|
||||
|
||||
$destRawGenerals = $db->query('SELECT no,name,officer_level,npc,gold,rice FROM general WHERE nation = %i ORDER BY npc,binary(name)', $this->generalObj->getNationID());
|
||||
$destGeneralList = [];
|
||||
foreach ($destRawGenerals as $destGeneral) {
|
||||
$nameColor = \sammo\getNameColor($destGeneral['npc']);
|
||||
if ($nameColor) {
|
||||
$nameColor = " style='color:{$nameColor}'";
|
||||
}
|
||||
|
||||
$name = $destGeneral['name'];
|
||||
if ($destGeneral['officer_level'] >= 5) {
|
||||
$name = "*{$name}*";
|
||||
}
|
||||
|
||||
$destGeneralList[] = [
|
||||
'no' => $destGeneral['no'],
|
||||
'color' => $nameColor,
|
||||
'name' => $name,
|
||||
'gold' => $destGeneral['gold'],
|
||||
'rice' => $destGeneral['rice']
|
||||
];
|
||||
}
|
||||
ob_start();
|
||||
?>
|
||||
국고로 장수에게 자금이나 군량을 지급합니다.<br>
|
||||
<select class='formInput' name="destGeneralID" id="destGeneralID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach ($destGeneralList as $destGeneral) : ?>
|
||||
<option value='<?= $destGeneral['no'] ?>' <?= $destGeneral['color'] ?>><?= $destGeneral['name'] ?>(금:<?= $destGeneral['gold'] ?>, 쌀:<?= $destGeneral['rice'] ?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<select class='formInput' name="isGold" id="isGold" size='1' style='color:white;background-color:black;'>
|
||||
<option value="true">금</option>
|
||||
<option value="false">쌀</option>
|
||||
</select>
|
||||
</select>
|
||||
<select class='formInput' name="amount" id="amount" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach (GameConst::$resourceActionAmountGuide as $amount) : ?>
|
||||
<option value='<?= $amount ?>'><?= $amount ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
$nationID = $this->getNationID();
|
||||
$troops = Util::convertArrayToDict($db->query('SELECT * FROM troop WHERE nation=%i', $nationID), 'troop_leader');
|
||||
$destRawGenerals = $db->queryAllLists('SELECT no,name,officer_level,npc,gold,rice,leadership,strength,intel,city,crew,train,atmos,troop FROM general WHERE nation = %i ORDER BY npc,binary(name)', $nationID);
|
||||
return [
|
||||
'procRes' => [
|
||||
'troops' => $troops,
|
||||
'generals' => $destRawGenerals,
|
||||
'generalsKey' => ['no', 'name', 'officerLevel', 'npc', 'gold', 'rice', 'leadership', 'strength', 'intel', 'cityID', 'crew', 'train', 'atmos', 'troopID'],
|
||||
'cities' => \sammo\JSOptionsForCities(),
|
||||
'minAmount' => 100,
|
||||
'maxAmount' => GameConst::$maxResourceActionAmount,
|
||||
'amountGuide' => GameConst::$resourceActionAmountGuide,
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General, DummyGeneral,
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
KVStorage,
|
||||
Message, MessageTarget
|
||||
Message,
|
||||
MessageTarget
|
||||
};
|
||||
|
||||
use function \sammo\buildNationCommandClass;
|
||||
@@ -20,48 +25,51 @@ use function \sammo\getNationStaticInfo;
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
class che_피장파장 extends Command\NationCommand{
|
||||
class che_피장파장 extends Command\NationCommand
|
||||
{
|
||||
static protected $actionName = '피장파장';
|
||||
static public $reqArg = true;
|
||||
static public $delayCnt = 60;
|
||||
|
||||
protected function argTest():bool{
|
||||
if($this->arg === null){
|
||||
protected function argTest(): bool
|
||||
{
|
||||
if ($this->arg === null) {
|
||||
return false;
|
||||
}
|
||||
//NOTE: 멸망 직전에 턴을 넣을 수 있으므로, 존재하지 않는 국가여도 argTest에서 바로 탈락시키지 않음
|
||||
if(!key_exists('destNationID', $this->arg)){
|
||||
if (!key_exists('destNationID', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
if(!key_exists('commandType', $this->arg)){
|
||||
if (!key_exists('commandType', $this->arg)) {
|
||||
return false;
|
||||
}
|
||||
$destNationID = $this->arg['destNationID'];
|
||||
$commandType = $this->arg['commandType'];
|
||||
|
||||
if(!is_int($destNationID)){
|
||||
if (!is_int($destNationID)) {
|
||||
return false;
|
||||
}
|
||||
if($destNationID < 1){
|
||||
if ($destNationID < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!is_string($commandType)){
|
||||
if (!is_string($commandType)) {
|
||||
return false;
|
||||
}
|
||||
if(!in_array($commandType, GameConst::$availableChiefCommand['전략'])){
|
||||
if (!in_array($commandType, GameConst::$availableChiefCommand['전략'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$this->arg = [
|
||||
'destNationID'=>$destNationID,
|
||||
'commandType'=>$commandType
|
||||
'destNationID' => $destNationID,
|
||||
'commandType' => $commandType
|
||||
];
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function init(){
|
||||
protected function init()
|
||||
{
|
||||
$general = $this->generalObj;
|
||||
|
||||
$env = $this->env;
|
||||
@@ -69,7 +77,7 @@ class che_피장파장 extends Command\NationCommand{
|
||||
$this->setCity();
|
||||
$this->setNation();
|
||||
|
||||
$this->minConditionConstraints=[
|
||||
$this->minConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
];
|
||||
@@ -79,8 +87,8 @@ class che_피장파장 extends Command\NationCommand{
|
||||
{
|
||||
$this->setDestNation($this->arg['destNationID'], null);
|
||||
|
||||
if($this->getNationID() == 0){
|
||||
$this->fullConditionConstraints=[
|
||||
if ($this->getNationID() == 0) {
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity()
|
||||
];
|
||||
return;
|
||||
@@ -90,14 +98,14 @@ class che_피장파장 extends Command\NationCommand{
|
||||
|
||||
$currYearMonth = Util::joinYearMonth($this->env['year'], $this->env['month']);
|
||||
$nextAvailableTurn = $cmd->getNextAvailableTurn();
|
||||
if($currYearMonth < $nextAvailableTurn){
|
||||
$this->fullConditionConstraints=[
|
||||
if ($currYearMonth < $nextAvailableTurn) {
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::AlwaysFail('해당 전략을 아직 사용할 수 없습니다')
|
||||
];
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::OccupiedCity(),
|
||||
ConstraintHelper::BeChief(),
|
||||
ConstraintHelper::ExistsDestNation(),
|
||||
@@ -108,35 +116,41 @@ class che_피장파장 extends Command\NationCommand{
|
||||
];
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
$name = $this->getName();
|
||||
$reqTurn = $this->getPreReqTurn()+1;
|
||||
$reqTurn = $this->getPreReqTurn() + 1;
|
||||
|
||||
return "{$name}/{$reqTurn}턴(대상 재사용 대기 {$this->getTargetPostReqTurn()})";
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getTargetPostReqTurn():int{
|
||||
public function getTargetPostReqTurn(): int
|
||||
{
|
||||
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
|
||||
$nextTerm = Util::round(sqrt($genCount*2)*10);
|
||||
$nextTerm = Util::round(sqrt($genCount * 2) * 10);
|
||||
|
||||
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
|
||||
$nextTerm = Util::valueFit($nextTerm, Util::round(static::$delayCnt * 1.2));
|
||||
return $nextTerm;
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
public function getBrief(): string
|
||||
{
|
||||
$commandName = $this->getName();
|
||||
$cmd = buildNationCommandClass($this->arg['commandType'], $this->generalObj, $this->env, new LastTurn());
|
||||
$targetCommandName = $cmd->getName();
|
||||
@@ -145,8 +159,9 @@ class che_피장파장 extends Command\NationCommand{
|
||||
}
|
||||
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
@@ -187,7 +202,7 @@ class che_피장파장 extends Command\NationCommand{
|
||||
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <G><b>{$destNationName}</b></>에 <G><b>{$cmd->getName()}</b></> 전략의 <M>{$commandName}</>{$josaUl} 발동하였습니다.";
|
||||
|
||||
$nationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
|
||||
foreach($nationGeneralList as $nationGeneralID){
|
||||
foreach ($nationGeneralList as $nationGeneralID) {
|
||||
$nationGeneralLogger = new ActionLogger($nationGeneralID, $nationID, $year, $month);
|
||||
$nationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$nationGeneralLogger->flush();
|
||||
@@ -198,7 +213,7 @@ class che_피장파장 extends Command\NationCommand{
|
||||
$broadcastMessage = "아국에 <G><b>{$cmd->getName()}</b></> 전략의 <M>{$commandName}</>{$josaYiCommand} 발동되었습니다.";
|
||||
|
||||
$destNationGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $destNationID, $generalID);
|
||||
foreach($destNationGeneralList as $destNationGeneralID){
|
||||
foreach ($destNationGeneralList as $destNationGeneralID) {
|
||||
$destNationGeneralLogger = new ActionLogger($destNationGeneralID, $destNationID, $year, $month);
|
||||
$destNationGeneralLogger->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
|
||||
$destNationGeneralLogger->flush();
|
||||
@@ -222,79 +237,55 @@ class che_피장파장 extends Command\NationCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectNationByMap'
|
||||
];
|
||||
}
|
||||
|
||||
public function getForm(): string
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
$generalObj = $this->generalObj;
|
||||
$nationID = $generalObj->getNationID();
|
||||
$nationList = [];
|
||||
$testTurn = new LastTurn($this->getName(), null, $this->getPreReqTurn());
|
||||
foreach(getAllNationStaticInfo() as $destNation){
|
||||
if($destNation['nation'] == $nationID){
|
||||
continue;
|
||||
foreach (getAllNationStaticInfo() as $destNation) {
|
||||
$testCommand = new static($generalObj, $this->env, $testTurn, ['destNationID' => $destNation['nation']]);
|
||||
|
||||
$nationTarget = [
|
||||
'id' => $destNation['nation'],
|
||||
'name' => $destNation['name'],
|
||||
'color' => $destNation['color'],
|
||||
'power' => $destNation['power'],
|
||||
];
|
||||
if (!$testCommand->hasFullConditionMet()) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
if ($destNation['id'] == $nationID) {
|
||||
$nationTarget['notAvailable'] = true;
|
||||
}
|
||||
|
||||
$testTurn->setArg(['destNationID'=>$destNation['nation']]);
|
||||
$testCommand = new static($generalObj, $this->env, $testTurn, ['destNationID'=>$destNation['nation']]);
|
||||
if($testCommand->hasFullConditionMet()){
|
||||
$destNation['availableCommand'] = true;
|
||||
}
|
||||
else{
|
||||
$destNation['availableCommand'] = false;
|
||||
}
|
||||
|
||||
$nationList[] = $destNation;
|
||||
$nationList[] = $nationTarget;
|
||||
}
|
||||
|
||||
|
||||
$availableCommandTypeList = [];
|
||||
$currYearMonth = Util::joinYearMonth($this->env['year'], $this->env['month']);
|
||||
foreach(GameConst::$availableChiefCommand['전략'] as $commandType){
|
||||
foreach (GameConst::$availableChiefCommand['전략'] as $commandType) {
|
||||
$cmd = buildNationCommandClass($commandType, $generalObj, $this->env, new LastTurn());
|
||||
$cmdName = $cmd->getName();
|
||||
$remainTurn = 0;
|
||||
$nextAvailableTurn = $cmd->getNextAvailableTurn();
|
||||
|
||||
if($nextAvailableTurn !== null && $currYearMonth < $nextAvailableTurn){
|
||||
if ($nextAvailableTurn !== null && $currYearMonth < $nextAvailableTurn) {
|
||||
$remainTurn = $nextAvailableTurn - $currYearMonth;
|
||||
}
|
||||
$availableCommandTypeList[$commandType] = [$cmdName, $remainTurn];
|
||||
$availableCommandTypeList[$commandType] = ['name' => $cmdName, 'remainTurn' => $remainTurn];
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<?=\sammo\getMapHtml()?><br>
|
||||
선택된 국가에 피장파장을 발동합니다.<br>
|
||||
지정한 전략을 상대국이 <?=static::$delayCnt?>턴 동안 사용할 수 없게됩니다.<br>
|
||||
대신 아국은 지정한 전략을<?=$this->getTargetPostReqTurn()?>턴 동안 사용할 수 없습니다.<br>
|
||||
선포, 전쟁중인 상대국에만 가능합니다.<br>
|
||||
상대 국가를 목록에서 선택하세요.<br>
|
||||
배경색은 현재 피장파장 불가능 국가는 <font color=red>붉은색</font>으로 표시됩니다.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach($nationList as $nation): ?>
|
||||
<option
|
||||
value='<?=$nation['nation']?>'
|
||||
style='color:<?=$nation['color']?>;<?=$nation['availableCommand']?'':'background-color:red;'?>'
|
||||
>【<?=$nation['name']?> 】</option>
|
||||
<?php endforeach; ?>
|
||||
</select>에
|
||||
<select class='formInput' name="commandType" id="commandType" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach($availableCommandTypeList as $commandType=>[$cmdName, $cmdRemainTurn]):
|
||||
/** @var \sammo\Command\NationCommand $cmdObj */
|
||||
?>
|
||||
<option
|
||||
value='<?=$commandType?>'
|
||||
style='color:white;<?=$cmdRemainTurn?'background-color:red;':''?>'
|
||||
><?=$cmdName?><?=$cmdRemainTurn?"({$cmdRemainTurn}턴 뒤)":''?></option>
|
||||
<?php endforeach; ?>
|
||||
</select> 전략을
|
||||
<input type=button id="commonSubmit" value="<?=$this->getName()?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
return [
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'nationList' => $nationList,
|
||||
'startYear' => $this->env['startyear'],
|
||||
'delayCnt' => static::$delayCnt,
|
||||
'postReqTurn' => $this->getTargetPostReqTurn(),
|
||||
'availableCommandTypeList' => $availableCommandTypeList
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,27 +199,14 @@ class che_허보 extends Command\NationCommand
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getJSPlugins(): array
|
||||
public function exportJSVars(): array
|
||||
{
|
||||
return [
|
||||
'defaultSelectCityByMap'
|
||||
'mapTheme' => \sammo\getMapTheme(),
|
||||
'procRes' => [
|
||||
'cities' => \sammo\JSOptionsForCities(),
|
||||
'distanceList' => new \stdClass(),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getForm(): string
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<?= \sammo\getMapHtml() ?><br>
|
||||
선택된 도시에 허보를 발동합니다.<br>
|
||||
전쟁중인 상대국 도시만 가능합니다.<br>
|
||||
목록을 선택하거나 도시를 클릭하세요.<br>
|
||||
<select class='formInput' name="destCityID" id="destCityID" size='1' style='color:white;background-color:black;'>
|
||||
<?= \sammo\optionsForCities() ?><br>
|
||||
</select> <input type=button id="commonSubmit" value="<?= $this->getName() ?>"><br>
|
||||
<br>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class GameUnitConstBase{
|
||||
0, null, null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
|
||||
['표준적인 보병입니다.','보병은 방어특화이며, 상대가 회피하기 어렵습니다.'],
|
||||
['표준적인 보병입니다.','보병은 방어특화이며,','상대가 회피하기 어렵습니다.'],
|
||||
null, ['che_방어력증가5p']
|
||||
],
|
||||
[
|
||||
|
||||
+23
-23
@@ -8,8 +8,8 @@ class GameUnitConst extends GameUnitConstBase
|
||||
protected static $_buildData = [
|
||||
[
|
||||
1000, self::T_CASTLE, '성벽',
|
||||
100, 100, 7, 0, 0, 99, 9,
|
||||
999999, null, null, 999999,
|
||||
100, 100, 7, 0, 0, 99, 9,
|
||||
999999, null, null, 999999,
|
||||
[],//성벽은 공격할 수 없다.
|
||||
[self::T_FOOTMAN=>1.2],
|
||||
['성벽입니다.','생성할 수 없습니다.'],
|
||||
@@ -18,18 +18,18 @@ class GameUnitConst extends GameUnitConstBase
|
||||
|
||||
[
|
||||
1100, self::T_FOOTMAN, '보병',
|
||||
100, 150, 7, 10, 0, 9, 9,
|
||||
0, null, null, 0,
|
||||
100, 150, 7, 10, 0, 9, 9,
|
||||
0, null, null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
|
||||
['표준적인 보병입니다.','보병은 방어특화이며, 상대가 회피하기 어렵습니다.'],
|
||||
['표준적인 보병입니다.','보병은 방어특화이며,','상대가 회피하기 어렵습니다.'],
|
||||
null, null
|
||||
],
|
||||
|
||||
[
|
||||
1200, self::T_ARCHER, '궁병',
|
||||
100, 100, 7, 20, 0, 10, 10,
|
||||
0, null, null, 0,
|
||||
1200, self::T_ARCHER, '궁병',
|
||||
100, 100, 7, 20, 0, 10, 10,
|
||||
0, null, null, 0,
|
||||
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
|
||||
['표준적인 궁병입니다.','궁병은 회피특화입니다.'],
|
||||
@@ -37,9 +37,9 @@ class GameUnitConst extends GameUnitConstBase
|
||||
],
|
||||
|
||||
[
|
||||
1300, self::T_CAVALRY, '기병',
|
||||
150, 100, 7, 5, 0, 11, 11,
|
||||
0, null, null, 0,
|
||||
1300, self::T_CAVALRY, '기병',
|
||||
150, 100, 7, 5, 0, 11, 11,
|
||||
0, null, null, 0,
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
|
||||
['표준적인 기병입니다.','기병은 공격특화입니다.'],
|
||||
@@ -47,18 +47,18 @@ class GameUnitConst extends GameUnitConstBase
|
||||
],
|
||||
|
||||
[
|
||||
1400, self::T_WIZARD, '귀병',
|
||||
80, 80, 7, 5, 0.5, 9, 9,
|
||||
0, null, null, 0,
|
||||
1400, self::T_WIZARD, '귀병',
|
||||
80, 80, 7, 5, 0.5, 9, 9,
|
||||
0, null, null, 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
['계략을 사용하는 병종입니다.'],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
1405, self::T_WIZARD, '남귀병',
|
||||
60, 60, 7, 10, 0.8, 8, 8,
|
||||
1000, null, null, 0,
|
||||
1405, self::T_WIZARD, '남귀병',
|
||||
60, 60, 7, 10, 0.8, 8, 8,
|
||||
1000, null, null, 0,
|
||||
[self::T_SIEGE=>1.2],
|
||||
[self::T_SIEGE=>0.8],
|
||||
['전투를 포기하고 계략에 몰두합니다.'],
|
||||
@@ -66,18 +66,18 @@ class GameUnitConst extends GameUnitConstBase
|
||||
],
|
||||
|
||||
[
|
||||
1500, self::T_SIEGE, '정란',
|
||||
100, 100, 6, 0, 0, 15, 5,
|
||||
0, null, null, 3,
|
||||
1500, self::T_SIEGE, '정란',
|
||||
100, 100, 6, 0, 0, 15, 5,
|
||||
0, null, null, 3,
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>1.8],
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
|
||||
['높은 구조물 위에서 공격합니다.'],
|
||||
['che_성벽부상무효'], null
|
||||
],
|
||||
[
|
||||
1501, self::T_SIEGE, '충차',
|
||||
150, 100, 6, 0, 0, 20, 5,
|
||||
1000, null, null, 3,
|
||||
1501, self::T_SIEGE, '충차',
|
||||
150, 100, 6, 0, 0, 20, 5,
|
||||
1000, null, null, 3,
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>2.4],
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
|
||||
['엄청난 위력으로 성벽을 부수어버립니다.'],
|
||||
|
||||
@@ -8,8 +8,8 @@ class GameUnitConst extends GameUnitConstBase
|
||||
protected static $_buildData = [
|
||||
[
|
||||
1000, self::T_CASTLE, '성벽',
|
||||
100, 100, 7, 0, 0, 99, 9,
|
||||
999999, null, null, 999999,
|
||||
100, 100, 7, 0, 0, 99, 9,
|
||||
999999, null, null, 999999,
|
||||
[],//성벽은 공격할 수 없다.
|
||||
[self::T_FOOTMAN=>1.2],
|
||||
['성벽입니다.','생성할 수 없습니다.'],
|
||||
@@ -17,18 +17,18 @@ class GameUnitConst extends GameUnitConstBase
|
||||
],
|
||||
[
|
||||
1100, self::T_FOOTMAN, '보병',
|
||||
100, 150, 7, 10, 0, 18, 18,
|
||||
0, null, null, 0,
|
||||
100, 150, 7, 10, 0, 18, 18,
|
||||
0, null, null, 0,
|
||||
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8],
|
||||
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2],
|
||||
['표준적인 보병입니다.','보병은 방어특화이며, 상대가 회피하기 어렵습니다.'],
|
||||
['표준적인 보병입니다.','보병은 방어특화이며,','상대가 회피하기 어렵습니다.'],
|
||||
null, null
|
||||
],
|
||||
|
||||
[
|
||||
1200, self::T_ARCHER, '궁병',
|
||||
100, 100, 7, 20, 0, 20, 20,
|
||||
0, null, null, 0,
|
||||
1200, self::T_ARCHER, '궁병',
|
||||
100, 100, 7, 20, 0, 20, 20,
|
||||
0, null, null, 0,
|
||||
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8],
|
||||
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2],
|
||||
['표준적인 궁병입니다.','궁병은 회피특화입니다.'],
|
||||
@@ -36,9 +36,9 @@ class GameUnitConst extends GameUnitConstBase
|
||||
],
|
||||
|
||||
[
|
||||
1300, self::T_CAVALRY, '기병',
|
||||
150, 100, 7, 5, 0, 22, 22,
|
||||
0, null, null, 0,
|
||||
1300, self::T_CAVALRY, '기병',
|
||||
150, 100, 7, 5, 0, 22, 22,
|
||||
0, null, null, 0,
|
||||
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8],
|
||||
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2],
|
||||
['표준적인 기병입니다.','기병은 공격특화입니다.'],
|
||||
@@ -46,18 +46,18 @@ class GameUnitConst extends GameUnitConstBase
|
||||
],
|
||||
|
||||
[
|
||||
1400, self::T_WIZARD, '귀병',
|
||||
80, 80, 7, 5, 0.5, 18, 18,
|
||||
0, null, null, 0,
|
||||
1400, self::T_WIZARD, '귀병',
|
||||
80, 80, 7, 5, 0.5, 18, 18,
|
||||
0, null, null, 0,
|
||||
[],
|
||||
[],
|
||||
['계략을 사용하는 병종입니다.'],
|
||||
null, null
|
||||
],
|
||||
[
|
||||
1405, self::T_WIZARD, '남귀병',
|
||||
60, 60, 7, 10, 0.8, 16, 16,
|
||||
1000, null, null, 0,
|
||||
1405, self::T_WIZARD, '남귀병',
|
||||
60, 60, 7, 10, 0.8, 16, 16,
|
||||
1000, null, null, 0,
|
||||
[],
|
||||
[],
|
||||
['전투를 포기하고 계략에 몰두합니다.'],
|
||||
@@ -65,36 +65,36 @@ class GameUnitConst extends GameUnitConstBase
|
||||
],
|
||||
|
||||
[
|
||||
1500, self::T_SIEGE, '정란',
|
||||
100, 100, 6, 0, 0, 7, 3,
|
||||
0, null, null, 0,
|
||||
1500, self::T_SIEGE, '정란',
|
||||
100, 100, 6, 0, 0, 7, 3,
|
||||
0, null, null, 0,
|
||||
[self::T_CASTLE=>1.8],
|
||||
[],
|
||||
['높은 구조물 위에서 공격합니다.'],
|
||||
['che_성벽부상무효'], null
|
||||
],
|
||||
[
|
||||
1501, self::T_SIEGE, '충차',
|
||||
150, 100, 6, 0, 0, 10, 3,
|
||||
1000, null, null, 3,
|
||||
1501, self::T_SIEGE, '충차',
|
||||
150, 100, 6, 0, 0, 10, 3,
|
||||
1000, null, null, 3,
|
||||
[self::T_CASTLE=>2.4],
|
||||
[],
|
||||
['엄청난 위력으로 성벽을 부수어버립니다.'],
|
||||
['che_성벽부상무효'], null
|
||||
],
|
||||
[
|
||||
1502, self::T_SIEGE, '벽력거',
|
||||
200, 100, 6, 0, 0, 20, 4,
|
||||
3000, ['업'], null, 0,
|
||||
1502, self::T_SIEGE, '벽력거',
|
||||
200, 100, 6, 0, 0, 20, 4,
|
||||
3000, ['업'], null, 0,
|
||||
[self::T_CASTLE=>1.8],
|
||||
[],
|
||||
['상대에게 돌덩이를 날립니다.'],
|
||||
['che_성벽부상무효'], null
|
||||
],
|
||||
[
|
||||
1503, self::T_SIEGE, '목우',
|
||||
50, 200, 5, 0, 0, 15, 3,
|
||||
3000, ['성도'], null, 0,
|
||||
1503, self::T_SIEGE, '목우',
|
||||
50, 200, 5, 0, 0, 15, 3,
|
||||
3000, ['성도'], null, 0,
|
||||
[],
|
||||
[],
|
||||
['상대를 저지하는 특수병기입니다.'],
|
||||
|
||||
Vendored
+1
@@ -7,6 +7,7 @@ $input-color: #303030;
|
||||
|
||||
@import url("https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css");
|
||||
|
||||
@import "./break_500px.scss";
|
||||
@import "./variables.scss";
|
||||
@import "./bootswatch_custom_variables.scss";
|
||||
@import "bootstrap/scss/bootstrap.scss";
|
||||
|
||||
@@ -12,4 +12,16 @@ $grid-breakpoints: (
|
||||
lg: 992px,
|
||||
xl: 1200px,
|
||||
xxl: 1400px
|
||||
);
|
||||
);
|
||||
|
||||
@mixin media-1000px{
|
||||
@media (min-width: map-get($grid-breakpoints, 'md')) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin media-500px{
|
||||
@media (max-width: calc(map-get($grid-breakpoints, 'md') - .02px)) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@ table.tb_layout {
|
||||
html,
|
||||
body {
|
||||
font-size: 14px;
|
||||
background-position: center;
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
|
||||
.tb_layout td,
|
||||
|
||||
+12
-24
@@ -1,6 +1,6 @@
|
||||
@import "./common/break_500px.scss";
|
||||
@import "./common/bootstrap5.scss";
|
||||
@import "./editor_component.scss";
|
||||
@import "./util.scss";
|
||||
body {
|
||||
color: white;
|
||||
background-color: black;
|
||||
@@ -10,14 +10,14 @@ body {
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
@include media-1000px {
|
||||
#container {
|
||||
width: 1000px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
@include media-500px {
|
||||
body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
@@ -52,6 +52,8 @@ body {
|
||||
}
|
||||
|
||||
box-shadow: 0 -1px 0 $dark;
|
||||
border-left: none !important;
|
||||
border-right: none !important;
|
||||
|
||||
.toolbarButton2 {
|
||||
text-decoration: underline;
|
||||
@@ -118,7 +120,7 @@ body {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
@include media-1000px {
|
||||
#map_view {
|
||||
grid-template-columns: 500px 200px 300px;
|
||||
grid-template-rows: 520px 130px;
|
||||
@@ -218,7 +220,7 @@ body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
@include media-500px {
|
||||
.buttonPlate {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
@@ -394,7 +396,7 @@ body {
|
||||
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
@include media-1000px {
|
||||
#message_board section {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
@@ -410,7 +412,7 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
@include media-500px {
|
||||
|
||||
#message_board .message_input_form {
|
||||
position: -webkit-sticky;
|
||||
@@ -535,7 +537,7 @@ body {
|
||||
}
|
||||
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
@include media-500px {
|
||||
#mailbox_list-col {
|
||||
order: 1;
|
||||
}
|
||||
@@ -586,13 +588,13 @@ body {
|
||||
}
|
||||
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
@include media-1000px {
|
||||
#float-tabs {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
@include media-500px {
|
||||
#float-tabs {
|
||||
position: fixed;
|
||||
right: -1rem;
|
||||
@@ -627,17 +629,3 @@ body {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.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;
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
|
||||
@import "./common/break_500px.scss";
|
||||
@import "./common/bootstrap5.scss";
|
||||
@import "./common_legacy.scss";
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
@include media-1000px{
|
||||
#container {
|
||||
width: 1000px;
|
||||
margin: 0 auto;
|
||||
@@ -17,10 +15,7 @@
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
@include media-500px{
|
||||
body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
@import "./common/bootstrap5.scss";
|
||||
@import "./editor_component.scss";
|
||||
@import "./common_legacy.scss";
|
||||
@import "./util.scss";
|
||||
|
||||
#amount {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
#colorType {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.no-padding .select2-results__option {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
@include media-1000px{
|
||||
#container {
|
||||
width: 1000px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-500px{
|
||||
body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#container {
|
||||
width: 500px;
|
||||
margin: 0 auto;
|
||||
|
||||
.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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
.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;
|
||||
}
|
||||
@@ -39,8 +39,6 @@ if ($permission < 1) {
|
||||
<meta name="viewport" content="width=1024" />
|
||||
<?= WebUtil::printCSS('../e_lib/select2/select2.min.css') ?>
|
||||
<?= WebUtil::printCSS('../e_lib/select2/select2-bootstrap4.css') ?>
|
||||
<!--<?= WebUtil::printCSS('../e_lib/tui.editor/tui-editor.min.css') ?>-->
|
||||
<!--<?= WebUtil::printCSS('../e_lib/tui.editor/tui-editor-contents.min.css') ?>-->
|
||||
<?= WebUtil::printCSS('../d_shared/common.css') ?>
|
||||
<?= WebUtil::printCSS('../css/config.css') ?>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
|
||||
|
||||
-326
@@ -1,326 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
// Type definitions for Summernote 0.8
|
||||
// Project: https://github.com/summernote/summernote#readme
|
||||
// Definitions by: Wouter Staelens <https://github.com/wstaelens>
|
||||
// Denny Harijanto <https://github.com/nusantara-cloud>
|
||||
// Corbin Crutchley <https://github.com/crutchcorn>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// TypeScript Version: 2.7
|
||||
|
||||
/// <reference types="jquery"/>
|
||||
|
||||
declare global {
|
||||
namespace Summernote {
|
||||
type fontSizeUnitOptions = 'px' | 'pt';
|
||||
|
||||
interface Options {
|
||||
airMode?: boolean | undefined;
|
||||
tabDisable?: boolean | undefined;
|
||||
codeviewFilter?: boolean | undefined;
|
||||
codeviewFilterRegex?: string | undefined;
|
||||
codeviewIframeWhitelistSrc?: string[] | undefined;
|
||||
codeviewIframeFilter?: boolean | undefined;
|
||||
callbacks?: SummernoteCallbacks | SummernoteUndocumentedCallbacks | undefined; // todo
|
||||
codemirror?: CodemirrorOptions | undefined;
|
||||
colors?: colorsDef | undefined;
|
||||
dialogsInBody?: boolean | undefined;
|
||||
dialogsFade?: boolean | undefined;
|
||||
direction?: string | undefined;
|
||||
disableDragAndDrop?: boolean | undefined;
|
||||
focus?: boolean | undefined;
|
||||
fontNames?: string[] | undefined;
|
||||
fontNamesIgnoreCheck?: string[] | undefined;
|
||||
fontSizes?: string[] | undefined;
|
||||
fontSizeUnits?: fontSizeUnitOptions[] | undefined;
|
||||
height?: number | undefined;
|
||||
hint?: HintOptions | undefined;
|
||||
icons?: IconsOptions | undefined;
|
||||
insertTableMaxSize?: InsertTableMaxSizeOptions | undefined;
|
||||
keyMap?: KeyMapOptions | undefined;
|
||||
lang?: string | undefined;
|
||||
lineHeights?: string[] | undefined;
|
||||
minHeight?: number | undefined;
|
||||
maxHeight?: number | undefined;
|
||||
maximumImageFileSize?: any;
|
||||
modules?: ModuleOptions | undefined;
|
||||
popover?: PopoverOptions | undefined;
|
||||
placeholder?: string | undefined;
|
||||
shortcuts?: boolean | undefined;
|
||||
styleTags?: styleTagsOptions[] | undefined;
|
||||
styleWithSpan?: boolean | undefined;
|
||||
tabsize?: number | undefined;
|
||||
tableClassName?: string | undefined;
|
||||
textareaAutoSync?: boolean | undefined;
|
||||
toolbar?: toolbarDef | undefined;
|
||||
width?: number | undefined;
|
||||
}
|
||||
|
||||
type toolbarStyleGroupOptions = 'style' | 'bold' | 'italic' | 'underline' | 'clear';
|
||||
type toolbarFontGroupOptions = 'fontname' | 'fontsize' | 'fontsizeunit' | 'color' | 'forecolor' | 'backcolor' | 'bold' | 'italic' | 'underline' | 'strikethrough' | 'superscript' |
|
||||
'subscript' | 'clear';
|
||||
type toolbarFontsizeGroupOptions = 'fontsize' | 'fontname' | 'color';
|
||||
type toolbarColorGroupOptions = 'color';
|
||||
type toolbarParaGroupOptions = 'ul' | 'ol' | 'paragraph' | 'style' | 'height';
|
||||
type toolbarHeightGroupOptions = 'height';
|
||||
type toolbarTableGroupOptions = 'table';
|
||||
type toolbarInsertGroupOptions = 'link' | 'picture' | 'hr' | 'table' | 'video';
|
||||
type toolbarViewGroupOptions = 'fullscreen' | 'codeview' | 'help';
|
||||
type toolbarHelpGroupOptions = 'help';
|
||||
type miscGroupOptions = 'fullscreen' | 'codeview' | 'undo' | 'redo' | 'help';
|
||||
// type toolbarDef = [string, string[]][]
|
||||
type toolbarDef = Array<
|
||||
['style', toolbarStyleGroupOptions[]]
|
||||
| ['font', toolbarFontGroupOptions[]]
|
||||
| ['fontname', toolbarFontNameOptions[]]
|
||||
| ['fontsize', toolbarFontsizeGroupOptions[]]
|
||||
| ['color', toolbarColorGroupOptions[]]
|
||||
| ['para', toolbarParaGroupOptions[]]
|
||||
| ['height', toolbarHeightGroupOptions[]]
|
||||
| ['table', toolbarTableGroupOptions[]]
|
||||
| ['insert', toolbarInsertGroupOptions[]]
|
||||
| ['view', toolbarViewGroupOptions[]]
|
||||
| ['help', toolbarHelpGroupOptions[]]
|
||||
| ['misc', miscGroupOptions[]]
|
||||
>;
|
||||
|
||||
type colorsDef = Array<[string[]]>;
|
||||
type styleTagsOptions = 'p' | 'blockquote' | 'pre' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
||||
|
||||
interface InsertTableMaxSizeOptions {
|
||||
col: number;
|
||||
row: number;
|
||||
}
|
||||
|
||||
interface IconsOptions {
|
||||
options?: any; // todo
|
||||
}
|
||||
|
||||
interface KeyMapOptions {
|
||||
pc?: KeyMapPcOptions | undefined;
|
||||
mac?: KeyMapMacOptions | undefined;
|
||||
}
|
||||
|
||||
interface KeyMapPcOptions {
|
||||
options?: any; // todo
|
||||
}
|
||||
|
||||
interface KeyMapMacOptions {
|
||||
options?: any; // todo
|
||||
}
|
||||
|
||||
type htmlElement = string;
|
||||
|
||||
interface HintOptions {
|
||||
words?: string[] | undefined;
|
||||
mentions?: string[] | undefined;
|
||||
match: RegExp;
|
||||
search: (keyword: string, callback: (plausibleItems: string[]) => void) => void;
|
||||
template?: ((item: string) => htmlElement) | undefined;
|
||||
content?: ((item: string) => htmlElement | JQuery.Node) | undefined;
|
||||
}
|
||||
|
||||
interface CodemirrorOptions {
|
||||
mode?: string | undefined;
|
||||
htmlNode?: boolean | undefined;
|
||||
lineNumbers?: boolean | undefined;
|
||||
theme?: string | undefined;
|
||||
}
|
||||
|
||||
type popoverImageOptionsImagesize = 'imageSize100' | 'imageSize50' | 'imageSize25';
|
||||
type popoverImageOptionsFloat = 'floatLeft' | 'floatRight' | 'floatNone';
|
||||
type popoverImageOptionsRemove = 'removeMedia';
|
||||
type popoverImageDef = [
|
||||
['imagesize', popoverImageOptionsImagesize[]],
|
||||
['float', popoverImageOptionsFloat[]],
|
||||
['remove', popoverImageOptionsRemove[]],
|
||||
['custom', string[]]?,//NOTE: 이 부분이 바뀜(Hide_D)
|
||||
];
|
||||
|
||||
type popoverLinkLinkOptions = 'linkDialogShow' | 'unlink';
|
||||
type popoverLinkDef = [
|
||||
['link', popoverLinkLinkOptions[]]
|
||||
];
|
||||
|
||||
type popoverAirOptionsColor = 'color';
|
||||
type popoverAirOptionsFont = 'bold' | 'underline' | 'clear';
|
||||
type popoverAirOptionsPara = 'ul' | 'paragraph';
|
||||
type popoverAirOptionsTable = 'table';
|
||||
type popoverAirOptionsInsert = 'link' | 'picture';
|
||||
type popoverAirDef = [
|
||||
['color', popoverAirOptionsColor],
|
||||
['font', popoverAirOptionsFont],
|
||||
['para', popoverAirOptionsPara],
|
||||
['table', popoverAirOptionsTable],
|
||||
['insert', popoverAirOptionsInsert]
|
||||
];
|
||||
|
||||
interface PopoverOptions {
|
||||
image?: popoverImageDef | undefined;
|
||||
link?: popoverLinkDef | undefined;
|
||||
air?: popoverAirDef | undefined;
|
||||
}
|
||||
|
||||
interface ModuleOptions {
|
||||
options?: any; // todo
|
||||
}
|
||||
|
||||
interface CreateLinkOptions {
|
||||
text: string;
|
||||
url: string;
|
||||
newWindow: boolean;
|
||||
}
|
||||
|
||||
type EditImageCallback = ($image: JQuery.Node) => void;
|
||||
|
||||
type toolbarFontNameOptions = string;
|
||||
|
||||
interface SummernoteCallbacks {
|
||||
onBeforeCommand?: (contents: string) => void;
|
||||
onChange?: (contents: string, $editable: JQuery) => void;
|
||||
onChangeCodeview?: (code: string, $editor: JQuery) => void;
|
||||
onDialogShown?: () => void;
|
||||
onEnter?: (ev: Event) => void;
|
||||
onFocus?: (ev: Event) => void;
|
||||
onBlur?: (ev: Event) => void;
|
||||
onBlurCodeview?: (code: string, ev: Event) => void;
|
||||
onImageLinkInsert?: (url: string) => void;
|
||||
onImageUpload?: (files: Blob[]) => void;
|
||||
onImageUploadError?: (err: any) => void;
|
||||
onInit?: () => void;
|
||||
onKeyup?: (ev: KeyboardEvent) => void;
|
||||
onKeydown?: (ev: KeyboardEvent) => void;
|
||||
onMouseDown?: (ev: MouseEvent) => void;
|
||||
onMouseUp?: (ev: MouseEvent) => void;
|
||||
onPaste?: (e: Event) => void;
|
||||
onScroll?: (e: Event) => void;
|
||||
}
|
||||
|
||||
type SummernoteUndocumentedCallbacks = {
|
||||
[key in Exclude<keyof SummernoteCallbacks, string>]: (...args: any[]) => void;
|
||||
};
|
||||
|
||||
interface Plugin{
|
||||
showLinkDialog(...args:any[]);
|
||||
show: () => void;
|
||||
bindEnterKey: ($input: JQuery<HTMLElement>, $btn: JQuery<HTMLElement>) => void;
|
||||
destroy: () => void;
|
||||
$dialog: JQuery<HTMLElement>;
|
||||
initialize: () => void;
|
||||
}
|
||||
|
||||
interface Context {
|
||||
//src/js/base/Context.js
|
||||
triggerEvent(namespace: string, ...args:any[]);
|
||||
options: any;
|
||||
invoke(arg0: string);
|
||||
memo(arg0: string, arg1: () => any);
|
||||
layoutInfo: {
|
||||
note: JQuery<HTMLElement>,
|
||||
editor: JQuery<HTMLElement>,
|
||||
editable: JQuery<HTMLElement>,
|
||||
toolbar: JQuery<HTMLElement>,
|
||||
}
|
||||
}
|
||||
|
||||
interface UI{
|
||||
showDialog($dialog: JQuery<HTMLElement>);
|
||||
onDialogHidden($dialog: JQuery<HTMLElement>, arg1: () => void);
|
||||
onDialogShown($dialog: JQuery<HTMLElement>, arg1: () => void);
|
||||
hideDialog($dialog: JQuery<HTMLElement>);
|
||||
dialog(arg0: { title: any; body: string; footer: string; });
|
||||
button: (...args:any[])=>any,
|
||||
icon: (...args:any[])=>any,
|
||||
}
|
||||
}
|
||||
|
||||
interface JQueryStatic{
|
||||
summernote: {
|
||||
lang: Record<string, Record<string, any>>,
|
||||
options: Record<string, any>,
|
||||
plugins: Record<string, any>,
|
||||
ui: Summernote.UI,
|
||||
};
|
||||
}
|
||||
|
||||
interface JQuery {
|
||||
summernote(): JQuery;
|
||||
summernote(command: string): JQuery;
|
||||
summernote(options?: Summernote.Options): JQuery;
|
||||
summernote(command: string, markupString: string): JQuery;
|
||||
summernote(command: string, value: number): JQuery;
|
||||
summernote(command: string, node: JQuery.Node): JQuery;
|
||||
summernote(command: string, url: string, filename?: (string | Summernote.EditImageCallback)): JQuery;
|
||||
|
||||
summernote(command: 'destroy'): JQuery;
|
||||
summernote(command: 'code'): string;
|
||||
summernote(command: 'code', markupStr: string): undefined;
|
||||
summernote(command: 'editor.pasteHTML' | 'pasteHTML', markup: string): JQuery;
|
||||
|
||||
// Basic API
|
||||
summernote(command: 'editor.createRange' | 'createRange'): JQuery;
|
||||
summernote(command: 'editor.saveRange' | 'saveRange'): JQuery;
|
||||
summernote(command: 'editor.restoreRange' | 'restoreRange'): JQuery;
|
||||
summernote(command: 'editor.undo' | 'undo'): JQuery;
|
||||
summernote(command: 'editor.redo' | 'redo'): JQuery;
|
||||
summernote(command: 'editor.focus' | 'focus'): JQuery;
|
||||
summernote(command: 'editor.isEmpty' | 'isEmpty'): boolean;
|
||||
summernote(command: 'reset'): JQuery;
|
||||
summernote(command: 'disable'): JQuery;
|
||||
summernote(command: 'enable'): JQuery;
|
||||
// Font style API
|
||||
summernote(fontStyle: 'editor.bold' | 'bold'): JQuery;
|
||||
summernote(fontStyle: 'editor.italic' | 'italic'): JQuery;
|
||||
summernote(fontStyle: 'editor.underline' | 'underline'): JQuery;
|
||||
summernote(fontStyle: 'editor.strikethrough' | 'strikethrough'): JQuery;
|
||||
summernote(command: 'editor.superscript' | 'superscript'): JQuery;
|
||||
summernote(command: 'editor.subscript' | 'subscript'): JQuery;
|
||||
summernote(command: 'editor.removeFormat' | 'removeFormat'): JQuery;
|
||||
summernote(command: 'backColor', color: string): JQuery;
|
||||
summernote(command: 'foreColor', color: string): JQuery;
|
||||
summernote(command: 'fontName', fontName: string): JQuery;
|
||||
summernote(command: 'editor.fontSize' | 'fontSize', fontSize: number): JQuery;
|
||||
// Paragraph API
|
||||
summernote(command: 'editor.justifyLeft' | 'justifyLeft'): JQuery;
|
||||
summernote(command: 'editor.justifyRight' | 'justifyRight'): JQuery;
|
||||
summernote(command: 'editor.justifyCenter' | 'justifyCenter'): JQuery;
|
||||
summernote(command: 'editor.justifyFull' | 'justifyFull'): JQuery;
|
||||
summernote(command: 'insertParagraph'): JQuery;
|
||||
summernote(command: 'editor.insertOrderedList' | 'insertOrderedList'): JQuery;
|
||||
summernote(command: 'editor.insertUnorderedList' | 'insertUnorderedList'): JQuery;
|
||||
summernote(command: 'editor.indent' | 'indent'): JQuery;
|
||||
summernote(command: 'editor.outdent' | 'outdent'): JQuery;
|
||||
summernote(command: 'formatPara'): JQuery;
|
||||
summernote(command: 'formatH1'): JQuery;
|
||||
summernote(command: 'formatH2'): JQuery;
|
||||
summernote(command: 'formatH3'): JQuery;
|
||||
summernote(command: 'formatH4'): JQuery;
|
||||
summernote(command: 'formatH5'): JQuery;
|
||||
summernote(command: 'formatH6'): JQuery;
|
||||
// Insertion API
|
||||
summernote(command: 'editor.insertImage' | 'insertImage', url: string, filename?: (string | Summernote.EditImageCallback)): JQuery;
|
||||
summernote(command: 'editor.insertNode' | 'insertNode', node: JQuery.Node): JQuery;
|
||||
summernote(command: 'editor.insertText' | 'insertText', text: string): JQuery;
|
||||
summernote(command: 'createLink', options: Summernote.CreateLinkOptions): JQuery;
|
||||
// TODO: Callbacks
|
||||
|
||||
// TODO: Editor
|
||||
// editor.insertImagesOrCallback ??
|
||||
// editor.afterCommand ??
|
||||
// editor.resizeTo ??
|
||||
// editor.resize ??
|
||||
// editor.saveTarget ??
|
||||
// editor.isActivated ??
|
||||
// editor.formatBlock ??
|
||||
// editor.color ??
|
||||
// editor.lineHeight ??
|
||||
// editor.insertTable ??
|
||||
// editor.insertHorizontalRule ??
|
||||
// editor.floatMe ??
|
||||
// editor.removeMedia ??
|
||||
// editor.currentStyle ??
|
||||
// editor.getLinkInfo ??
|
||||
// editor.getSelectedText ??
|
||||
}
|
||||
}
|
||||
|
||||
export { };
|
||||
@@ -133,9 +133,9 @@
|
||||
<div class="row gx-0">
|
||||
<div class="col-2 d-grid">
|
||||
<b-button
|
||||
:pressed="searchMode"
|
||||
@click="searchCommand()"
|
||||
:variant="searchMode ? 'info' : 'primary'"
|
||||
:pressed="searchModeOn"
|
||||
@click="toggleSearchCommand()"
|
||||
:variant="searchModeOn ? 'info' : 'primary'"
|
||||
v-b-tooltip.hover
|
||||
title="검색 기능을 활성화합니다."
|
||||
><i class="bi bi-search"></i
|
||||
@@ -160,7 +160,7 @@
|
||||
deselectGroupLabel=""
|
||||
placeholder="턴 선택"
|
||||
:maxHeight="400"
|
||||
:searchable="searchMode"
|
||||
:searchable="searchModeOn"
|
||||
>
|
||||
<template v-slot:noResult>검색 결과가 없습니다.</template>
|
||||
<template v-slot:option="props"
|
||||
@@ -209,8 +209,7 @@ import { mb_strwidth } from "@util/mb_strwidth";
|
||||
import { parseTime } from "@util/parseTime";
|
||||
import { parseYearMonth } from "@util/parseYearMonth";
|
||||
import { sammoAPI } from "@util/sammoAPI";
|
||||
import { filter초성withAlphabet } from "@util/filter초성withAlphabet";
|
||||
|
||||
import { convertSearch초성 } from "./util/convertSearch초성";
|
||||
type commandItem = {
|
||||
value: string;
|
||||
title: string;
|
||||
@@ -228,7 +227,6 @@ declare const commandList: {
|
||||
values: commandItem[];
|
||||
}[];
|
||||
declare const serverNow: string;
|
||||
declare const serverID: string;
|
||||
type TurnObj = {
|
||||
action: string;
|
||||
brief: string;
|
||||
@@ -284,7 +282,7 @@ function isDropdownChildren(e?: Event): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
const searchModeKey = `sammo_${serverID}_searchMode`;
|
||||
const searchModeKey = `sammo_searchModeOn`;
|
||||
|
||||
export default defineComponent({
|
||||
name: "PartialReservedCommand",
|
||||
@@ -449,7 +447,7 @@ export default defineComponent({
|
||||
|
||||
if (listReqArgCommand.has(commandName)) {
|
||||
document.location.href = stringifyUrl({
|
||||
url: "b_processing.php",
|
||||
url: "v_processing.php",
|
||||
query: {
|
||||
command: commandName,
|
||||
turnList: turnList.join("_"),
|
||||
@@ -478,10 +476,10 @@ export default defineComponent({
|
||||
}
|
||||
await this.reloadCommandList();
|
||||
},
|
||||
searchCommand() {
|
||||
const searchMode = !this.searchMode;
|
||||
this.searchMode = searchMode;
|
||||
localStorage.setItem(searchModeKey, searchMode ? "1" : "0");
|
||||
toggleSearchCommand() {
|
||||
const searchModeOn = !this.searchModeOn;
|
||||
this.searchModeOn = searchModeOn;
|
||||
localStorage.setItem(searchModeKey, searchModeOn ? "1" : "0");
|
||||
},
|
||||
},
|
||||
data() {
|
||||
@@ -499,14 +497,11 @@ export default defineComponent({
|
||||
if (command.searchText) {
|
||||
continue;
|
||||
}
|
||||
const [filteredTextH, filteredTextA] = filter초성withAlphabet(
|
||||
command.simpleName.replace(/\s+/g, "")
|
||||
);
|
||||
command.searchText = `${command.simpleName} ${filteredTextH} ${filteredTextA}`;
|
||||
command.searchText = convertSearch초성(command.simpleName).join('|');
|
||||
}
|
||||
}
|
||||
|
||||
const searchMode = (localStorage.getItem(searchModeKey) ?? "1") != "0";
|
||||
const searchModeOn = (localStorage.getItem(searchModeKey) ?? "0") != "0";
|
||||
|
||||
const emptyTurn: TurnObjWithTime[] = Array.from<TurnObjWithTime>({
|
||||
length: maxTurn,
|
||||
@@ -535,7 +530,7 @@ export default defineComponent({
|
||||
selectedCommand,
|
||||
reservedCommandList: emptyTurn,
|
||||
autorun_limit: null as null | number,
|
||||
searchMode,
|
||||
searchModeOn,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
@@ -547,7 +542,6 @@ export default defineComponent({
|
||||
@import "@scss/common/break_500px.scss";
|
||||
@import "@scss/common/variables.scss";
|
||||
@import "@scss/common/bootswatch_custom_variables.scss";
|
||||
@import "bootstrap/scss/bootstrap-utilities.scss";
|
||||
|
||||
.commandPad {
|
||||
background-color: $gray-900;
|
||||
@@ -560,7 +554,7 @@ export default defineComponent({
|
||||
//30, 70, 37.65, 160
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
@include media-1000px{
|
||||
.commandPad {
|
||||
margin-left: 10px;
|
||||
|
||||
@@ -582,7 +576,7 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
@include media-500px {
|
||||
.dropdown-item {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ import 'bootstrap';
|
||||
import download from 'downloadjs';
|
||||
import { unwrap } from "@util/unwrap";
|
||||
import { isInteger } from 'lodash';
|
||||
import { combineArray, errUnknown, getNpcColor } from '@/common_legacy';
|
||||
import { errUnknown, getNpcColor } from '@/common_legacy';
|
||||
import { combineArray } from "@util/combineArray";
|
||||
import { isBrightColor } from "@util/isBrightColor";
|
||||
import { numberWithCommas } from "@util/numberWithCommas";
|
||||
import { unwrap_any } from '@util/unwrap_any';
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
"install": "install.ts",
|
||||
"battle_simulator": "battle_simulator.ts",
|
||||
"recent_map": "recent_map.ts",
|
||||
"processing": "processing.ts",
|
||||
"select_npc": "select_npc.ts",
|
||||
"betting": "betting.ts",
|
||||
"bossInfo": "bossInfo.ts",
|
||||
@@ -27,7 +26,7 @@
|
||||
"v_NPCControl": "v_NPCControl.ts",
|
||||
"v_join": "v_join.ts",
|
||||
"v_main": "v_main.ts",
|
||||
"v_dipcenter": "v_dipcenter.ts"
|
||||
|
||||
"v_dipcenter": "v_dipcenter.ts",
|
||||
"v_processing": "v_processing.ts"
|
||||
}
|
||||
}
|
||||
@@ -237,7 +237,7 @@ $(function ($) {
|
||||
const $command = $('#chiefCommandList option:selected');
|
||||
if ($command.data('reqarg')) {
|
||||
document.location.href = stringifyUrl({
|
||||
url: 'b_processing.php',
|
||||
url: 'v_processing.php',
|
||||
query: {
|
||||
command: unwrap_any<string>($command.val()),
|
||||
turnList: turnList.join('_'),
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
export function colorSelect(): void{
|
||||
function changeNationColorPlate(){
|
||||
const $this = $('#colorType');
|
||||
const $option = $this.find('option:selected');
|
||||
$this.css({
|
||||
'background-color':$option.css('background-color'),
|
||||
'color':$option.css('color')
|
||||
});
|
||||
}
|
||||
$('#colorType').on('change', function(){
|
||||
changeNationColorPlate();
|
||||
});
|
||||
changeNationColorPlate();
|
||||
}
|
||||
@@ -69,16 +69,6 @@ export function combineObject<K extends string, V>(item: V[], columnList: K[]):
|
||||
return newItem;
|
||||
}
|
||||
|
||||
export function combineArray<K extends string, V>(array: V[][], columnList: K[]): Record<K, V>[] {
|
||||
const result: Record<K, V>[] = [];
|
||||
for (const key of array.keys()) {
|
||||
const item = array[key];
|
||||
result[key] = combineObject(item, columnList);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
export function errUnknown(): void {
|
||||
alert('작업을 실패했습니다.');
|
||||
}
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
<template>
|
||||
<table style="width: 1000px; margin: auto" class="bg0">
|
||||
<tr>
|
||||
<td style="text-align: left">
|
||||
{{title}}<br /><button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="back"
|
||||
>돌아가기</button><br />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="bg0">
|
||||
<button type="button" class="btn btn-sammo-base2 back_btn" @click="back">
|
||||
돌아가기
|
||||
</button>
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<div
|
||||
:id="uuid"
|
||||
:class="['world_map', `map_theme_${mapTheme}`, 'draw_required']"
|
||||
>
|
||||
<div
|
||||
class="map_title obj_tooltip"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="top"
|
||||
data-tooltip-class="map_title_tooltiptext"
|
||||
>
|
||||
<span class="map_title_text"> </span>
|
||||
<span class="tooltiptext"></span>
|
||||
</div>
|
||||
<div class="map_body">
|
||||
<div class="map_bglayer1"></div>
|
||||
<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-sm btn-minimum"
|
||||
data-bs-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-bs-toggle="button"
|
||||
aria-pressed="false"
|
||||
autocomplete="off"
|
||||
>
|
||||
두번 탭 해 도시 이동
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="city_tooltip">
|
||||
<div class="city_name"></div>
|
||||
<div class="nation_name"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import "@/../css/map.css";
|
||||
import { reloadWorldMap, loadMapOption, MapCityParsed } from "@/map";
|
||||
import { defineComponent, onMounted, PropType, ref } from "vue";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
export type { MapCityParsed };
|
||||
export default defineComponent({
|
||||
props: {
|
||||
mapTheme: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isDetailMap: { type: Boolean, default: undefined, required: false },
|
||||
clickableAll: { type: Boolean, default: undefined, required: false },
|
||||
selectCallback: {
|
||||
type: Function as PropType<loadMapOption["selectCallback"]>,
|
||||
required: false,
|
||||
},
|
||||
hrefTemplate: { type: String, default: undefined, required: false },
|
||||
useCachedMap: { type: Boolean, default: undefined, required: false },
|
||||
|
||||
year: { type: Number, default: undefined, required: false },
|
||||
month: { type: Number, default: undefined, required: false },
|
||||
aux: {
|
||||
type: Object as PropType<loadMapOption["aux"]>,
|
||||
default: undefined,
|
||||
required: false,
|
||||
},
|
||||
neutralView: { type: Boolean, default: undefined, required: false },
|
||||
showMe: { type: Boolean, default: undefined, required: false },
|
||||
|
||||
targetJson: { type: String, default: undefined, required: false },
|
||||
reqType: {
|
||||
type: String as PropType<loadMapOption["reqType"]>,
|
||||
default: undefined,
|
||||
},
|
||||
dynamicMapTheme: { type: Boolean, default: undefined, required: false },
|
||||
callback: {
|
||||
type: Function as PropType<loadMapOption["callback"]>,
|
||||
default: undefined,
|
||||
},
|
||||
startYear: { type: Number, default: undefined, required: false },
|
||||
|
||||
modelValue: {
|
||||
type: Object as PropType<MapCityParsed>,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue", "loaded"],
|
||||
setup(props, { emit }) {
|
||||
const uuid = uuidv4();
|
||||
const modelValue = ref(props.modelValue);
|
||||
|
||||
onMounted(async () => {
|
||||
const option: loadMapOption = {
|
||||
isDetailMap: props.isDetailMap,
|
||||
clickableAll: props.clickableAll,
|
||||
selectCallback: (city) => {
|
||||
modelValue.value = city;
|
||||
emit("update:modelValue", city);
|
||||
},
|
||||
hrefTemplate: props.hrefTemplate,
|
||||
useCachedMap: props.useCachedMap,
|
||||
|
||||
year: props.year,
|
||||
month: props.month,
|
||||
aux: props.aux,
|
||||
neutralView: props.neutralView,
|
||||
showMe: props.showMe,
|
||||
|
||||
targetJson: props.targetJson,
|
||||
reqType: props.reqType,
|
||||
dynamicMapTheme: props.dynamicMapTheme,
|
||||
callback: (a, rawObject) => {
|
||||
emit("loaded", [a, rawObject]);
|
||||
},
|
||||
|
||||
startYear: props.startYear,
|
||||
};
|
||||
|
||||
await reloadWorldMap(option, `#${uuid}`);
|
||||
});
|
||||
|
||||
return {
|
||||
uuid,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -1,9 +1,17 @@
|
||||
<template>
|
||||
<div class="bg0 back_bar">
|
||||
<button type="button" class="btn btn-primary back_btn" @click="back">
|
||||
<button type="button" class="btn btn-sammo-base2 back_btn" @click="back">
|
||||
돌아가기
|
||||
</button>
|
||||
</button><b-button
|
||||
class="btn-toggle-zoom"
|
||||
:variant="toggleSearch ? 'info' : 'secondary'"
|
||||
:pressed="toggleSearch"
|
||||
v-if="toggleSearch !== undefined"
|
||||
@click="toggleSearch = !toggleSearch"
|
||||
>{{ toggleSearch ? "검색 켜짐" : "검색 꺼짐" }}</b-button
|
||||
>
|
||||
<h2 class="title">{{ title }}</h2>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -25,6 +33,17 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
toggleSearch: this.searchable,
|
||||
};
|
||||
},
|
||||
emits: ["update:searchable"],
|
||||
watch: {
|
||||
toggleSearch(val: boolean) {
|
||||
this.$emit("update:searchable", val);
|
||||
},
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
@@ -35,6 +54,11 @@ export default defineComponent({
|
||||
default: "normal",
|
||||
required: false,
|
||||
},
|
||||
searchable: {
|
||||
type: Boolean,
|
||||
default: undefined,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -46,8 +70,6 @@ export default defineComponent({
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
position: relative;
|
||||
border-left: 1px solid #888;
|
||||
border-right: 1px solid #888;
|
||||
height: 24pt;
|
||||
}
|
||||
|
||||
@@ -57,6 +79,12 @@ export default defineComponent({
|
||||
height: 24pt;
|
||||
}
|
||||
|
||||
.btn-toggle-zoom{
|
||||
position: absolute;
|
||||
height: 24pt;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
line-height: 24pt;
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { reloadWorldMap } from "@/map";
|
||||
import { unwrap_any } from "@util/unwrap_any";
|
||||
|
||||
export function defaultSelectCityByMap(): void {
|
||||
const $target = $("#destCityID");
|
||||
console.log('city', $target);
|
||||
void reloadWorldMap({
|
||||
isDetailMap: false,
|
||||
clickableAll: true,
|
||||
neutralView: true,
|
||||
useCachedMap: true,
|
||||
selectCallback: function (city) {
|
||||
const currVal = unwrap_any<string>($target.val());
|
||||
$target.val(city.id);
|
||||
$target.trigger("change");
|
||||
if ($target.val() === null) {
|
||||
$target.val(currVal).trigger("change").blur();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import { reloadWorldMap } from "@/map";
|
||||
import { unwrap_any } from "@util/unwrap_any";
|
||||
|
||||
export function defaultSelectNationByMap(): void{
|
||||
const $target = $("#destNationID");
|
||||
console.log('nation', $target);
|
||||
void reloadWorldMap({
|
||||
isDetailMap: false,
|
||||
clickableAll: true,
|
||||
neutralView: true,
|
||||
useCachedMap: true,
|
||||
selectCallback: (city)=>{
|
||||
const currVal = unwrap_any<string>($target.val());
|
||||
if(!city.nationID){
|
||||
return false;
|
||||
}
|
||||
$target.val(city.nationID).trigger("change");
|
||||
if ($target.val() === null) {
|
||||
$target.val(currVal).trigger("change");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
+13
-1
@@ -133,6 +133,14 @@ export type NationPolicy = {
|
||||
properWarTrainAtmos: number,
|
||||
}
|
||||
|
||||
export type ItemTypeKey = 'horse' | 'weapon' | 'book' | 'item';
|
||||
export const ItemTypeNameMap: Record<ItemTypeKey, string> = {
|
||||
horse: '명마',
|
||||
weapon: '무기',
|
||||
book: '서적',
|
||||
item: '도구',
|
||||
}
|
||||
|
||||
export declare type Colors = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light';
|
||||
|
||||
export type IDItem<T> = {
|
||||
@@ -147,4 +155,8 @@ export type ToastType = {
|
||||
}
|
||||
|
||||
export const keyScreenMode = 'sam.screenMode';
|
||||
export type ScreenModeType = 'auto'|'500px'|'1000px';
|
||||
export type ScreenModeType = 'auto'|'500px'|'1000px';
|
||||
|
||||
export declare type ValuesOf<T> = T[keyof T];
|
||||
|
||||
export const NoneValue = 'None' as const;
|
||||
Vendored
-15
@@ -1,15 +0,0 @@
|
||||
type JQueryBootstrapToast = {
|
||||
container?: JQuery<HTMLElement>,
|
||||
position?: 'top-right' | 'top-left' | 'top-center' | 'bottom-right' | 'bottom-left' | 'bottom-center',
|
||||
title?: string,
|
||||
subtitle?: string,
|
||||
content?: string,
|
||||
type?: 'info'|'success'|'warning'|'danger'|'error',
|
||||
delay?: number,
|
||||
img?: string,
|
||||
pause_on_hover?: boolean,
|
||||
}
|
||||
|
||||
interface JQueryStatic {
|
||||
toast(opt: JQueryBootstrapToast): void;
|
||||
}
|
||||
+19
-11
@@ -1,11 +1,13 @@
|
||||
import axios from 'axios';
|
||||
import $ from 'jquery';
|
||||
import { extend, isNumber } from 'lodash';
|
||||
import { isNumber, merge } from 'lodash';
|
||||
import { convColorValue, convertDictById, stringFormat } from '@/common_legacy';
|
||||
import { InvalidResponse } from '@/defs';
|
||||
import { unwrap } from "@util/unwrap";
|
||||
import { convertFormData } from '@util/convertFormData';
|
||||
import { exportWindow } from '@util/exportWindow';
|
||||
import { htmlReady } from './util/htmlReady';
|
||||
import { initTooltip } from './legacy/initTooltip';
|
||||
|
||||
declare const serverNick: string;
|
||||
declare const serverID: string;
|
||||
@@ -57,7 +59,7 @@ type MapCityParsedRegionLevelText = MapCityParsedClickable & {
|
||||
text: string,
|
||||
}
|
||||
|
||||
type MapCityParsed = MapCityParsedRegionLevelText;
|
||||
export type MapCityParsed = MapCityParsedRegionLevelText;
|
||||
|
||||
type MapCityDrawable = {
|
||||
cityList: MapCityParsed[],
|
||||
@@ -107,7 +109,7 @@ function is_touch_device(): boolean {
|
||||
return mq(query);
|
||||
}
|
||||
|
||||
type loadMapOption = {
|
||||
export type loadMapOption = {
|
||||
isDetailMap?: boolean, //복잡 지도, 단순 지도
|
||||
clickableAll?: boolean, //어떤 경우든 클릭을 가능하게 함. 해당 동작의 동작 가능성 여부와는 별도.
|
||||
selectCallback?: (city: MapCityParsed) => void, //callback을 지정시 clickable과 관계 없이 해당 함수를 실행.
|
||||
@@ -160,7 +162,7 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
|
||||
startYear: undefined,
|
||||
};
|
||||
|
||||
option = extend({}, defaultOption, option);
|
||||
option = merge({}, defaultOption, option);
|
||||
|
||||
const useCachedMap = option.useCachedMap;
|
||||
const isDetailMap = option.isDetailMap;
|
||||
@@ -505,6 +507,9 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
|
||||
}
|
||||
|
||||
function setMouseWork(obj: MapCityDrawable) {
|
||||
|
||||
initTooltip($(drawTarget));
|
||||
|
||||
const $tooltip = $(drawTarget + ' .city_tooltip');
|
||||
const $tooltip_city = $tooltip.find('.city_name');
|
||||
const $tooltip_nation = $tooltip.find('.nation_name');
|
||||
@@ -655,7 +660,8 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
|
||||
}
|
||||
|
||||
if (selectCallback) {
|
||||
$cityLink.on('click', function () {
|
||||
$cityLink.on('click', function (e) {
|
||||
e.preventDefault();
|
||||
return selectCallback(city);
|
||||
});
|
||||
}
|
||||
@@ -671,7 +677,6 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
|
||||
|
||||
const $hideCityNameBtn = $world_map.find('.map_toggle_cityname');
|
||||
if (localStorage.getItem('sam.hideMapCityName') == 'yes') {
|
||||
console.log('tryHide!');
|
||||
$world_map.addClass('hide_cityname');
|
||||
$hideCityNameBtn.addClass('active').attr('aria-pressed', 'true');
|
||||
}
|
||||
@@ -680,7 +685,6 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
|
||||
//이전 상태 확인
|
||||
const state = localStorage.getItem('sam.hideMapCityName') == 'no';
|
||||
if (state) {
|
||||
console.log('tryHide!');
|
||||
$world_map.addClass('hide_cityname');
|
||||
localStorage.setItem('sam.hideMapCityName', 'yes');
|
||||
} else {
|
||||
@@ -789,8 +793,12 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
|
||||
}
|
||||
|
||||
exportWindow(reloadWorldMap, 'reloadWorldMap');
|
||||
$(function ($) {
|
||||
if (is_touch_device()) {
|
||||
$('.map_body .map_toggle_single_tap').show();
|
||||
htmlReady(function(){
|
||||
if( is_touch_device()){
|
||||
const target = document.querySelector('.map_body .map_toggle_single_tap') as HTMLElement | null;
|
||||
if(!target){
|
||||
return;
|
||||
}
|
||||
target.style.display = 'block';
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -1,300 +0,0 @@
|
||||
import $ from 'jquery';
|
||||
exportWindow($, '$');
|
||||
import { exportWindow } from '@util/exportWindow';
|
||||
import axios from 'axios';
|
||||
import 'bootstrap';
|
||||
import 'select2/dist/js/select2.full.js'
|
||||
import { setAxiosXMLHttpRequest } from '@util/setAxiosXMLHttpRequest';
|
||||
import { convertFormData } from '@util/convertFormData';
|
||||
import { InvalidResponse } from '@/defs';
|
||||
import { unwrap_any } from '@util/unwrap_any';
|
||||
import { DataFormat, IdTextPair, OptionData } from 'select2';
|
||||
import { unwrap } from "@util/unwrap";
|
||||
import { defaultSelectCityByMap } from '@/defaultSelectCityByMap';
|
||||
import { defaultSelectNationByMap } from '@/defaultSelectNationByMap';
|
||||
import { colorSelect } from '@/colorSelect';
|
||||
import { recruitCrewForm } from '@/recruitCrewForm';
|
||||
|
||||
declare const isChiefTurn: boolean;
|
||||
declare const jsPlugins: string[];
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
submitAction: () => Promise<void>;
|
||||
turnList: number[],
|
||||
command: string,
|
||||
}
|
||||
}
|
||||
|
||||
async function reserveTurn(turnList: number[], command: string, arg: Record<string, unknown>) {
|
||||
const target = isChiefTurn ? 'j_set_chief_command.php' : 'j_set_general_command.php';
|
||||
|
||||
let data: InvalidResponse;
|
||||
try {
|
||||
const response = await axios({
|
||||
url: target,
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
data: convertFormData({
|
||||
action: command,
|
||||
turnList: turnList,
|
||||
arg: JSON.stringify(arg)
|
||||
})
|
||||
});
|
||||
data = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`에러가 발생했습니다: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.result) {
|
||||
alert(data.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isChiefTurn) {
|
||||
window.location.href = './';
|
||||
} else {
|
||||
window.location.href = 'b_chiefcenter.php';
|
||||
}
|
||||
}
|
||||
|
||||
$(function ($) {
|
||||
setAxiosXMLHttpRequest();
|
||||
//checkCommandArg 참고
|
||||
const availableArgumentList = {
|
||||
'string': [
|
||||
'nationName', 'optionText', 'itemType', 'nationType', 'itemCode', 'commandType',
|
||||
],
|
||||
'int': [
|
||||
'crewType', 'destGeneralID', 'destCityID', 'destNationID',
|
||||
'amount', 'colorType',
|
||||
'year', 'month',
|
||||
'srcArmType', 'destArmType', //숙련전환 전용
|
||||
],
|
||||
'boolean': [
|
||||
'isGold', 'buyRice',
|
||||
],
|
||||
'integerArray': [
|
||||
'destNationIDList', 'destGeneralIDList', 'amountList'
|
||||
]
|
||||
}
|
||||
|
||||
type argTypes = keyof typeof availableArgumentList;
|
||||
type argValues = string | number | boolean | number[];
|
||||
|
||||
const handlerList: Record<argTypes, ($obj: JQuery<HTMLInputElement>) => argValues> = {
|
||||
'string': function ($obj: JQuery<HTMLInputElement>) {
|
||||
return $.trim(unwrap_any<string>($obj.eq(0).val()));
|
||||
},
|
||||
'int': function ($obj: JQuery<HTMLInputElement>) {
|
||||
return parseInt(unwrap_any<string>($obj.eq(0).val()));
|
||||
},
|
||||
'boolean': function ($obj: JQuery<HTMLInputElement>) {
|
||||
switch (unwrap_any<string>($obj.eq(0).val()).toLowerCase()) {
|
||||
case "true":
|
||||
case "yes":
|
||||
case "1":
|
||||
return true;
|
||||
case "false":
|
||||
case "no":
|
||||
case "0":
|
||||
return false;
|
||||
default:
|
||||
throw new Error("Boolean.parse: Cannot convert string to boolean.");
|
||||
}
|
||||
},
|
||||
'integerArray': function ($obj: JQuery<HTMLInputElement>) {
|
||||
const result: number[] = [];
|
||||
$obj.each(function () {
|
||||
result.push(parseInt(unwrap_any<string>($(this).val())));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
window.submitAction = async function (): Promise<void> {
|
||||
const argument: Record<string, argValues> = {};
|
||||
for (const typeName of Object.keys(availableArgumentList) as argTypes[]) {
|
||||
const typeKeys = availableArgumentList[typeName];
|
||||
for (const typeKey of typeKeys) {
|
||||
let $obj = $('#' + typeKey) as JQuery<HTMLInputElement>;
|
||||
if ($obj.length == 0) {
|
||||
$obj = $('.' + typeKey);
|
||||
if ($obj.length == 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
argument[typeKey] = handlerList[typeName]($obj);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(argument);
|
||||
await reserveTurn(window.turnList, window.command, argument);
|
||||
};
|
||||
|
||||
$('#commonSubmit').on('click', window.submitAction);
|
||||
|
||||
const $colorType = $('#colorType');
|
||||
if ($colorType.length) {
|
||||
$colorType.select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: "색상을 선택해 주세요.",
|
||||
language: "ko",
|
||||
containerCss: {
|
||||
display: "inline-block !important",
|
||||
color: 'white !important',
|
||||
},
|
||||
templateSelection: function (item) {
|
||||
if ((item as DataFormat).disabled) {
|
||||
return item.text;
|
||||
}
|
||||
const element = (item as OptionData).element;
|
||||
if (!element) {
|
||||
throw 'invalid type';
|
||||
}
|
||||
const bgcolor = unwrap(element.dataset.color);
|
||||
const fgcolor = unwrap(element.dataset.fontColor);
|
||||
// eslint-disable-next-line no-irregular-whitespace
|
||||
return $(`<span><span style='background-color:${bgcolor};color:${fgcolor};'> </span> ${item.text}</span>`);
|
||||
},
|
||||
templateResult: function (item) {
|
||||
if ((item as DataFormat).disabled) {
|
||||
return item.text;
|
||||
}
|
||||
const element = (item as OptionData).element;
|
||||
if (!element) {
|
||||
throw 'invalid type';
|
||||
}
|
||||
const bgcolor = unwrap(element.dataset.color);
|
||||
const fgcolor = unwrap(element.dataset.fontColor);
|
||||
return $(`<div style='padding: 0.75rem 0.375rem; background-color:${bgcolor};color:${fgcolor};'>${item.text}</div>`);
|
||||
},
|
||||
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
dropdownCssClass: 'no-padding simple-select2-align-center bg-secondary text-secondary',
|
||||
});
|
||||
}
|
||||
|
||||
const $nationType = $('#nationType');
|
||||
if ($nationType.length) {
|
||||
$nationType.select2({
|
||||
theme: 'bootstrap4',
|
||||
language: "ko",
|
||||
containerCss: {
|
||||
display: "inline-block !important",
|
||||
color: 'white !important',
|
||||
},
|
||||
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
});
|
||||
}
|
||||
|
||||
const $destCityID = $('#destCityID');
|
||||
if ($destCityID.length) {
|
||||
$destCityID.select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: "도시를 선택해 주세요.",
|
||||
language: "ko",
|
||||
containerCss: {
|
||||
display: "inline-block !important",
|
||||
color: 'white !important',
|
||||
},
|
||||
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
});
|
||||
}
|
||||
|
||||
const $destNationID = $('#destNationID');
|
||||
if ($destNationID.length) {
|
||||
$destNationID.select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: "국가를 선택해 주세요.",
|
||||
language: "ko",
|
||||
containerCss: {
|
||||
display: "inline-block !important",
|
||||
color: 'white !important',
|
||||
},
|
||||
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
});
|
||||
}
|
||||
|
||||
const $destGeneralID = $('#destGeneralID');
|
||||
if ($destGeneralID.length) {
|
||||
$destGeneralID.select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: "장수를 선택해 주세요.",
|
||||
language: "ko",
|
||||
containerCss: {
|
||||
display: "inline-block !important",
|
||||
color: 'white !important',
|
||||
},
|
||||
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
});
|
||||
}
|
||||
|
||||
const $isGold = $('#isGold');
|
||||
if ($isGold.length) {
|
||||
$isGold.select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: "분량을 지정해 주세요.",
|
||||
language: "ko",
|
||||
containerCss: {
|
||||
display: "inline-block !important",
|
||||
color: 'white !important',
|
||||
},
|
||||
minimumResultsForSearch: -1,
|
||||
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
});
|
||||
}
|
||||
|
||||
const $amount = $('#amount:not([type=hidden])');
|
||||
if ($amount.length) {
|
||||
$amount.select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: "분량을 지정해 주세요.",
|
||||
allowClear: false,
|
||||
language: "ko",
|
||||
containerCss: {
|
||||
display: "inline-block !important",
|
||||
color: 'white !important',
|
||||
},
|
||||
tags: true,
|
||||
sorter: function (items) {
|
||||
(items as IdTextPair[]).sort(function (lhs, rhs) {
|
||||
return parseInt(lhs.id) - parseInt(rhs.id);
|
||||
})
|
||||
return items;
|
||||
},
|
||||
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
dropdownCssClass: 'select2-only-number simple-select2-align-center bg-secondary text-secondary',
|
||||
})
|
||||
}
|
||||
|
||||
$(document).on('keypress', '.select2-only-number .select2-search__field', function (e) {
|
||||
$(this).val(unwrap_any<string>($(this).val()).replace(/[^\d].+/, ""));
|
||||
if ((e.which < 48 || e.which > 57)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
const pluginMap:Record<string, ()=>void> = {
|
||||
'defaultSelectCityByMap': defaultSelectCityByMap,
|
||||
'defaultSelectNationByMap': defaultSelectNationByMap,
|
||||
'colorSelect': colorSelect,
|
||||
'recruitCrewForm': recruitCrewForm,
|
||||
};
|
||||
for (const jsPlugin of jsPlugins) {
|
||||
if (jsPlugin in pluginMap) {
|
||||
pluginMap[jsPlugin]()
|
||||
}
|
||||
else{
|
||||
console.error(`'${jsPlugin}' is not supported`);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div v-for="(cityList, distance) in distanceList" :key="distance">
|
||||
{{ distance }}칸 떨어진 도시:
|
||||
<template v-for="(cityID, key) in cityList" :key="key">
|
||||
<template v-if="key !== 0">, </template>
|
||||
<a :style="{ color: colorMap[distance] ?? undefined, textDecoration:'underline' }" @click="$emit('selected', cityID)">{{
|
||||
citiesMap.get(cityID)?.name
|
||||
}}</a>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
distanceList: {
|
||||
type: Object as PropType<Record<number, number[]>>,
|
||||
required: true,
|
||||
},
|
||||
citiesMap: {
|
||||
type: Object as PropType<Map<number, { name: string }>>,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: ['selected'],
|
||||
data() {
|
||||
return {
|
||||
colorMap: {
|
||||
1: "magenta",
|
||||
2: "orange",
|
||||
3: "yellow",
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<div class="crewTypeItem crewTypeSubGrid text-center s-border-b">
|
||||
<div
|
||||
class="crewTypeImg"
|
||||
:style="{
|
||||
background: '#222222 no-repeat center',
|
||||
backgroundImage: `url('${crewType.img}')`,
|
||||
backgroundSize: '64px',
|
||||
outline: 'solid 1px gray',
|
||||
}"
|
||||
></div>
|
||||
<div
|
||||
:style="{
|
||||
backgroundColor: crewType.notAvailable
|
||||
? 'red'
|
||||
: crewType.reqTech == 0
|
||||
? 'green'
|
||||
: 'limegreen',
|
||||
height: '100%',
|
||||
}"
|
||||
class="d-grid crewTypeName"
|
||||
>
|
||||
<div style="margin: auto">
|
||||
{{ crewType.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div>{{ crewType.attack }}</div>
|
||||
<div>{{ crewType.defence }}</div>
|
||||
<div>{{ crewType.speed }}</div>
|
||||
<div>{{ crewType.avoid }}</div>
|
||||
<div>{{ crewType.baseCost.toFixed(1) }}</div>
|
||||
<div>{{ crewType.baseRice.toFixed(1) }}</div>
|
||||
<div class="crewTypePanel">
|
||||
<b-button-group
|
||||
><b-button class="py-1" variant="dark" @click="beHalf">절반</b-button
|
||||
><b-button class="py-1" variant="dark" @click="beFilled"
|
||||
>채우기</b-button
|
||||
><b-button class="py-1" variant="dark" @click="beFull"
|
||||
>가득</b-button
|
||||
></b-button-group
|
||||
>
|
||||
<div class="row">
|
||||
<div class="col mx-2">
|
||||
<div class="input-group my-0">
|
||||
<span class="input-group-text py-1">병력</span>
|
||||
<input
|
||||
type="number"
|
||||
class="form-control py-1 f_tnum px-0 text-end"
|
||||
v-model="amount"
|
||||
min="1"
|
||||
/>
|
||||
<span class="input-group-text py-1 f_tnum">00명</span>
|
||||
<span
|
||||
class="input-group-text py-1 f_tnum"
|
||||
style="
|
||||
text-align: right;
|
||||
min-width: 10ch;
|
||||
color: #303030;
|
||||
background-color: #ddd;
|
||||
"
|
||||
><div style="margin-left: auto">
|
||||
{{ Math.ceil(amount * crewType.baseCost * goldCoeff).toLocaleString() }}금
|
||||
</div></span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="crewTypeBtn d-grid">
|
||||
<b-button variant="primary" @click="doSubmit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
<div
|
||||
class="crewTypeInfo text-start"
|
||||
v-html="crewType.info.join('<br>')"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from "vue";
|
||||
import VueTypes from "vue-types";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
crewType: VueTypes.object.isRequired,
|
||||
leadership: VueTypes.number.isRequired,
|
||||
commandName: VueTypes.string.isRequired,
|
||||
currentCrewType: VueTypes.number.def(-1),
|
||||
crew: VueTypes.number.def(0),
|
||||
goldCoeff: VueTypes.number.isRequired,
|
||||
},
|
||||
emits: ["submitOutput", "update:amount"],
|
||||
watch: {
|
||||
amount(val: number) {
|
||||
this.$emit("update:amount", val);
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const amount = ref(0);
|
||||
|
||||
function beHalf() {
|
||||
amount.value = Math.ceil(props.leadership * 0.5);
|
||||
}
|
||||
|
||||
function beFilled() {
|
||||
if (props.crewType.id == props.currentCrewType) {
|
||||
amount.value = Math.max(
|
||||
1,
|
||||
props.leadership - Math.floor(props.crew / 100)
|
||||
);
|
||||
} else {
|
||||
amount.value = props.leadership;
|
||||
}
|
||||
}
|
||||
|
||||
function beFull() {
|
||||
amount.value = Math.floor(props.leadership * 1.2);
|
||||
}
|
||||
|
||||
function doSubmit(e: Event) {
|
||||
console.log(e);
|
||||
emit("submitOutput", e, amount.value, props.crewType.id);
|
||||
}
|
||||
|
||||
beFilled();
|
||||
|
||||
return {
|
||||
amount,
|
||||
beHalf,
|
||||
beFilled,
|
||||
beFull,
|
||||
doSubmit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" />
|
||||
<div class="bg0" v-if="!available건국">더 이상 건국은 불가능합니다.</div>
|
||||
<div class="bg0" v-else>
|
||||
<div>현재 도시에서 나라를 세웁니다. 중, 소도시에서만 가능합니다.</div>
|
||||
<ul>
|
||||
<li v-for="nationType in nationTypes" :key="nationType.type" class="row">
|
||||
<div class="col-2 col-md-1">- {{ nationType.name }}</div>
|
||||
<div class="col-4 col-md-2">
|
||||
: <span style="color: cyan">{{ nationType.pros }}</span
|
||||
>,
|
||||
</div>
|
||||
<div class="col-4 col-md-2">
|
||||
<span style="color: magenta">{{ nationType.cons }}</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="row">
|
||||
<div class="col-4 col-md-2">
|
||||
국명 : <b-form-input maxlength="18" v-model="destNationName" />
|
||||
</div>
|
||||
<div class="col-3 col-md-2">
|
||||
색상 : <ColorSelect :colors="colors" v-model="selectedColorID" />
|
||||
</div>
|
||||
<div class="col-3 col-md-2">
|
||||
<label>성향 :</label>
|
||||
<b-form-select
|
||||
:options="nationTypesOption"
|
||||
v-model="selectedNationType"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col-2 col-md-2 d-grid">
|
||||
<b-button @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import ColorSelect from "@/processing/SelectColor.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import { procNationTypeList } from "../processingRes";
|
||||
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
available건국: boolean;
|
||||
colors: string[];
|
||||
nationTypes: procNationTypeList;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
ColorSelect,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
setup() {
|
||||
const destNationName = ref("");
|
||||
const selectedColorID = ref(0);
|
||||
|
||||
console.log(procRes.nationTypes);
|
||||
const selectedNationType = ref(Object.values(procRes.nationTypes)[0].type);
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
colorType: selectedColorID.value,
|
||||
nationName: destNationName.value,
|
||||
nationType: selectedNationType.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
const nationTypesOption: { html: string; value: string }[] = [];
|
||||
for (const nationType of Object.values(procRes.nationTypes)) {
|
||||
nationTypesOption.push({
|
||||
html: nationType.name,
|
||||
value: nationType.type,
|
||||
});
|
||||
}
|
||||
console.log(nationTypesOption);
|
||||
|
||||
return {
|
||||
available건국: procRes.available건국,
|
||||
selectedColorID,
|
||||
selectedNationType,
|
||||
colors: procRes.colors,
|
||||
nationTypes: procRes.nationTypes,
|
||||
nationTypesOption,
|
||||
destNationName,
|
||||
commandName,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" />
|
||||
<div class="bg0">
|
||||
<div>
|
||||
자신의 군량을 사거나 팝니다.<br />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-2 col-md-1">
|
||||
군량을 :
|
||||
<b-button-group>
|
||||
<b-button :pressed="buyRice" @click="buyRice=true">삼</b-button>
|
||||
<b-button :pressed="!buyRice" @click="buyRice=false">팜</b-button>
|
||||
</b-button-group>
|
||||
</div>
|
||||
<div class="col-7 col-md-4">
|
||||
금액 :
|
||||
<SelectAmount
|
||||
:amountGuide="amountGuide"
|
||||
v-model="amount"
|
||||
:maxAmount="maxAmount"
|
||||
:minAmount="minAmount"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 col-md-2 d-grid">
|
||||
<b-button variant="primary" @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import SelectAmount from "@/processing/SelectAmount.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
minAmount: number;
|
||||
maxAmount: number;
|
||||
amountGuide: number[];
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
SelectAmount,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
setup() {
|
||||
const amount = ref(1000);
|
||||
const buyRice = ref(true);
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
amount: amount.value,
|
||||
buyRice: buyRice.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
return {
|
||||
buyRice,
|
||||
amount,
|
||||
minAmount: ref(procRes.minAmount),
|
||||
maxAmount: ref(procRes.maxAmount),
|
||||
amountGuide: procRes.amountGuide,
|
||||
commandName,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,100 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" v-model:searchable="searchable" />
|
||||
<div class="bg0">
|
||||
<div>
|
||||
재야나 타국의 장수를 등용합니다.<br />
|
||||
서신은 개인 메세지로 전달됩니다.<br />
|
||||
등용할 장수를 목록에서 선택하세요.<br />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6">
|
||||
장수 :
|
||||
<SelectGeneral
|
||||
:generals="generalList"
|
||||
:groupByNation="nationList"
|
||||
:textHelper="textHelpGeneral"
|
||||
:searchable="searchable"
|
||||
v-model="selectedGeneralID"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-4 col-md-2 d-grid">
|
||||
<b-button variant="primary" @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import SelectGeneral from "@/processing/SelectGeneral.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import {
|
||||
convertGeneralList,
|
||||
getProcSearchable,
|
||||
procGeneralItem,
|
||||
procGeneralKey,
|
||||
procGeneralRawItemList,
|
||||
procNationItem,
|
||||
procNationList,
|
||||
} from "../processingRes";
|
||||
import { getNpcColor } from "@/common_legacy";
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
generals: procGeneralRawItemList;
|
||||
generalsKey: procGeneralKey[];
|
||||
nationList: procNationList;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
SelectGeneral,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
setup() {
|
||||
const generalList = convertGeneralList(
|
||||
procRes.generalsKey,
|
||||
procRes.generals
|
||||
);
|
||||
|
||||
const selectedGeneralID = ref(generalList[0].no);
|
||||
|
||||
function textHelpGeneral(gen: procGeneralItem): string {
|
||||
const nameColor = getNpcColor(gen.npc);
|
||||
const name = nameColor
|
||||
? `<span style="color:${nameColor}">${gen.name}</span>`
|
||||
: gen.name;
|
||||
return name;
|
||||
}
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
destGeneralID: selectedGeneralID.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
const nationList = new Map<number, procNationItem>();
|
||||
for (const nationItem of procRes.nationList) {
|
||||
nationList.set(nationItem.id, nationItem);
|
||||
}
|
||||
|
||||
return {
|
||||
searchable: getProcSearchable(),
|
||||
selectedGeneralID,
|
||||
generalList,
|
||||
nationList,
|
||||
commandName,
|
||||
textHelpGeneral,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" v-model:searchable="searchable" />
|
||||
<div class="bg0">
|
||||
<div v-if="commandName == '등용'">
|
||||
재야나 타국의 장수를 등용합니다.<br />
|
||||
서신은 개인 메세지로 전달됩니다.<br />
|
||||
등용할 장수를 목록에서 선택하세요.<br />
|
||||
</div>
|
||||
<div v-if="commandName == '선양'">
|
||||
군주의 자리를 다른 장수에게 물려줍니다.<br />
|
||||
장수를 선택하세요.<br />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-9 col-md-4">
|
||||
장수 :
|
||||
<SelectGeneral
|
||||
:generals="generalList"
|
||||
:textHelper="textHelpGeneral"
|
||||
:searchable="searchable"
|
||||
v-model="selectedGeneralID"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 col-md-2 d-grid">
|
||||
<b-button variant="primary" @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import SelectGeneral from "@/processing/SelectGeneral.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import {
|
||||
convertGeneralList,
|
||||
getProcSearchable,
|
||||
procGeneralItem,
|
||||
procGeneralKey,
|
||||
procGeneralRawItemList,
|
||||
} from "../processingRes";
|
||||
import { getNpcColor } from "@/common_legacy";
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
generals: procGeneralRawItemList;
|
||||
generalsKey: procGeneralKey[];
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
SelectGeneral,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
setup() {
|
||||
const generalList = convertGeneralList(
|
||||
procRes.generalsKey,
|
||||
procRes.generals
|
||||
);
|
||||
|
||||
const selectedGeneralID = ref(generalList[0].no);
|
||||
|
||||
function textHelpGeneral(gen: procGeneralItem): string {
|
||||
const nameColor = getNpcColor(gen.npc);
|
||||
const name = nameColor
|
||||
? `<span style="color:${nameColor}">${gen.name}</span>`
|
||||
: gen.name;
|
||||
return `${name} (${gen.leadership}/${gen.strength}/${gen.leadership})`;
|
||||
}
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
destGeneralID: selectedGeneralID.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
return {
|
||||
searchable: getProcSearchable(),
|
||||
selectedGeneralID,
|
||||
generalList,
|
||||
commandName,
|
||||
textHelpGeneral,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,220 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" />
|
||||
<div class="bg0">
|
||||
<div>
|
||||
본인의 특정 병종 숙련을 40% 줄이고, 줄어든 숙련 중 9/10(90%p)를 다른 병종
|
||||
숙련으로 전환합니다.
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4 col-md-2">
|
||||
감소 대상 숙련 :
|
||||
<b-form-select v-model="srcArmTypeID">
|
||||
<b-form-select-option
|
||||
v-for="[armType, dexInfo] in dexFullInfo"
|
||||
:key="armType"
|
||||
:value="armType"
|
||||
>{{ dexInfo.name }} (<span
|
||||
:style="{ color: dexInfo.currentInfo.color }"
|
||||
>{{ dexInfo.currentInfo.name }}</span>)</b-form-select-option
|
||||
>
|
||||
</b-form-select>
|
||||
</div>
|
||||
<div class="col-4 col-md-2">
|
||||
전환 대상 숙련 :
|
||||
<b-form-select v-model="destArmTypeID">
|
||||
<b-form-select-option
|
||||
v-for="[armType, dexInfo] in dexFullInfo"
|
||||
:key="armType"
|
||||
:value="armType"
|
||||
>{{ dexInfo.name }} (<span
|
||||
:style="{ color: dexInfo.currentInfo.color }"
|
||||
>{{ dexInfo.currentInfo.name }}</span>)</b-form-select-option
|
||||
>
|
||||
</b-form-select>
|
||||
</div>
|
||||
<div class="col-4 col-md-2 d-grid">
|
||||
<b-button @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
<div :style="{
|
||||
display:'grid',
|
||||
gridTemplateColumns: '3ch 1ch 2ch 10ch 1ch 3ch 1ch 2ch 10ch 1ch'
|
||||
}">
|
||||
<div>{{dexFullInfo.get(srcArmTypeID).name}}</div>
|
||||
<div class="text-end">[</div>
|
||||
<div :style="`color:${dexFullInfo.get(srcArmTypeID).currentInfo.color}`">{{dexFullInfo.get(srcArmTypeID).currentInfo.name}}</div>
|
||||
<div class="f_tnum text-end">{{convNumberFormat(dexFullInfo.get(srcArmTypeID).currentInfo.amount)}}</div>
|
||||
<div>]</div>
|
||||
<div class="text-center">→</div>
|
||||
<div class="text-end">[</div>
|
||||
<div :style="`color:${dexFullInfo.get(srcArmTypeID).decreasedInfo.color}`">{{dexFullInfo.get(srcArmTypeID).decreasedInfo.name}}</div>
|
||||
<div class="f_tnum text-end">{{convNumberFormat(dexFullInfo.get(srcArmTypeID).decreasedInfo.amount)}}</div>
|
||||
<div>]</div>
|
||||
</div>
|
||||
<div :style="{
|
||||
display:'grid',
|
||||
gridTemplateColumns: '3ch 1ch 2ch 10ch 1ch 3ch 1ch 2ch 10ch 1ch'
|
||||
}">
|
||||
<div>{{dexFullInfo.get(destArmTypeID).name}}</div>
|
||||
<div class="text-end">[</div>
|
||||
<template v-if="srcArmTypeID == destArmTypeID">
|
||||
<div :style="`color:${dexFullInfo.get(destArmTypeID).decreasedInfo.color}`">{{dexFullInfo.get(destArmTypeID).decreasedInfo.name}}</div>
|
||||
<div class="f_tnum text-end">{{convNumberFormat(dexFullInfo.get(destArmTypeID).decreasedInfo.amount)}}</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div :style="`color:${dexFullInfo.get(destArmTypeID).currentInfo.color}`">{{dexFullInfo.get(destArmTypeID).currentInfo.name}}</div>
|
||||
<div class="f_tnum text-end">{{convNumberFormat(dexFullInfo.get(destArmTypeID).currentInfo.amount)}}</div>
|
||||
</template>
|
||||
<div>]</div>
|
||||
<div class="text-center">→</div>
|
||||
<div class="text-end">[</div>
|
||||
<div :style="`color:${dexFullInfo.get(destArmTypeID).afterInfo.get(srcArmTypeID).color}`">{{dexFullInfo.get(destArmTypeID).afterInfo.get(srcArmTypeID).name}}</div>
|
||||
<div class="f_tnum text-end">{{convNumberFormat(dexFullInfo.get(destArmTypeID).afterInfo.get(srcArmTypeID).amount)}}</div>
|
||||
<div>]</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
|
||||
declare const commandName: string;
|
||||
|
||||
type dexInfo = {
|
||||
amount: number;
|
||||
color: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
declare const procRes: {
|
||||
ownDexList: {
|
||||
armType: number;
|
||||
name: string;
|
||||
amount: number;
|
||||
}[];
|
||||
dexLevelList: dexInfo[];
|
||||
decreaseCoeff: number;
|
||||
convertCoeff: number;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
setup() {
|
||||
const srcArmTypeID = ref(procRes.ownDexList[0].armType);
|
||||
const destArmTypeID = ref(procRes.ownDexList[0].armType);
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
srcArmType: srcArmTypeID.value,
|
||||
destArmType: destArmTypeID.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
function getDexCall(dex: number): { color: string; name: string } {
|
||||
if (dex < 0) {
|
||||
throw `올바르지 않은 수치: ${dex}`;
|
||||
}
|
||||
|
||||
let color = "";
|
||||
let name = "";
|
||||
for (const nextDexLevel of procRes.dexLevelList) {
|
||||
if (dex < nextDexLevel.amount) {
|
||||
break;
|
||||
}
|
||||
color = nextDexLevel.color;
|
||||
name = nextDexLevel.name;
|
||||
}
|
||||
|
||||
return {
|
||||
color,
|
||||
name,
|
||||
};
|
||||
}
|
||||
|
||||
const dexFullInfo = new Map<
|
||||
number,
|
||||
{
|
||||
armType: number;
|
||||
name: string;
|
||||
amount: number;
|
||||
decresedAmount: number;
|
||||
currentInfo: dexInfo;
|
||||
decreasedInfo: dexInfo;
|
||||
afterInfo: Map<number, dexInfo>;
|
||||
}
|
||||
>();
|
||||
|
||||
for (const dexItem of procRes.ownDexList) {
|
||||
const amount = dexItem.amount;
|
||||
const currentInfo = { ...getDexCall(amount), amount };
|
||||
|
||||
const decresedAmount = amount * procRes.decreaseCoeff;
|
||||
const decresedAfterAmount = amount - decresedAmount;
|
||||
const decreasedInfo = {
|
||||
...getDexCall(decresedAfterAmount),
|
||||
amount: decresedAfterAmount,
|
||||
};
|
||||
|
||||
dexFullInfo.set(dexItem.armType, {
|
||||
...dexItem,
|
||||
decresedAmount,
|
||||
currentInfo,
|
||||
decreasedInfo,
|
||||
afterInfo: new Map(),
|
||||
});
|
||||
}
|
||||
|
||||
for (const [armType, dexItem] of dexFullInfo.entries()) {
|
||||
for (const [fromArmType, fromDexItem] of dexFullInfo.entries()) {
|
||||
let afterAmount = fromDexItem.decresedAmount * procRes.convertCoeff;
|
||||
if (armType != fromArmType) {
|
||||
afterAmount += dexItem.amount;
|
||||
} else {
|
||||
afterAmount += dexItem.decresedAmount;
|
||||
}
|
||||
|
||||
dexItem.afterInfo.set(fromArmType, {
|
||||
amount: afterAmount,
|
||||
...getDexCall(afterAmount),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function convDexFormat(value: dexInfo): string {
|
||||
const amount = convNumberFormat(value.amount);
|
||||
return `<span class="f_tnum" style="color:${value.color}">${value.name}</span>,${"\xa0".repeat(Math.max(0, 3 - value.name.length))} ${amount}`;
|
||||
}
|
||||
|
||||
function convNumberFormat(value: number): string {
|
||||
return Math.floor(value).toLocaleString();
|
||||
}
|
||||
|
||||
console.log(dexFullInfo);
|
||||
|
||||
return {
|
||||
...procRes,
|
||||
srcArmTypeID,
|
||||
destArmTypeID,
|
||||
dexFullInfo,
|
||||
getDexCall,
|
||||
commandName,
|
||||
submit,
|
||||
convDexFormat,
|
||||
convNumberFormat,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" v-model:searchable="searchable" />
|
||||
<div class="bg0">
|
||||
<div>
|
||||
국가에 임관합니다.<br />
|
||||
이미 임관/등용되었던 국가는 다시 임관할 수 없습니다.<br />
|
||||
바로 군주의 위치로 이동합니다.<br />
|
||||
임관할 국가를 목록에서 선택하세요.<br />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6 col-md-3">
|
||||
국가 :
|
||||
<SelectNation
|
||||
:nations="nationList"
|
||||
v-model="selectedNationID"
|
||||
:searchable="searchable"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-4 col-md-2 d-grid">
|
||||
<b-button @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nation-list">
|
||||
<div class="nation-header nation-row bg1 center">
|
||||
<div>국가명</div>
|
||||
<div>임관권유문</div>
|
||||
<div class="zoom-toggle d-grid">
|
||||
<b-button
|
||||
:pressed="toggleZoom"
|
||||
:variant="toggleZoom ? 'info' : 'secondary'"
|
||||
v-model="toggleZoom"
|
||||
@click="toggleZoom = !toggleZoom"
|
||||
>{{ toggleZoom ? "작게 보기" : "크게 보기" }}</b-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-for="[, nation] in nationList"
|
||||
:key="nation.id"
|
||||
:class="['nation-row', 's-border-b', toggleZoom ? 'on-zoom' : 'on-fit']"
|
||||
@click="selectedNationID = nation.id"
|
||||
>
|
||||
<div
|
||||
:style="{
|
||||
backgroundColor: nation.color,
|
||||
color: isBrightColor(nation.color) ? 'black' : 'white',
|
||||
fontSize: '1.3em',
|
||||
}"
|
||||
class="d-grid"
|
||||
>
|
||||
<div class="align-self-center center">{{ nation.name }}</div>
|
||||
</div>
|
||||
<div class="nation-scout-plate align-self-center">
|
||||
<div class="nation-scout-msg" v-html="nation.scoutMsg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import SelectNation from "@/processing/SelectNation.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import { procNationItem, procNationList, getProcSearchable } from "../processingRes";
|
||||
import { isBrightColor } from "@/util/isBrightColor";
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
nationList: procNationList;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
SelectNation,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
setup() {
|
||||
const nationList = new Map<number, procNationItem>();
|
||||
for (const nationItem of procRes.nationList) {
|
||||
nationList.set(nationItem.id, nationItem);
|
||||
}
|
||||
|
||||
const toggleZoom = ref(true);
|
||||
const selectedNationID = ref(procRes.nationList[0].id);
|
||||
|
||||
function selectedNation(nationID: number) {
|
||||
selectedNationID.value = nationID;
|
||||
}
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
destNationID: selectedNationID.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
return {
|
||||
searchable: getProcSearchable(),
|
||||
nationList: ref(nationList),
|
||||
selectedNationID,
|
||||
commandName,
|
||||
toggleZoom,
|
||||
isBrightColor,
|
||||
selectedNation,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@scss/common/break_500px.scss";
|
||||
|
||||
@include media-1000px {
|
||||
.nation-list .nation-row {
|
||||
display: grid;
|
||||
grid-template-columns: 130px 870px;
|
||||
}
|
||||
|
||||
.zoom-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.zoom-toggle > * {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-500px {
|
||||
.nation-list .nation-row.nation-header {
|
||||
display: grid;
|
||||
grid-template-columns: 3fr 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
|
||||
.zoom-toggle {
|
||||
grid-column: 2/3;
|
||||
grid-row: 1/3;
|
||||
}
|
||||
}
|
||||
|
||||
.nation-list .nation-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr minmax(1fr, calc(200px * 500 / 870));
|
||||
}
|
||||
|
||||
.on-fit {
|
||||
.nation-scout-plate {
|
||||
max-height: calc(200px * 500 / 870);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.nation-scout-msg {
|
||||
width: 870px;
|
||||
transform-origin: 0px 0px;
|
||||
transform: scale(calc(500 / 870));
|
||||
}
|
||||
}
|
||||
|
||||
.on-zoom {
|
||||
.nation-scout-plate {
|
||||
max-height: 200px;
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.nation-scout-msg {
|
||||
max-width: 870px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,190 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" v-model:searchable="searchable" />
|
||||
<div class="bg0">
|
||||
<div>
|
||||
장비를 구입하거나 매각합니다.<br />
|
||||
현재 구입 불가능한 것은 <span style="color: red">붉은색</span>으로
|
||||
표시됩니다.<br />
|
||||
현재 도시 치안 : {{ citySecu.toLocaleString() }} 현재
|
||||
자금 : {{ gold.toLocaleString() }}<br />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-8 col-md-4">
|
||||
장비:
|
||||
<v-multiselect
|
||||
v-model="selectedItemObj"
|
||||
class="selectedItemObj"
|
||||
:allow-empty="false"
|
||||
:options="forFind"
|
||||
:group-select="false"
|
||||
group-values="values"
|
||||
group-label="category"
|
||||
label="searchText"
|
||||
track-by="simpleName"
|
||||
:show-labels="false"
|
||||
selectLabel="선택(엔터)"
|
||||
selectGroupLabel=""
|
||||
selectedLabel="선택됨"
|
||||
deselectLabel="해제(엔터)"
|
||||
deselectGroupLabel=""
|
||||
placeholder="아이템 선택"
|
||||
:maxHeight="400"
|
||||
:searchable="searchable"
|
||||
>
|
||||
<template v-slot:option="props">
|
||||
<div
|
||||
v-if="props.option.html"
|
||||
v-html="
|
||||
`${props.option.html} ${
|
||||
props.option.notAvailable ? '(불가)' : ''
|
||||
}`
|
||||
"
|
||||
:style="{
|
||||
color: props.option.notAvailable ? 'red' : undefined,
|
||||
}"
|
||||
></div>
|
||||
<div
|
||||
v-else-if="props.option.simpleName"
|
||||
:style="{
|
||||
color: props.option.notAvailable ? 'red' : undefined,
|
||||
}"
|
||||
>
|
||||
{{ props.option.simpleName }}
|
||||
{{ props.option.notAvailable ? "(불가)" : undefined }}
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:singleLabel="props">
|
||||
[{{ ItemTypeNameMap[props.option.type] }}]
|
||||
{{ props.option.simpleName }}
|
||||
</template>
|
||||
</v-multiselect>
|
||||
</div>
|
||||
<div class="col-4 col-md-2 d-grid">
|
||||
<b-button @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="selectedItemObj.obj.id != NoneValue" class="row">
|
||||
<div class="col-4 col-md-2 align-self-center text-center">
|
||||
{{ selectedItemObj.obj.name }}
|
||||
</div>
|
||||
<div class="col" v-html="selectedItemObj.obj.info"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { entriesWithType } from "@util/entriesWithType";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import { getProcSearchable, procItemList, procItemType } from "../processingRes";
|
||||
import { ItemTypeKey, ItemTypeNameMap, NoneValue, ValuesOf } from "@/defs";
|
||||
import { convertSearch초성 } from "@/util/convertSearch초성";
|
||||
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
citySecu: number;
|
||||
gold: number;
|
||||
itemList: procItemList;
|
||||
ownItem: Record<ItemTypeKey, procItemType>;
|
||||
};
|
||||
|
||||
type selectItemKey = {
|
||||
type: ItemTypeKey;
|
||||
id: string;
|
||||
html: string;
|
||||
simpleName: string;
|
||||
searchText: string;
|
||||
notAvailable?: boolean;
|
||||
obj: procItemType;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
setup() {
|
||||
const forFind: {
|
||||
category: ValuesOf<typeof ItemTypeNameMap> | "판매";
|
||||
values: selectItemKey[];
|
||||
}[] = [];
|
||||
|
||||
//판매 처리
|
||||
const forSell: typeof forFind[0] = {
|
||||
category: "소유 물품 판매",
|
||||
values: [],
|
||||
};
|
||||
for (const [type, ownItem] of entriesWithType(procRes.ownItem)) {
|
||||
const typeName = ItemTypeNameMap[type];
|
||||
const itemNameHelp =
|
||||
ownItem.id == NoneValue
|
||||
? ""
|
||||
: ` [${ownItem.name}, ${(ownItem.cost / 2).toLocaleString()}금]`;
|
||||
forSell.values.push({
|
||||
type,
|
||||
id: NoneValue,
|
||||
html: `${typeName} 판매${itemNameHelp}`,
|
||||
simpleName: `${ownItem.id == NoneValue ? typeName : ownItem.name} 판매`,
|
||||
searchText: convertSearch초성(typeName).join("|"),
|
||||
notAvailable: ownItem.id == NoneValue,
|
||||
obj: ownItem,
|
||||
});
|
||||
}
|
||||
forFind.push(forSell);
|
||||
|
||||
const selectedItemObj = ref<selectItemKey>(forSell.values[0]);
|
||||
|
||||
for (const [type, itemSubList] of entriesWithType(procRes.itemList)) {
|
||||
const values: selectItemKey[] = [];
|
||||
const forBuy: typeof forFind[0] = {
|
||||
category: `${ItemTypeNameMap[type]} 구매`,
|
||||
values,
|
||||
};
|
||||
|
||||
for (const itemObj of itemSubList.values) {
|
||||
values.push({
|
||||
type,
|
||||
id: itemObj.id,
|
||||
html: `${
|
||||
itemObj.name
|
||||
} 구매 [${itemObj.cost.toLocaleString()}금, 필요 치안 ${itemObj.reqSecu.toLocaleString()}]`,
|
||||
simpleName: `${itemObj.name} 구매`,
|
||||
searchText: convertSearch초성(itemObj.name).join("|"),
|
||||
notAvailable:
|
||||
itemObj.reqSecu > procRes.citySecu || procRes.gold < itemObj.cost,
|
||||
obj: itemObj,
|
||||
});
|
||||
}
|
||||
|
||||
forFind.push(forBuy);
|
||||
}
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
itemType: selectedItemObj.value.type,
|
||||
itemCode: selectedItemObj.value.id,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
return {
|
||||
...procRes,
|
||||
searchable: getProcSearchable(),
|
||||
forFind,
|
||||
NoneValue,
|
||||
ItemTypeNameMap,
|
||||
selectedItemObj,
|
||||
commandName,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,202 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" v-model:searchable="searchable" />
|
||||
<div class="bg0">
|
||||
<div>
|
||||
장수를 따라 임관합니다.<br />
|
||||
이미 임관/등용되었던 국가는 다시 임관할 수 없습니다.<br />
|
||||
바로 군주의 위치로 이동합니다.<br />
|
||||
임관할 국가를 목록에서 선택하세요.<br />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-8 col-md-4">
|
||||
장수 :
|
||||
<SelectGeneral
|
||||
:generals="generalList"
|
||||
:groupByNation="nationList"
|
||||
:textHelper="textHelpGeneral"
|
||||
:searchable="searchable"
|
||||
v-model="selectedGeneralID"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-4 col-md-2 d-grid">
|
||||
<b-button variant="primary" @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nation-list">
|
||||
<div class="nation-header nation-row bg1 center">
|
||||
<div>국가명</div>
|
||||
<div>임관권유문</div>
|
||||
<div class="zoom-toggle d-grid">
|
||||
<b-button
|
||||
:pressed="toggleZoom"
|
||||
:variant="toggleZoom ? 'info' : 'secondary'"
|
||||
v-model="toggleZoom"
|
||||
@click="toggleZoom = !toggleZoom"
|
||||
>{{ toggleZoom ? "작게 보기" : "크게 보기" }}</b-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-for="[, nation] in nationList"
|
||||
:key="nation.id"
|
||||
:class="['nation-row', 's-border-b', toggleZoom ? 'on-zoom' : 'on-fit']"
|
||||
>
|
||||
<div
|
||||
:style="{
|
||||
backgroundColor: nation.color,
|
||||
color: isBrightColor(nation.color) ? 'black' : 'white',
|
||||
fontSize: '1.3em',
|
||||
}"
|
||||
class="d-grid"
|
||||
>
|
||||
<div class="align-self-center center">{{ nation.name }}</div>
|
||||
</div>
|
||||
<div class="nation-scout-plate align-self-center">
|
||||
<div class="nation-scout-msg" v-html="nation.scoutMsg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import SelectGeneral from "@/processing/SelectGeneral.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import {
|
||||
convertGeneralList,
|
||||
getProcSearchable,
|
||||
procGeneralItem,
|
||||
procGeneralKey,
|
||||
procGeneralRawItemList,
|
||||
procNationItem,
|
||||
procNationList,
|
||||
} from "../processingRes";
|
||||
import { getNpcColor } from "@/common_legacy";
|
||||
import { isBrightColor } from "@/util/isBrightColor";
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
generals: procGeneralRawItemList;
|
||||
generalsKey: procGeneralKey[];
|
||||
nationList: procNationList;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
SelectGeneral,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
setup() {
|
||||
const generalList = convertGeneralList(
|
||||
procRes.generalsKey,
|
||||
procRes.generals
|
||||
);
|
||||
|
||||
const toggleZoom = ref(true);
|
||||
const selectedGeneralID = ref(generalList[0].no);
|
||||
|
||||
function textHelpGeneral(gen: procGeneralItem): string {
|
||||
const nameColor = getNpcColor(gen.npc);
|
||||
const name = nameColor
|
||||
? `<span style="color:${nameColor}">${gen.name}</span>`
|
||||
: gen.name;
|
||||
return name;
|
||||
}
|
||||
|
||||
const nationList = new Map<number, procNationItem>();
|
||||
for (const nationItem of procRes.nationList) {
|
||||
nationList.set(nationItem.id, nationItem);
|
||||
}
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
destGeneralID: selectedGeneralID.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
return {
|
||||
searchable: getProcSearchable(),
|
||||
nationList: ref(nationList),
|
||||
selectedGeneralID,
|
||||
generalList,
|
||||
commandName,
|
||||
toggleZoom,
|
||||
isBrightColor,
|
||||
textHelpGeneral,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@scss/common/break_500px.scss";
|
||||
|
||||
@include media-1000px {
|
||||
.nation-list .nation-row {
|
||||
display: grid;
|
||||
grid-template-columns: 130px 870px;
|
||||
}
|
||||
|
||||
.zoom-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.zoom-toggle > * {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-500px {
|
||||
.nation-list .nation-row.nation-header {
|
||||
display: grid;
|
||||
grid-template-columns: 3fr 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
|
||||
.zoom-toggle {
|
||||
grid-column: 2/3;
|
||||
grid-row: 1/3;
|
||||
}
|
||||
}
|
||||
|
||||
.nation-list .nation-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr minmax(1fr, calc(200px * 500 / 870));
|
||||
}
|
||||
|
||||
.on-fit {
|
||||
.nation-scout-plate {
|
||||
max-height: calc(200px * 500 / 870);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.nation-scout-msg {
|
||||
width: 870px;
|
||||
transform-origin: 0px 0px;
|
||||
transform: scale(calc(500 / 870));
|
||||
}
|
||||
}
|
||||
|
||||
.on-zoom {
|
||||
.nation-scout-plate {
|
||||
max-height: 200px;
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.nation-scout-msg {
|
||||
max-width: 870px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,379 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" />
|
||||
<div class="bg0">
|
||||
<div>
|
||||
병사를 모집합니다.
|
||||
<template v-if="commandName == '징병'">
|
||||
훈련과 사기치는 낮지만 가격이 저렴합니다.<br />
|
||||
</template>
|
||||
<template v-else-if="commandName == '모병'">
|
||||
훈련과 사기치는 높지만 자금이 많이 듭니다.<br />
|
||||
</template>
|
||||
가능한 수보다 많게 입력하면 가능한 최대 병사를 모집합니다.<br />
|
||||
이미 병사가 있는 경우 추가 {{ commandName }}되며, 병종이 다를경우는 기존의
|
||||
병사는 소집해제됩니다. <br />
|
||||
현재 {{ commandName }} 가능한 병종은
|
||||
<span style="color: green">녹색</span>으로 표시되며, 현재
|
||||
{{ commandName }} 가능한 특수병종은
|
||||
<span style="color: limegreen">초록색</span>으로 표시됩니다.
|
||||
</div>
|
||||
<div class="crewTypeList" ref="defaultTarget">
|
||||
<div class="listFront">
|
||||
<div class="row gx-0 bg0">
|
||||
<div class="col-12 col-md-12 d-flex align-items-center">
|
||||
<div v-if="commandName == '모병'" class="text-center w-100">
|
||||
모병은 가격 2배의 자금이 소요됩니다.<br />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row text-center bg2 gx-0">
|
||||
<div class="col-4 col-md-2">현재 기술력 : {{ techLevel }}등급</div>
|
||||
<div class="col-4 col-md-2">
|
||||
현재 통솔 :
|
||||
<span
|
||||
:style="{
|
||||
color: leadership < fullLeadership ? 'red' : undefined,
|
||||
}"
|
||||
>{{ leadership }}</span
|
||||
>
|
||||
</div>
|
||||
<div class="col-4 col-md-2">최대 통솔 : {{ fullLeadership }}</div>
|
||||
<div class="col-4 col-md-2">
|
||||
현재 병종 : {{ crewTypeMap.get(currentCrewType).name }}
|
||||
</div>
|
||||
<div class="col-4 col-md-2">
|
||||
현재 병사 : {{ crew.toLocaleString() }}
|
||||
</div>
|
||||
<div class="col-4 col-md-2">
|
||||
현재 자금 : {{ gold.toLocaleString() }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="miniCrewPanel center bg0">
|
||||
<div
|
||||
class="crewTypeImg"
|
||||
:style="{
|
||||
background: '#222222 no-repeat center',
|
||||
backgroundImage: `url('${destCrewType.img}')`,
|
||||
backgroundSize: '64px',
|
||||
outline: 'solid 1px gray',
|
||||
height: '64px',
|
||||
}"
|
||||
></div>
|
||||
<div
|
||||
:style="{
|
||||
backgroundColor:
|
||||
(destCrewType.notAvailable
|
||||
? 'red'
|
||||
: destCrewType.reqTech == 0
|
||||
? 'green'
|
||||
: 'limegreen') + ' !important',
|
||||
height: '100%',
|
||||
}"
|
||||
class="d-grid"
|
||||
>
|
||||
<div style="margin: auto">
|
||||
{{ destCrewType.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
<div class="crewTypePanel">
|
||||
<b-button-group
|
||||
><b-button class="py-1" variant="dark" @click="beHalf"
|
||||
>절반</b-button
|
||||
><b-button class="py-1" variant="dark" @click="beFilled"
|
||||
>채우기</b-button
|
||||
><b-button class="py-1" variant="dark" @click="beFull"
|
||||
>가득</b-button
|
||||
></b-button-group
|
||||
>
|
||||
<div class="row">
|
||||
<div class="col mx-2">
|
||||
<div class="input-group my-0">
|
||||
<span class="input-group-text py-1">병력</span>
|
||||
<input
|
||||
type="number"
|
||||
class="form-control py-1 f_tnum px-0 text-end"
|
||||
v-model="amount"
|
||||
min="1"
|
||||
/>
|
||||
<span class="input-group-text py-1 f_tnum">00명</span>
|
||||
<span
|
||||
class="input-group-text py-1 f_tnum"
|
||||
style="
|
||||
text-align: right;
|
||||
min-width: 10ch;
|
||||
color: #303030;
|
||||
background-color: #ddd;
|
||||
"
|
||||
><div style="margin-left: auto">
|
||||
{{
|
||||
Math.ceil(
|
||||
amount * destCrewType.baseCost * goldCoeff
|
||||
).toLocaleString()
|
||||
}}금
|
||||
</div></span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
<b-button variant="primary" @click="submit">{{
|
||||
commandName
|
||||
}}</b-button>
|
||||
</div>
|
||||
<div class="listHeader crewTypeSubGrid text-center bg1">
|
||||
<div class="crewTypeImg">사진</div>
|
||||
<div class="crewTypeName">병종</div>
|
||||
<div>공격</div>
|
||||
<div>방어</div>
|
||||
<div>기동</div>
|
||||
<div>회피</div>
|
||||
<div>가격</div>
|
||||
<div>군량</div>
|
||||
<div class="crewTypePanel">병사 수</div>
|
||||
<div class="crewTypeBtn">행동</div>
|
||||
<div class="crewTypeInfo">특징</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="listMain">
|
||||
<template
|
||||
v-for="armCrewType in armCrewTypes"
|
||||
:key="armCrewType.armType"
|
||||
>
|
||||
<div class="s-border-b row gx-0">
|
||||
<div
|
||||
class="col-7 col-md-10 align-self-center px-3"
|
||||
style="font-size: 1.3em"
|
||||
>
|
||||
{{ armCrewType.armName }} 계열
|
||||
</div>
|
||||
<div class="col-5 col-md-2 d-grid">
|
||||
<b-button
|
||||
:variant="
|
||||
showNotAvailable.get(armCrewType.armType) ? 'warning' : 'dark'
|
||||
"
|
||||
:pressed="showNotAvailable.get(armCrewType.armType)"
|
||||
class="btn-sm"
|
||||
@click="toggleShowNotAvailable(armCrewType.armType)"
|
||||
>{{
|
||||
showNotAvailable.get(armCrewType.armType)
|
||||
? "선택 할 수 있는 병종만 보기"
|
||||
: "선택 할 수 없는 병종도 보기"
|
||||
}}</b-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<template v-for="crewType in armCrewType.values" :key="crewType.id">
|
||||
<CrewTypeItem
|
||||
v-if="
|
||||
showNotAvailable.get(armCrewType.armType) ||
|
||||
!crewType.notAvailable
|
||||
"
|
||||
:crewType="crewType"
|
||||
:leadership="fullLeadership"
|
||||
:commandName="commandName"
|
||||
:currentCrewType="currentCrewType"
|
||||
:crew="crew"
|
||||
:goldCoeff="goldCoeff"
|
||||
@submitOutput="trySubmit"
|
||||
@click="
|
||||
destCrewType = crewTypeMap.get(crewType.id);
|
||||
beFilled();
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import CrewTypeItem from "@/processing/CrewTypeItem.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import { procArmTypeItem, procCrewTypeItem } from "../processingRes";
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
relYear: number;
|
||||
year: number;
|
||||
tech: number;
|
||||
techLevel: number;
|
||||
startYear: number;
|
||||
goldCoeff: number;
|
||||
leadership: number;
|
||||
fullLeadership: number;
|
||||
armCrewTypes: procArmTypeItem[];
|
||||
currentCrewType: number;
|
||||
crew: number;
|
||||
gold: number;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
CrewTypeItem,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
setup() {
|
||||
const amount = ref(procRes.fullLeadership - Math.floor(procRes.crew / 100));
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
amount: amount.value * 100,
|
||||
crewType: destCrewType.value.id,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
const showNotAvailable = ref(new Map<number, boolean>());
|
||||
|
||||
const crewTypeMap = new Map<number, procCrewTypeItem>();
|
||||
for (const armType of procRes.armCrewTypes) {
|
||||
showNotAvailable.value.set(armType.armType, false);
|
||||
for (const crewType of armType.values) {
|
||||
crewTypeMap.set(crewType.id, crewType);
|
||||
}
|
||||
}
|
||||
|
||||
const destCrewType = ref(unwrap(crewTypeMap.get(procRes.currentCrewType)));
|
||||
|
||||
function beHalf() {
|
||||
amount.value = Math.ceil(procRes.fullLeadership * 0.5);
|
||||
}
|
||||
|
||||
function beFilled() {
|
||||
if (destCrewType.value.id == procRes.currentCrewType) {
|
||||
amount.value = Math.max(
|
||||
1,
|
||||
procRes.fullLeadership - Math.floor(procRes.crew / 100)
|
||||
);
|
||||
} else {
|
||||
amount.value = procRes.fullLeadership;
|
||||
}
|
||||
}
|
||||
|
||||
function beFull() {
|
||||
amount.value = Math.floor(procRes.fullLeadership * 1.2);
|
||||
}
|
||||
|
||||
function trySubmit(e: Event, inAmount: number, inCrewType: number) {
|
||||
e.preventDefault();
|
||||
amount.value = inAmount;
|
||||
destCrewType.value = unwrap(crewTypeMap.get(inCrewType));
|
||||
void submit(e);
|
||||
}
|
||||
|
||||
function toggleShowNotAvailable(armType: number) {
|
||||
showNotAvailable.value.set(
|
||||
armType,
|
||||
!(showNotAvailable.value.get(armType) ?? 0)
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
destCrewType,
|
||||
amount,
|
||||
showNotAvailable,
|
||||
...procRes,
|
||||
crewTypeMap,
|
||||
commandName,
|
||||
beHalf,
|
||||
beFilled,
|
||||
beFull,
|
||||
submit,
|
||||
toggleShowNotAvailable,
|
||||
trySubmit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@scss/common/break_500px.scss";
|
||||
|
||||
.crewTypeSubGrid {
|
||||
display: grid;
|
||||
align-items: center;
|
||||
}
|
||||
.crewTypeItem .crewTypeImg {
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.crewTypeInfo {
|
||||
padding-left: 0.5em;
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
|
||||
@include media-1000px {
|
||||
.crewTypeSubGrid {
|
||||
grid-template-columns: 64px 1.5fr 1fr 1fr 1fr 1fr 1fr 1fr 250px 1.5fr 270px;
|
||||
}
|
||||
|
||||
.miniCrewPanel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.only500pxMode {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-500px {
|
||||
.only1000pxMode {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.listFront {
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
}
|
||||
.crewTypeSubGrid {
|
||||
grid-template-columns: 64px 1.5fr 1fr 1fr 1fr 270px;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.crewTypeImg {
|
||||
grid-column: 1 / 2;
|
||||
grid-row: 1 / 3;
|
||||
}
|
||||
.crewTypeName {
|
||||
grid-row: 1/ 3;
|
||||
}
|
||||
|
||||
.crewTypeInfo {
|
||||
grid-column: -2 / -1;
|
||||
grid-row: 1 / 3;
|
||||
}
|
||||
|
||||
.crewTypePanel {
|
||||
display: none;
|
||||
}
|
||||
.crewTypeBtn {
|
||||
display: none;
|
||||
}
|
||||
.crewTypeBtn > button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.miniCrewPanel .crewTypePanel {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.miniCrewPanel {
|
||||
display: grid;
|
||||
grid-template-columns: 64px 1.5fr 0.5fr 270px 0.5fr 2fr;
|
||||
grid-template-rows: 64px;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style scoped>
|
||||
</style>
|
||||
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" />
|
||||
<div class="bg0">
|
||||
<div>
|
||||
자신의 자금이나 군량을 국가 재산으로 헌납합니다.
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-2 col-md-1">
|
||||
자원 :
|
||||
<b-button-group>
|
||||
<b-button :pressed="isGold" @click="isGold = true">금</b-button>
|
||||
<b-button :pressed="!isGold" @click="isGold = false">쌀</b-button>
|
||||
</b-button-group>
|
||||
</div>
|
||||
<div class="col-7 col-md-4">
|
||||
금액 :
|
||||
<SelectAmount
|
||||
:amountGuide="amountGuide"
|
||||
v-model="amount"
|
||||
:maxAmount="maxAmount"
|
||||
:minAmount="minAmount"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 col-md-2 d-grid">
|
||||
<b-button variant="primary" @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import SelectAmount from "@/processing/SelectAmount.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
minAmount: number;
|
||||
maxAmount: number;
|
||||
amountGuide: number[];
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
SelectAmount,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
setup() {
|
||||
const amount = ref(1000);
|
||||
const isGold = ref(true);
|
||||
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
amount: amount.value,
|
||||
isGold: isGold.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
return {
|
||||
amount,
|
||||
isGold,
|
||||
minAmount: ref(procRes.minAmount),
|
||||
maxAmount: ref(procRes.maxAmount),
|
||||
amountGuide: procRes.amountGuide,
|
||||
commandName,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,44 @@
|
||||
import { default as che_건국 } from "./che_건국.vue";
|
||||
import { default as che_군량매매 } from "./che_군량매매.vue";
|
||||
import { default as che_등용 } from "./che_등용.vue";
|
||||
import { default as che_선양 } from "./che_선양.vue";
|
||||
import { default as che_숙련전환 } from "./che_숙련전환.vue";
|
||||
import { default as che_임관 } from "./che_임관.vue";
|
||||
import { default as che_장비매매 } from "./che_장비매매.vue";
|
||||
import { default as che_장수대상임관 } from "./che_장수대상임관.vue";
|
||||
import { default as che_징병 } from "./che_징병.vue";
|
||||
import { default as che_헌납 } from "./che_헌납.vue";
|
||||
|
||||
import { default as ProcessCity } from "../ProcessCity.vue";
|
||||
import { default as ProcessGeneralAmount } from "../ProcessGeneralAmount.vue";
|
||||
|
||||
|
||||
//TODO: 자주 쓰는 녀석들은 Slot으로 변경
|
||||
|
||||
export const commandMap: Record<string, typeof ProcessCity> = {
|
||||
che_강행: ProcessCity,
|
||||
che_군량매매,
|
||||
che_건국,
|
||||
che_등용,
|
||||
che_모병: che_징병,
|
||||
che_선동: ProcessCity,
|
||||
che_선양,
|
||||
che_숙련전환,
|
||||
che_이동: ProcessCity,
|
||||
che_임관,
|
||||
che_장비매매,
|
||||
che_장수대상임관,
|
||||
che_징병,
|
||||
che_증여: ProcessGeneralAmount,
|
||||
che_첩보: ProcessCity,
|
||||
che_출병: ProcessCity,
|
||||
che_탈취: ProcessCity,
|
||||
che_파괴: ProcessCity,
|
||||
che_화계: ProcessCity,
|
||||
che_헌납,
|
||||
}
|
||||
|
||||
/*
|
||||
- 항목들
|
||||
고유 양식 - 장비매매
|
||||
*/
|
||||
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" />
|
||||
<div class="bg0">
|
||||
<div>
|
||||
국기를 변경합니다. 단 1회 가능합니다.<br>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6 col-md-3">
|
||||
색상 :
|
||||
<ColorSelect :colors="colors" v-model="selectedColorID" />
|
||||
</div>
|
||||
<div class="col-4 col-md-2 d-grid">
|
||||
<b-button @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import ColorSelect from "@/processing/SelectColor.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
colors: string[],
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
ColorSelect,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
setup() {
|
||||
|
||||
const selectedColorID = ref(0);
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
colorType: selectedColorID.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
return {
|
||||
selectedColorID,
|
||||
colors: procRes.colors,
|
||||
commandName,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" />
|
||||
<div class="bg0">
|
||||
<div>
|
||||
나라의 이름을 바꿉니다. 황제가 된 후 1회 가능합니다.<br />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6 col-md-3">
|
||||
국명 :
|
||||
<b-form-input maxlength="18" v-model="destNationName"/>
|
||||
</div>
|
||||
<div class="col-4 col-md-2 d-grid">
|
||||
<b-button @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
|
||||
declare const commandName: string;
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
setup() {
|
||||
const destNationName = ref("");
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
nationName: destNationName.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
return {
|
||||
destNationName,
|
||||
commandName,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,157 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" v-model:searchable="searchable" />
|
||||
<div class="bg0">
|
||||
<MapLegacyTemplate
|
||||
:isDetailMap="false"
|
||||
:clickableAll="true"
|
||||
:neutralView="true"
|
||||
:useCachedMap="true"
|
||||
:mapTheme="mapTheme"
|
||||
v-model="selectedCityObj"
|
||||
/>
|
||||
<div>
|
||||
타국에게 원조합니다.<br />
|
||||
작위별로 금액 제한이 있습니다.<br /><br />
|
||||
<ul>
|
||||
<template v-for="({ text, amount }, level) in levelInfo" :key="level">
|
||||
<li>
|
||||
<span
|
||||
:style="{
|
||||
width: '4em',
|
||||
display: 'inline-block',
|
||||
...(level != currentNationLevel
|
||||
? {}
|
||||
: {
|
||||
textDecoration: 'underline',
|
||||
fontWeight: 'bold',
|
||||
}),
|
||||
}"
|
||||
>{{ text }}</span
|
||||
>: {{ amount.toLocaleString() }}
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<br />
|
||||
원조할 국가를 목록에서 선택하세요.<br /><br />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6 col-md-3">
|
||||
국가 :
|
||||
<SelectNation :nations="nationList" v-model="selectedNationID" :searchable="searchable" />
|
||||
</div>
|
||||
<div class="col-6 col-md-0"></div>
|
||||
<div class="col-8 col-md-4">
|
||||
금 :
|
||||
<SelectAmount
|
||||
:amountGuide="amountGuide"
|
||||
v-model="goldAmount"
|
||||
:step="10"
|
||||
:maxAmount="maxAmount"
|
||||
:minAmount="minAmount"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-8 col-md-4">
|
||||
쌀 :
|
||||
<SelectAmount
|
||||
:amountGuide="amountGuide"
|
||||
v-model="riceAmount"
|
||||
:step="10"
|
||||
:maxAmount="maxAmount"
|
||||
:minAmount="minAmount"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-4 col-md-2 d-grid">
|
||||
<b-button variant="primary" @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import MapLegacyTemplate, {
|
||||
MapCityParsed,
|
||||
} from "@/components/MapLegacyTemplate.vue";
|
||||
import SelectNation from "@/processing/SelectNation.vue";
|
||||
import SelectAmount from "@/processing/SelectAmount.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import { getProcSearchable, procNationItem, procNationList } from "../processingRes";
|
||||
declare const mapTheme: string;
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
nationList: procNationList;
|
||||
currentNationLevel: number;
|
||||
levelInfo: Record<
|
||||
number,
|
||||
{
|
||||
text: string;
|
||||
amount: number;
|
||||
}
|
||||
>;
|
||||
minAmount: number;
|
||||
maxAmount: number;
|
||||
amountGuide: number[];
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MapLegacyTemplate,
|
||||
SelectNation,
|
||||
SelectAmount,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
watch: {
|
||||
selectedCityObj(city: MapCityParsed) {
|
||||
if (!city.nationID) {
|
||||
return;
|
||||
}
|
||||
this.selectedNationID = city.nationID;
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const nationList = new Map<number, procNationItem>();
|
||||
for (const nationItem of procRes.nationList) {
|
||||
nationList.set(nationItem.id, nationItem);
|
||||
}
|
||||
|
||||
const goldAmount = ref(procRes.minAmount);
|
||||
const riceAmount = ref(procRes.minAmount);
|
||||
|
||||
const selectedNationID = ref(procRes.nationList[0]?.id);
|
||||
const selectedCityObj = ref(); //mapping용
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
amountList: [goldAmount.value, riceAmount.value],
|
||||
destNationID: selectedNationID.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
return {
|
||||
searchable: getProcSearchable(),
|
||||
mapTheme,
|
||||
goldAmount,
|
||||
riceAmount,
|
||||
nationList,
|
||||
selectedNationID,
|
||||
selectedCityObj,
|
||||
currentNationLevel: procRes.currentNationLevel,
|
||||
levelInfo: procRes.levelInfo,
|
||||
minAmount: ref(procRes.minAmount),
|
||||
maxAmount: ref(procRes.maxAmount),
|
||||
amountGuide: procRes.amountGuide,
|
||||
commandName,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" v-model:searchable="searchable" />
|
||||
<div class="bg0">
|
||||
<MapLegacyTemplate
|
||||
:isDetailMap="false"
|
||||
:clickableAll="true"
|
||||
:neutralView="true"
|
||||
:useCachedMap="true"
|
||||
:mapTheme="mapTheme"
|
||||
v-model="selectedCityObj"
|
||||
/>
|
||||
|
||||
<div>
|
||||
선택된 도시로 아국 장수를 발령합니다.<br />
|
||||
아국 도시로만 발령이 가능합니다.<br />
|
||||
목록을 선택하거나 도시를 클릭하세요.<br />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6">
|
||||
장수 :
|
||||
<SelectGeneral
|
||||
:cities="citiesMap"
|
||||
:generals="generalList"
|
||||
:troops="troops"
|
||||
:textHelper="textHelpGeneral"
|
||||
:searchable="searchable"
|
||||
v-model="selectedGeneralID"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 col-md-4">
|
||||
도시 :
|
||||
<SelectCity :cities="citiesMap" v-model="selectedCityID" :searchable="searchable" />
|
||||
</div>
|
||||
<div class="col-4 col-md-2 d-grid">
|
||||
<b-button variant="primary" @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import MapLegacyTemplate, {
|
||||
MapCityParsed,
|
||||
} from "@/components/MapLegacyTemplate.vue";
|
||||
import SelectCity from "@/processing/SelectCity.vue";
|
||||
import SelectGeneral from "@/processing/SelectGeneral.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import {
|
||||
convertGeneralList,
|
||||
getProcSearchable,
|
||||
procGeneralItem,
|
||||
procGeneralKey,
|
||||
procGeneralRawItemList,
|
||||
procTroopList,
|
||||
} from "../processingRes";
|
||||
import { getNpcColor } from "@/common_legacy";
|
||||
declare const mapTheme: string;
|
||||
declare const currentCity: number;
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
distanceList: Record<number, number[]>;
|
||||
cities: [number, string][];
|
||||
troops: procTroopList;
|
||||
generals: procGeneralRawItemList;
|
||||
generalsKey: procGeneralKey[];
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MapLegacyTemplate,
|
||||
SelectCity,
|
||||
SelectGeneral,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
watch: {
|
||||
selectedCityObj(city: MapCityParsed) {
|
||||
this.selectedCityID = city.id;
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const citiesMap = new Map<
|
||||
number,
|
||||
{
|
||||
name: string;
|
||||
info?: string;
|
||||
}
|
||||
>();
|
||||
for (const [id, name] of procRes.cities) {
|
||||
citiesMap.set(id, { name });
|
||||
}
|
||||
|
||||
const generalList = convertGeneralList(
|
||||
procRes.generalsKey,
|
||||
procRes.generals
|
||||
);
|
||||
const selectedCityID = ref(currentCity);
|
||||
|
||||
function selectedCity(cityID: number) {
|
||||
selectedCityID.value = cityID;
|
||||
}
|
||||
|
||||
const selectedGeneralID = ref(generalList[0].no);
|
||||
|
||||
function textHelpGeneral(gen: procGeneralItem): string{
|
||||
const troops = (!gen.troopID)?'':`,${procRes.troops[gen.troopID].name}`;
|
||||
const nameColor = getNpcColor(gen.npc);
|
||||
const name = nameColor?`<span style="color:${nameColor}">${gen.name}</span>`:gen.name;
|
||||
return `${name} [${citiesMap.get(unwrap(gen.cityID))?.name}${troops}] (${gen.leadership}/${gen.leadership}/${gen.intel}) <병${unwrap(gen.crew).toLocaleString()}/훈${gen.train}/사${gen.atmos}>`;
|
||||
}
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
destCityID: selectedCityID.value,
|
||||
destGeneralID: selectedGeneralID.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
|
||||
// title: `${gen.name}[${this.cities.get(gen.cityID)?.name}] (${gen.leadership}/${gen.leadership}/${gen.intel}) <병${gen.crew.toLocaleString()}/훈${gen.train}/사${gen.atmos}`,
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
searchable: getProcSearchable(),
|
||||
mapTheme: ref(mapTheme),
|
||||
citiesMap: ref(citiesMap),
|
||||
selectedCityID,
|
||||
selectedGeneralID,
|
||||
selectedCityObj: ref(undefined as MapCityParsed | undefined),
|
||||
distanceList: procRes.distanceList,
|
||||
troops: procRes.troops,
|
||||
generalList,
|
||||
commandName,
|
||||
selectedCity,
|
||||
textHelpGeneral,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,138 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" v-model:searchable="searchable" />
|
||||
<div class="bg0">
|
||||
<MapLegacyTemplate
|
||||
:isDetailMap="false"
|
||||
:clickableAll="true"
|
||||
:neutralView="true"
|
||||
:useCachedMap="true"
|
||||
:mapTheme="mapTheme"
|
||||
v-model="selectedCityObj"
|
||||
/>
|
||||
|
||||
<div>
|
||||
타국에게 불가침을 제의합니다.<br />
|
||||
제의할 국가를 목록에서 선택하세요.<br />
|
||||
불가침 기한 다음 달부터 선포 가능합니다.<br />
|
||||
현재 제의가 불가능한 국가는
|
||||
<span style="color: red">붉은색</span>으로 표시됩니다.<br />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4 col-md-3">
|
||||
국가 :
|
||||
<SelectNation :nations="nationList" v-model="selectedNationID" :searchable="searchable" />
|
||||
</div>
|
||||
<div class="col-5 col-md-3">
|
||||
기간 :
|
||||
<div class="input-group">
|
||||
<b-form-select class="text-end selectedYear" v-model="selectedYear"
|
||||
><b-form-select-option
|
||||
v-for="yearP in maxYear - minYear + 1"
|
||||
:key="yearP"
|
||||
:value="yearP + minYear - 1"
|
||||
>{{ yearP + minYear - 1 }}</b-form-select-option
|
||||
>
|
||||
</b-form-select>
|
||||
<span class="input-group-text px-2">년</span>
|
||||
<b-form-select class="text-center" v-model="selectedMonth"
|
||||
><b-form-select-option v-for="month in 12" :key="month" :value="month">{{
|
||||
month
|
||||
}}</b-form-select-option>
|
||||
</b-form-select>
|
||||
<span class="input-group-text px-2">월</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3 col-md-2 d-grid">
|
||||
<b-button @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import MapLegacyTemplate, {
|
||||
MapCityParsed,
|
||||
} from "@/components/MapLegacyTemplate.vue";
|
||||
import SelectNation from "@/processing/SelectNation.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import { getProcSearchable, procNationItem, procNationList } from "../processingRes";
|
||||
declare const mapTheme: string;
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
nationList: procNationList;
|
||||
startYear: number;
|
||||
minYear: number;
|
||||
maxYear: number;
|
||||
month: number;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MapLegacyTemplate,
|
||||
SelectNation,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
watch: {
|
||||
selectedCityObj(city: MapCityParsed) {
|
||||
if (!city.nationID) {
|
||||
return;
|
||||
}
|
||||
this.selectedNationID = city.nationID;
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const nationList = new Map<number, procNationItem>();
|
||||
for (const nationItem of procRes.nationList) {
|
||||
nationList.set(nationItem.id, nationItem);
|
||||
}
|
||||
|
||||
const selectedNationID = ref(procRes.nationList[0].id);
|
||||
const selectedCityObj = ref(); //mapping용
|
||||
|
||||
const selectedYear = ref(procRes.minYear);
|
||||
const selectedMonth = ref(procRes.month);
|
||||
|
||||
function selectedNation(nationID: number) {
|
||||
selectedNationID.value = nationID;
|
||||
}
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
destNationID: selectedNationID.value,
|
||||
year: selectedYear.value,
|
||||
month: selectedMonth.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
return {
|
||||
searchable: getProcSearchable(),
|
||||
...procRes,
|
||||
selectedYear,
|
||||
selectedMonth,
|
||||
mapTheme: ref(mapTheme),
|
||||
nationList: ref(nationList),
|
||||
selectedCityObj,
|
||||
selectedNationID,
|
||||
commandName,
|
||||
selectedNation,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.selectedYear{
|
||||
width:32%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,139 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" v-model:searchable="searchable" />
|
||||
<div class="bg0">
|
||||
<MapLegacyTemplate
|
||||
:isDetailMap="false"
|
||||
:clickableAll="true"
|
||||
:neutralView="true"
|
||||
:useCachedMap="true"
|
||||
:mapTheme="mapTheme"
|
||||
v-model="selectedCityObj"
|
||||
/>
|
||||
<div>
|
||||
선택된 국가에 피장파장을 발동합니다.<br />
|
||||
지정한 전략을 상대국이
|
||||
{{ delayCnt }}턴 동안 사용할 수 없게됩니다.<br />
|
||||
대신 아국은 지정한 전략을 {{ postReqTurn }}턴 동안 사용할 수 없습니다.<br />
|
||||
선포, 전쟁중인 상대국에만 가능합니다.<br />
|
||||
상대 국가를 목록에서 선택하세요.<br />
|
||||
현재 피장파장이 불가능한 국가는
|
||||
<span style="color: red">붉은색</span>으로 표시됩니다.<br />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6 col-md-3">
|
||||
국가 :
|
||||
<SelectNation :nations="nationList" v-model="selectedNationID" :searchable="searchable" />
|
||||
</div>
|
||||
<div class="col-3 col-md-2">
|
||||
<label>전략 :</label>
|
||||
<b-form-select
|
||||
:options="commandTypesOption"
|
||||
v-model="selectedCommandID"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 col-md-2 d-grid">
|
||||
<b-button @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import MapLegacyTemplate, {
|
||||
MapCityParsed,
|
||||
} from "@/components/MapLegacyTemplate.vue";
|
||||
import SelectNation from "@/processing/SelectNation.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import { getProcSearchable, procNationItem, procNationList } from "../processingRes";
|
||||
declare const mapTheme: string;
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
nationList: procNationList;
|
||||
startYear: number;
|
||||
delayCnt: number;
|
||||
postReqTurn: number;
|
||||
availableCommandTypeList: Record<
|
||||
number,
|
||||
{
|
||||
name: string;
|
||||
remainTurn: number;
|
||||
}
|
||||
>;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MapLegacyTemplate,
|
||||
SelectNation,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
watch: {
|
||||
selectedCityObj(city: MapCityParsed) {
|
||||
if (!city.nationID) {
|
||||
return;
|
||||
}
|
||||
this.selectedNationID = city.nationID;
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const nationList = new Map<number, procNationItem>();
|
||||
for (const nationItem of procRes.nationList) {
|
||||
nationList.set(nationItem.id, nationItem);
|
||||
}
|
||||
|
||||
const selectedNationID = ref(procRes.nationList[0].id);
|
||||
const selectedCityObj = ref(); //mapping용
|
||||
|
||||
const commandTypesOption: { html: string; value: string }[] = [];
|
||||
for (const [commandTypeID, commandTypeInfo] of Object.entries(procRes.availableCommandTypeList)) {
|
||||
const notAvailable = commandTypeInfo.remainTurn > 0;
|
||||
const notAvailableText = notAvailable?' (불가)':'';
|
||||
const name = `${commandTypeInfo.name}${notAvailableText}`;
|
||||
const html = notAvailable?`<span style='color:red;'>${name}</span>`:name;
|
||||
commandTypesOption.push({
|
||||
html,
|
||||
value: commandTypeID,
|
||||
});
|
||||
}
|
||||
|
||||
const selectedCommandID = ref(
|
||||
Object.keys(procRes.availableCommandTypeList)[0]
|
||||
);
|
||||
|
||||
function selectedNation(nationID: number) {
|
||||
selectedNationID.value = nationID;
|
||||
}
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
destNationID: selectedNationID.value,
|
||||
commandType: selectedCommandID.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
return {
|
||||
searchable: getProcSearchable(),
|
||||
...procRes,
|
||||
selectedCommandID,
|
||||
commandTypesOption,
|
||||
mapTheme: ref(mapTheme),
|
||||
nationList: ref(nationList),
|
||||
selectedCityObj,
|
||||
selectedNationID,
|
||||
commandName,
|
||||
selectedNation,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,36 @@
|
||||
import { default as che_국기변경 } from "./che_국기변경.vue";
|
||||
import { default as che_국호변경 } from "./che_국호변경.vue";
|
||||
import { default as che_물자원조 } from "./che_물자원조.vue";
|
||||
import { default as che_불가침제의 } from "./che_불가침제의.vue";
|
||||
import { default as che_피장파장 } from "./che_피장파장.vue";
|
||||
|
||||
import { default as ProcessNation } from "../ProcessNation.vue";
|
||||
import { default as ProcessGeneralAmount } from "../ProcessGeneralAmount.vue";
|
||||
import { default as ProcessGeneralCity } from "./che_발령.vue";
|
||||
import { default as ProcessCity } from "../ProcessCity.vue";
|
||||
|
||||
export const commandMap: Record<string, typeof ProcessNation> = {
|
||||
che_국기변경,
|
||||
che_국호변경,
|
||||
che_급습: ProcessNation,
|
||||
che_몰수: ProcessGeneralAmount,
|
||||
che_물자원조,
|
||||
che_발령: ProcessGeneralCity,
|
||||
che_백성동원: ProcessCity,
|
||||
che_불가침제의,
|
||||
che_불가침파기제의: ProcessNation,
|
||||
che_선전포고: ProcessNation,
|
||||
che_수몰: ProcessCity,
|
||||
che_이호경식: ProcessNation,
|
||||
che_종전제의: ProcessNation,
|
||||
che_천도: ProcessCity,
|
||||
che_초토화: ProcessCity,
|
||||
che_포상: ProcessGeneralAmount,
|
||||
che_피장파장,
|
||||
che_허보: ProcessCity,
|
||||
}
|
||||
|
||||
/*
|
||||
- 항목들
|
||||
고유 양식 - 불가침제의
|
||||
*/
|
||||
@@ -0,0 +1,157 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" v-model:searchable="searchable" />
|
||||
<div class="bg0">
|
||||
<MapLegacyTemplate
|
||||
:isDetailMap="false"
|
||||
:clickableAll="true"
|
||||
:neutralView="true"
|
||||
:useCachedMap="true"
|
||||
:mapTheme="mapTheme"
|
||||
v-model="selectedCityObj"
|
||||
/>
|
||||
|
||||
<div v-if="commandName == '강행'">
|
||||
선택된 도시로 강행합니다.<br />
|
||||
최대 3칸내 도시로만 강행이 가능합니다.<br />
|
||||
목록을 선택하거나 도시를 클릭하세요.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '이동'">
|
||||
선택된 도시로 이동합니다.<br />
|
||||
인접 도시로만 이동이 가능합니다.<br />
|
||||
목록을 선택하거나 도시를 클릭하세요.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '출병'">
|
||||
선택된 도시를 향해 침공을 합니다.<br />
|
||||
침공 경로에 적군의 도시가 있다면 전투를 벌입니다.<br />
|
||||
목록을 선택하거나 도시를 클릭하세요.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '첩보'">
|
||||
선택된 도시에 첩보를 실행합니다.<br />
|
||||
인접도시일 경우 많은 정보를 얻을 수 있습니다.<br />
|
||||
목록을 선택하거나 도시를 클릭하세요.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName in { 화계: 1, 탈취: 1, 파괴: 1, 선동: 1 }">
|
||||
선택된 도시에 {{ commandName
|
||||
}}{{ JosaPick(commandName, "을") }} 실행합니다.<br />
|
||||
목록을 선택하거나 도시를 클릭하세요.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '수몰'">
|
||||
선택된 도시에 수몰을 발동합니다.<br />
|
||||
전쟁중인 상대국 도시만 가능합니다.<br />
|
||||
목록을 선택하거나 도시를 클릭하세요.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '백성동원'">
|
||||
선택된 도시에 백성을 동원해 성벽을 쌓습니다.<br />
|
||||
아국 도시만 가능합니다.<br />
|
||||
목록을 선택하거나 도시를 클릭하세요.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '천도'">
|
||||
선택된 도시로 천도합니다.<br />
|
||||
현재 수도에서 연결된 도시만 가능하며, 1+2×거리만큼의 턴이 필요합니다.<br />
|
||||
목록을 선택하거나 도시를 클릭하세요.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '허보'">
|
||||
선택된 도시에 허보를 발동합니다.<br />
|
||||
전쟁중인 상대국 도시만 가능합니다.<br />
|
||||
목록을 선택하거나 도시를 클릭하세요.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '초토화'">
|
||||
선택된 도시를 초토화 시킵니다.<br />
|
||||
도시가 공백지가 되며, 도시의 인구, 내정 상태에 따라 상당량의 국고가
|
||||
확보됩니다.<br />
|
||||
국가의 수뇌들은 명성을 잃고, 모든 장수들은 배신 수치가 1 증가합니다.<br />
|
||||
목록을 선택하거나 도시를 클릭하세요.<br />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4 col-md-2">
|
||||
도시:
|
||||
<SelectCity :cities="citiesMap" v-model="selectedCityID" :searchable="searchable" />
|
||||
</div>
|
||||
<div class="col-4 col-md-2 d-grid">
|
||||
<b-button @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
<CityBasedOnDistance
|
||||
:citiesMap="citiesMap"
|
||||
:distanceList="distanceList"
|
||||
@selected="selected"
|
||||
/>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import MapLegacyTemplate, {
|
||||
MapCityParsed,
|
||||
} from "@/components/MapLegacyTemplate.vue";
|
||||
import SelectCity from "@/processing/SelectCity.vue";
|
||||
import CityBasedOnDistance from "@/processing/CitiesBasedOnDistance.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import { pick as JosaPick } from "@util/JosaUtil";
|
||||
import { getProcSearchable } from "./processingRes";
|
||||
declare const mapTheme: string;
|
||||
declare const currentCity: number;
|
||||
declare const commandName: string;
|
||||
declare const procRes: {
|
||||
distanceList: Record<number, number[]>;
|
||||
cities: [number, string][];
|
||||
};
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MapLegacyTemplate,
|
||||
SelectCity,
|
||||
CityBasedOnDistance,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
watch: {
|
||||
selectedCityObj(city: MapCityParsed) {
|
||||
this.selectedCityID = city.id;
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const citiesMap = new Map<
|
||||
number,
|
||||
{
|
||||
name: string;
|
||||
info?: string;
|
||||
}
|
||||
>();
|
||||
for (const [id, name] of procRes.cities) {
|
||||
citiesMap.set(id, { name });
|
||||
}
|
||||
|
||||
const selectedCityID = ref(currentCity);
|
||||
|
||||
function selected(cityID: number) {
|
||||
selectedCityID.value = cityID;
|
||||
}
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
destCityID: selectedCityID.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
return {
|
||||
searchable: getProcSearchable(),
|
||||
mapTheme: ref(mapTheme),
|
||||
citiesMap: ref(citiesMap),
|
||||
selectedCityID,
|
||||
selectedCityObj: ref(undefined as MapCityParsed | undefined),
|
||||
distanceList: procRes.distanceList,
|
||||
commandName,
|
||||
JosaPick,
|
||||
selected,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" v-model:searchable="searchable" />
|
||||
<div class="bg0">
|
||||
<div v-if="commandName == '몰수'">
|
||||
장수의 자금이나 군량을 몰수합니다.<br />
|
||||
몰수한것은 국가재산으로 귀속됩니다.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '포상'">
|
||||
국고로 장수에게 자금이나 군량을 지급합니다.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '증여'">
|
||||
자신의 자금이나 군량을 다른 장수에게 증여합니다.<br>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-5">
|
||||
장수 :
|
||||
<SelectGeneral
|
||||
:cities="citiesMap"
|
||||
:generals="generalList"
|
||||
v-model="selectedGeneralID"
|
||||
:textHelper="textHelpGeneral"
|
||||
:searchable="searchable"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-2 col-md-1">
|
||||
자원 :
|
||||
<b-button-group>
|
||||
<b-button :pressed="isGold" @click="isGold=true">금</b-button>
|
||||
<b-button :pressed="!isGold" @click="isGold=false">쌀</b-button>
|
||||
</b-button-group>
|
||||
</div>
|
||||
<div class="col-7 col-md-4">
|
||||
금액 :
|
||||
<SelectAmount
|
||||
:amountGuide="amountGuide"
|
||||
v-model="amount"
|
||||
:maxAmount="maxAmount"
|
||||
:minAmount="minAmount"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 col-md-2 d-grid">
|
||||
<b-button variant="primary" @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import SelectGeneral from "@/processing/SelectGeneral.vue";
|
||||
import SelectAmount from "@/processing/SelectAmount.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import {
|
||||
convertGeneralList,
|
||||
getProcSearchable,
|
||||
procGeneralItem,
|
||||
procGeneralKey,
|
||||
procGeneralRawItemList,
|
||||
} from "./processingRes";
|
||||
import { getNpcColor } from "@/common_legacy";
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
distanceList: Record<number, number[]>;
|
||||
cities: [number, string][];
|
||||
generals: procGeneralRawItemList;
|
||||
generalsKey: procGeneralKey[];
|
||||
minAmount: number;
|
||||
maxAmount: number;
|
||||
amountGuide: number[];
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
SelectGeneral,
|
||||
SelectAmount,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
setup() {
|
||||
const citiesMap = new Map<
|
||||
number,
|
||||
{
|
||||
name: string;
|
||||
info?: string;
|
||||
}
|
||||
>();
|
||||
for (const [id, name] of procRes.cities) {
|
||||
citiesMap.set(id, { name });
|
||||
}
|
||||
|
||||
const generalList = convertGeneralList(
|
||||
procRes.generalsKey,
|
||||
procRes.generals
|
||||
);
|
||||
const amount = ref(1000);
|
||||
const isGold = ref(true);
|
||||
|
||||
const selectedGeneralID = ref(generalList[0].no);
|
||||
|
||||
function textHelpGeneral(gen: procGeneralItem): string {
|
||||
const nameColor = getNpcColor(gen.npc);
|
||||
const name = nameColor
|
||||
? `<span style="color:${nameColor}">${gen.name}</span>`
|
||||
: gen.name;
|
||||
return `${name} (금${unwrap(gen.gold).toLocaleString()}/쌀${unwrap(gen.rice).toLocaleString()}) (${
|
||||
gen.leadership
|
||||
}/${gen.leadership}/${gen.intel})`;
|
||||
}
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
amount: amount.value,
|
||||
isGold: isGold.value,
|
||||
destGeneralID: selectedGeneralID.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
return {
|
||||
searchable: getProcSearchable(),
|
||||
amount,
|
||||
isGold,
|
||||
selectedGeneralID,
|
||||
citiesMap: ref(citiesMap),
|
||||
distanceList: procRes.distanceList,
|
||||
minAmount: ref(procRes.minAmount),
|
||||
maxAmount: ref(procRes.maxAmount),
|
||||
amountGuide: procRes.amountGuide,
|
||||
generalList,
|
||||
commandName,
|
||||
textHelpGeneral,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<TopBackBar :title="commandName" type="chief" v-model:searchable="searchable" />
|
||||
<div class="bg0">
|
||||
<MapLegacyTemplate
|
||||
:isDetailMap="false"
|
||||
:clickableAll="true"
|
||||
:neutralView="true"
|
||||
:useCachedMap="true"
|
||||
:mapTheme="mapTheme"
|
||||
v-model="selectedCityObj"
|
||||
/>
|
||||
|
||||
<div v-if="commandName == '선전포고'">
|
||||
타국에게 선전 포고합니다.<br />
|
||||
선전 포고할 국가를 목록에서 선택하세요.<br />
|
||||
고립되지 않은 아국 도시에서 인접한 국가에 선포 가능합니다.<br />
|
||||
초반제한 해제 2년전부터 선포가 가능합니다. ({{ startYear + 1 }}년 1월부터
|
||||
가능)<br />
|
||||
현재 선포가 불가능한 국가는 배경색이
|
||||
<span style="color: red">붉은색</span>으로 표시됩니다.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '급습'">
|
||||
선택된 국가에 급습을 발동합니다.<br />
|
||||
선포, 전쟁중인 상대국에만 가능합니다.<br />
|
||||
상대 국가를 목록에서 선택하세요.<br />
|
||||
현재 급습이 불가능한 국가는
|
||||
<span style="color: red">붉은색</span>으로 표시됩니다.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '불가침 파기 제의'">
|
||||
불가침중인 국가에 조약 파기를 제의합니다.<br />
|
||||
제의할 국가를 목록에서 선택하세요.<br />
|
||||
현재 제의가 불가능한 국가는
|
||||
<span style="color: red">붉은색</span>으로 표시됩니다.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '이호경식'">
|
||||
선택된 국가에 이호경식을 발동합니다.<br />
|
||||
선포, 전쟁중인 상대국에만 가능합니다.<br />
|
||||
상대 국가를 목록에서 선택하세요.<br />
|
||||
현재 이호경식이 불가능한 국가는
|
||||
<span style="color: red">붉은색</span>으로 표시됩니다.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '종전 제의'">
|
||||
전쟁중인 국가에 종전을 제의합니다.<br />
|
||||
제의할 국가를 목록에서 선택하세요.<br />
|
||||
현재 제의가 불가능한 국가는
|
||||
<span style="color: red">붉은색</span>으로 표시됩니다.<br />
|
||||
</div>
|
||||
<div v-else-if="commandName == '허보'">
|
||||
전쟁중인 국가에 종전을 제의합니다.<br />
|
||||
제의할 국가를 목록에서 선택하세요.<br />
|
||||
현재 제의가 불가능한 국가는
|
||||
<span style="color: red">붉은색</span>으로 표시됩니다.<br />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6 col-md-3">
|
||||
국가 :
|
||||
<SelectNation :nations="nationList" v-model="selectedNationID" :searchable="searchable" />
|
||||
</div>
|
||||
<div class="col-4 col-md-2 d-grid">
|
||||
<b-button @click="submit">{{ commandName }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BottomBar :title="commandName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import MapLegacyTemplate, {
|
||||
MapCityParsed,
|
||||
} from "@/components/MapLegacyTemplate.vue";
|
||||
import SelectNation from "@/processing/SelectNation.vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { Args } from "@/processing/args";
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import { getProcSearchable, procNationItem, procNationList } from "./processingRes";
|
||||
declare const mapTheme: string;
|
||||
declare const commandName: string;
|
||||
|
||||
declare const procRes: {
|
||||
nationList: procNationList;
|
||||
startYear: number;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MapLegacyTemplate,
|
||||
SelectNation,
|
||||
TopBackBar,
|
||||
BottomBar,
|
||||
},
|
||||
watch: {
|
||||
selectedCityObj(city: MapCityParsed) {
|
||||
if (!city.nationID) {
|
||||
return;
|
||||
}
|
||||
this.selectedNationID = city.nationID;
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const nationList = new Map<number, procNationItem>();
|
||||
for (const nationItem of procRes.nationList) {
|
||||
nationList.set(nationItem.id, nationItem);
|
||||
}
|
||||
|
||||
const selectedNationID = ref(procRes.nationList[0].id);
|
||||
const selectedCityObj = ref(); //mapping용
|
||||
|
||||
function selectedNation(nationID: number) {
|
||||
selectedNationID.value = nationID;
|
||||
}
|
||||
|
||||
async function submit(e: Event) {
|
||||
const event = new CustomEvent<Args>("customSubmit", {
|
||||
detail: {
|
||||
destNationID: selectedNationID.value,
|
||||
},
|
||||
});
|
||||
unwrap(e.target).dispatchEvent(event);
|
||||
}
|
||||
|
||||
return {
|
||||
searchable: getProcSearchable(),
|
||||
startYear: procRes.startYear,
|
||||
mapTheme: ref(mapTheme),
|
||||
nationList: ref(nationList),
|
||||
selectedCityObj,
|
||||
selectedNationID,
|
||||
commandName,
|
||||
selectedNation,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<div class="input-group">
|
||||
<b-button
|
||||
v-if="maxAmount > 20000"
|
||||
class="btn-sm"
|
||||
@click="amount = Math.max(amount - 10000, minAmount)"
|
||||
>-만</b-button
|
||||
>
|
||||
<b-button
|
||||
v-if="maxAmount > 2000"
|
||||
class="btn-sm"
|
||||
@click="amount = Math.max(amount - 1000, minAmount)"
|
||||
>-천</b-button
|
||||
>
|
||||
<b-button
|
||||
v-if="maxAmount > 200"
|
||||
class="btn-sm"
|
||||
@click="amount = Math.max(amount - 100, minAmount)"
|
||||
>-백</b-button
|
||||
>
|
||||
<input
|
||||
type="number"
|
||||
class="form-control text-end"
|
||||
:max="maxAmount"
|
||||
:min="minAmount"
|
||||
:step="step"
|
||||
v-model="amount"
|
||||
placeholder="금액"
|
||||
/>
|
||||
<b-dropdown right text="" class="amount-dropdown" v-if="amountGuide">
|
||||
<b-dropdown-item
|
||||
v-for="guide in amountGuide"
|
||||
:key="guide"
|
||||
@click="amount = guide"
|
||||
><div class="text-end">
|
||||
{{ guide.toLocaleString() }}
|
||||
</div></b-dropdown-item
|
||||
>
|
||||
</b-dropdown>
|
||||
<b-button
|
||||
v-if="maxAmount > 200"
|
||||
class="btn-sm"
|
||||
@click="amount = Math.min(amount + 100, maxAmount)"
|
||||
>+백</b-button
|
||||
>
|
||||
<b-button
|
||||
v-if="maxAmount > 2000"
|
||||
class="btn-sm"
|
||||
@click="amount = Math.min(amount + 1000, maxAmount)"
|
||||
>+천</b-button
|
||||
>
|
||||
<b-button
|
||||
v-if="maxAmount > 20000"
|
||||
class="btn-sm"
|
||||
@click="amount = Math.min(amount + 10000, maxAmount)"
|
||||
>+만</b-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
minAmount: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
maxAmount: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
amountGuide: {
|
||||
type: Array as PropType<number[]>,
|
||||
required: false,
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 1,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
watch: {
|
||||
amount(val: number) {
|
||||
this.$emit("update:modelValue", val);
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
amount: this.modelValue,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
.btn-group.amount-dropdown > .btn {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.btn-group.amount-dropdown .dropdown-menu.show {
|
||||
min-width: 6rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<v-multiselect
|
||||
v-model="selectedCity"
|
||||
:allow-empty="false"
|
||||
:options="citiesForFind"
|
||||
:group-select="false"
|
||||
label="searchText"
|
||||
track-by="value"
|
||||
:show-labels="false"
|
||||
selectLabel="선택(엔터)"
|
||||
selectGroupLabel=""
|
||||
selectedLabel="선택됨"
|
||||
deselectLabel="해제(엔터)"
|
||||
deselectGroupLabel=""
|
||||
placeholder="도시 선택"
|
||||
:maxHeight="400"
|
||||
:searchable="searchable"
|
||||
>
|
||||
<template v-slot:option="props"
|
||||
><span
|
||||
:style="{
|
||||
color: props.option.notAvailable ? 'red' : undefined,
|
||||
}"
|
||||
>
|
||||
{{ props.option.title }}
|
||||
<span v-if="props.option.info">({{ props.option.info }})</span> {{ props.option.notAvailable ? "(불가)" : undefined }}</span
|
||||
>
|
||||
</template>
|
||||
<template v-slot:singleLabel="props">
|
||||
<span
|
||||
:style="{
|
||||
color: props.option.notAvailable ? 'red' : undefined,
|
||||
}"
|
||||
>{{ props.option.simpleName }} {{ props.option.notAvailable ? "(불가)" : undefined }}</span>
|
||||
</template>
|
||||
</v-multiselect>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { convertSearch초성 } from "@/util/convertSearch초성";
|
||||
import { defineComponent, PropType } from "vue";
|
||||
|
||||
type SelectedCity = {
|
||||
value: number;
|
||||
searchText: string;
|
||||
title: string;
|
||||
simpleName: string;
|
||||
info?: string;
|
||||
notAvailable?: boolean;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
cities: {
|
||||
type: Map as PropType<Map<number, { name: string; info?: string }>>,
|
||||
required: true,
|
||||
},
|
||||
searchable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
watch: {
|
||||
modelValue(val: number) {
|
||||
const target = this.targets.get(val);
|
||||
this.selectedCity = target;
|
||||
},
|
||||
selectedCity(val: SelectedCity) {
|
||||
this.$emit("update:modelValue", val.value);
|
||||
},
|
||||
},
|
||||
data() {
|
||||
const citiesForFind = [];
|
||||
const targets = new Map<number, SelectedCity>();
|
||||
let selectedCity;
|
||||
for (const [value, { name, info }] of this.cities.entries()) {
|
||||
const obj: SelectedCity = {
|
||||
value,
|
||||
title: name,
|
||||
info: info,
|
||||
simpleName: name,
|
||||
searchText: convertSearch초성(name).join('|'),
|
||||
};
|
||||
if (value == this.modelValue) {
|
||||
selectedCity = obj;
|
||||
}
|
||||
citiesForFind.push(obj);
|
||||
targets.set(value, obj);
|
||||
}
|
||||
return {
|
||||
selectedCity,
|
||||
citiesForFind,
|
||||
targets,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<v-multiselect
|
||||
v-model="selectedColor"
|
||||
:allow-empty="false"
|
||||
:options="forFind"
|
||||
:group-select="false"
|
||||
label="searchText"
|
||||
track-by="value"
|
||||
:show-labels="false"
|
||||
selectLabel="선택(엔터)"
|
||||
selectGroupLabel=""
|
||||
selectedLabel="선택됨"
|
||||
deselectLabel="해제(엔터)"
|
||||
deselectGroupLabel=""
|
||||
placeholder="색상 선택"
|
||||
:maxHeight="400"
|
||||
:searchable="false"
|
||||
>
|
||||
<template v-slot:option="props">
|
||||
<div
|
||||
:class="`sam-color-${props.option.title.slice(1)}`"
|
||||
:style="{
|
||||
margin: '-0.375rem -0.75rem',
|
||||
}"
|
||||
>
|
||||
<div
|
||||
class="sam-nation-own-bgcolor"
|
||||
:style="{
|
||||
padding: '0.545rem 0.75rem',
|
||||
}"
|
||||
>
|
||||
{{ props.option.title }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:singleLabel="props">
|
||||
<div
|
||||
:class="`sam-color-${props.option.title.slice(1)}`"
|
||||
:style="{
|
||||
margin: '-0.25rem -0.75rem',
|
||||
}"
|
||||
><div
|
||||
class="sam-nation-own-bgcolor"
|
||||
:style="{
|
||||
padding: '0.30rem 0.75rem',
|
||||
borderRadius: '0.25rem',
|
||||
}"
|
||||
>{{ props.option.title }}</div
|
||||
></div
|
||||
>
|
||||
</template>
|
||||
</v-multiselect>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { defineComponent, PropType } from "vue";
|
||||
|
||||
type SelectedColor = {
|
||||
value: number;
|
||||
title: string;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
colors: {
|
||||
type: Array as PropType<string[]>,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
watch: {
|
||||
modelValue(val: number) {
|
||||
const target = unwrap(this.targets.get(val));
|
||||
this.selectedColor = target;
|
||||
},
|
||||
selectedColor(val: SelectedColor) {
|
||||
this.$emit("update:modelValue", val.value);
|
||||
},
|
||||
},
|
||||
data() {
|
||||
const forFind = [];
|
||||
const targets = new Map<number, SelectedColor>();
|
||||
for (const [value, title] of this.colors.entries()) {
|
||||
const obj: SelectedColor = {
|
||||
value,
|
||||
title,
|
||||
};
|
||||
forFind.push(obj);
|
||||
targets.set(value, obj);
|
||||
}
|
||||
let selectedColor = forFind[0];
|
||||
|
||||
return {
|
||||
selectedColor,
|
||||
searchMode: false,
|
||||
forFind,
|
||||
targets,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,189 @@
|
||||
<template>
|
||||
<v-multiselect
|
||||
v-model="selectedGeneral"
|
||||
class="selectedGeneral"
|
||||
:allow-empty="false"
|
||||
:options="forFind"
|
||||
:group-select="false"
|
||||
:group-values="groupByNation ? 'values' : undefined"
|
||||
group-label="nationID"
|
||||
label="searchText"
|
||||
track-by="value"
|
||||
:show-labels="false"
|
||||
selectLabel="선택(엔터)"
|
||||
selectGroupLabel=""
|
||||
selectedLabel="선택됨"
|
||||
deselectLabel="해제(엔터)"
|
||||
deselectGroupLabel=""
|
||||
placeholder="장수 선택"
|
||||
:maxHeight="400"
|
||||
:searchable="searchable"
|
||||
>
|
||||
<template v-slot:option="props">
|
||||
<div v-if="props.option.title" v-html="props.option.title"></div>
|
||||
<div
|
||||
v-if="props.option.$groupLabel !== undefined"
|
||||
class="margin-filler"
|
||||
:style="{
|
||||
backgroundColor: groupByNation.get(props.option.$groupLabel).color,
|
||||
color: isBrightColor(
|
||||
groupByNation.get(props.option.$groupLabel).color
|
||||
)
|
||||
? 'black'
|
||||
: 'white',
|
||||
}"
|
||||
>
|
||||
{{ groupByNation.get(props.option.$groupLabel).name }}
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:singleLabel="props">
|
||||
{{ props.option.simpleName }} {{groupByNation?`[${groupByNation.get(props.option.obj.nationID).name}]`:undefined}}
|
||||
</template>
|
||||
</v-multiselect>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { getNpcColor } from "@/common_legacy";
|
||||
import { convertSearch초성 } from "@/util/convertSearch초성";
|
||||
import { isBrightColor } from "@/util/isBrightColor";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import { defineComponent, PropType } from "vue";
|
||||
import {
|
||||
procGeneralItem,
|
||||
procGeneralList,
|
||||
procNationItem,
|
||||
} from "./processingRes";
|
||||
|
||||
type SelectedGeneral = {
|
||||
value: number;
|
||||
searchText: string;
|
||||
title: string;
|
||||
simpleName: string;
|
||||
obj: procGeneralItem;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
generals: {
|
||||
type: Array as PropType<procGeneralList>,
|
||||
required: true,
|
||||
},
|
||||
textHelper: {
|
||||
type: Function as PropType<(item: procGeneralItem) => string>,
|
||||
required: false,
|
||||
default: undefined,
|
||||
},
|
||||
groupByNation: {
|
||||
type: Map as PropType<Map<number, procNationItem>>,
|
||||
required: false,
|
||||
default: undefined,
|
||||
},
|
||||
searchable:{
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
}
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
watch: {
|
||||
modelValue(val: number) {
|
||||
const target = this.targets.get(val);
|
||||
this.selectedGeneral = target;
|
||||
},
|
||||
selectedGeneral(val: SelectedGeneral) {
|
||||
this.$emit("update:modelValue", val.value);
|
||||
},
|
||||
},
|
||||
data() {
|
||||
const forFind: (
|
||||
| SelectedGeneral
|
||||
| {
|
||||
values: SelectedGeneral[];
|
||||
nationID: number;
|
||||
}
|
||||
)[] = [];
|
||||
const forFindGroup = new Map<number, SelectedGeneral[]>();
|
||||
const targets = new Map<number, SelectedGeneral>();
|
||||
|
||||
let selectedGeneral;
|
||||
|
||||
for (const gen of this.generals) {
|
||||
let groupArray = forFind;
|
||||
if (this.groupByNation) {
|
||||
const nationID = gen.nationID ?? 0;
|
||||
if (!forFindGroup.has(nationID)) {
|
||||
const nationItem = unwrap(this.groupByNation.get(nationID));
|
||||
let tmpArr: SelectedGeneral[] = [];
|
||||
forFindGroup.set(nationID, tmpArr);
|
||||
groupArray = tmpArr;
|
||||
|
||||
forFind.push({
|
||||
nationID: nationItem.id,
|
||||
values: tmpArr,
|
||||
});
|
||||
} else {
|
||||
groupArray = unwrap(forFindGroup.get(nationID));
|
||||
}
|
||||
}
|
||||
|
||||
const nameColor = getNpcColor(gen.npc);
|
||||
const name = nameColor
|
||||
? `<span style="color:${nameColor}">${gen.name}</span>`
|
||||
: gen.name;
|
||||
|
||||
const obj: SelectedGeneral = {
|
||||
value: gen.no,
|
||||
title: this.textHelper
|
||||
? this.textHelper(gen)
|
||||
: `${name} (${gen.leadership}/${gen.leadership}/${gen.intel})`,
|
||||
simpleName: gen.name,
|
||||
searchText: convertSearch초성(gen.name).join('|'),
|
||||
obj: gen,
|
||||
};
|
||||
if (gen.no == this.modelValue) {
|
||||
selectedGeneral = obj;
|
||||
}
|
||||
groupArray.push(obj);
|
||||
targets.set(gen.no, obj);
|
||||
}
|
||||
return {
|
||||
selectedGeneral,
|
||||
forFind,
|
||||
targets,
|
||||
isBrightColor,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "@scss/common/break_500px.scss";
|
||||
@import "@scss/common/variables.scss";
|
||||
@import "@scss/common/bootswatch_custom_variables.scss";
|
||||
@import "bootstrap/scss/bootstrap-utilities.scss";
|
||||
|
||||
.selectedGeneral {
|
||||
$vue-multiselect-bg: $gray-700;
|
||||
$vue-multiselect-color: $gray-100;
|
||||
$form-select-color: $gray-100;
|
||||
$text-muted: $gray-400;
|
||||
$dark: $gray-100;
|
||||
$light: $gray-700;
|
||||
$vue-multiselect-option-selected-bg: $gray-600;
|
||||
@import "@scss/common/vue-multiselect.scss";
|
||||
color: $vue-multiselect-color;
|
||||
|
||||
input {
|
||||
color: $vue-multiselect-color;
|
||||
}
|
||||
|
||||
.multiselect__option--group {
|
||||
padding: 0;
|
||||
}
|
||||
.margin-filler {
|
||||
padding: calc($vue-multiselect-padding-y + 0.17em) $vue-multiselect-padding-x;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<v-multiselect
|
||||
v-model="selectedNation"
|
||||
:allow-empty="false"
|
||||
:options="forFind"
|
||||
:group-select="false"
|
||||
label="searchText"
|
||||
track-by="value"
|
||||
:show-labels="false"
|
||||
selectLabel="선택(엔터)"
|
||||
selectGroupLabel=""
|
||||
selectedLabel="선택됨"
|
||||
deselectLabel="해제(엔터)"
|
||||
deselectGroupLabel=""
|
||||
placeholder="국가 선택"
|
||||
:maxHeight="400"
|
||||
:searchable="searchable"
|
||||
>
|
||||
<template v-slot:option="props">
|
||||
<span
|
||||
:style="{
|
||||
color: props.option.notAvailable ? 'red' : undefined,
|
||||
}"
|
||||
>
|
||||
{{ props.option.title }}
|
||||
<span v-if="props.option.info">({{ props.option.info }})</span>
|
||||
{{ props.option.notAvailable ? "(불가)" : undefined }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-slot:singleLabel="props">
|
||||
<span
|
||||
:style="{
|
||||
color: props.option.notAvailable ? 'red' : undefined,
|
||||
}"
|
||||
>
|
||||
{{ props.option.simpleName }}
|
||||
{{ props.option.notAvailable ? "(불가)" : undefined }}</span
|
||||
>
|
||||
</template>
|
||||
</v-multiselect>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { convertSearch초성 } from "@/util/convertSearch초성";
|
||||
import { defineComponent, PropType } from "vue";
|
||||
import { procNationItem } from "./processingRes";
|
||||
|
||||
type SelectedNation = {
|
||||
value: number;
|
||||
searchText: string;
|
||||
title: string;
|
||||
simpleName: string;
|
||||
info?: string;
|
||||
notAvailable?: boolean;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
nations: {
|
||||
type: Map as PropType<Map<number, procNationItem>>,
|
||||
required: true,
|
||||
},
|
||||
searchable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
}
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
watch: {
|
||||
modelValue(val: number) {
|
||||
const target = this.targets.get(val);
|
||||
this.selectedNation = target;
|
||||
},
|
||||
selectedNation(val: SelectedNation) {
|
||||
this.$emit("update:modelValue", val.value);
|
||||
},
|
||||
},
|
||||
data() {
|
||||
const forFind = [];
|
||||
const targets = new Map<number, SelectedNation>();
|
||||
let selectedNation;
|
||||
for (const nationItem of this.nations.values()) {
|
||||
const obj: SelectedNation = {
|
||||
value: nationItem.id,
|
||||
title: nationItem.name,
|
||||
info: nationItem.info,
|
||||
simpleName: nationItem.name,
|
||||
notAvailable: nationItem.notAvailable,
|
||||
searchText: convertSearch초성(nationItem.name).join('|'),
|
||||
};
|
||||
if (nationItem.id == this.modelValue) {
|
||||
selectedNation = obj;
|
||||
}
|
||||
forFind.push(obj);
|
||||
targets.set(nationItem.id, obj);
|
||||
}
|
||||
return {
|
||||
selectedNation,
|
||||
forFind,
|
||||
targets,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,87 @@
|
||||
import { mb_strwidth } from "@/util/mb_strwidth";
|
||||
import { isArray, isBoolean, isInteger, isString } from "lodash";
|
||||
|
||||
|
||||
const stringArgs = [
|
||||
'nationName', 'optionText', 'itemType', 'nationType', 'itemCode', 'commandType',
|
||||
] as const;
|
||||
const intArgs = [
|
||||
'crewType', 'destGeneralID', 'destCityID', 'destNationID',
|
||||
'amount', 'colorType',
|
||||
'year', 'month',
|
||||
'srcArmType', 'destArmType', //숙련전환 전용
|
||||
] as const;
|
||||
|
||||
const booleanArgs = [
|
||||
'isGold', 'buyRice',
|
||||
] as const;
|
||||
|
||||
const integerArrayArgs = [
|
||||
'destNationIDList', 'destGeneralIDList', 'amountList'
|
||||
] as const;
|
||||
|
||||
type StringKeys = typeof stringArgs[number];
|
||||
type IntKeys = typeof intArgs[number];
|
||||
type BooleanKeys = typeof booleanArgs[number];
|
||||
type IntegerArrayKeys = typeof integerArrayArgs[number];
|
||||
|
||||
|
||||
export type Args = {
|
||||
[key in StringKeys]?: string;
|
||||
} & {
|
||||
[key in IntKeys]?: number;
|
||||
} & {
|
||||
[key in BooleanKeys]?: boolean;
|
||||
} & {
|
||||
[key in IntegerArrayKeys]?: number[]
|
||||
};
|
||||
|
||||
|
||||
|
||||
export function testSubmitArgs(args: Args): true | ['int' | 'string' | 'boolean' | 'int[]', keyof Args, number | string | boolean | number[]] {
|
||||
for (const intKey of intArgs) {
|
||||
const testVal = args[intKey];
|
||||
if (testVal === undefined) {
|
||||
continue;
|
||||
}
|
||||
if (!isInteger(testVal)) {
|
||||
return ['int', intKey, testVal];
|
||||
}
|
||||
}
|
||||
for (const stringKey of stringArgs) {
|
||||
const testVal = args[stringKey];
|
||||
if (testVal === undefined) {
|
||||
continue;
|
||||
}
|
||||
if (!isString(testVal)) {
|
||||
return ['string', stringKey, testVal];
|
||||
}
|
||||
if(stringKey == 'nationName' && mb_strwidth(testVal) > 18){
|
||||
throw `길이가 반각 18자 분량을 넘었습니다.`;
|
||||
}
|
||||
}
|
||||
for (const booleanKey of booleanArgs) {
|
||||
const testVal = args[booleanKey];
|
||||
if (testVal === undefined) {
|
||||
continue;
|
||||
}
|
||||
if (!isBoolean(testVal)) {
|
||||
return ['boolean', booleanKey, testVal];
|
||||
}
|
||||
}
|
||||
for (const integerArrayKey of integerArrayArgs) {
|
||||
const testVal = args[integerArrayKey];
|
||||
if (testVal === undefined) {
|
||||
continue;
|
||||
}
|
||||
if (!isArray(args[integerArrayKey])) {
|
||||
return ['int[]', integerArrayKey, testVal];
|
||||
}
|
||||
for (const value of testVal) {
|
||||
if (!isInteger(value)) {
|
||||
return ['int[]', integerArrayKey, testVal];
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import { ItemTypeKey } from "@/defs";
|
||||
import { combineArray } from "@/util/combineArray";
|
||||
import { Ref, ref, watch } from "vue";
|
||||
|
||||
export type procGeneralItem = {
|
||||
no: number,
|
||||
name: string,
|
||||
nationID?: number,
|
||||
officerLevel: number,
|
||||
npc: number,
|
||||
gold?: number,
|
||||
rice?: number,
|
||||
leadership: number,
|
||||
strength: number,
|
||||
intel: number,
|
||||
cityID?: number,
|
||||
crew?: number,
|
||||
train?: number,
|
||||
atmos?: number,
|
||||
troopID?: number,
|
||||
}
|
||||
|
||||
export type procGeneralList = procGeneralItem[];
|
||||
|
||||
export type procGeneralKey = 'no' | 'name' | 'nationID' | 'officerLevel' | 'npc' | 'gold' | 'rice' | 'leadership' | 'strength' | 'intel' | 'cityID' | 'crew' | 'train' | 'atmos' | 'troopID';
|
||||
|
||||
export type procGeneralRawItem = procGeneralItem[procGeneralKey][];
|
||||
|
||||
export type procTroopItem = {
|
||||
troop_leader: number,
|
||||
nation: number,
|
||||
name: string
|
||||
};
|
||||
export type procTroopList = Record<number, procTroopItem>;
|
||||
|
||||
export type procGeneralRawItemList = procGeneralRawItem[];
|
||||
|
||||
export function convertGeneralList(keys: procGeneralKey[], rawList: procGeneralRawItemList): procGeneralList {
|
||||
return combineArray(rawList, keys) as procGeneralList;
|
||||
}
|
||||
|
||||
|
||||
export type procNationItem = {
|
||||
id: number,
|
||||
name: string,
|
||||
color: string,
|
||||
power: number,
|
||||
scoutMsg?: string,
|
||||
info?: string,
|
||||
notAvailable?: boolean,
|
||||
};
|
||||
|
||||
export type procNationList = procNationItem[];
|
||||
|
||||
export type procNationTypeItem = {
|
||||
type: string,
|
||||
name: string,
|
||||
pros: string,
|
||||
cons: string,
|
||||
}
|
||||
|
||||
export type procNationTypeList = Record<string, procNationTypeItem>;
|
||||
|
||||
|
||||
export type procArmTypeItem = {
|
||||
armType: number,
|
||||
armName: string,
|
||||
values: procCrewTypeItem[],
|
||||
}
|
||||
|
||||
export type procCrewTypeItem = {
|
||||
id: number,
|
||||
reqTech: number,
|
||||
reqYear: number,
|
||||
notAvailable?: boolean,
|
||||
baseRice: number,
|
||||
baseCost: number,
|
||||
name: string,
|
||||
attack: number,
|
||||
defence: number,
|
||||
speed: number,
|
||||
avoid: number,
|
||||
img: string,
|
||||
info: string[],
|
||||
}
|
||||
|
||||
export type procItemType = {
|
||||
id: string,
|
||||
name: string,
|
||||
reqSecu: number,
|
||||
cost: number,
|
||||
info: string,//<br>
|
||||
isBuyable: boolean,
|
||||
}
|
||||
|
||||
export type procItemList = Record<ItemTypeKey, {
|
||||
typeName: string,
|
||||
values: procItemType[],
|
||||
}>
|
||||
|
||||
|
||||
//XXX: vuex 쓰기 전까지...
|
||||
export const searchableProcessingMode = 'sam.processing.searchable';
|
||||
const searchable = ref((localStorage.getItem(searchableProcessingMode) ?? "0") != "0");
|
||||
watch(searchable, (val) => {
|
||||
localStorage.setItem(searchableProcessingMode, val ? "1" : "0");
|
||||
});
|
||||
|
||||
export function getProcSearchable():Ref<boolean>{
|
||||
return searchable;
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
import { unwrap_any } from '@util/unwrap_any';
|
||||
|
||||
|
||||
declare const leadership: number;
|
||||
declare const fullLeadership: number;
|
||||
declare const currentCrewType: number;
|
||||
declare const currentCrew: number;
|
||||
//declare const currentGold: number;
|
||||
declare const is모병 = false;
|
||||
function calc(id: number) {
|
||||
const $obj = $(`#crewType${id}`);
|
||||
const crew = parseInt(unwrap_any<string>($obj.find('.form_double').val()));
|
||||
const baseCost = $obj.data('cost');
|
||||
const $cost = $obj.find('.form_cost');
|
||||
|
||||
let cost = crew * baseCost;
|
||||
if (is모병) {
|
||||
cost *= 2;
|
||||
}
|
||||
$cost.val(Math.round(cost));
|
||||
}
|
||||
|
||||
export function recruitCrewForm(): void {
|
||||
const $formAmount = $('#amount');
|
||||
const $formCrewtype = $('#crewType');
|
||||
$('.form_double').on('keyup change', function (e) {
|
||||
const $this = $(this);
|
||||
const $parent = $this.parents('.input_form');
|
||||
const crewtype = parseInt($parent.data('crewtype'));
|
||||
calc(crewtype);
|
||||
$formCrewtype.val(crewtype);
|
||||
$formAmount.val(parseFloat(unwrap_any<string>($this.val())) * 100);
|
||||
|
||||
if (e.which === 13) {
|
||||
void window.submitAction();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.btn_half').on('click', function () {
|
||||
const $this = $(this);
|
||||
const $parent = $this.closest('.input_form');
|
||||
const crewtype = parseInt($parent.data('crewtype'));
|
||||
const $input = $parent.find('.form_double:eq(0)');
|
||||
|
||||
const fillValue = Math.round(leadership / 2);
|
||||
$formCrewtype.val(crewtype);
|
||||
$input.val(fillValue).change();
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.btn_fill').on('click', function () {
|
||||
const $this = $(this);
|
||||
const $parent = $this.closest('.input_form');
|
||||
const crewtype = parseInt($parent.data('crewtype'));
|
||||
const $input = $parent.find('.form_double:eq(0)');
|
||||
|
||||
let fillValue = Math.ceil((leadership * 100 - currentCrew) / 100);
|
||||
if (crewtype != currentCrewType) {
|
||||
fillValue = leadership;
|
||||
}
|
||||
$formCrewtype.val(crewtype);
|
||||
$input.val(fillValue).change();
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.btn_full').on('click', function () {
|
||||
const $this = $(this);
|
||||
const $parent = $this.closest('.input_form');
|
||||
const crewtype = parseInt($parent.data('crewtype'));
|
||||
const $input = $parent.find('.form_double:eq(0)');
|
||||
|
||||
const fillValue = fullLeadership + 15;
|
||||
$formCrewtype.val(crewtype);
|
||||
$input.val(fillValue).change();
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.submit_btn').on('click', function () {
|
||||
const $this = $(this);
|
||||
const $parent = $this.closest('tr').find('.input_form');
|
||||
const crewtype = parseInt($parent.data('crewtype'));
|
||||
const $input = $parent.find('.form_double');
|
||||
|
||||
$formCrewtype.val(crewtype);
|
||||
$formAmount.val(parseFloat(unwrap_any<string>($input.val())) * 100);
|
||||
|
||||
void window.submitAction();
|
||||
});
|
||||
|
||||
$('.btn_fill').click();
|
||||
|
||||
$('#show_unavailable_troops').change(function () {
|
||||
const show = $('#show_unavailable_troops').is(":checked");
|
||||
if (show) {
|
||||
$('.show_default_false').show();
|
||||
}
|
||||
else {
|
||||
$('.show_default_false').hide();
|
||||
}
|
||||
});
|
||||
$('.show_default_false').hide();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user