Merge origin/card0614 into card0614

合并远程药水限时强化系统与本地驻场光环配置,保留双方
BuffSet 新增条目(7111-7113 战前强攻 + 7010-7019
玩家计时性强化)。
This commit is contained in:
pan
2026-07-24 10:26:04 +08:00
18 changed files with 9520 additions and 5356 deletions

View File

@@ -31,29 +31,29 @@
"__id__": 64 "__id__": 64
}, },
{ {
"__id__": 90 "__id__": 96
}, },
{ {
"__id__": 98 "__id__": 104
}, },
{ {
"__id__": 116 "__id__": 122
} }
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 132 "__id__": 138
}, },
{ {
"__id__": 134 "__id__": 140
}, },
{ {
"__id__": 136 "__id__": 142
} }
], ],
"_prefab": { "_prefab": {
"__id__": 144 "__id__": 150
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -215,7 +215,7 @@
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 714, "width": 714,
"height": 94 "height": 114
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -565,7 +565,7 @@
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 712, "width": 712,
"height": 91 "height": 111
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -740,7 +740,7 @@
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 720, "width": 720,
"height": 100 "height": 120
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -862,7 +862,7 @@
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 720, "width": 720,
"height": 100 "height": 120
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -1023,7 +1023,7 @@
}, },
"_alignFlags": 8, "_alignFlags": 8,
"_target": null, "_target": null,
"_left": 10.696000000000026, "_left": 13.908000000000015,
"_right": 0, "_right": 0,
"_top": 0, "_top": 0,
"_bottom": 0, "_bottom": 0,
@@ -1071,8 +1071,8 @@
], ],
"value": { "value": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": -309.304, "x": -306.092,
"y": 0, "y": 2.693,
"z": 0 "z": 0
} }
}, },
@@ -1171,8 +1171,8 @@
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": -271.748, "x": -265.787,
"y": 16.571, "y": 38.564,
"z": 0 "z": 0
}, },
"_lrot": { "_lrot": {
@@ -1212,7 +1212,7 @@
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 104, "width": 84,
"height": 54.4 "height": 54.4
}, },
"_anchorPoint": { "_anchorPoint": {
@@ -1251,8 +1251,8 @@
"_string": "武器名称", "_string": "武器名称",
"_horizontalAlign": 0, "_horizontalAlign": 0,
"_verticalAlign": 1, "_verticalAlign": 1,
"_actualFontSize": 25, "_actualFontSize": 20,
"_fontSize": 25, "_fontSize": 20,
"_fontFamily": "Arial", "_fontFamily": "Arial",
"_lineHeight": 40, "_lineHeight": 40,
"_overflow": 0, "_overflow": 0,
@@ -1308,7 +1308,7 @@
}, },
"_alignFlags": 8, "_alignFlags": 8,
"_target": null, "_target": null,
"_left": 88.25200000000001, "_left": 94.21300000000002,
"_right": 0, "_right": 0,
"_top": 0, "_top": 0,
"_bottom": 0, "_bottom": 0,
@@ -1356,31 +1356,31 @@
"__id__": 65 "__id__": 65
}, },
{ {
"__id__": 71 "__id__": 73
}, },
{ {
"__id__": 77 "__id__": 81
} }
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 83 "__id__": 89
}, },
{ {
"__id__": 85 "__id__": 91
}, },
{ {
"__id__": 87 "__id__": 93
} }
], ],
"_prefab": { "_prefab": {
"__id__": 89 "__id__": 95
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": -160, "x": -265,
"y": 0, "y": -11.445000000000007,
"z": 0 "z": 0
}, },
"_lrot": { "_lrot": {
@@ -1422,10 +1422,13 @@
}, },
{ {
"__id__": 68 "__id__": 68
},
{
"__id__": 70
} }
], ],
"_prefab": { "_prefab": {
"__id__": 70 "__id__": 72
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -1470,7 +1473,7 @@
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 300, "width": 500,
"height": 23.333333333333332 "height": 23.333333333333332
}, },
"_anchorPoint": { "_anchorPoint": {
@@ -1552,6 +1555,42 @@
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
"fileId": "b5sZHO3gNIW76AXUeqZYBn" "fileId": "b5sZHO3gNIW76AXUeqZYBn"
}, },
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 65
},
"_enabled": true,
"__prefab": {
"__id__": 71
},
"_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": 300,
"_originalHeight": 0,
"_alignMode": 2,
"_lockFlags": 0,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "90OrNvrelLZbOIOrrDJnEv"
},
{ {
"__type__": "cc.PrefabInfo", "__type__": "cc.PrefabInfo",
"root": { "root": {
@@ -1577,14 +1616,17 @@
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 72 "__id__": 74
}, },
{ {
"__id__": 74 "__id__": 76
},
{
"__id__": 78
} }
], ],
"_prefab": { "_prefab": {
"__id__": 76 "__id__": 80
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -1621,15 +1663,15 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 71 "__id__": 73
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 73 "__id__": 75
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 300, "width": 500,
"height": 23.333333333333332 "height": 23.333333333333332
}, },
"_anchorPoint": { "_anchorPoint": {
@@ -1649,11 +1691,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 71 "__id__": 73
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 75 "__id__": 77
}, },
"_customMaterial": null, "_customMaterial": null,
"_srcBlendFactor": 2, "_srcBlendFactor": 2,
@@ -1711,6 +1753,42 @@
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
"fileId": "dc6KYeWoJBr5NspO5kGx92" "fileId": "dc6KYeWoJBr5NspO5kGx92"
}, },
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 73
},
"_enabled": true,
"__prefab": {
"__id__": 79
},
"_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": 300,
"_originalHeight": 0,
"_alignMode": 2,
"_lockFlags": 0,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "ecZYYEuDRAh5fCYP3KMUKj"
},
{ {
"__type__": "cc.PrefabInfo", "__type__": "cc.PrefabInfo",
"root": { "root": {
@@ -1736,14 +1814,17 @@
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 78 "__id__": 82
}, },
{ {
"__id__": 80 "__id__": 84
},
{
"__id__": 86
} }
], ],
"_prefab": { "_prefab": {
"__id__": 82 "__id__": 88
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -1780,15 +1861,15 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 77 "__id__": 81
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 79 "__id__": 83
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 300, "width": 500,
"height": 23.333333333333332 "height": 23.333333333333332
}, },
"_anchorPoint": { "_anchorPoint": {
@@ -1808,11 +1889,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 77 "__id__": 81
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 81 "__id__": 85
}, },
"_customMaterial": null, "_customMaterial": null,
"_srcBlendFactor": 2, "_srcBlendFactor": 2,
@@ -1870,6 +1951,42 @@
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
"fileId": "f0oseF23FJJY7bo5zkXU/L" "fileId": "f0oseF23FJJY7bo5zkXU/L"
}, },
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 81
},
"_enabled": true,
"__prefab": {
"__id__": 87
},
"_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": 300,
"_originalHeight": 0,
"_alignMode": 2,
"_lockFlags": 0,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "7dc/Tc5s5N+42zkFkChZxc"
},
{ {
"__type__": "cc.PrefabInfo", "__type__": "cc.PrefabInfo",
"root": { "root": {
@@ -1893,11 +2010,11 @@
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 84 "__id__": 90
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 420, "width": 500,
"height": 70 "height": 70
}, },
"_anchorPoint": { "_anchorPoint": {
@@ -1921,14 +2038,14 @@
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 86 "__id__": 92
}, },
"_alignFlags": 45, "_alignFlags": 45,
"_target": null, "_target": null,
"_left": 200, "_left": 95,
"_right": 100, "_right": 125,
"_top": 15, "_top": 36.445,
"_bottom": 15, "_bottom": 13.554999999999996,
"_horizontalCenter": 0, "_horizontalCenter": 0,
"_verticalCenter": 0, "_verticalCenter": 0,
"_isAbsLeft": true, "_isAbsLeft": true,
@@ -1957,7 +2074,7 @@
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 88 "__id__": 94
}, },
"_resizeMode": 1, "_resizeMode": 1,
"_layoutType": 2, "_layoutType": 2,
@@ -2010,22 +2127,22 @@
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 91 "__id__": 97
}, },
{ {
"__id__": 93 "__id__": 99
}, },
{ {
"__id__": 95 "__id__": 101
} }
], ],
"_prefab": { "_prefab": {
"__id__": 97 "__id__": 103
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": -246.42299999999997, "x": -150.389,
"y": -14.317, "y": 39.317,
"z": 0 "z": 0
}, },
"_lrot": { "_lrot": {
@@ -2057,11 +2174,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 90 "__id__": 96
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 92 "__id__": 98
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
@@ -2085,11 +2202,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 90 "__id__": 96
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 94 "__id__": 100
}, },
"_customMaterial": null, "_customMaterial": null,
"_srcBlendFactor": 2, "_srcBlendFactor": 2,
@@ -2153,15 +2270,15 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 90 "__id__": 96
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 96 "__id__": 102
}, },
"_alignFlags": 8, "_alignFlags": 8,
"_target": null, "_target": null,
"_left": 91.2922546983011, "_left": 187.32625469830108,
"_right": 0, "_right": 0,
"_top": 0, "_top": 0,
"_bottom": 0, "_bottom": 0,
@@ -2206,20 +2323,20 @@
}, },
"_children": [ "_children": [
{ {
"__id__": 99 "__id__": 105
}, },
{ {
"__id__": 107 "__id__": 113
} }
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 113 "__id__": 119
} }
], ],
"_prefab": { "_prefab": {
"__id__": 115 "__id__": 121
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -2256,23 +2373,23 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"_parent": { "_parent": {
"__id__": 98 "__id__": 104
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 100 "__id__": 106
}, },
{ {
"__id__": 102 "__id__": 108
}, },
{ {
"__id__": 104 "__id__": 110
} }
], ],
"_prefab": { "_prefab": {
"__id__": 106 "__id__": 112
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -2309,11 +2426,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 99 "__id__": 105
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 101 "__id__": 107
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
@@ -2337,11 +2454,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 99 "__id__": 105
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 103 "__id__": 109
}, },
"_customMaterial": null, "_customMaterial": null,
"_srcBlendFactor": 2, "_srcBlendFactor": 2,
@@ -2382,11 +2499,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 99 "__id__": 105
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 105 "__id__": 111
}, },
"_alignFlags": 45, "_alignFlags": 45,
"_target": null, "_target": null,
@@ -2431,20 +2548,20 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"_parent": { "_parent": {
"__id__": 98 "__id__": 104
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 108 "__id__": 114
}, },
{ {
"__id__": 110 "__id__": 116
} }
], ],
"_prefab": { "_prefab": {
"__id__": 112 "__id__": 118
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -2481,11 +2598,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 107 "__id__": 113
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 109 "__id__": 115
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
@@ -2509,11 +2626,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 107 "__id__": 113
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 111 "__id__": 117
}, },
"_customMaterial": null, "_customMaterial": null,
"_srcBlendFactor": 2, "_srcBlendFactor": 2,
@@ -2590,11 +2707,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 98 "__id__": 104
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 114 "__id__": 120
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
@@ -2635,20 +2752,20 @@
}, },
"_children": [ "_children": [
{ {
"__id__": 117 "__id__": 123
}, },
{ {
"__id__": 123 "__id__": 129
} }
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 129 "__id__": 135
} }
], ],
"_prefab": { "_prefab": {
"__id__": 131 "__id__": 137
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -2685,20 +2802,20 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"_parent": { "_parent": {
"__id__": 116 "__id__": 122
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 118 "__id__": 124
}, },
{ {
"__id__": 120 "__id__": 126
} }
], ],
"_prefab": { "_prefab": {
"__id__": 122 "__id__": 128
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -2735,11 +2852,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 117 "__id__": 123
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 119 "__id__": 125
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
@@ -2763,11 +2880,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 117 "__id__": 123
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 121 "__id__": 127
}, },
"_customMaterial": null, "_customMaterial": null,
"_srcBlendFactor": 2, "_srcBlendFactor": 2,
@@ -2821,20 +2938,20 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"_parent": { "_parent": {
"__id__": 116 "__id__": 122
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 124 "__id__": 130
}, },
{ {
"__id__": 126 "__id__": 132
} }
], ],
"_prefab": { "_prefab": {
"__id__": 128 "__id__": 134
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -2871,11 +2988,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 123 "__id__": 129
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 125 "__id__": 131
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
@@ -2899,11 +3016,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 123 "__id__": 129
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 127 "__id__": 133
}, },
"_customMaterial": null, "_customMaterial": null,
"_srcBlendFactor": 2, "_srcBlendFactor": 2,
@@ -2980,11 +3097,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 116 "__id__": 122
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 130 "__id__": 136
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
@@ -3025,12 +3142,12 @@
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 133 "__id__": 139
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 720, "width": 720,
"height": 100 "height": 120
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -3053,7 +3170,7 @@
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 135 "__id__": 141
}, },
"_alignFlags": 40, "_alignFlags": 40,
"_target": null, "_target": null,
@@ -3089,10 +3206,10 @@
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 137 "__id__": 143
}, },
"icon_node": { "icon_node": {
"__id__": 138 "__id__": 144
}, },
"bg_node": null, "bg_node": null,
"name_label": { "name_label": {
@@ -3102,16 +3219,16 @@
"__id__": 68 "__id__": 68
}, },
"fied2": { "fied2": {
"__id__": 74 "__id__": 76
}, },
"fied3": { "fied3": {
"__id__": 80 "__id__": 84
}, },
"level_label": { "level_label": {
"__id__": 93 "__id__": 99
}, },
"buy_node": { "buy_node": {
"__id__": 98 "__id__": 104
}, },
"_id": "" "_id": ""
}, },
@@ -3131,14 +3248,14 @@
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 139 "__id__": 145
}, },
{ {
"__id__": 141 "__id__": 147
} }
], ],
"_prefab": { "_prefab": {
"__id__": 143 "__id__": 149
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -3175,11 +3292,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 138 "__id__": 144
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 140 "__id__": 146
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
@@ -3203,11 +3320,11 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 138 "__id__": 144
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 142 "__id__": 148
}, },
"_customMaterial": null, "_customMaterial": null,
"_srcBlendFactor": 2, "_srcBlendFactor": 2,
@@ -3270,7 +3387,7 @@
"instance": null, "instance": null,
"targetOverrides": [ "targetOverrides": [
{ {
"__id__": 145 "__id__": 151
} }
], ],
"nestedPrefabInstanceRoots": [ "nestedPrefabInstanceRoots": [
@@ -3282,7 +3399,7 @@
{ {
"__type__": "cc.TargetOverrideInfo", "__type__": "cc.TargetOverrideInfo",
"source": { "source": {
"__id__": 136 "__id__": 142
}, },
"sourceInfo": null, "sourceInfo": null,
"propertyPath": [ "propertyPath": [
@@ -3292,7 +3409,7 @@
"__id__": 40 "__id__": 40
}, },
"targetInfo": { "targetInfo": {
"__id__": 146 "__id__": 152
} }
}, },
{ {

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": "f820a186-b9f6-44df-a534-bdcbaa6a639a",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "hero"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -93,4 +93,76 @@ export const BuffList: Record<number, BuffConfig> = {
modifiers: [{ attr: Attrs.ap, op: ModOp.Flat, value: 90 }], modifiers: [{ attr: Attrs.ap, op: ModOp.Flat, value: 90 }],
info: "攻击力 +90持续 10 秒", info: "攻击力 +90持续 10 秒",
}, },
// ==================== 玩家计时性强化(药水/技能用,默认 5s ====================
// 计时性回血HoT
7010: {
id: 7010, name: "再生", icon: "Stat_PotionBoost",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
tick: { interval: 0.5, damage_or_heal: 10, scale_by_ap_pct: 0 },
info: "每秒回复生命,持续 5 秒",
},
// 攻击强化(限时)
7011: {
id: 7011, name: "攻击爆发", icon: "Stat_Attack_03",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.ap, op: ModOp.PercentAdd, value: 50 }],
info: "攻击力提升 50%,持续 5 秒",
},
// 暴击强化(限时)
7012: {
id: 7012, name: "暴击爆发", icon: "Stat_CriticalChance_02",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.critical, op: ModOp.Flat, value: 30 }],
info: "暴击率提升 30%,持续 5 秒",
},
// 击退概率强化(限时)
7013: {
id: 7013, name: "击退爆发", icon: "Stat_Stun_01",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.knockback_chance, op: ModOp.Flat, value: 30 }],
info: "击退概率提升 30%,持续 5 秒",
},
// 穿透强化(限时)
7014: {
id: 7014, name: "穿透爆发", icon: "Stat_Tripleshot",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.puncture_chance, op: ModOp.Flat, value: 30 }],
info: "穿透概率提升 30%,持续 5 秒",
},
// 攻速强化(限时,走 getEffectiveSkillCd 计时修饰)
7015: {
id: 7015, name: "攻速爆发", icon: "Stat_AttackSpeed_02",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.speed, op: ModOp.Flat, value: 40 }],
info: "攻击速度提升 40%,持续 5 秒",
},
// 风怒强化(限时,按概率百分点)
7016: {
id: 7016, name: "风怒爆发", icon: "Stat_CriticalComboChance",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.wfuny, op: ModOp.Flat, value: 20 }],
info: "风怒概率提升 20%,持续 5 秒",
},
// 击晕概率强化(限时)
7017: {
id: 7017, name: "击晕爆发", icon: "Stat_Stun_01",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.stun_chance, op: ModOp.Flat, value: 30 }],
info: "击晕概率提升 30%,持续 5 秒",
},
// 击晕抗性强化(限时)
7018: {
id: 7018, name: "击晕抗性", icon: "Stat_Armor_01",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.stun_res, op: ModOp.Flat, value: 50 }],
info: "击晕抗性提升 50%,持续 5 秒",
},
// 冰冻抗性强化(限时)
7019: {
id: 7019, name: "冰冻抗性", icon: "Stat_Freeze",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.freeze_res, op: ModOp.Flat, value: 50 }],
info: "冰冻抗性提升 50%,持续 5 秒",
},
}; };

