Merge branch 'devel' into asia_scenario
This commit is contained in:
@@ -528,7 +528,7 @@ function checkWander(RandUtil $rng)
|
|||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
|
||||||
$admin = $gameStor->getValues(['year', 'month']);
|
$admin = $gameStor->getValues(['year', 'month', 'init_year', 'init_month']);
|
||||||
|
|
||||||
$wanderers = $db->queryFirstColumn('SELECT general.`no` FROM general LEFT JOIN nation ON general.nation = nation.nation WHERE nation.`level` = 0 AND general.`officer_level` = 12');
|
$wanderers = $db->queryFirstColumn('SELECT general.`no` FROM general LEFT JOIN nation ON general.nation = nation.nation WHERE nation.`level` = 0 AND general.`officer_level` = 12');
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ if ($session->userGrade < 5 && !$allowReset) {
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
|
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
|
||||||
<?= WebUtil::printCSS('css/install.css') ?>
|
<?= WebUtil::printCSS('css/install.css') ?>
|
||||||
|
<?= WebUtil::printDist('vue', [], true) ?>
|
||||||
<?= WebUtil::printDist('ts', ['common', 'install']) ?>
|
<?= WebUtil::printDist('ts', ['common', 'install']) ?>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ include "func.php";
|
|||||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
|
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
|
||||||
<?= WebUtil::printCSS('css/map.css') ?>
|
<?= WebUtil::printCSS('css/map.css') ?>
|
||||||
<?= WebUtil::printDist('ts', ['common', 'recent_map'], true) ?>
|
<?= WebUtil::printDist('ts', ['common', 'recent_map'], true) ?>
|
||||||
|
<?= WebUtil::printDist('vue', [], true) ?>
|
||||||
<style>
|
<style>
|
||||||
html {
|
html {
|
||||||
width: 700px;
|
width: 700px;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class Bet extends \sammo\BaseAPI
|
|||||||
->rule('int', 'bettingID')
|
->rule('int', 'bettingID')
|
||||||
->rule('integerArray', 'bettingType')
|
->rule('integerArray', 'bettingType')
|
||||||
->rule('int', 'amount')
|
->rule('int', 'amount')
|
||||||
->rule('min', 'amount', 1);
|
->rule('min', 'amount', 10);
|
||||||
|
|
||||||
if (!$v->validate()) {
|
if (!$v->validate()) {
|
||||||
return $v->errorStr();
|
return $v->errorStr();
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ class GetGeneralLog extends \sammo\BaseAPI
|
|||||||
if (
|
if (
|
||||||
$reqType === self::GENERAL_ACTION &&
|
$reqType === self::GENERAL_ACTION &&
|
||||||
$testGeneralNPCType < 2 &&
|
$testGeneralNPCType < 2 &&
|
||||||
$generalID !== $me['generalID'] &&
|
$generalID !== $me['no'] &&
|
||||||
$permission < 2
|
$permission < 2
|
||||||
) {
|
) {
|
||||||
return '권한이 부족합니다. 유저 장수의 개인 기록은 수뇌만 열람 가능합니다.';
|
return '권한이 부족합니다. 유저 장수의 개인 기록은 수뇌만 열람 가능합니다.';
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ class InheritancePointManager
|
|||||||
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
|
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
|
||||||
if ($storeType === true || ($gameStor->isunited != 0 && !$forceCalc)) {
|
if ($storeType === true || ($gameStor->isunited != 0 && !$forceCalc)) {
|
||||||
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}");
|
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}");
|
||||||
[$value, $aux] = $inheritStor->getValue($key);
|
[$value, $aux] = $inheritStor->getValue($key) ?? [0, null];
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
<TopBackBar title="감찰부" :reloadable="true" type="close" @reload="reload" />
|
<TopBackBar title="감찰부" :reloadable="true" type="close" @reload="reload" />
|
||||||
|
|
||||||
<div class="row gx-0">
|
<div class="row gx-0">
|
||||||
<div class="col-4">
|
<div class="col-2 col-md-1 d-grid">
|
||||||
|
<BButton @click="changeTargetByOffset(-1)">◀ 이전</BButton>
|
||||||
|
</div>
|
||||||
|
<div class="col-3 col-md-4">
|
||||||
<BFormSelect v-model="orderBy">
|
<BFormSelect v-model="orderBy">
|
||||||
<BFormSelectOption
|
<BFormSelectOption
|
||||||
v-for="[orderKey, [orderName]] of Object.entries(textMap)"
|
v-for="[orderKey, [orderName]] of Object.entries(textMap)"
|
||||||
@@ -14,7 +17,7 @@
|
|||||||
</BFormSelectOption>
|
</BFormSelectOption>
|
||||||
</BFormSelect>
|
</BFormSelect>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-8">
|
<div class="col-5 col-md-6">
|
||||||
<BFormSelect v-model="targetGeneralID">
|
<BFormSelect v-model="targetGeneralID">
|
||||||
<BFormSelectOption v-for="general of orderedGeneralList" :key="general.no" :value="general.no">
|
<BFormSelectOption v-for="general of orderedGeneralList" :key="general.no" :value="general.no">
|
||||||
<span
|
<span
|
||||||
@@ -28,11 +31,19 @@
|
|||||||
</BFormSelectOption>
|
</BFormSelectOption>
|
||||||
</BFormSelect>
|
</BFormSelect>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-2 col-md-1 d-grid">
|
||||||
|
<BButton @click="changeTargetByOffset(1)">다음 ▶</BButton>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="targetGeneral && nationInfo && targetGeneralLogs" class="row gx-0 bg0">
|
<div v-if="targetGeneral && nationInfo && targetGeneralLogs" class="row gx-0 bg0">
|
||||||
<div class="col-12 col-md-6">
|
<div class="col-12 col-md-6">
|
||||||
<div class="bg1 header-cell" style="color: skyblue">장수 정보</div>
|
<div class="bg1 header-cell" style="color: skyblue">장수 정보</div>
|
||||||
<GeneralBasicCard :general="targetGeneral" :nation="nationInfo" />
|
<GeneralBasicCard
|
||||||
|
:general="targetGeneral"
|
||||||
|
:nation="nationInfo"
|
||||||
|
:turnTerm="turnTerm"
|
||||||
|
:lastExecuted="lastExecuted"
|
||||||
|
/>
|
||||||
<GeneralSupplementCard :general="targetGeneral" />
|
<GeneralSupplementCard :general="targetGeneral" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-md-6">
|
<div class="col-12 col-md-6">
|
||||||
@@ -67,7 +78,7 @@ declare const queryValues: {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { BContainer, useToast, BFormSelect, BFormSelectOption } from "bootstrap-vue-3";
|
import { BContainer, useToast, BFormSelect, BFormSelectOption, BButton } from "bootstrap-vue-3";
|
||||||
import { onMounted, provide, ref, watch } from "vue";
|
import { onMounted, provide, ref, watch } from "vue";
|
||||||
import { getGameConstStore, type GameConstStore } from "./GameConstStore";
|
import { getGameConstStore, type GameConstStore } from "./GameConstStore";
|
||||||
import TopBackBar from "@/components/TopBackBar.vue";
|
import TopBackBar from "@/components/TopBackBar.vue";
|
||||||
@@ -83,6 +94,7 @@ import type { NationStaticItem } from "./defs";
|
|||||||
import type { GeneralLogType } from "./defs/API/General";
|
import type { GeneralLogType } from "./defs/API/General";
|
||||||
import { isString } from "lodash";
|
import { isString } from "lodash";
|
||||||
import { formatLog } from "./utilGame/formatLog";
|
import { formatLog } from "./utilGame/formatLog";
|
||||||
|
import { parseTime } from "./util/parseTime";
|
||||||
|
|
||||||
const toasts = unwrap(useToast());
|
const toasts = unwrap(useToast());
|
||||||
|
|
||||||
@@ -98,8 +110,12 @@ const textMap = {
|
|||||||
turntime: ["최근 턴", (gen: GeneralListItemP1) => gen.turntime, false, (gen: GeneralListItemP1) => ""],
|
turntime: ["최근 턴", (gen: GeneralListItemP1) => gen.turntime, false, (gen: GeneralListItemP1) => ""],
|
||||||
name: ["이름", (gen: GeneralListItemP1) => `${gen.npc} ${gen.name}`, true, (gen: GeneralListItemP1) => ""],
|
name: ["이름", (gen: GeneralListItemP1) => `${gen.npc} ${gen.name}`, true, (gen: GeneralListItemP1) => ""],
|
||||||
} as const;
|
} as const;
|
||||||
|
const turnTerm = ref<number>(1);
|
||||||
|
const lastExecuted = ref<Date>(new Date());
|
||||||
|
|
||||||
const orderedGeneralList = ref<GeneralListItemP1[]>([]);
|
const orderedGeneralList = ref<GeneralListItemP1[]>([]);
|
||||||
|
const orderedInvGeneralKeyIndex = ref(new Map<number, number>());
|
||||||
|
|
||||||
const orderBy = ref<keyof typeof textMap>("turntime");
|
const orderBy = ref<keyof typeof textMap>("turntime");
|
||||||
const targetGeneral = ref<GeneralListItemP1>();
|
const targetGeneral = ref<GeneralListItemP1>();
|
||||||
const targetGeneralID = ref(queryValues.generalID ?? undefined);
|
const targetGeneralID = ref(queryValues.generalID ?? undefined);
|
||||||
@@ -172,7 +188,15 @@ watch([generalList, orderBy], ([generalList, orderBy], [, oldOrderBy]) => {
|
|||||||
if (aVal === bVal) return 0;
|
if (aVal === bVal) return 0;
|
||||||
return isAsc ? (aVal > bVal ? 1 : -1) : aVal < bVal ? 1 : -1;
|
return isAsc ? (aVal > bVal ? 1 : -1) : aVal < bVal ? 1 : -1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const invIndex = new Map<number, number>();
|
||||||
|
for (const [idx, gen] of list.entries()) {
|
||||||
|
invIndex.set(gen.no, idx);
|
||||||
|
}
|
||||||
|
|
||||||
orderedGeneralList.value = list;
|
orderedGeneralList.value = list;
|
||||||
|
orderedInvGeneralKeyIndex.value = invIndex;
|
||||||
|
|
||||||
const oldTargetGeneralID = targetGeneralID.value;
|
const oldTargetGeneralID = targetGeneralID.value;
|
||||||
if (!oldTargetGeneralID) {
|
if (!oldTargetGeneralID) {
|
||||||
targetGeneralID.value = list[0].no;
|
targetGeneralID.value = list[0].no;
|
||||||
@@ -181,6 +205,27 @@ watch([generalList, orderBy], ([generalList, orderBy], [, oldOrderBy]) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function changeTargetByOffset(idx: number) {
|
||||||
|
const targetID = targetGeneralID.value;
|
||||||
|
if (targetID === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currIdx = orderedInvGeneralKeyIndex.value.get(targetID);
|
||||||
|
if (currIdx === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let newIdx = currIdx + idx;
|
||||||
|
const listLen = orderedGeneralList.value.length;
|
||||||
|
while (newIdx < 0) {
|
||||||
|
newIdx += listLen;
|
||||||
|
}
|
||||||
|
newIdx = newIdx % listLen;
|
||||||
|
|
||||||
|
targetGeneralID.value = orderedGeneralList.value[newIdx].no;
|
||||||
|
}
|
||||||
|
|
||||||
const asyncReady = ref(false);
|
const asyncReady = ref(false);
|
||||||
const gameConstStore = ref<GameConstStore>();
|
const gameConstStore = ref<GameConstStore>();
|
||||||
provide("gameConstStore", gameConstStore);
|
provide("gameConstStore", gameConstStore);
|
||||||
@@ -203,6 +248,9 @@ async function reload(): Promise<void> {
|
|||||||
throw "권한이 부족합니다.";
|
throw "권한이 부족합니다.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
turnTerm.value = env.turnterm;
|
||||||
|
lastExecuted.value = parseTime(env.turntime);
|
||||||
|
|
||||||
console.log(list);
|
console.log(list);
|
||||||
const rawGeneralList = merge2DArrToObjectArr(column, list);
|
const rawGeneralList = merge2DArrToObjectArr(column, list);
|
||||||
|
|
||||||
|
|||||||
+134
-46
@@ -14,6 +14,11 @@
|
|||||||
<div class="troopLeaderName">
|
<div class="troopLeaderName">
|
||||||
{{ troop.troopLeader.name }}
|
{{ troop.troopLeader.name }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="troopReservedCommand">
|
||||||
|
<div v-for="(brief, idx) in troop.reservedCommandBrief" :key="idx">
|
||||||
|
{{ `${idx + 1}: ${brief}` }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="troopMembers">
|
<div class="troopMembers">
|
||||||
<template v-for="(member, idx) in troop.members" :key="member.no">
|
<template v-for="(member, idx) in troop.members" :key="member.no">
|
||||||
<template v-if="idx != 0">, </template>
|
<template v-if="idx != 0">, </template>
|
||||||
@@ -26,25 +31,29 @@
|
|||||||
{{ member.name }}
|
{{ member.name }}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-else
|
v-else-if="troop.troopLeader.city == member.city"
|
||||||
class="troopMember"
|
class="troopMember"
|
||||||
@mouseover="setPopup($event, member)"
|
@mouseover="setPopup($event, member)"
|
||||||
@mouseout="setPopup($event, undefined)"
|
@mouseout="setPopup($event, undefined)"
|
||||||
>
|
>
|
||||||
{{ member.name }}
|
{{ member.name }}
|
||||||
</span>
|
</span>
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
class="troopMember troopDiffCityMemeber"
|
||||||
|
@mouseover="setPopup($event, member)"
|
||||||
|
@mouseout="setPopup($event, undefined)"
|
||||||
|
>
|
||||||
|
{{ member.name }} ({{ gameConstStore.cityConst[member.city].name }})
|
||||||
|
</span>
|
||||||
</template>
|
</template>
|
||||||
({{ troop.members.length }}명)
|
({{ troop.members.length }}명)
|
||||||
</div>
|
</div>
|
||||||
<div class="troopReservedCommand">
|
|
||||||
<div v-for="(brief, idx) in troop.reservedCommandBrief" :key="idx">
|
|
||||||
{{ `${idx + 1}: ${brief}` }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="troopAction">
|
<div class="troopAction">
|
||||||
<div
|
<div
|
||||||
v-if="tryTroopActionTarget.type === undefined || tryTroopActionTarget.targetTroop !== troop.troopID"
|
v-if="tryTroopActionTarget.type === undefined || tryTroopActionTarget.targetTroop !== troop.troopID"
|
||||||
class="d-grid"
|
class="actionButtons"
|
||||||
>
|
>
|
||||||
<BButton v-if="!me.troop" variant="primary" @click="joinTroop(troop.troopID)">부대 탑승</BButton>
|
<BButton v-if="!me.troop" variant="primary" @click="joinTroop(troop.troopID)">부대 탑승</BButton>
|
||||||
<BButton
|
<BButton
|
||||||
@@ -53,32 +62,30 @@
|
|||||||
@click="exitTroop()"
|
@click="exitTroop()"
|
||||||
>{{ me.no == me.troop ? "부대 해산" : "부대 탈퇴" }}</BButton
|
>{{ me.no == me.troop ? "부대 해산" : "부대 탈퇴" }}</BButton
|
||||||
>
|
>
|
||||||
<BButton
|
<BButton v-if="me.troop == troop.troopID && me.no == me.troop" @click="openKickTroopMemberDialog(troop)"
|
||||||
v-if="me.troop == troop.troopID && me.no == me.troop"
|
|
||||||
@click="openKickTroopMemberDialog(troop)"
|
|
||||||
>부대원 추방...</BButton
|
>부대원 추방...</BButton
|
||||||
>
|
>
|
||||||
<BButton variant="info" @click="openChangeTroopNameDialog(troop)"
|
<BButton v-if="myPermission >= 4" variant="info" @click="openChangeTroopNameDialog(troop)"
|
||||||
>부대명 변경...</BButton
|
>부대명 변경...</BButton
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="tryTroopActionTarget.type === 'changeName'" class="row gx-0">
|
<div v-else-if="tryTroopActionTarget.type === 'changeName'" class="subDialog">
|
||||||
<div class="col-12 bg1 center" style="padding: 0.2em">부대명 변경</div>
|
<div class="subTitle bg1 center"><span>부대명 변경</span></div>
|
||||||
<div class="col-12 d-grid">
|
<div class="subForm d-grid">
|
||||||
<BFormInput v-model="newTroopName" :trim="true" type="text" />
|
<BFormInput v-model="newTroopName" :trim="true" type="text" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 d-grid">
|
<div class="subBtnCancel d-grid">
|
||||||
<BButton variant="secondary" @click="tryTroopActionTarget = { type: undefined, targetTroop: 0 }"
|
<BButton variant="secondary" @click="tryTroopActionTarget = { type: undefined, targetTroop: 0 }"
|
||||||
>취소</BButton
|
>취소</BButton
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 d-grid">
|
<div class="subBtnOK d-grid">
|
||||||
<BButton variant="primary" @click="changeTroopName(troop)">변경</BButton>
|
<BButton variant="primary" @click="changeTroopName(troop)">변경</BButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="tryTroopActionTarget.type === 'kickMember'" class="row gx-0">
|
<div v-else-if="tryTroopActionTarget.type === 'kickMember'" class="subDialog">
|
||||||
<div class="col-12 bg1 center" style="padding: 0.2em">부대명 추방</div>
|
<div class="subTitle bg1 center" style="padding: 0.2em">부대명 추방</div>
|
||||||
<div class="col-12 d-grid">
|
<div class="subForm d-grid">
|
||||||
<BFormSelect v-model="kickTroopMemberID">
|
<BFormSelect v-model="kickTroopMemberID">
|
||||||
<template v-for="member of troop.members" :key="member.no">
|
<template v-for="member of troop.members" :key="member.no">
|
||||||
<BFormSelectOption v-if="member.no != troop.troopID" :value="member.no">
|
<BFormSelectOption v-if="member.no != troop.troopID" :value="member.no">
|
||||||
@@ -87,16 +94,17 @@
|
|||||||
</template>
|
</template>
|
||||||
</BFormSelect>
|
</BFormSelect>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 d-grid">
|
<div class="subBtnCancel d-grid">
|
||||||
<BButton variant="secondary" @click="tryTroopActionTarget = { type: undefined, targetTroop: 0 }"
|
<BButton variant="secondary" @click="tryTroopActionTarget = { type: undefined, targetTroop: 0 }"
|
||||||
>취소</BButton
|
>취소</BButton
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 d-grid">
|
<div class="subBtnOK d-grid">
|
||||||
<BButton variant="primary" @click="kickTroopMember(troop)">추방</BButton>
|
<BButton variant="primary" @click="kickTroopMember(troop)">추방</BButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="filler"><span class="dummy"></span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="asyncReady && gameConstStore && me" class="row additionalTroopOptions">
|
<div v-if="asyncReady && gameConstStore && me" class="row additionalTroopOptions">
|
||||||
@@ -124,6 +132,8 @@
|
|||||||
:general="popupGeneralTarget"
|
:general="popupGeneralTarget"
|
||||||
:troopInfo="convBasicCardTroopInfo(popupGeneralTarget)"
|
:troopInfo="convBasicCardTroopInfo(popupGeneralTarget)"
|
||||||
:nation="nationInfo"
|
:nation="nationInfo"
|
||||||
|
:turnTerm="turnTerm"
|
||||||
|
:lastExecuted="lastExecuted"
|
||||||
/>
|
/>
|
||||||
<GeneralSupplementCard :general="popupGeneralTarget" :showCommandList="true" />
|
<GeneralSupplementCard :general="popupGeneralTarget" :showCommandList="true" />
|
||||||
</template>
|
</template>
|
||||||
@@ -151,6 +161,7 @@ import type { NationStaticItem } from "./defs";
|
|||||||
import GeneralLiteCard from "./components/GeneralLiteCard.vue";
|
import GeneralLiteCard from "./components/GeneralLiteCard.vue";
|
||||||
import GeneralSupplementCard from "./components/GeneralSupplementCard.vue";
|
import GeneralSupplementCard from "./components/GeneralSupplementCard.vue";
|
||||||
import { pick } from "./util/JosaUtil";
|
import { pick } from "./util/JosaUtil";
|
||||||
|
import { parseTime } from "./util/parseTime";
|
||||||
const toasts = unwrap(useToast());
|
const toasts = unwrap(useToast());
|
||||||
|
|
||||||
const asyncReady = ref(false);
|
const asyncReady = ref(false);
|
||||||
@@ -221,6 +232,9 @@ type TroopInfo = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const me = ref<GeneralListItem>({} as GeneralListItem);
|
const me = ref<GeneralListItem>({} as GeneralListItem);
|
||||||
|
const myPermission = ref<0 | 1 | 2 | 3 | 4>(0);
|
||||||
|
const turnTerm = ref<number>(1);
|
||||||
|
const lastExecuted = ref<Date>(new Date());
|
||||||
|
|
||||||
const troopList = ref(new Map<number, TroopInfo>());
|
const troopList = ref(new Map<number, TroopInfo>());
|
||||||
const generalList = ref(new Map<number, GeneralListItem>());
|
const generalList = ref(new Map<number, GeneralListItem>());
|
||||||
@@ -245,6 +259,8 @@ async function refresh() {
|
|||||||
const nationP = SammoAPI.Nation.GetNationInfo({});
|
const nationP = SammoAPI.Nation.GetNationInfo({});
|
||||||
nationInfo.value = (await nationP).nation;
|
nationInfo.value = (await nationP).nation;
|
||||||
const { column, list, permission, troops, env, myGeneralID } = await generalListP;
|
const { column, list, permission, troops, env, myGeneralID } = await generalListP;
|
||||||
|
turnTerm.value = env.turnterm;
|
||||||
|
lastExecuted.value = parseTime(env.turntime);
|
||||||
|
|
||||||
//빠른 턴 순서로 정렬되어있다.
|
//빠른 턴 순서로 정렬되어있다.
|
||||||
|
|
||||||
@@ -277,11 +293,23 @@ async function refresh() {
|
|||||||
throw `?? ${permission}`;
|
throw `?? ${permission}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
myPermission.value = permission;
|
||||||
|
|
||||||
me.value = unwrap(generalList.value.get(myGeneralID));
|
me.value = unwrap(generalList.value.get(myGeneralID));
|
||||||
|
|
||||||
troopList.value = new Map();
|
troopList.value = new Map();
|
||||||
|
|
||||||
for (const { id: troopLeaderID, name: troopName, turntime: troopTurntime, reservedCommand } of troops) {
|
const sortedTroops = troops.sort((lhs, rhs) => {
|
||||||
|
if (lhs.turntime < rhs.turntime) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (lhs.turntime > rhs.turntime) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return lhs.id - rhs.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const { id: troopLeaderID, name: troopName, turntime: troopTurntime, reservedCommand } of sortedTroops) {
|
||||||
if (!generalList.value.has(troopLeaderID)) {
|
if (!generalList.value.has(troopLeaderID)) {
|
||||||
toasts.warning({
|
toasts.warning({
|
||||||
title: "경고",
|
title: "경고",
|
||||||
@@ -410,11 +438,11 @@ async function exitTroop() {
|
|||||||
await refresh();
|
await refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
function openChangeTroopNameDialog(troop: TroopInfo){
|
function openChangeTroopNameDialog(troop: TroopInfo) {
|
||||||
tryTroopActionTarget.value = {
|
tryTroopActionTarget.value = {
|
||||||
type: 'changeName',
|
type: "changeName",
|
||||||
targetTroop: troop.troopID
|
targetTroop: troop.troopID,
|
||||||
}
|
};
|
||||||
newTroopName.value = troop.troopName;
|
newTroopName.value = troop.troopName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,14 +476,13 @@ async function changeTroopName(troop: TroopInfo) {
|
|||||||
await refresh();
|
await refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openKickTroopMemberDialog(troop: TroopInfo) {
|
||||||
function openKickTroopMemberDialog(troop: TroopInfo){
|
|
||||||
tryTroopActionTarget.value = {
|
tryTroopActionTarget.value = {
|
||||||
type: 'kickMember',
|
type: "kickMember",
|
||||||
targetTroop: troop.troopID
|
targetTroop: troop.troopID,
|
||||||
}
|
};
|
||||||
for(const member of troop.members){
|
for (const member of troop.members) {
|
||||||
if(member.no == troop.troopID){
|
if (member.no == troop.troopID) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
kickTroopMemberID.value = member.no;
|
kickTroopMemberID.value = member.no;
|
||||||
@@ -465,7 +492,7 @@ function openKickTroopMemberDialog(troop: TroopInfo){
|
|||||||
|
|
||||||
async function kickTroopMember(troop: TroopInfo) {
|
async function kickTroopMember(troop: TroopInfo) {
|
||||||
const kickMember = generalList.value.get(kickTroopMemberID.value);
|
const kickMember = generalList.value.get(kickTroopMemberID.value);
|
||||||
if(kickMember === undefined){
|
if (kickMember === undefined) {
|
||||||
toasts.danger({
|
toasts.danger({
|
||||||
title: "오류",
|
title: "오류",
|
||||||
body: "잘못된 접근입니다.",
|
body: "잘못된 접근입니다.",
|
||||||
@@ -524,6 +551,10 @@ async function kickTroopMember(troop: TroopInfo) {
|
|||||||
border: solid 1px gray;
|
border: solid 1px gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.troopDiffCityMemeber {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
.troopItem {
|
.troopItem {
|
||||||
display: grid;
|
display: grid;
|
||||||
border-right: solid 1px gray;
|
border-right: solid 1px gray;
|
||||||
@@ -534,7 +565,7 @@ async function kickTroopMember(troop: TroopInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.troopInfo {
|
.troopInfo {
|
||||||
grid-column: 1/2;
|
grid-column: 1/3;
|
||||||
grid-row: 1/2;
|
grid-row: 1/2;
|
||||||
display: grid;
|
display: grid;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
@@ -542,7 +573,7 @@ async function kickTroopMember(troop: TroopInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.troopTurn {
|
.troopTurn {
|
||||||
grid-column: 1/2;
|
grid-column: 1/3;
|
||||||
grid-row: 2/3;
|
grid-row: 2/3;
|
||||||
display: grid;
|
display: grid;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
@@ -550,7 +581,7 @@ async function kickTroopMember(troop: TroopInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.troopLeaderIcon {
|
.troopLeaderIcon {
|
||||||
grid-column: 2/3;
|
grid-column: 3/4;
|
||||||
grid-row: 1/2;
|
grid-row: 1/2;
|
||||||
display: grid;
|
display: grid;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
@@ -558,7 +589,7 @@ async function kickTroopMember(troop: TroopInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.troopLeaderName {
|
.troopLeaderName {
|
||||||
grid-column: 2/3;
|
grid-column: 3/4;
|
||||||
grid-row: 2/3;
|
grid-row: 2/3;
|
||||||
display: grid;
|
display: grid;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -573,7 +604,7 @@ async function kickTroopMember(troop: TroopInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.troopAction {
|
.troopAction {
|
||||||
grid-column: 5/6;
|
grid-column: 6/7;
|
||||||
grid-row: 1/3;
|
grid-row: 1/3;
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
@@ -600,17 +631,51 @@ async function kickTroopMember(troop: TroopInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.troopItem {
|
.troopItem {
|
||||||
grid-template-rows: 65px 28px;
|
grid-template-rows: 65px 28px 34.5px;
|
||||||
grid-template-columns: 130px 130px 1fr 100px 140px;
|
grid-template-columns: 65px 65px 130px 100px 1fr;
|
||||||
|
|
||||||
.troopMembers {
|
.troopMembers {
|
||||||
grid-column: 3/4;
|
grid-column: 5/6;
|
||||||
grid-row: 1/3;
|
grid-row: 1/3;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-of-type {
|
&:last-of-type {
|
||||||
border-bottom: solid 1px gray;
|
border-bottom: solid 1px gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filler {
|
||||||
|
grid-column: 1/2;
|
||||||
|
grid-row: 3/4;
|
||||||
|
display: grid;
|
||||||
|
align-content: center;
|
||||||
|
justify-content: right;
|
||||||
|
|
||||||
|
.dummy::after {
|
||||||
|
content: "└";
|
||||||
|
padding-right: 1.5ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.troopAction {
|
||||||
|
grid-column: 2/7;
|
||||||
|
grid-row: 3/4;
|
||||||
|
border-left: transparent;
|
||||||
|
.actionButtons {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 110px 110px 110px;
|
||||||
|
grid-template-rows: 33.5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.subDialog {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 90px 140px 50px 50px;
|
||||||
|
|
||||||
|
.subTitle {
|
||||||
|
display: grid;
|
||||||
|
align-content: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,19 +692,42 @@ async function kickTroopMember(troop: TroopInfo) {
|
|||||||
|
|
||||||
.troopItem {
|
.troopItem {
|
||||||
grid-template-rows: 65px 28px auto;
|
grid-template-rows: 65px 28px auto;
|
||||||
grid-template-columns: 130px 130px 0px 100px 140px;
|
grid-template-columns: 65px 65px 130px 100px 0px 140px;
|
||||||
|
|
||||||
.troopMembers {
|
.troopMembers {
|
||||||
grid-column: 2/6;
|
grid-column: 3/7;
|
||||||
grid-row: 3/4;
|
grid-row: 3/4;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-of-type {
|
&:last-of-type {
|
||||||
.troopMembers,
|
.troopMembers {
|
||||||
.troopTurn {
|
|
||||||
border-bottom: solid 1px gray;
|
border-bottom: solid 1px gray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filler {
|
||||||
|
border-top: solid 1px gray;
|
||||||
|
grid-column: 1/3;
|
||||||
|
grid-row: 3/4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionButtons {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subDialog {
|
||||||
|
display: grid;
|
||||||
|
height: 100%;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
grid-template-rows: 1fr 1fr 1fr;
|
||||||
|
|
||||||
|
.subTitle,
|
||||||
|
.subForm {
|
||||||
|
display: grid;
|
||||||
|
align-content: center;
|
||||||
|
grid-column: 1/3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="row gx-0">
|
<div class="row gx-0">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<span :style="{ color: injuryInfo.color }">{{ general.leadership }}</span>
|
<span :style="{ color: injuryInfo.color }">{{ calcInjury("leadership", general) }}</span>
|
||||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||||
<span v-if="general.lbonus > 0" style="color: cyan">+{{ general.lbonus }}</span>
|
<span v-if="general.lbonus > 0" style="color: cyan">+{{ general.lbonus }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="row gx-0">
|
<div class="row gx-0">
|
||||||
<div class="col" :style="{ color: injuryInfo.color }">
|
<div class="col" :style="{ color: injuryInfo.color }">
|
||||||
{{ general.strength }}
|
{{ calcInjury("strength", general) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col align-self-center">
|
<div class="col align-self-center">
|
||||||
<SammoBar :height="10" :percent="(general.strength_exp / 20) * 100" />
|
<SammoBar :height="10" :percent="(general.strength_exp / 20) * 100" />
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="row gx-0">
|
<div class="row gx-0">
|
||||||
<div class="col" :style="{ color: injuryInfo.color }">
|
<div class="col" :style="{ color: injuryInfo.color }">
|
||||||
{{ general.intel }}
|
{{ calcInjury("intel", general) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col align-self-center">
|
<div class="col align-self-center">
|
||||||
<SammoBar :height="10" :percent="(general.intel_exp / 20) * 100" />
|
<SammoBar :height="10" :percent="(general.intel_exp / 20) * 100" />
|
||||||
@@ -60,18 +60,24 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg1">명마</div>
|
<div class="bg1">명마</div>
|
||||||
<div v-b-tooltip.hover :title="horse.info ?? '-'">{{ horse.name }}</div>
|
<div v-if="!horse.info">{{ horse.name }}</div>
|
||||||
|
<div v-else v-b-tooltip.hover :title="horse.info">{{ horse.name }}</div>
|
||||||
|
|
||||||
<div class="bg1">무기</div>
|
<div class="bg1">무기</div>
|
||||||
<div v-b-tooltip.hover :title="weapon.info ?? '-'">{{ weapon.name }}</div>
|
<div v-if="!weapon.info">{{ weapon.name }}</div>
|
||||||
|
<div v-else v-b-tooltip.hover :title="weapon.info">{{ weapon.name }}</div>
|
||||||
|
|
||||||
<div class="bg1">서적</div>
|
<div class="bg1">서적</div>
|
||||||
<div v-b-tooltip.hover :title="book.info ?? '-'">{{ book.name }}</div>
|
<div v-if="!book.info">{{ book.name }}</div>
|
||||||
|
<div v-else v-b-tooltip.hover :title="book.info">{{ book.name }}</div>
|
||||||
|
|
||||||
<div class="bg1">자금</div>
|
<div class="bg1">자금</div>
|
||||||
<div>{{ general.gold.toLocaleString() }}</div>
|
<div>{{ general.gold.toLocaleString() }}</div>
|
||||||
<div class="bg1">군량</div>
|
<div class="bg1">군량</div>
|
||||||
<div>{{ general.rice.toLocaleString() }}</div>
|
<div>{{ general.rice.toLocaleString() }}</div>
|
||||||
<div class="bg1">도구</div>
|
<div class="bg1">도구</div>
|
||||||
<div v-b-tooltip.hover :title="item.info ?? '-'">{{ item.name }}</div>
|
<div v-if="!item.info">{{ item.name }}</div>
|
||||||
|
<div v-else v-b-tooltip.hover :title="item.info">{{ item.name }}</div>
|
||||||
|
|
||||||
<!-- TODO: show_img_level을 고려 -->
|
<!-- TODO: show_img_level을 고려 -->
|
||||||
<div
|
<div
|
||||||
@@ -82,11 +88,13 @@
|
|||||||
></div>
|
></div>
|
||||||
|
|
||||||
<div class="bg1">병종</div>
|
<div class="bg1">병종</div>
|
||||||
<div v-b-tooltip.hover :title="crewtype.info ?? '-'">{{ crewtype.name }}</div>
|
<div v-if="!crewtype.info">{{ crewtype.name }}</div>
|
||||||
|
<div v-else v-b-tooltip.hover :title="crewtype.info">{{ crewtype.name }}</div>
|
||||||
<div class="bg1">병사</div>
|
<div class="bg1">병사</div>
|
||||||
<div>{{ general.crew.toLocaleString() }}</div>
|
<div>{{ general.crew.toLocaleString() }}</div>
|
||||||
<div class="bg1">성격</div>
|
<div class="bg1">성격</div>
|
||||||
<div v-b-tooltip.hover :title="personal.info ?? '-'">{{ personal.name }}</div>
|
<div v-if="!personal.info">{{ personal.name }}</div>
|
||||||
|
<div v-else v-b-tooltip.hover :title="personal.info">{{ personal.name }}</div>
|
||||||
|
|
||||||
<!-- TODO: bonusTrain 같은 개념이 필요 -->
|
<!-- TODO: bonusTrain 같은 개념이 필요 -->
|
||||||
<div class="bg1">훈련</div>
|
<div class="bg1">훈련</div>
|
||||||
@@ -95,8 +103,11 @@
|
|||||||
<div>{{ general.atmos }}</div>
|
<div>{{ general.atmos }}</div>
|
||||||
<div class="bg1">특기</div>
|
<div class="bg1">특기</div>
|
||||||
<div>
|
<div>
|
||||||
<span v-b-tooltip.hover :title="specialDomestic.info ?? '-'"> {{ specialDomestic.name }}</span> /
|
<span v-if="!specialDomestic.info"> {{ specialDomestic.name }}</span
|
||||||
<span v-b-tooltip.hover :title="specialWar.info ?? '-'"> {{ specialWar.name }}</span>
|
><span v-else v-b-tooltip.hover :title="specialDomestic.info"> {{ specialDomestic.name }}</span>
|
||||||
|
/
|
||||||
|
<span v-if="!specialWar.info"> {{ specialWar.name }}</span
|
||||||
|
><span v-else v-b-tooltip.hover :title="specialWar.info"> {{ specialWar.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg1">Lv</div>
|
<div class="bg1">Lv</div>
|
||||||
@@ -148,7 +159,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { GeneralListItemP1 } from "@/defs/API/Nation";
|
import type { GeneralListItemP1 } from "@/defs/API/Nation";
|
||||||
import { computed, inject, onMounted, ref, toRefs, type Ref } from "vue";
|
import { inject, ref, toRefs, watch, type Ref } from "vue";
|
||||||
import { getIconPath } from "@/util/getIconPath";
|
import { getIconPath } from "@/util/getIconPath";
|
||||||
import { isBrightColor } from "@/util/isBrightColor";
|
import { isBrightColor } from "@/util/isBrightColor";
|
||||||
import { formatInjury } from "@/utilGame/formatInjury";
|
import { formatInjury } from "@/utilGame/formatInjury";
|
||||||
@@ -163,6 +174,10 @@ import { parseTime } from "@/util/parseTime";
|
|||||||
import { clamp } from "lodash";
|
import { clamp } from "lodash";
|
||||||
import { formatCityName } from "@/utilGame/formatCityName";
|
import { formatCityName } from "@/utilGame/formatCityName";
|
||||||
import { isValidObjKey } from "@/utilGame/isValidObjKey";
|
import { isValidObjKey } from "@/utilGame/isValidObjKey";
|
||||||
|
import { calcInjury } from "@/utilGame/calcInjury";
|
||||||
|
import { addMinutes } from "date-fns/esm";
|
||||||
|
import type { GameIActionInfo } from "@/defs/GameObj";
|
||||||
|
|
||||||
const imagePath = window.pathConfig.gameImage;
|
const imagePath = window.pathConfig.gameImage;
|
||||||
const gameConstStore = unwrap(inject<Ref<GameConstStore>>("gameConstStore"));
|
const gameConstStore = unwrap(inject<Ref<GameConstStore>>("gameConstStore"));
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -172,95 +187,99 @@ const props = defineProps<{
|
|||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
nation: NationStaticItem;
|
nation: NationStaticItem;
|
||||||
|
turnTerm: number;
|
||||||
|
lastExecuted: Date;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { general, troopInfo, nation } = toRefs(props);
|
const { general, troopInfo, nation } = toRefs(props);
|
||||||
const iconPath = computed(() => getIconPath(general.value.imgsvr, general.value.picture));
|
const iconPath = ref("");
|
||||||
const injuryInfo = computed(() => {
|
|
||||||
const [text, color] = formatInjury(general.value.injury);
|
|
||||||
return {
|
|
||||||
text,
|
|
||||||
color,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const generalTypeCall = computed(() =>
|
|
||||||
formatGeneralTypeCall(
|
|
||||||
general.value.leadership,
|
|
||||||
general.value.strength,
|
|
||||||
general.value.intel,
|
|
||||||
gameConstStore.value.gameConst
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const horse = computed(() =>
|
const injuryInfo = ref<{ text: string; color: string }>({ text: "-", color: "white" });
|
||||||
isValidObjKey(general.value.horse)
|
const generalTypeCall = ref<string>("-");
|
||||||
? gameConstStore.value.iActionInfo.item[general.value.horse]
|
|
||||||
: { value: "None", name: "-", info: "" }
|
|
||||||
);
|
|
||||||
const weapon = computed(() =>
|
|
||||||
isValidObjKey(general.value.weapon)
|
|
||||||
? gameConstStore.value.iActionInfo.item[general.value.weapon]
|
|
||||||
: { value: "None", name: "-", info: "" }
|
|
||||||
);
|
|
||||||
const book = computed(() =>
|
|
||||||
isValidObjKey(general.value.book)
|
|
||||||
? gameConstStore.value.iActionInfo.item[general.value.book]
|
|
||||||
: { value: "None", name: "-", info: "" }
|
|
||||||
);
|
|
||||||
const item = computed(() =>
|
|
||||||
isValidObjKey(general.value.item)
|
|
||||||
? gameConstStore.value.iActionInfo.item[general.value.item]
|
|
||||||
: { value: "None", name: "-", info: "" }
|
|
||||||
);
|
|
||||||
|
|
||||||
const crewtype = computed(() =>
|
const ageColor = ref<string>("limegreen");
|
||||||
isValidObjKey(general.value.crewtype)
|
|
||||||
? gameConstStore.value.iActionInfo.crewtype[general.value.crewtype]
|
|
||||||
: { value: "None", name: "-", info: "-" }
|
|
||||||
);
|
|
||||||
|
|
||||||
const personal = computed(() =>
|
watch(
|
||||||
isValidObjKey(general.value.personal)
|
general,
|
||||||
? gameConstStore.value.iActionInfo.personality[general.value.personal]
|
(general) => {
|
||||||
: { value: "None", name: "-", info: "-" }
|
iconPath.value = getIconPath(general.imgsvr, general.picture);
|
||||||
);
|
|
||||||
const specialDomestic = computed(() =>
|
const [text, color] = formatInjury(general.injury);
|
||||||
isValidObjKey(general.value.specialDomestic)
|
injuryInfo.value = { text, color };
|
||||||
? gameConstStore.value.iActionInfo.specialDomestic[general.value.specialDomestic]
|
|
||||||
: {
|
generalTypeCall.value = formatGeneralTypeCall(
|
||||||
value: "None",
|
general.leadership,
|
||||||
name: `${Math.max(general.value.age + 1, general.value.specage)}세`,
|
general.strength,
|
||||||
info: '-',
|
general.intel,
|
||||||
|
gameConstStore.value.gameConst
|
||||||
|
);
|
||||||
|
|
||||||
|
ageColor.value = (() => {
|
||||||
|
const age = general.age;
|
||||||
|
const retirementYear = gameConstStore.value.gameConst.retirementYear;
|
||||||
|
if (age < retirementYear * 0.75) {
|
||||||
|
return "limegreen";
|
||||||
}
|
}
|
||||||
);
|
if (age < retirementYear) {
|
||||||
const specialWar = computed(() =>
|
return "yellow";
|
||||||
isValidObjKey(general.value.specialWar)
|
|
||||||
? gameConstStore.value.iActionInfo.specialWar[general.value.specialWar]
|
|
||||||
: {
|
|
||||||
value: "None",
|
|
||||||
name: `${Math.max(general.value.age + 1, general.value.specage2)}세`,
|
|
||||||
info: '-',
|
|
||||||
}
|
}
|
||||||
|
return "red";
|
||||||
|
})();
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
const ageColor = computed(() => {
|
const dummyInfo: GameIActionInfo = { value: "None", name: "-", info: "" };
|
||||||
const age = general.value.age;
|
|
||||||
const retirementYear = gameConstStore.value.gameConst.retirementYear;
|
const horse = ref<GameIActionInfo>(dummyInfo);
|
||||||
if (age < retirementYear * 0.75) {
|
const weapon = ref<GameIActionInfo>(dummyInfo);
|
||||||
return "limegreen";
|
const book = ref<GameIActionInfo>(dummyInfo);
|
||||||
}
|
const item = ref<GameIActionInfo>(dummyInfo);
|
||||||
if (age < retirementYear) {
|
|
||||||
return "yellow";
|
const crewtype = ref<GameIActionInfo>(dummyInfo);
|
||||||
}
|
|
||||||
return "red";
|
const personal = ref<GameIActionInfo>(dummyInfo);
|
||||||
});
|
const specialDomestic = ref<GameIActionInfo>(dummyInfo);
|
||||||
|
const specialWar = ref<GameIActionInfo>(dummyInfo);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
general,
|
||||||
|
(general) => {
|
||||||
|
horse.value = !isValidObjKey(general.horse) ? dummyInfo : gameConstStore.value.iActionInfo.item[general.horse];
|
||||||
|
weapon.value = !isValidObjKey(general.weapon) ? dummyInfo : gameConstStore.value.iActionInfo.item[general.weapon];
|
||||||
|
book.value = !isValidObjKey(general.book) ? dummyInfo : gameConstStore.value.iActionInfo.item[general.book];
|
||||||
|
item.value = !isValidObjKey(general.item) ? dummyInfo : gameConstStore.value.iActionInfo.item[general.item];
|
||||||
|
|
||||||
|
crewtype.value = !isValidObjKey(general.crewtype)
|
||||||
|
? dummyInfo
|
||||||
|
: gameConstStore.value.iActionInfo.crewtype[general.crewtype];
|
||||||
|
|
||||||
|
personal.value = !isValidObjKey(general.personal)
|
||||||
|
? dummyInfo
|
||||||
|
: gameConstStore.value.iActionInfo.personality[general.personal];
|
||||||
|
|
||||||
|
specialDomestic.value = !isValidObjKey(general.specialDomestic)
|
||||||
|
? { value: "None", name: `${Math.max(general.age + 1, general.specage)}세`, info: "-" }
|
||||||
|
: gameConstStore.value.iActionInfo.specialDomestic[general.specialDomestic];
|
||||||
|
specialWar.value = !isValidObjKey(general.specialWar)
|
||||||
|
? { value: "None", name: `${Math.max(general.age + 1, general.specage2)}세`, info: "-" }
|
||||||
|
: gameConstStore.value.iActionInfo.specialWar[general.specialWar];
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
const nextExecuteMinute = ref(999);
|
const nextExecuteMinute = ref(999);
|
||||||
onMounted(() => {
|
watch(
|
||||||
const now = new Date();
|
general,
|
||||||
const turnTime = parseTime(general.value.turntime);
|
() => {
|
||||||
nextExecuteMinute.value = Math.floor(clamp(turnTime.getSeconds() - now.getSeconds() / 60, 0));
|
let turnTime = parseTime(general.value.turntime);
|
||||||
});
|
if (turnTime.getTime() < props.lastExecuted.getTime()) {
|
||||||
|
turnTime = addMinutes(turnTime, props.turnTerm);
|
||||||
|
}
|
||||||
|
nextExecuteMinute.value = Math.floor(clamp((turnTime.getTime() - props.lastExecuted.getTime()) / 60000, 0, 999));
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="row gx-0">
|
<div class="row gx-0">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<span :style="{ color: injuryInfo.color }">{{ general.leadership }}</span>
|
<span :style="{ color: injuryInfo.color }">{{ calcInjury("leadership", general) }}</span>
|
||||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||||
<span v-if="general.lbonus > 0" style="color: cyan">+{{ general.lbonus }}</span>
|
<span v-if="general.lbonus > 0" style="color: cyan">+{{ general.lbonus }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="row gx-0">
|
<div class="row gx-0">
|
||||||
<div class="col" :style="{ color: injuryInfo.color }">
|
<div class="col" :style="{ color: injuryInfo.color }">
|
||||||
{{ general.strength }}
|
{{ calcInjury("strength", general) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="row gx-0">
|
<div class="row gx-0">
|
||||||
<div class="col" :style="{ color: injuryInfo.color }">
|
<div class="col" :style="{ color: injuryInfo.color }">
|
||||||
{{ general.intel }}
|
{{ calcInjury("intel", general) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,7 +51,8 @@
|
|||||||
<div class="bg1">군량</div>
|
<div class="bg1">군량</div>
|
||||||
<div>{{ general.rice.toLocaleString() }}</div>
|
<div>{{ general.rice.toLocaleString() }}</div>
|
||||||
<div class="bg1">성격</div>
|
<div class="bg1">성격</div>
|
||||||
<div v-b-tooltip.hover :title="personal.info ?? undefined">{{ personal.name }}</div>
|
<div v-if="!personal.info">{{ personal.name }}</div>
|
||||||
|
<div v-else v-b-tooltip.hover :title="personal.info">{{ personal.name }}</div>
|
||||||
|
|
||||||
<div class="filler"></div>
|
<div class="filler"></div>
|
||||||
<div class="bg1">Lv</div>
|
<div class="bg1">Lv</div>
|
||||||
@@ -64,8 +65,11 @@
|
|||||||
|
|
||||||
<div class="bg1">특기</div>
|
<div class="bg1">특기</div>
|
||||||
<div>
|
<div>
|
||||||
<span v-b-tooltip.hover :title="specialDomestic.info ?? undefined"> {{ specialDomestic.name }}</span> /
|
<span v-if="!specialDomestic.info"> {{ specialDomestic.name }}</span
|
||||||
<span v-b-tooltip.hover :title="specialWar.info ?? undefined"> {{ specialWar.name }}</span>
|
><span v-else v-b-tooltip.hover :title="specialDomestic.info"> {{ specialDomestic.name }}</span>
|
||||||
|
/
|
||||||
|
<span v-if="!specialWar.info"> {{ specialWar.name }}</span
|
||||||
|
><span v-else v-b-tooltip.hover :title="specialWar.info"> {{ specialWar.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="filler"></div>
|
<div class="filler"></div>
|
||||||
@@ -82,7 +86,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { GeneralListItemP0 } from "@/defs/API/Nation";
|
import type { GeneralListItemP0 } from "@/defs/API/Nation";
|
||||||
import { computed, inject, toRefs, type Ref } from "vue";
|
import { computed, inject, ref, toRefs, watch, type Ref } from "vue";
|
||||||
import { getIconPath } from "@/util/getIconPath";
|
import { getIconPath } from "@/util/getIconPath";
|
||||||
import { isBrightColor } from "@/util/isBrightColor";
|
import { isBrightColor } from "@/util/isBrightColor";
|
||||||
import { formatInjury } from "@/utilGame/formatInjury";
|
import { formatInjury } from "@/utilGame/formatInjury";
|
||||||
@@ -91,6 +95,10 @@ import { unwrap } from "@/util/unwrap";
|
|||||||
import type { GameConstStore } from "@/GameConstStore";
|
import type { GameConstStore } from "@/GameConstStore";
|
||||||
import { formatGeneralTypeCall } from "@/utilGame/formatGeneralTypeCall";
|
import { formatGeneralTypeCall } from "@/utilGame/formatGeneralTypeCall";
|
||||||
import { formatConnectScore } from "@/utilGame/formatConnectScore";
|
import { formatConnectScore } from "@/utilGame/formatConnectScore";
|
||||||
|
import { calcInjury } from "@/utilGame/calcInjury";
|
||||||
|
import type { GameIActionInfo } from "@/defs/GameObj";
|
||||||
|
import { isValidObjKey } from "@/utilGame/isValidObjKey";
|
||||||
|
|
||||||
const gameConstStore = unwrap(inject<Ref<GameConstStore>>("gameConstStore"));
|
const gameConstStore = unwrap(inject<Ref<GameConstStore>>("gameConstStore"));
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
general: GeneralListItemP0;
|
general: GeneralListItemP0;
|
||||||
@@ -98,52 +106,65 @@ const props = defineProps<{
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { general, nation } = toRefs(props);
|
const { general, nation } = toRefs(props);
|
||||||
const iconPath = computed(() => getIconPath(general.value.imgsvr, general.value.picture));
|
const iconPath = ref("");
|
||||||
const injuryInfo = computed(() => {
|
|
||||||
const [text, color] = formatInjury(general.value.injury);
|
const injuryInfo = ref<{ text: string; color: string }>({ text: "-", color: "white" });
|
||||||
return {
|
const generalTypeCall = ref<string>("-");
|
||||||
text,
|
|
||||||
color,
|
const ageColor = ref<string>("limegreen");
|
||||||
};
|
|
||||||
});
|
watch(
|
||||||
const generalTypeCall = computed(() =>
|
general,
|
||||||
formatGeneralTypeCall(
|
(general) => {
|
||||||
general.value.leadership,
|
iconPath.value = getIconPath(general.imgsvr, general.picture);
|
||||||
general.value.strength,
|
|
||||||
general.value.intel,
|
const [text, color] = formatInjury(general.injury);
|
||||||
gameConstStore.value.gameConst
|
injuryInfo.value = { text, color };
|
||||||
)
|
|
||||||
|
generalTypeCall.value = formatGeneralTypeCall(
|
||||||
|
general.leadership,
|
||||||
|
general.strength,
|
||||||
|
general.intel,
|
||||||
|
gameConstStore.value.gameConst
|
||||||
|
);
|
||||||
|
|
||||||
|
ageColor.value = (() => {
|
||||||
|
const age = general.age;
|
||||||
|
const retirementYear = gameConstStore.value.gameConst.retirementYear;
|
||||||
|
if (age < retirementYear * 0.75) {
|
||||||
|
return "limegreen";
|
||||||
|
}
|
||||||
|
if (age < retirementYear) {
|
||||||
|
return "yellow";
|
||||||
|
}
|
||||||
|
return "red";
|
||||||
|
})();
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
const personal = computed(
|
const dummyInfo: GameIActionInfo = { value: "None", name: "-", info: "" };
|
||||||
() => gameConstStore.value.iActionInfo.personality[general.value.personal] ?? { value: "None", name: "-" }
|
|
||||||
);
|
|
||||||
const specialDomestic = computed(
|
|
||||||
() =>
|
|
||||||
gameConstStore.value.iActionInfo.specialDomestic[general.value.specialDomestic] ?? {
|
|
||||||
value: "None",
|
|
||||||
name: `-`,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const specialWar = computed(
|
|
||||||
() =>
|
|
||||||
gameConstStore.value.iActionInfo.specialWar[general.value.specialWar] ?? {
|
|
||||||
value: "None",
|
|
||||||
name: `-`,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const ageColor = computed(() => {
|
const personal = ref<GameIActionInfo>(dummyInfo);
|
||||||
const age = general.value.age;
|
const specialDomestic = ref<GameIActionInfo>(dummyInfo);
|
||||||
const retirementYear = gameConstStore.value.gameConst.retirementYear;
|
const specialWar = ref<GameIActionInfo>(dummyInfo);
|
||||||
if (age < retirementYear * 0.75) {
|
|
||||||
return "limegreen";
|
watch(
|
||||||
}
|
general,
|
||||||
if (age < retirementYear) {
|
(general) => {
|
||||||
return "yellow";
|
personal.value = !isValidObjKey(general.personal)
|
||||||
}
|
? dummyInfo
|
||||||
return "red";
|
: gameConstStore.value.iActionInfo.personality[general.personal];
|
||||||
});
|
|
||||||
|
specialDomestic.value = !isValidObjKey(general.specialDomestic)
|
||||||
|
? dummyInfo
|
||||||
|
: gameConstStore.value.iActionInfo.specialDomestic[general.specialDomestic];
|
||||||
|
specialWar.value = !isValidObjKey(general.specialWar)
|
||||||
|
? dummyInfo
|
||||||
|
: gameConstStore.value.iActionInfo.specialWar[general.specialWar];
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import type { GeneralListItemP0 } from "@/defs/API/Nation";
|
||||||
|
|
||||||
|
export function calcInjury(statKey: 'leadership'|'strength'|'intel', general: GeneralListItemP0){
|
||||||
|
const baseStat = general[statKey];
|
||||||
|
return Math.round(baseStat * (100 -general.injury) / 100);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user