隔山打牛

master
humingxing 6 hours ago
parent b10fe3f91f
commit 33696f7403
  1. 262
      assets/bundles/battleHero/prefab/skill/隔山打牛.prefab
  2. 13
      assets/bundles/battleHero/prefab/skill/隔山打牛.prefab.meta
  3. 10
      assets/mx/module/battle/core/BattleSession.ts
  4. 9
      assets/res/spine/隔山打牛JSON.meta
  5. 1
      assets/res/spine/隔山打牛JSON/.WeDrive
  6. 104
      assets/res/spine/隔山打牛JSON/隔山打牛.atlas
  7. 12
      assets/res/spine/隔山打牛JSON/隔山打牛.atlas.meta
  8. 1
      assets/res/spine/隔山打牛JSON/隔山打牛.json
  9. 13
      assets/res/spine/隔山打牛JSON/隔山打牛.json.meta
  10. BIN
      assets/res/spine/隔山打牛JSON/隔山打牛.png
  11. 134
      assets/res/spine/隔山打牛JSON/隔山打牛.png.meta
  12. 12
      assets/script/battle/combat/PassiveSkillRuntime.ts
  13. 102
      assets/script/battle/view/CocosBattleCombatPresenter.ts
  14. 2
      docs/方案-Battlebuff扩展105-112.md

@ -0,0 +1,262 @@
[
{
"__type__": "cc.Prefab",
"_name": "隔山打牛",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "隔山打牛",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [
{
"__id__": 2
}
],
"_active": true,
"_components": [
{
"__id__": 10
}
],
"_prefab": {
"__id__": 12
},
"_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.Node",
"_name": "隔山打牛",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 3
},
{
"__id__": 5
},
{
"__id__": 7
}
],
"_prefab": {
"__id__": 9
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_mobility": 0,
"_layer": 33554432,
"_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": 438,
"height": 192
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5271917891828981,
"y": 0.1018749972184499
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "76ZZbT4/ZIqbtvk3NBMY6I"
},
{
"__type__": "sp.Skeleton",
"_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
},
"_skeletonData": {
"__uuid__": "4316bb66-bc50-49dc-82fc-b44973b80528",
"__expectedType__": "sp.SkeletonData"
},
"defaultSkin": "default",
"defaultAnimation": "animation",
"_premultipliedAlpha": true,
"_timeScale": 1,
"_preCacheMode": 0,
"_cacheMode": 0,
"_sockets": [],
"_useTint": false,
"_debugMesh": false,
"_debugBones": false,
"_debugSlots": false,
"_enableBatch": false,
"loop": true,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "87oQz6Hv1CFZDfHuDFAGS7"
},
{
"__type__": "cc.Sorting2D",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": {
"__id__": 8
},
"_sortingLayer": 4,
"_sortingOrder": 0,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "357LOOZDhGz6N8HJgzem9G"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "0dSiqHBHBO9ovVVKPIEJiD",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 11
},
"_contentSize": {
"__type__": "cc.Size",
"width": 100,
"height": 100
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "6a7/yPPNVIo6oyr7ThcJE1"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "4fxj20EUZCpoGh4SVCREIU",
"instance": null,
"targetOverrides": null
}
]

@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "61c1005c-b736-4626-8d07-d80895dda794",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "隔山打牛"
}
}

