mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-01-19 12:49:25 +08:00
地图伤害的计算
This commit is contained in:
parent
87166c5ed7
commit
06fc4c4940
@ -1,6 +1,6 @@
|
||||
import { getHeroStatusOf, getHeroStatusOn } from './hero';
|
||||
import { Range, RangeCollection } from './range';
|
||||
import { backDir, ensureArray, has, ofDir } from './utils';
|
||||
import { backDir, ensureArray, has, manhattan, ofDir } from './utils';
|
||||
|
||||
interface HaloType {
|
||||
square: {
|
||||
@ -34,7 +34,8 @@ interface DamageInfo {
|
||||
|
||||
interface MapDamage {
|
||||
damage: number;
|
||||
type: string[];
|
||||
type: Set<string>;
|
||||
mockery?: LocArr[];
|
||||
}
|
||||
|
||||
interface HaloData<T extends keyof HaloType = keyof HaloType> {
|
||||
@ -104,8 +105,14 @@ export class EnemyCollection implements RangeCollection<DamageEnemy> {
|
||||
*/
|
||||
calMapDamage(noCache: boolean = false) {
|
||||
if (noCache) this.mapDamage = {};
|
||||
const hero = getHeroStatusOn(
|
||||
realStatus,
|
||||
core.status.hero.loc.x,
|
||||
core.status.hero.loc.y,
|
||||
this.floorId
|
||||
);
|
||||
this.list.forEach(v => {
|
||||
v.calMapDamage(this.mapDamage);
|
||||
v.calMapDamage(this.mapDamage, hero);
|
||||
});
|
||||
}
|
||||
|
||||
@ -424,12 +431,109 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
}));
|
||||
}
|
||||
|
||||
calMapDamage(damage?: Record<string, MapDamage>) {
|
||||
damage ??= {};
|
||||
if (!has(this.x) || !has(this.y)) return damage;
|
||||
/**
|
||||
* 计算地图伤害
|
||||
* @param damage 存入的对象
|
||||
*/
|
||||
calMapDamage(
|
||||
damage: Record<string, MapDamage> = {},
|
||||
hero: Partial<HeroStatus> = getHeroStatusOn(realStatus)
|
||||
) {
|
||||
if (!has(this.x) || !has(this.y) || !has(this.floorId)) return damage;
|
||||
const enemy = this.enemy;
|
||||
const floor = core.status.maps[this.floorId];
|
||||
const w = floor.width;
|
||||
const h = floor.height;
|
||||
|
||||
// 突刺
|
||||
if (this.info.special.includes(15)) {
|
||||
const range = enemy.range ?? 1;
|
||||
const startX = Math.max(0, this.x - range);
|
||||
const startY = Math.max(0, this.y - range);
|
||||
const endX = Math.min(floor.width - 1, this.x + range);
|
||||
const endY = Math.min(floor.height - 1, this.y + range);
|
||||
const dam = Math.max((enemy.value ?? 0) - hero.def!, 0);
|
||||
|
||||
for (let x = startX; x <= endX; x++) {
|
||||
for (let y = startY; y <= endY; y++) {
|
||||
if (
|
||||
!enemy.zoneSquare &&
|
||||
manhattan(x, y, this.x, this.y) > range
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const loc = `${x},${y}`;
|
||||
this.setMapDamage(damage, loc, dam, '突刺');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 射击
|
||||
if (this.info.special.includes(24)) {
|
||||
const dirs: Dir[] = ['left', 'down', 'up', 'right'];
|
||||
const dam = Math.max((enemy.atk ?? 0) - hero.def!, 0);
|
||||
const objs = core.getMapBlocksObj(this.floorId);
|
||||
|
||||
for (const dir of dirs) {
|
||||
let x = this.x;
|
||||
let y = this.y;
|
||||
const { x: dx, y: dy } = core.utils.scan[dir];
|
||||
while (1) {
|
||||
if (x < 0 || y < 0 || x >= w || y >= h) break;
|
||||
x += dx;
|
||||
y += dy;
|
||||
const loc = `${x},${y}` as LocString;
|
||||
const block = objs[loc];
|
||||
if (
|
||||
block.event.noPass &&
|
||||
block.event.cls !== 'enemys' &&
|
||||
block.event.cls !== 'enemy48' &&
|
||||
block.id !== 141 &&
|
||||
block.id !== 151
|
||||
) {
|
||||
break;
|
||||
}
|
||||
this.setMapDamage(damage, loc, dam, '射击');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 电摇嘲讽
|
||||
if (this.info.special.includes(19)) {
|
||||
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].mockery ??= [];
|
||||
damage[loc].mockery!.push([this.x, this.y]);
|
||||
}
|
||||
}
|
||||
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].mockery ??= [];
|
||||
damage[loc].mockery!.push([this.x, this.y]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
private setMapDamage(
|
||||
damage: Record<string, MapDamage>,
|
||||
loc: string,
|
||||
dam: number,
|
||||
type: string
|
||||
) {
|
||||
damage[loc] ??= { damage: 0, type: new Set() };
|
||||
damage[loc].damage += dam;
|
||||
damage[loc].type.add(type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,6 +55,13 @@ export function ofDir(x: number, y: number, dir: Dir2): LocArr {
|
||||
return [x + dx, y + dy];
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算曼哈顿距离
|
||||
*/
|
||||
export function manhattan(x1: number, y1: number, x2: number, y2: number) {
|
||||
return Math.abs(x1 - x2) + Math.abs(y1 - y2);
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface GamePluginUtils {
|
||||
ofDir: typeof ofDir;
|
||||
|
Loading…
Reference in New Issue
Block a user