mirror of
https://github.com/unanmed/HumanBreak.git
synced 2026-11-15 19:34:32 +08:00
重构怪物属性定义
This commit is contained in:
1 parent
93fad2f637
commit
9bab089a14
18 files changed
+250
-610
No files matched your search
@@ -326,6 +326,8 @@ function handleScreenSetting<T extends number | boolean>(
|
||||
// 字体大小
|
||||
core.setLocalStorage('fontSize', n);
|
||||
root.style.fontSize = root2.style.fontSize = `${n}px`;
|
||||
} else if (key === 'smoothView') {
|
||||
core.setLocalStorage('smoothView', n);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,6 +372,7 @@ mainSetting
|
||||
.register('antiAlias', '抗锯齿', false)
|
||||
.register('autoScale', '自动放缩', true)
|
||||
.register('fontSize', '字体大小', 16, [8, 28, 1])
|
||||
.register('smoothView', '平滑镜头', true)
|
||||
)
|
||||
.register(
|
||||
'action',
|
||||
@@ -397,6 +400,7 @@ loading.once('coreInit', () => {
|
||||
'screen.antiAlias': !!core.getLocalStorage('antiAlias', false),
|
||||
'screen.autoScale': !!core.getLocalStorage('autoScale', true),
|
||||
'screen.fontSize': core.getLocalStorage('fontSize', 16),
|
||||
'screen.smoothView': !!core.getLocalStorage('smoothView', true),
|
||||
'action.fixed': !!core.getLocalStorage('fixed', true),
|
||||
'utils.betterLoad': !!core.getLocalStorage('betterLoad', true)
|
||||
});
|
||||
|
||||
@@ -75,7 +75,7 @@ export {};
|
||||
const fns = before[mod];
|
||||
for (const id in fns) {
|
||||
const fn = fns[id];
|
||||
if (typeof fn !== 'function' || id === 'hasSpecial') continue;
|
||||
if (typeof fn !== 'function') continue;
|
||||
const now = after[mod][id];
|
||||
if (fn.toString() !== now.toString()) {
|
||||
try {
|
||||
|
||||
@@ -96,7 +96,7 @@ core.events.afterBattle = function (
|
||||
core.status.hero.statistics.battle++;
|
||||
|
||||
// 智慧之源
|
||||
if (core.hasSpecial(special, 14) && flags.hard === 2) {
|
||||
if (special.includes(14) && flags.hard === 2) {
|
||||
core.addFlag(
|
||||
'inte_' + floorId,
|
||||
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10
|
||||
@@ -106,11 +106,11 @@ core.events.afterBattle = function (
|
||||
}
|
||||
|
||||
// 极昼永夜
|
||||
if (core.hasSpecial(special, 22)) {
|
||||
if (special.includes(22)) {
|
||||
flags[`night_${floorId}`] ??= 0;
|
||||
flags[`night_${floorId}`] -= enemy.enemy.night!;
|
||||
}
|
||||
if (core.hasSpecial(special, 23)) {
|
||||
if (special.includes(23)) {
|
||||
flags[`night_${floorId}`] ??= 0;
|
||||
flags[`night_${floorId}`] += enemy.enemy.day;
|
||||
}
|
||||
@@ -120,7 +120,7 @@ core.events.afterBattle = function (
|
||||
// }
|
||||
|
||||
// 如果是融化怪,需要特殊标记一下
|
||||
if (core.hasSpecial(special, 25) && core.has(x) && core.has(y)) {
|
||||
if (special.includes(25) && core.has(x) && core.has(y)) {
|
||||
flags[`melt_${floorId}`] ??= {};
|
||||
flags[`melt_${floorId}`][`${x},${y}`] = enemy.enemy.melt;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
///<reference path="../../../../src/types/core.d.ts" />
|
||||
|
||||
// todo: 优化,直接调用 floor.enemy.list 进行计算
|
||||
|
||||
/**
|
||||
* 检查漏怪
|
||||
* @param {FloorIds[]} floorIds
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
import { getHeroStatusOn } from '../hero';
|
||||
|
||||
export interface SpecialDeclaration {
|
||||
code: number;
|
||||
name: string | ((enemy: Enemy) => string);
|
||||
desc: string | ((enemy: Enemy) => string);
|
||||
color: string;
|
||||
}
|
||||
|
||||
export const enemySpecials: SpecialDeclaration[] = [
|
||||
{
|
||||
code: 0,
|
||||
name: '空',
|
||||
desc: '空',
|
||||
color: '#fff'
|
||||
},
|
||||
{
|
||||
code: 1,
|
||||
name: '致命一击',
|
||||
desc: enemy => `怪物每5回合触发一次强力攻击,造成${enemy.crit}%的伤害`,
|
||||
color: '#fc3'
|
||||
},
|
||||
{
|
||||
code: 2,
|
||||
name: '恶毒',
|
||||
desc: '怪物攻击无视勇士的防御',
|
||||
color: '#bbb0ff'
|
||||
},
|
||||
{
|
||||
code: 3,
|
||||
name: '坚固',
|
||||
desc: '怪物防御不小于勇士攻击-1',
|
||||
color: '#c0b088'
|
||||
},
|
||||
{
|
||||
code: 4,
|
||||
name: '2连击',
|
||||
desc: '怪物每回合攻击2次',
|
||||
color: '#fe7'
|
||||
},
|
||||
{
|
||||
code: 5,
|
||||
name: '3连击',
|
||||
desc: '怪物每回合攻击3次',
|
||||
color: '#fe7'
|
||||
},
|
||||
{
|
||||
code: 6,
|
||||
name: enemy => `${enemy.n}连击`,
|
||||
desc: enemy => `怪物每回合攻击${enemy.n}次`,
|
||||
color: '#fe7'
|
||||
},
|
||||
{
|
||||
code: 7,
|
||||
name: '饥渴',
|
||||
desc: enemy =>
|
||||
`战斗前,怪物降低勇士${enemy.hungry}%的攻击,并加在自己身上`,
|
||||
color: '#b67'
|
||||
},
|
||||
{
|
||||
code: 8,
|
||||
name: '抱团',
|
||||
desc: enemy =>
|
||||
`怪物周围5×5范围内每有一个拥有该属性的怪物,自身攻防就增加${enemy.together}%(线性叠加)`,
|
||||
color: '#fa4'
|
||||
},
|
||||
{
|
||||
code: 9,
|
||||
name: '绝对防御',
|
||||
desc: '怪物的奇特护甲可以让勇士的额外攻击失效,攻击变为基础攻击+额外攻击',
|
||||
color: '#80eed6'
|
||||
},
|
||||
{
|
||||
code: 10,
|
||||
name: '勇气之刃',
|
||||
desc: enemy => `怪物第一回合造成${enemy.courage}%的伤害`,
|
||||
color: '#b0c0dd'
|
||||
},
|
||||
{
|
||||
code: 11,
|
||||
name: '勇气冲锋',
|
||||
desc: enemy =>
|
||||
`怪物首先攻击,造成${enemy.charge}%的伤害,并眩晕勇士5回合`,
|
||||
color: '#ff00d2'
|
||||
},
|
||||
{
|
||||
code: 12,
|
||||
name: '追猎',
|
||||
desc: '当勇士移动到该怪物的水平或竖直方向上时,怪物向勇士移动一格',
|
||||
color: '#9e8'
|
||||
},
|
||||
{
|
||||
code: 13,
|
||||
name: '魔攻',
|
||||
desc: '怪物攻击无视勇士的防御',
|
||||
color: '#bbb0ff'
|
||||
},
|
||||
{
|
||||
code: 14,
|
||||
name: '智慧之源',
|
||||
desc: '困难难度下(简单难度没有效果),战斗后,怪物会吸取勇士30%的智慧(勇士智慧向下取整至整十)加在本层的拥有该属性的怪物攻击上',
|
||||
color: '#bbeef0'
|
||||
},
|
||||
{
|
||||
code: 15,
|
||||
name: '突刺',
|
||||
desc: enemy =>
|
||||
`勇士走到怪物怪物周围四格时,怪物对勇士造成${core.formatBigNumber(
|
||||
Math.max((enemy.value || 0) - getHeroStatusOn('def'))
|
||||
)}点伤害`,
|
||||
color: '#c677dd'
|
||||
},
|
||||
{
|
||||
code: 16,
|
||||
name: '空',
|
||||
desc: '空',
|
||||
color: '#fff'
|
||||
},
|
||||
{
|
||||
code: 17,
|
||||
name: '先攻',
|
||||
desc: '战斗时,怪物首先攻击',
|
||||
color: '#b0b666'
|
||||
},
|
||||
{
|
||||
code: 18,
|
||||
name: '阻击',
|
||||
desc: enemy =>
|
||||
`经过怪物十字范围内时怪物后退一格,同时对勇士造成${enemy.value}点伤害`,
|
||||
color: '#8888e6'
|
||||
},
|
||||
{
|
||||
code: 19,
|
||||
name: '电摇嘲讽',
|
||||
desc:
|
||||
'当勇士移动到怪物同行或同列时,勇士会直接冲向怪物,撞碎路上的所有地形和门,拾取路上的道具,与路上的怪物战斗' +
|
||||
',最后与该怪物战斗',
|
||||
color: '#ff6666'
|
||||
},
|
||||
{
|
||||
code: 20,
|
||||
name: '霜冻',
|
||||
desc: enemy =>
|
||||
`怪物寒冷的攻击使勇士动作变慢,勇士每回合对怪物造成的伤害减少${enemy.ice}%。装备杰克的衣服后可以免疫。`,
|
||||
color: 'cyan'
|
||||
},
|
||||
{
|
||||
code: 21,
|
||||
name: '冰封光环',
|
||||
desc: enemy =>
|
||||
`寒气逼人,使勇士对该怪物周围7*7范围内的怪物伤害减少${enemy.iceHalo}%(线性叠加)`,
|
||||
color: 'cyan'
|
||||
},
|
||||
{
|
||||
code: 22,
|
||||
name: '永夜',
|
||||
desc: enemy =>
|
||||
`战斗后,减少勇士${enemy.night}点攻防,增加本层所有怪物${enemy.night}点攻防,仅在本层有效`,
|
||||
color: '#d8a'
|
||||
},
|
||||
{
|
||||
code: 23,
|
||||
name: '极昼',
|
||||
desc: enemy =>
|
||||
`战斗后,减少本层所有怪物${enemy.day}点攻防,增加勇士${enemy.day}点攻防,仅在本层有效`,
|
||||
color: '#ffd'
|
||||
},
|
||||
{
|
||||
code: 24,
|
||||
name: '射击',
|
||||
desc: function () {
|
||||
return '经过怪物同行或同列的可视范围内时受到一次普通攻击的伤害';
|
||||
},
|
||||
color: '#dda0dd'
|
||||
},
|
||||
{
|
||||
code: 25,
|
||||
name: '融化',
|
||||
desc: enemy =>
|
||||
`战斗后该怪物会融化,在怪物位置产生一个3*3的范围光环,光环内怪物的攻防增加${enemy.melt}%`,
|
||||
color: '#e6e099'
|
||||
},
|
||||
{
|
||||
code: 26,
|
||||
name: '冰封之核',
|
||||
desc: enemy =>
|
||||
`怪物拥有逼人的寒气,使周围5*5范围内的怪物防御增加${enemy.iceCore}%`,
|
||||
color: '#70ffd1'
|
||||
},
|
||||
{
|
||||
code: 27,
|
||||
name: '火焰之核',
|
||||
desc: enemy =>
|
||||
`怪物拥有灼热的火焰,使周围5*5范围内的怪物攻击增加${enemy.fireCore}%`,
|
||||
color: '#ff6f0a'
|
||||
},
|
||||
{
|
||||
code: 28,
|
||||
name: '苍蓝刻',
|
||||
desc: enemy =>
|
||||
`怪物使用苍蓝之灵的力量,使自身受到的伤害减少${enemy.paleShield}%`,
|
||||
color: '#ff6f0a'
|
||||
}
|
||||
];
|
||||
|
||||
declare global {
|
||||
interface PluginDeclaration {
|
||||
special: SpecialDeclaration[];
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.special = enemySpecials;
|
||||
@@ -22,21 +22,6 @@ export function canStudySkill(number: number) {
|
||||
export function studySkill(enemy: any, number: number) {
|
||||
core.status.hero.special ??= { num: [], last: [] };
|
||||
const s = core.status.hero.special;
|
||||
const specials = core.getSpecials();
|
||||
let special = specials[number - 1][1];
|
||||
if (special instanceof Function) special = special(enemy);
|
||||
if (!canStudySkill(number)) {
|
||||
if (!main.replayChecking) {
|
||||
ancTe.plugin.utils.tip('error', `无法学习${special}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
s.num.push(number);
|
||||
s.last.push(core.plugin.skillTree.getSkillLevel(11) * 3 + 2);
|
||||
const value = values[number] ?? [];
|
||||
for (const key of value) {
|
||||
s[key] = enemy[key];
|
||||
}
|
||||
}
|
||||
|
||||
export function forgetStudiedSkill(num: number, i: number) {
|
||||
|
||||
+4
-13
@@ -56,15 +56,6 @@ export function getDetailedEnemy(
|
||||
enemy: DamageEnemy,
|
||||
floorId: FloorIds = core.status.floorId
|
||||
): ToShowEnemy {
|
||||
const specials = Object.fromEntries(
|
||||
core.getSpecials().map(v => {
|
||||
return [v[0], v.slice(1)];
|
||||
})
|
||||
) as Record<
|
||||
string,
|
||||
EnemySpecialDeclaration extends [number, ...infer F] ? F : never
|
||||
>;
|
||||
|
||||
const ratio = core.status.maps[floorId].ratio;
|
||||
|
||||
const dam = enemy.calDamage().damage;
|
||||
@@ -81,11 +72,11 @@ export function getDetailedEnemy(
|
||||
return typeof func === 'string' ? func : func(enemy);
|
||||
};
|
||||
const special: [string, string, string][] = enemy.enemy.special.map(vv => {
|
||||
const s = specials[vv];
|
||||
const s = core.plugin.special[vv];
|
||||
return [
|
||||
fromFunc(s[0], enemy.enemy),
|
||||
fromFunc(s[1], enemy.enemy),
|
||||
s[2] as string
|
||||
fromFunc(s.name, enemy.enemy),
|
||||
fromFunc(s.desc, enemy.enemy),
|
||||
s.color as string
|
||||
];
|
||||
});
|
||||
const l = isMobile ? 1 : 2;
|
||||
|
||||
Vendored
+1
-79
@@ -242,7 +242,7 @@ interface BookEnemyInfo extends Enemy, EnemyInfo {
|
||||
/**
|
||||
* 怪物模块
|
||||
*/
|
||||
interface Enemys extends EnemyData {
|
||||
interface Enemys {
|
||||
/**
|
||||
* 所有的怪物信息
|
||||
*/
|
||||
@@ -250,11 +250,6 @@ interface Enemys extends EnemyData {
|
||||
[P in EnemyIds]: Enemy<P>;
|
||||
};
|
||||
|
||||
/**
|
||||
* 脚本编辑的怪物相关
|
||||
*/
|
||||
readonly enemydata: EnemyData;
|
||||
|
||||
/**
|
||||
* 获得所有怪物原始数据的一个副本
|
||||
*/
|
||||
@@ -262,51 +257,6 @@ interface Enemys extends EnemyData {
|
||||
[P in EnemyIds]: Enemy<P>;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获得某种敌人的全部特殊属性名称
|
||||
* @example core.getSpecialText('greenSlime') // ['先攻', '3连击', '破甲', '反击']
|
||||
* @param enemy 敌人id或敌人对象,如core.material.enemys.greenSlime
|
||||
* @returns 字符串数组
|
||||
*/
|
||||
getSpecialText(enemy: EnemyIds | Enemy): string[];
|
||||
|
||||
/**
|
||||
* 获得所有特殊属性的颜色
|
||||
* @param enemy 敌人id或敌人对象,如core.material.enemys.greenSlime
|
||||
*/
|
||||
getSpecialColor(enemy: EnemyIds | Enemy): Color[];
|
||||
|
||||
/**
|
||||
* 获得所有特殊属性的额外标记
|
||||
* @param enemy 敌人id或敌人对象,如core.material.enemys.greenSlime
|
||||
*/
|
||||
getSpecialFlag(enemy: EnemyIds | Enemy): number[];
|
||||
|
||||
/**
|
||||
* 获得某种敌人的某种特殊属性的介绍
|
||||
* @example core.getSpecialHint('bat', 1) // '先攻:怪物首先攻击'
|
||||
* @param enemy 敌人id或敌人对象,用于确定属性的具体数值
|
||||
* @param special 属性编号,可以是该敌人没有的属性
|
||||
* @returns 属性的介绍,以属性名加中文冒号开头
|
||||
*/
|
||||
getSpecialHint(enemy: EnemyIds | Enemy, special: number): string;
|
||||
|
||||
/**
|
||||
* 获得某个敌人的某项属性值
|
||||
* @param enemy 敌人id或敌人对象
|
||||
* @param name 获取的敌人属性
|
||||
* @param x 敌人的横坐标
|
||||
* @param y 敌人的纵坐标
|
||||
* @param floorId 敌人所在楼层
|
||||
*/
|
||||
getEnemyValue<K extends keyof Enemy>(
|
||||
enemy: EnemyIds | Enemy,
|
||||
name: K,
|
||||
x?: number,
|
||||
y?: number,
|
||||
floorId?: FloorIds
|
||||
): Enemy[K];
|
||||
|
||||
/**
|
||||
* 判定主角当前能否打败某只敌人
|
||||
* @example core.canBattle('greenSlime',0,0,'MT0') // 能否打败主塔0层左上角的绿头怪(假设有)
|
||||
@@ -322,34 +272,6 @@ interface Enemys extends EnemyData {
|
||||
floorId?: FloorIds,
|
||||
dir?: Dir | 'none' | (Dir | 'none')[]
|
||||
): boolean;
|
||||
|
||||
/**
|
||||
* 获得某只敌人对主角的总伤害
|
||||
* @example core.getDamage('greenSlime',0,0,'MT0') // 绿头怪的总伤害
|
||||
* @param enemy 敌人id或敌人对象
|
||||
* @param x 敌人的横坐标
|
||||
* @param y 敌人的纵坐标
|
||||
* @param floorId 敌人所在的地图
|
||||
* @returns 总伤害,如果因为没有破防或无敌怪等其他原因无法战斗,则返回null
|
||||
*/
|
||||
getDamage(
|
||||
enemy: EnemyIds | Enemy,
|
||||
x?: number,
|
||||
y?: number,
|
||||
floorId?: FloorIds
|
||||
): number;
|
||||
|
||||
/**
|
||||
* 检查某些楼层是否还有漏打的(某种)敌人
|
||||
* @example core.hasEnemyLeft('greenSlime', ['sample0', 'sample1']) // 样板0层和1层是否有漏打的绿头怪
|
||||
* @param enemyId 敌人id,可选,默认为任意敌人
|
||||
* @param floorId 地图id或其数组,可选,默认为当前地图
|
||||
* @returns true表示有敌人被漏打,false表示敌人已死光
|
||||
*/
|
||||
hasEnemyLeft(
|
||||
enemyId?: EnemyIds | EnemyIds[],
|
||||
floorId?: FloorIds | FloorIds[]
|
||||
): boolean;
|
||||
}
|
||||
|
||||
declare const enemys: new () => Enemys;
|
||||
Vendored
-24
@@ -52,25 +52,6 @@ interface ControlData {
|
||||
parallelDo(time: number): void;
|
||||
}
|
||||
|
||||
interface EnemyData {
|
||||
/**
|
||||
* 获得所有特殊属性定义
|
||||
*/
|
||||
getSpecials(): EnemySpecialDeclaration[];
|
||||
|
||||
/**
|
||||
* 判定某种特殊属性的有无
|
||||
* @example core.hasSpecial('greenSlime', 1) // 判定绿头怪有无先攻属性
|
||||
* @param special 敌人id或敌人对象或正整数数组或自然数
|
||||
* @param test 待检查的属性编号
|
||||
* @returns 若special为数组或数且含有test或相等、或special为敌人id或对象且具有此属性,则返回true
|
||||
*/
|
||||
hasSpecial(
|
||||
special: number | number[] | EnemyIds | Enemy,
|
||||
test: number
|
||||
): boolean;
|
||||
}
|
||||
|
||||
interface UiData {
|
||||
/**
|
||||
* 数据统计界面统计的道具数量
|
||||
@@ -184,11 +165,6 @@ interface FunctionsData {
|
||||
*/
|
||||
control: ControlData;
|
||||
|
||||
/**
|
||||
* 怪物信息
|
||||
*/
|
||||
enemys: EnemyData;
|
||||
|
||||
/**
|
||||
* ui信息
|
||||
*/
|
||||
|
||||
@@ -48,22 +48,12 @@ import { LeftOutlined } from '@ant-design/icons-vue';
|
||||
import { KeyCode } from '../plugin/keyCodes';
|
||||
import { noClosePanel } from '../plugin/uiController';
|
||||
import { ToShowEnemy, detailInfo } from '../plugin/ui/book';
|
||||
import { isMobile } from '../plugin/use';
|
||||
import { getDetailedEnemy } from '../plugin/ui/fixed';
|
||||
|
||||
const floorId =
|
||||
// @ts-ignore
|
||||
core.floorIds[core.status.event?.ui?.index] ?? core.status.floorId;
|
||||
|
||||
const specials = Object.fromEntries(
|
||||
core.getSpecials().map(v => {
|
||||
return [v[0], v.slice(1)];
|
||||
})
|
||||
) as Record<
|
||||
string,
|
||||
EnemySpecialDeclaration extends [number, ...infer F] ? F : never
|
||||
>;
|
||||
|
||||
const enemy = core.getCurrentEnemys(floorId);
|
||||
const toShow: ToShowEnemy[] = enemy.map(v =>
|
||||
getDetailedEnemy(v.enemy, floorId)
|
||||
|
||||
@@ -154,6 +154,7 @@ async function clickStartButton(id: string) {
|
||||
}
|
||||
|
||||
function onmove(e: MouseEvent) {
|
||||
if (!window.core) return;
|
||||
const { offsetX, offsetY } = e;
|
||||
const ele = e.target as HTMLDivElement;
|
||||
const style = getComputedStyle(ele);
|
||||
|
||||
+5
-38
@@ -10,26 +10,11 @@
|
||||
>
|
||||
<Scroll :no-scroll="true" style="height: 100%">
|
||||
<div id="studied-main">
|
||||
<div v-for="(num, i) of studied" :key="i">
|
||||
<div id="studied-rough">
|
||||
<right-outlined
|
||||
:class="folded[i] ? 'folded' : ''"
|
||||
@click="folded[i] = !folded[i]"
|
||||
id="studied-fold"
|
||||
/>
|
||||
<span
|
||||
>{{ i }}. {{ skills[i] }},剩余{{
|
||||
last[i]
|
||||
}}场战斗</span
|
||||
>
|
||||
</div>
|
||||
<div id="studied-detail" v-if="!folded[i]">
|
||||
{{ hint(num) }}
|
||||
</div>
|
||||
</div>
|
||||
</div></Scroll
|
||||
></Box
|
||||
>
|
||||
<div
|
||||
v-for="(num, i) of studied"
|
||||
:key="i"
|
||||
></div></div></Scroll
|
||||
></Box>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -61,24 +46,6 @@ const last = computed(() => {
|
||||
return core.status.hero.special?.last ?? [];
|
||||
});
|
||||
|
||||
const skills = computed(() => {
|
||||
const specials = core.getSpecials();
|
||||
return studied.value.map(v => {
|
||||
const s = specials[v - 1][1];
|
||||
// @ts-ignore
|
||||
if (s instanceof Function) return s(core.status.hero.special);
|
||||
else return s;
|
||||
});
|
||||
});
|
||||
|
||||
function hint(number: number) {
|
||||
const specials = core.getSpecials();
|
||||
const s = specials[number - 1][2];
|
||||
// @ts-ignore
|
||||
if (s instanceof Function) return s(core.status.hero.special);
|
||||
else return s;
|
||||
}
|
||||
|
||||
async function calHeight() {
|
||||
await new Promise<void>(resolve => {
|
||||
requestAnimationFrame(() => {
|
||||
|
||||
Reference in new issue
Block a user