优化层级

master
humingxing 2 weeks ago
parent a74dd31d5a
commit 1e2f20c499
  1. 3121
      assets/bundles/battleGame/prefab/BattleGame.prefab
  2. 169
      assets/bundles/battleGame/prefab/canUpEff.prefab
  3. 13
      assets/bundles/battleGame/prefab/canUpEff.prefab.meta
  4. 2486
      assets/bundles/battleGame/prefab/textGrid.prefab
  5. 154
      assets/bundles/battleGame/prefab/trail1.prefab
  6. 13
      assets/bundles/battleGame/prefab/trail1.prefab.meta
  7. 154
      assets/bundles/battleGame/prefab/trail2.prefab
  8. 13
      assets/bundles/battleGame/prefab/trail2.prefab.meta
  9. 154
      assets/bundles/battleGame/prefab/trail3.prefab
  10. 13
      assets/bundles/battleGame/prefab/trail3.prefab.meta
  11. 0
      assets/bundles/battleHero/prefab/num.meta
  12. 146
      assets/bundles/battleHero/prefab/num/1.prefab
  13. 13
      assets/bundles/battleHero/prefab/num/1.prefab.meta
  14. 146
      assets/bundles/battleHero/prefab/num/1024.prefab
  15. 13
      assets/bundles/battleHero/prefab/num/1024.prefab.meta
  16. 146
      assets/bundles/battleHero/prefab/num/128.prefab
  17. 13
      assets/bundles/battleHero/prefab/num/128.prefab.meta
  18. 146
      assets/bundles/battleHero/prefab/num/16.prefab
  19. 13
      assets/bundles/battleHero/prefab/num/16.prefab.meta
  20. 146
      assets/bundles/battleHero/prefab/num/2.prefab
  21. 13
      assets/bundles/battleHero/prefab/num/2.prefab.meta
  22. 146
      assets/bundles/battleHero/prefab/num/2048.prefab
  23. 13
      assets/bundles/battleHero/prefab/num/2048.prefab.meta
  24. 146
      assets/bundles/battleHero/prefab/num/256.prefab
  25. 13
      assets/bundles/battleHero/prefab/num/256.prefab.meta
  26. 146
      assets/bundles/battleHero/prefab/num/32.prefab
  27. 13
      assets/bundles/battleHero/prefab/num/32.prefab.meta
  28. 146
      assets/bundles/battleHero/prefab/num/4.prefab
  29. 13
      assets/bundles/battleHero/prefab/num/4.prefab.meta
  30. 146
      assets/bundles/battleHero/prefab/num/4096.prefab
  31. 13
      assets/bundles/battleHero/prefab/num/4096.prefab.meta
  32. 146
      assets/bundles/battleHero/prefab/num/512.prefab
  33. 13
      assets/bundles/battleHero/prefab/num/512.prefab.meta
  34. 146
      assets/bundles/battleHero/prefab/num/64.prefab
  35. 13
      assets/bundles/battleHero/prefab/num/64.prefab.meta
  36. 146
      assets/bundles/battleHero/prefab/num/8.prefab
  37. 13
      assets/bundles/battleHero/prefab/num/8.prefab.meta
  38. 146
      assets/bundles/battleHero/prefab/num/8192.prefab
  39. 13
      assets/bundles/battleHero/prefab/num/8192.prefab.meta
  40. 2
      assets/res/font/str.txt
  41. 8
      assets/script/battle/ai/bridge/AiBattleBridge.ts
  42. 139
      assets/script/battle/ai/runtime/AiMapTextHost.ts
  43. 19
      assets/script/battle/presentation/SkillVisualChannel.ts
  44. 6
      assets/script/battle/res/BattleHeroResCollector.ts
  45. 18
      assets/script/battle/view/BagToMapPlaceAnimator.ts
  46. 56
      assets/script/battle/view/BoardGridRegistry.ts
  47. 4
      assets/script/battle/view/BoardPlaceFlightExecutor.ts
  48. 283
      assets/script/battle/view/CocosBagBoardView.ts
  49. 27
      assets/script/battle/view/PassiveIconArcFlight.ts
  50. 355
      assets/script/battle/view/TextGrid.ts
  51. 4
      assets/script/game/ResPkgBuilder.ts
  52. 6
      assets/script/ui/BattleGame/Auto_BattleGame.ts
  53. 3
      assets/script/ui/BattleGame/BattleGameStealGlyphFxPresenter.ts
  54. 2
      assets/script/ui/BattleGame/UIBattleGame.ts

File diff suppressed because it is too large Load Diff

@ -0,0 +1,169 @@
[
{
"__type__": "cc.Prefab",
"_name": "canUpEff",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "canUpEff",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": true,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
},
{
"__id__": 6
}
],
"_prefab": {
"__id__": 8
},
"_lpos": {
"__type__": "cc.Vec3",
"x": -19.787,
"y": 25.043,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 0.6,
"y": 0.6,
"z": 1
},
"_mobility": 0,
"_layer": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 56,
"height": 62
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "94ni4BMfBJrZ0TvuVmAoXz"
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_spriteFrame": {
"__uuid__": "a321ee3d-a4ff-4971-8872-984b95aa283f@f9941",
"__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": null,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "04x1i8T1lEtYia2LgggS7r"
},
{
"__type__": "cc.Sorting2D",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 7
},
"_sortingLayer": 3,
"_sortingOrder": 4,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "f2RKuNJOFC/qx2IaJBQKsi"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "cdhnJ1Id9Fm7Ok85sUiumO",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "6db958d2-0178-4baa-b196-8369cfa19481",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "canUpEff"
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,154 @@
[
{
"__type__": "cc.Prefab",
"_name": "trail1",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "trail1",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": true,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 100,
"height": 100
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "f9Pxh70lNHV79RUWjU1ey+"
},
{
"__type__": "443d9JuFCxBGI03SuHBsZqm",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 0,
"g": 0,
"b": 0,
"a": 255
},
"_spriteFrame": {
"__uuid__": "77c83777-51f5-4bbd-afc0-96adc847e1c8@f9941",
"__expectedType__": "cc.SpriteFrame"
},
"maxPoints": 20,
"minDistance": 3,
"headWidth": 36,
"tailWidth": 0,
"headAlpha": 255,
"tailAlpha": 0,
"fadeTime": 0.1,
"headColor": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"tailColor": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "dbxezP7s5H/p+8SELFen24"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "e7bHEhTWRBOL6ieambbKNS",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "9d49fa19-c29a-409a-92ce-49d589b373c3",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "trail1"
}
}

@ -0,0 +1,154 @@
[
{
"__type__": "cc.Prefab",
"_name": "trail2",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "trail2",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": true,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 100,
"height": 100
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "56QqNgyF9CS5Svgav8+MAF"
},
{
"__type__": "443d9JuFCxBGI03SuHBsZqm",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_spriteFrame": {
"__uuid__": "84598bbd-ea44-40a3-a97d-bd510cc3ba2f@f9941",
"__expectedType__": "cc.SpriteFrame"
},
"maxPoints": 20,
"minDistance": 3,
"headWidth": 36,
"tailWidth": 0,
"headAlpha": 255,
"tailAlpha": 0,
"fadeTime": 0.1,
"headColor": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"tailColor": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "e9XJNkKbZCyJwYJy53Of1F"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "efK+WWgNRBz7A+JgStPkTm",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "cb2ceec5-d7bb-455f-8a6b-ba679d7be043",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "trail2"
}
}

@ -0,0 +1,154 @@
[
{
"__type__": "cc.Prefab",
"_name": "trail3",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "trail3",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": true,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 100,
"height": 100
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "9fCMo5CblP7r2KJIxzfrv7"
},
{
"__type__": "443d9JuFCxBGI03SuHBsZqm",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_spriteFrame": {
"__uuid__": "77c83777-51f5-4bbd-afc0-96adc847e1c8@f9941",
"__expectedType__": "cc.SpriteFrame"
},
"maxPoints": 20,
"minDistance": 3,
"headWidth": 36,
"tailWidth": 0,
"headAlpha": 255,
"tailAlpha": 0,
"fadeTime": 0.1,
"headColor": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"tailColor": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "bfMj1XZXdM44uiikFUSoT3"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "aenC5jlMtOq435EFDgeqbR",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "02036cf1-44c9-4761-9f55-30c205611396",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "trail3"
}
}

@ -0,0 +1,146 @@
[
{
"__type__": "cc.Prefab",
"_name": "1",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "1",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": true,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 41.849998474121094,
"height": 52.43000030517578
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.3978494677562816,
"y": 0.37764636890734354
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "aaHm1s101NmKp40s6S3UoT"
},
{
"__type__": "sp.Skeleton",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_skeletonData": {
"__uuid__": "98480b03-176a-4572-87e5-24c15fc93ae9",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "土",
"defaultAnimation": "待机",
"_premultipliedAlpha": false,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "fd6iHqfopIPZQSO1lpt7/h"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "dee4UNWTBAJI+2cAC/h1Rl",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "b4b83de7-55c4-45be-b420-391bcdf373a1",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "1"
}
}

@ -0,0 +1,146 @@
[
{
"__type__": "cc.Prefab",
"_name": "1024",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "1024",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": false,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 75.37999725341797,
"height": 48.380001068115234
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5045104824220789,
"y": 0.38590325886946664
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "43F0LYkoJOl7d48ltVnu2I"
},
{
"__type__": "sp.Skeleton",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_skeletonData": {
"__uuid__": "c8cc4bd6-e5ce-4479-be13-de79ceed1917",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "土",
"defaultAnimation": "攻击",
"_premultipliedAlpha": false,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "4fkpKzI2VIn46uLcGv4VNx"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "c7OPYNrllJcJ5aHGnt+/9c",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "0941d0d4-67fc-4232-b5cc-a2137cd33063",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "1024"
}
}

@ -0,0 +1,146 @@
[
{
"__type__": "cc.Prefab",
"_name": "128",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "128",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": false,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 69.75,
"height": 44.779998779296875
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.49677421542478717,
"y": 0.43702546289197336
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "710Qje7g1BDaTD/d0orLRO"
},
{
"__type__": "sp.Skeleton",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_skeletonData": {
"__uuid__": "4c7e2cdd-58d0-4d24-bf3e-dbb7ebe1ea01",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "土",
"defaultAnimation": "待机",
"_premultipliedAlpha": false,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "9bmcgCIL9HVI3OKOqyB0KG"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "dfqCkVtK1GLY/o6P6vKO8J",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "54bfe38d-9146-40ca-a4d6-28283eda3b5e",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "128"
}
}

@ -0,0 +1,146 @@
[
{
"__type__": "cc.Prefab",
"_name": "16",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "16",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": false,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 58.95000076293945,
"height": 46.349998474121094
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.45038166061826307,
"y": 0.4125135160448559
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "74RUGK74NMJpjUwl5vccut"
},
{
"__type__": "sp.Skeleton",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_skeletonData": {
"__uuid__": "95f5d4e0-f589-4e29-8f31-6483e457efcf",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "土",
"defaultAnimation": "待机",
"_premultipliedAlpha": false,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "fdBpATYTtPv4fDedRug5bo"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "bf8G1dg4lKuoOJ6YuvjR7w",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "1f6554dc-0fed-44b5-b1fc-da63c390e8da",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "16"
}
}

@ -0,0 +1,146 @@
[
{
"__type__": "cc.Prefab",
"_name": "2",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "2",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": false,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 41.400001525878906,
"height": 49.5
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.39685989612598155,
"y": 0.37050505358763414
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "739kfRr8FGXYUON7L8wjbJ"
},
{
"__type__": "sp.Skeleton",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_skeletonData": {
"__uuid__": "92bf30d8-bc81-4826-8b8c-c9b5b9dcc2fd",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "土",
"defaultAnimation": "待机",
"_premultipliedAlpha": false,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "12pSSH+GVHk6n6vesSRQFJ"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "c2Lrl1O85OCbT/o9/KvIVH",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "c23b2a8b-98be-4f8a-998d-ec5c95faa403",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "2"
}
}

@ -0,0 +1,146 @@
[
{
"__type__": "cc.Prefab",
"_name": "2048",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "2048",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": false,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 74.93000030517578,
"height": 43.43000030517578
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.537568378690031,
"y": 0.3971908790878877
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "e7agUmcdRC9pC0vur0Q3ee"
},
{
"__type__": "sp.Skeleton",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_skeletonData": {
"__uuid__": "16c72eea-3349-4835-a09e-adccbd315fd2",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "土",
"defaultAnimation": "攻击",
"_premultipliedAlpha": false,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "8bfm+KYSVMQZ1IH0ayY7q5"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "ecZmt7RxFE5rMprVkC+aNo",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "f2416a3e-92c2-4801-b18e-af7c0ea51d03",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "2048"
}
}

@ -0,0 +1,146 @@
[
{
"__type__": "cc.Prefab",
"_name": "256",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "256",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": false,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 72.9000015258789,
"height": 41.630001068115234
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.4722908036284939,
"y": 0.35671390825025623
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "459AkUbyxPLqUOwTH4GrGc"
},
{
"__type__": "sp.Skeleton",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_skeletonData": {
"__uuid__": "d6fa2e09-cc73-4f68-8dd3-6ff2504de783",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "土",
"defaultAnimation": "攻击",
"_premultipliedAlpha": false,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "aa4yp9jAFGV6BRkNoClIDk"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "f9tZCgHidH56P9uQQPuSlT",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "c1fe4cce-c92a-48b3-96db-a0675e4bb15c",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "256"
}
}

@ -0,0 +1,146 @@
[
{
"__type__": "cc.Prefab",
"_name": "32",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "32",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": false,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 63.68000030517578,
"height": 48.380001068115234
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.4946608016495211,
"y": 0.41856137976288166
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "834wTjz/1P4LXfQG59nCjb"
},
{
"__type__": "sp.Skeleton",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_skeletonData": {
"__uuid__": "2cec1a4c-5d6f-45f4-b432-f59ac52a3e0c",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "土",
"defaultAnimation": "攻击",
"_premultipliedAlpha": false,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "d9kMay12dBPYdpHqKRaFDL"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "27EYySGkVKirlkqOa9CLha",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "ec46b248-e915-4b49-af2d-8fa8c100d43a",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "32"
}
}

