diff --git a/assets/script/game/common/config/SkillSet.ts b/assets/script/game/common/config/SkillSet.ts index 8b02b492..41763aa4 100644 --- a/assets/script/game/common/config/SkillSet.ts +++ b/assets/script/game/common/config/SkillSet.ts @@ -299,3 +299,33 @@ export const SkillSet: Record = { }; +export enum FieldSkillType { + SummonCount = 1, // 召唤触发技能次数提升 + DeadCount = 2, // 死亡触发技能次数提升 + StartCount = 3, // 战斗开始触发技能次数提升 + EndCount = 4, // 战斗结束触发技能次数提升 + WaveGold = 5, // 每回合金币收益提升 + SellGold = 6, // 卖出英雄金币提升 + WaveHeal = 7, // 战斗结束生命回复量提升 + HeroAtk = 8, // 英雄攻击力加成 +} + +export interface FieldSkillConfig { + uuid: number; + name: string; + type: FieldSkillType; + value: number; // 提升的数值 + info: string; +} + +export const FieldSkillSet: Record = { + 7001: { uuid: 7001, name: "召唤精通", type: FieldSkillType.SummonCount, value: 1, info: "场上所有友方召唤触发技能触发次数+1" }, + 7002: { uuid: 7002, name: "亡灵统御", type: FieldSkillType.DeadCount, value: 1, info: "场上所有友方死亡触发技能触发次数+1" }, + 7003: { uuid: 7003, name: "先发制人", type: FieldSkillType.StartCount, value: 1, info: "场上所有友方战斗开始触发技能触发次数+1" }, + 7004: { uuid: 7004, name: "余音绕梁", type: FieldSkillType.EndCount, value: 1, info: "场上所有友方战斗结束触发技能触发次数+1" }, + 7005: { uuid: 7005, name: "理财专家", type: FieldSkillType.WaveGold, value: 10, info: "每回合结束时金币收益提升10" }, + 7006: { uuid: 7006, name: "商业大亨", type: FieldSkillType.SellGold, value: 5, info: "卖出英雄时金币收益提升5" }, + 7007: { uuid: 7007, name: "神圣恢复", type: FieldSkillType.WaveHeal, value: 0.3, info: "战斗结束时全队恢复效果+30%" }, + 7008: { uuid: 7008, name: "战鼓激昂", type: FieldSkillType.HeroAtk, value: 0.2, info: "场上所有友方攻击力提升20%" }, +}; + diff --git a/assets/script/game/common/config/heroSet.ts b/assets/script/game/common/config/heroSet.ts index 16ecaa99..08d8df2d 100644 --- a/assets/script/game/common/config/heroSet.ts +++ b/assets/script/game/common/config/heroSet.ts @@ -67,6 +67,7 @@ export interface heroInfo { dead?:number[]; // 死亡后触发的技能uuid列表 fstart?:number[]; // 战斗开始时释放的技能uuid列表 fend?:number[]; // 战斗结束时释放的技能uuid列表 + field?:number[]; // 驻场技能uuid列表,英雄在场时对全局生效 atking?:{s_uuid:number, t_num:number}[]; // 普通攻击后触发的技能配置,s_uuid: 技能id, t_num: 触发所需的普攻次数 atked?:{s_uuid:number, t_num:number}[]; // 受击后触发的技能配置,s_uuid: 技能id, t_num: 触发所需的受击次数 // dis: number; // 攻击距离(像素) diff --git a/assets/script/game/hero/Hero.ts b/assets/script/game/hero/Hero.ts index 3ff3b468..3c68703a 100644 --- a/assets/script/game/hero/Hero.ts +++ b/assets/script/game/hero/Hero.ts @@ -10,6 +10,7 @@ import { GameEvent } from "../common/config/GameEvent"; import { Attrs} from "../common/config/HeroAttrs"; import { MoveComp } from "./MoveComp"; import { mLogger } from "../common/Logger"; +import { FieldSkillType } from "../common/config/SkillSet"; /** 英雄实体:负责英雄节点创建、属性初始化、入场动画与销毁流程 */ @ecs.register(`Hero`) @@ -200,14 +201,19 @@ export class Hero extends ecs.Entity { // 落地后触发 call 技能 if (model && model.call && model.call.length > 0) { - model.call.forEach(uuid => { - oops.message.dispatchEvent(GameEvent.TriggerSkill, { - s_uuid: uuid, - heroAttrs: model, - heroView: view, - triggerType: 'call' + let triggerCount = 1 + HeroAttrsComp.getFieldSkillTotalValue(FieldSkillType.SummonCount); + triggerCount = Math.max(1, Math.floor(triggerCount)); + + for (let i = 0; i < triggerCount; i++) { + model.call.forEach(uuid => { + oops.message.dispatchEvent(GameEvent.TriggerSkill, { + s_uuid: uuid, + heroAttrs: model, + heroView: view, + triggerType: 'call' + }); }); - }); + } } }) .start(); diff --git a/assets/script/game/hero/HeroAtkSystem.ts b/assets/script/game/hero/HeroAtkSystem.ts index 8363b534..e28933b4 100644 --- a/assets/script/game/hero/HeroAtkSystem.ts +++ b/assets/script/game/hero/HeroAtkSystem.ts @@ -10,6 +10,7 @@ import { smc } from "../common/SingletonModuleComp"; import { HeroInfo } from "../common/config/heroSet"; import { oops } from "db://oops-framework/core/Oops"; import { GameEvent } from "../common/config/GameEvent"; +import { FieldSkillType } from "../common/config/SkillSet"; import { mLogger } from "../common/Logger"; @@ -276,14 +277,19 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd if (TAttrsComp.dead && TAttrsComp.dead.length > 0) { const view = entity.get(HeroViewComp); if (view) { - TAttrsComp.dead.forEach((uuid: number) => { - oops.message.dispatchEvent(GameEvent.TriggerSkill, { - s_uuid: uuid, - heroAttrs: TAttrsComp, - heroView: view, - triggerType: 'dead' + let triggerCount = 1 + HeroAttrsComp.getFieldSkillTotalValue(FieldSkillType.DeadCount); + triggerCount = Math.max(1, Math.floor(triggerCount)); + + for (let i = 0; i < triggerCount; i++) { + TAttrsComp.dead.forEach((uuid: number) => { + oops.message.dispatchEvent(GameEvent.TriggerSkill, { + s_uuid: uuid, + heroAttrs: TAttrsComp, + heroView: view, + triggerType: 'dead' + }); }); - }); + } } } diff --git a/assets/script/game/hero/HeroAttrsComp.ts b/assets/script/game/hero/HeroAttrsComp.ts index d3c75d57..c8b15d59 100644 --- a/assets/script/game/hero/HeroAttrsComp.ts +++ b/assets/script/game/hero/HeroAttrsComp.ts @@ -1,8 +1,9 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; -import { HeroDisVal, HSkillInfo, HType } from "../common/config/heroSet"; +import { HeroDisVal, HeroInfo, HSkillInfo, HType } from "../common/config/heroSet"; import { mLogger } from "../common/Logger"; import { Timer } from "db://oops-framework/core/common/timer/Timer"; -import { FightSet } from "../common/config/GameSet"; +import { FacSet, FightSet } from "../common/config/GameSet"; +import { FieldSkillSet, FieldSkillType } from "../common/config/SkillSet"; @ecs.register('HeroAttrs') export class HeroAttrsComp extends ecs.Comp { public debugMode: boolean = false; @@ -279,8 +280,24 @@ export class HeroAttrsComp extends ecs.Comp { this.dirty_shield = false; } - - + /** 获取指定驻场技能类型的总加成值(只计算存活的英雄) */ + public static getFieldSkillTotalValue(type: FieldSkillType): number { + let total = 0; + ecs.query(ecs.allOf(HeroAttrsComp)).forEach((entity: ecs.Entity) => { + const model = entity.get(HeroAttrsComp); + if (!model || model.is_dead || model.fac !== FacSet.HERO) return; + const heroConfig = HeroInfo[model.hero_uuid]; + if (heroConfig && heroConfig.field) { + for (const skillUuid of heroConfig.field) { + const skillConfig = FieldSkillSet[skillUuid]; + if (skillConfig && skillConfig.type === type) { + total += skillConfig.value; + } + } + } + }); + return total; + } } @ecs.register('HeroBuffSystem') diff --git a/assets/script/game/map/HInfoComp.ts b/assets/script/game/map/HInfoComp.ts index 5696c4bc..095885af 100644 --- a/assets/script/game/map/HInfoComp.ts +++ b/assets/script/game/map/HInfoComp.ts @@ -25,6 +25,8 @@ import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/modu import { HeroInfo } from "../common/config/heroSet"; import { HeroAttrsComp } from "../hero/HeroAttrsComp"; import { Hero } from "../hero/Hero"; +import { FieldSkillType } from "../common/config/SkillSet"; +import { GameEvent } from "../common/config/GameEvent"; import { oops } from "db://oops-framework/core/Oops"; import { UIID } from "../common/config/GameUIConfig"; import { mLogger } from "../common/Logger"; @@ -251,6 +253,13 @@ export class HInfoComp extends CCComp { removed }); if (!removed) return; + + // 卖出英雄金币收益 + const baseSellGold = 1; // 基础卖出金币 + const goldBoost = HeroAttrsComp.getFieldSkillTotalValue(FieldSkillType.SellGold); + const totalSellGold = baseSellGold + goldBoost; + oops.message.dispatchEvent(GameEvent.CoinAdd, { delta: totalSellGold }); + oops.gui.remove(UIID.IBox); } diff --git a/assets/script/game/map/MissionComp.ts b/assets/script/game/map/MissionComp.ts index 5bf8a4a8..5b41bb7d 100644 --- a/assets/script/game/map/MissionComp.ts +++ b/assets/script/game/map/MissionComp.ts @@ -45,6 +45,7 @@ import { Skill } from "../skill/Skill"; import { Tooltip } from "../skill/Tooltip"; import { CardInitCoins } from "../common/config/CardSet"; import { Timer } from "db://oops-framework/core/common/timer/Timer"; +import { FieldSkillType } from "../common/config/SkillSet"; const { ccclass, property } = _decorator; /** 任务(关卡)生命周期阶段 */ @@ -466,20 +467,30 @@ export class MissionComp extends CCComp { * @param isStart 是否为战斗开始 */ private triggerHeroBattleSkills(isStart: boolean) { + let triggerCount = 1; + if (isStart) { + triggerCount += HeroAttrsComp.getFieldSkillTotalValue(FieldSkillType.StartCount); + } else { + triggerCount += HeroAttrsComp.getFieldSkillTotalValue(FieldSkillType.EndCount); + } + triggerCount = Math.max(1, Math.floor(triggerCount)); + ecs.query(this.heroAttrsMatcher).forEach(entity => { const attrs = entity.get(HeroAttrsComp); const view = entity.get(HeroViewComp); if (!attrs || !view || attrs.is_dead || attrs.fac !== FacSet.HERO) return; const skillUuids = isStart ? attrs.fstart : attrs.fend; if (skillUuids && skillUuids.length > 0) { - skillUuids.forEach(uuid => { - oops.message.dispatchEvent(GameEvent.TriggerSkill, { - s_uuid: uuid, - heroAttrs: attrs, - heroView: view, - triggerType: isStart ? 'fstart' : 'fend' + for (let i = 0; i < triggerCount; i++) { + skillUuids.forEach(uuid => { + oops.message.dispatchEvent(GameEvent.TriggerSkill, { + s_uuid: uuid, + heroAttrs: attrs, + heroView: view, + triggerType: isStart ? 'fstart' : 'fend' + }); }); - }); + } } }); } @@ -488,13 +499,16 @@ export class MissionComp extends CCComp { * 战斗结束阶段治疗所有英雄(包括墓地英雄),恢复70%最大生命值 */ private healAllHeroes() { + const healRateBoost = HeroAttrsComp.getFieldSkillTotalValue(FieldSkillType.WaveHeal); + const finalHealRate = Math.min(1, FightSet.WAVE_HEAL_RATE + healRateBoost); + ecs.query(this.heroAttrsMatcher).forEach(entity => { const attrs = entity.get(HeroAttrsComp); const view = entity.get(HeroViewComp); if (!attrs || !view || attrs.fac !== FacSet.HERO) return; // 计算恢复量:基于配置的百分比(如 70%)的最大生命值 - const healAmount = Math.floor(attrs.hp_max * FightSet.WAVE_HEAL_RATE); + const healAmount = Math.floor(attrs.hp_max * finalHealRate); // 应用恢复量,不超过最大生命值 attrs.hp = Math.min(attrs.hp_max, attrs.hp + healAmount); @@ -649,7 +663,12 @@ export class MissionComp extends CCComp { const base = Math.max(0, Math.floor(this.prepareBaseCoinReward)); const grow = Math.max(0, Math.floor(this.prepareCoinWaveGrow)); const cap = Math.max(0, Math.floor(this.prepareCoinRewardCap)); - const reward = Math.min(cap, base + (wave - 1) * grow); + let reward = Math.min(cap, base + (wave - 1) * grow); + + // 增加驻场技能金币收益 + const goldBoost = HeroAttrsComp.getFieldSkillTotalValue(FieldSkillType.WaveGold); + reward += goldBoost; + if (reward <= 0) { this.lastPrepareCoinWave = wave; return; @@ -657,7 +676,8 @@ export class MissionComp extends CCComp { smc.vmdata.mission_data.coin = Math.max(0, Math.floor((smc.vmdata.mission_data.coin ?? 0) + reward)); this.lastPrepareCoinWave = wave; oops.message.dispatchEvent(GameEvent.CoinAdd, { delta: reward, syncOnly: true }); - mLogger.log(this.debugMode, 'MissionComp', "prepare coin reward", { wave, reward, coin: smc.vmdata.mission_data.coin }); + + mLogger.log(this.debugMode, "MissionComp", "grantPrepareCoinByWave", { wave, reward, boost: goldBoost, coin: smc.vmdata.mission_data.coin }); } // ======================== 怪物数量管理 ======================== diff --git a/assets/script/game/map/MissionHeroComp.ts b/assets/script/game/map/MissionHeroComp.ts index 3f62ae7c..75f278ea 100644 --- a/assets/script/game/map/MissionHeroComp.ts +++ b/assets/script/game/map/MissionHeroComp.ts @@ -38,6 +38,7 @@ import { HeroAttrsComp } from "../hero/HeroAttrsComp"; import { FacSet, FightSet, BoxSet } from "../common/config/GameSet"; import { oneCom } from "../skill/oncend"; import { HeroViewComp } from "../hero/HeroViewComp"; +import { FieldSkillSet, FieldSkillType } from "../common/config/SkillSet"; const { ccclass } = _decorator; /** @@ -252,6 +253,26 @@ export class MissionHeroCompComp extends CCComp { return heroes; } + /** 获取指定驻场技能类型的总加成值(只计算存活的英雄) */ + public getFieldSkillTotalValue(type: FieldSkillType): number { + let total = 0; + const heroes = this.getAllHeroes(); + for (const hero of heroes) { + const model = hero.get(HeroAttrsComp); + if (!model || model.is_dead) continue; + const heroConfig = HeroInfo[model.hero_uuid]; + if (heroConfig && heroConfig.field) { + for (const skillUuid of heroConfig.field) { + const skillConfig = FieldSkillSet[skillUuid]; + if (skillConfig && skillConfig.type === type) { + total += skillConfig.value; + } + } + } + } + return total; + } + /** * 从存活英雄中挑选可参与本次合成的英雄组。 *