@ -295,6 +295,16 @@ export class BattleSession implements BattleServices {
/** 备战结束 / 连续模式开波 */
startCombat(): void {
if (this.ended) return;
// 备战中被 pauseBattle 弹窗(如三选一)暂停:仍登记开波,resume 后进 COMBAT
if (this._phase === BattlePhase.PAUSE) {
if (!this.isContinuousFlow && this._phaseBeforePause !== BattlePhase.PREP) return;
if (!this.spawner.hasMoreWaves()) return;
if (this.spawner.isWaveCombatActive()) return;
if (this._waveAdvancePending) return;
this._phaseBeforePause = BattlePhase.COMBAT;
this._tryStartWaveWithPrepDelay(this.spawner.waveIndex + 1);
return;
}
if (!this.isContinuousFlow && this._phase !== BattlePhase.PREP) return;
if (!this.spawner.hasMoreWaves()) return;
if (this.spawner.isWaveCombatActive()) return;

@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "4ed941b7-020f-4e00-97fe-3eebc70ee182",
"files": [],
"subMetas": {},
"userData": {}
}

@ -0,0 +1 @@
D:\WXWork\1688855084654441\WeDrive\中昱智云\抖音游戏\战斗类\【新】2048数字守卫战\动效\隔山打牛\隔山打牛JSON

@ -0,0 +1,104 @@
隔山打牛.png
size: 872,872
format: RGBA8888
filter: Linear,Linear
repeat: none
1
rotate: false
xy: 425, 244
size: 243, 267
orig: 246, 269
offset: 1, 1
index: -1
2
rotate: true
xy: 298, 20
size: 215, 295
orig: 217, 297
offset: 1, 1
index: -1
3
rotate: true
xy: 0, 10
size: 225, 296
orig: 227, 298
offset: 1, 1
index: -1
4
rotate: false
xy: 670, 200
size: 200, 311
orig: 202, 313
offset: 1, 1
index: -1
5
rotate: true
xy: 0, 237
size: 209, 312
orig: 211, 314
offset: 1, 1
index: -1
6
rotate: true
xy: 0, 448
size: 230, 317
orig: 232, 319
offset: 1, 1
index: -1
7
rotate: false
xy: 793, 650
size: 74, 67
orig: 76, 69
offset: 1, 1
index: -1
a0
rotate: true
xy: 863, 808
size: 62, 5
orig: 64, 7
offset: 1, 1
index: -1
a1
rotate: true
xy: 793, 553
size: 95, 25
orig: 97, 27
offset: 1, 1
index: -1
a2
rotate: true
xy: 595, 21
size: 177, 101
orig: 182, 103
offset: 3, 1
index: -1
a3
rotate: true
xy: 319, 406
size: 272, 104
orig: 280, 106
offset: 5, 1
index: -1
a4
rotate: false
xy: 435, 513
size: 356, 204
orig: 363, 206
offset: 3, 1
index: -1
a5
rotate: false
xy: 435, 719
size: 426, 151
orig: 439, 153
offset: 6, 1
index: -1
a6
rotate: false
xy: 0, 680
size: 433, 190
orig: 438, 192
offset: 4, 1
index: -1

@ -0,0 +1,12 @@
{
"ver": "1.0.0",
"importer": "*",
"imported": true,
"uuid": "d68878c7-e4ba-4692-a744-ee4cc6aaec63",
"files": [
".atlas",
".json"
],
"subMetas": {},
"userData": {}
}

@ -0,0 +1 @@
{"skeleton":{"hash":"pERjccZ3ExdzzTEfOZP4MZdU2Gw","spine":"3.8.75","x":-230.91,"y":-19.56,"width":438,"height":192},"bones":[{"name":"root"},{"name":"隔山打牛效果","parent":"root","length":45.73,"rotation":89.6,"x":0.27,"y":-1.19},{"name":"冲击效果","parent":"root","length":67.07,"rotation":90.4,"x":9.41,"y":-75.94},{"name":"冲击效果2","parent":"root","length":67.07,"rotation":90.4,"x":9.41,"y":-75.94}],"slots":[{"name":"冲击效果3","bone":"冲击效果2","attachment":"a6"},{"name":"隔山打牛效果","bone":"隔山打牛效果","attachment":"7"},{"name":"冲击效果","bone":"冲击效果","attachment":"a6"},{"name":"冲击效果2","bone":"冲击效果","attachment":"a6","blend":"additive"}],"skins":[{"name":"default","attachments":{"隔山打牛效果":{"0":{"x":141.75,"y":-8.74,"rotation":-89.6,"width":443,"height":383},"1":{"x":124.7,"y":-0.86,"rotation":-89.6,"width":246,"height":269},"2":{"x":138.69,"y":-0.26,"rotation":-89.6,"width":217,"height":297},"3":{"x":139.17,"y":2.75,"rotation":-89.6,"width":227,"height":298},"4":{"x":146.73,"y":-5.7,"rotation":-89.6,"width":202,"height":313},"5":{"x":148.24,"y":-7.19,"rotation":-89.6,"width":211,"height":314},"6":{"x":154.79,"y":-13.64,"rotation":-89.6,"width":232,"height":319},"7":{"x":41.78,"y":-13.44,"rotation":-89.6,"width":76,"height":69}},"冲击效果":{"a0":{"x":4.86,"y":-2.72,"rotation":-90.4,"width":64,"height":7},"a1":{"x":14.88,"y":-0.29,"rotation":-90.4,"width":97,"height":27},"a2":{"x":52.92,"y":4.94,"rotation":-90.4,"width":182,"height":103},"a3":{"x":59.52,"y":19.9,"rotation":-90.4,"width":280,"height":106},"a4":{"x":122.47,"y":12.96,"rotation":-90.4,"width":363,"height":206},"a5":{"x":114.06,"y":25.02,"rotation":-90.4,"width":439,"height":153},"a6":{"x":152.53,"y":20.25,"rotation":-90.4,"width":438,"height":192}},"冲击效果2":{"a0":{"x":4.86,"y":-2.72,"rotation":-90.4,"width":64,"height":7},"a1":{"x":14.88,"y":-0.29,"rotation":-90.4,"width":97,"height":27},"a2":{"x":52.92,"y":4.94,"rotation":-90.4,"width":182,"height":103},"a3":{"x":59.52,"y":19.9,"rotation":-90.4,"width":280,"height":106},"a4":{"x":122.47,"y":12.96,"rotation":-90.4,"width":363,"height":206},"a5":{"x":114.06,"y":25.02,"rotation":-90.4,"width":439,"height":153},"a6":{"x":152.53,"y":20.25,"rotation":-90.4,"width":438,"height":192}},"冲击效果3":{"a0":{"x":4.86,"y":-2.72,"rotation":-90.4,"width":64,"height":7},"a1":{"x":14.88,"y":-0.29,"rotation":-90.4,"width":97,"height":27},"a2":{"x":52.92,"y":4.94,"rotation":-90.4,"width":182,"height":103},"a3":{"x":59.52,"y":19.9,"rotation":-90.4,"width":280,"height":106},"a4":{"x":122.47,"y":12.96,"rotation":-90.4,"width":363,"height":206},"a5":{"x":114.06,"y":25.02,"rotation":-90.4,"width":439,"height":153},"a6":{"x":152.53,"y":20.25,"rotation":-90.4,"width":438,"height":192}}}}],"animations":{"animation":{"slots":{"隔山打牛效果":{"attachment":[{"time":0.0667,"name":"0"},{"time":0.1333,"name":"1"},{"time":0.2,"name":"2"},{"time":0.2667,"name":"3"},{"time":0.3333,"name":"4"},{"time":0.4,"name":"5"},{"time":0.4667,"name":null}]},"冲击效果3":{"attachment":[{"name":null},{"time":0.0667,"name":"a1"},{"time":0.1333,"name":"a2"},{"time":0.2,"name":"a3"},{"time":0.2667,"name":"a4"},{"time":0.3333,"name":"a5"},{"time":0.4,"name":"a6"},{"time":0.4667,"name":null},{"time":1,"name":null}]},"冲击效果2":{"attachment":[{"name":null},{"time":0.0667,"name":"a1"},{"time":0.1333,"name":"a2"},{"time":0.2,"name":"a3"},{"time":0.2667,"name":"a4"},{"time":0.3333,"name":"a5"},{"time":0.4,"name":"a6"},{"time":0.4667,"name":null}]},"冲击效果":{"attachment":[{"name":null},{"time":0.0667,"name":"a1"},{"time":0.1333,"name":"a2"},{"time":0.2,"name":"a3"},{"time":0.2667,"name":"a4"},{"time":0.3333,"name":"a5"},{"time":0.4,"name":"a6"},{"time":0.4667,"name":null}]}},"bones":{"冲击效果":{"translate":[{"time":0.0667,"x":-6.82,"y":71.92}],"scale":[{"time":0.0667,"x":1.082,"y":0.766}],"shear":[{"time":0.0667,"x":-6.61,"y":-2.69}]},"冲击效果2":{"translate":[{"time":0.0667,"x":-6.82,"y":71.92}],"scale":[{"time":0.0667,"x":1.407,"y":0.766}],"shear":[{"time":0.0667},{"time":0.4333,"x":-6.61,"y":-2.69}]}}}}}

@ -0,0 +1,13 @@
{
"ver": "1.2.7",
"importer": "spine-data",
"imported": true,
"uuid": "4316bb66-bc50-49dc-82fc-b44973b80528",
"files": [
".json"
],
"subMetas": {},
"userData": {
"atlasUuid": "d68878c7-e4ba-4692-a744-ee4cc6aaec63"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 KiB

@ -0,0 +1,134 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "54329a0d-1282-4c4e-ae07-05654b38f815",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "54329a0d-1282-4c4e-ae07-05654b38f815@6c48a",
"displayName": "隔山打牛",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "clamp-to-edge",
"wrapModeT": "clamp-to-edge",
"imageUuidOrDatabaseUri": "54329a0d-1282-4c4e-ae07-05654b38f815",
"isUuid": true,
"visible": false,
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
},
"f9941": {
"importer": "sprite-frame",
"uuid": "54329a0d-1282-4c4e-ae07-05654b38f815@f9941",
"displayName": "隔山打牛",
"id": "f9941",
"name": "spriteFrame",
"userData": {
"trimThreshold": 1,
"rotated": false,
"offsetX": -1,
"offsetY": -4,
"trimX": 0,
"trimY": 10,
"width": 870,
"height": 860,
"rawWidth": 872,
"rawHeight": 872,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"packable": true,
"pixelsToUnit": 100,
"pivotX": 0.5,
"pivotY": 0.5,
"meshType": 0,
"vertices": {
"rawPosition": [
-435,
-430,
0,
435,
-430,
0,
-435,
430,
0,
435,
430,
0
],
"indexes": [
0,
1,
2,
2,
1,
3
],
"uv": [
0,
862,
870,
862,
0,
2,
870,
2
],
"nuv": [
0,
0.0022935779816513763,
0.9977064220183486,
0.0022935779816513763,
0,
0.9885321100917431,
0.9977064220183486,
0.9885321100917431
],
"minPos": [
-435,
-430,
0
],
"maxPos": [
435,
430,
0
]
},
"isUuid": true,
"imageUuidOrDatabaseUri": "54329a0d-1282-4c4e-ae07-05654b38f815@6c48a",
"atlasUuid": "",
"trimType": "auto"
},
"ver": "1.0.12",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "sprite-frame",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "54329a0d-1282-4c4e-ae07-05654b38f815@6c48a"
}
}

@ -167,6 +167,8 @@ export const ICE_CONE_SPLIT_EVENT = 'IceConeSplitApplied';
export const POISON_APPLIED_EVENT = 'PoisonApplied';
/** 中毒清除表现事件名(目标上已无毒 DoT) */
export const POISON_REMOVED_EVENT = 'PoisonRemoved';
/** 隔山打牛(身后扇形)表现事件名 */
export const BEHIND_FAN_EVENT = 'BehindFanApplied';
/** 直线火龙预制体宽 100,命中半长(再加半格占地) */
const LINE_DRAGON_HALF_LEN = 50;
/** 直线火龙预制体高 30,命中半宽(再加半格占地) */
@ -210,6 +212,12 @@ export interface PoisonCue {
duration: number;
}
/** 隔山打牛表现 cue(落在命中目标坐标) */
export interface BehindFanCue {
/** 命中目标 */
target: EntityId;
}
/** 爆炸火球一枚(径向直线) */
export interface HomingDragonMissile {
/** 方向单位 X */
@ -2668,6 +2676,10 @@ export class PassiveSkillHost {
const radiusCells = radius / Math.max(1, session.grid.cellSize);
const ids = session.spatial.queryRadius(cell, radiusCells + 1);
const r2 = radius * radius;
if (target > 0) {
const cue: BehindFanCue = { target };
session.events.emit(BattleEventFactory.custom(BEHIND_FAN_EVENT, cue));
}
this._beginResultGate();
try {
for (let i = 0; i < ids.length; i++) {

@ -18,6 +18,7 @@ import { GBundle } from '../../game/ConfigRes';
import { BattleSpinePlayback } from '../presentation/BattleSpinePlayback';
import { SkillTransformDriver, computeAimAngleDeg } from '../skill/SkillTransformDriver';
import {
BEHIND_FAN_EVENT,
HOMING_DRAGON_EVENT,
ICE_CONE_SPLIT_EVENT,
LINE_DRAGON_EVENT,
@ -26,6 +27,7 @@ import {
LIGHTNING_CHAIN_EVENT,
POISON_APPLIED_EVENT,
POISON_REMOVED_EVENT,
type BehindFanCue,
type HomingDragonCue,
type IceConeSplitCue,
type LineDragonCue,
@ -100,6 +102,10 @@ const LIGHTNING_HIT_PREFAB = '电母-大招受击';
const LIGHTNING_BOLT_ANIM = '普通雷电';
/** 主链受击动画 */
const LIGHTNING_HIT_ANIM = '普通受击';
/** 隔山打牛命中特效 */
const BEHIND_FAN_PREFAB = '隔山打牛';
/** 隔山打牛 Spine 动画 */
const BEHIND_FAN_ANIM = 'animation';
/** 电弧根节点宽(锚点 x=0,scaleX=距离/此值) */
const LIGHTNING_BOLT_WIDTH = 150;
/** 相对资源原速 */
@ -123,6 +129,8 @@ export class CocosBattleCombatPresenter {
private readonly _swordWaveFx: Node[] = [];
private readonly _lightningFx: Node[] = [];
private readonly _iceConeFx: Node[] = [];
/** 隔山打牛命中特效(播完回收) */
private readonly _behindFanFx: { node: Node; endAt: number }[] = [];
private readonly _dragonFrom = new Vec3();
private readonly _dragonTo = new Vec3();
private readonly _iceConeFrom = new Vec3();
@ -146,6 +154,7 @@ export class CocosBattleCombatPresenter {
this._recycleAllSwordWaves();
this._recycleAllLightning();
this._recycleAllIceCones();
this._recycleAllBehindFan();
if (this._battle && this._listener) {
this._battle.off(BATTLE_EVENT_ALL, this._listener);
}
@ -264,6 +273,8 @@ export class CocosBattleCombatPresenter {
this._playLightningChain(event.payload as LightningChainCue | undefined);
} else if (event.name === ICE_CONE_SPLIT_EVENT) {
this._playIceConeSplit(event.payload as IceConeSplitCue | undefined);
} else if (event.name === BEHIND_FAN_EVENT) {
this._playBehindFan(event.payload as BehindFanCue | undefined);
} else if (event.name === POISON_APPLIED_EVENT) {
this._onPoisonApplied(event.payload as PoisonCue | undefined);
} else if (event.name === POISON_REMOVED_EVENT) {
@ -1012,6 +1023,97 @@ export class CocosBattleCombatPresenter {
if (node) this._recycleIceCone(node);
};
/**
* 隔山打牛:在命中怪坐标播一次特效后回收。
* @param cue 逻辑层 cue
*/
private _playBehindFan(cue: BehindFanCue | undefined): void {
const parent = this._displayRoot;
const battle = this._battle;
if (!cue || !parent?.isValid || !battle) return;
const monster = SkillPresentationEnv.getMonsterNode(cue.target);
const wp = monster?.isValid
? monster.worldPosition
: SkillPresentationEnv.getTargetGridWorldCenter(cue.target);
if (!wp) {
console.log('[CombatPresenter] 隔山打牛无落点', cue.target);
return;
}
let node: Node | null = null;
try {
node = gg.res.getNode(SWORD_ARRAY_PREFAB_PATH, BEHIND_FAN_PREFAB, GBundle.BattleHero);
} catch (err) {
console.log('[CombatPresenter] 隔山打牛 getNode 失败', String(err));
return;
}
if (!node?.isValid) {
console.log('[CombatPresenter] 隔山打牛预制体未加载', BEHIND_FAN_PREFAB);
return;
}
node.active = true;
node.layer = parent.layer;
node.angle = 0;
node.setScale(1, 1, 1);
node.setParent(parent);
node.setWorldPosition(wp);
node.setSiblingIndex(parent.children.length - 1);
const sk = node.getComponent(sp.Skeleton) ?? node.getComponentInChildren(sp.Skeleton);
if (!sk?.isValid) {
console.log('[CombatPresenter] 隔山打牛缺 Skeleton');
gg.res.putNode(node);
return;
}
if (sk.skeletonData) ensureSpineSkeletonDataRuntime(sk.skeletonData);
const delay = BattleSpinePlayback.resolveLogicalCompleteDelay(sk, BEHIND_FAN_ANIM, 1);
if (!(delay != null && delay > 0)) {
console.warn('[CombatPresenter] 隔山打牛无动画时长', BEHIND_FAN_ANIM);
gg.res.putNode(node);
return;
}
BattleSpinePlayback.play(sk, BEHIND_FAN_ANIM, { loop: false });
const endAt = battle.session.clock.time + delay;
this._behindFanFx.push({ node, endAt });
battle.session.clock.schedule(delay, this._onBehindFanExpire);
}
/** 时钟到期后回收已播完的隔山打牛 */
private readonly _onBehindFanExpire = (): void => {
this._recycleExpiredBehindFan();
};
/** 回收到期隔山打牛节点 */
private _recycleExpiredBehindFan(): void {
const now = this._battle?.session.clock.time ?? Number.POSITIVE_INFINITY;
for (let i = this._behindFanFx.length - 1; i >= 0; i--) {
if (this._behindFanFx[i].endAt <= now + 0.001) {
this._recycleBehindFanNode(this._behindFanFx[i].node);
this._behindFanFx.splice(i, 1);
}
}
}
/** 回收全部隔山打牛特效 */
private _recycleAllBehindFan(): void {
for (let i = 0; i < this._behindFanFx.length; i++) {
this._recycleBehindFanNode(this._behindFanFx[i].node);
}
this._behindFanFx.length = 0;
}
/**
* 停动画并回池。
* @param node 特效节点
*/
private _recycleBehindFanNode(node: Node): void {
if (!node?.isValid) return;
const sk = node.getComponent(sp.Skeleton) ?? node.getComponentInChildren(sp.Skeleton);
BattleSpinePlayback.clearPendingComplete(sk);
BattleSpinePlayback.resetTracks(sk);
node.angle = 0;
node.setScale(1, 1, 1);
gg.res.putNode(node);
}
/** 回收全部分裂冰锥表现 */
private _recycleAllIceCones(): void {
for (let i = this._iceConeFx.length - 1; i >= 0; i--) {

@ -29,7 +29,7 @@
| 16 | 秒杀 | `tryInstantKillSession` |
| 17 | 上毒 | 复用 result 8 DoT |
| 18 | 寒潭减速 | `PassiveSkillHost` 地面区 |
| 19 | 目标身后扇形 | 向量扇形圈伤 |
| 19 | 目标身后扇形 | 向量扇形圈伤;命中点播 `隔山打牛` 特效一次 |
| 20 | 击杀叠伤 | `dmg_mul` 叠层 |
| 21 | 该次伤害必暴+暴击转爆伤 | 伤害预调(配合 condition 7/8) |

Loading…
Cancel
Save