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