From 753f4e7a9c1bbde8cee98ac36d73973b6d9beb93 Mon Sep 17 00:00:00 2001 From: exane Date: Sun, 21 Jun 2015 16:50:50 +0200 Subject: [PATCH] lot of stuff --- .gitignore | 3 +- assets/data/abilities.js | 147 ++++++++- assets/data/cards.js | 57 ++++ assets/data/deck.js | 15 +- client/index.html | 25 +- client/js/client.js | 92 ++++-- client/scss/main.scss | 16 +- gulpfile.js | 1 + public/index.html | 25 +- server/Battle.js | 32 +- server/Battleside.js | 151 ++++++++- server/Card.js | 17 +- server/Field.js | 54 +++- server/Hand.js | 6 +- site/public/assets/css/app.css | 568 ++++++++++++++++++++++++++++++++- site/server/composer.lock | 2 +- test/src/CardSpec.js | 13 + test/src/PubSubSpec.js | 32 ++ test/src/mainSpec.js | 1 + 19 files changed, 1155 insertions(+), 102 deletions(-) create mode 100644 test/src/CardSpec.js diff --git a/.gitignore b/.gitignore index 18a59ae..6c5d384 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ test/spec /site/.idea /site/server/vendor /site/server/.env -/site/client/node_modules \ No newline at end of file +/site/client/node_modules +/site/public/assets/js/bundle.js \ No newline at end of file diff --git a/assets/data/abilities.js b/assets/data/abilities.js index 1f8a717..354e7a3 100644 --- a/assets/data/abilities.js +++ b/assets/data/abilities.js @@ -97,6 +97,7 @@ module.exports = { } }, "weather_fog": { + weather: 1/*, onEachTurn: function(card){ var targetRow = card.constructor.TYPE.RANGED; var forcedPower = 1; @@ -122,10 +123,11 @@ module.exports = { if(_card.getRawAbility() == "hero") return; _card.setForcedPower(forcedPower); }); - } + }*/ }, "weather_rain": { - onEachTurn: function(card){ + weather: 2 + /*onEachTurn: function(card){ var targetRow = card.constructor.TYPE.SIEGE; var forcedPower = 1; var field1 = this.field[targetRow].get(); @@ -137,12 +139,9 @@ module.exports = { if(_card.getRawAbility() == "hero") return; _card.setForcedPower(forcedPower); }); - - } - }, - "weather_frost": { - onEachTurn: function(card){ - var targetRow = card.constructor.TYPE.CLOSE_COMBAT; + }, + onEachCardPlace: function(card){ + var targetRow = card.constructor.TYPE.SIEGE; var forcedPower = 1; var field1 = this.field[targetRow].get(); var field2 = this.foe.field[targetRow].get(); @@ -153,20 +152,116 @@ module.exports = { if(_card.getRawAbility() == "hero") return; _card.setForcedPower(forcedPower); }); - - } + }*/ }, - "clear_weather": { - onAfterPlace: function(card){ - var targetRow = card.constructor.TYPE.WEATHER; - var field = this.field[targetRow].get(); + "weather_frost": { + weather: 0 + /* + onEachTurn: function(card){ + var targetRow = card.constructor.TYPE.CLOSE_COMBAT; + var forcedPower = 1; + var field1 = this.field[targetRow].get(); + var field2 = this.foe.field[targetRow].get(); - //todo: remove weather cards - } + var field = field1.concat(field2); + + field.forEach(function(_card){ + if(_card.getRawAbility() == "hero") return; + _card.setForcedPower(forcedPower); + }); + }, + onEachCardPlace: function(card){ + var targetRow = card.constructor.TYPE.CLOSE_COMBAT; + 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_clear": { + weather: 5 + /*onAfterPlace: function(card){ + var targetRow = card.constructor.TYPE.WEATHER; + var field = this.field[targetRow]; + field.removeAll(); + + for(var i = card.constructor.TYPE.CLOSE_COMBAT; i < card.constructor.TYPE.SIEGE; i++) { + var _field1, _field2, _field; + _field1 = this.field[i].get(); + _field2 = this.foe.field[i].get(); + _field = _field1.concat(_field2); + + _field.forEach(function(_card){ + if(_card.getRawAbility() == "hero") return; + _card.setForcedPower(-1); + }); + } + + }*/ }, "decoy": { replaceWith: true }, + "commanders_horn": { + commandersHorn: true/*, + onEachCardPlace: function(card){ + var field = this.field[card.getType()]; + var id = "commanders_horn"; + + if(!field.isOnField(card)){ + field.get().forEach(function(_card){ + if(_card.getID() == id) return; + if(_card.getType() != card.getType()) return; + if(_card.hasAbility("hero")) return; + _card.setBoost(id, 0); + }) + this.off("EachCardPlace", card.getUidEvents("EachCardPlace")); + return; + } + + field.get().forEach(function(_card){ + if(_card.getID() == id) return; + if(_card.getType() != card.getType()) return; + if(_card.hasAbility("hero")) return; + _card.setBoost(id, 0); + _card.setBoost(id, _card.getPower()); + }) + }*/ + }, + "commanders_horn_card": { + cancelPlacement: true, + commandersHorn: true, + isCommandersHornCard: true/*, + onEachCardPlace: function(card){ + var field = this.field[card.getType()]; + var id = "commanders_horn"; + + if(!field.isOnField(card)){ + field.get().forEach(function(_card){ + if(_card.getID() == id) return; + if(_card.getType() != card.getType()) return; + if(_card.hasAbility("hero")) return; + _card.setBoost(id, 0); + }) + this.off("EachCardPlace", card.getUidEvents("EachCardPlace")); + return; + } + + field.get().forEach(function(_card){ + if(_card.getID() == id) return; + if(_card.getType() != card.getType()) return; + if(_card.hasAbility("hero")) return; + _card.setBoost(id, 0); + _card.setBoost(id, _card.getPower()); + }) + }*/ + }, "foltest_leader1": { onActivate: function(){ var cards = this.deck.find("key", "impenetrable_fog") @@ -175,6 +270,26 @@ module.exports = { this.placeCard(card); } }, + "foltest_leader2": { + onActivate: function(){ + this.setWeather(5); + } + }, + "foltest_leader3": { + onActivate: function(){ + var siegeCards = this.field[2].get(); + + //todo: unless there is commanders horn active + siegeCards.forEach(function(card){ + card.setBoost("foltest_leader3", card.getPower()); + }) + } + }, + "foltest_leader4": { + onActivate: function(){ + + } + }, "francesca_leader1": { onActivate: function(){ } diff --git a/assets/data/cards.js b/assets/data/cards.js index 7b8f04f..229a8bf 100644 --- a/assets/data/cards.js +++ b/assets/data/cards.js @@ -186,6 +186,30 @@ module.exports = { faction: "Northern Realm", type: 3 }, + "foltest_lord_commander": { + name: "Foltest: Lord Commander", + power: -1, + ability: "foltest_leader2", + img: "foltest_commander", + faction: "Northern Realm", + type: 3 + }, + "foltest_siegemaster": { + name: "Foltest: The Siegemaster", + power: -1, + ability: "foltest_leader3", + img: "foltest_siege", + faction: "Northern Realm", + type: 3 + }, + "foltest_forged": { + name: "Foltest: The Steel-Forged", + power: -1, + ability: "foltest_leader4", + img: "foltest_forged", + faction: "Northern Realm", + type: 3 + }, "decoy": { name: "Decoy", power: -1, @@ -194,6 +218,15 @@ module.exports = { faction: null, type: 4 }, + "commanders_horn": { + name: "Commander's Horn", + power: -1, + ability: "commanders_horn_card", + img: "horn", + faction: null, + type: 4 + }, + "impenetrable_fog": { name: "Impenetrable Fog", power: -1, @@ -202,6 +235,30 @@ module.exports = { faction: null, type: 5 }, + "biting_frost": { + name: "Biting Frost", + power: -1, + ability: "weather_frost", + img: "frost", + faction: null, + type: 5 + }, + "torrential_rain": { + name: "Torrential Rain", + power: -1, + ability: "weather_rain", + img: "rain", + faction: null, + type: 5 + }, + "clear_weather": { + name: "Clear Weather", + power: -1, + ability: "weather_clear", + img: "clear", + faction: null, + type: 5 + }, "francesca_pureblood_elf": { diff --git a/assets/data/deck.js b/assets/data/deck.js index fe0e7bc..827c91a 100644 --- a/assets/data/deck.js +++ b/assets/data/deck.js @@ -24,9 +24,12 @@ module.exports = { "ballista", "trebuchet", "thaler", - "foltest_king_of_temeria", - "decoy", - "impenetrable_fog" + "foltest_siegemaster", + "biting_frost", + "torrential_rain", + "clear_weather", + "impenetrable_fog", + "decoy" ], "scoiatael": [ @@ -40,6 +43,9 @@ module.exports = { "toruviel", "decoy", "decoy", + "biting_frost", + "torrential_rain", + "clear_weather", "impenetrable_fog", "elven_skirmisher", "elven_skirmisher", @@ -78,6 +84,9 @@ module.exports = { "gargoyle", "cockatrice", "harpy", + "biting_frost", + "torrential_rain", + "clear_weather", "impenetrable_fog", "endrega", "vampire_bruxa", diff --git a/client/index.html b/client/index.html index eaf3ad9..f8811de 100644 --- a/client/index.html +++ b/client/index.html @@ -76,7 +76,6 @@
- {{#health lives}}{{/health}}
@@ -92,30 +91,42 @@
-
+
+
+
0
-
+
+
+
0
-
+
+
+
0
-
+
+
+
0
-
+
+
+
0
-
+
+
+
0
diff --git a/client/js/client.js b/client/js/client.js index 7adf62b..65a1a3a 100644 --- a/client/js/client.js +++ b/client/js/client.js @@ -21,16 +21,6 @@ Handlebars.registerHelper("health", function(lives, options){ return out; }); -/* -var Config = {}; - -Config.Server = { - "hostname": "localhost", - "port": 16918, - secure: false -} -*/ - var App = Backbone.Router.extend({ routes: { "lobby": "lobbyRoute", @@ -137,7 +127,9 @@ var SideView = Backbone.View.extend({ this.$info.find(".score").html(d.score); this.$info.find(".hand-card").html(d.hand); this.$info.find(".gwent-lives").html(this.lives(d.lives)); - this.$info.find(".field-leader").html(this.template(l)) + if(l._key){ + this.$info.find(".field-leader").html(this.template(l)) + } if(this.app.user.get("waiting") && this.side === ".player"){ this.$info.addClass("removeBackground"); @@ -153,47 +145,61 @@ var SideView = Backbone.View.extend({ if(!this.field.close) return; this.$fields = this.$el.find(".battleside" + this.side); var $field = this.$fields.find(".field-close").parent(); - var cards = this.field.close._cards; - var score = this.field.close._score; + var cards = this.field.close.cards; + var score = this.field.close.score; + var horn = this.field.close.horn; var html = this.templateCards(cards); $field.find(".field-close").html(html) $field.find(".large-field-counter").html(score) + if(horn){ + this.$fields.find(".field-horn-close").html(this.template(horn)); + } - calculateCardMargin($field.find(".card"), 433, 70, cards.length); + calculateCardMargin($field.find(".card"), 351, 70, cards.length); }, renderRangeField: function(){ if(!this.field.ranged) return; this.$fields = this.$el.find(".battleside" + this.side); var $field = this.$fields.find(".field-range").parent(); - var cards = this.field.ranged._cards; - var score = this.field.ranged._score; + var cards = this.field.ranged.cards; + var score = this.field.ranged.score; + var horn = this.field.ranged.horn; var html = this.templateCards(cards); $field.find(".field-range").html(html) $field.find(".large-field-counter").html(score) - calculateCardMargin($field.find(".card"), 433, 70, cards.length); + if(horn){ + this.$fields.find(".field-horn-range").html(this.template(horn)); + } + + calculateCardMargin($field.find(".card"), 351, 70, cards.length); }, renderSiegeField: function(){ if(!this.field.siege) return; this.$fields = this.$el.find(".battleside" + this.side); var $field = this.$fields.find(".field-siege").parent(); - var cards = this.field.siege._cards; - var score = this.field.siege._score; + var cards = this.field.siege.cards; + var score = this.field.siege.score; + var horn = this.field.siege.horn; var html = this.templateCards(cards); $field.find(".field-siege").html(html) $field.find(".large-field-counter").html(score) - calculateCardMargin($field.find(".card"), 433, 70, cards.length); + if(horn){ + this.$fields.find(".field-horn-siege").html(this.template(horn)); + } + + calculateCardMargin($field.find(".card"), 351, 70, cards.length); }, renderWeatherField: function(){ if(!this.field.weather) return; var $weatherField = this.$el.find(".field-weather"); - var cards = this.field.weather._cards; + var cards = this.field.weather.cards; $weatherField.html(this.templateCards(cards)); return this; @@ -214,7 +220,7 @@ var SideView = Backbone.View.extend({ var calculateCardMargin = function($selector, totalWidth, cardWidth, n){ var w = totalWidth, c = cardWidth; var res; - if(n < 7) + if(n < 6) res = 0; else { res = -((w - c) / (n - 1) - c) + 1 @@ -240,6 +246,7 @@ var BattleView = Backbone.View.extend({ this.listenTo(user, "change:passing", this.render); this.listenTo(user, "change:openDiscard", this.render); this.listenTo(user, "change:setAgile", this.render); + this.listenTo(user, "change:setHorn", this.render); this.$hand = this.$el.find(".field-hand"); this.$preview = this.$el.find(".card-preview"); @@ -290,6 +297,14 @@ var BattleView = Backbone.View.extend({ } return; } + if(!!this.user.get("setHorn")){ + if(id === this.user.get("setHorn")){ + this.user.set("setHorn", false); + this.app.send("cancel:horn"); + this.render(); + } + return; + } if(!!this.user.get("waitForDecoy")){ if(id === this.user.get("waitForDecoy")){ this.user.set("waitForDecoy", false); @@ -313,6 +328,9 @@ var BattleView = Backbone.View.extend({ if(this.user.get("waitForDecoy")){ var $card = $(e.target).closest(".card"); var _id = $card.data("id"); + + if($card.parent().hasClass("field-horn")) return; + this.app.send("decoy:replaceWith", { cardID: _id }) @@ -328,6 +346,16 @@ var BattleView = Backbone.View.extend({ }); this.user.set("setAgile", false); } + if(this.user.get("setHorn")){ + var $field = $(e.target).closest(".field.active").find(".field-close, .field-range, .field-siege"); + + console.log($field); + var target = $field.hasClass("field-close") ? 0 : ($field.hasClass("field-range") ? 1 : 2); + this.app.send("horn:field", { + field: target + }); + this.user.set("setHorn", false); + } }, onMouseover: function(e){ var target = $(e.target).closest(".card"); @@ -355,13 +383,20 @@ var BattleView = Backbone.View.extend({ var self = this; this.$el.html(this.template({ cards: self.handCards, - agile: self.user.get("setAgile") + active: { + close: self.user.get("setAgile") || self.user.get("setHorn"), + range: self.user.get("setAgile") || self.user.get("setHorn"), + siege: self.user.get("setHorn") + } })); if(!(this.otherSide && this.yourSide)) return; this.otherSide.render(); this.yourSide.render(); - calculateCardMargin(this.$el.find(".field-hand .card"), 538, 70, this.handCards.length); + + if(this.handCards){ + calculateCardMargin(this.$el.find(".field-hand .card"), 538, 70, this.handCards.length); + } if(this.user.get("openDiscard")){ var modal = new Modal({model: this.user}); @@ -375,6 +410,10 @@ var BattleView = Backbone.View.extend({ var id = this.user.get("setAgile"); this.$el.find("[data-id='" + id + "']").addClass("activeCard"); } + if(this.user.get("setHorn")){ + var id = this.user.get("setHorn"); + this.$el.find("[data-id='" + id + "']").addClass("activeCard"); + } if(this.user.get("waitForDecoy")){ var id = this.user.get("waitForDecoy"); this.$el.find("[data-id='" + id + "']").addClass("activeCard"); @@ -529,6 +568,11 @@ var User = Backbone.Model.extend({ self.set("setAgile", data.cardID); }) + app.receive("played:horn", function(data){ + console.log("played horn"); + self.set("setHorn", data.cardID); + }) + app.on("createRoom", this.createRoom, this); app.on("joinRoom", this.joinRoom, this); app.on("setName", this.setName, this); diff --git a/client/scss/main.scss b/client/scss/main.scss index e0c5499..a5bcdd0 100644 --- a/client/scss/main.scss +++ b/client/scss/main.scss @@ -17,7 +17,7 @@ $game-height: 800px; } .field { - width: 100%; + //width: 100%; height: 100px; border: 1px solid black;/* overflow: hidden; @@ -35,6 +35,14 @@ $game-height: 800px; } } +.field-horn {/* + border: 1px solid green;*/ + /*clear: both;*/ + margin: 0px; + padding: 0px; + +} + .field:hover, .field-single:hover { box-shadow: 0px 0px 10px #000; } @@ -104,11 +112,11 @@ $game-height: 800px; span { color: #00b000; font-weight: bold; - font-size: 24px; + font-size: 20px; position: absolute; text-shadow: 1px 1px #101010; - margin-top: 55px; - margin-left: 30px; + margin-top: 62px; + margin-left: 0px; cursor: default; } diff --git a/gulpfile.js b/gulpfile.js index ba9d3e6..dbd8527 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -58,6 +58,7 @@ gulp.task("unit tests", function(){ gulp.task("watch", function(){ gulp.watch("./client/js/*", ["browserify"]); gulp.watch("./client/scss/*", ["sass"]); + gulp.watch("./client/*.html", ["index"]); gulp.watch("./test/src/*", ["unit tests"]); }) diff --git a/public/index.html b/public/index.html index eaf3ad9..f8811de 100644 --- a/public/index.html +++ b/public/index.html @@ -76,7 +76,6 @@
- {{#health lives}}{{/health}}
@@ -92,30 +91,42 @@
-
+
+
+
0
-
+
+
+
0
-
+
+
+
0
-
+
+
+
0
-
+
+
+
0
-
+
+
+
0
diff --git a/server/Battle.js b/server/Battle.js index 2d48979..1280498 100644 --- a/server/Battle.js +++ b/server/Battle.js @@ -61,11 +61,17 @@ var Battle = (function(){ this.p2.setLeadercard(); this.p1.draw(10); this.p2.draw(10); - this.p1.hand.add(Card("blue_stripes_commando")); - this.p2.hand.add(Card("blue_stripes_commando")); - this.p1.hand.add(Card("blue_stripes_commando")); - this.p2.hand.add(Card("blue_stripes_commando")); -/* + this.p1.hand.add(Card("commanders_horn")); + this.p2.hand.add(Card("commanders_horn")); + this.p1.hand.add(Card("commanders_horn")); + this.p2.hand.add(Card("commanders_horn")); + /* + 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("kaedweni_siege_expert")); this.p2.hand.add(Card("kaedweni_siege_expert")); this.p1.hand.add(Card("ballista")); @@ -77,8 +83,8 @@ var Battle = (function(){ this.p1.hand.add(Card("ballista")); this.p2.hand.add(Card("ballista")); this.p1.hand.add(Card("ballista")); - this.p2.hand.add(Card("ballista")); - this.p1.hand.add(Card("decoy")); + this.p2.hand.add(Card("ballista"));*/ + /*this.p1.hand.add(Card("decoy")); this.p2.hand.add(Card("decoy"));*/ /* this.p1.hand.add(Card("dun_banner_medic")); @@ -86,8 +92,8 @@ var Battle = (function(){ this.p1.hand.add(Card("isengrim_faoiltiarnah")); this.p2.hand.add(Card("isengrim_faoiltiarnah"));*/ - this.p1.addToDiscard([Card("kaedweni_siege_expert")]); - this.p2.addToDiscard([Card("kaedweni_siege_expert")]); + /*this.p1.addToDiscard([Card("kaedweni_siege_expert")]); + this.p2.addToDiscard([Card("kaedweni_siege_expert")]);*/ /* this.p1.hand.add(Card("decoy")); this.p1.hand.add(Card("impenetrable_fog")); @@ -155,10 +161,10 @@ var Battle = (function(){ 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] + close: p.field[Card.TYPE.CLOSE_COMBAT].getInfo(), + ranged: p.field[Card.TYPE.RANGED].getInfo(), + siege: p.field[Card.TYPE.SIEGE].getInfo(), + weather: p.field[Card.TYPE.WEATHER].getInfo() }) } diff --git a/server/Battleside.js b/server/Battleside.js index fb9a9f5..af0970a 100644 --- a/server/Battleside.js +++ b/server/Battleside.js @@ -21,10 +21,15 @@ Battleside = (function(){ this._isWaiting = true; this.socket = user.socket; this.field = {}; - this.field[Card.TYPE.LEADER] = Field(Card.TYPE.LEADER); - this.field[Card.TYPE.CLOSE_COMBAT] = Field(Card.TYPE.CLOSE_COMBAT); - this.field[Card.TYPE.RANGED] = Field(Card.TYPE.RANGED); - this.field[Card.TYPE.SIEGE] = Field(Card.TYPE.SIEGE); + this.field[Card.TYPE.LEADER] = Field(this); + this.field[Card.TYPE.CLOSE_COMBAT] = Field(this, true); + this.field[Card.TYPE.RANGED] = Field(this, true); + this.field[Card.TYPE.SIEGE] = Field(this, true); + /*this.field[Card.TYPE.HORN] = { + close: Field(this), + range: Field(this), + siege: Field(this) + };*/ this.n = n ? "p2" : "p1"; this._name = name; this.battle = battle; @@ -88,14 +93,24 @@ Battleside = (function(){ self.playCard(card); }) - this.receive("agile:field", function(data) { + this.receive("agile:field", function(data){ var fieldType = data.field; + if(!(fieldType in [0, 1])) throw new Error("set field agile: false fieldtype " + fieldType); self.runEvent("agile:setField", null, [fieldType]); self.runEvent("NextTurn", null, [self.foe]); }) this.receive("cancel:agile", function(){ self.off("agile:setField"); }) + this.receive("horn:field", function(data){ + var fieldType = data.field; + if(!(fieldType in [0, 1, 2])) throw new Error("set field horn: false fieldtype " + fieldType); + self.runEvent("horn:setField", null, [fieldType]); + self.runEvent("NextTurn", null, [self.foe]); + }) + this.receive("cancel:horn", function(){ + self.off("horn:setField"); + }) this.on("Turn" + this.getID(), this.onTurnStart, this); @@ -129,7 +144,7 @@ Battleside = (function(){ } r.setUpWeatherFieldWith = function(p2){ - this.field[Card.TYPE.WEATHER] = p2.field[Card.TYPE.WEATHER] = Field(Card.TYPE.WEATHER); + this.field[Card.TYPE.WEATHER] = p2.field[Card.TYPE.WEATHER] = Field(this); } r.findCardOnFieldByID = function(id){ @@ -279,8 +294,16 @@ Battleside = (function(){ this.checkAbilities(card, obj); if(obj._cancelPlacement) return 0; - var field = obj.targetSide.field[card.getType()]; - field.add(card); + + var field; + if(typeof obj.isHorn !== "undefined"){ + field = obj.targetSide.field[obj.isHorn]; + field.add(card, true); + } + else { + field = obj.targetSide.field[card.getType()]; + field.add(card); + } this.runEvent("EachCardPlace"); @@ -298,6 +321,49 @@ Battleside = (function(){ return 1; } + r.setHorn = function(card) { + var self = this; + this.send("played:horn", {cardID: card.getID()}, true) + this.on("horn:setField", function(type){ + self.off("horn:setField"); + card.changeType(type); + self.placeCard(card, { + isHorn: type, + disabled: true + }); + self.hand.remove(card); + }) + } + + r.commanderHornAbility = function(card) { + var field = this.field[card.getType()]; + var id = "commanders_horn"; + + if(typeof field === "undefined") { + //console.log("field unknown | %s", card.getName()); + return; + } + + if(!field.isOnField(card)){ + field.get().forEach(function(_card){ + if(_card.getID() == id) return; + if(_card.getType() != card.getType()) return; + if(_card.hasAbility("hero")) return; + _card.setBoost(id, 0); + }) + this.off("EachCardPlace", card.getUidEvents("EachCardPlace")); + return; + } + + field.get().forEach(function(_card){ + if(_card.getID() == id) return; + if(_card.getType() != card.getType()) return; + if(_card.hasAbility("hero")) return; + _card.setBoost(id, 0); + _card.setBoost(id, _card.getPower()); + }) + } + r.checkAbilities = function(card, obj, __flag){ var self = this; obj.targetSide = this; @@ -316,10 +382,17 @@ Battleside = (function(){ } if(ability && !Array.isArray(ability)){ - if(ability.onBeforePlace) { + if(ability.onBeforePlace){ ability.onBeforePlace.apply(this, [card]); } - if(ability.cancelPlacement) { + if(ability.isCommandersHornCard) { + this.setHorn(card); + } + if(ability.commandersHorn) { + ability.onEachCardPlace = this.commanderHornAbility; + ability.onWeatherChange = this.commanderHornAbility; + } + if(ability.cancelPlacement){ obj._cancelPlacement = true; } if(ability.waitResponse){ @@ -327,10 +400,11 @@ Battleside = (function(){ } if(ability.changeSide){ obj.targetSide = this.foe; - }/* - if(ability.onReset){ - this.on("Reset", ability.onReset, this, [card]) - }*/ + } + if(typeof ability.weather !== "undefined"){ + ability.onEachTurn = this.setWeather.bind(this, ability.weather); + ability.onEachCardPlace = this.setWeather.bind(this, ability.weather); + } if(ability.replaceWith){ obj._cancelPlacement = true; this.on("Decoy:replaceWith", function(replaceCard){ @@ -362,6 +436,10 @@ Battleside = (function(){ var uid = this.on("EachCardPlace", ability.onEachCardPlace, this, [card]); card._uidEvents["EachCardPlace"] = uid; } + if(ability.onWeatherChange){ + var uid = this.on("WeatherChange", ability.onWeatherChange, this, [card]); + card._uidEvents["WeatherChange"] = uid; + } this.update(); } @@ -380,6 +458,49 @@ Battleside = (function(){ } } + r.setWeather = function(weather){ + var targetRow = weather; + var field; + if(typeof targetRow === "undefined") return; + + + //console.log(this.field[Card.TYPE.WEATHER]); + if(targetRow === Card.TYPE.WEATHER){ + field = this.field[targetRow]; + field.removeAll(); + + for(var i = Card.TYPE.CLOSE_COMBAT; i <= Card.TYPE.SIEGE; i++) { + var _field1, _field2, _field; + _field1 = this.field[i].get(); + _field2 = this.foe.field[i].get(); + _field = _field1.concat(_field2); + + _field.forEach(function(_card){ + if(_card.hasAbility("hero")) return; + _card.setForcedPower(-1); + }); + } + this.runEvent("WeatherChange"); + return; + } + var forcedPower = 1; + + if(typeof targetRow === "undefined"){ + console.trace(this); + } + var field1 = this.field[targetRow].get(); + var field2 = this.foe.field[targetRow].get(); + + field = field1.concat(field2); + + field.forEach(function(_card){ + if(_card.hasAbility("hero")) return; + _card.setForcedPower(forcedPower); + }); + this.runEvent("WeatherChange"); + this.update(); + } + r.clearMainFields = function(){ var cards1 = this.field[Card.TYPE.CLOSE_COMBAT].removeAll(); var cards2 = this.field[Card.TYPE.RANGED].removeAll(); @@ -432,7 +553,7 @@ Battleside = (function(){ if(_.isArray(property)){ var _f = false; for(var i = 0; i < property.length; i++) { - if(property[i] === val) { + if(property[i] === val){ _f = true; break; } diff --git a/server/Card.js b/server/Card.js index 46a6481..9628582 100644 --- a/server/Card.js +++ b/server/Card.js @@ -17,7 +17,6 @@ var Card = (function(){ this._boost = {}; this._forcedPower = -1; this._init(); - }; var r = Card.prototype; /** @@ -68,6 +67,7 @@ var Card = (function(){ } r.setForcedPower = function(nr){ this._forcedPower = nr; + /*this.getBoost(); *///recalculate } r.getRawAbility = function(){ return this._data.ability; @@ -82,6 +82,16 @@ var Card = (function(){ } return AbilityData[this._data.ability]; } + r.hasAbility = function(ability) { + var a = this.getRawAbility(); + if(Array.isArray(a)) { + for(var i=0; i= 0; } @@ -69,13 +85,45 @@ var Field = (function(){ r.removeAll = function(){ var tmp = this._cards.slice(); + var self = this; tmp.forEach(function(card){ card.reset(); + for(var event in card._uidEvents) { + self.side.off(event, card.getUidEvents(event)); + } }) this._cards = []; + if(this.getHorn()) { + var card = this.getHorn(); + card.reset(); + this.setHorn(null); + for(var event in card._uidEvents) { + self.side.off(event, card.getUidEvents(event)); + } + tmp.push(card); + } return tmp; } + r.getInfo = function() { + var self = this; + return { + cards: self._cards, + horn: self.getHorn(), + score: self._score + } + } + + r.getHorn = function() { + if(!this._hasHornField) return null; + return this._hornCard; + } + + r.setHorn = function(card) { + if(!this._hasHornField) return null; + this._hornCard = card; + } + return Field; })(); diff --git a/server/Hand.js b/server/Hand.js index fd59edf..a001c10 100644 --- a/server/Hand.js +++ b/server/Hand.js @@ -23,7 +23,8 @@ var Hand = (function(){ */ r._hand = null; - r.add = function(card){ + r.add = function(card){/* + console.log(card.getID(), card.getName());*/ this._hand.push(card); } @@ -45,6 +46,8 @@ var Hand = (function(){ //console.trace(id); id = id instanceof Card ? id.getID() : id; + if(!n) return -1; + for(var i = 0; i < n; i++) { if(!this._hand[i]) { console.trace(this._hand[i]); @@ -59,6 +62,7 @@ var Hand = (function(){ r.getRandomCard = function(){ var rnd = (Math.random() * this._hand.length) | 0; + if(!this._hand.length) return -1; return this._hand[rnd]; } diff --git a/site/public/assets/css/app.css b/site/public/assets/css/app.css index 4b9901c..5898569 100644 --- a/site/public/assets/css/app.css +++ b/site/public/assets/css/app.css @@ -1 +1,567 @@ -/*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@font-face{font-family:'Titillium Web';font-style:normal;font-weight:300;src:local("Titillium WebLight"),local("TitilliumWeb-Light"),url(http://fonts.gstatic.com/s/titilliumweb/v4/anMUvcNT0H1YN4FII8wpr6YfJ4wTnNoNUCmOpdh16Tg.woff2) format("woff2"),url(http://fonts.gstatic.com/s/titilliumweb/v4/anMUvcNT0H1YN4FII8wpr1uKlGE8-OjkUKWan_M3D6s.woff) format("woff")}@font-face{font-family:'Titillium Web';font-style:normal;font-weight:400;src:local("Titillium Web"),local("TitilliumWeb-Regular"),url(http://fonts.gstatic.com/s/titilliumweb/v4/7XUFZ5tgS-tD6QamInJTceHuglUR2dhBxWD-q_ehMME.woff2) format("woff2"),url(http://fonts.gstatic.com/s/titilliumweb/v4/7XUFZ5tgS-tD6QamInJTcZ_o9VAbKgK36i-4snuAuCM.woff) format("woff")}@font-face{font-family:'Titillium Web';font-style:normal;font-weight:600;src:local("Titillium WebSemiBold"),local("TitilliumWeb-SemiBold"),url(http://fonts.gstatic.com/s/titilliumweb/v4/anMUvcNT0H1YN4FII8wpr6d1JQt-lS5nD-1TJX2NNl0.woff2) format("woff2"),url(http://fonts.gstatic.com/s/titilliumweb/v4/anMUvcNT0H1YN4FII8wprx3QmhlKDgQgT1VN2Ed1WFo.woff) format("woff")}*{padding:0;box-sizing:border-box}body,html{height:100%}body{width:100%;font-family:'Titillium Web',sans-serif}::-moz-selection{background:rgba(217,111,31,.99);color:#fff;text-shadow:none}::selection{background:rgba(217,111,31,.99);color:#fff;text-shadow:none}input,textarea{font-family:'Titillium Web',sans-serif;outline:0}a{text-decoration:none}ul{list-style:none}.wrap-modal{max-width:600px;margin:0 auto}.modal{position:fixed;width:100%;height:100%;left:0;top:0;right:0;bottom:0;background:rgba(14,27,43,.8);z-index:10;opacity:0;visibility:hidden}.modal.active{visibility:visible;opacity:1;transition:all .3s ease-in-out 0s}.modal-banner{z-index:20;background:rgba(6,13,22,.95);width:100%;color:#fff;padding:50px 0;margin:15% 0 0;float:left}.icon-load{background:url(../img/load.gif) no-repeat #ca5a07;width:16px;height:16px;float:right;margin:5px -7px 0 7px;display:none}.form-session{float:left}.field-session{float:left;padding:10px 20px;border:0;color:#8798ac;font-size:16px;margin:0 10px 0 0;height:48px;width:220px;background:#243141;background:linear-gradient(to right,#243141 0,#334152 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#243141', endColorstr='#334152', GradientType=1)}.wrap-btn-action{float:left;padding:10px 20px;cursor:pointer;height:48px;background:#da7020;background:linear-gradient(to right,#da7020 0,#ca5907 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#da7020', endColorstr='#ca5907', GradientType=1)}.btn-action{color:#fff;font-size:16px;font-weight:400;border:0;background:0 0;cursor:pointer;float:left;text-transform:uppercase}.btn-none,.btn-second{color:#fff;font-size:16px;font-weight:400;border:0;padding:10px 20px;float:left;position:relative;cursor:pointer;height:48px;text-transform:uppercase;text-decoration:none;background:#243141;background:linear-gradient(to right,#243141 0,#334152 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#243141', endColorstr='#334152', GradientType=1)}.btn-none{background:0 0;color:#8798ac;transition:color .3s ease-in-out 0s}.btn-none:hover{color:#fff}body.landing{background:url(../img/landing-bg.jpg) center top no-repeat;background-size:cover}.wrap-landing{max-width:900px;margin:0 auto}.logo-big{margin:0 auto;display:block}.container-landing{float:left;width:100%;margin:12% 0 0}.teaser-landing{text-align:center;font-size:21px;font-weight:300;text-shadow:0 0 10px rgba(255,255,255,.6);color:#8798ac;line-height:29pt;cursor:default}.choose{float:left;color:#8798ac;margin:10px 30px;cursor:default}.container-form-landing{margin:40px 0;opacity:0}.container-form-landing.active{transition:all .4s ease-in-out .2s;margin:60px 0;opacity:1} \ No newline at end of file +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ +html { + font-family: sans-serif; + /* 1 */ + -ms-text-size-adjust: 100%; + /* 2 */ + -webkit-text-size-adjust: 100%; + /* 2 */ } + +/** + * Remove default margin. + */ +body { + margin: 0; } + +/* HTML5 display definitions + ========================================================================== */ +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; } + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ +audio, +canvas, +progress, +video { + display: inline-block; + /* 1 */ + vertical-align: baseline; + /* 2 */ } + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ +audio:not([controls]) { + display: none; + height: 0; } + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ +[hidden], +template { + display: none; } + +/* Links + ========================================================================== */ +/** + * Remove the gray background color from active links in IE 10. + */ +a { + background-color: transparent; } + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ +a:active, +a:hover { + outline: 0; } + +/* Text-level semantics + ========================================================================== */ +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ +abbr[title] { + border-bottom: 1px dotted; } + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ +b, +strong { + font-weight: bold; } + +/** + * Address styling not present in Safari and Chrome. + */ +dfn { + font-style: italic; } + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; } + +/** + * Address styling not present in IE 8/9. + */ +mark { + background: #ff0; + color: #000; } + +/** + * Address inconsistent and variable font size in all browsers. + */ +small { + font-size: 80%; } + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +/* Embedded content + ========================================================================== */ +/** + * Remove border when inside `a` element in IE 8/9/10. + */ +img { + border: 0; } + +/** + * Correct overflow not hidden in IE 9/10/11. + */ +svg:not(:root) { + overflow: hidden; } + +/* Grouping content + ========================================================================== */ +/** + * Address margin not present in IE 8/9 and Safari. + */ +figure { + margin: 1em 40px; } + +/** + * Address differences between Firefox and other browsers. + */ +hr { + box-sizing: content-box; + height: 0; } + +/** + * Contain overflow in all browsers. + */ +pre { + overflow: auto; } + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; } + +/* Forms + ========================================================================== */ +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ +button, +input, +optgroup, +select, +textarea { + color: inherit; + /* 1 */ + font: inherit; + /* 2 */ + margin: 0; + /* 3 */ } + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ +button { + overflow: visible; } + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ +button, +select { + text-transform: none; } + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ +button, +html input[type="button"], input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + /* 2 */ + cursor: pointer; + /* 3 */ } + +/** + * Re-set default cursor for disabled elements. + */ +button[disabled], +html input[disabled] { + cursor: default; } + +/** + * Remove inner padding and border in Firefox 4+. + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; } + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ +input { + line-height: normal; } + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; } + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ +input[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + /* 2 */ + box-sizing: content-box; } + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +/** + * Define consistent border, margin, and padding. + */ +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; } + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ +legend { + border: 0; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ +textarea { + overflow: auto; } + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ +optgroup { + font-weight: bold; } + +/* Tables + ========================================================================== */ +/** + * Remove most spacing between table cells. + */ +table { + border-collapse: collapse; + border-spacing: 0; } + +td, +th { + padding: 0; } + +@font-face { + font-family: 'Titillium Web'; + font-style: normal; + font-weight: 300; + src: local("Titillium WebLight"), local("TitilliumWeb-Light"), url(http://fonts.gstatic.com/s/titilliumweb/v4/anMUvcNT0H1YN4FII8wpr6YfJ4wTnNoNUCmOpdh16Tg.woff2) format("woff2"), url(http://fonts.gstatic.com/s/titilliumweb/v4/anMUvcNT0H1YN4FII8wpr1uKlGE8-OjkUKWan_M3D6s.woff) format("woff"); } + +@font-face { + font-family: 'Titillium Web'; + font-style: normal; + font-weight: 400; + src: local("Titillium Web"), local("TitilliumWeb-Regular"), url(http://fonts.gstatic.com/s/titilliumweb/v4/7XUFZ5tgS-tD6QamInJTceHuglUR2dhBxWD-q_ehMME.woff2) format("woff2"), url(http://fonts.gstatic.com/s/titilliumweb/v4/7XUFZ5tgS-tD6QamInJTcZ_o9VAbKgK36i-4snuAuCM.woff) format("woff"); } + +@font-face { + font-family: 'Titillium Web'; + font-style: normal; + font-weight: 600; + src: local("Titillium WebSemiBold"), local("TitilliumWeb-SemiBold"), url(http://fonts.gstatic.com/s/titilliumweb/v4/anMUvcNT0H1YN4FII8wpr6d1JQt-lS5nD-1TJX2NNl0.woff2) format("woff2"), url(http://fonts.gstatic.com/s/titilliumweb/v4/anMUvcNT0H1YN4FII8wprx3QmhlKDgQgT1VN2Ed1WFo.woff) format("woff"); } + +* { + padding: 0; + box-sizing: border-box; } + +html, +body { + height: 100%; } + +body { + width: 100%; + font-family: 'Titillium Web', sans-serif; } + +body.inner { + background: url(../img/inner-bg.jpg) center top no-repeat; + background-size: cover; } + +::-moz-selection { + background: rgba(217, 111, 31, 0.99); + color: #fff; + text-shadow: none; } + +::selection { + background: rgba(217, 111, 31, 0.99); + color: #fff; + text-shadow: none; } + +input, textarea { + font-family: 'Titillium Web', sans-serif; + outline: 0; } + +a { + text-decoration: none; } + +ul { + list-style: none; } + +.wrap-modal { + max-width: 600px; + margin: 0 auto; } + +.modal { + position: fixed; + width: 100%; + height: 100%; + left: 0; + top: 0; + right: 0; + bottom: 0; + background: rgba(14, 27, 43, 0.8); + z-index: 10; + opacity: 0; + visibility: hidden; } + .modal.active { + visibility: visible; + opacity: 1; + transition: all 0.3s ease-in-out 0s; } + +.modal-banner { + z-index: 20; + background: rgba(6, 13, 22, 0.95); + width: 100%; + color: #fff; + padding: 50px 0; + margin: 15% 0 0 0; + float: left; } + +.icon-load { + background: url(../img/load.gif) #ca5a07 no-repeat; + width: 16px; + height: 16px; + float: right; + margin: 5px -7px 0 7px; + display: none; } + +.form-session { + float: left; } + +.field-session { + float: left; + padding: 10px 20px; + border: 0; + color: #8798ac; + font-size: 16px; + margin: 0 10px 0 0; + height: 48px; + width: 220px; + background: #243141; + background: linear-gradient(to right, #243141 0%, #334152 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#243141', endColorstr='#334152',GradientType=1 ); } + +.wrap-btn-action { + float: left; + padding: 10px 20px; + cursor: pointer; + height: 48px; + background: #da7020; + background: linear-gradient(to right, #da7020 0%, #ca5907 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#da7020', endColorstr='#ca5907',GradientType=1 ); + transition: box-shadow 0.3s ease-in-out 0s; } + .wrap-btn-action:hover { + box-shadow: 0 0 10px 0 rgba(217, 111, 31, 0.8); } + +.btn-action { + color: #fff; + font-size: 16px; + font-weight: 400; + border: 0; + background: transparent; + cursor: pointer; + float: left; + text-transform: uppercase; } + +.btn-second, +.btn-none { + color: #fff; + font-size: 16px; + font-weight: 400; + border: 0; + padding: 10px 20px; + float: left; + position: relative; + cursor: pointer; + height: 48px; + text-transform: uppercase; + text-decoration: none; + background: #243141; + background: linear-gradient(to right, #243141 0%, #334152 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#243141', endColorstr='#334152',GradientType=1 ); + transition: all 0.3s ease-in-out 0s; } + +.btn-second:hover { + box-shadow: 0 0 10px 0 rgba(255, 255, 255, 0.1); } + +.btn-none { + background: transparent; + color: #8798ac; } + .btn-none:hover { + color: #fff; } + +::-webkit-input-placeholder { + color: #697e97; } + +:-moz-placeholder { + color: #697e97; + opacity: 1; } + +::-moz-placeholder { + color: #697e97; + opacity: 1; } + +:-ms-input-placeholder { + color: #697e97; } + +body.landing { + background: url(../img/landing-bg.jpg) center top no-repeat; + background-size: cover; } + +.wrap-landing { + max-width: 900px; + margin: 0 auto; } + +.logo-big { + margin: 0 auto; + display: block; } + +.container-landing { + float: left; + width: 100%; + margin: 12% 0 0 0; } + @media (max-width: 1450px) { + .container-landing { + margin: 9% 0 0 0; } } + +.teaser-landing { + text-align: center; + font-size: 21px; + font-weight: 300; + text-shadow: 0 0 10px rgba(255, 255, 255, 0.6); + color: #8798ac; + line-height: 29pt; + cursor: default; } + +.choose { + float: left; + color: #8798ac; + margin: 10px 30px; + cursor: default; } + +.container-form-landing { + margin: 40px 0; + opacity: 0; } + .container-form-landing.active { + transition: all 0.4s ease-in-out 0s; + margin: 60px 0; + opacity: 1; } diff --git a/site/server/composer.lock b/site/server/composer.lock index 01a2762..dfe1a7c 100644 --- a/site/server/composer.lock +++ b/site/server/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "5c6026b96e6fa11a641b51a6ba976f5e", + "hash": "541ee30ee4a0e782a2473d5a9ab09eb0", "packages": [ { "name": "classpreloader/classpreloader", diff --git a/test/src/CardSpec.js b/test/src/CardSpec.js new file mode 100644 index 0000000..8a0fa21 --- /dev/null +++ b/test/src/CardSpec.js @@ -0,0 +1,13 @@ +var Card = require("../../server/Card"); + +describe("cards", function(){ + var card; + + beforeEach(function() { + card = Card("john_natalis"); + }); + + it("should have hero ability", function() { + expect(card.hasAbility("hero")).toBe(true); + }) +}) \ No newline at end of file diff --git a/test/src/PubSubSpec.js b/test/src/PubSubSpec.js index 1b9951d..217b412 100644 --- a/test/src/PubSubSpec.js +++ b/test/src/PubSubSpec.js @@ -94,5 +94,37 @@ describe("pubsub", function(){ expect(battle.events).toEqual({});*/ }) + it("should give binded ctx", function() { + var obj = {}, otherCtx = { key: "test"}; + var card = Card("biting_frost"); + var ability = card.getAbility(); + + obj.setWeather = function(weatherType) { + expect(weatherType).toEqual(0); + expect(this).toBe(otherCtx); + } + + spyOn(obj, "setWeather").and.callThrough(); + + expect(ability.weather).toBeDefined(); + + ability.onEachTurn = obj.setWeather.bind(otherCtx, ability.weather); + ability.onEachCardPlace = obj.setWeather.bind(otherCtx, ability.weather); + + if(ability.onEachTurn){ + var uid = battle.on("EachTurn", ability.onEachTurn, battle, [card]) + card._uidEvents["EachTurn"] = uid; + } + if(ability.onEachCardPlace){ + var uid = battle.on("EachCardPlace", ability.onEachCardPlace, battle, [card]); + card._uidEvents["EachCardPlace"] = uid; + } + + battle.runEvent("EachCardPlace"); + battle.runEvent("EachTurn"); + + expect(obj.setWeather).toHaveBeenCalled(); + }) + }); diff --git a/test/src/mainSpec.js b/test/src/mainSpec.js index fbe8f19..677153e 100644 --- a/test/src/mainSpec.js +++ b/test/src/mainSpec.js @@ -1,5 +1,6 @@ require("./filterSpec"); require("./PubSubSpec"); +require("./CardSpec"); (function main(){