diff --git a/game/engine/KeyCommand.lua b/game/engine/KeyCommand.lua index b56d75055a176d0232a6a62aa776ef265202e773..b26f0715f8e0107f94debb0d8e5932823df4f03c 100644 --- a/game/engine/KeyCommand.lua +++ b/game/engine/KeyCommand.lua @@ -36,9 +36,7 @@ function _M:receiveKey(sym, ctrl, shift, alt, meta, unicode) if not self.commands[sym] and not self.commands[self.__DEFAULT] then if self.on_input and unicode then self.on_input(unicode) end - return - end - if self.commands[sym] and (ctrl or shift or alt or meta) and not self.commands[sym].anymod then + elseif self.commands[sym] and (ctrl or shift or alt or meta) and not self.commands[sym].anymod then local mods = {} if alt then mods[#mods+1] = "alt" end if ctrl then mods[#mods+1] = "ctrl" end @@ -53,6 +51,8 @@ function _M:receiveKey(sym, ctrl, shift, alt, meta, unicode) elseif self.commands[self.__DEFAULT] and self.commands[self.__DEFAULT].plain then self.commands[self.__DEFAULT].plain(sym, ctrl, shift, alt, meta, unicode) end + + if self.atLast then self.atLast(sym, ctrl, shift, alt, meta, unicode) end end --- Adds a key/command combinaison diff --git a/game/engine/LogFlasher.lua b/game/engine/LogFlasher.lua new file mode 100644 index 0000000000000000000000000000000000000000..62c5a9f0cf411360a03b2e9ef0eac95efe8cea7c --- /dev/null +++ b/game/engine/LogFlasher.lua @@ -0,0 +1,74 @@ +require "engine.class" + +--- Module that handles a single message line, with pausing and flashing +module(..., package.seeall, class.make) + +GOOD = 1 +NEUTRAL = 2 +BAD = 3 + +--- Creates the log zone +function _M:init(x, y, w, h, max, fontname, fontsize, color, bgcolor) + self.color = color or {255,255,255} + self.bgcolor = bgcolor or {0,0,0} + self.display_x, self.display_y = x, y + self.w, self.h = w, h + self.font = core.display.newFont(fontname or "/data/font/Vera.ttf", fontsize or 16) + self.font_h = self.font:lineSkip() + self.surface = core.display.newSurface(w, h) + self.log = {} + getmetatable(self).__call = _M.call + self.flashing_style = NEUTRAL + self.flashing = 0 + self.changed = true +end + +--- Appends text to the log +-- This method is set as the call methamethod too, this means it is usable like this:<br/> +-- log = LogDisplay.new(...)<br/> +-- log("foo %s", s) +function _M:call(style, str, ...) + if self.flashing == 0 and #self.log > 0 then self.log = {} end + + local base = "" + if #self.log > 0 then base = table.remove(self.log) end + + local lines = (base .. " " .. str:format(...)):splitLines(self.w - 4, self.font) + for i = 1, #lines do + table.insert(self.log, lines[i]) + end + self.flashing_style = style + self.flashing = 20 + self.changed = true +end + +--- Clear the log +function _M:empty(force) + if self.flashing == 0 or force then + self.log = {} + self.flashing = 0 + self.changed = true + end +end + +function _M:display() + -- If nothing changed, return the same surface as before + if not self.changed then return self.surface end + self.changed = false + + -- Erase and the display the map + if self.flashing_style == BAD then + self.surface:erase(self.bgcolor[1] + self.flashing * 10, self.bgcolor[2], self.bgcolor[3]) + elseif self.flashing_style == NEUTRAL then + self.surface:erase(self.bgcolor[1], self.bgcolor[2], self.bgcolor[3] + self.flashing * 10) + else + self.surface:erase(self.bgcolor[1], self.bgcolor[2] + self.flashing * 10, self.bgcolor[3]) + end + self.surface:drawColorString(self.font, self.log[1] or "", 0, 0, self.color[1], self.color[2], self.color[3]) + + self.flashing = self.flashing - 1 + if self.flashing > 0 then self.changed = true + else table.remove(self.log, 1) end + + return self.surface +end diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index be0e2c5e22ea8e6c63beb2cc3eeec998b0c4b288..2fc05a8e2df60e1234073fa5b5ca0f57d26a7d6b 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -22,6 +22,7 @@ local PlayerDisplay = require "mod.class.PlayerDisplay" local TalentsDisplay = require "mod.class.TalentsDisplay" local LogDisplay = require "engine.LogDisplay" +local LogFlasher = require "engine.LogFlasher" local DebugConsole = require "engine.DebugConsole" local FlyingText = require "engine.FlyingText" local Tooltip = require "engine.Tooltip" @@ -43,17 +44,20 @@ function _M:init() end function _M:run() - self.log = LogDisplay.new(0, self.h * 0.8, self.w * 0.5, self.h * 0.2, nil, nil, nil, {255,255,255}, {30,30,30}) - self.player_display = PlayerDisplay.new(0, 0, 200, self.h * 0.8, {30,30,0}) + self.flash = LogFlasher.new(0, 0, self.w, 20, nil, nil, nil, {255,255,255}, {0,0,0}) + self.logdisplay = LogDisplay.new(0, self.h * 0.8, self.w * 0.5, self.h * 0.2, nil, nil, nil, {255,255,255}, {30,30,30}) + self.player_display = PlayerDisplay.new(0, 20, 200, self.h * 0.8 - 20, {30,30,0}) self.talents_display = TalentsDisplay.new(self.w * 0.5, self.h * 0.8, self.w * 0.5, self.h * 0.2, {30,30,0}) self.calendar = Calendar.new("/data/calendar_rivendell.lua", "Today is the %s %s of the %s year of the Fourth Age of Middle-earth.\nThe time is %02d:%02d.", 122) self.tooltip = Tooltip.new(nil, nil, {255,255,255}, {30,30,30}) self.flyers = FlyingText.new() self:setFlyingText(self.flyers) - self.log("Welcome to #00FF00#Tales of Middle Earth!") - self.logSeen = function(e, ...) if e and self.level.map.seens(e.x, e.y) then self.log(...) end end - self.logPlayer = function(e, ...) if e == game.player then self.log(...) end end + self.log = function(style, ...) if type(style) == "number" then self.logdisplay(...) self.flash(style, ...) else self.logdisplay(style, ...) self.flash(self.flash.NEUTRAL, style, ...) end end + self.logSeen = function(e, style, ...) if e and self.level.map.seens(e.x, e.y) then self.log(style, ...) end end + self.logPlayer = function(e, style, ...) if e == game.player then self.log(style, ...) end end + + self.log(self.flash.GOOD, "Welcome to #00FF00#Tales of Middle Earth!") -- Setup inputs self:setupCommands() @@ -93,24 +97,24 @@ function _M:loaded() engine.GameTurnBased.loaded(self) Zone:setup{npc_class="mod.class.NPC", grid_class="mod.class.Grid", object_class="mod.class.Object"} Map:setViewerActor(self.player) - Map:setViewPort(200, 0, self.w - 200, math.floor(self.h * 0.80), 32, 32, nil, 20, true) + Map:setViewPort(200, 20, self.w - 200, math.floor(self.h * 0.80) - 20, 32, 32, nil, 20, true) self.key = engine.KeyCommand.new() end function _M:setupDisplayMode() self.gfxmode = self.gfxmode or 1 if self.gfxmode == 1 then - Map:setViewPort(200, 0, self.w - 200, math.floor(self.h * 0.80), 32, 32, nil, 20, true) + Map:setViewPort(200, 20, self.w - 200, math.floor(self.h * 0.80) - 20, 32, 32, nil, 20, true) Map:resetTiles() Map.tiles.use_images = true self.level.map:recreate() elseif self.gfxmode == 2 then - Map:setViewPort(200, 0, self.w - 200, math.floor(self.h * 0.80), 16, 16, nil, 14, true) + Map:setViewPort(200, 20, self.w - 200, math.floor(self.h * 0.80) - 20, 16, 16, nil, 14, true) Map:resetTiles() Map.tiles.use_images = true self.level.map:recreate() elseif self.gfxmode == 3 then - Map:setViewPort(200, 0, self.w - 200, math.floor(self.h * 0.80), 16, 16, nil, 14, false) + Map:setViewPort(200, 20, self.w - 200, math.floor(self.h * 0.80) - 20, 16, 16, nil, 14, false) Map:resetTiles() Map.tiles.use_images = false self.level.map:recreate() @@ -180,7 +184,8 @@ function _M:onTurn() end function _M:display() - self.log:display():toScreen(self.log.display_x, self.log.display_y) + self.flash:display():toScreen(self.flash.display_x, self.flash.display_y) + self.logdisplay:display():toScreen(self.logdisplay.display_x, self.logdisplay.display_y) self.player_display:display():toScreen(self.player_display.display_x, self.player_display.display_y) self.talents_display:display():toScreen(self.talents_display.display_x, self.talents_display.display_y) @@ -510,6 +515,7 @@ function _M:setupCommands() end end, } + self.key:setCurrent() end @@ -559,9 +565,9 @@ function _M:setupMouse() end end) -- Scroll message log - self.mouse:registerZone(self.log.display_x, self.log.display_y, self.w, self.h, function(button) - if button == "wheelup" then self.log:scrollUp(1) end - if button == "wheeldown" then self.log:scrollUp(-1) end + self.mouse:registerZone(self.logdisplay.display_x, self.logdisplay.display_y, self.w, self.h, function(button) + if button == "wheelup" then self.logdisplay:scrollUp(1) end + if button == "wheeldown" then self.logdisplay:scrollUp(-1) end end, {button=true}) end diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index 85633b897e3ed5a7e22acb6aa73aa215d36fcfd2..705aef475a339bb414bae783e086c5742c85ca26 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -70,6 +70,9 @@ end function _M:act() if not mod.class.Actor.act(self) then return end + -- Clean log flasher + game.flash:empty() + game.paused = true end diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua index 8822751e2cd773efe185ccf54083232bcb5724f8..45458a684f54ba1e4383a429343ebe9d1963e9f9 100644 --- a/game/modules/tome/data/damage_types.lua +++ b/game/modules/tome/data/damage_types.lua @@ -8,15 +8,21 @@ setDefaultProjector(function(src, x, y, type, dam) else dam = dam * (100 / (100 - res)) end - game.logSeen(target, "%s hits %s for #aaaaaa#%0.2f %s damage#ffffff#.", src.name:capitalize(), target.name, dam, DamageType:get(type).name) + local flash = game.flash.NEUTRAL + if target == game.player then flash = game.flash.BAD end + if src == game.player then flash = game.flash.GOOD end + + game.logSeen(target, flash, "%s hits %s for #aaaaaa#%0.2f %s damage#ffffff#.", src.name:capitalize(), target.name, dam, DamageType:get(type).name) local sx, sy = game.level.map:getTileToScreen(x, y) if target:takeHit(dam, src) then if src == game.player or target == game.player then game.flyers:add(sx, sy, 30, (rng.range(0,2)-1) * 0.5, -3, "Kill!", {255,0,255}) end else - if src == game.player or target == game.player then - game.flyers:add(sx, sy, 30, (rng.range(0,2)-1) * 0.5, -3, tostring(-dam), {255,0,255}) + if src == game.player then + game.flyers:add(sx, sy, 30, (rng.range(0,2)-1) * 0.5, -3, tostring(-dam), {0,255,0}) + elseif target == game.player then + game.flyers:add(sx, sy, 30, (rng.range(0,2)-1) * 0.5, -3, tostring(-dam), {255,0,0}) end end end @@ -123,6 +129,17 @@ newDamageType{ end, } +-- Cold damage + freeze chance +newDamageType{ + name = "ice", type = "ICE", + projector = function(src, x, y, type, dam) + DamageType:get(DamageType.COLD).projector(src, x, y, DamageType.COLD, dam) + if rng.percent(25) then + DamageType:get(DamageType.FREEZE).projector(src, x, y, DamageType.FREEZE, 2) + end + end, +} + -- Irresistible fire damage newDamageType{ name = "netherflame", type = "NETHERFLAME", diff --git a/game/modules/tome/data/talents/spells/water.lua b/game/modules/tome/data/talents/spells/water.lua index 7432755d6da177b11237571edbf46075d079ae39..fb22704b0eb09a8325f966860a49b41aeb283465 100644 --- a/game/modules/tome/data/talents/spells/water.lua +++ b/game/modules/tome/data/talents/spells/water.lua @@ -50,7 +50,7 @@ newTalent{ action = function(self, t) local duration = 5 + self:combatSpellpower(0.01) * self:getTalentLevel(t) local radius = 1 - local dam = 5 + self:combatSpellpower(0.1) * self:getTalentLevel(t) + local dam = 5 + self:combatSpellpower(0.2) * self:getTalentLevel(t) -- Add a lasting map effect game.level.map:addEffect(self, self.x, self.y, duration, @@ -65,10 +65,10 @@ newTalent{ ) return true end, - require = { stat = { mag=34 }, level=25 }, + require = { stat = { mag=24 }, }, info = function(self, t) return ([[A furious ice storm rages around the caster doing %0.2f cold damage in a radius of 3 each turns for %d turns. - The damage and duration will increase with the Magic stat]]):format(5 + self:combatSpellpower(0.1) * self:getTalentLevel(t), 5 + self:combatSpellpower(0.01) * self:getTalentLevel(t)) + The damage and duration will increase with the Magic stat]]):format(5 + self:combatSpellpower(0.2) * self:getTalentLevel(t), 5 + self:combatSpellpower(0.01) * self:getTalentLevel(t)) end, } @@ -88,7 +88,7 @@ newTalent{ -- Add a lasting map effect game.level.map:addEffect(self, self.x, self.y, duration, - DamageType.COLD, dam, + DamageType.ICE, dam, radius, 5, nil, engine.Entity.new{alpha=100, display='', color_br=30, color_bg=60, color_bb=200}, @@ -100,9 +100,10 @@ newTalent{ ) return true end, - require = { stat = { mag=34 }, level=25 }, + require = { stat = { mag=34 }, }, info = function(self, t) return ([[A furious ice storm rages around the caster doing %0.2f cold damage in a radius of 3 each turns for %d turns. + It has 25%% chance to freeze damaged targets. The damage and duration will increase with the Magic stat]]):format(5 + self:combatSpellpower(0.15) * self:getTalentLevel(t), 5 + self:combatSpellpower(0.05) + self:getTalentLevel(t)) end, } diff --git a/ideas/spells.ods b/ideas/spells.ods index b30c48a9f9801fa0c380e749817b7105fd02245f..f6c8870614f04668f10f920137b3bcb47e76e9b2 100644 Binary files a/ideas/spells.ods and b/ideas/spells.ods differ