mirror of
https://github.com/motajs/template.git
synced 2026-07-17 17:31:15 +08:00
chore: 调整勇士相关接口
This commit is contained in:
parent
931f610d37
commit
abaa5206c5
@ -43,8 +43,11 @@ export abstract class BaseHeroModifier<T, V> implements IHeroModifier<T, V, V> {
|
||||
export class HeroAttribute<THero> implements IHeroAttribute<THero> {
|
||||
/** 当前勇士属性修饰器 */
|
||||
private readonly modifier: Map<keyof THero, IHeroModifier[]> = new Map();
|
||||
/** 当前每个修饰器对应的属性值 */
|
||||
private readonly modifierName: Map<IHeroModifier, keyof THero> = new Map();
|
||||
/** 当前每个修饰器对应的属性名称 */
|
||||
private readonly modifierName: Map<
|
||||
IHeroModifier<THero[keyof THero]>,
|
||||
keyof THero
|
||||
> = new Map();
|
||||
/** 当前勇士最终属性 */
|
||||
private readonly finalAttribute: THero;
|
||||
|
||||
@ -144,7 +147,7 @@ export class HeroAttribute<THero> implements IHeroAttribute<THero> {
|
||||
|
||||
addModifier<K extends keyof THero>(
|
||||
name: K,
|
||||
modifier: IHeroModifier<THero[K], unknown>
|
||||
modifier: IHeroModifier<THero[K]>
|
||||
): void {
|
||||
if (modifier.owner) {
|
||||
const modiferName = modifier.constructor.name;
|
||||
@ -181,7 +184,7 @@ export class HeroAttribute<THero> implements IHeroAttribute<THero> {
|
||||
this.recalculateAttribute(name);
|
||||
}
|
||||
|
||||
markModifierDirty(modifier: IHeroModifier): void {
|
||||
markModifierDirty(modifier: IHeroModifier<THero[keyof THero]>): void {
|
||||
const name = this.modifierName.get(modifier);
|
||||
if (name === undefined) return;
|
||||
this.markDirty(name);
|
||||
@ -210,9 +213,16 @@ export class HeroAttribute<THero> implements IHeroAttribute<THero> {
|
||||
return structuredClone(this.attribute);
|
||||
}
|
||||
|
||||
*iterateModifiers(): IterableIterator<[keyof THero, IHeroModifier]> {
|
||||
*iterateModifiers(): IterableIterator<[PropertyKey, IHeroModifier]> {
|
||||
for (const [modifier, name] of this.modifierName) {
|
||||
yield [name, modifier];
|
||||
}
|
||||
}
|
||||
|
||||
getModifiers<K extends keyof THero>(
|
||||
name: K
|
||||
): Iterable<IHeroModifier<THero[K]>> {
|
||||
const arr = this.modifier.get(name) as IHeroModifier<THero[K]>[];
|
||||
return arr ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,6 +65,7 @@ export class HeroFollower implements IHeroFollower {
|
||||
|
||||
saveState(compression: SaveCompression): IHeroFollowerSave {
|
||||
return {
|
||||
num: this.num,
|
||||
rendering: this.rendering.saveState(compression),
|
||||
location: this.location.saveState(compression)
|
||||
};
|
||||
|
||||
@ -1,39 +1,66 @@
|
||||
import { HeroAttribute } from './attribute';
|
||||
import { HeroFollowersController } from './followersController';
|
||||
import { HeroLocation } from './location';
|
||||
import { HeroRendering } from './rendering';
|
||||
import {
|
||||
IHeroAttribute,
|
||||
IHeroFollowersController,
|
||||
IHeroLocation,
|
||||
IHeroModifier,
|
||||
IHeroMoveController,
|
||||
IHeroRendering,
|
||||
IHeroState,
|
||||
IHeroStateSave,
|
||||
IModifierStateSave,
|
||||
IReadonlyHeroAttribute
|
||||
} from './types';
|
||||
import { SaveCompression } from '@user/data-common';
|
||||
import {
|
||||
FaceDirection,
|
||||
IDataCommon,
|
||||
IFaceHandler,
|
||||
SaveCompression
|
||||
} from '@user/data-common';
|
||||
import { IFacedTileLocator, logger } from '@motajs/common';
|
||||
|
||||
export class HeroState<THero> implements IHeroState<THero> {
|
||||
/** 修饰器工厂函数注册表 */
|
||||
private readonly registry: Map<string, () => IHeroModifier> = new Map();
|
||||
private readonly registry: Map<
|
||||
string,
|
||||
<K extends keyof THero>() => IHeroModifier<THero[K]>
|
||||
> = new Map();
|
||||
|
||||
readonly location: IHeroLocation;
|
||||
readonly rendering: IHeroRendering;
|
||||
readonly followers: IHeroFollowersController;
|
||||
|
||||
constructor(
|
||||
public mover: IHeroMoveController,
|
||||
state: IDataCommon,
|
||||
faceHandler: IFaceHandler<FaceDirection>,
|
||||
public attribute: IHeroAttribute<THero>
|
||||
) {}
|
||||
|
||||
attachMover(mover: IHeroMoveController): void {
|
||||
this.mover = mover;
|
||||
) {
|
||||
this.rendering = new HeroRendering(state);
|
||||
const defaultLoc: IFacedTileLocator = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
direction: FaceDirection.Down
|
||||
};
|
||||
this.location = new HeroLocation(state, defaultLoc, faceHandler);
|
||||
this.followers = new HeroFollowersController(
|
||||
state,
|
||||
this.location,
|
||||
faceHandler
|
||||
);
|
||||
}
|
||||
|
||||
attachAttribute(attribute: IHeroAttribute<THero>): void {
|
||||
this.attribute = attribute;
|
||||
}
|
||||
|
||||
getHeroMover(): IHeroMoveController {
|
||||
return this.mover;
|
||||
}
|
||||
|
||||
getLocation(): IFacedTileLocator {
|
||||
return this.mover;
|
||||
return {
|
||||
x: this.location.x,
|
||||
y: this.location.y,
|
||||
direction: this.location.mover.faceDirection
|
||||
};
|
||||
}
|
||||
|
||||
getModifiableAttribute(): IHeroAttribute<THero> {
|
||||
@ -48,7 +75,10 @@ export class HeroState<THero> implements IHeroState<THero> {
|
||||
return this.attribute.getModifiableClone();
|
||||
}
|
||||
|
||||
registerModifier(type: string, cons: () => IHeroModifier): void {
|
||||
registerModifier(
|
||||
type: string,
|
||||
cons: <K extends keyof THero>() => IHeroModifier<THero[K]>
|
||||
): void {
|
||||
this.registry.set(type, cons);
|
||||
}
|
||||
|
||||
@ -57,9 +87,8 @@ export class HeroState<THero> implements IHeroState<THero> {
|
||||
if (!cons) {
|
||||
logger.warn(116, type);
|
||||
return null;
|
||||
} else {
|
||||
return cons() as IHeroModifier<T, V>;
|
||||
}
|
||||
return cons() as IHeroModifier<T, V>;
|
||||
}
|
||||
|
||||
createAndInsertModifier<K extends keyof THero, V>(
|
||||
@ -73,22 +102,23 @@ export class HeroState<THero> implements IHeroState<THero> {
|
||||
}
|
||||
|
||||
saveState(compression: SaveCompression): IHeroStateSave<THero> {
|
||||
const modifiers: IModifierStateSave[] = [];
|
||||
const modifiers: IModifierStateSave<THero>[] = [];
|
||||
for (const [name, modifier] of this.attribute.iterateModifiers()) {
|
||||
modifiers.push({
|
||||
name,
|
||||
name: name as keyof THero,
|
||||
type: modifier.type,
|
||||
state: modifier.saveState(compression)
|
||||
});
|
||||
}
|
||||
const followerSaves = this.followers
|
||||
.getAllFollowers()
|
||||
.map(v => v.saveState(compression));
|
||||
|
||||
return {
|
||||
attribute: this.attribute.toStructured(),
|
||||
locator: {
|
||||
x: this.mover.x,
|
||||
y: this.mover.y,
|
||||
direction: this.mover.direction
|
||||
},
|
||||
followers: structuredClone(this.mover.followers),
|
||||
location: this.location.saveState(compression),
|
||||
rendering: this.rendering.saveState(compression),
|
||||
followers: followerSaves,
|
||||
modifiers
|
||||
};
|
||||
}
|
||||
@ -102,19 +132,16 @@ export class HeroState<THero> implements IHeroState<THero> {
|
||||
const cons = this.registry.get(save.type);
|
||||
if (!cons) continue;
|
||||
const modifier = cons();
|
||||
modifier.loadState(save.state as never, compression);
|
||||
newAttribute.addModifier(
|
||||
save.name as keyof THero,
|
||||
modifier as unknown as IHeroModifier<THero[keyof THero]>
|
||||
);
|
||||
modifier.loadState(save.state, compression);
|
||||
newAttribute.addModifier(save.name, modifier);
|
||||
}
|
||||
this.attribute = newAttribute;
|
||||
this.mover.setPosition(state.locator.x, state.locator.y);
|
||||
this.mover.turn(state.locator.direction);
|
||||
this.mover.removeAllFollowers();
|
||||
state.followers.forEach(follower => {
|
||||
this.mover.addFollower(follower.num, follower.identifier);
|
||||
this.mover.setFollowerAlpha(follower.identifier, follower.alpha);
|
||||
});
|
||||
this.location.loadState(state.location, compression);
|
||||
this.rendering.loadState(state.rendering, compression);
|
||||
void this.followers.removeAllFollowers();
|
||||
for (const save of state.followers) {
|
||||
const follower = this.followers.addFollower(save.num);
|
||||
follower.loadState(save, compression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,9 +9,9 @@ import {
|
||||
//#region 勇士属性
|
||||
|
||||
export interface IHeroModifier<
|
||||
K = unknown,
|
||||
V = unknown,
|
||||
Save = unknown
|
||||
H = unknown, // 属性值类型
|
||||
V = unknown, // 修饰器参数类型
|
||||
Save = unknown // 存档类型
|
||||
> extends ISaveableContent<Save> {
|
||||
/** 修饰器类型 */
|
||||
readonly type: string;
|
||||
@ -45,17 +45,17 @@ export interface IHeroModifier<
|
||||
* @param baseValue 该属性值的基础属性值
|
||||
* @param name 属性名称
|
||||
*/
|
||||
modify(value: K, baseValue: K, name: PropertyKey): K;
|
||||
modify(value: H, baseValue: H, name: PropertyKey): H;
|
||||
|
||||
/**
|
||||
* 深拷贝此修饰器
|
||||
*/
|
||||
clone(): IHeroModifier<K, V>;
|
||||
clone(): IHeroModifier<H, V>;
|
||||
}
|
||||
|
||||
export interface IModifierStateSave {
|
||||
export interface IModifierStateSave<THero> {
|
||||
/** 属性名称 */
|
||||
readonly name: PropertyKey;
|
||||
readonly name: keyof THero;
|
||||
/** 修饰器类型 */
|
||||
readonly type: string;
|
||||
/** 修饰器存档数据 */
|
||||
@ -107,6 +107,14 @@ export interface IReadonlyHeroAttribute<THero> {
|
||||
* 遍历所有已挂载的属性修饰器
|
||||
*/
|
||||
iterateModifiers(): Iterable<[PropertyKey, IHeroModifier]>;
|
||||
|
||||
/**
|
||||
* 获取指定属性名称的所有修饰器
|
||||
* @param name 属性名称
|
||||
*/
|
||||
getModifiers<K extends keyof THero>(
|
||||
name: K
|
||||
): Iterable<IHeroModifier<THero[K]>>;
|
||||
}
|
||||
|
||||
export interface IHeroAttribute<THero> extends IReadonlyHeroAttribute<THero> {
|
||||
@ -263,6 +271,8 @@ export interface IHeroRendering
|
||||
//#region 勇士跟随者
|
||||
|
||||
export interface IHeroFollowerSave {
|
||||
/** 跟随者图块数字 */
|
||||
readonly num: number;
|
||||
/** 跟随者渲染对象保存 */
|
||||
readonly rendering: IHeroRenderingSave;
|
||||
/** 跟随者位置保存 */
|
||||
@ -369,11 +379,13 @@ export interface IHeroStateSave<THero> {
|
||||
/** 勇士属性状态 */
|
||||
readonly attribute: THero;
|
||||
/** 勇士当前位置 */
|
||||
readonly locator: IHeroLocationSave;
|
||||
readonly location: IHeroLocationSave;
|
||||
/** 勇士渲染状态 */
|
||||
readonly rendering: IHeroRenderingSave;
|
||||
/** 勇士当前的跟随者 */
|
||||
readonly followers: readonly IHeroFollowerSave[];
|
||||
/** 勇士属性修饰器状态 */
|
||||
readonly modifiers: readonly IModifierStateSave[];
|
||||
readonly modifiers: readonly IModifierStateSave<THero>[];
|
||||
}
|
||||
|
||||
export interface IHeroState<THero> extends ISaveableContent<
|
||||
|
||||
@ -700,7 +700,7 @@ export interface IEnemyContext<TEnemy, THero> extends IReadonlyEnemyContext<
|
||||
* 绑定伤害计算系统
|
||||
* @param system 伤害系统
|
||||
*/
|
||||
attachDamageSystem(system: IDamageSystem<TEnemy, unknown> | null): void;
|
||||
attachDamageSystem(system: IDamageSystem<TEnemy, THero> | null): void;
|
||||
|
||||
/**
|
||||
* 重建当前上下文中的全部怪物计算结果
|
||||
|
||||
Loading…
Reference in New Issue
Block a user