refactor: UI 移入 @motajs/legacy-ui

This commit is contained in:
unanmed 2025-03-05 11:25:12 +08:00
parent 4aa894a204
commit 693e531639
85 changed files with 940 additions and 1252 deletions

View File

@ -1 +1,3 @@
export * from './keyCodes';
export * as Render from '@motajs/render';

View File

View File

View File

@ -0,0 +1,8 @@
{
"name": "@motajs/legacy-ui",
"dependencies": {
"@motajs/render": "workspace:*",
"@motajs/common": "workspace:*",
"@motajs/client": "workspace:*"
}
}

View File

@ -49,8 +49,8 @@
<script lang="ts" setup>
import { onMounted, onUnmounted, onUpdated, ref, watch } from 'vue';
import { ArrowsAltOutlined, DragOutlined } from '@ant-design/icons-vue';
import { isMobile, useDrag, cancelGlobalDrag } from '../plugin/use';
import { has, requireUniqueSymbol } from '../plugin/utils';
import { isMobile, useDrag, cancelGlobalDrag } from '../use';
import { has, requireUniqueSymbol } from '../utils';
// todo:

View File

@ -8,8 +8,8 @@
<script lang="tsx" setup>
import { onMounted, onUnmounted, onUpdated } from 'vue';
import { addAnimate, removeAnimate } from '../plugin/animateController';
import { has, requireUniqueSymbol } from '../plugin/utils';
import { addAnimate, removeAnimate } from '../animateController';
import { has, requireUniqueSymbol } from '../utils';
const id = requireUniqueSymbol().toFixed(0);

View File

