Compare commits
16 Commits
c27c81cfa6
...
card0614
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4fee02d82e | ||
|
|
15d14f7d59 | ||
|
|
9579c4f75e | ||
|
|
d54e6ce1d6 | ||
|
|
d06c99e2f1 | ||
|
|
76082d8e1f | ||
|
|
695a9e2b66 | ||
|
|
c6b5e1431f | ||
|
|
7fa18329d6 | ||
|
|
a2c397120c | ||
|
|
cb2a72da52 | ||
|
|
9da3e2d9fd | ||
|
|
eb4b370533 | ||
|
|
a3375ec3b6 | ||
|
|
011e7b3dde | ||
|
|
038abdc5d2 |
@@ -38,10 +38,13 @@
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 110
|
||||
},
|
||||
{
|
||||
"__id__": 112
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 112
|
||||
"__id__": 114
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
@@ -95,7 +98,7 @@
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 9.114,
|
||||
"x": 0,
|
||||
"y": 10,
|
||||
"z": 0
|
||||
},
|
||||
@@ -217,7 +220,7 @@
|
||||
"__id__": 17
|
||||
}
|
||||
],
|
||||
"_active": false,
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 25
|
||||
@@ -235,7 +238,7 @@
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": -9.738,
|
||||
"y": -7.84,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
@@ -287,7 +290,7 @@
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": -35,
|
||||
"x": -20,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
@@ -328,8 +331,8 @@
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 70,
|
||||
"height": 10
|
||||
"width": 40,
|
||||
"height": 5
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
@@ -506,8 +509,8 @@
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 240,
|
||||
"height": 40
|
||||
"width": 140,
|
||||
"height": 23.333333333333336
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
@@ -631,8 +634,8 @@
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 70,
|
||||
"height": 10
|
||||
"width": 40,
|
||||
"height": 5
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
@@ -859,7 +862,7 @@
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 40,
|
||||
"height": 11
|
||||
"height": 9
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
@@ -1037,7 +1040,7 @@
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 140,
|
||||
"height": 43.333333333333336
|
||||
"height": 36.66666666666667
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
@@ -1162,7 +1165,7 @@
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 40,
|
||||
"height": 11
|
||||
"height": 9
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
@@ -1347,7 +1350,7 @@
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": -25,
|
||||
"x": -20,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
@@ -1388,8 +1391,8 @@
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 50,
|
||||
"height": 10
|
||||
"width": 40,
|
||||
"height": 9
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
@@ -1691,8 +1694,8 @@
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 50,
|
||||
"height": 10
|
||||
"width": 40,
|
||||
"height": 9
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
@@ -1813,7 +1816,7 @@
|
||||
"__id__": 99
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_active": false,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 105
|
||||
@@ -2520,8 +2523,8 @@
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 70,
|
||||
"height": 20
|
||||
"width": 40,
|
||||
"height": 11
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
@@ -2534,6 +2537,33 @@
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "cdvV5hAkdEaY6AT6urHKuf"
|
||||
},
|
||||
{
|
||||
"__type__": "c4181/FEWhKbY0D0PLdCyKi",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 113
|
||||
},
|
||||
"hpProgressBar": {
|
||||
"__id__": 53
|
||||
},
|
||||
"lvLabel": null,
|
||||
"shieldProgressBar": {
|
||||
"__id__": 77
|
||||
},
|
||||
"hpBarSprite": {
|
||||
"__id__": 36
|
||||
},
|
||||
"_id": "a77QVRkP5NX4b+LyqmW1KJ"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "3eCKBFOJhLHKqcnak/mi3d"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
|
||||
@@ -1398,7 +1398,7 @@
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 21.504,
|
||||
"y": -31.947,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
@@ -1875,7 +1875,7 @@
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 21.504,
|
||||
"y": -50.813,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
@@ -2352,7 +2352,7 @@
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"y": -150,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
@@ -2618,6 +2618,8 @@
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "6bE0ieRMBGyYHdxvuJ03FA",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
@@ -3432,6 +3434,8 @@
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "256TxMVzhHQopA08O7v8nq",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
@@ -3471,6 +3475,8 @@
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "5dWwAe3IFHRJuoSicXBEs8",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
@@ -3710,6 +3716,8 @@
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "b9zLdCeJlE5pPiK++dLgBX",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
@@ -4388,6 +4396,8 @@
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "9d2p/canpFGof2O/w8JyTj",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
@@ -4427,6 +4437,8 @@
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "6bkL20JyRDOI6ycVYKl/ie",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
@@ -4495,6 +4507,8 @@
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "14GnCNU65BbJPIzLWE/Oiz",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
@@ -7363,6 +7377,8 @@
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "c4IqMKgXNExa5w4EAciRxE",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
@@ -8202,7 +8218,7 @@
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "LINE2",
|
||||
"_name": "BOSS",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
@@ -8273,7 +8289,7 @@
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "ea767WaZRHo4s0bZQfN8zP"
|
||||
"fileId": "3fVB8r2UFAB5QujD6LOw6s"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
@@ -8283,14 +8299,14 @@
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "60UdPtJn9ALLHCveLwT1bT",
|
||||
"fileId": "f4iFaXCXNKorfGJFH32POa",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "HERO",
|
||||
"_name": "MON",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
@@ -8361,7 +8377,7 @@
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "dasmpuTSVM7qA3QW9/3XjQ"
|
||||
"fileId": "ea767WaZRHo4s0bZQfN8zP"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
@@ -8371,14 +8387,14 @@
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "eaiasKNEFO6qvodGhL4a0b",
|
||||
"fileId": "60UdPtJn9ALLHCveLwT1bT",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "LINE1",
|
||||
"_name": "HERO",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
@@ -8449,7 +8465,7 @@
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "b8C5CFg5lM4oUHMeSrc/sV"
|
||||
"fileId": "dasmpuTSVM7qA3QW9/3XjQ"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
@@ -8459,14 +8475,14 @@
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "4dcNJaDM1CLI9q3fIqHZ/U",
|
||||
"fileId": "eaiasKNEFO6qvodGhL4a0b",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "LINE3",
|
||||
"_name": "LINE1",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
@@ -8537,7 +8553,7 @@
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "a5LMIIbHtOKK10K5do5dSQ"
|
||||
"fileId": "b8C5CFg5lM4oUHMeSrc/sV"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
@@ -8547,14 +8563,14 @@
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "a6CBSkrzZIurlX0D/HzXDp",
|
||||
"fileId": "4dcNJaDM1CLI9q3fIqHZ/U",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "BOOS",
|
||||
"_name": "LINE3",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
@@ -8625,7 +8641,7 @@
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "3fVB8r2UFAB5QujD6LOw6s"
|
||||
"fileId": "a5LMIIbHtOKK10K5do5dSQ"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
@@ -8635,7 +8651,7 @@
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "f4iFaXCXNKorfGJFH32POa",
|
||||
"fileId": "a6CBSkrzZIurlX0D/HzXDp",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
@@ -8893,6 +8909,8 @@
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "35iAcUUYpE8akTtTCX1ITo",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
@@ -8932,6 +8950,8 @@
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "68Q5vEQWBINrggngtTZ7wh",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,15 +7,26 @@
|
||||
"embeddedPlayerGroups": []
|
||||
},
|
||||
"_native": "",
|
||||
"sample": 8,
|
||||
"sample": 24,
|
||||
"speed": 1,
|
||||
"wrapMode": 2,
|
||||
"wrapMode": 1,
|
||||
"enableTrsBlending": false,
|
||||
"_duration": 0,
|
||||
"_hash": 500763545,
|
||||
"_tracks": [],
|
||||
"_exoticAnimation": null,
|
||||
"_events": [],
|
||||
"_events": [
|
||||
{
|
||||
"frame": 0.08333333333333333,
|
||||
"func": "",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"frame": 0.08333333333333333,
|
||||
"func": "atk",
|
||||
"params": []
|
||||
}
|
||||
],
|
||||
"_embeddedPlayers": [],
|
||||
"_additiveSettings": {
|
||||
"__id__": 1
|
||||
|
||||
116
assets/resources/game/skill/anm/atk/atk02.anim
Normal file
116
assets/resources/game/skill/anm/atk/atk02.anim
Normal file
@@ -0,0 +1,116 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.AnimationClip",
|
||||
"_name": "atk01",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {
|
||||
"embeddedPlayerGroups": []
|
||||
},
|
||||
"_native": "",
|
||||
"sample": 24,
|
||||
"speed": 1,
|
||||
"wrapMode": 1,
|
||||
"enableTrsBlending": false,
|
||||
"_duration": 0.20833333333333334,
|
||||
"_hash": 500763545,
|
||||
"_tracks": [
|
||||
{
|
||||
"__id__": 1
|
||||
}
|
||||
],
|
||||
"_exoticAnimation": null,
|
||||
"_events": [
|
||||
{
|
||||
"frame": 0.08333333333333333,
|
||||
"func": "",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"frame": 0.08333333333333333,
|
||||
"func": "atk",
|
||||
"params": []
|
||||
}
|
||||
],
|
||||
"_embeddedPlayers": [],
|
||||
"_additiveSettings": {
|
||||
"__id__": 7
|
||||
},
|
||||
"_auxiliaryCurveEntries": []
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.ObjectTrack",
|
||||
"_binding": {
|
||||
"__type__": "cc.animation.TrackBinding",
|
||||
"path": {
|
||||
"__id__": 2
|
||||
},
|
||||
"proxy": null
|
||||
},
|
||||
"_channel": {
|
||||
"__id__": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.TrackPath",
|
||||
"_paths": [
|
||||
{
|
||||
"__id__": 3
|
||||
},
|
||||
{
|
||||
"__id__": 4
|
||||
},
|
||||
"spriteFrame"
|
||||
]
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.HierarchyPath",
|
||||
"path": "Node"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.ComponentPath",
|
||||
"component": "cc.Sprite"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.ObjectCurve",
|
||||
"_times": [
|
||||
0,
|
||||
0.041666666666666664,
|
||||
0.08333333333333333,
|
||||
0.125,
|
||||
0.16666666666666666
|
||||
],
|
||||
"_values": [
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@c9de1",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@3c745",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@1ebb0",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@0e5a2",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@360bd",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"__type__": "cc.AnimationClipAdditiveSettings",
|
||||
"enabled": false,
|
||||
"refClip": null
|
||||
}
|
||||
]
|
||||
13
assets/resources/game/skill/anm/atk/atk02.anim.meta
Normal file
13
assets/resources/game/skill/anm/atk/atk02.anim.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "2.0.3",
|
||||
"importer": "animation-clip",
|
||||
"imported": true,
|
||||
"uuid": "6b9c9f74-0168-4b57-824d-bfcc2cd1785d",
|
||||
"files": [
|
||||
".cconb"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"name": "atk02"
|
||||
}
|
||||
}
|
||||
116
assets/resources/game/skill/anm/atk/atk03.anim
Normal file
116
assets/resources/game/skill/anm/atk/atk03.anim
Normal file
@@ -0,0 +1,116 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.AnimationClip",
|
||||
"_name": "atk01",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {
|
||||
"embeddedPlayerGroups": []
|
||||
},
|
||||
"_native": "",
|
||||
"sample": 24,
|
||||
"speed": 1,
|
||||
"wrapMode": 1,
|
||||
"enableTrsBlending": false,
|
||||
"_duration": 0.20833333333333334,
|
||||
"_hash": 500763545,
|
||||
"_tracks": [
|
||||
{
|
||||
"__id__": 1
|
||||
}
|
||||
],
|
||||
"_exoticAnimation": null,
|
||||
"_events": [
|
||||
{
|
||||
"frame": 0.08333333333333333,
|
||||
"func": "",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"frame": 0.08333333333333333,
|
||||
"func": "atk",
|
||||
"params": []
|
||||
}
|
||||
],
|
||||
"_embeddedPlayers": [],
|
||||
"_additiveSettings": {
|
||||
"__id__": 7
|
||||
},
|
||||
"_auxiliaryCurveEntries": []
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.ObjectTrack",
|
||||
"_binding": {
|
||||
"__type__": "cc.animation.TrackBinding",
|
||||
"path": {
|
||||
"__id__": 2
|
||||
},
|
||||
"proxy": null
|
||||
},
|
||||
"_channel": {
|
||||
"__id__": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.TrackPath",
|
||||
"_paths": [
|
||||
{
|
||||
"__id__": 3
|
||||
},
|
||||
{
|
||||
"__id__": 4
|
||||
},
|
||||
"spriteFrame"
|
||||
]
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.HierarchyPath",
|
||||
"path": "Node"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.ComponentPath",
|
||||
"component": "cc.Sprite"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.ObjectCurve",
|
||||
"_times": [
|
||||
0,
|
||||
0.041666666666666664,
|
||||
0.08333333333333333,
|
||||
0.125,
|
||||
0.16666666666666666
|
||||
],
|
||||
"_values": [
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@c9de1",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@3c745",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@1ebb0",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@0e5a2",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@360bd",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"__type__": "cc.AnimationClipAdditiveSettings",
|
||||
"enabled": false,
|
||||
"refClip": null
|
||||
}
|
||||
]
|
||||
13
assets/resources/game/skill/anm/atk/atk03.anim.meta
Normal file
13
assets/resources/game/skill/anm/atk/atk03.anim.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "2.0.3",
|
||||
"importer": "animation-clip",
|
||||
"imported": true,
|
||||
"uuid": "26398731-5541-44ca-b2b7-4947dc9bf7f7",
|
||||
"files": [
|
||||
".cconb"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"name": "atk03"
|
||||
}
|
||||
}
|
||||
116
assets/resources/game/skill/anm/atk/atk04.anim
Normal file
116
assets/resources/game/skill/anm/atk/atk04.anim
Normal file
@@ -0,0 +1,116 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.AnimationClip",
|
||||
"_name": "atk01",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {
|
||||
"embeddedPlayerGroups": []
|
||||
},
|
||||
"_native": "",
|
||||
"sample": 24,
|
||||
"speed": 1,
|
||||
"wrapMode": 1,
|
||||
"enableTrsBlending": false,
|
||||
"_duration": 0.20833333333333334,
|
||||
"_hash": 500763545,
|
||||
"_tracks": [
|
||||
{
|
||||
"__id__": 1
|
||||
}
|
||||
],
|
||||
"_exoticAnimation": null,
|
||||
"_events": [
|
||||
{
|
||||
"frame": 0.08333333333333333,
|
||||
"func": "",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"frame": 0.08333333333333333,
|
||||
"func": "atk",
|
||||
"params": []
|
||||
}
|
||||
],
|
||||
"_embeddedPlayers": [],
|
||||
"_additiveSettings": {
|
||||
"__id__": 7
|
||||
},
|
||||
"_auxiliaryCurveEntries": []
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.ObjectTrack",
|
||||
"_binding": {
|
||||
"__type__": "cc.animation.TrackBinding",
|
||||
"path": {
|
||||
"__id__": 2
|
||||
},
|
||||
"proxy": null
|
||||
},
|
||||
"_channel": {
|
||||
"__id__": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.TrackPath",
|
||||
"_paths": [
|
||||
{
|
||||
"__id__": 3
|
||||
},
|
||||
{
|
||||
"__id__": 4
|
||||
},
|
||||
"spriteFrame"
|
||||
]
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.HierarchyPath",
|
||||
"path": "Node"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.ComponentPath",
|
||||
"component": "cc.Sprite"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.ObjectCurve",
|
||||
"_times": [
|
||||
0,
|
||||
0.041666666666666664,
|
||||
0.08333333333333333,
|
||||
0.125,
|
||||
0.16666666666666666
|
||||
],
|
||||
"_values": [
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@c9de1",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@3c745",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@1ebb0",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@0e5a2",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@360bd",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"__type__": "cc.AnimationClipAdditiveSettings",
|
||||
"enabled": false,
|
||||
"refClip": null
|
||||
}
|
||||
]
|
||||
13
assets/resources/game/skill/anm/atk/atk04.anim.meta
Normal file
13
assets/resources/game/skill/anm/atk/atk04.anim.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "2.0.3",
|
||||
"importer": "animation-clip",
|
||||
"imported": true,
|
||||
"uuid": "0ad94bf2-3b2d-4f80-8500-68c5e33e2ed1",
|
||||
"files": [
|
||||
".cconb"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"name": "atk04"
|
||||
}
|
||||
}
|
||||
116
assets/resources/game/skill/anm/atk/atk05.anim
Normal file
116
assets/resources/game/skill/anm/atk/atk05.anim
Normal file
@@ -0,0 +1,116 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.AnimationClip",
|
||||
"_name": "atk01",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {
|
||||
"embeddedPlayerGroups": []
|
||||
},
|
||||
"_native": "",
|
||||
"sample": 24,
|
||||
"speed": 1,
|
||||
"wrapMode": 1,
|
||||
"enableTrsBlending": false,
|
||||
"_duration": 0.20833333333333334,
|
||||
"_hash": 500763545,
|
||||
"_tracks": [
|
||||
{
|
||||
"__id__": 1
|
||||
}
|
||||
],
|
||||
"_exoticAnimation": null,
|
||||
"_events": [
|
||||
{
|
||||
"frame": 0.08333333333333333,
|
||||
"func": "",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"frame": 0.08333333333333333,
|
||||
"func": "atk",
|
||||
"params": []
|
||||
}
|
||||
],
|
||||
"_embeddedPlayers": [],
|
||||
"_additiveSettings": {
|
||||
"__id__": 7
|
||||
},
|
||||
"_auxiliaryCurveEntries": []
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.ObjectTrack",
|
||||
"_binding": {
|
||||
"__type__": "cc.animation.TrackBinding",
|
||||
"path": {
|
||||
"__id__": 2
|
||||
},
|
||||
"proxy": null
|
||||
},
|
||||
"_channel": {
|
||||
"__id__": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.TrackPath",
|
||||
"_paths": [
|
||||
{
|
||||
"__id__": 3
|
||||
},
|
||||
{
|
||||
"__id__": 4
|
||||
},
|
||||
"spriteFrame"
|
||||
]
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.HierarchyPath",
|
||||
"path": "Node"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.ComponentPath",
|
||||
"component": "cc.Sprite"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.ObjectCurve",
|
||||
"_times": [
|
||||
0,
|
||||
0.041666666666666664,
|
||||
0.08333333333333333,
|
||||
0.125,
|
||||
0.16666666666666666
|
||||
],
|
||||
"_values": [
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@c9de1",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@3c745",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@1ebb0",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@0e5a2",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@360bd",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"__type__": "cc.AnimationClipAdditiveSettings",
|
||||
"enabled": false,
|
||||
"refClip": null
|
||||
}
|
||||
]
|
||||
13
assets/resources/game/skill/anm/atk/atk05.anim.meta
Normal file
13
assets/resources/game/skill/anm/atk/atk05.anim.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "2.0.3",
|
||||
"importer": "animation-clip",
|
||||
"imported": true,
|
||||
"uuid": "ba0a95bf-2ea1-4d27-9c4f-cbd970ca558c",
|
||||
"files": [
|
||||
".cconb"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"name": "atk05"
|
||||
}
|
||||
}
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -336,4 +340,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -336,4 +340,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -336,4 +340,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -336,4 +340,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -336,4 +340,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.Prefab",
|
||||
"_name": "atk",
|
||||
"_name": "atk1",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_native": "",
|
||||
@@ -13,7 +13,7 @@
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "atk",
|
||||
"_name": "atk1",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": null,
|
||||
@@ -108,8 +108,8 @@
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": -0.5,
|
||||
"y": 0.5,
|
||||
"x": 1.3,
|
||||
"y": 1.1,
|
||||
"z": 1
|
||||
},
|
||||
"_mobility": 0,
|
||||
@@ -136,8 +136,8 @@
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 139,
|
||||
"height": 128
|
||||
"width": 95,
|
||||
"height": 96
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
@@ -186,7 +186,7 @@
|
||||
"_isTrimmedMode": true,
|
||||
"_useGrayscale": false,
|
||||
"_atlas": {
|
||||
"__uuid__": "3d46f945-3f07-477e-a95a-b49557d552c6",
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20",
|
||||
"__expectedType__": "cc.SpriteAtlas"
|
||||
},
|
||||
"_id": ""
|
||||
@@ -222,8 +222,8 @@
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 30,
|
||||
"height": 50
|
||||
"width": 120,
|
||||
"height": 120
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
@@ -248,8 +248,12 @@
|
||||
"__prefab": {
|
||||
"__id__": 11
|
||||
},
|
||||
"atk_x": 0,
|
||||
"atk_y": 0,
|
||||
"atk_x": 20,
|
||||
"atk_y": 40,
|
||||
"runType": 2,
|
||||
"endType": 0,
|
||||
"speed": 720,
|
||||
"time": 0,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
@@ -315,8 +319,8 @@
|
||||
},
|
||||
"_size": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 30,
|
||||
"height": 50
|
||||
"width": 120,
|
||||
"height": 120
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
@@ -336,7 +340,7 @@
|
||||
"__prefab": {
|
||||
"__id__": 17
|
||||
},
|
||||
"playOnLoad": false,
|
||||
"playOnLoad": true,
|
||||
"_clips": [
|
||||
{
|
||||
"__uuid__": "45017156-064b-43f2-a24e-176b6ce17ad8",
|
||||
@@ -8,6 +8,6 @@
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "atk"
|
||||
"syncNodeName": "atk1"
|
||||
}
|
||||
}
|
||||
375
assets/resources/game/skill/atk/atk2.prefab
Normal file
375
assets/resources/game/skill/atk/atk2.prefab
Normal file
@@ -0,0 +1,375 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.Prefab",
|
||||
"_name": "atk2",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_native": "",
|
||||
"data": {
|
||||
"__id__": 1
|
||||
},
|
||||
"optimizationPolicy": 0,
|
||||
"persistent": false
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "atk2",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": null,
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 2
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 8
|
||||
},
|
||||
{
|
||||
"__id__": 10
|
||||
},
|
||||
{
|
||||
"__id__": 12
|
||||
},
|
||||
{
|
||||
"__id__": 14
|
||||
},
|
||||
{
|
||||
"__id__": 16
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 18
|
||||
},
|
||||
"_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": "Node",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 3
|
||||
},
|
||||
{
|
||||
"__id__": 5
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 7
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1.3,
|
||||
"y": 1.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": 95,
|
||||
"height": 96
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "93pNmvtQlLSqtTgIepyEmA"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Sprite",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 2
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 6
|
||||
},
|
||||
"_customMaterial": null,
|
||||
"_srcBlendFactor": 2,
|
||||
"_dstBlendFactor": 4,
|
||||
"_color": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 255,
|
||||
"g": 255,
|
||||
"b": 255,
|
||||
"a": 255
|
||||
},
|
||||
"_spriteFrame": {
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@3c745",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
"_type": 0,
|
||||
"_fillType": 0,
|
||||
"_sizeMode": 1,
|
||||
"_fillCenter": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_fillStart": 0,
|
||||
"_fillRange": 0,
|
||||
"_isTrimmedMode": true,
|
||||
"_useGrayscale": false,
|
||||
"_atlas": {
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20",
|
||||
"__expectedType__": "cc.SpriteAtlas"
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "12eKc8gltBz50frJCS5+ww"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "3arqAMBz1MvoXBzeDaL5M/",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.UITransform",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 9
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 120,
|
||||
"height": 120
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "63NP9yq3hEUKD/OZZZ5t7x"
|
||||
},
|
||||
{
|
||||
"__type__": "57aabs7TE1J5obTAZczc+64",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 11
|
||||
},
|
||||
"atk_x": 20,
|
||||
"atk_y": 40,
|
||||
"runType": 2,
|
||||
"endType": 0,
|
||||
"speed": 720,
|
||||
"time": 0,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "35nW0iQNBH2bqkWAr3MVkQ"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RigidBody2D",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 13
|
||||
},
|
||||
"enabledContactListener": true,
|
||||
"bullet": false,
|
||||
"awakeOnLoad": true,
|
||||
"_group": 1,
|
||||
"_type": 1,
|
||||
"_allowSleep": false,
|
||||
"_gravityScale": 1,
|
||||
"_linearDamping": 0,
|
||||
"_angularDamping": 0,
|
||||
"_linearVelocity": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_angularVelocity": 0,
|
||||
"_fixedRotation": false,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "57cr7S0YpK4oEZCavwXtIX"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.BoxCollider2D",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 15
|
||||
},
|
||||
"tag": 0,
|
||||
"_group": 1,
|
||||
"_density": 1,
|
||||
"_sensor": true,
|
||||
"_friction": 0.2,
|
||||
"_restitution": 0,
|
||||
"_offset": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_size": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 120,
|
||||
"height": 120
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "ebw5mObxNGGKxnJXDgX5gl"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Animation",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 17
|
||||
},
|
||||
"playOnLoad": true,
|
||||
"_clips": [
|
||||
{
|
||||
"__uuid__": "6b9c9f74-0168-4b57-824d-bfcc2cd1785d",
|
||||
"__expectedType__": "cc.AnimationClip"
|
||||
}
|
||||
],
|
||||
"_defaultClip": {
|
||||
"__uuid__": "6b9c9f74-0168-4b57-824d-bfcc2cd1785d",
|
||||
"__expectedType__": "cc.AnimationClip"
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "20U0hP/NZErJJXRCEib1lq"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "c46/YsCPVOJYA4mWEpNYRx",
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
13
assets/resources/game/skill/atk/atk2.prefab.meta
Normal file
13
assets/resources/game/skill/atk/atk2.prefab.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "1.1.50",
|
||||
"importer": "prefab",
|
||||
"imported": true,
|
||||
"uuid": "ff6e9a75-b1b9-448e-9cbd-d30de98fd21b",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "atk2"
|
||||
}
|
||||
}
|
||||
375
assets/resources/game/skill/atk/atk3.prefab
Normal file
375
assets/resources/game/skill/atk/atk3.prefab
Normal file
@@ -0,0 +1,375 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.Prefab",
|
||||
"_name": "atk3",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_native": "",
|
||||
"data": {
|
||||
"__id__": 1
|
||||
},
|
||||
"optimizationPolicy": 0,
|
||||
"persistent": false
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "atk3",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": null,
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 2
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 8
|
||||
},
|
||||
{
|
||||
"__id__": 10
|
||||
},
|
||||
{
|
||||
"__id__": 12
|
||||
},
|
||||
{
|
||||
"__id__": 14
|
||||
},
|
||||
{
|
||||
"__id__": 16
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 18
|
||||
},
|
||||
"_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": "Node",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 3
|
||||
},
|
||||
{
|
||||
"__id__": 5
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 7
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1.3,
|
||||
"y": 1.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": 95,
|
||||
"height": 96
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "93pNmvtQlLSqtTgIepyEmA"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Sprite",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 2
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 6
|
||||
},
|
||||
"_customMaterial": null,
|
||||
"_srcBlendFactor": 2,
|
||||
"_dstBlendFactor": 4,
|
||||
"_color": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 255,
|
||||
"g": 255,
|
||||
"b": 255,
|
||||
"a": 255
|
||||
},
|
||||
"_spriteFrame": {
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@3c745",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
"_type": 0,
|
||||
"_fillType": 0,
|
||||
"_sizeMode": 1,
|
||||
"_fillCenter": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_fillStart": 0,
|
||||
"_fillRange": 0,
|
||||
"_isTrimmedMode": true,
|
||||
"_useGrayscale": false,
|
||||
"_atlas": {
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20",
|
||||
"__expectedType__": "cc.SpriteAtlas"
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "12eKc8gltBz50frJCS5+ww"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "3arqAMBz1MvoXBzeDaL5M/",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.UITransform",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 9
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 120,
|
||||
"height": 120
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "63NP9yq3hEUKD/OZZZ5t7x"
|
||||
},
|
||||
{
|
||||
"__type__": "57aabs7TE1J5obTAZczc+64",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 11
|
||||
},
|
||||
"atk_x": 20,
|
||||
"atk_y": 40,
|
||||
"runType": 2,
|
||||
"endType": 0,
|
||||
"speed": 720,
|
||||
"time": 0,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "35nW0iQNBH2bqkWAr3MVkQ"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RigidBody2D",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 13
|
||||
},
|
||||
"enabledContactListener": true,
|
||||
"bullet": false,
|
||||
"awakeOnLoad": true,
|
||||
"_group": 1,
|
||||
"_type": 1,
|
||||
"_allowSleep": false,
|
||||
"_gravityScale": 1,
|
||||
"_linearDamping": 0,
|
||||
"_angularDamping": 0,
|
||||
"_linearVelocity": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_angularVelocity": 0,
|
||||
"_fixedRotation": false,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "57cr7S0YpK4oEZCavwXtIX"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.BoxCollider2D",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 15
|
||||
},
|
||||
"tag": 0,
|
||||
"_group": 1,
|
||||
"_density": 1,
|
||||
"_sensor": true,
|
||||
"_friction": 0.2,
|
||||
"_restitution": 0,
|
||||
"_offset": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_size": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 120,
|
||||
"height": 120
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "ebw5mObxNGGKxnJXDgX5gl"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Animation",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 17
|
||||
},
|
||||
"playOnLoad": true,
|
||||
"_clips": [
|
||||
{
|
||||
"__uuid__": "26398731-5541-44ca-b2b7-4947dc9bf7f7",
|
||||
"__expectedType__": "cc.AnimationClip"
|
||||
}
|
||||
],
|
||||
"_defaultClip": {
|
||||
"__uuid__": "26398731-5541-44ca-b2b7-4947dc9bf7f7",
|
||||
"__expectedType__": "cc.AnimationClip"
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "20U0hP/NZErJJXRCEib1lq"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "c46/YsCPVOJYA4mWEpNYRx",
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
13
assets/resources/game/skill/atk/atk3.prefab.meta
Normal file
13
assets/resources/game/skill/atk/atk3.prefab.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "1.1.50",
|
||||
"importer": "prefab",
|
||||
"imported": true,
|
||||
"uuid": "16ca6f33-f910-4202-add4-2862be6c9127",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "atk3"
|
||||
}
|
||||
}
|
||||
375
assets/resources/game/skill/atk/atk4.prefab
Normal file
375
assets/resources/game/skill/atk/atk4.prefab
Normal file
@@ -0,0 +1,375 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.Prefab",
|
||||
"_name": "atk4",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_native": "",
|
||||
"data": {
|
||||
"__id__": 1
|
||||
},
|
||||
"optimizationPolicy": 0,
|
||||
"persistent": false
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "atk4",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": null,
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 2
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 8
|
||||
},
|
||||
{
|
||||
"__id__": 10
|
||||
},
|
||||
{
|
||||
"__id__": 12
|
||||
},
|
||||
{
|
||||
"__id__": 14
|
||||
},
|
||||
{
|
||||
"__id__": 16
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 18
|
||||
},
|
||||
"_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": "Node",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 3
|
||||
},
|
||||
{
|
||||
"__id__": 5
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 7
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1.3,
|
||||
"y": 1.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": 95,
|
||||
"height": 96
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "93pNmvtQlLSqtTgIepyEmA"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Sprite",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 2
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 6
|
||||
},
|
||||
"_customMaterial": null,
|
||||
"_srcBlendFactor": 2,
|
||||
"_dstBlendFactor": 4,
|
||||
"_color": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 255,
|
||||
"g": 255,
|
||||
"b": 255,
|
||||
"a": 255
|
||||
},
|
||||
"_spriteFrame": {
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@3c745",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
"_type": 0,
|
||||
"_fillType": 0,
|
||||
"_sizeMode": 1,
|
||||
"_fillCenter": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_fillStart": 0,
|
||||
"_fillRange": 0,
|
||||
"_isTrimmedMode": true,
|
||||
"_useGrayscale": false,
|
||||
"_atlas": {
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20",
|
||||
"__expectedType__": "cc.SpriteAtlas"
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "12eKc8gltBz50frJCS5+ww"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "3arqAMBz1MvoXBzeDaL5M/",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.UITransform",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 9
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 120,
|
||||
"height": 120
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "63NP9yq3hEUKD/OZZZ5t7x"
|
||||
},
|
||||
{
|
||||
"__type__": "57aabs7TE1J5obTAZczc+64",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 11
|
||||
},
|
||||
"atk_x": 20,
|
||||
"atk_y": 40,
|
||||
"runType": 2,
|
||||
"endType": 0,
|
||||
"speed": 720,
|
||||
"time": 0,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "35nW0iQNBH2bqkWAr3MVkQ"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RigidBody2D",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 13
|
||||
},
|
||||
"enabledContactListener": true,
|
||||
"bullet": false,
|
||||
"awakeOnLoad": true,
|
||||
"_group": 1,
|
||||
"_type": 1,
|
||||
"_allowSleep": false,
|
||||
"_gravityScale": 1,
|
||||
"_linearDamping": 0,
|
||||
"_angularDamping": 0,
|
||||
"_linearVelocity": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_angularVelocity": 0,
|
||||
"_fixedRotation": false,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "57cr7S0YpK4oEZCavwXtIX"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.BoxCollider2D",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 15
|
||||
},
|
||||
"tag": 0,
|
||||
"_group": 1,
|
||||
"_density": 1,
|
||||
"_sensor": true,
|
||||
"_friction": 0.2,
|
||||
"_restitution": 0,
|
||||
"_offset": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_size": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 120,
|
||||
"height": 120
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "ebw5mObxNGGKxnJXDgX5gl"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Animation",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 17
|
||||
},
|
||||
"playOnLoad": true,
|
||||
"_clips": [
|
||||
{
|
||||
"__uuid__": "0ad94bf2-3b2d-4f80-8500-68c5e33e2ed1",
|
||||
"__expectedType__": "cc.AnimationClip"
|
||||
}
|
||||
],
|
||||
"_defaultClip": {
|
||||
"__uuid__": "0ad94bf2-3b2d-4f80-8500-68c5e33e2ed1",
|
||||
"__expectedType__": "cc.AnimationClip"
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "20U0hP/NZErJJXRCEib1lq"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "c46/YsCPVOJYA4mWEpNYRx",
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
13
assets/resources/game/skill/atk/atk4.prefab.meta
Normal file
13
assets/resources/game/skill/atk/atk4.prefab.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "1.1.50",
|
||||
"importer": "prefab",
|
||||
"imported": true,
|
||||
"uuid": "7f30cd3c-57d1-476a-96bb-02c4eb082576",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "atk4"
|
||||
}
|
||||
}
|
||||
375
assets/resources/game/skill/atk/atk5.prefab
Normal file
375
assets/resources/game/skill/atk/atk5.prefab
Normal file
@@ -0,0 +1,375 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.Prefab",
|
||||
"_name": "atk5",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_native": "",
|
||||
"data": {
|
||||
"__id__": 1
|
||||
},
|
||||
"optimizationPolicy": 0,
|
||||
"persistent": false
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "atk5",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": null,
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 2
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 8
|
||||
},
|
||||
{
|
||||
"__id__": 10
|
||||
},
|
||||
{
|
||||
"__id__": 12
|
||||
},
|
||||
{
|
||||
"__id__": 14
|
||||
},
|
||||
{
|
||||
"__id__": 16
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 18
|
||||
},
|
||||
"_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": "Node",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 3
|
||||
},
|
||||
{
|
||||
"__id__": 5
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 7
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1.3,
|
||||
"y": 1.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": 95,
|
||||
"height": 96
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "93pNmvtQlLSqtTgIepyEmA"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Sprite",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 2
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 6
|
||||
},
|
||||
"_customMaterial": null,
|
||||
"_srcBlendFactor": 2,
|
||||
"_dstBlendFactor": 4,
|
||||
"_color": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 255,
|
||||
"g": 255,
|
||||
"b": 255,
|
||||
"a": 255
|
||||
},
|
||||
"_spriteFrame": {
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@3c745",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
"_type": 0,
|
||||
"_fillType": 0,
|
||||
"_sizeMode": 1,
|
||||
"_fillCenter": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_fillStart": 0,
|
||||
"_fillRange": 0,
|
||||
"_isTrimmedMode": true,
|
||||
"_useGrayscale": false,
|
||||
"_atlas": {
|
||||
"__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20",
|
||||
"__expectedType__": "cc.SpriteAtlas"
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "12eKc8gltBz50frJCS5+ww"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "3arqAMBz1MvoXBzeDaL5M/",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.UITransform",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 9
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 120,
|
||||
"height": 120
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "63NP9yq3hEUKD/OZZZ5t7x"
|
||||
},
|
||||
{
|
||||
"__type__": "57aabs7TE1J5obTAZczc+64",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 11
|
||||
},
|
||||
"atk_x": 20,
|
||||
"atk_y": 40,
|
||||
"runType": 2,
|
||||
"endType": 0,
|
||||
"speed": 720,
|
||||
"time": 0,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "35nW0iQNBH2bqkWAr3MVkQ"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RigidBody2D",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 13
|
||||
},
|
||||
"enabledContactListener": true,
|
||||
"bullet": false,
|
||||
"awakeOnLoad": true,
|
||||
"_group": 1,
|
||||
"_type": 1,
|
||||
"_allowSleep": false,
|
||||
"_gravityScale": 1,
|
||||
"_linearDamping": 0,
|
||||
"_angularDamping": 0,
|
||||
"_linearVelocity": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_angularVelocity": 0,
|
||||
"_fixedRotation": false,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "57cr7S0YpK4oEZCavwXtIX"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.BoxCollider2D",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 15
|
||||
},
|
||||
"tag": 0,
|
||||
"_group": 1,
|
||||
"_density": 1,
|
||||
"_sensor": true,
|
||||
"_friction": 0.2,
|
||||
"_restitution": 0,
|
||||
"_offset": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_size": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 120,
|
||||
"height": 120
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "ebw5mObxNGGKxnJXDgX5gl"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Animation",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 17
|
||||
},
|
||||
"playOnLoad": true,
|
||||
"_clips": [
|
||||
{
|
||||
"__uuid__": "ba0a95bf-2ea1-4d27-9c4f-cbd970ca558c",
|
||||
"__expectedType__": "cc.AnimationClip"
|
||||
}
|
||||
],
|
||||
"_defaultClip": {
|
||||
"__uuid__": "ba0a95bf-2ea1-4d27-9c4f-cbd970ca558c",
|
||||
"__expectedType__": "cc.AnimationClip"
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "20U0hP/NZErJJXRCEib1lq"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "c46/YsCPVOJYA4mWEpNYRx",
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
13
assets/resources/game/skill/atk/atk5.prefab.meta
Normal file
13
assets/resources/game/skill/atk/atk5.prefab.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "1.1.50",
|
||||
"importer": "prefab",
|
||||
"imported": true,
|
||||
"uuid": "7227b42b-9cc7-41bd-8858-9d05c4cc758b",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "atk5"
|
||||
}
|
||||
}
|
||||
@@ -282,7 +282,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 25,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -368,4 +372,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -282,7 +282,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 25,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -368,4 +372,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -282,7 +282,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 25,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -368,4 +372,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -336,4 +340,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -336,4 +340,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -253,7 +253,11 @@
|
||||
},
|
||||
"atk_x": 0,
|
||||
"atk_y": 0,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -368,4 +372,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -389,7 +389,11 @@
|
||||
},
|
||||
"atk_x": 0,
|
||||
"atk_y": 0,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 0,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -504,4 +508,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -336,4 +340,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -336,4 +340,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -336,4 +340,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -250,7 +250,11 @@
|
||||
},
|
||||
"atk_x": 10,
|
||||
"atk_y": 15,
|
||||
"_id": ""
|
||||
"_id": "",
|
||||
"runType": 1,
|
||||
"endType": 2,
|
||||
"speed": 720,
|
||||
"time": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
@@ -336,4 +340,4 @@
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
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: 926 KiB After Width: | Height: | Size: 982 KiB |
@@ -232,7 +232,7 @@
|
||||
"_top": 0,
|
||||
"_bottom": 546.004,
|
||||
"_horizontalCenter": 0,
|
||||
"_verticalCenter": 143,
|
||||
"_verticalCenter": -7,
|
||||
"_isAbsLeft": true,
|
||||
"_isAbsRight": true,
|
||||
"_isAbsTop": true,
|
||||
@@ -276,7 +276,7 @@
|
||||
"value": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 783,
|
||||
"y": 633,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
|
||||
@@ -104,12 +104,12 @@ export const BuffList: Record<number, BuffConfig> = {
|
||||
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 秒",
|
||||
info: "击退距离提升 30,持续 5 秒",
|
||||
},
|
||||
// 穿透强化(限时)
|
||||
7014: {
|
||||
|
||||
@@ -13,7 +13,7 @@ export enum BoxSet {
|
||||
LETF_END = -360,
|
||||
RIGHT_END = 360,
|
||||
//游戏地平线
|
||||
GAME_LINE = 160,
|
||||
GAME_LINE = 10,
|
||||
/** 技能/装备各自独立的上限 */
|
||||
BOX_MAX = 6,
|
||||
}
|
||||
@@ -39,12 +39,12 @@ export enum FightSet {
|
||||
// BACK_RANG=30,//后退范围
|
||||
BACK_RANG = 30,//后退范围
|
||||
FiIGHT_TIME = 30,//战斗时间
|
||||
// BACK_CHANCE=40,//击退概率
|
||||
FROST_TIME = 3,//冰冻时间
|
||||
STUN_TIME = 2,//击晕时间
|
||||
SKILL_CAST_DELAY = 0.15,
|
||||
CSKILL_START_X = -340,
|
||||
CSKILL_START_Y = 30,
|
||||
/** 护盾数值上限(数值减免型:1 点护盾吸收 1 点伤害) */
|
||||
SHIELD_MAX = 5,
|
||||
WAVE_HEAL_RATE = 0.4, // 回合结束时所有英雄恢复最大生命值的比例(与 DDA 放水兜底分层:回血保节奏,放水防崩盘)
|
||||
PUNCTURE_DOWN = 50,
|
||||
|
||||
@@ -31,7 +31,7 @@ export enum Attrs {
|
||||
freeze_res = "freeze_res", // 冰冻抗性
|
||||
stun_chance = "stun_chance", // 击晕概率
|
||||
stun_res = "stun_res", // 击晕抗性
|
||||
knockback_chance = "knockback_chance", // 击退概率
|
||||
knockback_chance = "knockback_chance", // 击退强化(原击退概率,现转换为击退距离增量)
|
||||
knockback_distance = "knockback_distance", // 击退距离强化
|
||||
knockback_res = "knockback_res", // 击退抗性
|
||||
invincible_time = "invincible_time",// 无敌时间
|
||||
|
||||
@@ -38,7 +38,7 @@ const ItemCardData: ItemCardRaw[] = [
|
||||
// ==================== 计时性强化(统一 5s) ====================
|
||||
{ uuid: 9102, skill: 6503, icon: "Sub_Item-FA_WP_Sub_Potion_001_Red", name: "攻击药水", info: "全体友方攻击力提升", cost: 0, weight: 15 },
|
||||
{ uuid: 9103, skill: 6504, icon: "Sub_Item-FA_WP_Sub_Potion_001_Yellow", name: "暴击药水", info: "全体友方暴击率提升", cost: 0, weight: 15 },
|
||||
{ uuid: 9104, skill: 6505, icon: "Sub_Item-FA_WP_Sub_Potion_001_Purple", name: "击退药水", info: "全体友方击退概率提升", cost: 0, weight: 12 },
|
||||
{ uuid: 9104, skill: 6505, icon: "Sub_Item-FA_WP_Sub_Potion_001_Purple", name: "击退药水", info: "全体友方击退距离提升", cost: 0, weight: 12 },
|
||||
{ uuid: 9105, skill: 6506, icon: "Sub_Item-FA_WP_Sub_Potion_001_Blue", name: "穿透药水", info: "全体友方穿透概率提升", cost: 0, weight: 12 },
|
||||
{ uuid: 9106, skill: 6507, icon: "Sub_Item-FA_WP_Sub_Potion_001_Red", name: "攻速药水", info: "全体友方攻击速度提升", cost: 0, weight: 15 },
|
||||
{ uuid: 9107, skill: 6508, icon: "Sub_Item-FA_WP_Sub_Potion_001_Purple", name: "风怒药水", info: "全体友方风怒概率提升", cost: 0, weight: 12 },
|
||||
|
||||
@@ -221,7 +221,7 @@ export const SkillDescSet: Record<number, SkillDescConfig> = {
|
||||
templTimed: "{target}{verb}{value}{unit},持续{dur}秒",
|
||||
},
|
||||
6505: {
|
||||
verb: "击退概率提升", unit: "%", permField: "ap", timedField: "buff_value",
|
||||
verb: "击退距离提升", unit: "", permField: "ap", timedField: "buff_value",
|
||||
templPerm: "{target}{verb}{value}{unit}",
|
||||
templTimed: "{target}{verb}{value}{unit},持续{dur}秒",
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// ========== 从 HeroAttrs.ts 导入属性相关定义 ==========
|
||||
// ========== 从 HeroAttrs.ts 导入属性相关定义 ==========
|
||||
import { Attrs } from "./HeroAttrs";
|
||||
|
||||
export enum HSSet {
|
||||
@@ -152,7 +152,7 @@ export interface SkillConfig {
|
||||
crt?: number, // 额外暴击率
|
||||
frz?: number, // 额外冰冻概率
|
||||
stun?: number, // 额外击晕概率
|
||||
bck?: number, // 额外击退概率
|
||||
bck?: number, // 额外击退强化(击退距离增量)
|
||||
buff_type?: Attrs, // Buff 类型 (单一职责)
|
||||
timed_buff_id?: number, // 计时性 buff 配置 id(指向 BuffList),存在时走 buffManager 而非永久 add_*
|
||||
buff_value?: number, // 覆写计时 buff 的修饰数值(modifiers.value / tick.damage_or_heal),由药水卡自定义档位
|
||||
@@ -363,7 +363,7 @@ export const SkillSet: Record<number, SkillConfig> = {
|
||||
6406: {
|
||||
uuid: 6406, 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: 1, hit_count: 1, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
|
||||
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.knockback_chance, timed_buff_id: 7013, info: "全体友方击退概率限时提升, 持续5秒",
|
||||
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.knockback_chance, timed_buff_id: 7013, info: "全体友方击退距离限时提升, 持续5秒",
|
||||
},
|
||||
6407: {
|
||||
uuid: 6407, name: "距推强化", sp_name: "buff_wind", icon: "Stat_Stun_01", TGroup: TGroup.Team, readyAnm: "up_blue", endAnm: "", act: "atk",
|
||||
@@ -416,7 +416,7 @@ export const SkillSet: Record<number, SkillConfig> = {
|
||||
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: 3, 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秒",
|
||||
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",
|
||||
|
||||
@@ -42,6 +42,7 @@ export const MonTypeName: Record<number, string> = {
|
||||
* 英雄攻击速度分级配置 (数值为攻击间隔cd,越小越快)
|
||||
* 每档3个速度级别:Lv1(最快) → Lv2(中间) → Lv3(最慢)
|
||||
* 6档共18级,覆盖所有英雄/怪物的攻击间隔
|
||||
* 注:最慢档 Slow3/VerySlow 系列上限 1.10s,保证战斗节奏紧凑
|
||||
*/
|
||||
export enum AtkSpeedLv {
|
||||
VeryFast1 = 1, VeryFast2 = 2, VeryFast3 = 3,
|
||||
@@ -55,22 +56,22 @@ export enum AtkSpeedLv {
|
||||
export const AtkSpeedSet = {
|
||||
[AtkSpeedLv.VeryFast1]: { name: "极速++", cd: 0.15 },
|
||||
[AtkSpeedLv.VeryFast2]: { name: "极速+", cd: 0.20 },
|
||||
[AtkSpeedLv.VeryFast3]: { name: "极速", cd: 0.30 },
|
||||
[AtkSpeedLv.Fast1]: { name: "快速++", cd: 0.40 },
|
||||
[AtkSpeedLv.Fast2]: { name: "快速+", cd: 0.50 },
|
||||
[AtkSpeedLv.Fast3]: { name: "快速", cd: 0.70 },
|
||||
[AtkSpeedLv.Normal1]: { name: "中速++", cd: 0.80 },
|
||||
[AtkSpeedLv.Normal2]: { name: "中速+", cd: 0.90 },
|
||||
[AtkSpeedLv.Normal3]: { name: "中速", cd: 1.00 },
|
||||
[AtkSpeedLv.Mid1]: { name: "一般+", cd: 1.10 },
|
||||
[AtkSpeedLv.Mid2]: { name: "一般", cd: 1.20 },
|
||||
[AtkSpeedLv.Mid3]: { name: "一般-", cd: 1.30 },
|
||||
[AtkSpeedLv.Slow1]: { name: "慢", cd: 1.50 },
|
||||
[AtkSpeedLv.Slow2]: { name: "慢+", cd: 1.60 },
|
||||
[AtkSpeedLv.Slow3]: { name: "慢++", cd: 1.80 },
|
||||
[AtkSpeedLv.VerySlow1]: { name: "很慢", cd: 2.30 },
|
||||
[AtkSpeedLv.VerySlow2]: { name: "很慢+", cd: 2.50 },
|
||||
[AtkSpeedLv.VerySlow3]: { name: "很慢++", cd: 2.80 },
|
||||
[AtkSpeedLv.VeryFast3]: { name: "极速", cd: 0.28 },
|
||||
[AtkSpeedLv.Fast1]: { name: "快速++", cd: 0.36 },
|
||||
[AtkSpeedLv.Fast2]: { name: "快速+", cd: 0.44 },
|
||||
[AtkSpeedLv.Fast3]: { name: "快速", cd: 0.52 },
|
||||
[AtkSpeedLv.Normal1]: { name: "中速++", cd: 0.60 },
|
||||
[AtkSpeedLv.Normal2]: { name: "中速+", cd: 0.68 },
|
||||
[AtkSpeedLv.Normal3]: { name: "中速", cd: 0.76 },
|
||||
[AtkSpeedLv.Mid1]: { name: "一般+", cd: 0.84 },
|
||||
[AtkSpeedLv.Mid2]: { name: "一般", cd: 0.92 },
|
||||
[AtkSpeedLv.Mid3]: { name: "一般-", cd: 1.00 },
|
||||
[AtkSpeedLv.Slow1]: { name: "慢", cd: 1.05 },
|
||||
[AtkSpeedLv.Slow2]: { name: "慢+", cd: 1.08 },
|
||||
[AtkSpeedLv.Slow3]: { name: "慢++", cd: 1.10 },
|
||||
[AtkSpeedLv.VerySlow1]: { name: "很慢", cd: 1.10 },
|
||||
[AtkSpeedLv.VerySlow2]: { name: "很慢+", cd: 1.10 },
|
||||
[AtkSpeedLv.VerySlow3]: { name: "很慢++", cd: 1.10 },
|
||||
};
|
||||
|
||||
export const HeroPos = {
|
||||
@@ -85,10 +86,11 @@ export const FormationPointX = {
|
||||
[HType.Long]: 100,
|
||||
} as const;
|
||||
|
||||
/** 各攻击定位的默认攻击距离(像素):近战100 / 中程300 / 远程450;英雄配置了 dis 时优先取配置值 */
|
||||
export const HeroDisVal: Record<HType.Melee | HType.Mid | HType.Long, number> = {
|
||||
[HType.Melee]: 120,
|
||||
[HType.Mid]: 720,
|
||||
[HType.Long]: 720,
|
||||
[HType.Melee]: 100,
|
||||
[HType.Mid]: 300,
|
||||
[HType.Long]: 450,
|
||||
}
|
||||
|
||||
export const resolveFormationTargetX = (fac: FacSet, type: HType): number => {
|
||||
@@ -403,7 +405,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5001 铁壁战士 — atked 护盾(标杆,原5011)
|
||||
5001: {
|
||||
uuid: 5001, name: "铁壁战士", path: "hk1", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 300, ap: 22,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
atked: {
|
||||
6301: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, ap: 2 } },
|
||||
@@ -416,7 +418,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5002 影袭刺客 — atking 自身攻击
|
||||
5002: {
|
||||
uuid: 5002, name: "影袭刺客", path: "hc1", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, role: HRole.Assassin, hp: 300, ap: 22,
|
||||
skills: { 6003: { uuid: 6003, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast2].cd, ccd: 0 } },
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast2].cd, ccd: 0 } },
|
||||
atking: {
|
||||
6401: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, ap: 1 } },
|
||||
@@ -429,7 +431,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5003 遗志将军 — dead 全队攻击
|
||||
5003: {
|
||||
uuid: 5003, name: "遗志将军", path: "hk2", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 300, ap: 22,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
dead: {
|
||||
6401: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 3 } },
|
||||
@@ -442,7 +444,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5004 破晓先知 — fstart 全队攻击
|
||||
5004: {
|
||||
uuid: 5004, name: "破晓先知", path: "hm1", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, role: HRole.Mage, hp: 143, ap: 32,
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid3].cd, ccd: 0 } },
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid1].cd, ccd: 0 } },
|
||||
fstart: {
|
||||
6401: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 3 } },
|
||||
@@ -455,7 +457,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5005 战歌法师 — field 攻击光环
|
||||
5005: {
|
||||
uuid: 5005, name: "战歌法师", path: "hm2", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, role: HRole.Support, hp: 143, ap: 32,
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid3].cd, ccd: 0 } },
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
field: [
|
||||
{ lv: 1, uuids: [{ uuid: 7002, value: 0.1 }] },
|
||||
{ lv: 3, uuids: [{ uuid: 7002, value: 0.2 }] },
|
||||
@@ -469,7 +471,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5101 不死斗士 — atked 回血(更高数值)
|
||||
5101: {
|
||||
uuid: 5101, name: "不死斗士", path: "hk3", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 600, ap: 46,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
atked: {
|
||||
6302: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, ap: 200 } },
|
||||
@@ -482,7 +484,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5102 致命杀手 — atking 暴击(更高数值)
|
||||
5102: {
|
||||
uuid: 5102, name: "致命杀手", path: "hc2", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, role: HRole.Assassin, hp: 600, ap: 46,
|
||||
skills: { 6003: { uuid: 6003, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast2].cd, ccd: 0 } },
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast2].cd, ccd: 0 } },
|
||||
atking: {
|
||||
6403: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, timed_buff_id: 7012, buff_value: 5, buff_duration: 5 } },
|
||||
@@ -495,7 +497,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5103 殉道勇士 — dead 全队护盾(更高数值)
|
||||
5103: {
|
||||
uuid: 5103, name: "殉道勇士", path: "hk4", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 600, ap: 46,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
dead: {
|
||||
6301: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 3 } },
|
||||
@@ -508,7 +510,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5104 圣光祭司 — fstart 全队护盾(更高数值)
|
||||
5104: {
|
||||
uuid: 5104, name: "圣光祭司", path: "hm3", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, role: HRole.Mage, hp: 287, ap: 64,
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow1].cd, ccd: 0 } },
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid1].cd, ccd: 0 } },
|
||||
fstart: {
|
||||
6301: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 3 } },
|
||||
@@ -532,7 +534,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5106 破甲射手 — atking 自身穿透伤害(计时buff增强)
|
||||
5106: {
|
||||
uuid: 5106, name: "破甲射手", path: "ha1", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Long, grow_type: HGrowType.Assassin, role: HRole.Archer, hp: 287, ap: 64,
|
||||
skills: { 6008: { uuid: 6008, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
skills: { 6008: { uuid: 6008, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Normal2].cd, ccd: 0 } },
|
||||
atking: {
|
||||
6512: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, timed_buff_id: 7022, buff_value: 5, buff_duration: 5 } },
|
||||
@@ -548,7 +550,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5201 怒血勇士 — atked 全队攻击(范围扩大)
|
||||
5201: {
|
||||
uuid: 5201, name: "怒血勇士", path: "hk5", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 900, ap: 68,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
atked: {
|
||||
6401: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Team, ap: 1 } },
|
||||
@@ -574,7 +576,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5203 传承卫士 — dead 全队生命(范围扩大)
|
||||
5203: {
|
||||
uuid: 5203, name: "传承卫士", path: "hk1", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 900, ap: 68,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
dead: {
|
||||
6402: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 10 } },
|
||||
@@ -587,7 +589,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5204 晨光贤者 — fstart 全队暴击(范围扩大)
|
||||
5204: {
|
||||
uuid: 5204, name: "晨光贤者", path: "hm2", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, role: HRole.Mage, hp: 430, ap: 96,
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid3].cd, ccd: 0 } },
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid1].cd, ccd: 0 } },
|
||||
fstart: {
|
||||
6403: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, timed_buff_id: 7012, buff_value: 5, buff_duration: 5 } },
|
||||
@@ -614,7 +616,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5301 复仇守护者 — atked 全队暴击(范围+数值)
|
||||
5301: {
|
||||
uuid: 5301, name: "复仇守护者", path: "hk2", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 1200, ap: 90,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow1].cd, ccd: 0 } },
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
atked: {
|
||||
6403: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Team, timed_buff_id: 7012, buff_value: 5, buff_duration: 5 } },
|
||||
@@ -627,7 +629,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5302 破灭游侠 — atking 队友暴伤(范围+数值)
|
||||
5302: {
|
||||
uuid: 5302, name: "破灭游侠", path: "ha2", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Long, grow_type: HGrowType.Assassin, role: HRole.Archer, hp: 573, ap: 128,
|
||||
skills: { 6008: { uuid: 6008, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Normal1].cd, ccd: 0 } },
|
||||
skills: { 6008: { uuid: 6008, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Normal2].cd, ccd: 0 } },
|
||||
atking: {
|
||||
6404: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Team, hit_count: 2, timed_buff_id: 7020, buff_value: 5, buff_duration: 5 } },
|
||||
@@ -640,7 +642,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5303 亡语刺客 — dead 全队暴击+暴伤(双效果)
|
||||
5303: {
|
||||
uuid: 5303, name: "亡语刺客", path: "hc3", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Melee, grow_type: HGrowType.Assassin, role: HRole.Assassin, hp: 1200, ap: 90,
|
||||
skills: { 6003: { uuid: 6003, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast3].cd, ccd: 0 } },
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Fast2].cd, ccd: 0 } },
|
||||
dead: {
|
||||
6403: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, timed_buff_id: 7012, buff_value: 5, buff_duration: 5 } },
|
||||
@@ -690,7 +692,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5401 不灭战魂 — atked 攻击 + revive(双技能)
|
||||
5401: {
|
||||
uuid: 5401, name: "不灭战魂", path: "hk3", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Melee, grow_type: HGrowType.Tank, role: HRole.Tank, hp: 1500, ap: 114,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
atked: {
|
||||
6401: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 5, overrides: { TGroup: TGroup.Self, ap: 2 } },
|
||||
@@ -726,7 +728,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5403 凤凰祭司 — dead 攻击+护盾 + revive(双技能)
|
||||
5403: {
|
||||
uuid: 5403, name: "凤凰祭司", path: "hk4", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Melee, grow_type: HGrowType.Warrior, role: HRole.Warrior, hp: 1500, ap: 114,
|
||||
skills: { 6001: { uuid: 6001, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } },
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
|
||||
dead: {
|
||||
6401: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 5 } },
|
||||
@@ -749,7 +751,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 5404 涅槃贤者 — fstart 护盾+攻击 + revive(双技能)
|
||||
5404: {
|
||||
uuid: 5404, name: "涅槃贤者", path: "hm3", fac: FacSet.HERO, card_lv: 5, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, role: HRole.Mage, hp: 717, ap: 160,
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Normal3].cd, ccd: 0 } },
|
||||
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid1].cd, ccd: 0 } },
|
||||
fstart: {
|
||||
6301: [
|
||||
{ lv: 1, s_lv: SkillLv.Lv1, t_num: 1, overrides: { TGroup: TGroup.Team, ap: 5 } },
|
||||
@@ -789,76 +791,76 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
},
|
||||
|
||||
/*
|
||||
*=============怪物配置列表================
|
||||
* 基础近战型(lv:1) : SPEED:800 |AP:12 | HP:360 | skills[0].cd=0.65
|
||||
* 重型坦克型(lv:1) : SPEED:800 |AP:30 | HP:1050 | skills[0].cd=2
|
||||
* 远程dps(lv:1) : SPEED:800 |AP:45 | HP:240 | skills[0].cd=1.5
|
||||
* 远程辅助(lv:1) : SPEED:800 |AP:20 | HP:240 | skills[0].cd=1
|
||||
* 精英 (lv:1) : SPEED:800 |AP:20 | HP:4500 | skills[0].cd=1
|
||||
*=============怪物配置列表================
|
||||
* 性能基准:1 级怪物与 1 级英雄(card_lv=1)单体性能持平 ——
|
||||
* 近战怪镜像 5001(hp300/ap22/cd0.92),远程怪镜像 5004(hp160/ap28/cd0.84),
|
||||
* 重型/Boss 以更高 hp 换取更低 DPS,承担"墙"与"压场"定位。
|
||||
* 运行时最终属性 = 本表基础值 × RogueConfig.MON_HP_MUL / MON_AP_MUL
|
||||
* (Boss 额外 × BOSS_HP_BONUS_MUL),校准目标:整场战斗双方对砍 ≈ 30s。
|
||||
*/
|
||||
|
||||
|
||||
// 基础怪物 (全部固定点位站桩攻击,HType仅决定是前排还是后排)
|
||||
// 前排怪物 (站在前排,承受更多伤害) — v5: TD节奏CD,多而弱爽感设计
|
||||
// 前排怪物 — 近战镜像 1 级英雄基准(hp300/ap22/cd0.92),变体微分定位
|
||||
6001: {
|
||||
uuid: 6001, name: "兽人战士", path: "m1", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.Melee, hp: 286, ap: 10, speed: 70,
|
||||
skills: { 6005: { uuid: 6005, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow1].cd, ccd: 0 } }, info: "基础前排怪"
|
||||
uuid: 6001, name: "兽人战士", path: "m1", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.Melee, hp: 300, ap: 22, speed: 70,
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } }, info: "基础前排怪, 与1级近战英雄持平"
|
||||
},
|
||||
6002: {
|
||||
uuid: 6002, name: "兽人精锐战士", path: "m2", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.Melee, hp: 390, ap: 14, speed: 110,
|
||||
skills: { 6005: { uuid: 6005, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow2].cd, ccd: 0 } }, info: "进阶前排怪, 更快更痛"
|
||||
uuid: 6002, name: "兽人精锐战士", path: "m2", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.Melee, hp: 340, ap: 26, speed: 110,
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid1].cd, ccd: 0 } }, info: "进阶前排怪, 更快更痛"
|
||||
},
|
||||
6003: {
|
||||
uuid: 6003, name: "兽人重装兵", path: "m3", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.Heavy, hp: 1105, ap: 20, speed: 50,
|
||||
skills: { 6005: { uuid: 6005, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow3].cd, ccd: 0 } }, info: "重型坦克怪, 高HP慢攻"
|
||||
uuid: 6003, name: "兽人重装兵", path: "m3", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.Heavy, hp: 800, ap: 14, speed: 50,
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, info: "重型坦克怪, 高HP低攻承伤位"
|
||||
},
|
||||
// 后排怪物 (站在后排,输出更高)
|
||||
// 后排怪物 — 远程镜像 1 级法师基准(hp160/ap28/cd0.84),变体微分定位
|
||||
6004: {
|
||||
uuid: 6004, name: "兽人射手", path: "m4", fac: FacSet.MON, lv: 1, type: HType.Long, monType: MonType.Long, hp: 247, ap: 35, speed: 70,
|
||||
skills: { 6008: { uuid: 6008, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow1].cd, ccd: 0 } }, info: "后排高DPS怪"
|
||||
uuid: 6004, name: "兽人射手", path: "m4", fac: FacSet.MON, lv: 1, type: HType.Long, monType: MonType.Long, hp: 160, ap: 28, speed: 70,
|
||||
skills: { 6008: { uuid: 6008, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid1].cd, ccd: 0 } }, info: "后排输出怪, 与1级远程英雄持平"
|
||||
},
|
||||
6005: {
|
||||
uuid: 6005, name: "兽人刺客", path: "m5", fac: FacSet.MON, lv: 1, type: HType.Long, monType: MonType.Assassin, hp: 273, ap: 38, speed: 130,
|
||||
skills: { 6103: { uuid: 6103, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow2].cd, ccd: 0 } }, info: "高AP快速攻击刺客"
|
||||
uuid: 6005, name: "兽人刺客", path: "m5", fac: FacSet.MON, lv: 1, type: HType.Long, monType: MonType.Assassin, hp: 130, ap: 26, speed: 130,
|
||||
skills: { 6103: { uuid: 6103, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Normal3].cd, ccd: 0 } }, info: "高攻速低HP刺客"
|
||||
},
|
||||
// 特殊位怪物
|
||||
6006: {
|
||||
uuid: 6006, name: "骷髅领主", path: "m6", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.MeleeBoss, hp: 6500, ap: 20, speed: 60,
|
||||
skills: { 6005: { uuid: 6005, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow3].cd, ccd: 0 } }, info: "前排MiniBoss级坦克"
|
||||
uuid: 6006, name: "骷髅领主", path: "m6", fac: FacSet.MON, lv: 1, type: HType.Melee, monType: MonType.MeleeBoss, hp: 900, ap: 20, speed: 60,
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, info: "前排MiniBoss级坦克"
|
||||
},
|
||||
6007: {
|
||||
uuid: 6007, name: "兽人术士", path: "m7", fac: FacSet.MON, lv: 1, type: HType.Long, monType: MonType.Support, hp: 390, ap: 24, speed: 70,
|
||||
skills: { 6103: { uuid: 6103, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow1].cd, ccd: 0 } }, info: "后排法师怪, 魔法攻击"
|
||||
uuid: 6007, name: "兽人术士", path: "m7", fac: FacSet.MON, lv: 1, type: HType.Long, monType: MonType.Support, hp: 240, ap: 18, speed: 70,
|
||||
skills: { 6103: { uuid: 6103, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid3].cd, ccd: 0 } }, info: "后排辅助法师怪"
|
||||
},
|
||||
6008: {
|
||||
uuid: 6008, name: "兽人火法", path: "m8", fac: FacSet.MON, lv: 1, type: HType.Long, monType: MonType.Summoner, hp: 351, ap: 32, speed: 70,
|
||||
skills: { 6103: { uuid: 6103, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow2].cd, ccd: 0 } }, info: "后排高输出法师怪"
|
||||
uuid: 6008, name: "兽人火法", path: "m8", fac: FacSet.MON, lv: 1, type: HType.Long, monType: MonType.Summoner, hp: 220, ap: 24, speed: 70,
|
||||
skills: { 6103: { uuid: 6103, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } }, info: "后排召唤系法师怪"
|
||||
},
|
||||
|
||||
// BOSS怪物 — Boss节奏1.2-1.5s,删除不存在的6206技能
|
||||
// BOSS怪物 — 与6006同基准,以高HP压场,血量经 BOSS_HP_BONUS_MUL 单独放大
|
||||
6101: {
|
||||
uuid: 6101, name: "兽人首领-双刀战士", path: "mb1", fac: FacSet.MON, lv: 6, type: HType.Melee, monType: MonType.MeleeBoss, hp: 2470, ap: 30, speed: 120,
|
||||
skills: { 6103: { uuid: 6103, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow3].cd, ccd: 0 } }, info: "前排Boss, 高攻速"
|
||||
uuid: 6101, name: "兽人首领-双刀战士", path: "mb1", fac: FacSet.MON, lv: 6, type: HType.Melee, monType: MonType.MeleeBoss, hp: 1200, ap: 24, speed: 120,
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid3].cd, ccd: 0 } }, info: "前排Boss, 攻速型"
|
||||
},
|
||||
6102: {
|
||||
uuid: 6102, name: "兽人首领-斧头战士", path: "mb2", fac: FacSet.MON, lv: 6, type: HType.Melee, monType: MonType.MeleeBoss, hp: 9750, ap: 26, speed: 60,
|
||||
skills: { 6005: { uuid: 6005, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow1].cd, ccd: 0 } }, info: "前排Boss, 超高HP"
|
||||
uuid: 6102, name: "兽人首领-斧头战士", path: "mb2", fac: FacSet.MON, lv: 6, type: HType.Melee, monType: MonType.MeleeBoss, hp: 1500, ap: 18, speed: 60,
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, info: "前排Boss, 超高HP"
|
||||
},
|
||||
6103: {
|
||||
uuid: 6103, name: "兽人首领-魔法师", path: "mb3", fac: FacSet.MON, lv: 6, type: HType.Long, monType: MonType.LongBoss, hp: 2925, ap: 38, speed: 110,
|
||||
skills: { 6103: { uuid: 6103, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow2].cd, ccd: 0 } }, info: "后排法系Boss, 高AP"
|
||||
uuid: 6103, name: "兽人首领-魔法师", path: "mb3", fac: FacSet.MON, lv: 6, type: HType.Long, monType: MonType.LongBoss, hp: 1000, ap: 28, speed: 110,
|
||||
skills: { 6103: { uuid: 6103, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } }, info: "后排法系Boss"
|
||||
},
|
||||
6104: {
|
||||
uuid: 6104, name: "兽人首领-射手", path: "mb4", fac: FacSet.MON, lv: 6, type: HType.Long, monType: MonType.LongBoss, hp: 8840, ap: 30, speed: 70,
|
||||
skills: { 6005: { uuid: 6005, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow3].cd, ccd: 0 } }, info: "后排位Boss, 均衡型"
|
||||
uuid: 6104, name: "兽人首领-射手", path: "mb4", fac: FacSet.MON, lv: 6, type: HType.Long, monType: MonType.LongBoss, hp: 1100, ap: 24, speed: 70,
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid3].cd, ccd: 0 } }, info: "后排位Boss, 均衡型"
|
||||
},
|
||||
6105: {
|
||||
uuid: 6105, name: "亡灵首领-法师", path: "mb5", fac: FacSet.MON, lv: 6, type: HType.Long, monType: MonType.LongBoss, hp: 3380, ap: 42, speed: 110,
|
||||
skills: { 6103: { uuid: 6103, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow1].cd, ccd: 0 } }, info: "后排高AP Boss"
|
||||
uuid: 6105, name: "亡灵首领-法师", path: "mb5", fac: FacSet.MON, lv: 6, type: HType.Long, monType: MonType.LongBoss, hp: 1000, ap: 30, speed: 110,
|
||||
skills: { 6103: { uuid: 6103, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } }, info: "后排高AP Boss"
|
||||
},
|
||||
6106: {
|
||||
uuid: 6106, name: "亡灵首领-骑马战士", path: "mb6", fac: FacSet.MON, lv: 6, type: HType.Melee, monType: MonType.MeleeBoss, hp: 11700, ap: 26, speed: 130,
|
||||
skills: { 6005: { uuid: 6005, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.VerySlow3].cd, ccd: 0 } }, info: "前排终极Boss, 最高HP+高速"
|
||||
uuid: 6106, name: "亡灵首领-骑马战士", path: "mb6", fac: FacSet.MON, lv: 6, type: HType.Melee, monType: MonType.MeleeBoss, hp: 1800, ap: 20, speed: 130,
|
||||
skills: { 6006: { uuid: 6006, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Slow3].cd, ccd: 0 } }, info: "前排终极Boss, 最高HP+高速"
|
||||
},
|
||||
|
||||
|
||||
@@ -1160,7 +1162,9 @@ function calcSupportEffectValue(config: SkillConfig, apEff: number, cd: number,
|
||||
return (value / 100) * (apEff / cd) * 0.05 * weights.W_DPS_PER_SEC * seconds;
|
||||
case Attrs.stun_chance:
|
||||
case Attrs.freeze_chance:
|
||||
return value * weights.W_control;
|
||||
case Attrs.knockback_chance:
|
||||
// 击退强化已改为击退距离增量,按距离价值折算
|
||||
return value * weights.W_control;
|
||||
case Attrs.speed:
|
||||
return (value / 100) * (apEff / cd) * weights.W_DPS_PER_SEC * seconds;
|
||||
@@ -1182,7 +1186,8 @@ function calcSkillEffectValue(skill: SkillConfig, overrides: SkillOverrides | un
|
||||
case SkillKind.Heal:
|
||||
return ((config.ap || 0) / 100) * apEff * weights.W_heal;
|
||||
case SkillKind.Shield:
|
||||
return (config.ap || 0) * weights.expectedEnemyDmg * weights.W_shield;
|
||||
// 护盾为数值减免型:1 点护盾 ≈ 1 点预期伤害减免
|
||||
return (config.ap || 0) * weights.W_shield;
|
||||
case SkillKind.Support:
|
||||
return calcSupportEffectValue(config, apEff, cd, seconds);
|
||||
default:
|
||||
|
||||
@@ -5,7 +5,7 @@ import { smc } from "../common/SingletonModuleComp";
|
||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { HeroViewComp } from "./HeroViewComp";
|
||||
import { BoxSet, FacSet, FightSet, IndexSet } from "../common/config/GameSet";
|
||||
import { HeroInfo, HeroPos, resolveFormationTargetX, resolveTriggerByLv, resolveFieldByLv, resolveReviveByLv, calcGrowBonus } from "../common/config/heroSet";
|
||||
import { HeroInfo, resolveFormationTargetX, resolveTriggerByLv, resolveFieldByLv, resolveReviveByLv, calcGrowBonus, HeroDisVal } from "../common/config/heroSet";
|
||||
import { GameEvent } from "../common/config/GameEvent";
|
||||
import { SkillTriggerType, HType } from "../common/config/heroSet";
|
||||
import { SkillTriggerHelper } from "./SkillTriggerHelper";
|
||||
@@ -122,8 +122,8 @@ export class Hero extends ecs.Entity {
|
||||
model.grow_type = hero.grow_type;
|
||||
model.role = hero.role;
|
||||
model.fac = FacSet.HERO;
|
||||
// 攻击距离:配置优先;未配置按攻击定位给默认值(近战180 / 远程600)
|
||||
model.dis = hero.dis ?? (hero.type === HType.Melee ? 180 : 600);
|
||||
// 攻击距离:配置优先;未配置按攻击定位取默认值(近战100 / 中程300 / 远程450)
|
||||
model.dis = hero.dis ?? HeroDisVal[hero.type as HType.Melee | HType.Mid | HType.Long];
|
||||
model.posIndex = posIndex;
|
||||
if (posIndex >= 0) {
|
||||
smc.mission.heroGrid[posIndex] = this.eid;
|
||||
|
||||
@@ -146,15 +146,15 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
}
|
||||
}
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', " after crit", damage)
|
||||
// 护盾吸收
|
||||
// 护盾数值减免(1 点护盾吸收 1 点伤害,扣完为止,溢出部分继续扣血)
|
||||
const shieldResult = this.absorbShield(TAttrsComp, damage);
|
||||
damage = shieldResult.remainingDamage;
|
||||
if (shieldResult.absorbedDamage > 0) {
|
||||
// 【评分系统 - 防御分】统计护盾成功抵挡伤害的次数
|
||||
smc.vmdata.scores.shield_block_count += 1;
|
||||
// 【评分系统 - 防御分】统计护盾累计吸收的伤害量
|
||||
smc.vmdata.scores.shield_block_count += Math.floor(shieldResult.absorbedDamage);
|
||||
}
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', " after shield", damage)
|
||||
// 显示护盾格挡飘字
|
||||
// 显示护盾减免飘字
|
||||
if (shieldResult.absorbedDamage > 0 && targetView) {
|
||||
targetView.shield_tip(shieldResult.absorbedDamage);
|
||||
}
|
||||
@@ -175,11 +175,6 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
TAttrsComp.atked_count++;
|
||||
this.checkAndTriggerAtkedSkills(TAttrsComp, targetView);
|
||||
|
||||
// 受击者产生击退效果
|
||||
// if (damage > 0 && targetView) {
|
||||
// targetView.back();
|
||||
// }
|
||||
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', ` 英雄${TAttrsComp.hero_name} (uuid: ${TAttrsComp.hero_uuid}) 受到 eid:${casterEid} 的 伤害 ${damage},${isCrit ? "暴击" : "普通"}攻击,技能ID ${damageEvent.s_uuid}`);
|
||||
|
||||
// 冰冻判定
|
||||
@@ -190,13 +185,14 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
const stunChance = (damageEvent.Attrs[Attrs.stun_chance] || 0) - TAttrsComp.getFinalStunRes();
|
||||
const isStun = !TAttrsComp.isStun() && this.checkChance(stunChance);
|
||||
|
||||
// 击退判定
|
||||
const knockbackChance = (damageEvent.Attrs[Attrs.knockback_chance] || 0) - (TAttrsComp.knockback_res || 0);
|
||||
const isKnockback = this.checkChance(knockbackChance);
|
||||
// 击退:受击默认后退,击退属性不再作为概率,而是转换为后退距离的增量
|
||||
// 击退增量 = 施法者击退强化(原击退概率)- 被攻击者击退抗性 + 击退距离强化
|
||||
const knockbackBonus = (damageEvent.Attrs[Attrs.knockback_chance] || 0) - (TAttrsComp.getFinalKnockbackRes() || 0);
|
||||
const knockbackExtra = Math.max(0, knockbackBonus + (damageEvent.Attrs[Attrs.knockback_distance] || 0));
|
||||
|
||||
// ✅ 触发视图层表现(伤害数字、受击动画、冰冻、击晕、击退)
|
||||
if (targetView) {
|
||||
targetView.do_atked(damage, isCrit, damageEvent.s_uuid, false);
|
||||
targetView.do_atked(damage, isCrit, damageEvent.s_uuid, knockbackExtra);
|
||||
targetView.playEnd(skillConf.endAnm);
|
||||
if (isFrost) {
|
||||
TAttrsComp.toFrost();
|
||||
@@ -212,9 +208,6 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
smc.vmdata.scores.stun_count++;
|
||||
}
|
||||
}
|
||||
if (isKnockback) {
|
||||
targetView.back(damageEvent.Attrs[Attrs.knockback_distance] || 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -395,7 +388,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
* 用于所有概率相关的判定:
|
||||
* - 暴击率判定
|
||||
* - 闪避率判定
|
||||
* - 击退概率判定
|
||||
* - 冰冻/击晕概率判定
|
||||
* - 其他特殊效果概率
|
||||
*
|
||||
* @param rate 概率值(0-100的百分比)
|
||||
@@ -420,29 +413,26 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
|
||||
|
||||
/**
|
||||
* 护盾吸收伤害
|
||||
*
|
||||
* 护盾吸收逻辑:
|
||||
* 1. 护盾值大于 0 时,抵挡本次伤害(免伤)
|
||||
* 2. 每次抵挡消耗 1 点护盾值
|
||||
* 3. 护盾归零时,重置护盾最大值属性
|
||||
*
|
||||
* 护盾数值减免伤害
|
||||
*
|
||||
* 护盾为数值减免型:
|
||||
* 1. 1 点护盾吸收 1 点伤害
|
||||
* 2. 护盾扣减实际吸收量,溢出部分继续结算到血量
|
||||
*
|
||||
* @param TAttrsComp 被攻击者的属性组件(包含当前护盾值)
|
||||
* @param damage 原始伤害值
|
||||
* @returns {remainingDamage, absorbedDamage} 剩余伤害值和被格挡的伤害值
|
||||
* @returns {remainingDamage, absorbedDamage} 剩余伤害值和被护盾减免的伤害值
|
||||
*/
|
||||
private absorbShield(TAttrsComp: HeroAttrsComp, damage: number): { remainingDamage: number, absorbedDamage: number } {
|
||||
if (TAttrsComp.shield <= 0) {
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', " 护盾值小于等于0,无法吸收伤害");
|
||||
return { remainingDamage: damage, absorbedDamage: 0 };
|
||||
}
|
||||
TAttrsComp.shield = Math.max(0, TAttrsComp.shield - 1);
|
||||
if (TAttrsComp.shield <= 0) {
|
||||
TAttrsComp.shield = 0;
|
||||
}
|
||||
const absorbed = Math.min(TAttrsComp.shield, damage);
|
||||
TAttrsComp.shield = Math.max(0, TAttrsComp.shield - absorbed);
|
||||
TAttrsComp.dirty_shield = true;
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', ` 护盾抵挡1次伤害,剩余次数 ${TAttrsComp.shield}`);
|
||||
return { remainingDamage: 0, absorbedDamage: damage };
|
||||
mLogger.log(this.debugMode, 'HeroAtkSystem', ` 护盾减免 ${absorbed.toFixed(1)} 点伤害,剩余护盾 ${TAttrsComp.shield.toFixed(1)}`);
|
||||
return { remainingDamage: damage - absorbed, absorbedDamage: absorbed };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -82,9 +82,9 @@ export class HeroAttrsComp extends ecs.Comp {
|
||||
freeze_res: number = 0; // 冰冻抗性
|
||||
stun_chance: number = 0; // 击晕概率
|
||||
stun_res: number = 0; // 击晕抗性
|
||||
knockback_chance: number = 0; // 击退概率
|
||||
knockback_chance: number = 0; // 击退强化(原击退概率,现转换为击退距离增量)
|
||||
knockback_distance: number = 0; // 击退距离强化
|
||||
knockback_res: number = 0; // 击退抗性
|
||||
knockback_res: number = 0; // 击退抗性(削减击退距离增量)
|
||||
crit_damage: number = 0; // 额外暴击伤害
|
||||
puncture_chance: number = 0; // 穿透概率
|
||||
puncture_dmg_bonus: number = 0; // 穿透后伤害增量(百分点,乘算加成)
|
||||
@@ -153,11 +153,11 @@ export class HeroAttrsComp extends ecs.Comp {
|
||||
const addValue = Math.max(0, Math.floor(value));
|
||||
if (addValue <= 0) return;
|
||||
this.shield += addValue;
|
||||
this.shield = Math.min(this.shield, FightSet.SHIELD_MAX); // 限制护盾最大层数
|
||||
this.shield = Math.min(this.shield, FightSet.SHIELD_MAX); // 限制护盾值上限(数值减免型)
|
||||
if (this.shield < 0) this.shield = 0;
|
||||
this.dirty_shield = true; // 标记护盾需要更新
|
||||
if (this.debugMode) {
|
||||
mLogger.log(this.debugMode, 'HeroAttrs', ` 护盾次数变更: ${this.hero_name}, 变化=${addValue}, ${Math.floor(oldShield)} -> ${Math.floor(this.shield)}`);
|
||||
mLogger.log(this.debugMode, 'HeroAttrs', ` 护盾值变更: ${this.hero_name}, 变化=${addValue}, ${Math.floor(oldShield)} -> ${Math.floor(this.shield)}`);
|
||||
}
|
||||
}
|
||||
add_hp_max(value: number) {
|
||||
@@ -449,7 +449,7 @@ export class HeroAttrsComp extends ecs.Comp {
|
||||
return base + mods.flatSum + mods.pctSum;
|
||||
}
|
||||
|
||||
/** 最终击退概率 = 基础击退 + 限时修饰(加法模型) */
|
||||
/** 最终击退强化 = 基础击退强化 + 限时修饰(加法模型,转换为击退距离增量) */
|
||||
public getFinalKnockbackChance(): number {
|
||||
const mods = this.aggregateTimedMods(Attrs.knockback_chance);
|
||||
return this.knockback_chance + mods.flatSum + mods.pctSum;
|
||||
|
||||
173
assets/script/game/hero/HeroTopBarComp.ts
Normal file
173
assets/script/game/hero/HeroTopBarComp.ts
Normal file
@@ -0,0 +1,173 @@
|
||||
import { _decorator, ProgressBar, Sprite, UIOpacity, Vec3, v3, tween, Tween, Color, clamp } 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 { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { FacSet, FightSet } from "../common/config/GameSet";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/**
|
||||
* 英雄头顶状态栏组件
|
||||
*
|
||||
* 挂载在英雄节点下的 "top" 子节点上,独立管理:
|
||||
* - 血条进度(ProgressBar)
|
||||
* - 护盾数值条(ProgressBar,top/shield 节点,显示 shield / SHIELD_MAX)
|
||||
* - 透明度激活 / 闲置
|
||||
* - 受击抖动动画
|
||||
*
|
||||
* 数据流:HeroViewComp 将 HeroAttrsComp 引用传入,本组件通过 model 读取属性。
|
||||
* 注意:英雄根节点下的 "shielded" 是护盾特效动画节点,由 HeroViewComp 管理,不在本组件职责内。
|
||||
*/
|
||||
@ccclass('HeroTopBarComp')
|
||||
@ecs.register('HeroTopBar', false)
|
||||
export class HeroTopBarComp extends CCComp {
|
||||
|
||||
// ==================== @property 绑定(编辑器拖拽) ====================
|
||||
@property({ type: ProgressBar, tooltip: "血条进度条" })
|
||||
private hpProgressBar: ProgressBar = null!;
|
||||
|
||||
@property({ type: ProgressBar, tooltip: "护盾数值条(top 下的 shield 节点)" })
|
||||
private shieldProgressBar: ProgressBar = null!;
|
||||
|
||||
@property({ type: Sprite, tooltip: "血条填充 Sprite(用于设置阵营颜色)" })
|
||||
private hpBarSprite: Sprite = null!;
|
||||
|
||||
// ==================== 内部引用 ====================
|
||||
private topOpacity: UIOpacity = null!;
|
||||
private basePos: Vec3 = v3();
|
||||
|
||||
// ==================== 配置 ====================
|
||||
private hp_height: number = 90;
|
||||
private boss_hp_height: number = 160;
|
||||
|
||||
// ==================== 透明度 ====================
|
||||
private readonly barIdleOpacity: number = 153;
|
||||
private readonly barActiveOpacity: number = 255;
|
||||
private readonly idleOpacityDelay: number = 0.25;
|
||||
|
||||
/** 外部赋值:英雄数据模型 */
|
||||
private _model: HeroAttrsComp = null!;
|
||||
public get model(): HeroAttrsComp { return this._model; }
|
||||
public set model(value: HeroAttrsComp) { this._model = value; }
|
||||
|
||||
private readonly restoreBarIdleOpacity = () => {
|
||||
this.setTopBarOpacity(false);
|
||||
};
|
||||
|
||||
/**
|
||||
* 初始化 / 对象池复用时重置
|
||||
* @param model 英雄属性组件
|
||||
* @param direction 显示方向(1 或 -1)
|
||||
*/
|
||||
public init(model: HeroAttrsComp, direction: number = 1): void {
|
||||
this._model = model;
|
||||
|
||||
// UIOpacity 无 @property 绑定,运行时获取或添加
|
||||
this.topOpacity = this.node.getComponent(UIOpacity) || this.node.addComponent(UIOpacity);
|
||||
|
||||
// 方向取 abs,避免对象池复用时 scale 累乘导致血条反转
|
||||
this.node.setScale(direction * Math.abs(this.node.scale.x), 1 * this.node.scale.y);
|
||||
|
||||
// 位置
|
||||
const height = model.is_boss ? this.boss_hp_height : this.hp_height;
|
||||
this.node.setPosition(0, height, 0);
|
||||
this.basePos = this.node.position.clone();
|
||||
|
||||
// 血条颜色(英雄阵营为绿色)
|
||||
if (model.fac === FacSet.HERO && this.hpBarSprite) {
|
||||
this.hpBarSprite.color = new Color("#2ECC71");
|
||||
}
|
||||
|
||||
// 确保血条等 UI 始终在最上层
|
||||
this.node.setSiblingIndex(999);
|
||||
|
||||
// 重置显示状态
|
||||
this.node.getChildByName("hp")!.active = true;
|
||||
this.node.getChildByName("cd")!.active = false;
|
||||
this.node.getChildByName("lv")!.active = false;
|
||||
this.node.active = true;
|
||||
|
||||
this.setTopBarOpacity(false);
|
||||
this.hpShow();
|
||||
this.shieldShow(model.shield);
|
||||
}
|
||||
|
||||
/** 更新血量进度条 */
|
||||
public hpShow(): void {
|
||||
if (!this._model || !this.hpProgressBar) return;
|
||||
const hp = this._model.hp;
|
||||
const hpMax = this._model.hp_max;
|
||||
let targetProgress = hpMax > 0 ? hp / hpMax : 0;
|
||||
targetProgress = clamp(targetProgress, 0, 1);
|
||||
|
||||
const prevProgress = this.hpProgressBar.progress;
|
||||
if (targetProgress < prevProgress) {
|
||||
this.activateTopBar();
|
||||
this.playHpBarShake();
|
||||
}
|
||||
this.hpProgressBar.progress = targetProgress;
|
||||
if (targetProgress > prevProgress) {
|
||||
this.setTopBarOpacity(false);
|
||||
}
|
||||
}
|
||||
|
||||
/** 更新护盾数值条(百分比 = shield / SHIELD_MAX) */
|
||||
public shieldShow(shield: number = 0): void {
|
||||
if (!this.shieldProgressBar) return;
|
||||
const progress = FightSet.SHIELD_MAX > 0 ? shield / FightSet.SHIELD_MAX : 0;
|
||||
this.shieldProgressBar.progress = clamp(progress, 0, 1);
|
||||
// 护盾节点显隐
|
||||
this.shieldProgressBar.node.active = shield > 0;
|
||||
}
|
||||
|
||||
/** 激活顶栏(高亮 + 延迟恢复闲置透明度) */
|
||||
public activateTopBar(): void {
|
||||
this.setTopBarOpacity(true);
|
||||
this.unschedule(this.restoreBarIdleOpacity);
|
||||
this.scheduleOnce(this.restoreBarIdleOpacity, this.idleOpacityDelay);
|
||||
}
|
||||
|
||||
/** 设置顶栏透明度 */
|
||||
public setTopBarOpacity(isActive: boolean): void {
|
||||
if (!this.node || !this.node.isValid) return;
|
||||
if (this.topOpacity) {
|
||||
this.topOpacity.opacity = isActive ? this.barActiveOpacity : this.barIdleOpacity;
|
||||
}
|
||||
this.node.active = true;
|
||||
}
|
||||
|
||||
/** 显示顶栏 */
|
||||
public show(): void {
|
||||
if (this.node && this.node.isValid) this.node.active = true;
|
||||
}
|
||||
|
||||
/** 隐藏顶栏 */
|
||||
public hide(): void {
|
||||
if (this.node && this.node.isValid) this.node.active = false;
|
||||
}
|
||||
|
||||
/** 血条受击抖动动画 */
|
||||
private playHpBarShake(): void {
|
||||
if (!this.node || !this.node.isValid) return;
|
||||
Tween.stopAllByTarget(this.node);
|
||||
this.node.setPosition(this.basePos);
|
||||
tween(this.node)
|
||||
.by(0.04, { position: v3(-3, 0, 0) })
|
||||
.by(0.04, { position: v3(6, 0, 0) })
|
||||
.by(0.04, { position: v3(-5, 0, 0) })
|
||||
.by(0.04, { position: v3(2, 0, 0) })
|
||||
.call(() => {
|
||||
this.node.setPosition(this.basePos);
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
/** 对象池回收 / 组件重置时调用 */
|
||||
public reset(): void {
|
||||
this.unscheduleAllCallbacks();
|
||||
if (this.node && this.node.isValid) {
|
||||
Tween.stopAllByTarget(this.node);
|
||||
this.node.setPosition(this.basePos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "a3113d69-645e-4a4b-bf68-a434fcbd6d8d",
|
||||
"uuid": "c4181fc5-1168-4a6d-8d03-d0f2dd0b22a2",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Vec3, _decorator, v3, Collider2D, Contact2DType, Label, Node, Prefab, instantiate, ProgressBar, Component, Material, Sprite, math, clamp, Game, tween, Tween, Color, BoxCollider2D, UITransform, UIOpacity } from "cc";
|
||||
import { Vec3, _decorator, v3, Collider2D, Contact2DType, Node, Prefab, instantiate, tween, Tween, BoxCollider2D, UITransform } 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 { mLogger } from "../common/Logger";
|
||||
import { HeroSpine } from "./HeroSpine";
|
||||
import { HeroTopBarComp } from "./HeroTopBarComp";
|
||||
import { BoxSet, FacSet, FightSet, NumberFormatter, TooltipTypes } from "../common/config/GameSet";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { SkillSet, } from "../common/config/SkillSet";
|
||||
@@ -37,21 +38,10 @@ export class HeroViewComp extends CCComp {
|
||||
realDeadTime: number = 0.1
|
||||
deadCD: number = 0
|
||||
monDeadTime: number = 0.1
|
||||
hp_height: number = 90
|
||||
boss_hp_height: number = 160
|
||||
// 血条显示相关
|
||||
lastBarUpdateTime: number = 0; // 最后一次血条/蓝条/护盾更新时间
|
||||
// ==================== UI 节点引用 ====================
|
||||
private top_node: Node = null!;
|
||||
private topOpacity: UIOpacity = null!;
|
||||
private topBasePos: Vec3 = v3();
|
||||
private lvLabel: Label | null = null; // 等级显示文本
|
||||
private readonly barIdleOpacity: number = 153;
|
||||
private readonly barActiveOpacity: number = 255;
|
||||
private readonly idleOpacityDelay: number = 0.25;
|
||||
private readonly restoreBarIdleOpacity = () => {
|
||||
this.setTopBarOpacity(false);
|
||||
};
|
||||
private topBar: HeroTopBarComp = null!;
|
||||
|
||||
// ==================== 直接访问 HeroAttrsComp ====================
|
||||
get model() {
|
||||
@@ -96,67 +86,26 @@ export class HeroViewComp extends CCComp {
|
||||
this.lastBarUpdateTime = 0;
|
||||
this.status_change("idle");
|
||||
|
||||
// 初始化 UI 节点
|
||||
this.initUINodes();
|
||||
// 初始化头顶状态栏
|
||||
const topNode = this.node.getChildByName("top");
|
||||
this.topBar = topNode.getComponent(HeroTopBarComp) || topNode.addComponent(HeroTopBarComp);
|
||||
this.topBar.init(this.model, this.scale);
|
||||
|
||||
/** 方向 */
|
||||
this.node.setScale(this.scale * Math.abs(this.node.scale.x), 1 * this.node.scale.y); // 确保 scale.x 为正后再乘方向
|
||||
// top_node 取 abs 避免对象池复用时 scale 累乘导致血条方向反转
|
||||
this.top_node.setScale(this.scale * Math.abs(this.top_node.scale.x), 1 * this.top_node.scale.y);
|
||||
/* 显示角色血*/
|
||||
this.top_node.getChildByName("hp").active = true;
|
||||
this.top_node.getChildByName("cd").active = false;
|
||||
this.top_node.getChildByName("shield").active = false;
|
||||
this.top_node.getChildByName("lv").active = true;
|
||||
this.top_node.active = true;
|
||||
this.setTopBarOpacity(false);
|
||||
|
||||
// 初始化等级显示
|
||||
this.lv_show();
|
||||
|
||||
// 🔥 重置血条 UI 显示状态
|
||||
// 🔥 重置描边
|
||||
if (this.model) {
|
||||
this.hp_show();
|
||||
|
||||
// 根据英雄模型中的等级数据设置描边
|
||||
// 注意:HeroViewComp 是挂在 node 上的,而 FlashSprite 可能挂在子节点(如 Sprite/anm 节点)
|
||||
let flashSprite = this.node.getComponent(FlashSprite);
|
||||
if (!flashSprite) {
|
||||
// 如果当前节点没有,尝试在所有子节点中查找
|
||||
flashSprite = this.node.getComponentInChildren(FlashSprite);
|
||||
}
|
||||
|
||||
if (flashSprite) {
|
||||
flashSprite.setOutlineByLevel(this.model.lv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 UI 节点引用 */
|
||||
private initUINodes() {
|
||||
this.top_node = this.node.getChildByName("top");
|
||||
this.topOpacity = this.top_node.getComponent(UIOpacity) || this.top_node.addComponent(UIOpacity);
|
||||
this.top_node.setPosition(0, this.hp_height, 0);
|
||||
if (this.model.is_boss) this.top_node.setPosition(0, this.boss_hp_height, 0);
|
||||
this.topBasePos = this.top_node.position.clone();
|
||||
const hpNode = this.top_node.getChildByName("hp");
|
||||
if (this.model.fac == FacSet.HERO) {
|
||||
hpNode.getChildByName("Bar").getComponent(Sprite).color = new Color("#2ECC71")
|
||||
}
|
||||
|
||||
// 确保血条等UI始终在最上层显示
|
||||
this.top_node.setSiblingIndex(999);
|
||||
|
||||
// 缓存等级显示 Label(lv 节点下的 Label 子节点)
|
||||
const lvNode = this.top_node.getChildByName("lv");
|
||||
if (lvNode) {
|
||||
this.lvLabel = lvNode.getChildByName("Label")?.getComponent(Label) ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* View 层每帧更新
|
||||
* 注意:数据更新逻辑已移到 HeroAttrSystem,这里只负责显示
|
||||
@@ -181,103 +130,21 @@ export class HeroViewComp extends CCComp {
|
||||
|
||||
// ✅ 按需更新 UI(脏标签模式)- 只在属性变化时更新
|
||||
if (this.model.dirty_hp) {
|
||||
this.hp_show();
|
||||
this.topBar.hpShow();
|
||||
this.model.dirty_hp = false;
|
||||
}
|
||||
|
||||
|
||||
if (this.model.dirty_shield) {
|
||||
this.show_shield(this.model.shield);
|
||||
this.topBar.shieldShow(this.model.shield);
|
||||
this.model.dirty_shield = false;
|
||||
}
|
||||
|
||||
if (this.model.dirty_lv) {
|
||||
this.lv_show();
|
||||
this.model.dirty_lv = false;
|
||||
}
|
||||
}
|
||||
|
||||
public cd_show() {
|
||||
return;
|
||||
}
|
||||
|
||||
/** 显示护盾 */
|
||||
private show_shield(shield: number = 0) {
|
||||
this.lastBarUpdateTime = Date.now() / 1000;
|
||||
this.node.getChildByName("shielded").active = shield > 0;
|
||||
}
|
||||
|
||||
/** 显示血量 */
|
||||
private hp_show() {
|
||||
this.lastBarUpdateTime = Date.now() / 1000;
|
||||
// 不再基于血量是否满来决定显示状态,只更新进度条
|
||||
let hp = this.model.hp;
|
||||
let hp_max = this.model.hp_max;
|
||||
// mLogger.log(this.debugMode, 'HeroViewComp', "hp_show",hp,hp_max)
|
||||
|
||||
let targetProgress = hp_max > 0 ? hp / hp_max : 0;
|
||||
targetProgress = clamp(targetProgress, 0, 1);
|
||||
let hpNode = this.top_node.getChildByName("hp");
|
||||
let hpProgressBar = hpNode.getComponent(ProgressBar);
|
||||
|
||||
const prevProgress = hpProgressBar.progress;
|
||||
if (targetProgress < hpProgressBar.progress) {
|
||||
this.activateTopBar();
|
||||
this.playHpBarShake();
|
||||
}
|
||||
hpProgressBar.progress = targetProgress;
|
||||
if (targetProgress > prevProgress) {
|
||||
this.setTopBarOpacity(false);
|
||||
}
|
||||
}
|
||||
|
||||
private isFullHpAndNoShield(): boolean {
|
||||
if (!this.model) return false;
|
||||
if (this.model.hp_max <= 0) return false;
|
||||
return this.model.hp >= this.model.hp_max;
|
||||
}
|
||||
|
||||
/** 更新等级显示 */
|
||||
private lv_show() {
|
||||
if (!this.lvLabel || !this.model) return;
|
||||
this.lvLabel.string = String(this.model.lv);
|
||||
}
|
||||
|
||||
private setTopBarOpacity(isActive: boolean) {
|
||||
if (!this.top_node || !this.top_node.isValid) return;
|
||||
if (this.topOpacity) {
|
||||
this.topOpacity.opacity = this.barActiveOpacity;
|
||||
}
|
||||
if (isActive) {
|
||||
this.top_node.active = true;
|
||||
return;
|
||||
}
|
||||
this.top_node.active = true;
|
||||
}
|
||||
|
||||
private activateTopBar() {
|
||||
this.setTopBarOpacity(true);
|
||||
this.unschedule(this.restoreBarIdleOpacity);
|
||||
this.scheduleOnce(this.restoreBarIdleOpacity, this.idleOpacityDelay);
|
||||
}
|
||||
|
||||
private playHpBarShake() {
|
||||
if (!this.top_node || !this.top_node.isValid) return;
|
||||
Tween.stopAllByTarget(this.top_node);
|
||||
this.top_node.setPosition(this.topBasePos);
|
||||
tween(this.top_node)
|
||||
.by(0.04, { position: v3(-3, 0, 0) })
|
||||
.by(0.04, { position: v3(6, 0, 0) })
|
||||
.by(0.04, { position: v3(-5, 0, 0) })
|
||||
.by(0.04, { position: v3(2, 0, 0) })
|
||||
.call(() => {
|
||||
this.top_node.setPosition(this.topBasePos);
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** 升级特效 */
|
||||
public lv_up() {
|
||||
this.spawnTimedFx("game/skill/buff/buff_lvup", this.node, 1.0);
|
||||
@@ -349,7 +216,7 @@ export class HeroViewComp extends CCComp {
|
||||
Tooltip.load(pos, type, value, s_uuid, this.node.parent, 1, this.model?.fac ?? FacSet.MON);
|
||||
}
|
||||
|
||||
/** 护盾格挡提示 */
|
||||
/** 护盾减免提示 */
|
||||
shield_tip(absorbed: number) {
|
||||
this.hp_tip(TooltipTypes.shield, NumberFormatter.formatNumber(Math.max(0, Math.floor(absorbed))));
|
||||
}
|
||||
@@ -432,7 +299,7 @@ export class HeroViewComp extends CCComp {
|
||||
}
|
||||
add_shield(shield: number) {
|
||||
// 护盾数据更新由 Model 层处理,这里只负责视图表现
|
||||
if (this.model && this.model.shield > 0) this.show_shield(this.model.shield);
|
||||
if (this.model && this.model.shield > 0) this.topBar.shieldShow(this.model.shield);
|
||||
}
|
||||
|
||||
health(hp: number = 0) {
|
||||
@@ -458,7 +325,7 @@ export class HeroViewComp extends CCComp {
|
||||
}
|
||||
|
||||
// 恢复UI
|
||||
this.top_node.active = true;
|
||||
this.topBar.show();
|
||||
|
||||
this.status_change("idle");
|
||||
|
||||
@@ -504,7 +371,7 @@ export class HeroViewComp extends CCComp {
|
||||
}
|
||||
|
||||
// 隐藏UI
|
||||
this.top_node.active = false;
|
||||
this.topBar.hide();
|
||||
|
||||
// 在销毁实体前先禁用碰撞体,从源头减少"尸体"参与碰撞
|
||||
const collider = this.node.getComponent(Collider2D);
|
||||
@@ -525,9 +392,10 @@ export class HeroViewComp extends CCComp {
|
||||
})
|
||||
.start();
|
||||
}
|
||||
do_atked(damage: number, isCrit: boolean, s_uuid: number, isBack: boolean = false) {
|
||||
/** 受击表现(伤害数字、受击动画、击退) */
|
||||
do_atked(damage: number, isCrit: boolean, s_uuid: number, knockbackExtra: number = 0) {
|
||||
// 受到攻击时更新最后更新时间
|
||||
this.activateTopBar();
|
||||
this.topBar.activateTopBar();
|
||||
this.lastBarUpdateTime = Date.now() / 1000;
|
||||
|
||||
if (damage <= 0) return;
|
||||
@@ -542,7 +410,7 @@ export class HeroViewComp extends CCComp {
|
||||
// 视图层表现
|
||||
let SConf = SkillSet[s_uuid]
|
||||
const hitAnm = SConf?.DAnm || "atked";
|
||||
if (isBack) this.back()
|
||||
this.back(knockbackExtra)
|
||||
this.in_atked(hitAnm, this.model.fac == FacSet.HERO ? 1 : -1);
|
||||
this.showDamage(damage, isCrit);
|
||||
}
|
||||
@@ -629,7 +497,7 @@ export class HeroViewComp extends CCComp {
|
||||
if (!this.model) return;
|
||||
|
||||
const damageText = NumberFormatter.formatNumber(Math.max(0, Math.floor(damage)));
|
||||
this.hp_show();
|
||||
this.topBar.hpShow();
|
||||
if (isCrit) {
|
||||
this.hp_tip(TooltipTypes.crit, damageText);
|
||||
} else {
|
||||
@@ -640,10 +508,7 @@ export class HeroViewComp extends CCComp {
|
||||
// 清理残留的定时器和缓动
|
||||
this.unscheduleAllCallbacks();
|
||||
Tween.stopAllByTarget(this.node);
|
||||
if (this.top_node && this.top_node.isValid) {
|
||||
Tween.stopAllByTarget(this.top_node);
|
||||
this.top_node.setPosition(this.topBasePos);
|
||||
}
|
||||
this.topBar.reset();
|
||||
|
||||
// 清理碰撞器事件监听
|
||||
const collider = this.getComponent(Collider2D);
|
||||
@@ -652,7 +517,6 @@ export class HeroViewComp extends CCComp {
|
||||
}
|
||||
this.deadCD = 0
|
||||
this.lastBarUpdateTime = 0
|
||||
this.unschedule(this.restoreBarIdleOpacity);
|
||||
|
||||
// 清理伤害队列
|
||||
this.damageQueue.length = 0;
|
||||
|
||||
@@ -3,11 +3,10 @@ import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/O
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { BoxSet, FacSet, FightSet, IndexSet } from "../common/config/GameSet";
|
||||
import { HeroInfo, resolveTriggerByLv, resolveReviveByLv } from "../common/config/heroSet";
|
||||
import { HeroInfo, resolveTriggerByLv, resolveReviveByLv, HeroDisVal } from "../common/config/heroSet";
|
||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { HeroViewComp } from "./HeroViewComp";
|
||||
import { MoveComp } from "./MoveComp";
|
||||
import { MonMoveComp } from "./MonMoveComp";
|
||||
import { GameEvent } from "../common/config/GameEvent";
|
||||
import { SkillTriggerType, HType } from "../common/config/heroSet";
|
||||
import { SkillTriggerHelper } from "./SkillTriggerHelper";
|
||||
@@ -19,7 +18,7 @@ export class Monster extends ecs.Entity {
|
||||
/** 怪物表现组件引用 */
|
||||
HeroView!: HeroViewComp;
|
||||
/** 怪物移动组件引用 */
|
||||
MonMove!: MonMoveComp;
|
||||
MonMove!: MoveComp;
|
||||
/** 调试开关,控制生命周期日志输出 */
|
||||
private debugMode: boolean = false;
|
||||
|
||||
@@ -98,7 +97,7 @@ export class Monster extends ecs.Entity {
|
||||
/** 注册实体必需组件:移动 + 属性 */
|
||||
protected init() {
|
||||
this.addComponents<ecs.Comp>(
|
||||
MonMoveComp,
|
||||
MoveComp,
|
||||
HeroAttrsComp,
|
||||
);
|
||||
}
|
||||
@@ -149,8 +148,9 @@ export class Monster extends ecs.Entity {
|
||||
(node as any)._baseScale = node.scale.clone();
|
||||
}
|
||||
|
||||
// 统一挂到实体显示层 HERO 节点下
|
||||
node.parent = scene.entityLayer!.node!.getChildByName("HERO")!;
|
||||
// 按身份挂载显示层:Boss → BOSS 层(最底),小怪 → MON 层(编辑器已配置好层级顺序)
|
||||
const layerName = is_boss ? "BOSS" : "MON";
|
||||
node.parent = scene.entityLayer!.node!.getChildByName(layerName)!;
|
||||
var view = node.getComponent(HeroViewComp)!;
|
||||
const collider = node.getComponent(BoxCollider2D);
|
||||
// 入场期间关闭碰撞,防止下落时提前参与战斗
|
||||
@@ -175,8 +175,8 @@ export class Monster extends ecs.Entity {
|
||||
model.speed = hero.speed ?? 800;
|
||||
model.type = hero.type;
|
||||
model.fac = FacSet.MON;
|
||||
// 攻击距离:配置优先;未配置按攻击定位给默认值(近战180 / 远程600)
|
||||
model.dis = hero.dis ?? (hero.type === HType.Melee ? 180 : 600);
|
||||
// 攻击距离:配置优先;未配置按攻击定位取默认值(近战100 / 中程300 / 远程450)
|
||||
model.dis = hero.dis ?? HeroDisVal[hero.type as HType.Melee | HType.Mid | HType.Long];
|
||||
model.posIndex = laneIndex;
|
||||
if (laneIndex >= 0) {
|
||||
smc.mission.monGrid[laneIndex] = this.eid;
|
||||
@@ -249,7 +249,7 @@ export class Monster extends ecs.Entity {
|
||||
// 广播怪物加载事件,供刷怪与战斗系统联动
|
||||
oops.message.dispatchEvent("monster_load", this)
|
||||
// 初始化移动参数:方向、目标 X、站位基准 Y
|
||||
const move = this.get(MonMoveComp);
|
||||
const move = this.get(MoveComp);
|
||||
move.reset();
|
||||
move.direction = -1;
|
||||
move.targetX = pos.x;
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { HeroViewComp } from "./HeroViewComp";
|
||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { BoxSet, FacSet } from "../common/config/GameSet";
|
||||
import { Node } from "cc";
|
||||
|
||||
@ecs.register('MonMoveComp')
|
||||
export class MonMoveComp extends ecs.Comp {
|
||||
/** 朝向:1=向右,-1=向左 */
|
||||
direction: number = -1;
|
||||
/** 当前移动目标 X */
|
||||
targetX: number = 0;
|
||||
/** 是否允许移动(出生落地前会短暂关闭) */
|
||||
moving: boolean = true;
|
||||
/** 站位基准 Y */
|
||||
baseY: number = 0;
|
||||
/** 出生序,用于同条件渲染排序稳定 */
|
||||
spawnOrder: number = 0;
|
||||
|
||||
reset() {
|
||||
this.direction = -1;
|
||||
this.targetX = 0;
|
||||
this.moving = true;
|
||||
this.baseY = 0;
|
||||
this.spawnOrder = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ecs.register('MonMoveSystem')
|
||||
export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||
/** 怪物接近英雄后的停船距离:小于该阈值即停下交战 */
|
||||
private readonly combatHaltDistance = 80;
|
||||
/** 渲染层级重排节流,避免每帧排序 */
|
||||
private readonly renderSortInterval = 0.05;
|
||||
private lastRenderSortAt = 0;
|
||||
private monMoveMatcher: ecs.IMatcher | null = null;
|
||||
private heroViewMatcher: ecs.IMatcher | null = null;
|
||||
private readonly renderEntries: { node: Node; bossPriority: number; frontScore: number; spawnOrder: number; eid: number }[] = [];
|
||||
private renderEntryCount = 0;
|
||||
|
||||
private getMonMoveMatcher(): ecs.IMatcher {
|
||||
if (!this.monMoveMatcher) {
|
||||
this.monMoveMatcher = ecs.allOf(HeroAttrsComp, HeroViewComp, MonMoveComp);
|
||||
}
|
||||
return this.monMoveMatcher;
|
||||
}
|
||||
|
||||
private getHeroViewMatcher(): ecs.IMatcher {
|
||||
if (!this.heroViewMatcher) {
|
||||
this.heroViewMatcher = ecs.allOf(HeroAttrsComp, HeroViewComp);
|
||||
}
|
||||
return this.heroViewMatcher;
|
||||
}
|
||||
|
||||
filter(): ecs.IMatcher {
|
||||
return ecs.allOf(MonMoveComp, HeroViewComp, HeroAttrsComp);
|
||||
}
|
||||
|
||||
update(e: ecs.Entity) {
|
||||
/** 战斗未开始/暂停时不驱动移动 */
|
||||
if (!smc.mission.play || smc.mission.pause) return;
|
||||
|
||||
const model = e.get(HeroAttrsComp);
|
||||
const move = e.get(MonMoveComp);
|
||||
const view = e.get(HeroViewComp);
|
||||
if (!model || !move || !view || !view.node) return;
|
||||
if (model.fac !== FacSet.MON) return;
|
||||
if (!move.moving) return;
|
||||
|
||||
/** 关卡阶段性冻结怪物行为 */
|
||||
if (smc.mission.stop_mon_action) {
|
||||
this.clearCombatTarget(model);
|
||||
view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
|
||||
if (model.is_stop || model.is_dead || model.is_reviving || model.isFrost() || model.isStun()) {
|
||||
this.clearCombatTarget(model);
|
||||
if (!model.is_reviving) view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
|
||||
/** 所有移动都锁定在 baseY,避免出现“漂移” */
|
||||
if (view.node.position.y !== move.baseY) {
|
||||
view.node.setPosition(view.node.position.x, move.baseY, 0);
|
||||
}
|
||||
// 渲染层级统交由 MoveSystem 统一处理,避免两个 System 争抢 setSiblingIndex
|
||||
|
||||
// 仅在战斗中才处理索敌;非战斗阶段也允许向左推进,让怪物自然逼近英雄阵地
|
||||
const nearestEnemy = smc.mission.in_fight ? this.findNearestEnemy(e) : null;
|
||||
if (nearestEnemy) {
|
||||
/** 有敌人:边移动边攻击 */
|
||||
this.processCombatLogic(e, move, view, model, nearestEnemy);
|
||||
this.syncCombatTarget(model, view, nearestEnemy);
|
||||
} else {
|
||||
/** 无敌人:清目标并继续向左推进 */
|
||||
this.clearCombatTarget(model);
|
||||
model.is_atking = false;
|
||||
this.moveLeft(view, move, model);
|
||||
}
|
||||
}
|
||||
|
||||
private clearCombatTarget(model: HeroAttrsComp): void {
|
||||
model.combat_target_eid = -1;
|
||||
model.enemy_in_cast_range = false;
|
||||
}
|
||||
|
||||
private syncCombatTarget(model: HeroAttrsComp, selfView: HeroViewComp, enemyView: HeroViewComp): void {
|
||||
if (!enemyView || !enemyView.node || !enemyView.ent) {
|
||||
this.clearCombatTarget(model);
|
||||
return;
|
||||
}
|
||||
const enemyAttrs = enemyView.ent.get(HeroAttrsComp);
|
||||
if (!enemyAttrs || enemyAttrs.is_dead || enemyAttrs.is_reviving || enemyAttrs.fac === model.fac) {
|
||||
this.clearCombatTarget(model);
|
||||
return;
|
||||
}
|
||||
model.combat_target_eid = enemyView.ent.eid;
|
||||
model.enemy_in_cast_range = this.isEnemyInAttackRange(model, selfView.node.position.x, enemyView.node.position.x);
|
||||
}
|
||||
|
||||
private isEnemyInAttackRange(model: HeroAttrsComp, selfX: number, enemyX: number): boolean {
|
||||
const dist = Math.abs(selfX - enemyX);
|
||||
const attackRange = model.dis;
|
||||
return dist <= attackRange;
|
||||
}
|
||||
|
||||
private processCombatLogic(e: ecs.Entity, move: MonMoveComp, view: HeroViewComp, model: HeroAttrsComp, enemy: HeroViewComp) {
|
||||
const selfX = view.node.position.x;
|
||||
const enemyX = enemy.node.position.x;
|
||||
// 停船判定使用固定阈值(80),不依赖技能攻击范围
|
||||
const inRange = Math.abs(selfX - enemyX) <= this.combatHaltDistance;
|
||||
|
||||
if (inRange) {
|
||||
// 接触到英雄方:停止移动,进入攻击状态,由 SCastSystem 负责技能释放
|
||||
model.is_atking = true;
|
||||
const dir = enemyX > selfX ? 1 : -1;
|
||||
view.scale = dir;
|
||||
if (view.status === "move") {
|
||||
view.status_change("idle");
|
||||
}
|
||||
} else {
|
||||
// 未接触:继续向左推进
|
||||
model.is_atking = false;
|
||||
this.moveLeft(view, move, model);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 持续向左推进:怪物不再固定站位,而是以 speed/3 的速度向左移动,
|
||||
* 直到抵达左边界(基地位置)后转入待机,由 SCastSystem 继续负责技能释放。
|
||||
*/
|
||||
private moveLeft(view: HeroViewComp, move: MonMoveComp, model: HeroAttrsComp) {
|
||||
const currentX = view.node.position.x;
|
||||
if (currentX <= BoxSet.LETF_END) {
|
||||
if (view.status !== "atk") {
|
||||
view.status_change("idle");
|
||||
}
|
||||
return;
|
||||
}
|
||||
const dir = -1;
|
||||
move.direction = dir;
|
||||
const speed = model.speed / 3;
|
||||
const delta = speed * this.dt * dir;
|
||||
const newX = Math.max(BoxSet.LETF_END, currentX + delta);
|
||||
if (Math.abs(newX - currentX) >= 0.01) {
|
||||
view.node.setPosition(newX, view.node.position.y, 0);
|
||||
view.status_change("move");
|
||||
}
|
||||
}
|
||||
|
||||
private findNearestEnemy(entity: ecs.Entity): HeroViewComp | null {
|
||||
const currentView = entity.get(HeroViewComp);
|
||||
if (!currentView?.node) return null;
|
||||
|
||||
const currentPos = currentView.node.position;
|
||||
const myFac = entity.get(HeroAttrsComp).fac;
|
||||
|
||||
let nearest: HeroViewComp | null = null;
|
||||
let minDis = Infinity;
|
||||
|
||||
/** 遍历筛出最近敌人:以 X 轴距离为主,Y 轴距离作为同排的决胜权重,使角色优先攻击同路的敌人 */
|
||||
ecs.query(this.getHeroViewMatcher()).forEach(e => {
|
||||
const m = e.get(HeroAttrsComp);
|
||||
if (m.fac !== myFac && !m.is_dead) {
|
||||
const v = e.get(HeroViewComp);
|
||||
if (v?.node) {
|
||||
const dx = Math.abs(currentPos.x - v.node.position.x);
|
||||
const dy = Math.abs(currentPos.y - v.node.position.y);
|
||||
const d = dx + dy * 0.1; // Y轴权重较小,仅在 X 相近时起决定作用
|
||||
if (d < minDis) {
|
||||
minDis = d;
|
||||
nearest = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return nearest;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,31 @@
|
||||
/**
|
||||
* @file MoveComp.ts
|
||||
* @description 统一移动组件与系统(英雄 + 怪物)
|
||||
*
|
||||
* 核心规则:
|
||||
* 1. 准备阶段:双方原地待命,不推进不索敌。
|
||||
* 2. 战斗阶段:双方向最近敌人推进,进入攻击范围(model.dis)后停止移动并攻击。
|
||||
* 3. 场上无敌人:停止移动(战斗结束,由 MissionComp 进入结算)。
|
||||
* 4. 击退/位移不会把单位推出屏幕:HERO 不越过 BoxSet.LETF_END,MON 不越过 BoxSet.RIGHT_END。
|
||||
* 5. 推进方向无上限限制,直到接触敌人或抵达敌方边界。
|
||||
*/
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { HeroViewComp } from "./HeroViewComp";
|
||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { BoxSet, FacSet } from "../common/config/GameSet";
|
||||
import { HeroDisVal, HType, HRole } from "../common/config/heroSet";
|
||||
import { BoxCollider2D, Node } from "cc";
|
||||
import { MonMoveComp } from "./MonMoveComp";
|
||||
import { Node } from "cc";
|
||||
|
||||
@ecs.register('MoveComp')
|
||||
export class MoveComp extends ecs.Comp {
|
||||
/** 朝向:1=向右,-1=向左 */
|
||||
/** 朝向:1=向右(HERO),-1=向左(MON),由系统根据 fac 自动维护 */
|
||||
direction: number = 1;
|
||||
/** 当前移动目标 X(战斗/回位都会更新) */
|
||||
/** 当前移动目标 X */
|
||||
targetX: number = 0;
|
||||
/** 是否允许移动(出生落地前会短暂关闭) */
|
||||
moving: boolean = true;
|
||||
/** 预留:目标 Y(当前逻辑主要使用 baseY 锁定地平线) */
|
||||
targetY: number = 0;
|
||||
/** 角色所属车道的地平线 Y,移动时强制贴地 */
|
||||
/** 站位基准 Y,移动时强制贴地 */
|
||||
baseY: number = 0;
|
||||
/** 预留:车道索引 */
|
||||
lane: number = 0;
|
||||
/** 出生序,用于同条件渲染排序稳定 */
|
||||
spawnOrder: number = 0;
|
||||
|
||||
@@ -28,68 +33,20 @@ export class MoveComp extends ecs.Comp {
|
||||
this.direction = 1;
|
||||
this.targetX = 0;
|
||||
this.moving = true;
|
||||
this.targetY = 0;
|
||||
this.baseY = 0;
|
||||
this.lane = 0;
|
||||
this.spawnOrder = 0;
|
||||
}
|
||||
}
|
||||
|
||||
interface MoveFacConfig {
|
||||
/** 阵营可前进边界(靠近敌方一侧) */
|
||||
moveFrontX: number;
|
||||
/** 阵营可后退边界(靠近己方一侧) */
|
||||
moveBackX: number;
|
||||
/** 被逼退时前侧安全边界 */
|
||||
retreatFrontX: number;
|
||||
/** 被逼退时后侧安全边界 */
|
||||
retreatBackX: number;
|
||||
}
|
||||
|
||||
@ecs.register('MoveSystem')
|
||||
export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||
private readonly heroFrontAnchorX = -200;
|
||||
private readonly monFrontAnchorX = 0;
|
||||
/** 常规同阵营横向最小间距(英雄) */
|
||||
private readonly heroAllySpacingX = 100;
|
||||
/** 常规同阵营横向最小间距(怪物) */
|
||||
private readonly monAllySpacingX = 75;
|
||||
/** 纵向判定为同排的最大 Y 差 */
|
||||
private readonly minSpacingY = 30;
|
||||
/** 渲染层级重排节流,避免每帧排序 */
|
||||
private readonly renderSortInterval = 0.05;
|
||||
private lastRenderSortAt = 0;
|
||||
private heroMoveMatcher: ecs.IMatcher | null = null;
|
||||
private heroViewMatcher: ecs.IMatcher | null = null;
|
||||
private readonly renderEntries: { node: Node; bossPriority: number; frontScore: number; spawnOrder: number; eid: number; laneScore: number }[] = [];
|
||||
private renderEntryCount = 0;
|
||||
|
||||
/**
|
||||
* 阵营可移动边界配置。
|
||||
* HERO 在左侧出生并向右推进;MON 在右侧出生并向左推进。
|
||||
*/
|
||||
private readonly facConfigs: Record<number, MoveFacConfig> = {
|
||||
[FacSet.HERO]: {
|
||||
moveFrontX: 999999,
|
||||
moveBackX: -999999,
|
||||
retreatFrontX: 999999,
|
||||
retreatBackX: -999999,
|
||||
},
|
||||
[FacSet.MON]: {
|
||||
moveFrontX: -999999,
|
||||
moveBackX: 999999,
|
||||
retreatFrontX: -999999,
|
||||
retreatBackX: 999999,
|
||||
}
|
||||
};
|
||||
|
||||
private getHeroMoveMatcher(): ecs.IMatcher {
|
||||
if (!this.heroMoveMatcher) {
|
||||
this.heroMoveMatcher = ecs.allOf(HeroAttrsComp, HeroViewComp, MoveComp);
|
||||
}
|
||||
return this.heroMoveMatcher;
|
||||
}
|
||||
|
||||
private getHeroViewMatcher(): ecs.IMatcher {
|
||||
if (!this.heroViewMatcher) {
|
||||
this.heroViewMatcher = ecs.allOf(HeroAttrsComp, HeroViewComp);
|
||||
@@ -109,52 +66,49 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
const move = e.get(MoveComp);
|
||||
const view = e.get(HeroViewComp);
|
||||
if (!model || !move || !view || !view.node) return;
|
||||
if (model.fac !== FacSet.HERO) return; // 只处理英雄移动
|
||||
if (!move.moving) return;
|
||||
|
||||
if (model.is_stop || model.is_dead || model.is_reviving || model.isFrost()) {
|
||||
/** 关卡阶段性冻结怪物行为 */
|
||||
if (smc.mission.stop_mon_action && model.fac === FacSet.MON) {
|
||||
this.clearCombatTarget(model);
|
||||
view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
|
||||
/** 死亡/复活/控制状态:停止移动与索敌 */
|
||||
if (model.is_stop || model.is_dead || model.is_reviving || model.isFrost() || model.isStun()) {
|
||||
this.clearCombatTarget(model);
|
||||
if (!model.is_reviving) view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 获取全局排位目标
|
||||
const slot = this.getGlobalFormationSlot(e, model);
|
||||
move.baseY = slot.targetY;
|
||||
move.targetX = slot.targetX;
|
||||
|
||||
// 2. 平滑 Y 轴换路(不分阶段,立即响应编队变化)
|
||||
let isChangingLane = false;
|
||||
if (Math.abs(view.node.position.y - move.baseY) > 2) {
|
||||
const currentY = view.node.position.y;
|
||||
const deltaY = move.baseY - currentY;
|
||||
const step = 400 * this.dt; // 换路速度
|
||||
const newY = currentY + Math.sign(deltaY) * Math.min(Math.abs(deltaY), step);
|
||||
view.node.setPosition(view.node.position.x, newY, 0);
|
||||
isChangingLane = true;
|
||||
} else {
|
||||
/** 所有移动都锁定在 baseY,避免出现“漂移” */
|
||||
if (view.node.position.y !== move.baseY) {
|
||||
view.node.setPosition(view.node.position.x, move.baseY, 0);
|
||||
}
|
||||
|
||||
// 渲染层级重排
|
||||
this.updateRenderOrder();
|
||||
/** 准备阶段:双方原地待命,不推进不索敌 */
|
||||
if (!smc.mission.in_fight) {
|
||||
this.clearCombatTarget(model);
|
||||
model.is_atking = false;
|
||||
if (view.status !== "atk") view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
|
||||
/** 战斗阶段:索敌并推进 */
|
||||
const nearestEnemy = this.findNearestEnemy(e);
|
||||
if (nearestEnemy) {
|
||||
/** 有敌人:进入战斗位移逻辑(立即向编队目标移动) */
|
||||
this.processCombatLogic(e, move, view, model, nearestEnemy);
|
||||
this.syncCombatTarget(model, view, nearestEnemy);
|
||||
} else {
|
||||
/** 无敌人:清目标并回归编队站位 */
|
||||
/** 无敌人:停止移动,等待战斗结束结算 */
|
||||
this.clearCombatTarget(model);
|
||||
this.moveToSlot(view, move, model, move.targetX);
|
||||
model.is_atking = false;
|
||||
if (view.status !== "atk") view.status_change("idle");
|
||||
}
|
||||
|
||||
// 如果只在 Y 轴移动,也要播放 move 动画
|
||||
if (isChangingLane && view.status !== "move" && view.status !== "atk") {
|
||||
view.status_change("move");
|
||||
}
|
||||
/** 渲染层级重排(双阵营统一处理) */
|
||||
this.updateRenderOrder();
|
||||
}
|
||||
|
||||
private clearCombatTarget(model: HeroAttrsComp): void {
|
||||
@@ -182,300 +136,55 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
return dist <= attackRange;
|
||||
}
|
||||
|
||||
private processCombatLogic(e: ecs.Entity, move: MoveComp, view: HeroViewComp, model: HeroAttrsComp, enemy: HeroViewComp) {
|
||||
const rangeType = model.type as HType.Melee | HType.Mid | HType.Long;
|
||||
switch (rangeType) {
|
||||
case HType.Melee:
|
||||
this.processMeleeLogic(e, move, view, model, enemy);
|
||||
break;
|
||||
case HType.Mid:
|
||||
this.processMidLogic(e, move, view, model, enemy);
|
||||
break;
|
||||
case HType.Long:
|
||||
this.processLongLogic(e, move, view, model, enemy);
|
||||
break;
|
||||
default:
|
||||
this.processMidLogic(e, move, view, model, enemy); // 默认中程
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 近战交战:怪物进入警戒线(ALERT_RANGE_X)内才向右推进迎敌,
|
||||
* 贴近到固定接触距离后停下攻击;警戒线外则退回后方编队位待命。
|
||||
* Why: 近战手短需主动逼近,但无威胁时不应孤军前压暴露阵型;
|
||||
* 停止判定用固定接触距离(非攻击距离 dis),
|
||||
* 使英雄进入攻击范围后仍继续贴近,直到贴上目标才站稳输出。
|
||||
* 怪物 y 与英雄同在 GAME_LINE 附近(微调也在攻击范围内),无需管 Y 轴。
|
||||
* 战斗位移:向最近敌人推进,进入攻击范围后停止。
|
||||
* 推进无上限限制,但击退/位移受阵营后退边界保护。
|
||||
*/
|
||||
private processMeleeLogic(e: ecs.Entity, move: MoveComp, view: HeroViewComp, model: HeroAttrsComp, enemy: HeroViewComp) {
|
||||
if (!enemy?.node) {
|
||||
this.processFormationCombat(e, move, view, model);
|
||||
return;
|
||||
}
|
||||
private processCombatLogic(_e: ecs.Entity, move: MoveComp, view: HeroViewComp, model: HeroAttrsComp, enemy: HeroViewComp) {
|
||||
const selfX = view.node.position.x;
|
||||
const enemyX = enemy.node.position.x;
|
||||
const dist = Math.abs(selfX - enemyX);
|
||||
// 已贴近到固定接触距离:停下攻击
|
||||
if (dist <= MoveSystem.MELEE_ENGAGE_X) {
|
||||
const attackRange = model.dis;
|
||||
/** 近战贴身作战:攻击距离 dis(100) 大于技能范围(60),推进到与敌人相隔 60 才停下,保证技能可命中且不过度贴身 */
|
||||
const stopRange = model.type === 0 ? 80 : attackRange;
|
||||
const inRange = dist <= stopRange;
|
||||
|
||||
if (inRange) {
|
||||
/** 进入攻击范围:停止移动,进入攻击状态,由 SCastSystem 负责技能释放 */
|
||||
model.is_atking = true;
|
||||
if (view.status !== "atk") view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
// 怪物在警戒线之外:不主动迎敌,退回后方编队位待命
|
||||
if (dist > MoveSystem.MELEE_ALERT_X) {
|
||||
this.clearCombatTarget(model);
|
||||
this.moveToSlot(view, move, model, move.targetX);
|
||||
const dir = enemyX > selfX ? 1 : -1;
|
||||
view.scale = dir;
|
||||
if (view.status === "move") {
|
||||
view.status_change("idle");
|
||||
}
|
||||
} else {
|
||||
/** 未接触:向敌人方向推进 */
|
||||
model.is_atking = false;
|
||||
return;
|
||||
const dir = enemyX > selfX ? 1 : -1;
|
||||
move.direction = dir;
|
||||
const speed = model.speed / 3;
|
||||
const delta = speed * this.dt * dir;
|
||||
let newX = selfX + delta;
|
||||
|
||||
/** 后退边界钳制:防止被击退/位移推出屏幕 */
|
||||
newX = this.clampByFacBoundary(newX, model.fac);
|
||||
|
||||
if (Math.abs(newX - selfX) >= 0.01) {
|
||||
view.node.setPosition(newX, view.node.position.y, 0);
|
||||
view.status_change("move");
|
||||
}
|
||||
}
|
||||
// 警戒线内未贴近:向怪物方向推进(攻击范围内也继续移动),于接触距离处停下
|
||||
const dir = enemyX > selfX ? 1 : -1;
|
||||
move.direction = dir;
|
||||
// 终止点取接触距离与推进上限的较小者,防止越过 150 继续追击
|
||||
let stopX = Math.min(enemyX - dir * MoveSystem.MELEE_ENGAGE_X, MoveSystem.HERO_ADVANCE_LIMIT_X);
|
||||
// 同阵营最小间距约束:防止近战推进时穿越前方队友
|
||||
stopX = this.clampAllySpacing(e, view, move, model, stopX);
|
||||
const speed = model.speed / 3;
|
||||
this.moveEntity(view, dir, speed, stopX);
|
||||
model.is_atking = false;
|
||||
}
|
||||
|
||||
private processMidLogic(e: ecs.Entity, move: MoveComp, view: HeroViewComp, model: HeroAttrsComp, enemy: HeroViewComp) {
|
||||
this.processFormationCombat(e, move, view, model);
|
||||
}
|
||||
|
||||
private processLongLogic(e: ecs.Entity, move: MoveComp, view: HeroViewComp, model: HeroAttrsComp, enemy: HeroViewComp) {
|
||||
this.processFormationCombat(e, move, view, model);
|
||||
}
|
||||
|
||||
private processFormationCombat(e: ecs.Entity, move: MoveComp, view: HeroViewComp, model: HeroAttrsComp) {
|
||||
this.moveToSlot(view, move, model, move.targetX);
|
||||
model.is_atking = true;
|
||||
}
|
||||
|
||||
private getGlobalFormationSlot(self: ecs.Entity, model: HeroAttrsComp): { targetX: number, targetY: number } {
|
||||
const allAllies: ecs.Entity[] = [];
|
||||
ecs.query(this.getHeroMoveMatcher()).forEach(e => {
|
||||
const attrs = e.get(HeroAttrsComp);
|
||||
const view = e.get(HeroViewComp);
|
||||
const move = e.get(MoveComp);
|
||||
if (!attrs || !view?.node || !move) return;
|
||||
if (attrs.is_dead || attrs.is_reviving) return;
|
||||
if (attrs.fac !== model.fac) return;
|
||||
allAllies.push(e);
|
||||
});
|
||||
|
||||
allAllies.sort((a, b) => {
|
||||
const attrsA = a.get(HeroAttrsComp);
|
||||
const attrsB = b.get(HeroAttrsComp);
|
||||
const priorityA = attrsA ? this.getFormationPriority(attrsA) : 0;
|
||||
const priorityB = attrsB ? this.getFormationPriority(attrsB) : 0;
|
||||
if (priorityA !== priorityB) return priorityB - priorityA;
|
||||
|
||||
const lvA = attrsA?.lv ?? 1;
|
||||
const lvB = attrsB?.lv ?? 1;
|
||||
if (lvA !== lvB) return lvB - lvA;
|
||||
const moveA = a.get(MoveComp);
|
||||
const moveB = b.get(MoveComp);
|
||||
const orderA = moveA?.spawnOrder ?? 0;
|
||||
const orderB = moveB?.spawnOrder ?? 0;
|
||||
if (orderA !== orderB) return orderA - orderB;
|
||||
return a.eid - b.eid;
|
||||
});
|
||||
|
||||
// allAllies 按优先级降序(索引 0 = 最高优先级 = 最靠右/最先接敌),
|
||||
// 反转为"从左侧起的排位"后再分配 X:最高优先级 → 最右
|
||||
const priorityRank = Math.max(0, allAllies.findIndex(entity => entity === self));
|
||||
const rankFromLeft = allAllies.length - 1 - priorityRank;
|
||||
const targetX = this.calcSlotX(rankFromLeft, allAllies.length);
|
||||
|
||||
return { targetX, targetY: BoxSet.GAME_LINE };
|
||||
}
|
||||
|
||||
// ==================== 编队站位(方案 A:单行横向分布) ====================
|
||||
/** 编队左端起点(最靠后/最后接敌) */
|
||||
private static readonly FORMATION_LEFT_X = -320;
|
||||
/** 编队右端终点(最靠前/最先接敌) */
|
||||
private static readonly FORMATION_RIGHT_X = 100;
|
||||
/** 固定步进间距(人数较少时按此从左侧逐位右排) */
|
||||
private static readonly FORMATION_STEP_X = 60;
|
||||
/** 近战贴近怪物的固定接触距离:小于攻击距离 dis,使英雄进攻击范围后仍继续贴近到此间距才停 */
|
||||
private static readonly MELEE_ENGAGE_X = 60;
|
||||
/** 近战警戒线:怪物进入该距离内才主动向右推进迎敌,否则退回后方编队位待命 */
|
||||
private static readonly MELEE_ALERT_X = 200;
|
||||
/** 英雄向敌人推进的最远终止点 X,防止近战追敌时无限右移脱离战场 */
|
||||
private static readonly HERO_ADVANCE_LIMIT_X = 100;
|
||||
/** 同阵营英雄间最小间距:小于该值时低优先级一方需让位 */
|
||||
private static readonly ALLY_MIN_GAP_X = 30;
|
||||
|
||||
/**
|
||||
* 计算某个槽位的目标 X。
|
||||
* Why: 单行站位避免横版拥挤——人少时按 60 固定步进从 -320 起步逐位右排(保持松散),
|
||||
* 人多到 60 步进装不下时,改为在 [-320, 100] 区间均分(利用全宽)。
|
||||
* @param rankFromLeft 从左侧起的排位(0=最靠左/最后,越大越靠右/越先接敌)
|
||||
* @param total 当前存活英雄总数
|
||||
*/
|
||||
private calcSlotX(rankFromLeft: number, total: number): number {
|
||||
const left = MoveSystem.FORMATION_LEFT_X;
|
||||
const right = MoveSystem.FORMATION_RIGHT_X;
|
||||
const step = MoveSystem.FORMATION_STEP_X;
|
||||
if (total <= 1) return left;
|
||||
// 固定步进能容纳的最大人数:相邻 60,且最右不超过 right
|
||||
const maxStepCount = Math.floor((right - left) / step) + 1;
|
||||
if (total <= maxStepCount) {
|
||||
return left + rankFromLeft * step;
|
||||
}
|
||||
// 超出后均分整段区间(含左右端点)
|
||||
return left + (right - left) * (rankFromLeft / (total - 1));
|
||||
}
|
||||
|
||||
private moveToSlot(view: HeroViewComp, move: MoveComp, model: HeroAttrsComp, targetX: number) {
|
||||
const currentX = view.node.position.x;
|
||||
const currentY = view.node.position.y;
|
||||
|
||||
// 当 X 和 Y 都到达目标时,才算真正到达
|
||||
if (Math.abs(currentX - targetX) <= 2 && Math.abs(currentY - move.baseY) <= 2) {
|
||||
view.node.setPosition(targetX, move.baseY, 0);
|
||||
view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
const dir = targetX > currentX ? 1 : -1;
|
||||
move.direction = dir;
|
||||
const speed = model.speed / 3;
|
||||
// 同阵营最小间距约束:防止编队挤压时穿越前方队友
|
||||
const clampedTargetX = this.clampAllySpacing(view.ent, view, move, model, targetX);
|
||||
this.moveEntity(view, dir, speed, clampedTargetX);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同阵营横向最小间距约束。
|
||||
* Why: 编队/追击时英雄可能挤到一起,低优先级一方需要保持在高优先级身后 ALLY_MIN_GAP_X 处,
|
||||
* 避免视觉重叠与站位混乱。
|
||||
* 优先级:编队优先级高者在前;同级时召唤早(spawnOrder 小)者在前。
|
||||
* @returns 裁剪后的目标 X(保证不越过身前队友)
|
||||
* 按阵营裁剪 X 坐标,防止被击退/位移推出屏幕。
|
||||
* HERO 后退不越过 BoxSet.LETF_END;MON 后退不越过 BoxSet.RIGHT_END。
|
||||
*/
|
||||
private clampAllySpacing(self: ecs.Entity, view: HeroViewComp, selfMove: MoveComp, model: HeroAttrsComp, targetX: number): number {
|
||||
const selfX = view.node.position.x;
|
||||
const selfY = view.node.position.y;
|
||||
let clamped = targetX;
|
||||
|
||||
ecs.query(this.getHeroMoveMatcher()).forEach(e => {
|
||||
if (e === self) return;
|
||||
const attrs = e.get(HeroAttrsComp);
|
||||
const v = e.get(HeroViewComp);
|
||||
const mv = e.get(MoveComp);
|
||||
if (!attrs || !v?.node || !mv) return;
|
||||
if (attrs.is_dead || attrs.is_reviving) return;
|
||||
if (attrs.fac !== model.fac) return;
|
||||
// 只约束同排(Y 差在阈值内)的队友
|
||||
if (Math.abs(v.node.position.y - selfY) > this.minSpacingY) return;
|
||||
|
||||
const otherX = v.node.position.x;
|
||||
// 判断对方是否在自己前方(以目标方向为前)
|
||||
const isAhead = clamped > selfX ? otherX > selfX : otherX < selfX;
|
||||
if (!isAhead) return;
|
||||
|
||||
// 判定谁该在前:编队优先级高者在前;同级时 spawnOrder 小者在前
|
||||
const myPriority = this.getFormationPriority(model);
|
||||
const otherPriority = this.getFormationPriority(attrs);
|
||||
let selfIsFront = false;
|
||||
if (myPriority !== otherPriority) {
|
||||
selfIsFront = myPriority > otherPriority;
|
||||
} else {
|
||||
selfIsFront = selfMove.spawnOrder <= mv.spawnOrder;
|
||||
}
|
||||
|
||||
if (!selfIsFront) {
|
||||
// 自己靠后:不能越过 otherX - ALLY_MIN_GAP_X(朝右)或 otherX + ALLY_MIN_GAP_X(朝左)
|
||||
const limitX = clamped > selfX ? otherX - MoveSystem.ALLY_MIN_GAP_X : otherX + MoveSystem.ALLY_MIN_GAP_X;
|
||||
clamped = clamped > selfX ? Math.min(clamped, limitX) : Math.max(clamped, limitX);
|
||||
}
|
||||
});
|
||||
|
||||
return clamped;
|
||||
}
|
||||
|
||||
private moveEntity(view: HeroViewComp, direction: number, speed: number, stopAtX?: number) {
|
||||
const model = view.ent.get(HeroAttrsComp);
|
||||
const move = view.ent.get(MoveComp);
|
||||
if (!model || !move) return;
|
||||
/** 按阵营边界裁剪,防止跑出战场可移动区域 */
|
||||
const cfg = this.facConfigs[model.fac] || this.facConfigs[FacSet.HERO];
|
||||
const moveMinX = Math.min(cfg.moveBackX, cfg.moveFrontX);
|
||||
const moveMaxX = Math.max(cfg.moveBackX, cfg.moveFrontX);
|
||||
const currentX = view.node.position.x;
|
||||
const currentY = view.node.position.y;
|
||||
|
||||
const delta = speed * this.dt * direction;
|
||||
let newX = view.node.position.x + delta;
|
||||
if (currentX < moveMinX && direction < 0) {
|
||||
// X 轴到底了,如果 Y 轴还在换路,继续维持 move 状态
|
||||
if (Math.abs(currentY - move.baseY) > 2) {
|
||||
view.status_change("move");
|
||||
} else {
|
||||
view.status_change("idle");
|
||||
}
|
||||
return;
|
||||
private clampByFacBoundary(x: number, fac: number): number {
|
||||
if (fac === FacSet.HERO) {
|
||||
return Math.max(BoxSet.LETF_END, x);
|
||||
}
|
||||
if (currentX > moveMaxX && direction > 0) {
|
||||
if (Math.abs(currentY - move.baseY) > 2) {
|
||||
view.status_change("move");
|
||||
} else {
|
||||
view.status_change("idle");
|
||||
}
|
||||
return;
|
||||
}
|
||||
newX = Math.max(moveMinX, Math.min(moveMaxX, newX));
|
||||
if (stopAtX !== undefined) {
|
||||
/** 指定停止点时,限制不越过 stopAtX */
|
||||
newX = direction > 0 ? Math.min(newX, stopAtX) : Math.max(newX, stopAtX);
|
||||
}
|
||||
if (Math.abs(newX - currentX) < 0.01) {
|
||||
// X轴虽然没变化,但如果Y轴还在移动,依然是move状态
|
||||
if (Math.abs(currentY - move.baseY) > 2) {
|
||||
view.status_change("move");
|
||||
} else {
|
||||
view.status_change("idle");
|
||||
}
|
||||
return;
|
||||
}
|
||||
view.node.setPosition(newX, view.node.position.y, 0); // 注意:这里只更新 X,Y 在外部平滑逻辑更新
|
||||
view.status_change("move");
|
||||
}
|
||||
|
||||
/**
|
||||
* 编队站位优先级(数值越大越靠前/越靠右)。
|
||||
* Why: 阵容职能决定承伤顺序——死亡触发英雄需最先阵亡以触发遗志,
|
||||
* 其次坦克承伤,再次战士/刺客,远程射手/法师/辅助依次靠后保护。
|
||||
* 排序档位:死亡触发 > 坦克 > 战士 > 刺客 > 射手 > 法师 > 辅助
|
||||
*/
|
||||
private getFormationPriority(model: HeroAttrsComp): number {
|
||||
// 死亡触发英雄最高优先:需要先死以发动遗志/献祭
|
||||
if (model.dead && Object.keys(model.dead).length > 0) return 100;
|
||||
if (model.role !== undefined) {
|
||||
switch (model.role) {
|
||||
case HRole.Tank: return 90;
|
||||
case HRole.Warrior: return 80;
|
||||
case HRole.Assassin: return 70;
|
||||
case HRole.Archer: return 60;
|
||||
case HRole.Mage: return 50;
|
||||
case HRole.Support: return 40;
|
||||
}
|
||||
}
|
||||
// 兜底:未配置 role 时按攻击定位(近战 > 中程 > 远程)
|
||||
const rangeType = model.type as HType.Melee | HType.Mid | HType.Long;
|
||||
if (rangeType === HType.Melee) return 30;
|
||||
if (rangeType === HType.Mid) return 20;
|
||||
return 10;
|
||||
}
|
||||
|
||||
private resolveCombatRange(model: HeroAttrsComp, defaultMin: number, defaultMax: number): [number, number] {
|
||||
const minRange = model.getCachedMinSkillDistance();
|
||||
const maxRange = model.getCachedMaxSkillDistance();
|
||||
if (maxRange <= 0) return [defaultMin, defaultMax];
|
||||
const safeMin = Math.max(0, Math.min(minRange, maxRange - 20));
|
||||
return [safeMin, maxRange];
|
||||
return Math.min(BoxSet.RIGHT_END, x);
|
||||
}
|
||||
|
||||
private findNearestEnemy(entity: ecs.Entity): HeroViewComp | null {
|
||||
@@ -509,13 +218,19 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
|
||||
private updateRenderOrder() {
|
||||
const scene = smc.map?.MapView?.scene;
|
||||
const actorRoot = scene?.entityLayer?.node?.getChildByName("HERO");
|
||||
if (!actorRoot) return;
|
||||
const layerNode = scene?.entityLayer?.node;
|
||||
if (!layerNode) return;
|
||||
|
||||
const now = Date.now() / 1000;
|
||||
if (now - this.lastRenderSortAt < this.renderSortInterval) return;
|
||||
this.lastRenderSortAt = now;
|
||||
|
||||
const heroRoot = layerNode.getChildByName("HERO");
|
||||
const monRoot = layerNode.getChildByName("MON");
|
||||
const bossRoot = layerNode.getChildByName("BOSS");
|
||||
|
||||
/** 分层重排同层节点:各阵营层内按 Y 轴路次 -> 前后位置 -> 出生序 -> eid 排序
|
||||
* (Boss 已有独立 BOSS 层固定在最底,无需 bossPriority 参与排序) */
|
||||
this.renderEntryCount = 0;
|
||||
ecs.query(this.getHeroViewMatcher()).forEach(e => {
|
||||
const attrs = e.get(HeroAttrsComp);
|
||||
@@ -523,24 +238,23 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
if (!attrs || !actorView?.node || attrs.is_dead) return;
|
||||
if (attrs.fac !== FacSet.HERO && attrs.fac !== FacSet.MON) return;
|
||||
|
||||
if (actorView.node.parent !== actorRoot) {
|
||||
actorView.node.parent = actorRoot;
|
||||
/** 按阵营/身份归位到对应显示层 */
|
||||
let targetRoot: Node | null | undefined;
|
||||
if (attrs.fac === FacSet.HERO) {
|
||||
targetRoot = heroRoot;
|
||||
} else {
|
||||
targetRoot = attrs.is_boss ? (bossRoot ?? monRoot ?? heroRoot) : (monRoot ?? heroRoot);
|
||||
}
|
||||
if (!targetRoot) return;
|
||||
if (actorView.node.parent !== targetRoot) {
|
||||
actorView.node.parent = targetRoot;
|
||||
}
|
||||
|
||||
// 获取 spawnOrder,由于可能挂载 MoveComp 或 MonMoveComp,我们需要动态获取
|
||||
let spawnOrder = 0;
|
||||
const heroMove = e.get(MoveComp);
|
||||
if (heroMove) {
|
||||
spawnOrder = heroMove.spawnOrder;
|
||||
} else {
|
||||
const monMove = e.get(MonMoveComp);
|
||||
if (monMove) {
|
||||
spawnOrder = monMove.spawnOrder;
|
||||
}
|
||||
}
|
||||
/** 统一从 MoveComp 获取 spawnOrder */
|
||||
const move = e.get(MoveComp);
|
||||
const spawnOrder = move?.spawnOrder ?? 0;
|
||||
|
||||
// 按 Y 轴计算渲染层级权重(Y 越小,说明越靠近屏幕下方,应该渲染在越前面)
|
||||
// 之前的 isFly 逻辑已被移除,统一按 Y 轴处理三路渲染
|
||||
const laneScore = -actorView.node.position.y;
|
||||
// X 轴权重:站在前排的(交战处)优先渲染
|
||||
const frontScore = attrs.fac === FacSet.HERO ? actorView.node.position.x : -actorView.node.position.x;
|
||||
@@ -552,7 +266,6 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
this.renderEntries.push(entry);
|
||||
}
|
||||
entry.node = actorView.node;
|
||||
entry.bossPriority = attrs.is_boss ? 1 : 0;
|
||||
entry.laneScore = laneScore;
|
||||
entry.frontScore = frontScore;
|
||||
entry.spawnOrder = spawnOrder;
|
||||
@@ -561,9 +274,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
});
|
||||
this.renderEntries.length = this.renderEntryCount;
|
||||
|
||||
/** 定时重排同层节点:Boss 优先级 -> Y 轴路次 -> 前后位置 -> 出生序 -> eid */
|
||||
this.renderEntries.sort((a, b) => {
|
||||
if (a.bossPriority !== b.bossPriority) return a.bossPriority - b.bossPriority;
|
||||
// Y轴靠下的(laneScore 较大)应该在后面,从而渲染在上面
|
||||
if (Math.abs(a.laneScore - b.laneScore) > 10) return a.laneScore - b.laneScore;
|
||||
if (a.frontScore !== b.frontScore) return a.frontScore - b.frontScore;
|
||||
@@ -571,8 +282,14 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
return a.eid - b.eid;
|
||||
});
|
||||
|
||||
this.renderEntries.forEach((item, index) => {
|
||||
/** 分层应用 siblingIndex:各层内部从 0 递增 */
|
||||
const layerCounters = new Map<Node, number>();
|
||||
this.renderEntries.forEach((item) => {
|
||||
const parent = item.node.parent;
|
||||
if (!parent) return;
|
||||
const index = layerCounters.get(parent) ?? 0;
|
||||
item.node.setSiblingIndex(index);
|
||||
layerCounters.set(parent, index + 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,10 +61,10 @@ export class HeroMoreCom extends Component {
|
||||
/** 冰冻率附加值 */
|
||||
@property(Label)
|
||||
private freeze_plus_label: Label = null;
|
||||
/** 击退率总值(百分点) */
|
||||
/** 击退强化总值(击退距离增量) */
|
||||
@property(Label)
|
||||
private knockback_all_label: Label = null;
|
||||
/** 击退率附加值 */
|
||||
/** 击退强化附加值 */
|
||||
@property(Label)
|
||||
private knockback_plus_label: Label = null;
|
||||
/** 穿透率总值(百分点) */
|
||||
@@ -177,12 +177,13 @@ export class HeroMoreCom extends Component {
|
||||
const finalCritDmg = this.model.getFinalCritDamage();
|
||||
this.setStatRow(this.crit_dmg_all_label, this.crit_dmg_plus_label, finalCritDmg, finalCritDmg - (this.model.crit_damage ?? 0), "%");
|
||||
|
||||
// ---- 冰冻率 / 击退率 / 穿透率 / 风怒率(百分点) ----
|
||||
// ---- 冰冻率 / 击退强化 / 穿透率 / 风怒率 ----
|
||||
const finalFreeze = this.model.getFinalFreezeChance();
|
||||
this.setStatRow(this.freeze_all_label, this.freeze_plus_label, finalFreeze, finalFreeze - (this.model.freeze_chance ?? 0), "%");
|
||||
|
||||
// 击退强化已改为击退距离增量,不再按百分比显示
|
||||
const finalKnockback = this.model.getFinalKnockbackChance();
|
||||
this.setStatRow(this.knockback_all_label, this.knockback_plus_label, finalKnockback, finalKnockback - (this.model.knockback_chance ?? 0), "%");
|
||||
this.setStatRow(this.knockback_all_label, this.knockback_plus_label, finalKnockback, finalKnockback - (this.model.knockback_chance ?? 0), "");
|
||||
|
||||
const finalPuncture = this.model.getFinalPunctureChance();
|
||||
this.setStatRow(this.puncture_all_label, this.puncture_plus_label, finalPuncture, finalPuncture - (this.model.puncture_chance ?? 0), "%");
|
||||
|
||||
@@ -805,7 +805,6 @@ export class MissionComp extends CCComp {
|
||||
this.clearTime = 0
|
||||
smc.vmdata.mission_data.mon_num = 0
|
||||
smc.vmdata.mission_data.level = 1
|
||||
smc.vmdata.mission_data.mon_max = Math.max(1, Math.floor(this.maxMonsterCount))
|
||||
this.currentPhase = MissionPhase.None;
|
||||
this.currentWave = 1;
|
||||
this.isBossWave = false;
|
||||
@@ -1006,21 +1005,17 @@ export class MissionComp extends CCComp {
|
||||
this.clearBattleSceneNodes();
|
||||
}
|
||||
|
||||
/** 清理战斗场景中的 HERO 和 SKILL 根节点下的所有子节点 */
|
||||
/** 清理战斗场景中的 HERO/MON/BOSS 和 SKILL 根节点下的所有子节点 */
|
||||
private clearBattleSceneNodes() {
|
||||
const scene = smc.map?.MapView?.scene;
|
||||
const layer = scene?.entityLayer?.node;
|
||||
if (!layer) return;
|
||||
const heroRoot = layer.getChildByName("HERO");
|
||||
const skillRoot = layer.getChildByName("SKILL");
|
||||
if (heroRoot) {
|
||||
for (let i = heroRoot.children.length - 1; i >= 0; i--) {
|
||||
heroRoot.children[i].destroy();
|
||||
}
|
||||
}
|
||||
if (skillRoot) {
|
||||
for (let i = skillRoot.children.length - 1; i >= 0; i--) {
|
||||
skillRoot.children[i].destroy();
|
||||
for (const name of ["HERO", "MON", "BOSS", "SKILL"]) {
|
||||
const root = layer.getChildByName(name);
|
||||
if (root) {
|
||||
for (let i = root.children.length - 1; i >= 0; i--) {
|
||||
root.children[i].destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,18 +53,16 @@ const { ccclass } = _decorator;
|
||||
export class MissionHeroComp extends CCComp {
|
||||
// ======================== 常量 ========================
|
||||
|
||||
/** 硬编码的英雄占位点(数量对齐 FightSet.HERO_MAX_NUM,落点 X 统一,英雄落地后由 MoveComp 自行移位到阵型目标) */
|
||||
/**
|
||||
* 英雄登场占位点(固定 3 列):
|
||||
* - index 0/1/2 分别对应 x=-320/-260/-200。
|
||||
* - 分配规则:近战优先靠前(x 更大),远程/中程优先靠后(x 更小);
|
||||
* 同类型按召唤先后从该类型的一侧开始依次填充。
|
||||
*/
|
||||
public static readonly HERO_POSITIONS: Vec3[] = [
|
||||
v3(-300, BoxSet.GAME_LINE, 0), // index 0
|
||||
v3(-300, BoxSet.GAME_LINE, 0), // index 1
|
||||
v3(-300, BoxSet.GAME_LINE, 0), // index 2
|
||||
v3(-300, BoxSet.GAME_LINE, 0), // index 3
|
||||
v3(-300, BoxSet.GAME_LINE, 0), // index 4
|
||||
v3(-300, BoxSet.GAME_LINE, 0), // index 5
|
||||
v3(-300, BoxSet.GAME_LINE, 0), // index 6
|
||||
v3(-300, BoxSet.GAME_LINE, 0), // index 7
|
||||
v3(-300, BoxSet.GAME_LINE, 0), // index 8
|
||||
v3(-300, BoxSet.GAME_LINE, 0), // index 9
|
||||
v3(-320, BoxSet.GAME_LINE, 0),
|
||||
v3(-260, BoxSet.GAME_LINE, 0),
|
||||
v3(-200, BoxSet.GAME_LINE, 0),
|
||||
];
|
||||
|
||||
/** 英雄出生时的掉落高度(从空中落到地面的像素差) */
|
||||
@@ -203,7 +201,7 @@ export class MissionHeroComp extends CCComp {
|
||||
* 动态分配英雄上场的位置
|
||||
* @param excludeEids 排除计算的实体ID数组(避免复活时把自己算成占据的位置)
|
||||
*/
|
||||
private pickPositionIndexForHero(excludeEids: number[] = []): number {
|
||||
private pickPositionIndexForHero(excludeEids: number[] = [], heroType: HType = HType.Melee): number {
|
||||
const heroes = this.getAllHeroes().filter(h => {
|
||||
const m = h.get(HeroAttrsComp);
|
||||
return m && !m.is_dead && !excludeEids.includes(h.eid);
|
||||
@@ -215,8 +213,10 @@ export class MissionHeroComp extends CCComp {
|
||||
if (m && m.posIndex >= 0) occupied.add(m.posIndex);
|
||||
}
|
||||
|
||||
// 按索引顺序填充空位(0..9),全部落点相同,英雄落地后自行移位
|
||||
const slotPriority = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
// 近战优先靠前(x 更大,索引更大);远程/中程优先靠后(x 更小,索引更小)
|
||||
const slotPriority = heroType === HType.Melee
|
||||
? [2, 1, 0]
|
||||
: [0, 1, 2];
|
||||
for (const idx of slotPriority) {
|
||||
if (!occupied.has(idx) && MissionHeroComp.HERO_POSITIONS[idx]) {
|
||||
return idx;
|
||||
@@ -255,7 +255,7 @@ export class MissionHeroComp extends CCComp {
|
||||
private spawnHeroAt(uuid: number, hero_lv: number, card_lv: number, posIndex: number) {
|
||||
let hero = ecs.getEntity<Hero>(Hero);
|
||||
let scale = 1
|
||||
const finalPosIndex = posIndex >= 0 ? posIndex : this.pickPositionIndexForHero();
|
||||
const finalPosIndex = posIndex >= 0 ? posIndex : this.pickPositionIndexForHero([], HeroInfo[uuid]?.type ?? HType.Melee);
|
||||
// 兜底:索引越界或点位缺失时复用 index 0,保证 landingPos 一定有效
|
||||
const landingPos = MissionHeroComp.HERO_POSITIONS[finalPosIndex] ?? MissionHeroComp.HERO_POSITIONS[0];
|
||||
let spawnPos: Vec3 = v3(landingPos.x, landingPos.y + MissionHeroComp.HERO_DROP_HEIGHT, 0);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* 关键设计:
|
||||
* - 5 只怪在 X∈[100,320] 内按登场序号均匀铺开,Boss/小怪同时登场,玩家看清阵容后三选一。
|
||||
* - 实际阵型与推进由 MonMoveComp 在战斗中向左移动自然形成,不再使用固定网格点。
|
||||
* - 实际推进由统一 MoveComp 在战斗中向敌人移动自然形成,不再使用固定网格点。
|
||||
* - 槽位索引仅用于 monGrid 寻路与 SCastSystem 索敌定位。
|
||||
*/
|
||||
import { _decorator, v3, Vec3 } from "cc";
|
||||
@@ -22,7 +22,7 @@ import { GameEvent } from "../common/config/GameEvent";
|
||||
import { BoxSet } from "../common/config/GameSet";
|
||||
import { spawningEngine, GeneratedMonster, TestModeConfig, BOSS_COUNT, MINION_COUNT } from "./RogueConfig";
|
||||
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
||||
import { MonMoveComp } from "../hero/MonMoveComp";
|
||||
import { MoveComp } from "../hero/MoveComp";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@@ -142,7 +142,7 @@ export class MissionMonCompComp extends CCComp {
|
||||
const spawnX = MissionMonCompComp.SPAWN_X_MIN
|
||||
+ (MissionMonCompComp.SPAWN_X_MAX - MissionMonCompComp.SPAWN_X_MIN)
|
||||
* (posIndex / Math.max(1, BOSS_COUNT + MINION_COUNT - 1));
|
||||
const landingY = basePos.y + (monData.isBoss ? 6 : 0);
|
||||
const landingY = basePos.y;
|
||||
const spawnPos: Vec3 = v3(spawnX, landingY + MissionMonCompComp.MON_DROP_HEIGHT, 0);
|
||||
this.globalSpawnOrder = (this.globalSpawnOrder + 1) % 999;
|
||||
|
||||
@@ -158,7 +158,7 @@ export class MissionMonCompComp extends CCComp {
|
||||
oops.message.dispatchEvent(GameEvent.BossSpawn, { pos: spawnPos.clone() });
|
||||
}
|
||||
|
||||
const move = mon.get(MonMoveComp);
|
||||
const move = mon.get(MoveComp);
|
||||
if (move) {
|
||||
move.spawnOrder = this.globalSpawnOrder;
|
||||
}
|
||||
|
||||
@@ -11,23 +11,19 @@
|
||||
* 设计层次:
|
||||
* 1. BossComboLibrary - Boss 组合库(小怪构成 + Boss/小怪技能池 + 抽取权重)
|
||||
* 2. MonSkillPool/BossSkillPool - 怪物技能池(atking / atked / dead 等全触发类型)
|
||||
* 3. RogueSpawningEngine - 生成引擎(按英雄强度反推怪物强度)
|
||||
* 3. RogueSpawningEngine - 生成引擎(基础属性 × 可调系数)
|
||||
*
|
||||
* 核心公式:
|
||||
* heroPower = Σ calcHeroPower(HeroInfo[uuid], lv) (场上存活英雄)
|
||||
* targetPower = heroPower × BOSS_TYPE_RATIO × FINAL_HP_MUL × MON_POWER_MUL
|
||||
* hpScale = targetPower ÷ Σ 怪物基础强度
|
||||
* 怪物 hp = base_hp × hpScale (走总强度框架,自动匹配玩家)
|
||||
*
|
||||
* 怪物 ap 独立挂钩玩家输出(不走总强度,避免被 hp 挤占):
|
||||
* 怪物 ap = 玩家平均攻击 × AP_GROWTH_FINAL × AP_RELATIVE × 类型系数
|
||||
* 核心公式(基础属性 × 可调系数):
|
||||
* 怪物 hp = HeroInfo 基础hp × MON_HP_MUL(Boss 额外 × BOSS_HP_BONUS_MUL)
|
||||
* 怪物 ap = HeroInfo 基础ap × MON_AP_MUL
|
||||
* 怪物基础面板与 1 级英雄持平(近战镜像 hp300/ap22/cd1.8),默认系数校准为
|
||||
* 整场战斗(3 英雄 vs 4 小怪 + 1 Boss)双方对砍 ≈ WAVE_DURATION(30s)。
|
||||
* 手感微调只改 MON_HP_MUL / MON_AP_MUL / BOSS_HP_BONUS_MUL 三个系数即可。
|
||||
*/
|
||||
|
||||
import { HeroInfo, MonType, MonTypeName, calcHeroPower, TriggerGrouped, LvReviveEntry } from "../common/config/heroSet";
|
||||
import { HeroInfo, MonType, MonTypeName, TriggerGrouped, LvReviveEntry } from "../common/config/heroSet";
|
||||
import { SkillOverrides } from "../common/config/SkillSet";
|
||||
import { FacSet } from "../common/config/GameSet";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
||||
|
||||
// ======================== 1. 战斗常量 ========================
|
||||
|
||||
@@ -38,17 +34,13 @@ export const WAVE_DURATION = 30;
|
||||
export const BOSS_COUNT = 1;
|
||||
export const MINION_COUNT = 4;
|
||||
|
||||
/** Boss 战强度系数(原压力回合系数) */
|
||||
export const BOSS_TYPE_RATIO = 1.2;
|
||||
/** 最终 Boss 战 HP 乘区(原 wave 20 配置) */
|
||||
export const FINAL_HP_MUL = 1.8;
|
||||
/** 全局怪物强度系数(2/3 = 强度削弱三分之一,同时作用于 hp 缩放与 ap 挂钩公式) */
|
||||
export const MON_POWER_MUL = 2 / 3;
|
||||
/** 怪物 ap 最终递进系数(原 wave 20 满档 3.0) */
|
||||
export const AP_GROWTH_FINAL = 3.0;
|
||||
/** 怪物 ap 相对玩家平均攻击的基础系数(<1 保证单怪不至于一击致命,由 Boss/精英类型再上浮) */
|
||||
export const AP_RELATIVE = 0.6;
|
||||
/** Boss 血量加成(原 wave 20 bossBonusHpMul = 1.6) */
|
||||
/** 怪物血量可调系数:最终 hp = HeroInfo 基础hp × MON_HP_MUL。
|
||||
* 2.6 = 校准后怪物总血量 / 3 英雄 30s 输出(≈30 DPS),双方对砍 ≈ 30s 分胜负 */
|
||||
export const MON_HP_MUL = 2.6;
|
||||
/** 怪物攻击可调系数:最终 ap = HeroInfo 基础ap × MON_AP_MUL。
|
||||
* 0.9 使 4 小怪+1 Boss 的总 DPS ≈ 20,30s 恰好磨光 3 英雄总血量(≈600) */
|
||||
export const MON_AP_MUL = 0.9;
|
||||
/** Boss 血量额外加成(在 MON_HP_MUL 之上乘算,突出压场定位) */
|
||||
export const BOSS_HP_BONUS_MUL = 1.6;
|
||||
/** 战斗超时(秒):超过后强制结算整局(残留怪销毁并扣留存分) */
|
||||
export const BATTLE_TIMEOUT = 90;
|
||||
@@ -371,12 +363,12 @@ export const TestModeConfig = {
|
||||
|
||||
/**
|
||||
* Boss 组合生成引擎
|
||||
* 随机抽一组 Boss 组合,按英雄强度反推怪物强度(最终 Boss 战档位)
|
||||
* 随机抽一组 Boss 组合,怪物最终属性 = HeroInfo 基础属性 × 可调系数
|
||||
*/
|
||||
export class RogueSpawningEngine {
|
||||
|
||||
/**
|
||||
* 生成一场战斗的怪物列表:随机一组 Boss 组合(1 Boss + 组合小怪)。
|
||||
* 生成一场战斗的怪物列表:随机一组 Boss 组合(1 Boss + 4 小怪,属性走基础×系数)。
|
||||
* Boss 压队尾(登场时由 MissionMonComp 统一布位)。
|
||||
* @returns 怪物列表(小怪在前、Boss 在尾)
|
||||
*/
|
||||
@@ -406,21 +398,10 @@ export class RogueSpawningEngine {
|
||||
monsters.push(this.makeBoss());
|
||||
}
|
||||
|
||||
// 属性缩放:直接取最终 Boss 战档位系数
|
||||
const heroPower = this.getCurrentHeroPower();
|
||||
const targetPower = heroPower * BOSS_TYPE_RATIO * MON_POWER_MUL;
|
||||
const totalBasePower = monsters.reduce((sum, m) => {
|
||||
const info = HeroInfo[m.uuid];
|
||||
return sum + (info ? calcHeroPower(info, 1) : m.hp + m.ap);
|
||||
}, 0);
|
||||
if (totalBasePower > 0 && targetPower > 0) {
|
||||
const hpScale = (targetPower * FINAL_HP_MUL) / totalBasePower;
|
||||
const heroAvgAp = this.getCurrentHeroAttack();
|
||||
for (const m of monsters) {
|
||||
m.hp = Math.max(1, Math.round(m.hp * hpScale));
|
||||
// ap = 玩家平均攻击 × 最终递进 × 基础系数 × 全局强度系数 × 类型系数
|
||||
m.ap = Math.max(1, Math.round(heroAvgAp * AP_GROWTH_FINAL * AP_RELATIVE * MON_POWER_MUL * this.getApTypeFactor(m)));
|
||||
}
|
||||
// 属性缩放:基础属性 × 可调系数(Boss 血量额外加成),校准目标双方对砍 ≈ 30s
|
||||
for (const m of monsters) {
|
||||
m.hp = Math.max(1, Math.round(m.hp * MON_HP_MUL * (m.isBoss ? BOSS_HP_BONUS_MUL : 1)));
|
||||
m.ap = Math.max(1, Math.round(m.ap * MON_AP_MUL));
|
||||
}
|
||||
|
||||
// 挂载组合技能(Boss 专属池 / 小怪普通池)
|
||||
@@ -443,45 +424,6 @@ export class RogueSpawningEngine {
|
||||
reset(): void {
|
||||
}
|
||||
|
||||
// ======================== 私有生成子算法 ========================
|
||||
|
||||
/**
|
||||
* 计算场上存活英雄的总强度
|
||||
* 通过 ECS 查询所有 HeroAttrsComp,累加 calcHeroPower
|
||||
*/
|
||||
private getCurrentHeroPower(): number {
|
||||
let total = 0;
|
||||
ecs.query(ecs.allOf(HeroAttrsComp)).forEach((entity: ecs.Entity) => {
|
||||
const attrs = entity.get(HeroAttrsComp);
|
||||
if (!attrs || attrs.is_dead || attrs.fac !== FacSet.HERO) return;
|
||||
const info = HeroInfo[attrs.hero_uuid];
|
||||
if (!info) return;
|
||||
// 使用英雄当前等级(升级卡驱动),保证强度评估与实战一致
|
||||
const lv = Math.max(1, attrs.lv || 1);
|
||||
total += calcHeroPower(info, lv);
|
||||
});
|
||||
// 兜底:无英雄时返回基准强度,避免除零
|
||||
return Math.max(total, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算场上存活英雄的输出强度(用于怪物 ap 挂钩玩家,独立于总强度框架)。
|
||||
* 取玩家英雄的"实时 ap 平均",怪物 ap 以此为锚,保证玩家输出越高、被反击越痛。
|
||||
*/
|
||||
private getCurrentHeroAttack(): number {
|
||||
let totalAp = 0;
|
||||
let count = 0;
|
||||
ecs.query(ecs.allOf(HeroAttrsComp)).forEach((entity: ecs.Entity) => {
|
||||
const attrs = entity.get(HeroAttrsComp);
|
||||
if (!attrs || attrs.is_dead || attrs.fac !== FacSet.HERO) return;
|
||||
totalAp += Math.max(1, attrs.ap || 1);
|
||||
count++;
|
||||
});
|
||||
// 兜底:无英雄时返回基准攻击,避免除零
|
||||
if (count === 0) return 30;
|
||||
return totalAp / count; // 平均单英雄攻击
|
||||
}
|
||||
|
||||
/** 测试模式:完全绕过引擎逻辑 */
|
||||
private generateTestWave(): GeneratedMonster[] {
|
||||
const count = Math.max(1, TestModeConfig.spawnCount || 1);
|
||||
@@ -536,20 +478,6 @@ export class RogueSpawningEngine {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 怪物 ap 类型系数:Boss 上浮,远程/召唤稍降(避免玻璃大炮互秒),近战/重甲基准。
|
||||
*/
|
||||
private getApTypeFactor(m: GeneratedMonster): number {
|
||||
if (m.isBoss) return 2.2; // Boss 单发重,符合"压场"定位
|
||||
if (m.isBossGuard) return 1.2; // 护卫略高于杂鱼
|
||||
switch (m.type) {
|
||||
case MonType.Long: return 0.9;
|
||||
case MonType.Summoner: return 0.7;
|
||||
case MonType.Assassin: return 1.1;
|
||||
default: return 1.0; // Melee / Heavy
|
||||
}
|
||||
}
|
||||
|
||||
/** 生成普通怪物 */
|
||||
private makeMonster(type: MonType, spawnIndex: number): GeneratedMonster {
|
||||
let uuids = MonList[type];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { v3, Vec3 ,Node} from "cc";
|
||||
import { v3, Vec3, Node } from "cc";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { EType, RType, SkillSet } from "../common/config/SkillSet";
|
||||
import { SMoveDataComp } from "./SMoveComp";
|
||||
@@ -26,46 +26,46 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
filter(): ecs.IMatcher {
|
||||
return ecs.allOf(SMoveDataComp, SkillView);
|
||||
}
|
||||
|
||||
|
||||
entityEnter(entity: ecs.Entity): void {
|
||||
const moveComp = entity.get(SMoveDataComp);
|
||||
const skillView = entity.get(SkillView);
|
||||
|
||||
|
||||
if (!moveComp || !skillView || !skillView.node) return;
|
||||
|
||||
|
||||
// 获取技能配置
|
||||
const skillConfig = SkillSet[moveComp.s_uuid];
|
||||
if (!skillConfig) {
|
||||
mLogger.warn(this.debugMode, 'SMoveSystem', `[SMoveSystem] 技能配置不存在: ${moveComp.s_uuid}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据配置设置移动速度与加速度
|
||||
if (skillConfig.speed > 0) {
|
||||
|
||||
// 移动参数由 prefab 的 SkillView @property 决定(speed<=0 时 Skill.load 已回退配置表值)
|
||||
if (moveComp.speed <= 0) {
|
||||
moveComp.speed = skillConfig.speed;
|
||||
}
|
||||
if (skillConfig.is_accel) {
|
||||
moveComp.isAccelerate = true;
|
||||
}
|
||||
|
||||
|
||||
// 根据runType设置初始位置
|
||||
this.initializePosition(moveComp, skillView);
|
||||
|
||||
|
||||
// 开始移动(除了固定位置类型)
|
||||
if (moveComp.runType !== RType.fixed && moveComp.runType !== RType.fixedEnd) {
|
||||
moveComp.startMove();
|
||||
}
|
||||
|
||||
|
||||
mLogger.log(this.debugMode, 'SMoveSystem', `[SMoveSystem] 技能 ${skillConfig.name} 开始移动,类型: ${moveComp.runType}`);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据runType初始化技能位置
|
||||
*/
|
||||
private initializePosition(moveComp: SMoveDataComp, skillView: SkillView): void {
|
||||
const node = skillView.node;
|
||||
|
||||
switch(moveComp.runType) {
|
||||
|
||||
switch (moveComp.runType) {
|
||||
case RType.linear:
|
||||
// linear类型:根据atk_x和atk_y调整起始位置
|
||||
const adjustedStartPos = v3(
|
||||
@@ -73,35 +73,35 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
moveComp.startPos.y + moveComp.atk_y,
|
||||
moveComp.startPos.z
|
||||
);
|
||||
|
||||
|
||||
const originTargetPos = v3(
|
||||
moveComp.targetPos.x,
|
||||
moveComp.targetPos.y,
|
||||
moveComp.targetPos.z
|
||||
);
|
||||
|
||||
|
||||
const direction = new Vec3();
|
||||
Vec3.subtract(direction, originTargetPos, adjustedStartPos);
|
||||
|
||||
|
||||
// 延长终止点,统一消亡点的x坐标为 +-500
|
||||
const targetX = moveComp.scale > 0 ? 500 : -500;
|
||||
let targetY = originTargetPos.y;
|
||||
|
||||
|
||||
if (Math.abs(direction.x) > 0.01) {
|
||||
const slope = direction.y / direction.x;
|
||||
targetY = adjustedStartPos.y + slope * (targetX - adjustedStartPos.x);
|
||||
}
|
||||
|
||||
|
||||
const adjustedTargetPos = v3(
|
||||
targetX,
|
||||
targetY,
|
||||
originTargetPos.z
|
||||
);
|
||||
|
||||
|
||||
moveComp.startPos.set(adjustedStartPos);
|
||||
moveComp.targetPos.set(adjustedTargetPos);
|
||||
node.setPosition(adjustedStartPos);
|
||||
|
||||
|
||||
// 设置旋转角度
|
||||
const dirForAngle = new Vec3();
|
||||
Vec3.subtract(dirForAngle, adjustedTargetPos, adjustedStartPos);
|
||||
@@ -113,12 +113,12 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
node.angle = angle;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case RType.fixed:
|
||||
// 固定起始位置
|
||||
node.setPosition(moveComp.startPos.x, node.position.y, 0);
|
||||
break;
|
||||
|
||||
|
||||
case RType.fixedEnd:
|
||||
// 固定结束位置
|
||||
node.setPosition(moveComp.targetPos.x > 360 ? 300 : moveComp.targetPos.x, moveComp.targetPos.y, 0);
|
||||
@@ -154,26 +154,26 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
}
|
||||
|
||||
update(entity: ecs.Entity): void {
|
||||
if(!smc.mission.play ) return;
|
||||
if(smc.mission.pause) return
|
||||
if (!smc.mission.play) return;
|
||||
if (smc.mission.pause) return
|
||||
const moveComp = entity.get(SMoveDataComp);
|
||||
const skillView = entity.get(SkillView);
|
||||
|
||||
|
||||
if (!moveComp || !skillView || !skillView.node) return;
|
||||
|
||||
|
||||
// 更新移动进度
|
||||
const isMoving = moveComp.updateProgress(this.dt);
|
||||
|
||||
|
||||
if (isMoving) {
|
||||
// 更新节点位置
|
||||
skillView.node.setPosition(moveComp.currentPos);
|
||||
|
||||
|
||||
// 处理自动旋转(贝塞尔移动)
|
||||
if (moveComp.runType === RType.bezier) {
|
||||
this.updateRotation(skillView.node, moveComp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 检查移动完成
|
||||
if (moveComp.isCompleted && moveComp.autoDestroy) {
|
||||
// 根据结束类型决定是否销毁
|
||||
@@ -185,7 +185,7 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新节点旋转(用于贝塞尔移动)
|
||||
*/
|
||||
@@ -193,29 +193,29 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
if (moveComp.progress < 1) {
|
||||
// 计算下一帧的位置来确定方向
|
||||
const nextProgress = Math.min(moveComp.progress + 0.01, 1);
|
||||
const t = moveComp.isAccelerate ?
|
||||
(nextProgress * nextProgress * 0.7 + nextProgress * 0.3) :
|
||||
const t = moveComp.isAccelerate ?
|
||||
(nextProgress * nextProgress * 0.7 + nextProgress * 0.3) :
|
||||
nextProgress;
|
||||
const nextPos = v3(0, 0, 0);
|
||||
|
||||
|
||||
// 计算下一个位置
|
||||
const oneMinusT = 1 - t;
|
||||
const oneMinusTSquared = oneMinusT * oneMinusT;
|
||||
const tSquared = t * t;
|
||||
const twoOneMinusTt = 2 * oneMinusT * t;
|
||||
|
||||
nextPos.x = oneMinusTSquared * moveComp.startPos.x +
|
||||
twoOneMinusTt * moveComp.controlPoint.x +
|
||||
tSquared * moveComp.targetPos.x;
|
||||
|
||||
nextPos.y = oneMinusTSquared * moveComp.startPos.y +
|
||||
twoOneMinusTt * moveComp.controlPoint.y +
|
||||
tSquared * moveComp.targetPos.y;
|
||||
|
||||
|
||||
nextPos.x = oneMinusTSquared * moveComp.startPos.x +
|
||||
twoOneMinusTt * moveComp.controlPoint.x +
|
||||
tSquared * moveComp.targetPos.x;
|
||||
|
||||
nextPos.y = oneMinusTSquared * moveComp.startPos.y +
|
||||
twoOneMinusTt * moveComp.controlPoint.y +
|
||||
tSquared * moveComp.targetPos.y;
|
||||
|
||||
// 计算方向角度
|
||||
const direction = new Vec3();
|
||||
Vec3.subtract(direction, nextPos, moveComp.currentPos);
|
||||
|
||||
|
||||
if (direction.length() > 0.01) {
|
||||
let angle = Math.atan2(direction.y, direction.x) * (180 / Math.PI);
|
||||
if (moveComp.scale < 0) {
|
||||
@@ -236,15 +236,15 @@ export class SMoveHelper {
|
||||
*/
|
||||
static setupMoveForSkill(entity: ecs.Entity, startPos: Vec3, targetPos: Vec3, s_uuid: number): void {
|
||||
let moveComp = entity.get(SMoveDataComp);
|
||||
|
||||
|
||||
if (!moveComp) {
|
||||
moveComp = entity.add(SMoveDataComp);
|
||||
}
|
||||
|
||||
|
||||
moveComp.startPos.set(startPos);
|
||||
moveComp.targetPos.set(targetPos);
|
||||
moveComp.s_uuid = s_uuid;
|
||||
|
||||
|
||||
// 从技能配置获取默认参数
|
||||
const skillConfig = SkillSet[s_uuid];
|
||||
if (skillConfig) {
|
||||
@@ -253,7 +253,7 @@ export class SMoveHelper {
|
||||
if (skillConfig.is_accel) moveComp.isAccelerate = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查技能是否正在移动
|
||||
*/
|
||||
@@ -261,7 +261,7 @@ export class SMoveHelper {
|
||||
const moveComp = entity.get(SMoveDataComp);
|
||||
return moveComp ? moveComp.isMoving : false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取技能移动统计信息
|
||||
*/
|
||||
@@ -269,7 +269,7 @@ export class SMoveHelper {
|
||||
const moveComp = entity.get(SMoveDataComp);
|
||||
return moveComp ? moveComp.getMoveStats() : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 停止技能移动
|
||||
*/
|
||||
|
||||
@@ -146,7 +146,7 @@ export class Skill extends ecs.Entity {
|
||||
if (node.isValid) node.destroy();
|
||||
return;
|
||||
}
|
||||
if (config.EType != EType.collision) {
|
||||
if (SView.endType != EType.collision) {
|
||||
const collider = node.getComponent(BoxCollider2D);
|
||||
if (collider) {
|
||||
collider.enabled = false
|
||||
@@ -174,8 +174,10 @@ export class Skill extends ecs.Entity {
|
||||
sMoveCom.targetPos.set(targetPos);
|
||||
sMoveCom.s_uuid = s_uuid;
|
||||
sMoveCom.scale = caster.node.scale.x < 0 ? -1 : 1;
|
||||
sMoveCom.runType = config.RType;
|
||||
sMoveCom.endType = config.EType;
|
||||
// runType/endType/speed/time 由 prefab 的 SkillView @property 决定,配置表同名字段仅作兜底
|
||||
sMoveCom.runType = SView.runType;
|
||||
sMoveCom.endType = SView.endType;
|
||||
sMoveCom.speed = SView.speed > 0 ? SView.speed : config.speed;
|
||||
sMoveCom.bezierStartHeight = config.bezier_start_y ?? sMoveCom.bezierStartHeight;
|
||||
sMoveCom.bezierMidHeight = config.bezier_mid_y ?? sMoveCom.bezierMidHeight;
|
||||
sMoveCom.bezierArc = config.bezier_arc ?? sMoveCom.bezierArc;
|
||||
@@ -183,12 +185,12 @@ export class Skill extends ecs.Entity {
|
||||
sMoveCom.atk_x = SView.atk_x;
|
||||
sMoveCom.atk_y = SView.atk_y;
|
||||
|
||||
if (config.EType === EType.timeEnd) {
|
||||
if (SView.endType === EType.timeEnd) {
|
||||
let sTimeCom = this.get(StimeDataComp);
|
||||
if (!sTimeCom) sTimeCom = this.add(StimeDataComp);
|
||||
sTimeCom.reset();
|
||||
sTimeCom.s_uuid = s_uuid;
|
||||
sTimeCom.totalTime = Math.max(1, config.time ?? 0);
|
||||
sTimeCom.totalTime = Math.max(1, SView.time > 0 ? SView.time : (config.time ?? 0));
|
||||
sTimeCom.hitInterval = Math.max(0.5, config.hitcd || 0);
|
||||
} else {
|
||||
const sTimeCom = this.get(StimeDataComp);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { _decorator, Animation, CCInteger, Collider2D, Contact2DType, UITransform, v3, Vec3 } from "cc";
|
||||
import { _decorator, Animation, CCFloat, CCInteger, Collider2D, Contact2DType, Enum, UITransform, v3, Vec3 } from "cc";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||
import { HeroViewComp } from "../hero/HeroViewComp";
|
||||
import { DTType, EType, SkillConfig, SkillSet } from "../common/config/SkillSet";
|
||||
import { DTType, EType, RType, SkillConfig, SkillSet } from "../common/config/SkillSet";
|
||||
import { SDataCom } from "./SDataCom";
|
||||
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
||||
import { DamageQueueHelper } from "../hero/DamageQueueComp";
|
||||
@@ -22,13 +22,29 @@ export class SkillView extends CCComp {
|
||||
@property({ type: CCInteger })
|
||||
atk_y: number = 0
|
||||
|
||||
/** 运动类型:直线/贝塞尔/固定起点/固定终点(由 prefab 配置,优先级高于 SkillSet) */
|
||||
@property({ type: Enum(RType), tooltip: "技能特效运动类型" })
|
||||
runType: RType = RType.linear;
|
||||
|
||||
/** 消亡条件:动画结束/计时结束/碰撞次数结束(由 prefab 配置,优先级高于 SkillSet) */
|
||||
@property({ type: Enum(EType), tooltip: "技能特效消亡条件" })
|
||||
endType: EType = EType.collision;
|
||||
|
||||
/** 移动速度(由 prefab 配置,<=0 时回退 SkillSet.speed) */
|
||||
@property({ type: CCFloat, slide: true, range: [0, 2000, 10], tooltip: "技能特效移动速度" })
|
||||
speed: number = 0;
|
||||
|
||||
/** timeEnd 持续时间(秒),仅 endType=timeEnd 时生效(由 prefab 配置,<=0 时回退 SkillSet.time) */
|
||||
@property({ type: CCFloat, slide: true, range: [0, 30, 0.1], tooltip: "timeEnd 持续时间(秒)" })
|
||||
time: number = 0;
|
||||
|
||||
private debugMode: boolean = false;
|
||||
|
||||
anim:Animation=null;
|
||||
group:number=0;
|
||||
SConf:SkillConfig=null;
|
||||
sData:SDataCom=null;
|
||||
s_uuid:number=1001
|
||||
anim: Animation = null;
|
||||
group: number = 0;
|
||||
SConf: SkillConfig = null;
|
||||
sData: SDataCom = null;
|
||||
s_uuid: number = 1001
|
||||
private collider: Collider2D = null; // 缓存碰撞体引用
|
||||
private pendingDisableCollider: boolean = false;
|
||||
private isDisposing: boolean = false;
|
||||
@@ -41,25 +57,25 @@ export class SkillView extends CCComp {
|
||||
this.pendingDisableCollider = false;
|
||||
this.isDisposing = false;
|
||||
this.collider = this.getComponent(Collider2D);
|
||||
if(this.collider) {
|
||||
if (this.collider) {
|
||||
this.collider.group = this.group;
|
||||
this.collider.off(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
|
||||
this.collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
|
||||
this.collider.enabled = this.SConf?.EType === EType.collision;
|
||||
this.collider.enabled = this.endType === EType.collision;
|
||||
}
|
||||
if(this.node.getComponent(Animation)){
|
||||
if (this.node.getComponent(Animation)) {
|
||||
let anim = this.node.getComponent(Animation);
|
||||
mLogger.log(this.debugMode, 'SkillView', "[SkillCom]:has anim",anim)
|
||||
mLogger.log(this.debugMode, 'SkillView', "[SkillCom]:has anim", anim)
|
||||
anim.off(Animation.EventType.FINISHED, this.onAnimationFinished, this);
|
||||
anim.on(Animation.EventType.FINISHED, this.onAnimationFinished, this);
|
||||
|
||||
|
||||
// 对象池复用时,需要手动播放默认动画(因为 Play On Load 只在首次生效)
|
||||
if (anim.defaultClip) {
|
||||
anim.play(anim.defaultClip.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
onBeginContact (seCol: Collider2D, oCol: Collider2D) {
|
||||
onBeginContact(seCol: Collider2D, oCol: Collider2D) {
|
||||
if (!this.sData || !this.SConf) {
|
||||
mLogger.warn(this.debugMode, 'SkillView', '[SkillView] onBeginContact 缺少 sData 或 SConf,忽略此次碰撞');
|
||||
return;
|
||||
@@ -126,17 +142,23 @@ export class SkillView extends CCComp {
|
||||
this.apply_damage(targetView, this.sData.hit_count)
|
||||
}
|
||||
|
||||
onAnimationFinished(){
|
||||
// animationEnd 类型:动画结束后再关闭碰撞并销毁
|
||||
if(this.SConf.EType==EType.animationEnd){
|
||||
onAnimationFinished() {
|
||||
// animationEnd 类型:动画结束后再关闭碰撞并销毁
|
||||
if (this.endType == EType.animationEnd) {
|
||||
this.disable_collider_now();
|
||||
this.ent.destroy()
|
||||
}
|
||||
return;
|
||||
}
|
||||
// fixed 类型不移动,无法通过移动完成销毁;动画播完作为兜底销毁时机
|
||||
if (this.runType == RType.fixed) {
|
||||
this.disable_collider_now();
|
||||
this.ent.destroy()
|
||||
}
|
||||
}
|
||||
// 动画帧事件 atk:仅负责开启一帧碰撞窗口,不负责伤害与计数
|
||||
public atk(args:any){
|
||||
if(!this.SConf) return;
|
||||
if(this.SConf.EType==EType.collision) return
|
||||
public atk(args: any) {
|
||||
if (!this.SConf) return;
|
||||
if (this.endType == EType.collision) return
|
||||
if (this.enable_collider_safely()) {
|
||||
mLogger.log(this.debugMode, 'SkillView', `[SkillView] [${this.SConf?.name}] 开启碰撞检测`);
|
||||
this.scheduleOnce(() => {
|
||||
@@ -179,7 +201,7 @@ export class SkillView extends CCComp {
|
||||
finalRatio,
|
||||
);
|
||||
}
|
||||
close_collider(){
|
||||
close_collider() {
|
||||
if (!this.collider) return;
|
||||
if (this.pendingDisableCollider && !this.collider.enabled) return;
|
||||
this.pendingDisableCollider = true;
|
||||
|
||||
@@ -146,10 +146,10 @@ export class TooltipCom extends CCComp {
|
||||
this.node.setPosition(v3(this.node.position.x, currentY - 60));
|
||||
this.node.setSiblingIndex(topSiblingIndex);
|
||||
break;
|
||||
case TooltipTypes.shield: // 护盾格挡
|
||||
case TooltipTypes.shield: // 护盾减免
|
||||
this.node.setPosition(v3(this.node.position.x + offsetX, currentY));
|
||||
this.node.setSiblingIndex(topSiblingIndex);
|
||||
this.setupLabel("add_life", "hp", "格挡");
|
||||
this.setupLabel("add_life", "hp", "减免");
|
||||
isHeal = true;
|
||||
break;
|
||||
}
|
||||
|
||||
83
tools/sync-skill-prefab.js
Normal file
83
tools/sync-skill-prefab.js
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* 一次性迁移脚本:把 SkillSet 中的 RType/EType/speed/time 刷入各技能 prefab 的 SkillView 序列化字段。
|
||||
* 用法: node tools/sync-skill-prefab.js
|
||||
* 注意: 直接改写 prefab JSON,运行前请保证工作区已提交。
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '..');
|
||||
const SKILL_SET = path.join(ROOT, 'assets/script/game/common/config/SkillSet.ts');
|
||||
const PREFAB_DIR = path.join(ROOT, 'assets/resources/game/skill/atk');
|
||||
// SkillView 组件在 prefab 中的脚本类 cid
|
||||
const SKILL_VIEW_CID = '57aabs7TE1J5obTAZczc+64';
|
||||
|
||||
const RTYPE = { linear: 0, bezier: 1, fixed: 2, fixedEnd: 3 };
|
||||
const ETYPE = { animationEnd: 0, timeEnd: 1, collision: 2 };
|
||||
|
||||
/** 从 SkillSet.ts 解析 sp_name -> {runType, endType, speed, time} */
|
||||
function parseSkillSet(src) {
|
||||
const map = new Map();
|
||||
// 匹配每个技能条目块
|
||||
const entryRe = /\d+:\s*\{([\s\S]*?)\n\s*\},/g;
|
||||
let m;
|
||||
while ((m = entryRe.exec(src)) !== null) {
|
||||
const body = m[1];
|
||||
const sp = body.match(/sp_name:\s*"([^"]+)"/);
|
||||
if (!sp) continue;
|
||||
const spName = sp[1];
|
||||
|
||||
const rt = body.match(/RType:\s*RType\.(\w+)/);
|
||||
const et = body.match(/EType:\s*EType\.(\w+)/);
|
||||
const speed = body.match(/speed:\s*([\d.]+)/);
|
||||
const time = body.match(/\btime:\s*([\d.]+)/);
|
||||
|
||||
const entry = {
|
||||
runType: rt ? RTYPE[rt[1]] : undefined,
|
||||
endType: et ? ETYPE[et[1]] : undefined,
|
||||
speed: speed ? Number(speed[1]) : undefined,
|
||||
time: time ? Number(time[1]) : 0,
|
||||
};
|
||||
// 多个技能可共用同一 sp_name,保留首个非 undefined 组合
|
||||
if (!map.has(spName)) map.set(spName, entry);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const src = fs.readFileSync(SKILL_SET, 'utf8');
|
||||
const confMap = parseSkillSet(src);
|
||||
|
||||
const files = fs.readdirSync(PREFAB_DIR).filter(f => f.endsWith('.prefab'));
|
||||
const report = { updated: [], skipped: [], noConf: [] };
|
||||
|
||||
for (const file of files) {
|
||||
const spName = path.basename(file, '.prefab');
|
||||
const conf = confMap.get(spName);
|
||||
const fp = path.join(PREFAB_DIR, file);
|
||||
const json = JSON.parse(fs.readFileSync(fp, 'utf8'));
|
||||
|
||||
// 定位 SkillView 组件
|
||||
const comp = json.find(o => o && o.__type__ === SKILL_VIEW_CID);
|
||||
if (!comp) { report.skipped.push(file + ' (no SkillView)'); continue; }
|
||||
|
||||
if (!conf) { report.noConf.push(file); continue; }
|
||||
|
||||
if (conf.runType !== undefined) comp.runType = conf.runType;
|
||||
if (conf.endType !== undefined) comp.endType = conf.endType;
|
||||
if (conf.speed !== undefined) comp.speed = conf.speed;
|
||||
comp.time = conf.time ?? 0;
|
||||
|
||||
fs.writeFileSync(fp, JSON.stringify(json, null, 2) + '\n', 'utf8');
|
||||
report.updated.push(`${file} -> runType=${comp.runType} endType=${comp.endType} speed=${comp.speed} time=${comp.time}`);
|
||||
}
|
||||
|
||||
console.log('=== updated ===');
|
||||
report.updated.forEach(s => console.log(' ' + s));
|
||||
console.log('=== no config matched ===');
|
||||
report.noConf.forEach(s => console.log(' ' + s));
|
||||
console.log('=== skipped ===');
|
||||
report.skipped.forEach(s => console.log(' ' + s));
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user