|
|
|
|
@ -150,6 +150,8 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
private _illustratedHintShownThisBattle = false; |
|
|
|
|
/** 桃 UI 缓存,避免每帧写 Label */ |
|
|
|
|
private _peachUiGold = -1; |
|
|
|
|
/** 已入账、飞币未到 btnCoin 的金币(显示暂不计入) */ |
|
|
|
|
private _peachUiPendingFly = 0; |
|
|
|
|
/** 召唤消耗缓存 */ |
|
|
|
|
private _peachUiCost = -1; |
|
|
|
|
/** 金币广告已用次数缓存 */ |
|
|
|
|
@ -297,6 +299,7 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
this._coinAdVideoIcon = this.btnCoin?.getChildByName('视频标') ?? null; |
|
|
|
|
this._waveUiIdx = -999; |
|
|
|
|
this._peachUiGold = -1; |
|
|
|
|
this._peachUiPendingFly = 0; |
|
|
|
|
this._peachUiCost = -1; |
|
|
|
|
this._peachUiCoinAdUsed = -1; |
|
|
|
|
this._refreshPeachUi(); |
|
|
|
|
@ -427,6 +430,7 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
console.error('[UIBattleGame] AiBattleBridge.start 异常', String(e)); |
|
|
|
|
} |
|
|
|
|
this._bindUnlockCoinFly(battle); |
|
|
|
|
this._bindGlyphRecycleGold(battle); |
|
|
|
|
this._bindBattleBuffSelect(battle); |
|
|
|
|
this._bindPeerMapToolApplied(battle); |
|
|
|
|
this._bindDigChest(map); |
|
|
|
|
@ -529,7 +533,7 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
const gold = this._waveSettleGold(); |
|
|
|
|
if (!(gold > 0)) return; |
|
|
|
|
battle.addPlayerGold(battle.localPlayerId, gold); |
|
|
|
|
this._refreshPeachUi(); |
|
|
|
|
this._holdPeachUiForFly(gold); |
|
|
|
|
this._playWaveSettleCoin(gold); |
|
|
|
|
this._grantWaveGoldToOthers(gold); |
|
|
|
|
} |
|
|
|
|
@ -607,11 +611,13 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
} |
|
|
|
|
this._ensurePeachCoinFly(); |
|
|
|
|
if (!layer.active) layer.active = true; |
|
|
|
|
this._peachCoinFly?.playWaveCoin(layer, layer.worldPosition, show, count); |
|
|
|
|
this._peachCoinFly?.playWaveCoin(layer, layer.worldPosition, show, count, () => { |
|
|
|
|
this._releasePeachUiAfterFly(gold); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 击杀掉桃表现:本机飞向 ui_money;AI 归属原地弹跳(金已入 AI 槽)。 |
|
|
|
|
* 击杀掉桃表现:本机飞向 btnCoin;AI 归属原地弹跳(金已入 AI 槽)。 |
|
|
|
|
* @param killer 击杀者 |
|
|
|
|
* @param victim 死亡实体 |
|
|
|
|
*/ |
|
|
|
|
@ -628,12 +634,50 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
} |
|
|
|
|
const ownerId = battle.resolveKillPeachOwnerPlayerId(killer, victim); |
|
|
|
|
if (ownerId === battle.localPlayerId) { |
|
|
|
|
fly.playKillDrop(from, peach); |
|
|
|
|
this._playLocalCoinFly(from, peach); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
fly.playKillDropLocal(from, peach); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 本机飞币:入账已发生,挂起 UI 数字,到达 btnCoin 后再显示。 |
|
|
|
|
* @param fromWorld 起点 |
|
|
|
|
* @param amount 本次金币 |
|
|
|
|
*/ |
|
|
|
|
private _playLocalCoinFly(fromWorld: Readonly<Vec3>, amount: number): void { |
|
|
|
|
const gold = Math.floor(Number(amount) || 0); |
|
|
|
|
if (!(gold > 0)) return; |
|
|
|
|
this._ensurePeachCoinFly(); |
|
|
|
|
this._holdPeachUiForFly(gold); |
|
|
|
|
const fly = this._peachCoinFly; |
|
|
|
|
if (!fly) { |
|
|
|
|
this._releasePeachUiAfterFly(gold); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
fly.playKillDrop(fromWorld, gold, () => this._releasePeachUiAfterFly(gold)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 飞币未到前暂不把新增金币画到 lb_coin。 |
|
|
|
|
* @param amount 本次挂起数量 |
|
|
|
|
*/ |
|
|
|
|
private _holdPeachUiForFly(amount: number): void { |
|
|
|
|
const n = Math.floor(Number(amount) || 0); |
|
|
|
|
if (!(n > 0)) return; |
|
|
|
|
this._peachUiPendingFly += n; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 飞币到达后解除挂起并刷新 lb_coin。 |
|
|
|
|
* @param amount 本次解除数量 |
|
|
|
|
*/ |
|
|
|
|
private _releasePeachUiAfterFly(amount: number): void { |
|
|
|
|
const n = Math.floor(Number(amount) || 0); |
|
|
|
|
if (n > 0) this._peachUiPendingFly = Math.max(0, this._peachUiPendingFly - n); |
|
|
|
|
this._refreshPeachUi(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 击杀时怪物世界坐标(节点优先,否则 presenter 缓存)。 |
|
|
|
|
* @param victim 死亡实体 |
|
|
|
|
@ -714,6 +758,7 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
console.log('[UIBattleGame] ui_delete 缺失,无法拖字删除'); |
|
|
|
|
} |
|
|
|
|
this._bagView.setDeleteNode(this.ui_delete); |
|
|
|
|
this._bagView.setRecycleGoldFxHandler(this._onRecycleGoldFx); |
|
|
|
|
// bind() 开头会 unbind,入场回调必须在 bind 之后再挂
|
|
|
|
|
this._bagView.setOtherBagAnchor(this.ui_otherBag); |
|
|
|
|
this._bagView.setInkstoneWorldPosProvider(this._inkstoneWorldPos); |
|
|
|
|
@ -833,9 +878,7 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
* @param fromWorld 金矿图标世界坐标 |
|
|
|
|
*/ |
|
|
|
|
private readonly _onGoldMineCoinFly = (fromWorld: Readonly<Vec3>): void => { |
|
|
|
|
this._ensurePeachCoinFly(); |
|
|
|
|
this._peachCoinFly?.playKillDrop(fromWorld, 1); |
|
|
|
|
this._refreshPeachUi(); |
|
|
|
|
this._playLocalCoinFly(fromWorld, 1); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** AI 金矿飞币:敌方被动金矿图标原地弹跳 */ |
|
|
|
|
@ -872,6 +915,50 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 数字拖垃圾桶回收:金币入账后刷新 UI;飞币等字飞到垃圾桶后再播。 |
|
|
|
|
* @param battle 战斗 |
|
|
|
|
*/ |
|
|
|
|
private _bindGlyphRecycleGold(battle: ProjectBattleHandle): void { |
|
|
|
|
this._ensurePeachCoinFly(); |
|
|
|
|
if (battle.bagSession) { |
|
|
|
|
battle.bagSession.onGlyphRecycleGold = this._onGlyphRecycleGold; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 回收金币已入账:先挂起 UI,飞币到垃圾桶后再播(见 `_onRecycleGoldFx`)。 |
|
|
|
|
* @param gold Const39 数量 |
|
|
|
|
* @param ownerPlayerId 归属 |
|
|
|
|
*/ |
|
|
|
|
private readonly _onGlyphRecycleGold = (gold: number, ownerPlayerId: number): void => { |
|
|
|
|
if (!(gold > 0)) return; |
|
|
|
|
const battle = this._battle; |
|
|
|
|
if (ownerPlayerId !== (battle?.localPlayerId ?? 0)) return; |
|
|
|
|
this._holdPeachUiForFly(gold); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 字飞到垃圾桶后:从 ui_delete 弹跳飞向 btnCoin,到达后刷新数字。 |
|
|
|
|
* @param gold Const39 数量 |
|
|
|
|
*/ |
|
|
|
|
private readonly _onRecycleGoldFx = (gold: number): void => { |
|
|
|
|
if (!(gold > 0)) return; |
|
|
|
|
this._ensurePeachCoinFly(); |
|
|
|
|
const from = this.ui_delete?.isValid ? this.ui_delete.worldPosition.clone() : null; |
|
|
|
|
if (!from) { |
|
|
|
|
console.warn('[UIBattleGame] 回收金币缺少 ui_delete 坐标'); |
|
|
|
|
this._releasePeachUiAfterFly(gold); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
const fly = this._peachCoinFly; |
|
|
|
|
if (!fly) { |
|
|
|
|
this._releasePeachUiAfterFly(gold); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
fly.playKillDrop(from, gold, () => this._releasePeachUiAfterFly(gold)); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 地图解锁达 Const27 次数:本机弹三选一,AI 自动选。 |
|
|
|
|
* @param battle 战斗 |
|
|
|
|
@ -1012,12 +1099,12 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
const fly = this._peachCoinFly; |
|
|
|
|
const from = this._bagView?.getMapGridWorldPosition(gridIndex); |
|
|
|
|
if (ownerPlayerId === battle?.localPlayerId) { |
|
|
|
|
this._refreshPeachUi(); |
|
|
|
|
if (!from) { |
|
|
|
|
console.log('[UIBattleGame] 寻金尺无飞币坐标', gridIndex); |
|
|
|
|
this._refreshPeachUi(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
fly?.playKillDrop(from, coin); |
|
|
|
|
this._playLocalCoinFly(from, coin); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (!from) { |
|
|
|
|
@ -1028,7 +1115,7 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 技能产桃:本机 coinFly 飞向 ui_money;敌方格心 coinFly 原地弹跳后回池。 |
|
|
|
|
* 技能产桃:本机飞到 btnCoin 后再入账刷新;敌方格心原地弹跳。 |
|
|
|
|
* @param gridIndex 施法格 |
|
|
|
|
* @param peachCount 蟠桃数量 |
|
|
|
|
*/ |
|
|
|
|
@ -1041,10 +1128,19 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
if (!from) { |
|
|
|
|
console.log('[UIBattleGame] 产桃坐标缺失', gridIndex, ownerPlayerId); |
|
|
|
|
bagView?.grantBattlePeach(peachCount); |
|
|
|
|
this._refreshPeachUi(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
this._ensurePeachCoinFly(); |
|
|
|
|
if (!fly) { |
|
|
|
|
bagView?.grantBattlePeach(peachCount); |
|
|
|
|
this._refreshPeachUi(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
fly?.playKillDrop(from, peachCount); |
|
|
|
|
bagView?.grantBattlePeach(peachCount); |
|
|
|
|
fly.playKillDrop(from, peachCount, () => { |
|
|
|
|
bagView?.grantBattlePeach(peachCount); |
|
|
|
|
this._refreshPeachUi(); |
|
|
|
|
}); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (battle && ownerPlayerId >= 0) { |
|
|
|
|
@ -1064,8 +1160,7 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
this._killPeach = new BattleGameKillPeachPresenter(); |
|
|
|
|
this._killPeach.bind( |
|
|
|
|
battle, |
|
|
|
|
this._bagView, |
|
|
|
|
this._peachCoinFly, |
|
|
|
|
(from, amount) => this._playLocalCoinFly(from, amount), |
|
|
|
|
(victim) => this._monsterDeathWorldPos(victim), |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
@ -1144,23 +1239,24 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
const battle = this._battle; |
|
|
|
|
if (!battle) return; |
|
|
|
|
|
|
|
|
|
const gold = battle.localGold; |
|
|
|
|
const realGold = battle.localGold; |
|
|
|
|
const showGold = Math.max(0, realGold - this._peachUiPendingFly); |
|
|
|
|
const cost = battle.bagSession |
|
|
|
|
? battle.bagSession.normalRefreshCost |
|
|
|
|
: getDiscountedBagNormalRefreshCost(0, resolveCarriedSummonCostReduceWan().reduceWan); |
|
|
|
|
const coinAdUsed = battle.coinAdUsed; |
|
|
|
|
if (gold === this._peachUiGold && cost === this._peachUiCost && coinAdUsed === this._peachUiCoinAdUsed) return; |
|
|
|
|
this._peachUiGold = gold; |
|
|
|
|
if (showGold === this._peachUiGold && cost === this._peachUiCost && coinAdUsed === this._peachUiCoinAdUsed) return; |
|
|
|
|
this._peachUiGold = showGold; |
|
|
|
|
this._peachUiCost = cost; |
|
|
|
|
this._peachUiCoinAdUsed = coinAdUsed; |
|
|
|
|
if (this.lb_coin?.isValid) { |
|
|
|
|
this.lb_coin.string = `${gold}`; |
|
|
|
|
this.lb_coin.string = `${showGold}`; |
|
|
|
|
} |
|
|
|
|
this._syncCoinAdUi(battle); |
|
|
|
|
if (this.lb_RefreshNeed?.isValid) { |
|
|
|
|
this.lb_RefreshNeed.string = `${cost}`; |
|
|
|
|
} |
|
|
|
|
const enough = cost <= 0 || gold >= cost; |
|
|
|
|
const enough = cost <= 0 || realGold >= cost; |
|
|
|
|
this._showRefreshBg1(enough); |
|
|
|
|
this._syncRefreshBounce(enough); |
|
|
|
|
} |
|
|
|
|
@ -1387,12 +1483,14 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
AiBattleBridge.inst.setGoldMineCoinFlyHandler(null); |
|
|
|
|
if (this._battle?.bagSession) { |
|
|
|
|
this._battle.bagSession.onUnlockCoinFly = null; |
|
|
|
|
this._battle.bagSession.onGlyphRecycleGold = null; |
|
|
|
|
this._battle.bagSession.onBattleBuffSelect = null; |
|
|
|
|
this._battle.bagSession.onPeerMapToolApplied = null; |
|
|
|
|
} |
|
|
|
|
const aiBagTeardown = AiBattleBridge.inst.aiBagSession; |
|
|
|
|
if (aiBagTeardown) { |
|
|
|
|
aiBagTeardown.onUnlockCoinFly = null; |
|
|
|
|
aiBagTeardown.onGlyphRecycleGold = null; |
|
|
|
|
aiBagTeardown.onBattleBuffSelect = null; |
|
|
|
|
aiBagTeardown.onPeerMapToolApplied = null; |
|
|
|
|
} |
|
|
|
|
@ -1444,6 +1542,7 @@ export class UIBattleGame extends Auto_BattleGame { |
|
|
|
|
this._refreshBounceHinted = false; |
|
|
|
|
this._illustratedHintShownThisBattle = false; |
|
|
|
|
this._peachUiGold = -1; |
|
|
|
|
this._peachUiPendingFly = 0; |
|
|
|
|
this._peachUiCost = -1; |
|
|
|
|
this._peachUiCoinAdUsed = -1; |
|
|
|
|
this._coinAdVideoIcon = null; |
|
|
|
|
|