View File

@@ -31,30 +31,25 @@ interface ItemCardRaw {
} }
const ItemCardData: ItemCardRaw[] = [ const ItemCardData: ItemCardRaw[] = [
// ==================== 基础恢复类 ==================== // ==================== 一次性回血(计时性 HoT5s ====================
{ uuid: 9101, skill: 6302, name: "治疗药水", info: "恢复全体友方 300 点生命", cost: 3, weight: 20 }, { uuid: 9101, skill: 6502, name: "再生药水", info: "全体友方每秒回复生命,持续 5 秒", cost: 0, weight: 20 },
{ uuid: 9102, skill: 6301, name: "护盾药水", info: "为全体友方添加护盾,可抵挡 3 次伤害", cost: 4, weight: 15 },
{ uuid: 9103, skill: 6303, name: "金币袋", info: "立即获得 5 金币", cost: 2, weight: 15, overrides: { gold: 5 } },
// ==================== 性强化类(单次触发 ==================== // ==================== 计时性强化(统一 5s ====================
{ uuid: 9111, skill: 6401, name: "攻击药", info: "全体友方攻击力提升 5", cost: 3, weight: 12 }, { uuid: 9102, skill: 6503, name: "攻击药", info: "全体友方攻击力提升 50%,持续 5 秒", cost: 0, weight: 15 },
{ uuid: 9112, skill: 6402, name: "生命药剂", info: "全体友方最大生命值提升 20 点", cost: 3, weight: 12 }, { uuid: 9103, skill: 6504, name: "暴击药水", info: "全体友方暴击率提升 30%,持续 5 秒", cost: 0, weight: 15 },
{ uuid: 9113, skill: 6403, name: "暴击药剂", info: "全体友方击率提升 10%", cost: 3, weight: 12 }, { uuid: 9104, skill: 6505, name: "击退药水", info: "全体友方击退概率提升 30%,持续 5 秒", cost: 0, weight: 12 },
{ uuid: 9114, skill: 6404, name: "暴伤药剂", info: "全体友方暴击伤害提升 20%", cost: 3, weight: 12 }, { uuid: 9105, skill: 6506, name: "穿透药水", info: "全体友方穿透概率提升 30%,持续 5 秒", cost: 0, weight: 12 },
{ uuid: 9115, skill: 6405, name: "击晕药剂", info: "全体友方击晕概率提升 10%", cost: 3, weight: 12 }, { uuid: 9106, skill: 6507, name: "攻速药水", info: "全体友方攻击速度提升 40%,持续 5 秒", cost: 0, weight: 15 },
{ uuid: 9116, skill: 6408, name: "穿刺药剂", info: "全体友方穿透概率提升 20%", cost: 3, weight: 12 }, { uuid: 9107, skill: 6508, name: "风怒药水", info: "全体友方风怒概率提升 20%,持续 5 秒", cost: 0, weight: 12 },
{ uuid: 9117, skill: 6409, name: "风怒药剂", info: "全体友方风怒次数提升 1 次", cost: 3, weight: 12 }, { uuid: 9108, skill: 6509, name: "击晕药水", info: "全体友方击晕概率提升 30%,持续 5 秒", cost: 0, weight: 12 },
{ uuid: 9109, skill: 6510, name: "击晕抗性药水", info: "全体友方击晕抗性提升 50%,持续 5 秒", cost: 4, weight: 10 },
{ uuid: 9110, skill: 6511, name: "冰冻抗性药水", info: "全体友方冰冻抗性提升 50%,持续 5 秒", cost: 4, weight: 10 },
// ==================== 高级恢复类 ==================== // ==================== 高级buff_value 覆写,复用同一技能底座) ====================
{ uuid: 9201, skill: 6302, name: "高级治疗药水", info: "恢复全体友方 600 点生命", cost: 6, weight: 8, overrides: { ap: 600 } }, { uuid: 9201, skill: 6502, name: "高级再生药水", info: "全体友方每秒回复 25 生命,持续 5 秒", cost: 0, weight: 8, overrides: { buff_value: 25 } },
{ uuid: 9202, skill: 6301, name: "高级护盾药水", info: "全体友方添加护盾,可抵挡 6 次伤害", cost: 8, weight: 6, overrides: { ap: 6 } }, { uuid: 9202, skill: 6503, name: "高级攻击药水", info: "全体友方攻击力提升 80%,持续 5 秒", cost: 0, weight: 8, overrides: { buff_value: 80 } },
{ uuid: 9203, skill: 6303, name: "大金币袋", info: "立即获得 12 金币", cost: 5, weight: 6, overrides: { gold: 12 } }, { uuid: 9203, skill: 6504, name: "高级暴击药水", info: "全体友方暴击率提升 50%,持续 5 秒", cost: 0, weight: 8, overrides: { buff_value: 50 } },
{ uuid: 9206, skill: 6507, name: "高级攻速药水", info: "全体友方攻击速度提升 70%,持续 5 秒", cost: 0, weight: 8, overrides: { buff_value: 70 } },
// ==================== 高级属性强化类 ====================
{ uuid: 9211, skill: 6401, name: "高级攻击药剂", info: "全体友方攻击力提升 10 点", cost: 6, weight: 5, overrides: { ap: 10 } },
{ uuid: 9212, skill: 6402, name: "高级生命药剂", info: "全体友方最大生命值提升 40 点", cost: 6, weight: 5, overrides: { ap: 40 } },
{ uuid: 9213, skill: 6403, name: "高级暴击药剂", info: "全体友方暴击率提升 20%", cost: 6, weight: 5, overrides: { ap: 2 } },
{ uuid: 9214, skill: 6404, name: "高级暴伤药剂", info: "全体友方暴击伤害提升 40%", cost: 6, weight: 5, overrides: { ap: 2 } },
]; ];
/** /**

View File

@@ -155,6 +155,7 @@ export interface SkillConfig {
bck?: number, // 额外击退概率 bck?: number, // 额外击退概率
buff_type?: Attrs, // Buff 类型 (单一职责) buff_type?: Attrs, // Buff 类型 (单一职责)
timed_buff_id?: number, // 计时性 buff 配置 id指向 BuffList存在时走 buffManager 而非永久 add_* timed_buff_id?: number, // 计时性 buff 配置 id指向 BuffList存在时走 buffManager 而非永久 add_*
buff_value?: number, // 覆写计时 buff 的修饰数值modifiers.value / tick.damage_or_heal由药水卡自定义档位
call_hero?: number, // 召唤技能召唤英雄id(可选) call_hero?: number, // 召唤技能召唤英雄id(可选)
is_accel?: boolean, // 是否逐渐加速飞行 is_accel?: boolean, // 是否逐渐加速飞行
info: string, // 技能描述 info: string, // 技能描述
@@ -172,6 +173,7 @@ export interface SkillOverrides {
bck?: number; bck?: number;
buff_type?: Attrs; buff_type?: Attrs;
timed_buff_id?: number; timed_buff_id?: number;
buff_value?: number;
call_hero?: number; call_hero?: number;
is_accel?: boolean; is_accel?: boolean;
} }
@@ -377,6 +379,59 @@ export const SkillSet: Record<number, SkillConfig> = {
uuid: 6501, name: "复活", sp_name: "buff_wind", icon: "Stat_HolyDamage", TGroup: TGroup.Self, readyAnm: "up_ap", endAnm: "", act: "atk", uuid: 6501, name: "复活", sp_name: "buff_wind", icon: "Stat_HolyDamage", TGroup: TGroup.Self, readyAnm: "up_ap", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 50, hit_count: 3, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support, DTType: DTType.single, kind: SkillKind.Support, ap: 50, hit_count: 3, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, info: "ap 代表复活的生命值百分比", RType: RType.fixed, EType: EType.animationEnd, info: "ap 代表复活的生命值百分比",
},
// ==================== 计时性强化技能(药水底座,统一 5s走 timed_buff_id ====================
// 注ap 字段在此类技能中无意义,修饰数值由 BuffList 配置hit_count=99 确保覆盖全队。
6502: {
uuid: 6502, name: "计时回血", sp_name: "buff_wind", icon: "Stat_PotionBoost", TGroup: TGroup.Team, readyAnm: "up_green", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.hp, timed_buff_id: 7010, info: "全体友方每秒回复生命持续5秒",
},
6503: {
uuid: 6503, name: "攻击爆发", sp_name: "buff_wind", icon: "Stat_Attack_03", TGroup: TGroup.Team, readyAnm: "up_ap", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.ap, timed_buff_id: 7011, info: "全体友方攻击力提升50%持续5秒",
},
6504: {
uuid: 6504, name: "暴击爆发", sp_name: "buff_wind", icon: "Stat_CriticalChance_02", TGroup: TGroup.Team, readyAnm: "up_ap", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.critical, timed_buff_id: 7012, info: "全体友方暴击率提升30%持续5秒",
},
6505: {
uuid: 6505, name: "击退爆发", sp_name: "buff_wind", icon: "Stat_Stun_01", TGroup: TGroup.Team, readyAnm: "up_blue", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.knockback_chance, timed_buff_id: 7013, info: "全体友方击退概率提升30%持续5秒",
},
6506: {
uuid: 6506, name: "穿透爆发", sp_name: "buff_wind", icon: "Stat_Tripleshot", TGroup: TGroup.Team, readyAnm: "up_ap", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.puncture_chance, timed_buff_id: 7014, info: "全体友方穿透概率提升30%持续5秒",
},
6507: {
uuid: 6507, name: "攻速爆发", sp_name: "buff_wind", icon: "Stat_AttackSpeed_02", TGroup: TGroup.Team, readyAnm: "up_ap", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.speed, timed_buff_id: 7015, info: "全体友方攻击速度提升40%持续5秒",
},
6508: {
uuid: 6508, name: "风怒爆发", sp_name: "buff_wind", icon: "Stat_CriticalComboChance", TGroup: TGroup.Team, readyAnm: "up_ap", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.wfuny, timed_buff_id: 7016, info: "全体友方风怒概率提升20%持续5秒",
},
6509: {
uuid: 6509, name: "击晕爆发", sp_name: "buff_wind", icon: "Stat_Stun_01", TGroup: TGroup.Team, readyAnm: "up_blue", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.stun_chance, timed_buff_id: 7017, info: "全体友方击晕概率提升30%持续5秒",
},
6510: {
uuid: 6510, name: "击晕抗性", sp_name: "buff_wind", icon: "Stat_Armor_01", TGroup: TGroup.Team, readyAnm: "up_blue", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.stun_res, timed_buff_id: 7018, info: "全体友方击晕抗性提升50%持续5秒",
},
6511: {
uuid: 6511, name: "冰冻抗性", sp_name: "buff_wind", icon: "Stat_Freeze", TGroup: TGroup.Team, readyAnm: "up_blue", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 99, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.freeze_res, timed_buff_id: 7019, info: "全体友方冰冻抗性提升50%持续5秒",
} }
}; };

View File

@@ -15,12 +15,15 @@ export class ActiveBuff {
source_ap_snapshot: number; source_ap_snapshot: number;
/** 周期效果累计时间(秒) */ /** 周期效果累计时间(秒) */
tick_acc: number = 0; tick_acc: number = 0;
/** 修饰数值覆写(来自药水卡 buff_value优先于 BuffList 配置值undefined 表示用配置值 */
value_override?: number;
constructor(cfg_id: number, dur: number, src_uuid: number, src_ap: number) { constructor(cfg_id: number, dur: number, src_uuid: number, src_ap: number, value_override?: number) {
this.config_id = cfg_id; this.config_id = cfg_id;
this.remaining = dur; this.remaining = dur;
this.source_uuid = src_uuid; this.source_uuid = src_uuid;
this.source_ap_snapshot = src_ap; this.source_ap_snapshot = src_ap;
this.value_override = value_override;
} }
} }

