mirror of
https://github.com/unanmed/HumanBreak.git
synced 2026-11-14 10:34:30 +08:00
feat: 苍蓝之殿南部两区
This commit is contained in:
1 parent
cb72e53c3d
commit
06bcb94eae
72 files changed
+1352
-2288
No files matched your search
@@ -266,6 +266,8 @@ function init() {
|
||||
if (core.status.event.id == null) core.continueAutomaticRoute();
|
||||
else core.clearContinueAutomaticRoute();
|
||||
|
||||
core.checkAutoEvents();
|
||||
|
||||
hook.emit('afterBattle', enemy, x, y);
|
||||
};
|
||||
}
|
||||
|
||||
+159
-26
@@ -48,6 +48,7 @@ interface MapDamage {
|
||||
damage: number;
|
||||
type: Set<string>;
|
||||
mockery?: LocArr[];
|
||||
hunt?: [x: number, y: number, dir: Dir][];
|
||||
}
|
||||
|
||||
interface HaloData<T extends keyof HaloType = keyof HaloType> {
|
||||
@@ -102,6 +103,9 @@ export class EnemyCollection implements RangeCollection<DamageEnemy> {
|
||||
mapDamage: Record<string, MapDamage> = {};
|
||||
haloList: HaloData[] = [];
|
||||
|
||||
/** 乾坤挪移属性 */
|
||||
translation: [number, number] = [0, 0];
|
||||
|
||||
constructor(floorId: FloorIds) {
|
||||
this.floorId = floorId;
|
||||
this.extract();
|
||||
@@ -128,10 +132,10 @@ export class EnemyCollection implements RangeCollection<DamageEnemy> {
|
||||
|
||||
/**
|
||||
* 计算怪物真实属性
|
||||
* @param noCache 是否不使用缓存
|
||||
*/
|
||||
calRealAttribute() {
|
||||
this.haloList = [];
|
||||
this.translation = [0, 0];
|
||||
this.list.forEach(v => {
|
||||
v.reset();
|
||||
});
|
||||
@@ -311,6 +315,17 @@ export class EnemyCollection implements RangeCollection<DamageEnemy> {
|
||||
alpha: 1
|
||||
});
|
||||
}
|
||||
|
||||
// 追猎
|
||||
if (dam.hunt) {
|
||||
core.status.damage.extraData.push({
|
||||
text: '猎',
|
||||
px: 32 * x + 16,
|
||||
py: 32 * (y + 1) - 14,
|
||||
color: '#fd4',
|
||||
alpha: 1
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -381,6 +396,12 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
}
|
||||
this.progress = 0;
|
||||
this.providedHalo.clear();
|
||||
|
||||
// 在这里计算乾坤挪移
|
||||
if (this.col && enemy.special.includes(30)) {
|
||||
this.col.translation[0] += enemy.translation![0];
|
||||
this.col.translation[1] += enemy.translation![1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -392,6 +413,11 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
const special = this.info.special;
|
||||
const info = this.info;
|
||||
const floorId = this.floorId ?? core.status.floorId;
|
||||
let [dx, dy] = [0, 0];
|
||||
const col = this.col ?? core.status.maps[this.floorId!]?.enemy;
|
||||
if (col) {
|
||||
[dx, dy] = col.translation;
|
||||
}
|
||||
|
||||
// 智慧之源
|
||||
if (flags.hard === 2 && special.includes(14)) {
|
||||
@@ -406,7 +432,10 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
if (has(flags[`melt_${floorId}`]) && has(this.x) && has(this.y)) {
|
||||
for (const [loc, per] of Object.entries(flags[`melt_${floorId}`])) {
|
||||
const [mx, my] = loc.split(',').map(v => parseInt(v));
|
||||
if (Math.abs(mx - this.x) <= 1 && Math.abs(my - this.y) <= 1) {
|
||||
if (
|
||||
Math.abs(mx + dx - this.x) <= 1 &&
|
||||
Math.abs(my + dy - this.y) <= 1
|
||||
) {
|
||||
info.atkBuff_ += per as number;
|
||||
info.defBuff_ += per as number;
|
||||
}
|
||||
@@ -463,6 +492,8 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
if (!has(this.x) || !has(this.y)) return;
|
||||
const special = this.getHaloSpecials();
|
||||
const col = this.col ?? core.status.maps[this.floorId!].enemy;
|
||||
let [dx, dy] = [0, 0];
|
||||
if (col) [dx, dy] = col.translation;
|
||||
|
||||
for (const halo of special) {
|
||||
switch (halo) {
|
||||
@@ -472,7 +503,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
const type = 'square';
|
||||
const r = Math.floor(e.haloRange!);
|
||||
const d = r * 2 + 1;
|
||||
const range = { x: this.x, y: this.y, d };
|
||||
const range = { x: this.x + dx, y: this.y + dy, d };
|
||||
|
||||
// 这一句必须放到applyHalo之前
|
||||
this.providedHalo.add(29);
|
||||
@@ -512,7 +543,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
);
|
||||
col.haloList.push({
|
||||
type: 'square',
|
||||
data: { x: this.x, y: this.y, d },
|
||||
data: { x: this.x + dx, y: this.y + dy, d },
|
||||
special: 29,
|
||||
from: this
|
||||
});
|
||||
@@ -532,6 +563,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
const col = this.col ?? core.status.maps[this.floorId].enemy;
|
||||
if (!col) return;
|
||||
const special = this.getHaloSpecials();
|
||||
const [dx, dy] = col.translation;
|
||||
|
||||
const square7: HaloFn[] = [];
|
||||
const square5: HaloFn[] = [];
|
||||
@@ -540,27 +572,32 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
|
||||
// 抱团
|
||||
if (special.includes(8)) {
|
||||
square5.push((e, enemy) => {
|
||||
if (
|
||||
e.special.includes(8) &&
|
||||
(e.x !== this.x || this.y !== e.y)
|
||||
) {
|
||||
e.atkBuff_ += enemy.together ?? 0;
|
||||
e.defBuff_ += enemy.together ?? 0;
|
||||
col.applyHalo(
|
||||
'square',
|
||||
{ x: this.x, y: this.y, d: 5 },
|
||||
this,
|
||||
(e, enemy) => {
|
||||
if (
|
||||
e.special.includes(8) &&
|
||||
(e.x !== this.x || this.y !== e.y)
|
||||
) {
|
||||
e.atkBuff_ += enemy.together ?? 0;
|
||||
e.defBuff_ += enemy.together ?? 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
this.providedHalo.add(8);
|
||||
}
|
||||
|
||||
// 冰封光环
|
||||
if (special.includes(21)) {
|
||||
square7.push(e => {
|
||||
e.damageDecline += this.enemy.iceHalo ?? 0;
|
||||
e.damageDecline += this.info.iceHalo ?? 0;
|
||||
});
|
||||
this.providedHalo.add(21);
|
||||
col.haloList.push({
|
||||
type: 'square',
|
||||
data: { x: this.x, y: this.y, d: 7 },
|
||||
data: { x: this.x + dx, y: this.y + dy, d: 7 },
|
||||
special: 21,
|
||||
from: this
|
||||
});
|
||||
@@ -569,12 +606,12 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
// 冰封之核
|
||||
if (special.includes(26)) {
|
||||
square5.push(e => {
|
||||
e.defBuff_ += this.enemy.iceCore ?? 0;
|
||||
e.defBuff_ += this.info.iceCore ?? 0;
|
||||
});
|
||||
this.providedHalo.add(26);
|
||||
col.haloList.push({
|
||||
type: 'square',
|
||||
data: { x: this.x, y: this.y, d: 5 },
|
||||
data: { x: this.x + dx, y: this.y + dy, d: 5 },
|
||||
special: 26,
|
||||
from: this
|
||||
});
|
||||
@@ -583,19 +620,29 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
// 火焰之核
|
||||
if (special.includes(27)) {
|
||||
square5.push(e => {
|
||||
e.atkBuff_ += this.enemy.fireCore ?? 0;
|
||||
e.atkBuff_ += this.info.fireCore ?? 0;
|
||||
});
|
||||
this.providedHalo.add(27);
|
||||
col.haloList.push({
|
||||
type: 'square',
|
||||
data: { x: this.x, y: this.y, d: 5 },
|
||||
data: { x: this.x + dx, y: this.y + dy, d: 5 },
|
||||
special: 27,
|
||||
from: this
|
||||
});
|
||||
}
|
||||
|
||||
col.applyHalo('square', { x: this.x, y: this.y, d: 7 }, this, square7);
|
||||
col.applyHalo('square', { x: this.x, y: this.y, d: 5 }, this, square5);
|
||||
col.applyHalo(
|
||||
'square',
|
||||
{ x: this.x + dx, y: this.y + dy, d: 7 },
|
||||
this,
|
||||
square7
|
||||
);
|
||||
col.applyHalo(
|
||||
'square',
|
||||
{ x: this.x + dx, y: this.y + dy, d: 5 },
|
||||
this,
|
||||
square5
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -703,6 +750,37 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
}
|
||||
}
|
||||
|
||||
// 追猎
|
||||
if (this.info.special.includes(12)) {
|
||||
const objs = core.getMapBlocksObj(this.floorId);
|
||||
for (let nx = 0; nx < w; nx++) {
|
||||
const loc = `${nx},${this.y}` as LocString;
|
||||
const block = objs[loc];
|
||||
if (!block?.event.noPass) {
|
||||
damage[loc] ??= { damage: 0, type: new Set() };
|
||||
damage[loc].hunt ??= [];
|
||||
damage[loc].hunt!.push([
|
||||
this.x,
|
||||
this.y,
|
||||
nx < this.x ? 'left' : 'right'
|
||||
]);
|
||||
}
|
||||
}
|
||||
for (let ny = 0; ny < h; ny++) {
|
||||
const loc = `${this.x},${ny}` as LocString;
|
||||
const block = objs[loc];
|
||||
if (!block?.event.noPass) {
|
||||
damage[loc] ??= { damage: 0, type: new Set() };
|
||||
damage[loc].hunt ??= [];
|
||||
damage[loc].hunt!.push([
|
||||
this.x,
|
||||
this.y,
|
||||
ny < this.y ? 'up' : 'down'
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
@@ -927,9 +1005,6 @@ const skills: [unlock: string, condition: string][] = [
|
||||
['shieldOn', 'shield']
|
||||
];
|
||||
|
||||
const haloValue: Map<number, SelectKey<Enemy, number | undefined>[]> =
|
||||
new Map();
|
||||
|
||||
/**
|
||||
* 计算怪物伤害
|
||||
* @param info 怪物信息
|
||||
@@ -939,7 +1014,13 @@ export function calDamageWith(
|
||||
info: EnemyInfo,
|
||||
hero: Partial<HeroStatus>
|
||||
): number | null {
|
||||
const { hp, hpmax, mana, mdef } = core.status.hero;
|
||||
const {
|
||||
hp,
|
||||
hpmax,
|
||||
mana,
|
||||
mdef,
|
||||
special: heroSpec = { num: [], last: [] }
|
||||
} = core.status.hero;
|
||||
let { atk, def } = hero as HeroStatus;
|
||||
let { hp: monHp, atk: monAtk, def: monDef, special, enemy } = info;
|
||||
|
||||
@@ -952,6 +1033,13 @@ export function calDamageWith(
|
||||
monAtk += delta;
|
||||
}
|
||||
|
||||
// 勇士学习的饥渴
|
||||
if (heroSpec.num.includes(7)) {
|
||||
const delta = Math.floor((monAtk * heroSpec.hungry!) / 100);
|
||||
atk += delta;
|
||||
monAtk -= delta;
|
||||
}
|
||||
|
||||
let heroPerDamage: number;
|
||||
|
||||
// 绝对防御
|
||||
@@ -975,11 +1063,19 @@ export function calDamageWith(
|
||||
|
||||
heroPerDamage *= 1 - info.damageDecline / 100;
|
||||
|
||||
// 勇士学习勇气之刃
|
||||
if (heroSpec.num.includes(10)) {
|
||||
monHp -= (heroSpec.courage / 100 - 1) * heroPerDamage;
|
||||
}
|
||||
|
||||
let enemyPerDamage: number;
|
||||
|
||||
// 魔攻
|
||||
if (special.includes(2) || special.includes(13)) {
|
||||
enemyPerDamage = monAtk;
|
||||
if (core.hasEquip('I663')) {
|
||||
enemyPerDamage = Math.max(0, enemyPerDamage - 500);
|
||||
}
|
||||
} else {
|
||||
enemyPerDamage = monAtk - def;
|
||||
if (enemyPerDamage < 0) enemyPerDamage = 0;
|
||||
@@ -995,13 +1091,49 @@ export function calDamageWith(
|
||||
if (special.includes(5)) enemyPerDamage *= 3;
|
||||
if (special.includes(6)) enemyPerDamage *= enemy.n!;
|
||||
|
||||
// 勇士学习霜冻
|
||||
if (heroSpec.num.includes(20)) {
|
||||
enemyPerDamage *= 1 - heroSpec.ice / 100;
|
||||
}
|
||||
|
||||
// 勇士学习苍蓝刻
|
||||
if (heroSpec.num.includes(28)) {
|
||||
enemyPerDamage *= 1 - heroSpec.paleShield / 100;
|
||||
}
|
||||
|
||||
// 苍蓝刻
|
||||
if (special.includes(28)) {
|
||||
heroPerDamage *= 1 - info.paleShield! / 100;
|
||||
}
|
||||
|
||||
// 勇士学习的连击
|
||||
if (heroSpec.num.includes(4)) heroPerDamage *= 2;
|
||||
if (heroSpec.num.includes(5)) heroPerDamage *= 3;
|
||||
if (heroSpec.num.includes(6)) heroPerDamage *= heroSpec.n;
|
||||
|
||||
// 勇士学习勇气冲锋
|
||||
const hasCharge = heroSpec.num.includes(11);
|
||||
if (hasCharge) {
|
||||
monHp -= (heroSpec.charge / 100) * heroPerDamage;
|
||||
}
|
||||
|
||||
let turn = Math.ceil(monHp / heroPerDamage);
|
||||
|
||||
// 勇士学习致命一击
|
||||
if (heroSpec.num.includes(1)) {
|
||||
const five =
|
||||
4 * heroPerDamage + (heroPerDamage * (info.crit! - 100)) / 100;
|
||||
const fTurn = Math.floor(monHp / five);
|
||||
const last = monHp - fTurn * five;
|
||||
const lastTurn = Math.min(last / heroPerDamage, 5);
|
||||
turn = fTurn * 5 + lastTurn;
|
||||
}
|
||||
|
||||
if (hasCharge) {
|
||||
turn -= 5;
|
||||
if (turn < 0) turn = 0;
|
||||
}
|
||||
|
||||
// 致命一击
|
||||
if (special.includes(1)) {
|
||||
const times = Math.floor(turn / 5);
|
||||
@@ -1014,7 +1146,7 @@ export function calDamageWith(
|
||||
}
|
||||
|
||||
// 勇气冲锋
|
||||
if (special.includes(11)) {
|
||||
if (special.includes(11) && !hasCharge) {
|
||||
damage += (info.charge! / 100) * enemyPerDamage;
|
||||
turn += 5;
|
||||
}
|
||||
@@ -1029,7 +1161,8 @@ export function calDamageWith(
|
||||
if (flags.hard === 1) damage *= 0.9;
|
||||
|
||||
if (flags.chapter > 1 && damage < 0) {
|
||||
damage *= 0.25;
|
||||
const dm = -enemy.hp * 0.25;
|
||||
if (damage < dm) damage = dm;
|
||||
}
|
||||
|
||||
return damage;
|
||||
|
||||
@@ -233,5 +233,18 @@ export const specials: SpecialDeclaration[] = [
|
||||
);
|
||||
},
|
||||
color: '#F721F7'
|
||||
},
|
||||
{
|
||||
code: 30,
|
||||
name: '乾坤挪移',
|
||||
desc: enemy => {
|
||||
const [dx, dy] = enemy.translation!;
|
||||
return `此怪物在场时,所有光环向${
|
||||
dx < 0 ? '左' : '右'
|
||||
}平移${Math.abs(dx)}格,向${dy < 0 ? '上' : '下'}平移${Math.abs(
|
||||
dy
|
||||
)}格。不同怪物间为加算叠加`;
|
||||
},
|
||||
color: '#FDCD0B'
|
||||
}
|
||||
];
|
||||
+3
-1
@@ -8,6 +8,7 @@ import { gameListener, hook, loading } from './game';
|
||||
import * as battle from './enemy/battle';
|
||||
import * as hero from './hero';
|
||||
import * as miscMechanism from './mechanism/misc';
|
||||
import * as study from './mechanism/study';
|
||||
|
||||
// ----- 类注册
|
||||
Mota.register('class', 'DamageEnemy', damage.DamageEnemy);
|
||||
@@ -27,7 +28,8 @@ Mota.register('var', 'gameListener', gameListener);
|
||||
Mota.register('var', 'loading', loading);
|
||||
// ----- 模块注册
|
||||
Mota.register('module', 'Mechanism', {
|
||||
BluePalace: miscMechanism.BluePalace
|
||||
BluePalace: miscMechanism.BluePalace,
|
||||
Study: study
|
||||
});
|
||||
|
||||
main.loading = loading;
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
import { has } from '@/plugin/game/utils';
|
||||
import { EnemyInfo } from '../enemy/damage';
|
||||
import { getSkillLevel } from '@/plugin/game/skillTree';
|
||||
import { hook } from '../game';
|
||||
|
||||
// 负责勇士技能:学习
|
||||
const canStudy: Set<number> = new Set([1, 4, 5, 6, 7, 10, 11, 20, 28, 30]);
|
||||
const numberProp: Record<number, (keyof Enemy)[]> = {
|
||||
1: ['crit'],
|
||||
6: ['n'],
|
||||
7: ['hungry'],
|
||||
10: ['courage'],
|
||||
11: ['charge'],
|
||||
20: ['ice'],
|
||||
28: ['paleShield']
|
||||
};
|
||||
|
||||
hook.on('afterBattle', () => {
|
||||
declineStudiedSkill();
|
||||
});
|
||||
|
||||
/**
|
||||
* 判断是否可以学习某个技能
|
||||
* @param number 要学习的技能
|
||||
*/
|
||||
export function canStudySkill(number: number) {
|
||||
const s = (core.status.hero.special ??= { num: [], last: [] });
|
||||
if (Mota.Plugin.require('skillTree_g').getSkillLevel(11) === 0)
|
||||
return false;
|
||||
if (s.num.length >= 1) return false;
|
||||
if (s.num.includes(number)) return false;
|
||||
return canStudy.has(number);
|
||||
}
|
||||
|
||||
/**
|
||||
* 学习某个怪物的某个技能
|
||||
* @param enemy 被学习的怪物
|
||||
* @param number 学习的技能
|
||||
*/
|
||||
export function studySkill(enemy: EnemyInfo, number: number) {
|
||||
core.status.hero.special ??= { num: [], last: [] };
|
||||
const s = core.status.hero.special;
|
||||
if (!canStudySkill(number)) return false;
|
||||
s.num.push(number);
|
||||
s.last.push(getSkillLevel(11) * 3 + 2);
|
||||
const value = numberProp[number] ?? [];
|
||||
for (const key of value) {
|
||||
s[key] = enemy[key];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 忘记某个学习过的技能
|
||||
* @param num 要忘记的技能
|
||||
* @param i 技能所在索引
|
||||
*/
|
||||
export function forgetStudiedSkill(num: number, i: number) {
|
||||
const s = core.status.hero.special;
|
||||
const index = has(i) ? i : s.num.indexOf(num);
|
||||
if (index === -1) return;
|
||||
s.num.splice(index, 1);
|
||||
s.last.splice(index, 1);
|
||||
const value = numberProp[num] ?? [];
|
||||
for (const key of value) {
|
||||
delete s[key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 战斗后减少剩余次数
|
||||
*/
|
||||
export function declineStudiedSkill() {
|
||||
const s = (core.status.hero.special ??= { num: [], last: [] });
|
||||
for (let i = 0; i < s.last.length; i++) {
|
||||
s.last[i]--;
|
||||
if (s.last[i] === 0) {
|
||||
forgetStudiedSkill(s.num[i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -136,7 +136,7 @@ interface PluginInterface {
|
||||
itemDetail_g: typeof import('../plugin/game/fx/itemDetail');
|
||||
checkBlock_g: typeof import('../plugin/game/enemy/checkblock');
|
||||
halo_g: typeof import('../plugin/game/fx/halo');
|
||||
study_g: typeof import('../plugin/game/study');
|
||||
// study_g: typeof import('../plugin/game/study');
|
||||
}
|
||||
|
||||
interface PackageInterface {
|
||||
|
||||
Reference in new issue
Block a user