From 95d58a8cbe317b037d47d008dc2cd36a50831497 Mon Sep 17 00:00:00 2001 From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54> Date: Mon, 30 Nov 2009 21:41:25 +0000 Subject: [PATCH] lasting spell effects noxious cloud git-svn-id: http://svn.net-core.org/repos/t-engine4@77 51575b47-30f0-44d4-a5cc-537603b46e54 --- game/engine/GameTurnBased.lua | 6 ++ game/engine/Map.lua | 80 +++++++++++++++++++ game/engine/utils.lua | 32 ++++++++ game/modules/tome/class/Actor.lua | 2 +- game/modules/tome/class/Game.lua | 13 +++ game/modules/tome/data/talents.lua | 34 ++++++++ .../tome/data/zones/ancient_ruins/npcs.lua | 2 + 7 files changed, 168 insertions(+), 1 deletion(-) diff --git a/game/engine/GameTurnBased.lua b/game/engine/GameTurnBased.lua index cd306a55c9..99fb985a2d 100644 --- a/game/engine/GameTurnBased.lua +++ b/game/engine/GameTurnBased.lua @@ -23,6 +23,12 @@ function _M:tick() while not self.paused do engine.GameEnergyBased.tick(self) self.turn = self.turn + 1 + self:onTurn() end end end + +--- Called every game turns +-- Does nothing, you can override it +function _M:onTurn() +end diff --git a/game/engine/Map.lua b/game/engine/Map.lua index 2f15216e88..c54cfac867 100644 --- a/game/engine/Map.lua +++ b/game/engine/Map.lua @@ -2,6 +2,7 @@ require "engine.class" local Entity = require "engine.Entity" local Tiles = require "engine.Tiles" local Faction = require "engine.Faction" +local DamageType = require "engine.DamageType" --- Represents a level map, handles display and various low level map work module(..., package.seeall, class.make) @@ -55,6 +56,7 @@ function _M:init(w, h) self.lites = {} self.seens = {} self.remembers = {} + self.effects = {} for i = 0, w * h - 1 do self.map[i] = {} end self:loaded() @@ -223,6 +225,9 @@ function _M:display() end end ]] end + + self:displayEffects() + return self.surface end @@ -345,3 +350,78 @@ function _M:isBound(x, y) if x < 0 or x >= self.w or y < 0 or y >= self.h then return false end return true end + +--- Adds a zone (temporary) effect +-- @param src the source actor +-- @param x the epicenter coords +-- @param y the epicenter coords +-- @param duration the number of turns to persist +-- @param damtype the DamageType to apply +-- @param radius the radius of the effect +-- @param dir the numpad direction of the effect, 5 for a ball effect +-- @param overlay a simple display entity to draw upon the map +function _M:addEffect(src, x, y, duration, damtype, dam, radius, dir, angle, overlay, update_fct) + table.insert(self.effects, { + src=src, x=x, y=y, duration=duration, damtype=damtype, dam=dam, radius=radius, dir=dir, angle=angle, overlay=overlay, + update_fct=update_fct, + }) + self.changed = true +end + +--- Display the overlay effects, called by self:display() +function _M:displayEffects() + for i, e in ipairs(self.effects) do + local grids + local s = self.tiles:get(e.overlay.display, e.overlay.color_r, e.overlay.color_g, e.overlay.color_b, e.overlay.color_br, e.overlay.color_bg, e.overlay.color_bb, e.overlay.image) + s:alpha(e.alpha or 150) + + -- Handle balls + if e.dir == 5 then + grids = core.fov.circle_grids(e.x, e.y, e.radius, true) + -- Handle beams + else + grids = core.fov.beam_grids(e.x, e.y, e.radius, e.dir, e.angle, true) + end + + -- Now display each grids + for lx, ys in pairs(grids) do + for ly, _ in pairs(ys) do + if self.seens(lx, ly) then + self.surface:merge(s, (lx - self.mx) * self.tile_w, (ly - self.my) * self.tile_h) + end + end + end + end +end + +--- Process the overlay effects, call it from your tick function +function _M:processEffects() + local todel = {} + for i, e in ipairs(self.effects) do + local grids + + -- Handle balls + if e.dir == 5 then + grids = core.fov.circle_grids(e.x, e.y, e.radius, true) + -- Handle beams + else + grids = core.fov.beam_grids(e.x, e.y, e.radius, e.dir, e.angle, true) + end + + -- Now display each grids + for lx, ys in pairs(grids) do + for ly, _ in pairs(ys) do + DamageType:get(e.damtype).projector(e.src, lx, ly, e.damtype, e.dam) + end + end + + e.duration = e.duration - 1 + if e.duration <= 0 then + table.insert(todel, i) + elseif e.update_fct then + e:update_fct() + end + end + + for i = #todel, 1, -1 do table.remove(self.effects, todel[i]) end +end diff --git a/game/engine/utils.lua b/game/engine/utils.lua index bbd907b119..4424fa0d97 100644 --- a/game/engine/utils.lua +++ b/game/engine/utils.lua @@ -199,3 +199,35 @@ function util.bound(i, min, max) elseif i > max then i = max end return i end + +function core.fov.circle_grids(x, y, radius, block) + local grids = {} + core.fov.calc_circle(x, y, radius, function(self, lx, ly) + if not grids[lx] then grids[lx] = {} end + grids[lx][ly] = true + + if block and game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "block_move") then return true end + end, function()end, self) + + -- point of origin + if not grids[x] then grids[x] = {} end + grids[x][y] = true + + return grids +end + +function core.fov.beam_grids(x, y, radius, dir, angle, block) + local grids = {} + core.fov.calc_beam(x, y, radius, dir, angle, function(self, lx, ly) + if not grids[lx] then grids[lx] = {} end + grids[lx][ly] = true + + if block and game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "block_move") then return true end + end, function()end, self) + + -- point of origin + if not grids[x] then grids[x] = {} end + grids[x][y] = true + + return grids +end diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index 64410f97ac..df1c665e0c 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -81,7 +81,7 @@ function _M:levelup() -- Healp up on new level self.life = self.max_life self.mana = self.max_mana - self.stamina = self.man_stamina + self.stamina = self.max_stamina -- Auto levelup ? if self.autolevel then diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 269233a3e7..3cc4c9c29f 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -124,6 +124,16 @@ function _M:tick() -- Fun stuff: this can make the game realtime, although callit it in display() will make it work better -- (since display is on a set FPS while tick() ticks as much as possible -- engine.GameEnergyBased.tick(self) +end + +--- Called every game turns +-- Does nothing, you can override it +function _M:onTurn() + -- The following happens only every 10 game turns (once for every turn of 1 mod speed actors) + if self.turn % 10 ~= 0 then return end + + -- Process overlay effects + self.level.map:processEffects() if not self.day_of_year or self.day_of_year ~= self.calendar:getDayOfYear(self.turn) then self.log(self.calendar:getTimeDate(self.turn)) @@ -259,6 +269,9 @@ function _M:setupCommands() _a = function() self.player:useTalent(ActorTalents.T_FIREFLASH) end, + _e = function() + self.player:useTalent(ActorTalents.T_NOXIOUS_CLOUD) + end, _z = function() self.player:useTalent(ActorTalents.T_BLINK) end, diff --git a/game/modules/tome/data/talents.lua b/game/modules/tome/data/talents.lua index 2653cd67d2..e1bf6104d9 100644 --- a/game/modules/tome/data/talents.lua +++ b/game/modules/tome/data/talents.lua @@ -147,3 +147,37 @@ newTalent{ The radius (%d) of the target area decreases with Magic stat]]):format(5 - self:getMag(4)) end, } + + +newTalent{ + name = "Noxious Cloud", + type = {"spell/earth",1}, + mana = 45, + cooldown = 8, + tactical = { + ATTACKAREA = 10, + }, + action = function(self) + local duration = 5 + self:getMag(10) + local radius = 3 + local t = {type="ball", range=15, radius=math.min(6, 3 + self:getMag(6))} + local x, y = self:getTarget(t) + if not x or not y then return nil end + x, y = game.target:pointAtRange(self.x, self.y, x, y, 15) + -- Add a lasting map effect + game.level.map:addEffect(self, + x, y, duration, + DamageType.NATURE, 4 + self:getMag(30), + radius, + 5, nil, + engine.Entity.new{alpha=100, display='', color_br=30, color_bg=180, color_bb=60} + ) + return true + end, + require = { stat = { mag=16 }, }, + info = function(self) + return ([[Noxious fumes raises from the ground doing %0.2f nature damage in a radius of 3 each turns for %d turns. + Cooldown: 8 turns + The damage and duration will increase with the Magic stat]]):format(4 + self:getMag(30), 5 + self:getMag(10)) + end, +} diff --git a/game/modules/tome/data/zones/ancient_ruins/npcs.lua b/game/modules/tome/data/zones/ancient_ruins/npcs.lua index d974b1cc44..281cf80922 100644 --- a/game/modules/tome/data/zones/ancient_ruins/npcs.lua +++ b/game/modules/tome/data/zones/ancient_ruins/npcs.lua @@ -7,6 +7,7 @@ return { autolevel = "warrior", max_life = 20, max_mana = 1000, + max_stamina = 1000, energy = { mod=0.5 }, has_blood = true, stats = { str=15, dex=8, mag=12, }, @@ -20,6 +21,7 @@ return { autolevel = "caster", max_life = 30, max_mana = 1000, + max_stamina = 1000, energy = { mod=0.3 }, has_blood = {nb=3, color={50,255,120}}, combat = { dam=5, atk=6, def=2, apr=1, armor=2}, -- GitLab