View File

@@ -4,19 +4,23 @@
* 设计说明: * 设计说明:
* - 非 ECS 组件,是普通 class 单例(参考 smc 的单例暴露模式)。 * - 非 ECS 组件,是普通 class 单例(参考 smc 的单例暴露模式)。
* - 对外提供 applyBuff / dispel / getStack / hasControl 四组核心能力。 * - 对外提供 applyBuff / dispel / getStack / hasControl 四组核心能力。
* - 控制类 buff 采用"双写"策略:既写入 BuffComp新框架也同步调用 * - 控制类 buff(冰冻/眩晕)统一写入 BuffComp由 BuffSystem 计时到期;
* HeroAttrsComp.toFrost/toStun旧框架保证过渡期表现一致 * 旧字段 frost_end_time/stun_end_time 已随 HeroBuffSystem 一并下线
*/ */
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { BuffCategory, BuffConfig, BuffList } from "../common/config/BuffSet"; import { BuffCategory, BuffList } from "../common/config/BuffSet";
import { FightSet } from "../common/config/GameSet";
import { HeroAttrsComp } from "./HeroAttrsComp";
import { BuffComp, ActiveBuff } from "./BuffComp"; import { BuffComp, ActiveBuff } from "./BuffComp";
import { mLogger } from "../common/Logger";
/** applyBuff 的覆盖参数(预留按需覆写持续时间) */ /** Buff 模块调试日志开关 */
const DEBUG = false;
/** applyBuff 的覆盖参数(预留按需覆写持续时间 / 修饰数值) */
export interface BuffApplyOverrides { export interface BuffApplyOverrides {
duration?: number; duration?: number;
/** 覆写计时 buff 的修饰数值modifiers.value / tick.damage_or_heal由药水卡 buff_value 自定义档位 */
value?: number;
} }
class BuffManagerImpl { class BuffManagerImpl {
@@ -26,9 +30,7 @@ class BuffManagerImpl {
* 叠层规则: * 叠层规则:
* - max_stack === 0无限叠加始终 push 新层 * - max_stack === 0无限叠加始终 push 新层
* - existing.length < max_stackpush 新层 * - existing.length < max_stackpush 新层
* - 已满:替换最老层(数组末尾) * - 已满:移除最老层(数组首部)后追加新层,保持 FIFO 刷新语义
*
* 控制类is_control额外双写旧字段frost/stun
* *
* @param target 目标实体 * @param target 目标实体
* @param buffId BuffList 配置 id * @param buffId BuffList 配置 id
@@ -38,7 +40,11 @@ class BuffManagerImpl {
*/ */
applyBuff(target: ecs.Entity, buffId: number, sourceUuid: number = 0, sourceAp: number = 0, overrides?: BuffApplyOverrides): void { applyBuff(target: ecs.Entity, buffId: number, sourceUuid: number = 0, sourceAp: number = 0, overrides?: BuffApplyOverrides): void {
const cfg = BuffList[buffId]; const cfg = BuffList[buffId];
if (!cfg) return; if (!cfg) {
mLogger.warn(true, "BuffManager", `applyBuff: buffId=${buffId} 配置不存在,跳过`);
return;
}
mLogger.log(DEBUG, "BuffManager", `applyBuff: buff=${cfg.name}(${buffId}) target_eid=${target.eid} duration=${overrides?.duration ?? cfg.duration} value_override=${overrides?.value} source_ap=${sourceAp}`);
const buffComp = this.ensureBuffComp(target); const buffComp = this.ensureBuffComp(target);
const duration = overrides?.duration ?? cfg.duration; const duration = overrides?.duration ?? cfg.duration;
@@ -49,21 +55,15 @@ class BuffManagerImpl {
buffComp.buffs.set(buffId, layers); buffComp.buffs.set(buffId, layers);
} }
const newLayer = new ActiveBuff(buffId, duration, sourceUuid, sourceAp); const newLayer = new ActiveBuff(buffId, duration, sourceUuid, sourceAp, overrides?.value);
if (cfg.max_stack === 0 || layers.length < cfg.max_stack) { if (cfg.max_stack === 0 || layers.length < cfg.max_stack) {
layers.push(newLayer); layers.push(newLayer);
} else { } else {
// 已满,移除最老层(数组首部)后追加新层,保持 FIFO 刷新语义
layers.shift(); layers.shift();
layers.push(newLayer); layers.push(newLayer);
} }
// 控制类双写旧字段
if (cfg.is_control) {
this.applyControlEffect(target, cfg, duration);
}
buffComp.dirty_buffs = true; buffComp.dirty_buffs = true;
} }
@@ -80,8 +80,6 @@ class BuffManagerImpl {
const buffComp = target.get(BuffComp); const buffComp = target.get(BuffComp);
let removedKinds = 0; let removedKinds = 0;
const controlKindsCleared: ('frost' | 'stun')[] = [];
buffComp.buffs.forEach((layers, buffId) => { buffComp.buffs.forEach((layers, buffId) => {
const cfg = BuffList[buffId]; const cfg = BuffList[buffId];
if (!cfg) return; if (!cfg) return;
@@ -90,18 +88,8 @@ class BuffManagerImpl {
if (layers.length > 0) removedKinds++; if (layers.length > 0) removedKinds++;
buffComp.buffs.delete(buffId); buffComp.buffs.delete(buffId);
// 记录被驱散的控制类型,用于后续重算
if (cfg.is_control && cfg.control_kind && cfg.control_kind !== 'none') {
controlKindsCleared.push(cfg.control_kind);
}
}); });
// 控制类驱散后重算旧字段
if (controlKindsCleared.length > 0) {
this.recomputeControlState(target, controlKindsCleared);
}
buffComp.dirty_buffs = true; buffComp.dirty_buffs = true;
return removedKinds; return removedKinds;
} }
@@ -118,23 +106,15 @@ class BuffManagerImpl {
/** /**
* 判断目标是否处于指定类型的控制状态下。 * 判断目标是否处于指定类型的控制状态下。
* 同时检查新框架 BuffComp 和旧字段,兼容过渡期 * 唯一判定来源:BuffComp 中是否存在对应 control_kind 的活跃控制 buff
*/ */
hasControl(target: ecs.Entity, kind: 'frost' | 'stun'): boolean { hasControl(target: ecs.Entity, kind: 'frost' | 'stun'): boolean {
// 新框架:检查 BuffComp 中是否有对应控制类 buff if (!target.has(BuffComp)) return false;
if (target.has(BuffComp)) { const buffComp = target.get(BuffComp);
const buffComp = target.get(BuffComp); for (const [buffId, layers] of buffComp.buffs) {
for (const [buffId, layers] of buffComp.buffs) { if (layers.length === 0) continue;
if (layers.length === 0) continue; const cfg = BuffList[buffId];
const cfg = BuffList[buffId]; if (cfg?.is_control && cfg.control_kind === kind) return true;
if (cfg?.is_control && cfg.control_kind === kind) return true;
}
}
// 旧字段兜底
if (target.has(HeroAttrsComp)) {
const attrs = target.get(HeroAttrsComp);
if (kind === 'frost') return attrs.isFrost();
if (kind === 'stun') return attrs.isStun();
} }
return false; return false;
} }
@@ -150,59 +130,6 @@ class BuffManagerImpl {
} }
return target.get(BuffComp); return target.get(BuffComp);
} }
/**
* 控制效果双写:将控制类 buff 同步写入旧字段。
* duration 会被换算成 toFrost/toStun 所需的倍数参数。
*/
private applyControlEffect(target: ecs.Entity, cfg: BuffConfig, duration: number): void {
if (!target.has(HeroAttrsComp)) return;
const attrs = target.get(HeroAttrsComp);
if (cfg.control_kind === 'frost') {
// toFrost(time) 内部会乘以 FROST_TIME这里反除得到倍数
attrs.toFrost(duration / FightSet.FROST_TIME);
} else if (cfg.control_kind === 'stun') {
attrs.toStun(duration / FightSet.STUN_TIME);
}
}
/**
* 驱散控制 buff 后重算旧字段。
* 如果对应类型的控制 buff 已全部清除,则立即将旧字段归零。
*
* @param target 目标实体
* @param clearedKinds 本次被驱散的控制类型列表
*/
private recomputeControlState(target: ecs.Entity, clearedKinds: ('frost' | 'stun')[]): void {
if (!target.has(HeroAttrsComp)) return;
const attrs = target.get(HeroAttrsComp);
// 检查是否还有同类型控制 buff 残留
const hasFrostInBuff = this.hasControlInBuff(target, 'frost');
const hasStunInBuff = this.hasControlInBuff(target, 'stun');
if (clearedKinds.includes('frost') && !hasFrostInBuff) {
attrs.frost_end_time = 0;
}
if (clearedKinds.includes('stun') && !hasStunInBuff) {
attrs.stun_end_time = 0;
}
}
/**
* 仅检查 BuffComp 中是否存在指定控制类型(不查旧字段)。
*/
private hasControlInBuff(target: ecs.Entity, kind: 'frost' | 'stun'): boolean {
if (!target.has(BuffComp)) return false;
const buffComp = target.get(BuffComp);
for (const [buffId, layers] of buffComp.buffs) {
if (layers.length === 0) continue;
const cfg = BuffList[buffId];
if (cfg?.is_control && cfg.control_kind === kind) return true;
}
return false;
}
} }
/** Buff 管理器单例(全局唯一实例) */ /** Buff 管理器单例(全局唯一实例) */

