refactor(hero): 重构英雄攻击系统并重命名文件
This commit is contained in:
283
assets/script/game/hero/HeroAtkSystem.ts
Normal file
283
assets/script/game/hero/HeroAtkSystem.ts
Normal file
@@ -0,0 +1,283 @@
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { FacSet } from "../common/config/GameSet";
|
||||
import { Attrs } from "../common/config/HeroAttrs";
|
||||
import { FightSet } from "../common/config/GameSet";
|
||||
import { SkillSet } from "../common/config/SkillSet";
|
||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { HeroViewComp } from "./HeroViewComp";
|
||||
import { DamageQueueComp, DamageEvent, DamageQueueHelper } from "./DamageQueueComp";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
|
||||
|
||||
/** 最终伤害数据接口 */
|
||||
interface FinalData {
|
||||
damage: number;
|
||||
isCrit: boolean;
|
||||
isDodge: boolean;
|
||||
}
|
||||
/** 业务层业务逻辑处理对象 伤害处理系统 */
|
||||
@ecs.register('HeroAtkSystem')
|
||||
export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||
|
||||
private debugMode: boolean = false; // 是否启用调试模式
|
||||
|
||||
/**
|
||||
* 过滤器:处理拥有伤害队列的实体
|
||||
*/
|
||||
filter(): ecs.IMatcher {
|
||||
return ecs.allOf(HeroAttrsComp, DamageQueueComp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统更新(每帧调用)
|
||||
* 处理伤害队列中的所有伤害事件
|
||||
*/
|
||||
update(e: ecs.Entity): void {
|
||||
if(!smc.mission.play || smc.mission.pause) return;
|
||||
const model = e.get(HeroAttrsComp);
|
||||
const damageQueue = e.get(DamageQueueComp);
|
||||
|
||||
if (!model || !damageQueue || damageQueue.isEmpty()) return;
|
||||
|
||||
// 标记正在处理
|
||||
damageQueue.isProcessing = true;
|
||||
|
||||
// 处理队列中的所有伤害事件
|
||||
let processedCount = 0;
|
||||
while (!damageQueue.isEmpty()) {
|
||||
const damageEvent = damageQueue.getNextDamageEvent();
|
||||
if (!damageEvent) break;
|
||||
|
||||
// 处理单个伤害事件
|
||||
const FDData = this.doAttack(e, damageEvent);
|
||||
processedCount++;
|
||||
damageQueue.processedCount++;
|
||||
|
||||
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}`);
|
||||
}
|
||||
|
||||
// 如果目标已死亡,停止处理后续伤害
|
||||
if (model.is_dead) {
|
||||
if (this.debugMode) {
|
||||
console.log(`[HeroAtkSystem] ${model.hero_name} 已死亡,停止处理剩余伤害`);
|
||||
}
|
||||
damageQueue.clear(); // 清空剩余伤害
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果队列已空,移除伤害队列组件
|
||||
if (damageQueue.isEmpty()) {
|
||||
e.remove(DamageQueueComp);
|
||||
|
||||
if (this.debugMode && processedCount > 0) {
|
||||
console.log(`[HeroAtkSystem] ${model.hero_name} 伤害队列处理完成,共处理 ${processedCount} 个伤害事件`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 执行攻击计算
|
||||
* @param target 目标实体
|
||||
* @param damageEvent 伤害事件数据
|
||||
* @returns 最终伤害数据
|
||||
*/
|
||||
private doAttack(target: ecs.Entity, damageEvent: DamageEvent): FinalData {
|
||||
const targetAttrs = target.get(HeroAttrsComp);
|
||||
const targetView = target.get(HeroViewComp);
|
||||
let reDate:FinalData={
|
||||
damage:0,
|
||||
isCrit:false,
|
||||
isDodge:false,
|
||||
}
|
||||
if (!targetAttrs || targetAttrs.is_dead) return reDate;
|
||||
|
||||
const caster = damageEvent.caster;
|
||||
const attackerModel = caster?.ent?.get(HeroAttrsComp);
|
||||
|
||||
// 获取技能配置
|
||||
const skillConf = SkillSet[damageEvent.s_uuid];
|
||||
if (!skillConf) return reDate;
|
||||
|
||||
// 触发被攻击事件
|
||||
this.onAttacked(target);
|
||||
|
||||
// 闪避判定
|
||||
const isDodge =this.checkChance(targetAttrs.Attrs[Attrs.DODGE] || 0);
|
||||
if (isDodge) {
|
||||
// TODO: 触发闪避视图表现
|
||||
reDate.isDodge=true;
|
||||
return reDate;
|
||||
}
|
||||
// 暴击判定
|
||||
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));
|
||||
reDate.isCrit=true;
|
||||
}
|
||||
// 伤害计算(考虑易伤等debuff)
|
||||
damage = this.calculateDamage(targetAttrs, damage);
|
||||
// 护盾吸收
|
||||
damage =Math.floor(this.absorbShield(targetAttrs, damage))
|
||||
if (damage <= 0) return reDate;
|
||||
// 应用伤害到数据层
|
||||
targetAttrs.hp -= damage;
|
||||
targetAttrs.atked_count++;
|
||||
//击退判定
|
||||
const isBack = this.checkChance(damageEvent.Attrs[Attrs.BACK_CHANCE] || 0);
|
||||
if (isBack) attackerModel?.clearTalBuffByAttr(Attrs.BACK_CHANCE);
|
||||
|
||||
|
||||
// ✅ 触发视图层表现(伤害数字、受击动画、后退)
|
||||
if (targetView) targetView.do_atked(damage, isCrit, damageEvent.s_uuid, isBack);
|
||||
|
||||
|
||||
// 检查死亡
|
||||
if (targetAttrs.hp <= 0) {
|
||||
this.doDead(target);
|
||||
// ✅ 触发死亡视图表现
|
||||
if (targetView) {
|
||||
targetView.do_dead();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.debugMode) {
|
||||
console.log(`[HeroAtkSystem] ${targetAttrs.hero_name} 受到 ${damage} 点伤害 (暴击: ${isCrit})`);
|
||||
}
|
||||
|
||||
reDate.damage=damage;
|
||||
return reDate;
|
||||
}
|
||||
//伤害计算,暂时简单计算
|
||||
private dmgCount(CAttrs:any,s_uuid:number){
|
||||
let sConf = SkillSet[s_uuid];
|
||||
if (!sConf) return 0;
|
||||
let AP = sConf.ap*CAttrs[Attrs.AP]/100;
|
||||
return AP;
|
||||
}
|
||||
/**
|
||||
* 处理角色死亡
|
||||
*/
|
||||
private doDead(entity: ecs.Entity): void {
|
||||
const model = entity.get(HeroAttrsComp);
|
||||
if (!model || model.is_dead) return;
|
||||
|
||||
model.is_dead = true;
|
||||
|
||||
// 触发死亡事件
|
||||
this.onDeath(entity);
|
||||
|
||||
if (this.debugMode) {
|
||||
console.log(`[HeroAtkSystem] ${model.hero_name} 死亡`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 暴击判定
|
||||
*/
|
||||
private checkChance(rate: number): boolean {
|
||||
if (rate <= 0) return false;
|
||||
const r = Math.random() * 100;
|
||||
return r < rate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 伤害计算(考虑易伤等debuff)
|
||||
*/
|
||||
private calculateDamage(model: HeroAttrsComp, baseDamage: number): number {
|
||||
// 这里可以添加易伤等debuff的计算逻辑
|
||||
// 例如:如果目标有易伤buff,增加受到的伤害
|
||||
return baseDamage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 护盾吸收伤害
|
||||
*/
|
||||
private absorbShield(model: HeroAttrsComp, damage: number): number {
|
||||
if (model.shield <= 0) return damage;
|
||||
|
||||
if (model.shield >= damage) {
|
||||
model.shield -= damage;
|
||||
if (model.shield <= 0) {
|
||||
model.shield = 0;
|
||||
model.Attrs[Attrs.SHIELD_MAX] = 0;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
const remainingDamage = damage - model.shield;
|
||||
model.shield = 0;
|
||||
model.Attrs[Attrs.SHIELD_MAX] = 0;
|
||||
return remainingDamage;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 被攻击时触发的事件
|
||||
*/
|
||||
private onAttacked(entity: ecs.Entity): void {
|
||||
const model = entity.get(HeroAttrsComp);
|
||||
if (!model || model.is_dead) return;
|
||||
|
||||
// 这里可以添加被攻击时的特殊处理逻辑
|
||||
if (model.fac === FacSet.MON) return;
|
||||
|
||||
// 例如:触发某些天赋效果、反击逻辑等
|
||||
}
|
||||
|
||||
/**
|
||||
* 死亡时触发的事件
|
||||
*/
|
||||
private onDeath(entity: ecs.Entity): void {
|
||||
const model = entity.get(HeroAttrsComp);
|
||||
if (!model) return;
|
||||
|
||||
if (model.fac === FacSet.MON) {
|
||||
// 怪物死亡处理
|
||||
this.scheduleDrop(entity);
|
||||
} else if (model.fac === FacSet.HERO) {
|
||||
// 英雄死亡处理
|
||||
this.scheduleHeroDeath(entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟执行掉落逻辑
|
||||
*/
|
||||
private scheduleDrop(entity: ecs.Entity): void {
|
||||
// 这里可以添加掉落逻辑
|
||||
// 例如:延迟一段时间后生成掉落物品
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟执行英雄死亡逻辑
|
||||
*/
|
||||
private scheduleHeroDeath(entity: ecs.Entity): void {
|
||||
// 这里可以添加英雄死亡的特殊处理
|
||||
// 例如:触发游戏结束、复活机制等
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用调试模式
|
||||
*/
|
||||
enableDebug() {
|
||||
this.debugMode = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用调试模式
|
||||
*/
|
||||
disableDebug() {
|
||||
this.debugMode = false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user