地图伤害的计算

This commit is contained in:
unanmed 2023-06-29 21:20:33 +08:00
parent 87166c5ed7
commit 06fc4c4940
2 changed files with 117 additions and 6 deletions

View File

@ -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);
}
}
/**

View File

@ -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;