diff --git a/assets/script/game/common/config/SkillSet.ts b/assets/script/game/common/config/SkillSet.ts index 83c5aafb..8ee2515c 100644 --- a/assets/script/game/common/config/SkillSet.ts +++ b/assets/script/game/common/config/SkillSet.ts @@ -158,6 +158,10 @@ export interface SkillConfig { } export const SkillSet: Record = { + 5000:{uuid:5000,name:"反伤",sp_name:"thorns",icon:"3036",TGroup:TGroup.Enemy,SType:SType.damage,act:"atk",DTType:DTType.single,DType:DType.ATK, + ap:0,map:0,cd:0,t_num:1,hit_num:1,hit:1,hitcd:0.2,speed:720,cost:0,with:0,dis:80,ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, + buffs:[],neAttrs:[],info:"反伤", + }, // ========== 基础攻击 ========== 6001-6099 6001: { uuid:6001,name:"挥击",sp_name:"atk_s1",icon:"3036",TGroup:TGroup.Enemy,SType:SType.damage,act:"atk",DTType:DTType.single,DType:DType.ATK, diff --git a/assets/script/game/hero/HeroAtkSystem.ts b/assets/script/game/hero/HeroAtkSystem.ts index bd723472..976e289f 100644 --- a/assets/script/game/hero/HeroAtkSystem.ts +++ b/assets/script/game/hero/HeroAtkSystem.ts @@ -30,7 +30,7 @@ interface FinalData { * * 重要概念: * - damageEvent.Attrs: 施法者属性快照(创建技能时保存) - * - targetAttrs: 被攻击者实时属性 + * - TAttrsComp: 被攻击者实时属性 * - 属性来源规范:攻击判定用施法者,防御判定用被攻击者 */ @ecs.register('HeroAtkSystem') @@ -51,10 +51,10 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd */ update(e: ecs.Entity): void { if(!smc.mission.play || smc.mission.pause) return; - const model = e.get(HeroAttrsComp); + const TAttrsComp = e.get(HeroAttrsComp); const damageQueue = e.get(DamageQueueComp); - if (!model || !damageQueue || damageQueue.isEmpty()) return; + if (!TAttrsComp || !damageQueue || damageQueue.isEmpty()) return; // 标记正在处理 damageQueue.isProcessing = true; @@ -73,13 +73,13 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd if (this.debugMode) { const casterName = damageEvent.caster?.ent?.get(HeroAttrsComp)?.hero_name || "未知"; const casterUuid = damageEvent.caster?.ent?.get(HeroAttrsComp)?.hero_uuid || 0; - console.log(`[HeroAtkSystem] 英雄${model.hero_name} (uuid: ${model.hero_uuid}) 受到 ${casterName}(uuid: ${casterUuid})的 伤害 ${FDData.damage},${FDData.isCrit?"暴击":"普通"}攻击,技能ID ${damageEvent.s_uuid}`); + console.log(`[HeroAtkSystem] 英雄${TAttrsComp.hero_name} (uuid: ${TAttrsComp.hero_uuid}) 受到 ${casterName}(uuid: ${casterUuid})的 伤害 ${FDData.damage},${FDData.isCrit?"暴击":"普通"}攻击,技能ID ${damageEvent.s_uuid}`); } // 如果目标已死亡,停止处理后续伤害 - if (model.is_dead) { + if (TAttrsComp.is_dead) { if (this.debugMode) { - console.log(`[HeroAtkSystem] ${model.hero_name} 已死亡,停止处理剩余伤害`); + console.log(`[HeroAtkSystem] ${TAttrsComp.hero_name} 已死亡,停止处理剩余伤害`); } damageQueue.clear(); // 清空剩余伤害 break; @@ -91,7 +91,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd e.remove(DamageQueueComp); if (this.debugMode && processedCount > 0) { - console.log(`[HeroAtkSystem] ${model.hero_name} 伤害队列处理完成,共处理 ${processedCount} 个伤害事件`); + console.log(`[HeroAtkSystem] ${TAttrsComp.hero_name} 伤害队列处理完成,共处理 ${processedCount} 个伤害事件`); } } } @@ -109,7 +109,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd * - HIT: 命中率(用于闪避计算) * - AP/MAP: 攻击力(基础伤害计算) * - * ✅ 正确使用被攻击者属性(targetAttrs - 实时): + * ✅ 正确使用被攻击者属性(TAttrsComp - 实时): * - DODGE: 闪避率(用于闪避计算) * - SHIELD_MAX: 护盾最大值(护盾吸收) * - hp: 当前生命值(伤害应用) @@ -124,17 +124,17 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd * @returns 最终伤害数据(包含伤害值、暴击标记、闪避标记) */ private doAttack(target: ecs.Entity, damageEvent: DamageEvent): FinalData { - const targetAttrs = target.get(HeroAttrsComp); + const TAttrsComp = target.get(HeroAttrsComp); const targetView = target.get(HeroViewComp); let reDate:FinalData={ damage:0, isCrit:false, isDodge:false, } - if (!targetAttrs || targetAttrs.is_dead) return reDate; + if (!TAttrsComp || TAttrsComp.is_dead) return reDate; const caster = damageEvent.caster; - const attackerModel = caster?.ent?.get(HeroAttrsComp); + const attackerTAttrsComp = caster?.ent?.get(HeroAttrsComp); // 获取技能配置 const skillConf = SkillSet[damageEvent.s_uuid]; @@ -145,19 +145,19 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd // 闪避判定 // 闪避成功概率 = 被攻击者闪避率 - 施法者命中率 - // targetAttrs.Attrs[Attrs.DODGE]: 被攻击者的实时闪避属性 + // TAttrsComp.Attrs[Attrs.DODGE]: 被攻击者的实时闪避属性 // damageEvent.Attrs[Attrs.HIT]: 施法者在技能创建时的命中属性快照 - const isDodge =this.checkChance((targetAttrs.Attrs[Attrs.DODGE]-damageEvent.Attrs[Attrs.HIT]) || 0); + const isDodge =this.checkChance((TAttrsComp.Attrs[Attrs.DODGE]-damageEvent.Attrs[Attrs.HIT]) || 0); if (isDodge) { // TODO: 触发闪避视图表现 reDate.isDodge=true; return reDate; } // 暴击判定 - // 使用施法者的暴击率属性(damageEvent.Attrs 快照),- 被攻击者的暴击抗性属性targetAttrs.Attrs[Attrs.CRITICAL_RESIST] - const isCrit = this.checkChance(damageEvent.Attrs[Attrs.CRITICAL]-targetAttrs.Attrs[Attrs.CRITICAL_RESIST]); + // 使用施法者的暴击率属性(damageEvent.Attrs 快照),- 被攻击者的暴击抗性属性TAttrsComp.Attrs[Attrs.CRITICAL_RESIST] + const isCrit = this.checkChance(damageEvent.Attrs[Attrs.CRITICAL]-TAttrsComp.Attrs[Attrs.CRITICAL_RESIST]); // 计算基础伤害 - let damage = this.dmgCount(damageEvent,targetAttrs); + let damage = this.dmgCount(damageEvent,TAttrsComp); if (isCrit) { // 暴击伤害计算 // 使用施法者的暴击伤害加成属性(damageEvent.Attrs 快照) @@ -165,20 +165,22 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd const casterCritDmg = damageEvent.Attrs[Attrs.CRITICAL_DMG] || 0; damage = Math.floor(damage * (1 + (FightSet.CRIT_DAMAGE + casterCritDmg) / 100)); reDate.isCrit=true; - attackerModel?.useValueTalByAttr(Attrs.CRITICAL); // 清除施法者的暴击buff + attackerTAttrsComp?.useValueTalByAttr(Attrs.CRITICAL); // 清除施法者的暴击buff } // 护盾吸收 - damage =Math.floor(this.absorbShield(targetAttrs, damage)) + damage =Math.floor(this.absorbShield(TAttrsComp, damage)) if (damage <= 0) return reDate; // 应用伤害到数据层 - targetAttrs.hp -= damage; - targetAttrs.atked_count++; + TAttrsComp.hp -= damage; + TAttrsComp.atked_count++; + //反伤判定 并应用到施法者 + this.check_thorns(TAttrsComp, caster?.ent,damage); // 击退判定 // 使用施法者的击退概率属性(damageEvent.Attrs 快照) // 击退成功后需要清理施法者的相关天赋buff const isBack = this.checkChance(damageEvent.Attrs[Attrs.BACK_CHANCE] || 0); - if (isBack) attackerModel?.useValueTalByAttr(Attrs.BACK_CHANCE); + if (isBack) attackerTAttrsComp?.useValueTalByAttr(Attrs.BACK_CHANCE); // ✅ 触发视图层表现(伤害数字、受击动画、后退) @@ -186,7 +188,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd // 检查死亡 - if (targetAttrs.hp <= 0) { + if (TAttrsComp.hp <= 0) { this.doDead(target); // ✅ 触发死亡视图表现 if (targetView) { @@ -195,12 +197,27 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd } if (this.debugMode) { - console.log(`[HeroAtkSystem] ${targetAttrs.hero_name} 受到 ${damage} 点伤害 (暴击: ${isCrit})`); + console.log(`[HeroAtkSystem] ${TAttrsComp.hero_name} 受到 ${damage} 点伤害 (暴击: ${isCrit})`); } reDate.damage=damage; return reDate; } + check_thorns(TAttrsComp:HeroAttrsComp, caster: ecs.Entity, damage:number) { + // 检查目标是否有反伤属性 + if (!caster||damage<=0) return; + let thornsDamage=0; + thornsDamage=TAttrsComp.Attrs[Attrs.THORNS]||0+TAttrsComp.useCountValTal(Attrs.THORNS); + let CAttrs=caster.get(HeroAttrsComp); + // 计算反伤伤害 + let thornsDmg=Math.floor(thornsDamage*damage/100); + // 应用反伤伤害到数据层 + CAttrs.hp -= thornsDmg; + CAttrs.atked_count++; + let CView=caster.get(HeroViewComp); + // ✅ 触发视图层表现(伤害数字、受击动画、后退) + if (CView) CView.do_atked(thornsDmg, false, SkillSet[5000].uuid, false); + } /** * 详细伤害计算核心方法 * @@ -343,16 +360,16 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd * 这确保了死亡逻辑的单一性和一致性 */ private doDead(entity: ecs.Entity): void { - const model = entity.get(HeroAttrsComp); - if (!model || model.is_dead) return; + const TAttrsComp = entity.get(HeroAttrsComp); + if (!TAttrsComp || TAttrsComp.is_dead) return; - model.is_dead = true; + TAttrsComp.is_dead = true; // 触发死亡事件 this.onDeath(entity); if (this.debugMode) { - console.log(`[HeroAtkSystem] ${model.hero_name} 死亡`); + console.log(`[HeroAtkSystem] ${TAttrsComp.hero_name} 死亡`); } } @@ -395,24 +412,24 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd * 2. 如果护盾值 < 伤害值:部分吸收,剩余伤害 = 原伤害 - 护盾值 * 3. 护盾被击破时,重置护盾最大值属性 * - * @param model 被攻击者的属性组件(包含当前护盾值) + * @param TAttrsComp 被攻击者的属性组件(包含当前护盾值) * @param damage 原始伤害值 * @returns 剩余伤害值(护盾吸收后的结果) */ - private absorbShield(model: HeroAttrsComp, damage: number): number { - if (model.shield <= 0) return damage; + private absorbShield(TAttrsComp: HeroAttrsComp, damage: number): number { + if (TAttrsComp.shield <= 0) return damage; - if (model.shield >= damage) { - model.shield -= damage; - if (model.shield <= 0) { - model.shield = 0; - model.Attrs[Attrs.SHIELD_MAX] = 0; + if (TAttrsComp.shield >= damage) { + TAttrsComp.shield -= damage; + if (TAttrsComp.shield <= 0) { + TAttrsComp.shield = 0; + TAttrsComp.Attrs[Attrs.SHIELD_MAX] = 0; } return 0; } else { - const remainingDamage = damage - model.shield; - model.shield = 0; - model.Attrs[Attrs.SHIELD_MAX] = 0; + const remainingDamage = damage - TAttrsComp.shield; + TAttrsComp.shield = 0; + TAttrsComp.Attrs[Attrs.SHIELD_MAX] = 0; return remainingDamage; } } @@ -430,11 +447,11 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd * @todo 当前对怪物实体直接返回,后续可以根据需求扩展怪物的被攻击逻辑 */ private onAttacked(entity: ecs.Entity): void { - const model = entity.get(HeroAttrsComp); - if (!model || model.is_dead) return; + const TAttrsComp = entity.get(HeroAttrsComp); + if (!TAttrsComp || TAttrsComp.is_dead) return; // 这里可以添加被攻击时的特殊处理逻辑 - if (model.fac === FacSet.MON) return; + if (TAttrsComp.fac === FacSet.MON) return; // 例如:触发某些天赋效果、反击逻辑等 } @@ -458,13 +475,13 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd * @important 死亡事件应该幂等,避免重复触发 */ private onDeath(entity: ecs.Entity): void { - const model = entity.get(HeroAttrsComp); - if (!model) return; + const TAttrsComp = entity.get(HeroAttrsComp); + if (!TAttrsComp) return; - if (model.fac === FacSet.MON) { + if (TAttrsComp.fac === FacSet.MON) { // 怪物死亡处理 this.scheduleDrop(entity); - } else if (model.fac === FacSet.HERO) { + } else if (TAttrsComp.fac === FacSet.HERO) { // 英雄死亡处理 this.scheduleHeroDeath(entity); }