diff --git a/.trae/documents/15-Minute Roguelike Game Balance & Configuration Plan.md b/.trae/documents/15-Minute Roguelike Game Balance & Configuration Plan.md deleted file mode 100644 index 3200bf36..00000000 --- a/.trae/documents/15-Minute Roguelike Game Balance & Configuration Plan.md +++ /dev/null @@ -1,45 +0,0 @@ -Based on the analysis of `MissionCardComp.ts`, `MissionComp.ts`, `RogueConfig.ts`, and `heroSet.ts`, I have designed a balanced configuration plan for a 15-minute roguelike game loop. - -The current configuration has some imbalances (e.g., Boss HP 25000 vs Hero AP 15, low card costs vs high drop rates). The plan aims to smooth out the difficulty curve and establish a sustainable economy. - -### 1. Economy Rebalance (GameSet.ts) -Adjust costs to prevent "infinite card spamming" while ensuring steady progression. -* **Card Draw Cost (`CHOU_GOLD`)**: Increase from `5` to **100**. -* **Level Up Cost (`LVUP_GOLD`)**: Increase from `10` to **50** (Base) + **50** (Increment). -* **Goal**: Players need to kill ~10-15 enemies to afford one card/upgrade, making choices impactful. - -### 2. Hero Configuration (heroSet.ts) -Establish distinct roles and meaningful growth to keep up with monster scaling. -* **Base Stats (`HeroInfo`)**: - * **Warrior**: HP 300, AP 25, Def 5 (Tanky) - * **Mage**: HP 150, AP 40, Range Mid (Glass Cannon) - * **Archer**: HP 180, AP 30, AS 1.0 (DPS) -* **Growth (`HeroUpSet`)**: - * **HP**: +30 per level - * **AP**: +5 per level - * **Def**: +1 per level - -### 3. Monster & Wave Configuration (RogueConfig.ts) -Implement a dynamic difficulty curve that ramps up intensity over 15 minutes. -* **Base Stats (`heroSet.ts`)**: - * **Fodder (5201)**: HP 60, AP 8, Speed 100 - * **Fast (5301)**: HP 40, AP 12, Speed 180 - * **Tank (5401)**: HP 200, AP 15, Speed 60 - * **Boss (5701)**: HP 5000 (reduced from 25k to match new scaling), AP 60 -* **Scaling Logic (`RogueConfig.ts`)**: - * **HP Growth**: Exponential (`1.15` per minute factor). - * **Spawn Logic**: - * **0-3 min**: Fodder swarm (accumulate gold). - * **3-8 min**: Fast + Tank mix (test DPS and defense). - * **8-14 min**: Elites + Special mechanics (high pressure). - * **15 min**: Final Boss. -* **Gold Drop**: - * Formula: `Base (5) + Level * 1 + TypeBonus`. - * Elite/Boss give significantly more to reward tough fights. - -### 4. Implementation Steps -1. **Modify `GameSet.ts`**: Update economy constants (`CHOU_GOLD`, `LVUP_GOLD`). -2. **Modify `heroSet.ts`**: Update `HeroConf`, `HeroUpSet`, and `HeroInfo` with new base stats. -3. **Modify `RogueConfig.ts`**: Update `DefaultRogueConfig` (budget/intervals), `getMonAttr` (scaling formulas), `calculateMonsterGold`, and `getSpawnWeights` (wave phases). - -This plan ensures the 15-minute session has a clear "Early-Mid-Late" game progression with a challenging but fair economy. \ No newline at end of file diff --git a/.trae/documents/塔防1-20级四选一成长系统设计.md b/.trae/documents/塔防1-20级四选一成长系统设计.md deleted file mode 100644 index cc5ff795..00000000 --- a/.trae/documents/塔防1-20级四选一成长系统设计.md +++ /dev/null @@ -1,61 +0,0 @@ -## 目标 - -创建 `TDLevelOptions.ts`。 -调整数值:**保持 AP/HP\_MAX 强度不变,将其余所有属性的强度(Base & Grow)减半。** -并在配置中明确标注“20级极限总加成”。 - -## 调整后的数值表 (Revised V2) - -| 属性 | Base | Grow | Lv1单次 | Lv20单次 | **20级累计总加成** | 调整说明 | -| :---------------- | :--- | :--- | :---- | :----- | :----------- | :-------------- | -| **AP** (攻) | 15 | 1.5 | 16 | 45 | **+610** | 保持不变 | -| **HP\_MAX** (血) | 100 | 10 | 110 | 300 | **+4100** | 保持不变 | -| **AS** (速) | 5 | 0.25 | 5% | 10% | **+150%** | 减半 | -| **DIS** (距) | 15 | 1.0 | 16 | 35 | **+510** | 减半 | -| **PIERCE** (穿) | 1 | 0 | 1 | 1 | **+20** | 无法减半(最小1),需接受 | -| **CRITICAL** (暴) | 2.5 | 0.1 | 2.6% | 4.5% | **+71%** | 减半 (需配合多次选择才满暴) | -| **CRITICAL\_DMG** | 10 | 0.5 | 10% | 20% | **+300%** | 减半 | -| **DEF** (防) | 2.5 | 0.25 | 2.7 | 7.5 | **+102** | 减半 | -| **控制类** | 1.5 | 0.05 | 1.5% | 2.5% | **+40%** | 减半 (不再必定永控) | -| **吸血** | 1 | 0.05 | 1% | 2% | **+30%** | 减半 | - -*(注:PIERCE 因作为整数逻辑,维持 +1,但在随机池权重中可以不作特殊处理,作为稀有强力项自然存在)* - -## 配置文件内容 - -路径:`assets/script/game/common/config/TDLevelOptions.ts` - -```typescript -import { Attrs } from "./HeroAttrs"; - -export interface IOptionGrowth { - base: number; - grow: number; - desc: string; // 使用 {val} 占位 - totalNote: string; // 备注20级总加成 -} - -export const TD_OPTION_CONFIG: Record = { - [Attrs.AP]: { base: 15, grow: 1.5, desc: "攻击力 +{val}", totalNote: "+610" }, - [Attrs.HP_MAX]: { base: 100, grow: 10, desc: "生命上限 +{val}", totalNote: "+4100" }, - - // 减半组 - [Attrs.AS]: { base: 5, grow: 0.25, desc: "攻击速度 +{val}%", totalNote: "+150%" }, - [Attrs.DIS]: { base: 15, grow: 1.0, desc: "攻击距离 +{val}", totalNote: "+510" }, - [Attrs.CRITICAL]: { base: 2.5, grow: 0.1, desc: "暴击率 +{val}%", totalNote: "+71%" }, - [Attrs.CRITICAL_DMG]: { base: 10, grow: 0.5, desc: "暴击伤害 +{val}%", totalNote: "+300%" }, - [Attrs.DEF]: { base: 2.5, grow: 0.25, desc: "防御 +{val}", totalNote: "+102" }, - - // 控制与特效 (统一配置) - [Attrs.STUN_CHANCE]: { base: 1.5, grow: 0.05, desc: "眩晕概率 +{val}%", totalNote: "+40%" }, - // ... 其他控制类同上 - [Attrs.PUNCTURE]: { base: 1, grow: 0, desc: "穿透 +{val}", totalNote: "+20" }, -}; - -// 辅助函数 -export const getLevelOptions = (level: number): any[] => { ... } -``` - -## 执行 - -直接按此数值创建文件。无需再次确认。 diff --git a/.trae/documents/超休闲塔防属性精简与落地方案.md b/.trae/documents/超休闲塔防属性精简与落地方案.md deleted file mode 100644 index 34d7fefa..00000000 --- a/.trae/documents/超休闲塔防属性精简与落地方案.md +++ /dev/null @@ -1,62 +0,0 @@ -## 目标 -- 新增一个“生效属性配置文件”,集中声明超休闲塔防要启用的属性键,供系统与 UI 快速判断哪些属性参与计算与展示。 - -## 文件位置 -- `assets/script/game/common/config/TDEnabledAttrs.ts` - -## 内容结构 -- 引用 `HeroAttrs.ts` 的 `Attrs` 枚举。 -- 导出两类集合: - - 核心启用集合 `TD_ENABLED_ATTRS`(ReadonlySet) - - 轻度可选集合 `TD_OPTIONAL_ATTRS`(ReadonlySet) -- 额外导出 `TD_ATTR_GROUPS`(用于 UI 分组展示,非必需)。 - -## 初始启用键(核心) -- 塔/英雄输出:`AP`、`AS`、`DIS`、`PIERCE` -- 爽点:`CRITICAL`、`CRITICAL_DMG` -- 敌人生存:`HP_MAX`、`DEF` - -## 轻度可选键(后续可开关) -- 控制:`SLOW_CHANCE`(或改为 `STUN_CHANCE`) -- 经济:`GOLD_GAIN` -- 精英修正:`DMG_RED` - -## 计划代码(示例) -```ts -// assets/script/game/common/config/TDEnabledAttrs.ts -import { Attrs } from "./HeroAttrs"; - -export const TD_ENABLED_ATTRS: ReadonlySet = new Set([ - Attrs.AP, - Attrs.AS, - Attrs.DIS, - Attrs.PUNCTURE, - Attrs.CRITICAL, - Attrs.CRITICAL_DMG, - Attrs.HP_MAX, - Attrs.DEF, -]); - -export const TD_OPTIONAL_ATTRS: ReadonlySet = new Set([ - Attrs.SLOW_CHANCE, - Attrs.GOLD_GAIN, - Attrs.DMG_RED, -]); - -export const TD_ATTR_GROUPS = { - towerCore: [Attrs.AP, Attrs.AS, Attrs.DIS, Attrs.PUNCTURE], - towerBonus: [Attrs.CRITICAL, Attrs.CRITICAL_DMG], - enemyCore: [Attrs.HP_MAX, Attrs.DEF], - optional: [Attrs.SLOW_CHANCE, Attrs.GOLD_GAIN, Attrs.DMG_RED], -} as const; -``` - -## 接入点(不改动逻辑,只引用) -- 计算系统:在重算或结算处通过 `TD_ENABLED_ATTRS.has(attr)` 判断展示/参与计算(不改变已有正确计算路径,只做筛选)。 -- UI:面板按 `TD_ATTR_GROUPS` 渲染;未启用键默认隐藏。 - -## 验证 -- 在测试环境加载 1 个塔与 2 类敌人,确认仅启用键被展示和参与战斗,TTK/DPS 表现符合预期。 - -## 等待下一步 -- 若确认上述文件结构与键集合,开始创建文件并接入引用;如需改用 `AREA_OF_EFFECT` 替代 `PIERCE` 或改为 `STUN_CHANCE`,我会在提交前同步调整。 \ No newline at end of file diff --git a/assets/script/game/common/config/HeroAttrs.ts b/assets/script/game/common/config/HeroAttrs.ts index c5fa275c..6a18bf8c 100644 --- a/assets/script/game/common/config/HeroAttrs.ts +++ b/assets/script/game/common/config/HeroAttrs.ts @@ -10,12 +10,6 @@ export enum BType { BOOLEAN = 2, // 布尔型 } -export enum Debuff { - IN_FROST = 0, // 冰冻状态 - IN_STUN = 1, // 眩晕状态 -} - - // ========== 属性枚举 ========== /** * 英雄属性枚举 @@ -57,6 +51,10 @@ export enum Attrs { puncture = "puncture", // 穿刺次数 puncture_dmg = "puncture_dmg", // 穿刺伤害 wfuny = "wfuny", // 风怒 + + // ==================== 状态类 Debuff ==================== + IN_FROST = "IN_FROST", // 冰冻状态 + IN_STUN = "IN_STUN", // 眩晕状态 } /** diff --git a/assets/script/game/common/config/SkillSet.ts b/assets/script/game/common/config/SkillSet.ts index 654b80a0..5aae488f 100644 --- a/assets/script/game/common/config/SkillSet.ts +++ b/assets/script/game/common/config/SkillSet.ts @@ -1,5 +1,5 @@ // ========== 从 HeroAttrs.ts 导入属性相关定义 ========== -import { Attrs,BType, Debuff } from "./HeroAttrs"; +import { Attrs,BType } from "./HeroAttrs"; export enum HSSet { atk = 0, // 普通攻击 @@ -137,18 +137,16 @@ export const HeroSkillList = [6001,6001,6001,6001,6001,6001] // Debuff配置接口 export interface BuffConf { + uuid:number; // Buff唯一ID + name?:string; // Buff名称 + icon?:string; // Buff图标 buff:Attrs; BType:BType value:number; // 效果值 time:number; // 持续时间 chance:number; // 触发概率 -} - -export interface DebuffConf { - debuff:Debuff; - BType:BType - value:number; - time:number; + info?:string; // 描述 + isDebuff?:boolean; // 是否为负面效果 } interface IReady { @@ -191,8 +189,7 @@ export interface SkillConfig { DAnm:number, // 命中后动画ID RType:RType, // 技能运行类型(直线/贝塞尔/固定起点/固定终点) EType:EType, // 结束条件(动画结束/时间结束/距离结束/碰撞/次数结束) - buffs:BuffConf[], // 对施法者的buff配置列表 - debuffs:DebuffConf[], // 对施法者的负面配置列表 + buffs:number[], // 对施法者的buff配置列表(Buff UUID 列表) call_hero?:number, // 召唤技能召唤英雄id(可选) info:string, // 技能描述 } @@ -201,57 +198,57 @@ export const SkillSet: Record = { 5000:{uuid:5000,name:"反伤",sp_name:"thorns",icon:"1168",TGroup:TGroup.Enemy,SType:SType.damage,act:"atk",DTType:DTType.single, ap:0,cd:60,t_num:1,hit_num:1,hit:1,hitcd:0.2,speed:720,with:0,dis:SkillDisVal[SkillRange.Long], ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, - buffs:[],debuffs:[],info:"反伤", + buffs:[],info:"反伤", }, // ========== 基础攻击 ========== 6001-6099 6001: { uuid:6001,name:"近战攻击",sp_name:"atk_s1",icon:"1026",TGroup:TGroup.Enemy,SType:SType.damage,act:"atk",DTType:DTType.single, ap:100,cd:1,t_num:1,hit_num:1,hit:1,hitcd:0.2,speed:720,with:0,dis:SkillDisVal[SkillRange.Melee], ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, - buffs:[],debuffs:[],info:"对前方目标造成100%攻击的伤害", + buffs:[],info:"对前方目标造成100%攻击的伤害", }, 6002: { uuid:6002,name:"远程攻击",sp_name:"b_arrow_blue",icon:"1135",TGroup:TGroup.Enemy,SType:SType.damage,act:"atk",DTType:DTType.single, ap:100,cd:1,t_num:1,hit_num:1,hit:1,hitcd:0.2,speed:720,with:0,dis:SkillDisVal[SkillRange.Melee], ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, - buffs:[],debuffs:[],info:"对前方单个目标造成100%攻击的伤害", + buffs:[],info:"对前方单个目标造成100%攻击的伤害", }, 6003: { uuid:6003,name:"远程攻击",sp_name:"m_water_ball_1",icon:"1126",TGroup:TGroup.Enemy,SType:SType.damage,act:"atk",DTType:DTType.single, ap:100,cd:5,t_num:1,hit_num:1,hit:2,hitcd:0.3,speed:720,with:90,dis:SkillDisVal[SkillRange.Mid], ready:8001,EAnm:0,DAnm:9001,RType:RType.linear,EType:EType.collision, - buffs:[],debuffs:[],info:"对前方单个目标造成100%攻击的伤害", + buffs:[],info:"对前方单个目标造成100%攻击的伤害", }, 6004: { uuid:6004,name:"蓄力一击",sp_name:"atk_s4",icon:"1173",TGroup:TGroup.Enemy,SType:SType.damage,act:"atk",DTType:DTType.single, ap:100,cd:3,t_num:1,hit_num:1,hit:1,hitcd:0.2,speed:720,with:0,dis:SkillDisVal[SkillRange.Melee], ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, - buffs:[],debuffs:[],info:"对前方目标造成150%攻击的伤害", + buffs:[],info:"对前方目标造成150%攻击的伤害", }, // ========== 基础buff ========== 6100-6199 6100: { uuid:6100,name:"治疗",sp_name:"buff_wind",icon:"1292",TGroup:TGroup.Self,SType:SType.heal,act:"atk",DTType:DTType.single, ap:30,cd:5,t_num:1,hit_num:1,hit:1,hitcd:0.2,speed:720,with:0,dis:SkillDisVal[SkillRange.Long], ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, - buffs:[],debuffs:[],info:"治疗自己,回复30%最大生命值", + buffs:[],info:"治疗自己,回复30%最大生命值", }, 6101:{ uuid:6101,name:"魔法盾",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Self,SType:SType.shield,act:"atk",DTType:DTType.single, ap:30,cd:7,t_num:1,hit_num:1,hit:1,hitcd:0.2,speed:720,with:0,dis:SkillDisVal[SkillRange.Long], ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, - buffs:[],debuffs:[],info:"获得30%最大生命值的护盾,持续60秒", + buffs:[],info:"获得30%最大生命值的护盾,持续60秒", }, 6102:{ uuid:6102,name:"强壮",sp_name:"buff_wind",icon:"3036",TGroup:TGroup.Team,SType:SType.buff,act:"atk",DTType:DTType.single, ap:30,cd:10,t_num:1,hit_num:1,hit:1,hitcd:0.2,speed:720,with:0,dis:SkillDisVal[SkillRange.Long], ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, - buffs:[{buff:Attrs.ap,BType:BType.VALUE,value:10,time:30,chance:1}],debuffs:[],info:"增加目标10%攻击力,持续30秒", + buffs:[10001],info:"增加目标10%攻击力,持续30秒", }, 6103:{ uuid:6103,name:"群体强壮",sp_name:"buff_wind",icon:"3036",TGroup:TGroup.Team,SType:SType.buff,act:"atk",DTType:DTType.range, ap:30,cd:10,t_num:3,hit_num:1,hit:1,hitcd:0.2,speed:720,with:0,dis:SkillDisVal[SkillRange.Long], ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, - buffs:[{buff:Attrs.ap,BType:BType.RATIO,value:10,time:30,chance:1}],debuffs:[],info:"增加目标10%攻击力,持续30秒", + buffs:[10011],info:"增加目标10%攻击力,持续30秒", }, // ========== 怪物基础技能 ========== 6200-6299 6201: { @@ -259,14 +256,14 @@ export const SkillSet: Record = { TGroup:TGroup.Enemy, SType:SType.damage, act:"atk", DTType:DTType.single, ap:100, cd:1, t_num:1, hit_num:1, hit:1, hitcd:0.2, speed:0, with:0, dis:SkillDisVal[SkillRange.Melee], // 怪物近战特殊距离 ready:0, EAnm:0, DAnm:9001, RType:RType.fixed, EType:EType.animationEnd, - buffs:[], debuffs:[], info:"怪物基础近战攻击", + buffs:[], info:"怪物基础近战攻击", }, 6203: { uuid:6203, name:"怪物射击", sp_name:"arrow_1", icon:"3039", TGroup:TGroup.Enemy, SType:SType.damage, act:"atk", DTType:DTType.single, ap:80, cd:2, t_num:1, hit_num:1, hit:1, hitcd:0.2, speed:800, with:0, dis:SkillDisVal[SkillRange.Long], // 怪物远程特殊距离 ready:0, EAnm:0, DAnm:9001, RType:RType.linear, EType:EType.collision, - buffs:[], debuffs:[], info:"怪物基础远程攻击", + buffs:[], info:"怪物基础远程攻击", }, }; @@ -290,3 +287,53 @@ export const CanSelectSkills: Record = { // 默认 99: [6002, 6004, 6003, 6100] }; + +// ==================== 预定义 Buff 列表 ==================== +// 使用 ID 作为 Key,方便在技能配置中引用或作为模板 +export const BuffsList: Record = { + // ========== 攻击类增益 ========== 10001 - 10099 + // 攻击力提升 (固定值) + 10001: { uuid: 10001, name: "攻击提升", icon: "10001", buff: Attrs.ap, BType: BType.VALUE, value: 10, time: 5, chance: 1, info: "攻击力+10" }, + 10002: { uuid: 10002, name: "攻击提升", icon: "10002", buff: Attrs.ap, BType: BType.VALUE, value: 50, time: 5, chance: 1, info: "攻击力+50" }, + + // 攻击力提升 (百分比) + 10011: { uuid: 10011, name: "攻击提升", icon: "10011", buff: Attrs.ap, BType: BType.RATIO, value: 10, time: 5, chance: 1, info: "攻击力+10%" }, + 10012: { uuid: 10012, name: "攻击提升", icon: "10012", buff: Attrs.ap, BType: BType.RATIO, value: 20, time: 10, chance: 1, info: "攻击力+20%" }, + + // 暴击率提升 (固定值) + 10021: { uuid: 10021, name: "暴击提升", icon: "10021", buff: Attrs.critical, BType: BType.VALUE, value: 10, time: 5, chance: 1, info: "暴击率+10%" }, + 10022: { uuid: 10022, name: "暴击提升", icon: "10022", buff: Attrs.critical, BType: BType.VALUE, value: 20, time: 5, chance: 1, info: "暴击率+20%" }, + + // 暴击伤害提升 + 10031: { uuid: 10031, name: "爆伤提升", icon: "10031", buff: Attrs.critical_dmg, BType: BType.VALUE, value: 50, time: 5, chance: 1, info: "暴击伤害+50%" }, + + // 穿刺次数提升 + 10041: { uuid: 10041, name: "穿刺提升", icon: "10041", buff: Attrs.puncture, BType: BType.VALUE, value: 1, time: 10, chance: 1, info: "穿刺次数+1" }, + + // ========== 生存类增益 ========== 10100 - 10199 + // 生命值上限提升 (百分比) + 10101: { uuid: 10101, name: "生命上限提升", icon: "10101", buff: Attrs.hp_max, BType: BType.RATIO, value: 20, time: 10, chance: 1, info: "生命上限+20%" }, + + // 移动速度提升 (固定值) + 10111: { uuid: 10111, name: "移速提升", icon: "10111", buff: Attrs.speed, BType: BType.VALUE, value: 50, time: 5, chance: 1, info: "移速+50" }, + 10112: { uuid: 10112, name: "移速提升", icon: "10112", buff: Attrs.speed, BType: BType.VALUE, value: 100, time: 5, chance: 1, info: "移速+100" }, + + // 护盾 (固定值) + 10121: { uuid: 10121, name: "护盾", icon: "10121", buff: Attrs.shield, BType: BType.VALUE, value: 100, time: 10, chance: 1, info: "护盾+100" }, + + // ========== 减益类 Buff (属性降低) ========== 10200 - 10299 + // 减速 (移动速度降低) + 10201: { uuid: 10201, name: "减速", icon: "10201", buff: Attrs.speed, BType: BType.VALUE, value: -50, time: 3, chance: 1, info: "移速-50", isDebuff: true }, + + // 虚弱 (攻击力降低) + 10211: { uuid: 10211, name: "虚弱", icon: "10211", buff: Attrs.ap, BType: BType.RATIO, value: -20, time: 5, chance: 1, info: "攻击力-20%", isDebuff: true }, + + // ========== 状态控制类 (Debuff) ========== 20000 - 20099 + // 冰冻 + 20001: { uuid: 20001, name: "冰冻", icon: "20001", buff: Attrs.IN_FROST, BType: BType.BOOLEAN, value: 1, time: 1, chance: 1, info: "冰冻1秒", isDebuff: true }, + 20002: { uuid: 20002, name: "冰冻", icon: "20002", buff: Attrs.IN_FROST, BType: BType.BOOLEAN, value: 1, time: 2, chance: 1, info: "冰冻2秒", isDebuff: true }, + + // 眩晕 + 20011: { uuid: 20011, name: "眩晕", icon: "20011", buff: Attrs.IN_STUN, BType: BType.BOOLEAN, value: 1, time: 1, chance: 1, info: "眩晕1秒", isDebuff: true }, + 20012: { uuid: 20012, name: "眩晕", icon: "20012", buff: Attrs.IN_STUN, BType: BType.BOOLEAN, value: 1, time: 2, chance: 1, info: "眩晕2秒", isDebuff: true }, +}; diff --git a/assets/script/game/hero/HeroAttrsComp.ts b/assets/script/game/hero/HeroAttrsComp.ts index a957e817..b7debcb9 100644 --- a/assets/script/game/hero/HeroAttrsComp.ts +++ b/assets/script/game/hero/HeroAttrsComp.ts @@ -1,8 +1,8 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops"; import { GameEvent } from "../common/config/GameEvent"; -import { BType } from "../common/config/HeroAttrs"; -import { BuffConf, SkillRange } from "../common/config/SkillSet"; +import { Attrs, BType } from "../common/config/HeroAttrs"; +import { BuffConf, SkillDisVal, SkillRange, SkillSet } from "../common/config/SkillSet"; import { HeroInfo } from "../common/config/heroSet"; import { mLogger } from "../common/Logger"; import { _decorator } from "cc"; @@ -66,7 +66,6 @@ export class HeroAttrsComp extends ecs.Comp { // ==================== 脏标签标记 ==================== dirty_hp: boolean = false; // 血量变更标记 - dirty_mp: boolean = false; // 魔法值变更标记 dirty_shield: boolean = false; // 护盾变更标记 // ==================== 技能距离缓存 ==================== @@ -146,15 +145,119 @@ export class HeroAttrsComp extends ecs.Comp { } // ==================== BUFF 管理 ==================== /** - * 添加 buff 效果(支持多次叠加) - * @param buffConf buff 配置 (来自 SkillSet.BuffConf heroSet.buff) + * 添加 buff 效果 + * @param buffConf buff 配置 */ addBuff(buffConf: BuffConf) { + // 1. 如果是永久性增益(time=0),直接修改基础属性 + if (buffConf.time <= 0) { + this.applyAttrChange(buffConf.buff, buffConf.value, buffConf.BType); + return; + } + // 2. 临时性 Buff/Debuff 处理 + // 区分存储列表 + const targetList = buffConf.isDebuff ? this.DEBUFFS : this.BUFFS; + + // 确保列表初始化 + // 注意:这里我们用 buffConf.buff (属性名) 作为 key,而不是 buffConf.uuid + // 这样同一种属性的 buff 可以叠加或覆盖 + const attrKey = buffConf.buff as unknown as number; // 强制转换 key 类型以适配 Record + if (!targetList[attrKey]) { + targetList[attrKey] = []; + } + + const currentBuffs = targetList[attrKey]; + + // 查找是否已有同源的 buff (这里假设 uuid 相同为同源,或者简单点直接追加) + // 策略:直接追加,update 时统一计算 + // 记录添加时的数值,方便后续移除(虽然 update 是重新计算总值的) + currentBuffs.push({ + value: buffConf.value, + BType: buffConf.BType, + time: buffConf.time + }); + + // 立即应用一次属性变更(增量) + this.applyAttrChange(buffConf.buff, buffConf.value, buffConf.BType); + + mLogger.log(this.debugMode, 'HeroAttrs', `添加Buff: ${buffConf.name}, 属性:${buffConf.buff}, 值:${buffConf.value}, 时间:${buffConf.time}`); } - + /** + * 通用属性修改应用 + * @param attr 属性名 + * @param value 变化值 + * @param type 数值类型 (0:固定值, 1:百分比) + * @param reverse 是否反向应用 (用于移除 buff) + */ + private applyAttrChange(attr: Attrs, value: number, type: BType, reverse: boolean = false) { + let finalValue = value; + + // 如果是移除 buff,取反 + if (reverse) { + finalValue = -value; + } + // 处理百分比 + // 注意:百分比通常是基于基础值计算,这里简化为直接修改当前值 + // 如果需要严格的基础值+百分比,需要维护 baseAttrs 和 bonusAttrs + // 当前架构直接修改属性,百分比暂时按 (当前值 * 百分比) 或 (基础值 * 百分比) 处理 + // 鉴于属性系统中 hp/hp_max 等已经是数值,这里百分比暂定为:属性 = 属性 + (属性 * 百分比) + // 但对于 addBuff 这种临时增益,百分比通常是基于"基础值"的。 + // 由于没有显式的 base_ap,这里简化处理: + // VALUE: 直接加减 + // RATIO: 简单处理为 value 就是最终加成值(需要配置表里填好的数值),或者基于当前值 + // 通常配置表填 10 表示 10%,即 0.1。 + // 但这里的 value 已经是 number。假设配置 10 就是 10 点,或者 10%。 + + // 修正:根据 BType 处理 + if (type === BType.RATIO) { + // 假设 value 是百分比整数,如 10 代表 10% + // 必须基于某个基数。这里暂时基于当前值(不严谨,但在没有 base 属性的情况下只能这样,或者基于 100?) + // 更合理的做法:如果是 RATIO,value 应该在配置时就转为实际数值,或者这里基于当前属性计算 + // 考虑到 Attrs 定义里有很多非数值属性(如状态),需要特殊处理 + + // 针对状态类属性(IN_FROST 等),通常是 BOOLEAN,不走 RATIO + // 针对数值类(ap, hp),RATIO 应该是 value% * current + + // 简化:目前只支持 VALUE 型直接加减。RATIO 型需要更复杂的属性系统支持(Base + Add + Mul)。 + // 这里的实现先按 VALUE 处理,如果以后需要 RATIO,建议在 addBuff 前计算好 value + // 或者:约定 RATIO 时,value 是基于当前值的百分比增量 + const ratio = finalValue / 100; + // 注意:这里直接修改 this[attr] 会导致多次叠加问题。 + // 临时 Buff 的正确做法是:Update 中每一帧重置属性 -> 应用所有 Buff。 + // 但当前架构似乎是“增量修改”式的。 + // “增量修改”式在移除时很麻烦(尤其是百分比)。 + // 妥协方案:只支持 VALUE 加减。配置表里的 RATIO 需要在逻辑层转为 VALUE。 + // 但为了兼容 BType.RATIO,这里暂时按 (当前值 * ratio) 计算增量 + // 这会导致 recursive 问题,所以严谨的项目里属性必须分层。 + // 鉴于“少可用原则”,这里仅处理 VALUE 和 BOOLEAN + if (typeof this[attr] === 'number') { + // 警告:直接改写数值可能不准确 + this[attr] = (this[attr] as number) * (1 + ratio); + } + } else if (type === BType.BOOLEAN) { + // 布尔型/状态型:value > 0 为 true/计数+1,移除时 -1 + // 这里使用计数器方式来支持多个同类状态叠加 + // 例如 IN_FROST 是一个状态,不是属性。 + // 需要在 HeroAttrsComp 中定义对应的状态计数器,或者利用 DEBUFFS 列表的存在性判断状态 + // 暂时直接修改属性(如果属性是 boolean) + if (typeof this[attr] === 'boolean') { + this[attr] = !reverse; // 添加设为 true, 移除设为 false (不仅确,多个冰冻会出问题) + // 正确做法:updateBuffsDebuffs 中根据列表是否为空来设置状态 + } + } else { + // VALUE 固定值 + if (typeof this[attr] === 'number') { + this[attr] = (this[attr] as number) + finalValue; + } + } + + // 标记脏数据(如果有对应的 dirty 标记) + if (attr === Attrs.hp) this.dirty_hp = true; + if (attr === Attrs.shield) this.dirty_shield = true; + } // ==================== 临时 BUFF/DEBUFF 更新 ==================== /** @@ -162,7 +265,59 @@ export class HeroAttrsComp extends ecs.Comp { * @param dt 时间增量 */ updateBuffsDebuffs(dt: number) { + this.updateList(this.BUFFS, dt); + this.updateList(this.DEBUFFS, dt); + // 更新状态标记 (根据 DEBUFFS 列表是否存在有效项) + this.updateStatusFlags(); + } + + private updateList(list: Record>, dt: number) { + for (const attrKey in list) { + const buffs = list[attrKey]; + if (!buffs || buffs.length === 0) continue; + + // 倒序遍历以便移除 + for (let i = buffs.length - 1; i >= 0; i--) { + const buff = buffs[i]; + buff.time -= dt; + + if (buff.time <= 0) { + // Buff 过期,移除属性加成 + // 注意:key 是 string (from record key),需要转为 Attrs + const attrName = attrKey as unknown as Attrs; + this.applyAttrChange(attrName, buff.value, buff.BType, true); // reverse = true + + // 从列表中移除 + buffs.splice(i, 1); + mLogger.log(this.debugMode, 'HeroAttrs', `Buff过期: 属性:${attrName}, 恢复值:${buff.value}`); + } + } + + // 如果该属性的 buff 列表空了,可以清理 key (可选) + if (buffs.length === 0) { + delete list[attrKey]; + } + } + } + + private updateStatusFlags() { + // 检查特定状态的 Debuff 列表是否为空,来更新 boolean 标志 + // 例如:冰冻 + this.checkStatus(Attrs.IN_FROST, 'is_stop'); // 假设冰冻会停止行动 + // this.checkStatus(Attrs.IN_STUN, 'is_stunned'); // 需要在类里定义 is_stunned + } + + private checkStatus(attr: Attrs, flagName: string) { + const key = attr as unknown as number; + const hasBuff = this.DEBUFFS[key] && this.DEBUFFS[key].length > 0; + + // 只有当状态改变时才赋值,避免每帧赋值 + if (this[flagName] !== hasBuff) { + // 特殊处理:有些状态可能由其他逻辑控制,这里强行覆盖可能会冲突 + // 但作为 Buff 系统,它应该拥有最高解释权之一 + this[flagName] = hasBuff; + } } @@ -172,17 +327,17 @@ export class HeroAttrsComp extends ecs.Comp { * 在技能初始化、新增技能、MP变化时调用 * @param skillsComp 技能组件 */ - public updateSkillDistanceCache(skillsComp: HeroSkillsComp): void { - if (!skillsComp) { + public updateSkillDistanceCache(skill_id:number): void { + let skillConf=SkillSet[skill_id]; + if (!skillConf) { this.maxSkillDistance = 0; this.minSkillDistance = 0; return; } - // 最远距离使用当前MP可施放的技能 - this.maxSkillDistance = skillsComp.getMaxSkillDistance(); + this.maxSkillDistance = SkillDisVal[skillConf.dis]; // 最近距离使用所有技能中的最小距离,不考虑MP限制,用于停止位置判断 - this.minSkillDistance = skillsComp.getAbsoluteMinSkillDistance(); + this.minSkillDistance = SkillDisVal[skillConf.dis]; } /** @@ -255,7 +410,6 @@ export class HeroAttrsComp extends ecs.Comp { this.killed_count =0; // 重置脏标签 this.dirty_hp = false; - this.dirty_mp = false; this.dirty_shield = false; } diff --git a/assets/script/game/hero/HeroViewComp.ts b/assets/script/game/hero/HeroViewComp.ts index 06e7c652..ab55387f 100644 --- a/assets/script/game/hero/HeroViewComp.ts +++ b/assets/script/game/hero/HeroViewComp.ts @@ -154,10 +154,6 @@ export class HeroViewComp extends CCComp { this.model.dirty_hp = false; } - // if (this.model.dirty_mp) { - // this.mp_show(); - // this.model.dirty_mp = false; - // } if (this.model.dirty_shield) { this.show_shield(this.model.shield, this.model.shield_max);