/** Purchases and login compensation use the same client-owned reward. */ export function starterPackReward() { return { coin: 3000, hammer: 3, freeze: 3, magic_wand: 3, infinite_health: 30 * 60 }; } 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; 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 { return 'Starter_pack_' + cc.fx.GameConfig.GM_INFO.uid; } 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; }