5 Commits

Author SHA1 Message Date
panFD
fb2c67ccab refactor(hero system): 重构英雄升级与卡片展示逻辑
1.  重构英雄升级方法,移除外部传入所需碎片参数,改为从配置表自动读取
2.  简化CardLiteComp.setHeroByUuid,移除卡池等级参数,直接读取英雄静态配置
3.  新增ChipComp.setHeroIconByUuid,重构英雄图标渲染逻辑
4.  新增英雄详情面板的升级功能与碎片展示
5.  新增英雄成长变化的事件监听与面板刷新逻辑
2026-08-23 16:27:58 +08:00
panFD
6eb51c8535 feat(map): add hero card chip view component
新增了图鉴卡牌预制体组件ChipComp,负责渲染卡牌图标与背景底框,支持英雄卡动画播放和普通卡牌静态图标展示,同时提供了数据设置、清空等对外接口。
2026-08-23 16:10:06 +08:00
panFD
a7d2745843 fix(ui/button): 修复按钮预制体的Label组件丢失问题
将原本被误删的按钮文字Label组件及其依赖组件重新添加回预制体,修正了按钮显示异常的问题。同时附带更新了关联的资源图片ui3.png。
2026-08-23 15:34:17 +08:00
panFD
a985214cbb refactor: 更新技能描述与UI预制件配置
1.  调整所有技能info字段为更清晰的功能说明
2.  新增怪物普攻配置规范与overrides示例
3.  新增Lable、herosbg两个UI预制件资源
4.  调整ui5.plist的边框配置参数
2026-08-22 18:41:28 +08:00
panFD
3d2bba0cac docs(spec): 更新英雄专属武器系统设计文档
将原英雄个人装备系统设计文档重命名为英雄专属武器系统设计文档,更新了背景目标、数据结构、锻造重铸规则、局内集成、存档结构、UI交互等内容,将装备相关逻辑替换为专属武器逻辑,并完成现有光环卡改名适配。
2026-08-21 23:41:21 +08:00
20 changed files with 15741 additions and 5105 deletions

View File

@@ -0,0 +1,633 @@
[
{
"__type__": "cc.Prefab",
"_name": "Lable",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "Lable",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [
{
"__id__": 2
},
{
"__id__": 10
},
{
"__id__": 18
}
],
"_active": true,
"_components": [
{
"__id__": 26
}
],
"_prefab": {
"__id__": 28
},
"_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": 1073741824,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "Label_Tapered_01_White_Bg",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 3
},
{
"__id__": 5
},
{
"__id__": 7
}
],
"_prefab": {
"__id__": 9
},
"_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": 1073741824,
"_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": 200,
"height": 54
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "06bJQzIv9Dd4vvjRlqtfn3"
},
{
"__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": 77,
"g": 197,
"b": 105,
"a": 255
},
"_spriteFrame": {
"__uuid__": "dd7e2f04-f9b9-489b-8d38-b4971ad81910@18590",
"__expectedType__": "cc.SpriteFrame"
},
"_type": 1,
"_fillType": 0,
"_sizeMode": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_useGrayscale": false,
"_atlas": null,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "4ckA8btpNNTrqJr6S7VGRN"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": {
"__id__": 8
},
"_alignFlags": 40,
"_target": null,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_horizontalCenter": 0,
"_verticalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 89,
"_originalHeight": 0,
"_alignMode": 2,
"_lockFlags": 0,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "592revODJGOrQJj32Arnxr"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "21e8sFFaVI3oYQ54vWxkdn",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{
"__type__": "cc.Node",
"_name": "Label_Tapered_01_White_InnerBorder",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 11
},
{
"__id__": 13
},
{
"__id__": 15
}
],
"_prefab": {
"__id__": 17
},
"_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": 1073741824,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 10
},
"_enabled": true,
"__prefab": {
"__id__": 12
},
"_contentSize": {
"__type__": "cc.Size",
"width": 200,
"height": 45
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "8d3sM/DlJKPpJHNKbTBwEP"
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 10
},
"_enabled": true,
"__prefab": {
"__id__": 14
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 51
},
"_spriteFrame": {
"__uuid__": "dd7e2f04-f9b9-489b-8d38-b4971ad81910@cfe80",
"__expectedType__": "cc.SpriteFrame"
},
"_type": 1,
"_fillType": 0,
"_sizeMode": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_useGrayscale": false,
"_atlas": null,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "95EXzuxS5CdahoFLEeNtIp"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 10
},
"_enabled": true,
"__prefab": {
"__id__": 16
},
"_alignFlags": 40,
"_target": null,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_horizontalCenter": 0,
"_verticalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 81,
"_originalHeight": 0,
"_alignMode": 2,
"_lockFlags": 0,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "dfflaM1YREGY9ftJzTpija"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "1es6ydKGJP7qT9zPyBEfrd",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{
"__type__": "cc.Node",
"_name": "Label_Tapered_01_White_Deco",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 19
},
{
"__id__": 21
},
{
"__id__": 23
}
],
"_prefab": {
"__id__": 25
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": 1,
"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": 1073741824,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 18
},
"_enabled": true,
"__prefab": {
"__id__": 20
},
"_contentSize": {
"__type__": "cc.Size",
"width": 192,
"height": 44
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "17CdGbg9BG87rd0n06WZvm"
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 18
},
"_enabled": true,
"__prefab": {
"__id__": 22
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 88,
"g": 228,
"b": 122,
"a": 255
},
"_spriteFrame": {
"__uuid__": "dd7e2f04-f9b9-489b-8d38-b4971ad81910@73949",
"__expectedType__": "cc.SpriteFrame"
},
"_type": 1,
"_fillType": 0,
"_sizeMode": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_useGrayscale": false,
"_atlas": null,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "b1UpBBMc9Obp5MBENsf/W/"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 18
},
"_enabled": true,
"__prefab": {
"__id__": 24
},
"_alignFlags": 40,
"_target": null,
"_left": 4,
"_right": 4,
"_top": 27.5,
"_bottom": 27.5,
"_horizontalCenter": 0,
"_verticalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 52,
"_originalHeight": 45,
"_alignMode": 2,
"_lockFlags": 0,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "17bNCG+UxKUotgzWxR3XPV"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "2cPjrYHjlPkoVbCT2O80nK",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 27
},
"_contentSize": {
"__type__": "cc.Size",
"width": 200,
"height": 100
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "32q1bLzYBFr5SK8ZtIeSWI"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "40LEKxke9Hs6tfg2pVspXT",
"targetOverrides": null
}
]

View File

@@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "c85dc4d5-6ebf-4cee-aa3e-6c027334e622",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "Lable"
}
}

View File

