diff --git a/assets/script/game/common/config/HeroAttrs.ts b/assets/script/game/common/config/HeroAttrs.ts index 86776008..bbe3d72f 100644 --- a/assets/script/game/common/config/HeroAttrs.ts +++ b/assets/script/game/common/config/HeroAttrs.ts @@ -17,18 +17,7 @@ export enum NeAttrs { IN_BURN = 2, IN_POISON = 3, } -export const getNeAttrs = () => { - let reAttrs = {}; - Object.keys(NeAttrs).forEach(key => { - if (!isNaN(Number(key))) { - reAttrs[Number(key)] = { - value: 0, - time: 0, - }; - } - }); - return reAttrs; -} + // ========== 属性枚举 ========== /** * 英雄属性枚举 @@ -140,6 +129,18 @@ export const getAttrs = () => { return reAttrs; } +export const getNeAttrs = () => { + let reAttrs = {}; + Object.keys(NeAttrs).forEach(key => { + if (!isNaN(Number(key))) { + reAttrs[Number(key)] = { + value: 0, + time: 0, + }; + } + }); + return reAttrs; +} /** * 属性类型配置表 * 用于区分每个属性是数值型还是百分比型 diff --git a/assets/script/game/hero/HeroAtkSystem.ts b/assets/script/game/hero/HeroAtkSystem.ts index 387d03e6..d4b80274 100644 --- a/assets/script/game/hero/HeroAtkSystem.ts +++ b/assets/script/game/hero/HeroAtkSystem.ts @@ -9,13 +9,30 @@ import { DamageQueueComp, DamageEvent, DamageQueueHelper } from "./DamageQueueCo import { smc } from "../common/SingletonModuleComp"; -/** 最终伤害数据接口 */ +/** 最终伤害数据接口 + * 用于封装一次攻击计算的所有结果数据 + * @property damage - 最终造成的伤害值(已考虑所有加成和减免) + * @property isCrit - 是否为暴击攻击 + * @property isDodge - 是否被闪避(闪避时damage为0) + */ interface FinalData { damage: number; isCrit: boolean; isDodge: boolean; } -/** 业务层业务逻辑处理对象 伤害处理系统 */ +/** + * 英雄攻击系统 - 伤害处理核心系统 + * + * 职责: + * 1. 处理所有伤害事件的计算和分发 + * 2. 管理伤害队列的处理流程 + * 3. 协调视图层的表现更新 + * + * 重要概念: + * - damageEvent.Attrs: 施法者属性快照(创建技能时保存) + * - targetAttrs: 被攻击者实时属性 + * - 属性来源规范:攻击判定用施法者,防御判定用被攻击者 + */ @ecs.register('HeroAtkSystem') export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate { @@ -81,10 +98,30 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd /** - * 执行攻击计算 - * @param target 目标实体 - * @param damageEvent 伤害事件数据 - * @returns 最终伤害数据 + * 执行攻击计算 - 核心伤害计算逻辑 + * + * 属性使用规范(重要!): + * + * ✅ 正确使用施法者属性(damageEvent.Attrs - 快照): + * - CRITICAL: 暴击率判定 + * - CRITICAL_DMG: 暴击伤害加成 + * - BACK_CHANCE: 击退概率 + * - HIT: 命中率(用于闪避计算) + * - AP/MAP: 攻击力(基础伤害计算) + * + * ✅ 正确使用被攻击者属性(targetAttrs - 实时): + * - DODGE: 闪避率(用于闪避计算) + * - SHIELD_MAX: 护盾最大值(护盾吸收) + * - hp: 当前生命值(伤害应用) + * - 各种抗性属性(预留扩展) + * + * ❌ 错误使用案例(已修复): + * - 不要混用施法者和被攻击者的属性进行同一计算 + * - 暴击伤害应该基于施法者的暴击伤害属性 + * + * @param target 目标实体(被攻击者) + * @param damageEvent 伤害事件数据(包含施法者信息和属性快照) + * @returns 最终伤害数据(包含伤害值、暴击标记、闪避标记) */ private doAttack(target: ecs.Entity, damageEvent: DamageEvent): FinalData { const targetAttrs = target.get(HeroAttrsComp); @@ -106,20 +143,28 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd // 触发被攻击事件 this.onAttacked(target); - // 闪避判定 - const isDodge =this.checkChance(targetAttrs.Attrs[Attrs.DODGE] || 0); + // 闪避判定 + // 闪避成功概率 = 被攻击者闪避率 - 施法者命中率 + // targetAttrs.Attrs[Attrs.DODGE]: 被攻击者的实时闪避属性 + // damageEvent.Attrs[Attrs.HIT]: 施法者在技能创建时的命中属性快照 + const isDodge =this.checkChance((targetAttrs.Attrs[Attrs.DODGE]-damageEvent.Attrs[Attrs.HIT]) || 0); if (isDodge) { // TODO: 触发闪避视图表现 reDate.isDodge=true; return reDate; } // 暴击判定 + // 使用施法者的暴击率属性(damageEvent.Attrs 快照) const isCrit = this.checkChance(damageEvent.Attrs[Attrs.CRITICAL]); if (isCrit) attackerModel?.clearTalBuffByAttr(Attrs.CRITICAL); // 计算伤害 let damage = this.dmgCount(damageEvent.Attrs,damageEvent.s_uuid); if (isCrit) { - damage = Math.floor(damage * (1 + (FightSet.CRIT_DAMAGE + targetAttrs.Attrs[Attrs.CRITICAL_DMG]) / 100)); + // 暴击伤害计算 + // 使用施法者的暴击伤害加成属性(damageEvent.Attrs 快照) + // 公式:最终伤害 = 基础伤害 * (1 + 系统暴击倍率 + 施法者暴击伤害加成) + const casterCritDmg = damageEvent.Attrs[Attrs.CRITICAL_DMG] || 0; + damage = Math.floor(damage * (1 + (FightSet.CRIT_DAMAGE + casterCritDmg) / 100)); reDate.isCrit=true; } // 伤害计算(考虑易伤等debuff) @@ -130,7 +175,9 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd // 应用伤害到数据层 targetAttrs.hp -= damage; targetAttrs.atked_count++; - //击退判定 + // 击退判定 + // 使用施法者的击退概率属性(damageEvent.Attrs 快照) + // 击退成功后需要清理施法者的相关天赋buff const isBack = this.checkChance(damageEvent.Attrs[Attrs.BACK_CHANCE] || 0); if (isBack) attackerModel?.clearTalBuffByAttr(Attrs.BACK_CHANCE); @@ -155,7 +202,19 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd reDate.damage=damage; return reDate; } - //伤害计算,暂时简单计算 + /** + * 基础伤害计算 + * 根据技能配置和施法者属性计算基础伤害值 + * + * @param CAttrs 施法者属性快照(包含攻击力等关键属性) + * @param s_uuid 技能ID,用于获取技能配置 + * @returns 基础伤害值(未考虑暴击、抗性等因素) + * + * @todo 后续可以扩展更多伤害计算公式: + * - 技能倍率加成 + * - 元素伤害计算 + * - 真实伤害/魔法伤害/物理伤害区分 + */ private dmgCount(CAttrs:any,s_uuid:number){ let sConf = SkillSet[s_uuid]; if (!sConf) return 0; @@ -164,6 +223,16 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd } /** * 处理角色死亡 + * + * 死亡处理流程: + * 1. 标记死亡状态(is_dead = true) + * 2. 触发死亡事件(onDeath) + * 3. 记录调试信息(如启用调试模式) + * + * @param entity 死亡的实体 + * + * @important 死亡状态一旦设置,该实体将不再处理新的伤害事件 + * 这确保了死亡逻辑的单一性和一致性 */ private doDead(entity: ecs.Entity): void { const model = entity.get(HeroAttrsComp); @@ -182,7 +251,26 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd /** - * 暴击判定 + * 统一概率判定方法 + * + * 用于所有概率相关的判定: + * - 暴击率判定 + * - 闪避率判定 + * - 击退概率判定 + * - 其他特殊效果概率 + * + * @param rate 概率值(0-100的百分比) + * @returns true-判定成功,false-判定失败 + * + * @example + * ```typescript + * // 10%概率触发 + * if (this.checkChance(10)) { + * // 触发特殊效果 + * } + * ``` + * + * @important 概率为0或负数时直接返回false,避免不必要的随机数计算 */ private checkChance(rate: number): boolean { if (rate <= 0) return false; @@ -192,6 +280,16 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd /** * 伤害计算(考虑易伤等debuff) + * + * 预留的伤害计算扩展点,用于处理: + * - 被攻击者的易伤状态(增加受到伤害) + * - 被攻击者的伤害减免状态(减少受到伤害) + * - 元素抗性计算 + * - 真实伤害/魔法伤害/物理伤害的类型区分 + * + * @param model 被攻击者的属性组件(包含抗性、易伤等状态) + * @param baseDamage 基础伤害值 + * @returns 最终伤害值(经过各种加成和减免后的结果) */ private calculateDamage(model: HeroAttrsComp, baseDamage: number): number { // 这里可以添加易伤等debuff的计算逻辑 @@ -201,6 +299,15 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd /** * 护盾吸收伤害 + * + * 护盾吸收逻辑: + * 1. 如果护盾值 >= 伤害值:完全吸收,剩余伤害为0 + * 2. 如果护盾值 < 伤害值:部分吸收,剩余伤害 = 原伤害 - 护盾值 + * 3. 护盾被击破时,重置护盾最大值属性 + * + * @param model 被攻击者的属性组件(包含当前护盾值) + * @param damage 原始伤害值 + * @returns 剩余伤害值(护盾吸收后的结果) */ private absorbShield(model: HeroAttrsComp, damage: number): number { if (model.shield <= 0) return damage; @@ -222,6 +329,15 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd /** * 被攻击时触发的事件 + * + * 预留的扩展点,用于处理被攻击时的特殊逻辑: + * - 触发反伤效果(荆棘光环等) + * - 触发被攻击天赋(如受击回血、受击反击等) + * - 触发特殊状态(如受伤狂暴、受伤护盾等) + * + * @param entity 被攻击的实体 + * + * @todo 当前对怪物实体直接返回,后续可以根据需求扩展怪物的被攻击逻辑 */ private onAttacked(entity: ecs.Entity): void { const model = entity.get(HeroAttrsComp); @@ -235,6 +351,21 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd /** * 死亡时触发的事件 + * + * 根据实体阵营类型处理不同的死亡逻辑: + * + * - FacSet.MON(怪物):触发掉落逻辑 + * - 延迟执行掉落,避免阻塞主逻辑 + * - 可以扩展:经验值计算、任务进度等 + * + * - FacSet.HERO(英雄):触发英雄死亡特殊处理 + * - 游戏结束判定 + * - 复活机制检查 + * - 死亡惩罚/奖励 + * + * @param entity 死亡的实体 + * + * @important 死亡事件应该幂等,避免重复触发 */ private onDeath(entity: ecs.Entity): void { const model = entity.get(HeroAttrsComp); @@ -251,6 +382,19 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd /** * 延迟执行掉落逻辑 + * + * 采用延迟执行的原因: + * 1. 避免在伤害计算过程中阻塞主线程 + * 2. 给死亡动画播放留出时间 + * 3. 可以批量处理多个掉落,优化性能 + * + * @param entity 死亡的怪物实体 + * + * @todo 具体实现可以包括: + * - 根据怪物等级计算基础掉落 + * - 幸运值影响掉落品质 + * - 特殊事件(双倍掉落、稀有掉落等) + * - 掉落物在场景中的生成位置计算 */ private scheduleDrop(entity: ecs.Entity): void { // 这里可以添加掉落逻辑 @@ -259,6 +403,19 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd /** * 延迟执行英雄死亡逻辑 + * + * 英雄死亡的特殊处理,比普通怪物复杂: + * + * 处理内容包括: + * - 检查复活次数和复活条件 + * - 触发游戏结束界面(如适用) + * - 记录死亡统计信息 + * - 处理死亡惩罚(经验损失、装备损坏等) + * + * @param entity 死亡的英雄实体 + * + * @important 英雄死亡通常需要玩家交互,所以必须延迟处理 + * 给玩家足够的反馈时间和操作空间 */ private scheduleHeroDeath(entity: ecs.Entity): void { // 这里可以添加英雄死亡的特殊处理