15 Commits

Author SHA1 Message Date
walkpan
5cacfee288 chore: 调整怪物数值与波次配置,优化游戏爽感与难度平衡
1.  调整MissionComp中怪物上限与恢复阈值,提升刷怪容错空间
2.  下调全基础怪物属性并调整注释,降低初期怪物强度,同时调整BOSS属性降低其压力
3.  更新MonsterStats与TierConfigs,调整怪物消耗、预算与生成数量
4.  调整各波次模板的怪物生成数量,优化战斗体验
5.  调整自适应刷怪的最大填充比例,提升怪物生成效率
6.  更新部分配置注释,补充设计说明
2026-05-23 22:06:46 +08:00
walkpan
92836c14b6 feat(map,economy): 重做游戏经济与卡牌平衡系统
本次提交重构了英雄出售、抽卡、波次金币的数值体系:
1. 调整英雄出售价格按等级计算,1/2/3级分别为3/10/25金币
2. 修改抽卡刷新费用为2,初始金币调整为10
3. 重做波次金币公式,基础收益改为10,每波增长4
4. 调整卡池卡牌消耗与特殊卡牌的定价
5. 优化卡牌抽取消耗的计算逻辑,使用指数增长替代线性计算
2026-05-23 19:03:48 +08:00
walkpan
f49831bf9e chore: 调整怪物配置与肉鸽模式参数,优化游戏平衡性
1.  重构基础怪物数据,按站位分类并更新属性、名称与描述
2.  更新怪物池与属性配置,调整各类型怪物生成权重与消耗
3.  修改阶梯预算与生成数量,调整适配性配置参数
4.  优化生成引擎的预算填充逻辑,增加生成上限限制
2026-05-23 19:03:09 +08:00
walkpan
9f6f09dbd3 refactor(heroConfig): 完成英雄配置v3版本重构
1.  更新职业触发规则文档,新增8大流派分类与职业绑定规则
2.  重构现有英雄配置,调整职业与触发逻辑:
    - 调整5006疾风战士为疾风刺客,新增死亡触发效果
    - 重构奥术法师等现有英雄,替换为field驻场机制
    - 新增击退推拉、暴击爆发、经济滚雪球、献祭亡语4大流派共12个新英雄
3.  更新英雄列表与文档说明,统一配置格式与触发逻辑
2026-05-23 18:29:46 +08:00
walkpan
8a485bb6e6 refactor: 重构英雄卡池为动态生成方式
更新导入以包含HeroList,移除硬编码的英雄卡池条目,改为动态生成卡牌,适配英雄等级与卡池等级的计算规则,提升代码可维护性。
2026-05-23 15:32:28 +08:00
walkpan
a2b5bbc39d docs(hero config): 完善英雄配置文档,新增四大流派及配套数据
补充了完整的流派协同矩阵、6人推荐组队方案与英雄ID总表,同时新增英雄配置Excel文件的导入元文件
2026-05-23 15:22:56 +08:00
walkpan
268c6e155a refactor(英雄&卡池): 修改英雄等级字段为pool_lv并优化卡池配置
重构heroInfo接口,将原cards_lv字段重命名为pool_lv,同步更新所有英雄配置与注释;修正HListComp的等级显示逻辑,新增按pool_lv分级的卡池配置。
2026-05-23 15:09:45 +08:00
walkpan
23db51df12 feat(config): 新增多流派英雄并优化英雄配置表
按流派重新分组整理英雄配置,保留原有可用核心英雄
新增攻速叠伤、铁壁反伤、冰冻控制、治疗续航四类新英雄
注释废弃的旧英雄配置项
移除怪物配置中的冗余cards_lv字段
更新HeroList数组仅包含活跃可用的英雄ID
2026-05-23 14:51:18 +08:00
walkpan
de67e36590 docs(英雄配置): 重构英雄配置文档并新增官方配置表
重写英雄配置说明文档,系统化整理四大英雄流派的设计规则、12款新英雄的详细配置与协同方案,新增heros.xlsx英雄配置表文件,统一现有与新设计英雄的属性和触发机制,替换旧版零散配置内容。
2026-05-23 14:24:32 +08:00
walkpan
0b59f601d8 feat(penetration): 将穿刺机制从固定次数改为概率触发模式
统一重命名所有穿刺相关属性为 `puncture_chance` 以规范代码命名,新增FightSet.PUNCTURE_DOWN配置项控制每次穿透后的概率衰减值。调整6408号穿刺强化技能,将提升穿刺次数效果改为提升20%穿透概率并修正AP消耗。在技能命中逻辑中添加穿透概率判定逻辑,实现概率穿透效果,同时更新所有引用原属性的代码位置确保功能正常。
2026-05-23 14:08:45 +08:00
walkpan
cb53417ea8 feat(skill config): 新增7个团队属性强化支援技能配置
新增的技能均为全体友方增益buff,覆盖暴击率、暴击伤害、冰冻概率、击退属性、穿透次数和风怒次数强化,持续1次生效
2026-05-23 13:32:21 +08:00
walkpan
9eccca7e2a refactor(skill/hero): 重构技能buff系统,优化属性处理与技能加成逻辑
- 新增HeroAttrsComp的add_special_attr方法,实现动态累加任意数字类型的英雄属性
- 废弃旧的BuffConf数组配置格式,改用单一buff_type字段简化技能buff配置
- 修复金币类技能加成未随技能等级提升的问题,调整计算逻辑为baseGold + sUp.ap * skillLv
- 重构applyActualFriendlyEffect方法,添加技能等级参数,按buff类型匹配对应升级加成
- 更新所有内置技能配置为新的格式规范
2026-05-23 13:26:11 +08:00
walkpan
fce7646de6 feat(技能系统): 新增获取金币技能功能
新增金币类型技能枚举与配置字段,添加6303号获取金币技能配置;新增通用的技能结束动画播放逻辑,当技能配置了endAnm时自动播放;完善施法系统的金币技能处理逻辑,计算并添加对应金币;新增对应的技能prefab资源文件。
2026-05-23 12:29:26 +08:00
walkpan
88d7bdae47 feat(skill): 支持技能参数自定义覆盖
本次修改实现同技能不同角色的差异化技能效果:
1. 新增SkillOverrides接口与mergeSkillParams工具函数,用于合并基础技能配置和角色覆盖参数
2. 更新英雄配置、属性组件、触发辅助系统与施法系统以适配该机制
3. 为盾骑士、医师添加示例差异化配置,验证功能可行性
4. 整理技能配置,删除冗余重复的旧技能条目
5. 新增技能重构设计计划文档,替换旧的迁移计划文档
2026-05-23 12:11:00 +08:00
walkpan
eae62f245a docs: add skill template refactor design and migration plan docs
新增技能基座重构的设计文档和完整迁移计划文档,包含新的接口定义、配置结构、运行时参数解析逻辑以及分步迁移验证方案,为后续技能系统重构提供完整的设计指导。
2026-05-22 10:22:33 +08:00
23 changed files with 1821 additions and 840 deletions

View File

@@ -0,0 +1,49 @@
# 技能配置重构实施计划
## 1. 探索阶段总结 (Current State Analysis)
经过对代码库的探索,当前技能触发系统及相关配置状态如下:
- `SkillSet.ts` 包含了所有技能的基座配置 `SkillConfig` 和技能字典 `SkillSet`
- `heroSet.ts` 中的 `HeroInfo` 存放英雄和怪物的配置,目前 `call`, `dead`, `fstart`, `fend` 被定义为 `number[]`,而 `atking``atked` 被定义为 `{s_uuid: number, t_num: number}[]`
- `HeroAttrsComp.ts` 内部存储了与配置一致的触发技能结构。
- `SkillTriggerHelper.ts` 负责判定并向外派发 `GameEvent.TriggerSkill` 事件,由 `SCastSystem.ts` 监听并执行 `forceCastTriggerSkill`
- 目前 `SCastSystem.ts` 在收集技能目标和施放技能时,都是直接从 `SkillSet[s_uuid]` 读取 `config`,没有针对具体角色的差异化机制。
## 2. 拟议变更 (Proposed Changes)
### 2.1 修改 `SkillSet.ts`
- **新增接口**:定义 `SkillOverrides` 接口,包含所有可被角色覆盖的技能参数(如 `TGroup`, `ap`, `hit_count`, `buffs` 等,全部为可选字段)。
- **新增函数**:编写 `mergeSkillParams(config, overrides?)` 函数,将基座 `config` 和角色覆盖 `overrides` 进行合并,返回一个新的 `SkillConfig` 对象。
### 2.2 修改 `heroSet.ts`
- **扩展接口**
-`HSkillInfo` 接口中增加 `overrides?: SkillOverrides;`
-`heroInfo` 接口中的触发字段 `call`, `dead`, `fstart`, `fend`, `atking`, `atked` 统一更新为 `{ s_uuid: number; t_num: number; overrides?: SkillOverrides }[]` 结构。
- **更新配置示例**:按照设计文档更新英雄 `5001`, `5002`, `5301`, `5302` 的配置,为特定的触发技能添加 `overrides` 字段(如盾骑士 5002 全队护盾覆盖)。
### 2.3 修改 `HeroAttrsComp.ts`
- **同步类型**:将 `call`, `dead`, `fstart`, `fend`, `atking`, `atked` 的类型同步改为与 `heroInfo` 一致的 `{ s_uuid: number; t_num: number; overrides?: SkillOverrides }[]`
### 2.4 修改 `SkillTriggerHelper.ts`
- **派发支持**
- 更新 `dispatchSingle` 方法签名,增加 `overrides?: SkillOverrides` 参数,并在 `oops.message.dispatchEvent(GameEvent.TriggerSkill, {...})` 中将其传入。
- 更新 `handleCall`, `handleDead`, `handleArrayTrigger` 处理逻辑,将原先对 `number[]` 的处理改为对 `{s_uuid, t_num, overrides}` 对象数组的处理,并提取 `overrides` 传递给 `dispatchArray`
- 更新 `handleAtking`, `handleAtked` 中的 `dispatchSingle` 调用,传入 `atkConfig.overrides`
### 2.5 修改 `SCastSystem.ts` (关键运行时逻辑)
- **事件监听更新**:在 `onTriggerSkill` 方法的 `args` 参数定义中补充 `overrides?: SkillOverrides`,并传递给 `forceCastTriggerSkill`
- **合并逻辑上移(架构优化)**
-`forceCastTriggerSkill``castSkill` 的**方法入口处**(而非 `applyFriendlySkillEffects` 内部),第一时间调用 `mergeSkillParams(config, overrides)` 获取 `effective` 技能配置。
- 将后续所有关于阵营判定(如 `effective.TGroup`)、目标收集、以及传递给 `applyFriendlySkillEffects` / `applyEnemySkillEffects` 的参数全部替换为 `effective`
- **为何如此设计**:如果在原设计中仅在 `applyFriendlySkillEffects` 入口处合并,那么前置的**目标选择逻辑**(依赖 `TGroup` 判定是 `Self` 还是 `Team`)将会使用未合并的基础配置,导致类似“自己加盾变为全队加盾”的 `TGroup` 覆盖无法生效。将合并操作前置可以彻底解决这一问题。
- **主动技能支持**:在 `pickCastSkill` 中,读取 `heroAttrs.skills[s_uuid]?.overrides` 并进行合并判定,同时将 `overrides` 放入返回的 `castPlan` 中,以便 `castSkill` 使用。
## 3. 假设与决策 (Assumptions & Decisions)
- **统一触发结构**:虽然 `call`, `dead`, `fstart`, `fend` 不严格需要 `t_num`,但为了类型统一并完全遵守设计规范,统一采用了包含 `t_num` 的对象结构。
- **合并前置决策**:如上所述,坚决在施放方法入口处进行 `mergeSkillParams` 以保证目标收集逻辑能够感知到 `TGroup` 的变化。这比设计规范中要求的修改范围略有扩大,但对于系统功能的正确实现是必须的。
- **卡牌技能影响**:卡牌技能(`forceCastCardSkill`)当前没有绑定角色的 `overrides`,因此维持读取基础 `SkillSet` 逻辑不变。
## 4. 验证步骤 (Verification steps)
1. 编译 TypeScript 代码,确保 `HeroAttrsComp`, `heroSet`, `SCastSystem` 等修改后的接口和类型无报错。
2. 启动游戏或运行测试,确认 `5001` (见习战士) 触发的基础护盾只对自己生效。
3. 确认 `5002` (盾骑士) 受击触发的护盾技能正确地为全队附加护盾并且护盾值ap与次数hit_count符合 `overrides` 配置。
4. 确认所有旧版英雄技能在无 `overrides` 时能够正确回退到 `SkillSet` 的默认配置,游戏运转正常无异常日志。

View File

@@ -0,0 +1,289 @@
[
{
"__type__": "cc.Prefab",
"_name": "gold",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "gold",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [
{
"__id__": 2
}
],
"_active": true,
"_components": [
{
"__id__": 8
},
{
"__id__": 10
},
{
"__id__": 12
}
],
"_prefab": {
"__id__": 14
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 6.112,
"y": 45.573,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_mobility": 0,
"_layer": 1,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "Node",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 3
},
{
"__id__": 5
}
],
"_prefab": {
"__id__": 7
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_mobility": 0,
"_layer": 1,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": {
"__id__": 4
},
"_contentSize": {
"__type__": "cc.Size",
"width": 127,
"height": 127
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "ddhDbko4FLmKZGY46brX7z"
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": {
"__id__": 6
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_spriteFrame": null,
"_type": 0,
"_fillType": 0,
"_sizeMode": 1,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_useGrayscale": false,
"_atlas": null,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "c3vPZUzCRINL3sICnCZKIr"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "feOW1uSctLKYCw3esMiuox",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 9
},
"_contentSize": {
"__type__": "cc.Size",
"width": 104,
"height": 75
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "a7pn5tzA1BSI1AfdpVsHh7"
},
{
"__type__": "cc.Animation",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 11
},
"playOnLoad": true,
"_clips": [
{
"__uuid__": "a2e59563-ef5b-4535-a9b3-1b19c5253489",
"__expectedType__": "cc.AnimationClip"
}
],
"_defaultClip": {
"__uuid__": "a2e59563-ef5b-4535-a9b3-1b19c5253489",
"__expectedType__": "cc.AnimationClip"
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "63z5ZyjTNKYbn+kEVB1s3W"
},
{
"__type__": "0f3c4JhFbFO2rEFqBJJ7hFv",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 13
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "32SLcINL1JHZ+vIyextzaC"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "cfqCWnxbFLNoQMedQXsav3",
"instance": null,
"targetOverrides": null
}
]

View File

@@ -0,0 +1 @@
{"ver":"1.1.50","importer":"prefab","imported":true,"uuid":"e8d41546-4291-4505-8d72-fec141f76309","files":[".json"],"subMetas":{},"userData":{"syncNodeName":"gold"}}

View File