@@ -785,10 +785,10 @@
"__id__": 35
},
{
"__id__": 41
"__id__": 53
},
{
"__id__": 59
"__id__": 71
}
],
"_active": true,
@@ -835,167 +835,6 @@
},
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "Label",
"_objFlags": 0,
"__editorExtras__": {
"mountedRoot": null
},
"_parent": {
"__id__": 34
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 36
},
{
"__id__": 38
}
],
"_prefab": {
"__id__": 40
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": 15,
"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": 1073741824,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 35
},
"_enabled": true,
"__prefab": {
"__id__": 37
},
"_contentSize": {
"__type__": "cc.Size",
"width": 54,
"height": 35.5
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "a4sqCI1VpI8YJnOwF8QknG"
},
{
"__type__": "cc.Label",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 35
},
"_enabled": true,
"__prefab": {
"__id__": 39
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_string": "刷新",
"_horizontalAlign": 1,
"_verticalAlign": 1,
"_actualFontSize": 25,
"_fontSize": 25,
"_fontFamily": "Arial",
"_lineHeight": 25,
"_overflow": 0,
"_enableWrapText": true,
"_font": null,
"_isSystemFontUsed": true,
"_spacingX": 0,
"_isItalic": false,
"_isBold": true,
"_isUnderline": false,
"_underlineHeight": 2,
"_cacheMode": 0,
"_enableOutline": true,
"_outlineColor": {
"__type__": "cc.Color",
"r": 0,
"g": 0,
"b": 0,
"a": 255
},
"_outlineWidth": 2,
"_enableShadow": false,
"_shadowColor": {
"__type__": "cc.Color",
"r": 0,
"g": 0,
"b": 0,
"a": 255
},
"_shadowOffset": {
"__type__": "cc.Vec2",
"x": 2,
"y": 2
},
"_shadowBlur": 2,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "cea0FpTiVBEprBOaYQFSav"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "28D4tFgVRPwbG9iXo3cRl7",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{
"__type__": "cc.Node",
"_name": "coin",
@@ -1008,28 +847,28 @@
},
"_children": [
{
"__id__": 42
"__id__": 36
},
{
"__id__": 48
"__id__": 42
}
],
"_active": true,
"_components": [
{
"__id__": 54
"__id__": 48
},
{
"__id__": 56
"__id__": 50
}
],
"_prefab": {
"__id__": 58
"__id__": 52
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": -17.75,
"y": 17.75,
"z": 0
},
"_lrot": {
@@ -1061,20 +900,20 @@
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 41
"__id__": 35
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 43
"__id__": 37
},
{
"__id__": 45
"__id__": 39
}
],
"_prefab": {
"__id__": 47
"__id__": 41
},
"_lpos": {
"__type__": "cc.Vec3",
@@ -1111,11 +950,11 @@
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 42
"__id__": 36
},
"_enabled": true,
"__prefab": {
"__id__": 44
"__id__": 38
},
"_contentSize": {
"__type__": "cc.Size",
@@ -1139,11 +978,11 @@
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 42
"__id__": 36
},
"_enabled": true,
"__prefab": {
"__id__": 46
"__id__": 40
},
"_customMaterial": null,
"_srcBlendFactor": 2,
@@ -1197,20 +1036,20 @@
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 41
"__id__": 35
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 49
"__id__": 43
},
{
"__id__": 51
"__id__": 45
}
],
"_prefab": {
"__id__": 53
"__id__": 47
},
"_lpos": {
"__type__": "cc.Vec3",
@@ -1247,11 +1086,11 @@
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 48
"__id__": 42
},
"_enabled": true,
"__prefab": {
"__id__": 50
"__id__": 44
},
"_contentSize": {
"__type__": "cc.Size",
@@ -1275,11 +1114,11 @@
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 48
"__id__": 42
},
"_enabled": true,
"__prefab": {
"__id__": 52
"__id__": 46
},
"_customMaterial": null,
"_srcBlendFactor": 2,
@@ -1356,11 +1195,11 @@
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 41
"__id__": 35
},
"_enabled": true,
"__prefab": {
"__id__": 55
"__id__": 49
},
"_contentSize": {
"__type__": "cc.Size",
@@ -1384,11 +1223,11 @@
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 41
"__id__": 35
},
"_enabled": true,
"__prefab": {
"__id__": 57
"__id__": 51
},
"_resizeMode": 1,
"_layoutType": 1,
@@ -1441,23 +1280,23 @@
},
"_children": [
{
"__id__": 60
"__id__": 54
},
{
"__id__": 66
"__id__": 60
}
],
"_active": false,
"_components": [
{
"__id__": 72
"__id__": 66
},
{
"__id__": 74
"__id__": 68
}
],
"_prefab": {
"__id__": 76
"__id__": 70
},
"_lpos": {
"__type__": "cc.Vec3",
@@ -1494,20 +1333,20 @@
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 59
"__id__": 53
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 61
"__id__": 55
},
{
"__id__": 63
"__id__": 57
}
],
"_prefab": {
"__id__": 65
"__id__": 59
},
"_lpos": {
"__type__": "cc.Vec3",
@@ -1544,11 +1383,11 @@
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 60
"__id__": 54
},
"_enabled": true,
"__prefab": {
"__id__": 62
"__id__": 56
},
"_contentSize": {
"__type__": "cc.Size",
@@ -1572,11 +1411,11 @@
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 60
"__id__": 54
},
"_enabled": true,
"__prefab": {
"__id__": 64
"__id__": 58
},
"_customMaterial": null,
"_srcBlendFactor": 2,
@@ -1633,20 +1472,20 @@
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 59
"__id__": 53
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 67
"__id__": 61
},
{
"__id__": 69
"__id__": 63
}
],
"_prefab": {
"__id__": 71
"__id__": 65
},
"_lpos": {
"__type__": "cc.Vec3",
@@ -1683,11 +1522,11 @@
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 66
"__id__": 60
},
"_enabled": true,
"__prefab": {
"__id__": 68
"__id__": 62
},
"_contentSize": {
"__type__": "cc.Size",
@@ -1711,11 +1550,11 @@
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 66
"__id__": 60
},
"_enabled": true,
"__prefab": {
"__id__": 70
"__id__": 64
},
"_customMaterial": null,
"_srcBlendFactor": 2,
@@ -1792,11 +1631,11 @@
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 59
"__id__": 53
},
"_enabled": true,
"__prefab": {
"__id__": 73
"__id__": 67
},
"_contentSize": {
"__type__": "cc.Size",
@@ -1820,11 +1659,11 @@
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 59
"__id__": 53
},
"_enabled": true,
"__prefab": {
"__id__": 75
"__id__": 69
},
"_resizeMode": 1,
"_layoutType": 1,
@@ -1865,6 +1704,167 @@
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{
"__type__": "cc.Node",
"_name": "Label",
"_objFlags": 0,
"__editorExtras__": {
"mountedRoot": null
},
"_parent": {
"__id__": 34
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 72
},
{
"__id__": 74
}
],
"_prefab": {
"__id__": 76
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": -15,
"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": 1073741824,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 71
},
"_enabled": true,
"__prefab": {
"__id__": 73
},
"_contentSize": {
"__type__": "cc.Size",
"width": 54,
"height": 35.5
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "a4sqCI1VpI8YJnOwF8QknG"
},
{
"__type__": "cc.Label",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 71
},
"_enabled": true,
"__prefab": {
"__id__": 75
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_string": "刷新",
"_horizontalAlign": 1,
"_verticalAlign": 1,
"_actualFontSize": 25,
"_fontSize": 25,
"_fontFamily": "Arial",
"_lineHeight": 25,
"_overflow": 0,
"_enableWrapText": true,
"_font": null,
"_isSystemFontUsed": true,
"_spacingX": 0,
"_isItalic": false,
"_isBold": true,
"_isUnderline": false,
"_underlineHeight": 2,
"_cacheMode": 0,
"_enableOutline": true,
"_outlineColor": {
"__type__": "cc.Color",
"r": 0,
"g": 0,
"b": 0,
"a": 255
},
"_outlineWidth": 2,
"_enableShadow": false,
"_shadowColor": {
"__type__": "cc.Color",
"r": 0,
"g": 0,
"b": 0,
"a": 255
},
"_shadowOffset": {
"__type__": "cc.Vec2",
"x": 2,
"y": 2
},
"_shadowBlur": 2,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "cea0FpTiVBEprBOaYQFSav"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "28D4tFgVRPwbG9iXo3cRl7",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{
"__type__": "cc.UITransform",
"_name": "",

View File

@@ -0,0 +1,672 @@
[
{
"__type__": "cc.Prefab",
"_name": "herosbg",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "herosbg",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [
{
"__id__": 2
},
{
"__id__": 10
},
{
"__id__": 18
}
],
"_active": true,
"_components": [
{
"__id__": 26
},
{
"__id__": 28
}
],
"_prefab": {
"__id__": 30
},
"_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": 1073741824,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "bg",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 3
},
{
"__id__": 5
},
{
"__id__": 7
}
],
"_prefab": {
"__id__": 9
},
"_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": 1073741824,
"_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": 720,
"height": 1280
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "66ZjkRl2JJuoQZiBfiCMCu"
},
{
"__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": 244,
"b": 0,
"a": 255
},
"_spriteFrame": {
"__uuid__": "7d8f9b89-4fd1-4c9f-a3ab-38ec7cded7ca@f9941",
"__expectedType__": "cc.SpriteFrame"
},
"_type": 0,
"_fillType": 0,
"_sizeMode": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_useGrayscale": false,
"_atlas": null,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "253QE7witBsbB6iYj7GHjO"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": {
"__id__": 8
},
"_alignFlags": 45,
"_target": null,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_horizontalCenter": 0,
"_verticalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 2,
"_originalHeight": 2,
"_alignMode": 2,
"_lockFlags": 0,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "aeT9KoTTRFWZdNtmLVvwyV"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "9eBnSBbxJPF7G44iYZdjjF",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{
"__type__": "cc.Node",
"_name": "Pattern01_l",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 11
},
{
"__id__": 13
},
{
"__id__": 15
}
],
"_prefab": {
"__id__": 17
},
"_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": 1073741824,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 10
},
"_enabled": true,
"__prefab": {
"__id__": 12
},
"_contentSize": {
"__type__": "cc.Size",
"width": 720,
"height": 1280
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "f3kCvKUwhEqr5HtLV9V27t"
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 10
},
"_enabled": true,
"__prefab": {
"__id__": 14
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 85
},
"_spriteFrame": {
"__uuid__": "cb93c900-b440-4571-91d1-7da1636e3d73@32ac8",
"__expectedType__": "cc.SpriteFrame"
},
"_type": 2,
"_fillType": 0,
"_sizeMode": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_useGrayscale": false,
"_atlas": null,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "015DHKMtpIrLoszvWeVn5S"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 10
},
"_enabled": true,
"__prefab": {
"__id__": 16
},
"_alignFlags": 45,
"_target": null,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_horizontalCenter": 0,
"_verticalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 305,
"_originalHeight": 287,
"_alignMode": 2,
"_lockFlags": 0,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "ffpm9zMVJLuZRfqpkGzK4K"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "daV2Ldkz1F7rfpCKnV7i2I",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{
"__type__": "cc.Node",
"_name": "Gradient_Panel01",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 19
},
{
"__id__": 21
},
{
"__id__": 23
}
],
"_prefab": {
"__id__": 25
},
"_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": 1073741824,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 18
},
"_enabled": true,
"__prefab": {
"__id__": 20
},
"_contentSize": {
"__type__": "cc.Size",
"width": 720,
"height": 1280
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "52mSf8VVRAbK1ZcheP8zBG"
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 18
},
"_enabled": true,
"__prefab": {
"__id__": 22
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 151,
"b": 18,
"a": 255
},
"_spriteFrame": {
"__uuid__": "cb93c900-b440-4571-91d1-7da1636e3d73@0cc10",
"__expectedType__": "cc.SpriteFrame"
},
"_type": 0,
"_fillType": 0,
"_sizeMode": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_useGrayscale": false,
"_atlas": null,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "9biHW3cOVCkb0JnJZjTlFV"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 18
},
"_enabled": true,
"__prefab": {
"__id__": 24
},
"_alignFlags": 45,
"_target": null,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_horizontalCenter": 0,
"_verticalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 4,
"_originalHeight": 661,
"_alignMode": 2,
"_lockFlags": 0,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "7agllM/8FKhaC3tBSzXjlC"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "92XCKB5MVN064Ck+45q3v/",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 27
},
"_contentSize": {
"__type__": "cc.Size",
"width": 720,
"height": 1280
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "7f41xFUPhJpqD5pstzmbk+"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 29
},
"_alignFlags": 45,
"_target": null,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_horizontalCenter": 0,
"_verticalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 100,
"_originalHeight": 100,
"_alignMode": 2,
"_lockFlags": 0,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "17Gdq34rlGzKlbhTp4ldAS"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "7228fRtBlHhKwOIL9H6qr/",
"targetOverrides": null
}
]