View File

@@ -5,10 +5,9 @@
* - 遍历 BuffComp.buffs每层 remaining -= 步长 * - 遍历 BuffComp.buffs每层 remaining -= 步长
* - 若配置了 tick 效果DoT/HoT累计 tick_acc 并按 interval 结算伤害/治疗 * - 若配置了 tick 效果DoT/HoT累计 tick_acc 并按 interval 结算伤害/治疗
* - 到期的层从数组中移除;数组空则清理 key * - 到期的层从数组中移除;数组空则清理 key
* - 兼容期:同时递减旧字段 frost_end_time / stun_end_time
* *
* 注意:当前 HeroBuffSystem 仍在运行相同的 frost/stun 递减逻辑, * 控制类 buff冰冻/眩晕)不在此处做特殊处理:层存活期间 hasControl 判定
* 待旧系统完全下线后可移除此处兼容代码 * 即生效,到期移除后控制自然解除。旧 HeroBuffSystem 已下线
*/ */
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
@@ -16,6 +15,10 @@ import { Timer } from "db://oops-framework/core/common/timer/Timer";
import { BuffList } from "../common/config/BuffSet"; import { BuffList } from "../common/config/BuffSet";
import { HeroAttrsComp } from "./HeroAttrsComp"; import { HeroAttrsComp } from "./HeroAttrsComp";
import { BuffComp, ActiveBuff } from "./BuffComp"; import { BuffComp, ActiveBuff } from "./BuffComp";
import { mLogger } from "../common/Logger";
/** Buff 模块调试日志开关 */
const DEBUG = false;
/** 固定步长(秒) */ /** 固定步长(秒) */
const TICK_STEP = 0.1; const TICK_STEP = 0.1;
@@ -61,6 +64,7 @@ export class BuffSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
if (cfg.duration > 0 && layer.remaining <= 0) { if (cfg.duration > 0 && layer.remaining <= 0) {
layers.splice(i, 1); layers.splice(i, 1);
anyChanged = true; anyChanged = true;
mLogger.log(DEBUG, "BuffSystem", `buff 到期移除: ${cfg.name}(${buffId}) eid=${e.eid} 剩余层数=${layers.length}`);
} }
} }
@@ -91,8 +95,10 @@ export class BuffSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
while (layer.tick_acc >= tick.interval) { while (layer.tick_acc >= tick.interval) {
layer.tick_acc -= tick.interval; layer.tick_acc -= tick.interval;
// 按 ap 缩放后取整floor(dmg * (1 + ap_snapshot * scale_pct / 10000)) // 按 ap 缩放后取整floor(dmg * (1 + ap_snapshot * scale_pct / 10000))
// damage_or_heal 优先取药水卡覆写值
const baseAmount = layer.value_override !== undefined ? layer.value_override : tick.damage_or_heal;
const scale = 1 + layer.source_ap_snapshot * tick.scale_by_ap_pct / 10000; const scale = 1 + layer.source_ap_snapshot * tick.scale_by_ap_pct / 10000;
const amount = Math.floor(tick.damage_or_heal * scale); const amount = Math.floor(baseAmount * scale);
attrs.add_hp(amount); attrs.add_hp(amount);
} }
} }

