diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index 40ae5b59513cfc50231d7a4797d2b7cafd6ed322..2047b840ab2e98e5f5471a289fe3425a87f14d66 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -1939,6 +1939,17 @@ function _M:canWearObject(o, try_slot) return engine.interface.ActorInventory.canWearObject(self, o, try_slot) end +function _M:lastLearntTalentsMax(what) + return what == "generic" and 3 or 4 +end + +function _M:capLastLearntTalents(what) + if self.no_last_learnt_talents_cap then return end + local list = self.last_learnt_talents[what] + local max = self:lastLearntTalentsMax(what) + while #list > max do table.remove(list, 1) end +end + --- Actor learns a talent -- @param t_id the id of the talent to learn -- @return true if the talent was learnt, nil and an error message otherwise @@ -1948,6 +1959,12 @@ function _M:learnTalent(t_id, force, nb) -- If we learned a spell, get mana, if you learned a technique get stamina, if we learned a wild gift, get power local t = _M.talents_def[t_id] + if not t.no_unlearn_last and self.last_learnt_talents then + local list = t.generic and self.last_learnt_talents.generic or self.last_learnt_talents.class + table.insert(list, t_id) + self:capLastLearntTalents(t.generic and "generic" or "class") + end + if t.dont_provide_pool then return true end if t.type[1]:find("^spell/") and not self:knowTalent(self.T_MANA_POOL) and t.mana or t.sustain_mana then @@ -2000,6 +2017,16 @@ end -- @return true if the talent was unlearnt, nil and an error message otherwise function _M:unlearnTalent(t_id) if not engine.interface.ActorTalents.unlearnTalent(self, t_id, force) then return false end + + local t = _M.talents_def[t_id] + + if not t.no_unlearn_last and self.last_learnt_talents then + local list = t.generic and self.last_learnt_talents.generic or self.last_learnt_talents.class + for i = #list, 1, -1 do + if list[i] == t_id then table.remove(list, i) break end + end + end + -- Check the various pools for key, num_refs in pairs(self.resource_pool_refs) do if num_refs == 0 then diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 628515ba4f17e4264c803c150c98fe06c4b99f1e..d095cd11cab09ca6882fbe7e8cfd3e82c6fe5c59 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -1076,12 +1076,10 @@ function _M:setupCommands() end end end end, [{"_g","ctrl"}] = function() if config.settings.cheat then - local list = mod.class.Trap:loadList("/data/general/traps/complex.lua") - local b = list[2]:clone() - b:resolve() b:resolve(nil, true) - self.zone:addEntity(self.level, b, "trap", self.player.x + 1, self.player.y) - - + print("== CLASS") + for i, tid in ipairs(game.player.last_learnt_talents.class) do print(i, tid) end + print("== GENERIC") + for i, tid in ipairs(game.player.last_learnt_talents.generic) do print(i, tid) end end end, [{"_f","ctrl"}] = function() if config.settings.cheat then self.player.quests["love-melinda"] = nil diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index 4c80ecf688ce8659f6cbe803ab5eb5767e592f52..2d2a89ad2055ad2b72513dc491f236902f15fa5b 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -84,6 +84,7 @@ function _M:init(t, no_default) self.descriptor = self.descriptor or {} self.died_times = self.died_times or {} + self.last_learnt_talents = { class={}, generic={} } end function _M:onBirth(birther) diff --git a/game/modules/tome/data/talents/misc/inscriptions.lua b/game/modules/tome/data/talents/misc/inscriptions.lua index 73cf790adff860dbe44ba7e5e3f866cbc467252b..a738ef27813e580ef11bc88b2ec513285197541c 100644 --- a/game/modules/tome/data/talents/misc/inscriptions.lua +++ b/game/modules/tome/data/talents/misc/inscriptions.lua @@ -54,6 +54,7 @@ local newInscription = function(t) if not tt.image then tt.image = "talents/"..(t.short_name or t.name):lower():gsub("[^a-z0-9_]", "_")..".png" end + tt.no_unlearn_last = true newTalent(tt) end end diff --git a/game/modules/tome/data/talents/misc/misc.lua b/game/modules/tome/data/talents/misc/misc.lua index e287231b004cf67bff5459eee5ceff508066962f..7d916e5c48ca63c724d51f35780b6d3245de5f9d 100644 --- a/game/modules/tome/data/talents/misc/misc.lua +++ b/game/modules/tome/data/talents/misc/misc.lua @@ -44,6 +44,7 @@ newTalent{ requires_target = true, target = {type="hit", range=1}, tactical = { ATTACK = 1 }, + no_unlearn_last = true, action = function(self, t) local tg = self:getTalentTarget(t) local x, y = self:getTarget(tg) @@ -68,6 +69,7 @@ newTalent{ info = "Allows you to have an energy pool. Energy is used to perform psionic manipulations.", mode = "passive", hide = true, + no_unlearn_last = true, } newTalent{ @@ -76,6 +78,7 @@ newTalent{ info = "Allows you to have a mana pool. Mana is used to cast all spells.", mode = "passive", hide = true, + no_unlearn_last = true, } newTalent{ name = "Vim Pool", @@ -83,6 +86,7 @@ newTalent{ info = "Allows you to have a vim pool. Vim is used by corruptions.", mode = "passive", hide = true, + no_unlearn_last = true, } newTalent{ name = "Stamina Pool", @@ -90,6 +94,7 @@ newTalent{ info = "Allows you to have a stamina pool. Stamina is used to activate special combat attacks.", mode = "passive", hide = true, + no_unlearn_last = true, } newTalent{ name = "Equilibrium Pool", @@ -97,6 +102,7 @@ newTalent{ info = "Allows you to have an equilibrium pool. Equilibrium is used to measure your balance with nature and the use of wild gifts.", mode = "passive", hide = true, + no_unlearn_last = true, } newTalent{ name = "Positive Pool", @@ -104,6 +110,7 @@ newTalent{ info = "Allows you to have a positive energy pool.", mode = "passive", hide = true, + no_unlearn_last = true, } newTalent{ name = "Negative Pool", @@ -111,6 +118,7 @@ newTalent{ info = "Allows you to have a negative energy pool.", mode = "passive", hide = true, + no_unlearn_last = true, } newTalent{ name = "Hate Pool", @@ -118,6 +126,7 @@ newTalent{ info = "Allows you to have a hate pool.", mode = "passive", hide = true, + no_unlearn_last = true, } newTalent{ @@ -126,49 +135,7 @@ newTalent{ info = "Allows you to have a paradox pool.", mode = "passive", hide = true, -} - -newTalent{ - name = "Improved Health I", - type = {"base/race", 1}, - info = "Improves the number of health points per level.", - mode = "passive", - hide = true, -} -newTalent{ - name = "Improved Health II", - type = {"base/race", 1}, - info = "Improves the number of health points per level.", - mode = "passive", - hide = true, -} -newTalent{ - name = "Improved Health III", - type = {"base/race", 1}, - info = "Improves the number of health points per level.", - mode = "passive", - hide = true, -} -newTalent{ - name = "Decreased Health I", - type = {"base/race", 1}, - info = "Improves the number of health points per level.", - mode = "passive", - hide = true, -} -newTalent{ - name = "Decreased Health II", - type = {"base/race", 1}, - info = "Improves the number of health points per level.", - mode = "passive", - hide = true, -} -newTalent{ - name = "Decreased Health III", - type = {"base/race", 1}, - info = "Improves the number of health points per level.", - mode = "passive", - hide = true, + no_unlearn_last = true, } -- Mages class talent, teleport to angolwen @@ -178,6 +145,7 @@ newTalent{ type = {"base/class", 1}, cooldown = 400, no_npc_use = true, + no_unlearn_last = true, no_silence=true, is_spell=true, action = function(self, t) if not self:canBe("worldport") or self:attr("never_move") then diff --git a/game/modules/tome/data/talents/misc/races.lua b/game/modules/tome/data/talents/misc/races.lua index 989c7506f7e553fc3103c6ff5213fa4ef62805ca..1c66e2d0c895ee2416dc7991e378197e468a2e1c 100644 --- a/game/modules/tome/data/talents/misc/races.lua +++ b/game/modules/tome/data/talents/misc/races.lua @@ -800,6 +800,7 @@ newTalent{ name = "Knowledge of the Way", type = {"base/race", 1}, no_npc_use = true, + no_unlearn_last = true, on_learn = function(self, t) self.auto_id = 2 end, action = function(self, t) local Chat = require("engine.Chat") diff --git a/game/modules/tome/data/talents/psionic/finer-energy-manipulations.lua b/game/modules/tome/data/talents/psionic/finer-energy-manipulations.lua index 65405adc83796477ba246ba8e549c99bfe2977aa..05a5ab6ed457ccebcbbaadc67e3fe6670190a039 100644 --- a/game/modules/tome/data/talents/psionic/finer-energy-manipulations.lua +++ b/game/modules/tome/data/talents/psionic/finer-energy-manipulations.lua @@ -46,9 +46,9 @@ newTalent{ psi = 0, points = 5, no_npc_use = true, + no_unlearn_last = true, boost = function(self, t) return math.floor(self:combatTalentIntervalDamage(t, "wil", 3, 20)) - end, action = function(self, t) local d d = self:showInventory("Reshape which weapon?", self:getInven("INVEN"), function(o) return not o.quest and o.type == "weapon" and not o.fully_reshaped end, function(o, item) @@ -91,6 +91,7 @@ newTalent{ psi = 0, points = 5, no_npc_use = true, + no_unlearn_last = true, arm_boost = function(self, t) --return math.floor(0.1*self:combatTalentIntervalDamage(t, "wil", 10, 30)) return math.floor(0.25*t.fat_red(self, t)) diff --git a/game/modules/tome/data/talents/spells/stone-alchemy.lua b/game/modules/tome/data/talents/spells/stone-alchemy.lua index 272764c06e8198e20da636c0d73d410fb0819e96..03321f3ed0a9dd3582bd6b69fb33b62e1974e53e 100644 --- a/game/modules/tome/data/talents/spells/stone-alchemy.lua +++ b/game/modules/tome/data/talents/spells/stone-alchemy.lua @@ -69,6 +69,7 @@ newTalent{ points = 5, mana = 5, no_npc_use = true, + no_unlearn_last = true, action = function(self, t) local d d = self:showEquipInven("Try to extract gems from which metallic item?", function(o) return o.metallic and (o.material_level or 1) <= self:getTalentLevelRaw(t) end, function(o, inven, item) if not o then return end @@ -109,6 +110,7 @@ newTalent{ mana = 80, cooldown = 100, no_npc_use = true, + no_unlearn_last = true, action = function(self, t) local d d = self:showInventory("Use which gem?", self:getInven("INVEN"), function(gem) return gem.type == "gem" and gem.imbue_powers and gem.material_level and gem.material_level <= self:getTalentLevelRaw(t) end, function(gem, gem_item) local nd = self:showInventory("Imbue which armour?", self:getInven("INVEN"), function(o) return o.type == "armor" and o.slot == "BODY" and not o.been_imbued end, function(o, item) diff --git a/game/modules/tome/data/talents/undeads/undeads.lua b/game/modules/tome/data/talents/undeads/undeads.lua index 8a17ca3349cf541b5f18803cfb1a267ebb266840..76cdf976084f5e92101067b1cd576618f37a9db2 100644 --- a/game/modules/tome/data/talents/undeads/undeads.lua +++ b/game/modules/tome/data/talents/undeads/undeads.lua @@ -51,6 +51,7 @@ newTalent{ name = "Knowledge of the Past", type = {"undead/base", 1}, no_npc_use = true, + no_unlearn_last = true, on_learn = function(self, t) self.auto_id = 2 end, action = function(self, t) local Chat = require("engine.Chat") diff --git a/game/modules/tome/dialogs/LevelupDialog.lua b/game/modules/tome/dialogs/LevelupDialog.lua index 8f7352e5408c8affd79d485acd0848f10b4653de..8af5b453d57411a936ce21e2886239631c3d1fb8 100644 --- a/game/modules/tome/dialogs/LevelupDialog.lua +++ b/game/modules/tome/dialogs/LevelupDialog.lua @@ -40,6 +40,7 @@ Class talent points left: #00FF00#%d#LAST# Generic talent points left: #00FF00#%d#LAST#]] function _M:init(actor, on_finish) + actor.no_last_learnt_talents_cap = true self.actor = actor self.unused_stats = self.actor.unused_stats self.new_stats_changed = false @@ -139,6 +140,12 @@ Mouse: #00FF00#Left click#FFFFFF# to increase a stat; #00FF00#right click#FFFFFF end end +function _M:unload() + self.actor.no_last_learnt_talents_cap = nil + self.actor:capLastLearntTalents("class") + self.actor:capLastLearntTalents("generic") +end + local prev_sel = nil function _M:onSelectStat(item, force) if item == prev_sel and not force then return end @@ -356,6 +363,7 @@ function _M:cancel() self.actor:unlearnTalent(t_id) end end + self.actor.last_learnt_talents = self.actor_dup.last_learnt_talents end function _M:tabTabs() @@ -596,6 +604,11 @@ function _M:treeSelect(item, sel, v) local it = self.c_t_tree.items_by_key[tid] if it then self.c_t_tree:drawItem(it) end end + local t = self.actor:getTalentFromId(item.talent) + for _, tid in ipairs(self.actor.last_learnt_talents[t.generic and "generic" or "class"]) do + local it = self.c_t_tree.items_by_key[tid] + if it then self.c_t_tree:drawItem(it) end + end end self.c_t_desc:switchItem(item) self.c_t_tree:outputList() @@ -632,6 +645,18 @@ function _M:checkDeps() end end +function _M:isUnlearnable(t, limit) + if not self.actor.last_learnt_talents then return end + local list = self.actor.last_learnt_talents[t.generic and "generic" or "class"] + local max = self.actor:lastLearntTalentsMax(t.generic and "generic" or "class") + local min = 1 + if limit then min = math.max(1, #list - (max - 1)) end + for i = #list, min, -1 do + if list[i] == t.id then return i end + end + return nil +end + function _M:learnTalent(t_id, v) self.talents_learned[t_id] = self.talents_learned[t_id] or 0 local t = self.actor:getTalentFromId(t_id) @@ -659,7 +684,7 @@ function _M:learnTalent(t_id, v) self:simplePopup("Impossible", "You do not know this talent!") return end - if self.actor_dup:getTalentLevelRaw(t_id) == self.actor:getTalentLevelRaw(t_id) then + if not self:isUnlearnable(t, true) and self.actor_dup:getTalentLevelRaw(t_id) >= self.actor:getTalentLevelRaw(t_id) then self:simplePopup("Impossible", "You cannot unlearn talents!") return end @@ -700,7 +725,7 @@ function _M:learnTalent(t_id, v) self:simplePopup("Impossible", "You do not know this talent!") return end - if self.actor_dup:getTalentLevelRaw(t_id) == self.actor:getTalentLevelRaw(t_id) then + if not self:isUnlearnable(t, true) and self.actor_dup:getTalentLevelRaw(t_id) >= self.actor:getTalentLevelRaw(t_id) then self:simplePopup("Impossible", "You cannot unlearn talents!") return end @@ -801,6 +826,13 @@ function _M:onDrawItem(item) else local t = self.actor:getTalentFromId(item.talent) + + if self:isUnlearnable(t, true) then + text:add({"color","LIGHT_BLUE"}, "This talent was recently learnt, you can still unlearn it.", true, "The last ", t.generic and "3 generic" or "4 class", " talents you learnt are always unlearnable.", {"color","LAST"}, true, true) + elseif t.no_unlearn_last then + text:add({"color","YELLOW"}, "This talent can alter the world in a permanent way, as such you can never unlearn it once known.", {"color","LAST"}, true, true) + end + local traw = self.actor:getTalentLevelRaw(t.id) local diff = function(i2, i1, res) res:add({"color", "LIGHT_GREEN"}, i1, {"color", "LAST"}, " [->", {"color", "YELLOW_GREEN"}, i2, {"color", "LAST"}, "]") @@ -887,7 +919,13 @@ function _M:generateList() entity=t.display_entity, talent=t.id, _type=tt.type, - color=function(item) return ((self.actor.talents[item.talent] or 0) ~= (self.actor_dup.talents[item.talent] or 0)) and {255, 215, 0} or self.actor:knowTalentType(item._type) and {255,255,255} or {175,175,175} end, + color=function(item) + if ((self.actor.talents[item.talent] or 0) ~= (self.actor_dup.talents[item.talent] or 0)) then return {255, 215, 0} + elseif self:isUnlearnable(t, true) then return colors.simple(colors.LIGHT_BLUE) + elseif self.actor:knowTalentType(item._type) then return {255,255,255} + else return {175,175,175} + end + end, } list[#list].status = function(item) local t = self.actor:getTalentFromId(item.talent)