View File

@@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "4eaa0a36-b178-460f-a4b2-0e58e119ea63",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "herosbg"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "4b8fb686-b649-4525-9aae-df0e7369205b",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "clips"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 997 KiB

After

Width:  |  Height:  |  Size: 993 KiB

View File

@@ -118,8 +118,8 @@
"rawHeight": 54,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"borderLeft": 44.5,
"borderRight": 44.5,
"packable": true,
"pixelsToUnit": 100,
"pivotX": 0.5,
@@ -578,8 +578,8 @@
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"borderLeft": 26,
"borderRight": 26,
"packable": true,
"pixelsToUnit": 100,
"pivotX": 0.5,
@@ -4994,8 +4994,8 @@
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"borderLeft": 40.5,
"borderRight": 40.5,
"packable": true,
"pixelsToUnit": 100,
"pivotX": 0.5,
@@ -5040,8 +5040,8 @@
"rawHeight": 42,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"borderLeft": 34.5,
"borderRight": 34.5,
"packable": true,
"pixelsToUnit": 100,
"pivotX": 0.5,
@@ -5086,8 +5086,8 @@
"rawHeight": 42,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"borderLeft": 34.5,
"borderRight": 34.5,
"packable": true,
"pixelsToUnit": 100,
"pivotX": 0.5,

View File

