/** Purchases and login compensation use the same client-owned reward. */ export function starterPackReward() { return { coin: 8000, hammer: 8, freeze: 8, magic_wand: 8 }; } 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; info.starter_packTime = (Number(data.starter_pack) || 0) / 1000; // A late status response cannot undo a purchase confirmed in this session. info.starterPackPurchased = info.starterPackPurchased || Number(data.starter_packState) === 1; 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; }