diff --git a/game/engines/default/engine/Module.lua b/game/engines/default/engine/Module.lua index d1ce9aba8467d828a57a5da67cf05bba3709dc95..9a1d896b8717c1faa5b9cbf2fde97a20f995967a 100644 --- a/game/engines/default/engine/Module.lua +++ b/game/engines/default/engine/Module.lua @@ -556,6 +556,7 @@ function _M:loadAddons(mod, saveuse) if saveuse then saveuse = table.reverse(saveuse) end local force_remove_addons = {} + local beta_removed = {} -- Filter based on settings for i = #adds, 1, -1 do @@ -585,6 +586,10 @@ function _M:loadAddons(mod, saveuse) print("Removing addon "..add.short_name..": not allowed by config") table.remove(adds, i) removed = true end + elseif not config.settings.cheat and not engine.beta_allow_addon(add) then + print("Removing addon "..add.short_name..": game beta forbids") + table.remove(adds, i) removed = true + beta_removed[#beta_removed+1] = add.long_name else -- Forbidden by version if not add.natural_compatible then @@ -627,6 +632,12 @@ You may try to force loading if you are sure the savefile does not use that addo end end end + if #beta_removed > 0 then + mod.post_load_exec = mod.post_load_exec or {} + mod.post_load_exec[#mod.post_load_exec+1] = function() + require("engine.ui.Dialog"):simpleLongPopup(_t"Beta Addons Disabled", _t"This beta version is meant to be tested without addons, as such the following ones are currently disabled:\n#GREY#"..table.concat(beta_removed, '#LAST#, #GREY#').."#LAST#\n\n".._t"#{italic}##PINK#Addons developers can still test their addons by enabling developer mode.#{normal}#", 600) + end + end -- Let addons disable addons! for i = #adds, 1, -1 do @@ -1144,6 +1155,8 @@ function _M:instanciate(mod, name, new_game, no_reboot, extra_module_info) core.display.resetAllFonts("normal") if mod.short_name ~= "boot" then profile:noMoreAuthWait() end + + if mod.post_load_exec then for _, fct in ipairs(mod.post_load_exec) do fct() end end end --- Setup write dir for a module diff --git a/game/engines/default/engine/interface/ActorTalents.lua b/game/engines/default/engine/interface/ActorTalents.lua index 1de866091e3bfc7aea4447be10575dab9e83f5ee..2c45266b27ca488347b74e68634841dc5cc03285 100644 --- a/game/engines/default/engine/interface/ActorTalents.lua +++ b/game/engines/default/engine/interface/ActorTalents.lua @@ -422,12 +422,13 @@ end -- "def" can have a field "ignore_energy" to not consume energy; other parameters can be passed and handled by an overload of this method. -- Object activation interface calls this method with an "ignore_ressources" parameter function _M:forceUseTalent(t, def) + if type(t) == "table" then t = t.id end -- Ugh local oldpause = game.paused local oldenergy = self.energy.value if def.ignore_energy then self.energy.value = 10000 end if def.ignore_ressources then self:attr("force_talent_ignore_ressources", 1) end - self:setCurrentTalentMode("forced", t.id) + self:setCurrentTalentMode("forced", t) local ret = {self:useTalent(t, def.force_who, def.force_level, def.ignore_cd or def.ignore_cooldown, def.force_target, def.silent, true)} self:setCurrentTalentMode(nil) if def.ignore_ressources then self:attr("force_talent_ignore_ressources", -1) end @@ -894,22 +895,20 @@ end --- Talent level, 0 if not known function _M:getTalentLevelRaw(id) if type(id) == "table" then id = id.id end - local lvl = self.talents[id] or 0 - if lvl > 0 and not self.disable_talents_add_levels then lvl = self:alterTalentLevelRaw(_M.talents_def[id], lvl) end - return lvl + return self.talents[id] or 0 end --- Talent level, 0 if not known -- Includes mastery (defaults to 1) function _M:getTalentLevel(id) local t + if type(id) == "table" then t, id = id, id.id + else t = _M.talents_def[id] end + if not t then return 0 end - if type(id) == "table" then - t, id = id, id.id - else - t = _M.talents_def[id] - end - return t and (self:getTalentLevelRaw(id)) * (self:getTalentMastery(t) or 0) or 0 + local lvl = self:getTalentLevelRaw(id) + if lvl > 0 then lvl = self:alterTalentLevelRaw(t, lvl) end + return lvl * (self:getTalentMastery(t) or 0) end diff --git a/game/engines/default/engine/version.lua b/game/engines/default/engine/version.lua index eecff72c45ba015222d7f6c9629b5b9d22a63899..896342f38a7bdc1d9304831cd9deeac323804ae9 100644 --- a/game/engines/default/engine/version.lua +++ b/game/engines/default/engine/version.lua @@ -110,6 +110,22 @@ end --- Check if we are running as beta function engine.version_hasbeta() if fs.exists("/engine/version_beta.lua") then - return dofile("/engine/version_beta.lua") + local beta = dofile("/engine/version_beta.lua") + return beta + end +end + +--- Check if we are running as beta +function engine.beta_allow_addon(add) + if fs.exists("/engine/version_beta.lua") then + local beta, allowed_addons = dofile("/engine/version_beta.lua") + if not beta or not allowed_addons then return true end + for _, test in ipairs(allowed_addons) do + if type(test) == "function" then return test(add) + elseif add.short_name == test then return true + elseif add.short_name:find(test) then return true end + end + else + return true end end diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index aa2e65a81f7dcccc98c58795b88d8d9af067bfac..71d12cdd1882e5250d27c1a042f53316750d6f05 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -3129,10 +3129,10 @@ function _M:die(src, death_note) local sx, sy = game.level.map:getTileToScreen(self.x, self.y, true) game.flyers:add(sx, sy, 30, (rng.range(0,2)-1) * 0.5, -3, _t"RESURRECT!", {255,120,0}) - local effs = {} - self:removeEffectsSustainsFilter(self, nil, nil, nil, {no_resist=true}) + local effs = {} + self.life = self.max_life self.mana = self.max_mana self.stamina = self.max_stamina @@ -3455,6 +3455,9 @@ function _M:die(src, death_note) if src and src.fireTalentCheck then src:fireTalentCheck("callbackOnKill", self, death_note) end if src and src.summoner and src.summoner.fireTalentCheck then src.summoner:fireTalentCheck("callbackOnSummonKill", src, self, death_note) end + -- We do it at the end so that effects can detect death + self:removeEffectsSustainsFilter(self, nil, nil, nil, {no_resist=true}) + return true end @@ -6750,7 +6753,7 @@ function _M:getTalentFullDescription(t, addlevel, config, fake_mastery) self:triggerHook{"Actor:getTalentFullDescription", str=d, t=t, addlevel=addlevel, config=config, fake_mastery=fake_mastery} d:add({"color",0x6f,0xff,0x83}, _t"Description: ", {"color",0xFF,0xFF,0xFF}) - d:merge(t.info(self, t):toTString():tokenize(" ()[]")) + d:merge(t.info(self, t):toTString():tokenize(" ()[],")) self.talents[t.id] = old @@ -6847,7 +6850,7 @@ end --- Called if a talent level is > 0 function _M:alterTalentLevelRaw(t, lvl) - if t.no_unlearn_last then return lvl end -- Those are dangerous, do not change them + -- if t.no_unlearn_last then return lvl end -- Those are dangerous, do not change them if self.talents_add_levels and self.talents_add_levels[t.id] then lvl = lvl + self.talents_add_levels[t.id] end if self:attr("all_talents_bonus_level") then lvl = lvl + self:attr("all_talents_bonus_level") end if self:attr("spells_bonus_level") and t.is_spell then lvl = lvl + self:attr("spells_bonus_level") end @@ -7078,6 +7081,27 @@ function _M:removeEffectsFilter(src, t, nb, silent, force, check_remove, allow_i return #eff_ids end +--- Force sustains off and on again to account for level/mastery/... changes +function _M:udpateSustains() + local reset = {} + local remaining = {} + for tid, act in pairs(self.sustain_talents) do if act and self:knowTalent(tid) then + local t = self:getTalentFromId(tid) + if not t.no_sustain_autoreset then + reset[#reset+1] = tid + else + remaining[#remaining+1] = tid + end + end end + self.turn_procs.resetting_talents = true + for i, tid in ipairs(reset) do + self:forceUseTalent(tid, {ignore_energy=true, ignore_cd=true, no_talent_fail=true}) + self:forceUseTalent(tid, {ignore_energy=true, ignore_cd=true, no_talent_fail=true, talent_reuse=true}) + end + self.turn_procs.resetting_talents = nil + return remaining +end + -- Mix in sustains local function getSustainType(talent_def) if talent_def.is_mind then return "mental" @@ -7183,7 +7207,7 @@ function _M:dispel(effid_or_tid, src, allow_immunity, params) -- Effect if effid_or_tid:find("^EFF_") then local eff = self:getEffectFromId(effid_or_tid) - if not eff or eff.type == "other" then return end -- NEVER touch other + if (not eff or eff.type == "other") and not params.force then return end -- NEVER touch other if not self:hasEffect(effid_or_tid) then return end if allow_immunity then @@ -7193,7 +7217,7 @@ function _M:dispel(effid_or_tid, src, allow_immunity, params) if self:fireTalentCheck("callbackOnDispel", "effect", effid_or_tid, src, allow_immunity) then allowed = false end end if allowed then - self:removeEffect(effid_or_tid, params.force) + self:removeEffect(effid_or_tid, params.silent, params.force) self:fireTalentCheck("callbackOnDispelled", "effect", effid_or_tid, src, allow_immunity) return true else diff --git a/game/modules/tome/class/GameState.lua b/game/modules/tome/class/GameState.lua index 70f22f9d984eef6086430ead677106e332f0494b..fa6ce75b1c2bc97a4c3cce318c0b3aed5b124db1 100644 --- a/game/modules/tome/class/GameState.lua +++ b/game/modules/tome/class/GameState.lua @@ -2176,14 +2176,14 @@ function _M:applyRandomClass(b, data, instant) local nb_focus, nb_shallow = 0, 0 local rank = b.rank if rank <= 3.2 then --rare - nb_focus = math.floor(0.2 + rng.float(0.25, 0.35)*(math.max(0,data.level))^0.55) -- first around 8-10, second around 25-35, third around 50-70 - nb_shallow = 2 + math.floor(0.25 + rng.float(0.1, 0.2)*(math.max(0,data.level))^0.6) -- third around 12-30, fourth 40-80 + nb_focus = math.floor(0.2 + rng.float(0.22, 0.35)*(math.max(0,data.level-3))^0.5) + nb_shallow = 2 + math.floor(0.25 + rng.float(0.08, 0.2)*(math.max(0,data.level-6))^0.5) elseif rank >= 4 then --boss/elite boss - nb_focus = 1 + math.floor(0.25 + rng.float(0.18, 0.33)*(math.max(0,data.level-4))^0.5) -- second around 11-23, third around 35-75, fourth around 80-90 rarely - nb_shallow = 1 + math.floor(0.33 + rng.float(0.125, 0.2)*(math.max(0,data.level-3))^0.6) -- second around 12-20, third 40-80 + nb_focus = 1 + math.floor(0.25 + rng.float(0.15, 0.35)*(math.max(0,data.level-6))^0.5) + nb_shallow = 1 + math.floor(0.3 + rng.float(0.1, 0.2)*(math.max(0,data.level-4))^0.5) else --unique - nb_focus = 1 + math.floor(0.2 + rng.float(0.15, 0.3)*(math.max(0,data.level-10))^0.5) -- second around 20-40, third around 50-90 - nb_shallow = 1 + math.floor(0.7 + rng.float(0.125, 0.2)*(math.max(0,data.level-8))^0.6) -- second around 11-14, third around 30-60, fourth around 70-90 rarely + nb_focus = 1 + math.floor(0.2 + rng.float(0.15, 0.3)*(math.max(0,data.level-10))^0.5) + nb_shallow = 1 + math.floor(0.55 + rng.float(0.1, 0.2)*(math.max(0,data.level-8))^0.5) end print("Adding "..nb_focus.." primary trees to boss") print("Adding "..nb_shallow.." secondary trees to boss") diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index 7a096e27c74671bbd696d49654184ce7be7c70a1..d90af0e8634e3e22c2e900e5fdff5c7a3d0505ec 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -182,7 +182,7 @@ function _M:onEnterLevel(zone, level) if type(self.tempeffect_def[eff_id].cancel_on_level_change) == "function" then self.tempeffect_def[eff_id].cancel_on_level_change(self, p) end end end - for i, eff_id in ipairs(effs) do self:removeEffect(eff_id) end + for i, eff_id in ipairs(effs) do self:removeEffect(eff_id, nil, true) end -- Clear existing player created effects on the map for i, eff in ipairs(level.map.effects) do diff --git a/game/modules/tome/class/Store.lua b/game/modules/tome/class/Store.lua index dba27a5093f70af67db2bfc972c1e4578c05995e..f056a9e7e5631fb072a64f532312dc00629f9b3d 100644 --- a/game/modules/tome/class/Store.lua +++ b/game/modules/tome/class/Store.lua @@ -280,6 +280,12 @@ end --- Actor interacts with the store -- @param who the actor who interacts function _M:interact(who, name) + -- Nice try + if who.no_inventory_access then + game.logPlayer(who, "This entity can not access inventories.") + return + end + -- Lore-ize me? if who.level < (self.store.minimum_level or 0) then game.logPlayer(who, "You must be level %d to access this shop.", self.store.minimum_level or 0) diff --git a/game/modules/tome/data/autolevel_schemes.lua b/game/modules/tome/data/autolevel_schemes.lua index c208f242fea9c473881e6d657e7cff331f2a0097..dfb5a266880e95dada346ae443767b7b42d3edcb 100644 --- a/game/modules/tome/data/autolevel_schemes.lua +++ b/game/modules/tome/data/autolevel_schemes.lua @@ -58,6 +58,10 @@ Autolevel:registerScheme{ name = "caster", levelup = function(self) self:learnStats{ self.STAT_MAG, self.STAT_MAG, self.STAT_WIL } end} +Autolevel:registerScheme{ name = "wisecaster", levelup = function(self) + self:learnStats{ self.STAT_MAG, self.STAT_WIL } +end} + Autolevel:registerScheme{ name = "warriormage", levelup = function(self) self:learnStats{ self.STAT_MAG, self.STAT_MAG, self.STAT_WIL, self.STAT_STR, self.STAT_STR, self.STAT_DEX } end} diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua index fb4762a40bd4dbe0979bf2189c5fd033406723a9..69472d20119f7e79684a72c398be69780e40b9ea 100644 --- a/game/modules/tome/data/damage_types.lua +++ b/game/modules/tome/data/damage_types.lua @@ -55,7 +55,7 @@ setDefaultProjector(function(src, x, y, type, dam, state) local crit_power = state.crit_power local add_dam = 0 - if not src.turn_procs.damage_type_fix_type then + if not src.turn_procs or not src.turn_procs.damage_type_fix_type then if src:attr("all_damage_convert") and src:attr("all_damage_convert_percent") and src.all_damage_convert ~= type then local ndam = dam * src.all_damage_convert_percent / 100 dam = dam - ndam @@ -676,7 +676,7 @@ setDefaultProjector(function(src, x, y, type, dam, state) target:triggerTalent(target.T_NATURE_S_DEFIANCE, nil, src, t) end end - if t.is_spell and src.knowTalent and src:knowTalent(src.T_BORN_INTO_MAGIC) then + if t.is_spell and src.knowTalent and src:knowTalent(src.T_BORN_INTO_MAGIC) and type ~= DamageType.THAUM then src:triggerTalent(target.T_BORN_INTO_MAGIC, nil, type) end diff --git a/game/modules/tome/data/general/objects/world-artifacts.lua b/game/modules/tome/data/general/objects/world-artifacts.lua index 4c29dc1f52e52e945a33eaab9c626eeca829a6f0..964c8eb1e56260b05fc3d3006004bdb1fadc77e4 100644 --- a/game/modules/tome/data/general/objects/world-artifacts.lua +++ b/game/modules/tome/data/general/objects/world-artifacts.lua @@ -4129,6 +4129,9 @@ newEntity{ base = "BASE_CLOTH_ARMOR", --Thanks Grayswandir! ["spell/water"] = 0.3, ["spell/ice"] = 0.3, ["spell/frost-alchemy"] = 0.3, --more! + ["spell/grave"] = 0.3, --more! + ["spell/glacial-waste"] = 0.3, --more! + ["spell/rime-wraith"] = 0.3, --more! }, }, talent_on_spell = { diff --git a/game/modules/tome/data/maps/vaults/renegade-wyrmics.lua b/game/modules/tome/data/maps/vaults/renegade-wyrmics.lua index ad33d126bfa3f11f5cfa60b2dcddc02b40680dd5..173f9620c4d0230db41e68482f1ece510ddc8684 100644 --- a/game/modules/tome/data/maps/vaults/renegade-wyrmics.lua +++ b/game/modules/tome/data/maps/vaults/renegade-wyrmics.lua @@ -81,15 +81,15 @@ defineTile('C', "ICY_FLOOR", {random_filter={add_levels=25, tome_mod="uvault"}}, [Talents.T_BODY_OF_ICE]={base=3, every=15, max=8}, [Talents.T_UTTERCOLD]={base=3, every=15, max=7},} e:resolve() - return e end, random_filter={add_levels=25, name = "ice wyrm", random_boss={name_scheme=_t"#rng# the Fozen Terror", nb_classes=2, class_filter=function(d) return d.power_source and (d.power_source.nature or d.power_source.technique) and d.name ~= "Wyrmic" end, loot_quality="store", loot_quantity=1, no_loot_randart=true, loot_unique=true, ai_move="move_complex", rank=4, force_classes={Wyrmic=true}}}} ) + return e end, random_filter={add_levels=25, name = "ice wyrm", random_boss={name_scheme=_t"#rng# the Frozen Terror", nb_classes=2, class_filter=function(d) return d.power_source and (d.power_source.nature or d.power_source.technique) and d.name ~= "Wyrmic" end, loot_quality="store", loot_quantity=1, no_loot_randart=true, loot_unique=true, ai_move="move_complex", rank=4, force_classes={Wyrmic=true}}}} ) defineTile('c', "ICY_FLOOR", {random_filter={add_levels=20, type="money"}}, {random_filter={add_levels=12, name = "cold drake"}} ) defineTile('V', "SLIME_FLOOR", {random_filter={add_levels=25, tome_mod="uvault"}}, {entity_mod=function(e) e[#e+1] = resolvers.talents{ - [Talents.T_INDISCERNIBLE_ANATOMY]={base=4, every=12, max=10}, - [Talents.T_GRAND_ARRIVAL]=3, - [Talents.T_WILD_SUMMON]=4, - [Talents.T_ACIDIC_SOIL]={base=3, every=15, max=7}, - [Talents.T_UNSTOPPABLE_NATURE]={base=3, every=15, max=7},} + [Talents.T_INDISCERNIBLE_ANATOMY]={base=2, every=15, max=8}, + [Talents.T_GRAND_ARRIVAL]=2, + [Talents.T_WILD_SUMMON]=3, + [Talents.T_ACIDIC_SOIL]={base=3, every=15, max=5}, + [Talents.T_UNSTOPPABLE_NATURE]={base=3, every=15, max=5},} e:resolve() return e end, random_filter={add_levels=25, name = "venom wyrm", random_boss={name_scheme=_t"#rng# the Caustic Terror", nb_classes=2, class_filter=function(d) return d.power_source and (d.power_source.nature) and d.name ~= "Oozemancer" end, loot_quality="store", loot_quantity=1, ai_move="move_complex", rank=4, force_classes={Oozemancer=true}}}} ) defineTile('v', "SLIME_FLOOR", {random_filter={add_levels=20, type="money"}}, {random_filter={add_levels=12, name = "venom drake"}} ) diff --git a/game/modules/tome/data/talents/chronomancy/anomalies.lua b/game/modules/tome/data/talents/chronomancy/anomalies.lua index 1031d39ec9ed6148cba4fdd18775298eb934c19b..dc2a915bd638e4c3d2e1abb2b6669d23475ba859 100644 --- a/game/modules/tome/data/talents/chronomancy/anomalies.lua +++ b/game/modules/tome/data/talents/chronomancy/anomalies.lua @@ -148,7 +148,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) local radius = self:getTalentRadius(t) @@ -198,7 +198,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) local range = self:getTalentRange(t) @@ -261,7 +261,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[You swap locations with a random target.]]):tformat() @@ -311,7 +311,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[50%% chance that damage the caster takes will be warped to a set target. @@ -410,7 +410,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Creates a wormhole nearby and a second wormhole up to ten tiles away.]]):tformat() @@ -458,7 +458,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Allows up to five targets in a radius of %d to travel up to %d tiles through walls.]]): @@ -507,7 +507,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Up to five targets in a radius of %d are teleporting %d tiles every turn.]]): @@ -622,7 +622,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Pulls innocent people into the fight.]]):tformat() @@ -672,7 +672,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Slows up to five targets in a radius %d ball by %d%%.]]): @@ -721,7 +721,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Increases global speed of up to five targets in a radius %d ball by %d%%.]]): @@ -771,7 +771,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Stuns up to five targets in a radius %d ball.]]): @@ -821,7 +821,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Time Prisons up to five targets in a radius %d ball.]]): @@ -869,7 +869,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Time Shields up to five targets in a radius of %d.]]): @@ -917,7 +917,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Invigorates up to five targets in a radius of %d.]]): @@ -970,7 +970,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Clones a random creature within range.]]):tformat() @@ -1014,7 +1014,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) local duration = self:combatScale(getParadoxSpellpower(self, t), 4, 10, 12, 100, 0.75)/2 @@ -1068,7 +1068,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Increases localized gravity, pulling in targets in a radius of %d.]]):tformat(self:getTalentRadius(t)) @@ -1106,7 +1106,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Digs out all terrain in a radius %d ball.]]):tformat(self:getTalentRadius(t)) @@ -1188,7 +1188,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Entombs a single target in a wall of stone.]]):tformat() @@ -1252,7 +1252,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Places between three and six talents of up to 5 targets in a radius %d ball on cooldown for up to %d turns.]]): @@ -1303,7 +1303,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Creates a gravity well in a radius %d ball, pinning up to five targets.]]):tformat(self:getTalentRadius(t)) @@ -1344,7 +1344,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Causes an earthquake in a radius of %d.]]): @@ -1392,7 +1392,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Reduces the resistances of up to five targets in a ball of radius %d by %d%%.]]):tformat(self:getTalentRadius(t), getAnomalyEffectPower(self, t)) @@ -1459,7 +1459,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Summons three to six dust storms.]]):tformat() @@ -1521,7 +1521,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Summons three to six blazing fires.]]):tformat() @@ -1565,7 +1565,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Turns up to 5 targets in a radius %d ball to stone for %d turns.]]): @@ -1610,7 +1610,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Teleports between 3 and 6 targets to the caster.]]): @@ -1654,7 +1654,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Substantially toughens and hastes one target for %d turns.]]):tformat(getAnomalyDuration(self, t)) @@ -1697,7 +1697,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Clones the caster.]]):tformat(getAnomalyDuration(self, t)) @@ -1746,7 +1746,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Clones all creatures in a radius of 10.]]):tformat(getAnomalyDuration(self, t)) @@ -1782,7 +1782,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Digs out all terrain in between three and six radius %d balls.]]):tformat(self:getTalentRadius(t)) @@ -1842,7 +1842,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Summons a sphere of destruction.]]):tformat() @@ -1921,7 +1921,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Summons three to six tornados.]]):tformat() @@ -2017,7 +2017,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Causes a meteor to fall from the sky.]]): @@ -2101,7 +2101,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Tears a hole in the fabric of spacetime.]]): @@ -2153,7 +2153,7 @@ newTalent{ return true end, action = function(self, t, cancellable) - t.doAction(self, t, true) + return t.doAction(self, t, true) end, info = function(self, t) return ([[Time elementals have been attracted to the timeline.]]): diff --git a/game/modules/tome/data/talents/corruptions/shadowflame.lua b/game/modules/tome/data/talents/corruptions/shadowflame.lua index 86f66491f295965af083ba09e4320ae0dda6a4a8..8bf55406ccf0675f9caab3aa36ead49052db654c 100644 --- a/game/modules/tome/data/talents/corruptions/shadowflame.lua +++ b/game/modules/tome/data/talents/corruptions/shadowflame.lua @@ -138,7 +138,10 @@ newTalent{ requires_target = true, cooldown = 60, no_sustain_autoreset = true, - random_boss_rarity = 10, + random_boss_rarity = 5, + rnd_boss_restrict = function(self, t, data) + return data.level < 20 + end, tactical = { -- heals (negative attack) demons hurts others ATTACKAREA = {FIRE = function(self, t, target) return target:attr("demon") and -2 or 2 end}, diff --git a/game/modules/tome/data/talents/gifts/antimagic.lua b/game/modules/tome/data/talents/gifts/antimagic.lua index 66fc13d0397798f7e64ca98cf9e95d83ed9ae954..fb0dc99ac6e6a5c7568be647335746c4d279b7d2 100644 --- a/game/modules/tome/data/talents/gifts/antimagic.lua +++ b/game/modules/tome/data/talents/gifts/antimagic.lua @@ -67,6 +67,9 @@ newTalent{ equilibrium = 20, cooldown = 12, tactical = { DISABLE = { silence = 4 } }, + rnd_boss_restrict = function(self, t, data) -- Restrict silencing until the player has the tools needed to deal with it + return data.level < 16 + end, range = 6, radius = function(self, t) return 3 end, getduration = function(self, t) return 3 end, @@ -124,6 +127,9 @@ newTalent{ sustain_equilibrium = 30, cooldown = 6, tactical = { DEFEND = 2 }, + rnd_boss_restrict = function(self, t, data) -- Flat damage reduction can be obnoxious early game + return data.level < 18 + end, getMax = function(self, t) local v = combatTalentPhysicalMindDamage(self, t, 20, 85) if self:knowTalent(self.T_TRICKY_DEFENSES) then @@ -180,6 +186,9 @@ newTalent{ cooldown = 15, range = 10, tactical = { ATTACK = { ARCANE = 3 } }, + rnd_boss_restrict = function(self, t, data) -- Restrict antimagic until the player has the tools to deal with it + return data.level < 22 + end, direct_hit = true, requires_target = true, getDamage = function(self, t) return combatTalentPhysicalMindDamage(self, t, 10, 460) end, diff --git a/game/modules/tome/data/talents/spells/dreadmaster.lua b/game/modules/tome/data/talents/spells/dreadmaster.lua index 151a909162737cfab69d8d8978894f4169edeae4..6a8d35d5eabc9448ca8ce49ce81846859e41e91e 100644 --- a/game/modules/tome/data/talents/spells/dreadmaster.lua +++ b/game/modules/tome/data/talents/spells/dreadmaster.lua @@ -40,7 +40,7 @@ newTalent{ sound_random = {"creatures/ghost/random%d", 1, 1}, level_range = {1, nil}, exp_worth = 0, body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1, QUIVER=1 }, - autolevel = "warriormage", + autolevel = "wisecaster", ai = "dumb_talented_simple", ai_state = { ai_target="target_closest", ai_move="move_complex", talent_in=2, }, dont_pass_target = true, stats = { str=14, dex=18, mag=20, con=12 }, @@ -90,7 +90,7 @@ newTalent{ sound_random = {"creatures/ghost/random%d", 1, 1}, level_range = {1, nil}, exp_worth = 0, body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1, QUIVER=1 }, - autolevel = "warriormage", + autolevel = "wisecaster", ai = "dumb_talented_simple", ai_state = { ai_target="target_closest", ai_move="move_complex", talent_in=2, }, dont_pass_target = true, stats = { str=14, dex=18, mag=20, con=12 }, diff --git a/game/modules/tome/data/talents/spells/eradication.lua b/game/modules/tome/data/talents/spells/eradication.lua index 1dc98d37db0ea0716d3dd89a95c2673cc3c72198..a9d3ec7369ee6d1fc42d5099eeb8fc4a83616ca1 100644 --- a/game/modules/tome/data/talents/spells/eradication.lua +++ b/game/modules/tome/data/talents/spells/eradication.lua @@ -113,7 +113,7 @@ newTalent{ if foe:canBe("teleport") and foe:checkHit(self:combatSpellpower(), foe:combatSpellResist(), 0, 95, 15) then foe:forceMoveAnim(spot[1], spot[2]) else - game.logSeen(foe, "%s resists the call of the boneyard!") + game.logSeen(foe, "%s resists the call of the boneyard!", foe:getName():capitalize()) end end diff --git a/game/modules/tome/data/talents/spells/master-of-bones.lua b/game/modules/tome/data/talents/spells/master-of-bones.lua index d834625c3774b8b69a116f383a64f3291fcb177e..671406f7eac37479fda8043dc14c8c195ffaece8 100644 --- a/game/modules/tome/data/talents/spells/master-of-bones.lua +++ b/game/modules/tome/data/talents/spells/master-of-bones.lua @@ -483,10 +483,10 @@ newTalent{ requires_target = true, range = 10, getLevel = function(self, t) return math.floor(self:combatScale(self:getTalentLevel(t), -6, 0.9, 2, 5)) end, -- -6 @ 1, +2 @ 5, +5 @ 8 - on_pre_use = function(self, t) local stats = necroArmyStats(self) return stats.nb_skeleton >= 3 end, + on_pre_use = function(self, t) local stats = necroArmyStats(self) return stats.nb_skeleton >= (stats.lord_of_skulls and 4 or 3) end, action = function(self, t) local stats = necroArmyStats(self) - if stats.nb_skeleton < 3 then return end + if stats.nb_skeleton < (stats.lord_of_skulls and 4 or 3) then return end if stats.bone_giant then stats.bone_giant:die(self) end local list = {} diff --git a/game/modules/tome/data/talents/spells/master-of-flesh.lua b/game/modules/tome/data/talents/spells/master-of-flesh.lua index ab4de88d4d89ecb58868d1ddaa27c6b58e186087..b1dc0143fedecb9b3bf2d31e46b2b40be8096889 100644 --- a/game/modules/tome/data/talents/spells/master-of-flesh.lua +++ b/game/modules/tome/data/talents/spells/master-of-flesh.lua @@ -216,7 +216,7 @@ newTalent{ Ghouls, ghasts and ghoulkings last for %d turns. #GREY##{italic}#Ghoul minions come in larger numbers than skeleton minions but are generally more frail and disposable.#{normal}# - ]]):tformat(t:_getEvery(self), math.max(1, self.level + t:_getLevel(self)), t:_getNb(self), self:getTalentRadius(self, t), t:_getTurns(self)) + ]]):tformat(t:_getEvery(self), math.max(1, self.level + t:_getLevel(self)), t:_getNb(self), t:_getTurns(self)) end, } @@ -316,7 +316,7 @@ newTalent{ e.duration = 10 -- Duration is fake, its handled by the sustain return true end, - false + false, false ) return ret diff --git a/game/modules/tome/data/talents/spells/phantasm.lua b/game/modules/tome/data/talents/spells/phantasm.lua index f3bbe7783c6df8c7f49d6d8211b7a9e025841f48..68961f16ffb7ad51375b55764d655e657d060525 100644 --- a/game/modules/tome/data/talents/spells/phantasm.lua +++ b/game/modules/tome/data/talents/spells/phantasm.lua @@ -86,7 +86,7 @@ newTalent{ callbackOnHit = function(self, t, cb, src, dt) local p = self:isTalentActive(t.id) if not p then return end - if cb.value <= 0 then return end + if cb.value <= 0 or src == self then return end if rng.percent(t.getEvade(self, t)) then game:delayedLogDamage(src, self, 0, ("#YELLOW#(%d ignored)#LAST#"):format(cb.value), false) cb.value = 0 @@ -237,7 +237,9 @@ newTalent{ on_die = function(self) self.summoner:removeEffect(self.summoner.EFF_MIRROR_IMAGE_REAL, true, true) end, - spellFriendlyFire = function() return 100 end, + spellFriendlyFire = function(self) return self.summoner:spellFriendlyFire() end, + archmage_widebeam = self.archmage_widebeam, + iceblock_pierce = self.iceblock_pierce, no_breath = 1, remove_from_party_on_death = true, } @@ -279,7 +281,7 @@ newTalent{ return true end, info = function(self, t) - return ([[Create a perfect lookalike of your own form made out of pure light near a creature or yourself if no creature is present. + return ([[Create a perfect lookalike of your own form made out of pure light near a creature. This image has %d life and can never take more than 1 damage per creature per turn and is immune to any non direct damage (ground effects, damage over time, ...). Whenever you cast a spell your mirror image will try to duplicate it at the same target for 66%% less damage, if possible. If it can it will loose 1 life, if not it will instead taunt a creature to focus its attention on itself. While the image exists you receive the damage bonus from the Invisibility spell as if you were invisible. diff --git a/game/modules/tome/data/talents/spells/spells.lua b/game/modules/tome/data/talents/spells/spells.lua index 35f9f8db68c96f37ce6e4966cf59830aa9c81120..6b5f61b4404424f59d5b5eda3ff99903799c4985 100644 --- a/game/modules/tome/data/talents/spells/spells.lua +++ b/game/modules/tome/data/talents/spells/spells.lua @@ -193,7 +193,7 @@ function necroSetupSummon(self, def, x, y, level, turns, no_control) m.unused_generics = 0 m.unused_talents_types = 0 m.silent_levelup = true - m.no_points_on_levelup = true + -- m.no_points_on_levelup = true m.ai_state = m.ai_state or {} m.ai_state.tactic_leash = 100 -- Try to use stored AI talents to preserve tweaking over multiple summons diff --git a/game/modules/tome/data/talents/spells/thaumaturgy.lua b/game/modules/tome/data/talents/spells/thaumaturgy.lua index c22e50dc91664c3e042a1f0100b191dffe66fc8d..306fd6182cbf5869aafe399e30de1aae895333dd 100644 --- a/game/modules/tome/data/talents/spells/thaumaturgy.lua +++ b/game/modules/tome/data/talents/spells/thaumaturgy.lua @@ -76,11 +76,15 @@ newTalent{ if not thaumaturgyCheck(self) then return end local tids = {} + local is_aethar_avatar = self:hasEffect(self.EFF_AETHER_AVATAR) for kind, list in pairs(t.spells_list) do - for _, tid in ipairs(list) do if self:knowTalent(tid) then - -- print(("[%s] %s : %d"):format(kind, tid, self:getTalentCooldown(self:getTalentFromId(tid), true))) - tids[#tids+1] = {tid=tid, cd=self:getTalentCooldown(self:getTalentFromId(tid), true)} - end end + for _, tid in ipairs(list) do + local tt = self:getTalentFromId(tid) + if self:knowTalent(tid) and (not is_aethar_avatar or (tt.use_only_arcane and self:getTalentLevel(self.T_AETHER_AVATAR) >= tt.use_only_arcane)) then + -- print(("[%s] %s : %d"):format(kind, tid, self:getTalentCooldown(self:getTalentFromId(tid), true))) + tids[#tids+1] = {tid=tid, cd=self:getTalentCooldown(tt, true)} + end + end end local choice = rng.rarityTable(tids, "cd") if not choice then return end @@ -97,7 +101,8 @@ newTalent{ return ([[Casting beam spells has become so instinctive for you that you can now easily weave in other spells at the same time. Anytime you cast a beam spell there is a %d%% chance to automatically cast an offensive spell that you know. This can only happen once per turn. Beam spells duplicated by the Orb of Thaumaturgy can also trigger this effect. - The additional cast will cost mana but no turn and will not active its cooldown.]]): + The additional cast will cost mana but no turn and will not active its cooldown. + During Aether Avatar only compatible spells are used.]]): tformat(t:_getChance(self)) end, } @@ -163,10 +168,17 @@ newTalent{ end, on_pre_use = thaumaturgyCheck, activate = function(self, t) - local ret = { charges = t:_getNb(self) } + local ret = { charges = t:_getNb(self), max_charges = t:_getNb(self) } + -- I'm French and I like cheese but I'll still try to prevent it! + if self.turn_procs.resetting_talents then + ret.charges = ret.charges - self.turn_procs.slipstream_resetting + if ret.charges <= 0 then game:onTickEnd(function() self:forceUseTalent(t.id, {ignore_energy=true}) end) end + end return ret end, - deactivate = function(self, t) + deactivate = function(self, t, p) + -- I'm French and I like cheese but I'll still try to prevent it! + if self.turn_procs.resetting_talents then self.turn_procs.slipstream_resetting = p.max_charges - p.charges end return true end, info = function(self, t) diff --git a/game/modules/tome/data/talents/uber/mag.lua b/game/modules/tome/data/talents/uber/mag.lua index 31997993baf98556b9e97a555694291d70eb7bc6..9939367d9bbe18777898b9c376d532bbcf6a4c16 100644 --- a/game/modules/tome/data/talents/uber/mag.lua +++ b/game/modules/tome/data/talents/uber/mag.lua @@ -431,7 +431,16 @@ uberTalent{ on_learn = function(self, t) self:attr("greater_undead", 1) -- Set that here so that the player cant become an Exarch while waiting for their death to become a Lich self:learnTalent(self.T_NEVERENDING_UNLIFE, true, 1) - game.bignews:say(120, "#DARK_ORCHID#You are on your way to Lichdom. #{bold}#Your next death will finish the ritual.#{normal}#") + + -- Wait for death + if not self.no_resurrect then + game.bignews:say(120, "#DARK_ORCHID#You are on your way to Lichdom. #{bold}#Your next death will finish the ritual.#{normal}#") + -- We cant wait for death! do it now! + else + local dialog = require("mod.dialogs.DeathDialog").new(self) + t:_becomeLich(self) + game.level.map:particleEmitter(self.x, self.y, 1, "demon_teleport") + end end, on_unlearn = function(self, t) end, diff --git a/game/modules/tome/data/timed_effects/magical.lua b/game/modules/tome/data/timed_effects/magical.lua index 28cca64526098515f069009237cf3745ed794c0b..3d781468c322fc88b9b56614a5cc8e3f6102cdeb 100644 --- a/game/modules/tome/data/timed_effects/magical.lua +++ b/game/modules/tome/data/timed_effects/magical.lua @@ -5369,24 +5369,9 @@ newEffect{ parameters = {power=1}, on_gain = function(self, err) return _t"#Target# is overflowing with energy!", true end, on_lose = function(self, err) return _t"#Target# is no more overflowing with energy.", true end, - udpateSustains = function(self) - local reset = {} - for tid, act in pairs(self.sustain_talents) do if act then - local t = self:getTalentFromId(tid) - if not t.no_sustain_autoreset and self:knowTalent(tid) then - reset[#reset+1] = tid - end - end end - self.turn_procs.resetting_talents = true - for i, tid in ipairs(reset) do - self:forceUseTalent(tid, {ignore_energy=true, ignore_cd=true, no_talent_fail=true}) - self:forceUseTalent(tid, {ignore_energy=true, ignore_cd=true, no_talent_fail=true, talent_reuse=true}) - end - self.turn_procs.resetting_talents = nil - end, activate = function(self, eff, ed) eff.tmpid = self:addTemporaryValue("spells_bonus_level", eff.power) - ed.udpateSustains(self) + self:udpateSustains() if core.shader.allow("adv") then eff.particle1, eff.particle2 = self:addParticles3D("volumetric", {kind="fast_sphere", appear=10, radius=1.2, twist=50, density=15, growSpeed=0.002, scrollingSpeed=0.008, img="continuum_01"}) @@ -5396,8 +5381,8 @@ newEffect{ end, deactivate = function(self, eff, ed) self:removeTemporaryValue("spells_bonus_level", eff.tmpid) + self:udpateSustains() if eff.particle1 then self:removeParticles(eff.particle1) end if eff.particle2 then self:removeParticles(eff.particle2) end - ed.udpateSustains(self) end, } diff --git a/game/modules/tome/dialogs/ArenaFinish.lua b/game/modules/tome/dialogs/ArenaFinish.lua index 1f8e47440a87fcabf40c01969540a87c4245381e..3aca6dd753d7fd50f130839a4691f4f4fddf7a4c 100644 --- a/game/modules/tome/dialogs/ArenaFinish.lua +++ b/game/modules/tome/dialogs/ArenaFinish.lua @@ -18,38 +18,20 @@ -- darkgod@te4.org require "engine.class" -local Dialog = require "engine.ui.Dialog" +local DeathDialog = require "mod.dialogs.DeathDialog" local Textzone = require "engine.ui.Textzone" -local Separator = require "engine.ui.Separator" -local List = require "engine.ui.List" -local Savefile = require "engine.Savefile" -local Map = require "engine.Map" +local Shader = require "engine.Shader" -module(..., package.seeall, class.inherit(Dialog)) +module(..., package.seeall, class.inherit(DeathDialog)) function _M:init(actor) - self.actor = actor - Dialog.init(self, _t"Arena mode", 500, 300) - - actor:saveUUID() - - self:generateList() - - self.c_desc = Textzone.new{width=self.iw, auto_height=true, text=self:printRanking() } - self.c_list = List.new{width=self.iw, nb_items=#self.list, list=self.list, fct=function(item) self:use(item) end} - - self:loadUI{ - {left=0, top=0, ui=self.c_desc}, - {left=5, top=self.c_desc.h, padding_h=10, ui=Separator.new{dir="vertical", size=self.iw - 10}}, - {left=0, bottom=0, ui=self.c_list}, - } - self:setFocus(self.c_list) - self:setupUI(false, true) + DeathDialog.init(self, actor) end function _M:printRanking() local scores = world.arena.scores - if not scores[1].name then return _t"#LIGHT_GREEN#No high scores. This should not happen." + if not scores[1].name then + return _t"#LIGHT_GREEN#No high scores. This should not happen." else local text = "" local tmp = "" @@ -65,102 +47,12 @@ function _M:printRanking() end i = i + 1 end - return text - end -end - ---- Clean the actor from debuffs/buffs -function _M:cleanActor(actor) - local effs = {} - - -- Go through all spell effects - for eff_id, p in pairs(actor.tmp) do - local e = actor.tempeffect_def[eff_id] - effs[#effs+1] = {"effect", eff_id} - end - - -- Go through all sustained spells - for tid, act in pairs(actor.sustain_talents) do - if act then - effs[#effs+1] = {"talent", tid} - end - end - - while #effs > 0 do - local eff = rng.tableRemove(effs) - - if eff[1] == "effect" then - actor:removeEffect(eff[2]) - else - actor:forceUseTalent(eff[2], {ignore_energy=true}) - end + return text end end ---- Restore resources -function _M:restoreResources(actor) - if actor.resetToFull then - actor:resetToFull() - actor.energy.value = game.energy_to_act - end -end - ---- Basic resurrection -function _M:resurrectBasic(actor) - actor.dead = false - actor.died = (actor.died or 0) + 1 - - local x, y = util.findFreeGrid(actor.x, actor.y, 20, true, {[Map.ACTOR]=true}) - if not x then x, y = actor.x, actor.y end - actor.x, actor.y = nil, nil - - actor:move(x, y, true) - game.level:addEntity(actor) - game:unregisterDialog(self) - game.level.map:redisplay() - actor.energy.value = game.energy_to_act - actor.changed = true - game.paused = true -end - -function _M:use(item) - if not item then return end - local act = item.action - - if act == "exit" then - game:getPlayer(true).dead = true - game:saveGame() - - world:saveWorld() - if item.subaction == "none" then - util.showMainMenu() - elseif item.subaction == "restart" then - util.showMainMenu(false, engine.version[4], engine.version[1].."."..engine.version[2].."."..engine.version[3], game.__mod_info.short_name, game.save_name, true, ("auto_quickbirth=%q"):format(game:getPlayer(true).name)) - elseif item.subaction == "restart-new" then - util.showMainMenu(false, engine.version[4], engine.version[1].."."..engine.version[2].."."..engine.version[3], game.__mod_info.short_name, game.save_name, true) - end - elseif act == "cheat" then - game.logPlayer(self.actor, "#LIGHT_BLUE#You resurrect! CHEATER !") - - self:cleanActor(self.actor) - self:restoreResources(self.actor) - self:resurrectBasic(self.actor) - elseif act == "dump" then - game:registerDialog(require("mod.dialogs.CharacterSheet").new(self.actor)) - elseif act == "log" then - game:registerDialog(require("mod.dialogs.ShowChatLog").new(_t"Message Log", 0.6, game.uiset.logdisplay, profile.chat)) - end -end - -function _M:generateList() - local list = {} - - if config.settings.cheat then list[#list+1] = {name=_t"Resurrect by cheating", action="cheat"} end - list[#list+1] = {name=(not profile.auth and _t"Message Log" or _t"Message/Chat log (allows to talk)"), action="log"} - list[#list+1] = {name=_t"Character dump", action="dump"} - list[#list+1] = {name=_t"Restart the same character", action="exit", subaction="restart"} - list[#list+1] = {name=_t"Restart with a new character", action="exit", subaction="restart-new"} - list[#list+1] = {name=_t"Exit to main menu", action="exit", subaction="none"} - - self.list = list +function _M:setupDescription() + self.c_desc = Textzone.new{width=self.iw, auto_height=true, text=self:printRanking()} + self.c_desc:setTextShadow(1) + self.c_desc:setShadowShader(Shader.default.textoutline and Shader.default.textoutline.shad, 1.2) end diff --git a/game/modules/tome/dialogs/DeathDialog.lua b/game/modules/tome/dialogs/DeathDialog.lua index 7d2fc20a80436c74f5fb89518aa40a6197df0bdf..39798b3241729b1edd97d7d3dca2328bfac3d46c 100644 --- a/game/modules/tome/dialogs/DeathDialog.lua +++ b/game/modules/tome/dialogs/DeathDialog.lua @@ -39,18 +39,9 @@ function _M:init(actor) if self.dont_show then return end if not config.settings.cheat then game:onTickEnd(function() game:saveGame() end) end - local text = _t[[Death in #{bold}#Tales of Maj'Eyal#{normal}# is usually permanent, but if you have a means of resurrection it will be proposed in the menu below. -You can dump your character data to a file to remember her/him forever, or you can exit and try once again to survive in the wilds! -]] - - if #game.party.on_death_show_achieved > 0 then - self.c_achv = Textzone.new{width=self.iw, scrollbar=true, height=100, text=("#LIGHT_GREEN#During your game you#WHITE#:\n* %s"):tformat(table.concat(game.party.on_death_show_achieved, "\n* "))} - end + self:setupDescription() self:setTitleShadowShader(Shader.default.textoutline and Shader.default.textoutline.shad, 1.5) - self.c_desc = Textzone.new{width=self.iw, auto_height=true, text=text} - self.c_desc:setTextShadow(1) - self.c_desc:setShadowShader(Shader.default.textoutline and Shader.default.textoutline.shad, 1.2) self.c_list = List.new{width=self.iw, nb_items=#self.list, list=self.list, fct=function(item) self:use(item) end, select=function(item) self.cur_item = item end} @@ -88,6 +79,18 @@ You can dump your character data to a file to remember her/him forever, or you c self:setupUI(false, true) end +function _M:setupDescription() + self.c_desc = Textzone.new{width=self.iw, auto_height=true, text=_t[[Death in #{bold}#Tales of Maj'Eyal#{normal}# is usually permanent, but if you have a means of resurrection it will be proposed in the menu below. +You can dump your character data to a file to remember her/him forever, or you can exit and try once again to survive in the wilds! +]]} + self.c_desc:setTextShadow(1) + self.c_desc:setShadowShader(Shader.default.textoutline and Shader.default.textoutline.shad, 1.2) + + if #game.party.on_death_show_achieved > 0 then + self.c_achv = Textzone.new{width=self.iw, scrollbar=true, height=100, text=("#LIGHT_GREEN#During your game you#WHITE#:\n* %s"):tformat(table.concat(game.party.on_death_show_achieved, "\n* "))} + end +end + --- Clean the actor from debuffs/buffs function _M:cleanActor(actor) local effs = {} @@ -180,9 +183,9 @@ function _M:eidolonPlane() local is_exploration = game.permadeath == game.PERMADEATH_INFINITE self:cleanActor(self.actor) self:resurrectBasic(self.actor, "eidolon_plane") - for e, _ in pairs(game.party.members) do + for e, _ in pairs(game.party.members) do if e ~= self.actor then self:cleanActor(e) - end + end end for uid, e in pairs(game.level.entities) do if not is_exploration or game.party:hasMember(e) then self:restoreResources(e) diff --git a/game/modules/tome/dialogs/LevelupDialog.lua b/game/modules/tome/dialogs/LevelupDialog.lua index 5b727be261d1e2c37b5529da925f95859c9204d4..c384321013d607ff3ce43b9e2d18c242225156f8 100644 --- a/game/modules/tome/dialogs/LevelupDialog.lua +++ b/game/modules/tome/dialogs/LevelupDialog.lua @@ -55,7 +55,6 @@ end function _M:init(actor, on_finish, on_birth) self.on_birth = on_birth actor.is_dialog_talent_leveling = true - actor.disable_talents_add_levels = true actor.no_last_learnt_talents_cap = true self.actor = actor self.unused_stats = self.actor.unused_stats @@ -160,7 +159,6 @@ end function _M:unload() self.actor.is_dialog_talent_leveling = nil self.actor.no_last_learnt_talents_cap = nil - self.actor.disable_talents_add_levels = nil self.actor:capLastLearntTalents("class") self.actor:capLastLearntTalents("generic") end @@ -194,26 +192,12 @@ function _M:finish() local txt = _t"#LIGHT_BLUE#Warning: You have increased some of your statistics or talent. Talent(s) actually sustained: \n %s If these are dependent on one of the stats you changed, you need to re-use them for the changes to take effect." local talents = "" - local reset = {} - for tid, act in pairs(self.actor.sustain_talents) do - if act then - local t = self.actor:getTalentFromId(tid) - if t.no_sustain_autoreset and self.actor:knowTalent(tid) then - talents = talents.."#GOLD# - "..t.name.."#LAST#\n" - else - reset[#reset+1] = tid - end - end + for _, tid in ipairs(self.actor:udpateSustains()) do + local t = self.actor:getTalentFromId(tid) + talents = talents.."#GOLD# - "..t.name.."#LAST#\n" end - if talents ~= "" then - game.logPlayer(self.actor, txt:format(talents)) - end - self.actor.turn_procs.resetting_talents = true - for i, tid in ipairs(reset) do - self.actor:forceUseTalent(tid, {ignore_energy=true, ignore_cd=true, no_talent_fail=true}) - if self.actor:knowTalent(tid) then self.actor:forceUseTalent(tid, {ignore_energy=true, ignore_cd=true, no_talent_fail=true, talent_reuse=true}) end - end - self.actor.turn_procs.resetting_talents = nil + if talents ~= "" then game.logPlayer(self.actor, txt:format(talents)) end + -- Prodigies if self.on_finish_prodigies then for tid, ok in pairs(self.on_finish_prodigies) do if ok then self.actor:learnTalent(tid, true, nil, {no_unlearn=true}) end end @@ -985,15 +969,18 @@ function _M:getTalentDesc(item) end local traw = self.actor:getTalentLevelRaw(t.id) + local lvl_alt = self.actor:alterTalentLevelRaw(t, traw) - traw if config.settings.tome.show_detailed_talents_desc then local list = {} for i = 1, 5 do local d = self.actor:getTalentReqDesc(item.talent, i-traw):toTString():tokenize(" ()[]") d:merge(self.actor:getTalentFullDescription(t, i-traw)) - list[i] = d:tokenize(tokenize_number.decimal) + list[i] = d + -- list[i] = d:tokenize(tokenize_number.decimal) end - text:add({"font", "bold"}, _t"Current talent level: "..traw, {"font", "normal"}) - text:add(true) + text:add({"font", "bold"}, _t"Current talent level: "..traw) + if lvl_alt ~= 0 then text:add((" (%+d bonus level)"):tformat(lvl_alt)) end + text:add({"font", "normal"}, true) text:merge(tstring:diffMulti(list, function(diffs, res) for i, d in ipairs(diffs) do if i ~= traw then @@ -1021,22 +1008,25 @@ function _M:getTalentDesc(item) if traw == 0 then local req = self.actor:getTalentReqDesc(item.talent, 1):toTString():tokenize(" ()[]") text:add{"color","WHITE"} - text:add({"font", "bold"}, _t"First talent level: ", tostring(traw+1), {"font", "normal"}) - text:add(true) + text:add({"font", "bold"}, _t"First talent level: ", tostring(traw+1)) + if lvl_alt ~= 0 then text:add((" (%+d bonus level)"):tformat(lvl_alt)) end + text:add({"font", "normal"}, true) text:merge(req) text:merge(self.actor:getTalentFullDescription(t, 1000):diffWith(self.actor:getTalentFullDescription(t, 1), diff_color)) elseif traw < self:getMaxTPoints(t) then local req = self.actor:getTalentReqDesc(item.talent):toTString():tokenize(" ()[]") local req2 = self.actor:getTalentReqDesc(item.talent, 1):toTString():tokenize(" ()[]") text:add{"color","WHITE"} - text:add({"font", "bold"}, traw == 0 and _t"Next talent level" or _t"Current talent level: ", tostring(traw), " [-> ", tostring(traw + 1), "]", {"font", "normal"}) - text:add(true) + text:add({"font", "bold"}, traw == 0 and _t"Next talent level" or _t"Current talent level: ", tostring(traw), " [-> ", tostring(traw + 1), "]") + if lvl_alt ~= 0 then text:add((" (%+d bonus level)"):tformat(lvl_alt)) end + text:add({"font", "normal"}, true) text:merge(req2:diffWith(req, diff_full)) text:merge(self.actor:getTalentFullDescription(t, 1):diffWith(self.actor:getTalentFullDescription(t), diff_full)) else local req = self.actor:getTalentReqDesc(item.talent):toTString():tokenize(" ()[]") - text:add({"font", "bold"}, _t"Current talent level: "..traw, {"font", "normal"}) - text:add(true) + text:add({"font", "bold"}, _t"Current talent level: "..traw) + if lvl_alt ~= 0 then text:add((" (%+d bonus level)"):tformat(lvl_alt)) end + text:add({"font", "normal"}, true) text:merge(req) text:merge(self.actor:getTalentFullDescription(t, 1000):diffWith(self.actor:getTalentFullDescription(t), diff_color)) end diff --git a/utils/release.sh b/utils/release.sh index 5828e614dd86971c916d13e0632eb673a75a8d2b..119c5599324cdfef0f502f1e47c4e05209347cdb 100755 --- a/utils/release.sh +++ b/utils/release.sh @@ -1,7 +1,7 @@ #!/bin/sh if test $# -lt 1 ; then - echo "Usage: release.sh [version] [beta, if any]" + echo "Usage: release.sh [version] [beta, if any] [if beta, allowed addons list or 'all' or 'no-dlc' or 'with-dlc']" exit fi @@ -69,7 +69,21 @@ find . -name '*~' -or -name '.svn' -or -name '.keep' | xargs rm -rf echo "version_desc = '$ver'" >> game/engines/default/modules/boot/init.lua echo "version_desc = '$ver'" >> game/modules/tome/init.lua if test -n "$beta"; then - echo "return '$beta'" > game/engines/default/engine/version_beta.lua + if test $# -lt 3 ; then + echo "Usage: release.sh [version] [beta] [allowed addons list or 'all' or 'no-dlc' or 'with-dlc']" + exit + fi + addons="$3" + if test "$addons" = "all"; then + echo "return '$beta'" > game/engines/default/engine/version_beta.lua + elif test "$addons" = "no-dlc"; then + echo "return '$beta', "'{"possessors", "items-vault", "^cosmetic%-shimmer%-.+"}' > game/engines/default/engine/version_beta.lua + elif test "$addons" = "with-dlc"; then + echo "return '$beta', "'{"possessors", "items-vault", "^cosmetic%-shimmer%-.+", function(add) return add.id_dlc end}' > game/engines/default/engine/version_beta.lua + else + addons_check=`echo "$addons" | sed -e 's/\([^,]\+\)/"\1"/g' -e 's/^/{/' -e 's/$/}/'` + echo "return '$beta', '$addons_check'" > game/engines/default/engine/version_beta.lua + fi fi # create teae/teams