3 Commits

Author SHA1 Message Date
pan
695a9e2b66 refactor(skill): 重构技能配置加载逻辑,将参数下沉至prefab配置
1. 新增SkillView组件属性runType/endType/speed/time,替换原配置表字段
2. 批量同步所有技能prefab的配置参数
3. 优化技能运行逻辑,优先使用prefab配置,配置表仅作兜底
4. 新增同步脚本用于批量迁移技能配置
2026-08-13 16:26:19 +08:00
pan
c6b5e1431f fix(skill): 修复技能相关的显示与逻辑问题
1. 调整技能预制体的锚点和攻击偏移参数
2. 修复SkillView.ts的代码格式与导入错误
3. 补充fixed类型技能的动画结束销毁逻辑
2026-08-13 15:36:57 +08:00
pan
7fa18329d6 fix(skill): 调整普攻技能配置与表现
1.  修改普攻预制体的缩放、尺寸、锚点与精灵贴图
2.  更新普攻动画的采样率、时长与帧动画帧
3.  调整技能配置,将默认普攻替换为6006并修正攻击类型
4.  统一全英雄与怪物的默认技能为6006普攻
2026-08-13 15:11:11 +08:00
24 changed files with 420 additions and 152 deletions

View File

@@ -7,21 +7,107 @@
"embeddedPlayerGroups": [] "embeddedPlayerGroups": []
}, },
"_native": "", "_native": "",
"sample": 8, "sample": 24,
"speed": 1, "speed": 1,
"wrapMode": 2, "wrapMode": 1,
"enableTrsBlending": false, "enableTrsBlending": false,
"_duration": 0, "_duration": 0.20833333333333334,
"_hash": 500763545, "_hash": 500763545,
"_tracks": [], "_tracks": [
{
"__id__": 1
}
],
"_exoticAnimation": null, "_exoticAnimation": null,
"_events": [], "_events": [
{
"frame": 0.3333333333333333,
"func": "",
"params": []
},
{
"frame": 0.3333333333333333,
"func": "atk",
"params": []
}
],
"_embeddedPlayers": [], "_embeddedPlayers": [],
"_additiveSettings": { "_additiveSettings": {
"__id__": 1 "__id__": 7
}, },
"_auxiliaryCurveEntries": [] "_auxiliaryCurveEntries": []
}, },
{
"__type__": "cc.animation.ObjectTrack",
"_binding": {
"__type__": "cc.animation.TrackBinding",
"path": {
"__id__": 2
},
"proxy": null
},
"_channel": {
"__id__": 5
}
},
{
"__type__": "cc.animation.TrackPath",
"_paths": [
{
"__id__": 3
},
{
"__id__": 4
},
"spriteFrame"
]
},
{
"__type__": "cc.animation.HierarchyPath",
"path": "Node"
},
{
"__type__": "cc.animation.ComponentPath",
"component": "cc.Sprite"
},
{
"__type__": "cc.animation.Channel",
"_curve": {
"__id__": 6
}
},
{
"__type__": "cc.ObjectCurve",
"_times": [
0,
0.041666666666666664,
0.08333333333333333,
0.125,
0.16666666666666666
],
"_values": [
{
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@c9de1",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@3c745",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@1ebb0",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@0e5a2",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@360bd",
"__expectedType__": "cc.SpriteFrame"
}
]
},
{ {
"__type__": "cc.AnimationClipAdditiveSettings", "__type__": "cc.AnimationClipAdditiveSettings",
"enabled": false, "enabled": false,

View File

@@ -250,7 +250,11 @@
}, },
"atk_x": 10, "atk_x": 10,
"atk_y": 15, "atk_y": 15,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -336,4 +340,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -250,7 +250,11 @@
}, },
"atk_x": 10, "atk_x": 10,
"atk_y": 15, "atk_y": 15,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -336,4 +340,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -250,7 +250,11 @@
}, },
"atk_x": 10, "atk_x": 10,
"atk_y": 15, "atk_y": 15,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -336,4 +340,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -250,7 +250,11 @@
}, },
"atk_x": 10, "atk_x": 10,
"atk_y": 15, "atk_y": 15,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -336,4 +340,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -250,7 +250,11 @@
}, },
"atk_x": 10, "atk_x": 10,
"atk_y": 15, "atk_y": 15,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -336,4 +340,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -108,8 +108,8 @@
}, },
"_lscale": { "_lscale": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": -0.5, "x": 1.3,
"y": 0.5, "y": 1.1,
"z": 1 "z": 1
}, },
"_mobility": 0, "_mobility": 0,
@@ -136,8 +136,8 @@
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 139, "width": 95,
"height": 128 "height": 96
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -172,7 +172,10 @@
"b": 255, "b": 255,
"a": 255 "a": 255
}, },
"_spriteFrame": null, "_spriteFrame": {
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@3c745",
"__expectedType__": "cc.SpriteFrame"
},
"_type": 0, "_type": 0,
"_fillType": 0, "_fillType": 0,
"_sizeMode": 1, "_sizeMode": 1,
@@ -186,7 +189,7 @@
"_isTrimmedMode": true, "_isTrimmedMode": true,
"_useGrayscale": false, "_useGrayscale": false,
"_atlas": { "_atlas": {
"__uuid__": "3d46f945-3f07-477e-a95a-b49557d552c6", "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20",
"__expectedType__": "cc.SpriteAtlas" "__expectedType__": "cc.SpriteAtlas"
}, },
"_id": "" "_id": ""
@@ -222,8 +225,8 @@
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 30, "width": 120,
"height": 50 "height": 120
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -248,8 +251,12 @@
"__prefab": { "__prefab": {
"__id__": 11 "__id__": 11
}, },
"atk_x": 0, "atk_x": 20,
"atk_y": 0, "atk_y": 40,
"runType": 2,
"endType": 2,
"speed": 720,
"time": 0,
"_id": "" "_id": ""
}, },
{ {
@@ -311,12 +318,12 @@
"_offset": { "_offset": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
"x": 0, "x": 0,
"y": 0 "y": -0.1
}, },
"_size": { "_size": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 30, "width": 120,
"height": 50 "height": 120
}, },
"_id": "" "_id": ""
}, },

View File