@@ -1,5 +1,5 @@
import * as exp from "constants"
import { HeroInfo, HType } from "./heroSet"
import { HeroInfo, HeroList, HType } from "./heroSet"
import { FightSet } from "./GameSet"
import { oops } from "db://oops-framework/core/Oops"
@@ -70,7 +70,7 @@ export const CardsUpSet: Record<number, number> = {
}
/**初始coin数 */
export const CardInitCoins = 11
export const CardInitCoins = 10
/** 卡池升级每波减免金额 */
export const CARD_POOL_UPGRADE_DISCOUNT_PER_WAVE = 10
/** 卡池默认初始等级 */
@@ -81,44 +81,58 @@ export const CARD_POOL_MAX_LEVEL = CardLV.LV3
export const CARD_HERO_MAX_LEVEL = 1
/** 基础卡池(英雄、技能、功能) */
export const CardPoolList: CardConfig[] = [
{ uuid: 5001, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5002, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5003, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5004, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5005, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
export const CardPoolList: CardConfig[] = [];
{ uuid: 5101, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5102, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5103, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5104, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5105, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
// 动态生成英雄卡池
HeroList.forEach(uuid => {
const hero = HeroInfo[uuid];
if (!hero) return;
{ uuid: 5201, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5202, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5203, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5204, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5301, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5302, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
const basePoolLv = hero.pool_lv || 1;
const baseHeroLv = hero.lv || 1;
const baseCost = 5;
const baseWeight = 25;
{ uuid: 5401, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5402, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
// 生成从 basePoolLv 到 CARD_POOL_MAX_LEVEL 的卡牌
for (let pLv = basePoolLv; pLv <= CARD_POOL_MAX_LEVEL; pLv++) {
const offset = pLv - basePoolLv;
const targetHeroLv = baseHeroLv + offset;
// 英雄的最高等级 是MERGE_MAX-1
if (targetHeroLv > FightSet.MERGE_MAX - 1) {
break;
}
// cost = baseCost * 3^(lv-1): Lv1=5, Lv2=15, Lv3=45
let cost = baseCost;
if (targetHeroLv > 1) {
cost = baseCost * Math.pow(FightSet.MERGE_NEED, targetHeroLv - 1);
}
CardPoolList.push({
uuid: hero.uuid,
type: CardType.Hero,
cost: cost,
weight: baseWeight,
pool_lv: pLv as CardLV,
kind: CKind.Hero,
hero_lv: targetHeroLv
});
}
});
// 添加非英雄卡牌 (技能、功能卡)
CardPoolList.push(
// 技能卡牌 (以增益/辅助为主,因为在备战期没有敌人)
{ uuid: 6401, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6401"), info: t("skill_info_6401"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6402, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6402"), info: t("skill_info_6402"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6403, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6403"), info: t("skill_info_6403"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6404, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6404"), info: t("skill_info_6404"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6405, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6405"), info: t("skill_info_6405"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6406, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6406"), info: t("skill_info_6406"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6304, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 3, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6304"), info: t("skill_info_6304"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6305, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 3, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6305"), info: t("skill_info_6305"), is_inst: true, t_times: 1, t_inv: 0 },
// { uuid: 7101, type: CardType.SpecialRefresh, cost: 1, weight: 12, pool_lv: 1 ,kind: CKind.Card },
// { uuid: 7102, type: CardType.SpecialRefresh, cost: 1, weight: 12, pool_lv: 1 ,kind: CKind.Card },
// { uuid: 7103, type: CardType.SpecialRefresh, cost: 1, weight: 12, pool_lv: 1 ,kind: CKind.Card },
]
{ uuid: 6401, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6401"), info: t("skill_info_6401"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6402, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6402"), info: t("skill_info_6402"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6403, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6403"), info: t("skill_info_6403"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6404, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6404"), info: t("skill_info_6404"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6405, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6405"), info: t("skill_info_6405"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6406, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6406"), info: t("skill_info_6406"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6304, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 3, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6304"), info: t("skill_info_6304"), is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6305, type: CardType.Skill, cost: 8, weight: 20, pool_lv: 3, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6305"), info: t("skill_info_6305"), is_inst: true, t_times: 1, t_inv: 0 },
);
export enum SpecialRefreshHeroType {
@@ -148,22 +162,22 @@ export interface SpecialRefreshCardConfig extends CardConfig {
export const SpecialUpgradeCardList: Record<number, SpecialUpgradeCardConfig> = {
7001: { uuid: 7001,type: CardType.SpecialUpgrade,cost: 6,weight: 16,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7001"),info:t("scard_info_7001"),
7001: { uuid: 7001,type: CardType.SpecialUpgrade,cost: 10,weight: 16,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7001"),info:t("scard_info_7001"),
currentLv: 1, targetLv: 2,
},
7002: { uuid: 7002,type: CardType.SpecialUpgrade,cost: 6,weight: 14,pool_lv: CardLV.LV2,kind:CKind.Card,name:t("scard_name_7002"),info:t("scard_info_7002"),
7002: { uuid: 7002,type: CardType.SpecialUpgrade,cost: 28,weight: 14,pool_lv: CardLV.LV2,kind:CKind.Card,name:t("scard_name_7002"),info:t("scard_info_7002"),
currentLv: 2, targetLv: 3,
},
}
export const SpecialRefreshCardList: Record<number, SpecialRefreshCardConfig> = {
7101: { uuid: 7101,type: CardType.SpecialRefresh,cost: 4,weight: 14,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7101"),info:t("scard_info_7101"),
7101: { uuid: 7101,type: CardType.SpecialRefresh,cost: 3,weight: 14,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7101"),info:t("scard_info_7101"),
refreshLv: 0, refreshHeroType: SpecialRefreshHeroType.Melee,
},
7102: { uuid: 7102,type: CardType.SpecialRefresh,cost: 4,weight: 14,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7102"),info:t("scard_info_7102"),
7102: { uuid: 7102,type: CardType.SpecialRefresh,cost: 3,weight: 14,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7102"),info:t("scard_info_7102"),
refreshLv: 0, refreshHeroType: SpecialRefreshHeroType.Ranged,
},
7103: { uuid: 7103,type: CardType.SpecialRefresh,cost: 5,weight: 12,pool_lv: CardLV.LV2,kind:CKind.Card,name:t("scard_name_7103"),info:t("scard_info_7103"),
7103: { uuid: 7103,type: CardType.SpecialRefresh,cost: 4,weight: 12,pool_lv: CardLV.LV2,kind:CKind.Card,name:t("scard_name_7103"),info:t("scard_info_7103"),
refreshLv: 3, refreshHeroType: SpecialRefreshHeroType.Any,
},
}

View File

@@ -35,6 +35,7 @@ export enum FightSet {
CSKILL_START_Y=30,
SHIELD_MAX=5,
WAVE_HEAL_RATE=0.5, // 回合结束时所有英雄恢复最大生命值的比例
PUNCTURE_DOWN=50,
}
export const laneIdx = {

View File

@@ -33,7 +33,7 @@ export enum Attrs {
knockback_distance = "knockback_distance", // 击退距离强化
knockback_res = "knockback_res", // 击退抗性
invincible_time = "invincible_time",// 无敌时间
puncture = "puncture", // 穿刺次数
puncture_chance = "puncture_chance", // 穿透概率
wfuny = "wfuny", // 风怒
}

View File

@@ -24,7 +24,8 @@ export enum SkillKind {
Damage = 0,
Heal = 1,
Shield = 2,
Support = 3
Support = 3,
Gold = 4
}
@@ -101,11 +102,7 @@ export enum IType {
export const HeroSkillList = [6001,6001,6001,6001,6001,6001]
// Debuff配置接口
export interface BuffConf {
buff:Attrs;
value:number; // 效果值
}
// (已被废弃,采用平铺字段 buff_type 和 buff_value 代替)
interface IReady {
uuid:number,
@@ -133,6 +130,7 @@ export interface SkillConfig {
act:string, // 角色执行的动画
DTType:DTType, // 伤害类型(单体/范围)
ap:number, // 伤害/治疗技能为攻击百分比,护盾技能为免疫次数
gold?:number, // 获取金币技能的金币值
hit_count:number, // 可命中次数
hitcd:number, // 持续伤害的伤害间隔(秒)
speed:number, // 移动速度
@@ -153,11 +151,37 @@ export interface SkillConfig {
crt?:number, // 额外暴击率
frz?:number, // 额外冰冻概率
bck?:number, // 额外击退概率
buffs:BuffConf[], // 对目标应用的 buff 配置列表
buff_type?:Attrs, // Buff 类型 (单一职责)
call_hero?:number, // 召唤技能召唤英雄id(可选)
info:string, // 技能描述
}
export interface SkillOverrides {
TGroup?: TGroup;
ap?: number;
gold?: number;
hit_count?: number;
hitcd?: number;
crt?: number;
frz?: number;
bck?: number;
buff_type?: Attrs;
}
/**
* 将覆盖参数合并到基础技能配置中
* @param config 基础技能配置
* @param overrides 技能覆盖参数
* @returns 合并后的新技能配置
*/
export function mergeSkillParams(config: SkillConfig, overrides?: SkillOverrides): SkillConfig {
if (!overrides) return config;
return {
...config,
...overrides
};
}
export const SkillUpList = {
1001:{ap:0,hit_count:0,buff_ap:0,buff_hp:0,bck:0,frz:0,crt:0,num:0}
}
@@ -174,153 +198,158 @@ export const SkillSet: Record<number, SkillConfig> = {
6001: {
uuid:6001,name:"普通攻击",sp_name:"atk",icon:"1026",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
DTType:DTType.single,ap:100,hit_count:1,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.Melee,
RType:RType.linear,EType:EType.collision,buffs:[],info:"造成攻击力100%的伤害",
RType:RType.linear,EType:EType.collision,info:"造成攻击力100%的伤害",
},
6002: {
uuid:6002,name:"光箭蓝",sp_name:"atk_c1",icon:"1126",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
DTType:DTType.single,ap:100,hit_count:1,hitcd:0.3,speed:720,with:90,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.bezier,EType:EType.collision,buffs:[],info:"近战普通攻击技能",
RType:RType.bezier,EType:EType.collision,info:"近战普通攻击技能",
},
6003: {
uuid:6003,name:"光箭红",sp_name:"atk_c2",icon:"1126",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
DTType:DTType.single,ap:100,hit_count:1,hitcd:0.3,speed:720,with:90,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.bezier,EType:EType.collision,buffs:[],info:"一定几率暴击",
RType:RType.bezier,EType:EType.collision,info:"一定几率暴击",
},
6004: {
uuid:6004,name:"光箭绿",sp_name:"atk_c3",icon:"1126",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
DTType:DTType.single,ap:100,hit_count:1,hitcd:0.3,speed:720,with:90,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.bezier,EType:EType.collision,buffs:[],info:"一定几率击退目标",
RType:RType.bezier,EType:EType.collision,info:"一定几率击退目标",
},
//怪物战士类型统一使用 6005
6005: {
uuid:6005,name:"光箭深红",sp_name:"atk_c4",icon:"1126",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
DTType:DTType.single,ap:100,hit_count:1,hitcd:0.3,speed:720,with:90,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.bezier,EType:EType.collision,buffs:[],info:"一定几率击退目标",
RType:RType.bezier,EType:EType.collision,info:"一定几率击退目标",
},
6006: {
uuid:6006,name:"光箭灰白",sp_name:"atk_c5",icon:"1126",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
DTType:DTType.single,ap:100,hit_count:1,hitcd:0.3,speed:720,with:90,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.bezier,EType:EType.collision,buffs:[],info:"一定几率击退目标",
RType:RType.bezier,EType:EType.collision,info:"一定几率击退目标",
},
6007: {
uuid:6007,name:"水球",sp_name:"ball_water",icon:"1126",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
DTType:DTType.single,ap:100,hit_count:1,hitcd:0.3,speed:720,with:90,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.bezier,EType:EType.collision,buffs:[],info:"一定几率冰冻目标",
RType:RType.bezier,EType:EType.collision,info:"一定几率冰冻目标",
},
6008: {
uuid:6008,name:"箭矢",sp_name:"arrow",icon:"1135",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
DTType:DTType.single,ap:100,hit_count:1,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.bezier,EType:EType.collision,bezier_start_y:20,bezier_mid_y:140,bezier_arc:1.05,buffs:[],info:"造成攻击力100%的伤害",
RType:RType.bezier,EType:EType.collision,bezier_start_y:20,bezier_mid_y:140,bezier_arc:1.05,info:"造成攻击力100%的伤害",
},
6009: {
uuid:6009,name:"箭矢蓝",sp_name:"arrow_blue",icon:"1135",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
DTType:DTType.single,ap:100,hit_count:1,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.bezier,EType:EType.collision,bezier_start_y:20,bezier_mid_y:140,bezier_arc:1.05,buffs:[],info:"造成攻击力100%的伤害",
RType:RType.bezier,EType:EType.collision,bezier_start_y:20,bezier_mid_y:140,bezier_arc:1.05,info:"造成攻击力100%的伤害",
},
6010: {
uuid:6010,name:"箭矢红",sp_name:"arrow_red",icon:"1135",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
DTType:DTType.single,ap:100,hit_count:1,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.bezier,EType:EType.collision,bezier_start_y:20,bezier_mid_y:140,bezier_arc:1.05,buffs:[],info:"造成攻击力100%的伤害",
RType:RType.bezier,EType:EType.collision,bezier_start_y:20,bezier_mid_y:140,bezier_arc:1.05,info:"造成攻击力100%的伤害",
},
6101: {
uuid:6101,name:"火球",sp_name:"ball_fire",icon:"1126",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
DTType:DTType.single,frz:0,ap:100,hit_count:1,hitcd:0.3,speed:720,with:90,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.linear,EType:EType.collision,buffs:[],info:"造成攻击力100%的伤害,一定几率暴击,高阶技能",
RType:RType.linear,EType:EType.collision,info:"造成攻击力100%的伤害,一定几率暴击,高阶技能",
},
6102: {
uuid:6102,name:"龙卷风",sp_name:"ball_winds",icon:"1126",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
DTType:DTType.single,ap:100,hit_count:1,hitcd:0.3,speed:720,with:90,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.linear,EType:EType.collision,buffs:[],info:"造成攻击力100%的伤害,一定几率击退目标,高阶技能",
RType:RType.linear,EType:EType.collision,info:"造成攻击力100%的伤害,一定几率击退目标,高阶技能",
},
//怪物法师统一使用 暗影球
6103: {
uuid:6103,name:"暗影球",sp_name:"ball_zi",icon:"1126",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
DTType:DTType.single,ap:100,hit_count:1,hitcd:0.3,speed:720,with:90,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.linear,EType:EType.collision,buffs:[],info:"造成攻击力100%的伤害,一定几率上毒(后期加入),高阶技能 ",
RType:RType.linear,EType:EType.collision,info:"造成攻击力100%的伤害,一定几率上毒(后期加入),高阶技能 ",
},
6104: {
uuid:6104,name:"穿云箭",sp_name:"arrow_big_yellow",icon:"1135",TGroup:TGroup.Enemy,readyAnm:"yellow",endAnm:"",act:"max",
DTType:DTType.single,crt:20,ap:100,hit_count:6,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.linear,EType:EType.collision,buffs:[],info:"射出强力箭矢最多穿透6个敌人附带20%额外暴击率",
RType:RType.linear,EType:EType.collision,info:"射出强力箭矢最多穿透6个敌人附带20%额外暴击率",
},
6105: {
uuid:6105,name:"冰刺",sp_name:"ice_up",icon:"1173",TGroup:TGroup.Enemy,readyAnm:"blues",endAnm:"",act:"max",
DTType:DTType.range,frz:0,ap:150,hit_count:6,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.fixedEnd,EType:EType.animationEnd,buffs:[],info:"召唤冰刺攻击一排的敌人,有概率冰冻",
RType:RType.fixedEnd,EType:EType.animationEnd,info:"召唤冰刺攻击一排的敌人,有概率冰冻",
},
6106: {
uuid:6106,name:"冰推",sp_name:"ice_t",icon:"1173",TGroup:TGroup.Enemy,readyAnm:"blues",endAnm:"",act:"max",
DTType:DTType.range,frz:0,ap:150,hit_count:6,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.fixed,EType:EType.animationEnd,buffs:[],info:"召唤冰墙阻挡敌人,有概率冰冻,100%击退",
RType:RType.fixed,EType:EType.animationEnd,info:"召唤冰墙阻挡敌人,有概率冰冻,100%击退",
},
6107: {
uuid:6107,name:"陨石",sp_name:"fire_yuns",icon:"1173",TGroup:TGroup.Enemy,readyAnm:"reds",endAnm:"",act:"max",
DTType:DTType.range,crt:20,ap:150,hit_count:6,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
RType:RType.fixedEnd,EType:EType.animationEnd,buffs:[],info:"召唤攻击敌人造成攻击力150%的范围伤害附带20%额外暴击率",
RType:RType.fixedEnd,EType:EType.animationEnd,info:"召唤攻击敌人造成攻击力150%的范围伤害附带20%额外暴击率",
},
//============================= ====== 辅助技能 ====== ==========================
6301:{
uuid:6301,name:"护盾",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Self,readyAnm:"up_blue",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Shield,ap:3,hit_count:1,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.support,
RType:RType.fixed,EType:EType.animationEnd,buffs:[],info:"为自己添加护盾可抵挡3次伤害",
RType:RType.fixed,EType:EType.animationEnd,info:"为伙伴/自己添加护盾可抵挡3次伤害",
},
6302: {
uuid:6302,name:"群体治疗",sp_name:"buff_wind",icon:"1292",TGroup:TGroup.Team,readyAnm:"up_green",endAnm:"",act:"atk",
uuid:6302,name:"治疗",sp_name:"buff_wind",icon:"1292",TGroup:TGroup.Team,readyAnm:"up_green",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Heal,ap:300,hit_count:1,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.support,
RType:RType.fixed,EType:EType.animationEnd,buffs:[],info:"为全体友方恢复攻击力300%的生命值",
RType:RType.fixed,EType:EType.animationEnd,info:"治疗伙伴/自己",
},
6303:{
uuid:6303,name:"强化护盾",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Self,readyAnm:"up_blue",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Shield,ap:3,hit_count:1,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.support,
RType:RType.fixed,EType:EType.animationEnd,buffs:[],info:"为自己添加强化护盾可抵挡3次伤害",
},
6304: {
uuid:6304,name:"持续恢复",sp_name:"buff_wind",icon:"1292",TGroup:TGroup.Team,readyAnm:"up_green",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Heal,ap:200,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,buffs:[],info:"为全体友方持续恢复共3次每次恢复攻击力200%的生命值",
},
6305:{
uuid:6305,name:"团队护盾",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Team,readyAnm:"up_blue",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Shield,ap:2,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,buffs:[],info:"为全体友方添加护盾每人可抵挡2次伤害持续3次",
6303: {
uuid:6303,name:"获取金币",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Self,readyAnm:"up_blue",endAnm:"gold",act:"atk",
DTType:DTType.single,kind:SkillKind.Gold,ap:0,gold:10,hit_count:1,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.support,
RType:RType.fixed,EType:EType.animationEnd,info:"增加一定数量的金币",
},
//==========================buff 技能=====================
6401:{
uuid:6401,name:"攻击强化",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Team,readyAnm:"up_ap",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Support,ap:0,hit_count:1,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.support,
RType:RType.fixed,EType:EType.animationEnd,buffs:[{buff:Attrs.ap,value:5}],info:"全体友方攻击力提升5点持续1次",
DTType:DTType.single,kind:SkillKind.Support,ap:5,hit_count:1,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,info:"全体友方攻击力提升5点持续1次",
},
6402:{
uuid:6402,name:"生命强化",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Team,readyAnm:"up_hp",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Support,ap:0,hit_count:1,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.support,
RType:RType.fixed,EType:EType.animationEnd,buffs:[{buff:Attrs.hp_max,value:20}],info:"全体友方最大生命值提升20点持续1次",
DTType:DTType.single,kind:SkillKind.Support,ap:20,hit_count:1,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_max,info:"全体友方最大生命值提升20点持续1次",
},
6403:{
uuid:6403,name:"全面强化",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Team,readyAnm:"up_hp",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Support,ap:0,hit_count:1,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.support,
RType:RType.fixed,EType:EType.animationEnd,buffs:[{buff:Attrs.ap,value:5},{buff:Attrs.hp_max,value:20}],info:"全体友方攻击力提升5点最大生命值提升20点持续1次",
uuid:6403,name:"暴击强化",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Team,readyAnm:"up_ap",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Support,ap:1,hit_count:1,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,info:"全体友方暴击率提升10%持续1次",
},
6404:{
uuid:6404,name:"持续攻击强化",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Team,readyAnm:"up_ap",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Support,ap:0,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,buffs:[{buff:Attrs.ap,value:2}],info:"全体友方攻击力提升2,持续3次",
uuid:6404,name:"暴伤强化",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Team,readyAnm:"up_ap",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Support,ap:1,hit_count:1,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_damage,info:"全体友方暴击伤害提升20%,持续1次",
},
6405:{
uuid:6405,name:"持续生命强化",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Team,readyAnm:"up_hp",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Support,ap:0,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,buffs:[{buff:Attrs.hp_max,value:10}],info:"全体友方最大生命值提升10,持续3次",
uuid:6405,name:"冰冻强化",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Team,readyAnm:"up_blue",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Support,ap:1,hit_count:1,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_chance,info:"全体友方冰冻概率提升10%,持续1次",
},
6406:{
uuid:6406,name:"持续全面强化",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Team,readyAnm:"up_ap",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Support,ap:0,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,buffs:[{buff:Attrs.ap,value:2},{buff:Attrs.hp_max,value:10}],info:"全体友方攻击力提升2点最大生命值提升10,持续3次",
uuid:6406,name:"击退强化",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Team,readyAnm:"up_blue",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Support,ap:1,hit_count:1,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,info:"全体友方击退概率提升10%,持续1次",
},
6407:{
uuid:6407,name:"距推强化",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Team,readyAnm:"up_blue",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Support,ap:1,hit_count:1,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_distance,info:"全体友方击退距离提升20点持续1次",
},
6408:{
uuid:6408,name:"穿刺强化",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Team,readyAnm:"up_ap",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Support,ap:20,hit_count:1,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,info:"全体友方穿透概率提升20%持续1次",
},
6409:{
uuid:6409,name:"风怒强化",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Team,readyAnm:"up_ap",endAnm:"",act:"atk",
DTType:DTType.single,kind:SkillKind.Support,ap:1,hit_count:1,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,info:"全体友方风怒次数提升1次持续1次",
},
6501:{
uuid:6501,name:"复活",sp_name:"buff_wind",icon:"1255",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,buffs:[],info:"ap 代表复活的生命值百分比",
RType:RType.fixed,EType:EType.animationEnd,info:"ap 代表复活的生命值百分比",
}
};

View File

@@ -1,5 +1,6 @@
import { v3 } from "cc"
import { BoxSet, FacSet } from "./GameSet"
import { SkillOverrides, TGroup } from "./SkillSet"
export enum HType {
Melee = 0,
@@ -83,100 +84,328 @@ export interface heroInfo {
fac: FacSet; // 阵营FacSet.HERO 或 FacSet.MON
kind?: number; // 未使用
lv: number; // 英雄等级
cards_lv?: number; // 卡片等级
pool_lv?: number; // 卡片等级
type: HType; // 攻击定位(近战/中程/远程)
hp: number; // 生命值上限
ap: number; // 攻击力
call?:number[]; // 召唤后触发的技能uuid列表
dead?:number[]; // 死亡后触发的技能uuid列表
fstart?:number[]; // 战斗开始时释放的技能uuid列表
fend?:number[]; // 战斗结束时释放的技能uuid列表
call?:{s_uuid:number, t_num:number, overrides?: SkillOverrides}[]; // 召唤后触发的技能配置
dead?:{s_uuid:number, t_num:number, overrides?: SkillOverrides}[]; // 死亡后触发的技能配置
fstart?:{s_uuid:number, t_num:number, overrides?: SkillOverrides}[]; // 战斗开始时释放的技能配置
fend?:{s_uuid:number, t_num:number, overrides?: SkillOverrides}[]; // 战斗结束时释放的技能配置
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: 触发所需的受击次数
atking?:{s_uuid:number, t_num:number, overrides?: SkillOverrides}[]; // 普通攻击后触发的技能配置s_uuid: 技能id, t_num: 触发所需的普攻次数
atked?:{s_uuid:number, t_num:number, overrides?: SkillOverrides}[]; // 受击后触发的技能配置s_uuid: 技能id, t_num: 触发所需的受击次数
revive?:{s_uuid:number,r_num:number,upr:number}; // 复活技能配置s_uuid: 技能id, r_num: 触发所需的复活次数, upr 等级对复活次数的影响
dis?: number; // 攻击距离(像素)
dis?: number; // 攻击距离(像素)
speed?: number; // 移动速度(像素/秒)
skills: Record<number, HSkillInfo> ; // 携带技能ID列表
info: string; // 描述文案
}
/**
* 英雄/怪物基础信息接口
* 技能基础信息接口
*/
export interface HSkillInfo {
uuid: number; // 唯一标识(英雄5000段,怪物5200段
uuid: number; // 唯一标识(技能6000段
lv:number; // 技能等级
cd:number; // 技能cd
ccd:number; // 占位当前cd用于cd计时
overrides?: SkillOverrides; // 角色专属参数覆盖
}
/*
*=============英雄配置列表================
* 英雄规则设定
* 战士 专注 受攻击触发技能
* 射手 专注 施法触发技能
* 法师 专注 战斗开始触发技能
* 辅助 专注 战斗结束触发技能
*
*=============英雄配置列表================
* 职业触发规则 (v3)
* 战士 专注 atked(受击) + dead(死亡) 触发 — 承伤坦克定位
* 刺客 专注 atking(攻击) + dead(死亡) 触发 — 高风险高回报近战
* 射手 专注 atking(攻击) + fstart(战前) 触发 — 稳定远程输出
* 法师 专注 atking(攻击) + field(驻场) 触发 — 魔法输出+被动光环
* 辅助 专注 atking(攻击) + revive(复活) 触发 — 战斗支援
*
* 设定中的英雄都是1级,最高可以升级到3级不在列表内提现,升级在游戏内进行)
* skills[0]是普通攻击技能
* skills[1]是等级2时的技能,skills[2]是等级3时的技能
*
* 属性基准(cards_lv:1,lv:1) SPEED:800, AP:30 | HP:300 | skills[0].cd = 1.0 (普通)
* 坦克(cards_lv:1,lv:1) SPEED:800, AP:25 | HP:450 | skills[0].cd = 2.3 或 2.8 (很慢+/很慢) - 突出沉重感与承伤定位
* 近战dps(cards_lv:1,lv:1) SPEED:800, AP:50 | HP:250 | skills[0].cd = 0.3 或 0.5 (极速/快速+) - 强化割草连击爽感
* 远程dps(cards_lv:1,lv:1) SPEED:800, AP:60 | HP:150 | skills[0].cd = 0.7 或 0.9 (快速/普通+) - 稳定持续的物理输出节奏
*远程法dps(cards_lv:1,lv:1) SPEED:800, AP:60 | HP:150 | skills[0].cd = 1.5 或 1.8 (慢+/慢) - 强调施法前摇与单发爆发
* 远程辅助(cards_lv:1,lv:1) SPEED:800, AP:20 | HP:150 | skills[0].cd = 1.1 (普通) - 贴近基准,动作不急不躁,侧重技能
*
* 属性基准(pool_lv:1,lv:1) SPEED:800, AP:30 | HP:300 | skills[0].cd = 1.0 (普通)
* 坦克(pool_lv:1,lv:1) SPEED:800, AP:25 | HP:450 | skills[0].cd = 2.3 或 2.8 (很慢+/很慢) - 突出沉重感与承伤定位
* 近战dps(pool_lv:1,lv:1) SPEED:800, AP:50 | HP:250 | skills[0].cd = 0.3 或 0.5 (极速/快速+) - 强化割草连击爽感
* 远程dps(pool_lv:1,lv:1) SPEED:800, AP:60 | HP:150 | skills[0].cd = 0.7 或 0.9 (快速/普通+) - 稳定持续的物理输出节奏
*远程法dps(pool_lv:1,lv:1) SPEED:800, AP:60 | HP:150 | skills[0].cd = 1.5 或 1.8 (慢+/慢) - 强调施法前摇与单发爆发
* 远程辅助(pool_lv:1,lv:1) SPEED:800, AP:20 | HP:150 | skills[0].cd = 1.1 (普通) - 贴近基准,动作不急不躁,侧重技能
*/
export const HeroInfo: Record<number, heroInfo> = {
// ========== 近战英雄 ==========
5001:{uuid:5001,name:"见习战士",path:"hk2", fac:FacSet.HERO,cards_lv:1,lv:1,type:HType.Melee,hp:150,ap:25,
skills:{6002:{uuid:6002,lv:1,cd:1.5,ccd:0}},atking:[{s_uuid:6301,t_num:2}],info:" "},
5002:{uuid:5002,name:"盾骑士",path:"hk1", fac:FacSet.HERO,cards_lv:3,lv:1,type:HType.Melee,hp:150,ap:75,
skills:{6002:{uuid:6002,lv:1,cd:1.5,ccd:0}},atked:[{s_uuid:6301,t_num:2}],info:" "},
5003:{uuid:5003,name:"战士3",path:"hk3", fac:FacSet.HERO,cards_lv:2,lv:1,type:HType.Melee,hp:100,ap:100,
skills:{6002:{uuid:6002,lv:1,cd:1.5,ccd:0}},info:" "},
5004:{uuid:5004,name:"战士4",path:"hk4", fac:FacSet.HERO,cards_lv:4,lv:1,type:HType.Melee,hp:100,ap:200,
skills:{6002:{uuid:6002,lv:1,cd:0.7,ccd:0}},info:" "},
5005:{uuid:5005,name:"战士5",path:"hk5", fac:FacSet.HERO,cards_lv:4,lv:1,type:HType.Melee,hp:100,ap:200,
skills:{6002:{uuid:6002,lv:1,cd:1.5,ccd:0}},info:" "},
// ========== 铁壁反伤流 (保留原有 5001, 5002) ==========
5001:{uuid:5001,name:"见习战士",path:"hk2", fac:FacSet.HERO,pool_lv:1,lv:1,type:HType.Melee,hp:150,ap:25,
skills:{6002:{uuid:6002,lv:1,cd:1.5,ccd:0}},
atked:[{s_uuid:6301,t_num:2}],
info:" "},
5002:{uuid:5002,name:"盾骑士",path:"hk1", fac:FacSet.HERO,pool_lv:3,lv:1,type:HType.Melee,hp:150,ap:75,
skills:{6002:{uuid:6002,lv:1,cd:1.5,ccd:0}},
atked:[{s_uuid:6301,t_num:2,overrides:{TGroup:TGroup.Team,ap:2,hit_count:3}}],
info:" "},
/*
// 废弃旧英雄
5003:{uuid:5003,name:"战士3",path:"hk3", fac:FacSet.HERO,pool_lv:2,lv:1,type:HType.Melee,hp:100,ap:100,
skills:{6002:{uuid:6002,lv:1,cd:1.5,ccd:0}},
info:" "},
5004:{uuid:5004,name:"战士4",path:"hk4", fac:FacSet.HERO,pool_lv:4,lv:1,type:HType.Melee,hp:100,ap:200,
skills:{6002:{uuid:6002,lv:1,cd:0.7,ccd:0}},
info:" "},
5005:{uuid:5005,name:"战士5",path:"hk5", fac:FacSet.HERO,pool_lv:4,lv:1,type:HType.Melee,hp:100,ap:200,
skills:{6002:{uuid:6002,lv:1,cd:1.5,ccd:0}},
info:" "},
*/
// ========== 法师英雄 ==========
5101:{uuid:5101,name:"奥术法师",path:"hm2", fac:FacSet.HERO,cards_lv:1,lv:1,type:HType.Long,hp:150,ap:60,
skills:{6003:{uuid:6003,lv:1,cd:1,ccd:0}},revive:{s_uuid:6501,r_num:1,upr:0.5},info:""},
5102:{uuid:5102,name:"火焰法师",path:"hm1", fac:FacSet.HERO,cards_lv:2,lv:1,type:HType.Long,hp:130,ap:120,
skills:{6003:{uuid:6003,lv:1,cd:1,ccd:0}},info:""},
5103:{uuid:5103,name:"冰法法师",path:"hm3", fac:FacSet.HERO,cards_lv:3,lv:1,type:HType.Long,hp:145,ap:180,
skills:{6003:{uuid:6003,lv:1,cd:1,ccd:0}},info:""},
5104:{uuid:5104,name:"寒霜术士",path:"hm5", fac:FacSet.HERO,cards_lv:4,lv:1,type:HType.Long,hp:160,ap:240,
skills:{6003:{uuid:6003,lv:1,cd:1,ccd:0}},info:""},
5105:{uuid:5105,name:"炎爆法师",path:"hm4", fac:FacSet.HERO,cards_lv:5,lv:1,type:HType.Long,hp:175,ap:300,
skills:{6003:{uuid:6003,lv:1,cd:1,ccd:0}},info:"" },
// ========== 远程英雄 ==========
5201:{uuid:5201,name:"射手",path:"ha1", fac:FacSet.HERO,cards_lv:1,lv:1,type:HType.Long,hp:115,ap:60,
skills:{6005:{uuid:6005,lv:1,cd:0.9,ccd:0}},info:""},
5202:{uuid:5202,name:"游侠2",path:"ha2", fac:FacSet.HERO,cards_lv:3,lv:1,type:HType.Long,hp:145,ap:180,
skills:{6005:{uuid:6005,lv:1,cd:0.9,ccd:0}},info:""},
5203:{uuid:5203,name:"游侠3",path:"ha3", fac:FacSet.HERO,cards_lv:3,lv:1,type:HType.Long,hp:145,ap:180,
skills:{6005:{uuid:6005,lv:1,cd:0.9,ccd:0}},info:""},
5204:{uuid:5204,name:"游侠4",path:"ha4", fac:FacSet.HERO,cards_lv:3,lv:1,type:HType.Long,hp:145,ap:180,
skills:{6005:{uuid:6005,lv:1,cd:0.9,ccd:0}},info:""},
// ========== 辅助英雄 ==========
5301:{uuid:5301,name:"牧师",path:"hh1", fac:FacSet.HERO,cards_lv:1,lv:1,type:HType.Long,hp:115,ap:50,
skills:{6004:{uuid:6004,lv:1,cd:1.2,ccd:0}},atking:[{s_uuid:6302,t_num:2}],info:"" },
5302:{uuid:5302,name:"医师",path:"hh2", fac:FacSet.HERO,cards_lv:2,lv:1,type:HType.Long,hp:130,ap:50,
skills:{6004:{uuid:6004,lv:1,cd:1.2,ccd:0}}, atking:[{s_uuid:6304,t_num:2}],info:""},
// ========== 攻速叠伤流 ==========
5006:{uuid:5006,name:"疾风刺客",path:"hk3", fac:FacSet.HERO,pool_lv:2,lv:1,type:HType.Melee,
hp:200,ap:35,
skills:{6001:{uuid:6001,lv:1,cd:0.3,ccd:0}},
atking:[{s_uuid:6401,t_num:1,overrides:{TGroup:TGroup.Self,ap:5}}],
dead:[{s_uuid:6401,t_num:1,overrides:{TGroup:TGroup.Team,ap:8}}],
info:"极速攻速近战,每次攻击给自己叠攻击,死亡时把力量传给全队"},
5205:{uuid:5205,name:"暴风射手",path:"ha3", fac:FacSet.HERO,pool_lv:2,lv:1,type:HType.Long,
hp:180,ap:55,
skills:{6002:{uuid:6002,lv:1,cd:0.5,ccd:0}},
atking:[{s_uuid:6403,t_num:2}],
info:"远程快速射击每2次攻击为全队叠加暴击率"},
// ========== 辅助英雄 ==========
5401:{uuid:5401,name:"刺客1",path:"hc1", fac:FacSet.HERO,cards_lv:1,lv:1,type:HType.Long,hp:115,ap:50,
skills:{6006:{uuid:6006,lv:1,cd:1.2,ccd:0}},atking:[{s_uuid:6302,t_num:2}],info:"" },
5402:{uuid:5402,name:"刺客2",path:"hc2", fac:FacSet.HERO,cards_lv:2,lv:1,type:HType.Long,hp:130,ap:50,
skills:{6006:{uuid:6006,lv:1,cd:1.2,ccd:0}},atking:[{s_uuid:6304,t_num:2}],info:""},
5403:{uuid:5403,name:"嗜血剑圣",path:"hc1", fac:FacSet.HERO,pool_lv:3,lv:1,type:HType.Melee,
hp:280,ap:90,
skills:{6001:{uuid:6001,lv:1,cd:0.7,ccd:0}},
atking:[{s_uuid:6401,t_num:1,overrides:{TGroup:TGroup.Self,ap:8}}],
dead:[{s_uuid:6401,t_num:1,overrides:{TGroup:TGroup.Team,ap:10}}],
info:"每次攻击给自己叠攻击,死亡时把力量传给全队"},
// ========== 铁壁反伤流 (新加) ==========
5007:{uuid:5007,name:"盾卫",path:"hk1", fac:FacSet.HERO,pool_lv:1,lv:1,type:HType.Melee,
hp:450,ap:25,
skills:{6001:{uuid:6001,lv:1,cd:2.3,ccd:0}},
atked:[{s_uuid:6301,t_num:2}],
info:"高血量坦克受击2次自动加护盾"},
5008:{uuid:5008,name:"守护骑士",path:"hk2", fac:FacSet.HERO,pool_lv:3,lv:1,type:HType.Melee,
hp:500,ap:20,
skills:{6001:{uuid:6001,lv:1,cd:2.3,ccd:0}},
atked:[{s_uuid:6301,t_num:2,overrides:{TGroup:TGroup.Team,ap:2,hit_count:2}}],
info:"受击时为全队加护盾,越被围殴全队越安全"},
5009:{uuid:5009,name:"不屈战神",path:"hk4", fac:FacSet.HERO,pool_lv:3,lv:1,type:HType.Melee,
hp:600,ap:30,
skills:{6001:{uuid:6001,lv:1,cd:2.8,ccd:0}},
atked:[
{s_uuid:6301,t_num:1,overrides:{TGroup:TGroup.Self,ap:4}},
{s_uuid:6402,t_num:3}
],
dead:[{s_uuid:6402,t_num:1,overrides:{ap:40}}],
info:"血量最厚的前排,受击加盾+全队加血,死亡时给全队巨额生命强化"},
// ========== 法师英雄 (保留 5101) ==========
5101:{uuid:5101,name:"奥术法师",path:"hm2", fac:FacSet.HERO,pool_lv:1,lv:1,type:HType.Long,hp:150,ap:60,
skills:{6003:{uuid:6003,lv:1,cd:1,ccd:0}},
field:[6401],
atking:[{s_uuid:6401,t_num:2,overrides:{ap:3}}],
info:"驻场提供攻击力光环每2次攻击为全队叠加攻击力"},
/*
// 废弃旧英雄
5102:{uuid:5102,name:"火焰法师",path:"hm1", fac:FacSet.HERO,pool_lv:2,lv:1,type:HType.Long,hp:130,ap:120,
skills:{6003:{uuid:6003,lv:1,cd:1,ccd:0}},
info:""},
5103:{uuid:5103,name:"冰法法师",path:"hm3", fac:FacSet.HERO,pool_lv:3,lv:1,type:HType.Long,hp:145,ap:180,
skills:{6003:{uuid:6003,lv:1,cd:1,ccd:0}},
info:""},
5104:{uuid:5104,name:"寒霜术士",path:"hm5", fac:FacSet.HERO,pool_lv:4,lv:1,type:HType.Long,hp:160,ap:240,
skills:{6003:{uuid:6003,lv:1,cd:1,ccd:0}},
info:""},
5105:{uuid:5105,name:"炎爆法师",path:"hm4", fac:FacSet.HERO,pool_lv:5,lv:1,type:HType.Long,hp:175,ap:300,
skills:{6003:{uuid:6003,lv:1,cd:1,ccd:0}},
info:"" },
*/
// ========== 冰冻控制流 (新加) ==========
5106:{uuid:5106,name:"寒冰学徒",path:"hm3", fac:FacSet.HERO,pool_lv:1,lv:1,type:HType.Long,
hp:130,ap:50,
skills:{6007:{uuid:6007,lv:1,cd:1.5,ccd:0}},
field:[6405],
atking:[{s_uuid:6405,t_num:2}],
info:"驻场提供冰冻光环每2次普攻叠加冰冻概率"},
5107:{uuid:5107,name:"霜寒法师",path:"hm5", fac:FacSet.HERO,pool_lv:2,lv:1,type:HType.Long,
hp:160,ap:80,
skills:{6007:{uuid:6007,lv:1,cd:1.0,ccd:0}},
field:[6405],
atking:[{s_uuid:6105,t_num:2,overrides:{ap:120,frz:25}}],
info:"驻场冰冻光环每2次攻击触发冰刺AOE25%冰冻概率冻住一排敌人"},
5108:{uuid:5108,name:"永冬贤者",path:"hm4", fac:FacSet.HERO,pool_lv:3,lv:1,type:HType.Long,
hp:250,ap:110,
skills:{6007:{uuid:6007,lv:1,cd:1.8,ccd:0}},
field:[6405],
atking:[{s_uuid:6105,t_num:1,overrides:{ap:150,frz:35,hit_count:8}}],
info:"驻场强力冰冻光环每次攻击释放冰刺35%冰冻概率"},
/*
// ========== 远程英雄 (旧) ==========
5201:{uuid:5201,name:"射手",path:"ha1", fac:FacSet.HERO,pool_lv:1,lv:1,type:HType.Long,hp:115,ap:60,
skills:{6005:{uuid:6005,lv:1,cd:0.9,ccd:0}},
info:""},
5202:{uuid:5202,name:"游侠2",path:"ha2", fac:FacSet.HERO,pool_lv:3,lv:1,type:HType.Long,hp:145,ap:180,
skills:{6005:{uuid:6005,lv:1,cd:0.9,ccd:0}},
info:""},
5203:{uuid:5203,name:"游侠3",path:"ha3", fac:FacSet.HERO,pool_lv:3,lv:1,type:HType.Long,hp:145,ap:180,
skills:{6005:{uuid:6005,lv:1,cd:0.9,ccd:0}},
info:""},
5204:{uuid:5204,name:"游侠4",path:"ha4", fac:FacSet.HERO,pool_lv:3,lv:1,type:HType.Long,hp:145,ap:180,
skills:{6005:{uuid:6005,lv:1,cd:0.9,ccd:0}},
info:""},
*/
// ========== 辅助英雄 (保留 5301, 5302) ==========
5301:{uuid:5301,name:"牧师",path:"hh1", fac:FacSet.HERO,pool_lv:1,lv:1,type:HType.Long,hp:115,ap:50,
skills:{6004:{uuid:6004,lv:1,cd:1.2,ccd:0}},
atking:[{s_uuid:6302,t_num:2}],
info:"" },
5302:{uuid:5302,name:"医师",path:"hh2", fac:FacSet.HERO,pool_lv:2,lv:1,type:HType.Long,hp:130,ap:50,
skills:{6004:{uuid:6004,lv:1,cd:1.2,ccd:0}},
atking:[{s_uuid:6302,t_num:2,overrides:{hit_count:3,ap:200}}],
info:""},
// ========== 治疗续航流 (新加) ==========
5303:{uuid:5303,name:"见习牧师",path:"hh1", fac:FacSet.HERO,pool_lv:1,lv:1,type:HType.Long,
hp:120,ap:40,
skills:{6004:{uuid:6004,lv:1,cd:1.1,ccd:0}},
atking:[{s_uuid:6302,t_num:2}],
info:"每2次普攻后治疗全队恢复攻击力300%的生命值"},
5304:{uuid:5304,name:"神圣医师",path:"hh2", fac:FacSet.HERO,pool_lv:2,lv:1,type:HType.Long,
hp:150,ap:50,
skills:{6004:{uuid:6004,lv:1,cd:0.9,ccd:0}},
atking:[{s_uuid:6302,t_num:2,overrides:{hit_count:3,ap:200}}],
revive:{s_uuid:6501,r_num:1,upr:0.3},
info:"持续治疗每2次普攻触发3次群体治疗死后可复活一次继续治疗"},
5305:{uuid:5305,name:"生命贤者",path:"hh3", fac:FacSet.HERO,pool_lv:3,lv:1,type:HType.Long,
hp:200,ap:70,
skills:{6004:{uuid:6004,lv:1,cd:1.0,ccd:0}},
atking:[{s_uuid:6302,t_num:1,overrides:{ap:250}}],
revive:{s_uuid:6501,r_num:1,upr:0.5},
info:"每次普攻后全队治疗250%攻击力,死后复活一次继续治疗"},
/*
// ========== 刺客英雄 (旧) ==========
5401:{uuid:5401,name:"刺客1",path:"hc1", fac:FacSet.HERO,pool_lv:1,lv:1,type:HType.Long,hp:115,ap:50,
skills:{6006:{uuid:6006,lv:1,cd:1.2,ccd:0}},
atking:[{s_uuid:6302,t_num:2}],
info:"" },
5402:{uuid:5402,name:"刺客2",path:"hc2", fac:FacSet.HERO,pool_lv:2,lv:1,type:HType.Long,hp:130,ap:50,
skills:{6006:{uuid:6006,lv:1,cd:1.2,ccd:0}},
atking:[{s_uuid:6304,t_num:2}],
info:""},
*/
// ========== 击退推拉流 ==========
5209:{uuid:5209,name:"风弓手",path:"ha2", fac:FacSet.HERO,pool_lv:1,lv:1,type:HType.Long,
hp:140,ap:45,
skills:{6005:{uuid:6005,lv:1,cd:0.7,ccd:0}},
atking:[{s_uuid:6406,t_num:2}],
info:"快速射击每2次攻击为全队叠加击退概率"},
5210:{uuid:5210,name:"龙卷猎手",path:"ha3", fac:FacSet.HERO,pool_lv:2,lv:1,type:HType.Long,
hp:170,ap:70,
skills:{6005:{uuid:6005,lv:1,cd:0.9,ccd:0}},
atking:[{s_uuid:6102,t_num:2,overrides:{bck:30,hit_count:3}}],
info:"每2次攻击释放龙卷风30%击退概率推开一排敌人"},
5404:{uuid:5404,name:"风暴刺客",path:"hc2", fac:FacSet.HERO,pool_lv:4,lv:1,type:HType.Melee,
hp:250,ap:100,
skills:{6001:{uuid:6001,lv:1,cd:0.5,ccd:0}},
atking:[
{s_uuid:6407,t_num:1},
{s_uuid:6102,t_num:3,overrides:{bck:50,hit_count:5,ap:120}}
],
dead:[{s_uuid:6406,t_num:1}],
info:"极速近战每次攻击给全队加击退距离每3次攻击释放龙卷风死后全队永久击退率加成"},
// ========== 暴击爆发流 ==========
5211:{uuid:5211,name:"猎鹰射手",path:"ha4", fac:FacSet.HERO,pool_lv:1,lv:1,type:HType.Long,
hp:130,ap:55,
skills:{6002:{uuid:6002,lv:1,cd:0.9,ccd:0}},
atking:[{s_uuid:6403,t_num:2}],
info:"稳定输出每2次攻击为全队叠加暴击率"},
5212:{uuid:5212,name:"穿心弩手",path:"ha1", fac:FacSet.HERO,pool_lv:3,lv:1,type:HType.Long,
hp:160,ap:80,
skills:{6003:{uuid:6003,lv:1,cd:1.0,ccd:0}},
fstart:[{s_uuid:6403,t_num:1}],
atking:[{s_uuid:6404,t_num:2}],
info:"开局全队暴击强化,战斗中持续叠加暴击伤害"},
5405:{uuid:5405,name:"死线执行者",path:"hc1", fac:FacSet.HERO,pool_lv:5,lv:1,type:HType.Melee,
hp:220,ap:120,
skills:{6001:{uuid:6001,lv:1,cd:1.5,ccd:0}},
atking:[{s_uuid:6104,t_num:1,overrides:{ap:150,crt:35}}],
dead:[
{s_uuid:6403,t_num:1,overrides:{ap:3}},
{s_uuid:6404,t_num:1,overrides:{ap:3}}
],
info:"每次攻击释放穿云箭穿透6个目标35%暴击率死亡时给全队3层暴击+3层暴伤"},
// ========== 经济滚雪球流 ==========
5109:{uuid:5109,name:"点金学徒",path:"hm2", fac:FacSet.HERO,pool_lv:1,lv:1,type:HType.Long,
hp:120,ap:35,
skills:{6007:{uuid:6007,lv:1,cd:1.0,ccd:0}},
field:[6401],
atking:[{s_uuid:6303,t_num:3,overrides:{gold:8}}],
info:"驻场提供攻击力光环每3次普攻额外获得8金币"},
5306:{uuid:5306,name:"商贾",path:"hh3", fac:FacSet.HERO,pool_lv:2,lv:1,type:HType.Long,
hp:150,ap:30,
skills:{6004:{uuid:6004,lv:1,cd:1.1,ccd:0}},
atking:[{s_uuid:6303,t_num:2,overrides:{gold:12}}],
revive:{s_uuid:6501,r_num:1,upr:0.3},
info:"战斗中持续产金币,死了也能复活继续赚钱"},
5213:{uuid:5213,name:"丰收猎手",path:"ha2", fac:FacSet.HERO,pool_lv:4,lv:1,type:HType.Long,
hp:180,ap:65,
skills:{6002:{uuid:6002,lv:1,cd:0.8,ccd:0}},
fstart:[{s_uuid:6401,t_num:1,overrides:{ap:8}}],
atking:[
{s_uuid:6303,t_num:2,overrides:{gold:10}},
{s_uuid:6401,t_num:1,overrides:{ap:3}}
],
info:"开战前全队加攻,边打边赚金币,每次攻击给全队加攻击力"},
// ========== 献祭亡语流 ==========
5010:{uuid:5010,name:"烈焰殉道者",path:"hk5", fac:FacSet.HERO,pool_lv:1,lv:1,type:HType.Melee,
hp:250,ap:30,
skills:{6001:{uuid:6001,lv:1,cd:1.5,ccd:0}},
dead:[{s_uuid:6401,t_num:1,overrides:{ap:15}}],
info:"死亡时为全队永久增加15点攻击力"},
5110:{uuid:5110,name:"亡语刺客",path:"hc2", fac:FacSet.HERO,pool_lv:3,lv:1,type:HType.Melee,
hp:280,ap:70,
skills:{6001:{uuid:6001,lv:1,cd:1.0,ccd:0}},
atking:[{s_uuid:6405,t_num:2,overrides:{ap:1}}],
dead:[
{s_uuid:6401,t_num:1,overrides:{ap:10}},
{s_uuid:6405,t_num:1,overrides:{ap:2}},
{s_uuid:6301,t_num:1,overrides:{TGroup:TGroup.Team,ap:2,hit_count:2}}
],
info:"活着时叠冰冻率,死亡时三重亡语:全队+10攻击+2层冰冻率+2层护盾"},
5111:{uuid:5111,name:"血影绝杀",path:"hc1", fac:FacSet.HERO,pool_lv:5,lv:1,type:HType.Melee,
hp:300,ap:100,
skills:{6001:{uuid:6001,lv:1,cd:1.2,ccd:0}},
atking:[{s_uuid:6404,t_num:1,overrides:{TGroup:TGroup.Self,ap:2}}],
dead:[
{s_uuid:6401,t_num:1,overrides:{ap:20}},
{s_uuid:6404,t_num:1,overrides:{ap:2}},
{s_uuid:6402,t_num:1,overrides:{ap:30}}
],
info:"活着时每次攻击给自己叠暴伤,死后全队+20攻+2层暴伤+30血"},
@@ -191,47 +420,61 @@ export const HeroInfo: Record<number, heroInfo> = {
*/
// 基础怪物
6001:{uuid:6001,name:"兽人初阶战士",path:"m1", fac:FacSet.MON,cards_lv:1,lv:1,type:HType.Melee,dis:360,hp:360,ap:12,speed:100,
skills:{6005:{uuid:6005,lv:1,cd:0.65,ccd:0}},info:""},
6002:{uuid:6002,name:"兽人高阶战士",path:"m2", fac:FacSet.MON,cards_lv:1,lv:1,type:HType.Melee,dis:360,hp:360,ap:12,speed:100,
skills:{6005:{uuid:6005,lv:1,cd:0.65,ccd:0}},info:""},
6003:{uuid:6003,name:"兽人初阶射手",path:"m3", fac:FacSet.MON,cards_lv:1,lv:1,type:HType.Melee,dis:360,hp:1050,ap:30,speed:100,
skills:{6008:{uuid:6008,lv:1,cd:2,ccd:0}},info:""},
6004:{uuid:6004,name:"兽人高阶射手",path:"m4", fac:FacSet.MON,cards_lv:1,lv:1,type:HType.Long,hp:720,ap:45,speed:100,
skills:{6008:{uuid:6008,lv:1,cd:1.5,ccd:0}},info:""},
6005:{uuid:6005,name:"兽人刺客",path:"m5", fac:FacSet.MON,cards_lv:1,lv:1,type:HType.Long,hp:720,ap:20,speed:100,
skills:{6103:{uuid:6103,lv:1,cd:1.5,ccd:0}},info:""},
6006:{uuid:6006,name:"骷髅高阶战士",path:"m6", fac:FacSet.MON,cards_lv:1,lv:1,type:HType.Melee,dis:360,hp:4500,ap:20,speed:100,
skills:{6005:{uuid:6005,lv:1,cd:2,ccd:0}},info:""},
6007:{uuid:6007,name:"兽人蓝色法师",path:"m7", fac:FacSet.MON,cards_lv:1,lv:1,type:HType.Melee,dis:360,hp:4500,ap:20,speed:100,
skills:{6103:{uuid:6103,lv:1,cd:2,ccd:0}},info:""},
6008:{uuid:6008,name:"兽人红色法师",path:"m8", fac:FacSet.MON,cards_lv:1,lv:1,type:HType.Melee,dis:360,hp:4500,ap:20,speed:100,
skills:{6103:{uuid:6103,lv:1,cd:2,ccd:0}},info:""},
// 基础怪物 (全部远程攻击HType仅决定站位)
// 近战位怪物 (站在前排,承受更多伤害) — v4: 数量×2 强度×0.6 爽感设计
6001:{uuid:6001,name:"兽人战士",path:"m1", fac:FacSet.MON,lv:1,type:HType.Melee,dis:360,hp:220,ap:10,speed:100,
skills:{6005:{uuid:6005,lv:1,cd:0.65,ccd:0}},info:"基础近战位怪"},
6002:{uuid:6002,name:"兽人精锐战士",path:"m2", fac:FacSet.MON,lv:1,type:HType.Melee,dis:360,hp:300,ap:14,speed:110,
skills:{6005:{uuid:6005,lv:1,cd:0.55,ccd:0}},info:"进阶近战位怪,更快更痛"},
6003:{uuid:6003,name:"兽人重装兵",path:"m3", fac:FacSet.MON,lv:1,type:HType.Melee,dis:360,hp:850,ap:20,speed:80,
skills:{6008:{uuid:6008,lv:1,cd:1.8,ccd:0}},info:"重型坦克怪高HP慢攻"},
// 远程位怪物 (站在后排,输出更高)
6004:{uuid:6004,name:"兽人射手",path:"m4", fac:FacSet.MON,lv:1,type:HType.Long,hp:190,ap:35,speed:100,
skills:{6008:{uuid:6008,lv:1,cd:1.2,ccd:0}},info:"远程高DPS怪"},
6005:{uuid:6005,name:"兽人刺客",path:"m5", fac:FacSet.MON,lv:1,type:HType.Long,hp:210,ap:38,speed:130,
skills:{6103:{uuid:6103,lv:1,cd:0.8,ccd:0}},info:"高AP快速攻击刺客"},
// 特殊位怪物
6006:{uuid:6006,name:"骷髅领主",path:"m6", fac:FacSet.MON,lv:1,type:HType.Melee,dis:360,hp:5000,ap:20,speed:90,
skills:{6005:{uuid:6005,lv:1,cd:1.5,ccd:0}},info:"MiniBoss级坦克"},
6007:{uuid:6007,name:"兽人术士",path:"m7", fac:FacSet.MON,lv:1,type:HType.Melee,dis:360,hp:300,ap:24,speed:100,
skills:{6103:{uuid:6103,lv:1,cd:1.2,ccd:0}},info:"法师怪,远程魔法攻击"},
6008:{uuid:6008,name:"兽人火法",path:"m8", fac:FacSet.MON,lv:1,type:HType.Melee,dis:360,hp:270,ap:32,speed:100,
skills:{6103:{uuid:6103,lv:1,cd:1.0,ccd:0}},info:"高输出法师怪"},
// BOSS怪物
6101:{uuid:6101,name:"兽人首领-双刀战士-蓝边",path:"mb1", fac:FacSet.MON,cards_lv:1,lv:6,type:HType.Long,hp:720,ap:30,speed:100,
skills:{6103:{uuid:6103,lv:1,cd:2,ccd:0},6206:{uuid:6206,lv:1,cd:10,ccd:0}},info:""},
6102:{uuid:6102,name:"兽人首领-斧头战士-绿边",path:"mb2", fac:FacSet.MON,cards_lv:1,lv:6,type:HType.Melee,dis:360,hp:4500,ap:20,speed:100,
skills:{6005:{uuid:6005,lv:1,cd:2,ccd:0},},info:""},
6103:{uuid:6103,name:"兽人首领-魔法师-紫边",path:"mb3", fac:FacSet.MON,cards_lv:1,lv:6,type:HType.Long,hp:720,ap:30,speed:100,
skills:{6103:{uuid:6103,lv:1,cd:2,ccd:0},6206:{uuid:6206,lv:1,cd:10,ccd:0}},info:""},
6104:{uuid:6104,name:"兽人首领-射手-黄边",path:"mb4", fac:FacSet.MON,cards_lv:1,lv:6,type:HType.Melee,dis:360,hp:4500,ap:20,speed:100,
skills:{6005:{uuid:6005,lv:1,cd:2,ccd:0},},info:""},
6105:{uuid:6105,name:"亡灵首领-法师-红边",path:"mb5", fac:FacSet.MON,cards_lv:1,lv:6,type:HType.Long,hp:720,ap:30,speed:100,
skills:{6103:{uuid:6103,lv:1,cd:2,ccd:0},6206:{uuid:6206,lv:1,cd:10,ccd:0}},info:""},
6106:{uuid:6106,name:"亡灵首领-骑马战士-红边",path:"mb6", fac:FacSet.MON,cards_lv:1,lv:6,type:HType.Melee,dis:360,hp:4500,ap:20,speed:100,
skills:{6005:{uuid:6005,lv:1,cd:2,ccd:0},},info:""},
// BOSS怪物 — Boss强度降低~25%,靠护卫小怪制造场面压力
6101:{uuid:6101,name:"兽人首领-双刀战士",path:"mb1", fac:FacSet.MON,lv:6,type:HType.Long,hp:1900,ap:30,speed:120,
skills:{6103:{uuid:6103,lv:1,cd:0.8,ccd:0},6206:{uuid:6206,lv:1,cd:10,ccd:0}},info:"远程Boss高攻速"},
6102:{uuid:6102,name:"兽人首领-斧头战士",path:"mb2", fac:FacSet.MON,lv:6,type:HType.Melee,dis:360,hp:7500,ap:26,speed:90,
skills:{6005:{uuid:6005,lv:1,cd:1.2,ccd:0}},info:"近战Boss超高HP"},
6103:{uuid:6103,name:"兽人首领-魔法师",path:"mb3", fac:FacSet.MON,lv:6,type:HType.Long,hp:2250,ap:38,speed:110,
skills:{6103:{uuid:6103,lv:1,cd:0.7,ccd:0},6206:{uuid:6206,lv:1,cd:8,ccd:0}},info:"远程法系Boss高AP"},
6104:{uuid:6104,name:"兽人首领-射手",path:"mb4", fac:FacSet.MON,lv:6,type:HType.Melee,dis:360,hp:6800,ap:30,speed:100,
skills:{6005:{uuid:6005,lv:1,cd:1.0,ccd:0}},info:"近战位Boss均衡型"},
6105:{uuid:6105,name:"亡灵首领-法师",path:"mb5", fac:FacSet.MON,lv:6,type:HType.Long,hp:2600,ap:42,speed:110,
skills:{6103:{uuid:6103,lv:1,cd:0.7,ccd:0},6206:{uuid:6206,lv:1,cd:8,ccd:0}},info:"远程高AP Boss"},
6106:{uuid:6106,name:"亡灵首领-骑马战士",path:"mb6", fac:FacSet.MON,lv:6,type:HType.Melee,dis:360,hp:9000,ap:26,speed:130,
skills:{6005:{uuid:6005,lv:1,cd:1.0,ccd:0}},info:"终极Boss最高HP+高速"},
};
export const HeroList: number[] = [
5001, 5002, 5003, 5004, 5005,
5101, 5102, 5103, 5104, 5105,
5201, 5202,5203,5204,
5301, 5302,
5401, 5402,
// 铁壁反伤流
5001, 5002, 5007, 5008, 5009,
// 攻速叠伤流
5006, 5205, 5403,
// 冰冻控制流
5101, 5106, 5107, 5108,
// 治疗续航流
5301, 5302, 5303, 5304, 5305,
// 击退推拉流
5209, 5210, 5404,
// 暴击爆发流
5211, 5212, 5405,
// 经济滚雪球流
5109, 5306, 5213,
// 献祭亡语流
5010, 5110, 5111,
];

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,12 @@
{
"ver": "1.0.0",
"importer": "*",
"imported": true,
"uuid": "19f625a6-5615-4db8-8e96-03e227bbf253",
"files": [
".json",
".xlsx"
],
"subMetas": {},
"userData": {}
}

View File

@@ -3,9 +3,10 @@ import { HeroDisVal, HeroInfo, HSkillInfo, HType } from "../common/config/heroSe
import { mLogger } from "../common/Logger";
import { Timer } from "db://oops-framework/core/common/timer/Timer";
import { FacSet, FightSet } from "../common/config/GameSet";
import { FieldSkillSet, FieldSkillType } from "../common/config/SkillSet";
import { FieldSkillSet, FieldSkillType, SkillOverrides } from "../common/config/SkillSet";
import { smc } from "../common/SingletonModuleComp";
import { TalentConfig, TalentType } from "../common/config/TalentSet";
import { Attrs } from "../common/config/HeroAttrs";
import { FieldSkillHelper } from "./FieldSkillHelper";
@ecs.register('HeroAttrs')
export class HeroAttrsComp extends ecs.Comp {
@@ -33,12 +34,12 @@ export class HeroAttrsComp extends ecs.Comp {
skills: Record<number, HSkillInfo> = {};
// ==================== 触发类技能 ====================
call?: number[];
dead?: number[];
fstart?: number[];
fend?: number[];
atking?: {s_uuid: number, t_num: number}[];
atked?: {s_uuid: number, t_num: number}[];
call?: { s_uuid: number; t_num: number; overrides?: SkillOverrides }[];
dead?: { s_uuid: number; t_num: number; overrides?: SkillOverrides }[];
fstart?: { s_uuid: number; t_num: number; overrides?: SkillOverrides }[];
fend?: { s_uuid: number; t_num: number; overrides?: SkillOverrides }[];
atking?: { s_uuid: number; t_num: number; overrides?: SkillOverrides }[];
atked?: { s_uuid: number; t_num: number; overrides?: SkillOverrides }[];
revive?: {s_uuid: number, r_num: number, upr: number};
// ==================== 特殊属性 ====================
@@ -50,7 +51,7 @@ export class HeroAttrsComp extends ecs.Comp {
knockback_distance: number = 0; // 击退距离强化
knockback_res: number = 0; // 击退抗性
crit_damage: number = 0; // 额外暴击伤害
puncture: number = 0; // 穿刺次数
puncture_chance: number = 0; // 穿透概率
wfuny: number = 0; // 风怒
revived_count: number = 0; // 已复活次数
@@ -135,6 +136,25 @@ export class HeroAttrsComp extends ecs.Comp {
return value
}
/**
* 统一的特殊/固定属性数值增加方法
* @param attr_type 属性类型枚举
* @param value 增加的数值
*/
add_special_attr(attr_type: Attrs, value: number) {
// 利用枚举值(字符串)与类属性名一致的特性,动态访问并累加属性
const key = attr_type as keyof this;
// 确保目标属性存在且类型为数字,避免运行时错误
if (typeof this[key] === 'number') {
(this as any)[key] += value;
} else {
if (this.debugMode) {
mLogger.log(this.debugMode, 'HeroAttrs', `未找到对应数字属性或无法累加: attr_type=${attr_type}, value=${value}`);
}
}
}
toFrost(time: number=1) {
const frostTime = FightSet.FROST_TIME * time;
@@ -223,6 +243,11 @@ export class HeroAttrsComp extends ecs.Comp {
return this.freeze_chance + this.getFieldPercentValue(FieldSkillType.HeroFrost);
}
/** 英雄实时穿透概率 = 基础穿透概率。 */
public getRuntimePunctureChance(): number {
return this.puncture_chance;
}
/** 英雄实时暴击伤害 = 基础额外暴伤 + 驻场暴伤。 */
public getRuntimeCritDamageBonus(): number {
if (this.fac !== FacSet.HERO) return this.crit_damage;
@@ -310,7 +335,7 @@ export class HeroAttrsComp extends ecs.Comp {
this.crit_damage = 0;
this.revived_count = 0;
this.invincible_time = 0;
this.puncture = 0;
this.puncture_chance = 0;
this.wfuny = 0;
this.boom = false;

View File

@@ -2,7 +2,7 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec
import { Vec3, Prefab, instantiate, tween, Node } from "cc";
import { HeroAttrsComp } from "./HeroAttrsComp";
import { HeroViewComp } from "./HeroViewComp";
import { DTType, RType, SkillConfig, SkillKind, SkillSet, SkillUpList, TGroup } from "../common/config/SkillSet";
import { DTType, RType, SkillConfig, SkillKind, SkillSet, SkillUpList, TGroup, SkillOverrides, mergeSkillParams } from "../common/config/SkillSet";
import { Skill } from "../skill/Skill";
import { smc } from "../common/SingletonModuleComp";
import { HeroDisVal, HeroInfo, HType } from "../common/config/heroSet";
@@ -11,6 +11,7 @@ import { BoxSet, FacSet, FightSet } from "../common/config/GameSet";
import { oops } from "db://oops-framework/core/Oops";
import { GameEvent, SkillTriggerType } from "../common/config/GameEvent";
import { SkillTriggerHelper } from "./SkillTriggerHelper";
import { MissionEconomy } from "../map/MissionEconomy";
/**
* ==================== 自动施法系统 ====================
@@ -48,7 +49,8 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
triggerType?: string,
isCardSkill?: boolean,
card_lv?: number,
targetPos?: Vec3
targetPos?: Vec3,
overrides?: any
}) {
if (!args || !args.s_uuid) return;
@@ -60,7 +62,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
// 常规英雄技能触发
if (!args.heroAttrs || !args.heroView) return;
this.forceCastTriggerSkill(args.s_uuid, args.heroAttrs, args.heroView, args.triggerType);
this.forceCastTriggerSkill(args.s_uuid, args.heroAttrs, args.heroView, args.triggerType, args.overrides);
}
/**
@@ -106,7 +108,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
mockAttrs.ap = highestAp;
mockAttrs.critical = 0;
mockAttrs.freeze_chance = 0;
mockAttrs.puncture = 0;
mockAttrs.puncture_chance = 0;
mockAttrs.fac = FacSet.HERO;
for (let i = 0; i < castTimes; i++) {
@@ -140,7 +142,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
skill.load(actualStartPos, parent, s_uuid, targetPos.clone(), mockView, mockAttrs, skillLv, 0);
}
/** 空施法计划:用于“当前无可施法技能”时的统一返回 */
private readonly emptyCastPlan = { skillId: 0, skillLv: 1, isFriendly: false, targetPos: null as Vec3 | null, targetEids: [] as number[] };
private readonly emptyCastPlan = { skillId: 0, skillLv: 1, isFriendly: false, targetPos: null as Vec3 | null, targetEids: [] as number[], overrides: undefined as SkillOverrides | undefined };
/** 查询缓存:避免每帧重复创建 matcher */
private heroMatcher: ecs.IMatcher | null = null;
@@ -188,7 +190,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
* 强制执行触发技能(召唤/死亡触发)
* 忽略CD、状态、动画前摇直接生效
*/
public forceCastTriggerSkill(s_uuid: number, heroAttrs: HeroAttrsComp, heroView: HeroViewComp, triggerType?: string) {
public forceCastTriggerSkill(s_uuid: number, heroAttrs: HeroAttrsComp, heroView: HeroViewComp, triggerType?: string, overrides?: SkillOverrides) {
// 播放相应的触发动画
if (triggerType === 'call') {
heroView.playReady("yellow");
@@ -199,8 +201,9 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
}
// 如果是敌方攻击技能,必须在战斗中才能释放;友方增益/护盾则允许在非战斗中释放
const config = SkillSet[s_uuid];
let config = SkillSet[s_uuid];
if (!config) return;
config = mergeSkillParams(config, overrides);
const isEnemyTarget = !this.isSelfSkill(config.TGroup) && !this.isFriendlySkill(config.TGroup);
if (isEnemyTarget && !smc.mission.in_fight) return;
@@ -245,7 +248,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
this.applyFriendlySkillEffects(s_uuid, skillLv, config, heroView, heroAttrs, friendlyTargets, null);
} else {
const enemyTargetPos = this.resolveRepeatCastTargetPos(targetPos, i);
this.applyEnemySkillEffects(s_uuid, skillLv, config, heroView, heroAttrs, enemyTargetPos, i);
this.applyEnemySkillEffects(s_uuid, skillLv, config, heroView, heroAttrs, enemyTargetPos, i, overrides);
}
}
}
@@ -255,7 +258,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
* 选择顺序:技能候选列表顺序 + 条件过滤CD、目标可达、目标类型匹配
* 返回内容同时包含“对敌施法”和“友方施法”两种执行所需数据。
*/
private pickCastSkill(heroAttrs: HeroAttrsComp, heroView: HeroViewComp): { skillId: number; skillLv: number; isFriendly: boolean; targetPos: Vec3 | null; targetEids: number[] } {
private pickCastSkill(heroAttrs: HeroAttrsComp, heroView: HeroViewComp): { skillId: number; skillLv: number; isFriendly: boolean; targetPos: Vec3 | null; targetEids: number[]; overrides?: SkillOverrides } {
const type = heroAttrs.type as HType;
const maxRange = this.resolveMaxCastRange(heroAttrs, type);
const target = this.findNearestEnemyInRange(heroAttrs, heroView, maxRange);
@@ -263,24 +266,26 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
const selfEid = heroView.ent?.eid;
for (const s_uuid of skillCandidates) {
if (!s_uuid) continue;
const config = SkillSet[s_uuid];
let config = SkillSet[s_uuid];
if (!config) continue;
if (!heroAttrs.isSkillReady(s_uuid)) continue;
const skillLv = heroAttrs.getSkillLevel(s_uuid);
const overrides = heroAttrs.skills[s_uuid]?.overrides;
config = mergeSkillParams(config, overrides);
if (this.isSelfSkill(config.TGroup)) {
if (typeof selfEid !== "number") continue;
return { skillId: s_uuid, skillLv, isFriendly: true, targetPos: null, targetEids: [selfEid] };
return { skillId: s_uuid, skillLv, isFriendly: true, targetPos: null, targetEids: [selfEid], overrides };
}
if (this.isFriendlySkill(config.TGroup)) {
const includeSelf = config.TGroup === TGroup.Ally;
const friendlyEids = this.collectFriendlyTargetEids(heroAttrs.fac, selfEid, includeSelf);
if (friendlyEids.length === 0) continue;
return { skillId: s_uuid, skillLv, isFriendly: true, targetPos: null, targetEids: friendlyEids };
return { skillId: s_uuid, skillLv, isFriendly: true, targetPos: null, targetEids: friendlyEids, overrides };
}
if (!target || !heroView.node || !target.node) continue;
const targetPos = this.resolveEnemyCastTargetPos(config, heroAttrs, heroView, target, maxRange);
if (!targetPos) continue;
return { skillId: s_uuid, skillLv, isFriendly: false, targetPos, targetEids: [] };
return { skillId: s_uuid, skillLv, isFriendly: false, targetPos, targetEids: [], overrides };
}
return this.emptyCastPlan;
}
@@ -291,14 +296,18 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
* - 延迟到出手时机后,按技能目标类型分发到对敌/友方效果处理
* - 触发技能CD
*/
private castSkill(castPlan: { skillId: number; skillLv: number; isFriendly: boolean; targetPos: Vec3 | null; targetEids: number[] }, heroAttrs: HeroAttrsComp, heroView: HeroViewComp) {
private castSkill(castPlan: { skillId: number; skillLv: number; isFriendly: boolean; targetPos: Vec3 | null; targetEids: number[]; overrides?: SkillOverrides }, heroAttrs: HeroAttrsComp, heroView: HeroViewComp) {
if (!smc.mission.in_fight) return;
const s_uuid = castPlan.skillId;
const skillLv = castPlan.skillLv;
const config = SkillSet[s_uuid];
const overrides = castPlan.overrides;
let config = SkillSet[s_uuid];
const sUp = SkillUpList[s_uuid] ? SkillUpList[s_uuid]:SkillUpList[1001];
const cNum = Math.min(2, Math.max(0, Math.floor(sUp.num ?? 0)));
if (!config) return;
config = mergeSkillParams(config, overrides);
//播放前摇技能动画
heroView.playReady(config.readyAnm);
//播放角色攻击动画
@@ -331,7 +340,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
continue;
}
const enemyTargetPos = this.resolveRepeatCastTargetPos(castPlan.targetPos, i);
this.applyEnemySkillEffects(s_uuid, skillLv, config, heroView, heroAttrs, enemyTargetPos, i);
this.applyEnemySkillEffects(s_uuid, skillLv, config, heroView, heroAttrs, enemyTargetPos, i, overrides);
}
}, delay);
heroAttrs.triggerSkillCD(s_uuid);
@@ -360,24 +369,24 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
* 创建技能实体(投射物/范围体等)。
* 仅用于对敌伤害技能的实体化表现与碰撞伤害分发。
*/
private createSkillEntity(s_uuid: number, skillLv: number, caster: HeroViewComp,cAttrsComp: HeroAttrsComp, targetPos: Vec3, castIndex: number = 0) {
private createSkillEntity(s_uuid: number, skillLv: number, caster: HeroViewComp,cAttrsComp: HeroAttrsComp, targetPos: Vec3, castIndex: number = 0, overrides?: SkillOverrides) {
if (!caster.node || !caster.node.isValid) return;
const parent = caster.node.parent;
if (!parent) return;
const skill = ecs.getEntity<Skill>(Skill);
const startPos = this.resolveRepeatCastStartPos(caster.node.position, castIndex);
skill.load(startPos, parent, s_uuid, targetPos.clone(), caster, cAttrsComp, skillLv, 0);
skill.load(startPos, parent, s_uuid, targetPos.clone(), caster, cAttrsComp, skillLv, 0, overrides);
}
/**
* 对敌技能效果处理。
* 当前职责:仅处理伤害技能并创建技能实体。
*/
private applyEnemySkillEffects(s_uuid: number, skillLv: number, config: SkillConfig, heroView: HeroViewComp, cAttrsComp: HeroAttrsComp, targetPos: Vec3 | null, castIndex: number = 0) {
private applyEnemySkillEffects(s_uuid: number, skillLv: number, config: SkillConfig, heroView: HeroViewComp, cAttrsComp: HeroAttrsComp, targetPos: Vec3 | null, castIndex: number = 0, overrides?: SkillOverrides) {
const kind = config.kind ?? SkillKind.Damage;
if (kind !== SkillKind.Damage) return;
if (config.ap <= 0 || !targetPos) return;
this.createSkillEntity(s_uuid, skillLv, heroView, cAttrsComp, targetPos, castIndex);
this.createSkillEntity(s_uuid, skillLv, heroView, cAttrsComp, targetPos, castIndex, overrides);
}
private resolveRepeatCastStartPos(startPos: Readonly<Vec3>, castIndex: number): Vec3 {
@@ -403,16 +412,21 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
: this.pickRandomFriendlyTargets(targets, sHit);
for (const target of applyTargets) {
this.applyActualFriendlyEffect(target, kind, sAp, _cAttrsComp, config, sUp);
this.applyActualFriendlyEffect(target, kind, sAp, _cAttrsComp, config, sUp, _skillLv);
}
}
private applyActualFriendlyEffect(target: HeroViewComp, kind: SkillKind, sAp: number, _cAttrsComp: HeroAttrsComp, config: SkillConfig, sUp: any) {
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;
if (config.endAnm && config.endAnm !== "") {
target.playEnd(config.endAnm);
}
if (kind === SkillKind.Heal && sAp !== 0) {
const addHp = Math.floor(sAp*_cAttrsComp.ap/100);
model.add_hp(addHp);
@@ -424,19 +438,37 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
} else if (kind === SkillKind.Shield && sAp !== 0) {
const addShield = Math.max(0, Math.floor(sAp));
model.add_shield(addShield);
} else if (kind === SkillKind.Gold) {
const baseGold = config.gold ?? config.ap;
const addGold = baseGold + (sUp.ap * _skillLv);
if (addGold > 0) {
MissionEconomy.addCoin(addGold);
}
}
if (!config.buffs || config.buffs.length === 0) return;
for (const buffConf of config.buffs) {
if (!buffConf) continue;
const sBuffAp=buffConf.value+sUp.buff_ap
const sBuffHp=buffConf.value+sUp.buff_hp
switch (buffConf.buff){
if (config.buff_type !== undefined) {
const baseValue = config.ap;
let upgradeValue = 0;
// 根据 buff 类型选择对应的升级加成
if (config.buff_type === Attrs.ap) upgradeValue = sUp.buff_ap || 0;
else if (config.buff_type === Attrs.hp_max) upgradeValue = sUp.buff_hp || 0;
else if (config.buff_type === Attrs.critical) upgradeValue = sUp.crt || 0;
// 如果后续有冰冻等,在这里加上对应的 sUp 字段即可,如 sUp.frz
const totalBuffValue = baseValue + upgradeValue;
switch (config.buff_type){
case Attrs.ap:
model.add_ap(sBuffAp)
break
model.add_ap(totalBuffValue);
break;
case Attrs.hp_max:
model.add_hp_max(sBuffHp)
break
model.add_hp_max(totalBuffValue);
break;
default:
// 除了 hp_max 和 ap其他固定属性走统一的 add_special_attr 方法
model.add_special_attr(config.buff_type, totalBuffValue);
break;
}
}
}
@@ -512,7 +544,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
}
/** 判定施法计划是否具备有效目标 */
private hasCastTarget(castPlan: { skillId: number; skillLv: number; isFriendly: boolean; targetPos: Vec3 | null; targetEids: number[] }): boolean {
private hasCastTarget(castPlan: { skillId: number; skillLv: number; isFriendly: boolean; targetPos: Vec3 | null; targetEids: number[]; overrides?: SkillOverrides }): boolean {
if (castPlan.skillId === 0) return false;
if (castPlan.isFriendly) return castPlan.targetEids.length > 0;
return !!castPlan.targetPos;

View File

@@ -3,7 +3,7 @@ import { GameEvent, SkillTriggerType } from "../common/config/GameEvent";
import { HeroAttrsComp } from "./HeroAttrsComp";
import { HeroViewComp } from "./HeroViewComp";
import { FacSet } from "../common/config/GameSet";
import { FieldSkillType } from "../common/config/SkillSet";
import { FieldSkillType, SkillOverrides } from "../common/config/SkillSet";
import { TalentType } from "../common/config/TalentSet";
import { smc } from "../common/SingletonModuleComp";
import { FieldSkillHelper } from "./FieldSkillHelper";
@@ -105,7 +105,7 @@ export class SkillTriggerHelper {
model.atking.forEach(atkConfig => {
// atk_count 代表已进行的普攻次数。当其余数刚好整除配置阈值时触发。
if (model.atk_count > 0 && model.atk_count % atkConfig.t_num === 0) {
this.dispatchSingle(atkConfig.s_uuid, model, view, SkillTriggerType.Atking);
this.dispatchSingle(atkConfig.s_uuid, model, view, SkillTriggerType.Atking, atkConfig.overrides);
}
});
}
@@ -119,7 +119,7 @@ export class SkillTriggerHelper {
model.atked.forEach(atkConfig => {
// atked_count 代表已承受的受击次数。当其余数刚好整除配置阈值时触发。
if (model.atked_count > 0 && model.atked_count % atkConfig.t_num === 0) {
this.dispatchSingle(atkConfig.s_uuid, model, view, SkillTriggerType.Atked);
this.dispatchSingle(atkConfig.s_uuid, model, view, SkillTriggerType.Atked, atkConfig.overrides);
}
});
}
@@ -127,28 +127,29 @@ export class SkillTriggerHelper {
/**
* 通用的数组型触发器处理(适用于 FStart / FEnd 等无需额外判定的简单列表触发)
*/
private static handleArrayTrigger(uuids: number[] | undefined, model: HeroAttrsComp, view: HeroViewComp, type: SkillTriggerType) {
if (!uuids || uuids.length === 0) return;
this.dispatchArray(uuids, model, view, type);
private static handleArrayTrigger(configs: {s_uuid: number, t_num: number, overrides?: SkillOverrides}[] | undefined, model: HeroAttrsComp, view: HeroViewComp, type: SkillTriggerType) {
if (!configs || configs.length === 0) return;
this.dispatchArray(configs, model, view, type);
}
/**
* 批量派发技能事件
*/
private static dispatchArray(uuids: number[], model: HeroAttrsComp, view: HeroViewComp, type: SkillTriggerType) {
uuids.forEach(uuid => this.dispatchSingle(uuid, model, view, type));
private static dispatchArray(configs: {s_uuid: number, t_num?: number, overrides?: SkillOverrides}[], model: HeroAttrsComp, view: HeroViewComp, type: SkillTriggerType) {
configs.forEach(config => this.dispatchSingle(config.s_uuid, model, view, type, config.overrides));
}
/**
* 单一技能事件派发底层接口
* 事件发出后,将由 SCastSystem 的 forceCastTriggerSkill 监听拦截并执行无视CD的强制施法
*/
private static dispatchSingle(s_uuid: number, model: HeroAttrsComp, view: HeroViewComp, type: SkillTriggerType) {
private static dispatchSingle(s_uuid: number, model: HeroAttrsComp, view: HeroViewComp, type: SkillTriggerType, overrides?: SkillOverrides) {
oops.message.dispatchEvent(GameEvent.TriggerSkill, {
s_uuid: s_uuid,
heroAttrs: model,
heroView: view,
triggerType: type
triggerType: type,
overrides: overrides
});
}
}

View File

@@ -304,17 +304,19 @@ export class HInfoComp extends CCComp {
*/
private onSellHero(event?: Event) {
if (!this.eid) return;
const heroLv = Math.max(1, Math.floor(this.model?.lv ?? 1));
const removed = Hero.removeByEid(this.eid);
mLogger.log(this.debugMode, "HInfoComp", "onSellHero", {
eid: this.eid,
heroLv,
isAlive: this.isModelAlive(),
removed
});
if (!removed) return;
// 使用统一经济管理入口出售英雄
MissionEconomy.executeSellHero();
// 使用统一经济管理入口出售英雄(按等级计算卖价)
MissionEconomy.executeSellHero(heroLv);
oops.gui.remove(UIID.IBox);
}

View File

@@ -230,7 +230,7 @@ export class HListComp extends CCComp {
if (infoLabel) infoLabel.string = `${hero.info || ""}`;
}
const cardLvStr = `lv${hero.cards_lv ?? 1}`;
const cardLvStr = `lv${hero.pool_lv ?? 1}`;
if (this.lv_node) {
this.lv_node.active = true;
this.lv_node.children.forEach(child => {

View File

@@ -74,7 +74,7 @@ export class MissionCardComp extends CCComp {
/** 按钮弹起缩放(峰值) */
private readonly buttonClickScale: number = 1.06;
/** 抽卡(刷新)费用 */
refreshCost: number = 1;
refreshCost: number = 2;
/** 卡牌面板展开/收起动画时长(秒) */
cardsPanelMoveDuration: number = 0.2;

View File

@@ -84,13 +84,13 @@ export class MissionComp extends CCComp {
// ======================== 配置参数 ========================
/** 怪物数量上限(超过后暂停刷怪) */
private maxMonsterCount: number = 50;
private maxMonsterCount: number = 80;
/** 怪物数量恢复阈值(降至此值以下恢复刷怪) */
private resumeMonsterCount: number = 30;
/** 新一波金币奖励基础值(现已固定,不再随波次增长) */
private prepareBaseCoinReward: number = 25;
/** 每一波金币增长值(固定收益设为0 */
private prepareCoinWaveGrow: number = 0;
private resumeMonsterCount: number = 45;
/** 新一波金币奖励基础值 */
private prepareBaseCoinReward: number = 10;
/** 每一波金币增长值(公式: base + (wave-1) * growth */
private prepareCoinWaveGrow: number = 4;
/** 金币奖励上限(固定收益,此值不再生效) */
private prepareCoinRewardCap: number = 100;
/** 卡池升级波次配置:达到对应波次时,推送卡池升级事件 */
@@ -788,12 +788,13 @@ export class MissionComp extends CCComp {
private grantPrepareCoinByWave(wave: number) {
if (wave <= 1) return;
if (wave <= this.lastPrepareCoinWave) return;
// 使用统一经济管理入口发放每波金币
const reward = MissionEconomy.executeWaveGold(this.prepareBaseCoinReward);
// 波次金币公式: baseReward + (wave-1) * waveGrow
const waveReward = this.prepareBaseCoinReward + (wave - 1) * this.prepareCoinWaveGrow;
const reward = MissionEconomy.executeWaveGold(waveReward);
this.lastPrepareCoinWave = wave;
mLogger.log(this.debugMode, "MissionComp", "grantPrepareCoinByWave", { wave, reward, coin: smc.vmdata.mission_data.coin });
mLogger.log(this.debugMode, "MissionComp", "grantPrepareCoinByWave", { wave, waveReward, reward, coin: smc.vmdata.mission_data.coin });
}
// ======================== 怪物数量管理 ========================

View File

@@ -66,11 +66,12 @@ export class MissionEconomy {
return success;
}
/**
* 计算英雄出售金币
/**
* 计算英雄出售金币(按英雄等级缩放)
*/
static getSellGold(): number {
const baseSellGold = 1; // 基础卖出金币
static getSellGold(heroLevel: number = 1): number {
const sellByLevel: Record<number, number> = { 1: 3, 2: 10, 3: 25 };
const baseSellGold = sellByLevel[heroLevel] || 3;
const goldBoost = FieldSkillHelper.getFieldSkillTotalValue(FieldSkillType.SellGold);
let totalSellGold = baseSellGold + goldBoost;
// 应用天赋 SellBonus (增加数值)
@@ -81,11 +82,11 @@ export class MissionEconomy {
return Math.floor(totalSellGold);
}
/**
* 执行出售英雄并增加金币
/**
* 执行出售英雄并增加金币
*/
static executeSellHero(): number {
const gold = this.getSellGold();
static executeSellHero(heroLevel: number = 1): number {
const gold = this.getSellGold(heroLevel);
this.addCoin(gold);
return gold;
}

View File

@@ -183,13 +183,13 @@ export const TemplateModifier: Record<TemplateType, number> = {
*/
export const MonList: Record<number, number[]> = {
[MonType.Melee]: [6001, 6002],
[MonType.Heavy]: [6003, 6103],
[MonType.Long]: [6004, 6102],
[MonType.Support]: [6005],
[MonType.Summoner]: [6203],
[MonType.Assassin]: [6204],
[MonType.MeleeBoss]: [6006, 6105],
[MonType.LongBoss]: [6104],
[MonType.Heavy]: [6003],
[MonType.Long]: [6004],
[MonType.Support]: [6007],
[MonType.Summoner]: [6008],
[MonType.Assassin]: [6005],
[MonType.MeleeBoss]: [6006, 6102, 6104, 6106],
[MonType.LongBoss]: [6101, 6103, 6105],
}
// ======================== 怪物基础属性 & 成本 ========================
@@ -215,14 +215,14 @@ export interface MonsterBaseStats {
* @see MonsterBaseStats 字段说明
*/
export const MonsterStats: Record<MonType, MonsterBaseStats> = {
[MonType.Melee]: { hp: 360, ap: 12, cost: 30, isBoss: false },
[MonType.Heavy]: { hp: 1050, ap: 30, cost: 50, isBoss: false },
[MonType.Long]: { hp: 240, ap: 45, cost: 40, isBoss: false },
[MonType.Support]: { hp: 240, ap: 20, cost: 50, isBoss: false },
[MonType.Summoner]: { hp: 300, ap: 15, cost: 60, isBoss: false },
[MonType.Assassin]: { hp: 270, ap: 55, cost: 45, isBoss: false },
[MonType.MeleeBoss]: { hp: 4500, ap: 20, cost: 200, isBoss: true },
[MonType.LongBoss]: { hp: 1050, ap: 30, cost: 200, isBoss: true },
[MonType.Melee]: { hp: 220, ap: 10, cost: 18, isBoss: false },
[MonType.Heavy]: { hp: 850, ap: 20, cost: 35, isBoss: false },
[MonType.Long]: { hp: 190, ap: 35, cost: 25, isBoss: false },
[MonType.Support]: { hp: 300, ap: 24, cost: 28, isBoss: false },
[MonType.Summoner]: { hp: 270, ap: 32, cost: 35, isBoss: false },
[MonType.Assassin]: { hp: 210, ap: 38, cost: 25, isBoss: false },
[MonType.MeleeBoss]: { hp: 7000, ap: 26, cost: 130, isBoss: true },
[MonType.LongBoss]: { hp: 2100, ap: 38, cost: 130, isBoss: true },
}
// ======================== 阶梯Tier配置 ========================
@@ -252,11 +252,11 @@ const MAJOR_BOSS_TIERS = new Set([3, 5])
* 主线 15 波映射wave 1-3 → T1, wave 4-6 → T2, ..., wave 13-15 → T5
*/
export const TierConfigs: Record<number, TierConfig> = {
1: { multiplier: 1.0, budget: 500, availableTypes: [MonType.Melee, MonType.Heavy, MonType.Long], isBossTier: false },
2: { multiplier: 1.6, budget: 1000, availableTypes: [MonType.Melee, MonType.Heavy, MonType.Long, MonType.Support], isBossTier: true },
3: { multiplier: 2.5, budget: 1800, availableTypes: [MonType.Melee, MonType.Heavy, MonType.Long, MonType.Support, MonType.Assassin], isBossTier: true },
4: { multiplier: 3.8, budget: 3000, availableTypes: [MonType.Melee, MonType.Heavy, MonType.Long, MonType.Support, MonType.Assassin, MonType.Summoner], isBossTier: true },
5: { multiplier: 5.5, budget: 5000, availableTypes: [MonType.Melee, MonType.Heavy, MonType.Long, MonType.Support, MonType.Assassin, MonType.Summoner], isBossTier: true },
1: { multiplier: 1.0, budget: 350, availableTypes: [MonType.Melee, MonType.Heavy, MonType.Long], isBossTier: false },
2: { multiplier: 2.0, budget: 1000, availableTypes: [MonType.Melee, MonType.Heavy, MonType.Long, MonType.Support], isBossTier: true },
3: { multiplier: 3.5, budget: 2300, availableTypes: [MonType.Melee, MonType.Heavy, MonType.Long, MonType.Support, MonType.Assassin], isBossTier: true },
4: { multiplier: 5.5, budget: 4000, availableTypes: [MonType.Melee, MonType.Heavy, MonType.Long, MonType.Support, MonType.Assassin, MonType.Summoner], isBossTier: true },
5: { multiplier: 8.5, budget: 6500, availableTypes: [MonType.Melee, MonType.Heavy, MonType.Long, MonType.Support, MonType.Assassin, MonType.Summoner], isBossTier: true },
}
/**
@@ -361,100 +361,107 @@ export interface BlueprintTemplate {
* 生成引擎根据当前 Tier 和波内位置从中筛选并随机抽取
*/
export const BlueprintTemplates: BlueprintTemplate[] = [
// ---- REST 类 ----
// ---- REST 类 (恢复波:少量怪,让玩家喘口气) ----
{ id: "R1", type: TemplateType.REST, tierMin: 1, allowAffix: false,
slots: [{ typePool: [MonType.Melee], countMin: 5, countMax: 10, weight: 1.0 }] },
{ id: "R2", type: TemplateType.REST, tierMin: 1, allowAffix: false,
slots: [{ typePool: [MonType.Melee, MonType.Heavy], countMin: 5, countMax: 15, weight: 1.0 }] },
slots: [{ typePool: [MonType.Melee], countMin: 4, countMax: 7, weight: 1.0 }] },
{ id: "R2", type: TemplateType.REST, tierMin: 2, allowAffix: false,
slots: [{ typePool: [MonType.Melee, MonType.Heavy], countMin: 6, countMax: 10, weight: 1.0 }] },
{ id: "R3", type: TemplateType.REST, tierMin: 3, allowAffix: false,
slots: [{ typePool: [MonType.Melee, MonType.Long], countMin: 10, countMax: 15, weight: 1.0 }] },
slots: [{ typePool: [MonType.Melee, MonType.Long], countMin: 8, countMax: 14, weight: 1.0 }] },
// ---- NORMAL 类 ----
// N1/N2: T1专用(1-5英雄)
{ id: "N1", type: TemplateType.NORMAL, tierMin: 1, allowAffix: false,
slots: [{ typePool: [MonType.Melee], countMin: 10, countMax: 20, weight: 1.0 }] },
slots: [{ typePool: [MonType.Melee], countMin: 4, countMax: 7, weight: 1.0 }] },
{ id: "N2", type: TemplateType.NORMAL, tierMin: 1, allowAffix: false,
slots: [
{ typePool: [MonType.Melee], countMin: 5, countMax: 15, weight: 0.6 },
{ typePool: [MonType.Long, MonType.Heavy], countMin: 5, countMax: 10, weight: 0.4 },
{ typePool: [MonType.Melee], countMin: 3, countMax: 6, weight: 0.6 },
{ typePool: [MonType.Long], countMin: 2, countMax: 4, weight: 0.4 },
] },
// N3+: T2起(5-6英雄),正常数量
{ id: "N3", type: TemplateType.NORMAL, tierMin: 2, allowAffix: true,
slots: [
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 10, countMax: 15, weight: 0.5 },
{ typePool: [MonType.Long], countMin: 5, countMax: 10, weight: 0.3 },
{ typePool: [MonType.Support], countMin: 5, countMax: 5, weight: 0.2 },
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 6, countMax: 12, weight: 0.5 },
{ typePool: [MonType.Long], countMin: 4, countMax: 8, weight: 0.3 },
{ typePool: [MonType.Support], countMin: 2, countMax: 5, weight: 0.2 },
] },
{ id: "N4", type: TemplateType.NORMAL, tierMin: 3, allowAffix: true,
slots: [
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 10, countMax: 20, weight: 0.4 },
{ typePool: [MonType.Long, MonType.Assassin], countMin: 5, countMax: 15, weight: 0.3 },
{ typePool: [MonType.Support], countMin: 5, countMax: 10, weight: 0.3 },
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 8, countMax: 14, weight: 0.4 },
{ typePool: [MonType.Long, MonType.Assassin], countMin: 5, countMax: 10, weight: 0.3 },
{ typePool: [MonType.Support], countMin: 3, countMax: 6, weight: 0.3 },
] },
// ---- MIXED 类 ----
// M1: T1专用(波3,5英雄)
{ id: "M1", type: TemplateType.MIXED, tierMin: 1, allowAffix: true,
slots: [
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 10, countMax: 15, weight: 0.4 },
{ typePool: [MonType.Long], countMin: 5, countMax: 10, weight: 0.3 },
{ typePool: [MonType.Support], countMin: 5, countMax: 5, weight: 0.3 },
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 4, countMax: 7, weight: 0.4 },
{ typePool: [MonType.Long], countMin: 3, countMax: 5, weight: 0.3 },
{ typePool: [MonType.Support], countMin: 1, countMax: 3, weight: 0.3 },
] },
// M2+: T3起(6英雄)
{ id: "M2", type: TemplateType.MIXED, tierMin: 3, allowAffix: true,
slots: [
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 10, countMax: 20, weight: 0.3 },
{ typePool: [MonType.Long, MonType.Assassin], countMin: 10, countMax: 15, weight: 0.3 },
{ typePool: [MonType.Support], countMin: 5, countMax: 5, weight: 0.4 },
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 8, countMax: 14, weight: 0.3 },
{ typePool: [MonType.Long, MonType.Assassin], countMin: 6, countMax: 10, weight: 0.3 },
{ typePool: [MonType.Support], countMin: 4, countMax: 7, weight: 0.4 },
] },
{ id: "M3", type: TemplateType.MIXED, tierMin: 4, allowAffix: true,
slots: [
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 15, countMax: 20, weight: 0.3 },
{ typePool: [MonType.Long, MonType.Assassin], countMin: 10, countMax: 15, weight: 0.3 },
{ typePool: [MonType.Summoner], countMin: 5, countMax: 10, weight: 0.2 },
{ typePool: [MonType.Support], countMin: 5, countMax: 10, weight: 0.2 },
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 10, countMax: 16, weight: 0.3 },
{ typePool: [MonType.Long, MonType.Assassin], countMin: 6, countMax: 12, weight: 0.3 },
{ typePool: [MonType.Summoner], countMin: 3, countMax: 5, weight: 0.2 },
{ typePool: [MonType.Support], countMin: 3, countMax: 6, weight: 0.2 },
] },
// ---- ELITE 类 ----
// ---- ELITE 类 (精英波:少但强,考验单兵质量) ----
{ id: "E1", type: TemplateType.ELITE, tierMin: 3, allowAffix: true,
slots: [
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 5, countMax: 10, weight: 0.5, forceAffix: true },
{ typePool: [MonType.Long, MonType.Assassin], countMin: 5, countMax: 10, weight: 0.5, forceAffix: true },
{ typePool: [MonType.Heavy], countMin: 4, countMax: 7, weight: 0.5, forceAffix: true },
{ typePool: [MonType.Long, MonType.Assassin], countMin: 4, countMax: 8, weight: 0.5, forceAffix: true },
] },
{ id: "E2", type: TemplateType.ELITE, tierMin: 4, allowAffix: true,
slots: [
{ typePool: [MonType.Heavy], countMin: 5, countMax: 10, weight: 0.3, forceAffix: true },
{ typePool: [MonType.Assassin], countMin: 5, countMax: 10, weight: 0.4, forceAffix: true },
{ typePool: [MonType.Support], countMin: 5, countMax: 10, weight: 0.3, forceAffix: true },
{ typePool: [MonType.Heavy], countMin: 4, countMax: 7, weight: 0.3, forceAffix: true },
{ typePool: [MonType.Assassin], countMin: 5, countMax: 8, weight: 0.4, forceAffix: true },
{ typePool: [MonType.Support], countMin: 3, countMax: 5, weight: 0.3, forceAffix: true },
] },
// ---- BOSS 类 ----
{ id: "B1", type: TemplateType.BOSS, tierMin: 1, allowAffix: true,
// ---- BOSS 类 (Boss波1个Boss + 大量护卫小怪,制造清杂兵爽感) ----
{ id: "B1", type: TemplateType.BOSS, tierMin: 2, allowAffix: true,
slots: [
{ typePool: [MonType.MeleeBoss], countMin: 1, countMax: 1, weight: 1.0 },
{ typePool: [MonType.Melee], countMin: 10, countMax: 15, weight: 0.6 },
{ typePool: [MonType.Long], countMin: 0, countMax: 10, weight: 0.4 },
{ typePool: [MonType.Melee], countMin: 6, countMax: 10, weight: 0.5 },
{ typePool: [MonType.Long], countMin: 4, countMax: 7, weight: 0.3 },
{ typePool: [MonType.Support], countMin: 2, countMax: 3, weight: 0.2 },
] },
{ id: "B2", type: TemplateType.BOSS, tierMin: 2, allowAffix: true,
slots: [
{ typePool: [MonType.MeleeBoss], countMin: 1, countMax: 1, weight: 1.0 },
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 10, countMax: 15, weight: 0.5 },
{ typePool: [MonType.Long, MonType.Support], countMin: 5, countMax: 10, weight: 0.5 },
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 8, countMax: 12, weight: 0.5 },
{ typePool: [MonType.Long, MonType.Support], countMin: 5, countMax: 8, weight: 0.3 },
{ typePool: [MonType.Assassin], countMin: 2, countMax: 4, weight: 0.2 },
] },
{ id: "B3", type: TemplateType.BOSS, tierMin: 3, allowAffix: true,
slots: [
{ typePool: [MonType.MeleeBoss, MonType.LongBoss], countMin: 1, countMax: 1, weight: 1.0 },
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 10, countMax: 20, weight: 0.4 },
{ typePool: [MonType.Long, MonType.Assassin], countMin: 5, countMax: 15, weight: 0.3 },
{ typePool: [MonType.Support], countMin: 5, countMax: 10, weight: 0.3 },
{ typePool: [MonType.Melee, MonType.Heavy], countMin: 8, countMax: 14, weight: 0.35 },
{ typePool: [MonType.Long, MonType.Assassin], countMin: 5, countMax: 10, weight: 0.35 },
{ typePool: [MonType.Support], countMin: 3, countMax: 6, weight: 0.3 },
] },
{ id: "B4", type: TemplateType.BOSS, tierMin: 4, allowAffix: true,
slots: [
{ typePool: [MonType.MeleeBoss, MonType.LongBoss], countMin: 1, countMax: 1, weight: 1.0 },
{ typePool: [MonType.Heavy], countMin: 10, countMax: 15, weight: 0.4 },
{ typePool: [MonType.Assassin], countMin: 5, countMax: 10, weight: 0.3 },
{ typePool: [MonType.Summoner, MonType.Support], countMin: 5, countMax: 10, weight: 0.3 },
{ typePool: [MonType.Heavy], countMin: 6, countMax: 12, weight: 0.35 },
{ typePool: [MonType.Assassin], countMin: 5, countMax: 8, weight: 0.3 },
{ typePool: [MonType.Summoner, MonType.Support], countMin: 4, countMax: 8, weight: 0.2 },
{ typePool: [MonType.Melee], countMin: 5, countMax: 10, weight: 0.15 },
] },
// ---- 教程专用 ----
// ---- 教程专用 (波1: 1个英雄3只弱怪热身) ----
{ id: "TUTORIAL", type: TemplateType.NORMAL, tierMin: 1, allowAffix: false,
slots: [{ typePool: [MonType.Melee], countMin: 2, countMax: 2, weight: 1.0 }] },
slots: [{ typePool: [MonType.Melee], countMin: 3, countMax: 3, weight: 1.0 }] },
]
// ======================== 自适应难度配置 ========================
@@ -471,14 +478,14 @@ export const BlueprintTemplates: BlueprintTemplate[] = [
* @property antiDriftDelta - 反漂移时的反向微调量
*/
export const AdaptiveConfig = {
factorMin: 0.85,
factorMax: 1.15,
deltaPerWave: 0.03,
targetClearTime: 15.0,
factorMin: 0.75,
factorMax: 1.30,
deltaPerWave: 0.04,
targetClearTime: 12.0,
strongThreshold: 0.8,
weakThreshold: 0.3,
maxConsecutiveDirection: 5,
antiDriftDelta: 0.01,
weakThreshold: 0.4,
maxConsecutiveDirection: 4,
antiDriftDelta: 0.015,
}
// ======================== 无限模式配置 ========================
@@ -866,13 +873,15 @@ export class RogueSpawningEngine {
}
}
// 预算利用率检查 (目标 >= 70%)
// 预算利用率检查 (目标 >= 70%但填充上限为模板数量的50%)
let totalCost = budget - remainingBudget
if (budget > 0 && totalCost / budget < 0.7 && template.id !== "TUTORIAL") {
const tierConfig = getTierConfig(tier)
const type = MonType.Melee
const stats = MonsterStats[type]
while (remainingBudget >= stats.cost) {
const maxFill = Math.max(5, Math.ceil(monsters.length * 0.8))
let fillCount = 0
while (remainingBudget >= stats.cost && fillCount < maxFill) {
const finalHp = Math.max(1, Math.round(stats.hp * tierConfig.multiplier * this.adaptiveFactor))
const finalAp = Math.max(1, Math.round(stats.ap * tierConfig.multiplier * this.adaptiveFactor))
const uuids = MonList[type]
@@ -884,6 +893,7 @@ export class RogueSpawningEngine {
spawnIndex++
remainingBudget -= stats.cost
totalCost += stats.cost
fillCount++
}
}

View File

@@ -1,6 +1,6 @@
import { BoxCollider2D, instantiate, Node, Prefab, v3, Vec3, NodePool } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { EType, SkillSet, SkillUpList } from "../common/config/SkillSet";
import { EType, SkillSet, SkillUpList, SkillOverrides, mergeSkillParams } from "../common/config/SkillSet";
import { oops } from "db://oops-framework/core/Oops";
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
import { Attrs } from "../common/config/HeroAttrs";
@@ -101,12 +101,13 @@ export class Skill extends ecs.Entity {
this.addComponents<SMoveDataComp>(SMoveDataComp);
}
load(startPos: Vec3, parent: Node, s_uuid: number, targetPos: Vec3,
caster:HeroViewComp,cAttrsComp:HeroAttrsComp, skill_lv:number=0, ext_dmg:number=0) {
const config = SkillSet[s_uuid];
caster:HeroViewComp,cAttrsComp:HeroAttrsComp, skill_lv:number=0, ext_dmg:number=0, overrides?: SkillOverrides) {
let config = SkillSet[s_uuid];
if (!config) {
mLogger.error(this.debugMode, 'Skill', "[Skill] 技能配置不存在:", s_uuid);
return;
}
config = mergeSkillParams(config, overrides);
// 加载预制体
const path = `game/skill/atk/${config.sp_name}`;
@@ -211,13 +212,14 @@ export class Skill extends ecs.Entity {
const sCrt = (config.crt ?? 0)+(SUp.crt*skill_lv);
const sFrz = (config.frz ?? 0)+(SUp.frz*skill_lv);
const sAp =config.ap+(SUp.ap*skill_lv);
const sHit=config.hit_count+(SUp.hit_count*skill_lv) + cAttrsComp.puncture
const sHit=config.hit_count+(SUp.hit_count*skill_lv);
sDataCom.Attrs[Attrs.ap] = Math.floor(cAttrsComp.ap*sAp/100); //技能的ap是百分值 需要/100 而且需要再最终计算总ap时再/100不然会出现ap为90%变0
sDataCom.Attrs[Attrs.critical] = cAttrsComp.getRuntimeCritical() + sCrt;
sDataCom.Attrs[Attrs.critical_damage] = cAttrsComp.getRuntimeCritDamageBonus();
sDataCom.Attrs[Attrs.freeze_chance] = cAttrsComp.getRuntimeFreezeChance() + sFrz;
sDataCom.Attrs[Attrs.knockback_chance] = cAttrsComp.knockback_chance || 0;
sDataCom.Attrs[Attrs.knockback_distance] = cAttrsComp.knockback_distance || 0;
sDataCom.Attrs[Attrs.puncture_chance] = cAttrsComp.getRuntimePunctureChance(); // 初始化携带施法者的穿透概率
sDataCom.s_uuid=s_uuid
sDataCom.skill_lv = Math.max(0, skill_lv);
sDataCom.fac=cAttrsComp.fac

View File

@@ -2,11 +2,13 @@ import { _decorator, Animation, CCInteger, Collider2D, Contact2DType, UITransfor
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { HeroViewComp } from "../hero/HeroViewComp";
import { EType, SkillConfig, SkillSet } from "../common/config/SkillSet";
import { DTType, EType, SkillConfig, SkillSet } from "../common/config/SkillSet";
import { SDataCom } from "./SDataCom";
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
import { DamageQueueHelper } from "../hero/DamageQueueComp";
import { mLogger } from "../common/Logger";
import { FightSet } from "../common/config/GameSet";
import { Attrs } from "../common/config/HeroAttrs";
const { ccclass, property } = _decorator;
@@ -86,7 +88,30 @@ export class SkillView extends CCComp {
}
this.sData.hit_count++;
if (this.sData.hit_count >= this.sData.max_hit_count) {
this.handle_collision_limit();
// == 新增:穿透概率判定 ==
// 仅对单体伤害技能生效DTType.single且存在穿透概率
if (this.SConf.DTType === DTType.single) {
const punctureChance = this.sData.Attrs[Attrs.puncture_chance] || 0;
if (punctureChance > 0) {
const rand = Math.random() * 100;
if (rand < punctureChance) {
// 触发穿透:不销毁,增加 max_hit_count 允许继续穿透
this.sData.max_hit_count++;
// 概率衰减(减去固定的 PUNCTURE_DOWN 值,比如 50
this.sData.Attrs[Attrs.puncture_chance] = Math.max(0, punctureChance - FightSet.PUNCTURE_DOWN);
if (this.debugMode) {
mLogger.log(this.debugMode, 'SkillView', `[SkillView] 触发穿透!剩余概率: ${this.sData.Attrs[Attrs.puncture_chance]}%`);
}
} else {
// 未触发穿透,正常销毁
this.handle_collision_limit();
}
} else {
this.handle_collision_limit();
}
} else {
this.handle_collision_limit();
}
}
// 命中次数按碰撞事件统计:不依赖是否最终造成伤害

View File

@@ -0,0 +1,148 @@
# 技能配置重构设计(简化版)
## 背景
当前技能系统核心问题:**同一个技能 UUID不同角色无法差异化效果**。例如护盾技能 6301所有角色都是给自己加盾无法让某个角色给全队加盾。
## 设计目标
- SkillConfig **保持不变**,作为技能基座(动画、弹道、默认数值)
- 角色通过 **overrides** 覆盖技能的可定制参数ap、TGroup、hit_count、buffs 等)
- 同一个技能 UUID不同角色可以有不同效果
- 触发技能atking/atked也支持 overrides
- **不迁移 SkillSet 数据**,不拆分接口,不改消费者文件类型引用
## 改动内容(共 3 个接口 + 1 个函数)
### 1. SkillOverrides — 角色可覆盖的技能参数
```typescript
/** 角色可覆盖的技能参数 — 所有字段可选 */
export interface SkillOverrides {
TGroup?: TGroup;
ap?: number;
hit_count?: number;
hitcd?: number;
crt?: number;
frz?: number;
bck?: number;
buffs?: BuffConf[];
}
```
### 2. HSkillInfo 增加 overrides
```typescript
export interface HSkillInfo {
uuid: number;
lv: number;
cd: number;
ccd: number;
overrides?: SkillOverrides; // 新增:角色专属参数覆盖
}
```
### 3. 触发技能配置增加 overrides
```typescript
// heroInfo 中触发字段扩展:
atking?: { s_uuid: number; t_num: number; overrides?: SkillOverrides }[];
atked?: { s_uuid: number; t_num: number; overrides?: SkillOverrides }[];
call?: { s_uuid: number; t_num: number; overrides?: SkillOverrides }[];
dead?: { s_uuid: number; t_num: number; overrides?: SkillOverrides }[];
fstart?: { s_uuid: number; t_num: number; overrides?: SkillOverrides }[];
fend?: { s_uuid: number; t_num: number; overrides?: SkillOverrides }[];
```
### 4. mergeSkillParams — 合并基座 + 覆盖
```typescript
/** 合并技能基座参数和角色覆盖参数 */
export function mergeSkillParams(
config: SkillConfig,
overrides?: SkillOverrides
): SkillConfig {
if (!overrides) return config;
return { ...config, ...overrides };
}
```
就这么简单:把 config 展开,把 overrides 展开覆盖上去。没有 overrides 时原样返回。
## 配置示例
### SkillSet.ts — 不变
```typescript
// 6301 护盾 — 保持原样
6301: {
uuid: 6301, name: "护盾", ..., TGroup: TGroup.Self, kind: SkillKind.Shield, ap: 3, ...
},
```
### heroSet.ts — 角色差异化
```typescript
// 见习战士受击2次触发护盾使用基座默认值给自己加3次盾
5001: {
..., atked: [{ s_uuid: 6301, t_num: 2 }],
},
// 盾骑士受击2次触发护盾覆盖为全队加2次盾
5002: {
..., atked: [{ s_uuid: 6301, t_num: 2,
overrides: { TGroup: TGroup.Team, ap: 2, hit_count: 3 }
}],
},
// 牧师普攻2次触发治疗使用基座默认值
5301: {
..., atking: [{ s_uuid: 6302, t_num: 2 }],
},
// 医师普攻2次触发治疗覆盖为持续3次
5302: {
..., atking: [{ s_uuid: 6302, t_num: 2,
overrides: { hit_count: 3, ap: 200 }
}],
},
```
## 运行时改动(仅 SCastSystem + SkillTriggerHelper
### SCastSystem 改动
`applyFriendlySkillEffects``applyActualFriendlyEffect` 中:
```typescript
// 旧:直接读 config
const kind = config.kind ?? SkillKind.Support;
const sAp = config.ap + sUp.ap * _skillLv;
// 新:先合并 overrides再读
const effective = mergeSkillParams(config, triggerConf?.overrides);
const kind = effective.kind ?? SkillKind.Support;
const sAp = effective.ap + sUp.ap * _skillLv;
```
改动范围:只在 `applyFriendlySkillEffects` 入口处加一行 `mergeSkillParams`,其余逻辑不变。
### SkillTriggerHelper 改动
触发技能时传递 `triggerConf.overrides` 给 SCastSystem。
### HeroAttrsComp 类型同步
atking/atked 的内联类型加上 `overrides?: SkillOverrides`
## 涉及文件
| 文件 | 改动 |
|------|------|
| `SkillSet.ts` | 新增 `SkillOverrides` 接口 + `mergeSkillParams` 函数 |
| `heroSet.ts` | HSkillInfo 增加 `overrides?`,触发配置增加 `overrides?` |
| `HeroAttrsComp.ts` | atking/atked 内联类型增加 `overrides?` |
| `SCastSystem.ts` | applyFriendlySkillEffects 中调用 mergeSkillParams |
| `SkillTriggerHelper.ts` | 传递 overrides |
**不涉及的文件**Skill.ts、SkillView.ts、SMoveSystem.ts、STimeComp.ts、HeroAtkSystem.ts、HeroViewComp.ts、Hero.ts、Mon.ts、CardComp.ts、IBoxComp.ts — 这些文件不改动。