@ -0,0 +1,146 @@
[
{
"__type__": "cc.Prefab",
"_name": "4",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "4",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": false,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 45,
"height": 53.54999923706055
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5182222154405381,
"y": 0.3802054323141977
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "b7CBv0sTVE3LMfjHrLU3t9"
},
{
"__type__": "sp.Skeleton",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_skeletonData": {
"__uuid__": "e339dee0-8893-4875-9063-df82b5bca67b",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "土",
"defaultAnimation": "待机",
"_premultipliedAlpha": false,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "fbKzpIDjVF8KUuzutZzsIG"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "4cgPM6k61DUaokJEHO3qwZ",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "5442195f-037d-401f-ade6-877c61fce143",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "4"
}
}

@ -0,0 +1,146 @@
[
{
"__type__": "cc.Prefab",
"_name": "4096",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "4096",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": false,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 88.19999694824219,
"height": 44.099998474121094
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5281179528655644,
"y": 0.4081632794287469
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "09lQ21MhdM9KN8o061RQbx"
},
{
"__type__": "sp.Skeleton",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_skeletonData": {
"__uuid__": "30ee2b62-6672-454a-9eb7-031ee8265f0d",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "土",
"defaultAnimation": "攻击",
"_premultipliedAlpha": false,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "8bTH1n+0ZAYbT2MvrT9lOQ"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "3b4018AKJPe5aMARnRsOMz",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "90816da4-4634-4c97-b0ef-91e9e301195f",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "4096"
}
}

@ -0,0 +1,146 @@
[
{
"__type__": "cc.Prefab",
"_name": "512",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "512",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": false,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 69.75,
"height": 42.529998779296875
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.49677421542478717,
"y": 0.38984247353839596
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "179axgU+BI24XdWFHZ0BQn"
},
{
"__type__": "sp.Skeleton",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_skeletonData": {
"__uuid__": "fe6d211a-a3bc-40ce-8921-360be95f8ffe",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "土",
"defaultAnimation": "攻击",
"_premultipliedAlpha": false,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "16b1tlkZZIi7FTh/B9GPKY"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "fbaHwvSDRLdJonELvEfeyC",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "300ac2de-411a-403a-a0bb-9c2388f7e558",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "512"
}
}

@ -0,0 +1,146 @@
[
{
"__type__": "cc.Prefab",
"_name": "64",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "64",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": false,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 56.70000076293945,
"height": 48.599998474121094
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5079364876461333,
"y": 0.3656378809811276
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "32AZUqlH9AFqMhb0CV+GJX"
},
{
"__type__": "sp.Skeleton",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_skeletonData": {
"__uuid__": "09178b67-37db-4e78-9091-15923024379b",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "土",
"defaultAnimation": "攻击",
"_premultipliedAlpha": false,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "1adD6fRaxDWovsUv6a4l2g"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "67kA5R7LZPYreIy5QlKUjJ",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "035cd432-7b27-430e-98d8-adb6cf586bf1",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "64"
}
}

@ -0,0 +1,146 @@
[
{
"__type__": "cc.Prefab",
"_name": "8",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "8",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": false,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 36.22999954223633,
"height": 52.20000076293945
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5224951847738089,
"y": 0.3772030698520022
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "f7gMAJJ7ZEQLPi6ZKFVwII"
},
{
"__type__": "sp.Skeleton",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_skeletonData": {
"__uuid__": "abeffe7b-8d0c-40b1-8685-77bed935b9a3",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "土",
"defaultAnimation": "待机",
"_premultipliedAlpha": false,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "93yNkZF4BDWKR9ml8O2Tc8"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "fejtObpJ9MV6ebnbt2j5V3",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "4805bc2e-ab54-42d8-8950-63afe85f5e92",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "8"
}
}

@ -0,0 +1,146 @@
[
{
"__type__": "cc.Prefab",
"_name": "8192",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "8192",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": false,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 6
},
"_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": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_contentSize": {
"__type__": "cc.Size",
"width": 88.87999725341797,
"height": 41.849998474121094
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.48098561342333984,
"y": 0.40860217455070885
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "99Q9gf3i9F7ZAe2hydV+OG"
},
{
"__type__": "sp.Skeleton",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_skeletonData": {
"__uuid__": "1f63a4cc-ec66-444d-a7cb-6f405f874c49",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "土",
"defaultAnimation": "攻击",
"_premultipliedAlpha": false,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "fcR+BLc6BIC4Ba5/pgUvqh"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "29bEnCs7hAxK6sSC5LHGSn",
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "116c0ef4-c0d7-4162-8601-82bafaa3cb3a",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "8192"
}
}

File diff suppressed because one or more lines are too long