@@ -282,7 +282,11 @@
}, },
"atk_x": 10, "atk_x": 10,
"atk_y": 25, "atk_y": 25,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -368,4 +372,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -282,7 +282,11 @@
}, },
"atk_x": 10, "atk_x": 10,
"atk_y": 25, "atk_y": 25,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -368,4 +372,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -282,7 +282,11 @@
}, },
"atk_x": 10, "atk_x": 10,
"atk_y": 25, "atk_y": 25,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -368,4 +372,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -250,7 +250,11 @@
}, },
"atk_x": 10, "atk_x": 10,
"atk_y": 15, "atk_y": 15,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -336,4 +340,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -250,7 +250,11 @@
}, },
"atk_x": 10, "atk_x": 10,
"atk_y": 15, "atk_y": 15,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -336,4 +340,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -253,7 +253,11 @@
}, },
"atk_x": 0, "atk_x": 0,
"atk_y": 0, "atk_y": 0,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -368,4 +372,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -389,7 +389,11 @@
}, },
"atk_x": 0, "atk_x": 0,
"atk_y": 0, "atk_y": 0,
"_id": "" "_id": "",
"runType": 0,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -504,4 +508,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -250,7 +250,11 @@
}, },
"atk_x": 10, "atk_x": 10,
"atk_y": 15, "atk_y": 15,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -336,4 +340,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -250,7 +250,11 @@
}, },
"atk_x": 10, "atk_x": 10,
"atk_y": 15, "atk_y": 15,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -336,4 +340,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -250,7 +250,11 @@
}, },
"atk_x": 10, "atk_x": 10,
"atk_y": 15, "atk_y": 15,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -336,4 +340,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -250,7 +250,11 @@
}, },
"atk_x": 10, "atk_x": 10,
"atk_y": 15, "atk_y": 15,
"_id": "" "_id": "",
"runType": 1,
"endType": 2,
"speed": 720,
"time": 0
}, },
{ {
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
@@ -336,4 +340,4 @@
"instance": null, "instance": null,
"targetOverrides": null "targetOverrides": null
} }
] ]

View File