@ -23,11 +23,11 @@
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, onUpdated, ref } from 'vue';
import { onMounted, onUpdated } from 'vue';
import { LeftOutlined } from '@ant-design/icons-vue';
import Scroll from './scroll.vue';
import { isMobile } from '../plugin/use';
import { has, requireUniqueSymbol } from '../plugin/utils';
import { isMobile } from '../use';
import { has, requireUniqueSymbol } from '../utils';
const emits = defineEmits<{
(e: 'close'): void;

View File

@ -4,7 +4,6 @@
@click="select"
@mousemove="enter"
:selected="selected"
:style="style"
>
<div class="info">
<div class="leftbar">
@ -20,9 +19,7 @@
v-if="has(enemy.special) && enemy.special.length > 0"
>
<template v-for="(text, i) in enemy.showSpecial">
<span
v-if="i < (isMobile ? 1 : 2)"
:style="{ color: text[2] }"
<span v-if="i < (isMobile ? 1 : 2)"
>&nbsp;{{ text[0] }}&nbsp;</span
>
<span v-if="i === (isMobile ? 1 : 2)">...</span>
@ -113,11 +110,10 @@
</template>
<script lang="ts" setup>
import { has } from '../plugin/utils';
import { has } from '../utils';
import BoxAnimate from '../components/boxAnimate.vue';
import { isMobile } from '../plugin/use';
import { ToShowEnemy } from '../plugin/ui/book';
import border from '@/data/enemyBorder.json';
import { isMobile } from '../use';
import { ToShowEnemy } from '../tools/book';
const props = defineProps<{
enemy: ToShowEnemy;
@ -133,8 +129,6 @@ const core = window.core;
const w = window.innerWidth * 0.032;
const style = border[props.enemy.enemy.enemy.id as keyof typeof border] ?? {};
/**
* 选择这个怪物时
*/

View File

@ -4,10 +4,9 @@
<script lang="ts" setup>
import { onMounted, onUnmounted } from 'vue';
import { requireUniqueSymbol } from '../plugin/utils';
import { MinimapDrawer, getArea } from '../plugin/ui/fly';
import { hook } from '@/game/game';
import { useDrag, useWheel } from '@/plugin/use';
import { requireUniqueSymbol } from '../utils';
import { MinimapDrawer, getArea } from '../tools/fly';
import { useDrag, useWheel } from '../use';
import { debounce } from 'lodash-es';
import { mainSetting } from '@/core/main/setting';
@ -135,6 +134,7 @@ onMounted(() => {
}
drawer.drawMap();
const hook = Mota.require('var', 'hook');
hook.on('afterChangeFloor', onChange);
hook.on('afterBattle', afterBattle);

View File

@ -12,8 +12,8 @@
<script lang="ts" setup>
import { sleep } from 'mutate-animate';
import { onMounted, onUnmounted, onUpdated } from 'vue';
import { cancelGlobalDrag, useDrag, useWheel } from '../plugin/use';
import { requireUniqueSymbol } from '@/plugin/utils';
import { cancelGlobalDrag, useDrag, useWheel } from '../use';
import { requireUniqueSymbol } from '../utils';
let main: HTMLDivElement;

View File

@ -0,0 +1,88 @@
{
"normal": [
{
"name": "虚惊一场",
"text": [
"打完山洞门口的兽人后只剩一滴血"
],
"point": 30
},
{
"name": "真能刷",
"text": [
"勇气之路的刷血怪刷到 <span style=\"color: gold\">15w</span> 以上的血"
],
"point": 30
}
],
"challenge": [
{
"name": "逃出生天",
"text": [
"通过山路追逐战的困难难度"
],
"point": 20
},
{
"name": "冰与火之舞",
"text": [
"完成第二章音游特殊战的困难难度"
],
"point": 50
}
],
"explore": [
{
"name": "勇气巅峰",
"text": [
"第一章完成度达到100%"
],
"progress": "${Mota.Plugin.require('completion_r').getChapterCompletion(1)} / 100",
"percent": true,
"point": 50
},
{
"name": "你是怎么办到的?!",
"text": [
"与山路上的若干个神秘木牌对话"
],
"progress": "${core.getLocalStorage('mountSign', 0)} / 5",
"hide": "该探索成就需要你自己探索如何达成",
"point": 25
},
{
"name": "智慧之心",
"text": [
"第二章完成度达到100%"
],
"progress": "${Mota.Plugin.require('completion_r').getChapterCompletion(2)} / 100",
"percent": true,
"point": 50
},
{
"name": "源头?",
"text": [
"在冰封雪原第一个山洞的水源处使用跳跃技能,并向前一步触发剧情"
],
"hide": "该探索成就需要你自己探索如何达成",
"point": 30
},
{
"name": "学坏了",
"text": [
"学习电摇嘲讽技能"
],
"hide": "该探索成就需要你自己探索如何达成",
"point": 20
},
{
"name": "满腹经纶",
"text": [
"把第二章中所有能学习的技能都学一遍"
],
"hide": "该探索成就需要你自己探索如何达成",
"progress": "",
"point": 50
}
]
}

View File

@ -0,0 +1,563 @@
{
"tip": {
"text": "注意事项",
"condition": "true",
"desc": [
"这里显示本塔中需要注意的事项。",
"<br>",
"<br>",
"1. <span style=\"color: yellow; font-weight: 700\">",
"本百科全书字数很多,可以选择性地阅读。</span>不过本条目最好可以全部阅读一遍。",
"<br>",
"<br>",
"2. 本百科全书的内容会<span style=\"color: gold\">随着游戏的推进而增加新内容</span>",
"同时每次增加新内容时都会有提示。",
"<br>",
"<br>",
"3. <span style=\"color: gold\">背包中的系统设置同样非常重要,有些问题可以在那里找到原因</span>。",
"例如当你获得技能时可能会发现开启不了技能,",
"就是因为你打开了<span style=\"color: gold\">自动切换技能</span>的功能,在系统设置里面有说。",
"<br>",
"<br>",
"4. <span style=\"color: yellow; font-weight: 700\">重要!!!</span>本塔没有考虑录像的二次播放性,",
"这意味着如果你从头播放一个录像,播放完成后继续游玩,提交成绩后不能保证绿录像,请谨慎考虑。",
"<br>",
"<br>",
"5. 本塔中<span style=\"color: gold\">几乎所有 ui 都可以纵向滚动</span>,如果发现显示不全,",
"可以尝试上下拖动,就像浏览网页一样。电脑端还可以使用滚轮上下滚动。",
"大部分可以纵向滚动的 ui 都会在右方有一个滚动条,也可以拖动它进行滚动,例如本百科全书的条目列表和",
"条目说明都是可以通过上述方式滚动的。",
"<br>",
"<br>",
"6. 本塔主要面向电脑端设计,",
"<span style=\"color: gold\">建议使用电脑游玩以获得更好的游戏体验同时使用约16:9的比例游玩更加合适",
"</span>。但是手机依然可以游玩本塔,",
"但部分操作可能不是很方便ui 也可能不是很美观,不过依然可以完整体验本游戏。",
"<br>",
"<br>",
"7. 对于手机端,可以点击<span style=\"color: gold\">右下角的难度文字</span>来切换工具栏至数字键。",
"这样,你可以更加方便地进行使用技能等操作。",
"<br>",
"<br>",
"8. 本塔中几乎所有 ui 在打开时都会有一个0.6s的动画,如果不想要,可以在开头捡的系统设置里面关闭(默认关闭)。",
"同时,几乎所有 ui 的退出按钮都在左上角。",
"<br>",
"<br>",
"9. 地图上显示的怪物临界有可能不准,当其与折线图有差异时,<span style=\"color: gold\">请以折线图为准</span>。"
]
},
"about": {
"text": "关于游戏",
"condition": "true",
"desc": [
"使用样板Vite 魔塔样板",
"<br>",
"样板版本V2.10.0",
"<br>",
"游戏版本V1.0.0-alpha",
"<br>",
"游戏作者:古祠",
"<br>",
"游戏开源地址:<a href=\"https://github.com/unanmed/HumanBreak\" target=\"_blank\">",
"https://github.com/unanmed/HumanBreak</a>",
"<br>",
"本塔遵循MIT开源协议。<a href=\"LICENSE\" target=\"_blank\">查看开源协议</a>",
"<br>",
"音乐来源:网易云音乐等",
"<br>",
"素材来源:大素材库、爱给网、网站素材库等",
"<br>",
"<span style=\"color: gold\">特别说明:素材与音乐均来自网络,不得用于商业用途,仅用于参考与学习</span>",
"<br>",
"特别鸣谢(排名不分先后):",
"<br>",
"1. 无名甲烷菌(提供部分特殊属性与机制想法)",
"<br>",
"测试(排名不分先后):",
"<br>",
"1. 永葆一颗童心",
"<br>",
"2. 影法师",
"<br>",
"3. 夜战天明889",
"<br>",
"4. 霸道的老鼠"
]
},
"tutorial": {
"text": "新手教程",
"condition": "true",
"desc": [
"本条目是魔塔游戏的新手教程,如果对魔塔有一定的了解,可以直接忽略。",
"<br>",
"<br>",
"魔塔是一种固定数值rpg游戏在打怪的时候遵循<span style=\"color: gold\">我打你一下,你打我一下</span>",
"的原则,造成的伤害是己方攻击减去对方防御,最后怪物的伤害便是你在战斗中失去的生命值。当然,为了游戏体验,",
"战斗过程会被省略。",
"<br>",
"<br>",
"宝石可以增加你的属性,在大部分魔塔中,红宝石增加攻击,蓝宝石增加防御,本塔也不例外。血瓶可以增加你的生命值。",
"一般情况下,拾取宝物的优先级是<span style=\"color: gold\">红宝石 &gt; 蓝宝石 &gt; 血瓶</span>",
"但部分情况可能不是这样,这需要你自己的游玩经验等。",
"<br>",
"<br>",
"本塔还拥有升级机制,升级时能够给你增加大量的属性,因此,一般情况下当你接近升级时,需要尽快打怪升级。",
"<br>",
"<br>",
"然后是门。在魔塔中,很多门都不是必开的门,它们的作用一般是可以躲开怪物拿宝石,或者门里面有血瓶等。",
"当你血量足够时,这些门可以不用开,不然可能会有必开的门无法开启导致卡关。对于钥匙,每种颜色的钥匙开对应颜色的门,",
"价值是<span style=\"color: gold\">红 &gt; 蓝 &gt; 黄</span>。",
"<br>",
"<br>",
"为了更加方便,本塔增加了宝石血瓶显示数据的功能,这样你可以清晰地知道每个宝石增加了多少属性。",
"<br>",
"<br>",
"下面是勇士基础属性的说明:",
"<br>",
"<span style=\"color: lightgreen\">1. 生命值</span>",
"勇士的血量,当它归零时,游戏结束",
"<br>",
"<span style=\"color: lightcoral\">2. 攻击</span>",
"勇士的攻击,攻击越高,每回合对怪物造成的伤害越高",
"<br>",
"<span style=\"color: lightblue\">3. 防御</span>",
"勇士的防御,防御越高,怪物每回合对你造成的伤害越低",
"<br>",
"<span style=\"color: green\">4. 经验</span>",
"勇士的经验,到达一定值后会升级。本塔在状态栏中显示为距离升级剩余的经验",
"<br>",
"<span style=\"color: gold\">5. 金币</span>",
"勇士的金币,可以用于购买物品。本塔中在进入第二章后会有用",
"<br>",
"<span style=\"color: lightgreen\">6. 护盾</span>",
"勇士的护盾,用处是能够在战后减少同等数值的伤害,在本塔中可以使伤害变为负值。本塔中,在点开无上之盾技能后,",
"智慧会充当护盾。更多信息可以查看“勇士属性”条目。"
]
},
"noun": {
"text": "名词解释",
"condition": "true",
"desc": [
"本条目会解释诸如临界等魔塔术语,对魔塔有一定了解的可以直接忽略。",
"<br>",
"<br>",
"<span style=\"color: lightcoral\">1. 临界</span>",
"在魔塔中,临界是一个非常重要的东西。首先,我们很容易可以得到,吃攻击时只有当减少了战斗回合数时怪物的伤害会减少,",
"那么,吃攻击时怪物的减伤是不连续的。而<span style=\"color: gold\">距离下一次减少怪物的伤害需要加的攻击的量</span>",
"便是临界。当我们吃一个攻击恰好使怪物伤害减少时,称为“踩临界”。一般情况下,踩临界的减伤要比吃防御要高,",
"因此,当能踩到临界时,我们应当先踩临界,再吃防御。",
"<br>",
"<br>",
"<span style=\"color: lightblue\">2. 加防</span>",
"加防指的是加防对怪物的减伤。在本塔中会以“n防”的形式显示在怪物手册或其他地方。在本塔中一般你不需要刻意计算",
"临界与加防减伤,你可以在怪物手册中<span style=\"color: gold\">查看减伤折线图</span>",
"更多信息请查看“怪物手册”条目。",
"<br>",
"<br>",
"<span style=\"color: gold\">3. 咸鱼</span>",
"一般来讲,开不必开的门,或者使用不必使用的道具被称为咸鱼,或者是咸门,咸道具。一般情况下,说“咸”便是指咸鱼。",
"一般情况下,门后面有宝石且无法通过其他方式进入的都是必开门,而只有血瓶的都是咸鱼门。"
]
},
"shortcut": {
"text": "快捷键",
"condition": "true",
"desc": [
"这里包含本塔中所有的快捷键。对于手机端,可以点击工具栏的难度的位置切换工具栏至数字键。",
"下面会分为样板快捷键和本塔快捷键两类分别说明。可以ctrl+F进行搜索快捷键的功能。",
"<br>",
"<br>",
"下面是样板中的所有快捷键:",
"<br>",
"<span style=\"color: gold\">X</span>:打开怪物手册",
"<br>",
"<span style=\"color: gold\">S</span>:打开存档界面",
"<br>",
"<span style=\"color: gold\">D</span>:打开读档界面",
"<br>",
"<span style=\"color: gold\">A或5</span>:读取自动存档",
"<br>",
"<span style=\"color: gold\">W或6</span>:撤销读取的自动存档",
"<br>",
"<span style=\"color: gold\">Q</span>:打开装备栏",
"<br>",
"<span style=\"color: gold\">T</span>:打开道具栏",
"<br>",
"<span style=\"color: gold\">G</span>:打开楼层传送器",
"<br>",
"<span style=\"color: gold\">Z或单击勇士</span>:勇士转向",
"<br>",
"<span style=\"color: gold\">空格或双击勇士或7</span>:轻按(拾取勇士周围的宝物但不移动勇士)",
"<br>",
"<span style=\"color: gold\">Esc</span>:打开游戏菜单",
"<br>",
"<span style=\"color: gold\">R</span>:打开录像回放菜单",
"<br>",
"<span style=\"color: gold\">N</span>:询问是否返回游戏主菜单",
"<br>",
"<span style=\"color: gold\">V</span>:打开快捷商店",
"<br>",
"<span style=\"color: gold\">B</span>:打开数据统计界面",
"<br>",
"<span style=\"color: gold\">Alt + 数字键</span>:快速换装",
"<br>",
"<span style=\"color: gold\">PgUp或PgDn</span>:浏览地图",
"<br>",
"<span style=\"color: gold\">P</span>:打开评论区",
"<br>",
"<br>",
"下面是本塔中新增的快捷键(不包括技能,技能快捷键请在查看技能界面中查看):",
"<br>",
"<span style=\"color: gold\">M</span>:快速标记怪物",
"<br>",
"<span style=\"color: gold\">J</span>:打开技能树",
"<br>",
"<span style=\"color: gold\">H</span>:打开百科全书",
"<br>",
"<span style=\"color: gold\">E</span>:查看鼠标位置怪物的特殊属性信息",
"<br>",
"<span style=\"color: gold\">C</span>:查看鼠标位置怪物的详细临界信息"
]
},
"extraAttr": {
"text": "勇士属性",
"condition": "true",
"desc": [
"这里只对本塔中新增的勇士属性进行说明。",
"<br>",
"<br>",
"<span style=\"color: lightblue\">1. 智慧</span>",
"智慧是该塔的核心属性之一。智慧可用于智慧加点,该功能会在进入第一章后开启。使用智慧可以点技能树。",
"除此之外,智慧也有其它功能。例如点开无上之盾技能后智慧还可以充当护盾,第二章点开学习技能后可以使用智慧学习怪物技能等。",
"<br>",
"<br>",
"<span style=\"color: lightgreen\">2. 生命回复</span>",
"生命回复指的是勇士每回合回复的生命值。当与怪物战斗时,勇士每回合都会回复对应量的生命值。因此,当吃攻击时,",
"与怪物战斗的回合数可能会减少,导致生命回复的总回复量减少。不过大部分情况下不需要在意这一点,",
"减少一回合并不会对吸的血造成很大的影响,除了一些特殊情况。",
"该项会显示在状态栏的生命值右方偏下的位置。该项不会超过勇士防御的十分之一,如果真实值溢出,那么多余部分会忽略,",
"当防御提高时,其值会一同改变",
"<br>",
"<br>",
"<span style=\"color: lightcoral\">3. 额外攻击</span>",
"额外攻击指的是勇士每回合的额外造成的伤害。一般情况下,当勇士破了怪物的防御时,该项便会起作用。",
"额外攻击相当于魔攻,无法通过一般方式减免。当勇士攻击怪物时,每回合都会附加对应量的伤害,对坚固怪同样有效。",
"额外攻击会显示在状态栏的攻击右方偏下的位置。"
]
},
"statusBar": {
"text": "状态栏",
"condition": "true",
"desc": [
"在本塔中,状态栏与游戏画面是分开的。<span style=\"color: gold\">你可以自由拖动状态栏,也可以修改其大小</span>。",
"具体方法如下:点击一下状态栏之后,左上角的拖拽图标会放大,此时你可以按住它拖动状态栏。",
"你可以直接将鼠标放到状态栏的边框上,然后直接拖动以改变状态栏的大小。手机端可以先点击一下状态栏使边框",
"变宽,然后拖动。电脑端点击状态栏也可以使边框变宽。如果你想折叠状态栏,完全可以拖动状态栏的下边框,",
"然后直接拖动至上方,这时状态栏便会变成一条线,相当于折叠了状态栏",
"<br>",
"<br>",
"<span style=\"color: gold\">状态栏可以纵向滚动</span>",
"如果你发现状态栏显示不全,可以尝试拉大状态栏,或者纵向拖动状态栏,就像网页上下滚动一样。",
"电脑端还可以使用滚轮上下滚动。",
"<br>",
"<br>",
"如果你觉得状态栏有些碍事,你完全可以将其缩小,或者把它放到不碍事的地方。",
"<br>",
"<br>",
"状态栏上面可能会有按钮,你可以直接点击。",
"<br>",
"<br>",
"对状态栏布局的说明。",
"<br>",
"本塔的状态栏的布局较为灵活。它是横向的布局,在状态栏较宽时可以看到,属性会横向依次显示。按照显示顺序,",
"状态栏显示项依次为:",
"<br>",
"<br>",
"1. <span style=\"color: gold\">楼层名</span>,点击后进入浏览地图界面",
"<br>",
"2. <span style=\"color: gold\">勇士等级</span>",
"<br>",
"3. <span style=\"color: gold\">当前开启的技能</span>",
"<br>",
"4. <span style=\"color: lightgreen\">当前勇士生命值</span>,右方偏下为每回合回复的生命值",
",当点开治愈之泉技能时,右方偏上会显示距离增加生命回复剩余血瓶数",
"<br>",
"5. <span style=\"color: lightcoral\">当前勇士的攻击</span>,右方偏下为勇士的额外攻击",
"<br>",
"6. <span style=\"color: lightblue\">当前勇士的防御</span>,当有魔法防御时,右方偏下为勇士的魔法防御",
"<br>",
"7. <span style=\"color: lightgreen\">当前勇士的智慧</span>,可以用于智慧加点等",
"<br>",
"8. <span style=\"color: gold\">当前勇士的金币</span>",
"<br>",
"9. <span style=\"color: lightgreen\">当前勇士距离升级剩余经验数</span>",
"<br>",
"10. <span style=\"color: gold\">三色钥匙</span>",
"<br>",
"11. <span style=\"color: gold\">打开技能树</span>(进入第一章后开启)",
"<br>",
"12. <span style=\"color: gold\">查看勇士的技能</span>(进入第一章后开启)"
]
},
"markEnemy": {
"text": "标记怪物",
"condition": "true",
"desc": [
"标记怪物可以使你能够更加方便地了解一个怪物的情况。",
"<br>",
"你可以通过以下两种方式标记怪物:",
"<br>",
"1. 打开怪物手册,选中怪物,进入怪物更多信息栏,点击标记怪物。",
"<br>",
"2. 将鼠标移动到你想要标记的怪物上面,<span style=\"color: gold\">",
"按下M键</span>,即可标记怪物,注意浏览地图中不能用该方式标记。",
"手机端暂时没有快速标记怪物的方式。",
"<br>",
"<br>",
"<span style=\"color: gold\">当一个怪物被标记后,怪物会有以下行为</span>",
"<br>",
"1. 当勇士恰好能打败怪物时,会进行提示",
"<br>",
"2. 当怪物的伤害恰好低于勇士生命值的2/3或1/3时会进行提示",
"<br>",
"3. 当勇士恰好踩到怪物的临界时,会进行提示",
"<br>",
"4. 当怪物零伤时,会进行提示",
"<br>",
"5. 被标记的怪物会出现类似于状态栏的盒子,可以随意拖动和改变大小。你也可以选择关闭这个盒子,",
"被关闭后可以通过重新标记来打开。这个盒子会显示标记的怪物的临界与伤害信息等,与状态栏一样,可以纵向滚动。",
"<br>",
"<br>",
"这个功能可以用于标记boss或者较强的挡路怪当这些怪能够攻击时你可以直接收到信息不需要再时刻费心注意怪物的伤害。",
"<br>",
"<br>",
"<span style=\"color: gold\">注意,标记的怪物是不计入存档的,同时标记的怪物只在本次游戏中有效,刷新页面后便会消失。</span>"
]
},
"book": {
"text": "怪物手册",
"condition": "true",
"desc": [
"本塔的怪物手册功能很多,下面一一介绍。",
"<br>",
"<br>",
"首先你可以按X打开怪物手册。除此之外将鼠标移动到怪物上也可以定点查看怪物的粗略信息。",
"将鼠标移动到一个怪物上,按下<span style=\"color: gold\">",
"E键</span>,可以查看该怪物的特殊属性信息。按下<span style=\"color: gold\">",
"C键</span>,可以查看该怪物的详细临界信息。",
"<br>",
"<br>",
"怪物手册打开的时候有一个0.6秒的动画,如果不想要可以在开头捡的系统设置里面关闭(默认关闭)。",
"<br>",
"<br>",
"打开怪物手册后,怪物手册的布局与样板自带的类似。与样板不同的是,这里的怪物手册不再是翻页式结构。",
"<span style=\"color: gold\">这里的怪物手册是滚动式结构</span>",
"你可以像浏览网页一样,用手指或鼠标上下滚动或者拖动右边的滚动条,电脑端还可以使用滚轮。",
"对于电脑端还可以使用键盘操作。上和下可以上下选择怪物左和右可以向上或向下移动5个怪物。这些操作与样板都类似。",
"<br>",
"<br>",
"点击一个怪物或者按下回车空格后,将进入怪物详细信息界面。这个界面分为多个栏,分别是特殊属性栏,详细临界栏,更多信息栏。",
"进入怪物详细信息后默认在特殊属性栏,该栏可以查看怪物的特殊属性。",
"注意特殊属性依然可以纵向滚动。在特殊属性下方,",
"是怪物的临界表,可以粗略地查看怪物的临界信息。在下方,你可以点击详细临界信息进入详细临界栏。",
"<br>",
"<br>",
"在详细临界栏中,怪物的伤害会以<span style=\"color: gold\">可视化折线图</span>的方式显示出来,",
"从而你可以更为清晰地看出怪物减伤趋势。",
"除了查看怪物伤害曲线,你还可以规划宝石。每个折线图下方都有一个滑动条,你可以拖动来模拟吃宝石。",
"注意,拖动时,滑动条左边会显示当前的加攻或加防次数,这个数值指的是在勇士所在地图中需要吃的最弱的宝石数量。",
"例如当前勇士所在地图中最弱的宝石加2点攻击加攻次数为3那么勇士的攻击增加量就为6。",
"勇士增加的攻击数值也会在下方显示。当加攻次数和加防次数改变时,折线图也会变化。",
"当前状态下怪物的伤害以及减伤总量也会在下方显示。<span style=\"color: gold\">",
"注意在此栏中无法通过点击屏幕回到怪物手册界面,更多信息请查看最后一段</span>。",
"<br>",
"<br>",
"在特殊属性栏,点击下方的怪物更多信息可以进入更多信息栏。此栏中,你可以查看怪物描述。但这不是这一栏的核心功能。",
"这一栏的核心功能是标记怪物。被标记的怪物会有一些非常方便的行为,这些行为可以在“",
"<span style=\"color: gold\">标记怪物</span>”条目中查看。",
"<br>",
"<br>",
"注意,在怪物详细信息中,除详细临界栏外均可以通过点击屏幕返回到怪物手册界面。",
"如果你是电脑端,在任意栏目中<span style=\"color: gold\">按下X键</span>会退出怪物手册,返回游戏,",
"<span style=\"color: gold\">按下回车Enter键</span>会回到怪物手册界面。"
]
},
"fly": {
"text": "楼层传送器",
"condition": "true",
"desc": [
"楼传界面打开时会有一个0.6秒的动画,如果不想要可以在开头捡的系统设置里面关闭。(默认关闭)",
"<br>",
"<br>",
"本塔的楼层传送器是一个集<span style=\"color: gold\">分区、小地图、楼层传送、浏览地图</span>于一体的多功能楼传。",
"<a href=\"https://unanmed.github.io/HumanBreak/maps/index.html\" target=\"_blank\">你也可以点击这里</a>查看所有区域的缩略图。",
"下面是楼传的具体说明:",
"<br>",
"<br>",
"首先,对于电脑端,最左侧显示区域信息,手机端则在上方的左侧。",
"<br>",
"<br>",
"然后,区域的右侧是小地图栏,这一栏会显示楼层的平面结构。你可以拖动,也可以使用滚轮或者双指放缩,当放缩到一定大小时,",
"会显示地图的缩略图。直接点击地图也可以选中地图,再次点击会传送至目标地图。",
"<br>",
"<br>",
"对于电脑端,最右侧是当前选中的地图的缩略图,手机则在下方,点击缩略图也可以传送。缩略图的下方是当前选中的地图名,",
"左右各有两个按钮表示后退10层、后退1层、前进1层、前进10层与样板的楼传的按钮功能类似对于小地图无法显示的单层",
"可以使用该功能到达。",
"<br>",
"<br>",
"最下方是设置按钮,可以切换无边框模式,电脑端还可以切换传统按键模式,传统按键模式下按键遵循样板的楼传按键方式。",
"对于非传统模式,<span style=\"color: gold\">上下左右</span>可以移动地图,",
"<span style=\"color: gold\">PageUp和PageDown</span>可以前进1层或后退1层。"
]
},
"tools": {
"text": "道具栏与装备栏",
"condition": "true",
"desc": [
"道具栏与装备栏打开时会有一个0.6秒的动画,如果不想要可以在开头捡的系统设置里面关闭。(默认关闭)",
"<br>",
"<br>",
"本塔的道具栏没有特别之处,这里不需要说明。主要是装备栏。",
"<br>",
"<br>",
"本塔的装备栏手机和电脑端不同,电脑端比手机端多了一个勇士属性的显示。在装备栏的装备列表栏,",
"<span style=\"color: gold\">上方有两个选择框与一个排序方式的选项</span>。",
"这三个可以筛选你拥有的装备并进行排序,从而让你能够更清楚地知道哪个装备更强。",
"第一个选择框可以筛选装备增加的属性,如果装备不增加选择的属性,那么会不显示。第二个选择框可以筛选增加的属性的方式,",
"有数值增加和百分比增加两种。在这个选择框右边有一个图标,这个图标可以改变武器的排序方式,有升序和降序两种,默认为升序。",
"例如你拥有两个装备分别增加10攻击和20攻击三者你分别选择了攻击数值升序那么增加10攻击的装备会排在上面",
"而增加20攻击的装备会排在下面。",
"<br>",
"<br>",
"对于电脑端,如果你想装装备,<span style=\"color: gold\">可以直接拖动装备至装备孔</span>",
"也可以选中装备后再次点击。<span style=\"color: gold\">手机端暂时无法拖动装备</span>。当选中一个装备后,",
"电脑端和手机端均会显示装备增加或减少的属性,注意有的装备可能<span style=\"color: gold\">不增加属性但是有特殊功能</span>。",
"对于电脑端,还会直接在勇士属性栏显示增加或减少的属性。"
]
},
"achievement": {
"text": "成就",
"condition": "true",
"desc": [
"成就系统是本塔的一个独立系统。它不会像勇士属性一样跟随存档变化,而是只要你完成了成就,那么就永远完成了,",
"除非你清理了浏览器。每个成就都有成就点,<span style=\"color: gold\">成就点目前没有实际用途,",
"只是一个收集要素,对游戏进程没有任何影响。</span>",
"<br>",
"<br>",
"成就分为三种,普通成就,挑战成就和探索成就。普通成就完成难度一般较低,挑战成就完成难度较高,",
"而探索成就一般需要你自己探索如何完成。对于完成度类型的探索成就,它的完成度由到达过的地图与本章完成的成就数决定。",
"<br>",
"<br>",
"<span style=\"color: gold\">调试模式下无法完成成就!</span>"
]
},
"score": {
"text": "计分方式",
"condition": "true",
"desc": [
"第一章计分方式:血量 + 黄 * 5000 + 蓝 * 15000",
"<br>",
"第二章计分方式:血量 / 10 + 黄 * 2000 + 蓝 * 5000 + 红 * 10000"
]
},
"skillTree": {
"text": "技能树",
"condition": "flags.chapter > 0",
"desc": [
"打开技能树可以点击状态栏的<span style=\"color: gold\">",
"技能树按钮</span>(如果发现没有显示可以尝试上下滚动状态栏),还可以按",
"<span style=\"color: gold\">快捷键J</span>打开。",
"<br>",
"<br>",
"技能树是本塔的主要玩法之一。它可以让你使用智慧来学习技能,增加属性等。智慧在状态栏显示在防御的下一项,",
"绿宝石可以增加勇士的智慧。",
"<br>",
"<br>",
"打开技能树页面后,你可以在上方看到技能的名称与描述,下方会显示技能树,以及升级要求等。点击一个技能可以选中技能,",
"再次点击可以升级技能。注意,前置技能栏可以上下滚动,因此如果发现显示不全,可以尝试上下滚动前置技能栏",
"<br>",
"<br>",
"注意,技能在点开之后是无法取消的,因此,加点时请慎重加点。注意,部分技能是必点技能,这些技能会在技能说明中明确指出,",
"这些技能一般需要尽早点出。"
]
},
"study": {
"text": "学习",
"condition": "Mota.Plugin.require('skillTree_g').getSkillLevel(11) > 0",
"desc": [
"本条目会详细说明学习的机制与所有可以被学习的技能被学习后的效果。当前已经学习的技能会以与状态栏类似的盒子展示出来。",
"<br>",
"<br>",
"首先学习技能消耗的智慧点会越来越多初始消耗的智慧点为500每学习一次增加250。",
"学习的技能可以持续5场战斗在技能树界面每升级一次增加3场",
"<span style=\"color: gold\">当前为${Mota.Plugin.require('skillTree_g').getSkillLevel(11) * 3 + 2}场</span>。",
"学习后对应属性的值,例如抱团怪增加的属性百分比,会与被学习的怪物相同。学习界面可以使用背包中的道具或点击状态栏打开。",
"<br>",
"<br>",
"下面会详细说明每一种可以被学习的技能被学习后的效果,没有列出的均不可学习。",
"<br>",
"<br>",
"<span style=\"color: #fc3\">1. 致命一击</span>勇士每5回合对怪物造成一次强力攻击。",
"<br>",
"<span style=\"color: #bbb0ff\">2. 恶毒</span>:勇士攻击无视怪物的防御。",
"<br>",
"<span style=\"color: #c0b088\">3. 坚固</span>:勇士防御不低于怪物的攻击-1。",
"<br>",
"<span style=\"color: #fe7\">4. n连击</span>勇士每回合攻击n次",
"<br>",
"<span style=\"color: #b30000\">5. 饥渴</span>:勇士在战前吸取怪物一定量的攻击加载自己身上,",
"同时减少怪物相应量的攻击,优先于怪物。",
"<br>",
"<span style=\"color: #fa4\">6. 抱团</span>:勇士周围每有一个拥有抱团属性的怪物,勇士的属性便增加一定值。",
"相应地,拥有抱团属性的怪物也会受到勇士的加成。",
"<br>",
"<span style=\"color: #b0c0dd\">7. 勇气之刃</span>:勇士第一回合造成一定量的伤害,之后正常。",
"<br>",
"<span style=\"color: #ff00d2\">8. 勇气冲锋</span>勇士首先发动冲锋造成一定量的伤害眩晕怪物5回合。",
"学习该技能后,勇士无条件先手。",
"<br>",
"<span style=\"color: #bbb0ff\">9. 魔攻</span>:勇士攻击无视怪物的防御。",
"<br>",
"<span style=\"color: #b0b666\">10. 先攻</span>:勇士无条件先手。"
]
},
"special1": {
"text": "第一章怪物特技",
"condition": "flags.chapter > 0",
"desc": [
"这里会展示第一章的怪物中需要特别说明的怪物特技。",
"<br>",
"<br>",
"<span style=\"color: #c0b088\">1. 坚固</span>",
"在本塔中,额外攻击可以对坚固怪造成额外伤害。",
"<br>",
"<br>",
"<span style=\"color: #80eed6\">2. 绝对防御</span>",
"该怪物一般可以用于刷血。该怪物可以使你每回合对怪物造成的伤害恰好为1导致战斗回合数很高因此可以刷血。",
"<br>",
"<br>",
"<span style=\"color: #fc3\">3. 致命一击、勇气之刃、勇气冲锋</span>",
"造成的伤害为怪物每回合对勇士的伤害的一定倍数,而非攻击提高一定倍数。"
]
},
"special2": {
"text": "第二章怪物特技",
"condition": "flags.chapter > 1",
"desc": [
"这里会展示第二章的怪物中需要特别说明的怪物特技。",
"<br>",
"<br>",
"<span style=\"color: #f66\">1. 电摇嘲讽</span>",
"该特技会撞碎路上的所有地形和门,不需要消耗钥匙,拾取路上的所有道具,与路上的怪物战斗,最后与该怪物战斗。",
"如果怪物所在位置可以被嘲讽,那么勇士会被继续嘲讽。如果在被嘲讽的路上可以被其他怪物嘲讽,则不会触发。",
"如果一个点可以被多个怪物嘲讽,那么会优先选择最靠左上角的怪物。在地图上会标记出勇士的移动方向。",
"<span style=\"color: gold\">在被嘲讽之前会自动存档。</span>",
"<br>",
"<br>",
"<span style=\"color: #d8a\">2. 永夜</span>、<span style=\"color: #ffd\">极昼</span>",
"战斗后会在本楼层中加减怪物与勇士的攻防每个楼层会单独存储。例如你在1楼层增加了100点攻击2楼层减少了100点攻击",
"那么当你从2楼层到1楼层时攻击会增加200点反之亦然。注意这里没有计算buff。"
]
}
}

View File

@ -0,0 +1,43 @@
{
"none": {
"text": "无",
"opened": "true",
"desc": [
"当前未选择技能"
]
},
"blade": {
"text": "1断灭之刃",
"opened": "true",
"desc": [
"<span style=\"color: gold\">快捷键1</span>,开启后勇士攻击增加${level:2 * 10}%",
"同时防御减少${level:2 * 10}%。",
"<br>",
"<br>",
"当前等级:${level:2}"
]
},
"jump": {
"text": "2跳跃",
"opened": "true",
"desc": [
"<span style=\"color: gold\">快捷键2</span>消耗200点生命值困难消耗400点一个地图只能使用3次",
"如果前方为可通行的地面,则不能使用该技能,如果前方为怪物,则将怪物移至勇士视线上第一个不能通行的方块后",
"如果前方为障碍物,则直接跳到该障碍物的后方。",
"<br>",
"<br>",
"进入第二章后不再消耗生命值。"
]
},
"shield": {
"text": "3铸剑为盾",
"opened": "true",
"desc": [
"<span style=\"color: gold\">快捷键3</span>,开启后勇士防御增加${level:10 * 10}%",
"同时攻击减少${level:10 * 10}%。",
"<br>",
"<br>",
"当前等级:${level:10}"
]
}
}

View File

@ -0,0 +1,37 @@
[
"按下C可以查看鼠标位置怪物临界",
"按下E可以查看鼠标位置怪物的详细属性",
"将鼠标移动到光环怪上以查看其产生的光环",
"字体太大?试试在背包的系统设置里面调整字体大小吧!",
"字体太小?试试在背包的系统设置里面调整字体大小吧!",
"按键不合心意?试试在背包的系统设置里面自定义快捷键",
"拖动状态栏左上角可以移动状态栏哦!",
"拖动状态栏右下角可以缩放状态栏哦!",
"按下M键鼠标位置的怪物的信息就会被你看光啦",
"咱就是说,要不要试一下工具栏的最后一个按钮?",
"要不要试试工具栏倒数第二个按钮呢?",
"想自定义工具栏?去背包的系统设置看看吧!",
"冷知识:临界界面可以拖动滚动条来查看减伤情况",
"可以用滚轮或者双指缩放小地图!",
"楼传的最左侧一栏可以选择区域!",
"冷知识:装备栏左栏最上面可以修改装备排序",
"冷冷冷知识:装备栏左栏最上面右侧可以更改顺序或倒序",
"第一章使用跳跃技能可是要扣血的!要注意!",
"按H查看本游戏的百科全书",
"给别人炫耀一下自己的成就点吧!虽然不能记榜(",
"抱团属性会在怪物右上角显示加成数量!",
"乾坤挪移属性会在怪物左上角显示“乾”字!",
"电脑端可以试试按F11全屏游玩",
"手机端要不试试横屏玩?",
"不在楼梯边也可以使用楼传!",
"技能树的右下角可以切换章节!",
"开启自动切换技能就会自动帮你选择最优技能了!",
"魔塔不仅有撤回还有恢复按W或6就可以了",
"觉得卡顿?可以去试着设置里面关闭一些特性!",
"从第二章开始怪物负伤害量不会超过其生命的1/4",
"生命回复不会超过防御的十分之一",
"不想看小贴士?设置里面可以关掉!",
"不小心进入了追猎范围?读取自动存档撤回到进入前吧!",
"不小心进入了电摇嘲讽范围?读取自动存档撤回到进入前吧!",
"小地图出现卡顿?试试在背包中系统设置里把小地图懒更新打开吧!"
]

View File

@ -0,0 +1,7 @@
export * as UI from './ui';
export * from './tools';
export * from './animateController';
export * from './mark';
export * from './use';
export * from './utils';

View File

@ -1,5 +1,5 @@
import { fixedUi } from '@/core/main/init/ui';
import type { DamageEnemy } from '../game/enemy/damage';
import type { DamageEnemy } from '@/game/enemy/damage';
import { tip } from './utils';
import { ref, Ref } from 'vue';

View File

@ -94,12 +94,13 @@
<script lang="ts" setup>
import { computed, onMounted, ref, watch } from 'vue';
import { detailInfo, getCriticalDamage, getDefDamage } from '../plugin/ui/book';
import { detailInfo, getCriticalDamage, getDefDamage } from '../tools/book';
import Chart, { ChartConfiguration } from 'chart.js/auto';
import { has, setCanvasSize } from '../plugin/utils';
import { has, setCanvasSize } from '../utils';
import { debounce } from 'lodash-es';
import { isMobile } from '../plugin/use';
import { createChangable } from '@/plugin/ui/common';
import { isMobile } from '../use';
import { createChangable } from '../tools/common';
const props = defineProps<{
fromBook?: boolean;
}>();

View File

@ -28,8 +28,8 @@
</template>
<script lang="ts" setup>
import { isMobile } from '../plugin/use';
import { detailInfo, getSpecialHint } from '../plugin/ui/book';
import { isMobile } from '../use';
import { detailInfo, getSpecialHint } from '../tools/book';
const props = defineProps<{
fromBook?: boolean;

View File

@ -29,8 +29,8 @@
<script lang="ts" setup>
import { ref } from 'vue';
import Scroll from '../components/scroll.vue';
import { detailInfo } from '../plugin/ui/book';
import { hasMarkedEnemy, markEnemy } from '@/plugin/mark';
import { detailInfo } from '../tools/book';
import { hasMarkedEnemy, markEnemy } from '../mark';
const enemy = detailInfo.enemy!;
const marked = ref(hasMarkedEnemy(enemy.enemy.id));

View File

@ -24,7 +24,7 @@
import { checkAssist } from '@/core/main/custom/hotkey';
import { Keyboard } from '@/core/main/custom/keyboard';
import { KeyboardEmits } from '@/core/main/custom/keyboard';
import { KeyCodeUtils } from '@/plugin/keyCodes';
import { KeyCodeUtils } from '@motajs/client';
import { nextTick, onUnmounted, ref } from 'vue';
const props = defineProps<{

View File

@ -1,6 +1,5 @@
import { ref } from 'vue';
import list from '../../data/achievement.json';
import { achiDict, checkCompletionAchievement } from '../completion';
import list from '../data/achievement.json';
import { achiDict, checkCompletionAchievement } from './completion';
import { changeLocalStorage, has } from '../utils';
type AchievementList = typeof list;

View File

@ -1,4 +1,4 @@
import type { CurrentEnemy } from '../../game/enemy/battle';
import type { CurrentEnemy } from '@/game/enemy/battle';
import { has } from '../utils';
export interface ToShowEnemy extends CurrentEnemy {

View File

@ -2,8 +2,8 @@ import {
AchievementType,
completeAchievement,
hasCompletedAchievement
} from './ui/achievement';
import { changeLocalStorage } from './utils';
} from './achievement';
import { changeLocalStorage } from '../utils';
import list from '../data/achievement.json';
export const floors: Record<number, FloorIds[]> = {

View File

@ -1,6 +1,6 @@
import { getDamageColor } from '../utils';
import { ToShowEnemy } from './book';
import type { DamageEnemy, EnemyInfo } from '../../game/enemy/damage';
import type { DamageEnemy, EnemyInfo } from '@/game/enemy/damage';
import { isMobile } from '../use';
export function getLocFromMouseLoc(x: number, y: number): LocArr {

View File

@ -0,0 +1,7 @@
export * from './achievement';
export * from './book';
export * from './common';
export * from './completion';
export * from './equipbox';
export * from './fixed';
export * from './fly';

View File

@ -1,5 +1,3 @@
import { has } from '../utils';
interface ClsMap {
tools: '消耗道具';
constants: '永久道具';

View File

@ -104,9 +104,9 @@ import {
Achievement,
getNowPoint,
hasCompletedAchievement
} from '../plugin/ui/achievement';
} from '../tools/achievement';
import Scroll from '../components/scroll.vue';
import { isMobile } from '../plugin/use';
import { isMobile } from '../use';
const props = defineProps<{
num: number;

View File

@ -38,20 +38,19 @@
</template>
<script setup lang="tsx">
import { sleep } from 'mutate-animate';
import { onMounted, onUnmounted, ref } from 'vue';
import { onUnmounted, ref } from 'vue';
import EnemyOne from '../components/enemyOne.vue';
import Scroll from '../components/scroll.vue';
import { getDamageColor, has, keycode } from '../plugin/utils';
import { has } from '../utils';
import BookDetail from './bookDetail.vue';
import { LeftOutlined } from '@ant-design/icons-vue';
import { ToShowEnemy, detailInfo } from '../plugin/ui/book';
import { getDetailedEnemy } from '../plugin/ui/fixed';
import { ToShowEnemy, detailInfo } from '../tools/book';
import { getDetailedEnemy } from '../tools/fixed';
import { GameUi } from '@/core/main/custom/ui';
import { gameKey } from '@/core/main/custom/hotkey';
import { mainUi } from '@/core/main/init/ui';
import { mainSetting } from '@/core/main/setting';
import { isMobile } from '@/plugin/use';
import { isMobile } from '../use';
const props = defineProps<{
num: number;

View File

@ -77,12 +77,12 @@
<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from 'vue';
import EnemyOne from '../components/enemyOne.vue';
import { useDrag } from '../plugin/use';
import { useDrag } from '../use';
import EnemySpecial from '../panel/enemySpecial.vue';
import { LeftOutlined, RightOutlined } from '@ant-design/icons-vue';
import EnemyCritical from '../panel/enemyCritical.vue';
import EnemyTarget from '../panel/enemyTarget.vue';
import { detailInfo } from '../plugin/ui/book';
import { detailInfo } from '../tools/book';
import { gameKey } from '@/core/main/custom/hotkey';
const props = defineProps<{

View File

@ -8,7 +8,7 @@
<script lang="ts" setup>
import { Animation, hyper, sleep } from 'mutate-animate';
import { onMounted } from 'vue';
import { has } from '../plugin/utils';
import { has } from '../utils';
import { GameUi } from '@/core/main/custom/ui';
import { fixedUi } from '@/core/main/init/ui';

View File

@ -22,11 +22,7 @@ import { sleep, Ticker } from 'mutate-animate';
import { computed, onMounted, ref } from 'vue';
import Box from '../components/box.vue';
import list from '../data/achievement.json';
import {
AchievementType,
getNowPoint,
totalPoint
} from '../plugin/ui/achievement';
import { AchievementType, getNowPoint, totalPoint } from '../tools/achievement';
import { GameUi } from '@/core/main/custom/ui';
import { fixedUi } from '@/core/main/init/ui';

View File

@ -28,7 +28,7 @@
<script lang="ts" setup>
import { nextTick, onUnmounted, reactive, watch } from 'vue';
import { Danmaku } from '../core/main/custom/danmaku';
import { Danmaku } from '@/core/main/custom/danmaku';
import { LikeFilled } from '@ant-design/icons-vue';
import { mainSetting } from '@/core/main/setting';
import { debounce } from 'lodash-es';
@ -205,7 +205,10 @@ onUnmounted(() => {});
}
.danmaku-info {
text-shadow: 1px 1px 1px black, 1px -1px 1px black, -1px 1px 1px black,
text-shadow:
1px 1px 1px black,
1px -1px 1px black,
-1px 1px 1px black,
-1px -1px 1px black;
}

View File

@ -162,10 +162,10 @@ import { Danmaku } from '@/core/main/custom/danmaku';
import { GameUi } from '@/core/main/custom/ui';
import { sleep } from 'mutate-animate';
import { fixedUi } from '@/core/main/init/ui';
import { calStringSize, tip } from '@/plugin/utils';
import { calStringSize, tip } from '../utils';
import { gameKey } from '@/core/main/custom/hotkey';
import { isNil } from 'lodash-es';
import { stringifyCSS, parseCss, getIconHeight } from '@/plugin/utils';
import { stringifyCSS, parseCss, getIconHeight } from '../utils';
import { logger, LogLevel } from '@motajs/common';
import Scroll from '@/components/scroll.vue';
import BoxAnimate from '@/components/boxAnimate.vue';

View File

@ -20,7 +20,7 @@
<script lang="ts" setup>
import { computed, onUnmounted, ref } from 'vue';
import desc from '../data/desc.json';
import { splitText } from '../plugin/utils';
import { splitText } from '../utils';
import Colomn from '../components/colomn.vue';
import { GameUi } from '@/core/main/custom/ui';
import { gameKey } from '@/core/main/custom/hotkey';

View File

@ -125,8 +125,8 @@
<BoxAnimate
:id="
isCol
? equiped[selected] ?? 'none'
: toShow[selected]?.[0] ?? 'none'
? (equiped[selected] ?? 'none')
: (toShow[selected]?.[0] ?? 'none')
"
></BoxAnimate>
<span>{{ equip.name }}</span>
@ -179,24 +179,16 @@ import {
SortAscendingOutlined,
SortDescendingOutlined
} from '@ant-design/icons-vue';
import {
computed,
nextTick,
onMounted,
onUnmounted,
reactive,
ref,
watch
} from 'vue';
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
import Scroll from '../components/scroll.vue';
import { getAddStatus, getEquips, getNowStatus } from '../plugin/ui/equipbox';
import { getAddStatus, getEquips, getNowStatus } from '../tools/equipbox';
import BoxAnimate from '../components/boxAnimate.vue';
import { has, tip, type } from '../plugin/utils';
import { cancelGlobalDrag, isMobile, useDrag } from '../plugin/use';
import { has, tip, type } from '../utils';
import { cancelGlobalDrag, isMobile, useDrag } from '../use';
import { hyper } from 'mutate-animate';
import { GameUi } from '@/core/main/custom/ui';
import { gameKey } from '@/core/main/custom/hotkey';
import { getStatusLabel } from '../plugin/utils';
import { getStatusLabel } from '../utils';
import { mainUi } from '@/core/main/init/ui';
const props = defineProps<{

View File

@ -33,7 +33,7 @@ import { onMounted, onUpdated, Ref, ref, watch } from 'vue';
import Box from '../components/box.vue';
import { GameUi } from '@/core/main/custom/ui';
import type { DamageEnemy, EnemyInfo } from '@/game/enemy/damage';
import { nextFrame } from '@/plugin/utils';
import { nextFrame } from '../utils';
const props = defineProps<{
num: number;

View File

@ -9,9 +9,9 @@
</template>
<script lang="ts" setup>
import { getDetailedEnemy } from '../plugin/ui/fixed';
import { getDetailedEnemy } from '../tools/fixed';
import BookDetail from './bookDetail.vue';
import { detailInfo } from '../plugin/ui/book';
import { detailInfo } from '../tools/book';
import { hovered } from '@/core/main/init/fixed';
import { GameUi } from '@/core/main/custom/ui';
import { mainUi } from '@/core/main/init/ui';

View File

@ -89,8 +89,8 @@
<script lang="ts" setup>
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
import Scroll from '../components/scroll.vue';
import { getArea, getMapData, MinimapDrawer } from '../plugin/ui/fly';
import { cancelGlobalDrag, isMobile, useDrag, useWheel } from '../plugin/use';
import { getArea, getMapData, MinimapDrawer } from '../tools/fly';
import { cancelGlobalDrag, isMobile, useDrag, useWheel } from '../use';
import {
LeftOutlined,
DoubleLeftOutlined,
@ -98,10 +98,10 @@ import {
DoubleRightOutlined
} from '@ant-design/icons-vue';
import { debounce } from 'lodash-es';
import { tip } from '../plugin/utils';
import { tip } from '../utils';
import { GameUi } from '@/core/main/custom/ui';
import { gameKey } from '@/core/main/custom/hotkey';
import { createChangable } from '@/plugin/ui/common';
import { createChangable } from '../tools/common';
import { mainUi } from '@/core/main/init/ui';
import { mainSetting } from '@/core/main/setting';
import { GameStorage } from '@/core/main/storage';
@ -584,7 +584,10 @@ onUnmounted(() => {
max-width: 50%;
text-overflow: ellipsis;
overflow: hidden;
text-shadow: 1px 1px 1px black, 1px -1px 1px black, -1px 1px 1px black,
text-shadow:
1px 1px 1px black,
1px -1px 1px black,
-1px 1px 1px black,
-1px -1px 1px black;
}

View File

@ -38,11 +38,11 @@
<script lang="ts" setup>
import { Hotkey } from '@/core/main/custom/hotkey';
import { GameUi } from '@/core/main/custom/ui';
import Column from '@/components/colomn.vue';
import Column from '../components/colomn.vue';
import { mainUi } from '@/core/main/init/ui';
import { computed, onMounted, onUnmounted, reactive, ref } from 'vue';
import { KeyCode, KeyCodeUtils } from '@/plugin/keyCodes';
import { generateBinary, keycode } from '@/plugin/utils';
import { KeyCode, KeyCodeUtils } from '@motajs/client';
import { generateBinary, keycode } from '../utils';
import { cloneDeep } from 'lodash-es';
import { gameKey } from '@/core/main/custom/hotkey';

View File

@ -15,7 +15,6 @@ export { default as Shop } from './shop.vue';
export { default as Skill } from './skill.vue';
export { default as SkillTree } from './skillTree.vue';
export { default as Start } from './start.vue';
export { default as StatusBar } from './statusBar.vue';
export { default as Toolbox } from './toolbox.vue';
export { default as Hotkey } from './hotkey.vue';
export { default as Toolbar } from './toolbar.vue';

View File

@ -32,7 +32,7 @@ import {
LoadTask
} from '@motajs/legacy-common';
import { GameUi } from '@/core/main/custom/ui';
import { formatSize } from '@/plugin/utils';
import { formatSize } from '../utils';
import { logger } from '@motajs/common';
import { fixedUi } from '@/core/main/init/ui';
import { sleep } from 'mutate-animate';

View File

@ -52,7 +52,7 @@
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue';
import { MarkInfo, unmarkEnemy } from '../plugin/mark';
import { MarkInfo, unmarkEnemy } from '../mark';
import Box from '../components/box.vue';
import Scroll from '../components/scroll.vue';
import BoxAnimate from '../components/boxAnimate.vue';

View File

@ -58,7 +58,7 @@
<div class="info-editor" v-if="!!selectedItem">
<div class="editor-custom">
<component
:is="(selectedItem.controller as any)"
:is="selectedItem.controller as any"
:item="selectedItem"
:displayer="displayer"
:setting="setting"
@ -79,11 +79,11 @@ import {
MotaSettingItem,
SettingDisplayer,
SettingDisplayInfo
} from '../core/main/setting';
} from '@/core/main/setting';
import { RightOutlined, LeftOutlined } from '@ant-design/icons-vue';
import { splitText } from '../plugin/utils';
import { splitText } from '../utils';
import Scroll from '../components/scroll.vue';
import { isMobile } from '../plugin/use';
import { isMobile } from '../use';
import { gameKey } from '@/core/main/custom/hotkey';
import { GameUi } from '@/core/main/custom/ui';
import { mainUi } from '@/core/main/init/ui';

View File

@ -169,7 +169,7 @@ import {
RightOutlined,
DoubleRightOutlined
} from '@ant-design/icons-vue';
import { splitText, tip } from '../plugin/utils';
import { splitText, tip } from '../utils';
import Scroll from '../components/scroll.vue';
import BoxAnimate from '../components/boxAnimate.vue';
import { GameUi } from '@/core/main/custom/ui';

View File

@ -19,7 +19,7 @@
<script lang="ts" setup>
import { computed, ref } from 'vue';
import skills from '../data/skill.json';
import { has } from '../plugin/utils';
import { has } from '../utils';
import Column from '../components/colomn.vue';
import { mainUi } from '@/core/main/init/ui';

View File

@ -81,8 +81,8 @@
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
import { LeftOutlined, RightOutlined } from '@ant-design/icons-vue';
import Scroll from '../components/scroll.vue';
import { has, splitText, tip } from '../plugin/utils';
import { isMobile } from '../plugin/use';
import { has, splitText, tip } from '../utils';
import { isMobile } from '../use';
import { sleep } from 'mutate-animate';
import { gameKey } from '@/core/main/custom/hotkey';
import { GameUi } from '@/core/main/custom/ui';

View File

@ -64,15 +64,16 @@ import {
FullscreenExitOutlined
} from '@ant-design/icons-vue';
import { sleep } from 'mutate-animate';
import { doByInterval, keycode } from '../plugin/utils';
import { triggerFullscreen } from '../plugin/utils';
import { isMobile } from '../plugin/use';
import { doByInterval } from '../utils';
import { triggerFullscreen } from '../utils';
import { isMobile } from '../use';
import { GameUi } from '@/core/main/custom/ui';
import { gameKey } from '@/core/main/custom/hotkey';
import { mainUi } from '@/core/main/init/ui';
import { CustomToolbar } from '@/core/main/custom/toolbar';
import { mainSetting } from '@/core/main/setting';
import { mat4 } from 'gl-matrix';
// todo:
import { bgmController } from '@/module';
const props = defineProps<{

View File

@ -4,7 +4,7 @@
<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from 'vue';
import tips from '@/data/tips.json';
import tips from '../data/tips.json';
const span = ref<HTMLSpanElement>();
const nowTip = ref<string>();

View File

@ -200,9 +200,9 @@ import {
LeftOutlined
} from '@ant-design/icons-vue';
import { mainUi } from '@/core/main/init/ui';
import { isMobile } from '@/plugin/use';
import Scroll from '@/components/scroll.vue';
import { deleteWith, tip } from '@/plugin/utils';
import { isMobile } from '../use';
import Scroll from '../components/scroll.vue';
import { deleteWith, tip } from '../utils';
import { Modal } from 'ant-design-vue';
import { mainSetting } from '@/core/main/setting';
import { ToolbarItemType } from '@/core/main/init/toolbar';

View File

@ -17,7 +17,7 @@
:noaction="!!item.noDefaultAction"
>
<component
:is="(CustomToolbar.info[item.type].show as any)"
:is="CustomToolbar.info[item.type].show as any"
:item="item"
:toolbar="bar"
></component>
@ -27,7 +27,7 @@
</template>
<script lang="ts" setup>
import Box from '@/components/box.vue';
import Box from '../components/box.vue';
import { CustomToolbar } from '@/core/main/custom/toolbar';
import { GameUi } from '@/core/main/custom/ui';
import { mainSetting } from '@/core/main/setting';

View File

@ -85,8 +85,8 @@
<span>{{
selected === 'none'
? '永久道具'
: getClsName(all[selected].cls as ItemMode) ??
'永久道具'
: (getClsName(all[selected].cls as ItemMode) ??
'永久道具')
}}</span>
</div>
</div>
@ -108,13 +108,13 @@
<script lang="ts" setup>
import { LeftOutlined, RightOutlined } from '@ant-design/icons-vue';
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
import { computed, nextTick, onUnmounted, ref, watch } from 'vue';
import Scroll from '../components/scroll.vue';
import BoxAnimate from '../components/boxAnimate.vue';
import { getClsName, getItems } from '../plugin/ui/toolbox';
import { isMobile } from '../plugin/use';
import { type, keycode, has } from '../plugin/utils';
import { hyper, sleep } from 'mutate-animate';
import { getClsName, getItems } from '../tools/toolbox';
import { isMobile } from '../use';
import { type, has } from '../utils';
import { hyper } from 'mutate-animate';
import { message } from 'ant-design-vue';
import { GameUi } from '@/core/main/custom/ui';
import { gameKey } from '@/core/main/custom/hotkey';

View File

@ -73,7 +73,7 @@ export function useDrag(
if (ele) {
(ele as HTMLElement).removeEventListener('mousemove', mouseFn);
}
onup && onup(e);
onup?.(e);
};
const touchUp = (e: TouchEvent) => {
@ -81,7 +81,7 @@ export function useDrag(
if (ele) {
(ele as HTMLElement).removeEventListener('touchmove', touchFn);
}
onup && onup(e);
onup?.(e);
};
const md = (e: MouseEvent) => {

View File

@ -3,7 +3,7 @@ import { MessageApi } from 'ant-design-vue/lib/message';
import { isNil } from 'lodash-es';
import { Animation, sleep, TimingFn } from 'mutate-animate';
import { Ref, ref } from 'vue';
import { EVENT_KEY_CODE_MAP, KeyCode } from './keyCodes';
import { EVENT_KEY_CODE_MAP, KeyCode } from '@motajs/client';
import axios from 'axios';
import { decompressFromBase64 } from 'lz-string';
import { Keyboard, KeyboardEmits } from '@/core/main/custom/keyboard';
@ -336,7 +336,7 @@ export async function swapChapter(chapter: number, hard: number) {
}
export function ensureArray<T>(arr: T): T extends any[] ? T : T[] {
// @ts-ignore
// @ts-expect-error 暂时无法推导
return arr instanceof Array ? arr : [arr];
}
@ -447,7 +447,7 @@ export function getVitualKeyOnce(
const key = Keyboard.get('full')!;
key.withAssist(assist);
const id = mainUi.open('virtualKey', { keyboard: key });
key.on('emit', (item, assist, index, ev) => {
key.on('emit', (item, assist, _index, ev) => {
ev.preventDefault();
if (emitAssist) {
if (emittable.length === 0 || emittable.includes(item.key)) {

View File

@ -195,6 +195,36 @@ importers:
packages/common: {}
packages/legacy-client:
dependencies:
'@motajs/common':
specifier: workspace:*
version: link:../common
packages/legacy-common:
dependencies:
'@motajs/common':
specifier: workspace:*
version: link:../common
packages/legacy-data:
dependencies:
'@motajs/common':
specifier: workspace:*
version: link:../common
packages/legacy-ui:
dependencies:
'@motajs/client':
specifier: workspace:*
version: link:../client
'@motajs/common':
specifier: workspace:*
version: link:../common
'@motajs/render':
specifier: workspace:*
version: link:../render
packages/render:
dependencies:
'@motajs/render-core':

View File

@ -1,4 +1,4 @@
import { ensureArray, tip } from '@/plugin/utils';
import { ensureArray, tip } from '@motajs/legacy-ui';
import { sleep } from 'mutate-animate';
import { logger } from '@motajs/common';

View File

@ -11,8 +11,7 @@ import {
mainSetting,
settingStorage
} from './main/setting';
import { KeyCode } from '@/plugin/keyCodes';
import { status } from '@/plugin/ui/statusBar';
import { KeyCode } from '@motajs/client';
import '@/plugin';
import './package';
import { CustomToolbar } from './main/custom/toolbar';
@ -25,26 +24,13 @@ import {
} from './main/custom/hotkey';
import { Keyboard, generateKeyboardEvent } from './main/custom/keyboard';
import './main/layout';
import { MComponent, m } from './main/layout';
import { createSettingComponents } from './main/init/settings';
import {
createToolbarComponents,
createToolbarEditorComponents
} from './main/init/toolbar';
import { VirtualKey } from './main/init/misc';
import * as utils from '@/plugin/utils';
import * as use from '@/plugin/use';
import * as mark from '@/plugin/mark';
import * as keyCodes from '@/plugin/keyCodes';
import { addAnimate, removeAnimate } from '@/plugin/animateController';
import * as bookTools from '@/plugin/ui/book';
import * as commonTools from '@/plugin/ui/common';
import * as equipboxTools from '@/plugin/ui/equipbox';
import * as fixedTools from '@/plugin/ui/fixed';
import * as flyTools from '@/plugin/ui/fly';
import * as statusBarTools from '@/plugin/ui/statusBar';
import * as toolboxTools from '@/plugin/ui/toolbox';
import * as UI from '@ui/index';
import { UI } from '@motajs/legacy-ui';
import Box from '@/components/box.vue';
import BoxAnimate from '@/components/boxAnimate.vue';
import Colomn from '@/components/colomn.vue';
@ -54,7 +40,6 @@ import EnemyCritical from '@/panel/enemyCritical.vue';
import EnemySpecial from '@/panel/enemySpecial.vue';
import EnemyTarget from '@/panel/enemyTarget.vue';
import KeyboardPanel from '@/panel/keyboard.vue';
import { MCGenerator } from './main/layout';
import { logger } from '@motajs/common';
import { Danmaku } from './main/custom/danmaku';
import * as Shadow from './fx/shadow';
@ -73,16 +58,12 @@ Mota.register('class', 'Keyboard', Keyboard);
Mota.register('class', 'MotaSetting', MotaSetting);
Mota.register('class', 'SettingDisplayer', SettingDisplayer);
Mota.register('class', 'UiController', UiController);
Mota.register('class', 'MComponent', MComponent);
Mota.register('class', 'Danmaku', Danmaku);
// ----- 函数注册
Mota.register('fn', 'm', m);
Mota.register('fn', 'unwrapBinary', unwarpBinary);
Mota.register('fn', 'checkAssist', checkAssist);
Mota.register('fn', 'isAssist', isAssist);
Mota.register('fn', 'generateKeyboardEvent', generateKeyboardEvent);
Mota.register('fn', 'addAnimate', addAnimate);
Mota.register('fn', 'removeAnimate', removeAnimate);
// ----- 变量注册
Mota.register('var', 'mainUi', mainUi);
Mota.register('var', 'fixedUi', fixedUi);
@ -102,18 +83,6 @@ Mota.register('module', 'MiscComponents', {
VirtualKey
});
Mota.register('module', 'RenderUtils', utils);
Mota.register('module', 'Use', use);
Mota.register('module', 'Mark', mark);
Mota.register('module', 'KeyCodes', keyCodes);
Mota.register('module', 'UITools', {
book: bookTools,
common: commonTools,
equipbox: equipboxTools,
fixed: fixedTools,
fly: flyTools,
statusBar: statusBarTools,
toolbox: toolboxTools
});
Mota.register('module', 'UI', UI);
Mota.register('module', 'UIComponents', {
Box,
@ -126,7 +95,6 @@ Mota.register('module', 'UIComponents', {
EnemyTarget,
Keyboard: KeyboardPanel
});
Mota.register('module', 'MCGenerator', MCGenerator);
Mota.register('module', 'Shadow', Shadow);
Mota.register('module', 'Effect', {});
Mota.register('module', 'Render', Render);

View File

@ -1,4 +1,4 @@
import { KeyCode } from '@/plugin/keyCodes';
import { KeyCode } from '@motajs/client';
import { Hotkey, HotkeyData } from '../custom/hotkey';
import type { HeroMover, IMoveController } from '@/game/state/move';
import { Ticker } from 'mutate-animate';

View File

@ -8,7 +8,7 @@ import {
getIconHeight,
parseCss,
tip
} from '@/plugin/utils';
} from '@motajs/legacy-ui';
import axios, { AxiosResponse, toFormData } from 'axios';
import { Component, VNode, h, shallowReactive } from 'vue';
// /* @__PURE__ */ import { id, password } from '../../../../user';

View File

@ -1,5 +1,10 @@
import { KeyCode } from '@/plugin/keyCodes';
import { deleteWith, generateBinary, keycode, spliceBy } from '@/plugin/utils';
import { KeyCode } from '@motajs/client';
import {
deleteWith,
generateBinary,
keycode,
spliceBy
} from '@motajs/legacy-ui';
import { EventEmitter } from 'eventemitter3';
import { isNil } from 'lodash-es';

View File

@ -1,8 +1,8 @@
import { EventEmitter, Listener } from '@motajs/legacy-common';
import { KeyCode } from '@/plugin/keyCodes';
import { KeyCode } from '@motajs/client';
import { gameKey } from './hotkey';
import { unwarpBinary } from './hotkey';
import { deleteWith, flipBinary } from '@/plugin/utils';
import { deleteWith, flipBinary } from '@motajs/legacy-ui';
import { cloneDeep } from 'lodash-es';
import { shallowReactive } from 'vue';

View File

@ -1,5 +1,5 @@
import { EventEmitter } from '@motajs/legacy-common';
import { deleteWith, has } from '@/plugin/utils';
import { deleteWith, has } from '@motajs/legacy-ui';
import { Component, nextTick, reactive, shallowReactive } from 'vue';
import { fixedUi } from '../init/ui';
import { GameStorage } from '../storage';
@ -126,48 +126,6 @@ const misc: Misc = {
}
};
const playingDefaultTool: MiscToolbar = {
id: '@defaults_misc',
type: 'misc',
folded: false,
noDefaultAction: true,
items: [
'book',
'fly',
'save',
'load',
'toolbox',
'equipbox',
'shop',
'virtualKey',
'setting',
'undo',
'redo',
'viewMap',
'danmaku',
'minimap'
]
};
const replayingDefaultTool: MiscToolbar = {
id: '@defaults_misc',
type: 'misc',
folded: false,
noDefaultAction: true,
items: [
'startReplay',
'stopReplay',
'rewindReplay',
'stepReplay',
'book',
'speedDownReplay',
'speedUpReplay',
'save',
'viewMap',
'danmaku',
'minimap'
]
};
export class CustomToolbar extends EventEmitter<CustomToolbarEvent> {
static num: number = 0;
static list: CustomToolbar[] = shallowReactive([]);
@ -389,11 +347,11 @@ export class CustomToolbar extends EventEmitter<CustomToolbarEvent> {
toolbarStorage.read();
for (const [key, value] of Object.entries(toolbarStorage.data)) {
const bar = this.get(key) ?? new CustomToolbar(key);
bar.x = value.x;
bar.y = value.y;
bar.width = value.w;
bar.height = value.h;
for (const item of value.items) {
bar.x = value!.x;
bar.y = value!.y;
bar.width = value!.w;
bar.height = value!.h;
for (const item of value!.items) {
bar.add(item);
}
}

View File

@ -1,8 +1,13 @@
import { KeyCode } from '@/plugin/keyCodes';
import { KeyCode } from '@motajs/client';
import { gameKey, HotkeyJSON } from '../custom/hotkey';
import { openDanmakuPoster, tip } from '@/plugin/utils';
import {
openDanmakuPoster,
tip,
hasMarkedEnemy,
markEnemy,
unmarkEnemy
} from '@motajs/legacy-ui';
import { hovered } from './fixed';
import { hasMarkedEnemy, markEnemy, unmarkEnemy } from '@/plugin/mark';
import { mainUi } from './ui';
import { GameStorage } from '../storage';

View File

@ -1,4 +1,4 @@
import { KeyCode } from '@/plugin/keyCodes';
import { KeyCode } from '@motajs/client';
import { Keyboard } from '../custom/keyboard';
const qweKey = new Keyboard('qwe'); // 字母键盘A-Z

View File

@ -1,4 +1,4 @@
import { KeyCode, KeyCodeUtils } from '@/plugin/keyCodes';
import { KeyCode, KeyCodeUtils } from '@motajs/client';
import { CustomToolbar } from '../custom/toolbar';
import BoxAnimate from '@/components/boxAnimate.vue';
import { checkAssist, unwarpBinary } from '../custom/hotkey';
@ -6,7 +6,7 @@ import {
flipBinary,
getVitualKeyOnce,
openDanmakuPoster
} from '@/plugin/utils';
} from '@motajs/legacy-ui';
import { cloneDeep } from 'lodash-es';
import {
Button,
@ -18,11 +18,10 @@ import {
import { MotaSettingItem, mainSetting } from '../setting';
import Minimap from '@/components/minimap.vue';
import { gameKey } from '../custom/hotkey';
import { FunctionalComponent, StyleValue, h, ref } from 'vue';
import { FunctionalComponent, h, ref } from 'vue';
import { mainUi } from './ui';
import { isMobile } from '@/plugin/use';
import { isMobile } from '@motajs/legacy-ui';
import {
BackwardFilled,
BackwardOutlined,
BorderOuterOutlined,
CaretRightOutlined,

View File

@ -1,4 +1,4 @@
import * as UI from '@ui/.';
import { UI } from '@motajs/legacy-ui';
import * as MiscUI from './misc';
import { GameUi, UiController } from '../custom/ui';
import { mainSetting } from '../setting';
@ -26,7 +26,6 @@ mainUi.showAll();
export const fixedUi = new UiController(true);
fixedUi.register(
new GameUi('statusBar', UI.StatusBar),
new GameUi('markedEnemy', UI.Marked),
new GameUi('fixed', UI.Fixed),
new GameUi('chapter', UI.Chapter),

View File

@ -1,509 +0,0 @@
import {
Component,
RenderFunction,
SetupContext,
VNode,
VNodeChild,
defineComponent,
h as hVue,
isVNode,
onMounted
} from 'vue';
import BoxAnimate from '@/components/boxAnimate.vue';
import { ensureArray } from '@/plugin/utils';
interface VForRenderer {
type: '@v-for';
items: any[] | (() => any[]);
map: (value: any, index: number) => VNode;
}
interface MotaComponent extends MotaComponentConfig {
type: string;
children: (MComponent | MotaComponent | VNode)[];
}
interface MotaComponentConfig {
innerText?: string | (() => string);
props?: Record<string, () => any>;
component?: Component | MComponent;
dComponent?: () => Component;
/** 传递插槽 */
slots?: Record<string, (props: Record<string, any>) => VNode | VNode[]>;
vif?: () => boolean;
velse?: boolean;
}
type OnSetupFunction = (props: Record<string, any>, ctx: SetupContext) => void;
type SetupFunction = (
props: Record<string, any>,
ctx: SetupContext
) => RenderFunction | Promise<RenderFunction>;
type RetFunction = (
props: Record<string, any>,
ctx: SetupContext
) => VNodeChild | VNodeChild[];
type OnMountedFunction = (
props: Record<string, any>,
ctx: SetupContext,
canvas: HTMLCanvasElement[]
) => void;
type NonComponentConfig = Omit<
MotaComponentConfig,
'innerText' | 'component' | 'slots' | 'dComponent'
>;
type MComponentChildren =
| (MComponent | MotaComponent | VNode)[]
| MComponent
| MotaComponent
| VNode;
export class MComponent {
static mountNum: number = 0;
content: (MotaComponent | VForRenderer)[] = [];
private onSetupFn?: OnSetupFunction;
private setupFn?: SetupFunction;
private onMountedFn?: OnMountedFunction;
private retFn?: RetFunction;
private propsDef: Record<string, any> = {};
private emitsDef: string[] = [];
/**
* propsprops名称例如num: Number
* `UiController.open`ui
* - num: ui的唯一标识符Number
* - ui: 对于的GameUi实例GameUi
* @param props props
*/
defineProps(props: Record<string, any>) {
this.propsDef = props;
}
/**
* emitsemits的名称
* @param emits emits
*/
defineEmits(emits: string[]) {
this.emitsDef = emits;
}
/**
* div渲染内容
* @param children
* @param config {@link MComponent.h}
*/
div(children?: MComponentChildren, config?: NonComponentConfig) {
return this.h('div', children, config);
}
/**
* span渲染内容
* @param children
* @param config {@link MComponent.h}
*/
span(children?: MComponentChildren, config?: NonComponentConfig) {
return this.h('span', children, config);
}
/**
* canvas渲染内容
* @param config {@link MComponent.h}
*/
canvas(config?: NonComponentConfig) {
return this.h('canvas', [], config);
}
/**
*
* @param text
*/
text(text: string | (() => string), config: NonComponentConfig = {}) {
return this.h('text', [], { ...config, innerText: text });
}
/**
*
* @param component
* @param config {@link MComponent.h}
*/
com(
component: Component | MComponent,
config?: Omit<MotaComponentConfig, 'innerText' | 'component'>
) {
return this.h(component, [], config);
}
/**
*
* @param items
* @param map VNodeVNode可以通过Vue.h函数
* MComponent.vNode函数生成
*/
vfor<T>(items: T[] | (() => T[]), map: (value: T, index: number) => VNode) {
this.content.push(MCGenerator.vfor(items, map));
return this;
}
/**
* `MComponent``MComponent``export`
* `Vue``h``h``export`
*
* `slots``vfor.map`
* 使使`setup`
* `setup`
* @param type
* - dom元素`div` `span`
* - `MComponent`
* - `text``children`
* `config``innerText`
* - `component``config``component`
* `children`
* - `@v-for`
* @param children
* - `MComponent`
* - `MComponent`
* @param config
* - `innerText`:
* - `props`: `props``props`
* `prop``class` `id`html属性`attribute`
* `Vue``attribute`on开头
* v-on
* - `component`: `dComponent`
* - `dComponent`: `component`
* `component`使
* - `slots`:
* VNode或数组`MComponent.vNode`VNode数组
*
* - `vif`: `velse``true`
* `else-if`
* - `velse`:
*/
h(
type: string | Component | MComponent,
children?: MComponentChildren,
config: MotaComponentConfig = {}
): this {
this.content.push(MCGenerator.h(type, children, config));
return this;
}
/**
* setup被执行时props
*/
onSetup(fn: OnSetupFunction) {
this.onSetupFn = fn;
return this;
}
/**
*
* @param fn props和当前级组件
*
* A组件中调用了B组件A组件的画布B组件的画布
*/
onMounted(fn: OnMountedFunction) {
this.onMountedFn = fn;
return this;
}
/**
* setup执行函数props, slotsVNode
*/
setup(fn: SetupFunction) {
this.setupFn = fn;
return this;
}
/**
* setup返回的函数
* @param fn setup返回的函数
*/
ret(fn: RetFunction) {
this.retFn = fn;
return this;
}
/**
* MComponent实例导出成为一个组件
*/
export() {
if (!this.setupFn) {
return defineComponent(
(props, ctx) => {
const mountNum = MComponent.mountNum++;
this.onSetupFn?.(props, ctx);
onMounted(() => {
this.onMountedFn?.(
props,
ctx,
Array.from(
document.getElementsByClassName(
`--mota-component-canvas-${mountNum}`
) as HTMLCollectionOf<HTMLCanvasElement>
)
);
});
if (this.retFn) return () => this.retFn!(props, ctx);
else {
return () => {
const vNodes = MComponent.vNode(
this.content,
mountNum
);
return vNodes;
};
}
},
{
emits: this.emitsDef,
props: this.propsDef
}
);
} else {
return defineComponent((props, ctx) => this.setupFn!(props, ctx));
}
}
/**
* VNode
* @param child
* @param mount id
*/
static vNodeS(child: MotaComponent, mount?: number) {
return this.vNode([child], mount)[0];
}
/**
* MComponent实例生成为一个VNode列表
* @param mc VNode的组件
* @param mount id
*/
static vNodeM(mc: MComponent, mount?: number) {
return this.vNode(mc.content, mount);
}
/**
* MComponent内容生成为一个VNode列表
* @param children VNode的内容列表
* @param mount id
*/
static vNode(
children: (MotaComponent | VForRenderer | VNode)[],
mount?: number
) {
const mountNum = mount ?? this.mountNum++;
const res: VNode[] = [];
const vifRes: Map<number, boolean> = new Map();
children.forEach((v, i) => {
if (isVNode(v)) {
res.push(v);
return;
}
if (v.type === '@v-for') {
const node = v as VForRenderer;
const items =
typeof node.items === 'function'
? node.items()
: node.items;
items.forEach((v, i) => {
res.push(node.map(v, i));
});
} else {
const node = v as MotaComponent;
if (node.velse && vifRes.get(i - 1)) {
vifRes.set(i, true);
return;
}
let vif = true;
if (node.vif) {
vifRes.set(i, (vif = node.vif()));
}
if (!vif) return;
const props = this.unwrapProps(node.props);
if (v.type === 'component') {
if (!v.component && !v.dComponent) {
throw new Error(
`Using dynamic component must provide component property.`
);
}
if (v.dComponent) {
res.push(hVue(v.dComponent(), props, v.slots));
} else {
if (v.component instanceof MComponent) {
res.push(
...MComponent.vNode(
v.component.content,
mountNum
)
);
} else {
res.push(hVue(v.component!, props, v.slots));
}
}
} else if (v.type === 'text') {
res.push(
hVue(
'span',
typeof v.innerText === 'function'
? v.innerText()
: v.innerText
)
);
} else if (v.type === 'canvas') {
const cls = `--mota-component-canvas-${mountNum}`;
const mix = !!props.class ? cls + ' ' + props.class : cls;
props.class = mix;
res.push(hVue('canvas', props, node.slots));
} else {
// 这个时候不可能会有插槽,只会有子内容,因此直接渲染子内容
const content = node.children;
const vn = this.vNode(
content
.map(v => (v instanceof MComponent ? v.content : v))
.flat(),
mountNum
);
res.push(hVue(v.type, props, vn));
}
}
});
return res;
}
/**
* props的真实值props是一个函数
* @param props props
*/
static unwrapProps(props?: Record<string, () => any>): Record<string, any> {
if (!props) return {};
const res: Record<string, any> = {};
for (const [key, value] of Object.entries(props)) {
res[key] = value();
}
return res;
}
/**
* propsprops
* @param component props的组件
* @param props props
*/
static prop(component: Component, props: Record<string, any>) {
return hVue(component, props);
}
}
/**
* MComponent实例ui时会频繁使用使m这个简单的名字作为函数名
* @returns MComponent实例
*/
export function m() {
return new MComponent();
}
export namespace MCGenerator {
export function h(
type: string | Component | MComponent,
children?: MComponentChildren,
config: MotaComponentConfig = {}
): MotaComponent {
if (typeof type === 'string') {
return {
type,
children: ensureArray(children ?? []),
props: config.props,
innerText: config.innerText,
slots: config.slots,
vif: config.vif,
velse: config.velse,
component: config.component
};
} else {
return {
type: 'component',
children: ensureArray(children ?? []),
props: config.props,
innerText: config.innerText,
slots: config.slots,
vif: config.vif,
velse: config.velse,
component: type
};
}
}
export function div(
children?: MComponentChildren,
config?: NonComponentConfig
): MotaComponent {
return h('div', children, config);
}
export function span(
children?: MComponentChildren,
config?: NonComponentConfig
): MotaComponent {
return h('span', children, config);
}
export function canvas(config?: NonComponentConfig): MotaComponent {
return h('canvas', [], config);
}
export function text(
text: string | (() => string),
config: NonComponentConfig = {}
): MotaComponent {
return h('text', [], { ...config, innerText: text });
}
export function com(
component: Component | MComponent,
config: Omit<MotaComponentConfig, 'innerText' | 'component'>
): MotaComponent {
return h(component, [], config);
}
/**
* VNode
* @param id id
* @param width
* @param height
* @param noBoarder
*/
export function icon(
id: AllIds,
width?: number,
height?: number,
noBoarder?: number
): VNode {
return hVue(BoxAnimate, { id, width, height, noBoarder });
}
export function vfor<T>(
items: T[] | (() => T[]),
map: (value: T, index: number) => VNode
): VForRenderer {
return {
type: '@v-for',
items,
map
};
}
/**
*
* @param value
*/
export function f<T>(value: T): () => T {
return () => value;
}
}

View File

@ -1,11 +1,9 @@
import { FunctionalComponent, reactive } from 'vue';
import { EventEmitter } from '@motajs/legacy-common';
import { GameStorage } from './storage';
import { has, triggerFullscreen } from '@/plugin/utils';
import { has, triggerFullscreen, isMobile } from '@motajs/legacy-ui';
import { createSettingComponents } from './init/settings';
import settingsText from '@/data/settings.json';
import { isMobile } from '@/plugin/use';
import { fontSize } from '@/plugin/ui/statusBar';
import { CustomToolbar } from './custom/toolbar';
import { fixedUi } from './init/ui';
import { bgmController, soundPlayer } from '@/module';
@ -361,7 +359,7 @@ function handleScreenSetting<T extends number | boolean>(
storage.setValue('@@absoluteFontSize', absoluteSize);
storage.write();
} else if (key === 'fontSizeStatus') {
fontSize.value = n as number;
// fontSize.value = n as number;
}
}

View File

@ -1,10 +1,10 @@
import { has } from '@/plugin/utils';
import { isNil } from 'lodash-es';
export class GameStorage<T extends object = any> {
static list: GameStorage<any>[] = [];
key: string;
data!: T;
data!: Partial<T>;
constructor(key: string) {
this.key = key;
@ -42,7 +42,7 @@ export class GameStorage<T extends object = any> {
getValue<K extends keyof T>(key: K, defaults: T[K]): T[K];
getValue<T>(key: string, defaults?: T): T;
getValue<K extends keyof T>(key: K, defaults?: T[K]) {
if (has(this.data[key])) return this.data[key];
if (!isNil(this.data[key])) return this.data[key];
else {
if (defaults !== void 0) {
this.data[key] = defaults;
@ -57,7 +57,6 @@ export class GameStorage<T extends object = any> {
}
clear() {
// @ts-ignore
this.data = {};
}

View File

@ -13,7 +13,7 @@ import type { MotaSetting, SettingDisplayer } from '@/core/main/setting';
import type { GameStorage } from '@/core/main/storage';
import type { DamageEnemy, EnemyCollection } from './enemy/damage';
import type { specials } from './enemy/special';
import type { KeyCode } from '@/plugin/keyCodes';
import type { KeyCode } from '@motajs/client';
import type { Ref } from 'vue';
import type * as battle from './enemy/battle';
import type * as hero from './state/hero';
@ -121,10 +121,7 @@ type InterfaceType = keyof SystemInterfaceMap;
interface PluginInterface {
// 渲染进程定义的插件
use_r: typeof import('../plugin/use');
fly_r: typeof import('../plugin/ui/fly');
chase_r: typeof import('../plugin/chase');
completion_r: typeof import('../plugin/completion');
gameCanvas_r: typeof import('../plugin/fx/gameCanvas');
frag_r: typeof import('../plugin/fx/frag');
boss_r: typeof import('../plugin/boss');

View File

@ -13,7 +13,7 @@ import {
import { mainUi } from '@/core/main/init/ui';
import { gameKey } from '@/core/main/custom/hotkey';
import { generateKeyboardEvent } from '@/core/main/custom/keyboard';
import { getVitualKeyOnce } from '@/plugin/utils';
import { getVitualKeyOnce } from '@motajs/legacy-ui';
import { getAllSavesData, getSaveData } from '@/module/utils';
export interface SettingsProps extends Partial<ChoicesProps>, UIComponentProps {

View File

@ -11,7 +11,7 @@ import {
import { transitionedColor } from '../use';
import { linear } from 'mutate-animate';
import { Scroll } from '../components/scroll';
import { getArea, MinimapDrawer } from '@/plugin/ui/fly';
import { getArea, MinimapDrawer } from '@motajs/legacy-ui';
import {
NumpadToolbar,
PlayingToolbar,

View File

@ -17,12 +17,12 @@ import {
generateBinary,
getVitualKeyOnce,
openDanmakuPoster
} from '@/plugin/utils';
} from '@motajs/legacy-ui';
import { gameKey } from '@/core/main/custom/hotkey';
import { generateKeyboardEvent } from '@/core/main/custom/keyboard';
import { transitioned } from '../use';
import { linear } from 'mutate-animate';
import { KeyCode } from '@/plugin/keyCodes';
import { KeyCode } from '@motajs/client';
import { Progress } from '../components/misc';
interface ToolbarProps extends DefaultProps {

View File

@ -8,6 +8,7 @@
"@motajs/system-ui": "workspace:*",
"@motajs/legacy-common": "workspace:*",
"@motajs/legacy-client": "workspace:*",
"@motajs/legacy-data": "workspace:*"
"@motajs/legacy-data": "workspace:*",
"@motajs/legacy-ui": "workspacee:*"
}
}

View File

@ -2,7 +2,7 @@ import { Transform, MotaOffscreenCanvas2D } from '@motajs/render';
import { IStateDamageable } from '@/game/state/interface';
import { Hitbox, Projectile } from './barrage';
import type { PalaceBoss } from './palaceBoss';
import { clamp } from '../utils';
import { clamp } from '@motajs/legacy-ui';
function popDamage(damage: number, boss: PalaceBoss, color: string) {
const { x, y } = core.status.hero.loc;

View File

@ -1,6 +1,6 @@
import { Animation, hyper, linear, power, sleep } from 'mutate-animate';
import { Chase, ChaseData, IChaseController } from './chase';
import { completeAchievement } from '../ui/achievement';
import { completeAchievement } from '@motajs/legacy-ui';
import {
Camera,
CameraAnimation,

View File

@ -1,5 +1,5 @@
import { Animation, linear, sleep } from 'mutate-animate';
import { has } from '../utils';
import { has } from '@motajs/legacy-ui';
// todo: 移植到渲染树

View File

@ -1,25 +1,10 @@
import * as fly from './ui/fly';
import * as chase from './chase';
import * as completion from './completion';
import * as use from './use';
import * as gameCanvas from './fx/gameCanvas';
import * as animateController from './animateController';
import * as achievement from './ui/achievement';
import * as boss from './boss';
import * as utils from './utils';
import './loopMap';
Mota.Plugin.register('fly_r', fly);
Mota.Plugin.register('chase_r', chase);
Mota.Plugin.register('completion_r', completion, completion.init);
Mota.Plugin.register('use_r', use);
Mota.Plugin.register('gameCanvas_r', gameCanvas);
Mota.Plugin.register(
'animateController_r',
animateController,
animateController.default
);
Mota.Plugin.register('chase_r', chase);
Mota.Plugin.register('achievement_r', achievement);
Mota.Plugin.register('boss_r', boss);
Mota.Plugin.register('utils_r', utils);

View File

@ -1,4 +0,0 @@
import { ref } from 'vue';
export const status = ref(false);
export const fontSize = ref(100);

View File

@ -1,90 +0,0 @@
<template>
<Colomn @close="exit" :width="60" :height="80" :left="30" :right="70"
><template #left>
<div id="bgm-list">
<span
v-for="(bgm, i) of list"
class="selectable"
:selected="selected === i"
@click="select(i)"
>
{{ bgm!.area }}
</span>
</div></template
>
<template #right
><div>
<div id="bgm-name">
<img id="bgm-image" :src="list[selected]!.img" />
<span>{{ name }}</span>
<span v-if="list[selected]!.from"
>出自&nbsp;&nbsp;&nbsp;&nbsp;{{
list[selected]!.from
}}</span
>
</div>
<span v-html="content"></span></div></template
></Colomn>
</template>
<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue';
import Colomn from '../components/colomn.vue';
import bgm from '../data/bgm.json';
import { splitText } from '../plugin/utils';
import { mainUi } from '@/core/main/init/ui';
const props = defineProps<{
num: number;
}>();
interface Bgm {
img: string;
area: string;
name: string;
desc: string[];
from?: string;
}
const list = bgm as Partial<Record<BgmIds, Bgm>>;
const selected = ref<BgmIds>('title.opus');
const content = computed(() => {
return eval('`' + splitText(list[selected.value]!.desc) + '`');
});
const name = computed(() => list[selected.value]!.name);
function exit() {
mainUi.close(props.num);
}
function select(id: BgmIds) {
selected.value = id;
}
</script>
<style lang="less" scoped>
#bgm-list {
display: flex;
flex-direction: column;
}
#bgm-name {
display: flex;
flex-direction: column;
align-items: center;
}
#bgm-image {
margin-top: 5%;
border: 1px solid #fff;
width: 33vw;
}
@media screen and (max-width: 600px) {
#bgm-image {
width: 70vw;
}
}
</style>

View File

@ -1,393 +0,0 @@
<template>
<div id="status-bar">
<Box
:resizable="true"
:dragable="true"
v-model:width="width"
v-model:height="height"
>
<Scroll
id="status-main"
v-model:update="updateStatus"
:no-scroll="true"
>
<div id="status-div">
<span
id="status-floor"
@click.stop="viewMap"
class="button-text"
>{{ floor }}</span
>
<span id="status-lv">{{ lvName }}</span>
<div id="status-skill" class="status-item">
<img :src="imgs['skill.png'].src" class="status-icon" />
<span>{{ skill }}</span>
<span
v-if="has(spring)"
id="status-spring"
class="status-extra"
>剩余{{ spring }}</span
>
</div>
<div id="status-hp" class="status-item">
<img :src="imgs['hp.png'].src" class="status-icon" />
<span class="status-item-bold">{{
format(hero.hp!)
}}</span>
<span
id="status-hpmax"
class="status-extra status-item-bold"
>+{{
format(Math.min(hero.hpmax!, hero.def! / 10))
}}/t</span
>
<span
v-if="jumpCnt !== -1"
id="status-jump"
class="status-extra"
>跳跃剩余{{ jumpCnt }}</span
>
</div>
<div id="status-atk" class="status-item">
<img :src="imgs['atk.png'].src" class="status-icon" />
<span class="status-item-bold">{{
format(hero.atk!)
}}</span>
<span
id="status-mana"
class="status-extra status-item-bold"
>+{{ format(hero.mana!) }}</span
>
</div>
<div id="status-def" class="status-item status-item-bold">
<img :src="imgs['def.png'].src" class="status-icon" />
<span>{{ format(hero.def!) }}</span>
<span
v-if="hero.magicDef! > 0"
id="status-magic-def"
class="status-extra status-item-bold"
>+{{ format(hero.magicDef!) }}</span
>
</div>
<div id="status-mdef" class="status-item status-item-bold">
<img :src="imgs['IQ.png'].src" class="status-icon" />
<span>{{ format(hero.mdef!) }}</span>
</div>
<div id="status-money" class="status-item status-item-bold">
<img :src="imgs['money.png'].src" class="status-icon" />
<span>{{ format(hero.money!) }}</span>
</div>
<div id="status-exp" class="status-item status-item-bold">
<img :src="imgs['exp.png'].src" class="status-icon" />
<span>{{ format(up) }}</span>
</div>
<div id="status-key" class="status-item status-item-bold">
<span style="color: #fca; padding-left: 10%">{{
keys[0]?.toString().padStart(2, '0')
}}</span>
<span style="color: #aad">{{
keys[1]?.toString().padStart(2, '0')
}}</span>
<span style="color: #f88; padding-right: 10%">{{
keys[2]?.toString().padStart(2, '0')
}}</span>
</div>
<div v-if="skillOpened" class="status-item">
<span
id="skill-tree"
class="button-text"
@click.stop="openSkillTree"
>技能树</span
>
</div>
<div v-if="skillOpened" class="status-item">
<span
id="status-skill"
class="button-text"
@click.stop="openSkill"
>查看技能</span
>
</div>
</div>
</Scroll>
</Box>
</div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref, shallowReactive, watch } from 'vue';
import Box from '../components/box.vue';
import Scroll from '../components/scroll.vue';
import { status } from '../plugin/ui/statusBar';
import { isMobile } from '../plugin/use';
import { fontSize } from '../plugin/ui/statusBar';
import { has } from '@/plugin/utils';
let main: HTMLDivElement;
const imgs = core.material.images.images;
const width = ref(
isMobile ? window.innerWidth - 60 : window.innerWidth * 0.175
);
const height = ref(isMobile ? 250 : window.innerHeight - 100);
const updateStatus = ref(false);
const format = core.formatBigNumber;
watch(width, n => (updateStatus.value = !updateStatus.value));
watch(height, n => (updateStatus.value = !updateStatus.value));
watch(fontSize, n => (main.style.fontSize = `${isMobile ? n * 1.5 : n}%`));
const HeroSkill = Mota.require('module', 'Mechanism').HeroSkill;
const hero = shallowReactive<Partial<HeroStatus>>({});
const keys = shallowReactive<number[]>([]);
const floor = ref<string>();
const lvName = ref<string>();
const skill = ref<string>(HeroSkill.getAutoSkill() ? '自动切换' : '无');
const up = ref(0);
const spring = ref<number>();
const skillOpened = ref(core.getFlag('chapter', 0) > 0);
const jumpCnt = ref<number>();
/**
* 要展示的勇士属性
*/
const toShow: (keyof HeroStatus)[] = [
'hp', //
'atk', //
'def', //
'mdef', //
'hpmax', //
'mana', //
'money', //
'exp', //
'lv', //
'magicDef' //
];
watch(status, update);
/**
* 更新显示内容
*/
function update() {
toShow.forEach(v => {
hero[v] = Mota.requireAll('fn').getHeroStatusOn(v);
});
keys[0] = core.itemCount('yellowKey');
keys[1] = core.itemCount('blueKey');
keys[2] = core.itemCount('redKey');
floor.value = core.status.thisMap?.title;
lvName.value = core.getLvName(hero.lv);
if (HeroSkill.getAutoSkill()) {
skill.value = '自动切换';
} else {
const enabled = HeroSkill.getEnabled();
switch (enabled) {
case HeroSkill.Blade:
skill.value = '断灭之刃';
break;
case HeroSkill.Shield:
skill.value = '铸剑为盾';
break;
default:
skill.value = '无';
break;
}
}
up.value = core.getNextLvUpNeed() ?? 0;
if (core.hasFlag('spring')) {
spring.value = 50 - (flags.springCount ?? 0);
} else {
spring.value = void 0;
}
skillOpened.value = core.getFlag('chapter', 0) > 0;
jumpCnt.value =
!HeroSkill.learnedSkill(HeroSkill.Jump) ||
Mota.Plugin.require('skill_g').jumpIgnoreFloor.has(core.status.floorId)
? -1
: 3 - (flags[`jump_${core.status.floorId}`] ?? 0);
}
function openSkillTree() {
core.useItem('skill1');
}
function openSkill() {
core.useItem('cross');
}
function viewMap() {
core.ui._drawViewMaps();
}
function openStudy() {}
function resize() {
requestAnimationFrame(() => {
main.style.fontSize = `${
isMobile ? fontSize.value * 1.5 : fontSize.value
}%`;
});
}
onMounted(() => {
update();
main = document.getElementById('status-main') as HTMLDivElement;
window.addEventListener('resize', resize);
resize();
});
onUnmounted(() => {
window.removeEventListener('resize', resize);
});
</script>
<style lang="less" scoped>
#status-main {
background-color: #0009;
width: 100%;
height: 100%;
padding: 1vh 0;
font-size: v-bind(fontSize);
}
.status-item {
position: relative;
max-width: 17.5vw;
font-size: 200%;
width: 100%;
margin-bottom: 14px;
text-shadow:
3px 2px 3px #000,
0px 0px 3px #111;
display: flex;
flex-direction: row;
align-items: center;
}
.status-item-bold {
font-weight: bold;
}
.status-icon {
width: 2.8vw;
height: 2.8vw;
margin-right: 10%;
margin-left: 10%;
pointer-events: none;
}
.status-value {
transform: translateY(2px);
}
#status-header {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
#status-div {
display: flex;
flex-direction: row;
flex-wrap: wrap;
height: 100%;
}
#status-floor {
max-width: 17.5vw;
font-size: 200%;
width: 100%;
text-align: center;
text-shadow:
3px 2px 3px #000,
0px 0px 3px #111;
}
#status-lv {
max-width: 17.5vw;
font-size: 200%;
width: 100%;
text-align: center;
text-shadow:
3px 2px 3px #000,
0px 0px 3px #111;
}
.status-extra {
position: absolute;
right: 10%;
bottom: 0;
font-size: 75%;
}
#status-mana {
line-height: 0;
color: rgb(255, 211, 211);
}
#status-magic-def {
line-height: 0;
color: rgb(176, 189, 255);
}
#status-hpmax {
line-height: 0;
color: rgb(167, 255, 167);
}
#status-spring {
line-height: 0;
color: rgb(167, 255, 167);
top: 0;
font-size: 75%;
}
#status-jump {
line-height: 0;
top: 0;
font-size: 75%;
}
#status-key {
display: flex;
flex-direction: row;
justify-content: space-around;
}
#skill-tree,
#status-skill {
text-align: center;
width: 100%;
}
@media screen and (max-width: 600px) {
.status-item {
max-width: 40vw;
font-size: 120%;
}
#status-floor {
max-width: 40vw;
font-size: 120%;
width: 100%;
}
#status-lv {
max-width: 40vw;
font-size: 120%;
width: 100%;
}
.status-icon {
width: 28px;
height: 28px;
}
}
</style>