diff --git a/html/js/network/socketHandlers.js b/html/js/network/socketHandlers.js index d5e46cc..50f17b9 100644 --- a/html/js/network/socketHandlers.js +++ b/html/js/network/socketHandlers.js @@ -1708,81 +1708,95 @@ const SocketHandlers = { // Entry Choice Modal // ===================== + // ONE consolidated entry modal: timing (when) + stakes (free vs ranked) in a single dialog, so + // the player never hits the old timing-modal-then-payment-modal double. Each card emits the + // FINAL intent — Free sends {free:true} (server skips its options modal), Ranked uses a credit + // or opens the real payment UI. Nothing starts until a card is clicked. showEntryChoiceModal: function(opts) { opts = opts || {}; - // Remove any existing modal $('#entryChoiceOverlay').remove(); - + var freeAvailable = !!opts.freeAvailable; + var hasCredits = !!opts.hasCredits; var cost = this._creditsPerGame || 1; - var costText = opts.freeAvailable - ? 'Free play — no credits needed' - : ('Cost: ' + cost + ' credit per game'); + var currency = this._currencyLabel || 'WOW'; + var timing = 'wait'; // safe default + var $overlay = $('
').css({ position: 'fixed', top: 0, left: 0, width: '100%', height: '100%', - background: 'rgba(0,0,0,0.7)', zIndex: 3000, - display: 'flex', alignItems: 'center', justifyContent: 'center' + background: 'rgba(0,0,0,0.74)', zIndex: 3000, display: 'flex', + alignItems: 'center', justifyContent: 'center' }); - var $modal = $('
').css({ - background: '#0a1a0a', border: '2px solid #0f0', borderRadius: '8px', - padding: '24px', maxWidth: '420px', width: '90%', color: '#0f0', - fontFamily: 'monospace', textAlign: 'center' + background: 'linear-gradient(180deg,#101609,#0b0f07)', border: '1px solid #33421f', + borderRadius: '12px', width: '92%', maxWidth: '480px', color: '#e6ead0', + fontFamily: 'monospace', boxShadow: '0 22px 60px rgba(0,0,0,.6)', overflow: 'hidden' }); - $modal.html( - '
How do you want to enter?
' + - '
' + costText + '
' + - '' + - '' + - '' - ); + function seg(id, on, t, d, danger) { + var col = on ? (danger ? '#ff6a1a' : '#4fd463') : '#8b9a78'; + var bg = on ? (danger ? 'linear-gradient(180deg,#4a1c05,#2a1103)' : 'linear-gradient(180deg,#123a17,#0b2410)') : '#0a0f07'; + var bc = on ? (danger ? '#ff6a1a' : '#4fd463') : '#33421f'; + return ''; + } + function stake(id, k, t, s, accent) { + return '
' + + '' + k + '' + + '
' + t + '
' + + '
' + s + '
' + + 'ENTER ▸
'; + } + function begin(msg, emit) { + $('#entryChoiceOverlay').remove(); + emit(); + $('#messages').append($('
  • ').text(msg)); + if (typeof UI !== 'undefined' && UI.scrollChat) UI.scrollChat(); + if (typeof ScreenManager !== 'undefined' && ScreenManager.drawWaitingScreen) ScreenManager.drawWaitingScreen(); + } + function pay() { + $('#entryChoiceOverlay').remove(); + if (typeof PaymentUI !== 'undefined' && PaymentUI.show) PaymentUI.show(); + } + function render() { + $modal.html( + '
    ' + + '⚔' + + '

    Enter the Dungeon

    ' + + 'esc' + + '
    ' + + '
    ' + + '
    1 · When do you drop in?
    ' + + '
    ' + + seg('ecWait', timing === 'wait', '🛡 Next block', 'Safe — full block window', false) + + seg('ecNow', timing === 'now', '⚡ Right now', 'Risky — die on next block', true) + + '
    ' + + '
    2 · Choose your stakes
    ' + + (freeAvailable ? stake('ecFree', '🆓', 'Free Play', 'No cost · Pleb leaderboard', '#123a17') : '') + + stake('ecRank', '💰', 'Ranked', (hasCredits ? '1 credit' : ('Pay ' + cost + ' ' + currency)) + ' · Hall of Champions', '#2a1a4a') + + '
    + Buy credits (bulk discount)
    ' + + '
    ' + ); + $('#ecWait').on('click', function () { timing = 'wait'; render(); }); + $('#ecNow').on('click', function () { timing = 'now'; render(); }); + $('#ecX').on('click', function () { $('#entryChoiceOverlay').remove(); }); + $('#ecFree').on('click', function () { + if (timing === 'now') begin('⚡ Free game — dropping in now...', function () { socket.emit('auto_start', { free: true }); }); + else begin('🛡️ Free game — queued for the next block...', function () { socket.emit('join_queue'); }); + }); + $('#ecRank').on('click', function () { + if (!hasCredits) { pay(); return; } + if (timing === 'now') begin('⚡ Ranked — dropping in now...', function () { socket.emit('auto_start'); }); + else begin('🛡️ Ranked — queued for the next block...', function () { socket.emit('join_queue'); }); + }); + $('#ecBuy').on('click', pay); + } - $overlay.append($modal); + $overlay.append($modal).on('click', function (e) { if (e.target === this) $('#entryChoiceOverlay').remove(); }); $('body').append($overlay); - - // Handlers - $('#entryChoiceNow').on('click', function() { - $('#entryChoiceOverlay').remove(); - socket.emit('auto_start'); - $('#messages').append($('
  • ').text('⚡ Starting game immediately...')); - UI.scrollChat(); - if (typeof ScreenManager !== 'undefined' && ScreenManager.drawWaitingScreen) { - ScreenManager.drawWaitingScreen(); - } - }); - - $('#entryChoiceQueue').on('click', function() { - $('#entryChoiceOverlay').remove(); - socket.emit('join_queue'); - $('#messages').append($('
  • ').text('🛡️ Joining queue — waiting for next block...')); - UI.scrollChat(); - if (typeof ScreenManager !== 'undefined' && ScreenManager.drawWaitingScreen) { - ScreenManager.drawWaitingScreen(); - } - }); - - $('#entryChoiceCancel').on('click', function() { - $('#entryChoiceOverlay').remove(); - }); - - // Close on overlay click (outside modal) - $overlay.on('click', function(e) { - if (e.target === this) { - $('#entryChoiceOverlay').remove(); - } - }); + render(); } };