|
|
|
@ -1,5 +1,5 @@ |
|
|
|
import { |
|
|
|
import { |
|
|
|
_decorator, Button, Canvas, Component, instantiate, Label, Node, Rect, Sprite, Tween, tween, UIOpacity, UITransform, Vec3, view, Widget, |
|
|
|
_decorator, Button, Canvas, Component, instantiate, Label, Node, Rect, sp, Sprite, Tween, tween, UIOpacity, UITransform, Vec3, view, Widget, |
|
|
|
} from 'cc'; |
|
|
|
} from 'cc'; |
|
|
|
import { SpriteLoad } from 'db://assets/mx/components/SpriteLoad'; |
|
|
|
import { SpriteLoad } from 'db://assets/mx/components/SpriteLoad'; |
|
|
|
import { GBundle } from '../../game/ConfigRes'; |
|
|
|
import { GBundle } from '../../game/ConfigRes'; |
|
|
|
@ -8,6 +8,7 @@ import type { ProjectBattleHandle } from '../../battle/runtime/BattleRuntime'; |
|
|
|
import type { EntityId } from 'db://assets/mx/module/ecs'; |
|
|
|
import type { EntityId } from 'db://assets/mx/module/ecs'; |
|
|
|
import type { WeaponDropRecord } from '../../battle/combat/WeaponDropService'; |
|
|
|
import type { WeaponDropRecord } from '../../battle/combat/WeaponDropService'; |
|
|
|
import { BattleAudio } from '../../battle/audio/BattleAudio'; |
|
|
|
import { BattleAudio } from '../../battle/audio/BattleAudio'; |
|
|
|
|
|
|
|
import { BattleSpinePlayback } from '../../battle/presentation/BattleSpinePlayback'; |
|
|
|
|
|
|
|
|
|
|
|
const { ccclass } = _decorator; |
|
|
|
const { ccclass } = _decorator; |
|
|
|
|
|
|
|
|
|
|
|
@ -21,6 +22,10 @@ const ICON_NODE = '图标'; |
|
|
|
const QUALITY_ROOT = '品质'; |
|
|
|
const QUALITY_ROOT = '品质'; |
|
|
|
/** 品质子节点档位数 */ |
|
|
|
/** 品质子节点档位数 */ |
|
|
|
const QUALITY_MAX = 4; |
|
|
|
const QUALITY_MAX = 4; |
|
|
|
|
|
|
|
/** 品质光柱正式动画(Spine 另含美术误导出的「效果预览」,禁止播放) */ |
|
|
|
|
|
|
|
const QUALITY_DROP_ANIM = 'animation'; |
|
|
|
|
|
|
|
/** 品质光柱禁用动画名 */ |
|
|
|
|
|
|
|
const QUALITY_PREVIEW_ANIM = '效果预览'; |
|
|
|
/** 结算模板图标子节点名(ui_gemTemp/icon) */ |
|
|
|
/** 结算模板图标子节点名(ui_gemTemp/icon) */ |
|
|
|
const SETTLE_ICON_NODE = 'icon'; |
|
|
|
const SETTLE_ICON_NODE = 'icon'; |
|
|
|
/** 碎片数量底节点名 */ |
|
|
|
/** 碎片数量底节点名 */ |
|
|
|
@ -46,6 +51,8 @@ const SCREEN_PAD = 8; |
|
|
|
const FLY_SEC = 0.55; |
|
|
|
const FLY_SEC = 0.55; |
|
|
|
/** 飞入终点相对预制体基准 scale 的倍率 */ |
|
|
|
/** 飞入终点相对预制体基准 scale 的倍率 */ |
|
|
|
const FLY_END_SCALE_MUL = 0.45; |
|
|
|
const FLY_END_SCALE_MUL = 0.45; |
|
|
|
|
|
|
|
/** 「宝石掉落」预制体根设计 scale(与 prefab `_lscale` 一致;池基准缺失时兜底) */ |
|
|
|
|
|
|
|
const DROP_PREFAB_SCALE = 0.5; |
|
|
|
/** 到达后渐隐时长 */ |
|
|
|
/** 到达后渐隐时长 */ |
|
|
|
const FADE_SEC = 0.18; |
|
|
|
const FADE_SEC = 0.18; |
|
|
|
|
|
|
|
|
|
|
|
@ -283,7 +290,7 @@ export class WeaponDropView extends Component { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 切换「品质」下 1~4 子节点(表品质 5 钳到 4)。 |
|
|
|
* 切换「品质」下 1~4 子节点(表品质 5 钳到 4),并强制播正式光柱动画。 |
|
|
|
* @param node 掉落根 |
|
|
|
* @param node 掉落根 |
|
|
|
* @param quality Weapon.quality |
|
|
|
* @param quality Weapon.quality |
|
|
|
* @param weaponId 宝石 id(日志) |
|
|
|
* @param weaponId 宝石 id(日志) |
|
|
|
@ -304,7 +311,40 @@ export class WeaponDropView extends Component { |
|
|
|
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; |
|
|
|
child.active = child.name === name; |
|
|
|
const on = child.name === name; |
|
|
|
|
|
|
|
if (on) WeaponDropView._prepareQualityDropAnim(child); |
|
|
|
|
|
|
|
child.active = on; |
|
|
|
|
|
|
|
if (on) WeaponDropView._playQualityDropAnim(child, weaponId); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* 激活前写入 `animation`,避免 onEnable 误播「效果预览」。 |
|
|
|
|
|
|
|
* @param qualityNode 品质子节点 1~4 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private static _prepareQualityDropAnim(qualityNode: Node): void { |
|
|
|
|
|
|
|
const sk = qualityNode.getComponent(sp.Skeleton) ?? qualityNode.getComponentInChildren(sp.Skeleton); |
|
|
|
|
|
|
|
if (!sk?.isValid) return; |
|
|
|
|
|
|
|
sk.loop = true; |
|
|
|
|
|
|
|
sk.animation = QUALITY_DROP_ANIM; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* 品质光柱只播 animation,避开「效果预览」。 |
|
|
|
|
|
|
|
* @param qualityNode 品质子节点 1~4 |
|
|
|
|
|
|
|
* @param weaponId 宝石 id(日志) |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private static _playQualityDropAnim(qualityNode: Node, weaponId: number): void { |
|
|
|
|
|
|
|
const sk = qualityNode.getComponent(sp.Skeleton) ?? qualityNode.getComponentInChildren(sp.Skeleton); |
|
|
|
|
|
|
|
if (!sk?.isValid) { |
|
|
|
|
|
|
|
console.warn('[WeaponDrop] 品质缺少 Spine', weaponId, qualityNode.name); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
sk.paused = false; |
|
|
|
|
|
|
|
sk.loop = true; |
|
|
|
|
|
|
|
sk.animation = QUALITY_DROP_ANIM; |
|
|
|
|
|
|
|
if (!BattleSpinePlayback.play(sk, QUALITY_DROP_ANIM, { loop: true, optional: true })) { |
|
|
|
|
|
|
|
console.warn('[WeaponDrop] 品质动画缺失', QUALITY_DROP_ANIM, weaponId, qualityNode.name, QUALITY_PREVIEW_ANIM); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -556,6 +596,8 @@ export class WeaponDropView extends Component { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
Tween.stopAllByTarget(node); |
|
|
|
Tween.stopAllByTarget(node); |
|
|
|
|
|
|
|
// 先回到基准再飞入缩小,避免以上一次飞入末态为起点连乘
|
|
|
|
|
|
|
|
this._restorePrefabScale(); |
|
|
|
const base = this._prefabBaseScale(); |
|
|
|
const base = this._prefabBaseScale(); |
|
|
|
tween(node) |
|
|
|
tween(node) |
|
|
|
.to( |
|
|
|
.to( |
|
|
|
@ -591,7 +633,7 @@ export class WeaponDropView extends Component { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 预制体根设计 scale(出池时 ResourcesManager 写入 poolBaseScale)。 |
|
|
|
* 预制体根设计 scale(出池时 ResourcesManager 写入 poolBaseScale)。 |
|
|
|
* 禁止统一洗成 1,否则改预制体缩放无效。 |
|
|
|
* 禁止回退到当前 scale:飞入后已缩小,会把基准越写越小。 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private _prefabBaseScale(): { x: number; y: number } { |
|
|
|
private _prefabBaseScale(): { x: number; y: number } { |
|
|
|
const n = this.node; |
|
|
|
const n = this.node; |
|
|
|
@ -601,11 +643,10 @@ export class WeaponDropView extends Component { |
|
|
|
return { x: sx, y: sy }; |
|
|
|
return { x: sx, y: sy }; |
|
|
|
} |
|
|
|
} |
|
|
|
if (n?.isValid) { |
|
|
|
if (n?.isValid) { |
|
|
|
const cx = n.scale.x; |
|
|
|
n['poolBaseScaleX'] = DROP_PREFAB_SCALE; |
|
|
|
const cy = n.scale.y; |
|
|
|
n['poolBaseScaleY'] = DROP_PREFAB_SCALE; |
|
|
|
if (cx > 0 && cy > 0) return { x: cx, y: cy }; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return { x: 1, y: 1 }; |
|
|
|
return { x: DROP_PREFAB_SCALE, y: DROP_PREFAB_SCALE }; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** 恢复为预制体基准缩放 */ |
|
|
|
/** 恢复为预制体基准缩放 */ |
|
|
|
@ -615,6 +656,11 @@ export class WeaponDropView extends Component { |
|
|
|
this.node.setScale(base.x, base.y, 1); |
|
|
|
this.node.setScale(base.x, base.y, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 停动画并恢复基准缩放后回池(unbind 清场用) */ |
|
|
|
|
|
|
|
recycleToPool(): void { |
|
|
|
|
|
|
|
this._recycle(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 设置透明度。 |
|
|
|
* 设置透明度。 |
|
|
|
* @param value 0~255 |
|
|
|
* @param value 0~255 |
|
|
|
@ -721,8 +767,10 @@ export class BattleWeaponDropPresenter { |
|
|
|
const node = children[i]; |
|
|
|
const node = children[i]; |
|
|
|
if (!node?.isValid) continue; |
|
|
|
if (!node?.isValid) continue; |
|
|
|
const view = node.getComponent(WeaponDropView); |
|
|
|
const view = node.getComponent(WeaponDropView); |
|
|
|
if (!view) continue; |
|
|
|
if (view) { |
|
|
|
view.resetMotion(); |
|
|
|
view.recycleToPool(); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
gg.res.putNode(node); |
|
|
|
gg.res.putNode(node); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|