From f92502f4f56adb08dd69dd029d77a7adb057210b Mon Sep 17 00:00:00 2001 From: pan Date: Tue, 22 Sep 2026 15:56:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(skill):=20=E6=96=B0=E5=A2=9E=E5=8F=AC?= =?UTF-8?q?=E5=94=A4=E7=9B=AE=E6=A0=87=E9=80=89=E6=8B=A9=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E4=B8=8E=E6=8A=80=E8=83=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增SummonTMode枚举,支持同一敌人/随机敌人/去重三种召唤目标模式 2. 为多个技能prefab新增召唤参数配置字段 3. 重构索敌逻辑,支持按配置模式选择召唤目标 4. 优化技能伤害与动画配置,新增maxm7技能与动画资源 5. 修复部分技能的碰撞次数与偏移参数 --- assets/resources/game/skill/anm/atk/fb-8.anim | 921 ++++++++++++++++++ .../game/skill/anm/atk/fb-8.anim.meta | 13 + assets/resources/game/skill/atk/m3.prefab | 5 +- assets/resources/game/skill/atk/maxa1.prefab | 4 + assets/resources/game/skill/atk/maxa2.prefab | 4 + assets/resources/game/skill/atk/maxm1.prefab | 4 + assets/resources/game/skill/atk/maxm2.prefab | 4 + assets/resources/game/skill/atk/maxm3.prefab | 8 +- assets/resources/game/skill/atk/maxm4.prefab | 4 + assets/resources/game/skill/atk/maxm5.prefab | 4 + assets/resources/game/skill/atk/maxm6.prefab | 4 + assets/resources/game/skill/atk/maxm7.prefab | 526 ++++++++++ .../game/skill/atk/maxm7.prefab.meta | 13 + assets/script/game/common/config/SkillSet.ts | 20 +- assets/script/game/hero/SCastSystem.ts | 119 ++- assets/script/game/skill/SkillView.ts | 6 +- 16 files changed, 1622 insertions(+), 37 deletions(-) create mode 100644 assets/resources/game/skill/anm/atk/fb-8.anim create mode 100644 assets/resources/game/skill/anm/atk/fb-8.anim.meta create mode 100644 assets/resources/game/skill/atk/maxm7.prefab create mode 100644 assets/resources/game/skill/atk/maxm7.prefab.meta diff --git a/assets/resources/game/skill/anm/atk/fb-8.anim b/assets/resources/game/skill/anm/atk/fb-8.anim new file mode 100644 index 00000000..08377181 --- /dev/null +++ b/assets/resources/game/skill/anm/atk/fb-8.anim @@ -0,0 +1,921 @@ +[ + { + "__type__": "cc.AnimationClip", + "_name": "fb-8", + "_objFlags": 0, + "__editorExtras__": { + "embeddedPlayerGroups": [] + }, + "_native": "", + "sample": 20, + "speed": 1, + "wrapMode": 1, + "enableTrsBlending": false, + "_duration": 1.4, + "_hash": 500763545, + "_tracks": [ + { + "__id__": 1 + }, + { + "__id__": 7 + }, + { + "__id__": 13 + }, + { + "__id__": 24 + } + ], + "_exoticAnimation": null, + "_events": [ + { + "frame": 0, + "func": "", + "params": [] + }, + { + "frame": 0, + "func": "atk", + "params": [] + }, + { + "frame": 0.6, + "func": "", + "params": [] + }, + { + "frame": 0.6, + "func": "atk", + "params": [] + }, + { + "frame": 1.2, + "func": "", + "params": [] + }, + { + "frame": 1.2, + "func": "atk", + "params": [] + } + ], + "_embeddedPlayers": [], + "_additiveSettings": { + "__id__": 35 + }, + "_auxiliaryCurveEntries": [] + }, + { + "__type__": "cc.animation.ObjectTrack", + "_binding": { + "__type__": "cc.animation.TrackBinding", + "path": { + "__id__": 2 + }, + "proxy": null + }, + "_channel": { + "__id__": 5 + } + }, + { + "__type__": "cc.animation.TrackPath", + "_paths": [ + { + "__id__": 3 + }, + { + "__id__": 4 + }, + "spriteFrame" + ] + }, + { + "__type__": "cc.animation.HierarchyPath", + "path": "Node" + }, + { + "__type__": "cc.animation.ComponentPath", + "component": "cc.Sprite" + }, + { + "__type__": "cc.animation.Channel", + "_curve": { + "__id__": 6 + } + }, + { + "__type__": "cc.ObjectCurve", + "_times": [ + 0, + 0.05, + 0.1, + 0.15, + 0.2, + 0.25, + 0.3, + 0.35, + 0.4, + 0.45, + 0.5, + 0.55, + 0.6, + 0.65, + 0.7, + 0.75, + 0.8, + 0.85, + 0.9, + 0.95, + 1, + 1.05, + 1.1, + 1.15, + 1.2, + 1.25, + 1.3, + 1.35 + ], + "_values": [ + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@55402", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@2ac32", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@a38c9", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@005f7", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@d585f", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@740a0", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@6b34e", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@55402", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@2ac32", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@a38c9", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@005f7", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@d585f", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@740a0", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@6b34e", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@55402", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@2ac32", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@a38c9", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@005f7", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@d585f", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@740a0", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@6b34e", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@55402", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@2ac32", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@a38c9", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@005f7", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@d585f", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@740a0", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@6b34e", + "__expectedType__": "cc.SpriteFrame" + } + ] + }, + { + "__type__": "cc.animation.ObjectTrack", + "_binding": { + "__type__": "cc.animation.TrackBinding", + "path": { + "__id__": 8 + }, + "proxy": null + }, + "_channel": { + "__id__": 11 + } + }, + { + "__type__": "cc.animation.TrackPath", + "_paths": [ + { + "__id__": 9 + }, + { + "__id__": 10 + }, + "spriteFrame" + ] + }, + { + "__type__": "cc.animation.HierarchyPath", + "path": "Node-001" + }, + { + "__type__": "cc.animation.ComponentPath", + "component": "cc.Sprite" + }, + { + "__type__": "cc.animation.Channel", + "_curve": { + "__id__": 12 + } + }, + { + "__type__": "cc.ObjectCurve", + "_times": [ + 0, + 0.05, + 0.1, + 0.15, + 0.2, + 0.25, + 0.3, + 0.35, + 0.4, + 0.45, + 0.5, + 0.55, + 0.6, + 0.65, + 0.7, + 0.75, + 0.8, + 0.85, + 0.9, + 0.95, + 1, + 1.05, + 1.1, + 1.15, + 1.2, + 1.25, + 1.3, + 1.35 + ], + "_values": [ + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@55402", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@2ac32", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@a38c9", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@005f7", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@d585f", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@740a0", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@6b34e", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@55402", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@2ac32", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@a38c9", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@005f7", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@d585f", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@740a0", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@6b34e", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@55402", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@2ac32", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@a38c9", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@005f7", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@d585f", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@740a0", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@6b34e", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@55402", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@2ac32", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@a38c9", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@005f7", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@d585f", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@740a0", + "__expectedType__": "cc.SpriteFrame" + }, + { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@6b34e", + "__expectedType__": "cc.SpriteFrame" + } + ] + }, + { + "__type__": "cc.animation.VectorTrack", + "_binding": { + "__type__": "cc.animation.TrackBinding", + "path": { + "__id__": 14 + }, + "proxy": null + }, + "_channels": [ + { + "__id__": 16 + }, + { + "__id__": 18 + }, + { + "__id__": 20 + }, + { + "__id__": 22 + } + ], + "_nComponents": 3 + }, + { + "__type__": "cc.animation.TrackPath", + "_paths": [ + { + "__id__": 15 + }, + "position" + ] + }, + { + "__type__": "cc.animation.HierarchyPath", + "path": "Node" + }, + { + "__type__": "cc.animation.Channel", + "_curve": { + "__id__": 17 + } + }, + { + "__type__": "cc.RealCurve", + "_times": [ + 0, + 0.65, + 1.35 + ], + "_values": [ + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": -70, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + }, + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": 70, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + }, + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": -70, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + } + ], + "preExtrapolation": 1, + "postExtrapolation": 1 + }, + { + "__type__": "cc.animation.Channel", + "_curve": { + "__id__": 19 + } + }, + { + "__type__": "cc.RealCurve", + "_times": [ + 0, + 0.3, + 0.65, + 1, + 1.35 + ], + "_values": [ + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": -60, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + }, + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": -70, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + }, + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": -60, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + }, + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": -50, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + }, + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": -60, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + } + ], + "preExtrapolation": 1, + "postExtrapolation": 1 + }, + { + "__type__": "cc.animation.Channel", + "_curve": { + "__id__": 21 + } + }, + { + "__type__": "cc.RealCurve", + "_times": [], + "_values": [], + "preExtrapolation": 1, + "postExtrapolation": 1 + }, + { + "__type__": "cc.animation.Channel", + "_curve": { + "__id__": 23 + } + }, + { + "__type__": "cc.RealCurve", + "_times": [], + "_values": [], + "preExtrapolation": 1, + "postExtrapolation": 1 + }, + { + "__type__": "cc.animation.VectorTrack", + "_binding": { + "__type__": "cc.animation.TrackBinding", + "path": { + "__id__": 25 + }, + "proxy": null + }, + "_channels": [ + { + "__id__": 27 + }, + { + "__id__": 29 + }, + { + "__id__": 31 + }, + { + "__id__": 33 + } + ], + "_nComponents": 3 + }, + { + "__type__": "cc.animation.TrackPath", + "_paths": [ + { + "__id__": 26 + }, + "position" + ] + }, + { + "__type__": "cc.animation.HierarchyPath", + "path": "Node-001" + }, + { + "__type__": "cc.animation.Channel", + "_curve": { + "__id__": 28 + } + }, + { + "__type__": "cc.RealCurve", + "_times": [ + 0, + 0.65, + 1.35 + ], + "_values": [ + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": 70, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + }, + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": -70, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + }, + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": 70, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + } + ], + "preExtrapolation": 1, + "postExtrapolation": 1 + }, + { + "__type__": "cc.animation.Channel", + "_curve": { + "__id__": 30 + } + }, + { + "__type__": "cc.RealCurve", + "_times": [ + 0, + 0.3, + 0.65, + 1, + 1.35 + ], + "_values": [ + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": -60, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + }, + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": -50, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + }, + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": -60, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + }, + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": -70, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + }, + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": -60, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + } + ], + "preExtrapolation": 1, + "postExtrapolation": 1 + }, + { + "__type__": "cc.animation.Channel", + "_curve": { + "__id__": 32 + } + }, + { + "__type__": "cc.RealCurve", + "_times": [ + 0, + 0.65, + 1.35 + ], + "_values": [ + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": 0, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + }, + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": 0, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + }, + { + "__type__": "cc.RealKeyframeValue", + "interpolationMode": 0, + "tangentWeightMode": 0, + "value": 0, + "rightTangent": 0, + "rightTangentWeight": 1, + "leftTangent": 0, + "leftTangentWeight": 1, + "easingMethod": 0, + "__editorExtras__": { + "broken": null + } + } + ], + "preExtrapolation": 1, + "postExtrapolation": 1 + }, + { + "__type__": "cc.animation.Channel", + "_curve": { + "__id__": 34 + } + }, + { + "__type__": "cc.RealCurve", + "_times": [], + "_values": [], + "preExtrapolation": 1, + "postExtrapolation": 1 + }, + { + "__type__": "cc.AnimationClipAdditiveSettings", + "enabled": false, + "refClip": null + } +] \ No newline at end of file diff --git a/assets/resources/game/skill/anm/atk/fb-8.anim.meta b/assets/resources/game/skill/anm/atk/fb-8.anim.meta new file mode 100644 index 00000000..163576fe --- /dev/null +++ b/assets/resources/game/skill/anm/atk/fb-8.anim.meta @@ -0,0 +1,13 @@ +{ + "ver": "2.0.3", + "importer": "animation-clip", + "imported": true, + "uuid": "b0bec9a1-c3c7-412f-b6de-e27ec78dcc86", + "files": [ + ".cconb" + ], + "subMetas": {}, + "userData": { + "name": "fb-8" + } +} diff --git a/assets/resources/game/skill/atk/m3.prefab b/assets/resources/game/skill/atk/m3.prefab index 9636bd10..db62a8ae 100644 --- a/assets/resources/game/skill/atk/m3.prefab +++ b/assets/resources/game/skill/atk/m3.prefab @@ -96,7 +96,7 @@ "_lpos": { "__type__": "cc.Vec3", "x": 0, - "y": -30, + "y": -60, "z": 0 }, "_lrot": { @@ -108,7 +108,7 @@ }, "_lscale": { "__type__": "cc.Vec3", - "x": 1, + "x": 1.4, "y": 2, "z": 1 }, @@ -261,6 +261,7 @@ "forceStartX": -1, "forceStartY": -1, "summon_count": 1, + "summon_target_mode": 0, "summon_x_offset": 0, "summon_y_offset": 0, "summon_interval": 0, diff --git a/assets/resources/game/skill/atk/maxa1.prefab b/assets/resources/game/skill/atk/maxa1.prefab index 51a49f38..958d0ff3 100644 --- a/assets/resources/game/skill/atk/maxa1.prefab +++ b/assets/resources/game/skill/atk/maxa1.prefab @@ -293,6 +293,10 @@ "forceStartX": -1, "forceStartY": -1, "summon_count": 4, + "summon_target_mode": 2, + "summon_x_offset": 0, + "summon_y_offset": 0, + "summon_interval": 0, "height_offset": 100, "_id": "" }, diff --git a/assets/resources/game/skill/atk/maxa2.prefab b/assets/resources/game/skill/atk/maxa2.prefab index a5ab4ed3..a819c1c1 100644 --- a/assets/resources/game/skill/atk/maxa2.prefab +++ b/assets/resources/game/skill/atk/maxa2.prefab @@ -293,6 +293,10 @@ "forceStartX": -1, "forceStartY": -1, "summon_count": 6, + "summon_target_mode": 2, + "summon_x_offset": 0, + "summon_y_offset": 0, + "summon_interval": 0, "height_offset": 100, "_id": "" }, diff --git a/assets/resources/game/skill/atk/maxm1.prefab b/assets/resources/game/skill/atk/maxm1.prefab index 1a9d6f84..5a1cae9e 100644 --- a/assets/resources/game/skill/atk/maxm1.prefab +++ b/assets/resources/game/skill/atk/maxm1.prefab @@ -261,6 +261,10 @@ "forceStartX": -1, "forceStartY": -1, "summon_count": 3, + "summon_target_mode": 2, + "summon_x_offset": 0, + "summon_y_offset": 0, + "summon_interval": 0, "height_offset": 100, "_id": "" }, diff --git a/assets/resources/game/skill/atk/maxm2.prefab b/assets/resources/game/skill/atk/maxm2.prefab index 120e3cef..55f37390 100644 --- a/assets/resources/game/skill/atk/maxm2.prefab +++ b/assets/resources/game/skill/atk/maxm2.prefab @@ -397,6 +397,10 @@ "forceStartX": -1, "forceStartY": -1, "summon_count": 3, + "summon_target_mode": 0, + "summon_x_offset": 0, + "summon_y_offset": 0, + "summon_interval": 0.2, "height_offset": 0, "_id": "" }, diff --git a/assets/resources/game/skill/atk/maxm3.prefab b/assets/resources/game/skill/atk/maxm3.prefab index c866b267..80acb0f3 100644 --- a/assets/resources/game/skill/atk/maxm3.prefab +++ b/assets/resources/game/skill/atk/maxm3.prefab @@ -96,7 +96,7 @@ "_lpos": { "__type__": "cc.Vec3", "x": 0, - "y": -30, + "y": -90, "z": 0 }, "_lrot": { @@ -108,7 +108,7 @@ }, "_lscale": { "__type__": "cc.Vec3", - "x": 1, + "x": 1.5, "y": 2, "z": 1 }, @@ -261,6 +261,10 @@ "forceStartX": -1, "forceStartY": -1, "summon_count": 5, + "summon_target_mode": 2, + "summon_x_offset": 0, + "summon_y_offset": 0, + "summon_interval": 0, "height_offset": 0, "_id": "" }, diff --git a/assets/resources/game/skill/atk/maxm4.prefab b/assets/resources/game/skill/atk/maxm4.prefab index aa3ff678..afe2a9a9 100644 --- a/assets/resources/game/skill/atk/maxm4.prefab +++ b/assets/resources/game/skill/atk/maxm4.prefab @@ -261,6 +261,10 @@ "forceStartX": -1, "forceStartY": -1, "summon_count": 3, + "summon_target_mode": 2, + "summon_x_offset": 0, + "summon_y_offset": 0, + "summon_interval": 0.5, "height_offset": 100, "_id": "" }, diff --git a/assets/resources/game/skill/atk/maxm5.prefab b/assets/resources/game/skill/atk/maxm5.prefab index 8160511e..bfa11695 100644 --- a/assets/resources/game/skill/atk/maxm5.prefab +++ b/assets/resources/game/skill/atk/maxm5.prefab @@ -261,6 +261,10 @@ "forceStartX": -1, "forceStartY": -1, "summon_count": 3, + "summon_target_mode": 2, + "summon_x_offset": 0, + "summon_y_offset": 0, + "summon_interval": 0, "height_offset": 100, "_id": "" }, diff --git a/assets/resources/game/skill/atk/maxm6.prefab b/assets/resources/game/skill/atk/maxm6.prefab index dbb2313b..072fb1a3 100644 --- a/assets/resources/game/skill/atk/maxm6.prefab +++ b/assets/resources/game/skill/atk/maxm6.prefab @@ -261,6 +261,10 @@ "forceStartX": -1, "forceStartY": -1, "summon_count": 3, + "summon_target_mode": 2, + "summon_x_offset": 0, + "summon_y_offset": 0, + "summon_interval": 0, "height_offset": 100, "_id": "" }, diff --git a/assets/resources/game/skill/atk/maxm7.prefab b/assets/resources/game/skill/atk/maxm7.prefab new file mode 100644 index 00000000..bdc90e5c --- /dev/null +++ b/assets/resources/game/skill/atk/maxm7.prefab @@ -0,0 +1,526 @@ +[ + { + "__type__": "cc.Prefab", + "_name": "maxm7", + "_objFlags": 0, + "__editorExtras__": {}, + "_native": "", + "data": { + "__id__": 1 + }, + "optimizationPolicy": 0, + "persistent": false + }, + { + "__type__": "cc.Node", + "_name": "maxm7", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": null, + "_children": [ + { + "__id__": 2 + }, + { + "__id__": 8 + } + ], + "_active": true, + "_components": [ + { + "__id__": 14 + }, + { + "__id__": 16 + }, + { + "__id__": 18 + }, + { + "__id__": 20 + }, + { + "__id__": 22 + } + ], + "_prefab": { + "__id__": 24 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "" + }, + { + "__type__": "cc.Node", + "_name": "Node", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 1 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 3 + }, + { + "__id__": 5 + } + ], + "_prefab": { + "__id__": 7 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": -30, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 2, + "y": 2, + "z": 1 + }, + "_mobility": 0, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 2 + }, + "_enabled": true, + "__prefab": { + "__id__": 4 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 128, + "height": 128 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0 + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "93pNmvtQlLSqtTgIepyEmA" + }, + { + "__type__": "cc.Sprite", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 2 + }, + "_enabled": true, + "__prefab": { + "__id__": 6 + }, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_spriteFrame": { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@55402", + "__expectedType__": "cc.SpriteFrame" + }, + "_type": 0, + "_fillType": 0, + "_sizeMode": 1, + "_fillCenter": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_fillStart": 0, + "_fillRange": 0, + "_isTrimmedMode": true, + "_useGrayscale": false, + "_atlas": { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20", + "__expectedType__": "cc.SpriteAtlas" + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "12eKc8gltBz50frJCS5+ww" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "3arqAMBz1MvoXBzeDaL5M/", + "instance": null, + "targetOverrides": null, + "nestedPrefabInstanceRoots": null + }, + { + "__type__": "cc.Node", + "_name": "Node-001", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 1 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 9 + }, + { + "__id__": 11 + } + ], + "_prefab": { + "__id__": 13 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": -30, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 2, + "y": 2, + "z": 1 + }, + "_mobility": 0, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 8 + }, + "_enabled": true, + "__prefab": { + "__id__": 10 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 128, + "height": 128 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0 + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "cbS/mBx7hFKK1RlGcpOgD1" + }, + { + "__type__": "cc.Sprite", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 8 + }, + "_enabled": true, + "__prefab": { + "__id__": 12 + }, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_spriteFrame": { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20@55402", + "__expectedType__": "cc.SpriteFrame" + }, + "_type": 0, + "_fillType": 0, + "_sizeMode": 1, + "_fillCenter": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_fillStart": 0, + "_fillRange": 0, + "_isTrimmedMode": true, + "_useGrayscale": false, + "_atlas": { + "__uuid__": "2842dc10-d89e-4ff6-8a11-6d09bf48cf20", + "__expectedType__": "cc.SpriteAtlas" + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "eah7cf5S5FCrmP7CHX5e38" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "f9cYdo2HdAp7KWposjmIcg", + "instance": null, + "targetOverrides": null, + "nestedPrefabInstanceRoots": null + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 1 + }, + "_enabled": true, + "__prefab": { + "__id__": 15 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 200, + "height": 100 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.3 + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "63NP9yq3hEUKD/OZZZ5t7x" + }, + { + "__type__": "57aabs7TE1J5obTAZczc+64", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 1 + }, + "_enabled": true, + "__prefab": { + "__id__": 17 + }, + "atk_x": 0, + "atk_y": 0, + "runType": 3, + "endType": 0, + "speed": 720, + "time": 0, + "distance": 0, + "forceStartX": -1, + "forceStartY": -1, + "summon_count": 1, + "summon_target_mode": 2, + "summon_x_offset": 0, + "summon_y_offset": 0, + "summon_interval": 0.5, + "height_offset": 0, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "35nW0iQNBH2bqkWAr3MVkQ" + }, + { + "__type__": "cc.RigidBody2D", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 1 + }, + "_enabled": true, + "__prefab": { + "__id__": 19 + }, + "enabledContactListener": true, + "bullet": false, + "awakeOnLoad": true, + "_group": 1, + "_type": 1, + "_allowSleep": false, + "_gravityScale": 1, + "_linearDamping": 0, + "_angularDamping": 0, + "_linearVelocity": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_angularVelocity": 0, + "_fixedRotation": false, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "57cr7S0YpK4oEZCavwXtIX" + }, + { + "__type__": "cc.BoxCollider2D", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 1 + }, + "_enabled": true, + "__prefab": { + "__id__": 21 + }, + "tag": 0, + "_group": 1, + "_density": 1, + "_sensor": true, + "_friction": 0.2, + "_restitution": 0, + "_offset": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_size": { + "__type__": "cc.Size", + "width": 200, + "height": 100 + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "ebw5mObxNGGKxnJXDgX5gl" + }, + { + "__type__": "cc.Animation", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 1 + }, + "_enabled": true, + "__prefab": { + "__id__": 23 + }, + "playOnLoad": true, + "_clips": [ + { + "__uuid__": "b0bec9a1-c3c7-412f-b6de-e27ec78dcc86", + "__expectedType__": "cc.AnimationClip" + } + ], + "_defaultClip": { + "__uuid__": "b0bec9a1-c3c7-412f-b6de-e27ec78dcc86", + "__expectedType__": "cc.AnimationClip" + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "20U0hP/NZErJJXRCEib1lq" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "c46/YsCPVOJYA4mWEpNYRx", + "instance": null, + "targetOverrides": null + } +] \ No newline at end of file diff --git a/assets/resources/game/skill/atk/maxm7.prefab.meta b/assets/resources/game/skill/atk/maxm7.prefab.meta new file mode 100644 index 00000000..e603c58d --- /dev/null +++ b/assets/resources/game/skill/atk/maxm7.prefab.meta @@ -0,0 +1,13 @@ +{ + "ver": "1.1.50", + "importer": "prefab", + "imported": true, + "uuid": "2316d214-bb61-434e-a056-48793e72dcce", + "files": [ + ".json" + ], + "subMetas": {}, + "userData": { + "syncNodeName": "maxm7" + } +} diff --git a/assets/script/game/common/config/SkillSet.ts b/assets/script/game/common/config/SkillSet.ts index fea20aaf..37fa2241 100644 --- a/assets/script/game/common/config/SkillSet.ts +++ b/assets/script/game/common/config/SkillSet.ts @@ -65,6 +65,16 @@ export enum EType { timeEnd = 1, //碰撞够也不消失,时间到才消失 collision = 2, //碰撞次数够就消失 } + +/** + * 召唤类技能(summon_count>1)多次施放的目标选择模式(由技能 prefab 上 SkillView 配置)。 + * 仅对敌方目标技能生效;友方/自身技能不走该逻辑。 + */ +export enum SummonTMode { + same = 0, // 同一敌人:所有召唤物锁定施法时选定的目标(默认,原行为) + random = 1, // 随机敌人:每次出手时从射程内敌人中随机锁定一个 + unique = 2, // 避免相同敌人:优先锁定本轮尚未选过的敌人,一轮选完后重置再选 +} //debuff类型 @@ -379,22 +389,22 @@ export const SkillSet: Record = { }, 6201: { uuid: 6201, name: "飓风", sp_name: "maxm2", icon: "98-Enchant-Wind", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max1", - DTType: DTType.single, ap: 100, hit_count: 2, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote, + DTType: DTType.single, ap: 100, hit_count: 99, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote, RType: RType.linear, EType: EType.collision, info: "一个飓风", }, 6202: { uuid: 6202, name: "毒气弹", sp_name: "maxm4", icon: "o_warlock_hyzy_skill", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max1", - DTType: DTType.single, ap: 100, hit_count: 2, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote, + DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote, RType: RType.linear, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05, info: "一个大毒气弹", }, 6203: { uuid: 6203, name: "能量波", sp_name: "maxm5", icon: "b_priest_kx_skill", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max1", - DTType: DTType.single, ap: 100, hit_count: 2, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote, + DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote, RType: RType.linear, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05, info: "一个能量波", }, 6204: { - uuid: 6204, name: "闪电", sp_name: "maxm4", icon: "o_warlock_hyzy_skill", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max1", - DTType: DTType.single, ap: 100, hit_count: 2, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote, + uuid: 6204, name: "雷暴", sp_name: "maxm7", icon: "o_warlock_hyzy_skill", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "max1", + DTType: DTType.single, ap: 100, hit_count: 99, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote, RType: RType.linear, EType: EType.collision, bezier_start_y: 20, bezier_mid_y: 140, bezier_arc: 1.05, info: "一个大毒气弹", }, diff --git a/assets/script/game/hero/SCastSystem.ts b/assets/script/game/hero/SCastSystem.ts index b91bb6b4..74b82e7c 100644 --- a/assets/script/game/hero/SCastSystem.ts +++ b/assets/script/game/hero/SCastSystem.ts @@ -1,8 +1,8 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; -import { Vec3, Prefab, instantiate, tween, Node } from "cc"; +import { Vec3, Prefab, instantiate, tween, Node, UITransform } from "cc"; import { HeroAttrsComp } from "./HeroAttrsComp"; import { HeroViewComp } from "./HeroViewComp"; -import { DTType, RType, SkillConfig, SkillKind, SkillSet, TGroup, SkillOverrides, mergeSkillParams } from "../common/config/SkillSet"; +import { DTType, RType, SkillConfig, SkillKind, SkillSet, SummonTMode, TGroup, SkillOverrides, mergeSkillParams } from "../common/config/SkillSet"; import { Skill } from "../skill/Skill"; import { SkillView } from "../skill/SkillView"; import { smc } from "../common/SingletonModuleComp"; @@ -20,12 +20,14 @@ import { BuffList } from "../common/config/BuffSet"; import { CameraFX } from "../common/CameraFX"; import { ScreenShake } from "../common/ScreenShake"; -/** 召唤参数:数量 / XY 步进偏移 / 生成间隔,均由技能 prefab 上的 SkillView 配置 */ +/** 召唤参数:数量 / XY 步进偏移 / 生成间隔 / 目标选择模式,均由技能 prefab 上的 SkillView 配置 */ export interface SummonParams { count: number; x_offset: number; y_offset: number; interval: number; + /** 多次施放的目标选择模式(同一敌人/随机敌人/避免相同敌人) */ + target_mode: SummonTMode; } /** @@ -137,12 +139,12 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate mockAttrs.type = HType.Long; // 假定为远程,拥有较长索敌范围 mockAttrs.dis = 2000; // 给予全屏以上的索敌范围 + // 伪造一个 view 供找敌逻辑使用,位置为 spawnPos(random/unique 模式实时索敌也复用) + const mockView = { + node: { position: spawnPos } + } as any; let targetPos: Vec3 | null = null; if (!isFriendly) { - // 伪造一个 view 供找敌逻辑使用,位置为 spawnPos - const mockView = { - node: { position: spawnPos } - } as any; // 获取全屏索敌范围 const maxRange = this.resolveMaxCastRange(mockAttrs, mockAttrs.type as HType); const target = this.findNearestEnemyInRange(mockAttrs, mockView, maxRange); @@ -157,6 +159,8 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate } mLogger.log(this.debugMode, "SCastSystem", `[卡牌施法] 释放技能「${config.name}」(s_uuid:${s_uuid}) rarity:${rarity} castTimes:${castTimes} targetPos:${targetPos ? `(${targetPos.x.toFixed(0)},${targetPos.y.toFixed(0)})` : "none"} isFriendly:${isFriendly}`); + // unique 模式去重记录:本次施法序列内已锁定过的敌人 eid + const usedTargetEids = new Set(); for (let i = 0; i < castTimes; i++) { // 多发/召唤按间隔错峰执行:i=0 立即,其余延迟 i*castInterval(召唤间隔由 prefab 配置) const exec = () => { @@ -167,7 +171,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate if (friendlyTargets.length === 0) return; this.applyFriendlySkillEffects(s_uuid, rarity, config, null as any, mockAttrs, friendlyTargets, spawnPos); } else { - const enemyTargetPos = this.resolveRepeatCastTargetPos(targetPos, i, summon); + const enemyTargetPos = this.resolveSummonCastTargetPos(config, mockAttrs, mockView, targetPos, i, summon, usedTargetEids); this.createSkillEntityForCard(s_uuid, rarity, mockAttrs, spawnPos, enemyTargetPos, i, overrides, summon); } }; @@ -214,14 +218,14 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate /** * 解析单次施法的召唤参数。 * 数量优先级:合并后配置上的 summon_count(heroSet overrides 可覆写) > prefab 上 SkillView.summon_count; - * XY 偏移与间隔仅由 prefab 配置。 + * XY 偏移、间隔与目标选择模式仅由 prefab 配置。 */ private resolveSummonParams(config: SkillConfig): SummonParams { const fromPrefab = this.readSummonParamsFromPrefab(config.sp_name); const count = typeof config.summon_count === "number" ? Math.max(1, Math.floor(config.summon_count)) : fromPrefab.count; - return { count, x_offset: fromPrefab.x_offset, y_offset: fromPrefab.y_offset, interval: fromPrefab.interval }; + return { count, x_offset: fromPrefab.x_offset, y_offset: fromPrefab.y_offset, interval: fromPrefab.interval, target_mode: fromPrefab.target_mode }; } /** @@ -232,7 +236,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate const cached = this.summonParamsCache.get(sp_name); if (cached) return cached; const path = `game/skill/atk/${sp_name}`; - let params: SummonParams = { count: 1, x_offset: 0, y_offset: 0, interval: 0 }; + let params: SummonParams = { count: 1, x_offset: 0, y_offset: 0, interval: 0, target_mode: SummonTMode.same }; const prefab = oops.res.get(path, Prefab) as Prefab | null; if (prefab) { const view = prefab.data?.getComponent(SkillView); @@ -242,6 +246,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate x_offset: view.summon_x_offset, y_offset: view.summon_y_offset, interval: view.summon_interval, + target_mode: view.summon_target_mode ?? SummonTMode.same, }; } this.summonParamsCache.set(sp_name, params); @@ -355,6 +360,8 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate } heroView.skill_name(val, s_uuid) mLogger.log(this.debugMode, "SCastSystem", `[触发施法] ${heroAttrs.hero_name}(uuid:${heroAttrs.hero_uuid}) 触发类型:${triggerType ?? "none"} 释放技能「${config.name}」(s_uuid:${s_uuid}) lv:${skillLv} ${isFriendly ? "友方" : "对敌"} castTimes:${castTimes}`); + // unique 模式去重记录:本次施法序列内已锁定过的敌人 eid + const usedTargetEids = new Set(); for (let i = 0; i < castTimes; i++) { if (!heroView.node || !heroView.node.isValid) return; // 多发/召唤按间隔错峰执行:i=0 立即,其余延迟 i*castInterval(召唤间隔由 prefab 配置) @@ -367,7 +374,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate this.applyFriendlySkillEffects(s_uuid, skillLv, config, heroView, heroAttrs, friendlyTargets, null); return; } - const enemyTargetPos = this.resolveRepeatCastTargetPos(targetPos, i, summon); + const enemyTargetPos = this.resolveSummonCastTargetPos(config, heroAttrs, heroView, targetPos, i, summon, usedTargetEids); this.applyEnemySkillEffects(s_uuid, skillLv, config, heroView, heroAttrs, enemyTargetPos, i, overrides, summon); }, i * castInterval); } @@ -469,6 +476,8 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate // 注意:这里仍然是基于时间的延迟,受帧率波动影响。 // 若需精确同步,建议在动画中添加帧事件并在 HeroViewComp 中监听。 const delay = config.ready > 0 ? config.ready : FightSet.SKILL_CAST_DELAY; + // unique 模式去重记录:本次施法序列内已锁定过的敌人 eid + const usedTargetEids = new Set(); heroView.scheduleOnce(() => { if (!smc.mission.play || smc.mission.pause || !smc.mission.in_fight) return; @@ -484,7 +493,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate this.applyFriendlySkillEffects(s_uuid, skillLv, config, heroView, heroAttrs, friendlyTargets, null); return; } - const enemyTargetPos = this.resolveRepeatCastTargetPos(castPlan.targetPos, i, summon); + const enemyTargetPos = this.resolveSummonCastTargetPos(config, heroAttrs, heroView, castPlan.targetPos, i, summon, usedTargetEids); this.applyEnemySkillEffects(s_uuid, skillLv, config, heroView, heroAttrs, enemyTargetPos, i, overrides, summon); }, i * castInterval); } @@ -537,6 +546,71 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate return new Vec3(targetPos.x + offset.x, targetPos.y + offset.y, targetPos.z); } + /** + * 解析第 castIndex 次施放的对敌目标点(召唤目标选择模式入口)。 + * - same(默认):沿用施法时锁定的目标点并按召唤偏移对称铺开(原行为); + * - random:每次出手时从射程内敌人中随机锁定一个(错峰施放时实时索敌,目标状态最新鲜); + * - unique:优先锁定本轮未选过的敌人,敌人不足一轮时重置去重记录再来一轮; + * 实时索敌失败(敌人死亡/移动出射程)时回退施法时锁定的目标点,保证技能不落空。 + */ + private resolveSummonCastTargetPos(config: SkillConfig, heroAttrs: HeroAttrsComp, heroView: HeroViewComp | null, baseTargetPos: Vec3 | null, castIndex: number, summon: SummonParams | undefined, usedEids: Set): Vec3 | null { + if (!summon || summon.count <= 1 || summon.target_mode === SummonTMode.same) { + return this.resolveRepeatCastTargetPos(baseTargetPos, castIndex, summon); + } + const maxRange = this.resolveMaxCastRange(heroAttrs, heroAttrs.type as HType); + const enemies = this.collectEnemiesInRange(heroAttrs, heroView, maxRange); + const picked = enemies.length > 0 ? this.pickEnemyByTargetMode(enemies, summon.target_mode, usedEids) : null; + if (picked?.node) { + mLogger.log(this.debugMode, "SCastSystem", `[召唤索敌] 「${config.name}」第${castIndex + 1}个实体锁定目标 eid:${picked.ent?.eid} 模式:${SummonTMode[summon.target_mode]}`); + // 与 resolveEnemyCastTargetPos 保持一致:贝塞尔取脚底原始坐标,其余补半身高命中身体中心 + const pos = config.RType === RType.bezier ? picked.node.position.clone() : this.buildEnemyCastTargetPos(picked); + // 召唤偏移铺开仍生效:random 模式重复锁定同一敌人时,避免实体完全重叠 + const offset = this.resolveCastOffset(castIndex, summon); + pos.x += offset.x; + pos.y += offset.y; + return pos; + } + // 实时索敌失败:回退施法时锁定的目标点 + return this.resolveRepeatCastTargetPos(baseTargetPos, castIndex, summon); + } + + /** 按目标模式从射程内候选敌人中挑选本次施放的锁定目标,并写入去重记录 */ + private pickEnemyByTargetMode(enemies: HeroViewComp[], mode: SummonTMode, usedEids: Set): HeroViewComp | null { + let pool = enemies; + if (mode === SummonTMode.unique) { + const unused = enemies.filter(view => !view.ent || !usedEids.has(view.ent.eid)); + if (unused.length > 0) { + pool = unused; + } else { + // 敌人不足一轮:重置已选记录,重新开始去重,保证尽量分散 + usedEids.clear(); + } + } + const picked = pool[Math.floor(Math.random() * pool.length)]; + if (picked?.ent) usedEids.add(picked.ent.eid); + return picked ?? null; + } + + /** 收集施法者射程内的全部敌方目标(随机/去重目标模式实时索敌用),网格遍历与 findNearestEnemyByGrid 同源 */ + private collectEnemiesInRange(heroAttrs: HeroAttrsComp, heroView: HeroViewComp | null, maxRange: number): HeroViewComp[] { + const result: HeroViewComp[] = []; + if (!heroView?.node) return result; + const grid = heroAttrs.fac === FacSet.HERO ? smc.mission.monGrid : smc.mission.heroGrid; + const currentX = heroView.node.position.x; + for (const eid of grid) { + if (eid < 0) continue; + const entity = ecs.getEntityByEid(eid); + if (!entity) continue; + const model = entity.get(HeroAttrsComp); + const view = entity.get(HeroViewComp); + if (!model || model.is_dead || model.is_reviving || !view?.node) continue; + if (Math.abs(currentX - view.node.position.x) <= maxRange) { + result.push(view); + } + } + return result; + } + /** 解析第 castIndex 个实体的偏移:召唤技能按 prefab 配置对称交替铺开(0, +1, -1, +2, -2... 档 × 步进值);多发回落纵向扇形档位 */ private resolveCastOffset(castIndex: number, summon?: SummonParams): { x: number; y: number } { if (summon && summon.count > 1) { @@ -883,7 +957,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate return nearestEnemy.node?.position.clone() ?? null; } if (config.DTType !== DTType.range) { - return this.buildEnemyCastTargetPos(heroView, nearestEnemy, maxRange); + return this.buildEnemyCastTargetPos(nearestEnemy); } const frontEnemy = this.findFrontEnemyInRange(heroAttrs, heroView, maxRange, nearestEnemy); if (!frontEnemy?.node) return null; @@ -897,19 +971,10 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate return heroAttrs.dis; } - /** 生成沿目标方向的施法目标坐标 */ - private buildEnemyCastTargetPos(caster: HeroViewComp, target: HeroViewComp, castRange: number): Vec3 { - // 直接返回目标的真实坐标,保留其 Y 轴信息,确保能向目标真实所在位置发射 - // 考虑到目前角色的 y 坐标都是脚底(碰撞体底部),为了命中身体中心,给目标 y 加上高度的一半 - let halfHeight = 0; - if (target.node) { - const transform = target.node.getComponent('cc.UITransform') as any; - if (transform) { - halfHeight = transform.height / 2; - } else { - halfHeight = 40; // 如果没有 UITransform,给一个默认高度偏移 - } - } + /** 生成对敌施法目标坐标:直接返回目标的真实坐标;y 为脚底(碰撞体底部),补半身高以命中身体中心 */ + private buildEnemyCastTargetPos(target: HeroViewComp): Vec3 { + const transform = target.node?.getComponent(UITransform); + const halfHeight = transform ? transform.height / 2 : 40; // 无 UITransform 时给默认高度偏移 const pos = target.node.position.clone(); pos.y += halfHeight; diff --git a/assets/script/game/skill/SkillView.ts b/assets/script/game/skill/SkillView.ts index 91c83852..bff8873f 100644 --- a/assets/script/game/skill/SkillView.ts +++ b/assets/script/game/skill/SkillView.ts @@ -2,7 +2,7 @@ import { _decorator, Animation, CCFloat, CCInteger, Collider2D, Contact2DType, E import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp"; import { HeroViewComp } from "../hero/HeroViewComp"; -import { DTType, EType, RType, SkillConfig, SkillSet } from "../common/config/SkillSet"; +import { DTType, EType, RType, SkillConfig, SkillSet, SummonTMode } from "../common/config/SkillSet"; import { SDataCom } from "./SDataCom"; import { HeroAttrsComp } from "../hero/HeroAttrsComp"; import { DamageQueueHelper } from "../hero/DamageQueueComp"; @@ -54,6 +54,10 @@ export class SkillView extends CCComp { @property({ type: CCInteger, slide: true, range: [1, 8, 1], tooltip: "单次施法召唤的技能实体个数" }) summon_count: number = 1; + /** 召唤目标选择模式:same=锁定同一敌人(默认);random=每次出手随机敌人;unique=避免重复敌人(一轮选完重置) */ + @property({ type: Enum(SummonTMode), tooltip: "召唤目标选择:同一敌人/随机敌人/避免相同敌人" }) + summon_target_mode: SummonTMode = SummonTMode.same; + /** 召唤物 X 轴步进偏移(像素):summon_count>1 时以出生点/目标点为中心对称交替铺开(第1个=0,之后按 +1,-1,+2,-2... 档 × 该值,正=右) */ @property({ type: CCFloat, slide: true, range: [-200, 200, 5], tooltip: "召唤物X轴步进偏移:以中心对称交替铺开(0,+1,-1,+2,-2...档×该值)" }) summon_x_offset: number = 0;