Files
heros/assets/script/game/hero/HeroAtk.ts
panw 40e0086be3 refactor(hero): 移除SkillConComp并添加ECS系统注册装饰器
- 删除废弃的SkillConComp组件及其meta文件
- 为HeroAtkSystem、HeroAttrSystem等系统添加@ecs.register装饰器
- 在生命周期系统中添加空安全检查
- 移除SkillConComp相关引用及调试日志
- 在移动系统中添加节点有效性检查
2025-10-30 16:31:44 +08:00

248 lines
7.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { FacSet } from "../common/config/BoxSet";
import { Attrs } from "../common/config/HeroAttrs";
import { FightSet } from "../common/config/Mission";
import { SkillSet } from "../common/config/SkillSet";
import { HeroAttrsComp } from "./HeroAttrsComp";
import { HeroViewComp } from "./HeroViewComp";
/** 业务层对象 */
@ecs.register('HeroAtk')
export class HeroAtkComp extends ecs.Comp {
/** 业务层组件移除时,重置所有数据为默认值 */
reset() {
}
}
/** 业务层业务逻辑处理对象 */
@ecs.register('HeroAtkSystem')
export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate, ecs.IEntityEnterSystem {
private debugMode: boolean = false; // 是否启用调试模式
/**
* 过滤器:只处理拥有 HeroAttrsComp 的实体
*/
filter(): ecs.IMatcher {
return ecs.allOf(HeroAttrsComp);
}
/**
* 实体首次进入系统时调用(每个实体只调用一次)
*/
entityEnter(e: ecs.Entity): void {
const model = e.get(HeroAttrsComp);
if (!model) return;
console.log(`[HeroBattleSystem] 英雄进入战斗系统: ${model.hero_name} (uuid: ${model.hero_uuid})`);
}
/**
* 处理角色被攻击
* @param target 被攻击的目标实体
* @param remainingDamage 基础伤害值
* @param attackerAttrs 攻击者的属性
* @param skillId 技能ID
* @returns 实际造成的伤害
*/
public doAttack(target: ecs.Entity, remainingDamage: number, attackerAttrs: any, skillId: number): number {
const targetModel = target.get(HeroAttrsComp);
const targetView = target.get(HeroViewComp);
if (!targetModel || targetModel.is_dead) return 0;
// 获取技能配置
const skillConf = SkillSet[skillId];
// 触发被攻击事件
this.onAttacked(target);
// 闪避判定
if (this.checkDodge(targetModel)) {
// TODO: 触发闪避视图表现
return 0;
}
// 暴击判定
const isCrit = this.checkCrit(attackerAttrs[Attrs.CRITICAL]);
let damage = remainingDamage;
if (isCrit) {
damage = Math.floor(damage * (1 + (FightSet.CRIT_DAMAGE + attackerAttrs[Attrs.CRITICAL_DMG]) / 100));
}
// 伤害计算考虑易伤等debuff
damage = this.calculateDamage(targetModel, damage);
// 护盾吸收
damage = this.absorbShield(targetModel, damage);
if (damage <= 0) return 0;
// 应用伤害到数据层
targetModel.hp -= damage;
targetModel.atked_count++;
// ✅ 触发视图层表现(伤害数字、受击动画、后退)
if (targetView) {
targetView.do_atked(damage, isCrit, skillId);
}
// 检查死亡
if (targetModel.hp <= 0) {
this.doDead(target);
// ✅ 触发死亡视图表现
if (targetView) {
targetView.do_dead();
}
}
if (this.debugMode) {
console.log(`[HeroAtkSystem] ${targetModel.hero_name} 受到 ${damage} 点伤害 (暴击: ${isCrit})`);
}
return damage;
}
/**
* 处理角色死亡
*/
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(`[HeroBattleSystem] ${model.hero_name} 死亡`);
}
}
/**
* 闪避判定
*/
private checkDodge(model: HeroAttrsComp): boolean {
if (model.Attrs[Attrs.DODGE] > 0) {
const random = Math.random() * 100;
if (random < model.Attrs[Attrs.DODGE]) {
if (this.debugMode) {
console.log(`[HeroBattleSystem] ${model.hero_name} 闪避了攻击`);
}
return true;
}
}
return false;
}
/**
* 暴击判定
*/
private checkCrit(critRate: number): boolean {
if (critRate > 0) {
const random = Math.random() * 100;
return random < critRate;
}
return false;
}
/**
* 伤害计算考虑易伤等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;
}
/**
* 系统更新(每帧调用)
* 可以在这里添加需要每帧处理的战斗逻辑
*/
update(e: ecs.Entity): void {
// 这里可以添加需要每帧处理的战斗逻辑
// 例如:持续伤害、战斗状态检查等
}
}