View File

@@ -200,14 +200,14 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
targetView.playEnd(skillConf.endAnm); targetView.playEnd(skillConf.endAnm);
if (isFrost) { if (isFrost) {
TAttrsComp.toFrost(); TAttrsComp.toFrost();
targetView.in_iced(TAttrsComp.frost_end_time); targetView.in_iced(FightSet.FROST_TIME);
if (damageEvent.Attrs.fac === FacSet.HERO) { if (damageEvent.Attrs.fac === FacSet.HERO) {
smc.vmdata.scores.freeze_count++; smc.vmdata.scores.freeze_count++;
} }
} }
if (isStun) { if (isStun) {
TAttrsComp.toStun(); TAttrsComp.toStun();
targetView.in_stun(TAttrsComp.stun_end_time); targetView.in_stun(FightSet.STUN_TIME);
if (damageEvent.Attrs.fac === FacSet.HERO) { if (damageEvent.Attrs.fac === FacSet.HERO) {
smc.vmdata.scores.stun_count++; smc.vmdata.scores.stun_count++;
} }

View File

@@ -1,7 +1,6 @@
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { HeroDisVal, HeroInfo, HSkillInfo, HType, SkillTriggerType } from "../common/config/heroSet"; import { HeroDisVal, HeroInfo, HSkillInfo, HType, SkillTriggerType } from "../common/config/heroSet";
import { mLogger } from "../common/Logger"; import { mLogger } from "../common/Logger";
import { Timer } from "db://oops-framework/core/common/timer/Timer";
import { FacSet, FightSet } from "../common/config/GameSet"; import { FacSet, FightSet } from "../common/config/GameSet";
import { FieldSkillSet, FieldSkillType, SkillOverrides } from "../common/config/SkillSet"; import { FieldSkillSet, FieldSkillType, SkillOverrides } from "../common/config/SkillSet";
import { smc } from "../common/SingletonModuleComp"; import { smc } from "../common/SingletonModuleComp";
@@ -9,6 +8,11 @@ import { Attrs } from "../common/config/HeroAttrs";
import { FieldSkillHelper } from "./FieldSkillHelper"; import { FieldSkillHelper } from "./FieldSkillHelper";
import { BuffComp } from "./BuffComp"; import { BuffComp } from "./BuffComp";
import { BuffList, ModOp } from "../common/config/BuffSet"; import { BuffList, ModOp } from "../common/config/BuffSet";
import { buffManager } from "./BuffManager";
/** 控制类 buff 配置 id对应 BuffList */
const BUFF_ID_FROST = 7003;
const BUFF_ID_STUN = 7004;
@ecs.register('HeroAttrs') @ecs.register('HeroAttrs')
export class HeroAttrsComp extends ecs.Comp { export class HeroAttrsComp extends ecs.Comp {
public debugMode: boolean = false; public debugMode: boolean = false;
@@ -66,9 +70,6 @@ export class HeroAttrsComp extends ecs.Comp {
invincible_time: number = 0;// 无敌时间 invincible_time: number = 0;// 无敌时间
frost_end_time: number = 0;
stun_end_time: number = 0;
boom: boolean = false; // 自爆怪 boom: boolean = false; // 自爆怪
// ==================== 脏标签标记 ==================== // ==================== 脏标签标记 ====================
@@ -108,8 +109,6 @@ export class HeroAttrsComp extends ecs.Comp {
* 从 HeroInfo 读取初始配置,建立属性系统 * 从 HeroInfo 读取初始配置,建立属性系统
*/ */
initAttrs() { initAttrs() {
this.frost_end_time = 0;
this.stun_end_time = 0;
} }
/*******************基础属性管理********************/ /*******************基础属性管理********************/
@@ -169,14 +168,16 @@ export class HeroAttrsComp extends ecs.Comp {
} }
/** 施加冰冻:委托 buffManager 写入 BuffCompduration = FROST_TIME * time */
toFrost(time: number = 1) { toFrost(time: number = 1) {
const frostTime = FightSet.FROST_TIME * time; if (!this.ent) return;
this.frost_end_time = Math.max(this.frost_end_time, frostTime); buffManager.applyBuff(this.ent, BUFF_ID_FROST, 0, 0, { duration: FightSet.FROST_TIME * time });
} }
/** 施加击晕:委托 buffManager 写入 BuffComp并清零技能 CD */
toStun(time: number = 1) { toStun(time: number = 1) {
const stunTime = FightSet.STUN_TIME * time; if (!this.ent) return;
this.stun_end_time = Math.max(this.stun_end_time, stunTime); buffManager.applyBuff(this.ent, BUFF_ID_STUN, 0, 0, { duration: FightSet.STUN_TIME * time });
// 击晕时 CD 清零 // 击晕时 CD 清零
for (const key in this.skills) { for (const key in this.skills) {
@@ -217,11 +218,13 @@ export class HeroAttrsComp extends ecs.Comp {
skill.ccd = Math.min(actualCd, skill.ccd + dt); skill.ccd = Math.min(actualCd, skill.ccd + dt);
} }
} }
/** 是否处于冰冻状态(统一走 BuffComp 判定) */
isFrost(): boolean { isFrost(): boolean {
return this.frost_end_time > 0 return !!this.ent && buffManager.hasControl(this.ent, 'frost');
} }
/** 是否处于击晕状态(统一走 BuffComp 判定) */
isStun(): boolean { isStun(): boolean {
return this.stun_end_time > 0 return !!this.ent && buffManager.hasControl(this.ent, 'stun');
} }
getSkillLevel(skillId: number): number { getSkillLevel(skillId: number): number {
if (!skillId) return 0; if (!skillId) return 0;
@@ -350,14 +353,17 @@ export class HeroAttrsComp extends ecs.Comp {
if (!cfg || !cfg.modifiers) return; if (!cfg || !cfg.modifiers) return;
// 每层独立贡献,模拟叠层放大效果 // 每层独立贡献,模拟叠层放大效果
for (let i = 0; i < layers.length; i++) { for (let i = 0; i < layers.length; i++) {
const layerVal = layers[i].value_override; // 药水卡覆写值优先
for (const mod of cfg.modifiers) { for (const mod of cfg.modifiers) {
if (mod.attr !== attr) continue; if (mod.attr !== attr) continue;
const value = layerVal !== undefined ? layerVal : mod.value;
mLogger.log(this.debugMode, "HeroAttrs", `aggregateTimedMods 命中: ${this.hero_name} buff=${cfg.name} attr=${attr} op=${mod.op} value=${value} remaining=${layers[i].remaining.toFixed(1)}`);
if (mod.op === ModOp.Flat) { if (mod.op === ModOp.Flat) {
result.flatSum += mod.value; result.flatSum += value;
} else { } else {
// PercentAdd 与 PercentMul 暂统一按加法百分比聚合; // PercentAdd 与 PercentMul 暂统一按加法百分比聚合;
// PercentMul 真正的独立乘区尚未启用TODO: 启用时需改造为多乘区连乘 // PercentMul 真正的独立乘区尚未启用TODO: 启用时需改造为多乘区连乘
result.pctSum += mod.value; result.pctSum += value;
} }
} }
} }
@@ -372,7 +378,11 @@ export class HeroAttrsComp extends ecs.Comp {
public getFinalAp(): number { public getFinalAp(): number {
const runtimeAp = this.getRuntimeAp(this.ap); const runtimeAp = this.getRuntimeAp(this.ap);
const mods = this.aggregateTimedMods(Attrs.ap); const mods = this.aggregateTimedMods(Attrs.ap);
return (runtimeAp + mods.flatSum) * (1 + mods.pctSum / 100); const final = (runtimeAp + mods.flatSum) * (1 + mods.pctSum / 100);
if (this.debugMode && (mods.flatSum !== 0 || mods.pctSum !== 0)) {
mLogger.log(this.debugMode, "HeroAttrs", `getFinalAp: ${this.hero_name} base=${this.ap} runtime=${runtimeAp.toFixed(1)} flat=${mods.flatSum} pct=${mods.pctSum} final=${final.toFixed(1)}`);
}
return final;
} }
/** /**
@@ -471,7 +481,9 @@ export class HeroAttrsComp extends ecs.Comp {
const skill = this.skills[skillId]; const skill = this.skills[skillId];
if (!skill) return 0; if (!skill) return 0;
if (skill.cd <= 0) return 0; if (skill.cd <= 0) return 0;
const speedBonus = this.getRuntimeAttackSpeedBonus(); // 攻速 = 驻场加成 + 计时性 buff 修饰speed 属性的 flat/pct 均按攻速百分点处理)
const timedMods = this.aggregateTimedMods(Attrs.speed);
const speedBonus = this.getRuntimeAttackSpeedBonus() + timedMods.flatSum + timedMods.pctSum;
if (speedBonus <= 0) return skill.cd; if (speedBonus <= 0) return skill.cd;
const speedRate = 1 + speedBonus / 100; const speedRate = 1 + speedBonus / 100;
return Math.max(HeroAttrsComp.minAttackCd, skill.cd / speedRate); return Math.max(HeroAttrsComp.minAttackCd, skill.cd / speedRate);
@@ -549,9 +561,6 @@ export class HeroAttrsComp extends ecs.Comp {
this.wfuny = 0; this.wfuny = 0;
this.boom = false; this.boom = false;
this.frost_end_time = 0;
this.stun_end_time = 0;
// 重置技能距离缓存 // 重置技能距离缓存
this.maxSkillDistance = 0; this.maxSkillDistance = 0;
this.minSkillDistance = 0; this.minSkillDistance = 0;
@@ -580,32 +589,5 @@ export class HeroAttrsComp extends ecs.Comp {
} }
} }
@ecs.register('HeroBuffSystem')
export class HeroBuffSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
private timer = new Timer(0.1)
filter(): ecs.IMatcher {
return ecs.allOf(HeroAttrsComp);
}
update(e: ecs.Entity): void {
if (this.timer.update(this.dt)) {
const attrsComp = e.get(HeroAttrsComp);
if (attrsComp.frost_end_time > 0) {
attrsComp.frost_end_time -= 0.1;
if (attrsComp.frost_end_time <= 0) {
attrsComp.frost_end_time = 0;
}
}
if (attrsComp.stun_end_time > 0) {
attrsComp.stun_end_time -= 0.1;
if (attrsComp.stun_end_time <= 0) {
attrsComp.stun_end_time = 0;
}
}
}
void e;
}
}

View File

@@ -13,6 +13,7 @@ import { GameEvent } from "../common/config/GameEvent";
import { SkillTriggerType } from "../common/config/heroSet"; import { SkillTriggerType } from "../common/config/heroSet";
import { SkillTriggerHelper } from "./SkillTriggerHelper"; import { SkillTriggerHelper } from "./SkillTriggerHelper";
import { MissionEconomy } from "../map/MissionEconomy"; import { MissionEconomy } from "../map/MissionEconomy";
import { mLogger } from "../common/Logger";
import { MissionHeroComp } from "../map/MissionHeroComp"; import { MissionHeroComp } from "../map/MissionHeroComp";
import { buffManager } from "./BuffManager"; import { buffManager } from "./BuffManager";
@@ -142,10 +143,11 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
} }
} }
console.log("[SCastSystem] forceCastCardSkill: casting skill", s_uuid, "castTimes", castTimes, "targetPos", targetPos); mLogger.log(this.debugMode, "SCastSystem", "forceCastCardSkill: casting skill", s_uuid, "castTimes", castTimes, "targetPos", targetPos, "isFriendly", isFriendly, "buff_value", config.buff_value, "timed_buff_id", config.timed_buff_id);
for (let i = 0; i < castTimes; i++) { for (let i = 0; i < castTimes; i++) {
if (isFriendly) { if (isFriendly) {
const friendlyTargets = this.resolveFriendlyTargets(targetEids, FacSet.HERO); const friendlyTargets = this.resolveFriendlyTargets(targetEids, FacSet.HERO);
mLogger.log(this.debugMode, "SCastSystem", "friendlyTargets count =", friendlyTargets.length);
if (friendlyTargets.length === 0) continue; if (friendlyTargets.length === 0) continue;
this.applyFriendlySkillEffects(s_uuid, cardLv, config, null as any, mockAttrs, friendlyTargets, spawnPos); this.applyFriendlySkillEffects(s_uuid, cardLv, config, null as any, mockAttrs, friendlyTargets, spawnPos);
} else { } else {
@@ -455,12 +457,11 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
} }
} }
private applyActualFriendlyEffect(target: HeroViewComp, kind: SkillKind, sAp: number, _cAttrsComp: HeroAttrsComp, config: SkillConfig, sUp: any, _skillLv: number = 1) { private applyActualFriendlyEffect(target: HeroViewComp, kind: SkillKind, sAp: number, _cAttrsComp: HeroAttrsComp, config: SkillConfig, sUp: any, _skillLv: number = 1) {
if (!target.ent) return; if (!target.ent) return;
const model = target.ent.get(HeroAttrsComp); const model = target.ent.get(HeroAttrsComp);
if (!model || model.is_dead) return; if (!model || model.is_dead) return;
mLogger.log(this.debugMode, "SCastSystem", `applyActualFriendlyEffect: skill=${config.uuid} kind=${kind} buff_type=${config.buff_type} timed_buff_id=${config.timed_buff_id} buff_value=${config.buff_value} target=${model.hero_name}`);
if (config.endAnm && config.endAnm !== "") { if (config.endAnm && config.endAnm !== "") {
target.playEnd(config.endAnm); target.playEnd(config.endAnm);
@@ -493,7 +494,8 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
target.ent, target.ent,
config.timed_buff_id, config.timed_buff_id,
_cAttrsComp.hero_uuid, _cAttrsComp.hero_uuid,
_cAttrsComp.ap _cAttrsComp.ap,
config.buff_value !== undefined ? { value: config.buff_value } : undefined
); );
return; return;
} }

View File

@@ -355,8 +355,9 @@ export class HInfoComp extends CCComp {
} }
// ---- 数值标签 ---- // ---- 数值标签 ----
// 攻击力显示最终值(含计时 buff 修饰),实时反映药水等限时强化
if (this.apLabel) { if (this.apLabel) {
const currentAp = Math.max(0, Math.floor(this.model.ap ?? 0)); const currentAp = Math.max(0, Math.floor(this.model.getFinalAp()));
const baseAp = Math.max(0, Math.floor(this.model.base_ap ?? 0)); const baseAp = Math.max(0, Math.floor(this.model.base_ap ?? 0));
this.apLabel.string = `${currentAp}`; this.apLabel.string = `${currentAp}`;
if (this.apPlusLabel) { if (this.apPlusLabel) {
@@ -370,7 +371,7 @@ export class HInfoComp extends CCComp {
} }
} }
if (this.hpLabel) { if (this.hpLabel) {
const currentHp = Math.max(0, Math.floor(this.model.hp_max ?? 0)); const currentHp = Math.max(0, Math.floor(this.model.getFinalHpMax()));
const baseHp = Math.max(0, Math.floor(this.model.base_hp ?? 0)); const baseHp = Math.max(0, Math.floor(this.model.base_hp ?? 0));
this.hpLabel.string = `${currentHp}`; this.hpLabel.string = `${currentHp}`;
if (this.hpPlusLabel) { if (this.hpPlusLabel) {

View File

@@ -28,6 +28,9 @@ import { SBox } from "./SBox";
import { oops } from "db://oops-framework/core/Oops"; import { oops } from "db://oops-framework/core/Oops";
import { GameEvent } from "../common/config/GameEvent"; import { GameEvent } from "../common/config/GameEvent";
import { BoxSet } from "../common/config/GameSet"; import { BoxSet } from "../common/config/GameSet";
import { SkillOverrides, SkillSet } from "../common/config/SkillSet";
import { smc } from "../common/SingletonModuleComp";
import { buffManager } from "../hero/BuffManager";
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
/** 技能槽位数据结构 */ /** 技能槽位数据结构 */
@@ -73,6 +76,7 @@ export class MissSkillsComp extends CCComp {
/** 注册事件监听 */ /** 注册事件监听 */
onLoad() { onLoad() {
oops.message.on(GameEvent.UseSkillCard, this.onUseSkillCard, this); oops.message.on(GameEvent.UseSkillCard, this.onUseSkillCard, this);
oops.message.on(GameEvent.UseItemCard, this.onUseItemCard, this);
oops.message.on(GameEvent.RemoveSkillBox, this.onRemoveSkillBox, this); oops.message.on(GameEvent.RemoveSkillBox, this.onRemoveSkillBox, this);
} }
@@ -80,6 +84,7 @@ export class MissSkillsComp extends CCComp {
onDestroy() { onDestroy() {
super.onDestroy(); super.onDestroy();
oops.message.off(GameEvent.UseSkillCard, this.onUseSkillCard, this); oops.message.off(GameEvent.UseSkillCard, this.onUseSkillCard, this);
oops.message.off(GameEvent.UseItemCard, this.onUseItemCard, this);
oops.message.off(GameEvent.RemoveSkillBox, this.onRemoveSkillBox, this); oops.message.off(GameEvent.RemoveSkillBox, this.onRemoveSkillBox, this);
} }
@@ -138,10 +143,48 @@ export class MissSkillsComp extends CCComp {
*/ */
private onUseSkillCard(event: string, args: any) { private onUseSkillCard(event: string, args: any) {
const payload = args ?? event; const payload = args ?? event;
const uuid = Number(payload?.uuid ?? 0); // 卡 uuid 仅用于查配置;真正施法用技能 idpayload.skill缺省时退回 uuid兼容技能卡直接用技能 id 的场景)
const skillUuid = Number(payload?.skill ?? payload?.uuid ?? 0);
const card_lv = Math.max(1, Math.floor(Number(payload?.card_lv ?? 1))); const card_lv = Math.max(1, Math.floor(Number(payload?.card_lv ?? 1)));
if (!uuid) return; if (!skillUuid) return;
this.addSkill(uuid, card_lv); // 药水/技能卡的 overrides含 buff_value需透传到技能实体
this.addSkill(skillUuid, card_lv, payload?.overrides);
}
/**
* 处理药水卡使用事件:直接对全队存活英雄施加计时 buff不经过 SBox 施法流程。
*
* 设计:
* 药水是"即时全队强化",无需节点、动画、槽位;
* 从技能配置取 timed_buff_id遍历 heroGrid 对每个存活英雄 applyBuff
* buff_value 覆写值透传到 ActiveBuff.value_override。
*
* @param event 事件名
* @param args 卡牌数据(含 skill、overrides
*/
private onUseItemCard(event: string, args: any) {
const payload = args ?? event;
const skillId = Number(payload?.skill ?? 0);
const config = SkillSet[skillId];
if (!config) {
mLogger.warn(this.debugMode, "MissSkillsComp", `potion skill ${skillId} config not found`);
return;
}
const buffId = config.timed_buff_id;
if (buffId === undefined) {
mLogger.warn(this.debugMode, "MissSkillsComp", `potion skill ${skillId} has no timed_buff_id`);
return;
}
const buffValue = payload?.overrides?.buff_value;
let applied = 0;
for (const eid of smc.mission.heroGrid) {
if (eid <= 0) continue;
const entity = ecs.getEntityByEid(eid);
if (!entity) continue;
buffManager.applyBuff(entity, buffId, 0, 0, buffValue !== undefined ? { value: buffValue } : undefined);
applied++;
}
mLogger.log(this.debugMode, "MissSkillsComp", `potion applied: skill=${skillId} buff=${buffId} value=${buffValue} heroes=${applied}`);
} }
start() { start() {
@@ -157,7 +200,7 @@ export class MissSkillsComp extends CCComp {
* @param uuid 技能 UUID * @param uuid 技能 UUID
* @param card_lv 技能卡等级 * @param card_lv 技能卡等级
*/ */
addSkill(uuid: number, card_lv: number) { addSkill(uuid: number, card_lv: number, overrides?: SkillOverrides) {
if (!this.skill_box) { if (!this.skill_box) {
mLogger.error(this.debugMode, "MissSkillsComp", "skill_box prefab not set"); mLogger.error(this.debugMode, "MissSkillsComp", "skill_box prefab not set");
return; return;
@@ -174,7 +217,7 @@ export class MissSkillsComp extends CCComp {
// 使用 ECS 实体创建技能节点 // 使用 ECS 实体创建技能节点
let sbox = ecs.getEntity<SBox>(SBox); let sbox = ecs.getEntity<SBox>(SBox);
let pos = new Vec3(this.slots[emptyIndex].x, this.slots[emptyIndex].y, 0); let pos = new Vec3(this.slots[emptyIndex].x, this.slots[emptyIndex].y, 0);
let node = sbox.load(uuid, card_lv, pos, this.skill_box); let node = sbox.load(uuid, card_lv, pos, this.skill_box, overrides);
this.slots[emptyIndex].used = true; this.slots[emptyIndex].used = true;
this.slots[emptyIndex].node = node; this.slots[emptyIndex].node = node;

View File

@@ -2,6 +2,7 @@ import { instantiate, Prefab, 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 { smc } from "../common/SingletonModuleComp"; import { smc } from "../common/SingletonModuleComp";
import { SkillBoxComp } from "./SkillBoxComp"; import { SkillBoxComp } from "./SkillBoxComp";
import { SkillOverrides } from "../common/config/SkillSet";
/** SBox 实体:负责技能卡效果节点创建、初始化与销毁流程 */ /** SBox 实体:负责技能卡效果节点创建、初始化与销毁流程 */
@ecs.register(`SBox`) @ecs.register(`SBox`)
@@ -29,7 +30,7 @@ export class SBox extends ecs.Entity {
* 1) 创建节点并挂到 SKILL 层 * 1) 创建节点并挂到 SKILL 层
* 2) 初始化表现与属性数据 * 2) 初始化表现与属性数据
*/ */
load(uuid: number, card_lv: number, pos: Vec3, prefab: Prefab): Node { load(uuid: number, card_lv: number, pos: Vec3, prefab: Prefab, overrides?: SkillOverrides): Node {
let node = instantiate(prefab); let node = instantiate(prefab);
let scene = smc.map.MapView.scene; let scene = smc.map.MapView.scene;
@@ -44,8 +45,8 @@ export class SBox extends ecs.Entity {
let sboxComp = node.getComponent(SkillBoxComp) || node.addComponent(SkillBoxComp); let sboxComp = node.getComponent(SkillBoxComp) || node.addComponent(SkillBoxComp);
this.add(sboxComp); this.add(sboxComp);
// 初始化业务逻辑 // 初始化业务逻辑(透传药水卡 overrides含 buff_value
sboxComp.init(uuid, card_lv); sboxComp.init(uuid, card_lv, overrides);
return node; return node;
} }

View File

@@ -166,10 +166,10 @@ export class SkillBoxComp extends CCComp {
* @param uuid 卡牌 UUID * @param uuid 卡牌 UUID
* @param card_lv 技能卡等级 * @param card_lv 技能卡等级
*/ */
init(uuid: number, card_lv: number) { init(uuid: number, card_lv: number, overrides?: SkillOverrides) {
this.card_lv = card_lv; this.card_lv = card_lv;
// 查询触发配置 // 查询触发配置(药水卡不在 SkillCardList会走 else 分支)
const config = SkillCardList.find(c => c.uuid === uuid); const config = SkillCardList.find(c => c.uuid === uuid);
if (config) { if (config) {
this.s_uuid = config.skill ?? uuid; // 获取实际的技能 UUID this.s_uuid = config.skill ?? uuid; // 获取实际的技能 UUID
@@ -177,14 +177,18 @@ export class SkillBoxComp extends CCComp {
this.trigger_times = config.t_times ?? 1; this.trigger_times = config.t_times ?? 1;
this.trigger_interval = config.t_inv ?? 0; this.trigger_interval = config.t_inv ?? 0;
this.keep_waves = config.keep_waves ?? 0; this.keep_waves = config.keep_waves ?? 0;
this.overrides = config.overrides; this.overrides = overrides ?? config.overrides; // 外部透传(药水卡)优先
this.field = config.field || []; this.field = config.field || [];
this.card_icon = config.icon; // 保存卡牌自定义图标(优先级最高) this.card_icon = config.icon; // 保存卡牌自定义图标(优先级最高)
// 读取触发类型与上限(兜底默认值,避免 undefined // 读取触发类型与上限(兜底默认值,避免 undefined
this.trigger_type = config.trigger_type ?? CardTriggerType.Instant; this.trigger_type = config.trigger_type ?? CardTriggerType.Instant;
this.trigger_limit = config.trigger_limit ?? Infinity; this.trigger_limit = config.trigger_limit ?? Infinity;
} else { } else {
// 药水卡等uuid 即技能 id触发类型默认 Instant即时生效一次
this.s_uuid = uuid; this.s_uuid = uuid;
this.overrides = overrides;
this.trigger_type = CardTriggerType.Instant;
this.trigger_times = 1;
} }
this.current_trigger_times = 0; this.current_trigger_times = 0;