refactor(debug-log): 优化全模块调试日志格式与默认开关
1. 将BuffManager的静态DEBUG开关改为运行时可配置的debug属性,默认开启 2. 统一所有模块的调试日志输出格式,增加技能/ buff名称、UUID、目标信息和判定详情 3. 为HeroAtkSystem的概率判定添加统一日志,修复击退判定逻辑并补充日志 4. 开启SkillView和HeroAtkSystem的默认调试模式
This commit is contained in:
@@ -13,9 +13,6 @@ import { BuffCategory, BuffList } from "../common/config/BuffSet";
|
|||||||
import { BuffComp, ActiveBuff } from "./BuffComp";
|
import { BuffComp, ActiveBuff } from "./BuffComp";
|
||||||
import { mLogger } from "../common/Logger";
|
import { mLogger } from "../common/Logger";
|
||||||
|
|
||||||
/** Buff 模块调试日志开关 */
|
|
||||||
const DEBUG = false;
|
|
||||||
|
|
||||||
/** applyBuff 的覆盖参数(预留按需覆写持续时间 / 修饰数值) */
|
/** applyBuff 的覆盖参数(预留按需覆写持续时间 / 修饰数值) */
|
||||||
export interface BuffApplyOverrides {
|
export interface BuffApplyOverrides {
|
||||||
duration?: number;
|
duration?: number;
|
||||||
@@ -26,6 +23,9 @@ export interface BuffApplyOverrides {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BuffManagerImpl {
|
class BuffManagerImpl {
|
||||||
|
/** 调试日志开关:运行时可通过 buffManager.debug = false 关闭(测试期默认开启) */
|
||||||
|
public debug: boolean = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对目标施加一个 buff 实例。
|
* 对目标施加一个 buff 实例。
|
||||||
*
|
*
|
||||||
@@ -46,7 +46,7 @@ class BuffManagerImpl {
|
|||||||
mLogger.warn(true, "BuffManager", `applyBuff: buffId=${buffId} 配置不存在,跳过`);
|
mLogger.warn(true, "BuffManager", `applyBuff: buffId=${buffId} 配置不存在,跳过`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mLogger.log(DEBUG, "BuffManager", `applyBuff: buff=${cfg.name}(${buffId}) target_eid=${target.eid} duration=${overrides?.duration ?? cfg.duration} value_override=${overrides?.value} source_ap=${sourceAp}`);
|
mLogger.log(this.debug, "BuffManager", `[挂buff] 「${cfg.name}」(buffId:${buffId}) -> target_eid:${target.eid} duration:${overrides?.duration ?? cfg.duration} value:${overrides?.value ?? "-"} source_ap:${sourceAp}`);
|
||||||
|
|
||||||
const buffComp = this.ensureBuffComp(target);
|
const buffComp = this.ensureBuffComp(target);
|
||||||
const duration = overrides?.duration ?? cfg.duration;
|
const duration = overrides?.duration ?? cfg.duration;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ interface FinalData {
|
|||||||
@ecs.register('HeroAtkSystem')
|
@ecs.register('HeroAtkSystem')
|
||||||
export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||||
|
|
||||||
private debugMode: boolean = false; // 是否启用调试模式
|
private debugMode: boolean = true; // 是否启用调试模式
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 过滤器:处理拥有伤害队列的实体
|
* 过滤器:处理拥有伤害队列的实体
|
||||||
@@ -145,7 +145,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
|||||||
// 暴击判定
|
// 暴击判定
|
||||||
// 使用施法者的暴击率属性(damageEvent.Attrs 快照)- 被攻击者的暴击抗性 + 目标出血层数附加的被暴击率
|
// 使用施法者的暴击率属性(damageEvent.Attrs 快照)- 被攻击者的暴击抗性 + 目标出血层数附加的被暴击率
|
||||||
const criticalChance = (damageEvent.Attrs[Attrs.critical] || 0) - TAttrsComp.getFinalCriticalRes() + this.getBleedCritBonus(target);
|
const criticalChance = (damageEvent.Attrs[Attrs.critical] || 0) - TAttrsComp.getFinalCriticalRes() + this.getBleedCritBonus(target);
|
||||||
const isCrit = this.checkChance(criticalChance);
|
const isCrit = this.checkChance(criticalChance, `暴击->${TAttrsComp.hero_name}`);
|
||||||
|
|
||||||
// 计算基础伤害:DoT 直接用固定 tick 值,普攻走 dmgCount 公式
|
// 计算基础伤害:DoT 直接用固定 tick 值,普攻走 dmgCount 公式
|
||||||
let damage = isDot ? (damageEvent.dot_dmg ?? 0) : this.dmgCount(damageEvent, TAttrsComp);
|
let damage = isDot ? (damageEvent.dot_dmg ?? 0) : this.dmgCount(damageEvent, TAttrsComp);
|
||||||
@@ -214,15 +214,15 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
|||||||
|
|
||||||
// 冰冻判定
|
// 冰冻判定
|
||||||
const freezeChance = (damageEvent.Attrs[Attrs.freeze_chance] || 0) - (TAttrsComp.freeze_res || 0);
|
const freezeChance = (damageEvent.Attrs[Attrs.freeze_chance] || 0) - (TAttrsComp.freeze_res || 0);
|
||||||
const isFrost = !TAttrsComp.isFrost() && this.checkChance(freezeChance);
|
const isFrost = !TAttrsComp.isFrost() && this.checkChance(freezeChance, `冰冻->${TAttrsComp.hero_name}`);
|
||||||
|
|
||||||
// 击晕判定
|
// 击晕判定
|
||||||
const stunChance = (damageEvent.Attrs[Attrs.stun_chance] || 0) - TAttrsComp.getFinalStunRes();
|
const stunChance = (damageEvent.Attrs[Attrs.stun_chance] || 0) - TAttrsComp.getFinalStunRes();
|
||||||
const isStun = !TAttrsComp.isStun() && this.checkChance(stunChance);
|
const isStun = !TAttrsComp.isStun() && this.checkChance(stunChance, `击晕->${TAttrsComp.hero_name}`);
|
||||||
|
|
||||||
// 麻痹判定(无麻痹抗性,仅按概率)
|
// 麻痹判定(无麻痹抗性,仅按概率)
|
||||||
const paralyzeChance = damageEvent.Attrs[Attrs.paralyze_chance] || 0;
|
const paralyzeChance = damageEvent.Attrs[Attrs.paralyze_chance] || 0;
|
||||||
const isParalyze = !TAttrsComp.isParalyze() && this.checkChance(paralyzeChance);
|
const isParalyze = !TAttrsComp.isParalyze() && this.checkChance(paralyzeChance, `麻痹->${TAttrsComp.hero_name}`);
|
||||||
|
|
||||||
// ✅ 触发视图层表现(伤害数字、受击动画、冰冻、击晕、击退)
|
// ✅ 触发视图层表现(伤害数字、受击动画、冰冻、击晕、击退)
|
||||||
if (targetView) {
|
if (targetView) {
|
||||||
@@ -234,7 +234,11 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
|||||||
// 击退概率判定:概率来自技能配置 bck_chance(heroSet overrides 可覆写),未配置视为 0 不击退。
|
// 击退概率判定:概率来自技能配置 bck_chance(heroSet overrides 可覆写),未配置视为 0 不击退。
|
||||||
// 不复用 checkChance:其 70% 上限封顶会把 100% 击退(近战普攻 6004)削成 70%
|
// 不复用 checkChance:其 70% 上限封顶会把 100% 击退(近战普攻 6004)削成 70%
|
||||||
const knockbackChance = damageEvent.Attrs[Attrs.knockback_skill_chance] || 0;
|
const knockbackChance = damageEvent.Attrs[Attrs.knockback_skill_chance] || 0;
|
||||||
const isKnockback = knockbackChance >= 100 || (knockbackChance > 0 && Math.random() * 100 < knockbackChance);
|
const knockbackRand = knockbackChance >= 100 ? 0 : Math.random() * 100;
|
||||||
|
const isKnockback = knockbackChance >= 100 || (knockbackChance > 0 && knockbackRand < knockbackChance);
|
||||||
|
if (knockbackChance > 0) {
|
||||||
|
mLogger.log(this.debugMode, 'HeroAtkSystem', `[概率判定] 击退->${TAttrsComp.hero_name} 概率:${knockbackChance.toFixed(1)}% 随机:${knockbackRand.toFixed(1)} -> ${isKnockback ? "✔成功" : "✘失败"}`);
|
||||||
|
}
|
||||||
|
|
||||||
// 击退距离增量 = 施法者击退强化(原击退概率)- 被攻击者击退抗性 + 击退距离强化(仅命中击退时生效)
|
// 击退距离增量 = 施法者击退强化(原击退概率)- 被攻击者击退抗性 + 击退距离强化(仅命中击退时生效)
|
||||||
const knockbackBonus = (damageEvent.Attrs[Attrs.knockback_chance] || 0) - (TAttrsComp.getFinalKnockbackRes() || 0);
|
const knockbackBonus = (damageEvent.Attrs[Attrs.knockback_chance] || 0) - (TAttrsComp.getFinalKnockbackRes() || 0);
|
||||||
@@ -279,13 +283,18 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
|||||||
// 施法者 ap/完整属性快照取自伤害事件,供 BuffSystem tick 缩放与暴击/冰冻/击晕判定
|
// 施法者 ap/完整属性快照取自伤害事件,供 BuffSystem tick 缩放与暴击/冰冻/击晕判定
|
||||||
if (!isDot && skillConf.timed_buff_id) {
|
if (!isDot && skillConf.timed_buff_id) {
|
||||||
const buffChance = skillConf.buff_chance ?? 100;
|
const buffChance = skillConf.buff_chance ?? 100;
|
||||||
if (buffChance >= 100 || Math.random() * 100 < buffChance) {
|
const buffRand = buffChance >= 100 ? 0 : Math.random() * 100;
|
||||||
|
if (buffChance >= 100 || buffRand < buffChance) {
|
||||||
const buffOverrides: BuffApplyOverrides = { source_attrs: damageEvent.Attrs };
|
const buffOverrides: BuffApplyOverrides = { source_attrs: damageEvent.Attrs };
|
||||||
if (skillConf.buff_value !== undefined) buffOverrides.value = skillConf.buff_value;
|
if (skillConf.buff_value !== undefined) buffOverrides.value = skillConf.buff_value;
|
||||||
if (skillConf.buff_duration !== undefined) buffOverrides.duration = skillConf.buff_duration;
|
if (skillConf.buff_duration !== undefined) buffOverrides.duration = skillConf.buff_duration;
|
||||||
for (const buffTarget of this.resolveBuffTargets(target, casterEid, TAttrsComp.fac, skillConf.buff_target)) {
|
const buffTargets = this.resolveBuffTargets(target, casterEid, TAttrsComp.fac, skillConf.buff_target);
|
||||||
|
mLogger.log(this.debugMode, 'HeroAtkSystem', `[概率判定] 附带buff「${BuffList[skillConf.timed_buff_id]?.name ?? "?"}」 概率:${buffChance.toFixed(1)}% 随机:${buffRand.toFixed(1)} -> ✔成功(技能「${skillConf.name}」命中 ${TAttrsComp.hero_name},${buffTargets.length} 个目标)`);
|
||||||
|
for (const buffTarget of buffTargets) {
|
||||||
buffManager.applyBuff(buffTarget, skillConf.timed_buff_id, casterEid, damageEvent.Attrs[Attrs.ap] || 0, buffOverrides);
|
buffManager.applyBuff(buffTarget, skillConf.timed_buff_id, casterEid, damageEvent.Attrs[Attrs.ap] || 0, buffOverrides);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
mLogger.log(this.debugMode, 'HeroAtkSystem', `[概率判定] 附带buff「${BuffList[skillConf.timed_buff_id]?.name ?? "?"}」 概率:${buffChance.toFixed(1)}% 随机:${buffRand.toFixed(1)} -> ✘失败(技能「${skillConf.name}」命中 ${TAttrsComp.hero_name})`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,16 +304,20 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
|||||||
if (!isDot && damageEvent.proc_skill) {
|
if (!isDot && damageEvent.proc_skill) {
|
||||||
const proc = damageEvent.proc_skill;
|
const proc = damageEvent.proc_skill;
|
||||||
const procChance = proc.chance ?? 100;
|
const procChance = proc.chance ?? 100;
|
||||||
if (procChance >= 100 || Math.random() * 100 < procChance) {
|
const procRand = procChance >= 100 ? 0 : Math.random() * 100;
|
||||||
|
if (procChance >= 100 || procRand < procChance) {
|
||||||
const caster = ecs.getEntityByEid(casterEid);
|
const caster = ecs.getEntityByEid(casterEid);
|
||||||
if (caster) {
|
if (caster) {
|
||||||
const casterAttrs = caster.get(HeroAttrsComp);
|
const casterAttrs = caster.get(HeroAttrsComp);
|
||||||
const casterView = caster.get(HeroViewComp);
|
const casterView = caster.get(HeroViewComp);
|
||||||
if (casterAttrs && casterView && !casterAttrs.is_dead && !casterAttrs.is_reviving) {
|
if (casterAttrs && casterView && !casterAttrs.is_dead && !casterAttrs.is_reviving) {
|
||||||
|
mLogger.log(this.debugMode, 'HeroAtkSystem', `[概率判定] 额外技能「${SkillSet[proc.s_uuid]?.name ?? "?"}」 概率:${procChance.toFixed(1)}% 随机:${procRand.toFixed(1)} -> ✔成功(技能「${skillConf.name}」命中 ${TAttrsComp.hero_name},由 ${casterAttrs.hero_name} 释放)`);
|
||||||
// proc_skill.overrides 透传给被触发技能(如自定义 ap 伤害),与被触发技能自身 overrides 叠加(本次传入优先)
|
// proc_skill.overrides 透传给被触发技能(如自定义 ap 伤害),与被触发技能自身 overrides 叠加(本次传入优先)
|
||||||
SkillTriggerHelper.dispatchSinglePublic(proc.s_uuid, casterAttrs, casterView, SkillTriggerType.Atking, proc.overrides);
|
SkillTriggerHelper.dispatchSinglePublic(proc.s_uuid, casterAttrs, casterView, SkillTriggerType.Atking, proc.overrides);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
mLogger.log(this.debugMode, 'HeroAtkSystem', `[概率判定] 额外技能「${SkillSet[proc.s_uuid]?.name ?? "?"}」 概率:${procChance.toFixed(1)}% 随机:${procRand.toFixed(1)} -> ✘失败(技能「${skillConf.name}」命中 ${TAttrsComp.hero_name})`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,11 +520,15 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
|||||||
*
|
*
|
||||||
* @important 概率为0或负数时直接返回false,避免不必要的随机数计算
|
* @important 概率为0或负数时直接返回false,避免不必要的随机数计算
|
||||||
*/
|
*/
|
||||||
private checkChance(rate: number): boolean {
|
private checkChance(rate: number, label?: string): boolean {
|
||||||
if (rate <= 0) return false;
|
if (rate <= 0) return false;
|
||||||
if (rate >= 70) rate = 70
|
const capped = Math.min(rate, 70); // 70% 概率封顶
|
||||||
const r = Math.random() * 100;
|
const r = Math.random() * 100;
|
||||||
return r < rate;
|
const ok = r < capped;
|
||||||
|
if (label !== undefined) {
|
||||||
|
mLogger.log(this.debugMode, 'HeroAtkSystem', `[概率判定] ${label} 概率:${rate.toFixed(1)}%(封顶${capped}%) 随机:${r.toFixed(1)} -> ${ok ? "✔成功" : "✘失败"}`);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -546,7 +563,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
|||||||
private checkDodge(damageEvent: DamageEvent, TAttrsComp: HeroAttrsComp): boolean {
|
private checkDodge(damageEvent: DamageEvent, TAttrsComp: HeroAttrsComp): boolean {
|
||||||
const dodgeChance = TAttrsComp.getFinalDodge() - (damageEvent.Attrs[Attrs.accuracy] || 0);
|
const dodgeChance = TAttrsComp.getFinalDodge() - (damageEvent.Attrs[Attrs.accuracy] || 0);
|
||||||
if (dodgeChance <= 0) return false;
|
if (dodgeChance <= 0) return false;
|
||||||
return this.checkChance(dodgeChance);
|
return this.checkChance(dodgeChance, `闪避:${TAttrsComp.hero_name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -531,7 +531,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
|||||||
if (!target.ent) return;
|
if (!target.ent) return;
|
||||||
const model = target.ent.get(HeroAttrsComp);
|
const model = target.ent.get(HeroAttrsComp);
|
||||||
if (!model || model.is_dead) return;
|
if (!model || model.is_dead) return;
|
||||||
mLogger.log(this.debugMode, "SCastSystem", `applyActualFriendlyEffect: skill=${config.uuid} kind=${kind} buff_type=${config.buff_type} timed_buff_id=${config.timed_buff_id} buff_value=${config.buff_value} target=${model.hero_name}`);
|
mLogger.log(this.debugMode, "SCastSystem", `[友方效果] 技能「${config.name}」(s_uuid:${config.uuid}) -> ${model.hero_name} kind:${kind} buff_type:${config.buff_type ?? "-"} timed_buff_id:${config.timed_buff_id ?? "-"} buff_value:${config.buff_value ?? "-"}`);
|
||||||
|
|
||||||
if (config.endAnm && config.endAnm !== "") {
|
if (config.endAnm && config.endAnm !== "") {
|
||||||
target.playEnd(config.endAnm);
|
target.playEnd(config.endAnm);
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export class SkillView extends CCComp {
|
|||||||
@property({ type: CCFloat, slide: true, range: [0, 500, 5], tooltip: "抛射物高度增量(叠加到贝塞尔弹道中点高度)" })
|
@property({ type: CCFloat, slide: true, range: [0, 500, 5], tooltip: "抛射物高度增量(叠加到贝塞尔弹道中点高度)" })
|
||||||
height_offset: number = 0;
|
height_offset: number = 0;
|
||||||
|
|
||||||
private debugMode: boolean = false;
|
private debugMode: boolean = true;
|
||||||
|
|
||||||
anim: Animation = null;
|
anim: Animation = null;
|
||||||
group: number = 0;
|
group: number = 0;
|
||||||
@@ -135,10 +135,9 @@ export class SkillView extends CCComp {
|
|||||||
this.sData.max_hit_count++;
|
this.sData.max_hit_count++;
|
||||||
// 概率衰减(减去固定的 PUNCTURE_DOWN 值,比如 50)
|
// 概率衰减(减去固定的 PUNCTURE_DOWN 值,比如 50)
|
||||||
this.sData.Attrs[Attrs.puncture_chance] = Math.max(0, punctureChance - FightSet.PUNCTURE_DOWN);
|
this.sData.Attrs[Attrs.puncture_chance] = Math.max(0, punctureChance - FightSet.PUNCTURE_DOWN);
|
||||||
if (this.debugMode) {
|
mLogger.log(this.debugMode, 'SkillView', `[概率判定] 穿透 概率:${punctureChance.toFixed(1)}% 随机:${rand.toFixed(1)} -> ✔成功(衰减后剩余:${this.sData.Attrs[Attrs.puncture_chance]}%)`);
|
||||||
mLogger.log(this.debugMode, 'SkillView', `[SkillView] 触发穿透!剩余概率: ${this.sData.Attrs[Attrs.puncture_chance]}%`);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
mLogger.log(this.debugMode, 'SkillView', `[概率判定] 穿透 概率:${punctureChance.toFixed(1)}% 随机:${rand.toFixed(1)} -> ✘失败,投射物销毁`);
|
||||||
// 未触发穿透,正常销毁
|
// 未触发穿透,正常销毁
|
||||||
this.handle_collision_limit();
|
this.handle_collision_limit();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user