@@ -1,4 +1,4 @@
// ========== 从 HeroAttrs.ts 导入属性相关定义 ========== // ========== 从 HeroAttrs.ts 导入属性相关定义 ==========
import { Attrs } from "./HeroAttrs"; import { Attrs } from "./HeroAttrs";
export enum HSSet { export enum HSSet {
@@ -134,6 +134,7 @@ export interface SkillConfig {
gold?: number, // 获取金币技能的金币值 gold?: number, // 获取金币技能的金币值
hit_count: number, // 可命中次数 hit_count: number, // 可命中次数
hitcd: number, // 持续伤害的伤害间隔(秒) hitcd: number, // 持续伤害的伤害间隔(秒)
/** @deprecated 已下沉到 SkillView @propertyprefab 配置),此处仅作兜底 */
speed: number, // 移动速度 speed: number, // 移动速度
with: number, // 宽度(暂时无用) with: number, // 宽度(暂时无用)
ready: number, // 前摇时间 ready: number, // 前摇时间
@@ -142,11 +143,14 @@ export interface SkillConfig {
EAnm: number, // 结束动画ID EAnm: number, // 结束动画ID
DAnm: string, // 命中后动画ID DAnm: string, // 命中后动画ID
IType: IType, // 技能类型(近战/远程/辅助) IType: IType, // 技能类型(近战/远程/辅助)
/** @deprecated 已下沉到 SkillView @propertyprefab 配置),此处仅作兜底 */
RType: RType, // 技能运行类型(直线/贝塞尔/固定起点/固定终点) RType: RType, // 技能运行类型(直线/贝塞尔/固定起点/固定终点)
/** @deprecated 已下沉到 SkillView @propertyprefab 配置),此处仅作兜底 */
EType: EType, // 结束条件(动画结束/时间结束/距离结束/碰撞/次数结束) EType: EType, // 结束条件(动画结束/时间结束/距离结束/碰撞/次数结束)
bezier_start_y?: number, // 贝塞尔起始抬升高度 bezier_start_y?: number, // 贝塞尔起始抬升高度
bezier_mid_y?: number, // 贝塞尔中间高度增量 bezier_mid_y?: number, // 贝塞尔中间高度增量
bezier_arc?: number, // 贝塞尔弧度系数 bezier_arc?: number, // 贝塞尔弧度系数
/** @deprecated 已下沉到 SkillView @propertyprefab 配置),此处仅作兜底 */
time?: number, // timeEnd 持续时间(秒) time?: number, // timeEnd 持续时间(秒)
kind?: SkillKind, // 主效果类型 kind?: SkillKind, // 主效果类型
crt?: number, // 额外暴击率 crt?: number, // 额外暴击率
@@ -218,22 +222,22 @@ export const SkillSet: Record<number, SkillConfig> = {
DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.Melee, is_accel: true, DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.Melee, is_accel: true,
RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害", RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害",
}, },
6002: { 6002: {
uuid: 6002, name: "飞刀", sp_name: "a2", icon: "Sword-FA_WP_Main_Sword_009_GraySilver", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "atk", uuid: 6002, name: "飞刀", sp_name: "a2", icon: "Sword-FA_WP_Main_Sword_009_GraySilver", 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, is_accel: true, DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.Melee, is_accel: true,
RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害", RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害",
}, },
6003: { 6003: {
uuid: 6003, name: "匕首", sp_name: "a3", icon: "Sword-FA_WP_Main_Sword_019_WoodSilver", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "atk", uuid: 6003, name: "匕首", sp_name: "a3", icon: "Sword-FA_WP_Main_Sword_019_WoodSilver", 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, is_accel: true, DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.Melee, is_accel: true,
RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害", RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害",
}, },
6004: { 6004: {
uuid: 6004, name: "飞斧", sp_name: "a4", icon: "Axe-FA_WP_Main_Axe_004_WoodGray", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "atk", uuid: 6004, name: "飞斧", sp_name: "a4", icon: "Axe-FA_WP_Main_Axe_004_WoodGray", 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, is_accel: true, DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.Melee, is_accel: true,
RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害", RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害",
}, },
6005: { 6005: {
uuid: 6005, name: "飞枪", sp_name: "a5", icon: "Spear-FA_WP_Main_Spear_010_MetalBlue", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "atk", uuid: 6005, name: "飞枪", sp_name: "a5", icon: "Spear-FA_WP_Main_Spear_010_MetalBlue", 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, is_accel: true, DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.Melee, is_accel: true,
RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害", RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害",
@@ -241,7 +245,7 @@ export const SkillSet: Record<number, SkillConfig> = {
6006: { 6006: {
uuid: 6006, name: "攻击", sp_name: "atk", icon: "Stat_Attack_01", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "atk", uuid: 6006, name: "攻击", sp_name: "atk", icon: "Stat_Attack_01", 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, is_accel: true, DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.Melee, is_accel: true,
RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害", RType: RType.fixed, EType: EType.collision, info: "造成攻击力100%的伤害",
}, },
6007: { 6007: {
uuid: 6007, name: "飞棒", sp_name: "b1", icon: "Blunt-FA_WP_Main_Blunt_002_Wood", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "atk", uuid: 6007, name: "飞棒", sp_name: "b1", icon: "Blunt-FA_WP_Main_Blunt_002_Wood", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "atk",

View File

@@ -404,7 +404,7 @@ export const HeroInfo: Record<number, heroInfo> = {
// 5001 铁壁战士 — atked 护盾标杆原5011 // 5001 铁壁战士 — atked 护盾标杆原5011
5001: { 5001: {
uuid: 5001, name: "铁壁战士", path: "hk1", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 300, ap: 22, uuid: 5001, name: "铁壁战士", path: "hk1", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 300, ap: 22,
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
atked: { atked: {
6301: [ 6301: [
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, ap: 2 } }, { lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, ap: 2 } },
@@ -417,7 +417,7 @@ export const HeroInfo: Record<number, heroInfo> = {
// 5002 影袭刺客 — atking 自身攻击 // 5002 影袭刺客 — atking 自身攻击
5002: { 5002: {
uuid: 5002, name: "影袭刺客", path: "hc1", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, role: HRole.Assassin, hp: 300, ap: 22, uuid: 5002, name: "影袭刺客", path: "hc1", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, role: HRole.Assassin, hp: 300, ap: 22,
skills: { 6003: { uuid: 6003, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast2].cd, ccd: 0 } }, skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast2].cd, ccd: 0 } },
atking: { atking: {
6401: [ 6401: [
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, ap: 1 } }, { lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, ap: 1 } },
@@ -430,7 +430,7 @@ export const HeroInfo: Record<number, heroInfo> = {
// 5003 遗志将军 — dead 全队攻击 // 5003 遗志将军 — dead 全队攻击
5003: { 5003: {
uuid: 5003, name: "遗志将军", path: "hk2", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 300, ap: 22, uuid: 5003, name: "遗志将军", path: "hk2", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 300, ap: 22,
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
dead: { dead: {
6401: [ 6401: [
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 3 } }, { lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 3 } },
@@ -470,7 +470,7 @@ export const HeroInfo: Record<number, heroInfo> = {
// 5101 不死斗士 — atked 回血(更高数值) // 5101 不死斗士 — atked 回血(更高数值)
5101: { 5101: {
uuid: 5101, name: "不死斗士", path: "hk3", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 600, ap: 46, uuid: 5101, name: "不死斗士", path: "hk3", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 600, ap: 46,
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
atked: { atked: {
6302: [ 6302: [
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, ap: 200 } }, { lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, ap: 200 } },
@@ -483,7 +483,7 @@ export const HeroInfo: Record<number, heroInfo> = {
// 5102 致命杀手 — atking 暴击(更高数值) // 5102 致命杀手 — atking 暴击(更高数值)
5102: { 5102: {
uuid: 5102, name: "致命杀手", path: "hc2", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, role: HRole.Assassin, hp: 600, ap: 46, uuid: 5102, name: "致命杀手", path: "hc2", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, role: HRole.Assassin, hp: 600, ap: 46,
skills: { 6003: { uuid: 6003, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast2].cd, ccd: 0 } }, skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast2].cd, ccd: 0 } },
atking: { atking: {
6403: [ 6403: [
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, timed_buff_id: 7012, buff_value: 5, buff_duration: 5 } }, { lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, timed_buff_id: 7012, buff_value: 5, buff_duration: 5 } },
@@ -496,7 +496,7 @@ export const HeroInfo: Record<number, heroInfo> = {
// 5103 殉道勇士 — dead 全队护盾(更高数值) // 5103 殉道勇士 — dead 全队护盾(更高数值)
5103: { 5103: {
uuid: 5103, name: "殉道勇士", path: "hk4", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 600, ap: 46, uuid: 5103, name: "殉道勇士", path: "hk4", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 600, ap: 46,
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
dead: { dead: {
6301: [ 6301: [
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 3 } }, { lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 3 } },
@@ -549,7 +549,7 @@ export const HeroInfo: Record<number, heroInfo> = {
// 5201 怒血勇士 — atked 全队攻击(范围扩大) // 5201 怒血勇士 — atked 全队攻击(范围扩大)
5201: { 5201: {
uuid: 5201, name: "怒血勇士", path: "hk5", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 900, ap: 68, uuid: 5201, name: "怒血勇士", path: "hk5", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 900, ap: 68,
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
atked: { atked: {
6401: [ 6401: [
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Team, ap: 1 } }, { lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Team, ap: 1 } },
@@ -575,7 +575,7 @@ export const HeroInfo: Record<number, heroInfo> = {
// 5203 传承卫士 — dead 全队生命(范围扩大) // 5203 传承卫士 — dead 全队生命(范围扩大)
5203: { 5203: {
uuid: 5203, name: "传承卫士", path: "hk1", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 900, ap: 68, uuid: 5203, name: "传承卫士", path: "hk1", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 900, ap: 68,
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
dead: { dead: {
6402: [ 6402: [
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 10 } }, { lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 10 } },
@@ -615,7 +615,7 @@ export const HeroInfo: Record<number, heroInfo> = {
// 5301 复仇守护者 — atked 全队暴击(范围+数值) // 5301 复仇守护者 — atked 全队暴击(范围+数值)
5301: { 5301: {
uuid: 5301, name: "复仇守护者", path: "hk2", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 1200, ap: 90, uuid: 5301, name: "复仇守护者", path: "hk2", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 1200, ap: 90,
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow1].cd, ccd: 0 } }, skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow1].cd, ccd: 0 } },
atked: { atked: {
6403: [ 6403: [
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Team, timed_buff_id: 7012, buff_value: 5, buff_duration: 5 } }, { lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Team, timed_buff_id: 7012, buff_value: 5, buff_duration: 5 } },
@@ -641,7 +641,7 @@ export const HeroInfo: Record<number, heroInfo> = {
// 5303 亡语刺客 — dead 全队暴击+暴伤(双效果) // 5303 亡语刺客 — dead 全队暴击+暴伤(双效果)
5303: { 5303: {
uuid: 5303, name: "亡语刺客", path: "hc3", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, role: HRole.Assassin, hp: 1200, ap: 90, uuid: 5303, name: "亡语刺客", path: "hc3", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, role: HRole.Assassin, hp: 1200, ap: 90,
skills: { 6003: { uuid: 6003, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast3].cd, ccd: 0 } }, skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast3].cd, ccd: 0 } },
dead: { dead: {
6403: [ 6403: [
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, timed_buff_id: 7012, buff_value: 5, buff_duration: 5 } }, { lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, timed_buff_id: 7012, buff_value: 5, buff_duration: 5 } },
@@ -691,7 +691,7 @@ export const HeroInfo: Record<number, heroInfo> = {
// 5401 不灭战魂 — atked 攻击 + revive双技能 // 5401 不灭战魂 — atked 攻击 + revive双技能
5401: { 5401: {
uuid: 5401, name: "不灭战魂", path: "hk3", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 1500, ap: 114, uuid: 5401, name: "不灭战魂", path: "hk3", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 1500, ap: 114,
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
atked: { atked: {
6401: [ 6401: [
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, ap: 2 } }, { lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, ap: 2 } },
@@ -727,7 +727,7 @@ export const HeroInfo: Record<number, heroInfo> = {
// 5403 凤凰祭司 — dead 攻击+护盾 + revive双技能 // 5403 凤凰祭司 — dead 攻击+护盾 + revive双技能
5403: { 5403: {
uuid: 5403, name: "凤凰祭司", path: "hk4", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 1500, ap: 114, uuid: 5403, name: "凤凰祭司", path: "hk4", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 1500, ap: 114,
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
dead: { dead: {
6401: [ 6401: [
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 5 } }, { lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 5 } },
@@ -803,15 +803,15 @@ export const HeroInfo: Record<number, heroInfo> = {
// 前排怪物 — 近战镜像 1 级英雄基准hp300/ap22/cd1.8),变体微分定位 // 前排怪物 — 近战镜像 1 级英雄基准hp300/ap22/cd1.8),变体微分定位
6001: { 6001: {
uuid: 6001, name: "兽人战士", path: "m1", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.Melee, hp: 300, ap: 22, speed: 70, uuid: 6001, name: "兽人战士", path: "m1", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.Melee, hp: 300, ap: 22, speed: 70,
skills: { 6005: { uuid: 6005, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, info: "基础前排怪, 与1级近战英雄持平" skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, info: "基础前排怪, 与1级近战英雄持平"
}, },
6002: { 6002: {
uuid: 6002, name: "兽人精锐战士", path: "m2", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.Melee, hp: 340, ap: 26, speed: 110, uuid: 6002, name: "兽人精锐战士", path: "m2", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.Melee, hp: 340, ap: 26, speed: 110,
skills: { 6005: { uuid: 6005, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow2].cd, ccd: 0 } }, info: "进阶前排怪, 更快更痛" skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow2].cd, ccd: 0 } }, info: "进阶前排怪, 更快更痛"
}, },
6003: { 6003: {
uuid: 6003, name: "兽人重装兵", path: "m3", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.Heavy, hp: 800, ap: 14, speed: 50, uuid: 6003, name: "兽人重装兵", path: "m3", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.Heavy, hp: 800, ap: 14, speed: 50,
skills: { 6005: { uuid: 6005, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow3].cd, ccd: 0 } }, info: "重型坦克怪, 高HP低攻承伤位" skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow3].cd, ccd: 0 } }, info: "重型坦克怪, 高HP低攻承伤位"
}, },
// 后排怪物 — 远程镜像 1 级法师基准hp160/ap28/cd1.3),变体微分定位 // 后排怪物 — 远程镜像 1 级法师基准hp160/ap28/cd1.3),变体微分定位
6004: { 6004: {
@@ -825,7 +825,7 @@ export const HeroInfo: Record<number, heroInfo> = {
// 特殊位怪物 // 特殊位怪物
6006: { 6006: {
uuid: 6006, name: "骷髅领主", path: "m6", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.MeleeBoss, hp: 900, ap: 20, speed: 60, uuid: 6006, name: "骷髅领主", path: "m6", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.MeleeBoss, hp: 900, ap: 20, speed: 60,
skills: { 6005: { uuid: 6005, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow3].cd, ccd: 0 } }, info: "前排MiniBoss级坦克" skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow3].cd, ccd: 0 } }, info: "前排MiniBoss级坦克"
}, },
6007: { 6007: {
uuid: 6007, name: "兽人术士", path: "m7", fac: FacSet.MON, lv: 1, type: HType.Long, monType: MonType.Support, hp: 240, ap: 18, speed: 70, uuid: 6007, name: "兽人术士", path: "m7", fac: FacSet.MON, lv: 1, type: HType.Long, monType: MonType.Support, hp: 240, ap: 18, speed: 70,
@@ -839,11 +839,11 @@ export const HeroInfo: Record<number, heroInfo> = {
// BOSS怪物 — 与6006同基准以高HP压场血量经 BOSS_HP_BONUS_MUL 单独放大 // BOSS怪物 — 与6006同基准以高HP压场血量经 BOSS_HP_BONUS_MUL 单独放大
6101: { 6101: {
uuid: 6101, name: "兽人首领-双刀战士", path: "mb1", fac: FacSet.MON, lv: 6, type: HType.Melee, monType: MonType.MeleeBoss, hp: 1200, ap: 24, speed: 120, uuid: 6101, name: "兽人首领-双刀战士", path: "mb1", fac: FacSet.MON, lv: 6, type: HType.Melee, monType: MonType.MeleeBoss, hp: 1200, ap: 24, speed: 120,
skills: { 6103: { uuid: 6103, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, info: "前排Boss, 攻速型" skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, info: "前排Boss, 攻速型"
}, },
6102: { 6102: {
uuid: 6102, name: "兽人首领-斧头战士", path: "mb2", fac: FacSet.MON, lv: 6, type: HType.Melee, monType: MonType.MeleeBoss, hp: 1500, ap: 18, speed: 60, uuid: 6102, name: "兽人首领-斧头战士", path: "mb2", fac: FacSet.MON, lv: 6, type: HType.Melee, monType: MonType.MeleeBoss, hp: 1500, ap: 18, speed: 60,
skills: { 6005: { uuid: 6005, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow3].cd, ccd: 0 } }, info: "前排Boss, 超高HP" skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow3].cd, ccd: 0 } }, info: "前排Boss, 超高HP"
}, },
6103: { 6103: {
uuid: 6103, name: "兽人首领-魔法师", path: "mb3", fac: FacSet.MON, lv: 6, type: HType.Long, monType: MonType.LongBoss, hp: 1000, ap: 28, speed: 110, uuid: 6103, name: "兽人首领-魔法师", path: "mb3", fac: FacSet.MON, lv: 6, type: HType.Long, monType: MonType.LongBoss, hp: 1000, ap: 28, speed: 110,
@@ -851,7 +851,7 @@ export const HeroInfo: Record<number, heroInfo> = {
}, },
6104: { 6104: {
uuid: 6104, name: "兽人首领-射手", path: "mb4", fac: FacSet.MON, lv: 6, type: HType.Long, monType: MonType.LongBoss, hp: 1100, ap: 24, speed: 70, uuid: 6104, name: "兽人首领-射手", path: "mb4", fac: FacSet.MON, lv: 6, type: HType.Long, monType: MonType.LongBoss, hp: 1100, ap: 24, speed: 70,
skills: { 6005: { uuid: 6005, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow2].cd, ccd: 0 } }, info: "后排位Boss, 均衡型" skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow2].cd, ccd: 0 } }, info: "后排位Boss, 均衡型"
}, },
6105: { 6105: {
uuid: 6105, name: "亡灵首领-法师", path: "mb5", fac: FacSet.MON, lv: 6, type: HType.Long, monType: MonType.LongBoss, hp: 1000, ap: 30, speed: 110, uuid: 6105, name: "亡灵首领-法师", path: "mb5", fac: FacSet.MON, lv: 6, type: HType.Long, monType: MonType.LongBoss, hp: 1000, ap: 30, speed: 110,
@@ -859,7 +859,7 @@ export const HeroInfo: Record<number, heroInfo> = {
}, },
6106: { 6106: {
uuid: 6106, name: "亡灵首领-骑马战士", path: "mb6", fac: FacSet.MON, lv: 6, type: HType.Melee, monType: MonType.MeleeBoss, hp: 1800, ap: 20, speed: 130, uuid: 6106, name: "亡灵首领-骑马战士", path: "mb6", fac: FacSet.MON, lv: 6, type: HType.Melee, monType: MonType.MeleeBoss, hp: 1800, ap: 20, speed: 130,
skills: { 6005: { uuid: 6005, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow3].cd, ccd: 0 } }, info: "前排终极Boss, 最高HP+高速" skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow3].cd, ccd: 0 } }, info: "前排终极Boss, 最高HP+高速"
}, },

View File

@@ -1,4 +1,4 @@
import { v3, Vec3 ,Node} from "cc"; import { v3, Vec3, Node } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { EType, RType, SkillSet } from "../common/config/SkillSet"; import { EType, RType, SkillSet } from "../common/config/SkillSet";
import { SMoveDataComp } from "./SMoveComp"; import { SMoveDataComp } from "./SMoveComp";
@@ -26,46 +26,46 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
filter(): ecs.IMatcher { filter(): ecs.IMatcher {
return ecs.allOf(SMoveDataComp, SkillView); return ecs.allOf(SMoveDataComp, SkillView);
} }
entityEnter(entity: ecs.Entity): void { entityEnter(entity: ecs.Entity): void {
const moveComp = entity.get(SMoveDataComp); const moveComp = entity.get(SMoveDataComp);
const skillView = entity.get(SkillView); const skillView = entity.get(SkillView);
if (!moveComp || !skillView || !skillView.node) return; if (!moveComp || !skillView || !skillView.node) return;
// 获取技能配置 // 获取技能配置
const skillConfig = SkillSet[moveComp.s_uuid]; const skillConfig = SkillSet[moveComp.s_uuid];
if (!skillConfig) { if (!skillConfig) {
mLogger.warn(this.debugMode, 'SMoveSystem', `[SMoveSystem] 技能配置不存在: ${moveComp.s_uuid}`); mLogger.warn(this.debugMode, 'SMoveSystem', `[SMoveSystem] 技能配置不存在: ${moveComp.s_uuid}`);
return; return;
} }
// 根据配置设置移动速度与加速度 // 移动参数由 prefab 的 SkillView @property 决定speed<=0 时 Skill.load 已回退配置表值)
if (skillConfig.speed > 0) { if (moveComp.speed <= 0) {
moveComp.speed = skillConfig.speed; moveComp.speed = skillConfig.speed;
} }
if (skillConfig.is_accel) { if (skillConfig.is_accel) {
moveComp.isAccelerate = true; moveComp.isAccelerate = true;
} }
// 根据runType设置初始位置 // 根据runType设置初始位置
this.initializePosition(moveComp, skillView); this.initializePosition(moveComp, skillView);
// 开始移动(除了固定位置类型) // 开始移动(除了固定位置类型)
if (moveComp.runType !== RType.fixed && moveComp.runType !== RType.fixedEnd) { if (moveComp.runType !== RType.fixed && moveComp.runType !== RType.fixedEnd) {
moveComp.startMove(); moveComp.startMove();
} }
mLogger.log(this.debugMode, 'SMoveSystem', `[SMoveSystem] 技能 ${skillConfig.name} 开始移动,类型: ${moveComp.runType}`); mLogger.log(this.debugMode, 'SMoveSystem', `[SMoveSystem] 技能 ${skillConfig.name} 开始移动,类型: ${moveComp.runType}`);
} }
/** /**
* 根据runType初始化技能位置 * 根据runType初始化技能位置
*/ */
private initializePosition(moveComp: SMoveDataComp, skillView: SkillView): void { private initializePosition(moveComp: SMoveDataComp, skillView: SkillView): void {
const node = skillView.node; const node = skillView.node;
switch(moveComp.runType) { switch (moveComp.runType) {
case RType.linear: case RType.linear:
// linear类型根据atk_x和atk_y调整起始位置 // linear类型根据atk_x和atk_y调整起始位置
const adjustedStartPos = v3( const adjustedStartPos = v3(
@@ -73,35 +73,35 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
moveComp.startPos.y + moveComp.atk_y, moveComp.startPos.y + moveComp.atk_y,
moveComp.startPos.z moveComp.startPos.z
); );
const originTargetPos = v3( const originTargetPos = v3(
moveComp.targetPos.x, moveComp.targetPos.x,
moveComp.targetPos.y, moveComp.targetPos.y,
moveComp.targetPos.z moveComp.targetPos.z
); );
const direction = new Vec3(); const direction = new Vec3();
Vec3.subtract(direction, originTargetPos, adjustedStartPos); Vec3.subtract(direction, originTargetPos, adjustedStartPos);
// 延长终止点统一消亡点的x坐标为 +-500 // 延长终止点统一消亡点的x坐标为 +-500
const targetX = moveComp.scale > 0 ? 500 : -500; const targetX = moveComp.scale > 0 ? 500 : -500;
let targetY = originTargetPos.y; let targetY = originTargetPos.y;
if (Math.abs(direction.x) > 0.01) { if (Math.abs(direction.x) > 0.01) {
const slope = direction.y / direction.x; const slope = direction.y / direction.x;
targetY = adjustedStartPos.y + slope * (targetX - adjustedStartPos.x); targetY = adjustedStartPos.y + slope * (targetX - adjustedStartPos.x);
} }
const adjustedTargetPos = v3( const adjustedTargetPos = v3(
targetX, targetX,
targetY, targetY,
originTargetPos.z originTargetPos.z
); );
moveComp.startPos.set(adjustedStartPos); moveComp.startPos.set(adjustedStartPos);
moveComp.targetPos.set(adjustedTargetPos); moveComp.targetPos.set(adjustedTargetPos);
node.setPosition(adjustedStartPos); node.setPosition(adjustedStartPos);
// 设置旋转角度 // 设置旋转角度
const dirForAngle = new Vec3(); const dirForAngle = new Vec3();
Vec3.subtract(dirForAngle, adjustedTargetPos, adjustedStartPos); Vec3.subtract(dirForAngle, adjustedTargetPos, adjustedStartPos);
@@ -113,12 +113,12 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
node.angle = angle; node.angle = angle;
} }
break; break;
case RType.fixed: case RType.fixed:
// 固定起始位置 // 固定起始位置
node.setPosition(moveComp.startPos.x, node.position.y, 0); node.setPosition(moveComp.startPos.x, node.position.y, 0);
break; break;
case RType.fixedEnd: case RType.fixedEnd:
// 固定结束位置 // 固定结束位置
node.setPosition(moveComp.targetPos.x > 360 ? 300 : moveComp.targetPos.x, moveComp.targetPos.y, 0); node.setPosition(moveComp.targetPos.x > 360 ? 300 : moveComp.targetPos.x, moveComp.targetPos.y, 0);
@@ -154,26 +154,26 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
} }
update(entity: ecs.Entity): void { update(entity: ecs.Entity): void {
if(!smc.mission.play ) return; if (!smc.mission.play) return;
if(smc.mission.pause) return if (smc.mission.pause) return
const moveComp = entity.get(SMoveDataComp); const moveComp = entity.get(SMoveDataComp);
const skillView = entity.get(SkillView); const skillView = entity.get(SkillView);
if (!moveComp || !skillView || !skillView.node) return; if (!moveComp || !skillView || !skillView.node) return;
// 更新移动进度 // 更新移动进度
const isMoving = moveComp.updateProgress(this.dt); const isMoving = moveComp.updateProgress(this.dt);
if (isMoving) { if (isMoving) {
// 更新节点位置 // 更新节点位置
skillView.node.setPosition(moveComp.currentPos); skillView.node.setPosition(moveComp.currentPos);
// 处理自动旋转(贝塞尔移动) // 处理自动旋转(贝塞尔移动)
if (moveComp.runType === RType.bezier) { if (moveComp.runType === RType.bezier) {
this.updateRotation(skillView.node, moveComp); this.updateRotation(skillView.node, moveComp);
} }
} }
// 检查移动完成 // 检查移动完成
if (moveComp.isCompleted && moveComp.autoDestroy) { if (moveComp.isCompleted && moveComp.autoDestroy) {
// 根据结束类型决定是否销毁 // 根据结束类型决定是否销毁
@@ -185,7 +185,7 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
} }
} }
} }
/** /**
* 更新节点旋转(用于贝塞尔移动) * 更新节点旋转(用于贝塞尔移动)
*/ */
@@ -193,29 +193,29 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
if (moveComp.progress < 1) { if (moveComp.progress < 1) {
// 计算下一帧的位置来确定方向 // 计算下一帧的位置来确定方向
const nextProgress = Math.min(moveComp.progress + 0.01, 1); const nextProgress = Math.min(moveComp.progress + 0.01, 1);
const t = moveComp.isAccelerate ? const t = moveComp.isAccelerate ?
(nextProgress * nextProgress * 0.7 + nextProgress * 0.3) : (nextProgress * nextProgress * 0.7 + nextProgress * 0.3) :
nextProgress; nextProgress;
const nextPos = v3(0, 0, 0); const nextPos = v3(0, 0, 0);
// 计算下一个位置 // 计算下一个位置
const oneMinusT = 1 - t; const oneMinusT = 1 - t;
const oneMinusTSquared = oneMinusT * oneMinusT; const oneMinusTSquared = oneMinusT * oneMinusT;
const tSquared = t * t; const tSquared = t * t;
const twoOneMinusTt = 2 * oneMinusT * t; const twoOneMinusTt = 2 * oneMinusT * t;
nextPos.x = oneMinusTSquared * moveComp.startPos.x + nextPos.x = oneMinusTSquared * moveComp.startPos.x +
twoOneMinusTt * moveComp.controlPoint.x + twoOneMinusTt * moveComp.controlPoint.x +
tSquared * moveComp.targetPos.x; tSquared * moveComp.targetPos.x;
nextPos.y = oneMinusTSquared * moveComp.startPos.y + nextPos.y = oneMinusTSquared * moveComp.startPos.y +
twoOneMinusTt * moveComp.controlPoint.y + twoOneMinusTt * moveComp.controlPoint.y +
tSquared * moveComp.targetPos.y; tSquared * moveComp.targetPos.y;
// 计算方向角度 // 计算方向角度
const direction = new Vec3(); const direction = new Vec3();
Vec3.subtract(direction, nextPos, moveComp.currentPos); Vec3.subtract(direction, nextPos, moveComp.currentPos);
if (direction.length() > 0.01) { if (direction.length() > 0.01) {
let angle = Math.atan2(direction.y, direction.x) * (180 / Math.PI); let angle = Math.atan2(direction.y, direction.x) * (180 / Math.PI);
if (moveComp.scale < 0) { if (moveComp.scale < 0) {
@@ -236,15 +236,15 @@ export class SMoveHelper {
*/ */
static setupMoveForSkill(entity: ecs.Entity, startPos: Vec3, targetPos: Vec3, s_uuid: number): void { static setupMoveForSkill(entity: ecs.Entity, startPos: Vec3, targetPos: Vec3, s_uuid: number): void {
let moveComp = entity.get(SMoveDataComp); let moveComp = entity.get(SMoveDataComp);
if (!moveComp) { if (!moveComp) {
moveComp = entity.add(SMoveDataComp); moveComp = entity.add(SMoveDataComp);
} }
moveComp.startPos.set(startPos); moveComp.startPos.set(startPos);
moveComp.targetPos.set(targetPos); moveComp.targetPos.set(targetPos);
moveComp.s_uuid = s_uuid; moveComp.s_uuid = s_uuid;
// 从技能配置获取默认参数 // 从技能配置获取默认参数
const skillConfig = SkillSet[s_uuid]; const skillConfig = SkillSet[s_uuid];
if (skillConfig) { if (skillConfig) {
@@ -253,7 +253,7 @@ export class SMoveHelper {
if (skillConfig.is_accel) moveComp.isAccelerate = true; if (skillConfig.is_accel) moveComp.isAccelerate = true;
} }
} }
/** /**
* 检查技能是否正在移动 * 检查技能是否正在移动
*/ */
@@ -261,7 +261,7 @@ export class SMoveHelper {
const moveComp = entity.get(SMoveDataComp); const moveComp = entity.get(SMoveDataComp);
return moveComp ? moveComp.isMoving : false; return moveComp ? moveComp.isMoving : false;
} }
/** /**
* 获取技能移动统计信息 * 获取技能移动统计信息
*/ */
@@ -269,7 +269,7 @@ export class SMoveHelper {
const moveComp = entity.get(SMoveDataComp); const moveComp = entity.get(SMoveDataComp);
return moveComp ? moveComp.getMoveStats() : null; return moveComp ? moveComp.getMoveStats() : null;
} }
/** /**
* 停止技能移动 * 停止技能移动
*/ */

View File

@@ -146,7 +146,7 @@ export class Skill extends ecs.Entity {
if (node.isValid) node.destroy(); if (node.isValid) node.destroy();
return; return;
} }
if (config.EType != EType.collision) { if (SView.endType != EType.collision) {
const collider = node.getComponent(BoxCollider2D); const collider = node.getComponent(BoxCollider2D);
if (collider) { if (collider) {
collider.enabled = false collider.enabled = false
@@ -174,8 +174,10 @@ export class Skill extends ecs.Entity {
sMoveCom.targetPos.set(targetPos); sMoveCom.targetPos.set(targetPos);
sMoveCom.s_uuid = s_uuid; sMoveCom.s_uuid = s_uuid;
sMoveCom.scale = caster.node.scale.x < 0 ? -1 : 1; sMoveCom.scale = caster.node.scale.x < 0 ? -1 : 1;
sMoveCom.runType = config.RType; // runType/endType/speed/time 由 prefab 的 SkillView @property 决定,配置表同名字段仅作兜底
sMoveCom.endType = config.EType; sMoveCom.runType = SView.runType;
sMoveCom.endType = SView.endType;
sMoveCom.speed = SView.speed > 0 ? SView.speed : config.speed;
sMoveCom.bezierStartHeight = config.bezier_start_y ?? sMoveCom.bezierStartHeight; sMoveCom.bezierStartHeight = config.bezier_start_y ?? sMoveCom.bezierStartHeight;
sMoveCom.bezierMidHeight = config.bezier_mid_y ?? sMoveCom.bezierMidHeight; sMoveCom.bezierMidHeight = config.bezier_mid_y ?? sMoveCom.bezierMidHeight;
sMoveCom.bezierArc = config.bezier_arc ?? sMoveCom.bezierArc; sMoveCom.bezierArc = config.bezier_arc ?? sMoveCom.bezierArc;
@@ -183,12 +185,12 @@ export class Skill extends ecs.Entity {
sMoveCom.atk_x = SView.atk_x; sMoveCom.atk_x = SView.atk_x;
sMoveCom.atk_y = SView.atk_y; sMoveCom.atk_y = SView.atk_y;
if (config.EType === EType.timeEnd) { if (SView.endType === EType.timeEnd) {
let sTimeCom = this.get(StimeDataComp); let sTimeCom = this.get(StimeDataComp);
if (!sTimeCom) sTimeCom = this.add(StimeDataComp); if (!sTimeCom) sTimeCom = this.add(StimeDataComp);
sTimeCom.reset(); sTimeCom.reset();
sTimeCom.s_uuid = s_uuid; sTimeCom.s_uuid = s_uuid;
sTimeCom.totalTime = Math.max(1, config.time ?? 0); sTimeCom.totalTime = Math.max(1, SView.time > 0 ? SView.time : (config.time ?? 0));
sTimeCom.hitInterval = Math.max(0.5, config.hitcd || 0); sTimeCom.hitInterval = Math.max(0.5, config.hitcd || 0);
} else { } else {
const sTimeCom = this.get(StimeDataComp); const sTimeCom = this.get(StimeDataComp);

View File

@@ -1,8 +1,8 @@
import { _decorator, Animation, CCInteger, Collider2D, Contact2DType, UITransform, v3, Vec3 } from "cc"; import { _decorator, Animation, CCFloat, CCInteger, Collider2D, Contact2DType, Enum, UITransform, v3, Vec3 } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp"; import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { HeroViewComp } from "../hero/HeroViewComp"; import { HeroViewComp } from "../hero/HeroViewComp";
import { DTType, EType, SkillConfig, SkillSet } from "../common/config/SkillSet"; import { DTType, EType, RType, SkillConfig, SkillSet } from "../common/config/SkillSet";
import { SDataCom } from "./SDataCom"; import { SDataCom } from "./SDataCom";
import { HeroAttrsComp } from "../hero/HeroAttrsComp"; import { HeroAttrsComp } from "../hero/HeroAttrsComp";
import { DamageQueueHelper } from "../hero/DamageQueueComp"; import { DamageQueueHelper } from "../hero/DamageQueueComp";
@@ -22,13 +22,29 @@ export class SkillView extends CCComp {
@property({ type: CCInteger }) @property({ type: CCInteger })
atk_y: number = 0 atk_y: number = 0
/** 运动类型:直线/贝塞尔/固定起点/固定终点(由 prefab 配置,优先级高于 SkillSet */
@property({ type: Enum(RType), tooltip: "技能特效运动类型" })
runType: RType = RType.linear;
/** 消亡条件:动画结束/计时结束/碰撞次数结束(由 prefab 配置,优先级高于 SkillSet */
@property({ type: Enum(EType), tooltip: "技能特效消亡条件" })
endType: EType = EType.collision;
/** 移动速度(由 prefab 配置,<=0 时回退 SkillSet.speed */
@property({ type: CCFloat, slide: true, range: [0, 2000, 10], tooltip: "技能特效移动速度" })
speed: number = 0;
/** timeEnd 持续时间(秒),仅 endType=timeEnd 时生效(由 prefab 配置,<=0 时回退 SkillSet.time */
@property({ type: CCFloat, slide: true, range: [0, 30, 0.1], tooltip: "timeEnd 持续时间(秒)" })
time: number = 0;
private debugMode: boolean = false; private debugMode: boolean = false;
anim:Animation=null; anim: Animation = null;
group:number=0; group: number = 0;
SConf:SkillConfig=null; SConf: SkillConfig = null;
sData:SDataCom=null; sData: SDataCom = null;
s_uuid:number=1001 s_uuid: number = 1001
private collider: Collider2D = null; // 缓存碰撞体引用 private collider: Collider2D = null; // 缓存碰撞体引用
private pendingDisableCollider: boolean = false; private pendingDisableCollider: boolean = false;
private isDisposing: boolean = false; private isDisposing: boolean = false;
@@ -41,25 +57,25 @@ export class SkillView extends CCComp {
this.pendingDisableCollider = false; this.pendingDisableCollider = false;
this.isDisposing = false; this.isDisposing = false;
this.collider = this.getComponent(Collider2D); this.collider = this.getComponent(Collider2D);
if(this.collider) { if (this.collider) {
this.collider.group = this.group; this.collider.group = this.group;
this.collider.off(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this); this.collider.off(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
this.collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this); this.collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
this.collider.enabled = this.SConf?.EType === EType.collision; this.collider.enabled = this.endType === EType.collision;
} }
if(this.node.getComponent(Animation)){ if (this.node.getComponent(Animation)) {
let anim = this.node.getComponent(Animation); let anim = this.node.getComponent(Animation);
mLogger.log(this.debugMode, 'SkillView', "[SkillCom]:has anim",anim) mLogger.log(this.debugMode, 'SkillView', "[SkillCom]:has anim", anim)
anim.off(Animation.EventType.FINISHED, this.onAnimationFinished, this); anim.off(Animation.EventType.FINISHED, this.onAnimationFinished, this);
anim.on(Animation.EventType.FINISHED, this.onAnimationFinished, this); anim.on(Animation.EventType.FINISHED, this.onAnimationFinished, this);
// 对象池复用时,需要手动播放默认动画(因为 Play On Load 只在首次生效) // 对象池复用时,需要手动播放默认动画(因为 Play On Load 只在首次生效)
if (anim.defaultClip) { if (anim.defaultClip) {
anim.play(anim.defaultClip.name); anim.play(anim.defaultClip.name);
} }
} }
} }
onBeginContact (seCol: Collider2D, oCol: Collider2D) { onBeginContact(seCol: Collider2D, oCol: Collider2D) {
if (!this.sData || !this.SConf) { if (!this.sData || !this.SConf) {
mLogger.warn(this.debugMode, 'SkillView', '[SkillView] onBeginContact 缺少 sData 或 SConf忽略此次碰撞'); mLogger.warn(this.debugMode, 'SkillView', '[SkillView] onBeginContact 缺少 sData 或 SConf忽略此次碰撞');
return; return;
@@ -126,17 +142,23 @@ export class SkillView extends CCComp {
this.apply_damage(targetView, this.sData.hit_count) this.apply_damage(targetView, this.sData.hit_count)
} }
onAnimationFinished(){ onAnimationFinished() {
// animationEnd 类型:动画结束后再关闭碰撞并销毁 // animationEnd 类型:动画结束后再关闭碰撞并销毁
if(this.SConf.EType==EType.animationEnd){ if (this.endType == EType.animationEnd) {
this.disable_collider_now(); this.disable_collider_now();
this.ent.destroy() this.ent.destroy()
} return;
}
// fixed 类型不移动,无法通过移动完成销毁;动画播完作为兜底销毁时机
if (this.runType == RType.fixed) {
this.disable_collider_now();
this.ent.destroy()
}
} }
// 动画帧事件 atk仅负责开启一帧碰撞窗口不负责伤害与计数 // 动画帧事件 atk仅负责开启一帧碰撞窗口不负责伤害与计数
public atk(args:any){ public atk(args: any) {
if(!this.SConf) return; if (!this.SConf) return;
if(this.SConf.EType==EType.collision) return if (this.endType == EType.collision) return
if (this.enable_collider_safely()) { if (this.enable_collider_safely()) {
mLogger.log(this.debugMode, 'SkillView', `[SkillView] [${this.SConf?.name}] 开启碰撞检测`); mLogger.log(this.debugMode, 'SkillView', `[SkillView] [${this.SConf?.name}] 开启碰撞检测`);
this.scheduleOnce(() => { this.scheduleOnce(() => {
@@ -179,7 +201,7 @@ export class SkillView extends CCComp {
finalRatio, finalRatio,
); );
} }
close_collider(){ close_collider() {
if (!this.collider) return; if (!this.collider) return;
if (this.pendingDisableCollider && !this.collider.enabled) return; if (this.pendingDisableCollider && !this.collider.enabled) return;
this.pendingDisableCollider = true; this.pendingDisableCollider = true;

View File

@@ -0,0 +1,83 @@
/**
* 一次性迁移脚本:把 SkillSet 中的 RType/EType/speed/time 刷入各技能 prefab 的 SkillView 序列化字段。
* 用法: node tools/sync-skill-prefab.js
* 注意: 直接改写 prefab JSON运行前请保证工作区已提交。
*/
const fs = require('fs');
const path = require('path');
const ROOT = path.resolve(__dirname, '..');
const SKILL_SET = path.join(ROOT, 'assets/script/game/common/config/SkillSet.ts');
const PREFAB_DIR = path.join(ROOT, 'assets/resources/game/skill/atk');
// SkillView 组件在 prefab 中的脚本类 cid
const SKILL_VIEW_CID = '57aabs7TE1J5obTAZczc+64';
const RTYPE = { linear: 0, bezier: 1, fixed: 2, fixedEnd: 3 };
const ETYPE = { animationEnd: 0, timeEnd: 1, collision: 2 };
/** 从 SkillSet.ts 解析 sp_name -> {runType, endType, speed, time} */
function parseSkillSet(src) {
const map = new Map();
// 匹配每个技能条目块
const entryRe = /\d+:\s*\{([\s\S]*?)\n\s*\},/g;
let m;
while ((m = entryRe.exec(src)) !== null) {
const body = m[1];
const sp = body.match(/sp_name:\s*"([^"]+)"/);
if (!sp) continue;
const spName = sp[1];
const rt = body.match(/RType:\s*RType\.(\w+)/);
const et = body.match(/EType:\s*EType\.(\w+)/);
const speed = body.match(/speed:\s*([\d.]+)/);
const time = body.match(/\btime:\s*([\d.]+)/);
const entry = {
runType: rt ? RTYPE[rt[1]] : undefined,
endType: et ? ETYPE[et[1]] : undefined,
speed: speed ? Number(speed[1]) : undefined,
time: time ? Number(time[1]) : 0,
};
// 多个技能可共用同一 sp_name保留首个非 undefined 组合
if (!map.has(spName)) map.set(spName, entry);
}
return map;
}
function main() {
const src = fs.readFileSync(SKILL_SET, 'utf8');
const confMap = parseSkillSet(src);
const files = fs.readdirSync(PREFAB_DIR).filter(f => f.endsWith('.prefab'));
const report = { updated: [], skipped: [], noConf: [] };
for (const file of files) {
const spName = path.basename(file, '.prefab');
const conf = confMap.get(spName);
const fp = path.join(PREFAB_DIR, file);
const json = JSON.parse(fs.readFileSync(fp, 'utf8'));
// 定位 SkillView 组件
const comp = json.find(o => o && o.__type__ === SKILL_VIEW_CID);
if (!comp) { report.skipped.push(file + ' (no SkillView)'); continue; }
if (!conf) { report.noConf.push(file); continue; }
if (conf.runType !== undefined) comp.runType = conf.runType;
if (conf.endType !== undefined) comp.endType = conf.endType;
if (conf.speed !== undefined) comp.speed = conf.speed;
comp.time = conf.time ?? 0;
fs.writeFileSync(fp, JSON.stringify(json, null, 2) + '\n', 'utf8');
report.updated.push(`${file} -> runType=${comp.runType} endType=${comp.endType} speed=${comp.speed} time=${comp.time}`);
}
console.log('=== updated ===');
report.updated.forEach(s => console.log(' ' + s));
console.log('=== no config matched ===');
report.noConf.forEach(s => console.log(' ' + s));
console.log('=== skipped ===');
report.skipped.forEach(s => console.log(' ' + s));
}
main();