@ -122,6 +122,14 @@ export class AiBattleBridge {
this._mapText.setFlyLayer(layer); this._mapText.setFlyLayer(layer);
} }
/**
* 绑定 AI 地图字专用层(与玩家 ui_textGrids 相同)。
* @param layer 字块层
*/
setTextGridLayer(layer: Node | null): void {
this._mapText.setTextGridLayer(layer);
}
/** AI 盘面变更后刷新地图字与技能绑定 */ /** AI 盘面变更后刷新地图字与技能绑定 */
notifyAiBoardChanged(): void { notifyAiBoardChanged(): void {
this._onBoardChanged(); this._onBoardChanged();

@ -62,6 +62,8 @@ export class AiMapTextHost {
private _mapClickHandler: ((grid: TextGrid) => void) | null = null; private _mapClickHandler: ((grid: TextGrid) => void) | null = null;
/** 与玩家相同的跳飞层(ui_fly) */ /** 与玩家相同的跳飞层(ui_fly) */
private _flyLayer: Node | null = null; private _flyLayer: Node | null = null;
/** 地图字专用层(ui_textGrids) */
private _textGridLayer: Node | null = null;
/** 当前跳飞;未飞为 null */ /** 当前跳飞;未飞为 null */
private _flight: AiPlaceFlightRun | null = null; private _flight: AiPlaceFlightRun | null = null;
/** 跳飞世代 */ /** 跳飞世代 */
@ -96,6 +98,14 @@ export class AiMapTextHost {
this._flyLayer = layer; this._flyLayer = layer;
} }
/**
* 绑定地图字专用层。
* @param layer ui_textGrids
*/
setTextGridLayer(layer: Node | null): void {
this._textGridLayer = layer?.isValid ? layer : null;
}
/** /**
* 尝试播与玩家相同的跳飞;成功则落地后回调,期间不改 merge。 * 尝试播与玩家相同的跳飞;成功则落地后回调,期间不改 merge。
* 背包无 UI:上阵起点取地图最上方一排中间的上方。 * 背包无 UI:上阵起点取地图最上方一排中间的上方。
@ -132,10 +142,10 @@ export class AiMapTextHost {
const destHasTile = target.kind === 'map' && !!bag.merge.map.getTile(target.gridIndex); const destHasTile = target.kind === 'map' && !!bag.merge.map.getTile(target.gridIndex);
const recyclePrimary = target.kind === 'bag' || (destHasTile && !swap); const recyclePrimary = target.kind === 'bag' || (destHasTile && !swap);
const primaryAttach = !recyclePrimary && target.kind === 'map' const primaryAttach = !recyclePrimary && target.kind === 'map'
? map.getMapGridByIndex(target.gridIndex)?.node ?? null ? this._placeParent(target.gridIndex)
: null; : null;
const swapAttach = swap && source.kind === 'map' const swapAttach = swap && source.kind === 'map'
? map.getMapGridByIndex(source.gridIndex)?.node ?? null ? this._placeParent(source.gridIndex)
: null; : null;
const primary = this._takeFlightGrid(source, startWorld); const primary = this._takeFlightGrid(source, startWorld);
@ -177,14 +187,16 @@ export class AiMapTextHost {
BagToMapPlaceAnimator.play(primary, targetWorld, flyLayer, this._onFlightLegDone, { BagToMapPlaceAnimator.play(primary, targetWorld, flyLayer, this._onFlightLegDone, {
attachParent: primaryAttach, attachParent: primaryAttach,
restWorld: primaryAttach && target.kind === 'map' ? targetWorld : null,
startWorld, startWorld,
showTrail: DeviceProfile.enableBoardPlaceTrail, showTrail: DeviceProfile.enableBoardPlaceTrail,
}); });
if (swapGrid) { if (swapGrid) {
const swapDest = swapAttach ? swapAttach.worldPosition : bagOrigin; const swapDest = swapAttach ? this._cellWorld(source.kind === 'map' ? source.gridIndex : -1) ?? bagOrigin : bagOrigin;
const swapStart = swapGrid.node.worldPosition.clone(); const swapStart = swapGrid.node.worldPosition.clone();
BagToMapPlaceAnimator.play(swapGrid, swapDest, flyLayer, this._onFlightLegDone, { BagToMapPlaceAnimator.play(swapGrid, swapDest, flyLayer, this._onFlightLegDone, {
attachParent: swapAttach, attachParent: swapAttach,
restWorld: swapAttach && source.kind === 'map' ? swapDest : null,
startWorld: swapStart, startWorld: swapStart,
showTrail: DeviceProfile.enableBoardPlaceTrail, showTrail: DeviceProfile.enableBoardPlaceTrail,
}); });
@ -246,16 +258,13 @@ export class AiMapTextHost {
if (!bag || !map) return; if (!bag || !map) return;
const tile = bag.merge.map.getTile(gridIndex); const tile = bag.merge.map.getTile(gridIndex);
if (!tile) return; if (!tile) return;
const parent = map.getMapGridByIndex(gridIndex)?.node;
if (!parent?.isValid) return;
for (let i = this._recs.length - 1; i >= 0; i--) { for (let i = this._recs.length - 1; i >= 0; i--) {
if (this._recs[i].gridIndex !== gridIndex && this._recs[i].grid !== grid) continue; if (this._recs[i].gridIndex !== gridIndex && this._recs[i].grid !== grid) continue;
this._recs.splice(i, 1); this._recs.splice(i, 1);
} }
this._purgeSiblingTextGrids(parent, grid); this._purgeTextGridAtIndex(gridIndex, grid);
Tween.stopAllByTarget(grid.node); Tween.stopAllByTarget(grid.node);
grid.node.parent = parent; if (!this._placeAtIndex(grid, gridIndex)) return;
grid.node.setPosition(0, 0, 0);
grid.node.setScale(1, 1, 1); grid.node.setScale(1, 1, 1);
grid.node.active = true; grid.node.active = true;
const composition = this._compositionAt(bag, gridIndex); const composition = this._compositionAt(bag, gridIndex);
@ -282,6 +291,7 @@ export class AiMapTextHost {
this._mapClickHandler = null; this._mapClickHandler = null;
this.abortFlight(); this.abortFlight();
this._flyLayer = null; this._flyLayer = null;
this._textGridLayer = null;
this._bag = null; this._bag = null;
this._map = null; this._map = null;
this._player = null; this._player = null;
@ -348,13 +358,10 @@ export class AiMapTextHost {
private _registerFlightGrid(grid: TextGrid, gridIndex: number): void { private _registerFlightGrid(grid: TextGrid, gridIndex: number): void {
this._removeRecByGrid(grid); this._removeRecByGrid(grid);
this._removeRecByIndex(gridIndex); this._removeRecByIndex(gridIndex);
const parent = this._map?.getMapGridByIndex(gridIndex)?.node; const parent = this._placeParent(gridIndex);
if (parent?.isValid && grid.node?.isValid) { if (parent?.isValid && grid.node?.isValid) {
this._purgeSiblingTextGrids(parent, grid); this._purgeTextGridAtIndex(gridIndex, grid);
if (grid.node.parent !== parent) { this._placeAtIndex(grid, gridIndex);
grid.node.parent = parent;
grid.node.setPosition(0, 0, 0);
}
grid.node.setScale(1, 1, 1); grid.node.setScale(1, 1, 1);
} }
grid.finishPlaceFlightVisual(); grid.finishPlaceFlightVisual();
@ -441,10 +448,19 @@ export class AiMapTextHost {
private _spawnAtWorld(entity: NonNullable<ReturnType<typeof buildTextGridEntityData>>, startWorld: Readonly<Vec3>): TextGrid | null { private _spawnAtWorld(entity: NonNullable<ReturnType<typeof buildTextGridEntityData>>, startWorld: Readonly<Vec3>): TextGrid | null {
const flyLayer = this._flyLayer; const flyLayer = this._flyLayer;
if (!flyLayer?.isValid) return null; if (!flyLayer?.isValid) return null;
const spawned = this._spawn(entity, flyLayer); const node = gg.res.getNode('prefab/', 'textGrid', GBundle.BattleGame);
if (!spawned?.node?.isValid) return null; if (!node?.isValid) {
spawned.node.setWorldPosition(startWorld.x, startWorld.y, startWorld.z); aiLog('[AiMapTextHost] textGrid prefab missing');
return spawned; return null;
}
node.active = true;
node.parent = flyLayer;
node.setWorldPosition(startWorld.x, startWorld.y, startWorld.z);
node.setScale(1, 1, 1);
const comp = node.getComponent(TextGrid) ?? node.addComponent(TextGrid);
this._applyLite(comp, entity);
comp.rememberOrigin();
return comp;
} }
/** /**
@ -607,10 +623,10 @@ export class AiMapTextHost {
const tile = bag.merge.map.getTile(gridIndex); const tile = bag.merge.map.getTile(gridIndex);
if (!tile) return; if (!tile) return;
const composition = this._compositionAt(bag, gridIndex); const composition = this._compositionAt(bag, gridIndex);
const parent = map.getMapGridByIndex(gridIndex)?.node; const cell = map.getMapGridByIndex(gridIndex)?.node;
if (!parent?.isValid) return; if (!cell?.isValid) return;
keep.push(gridIndex); keep.push(gridIndex);
this._ensure(gridIndex, tile, composition, parent, player); this._ensure(gridIndex, tile, composition, player);
}); });
for (let i = this._recs.length - 1; i >= 0; i--) { for (let i = this._recs.length - 1; i >= 0; i--) {
if (keep.indexOf(this._recs[i].gridIndex) >= 0) continue; if (keep.indexOf(this._recs[i].gridIndex) >= 0) continue;
@ -631,7 +647,6 @@ export class AiMapTextHost {
gridIndex: number, gridIndex: number,
tile: MapTileRecord, tile: MapTileRecord,
composition: ComposedUnit | null, composition: ComposedUnit | null,
parent: Node,
player: Player | null, player: Player | null,
): void { ): void {
const entity = buildTextGridEntityData( const entity = buildTextGridEntityData(
@ -652,17 +667,14 @@ export class AiMapTextHost {
if (this._recs[i].gridIndex !== gridIndex) continue; if (this._recs[i].gridIndex !== gridIndex) continue;
const grid = this._recs[i].grid; const grid = this._recs[i].grid;
if (grid?.isValid && grid.node?.isValid) { if (grid?.isValid && grid.node?.isValid) {
this._purgeSiblingTextGrids(parent, grid); this._purgeTextGridAtIndex(gridIndex, grid);
if (grid.node.parent !== parent) { this._placeAtIndex(grid, gridIndex);
grid.node.parent = parent;
}
if (this._liteSnapshotUnchanged(grid, entity, gridIndex)) { if (this._liteSnapshotUnchanged(grid, entity, gridIndex)) {
grid.setRuinStyle(!!tile.ruined); grid.setRuinStyle(!!tile.ruined);
return; return;
} }
Tween.stopAllByTarget(grid.node); Tween.stopAllByTarget(grid.node);
// 落下 tween 可能未结束就被合成刷新打断,必须归零,否则停在偏上位置 this._placeAtIndex(grid, gridIndex);
grid.node.setPosition(0, 0, 0);
grid.node.setScale(1, 1, 1); grid.node.setScale(1, 1, 1);
grid.node.active = true; grid.node.active = true;
this._applyLite(grid, entity); this._applyLite(grid, entity);
@ -671,27 +683,39 @@ export class AiMapTextHost {
this._recs.splice(i, 1); this._recs.splice(i, 1);
break; break;
} }
this._purgeSiblingTextGrids(parent, null); this._purgeTextGridAtIndex(gridIndex, null);
const spawned = this._spawn(entity, parent); const spawned = this._spawn(entity, gridIndex);
if (!spawned) return; if (!spawned) return;
this._recs.push({ gridIndex, grid: spawned }); this._recs.push({ gridIndex, grid: spawned });
this._playDropIn(spawned.node); this._playDropIn(spawned.node);
} }
/** /**
* 同一 MapGrid 上只留一个 TextGrid,清掉叠字残留(含本机视图误挂的)。 * 清掉该格在专用层/格子上的其它 TextGrid。
* @param parent 格节点 * @param gridIndex 格
* @param keep 保留的字块;null 表示全清 * @param keep 保留的字块;null 表示全清
*/ */
private _purgeSiblingTextGrids(parent: Node, keep: TextGrid | null): void { private _purgeTextGridAtIndex(gridIndex: number, keep: TextGrid | null): void {
if (!parent?.isValid) return; this._purgeHostTextGrids(this._placeParent(gridIndex), gridIndex, keep);
const children = parent.children.slice(); this._purgeHostTextGrids(this._map?.getMapGridByIndex(gridIndex)?.node ?? null, gridIndex, keep);
}
/**
* @param host 扫描节点
* @param gridIndex 格
* @param keep 保留
*/
private _purgeHostTextGrids(host: Node | null, gridIndex: number, keep: TextGrid | null): void {
if (!host?.isValid) return;
const children = host.children.slice();
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
const child = children[i]; const child = children[i];
if (!child?.isValid) continue; if (!child?.isValid) continue;
const tg = child.getComponent(TextGrid); const tg = child.getComponent(TextGrid);
if (!tg?.isValid) continue; if (!tg?.isValid) continue;
if (keep && tg === keep) continue; if (keep && tg === keep) continue;
const loc = tg.location;
if (host === this._textGridLayer && loc?.kind === 'map' && loc.gridIndex !== gridIndex) continue;
for (let r = this._recs.length - 1; r >= 0; r--) { for (let r = this._recs.length - 1; r >= 0; r--) {
if (this._recs[r].grid === tg) this._recs.splice(r, 1); if (this._recs[r].grid === tg) this._recs.splice(r, 1);
} }
@ -702,18 +726,56 @@ export class AiMapTextHost {
} }
} }
private _spawn(entity: NonNullable<ReturnType<typeof buildTextGridEntityData>>, parent: Node): TextGrid | null { /**
* 地图字父节点:专用层优先。
* @param gridIndex 格
*/
private _placeParent(gridIndex: number): Node | null {
const layer = this._textGridLayer;
if (layer?.isValid) return layer;
return this._map?.getMapGridByIndex(gridIndex)?.node ?? null;
}
/**
* 格子世界坐标。
* @param gridIndex 格;<0 无效
*/
private _cellWorld(gridIndex: number): Vec3 | null {
if (gridIndex < 0) return null;
const cell = this._map?.getMapGridByIndex(gridIndex)?.node;
if (!cell?.isValid) return null;
return cell.worldPosition.clone();
}
/**
* 挂到专用层并对齐格子。
* @param grid 字块
* @param gridIndex 格
*/
private _placeAtIndex(grid: TextGrid, gridIndex: number): boolean {
const parent = this._placeParent(gridIndex);
if (!parent?.isValid || !grid.node?.isValid) return false;
if (grid.node.parent !== parent) grid.node.parent = parent;
const world = this._cellWorld(gridIndex);
if (world) grid.node.setWorldPosition(world);
return true;
}
/**
* @param entity 快照
* @param gridIndex 格
*/
private _spawn(entity: NonNullable<ReturnType<typeof buildTextGridEntityData>>, gridIndex: number): TextGrid | null {
const node = gg.res.getNode('prefab/', 'textGrid', GBundle.BattleGame); const node = gg.res.getNode('prefab/', 'textGrid', GBundle.BattleGame);
if (!node?.isValid) { if (!node?.isValid) {
aiLog('[AiMapTextHost] textGrid prefab missing'); aiLog('[AiMapTextHost] textGrid prefab missing');
return null; return null;
} }
node.active = true; node.active = true;
node.parent = parent;
node.setPosition(0, 0, 0);
node.setScale(1, 1, 1); node.setScale(1, 1, 1);
const comp = node.getComponent(TextGrid) ?? node.addComponent(TextGrid); const comp = node.getComponent(TextGrid) ?? node.addComponent(TextGrid);
this._applyLite(comp, entity); this._applyLite(comp, entity);
this._placeAtIndex(comp, gridIndex);
comp.rememberOrigin(); comp.rememberOrigin();
return comp; return comp;
} }
@ -725,7 +787,6 @@ export class AiMapTextHost {
private _playDropIn(node: Node): void { private _playDropIn(node: Node): void {
if (!node?.isValid) return; if (!node?.isValid) return;
Tween.stopAllByTarget(node); Tween.stopAllByTarget(node);
node.setPosition(0, 0, 0);
node.setScale(0.88, 0.88, 1); node.setScale(0.88, 0.88, 1);
tween(node) tween(node)
.to(0.12, { scale: v3(1.1, 1.1, 1) }, { easing: 'quadOut' }) .to(0.12, { scale: v3(1.1, 1.1, 1) }, { easing: 'quadOut' })

@ -687,12 +687,12 @@ export class SkillVisualChannel {
} }
/** /**
* 父节点(TextGrid)上当前激活的数字 Skeleton。 * 在 host 子节点中找当前激活的数字 Skeleton。
* @param host TextGrid 根或 skin
*/ */
private _findNumberGlyphOnParent(): sp.Skeleton | null { private _findNumberGlyphOn(host: Node | null): sp.Skeleton | null {
const parent = this._parent; if (!host?.isValid) return null;
if (!parent?.isValid) return null; const children = host.children;
const children = parent.children;
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
const child = children[i]; const child = children[i];
if (!child?.isValid || !child.active) continue; if (!child?.isValid || !child.active) continue;
@ -703,6 +703,15 @@ export class SkillVisualChannel {
return null; return null;
} }
/**
* 父节点(TextGrid)或 skin 上当前激活的数字 Skeleton。
*/
private _findNumberGlyphOnParent(): sp.Skeleton | null {
const parent = this._parent;
if (!parent?.isValid) return null;
return this._findNumberGlyphOn(parent) ?? this._findNumberGlyphOn(parent.getChildByName('skin'));
}
/** /**
* 子节点名是否为纯数字(对应 Hero.number)。 * 子节点名是否为纯数字(对应 Hero.number)。
* @param name 节点名 * @param name 节点名

@ -13,10 +13,13 @@ export const BATTLE_HERO_WEAPON_PATH = 'prefab/weapon';
/** 局内 buff 预制体目录(缚仙网 / 乾坤袋 / 文昌笔等) */ /** 局内 buff 预制体目录(缚仙网 / 乾坤袋 / 文昌笔等) */
export const BATTLE_HERO_BUFF_PATH = 'prefab/buff/'; export const BATTLE_HERO_BUFF_PATH = 'prefab/buff/';
/** 五行数字字形预制体目录(1/2/4…8192) */
export const BATTLE_HERO_NUM_PATH = 'prefab/num/';
/** battleGameMonster 怪物皮肤目录 */ /** battleGameMonster 怪物皮肤目录 */
export const BATTLE_MONSTER_SKIN_PATH = 'prefab/monster'; export const BATTLE_MONSTER_SKIN_PATH = 'prefab/monster';
/** 进战阻塞包:攻效 + buff + 武器类型预制体(不含已下线的 prefab/hero 英雄体) */ /** 进战阻塞包:攻效 + buff + 武器类型 + 数字字形预制体(不含已下线的 prefab/hero 英雄体) */
export function appendBattleHeroDirLoads(resPkg: ResPakage): void { export function appendBattleHeroDirLoads(resPkg: ResPakage): void {
if (!resPkg.dirs) { if (!resPkg.dirs) {
resPkg.dirs = []; resPkg.dirs = [];
@ -25,6 +28,7 @@ export function appendBattleHeroDirLoads(resPkg: ResPakage): void {
{ bundle: BATTLE_HERO_BUNDLE, path: BATTLE_HERO_SKILL_PATH, type: Prefab }, { bundle: BATTLE_HERO_BUNDLE, path: BATTLE_HERO_SKILL_PATH, type: Prefab },
{ bundle: BATTLE_HERO_BUNDLE, path: BATTLE_HERO_BUFF_PATH, type: Prefab }, { bundle: BATTLE_HERO_BUNDLE, path: BATTLE_HERO_BUFF_PATH, type: Prefab },
{ bundle: BATTLE_HERO_BUNDLE, path: BATTLE_HERO_WEAPON_PATH, type: Prefab }, { bundle: BATTLE_HERO_BUNDLE, path: BATTLE_HERO_WEAPON_PATH, type: Prefab },
{ bundle: BATTLE_HERO_BUNDLE, path: 'prefab/num', type: Prefab },
]; ];
for (const dir of dirs) { for (const dir of dirs) {
resPkg.dirs.push(dir); resPkg.dirs.push(dir);

@ -11,6 +11,8 @@ const LIFT_HEIGHT = 42;
export interface BagToMapPlaceOptions { export interface BagToMapPlaceOptions {
/** 动画结束后挂接的槽位/地图格节点(避免 rebuild 前停在 dragLayer 再瞬移) */ /** 动画结束后挂接的槽位/地图格节点(避免 rebuild 前停在 dragLayer 再瞬移) */
attachParent?: Node | null; attachParent?: Node | null;
/** 落地世界坐标;地图字挂专用层时必须给,否则会落到层原点 */
restWorld?: Readonly<Vec3> | null;
/** 飞行时显示字块拖尾(与背包刷新入场同一套 trail1/2/3) */ /** 飞行时显示字块拖尾(与背包刷新入场同一套 trail1/2/3) */
showTrail?: boolean; showTrail?: boolean;
/** 飞行起点世界坐标;缺省为 node 当前 worldPosition(拉线拖动用 ghost/跟指位置) */ /** 飞行起点世界坐标;缺省为 node 当前 worldPosition(拉线拖动用 ghost/跟指位置) */
@ -105,7 +107,7 @@ export class BagToMapPlaceAnimator {
return; return;
} }
node.setPosition(endLocal); node.setPosition(endLocal);
this._attachToParent(node, opts?.attachParent); this._attachToParent(node, opts?.attachParent, opts?.restWorld);
finish(); finish();
}) })
.start(); .start();
@ -117,12 +119,18 @@ export class BagToMapPlaceAnimator {
grid.resetNodeTransform(); grid.resetNodeTransform();
} }
/** 保持世界坐标挂到目标父节点,并归零本地坐标(与槽位/格心对齐) */ /**
private static _attachToParent(node: Node, attachParent: Node | null | undefined): void { * 挂到目标父节点。
* 有 restWorld:对齐该世界坐标(地图字专用层)。
* 无 restWorld:本地归零(背包槽中心)。
*/
private static _attachToParent(node: Node, attachParent: Node | null | undefined, restWorld?: Readonly<Vec3> | null): void {
if (!attachParent?.isValid) return; if (!attachParent?.isValid) return;
const wp = node.worldPosition.clone();
node.parent = attachParent; node.parent = attachParent;
node.setWorldPosition(wp); if (restWorld) {
node.setWorldPosition(restWorld.x, restWorld.y, restWorld.z);
return;
}
node.setPosition(0, 0, 0); node.setPosition(0, 0, 0);
} }
} }

@ -128,12 +128,16 @@ export class BoardGridRegistry {
return mapHostedCheck(grid); return mapHostedCheck(grid);
} }
/** 背包重建前:收集所有须保护的地图字块(含场景扫描) */ /**
* 背包重建前:收集所有须保护的地图字块(含专用层与格子残留)。
* @param textLayer ui_textGrids
*/
collectMapProtected( collectMapProtected(
out: MembershipSet<TextGrid>, out: MembershipSet<TextGrid>,
map: MapManager | null, map: MapManager | null,
prevMap?: ReadonlyMap<number, TextGrid>, prevMap?: ReadonlyMap<number, TextGrid>,
hasTile?: (gridIndex: number) => boolean, hasTile?: (gridIndex: number) => boolean,
textLayer?: import('cc').Node | null,
): void { ): void {
for (const g of this._mapGrids.values()) { for (const g of this._mapGrids.values()) {
if (g?.isValid) membershipAdd(out, g); if (g?.isValid) membershipAdd(out, g);
@ -143,26 +147,23 @@ export class BoardGridRegistry {
if (g?.isValid && (!hasTile || hasTile(idx))) membershipAdd(out, g); if (g?.isValid && (!hasTile || hasTile(idx))) membershipAdd(out, g);
} }
} }
this._collectTextGridsOnNode(textLayer, out);
const cells = map?.mapGrids; const cells = map?.mapGrids;
if (!cells?.length) return; if (!cells?.length) return;
for (let i = 0; i < cells.length; i++) { for (let i = 0; i < cells.length; i++) {
const parent = cells[i]?.node; this._collectTextGridsOnNode(cells[i]?.node, out);
if (!parent?.isValid) continue;
for (const child of parent.children) {
if (child.name === '__bagDragGhost') continue;
const tg = child.getComponent(TextGrid);
if (tg?.isValid) membershipAdd(out, tg);
}
} }
} }
/** /**
* 背包重建后:按 session 地图数据 + 场景父节点对齐 _mapGrids。 * 背包重建后:按 session 地图数据 + 专用层/格子对齐 _mapGrids。
* @param textLayer ui_textGrids
*/ */
reconcileMapFromScene( reconcileMapFromScene(
map: MapManager, map: MapManager,
hasTile: (gridIndex: number) => boolean, hasTile: (gridIndex: number) => boolean,
isNodeUnderMapCell: (node: import('cc').Node | null | undefined) => boolean, isNodeOnMapLayer: (node: import('cc').Node | null | undefined) => boolean,
textLayer?: import('cc').Node | null,
): void { ): void {
const mapIdx = mapKeysToArray(this._mapGrids); const mapIdx = mapKeysToArray(this._mapGrids);
for (let i = 0; i < mapIdx.length; i++) { for (let i = 0; i < mapIdx.length; i++) {
@ -170,18 +171,18 @@ export class BoardGridRegistry {
const g = this._mapGrids.get(idx); const g = this._mapGrids.get(idx);
if (!hasTile(idx)) { if (!hasTile(idx)) {
this._mapGrids.delete(idx); this._mapGrids.delete(idx);
} else if (!g?.node?.isValid || !isNodeUnderMapCell(g.node)) { } else if (!g?.node?.isValid || !isNodeOnMapLayer(g.node)) {
this._mapGrids.delete(idx); this._mapGrids.delete(idx);
} }
} }
this._indexLayerMapGrids(textLayer, hasTile);
const cells = map.mapGrids; const cells = map.mapGrids;
if (!cells?.length) return; if (!cells?.length) return;
for (let i = 0; i < cells.length; i++) { for (let i = 0; i < cells.length; i++) {
if (!hasTile(i)) continue; if (!hasTile(i)) continue;
if (this._mapGrids.get(i)?.node?.isValid) continue;
const parent = cells[i]?.node; const parent = cells[i]?.node;
if (!parent?.isValid) continue; if (!parent?.isValid) continue;
const tracked = this._mapGrids.get(i);
if (tracked?.node?.isValid && tracked.node.parent === parent) continue;
for (const child of parent.children) { for (const child of parent.children) {
if (child.name === '__bagDragGhost') continue; if (child.name === '__bagDragGhost') continue;
const tg = child.getComponent(TextGrid); const tg = child.getComponent(TextGrid);
@ -222,6 +223,35 @@ export class BoardGridRegistry {
this._flightGrids = []; this._flightGrids = [];
} }
private _collectTextGridsOnNode(host: import('cc').Node | null | undefined, out: MembershipSet<TextGrid>): void {
if (!host?.isValid) return;
for (const child of host.children) {
if (child.name === '__bagDragGhost') continue;
const tg = child.getComponent(TextGrid);
if (tg?.isValid) membershipAdd(out, tg);
}
}
/**
* 按 location 把专用层上的地图字写入索引。
* @param textLayer ui_textGrids
* @param hasTile 该格是否仍有字
*/
private _indexLayerMapGrids(textLayer: import('cc').Node | null | undefined, hasTile: (gridIndex: number) => boolean): void {
if (!textLayer?.isValid) return;
for (const child of textLayer.children) {
if (child.name === '__bagDragGhost') continue;
const tg = child.getComponent(TextGrid);
if (!tg?.isValid) continue;
const loc = tg.location;
if (loc?.kind !== 'map') continue;
if (!hasTile(loc.gridIndex)) continue;
if (!this._mapGrids.get(loc.gridIndex)?.node?.isValid) {
this._mapGrids.set(loc.gridIndex, tg);
}
}
}
private _purgeGridFromIndices(grid: TextGrid): void { private _purgeGridFromIndices(grid: TextGrid): void {
for (const [idx, g] of this._slotGrids) { for (const [idx, g] of this._slotGrids) {
if (g === grid) this._slotGrids.delete(idx); if (g === grid) this._slotGrids.delete(idx);

@ -14,6 +14,8 @@ export interface BoardPlaceFlightLeg {
targetWorld: Readonly<Vec3>; targetWorld: Readonly<Vec3>;
/** 动画结束后挂接父节点;合成时不挂(格上已有真身) */ /** 动画结束后挂接父节点;合成时不挂(格上已有真身) */
attachParent?: Node | null; attachParent?: Node | null;
/** 落地世界坐标(地图字挂 ui_textGrids 时用) */
restWorld?: Readonly<Vec3> | null;
/** 起飞后清空原槽/格残留 */ /** 起飞后清空原槽/格残留 */
vacateFrom: GridDetachSource; vacateFrom: GridDetachSource;
/** 起点世界坐标 */ /** 起点世界坐标 */
@ -124,6 +126,7 @@ export class BoardPlaceFlightExecutor {
BagToMapPlaceAnimator.play(primaryLeg.grid, primaryLeg.targetWorld, dragLayer, onAnimDone, { BagToMapPlaceAnimator.play(primaryLeg.grid, primaryLeg.targetWorld, dragLayer, onAnimDone, {
attachParent: primaryLeg.attachParent, attachParent: primaryLeg.attachParent,
restWorld: primaryLeg.restWorld,
startWorld: primaryLeg.startWorld, startWorld: primaryLeg.startWorld,
showTrail: DeviceProfile.enableBoardPlaceTrail, showTrail: DeviceProfile.enableBoardPlaceTrail,
}); });
@ -132,6 +135,7 @@ export class BoardPlaceFlightExecutor {
if (swapLeg) { if (swapLeg) {
BagToMapPlaceAnimator.play(swapLeg.grid, swapLeg.targetWorld, dragLayer, onAnimDone, { BagToMapPlaceAnimator.play(swapLeg.grid, swapLeg.targetWorld, dragLayer, onAnimDone, {
attachParent: swapLeg.attachParent, attachParent: swapLeg.attachParent,
restWorld: swapLeg.restWorld,
startWorld: swapLeg.startWorld, startWorld: swapLeg.startWorld,
showTrail: DeviceProfile.enableBoardPlaceTrail, showTrail: DeviceProfile.enableBoardPlaceTrail,
}); });

@ -145,6 +145,8 @@ export class CocosBagBoardView {
/** AI 神偷落背包时飞行目标(BattleGame ui_otherBag) */ /** AI 神偷落背包时飞行目标(BattleGame ui_otherBag) */
private _otherBagAnchor: Node | null = null; private _otherBagAnchor: Node | null = null;
private _mapRoot: Node | null = null; private _mapRoot: Node | null = null;
/** 地图字专用层(BattleGame ui_textGrids);未绑定时回退格子节点 */
private _textGridLayer: Node | null = null;
private _dragLayer: Node | null = null; private _dragLayer: Node | null = null;
private _lineNode: Node | null = null; private _lineNode: Node | null = null;
/** 出怪口→受击点流动箭头(由 UI 注入) */ /** 出怪口→受击点流动箭头(由 UI 注入) */
@ -298,12 +300,72 @@ export class CocosBagBoardView {
return null; return null;
} }
/** 节点是否挂在地图格 MapGrid 下 */ /** 地图字父节点:专用层优先 */
private _mapTextLayer(): Node | null {
return this._textGridLayer?.isValid ? this._textGridLayer : null;
}
/**
* 地图字落地挂点与世界坐标。
* @param gridIndex 地图格
*/
private _mapPlaceAttach(gridIndex: number): { attachParent: Node | null; restWorld: Vec3 | null } {
const cell = this._map?.getMapGridByIndex(gridIndex)?.node ?? null;
if (!cell?.isValid) return { attachParent: null, restWorld: null };
const layer = this._mapTextLayer();
return {
attachParent: layer ?? cell,
restWorld: cell.worldPosition.clone(),
};
}
/**
* 把字块挂到专用层并对齐格子世界坐标。
* @param grid 字块
* @param gridIndex 地图格
*/
private _placeMapTextGrid(grid: TextGrid, gridIndex: number): boolean {
if (!grid?.node?.isValid) return false;
const land = this._mapPlaceAttach(gridIndex);
if (!land.attachParent?.isValid || !land.restWorld) return false;
if (grid.node.parent !== land.attachParent) {
grid.node.parent = land.attachParent;
}
grid.node.setWorldPosition(land.restWorld.x, land.restWorld.y, land.restWorld.z);
return true;
}
/**
* 当前地图格上的字块(索引 / 专用层 / 格子残留)。
* @param gridIndex 地图格
*/
private _mapGridOnCell(gridIndex: number): TextGrid | null {
const tracked = this._mapGrids.get(gridIndex);
if (tracked?.isValid && tracked.node?.isValid) return tracked;
const layer = this._mapTextLayer();
if (layer?.isValid) {
const children = layer.children;
for (let i = 0; i < children.length; i++) {
const tg = children[i].getComponent(TextGrid);
if (!tg?.isValid) continue;
const loc = tg.location;
if (loc?.kind === 'map' && loc.gridIndex === gridIndex) return tg;
}
}
const cell = this._map?.getMapGridByIndex(gridIndex)?.node;
return cell?.isValid ? this._grids.findMapGridOnCell(cell) : null;
}
/** 节点是否挂在地图字层或格子下 */
private _isNodeUnderMapCell(node: Node | null | undefined): boolean { private _isNodeUnderMapCell(node: Node | null | undefined): boolean {
if (!node?.isValid || !this._map?.mapGrids?.length) return false; if (!node?.isValid) return false;
const layer = this._mapTextLayer();
if (layer?.isValid && node.parent === layer) return true;
if (!this._map?.mapGrids?.length) return false;
const cells = this._map.mapGrids; const cells = this._map.mapGrids;
let p: Node | null = node.parent; let p: Node | null = node.parent;
while (p) { while (p) {
if (layer?.isValid && p === layer) return true;
for (let i = 0; i < cells.length; i++) { for (let i = 0; i < cells.length; i++) {
if (cells[i]?.node === p) return true; if (cells[i]?.node === p) return true;
} }
@ -338,6 +400,7 @@ export class CocosBagBoardView {
this._map, this._map,
prevMap, prevMap,
(idx) => !!this._bagSession?.merge.map.hasTile(idx), (idx) => !!this._bagSession?.merge.map.hasTile(idx),
this._textGridLayer,
); );
} }
@ -349,6 +412,7 @@ export class CocosBagBoardView {
this._map, this._map,
(idx) => session.hasTile(idx), (idx) => session.hasTile(idx),
(node) => this._isNodeUnderMapCell(node), (node) => this._isNodeUnderMapCell(node),
this._textGridLayer,
); );
} }
@ -360,21 +424,14 @@ export class CocosBagBoardView {
if (!this._bagSession || !this._map || !grid?.isValid || !grid.node?.isValid) return; if (!this._bagSession || !this._map || !grid?.isValid || !grid.node?.isValid) return;
const tile = this._bagSession.merge.map.getTile(gridIndex); const tile = this._bagSession.merge.map.getTile(gridIndex);
if (!tile) return; if (!tile) return;
const parent = this._map.getMapGridByIndex(gridIndex)?.node; const occupant = this._mapGridOnCell(gridIndex);
if (!parent?.isValid) return;
const occupant = this._grids.findMapGridOnCell(parent);
if (occupant && occupant !== grid) { if (occupant && occupant !== grid) {
console.warn('[CocosBagBoardView] commitMap 格上真身与提交块不一致', gridIndex, occupant.weapon2Id, grid.weapon2Id); console.warn('[CocosBagBoardView] commitMap 格上真身与提交块不一致', gridIndex, occupant.weapon2Id, grid.weapon2Id);
if (occupant.weapon2Id === tile.weapon2Id || grid.weapon2Id !== tile.weapon2Id) { if (occupant.weapon2Id === tile.weapon2Id || grid.weapon2Id !== tile.weapon2Id) {
grid = occupant; grid = occupant;
} }
} }
if (grid.node.parent !== parent) { if (!this._placeMapTextGrid(grid, gridIndex)) return;
if (occupant && occupant !== grid) return;
grid.node.parent = parent;
}
// 无论是否换父节点都归零,避免落下/拖拽残留本地偏移
grid.node.setPosition(0, 0, 0);
const entity = this._buildMapTileEntity(gridIndex); const entity = this._buildMapTileEntity(gridIndex);
if (!entity) return; if (!entity) return;
if (!this._isGridBoundTo(grid, entity)) { if (!this._isGridBoundTo(grid, entity)) {
@ -386,7 +443,6 @@ export class CocosBagBoardView {
this._grids.setMapGrid(gridIndex, grid); this._grids.setMapGrid(gridIndex, grid);
grid.enableDrag(this._canDrag()); grid.enableDrag(this._canDrag());
this._bindDrag(grid); this._bindDrag(grid);
this._warnExtraTextGrids(parent, grid);
if (this._textDragDebugSeq > 0) { if (this._textDragDebugSeq > 0) {
BagTextDragDebugLog.snap(this._textDragDebugSeq, 'commitMap', grid, `map=${gridIndex}`); BagTextDragDebugLog.snap(this._textDragDebugSeq, 'commitMap', grid, `map=${gridIndex}`);
} }
@ -437,8 +493,7 @@ export class CocosBagBoardView {
swap?: { grid: TextGrid; target: DropTarget } | null, swap?: { grid: TextGrid; target: DropTarget } | null,
): void { ): void {
if (target.kind === 'map') { if (target.kind === 'map') {
const parent = this._map?.getMapGridByIndex(target.gridIndex)?.node; this._commitMapTextGridView(target.gridIndex, swap ? grid : this._keeperAfterMapDrop(grid, target.gridIndex));
this._commitMapTextGridView(target.gridIndex, swap ? grid : this._keeperAfterDrop(grid, parent));
} else { } else {
const slotNode = this._bagSlotNodeAt(target.slotIndex); const slotNode = this._bagSlotNodeAt(target.slotIndex);
const incoming = swap && grid.weapon2Id !== 0 ? grid : this._keeperAfterDrop(grid, slotNode); const incoming = swap && grid.weapon2Id !== 0 ? grid : this._keeperAfterDrop(grid, slotNode);
@ -454,6 +509,23 @@ export class CocosBagBoardView {
this._dropSyncPhase = 'patchReady'; this._dropSyncPhase = 'patchReady';
} }
/**
* 地图落子:飞来的块 vs 专用层上已有真身。
* @param incoming 飞来的字块
* @param gridIndex 落点格
*/
private _keeperAfterMapDrop(incoming: TextGrid, gridIndex: number): TextGrid {
if (!incoming?.isValid) return incoming;
const other = this._mapGridOnCell(gridIndex);
if (!other?.isValid || other === incoming) return incoming;
if (this._isKeepDigTextGrid(incoming) && this._isKeepDigTextGrid(other)) {
this._forceRecycleTextGrid(other);
return incoming;
}
this._forceRecycleTextGrid(incoming);
return other;
}
/** /**
* 空格/交换:飞来的块就是真身。 * 空格/交换:飞来的块就是真身。
* 合成:格上已有块才是真身,飞来的是材料,回池。 * 合成:格上已有块才是真身,飞来的是材料,回池。
@ -480,23 +552,22 @@ export class CocosBagBoardView {
private _ensureMapTileView(gridIndex: number): void { private _ensureMapTileView(gridIndex: number): void {
if (!this._bagSession || !this._map) return; if (!this._bagSession || !this._map) return;
if (!this._bagSession.merge.map.getTile(gridIndex)) return; if (!this._bagSession.merge.map.getTile(gridIndex)) return;
const parent = this._map.getMapGridByIndex(gridIndex)?.node; const onCell = this._mapGridOnCell(gridIndex);
const onCell = parent?.isValid ? this._grids.findMapGridOnCell(parent) : null;
if (!onCell && (this._findFlightGridForMap(gridIndex) || this._mapDropAnimInflight > 0)) { if (!onCell && (this._findFlightGridForMap(gridIndex) || this._mapDropAnimInflight > 0)) {
return; return;
} }
const entity = this._buildMapTileEntity(gridIndex); const entity = this._buildMapTileEntity(gridIndex);
if (!entity) return; if (!entity) return;
if (onCell?.isValid) { if (onCell?.isValid) {
if (parent?.isValid && onCell.node.parent === parent && this._isGridBoundTo(onCell, entity)) { if (this._isGridBoundTo(onCell, entity)) {
this._placeMapTextGrid(onCell, gridIndex);
this._grids.setMapGrid(gridIndex, onCell); this._grids.setMapGrid(gridIndex, onCell);
return; return;
} }
this._commitMapTextGridView(gridIndex, onCell); this._commitMapTextGridView(gridIndex, onCell);
return; return;
} }
if (!parent?.isValid) return; const spawned = this._spawnTextGrid(entity, this._mapTextLayer() ?? this._map.getMapGridByIndex(gridIndex)?.node ?? this._mapRoot!, this._canDrag());
const spawned = this._spawnTextGrid(entity, parent, this._canDrag());
if (spawned) this._commitMapTextGridView(gridIndex, spawned); if (spawned) this._commitMapTextGridView(gridIndex, spawned);
} }
@ -504,17 +575,19 @@ export class CocosBagBoardView {
private _repairMapTileViewAfterDrop(gridIndex: number): void { private _repairMapTileViewAfterDrop(gridIndex: number): void {
if (!this._bagSession || !this._map) return; if (!this._bagSession || !this._map) return;
if (!this._bagSession.merge.map.hasTile(gridIndex)) return; if (!this._bagSession.merge.map.hasTile(gridIndex)) return;
const parent = this._map.getMapGridByIndex(gridIndex)?.node;
if (!parent?.isValid) return;
const entity = this._buildMapTileEntity(gridIndex); const entity = this._buildMapTileEntity(gridIndex);
if (!entity) return; if (!entity) return;
let onCell = this._grids.findMapGridOnCell(parent); let onCell = this._mapGridOnCell(gridIndex);
if (!onCell?.isValid) { if (!onCell?.isValid) {
const parent = this._mapTextLayer() ?? this._map.getMapGridByIndex(gridIndex)?.node;
if (!parent?.isValid) return;
onCell = this._spawnTextGrid(entity, parent, this._canDrag()); onCell = this._spawnTextGrid(entity, parent, this._canDrag());
} }
if (!onCell?.isValid) return; if (!onCell?.isValid) return;
this._commitMapTextGridView(gridIndex, onCell); this._commitMapTextGridView(gridIndex, onCell);
onCell.ensureBagGlyphVisible(); onCell.ensureBagGlyphVisible();
this._placeMapTextGrid(onCell, gridIndex);
onCell.rememberOrigin();
onCell.enableDrag(this._canDrag()); onCell.enableDrag(this._canDrag());
this._bindDrag(onCell); this._bindDrag(onCell);
} }
@ -894,17 +967,18 @@ export class CocosBagBoardView {
* @param force 损毁等强制清;默认跳过飞行中的字块 * @param force 损毁等强制清;默认跳过飞行中的字块
*/ */
private _vacateMapCellView(gridIndex: number, force = false): void { private _vacateMapCellView(gridIndex: number, force = false): void {
const parent = this._map?.getMapGridByIndex(gridIndex)?.node; const tracked = this._mapGrids.get(gridIndex);
if (!force && this._mapCellHasProtectedTextGrid(parent)) return; if (!force && tracked && this._grids.flightGrids.indexOf(tracked) >= 0) return;
this._grids.deleteMapCell(gridIndex); this._grids.deleteMapCell(gridIndex);
HeroActorHost.instance.destroyAtGrid(gridIndex); HeroActorHost.instance.destroyAtGrid(gridIndex);
if (!parent?.isValid) return; const recycle = (tg: TextGrid) => {
for (const child of [...parent.children]) { if (!tg?.isValid) return;
const tg = child.getComponent(TextGrid); if (!force && this._grids.flightGrids.indexOf(tg) >= 0) return;
if (!tg?.isValid) continue;
if (!force && this._grids.flightGrids.indexOf(tg) >= 0) continue;
this._forceRecycleTextGrid(tg); this._forceRecycleTextGrid(tg);
} };
if (tracked) recycle(tracked);
const onCell = this._mapGridOnCell(gridIndex);
if (onCell && onCell !== tracked) recycle(onCell);
} }
/** 格上是否有飞行中的字块 */ /** 格上是否有飞行中的字块 */
@ -1182,6 +1256,7 @@ export class CocosBagBoardView {
dragLayer?: Node, dragLayer?: Node,
lineNode?: Node, lineNode?: Node,
rangeNode?: Node, rangeNode?: Node,
textGridLayer?: Node,
pathFlow?: PathFlowLinePresenter | null, pathFlow?: PathFlowLinePresenter | null,
): void { ): void {
this.unbind(); this.unbind();
@ -1190,6 +1265,7 @@ export class CocosBagBoardView {
this._bagList = bagList; this._bagList = bagList;
this._land.bind(battle.LevelConfigId, bagList); this._land.bind(battle.LevelConfigId, bagList);
this._mapRoot = mapRoot; this._mapRoot = mapRoot;
this._textGridLayer = textGridLayer?.isValid ? textGridLayer : null;
this._dragLayer = dragLayer ?? mapRoot; this._dragLayer = dragLayer ?? mapRoot;
if (this._dragLayer?.isValid) { if (this._dragLayer?.isValid) {
this._dragLayer.active = true; this._dragLayer.active = true;
@ -1399,6 +1475,7 @@ export class CocosBagBoardView {
console.log('[CocosBagBoardView] _clearAllGrids failed', String(e)); console.log('[CocosBagBoardView] _clearAllGrids failed', String(e));
} }
this._map = null; this._map = null;
this._textGridLayer = null;
} }
refreshBag(): void { refreshBag(): void {
@ -1643,7 +1720,7 @@ export class CocosBagBoardView {
/** 妙手神偷落点挂接父节点 */ /** 妙手神偷落点挂接父节点 */
getStealReceiveAttachParent(placement: StealGlyphReceivePlacement): Node | null { getStealReceiveAttachParent(placement: StealGlyphReceivePlacement): Node | null {
if (placement.kind === 'map') { if (placement.kind === 'map') {
return this._map?.getMapGridByIndex(placement.gridIndex)?.node ?? null; return this._mapPlaceAttach(placement.gridIndex).attachParent;
} }
return this._bagSlotNodeAt(placement.slotIndex) ?? null; return this._bagSlotNodeAt(placement.slotIndex) ?? null;
} }
@ -1688,28 +1765,26 @@ export class CocosBagBoardView {
/** 清理敌方被偷格上的残留字块(HeroActor 由 DeploySync 对账移除) */ /** 清理敌方被偷格上的残留字块(HeroActor 由 DeploySync 对账移除) */
purgeEnemyStealSourceCell(gridIndex: number, keepGrid: TextGrid | null): void { purgeEnemyStealSourceCell(gridIndex: number, keepGrid: TextGrid | null): void {
const mg = this._map?.getMapGridByIndex(gridIndex); const mg = this._map?.getMapGridByIndex(gridIndex);
const parent = mg?.node; if (mg) {
if (!parent?.isValid) return; mg.isSelectStatus = false;
mg.isSelectStatus = false; mg.isRedSelectStatus = false;
mg.isRedSelectStatus = false; }
for (const child of parent.children.slice()) { const live = this._mapGridOnCell(gridIndex);
if (!child?.isValid) continue; if (live?.isValid && live !== keepGrid) this._forceRecycleTextGrid(live);
const tg = child.getComponent(TextGrid); let enemy: TextGrid | null = null;
if (!tg?.isValid) continue; this.forEachEnemyMapTextGrid((g, idx) => {
if (keepGrid && tg === keepGrid) continue; if (idx === gridIndex) enemy = g;
this._forceRecycleTextGrid(tg); });
} if (enemy?.isValid && enemy !== keepGrid) this._forceRecycleTextGrid(enemy);
} }
/** 读取敌方地图字块视图(不摘除托管) */ /** 读取敌方地图字块视图(不摘除托管) */
getEnemyMapTextGrid(gridIndex: number): TextGrid | null { getEnemyMapTextGrid(gridIndex: number): TextGrid | null {
const parent = this._map?.getMapGridByIndex(gridIndex)?.node; let found: TextGrid | null = null;
if (!parent?.isValid) return null; this.forEachEnemyMapTextGrid((g, idx) => {
for (const child of parent.children) { if (idx === gridIndex) found = g;
const tg = child.getComponent(TextGrid); });
if (tg?.isValid) return tg; return found;
}
return null;
} }
/** /**
@ -1770,11 +1845,7 @@ export class CocosBagBoardView {
/** 读取本机地图字块视图(不摘除) */ /** 读取本机地图字块视图(不摘除) */
getOwnMapTextGrid(gridIndex: number): TextGrid | null { getOwnMapTextGrid(gridIndex: number): TextGrid | null {
const tracked = this._mapGrids.get(gridIndex); return this._mapGridOnCell(gridIndex);
if (tracked?.isValid && tracked.node?.isValid) return tracked;
const parent = this._map?.getMapGridByIndex(gridIndex)?.node;
if (!parent?.isValid) return null;
return this._grids.findMapGridOnCell(parent) ?? null;
} }
/** /**
@ -1844,7 +1915,7 @@ export class CocosBagBoardView {
/** AI 妙手神偷落点挂接父节点;背包无视图则 null */ /** AI 妙手神偷落点挂接父节点;背包无视图则 null */
getAiStealReceiveAttachParent(placement: StealGlyphReceivePlacement): Node | null { getAiStealReceiveAttachParent(placement: StealGlyphReceivePlacement): Node | null {
if (placement.kind === 'map') { if (placement.kind === 'map') {
return this._map?.getMapGridByIndex(placement.gridIndex)?.node ?? null; return this._mapPlaceAttach(placement.gridIndex).attachParent;
} }
return null; return null;
} }
@ -2967,10 +3038,13 @@ export class CocosBagBoardView {
parent: Node, parent: Node,
enableDragNow = true, enableDragNow = true,
): TextGrid | null { ): TextGrid | null {
if (parent !== this._dragLayer) { const mapIndex = entity.location.kind === 'map' ? entity.location.gridIndex : -1;
const occupant = this._grids.findMapGridOnCell(parent); const layer = mapIndex >= 0 ? this._mapTextLayer() : null;
const spawnParent = layer ?? parent;
if (spawnParent !== this._dragLayer && spawnParent !== layer) {
const occupant = this._grids.findMapGridOnCell(spawnParent);
if (occupant?.isValid) { if (occupant?.isValid) {
console.warn('[CocosBagBoardView] spawn 拒绝:父节点已有 TextGrid', parent.name, occupant.weapon2Id); console.warn('[CocosBagBoardView] spawn 拒绝:父节点已有 TextGrid', spawnParent.name, occupant.weapon2Id);
return occupant; return occupant;
} }
} }
@ -2990,11 +3064,12 @@ export class CocosBagBoardView {
node.active = true; node.active = true;
node.name = 'textGrid'; node.name = 'textGrid';
node.parent = parent; node.parent = spawnParent;
node.setPosition(0, 0, 0); node.setPosition(0, 0, 0);
const comp = node.getComponent(TextGrid) ?? node.addComponent(TextGrid); const comp = node.getComponent(TextGrid) ?? node.addComponent(TextGrid);
this._writeGridData(comp, entity); this._writeGridData(comp, entity);
if (mapIndex >= 0) this._placeMapTextGrid(comp, mapIndex);
comp.rememberOrigin(); comp.rememberOrigin();
const dragOn = entity.location.kind === 'bag' const dragOn = entity.location.kind === 'bag'
? this._canEnableBagGridDrag(comp) ? this._canEnableBagGridDrag(comp)
@ -3057,18 +3132,19 @@ export class CocosBagBoardView {
else node.destroy(); else node.destroy();
} }
/** rebuild 后只对账索引;同格多块只 warn,不猜该留哪块 */ /** rebuild 后扫描专用层:无 tile 的地图字只 warn */
private _purgeOrphanTextGridsOnMap(): void { private _purgeOrphanTextGridsOnMap(): void {
const grids = this._map?.mapGrids; const layer = this._mapTextLayer();
if (!grids?.length) return; if (!layer?.isValid) return;
for (let i = 0; i < grids.length; i++) { const children = layer.children;
if (this._isEnemyPlaceCampCell(i)) continue; for (let i = 0; i < children.length; i++) {
const parent = grids[i]?.node; const tg = children[i].getComponent(TextGrid);
if (!parent?.isValid) continue; if (!tg?.isValid) continue;
const kept = this._mapGrids.get(i); const loc = tg.location;
if (kept?.isValid && kept.node.parent === parent) { if (loc?.kind !== 'map') continue;
this._warnExtraTextGrids(parent, kept); if (this._isEnemyPlaceCampCell(loc.gridIndex)) continue;
} if (this._mapGrids.get(loc.gridIndex) === tg) continue;
console.warn('[CocosBagBoardView] 专用层出现未索引地图字', loc.gridIndex, tg.weapon2Id);
} }
} }
@ -3557,7 +3633,8 @@ export class CocosBagBoardView {
primaryLeg: { primaryLeg: {
grid, grid,
targetWorld, targetWorld,
attachParent: swapToBag || !displacedGrid?.node?.isValid ? mapGrid.node : undefined, attachParent: swapToBag || !displacedGrid?.node?.isValid ? this._mapPlaceAttach(mapIndex).attachParent : undefined,
restWorld: swapToBag || !displacedGrid?.node?.isValid ? this._mapPlaceAttach(mapIndex).restWorld : undefined,
vacateFrom: { kind: 'bag', slotIndex }, vacateFrom: { kind: 'bag', slotIndex },
startWorld: placeStartWorld, startWorld: placeStartWorld,
}, },
@ -3706,7 +3783,8 @@ export class CocosBagBoardView {
? { ? {
grid: displacedGrid!, grid: displacedGrid!,
targetWorld: sourceMapGrid.node.worldPosition, targetWorld: sourceMapGrid.node.worldPosition,
attachParent: sourceMapGrid.node, attachParent: this._mapPlaceAttach(fromMapIndex).attachParent,
restWorld: this._mapPlaceAttach(fromMapIndex).restWorld,
vacateFrom: { kind: 'bag', slotIndex: toSlot }, vacateFrom: { kind: 'bag', slotIndex: toSlot },
startWorld: displacedStartWorld, startWorld: displacedStartWorld,
} }
@ -3790,7 +3868,8 @@ export class CocosBagBoardView {
primaryLeg: { primaryLeg: {
grid, grid,
targetWorld, targetWorld,
attachParent: swapMap || !displacedGrid?.node?.isValid ? mapGrid.node : undefined, attachParent: swapMap || !displacedGrid?.node?.isValid ? this._mapPlaceAttach(toMapIndex).attachParent : undefined,
restWorld: swapMap || !displacedGrid?.node?.isValid ? this._mapPlaceAttach(toMapIndex).restWorld : undefined,
vacateFrom: { kind: 'map', gridIndex: fromMapIndex }, vacateFrom: { kind: 'map', gridIndex: fromMapIndex },
startWorld: placeStartWorld, startWorld: placeStartWorld,
}, },
@ -3798,7 +3877,8 @@ export class CocosBagBoardView {
? { ? {
grid: displacedGrid!, grid: displacedGrid!,
targetWorld: sourceWorld, targetWorld: sourceWorld,
attachParent: sourceMapGrid.node, attachParent: this._mapPlaceAttach(fromMapIndex).attachParent,
restWorld: this._mapPlaceAttach(fromMapIndex).restWorld,
vacateFrom: { kind: 'map', gridIndex: toMapIndex }, vacateFrom: { kind: 'map', gridIndex: toMapIndex },
startWorld: displacedStartWorld, startWorld: displacedStartWorld,
} }
@ -4020,7 +4100,7 @@ export class CocosBagBoardView {
: { kind: 'map', gridIndex: drag.mapDrag?.fromGridIndex ?? drag.source.gridIndex }; : { kind: 'map', gridIndex: drag.mapDrag?.fromGridIndex ?? drag.source.gridIndex };
const home = from.kind === 'bag' const home = from.kind === 'bag'
? this._bagSlotNodeAt(from.slotIndex) ? this._bagSlotNodeAt(from.slotIndex)
: this._map?.getMapGridByIndex(from.gridIndex)?.node ?? null; : this._mapPlaceAttach(from.gridIndex).attachParent;
const startWorld = grid.node.worldPosition.clone(); const startWorld = grid.node.worldPosition.clone();
this._mapDropAnimInflight++; this._mapDropAnimInflight++;
this._detachGridForFlight(grid, from); this._detachGridForFlight(grid, from);
@ -4031,9 +4111,11 @@ export class CocosBagBoardView {
if (!this._discardGlyphData(drag)) { if (!this._discardGlyphData(drag)) {
if (this._mapDropAnimInflight > 0) this._mapDropAnimInflight--; if (this._mapDropAnimInflight > 0) this._mapDropAnimInflight--;
this._grids.removeFromFlight(grid); this._grids.removeFromFlight(grid);
if (home?.isValid) { if (from.kind === 'bag' && home?.isValid) {
grid.node.parent = home; grid.node.parent = home;
grid.node.setPosition(0, 0, 0); grid.node.setPosition(0, 0, 0);
} else if (from.kind === 'map') {
this._placeMapTextGrid(grid, from.gridIndex);
} }
this._lineDragCancel(grid, drag); this._lineDragCancel(grid, drag);
return; return;
@ -4771,16 +4853,14 @@ if (weapon2Id === GRID_WEAPON2_ID) return true;
const weapon2Id = Number(entity.tile.id); const weapon2Id = Number(entity.tile.id);
const level = entity.level; const level = entity.level;
const cellParent = mapGrid.node; const cellParent = mapGrid.node;
const onCell = this._grids.findMapGridOnCell(cellParent); const mapParent = this._mapTextLayer() ?? cellParent;
const onCell = this._mapGridOnCell(gridIndex);
let reuseCandidate: TextGrid | undefined; let reuseCandidate: TextGrid | undefined;
if (onCell && !usedTextGrids.has(onCell)) { if (onCell && !usedTextGrids.has(onCell)) {
reuseCandidate = this._rejectBagHostedGrid(onCell); reuseCandidate = this._rejectBagHostedGrid(onCell);
} }
if (!reuseCandidate) { if (!reuseCandidate) {
reuseCandidate = this._pickFlightTextGridOnParent( reuseCandidate = this._rejectBagHostedGrid(this._findFlightGridForMap(gridIndex, flightGrids) ?? undefined);
flightGrids, cellParent, weapon2Id, level, usedTextGrids,
);
reuseCandidate = this._rejectBagHostedGrid(reuseCandidate);
} }
const atCell = prevMap.get(gridIndex); const atCell = prevMap.get(gridIndex);
if ( if (
@ -4802,10 +4882,10 @@ if (weapon2Id === GRID_WEAPON2_ID) return true;
)); ));
} }
let grid: TextGrid | null = this._tryReuseTextGrid( let grid: TextGrid | null = this._tryReuseTextGrid(
reuseCandidate, entity, cellParent, flightGrids, usedTextGrids, reuseCandidate, entity, mapParent, flightGrids, usedTextGrids,
); );
if (!grid && !this._grids.findMapGridOnCell(cellParent) && !this._findFlightGridForMap(gridIndex, flightGrids)) { if (!grid && !this._mapGridOnCell(gridIndex) && !this._findFlightGridForMap(gridIndex, flightGrids)) {
grid = this._spawnTextGrid(entity, mapGrid.node); grid = this._spawnTextGrid(entity, mapParent);
} }
if (grid) { if (grid) {
this._mapGrids.set(gridIndex, grid); this._mapGrids.set(gridIndex, grid);
@ -4945,7 +5025,9 @@ if (weapon2Id === GRID_WEAPON2_ID) return true;
if (this._isNodeUnderBagList(existing.node) && !this._isNodeUnderBagList(parent)) { if (this._isNodeUnderBagList(existing.node) && !this._isNodeUnderBagList(parent)) {
return null; return null;
} }
const occupant = this._grids.findMapGridOnCell(parent); const occupant = parent === this._textGridLayer || parent === this._dragLayer
? null
: this._grids.findMapGridOnCell(parent);
if (occupant && occupant !== existing) { if (occupant && occupant !== existing) {
return null; return null;
} }
@ -4955,6 +5037,9 @@ if (weapon2Id === GRID_WEAPON2_ID) return true;
existing.node.parent = parent; existing.node.parent = parent;
existing.node.setPosition(0, 0, 0); existing.node.setPosition(0, 0, 0);
} }
if (entity.location.kind === 'map') {
this._placeMapTextGrid(existing, entity.location.gridIndex);
}
existing.node.active = true; existing.node.active = true;
const uo = existing.node.getComponent(UIOpacity); const uo = existing.node.getComponent(UIOpacity);
if (uo) uo.opacity = 255; if (uo) uo.opacity = 255;
@ -5160,8 +5245,8 @@ if (weapon2Id === GRID_WEAPON2_ID) return true;
if (!parent?.isValid) return null; if (!parent?.isValid) return null;
let grid = this._mapGrids.get(gridIndex) ?? null; let grid = this._mapGrids.get(gridIndex) ?? null;
if (!grid?.isValid || grid.node.parent !== parent) { if (!grid?.isValid) {
grid = this._grids.findMapGridOnCell(parent) ?? null; grid = this._mapGridOnCell(gridIndex);
} }
return grid?.isValid ? grid : null; return grid?.isValid ? grid : null;
} }
@ -6788,10 +6873,6 @@ if (weapon2Id === GRID_WEAPON2_ID) return true;
finish(false); finish(false);
return; return;
} }
if (flightGrid.node.parent !== mapGrid.node) {
flightGrid.node.parent = mapGrid.node;
flightGrid.node.setPosition(0, 0, 0);
}
this._commitMapTextGridView(gridIndex, flightGrid); this._commitMapTextGridView(gridIndex, flightGrid);
mapGrid.playFallEffect?.(); mapGrid.playFallEffect?.();
BattleAudio.playPlaceGrid(); BattleAudio.playPlaceGrid();
@ -6801,7 +6882,8 @@ if (weapon2Id === GRID_WEAPON2_ID) return true;
} }
finish(true); finish(true);
}, { }, {
attachParent: mapGrid.node, attachParent: this._mapPlaceAttach(gridIndex).attachParent,
restWorld: this._mapPlaceAttach(gridIndex).restWorld,
startWorld: opts.fromWorld, startWorld: opts.fromWorld,
showTrail: DeviceProfile.enableBoardPlaceTrail, showTrail: DeviceProfile.enableBoardPlaceTrail,
}); });
@ -6863,13 +6945,7 @@ if (weapon2Id === GRID_WEAPON2_ID) return true;
return true; return true;
} }
const mapGrid = this._map?.getMapGridByIndex(source.gridIndex); return this._placeMapTextGrid(grid, source.gridIndex);
if (!mapGrid?.node?.isValid) return false;
if (grid.node.parent !== mapGrid.node) {
grid.node.parent = mapGrid.node;
}
grid.node.setPosition(0, 0, 0);
return true;
} }
private _autoDropBagToMap( private _autoDropBagToMap(
@ -6917,7 +6993,8 @@ if (weapon2Id === GRID_WEAPON2_ID) return true;
primaryLeg: { primaryLeg: {
grid, grid,
targetWorld, targetWorld,
attachParent: swapToBag || !displacedGrid?.node?.isValid ? mapGrid.node : undefined, attachParent: swapToBag || !displacedGrid?.node?.isValid ? this._mapPlaceAttach(mapIndex).attachParent : undefined,
restWorld: swapToBag || !displacedGrid?.node?.isValid ? this._mapPlaceAttach(mapIndex).restWorld : undefined,
vacateFrom: { kind: 'bag', slotIndex }, vacateFrom: { kind: 'bag', slotIndex },
}, },
swapLeg: swapToBag && bagSlotNode && displacedStartWorld swapLeg: swapToBag && bagSlotNode && displacedStartWorld
@ -7046,14 +7123,16 @@ if (weapon2Id === GRID_WEAPON2_ID) return true;
primaryLeg: { primaryLeg: {
grid, grid,
targetWorld: mapGrid.node.worldPosition, targetWorld: mapGrid.node.worldPosition,
attachParent: swapMap || !displacedGrid?.node?.isValid ? mapGrid.node : undefined, attachParent: swapMap || !displacedGrid?.node?.isValid ? this._mapPlaceAttach(toMapIndex).attachParent : undefined,
restWorld: swapMap || !displacedGrid?.node?.isValid ? this._mapPlaceAttach(toMapIndex).restWorld : undefined,
vacateFrom: { kind: 'map', gridIndex: fromMapIndex }, vacateFrom: { kind: 'map', gridIndex: fromMapIndex },
}, },
swapLeg: swapMap && displacedStartWorld swapLeg: swapMap && displacedStartWorld
? { ? {
grid: displacedGrid!, grid: displacedGrid!,
targetWorld: sourceMapGrid.node.worldPosition, targetWorld: sourceMapGrid.node.worldPosition,
attachParent: sourceMapGrid.node, attachParent: this._mapPlaceAttach(fromMapIndex).attachParent,
restWorld: this._mapPlaceAttach(fromMapIndex).restWorld,
vacateFrom: { kind: 'map', gridIndex: toMapIndex }, vacateFrom: { kind: 'map', gridIndex: toMapIndex },
startWorld: displacedStartWorld, startWorld: displacedStartWorld,
} }

@ -1,6 +1,4 @@
import { import { instantiate, Node, Tween, tween, UIOpacity, UITransform, v3, Vec3 } from 'cc';
instantiate, Node, Tween, tween, UIOpacity, UITransform, v3, Vec3,
} from 'cc';
import { GBundle } from '../../game/ConfigRes'; import { GBundle } from '../../game/ConfigRes';
/** 沿弧线飞移速度(px/s) */ /** 沿弧线飞移速度(px/s) */
@ -140,28 +138,20 @@ export class PassiveIconArcFlight {
this._destroyHost(host); this._destroyHost(host);
} }
/** 从 textGrid 借 trail1 节点(instantiate 副本) */ /** 从对象池取 trail1 */
private static _borrowTrail1Node(): Node | null { private static _borrowTrail1Node(): Node | null {
let gridNode: Node | null = null; let node: Node | null = null;
try { try {
gridNode = gg.res.getNode('prefab/', 'textGrid', GBundle.BattleGame); node = gg.res.getNode('prefab/', 'trail1', GBundle.BattleGame);
} catch (e) { } catch (e) {
console.log('[PassiveIconArcFlight] textGrid 加载失败', String(e)); console.log('[PassiveIconArcFlight] trail1 加载失败', String(e));
return null; return null;
} }
if (!gridNode?.isValid) { if (!node?.isValid) {
console.log('[PassiveIconArcFlight] textGrid 缺失');
return null;
}
const trail = gridNode.getChildByName('trail1');
if (!trail?.isValid) {
gg.res.putNode(gridNode);
console.log('[PassiveIconArcFlight] trail1 缺失'); console.log('[PassiveIconArcFlight] trail1 缺失');
return null; return null;
} }
const trailClone = instantiate(trail); return node;
gg.res.putNode(gridNode);
return trailClone;
} }
/** 落地淡出后销毁 */ /** 落地淡出后销毁 */
@ -195,7 +185,8 @@ export class PassiveIconArcFlight {
if (!child?.isValid) continue; if (!child?.isValid) continue;
const opacity = child.getComponent(UIOpacity); const opacity = child.getComponent(UIOpacity);
if (opacity?.isValid) Tween.stopAllByTarget(opacity); if (opacity?.isValid) Tween.stopAllByTarget(opacity);
child.destroy(); if (child['resKey']) gg.res.putNode(child);
else child.destroy();
} }
host.destroy(); host.destroy();
} }

@ -1,9 +1,10 @@
import { _decorator, BlockInputEvents, Component, isValid, Node, Sorting2D, sp, Tween, tween, UIOpacity, UITransform, v3, Vec2, Vec3, type EventTouch } from 'cc'; import { _decorator, BlockInputEvents, Component, isValid, Node, Prefab, Sorting2D, sp, Tween, tween, UIOpacity, UITransform, v3, Vec2, Vec3, type EventTouch } from 'cc';
import type { EntityId } from 'db://assets/mx/module/ecs'; import type { EntityId } from 'db://assets/mx/module/ecs';
import type { ComposedUnit } from 'db://assets/mx/module/merge'; import type { ComposedUnit } from 'db://assets/mx/module/merge';
import { isElementGlyphType, Weapon2TileType } from 'db://assets/mx/module/merge'; import { isElementGlyphType, Weapon2TileType } from 'db://assets/mx/module/merge';
import { GEvent } from 'db://assets/mx/module/event/GEvent'; import { GEvent } from 'db://assets/mx/module/event/GEvent';
import { GBundle, GPath } from '../../game/ConfigRes'; import { GBundle, GPath } from '../../game/ConfigRes';
import { BATTLE_HERO_NUM_PATH } from '../res/BattleHeroResCollector';
import { TableNames } from '../../game/ConfigTableData'; import { TableNames } from '../../game/ConfigTableData';
import { BattleMapSpec } from '../map/BattleMapSpec'; import { BattleMapSpec } from '../map/BattleMapSpec';
import { PEACH_TREE_WEAPON2_ID } from '../bag/BagPrepConfig'; import { PEACH_TREE_WEAPON2_ID } from '../bag/BagPrepConfig';
@ -117,7 +118,7 @@ export interface TextGridData extends TileEntitySnapshot {
/** /**
* 背包/地图字块视图(textGrid 预制体)。 * 背包/地图字块视图(textGrid 预制体)。
* 五行字:按 Hero(herotype=Text.type, level=当前显示等级).number 打开同名节点,并切金/木/水/火/土皮。 * 五行字:按 Hero.number 从 battleHero/prefab/num 出池,挂到 skin,并切金/木/水/火/土皮。
* 地图激活后按当前 Hero.herotype 挂 weaponType*。 * 地图激活后按当前 Hero.herotype 挂 weaponType*。
*/ */
@ccclass('TextGrid') @ccclass('TextGrid')
@ -137,7 +138,7 @@ export class TextGrid extends Component {
private _dragSurface: Node | null = null; private _dragSurface: Node | null = null;
private _originParent: Node | null = null; private _originParent: Node | null = null;
private _originPos = { x: 0, y: 0, z: 0 }; private _originPos = { x: 0, y: 0, z: 0 };
/** 当前五行数字皮节点(子节点名 = Hero.number) */ /** 当前五行数字皮节点(battleHero/prefab/num,挂在 skin 下) */
private _numberNode: Node | null = null; private _numberNode: Node | null = null;
/** 当前数字节点已套的五行皮名(金/木/水/火/土) */ /** 当前数字节点已套的五行皮名(金/木/水/火/土) */
private _elementSkinApplied = ''; private _elementSkinApplied = '';
@ -160,10 +161,16 @@ export class TextGrid extends Component {
private _ruinFallNode: Node | null = null; private _ruinFallNode: Node | null = null;
/** ebg 未旋转时的局部坐标 */ /** ebg 未旋转时的局部坐标 */
private readonly _decorRest: RuinDecorRest[] = []; private readonly _decorRest: RuinDecorRest[] = [];
/** 可升级提示箭头(预制体默认隐藏) */ /** 可升级提示箭头(battleGame/prefab/canUpEff,按需出池) */
private _canUpEff: Node | null = null; private _canUpEff: Node | null = null;
private _canUpEffBaseX = 0; private _canUpEffBaseX = 0;
private _canUpEffBaseY = 0; private _canUpEffBaseY = 0;
/** 入场拖尾 trail1(按需出池) */
private _trail1: Node | null = null;
/** 入场拖尾 trail2(按需出池) */
private _trail2: Node | null = null;
/** 入场拖尾 trail3(按需出池) */
private _trail3: Node | null = null;
/** 拖动时可合成目标:每秒抖动一次 */ /** 拖动时可合成目标:每秒抖动一次 */
private _mergeShakeOn = false; private _mergeShakeOn = false;
private _mergeShakeBase = { x: 0, y: 0, z: 0 }; private _mergeShakeBase = { x: 0, y: 0, z: 0 };
@ -193,29 +200,6 @@ export class TextGrid extends Component {
this.selectNode = this.node.getChildByName('select'); this.selectNode = this.node.getChildByName('select');
this.redSelectNode = this.node.getChildByName('redSelect'); this.redSelectNode = this.node.getChildByName('redSelect');
this._updateSelect(); this._updateSelect();
this._canUpEff = this.node.getChildByName('canUpEff');
if (this._canUpEff?.isValid) {
this._canUpEffBaseX = this._canUpEff.position.x;
this._canUpEffBaseY = this._canUpEff.position.y;
this._canUpEff.active = false;
}
this._disableBrokenNumberSkeletons();
}
/**
* 数字节点 Spine 资源缺失时关掉组件,避免 SkeletonSystem wasm 崩。
*/
private _disableBrokenNumberSkeletons(): void {
const children = this.node.children;
for (let i = 0; i < children.length; i++) {
const child = children[i];
if (!child?.isValid || !this._isNumberFaceName(child.name)) continue;
const sk = child.getComponent(sp.Skeleton);
if (!sk?.isValid) continue;
if (sk.skeletonData?.isValid) continue;
sk.enabled = false;
console.error('[TextGrid] 数字 Spine 资源缺失,已禁用', child.name);
}
} }
/** /**
@ -506,28 +490,26 @@ export class TextGrid extends Component {
} }
/** /**
* 可合成/可升级提示:显示时上下浮动待机;隐藏时停动画并复位。 * 可合成/可升级提示:显示时出池并上下浮动;隐藏时回池。
* 蟠桃树不可合成,强制不显示。 * 蟠桃树不可合成,强制不显示。
*/ */
setCanUpgradeHint(visible: boolean): void { setCanUpgradeHint(visible: boolean): void {
const n = this._canUpEff;
if (!n?.isValid) return;
Tween.stopAllByTarget(n);
if (!visible || this.isPeachTreeTile()) { if (!visible || this.isPeachTreeTile()) {
n.active = false; this._releaseCanUpEff();
n.setPosition(this._canUpEffBaseX, this._canUpEffBaseY, n.position.z);
return; return;
} }
const n = this._ensureCanUpEff();
if (!n) return;
Tween.stopAllByTarget(n);
n.active = true; n.active = true;
const x = this._canUpEffBaseX; const x = this._canUpEffBaseX;
const y = this._canUpEffBaseY; const y = this._canUpEffBaseY;
const z = n.position.z; n.setPosition(x, y, 0);
n.setPosition(x, y, z);
tween(n) tween(n)
.repeatForever( .repeatForever(
tween(n) tween(n)
.to(0.45, { position: v3(x, y + 10, z) }, { easing: 'sineInOut' }) .to(0.45, { position: v3(x, y + 10, 0) }, { easing: 'sineInOut' })
.to(0.45, { position: v3(x, y, z) }, { easing: 'sineInOut' }), .to(0.45, { position: v3(x, y, 0) }, { easing: 'sineInOut' }),
) )
.start(); .start();
} }
@ -741,6 +723,7 @@ export class TextGrid extends Component {
* 拖动/交换落地后恢复字形可见。 * 拖动/交换落地后恢复字形可见。
* putNode 会把子树 Skeleton.enabled 关掉;地图原先跳过,交换后只剩 ebg 阴影和 lv。 * putNode 会把子树 Skeleton.enabled 关掉;地图原先跳过,交换后只剩 ebg 阴影和 lv。
* 已成将格只对账藏/显皮,不把格子皮强行打开(避免叠在 heroTemplate 上)。 * 已成将格只对账藏/显皮,不把格子皮强行打开(避免叠在 heroTemplate 上)。
* 根节点回到 rememberOrigin 位置(地图字在专用层上本地非 0)。
* @returns 是否曾发现异常并修复 * @returns 是否曾发现异常并修复
*/ */
ensureBagGlyphVisible(): boolean { ensureBagGlyphVisible(): boolean {
@ -757,8 +740,8 @@ export class TextGrid extends Component {
repaired = true; repaired = true;
} }
this.node.setScale(1, 1, 1); this.node.setScale(1, 1, 1);
this.node.setPosition(0, 0, 0); // 地图字挂 ui_textGrids 时本地非 (0,0);归零会把字形和武器甩到层原点
this.resetNodeTransform(); this.restoreOrigin();
this.resetSkinPresentation(); this.resetSkinPresentation();
if (this._isElementNumberTile()) { if (this._isElementNumberTile()) {
@ -892,13 +875,13 @@ export class TextGrid extends Component {
this.clearSleepFx(); this.clearSleepFx();
this.clearConfusionFx(); this.clearConfusionFx();
this.clearAttachedBattleBuffFx(); this.clearAttachedBattleBuffFx();
if (this._canUpEff?.isValid) { this._releaseCanUpEff();
Tween.stopAllByTarget(this._canUpEff); this._releaseTrails();
}
if (this._mergeShakeOn) { if (this._mergeShakeOn) {
this.setMergeTargetShake(false); this.setMergeTargetShake(false);
} }
this.resetSkinPresentation(); this.resetSkinPresentation();
this._hideNumberNodes();
if (this._dragSurface?.isValid) { if (this._dragSurface?.isValid) {
this._dragSurface.removeDragEvent?.(); this._dragSurface.removeDragEvent?.();
this._dragSurface.destroy(); this._dragSurface.destroy();
@ -1379,7 +1362,7 @@ export class TextGrid extends Component {
} }
/** /**
* 出字入场拖尾:普通字 trail1、金色组合字 trail2。 * 出字入场拖尾:普通字 / 五行字用 trail1。
* 仅入场飞行时打开,落地后须 hideEntranceTrail。 * 仅入场飞行时打开,落地后须 hideEntranceTrail。
*/ */
showEntranceTrail(): void { showEntranceTrail(): void {
@ -1389,24 +1372,131 @@ export class TextGrid extends Component {
} }
hideEntranceTrail(): void { hideEntranceTrail(): void {
if (!this.isValid || !this.node?.isValid) return; this._releaseTrails();
const trail1 = this.node.getChildByName('trail1');
const trail2 = this.node.getChildByName('trail2');
const trail3 = this.node.getChildByName('trail3');
if (trail1?.isValid) trail1.active = false;
if (trail2?.isValid) trail2.active = false;
if (trail3?.isValid) trail3.active = false;
} }
/** 入场拖尾:文字 trail1 */ /** 入场拖尾:文字 trail1 */
private _applyTrailByTileType(type: Weapon2TileType): void { private _applyTrailByTileType(type: Weapon2TileType): void {
const trail1 = this.node.getChildByName('trail1'); this._releaseTrails();
const trail2 = this.node.getChildByName('trail2');
const trail3 = this.node.getChildByName('trail3');
const use1 = type === Weapon2TileType.Single || isElementGlyphType(type); const use1 = type === Weapon2TileType.Single || isElementGlyphType(type);
if (trail1?.isValid) trail1.active = use1; if (!use1) return;
if (trail2?.isValid) trail2.active = false; const trail1 = this._ensureTrail(1);
if (trail3?.isValid) trail3.active = false; if (trail1) trail1.active = true;
}
/**
* 从 battleGame/prefab 出池并挂到字块根。
* @param name 预制体名
*/
private _takeGridDecor(name: string): Node | null {
let node: Node | null = null;
try {
node = gg.res.getNode(GPath.Prefab, name, GBundle.BattleGame);
} catch (e) {
console.error('[TextGrid] 装饰预制体加载失败', name, String(e));
return null;
}
if (!node?.isValid) {
console.error('[TextGrid] 装饰预制体缺失', name);
return null;
}
node.parent = this.node;
node.layer = this.node.layer;
this._forwardChildTouchToSurface();
this._ensureDragSurface();
return node;
}
/** 装饰节点回池 */
private _putGridDecor(node: Node | null): void {
if (!node?.isValid) return;
Tween.stopAllByTarget(node);
if (node['resKey']) gg.res.putNode(node);
else node.destroy();
}
/** 可升级箭头出池 */
private _ensureCanUpEff(): Node | null {
if (this._canUpEff?.isValid) return this._canUpEff;
const node = this._takeGridDecor('canUpEff');
if (!node) return null;
this._applyCanUpEffPrefabPose(node);
this._canUpEff = node;
return node;
}
/** 按预制体记录箭头局部坐标(getNode 会清零 position) */
private _applyCanUpEffPrefabPose(node: Node): void {
const prefab = gg.res.getRes('canUpEff', GPath.Prefab, GBundle.BattleGame, Prefab) as Prefab | null;
const data = prefab?.data;
if (!data?.isValid) {
console.error('[TextGrid] canUpEff 预制体位姿读不到');
this._canUpEffBaseX = 0;
this._canUpEffBaseY = 0;
return;
}
this._canUpEffBaseX = data.position.x;
this._canUpEffBaseY = data.position.y;
node.setPosition(this._canUpEffBaseX, this._canUpEffBaseY, 0);
}
/** 可升级箭头回池 */
private _releaseCanUpEff(): void {
const n = this._canUpEff;
this._canUpEff = null;
this._putGridDecor(n);
const leftover = this.node?.getChildByName('canUpEff');
if (leftover?.isValid && leftover !== n) this._putGridDecor(leftover);
}
/**
* 入场拖尾出池。
* @param index 1/2/3
*/
private _ensureTrail(index: 1 | 2 | 3): Node | null {
const held = this._trailByIndex(index);
if (held?.isValid) return held;
const name = `trail${index}`;
const node = this._takeGridDecor(name);
if (!node) return null;
node.setPosition(0, 0, 0);
this._setTrailByIndex(index, node);
return node;
}
/**
* 当前持有的拖尾节点。
* @param index 1/2/3
*/
private _trailByIndex(index: 1 | 2 | 3): Node | null {
if (index === 1) return this._trail1;
if (index === 2) return this._trail2;
return this._trail3;
}
/**
* 记录拖尾节点。
* @param index 1/2/3
* @param node 拖尾节点
*/
private _setTrailByIndex(index: 1 | 2 | 3, node: Node | null): void {
if (index === 1) this._trail1 = node;
else if (index === 2) this._trail2 = node;
else this._trail3 = node;
}
/** 入场拖尾全部回池 */
private _releaseTrails(): void {
this._putGridDecor(this._trail1);
this._putGridDecor(this._trail2);
this._putGridDecor(this._trail3);
this._trail1 = null;
this._trail2 = null;
this._trail3 = null;
if (!this.node?.isValid) return;
this._putGridDecor(this.node.getChildByName('trail1'));
this._putGridDecor(this.node.getChildByName('trail2'));
this._putGridDecor(this.node.getChildByName('trail3'));
} }
/** /**
@ -1454,17 +1544,87 @@ export class TextGrid extends Component {
return null; return null;
} }
/** 关掉全部数字皮节点 */ /** 当前数字节点回池 */
private _hideNumberNodes(): void { private _putNumberNode(node: Node | null): void {
if (!this.node?.isValid) return; if (!node?.isValid) return;
const children = this.node.children; Tween.stopAllByTarget(node);
for (let i = 0; i < children.length; i++) { node.off(Node.EventType.TOUCH_START, this._relayTouchToDragSurface, this);
node.off(Node.EventType.TOUCH_MOVE, this._relayTouchToDragSurface, this);
node.off(Node.EventType.TOUCH_END, this._relayTouchToDragSurface, this);
node.off(Node.EventType.TOUCH_CANCEL, this._relayTouchToDragSurface, this);
if (node['resKey']) gg.res.putNode(node);
else node.destroy();
}
/**
* 从对象池取出数字预制体。
* @param num Hero.number
*/
private _takeNumberNode(num: number): Node | null {
const name = String(num);
let node: Node | null = null;
try {
node = gg.res.getNode(BATTLE_HERO_NUM_PATH, name, GBundle.BattleHero);
} catch (e) {
console.error('[TextGrid] 数字预制体加载失败', name, String(e));
return null;
}
if (!node?.isValid) {
console.error('[TextGrid] 数字预制体缺失', name);
return null;
}
return node;
}
/**
* 把数字预制体挂到 skin。
* @param node 出池节点
*/
private _attachNumberNode(node: Node): boolean {
this._ensureSkinNode();
const skin = this._skinNode;
if (!skin?.isValid) {
console.error('[TextGrid] skin 节点缺失,无法挂数字', node.name);
this._putNumberNode(node);
return false;
}
skin.active = true;
node.parent = skin;
node.layer = this.node.layer;
node.setPosition(0, 0, 0);
this._ensureNumberGlyphSorting(node);
this._forwardChildTouchToSurface();
return true;
}
/** 数字 Spine 与字形 Sorting2D 对齐 */
private _ensureNumberGlyphSorting(node: Node): void {
let sorting = node.getComponent(Sorting2D);
if (!sorting) sorting = node.addComponent(Sorting2D);
sorting.sortingLayer = TEXT_GRID_BUFF_FX_SORT_LAYER;
sorting.sortingOrder = TEXT_GRID_GLYPH_SORT_ORDER;
}
/** host 下残留数字节点回池 */
private _recycleNumberChildren(host: Node | null): void {
if (!host?.isValid) return;
const children = host.children;
for (let i = children.length - 1; i >= 0; i--) {
const child = children[i]; const child = children[i];
if (!child?.isValid || !this._isNumberFaceName(child.name)) continue; if (!child?.isValid || child === this._numberNode) continue;
child.active = false; if (!this._isNumberFaceName(child.name)) continue;
this._putNumberNode(child);
} }
}
/** 关掉当前数字皮并归还对象池 */
private _hideNumberNodes(): void {
const held = this._numberNode;
this._numberNode = null; this._numberNode = null;
this._elementSkinApplied = ''; this._elementSkinApplied = '';
this._putNumberNode(held);
this._recycleNumberChildren(this._skinNode);
this._recycleNumberChildren(this.node);
} }
/** 旧 skin 与当前数字皮一起显隐 */ /** 旧 skin 与当前数字皮一起显隐 */
@ -1478,7 +1638,7 @@ export class TextGrid extends Component {
} }
/** /**
* 打开 Hero.number 同名节点并切五行皮。 * 按 Hero.number 出池数字预制体并切五行皮。
* @param show 是否可见(成将盖住时仍选中节点但保持关闭) * @param show 是否可见(成将盖住时仍选中节点但保持关闭)
*/ */
private _applyNumberGlyph(show: boolean): void { private _applyNumberGlyph(show: boolean): void {
@ -1501,24 +1661,24 @@ export class TextGrid extends Component {
this._hideNumberNodes(); this._hideNumberNodes();
return; return;
} }
const node = this.node.getChildByName(String(num));
if (!node?.isValid || !this._isNumberFaceName(node.name)) {
console.log('[TextGrid] 数字节点缺失', num, 'hero=', hero.id);
this._hideNumberNodes();
return;
}
const skinName = this._elementSkinName(herotype); const skinName = this._elementSkinName(herotype);
if (!skinName) { if (!skinName) {
console.log('[TextGrid] 五行皮肤未定义', herotype, 'hero=', hero.id); console.log('[TextGrid] 五行皮肤未定义', herotype, 'hero=', hero.id);
this._hideNumberNodes(); this._hideNumberNodes();
return; return;
} }
if (this._numberNode === node && this._elementSkinApplied === skinName) { const faceName = String(num);
if (this._numberNode?.isValid && this._numberNode.name === faceName && this._elementSkinApplied === skinName) {
this._ensureSkinNode();
if (this._skinNode?.isValid) this._skinNode.active = true;
if (this._numberNode.active !== show) this._numberNode.active = show; if (this._numberNode.active !== show) this._numberNode.active = show;
this._syncElementVisualChannel(); this._syncElementVisualChannel();
return; return;
} }
this._hideNumberNodes(); this._hideNumberNodes();
const node = this._takeNumberNode(num);
if (!node) return;
if (!this._attachNumberNode(node)) return;
this._numberNode = node; this._numberNode = node;
node.active = true; node.active = true;
this._playElementSkin(node, skinName); this._playElementSkin(node, skinName);
@ -1631,23 +1791,44 @@ export class TextGrid extends Component {
return { width: cell, height: cell }; return { width: cell, height: cell };
} }
private _forwardChildTouchToSurface(): void { /** 子节点触摸转发给拖拽面 */
private _relayTouchToDragSurface(e: EventTouch): void {
const surface = this._dragSurface; const surface = this._dragSurface;
if (!surface) return; if (!surface?.isValid) return;
const relay = (e: EventTouch) => { e.preventSwallow = true;
e.preventSwallow = true; surface.emit(e.type, e);
surface.emit(e.type, e); }
};
for (const child of this.node.children) { /**
if (child === surface) continue; * 绑定触摸转发。
child.off(Node.EventType.TOUCH_START, relay, this); * @param node 子节点
child.off(Node.EventType.TOUCH_MOVE, relay, this); */
child.off(Node.EventType.TOUCH_END, relay, this); private _bindTouchRelay(node: Node): void {
child.off(Node.EventType.TOUCH_CANCEL, relay, this); node.off(Node.EventType.TOUCH_START, this._relayTouchToDragSurface, this);
child.on(Node.EventType.TOUCH_START, relay, this); node.off(Node.EventType.TOUCH_MOVE, this._relayTouchToDragSurface, this);
child.on(Node.EventType.TOUCH_MOVE, relay, this); node.off(Node.EventType.TOUCH_END, this._relayTouchToDragSurface, this);
child.on(Node.EventType.TOUCH_END, relay, this); node.off(Node.EventType.TOUCH_CANCEL, this._relayTouchToDragSurface, this);
child.on(Node.EventType.TOUCH_CANCEL, relay, this); node.on(Node.EventType.TOUCH_START, this._relayTouchToDragSurface, this);
node.on(Node.EventType.TOUCH_MOVE, this._relayTouchToDragSurface, this);
node.on(Node.EventType.TOUCH_END, this._relayTouchToDragSurface, this);
node.on(Node.EventType.TOUCH_CANCEL, this._relayTouchToDragSurface, this);
}
private _forwardChildTouchToSurface(): void {
if (!this._dragSurface) return;
const children = this.node.children;
for (let i = 0; i < children.length; i++) {
const child = children[i];
if (!child?.isValid || child === this._dragSurface) continue;
this._bindTouchRelay(child);
}
const skin = this._skinNode;
if (!skin?.isValid) return;
const nested = skin.children;
for (let i = 0; i < nested.length; i++) {
const child = nested[i];
if (!child?.isValid) continue;
this._bindTouchRelay(child);
} }
} }

@ -53,6 +53,10 @@ export class ResPkgBuilder {
{ name: '营地血条', bundle: B.BattleGame, path: PrefabPath, type: Prefab }, { name: '营地血条', bundle: B.BattleGame, path: PrefabPath, type: Prefab },
{ name: '怪跳出拖尾', bundle: B.BattleGame, path: PrefabPath, type: Prefab }, { name: '怪跳出拖尾', bundle: B.BattleGame, path: PrefabPath, type: Prefab },
{ name: 'battleText', bundle: B.BattleGame, path: PrefabPath, type: Prefab }, { name: 'battleText', bundle: B.BattleGame, path: PrefabPath, type: Prefab },
{ name: 'canUpEff', bundle: B.BattleGame, path: PrefabPath, type: Prefab },
{ name: 'trail1', bundle: B.BattleGame, path: PrefabPath, type: Prefab },
{ name: 'trail2', bundle: B.BattleGame, path: PrefabPath, type: Prefab },
{ name: 'trail3', bundle: B.BattleGame, path: PrefabPath, type: Prefab },
]; ];
ResPkgBuilder.pushBattlePrefab(ress, B.BattleGame, 'prefab/数字/', 'atkMonsterScore'); ResPkgBuilder.pushBattlePrefab(ress, B.BattleGame, 'prefab/数字/', 'atkMonsterScore');

@ -25,6 +25,9 @@ const { ccclass } = _decorator;
export class Auto_BattleGame extends UIBase { export class Auto_BattleGame extends UIBase {
ui_touchMask:Node; ui_touchMask:Node;
ui_mapParentNode:Node; ui_mapParentNode:Node;
ui_textGridDown:Node;
ui_textGrids:Node;
ui_textGridUp:Node;
ui_top:Node; ui_top:Node;
ui_title:Node; ui_title:Node;
btnPause:Node; btnPause:Node;
@ -67,6 +70,9 @@ export class Auto_BattleGame extends UIBase {
super.onLoad(); super.onLoad();
this.ui_touchMask = find("ui_touchMask",this.node); this.ui_touchMask = find("ui_touchMask",this.node);
this.ui_mapParentNode = find("ui_mapParentNode",this.node); this.ui_mapParentNode = find("ui_mapParentNode",this.node);
this.ui_textGridDown = find("ui_textGridDown",this.node);
this.ui_textGrids = find("ui_textGrids",this.node);
this.ui_textGridUp = find("ui_textGridUp",this.node);
this.ui_top = find("ui_top",this.node); this.ui_top = find("ui_top",this.node);
this.ui_title = find("ui_top/ui_title",this.node); this.ui_title = find("ui_top/ui_title",this.node);
this.btnPause = find("ui_top/btnPause",this.node); this.btnPause = find("ui_top/btnPause",this.node);

@ -300,6 +300,7 @@ export class BattleGameStealGlyphFxPresenter {
this._onFlightComplete(grid, placement, attachParent, direction); this._onFlightComplete(grid, placement, attachParent, direction);
}, { }, {
attachParent, attachParent,
restWorld: placement.kind === 'map' ? destWorld : null,
startWorld, startWorld,
showTrail: true, showTrail: true,
moveSpeedPx: STEAL_FLIGHT_SPEED_PX, moveSpeedPx: STEAL_FLIGHT_SPEED_PX,
@ -331,7 +332,7 @@ export class BattleGameStealGlyphFxPresenter {
return; return;
} }
if (attachParent?.isValid && grid.node.parent !== attachParent) { if (placement.kind !== 'map' && attachParent?.isValid && grid.node.parent !== attachParent) {
grid.node.parent = attachParent; grid.node.parent = attachParent;
grid.node.setPosition(0, 0, 0); grid.node.setPosition(0, 0, 0);
} }

@ -420,6 +420,7 @@ export class UIBattleGame extends Auto_BattleGame {
// 须在 AI start 之后再挂血条:AI 镇宅牌会改 wallMaxHp,挂早了格宽会按 3 算 // 须在 AI start 之后再挂血条:AI 镇宅牌会改 wallMaxHp,挂早了格宽会按 3 算
AiBattleBridge.inst.setMapTextFlyLayer(this.ui_fly ?? this.ui_mapParentNode); AiBattleBridge.inst.setMapTextFlyLayer(this.ui_fly ?? this.ui_mapParentNode);
AiBattleBridge.inst.setTextGridLayer(this.ui_textGrids);
try { try {
if (AiBattleBridge.inst.start(battle, map, undefined, this.node, this.ui_textList)) { if (AiBattleBridge.inst.start(battle, map, undefined, this.node, this.ui_textList)) {
this._otherSkillView?.refresh(); this._otherSkillView?.refresh();
@ -593,6 +594,7 @@ export class UIBattleGame extends Auto_BattleGame {
this.ui_fly ?? this.ui_mapParentNode, this.ui_fly ?? this.ui_mapParentNode,
this.ui_line, this.ui_line,
rangeNode, rangeNode,
this.ui_textGrids,
); );
// bind() 开头会 unbind,入场回调必须在 bind 之后再挂 // bind() 开头会 unbind,入场回调必须在 bind 之后再挂
this._bagView.setOtherBagAnchor(this.ui_otherBag); this._bagView.setOtherBagAnchor(this.ui_otherBag);

Loading…
Cancel
Save