You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
583 lines
22 KiB
583 lines
22 KiB
|
|
//*********************
|
|
// create by 流云
|
|
// time: Wed Aug 19 2026
|
|
// desc: 结算后每日buff购买(抽奖已拆至 PopDailyShopLottery)
|
|
//*********************
|
|
import { _decorator, Color, EventTouch, instantiate, Label, Layout, Node, Sprite, v3 } from 'cc';
|
|
import { Auto_PopDailyShopBuy } from './Auto_PopDailyShopBuy';
|
|
import { DailyShopBuySkillFlyPresenter } from './DailyShopBuySkillFlyPresenter';
|
|
import { DailyShopLotteryIcon, DailyShopOwnedDesc } from '../PopDailyShopLottery/DailyShopLotteryIcon';
|
|
import { GEvent } from '../../../mx/module/event/GEvent';
|
|
import { UIID } from '../../game/ConfigRes';
|
|
import { ItemNumType } from '../../game/GameData';
|
|
import { DailyShopDataManager } from '../../manager/DailyShopDataManager';
|
|
import { PopReplaceSkillParam } from '../PopReplaceSkill/UIPopReplaceSkill';
|
|
import { PopToastType } from '../PopToast/UIPopToast';
|
|
import {
|
|
DailyShopGoods,
|
|
DailyShopKind,
|
|
DailyShopParsed,
|
|
DailyShopPurchaseFail,
|
|
DailyShopPurchaseResult,
|
|
dailyShopFailReason,
|
|
isDailyShopNeedReplace,
|
|
} from '../../manager/DailyShopTypes';
|
|
import { RankReport } from '../../manager/RankReport';
|
|
const { ccclass } = _decorator;
|
|
|
|
const BUY_USED_TIP = '商品已售罄,欢迎下次光临!';
|
|
|
|
/** 商店物品名称描边色(按品质) */
|
|
const SHOP_NAME_OUTLINE_HEX: Record<number, string> = {
|
|
1: '#386c42',
|
|
2: '#285c6d',
|
|
3: '#623073',
|
|
4: '#734930',
|
|
};
|
|
|
|
@ccclass('UIPopDailyShopBuy')
|
|
export class UIPopDailyShopBuy extends Auto_PopDailyShopBuy {
|
|
|
|
private _busy = false;
|
|
private _ownedDesc: DailyShopOwnedDesc | null = null;
|
|
private _skillFly: DailyShopBuySkillFlyPresenter | null = null;
|
|
|
|
onLoad(): void {
|
|
super.onLoad();
|
|
this._skillFly = new DailyShopBuySkillFlyPresenter();
|
|
this._skillFly.bind(this.ui_center);
|
|
if (this.ui_shopItem?.isValid) this.ui_shopItem.active = false;
|
|
if (this.ui_skillMainItem?.isValid) this.ui_skillMainItem.active = false;
|
|
if (this.ui_skillPassiveItem?.isValid) this.ui_skillPassiveItem.active = false;
|
|
if (this.ui_emptySkillMainItem?.isValid) this.ui_emptySkillMainItem.active = false;
|
|
if (this.ui_emptySkillPassiveItem?.isValid) this.ui_emptySkillPassiveItem.active = false;
|
|
if (this.ui_descLeft?.isValid || this.ui_descRight?.isValid) {
|
|
this._ownedDesc = new DailyShopOwnedDesc(this.ui_descLeft, this.ui_descRight);
|
|
this._ownedDesc.init();
|
|
}
|
|
}
|
|
|
|
onEnable(): void {
|
|
super.onEnable();
|
|
this._ownedDesc?.bindDismiss();
|
|
GEvent.Ins.on(GEvent.DailyShopOffersRefresh, this._onOffersRefresh, this);
|
|
GEvent.Ins.on(GEvent.UpdateItemNum, this._onItemNumChange, this);
|
|
void this._refreshView();
|
|
}
|
|
|
|
onDisable(): void {
|
|
GEvent.Ins.off(GEvent.DailyShopOffersRefresh, this._onOffersRefresh, this);
|
|
GEvent.Ins.off(GEvent.UpdateItemNum, this._onItemNumChange, this);
|
|
this._ownedDesc?.unbindDismiss();
|
|
this._skillFly?.unbind();
|
|
super.onDisable();
|
|
}
|
|
|
|
onInit(): void {
|
|
this._busy = false;
|
|
this.showOpenCenterEff();
|
|
this.showOpenMaskEff(2);
|
|
void this._resetAndShow();
|
|
}
|
|
|
|
click_btnClose(): void {
|
|
void this._closeThenTryLottery();
|
|
}
|
|
|
|
/** 先关购买窗,再按概率链式弹抽奖(避免队列被当前窗阻塞 + 0.5s 轮询延迟) */
|
|
private async _closeThenTryLottery(): Promise<void> {
|
|
await this.close(2);
|
|
DailyShopDataManager.tryPopLotteryAfterBuyClose();
|
|
gg.ui.flushPopQueue();
|
|
}
|
|
|
|
private async _resetAndShow(): Promise<void> {
|
|
await DailyShopDataManager.ensureTable();
|
|
if (!this.isValid) return;
|
|
DailyShopDataManager.ensureToday();
|
|
await this._refreshView();
|
|
const pendingId = DailyShopDataManager.getPendingReplaceGoodsId();
|
|
if (pendingId > 0) this._askReplace(pendingId);
|
|
}
|
|
|
|
private _onOffersRefresh(offers: DailyShopGoods[]): void {
|
|
if (!this.isValid) return;
|
|
if (this._busy) return;
|
|
this._renderOwnedSkills();
|
|
this._renderOffers(offers);
|
|
}
|
|
|
|
private _onItemNumChange(itemId?: number): void {
|
|
if (itemId != null && itemId !== ItemNumType.money) return;
|
|
if (this._busy) return;
|
|
if (!this.isValid || !this.ui_shopContent?.isValid || !this.ui_shopItem?.isValid) return;
|
|
this._renderOffers(DailyShopDataManager.getOffers());
|
|
}
|
|
|
|
private async _refreshView(): Promise<void> {
|
|
await DailyShopDataManager.ensureTable();
|
|
if (!this.isValid) return;
|
|
this._renderOwnedSkills();
|
|
this._renderOffers(DailyShopDataManager.getOffers());
|
|
}
|
|
|
|
private _renderOffers(offers: DailyShopGoods[]): void {
|
|
if (!this.ui_shopContent?.isValid || !this.ui_shopItem?.isValid) return;
|
|
this.ui_shopContent.removeAllChildren();
|
|
for (const goods of offers) {
|
|
const item = instantiate(this.ui_shopItem);
|
|
item.active = true;
|
|
item.setPosition(v3(0, 0, 0));
|
|
item.parent = this.ui_shopContent;
|
|
this._bindShopItem(item, goods);
|
|
}
|
|
this.ui_shopContent.getComponent(Layout)?.updateLayout();
|
|
}
|
|
|
|
private _renderOwnedSkills(hideSlot?: { kind: DailyShopKind; slotIndex: number }): void {
|
|
this._ownedDesc?.hide();
|
|
const { active, passive } = DailyShopDataManager.getSlotCaps();
|
|
this._fillSkillSlots(
|
|
this.ui_skillMain,
|
|
this.ui_skillMainItem,
|
|
this.ui_emptySkillMainItem,
|
|
DailyShopDataManager.getActiveSlotIds(),
|
|
active,
|
|
DailyShopKind.Active,
|
|
hideSlot?.kind === DailyShopKind.Active ? hideSlot.slotIndex : -1,
|
|
);
|
|
this._fillSkillSlots(
|
|
this.ui_skillPassive,
|
|
this.ui_skillPassiveItem,
|
|
this.ui_emptySkillPassiveItem,
|
|
DailyShopDataManager.getPassiveSlotIds(),
|
|
passive,
|
|
DailyShopKind.Passive,
|
|
hideSlot?.kind === DailyShopKind.Passive ? hideSlot.slotIndex : -1,
|
|
);
|
|
}
|
|
|
|
private _fillSkillSlots(
|
|
container: Node | null | undefined,
|
|
template: Node | null | undefined,
|
|
emptyTemplate: Node | null | undefined,
|
|
slotIds: number[],
|
|
slotCount: number,
|
|
kind: DailyShopKind,
|
|
hideSlotIndex = -1,
|
|
): void {
|
|
if (!container?.isValid || !template?.isValid || slotCount <= 0) {
|
|
container?.removeAllChildren();
|
|
return;
|
|
}
|
|
container.removeAllChildren();
|
|
for (let i = 0; i < slotCount; i++) {
|
|
// 始终显示空模板作为底
|
|
const base = emptyTemplate?.isValid ? instantiate(emptyTemplate) : null;
|
|
if (base) {
|
|
base.active = true;
|
|
base.setPosition(v3(0, 0, 0));
|
|
base.parent = container;
|
|
}
|
|
// 有技能则叠在空模板上面
|
|
const id = Number(slotIds[i]) || 0;
|
|
const parsed = id > 0 ? DailyShopDataManager.getParsed(id) : null;
|
|
if (parsed && i !== hideSlotIndex) {
|
|
const item = instantiate(template);
|
|
item.active = true;
|
|
item.setPosition(v3(0, 0, 0));
|
|
item.parent = base ?? container;
|
|
DailyShopLotteryIcon.bindSlotItem(item, parsed, kind);
|
|
this._ownedDesc?.bindSlotItem(item, parsed, kind);
|
|
this._bindDeleteBtn(item, kind, i);
|
|
}
|
|
}
|
|
container.getComponent(Layout)?.updateLayout();
|
|
}
|
|
|
|
private _bindDeleteBtn(item: Node, kind: DailyShopKind, slotIndex: number): void {
|
|
const deleteBtn = item.getChildByName('deleteBtn');
|
|
if (!deleteBtn?.isValid) return;
|
|
deleteBtn.active = true;
|
|
deleteBtn.setPosition(v3(32, 32, 0));
|
|
deleteBtn.setSiblingIndex(item.children.length - 1);
|
|
const deleteIcon = deleteBtn.getChildByName('icon');
|
|
// 预制体已内置删除图标 spriteFrame,勿再动态加载不存在的 popCommon 路径
|
|
if (deleteIcon?.isValid) {
|
|
deleteIcon.active = true;
|
|
}
|
|
deleteBtn['dailyShopSlotKind'] = kind;
|
|
deleteBtn['dailyShopSlotIndex'] = slotIndex;
|
|
deleteBtn.targetOff(Node.EventType.TOUCH_END);
|
|
deleteBtn.on(Node.EventType.TOUCH_END, this._onClickDeleteSlot, this);
|
|
}
|
|
|
|
private _onClickDeleteSlot(event: EventTouch): void {
|
|
if (this._busy) return;
|
|
const btn = event.currentTarget as Node;
|
|
const kind = Number(btn?.['dailyShopSlotKind']) as DailyShopKind;
|
|
const slotIndex = Number(btn?.['dailyShopSlotIndex']) || 0;
|
|
const name = this._getSlotGoodsName(kind, slotIndex);
|
|
gg.game.showPopToast(
|
|
`你确定要删除${name}道具吗?`,
|
|
PopToastType.DeleteItem,
|
|
() => {
|
|
if (!DailyShopDataManager.removeSlotAt(kind, slotIndex)) {
|
|
gg.ui.showToast('删除失败', false);
|
|
return;
|
|
}
|
|
void this._refreshView();
|
|
},
|
|
);
|
|
}
|
|
|
|
private _getSlotGoodsName(kind: DailyShopKind, slotIndex: number): string {
|
|
const ids = kind === DailyShopKind.Passive
|
|
? DailyShopDataManager.getPassiveSlotIds()
|
|
: DailyShopDataManager.getActiveSlotIds();
|
|
const id = Number(ids[slotIndex]) || 0;
|
|
if (id <= 0) return '';
|
|
return DailyShopDataManager.getParsed(id)?.name ?? '';
|
|
}
|
|
|
|
private _bindShopItem(item: Node, goods: DailyShopGoods): void {
|
|
DailyShopLotteryIcon.bindShopItem(item, goods);
|
|
this._ownedDesc?.bindShopItem(item, goods);
|
|
const row = goods.row as ITableBattlebuff;
|
|
|
|
const nameNode = item.getChildByName('name') ?? item.getChildByName('Label');
|
|
if (nameNode?.isValid) {
|
|
const lb = nameNode.getComponent(Label);
|
|
if (lb) {
|
|
lb.string = goods.name;
|
|
const hex = SHOP_NAME_OUTLINE_HEX[Math.max(1, Math.floor(goods.quality) || 1)];
|
|
if (hex) {
|
|
lb.enableOutline = true;
|
|
lb.outlineColor = Color.fromHEX(new Color(), hex);
|
|
}
|
|
}
|
|
}
|
|
|
|
const descNode = item.getChildByName('desc');
|
|
if (descNode?.isValid) {
|
|
const lb = descNode.getComponent(Label);
|
|
if (lb) lb.string = String(row?.desc ?? '');
|
|
}
|
|
|
|
const complete = item.getChildByName('complete');
|
|
const buyBtn = item.getChildByName('buyBtn');
|
|
const buyBtnAd = item.getChildByName('buyBtnAd');
|
|
const lockBuy = this._isBuyLocked();
|
|
|
|
const priceNode = buyBtn?.getChildByName('lay')?.getChildByName('price');
|
|
if (priceNode?.isValid) {
|
|
const lb = priceNode.getComponent(Label);
|
|
if (lb) {
|
|
const cost = Math.max(0, Math.floor(Number(goods.cost) || 0));
|
|
lb.string = `${cost}`;
|
|
if (lockBuy) {
|
|
lb.color = new Color(255, 255, 255, 255);
|
|
} else {
|
|
const enough = gg.data.getItemNum(ItemNumType.money) >= cost;
|
|
lb.color = enough
|
|
? new Color(255, 255, 255, 255)
|
|
: new Color(255, 0, 0, 255);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (goods.sold) {
|
|
if (complete?.isValid) complete.active = true;
|
|
if (buyBtn?.isValid) buyBtn.active = false;
|
|
if (buyBtnAd?.isValid) buyBtnAd.active = false;
|
|
return;
|
|
}
|
|
|
|
if (complete?.isValid) complete.active = false;
|
|
if (goods.isAd) {
|
|
if (buyBtnAd?.isValid) {
|
|
buyBtnAd.active = true;
|
|
this._setBuyBtnGray(buyBtnAd, lockBuy);
|
|
this._bindBuyBtn(buyBtnAd, goods.id, true);
|
|
}
|
|
if (buyBtn?.isValid) buyBtn.active = false;
|
|
} else {
|
|
if (buyBtn?.isValid) {
|
|
buyBtn.active = true;
|
|
this._setBuyBtnGray(buyBtn, lockBuy);
|
|
this._bindBuyBtn(buyBtn, goods.id, false);
|
|
}
|
|
if (buyBtnAd?.isValid) buyBtnAd.active = false;
|
|
}
|
|
}
|
|
|
|
private _isBuyLocked(): boolean {
|
|
return DailyShopDataManager.hasUsedShopPurchase();
|
|
}
|
|
|
|
private _setBuyBtnGray(btn: Node, gray: boolean): void {
|
|
const walk = (n: Node) => {
|
|
const sp = n.getComponent(Sprite);
|
|
if (sp) sp.grayscale = gray;
|
|
const kids = n.children;
|
|
for (let i = 0; i < kids.length; i++) walk(kids[i]);
|
|
};
|
|
walk(btn);
|
|
}
|
|
|
|
private _bindBuyBtn(btn: Node, goodsId: number, payByAd: boolean): void {
|
|
btn['dailyShopGoodsId'] = goodsId;
|
|
btn['dailyShopPayByAd'] = payByAd;
|
|
btn.targetOff(Node.EventType.TOUCH_END);
|
|
btn.on(Node.EventType.TOUCH_END, this._onClickBuy, this);
|
|
}
|
|
|
|
private _onClickBuy(event: EventTouch): void {
|
|
if (this._busy) return;
|
|
if (this._isBuyLocked()) {
|
|
gg.ui.showToast(BUY_USED_TIP, false);
|
|
return;
|
|
}
|
|
const btn = event.currentTarget as Node;
|
|
const shopItem = btn.parent;
|
|
const sourceIcon = shopItem?.isValid ? DailyShopLotteryIcon.resolveShopIcon(shopItem) : null;
|
|
const goodsId = Number(btn?.['dailyShopGoodsId']) || 0;
|
|
const payByAd = !!btn?.['dailyShopPayByAd'];
|
|
if (goodsId <= 0) return;
|
|
|
|
if (payByAd) {
|
|
gg.sdk.showVideoAd((res: boolean) => {
|
|
if (!res) {
|
|
gg.ui.showToast('观看视频失败', false);
|
|
return;
|
|
}
|
|
this._tryPurchase(goodsId, true, sourceIcon);
|
|
});
|
|
return;
|
|
}
|
|
this._tryPurchase(goodsId, false, sourceIcon);
|
|
}
|
|
|
|
private _tryPurchase(goodsId: number, payByAd: boolean, sourceIcon?: Node | null): void {
|
|
if (this._busy) return;
|
|
this._busy = true;
|
|
const result = DailyShopDataManager.purchase(goodsId, { payByAd });
|
|
this._handlePurchaseResult(goodsId, result, payByAd, sourceIcon ?? null);
|
|
}
|
|
|
|
private _handlePurchaseResult(
|
|
goodsId: number,
|
|
result: DailyShopPurchaseResult,
|
|
payByAd = false,
|
|
sourceIcon: Node | null = null,
|
|
): void {
|
|
if (result.ok) {
|
|
const name = DailyShopDataManager.getParsed(goodsId)?.name ?? '';
|
|
if (payByAd) RankReport.adShopBuy();
|
|
RankReport.shopBuy(name);
|
|
this._showPurchaseSuccessToast(result);
|
|
gg.dot?.updateRedDot();
|
|
if (result.instant) {
|
|
this._busy = false;
|
|
void this._refreshView();
|
|
return;
|
|
}
|
|
const slotIndex = result.slotIndex;
|
|
const slotKind = result.slotKind ?? result.parsed.kind;
|
|
if (slotIndex != null && slotIndex >= 0 && sourceIcon?.isValid) {
|
|
this._playBuyToEmptySlotAnim(sourceIcon, result.parsed, slotKind, slotIndex);
|
|
return;
|
|
}
|
|
this._busy = false;
|
|
void this._refreshView();
|
|
return;
|
|
}
|
|
|
|
this._busy = false;
|
|
if (isDailyShopNeedReplace(result)) {
|
|
if (payByAd) RankReport.adShopBuy();
|
|
void this._refreshView();
|
|
this._askReplace(goodsId);
|
|
return;
|
|
}
|
|
|
|
gg.ui.showToast(this._failTip(dailyShopFailReason(result)), false);
|
|
}
|
|
|
|
/** 购买成功提示文案 */
|
|
private _showPurchaseSuccessToast(result: DailyShopPurchaseResult & { ok: true }): void {
|
|
if (result.instant) {
|
|
gg.ui.showToast('购买成功', false);
|
|
return;
|
|
}
|
|
if (result.replacedId) {
|
|
const oldName = DailyShopDataManager.getParsed(result.replacedId)?.name ?? '';
|
|
gg.ui.showToast(oldName ? `已替换「${oldName}」` : '购买成功', false);
|
|
return;
|
|
}
|
|
gg.ui.showToast('购买成功', false);
|
|
}
|
|
|
|
/** 购买入空槽:货架 icon 影子飞行 + 技能放大 */
|
|
private _playBuyToEmptySlotAnim(
|
|
sourceIcon: Node,
|
|
parsed: DailyShopParsed,
|
|
slotKind: DailyShopKind,
|
|
slotIndex: number,
|
|
): void {
|
|
const slotBase = this._getSlotBase(slotKind, slotIndex);
|
|
const fly = this._skillFly;
|
|
if (!sourceIcon?.isValid || !slotBase?.isValid || !fly) {
|
|
console.log('[PopDailyShopBuy] 购买飞行动画参数无效');
|
|
this._busy = false;
|
|
void this._refreshView();
|
|
return;
|
|
}
|
|
fly.playIconFly(sourceIcon, slotBase, this._onBuyIconFlyArrived.bind(this, parsed, slotKind, slotIndex));
|
|
this._renderOwnedSkills({ kind: slotKind, slotIndex });
|
|
this._renderOffers(DailyShopDataManager.getOffers());
|
|
}
|
|
|
|
/** 购买 icon 飞行结束:显示技能并放大缩小 */
|
|
private _onBuyIconFlyArrived(parsed: DailyShopParsed, slotKind: DailyShopKind, slotIndex: number): void {
|
|
if (!this.isValid) return;
|
|
const skillItem = this._revealSkillAtSlot(parsed, slotKind, slotIndex);
|
|
const fly = this._skillFly;
|
|
if (!skillItem?.isValid || !fly) {
|
|
this._busy = false;
|
|
void this._refreshView();
|
|
return;
|
|
}
|
|
fly.playSlotPulse(skillItem, this._onBuySkillPulseDone.bind(this));
|
|
}
|
|
|
|
/** 购买技能放大动画结束 */
|
|
private _onBuySkillPulseDone(): void {
|
|
this._busy = false;
|
|
}
|
|
|
|
/** 在槽位空模板上显示新技能 */
|
|
private _revealSkillAtSlot(parsed: DailyShopParsed, kind: DailyShopKind, slotIndex: number): Node | null {
|
|
const template = kind === DailyShopKind.Active ? this.ui_skillMainItem : this.ui_skillPassiveItem;
|
|
const base = this._getSlotBase(kind, slotIndex);
|
|
if (!template?.isValid || !base?.isValid) return null;
|
|
const item = instantiate(template);
|
|
item.active = true;
|
|
item.setPosition(v3(0, 0, 0));
|
|
item.parent = base;
|
|
DailyShopLotteryIcon.bindSlotItem(item, parsed, kind);
|
|
this._ownedDesc?.bindSlotItem(item, parsed, kind);
|
|
this._bindDeleteBtn(item, kind, slotIndex);
|
|
return item;
|
|
}
|
|
|
|
/** 槽位空模板节点 */
|
|
private _getSlotBase(kind: DailyShopKind, slotIndex: number): Node | null {
|
|
const container = kind === DailyShopKind.Active ? this.ui_skillMain : this.ui_skillPassive;
|
|
if (!container?.isValid || slotIndex < 0 || slotIndex >= container.children.length) return null;
|
|
return container.children[slotIndex];
|
|
}
|
|
|
|
/** 槽位上的技能节点(排除 deleteBtn) */
|
|
private _findSlotSkillItem(base: Node): Node | null {
|
|
const kids = base.children;
|
|
for (let i = 0; i < kids.length; i++) {
|
|
const child = kids[i];
|
|
if (child.name === 'deleteBtn') continue;
|
|
return child;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/** 替换成功:当前槽位放大缩小(无影子飞行) */
|
|
private _playReplaceSlotPulse(kind: DailyShopKind, slotIndex: number): void {
|
|
const base = this._getSlotBase(kind, slotIndex);
|
|
const skillItem = base?.isValid ? this._findSlotSkillItem(base) : null;
|
|
const fly = this._skillFly;
|
|
if (!skillItem?.isValid || !fly) {
|
|
this._busy = false;
|
|
return;
|
|
}
|
|
fly.playSlotPulse(skillItem, this._onReplaceSkillPulseDone.bind(this));
|
|
}
|
|
|
|
/** 替换技能放大动画结束 */
|
|
private _onReplaceSkillPulseDone(): void {
|
|
this._busy = false;
|
|
}
|
|
|
|
private _askReplace(goodsId: number): void {
|
|
const parsed = DailyShopDataManager.getParsed(goodsId);
|
|
if (!parsed) return;
|
|
const entries = DailyShopDataManager.getOccupiedSlotEntries(parsed.kind);
|
|
if (entries.length <= 0) {
|
|
gg.ui.showToast('没有可替换的道具', false);
|
|
return;
|
|
}
|
|
gg.ui.openPanel(UIID.PopReplaceSkill, {
|
|
data: {
|
|
goodsId,
|
|
onConfirm: (replaceOwnedId: number) => {
|
|
this._completeReplace(replaceOwnedId);
|
|
},
|
|
onCancel: () => {
|
|
void this._refreshView();
|
|
},
|
|
} satisfies PopReplaceSkillParam,
|
|
});
|
|
}
|
|
|
|
private _completeReplace(replaceOwnedId: number): void {
|
|
if (this._busy) return;
|
|
this._busy = true;
|
|
const result = DailyShopDataManager.completeReplace(replaceOwnedId);
|
|
this._handleReplaceResult(result);
|
|
}
|
|
|
|
private _handleReplaceResult(result: DailyShopPurchaseResult): void {
|
|
if (result.ok) {
|
|
RankReport.shopBuy(result.parsed?.name ?? '');
|
|
const oldName = result.replacedId
|
|
? DailyShopDataManager.getParsed(result.replacedId)?.name ?? ''
|
|
: '';
|
|
gg.ui.showToast(oldName ? `已替换「${oldName}」` : '购买成功', false);
|
|
gg.dot?.updateRedDot();
|
|
void this._refreshView().then(this._onReplaceViewRefreshed.bind(this, result));
|
|
return;
|
|
}
|
|
this._busy = false;
|
|
gg.ui.showToast(this._failTip(dailyShopFailReason(result)), false);
|
|
}
|
|
|
|
/** 替换刷新完成后播放槽位放大 */
|
|
private _onReplaceViewRefreshed(result: DailyShopPurchaseResult & { ok: true }): void {
|
|
if (!this.isValid) return;
|
|
const slotIndex = result.slotIndex;
|
|
const slotKind = result.slotKind ?? result.parsed.kind;
|
|
if (slotIndex != null && slotIndex >= 0) {
|
|
this._playReplaceSlotPulse(slotKind, slotIndex);
|
|
return;
|
|
}
|
|
this._busy = false;
|
|
}
|
|
|
|
private _failTip(reason: DailyShopPurchaseFail): string {
|
|
switch (reason) {
|
|
case DailyShopPurchaseFail.NotEnoughMoney:
|
|
return '铜币不足';
|
|
case DailyShopPurchaseFail.AlreadySold:
|
|
return '已售罄';
|
|
case DailyShopPurchaseFail.NotInOffer:
|
|
return '不在今日货架';
|
|
case DailyShopPurchaseFail.NotAdOffer:
|
|
return '该商品不可广告购买';
|
|
case DailyShopPurchaseFail.InvalidReplace:
|
|
return '替换目标无效';
|
|
case DailyShopPurchaseFail.PendingReplace:
|
|
return '请先完成替换';
|
|
default:
|
|
return '购买失败';
|
|
}
|
|
}
|
|
}
|
|
|