refactor(hero): 重构英雄属性与状态管理
- 将增益效果属性组移到武器进化属性后以优化结构 - 新增 in_stun 和 in_frost 状态标志替代 isStun/isFrost 方法 - 更新状态检查逻辑以使用新的状态标志 - 移除 HeroSkillsComp 依赖以简化移动系统 - 修改伤害计算直接使用 HeroAttrsComp 属性而非 Attrs 映射 - 简化暴击、击退等判定逻辑,移除闪避和抗性计算 - 优化 reset 方法,设置合理的默认值并重置新增状态标志 - 添加状态变化时的调试日志输出
This commit is contained in:
@@ -7,7 +7,6 @@ import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { HeroViewComp } from "./HeroViewComp";
|
||||
import { DamageQueueComp, DamageEvent } from "./DamageQueueComp";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { TalAttrs } from "../common/config/TalSet";
|
||||
import { oops } from "db://oops-framework/core/Oops";
|
||||
import { GameEvent } from "../common/config/GameEvent";
|
||||
|
||||
@@ -141,19 +140,9 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
// 触发被攻击事件
|
||||
this.onAttacked(target);
|
||||
|
||||
// 闪避判定
|
||||
// 闪避成功概率 = 被攻击者闪避率 - 施法者命中率
|
||||
// TAttrsComp.Attrs[Attrs.DODGE]: 被攻击者的实时闪避属性
|
||||
// damageEvent.Attrs[Attrs.HIT]: 施法者在技能创建时的命中属性快照
|
||||
const isDodge =this.checkChance((TAttrsComp.Attrs[Attrs.DODGE]-damageEvent.Attrs[Attrs.HIT]) || 0);
|
||||
if (isDodge) {
|
||||
// TODO: 触发闪避视图表现
|
||||
reDate.isDodge=true;
|
||||
return reDate;
|
||||
}
|
||||
// 暴击判定
|
||||
// 使用施法者的暴击率属性(damageEvent.Attrs 快照),- 被攻击者的暴击抗性属性TAttrsComp.Attrs[Attrs.CRITICAL_RES]
|
||||
const isCrit = this.checkChance(damageEvent.Attrs[Attrs.CRITICAL]-TAttrsComp.Attrs[Attrs.CRITICAL_RES]);
|
||||
// 使用施法者的暴击率属性(damageEvent.Attrs 快照),- 被攻击者的暴击抗性属
|
||||
const isCrit = this.checkChance(damageEvent.Attrs[Attrs.CRITICAL]);
|
||||
// 计算基础伤害
|
||||
let damage = this.dmgCount(damageEvent,TAttrsComp);
|
||||
|
||||
@@ -165,7 +154,6 @@ 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;
|
||||
CAttrsComp?.useValueTalByAttr(Attrs.CRITICAL); // 清除施法者的暴击buff
|
||||
|
||||
}
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', " after crit",damage)
|
||||
@@ -187,8 +175,6 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
// targetView.back();
|
||||
// }
|
||||
|
||||
smc.updateHeroInfo(TAttrsComp); // 更新英雄数据到 VM
|
||||
|
||||
const casterName = CAttrsComp?.hero_name || "未知";
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', ` 英雄${TAttrsComp.hero_name} (uuid: ${TAttrsComp.hero_uuid}) 受到 ${casterName}(eid: ${casterEid})的 伤害 ${damage},${isCrit?"暴击":"普通"}攻击,技能ID ${damageEvent.s_uuid}`);
|
||||
|
||||
@@ -197,8 +183,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
// 击退判定
|
||||
// 使用施法者的击退概率属性(damageEvent.Attrs 快照) - 被攻击者的控制抗性
|
||||
// 击退成功后需要清理施法者的相关天赋buff
|
||||
const isBack = this.checkChance((damageEvent.Attrs[Attrs.BACK_CHANCE] || 0) - (TAttrsComp.Attrs[Attrs.CON_RES] || 0));
|
||||
if (isBack) CAttrsComp?.useValueTalByAttr(Attrs.BACK_CHANCE);
|
||||
const isBack = this.checkChance((damageEvent.Attrs[Attrs.BACK_CHANCE] || 0));
|
||||
|
||||
|
||||
// ✅ 触发视图层表现(伤害数字、受击动画、后退)
|
||||
@@ -208,8 +193,8 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
// 检查死亡
|
||||
if (TAttrsComp.hp <= 0) {
|
||||
// 复活机制:如果玩家属性内的复活属性值>=1 则执行复活,原地50%血量复活
|
||||
if (TAttrsComp.is_master && TAttrsComp.Attrs[Attrs.REVIVE_COUNT] >= 1) {
|
||||
TAttrsComp.Attrs[Attrs.REVIVE_COUNT]--;
|
||||
if (TAttrsComp.is_master && TAttrsComp.revive_count >= 1) {
|
||||
TAttrsComp.revive_count--;
|
||||
TAttrsComp.is_reviving = true; // 标记为正在复活
|
||||
|
||||
// 停止怪物行动
|
||||
@@ -222,18 +207,18 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
targetView.scheduleRevive(1.0);
|
||||
}
|
||||
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', ` Hero waiting to revive! Lives left: ${TAttrsComp.Attrs[Attrs.REVIVE_COUNT]}`);
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', ` Hero waiting to revive! Lives left: ${TAttrsComp.revive_count}`);
|
||||
return reDate;
|
||||
}
|
||||
|
||||
// 增加被击杀计数
|
||||
if (caster) CAttrsComp.Attrs.killed_count++;
|
||||
if (caster) CAttrsComp.killed_count++;
|
||||
|
||||
// 玩家英雄死亡后,怪物停止刷新和移动
|
||||
if (TAttrsComp.is_master&&TAttrsComp.Attrs[Attrs.REVIVE_COUNT] <= 0) {
|
||||
if (TAttrsComp.is_master&&TAttrsComp.revive_count <= 0) {
|
||||
smc.mission.stop_mon_action = true;
|
||||
oops.message.dispatchEvent(GameEvent.HeroDead, { hero_uuid: TAttrsComp.hero_uuid});
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', " Hero died, stopping monster action (spawn/move)"+TAttrsComp.Attrs[Attrs.REVIVE_COUNT]);
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', " Hero died, stopping monster action (spawn/move)"+TAttrsComp.revive_count);
|
||||
}
|
||||
|
||||
this.doDead(target);
|
||||
@@ -268,8 +253,8 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
// 检查死亡
|
||||
if (CAttrs.hp <= 0) {
|
||||
// 复活机制
|
||||
if (CAttrs.is_master && CAttrs.Attrs[Attrs.REVIVE_COUNT] >= 1) {
|
||||
CAttrs.Attrs[Attrs.REVIVE_COUNT]--;
|
||||
if (CAttrs.is_master && CAttrs.revive_count >= 1) {
|
||||
CAttrs.revive_count--;
|
||||
CAttrs.is_reviving = true;
|
||||
|
||||
smc.mission.stop_mon_action = true;
|
||||
@@ -279,12 +264,12 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
CView.scheduleRevive(1.0);
|
||||
}
|
||||
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', ` Hero waiting to revive from Thorns! Lives left: ${CAttrs.Attrs[Attrs.REVIVE_COUNT]}`);
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', ` Hero waiting to revive from Thorns! Lives left: ${CAttrs.revive_count}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 玩家英雄死亡后,怪物停止刷新和移动
|
||||
if (CAttrs.is_master&&CAttrs.Attrs[Attrs.REVIVE_COUNT] <= 0) {
|
||||
if (CAttrs.is_master&&CAttrs.revive_count <= 0) {
|
||||
smc.mission.stop_mon_action = true;
|
||||
oops.message.dispatchEvent(GameEvent.HeroDead, { hero_uuid: CAttrs.hero_uuid});
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', " Hero died from thorns, stopping monster action (spawn/move)");
|
||||
@@ -292,7 +277,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
|
||||
this.doDead(caster);
|
||||
// 增加击杀计数
|
||||
if (caster) TAttrsComp.Attrs.killed_count++;
|
||||
if (caster) TAttrsComp.killed_count++;
|
||||
// ✅ 触发死亡视图表现
|
||||
if (CView) {
|
||||
CView.do_dead();
|
||||
@@ -320,7 +305,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
private dmgCount(damageEvent:DamageEvent,TAttrsComp:HeroAttrsComp){
|
||||
// 1. 获取技能配置 - 如果技能不存在,直接返回0伤害
|
||||
const CAttrs=damageEvent.Attrs;
|
||||
const TAttrs=TAttrsComp.Attrs;
|
||||
const TAttrs=TAttrsComp;
|
||||
let sConf = SkillSet[damageEvent.s_uuid];
|
||||
if (!sConf) return 0;
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', ` 伤害处理对象`,CAttrs,TAttrs);
|
||||
|
||||
@@ -49,18 +49,20 @@ export class HeroAttrsComp extends ecs.Comp {
|
||||
back_chance: number = 0; // 击退概率
|
||||
slow_chance: number = 0; // 减速概率
|
||||
|
||||
// ==================== 增益效果属性 ====================
|
||||
revive_count: number = 0; // 复活次数
|
||||
revive_time: number = 0; // 复活时间
|
||||
invincible_time: number = 0;// 无敌时间
|
||||
|
||||
// ==================== 武器进化相关 ====================
|
||||
puncture: number = 0; // 穿刺次数
|
||||
puncture_dmg: number = 0; // 穿刺伤害
|
||||
wfuny: number = 0; // 风怒
|
||||
|
||||
// ==================== 增益效果属性 ====================
|
||||
revive_count: number = 0; // 复活次数
|
||||
revive_time: number = 0; // 复活时间
|
||||
invincible_time: number = 0;// 无敌时间
|
||||
|
||||
|
||||
in_stun=false
|
||||
in_frost=false
|
||||
|
||||
boom: boolean = false; // 自爆怪
|
||||
|
||||
|
||||
@@ -303,9 +305,8 @@ export class HeroAttrsComp extends ecs.Comp {
|
||||
|
||||
private updateStatusFlags() {
|
||||
// 检查特定状态的 Debuff 列表是否为空,来更新 boolean 标志
|
||||
// 例如:冰冻
|
||||
this.checkStatus(Attrs.IN_FROST, 'is_stop'); // 假设冰冻会停止行动
|
||||
// this.checkStatus(Attrs.IN_STUN, 'is_stunned'); // 需要在类里定义 is_stunned
|
||||
this.checkStatus(Attrs.IN_FROST, 'in_frost');
|
||||
this.checkStatus(Attrs.IN_STUN, 'in_stun');
|
||||
}
|
||||
|
||||
private checkStatus(attr: Attrs, flagName: string) {
|
||||
@@ -314,9 +315,11 @@ export class HeroAttrsComp extends ecs.Comp {
|
||||
|
||||
// 只有当状态改变时才赋值,避免每帧赋值
|
||||
if (this[flagName] !== hasBuff) {
|
||||
// 特殊处理:有些状态可能由其他逻辑控制,这里强行覆盖可能会冲突
|
||||
// 但作为 Buff 系统,它应该拥有最高解释权之一
|
||||
this[flagName] = hasBuff;
|
||||
// 状态变化日志
|
||||
if (this.debugMode) {
|
||||
mLogger.log(this.debugMode, 'HeroAttrs', `状态变更: ${this.hero_name}, ${flagName} = ${hasBuff}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,11 +366,12 @@ export class HeroAttrsComp extends ecs.Comp {
|
||||
this.lv = 1;
|
||||
this.type = 0;
|
||||
this.fac = 0;
|
||||
this.rangeType = SkillRange.Melee;
|
||||
this.ap = 0;
|
||||
this.hp = 100;
|
||||
this.hp_max = 100;
|
||||
this.speed = 100;
|
||||
this.dis = 0;
|
||||
this.hp = 100;
|
||||
this.dis = 100;
|
||||
this.shield = 0;
|
||||
this.shield_max = 0;
|
||||
|
||||
@@ -390,11 +394,15 @@ export class HeroAttrsComp extends ecs.Comp {
|
||||
this.wfuny = 0;
|
||||
this.boom = false;
|
||||
|
||||
this.in_frost = false;
|
||||
this.in_stun = false;
|
||||
|
||||
this.BUFFS = {};
|
||||
this.DEBUFFS = {};
|
||||
// 重置技能距离缓存
|
||||
this.maxSkillDistance = 0;
|
||||
this.minSkillDistance = 0;
|
||||
|
||||
this.is_dead = false;
|
||||
this.is_count_dead = false;
|
||||
this.is_atking = false;
|
||||
@@ -405,9 +413,13 @@ export class HeroAttrsComp extends ecs.Comp {
|
||||
this.is_friend = false;
|
||||
this.is_kalami = false;
|
||||
this.is_reviving = false;
|
||||
|
||||
this.atk_count = 0;
|
||||
this.atked_count = 0;
|
||||
this.killed_count =0;
|
||||
this.atk_id = 0;
|
||||
this.skill_id = 0;
|
||||
|
||||
// 重置脏标签
|
||||
this.dirty_hp = false;
|
||||
this.dirty_shield = false;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { HeroViewComp } from "./HeroViewComp";
|
||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { HeroSkillsComp } from "./HeroSkills";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { FacSet } from "../common/config/GameSet";
|
||||
import { HType } from "../common/config/heroSet";
|
||||
@@ -29,7 +28,7 @@ export class HeroMoveComp extends ecs.Comp {
|
||||
@ecs.register('HeroMoveSystem')
|
||||
export class HeroMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||
filter(): ecs.IMatcher {
|
||||
return ecs.allOf(HeroMoveComp, HeroViewComp, HeroAttrsComp, HeroSkillsComp);
|
||||
return ecs.allOf(HeroMoveComp, HeroViewComp, HeroAttrsComp);
|
||||
}
|
||||
|
||||
update(e: ecs.Entity) {
|
||||
@@ -47,7 +46,7 @@ export class HeroMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
if (!move.moving) return;
|
||||
|
||||
// 2. 异常状态检查 (死亡/复活/眩晕/冰冻)
|
||||
if (model.is_stop || model.is_dead || model.is_reviving || model.isStun() || model.isFrost()) {
|
||||
if (model.is_stop || model.is_dead || model.is_reviving || model.in_stun || model.in_frost) {
|
||||
if (!model.is_reviving) view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
@@ -119,7 +118,7 @@ export class HeroMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
view.status_change("idle");
|
||||
model.is_atking = true;
|
||||
} else {
|
||||
const speed = model.Attrs[Attrs.SPEED] / 3;
|
||||
const speed = model.speed / 3;
|
||||
this.moveEntity(view, move.direction, speed);
|
||||
model.is_atking = false;
|
||||
}
|
||||
@@ -145,7 +144,7 @@ export class HeroMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
this.performRetreat(view, move, model, currentX);
|
||||
} else if (dist > maxRange) {
|
||||
// 太远了,追击
|
||||
const speed = model.Attrs[Attrs.SPEED] / 3;
|
||||
const speed = model.speed / 3;
|
||||
this.moveEntity(view, move.direction, speed);
|
||||
model.is_atking = false;
|
||||
} else {
|
||||
@@ -175,7 +174,7 @@ export class HeroMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
this.performRetreat(view, move, model, currentX);
|
||||
} else if (dist > maxRange) {
|
||||
// 太远了,追击
|
||||
const speed = model.Attrs[Attrs.SPEED] / 3;
|
||||
const speed = model.speed / 3;
|
||||
this.moveEntity(view, move.direction, speed);
|
||||
model.is_atking = false;
|
||||
} else {
|
||||
@@ -189,7 +188,7 @@ export class HeroMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
private performRetreat(view: HeroViewComp, move: HeroMoveComp, model: HeroAttrsComp, currentX: number) {
|
||||
const safeRetreatX = currentX - move.direction * 50;
|
||||
if (safeRetreatX >= -300 && safeRetreatX <= 300) {
|
||||
const retreatSpeed = (model.Attrs[Attrs.SPEED] / 3) * 0.8;
|
||||
const retreatSpeed = (model.speed / 3) * 0.8;
|
||||
this.moveEntity(view, -move.direction, retreatSpeed);
|
||||
model.is_atking = false;
|
||||
} else {
|
||||
@@ -214,7 +213,7 @@ export class HeroMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
|
||||
if (Math.abs(currentX - targetX) > 5) {
|
||||
const dir = targetX > currentX ? 1 : -1;
|
||||
const speed = model.Attrs[Attrs.SPEED] / 3;
|
||||
const speed = model.speed / 3;
|
||||
|
||||
// 修正朝向:回正
|
||||
move.direction = 1;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { HeroViewComp } from "./HeroViewComp";
|
||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { HeroSkillsComp } from "./HeroSkills";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { FacSet, IndexSet } from "../common/config/GameSet";
|
||||
import { Attrs } from "../common/config/HeroAttrs";
|
||||
@@ -38,7 +37,7 @@ export class MonMoveComp extends ecs.Comp {
|
||||
@ecs.register('MonMoveSystem')
|
||||
export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||
filter(): ecs.IMatcher {
|
||||
return ecs.allOf(MonMoveComp, HeroViewComp, HeroAttrsComp, HeroSkillsComp);
|
||||
return ecs.allOf(MonMoveComp, HeroViewComp, HeroAttrsComp);
|
||||
}
|
||||
|
||||
update(e: ecs.Entity) {
|
||||
@@ -61,7 +60,7 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
if (!move.moving) return;
|
||||
|
||||
// 2. 异常状态检查 (死亡/复活/眩晕/冰冻)
|
||||
if (model.is_stop || model.is_dead || model.isStun() || model.isFrost()) {
|
||||
if (model.is_stop || model.is_dead || model.in_stun|| model.in_frost) {
|
||||
view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
@@ -136,7 +135,7 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
view.status_change("idle");
|
||||
model.is_atking = true;
|
||||
} else {
|
||||
const speed = model.Attrs[Attrs.SPEED] / 3;
|
||||
const speed = model.speed / 3;
|
||||
this.moveEntity(view, move.direction, speed);
|
||||
model.is_atking = false;
|
||||
}
|
||||
@@ -162,7 +161,7 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
this.performRetreat(view, move, model, currentX);
|
||||
} else if (dist > maxRange) {
|
||||
// 太远了,追击
|
||||
const speed = model.Attrs[Attrs.SPEED] / 3;
|
||||
const speed = model.speed / 3;
|
||||
this.moveEntity(view, move.direction, speed);
|
||||
model.is_atking = false;
|
||||
} else {
|
||||
@@ -192,7 +191,7 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
this.performRetreat(view, move, model, currentX);
|
||||
} else if (dist > maxRange) {
|
||||
// 太远了,追击
|
||||
const speed = model.Attrs[Attrs.SPEED] / 3;
|
||||
const speed = model.speed / 3;
|
||||
this.moveEntity(view, move.direction, speed);
|
||||
model.is_atking = false;
|
||||
} else {
|
||||
@@ -207,7 +206,7 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
const safeRetreatX = currentX - move.direction * 50;
|
||||
// 怪物活动范围通常宽一些
|
||||
if (safeRetreatX >= -450 && safeRetreatX <= 450) {
|
||||
const retreatSpeed = (model.Attrs[Attrs.SPEED] / 3) * 0.8;
|
||||
const retreatSpeed = (model.speed / 3) * 0.8;
|
||||
this.moveEntity(view, -move.direction, retreatSpeed);
|
||||
model.is_atking = false;
|
||||
} else {
|
||||
@@ -227,7 +226,7 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
|
||||
if (Math.abs(currentX - targetX) > 5) {
|
||||
const dir = targetX > currentX ? 1 : -1;
|
||||
const speed = model.Attrs[Attrs.SPEED] / 3;
|
||||
const speed = model.speed / 3;
|
||||
|
||||
// 修正朝向
|
||||
move.direction = dir;
|
||||
|
||||
Reference in New Issue
Block a user