范围类

This commit is contained in:
AncTe committed 2023-05-04 16:03:23 +08:00
1 parent 2e7e64b399
commit 068dca14f9
6 files changed
+287 -41

No files matched your search

+143 -4
View File
@@ -1,9 +1,148 @@
///<reference path="../../../src/types/core.d.ts" />
import { Range, RangeCollection } from './range';
import { ensureArray } from './utils';
export class EnemyCollection {}
interface HaloType {
square: {
x: number;
y: number;
d: number;
};
}
export class Enemy {}
type HaloFn<T extends EnemyIds = EnemyIds> = (enemy: Enemy<T>) => Enemy<T>;
export const haloSpecials: number[] = [21, 25, 26, 27];
export class EnemyCollection implements RangeCollection<DamageEnemy> {
floorId: FloorIds;
list: DamageEnemy[] = [];
range: Range<DamageEnemy> = new Range(this);
constructor(floorId: FloorIds) {
this.floorId = floorId;
}
extract() {
core.extractBlocks(this.floorId);
core.status.maps[this.floorId].blocks.forEach(v => {
if (v.event.cls !== 'enemy48' && v.event.cls !== 'enemys') return;
const enemy = core.material.enemys[v.event.id as EnemyIds];
this.list.push(new DamageEnemy(enemy));
});
}
calAttribute(noCache: boolean = false) {}
calDamage(noCache: boolean = false) {}
/**
* 向怪物施加光环
* @param type 光环的范围类型
* @param data 光环范围信息
* @param halo 光环效果函数
* @param recursion 是否递归施加,一般只有在光环预平衡阶段会使用到
*/
applyHalo<K extends keyof HaloType>(
type: K,
data: HaloType[K],
halo: HaloFn | HaloFn[],
recursion: boolean = false
) {
const arr = ensureArray(halo);
}
/**
* 预平衡光环
*/
preBalanceHalo() {}
}
export class DamageEnemy<T extends EnemyIds = EnemyIds> {
id: T;
x?: number;
y?: number;
floorId?: FloorIds;
enemy: Enemy<T>;
/** 计算特殊属性但不计算光环的属性 */
noHaloInfo?: Enemy<T>;
/** 既计算特殊属性又计算光环的属性 */
realInfo?: Enemy<T>;
/** 向其他怪提供过的光环 */
providedHalo: number[] = [];
constructor(enemy: Enemy<T>, x?: number, y?: number, floorId?: FloorIds) {
this.id = enemy.id;
this.enemy = enemy;
this.x = x;
this.y = y;
this.floorId = floorId;
}
reset() {
delete this.noHaloInfo;
delete this.realInfo;
}
calAttribute() {}
getHaloSpecials(): number[] {
if (!this.floorId) return [];
if (!core.has(this.x) || !core.has(this.y)) return [];
const special = this.realInfo?.special ?? this.enemy.special;
const filter = special.filter(v => {
return haloSpecials.includes(v) && !this.providedHalo.includes(v);
});
if (filter.length === 0) return [];
const collection = core.status.maps[this.floorId].enemy;
if (!collection) {
throw new Error(
`Unexpected undefined of enemy collection in floor ${this.floorId}.`
);
}
return filter;
}
/**
* 光环预提供,用于平衡所有怪的光环属性,避免出现不同情况下光环效果不一致的现象
*/
preProvideHalo() {}
/**
* 向其他怪提供光环
*/
provideHalo() {
const speical = this.getHaloSpecials();
const square7: HaloFn[] = [];
if (speical.includes(21)) {
}
}
/**
* 接受其他怪的光环
*/
injectHalo(halo: HaloFn<T>) {}
calDamage() {}
}
declare global {
interface PluginDeclaration {
damage: {
Enemy: typeof DamageEnemy;
Collection: typeof EnemyCollection;
};
}
interface Floor {
enemy: EnemyCollection;
}
}
core.plugin.damage = {
Enemy
Enemy: DamageEnemy,
Collection: EnemyCollection
};
+19 -19
View File
@@ -1,22 +1,22 @@
import './fiveLayer.js';
import './heroFourFrames.js';
import './hotReload.js';
import './itemDetail.js';
import './popup.js';
import './replay.js';
import './ui.js';
import * as halo from './halo.js';
import * as hero from './hero.js';
import * as loopMap from './loopMap.js';
import * as remainEnemy from './remainEnemy.js';
import * as removeMap from './removeMap.js';
import * as shop from './shop.js';
import * as skill from './skills.js';
import * as skillTree from './skillTree.js';
import * as study from './study.js';
import * as towerBoss from './towerBoss.js';
import * as utils from './utils.js';
import * as chase from './chase.js';
import './fiveLayer';
import './heroFourFrames';
import './hotReload';
import './itemDetail';
import './popup';
import './replay';
import './ui';
import * as halo from './halo';
import * as hero from './hero';
import * as loopMap from './loopMap';
import * as remainEnemy from './remainEnemy';
import * as removeMap from './removeMap';
import * as shop from './shop';
import * as skill from './skills';
import * as skillTree from './skillTree';
import * as study from './study';
import * as towerBoss from './towerBoss';
import * as utils from './utils';
import * as chase from './chase';
import * as damage from './damage';
export {
+100
View File
@@ -0,0 +1,100 @@
type RangeScanFn<C extends Partial<Loc>> = (
collection: Range<C>,
data: any
) => C[];
type InRangeFn<C extends Partial<Loc>> = (
collection: Range<C>,
data: any,
item: Partial<Loc>
) => boolean;
interface RangeType<C extends Partial<Loc>> {
scan: RangeScanFn<C>;
inRange: InRangeFn<C>;
}
export interface RangeCollection<I extends Partial<Loc>> {
list: I[];
range: Range<I>;
}
export class Range<C extends Partial<Loc>> {
collection: RangeCollection<C>;
cache: Record<string, any> = {};
static rangeType: Record<string, RangeType<Partial<Loc>>> = {};
constructor(collection: RangeCollection<C>) {
this.collection = collection;
}
/**
* 扫描 collection 中在范围内的物品
* @param type 范围类型
* @param data 范围数据
* @returns 在范围内的物品列表
*/
scan(type: string, data: any): C[] {
const t = Range.rangeType[type];
if (!t) {
throw new Error(`Unknown range type: ${type}.`);
}
return t.scan(this, data) as C[];
}
inRange(type: string, data: any, item: Partial<Loc>) {
const t = Range.rangeType[type];
if (!t) {
throw new Error(`Unknown range type: ${type}.`);
}
return t.inRange(this, data, item);
}
clearCache() {
this.cache = {};
}
static registerRangeType(
type: string,
scan: RangeScanFn<Partial<Loc>>,
inRange: InRangeFn<Partial<Loc>>
) {
Range.rangeType[type] = {
scan,
inRange
};
}
}
// ----- 默认的范围类型
// 方形区域
Range.registerRangeType(
'square',
(col, { x, y, d }) => {
const cache = (col.cache.square ??= {});
const index = `${x},${y},${d}`;
if (index in cache) return cache[index];
const list = col.collection.list;
const r = Math.floor(d);
return (cache[index] = list.filter(v => {
return (
core.has(v.x) &&
core.has(v.y) &&
Math.abs(v.x - x) <= r &&
Math.abs(v.y - y) <= r
);
}));
},
(col, { x, y, d }, item) => {
const r = Math.floor(d / 2);
return (
core.has(item.x) &&
core.has(item.y) &&
Math.abs(item.x - x) <= r &&
Math.abs(item.y - y) <= r
);
}
);
@@ -2,10 +2,10 @@
/**
* 滑动数组
* @param {any[]} arr
* @param {number} delta
* @param arr
* @param delta
*/
export function slide(arr, delta) {
export function slide<T>(arr: T[], delta: number): T[] {
if (delta === 0) return arr;
delta %= arr.length;
if (delta > 0) {
@@ -16,27 +16,29 @@ export function slide(arr, delta) {
arr.push(...arr.splice(0, -delta));
return arr;
}
return arr;
}
export function backDir(dir) {
export function backDir(dir: Dir): Dir {
return {
up: 'down',
down: 'up',
left: 'right',
right: 'left'
}[dir];
}[dir] as Dir;
}
export function has(v) {
export function has<T>(v: T): v is NonNullable<T> {
return v !== null && v !== void 0;
}
export function maxGameScale(n = 0) {
export function maxGameScale(n: number = 0) {
const index = core.domStyle.availableScale.indexOf(core.domStyle.scale);
core.control.setDisplayScale(
core.domStyle.availableScale.length - 1 - index - n
);
if (!core.isPlaying() && core.flags.enableHDCanvas) {
// @ts-ignore
core.domStyle.ratio = Math.max(
window.devicePixelRatio || 1,
core.domStyle.scale
@@ -45,6 +47,11 @@ export function maxGameScale(n = 0) {
}
}
export function ensureArray<T>(arr: T): T extends any[] ? T : T[] {
// @ts-ignore
return arr instanceof Array ? arr : [arr];
}
core.plugin.utils = {
slide,
backDir,