@@ -8,7 +8,7 @@ import { GameEvent } from "./config/GameEvent";
import { GameScoreStats } from "./config/HeroAttrs";
import { mLogger } from "./Logger";
import { gameDataSync } from "./GameDataSync";
import { FightSet } from "./config/GameSet";
import { FightSet, HERO_UPGRADE_NEED_FRAGMENTS } from "./config/GameSet";
/**
* 用远程数据覆盖本地数据(统一方法)
@@ -351,13 +351,15 @@ export class SingletonModuleComp extends ecs.Comp {
}
/**
* 消耗碎片提升英雄局外等级
* 消耗碎片提升英雄局外等级(内部查表决定所需碎片数)
* @param uuid 英雄模板 uuid
* @param needFragments 本次升级所需碎片数量(由外部配置表计算)
* @returns 是否升级成功
* @returns 是否升级成功(已到满级或碎片不足时返回 false)
*/
upgradeHero(uuid: number, needFragments: number): boolean {
upgradeHero(uuid: number): boolean {
const growth = this.getHeroGrowth(uuid);
const needFragments = HERO_UPGRADE_NEED_FRAGMENTS[growth.lv + 1];
// 配置表中查不到下一级 = 已到满级
if (needFragments === undefined) return false;
if (growth.fragments < needFragments) return false;
growth.fragments -= needFragments;
growth.lv += 1;

View File

@@ -213,131 +213,131 @@ export const SkillSet: Record<number, SkillConfig> = {
6001: {
uuid: 6001, name: "飞剑", sp_name: "a2", icon: "Sword-FA_WP_Main_Sword_003_PurpleSilver", 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,
RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害",
RType: RType.bezier, EType: EType.collision, info: "剑抛射物",
},
6002: {
uuid: 6002, 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,
RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害",
RType: RType.bezier, EType: EType.collision, info: "匕首抛射物",
},
6003: {
uuid: 6003, 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,
RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害",
RType: RType.bezier, EType: EType.collision, info: "斧头抛射物",
},
// 普通攻击 近战普通攻击
6004: {
uuid: 6004, name: "攻击", sp_name: "atk1", 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,
RType: RType.bezier, EType: EType.collision, bck_chance: 100, info: "造成攻击力100%的伤害",
RType: RType.bezier, EType: EType.collision, bck_chance: 100, info: "只有碰撞体没有实体动画元素",
},
//中距 射手普通技能
6006: {
uuid: 6006, name: "射击", sp_name: "aw2", icon: "Stat_RangedAttack", 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, info: "造成攻击力100%的伤害",
RType: RType.bezier, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05, info: "箭抛射物",
},
6007: {
uuid: 6007, name: "蓝箭", sp_name: "aw1", icon: "Stat_RangedAttack", 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, info: "造成攻击力100%的伤害",
RType: RType.bezier, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05, info: "蓝箭抛射物",
},
6008: {
uuid: 6008, name: "红箭", sp_name: "aw3", icon: "Stat_RangedAttack", 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, info: "造成攻击力100%的伤害",
RType: RType.bezier, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05, info: "红箭抛射物",
},
// 远程,魔法师 辅助等普通技能
6009: {
uuid: 6009, name: "蓝珠", sp_name: "m1", icon: "Sub_Item-FA_WP_Sub_MagicBall_001_Blue", 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,
RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害",
RType: RType.bezier, EType: EType.collision, info: "蓝珠抛射物",
},
6010: {
uuid: 6010, name: "紫珠", sp_name: "m2", icon: " Sub_Item-FA_WP_Sub_MagicBall_001_Purple", 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,
RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害",
RType: RType.bezier, EType: EType.collision, info: "紫珠抛射物",
},
6011: {
uuid: 6011, name: "绿瓶", sp_name: "h1", icon: "Sub_Item-FA_WP_Sub_Potion_001_Green", 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,
RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害",
RType: RType.bezier, EType: EType.collision, info: "绿瓶抛射物",
},
6012: {
uuid: 6012, name: "红瓶", sp_name: "h2", icon: "Sub_Item-FA_WP_Sub_Potion_001_Red", 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,
RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害",
RType: RType.bezier, EType: EType.collision, info: "红瓶抛射物",
},
// ==================== 群体大招(按职业分段:6100-6149 坦克/战士、6150-6199 刺客/射手、6200-6249 法师/辅助) ====================
// 坦克/战士群体攻击大招
6100: {
uuid: 6100, name: "闪光斩", sp_name: "atk3", icon: "Stat_Attack_01", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max0",
DTType: DTType.single, ap: 150, hit_count: 5, 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: "对周围的敌人造成攻击力150%的伤害",//英雄配置技能的时候,可以叠加出血debuff
RType: RType.bezier, EType: EType.collision, info: "闪光斩动画",//英雄配置技能的时候,可以叠加出血debuff
},
6101: {
uuid: 6101, name: "裂气斩", sp_name: "atk2", icon: "Stat_Attack_01", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max0",
DTType: DTType.single, ap: 150, hit_count: 5, 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: "对周围的敌人造成攻击力150%的伤害",//英雄配置技能的时候,可以叠加击退
RType: RType.bezier, EType: EType.collision, info: "裂气斩动画",//英雄配置技能的时候,可以叠加击退
},
6102: {
uuid: 6102, name: "火焰斩", sp_name: "atk5", icon: "Stat_Attack_01", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max0",
DTType: DTType.single, ap: 150, hit_count: 5, 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: "对周围的敌人造成攻击力150%的伤害",//英雄配置技能的时候,可以叠加暴击debuff
RType: RType.bezier, EType: EType.collision, info: "火焰斩动画",//英雄配置技能的时候,可以叠加暴击debuff
},
6103: {
uuid: 6103, name: "闪电斩", sp_name: "atk5", icon: "Stat_Attack_01", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max0",
DTType: DTType.single, para: 30, ap: 150, hit_count: 5, 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: "对周围的敌人造成攻击力150%的伤害, 30%概率麻痹",//英雄配置技能的时候,可以疲惫触发闪电系追加技能
RType: RType.bezier, EType: EType.collision, info: "闪电斩动画",//英雄配置技能的时候,可以疲惫触发闪电系追加技能
},
6104: {
uuid: 6104, name: "开山斧", sp_name: "range2", icon: "Stat_Tripleshot", TGroup: TGroup.Enemy, readyAnm: "blues", endAnm: "", act: "max0",
DTType: DTType.range, stun: 0, ap: 300, 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, info: "召唤巨斧劈向前方敌人",//可以附加击晕增强
RType: RType.fixed, EType: EType.animationEnd, info: "开山斧劈下动画",//可以附加击晕增强
},
// 刺客/射手群体攻击大招
6150: {
uuid: 6150, name: "万箭齐发.冰", sp_name: "maxa1", icon: "Stat_RangedAttack", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max0",
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, info: "造成攻击力100%的伤害",
RType: RType.bezier, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05, info: "6个蓝箭抛射物",
},
6151: {
uuid: 6151, name: "万箭齐发.火", sp_name: "maxa2", icon: "Stat_RangedAttack", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max0",
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, info: "造成攻击力100%的伤害",
RType: RType.bezier, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05, info: "6个红箭抛射物",
},
// 法师/辅助群体攻击大招
6200: {
uuid: 6200, name: "火焰喷射", sp_name: "maxm1", icon: "Stat_RangedAttack", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max0",
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, info: "造成攻击力100%的伤害",
RType: RType.bezier, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05, info: "一个大火球",
},
6201: {
uuid: 6201, name: "大飓风", sp_name: "maxm2", icon: "Stat_Mana", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max1",
DTType: DTType.single, ap: 100, hit_count: 2, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote,
RType: RType.linear, EType: EType.collision, info: "造成攻击力100%的伤害, 高阶技能",
RType: RType.linear, EType: EType.collision, info: "一个飓风",
},
6202: {
uuid: 6202, name: "大毒气", sp_name: "maxm4", icon: "Stat_Mana", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max1",
DTType: DTType.single, ap: 100, hit_count: 2, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote,
RType: RType.linear, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05,info: "造成攻击力100%的伤害, 高阶技能",
RType: RType.linear, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05,info: "一个大毒气弹",
},
6203: {
uuid: 6203, name: "大能量波", sp_name: "maxm5", icon: "Stat_Mana", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max1",
DTType: DTType.single, ap: 100, hit_count: 2, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote,
RType: RType.linear, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05, info: "造成攻击力100%的伤害, 高阶技能",
RType: RType.linear, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05, info: "一个能量波",
},
6204: {
uuid: 6204, name: "大毒气弹", sp_name: "maxm6", icon: "Stat_Mana", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max1",
DTType: DTType.single, ap: 100, hit_count: 2, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote,
RType: RType.linear, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05,info: "造成攻击力100%的伤害, 高阶技能",
RType: RType.linear, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05,info: "一个大毒气弹",
},
//============================= ====== 辅助技能 回合技能 ====== ==========================
6301: {
uuid: 6301, name: "护盾", sp_name: "buff_wind", icon: "Stat_Defense", 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, info: "为伙伴/自己添加护盾, 可抵挡3次伤害",
RType: RType.fixed, EType: EType.animationEnd, info: "护盾动画",
},
6302: {
uuid: 6302, name: "治疗", sp_name: "buff_wind", icon: "Stat_Hp_01", TGroup: TGroup.Team, readyAnm: "up_green", endAnm: "", act: "atk",

View File

@@ -1,7 +1,7 @@
{
"schema_version": 2,
"generated_at": "2026-08-19T11:43:02.437Z",
"gen_hash": "46a818cb923f684b20f473c5c0beb2a3893b9f55",
"generated_at": "2026-08-21T13:19:33.023Z",
"gen_hash": "07f688f6142abfe995eae27afc41ee9c7c59a022",
"sections": [
{
"title": " // ========== 几何王国复刻英雄(5001~5009,依据 英雄设计指引.md) ==========",
@@ -27,6 +27,8 @@
" * 性能基准:1 级怪物与 1 级英雄单体性能持平 ——",
" * 近战怪基准 hp300/ap22/cd1.20,远程怪基准 hp160/ap28/cd1.20,",
" * 重型/Boss 以更高 hp 换取更低 DPS,承担\"墙\"与\"压场\"定位。",
" * 怪物普攻统一使用 SkillSet 基础单体攻击(6001~6012 段),",
" * 并通过 overrides.ap=100 显式声明伤害为攻击力的 100%。",
" * 运行时最终属性 = 本表基础值 × RogueConfig.MON_HP_MUL / MON_AP_MUL",
" * (Boss 额外 × BOSS_HP_BONUS_MUL),校准目标:整场战斗双方对砍 ≈ 30s。",
" */",
@@ -59,7 +61,10 @@
"overrides": {
"ap": 100,
"para": 30
}
},
"comment": [
" // 普攻:紫魔球底座 + overrides 注入麻痹"
]
},
{
"uuid": 6203,
@@ -72,7 +77,8 @@
"overrides": {
"ap": 250,
"bck": 30,
"para": 40
"para": 40,
"summon_count": 1
},
"lv_entries": [
{
@@ -80,7 +86,8 @@
"overrides": {
"ap": 250,
"bck": 60,
"para": 40
"para": 40,
"summon_count": 1
},
"s_lv": 2
},
@@ -90,7 +97,8 @@
"ap": 300,
"bck": 90,
"timed_buff_id": 7005,
"para": 50
"para": 50,
"summon_count": 2
},
"s_lv": 3
},
@@ -99,7 +107,8 @@
"overrides": {
"ap": 400,
"timed_buff_id": 7025,
"para": 70
"para": 70,
"summon_count": 3
},
"s_lv": 4
}
@@ -298,7 +307,8 @@
],
"overrides": {
"ap": 150,
"para": 40
"para": 40,
"summon_count": 1
},
"lv_entries": [
{
@@ -306,7 +316,8 @@
"overrides": {
"ap": 150,
"timed_buff_id": 7006,
"para": 40
"para": 40,
"summon_count": 1
},
"s_lv": 2
},
@@ -316,7 +327,8 @@
"ap": 180,
"timed_buff_id": 7006,
"buff_value": -15,
"para": 50
"para": 50,
"summon_count": 2
},
"s_lv": 3
},
@@ -326,7 +338,8 @@
"ap": 200,
"hit_count": 6,
"bck": 40,
"para": 60
"para": 60,
"summon_count": 3
},
"s_lv": 4
}
@@ -428,14 +441,16 @@
" // 大招:大能量波,独立 cd,按英雄等级分档成长"
],
"overrides": {
"ap": 150
"ap": 150,
"summon_count": 1
},
"lv_entries": [
{
"lv": 3,
"overrides": {
"ap": 150,
"frz": 15
"frz": 15,
"summon_count": 1
},
"s_lv": 2
},
@@ -444,7 +459,8 @@
"overrides": {
"ap": 180,
"frz": 30,
"hit_count": 8
"hit_count": 8,
"summon_count": 2
},
"s_lv": 3
},
@@ -452,7 +468,8 @@
"lv": 7,
"overrides": {
"ap": 200,
"timed_buff_id": 7003
"timed_buff_id": 7003,
"summon_count": 3
},
"s_lv": 4
}
@@ -538,14 +555,16 @@
],
"overrides": {
"TGroup": "Self",
"ap": 3
"ap": 3,
"summon_count": 1
},
"lv_entries": [
{
"lv": 3,
"overrides": {
"TGroup": "Self",
"ap": 5
"ap": 5,
"summon_count": 1
},
"s_lv": 2
},
@@ -553,7 +572,8 @@
"lv": 5,
"overrides": {
"TGroup": "Self",
"ap": 6
"ap": 6,
"summon_count": 2
},
"s_lv": 3
},
@@ -561,7 +581,8 @@
"lv": 7,
"overrides": {
"TGroup": "Self",
"ap": 8
"ap": 8,
"summon_count": 3
},
"s_lv": 4
}
@@ -698,14 +719,16 @@
],
"overrides": {
"TGroup": "Team",
"ap": 300
"ap": 300,
"summon_count": 1
},
"lv_entries": [
{
"lv": 3,
"overrides": {
"TGroup": "Team",
"ap": 400
"ap": 400,
"summon_count": 1
},
"s_lv": 2
},
@@ -713,7 +736,8 @@
"lv": 5,
"overrides": {
"TGroup": "Team",
"ap": 450
"ap": 450,
"summon_count": 2
},
"s_lv": 3
},
@@ -722,7 +746,8 @@
"overrides": {
"TGroup": "Team",
"ap": 450,
"timed_buff_id": 7010
"timed_buff_id": 7010,
"summon_count": 3
},
"s_lv": 4
}
@@ -825,14 +850,16 @@
" // 大招:气斩,独立 cd,按英雄等级分档成长"
],
"overrides": {
"ap": 150
"ap": 150,
"summon_count": 1
},
"lv_entries": [
{
"lv": 3,
"overrides": {
"ap": 150,
"timed_buff_id": 7002
"timed_buff_id": 7002,
"summon_count": 1
},
"s_lv": 2
},
@@ -842,7 +869,8 @@
"ap": 180,
"bck": 60,
"timed_buff_id": 7002,
"buff_value": 20
"buff_value": 20,
"summon_count": 2
},
"s_lv": 3
},
@@ -850,7 +878,8 @@
"lv": 7,
"overrides": {
"ap": 220,
"bck": 80
"bck": 80,
"summon_count": 3
},
"s_lv": 4
}
@@ -941,14 +970,16 @@
" // 大招:开山斧,独立 cd,按英雄等级分档成长"
],
"overrides": {
"ap": 300
"ap": 300,
"summon_count": 1
},
"lv_entries": [
{
"lv": 3,
"overrides": {
"ap": 300,
"stun": 20
"stun": 20,
"summon_count": 1
},
"s_lv": 2
},
@@ -957,7 +988,8 @@
"overrides": {
"ap": 350,
"stun": 35,
"hit_count": 8
"hit_count": 8,
"summon_count": 2
},
"s_lv": 3
},
@@ -965,7 +997,8 @@
"lv": 7,
"overrides": {
"ap": 400,
"timed_buff_id": 7004
"timed_buff_id": 7004,
"summon_count": 3
},
"s_lv": 4
}
@@ -1050,20 +1083,23 @@
" // 大招:气斩,独立 cd,按英雄等级分档成长"
],
"overrides": {
"ap": 150
"ap": 150,
"summon_count": 1
},
"lv_entries": [
{
"lv": 3,
"overrides": {
"ap": 180
"ap": 180,
"summon_count": 1
},
"s_lv": 2
},
{
"lv": 5,
"overrides": {
"ap": 200
"ap": 200,
"summon_count": 2
},
"s_lv": 3
},
@@ -1071,7 +1107,8 @@
"lv": 7,
"overrides": {
"ap": 220,
"bck": 40
"bck": 40,
"summon_count": 3
},
"s_lv": 4
}
@@ -1174,7 +1211,10 @@
"uuid": 6004,
"lv": 1,
"cd": "Slow",
"ccd": 0
"ccd": 0,
"overrides": {
"ap": 100
}
}
],
"info": "基础前排怪, 与1级近战英雄持平",
@@ -1224,7 +1264,10 @@
"uuid": 6004,
"lv": 1,
"cd": "VerySlow",
"ccd": 0
"ccd": 0,
"overrides": {
"ap": 100
}
}
],
"info": "重型坦克怪, 高HP低攻承伤位",
@@ -1249,7 +1292,10 @@
"uuid": 6006,
"lv": 1,
"cd": "Slow",
"ccd": 0
"ccd": 0,
"overrides": {
"ap": 100
}
}
],
"info": "后排输出怪, 与1级远程英雄持平",
@@ -1277,7 +1323,11 @@
"uuid": 6002,
"lv": 1,
"cd": "Normal",
"ccd": 0
"ccd": 0,
"overrides": {
"ap": 100,
"hit_count": 2
}
}
],
"info": "高攻速低HP刺客",
@@ -1302,7 +1352,10 @@
"uuid": 6004,
"lv": 1,
"cd": "VerySlow",
"ccd": 0
"ccd": 0,
"overrides": {
"ap": 100
}
}
],
"info": "前排MiniBoss级坦克",
@@ -1330,7 +1383,11 @@
"uuid": 6009,
"lv": 1,
"cd": "Slow",
"ccd": 0
"ccd": 0,
"overrides": {
"ap": 100,
"hit_count": 2
}
}
],
"info": "后排辅助法师怪",
@@ -1355,7 +1412,11 @@
"uuid": 6010,
"lv": 1,
"cd": "Slow",
"ccd": 0
"ccd": 0,
"overrides": {
"ap": 100,
"hit_count": 2
}
}
],
"info": "后排召唤系法师怪",
@@ -1380,7 +1441,10 @@
"uuid": 6004,
"lv": 1,
"cd": "Slow",
"ccd": 0
"ccd": 0,
"overrides": {
"ap": 100
}
}
],
"info": "前排Boss, 攻速型",
@@ -1410,7 +1474,10 @@
"uuid": 6004,
"lv": 1,
"cd": "VerySlow",
"ccd": 0
"ccd": 0,
"overrides": {
"ap": 100
}
}
],
"info": "前排Boss, 超高HP",
@@ -1435,7 +1502,11 @@
"uuid": 6009,
"lv": 1,
"cd": "Slow",
"ccd": 0
"ccd": 0,
"overrides": {
"ap": 100,
"hit_count": 2
}
}
],
"info": "后排法系Boss",
@@ -1460,7 +1531,10 @@
"uuid": 6004,
"lv": 1,
"cd": "Slow",
"ccd": 0
"ccd": 0,
"overrides": {
"ap": 100
}
}
],
"info": "后排位Boss, 均衡型",
@@ -1487,7 +1561,8 @@
"cd": "Slow",
"ccd": 0,
"overrides": {
"ap": 80,
"ap": 100,
"hit_count": 2,
"timed_buff_id": 7002
}
}
@@ -1514,7 +1589,10 @@
"uuid": 6004,
"lv": 1,
"cd": "VerySlow",
"ccd": 0
"ccd": 0,
"overrides": {
"ap": 100
}
}
],
"info": "前排终极Boss, 最高HP+高速",

