var GameState = function() { // Websocket handle this.conn = null; this.started = false; this.defusing = false; this.ourTurn = false; this.locked = false; this.favouring = false; this.combo = 1; this.playerColorMap = {}; this.playerColors = [ "#BDE038", "#F2A71B", "#025E73", "#BD2A2E", "#00B3AD", "#F2CB05", "#0468BF", "#D99CD5", "#72583D", "#89A666", "#7365A6", "#8C1F1F" ]; this.servEvHandlers = new ServerEventsHandlers(this); // Player and lobby name this.name = ""; this.lobby = ""; this.nowPlaying = ""; this.players = []; this.spectators = []; this.hand = []; // Assets this.assets = {}; this.loadAsset = function(url, el) { this.assets[url] = el; } this.resetButtons = function() { let buttons = $(".combo-btn").toArray(); buttons.forEach(function(btn) { $(btn).removeClass("active"); }); this.combo = 1; } this.start = function() { // Run the game! // Doesn't actually _start_ the game, but rather starts the game client $("#player-name").text(this.name); $("#lobby-name").text(this.lobby); // Scroll wheel hack - allows the user to scroll the card deck horizontally // WTF? $("#card-deck").mousewheel(function(ev, delta) { this.scrollLeft -= (delta * 30); ev.preventDefault(); }); // Send the contents of the chat box when enter is pressed // feat. a stupid scope hack (function (gameState) { $("#chat-message").keydown( function(ev) { if (ev.key === "Enter") { if ($( this ).val().startsWith("/")) { // Send as a command let msg = $( this ).val().substring(1); gameState.send(msg); } else { // Send as a message let msg = $( this ).val(); gameState.send("chat " + msg); } // Clear the box setTimeout(() => { $( this ).val(""); $( this ).html(""); }, 50); } }); })(this); // Draw a card (function(gameState) { $(".draw-pile-container").on('click', function() { if (gameState.ourTurn) { gameState.send("draw"); } }); })(this); // 2x and 3x buttons (function(gameState) { let buttons = $(".combo-btn").toArray(); buttons.forEach(function(btn) { $(btn).on("click", function() { // deactive all the buttons, except this one buttons.forEach(function(b) { if (b != btn) { $(b).removeClass("active"); $(b).removeClass("btn-light"); } }); $(this).toggleClass("active"); $(this).toggleClass("btn-light"); if ($(this).hasClass("active")) { gameState.combo = $(this).attr("id") == "2x-button" ? 2 : 3; } else { gameState.combo = 0; } }); }); })(this); // Sort button (function(gameState) { $("#sort-button").on("click", function() { gameState.send("sort"); }); })(this); // Mute button (function(gameState) { $("#mute-button").on("click", function() { if (gameState.assets["atomic.ogg"].muted) { gameState.assets["atomic.ogg"].muted = false; $("#mute-button").text("Mute sound"); } else { gameState.assets["atomic.ogg"].muted = true; $("#mute-button").text("Unmute sound"); } }); })(this); (function(gameState) { window.onbeforeunload = function () { if (gameState.conn.readyState !== WebSocket.CLOSED) { gameState.conn.onclose = null; return ""; // Display confirmation message } }; })(this); this.console("<span class=\"text-info\">Welcome to Detonating Cats!</span>"); // We're ready to bring the game board into view $("#welcome").toggleClass("reveal"); $("#game-view").toggleClass("reveal"); this.started = true; } this.console = function(msg) { msg = msg.split(":"); msg[0] = `<b>${msg[0]}</b>`; msg = msg.join(":"); $("#game-log").append(`<div class="msg">${msg}</div>`); // Scroll to bottom $("#game-log").scrollTop($("#game-log")[0].scrollHeight); } this.drawClientsList = function(container, clientList, cl, statusIcon, withColor) { container.empty(); let colorAddition = ""; clientList.forEach(x => { if(withColor) { if(typeof this.playerColorMap[x] == "undefined") { const randomIndex = Math.floor(Math.random() * this.playerColors.length); const color = this.playerColors[randomIndex]; this.playerColors.splice(randomIndex, 1); this.playerColorMap[x] = color; } colorAddition = `style="background-color: ${this.playerColorMap[x]}"`; } const firstLetter = x.slice(0, 2); const playerName = x; x = `<div class="user-icon" ${colorAddition}>${firstLetter}</div>${x}`; container.append(`<li class="${cl}" data-player-name="${playerName}">${x} ${statusIcon}</li>`); }); } this.drawSpectatorsList = function() { this.drawClientsList( $("#spectator-list"), this.spectators, "spectator", `<span class="iconify" data-icon="mdi-eye-outline"></span>`, false ); } this.drawPlayerList = function() { this.drawClientsList( $("#player-list"), this.players, "player", "", true ); (function(gameState) { $("#player-list > li").each( function() { if (this.dataset.playerName == gameState.nowPlaying) { $( this ).addClass("active"); } } ); })(this); } this.readFromServer = function(ev) { var parts = ev.data.split(" "); const eventName = parts[0]; console.log('Server Event', parts); if( parts.length && typeof eventName == "string" && eventName.length && eventName in this.servEvHandlers && typeof this.servEvHandlers[eventName] == "function" ) { parts.splice(0, 1).map(i => entities(i)); const eventData = parts; return this.servEvHandlers[eventName](eventData); } console.warn("WARN: received unknown data from server: "+ev.data); } this.send = function(msg) { this.conn.send(msg); } this.addSpectator = function(nickname) { this.freePlayerColor(nickname); this.spectators.push(nickname); this.drawSpectatorsList(); } this.removeSpectator = function(nickname) { this.spectators.splice(this.spectators.indexOf(nickname), 1); this.drawSpectatorsList(); } this.addPlayer = function(nickname) { } this.removePlayer = function(nickname) { } this.freePlayerColor = function(nickname) { if(nickname in this.playerColorMap) { const color = this.playerColorMap[nickname]; delete this.playerColorMap[nickname]; this.playerColors.push(color); } } }