refactor(战斗系统): 重构攻击处理逻辑并优化击退机制
- 将闪避、暴击和击退的概率检查统一为checkChance方法 - 移除HeroAtkComp类并清理无用代码 - 新增clearTalBuffByAttr方法用于清除特定属性的天赋buff - 修改HeroViewComp.do_atked方法支持可选击退参数 - 移除Attrs.BACK属性及相关配置
This commit is contained in:
@@ -108,7 +108,6 @@ export enum Attrs {
|
|||||||
// ========== 武器进化相关 (70-79) ==========
|
// ========== 武器进化相关 (70-79) ==========
|
||||||
PUNCTURE = 70, // 穿刺次数
|
PUNCTURE = 70, // 穿刺次数
|
||||||
PUNCTURE_DMG = 71, // 穿刺伤害
|
PUNCTURE_DMG = 71, // 穿刺伤害
|
||||||
BACK = 73, // 被击退概率(兼容旧代码)
|
|
||||||
MOVE_SPEED = 74, // 移动速度
|
MOVE_SPEED = 74, // 移动速度
|
||||||
BURN = 75, // 易伤效果
|
BURN = 75, // 易伤效果
|
||||||
WFUNY = 77, // 风怒
|
WFUNY = 77, // 风怒
|
||||||
@@ -220,7 +219,6 @@ export const AttrsType: Record<Attrs, BType> = {
|
|||||||
// ========== 武器进化相关(混合类型) ==========
|
// ========== 武器进化相关(混合类型) ==========
|
||||||
[Attrs.PUNCTURE]: BType.VALUE, // 穿刺次数 - 数值型
|
[Attrs.PUNCTURE]: BType.VALUE, // 穿刺次数 - 数值型
|
||||||
[Attrs.PUNCTURE_DMG]: BType.RATIO, // 穿刺伤害 - 百分比型
|
[Attrs.PUNCTURE_DMG]: BType.RATIO, // 穿刺伤害 - 百分比型
|
||||||
[Attrs.BACK]: BType.RATIO, // 被击退概率(兼容)- 百分比型
|
|
||||||
[Attrs.MOVE_SPEED]: BType.VALUE, // 移动速度 - 数值型
|
[Attrs.MOVE_SPEED]: BType.VALUE, // 移动速度 - 数值型
|
||||||
[Attrs.BURN]: BType.RATIO, // 易伤效果 - 百分比型
|
[Attrs.BURN]: BType.RATIO, // 易伤效果 - 百分比型
|
||||||
[Attrs.WFUNY]: BType.RATIO, // 未知特殊属性 - 百分比型
|
[Attrs.WFUNY]: BType.RATIO, // 未知特殊属性 - 百分比型
|
||||||
|
|||||||
@@ -8,14 +8,7 @@ import { HeroViewComp } from "./HeroViewComp";
|
|||||||
import { DamageQueueComp, DamageEvent, DamageQueueHelper } from "./DamageQueueComp";
|
import { DamageQueueComp, DamageEvent, DamageQueueHelper } from "./DamageQueueComp";
|
||||||
import { smc } from "../common/SingletonModuleComp";
|
import { smc } from "../common/SingletonModuleComp";
|
||||||
|
|
||||||
/** 业务层对象 */
|
|
||||||
@ecs.register('HeroAtk')
|
|
||||||
export class HeroAtkComp extends ecs.Comp {
|
|
||||||
/** 业务层组件移除时,重置所有数据为默认值 */
|
|
||||||
reset() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/** 最终伤害数据接口 */
|
/** 最终伤害数据接口 */
|
||||||
interface FinalData {
|
interface FinalData {
|
||||||
damage: number;
|
damage: number;
|
||||||
@@ -94,17 +87,17 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
* @returns 最终伤害数据
|
* @returns 最终伤害数据
|
||||||
*/
|
*/
|
||||||
private doAttack(target: ecs.Entity, damageEvent: DamageEvent): FinalData {
|
private doAttack(target: ecs.Entity, damageEvent: DamageEvent): FinalData {
|
||||||
const targetModel = target.get(HeroAttrsComp);
|
const targetAttrs = target.get(HeroAttrsComp);
|
||||||
const targetView = target.get(HeroViewComp);
|
const targetView = target.get(HeroViewComp);
|
||||||
let reDate:FinalData={
|
let reDate:FinalData={
|
||||||
damage:0,
|
damage:0,
|
||||||
isCrit:false,
|
isCrit:false,
|
||||||
isDodge:false,
|
isDodge:false,
|
||||||
}
|
}
|
||||||
if (!targetModel || targetModel.is_dead) return reDate;
|
if (!targetAttrs || targetAttrs.is_dead) return reDate;
|
||||||
|
|
||||||
// 获取攻击者数据
|
|
||||||
const caster = damageEvent.caster;
|
const caster = damageEvent.caster;
|
||||||
|
const attackerModel = caster?.ent?.get(HeroAttrsComp);
|
||||||
|
|
||||||
// 获取技能配置
|
// 获取技能配置
|
||||||
const skillConf = SkillSet[damageEvent.s_uuid];
|
const skillConf = SkillSet[damageEvent.s_uuid];
|
||||||
@@ -114,38 +107,40 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
this.onAttacked(target);
|
this.onAttacked(target);
|
||||||
|
|
||||||
// 闪避判定
|
// 闪避判定
|
||||||
if (this.checkDodge(targetModel)) {
|
const isDodge =this.checkChance(targetAttrs.Attrs[Attrs.DODGE] || 0);
|
||||||
|
if (isDodge) {
|
||||||
// TODO: 触发闪避视图表现
|
// TODO: 触发闪避视图表现
|
||||||
reDate.isDodge=true;
|
reDate.isDodge=true;
|
||||||
return reDate;
|
return reDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 暴击判定
|
// 暴击判定
|
||||||
const isCrit = this.checkCrit(targetModel.Attrs[Attrs.CRITICAL]);
|
const isCrit = this.checkChance(damageEvent.Attrs[Attrs.CRITICAL]);
|
||||||
|
if (isCrit) attackerModel?.clearTalBuffByAttr(Attrs.CRITICAL);
|
||||||
|
// 计算伤害
|
||||||
let damage = this.dmgCount(damageEvent.Attrs,damageEvent.s_uuid);
|
let damage = this.dmgCount(damageEvent.Attrs,damageEvent.s_uuid);
|
||||||
if (isCrit) {
|
if (isCrit) {
|
||||||
damage = Math.floor(damage * (1 + (FightSet.CRIT_DAMAGE + targetModel.Attrs[Attrs.CRITICAL_DMG]) / 100));
|
damage = Math.floor(damage * (1 + (FightSet.CRIT_DAMAGE + targetAttrs.Attrs[Attrs.CRITICAL_DMG]) / 100));
|
||||||
reDate.isCrit=true;
|
reDate.isCrit=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 伤害计算(考虑易伤等debuff)
|
// 伤害计算(考虑易伤等debuff)
|
||||||
damage = this.calculateDamage(targetModel, damage);
|
damage = this.calculateDamage(targetAttrs, damage);
|
||||||
|
|
||||||
// 护盾吸收
|
// 护盾吸收
|
||||||
damage =Math.floor(this.absorbShield(targetModel, damage))
|
damage =Math.floor(this.absorbShield(targetAttrs, damage))
|
||||||
if (damage <= 0) return reDate;
|
if (damage <= 0) return reDate;
|
||||||
|
|
||||||
// 应用伤害到数据层
|
// 应用伤害到数据层
|
||||||
targetModel.hp -= damage;
|
targetAttrs.hp -= damage;
|
||||||
targetModel.atked_count++;
|
targetAttrs.atked_count++;
|
||||||
|
//击退判定
|
||||||
|
const isBack = this.checkChance(damageEvent.Attrs[Attrs.BACK_CHANCE] || 0);
|
||||||
|
if (isBack) attackerModel?.clearTalBuffByAttr(Attrs.BACK_CHANCE);
|
||||||
|
|
||||||
|
|
||||||
// ✅ 触发视图层表现(伤害数字、受击动画、后退)
|
// ✅ 触发视图层表现(伤害数字、受击动画、后退)
|
||||||
if (targetView) {
|
if (targetView) targetView.do_atked(damage, isCrit, damageEvent.s_uuid, isBack);
|
||||||
targetView.do_atked(damage, isCrit, damageEvent.s_uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查死亡
|
// 检查死亡
|
||||||
if (targetModel.hp <= 0) {
|
if (targetAttrs.hp <= 0) {
|
||||||
this.doDead(target);
|
this.doDead(target);
|
||||||
// ✅ 触发死亡视图表现
|
// ✅ 触发死亡视图表现
|
||||||
if (targetView) {
|
if (targetView) {
|
||||||
@@ -154,7 +149,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.debugMode) {
|
if (this.debugMode) {
|
||||||
console.log(`[HeroAtkSystem] ${targetModel.hero_name} 受到 ${damage} 点伤害 (暴击: ${isCrit})`);
|
console.log(`[HeroAtkSystem] ${targetAttrs.hero_name} 受到 ${damage} 点伤害 (暴击: ${isCrit})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
reDate.damage=damage;
|
reDate.damage=damage;
|
||||||
@@ -184,31 +179,15 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 闪避判定
|
|
||||||
*/
|
|
||||||
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 {
|
private checkChance(rate: number): boolean {
|
||||||
if (critRate > 0) {
|
if (rate <= 0) return false;
|
||||||
const random = Math.random() * 100;
|
const r = Math.random() * 100;
|
||||||
return random < critRate;
|
return r < rate;
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -425,6 +425,17 @@ export class HeroAttrsComp extends ecs.Comp {
|
|||||||
delete this.BUFFS_TAL[t_uuid];
|
delete this.BUFFS_TAL[t_uuid];
|
||||||
this.recalculateSingleAttr(attrIndex);
|
this.recalculateSingleAttr(attrIndex);
|
||||||
}
|
}
|
||||||
|
clearTalBuffByAttr(attrIndex: number) {
|
||||||
|
let changed = false;
|
||||||
|
for (const key in this.BUFFS_TAL) {
|
||||||
|
const b = this.BUFFS_TAL[Number(key)];
|
||||||
|
if (b && b.attrIndex === attrIndex) {
|
||||||
|
delete this.BUFFS_TAL[Number(key)];
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed) this.recalculateSingleAttr(attrIndex);
|
||||||
|
}
|
||||||
|
|
||||||
addTalent(eff: number, value: number) {
|
addTalent(eff: number, value: number) {
|
||||||
const t = this.Talents[eff] || { value: 0, count: 0 };
|
const t = this.Talents[eff] || { value: 0, count: 0 };
|
||||||
|
|||||||
@@ -350,7 +350,7 @@ export class HeroViewComp extends CCComp {
|
|||||||
this.ent.destroy();
|
this.ent.destroy();
|
||||||
|
|
||||||
}
|
}
|
||||||
do_atked(damage:number,isCrit:boolean,s_uuid:number){
|
do_atked(damage:number,isCrit:boolean,s_uuid:number,isBack:boolean=false){
|
||||||
// 受到攻击时显示血条,并设置显示时间(即使伤害为0也显示)
|
// 受到攻击时显示血条,并设置显示时间(即使伤害为0也显示)
|
||||||
this.top_node.active = true;
|
this.top_node.active = true;
|
||||||
this.hpBarShowCD = this.hpBarShowTime;
|
this.hpBarShowCD = this.hpBarShowTime;
|
||||||
@@ -359,8 +359,8 @@ export class HeroViewComp extends CCComp {
|
|||||||
|
|
||||||
// 视图层表现
|
// 视图层表现
|
||||||
let SConf=SkillSet[s_uuid]
|
let SConf=SkillSet[s_uuid]
|
||||||
this.back()
|
if (isBack) this.back()
|
||||||
this.showDamage(damage, isCrit, SConf.DAnm); // 暴击状态由战斗系统内部处理, DAnm和EAnm共用设定数组
|
this.showDamage(damage, isCrit, SConf.DAnm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private isBackingUp: boolean = false; // 🔥 添加后退状态标记
|
private isBackingUp: boolean = false; // 🔥 添加后退状态标记
|
||||||
|
|||||||
Reference in New Issue
Block a user