diff --git a/assets/data/abilities.js b/assets/data/abilities.js index a0cec65..f7698e9 100644 --- a/assets/data/abilities.js +++ b/assets/data/abilities.js @@ -8,10 +8,11 @@ module.exports = { }, "morale_boost": { onAfterPlace: function(card) { - var field = this.getYourside().getField(card.getType()); - var cards = field.getCards(); + var field = this.field[card.getType()]; + var cards = field.get(); cards.forEach(function(_card) { + if(_card.getID() == card.getID()) return; _card.boost(1); }) } @@ -21,17 +22,17 @@ module.exports = { var name = card.getName(); var self = this; - var cards = this.getDeck().find("name", name); + var cards = this.deck.find("name", name); cards.forEach(function(_card) { - self.getDeck().removeFromDeck(_card.getID()); - this._placeCard(_card); + self.deck.removeFromDeck(_card); + this.placeCard(_card); }) } }, "tight_bond": { onAfterPlace: function(card){ - var field = this.getYourside().getField(card.getType()); - var cards = field.getCards(); + var field = this.field[card.getType()]; + var cards = field.get(); var lastInsert = cards.length; if(lastInsert < 2) return; @@ -45,15 +46,15 @@ module.exports = { "spy": { changeSide: true, onAfterPlace: function(card){ - this.drawCards(2); + this.draw(2); } }, "weather_fog": { onEachTurn: function(card) { var targetRow = card.constructor.TYPE.RANGED; var forcedPower = 1; - var field1 = this.getYourside().getField(targetRow).getCards(); - var field2 = this.getOtherside().getField(targetRow).getCards(); + var field1 = this.field[targetRow].get(); + var field2 = this.foe.field[targetRow].get(); var field = field1.concat(field2); @@ -61,15 +62,27 @@ module.exports = { if(_card.getRawAbility() == "hero") return; _card.setForcedPower(forcedPower); }); + }, + onEachCardPlace: function(card) { + var targetRow = card.constructor.TYPE.RANGED; + var forcedPower = 1; + var field1 = this.field[targetRow].get(); + var field2 = this.foe.field[targetRow].get(); + var field = field1.concat(field2); + + field.forEach(function(_card) { + if(_card.getRawAbility() == "hero") return; + _card.setForcedPower(forcedPower); + }); } }, "weather_rain": { onEachTurn: function(card) { var targetRow = card.constructor.TYPE.SIEGE; var forcedPower = 1; - var field1 = this.getYourside().getField(targetRow).getCards(); - var field2 = this.getOtherside().getField(targetRow).getCards(); + var field1 = this.field[targetRow].get(); + var field2 = this.foe.field[targetRow].get(); var field = field1.concat(field2); @@ -84,8 +97,8 @@ module.exports = { onEachTurn: function(card) { var targetRow = card.constructor.TYPE.CLOSE_COMBAT; var forcedPower = 1; - var field1 = this.getYourside().getField(targetRow).getCards(); - var field2 = this.getOtherside().getField(targetRow).getCards(); + var field1 = this.field[targetRow].get(); + var field2 = this.foe.field[targetRow].get(); var field = field1.concat(field2); @@ -99,7 +112,7 @@ module.exports = { "clear_weather": { onAfterPlace: function(card) { var targetRow = card.constructor.TYPE.WEATHER; - var field = this.getYourside().getField(targetRow).getCards(); + var field = this.field[targetRow].get(); //todo: remove weather cards } diff --git a/public/js/client.js b/public/js/client.js index 19852de..59e21d9 100644 --- a/public/js/client.js +++ b/public/js/client.js @@ -95,9 +95,12 @@ var App = Backbone.Router.extend({ var SideView = Backbone.View.extend({ el: ".container", - template: Handlebars.compile('
'), + template: Handlebars.compile('
' + + '' + + '
'), templateCards: Handlebars.compile('{{#each this}}' + - '
' + + '
' + + '{{#if _boost}}+{{_boost}}{{/if}}' + '' + '
' + '{{/each}}'), @@ -113,11 +116,11 @@ var SideView = Backbone.View.extend({ }, render: function(){ - this.renderInfo(); this.renderCloseField(); this.renderRangeField(); this.renderSiegeField(); + this.renderWeatherField(); return this; }, @@ -138,6 +141,8 @@ var SideView = Backbone.View.extend({ this.$info.addClass("removeBackground"); } + this.$info.find(".passing").html(d.passing?"Passed":""); + }, renderCloseField: function(){ if(!this.field.close) return; @@ -175,6 +180,14 @@ var SideView = Backbone.View.extend({ $field.find(".field-siege").html(html) $field.find(".large-field-counter").html(score) }, + renderWeatherField: function(){ + if(!this.field.weather) return; + var $weatherField = this.$el.find(".field-weather"); + var cards = this.field.weather._cards; + $weatherField.html(this.templateCards(cards)); + + return this; + }, lives: function(lives){ var out = ""; for(var i = 0; i < 2; i++) { @@ -201,12 +214,12 @@ var BattleView = Backbone.View.extend({ this.listenTo(user, "change:showPreview", this.render); this.listenTo(user, "change:waiting", this.render); + this.listenTo(user, "change:passing", this.render); this.$hand = this.$el.find(".field-hand"); this.$preview = this.$el.find(".card-preview"); app.receive("update:hand", function(data){ - console.log("update:hand", user.get("roomSide"), data._roomSide); if(user.get("roomSide") == data._roomSide){ self.handCards = JSON.parse(data.cards); self.render(); @@ -223,7 +236,6 @@ var BattleView = Backbone.View.extend({ if(user.get("roomSide") != _side){ side = otherSide; } - console.log(side); side.infoData = infoData; side.leader = leader; side.render(); @@ -242,6 +254,7 @@ var BattleView = Backbone.View.extend({ side.field.close = data.close; side.field.ranged = data.ranged; side.field.siege = data.siege; + side.field.weather = data.weather; side.render(); }) @@ -263,16 +276,53 @@ var BattleView = Backbone.View.extend({ events: { "mouseover .card": "onMouseover", "mouseleave .card": "onMouseleave", - "click .field-hand": "onClick" + "click .field-hand": "onClick", + "click .battleside.player": "onClickDecoy", + "click .button-pass": "onPassing" + }, + onPassing: function(){ + if(this.user.get("passing")) return; + if(this.user.get("waiting")) return; + this.user.set("passing", true); + this.user.get("app").send("set:passing"); }, onClick: function(e){ if(!!this.user.get("waiting")) return; + if(!!this.user.get("passing")) return; + var self = this; var $card = $(e.target).closest(".card"); var id = $card.data("id"); - console.log("clicked id ", id); + var key = $card.data("key"); + this.app.send("play:cardFromHand", { id: id }); + + if(key === "decoy"){ + console.log("its decoy!!!"); + this.user.set("waitForDecoy", id); + /* + this.$el.find(".battleside.player").on("click", ".card", function(e) { + console.log("replacement card found: "); + var $card = $(e.target).closest(".card"); + var _id = $card.data("id"); + self.app.send("decoy:replaceWith", { + oldCard: id, + newCard: _id + }) + self.$el.find(".battleside.player").off("click"); + });*/ + } + }, + onClickDecoy: function(e){ + if(!this.user.get("waitForDecoy")) return; + console.log("replacement card found: "); + var $card = $(e.target).closest(".card"); + var _id = $card.data("id"); + this.app.send("decoy:replaceWith", { + cardID: _id + }) + this.user.set("waitForDecoy", false); }, onMouseover: function(e){ var target = $(e.target).closest(".card"); @@ -307,7 +357,6 @@ var User = Backbone.Model.extend({ var self = this; var app = this.get("app"); - app.receive("response:name", function(data){ self.set("name", data.name); }); @@ -330,7 +379,6 @@ var User = Backbone.Model.extend({ app.receive("set:waiting", function(data){ var waiting = data.waiting; - console.log("is waiting: ", waiting); self.set("waiting", waiting); }) diff --git a/public/scss/main.scss b/public/scss/main.scss index b8df163..cbe1eb0 100644 --- a/public/scss/main.scss +++ b/public/scss/main.scss @@ -34,8 +34,8 @@ $game-height: 800px; } } -.passing { - display: none; +.passing {/* + display: none;*/ } .field-single { @@ -81,6 +81,16 @@ $game-height: 800px; img { height: 120px; } + span { + color: #00b000; + font-weight: bold; + font-size: 24px; + position: absolute; + text-shadow: 1px 1px #101010; + margin-top: 55px; + margin-left: 30px; + cursor: default; + } } .card-preview { diff --git a/server/Battle.js b/server/Battle.js index d015bfa..65ba397 100644 --- a/server/Battle.js +++ b/server/Battle.js @@ -1,5 +1,6 @@ var Battleside = require("./Battleside"); var PubSub = require("pubsub-js"); +var Card = require("./Card"); var io = global.io; @@ -28,14 +29,17 @@ var Battle = (function(){ r._user2 = null; r.turn = 0; + r._id = null; r.init = function(){ + PubSub.subscribe("update", this.update.bind(this)); this.p1 = Battleside(this._user1.getName(), 0, this, this._user1); this.p2 = Battleside(this._user2.getName(), 1, this, this._user2); this.p1.foe = this.p2; this.p2.foe = this.p1; + this.p1.setUpWeatherFieldWith(this.p2); this.start(); } @@ -46,12 +50,20 @@ var Battle = (function(){ this.p1.draw(10); this.p2.draw(10); + this.p1.hand.add(Card("decoy")); + this.p1.hand.add(Card("impenetrable_fog")); + this.p2.hand.add(Card("decoy")); + this.p2.hand.add(Card("impenetrable_fog")); + + this.update(); + + PubSub.subscribe("nextTurn", this.switchTurn.bind(this)); this.switchTurn(); } - r.switchTurn = function(){ + r.switchTurn = function(__flag){ /*this.playerManager.renderInfos(); if(this.playerManager.bothPassed() && !this._roundCheck) { //start new round @@ -65,8 +77,15 @@ var Battle = (function(){ var entity = this.playerManager.getNextPlayer(); this.playerManager.renderInfos();*/ + __flag = typeof __flag == "undefined" ? 0 : 1; var side = this.turn++ % 2 ? this.p1 : this.p2; + if(side.isPassing()){ + if(__flag) { + return this.startNextRound(); + } + return this.switchTurn(1); + } PubSub.publish("onEachTurn"); PubSub.publish("turn/" + side.getID()); @@ -74,6 +93,30 @@ var Battle = (function(){ } + r.startNextRound = function() { + + } + + r.update = function(){ + this._update(this.p1); + this._update(this.p2); + } + + r._update = function(p){ + p.send("update:info", { + info: p.getInfo(), + leader: p.field[Card.TYPE.LEADER].get()[0] + }) + p.send("update:hand", { + cards: JSON.stringify(p.hand.getCards()) + }); + p.send("update:fields", { + close: p.field[Card.TYPE.CLOSE_COMBAT], + ranged: p.field[Card.TYPE.RANGED], + siege: p.field[Card.TYPE.SIEGE], + weather: p.field[Card.TYPE.WEATHER] + }) + } r.send = function(event, data){ io.to(this._id).emit(event, data); diff --git a/server/Battleside.js b/server/Battleside.js index 0fe7c5c..b0717ea 100644 --- a/server/Battleside.js +++ b/server/Battleside.js @@ -7,7 +7,8 @@ var Field = require("./Field"); var PubSub = require("pubsub-js"); -var Battleside = (function(){ +var Battleside; +Battleside = (function(){ var Battleside = function(name, n, battle, user){ if(!(this instanceof Battleside)){ return (new Battleside(name, n, battle, user)); @@ -16,6 +17,7 @@ var Battleside = (function(){ * constructor here */ + var self = this; this._isWaiting = true; this.socket = user.socket; this.field = {}; @@ -30,6 +32,26 @@ var Battleside = (function(){ this.deck = Deck(DeckData["test"]); + this.receive("play:cardFromHand", function(data){ + if(self._isWaiting) return; + if(self.isPassing()) return; + var cardID = data.id; + var card = self.hand.getCard(cardID); + + self.playCard(card); + }) + this.receive("decoy:replaceWith", function(data){ + if(self._isWaiting) return; + var card = self.findCardOnFieldByID(data.cardID); + if(card === -1) throw "decoy:replace | unknown card"; + PubSub.publish("decoy:replaceWith", card); + }) + this.receive("set:passing", function() { + self.setPassing(true); + self.update(); + PubSub.publish("nextTurn"); + }) + PubSub.subscribe("turn/" + this.getID(), this.onTurnStart.bind(this)); }; var r = Battleside.prototype; @@ -48,6 +70,7 @@ var Battleside = (function(){ r._lives = 2; r._score = 0; r._isWaiting = null; + r._passing = null; r.field = null; @@ -59,12 +82,33 @@ var Battleside = (function(){ r.battle = null; r.deck = null; + r.isPassing = function() { + return this._passing; + } + + r.setUpWeatherFieldWith = function(p2){ + this.field[Card.TYPE.WEATHER] = p2.field[Card.TYPE.WEATHER] = Field(Card.TYPE.WEATHER); + } + + r.findCardOnFieldByID = function(id) { + for(var key in this.field) { + var field = this.field[key]; + var card = field.getCard(id); + if(card !== -1) return card; + } + return -1; + } + + r.setPassing = function(b) { + this._passing = b; + } + r.wait = function(){ this._isWaiting = true; this.send("set:waiting", {waiting: this._isWaiting}, true); } - r.turn = function() { + r.turn = function(){ this._isWaiting = false; this.send("set:waiting", {waiting: this._isWaiting}, true); } @@ -77,7 +121,7 @@ var Battleside = (function(){ this.field[Card.TYPE.LEADER].add(leaderCard[0]); } - r.getID = function() { + r.getID = function(){ return this.n; } @@ -92,7 +136,7 @@ var Battleside = (function(){ this.update(); } - r.calcScore = function() { + r.calcScore = function(){ var score = 0; for(var key in this.field) { score += +this.field[key].getScore(); @@ -101,12 +145,12 @@ var Battleside = (function(){ } r.getInfo = function(){ - console.log(this.getName(), this._isWaiting); return { name: this.getName(), lives: this._lives, score: this.calcScore(), - hand: this.hand.length() + hand: this.hand.length(), + passing: this._passing } } @@ -119,56 +163,119 @@ var Battleside = (function(){ isPrivate = typeof isPrivate === "undefined" ? false : isPrivate; msg._roomSide = this.n; - if(isPrivate) { + if(isPrivate){ return this.socket.emit(event, msg); } this.battle.send(event, msg); } - r.receive = function(event, cb) { + r.receive = function(event, cb){ this.socket.on(event, cb); } r.update = function(){ - this.send("update:info", { - info: this.getInfo(), - leader: this.field[Card.TYPE.LEADER].get()[0] - }) - this.send("update:hand", { - cards: JSON.stringify(this.hand.getCards()) - }); - this.send("update:fields", { - close: this.field[Card.TYPE.CLOSE_COMBAT], - ranged: this.field[Card.TYPE.RANGED], - siege: this.field[Card.TYPE.SIEGE] - }) + /* + this.send("update:info", { + info: this.getInfo(), + leader: this.field[Card.TYPE.LEADER].get()[0] + }) + this.send("update:hand", { + cards: JSON.stringify(this.hand.getCards()) + }); + this.send("update:fields", { + close: this.field[Card.TYPE.CLOSE_COMBAT], + ranged: this.field[Card.TYPE.RANGED], + siege: this.field[Card.TYPE.SIEGE] + })*/ + PubSub.publish("update"); } - r.onTurnStart = function() { + r.onTurnStart = function(){ this.foe.wait(); this.turn(); - var self = this; - this.receive("play:cardFromHand", function(data) { - var cardID = data.id; - var card = self.hand.getCard(cardID); - self.hand.remove(cardID); + //wait for cardplay event + - self.playCard(card); - }) }; - r.playCard = function(card) { - if(card === -1) return; - var field = this.field[card.getType()]; + r.playCard = function(card){ + if(card === null || card === -1) return; - field.add(card); + this.hand.remove(card); + + if(!this.placeCard(card)) return; this.update(); PubSub.publish("nextTurn"); } + r.placeCard = function(card){ + var obj = {}; + + this.checkAbilities(card, obj); + if(obj._canclePlacement) return 0; + + var field = obj.targetSide.field[card.getType()]; + field.add(card); + + PubSub.publish("onEachCardPlace"); + + this.checkAbilityOnAfterPlace(card); + + return 1; + } + + r.checkAbilities = function(card, obj){ + var self = this; + obj.targetSide = this; + + if(card.getAbility()){ + var ability = card.getAbility(); + if(ability.changeSide){ + obj.targetSide = this.foe; + } + if(ability.replaceWith){ + obj._canclePlacement = true; + + var decoy = PubSub.subscribe("decoy:replaceWith", function(event, replaceCard){ + if(replaceCard.getType() == Card.TYPE.LEADER || + replaceCard.getType() == Card.TYPE.WEATHER || + replaceCard.getType() == Card.TYPE.SPECIAL){ + return; + } + PubSub.unsubscribe(decoy); + var field = self.field[replaceCard.getType()]; + + field.replaceWith(replaceCard, card); + + self.hand.add(replaceCard); + + self.update(); + + PubSub.publish("nextTurn"); + }) + } + if(ability.onEachTurn){ + PubSub.subscribe("onEachTurn", ability.onEachTurn.bind(this, card)); + } + if(ability.onEachCardPlace){ + PubSub.subscribe("onEachCardPlace", ability.onEachCardPlace.bind(this, card)); + } + + } + } + + r.checkAbilityOnAfterPlace = function(card){ + var ability = card.getAbility(); + if(ability){ + if(ability.onAfterPlace){ + ability.onAfterPlace.call(this, card) + } + } + } + return Battleside; })(); diff --git a/server/Card.js b/server/Card.js index e514697..b4d9655 100644 --- a/server/Card.js +++ b/server/Card.js @@ -38,6 +38,7 @@ var Card = (function(){ WEATHER: 5 }; + r._init = function(){ this._id = ++Card.__id; } @@ -46,15 +47,15 @@ var Card = (function(){ return this._data.name; } r.getPower = function(){ - if(this._forcedPower > -1) { + if(this._forcedPower > -1){ return this._forcedPower + this._boost; } return this._data.power + this._boost; } - r.setForcedPower = function(nr) { + r.setForcedPower = function(nr){ this._forcedPower = nr; } - r.getRawAbility = function() { + r.getRawAbility = function(){ return this._data.ability; } r.getAbility = function(){ @@ -77,7 +78,8 @@ var Card = (function(){ return this._id; } - r.boost = function(nr) { + r.boost = function(nr){ + this.getPower(); //to recalculate this._power; this._boost += nr; } diff --git a/server/Field.js b/server/Field.js index cfb6242..1acb3ae 100644 --- a/server/Field.js +++ b/server/Field.js @@ -19,27 +19,49 @@ var Field = (function(){ r._cards = null; r._score = 0; - r.add = function(card) { + r.add = function(card){ this._cards.push(card); this.updateScore(); } - r.get = function() { + r.get = function(){ return this._cards; } - r.getScore = function() { + r.getScore = function(){ + this.updateScore(); return this._score; } - r.updateScore = function() { + r.updateScore = function(){ this._score = 0; - for(var i=0; i