diff --git a/game/engines/default/engine/Trap.lua b/game/engines/default/engine/Trap.lua index 45ef4525792563f2242140338f47f3b85e7eb1a1..739c5becdc4e493846d0b93f57f6f4f4b303e31d 100644 --- a/game/engines/default/engine/Trap.lua +++ b/game/engines/default/engine/Trap.lua @@ -28,6 +28,7 @@ module(..., package.seeall, class.inherit(Entity)) _M.display_on_seen = true _M.display_on_remember = true _M.display_on_unknown = false +_M.__is_trap = true function _M:init(t, no_default) t = t or {} @@ -88,7 +89,7 @@ end --- Get the known status for the given actor function _M:knownBy(actor) - return self.known_by[actor] or self.all_know + return self.all_know or self.known_by[actor] end --- Can we disarm this trap? diff --git a/game/engines/default/engine/ui/Inventory.lua b/game/engines/default/engine/ui/Inventory.lua index 2f6644f2386a69d1947c1c3168cb85e254a8da70..fca180d5f2c9b2d51aef247644c9fc554446e277 100644 --- a/game/engines/default/engine/ui/Inventory.lua +++ b/game/engines/default/engine/ui/Inventory.lua @@ -75,12 +75,26 @@ function _M:generate() end self.c_tabs.no_keyboard_focus = true - if _M._last_tabs then - for _, l in ipairs(_M._last_tabs) do self.c_tabs.dlist[l[1]][l[2]].selected = true end - if _M._last_tabs_i then self.c_tabs.sel_i = _M._last_tabs_i end - else + + local found_tab = false + if _M._last_tabs then -- reselect previously selected tabs if possible + local sel_all = _M._last_tabs.all + local last_kinds = {} + for _, lt in ipairs(_M._last_tabs) do if lt.kind then last_kinds[lt.kind] = true end end + for j, row in ipairs(self.c_tabs.dlist) do for i, item in ipairs(row) do + if sel_all or last_kinds[item.data.kind] then + item.selected = true + found_tab = true + self.c_tabs.sel_i, self.c_tabs.sel_j = i, j + if sel_all and item.data.filter=="all" then _M._last_tabs_i = i end + end + end end + end + if not found_tab then + self.c_tabs.sel_i, self.c_tabs.sel_j = 1, 1 self.c_tabs.dlist[1][1].selected = true end + self.uis[#self.uis+1] = {x=0, y=0, ui=self.c_tabs} self.c_tabs.on_focus_change = function(ui_self, status) if status == true then @@ -241,14 +255,17 @@ function _M:updateTabFilterList(list) return false end - -- Save for next dialogs + -- Save for next dialog if not self.dont_update_last_tabs then _M._last_tabs = self.c_tabs:getAllSelectedKeys() if not is_all then local i = 1 - for _, d in ipairs(_M._last_tabs) do i = math.max(i, d[2]) end + for _, d in ipairs(_M._last_tabs) do + i = math.max(i, d[2]) d.kind = self.c_tabs.dlist[d[1]][d[2]].data.kind + end _M._last_tabs_i = i else + _M._last_tabs.all = true _M._last_tabs_i = #self.tabslist end end diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index f19901fe8bc63f711c7eb34a2d742790086d9fa8..1c497be76287cff7d13936313e3c715142a85022 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -251,9 +251,9 @@ function _M:init(t, no_default) physspeed =1, dammod = { str=1 }, damrange=1.1, - talented = "unarmed", } - -- Insures we have certain values for gloves to modify + -- Ensures we have certain values for gloves to modify + self.combat.talented = self.combat.talented or "unarmed" self.combat.damrange = self.combat.damrange or 1.1 self.combat.physspeed = self.combat.physspeed or 1 self.combat.dammod = self.combat.dammod or {str=0.6} @@ -1330,11 +1330,7 @@ function _M:move(x, y, force) local grids = core.fov.circle_grids(self.x, self.y, 1, true) for x, yy in pairs(grids) do for y, _ in pairs(yy) do local trap = game.level.map(x, y, Map.TRAP) - if trap and not trap:knownBy(self) and self:canSee(trap) and self:checkHit(power, trap.detect_power) then - trap:setKnown(self, true, x, y) - game.level.map:updateMap(x, y) - game.logPlayer(self, "You have found a trap (%s)!", trap:getName()) - end + if trap then self:detectTrap(trap, x, y, power) end end end end @@ -1571,6 +1567,32 @@ function _M:doQuake(tg, x, y) end) end +--- Attempt to detect a trap at x, y +-- param trap the trap to be detected +-- param x, y trap coordinates +-- param power detection power (optional) +function _M:detectTrap(trap, x, y, power) + power = power or self:callTalent(self.T_HEIGHTENED_SENSES, "trapPower") + if power <= 0 then return end + trap = trap or game.level.map(x, y, Map.TRAP) + if trap then + x, y = x or trap.x, y or trap.y +--print("[Actor:detectTrap]", self.name, "attempting to detect trap at", x, y, trap.name, power, trap.detect_power) + local known = trap:knownBy(self) + if not known then + if self == trap.summoner and known == nil then trap:setKnown(self, true, x, y) return end + known = self:canSee(trap) and self:checkHit(power, trap.detect_power) + if known then + trap:setKnown(self, true, x, y) + if self.player then + game.level.map:updateMap(x, y) + game.logPlayer(self, "#AQUAMARINE#You notice a trap (%s)!", trap:getName()) + end + end + end + end +end + --- Reveals location surrounding the actor function _M:magicMap(radius, x, y, checker) x = x or self.x @@ -5978,27 +6000,31 @@ function _M:suffocate(value, src, death_message) return false, true end --- Can the actor see the target actor (or other entity) +-- Can the actor see the target (Actor or other Entity), recomputes results (does not use can_see_cache) -- This does not check LOS or such, only the actual ability to see it.<br/> --- Check for telepathy, invisibility, stealth, ... +-- Checks for telepathy, invisibility, stealth, ... +-- @param[type=Entity] actor the target Entity (usually Actor) to be seen +-- @param[type=boolean] def the default result +-- @param[type=number] def_pct the default percent chance +-- @return[1] true or false +-- @return[2] a number from 0 to 100 representing the percent "chance" to be seen function _M:canSeeNoCache(actor, def, def_pct) if not actor then return false, 0 end - -- Full ESP - if self.esp_all and self.esp_all > 0 then - return true, 100 - end + if actor.__is_actor then -- check ESP against actors + if self.esp_all and self.esp_all > 0 then return true, 100 end -- Full ESP - -- ESP, see all, or only types/subtypes - if self.esp then - local esp = self.esp - local t, st = tostring(rawget(actor, "type") or "???"), tostring(rawget(actor, "subtype") or "???") - -- Type based ESP - if esp[t] and esp[t] > 0 then - return true, 100 - end - if esp[t.."/"..st] and esp[t.."/"..st] > 0 then - return true, 100 + -- ESP, see all, or only types/subtypes + if self.esp then + local esp = self.esp + local t, st = tostring(rawget(actor, "type") or "???"), tostring(rawget(actor, "subtype") or "???") + -- Type based ESP + if esp[t] and esp[t] > 0 then + return true, 100 + end + if esp[t.."/"..st] and esp[t.."/"..st] > 0 then + return true, 100 + end end end @@ -6007,33 +6033,38 @@ function _M:canSeeNoCache(actor, def, def_pct) return false, 0 end - -- Check for stealth. Checks against the target cunning and level - if actor ~= self and actor.attr and actor:attr("stealth") then - local def = self:combatSeeStealth() - local hit, chance = self:checkHitOld(def, actor:attr("stealth") + (actor:attr("inc_stealth") or 0), 0, 100) - if not hit then - return false, chance - end - end - + local chance, hit = 100 -- Check for invisibility. This is a "simple" checkHit between invisible and see_invisible attrs if actor ~= self and actor.attr and actor:attr("invisible") then -- Special case, 0 see invisible, can NEVER see invisible things local def = self:combatSeeInvisible() if def <= 0 then return false, 0 end - local hit, chance = self:checkHitOld(def, actor:attr("invisible"), 0, 100) - if not hit then - return false, chance + hit, chance = self:checkHitOld(def, actor:attr("invisible"), 0, 100) end + -- Check for stealth. Applies cunning and level vs target's stealth attributes + if actor ~= self and actor.attr and actor:attr("stealth") then + local def, st_chance = self:combatSeeStealth() + hit, st_chance = self:checkHitOld(def, actor:attr("stealth") + (actor:attr("inc_stealth") or 0), 0, 100) + chance = chance*st_chance/100 end + if chance < 100 then hit = rng.percent(chance) else hit = true end if def ~= nil then return def, def_pct else - return true, 100 + return hit, chance end end +--- Can the actor see the target (Actor or other Entity)? +-- This does not check LOS or such, only the actual ability to see it.<br/> +-- Checks for telepathy, invisibility, stealth, ... +-- Stores results in self.can_see_cache for later calls +-- @param[type=Actor] actor the target actor to check +-- @param[type=boolean] def the default result +-- @param[type=number] def_pct the default percent chance +-- @return[1] true or false +-- @return[2] a number from 0 to 100 representing the "chance" to be seen function _M:canSee(actor, def, def_pct) if not actor then return false, 0 end @@ -6058,7 +6089,7 @@ function _M:resetCanSeeCache() self.can_see_cache = setmetatable({}, {__mode="k"}) end ---- Reset the cache of everything else that had see us on the level +--- Reset the cache of everything else that had seen us on the level function _M:resetCanSeeCacheOf() if not game.level then return end for uid, e in pairs(game.level.entities) do diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 8386e58940f1c015063f8ec0b9f512adc3f274f0..a37be1a4cc303c917b607fc299e38e1d822ede5a 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -1381,28 +1381,44 @@ function _M:tick() end -- Game Log management functions: --- logVisible to determine if a message should be visible to the player --- logMessage to add a message to the display --- delayedLogMessage to queue an actor-specific message for display at the end of the current game tick --- displayDelayedLogMessages() to display the queued messages (before combat damage messages) --- delayedLogDamage to queue a combat (damage) message for display at the end of the current game tick --- displayDelayedLogDamage to display the queued combat messages - --- output a message to the log based on the visibility of an actor to the player +-- logVisible: determines if a message should be visible to the player +-- logMessage: creates the message to be passed to the display +-- delayedLogMessage: queues an actor-specific message for display at the end of the current game tick +-- displayDelayedLogMessages: displays the queued delayedLogMessage messages (before combat damage messages) +-- delayedLogDamage: queues combat damage (and associated message) for display at the end of the current game tick +-- displayDelayedLogDamage: collates and displays queued delayedLogDamage information + +--- Output a message to the log based on the visibility of an actor to the player +-- @param e the actor(entity) to check visibility for +-- @param style the message to display +-- @param ... arguments to be passed to format for style function _M.logSeen(e, style, ...) if e and e.player or (not e.dead and e.x and e.y and game.level and game.level.map.seens(e.x, e.y) and game.player:canSee(e)) then game.log(style, ...) end end --- determine whether an action between 2 actors should produce a message in the log and if the player --- can identify them --- output: src, srcSeen: source display?, identify? --- tgt, tgtSeen: target display?, identify? --- output: Visible? and srcSeen (source is identified by the player), tgtSeen(target is identified by the player) +--- Determine whether an action between 2 actors (or entities or effects) should produce a message in the log +-- and if they should be identified to the player +-- @param source: source of the action +-- @param target: target of the action +-- @return[1] [type=boolean] message visible to player +-- @return[2] [type=boolean] source is identified by player +-- @return[3] [type=boolean] target is identified by player function _M:logVisible(source, target) - -- target should display if it's the player, an actor (or projectile) in a seen tile, or a non-actor without coordinates - local tgt = target and (target.player or ((target.__is_actor or target.__is_projectile) and game.level.map.seens(target.x, target.y)) or (not target.__is_actor and not target.x)) - local tgtSeen = tgt and (target.player or game.player:canSee(target)) or false - local src, srcSeen = false, false + -- target should display if it's the player, an acting entity (actor, projectile, or trap) in a seen tile, or a non-acting entity without coordinates + local tgt, tgtSeen + if target then + if target.player then tgt, tgtSeen = true, true + else + if target.__is_actor or target.__is_projectile or target.__is_trap then + tgt = game.level.map.seens(target.x, target.y) + else + tgt = not target.x + end + tgtSeen = tgt and game.player:canSee(target) or false + end + end + + local src, srcSeen, src_act = false, false -- Special cases if not source.x then -- special case: unpositioned source uses target parameters (for timed effects on target) if tgtSeen then @@ -1410,18 +1426,29 @@ function _M:logVisible(source, target) else src, tgt = nil, nil end - else -- source should display if it's the player or an actor (or projectile) in a seen tile, or same as target for non-actors - src = source.player or ((source.__is_actor or source.__is_projectile) and game.level.map.seens(source.x, source.y)) or (not source.__is_actor and tgt) - srcSeen = src and game.player:canSee(source) or false + else -- source should display if it's the player or an acting entity in a seen tile, or same as target for non-acting entities + if source.player then src, srcSeen = true, true + else + if source.__is_actor or source.__is_projectile or source.__is_trap then + src = game.level.map.seens(source.x, source.y) + else + src = tgt + end + srcSeen = src and game.player:canSee(source) or false + end end - return src or tgt or false, srcSeen, tgtSeen end --- Generate a message (string) for the log with possible source and target, --- highlighting the player and taking visibility into account --- srcSeen, tgtSeen = can player see(identify) the source, target? --- style text message to display, may contain: +--- Generate a message (string) for the log with possible source and target, +-- highlights the player and takes visibility into account +-- @param source: source (primary) actor +-- @param srcSeen: [type=boolean] source is identified +-- @param target: target (secondary) actor +-- @param tgtSeen: [type=boolean] target is identified +-- @param style the message to display +-- @param ... arguments to be passed to format for style +-- @return the string with certain fields replaced: -- #source#|#Source# -> <displayString>..self.name|self.name:capitalize() -- #target#|#Target# -> target.name|target.name:capitalize() function _M:logMessage(source, srcSeen, target, tgtSeen, style, ...) @@ -1449,10 +1476,14 @@ function _M:logMessage(source, srcSeen, target, tgtSeen, style, ...) return style end --- log an entity-specific message for display later with displayDelayedLogDamage --- only one message (processed with logMessage) will be logged for each source and label +--- Log an entity-specific message for display later with displayDelayedLogMessages -- useful to avoid spamming repeated messages --- target is optional and is used only to resolve the msg +-- @param source: source (primary) actor +-- @param target [optional]: target (secondary) actor (used only to resolve msg) +-- @param label: a unique tag for this message +-- @param msg raw string passed to logMessage +-- takes visibility into account +-- only one message (processed with logMessage) will be logged for each source and label function _M:delayedLogMessage(source, target, label, msg, ...) local visible, srcSeen, tgtSeen = self:logVisible(source, target) if visible then @@ -1462,7 +1493,8 @@ function _M:delayedLogMessage(source, target, label, msg, ...) end end --- display the delayed log messages +--- Push all queued delayed log messages to the combat log +-- Called at the end of each game tick function _M:displayDelayedLogMessages() if not self.uiset or not self.uiset.logdisplay then return end for src, msgs in pairs(self.delayed_log_messages) do @@ -1473,7 +1505,8 @@ function _M:displayDelayedLogMessages() self.delayed_log_messages = {} end --- Note: There can be up to a 1 tick delay in displaying log information +--- Collate and push all queued delayed log damage information to the combat log +-- Called at the end of each game tick function _M:displayDelayedLogDamage() if not self.uiset or not self.uiset.logdisplay then return end for real_src, psrcs in pairs(self.delayed_log_damage) do @@ -1514,7 +1547,13 @@ function _M:displayDelayedLogDamage() self.delayed_log_damage = {} end --- log and collate combat damage for later display with displayDelayedLogDamage +--- Queue combat damage values and messages for later display with displayDelayedLogDamage +-- @param src: source (primary) actor dealing the damage +-- @param target: target (secondary) actor recieving the damage +-- @param dam: [type=number] damage effectively dealt, added to total +-- negative dam is counted as healing and summed separately +-- @param desc: [type=string] text description of damage dealth, passed directly to log message +-- @param crit: [type=boolean] set true if the damage was dealt via critcal hit function _M:delayedLogDamage(src, target, dam, desc, crit) if not target or not src then return end local psrc = src.__project_source or src -- assign message to indirect damage source if available diff --git a/game/modules/tome/class/Object.lua b/game/modules/tome/class/Object.lua index a2e361bc8184379a9f212046cfdb2c7ace6f50e0..ea2a2f3390fefee04e5cf2d67353fc9f993b742b 100644 --- a/game/modules/tome/class/Object.lua +++ b/game/modules/tome/class/Object.lua @@ -41,6 +41,9 @@ _M.projectile_class = "mod.class.Projectile" _M.logCombat = Combat.logCombat +-- ego fields that are appended as a list when the ego is applied (by Zone:applyEgo) +_M._special_ego_rules = {special_on_hit=true, special_on_crit=true, special_on_kill=true, charm_on_use=true} + function _M:getRequirementDesc(who) local base_getRequirementDesc = engine.Object.getRequirementDesc if self.subtype == "shield" and type(self.require) == "table" and who:knowTalent(who.T_SKIRMISHER_BUCKLER_EXPERTISE) then diff --git a/game/modules/tome/class/Trap.lua b/game/modules/tome/class/Trap.lua index d38eb06261e4dd532763f10e304bcbac3722d177..7b3fe8b1898d64e86c23bf482c0ae3a50072ae3b 100644 --- a/game/modules/tome/class/Trap.lua +++ b/game/modules/tome/class/Trap.lua @@ -65,6 +65,21 @@ function _M:resolveSource() end end +--- Called when the trap is added to the level +function _M:added() + engine.Entity.added(self) + if self.x and self.y then --give adjacent actors a chance to detect the trap when it is placed + local grids = core.fov.circle_grids(self.x, self.y, 1, true) + local act + for x, yy in pairs(grids) do for y, _ in pairs(yy) do + act = game.level.map(x, y, engine.Map.ACTOR) + if act and not self:knownBy(act) then + act:detectTrap(self, self.x, self.y) + end + end end + end +end + -- Gets the full name of the trap function _M:getName() local name = self.name or "trap" diff --git a/game/modules/tome/class/Zone.lua b/game/modules/tome/class/Zone.lua index 7a78aa8fcbee44cbb4b1fc16d5a646b712d35c64..aaf08bf5c24ce1e1a410d276b27f9cf6c388c847 100644 --- a/game/modules/tome/class/Zone.lua +++ b/game/modules/tome/class/Zone.lua @@ -28,10 +28,15 @@ _M:enableLastPersistZones(3) -- retain the room map after level generation (for runPostGeneration callbacks) _M._retain_level_room_map = true +-- object ego fields that are appended as a list when the ego is applied +-- overridden by mod.class.Object._special_ego_rules (defined here for backwards compatibility) +_M._object_special_ego_rules = {special_on_hit=true, special_on_crit=true, special_on_kill=true} + -- Merge special_on_crit values. _M:addEgoRule("object", function(dvalue, svalue, key, dst, src, rules, state) - -- Only work on the special_on_* keys. - if key ~= 'special_on_hit' and key ~= 'special_on_crit' and key ~= 'special_on_kill' then return end + -- Only apply to some special fields + local special_rule_egos = mod.class.Object._special_ego_rules or _M._object_special_ego_rules + if not special_rule_egos[key] then return end -- If the special isn't a table, make it an empty one. if type(dvalue) ~= 'table' then dvalue = {} end if type(svalue) ~= 'table' then svalue = {} end diff --git a/game/modules/tome/data/general/objects/egos/charms.lua b/game/modules/tome/data/general/objects/egos/charms.lua index a5ae6f4f55b47fe4ef29c222ab8762a0ed09356e..e69ce495711f8c69c6dfd7498eec594a957dc22c 100644 --- a/game/modules/tome/data/general/objects/egos/charms.lua +++ b/game/modules/tome/data/general/objects/egos/charms.lua @@ -17,16 +17,35 @@ -- Nicolas Casalini "DarkGod" -- darkgod@te4.org +-- modify the power and cooldown of charm powers +-- This makes adjustments after zone:finishEntity is finished, which handles any egos added via e.addons +local function modify_charm(e, e, zone, level) + for i, c_mod in ipairs(e.charm_power_mods) do + c_mod(e, e, zone, level) + end + if e._old_finish and e._old_finish ~= e._modify_charm then return e._old_finish(e, e, zone, level) end +end + newEntity{ name = "quick ", prefix=true, keywords = {quick=true}, level_range = {1, 50}, rarity = 15, cost = 5, + _modify_charm = modify_charm, resolvers.genericlast(function(e) - if not e.use_power or not e.charm_power then return end - e.use_power.power = math.ceil(e.use_power.power * rng.float(0.6, 0.8)) - e.charm_power = math.ceil(e.charm_power * rng.float(0.4, 0.7)) + if e.finish ~= e._modify_charm then e._old_finish = e.finish end + e.finish = e._modify_charm + e.charm_power_mods = e.charm_power_mods or {} + table.insert(e.charm_power_mods, function(e, e, zone, level) + if e.charm_power and e.use_power and e.use_power.power then + print("\t Applying quick ego changes.") + e.use_power.power = math.ceil(e.use_power.power * rng.float(0.6, 0.8)) + e.charm_power = math.ceil(e.charm_power * rng.float(0.6, 0.9)) + else + print("\tquick ego changes aborted.") + end + end) end), } @@ -36,10 +55,20 @@ newEntity{ level_range = {1, 50}, rarity = 15, cost = 5, + _modify_charm = modify_charm, resolvers.genericlast(function(e) - if not e.use_power or not e.charm_power then return end - e.use_power.power = math.ceil(e.use_power.power * rng.float(1.2, 1.5)) - e.charm_power = math.ceil(e.charm_power * rng.float(1.3, 1.5)) + if e.finish ~= e._modify_charm then e._old_finish = e.finish end + e.finish = e._modify_charm + e.charm_power_mods = e.charm_power_mods or {} + table.insert(e.charm_power_mods, function(e, e, zone, level) + if e.charm_power and e.use_power and e.use_power.power then + print("\t Applying supercharged ego changes.") + e.use_power.power = math.ceil(e.use_power.power * rng.float(1.1, 1.3)) + e.charm_power = math.ceil(e.charm_power * rng.float(1.3, 1.5)) + else + print("\tsupercharged ego changes aborted.") + end + end) end), } @@ -50,9 +79,19 @@ newEntity{ greater_ego = 1, rarity = 16, cost = 5, + _modify_charm = modify_charm, resolvers.genericlast(function(e) - if not e.use_power or not e.charm_power then return end - e.use_power.power = math.ceil(e.use_power.power * rng.float(1.4, 1.7)) - e.charm_power = math.ceil(e.charm_power * rng.float(1.6, 1.9)) + if e.finish ~= e._modify_charm then e._old_finish = e.finish end + e.finish = e._modify_charm + e.charm_power_mods = e.charm_power_mods or {} + table.insert(e.charm_power_mods, function(e, e, zone, level) + if e.charm_power and e.use_power and e.use_power.power then + print("\t Applying overpowered ego changes.") + e.use_power.power = math.ceil(e.use_power.power * rng.float(1.2, 1.5)) + e.charm_power = math.ceil(e.charm_power * rng.float(1.6, 1.9)) + else + print("\toverpowered ego changes aborted.") + end + end) end), } diff --git a/game/modules/tome/data/general/objects/egos/torques.lua b/game/modules/tome/data/general/objects/egos/torques.lua index 7b582276cfc3ef582545fa6e79eb02010ad4c3ef..37aa4fad657fc96f3e405710086db431f0f937cb 100644 --- a/game/modules/tome/data/general/objects/egos/torques.lua +++ b/game/modules/tome/data/general/objects/egos/torques.lua @@ -34,7 +34,7 @@ newEntity{ who:incPsi(self:getCharmPower(who, true) / 7) end}, }, - use_power = {tactical = {PSI = 1}} + use_power = {tactical = {PSI = 0.5}} } newEntity{ @@ -49,7 +49,7 @@ newEntity{ who:incHate(self:getCharmPower(who, true) / 7) end}, }, - use_power = {tactical = {HATE = 1}} + use_power = {tactical = {HATE = 0.5}} } newEntity{ @@ -79,7 +79,7 @@ newEntity{ cost = 5, wielder = { - talent_cd_reduction={[Talents.T_SILENCE]=-5}, + talent_cd_reduction={[Talents.T_SILENCE]=1}, learn_talent = {[Talents.T_SILENCE] = resolvers.mbonus_material(4, 1)}, }, } @@ -93,7 +93,7 @@ newEntity{ cost = 5, wielder = { - talent_cd_reduction={[Talents.T_TELEKINETIC_BLAST]=-5}, +-- talent_cd_reduction={[Talents.T_TELEKINETIC_BLAST]=-5}, learn_talent = {[Talents.T_TELEKINETIC_BLAST] = resolvers.mbonus_material(4, 1)}, }, } diff --git a/game/modules/tome/data/general/objects/egos/totems-powers.lua b/game/modules/tome/data/general/objects/egos/totems-powers.lua index a514f1eaa006c2205184c17be4864aff3c6545b4..36d256746bde3430a54c4b2a35f63d1c036158ca 100644 --- a/game/modules/tome/data/general/objects/egos/totems-powers.lua +++ b/game/modules/tome/data/general/objects/egos/totems-powers.lua @@ -21,7 +21,6 @@ Totems *healing *cure illness -*cure poisons *thorny skin ]] @@ -79,7 +78,8 @@ newEntity{ end end return nb - end}, + end, + }, }), } @@ -122,7 +122,7 @@ newEntity{ who:project(tg, x, y, engine.DamageType.HEAL, dam) game:playSoundNear(who, "talents/heal") return {id=true, used=true} - end, + end, "T_GLOBAL_CD", {range = function(self, who) return math.floor(who:combatStatScale("wil", 6, 10)) end, damage = function(self, who) return self:getCharmPower(who) end, diff --git a/game/modules/tome/data/general/objects/egos/totems.lua b/game/modules/tome/data/general/objects/egos/totems.lua index ab9e767f67679074b79d595a1ffc66e9266c9c16..eb206cf367523bb18fe4135a7effdbd439e6a493 100644 --- a/game/modules/tome/data/general/objects/egos/totems.lua +++ b/game/modules/tome/data/general/objects/egos/totems.lua @@ -34,7 +34,7 @@ newEntity{ who:incEquilibrium(-self:getCharmPower(who, true) / 5) end}, }, - use_power = {tactical = {EQUILIBRIUM = 1}} + use_power = {tactical = {EQUILIBRIUM = 0.5}} } newEntity{ @@ -49,7 +49,7 @@ newEntity{ who:incStamina(self:getCharmPower(who, true) / 6) end}, }, - use_power = {tactical = {STAMINA = 1}} + use_power = {tactical = {STAMINA = 0.5}} } newEntity{ @@ -79,6 +79,7 @@ newEntity{ cost = 5, wielder = { + talent_cd_reduction={[Talents.T_RUSHING_CLAWS]=1}, learn_talent = {[Talents.T_RUSHING_CLAWS] = resolvers.mbonus_material(4, 1)}, }, } @@ -92,6 +93,7 @@ newEntity{ cost = 5, wielder = { + talent_cd_reduction={[Talents.T_LAY_WEB]=1}, learn_talent = {[Talents.T_LAY_WEB] = resolvers.mbonus_material(4, 1)}, }, } @@ -105,7 +107,7 @@ newEntity{ cost = 15, wielder = { - talent_cd_reduction={[Talents.T_INVOKE_TENTACLE]=-5}, +-- talent_cd_reduction={[Talents.T_INVOKE_TENTACLE]=-5}, learn_talent = {[Talents.T_INVOKE_TENTACLE] = 1}, }, } diff --git a/game/modules/tome/data/general/objects/egos/wands.lua b/game/modules/tome/data/general/objects/egos/wands.lua index 3b8a8c671dea22e4671884727936625608c8d28a..a0f919d7ce526c6f73a4ebaaf82647854c353bb8 100644 --- a/game/modules/tome/data/general/objects/egos/wands.lua +++ b/game/modules/tome/data/general/objects/egos/wands.lua @@ -108,7 +108,7 @@ newEntity{ cost = 5, wielder = { - talent_cd_reduction={[Talents.T_VOID_BLAST]=-6}, +-- talent_cd_reduction={[Talents.T_VOID_BLAST]=-6}, learn_talent = {[Talents.T_VOID_BLAST] = resolvers.mbonus_material(4, 1)}, }, } @@ -122,6 +122,7 @@ newEntity{ cost = 5, wielder = { + talent_cd_reduction={[Talents.T_VOLCANO]=2}, learn_talent = {[Talents.T_VOLCANO] = resolvers.mbonus_material(4, 1)}, }, } @@ -135,6 +136,7 @@ newEntity{ cost = 5, wielder = { + talent_cd_reduction={[Talents.T_STRIKE]=1}, learn_talent = {[Talents.T_STRIKE] = resolvers.mbonus_material(4, 1)}, }, } diff --git a/game/modules/tome/resolvers.lua b/game/modules/tome/resolvers.lua index 0eaa3d85d7ca9314472760ee5760d260f2e27c9c..afbf9c5744d7ddd6518d73c9912adf8f5d91c8a9 100644 --- a/game/modules/tome/resolvers.lua +++ b/game/modules/tome/resolvers.lua @@ -497,7 +497,7 @@ function resolvers.calc.charm(tt, e) local cd = tt[2] e.max_power = cd e.power = e.max_power - e.use_power = {name=tt[1], power=cd, use=tt[3], __no_merge_add=true} + e.use_power = table.merge(e.use_power or {}, {name=tt[1], power=cd, use=tt[3], __no_merge_add=true}) if e.talent_cooldown == nil then e.talent_cooldown = tt[4] or "T_GLOBAL_CD" end if tt[5] then table.merge(e.use_power, tt[5], true) end return