This commit is contained in:
AncTe committed 2023-01-16 22:32:04 +08:00
1 parent 5f48eef6af
commit e471648e52
10 files changed
+680 -588

No files matched your search

+17 -14
View File
@@ -66,7 +66,7 @@ export function getMarkInfo(id: EnemyIds, noMessage: boolean = false) {
tip('success', `踩到了${core.material.enemys[id].name}的临界!`);
}
reached[info.nextCritical] = true;
const n = core.nextCriticals(id, 1)[0]?.[0];
const n = core.nextCriticals(id, 1, void 0, void 0, 'empty')[0]?.[0];
const next = (n ?? 0) + core.status.hero.atk;
info.nextCritical = next;
}
@@ -80,37 +80,40 @@ export function checkMarkedEnemy(noMessage: boolean = false) {
const hp = core.status.hero.hp;
getMarkedEnemy().forEach(v => {
getMarkInfo(v);
const damage = core.getDamageInfo(v)?.damage ?? -1;
const damage =
core.getDamageInfo(v, void 0, void 0, void 0, 'empty')?.damage ??
-1;
if (damage === -1) return;
const info = enemyDamageInfo[v]!;
const name = core.material.enemys[v].name;
let res = 0;
if (damage <= 0) {
if (!noMessage) tip('success', `${name}已经零伤了!`);
} else if (damage < hp / 3) {
if (!info[3] && !noMessage) {
tip('success', `${name}的伤害已降至勇士生命值的1/3!`);
}
info[1] = true;
info[2] = true;
info[3] = true;
res = 0b111;
} else if (damage < (hp / 3) * 2) {
if (!info[2] && !noMessage) {
tip('success', `${name}的伤害已降至勇士生命值的2/3!`);
}
info[1] = true;
info[2] = true;
info[3] = false;
res = 0b110;
} else if (damage < hp) {
if (!info[1] && !noMessage) {
tip('success', `你已经能打过${name}了!`);
}
res = 0b100;
}
info[1] = info[2] = info[3] = false;
if (res & 0b100) {
info[1] = true;
info[2] = false;
info[3] = false;
} else {
info[1] = false;
info[2] = false;
info[3] = false;
}
if (res & 0b010) {
info[2] = true;
}
if (res & 0b001) {
info[3] = true;
}
});
}
+6 -2
View File
@@ -9,6 +9,7 @@ import Skill from '../ui/skill.vue';
import SkillTree from '../ui/skillTree.vue';
import Fly from '../ui/fly.vue';
import FixedDetail from '../ui/fixedDetail.vue';
import Shop from '../ui/shop.vue';
export const bookOpened = ref(false);
export const toolOpened = ref(false);
@@ -21,6 +22,7 @@ export const skillTreeOpened = ref(false);
export const flyOpened = ref(false);
export const showStudiedSkill = ref(false);
export const fixedDetailOpened = ref(false);
export const shopOpened = ref(false);
export const transition = ref(true);
export const noClosePanel = ref(false);
@@ -37,7 +39,8 @@ const UI_LIST: [Ref<boolean>, Component][] = [
[skillOpened, Skill],
[skillTreeOpened, SkillTree],
[flyOpened, Fly],
[fixedDetailOpened, FixedDetail]
[fixedDetailOpened, FixedDetail],
[shopOpened, Shop]
];
/** ui栈 */
@@ -74,7 +77,8 @@ export default function init() {
skillTreeOpened,
flyOpened,
showStudiedSkill,
fixedDetailOpened
fixedDetailOpened,
shopOpened
};
}
+2 -2
View File
@@ -12,13 +12,13 @@ interface ItemDeclaration {
greenPotion: 'items';
sword0: 'items';
sword1: 'equips';
sword2: 'items';
sword2: 'equips';
sword3: 'items';
sword4: 'items';
sword5: 'items';
shield0: 'items';
shield1: 'equips';
shield2: 'items';
shield2: 'equips';
shield3: 'items';
shield4: 'items';
shield5: 'items';
+14
View File
@@ -25,6 +25,7 @@
transition: color 0.2s linear;
}
.button-text[active='true'],
.button-text:hover {
color: aqua;
}
@@ -33,6 +34,19 @@
color: aquamarine;
}
.button-text[danger='true'][danger-display='true'] {
color: rgb(255, 47, 47);
}
.button-text[danger='true']:hover,
.button-text[danger='true'][active='true'] {
color: rgb(255, 120, 120);
}
.button-text[danger='true']:active {
color: rgb(255, 182, 182);
}
.selectable {
border: #0000 0.5px solid;
padding: 1% 3% 1% 3%;
+6
View File
@@ -152,6 +152,9 @@ interface PluginUis {
/** 定点查看的界面,特殊属性还是临界 */
fixedDetailPanel: 'special' | 'critical';
/** 打开的商店id */
openedShopId: string;
/** ui是否使用渐变 */
readonly transition: Ref<boolean>;
@@ -200,6 +203,9 @@ interface PluginUis {
/** 是否展示移动鼠标显示怪物信息的盒子 */
readonly showFixed: Ref<boolean>;
/** 商店是否打开 */
readonly shopOpened: Ref<boolean>;
/** ui栈 */
readonly uiStack: Ref<Component[]>;
+450
View File
@@ -0,0 +1,450 @@
<template>
<div id="shop">
<div id="tools">
<span class="button-text" @click="exit"
><left-outlined /> 返回游戏</span
>
</div>
<span id="item-name">{{ info.name }}</span>
<a-divider dashed style="border-color: #ddd4" id="divider"></a-divider>
<div id="item-info">
<Scroll id="item-desc" :no-scroll="true">
<span v-html="desc"></span>
</Scroll>
</div>
<a-divider
dashed
style="border-color: #ddd4"
id="divider-split"
></a-divider>
<div id="shop-bottom">
<div id="item-list">
<Scroll style="width: 100%; height: 100%">
<div
class="selectable item-one"
v-for="(i, index) of choices"
:selected="index === selected"
@click="selected = index"
>
<div class="item-icon">
<BoxAnimate
:id="i.id"
:noborder="true"
></BoxAnimate>
<span>{{ all[i.id].name }}</span>
</div>
<span
>×&nbsp;{{
(mode === 'buy'
? i.number - (f.itemShop[id]?.[i.id] ?? 0)
: cnt(i.id)) + (update ? 0 : 0)
}}</span
>
</div>
</Scroll>
</div>
<a-divider
dashed
style="border-color: #ddd4"
:type="isMobile ? 'horizontal' : 'vertical'"
id="divider-vertical"
></a-divider>
<div id="item-sell-info">
<div id="shop-mode">
<span
class="button-text mode-button"
:active="mode === 'buy'"
@click="mode = 'buy'"
>购买</span
>
<a-divider
dashed
type="vertical"
id="divider-vertical"
style="border-color: #ddd4"
></a-divider>
<span
class="button-text mode-button"
:active="mode === 'sell'"
danger="true"
@click="mode = 'sell'"
>售出</span
>
</div>
<a-divider
dashed
style="border-color: #ddd4"
id="divider-mode"
></a-divider>
<div
class="item-sell-info"
:style="{ color: mode === 'buy' ? 'lightgreen' : 'white' }"
>
<span>买价</span>
<span>{{ item.money }}</span>
</div>
<div
class="item-sell-info"
:style="{ color: mode === 'sell' ? 'lightcoral' : 'white' }"
>
<span>卖价</span>
<span>{{ item.sell }}</span>
</div>
<div class="item-sell-info">
<span>存货</span>
<span>{{ remain }}</span>
</div>
<div class="item-sell-info">
<span>拥有</span>
<span>{{ cnt(item.id) }}</span>
</div>
<a-divider
dashed
style="border-color: #ddd4"
id="divider-mode"
></a-divider>
<div id="sell-count">
<span>{{ mode === 'buy' ? '购买' : '售出' }}数量</span>
<div id="sell-count-select">
<double-left-outlined
class="button-text"
@click="count -= 10"
/>
<left-outlined class="button-text" @click="count--" />
<span id="fly-now">{{ count }}</span>
<right-outlined class="button-text" @click="count++" />
<double-right-outlined
class="button-text"
@click="count += 10"
/>
</div>
</div>
<a-divider
dashed
style="border-color: #ddd4; margin: 2vh 0 2vh 0"
></a-divider>
<div id="sell-confirm">
<span
id="sell-total"
:style="{
color:
mode === 'buy'
? nowMoney > cost
? 'lightgreen'
: 'lightcoral'
: 'lightcoral'
}"
>总价:{{
count *
parseInt(mode === 'buy' ? item.money : item.sell)
}}</span
>
<span
id="sell-button"
class="button-text"
:danger="mode === 'sell'"
danger-display="true"
active="true"
@click="confirm"
>确认{{ mode === 'buy' ? '购买' : '售出' }}</span
>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
import {
LeftOutlined,
DoubleLeftOutlined,
RightOutlined,
DoubleRightOutlined
} from '@ant-design/icons-vue';
import { keycode, splitText, tip } from '../plugin/utils';
import Scroll from '../components/scroll.vue';
import { isMobile } from '../plugin/use';
import BoxAnimate from '../components/boxAnimate.vue';
import { KeyCode } from '../plugin/keyCodes';
import { sleep } from 'mutate-animate';
const id = core.plugin.openedShopId;
const shop = core.status.shops[core.plugin.openedShopId] as ItemShopEvent;
if (!shop.item) {
throw new TypeError(
`Wrong global shop type delivered in opening item shop.`
);
}
flags.itemShop ??= {};
const f = flags;
const choices = shop.choices;
const selected = ref(0);
const mode = ref<'sell' | 'buy'>('buy');
const all = core.material.items;
const cnt = core.itemCount;
const count = ref(0);
const nowMoney = ref(core.status.hero.money);
const update = ref(false);
let bought = false;
watch(count, n => {
if (n < 0) n = 0;
if (mode.value === 'buy') {
if (n > remain.value) n = remain.value;
} else {
const c = cnt(item.value.id);
if (n > c) n = c;
}
count.value = n;
});
const item = computed(() => {
return choices[selected.value];
});
const remain = computed(() => {
update.value;
return item.value.number - (flags.itemShop[id]?.[item.value.id] ?? 0);
});
const info = computed(() => {
return core.material.items[item.value.id];
});
const desc = computed(() => {
const text = info.value.text!;
const res = splitText([text.startsWith('!!html') ? text.slice(6) : text]);
return res;
});
const cost = computed(() => {
return (
count.value *
parseInt(mode.value === 'buy' ? item.value.money : item.value.sell)
);
});
watch(remain, n => {
if (n < count.value) {
count.value = n;
}
});
function confirm() {
if (count.value === 0) return;
const money = core.status.hero.money;
bought = true;
core.status.route.push(`openShop:${id}`);
if (mode.value === 'buy') {
if (cost.value <= money) {
core.getItem(item.value.id, count.value);
core.status.hero.money -= cost.value;
nowMoney.value -= cost.value;
flags.itemShop[id] ??= {};
flags.itemShop[id][item.value.id] ??= 0;
flags.itemShop[id][item.value.id] += count.value;
tip('success', `成功购买${count.value}个${info.value.name}!`);
core.status.route.push(`buy:${item.value.id}:${count.value}`);
} else {
tip('error', '你的金币不够!');
}
} else {
core.addItem(item.value.id, -count.value);
core.status.hero.money += cost.value;
nowMoney.value += cost.value;
flags.itemShop[id] ??= {};
flags.itemShop[id][item.value.id] ??= 0;
flags.itemShop[id][item.value.id] -= count.value;
tip('success', `成功卖出${count.value}个${info.value.name}!`);
core.status.route.push(`sell:${item.value.id}:${count.value}`);
}
count.value = 0;
update.value = !update.value;
}
function keyup(e: KeyboardEvent) {
const c = keycode(e.keyCode);
if (c === KeyCode.KeyX || c === KeyCode.Escape || c === KeyCode.KeyV) {
exit();
}
if (c === KeyCode.UpArrow) {
if (selected.value >= 1) {
selected.value--;
}
}
if (c === KeyCode.DownArrow) {
if (selected.value <= choices.length - 2) {
selected.value++;
}
}
if (c === KeyCode.KeyC || c === KeyCode.Space || c === KeyCode.Enter) {
confirm();
}
}
function keydown(e: KeyboardEvent) {
const c = keycode(e.keyCode);
if (c === KeyCode.LeftArrow) {
count.value--;
}
if (c === KeyCode.RightArrow) {
count.value++;
}
}
function exit() {
if (bought) core.status.route.push('closeShop');
core.plugin.shopOpened.value = false;
}
onMounted(async () => {
await sleep(50);
if (core.plugin.transition.value) await sleep(600);
document.addEventListener('keyup', keyup);
document.addEventListener('keydown', keydown);
});
onUnmounted(() => {
document.removeEventListener('keyup', keyup);
document.removeEventListener('keydown', keydown);
});
</script>
<style lang="less" scoped>
#shop {
width: 90vh;
height: 90vh;
font-family: 'normal';
font-size: 2.8vh;
display: flex;
flex-direction: column;
user-select: none;
}
#tools {
height: 5vh;
font-size: 3.2vh;
}
#item-name {
width: 100%;
text-align: center;
font-size: 4vh;
height: 5vh;
line-height: 1;
}
#item-info {
height: 24vh;
display: flex;
flex-direction: column;
justify-content: space-between;
}
#divider {
width: 100%;
margin: 1vh 0 1vh 0;
}
#divider-split {
margin: 1vh 0 0 0;
}
#divider-vertical {
height: 100%;
margin: 0;
}
#shop-bottom {
height: 53vh;
width: 100%;
display: flex;
flex-direction: row;
}
#item-list {
height: 53vh;
width: 53vh;
padding: 1vh 0 1vh 0;
}
#item-sell-info {
width: 47vh;
display: flex;
flex-direction: column;
align-items: center;
}
.item-icon {
display: flex;
flex-direction: row;
align-items: center;
width: 100%;
span {
margin-left: 5%;
}
}
.item-one {
display: flex;
justify-content: space-between;
flex-direction: row;
margin-bottom: 1vh;
}
#shop-mode {
width: 100%;
display: flex;
justify-content: space-around;
align-items: center;
height: 5vh;
}
.mode-button {
width: 100%;
text-align: center;
}
#divider-mode {
margin: 0;
}
.item-sell-info {
width: 60%;
display: flex;
flex-direction: row;
justify-content: space-between;
margin: 1vh 0 1vh 0;
transition: color 0.2s linear;
}
#sell-count {
width: 100%;
padding-top: 1vh;
display: flex;
flex-direction: column;
align-items: center;
}
#sell-count-select {
margin-top: 1vh;
width: 90%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
}
#sell-confirm {
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-around;
}
#sell-total {
transition: color 0.2s linear;
}
</style>