diff --git a/game/engines/default/engine/interface/ActorLife.lua b/game/engines/default/engine/interface/ActorLife.lua index 9cfdd8d65eb5230ca1c0e99e62c8499f0f76737c..e1a865efb5d8e4c2e7866ec73a52865f960ff965 100644 --- a/game/engines/default/engine/interface/ActorLife.lua +++ b/game/engines/default/engine/interface/ActorLife.lua @@ -51,6 +51,7 @@ end --- Heal some function _M:heal(value, src) + if self.onHeal then value = self:onHeal(value, src) end self.life = util.bound(self.life + value, 0, self.max_life) self.changed = true end diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index ea06adc5b01129bc28a7e36fc03e6ccd549a087c..fb0fa3722fc532d3af8643033105be767152d1a7 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -512,6 +512,14 @@ Faction: %s%s (%s, %d) ) end +--- Called before healing +function _M:onHeal(value, src) + if self:hasEffect(self.EFF_UNSTOPPABLE) then + return 0 + end + return value +end + --- Called before taking a hit, it's the chance to check for shields function _M:onTakeHit(value, src) -- Un-daze @@ -654,6 +662,10 @@ function _M:onTakeHit(value, src) t:onTakeHit(self, value / self.max_life) end + if self:hasEffect(self.EFF_UNSTOPPABLE) then + if value > self.life then value = self.life - 1 end + end + return value end @@ -705,6 +717,16 @@ function _M:die(src) t.on_kill(src, t) end + if src and src.knowTalent and src:knowTalent(src.T_BLOODRAGE) then + local t = src:getTalentFromId(src.T_BLOODRAGE) + t.on_kill(src, t) + end + + if src and src.hasEffect and src:hasEffect(self.EFF_UNSTOPPABLE) then + local p = src:hasEffect(self.EFF_UNSTOPPABLE) + p.kills = p.kills + 1 + end + -- Adds hate if src and src.max_hate and src.max_hate > 0 then src.hate = math.min(src.max_hate, src.hate + src.hate_per_kill) diff --git a/game/modules/tome/class/Object.lua b/game/modules/tome/class/Object.lua index 0e628543cf6225cd510bfe8f0631b2165a5da041..8b72db0ca780df567ac8345573d1dba97fcf1857 100644 --- a/game/modules/tome/class/Object.lua +++ b/game/modules/tome/class/Object.lua @@ -74,6 +74,10 @@ function _M:use(who, typ, inven, item) game.logPlayer(who, "You must wear this object to use it!") return end + if who:hasEffect(self.EFF_UNSTOPPABLE) then + game.logPlayer(who, "You can not use items during a battle frenzy!") + return + end local types = {} if self:canUseObject() then types[#types+1] = "use" end diff --git a/game/modules/tome/class/interface/Combat.lua b/game/modules/tome/class/interface/Combat.lua index 734c1be3d569ff43f335115e3cd2ef214eac3f12..240c2c13bab568ac9a2faefda83679391cae5762 100644 --- a/game/modules/tome/class/interface/Combat.lua +++ b/game/modules/tome/class/interface/Combat.lua @@ -203,6 +203,7 @@ function _M:attackTargetWith(target, weapon, damtype, mult) -- If hit is over 0 it connects, if it is 0 we still have 50% chance local hitted = false + local crit = false local evaded = false if self:checkEvasion(target) then evaded = true @@ -213,7 +214,6 @@ function _M:attackTargetWith(target, weapon, damtype, mult) local damrange = self:combatDamageRange(weapon) dam = rng.range(dam, dam * damrange) print("[ATTACK] after range", dam) - local crit dam, crit = self:physicalCrit(dam, weapon, target) print("[ATTACK] after crit", dam) dam = dam * mult @@ -334,6 +334,18 @@ function _M:attackTargetWith(target, weapon, damtype, mult) t.do_splash(target, t, self) end + -- Bloodbath + if hitted and crit and self:knowTalent(self.T_BLOODBATH) then + local t = self:getTalentFromId(self.T_BLOODBATH) + t.do_bloodbath(self, t) + end + + -- Mortal Terror + if hitted and not target.dead and self:knowTalent(self.T_MORTAL_TERROR) then + local t = self:getTalentFromId(self.T_MORTAL_TERROR) + t.do_terror(self, t, target, dam) + end + -- Regen on being hit if hitted and not target.dead and target:attr("stamina_regen_on_hit") then target:incStamina(target.stamina_regen_on_hit) end if hitted and not target.dead and target:attr("mana_regen_on_hit") then target:incMana(target.mana_regen_on_hit) end diff --git a/game/modules/tome/data/birth/classes/warrior.lua b/game/modules/tome/data/birth/classes/warrior.lua index 55849d89bb6ca8603b7edf2cf8b14b9a80fd283f..4f3a338ed040aa949c67b6ab14253902070b576a 100644 --- a/game/modules/tome/data/birth/classes/warrior.lua +++ b/game/modules/tome/data/birth/classes/warrior.lua @@ -97,6 +97,7 @@ newBirthDescriptor{ ["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}, }, diff --git a/game/modules/tome/data/talents/techniques/bloodthirst.lua b/game/modules/tome/data/talents/techniques/bloodthirst.lua new file mode 100644 index 0000000000000000000000000000000000000000..476350ae7f868ad62c93a69dbcd2d34ddc2002f7 --- /dev/null +++ b/game/modules/tome/data/talents/techniques/bloodthirst.lua @@ -0,0 +1,100 @@ +-- ToME - Tales of Middle-Earth +-- Copyright (C) 2009, 2010 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 +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-- Nicolas Casalini "DarkGod" +-- darkgod@te4.org + + +newTalent{ + name = "Bloodbath", + type = {"technique/bloodthirst", 1}, + require = techs_req_high1, + points = 5, + mode = "passive", + do_bloodbath = function(self, t) + self:setEffect(self.EFF_BLOODBATH, 5 + self:getTalentLevelRaw(t), {regen=math.floor(self:getTalentLevel(t) * 40), hp=math.floor(self:getTalentLevel(t) * 2)}) + end, + info = function(self, t) + return ([[Delight in spilling the blood of your foes. After scoring a critical hit your life and stamina regeneration is increased by %d%% and your maximum life is increased by %d%%.]]): + format(math.floor(self:getTalentLevel(t) * 40), math.floor(self:getTalentLevel(t) * 2)) + end, +} + +newTalent{ + name = "Mortal Terror", + type = {"technique/bloodthirst", 2}, + require = techs_req_high2, + points = 5, + mode = "passive", + do_terror = function(self, t, target, dam) + if dam < target.max_life * (20 + (30 - self:getTalentLevelRaw(t) * 5)) / 100 then return end + + local weapon = target:getInven("MAINHAND") + if weapon then weapon = weapon[1] and weapon[1].combat end + if not weapon or type(weapon) ~= "table" then weapon = nil end + weapon = weapon or target.combat + + if target:checkHit(self:combatAttackStr(weapon.combat), target:combatPhysicalResist(), 0, 95, 8 - self:getTalentLevel(t) / 2) and target:canBe("stun") then + target:setEffect(target.EFF_DAZED, 5, {}) + else + game.logSeen(target, "%s resists the terror!", target.name:capitalize()) + end + end, + on_learn = function(self, t) + self.combat_physcrit = self.combat_physcrit + 2.8 + end, + on_unlearn = function(self, t) + self.combat_physcrit = self.combat_physcrit - 2.8 + end, + info = function(self, t) + return ([[Your mighty blows inspire utter terror on your foes. Any melee strike you do that deals more than %d%% of the target's total life puts them in a mortal terror, dazing them for 5 turns. + Your critical strike chance also increase by %d%%.]]): + format(20 + (30 - self:getTalentLevelRaw(t) * 5), self:getTalentLevelRaw(t) * 3) + end, +} + +newTalent{ + name = "Bloodrage", + type = {"technique/bloodthirst", 3}, + require = techs_req_high3, + points = 5, + mode = "passive", + on_kill = function(self, t) + self:setEffect(self.EFF_BLOODRAGE, 5, {max=math.floor(self:getTalentLevel(t) * 6), inc=2}) + end, + info = function(self, t) + return ([[Each time one of your foes bites the dust you feel a surge of power, increasing your strength by 2 up to a maximum of %d.]]): + format(math.floor(self:getTalentLevel(t) * 6)) + end, +} + +newTalent{ + name = "Unstoppable", + type = {"technique/bloodthirst", 4}, + require = techs_req_high4, + points = 5, + cooldown = 45, + stamina = 120, + action = function(self, t) + self:setEffect(self.EFF_UNSTOPPABLE, 2 + self:getTalentLevelRaw(t), {hp_per_kill=math.floor(self:getTalentLevel(t) * 3.5)}) + return true + end, + info = function(self, t) + return ([[You enter a battle frenzy for %d turns. During the time you can not use items, healing has no effect and your health can not drop below 1. + At the end of the frenzy you regain %d%% of your health per foes slain during thr frenzy.]]): + format(2 + self:getTalentLevelRaw(t), math.floor(self:getTalentLevel(t) * 3.5)) + end, +} diff --git a/game/modules/tome/data/talents/techniques/techniques.lua b/game/modules/tome/data/talents/techniques/techniques.lua index 2334f0234760619365945c34703ed23fc9b1f1a6..ea8778f3c4d15b3ba0226e3d6e20701c5222a263 100644 --- a/game/modules/tome/data/talents/techniques/techniques.lua +++ b/game/modules/tome/data/talents/techniques/techniques.lua @@ -31,6 +31,7 @@ newTalentType{ type="technique/archery-training", name = "archery - common", des newTalentType{ type="technique/archery-utility", name = "archery - utility", description = "Specialized archery techniques to maim your targets." } newTalentType{ type="technique/superiority", name = "superiority", description = "Advanced combat techniques." } newTalentType{ type="technique/warcries", name = "warcries", description = "Master the warcries to improve yourself and weaken others." } +newTalentType{ type="technique/bloodthirst", name = "bloodthirst", description = "Delight in the act of battle and the spilling of blood." } newTalentType{ type="technique/field-control", name = "field control", generic = true, description = "Control the battlefield using various techniques." } newTalentType{ type="technique/combat-techniques-active", name = "combat techniques", description = "Generic combat oriented techniques." } newTalentType{ type="technique/combat-techniques-passive", name = "combat techniques", description = "Generic combat oriented techniques." } @@ -129,6 +130,7 @@ load("/data/talents/techniques/dualweapon.lua") load("/data/talents/techniques/weaponshield.lua") load("/data/talents/techniques/superiority.lua") load("/data/talents/techniques/warcries.lua") +load("/data/talents/techniques/bloodthirst.lua") load("/data/talents/techniques/field-control.lua") load("/data/talents/techniques/combat-techniques.lua") load("/data/talents/techniques/combat-training.lua") diff --git a/game/modules/tome/data/timed_effects.lua b/game/modules/tome/data/timed_effects.lua index a84a17fe56750b737075b88a9a15ef4b9bcbcc0f..c876e5d6b1d556726802b8a91dd006d22ce34bb4 100644 --- a/game/modules/tome/data/timed_effects.lua +++ b/game/modules/tome/data/timed_effects.lua @@ -1516,4 +1516,63 @@ newEffect{ old_eff.dur = math.min(old_eff.dur + new_eff.dur, 15) return old_eff end, -} \ No newline at end of file +} + +newEffect{ + name = "BLOODBATH", + desc = "Bloodbath", + type = "physical", + status = "beneficial", + parameters = { hp=10, regen=10 }, + on_gain = function(self, err) return nil, "+Bloodbath" end, + on_lose = function(self, err) return nil, "-Bloodbath" end, + activate = function(self, eff) + local v = eff.hp * self.max_life / 100 + eff.life_id = self:addTemporaryValue("max_life", v) + self:heal(v) + eff.life_regen_id = self:addTemporaryValue("life_regen", eff.regen * self.life_regen / 100) + eff.stamina_regen_id = self:addTemporaryValue("stamina_regen", eff.regen * self.stamina_regen / 100) + end, + deactivate = function(self, eff) + self:removeTemporaryValue("max_life", eff.life_id) + self:removeTemporaryValue("life_regen", eff.life_regen_id) + self:removeTemporaryValue("stamina_regen", eff.stamina_regen_id) + end, +} + +newEffect{ + name = "BLOODRAGE", + desc = "Bloodrage", + type = "physical", + status = "beneficial", + parameters = { inc=1, max=10 }, + on_merge = function(self, old_eff, new_eff) + self:removeTemporaryValue("inc_stats", old_eff.tmpid) + old_eff.cur_inc = math.min(old_eff.cur_inc + new_eff.inc, new_eff.max) + old_eff.tmpid = self:addTemporaryValue("inc_stats", {[Stats.STAT_STR] = old_eff.cur_inc}) + + old_eff.dur = new_eff.dur + return old_eff + end, + activate = function(self, eff) + eff.cur_inc = eff.inc + eff.tmpid = self:addTemporaryValue("inc_stats", {[Stats.STAT_STR] = eff.inc}) + end, + deactivate = function(self, eff) + self:removeTemporaryValue("inc_stats", eff.tmpid) + end, +} + +newEffect{ + name = "UNSTOPPABLE", + desc = "Unstoppable", + type = "physical", + status = "beneficial", + parameters = { hp_per_kill=2 }, + activate = function(self, eff) + eff.kills = 0 + end, + deactivate = function(self, eff) + self:heal(eff.kills * eff.hp_per_kill * self.max_life / 100) + end, +} diff --git a/ideas/technics.ods b/ideas/technics.ods index c703ff0d8178ff997edfc848f1b6430c89d7222b..755a638287fc54b80b075448da291cf4727e4061 100644 Binary files a/ideas/technics.ods and b/ideas/technics.ods differ