From 0b6b1c9b2f4818bbfcdff7ca9e77c68d71399056 Mon Sep 17 00:00:00 2001 From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54> Date: Sun, 29 Nov 2009 22:51:12 +0000 Subject: [PATCH] actor resources talent cooldowns git-svn-id: http://svn.net-core.org/repos/t-engine4@73 51575b47-30f0-44d4-a5cc-537603b46e54 --- game/engine/interface/ActorResource.lua | 53 +++++++++++++++++++++++ game/engine/interface/ActorTalents.lua | 32 +++++++++++++- game/modules/tome/class/Actor.lua | 48 ++++++++++++++------ game/modules/tome/class/Game.lua | 9 +++- game/modules/tome/class/NPC.lua | 1 + game/modules/tome/class/Player.lua | 2 + game/modules/tome/class/PlayerDisplay.lua | 8 +++- game/modules/tome/data/talents.lua | 7 ++- 8 files changed, 140 insertions(+), 20 deletions(-) create mode 100644 game/engine/interface/ActorResource.lua diff --git a/game/engine/interface/ActorResource.lua b/game/engine/interface/ActorResource.lua new file mode 100644 index 0000000000..6183ee7f3d --- /dev/null +++ b/game/engine/interface/ActorResource.lua @@ -0,0 +1,53 @@ +require "engine.class" + +--- Handles actors life and death +module(..., package.seeall, class.make) + +_M.resources_def = {} + +--- Defines resource +-- Static! +-- All actors will now have :getResourcename() and :incResourcename() methods as well as a .max_resourcename and .resourcename +-- properties. It is advised to NOT access .resourcename directly and use the get/inc methods. They handle talent +-- dependencies +function _M:defineResource(name, short_name, talent, desc) + assert(name, "no resource name") + assert(short_name, "no resource short_name") + table.insert(self.resources_def, { + name = name, + short_name = short_name, + talent = talent, + description = desc, + }) + self.resources_def[#self.resources_def].id = #self.resources_def + self.resources_def[short_name] = self.resources_def[#self.resources_def] + self["RS_"..short_name:upper()] = #self.resources_def + local maxname = "max_"..short_name + self["inc"..short_name:lower():capitalize()] = function(self, v) + self[short_name] = util.bound(self[short_name] + v, 0, self[maxname]) + end + self["incMax"..short_name:lower():capitalize()] = function(self, v) + self[maxname] = self[maxname] + v + end + if talent then + -- if there is an associated talent, check for it + self["get"..short_name:lower():capitalize()] = function(self) + if self:knowTalent(talent) then + return self[short_name] + else + return 0 + end + end + else + self["get"..short_name:lower():capitalize()] = function(self) + return self[short_name] + end + end +end + +function _M:init(t) + for i, r in ipairs(_M.resources_def) do + self["max_"..r.short_name] = t["max_"..r.short_name] or 100 + self[r.short_name] = t[r.short_name] or self["max_"..r.short_name] + end +end diff --git a/game/engine/interface/ActorTalents.lua b/game/engine/interface/ActorTalents.lua index 8038cfe192..1745b6b113 100644 --- a/game/engine/interface/ActorTalents.lua +++ b/game/engine/interface/ActorTalents.lua @@ -37,8 +37,6 @@ function _M:newTalent(t) assert(t.type, "no or unknown talent type") t.short_name = t.short_name or t.name t.short_name = t.short_name:upper():gsub("[ ]", "_") - t.mana = t.mana or 0 - t.stamina = t.stamina or 0 t.mode = t.mode or "activated" t.points = t.points or 1 assert(t.mode == "activated" or t.mode == "sustained", "wrong talent mode, requires either 'activated' or 'sustained'") @@ -65,6 +63,7 @@ end function _M:init(t) self.talents = t.talents or {} self.talents_types = t.talents_types or {} + self.talents_cd = {} end --- Make the actor use the talent @@ -73,11 +72,18 @@ function _M:useTalent(id) assert(ab, "trying to cast talent "..tostring(id).." but it is not defined") if ab.action then + if self:isTalentCoolingDown(ab) then + game.logPlayer(self, "%s is still on cooldown for %d turns.", ab.name:capitalize(), self.talents_cd[ab.id]) + return + end if not self:preUseTalent(ab) then return end local co = coroutine.create(function() local ret = ab.action(self) if not self:postUseTalent(ab, ret) then return end + + -- Everything went ok? then start cooldown if any + self:startTalentCooldown(ab) end) local ok, err = coroutine.resume(co) if not ok and err then error(err) end @@ -229,3 +235,25 @@ function _M:unlearnTalentType(tt) self.talents_types[tt] = nil return true end + +--- Starts a talent cooldown +-- @param t the talent to cooldown +function _M:startTalentCooldown(t) + if not t.cooldown then return end + self.talents_cd[t.id] = t.cooldown +end + +--- Is talent in cooldown? +function _M:isTalentCoolingDown(t) + if not t.cooldown then return false end + if self.talents_cd[t.id] and self.talents_cd[t.id] > 0 then return true else return false end +end + +--- Cooldown all talents by one +-- This should be called in your actors "act()" method +function _M:cooldownTalents() + for tid, c in pairs(self.talents_cd) do + self.talents_cd[tid] = self.talents_cd[tid] - 1 + if self.talents_cd[tid] == 0 then self.talents_cd[tid] = nil end + end +end diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index abb263aeeb..7901c16f30 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -4,6 +4,7 @@ require "engine.interface.ActorLife" require "engine.interface.ActorLevel" require "engine.interface.ActorStats" require "engine.interface.ActorTalents" +require "engine.interface.ActorResource" require "engine.interface.BloodyDeath" require "mod.class.interface.Combat" @@ -14,7 +15,7 @@ module(..., package.seeall, class.inherit( engine.interface.ActorLevel, engine.interface.ActorStats, engine.interface.ActorTalents, --- engine.interface.ActorResource, + engine.interface.ActorResource, engine.interface.BloodyDeath, mod.class.interface.Combat )) @@ -25,13 +26,18 @@ function _M:init(t) engine.interface.ActorLevel.init(self, t) engine.interface.ActorStats.init(self, t) engine.interface.ActorTalents.init(self, t) --- engine.interface.ActorResouce.init(self, t) + engine.interface.ActorResource.init(self, t) self.unused_stats = 0 self.unused_talents = 0 self.unused_talents_types = 0 end +function _M:act() + -- Cooldown talents + self:cooldownTalents() +end + function _M:move(x, y, force) local moved = false if force or self:enoughEnergy() then @@ -67,7 +73,8 @@ function _M:onStatChange(stat, v) if stat == self.STAT_CON then self.max_life = self.max_life + 5 * v elseif stat == self.STAT_WIL then - self.max_mana = self.max_mana + 5 * v + self:incMaxMana(5 * v) + self:incMaxStamina(5 * v) end end @@ -85,17 +92,24 @@ end -- @param ab the talent (not the id, the table) -- @return true to continue, false to stop function _M:preUseTalent(ab) - local ret = self:enoughEnergy() - if ret == true then - if ab.message then - game.logSeen(self, "%s", self:useTalentMessage(ab)) - elseif ab.type[1]:find("^spell/") then - game.logSeen(self, "%s casts %s.", self.name:capitalize(), ab.name) - else - game.logSeen(self, "%s uses %s.", self.name:capitalize(), ab.name) - end + if not self:enoughEnergy() then return end + if ab.mana and self:getMana() < ab.mana then + game.logPlayer(self, "You do not have enough mana to cast %s.", ab.name) + return + end + if ab.stamina and self:getStamina() < ab.stamina then + game.logPlayer(self, "You do not have enough stamina to use %s.", ab.name) + return + end + + if ab.message then + game.logSeen(self, "%s", self:useTalentMessage(ab)) + elseif ab.type[1]:find("^spell/") then + game.logSeen(self, "%s casts %s.", self.name:capitalize(), ab.name) + else + game.logSeen(self, "%s uses %s.", self.name:capitalize(), ab.name) end - return ret + return true end --- Called before a talent is used @@ -106,5 +120,13 @@ end function _M:postUseTalent(ab, ret) if ret == nil then return end self:useEnergy() + + if ab.mana then + self:incMana(-ab.mana) + end + if ab.stamina then + self:incStamina(-ab.stamina) + end + return true end diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 3e0e1ed3db..0dbac4a1ba 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -11,6 +11,7 @@ local Level = require "engine.Level" local Grid = require "engine.Grid" local Actor = require "mod.class.Actor" local ActorStats = require "engine.interface.ActorStats" +local ActorResource = require "engine.interface.ActorResource" local ActorTalents = require "engine.interface.ActorTalents" local Player = require "mod.class.Player" local NPC = require "mod.class.NPC" @@ -39,6 +40,11 @@ end function _M:run() -- Damage types DamageType:loadDefinition("/data/damage_types.lua") + -- Talents + ActorTalents:loadDefinition("/data/talents.lua") + -- Actor resources + ActorResource:defineResource("Mana", "mana", ActorTalents.T_MANA_POOL, "Mana represents your reserve of magical energies. Each spell cast consumes mana and each sustained spell reduces your maximun mana.") + ActorResource:defineResource("Stamina", "stamina", ActorTalents.T_STAMINA_POOL, "Stamina represents your physical fatigue. Each physical ability used reduces it.") -- Actor stats ActorStats:defineStat("Strength", "str", 10, 1, 100, "Strength defines your character's ability to apply physical force. It increases your melee damage, damage with heavy weapons, your chance to resist physical effects, and carrying capacity.") ActorStats:defineStat("Dexterity", "dex", 10, 1, 100, "Dexterity defines your character's ability to be agile and alert. It increases your chance to hit, your ability to avoid attacks and your damage with light weapons.") @@ -46,8 +52,6 @@ function _M:run() ActorStats:defineStat("Willpower", "wil", 10, 1, 100, "Willpower defines your character's ability to concentrate. It increases your mana and stamina capacity, and your chance to resist mental attacks.") ActorStats:defineStat("Cunning", "cun", 10, 1, 100, "Cunning defines your character's ability to learn and think. It allows you to learn many wordly abilities, increases your mental resistance and armor penetration.") ActorStats:defineStat("Constitution", "con", 10, 1, 100, "Constitution defines your character's ability to withstand and resist damage. It increases your maximun life and physical resistance.") - -- Talents - ActorTalents:loadDefinition("/data/talents.lua") self.log = LogDisplay.new(0, self.h * 0.80, self.w * 0.5, self.h * 0.20, nil, nil, nil, {255,255,255}, {30,30,30}) self.player_display = PlayerDisplay.new(0, 0, self.w * 0.2, self.h * 0.8, {30,30,0}) @@ -58,6 +62,7 @@ function _M:run() 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 -- Setup inputs self:setupCommands() diff --git a/game/modules/tome/class/NPC.lua b/game/modules/tome/class/NPC.lua index 2b1a4ee9bc..b983b5880a 100644 --- a/game/modules/tome/class/NPC.lua +++ b/game/modules/tome/class/NPC.lua @@ -8,5 +8,6 @@ function _M:init(t) end function _M:act() + mod.class.Actor.act(self) self:move(self.x + 1, self.y) end diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index 3e2fd3855b..e6cf6425aa 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -21,6 +21,8 @@ function _M:move(x, y, force) end function _M:act() + mod.class.Actor.act(self) + game.paused = true end diff --git a/game/modules/tome/class/PlayerDisplay.lua b/game/modules/tome/class/PlayerDisplay.lua index e25e602007..559a1b8611 100644 --- a/game/modules/tome/class/PlayerDisplay.lua +++ b/game/modules/tome/class/PlayerDisplay.lua @@ -25,7 +25,13 @@ function _M:display() self.surface:drawColorString(self.font, "Level: #00ff00#"..game.player.level, 0, h, 255, 255, 255) h = h + self.font_h self.surface:drawColorString(self.font, ("Exp: #00ff00#%2d%%"):format(100 * cur_exp / max_exp), 0, h, 255, 255, 255) h = h + self.font_h h = h + self.font_h - self.surface:drawColorString(self.font, ("#c00000#Life: #00ff00#%d/%d"):format(game.player.life, game.player.max_life), 0, h, 255, 255, 255) h = h + self.font_h + self.surface:drawColorString(self.font, ("#c00000#Life: #00ff00#%d/%d"):format(game.player.life, game.player.max_life), 0, h, 255, 255, 255) h = h + self.font_h + if game.player:knowTalent(game.player.T_MANA_POOL) then + self.surface:drawColorString(self.font, ("#7fffd4#Mana: #00ff00#%d/%d"):format(game.player:getMana(), game.player.max_mana), 0, h, 255, 255, 255) h = h + self.font_h + end + if game.player:knowTalent(game.player.T_STAMINA_POOL) then + self.surface:drawColorString(self.font, ("#ffcc80#Stamina: #00ff00#%d/%d"):format(game.player:getMana(), game.player.max_mana), 0, h, 255, 255, 255) h = h + self.font_h + end h = h + self.font_h self.surface:drawColorString(self.font, ("STR: #00ff00#%3d"):format(game.player:getStr()), 0, h, 255, 255, 255) h = h + self.font_h self.surface:drawColorString(self.font, ("DEX: #00ff00#%3d"):format(game.player:getDex()), 0, h, 255, 255, 255) h = h + self.font_h diff --git a/game/modules/tome/data/talents.lua b/game/modules/tome/data/talents.lua index a1468efea7..6bd02d39bf 100644 --- a/game/modules/tome/data/talents.lua +++ b/game/modules/tome/data/talents.lua @@ -51,7 +51,8 @@ newTalent{ newTalent{ name = "Disruption Shield", type = {"spell/arcane",2}, - mana = 80, + mode = "sustained", + sustain_mana = 60, tactical = { DEFEND = 10, }, @@ -87,7 +88,8 @@ newTalent{ newTalent{ name = "Fireflash", type = {"spell/fire",2}, - mana = 45, + mana = 35, + cooldown = 6, tactical = { ATTACKAREA = 10, }, @@ -101,6 +103,7 @@ newTalent{ require = { stat = { mag=16 }, }, info = function(self) return ([[Conjures up a flash of fire doing %0.2f fire damage in a radius of %d. + Cooldown: 6 turns The damage will increase with the Magic stat]]):format(8 + self:getMag(70), math.min(6, 3 + self:getMag(6))) end, } -- GitLab