HumanBreak/src/plugin/mark.ts
2023-07-28 12:17:20 +08:00

154 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { reactive, ref } from 'vue';
import { tip } from './utils';
export const showMarkedEnemy = ref(false);
const markedEnemy = reactive<EnemyIds[]>([]);
interface MarkInfo {
nextCritical: number;
}
const markInfo: Partial<Record<EnemyIds, MarkInfo>> = {};
const criticalReached: Partial<Record<EnemyIds, Record<number, boolean>>> = {};
const enemyDamageInfo: Partial<Record<EnemyIds, Record<number, boolean>>> = {};
/**
* 标记一个怪物标记后的怪物会在勇士刚好能打过怪物时、伤害刚好小于勇士生命值的2/3和1/3时、踩到临界时提示
* @param id 标记的怪物id
*/
export function markEnemy(id: EnemyIds) {
// todo: 不使用 nextCriticals
if (hasMarkedEnemy(id)) return;
markedEnemy.push(id);
markInfo[id] = {
nextCritical:
core.nextCriticals(id, 1)[0]?.[0] ?? 0 + core.status.hero.atk
};
criticalReached[id] = { 0: true };
enemyDamageInfo[id] = { 1: false, 2: false, 3: false };
getMarkInfo(id, true);
checkMarkedEnemy(true);
}
/**
* 是否标记过某个怪物
*/
export function hasMarkedEnemy(id: EnemyIds) {
return markedEnemy.includes(id);
}
/**
* 取消标记某个怪物
*/
export function unmarkEnemy(id: EnemyIds) {
const index = markedEnemy.indexOf(id);
if (index === -1) return;
markedEnemy.splice(index, 1);
checkMarkedEnemy();
}
export function unmarkAll() {
markedEnemy.splice(0);
checkMarkedEnemy();
}
/**
* 获得所有被标记的怪物
*/
export function getMarkedEnemy() {
return markedEnemy;
}
/**
* 获取怪物的临界信息
* @param id 怪物id
*/
export function getMarkInfo(id: EnemyIds, noMessage: boolean = false) {
// todo: 不使用 nextCriticals
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 = core.nextCriticals(id, 1, void 0, void 0, 'empty')[0]?.[0];
const next = (n ?? 0) + core.status.hero.atk;
info.nextCritical = next;
}
}
/**
* 检查被标记怪物的状态
*/
export function checkMarkedEnemy(noMessage: boolean = false) {
// todo: 删除 getDamageInfo
checkMarkedStatus.value = !checkMarkedStatus.value;
const hp = core.status.hero.hp;
getMarkedEnemy().forEach(v => {
getMarkInfo(v);
const damage =
core.getDamageInfo(v, void 0, void 0, void 0, 'empty')?.damage ??
-1;
if (damage === -1) return;
const info = enemyDamageInfo[v]!;
const name = core.material.enemys[v].name;
let res = 0;
if (damage <= 0) {
if (!noMessage) tip('success', `${name}已经零伤了!`);
} else if (damage < hp / 3) {
if (!info[3] && !noMessage) {
tip('success', `${name}的伤害已降至勇士生命值的1/3`);
}
res = 0b111;
} else if (damage < (hp / 3) * 2) {
if (!info[2] && !noMessage) {
tip('success', `${name}的伤害已降至勇士生命值的2/3`);
}
res = 0b110;
} else if (damage < hp) {
if (!info[1] && !noMessage) {
tip('success', `你已经能打过${name}了!`);
}
res = 0b100;
}
info[1] = info[2] = info[3] = false;
if (res & 0b100) {
info[1] = true;
}
if (res & 0b010) {
info[2] = true;
}
if (res & 0b001) {
info[3] = true;
}
});
}
export const checkMarkedStatus = ref(false);
export default function init() {
// 鼠标移动时进行监听按下M时进行快速标记
core.registerAction(
'onmove',
'mark',
(x, y) => {
if (core.isPlaying()) {
flags.mouseLoc = [x, y];
}
return false;
},
150
);
return {
checkMarkedEnemy,
checkStatus: checkMarkedStatus,
markEnemy,
hasMarkedEnemy,
unmarkEnemy,
showMarkedEnemy,
unmarkAll
};
}