/* System Variable */
var time,timer;
var MouseOn = false;
var now = null; // to store whose turn is this. value: "player" or "enemy"
var socketReady = false;
var lock = true;
var debugMode = false;
var dialogDisplay = false;
var playerChooseStatus = false;
var curName = "";
var eneName = "";
var drawID = "";
var poisonDamage = "";
var tradeChoose = "";
var handCards = [];
/* DOM Objects */
var cardContainer = $('.cards.container')[0];
var dialog = $('#modal');
var grid = $('#grid')[0];
var column = $('.column');
var log = $('#log')[0];
var gameStatus = $('#status');
var turn = $('#turn')[0];
var roomNum = $('.statistic > .value')[0];
var enemy = $('#enemy');
var myself = $('#myself');
/* text */
// cards
var cards = {'1': '攻擊', '2': '防禦', '3': '治癒', '4': '補給', '5': '強奪', '6': '奇襲', '7': '交易', '8': '洞悉', '9': '妙策', '10': '掃射', '11': '加護', '12': '劇毒', '13': '詛咒', '14': '反制', '15': '狂亂', '16': '逆轉'};
var cardsDescription = {"1":"對敵方造成兩點傷害","2":"回復一點生命
被動:抵擋攻擊類卡片","3":"回復兩點生命","4":"抽取兩張手牌","5":"從敵方手牌中選擇一張加入自己的手牌","6":"對敵方造成一點傷害,並使其隨機損失一張手牌","7":"選取一張手牌與敵方交換","8":"抽取三張手牌
被動:抵擋攻擊類卡片,並抽取一張手牌、抵擋強奪的效果","9":"從牌庫中隨機挑出三張卡片,選擇一張加入手牌","10":"對敵方造成零~五點傷害","11":"回復三點生命,並解除中毒","12":"使敵方中毒:每個回合,玩家會損失一點生命","13":"使其損失四點生命,並隨機損失一張手牌","14":"使敵方生命減半
被動:抵擋攻擊類卡片,並反彈其傷害和效果","15":"回復三點生命,並對敵方造成三點傷害","16":"使自己與敵方的生命交換"}
var characters = {'1': '安', '2': '圭月', '3': '梅', '4': '小兔', '5': '銀', '6': '正作', '7': 'W', '8': '桑德', '9': '海爾', '10': '雪村'};
// templates
var cardTemplate = `
'+eneName+'
'+curName+'
'); dialog.children(".actions").html(''); timerInitialize(); // also remember to stop the timer modalOpen(); resultListener(); quit(); }); function resultListener() { $('#returnIndex').click(function() { location.href = './index.html'; }); $('#restart').click(function() { location.reload(); }); $('#close').click(function() { modalClose(); }); } // log log.addEventListener("mouseover", function() { MouseOn = true; }); // if mouse is over the div, don't scroll to bottom log.addEventListener("mouseleave", function() { MouseOn = false; }); function Log(msgJson) { var node = logTemplate; node = (now === "player") ? node.replace("{{ isSelf }}","right") : node.replace("{{ isSelf }}",""); // to distinguish if this is self log or enemy log node = node.replace("{{ content }}",messages[msgJson['msg']].format(msgJson['data'])); log.insertAdjacentHTML("beforeend",node); // insert to log if (!MouseOn) { // if mouse isn't over the div, scroll to bottom log.scrollTop = log.scrollHeight; // scroll to bottom } } function LogPlayerDraw() { var node = logTemplate.replace("{{ isSelf }}","right"); node = node.replace("{{ content }}",messages['draw'].format([curName,cards[drawID]])); // msgJson['data'][0] player name, msgJson['data'][1] card id log.insertAdjacentHTML("beforeend",node); // insert to log if (!MouseOn) { // if mouse isn't over the div, scroll to bottom log.scrollTop = log.scrollHeight; // scroll to bottom } drawID = ""; } function LogPlayerChoose(type,data) { var node = logTemplate; var name = data[0]; var chooseID = data[1]; if (playerChooseStatus || type === "robbed") { node = (now === "player") ? node.replace("{{ isSelf }}","right") : node.replace("{{ isSelf }}",""); // to distinguish if this is self log or enemy log } else { node = (now === "player") ? node.replace("{{ isSelf }}","") : node.replace("{{ isSelf }}","right"); // if this is the second one playerChoose message, then this is another one's choice } node = node.replace("{{ content }}",messages[type].format([name,cards[chooseID]])); // msgJson['data'][0] player name, msgJson['data'][1] card id log.insertAdjacentHTML("beforeend",node); // insert to log if (!MouseOn) { // if mouse isn't over the div, scroll to bottom log.scrollTop = log.scrollHeight; // scroll to bottom } playerChooseStatus = (playerChooseStatus && type !== "robbed") ? false : true; // to count this is first playerChoose message or second one on the turn } function LogPlayerPoisonDamaged() { var node = logTemplate; var tmpName = ""; if(now === "player") { // to distinguish if this is self log or enemy log node = node.replace("{{ isSelf }}","right"); tmpName = curName; } else if (now === "enemy") { node = node.replace("{{ isSelf }}",""); tmpName = eneName; } node = node.replace("{{ content }}",messages['poisonDamaged'].format([tmpName,poisonDamage])); // msgJson['data'][0] player name, msgJson['data'][1] card id log.insertAdjacentHTML("beforeend",node); // insert to log if (!MouseOn) { // if mouse isn't over the div, scroll to bottom log.scrollTop = log.scrollHeight; // scroll to bottom } poisonDamage = ""; } function rawLog(msg) { console.log(JSON.stringify(msg)); if (!MouseOn) { // if mouse isn't over the div, scroll to bottom log.scrollTop = log.scrollHeight; // scroll to bottom } } function logTurn(playerName,playerTurn) { var node = logDivider; node = node.replace("{{ player }}",playerName); node = node.replace("{{ turn }}",playerTurn); log.insertAdjacentHTML("beforeend",node); // insert to log if (!MouseOn) { // if mouse isn't over the div, scroll to bottom log.scrollTop = log.scrollHeight; // scroll to bottom } } // game status updater function gameUpdate(data) { if (data.room) { roomNum.innerHTML = data.room.padStart(5,'0'); } else if (data.now) { if (data.now === "player") { turn.innerHTML = curName+" Turn "+data.player.turn; logTurn(curName,data.player.turn); if (drawID !== "") { LogPlayerDraw(data); } statusInitialize(); lock = false; // unlock the cards gameStatus.addClass('primary'); gameStatus.html('輪到你出牌'); timerSetup(28); } else if (data.now === "enemy") { turn.innerHTML = eneName+" Turn "+data.enemy.turn; logTurn(eneName,data.enemy.turn); statusInitialize(); gameStatus.html('等待對手出牌'); } if (poisonDamage !== "") { LogPlayerPoisonDamaged(); } playerUpdate(data['player']); enemyUpdate(data['enemy']); modalClose(); } } function statusInitialize() { gameStatus.removeClass('info negative warning pulsing primary inverted'); // initailize the status timerInitialize(); } // player status updater function setPlayerName(name) { var selfNameHeader = $('#myself > .profile > .name > .header'); selfNameHeader.html(name); } function setEnemyName(name) { var eneNameHeader = $('#enemy > .profile > .name > .header'); eneNameHeader.html(name); } function playerUpdate(data) { handCards = data['hand']; setCard(data['hand']); var selfHand = $('#selfHand'); // 手牌數 var selfDeck = $('#selfDeck'); var selfLifeBar = $('#myself > .profile > .life.progress > .bar'); var selfLifeText = selfLifeBar.children(); var selfStatus = $('#myself > .profile > .status'); var barWidth = (parseInt(data['life'])/20)*100 // % selfHand.html(data['hand'].length); selfDeck.html(data['deck_left']); selfLifeBar.css('width',barWidth+'%'); selfLifeBar.attr('data-life',data['life']); selfLifeText.html(data['life']); if (parseInt(data['poison']) > 0){ selfStatus.html('中毒 lv.'+data['poison']+'
'); selfLifeBar.addClass('poison'); } else if (parseInt(data['poison']) == 0) { if (selfLifeBar.hasClass('poison')) { selfLifeBar.removeClass('poison'); } selfStatus.html('清新'); } if (parseInt(data['life']) <= 0) { // dead if (selfLifeBar.hasClass('poison')) { selfLifeBar.removeClass('poison'); } selfLifeBar.addClass('negative'); } } function enemyUpdate(data) { var eneHand = $('#eneHand'); // 手牌數 var eneDeck = $('#eneDeck'); var eneLifeBar = $('#enemy > .profile > .life.progress > .bar'); var eneLifeText = eneLifeBar.children(); var eneStatus = $('#enemy > .profile > .status'); var barWidth = (parseInt(data['life'])/20)*100 // % eneHand.html(data['hand']); eneDeck.html(data['deck_left']); eneLifeBar.css('width',barWidth+'%'); eneLifeBar.attr('data-life',data['life']); eneLifeText.html(data['life']); if (parseInt(data['poison']) > 0){ eneStatus.html('中毒 lv.'+data['poison']+'
'); eneLifeBar.addClass('poison'); } else if (parseInt(data['poison']) == 0) { if (eneLifeBar.hasClass('poison')) { eneLifeBar.removeClass('poison'); } eneStatus.html('清新'); } if (parseInt(data['life']) <= 0) { // dead if (eneLifeBar.hasClass('poison')) { eneLifeBar.removeClass('poison'); } eneLifeBar.addClass('negative'); } } // card function useCard(id) { if (!lock) { statusInitialize(); send(id); lock = true; } } function setCard(cardsArray) { $(cardContainer).empty(); var node = ""; cardsArray.forEach((id) => { var tmp = cardTemplate; tmp = tmp.replace(/{{ id }}/g,id).replace("{{ name }}",cards[id]).replace("{{ description }}",cardsDescription[id]); node += tmp; }); $(cardContainer).append(node); setCardListener(); resize(); // special case } // modals function chooseRob(data) { var list = `對手選擇了"+cards[tradeID]+"
"; } else { var text = "選擇一張卡與對手交換
"; } var list = `請從三張卡中選擇一張加入手牌
`; var list = `'+eneName+'
'+curName+'
'); dialog.children(".actions").html(''); timerInitialize(); // also remember to stop the timer modalOpen(); resultListener(); } function playerLose() { dialog.children(".header").html('你輸爆了,SAD'); dialog.children(".content").html(''+eneName+'
'+curName+'
'); dialog.children(".actions").html(''); timerInitialize(); // also remember to stop the timer modalOpen(); resultListener(); } function modalClose() { if (dialogDisplay) { ts('#modal').modal('hide'); dialogDisplay = false; } } function modalOpen() { if (!dialogDisplay) { ts('#modal').modal('show'); dialogDisplay = true; } } // countdown timer for each turn function timing() { if (time == 0) { clearInterval(timer); // unset the timer gameStatus.removeClass('warning pulsing'); gameStatus.addClass('negative'); gameStatus.text('時間到!'); return null; } if (time <= 5) { if(!gameStatus.hasClass('pulsing')) { gameStatus.addClass('pulsing'); // pulsing animation } gameStatus.removeClass('info'); gameStatus.addClass('warning'); gameStatus.text('輪到你出牌 '+time); } else if (time <= 10) { if(!gameStatus.hasClass('pulsing')) { gameStatus.addClass('pulsing'); // pulsing animation } gameStatus.text('輪到你出牌 '+time); } else { gameStatus.removeClass('negative pulsing'); gameStatus.addClass('info'); gameStatus.text('輪到你出牌'); } time--; } function timerSetup(t) { time = t; timer = setInterval(timing,1000); } function timerInitialize() { clearInterval(timer); gameStatus.addClass('inverted'); gameStatus.html('等待中'); } // resize function resize() { var h = cardContainer.offsetHeight; grid.style.height='calc(100vh - ' + h + 'px)'; column.css('height','calc(100vh - ' + h + 'px)'); } resize(); window.addEventListener("resize",resize); // game initailize $(document).ready(() => { var roomID = localStorage.getItem('room'); var characterID = localStorage.getItem('character'); if(!roomID || !characterID){ roomID = "n"; characterID = Math.floor(Math.random()*10 + 1).toString(); // randomly choose a player } curName = characters[characterID]; setPlayerName(characters[characterID]); init(); var retry = setInterval(() => { if(socketReady) { // send the charactor id and room id until the connected send(characterID); send(roomID); clearInterval(retry); } }, 300); // try every 0.3s }); /* https://stackoverflow.com/questions/11700927/horizontal-scrolling-with-mouse-wheel-in-a-div */ function scrollHorizontally(e) { e = window.event || e; var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail))); cardContainer.scrollLeft -= (delta*40); // Multiplied by 40 e.preventDefault(); } cardContainer.addEventListener("mousewheel", scrollHorizontally, false); cardContainer.addEventListener("DOMMouseScroll", scrollHorizontally, false); //Firefox