diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index f6cd2e4cf5e171c39d31037eaad8453b5886d620..e56ad76d10bdb35924f6807e5d5524eb1ef2957b 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -1324,8 +1324,8 @@ function _M:move(x, y, force) self.did_energy = nil -- Try to detect traps - if not force and self:knowTalent(self.T_HEIGHTENED_SENSES) then - local power = self:callTalent(self.T_HEIGHTENED_SENSES,"trapPower") + if not force and self:knowTalent(self.T_DEVICE_MASTERY) then + local power = self:callTalent(self.T_DEVICE_MASTERY,"trapPower") 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) @@ -1572,7 +1572,7 @@ end -- param power detection power (optional) -- @return the trap @ x, y if present and detected function _M:detectTrap(trap, x, y, power) - power = power or self:callTalent(self.T_HEIGHTENED_SENSES, "trapPower") + power = power or self:callTalent(self.T_DEVICE_MASTERY, "trapPower") if power <= 0 then return end trap = trap or game.level.map(x, y, Map.TRAP) if trap then diff --git a/game/modules/tome/class/Trap.lua b/game/modules/tome/class/Trap.lua index 0b73ba07b36101fc2da10ddfc1c1d702c9103ce7..a16508dacb8a8b894c3dcd40a065a563e7be0875 100644 --- a/game/modules/tome/class/Trap.lua +++ b/game/modules/tome/class/Trap.lua @@ -164,8 +164,8 @@ function _M:canDisarm(x, y, who) if not engine.Trap.canDisarm(self, x, y, who) then return false end -- do we know how to disarm? - if (who:getTalentLevel(who.T_HEIGHTENED_SENSES) >= 3) or who:attr("can_disarm") then - local th = who:getTalentFromId(who.T_HEIGHTENED_SENSES) + if (who:getTalentLevel(who.T_DEVICE_MASTERY) >= 1) or who:attr("can_disarm") then + local th = who:getTalentFromId(who.T_DEVICE_MASTERY) local power = th.trapPower(who, th) + (who:attr("disarm_bonus") or 0) if who:checkHitOld(power, self.disarm_power) and (not self.faction or who:reactionToward(self) < 0) then return true @@ -193,7 +193,7 @@ function _M:onDisarm(x, y, who) --table.set(game, "debug", "last_trap_disarmed", self) -- debugging -- The player may unlock a trap talent when disarming a (similar) trap (uses Trap Mastery) if self.unlock_talent_on_disarm and who.player and who:knowTalent(who.T_TRAP_MASTERY) and core.fov.distance(x, y, who.x, who.y) <= 1 and not game.state:unlockTalentCheck(self.unlock_talent_on_disarm.tid, who) then - local hit, chance = who:checkHit(who:callTalent(who.T_TRAP_MASTERY, "getPower") + who:callTalent(who.T_HEIGHTENED_SENSES, "trapPower")*.25, self.disarm_power) + local hit, chance = who:checkHit(who:callTalent(who.T_TRAP_MASTERY, "getPower") + who:callTalent(who.T_DEVICE_MASTERY, "trapPower")*.25, self.disarm_power) local t = who:getTalentFromId(self.unlock_talent_on_disarm.tid) if t and hit and chance > 20 and (not self.unlock_talent_on_disarm.chance or rng.percent(self.unlock_talent_on_disarm.chance)) and next(who:spotHostiles()) == nil then local diff_level = (t.trap_mastery_level or 5) diff --git a/game/modules/tome/class/interface/Combat.lua b/game/modules/tome/class/interface/Combat.lua index bb6d952fe2c3674bfcf1e43061e04047556484db..2d996679c59d00faebe5c174273724edad413c26 100644 --- a/game/modules/tome/class/interface/Combat.lua +++ b/game/modules/tome/class/interface/Combat.lua @@ -1173,6 +1173,9 @@ function _M:combatDefenseBase(fake) if self:hasDualWeapon() and self:knowTalent(self.T_DUAL_WEAPON_DEFENSE) then add = add + self:callTalent(self.T_DUAL_WEAPON_DEFENSE,"getDefense") end + if self:hasLightArmor() and self:knowTalent(self.T_LIGHT_ARMOUR_TRAINING) then + add = add + self:callTalent(self.T_LIGHT_ARMOUR_TRAINING,"getDefense") + end if not fake then add = add + (self:checkOnDefenseCall("defense") or 0) end @@ -1198,6 +1201,11 @@ function _M:combatDefenseBase(fake) if self:hasLightArmor() and self:knowTalent(self.T_MOBILE_DEFENCE) then mult = mult + self:callTalent(self.T_MOBILE_DEFENCE,"getDef") end + + if self:hasLightArmor() and self:hasEffect(self.EFF_MOBILE_DEFENCE) then + local eff = self:hasEffect(self.EFF_MOBILE_DEFENCE) + mult = mult + (eff.power/100) + end return math.max(0, d * mult + add) -- Add bonuses last to avoid compounding defense multipliers from talents end @@ -1261,6 +1269,9 @@ function _M:combatArmorHardiness() if self:hasLightArmor() and self:knowTalent(self.T_MOBILE_DEFENCE) then add = add + self:callTalent(self.T_MOBILE_DEFENCE, "getHardiness") end + if self:hasLightArmor() and self:knowTalent(self.T_LIGHT_ARMOUR_TRAINING) then + add = add + self:callTalent(self.T_LIGHT_ARMOUR_TRAINING, "getArmorHardiness") + end if self:knowTalent(self.T_ARMOUR_OF_SHADOWS) and not game.level.map.lites(self.x, self.y) then add = add + 50 end @@ -1719,10 +1730,13 @@ end function _M:getOffHandMult(combat, mult) if combat and combat.range and not combat.dam then return mult or 1 end --no penalty for ranged shooters local offmult = 1/2 - -- Take the bigger multiplier from Dual weapon training and Corrupted Strength + -- Take the bigger multiplier from Dual weapon training, Dual Weapon Mastery and Corrupted Strength if self:knowTalent(Talents.T_DUAL_WEAPON_TRAINING) then offmult = math.max(offmult,self:callTalent(Talents.T_DUAL_WEAPON_TRAINING,"getoffmult")) end + if self:knowTalent(Talents.T_DUAL_WEAPON_MASTERY) then + offmult = math.max(offmult,self:callTalent(Talents.T_DUAL_WEAPON_MASTERY,"getoffmult")) + end if self:knowTalent(Talents.T_CORRUPTED_STRENGTH) then offmult = math.max(offmult,self:callTalent(Talents.T_CORRUPTED_STRENGTH,"getoffmult")) end diff --git a/game/modules/tome/data/birth/classes/rogue.lua b/game/modules/tome/data/birth/classes/rogue.lua index 9937140199f69500ecfb62a011f48bc4b6a5af6e..62b9bc26b27891772ecf17e9247c6f1ca2bcaf8d 100644 --- a/game/modules/tome/data/birth/classes/rogue.lua +++ b/game/modules/tome/data/birth/classes/rogue.lua @@ -55,12 +55,10 @@ newBirthDescriptor{ stats = { dex=3, str=1, cun=5, }, talents_types = { ["technique/dualweapon-attack"]={true, 0.3}, - ["technique/dualweapon-training"]={true, 0.3}, ["technique/duelist"]={true, 0.3}, ["technique/combat-techniques-active"]={false, 0.3}, ["technique/combat-training"]={true, 0.3}, - ["technique/field-control"]={false, 0}, - ["technique/acrobatics"]={true, 0.3}, + ["technique/mobility"]={true, 0.3}, ["technique/throwing-knives"]={true, 0.3}, ["technique/assassination"]={false, 0.3}, ["cunning/stealth"]={true, 0.3}, @@ -77,7 +75,7 @@ newBirthDescriptor{ talents = { [ActorTalents.T_SHOOT] = 1, [ActorTalents.T_STEALTH] = 1, - [ActorTalents.T_PARRY] = 1, + [ActorTalents.T_DUAL_WEAPON_MASTERY] = 1, [ActorTalents.T_LETHALITY] = 1, [ActorTalents.T_DUAL_STRIKE] = 1, [ActorTalents.T_KNIFE_MASTERY] = 1, @@ -119,7 +117,7 @@ newBirthDescriptor{ ["spell/divination"]={false, 0}, ["spell/conveyance"]={true, 0}, ["technique/dualweapon-attack"]={true, 0.2}, - ["technique/dualweapon-training"]={true, 0.2}, + ["technique/duelist"]={true, 0.2}, ["technique/combat-techniques-active"]={true, 0.3}, ["technique/combat-techniques-passive"]={false, 0.3}, ["technique/combat-training"]={true, 0.2}, @@ -165,12 +163,10 @@ newBirthDescriptor{ stats = { dex=4, str=4, cun=1, }, talents_types = { ["technique/dualweapon-attack"]={true, 0.2}, - ["technique/dualweapon-training"]={true, 0.2}, - ["technique/duelist"]={false, 0.2}, + ["technique/duelist"]={true, 0.2}, ["technique/combat-techniques-active"]={true, 0.3}, ["technique/combat-techniques-passive"]={true, 0.0}, ["technique/combat-training"]={true, 0.3}, - ["technique/field-control"]={true, 0.3}, ["technique/battle-tactics"]={false, 0.2}, ["technique/mobility"]={true, 0.3}, ["technique/thuggery"]={true, 0.3}, @@ -225,10 +221,9 @@ newBirthDescriptor{ ["cunning/called-shots"]={true, 0.3}, ["technique/tireless-combatant"]={true, 0.3}, ["cunning/trapping"]={false, 0.1}, - ["technique/mobility"]={true, 0.3}, -- generic - ["technique/acrobatics"]={true, 0.3}, + ["technique/mobility"]={true, 0.3}, ["cunning/survival"]={true, 0.3}, ["technique/combat-training"]={true, 0.3}, ["technique/field-control"]={false, 0.1}, diff --git a/game/modules/tome/data/birth/classes/warrior.lua b/game/modules/tome/data/birth/classes/warrior.lua index ac9253f8b30e3a79187b4182d994f248e9603936..31239bc6ec9bbeb4ed75cc799d406d0beb549f61 100644 --- a/game/modules/tome/data/birth/classes/warrior.lua +++ b/game/modules/tome/data/birth/classes/warrior.lua @@ -67,7 +67,6 @@ newBirthDescriptor{ ["technique/conditioning"]={true, 0.3}, ["technique/superiority"]={false, 0.3}, ["technique/warcries"]={false, 0.3}, - ["technique/field-control"]={false, 0}, ["technique/bloodthirst"]={false, 0.2}, ["cunning/survival"]={true, 0}, ["cunning/dirty"]={false, 0}, @@ -115,7 +114,6 @@ newBirthDescriptor{ ["technique/superiority"]={false, 0.3}, ["technique/warcries"]={false, 0.3}, ["technique/battle-tactics"]={false, 0.3}, - ["technique/field-control"]={false, 0}, ["cunning/survival"]={true, 0}, ["cunning/dirty"]={false, 0}, }, @@ -162,7 +160,7 @@ newBirthDescriptor{ ["technique/combat-techniques-active"]={false, -0.1}, ["technique/combat-techniques-passive"]={true, -0.1}, ["technique/combat-training"]={true, 0.3}, - ["technique/field-control"]={true, 0}, + ["technique/mobility"]={true, 0}, ["cunning/trapping"]={false, 0.2}, ["cunning/survival"]={true, 0}, ["cunning/dirty"]={false, 0}, @@ -288,9 +286,8 @@ newBirthDescriptor{ talents_types = { ["cunning/dirty"]={false, 0}, ["cunning/tactical"]={true, 0.3}, - ["cunning/survival"]={false, 0}, + ["cunning/survival"]={true, 0}, ["technique/combat-training"]={true, 0.1}, - ["technique/field-control"]={true, 0}, ["technique/combat-techniques-active"]={true, 0.1}, ["technique/combat-techniques-passive"]={true, 0.1}, ["technique/pugilism"]={true, 0.3}, diff --git a/game/modules/tome/data/chats/escort-quest.lua b/game/modules/tome/data/chats/escort-quest.lua index c53c87f6619f8e148c8a815cf5e34fd304513d14..58bb33975f3a0afe52949925764a45b19a09f65a 100644 --- a/game/modules/tome/data/chats/escort-quest.lua +++ b/game/modules/tome/data/chats/escort-quest.lua @@ -98,8 +98,8 @@ local reward_types = { }, talents = { [Talents.T_HEIGHTENED_SENSES] = 1, - [Talents.T_CHARM_MASTERY] = 1, - [Talents.T_PIERCING_SIGHT] = 1, + [Talents.T_DEVICE_MASTERY] = 1, + [Talents.T_TRACK] = 1, }, stats = { [Stats.STAT_DEX] = 2, @@ -123,8 +123,8 @@ local reward_types = { ["technique/mobility"] = 0.8, }, talents = { - [Talents.T_HACK_N_BACK] = 1, - [Talents.T_LIGHT_OF_FOOT] = 1, + [Talents.T_DISENGAGE] = 1, + [Talents.T_EVASION] = 1, }, saves = { spell = 4, phys = 4 }, stats = { @@ -147,11 +147,11 @@ local reward_types = { }, antimagic = { types = { - ["technique/field-control"] = 0.8, + ["technique/feedback"] = 0.8, }, talents = { - [Talents.T_TRACK] = 1, - [Talents.T_HEAVE] = 1, + [Talents.T_BIOFEEDBACK] = 1, + [Talents.T_CONVERSION] = 1, }, saves = { spell = 4, mental = 4 }, stats = { diff --git a/game/modules/tome/data/general/npcs/skeleton.lua b/game/modules/tome/data/general/npcs/skeleton.lua index 55c8b5b49d6b75d45e304f6415ee03a92d254210..707cd8f47aaa99270ff2032282ae31e66648fc0c 100644 --- a/game/modules/tome/data/general/npcs/skeleton.lua +++ b/game/modules/tome/data/general/npcs/skeleton.lua @@ -205,7 +205,7 @@ newEntity{ base = "BASE_NPC_SKELETON", resolvers.inscriptions(1, "rune"), resolvers.talents{ - [Talents.T_PARRY]={base=1, every=10, max=7}, + [Talents.T_DUAL_WEAPON_MASTERY]={base=1, every=10, max=7}, [Talents.T_TEMPO]={base=1, every=10, max=7}, [Talents.T_FLURRY]={base=1, every=10, max=7}, [Talents.T_DIRTY_FIGHTING]={base=1, every=10, max=7}, diff --git a/game/modules/tome/data/general/npcs/thieve.lua b/game/modules/tome/data/general/npcs/thieve.lua index c2ae15b8e67bf755bf1ca17194126c34f1ef4890..b734542b478aa96a4076e09b51afbcd753ceb696 100644 --- a/game/modules/tome/data/general/npcs/thieve.lua +++ b/game/modules/tome/data/general/npcs/thieve.lua @@ -145,7 +145,7 @@ newEntity{ base = "BASE_NPC_THIEF", define_as = "THIEF_ASSASSIN", resolvers.talents{ [Talents.T_STEALTH]={base=3, every=6, max=7}, [Talents.T_EXPOSE_WEAKNESS]={base=3, every=6, max=7}, - [Talents.T_PARRY]={base=2, every=6, max=6}, + [Talents.T_DUAL_WEAPON_MASTERY]={base=2, every=6, max=6}, [Talents.T_TEMPO]={base=2, every=6, max=6}, [Talents.T_DUAL_STRIKE]={base=1, every=6, max=6}, [Talents.T_COUP_DE_GRACE]={base=1, every=6, max=6}, @@ -167,7 +167,7 @@ newEntity{ base = "BASE_NPC_THIEF", define_as = "THIEF_ASSASSIN", combat_armor = 3, combat_def = 10, resolvers.talents{ [Talents.T_STEALTH]={base=3, every=5, max=8}, - [Talents.T_PARRY]={base=2, every=6, max=6}, + [Talents.T_DUAL_WEAPON_MASTERY]={base=2, every=6, max=6}, [Talents.T_TEMPO]={base=2, every=6, max=6}, [Talents.T_DUAL_STRIKE]={base=1, every=6, max=6}, [Talents.T_SHADOWSTRIKE]={base=2, every=6, max=6}, @@ -204,7 +204,7 @@ newEntity{ base = "BASE_NPC_THIEF", define_as = "THIEF_SAPPER", [Talents.T_TRAP_MASTERY]={base=3, every=6, max=7}, [Talents.T_TRAP_LAUNCHER]={base=1, every=8, max=5}, [Talents.T_TRAP_PRIMING]={base=-1, every=8, max=5}, - [Talents.T_PARRY]={base=1, every=8, max=5}, + [Talents.T_DUAL_WEAPON_MASTERY]={base=1, every=8, max=5}, [Talents.T_TEMPO]={base=1, every=8, max=5}, [Talents.T_DUAL_STRIKE]={base=1, every=6, max=6}, [Talents.T_DISARM]={base=1, every=6, max=6}, diff --git a/game/modules/tome/data/gfx/talents/danger_sense.png b/game/modules/tome/data/gfx/talents/danger_sense.png new file mode 100644 index 0000000000000000000000000000000000000000..a11e3ce5395355f6f1b7e1815e17129d386e5990 Binary files /dev/null and b/game/modules/tome/data/gfx/talents/danger_sense.png differ diff --git a/game/modules/tome/data/gfx/talents/device_mastery.png b/game/modules/tome/data/gfx/talents/device_mastery.png new file mode 100644 index 0000000000000000000000000000000000000000..11d580f17759704383d5c93d931afdd4873a5c20 Binary files /dev/null and b/game/modules/tome/data/gfx/talents/device_mastery.png differ diff --git a/game/modules/tome/data/gfx/talents/disengage.png b/game/modules/tome/data/gfx/talents/disengage.png index aad8af98ebd6fa65a42341e059cfa02d505cf076..e78d2f3cf111e62a1534148d83ca634a99371e57 100644 Binary files a/game/modules/tome/data/gfx/talents/disengage.png and b/game/modules/tome/data/gfx/talents/disengage.png differ diff --git a/game/modules/tome/data/gfx/talents/parry.png b/game/modules/tome/data/gfx/talents/dual_weapon_mastery.png similarity index 100% rename from game/modules/tome/data/gfx/talents/parry.png rename to game/modules/tome/data/gfx/talents/dual_weapon_mastery.png diff --git a/game/modules/tome/data/gfx/talents/evasion.png b/game/modules/tome/data/gfx/talents/evasion.png index 7eb5e78002e8d5e32599b3f5427a7406dc6ab293..1b3c6cae47c248e90e7d1934f6c0e8aa479c75a4 100644 Binary files a/game/modules/tome/data/gfx/talents/evasion.png and b/game/modules/tome/data/gfx/talents/evasion.png differ diff --git a/game/modules/tome/data/gfx/talents/light_armour_training.png b/game/modules/tome/data/gfx/talents/light_armour_training.png new file mode 100644 index 0000000000000000000000000000000000000000..385f270aeb40bdc96be5617df29ef40004dec90d Binary files /dev/null and b/game/modules/tome/data/gfx/talents/light_armour_training.png differ diff --git a/game/modules/tome/data/gfx/talents/track.png b/game/modules/tome/data/gfx/talents/track.png index 6f0351a17bf4aa1e36b2cf040d74052ec897fe8d..78b1ae58807f9c43e4ed9daae278f1e57dbd260d 100644 Binary files a/game/modules/tome/data/gfx/talents/track.png and b/game/modules/tome/data/gfx/talents/track.png differ diff --git a/game/modules/tome/data/gfx/talents/trained_reactions.png b/game/modules/tome/data/gfx/talents/trained_reactions.png new file mode 100644 index 0000000000000000000000000000000000000000..3932fe977a5244c45cb0ffa65311379292fa2038 Binary files /dev/null and b/game/modules/tome/data/gfx/talents/trained_reactions.png differ diff --git a/game/modules/tome/data/gfx/talents/tumble.png b/game/modules/tome/data/gfx/talents/tumble.png new file mode 100644 index 0000000000000000000000000000000000000000..f8cd3bdc06794e0dbc0690fe462d394d7a8aecd1 Binary files /dev/null and b/game/modules/tome/data/gfx/talents/tumble.png differ diff --git a/game/modules/tome/data/talents/cunning/lethality.lua b/game/modules/tome/data/talents/cunning/lethality.lua index 8d0a2e82c516d3323214c6db497d7fff9e1c6108..60f6081595ece9210f494ea15bf8a28647d8f1dd 100644 --- a/game/modules/tome/data/talents/cunning/lethality.lua +++ b/game/modules/tome/data/talents/cunning/lethality.lua @@ -23,12 +23,18 @@ newTalent{ mode = "passive", points = 5, require = cuns_req1, + critpower = function(self, t) return self:combatTalentScale(t, 7.5, 20, 0.75) end, + -- called by _M:combatCrit in mod.class.interface.Combat.lua getCriticalChance = function(self, t) return self:combatTalentScale(t, 2.3, 7.5, 0.75) end, + passives = function(self, t, p) + self:talentTemporaryValue(p, "combat_critical_power", t.critpower(self, t)) + end, info = function(self, t) local critchance = t.getCriticalChance(self, t) - return ([[You are trained to strike critical areas when fighting, and have a %d%% increased critical strike chance. - Also, when using knives, you use your Cunning instead of your Strength for bonus damage.]]): - format(critchance) + local power = t.critpower(self, t) + return ([[You have learned to find and hit weak spots. All your strikes have a %0.2f%% greater chance to be critical hits, and your critical hits do %0.1f%% more damage. + Also, when using knives, you now use your Cunning instead of your Strength for bonus damage.]]): + format(critchance, power) end, } @@ -118,7 +124,7 @@ newTalent{ end, info = function(self, t) return ([[Become a whirling storm of blades, increasing attack speed by %d%% and causing melee attacks to strike an additional adjacent target other than your primary target for %d%% weapon damage. -This talent is exhausting to use, draining -6 stamina each turn.]]):format(t.getSpeed(self, t)*100, t.getDamage(self,t)*100) +This talent is exhausting to use, draining 6 stamina each turn.]]):format(t.getSpeed(self, t)*100, t.getDamage(self,t)*100) end, } diff --git a/game/modules/tome/data/talents/cunning/stealth.lua b/game/modules/tome/data/talents/cunning/stealth.lua index 1b8c704311725d6af0f3bae65362cd3f68c7d113..ae3fe4af873894a764ceb116434cdb75580b5f7b 100644 --- a/game/modules/tome/data/talents/cunning/stealth.lua +++ b/game/modules/tome/data/talents/cunning/stealth.lua @@ -152,7 +152,7 @@ newTalent{ info = function(self, t) local multiplier = t.getMultiplier(self, t) return ([[When striking from stealth, the attack is automatically critical if the target does not notice you just before you land it. Spell and mind crits always critically strike, regardless of whether the target can see you. -In addition, the surprise caused by your assault increases your critical multiplier by %d%%. This effect persists for 3 turns after exiting stealth, or 4 turns at talent level 3 and above.]]): +In addition, the surprise caused by your assault increases your critical multiplier by %d%%. This effect persists for 2 turns after exiting stealth, or 3 turns at talent level 3 and above.]]): format(multiplier) end, } @@ -163,15 +163,15 @@ newTalent{ require = cuns_req3, points = 5, mode = "passive", - getLife = function(self, t) return self:combatTalentScale(t, 1, 3) end, - getStamina = function(self, t) return self:combatTalentScale(t, 0.5, 2) end, - getReduction = function(self, t) return self:combatTalentStatDamage(t, "cun", 5, 25) end, + getLife = function(self, t) return self:combatTalentScale(t, 2, 10) end, --12 @TL5, mostly useful for out of combat as this won't do much in a fight + getStamina = function(self, t) return self:combatTalentScale(t, 1, 2.5) end, --2.9 @TL5 + getReduction = function(self, t) return self:combatTalentStatDamage(t, "cun", 10, 35) end, --29 @100 Cun, effectively about 40% weaker than Automated Cloak Tesselation with less uptime getDuration = function(self,t) if self:getTalentLevel(t) >= 3 then return 3 else return 2 end end, info = function(self, t) return ([[You have a special affinity for darkness. When standing in an unlit grid, enemies observing you will not prevent you from entering stealth. - While stealted, and for %d turns thereafter, all damage against you is reduced by %d, your life regeneration is increased by %0.1f, and your stamina regeneration is increased %0.1f]]): - format(t.getDuration(self, t), t.getReduction(self,t), t.getLife(self,t), t.getStamina(self,t)) + While stealthed, all damage against you is reduced by %d, your life regeneration is increased by %0.1f, and your stamina regeneration is increased %0.1f. This effect persists for 2 turns after exiting stealth, or 3 turns at talent level 3 and above.]]): + format(t.getReduction(self,t), t.getLife(self,t), t.getStamina(self,t)) end, } diff --git a/game/modules/tome/data/talents/cunning/survival.lua b/game/modules/tome/data/talents/cunning/survival.lua index 9db5e8c9cc62b397e080df0ca31c13762c5f2984..0d9ccf049cbdd5d164af7c5f5bac162db9d0919c 100644 --- a/game/modules/tome/data/talents/cunning/survival.lua +++ b/game/modules/tome/data/talents/cunning/survival.lua @@ -24,27 +24,108 @@ newTalent{ mode = "passive", points = 5, sense = function(self, t) return math.floor(self:combatTalentScale(t, 5, 9)) end, - trapPower = function(self, t) return self:combatScale(self:getTalentLevel(t) * self:getCun(25, true), 0, 0, 90, 125) end, -- ~90 at TL5, 100 cunning + seePower = function(self, t) return self:combatScale(self:getCun(15, true)*self:getTalentLevel(t), 5, 0, 80, 75) end, --I5 + getResists = function(self, t) return self:combatTalentLimit(t, 40, 5, 25) end, passives = function(self, t, p) self:talentTemporaryValue(p, "heightened_senses", t.sense(self, t)) + self:talentTemporaryValue(p, "see_invisible", t.seePower(self, t)) + self:talentTemporaryValue(p, "see_stealth", t.seePower(self, t)) + if self:getTalentLevel(t) >= 3 then + self:talentTemporaryValue(p, "resist_unseen", t.getResists(self, t)) + end + end, + info = function(self, t) + return ([[You notice the small things others do not notice, allowing you to "see" creatures in a %d radius even outside of light radius. + This is not telepathy, however, and it is still limited to line of sight. + Also, your attention to detail increases stealth detection and invisibility detection by %d. + At level 3, you are able to react quickly to stealthed and invisible enemies attacking you, reducing the damage they deal by %d%%. + The detection power improves with your Cunning.]]): + format(t.sense(self,t), t.seePower(self,t), t.getResists(self,t)) + end, +} + +newTalent{ + name = "Track", + type = {"cunning/survival", 2}, + require = cuns_req2, + points = 5, + random_ego = "utility", + cooldown = 20, + radius = function(self, t) return math.floor(self:combatScale(self:getCun(10, true) * self:getTalentLevel(t), 5, 0, 55, 50)) end, + no_npc_use = true, + action = function(self, t) + local rad = self:getTalentRadius(t) + self:setEffect(self.EFF_SENSE, 3 + self:getTalentLevel(t), { + range = rad, + actor = 1, + }) + return true + end, + info = function(self, t) + local rad = self:getTalentRadius(t) + return ([[Sense foes around you in a radius of %d for %d turns. + The radius will increase with your Cunning.]]):format(rad, 3 + self:getTalentLevel(t)) + end, +} + +newTalent{ + name = "Device Mastery", + type = {"cunning/survival", 3}, + require = cuns_req3, + mode = "passive", + points = 5, + cdReduc = function(tl) + if tl <=0 then return 0 end + return math.floor(100*tl/(tl+7.5)) -- Limit < 100% + end, + passives = function(self, t, p) + self:talentTemporaryValue(p, "use_object_cooldown_reduce", t.cdReduc(self:getTalentLevel(t))) end, on_learn = function(self, t) - if self:getTalentLevel(t) >= 3 and not self:knowTalent(self.T_DISARM_TRAP) then + if not self:knowTalent(self.T_DISARM_TRAP) then self:learnTalent(self.T_DISARM_TRAP, true, 1) end end, on_unlearn = function(self, t) - if self:getTalentLevel(t) < 3 and self:knowTalent(self.T_DISARM_TRAP) then + if self:getTalentLevel(t) < 1 and self:knowTalent(self.T_DISARM_TRAP) then self:unlearnTalent(self.T_DISARM_TRAP, 1) end end, + trapPower = function(self, t) return self:combatScale(self:getTalentLevel(t) * self:getCun(25, true), 0, 0, 125, 125) end, info = function(self, t) - return ([[You notice the small things others do not notice, allowing you to "see" creatures in a %d radius even outside of light radius. - This is not telepathy, however, and it is still limited to line of sight. - Also, your attention to detail allows you to detect traps around you (%d detection 'power'). - At level 3, you learn to disarm known traps (%d disarm 'power'). - The trap detection and disarming ability improves with your Cunning.]]): - format(t.sense(self,t),t.trapPower(self,t),t.trapPower(self,t)) + return ([[Your cunning manipulations allow you to use charms (wands, totems and torques) more efficiently, reducing their cooldowns and the power cost of all usable items by %d%%. +In addition, your knowledge of devices allows you to detect traps around you and disarm known traps (%d detection and disarm 'power'). +The trap detection and disarming ability improves with your Cunning. ]]): + format(t.cdReduc(self:getTalentLevel(t)), t.trapPower(self,t)) --I5 + end, +} + +newTalent{ + name = "Danger Sense", + type = {"cunning/survival", 4}, + require = cuns_req4, + points = 5, + mode = "passive", + getTrigger = function(self, t) return self:combatTalentScale(t, 0.15, 0.40, 0.5) end, + cooldown = function(self, t) return 30 end, + no_npc_use = true, + getReduction = function(self, t) + return self:combatTalentLimit(t, 75, 25, 65) + end, + callbackOnHit = function(self, t, cb, src) + if self.life > self.max_life*t.getTrigger(self,t) and self.life - cb.value <= self.max_life*t.getTrigger(self,t) and not self:isTalentCoolingDown(t) then + self:setEffect("EFF_DANGER_SENSE", 1, {reduce = t.getReduction(self, t)}) + local eff = self:hasEffect("EFF_DANGER_SENSE") + eff.dur = eff.dur - 1 + cb.value = cb.value * (100-t.getReduction(self, t)) / 100 + self:startTalentCooldown(t) + end + return cb.value + end, + info = function(self, t) + return ([[You react quickly when in danger - on falling below %d%% life, all damage you take from the attack and all further damage that turn is reduced by %d%%. +This talent has a cooldown.]]): + format(t.getTrigger(self,t)*100, t.getReduction(self,t) ) end, } @@ -88,77 +169,10 @@ newTalent{ return true end, info = function(self, t) - local ths = self:getTalentFromId(self.T_HEIGHTENED_SENSES) + local ths = self:getTalentFromId(self.T_DEVICE_MASTERY) local power = ths.trapPower(self,ths) return ([[You search an adjacent grid for a hidden trap (%d detection 'power') and attempt to disarm it (%d disarm 'power'). To disarm a trap, you must be able to enter its grid to manipulate it, even though you stay in your current location. Success depends on your skill in the %s talent and your Cunning, and failing to disarm a trap may trigger it.]]):format(power, power + (self:attr("disarm_bonus") or 0), ths.name) end, -} - -newTalent{ - name = "Charm Mastery", - type = {"cunning/survival", 2}, - require = cuns_req2, - mode = "passive", - points = 5, - cdReduc = function(tl) - if tl <=0 then return 0 end - return math.floor(100*tl/(tl+7.5)) -- Limit < 100% - end, - passives = function(self, t, p) - self:talentTemporaryValue(p, "use_object_cooldown_reduce", t.cdReduc(self:getTalentLevel(t))) - end, --- on_unlearn = function(self, t) --- end, - info = function(self, t) - return ([[Your cunning manipulations allow you to use charms (wands, totems and torques) more efficiently, reducing their cooldowns by %d%%.]]): - format(t.cdReduc(self:getTalentLevel(t))) - end, -} - -newTalent{ - name = "Piercing Sight", - type = {"cunning/survival", 3}, - require = cuns_req3, - mode = "passive", - points = 5, - -- called by functions _M:combatSeeStealth and _M:combatSeeInvisible functions mod\class\interface\Combat.lua - seePower = function(self, t) return self:combatScale(self:getCun(15, true)*self:getTalentLevel(t), 5, 0, 80, 75) end, --I5 - info = function(self, t) - return ([[You look at your surroundings with more intensity than most people, allowing you to see stealthed or invisible creatures. - Increases stealth detection by %d and invisibility detection by %d. - The detection power increases with your Cunning.]]): - format(t.seePower(self,t), t.seePower(self,t)) - end, -} - -newTalent{ - name = "Evasion", - type = {"cunning/survival", 4}, - points = 5, - require = cuns_req4, - random_ego = "defensive", - tactical = { ESCAPE = 2, DEFEND = 2 }, - cooldown = 30, - getDur = function(self) return math.floor(self:combatStatLimit("wil", 30, 6, 15)) end, -- Limit < 30 - getChanceDef = function(self, t) - if self.perfect_evasion then return 100, 0 end - return self:combatLimit(5*self:getTalentLevel(t) + self:getCun(25,true) + self:getDex(25,true), 50, 10, 10, 37.5, 75), - self:combatScale(self:getTalentLevel(t) * (self:getCun(25, true) + self:getDex(25, true)), 0, 0, 55, 250, 0.75) - -- Limit evasion chance < 50%, defense bonus ~= 55 at level 50 - end, - speed = "combat", - action = function(self, t) - local dur = t.getDur(self) - local chance, def = t.getChanceDef(self,t) - self:setEffect(self.EFF_EVASION, dur, {chance=chance, defense = def}) - return true - end, - info = function(self, t) - local chance, def = t.getChanceDef(self,t) - return ([[Your quick wit allows you to see attacks before they land, granting you a %d%% chance to completely evade them and granting you %d defense for %d turns. - Duration increases with Willpower, and chance to evade and defense with Cunning and Dexterity.]]): - format(chance, def,t.getDur(self)) - end, -} +} \ No newline at end of file diff --git a/game/modules/tome/data/talents/misc/npcs.lua b/game/modules/tome/data/talents/misc/npcs.lua index 91bfd6b38787bce9896ea8e6b3daf3fa70db57a0..7e9a476bf003d57460bed75877f4252fe44460a5 100644 --- a/game/modules/tome/data/talents/misc/npcs.lua +++ b/game/modules/tome/data/talents/misc/npcs.lua @@ -3117,4 +3117,136 @@ newTalent{ You estimate your current chance to maintain stealth as %0.1f%%.]]): format(t.stealthMult(self, t), t.getChance(self, t, true), t.getChance(self, t, false, true)) end, +} + +newTalent{ + name = "Hack'n'Back", + type = {"other/other", 1}, + points = 5, + cooldown = 14, + stamina = 30, + tactical = { ESCAPE = 1, ATTACK = { weapon = 0.5 } }, +-- require = techs_dex_req1, + requires_target = true, + is_melee = true, + target = function(self, t) return {type="hit", range=self:getTalentRange(t)} end, + range = 1, + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.4, 1) end, + getDist = function(self, t) return math.ceil(self:combatTalentScale(t, 1.2, 3.3)) end, + on_pre_use = function(self, t) + if self:attr("never_move") then return false end + return true + end, + action = function(self, t) + local tg = self:getTalentTarget(t) + local x, y, target = self:getTarget(tg) + if not target or not self:canProject(tg, x, y) then return nil end + local hitted = self:attackTarget(target, nil, t.getDamage(self, t), true) + + if hitted then + self:knockback(target.x, target.y, t.getDist(self, t)) + end + + return true + end, + info = function(self, t) + local damage = t.getDamage(self, t) + local dist = t.getDist(self, t) + return ([[You hit your target, doing %d%% damage, distracting it while you jump back %d squares away.]]): + format(100 * damage, dist) + end, +} + +newTalent{ + name = "Mobile Defence", + type = {"other/other", 1}, + mode = "passive", + points = 5, +-- require = techs_dex_req2, + getDef = function(self, t) return self:getTalentLevel(t) * 0.08 end, + getHardiness = function(self, t) return self:getTalentLevel(t) * 0.06 end, + -- called by _M:combatDefenseBase function in mod\class\interface\Combat.lua + getDef = function(self, t) return self:combatTalentLimit(t, 1, 0.10, 0.40) end, -- Limit to <100% defense bonus + -- called by _M:combatArmorHardiness function in mod\class\interface\Combat.lua + getHardiness = function(self, t) return self:combatTalentLimit(t, 100, 6, 30) end, -- Limit < 100% + info = function(self, t) + return ([[Whilst wearing leather or lighter armour, you gain %d%% Defense and %d%% Armour hardiness.]]): + format(t.getDef(self, t) * 100, t.getHardiness(self, t)) + end, +} + +newTalent{ + name = "Light of Foot", + type = {"other/other", 1}, + mode = "passive", + points = 5, +-- require = techs_dex_req3, + getFatigue = function(self, t) return self:combatTalentLimit(t, 100, 1.5, 7.5) end, -- Limit < 50% + passives = function(self, t, p) + self:talentTemporaryValue(p, "fatigue", -t.getFatigue(self, t)) + end, + info = function(self, t) + return ([[You are light on your feet, handling your armour better. Each step you take regenerates %0.2f stamina, and your fatigue is permanently reduced by %0.1f%%. + At level 3 you are able to walk so lightly that you never trigger traps that require pressure.]]): + format(self:getTalentLevelRaw(t) * 0.2, t.getFatigue(self, t)) + end, + +} + +newTalent{ + name = "Strider", + type = {"other/other", 1}, + mode = "passive", + points = 5, +-- require = techs_dex_req4, + incspeed = function(self, t) return self:combatTalentScale(t, 0.02, 0.10, 0.75) end, + CDreduce = function(self, t) return math.floor(self:combatTalentLimit(t, 8, 1, 5)) end, -- Limit < 8 + passives = function(self, t, p) + local cdr = t.CDreduce(self, t) + self:talentTemporaryValue(p, "movement_speed", t.incspeed(self, t)) + self:talentTemporaryValue(p, "talent_cd_reduction", + {[Talents.T_RUSH]=cdr, [Talents.T_HACK_N_BACK]=cdr, [Talents.T_DISENGAGE]=cdr, [Talents.T_EVASION]=cdr}) + end, + info = function(self, t) + return ([[You literally dance around your foes, increasing your movement speed by %d%% and reducing the cooldown of Hack'n'Back, Rush, Disengage and Evasion by %d turns.]]): + format(t.incspeed(self, t)*100,t.CDreduce(self, t)) + end, +} + + +newTalent{ + name = "Charm Mastery", + type = {"other/other", 1}, +-- require = cuns_req2, + mode = "passive", + points = 5, + cdReduc = function(tl) + if tl <=0 then return 0 end + return math.floor(100*tl/(tl+7.5)) -- Limit < 100% + end, + passives = function(self, t, p) + self:talentTemporaryValue(p, "use_object_cooldown_reduce", t.cdReduc(self:getTalentLevel(t))) + end, +-- on_unlearn = function(self, t) +-- end, + info = function(self, t) + return ([[Your cunning manipulations allow you to use charms (wands, totems and torques) more efficiently, reducing their cooldowns by %d%%.]]): + format(t.cdReduc(self:getTalentLevel(t))) + end, +} + +newTalent{ + name = "Piercing Sight", + type = {"other/other", 1}, +-- require = cuns_req3, + mode = "passive", + points = 5, + -- called by functions _M:combatSeeStealth and _M:combatSeeInvisible functions mod\class\interface\Combat.lua + seePower = function(self, t) return self:combatScale(self:getCun(15, true)*self:getTalentLevel(t), 5, 0, 80, 75) end, --I5 + info = function(self, t) + return ([[You look at your surroundings with more intensity than most people, allowing you to see stealthed or invisible creatures. + Increases stealth detection by %d and invisibility detection by %d. + The detection power increases with your Cunning.]]): + format(t.seePower(self,t), t.seePower(self,t)) + end, } \ No newline at end of file diff --git a/game/modules/tome/data/talents/techniques/assassination.lua b/game/modules/tome/data/talents/techniques/assassination.lua index eb8ba2af484b94efb845eb6269324d1d8a8561fa..ee5ac70ae616b2425f3b54e355099173ce24f779 100644 --- a/game/modules/tome/data/talents/techniques/assassination.lua +++ b/game/modules/tome/data/talents/techniques/assassination.lua @@ -66,9 +66,10 @@ newTalent{ end end - if target.dead and self:knowTalent(self.T_STEALTH) and not self:isTalentActive(self.T_STEALTH) and not self:isTalentCoolingDown(self.T_STEALTH) then + if target.dead and self:knowTalent(self.T_STEALTH) and not self:isTalentActive(self.T_STEALTH) then game:onTickEnd(function() self.hide_chance = 1000 + self.talents_cd["T_STEALTH"] = 0 self:forceUseTalent(self.T_STEALTH, {ignore_energy=true, silent = true}) self.hide_chance = nil end) @@ -81,7 +82,7 @@ newTalent{ dam = t.getDamage(self,t)*100 perc = t.getPercent(self,t)*100 return ([[Attempt to finish off a wounded enemy, striking them with both weapons for %d%% weapon damage, plus additional physical damage for each hit that lands equal to %d%% of their missing life (divided by rank: from 1 (critter) to 5 (elite boss)). - A target brought below 20%% of its maximum life may be instantly slain, which you may take advantage of to slip back into stealth if it's not on cooldown.]]): + A target brought below 20%% of its maximum life may be instantly slain, which you may take advantage of to slip back into stealth.]]): format(dam, perc) end, } @@ -105,7 +106,7 @@ newTalent{ info = function(self, t) local radius = self:getTalentRadius(t) local duration = t.getDuration(self,t) - return ([[When you exit stealth, you reveal yourself dramatically, intimitading foes around you. + return ([[When you exit stealth, you reveal yourself dramatically, intimidating foes around you. All enemies that witness you leaving stealth within radius %d will be stricken with terror, which randomly inflicts stun, slow (40%% power), or confusion (50%% power) for %d turns.]]) :format(radius, duration) end, diff --git a/game/modules/tome/data/talents/techniques/combat-training.lua b/game/modules/tome/data/talents/techniques/combat-training.lua index 8c71ed0df2018918bfd2a07b00cc89b5c8a159c1..f320d77568377c20af05a41c7df2d59798d40ba8 100644 --- a/game/modules/tome/data/talents/techniques/combat-training.lua +++ b/game/modules/tome/data/talents/techniques/combat-training.lua @@ -99,11 +99,49 @@ newTalent{ end, } +newTalent{ + name = "Light Armour Training", + type = {"technique/combat-training", 1}, + mode = "passive", + levelup_screen_break_line = true, + no_unlearn_last = true, + points = 5, + require = {stat = {dex = function(level) return 16 + (level + 2) * (level - 1) end}}, + getArmorHardiness = function(self, t) + return math.max(0, self:combatLimit(self:getTalentLevel(t) * 4, 100, 5, 3.75, 50, 37.5)) + end, + getDefense = function(self, t) return self:combatScale(self:getTalentLevel(t) * self:getDex(), 4, 0, 45.7, 500) end, + getPercentageDefense = function(self, t) return self:combatTalentLimit(t, 75, 15, 45) end, + getStamina = function(self, t) return self:combatTalentLimit(t, 5, 1.5, 3.5) end, + callbackOnMove = function(self, t, moved, force, ox, oy) + if not moved or force or (ox == self.x and oy == self.y) then return end + + local nb_foes = 0 + local add_if_visible_enemy = function(x, y) + local target = game.level.map(x, y, game.level.map.ACTOR) + if target and self:reactionToward(target) < 0 and self:canSee(target) then + nb_foes = nb_foes + 1 + end + end + local adjacent_tg = {type = "ball", range = 0, radius = 1, selffire = false} + self:project(adjacent_tg, self.x, self.y, add_if_visible_enemy) + + if nb_foes > 0 then + self:setEffect(self.EFF_MOBILE_DEFENCE, 2, {power=t.getDefense(self,t), stamina=t.getStamina(self,t)}) + end + end, + info = function(self, t) + return ([[Whilst wearing leather or lighter armour, you gain %d Defense and %d%% Armour hardiness. + In addition, stepping into a tile adjacent to a visible enemy will increase your stamina regeneration by %0.1f and total Defense by %d%% for 2 turns. + The Defense bonus scales with your Dexterity.]]): + format(t.getDefense(self,t), t.getArmorHardiness(self,t), t.getStamina(self,t), t.getPercentageDefense(self,t)) + end, +} + newTalent{ name = "Combat Accuracy", short_name = "WEAPON_COMBAT", type = {"technique/combat-training", 1}, points = 5, - levelup_screen_break_line = true, require = { level=function(level) return (level - 1) * 4 end }, mode = "passive", --getAttack = function(self, t) return self:getTalentLevel(t) * 10 end, diff --git a/game/modules/tome/data/talents/techniques/duelist.lua b/game/modules/tome/data/talents/techniques/duelist.lua index 4da20bbefb3585dc4ff0c92b253966070d8d81e5..587b19d2a4e2b2985bff7510b51fce7877269346 100644 --- a/game/modules/tome/data/talents/techniques/duelist.lua +++ b/game/modules/tome/data/talents/techniques/duelist.lua @@ -22,13 +22,13 @@ local Object = require "engine.Object" local Map = require "engine.Map" newTalent{ - name = "Parry", + name = "Dual Weapon Mastery", type = {"technique/duelist", 1}, points = 5, require = techs_dex_req1, mode = "passive", - getDeflectChance = function(self, t) return self:combatTalentLimit(t, 100, 20, 61) end, -- ~67% at TL 6.5 - getDeflectPercent = function(self, t) return self:combatTalentLimit(t, 100, 20, 40) end, + getDeflectChance = function(self, t) return self:combatTalentLimit(t, 100, 20, 65) end, + getDeflectPercent = function(self, t) return self:combatTalentLimit(t, 100, 20, 50) end, getDeflect = function(self, t, fake) local dam,_,weapon = 0,self:hasDualWeapon() if not weapon or weapon.subtype=="mindstar" and not fake then return 0 end @@ -48,6 +48,9 @@ newTalent{ end return t.getDeflectPercent(self, t) * dam/100 end, + getoffmult = function(self,t) + return self:combatTalentLimit(t, 1, 0.65, 0.85)-- limit <100% + end, callbackOnActBase = function(self, t) local mh, oh = self:hasDualWeapon() -- if self:hasDualWeapon() then @@ -60,10 +63,11 @@ newTalent{ block = t.getDeflect(self,t) chance = t.getDeflectChance(self,t) perc = t.getDeflectPercent(self,t) + mult = t.getoffmult(self,t)*100 return ([[Up to %d times a turn, you have a %d%% chance to parry up to %d damage (%d%% of your offhand weapon damage) from a melee or ranged attack. A successful parry reduces damage like armour (before any attack multipliers) and prevents critical strikes. It is difficult to parry attacks from unseen attackers and you cannot parry with a mindstar. - The number of attacks you can parry and their chance partially stacks with those of Dual Weapon Defense.]]): - format(t.getDeflects(self, t, true), chance, block, perc) + In addition, the damage dealt by your offhand weapon is increased to %d%%.]]): + format(t.getDeflects(self, t, true), chance, block, perc, mult) end, } @@ -126,7 +130,7 @@ newTalent{ cooldown = 30, no_energy = true, getChance = function(self, t) return self:combatTalentLimit(t, 25, 5, 15) end, - critResist = function(self, t) return self:combatTalentScale(t, 3, 8, 0.75) end, + critResist = function(self, t) return self:combatTalentScale(t, 15, 50, 0.75) end, on_pre_use = function(self, t, silent, fake) local armor = self:getInven("BODY") and self:getInven("BODY")[1] if armor and (armor.subtype == "heavy" or armor.subtype == "massive") then @@ -168,8 +172,8 @@ newTalent{ range = 1, target = function(self, t) return {type="hit", range=self:getTalentRange(t)} end, getDuration = function(self, t) return math.floor(self:combatTalentLimit(t, 8, 3, 5)) end, - getSpeedPenalty = function(self, t) return self:combatLimit(self:combatTalentStatDamage(t, "dex", 5, 50), 50, 10, 0, 30, 35.7) end, -- Limit < 50% - getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 1.2, 1.5) end, + getSpeedPenalty = function(self, t) return self:combatLimit(self:combatTalentStatDamage(t, "dex", 5, 50), 100, 10, 0, 50, 35.7) end, -- Limit < 100% + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 1.2, 2.5) end, on_pre_use = function(self, t, silent) if self:attr("never_move") then if not silent then game.logPlayer(self, "You must be able to move to use this talent.") end diff --git a/game/modules/tome/data/talents/techniques/field-control.lua b/game/modules/tome/data/talents/techniques/field-control.lua index 535ff39fa4ce1cc722ce4b7ccb50aca3db2c7579..5a073d5416687b2b9dd44aa9ed237116c0f9e851 100644 --- a/game/modules/tome/data/talents/techniques/field-control.lua +++ b/game/modules/tome/data/talents/techniques/field-control.lua @@ -18,64 +18,64 @@ -- darkgod@te4.org -newTalent{ - name = "Disengage", - type = {"technique/field-control", 1}, - require = techs_dex_req1, - points = 5, - random_ego = "utility", - cooldown = 12, - stamina = 20, - range = 7, - tactical = { ESCAPE = 2 }, - requires_target = true, - target = function(self, t) return {type="hit", range=self:getTalentRange(t)} end, - on_pre_use = function(self, t) - if self:attr("never_move") then return false end - return true - end, - getDist = function(self, t) return math.floor(self:combatTalentScale(t, 3, 7)) end, - action = function(self, t) - local tg = self:getTalentTarget(t) - local x, y, target = self:getTarget(tg) - if not target or not self:canProject(tg, x, y) then return nil end - - self:knockback(target.x, target.y, t.getDist(self, t)) - return true - end, - info = function(self, t) - return ([[Jump away %d grids from your target.]]):format(t.getDist(self, t)) - end, -} - -newTalent{ - name = "Track", - type = {"technique/field-control", 2}, - require = techs_dex_req2, - points = 5, - random_ego = "utility", - stamina = 20, - cooldown = 20, - radius = function(self, t) return math.floor(self:combatScale(self:getCun(10, true) * self:getTalentLevel(t), 5, 0, 55, 50)) end, - no_npc_use = true, - action = function(self, t) - local rad = self:getTalentRadius(t) - self:setEffect(self.EFF_SENSE, 3 + self:getTalentLevel(t), { - range = rad, - actor = 1, - }) - return true - end, - info = function(self, t) - local rad = self:getTalentRadius(t) - return ([[Sense foes around you in a radius of %d for %d turns. - The radius will increase with your Cunning.]]):format(rad, 3 + self:getTalentLevel(t)) - end, -} +--newTalent{ +-- name = "Disengage", +-- type = {"technique/field-control", 1}, +-- require = techs_dex_req1, +-- points = 5, +-- random_ego = "utility", +-- cooldown = 12, +-- stamina = 20, +-- range = 7, +-- tactical = { ESCAPE = 2 }, +-- requires_target = true, +-- target = function(self, t) return {type="hit", range=self:getTalentRange(t)} end, +-- on_pre_use = function(self, t) +-- if self:attr("never_move") then return false end +-- return true +-- end, +-- getDist = function(self, t) return math.floor(self:combatTalentScale(t, 3, 7)) end, +-- action = function(self, t) +-- local tg = self:getTalentTarget(t) +-- local x, y, target = self:getTarget(tg) +-- if not target or not self:canProject(tg, x, y) then return nil end +-- +-- self:knockback(target.x, target.y, t.getDist(self, t)) +-- return true +-- end, +-- info = function(self, t) +-- return ([[Jump away %d grids from your target.]]):format(t.getDist(self, t)) +-- end, +--} +-- +--newTalent{ +-- name = "Track", +-- type = {"technique/field-control", 2}, +-- require = techs_dex_req2, +-- points = 5, +-- random_ego = "utility", +-- stamina = 20, +-- cooldown = 20, +-- radius = function(self, t) return math.floor(self:combatScale(self:getCun(10, true) * self:getTalentLevel(t), 5, 0, 55, 50)) end, +-- no_npc_use = true, +-- action = function(self, t) +-- local rad = self:getTalentRadius(t) +-- self:setEffect(self.EFF_SENSE, 3 + self:getTalentLevel(t), { +-- range = rad, +-- actor = 1, +-- }) +-- return true +-- end, +-- info = function(self, t) +-- local rad = self:getTalentRadius(t) +-- return ([[Sense foes around you in a radius of %d for %d turns. +-- The radius will increase with your Cunning.]]):format(rad, 3 + self:getTalentLevel(t)) +-- end, +--} newTalent{ name = "Heave", - type = {"technique/field-control", 3}, + type = {"technique/field-control", 1}, require = techs_dex_req3, points = 5, random_ego = "defensive", @@ -117,7 +117,7 @@ newTalent{ newTalent{ name = "Slow Motion", - type = {"technique/field-control", 4}, + type = {"technique/field-control", 2}, require = techs_dex_req4, mode = "sustained", points = 5, diff --git a/game/modules/tome/data/talents/techniques/mobility.lua b/game/modules/tome/data/talents/techniques/mobility.lua index f3376127abce8411b792dc3d2a2d220bf8250dea..69b383e2d03f327f26396733c6f80a853a817484 100644 --- a/game/modules/tome/data/talents/techniques/mobility.lua +++ b/game/modules/tome/data/talents/techniques/mobility.lua @@ -1,5 +1,5 @@ -- ToME - Tales of Maj'Eyal --- Copyright (C) 2009 - 2016 Nicolas Casalini +-- Copyright (C) 2009 - 2014 Nicolas Casalini -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by @@ -20,95 +20,186 @@ local Map = require "engine.Map" newTalent{ - name = "Hack'n'Back", + name = "Disengage", type = {"technique/mobility", 1}, - points = 5, - cooldown = 14, - stamina = 30, - tactical = { ESCAPE = 1, ATTACK = { weapon = 0.5 } }, require = techs_dex_req1, + points = 5, + random_ego = "utility", + cooldown = 10, + stamina = 12, + range = 7, + getSpeed = function(self, t) return self:combatTalentScale(t, 100, 250, 0.75) end, + getReload = function(self, t) return math.floor(self:combatTalentScale(t, 2, 10)) end, + tactical = { ESCAPE = 2 }, requires_target = true, - is_melee = true, target = function(self, t) return {type="hit", range=self:getTalentRange(t)} end, - range = 1, - getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.4, 1) end, - getDist = function(self, t) return math.ceil(self:combatTalentScale(t, 1.2, 3.3)) end, on_pre_use = function(self, t) if self:attr("never_move") then return false end return true end, + getDist = function(self, t) return math.floor(self:combatTalentScale(t, 3, 7)) end, action = function(self, t) local tg = self:getTalentTarget(t) local x, y, target = self:getTarget(tg) if not target or not self:canProject(tg, x, y) then return nil end - local hitted = self:attackTarget(target, nil, t.getDamage(self, t), true) - if hitted then - self:knockback(target.x, target.y, t.getDist(self, t)) + self:knockback(target.x, target.y, t.getDist(self, t)) + + if self:getTalentLevel(t) >= 4 then + self:setEffect("EFF_AVOIDANCE", 1, {power=100}) + local eff = self:hasEffect("EFF_AVOIDANCE") + eff.dur = eff.dur - 1 + end + + game:onTickEnd(function() + self:setEffect(self.EFF_WILD_SPEED, 3, {power=t.getSpeed(self,t)}) + end) + + local weapon, ammo, offweapon = self:hasArcheryWeapon() + if weapon and ammo and not ammo.infinite then + ammo.combat.shots_left = math.min(ammo.combat.shots_left + t.getReload(self, t), ammo.combat.capacity) + game.logSeen(self, "%s reloads.", self.name:capitalize()) end return true end, info = function(self, t) - local damage = t.getDamage(self, t) - local dist = t.getDist(self, t) - return ([[You hit your target, doing %d%% damage, distracting it while you jump back %d squares away.]]): - format(100 * damage, dist) + return ([[Jump away %d grids from your target and gain a burst of speed on landing, increasing you movement speed by %d%% for 3 turns. + Any actions other than movement will end the speed boost. + At talent level 4 you avoid all attacks against you while disengaging. + If you have a quiver equip, you also take the time to reload %d shots.]]): + format(t.getDist(self, t), t.getSpeed(self,t), t.getReload(self,t)) end, } -newTalent{ - name = "Mobile Defence", +newTalent { + name = "Tumble", type = {"technique/mobility", 2}, - mode = "passive", - points = 5, require = techs_dex_req2, - getDef = function(self, t) return self:getTalentLevel(t) * 0.08 end, - getHardiness = function(self, t) return self:getTalentLevel(t) * 0.06 end, - -- called by _M:combatDefenseBase function in mod\class\interface\Combat.lua - getDef = function(self, t) return self:combatTalentLimit(t, 1, 0.10, 0.40) end, -- Limit to <100% defense bonus - -- called by _M:combatArmorHardiness function in mod\class\interface\Combat.lua - getHardiness = function(self, t) return self:combatTalentLimit(t, 100, 6, 30) end, -- Limit < 100% - info = function(self, t) - return ([[Whilst wearing leather or lighter armour, you gain %d%% Defense and %d%% Armour hardiness.]]): - format(t.getDef(self, t) * 100, t.getHardiness(self, t)) + points = 5, + random_ego = "attack", + cooldown = function(self, t) + return math.max(10 - self:getTalentLevel(t), 1) + end, + no_energy = true, + no_break_stealth = true, + tactical = { ESCAPE = 2 }, + stamina = function(self, t) + local eff = self:hasEffect(self.EFF_EXHAUSTION) + if eff and eff.charges then + return 15 + eff.charges*15 + else + return 15 + end + end, + range = function(self, t) + return math.floor(self:combatTalentScale(t, 2, 4)) + end, + getDuration = function(self, t) + return math.max(20 - self:getTalentLevel(t), 5) + end, + target = function(self, t) + return {type="beam", range=self:getTalentRange(t), talent=t} + end, + action = function(self, t) + local tg = self:getTalentTarget(t) + local x, y, target = self:getTarget(tg) + if not x or not y then return end + if self.x == x and self.y == y then return end + if core.fov.distance(self.x, self.y, x, y) > self:getTalentRange(t) or not self:hasLOS(x, y) then return end + + if target or game.level.map:checkEntity(x, y, Map.TERRAIN, "block_move", self) then + game.logPlayer(self, "You must have an empty space to roll to.") + return false + end + + self:move(x, y, true) + + game:onTickEnd(function() + self:setEffect(self.EFF_EXHAUSTION, t.getDuration(self,t), { max_stacks=5 }) + end) + + return true end, + info = function(self, t) + return ([[Move to a spot within range, bounding around, over, or through any enemies in the way. This can be used while pinned, and does not break stealth. + This quickly becomes exhausting to use, increasing the stamina cost by 15 for %d turns after use.]]):format(t.getDuration(self,t)) + end } -newTalent{ - name = "Light of Foot", +newTalent { + name = "Trained Reactions", type = {"technique/mobility", 3}, - mode = "passive", + mode = "sustained", points = 5, + cooldown = function(self, t) return 10 end, + sustain_stamina = 10, + no_energy = true, require = techs_dex_req3, - getFatigue = function(self, t) return self:combatTalentLimit(t, 100, 1.5, 7.5) end, -- Limit < 50% - passives = function(self, t, p) - self:talentTemporaryValue(p, "fatigue", -t.getFatigue(self, t)) + tactical = { BUFF = 2 }, + activate = function(self, t) + return {} end, - info = function(self, t) - return ([[You are light on your feet, handling your armour better. Each step you take regenerates %0.2f stamina, and your fatigue is permanently reduced by %0.1f%%. - At level 3 you are able to walk so lightly that you never trigger traps that require pressure.]]): - format(self:getTalentLevelRaw(t) * 0.2, t.getFatigue(self, t)) + deactivate = function(self, t, p) + return true + end, + getLifeTrigger = function(self, t) + return self:combatTalentLimit(t, 10, 40, 22) + end, + getReduction = function(self, t) + return (0.05 + (self:combatTalentLimit(t, 1, 0.15, 0.50) * self:combatLimit(self:combatDefense(), 1, 0.20, 10, 0.50, 50)))*100 end, + callbackOnHit = function(self, t, cb, src) + if cb.value >= self.max_life * t.getLifeTrigger(self, t) * 0.01 and use_stamina(self, 10) then + -- Apply effect with duration 0. + self:setEffect("EFF_SKIRMISHER_DEFENSIVE_ROLL", 1, {reduce = t.getReduction(self, t)}) + local eff = self:hasEffect("EFF_SKIRMISHER_DEFENSIVE_ROLL") + eff.dur = eff.dur - 1 + cb.value = cb.value * (100-t.getReduction(self, t)) / 100 + end + return cb.value + end, + info = function(self, t) + local trigger = t.getLifeTrigger(self, t) + local reduce = t.getReduction(self, t) + return ([[While this talent is sustained, you anticipate deadly attacks against you. + Any time you would lose more than %d%% of your life in a single hit, you instead duck out of the way and assume a defensive posture. + This reduces the triggering damage and all further damage in the same turn by %d%%. + This costs 10 stamina each time it triggers. + The damage reduction increases based on your Defense.]]) + :format(trigger, reduce, cost) + end, } newTalent{ - name = "Strider", + name = "Evasion", type = {"technique/mobility", 4}, - mode = "passive", points = 5, require = techs_dex_req4, - incspeed = function(self, t) return self:combatTalentScale(t, 0.02, 0.10, 0.75) end, - CDreduce = function(self, t) return math.floor(self:combatTalentLimit(t, 8, 1, 5)) end, -- Limit < 8 - passives = function(self, t, p) - local cdr = t.CDreduce(self, t) - self:talentTemporaryValue(p, "movement_speed", t.incspeed(self, t)) - self:talentTemporaryValue(p, "talent_cd_reduction", - {[Talents.T_RUSH]=cdr, [Talents.T_HACK_N_BACK]=cdr, [Talents.T_DISENGAGE]=cdr, [Talents.T_EVASION]=cdr}) + random_ego = "defensive", + tactical = { ESCAPE = 2, DEFEND = 2 }, + cooldown = 30, + stamina = 20, + no_energy = true, + getDur = function(self, t) return math.floor(self:combatTalentLimit(t, 30, 5, 9)) end, -- Limit < 30 + getChanceDef = function(self, t) + if self.perfect_evasion then return 100, 0 end + return self:combatLimit(5*self:getTalentLevel(t) + self:getDex(50,true), 50, 10, 10, 37.5, 75), + self:combatScale(self:getTalentLevel(t) * (self:getDex(50, true)), 0, 0, 55, 250, 0.75) + -- Limit evasion chance < 50%, defense bonus ~= 55 at level 50 + end, + speed = "combat", + action = function(self, t) + local dur = t.getDur(self,t) + local chance, def = t.getChanceDef(self,t) + self:setEffect(self.EFF_EVASION, dur, {chance=chance, defense = def}) + return true end, info = function(self, t) - return ([[You literally dance around your foes, increasing your movement speed by %d%% and reducing the cooldown of Hack'n'Back, Rush, Disengage and Evasion by %d turns.]]): - format(t.incspeed(self, t)*100,t.CDreduce(self, t)) + local chance, def = t.getChanceDef(self,t) + return ([[Your quick wit allows you to see melee attacks before they land, granting you a %d%% chance to completely evade them and granting you %d defense for %d turns. + The chance to evade and defense increases with your Dexterity.]]): + format(chance, def,t.getDur(self,t)) end, -} +} \ No newline at end of file diff --git a/game/modules/tome/data/talents/techniques/pugilism.lua b/game/modules/tome/data/talents/techniques/pugilism.lua index 4cd2ef1951d1d8bfe8c8150a61ea736299a96604..e1546a01ed7934946aa32bd463f85b6abaaea5ea 100644 --- a/game/modules/tome/data/talents/techniques/pugilism.lua +++ b/game/modules/tome/data/talents/techniques/pugilism.lua @@ -39,7 +39,13 @@ newTalent{ no_unlearn_last = true, getAttack = function(self, t) return self:getDex(25, true) end, getDamage = function(self, t) return self:combatStatScale("dex", 5, 35) end, - getFlatReduction = function(self, t) return math.min(35, self:combatStatScale("str", 1, 30, 0.75)) end, + getFlatReduction = function(self, t) + if self:knowTalent(self.T_REFLEX_DEFENSE) then + return math.min(35, self:combatStatScale("str", 1, 30, 0.75)) * (1 + (self:callTalent(self.T_REFLEX_DEFENSE, "getFlatReduction")/100) ) + else + return math.min(35, self:combatStatScale("str", 1, 30, 0.75)) + end + end, -- 13 Strength = 2, 20 = 5, 30 = 9, 40 = 12, 50 = 16, 55 = 17, 70 = 22, 80 = 25 activate = function(self, t) cancelStances(self) diff --git a/game/modules/tome/data/talents/techniques/throwing-knives.lua b/game/modules/tome/data/talents/techniques/throwing-knives.lua index 21c950941973071736043bad482fac0e560da627..2dcd2b8dc97a6f07330171f03fdec62eb95ba5ef 100644 --- a/game/modules/tome/data/talents/techniques/throwing-knives.lua +++ b/game/modules/tome/data/talents/techniques/throwing-knives.lua @@ -273,7 +273,7 @@ newTalent{ local power = t.getCritPower(self,t) local chance = t.getChance(self,t) return ([[You are able to target your throwing knives with pinpoint accuracy, increasing their critical strike chance by %d%% and critical strike damage by %d%%. -In addition, your critical strikes with throwing knives have a %d%% chance will to randomly disable your target, possibly disarming, silencing or pinning them for 2 turns.]]) +In addition, your critical strikes with throwing knives have a %d%% chance to randomly disable your target, possibly disarming, silencing or pinning them for 2 turns.]]) :format(crit, power, chance) end, } diff --git a/game/modules/tome/data/talents/techniques/thuggery.lua b/game/modules/tome/data/talents/techniques/thuggery.lua index 3901e32cd5da4b17e057566b43e8d122cb29adc0..12fd4df0333609cc0c7798aec3cdb139a6e5f7c6 100644 --- a/game/modules/tome/data/talents/techniques/thuggery.lua +++ b/game/modules/tome/data/talents/techniques/thuggery.lua @@ -127,24 +127,22 @@ newTalent{ tactical = { BUFF = 2 }, getCrit = function(self, t) return self:combatTalentStatDamage(t, "dex", 10, 50) / 1.5 end, getPen = function(self, t) return self:combatLimit(self:combatTalentStatDamage(t, "str", 10, 50), 100, 0, 0, 35.7, 35.7) end, -- Limit to <100% - getDrain = function(self, t) return self:combatTalentLimit(t, 0, 11, 6) end, -- Limit to >0 stam + drain_stamina = 6, activate = function(self, t) local ret = { crit = self:addTemporaryValue("combat_physcrit", t.getCrit(self, t)), pen = self:addTemporaryValue("resists_pen", {[DamageType.PHYSICAL] = t.getPen(self, t)}), - drain = self:addTemporaryValue("stamina_regen_on_hit", - t.getDrain(self, t)), } return ret end, deactivate = function(self, t, p) self:removeTemporaryValue("combat_physcrit", p.crit) self:removeTemporaryValue("resists_pen", p.pen) - self:removeTemporaryValue("stamina_regen_on_hit", p.drain) return true end, info = function(self, t) return ([[You go all out, trying to burn down your foes as fast as possible. - Every hit in battle has +%d%% critical chance and +%d%% physical resistance penetration, but each strike drains %0.1f stamina.]]): + Every hit in battle has +%d%% critical chance and +%d%% physical resistance penetration, but this talent drains 6 stamina each turn.]]): format(t.getCrit(self, t), t.getPen(self, t), t.getDrain(self, t)) end, } diff --git a/game/modules/tome/data/talents/techniques/unarmed-training.lua b/game/modules/tome/data/talents/techniques/unarmed-training.lua index a859bc9140b96fc9aa6fcde24f3510ca93f242aa..5e018dfd8713e0f713e5adf54a19fcab237926be 100644 --- a/game/modules/tome/data/talents/techniques/unarmed-training.lua +++ b/game/modules/tome/data/talents/techniques/unarmed-training.lua @@ -112,30 +112,20 @@ newTalent{ end, } --- It's a bit wierd that this works against mind attacks newTalent{ name = "Reflex Defense", type = {"technique/unarmed-training", 4}, - require = techs_cun_req4, -- bit icky since this is clearly dex, but whatever, cun turns defense special *handwave* + require = techs_cun_req4, points = 5, mode = "passive", - getDamageReduction = function(self, t) - return self:combatTalentLimit(t, 1, 0.15, 0.50) * self:combatLimit(self:combatDefense(), 1, 0.15, 10, 0.5, 50) -- Limit < 100%, 25% for TL 5.0 and 50 defense + getFlatReduction = function(self, t) return self:combatTalentScale(t, 30, 70, 0.75) end, + critResist = function(self, t) return self:combatTalentScale(t, 15, 50, 0.75) end, + passives = function(self, t, p) + self:talentTemporaryValue(p, "ignore_direct_crits", t.critResist(self, t)) end, - getDamagePct = function(self, t) - return self:combatTalentLimit(t, 0.1, 0.3, 0.15) -- Limit trigger > 10% life - end, - callbackOnHit = function(self, t, cb) - if ( cb.value > (t.getDamagePct(self, t) * self.max_life) ) then - local damageReduction = cb.value * t.getDamageReduction(self, t) - cb.value = cb.value - damageReduction - game.logPlayer(self, "#GREEN#You twist your body in complex ways mitigating the blow by #ORCHID#" .. math.ceil(damageReduction) .. "#LAST#.") - end - return cb.value - end, info = function(self, t) - return ([[Your understanding of physiology allows you to apply your reflexes in new ways. Whenever you would receive damage (from any source) greater than %d%% of your maximum life you reduce that damage by %0.1f%% (based on your Defense).]]): - format(t.getDamagePct(self, t)*100, t.getDamageReduction(self, t)*100 ) - end, + return ([[Your understanding of physiology allows you to apply your reflexes in new ways, increasing the flat damage reduction granted by Striking Stance by %d%% and causing direct critical hits (physical, mental, spells) against you to have a %d%% lower Critical multiplier (but always do at least normal damage).]]): + format(t.getFlatReduction(self,t), t.critResist(self,t) ) + end } diff --git a/game/modules/tome/data/timed_effects/physical.lua b/game/modules/tome/data/timed_effects/physical.lua index afbf99b4f666c70b694b5d54c155cc17e667511b..19e6367ab62a98deb819b03f15c1d03b132a1f49 100644 --- a/game/modules/tome/data/timed_effects/physical.lua +++ b/game/modules/tome/data/timed_effects/physical.lua @@ -2069,7 +2069,7 @@ newEffect{ -- Note: This effect is cancelled by EFF_DISARMED } newEffect{ -- Note: This effect is cancelled by EFF_DISARMED - name = "PARRY", image = "talents/parry.png", + name = "PARRY", image = "talents/dual_weapon_mastery.png", desc = "Parrying", deflectchance = function(self, eff, adj) -- The last partial deflect has a reduced chance to happen adj = adj or 1 @@ -3507,3 +3507,72 @@ newEffect{ deactivate = function(self, eff) end, } + +newEffect{ + name = "AVOIDANCE", image = "talents/disengage.png", + desc = "Avoidance", + long_desc = function(self, eff) return ("%d%% chance to fully evade any damaging actions."):format(eff.power) end, + type = "physical", + subtype = { evade=true }, + status = "beneficial", + parameters = { power=10 }, + activate = function(self, eff) + eff.tmpid = self:addTemporaryValue("cancel_damage_chance", eff.power) + end, + deactivate = function(self, eff) + self:removeTemporaryValue("cancel_damage_chance", eff.tmpid) + end, +} + +newEffect{ + name = "EXHAUSTION", image = "talents/slumber.png", + desc = "Exhaustion", + long_desc = function(self, eff) return ("The target is exhausted, increasing the stamina cost of Tumble by %d."):format(eff.charges*30) end, + type = "other", + subtype = { }, + status = "detrimental", + parameters = { }, + charges = function(self, eff) return eff.charges end, + on_merge = function(self, old_eff, new_eff) + new_eff.charges = math.min(old_eff.charges + 1, 5) + return new_eff + end, + activate = function(self, eff) + eff.charges = 1 + end, + deactivate = function(self, eff) + end, +} + +newEffect { + name = "DANGER_SENSE", image = "talents/danger_sense.png", + desc = "Danger Sense", + type = "physical", + subtype = {tactic = true}, + status = "beneficial", + parameters = { + -- percent of all damage to ignore + reduce = 50 + }, + on_gain = function(self, eff) return "#Target# danger sense lets them narrowly avoid the blow!" end, + activate = function(self, eff) + self:effectTemporaryValue(eff, "incoming_reduce", eff.reduce) + end, + long_desc = function(self, eff) + return ([[The target is avoiding damage, ignoring %d%% of all incoming damage.]]) + :format(eff.reduce) + end, +} + +newEffect{ + name = "MOBILE_DEFENCE", image = "talents/light_armour_training.png", + desc = "Mobile Defense", + long_desc = function(self, eff) return ("Increases stamina regeneration by %d and total defense by %d%%."):format(eff.stamina, eff.power) end, + type = "physical", + subtype = { tactic=true }, + status = "beneficial", + parameters = {stamina=1, power=10}, + activate = function(self, eff) + self:effectTemporaryValue(eff, "stamina_regen", eff.stamina) + end, +}