diff --git a/assets/data/deck.js b/assets/data/deck.js index 6c9f904..2051978 100644 --- a/assets/data/deck.js +++ b/assets/data/deck.js @@ -1,124 +1,169 @@ module.exports = { - "northern": [ - "redanian_foot_soldier", - "redanian_foot_soldier", - "poor_fucking_infantry", - "redanian_foot_soldier", - "poor_fucking_infantry", - "yarpen_zigrin", - "blue_stripes_commando", - "sigismund_dijkstra", - "prince_stennis", - "siegfried_of_denesle", - "ves", - "vernon_roche", - "john_natalis", - "sheldon_skaggs", - "sabrina_glevissig", - "crinfrid_reavers_dragon_hunter", - "sile_de_tansarville", - "keira_metz", - "dethmold", - "kaedweni_siege_expert", - "dun_banner_medic", - "ballista", - "trebuchet", - "thaler", - "foltest_siegemaster", - "biting_frost", - "torrential_rain", - "clear_weather", - "impenetrable_fog", - "commanders_horn", - "commanders_horn", - "decoy" - ], + "northern": { + faction: "northern", + data: [ + "redanian_foot_soldier", + "redanian_foot_soldier", + "poor_fucking_infantry", + "redanian_foot_soldier", + "poor_fucking_infantry", + "yarpen_zigrin", + "blue_stripes_commando", + "sigismund_dijkstra", + "prince_stennis", + "siegfried_of_denesle", + "ves", + "vernon_roche", + "john_natalis", + "sheldon_skaggs", + "sabrina_glevissig", + "crinfrid_reavers_dragon_hunter", + "sile_de_tansarville", + "keira_metz", + "dethmold", + "kaedweni_siege_expert", + "dun_banner_medic", + "ballista", + "trebuchet", + "thaler", + "foltest_siegemaster", + "biting_frost", + "torrential_rain", + "clear_weather", + "impenetrable_fog", + "commanders_horn", + "commanders_horn", + "decoy" + ] + }, + "nilfgaardian": { //test only + faction: "nilfgaardian", + data: [ + "redanian_foot_soldier", + "redanian_foot_soldier", + "poor_fucking_infantry", + "redanian_foot_soldier", + "poor_fucking_infantry", + "yarpen_zigrin", + "blue_stripes_commando", + "sigismund_dijkstra", + "prince_stennis", + "siegfried_of_denesle", + "ves", + "vernon_roche", + "john_natalis", + "sheldon_skaggs", + "sabrina_glevissig", + "crinfrid_reavers_dragon_hunter", + "sile_de_tansarville", + "keira_metz", + "dethmold", + "kaedweni_siege_expert", + "dun_banner_medic", + "ballista", + "trebuchet", + "thaler", + "foltest_siegemaster", + "biting_frost", + "torrential_rain", + "clear_weather", + "impenetrable_fog", + "commanders_horn", + "commanders_horn", + "decoy" + ] + }, + "scoiatael": { + faction: "scoiatael", + data: [ + "francesca_the_beautiful", + "commanders_horn", + "commanders_horn", + "saesenthessis", + "iorveth", + "isengrim_faoiltiarnah", + "eithne", + "havekar_healer", + "riordain", + "havekar_smuggler", + "havekar_smuggler", + "havekar_smuggler", + "toruviel", + "decoy", + "decoy", + "biting_frost", + "torrential_rain", + "clear_weather", + "impenetrable_fog", + "elven_skirmisher", + "elven_skirmisher", + "dwarven_skirmisher", + "dwarven_skirmisher", + "ciaran_aep_easnillien", + "vrihedd_brigade_recruit", + "dol_blathanna_archer", + "havekar_smuggler", + "mahakaman_defender", + "vrihedd_brigade_veteran", + "dennis_cranmer", + "filavandrel_aen_fidhail", + "filavandrel_aen_fidhail", + "ida_emean_aep_sivney", + "yaevinn", + "barclay_els", + "dol_blathanna_scout", + "milva" + ] + }, - "scoiatael": [ - "francesca_the_beautiful", - "commanders_horn", - "commanders_horn", - "saesenthessis", - "iorveth", - "isengrim_faoiltiarnah", - "eithne", - "havekar_healer", - "riordain", - "havekar_smuggler", - "havekar_smuggler", - "havekar_smuggler", - "toruviel", - "decoy", - "decoy", - "biting_frost", - "torrential_rain", - "clear_weather", - "impenetrable_fog", - "elven_skirmisher", - "elven_skirmisher", - "dwarven_skirmisher", - "dwarven_skirmisher", - "ciaran_aep_easnillien", - "vrihedd_brigade_recruit", - "dol_blathanna_archer", - "havekar_smuggler", - "mahakaman_defender", - "vrihedd_brigade_veteran", - "dennis_cranmer", - "filavandrel_aen_fidhail", - "filavandrel_aen_fidhail", - "ida_emean_aep_sivney", - "yaevinn", - "barclay_els", - "dol_blathanna_scout", - "milva" - ], - - "monster": [ - "eredin_king_of_the_wild_hunt", - "kayran", - "leshen", - "imlerith", - "draug", - "ghoul", - "decoy", - "nekker", - "nekker", - "wyvern", - "foglet", - "celaeno_harpy", - "gargoyle", - "cockatrice", - "harpy", - "biting_frost", - "torrential_rain", - "clear_weather", - "impenetrable_fog", - "endrega", - "vampire_bruxa", - "vampire_fleder", - "vampire_garkain", - "vampire_ekimmara", - "commanders_horn", - "commanders_horn", - "vampire_ekimmara", - "arachas", - "botchling", - "forktail", - "plague_maiden", - "griffin", - "werewolf", - "frightener", - "ice_giant", - "grave_hag", - //"vampire_katakan", - "crone_whispess", - "crone_brewess", - "crone_weavess", - "arachas_behemoth", - "fire_elemental", - "fiend", - "earth_elemental" - ] + "monster": { + faction: "monster", + data: [ + "eredin_king_of_the_wild_hunt", + "kayran", + "leshen", + "imlerith", + "draug", + "ghoul", + "decoy", + "nekker", + "nekker", + "wyvern", + "foglet", + "celaeno_harpy", + "gargoyle", + "cockatrice", + "harpy", + "biting_frost", + "torrential_rain", + "clear_weather", + "impenetrable_fog", + "endrega", + "vampire_bruxa", + "vampire_fleder", + "vampire_garkain", + "vampire_ekimmara", + "commanders_horn", + "commanders_horn", + "vampire_ekimmara", + "arachas", + "botchling", + "forktail", + "plague_maiden", + "griffin", + "werewolf", + "frightener", + "ice_giant", + "grave_hag", + //"vampire_katakan", + "crone_whispess", + "crone_brewess", + "crone_weavess", + "arachas_behemoth", + "fire_elemental", + "fiend", + "earth_elemental" + ] + } } \ No newline at end of file diff --git a/client/js/client.js b/client/js/client.js index 9588ca1..51f69db 100644 --- a/client/js/client.js +++ b/client/js/client.js @@ -274,6 +274,7 @@ let BattleView = Backbone.View.extend({ this.listenTo(user, "change:setAgile", this.render); this.listenTo(user, "change:setHorn", this.render); this.listenTo(user, "change:isReDrawing", this.render); + this.listenTo(user, "change:chooseSide", this.render); /*this.listenTo(user, "change:handCards", this.render);*/ this.$hand = this.$el.find(".field-hand"); @@ -437,11 +438,14 @@ let BattleView = Backbone.View.extend({ let modal = new ReDrawModal({model: this.user}); this.$el.prepend(modal.render().el); } - - if(this.user.get("openDiscard")){ + if(this.user.get("openDiscard")) { let modal = new Modal({model: this.user}); this.$el.prepend(modal.render().el); } + if(this.user.get("chooseSide")){ + let modal = new ChooseSideModal({model: this.user}); + this.$el.prepend(modal.render().el); + } if(this.user.get("medicDiscard")){ let modal = new MedicModal({model: this.user}); this.$el.prepend(modal.render().el); @@ -621,6 +625,29 @@ let ReDrawModal = Modal.extend({ let WinnerModal = Modal.extend({ template: require("../templates/modal.winner.handlebars") }); +let ChooseSideModal = Modal.extend({ + template: require("../templates/modal.side.handlebars"), + events: { + "click .btn": "onBtnClick" + }, + beforeCancel: function() { + return false; + }, + onBtnClick: function(e) { + var id = $(e.target).closest(".btn").data().id; + + this.model.set("chooseSide", false); + if(id === "you") { + //this.model.set("chosenSide", this.model.get("roomSide")); + this.model.chooseSide(this.model.get("roomSide")); + this.remove(); + return; + } + //this.model.set("chosenSide", this.model.get("roomFoeSide")); + this.model.chooseSide(this.model.get("roomFoeSide")); + this.remove(); + } +}); let User = Backbone.Model.extend({ defaults: { @@ -632,6 +659,8 @@ let User = Backbone.Model.extend({ let user = this; let app = user.get("app"); + self.set("chooseSide", false); + this.listenTo(this.attributes, "change:room", this.subscribeRoom); app.receive("response:name", function(data){ @@ -641,17 +670,13 @@ let User = Backbone.Model.extend({ app.receive("init:battle", function(data){ //console.log("opponent found!"); self.set("roomSide", data.side); + self.set("roomFoeSide", data.foeSide); /* self.set("channel:battle", app.socket.subscribe(self.get("room")));*/ //app.navigate("battle", {trigger: true}); app.battleRoute(); }) - /*app.receive("response:createRoom", function(roomID){ - self.set("room", roomID); - console.log("room created", roomID); - });*/ - app.receive("response:joinRoom", function(roomID){ self.set("room", roomID); //console.log("room id", self.get("room")); @@ -717,6 +742,9 @@ let User = Backbone.Model.extend({ let modal = new WinnerModal({model: new model({winner: winner})}); $("body").prepend(modal.render().el); }) + app.receive("request:chooseWhichSideBegins", function() { + self.set("chooseSide", true); + }) app.on("startMatchmaking", this.startMatchmaking, this); app.on("joinRoom", this.joinRoom, this); @@ -746,6 +774,11 @@ let User = Backbone.Model.extend({ //console.log("deck: ", deckKey); this.set("deckKey", deckKey); this.get("app").send("set:deck", {deck: deckKey}); + }, + chooseSide: function(roomSide) { + this.get("app").send("response:chooseWhichSideBegins", { + side: roomSide + }) } }); diff --git a/client/templates/lobby.handlebars b/client/templates/lobby.handlebars index 6c03416..8fb82c0 100644 --- a/client/templates/lobby.handlebars +++ b/client/templates/lobby.handlebars @@ -9,6 +9,7 @@ + diff --git a/client/templates/modal.side.handlebars b/client/templates/modal.side.handlebars new file mode 100644 index 0000000..545b3e0 --- /dev/null +++ b/client/templates/modal.side.handlebars @@ -0,0 +1,10 @@ +
+

Choose which side should begin

+
+
+
You
+
Foe
+
+
+ +
diff --git a/gulpfile.js b/gulpfile.js index ffaedda..29c7ad7 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -72,7 +72,6 @@ gulp.task("watch", function(){ }) - gulp.task("index", function(){ gulp.src("./client/index.html") .pipe(gulp.dest("./public/")); @@ -90,6 +89,7 @@ gulp.task('resize sm', function(done){ .pipe(gm(function(gmfile){ return gmfile.resize(null, 120); })) + .pipe(imagemin()) .pipe(gulp.dest('./assets/cards/sm/')); }); @@ -102,6 +102,7 @@ gulp.task('resize lg', ["resize sm"], function(done){ .pipe(gm(function(gmfile){ return gmfile.resize(null, 450); })) + .pipe(imagemin()) .pipe(gulp.dest('./assets/cards/lg/')); }); @@ -125,6 +126,7 @@ gulp.task("sprite", ["resize lg"], function(){ //template: "./client/scss/_cards.hbs" }) //.pipe(gulpif("*.png", gulp.dest("./public/build/"), gulp.dest("./client/scss/"))); + .pipe(imagemin()) .pipe(gulp.dest("./public/build/")); diff --git a/server/Battle.js b/server/Battle.js index dca4211..c4afdcf 100644 --- a/server/Battle.js +++ b/server/Battle.js @@ -1,5 +1,6 @@ var Battleside = require("./Battleside"); var Card = require("./Card"); +var Deck = require("./Deck"); var shortid = require("shortid"); var Promise = require("jquery-deferred"); @@ -54,7 +55,6 @@ var Battle = (function(){ this.p1.setUpWeatherFieldWith(this.p2); - this.start(); } @@ -63,26 +63,27 @@ var Battle = (function(){ this.p2.setLeadercard(); this.p1.draw(10); this.p2.draw(10); + /* - this.p1.placeCard("ves"); - this.p2.placeCard("ves"); - this.p1.placeCard("yarpen_zigrin"); - this.p2.placeCard("yarpen_zigrin"); + this.p1.placeCard("ves"); + this.p2.placeCard("ves"); + this.p1.placeCard("yarpen_zigrin"); + this.p2.placeCard("yarpen_zigrin"); - this.p1.hand.add(Card("scorch")); - this.p2.hand.add(Card("scorch")); - this.p1.hand.add(Card("villentretenmerth")); - this.p2.hand.add(Card("villentretenmerth")); - - this.p1.hand.add(Card("impenetrable_fog")); - this.p2.hand.add(Card("impenetrable_fog")); - this.p1.hand.add(Card("biting_frost")); - this.p2.hand.add(Card("biting_frost")); - this.p1.hand.add(Card("torrential_rain")); - this.p2.hand.add(Card("torrential_rain")); - this.p1.hand.add(Card("clear_weather")); - this.p2.hand.add(Card("clear_weather")); + this.p1.hand.add(Card("scorch")); + this.p2.hand.add(Card("scorch")); + this.p1.hand.add(Card("villentretenmerth")); + this.p2.hand.add(Card("villentretenmerth")); + this.p1.hand.add(Card("impenetrable_fog")); + this.p2.hand.add(Card("impenetrable_fog")); + this.p1.hand.add(Card("biting_frost")); + this.p2.hand.add(Card("biting_frost")); + this.p1.hand.add(Card("torrential_rain")); + this.p2.hand.add(Card("torrential_rain")); + this.p1.hand.add(Card("clear_weather")); + this.p2.hand.add(Card("clear_weather")); + */ this.update(); @@ -121,9 +122,10 @@ var Battle = (function(){ r.startNextRound = function(){ var loser = this.checkRubies(); + var winner = loser.foe; if(this.checkIfIsOver()){ console.log("its over!"); - this.gameOver(loser.foe); + this.gameOver(winner); this.update(); return; } @@ -133,11 +135,41 @@ var Battle = (function(){ console.log("start new round!"); + if(winner.deck.getFaction() === Deck.FACTION.NORTHERN_REALM){ + winner.draw(1); + console.log(winner.getName() + " draws 1 extra card! (Northern ability)"); + } + this.update(); - this.switchTurn(loser); + + if(winner.deck.getFaction() === Deck.FACTION.SCOIATAEL){ + this.waitForScoiatael(winner); + } + else if(this.p1.deck.getFaction() === Deck.FACTION.SCOIATAEL){ + this.waitForScoiatael(this.p1); + } + else if(this.p2.deck.getFaction() === Deck.FACTION.SCOIATAEL){ + this.waitForScoiatael(this.p2); + } + else { + this.switchTurn(loser); + } } - r.gameOver = function(winner) { + r.waitForScoiatael = function(side){ + var self = this; + side.send("request:chooseWhichSideBegins", null, true); + side.socket.once("response:chooseWhichSideBegins", function(data){ + console.log("which side? ", data.side); + + if(data.side !== "p1" && data.side !== "p2") + throw new Error("Unknown side property! - ", data.side); + + self.switchTurn(self[data.side]); + }) + } + + r.gameOver = function(winner){ this.send("gameover", { winner: winner.getName() }) @@ -149,7 +181,7 @@ var Battle = (function(){ this._update(this.p2); } - r.updateSelf = function(side) { + r.updateSelf = function(side){ this._update(side, true); } @@ -161,7 +193,7 @@ var Battle = (function(){ }, isPrivate) p.send("update:hand", { cards: JSON.stringify(p.hand.getCards()) - },isPrivate); + }, isPrivate); p.send("update:fields", { close: p.field[Card.TYPE.CLOSE_COMBAT].getInfo(), ranged: p.field[Card.TYPE.RANGED].getInfo(), @@ -265,6 +297,19 @@ var Battle = (function(){ } //tie + + //check if is nilfgaardian faction ability + if(this.p1.deck.getFaction() === Deck.FACTION.NILFGAARDIAN_EMPIRE && this.p1.deck.getFaction() !== this.p2.deck.getFaction()){ + this.p2.removeRuby(); + console.log(this.p1.getName() + " wins the tie! (nilfgaardian ability)"); + return this.p2; + } + if(this.p2.deck.getFaction() === Deck.FACTION.NILFGAARDIAN_EMPIRE && this.p1.deck.getFaction() !== this.p2.deck.getFaction()){ + this.p1.removeRuby(); + console.log(this.p2.getName() + " wins the tie! (nilfgaardian ability)"); + return this.p1; + } + this.p1.removeRuby(); this.p2.removeRuby(); return Math.random() > 0.5 ? this.p1 : this.p2; diff --git a/server/Battleside.js b/server/Battleside.js index 7bc683f..6c76c73 100644 --- a/server/Battleside.js +++ b/server/Battleside.js @@ -166,6 +166,19 @@ Battleside = (function(){ return -1; } + r.getRandomCardOnField = function() { + var close, range, siege; + + close = this.field[Card.TYPE.CLOSE_COMBAT].get(); + range = this.field[Card.TYPE.RANGED].get(); + siege = this.field[Card.TYPE.SIEGE].get(); + + var allCards = close.concat(range.concat(siege)); + var rnd = (Math.random() * allCards.length) | 0 ; + + return allCards[rnd]; + } + r.getCardFromDiscard = function(id){ for(var i = 0; i < this._discard.length; i++) { var c = this._discard[i]; @@ -558,6 +571,10 @@ Battleside = (function(){ } r.clearMainFields = function(){ + var rndCard = null; + if(this.deck.getFaction() === Deck.FACTION.MONSTERS) { + rndCard = this.getRandomCardOnField(); + } var cards1 = this.field[Card.TYPE.CLOSE_COMBAT].removeAll(); var cards2 = this.field[Card.TYPE.RANGED].removeAll(); var cards3 = this.field[Card.TYPE.SIEGE].removeAll(); @@ -565,6 +582,12 @@ Battleside = (function(){ var cards = cards1.concat(cards2.concat(cards3.concat(cards4))); this.addToDiscard(cards); + + if(rndCard) { + this.removeFromDiscard(rndCard); + this.placeCard(rndCard, {disabled: true}); //disabled == no abilities get triggered + console.log("Monsters faction ability triggered!"); + } } r.addToDiscard = function(cards){ diff --git a/server/Deck.js b/server/Deck.js index 4b83e79..7484b7a 100644 --- a/server/Deck.js +++ b/server/Deck.js @@ -11,8 +11,11 @@ var Deck = (function(){ */ this._deck = []; + if(typeof deck !== "object") throw new Error("Deck is not an object!"); + this._originalDeck = []; - this.setDeck(deck); + this._faction = deck.faction; + this.setDeck(deck.data); }; var r = Deck.prototype; /** @@ -23,6 +26,14 @@ var Deck = (function(){ r._deck = null; r._owner = null; r._originalDeck = null; + r._faction = null; + + Deck.FACTION = { + NORTHERN_REALM: "northern", + SCOIATAEL: "scoiatael", + NILFGAARDIAN_EMPIRE: "nilfgaardian", + MONSTERS: "monster" + } r.setDeck = function(deckData){ this._originalDeck = deckData.slice(); @@ -32,6 +43,10 @@ var Deck = (function(){ this.shuffle(); } + r.getFaction = function() { + return this._faction; + } + r.getLength = function(){ return this._deck.length; } @@ -99,7 +114,7 @@ var Deck = (function(){ } } - r.add = function(card) { + r.add = function(card){ this._deck.push(card); } diff --git a/server/Room.js b/server/Room.js index 157356b..48e9d26 100644 --- a/server/Room.js +++ b/server/Room.js @@ -58,8 +58,8 @@ var Room = (function(){ r.initBattle = function(){ this._battle = Battle(this._id, this._users[0], this._users[1], io); - this._users[0].send("init:battle", {side: "p1"}); - this._users[1].send("init:battle", {side: "p2"}); + this._users[0].send("init:battle", {side: "p1", foeSide: "p2"}); + this._users[1].send("init:battle", {side: "p2", foeSide: "p2"}); } r.setReady = function(user, b){