View File

@@ -112,29 +112,22 @@ export class CardLiteComp extends CCComp {
}
/**
* 便捷方法:通过英雄 UUID 和卡池等级直接设置英雄卡。
* 自动从 CardPoolList 查找匹配的卡牌配置。
* 通过英雄 UUID 直接设置英雄卡(纯展示场景)。
* 从 HeroInfo 读取静态配置,不再依赖 CardPoolList。
* @param uuid 英雄 UUID
* @param cardLv 卡牌等级(默认 1)
*/
setHeroByUuid(uuid: number, cardLv: number = 1) {
const card = CardPoolList.find(c => c.uuid === uuid && c.card_lv === cardLv);
if (card) {
this.setData(card);
return;
}
setHeroByUuid(uuid: number) {
const hero = HeroInfo[uuid];
if (hero) {
this.setData({
uuid: hero.uuid,
type: CardType.Hero,
cost: 5,
weight: 25,
card_lv: cardLv,
kind: CKind.Hero,
hero_lv: smc.getHeroOuterLv(hero.uuid)
});
}
if (!hero) return;
this.setData({
uuid: hero.uuid,
type: CardType.Hero,
cost: 0,
weight: 0,
card_lv: hero.card_lv ?? 1,
kind: CKind.Hero,
hero_lv: smc.getHeroOuterLv(hero.uuid)
});
}
/** 查询当前是否有卡牌数据 */

View File

@@ -0,0 +1,254 @@
/**
* @file ChipComp.ts
* @description 英雄图鉴卡预制体组件(UI 视图层·精简版)
*
* 职责:
* 1. 根据卡牌配置渲染 **图标**(英雄卡为 idle 动画,其他卡为静态图集帧)。
* 2. 根据 card_lv / kind 渲染 **背景底框**。
*
* 说明:
* - 仅保留图标与背景渲染能力,名称、费用、等级等展示由外部组件负责。
* - 通过 iconVisualToken 防止异步动画加载竞态。
*
* 依赖:
* - CardConfig / CardType / CKind / CardPoolList(CardSet)
* - HeroInfo(heroSet)、SkillSet(SkillSet)
* - smc —— 全局单例,访问图标图集缓存
*/
import { mLogger } from "../common/Logger";
import { _decorator, Animation, AnimationClip, Node, Sprite, Vec3, resources } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { CardConfig, CardType, CKind, CardPoolList } from "../common/config/CardSet";
import { CardBgComp } from "./CardBgComp";
import { HeroInfo } from "../common/config/heroSet";
import { SkillSet } from "../common/config/SkillSet";
import { smc } from "../common/SingletonModuleComp";
const { ccclass, property } = _decorator;
/**
* ChipComp —— 单张卡牌图标/背景视图组件
*
* 挂载在图鉴卡预制体上,仅负责图标与背景的渲染。
*/
@ccclass('ChipComp')
@ecs.register('ChipComp', false)
export class ChipComp extends CCComp {
private debugMode: boolean = false;
// ======================== 编辑器绑定节点 ========================
@property(Node)
icon_node: Node = null!
@property(Node)
BG_node: Node = null!
// ======================== 运行时状态 ========================
card_uuid: number = 0
card_type: CardType = CardType.Hero
private cardData: CardConfig | null = null;
private iconVisualToken: number = 0;
// ======================== 生命周期 ========================
onLoad() {
if (!this.cardData) {
this.applyEmptyUI();
}
}
// ======================== 对外接口 ========================
/**
* 设置卡牌数据并渲染图标与背景。
* @param data 卡牌配置数据
*/
setData(data: CardConfig) {
if (!data) return;
this.cardData = data;
this.card_uuid = data.uuid;
this.card_type = data.type;
this.node.active = true;
this.applyCardUI();
mLogger.log(this.debugMode, "ChipComp", "setData", {
uuid: this.card_uuid,
type: this.card_type
});
}
/**
* 通过英雄 UUID 直接渲染英雄图标(自动播放 idle 动画并应用背景)。
* 适用于碎片、头像、图鉴等纯展示场景。
* @param uuid 英雄 UUID
*/
setHeroIconByUuid(uuid: number) {
const hero = HeroInfo[uuid];
if (!hero) return;
this.cardData = null;
this.card_uuid = uuid;
this.card_type = CardType.Hero;
this.node.active = true;
this.iconVisualToken += 1;
// 背景:按 HeroInfo.card_lv 应用英雄底框样式
if (this.BG_node) {
const cardLv = hero.card_lv ?? 1;
const kindName = CKind[CKind.Hero];
this.BG_node.children.forEach(child => {
child.active = (child.name === kindName);
const bg = child.getComponent(CardBgComp);
if (bg) child.active ? bg.apply(cardLv) : bg.clear();
});
}
// 图标:英雄 idle 动画(带镜像翻转)
if (this.icon_node) {
this.icon_node.setScale(new Vec3(-1.5, 1.5, 1));
this.updateHeroAnimation(this.icon_node, uuid, this.iconVisualToken);
}
}
/** 清空卡牌数据并重置 UI */
clear() {
this.cardData = null;
this.card_uuid = 0;
this.card_type = CardType.Hero;
this.applyEmptyUI();
this.node.active = false;
}
// ======================== UI 渲染 ========================
/** 渲染图标与背景 */
private applyCardUI() {
if (!this.cardData) {
this.applyEmptyUI();
return;
}
this.iconVisualToken += 1;
const kindName = CKind[this.cardData.kind];
// 背景:按 kind 显示对应底框,按 card_lv 应用等级样式
if (this.BG_node) {
const bgLv = this.cardData.base_card_lv ?? this.cardData.card_lv;
this.BG_node.children.forEach(child => {
child.active = (child.name === kindName);
const bg = child.getComponent(CardBgComp);
if (bg) child.active ? bg.apply(bgLv) : bg.clear();
});
}
// 图标:英雄卡播放 idle 动画,其他卡使用静态图集帧
if (this.icon_node) {
const iconNode = this.icon_node;
if (this.card_type === CardType.Hero) {
// 英雄图标做镜像翻转(原图朝右,卡面需朝左)
iconNode.setScale(new Vec3(-1.5, 1.5, 1));
this.updateHeroAnimation(iconNode, this.card_uuid, this.iconVisualToken);
return;
}
iconNode.setScale(new Vec3(1, 1, 1));
this.clearIconAnimation(iconNode);
const iconId = this.resolveCardIconId(this.card_type, this.card_uuid);
if (iconId) {
this.updateIcon(iconNode, iconId);
} else {
const sprite = iconNode.getComponent(Sprite) || iconNode.getComponentInChildren(Sprite);
if (sprite) sprite.spriteFrame = null;
}
}
}
/** 渲染空槽状态:清空图标与背景 */
private applyEmptyUI() {
this.iconVisualToken += 1;
if (this.BG_node) {
this.BG_node.children.forEach(child => {
child.active = false;
const bg = child.getComponent(CardBgComp);
if (bg) bg.clear();
});
}
if (this.icon_node) {
this.icon_node.setScale(new Vec3(1, 1, 1));
this.clearIconAnimation(this.icon_node);
const sprite = this.icon_node.getComponent(Sprite) || this.icon_node.getComponentInChildren(Sprite);
if (sprite) sprite.spriteFrame = null;
}
}
// ======================== 工具方法 ========================
/** 更新图标:从全局缓存图集中获取对应帧 */
private updateIcon(node: Node, iconId: string) {
if (!node || !iconId) return;
const sprite = node.getComponent(Sprite) || node.getComponentInChildren(Sprite);
if (!sprite) return;
if (smc.uiconsAtlas) {
const frame = smc.uiconsAtlas.getSpriteFrame(iconId);
sprite.spriteFrame = frame || null;
}
}
/** 根据卡牌类型和 UUID 解析出图标 ID(在 SpriteAtlas 中的帧名) */
private resolveCardIconId(type: CardType, uuid: number): string {
if (type === CardType.Skill) {
return SkillSet[uuid]?.icon || `${uuid}`;
}
if (type === CardType.Hero) {
return HeroInfo[uuid]?.icon || `${uuid}`;
}
return `${uuid}`;
}
/**
* 为英雄卡图标加载并播放 idle 动画。
* 使用 token 做竞态保护,确保异步回调时不会覆盖已更新的图标。
*/
private updateHeroAnimation(node: Node, uuid: number, token: number) {
const sprite = node?.getComponent(Sprite) || node?.getComponentInChildren(Sprite);
if (sprite) sprite.spriteFrame = null;
const hero = HeroInfo[uuid];
if (!hero) return;
const anim = node.getComponent(Animation) || node.addComponent(Animation);
this.clearAnimationClips(anim);
const path = `game/heros/hero/${hero.path}/idle`;
resources.load(path, AnimationClip, (err, clip) => {
if (err || !clip) {
mLogger.log(this.debugMode, "ChipComp", `load hero animation failed ${uuid}`, err);
return;
}
if (token !== this.iconVisualToken || !this.cardData || this.card_type !== CardType.Hero || this.card_uuid !== uuid) {
return;
}
this.clearAnimationClips(anim);
anim.addClip(clip);
anim.play("idle");
});
}
/** 清除图标节点上的动画(停止播放并移除所有 clip) */
private clearIconAnimation(node: Node) {
const anim = node?.getComponent(Animation);
if (!anim) return;
anim.stop();
this.clearAnimationClips(anim);
}
/** 移除 Animation 组件上的全部 AnimationClip */
private clearAnimationClips(anim: Animation) {
const clips = anim.clips as AnimationClip[] | undefined;
if (!clips || clips.length === 0) return;
[...clips].forEach(clip => anim.removeClip(clip, true));
}
// ======================== 生命周期钩子 ========================
/** ECS 组件移除时的释放钩子:销毁节点 */
reset() {
this.node.destroy();
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "dc823f36-51eb-405f-8361-7027eb49c8a6",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -25,8 +25,12 @@ import { mLogger } from "../common/Logger";
import { HeroInfo, HeroList } from "../common/config/heroSet";
import { buildSkillDesc } from "../common/config/HeroSkillDesc";
import { CKind } from "../common/config/CardSet";
import { GameEvent } from "../common/config/GameEvent";
import { HERO_UPGRADE_NEED_FRAGMENTS } from "../common/config/GameSet";
import { CardBgComp } from "./CardBgComp";
import { CardLiteComp } from "./CardLiteComp";
import { ChipComp } from "./ChipComp";
import { smc } from "../common/SingletonModuleComp";
const { property, ccclass } = _decorator;
@@ -41,6 +45,9 @@ export class HerosListComp extends CCComp {
@property(Node)
ap_node = null!
@property(Node)
def_node = null!
@property(Node)
hp_node = null!
@@ -69,6 +76,18 @@ export class HerosListComp extends CCComp {
@property(Node)
type_node = null!
/** 升级按钮节点 */
@property(Node)
upgrade_btn = null!
/** 碎片数量显示节点(Label) */
@property(Node)
fragment_node = null!
/** 碎片图标节点(挂载 ChipComp 用于渲染碎片图标) */
@property(Node)
chip_node = null!
// ======================== 运行时状态 ========================
huuid: number = 0
@@ -84,15 +103,49 @@ export class HerosListComp extends CCComp {
}
protected onEnable(): void {
oops.message.on(GameEvent.HERO_GROWTH_UPDATE, this.onGrowthUpdate, this)
if (this.cards_node && this.cards_node.children.length > 0) {
this.onCardSelect(this.huuid || HeroList[0])
}
}
protected onDisable(): void {
oops.message.off(GameEvent.HERO_GROWTH_UPDATE, this.onGrowthUpdate, this)
}
private onGrowthUpdate() {
if (this.huuid) {
this.updateHeroDetail(this.huuid)
}
}
closeHeros() {
this.node.active = false
}
/**
* 升级按钮点击回调
* 消耗碎片提升英雄局外等级,成功后刷新详情面板
*/
onUpgradeClick() {
const uuid = this.huuid
if (!uuid) return
const success = smc.upgradeHero(uuid)
if (success) {
mLogger.log(this.debugMode, "HerosListComp", `英雄 ${uuid} 升级成功`)
this.updateHeroDetail(uuid)
} else {
const growth = smc.getHeroGrowth(uuid)
const need = HERO_UPGRADE_NEED_FRAGMENTS[growth.lv + 1]
mLogger.log(this.debugMode, "HerosListComp", `英雄 ${uuid} 升级失败`, {
currentLv: growth.lv,
fragments: growth.fragments,
needFragments: need ?? "MAX",
})
}
}
// ======================== 卡片列表 ========================
private initCardList() {
@@ -136,7 +189,7 @@ export class HerosListComp extends CCComp {
})
const comp = cardNode.getComponent(CardLiteComp) || cardNode.addComponent(CardLiteComp)
comp.setHeroByUuid(uuid, hero.card_lv ?? 1)
comp.setHeroByUuid(uuid)
comp.onClickCallback = (cardComp: CardLiteComp) => {
this.onCardSelect(uuid)
this.highlightCard(cardNode)
@@ -197,6 +250,7 @@ export class HerosListComp extends CCComp {
const suffix = heroLv >= 2 ? "★".repeat(heroLv - 1) : ""
this.setLabelText(this.name_node, `${suffix}${hero.name || ""}${suffix}`)
this.setLabelText(this.ap_node, `${(hero.ap ?? 0) * heroLv}`)
this.setLabelText(this.def_node, `${(hero.def ?? 0) * heroLv}`)
this.setLabelText(this.hp_node, `${(hero.hp ?? 0) * heroLv}`)
this.updateCdDisplay(hero)
@@ -213,6 +267,7 @@ export class HerosListComp extends CCComp {
this.updateLvDisplay(hero)
this.updateTypeDisplay(hero)
this.updateHeroAnimation(uuid)
this.updateGrowthPanel(uuid)
}
private updatePoolLvBg(poolLv: number) {
@@ -261,6 +316,38 @@ export class HerosListComp extends CCComp {
})
}
/**
* 更新局外成长面板:碎片数量与升级按钮状态
* @param uuid 英雄模板 uuid
*/
private updateGrowthPanel(uuid: number) {
const growth = smc.getHeroGrowth(uuid)
const needFragments = HERO_UPGRADE_NEED_FRAGMENTS[growth.lv + 1]
const isMaxLv = needFragments === undefined
// 碎片数量显示:当前拥有 / 下一级所需(满级时显示 MAX)
if (this.fragment_node) {
const fragmentText = isMaxLv
? `${growth.fragments} / MAX`
: `${growth.fragments} / ${needFragments}`
this.setLabelText(this.fragment_node, fragmentText)
}
// 碎片图标:使用 ChipComp 渲染英雄图标(自动读取 HeroInfo 配置)
if (this.chip_node) {
const chipComp = this.chip_node.getComponent(ChipComp) || this.chip_node.addComponent(ChipComp)
chipComp.setHeroIconByUuid(uuid)
}
// 升级按钮状态:未满级且碎片足够时可用
if (this.upgrade_btn) {
const canUpgrade = !isMaxLv && growth.fragments >= needFragments
this.upgrade_btn.active = true
const btnComp = this.upgrade_btn.getComponent("cc.Button") as import("cc").Button | null
if (btnComp) btnComp.interactable = canUpgrade
}
}
// ======================== 英雄动画 ========================
private updateHeroAnimation(uuid: number) {

View File

@@ -1,33 +1,39 @@
# 英雄个人装备系统设计
# 英雄专属武器系统设计
- 日期:2026-08-21
- 状态:已评审(brainstorming 阶段用户逐节确认)
- 涉及文件:`HeroEquipSet.ts`(新增)、`heroSet.ts`、`HeroAttrs.ts`、`HeroAttrsComp.ts`、`SingletonModuleComp.ts`、`GameEvent.ts`、`EquipSet.ts`(改名 TalentSet)
- 涉及文件:`HeroWeaponSet.ts`(新增)、`heroSet.ts`、`HeroAttrs.ts`、`HeroAttrsComp.ts`、`SingletonModuleComp.ts`、`GameEvent.ts`、`GameSet.ts`、`EquipSet.ts`(改名 TalentSet)
## 1. 背景与目标
现有"装备"(`EquipSet.ts`,8701~8820 段)是**全体驻场光环卡**:购买后全队加属性,经 `EquipBoxComp → FieldSkillHelper` 全局聚合。
本设计新增**英雄个人装备**:每个英雄可装备**一件**装备,词条只作用于该英雄本身;与现有光环卡**并存**,光环卡在表述上改名为**战队天赋**。
本设计新增**英雄专属武器**:每个英雄天生绑定一件专属武器,不可卸下、不可更换;词条只作用于该英雄本身;与现有光环卡**并存**,光环卡在表述上改名为**战队天赋**。
核心特性:
- 装备在**玩家获得时**(开箱子 / 抽卡)随机生成词条并固定(暗黑式:从词条池随机抽 N 条、数值在区间内随机)。
- **词条数量与数值高低决定装备品质**。
- 装备是**局外资产**,随云存档持久化;局内只有战斗,不产生、不修改装备,开局快照生效。
## 2. 数据结构(HeroEquipSet.ts,新增)
- 武器通过**锻造**成长:每次锻造 = 等级 +1,并从词条池加权随机获得 1 条词条(暗黑式:数值在区间内随机)。
- 抽中**已有词条则数值累加**,新词条则新增一条。
- 等级上限 **16 级**;**特定里程碑等级必得该英雄专属词条**(数值随机,合并到同 attr)。
- 0 级白板武器自带 1 条**初始专属词条**。
- **品质按等级阶梯跃升**,与词条数脱钩。
- **重铸**:看广告将武器归零(0 级 0 随机词条),已投入材料全部返还,初始专属词条重新 roll。
- 武器是**局外资产**,随云存档持久化;局内只有战斗,不产生、不修改武器,开局快照生效。
位置:`assets/script/game/common/config/HeroEquipSet.ts`,与 `EquipSet.ts`(将改名 `TalentSet.ts`)平级。
## 2. 数据结构(HeroWeaponSet.ts,新增)
位置:`assets/script/game/common/config/HeroWeaponSet.ts`,与 `EquipSet.ts`(将改名 `TalentSet.ts`)平级。
```typescript
import { Attrs } from "./HeroAttrs";
/** 装备品质(由词条数推导:1=普通 2=稀有 3=史诗 4=传说) */
export enum EquipQuality {
Normal = 1,
Rare = 2,
Epic = 3,
Legend = 4,
/** 武器品质(按等级阶梯推导,不存储) */
export enum WeaponQuality {
Fine = 1, // 优秀(绿)0~3 级
Superior = 2, // 精良(蓝)4~7 级
Epic = 3, // 史诗(紫)8~11 级
Legend = 4, // 传说(橙)12~15 级
Unique = 5, // 唯一(红)16 级满级
}
/** 词条池条目:attr 指向 Attrs 枚举,roll 时 value 在 [min, max] 内随机 */
@@ -38,125 +44,129 @@ export interface AffixPoolEntry {
weight: number; // 抽取权重
}
/** 装备底座:只定义随机规则,不含固定词条(段位 9001-9099) */
export interface HeroEquipBase {
base_id: number;
name: string;
icon: string;
affix_count: [number, number]; // 词条数区间,如 [1,2]
affix_pool: AffixPoolEntry[];
/** 专属词条里程碑:到达 level 必得,value 在 [min, max] 内随机后合并到同 attr */
export interface ExclusiveAffix {
level: number; // 0=初始自带;1~16=锻造到达解锁
attr: Attrs;
min: number;
max: number;
}
/** 装备实例(roll 生成后固定;不冗余存 name/icon,查询走底座表) */
export interface HeroEquipInstance {
inst_id: number; // 实例唯一 id(equip_next_id 自增)
base_id: number;
affixes: { attr: Attrs; value: number }[]; // quality = affixes.length,不单独存储
}
/** 装备箱子配置(段位 8901-8999,2 档) */
export interface EquipBoxConfig {
uuid: number;
/** 武器底座:key=英雄模板 uuid(段位 9001-9099),只定义规则不含实例 */
export interface HeroWeaponBase {
hero_uuid: number;
name: string;
icon: string;
pool: { base_id: number; weight: number }[]; // 底座加权池
affix_pool: AffixPoolEntry[]; // 随机词条池(attr 白名单见第 4.4 节)
exclusive: ExclusiveAffix[]; // 专属词条里程碑,按 level 升序,必含 1 条 level=0
forge_cost: { item_id: number; count: number }[]; // 单次锻造材料(各级同价)
}
/** 武器状态:挂在英雄存档上,局外持久化;同 attr 词条已合并 */
export interface HeroWeaponState {
level: number; // = 已锻造次数,0=未锻造白板,上限 16
affixes: { attr: Attrs; value: number }[]; // 随机词条+专属词条,同 attr 已累加合并
invested: { item_id: number; count: number }[]; // 累计已投入材料(重铸全量返还用)
}
```
### 品质阶梯
| 等级 | 品质 | 颜色 |
|------|------|------|
| 0~3 | 优秀(Fine) | 绿 |
| 4~7 | 精良(Superior) | 蓝 |
| 8~11 | 史诗(Epic) | 紫 |
| 12~15 | 传说(Legend) | 橙 |
| 16 | 唯一(Unique) | 红 |
```typescript
/** 按武器等级推导品质(不存储,实时推导) */
export function getWeaponQuality(level: number): WeaponQuality
```
### 词条口径(与现有百分比口径一致)
- **数值型**(仅 `ap` / `hp_max` / `defense`):Flat 数值,roll 取**整数**。
- **概率型**(其余全部):百分点,roll 取 **1 位小数**。
- 词条池仅允许出现第 4.4 节白名单中的 attr,配置时校验。
- 词条池与专属词条仅允许出现第 4.4 节白名单中的 attr,配置加载时校验。
### 品质规则
## 3. 锻造与重铸
- `quality = 词条数`(1~4 对应普通~传说),初版从简;数值高低不参与品质,后续可扩展档位评分。
## 3. Roll 生成与获取途径
### 3.1 核心纯函数(HeroEquipSet.ts)
### 3.1 核心纯函数(HeroWeaponSet.ts)
```typescript
/**
* 获得装备时调用:按底座规则 roll 出一件词条固定的装备实例
* @param base_id 装备底座 id
* @param instId 实例 id(由 SingletonModuleComp 分配)
* 锻造一次:等级+1 → 从 affix_pool 加权抽 1 条词条合并(已有 attr 数值累加,新 attr 新增)
* → 若新等级命中 exclusive 里程碑,roll 专属词条数值并合并到同 attr
* @param base 武器底座
* @param state 当前武器状态(level < 16)
* @returns 新状态;base 非法或已满级返回 null 并 mLogger.warn
*/
export function rollHeroEquip(base_id: number, instId: number): HeroEquipInstance | null
```
export function forgeWeapon(base: HeroWeaponBase, state: HeroWeaponState): HeroWeaponState | null
Roll 流程:
1. `affix_count: [min, max]` 内均匀随机词条数 N。
2. 从 `affix_pool` 按 weight 加权**不放回**抽 N 条不同 attr(同装备不重复属性)。
3. 每条词条在 `[min, max]` 内随机(数值型取整,概率型 1 位小数)。
4. 品质 = N。
```typescript
/**
* 按底座池加权抽取并 roll 出 count 件装备(箱子/抽卡统一入口)
* @param pool 底座加权池
* @param count 抽取件数
* @param allocInstId 实例 id 分配器(每次调用返回新 id)
* @param guaranteeMinQuality N 连保底品质(0=不保底)
* 初始化武器:0 级白板 + roll level=0 的初始专属词条(获得英雄/懒初始化时调用)
*/
export function rollEquipPool(
pool: { base_id: number; weight: number }[],
count: number,
allocInstId: () => number,
guaranteeMinQuality: EquipQuality = 0,
): HeroEquipInstance[]
export function initWeapon(base: HeroWeaponBase): HeroWeaponState
/**
* 重铸:等级与随机词条清零,invested 全量返还,初始专属词条(level=0)重新 roll
* @returns 新状态 + 应返还材料列表(= 原 invested 全量)
*/
export function reforgeWeapon(base: HeroWeaponBase, state: HeroWeaponState): {
state: HeroWeaponState;
refund: { item_id: number; count: number }[];
}
```
保底逻辑:当 `count >= GACHA_COUNT` 且全部 < `guaranteeMinQuality` 时,最后一件重 roll 至 ≥ 保底品质。
锻造流程:
1. `level+1`。
2. 从 `affix_pool` 按 weight 加权抽 1 条 attr;在 `[min, max]` 内随机(数值型取整,概率型 1 位小数)。
3. 该 attr 已存在于 `affixes` → 数值累加;否则新增一条。
4. 若 `exclusive` 中存在 `level == 新等级` 的条目 → 每条在 `[min, max]` 内随机并累加到同 attr(不存在则新增)。
5. `invested` 累加本次 `forge_cost`。
### 3.2 可调参数(GameSet.ts)
```typescript
GACHA_COUNT = 10, // N 连连抽数(后期可调 20/30)
GACHA_MAX_DRAW = 10, // 单次最多一起抽的张数
GACHA_GUARANTEE_QUALITY = 2, // N 连保底品质(稀有)
MAX_WEAPON_LEVEL = 16, // 武器锻造等级上限
```
### 3.3 双获取通道
### 3.3 材料与货币
| 途径 | 流程 | 产出 |
|------|------|------|
| **装备箱子**(2 档:普通箱/高级箱) | 商店购买/奖励 → `equip_boxes` 库存 → 背包界面点击开箱 | 固定 1 件,走 `rollEquipPool(box.pool, 1)` |
| **抽卡**(消耗装备抽卡券) | 抽卡界面选 1 抽 / N 连(默认 10,≤ GACHA_MAX_DRAW)→ 消耗 `equip_tickets` | N 件,走 `rollEquipPool(gachaPool, N, 保底)` |
- 高级箱与普通箱的差异仅为 `pool` 中底座权重(高词条数底座权重更高)。
- 单局结算奖励可发放:箱子(入 `equip_boxes`)和/或装备抽卡券(入 `equip_tickets`)。
- 锻造材料为通用道具(如"精铁"),走现有道具库存;`forge_cost` 各级同价(递增为后续扩展,见 YAGNI)。
- 重铸不消耗材料,改为**看激励视频广告**:广告播放完成回调成功后才执行 `reforgeWeapon`;`invested` 中材料全量返还道具库存。
## 4. 局内集成(HeroAttrsComp)
**原则:局内快照,只读生效。** 开战创建英雄实体时快照装备词条,局内不参与装备增删改。
**原则:局内快照,只读生效。** 开战创建英雄实体时快照武器词条,局内不参与武器增删改。
### 4.1 快照字段
```typescript
// HeroAttrsComp 新增
/** 装备词条加成缓存(局外穿戴装备在开局时快照;数值型=flat,概率型=百分点) */
/** 武器词条加成缓存(局外武器在开局时快照;数值型=flat,概率型=百分点) */
equip_mods: Partial<Record<Attrs, number>> = {};
```
- 不存 `HeroEquipInstance`,只存"每条属性加了多少"的聚合结果(同 attr 多词条快照时已累加)。
- 不存 `HeroWeaponState`,只存"每条属性加了多少"的聚合结果(`affixes` 已同 attr 合并,直接遍历即可)。
- `reset()` 中清空。
- 局内 UI 若要显示装备名,从 `hero_equips` 反查,不影响战斗数据。
- 局内 UI 若要显示武器名,从 `hero_weapons` 反查,不影响战斗数据。
### 4.2 快照时机
英雄实体初始化(读 `HeroInfo` 填充属性的同一入口处)追加:
```typescript
const instId = smc.data.hero_equips[hero_uuid];
const inst = instId ? smc.data.equips[instId] : null;
attrsComp.equip_mods = aggregateAffixes(inst); // HeroEquipSet.ts 纯函数,UI 属性预览可复用
const weapon = smc.getHeroWeapon(hero_uuid);
attrsComp.equip_mods = aggregateWeaponAffixes(weapon); // HeroWeaponSet.ts 纯函数,UI 属性预览可复用
```
### 4.3 结算接入(最小侵入,每个 getFinal 加一项)
**数值型**:装备 flat **先进基础值,再吃驻场光环百分比**(乘算放大,装备更值钱):
**数值型**:武器 flat **先进基础值,再吃驻场光环百分比**(乘算放大,武器更值钱):
```typescript
public getFinalAp(): number {
@@ -167,9 +177,9 @@ public getFinalAp(): number {
}
```
顺序:装备 flat → 驻场光环 % → 计时 buff。同理 `getFinalHpMax`、`getFinalDefense`。
顺序:武器 flat → 驻场光环 % → 计时 buff。同理 `getFinalHpMax`、`getFinalDefense`。
**概率型**:百分点直接累加(`base + equip + timed`):
**概率型**:百分点直接累加(`base + weapon + timed`):
```typescript
public getFinalCritical(): number {
@@ -197,66 +207,44 @@ public getFinalCritical(): number {
```typescript
data: any = {
// ...现有字段
/** 玩家装备库:key=inst_id;局外资产随云存档持久化 */
equips: {} as Record<number, HeroEquipInstance>,
/** 实例 id 自增计数器(云端同步,防 id 冲突) */
equip_next_id: 1,
/** 英雄穿戴表:key=英雄模板 uuid,value=inst_id(0=未穿戴) */
hero_equips: {} as Record<number, number>,
/** 装备箱子库存:key=箱子 uuid,value=数量 */
equip_boxes: {} as Record<number, number>,
/** 装备抽卡券数量 */
equip_tickets: 0,
/** 英雄武器状态:key=英雄模板 uuid;局外资产随云存档持久化,懒初始化 */
hero_weapons: {} as Record<number, HeroWeaponState>,
}
```
`GameDate` 接口同步补充上述可选字段。
**数据量评估**:每件装备实例 JSON 约 60~80 字节(只存 `inst_id/base_id/affixes`,不冗余存 name/icon);500 件 ≈ 40KB,远低于微信云存储 1MB 单记录上限。`quality` 不存储(= `affixes.length`)。
**数据量评估**:每件武器 JSON 约 40~60 字节(只存 `level/affixes/invested`);50 英雄 ≈ 3KB,远低于微信云存储 1MB 单记录上限。品质不存储(= `getWeaponQuality(level)` 实时推导)。
### 数据操作方法(封装在 SingletonModuleComp,UI 不直改数据)
```typescript
addEquipInstances(insts: HeroEquipInstance[]): void // 入库 + markDataDirty + Equip_Update
wearEquip(heroUuid: number, instId: number): boolean // 穿戴/替换,旧装自动回库
unwearEquip(heroUuid: number): void
consumeEquipBox(boxUuid: number): HeroEquipInstance | null // 开箱:扣库存→roll→入库→返回
drawEquips(count: number): HeroEquipInstance[] | null // 抽卡:扣券→roll(保底)→入库
addEquipTickets(n: number): void
addEquipBox(boxUuid: number, n: number): void
getHeroWeapon(heroUuid: number): HeroWeaponState // 懒初始化:无记录时按底座 initWeapon 生成 0 级白板
forgeHeroWeapon(heroUuid: number): boolean // 校验满级/材料 → 扣材料 → forgeWeapon → 累加 invested → markDataDirty + HeroWeapon_Update
reforgeHeroWeapon(heroUuid: number): boolean // 广告成功回调内调用 → 返还 invested 全量 → reforgeWeapon → markDataDirty + HeroWeapon_Update
```
每个方法内部 `gameDataSync.markDataDirty()` + `oops.message.dispatchEvent` 对应事件。
每个方法内部 `gameDataSync.markDataDirty()` + `oops.message.dispatchEvent(GameEvent.HeroWeapon_Update)`。
### 新增事件(GameEvent.ts)
```typescript
static Equip_Update = "Equip_Update"; // 装备库/穿戴表变更(背包/英雄界面刷新)
static EquipBox_Update = "EquipBox_Update"; // 箱子数量变更
static EquipTicket_Update = "EquipTicket_Update"; // 抽卡券数量变更
static HeroWeapon_Update = "HeroWeapon_Update"; // 武器锻造/重铸变更(英雄界面刷新)
```
监听方必须在 `onDestroy`/`onDisable` 注销(oops 规范)。
## 6. UI 与交互
### 6.1 英雄界面(唯一穿戴入口)
### 6.1 英雄界面 · 武器页签(唯一操作入口)
- 英雄详情面板新增**装备槽**(属性区附近):空槽显示 `+`,已穿戴显示装备图标+品质边框。
- **穿戴/换装**:点击装备槽 → 弹出装备选择层,仅列**未被任何英雄穿戴**的装备(按品质排序)→ 点击即穿戴/替换(旧装回库)。
- **卸下**:已穿戴时选择层提供【卸下】按钮。
- 已被其他英雄穿戴的装备在选择层中**不显示**。
- 英雄详情面板新增**武器页签**:武器图标 + 品质边框(按等级变色)+ 等级(x/16)+ 当前词条列表(attr 名 + 数值)。
- 【锻造】按钮:显示本次材料消耗;材料不足或满级(16 级)置灰;点击 → 扣材料锻造 → 弹出结果浮层,高亮本次新增/累加的词条变化与品质跃升提示。
- 【重铸】按钮:弹确认框(说明"观看广告重置武器,全部锻造材料返还")→ 调激励视频广告 → 播放完成回调成功后执行重铸并展示返还材料。
### 6.2 装备背包界面(资产总览 + 开箱)
### 6.2 不做独立武器背包
- 入口:主界面"装备"按钮(复用 `tip_done.equip` 引导标记)。
- 布局:装备网格列表(按品质:传说→史诗→稀有→普通;已穿戴的标记穿戴英雄头像角标)+ 点击看词条详情;顶部**箱子区**(普通箱/高级箱图标+数量),点击开箱 → 展示战利品 → 入库。
### 6.3 抽卡界面
- 入口:商店界面新增"装备抽卡"页签。
- 【抽 1 次】= 1 张券;【抽 N 次】= N 张券(N 显示当前 `GACHA_COUNT`);券不足按钮置灰。
- 结果浮层:网格展示 N 件装备(图标+品质色),点击看词条;保底装备高亮"保底"标记。
武器与英雄强绑定,无装备网格列表、无穿戴选择层;武器信息只在英雄界面展示。
## 7. 现有光环卡改名"战队天赋"
@@ -266,16 +254,17 @@ static EquipTicket_Update = "EquipTicket_Update"; // 抽卡券数量变更
## 8. 错误处理与边界
- `rollHeroEquip` 对未知 `base_id` 返回 `null` 并 `mLogger.warn`;`rollEquipPool` 空池返回空数组。
- 穿戴时 `instId` 不存在(云端数据异常)→ `wearEquip` 返回 false,不崩溃。
- 英雄被穿戴的装备在库中不存在 → 快照时按无装备处理(`equip_mods = {}`)。
- 词条池 attr 不在白名单 → 配置加载时 `mLogger.warn` 并跳过该词条。
- 旧存档无 `equips` 等新字段 → `Object.assign` 合并后由访问方兜底初始化(参照 `getHeroGrowth` 的懒初始化模式)。
- `forgeWeapon` 对未知 `hero_uuid` 底座或已满级(16 级)返回 `null` 并 `mLogger.warn`;`forgeHeroWeapon` 材料不足返回 false,不扣材料。
- 存档中 `hero_weapons[hero_uuid]` 存在但底座表无对应配置(云端数据异常)→ 快照时按 0 级白板处理(`equip_mods = {}`)。
- 词条池 / 专属词条 attr 不在白名单 → 配置加载时 `mLogger.warn` 并跳过该词条。
- 旧存档无 `hero_weapons` 字段 → `Object.assign` 合并后由 `getHeroWeapon` 懒初始化兜底(参照 `getHeroGrowth` 的懒初始化模式)。
- 重铸广告播放失败/中途关闭 → 不执行重铸,数据不变。
- `invested` 与 `level × forge_cost` 不一致(异常数据)→ 重铸以 `invested` 记录为准。
## 9. 不做的事(YAGNI)
- 跨局账号级装备强化/分解/合成系统。
- 装备部位(武器/盔甲等多槽位)——当前每英雄仅 1 槽。
- 数值档位评分影响品质(初版品质=词条数)。
- 局内掉落/换装。
- 词条重 roll(洗练)。
- 武器卸下/更换/交易;多武器槽位。
- 词条锁定(洗单词条保留其他词条)。
- 锻造材料随等级递增(初版各级同价)。
- 词条重 roll(洗练)——重铸全洗已覆盖该需求。
- 局内掉落/换武器。