mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-01-19 20:59:37 +08:00
refactor: 怪物标记
This commit is contained in:
parent
d178908649
commit
8a8dee3176
@ -404,9 +404,6 @@ main.prototype.loadAsync = async function (mode, callback) {
|
|||||||
});
|
});
|
||||||
await core.init(coreData, callback);
|
await core.init(coreData, callback);
|
||||||
if (main.mode === 'play') main.loading.emit('coreInit');
|
if (main.mode === 'play') main.loading.emit('coreInit');
|
||||||
if (main.mode === 'play') {
|
|
||||||
mota.plugin.mark.showMarkedEnemy.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
core.resize();
|
core.resize();
|
||||||
|
|
||||||
|
@ -420,21 +420,9 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 77: // M:快速标记
|
case 77: // M:快速标记
|
||||||
|
// todo: refactor
|
||||||
const blocks = core.getMapBlocksObj();
|
const blocks = core.getMapBlocksObj();
|
||||||
const block = blocks[`${mx},${my}`];
|
const block = blocks[`${mx},${my}`];
|
||||||
if (block.event.cls.startsWith('enemy')) {
|
|
||||||
const name = core.material.enemys[block.event.id].name;
|
|
||||||
if (mota.plugin.mark.hasMarkedEnemy(block.event.id)) {
|
|
||||||
mota.plugin.utils.tip(
|
|
||||||
'success',
|
|
||||||
`已取消标记${name}!`
|
|
||||||
);
|
|
||||||
mota.plugin.mark.unmarkEnemy(block.event.id);
|
|
||||||
} else {
|
|
||||||
mota.plugin.utils.tip('success', `已标记${name}!`);
|
|
||||||
mota.plugin.mark.checkMarkedEnemy(block.event.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 78: // N:重新开始
|
case 78: // N:重新开始
|
||||||
core.confirmRestart();
|
core.confirmRestart();
|
||||||
|
@ -17,7 +17,6 @@ interface AncTePlugin {
|
|||||||
animate: ReturnType<typeof import('../plugin/animateController').default>;
|
animate: ReturnType<typeof import('../plugin/animateController').default>;
|
||||||
utils: ReturnType<typeof import('../plugin/utils').default>;
|
utils: ReturnType<typeof import('../plugin/utils').default>;
|
||||||
status: ReturnType<typeof import('../plugin/ui/statusBar').default>;
|
status: ReturnType<typeof import('../plugin/ui/statusBar').default>;
|
||||||
mark: ReturnType<typeof import('../plugin/mark').default>;
|
|
||||||
fly: ReturnType<typeof import('../plugin/ui/fly').default>;
|
fly: ReturnType<typeof import('../plugin/ui/fly').default>;
|
||||||
chase: ReturnType<typeof import('../plugin/chase/chase').default>;
|
chase: ReturnType<typeof import('../plugin/chase/chase').default>;
|
||||||
webglUtils: ReturnType<typeof import('../plugin/webgl/utils').default>;
|
webglUtils: ReturnType<typeof import('../plugin/webgl/utils').default>;
|
||||||
|
@ -267,21 +267,9 @@ hotkey
|
|||||||
.register('mark', '标记怪物', {
|
.register('mark', '标记怪物', {
|
||||||
defaults: KeyCode.KeyM,
|
defaults: KeyCode.KeyM,
|
||||||
func: () => {
|
func: () => {
|
||||||
|
// todo: refactor
|
||||||
const [x, y] = flags.mouseLoc ?? [];
|
const [x, y] = flags.mouseLoc ?? [];
|
||||||
const [mx, my] = getLocFromMouseLoc(x, y);
|
const [mx, my] = getLocFromMouseLoc(x, y);
|
||||||
const blocks = core.getMapBlocksObj();
|
|
||||||
const block = blocks[`${mx},${my}`];
|
|
||||||
if (block.event.cls.startsWith('enemy')) {
|
|
||||||
const id = block.event.id as EnemyIds;
|
|
||||||
const name = core.material.enemys[id].name;
|
|
||||||
if (mota.plugin.mark.hasMarkedEnemy(id)) {
|
|
||||||
tip('success', `已取消标记${name}!`);
|
|
||||||
mota.plugin.mark.unmarkEnemy(id);
|
|
||||||
} else {
|
|
||||||
tip('success', `已标记${name}!`);
|
|
||||||
mota.plugin.mark.checkMarkedEnemy(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.register('skillTree', '技能树', {
|
.register('skillTree', '技能树', {
|
||||||
|
@ -6,6 +6,8 @@ export interface GameEvent extends EmitableEvent {
|
|||||||
reset: () => void;
|
reset: () => void;
|
||||||
/** Emitted in src/App.vue setup. */
|
/** Emitted in src/App.vue setup. */
|
||||||
mounted: () => void;
|
mounted: () => void;
|
||||||
|
/** Emitted in plugin/ui.js */
|
||||||
|
statusBarUpdate: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const hook = new EventEmitter<GameEvent>();
|
export const hook = new EventEmitter<GameEvent>();
|
||||||
@ -50,7 +52,7 @@ class GameListener extends EventEmitter<ListenerEvent> {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
// hover & leave
|
// hover & leave & mouseMove
|
||||||
data.addEventListener('mousemove', e => {
|
data.addEventListener('mousemove', e => {
|
||||||
if (core.status.lockControl || !core.isPlaying()) return;
|
if (core.status.lockControl || !core.isPlaying()) return;
|
||||||
this.emit('mouseMove', e);
|
this.emit('mouseMove', e);
|
||||||
|
@ -4,7 +4,6 @@ import use from '@/plugin/use';
|
|||||||
import animate from '@/plugin/animateController';
|
import animate from '@/plugin/animateController';
|
||||||
import utils from '@/plugin/utils';
|
import utils from '@/plugin/utils';
|
||||||
import status from '@/plugin/ui/statusBar';
|
import status from '@/plugin/ui/statusBar';
|
||||||
import mark from '@/plugin/mark';
|
|
||||||
import fly from '@/plugin/ui/fly';
|
import fly from '@/plugin/ui/fly';
|
||||||
import chase from '@/plugin/chase/chase';
|
import chase from '@/plugin/chase/chase';
|
||||||
import webglUtils from '@/plugin/webgl/utils';
|
import webglUtils from '@/plugin/webgl/utils';
|
||||||
@ -27,7 +26,6 @@ export function resolvePlugin() {
|
|||||||
['animate', animate()],
|
['animate', animate()],
|
||||||
['utils', utils()],
|
['utils', utils()],
|
||||||
['status', status()],
|
['status', status()],
|
||||||
['mark', mark()],
|
|
||||||
['fly', fly()],
|
['fly', fly()],
|
||||||
['chase', chase()],
|
['chase', chase()],
|
||||||
['webglUtils', webglUtils()],
|
['webglUtils', webglUtils()],
|
||||||
|
@ -29,15 +29,14 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import Scroll from '../components/scroll.vue';
|
import Scroll from '../components/scroll.vue';
|
||||||
import { hasMarkedEnemy, markEnemy, unmarkEnemy } from '../plugin/mark';
|
|
||||||
import { detailInfo } from '../plugin/ui/book';
|
import { detailInfo } from '../plugin/ui/book';
|
||||||
|
import { hasMarkedEnemy, markEnemy } from '@/plugin/mark';
|
||||||
|
|
||||||
const enemy = detailInfo.enemy!;
|
const enemy = detailInfo.enemy!;
|
||||||
const marked = ref(hasMarkedEnemy(enemy.enemy.id));
|
const marked = ref(hasMarkedEnemy(enemy.enemy.id));
|
||||||
|
|
||||||
function mark() {
|
function mark() {
|
||||||
if (marked.value) unmarkEnemy(enemy.enemy.id);
|
markEnemy(enemy.enemy.id);
|
||||||
if (!marked.value) markEnemy(enemy.enemy.id);
|
|
||||||
marked.value = hasMarkedEnemy(enemy.enemy.id);
|
marked.value = hasMarkedEnemy(enemy.enemy.id);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -20,7 +20,6 @@ export {};
|
|||||||
if (main.replayChecking) return;
|
if (main.replayChecking) return;
|
||||||
mota.plugin.status.statusBarStatus.value =
|
mota.plugin.status.statusBarStatus.value =
|
||||||
!mota.plugin.status.statusBarStatus.value;
|
!mota.plugin.status.statusBarStatus.value;
|
||||||
mota.plugin.mark.checkMarkedEnemy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.prototype.drawBook = function () {
|
ui.prototype.drawBook = function () {
|
||||||
@ -49,6 +48,7 @@ export {};
|
|||||||
core.control.noAutoEvents = true;
|
core.control.noAutoEvents = true;
|
||||||
// 更新vue状态栏
|
// 更新vue状态栏
|
||||||
updateVueStatusBar();
|
updateVueStatusBar();
|
||||||
|
mota.game.hook.emit('statusBarUpdate');
|
||||||
};
|
};
|
||||||
|
|
||||||
// todo: 多个状态栏分离与控制
|
// todo: 多个状态栏分离与控制
|
||||||
|
@ -1,156 +1,159 @@
|
|||||||
import { reactive, ref } from 'vue';
|
import { fixedUi } from '@/core/main/init/ui';
|
||||||
import { tip } from './utils';
|
|
||||||
import type { DamageEnemy } from './game/enemy/damage';
|
import type { DamageEnemy } from './game/enemy/damage';
|
||||||
|
import { tip } from './utils';
|
||||||
|
import { ref, Ref } from 'vue';
|
||||||
|
import { hook } from '@/core/main/game';
|
||||||
|
|
||||||
export const showMarkedEnemy = ref(false);
|
export interface MarkInfo<T extends EnemyIds> {
|
||||||
|
id: T;
|
||||||
const markedEnemy = reactive<EnemyIds[]>([]);
|
enemy: DamageEnemy<T>;
|
||||||
|
/**
|
||||||
interface MarkInfo {
|
* 提示模式,从低到高位数分别为:
|
||||||
enemy: DamageEnemy;
|
* 1. 踩临界时
|
||||||
nextCritical: number;
|
* 2. 能打过怪物时
|
||||||
|
* 3. 小于勇士生命值的2/3时
|
||||||
|
* 4. 小于勇士生命值的1/3时
|
||||||
|
* 5. 零伤时
|
||||||
|
* 6. 小于指定伤害时
|
||||||
|
*/
|
||||||
|
mode: number;
|
||||||
|
/** 当前提示状态,提示模式的 2-6 */
|
||||||
|
status: number;
|
||||||
|
lastAtk: number;
|
||||||
|
lastDamage: number;
|
||||||
|
markDamage?: number;
|
||||||
|
/** 数据更新用,取反更新标记信息 */
|
||||||
|
update: Ref<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const markInfo: Partial<Record<EnemyIds, MarkInfo>> = {};
|
const uiMap = new Map<EnemyIds, number>();
|
||||||
const criticalReached: Partial<Record<EnemyIds, Record<number, boolean>>> = {};
|
const marked: MarkInfo<EnemyIds>[] = [];
|
||||||
const enemyDamageInfo: Partial<Record<EnemyIds, Record<number, boolean>>> = {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标记一个怪物,标记后的怪物会在勇士刚好能打过怪物时、伤害刚好小于勇士生命值的2/3和1/3时、踩到临界时提示
|
* 标记一个怪物,标记后的怪物会在勇士刚好能打过怪物时、伤害刚好小于勇士生命值的2/3和1/3时、踩到临界时提示
|
||||||
* @param id 标记的怪物id
|
* @param id 标记的怪物id
|
||||||
*/
|
*/
|
||||||
export function markEnemy(id: EnemyIds) {
|
export function markEnemy(id: EnemyIds) {
|
||||||
const { Enemy } = core.plugin.damage;
|
|
||||||
if (hasMarkedEnemy(id)) return;
|
if (hasMarkedEnemy(id)) return;
|
||||||
markedEnemy.push(id);
|
const { Enemy } = core.plugin.damage;
|
||||||
const enemy = new Enemy(core.material.enemys[id]);
|
const enemy = new Enemy(core.material.enemys[id]);
|
||||||
enemy.calAttribute();
|
enemy.calAttribute();
|
||||||
enemy.getRealInfo();
|
enemy.getRealInfo();
|
||||||
markInfo[id] = {
|
|
||||||
nextCritical:
|
const info: MarkInfo<EnemyIds> = {
|
||||||
enemy.calCritical(1)[0]?.atkDelta ?? 0 + core.status.hero.atk,
|
id,
|
||||||
enemy
|
enemy,
|
||||||
|
mode: 0b011111,
|
||||||
|
lastAtk: core.plugin.hero.getHeroStatusOn('atk', 'empty'),
|
||||||
|
lastDamage: enemy.calDamage().damage,
|
||||||
|
status: 0b0,
|
||||||
|
update: ref(true)
|
||||||
};
|
};
|
||||||
criticalReached[id] = { 0: true };
|
marked.push(info);
|
||||||
enemyDamageInfo[id] = { 1: false, 2: false, 3: false };
|
|
||||||
getMarkInfo(id, true);
|
uiMap.set(id, fixedUi.open('markedEnemy', { enemy: info }));
|
||||||
checkMarkedEnemy(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否标记过某个怪物
|
|
||||||
*/
|
|
||||||
export function hasMarkedEnemy(id: EnemyIds) {
|
|
||||||
return markedEnemy.includes(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取消标记某个怪物
|
|
||||||
*/
|
|
||||||
export function unmarkEnemy(id: EnemyIds) {
|
export function unmarkEnemy(id: EnemyIds) {
|
||||||
const index = markedEnemy.indexOf(id);
|
fixedUi.close(uiMap.get(id) ?? -1);
|
||||||
if (index === -1) return;
|
uiMap.delete(id);
|
||||||
markedEnemy.splice(index, 1);
|
const index = marked.findIndex(v => v.id === id);
|
||||||
checkMarkedEnemy();
|
marked.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function unmarkAll() {
|
export function checkMarkedEnemy() {
|
||||||
markedEnemy.splice(0);
|
marked.forEach(v => {
|
||||||
checkMarkedEnemy();
|
const { id, enemy, mode, lastAtk, lastDamage, markDamage } = v;
|
||||||
}
|
const atk = core.plugin.hero.getHeroStatusOn('atk', 'empty');
|
||||||
|
let tip = 0;
|
||||||
/**
|
if (mode & 0b11110) {
|
||||||
* 获得所有被标记的怪物
|
|
||||||
*/
|
|
||||||
export function getMarkedEnemy() {
|
|
||||||
return markedEnemy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取怪物的临界信息
|
|
||||||
* @param id 怪物id
|
|
||||||
*/
|
|
||||||
export function getMarkInfo(id: EnemyIds, noMessage: boolean = false) {
|
|
||||||
const reached = criticalReached[id]!;
|
|
||||||
const info = markInfo[id]!;
|
|
||||||
if (core.status.hero.atk >= info.nextCritical) {
|
|
||||||
if (!reached[info.nextCritical] && !noMessage) {
|
|
||||||
tip('success', `踩到了${core.material.enemys[id].name}的临界!`);
|
|
||||||
}
|
|
||||||
reached[info.nextCritical] = true;
|
|
||||||
const n = info.enemy.calCritical(1)[0]?.atkDelta;
|
|
||||||
const next = (n ?? 0) + core.status.hero.atk;
|
|
||||||
info.nextCritical = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查被标记怪物的状态
|
|
||||||
*/
|
|
||||||
export function checkMarkedEnemy(noMessage: boolean = false) {
|
|
||||||
checkMarkedStatus.value = !checkMarkedStatus.value;
|
|
||||||
const hp = core.status.hero.hp;
|
|
||||||
getMarkedEnemy().forEach(v => {
|
|
||||||
getMarkInfo(v);
|
|
||||||
const { enemy } = markInfo[v]!;
|
|
||||||
const damage = enemy.calDamage().damage;
|
const damage = enemy.calDamage().damage;
|
||||||
if (!isFinite(damage)) return;
|
const hp = core.status.hero.hp;
|
||||||
const info = enemyDamageInfo[v]!;
|
v.lastDamage = damage;
|
||||||
const name = core.material.enemys[v].name;
|
if (damage > lastDamage) return;
|
||||||
let res = 0;
|
// 重置标记状态
|
||||||
if (damage <= 0) {
|
if (damage > hp) {
|
||||||
if (!noMessage) tip('success', `${name}已经零伤了!`);
|
v.status &= 0b100001;
|
||||||
} else if (damage < hp / 3) {
|
|
||||||
if (!info[3] && !noMessage) {
|
|
||||||
tip('success', `${name}的伤害已降至勇士生命值的1/3!`);
|
|
||||||
}
|
}
|
||||||
res = 0b111;
|
if (damage > (markDamage ?? Infinity)) {
|
||||||
} else if (damage < (hp / 3) * 2) {
|
v.status &= 0b1;
|
||||||
if (!info[2] && !noMessage) {
|
|
||||||
tip('success', `${name}的伤害已降至勇士生命值的2/3!`);
|
|
||||||
}
|
}
|
||||||
res = 0b110;
|
// 能打过怪物提示、2/3提示、1/3提示、零伤提示、指定伤害提示
|
||||||
} else if (damage < hp) {
|
if (mode & (1 << 1) && damage < hp && damage > (hp * 2) / 3) {
|
||||||
if (!info[1] && !noMessage) {
|
if (!(v.status & (1 << 1))) {
|
||||||
tip('success', `你已经能打过${name}了!`);
|
v.status &= 0b100001;
|
||||||
|
v.status |= 1 << 1;
|
||||||
|
tip |= 1 << 1;
|
||||||
}
|
}
|
||||||
res = 0b100;
|
} else if (mode & (1 << 2) && damage > hp / 3) {
|
||||||
|
if (!(v.status & (1 << 2))) {
|
||||||
|
v.status &= 0b100011;
|
||||||
|
v.status |= 1 << 2;
|
||||||
|
tip |= 1 << 2;
|
||||||
}
|
}
|
||||||
info[1] = info[2] = info[3] = false;
|
} else if (mode & (1 << 3) && damage > 0) {
|
||||||
if (res & 0b100) {
|
if (!(v.status & (1 << 3))) {
|
||||||
info[1] = true;
|
v.status &= 0b100111;
|
||||||
|
v.status |= 1 << 3;
|
||||||
|
tip |= 1 << 3;
|
||||||
}
|
}
|
||||||
if (res & 0b010) {
|
} else if (mode & (1 << 4)) {
|
||||||
info[2] = true;
|
if (!(v.status & (1 << 4))) {
|
||||||
|
v.status &= 0b101111;
|
||||||
|
v.status |= 1 << 4;
|
||||||
|
tip |= 1 << 4;
|
||||||
}
|
}
|
||||||
if (res & 0b001) {
|
|
||||||
info[3] = true;
|
|
||||||
}
|
}
|
||||||
|
if (mode & (1 << 5) && damage < (markDamage ?? Infinity)) {
|
||||||
|
if (!(v.status & (1 << 5))) {
|
||||||
|
if (damage < (markDamage ?? Infinity)) {
|
||||||
|
v.status |= 1 << 5;
|
||||||
|
} else {
|
||||||
|
v.status &= 0b011111;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 临界提示
|
||||||
|
if (mode & (1 << 0)) {
|
||||||
|
const critical = enemy.calCritical(1)[0]?.atkDelta ?? Infinity;
|
||||||
|
v.lastAtk = atk + critical;
|
||||||
|
if (critical + atk > lastAtk) {
|
||||||
|
tip |= 1 << 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
makeTip(id, tip, v);
|
||||||
|
v.update.value = !v.update.value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const checkMarkedStatus = ref(false);
|
function makeTip(enemy: EnemyIds, mode: number, info: MarkInfo<EnemyIds>) {
|
||||||
|
const name = core.material.enemys[enemy].name;
|
||||||
export default function init() {
|
if (mode & (1 << 0)) {
|
||||||
// 鼠标移动时进行监听,按下M时进行快速标记
|
tip('success', `已踩到 ${name} 的临界!`);
|
||||||
core.registerAction(
|
}
|
||||||
'onmove',
|
if (mode & (1 << 1)) {
|
||||||
'mark',
|
tip('success', `已能打过 ${name}!`);
|
||||||
(x, y) => {
|
}
|
||||||
if (core.isPlaying()) {
|
if (mode & (1 << 2)) {
|
||||||
flags.mouseLoc = [x, y];
|
tip('success', `${name} 的伤害已降至 2/3!`);
|
||||||
|
}
|
||||||
|
if (mode & (1 << 3)) {
|
||||||
|
tip('success', `${name} 的伤害已降至 1/3!`);
|
||||||
|
}
|
||||||
|
if (mode & (1 << 4)) {
|
||||||
|
tip('success', `${name} 已零伤!`);
|
||||||
|
}
|
||||||
|
if (mode & (1 << 5)) {
|
||||||
|
const damage = core.formatBigNumber(info.markDamage ?? Infinity);
|
||||||
|
tip('success', `${name} 的伤害已降至 ${damage}!`);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
},
|
|
||||||
150
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
checkMarkedEnemy,
|
|
||||||
checkStatus: checkMarkedStatus,
|
|
||||||
markEnemy,
|
|
||||||
hasMarkedEnemy,
|
|
||||||
unmarkEnemy,
|
|
||||||
showMarkedEnemy,
|
|
||||||
unmarkAll
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function hasMarkedEnemy(id: EnemyIds) {
|
||||||
|
return marked.some(v => v.id === id);
|
||||||
|
}
|
||||||
|
|
||||||
|
hook.on('statusBarUpdate', () => {
|
||||||
|
checkMarkedEnemy();
|
||||||
|
});
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.antdv-message {
|
.antdv-message {
|
||||||
|
24
src/types/plugin.d.ts
vendored
24
src/types/plugin.d.ts
vendored
@ -48,9 +48,6 @@ interface PluginDeclaration
|
|||||||
/** 状态栏信息,取反后刷新状态栏 */
|
/** 状态栏信息,取反后刷新状态栏 */
|
||||||
readonly statusBarStatus: Ref<boolean>;
|
readonly statusBarStatus: Ref<boolean>;
|
||||||
|
|
||||||
/** 检查标记的怪物,取反后更新显示信息 */
|
|
||||||
readonly checkMarkedStatus: Ref<boolean>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加一个动画
|
* 添加一个动画
|
||||||
* @param fn 要添加的函数
|
* @param fn 要添加的函数
|
||||||
@ -63,27 +60,6 @@ interface PluginDeclaration
|
|||||||
*/
|
*/
|
||||||
removeAnimate(fn: (time: number) => void);
|
removeAnimate(fn: (time: number) => void);
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查被标记怪物的状态
|
|
||||||
*/
|
|
||||||
checkMarkedEnemy(): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 标记怪物
|
|
||||||
* @param id 怪物id
|
|
||||||
*/
|
|
||||||
markEnemy(id: EnemyIds): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否标记过某个怪物
|
|
||||||
*/
|
|
||||||
hasMarkedEnemy(id: EnemyIds): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取消标记过某个怪物
|
|
||||||
*/
|
|
||||||
unmarkEnemy(id: EnemyIds): void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判定一个值是否不是undefined或null
|
* 判定一个值是否不是undefined或null
|
||||||
* @param value 要判断的值
|
* @param value 要判断的值
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="marked-enemy">
|
<div id="marked-enemy">
|
||||||
<div v-for="v of all">
|
|
||||||
<Box
|
<Box
|
||||||
:key="v"
|
v-model:left="boxPos.left"
|
||||||
v-if="!getBoxPos(v).hidden"
|
v-model:top="boxPos.top"
|
||||||
v-model:left="getBoxPos(v).left"
|
v-model:width="boxPos.width"
|
||||||
v-model:top="getBoxPos(v).top"
|
v-model:height="boxPos.height"
|
||||||
v-model:width="getBoxPos(v).width"
|
|
||||||
v-model:height="getBoxPos(v).height"
|
|
||||||
:resizable="true"
|
:resizable="true"
|
||||||
:dragable="true"
|
:dragable="true"
|
||||||
>
|
>
|
||||||
@ -15,35 +12,35 @@
|
|||||||
<div class="marked-main">
|
<div class="marked-main">
|
||||||
<div class="marked-info">
|
<div class="marked-info">
|
||||||
<BoxAnimate
|
<BoxAnimate
|
||||||
:id="v"
|
:id="enemy.id"
|
||||||
:width="24"
|
:width="24"
|
||||||
:height="24"
|
:height="24"
|
||||||
></BoxAnimate>
|
></BoxAnimate>
|
||||||
<span class="marked-name marked-item">{{
|
<span class="marked-name marked-item">{{
|
||||||
getName(v)
|
getName()
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="marked-damage marked-item"
|
<span class="marked-damage marked-item"
|
||||||
>伤害:{{ getDamage(v) }}</span
|
>伤害:{{ format(info.damage) }}</span
|
||||||
>
|
>
|
||||||
<span class="marked-critical marked-item"
|
<span class="marked-critical marked-item"
|
||||||
>临界:{{ getCritical(v)[0] }}</span
|
>临界:{{ format(info.critical) }}</span
|
||||||
>
|
>
|
||||||
<span class="marked-critical-damage marked-item"
|
<span class="marked-critical-damage marked-item"
|
||||||
>减伤:{{ getCritical(v)[1] }}</span
|
>减伤:{{ format(info.criticalDam) }}</span
|
||||||
>
|
>
|
||||||
<span class="marked-def marked-item"
|
<span class="marked-def marked-item"
|
||||||
>{{ ratio }}防:{{ getDefDamage(v) }}</span
|
>{{ ratio }}防:{{ format(info.defDamage) }}</span
|
||||||
>
|
>
|
||||||
<div class="marked-button">
|
<div class="marked-button">
|
||||||
<span
|
<span
|
||||||
class="marked-hide button-text"
|
class="marked-hide button-text"
|
||||||
@click.stop="getBoxPos(v).hidden = true"
|
@click.stop="hidden = true"
|
||||||
>隐藏盒子</span
|
>隐藏盒子</span
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="marked-cancel button-text"
|
class="marked-cancel button-text"
|
||||||
@click.stop="unmarkEnemy(v)"
|
@click.stop="unmarkEnemy(enemy.id)"
|
||||||
>取消标记</span
|
>取消标记</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@ -51,72 +48,71 @@
|
|||||||
>
|
>
|
||||||
</Box>
|
</Box>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive, ref, watch } from 'vue';
|
import { reactive, ref, watch } from 'vue';
|
||||||
import {
|
import { MarkInfo, unmarkEnemy } from '../plugin/mark';
|
||||||
checkMarkedStatus,
|
|
||||||
getMarkedEnemy,
|
|
||||||
markInfo,
|
|
||||||
unmarkEnemy
|
|
||||||
} from '../plugin/mark';
|
|
||||||
import { has } from '../plugin/utils';
|
|
||||||
import Box from '../components/box.vue';
|
import Box from '../components/box.vue';
|
||||||
import Scroll from '../components/scroll.vue';
|
import Scroll from '../components/scroll.vue';
|
||||||
import BoxAnimate from '../components/boxAnimate.vue';
|
import BoxAnimate from '../components/boxAnimate.vue';
|
||||||
|
import { GameUi } from '@/core/main/custom/ui';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
num: number;
|
||||||
|
ui: GameUi;
|
||||||
|
enemy: MarkInfo<EnemyIds>;
|
||||||
|
}>();
|
||||||
|
|
||||||
interface BoxPos {
|
interface BoxPos {
|
||||||
left: number;
|
left: number;
|
||||||
top: number;
|
top: number;
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
hidden: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface MarkedEnemy {
|
||||||
|
damage: number;
|
||||||
|
critical: number;
|
||||||
|
criticalDam: number;
|
||||||
|
defDamage: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const enemy = props.enemy;
|
||||||
const ratio = core.status.thisMap?.ratio ?? 1;
|
const ratio = core.status.thisMap?.ratio ?? 1;
|
||||||
|
|
||||||
let all = getMarkedEnemy();
|
const format = core.formatBigNumber;
|
||||||
|
|
||||||
watch(checkMarkedStatus, update);
|
const boxPos = reactive<BoxPos>({
|
||||||
|
|
||||||
const boxPos = reactive<Partial<Record<EnemyIds, BoxPos>>>({});
|
|
||||||
|
|
||||||
function update() {
|
|
||||||
all.push(...all.splice(0, all.length));
|
|
||||||
for (const id in boxPos) {
|
|
||||||
if (!all.includes(id as EnemyIds)) delete boxPos[id as EnemyIds];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBoxPos(id: EnemyIds) {
|
|
||||||
if (has(boxPos[id])) return boxPos[id]!;
|
|
||||||
boxPos[id] = {
|
|
||||||
left: window.innerWidth - 300,
|
left: window.innerWidth - 300,
|
||||||
top: 100,
|
top: 100,
|
||||||
width: 200,
|
width: 200,
|
||||||
height: 150,
|
height: 150
|
||||||
hidden: false
|
});
|
||||||
};
|
const info = reactive<MarkedEnemy>({
|
||||||
return boxPos[id]!;
|
damage: 0,
|
||||||
|
critical: 0,
|
||||||
|
criticalDam: 0,
|
||||||
|
defDamage: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
const hidden = ref(false);
|
||||||
|
|
||||||
|
watch(hidden, n => {
|
||||||
|
if (n) mota.ui.fixed.close(props.num);
|
||||||
|
});
|
||||||
|
watch(enemy.update, update);
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
info.damage = enemy.enemy.calDamage().damage;
|
||||||
|
const critical = enemy.enemy.calCritical()[0];
|
||||||
|
info.critical = critical?.atkDelta ?? 0;
|
||||||
|
info.criticalDam = critical.delta ?? 0;
|
||||||
|
info.defDamage = enemy.enemy.calDefDamage(ratio).delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getName(id: EnemyIds) {
|
function getName() {
|
||||||
return core.material.enemys[id].name;
|
return enemy.enemy.enemy.name;
|
||||||
}
|
|
||||||
|
|
||||||
function getDamage(id: EnemyIds) {
|
|
||||||
return core.formatBigNumber(markInfo[id]!.enemy.calDamage().damage);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCritical(id: EnemyIds) {
|
|
||||||
const { delta, atkDelta } = markInfo[id]!.enemy.calCritical(1)[0];
|
|
||||||
return [-delta, atkDelta];
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDefDamage(id: EnemyIds) {
|
|
||||||
return core.formatBigNumber(markInfo[id]!.enemy.calDefDamage(ratio).delta);
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user