mirror of
https://github.com/motajs/template.git
synced 2026-10-14 08:40:16 +08:00
feat: 特殊光环描述
This commit is contained in:
parent
a2dd4ace72
commit
77a8adc05d
@ -13,10 +13,8 @@ import { isNil } from 'lodash-es';
|
||||
|
||||
export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
/** 特殊属性注册表,code -> 创建函数 */
|
||||
private readonly specialRegistry: Map<
|
||||
number,
|
||||
SpecialCreation<any, TEnemy>
|
||||
> = new Map();
|
||||
private readonly specialRegistry: Map<number, SpecialCreation<any>> =
|
||||
new Map();
|
||||
/** 怪物模板表,code -> IEnemy */
|
||||
private readonly prefabByCode: Map<number, IEnemy<TEnemy>> = new Map();
|
||||
/** 复用映射,reusedCode -> sourceCode */
|
||||
@ -32,10 +30,14 @@ export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
|
||||
constructor(private readonly tileStore: ITileStore) {}
|
||||
|
||||
registerSpecial(code: number, cons: SpecialCreation<any, TEnemy>): void {
|
||||
registerSpecial(code: number, cons: SpecialCreation<any>): void {
|
||||
this.specialRegistry.set(code, cons);
|
||||
}
|
||||
|
||||
getSpecial(code: number): SpecialCreation<any> | null {
|
||||
return this.specialRegistry.get(code) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据怪物的图块数字或 id 获取其模板
|
||||
* @param token 怪物的图块数字或 id
|
||||
|
||||
@ -133,18 +133,18 @@ export class NonePropertySpecial implements ISpecial<void> {
|
||||
}
|
||||
}
|
||||
|
||||
export function defineCommonSerializableSpecial<T, TAttr = any>(
|
||||
export function defineCommonSerializableSpecial<T>(
|
||||
code: number,
|
||||
value: T,
|
||||
config: ICommonSpecialConfig<T>
|
||||
): SpecialCreation<T, TAttr> {
|
||||
): SpecialCreation<T> {
|
||||
return () =>
|
||||
new CommonSerializableSpecial(code, structuredClone(value), config);
|
||||
}
|
||||
|
||||
export function defineNonePropertySpecial<TAttr = any>(
|
||||
export function defineNonePropertySpecial(
|
||||
code: number,
|
||||
config: ICommonSpecialConfig<void>
|
||||
): SpecialCreation<void, TAttr> {
|
||||
): SpecialCreation<void> {
|
||||
return () => new NonePropertySpecial(code, config);
|
||||
}
|
||||
|
||||
@ -161,7 +161,7 @@ export interface IEnemy<TAttr>
|
||||
|
||||
//#region 怪物管理器
|
||||
|
||||
export type SpecialCreation<T, TAttr> = (enemy: IEnemy<TAttr>) => ISpecial<T>;
|
||||
export type SpecialCreation<T> = () => ISpecial<T>;
|
||||
|
||||
export interface IEnemyManager<TAttr> extends ISaveableContent<
|
||||
IEnemyManagerSaveState<TAttr>
|
||||
@ -171,7 +171,13 @@ export interface IEnemyManager<TAttr> extends ISaveableContent<
|
||||
* @param code 特殊属性代码
|
||||
* @param cons 特殊属性创建函数
|
||||
*/
|
||||
registerSpecial(code: number, cons: SpecialCreation<any, TAttr>): void;
|
||||
registerSpecial(code: number, cons: SpecialCreation<any>): void;
|
||||
|
||||
/**
|
||||
* 获取一个特殊属性的注册函数
|
||||
* @param code 特殊属性代码
|
||||
*/
|
||||
getSpecial(code: number): SpecialCreation<any> | null;
|
||||
|
||||
/**
|
||||
* 创建怪物对象,如果对应数字的怪物不存在则会返回 `null`
|
||||
|
||||
@ -204,8 +204,8 @@ function createPipelineSpecials(haloAtkBuff: number): ISpecial<any>[] {
|
||||
createSpecial<void>(17, undefined),
|
||||
createSpecial<number>(22, 7),
|
||||
createSpecial<ISpecial23Value>(25, {
|
||||
haloRange: 0,
|
||||
haloSquare: false,
|
||||
range: 0,
|
||||
square: false,
|
||||
hpBuff: 0,
|
||||
atkBuff: haloAtkBuff,
|
||||
defBuff: 0
|
||||
@ -256,8 +256,8 @@ describe('enemy combination stage 1 - component baselines', () => {
|
||||
attrs: { atk: 20 },
|
||||
specials: [
|
||||
createSpecial<ISpecial23Value>(25, {
|
||||
haloRange: 0,
|
||||
haloSquare: false,
|
||||
range: 0,
|
||||
square: false,
|
||||
hpBuff: 0,
|
||||
atkBuff: 50,
|
||||
defBuff: 0
|
||||
@ -490,8 +490,8 @@ describe('enemy combination stage 2 - multi-special and system pipelines', () =>
|
||||
code: 25,
|
||||
specials: [
|
||||
createSpecial<ISpecial23Value>(25, {
|
||||
haloRange: 0,
|
||||
haloSquare: false,
|
||||
range: 0,
|
||||
square: false,
|
||||
hpBuff: 0,
|
||||
atkBuff: 50,
|
||||
defBuff: 0
|
||||
|
||||
@ -157,8 +157,8 @@ const MONSTER_PORTFOLIO: readonly IMonsterPrefab[] = [
|
||||
specials: [
|
||||
// haloRange 为 0 时 25 会落到 FullRange,即同楼层全体光环
|
||||
createSpecial<ISpecial23Value>(25, {
|
||||
haloRange: 0,
|
||||
haloSquare: false,
|
||||
range: 0,
|
||||
square: false,
|
||||
hpBuff: 0,
|
||||
atkBuff: 30,
|
||||
defBuff: 0
|
||||
@ -172,8 +172,8 @@ const MONSTER_PORTFOLIO: readonly IMonsterPrefab[] = [
|
||||
specials: [
|
||||
// 十字范围光环,让光环拓扑随怪物坐标变化而非全图连通
|
||||
createSpecial<ISpecial23Value>(25, {
|
||||
haloRange: 3,
|
||||
haloSquare: false,
|
||||
range: 3,
|
||||
square: false,
|
||||
hpBuff: 20,
|
||||
atkBuff: 0,
|
||||
defBuff: 0
|
||||
@ -187,8 +187,8 @@ const MONSTER_PORTFOLIO: readonly IMonsterPrefab[] = [
|
||||
specials: [
|
||||
// 九宫格范围光环,与十字范围共用同一转换器但走不同 range 实现
|
||||
createSpecial<ISpecial23Value>(25, {
|
||||
haloRange: 2,
|
||||
haloSquare: true,
|
||||
range: 2,
|
||||
square: true,
|
||||
hpBuff: 0,
|
||||
atkBuff: 0,
|
||||
defBuff: 25
|
||||
@ -212,7 +212,7 @@ const MONSTER_PORTFOLIO: readonly IMonsterPrefab[] = [
|
||||
specials: [
|
||||
createSpecial<ISpecial13Value>(15, {
|
||||
zone: 5,
|
||||
zoneSquare: false,
|
||||
square: false,
|
||||
range: 2
|
||||
})
|
||||
]
|
||||
@ -224,7 +224,7 @@ const MONSTER_PORTFOLIO: readonly IMonsterPrefab[] = [
|
||||
specials: [
|
||||
createSpecial<ISpecial13Value>(15, {
|
||||
zone: 8,
|
||||
zoneSquare: true,
|
||||
square: true,
|
||||
range: 1
|
||||
}),
|
||||
createSpecial<void>(2, undefined)
|
||||
|
||||
@ -182,8 +182,8 @@ function createWritableHandler(
|
||||
*/
|
||||
function createHalo(overrides: Partial<ISpecial23Value> = {}): ISpecial23Value {
|
||||
return {
|
||||
haloRange: 0,
|
||||
haloSquare: false,
|
||||
range: 0,
|
||||
square: false,
|
||||
hpBuff: 0,
|
||||
atkBuff: 0,
|
||||
defBuff: 0,
|
||||
@ -227,7 +227,7 @@ describe('CommonAura range', () => {
|
||||
const { enemy } = createEnemy();
|
||||
const aura = new modules.CommonAura(
|
||||
enemy,
|
||||
createSpecial(25, createHalo({ haloRange: 0 })),
|
||||
createSpecial(25, createHalo({ range: 0 })),
|
||||
{ x: 3, y: 4 }
|
||||
);
|
||||
|
||||
@ -240,7 +240,7 @@ describe('CommonAura range', () => {
|
||||
const { enemy } = createEnemy();
|
||||
const aura = new modules.CommonAura(
|
||||
enemy,
|
||||
createSpecial(25, createHalo({ haloRange: 2, haloSquare: true })),
|
||||
createSpecial(25, createHalo({ range: 2, square: true })),
|
||||
{ x: 3, y: 4 }
|
||||
);
|
||||
|
||||
@ -253,7 +253,7 @@ describe('CommonAura range', () => {
|
||||
const { enemy } = createEnemy();
|
||||
const aura = new modules.CommonAura(
|
||||
enemy,
|
||||
createSpecial(25, createHalo({ haloRange: 2, haloSquare: false })),
|
||||
createSpecial(25, createHalo({ range: 2, square: false })),
|
||||
{ x: 3, y: 4 }
|
||||
);
|
||||
|
||||
|
||||
@ -217,7 +217,7 @@ describe('ZoneDamageView', () => {
|
||||
it('builds a manhattan range and zone damage for a cross zone', () => {
|
||||
const special = createSpecial<ISpecial13Value>(15, {
|
||||
zone: 7,
|
||||
zoneSquare: false,
|
||||
square: false,
|
||||
range: 1
|
||||
});
|
||||
const view = new modules.ZoneDamageView(
|
||||
@ -237,7 +237,7 @@ describe('ZoneDamageView', () => {
|
||||
it('builds a rect range and zone damage for a square zone', () => {
|
||||
const special = createSpecial<ISpecial13Value>(15, {
|
||||
zone: 4,
|
||||
zoneSquare: true,
|
||||
square: true,
|
||||
range: 2
|
||||
});
|
||||
const view = new modules.ZoneDamageView(
|
||||
@ -257,7 +257,7 @@ describe('ZoneDamageView', () => {
|
||||
it('checks coordinates against the zone range', () => {
|
||||
const special = createSpecial<ISpecial13Value>(15, {
|
||||
zone: 7,
|
||||
zoneSquare: false,
|
||||
square: false,
|
||||
range: 1
|
||||
});
|
||||
const view = new modules.ZoneDamageView(
|
||||
|
||||
@ -147,8 +147,8 @@ describe('registerSpecials', () => {
|
||||
expect(halo.getDescription()).toContain('线性叠加。');
|
||||
|
||||
const value: ISpecial23Value = {
|
||||
haloRange: 2,
|
||||
haloSquare: true,
|
||||
range: 2,
|
||||
square: true,
|
||||
hpBuff: 10,
|
||||
atkBuff: 0,
|
||||
defBuff: 0
|
||||
|
||||
@ -63,7 +63,7 @@ export class CommonAura implements IEnemyAuraView<
|
||||
private createRange(): IRange<
|
||||
IRectRangeParam | IManhattanRangeParam | void
|
||||
> {
|
||||
const { haloRange, haloSquare } = this.special.value;
|
||||
const { range: haloRange, square: haloSquare } = this.special.value;
|
||||
if (haloRange <= 0) {
|
||||
return FULL_RANGE;
|
||||
}
|
||||
@ -71,7 +71,7 @@ export class CommonAura implements IEnemyAuraView<
|
||||
}
|
||||
|
||||
getRangeParam(): IRectRangeParam | IManhattanRangeParam | void {
|
||||
const { haloRange, haloSquare } = this.special.value;
|
||||
const { range: haloRange, square: haloSquare } = this.special.value;
|
||||
if (haloRange <= 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -93,11 +93,11 @@ export class ZoneDamageView extends BaseMapDamageView<
|
||||
}
|
||||
|
||||
getRange(): IRange<IRectRangeParam | IManhattanRangeParam> {
|
||||
return this.special.value.zoneSquare ? RECT_RANGE : MANHATTAN_RANGE;
|
||||
return this.special.value.square ? RECT_RANGE : MANHATTAN_RANGE;
|
||||
}
|
||||
|
||||
getRangeParam(): IRectRangeParam | IManhattanRangeParam {
|
||||
if (this.special.value.zoneSquare) {
|
||||
if (this.special.value.square) {
|
||||
return {
|
||||
h: this.special.value.range * 2 + 1,
|
||||
w: this.special.value.range * 2 + 1,
|
||||
|
||||
@ -3,7 +3,6 @@ import {
|
||||
defineNonePropertySpecial,
|
||||
SpecialCreation
|
||||
} from '@user/data-base';
|
||||
import { IEnemyAttr } from '@user/data-common';
|
||||
import { IStateSystem } from '@user/data-system';
|
||||
|
||||
// 重要!!!下面这一行的注释不要删
|
||||
@ -25,7 +24,7 @@ export interface ISpecial13Value {
|
||||
/** 领域伤害值 */
|
||||
zone: number;
|
||||
/** 矩形领域(true)还是十字形领域(false),当范围大于 1 时,十字型领域采用曼哈顿距离计算 */
|
||||
zoneSquare: boolean;
|
||||
square: boolean;
|
||||
/** 领域范围值 */
|
||||
range: number;
|
||||
}
|
||||
@ -38,11 +37,12 @@ export interface ISpecial21Value {
|
||||
defValue: number;
|
||||
}
|
||||
|
||||
/** 23 - 光环 */
|
||||
export interface ISpecial23Value {
|
||||
/** 光环范围值 */
|
||||
haloRange: number;
|
||||
range: number;
|
||||
/** 光环是矩形范围(true)还是十字型范围(false),当范围大于 1 时,十字型范围采用曼哈顿距离计算 */
|
||||
haloSquare: boolean;
|
||||
square: boolean;
|
||||
/** 生命值增加比例 */
|
||||
hpBuff: number;
|
||||
/** 攻击力增加比例 */
|
||||
@ -51,6 +51,18 @@ export interface ISpecial23Value {
|
||||
defBuff: number;
|
||||
}
|
||||
|
||||
/** 26 - 特殊光环 */
|
||||
export interface ISpecial26Value {
|
||||
/** 光环范围值 */
|
||||
range: number;
|
||||
/** 光环是矩形范围(true)还是十字型范围(false),当范围大于 1 时,十字型范围采用曼哈顿距离计算 */
|
||||
square: boolean;
|
||||
/** 当怪物受到多个特殊光环加成时,是乘算叠加(true),还是加算叠加(false) */
|
||||
mulAdd: boolean;
|
||||
/** 增加的特殊属性列表 */
|
||||
specials: [number, any][];
|
||||
}
|
||||
|
||||
// 重要!!!下面这一行的注释不要删
|
||||
//#endregion
|
||||
|
||||
@ -69,10 +81,10 @@ export interface ISpecial23Value {
|
||||
*/
|
||||
export function createSpecials(
|
||||
state: IStateSystem
|
||||
): ReadonlyMap<number, SpecialCreation<any, IEnemyAttr>> {
|
||||
): ReadonlyMap<number, SpecialCreation<any>> {
|
||||
const hero = state.hero;
|
||||
|
||||
const map = new Map<number, SpecialCreation<any, IEnemyAttr>>();
|
||||
const map = new Map<number, SpecialCreation<any>>();
|
||||
|
||||
// 注意,不需要参数的特殊属性,如先攻、魔攻、坚固这些纯机制,
|
||||
// 不需要一个数值来描述的特殊属性,使用 defineNonePropertySpecial 定义。
|
||||
@ -250,11 +262,11 @@ export function createSpecials(
|
||||
13,
|
||||
defineCommonSerializableSpecial<ISpecial13Value>(
|
||||
13,
|
||||
{ zone: 0, zoneSquare: false, range: 1 },
|
||||
{ zone: 0, square: false, range: 1 },
|
||||
{
|
||||
name: '领域',
|
||||
desc: special => {
|
||||
const { zone, zoneSquare, range } = special.value;
|
||||
const { zone, square: zoneSquare, range } = special.value;
|
||||
return `经过怪物周围${zoneSquare ? '九宫格' : '十字'}范围内${range}格时自动减生命${zone}点。`;
|
||||
},
|
||||
color: '#C677DD'
|
||||
@ -368,8 +380,8 @@ export function createSpecials(
|
||||
defineCommonSerializableSpecial<ISpecial23Value>(
|
||||
23,
|
||||
{
|
||||
haloRange: 0,
|
||||
haloSquare: false,
|
||||
range: 0,
|
||||
square: false,
|
||||
hpBuff: 0,
|
||||
atkBuff: 0,
|
||||
defBuff: 0
|
||||
@ -377,8 +389,13 @@ export function createSpecials(
|
||||
{
|
||||
name: '光环',
|
||||
desc: special => {
|
||||
const { haloRange, haloSquare, hpBuff, atkBuff, defBuff } =
|
||||
special.value;
|
||||
const {
|
||||
range: haloRange,
|
||||
square: haloSquare,
|
||||
hpBuff,
|
||||
atkBuff,
|
||||
defBuff
|
||||
} = special.value;
|
||||
let str = '';
|
||||
if (haloRange > 0) {
|
||||
if (haloSquare) {
|
||||
@ -420,14 +437,46 @@ export function createSpecials(
|
||||
// 25 - 捕捉
|
||||
map.set(
|
||||
25,
|
||||
defineNonePropertySpecial(27, {
|
||||
defineNonePropertySpecial(25, {
|
||||
name: '捕捉',
|
||||
desc: '当走到怪物十字范围内时会进行强制战斗。',
|
||||
color: '#C0DDBB'
|
||||
})
|
||||
);
|
||||
|
||||
// TODO: 26 - 特殊光环
|
||||
// 26 - 特殊光环
|
||||
map.set(
|
||||
26,
|
||||
defineCommonSerializableSpecial<ISpecial26Value>(
|
||||
26,
|
||||
{
|
||||
range: 0,
|
||||
square: false,
|
||||
mulAdd: false,
|
||||
specials: []
|
||||
},
|
||||
{
|
||||
name: '特殊光环',
|
||||
desc: special => {
|
||||
const { range, square, specials, mulAdd } = special.value;
|
||||
const prefix = `在怪物周围${square ? '正方形' : '十字'} ${range} 格范围内的怪物获得如下特殊属性,${mulAdd ? '乘算' : '加算'}叠加:\n`;
|
||||
const list: string[] = [];
|
||||
for (const [code, param] of specials) {
|
||||
const special = state.enemyManager.getSpecial(code)?.();
|
||||
if (!special) continue;
|
||||
special.setValue(param);
|
||||
const name = special.getSpecialName();
|
||||
const color = special.getNameColor();
|
||||
const desc = special.getDescription();
|
||||
const item = ` ${list.length + 1}. \\r[${color}]${name}\\r: ${desc}`;
|
||||
list.push(item);
|
||||
}
|
||||
return prefix + list.join('\n');
|
||||
},
|
||||
color: '#e945ff'
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// 重要!!!下面这一行的注释不要删
|
||||
//#endregion
|
||||
|
||||
Loading…
Reference in New Issue
Block a user