74 lines
3.7 KiB
TypeScript
74 lines
3.7 KiB
TypeScript
const STARTER_PACK_REWARDS = {
|
|
starter_pack: { coin: 3000, hammer: 1, freeze: 1, magic_wand: 1, infinite_health: 30 * 60 },
|
|
starter_pack_2: { coin: 3000, hammer: 1, freeze: 1, magic_wand: 1, infinite_health: 30 * 60 },
|
|
starter_pack_3: { coin: 4500, hammer: 3, freeze: 3, magic_wand: 3, infinite_health: 45 * 60 },
|
|
starter_pack_4: { coin: 5000, hammer: 5, freeze: 5, magic_wand: 5, infinite_health: 60 * 60 },
|
|
starter_pack_5: { coin: 8000, hammer: 8, freeze: 8, magic_wand: 8, infinite_health: 180 * 60 },
|
|
};
|
|
|
|
/** Rewards are fixed by the client SKU; the server only selects the offer tier. */
|
|
export function starterPackReward(productId = "starter_pack") {
|
|
return { ...(STARTER_PACK_REWARDS[productId] || STARTER_PACK_REWARDS.starter_pack) };
|
|
}
|
|
|
|
export function starterPackNow(): number {
|
|
return Date.now() + (cc.fx.GameConfig.GM_INFO.starterPackServerOffset || 0);
|
|
}
|
|
|
|
export function starterPackRemaining(): number {
|
|
if (cc.fx.GameConfig.GM_INFO.starterPackPurchased) return 0;
|
|
return Math.max(0, Math.ceil(cc.fx.GameConfig.GM_INFO.starter_packTime - starterPackNow() / 1000));
|
|
}
|
|
|
|
export function starterPackTimeText(seconds: number): string {
|
|
const value = Math.max(0, Math.floor(seconds));
|
|
return [Math.floor(value / 3600), Math.floor(value / 60) % 60, value % 60]
|
|
.map(part => String(part).padStart(2, '0')).join(':');
|
|
}
|
|
|
|
export function applyStarterPackStatus(data: any): void {
|
|
const info = cc.fx.GameConfig.GM_INFO;
|
|
const expiry = Number(data.starter_pack) || 0;
|
|
const round = Number(data.starterPackRound || data.starterPackOffer?.round) || 0;
|
|
if (round && round < (info.starterPackRound || 0)) return;
|
|
if (round > (info.starterPackRound || 0)) {
|
|
info.starterPackPurchased = false;
|
|
info.starterPackReactivatedDeadline = 0;
|
|
info.starterPackRound = round;
|
|
}
|
|
if (data.starterPackOffer && (!info.starterPackOffer || round > Number(info.starterPackOffer.round))) {
|
|
info.starterPackOffer = data.starterPackOffer;
|
|
}
|
|
info.starterPackAutoShownRound = Math.max(info.starterPackAutoShownRound || 0, Number(data.starterPackAutoShownRound) || 0);
|
|
if (data.reactivated) info.starterPackReactivatedDeadline = Math.max(info.starterPackReactivatedDeadline || 0, expiry);
|
|
// An activity read started before reactivation may arrive after its response.
|
|
info.starter_packTime = Math.max(expiry, info.starterPackReactivatedDeadline || 0) / 1000;
|
|
// A late status response cannot undo a purchase confirmed in this session.
|
|
info.starterPackPurchased = info.starterPackPurchased || Number(data.starter_packState) === 1;
|
|
info.starterPackLastShownAt = Math.max(info.starterPackLastShownAt || 0, Number(data.starterPackLastShownAt) || 0);
|
|
if (Number(data.serverTime) > 0) info.starterPackServerOffset = Number(data.serverTime) - Date.now();
|
|
}
|
|
|
|
export function starterPackDay(): string {
|
|
// Keep the existing local calendar-day policy, using server-corrected time.
|
|
const date = new Date(starterPackNow());
|
|
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
|
|
}
|
|
|
|
export function starterPackPopupKey(): string {
|
|
const info = cc.fx.GameConfig.GM_INFO;
|
|
return 'Starter_pack_' + info.uid + '_' + (info.starterPackRound || info.starter_packTime);
|
|
}
|
|
|
|
export function starterPackFailureKey(): string {
|
|
const info = cc.fx.GameConfig.GM_INFO;
|
|
return 'StarterPackFailures_' + info.uid + '_' + info.level;
|
|
}
|
|
|
|
export function starterPackRecordResult(won: boolean): number {
|
|
const key = starterPackFailureKey();
|
|
const count = won ? 0 : Math.min(4, Math.max(0, Number(cc.fx.StorageMessage.getStorage(key)) || 0) + 1);
|
|
cc.fx.StorageMessage.setStorage(key, count);
|
|
return count;
|
|
}
|