From acda0b339c9ae6f45896dfaf7d9dad34fabf95f7 Mon Sep 17 00:00:00 2001 From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54> Date: Sun, 29 Nov 2009 14:11:49 +0000 Subject: [PATCH] talents git-svn-id: http://svn.net-core.org/repos/t-engine4@70 51575b47-30f0-44d4-a5cc-537603b46e54 --- game/engine/interface/ActorStats.lua | 11 ++ game/engine/interface/ActorTalents.lua | 31 +++- game/modules/tome/class/Game.lua | 4 +- game/modules/tome/data/talents.lua | 12 +- .../tome/dialogs/LevelupStatsDialog.lua | 4 + .../tome/dialogs/LevelupTalentsDialog.lua | 134 +++++++++++++----- 6 files changed, 149 insertions(+), 47 deletions(-) diff --git a/game/engine/interface/ActorStats.lua b/game/engine/interface/ActorStats.lua index 24a826cbfd..022642030b 100644 --- a/game/engine/interface/ActorStats.lua +++ b/game/engine/interface/ActorStats.lua @@ -70,6 +70,17 @@ function _M:getStat(stat, scale) return val end +--- Is the stat maxed ? +function _M:isStatMax(stat) + local val + if type(stat) == "string" then + val = self.stats[_M.stats_def[stat].id] + else + val = self.stats[stat] + end + if math.floor(val) == _M.stats_def[stat].max then return true end +end + --- Notifies a change of stat value function _M:onStatChange(stat, v) end diff --git a/game/engine/interface/ActorTalents.lua b/game/engine/interface/ActorTalents.lua index 08e3f685aa..3757eb5c35 100644 --- a/game/engine/interface/ActorTalents.lua +++ b/game/engine/interface/ActorTalents.lua @@ -23,6 +23,8 @@ end function _M:newTalentType(t) assert(t.name, "no talent type name") assert(t.type, "no talent type type") + t.description = t.description or "" + t.points = t.points or 1 t.talents = {} table.insert(self.talents_types_def, t) self.talents_types_def[t.type] = t @@ -38,6 +40,7 @@ function _M:newTalent(t) 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'") assert(t.info, "no talent info") @@ -120,6 +123,14 @@ function _M:learnTalent(t_id) return true end +--- Actor forgets a talent +-- @param t_id the id of the talent to learn +-- @return true if the talent was unlearnt, nil and an error message otherwise +function _M:unlearnTalent(t_id) + self.talents[t_id] = nil + return true +end + function _M:canLearnTalent(t) -- Check prerequisites if t.require then @@ -136,7 +147,7 @@ function _M:canLearnTalent(t) -- Check talent type local known = self:numberKnownTalent(t.type[1]) - if known < t.type[1] - 1 then + if known < t.type[2] - 1 then return nil, "not enough talents of this type known" end @@ -145,11 +156,21 @@ function _M:canLearnTalent(t) end --- Do we know this talent type -function _M:knowTalentType(t) - return self.talents_types[t] +function _M:knowTalentType(name) + return self.talents_types[name] end --- Do we know this talent -function _M:knowTalent(t) - return self.talents[t] +function _M:knowTalent(id) + return self.talents[id] and true or false +end + +--- Return talent definition from id +function _M:getTalentFromId(id) + return _M.talents_def[id] +end + +--- Return talent definition from id +function _M:getTalentTypeFrom(id) + return _M.talents_types_def[id] end diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index ec2f15108e..76875d8dc3 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -85,7 +85,6 @@ end function _M:loaded() Zone:setup{npc_class="mod.class.NPC", grid_class="mod.class.Grid", object_class="engine.Entity"} --- Map:setViewPort(0, 0, self.w, math.floor(self.h * 0.80), 20, 20, "/data/font/10X20.FON", 20) Map:setViewPort(self.w * 0.2, 0, self.w * 0.8, math.floor(self.h * 0.80), 16, 16) engine.GameTurnBased.loaded(self) self.key = engine.KeyCommand.new() @@ -115,6 +114,9 @@ function _M:tick() if self.target.target.entity and not self.level:hasEntity(self.target.target.entity) then self.target.target.entity = false end engine.GameTurnBased.tick(self) + -- 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) if not self.day_of_year or self.day_of_year ~= self.calendar:getDayOfYear(self.turn) then self.log(self.calendar:getTimeDate(self.turn)) diff --git a/game/modules/tome/data/talents.lua b/game/modules/tome/data/talents.lua index 10c7d5d7d9..35dda48f91 100644 --- a/game/modules/tome/data/talents.lua +++ b/game/modules/tome/data/talents.lua @@ -24,9 +24,9 @@ newTalent{ self:project(t, x, y, DamageType.ARCANE, 10 + self:getMag()) return true end, - require = { stat = { mag=12 }, }, + require = { stat = { mag=10 }, }, info = function(self) - return ([[Conjures up mana into a powerful bolt doing %0.2f arcane damage", + return ([[Conjures up mana into a powerful bolt doing %0.2f arcane damage The damage will increase with the Magic stat]]):format(10 + self:getMag()) end, } @@ -42,7 +42,7 @@ newTalent{ end, require = { stat = { mag=12 }, }, info = function(self) - return ([[Uses mana instead of life to take damage", + return ([[Uses mana instead of life to take damage The damage to mana ratio increases with the Magic stat]]):format(10 + self:getMag()) end, } @@ -61,7 +61,7 @@ newTalent{ end, require = { stat = { mag=10 }, }, info = function(self) - return ([[Creates a globe of pure light with a radius of %d that illuminates the area.", + return ([[Creates a globe of pure light with a radius of %d that illuminates the area. The radius will increase with the Magic stat]]):format(5 + self:getMag(10)) end, } @@ -82,7 +82,7 @@ newTalent{ end, require = { stat = { mag=16 }, }, info = function(self) - return ([[Conjures up a flash of fire doing %0.2f fire damage in a radius of %d", + return ([[Conjures up a flash of fire doing %0.2f fire damage in a radius of %d. The damage will increase with the Magic stat]]):format(8 + self:getMag(70), math.min(6, 3 + self:getMag(6))) end, } @@ -101,7 +101,7 @@ newTalent{ end, require = { stat = { mag=16 }, }, info = function(self) - return ([[Teleports you randomly on a small scale range (%d)", + return ([[Teleports you randomly on a small scale range (%d) The range will increase with the Magic stat]]):format(10 + self:getMag(10)) end, } diff --git a/game/modules/tome/dialogs/LevelupStatsDialog.lua b/game/modules/tome/dialogs/LevelupStatsDialog.lua index 999644a856..643b31865e 100644 --- a/game/modules/tome/dialogs/LevelupStatsDialog.lua +++ b/game/modules/tome/dialogs/LevelupStatsDialog.lua @@ -33,6 +33,10 @@ function _M:incStat(v) self:simplePopup("Not enough stat points", "You have no stat points left!") return end + if self.actor:isStatMax(self.statsel) then + self:simplePopup("Stat is at the maximun", "You can not increase this stat further!") + return + end else if self.actor_dup:getStat(self.statsel) == self.actor:getStat(self.statsel) then self:simplePopup("Impossible", "You cannot take out more points!") diff --git a/game/modules/tome/dialogs/LevelupTalentsDialog.lua b/game/modules/tome/dialogs/LevelupTalentsDialog.lua index 3ca700bbcb..f260004f13 100644 --- a/game/modules/tome/dialogs/LevelupTalentsDialog.lua +++ b/game/modules/tome/dialogs/LevelupTalentsDialog.lua @@ -8,75 +8,139 @@ function _M:init(actor) self.actor_dup = actor:clone() engine.Dialog.init(self, "Talents Levelup: "..actor.name, 800, 600) + self:generateList() + + self.talentsel = 1 + self:keyCommands{ + _UP = function() self.talentsel = util.boundWrap(self.talentsel - 1, 1, #self.list) end, + _DOWN = function() self.talentsel = util.boundWrap(self.talentsel + 1, 1, #self.list) end, + _LEFT = function() self:learn(false) end, + _RIGHT = function() self:learn(true) end, + _ESCAPE = function() game:unregisterDialog(self) end, + } + self:mouseZones{ + { x=2, y=45, w=350, h=self.font_h*#self.list, fct=function(button, x, y, xrel, yrel, tx, ty) + self.talentsel = 1 + math.floor(ty / self.font_h) + if button == "left" then self:learn(true) + elseif button == "right" then self:learn(false) + end + end }, + } +end + +function _M:generateList() -- Makes up the list local list, known = {}, {} for i, tt in ipairs(self.actor.talents_types_def) do local cat = tt.type:gsub("/.*", "") - list[#list+1] = { name="<"..cat:capitalize().." / "..tt.name:capitalize()..">", type=tt.type } - if actor:knowTalentType(tt.type) then known[#known+1] = "known" else known[#known+1] = "unknown" end + list[#list+1] = { name=cat:capitalize().." / "..tt.name:capitalize() .." (category)", type=tt.type } + if self.actor:knowTalentType(tt.type) then known[#known+1] = "#00FF00#known" else known[#known+1] = tt.points.." point(s)" end -- Find all talents of this school for j, t in ipairs(tt.talents) do - list[#list+1] = { name=" "..t.name, talent=t.id } - if actor:knowTalent(t.id) then known[#known+1] = "known" else known[#known+1] = "unknown" end + local typename = "talent" + if t.type[1]:find("^spell/") then typename = "spell" end + list[#list+1] = { name=" "..t.name.." ("..typename..")", talent=t.id } + if self.actor:knowTalent(t.id) then known[#known+1] = "#00FF00#known" else known[#known+1] = t.points.." point(s)" end end end self.list = list self.list_known = known +end - self.talentsel = 1 - self:keyCommands{ - _UP = function() self.talentsel = util.boundWrap(self.talentsel - 1, 1, #list) end, - _DOWN = function() self.talentsel = util.boundWrap(self.talentsel + 1, 1, #list) end, --- _LEFT = function() self:incStat(-1) end, --- _RIGHT = function() self:incStat(1) end, - _ESCAPE = function() game:unregisterDialog(self) end, - } - self:mouseZones{ - { x=2, y=45, w=350, h=self.font_h*#list, fct=function(button, x, y, xrel, yrel, tx, ty) - self.talentsel = 1 + math.floor(ty / self.font_h) --- if button == "left" then self:incStat(1) --- elseif button == "right" then self:incStat(-1) --- end - end }, - } +function _M:learn(v) + if self.list[self.talentsel].type then + self:learnType(self.list[self.talentsel].type, v) + else + self:learnTalent(self.list[self.talentsel].talent, v) + end end ---[[ -function _M:incStat(v) - if v == 1 then + +function _M:learnTalent(t, v) + if v then if self.actor.unused_talents == 0 then self:simplePopup("Not enough talent points", "You have no talent points left!") return end + if not self.actor:canLearnTalent(self.actor:getTalentFromId(t)) then + self:simplePopup("Cannot learn talent", "Prerequisites not met!") + return + end + if self.actor:knowTalent(t) then + self:simplePopup("Already known", "You already know this talent!") + return + end + self.actor:learnTalent(t) + self.actor.unused_talents = self.actor.unused_talents - 1 + else + if not self.actor:knowTalent(t) then + self:simplePopup("Impossible", "You do not know this talent!") + return + end + if self.actor_dup:knowTalent(t) == true and self.actor:knowTalent(t) == true then + self:simplePopup("Impossible", "You cannot unlearn talents!") + return + end + self.actor:unlearnTalent(t) + self.actor.unused_talents = self.actor.unused_talents + 1 + end + self:generateList() +end + +function _M:learnType(tt, v) + if v then + if self.actor.unused_talents_types == 0 then + self:simplePopup("Not enough talent category points", "You have no talent category points left!") + return + end + self.actor.unused_talents_types = self.actor.unused_talents_types - 1 else if self.actor_dup:getStat(self.talentsel) == self.actor:getStat(self.talentsel) then self:simplePopup("Impossible", "You cannot take out more points!") return end + self.actor.unused_talents_types = self.actor.unused_talents_types + 1 end - self.actor:incStat(self.talentsel, v) - self.actor.unused_stats = self.actor.unused_stats - v + self:generateList() end -]] + function _M:drawDialog(s) -- Description part self:drawHBorder(s, self.iw / 2, 2, self.ih - 4) ---[=[ - local statshelp = ([[Keyboard: #00FF00#up key/down key#FFFFFF# to select a stat; #00FF00#right key#FFFFFF# to increase stat; #00FF00#left key#FFFFFF# to decrease a stat. -Mouse: #00FF00#Left click#FFFFFF# to increase a stat; #00FF00#right click#FFFFFF# to decrease a stat. + + local talentshelp = ([[Keyboard: #00FF00#up key/down key#FFFFFF# to select a stat; #00FF00#right key#FFFFFF# to learn; #00FF00#left key#FFFFFF# to unlearn. +Mouse: #00FF00#Left click#FFFFFF# to learn; #00FF00#right click#FFFFFF# to unlearn. ]]):splitLines(self.iw / 2 - 10, self.font) - local lines = self.actor.talents_def[self.talentsel].description:splitLines(self.iw / 2 - 10, self.font) - for i = 1, #statshelp do - s:drawColorString(self.font, statshelp[i], self.iw / 2 + 5, 2 + (i-1) * self.font:lineSkip()) + + local lines, helplines = {} + if self.list[self.talentsel].type then + local str = "" + str = str .. "#00FFFF#Talent Category\n" + str = str .. "#00FFFF#A talent category allows you to learn talents of this category. You gain a talent category point every few levels. You may also find trainers or artifacts that allows you to learn more.\n\n" + helplines = str:splitLines(self.iw / 2 - 10, self.font) + lines = self.actor:getTalentTypeFrom(self.list[self.talentsel].type).description:splitLines(self.iw / 2 - 10, self.font) + else + local str = "" + str = str .. "#00FFFF#Talent\n" + str = str .. "#00FFFF#A talent allows you to perform new combat moves, cast spells, improve your character. You gain a talent point every level. You may also find trainers or artifacts that allows you to learn more.\n\n" + helplines = str:splitLines(self.iw / 2 - 10, self.font) + lines = self.actor:getTalentFromId(self.list[self.talentsel].talent).info(self.actor):splitLines(self.iw / 2 - 10, self.font) + end + for i = 1, #talentshelp do + s:drawColorString(self.font, talentshelp[i], self.iw / 2 + 5, 2 + (i-1) * self.font:lineSkip()) + end + self:drawWBorder(s, self.iw / 2 + self.iw / 6, 2 + (0.5 + #talentshelp) * self.font:lineSkip(), self.iw / 6) + for i = 1, #helplines do + s:drawColorString(self.font, helplines[i], self.iw / 2 + 5, 2 + (i + #talentshelp) * self.font:lineSkip()) end + self:drawWBorder(s, self.iw / 2 + self.iw / 6, 2 + (1.5 + #talentshelp + #helplines) * self.font:lineSkip(), self.iw / 6) for i = 1, #lines do - s:drawColorString(self.font, lines[i], self.iw / 2 + 5, 2 + (i + #statshelp + 1) * self.font:lineSkip()) + s:drawColorString(self.font, lines[i], self.iw / 2 + 5, 2 + (i + #helplines + #talentshelp + 2) * self.font:lineSkip()) end -]=] -- Talents - s:drawColorString(self.font, "Talents types points left: #00FF00#"..self.actor.unused_talents_types, 2, 2) + s:drawColorString(self.font, "Talent categories points left: #00FF00#"..self.actor.unused_talents_types, 2, 2) s:drawColorString(self.font, "Talents points left: #00FF00#"..self.actor.unused_talents, 2, 2 + self.font_h) self:drawWBorder(s, 2, 40, 200) -- GitLab