diff --git a/index.html b/index.html index f239eed..84ac370 100644 --- a/index.html +++ b/index.html @@ -20,17 +20,19 @@ + - - + + + diff --git a/js/common/being.js b/js/common/being.js index cc38855..53bf5fa 100644 --- a/js/common/being.js +++ b/js/common/being.js @@ -112,10 +112,14 @@ Game.Being.prototype.getMaxHP = function() { Game.Being.prototype.adjustHP = function(diff) { this._hp = Math.max(0, this._hp + diff); - if (!this._hp) { this._die(); } + if (!this._hp) { this.die(); } return this; } +Game.Being.prototype.getWeapon = function() { + return this._weapon; +} + Game.Being.prototype.attack = function(target) { /* FIXME probably refactor to a dedicated attack logic? */ @@ -151,7 +155,7 @@ Game.Being.prototype.attack = function(target) { Game.status.show(str); } -Game.Being.prototype._die = function() { +Game.Being.prototype.die = function() { var corpse = Game.Items.create("corpse", {color:this._color, name:this._name+" corpse"}); this._level.setItem(corpse, this._position[0], this._position[1]); this._level.removeBeing(this); diff --git a/js/common/level.js b/js/common/level.js index 781dfba..f34c06e 100644 --- a/js/common/level.js +++ b/js/common/level.js @@ -3,7 +3,7 @@ Game.Level = function() { this.beings = {}; this.items = {}; - this._display = new ROT.Display({fontFamily:"droid sans mono, monospace"}); + this._display = new Game.Display({fontFamily:"droid sans mono, monospace"}); this._ambientLight = [130, 130, 130]; this._sightRange = 8; @@ -290,7 +290,10 @@ Game.Level.prototype._draw = function(x, y) { if (!(key in this._visibleArea)) { return; } var entity = this.beings[key] || this.items[key] || this.cells[key]; - if (entity) { this._display.draw(x, y, entity.getChar(), ROT.Color.toRGB(entity.getColor())); } + if (entity) { + this._display.draw(x, y, entity.getChar(), ROT.Color.toRGB(entity.getColor())); + if (entity == Game.player) { this._display.setCursor(x, y); } + } } Game.Level.prototype._drawFog = function(x, y) { @@ -309,7 +312,6 @@ Game.Level.prototype._drawFog = function(x, y) { /* 3. average */ var gray = (color[0]+color[1]+color[2])/3; - var c1 = 0.4; var c2 = 1-c1; diff --git a/js/common/lib/beings.js b/js/common/lib/beings.js index 588c716..531e944 100644 --- a/js/common/lib/beings.js +++ b/js/common/lib/beings.js @@ -4,6 +4,11 @@ Game.Beings.define("animal", { tasks: ["wander"] }); +Game.Beings.define("humanoid", { + tasks: ["wander"], + "char": "@" +}); + Game.Beings.define("dog", { extend: "animal", name: "dog", @@ -11,10 +16,6 @@ Game.Beings.define("dog", { "char": "d" }); -Game.Beings.define("humanoid", { - tasks: ["wander"], -}); - Game.Beings.define("rat", { extend: "animal", name: "rat", @@ -24,7 +25,6 @@ Game.Beings.define("rat", { Game.Beings.define("mugger", { extend: "humanoid", - "char": "M", name: "mugger", color: [160, 100, 100], chats: [ diff --git a/js/common/lib/cells.js b/js/common/lib/cells.js index 27020d2..0467827 100644 --- a/js/common/lib/cells.js +++ b/js/common/lib/cells.js @@ -77,20 +77,6 @@ Game.Cells.define("tree", { name: "tree" }); -Game.Cells.define("flower", { - "char": "*", - colors: [ - [240, 60, 60], - [60, 60, 240], - [240, 120, 30], - [240, 120, 120], - [240, 240, 30], - [240, 30, 240], - [240, 240, 240], - ], - name: "flower" -}); - /* features */ Game.Cells.define("staircase-up", { diff --git a/js/common/repository.js b/js/common/repository.js index 9c47e93..525fc36 100644 --- a/js/common/repository.js +++ b/js/common/repository.js @@ -15,7 +15,7 @@ Game.Repository.prototype.is = function(type, parent) { } Game.Repository.prototype.define = function(type, template) { - if (template.extend) { /* create prototype link to parent definition */ + if ("extend" in template) { /* create prototype link to parent definition */ if (!(template.extend in this._storage)) { throw new Error("Repository type '"+type+"' cannot extend '"+template.extend+"'"); } @@ -34,7 +34,8 @@ Game.Repository.prototype.create = function(type, template) { var finalTemplate = Object.create(this._storage[type]); for (var p in template) { finalTemplate[p] = template[p]; } - var ctor = finalTemplate.ctor || this._defaultCtor; /* constructor function */ + /* constructor function; ternary operator guarantees crash instead of wrong ctor */ + var ctor = ("ctor" in finalTemplate ? finalTemplate.ctor : this._defaultCtor); return new ctor(type).fromTemplate(finalTemplate); } diff --git a/js/display.js b/js/display.js new file mode 100644 index 0000000..2b30f9a --- /dev/null +++ b/js/display.js @@ -0,0 +1,30 @@ +Game.Display = function(options) { + var o = options || {}; + o.layout = "rectCursor"; + ROT.Display.call(this, o); + this._cursor = ""; +} +Game.Display.extend(ROT.Display); + +Game.Display.prototype.setCursor = function(x, y) { + this._cursor = x+","+y; +} + +Game.Display.prototype._draw = function(key, clearBefore) { + ROT.Display.prototype._draw.call(this, key, clearBefore); + if (key == this._cursor) { + var parts = this._cursor.split(","); + this._backend.drawCursor(parseInt(parts[0]), parseInt(parts[1]), this._data[key][3]); + } +} + +ROT.Display.RectCursor = function(context) { + ROT.Display.Rect.call(this, context); +} +ROT.Display.RectCursor.extend(ROT.Display.Rect); + +ROT.Display.RectCursor.prototype.drawCursor = function(x, y, color) { + var height = Math.round(this._spacingY / 10); + this._context.fillStyle = color; + this._context.fillRect(x*this._spacingX, (y+1)*this._spacingY - height, this._spacingX, height); +} diff --git a/js/game.js b/js/game.js index 80ad82b..09b60dc 100644 --- a/js/game.js +++ b/js/game.js @@ -3,6 +3,9 @@ var Game = { player: null, level: null, story: null, + storyFlags: { + wantsFlower: false + }, init: function() { window.addEventListener("load", this); diff --git a/js/lib/beings.js b/js/lib/beings.js index 16fa413..24057a9 100644 --- a/js/lib/beings.js +++ b/js/lib/beings.js @@ -1,6 +1,5 @@ Game.Beings.define("player", { extend: "humanoid", - "char": "@", pv: 3, hp: 10, damage: 3, @@ -11,23 +10,43 @@ Game.Beings.define("player", { Game.Beings.define("guard", { extend: "humanoid", name: "guard", - "char": "G", tasks: [], color: [220, 140, 140] }); Game.Beings.define("jester", { extend: "humanoid", - "char": "J", - ctor: Game.Being.Jester, + chats: ["There is a secret passage to the kitchen, hidden in the throne room. But only the King shall know about it!"], name: "jester", color: [240, 100, 100] }); Game.Beings.define("gardener", { extend: "humanoid", - "char": "G", name: "gardener", chats: ["Good day to you, sir!", "Watch these flowers blossom!", "This garden needs my attention."], color: [100, 240, 100], }); + +Game.Beings.define("bride", { + extend: "humanoid", + ctor: Game.Being.Bride, + tasks: [], + name: "bride", + color: [240, 240, 240] +}); + +Game.Beings.define("groom", { + extend: "humanoid", + tasks: [], + name: "groom", + color: [80, 80, 80] +}); + +Game.Beings.define("priest", { + extend: "humanoid", + tasks: [], + chats: ["You would like to talk to the bride - and you brought her nothing? Shame on you!"], + name: "priest", + color: [200, 30, 200] +}); diff --git a/js/lib/bride.js b/js/lib/bride.js new file mode 100644 index 0000000..9c49777 --- /dev/null +++ b/js/lib/bride.js @@ -0,0 +1,5 @@ +Game.Being.Bride = function(type) { + Game.Being.call(this, type); +} +Game.Being.Bride.extend(Game.Being); + diff --git a/js/gate.js b/js/lib/gate.js similarity index 100% rename from js/gate.js rename to js/lib/gate.js diff --git a/js/lib/items.js b/js/lib/items.js new file mode 100644 index 0000000..b7b2859 --- /dev/null +++ b/js/lib/items.js @@ -0,0 +1,15 @@ +Game.Items.define("flower", { + extend: "weapon", + damage: 0, + "char": "*", + colors: [ + [240, 60, 60], + [60, 60, 240], + [240, 120, 30], + [240, 120, 120], + [240, 240, 30], + [240, 30, 240], + [240, 240, 240], + ], + name: "flower" +}); diff --git a/js/jester.js b/js/lib/jester.js similarity index 100% rename from js/jester.js rename to js/lib/jester.js diff --git a/js/player.js b/js/player.js index f3fa852..9ae0796 100644 --- a/js/player.js +++ b/js/player.js @@ -1,4 +1,5 @@ Game.Player = function(type) { + this._debug = true; Game.Being.call(this, type); this._light = [30, 30, 30]; @@ -90,7 +91,7 @@ Game.Player.prototype.setPosition = function(x, y, level) { Game.Player.prototype.updateVisibility = function() { var visibility = this._getVisibleArea(); - this._level.setVisibility(/*true ||*/ visibility); + this._level.setVisibility(this._debug || visibility); } Game.Player.prototype._getVisibleArea = function() { @@ -166,7 +167,7 @@ Game.Player.prototype._pickItem = function(x, y) { return; } - if (Game.Items.is(type, "weapon")) { + if (Game.Items.is(type, "weapon") && (type != "flower" || Game.storyFlags.wantsFlower)) { this._level.removeItem(item); if (this._weapon) { @@ -194,8 +195,8 @@ Game.Player.prototype.adjustHP = function(diff) { this._updateStats(); } -Game.Player.prototype._die = function() { - Game.Being.prototype._die.call(this); +Game.Player.prototype.die = function() { + Game.Being.prototype.die.call(this); this._char = "☠"; this._color = [255, 255, 255]; Game.over(); diff --git a/levels/castle.js b/levels/castle.js index 2e9367d..d83e4b8 100644 --- a/levels/castle.js +++ b/levels/castle.js @@ -6,6 +6,7 @@ Game.Level.Castle = function() { this._gates = []; this._guards = []; this._jester = null; + this._gardener = null; this._rats = []; } Game.Level.Castle.extend(Game.Level); @@ -23,6 +24,7 @@ Game.Level.Castle.prototype.fromTemplate = function(map, def) { if (being.getType() == "guard") { this._guards.push(being); } if (being.getType() == "jester") { this._jester = being; } if (being.getType() == "rat") { this._rats.push(being); } + if (being.getType() == "gardener") { this._gardener = being; } } this._initStory(); @@ -114,4 +116,12 @@ Game.Level.Castle.prototype._initStory = function() { Game.story.newChapter("Me versus rats – 3:0. Nice. Now let's get to that chapel before the wedding is over!"); return true; }); + + this._addRule(function() { + return Game.storyFlags.wantsFlower; + }, function() { + this.removeBeing(this._gardener); + Game.engine.removeActor(this._gardener); + return true; + }); } diff --git a/levels/castle.txt b/levels/castle.txt index e725438..deb69bb 100644 --- a/levels/castle.txt +++ b/levels/castle.txt @@ -74,7 +74,8 @@ T==========w# ##################5#### "item": "gold" }, "f": { - "cell": "flower" + "cell": "grass", + "item": "flower" }, "W": { "cell": "well" diff --git a/levels/chapel.js b/levels/chapel.js index a4b0393..d5d02f7 100644 --- a/levels/chapel.js +++ b/levels/chapel.js @@ -1,13 +1,27 @@ Game.Level.Chapel = function() { + /* FIXME druhy blocker krom priesta; konverzace a AI guestu */ Game.Level.call(this); this._lighting.setOptions({range:8}); + + this._priest = null; + this._bride = null; + this._groom = null; + this._guests = []; } Game.Level.Chapel.extend(Game.Level); Game.Level.Chapel.prototype.fromTemplate = function(map, def) { Game.Level.prototype.fromTemplate.call(this, map, def); + for (var key in this.beings) { + var being = this.beings[key]; + if (being.getType() == "guest") { this._guests.push(being); } + if (being.getType() == "priest") { this._priest = being; } + if (being.getType() == "bride") { this._bride = being; } + if (being.getType() == "groom") { this._groom = being; } + } + this._initStory(); return this; } @@ -19,4 +33,31 @@ Game.Level.Chapel.prototype._initStory = function() { Game.story.newChapter("I finally arrived at the chapel. By this time the wedding ceremony is probably already over, so I should at least get in and give my congratulations. I guess a lot of people are attending..."); return true; /* remove from rule list */ }); + + this._addRule(function() { + return this._priest.chattedWith(); + }, function() { + Game.story.addChapter("Indeed, it would be polite to bring some gift to the bride. I was in a hurry, so I brought nothing. Fortunately, I noticed some beautifully blossoming flowers in the castle garden."); + Game.story.setTask("Get back to castle garden and bring a flower."); + Game.storyFlags.wantsFlower = 1; + return true; + }); + + this._addRule(function() { + var weapon = Game.player.getWeapon(); + return (weapon && weapon.getType() == "flower"); + }, function() { + this._groom.die(); /* :-/ */ + + var pos = this.getCellById("window").getPosition(); + var floor = Game.Cells.create("floor"); + this.setCell(floor, pos[0], pos[1]); + + var pos = this.getCellById("exit").getPosition(); + var staircase = Game.Cells.create("staircase-down"); + this.setCell(staircase, pos[0], pos[1]); + + + return true; + }); } diff --git a/levels/chapel.txt b/levels/chapel.txt index 7a3ad44..04e0637 100644 --- a/levels/chapel.txt +++ b/levels/chapel.txt @@ -8,9 +8,9 @@ =--====#....................................±..#============= =--====#..............................#........#$============ =--====#....##..##..##..##..##..##..######//##########======= -==---==#.............................................###===== -===----/.........|G|.|G|.|G|.|G|.|G|.|G|.|.....±.......##==== -=====--/.........|G|.|G|.|G|.|G|.|G|.|G|.|.....±.......##==== +==---==#.......................................P.....###===== +===----/.........|g|.|g|.|g|.|g|.|g|.|g|.|.....±B......##==== +=====--/.........|g|.|g|.|g|.|g|.|g|.|g|.|.....±G......##==== =======#.............................................###===== =======#....##..##..##..##..##..##..######//##########======= =======#..............................#........#======+====== @@ -20,7 +20,7 @@ =====================================+=========+============= ===============================+===+======+=========+===+==== =============================+==================+=========+== -=================================+===========+=======+======= +=================================+========>==+=======+======= =====================================+=====================+= ============================================================= @@ -60,6 +60,12 @@ "+": { "cell": "tombstone" }, + ">": { + "cell": { + "type": "grass", + "id": "exit" + } + }, "±": { "cell": "altar" }, @@ -90,16 +96,27 @@ "name": "stained glass window" } }, - "G": { + "g": { "cell": "floor", "being": { "type": "humanoid", "name": "wedding guest", - "char": "G", "color": [140, 140, 140], "colorVariation": [30, 30, 30] } }, + "B": { + "cell": "floor", + "being": "bride" + }, + "G": { + "cell": "floor", + "being": "groom" + }, + "P": { + "cell": "floor", + "being": "priest" + }, "1": { "cell": { "type": "path",