feat: 实现药水卡限时强化功能,支持自定义数值覆写
1. 新增Buff数值覆写机制,支持药水卡自定义buff效果数值 2. 重构属性计算逻辑,支持读取药水卡传递的覆写值 3. 新增多组限时强化Buff与药水卡配置 4. 优化UI数值显示,实时展示最终属性值 5. 新增多维度调试日志方便排查问题
This commit is contained in:
@@ -74,4 +74,76 @@ export const BuffList: Record<number, BuffConfig> = {
|
||||
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 秒",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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 } },
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<number, SkillConfig> = {
|
||||
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秒",
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>(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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user