From ac0891ccdde5fa2267e1b0e60d4f1d71745b81ce Mon Sep 17 00:00:00 2001 From: panFD Date: Thu, 23 Jul 2026 23:00:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E8=8D=AF=E6=B0=B4?= =?UTF-8?q?=E5=8D=A1=E9=99=90=E6=97=B6=E5=BC=BA=E5=8C=96=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=E8=87=AA=E5=AE=9A=E4=B9=89=E6=95=B0?= =?UTF-8?q?=E5=80=BC=E8=A6=86=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增Buff数值覆写机制,支持药水卡自定义buff效果数值 2. 重构属性计算逻辑,支持读取药水卡传递的覆写值 3. 新增多组限时强化Buff与药水卡配置 4. 优化UI数值显示,实时展示最终属性值 5. 新增多维度调试日志方便排查问题 --- assets/script/game/common/config/BuffSet.ts | 72 ++++++++++++++++++++ assets/script/game/common/config/ICardSet.ts | 39 +++++------ assets/script/game/common/config/SkillSet.ts | 55 +++++++++++++++ assets/script/game/hero/BuffComp.ts | 5 +- assets/script/game/hero/BuffManager.ts | 12 +++- assets/script/game/hero/BuffSystem.ts | 5 +- assets/script/game/hero/HeroAttrsComp.ts | 17 +++-- assets/script/game/hero/SCastSystem.ts | 9 +-- assets/script/game/map/HInfoComp.ts | 5 +- assets/script/game/map/MissSkillsComp.ts | 15 ++-- assets/script/game/map/SBox.ts | 11 +-- assets/script/game/map/SkillBoxComp.ts | 10 ++- 12 files changed, 205 insertions(+), 50 deletions(-) diff --git a/assets/script/game/common/config/BuffSet.ts b/assets/script/game/common/config/BuffSet.ts index 328d97e3..26bc1b71 100644 --- a/assets/script/game/common/config/BuffSet.ts +++ b/assets/script/game/common/config/BuffSet.ts @@ -74,4 +74,76 @@ export const BuffList: Record = { is_control: true, control_kind: 'stun', info: "击晕目标,无法行动", }, + + // ==================== 玩家计时性强化(药水/技能用,默认 5s) ==================== + // 计时性回血(HoT) + 7010: { + id: 7010, name: "再生", icon: "Stat_PotionBoost", + category: BuffCategory.Buff, duration: 5, max_stack: 1, + tick: { interval: 0.5, damage_or_heal: 10, scale_by_ap_pct: 0 }, + info: "每秒回复生命,持续 5 秒", + }, + // 攻击强化(限时) + 7011: { + id: 7011, name: "攻击爆发", icon: "Stat_Attack_03", + category: BuffCategory.Buff, duration: 5, max_stack: 1, + modifiers: [{ attr: Attrs.ap, op: ModOp.PercentAdd, value: 50 }], + info: "攻击力提升 50%,持续 5 秒", + }, + // 暴击强化(限时) + 7012: { + id: 7012, name: "暴击爆发", icon: "Stat_CriticalChance_02", + category: BuffCategory.Buff, duration: 5, max_stack: 1, + modifiers: [{ attr: Attrs.critical, op: ModOp.Flat, value: 30 }], + info: "暴击率提升 30%,持续 5 秒", + }, + // 击退概率强化(限时) + 7013: { + id: 7013, name: "击退爆发", icon: "Stat_Stun_01", + category: BuffCategory.Buff, duration: 5, max_stack: 1, + modifiers: [{ attr: Attrs.knockback_chance, op: ModOp.Flat, value: 30 }], + info: "击退概率提升 30%,持续 5 秒", + }, + // 穿透强化(限时) + 7014: { + id: 7014, name: "穿透爆发", icon: "Stat_Tripleshot", + category: BuffCategory.Buff, duration: 5, max_stack: 1, + modifiers: [{ attr: Attrs.puncture_chance, op: ModOp.Flat, value: 30 }], + info: "穿透概率提升 30%,持续 5 秒", + }, + // 攻速强化(限时,走 getEffectiveSkillCd 计时修饰) + 7015: { + id: 7015, name: "攻速爆发", icon: "Stat_AttackSpeed_02", + category: BuffCategory.Buff, duration: 5, max_stack: 1, + modifiers: [{ attr: Attrs.speed, op: ModOp.Flat, value: 40 }], + info: "攻击速度提升 40%,持续 5 秒", + }, + // 风怒强化(限时,按概率百分点) + 7016: { + id: 7016, name: "风怒爆发", icon: "Stat_CriticalComboChance", + category: BuffCategory.Buff, duration: 5, max_stack: 1, + modifiers: [{ attr: Attrs.wfuny, op: ModOp.Flat, value: 20 }], + info: "风怒概率提升 20%,持续 5 秒", + }, + // 击晕概率强化(限时) + 7017: { + id: 7017, name: "击晕爆发", icon: "Stat_Stun_01", + category: BuffCategory.Buff, duration: 5, max_stack: 1, + modifiers: [{ attr: Attrs.stun_chance, op: ModOp.Flat, value: 30 }], + info: "击晕概率提升 30%,持续 5 秒", + }, + // 击晕抗性强化(限时) + 7018: { + id: 7018, name: "击晕抗性", icon: "Stat_Armor_01", + category: BuffCategory.Buff, duration: 5, max_stack: 1, + modifiers: [{ attr: Attrs.stun_res, op: ModOp.Flat, value: 50 }], + info: "击晕抗性提升 50%,持续 5 秒", + }, + // 冰冻抗性强化(限时) + 7019: { + id: 7019, name: "冰冻抗性", icon: "Stat_Freeze", + category: BuffCategory.Buff, duration: 5, max_stack: 1, + modifiers: [{ attr: Attrs.freeze_res, op: ModOp.Flat, value: 50 }], + info: "冰冻抗性提升 50%,持续 5 秒", + }, }; diff --git a/assets/script/game/common/config/ICardSet.ts b/assets/script/game/common/config/ICardSet.ts index df6d5a73..98845f77 100644 --- a/assets/script/game/common/config/ICardSet.ts +++ b/assets/script/game/common/config/ICardSet.ts @@ -31,30 +31,25 @@ interface ItemCardRaw { } const ItemCardData: ItemCardRaw[] = [ - // ==================== 基础恢复类 ==================== - { uuid: 9101, skill: 6302, name: "治疗药水", info: "恢复全体友方 300 点生命", cost: 3, weight: 20 }, - { uuid: 9102, skill: 6301, name: "护盾药水", info: "为全体友方添加护盾,可抵挡 3 次伤害", cost: 4, weight: 15 }, - { uuid: 9103, skill: 6303, name: "金币袋", info: "立即获得 5 金币", cost: 2, weight: 15, overrides: { gold: 5 } }, + // ==================== 一次性回血(计时性 HoT,5s) ==================== + { uuid: 9101, skill: 6502, name: "再生药水", info: "全体友方每秒回复生命,持续 5 秒", cost: 0, weight: 20 }, - // ==================== 属性强化类(单次触发) ==================== - { uuid: 9111, skill: 6401, name: "攻击药剂", info: "全体友方攻击力提升 5 点", cost: 3, weight: 12 }, - { uuid: 9112, skill: 6402, name: "生命药剂", info: "全体友方最大生命值提升 20 点", cost: 3, weight: 12 }, - { uuid: 9113, skill: 6403, name: "暴击药剂", info: "全体友方暴击率提升 10%", cost: 3, weight: 12 }, - { uuid: 9114, skill: 6404, name: "暴伤药剂", info: "全体友方暴击伤害提升 20%", cost: 3, weight: 12 }, - { uuid: 9115, skill: 6405, name: "击晕药剂", info: "全体友方击晕概率提升 10%", cost: 3, weight: 12 }, - { uuid: 9116, skill: 6408, name: "穿刺药剂", info: "全体友方穿透概率提升 20%", cost: 3, weight: 12 }, - { uuid: 9117, skill: 6409, name: "风怒药剂", info: "全体友方风怒次数提升 1 次", cost: 3, weight: 12 }, + // ==================== 计时性强化(统一 5s) ==================== + { uuid: 9102, skill: 6503, name: "攻击药水", info: "全体友方攻击力提升 50%,持续 5 秒", cost: 0, weight: 15 }, + { uuid: 9103, skill: 6504, name: "暴击药水", info: "全体友方暴击率提升 30%,持续 5 秒", cost: 0, weight: 15 }, + { uuid: 9104, skill: 6505, name: "击退药水", info: "全体友方击退概率提升 30%,持续 5 秒", cost: 0, weight: 12 }, + { uuid: 9105, skill: 6506, name: "穿透药水", info: "全体友方穿透概率提升 30%,持续 5 秒", cost: 0, weight: 12 }, + { uuid: 9106, skill: 6507, name: "攻速药水", info: "全体友方攻击速度提升 40%,持续 5 秒", cost: 0, weight: 15 }, + { uuid: 9107, skill: 6508, name: "风怒药水", info: "全体友方风怒概率提升 20%,持续 5 秒", cost: 0, weight: 12 }, + { uuid: 9108, skill: 6509, name: "击晕药水", info: "全体友方击晕概率提升 30%,持续 5 秒", cost: 0, weight: 12 }, + { uuid: 9109, skill: 6510, name: "击晕抗性药水", info: "全体友方击晕抗性提升 50%,持续 5 秒", cost: 4, weight: 10 }, + { uuid: 9110, skill: 6511, name: "冰冻抗性药水", info: "全体友方冰冻抗性提升 50%,持续 5 秒", cost: 4, weight: 10 }, - // ==================== 高级恢复类 ==================== - { uuid: 9201, skill: 6302, name: "高级治疗药水", info: "恢复全体友方 600 点生命", cost: 6, weight: 8, overrides: { ap: 600 } }, - { uuid: 9202, skill: 6301, name: "高级护盾药水", info: "为全体友方添加护盾,可抵挡 6 次伤害", cost: 8, weight: 6, overrides: { ap: 6 } }, - { uuid: 9203, skill: 6303, name: "大金币袋", info: "立即获得 12 金币", cost: 5, weight: 6, overrides: { gold: 12 } }, - - // ==================== 高级属性强化类 ==================== - { uuid: 9211, skill: 6401, name: "高级攻击药剂", info: "全体友方攻击力提升 10 点", cost: 6, weight: 5, overrides: { ap: 10 } }, - { uuid: 9212, skill: 6402, name: "高级生命药剂", info: "全体友方最大生命值提升 40 点", cost: 6, weight: 5, overrides: { ap: 40 } }, - { uuid: 9213, skill: 6403, name: "高级暴击药剂", info: "全体友方暴击率提升 20%", cost: 6, weight: 5, overrides: { ap: 2 } }, - { uuid: 9214, skill: 6404, name: "高级暴伤药剂", info: "全体友方暴击伤害提升 40%", cost: 6, weight: 5, overrides: { ap: 2 } }, + // ==================== 高级档(buff_value 覆写,复用同一技能底座) ==================== + { uuid: 9201, skill: 6502, name: "高级再生药水", info: "全体友方每秒回复 25 生命,持续 5 秒", cost: 0, weight: 8, overrides: { buff_value: 25 } }, + { uuid: 9202, skill: 6503, name: "高级攻击药水", info: "全体友方攻击力提升 80%,持续 5 秒", cost: 0, weight: 8, overrides: { buff_value: 80 } }, + { uuid: 9203, skill: 6504, name: "高级暴击药水", info: "全体友方暴击率提升 50%,持续 5 秒", cost: 0, weight: 8, overrides: { buff_value: 50 } }, + { uuid: 9206, skill: 6507, name: "高级攻速药水", info: "全体友方攻击速度提升 70%,持续 5 秒", cost: 0, weight: 8, overrides: { buff_value: 70 } }, ]; /** diff --git a/assets/script/game/common/config/SkillSet.ts b/assets/script/game/common/config/SkillSet.ts index 91adc81e..cc8b60d4 100644 --- a/assets/script/game/common/config/SkillSet.ts +++ b/assets/script/game/common/config/SkillSet.ts @@ -155,6 +155,7 @@ export interface SkillConfig { bck?: number, // 额外击退概率 buff_type?: Attrs, // Buff 类型 (单一职责) timed_buff_id?: number, // 计时性 buff 配置 id(指向 BuffList),存在时走 buffManager 而非永久 add_* + buff_value?: number, // 覆写计时 buff 的修饰数值(modifiers.value / tick.damage_or_heal),由药水卡自定义档位 call_hero?: number, // 召唤技能召唤英雄id(可选) is_accel?: boolean, // 是否逐渐加速飞行 info: string, // 技能描述 @@ -172,6 +173,7 @@ export interface SkillOverrides { bck?: number; buff_type?: Attrs; timed_buff_id?: number; + buff_value?: number; call_hero?: number; is_accel?: boolean; } @@ -377,6 +379,59 @@ export const SkillSet: Record = { uuid: 6501, name: "复活", sp_name: "buff_wind", icon: "Stat_HolyDamage", TGroup: TGroup.Self, readyAnm: "up_ap", endAnm: "", act: "atk", DTType: DTType.single, kind: SkillKind.Support, ap: 50, hit_count: 3, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support, RType: RType.fixed, EType: EType.animationEnd, info: "ap 代表复活的生命值百分比", + }, + + // ==================== 计时性强化技能(药水底座,统一 5s,走 timed_buff_id) ==================== + // 注:ap 字段在此类技能中无意义,修饰数值由 BuffList 配置;hit_count=99 确保覆盖全队。 + 6502: { + uuid: 6502, name: "计时回血", sp_name: "buff_wind", icon: "Stat_PotionBoost", TGroup: TGroup.Team, readyAnm: "up_green", endAnm: "", act: "atk", + DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support, + RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.hp, timed_buff_id: 7010, info: "全体友方每秒回复生命,持续5秒", + }, + 6503: { + uuid: 6503, name: "攻击爆发", sp_name: "buff_wind", icon: "Stat_Attack_03", TGroup: TGroup.Team, readyAnm: "up_ap", endAnm: "", act: "atk", + DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support, + RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.ap, timed_buff_id: 7011, info: "全体友方攻击力提升50%,持续5秒", + }, + 6504: { + uuid: 6504, name: "暴击爆发", sp_name: "buff_wind", icon: "Stat_CriticalChance_02", TGroup: TGroup.Team, readyAnm: "up_ap", endAnm: "", act: "atk", + DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support, + RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.critical, timed_buff_id: 7012, info: "全体友方暴击率提升30%,持续5秒", + }, + 6505: { + uuid: 6505, name: "击退爆发", sp_name: "buff_wind", icon: "Stat_Stun_01", TGroup: TGroup.Team, readyAnm: "up_blue", endAnm: "", act: "atk", + DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support, + RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.knockback_chance, timed_buff_id: 7013, info: "全体友方击退概率提升30%,持续5秒", + }, + 6506: { + uuid: 6506, name: "穿透爆发", sp_name: "buff_wind", icon: "Stat_Tripleshot", TGroup: TGroup.Team, readyAnm: "up_ap", endAnm: "", act: "atk", + DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support, + RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.puncture_chance, timed_buff_id: 7014, info: "全体友方穿透概率提升30%,持续5秒", + }, + 6507: { + uuid: 6507, name: "攻速爆发", sp_name: "buff_wind", icon: "Stat_AttackSpeed_02", TGroup: TGroup.Team, readyAnm: "up_ap", endAnm: "", act: "atk", + DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support, + RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.speed, timed_buff_id: 7015, info: "全体友方攻击速度提升40%,持续5秒", + }, + 6508: { + uuid: 6508, name: "风怒爆发", sp_name: "buff_wind", icon: "Stat_CriticalComboChance", TGroup: TGroup.Team, readyAnm: "up_ap", endAnm: "", act: "atk", + DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support, + RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.wfuny, timed_buff_id: 7016, info: "全体友方风怒概率提升20%,持续5秒", + }, + 6509: { + uuid: 6509, name: "击晕爆发", sp_name: "buff_wind", icon: "Stat_Stun_01", TGroup: TGroup.Team, readyAnm: "up_blue", endAnm: "", act: "atk", + DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support, + RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.stun_chance, timed_buff_id: 7017, info: "全体友方击晕概率提升30%,持续5秒", + }, + 6510: { + uuid: 6510, name: "击晕抗性", sp_name: "buff_wind", icon: "Stat_Armor_01", TGroup: TGroup.Team, readyAnm: "up_blue", endAnm: "", act: "atk", + DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support, + RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.stun_res, timed_buff_id: 7018, info: "全体友方击晕抗性提升50%,持续5秒", + }, + 6511: { + uuid: 6511, name: "冰冻抗性", sp_name: "buff_wind", icon: "Stat_Freeze", TGroup: TGroup.Team, readyAnm: "up_blue", endAnm: "", act: "atk", + DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support, + RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.freeze_res, timed_buff_id: 7019, info: "全体友方冰冻抗性提升50%,持续5秒", } }; diff --git a/assets/script/game/hero/BuffComp.ts b/assets/script/game/hero/BuffComp.ts index 1880dd83..3c442d5b 100644 --- a/assets/script/game/hero/BuffComp.ts +++ b/assets/script/game/hero/BuffComp.ts @@ -15,12 +15,15 @@ export class ActiveBuff { source_ap_snapshot: number; /** 周期效果累计时间(秒) */ tick_acc: number = 0; + /** 修饰数值覆写(来自药水卡 buff_value),优先于 BuffList 配置值;undefined 表示用配置值 */ + value_override?: number; - constructor(cfg_id: number, dur: number, src_uuid: number, src_ap: number) { + constructor(cfg_id: number, dur: number, src_uuid: number, src_ap: number, value_override?: number) { this.config_id = cfg_id; this.remaining = dur; this.source_uuid = src_uuid; this.source_ap_snapshot = src_ap; + this.value_override = value_override; } } diff --git a/assets/script/game/hero/BuffManager.ts b/assets/script/game/hero/BuffManager.ts index 61c007d3..5adea2df 100644 --- a/assets/script/game/hero/BuffManager.ts +++ b/assets/script/game/hero/BuffManager.ts @@ -12,9 +12,11 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec import { BuffCategory, BuffList } from "../common/config/BuffSet"; import { BuffComp, ActiveBuff } from "./BuffComp"; -/** applyBuff 的覆盖参数(预留按需覆写持续时间) */ +/** applyBuff 的覆盖参数(预留按需覆写持续时间 / 修饰数值) */ export interface BuffApplyOverrides { duration?: number; + /** 覆写计时 buff 的修饰数值(modifiers.value / tick.damage_or_heal),由药水卡 buff_value 自定义档位 */ + value?: number; } class BuffManagerImpl { @@ -34,7 +36,11 @@ class BuffManagerImpl { */ applyBuff(target: ecs.Entity, buffId: number, sourceUuid: number = 0, sourceAp: number = 0, overrides?: BuffApplyOverrides): void { const cfg = BuffList[buffId]; - if (!cfg) return; + if (!cfg) { + console.log(`[BuffManager] applyBuff: buffId=${buffId} 配置不存在,跳过`); + return; + } + console.log(`[BuffManager] applyBuff: buff=${cfg.name}(${buffId}) target_eid=${target.eid} duration=${overrides?.duration ?? cfg.duration} value_override=${overrides?.value} source_ap=${sourceAp}`); const buffComp = this.ensureBuffComp(target); const duration = overrides?.duration ?? cfg.duration; @@ -45,7 +51,7 @@ class BuffManagerImpl { buffComp.buffs.set(buffId, layers); } - const newLayer = new ActiveBuff(buffId, duration, sourceUuid, sourceAp); + const newLayer = new ActiveBuff(buffId, duration, sourceUuid, sourceAp, overrides?.value); if (cfg.max_stack === 0 || layers.length < cfg.max_stack) { layers.push(newLayer); diff --git a/assets/script/game/hero/BuffSystem.ts b/assets/script/game/hero/BuffSystem.ts index 522d01a7..41cbbb08 100644 --- a/assets/script/game/hero/BuffSystem.ts +++ b/assets/script/game/hero/BuffSystem.ts @@ -60,6 +60,7 @@ export class BuffSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate if (cfg.duration > 0 && layer.remaining <= 0) { layers.splice(i, 1); anyChanged = true; + console.log(`[BuffSystem] buff 到期移除: ${cfg.name}(${buffId}) eid=${e.eid} 剩余层数=${layers.length}`); } } @@ -90,8 +91,10 @@ export class BuffSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate while (layer.tick_acc >= tick.interval) { layer.tick_acc -= tick.interval; // 按 ap 缩放后取整:floor(dmg * (1 + ap_snapshot * scale_pct / 10000)) + // damage_or_heal 优先取药水卡覆写值 + const baseAmount = layer.value_override !== undefined ? layer.value_override : tick.damage_or_heal; const scale = 1 + layer.source_ap_snapshot * tick.scale_by_ap_pct / 10000; - const amount = Math.floor(tick.damage_or_heal * scale); + const amount = Math.floor(baseAmount * scale); attrs.add_hp(amount); } } diff --git a/assets/script/game/hero/HeroAttrsComp.ts b/assets/script/game/hero/HeroAttrsComp.ts index 459ccc9e..86e4e259 100644 --- a/assets/script/game/hero/HeroAttrsComp.ts +++ b/assets/script/game/hero/HeroAttrsComp.ts @@ -351,14 +351,17 @@ export class HeroAttrsComp extends ecs.Comp { if (!cfg || !cfg.modifiers) return; // 每层独立贡献,模拟叠层放大效果 for (let i = 0; i < layers.length; i++) { + const layerVal = layers[i].value_override; // 药水卡覆写值优先 for (const mod of cfg.modifiers) { if (mod.attr !== attr) continue; + const value = layerVal !== undefined ? layerVal : mod.value; + console.log(`[HeroAttrs] aggregateTimedMods 命中: ${this.hero_name} buff=${cfg.name} attr=${attr} op=${mod.op} value=${value} remaining=${layers[i].remaining.toFixed(1)}`); if (mod.op === ModOp.Flat) { - result.flatSum += mod.value; + result.flatSum += value; } else { // PercentAdd 与 PercentMul 暂统一按加法百分比聚合; // PercentMul 真正的独立乘区尚未启用,TODO: 启用时需改造为多乘区连乘 - result.pctSum += mod.value; + result.pctSum += value; } } } @@ -373,7 +376,11 @@ export class HeroAttrsComp extends ecs.Comp { public getFinalAp(): number { const runtimeAp = this.getRuntimeAp(this.ap); const mods = this.aggregateTimedMods(Attrs.ap); - return (runtimeAp + mods.flatSum) * (1 + mods.pctSum / 100); + const final = (runtimeAp + mods.flatSum) * (1 + mods.pctSum / 100); + if (mods.flatSum !== 0 || mods.pctSum !== 0) { + console.log(`[HeroAttrs] getFinalAp: ${this.hero_name} base=${this.ap} runtime=${runtimeAp.toFixed(1)} flat=${mods.flatSum} pct=${mods.pctSum} final=${final.toFixed(1)}`); + } + return final; } /** @@ -472,7 +479,9 @@ export class HeroAttrsComp extends ecs.Comp { const skill = this.skills[skillId]; if (!skill) return 0; if (skill.cd <= 0) return 0; - const speedBonus = this.getRuntimeAttackSpeedBonus(); + // 攻速 = 驻场加成 + 计时性 buff 修饰(speed 属性的 flat/pct 均按攻速百分点处理) + const timedMods = this.aggregateTimedMods(Attrs.speed); + const speedBonus = this.getRuntimeAttackSpeedBonus() + timedMods.flatSum + timedMods.pctSum; if (speedBonus <= 0) return skill.cd; const speedRate = 1 + speedBonus / 100; return Math.max(HeroAttrsComp.minAttackCd, skill.cd / speedRate); diff --git a/assets/script/game/hero/SCastSystem.ts b/assets/script/game/hero/SCastSystem.ts index ebe87dd2..c84622f6 100644 --- a/assets/script/game/hero/SCastSystem.ts +++ b/assets/script/game/hero/SCastSystem.ts @@ -142,10 +142,11 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate } } - console.log("[SCastSystem] forceCastCardSkill: casting skill", s_uuid, "castTimes", castTimes, "targetPos", targetPos); + console.log("[SCastSystem] forceCastCardSkill: casting skill", s_uuid, "castTimes", castTimes, "targetPos", targetPos, "isFriendly", isFriendly, "buff_value", config.buff_value, "timed_buff_id", config.timed_buff_id); for (let i = 0; i < castTimes; i++) { if (isFriendly) { const friendlyTargets = this.resolveFriendlyTargets(targetEids, FacSet.HERO); + console.log("[SCastSystem] friendlyTargets count =", friendlyTargets.length); if (friendlyTargets.length === 0) continue; this.applyFriendlySkillEffects(s_uuid, cardLv, config, null as any, mockAttrs, friendlyTargets, spawnPos); } else { @@ -455,12 +456,11 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate } } - - private applyActualFriendlyEffect(target: HeroViewComp, kind: SkillKind, sAp: number, _cAttrsComp: HeroAttrsComp, config: SkillConfig, sUp: any, _skillLv: number = 1) { if (!target.ent) return; const model = target.ent.get(HeroAttrsComp); if (!model || model.is_dead) return; + console.log(`[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}`); if (config.endAnm && config.endAnm !== "") { target.playEnd(config.endAnm); @@ -493,7 +493,8 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate target.ent, config.timed_buff_id, _cAttrsComp.hero_uuid, - _cAttrsComp.ap + _cAttrsComp.ap, + config.buff_value !== undefined ? { value: config.buff_value } : undefined ); return; } diff --git a/assets/script/game/map/HInfoComp.ts b/assets/script/game/map/HInfoComp.ts index 3a3318c9..8dbe2b7d 100644 --- a/assets/script/game/map/HInfoComp.ts +++ b/assets/script/game/map/HInfoComp.ts @@ -355,8 +355,9 @@ export class HInfoComp extends CCComp { } // ---- 数值标签 ---- + // 攻击力显示最终值(含计时 buff 修饰),实时反映药水等限时强化 if (this.apLabel) { - const currentAp = Math.max(0, Math.floor(this.model.ap ?? 0)); + const currentAp = Math.max(0, Math.floor(this.model.getFinalAp())); const baseAp = Math.max(0, Math.floor(this.model.base_ap ?? 0)); this.apLabel.string = `${currentAp}`; if (this.apPlusLabel) { @@ -370,7 +371,7 @@ export class HInfoComp extends CCComp { } } if (this.hpLabel) { - const currentHp = Math.max(0, Math.floor(this.model.hp_max ?? 0)); + const currentHp = Math.max(0, Math.floor(this.model.getFinalHpMax())); const baseHp = Math.max(0, Math.floor(this.model.base_hp ?? 0)); this.hpLabel.string = `${currentHp}`; if (this.hpPlusLabel) { diff --git a/assets/script/game/map/MissSkillsComp.ts b/assets/script/game/map/MissSkillsComp.ts index b7685b2d..6f4e3088 100644 --- a/assets/script/game/map/MissSkillsComp.ts +++ b/assets/script/game/map/MissSkillsComp.ts @@ -28,6 +28,7 @@ import { SBox } from "./SBox"; import { oops } from "db://oops-framework/core/Oops"; import { GameEvent } from "../common/config/GameEvent"; import { BoxSet } from "../common/config/GameSet"; +import { SkillOverrides } from "../common/config/SkillSet"; const { ccclass, property } = _decorator; /** 技能槽位数据结构 */ @@ -73,6 +74,7 @@ export class MissSkillsComp extends CCComp { /** 注册事件监听 */ onLoad() { oops.message.on(GameEvent.UseSkillCard, this.onUseSkillCard, this); + oops.message.on(GameEvent.UseItemCard, this.onUseSkillCard, this); oops.message.on(GameEvent.RemoveSkillBox, this.onRemoveSkillBox, this); } @@ -80,6 +82,7 @@ export class MissSkillsComp extends CCComp { onDestroy() { super.onDestroy(); oops.message.off(GameEvent.UseSkillCard, this.onUseSkillCard, this); + oops.message.off(GameEvent.UseItemCard, this.onUseSkillCard, this); oops.message.off(GameEvent.RemoveSkillBox, this.onRemoveSkillBox, this); } @@ -138,10 +141,12 @@ export class MissSkillsComp extends CCComp { */ private onUseSkillCard(event: string, args: any) { const payload = args ?? event; - const uuid = Number(payload?.uuid ?? 0); + // 卡 uuid 仅用于查配置;真正施法用技能 id(payload.skill),缺省时退回 uuid(兼容技能卡直接用技能 id 的场景) + const skillUuid = Number(payload?.skill ?? payload?.uuid ?? 0); const card_lv = Math.max(1, Math.floor(Number(payload?.card_lv ?? 1))); - if (!uuid) return; - this.addSkill(uuid, card_lv); + if (!skillUuid) return; + // 药水/技能卡的 overrides(含 buff_value)需透传到技能实体 + this.addSkill(skillUuid, card_lv, payload?.overrides); } start() { @@ -157,7 +162,7 @@ export class MissSkillsComp extends CCComp { * @param uuid 技能 UUID * @param card_lv 技能卡等级 */ - addSkill(uuid: number, card_lv: number) { + addSkill(uuid: number, card_lv: number, overrides?: SkillOverrides) { if (!this.skill_box) { mLogger.error(this.debugMode, "MissSkillsComp", "skill_box prefab not set"); return; @@ -174,7 +179,7 @@ export class MissSkillsComp extends CCComp { // 使用 ECS 实体创建技能节点 let sbox = ecs.getEntity(SBox); let pos = new Vec3(this.slots[emptyIndex].x, this.slots[emptyIndex].y, 0); - let node = sbox.load(uuid, card_lv, pos, this.skill_box); + let node = sbox.load(uuid, card_lv, pos, this.skill_box, overrides); this.slots[emptyIndex].used = true; this.slots[emptyIndex].node = node; diff --git a/assets/script/game/map/SBox.ts b/assets/script/game/map/SBox.ts index 5dba0f53..c5dcb7de 100644 --- a/assets/script/game/map/SBox.ts +++ b/assets/script/game/map/SBox.ts @@ -2,6 +2,7 @@ import { instantiate, Prefab, Vec3, Node } from "cc"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { smc } from "../common/SingletonModuleComp"; import { SkillBoxComp } from "./SkillBoxComp"; +import { SkillOverrides } from "../common/config/SkillSet"; /** SBox 实体:负责技能卡效果节点创建、初始化与销毁流程 */ @ecs.register(`SBox`) @@ -29,10 +30,10 @@ export class SBox extends ecs.Entity { * 1) 创建节点并挂到 SKILL 层 * 2) 初始化表现与属性数据 */ - load(uuid: number, card_lv: number, pos: Vec3, prefab: Prefab): Node { + load(uuid: number, card_lv: number, pos: Vec3, prefab: Prefab, overrides?: SkillOverrides): Node { let node = instantiate(prefab); let scene = smc.map.MapView.scene; - + // 统一挂到实体显示层 SKILL 节点下 let parent = scene.entityLayer!.node!.getChildByName("SKILL"); if (parent) { @@ -43,9 +44,9 @@ export class SBox extends ecs.Entity { // 获取并注册组件 let sboxComp = node.getComponent(SkillBoxComp) || node.addComponent(SkillBoxComp); this.add(sboxComp); - - // 初始化业务逻辑 - sboxComp.init(uuid, card_lv); + + // 初始化业务逻辑(透传药水卡 overrides,含 buff_value) + sboxComp.init(uuid, card_lv, overrides); return node; } diff --git a/assets/script/game/map/SkillBoxComp.ts b/assets/script/game/map/SkillBoxComp.ts index a80780e4..7815d8b6 100644 --- a/assets/script/game/map/SkillBoxComp.ts +++ b/assets/script/game/map/SkillBoxComp.ts @@ -166,10 +166,10 @@ export class SkillBoxComp extends CCComp { * @param uuid 卡牌 UUID * @param card_lv 技能卡等级 */ - init(uuid: number, card_lv: number) { + init(uuid: number, card_lv: number, overrides?: SkillOverrides) { this.card_lv = card_lv; - // 查询触发配置 + // 查询触发配置(药水卡不在 SkillCardList,会走 else 分支) const config = SkillCardList.find(c => c.uuid === uuid); if (config) { this.s_uuid = config.skill ?? uuid; // 获取实际的技能 UUID @@ -177,14 +177,18 @@ export class SkillBoxComp extends CCComp { this.trigger_times = config.t_times ?? 1; this.trigger_interval = config.t_inv ?? 0; this.keep_waves = config.keep_waves ?? 0; - this.overrides = config.overrides; + this.overrides = overrides ?? config.overrides; // 外部透传(药水卡)优先 this.field = config.field || []; this.card_icon = config.icon; // 保存卡牌自定义图标(优先级最高) // 读取触发类型与上限(兜底默认值,避免 undefined) this.trigger_type = config.trigger_type ?? CardTriggerType.Instant; this.trigger_limit = config.trigger_limit ?? Infinity; } else { + // 药水卡等:uuid 即技能 id,触发类型默认 Instant(即时生效一次) this.s_uuid = uuid; + this.overrides = overrides; + this.trigger_type = CardTriggerType.Instant; + this.trigger_times = 1; } this.current_trigger_times = 0;