- 删除废弃的SkillConComp组件及其meta文件 - 为HeroAtkSystem、HeroAttrSystem等系统添加@ecs.register装饰器 - 在生命周期系统中添加空安全检查 - 移除SkillConComp相关引用及调试日志 - 在移动系统中添加节点有效性检查
248 lines
7.1 KiB
TypeScript
248 lines
7.1 KiB
TypeScript
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 {
|
||
// 这里可以添加需要每帧处理的战斗逻辑
|
||
// 例如:持续伤害、战斗状态检查等
|
||
}
|
||
} |