mirror of
https://github.com/motajs/template.git
synced 2026-05-20 09:11:10 +08:00
feat: IEnemyHandler 引入 IStateBase 成员
This commit is contained in:
parent
0da19e1697
commit
43ad3fd83e
@ -18,66 +18,73 @@ import { IReadonlyHeroAttribute } from '../hero';
|
|||||||
import { IEnemy, IReadonlyEnemy, ISpecial } from '../enemy';
|
import { IEnemy, IReadonlyEnemy, ISpecial } from '../enemy';
|
||||||
import { EnemyView } from './enemy';
|
import { EnemyView } from './enemy';
|
||||||
import { ILocationIndexer, MapLocIndexer } from '../common/indexer';
|
import { ILocationIndexer, MapLocIndexer } from '../common/indexer';
|
||||||
|
import { IStateBase } from '../types';
|
||||||
|
|
||||||
export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
export class EnemyContext<TEnemy, THero> implements IEnemyContext<
|
||||||
|
TEnemy,
|
||||||
|
THero
|
||||||
|
> {
|
||||||
/** 坐标索引 -> 怪物视图 */
|
/** 坐标索引 -> 怪物视图 */
|
||||||
private readonly enemyViewMap: Map<number, EnemyView<TAttr>> = new Map();
|
private readonly enemyViewMap: Map<number, EnemyView<TEnemy>> = new Map();
|
||||||
/** 坐标索引 -> 计算前怪物对象 */
|
/** 坐标索引 -> 计算前怪物对象 */
|
||||||
private readonly enemyMap: Map<number, IEnemy<TAttr>> = new Map();
|
private readonly enemyMap: Map<number, IEnemy<TEnemy>> = new Map();
|
||||||
/** 怪物视图 -> 坐标索引 */
|
/** 怪物视图 -> 坐标索引 */
|
||||||
private readonly locatorViewMap: Map<IEnemyView<TAttr>, number> = new Map();
|
private readonly locatorViewMap: Map<IEnemyView<TEnemy>, number> =
|
||||||
|
new Map();
|
||||||
/** 计算前怪物对象 -> 坐标索引 */
|
/** 计算前怪物对象 -> 坐标索引 */
|
||||||
private readonly locatorEnemyMap: Map<IEnemy<TAttr>, number> = new Map();
|
private readonly locatorEnemyMap: Map<IEnemy<TEnemy>, number> = new Map();
|
||||||
/** 计算后怪物对象 -> 怪物视图 */
|
/** 计算后怪物对象 -> 怪物视图 */
|
||||||
private readonly computedToView: Map<
|
private readonly computedToView: Map<
|
||||||
IReadonlyEnemy<TAttr>,
|
IReadonlyEnemy<TEnemy>,
|
||||||
EnemyView<TAttr>
|
EnemyView<TEnemy>
|
||||||
> = new Map();
|
> = new Map();
|
||||||
|
|
||||||
/** 当前已注册的光环转换器 */
|
/** 当前已注册的光环转换器 */
|
||||||
private readonly auraConverter: Set<IAuraConverter<TAttr, THero>> =
|
private readonly auraConverter: Set<IAuraConverter<TEnemy, THero>> =
|
||||||
new Set();
|
new Set();
|
||||||
/** 光环转换器是否启用 */
|
/** 光环转换器是否启用 */
|
||||||
private readonly converterStatus: Map<
|
private readonly converterStatus: Map<
|
||||||
IAuraConverter<TAttr, THero>,
|
IAuraConverter<TEnemy, THero>,
|
||||||
boolean
|
boolean
|
||||||
> = new Map();
|
> = new Map();
|
||||||
/** 所有已被转换的光环 */
|
/** 所有已被转换的光环 */
|
||||||
private readonly convertedAura: Map<ISpecial<any>, IAuraView<TAttr>> =
|
private readonly convertedAura: Map<ISpecial<any>, IAuraView<TEnemy>> =
|
||||||
new Map();
|
new Map();
|
||||||
|
|
||||||
/** 普通查询效果注册,特殊属性 -> 此特殊属性的查询效果列表,按照优先级从高到低排序 */
|
/** 普通查询效果注册,特殊属性 -> 此特殊属性的查询效果列表,按照优先级从高到低排序 */
|
||||||
private readonly commonQueryMap: Map<
|
private readonly commonQueryMap: Map<
|
||||||
number,
|
number,
|
||||||
IEnemyCommonQueryEffect<TAttr, THero>[]
|
IEnemyCommonQueryEffect<TEnemy, THero>[]
|
||||||
> = new Map();
|
> = new Map();
|
||||||
|
|
||||||
/** 特殊查询效果注册,特殊属性 -> 此特殊属性的特殊查询效果列表,按照优先级从高到低排序 */
|
/** 特殊查询效果注册,特殊属性 -> 此特殊属性的特殊查询效果列表,按照优先级从高到低排序 */
|
||||||
private readonly specialQueryEffects: Map<
|
private readonly specialQueryEffects: Map<
|
||||||
number,
|
number,
|
||||||
IEnemySpecialQueryEffect<TAttr, THero>[]
|
IEnemySpecialQueryEffect<TEnemy, THero>[]
|
||||||
> = new Map();
|
> = new Map();
|
||||||
|
|
||||||
/** 最终效果列表,按照优先级从高到低排列 */
|
/** 最终效果列表,按照优先级从高到低排列 */
|
||||||
private readonly finalEffects: IEnemyFinalEffect<TAttr, THero>[] = [];
|
private readonly finalEffects: IEnemyFinalEffect<TEnemy, THero>[] = [];
|
||||||
/** 添加的无来源全局光环列表 */
|
/** 添加的无来源全局光环列表 */
|
||||||
private readonly globalAuraList: Set<IAuraView<TAttr>> = new Set();
|
private readonly globalAuraList: Set<IAuraView<TEnemy>> = new Set();
|
||||||
/** 排序后的光环视图,视图优先级 -> 光环视图列表 */
|
/** 排序后的光环视图,视图优先级 -> 光环视图列表 */
|
||||||
private readonly sortedAura: Map<number, Set<IAuraView<TAttr>>> = new Map();
|
private readonly sortedAura: Map<number, Set<IAuraView<TEnemy>>> =
|
||||||
|
new Map();
|
||||||
|
|
||||||
/** 当怪物更新后,需要对上下文进行全量刷新的怪物列表 */
|
/** 当怪物更新后,需要对上下文进行全量刷新的怪物列表 */
|
||||||
private readonly needTotallyRefresh: Set<IEnemyView<TAttr>> = new Set();
|
private readonly needTotallyRefresh: Set<IEnemyView<TEnemy>> = new Set();
|
||||||
/** 所有实际查询了上下文的常规查询效果,这些怪物需要在上下文或其他怪物刷新时一并刷新 */
|
/** 所有实际查询了上下文的常规查询效果,这些怪物需要在上下文或其他怪物刷新时一并刷新 */
|
||||||
private readonly requestedCommonContext: Set<IEnemyView<TAttr>> = new Set();
|
private readonly requestedCommonContext: Set<IEnemyView<TEnemy>> =
|
||||||
|
new Set();
|
||||||
/** 所有需要被标记为脏的怪物 */
|
/** 所有需要被标记为脏的怪物 */
|
||||||
private readonly dirtyEnemy: Set<IEnemyView<TAttr>> = new Set();
|
private readonly dirtyEnemy: Set<IEnemyView<TEnemy>> = new Set();
|
||||||
|
|
||||||
/** 当前绑定的勇士属性对象 */
|
/** 当前绑定的勇士属性对象 */
|
||||||
private bindedHero: IReadonlyHeroAttribute<THero> | null = null;
|
private bindedHero: IReadonlyHeroAttribute<THero> | null = null;
|
||||||
/** 地图伤害对象 */
|
/** 地图伤害对象 */
|
||||||
private mapDamage: IMapDamage<TAttr, THero> | null = null;
|
private mapDamage: IMapDamage<TEnemy, THero> | null = null;
|
||||||
/** 伤害系统对象 */
|
/** 伤害系统对象 */
|
||||||
private damageSystem: IDamageSystem<TAttr, THero> | null = null;
|
private damageSystem: IDamageSystem<TEnemy, THero> | null = null;
|
||||||
|
|
||||||
/** 索引工具 */
|
/** 索引工具 */
|
||||||
readonly indexer: ILocationIndexer = new MapLocIndexer();
|
readonly indexer: ILocationIndexer = new MapLocIndexer();
|
||||||
@ -89,6 +96,8 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
width: number = 0;
|
width: number = 0;
|
||||||
height: number = 0;
|
height: number = 0;
|
||||||
|
|
||||||
|
constructor(readonly dataState: IStateBase<TEnemy, THero>) {}
|
||||||
|
|
||||||
resize(width: number, height: number): void {
|
resize(width: number, height: number): void {
|
||||||
this.clear();
|
this.clear();
|
||||||
this.width = width;
|
this.width = width;
|
||||||
@ -97,20 +106,20 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
this.needUpdate = true;
|
this.needUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
registerAuraConverter(converter: IAuraConverter<TAttr, THero>): void {
|
registerAuraConverter(converter: IAuraConverter<TEnemy, THero>): void {
|
||||||
this.auraConverter.add(converter);
|
this.auraConverter.add(converter);
|
||||||
this.converterStatus.set(converter, true);
|
this.converterStatus.set(converter, true);
|
||||||
this.needUpdate = true;
|
this.needUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unregisterAuraConverter(converter: IAuraConverter<TAttr, THero>): void {
|
unregisterAuraConverter(converter: IAuraConverter<TEnemy, THero>): void {
|
||||||
this.auraConverter.delete(converter);
|
this.auraConverter.delete(converter);
|
||||||
this.converterStatus.delete(converter);
|
this.converterStatus.delete(converter);
|
||||||
this.needUpdate = true;
|
this.needUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
setAuraConverterEnabled(
|
setAuraConverterEnabled(
|
||||||
converter: IAuraConverter<TAttr, THero>,
|
converter: IAuraConverter<TEnemy, THero>,
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
): void {
|
): void {
|
||||||
if (!this.auraConverter.has(converter)) return;
|
if (!this.auraConverter.has(converter)) return;
|
||||||
@ -120,7 +129,7 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
|
|
||||||
registerCommonQueryEffect(
|
registerCommonQueryEffect(
|
||||||
code: number,
|
code: number,
|
||||||
effect: IEnemyCommonQueryEffect<TAttr, THero>
|
effect: IEnemyCommonQueryEffect<TEnemy, THero>
|
||||||
): void {
|
): void {
|
||||||
const array = this.commonQueryMap.getOrInsert(code, []);
|
const array = this.commonQueryMap.getOrInsert(code, []);
|
||||||
array.push(effect);
|
array.push(effect);
|
||||||
@ -130,7 +139,7 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
|
|
||||||
unregisterCommonQueryEffect(
|
unregisterCommonQueryEffect(
|
||||||
code: number,
|
code: number,
|
||||||
effect: IEnemyCommonQueryEffect<TAttr, THero>
|
effect: IEnemyCommonQueryEffect<TEnemy, THero>
|
||||||
): void {
|
): void {
|
||||||
const array = this.commonQueryMap.get(code);
|
const array = this.commonQueryMap.get(code);
|
||||||
if (!array) return;
|
if (!array) return;
|
||||||
@ -141,7 +150,7 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
registerSpecialQueryEffect(
|
registerSpecialQueryEffect(
|
||||||
effect: IEnemySpecialQueryEffect<TAttr, THero>
|
effect: IEnemySpecialQueryEffect<TEnemy, THero>
|
||||||
): void {
|
): void {
|
||||||
const list = this.specialQueryEffects.getOrInsert(effect.priority, []);
|
const list = this.specialQueryEffects.getOrInsert(effect.priority, []);
|
||||||
list.push(effect);
|
list.push(effect);
|
||||||
@ -149,7 +158,7 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unregisterSpecialQueryEffect(
|
unregisterSpecialQueryEffect(
|
||||||
effect: IEnemySpecialQueryEffect<TAttr, THero>
|
effect: IEnemySpecialQueryEffect<TEnemy, THero>
|
||||||
): void {
|
): void {
|
||||||
const list = this.specialQueryEffects.get(effect.priority);
|
const list = this.specialQueryEffects.get(effect.priority);
|
||||||
if (!list) return;
|
if (!list) return;
|
||||||
@ -163,13 +172,13 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
this.needUpdate = true;
|
this.needUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
registerFinalEffect(effect: IEnemyFinalEffect<TAttr, THero>): void {
|
registerFinalEffect(effect: IEnemyFinalEffect<TEnemy, THero>): void {
|
||||||
this.finalEffects.push(effect);
|
this.finalEffects.push(effect);
|
||||||
this.finalEffects.sort((a, b) => b.priority - a.priority);
|
this.finalEffects.sort((a, b) => b.priority - a.priority);
|
||||||
this.needUpdate = true;
|
this.needUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unregisterFinalEffect(effect: IEnemyFinalEffect<TAttr, THero>): void {
|
unregisterFinalEffect(effect: IEnemyFinalEffect<TEnemy, THero>): void {
|
||||||
const index = this.finalEffects.indexOf(effect);
|
const index = this.finalEffects.indexOf(effect);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
this.finalEffects.splice(index, 1);
|
this.finalEffects.splice(index, 1);
|
||||||
@ -194,37 +203,39 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
* @param locator 怪物位置
|
* @param locator 怪物位置
|
||||||
*/
|
*/
|
||||||
private createHandler(
|
private createHandler(
|
||||||
enemy: IEnemy<TAttr>,
|
enemy: IEnemy<TEnemy>,
|
||||||
locator: ITileLocator
|
locator: ITileLocator
|
||||||
): IEnemyHandler<TAttr, THero> {
|
): IEnemyHandler<TEnemy, THero> {
|
||||||
return { enemy, locator, hero: this.bindedHero! };
|
return { enemy, locator, hero: this.bindedHero!, data: this.dataState };
|
||||||
}
|
}
|
||||||
|
|
||||||
getEnemyLocator(enemy: IEnemy<TAttr>): Readonly<ITileLocator> | null {
|
getEnemyLocator(enemy: IEnemy<TEnemy>): Readonly<ITileLocator> | null {
|
||||||
const index = this.locatorEnemyMap.get(enemy);
|
const index = this.locatorEnemyMap.get(enemy);
|
||||||
if (index === undefined) return null;
|
if (index === undefined) return null;
|
||||||
return this.indexer.indexToLocator(index);
|
return this.indexer.indexToLocator(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
getEnemyLocatorByView(
|
getEnemyLocatorByView(
|
||||||
view: IEnemyView<TAttr>
|
view: IEnemyView<TEnemy>
|
||||||
): Readonly<ITileLocator> | null {
|
): Readonly<ITileLocator> | null {
|
||||||
const index = this.locatorViewMap.get(view);
|
const index = this.locatorViewMap.get(view);
|
||||||
if (index === undefined) return null;
|
if (index === undefined) return null;
|
||||||
return this.indexer.indexToLocator(index);
|
return this.indexer.indexToLocator(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
getEnemyByLocator(locator: ITileLocator): IEnemyView<TAttr> | null {
|
getEnemyByLocator(locator: ITileLocator): IEnemyView<TEnemy> | null {
|
||||||
const index = this.indexer.locToIndex(locator.x, locator.y);
|
const index = this.indexer.locToIndex(locator.x, locator.y);
|
||||||
return this.enemyViewMap.get(index) ?? null;
|
return this.enemyViewMap.get(index) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getEnemyByLoc(x: number, y: number): IEnemyView<TAttr> | null {
|
getEnemyByLoc(x: number, y: number): IEnemyView<TEnemy> | null {
|
||||||
const index = this.indexer.locToIndex(x, y);
|
const index = this.indexer.locToIndex(x, y);
|
||||||
return this.enemyViewMap.get(index) ?? null;
|
return this.enemyViewMap.get(index) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getViewByComputed(enemy: IReadonlyEnemy<TAttr>): IEnemyView<TAttr> | null {
|
getViewByComputed(
|
||||||
|
enemy: IReadonlyEnemy<TEnemy>
|
||||||
|
): IEnemyView<TEnemy> | null {
|
||||||
return this.computedToView.get(enemy) ?? null;
|
return this.computedToView.get(enemy) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,11 +267,11 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
this.locatorEnemyMap.delete(enemy);
|
this.locatorEnemyMap.delete(enemy);
|
||||||
}
|
}
|
||||||
|
|
||||||
setEnemyAt(locator: ITileLocator, enemy: IEnemy<TAttr>): void {
|
setEnemyAt(locator: ITileLocator, enemy: IEnemy<TEnemy>): void {
|
||||||
const index = this.indexer.locToIndex(locator.x, locator.y);
|
const index = this.indexer.locToIndex(locator.x, locator.y);
|
||||||
this.deleteEnemyAt(index);
|
this.deleteEnemyAt(index);
|
||||||
|
|
||||||
const view = new EnemyView<TAttr>(enemy, this);
|
const view = new EnemyView<TEnemy>(enemy, this);
|
||||||
this.enemyMap.set(index, enemy);
|
this.enemyMap.set(index, enemy);
|
||||||
this.enemyViewMap.set(index, view);
|
this.enemyViewMap.set(index, view);
|
||||||
this.locatorEnemyMap.set(enemy, index);
|
this.locatorEnemyMap.set(enemy, index);
|
||||||
@ -290,7 +301,7 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
private *internalScanRange<T>(
|
private *internalScanRange<T>(
|
||||||
range: IRange<T>,
|
range: IRange<T>,
|
||||||
param: T
|
param: T
|
||||||
): Iterable<[ITileLocator, EnemyView<TAttr>]> {
|
): Iterable<[ITileLocator, EnemyView<TEnemy>]> {
|
||||||
range.bindHost(this);
|
range.bindHost(this);
|
||||||
const keys = new Set(this.enemyViewMap.keys());
|
const keys = new Set(this.enemyViewMap.keys());
|
||||||
const matched = range.autoDetect(keys, param);
|
const matched = range.autoDetect(keys, param);
|
||||||
@ -307,46 +318,46 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
scanRange<T>(
|
scanRange<T>(
|
||||||
range: IRange<T>,
|
range: IRange<T>,
|
||||||
param: T
|
param: T
|
||||||
): Iterable<[ITileLocator, IEnemyView<TAttr>]> {
|
): Iterable<[ITileLocator, IEnemyView<TEnemy>]> {
|
||||||
return this.internalScanRange(range, param);
|
return this.internalScanRange(range, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
*iterateEnemy(): Iterable<[ITileLocator, IEnemyView<TAttr>]> {
|
*iterateEnemy(): Iterable<[ITileLocator, IEnemyView<TEnemy>]> {
|
||||||
for (const [index, view] of this.enemyViewMap) {
|
for (const [index, view] of this.enemyViewMap) {
|
||||||
const locator = this.indexer.indexToLocator(index);
|
const locator = this.indexer.indexToLocator(index);
|
||||||
yield [locator, view];
|
yield [locator, view];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addAura(aura: IAuraView<TAttr>): void {
|
addAura(aura: IAuraView<TEnemy>): void {
|
||||||
this.globalAuraList.add(aura);
|
this.globalAuraList.add(aura);
|
||||||
this.needUpdate = true;
|
this.needUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteAura(aura: IAuraView<TAttr>): void {
|
deleteAura(aura: IAuraView<TEnemy>): void {
|
||||||
this.globalAuraList.delete(aura);
|
this.globalAuraList.delete(aura);
|
||||||
this.needUpdate = true;
|
this.needUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
attachMapDamage(damage: IMapDamage<TAttr, THero> | null): void {
|
attachMapDamage(damage: IMapDamage<TEnemy, THero> | null): void {
|
||||||
this.mapDamage = damage;
|
this.mapDamage = damage;
|
||||||
if (damage) {
|
if (damage) {
|
||||||
damage.refreshAll();
|
damage.refreshAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getMapDamage(): IMapDamage<TAttr, THero> | null {
|
getMapDamage(): IMapDamage<TEnemy, THero> | null {
|
||||||
return this.mapDamage;
|
return this.mapDamage;
|
||||||
}
|
}
|
||||||
|
|
||||||
attachDamageSystem(system: IDamageSystem<TAttr, unknown> | null): void {
|
attachDamageSystem(system: IDamageSystem<TEnemy, THero> | null): void {
|
||||||
this.damageSystem = system;
|
this.damageSystem = system;
|
||||||
if (system) {
|
if (system) {
|
||||||
system.bindHeroStatus(this.bindedHero);
|
system.bindHeroStatus(this.bindedHero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getDamageSystem(): IDamageSystem<TAttr, THero> | null {
|
getDamageSystem(): IDamageSystem<TEnemy, THero> | null {
|
||||||
return this.damageSystem;
|
return this.damageSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,9 +369,9 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
*/
|
*/
|
||||||
private convertSpecial(
|
private convertSpecial(
|
||||||
special: ISpecial<any>,
|
special: ISpecial<any>,
|
||||||
handler: IReadonlyEnemyHandler<TAttr, THero>
|
handler: IReadonlyEnemyHandler<TEnemy, THero>
|
||||||
): IEnemyAuraView<TAttr, any, any> | null {
|
): IEnemyAuraView<TEnemy, any, any> | null {
|
||||||
let matched: IAuraConverter<TAttr, THero> | null = null;
|
let matched: IAuraConverter<TEnemy, THero> | null = null;
|
||||||
for (const converter of this.auraConverter) {
|
for (const converter of this.auraConverter) {
|
||||||
if (!this.converterStatus.get(converter)) continue;
|
if (!this.converterStatus.get(converter)) continue;
|
||||||
if (converter.shouldConvert(special, handler)) {
|
if (converter.shouldConvert(special, handler)) {
|
||||||
@ -380,7 +391,7 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
* 将光环按优先级插入到有序表中
|
* 将光环按优先级插入到有序表中
|
||||||
* @param aura 光环视图
|
* @param aura 光环视图
|
||||||
*/
|
*/
|
||||||
private insertIntoSortedAura(aura: IAuraView<TAttr>): void {
|
private insertIntoSortedAura(aura: IAuraView<TEnemy>): void {
|
||||||
const set = this.sortedAura.getOrInsertComputed(
|
const set = this.sortedAura.getOrInsertComputed(
|
||||||
aura.priority,
|
aura.priority,
|
||||||
() => new Set()
|
() => new Set()
|
||||||
@ -392,7 +403,7 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
* 从优先级表中移除一个光环
|
* 从优先级表中移除一个光环
|
||||||
* @param aura 光环视图
|
* @param aura 光环视图
|
||||||
*/
|
*/
|
||||||
private removeFromSortedAura(aura: IAuraView<TAttr>): void {
|
private removeFromSortedAura(aura: IAuraView<TEnemy>): void {
|
||||||
const set = this.sortedAura.get(aura.priority);
|
const set = this.sortedAura.get(aura.priority);
|
||||||
if (set) {
|
if (set) {
|
||||||
set.delete(aura);
|
set.delete(aura);
|
||||||
@ -410,12 +421,12 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
* @param currentPriority 当前处理的优先级
|
* @param currentPriority 当前处理的优先级
|
||||||
*/
|
*/
|
||||||
private processSpecialModifier(
|
private processSpecialModifier(
|
||||||
modifier: IEnemySpecialModifier<TAttr>,
|
modifier: IEnemySpecialModifier<TEnemy>,
|
||||||
handler: IEnemyHandler<TAttr, THero>,
|
handler: IEnemyHandler<TEnemy, THero>,
|
||||||
currentPriority: number
|
currentPriority: number
|
||||||
): Set<IAuraView<TAttr>> {
|
): Set<IAuraView<TEnemy>> {
|
||||||
const enemy = handler.enemy;
|
const enemy = handler.enemy;
|
||||||
const affectedAuras = new Set<IAuraView<TAttr>>();
|
const affectedAuras = new Set<IAuraView<TEnemy>>();
|
||||||
const toAdd = modifier.add(handler);
|
const toAdd = modifier.add(handler);
|
||||||
const toDelete = modifier.delete(handler);
|
const toDelete = modifier.delete(handler);
|
||||||
|
|
||||||
@ -487,7 +498,7 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
* @param currentPriority 当前处理的优先级
|
* @param currentPriority 当前处理的优先级
|
||||||
*/
|
*/
|
||||||
private processSpecialQuery(
|
private processSpecialQuery(
|
||||||
effect: IEnemySpecialQueryEffect<TAttr, THero>,
|
effect: IEnemySpecialQueryEffect<TEnemy, THero>,
|
||||||
currentPriority: number
|
currentPriority: number
|
||||||
): void {
|
): void {
|
||||||
const modifier = effect.for(this);
|
const modifier = effect.for(this);
|
||||||
@ -519,7 +530,7 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
* @param currentPriority 当前处理的优先级
|
* @param currentPriority 当前处理的优先级
|
||||||
*/
|
*/
|
||||||
private processAuraSpecial(
|
private processAuraSpecial(
|
||||||
aura: IAuraView<TAttr>,
|
aura: IAuraView<TEnemy>,
|
||||||
currentPriority: number
|
currentPriority: number
|
||||||
): void {
|
): void {
|
||||||
const param = aura.getRangeParam();
|
const param = aura.getRangeParam();
|
||||||
@ -694,7 +705,7 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
markDirty(view: IEnemyView<TAttr>): void {
|
markDirty(view: IEnemyView<TEnemy>): void {
|
||||||
if (!this.locatorViewMap.has(view)) return;
|
if (!this.locatorViewMap.has(view)) return;
|
||||||
this.dirtyEnemy.add(view);
|
this.dirtyEnemy.add(view);
|
||||||
if (this.damageSystem) {
|
if (this.damageSystem) {
|
||||||
@ -709,8 +720,8 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
* @param locator 怪物位置
|
* @param locator 怪物位置
|
||||||
*/
|
*/
|
||||||
private refreshSpecialModifier(
|
private refreshSpecialModifier(
|
||||||
modifier: IEnemySpecialModifier<TAttr>,
|
modifier: IEnemySpecialModifier<TEnemy>,
|
||||||
handler: IEnemyHandler<TAttr, THero>
|
handler: IEnemyHandler<TEnemy, THero>
|
||||||
): void {
|
): void {
|
||||||
const enemy = handler.enemy;
|
const enemy = handler.enemy;
|
||||||
const toAdd = modifier.add(handler);
|
const toAdd = modifier.add(handler);
|
||||||
@ -756,7 +767,7 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
* 刷新单个怪物视图的计算结果
|
* 刷新单个怪物视图的计算结果
|
||||||
* @param view 怪物视图
|
* @param view 怪物视图
|
||||||
*/
|
*/
|
||||||
private refreshEnemy(view: EnemyView<TAttr>): void {
|
private refreshEnemy(view: EnemyView<TEnemy>): void {
|
||||||
const locator = this.getEnemyLocatorByView(view);
|
const locator = this.getEnemyLocatorByView(view);
|
||||||
if (!locator) return;
|
if (!locator) return;
|
||||||
|
|
||||||
@ -851,7 +862,7 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
requestRefresh(view: IEnemyView<TAttr>): void {
|
requestRefresh(view: IEnemyView<TEnemy>): void {
|
||||||
if (!this.dirtyEnemy.has(view)) return;
|
if (!this.dirtyEnemy.has(view)) return;
|
||||||
if (this.needTotallyRefresh.has(view)) {
|
if (this.needTotallyRefresh.has(view)) {
|
||||||
this.needUpdate = true;
|
this.needUpdate = true;
|
||||||
@ -861,11 +872,11 @@ export class EnemyContext<TAttr, THero> implements IEnemyContext<TAttr, THero> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.refreshEnemy(view as EnemyView<TAttr>);
|
this.refreshEnemy(view as EnemyView<TEnemy>);
|
||||||
|
|
||||||
for (const requestedView of this.requestedCommonContext) {
|
for (const requestedView of this.requestedCommonContext) {
|
||||||
if (requestedView === view) continue;
|
if (requestedView === view) continue;
|
||||||
this.refreshEnemy(requestedView as EnemyView<TAttr>);
|
this.refreshEnemy(requestedView as EnemyView<TEnemy>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import {
|
|||||||
} from './types';
|
} from './types';
|
||||||
import { IHeroAttribute, IReadonlyHeroAttribute } from '../hero';
|
import { IHeroAttribute, IReadonlyHeroAttribute } from '../hero';
|
||||||
import { IReadonlyEnemy } from '../enemy';
|
import { IReadonlyEnemy } from '../enemy';
|
||||||
|
import { IStateBase } from '../types';
|
||||||
|
|
||||||
interface ICriticalSearchResult {
|
interface ICriticalSearchResult {
|
||||||
/** 此临界点的属性值 */
|
/** 此临界点的属性值 */
|
||||||
@ -21,20 +22,23 @@ interface ICriticalSearchResult {
|
|||||||
readonly info: IEnemyDamageInfo;
|
readonly info: IEnemyDamageInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DamageContext<TAttr, THero> implements IDamageContext<
|
export class DamageContext<TEnemy, THero> implements IDamageContext<
|
||||||
TAttr,
|
TEnemy,
|
||||||
THero
|
THero
|
||||||
> {
|
> {
|
||||||
/** 当前正在使用的计算器 */
|
/** 当前正在使用的计算器 */
|
||||||
protected calculator: IDamageCalculator<TAttr, THero> | null;
|
protected calculator: IDamageCalculator<TEnemy, THero> | null;
|
||||||
/** 当前勇士属性 */
|
/** 当前勇士属性 */
|
||||||
protected heroStatus: IReadonlyHeroAttribute<THero> | null;
|
protected heroStatus: IReadonlyHeroAttribute<THero> | null;
|
||||||
|
|
||||||
|
readonly dataState: IStateBase<TEnemy, THero>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
readonly context: IEnemyContext<TAttr, THero>,
|
readonly context: IEnemyContext<TEnemy, THero>,
|
||||||
calculator: IDamageCalculator<TAttr, THero> | null = null,
|
calculator: IDamageCalculator<TEnemy, THero> | null = null,
|
||||||
heroStatus: IReadonlyHeroAttribute<THero> | null = null
|
heroStatus: IReadonlyHeroAttribute<THero> | null = null
|
||||||
) {
|
) {
|
||||||
|
this.dataState = context.dataState;
|
||||||
this.calculator = calculator;
|
this.calculator = calculator;
|
||||||
this.heroStatus = heroStatus;
|
this.heroStatus = heroStatus;
|
||||||
}
|
}
|
||||||
@ -46,14 +50,14 @@ export class DamageContext<TAttr, THero> implements IDamageContext<
|
|||||||
* @param hero 勇士属性对象
|
* @param hero 勇士属性对象
|
||||||
*/
|
*/
|
||||||
private createReadonlyHandler(
|
private createReadonlyHandler(
|
||||||
enemy: IReadonlyEnemy<TAttr>,
|
enemy: IReadonlyEnemy<TEnemy>,
|
||||||
locator: ITileLocator,
|
locator: ITileLocator,
|
||||||
hero: IReadonlyHeroAttribute<THero>
|
hero: IReadonlyHeroAttribute<THero>
|
||||||
): IReadonlyEnemyHandler<TAttr, THero> {
|
): IReadonlyEnemyHandler<TEnemy, THero> {
|
||||||
return { enemy, locator, hero };
|
return { enemy, locator, hero, data: this.dataState };
|
||||||
}
|
}
|
||||||
|
|
||||||
getDamageInfo(enemy: IEnemyView<TAttr>): IEnemyDamageInfo | null {
|
getDamageInfo(enemy: IEnemyView<TEnemy>): IEnemyDamageInfo | null {
|
||||||
if (!this.heroStatus) {
|
if (!this.heroStatus) {
|
||||||
logger.warn(107);
|
logger.warn(107);
|
||||||
return null;
|
return null;
|
||||||
@ -73,7 +77,7 @@ export class DamageContext<TAttr, THero> implements IDamageContext<
|
|||||||
}
|
}
|
||||||
|
|
||||||
getDamageInfoByComputed(
|
getDamageInfoByComputed(
|
||||||
enemy: IReadonlyEnemy<TAttr>
|
enemy: IReadonlyEnemy<TEnemy>
|
||||||
): IEnemyDamageInfo | null {
|
): IEnemyDamageInfo | null {
|
||||||
if (!this.heroStatus) {
|
if (!this.heroStatus) {
|
||||||
logger.warn(107);
|
logger.warn(107);
|
||||||
@ -96,7 +100,7 @@ export class DamageContext<TAttr, THero> implements IDamageContext<
|
|||||||
}
|
}
|
||||||
|
|
||||||
*calculateCritical(
|
*calculateCritical(
|
||||||
view: IEnemyView<TAttr>,
|
view: IEnemyView<TEnemy>,
|
||||||
attribute: CriticalableHeroStatus<THero>,
|
attribute: CriticalableHeroStatus<THero>,
|
||||||
precision: number = 12
|
precision: number = 12
|
||||||
): Generator<IEnemyCritical, void, void> {
|
): Generator<IEnemyCritical, void, void> {
|
||||||
@ -168,7 +172,7 @@ export class DamageContext<TAttr, THero> implements IDamageContext<
|
|||||||
* @param maxIterations 最大迭代数量
|
* @param maxIterations 最大迭代数量
|
||||||
*/
|
*/
|
||||||
private findNextCritical(
|
private findNextCritical(
|
||||||
handler: IReadonlyEnemyHandler<TAttr, THero>,
|
handler: IReadonlyEnemyHandler<TEnemy, THero>,
|
||||||
hero: IHeroAttribute<THero>,
|
hero: IHeroAttribute<THero>,
|
||||||
attribute: CriticalableHeroStatus<THero>,
|
attribute: CriticalableHeroStatus<THero>,
|
||||||
currentValue: number,
|
currentValue: number,
|
||||||
@ -206,24 +210,24 @@ export class DamageContext<TAttr, THero> implements IDamageContext<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DamageSystem<TAttr, THero>
|
export class DamageSystem<TEnemy, THero>
|
||||||
extends DamageContext<TAttr, THero>
|
extends DamageContext<TEnemy, THero>
|
||||||
implements IDamageSystem<TAttr, THero>
|
implements IDamageSystem<TEnemy, THero>
|
||||||
{
|
{
|
||||||
/** 怪物伤害缓存 */
|
/** 怪物伤害缓存 */
|
||||||
private readonly cache: Map<IEnemyView<TAttr>, IEnemyDamageInfo> =
|
private readonly cache: Map<IEnemyView<TEnemy>, IEnemyDamageInfo> =
|
||||||
new Map();
|
new Map();
|
||||||
|
|
||||||
constructor(context: IEnemyContext<TAttr, THero>) {
|
constructor(context: IEnemyContext<TEnemy, THero>) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
useCalculator(calculator: IDamageCalculator<TAttr, THero>): void {
|
useCalculator(calculator: IDamageCalculator<TEnemy, THero>): void {
|
||||||
this.calculator = calculator;
|
this.calculator = calculator;
|
||||||
this.markAllDirty();
|
this.markAllDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
getCalculator(): IDamageCalculator<TAttr, THero> | null {
|
getCalculator(): IDamageCalculator<TEnemy, THero> | null {
|
||||||
return this.calculator;
|
return this.calculator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +236,7 @@ export class DamageSystem<TAttr, THero>
|
|||||||
this.markAllDirty();
|
this.markAllDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
getDamageInfo(enemy: IEnemyView<TAttr>): IEnemyDamageInfo | null {
|
getDamageInfo(enemy: IEnemyView<TEnemy>): IEnemyDamageInfo | null {
|
||||||
const cached = this.cache.get(enemy);
|
const cached = this.cache.get(enemy);
|
||||||
if (cached) {
|
if (cached) {
|
||||||
return cached;
|
return cached;
|
||||||
@ -246,7 +250,7 @@ export class DamageSystem<TAttr, THero>
|
|||||||
}
|
}
|
||||||
|
|
||||||
getDamageInfoByComputed(
|
getDamageInfoByComputed(
|
||||||
enemy: IReadonlyEnemy<TAttr>
|
enemy: IReadonlyEnemy<TEnemy>
|
||||||
): IEnemyDamageInfo | null {
|
): IEnemyDamageInfo | null {
|
||||||
const view = this.context.getViewByComputed(enemy);
|
const view = this.context.getViewByComputed(enemy);
|
||||||
if (view) {
|
if (view) {
|
||||||
@ -264,11 +268,11 @@ export class DamageSystem<TAttr, THero>
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
markDirty(enemy: IEnemyView<TAttr>): void {
|
markDirty(enemy: IEnemyView<TEnemy>): void {
|
||||||
this.cache.delete(enemy);
|
this.cache.delete(enemy);
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteEnemy(enemy: IEnemyView<TAttr>): void {
|
deleteEnemy(enemy: IEnemyView<TEnemy>): void {
|
||||||
this.cache.delete(enemy);
|
this.cache.delete(enemy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +280,7 @@ export class DamageSystem<TAttr, THero>
|
|||||||
this.cache.clear();
|
this.cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
with(hero: IHeroAttribute<THero>): IDamageContext<TAttr, THero> {
|
with(hero: IHeroAttribute<THero>): IDamageContext<TEnemy, THero> {
|
||||||
return new DamageContext(this.context, this.calculator, hero);
|
return new DamageContext(this.context, this.calculator, hero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import {
|
|||||||
IMapDamageView
|
IMapDamageView
|
||||||
} from './types';
|
} from './types';
|
||||||
import { ILocationHelper } from '../common/indexer';
|
import { ILocationHelper } from '../common/indexer';
|
||||||
|
import { IStateBase } from '../types';
|
||||||
|
|
||||||
interface IPointInfo {
|
interface IPointInfo {
|
||||||
/** 该点所有的地图伤害 */
|
/** 该点所有的地图伤害 */
|
||||||
@ -34,9 +35,9 @@ interface IDamageStore<TAttr> {
|
|||||||
readonly index: number;
|
readonly index: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MapDamage<TAttr, THero> implements IMapDamage<TAttr, THero> {
|
export class MapDamage<TEnemy, THero> implements IMapDamage<TEnemy, THero> {
|
||||||
/** 当前使用的地图伤害转换器 */
|
/** 当前使用的地图伤害转换器 */
|
||||||
private converter: IMapDamageConverter<TAttr, THero> | null = null;
|
private converter: IMapDamageConverter<TEnemy, THero> | null = null;
|
||||||
/** 当前使用的地图伤害合并器 */
|
/** 当前使用的地图伤害合并器 */
|
||||||
private reducer: IMapDamageReducer | null = null;
|
private reducer: IMapDamageReducer | null = null;
|
||||||
|
|
||||||
@ -45,14 +46,14 @@ export class MapDamage<TAttr, THero> implements IMapDamage<TAttr, THero> {
|
|||||||
/** 有来源地图伤害,坐标 -> 点伤害信息 */
|
/** 有来源地图伤害,坐标 -> 点伤害信息 */
|
||||||
private readonly sourcedDamage: Map<number, IPointInfo> = new Map();
|
private readonly sourcedDamage: Map<number, IPointInfo> = new Map();
|
||||||
/** 地图伤害视图 -> 其信息对象 */
|
/** 地图伤害视图 -> 其信息对象 */
|
||||||
private readonly viewStore: Map<IMapDamageView<any>, IViewStore<TAttr>> =
|
private readonly viewStore: Map<IMapDamageView<any>, IViewStore<TEnemy>> =
|
||||||
new Map();
|
new Map();
|
||||||
/** 地图伤害信息 -> 其信息对象 */
|
/** 地图伤害信息 -> 其信息对象 */
|
||||||
private readonly damageStore: Map<IMapDamageInfo, IDamageStore<TAttr>> =
|
private readonly damageStore: Map<IMapDamageInfo, IDamageStore<TEnemy>> =
|
||||||
new Map();
|
new Map();
|
||||||
/** 怪物视图 -> 其影响对象 */
|
/** 怪物视图 -> 其影响对象 */
|
||||||
private readonly enemyStore: Map<
|
private readonly enemyStore: Map<
|
||||||
IEnemyView<TAttr>,
|
IEnemyView<TEnemy>,
|
||||||
Set<IMapDamageView<any>>
|
Set<IMapDamageView<any>>
|
||||||
> = new Map();
|
> = new Map();
|
||||||
/** 需要延迟刷新的坐标索引 */
|
/** 需要延迟刷新的坐标索引 */
|
||||||
@ -63,11 +64,14 @@ export class MapDamage<TAttr, THero> implements IMapDamage<TAttr, THero> {
|
|||||||
/** 坐标索引对象 */
|
/** 坐标索引对象 */
|
||||||
private readonly indexer: ILocationHelper;
|
private readonly indexer: ILocationHelper;
|
||||||
|
|
||||||
constructor(readonly context: IEnemyContext<TAttr, THero>) {
|
readonly dataState: IStateBase<TEnemy, THero>;
|
||||||
|
|
||||||
|
constructor(readonly context: IEnemyContext<TEnemy, THero>) {
|
||||||
this.indexer = context.indexer;
|
this.indexer = context.indexer;
|
||||||
|
this.dataState = context.dataState;
|
||||||
}
|
}
|
||||||
|
|
||||||
useConverter(converter: IMapDamageConverter<TAttr, THero>): void {
|
useConverter(converter: IMapDamageConverter<TEnemy, THero>): void {
|
||||||
this.converter = converter;
|
this.converter = converter;
|
||||||
this.refreshAll();
|
this.refreshAll();
|
||||||
}
|
}
|
||||||
@ -78,15 +82,16 @@ export class MapDamage<TAttr, THero> implements IMapDamage<TAttr, THero> {
|
|||||||
* @param locator 怪物位置
|
* @param locator 怪物位置
|
||||||
*/
|
*/
|
||||||
private createReadonlyHandler(
|
private createReadonlyHandler(
|
||||||
view: IEnemyView<TAttr>,
|
view: IEnemyView<TEnemy>,
|
||||||
locator: ITileLocator
|
locator: ITileLocator
|
||||||
): IReadonlyEnemyHandler<TAttr, THero> | null {
|
): IReadonlyEnemyHandler<TEnemy, THero> | null {
|
||||||
const hero = this.context.getBindedHero();
|
const hero = this.context.getBindedHero();
|
||||||
if (!hero) return null;
|
if (!hero) return null;
|
||||||
return {
|
return {
|
||||||
enemy: view.getComputedEnemy(),
|
enemy: view.getComputedEnemy(),
|
||||||
locator,
|
locator,
|
||||||
hero
|
hero,
|
||||||
|
data: this.context.dataState
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +131,7 @@ export class MapDamage<TAttr, THero> implements IMapDamage<TAttr, THero> {
|
|||||||
this.markDirtyIndex(this.indexer.locaterToIndex(locator));
|
this.markDirtyIndex(this.indexer.locaterToIndex(locator));
|
||||||
}
|
}
|
||||||
|
|
||||||
markEnemyDirty(view: IEnemyView<TAttr>): void {
|
markEnemyDirty(view: IEnemyView<TEnemy>): void {
|
||||||
const store = this.enemyStore.get(view);
|
const store = this.enemyStore.get(view);
|
||||||
const locator = this.context.getEnemyLocatorByView(view);
|
const locator = this.context.getEnemyLocatorByView(view);
|
||||||
if (!store) {
|
if (!store) {
|
||||||
@ -141,7 +146,7 @@ export class MapDamage<TAttr, THero> implements IMapDamage<TAttr, THero> {
|
|||||||
this.refreshEnemyAndClearCache(view, locator);
|
this.refreshEnemyAndClearCache(view, locator);
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteEnemy(view: IEnemyView<TAttr>): void {
|
deleteEnemy(view: IEnemyView<TEnemy>): void {
|
||||||
const store = this.enemyStore.get(view);
|
const store = this.enemyStore.get(view);
|
||||||
if (!store) return;
|
if (!store) return;
|
||||||
const collection = new Set<number>();
|
const collection = new Set<number>();
|
||||||
@ -231,7 +236,7 @@ export class MapDamage<TAttr, THero> implements IMapDamage<TAttr, THero> {
|
|||||||
* 移除指定怪物所产生的地图伤害
|
* 移除指定怪物所产生的地图伤害
|
||||||
* @param view 怪物视图
|
* @param view 怪物视图
|
||||||
*/
|
*/
|
||||||
private removeEnemyAffecting(view: IEnemyView<TAttr>) {
|
private removeEnemyAffecting(view: IEnemyView<TEnemy>) {
|
||||||
const views = this.enemyStore.get(view);
|
const views = this.enemyStore.get(view);
|
||||||
if (!views) return;
|
if (!views) return;
|
||||||
views.forEach(viewItem => {
|
views.forEach(viewItem => {
|
||||||
@ -253,7 +258,7 @@ export class MapDamage<TAttr, THero> implements IMapDamage<TAttr, THero> {
|
|||||||
* 刷新指定位置的怪物地图伤害,并执行刷新缓存的操作
|
* 刷新指定位置的怪物地图伤害,并执行刷新缓存的操作
|
||||||
*/
|
*/
|
||||||
private refreshEnemyAndClearCache(
|
private refreshEnemyAndClearCache(
|
||||||
view: IEnemyView<TAttr>,
|
view: IEnemyView<TEnemy>,
|
||||||
locator: ITileLocator
|
locator: ITileLocator
|
||||||
) {
|
) {
|
||||||
this.removeEnemyAffecting(view);
|
this.removeEnemyAffecting(view);
|
||||||
@ -295,7 +300,7 @@ export class MapDamage<TAttr, THero> implements IMapDamage<TAttr, THero> {
|
|||||||
/**
|
/**
|
||||||
* 刷新指定位置的怪物地图伤害
|
* 刷新指定位置的怪物地图伤害
|
||||||
*/
|
*/
|
||||||
private refreshEnemy(view: IEnemyView<TAttr>, locator: ITileLocator) {
|
private refreshEnemy(view: IEnemyView<TEnemy>, locator: ITileLocator) {
|
||||||
this.removeEnemyAffecting(view);
|
this.removeEnemyAffecting(view);
|
||||||
if (!this.converter) return;
|
if (!this.converter) return;
|
||||||
const handler = this.createReadonlyHandler(view, locator);
|
const handler = this.createReadonlyHandler(view, locator);
|
||||||
|
|||||||
@ -2,34 +2,39 @@ import { ITileLocator, IRange } from '@motajs/common';
|
|||||||
import { IEnemy, IReadonlyEnemy, ISpecial } from '../enemy';
|
import { IEnemy, IReadonlyEnemy, ISpecial } from '../enemy';
|
||||||
import { IReadonlyHeroAttribute, IHeroAttribute } from '../hero';
|
import { IReadonlyHeroAttribute, IHeroAttribute } from '../hero';
|
||||||
import { ILocationHelper } from '../common/indexer';
|
import { ILocationHelper } from '../common/indexer';
|
||||||
|
import { IStateBase } from '../types';
|
||||||
|
|
||||||
//#region 辅助接口
|
//#region 辅助接口
|
||||||
|
|
||||||
export interface IEnemyHandler<TAttr, THero> {
|
export interface IEnemyHandler<TEnemy, THero> {
|
||||||
/** 怪物属性信息 */
|
/** 怪物属性信息 */
|
||||||
readonly enemy: IEnemy<TAttr>;
|
readonly enemy: IEnemy<TEnemy>;
|
||||||
/** 怪物定位符 */
|
/** 怪物定位符 */
|
||||||
readonly locator: ITileLocator;
|
readonly locator: ITileLocator;
|
||||||
/** 勇士属性信息 */
|
/** 勇士属性信息 */
|
||||||
readonly hero: IReadonlyHeroAttribute<THero>;
|
readonly hero: IReadonlyHeroAttribute<THero>;
|
||||||
|
/** 当前全局状态对象 */
|
||||||
|
readonly data: IStateBase<TEnemy, THero>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IReadonlyEnemyHandler<TAttr, THero> {
|
export interface IReadonlyEnemyHandler<TEnemy, THero> {
|
||||||
/** 怪物属性信息 */
|
/** 怪物属性信息 */
|
||||||
readonly enemy: IReadonlyEnemy<TAttr>;
|
readonly enemy: IReadonlyEnemy<TEnemy>;
|
||||||
/** 怪物定位符 */
|
/** 怪物定位符 */
|
||||||
readonly locator: ITileLocator;
|
readonly locator: ITileLocator;
|
||||||
/** 勇士属性信息 */
|
/** 勇士属性信息 */
|
||||||
readonly hero: IReadonlyHeroAttribute<THero>;
|
readonly hero: IReadonlyHeroAttribute<THero>;
|
||||||
|
/** 当前全局状态对象 */
|
||||||
|
readonly data: IStateBase<TEnemy, THero>;
|
||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region 怪物对象
|
//#region 怪物对象
|
||||||
|
|
||||||
export interface IEnemyView<TAttr> {
|
export interface IEnemyView<TEnemy> {
|
||||||
/** 怪物视图所属的上下文 */
|
/** 怪物视图所属的上下文 */
|
||||||
readonly context: IEnemyContext<TAttr, unknown>;
|
readonly context: IEnemyContext<TEnemy, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置此怪物视图的状态,将计算后怪物对象恢复至初始状态
|
* 重置此怪物视图的状态,将计算后怪物对象恢复至初始状态
|
||||||
@ -39,18 +44,18 @@ export interface IEnemyView<TAttr> {
|
|||||||
/**
|
/**
|
||||||
* 获取基本怪物对象
|
* 获取基本怪物对象
|
||||||
*/
|
*/
|
||||||
getBaseEnemy(): IReadonlyEnemy<TAttr>;
|
getBaseEnemy(): IReadonlyEnemy<TEnemy>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取计算后的怪物对象,返回的怪物对象同引用
|
* 获取计算后的怪物对象,返回的怪物对象同引用
|
||||||
*/
|
*/
|
||||||
getComputedEnemy(): IReadonlyEnemy<TAttr>;
|
getComputedEnemy(): IReadonlyEnemy<TEnemy>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取可修改的怪物对象。如果修改此方法获取的怪物对象,那么怪物的真实信息是不会刷新的,
|
* 获取可修改的怪物对象。如果修改此方法获取的怪物对象,那么怪物的真实信息是不会刷新的,
|
||||||
* 需要手动调用 markDirty 方法来刷新。
|
* 需要手动调用 markDirty 方法来刷新。
|
||||||
*/
|
*/
|
||||||
getModifiableEnemy(): IEnemy<TAttr>;
|
getModifiableEnemy(): IEnemy<TEnemy>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将此怪物标记为脏,需要更新
|
* 将此怪物标记为脏,需要更新
|
||||||
@ -62,18 +67,18 @@ export interface IEnemyView<TAttr> {
|
|||||||
|
|
||||||
//#region 光环与查询
|
//#region 光环与查询
|
||||||
|
|
||||||
export interface IEnemySpecialModifier<TAttr> {
|
export interface IEnemySpecialModifier<TEnemy> {
|
||||||
/**
|
/**
|
||||||
* 获取要添加到指定怪物身上的特殊属性
|
* 获取要添加到指定怪物身上的特殊属性
|
||||||
* @param handler 信息对象
|
* @param handler 信息对象
|
||||||
*/
|
*/
|
||||||
add(handler: IReadonlyEnemyHandler<TAttr, unknown>): ISpecial<any>[];
|
add(handler: IReadonlyEnemyHandler<TEnemy, unknown>): ISpecial<any>[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取制定怪物身上要删除的特殊属性
|
* 获取制定怪物身上要删除的特殊属性
|
||||||
* @param handler 信息对象
|
* @param handler 信息对象
|
||||||
*/
|
*/
|
||||||
delete(handler: IReadonlyEnemyHandler<TAttr, unknown>): ISpecial<any>[];
|
delete(handler: IReadonlyEnemyHandler<TEnemy, unknown>): ISpecial<any>[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改一个怪物的特殊属性,如果真正进行了修改则返回 true,否则返回 false
|
* 修改一个怪物的特殊属性,如果真正进行了修改则返回 true,否则返回 false
|
||||||
@ -81,16 +86,16 @@ export interface IEnemySpecialModifier<TAttr> {
|
|||||||
* @param special 要修改的怪物特殊属性
|
* @param special 要修改的怪物特殊属性
|
||||||
*/
|
*/
|
||||||
modify(
|
modify(
|
||||||
handler: IEnemyHandler<TAttr, unknown>,
|
handler: IEnemyHandler<TEnemy, unknown>,
|
||||||
special: ISpecial<any>
|
special: ISpecial<any>
|
||||||
): boolean;
|
): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAuraView<TAttr, T = any> {
|
export interface IAuraView<TEnemy, TRange = any> {
|
||||||
/** 此光环视图的优先级 */
|
/** 此光环视图的优先级 */
|
||||||
readonly priority: number;
|
readonly priority: number;
|
||||||
/** 此光环视图的影响范围 */
|
/** 此光环视图的影响范围 */
|
||||||
readonly range: IRange<T>;
|
readonly range: IRange<TRange>;
|
||||||
|
|
||||||
/** 这个光环视图是否有可能修改怪物的基本属性 */
|
/** 这个光环视图是否有可能修改怪物的基本属性 */
|
||||||
readonly couldApplyBase: boolean;
|
readonly couldApplyBase: boolean;
|
||||||
@ -100,7 +105,7 @@ export interface IAuraView<TAttr, T = any> {
|
|||||||
/**
|
/**
|
||||||
* 获取范围扫描参数
|
* 获取范围扫描参数
|
||||||
*/
|
*/
|
||||||
getRangeParam(): T;
|
getRangeParam(): TRange;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对指定怪物对象施加修饰器
|
* 对指定怪物对象施加修饰器
|
||||||
@ -108,8 +113,8 @@ export interface IAuraView<TAttr, T = any> {
|
|||||||
* @param baseEnemy 原始怪物对象,即未进行任何修改的怪物对象
|
* @param baseEnemy 原始怪物对象,即未进行任何修改的怪物对象
|
||||||
*/
|
*/
|
||||||
apply(
|
apply(
|
||||||
handler: IEnemyHandler<TAttr, unknown>,
|
handler: IEnemyHandler<TEnemy, unknown>,
|
||||||
baseEnemy: IReadonlyEnemy<TAttr>
|
baseEnemy: IReadonlyEnemy<TEnemy>
|
||||||
): void;
|
): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,21 +123,24 @@ export interface IAuraView<TAttr, T = any> {
|
|||||||
* @param baseEnemy 原始怪物对象,即未进行任何修改的怪物对象
|
* @param baseEnemy 原始怪物对象,即未进行任何修改的怪物对象
|
||||||
*/
|
*/
|
||||||
applySpecial(
|
applySpecial(
|
||||||
handler: IEnemyHandler<TAttr, unknown>,
|
handler: IEnemyHandler<TEnemy, unknown>,
|
||||||
baseEnemy: IReadonlyEnemy<TAttr>
|
baseEnemy: IReadonlyEnemy<TEnemy>
|
||||||
): IEnemySpecialModifier<TAttr> | null;
|
): IEnemySpecialModifier<TEnemy> | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEnemyAuraView<TAttr, R, S> extends IAuraView<TAttr, R> {
|
export interface IEnemyAuraView<TEnemy, TRange, TSpecial> extends IAuraView<
|
||||||
|
TEnemy,
|
||||||
|
TRange
|
||||||
|
> {
|
||||||
/** 此光环视图所属的怪物 */
|
/** 此光环视图所属的怪物 */
|
||||||
readonly enemy: IReadonlyEnemy<TAttr>;
|
readonly enemy: IReadonlyEnemy<TEnemy>;
|
||||||
/** 此光环视图所属的特殊属性 */
|
/** 此光环视图所属的特殊属性 */
|
||||||
readonly special: ISpecial<S>;
|
readonly special: ISpecial<TSpecial>;
|
||||||
/** 此光环视图所属怪物的定位符 */
|
/** 此光环视图所属怪物的定位符 */
|
||||||
readonly locator: ITileLocator;
|
readonly locator: ITileLocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAuraConverter<TAttr, THero> {
|
export interface IAuraConverter<TEnemy, THero> {
|
||||||
/**
|
/**
|
||||||
* 判断一个特殊属性是否应该被当前光环转换器执行转换
|
* 判断一个特殊属性是否应该被当前光环转换器执行转换
|
||||||
* @param special 要转换的特殊属性
|
* @param special 要转换的特殊属性
|
||||||
@ -140,7 +148,7 @@ export interface IAuraConverter<TAttr, THero> {
|
|||||||
*/
|
*/
|
||||||
shouldConvert(
|
shouldConvert(
|
||||||
special: ISpecial<any>,
|
special: ISpecial<any>,
|
||||||
handler: IReadonlyEnemyHandler<TAttr, THero>
|
handler: IReadonlyEnemyHandler<TEnemy, THero>
|
||||||
): boolean;
|
): boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -148,22 +156,22 @@ export interface IAuraConverter<TAttr, THero> {
|
|||||||
*/
|
*/
|
||||||
convert(
|
convert(
|
||||||
special: ISpecial<any>,
|
special: ISpecial<any>,
|
||||||
handler: IReadonlyEnemyHandler<TAttr, THero>,
|
handler: IReadonlyEnemyHandler<TEnemy, THero>,
|
||||||
context: IEnemyContext<TAttr, THero>
|
context: IEnemyContext<TEnemy, THero>
|
||||||
): IEnemyAuraView<TAttr, any, any>;
|
): IEnemyAuraView<TEnemy, any, any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEnemySpecialQueryModifier<
|
export interface IEnemySpecialQueryModifier<
|
||||||
TAttr,
|
TEnemy,
|
||||||
THero
|
THero
|
||||||
> extends IEnemySpecialModifier<TAttr> {
|
> extends IEnemySpecialModifier<TEnemy> {
|
||||||
/**
|
/**
|
||||||
* 判断一个怪物是否应该查询外部状态
|
* 判断一个怪物是否应该查询外部状态
|
||||||
*/
|
*/
|
||||||
shouldQuery(handler: IReadonlyEnemyHandler<TAttr, THero>): boolean;
|
shouldQuery(handler: IReadonlyEnemyHandler<TEnemy, THero>): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEnemySpecialQueryEffect<TAttr, THero> {
|
export interface IEnemySpecialQueryEffect<TEnemy, THero> {
|
||||||
/** 效果优先级,与光环属性共用 */
|
/** 效果优先级,与光环属性共用 */
|
||||||
readonly priority: number;
|
readonly priority: number;
|
||||||
|
|
||||||
@ -171,11 +179,11 @@ export interface IEnemySpecialQueryEffect<TAttr, THero> {
|
|||||||
* 根据传入的怪物上下文,获取对应的怪物特殊属性修饰器
|
* 根据传入的怪物上下文,获取对应的怪物特殊属性修饰器
|
||||||
*/
|
*/
|
||||||
for(
|
for(
|
||||||
ctx: IEnemyContext<TAttr, THero>
|
ctx: IEnemyContext<TEnemy, THero>
|
||||||
): IEnemySpecialQueryModifier<TAttr, THero>;
|
): IEnemySpecialQueryModifier<TEnemy, THero>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEnemyCommonQueryEffect<TAttr, THero> {
|
export interface IEnemyCommonQueryEffect<TEnemy, THero> {
|
||||||
/** 优先级,越高的越先执行 */
|
/** 优先级,越高的越先执行 */
|
||||||
readonly priority: number;
|
readonly priority: number;
|
||||||
|
|
||||||
@ -183,20 +191,20 @@ export interface IEnemyCommonQueryEffect<TAttr, THero> {
|
|||||||
* 对怪物的某个特殊属性施加常规查询效果
|
* 对怪物的某个特殊属性施加常规查询效果
|
||||||
*/
|
*/
|
||||||
apply(
|
apply(
|
||||||
handler: IEnemyHandler<TAttr, THero>,
|
handler: IEnemyHandler<TEnemy, THero>,
|
||||||
special: ISpecial<any>,
|
special: ISpecial<any>,
|
||||||
query: () => IEnemyContext<TAttr, THero>
|
query: () => IEnemyContext<TEnemy, THero>
|
||||||
): void;
|
): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEnemyFinalEffect<TAttr, THero> {
|
export interface IEnemyFinalEffect<TEnemy, THero> {
|
||||||
/** 效果优先级,越高会越先被执行 */
|
/** 效果优先级,越高会越先被执行 */
|
||||||
readonly priority: number;
|
readonly priority: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 向怪物施加最终修饰效果
|
* 向怪物施加最终修饰效果
|
||||||
*/
|
*/
|
||||||
apply(handler: IEnemyHandler<TAttr, THero>): void;
|
apply(handler: IEnemyHandler<TEnemy, THero>): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
@ -245,13 +253,13 @@ export interface IMapDamageView<T = any> {
|
|||||||
): Readonly<IMapDamageInfo> | null;
|
): Readonly<IMapDamageInfo> | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IMapDamageConverter<TAttr, THero> {
|
export interface IMapDamageConverter<TEnemy, THero> {
|
||||||
/**
|
/**
|
||||||
* 转换地图伤害视图
|
* 转换地图伤害视图
|
||||||
*/
|
*/
|
||||||
convert(
|
convert(
|
||||||
handler: IReadonlyEnemyHandler<TAttr, THero>,
|
handler: IReadonlyEnemyHandler<TEnemy, THero>,
|
||||||
context: IEnemyContext<TAttr, THero>
|
context: IEnemyContext<TEnemy, THero>
|
||||||
): IMapDamageView<any>[];
|
): IMapDamageView<any>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,15 +273,17 @@ export interface IMapDamageReducer {
|
|||||||
): Readonly<IMapDamageInfo>;
|
): Readonly<IMapDamageInfo>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IMapDamage<TAttr, THero> {
|
export interface IMapDamage<TEnemy, THero> {
|
||||||
/** 当前绑定的怪物上下文 */
|
/** 当前绑定的怪物上下文 */
|
||||||
readonly context: IEnemyContext<TAttr, THero>;
|
readonly context: IEnemyContext<TEnemy, THero>;
|
||||||
|
/** 地图伤害系统绑定的全局状态对象 */
|
||||||
|
readonly dataState: IStateBase<TEnemy, THero>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置地图伤害转换器,并基于当前上下文重建所有地图伤害视图
|
* 设置地图伤害转换器,并基于当前上下文重建所有地图伤害视图
|
||||||
* @param converter 地图伤害转换器
|
* @param converter 地图伤害转换器
|
||||||
*/
|
*/
|
||||||
useConverter(converter: IMapDamageConverter<TAttr, THero>): void;
|
useConverter(converter: IMapDamageConverter<TEnemy, THero>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置地图伤害合并器
|
* 设置地图伤害合并器
|
||||||
@ -305,7 +315,7 @@ export interface IMapDamage<TAttr, THero> {
|
|||||||
* 将指定怪物对应的地图伤害标记为脏并刷新
|
* 将指定怪物对应的地图伤害标记为脏并刷新
|
||||||
* @param view 怪物视图
|
* @param view 怪物视图
|
||||||
*/
|
*/
|
||||||
markEnemyDirty(view: IEnemyView<TAttr>): void;
|
markEnemyDirty(view: IEnemyView<TEnemy>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基于当前上下文重新刷新全部有来源地图伤害
|
* 基于当前上下文重新刷新全部有来源地图伤害
|
||||||
@ -316,7 +326,7 @@ export interface IMapDamage<TAttr, THero> {
|
|||||||
* 删除指定怪物带来的全部地图伤害来源
|
* 删除指定怪物带来的全部地图伤害来源
|
||||||
* @param view 怪物视图
|
* @param view 怪物视图
|
||||||
*/
|
*/
|
||||||
deleteEnemy(view: IEnemyView<TAttr>): void;
|
deleteEnemy(view: IEnemyView<TEnemy>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取指定位置合并后的地图伤害
|
* 获取指定位置合并后的地图伤害
|
||||||
@ -363,12 +373,12 @@ export type CriticalableHeroStatus<THero> = keyof {
|
|||||||
[P in keyof THero as THero[P] extends number ? P : never]: number;
|
[P in keyof THero as THero[P] extends number ? P : never]: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface IDamageCalculator<TAttr, THero> {
|
export interface IDamageCalculator<TEnemy, THero> {
|
||||||
/**
|
/**
|
||||||
* 计算战斗伤害信息
|
* 计算战斗伤害信息
|
||||||
* @param handler 信息对象
|
* @param handler 信息对象
|
||||||
*/
|
*/
|
||||||
calculate(handler: IReadonlyEnemyHandler<TAttr, THero>): IEnemyDamageInfo;
|
calculate(handler: IReadonlyEnemyHandler<TEnemy, THero>): IEnemyDamageInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取临界计算的上界
|
* 获取临界计算的上界
|
||||||
@ -376,24 +386,27 @@ export interface IDamageCalculator<TAttr, THero> {
|
|||||||
* @param attribute 勇士的临界属性
|
* @param attribute 勇士的临界属性
|
||||||
*/
|
*/
|
||||||
getCriticalLimit(
|
getCriticalLimit(
|
||||||
handler: IReadonlyEnemyHandler<TAttr, THero>,
|
handler: IReadonlyEnemyHandler<TEnemy, THero>,
|
||||||
attribute: CriticalableHeroStatus<THero>
|
attribute: CriticalableHeroStatus<THero>
|
||||||
): number;
|
): number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDamageContext<TAttr, THero> {
|
export interface IDamageContext<TEnemy, THero> {
|
||||||
|
/** 伤害上下文所属的全局状态对象 */
|
||||||
|
readonly dataState: IStateBase<TEnemy, THero>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取战斗伤害信息
|
* 获取战斗伤害信息
|
||||||
* @param enemy 怪物视图
|
* @param enemy 怪物视图
|
||||||
*/
|
*/
|
||||||
getDamageInfo(enemy: IEnemyView<TAttr>): IEnemyDamageInfo | null;
|
getDamageInfo(enemy: IEnemyView<TEnemy>): IEnemyDamageInfo | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据怪物对象获取战斗伤害信息
|
* 根据怪物对象获取战斗伤害信息
|
||||||
* @param enemy 怪物对象
|
* @param enemy 怪物对象
|
||||||
*/
|
*/
|
||||||
getDamageInfoByComputed(
|
getDamageInfoByComputed(
|
||||||
enemy: IReadonlyEnemy<TAttr>
|
enemy: IReadonlyEnemy<TEnemy>
|
||||||
): IEnemyDamageInfo | null;
|
): IEnemyDamageInfo | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -403,29 +416,29 @@ export interface IDamageContext<TAttr, THero> {
|
|||||||
* @param precision 临界计算精度,表示会进行多少次二分计算,一般填写 `12-16` 之间的数即可,默认是 12
|
* @param precision 临界计算精度,表示会进行多少次二分计算,一般填写 `12-16` 之间的数即可,默认是 12
|
||||||
*/
|
*/
|
||||||
calculateCritical(
|
calculateCritical(
|
||||||
enemy: IEnemyView<TAttr>,
|
enemy: IEnemyView<TEnemy>,
|
||||||
attribute: CriticalableHeroStatus<THero>,
|
attribute: CriticalableHeroStatus<THero>,
|
||||||
precision?: number
|
precision?: number
|
||||||
): Generator<IEnemyCritical, void, void>;
|
): Generator<IEnemyCritical, void, void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDamageSystem<TAttr, THero> extends IDamageContext<
|
export interface IDamageSystem<TEnemy, THero> extends IDamageContext<
|
||||||
TAttr,
|
TEnemy,
|
||||||
THero
|
THero
|
||||||
> {
|
> {
|
||||||
/** 伤害系统所属的上下文 */
|
/** 伤害系统所属的上下文 */
|
||||||
readonly context: IEnemyContext<TAttr, THero>;
|
readonly context: IEnemyContext<TEnemy, THero>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置当前伤害计算系统使用的伤害计算器
|
* 设置当前伤害计算系统使用的伤害计算器
|
||||||
* @param calculator 伤害计算器
|
* @param calculator 伤害计算器
|
||||||
*/
|
*/
|
||||||
useCalculator(calculator: IDamageCalculator<TAttr, THero>): void;
|
useCalculator(calculator: IDamageCalculator<TEnemy, THero>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前使用的伤害计算器
|
* 获取当前使用的伤害计算器
|
||||||
*/
|
*/
|
||||||
getCalculator(): IDamageCalculator<TAttr, THero> | null;
|
getCalculator(): IDamageCalculator<TEnemy, THero> | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绑定勇士信息
|
* 绑定勇士信息
|
||||||
@ -437,13 +450,13 @@ export interface IDamageSystem<TAttr, THero> extends IDamageContext<
|
|||||||
* 将指定的怪物标记为脏
|
* 将指定的怪物标记为脏
|
||||||
* @param enemy 怪物视图
|
* @param enemy 怪物视图
|
||||||
*/
|
*/
|
||||||
markDirty(enemy: IEnemyView<TAttr>): void;
|
markDirty(enemy: IEnemyView<TEnemy>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除指定的怪物
|
* 删除指定的怪物
|
||||||
* @param enemy 怪物视图
|
* @param enemy 怪物视图
|
||||||
*/
|
*/
|
||||||
deleteEnemy(enemy: IEnemyView<TAttr>): void;
|
deleteEnemy(enemy: IEnemyView<TEnemy>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将所有怪物标记为脏
|
* 将所有怪物标记为脏
|
||||||
@ -454,20 +467,22 @@ export interface IDamageSystem<TAttr, THero> extends IDamageContext<
|
|||||||
* 修改勇士属性,然后返回修改后勇士属性所组成的计算对象,不影响当前伤害系统的状态
|
* 修改勇士属性,然后返回修改后勇士属性所组成的计算对象,不影响当前伤害系统的状态
|
||||||
* @param modify 勇士修改函数
|
* @param modify 勇士修改函数
|
||||||
*/
|
*/
|
||||||
with(hero: IHeroAttribute<THero>): IDamageContext<TAttr, THero>;
|
with(hero: IHeroAttribute<THero>): IDamageContext<TEnemy, THero>;
|
||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region 上下文
|
//#region 上下文
|
||||||
|
|
||||||
export interface IEnemyContext<TAttr, THero> {
|
export interface IEnemyContext<TEnemy, THero> {
|
||||||
/** 怪物上下文宽度 */
|
/** 怪物上下文宽度 */
|
||||||
readonly width: number;
|
readonly width: number;
|
||||||
/** 怪物上下文高度 */
|
/** 怪物上下文高度 */
|
||||||
readonly height: number;
|
readonly height: number;
|
||||||
/** 此上下文使用的索引对象 */
|
/** 此上下文使用的索引对象 */
|
||||||
readonly indexer: ILocationHelper;
|
readonly indexer: ILocationHelper;
|
||||||
|
/** 当前怪物上下文绑定的全局状态对象 */
|
||||||
|
readonly dataState: IStateBase<TEnemy, THero>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 调整上下文尺寸,并清空当前上下文中的所有怪物与状态
|
* 调整上下文尺寸,并清空当前上下文中的所有怪物与状态
|
||||||
@ -480,13 +495,13 @@ export interface IEnemyContext<TAttr, THero> {
|
|||||||
* 注册一个光环转换器
|
* 注册一个光环转换器
|
||||||
* @param converter 光环转换器
|
* @param converter 光环转换器
|
||||||
*/
|
*/
|
||||||
registerAuraConverter(converter: IAuraConverter<TAttr, THero>): void;
|
registerAuraConverter(converter: IAuraConverter<TEnemy, THero>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注销一个光环转换器
|
* 注销一个光环转换器
|
||||||
* @param converter 光环转换器
|
* @param converter 光环转换器
|
||||||
*/
|
*/
|
||||||
unregisterAuraConverter(converter: IAuraConverter<TAttr, THero>): void;
|
unregisterAuraConverter(converter: IAuraConverter<TEnemy, THero>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置光环转换器的启用状态
|
* 设置光环转换器的启用状态
|
||||||
@ -494,7 +509,7 @@ export interface IEnemyContext<TAttr, THero> {
|
|||||||
* @param enabled 是否启用
|
* @param enabled 是否启用
|
||||||
*/
|
*/
|
||||||
setAuraConverterEnabled(
|
setAuraConverterEnabled(
|
||||||
converter: IAuraConverter<TAttr, THero>,
|
converter: IAuraConverter<TEnemy, THero>,
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
): void;
|
): void;
|
||||||
|
|
||||||
@ -503,7 +518,7 @@ export interface IEnemyContext<TAttr, THero> {
|
|||||||
* @param effect 特殊属性查询效果
|
* @param effect 特殊属性查询效果
|
||||||
*/
|
*/
|
||||||
registerSpecialQueryEffect(
|
registerSpecialQueryEffect(
|
||||||
effect: IEnemySpecialQueryEffect<TAttr, THero>
|
effect: IEnemySpecialQueryEffect<TEnemy, THero>
|
||||||
): void;
|
): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -511,7 +526,7 @@ export interface IEnemyContext<TAttr, THero> {
|
|||||||
* @param effect 特殊属性查询效果
|
* @param effect 特殊属性查询效果
|
||||||
*/
|
*/
|
||||||
unregisterSpecialQueryEffect(
|
unregisterSpecialQueryEffect(
|
||||||
effect: IEnemySpecialQueryEffect<TAttr, THero>
|
effect: IEnemySpecialQueryEffect<TEnemy, THero>
|
||||||
): void;
|
): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -521,7 +536,7 @@ export interface IEnemyContext<TAttr, THero> {
|
|||||||
*/
|
*/
|
||||||
registerCommonQueryEffect(
|
registerCommonQueryEffect(
|
||||||
code: number,
|
code: number,
|
||||||
effect: IEnemyCommonQueryEffect<TAttr, THero>
|
effect: IEnemyCommonQueryEffect<TEnemy, THero>
|
||||||
): void;
|
): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -531,20 +546,20 @@ export interface IEnemyContext<TAttr, THero> {
|
|||||||
*/
|
*/
|
||||||
unregisterCommonQueryEffect(
|
unregisterCommonQueryEffect(
|
||||||
code: number,
|
code: number,
|
||||||
effect: IEnemyCommonQueryEffect<TAttr, THero>
|
effect: IEnemyCommonQueryEffect<TEnemy, THero>
|
||||||
): void;
|
): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册一个最终效果
|
* 注册一个最终效果
|
||||||
* @param effect 最终效果
|
* @param effect 最终效果
|
||||||
*/
|
*/
|
||||||
registerFinalEffect(effect: IEnemyFinalEffect<TAttr, THero>): void;
|
registerFinalEffect(effect: IEnemyFinalEffect<TEnemy, THero>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注销一个最终效果
|
* 注销一个最终效果
|
||||||
* @param effect 最终效果
|
* @param effect 最终效果
|
||||||
*/
|
*/
|
||||||
unregisterFinalEffect(effect: IEnemyFinalEffect<TAttr, THero>): void;
|
unregisterFinalEffect(effect: IEnemyFinalEffect<TEnemy, THero>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绑定勇士对象
|
* 绑定勇士对象
|
||||||
@ -561,41 +576,41 @@ export interface IEnemyContext<TAttr, THero> {
|
|||||||
* 获取指定怪物对象当前所在位置
|
* 获取指定怪物对象当前所在位置
|
||||||
* @param enemy 怪物对象
|
* @param enemy 怪物对象
|
||||||
*/
|
*/
|
||||||
getEnemyLocator(enemy: IEnemy<TAttr>): Readonly<ITileLocator> | null;
|
getEnemyLocator(enemy: IEnemy<TEnemy>): Readonly<ITileLocator> | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取指定怪物视图当前所在位置
|
* 获取指定怪物视图当前所在位置
|
||||||
* @param view 怪物视图
|
* @param view 怪物视图
|
||||||
*/
|
*/
|
||||||
getEnemyLocatorByView(
|
getEnemyLocatorByView(
|
||||||
view: IEnemyView<TAttr>
|
view: IEnemyView<TEnemy>
|
||||||
): Readonly<ITileLocator> | null;
|
): Readonly<ITileLocator> | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据定位符获取怪物视图
|
* 根据定位符获取怪物视图
|
||||||
* @param locator 地图定位符
|
* @param locator 地图定位符
|
||||||
*/
|
*/
|
||||||
getEnemyByLocator(locator: ITileLocator): IEnemyView<TAttr> | null;
|
getEnemyByLocator(locator: ITileLocator): IEnemyView<TEnemy> | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据坐标获取怪物视图
|
* 根据坐标获取怪物视图
|
||||||
* @param x 横坐标
|
* @param x 横坐标
|
||||||
* @param y 纵坐标
|
* @param y 纵坐标
|
||||||
*/
|
*/
|
||||||
getEnemyByLoc(x: number, y: number): IEnemyView<TAttr> | null;
|
getEnemyByLoc(x: number, y: number): IEnemyView<TEnemy> | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据计算后怪物对象反查怪物视图
|
* 根据计算后怪物对象反查怪物视图
|
||||||
* @param enemy 计算后怪物对象
|
* @param enemy 计算后怪物对象
|
||||||
*/
|
*/
|
||||||
getViewByComputed(enemy: IReadonlyEnemy<TAttr>): IEnemyView<TAttr> | null;
|
getViewByComputed(enemy: IReadonlyEnemy<TEnemy>): IEnemyView<TEnemy> | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在指定位置放置一个怪物对象
|
* 在指定位置放置一个怪物对象
|
||||||
* @param locator 地图定位符
|
* @param locator 地图定位符
|
||||||
* @param enemy 怪物对象
|
* @param enemy 怪物对象
|
||||||
*/
|
*/
|
||||||
setEnemyAt(locator: ITileLocator, enemy: IEnemy<TAttr>): void;
|
setEnemyAt(locator: ITileLocator, enemy: IEnemy<TEnemy>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除指定位置的怪物
|
* 删除指定位置的怪物
|
||||||
@ -611,46 +626,46 @@ export interface IEnemyContext<TAttr, THero> {
|
|||||||
scanRange<T>(
|
scanRange<T>(
|
||||||
range: IRange<T>,
|
range: IRange<T>,
|
||||||
param: T
|
param: T
|
||||||
): Iterable<[ITileLocator, IEnemyView<TAttr>]>;
|
): Iterable<[ITileLocator, IEnemyView<TEnemy>]>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 迭代上下文中的全部怪物
|
* 迭代上下文中的全部怪物
|
||||||
*/
|
*/
|
||||||
iterateEnemy(): Iterable<[ITileLocator, IEnemyView<TAttr>]>;
|
iterateEnemy(): Iterable<[ITileLocator, IEnemyView<TEnemy>]>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加一个全局光环视图
|
* 添加一个全局光环视图
|
||||||
* @param aura 光环视图
|
* @param aura 光环视图
|
||||||
*/
|
*/
|
||||||
addAura(aura: IAuraView<TAttr>): void;
|
addAura(aura: IAuraView<TEnemy>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除一个全局光环视图
|
* 删除一个全局光环视图
|
||||||
* @param aura 光环视图
|
* @param aura 光环视图
|
||||||
*/
|
*/
|
||||||
deleteAura(aura: IAuraView<TAttr>): void;
|
deleteAura(aura: IAuraView<TEnemy>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绑定地图伤害管理器
|
* 绑定地图伤害管理器
|
||||||
* @param damage 地图伤害管理器
|
* @param damage 地图伤害管理器
|
||||||
*/
|
*/
|
||||||
attachMapDamage(damage: IMapDamage<TAttr, THero> | null): void;
|
attachMapDamage(damage: IMapDamage<TEnemy, THero> | null): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前绑定的地图伤害管理器
|
* 获取当前绑定的地图伤害管理器
|
||||||
*/
|
*/
|
||||||
getMapDamage(): IMapDamage<TAttr, THero> | null;
|
getMapDamage(): IMapDamage<TEnemy, THero> | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绑定伤害计算系统
|
* 绑定伤害计算系统
|
||||||
* @param system 伤害系统
|
* @param system 伤害系统
|
||||||
*/
|
*/
|
||||||
attachDamageSystem(system: IDamageSystem<TAttr, unknown> | null): void;
|
attachDamageSystem(system: IDamageSystem<TEnemy, unknown> | null): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前绑定的伤害计算系统
|
* 获取当前绑定的伤害计算系统
|
||||||
*/
|
*/
|
||||||
getDamageSystem(): IDamageSystem<TAttr, THero> | null;
|
getDamageSystem(): IDamageSystem<TEnemy, THero> | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重建当前上下文中的全部怪物计算结果
|
* 重建当前上下文中的全部怪物计算结果
|
||||||
@ -666,13 +681,13 @@ export interface IEnemyContext<TAttr, THero> {
|
|||||||
* 将指定怪物视图标记为脏
|
* 将指定怪物视图标记为脏
|
||||||
* @param view 怪物视图
|
* @param view 怪物视图
|
||||||
*/
|
*/
|
||||||
markDirty(view: IEnemyView<TAttr>): void;
|
markDirty(view: IEnemyView<TEnemy>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 申请刷新指定怪物视图
|
* 申请刷新指定怪物视图
|
||||||
* @param view 怪物视图
|
* @param view 怪物视图
|
||||||
*/
|
*/
|
||||||
requestRefresh(view: IEnemyView<TAttr>): void;
|
requestRefresh(view: IEnemyView<TEnemy>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清空当前上下文中的所有对象与运行状态
|
* 清空当前上下文中的所有对象与运行状态
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { logger } from '@motajs/common';
|
import { logger } from '@motajs/common';
|
||||||
|
import { SaveCompression } from '../common';
|
||||||
import { IEnemy, IEnemySaveState, IReadonlyEnemy, ISpecial } from './types';
|
import { IEnemy, IEnemySaveState, IReadonlyEnemy, ISpecial } from './types';
|
||||||
import { SaveCompression } from '../common/types';
|
|
||||||
|
|
||||||
export class Enemy<TAttr> implements IEnemy<TAttr> {
|
export class Enemy<TAttr> implements IEnemy<TAttr> {
|
||||||
/** 怪物身上的特殊属性列表 */
|
/** 怪物身上的特殊属性列表 */
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
import { SaveCompression } from '../common/types';
|
import { SaveCompression } from '../common';
|
||||||
import { ISpecial, SpecialCreation } from './types';
|
import { ISpecial, SpecialCreation } from './types';
|
||||||
|
|
||||||
// TODO: 颜色参数
|
// TODO: 颜色参数
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { ISaveableContent } from '../common/types';
|
import { ISaveableContent } from '../common';
|
||||||
|
|
||||||
//#region 怪物基础
|
//#region 怪物基础
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user