mirror of
https://github.com/motajs/template.git
synced 2026-06-14 10:41:12 +08:00
Compare commits
2 Commits
82b621c98f
...
8e4efddd63
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e4efddd63 | ||
| 604c77f7c7 |
@ -97,7 +97,7 @@ export class MainDamageCalculator implements IDamageCalculator<
|
||||
context: handler.context,
|
||||
locator,
|
||||
hero,
|
||||
data: handler.data
|
||||
state: handler.state
|
||||
});
|
||||
turn += extraInfo.turn;
|
||||
damage += extraInfo.damage;
|
||||
|
||||
@ -311,7 +311,7 @@ export class MainMapDamageConverter implements IMapDamageConverter<
|
||||
|
||||
const laser = enemy.getSpecial<number>(24);
|
||||
if (laser) {
|
||||
const face = handler.data.faceManager.get(FaceGroup.Dir4)!;
|
||||
const face = handler.state.faceManager.get(FaceGroup.Dir4)!;
|
||||
views.push(new LaserDamageView(context, locator, laser, face));
|
||||
}
|
||||
|
||||
|
||||
@ -100,7 +100,7 @@ export class EnemyContext<TEnemy, THero> implements IEnemyContext<
|
||||
width: number = 0;
|
||||
height: number = 0;
|
||||
|
||||
constructor(readonly dataState: IStateBase) {}
|
||||
constructor(readonly state: IStateBase) {}
|
||||
|
||||
resize(width: number, height: number): void {
|
||||
this.clear();
|
||||
@ -215,7 +215,7 @@ export class EnemyContext<TEnemy, THero> implements IEnemyContext<
|
||||
context: this,
|
||||
locator,
|
||||
hero: this.bindedHero!,
|
||||
data: this.dataState
|
||||
state: this.state
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,8 @@ import {
|
||||
IEnemyCritical,
|
||||
IEnemyDamageInfo,
|
||||
IReadonlyEnemyHandler,
|
||||
IEnemyView
|
||||
IEnemyView,
|
||||
IEnemyDamageInfoBase
|
||||
} from './types';
|
||||
import {
|
||||
IHeroAttribute,
|
||||
@ -22,7 +23,7 @@ interface ICriticalSearchResult {
|
||||
/** 此临界点的属性值 */
|
||||
readonly value: number;
|
||||
/** 此临界点的伤害信息 */
|
||||
readonly info: IEnemyDamageInfo;
|
||||
readonly info: IEnemyDamageInfoBase;
|
||||
}
|
||||
|
||||
export class DamageContext<TEnemy, THero> implements IDamageContext<
|
||||
@ -34,14 +35,14 @@ export class DamageContext<TEnemy, THero> implements IDamageContext<
|
||||
/** 当前勇士属性 */
|
||||
protected heroStatus: IReadonlyHeroAttribute<THero> | null;
|
||||
|
||||
readonly dataState: IStateBase;
|
||||
readonly state: IStateBase;
|
||||
|
||||
constructor(
|
||||
readonly context: IEnemyContext<TEnemy, THero>,
|
||||
calculator: IDamageCalculator<TEnemy, THero> | null = null,
|
||||
heroStatus: IReadonlyHeroAttribute<THero> | null = null
|
||||
) {
|
||||
this.dataState = context.dataState;
|
||||
this.state = context.state;
|
||||
this.calculator = calculator;
|
||||
this.heroStatus = heroStatus;
|
||||
}
|
||||
@ -62,11 +63,13 @@ export class DamageContext<TEnemy, THero> implements IDamageContext<
|
||||
context: this.context,
|
||||
locator,
|
||||
hero,
|
||||
data: this.dataState
|
||||
state: this.state
|
||||
};
|
||||
}
|
||||
|
||||
getDamageInfo(enemy: IEnemyView<TEnemy>): IEnemyDamageInfo | null {
|
||||
getDamageInfo(
|
||||
enemy: IEnemyView<TEnemy>
|
||||
): IEnemyDamageInfo<TEnemy, THero> | null {
|
||||
if (!this.heroStatus) {
|
||||
logger.warn(107);
|
||||
return null;
|
||||
@ -82,12 +85,15 @@ export class DamageContext<TEnemy, THero> implements IDamageContext<
|
||||
const computed = enemy.getComputedEnemy();
|
||||
const handler = this.createReadonlyHandler(computed, locator, hero);
|
||||
|
||||
return this.calculator.calculate(handler);
|
||||
return {
|
||||
handler,
|
||||
...this.calculator.calculate(handler)
|
||||
};
|
||||
}
|
||||
|
||||
getDamageInfoByComputed(
|
||||
enemy: IReadonlyEnemy<TEnemy>
|
||||
): IEnemyDamageInfo | null {
|
||||
): IEnemyDamageInfo<TEnemy, THero> | null {
|
||||
if (!this.heroStatus) {
|
||||
logger.warn(107);
|
||||
return null;
|
||||
@ -105,7 +111,10 @@ export class DamageContext<TEnemy, THero> implements IDamageContext<
|
||||
|
||||
const handler = this.createReadonlyHandler(enemy, locator, hero);
|
||||
|
||||
return this.calculator.calculate(handler);
|
||||
return {
|
||||
handler,
|
||||
...this.calculator.calculate(handler)
|
||||
};
|
||||
}
|
||||
|
||||
*calculateCritical(
|
||||
@ -224,8 +233,10 @@ export class DamageSystem<TEnemy, THero>
|
||||
implements IDamageSystem<TEnemy, THero>
|
||||
{
|
||||
/** 怪物伤害缓存 */
|
||||
private readonly cache: Map<IEnemyView<TEnemy>, IEnemyDamageInfo> =
|
||||
new Map();
|
||||
private readonly cache: Map<
|
||||
IEnemyView<TEnemy>,
|
||||
IEnemyDamageInfo<TEnemy, THero>
|
||||
> = new Map();
|
||||
|
||||
constructor(context: IEnemyContext<TEnemy, THero>) {
|
||||
super(context);
|
||||
@ -245,7 +256,9 @@ export class DamageSystem<TEnemy, THero>
|
||||
this.markAllDirty();
|
||||
}
|
||||
|
||||
getDamageInfo(enemy: IEnemyView<TEnemy>): IEnemyDamageInfo | null {
|
||||
getDamageInfo(
|
||||
enemy: IEnemyView<TEnemy>
|
||||
): IEnemyDamageInfo<TEnemy, THero> | null {
|
||||
const cached = this.cache.get(enemy);
|
||||
if (cached) {
|
||||
return cached;
|
||||
@ -260,7 +273,7 @@ export class DamageSystem<TEnemy, THero>
|
||||
|
||||
getDamageInfoByComputed(
|
||||
enemy: IReadonlyEnemy<TEnemy>
|
||||
): IEnemyDamageInfo | null {
|
||||
): IEnemyDamageInfo<TEnemy, THero> | null {
|
||||
const view = this.context.getViewByComputed(enemy);
|
||||
if (view) {
|
||||
const cached = this.cache.get(view);
|
||||
|
||||
@ -64,11 +64,11 @@ export class MapDamage<TEnemy, THero> implements IMapDamage<TEnemy, THero> {
|
||||
/** 坐标索引对象 */
|
||||
private readonly indexer: ILocationHelper;
|
||||
|
||||
readonly dataState: IStateBase;
|
||||
readonly state: IStateBase;
|
||||
|
||||
constructor(readonly context: IEnemyContext<TEnemy, THero>) {
|
||||
this.indexer = context.indexer;
|
||||
this.dataState = context.dataState;
|
||||
this.state = context.state;
|
||||
}
|
||||
|
||||
useConverter(converter: IMapDamageConverter<TEnemy, THero>): void {
|
||||
@ -92,7 +92,7 @@ export class MapDamage<TEnemy, THero> implements IMapDamage<TEnemy, THero> {
|
||||
context: this.context,
|
||||
locator,
|
||||
hero,
|
||||
data: this.context.dataState
|
||||
state: this.state
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import { ITileLocator, IRange } from '@motajs/common';
|
||||
import { ITileLocator, IRange, IHookable, IHookBase } from '@motajs/common';
|
||||
import {
|
||||
IEnemy,
|
||||
IReadonlyEnemy,
|
||||
ISpecial,
|
||||
IReadonlyHeroAttribute,
|
||||
IHeroAttribute,
|
||||
IStateBase
|
||||
IStateBase,
|
||||
IStateBaseExtended
|
||||
} from '@user/data-base';
|
||||
import { ILocationHelper } from '@user/data-common';
|
||||
|
||||
@ -21,7 +22,7 @@ export interface IEnemyHandler<TEnemy, THero> {
|
||||
/** 勇士属性信息 */
|
||||
readonly hero: IReadonlyHeroAttribute<THero>;
|
||||
/** 当前全局状态对象 */
|
||||
readonly data: IStateBase;
|
||||
readonly state: IStateBase;
|
||||
}
|
||||
|
||||
export interface IReadonlyEnemyHandler<TEnemy, THero> {
|
||||
@ -34,7 +35,7 @@ export interface IReadonlyEnemyHandler<TEnemy, THero> {
|
||||
/** 勇士属性信息 */
|
||||
readonly hero: IReadonlyHeroAttribute<THero>;
|
||||
/** 当前全局状态对象 */
|
||||
readonly data: IStateBase;
|
||||
readonly state: IStateBase;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
@ -282,11 +283,9 @@ export interface IMapDamageReducer {
|
||||
): Readonly<IMapDamageInfo>;
|
||||
}
|
||||
|
||||
export interface IMapDamage<TEnemy, THero> {
|
||||
export interface IMapDamage<TEnemy, THero> extends IStateBaseExtended {
|
||||
/** 当前绑定的怪物上下文 */
|
||||
readonly context: IEnemyContext<TEnemy, THero>;
|
||||
/** 地图伤害系统绑定的全局状态对象 */
|
||||
readonly dataState: IStateBase;
|
||||
|
||||
/**
|
||||
* 设置地图伤害转换器,并基于当前上下文重建所有地图伤害视图
|
||||
@ -356,13 +355,18 @@ export interface IMapDamage<TEnemy, THero> {
|
||||
|
||||
//#region 伤害系统
|
||||
|
||||
export interface IEnemyDamageInfo {
|
||||
export interface IEnemyDamageInfoBase {
|
||||
/** 战斗伤害值 */
|
||||
readonly damage: number;
|
||||
/** 战斗回合数 */
|
||||
readonly turn: number;
|
||||
}
|
||||
|
||||
export interface IEnemyDamageInfo<TEnemy, THero> extends IEnemyDamageInfoBase {
|
||||
/** 信息对象 */
|
||||
readonly handler: IReadonlyEnemyHandler<TEnemy, THero>;
|
||||
}
|
||||
|
||||
export interface IEnemyCritical {
|
||||
/** 此临界点中指定勇士属性的值 */
|
||||
readonly nextValue: number;
|
||||
@ -371,9 +375,9 @@ export interface IEnemyCritical {
|
||||
/** 此临界点中指定勇士数值的值与当前值的差,即 `nextValue - baseValue` */
|
||||
readonly nextDiff: number;
|
||||
/** 当前状态下怪物的伤害信息 */
|
||||
readonly baseInfo: IEnemyDamageInfo;
|
||||
readonly baseInfo: IEnemyDamageInfoBase;
|
||||
/** 此临界点下怪物的伤害信息 */
|
||||
readonly info: IEnemyDamageInfo;
|
||||
readonly info: IEnemyDamageInfoBase;
|
||||
/** 此临界点的伤害值与当前伤害值的差 */
|
||||
readonly damageDiff: number;
|
||||
}
|
||||
@ -387,7 +391,9 @@ export interface IDamageCalculator<TEnemy, THero> {
|
||||
* 计算战斗伤害信息
|
||||
* @param handler 信息对象
|
||||
*/
|
||||
calculate(handler: IReadonlyEnemyHandler<TEnemy, THero>): IEnemyDamageInfo;
|
||||
calculate(
|
||||
handler: IReadonlyEnemyHandler<TEnemy, THero>
|
||||
): IEnemyDamageInfoBase;
|
||||
|
||||
/**
|
||||
* 获取临界计算的上界
|
||||
@ -400,15 +406,14 @@ export interface IDamageCalculator<TEnemy, THero> {
|
||||
): number;
|
||||
}
|
||||
|
||||
export interface IDamageContext<TEnemy, THero> {
|
||||
/** 伤害上下文所属的全局状态对象 */
|
||||
readonly dataState: IStateBase;
|
||||
|
||||
export interface IDamageContext<TEnemy, THero> extends IStateBaseExtended {
|
||||
/**
|
||||
* 获取战斗伤害信息
|
||||
* @param enemy 怪物视图
|
||||
*/
|
||||
getDamageInfo(enemy: IEnemyView<TEnemy>): IEnemyDamageInfo | null;
|
||||
getDamageInfo(
|
||||
enemy: IEnemyView<TEnemy>
|
||||
): IEnemyDamageInfo<TEnemy, THero> | null;
|
||||
|
||||
/**
|
||||
* 根据怪物对象获取战斗伤害信息
|
||||
@ -416,7 +421,7 @@ export interface IDamageContext<TEnemy, THero> {
|
||||
*/
|
||||
getDamageInfoByComputed(
|
||||
enemy: IReadonlyEnemy<TEnemy>
|
||||
): IEnemyDamageInfo | null;
|
||||
): IEnemyDamageInfo<TEnemy, THero> | null;
|
||||
|
||||
/**
|
||||
* 计算怪物在指定勇士属性下的临界
|
||||
@ -483,15 +488,16 @@ export interface IDamageSystem<TEnemy, THero> extends IDamageContext<
|
||||
|
||||
//#region 上下文
|
||||
|
||||
export interface IReadonlyEnemyContext<TEnemy, THero> {
|
||||
export interface IReadonlyEnemyContext<
|
||||
TEnemy,
|
||||
THero
|
||||
> extends IStateBaseExtended {
|
||||
/** 怪物上下文宽度 */
|
||||
readonly width: number;
|
||||
/** 怪物上下文高度 */
|
||||
readonly height: number;
|
||||
/** 此上下文使用的索引对象 */
|
||||
readonly indexer: ILocationHelper;
|
||||
/** 当前怪物上下文绑定的全局状态对象 */
|
||||
readonly dataState: IStateBase;
|
||||
|
||||
/**
|
||||
* 获取当前绑定的勇士属性对象
|
||||
@ -567,8 +573,6 @@ export interface IEnemyContext<TEnemy, THero> extends IReadonlyEnemyContext<
|
||||
readonly height: number;
|
||||
/** 此上下文使用的索引对象 */
|
||||
readonly indexer: ILocationHelper;
|
||||
/** 当前怪物上下文绑定的全局状态对象 */
|
||||
readonly dataState: IStateBase;
|
||||
|
||||
/**
|
||||
* 调整上下文尺寸,并清空当前上下文中的所有怪物与状态
|
||||
@ -724,3 +728,111 @@ export interface IEnemyContext<TEnemy, THero> extends IReadonlyEnemyContext<
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 战斗流程
|
||||
|
||||
export interface ICombatFlowHandler<TEnemy, THero> {
|
||||
/** 战斗的怪物是否在地图上 */
|
||||
readonly onMap: boolean;
|
||||
/** 可修改勇士对象 */
|
||||
readonly hero: IHeroAttribute<THero>;
|
||||
/** 可修改怪物对象 */
|
||||
readonly enemy: IEnemy<TEnemy>;
|
||||
/** 怪物上下文 */
|
||||
readonly context: IEnemyContext<TEnemy, THero>;
|
||||
/** 怪物位置 */
|
||||
readonly locator: ITileLocator;
|
||||
/** 全局状态对象 */
|
||||
readonly state: IStateBase;
|
||||
}
|
||||
|
||||
export interface ICombatFlowHook<TEnemy, THero> extends IHookBase {
|
||||
/**
|
||||
* 战前脚本
|
||||
* @param info 战斗伤害信息
|
||||
*/
|
||||
onBeforeCombat?(info: IEnemyDamageInfo<TEnemy, THero>): Promise<void>;
|
||||
|
||||
/**
|
||||
* 战后脚本
|
||||
* @param info 战斗伤害信息
|
||||
*/
|
||||
onAfterCombat?(info: IEnemyDamageInfo<TEnemy, THero>): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ICombatScript<TEnemy, THero> {
|
||||
/** 此脚本的优先级 */
|
||||
readonly priority: number;
|
||||
|
||||
/**
|
||||
* 战前执行的内容,返回 `false` 会立刻停止后续战前内容的执行,并放弃此次战斗
|
||||
* @param info 战斗伤害信息
|
||||
* @param handler 信息对象
|
||||
*/
|
||||
before(
|
||||
info: IEnemyDamageInfo<TEnemy, THero>,
|
||||
handler: ICombatFlowHandler<TEnemy, THero>
|
||||
): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* 战后执行的内容
|
||||
* @param info 战斗伤害信息
|
||||
* @param handler 信息对象
|
||||
*/
|
||||
after(
|
||||
info: IEnemyDamageInfo<TEnemy, THero>,
|
||||
handler: ICombatFlowHandler<TEnemy, THero>
|
||||
): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ICombatFlow<TEnemy, THero>
|
||||
extends IHookable<ICombatFlowHook<TEnemy, THero>>, IStateBaseExtended {
|
||||
/** 勇士属性对象 */
|
||||
readonly hero: IReadonlyHeroAttribute<THero> | null;
|
||||
/** 怪物上下文对象 */
|
||||
readonly context: IReadonlyEnemyContext<TEnemy, THero> | null;
|
||||
/** 伤害上下文 */
|
||||
readonly damage: IDamageContext<TEnemy, THero> | null;
|
||||
|
||||
/**
|
||||
* 绑定勇士属性对象
|
||||
* @param hero 勇士属性对象
|
||||
*/
|
||||
bindHero(hero: IHeroAttribute<THero> | null): void;
|
||||
|
||||
/**
|
||||
* 绑定怪物上下文
|
||||
* @param context 怪物上下文
|
||||
*/
|
||||
bindContext(context: IReadonlyEnemyContext<TEnemy, THero> | null): void;
|
||||
|
||||
/**
|
||||
* 绑定伤害上下文
|
||||
* @param damage 伤害上下文
|
||||
*/
|
||||
bindDamage(damage: IDamageContext<TEnemy, THero> | null): void;
|
||||
|
||||
/**
|
||||
* 与指定怪物战斗
|
||||
* @param enemy 怪物视图对象
|
||||
*/
|
||||
battle(
|
||||
enemy: IEnemyView<TEnemy>
|
||||
): Promise<IEnemyDamageInfo<TEnemy, THero> | null>;
|
||||
|
||||
/**
|
||||
* 与指定怪物战斗
|
||||
* @param enemy 怪物对象
|
||||
*/
|
||||
battleComputed(
|
||||
enemy: IReadonlyEnemy<TEnemy>
|
||||
): Promise<IEnemyDamageInfo<TEnemy, THero> | null>;
|
||||
|
||||
/**
|
||||
* 添加战前战后脚本
|
||||
* @param script 战前战后脚本
|
||||
*/
|
||||
addCombatScript(script: ICombatScript<TEnemy, THero>): void;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
## 示例文档
|
||||
|
||||
对于新增接口/彻底性地重构接口,大致按照以下格式编写,其余需求按照自己的理解去写即可。如某部分需要详细描述,可单独开设标题;若某个接口内容较多,也可以在文档中为其单独开一个章节进行讲述。我会使用引用块的形式在文档中提出建议或回答。Markdown 文档不需要刻意换行,我的编辑器有自动换行功能,正常写没有问题。
|
||||
对于新增接口/彻底性地重构接口,按照以下格式编写,其余需求按照自己的理解去写即可。如某部分需要详细描述,可单独开设标题;若某个接口内容较多,也可以在文档中为其单独开一个章节进行讲述。我会使用引用块的形式在文档中提出建议或回答。Markdown 文档不需要刻意换行,我的编辑器有自动换行功能,正常写没有问题。文档保证简洁,不要过于啰嗦,但必须包含所有的必要信息,控制在 100-250 行以内。
|
||||
|
||||
```md
|
||||
# 需求综述
|
||||
@ -43,7 +43,7 @@
|
||||
|
||||
# 接口设计与预期
|
||||
|
||||
这是相当重要的一章。需要按接口逐一列出其方法与成员,分析每个成员和方法的预期使用频率(高 / 中 / 低)并说明判断依据;对于中频和高频成员,还需列出至少一个典型使用场景。
|
||||
这是相当重要的一章。需要按接口逐一列出其方法与成员,分析每个成员和方法的预期使用频率(高 / 中 / 低)并说明判断依据;对于中频和高频成员,还需列出至少一个典型使用场景。必须认真分析频率,想明白**用户**调用的频率,而不是**引擎**调用的频率,比如战斗函数在引擎中可能是中频,但是对用户来说,用户一般会使用系统默认行为来战斗,而**不会**自己调用,因此属于低频。
|
||||
|
||||
**命名长度原则**:频率越高,成员名应越短。高频成员以一个单词为宜,最多不超过两个单词;中频成员不超过三个单词;低频成员可以稍长,但不宜过长。
|
||||
|
||||
@ -68,7 +68,7 @@
|
||||
|
||||
## 可能风险
|
||||
|
||||
在任何时候,需要修改已有接口时,必须在文档中写明修改这一接口的风险。这里的已有接口指的是本次设计新增接口之外的接口,即所有已存在于代码中的接口。
|
||||
在任何时候,需要修改已有接口时,必须在文档中写明修改这一接口的风险。这里的已有接口指的是本次设计新增接口之外的接口,即所有已存在于代码中的接口。本章节**只写**关于修改已有接口可能导致的风险,**不写任何关于实现的风险**,关于实现的风险应该写到最后的问题节,而不是这里。
|
||||
|
||||
# 实现思路
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user