diff --git a/game/modules/tome/data/gfx/talents/hack_n_back.png b/game/modules/tome/data/gfx/talents/hack_n_back.png new file mode 100644 index 0000000000000000000000000000000000000000..0e27ebf1a5be3c755f79fb3fc21ee7ad85cc3fca Binary files /dev/null and b/game/modules/tome/data/gfx/talents/hack_n_back.png differ diff --git a/game/modules/tome/data/gfx/talents/light_of_foot.png b/game/modules/tome/data/gfx/talents/light_of_foot.png new file mode 100644 index 0000000000000000000000000000000000000000..3857758bbad931d1241b2a03a008fac6440fd64d Binary files /dev/null and b/game/modules/tome/data/gfx/talents/light_of_foot.png differ diff --git a/game/modules/tome/data/gfx/talents/mobile_defence.png b/game/modules/tome/data/gfx/talents/mobile_defence.png new file mode 100644 index 0000000000000000000000000000000000000000..7089711c542b28fba29b16f9b88038ade920ba81 Binary files /dev/null and b/game/modules/tome/data/gfx/talents/mobile_defence.png differ diff --git a/game/modules/tome/data/gfx/talents/riot_born.png b/game/modules/tome/data/gfx/talents/riot_born.png new file mode 100644 index 0000000000000000000000000000000000000000..14d5c03c83692704202a21022cbaeba83facc560 Binary files /dev/null and b/game/modules/tome/data/gfx/talents/riot_born.png differ diff --git a/game/modules/tome/data/gfx/talents/skullcracker.png b/game/modules/tome/data/gfx/talents/skullcracker.png new file mode 100644 index 0000000000000000000000000000000000000000..99250487374dffc531bd06487c8300997f064352 Binary files /dev/null and b/game/modules/tome/data/gfx/talents/skullcracker.png differ diff --git a/game/modules/tome/data/gfx/talents/strider.png b/game/modules/tome/data/gfx/talents/strider.png new file mode 100644 index 0000000000000000000000000000000000000000..127b6831ab834fae86fa228301961c8be44f27ce Binary files /dev/null and b/game/modules/tome/data/gfx/talents/strider.png differ diff --git a/game/modules/tome/data/gfx/talents/total_thuggery.png b/game/modules/tome/data/gfx/talents/total_thuggery.png new file mode 100644 index 0000000000000000000000000000000000000000..2ea691b49233147dd0d5662148764c7dc76ae6c5 Binary files /dev/null and b/game/modules/tome/data/gfx/talents/total_thuggery.png differ diff --git a/game/modules/tome/data/gfx/talents/vicious_strikes.png b/game/modules/tome/data/gfx/talents/vicious_strikes.png new file mode 100644 index 0000000000000000000000000000000000000000..a50fc964b05b8cc5b544adb0a9f5fbbcd4d8b86b Binary files /dev/null and b/game/modules/tome/data/gfx/talents/vicious_strikes.png differ diff --git a/game/modules/tome/data/talents/techniques/mobility.lua b/game/modules/tome/data/talents/techniques/mobility.lua new file mode 100644 index 0000000000000000000000000000000000000000..384582953378c87a0032af61d8d55d15ff1684b1 --- /dev/null +++ b/game/modules/tome/data/talents/techniques/mobility.lua @@ -0,0 +1,133 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009, 2010, 2011 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 + +local Map = require "engine.Map" + +newTalent{ + name = "Hack'n'Back", + type = {"technique/mobility", 1}, + points = 5, + cooldown = 14, + stamina = 30, + tactical = { ESCAPE = 1, ATTACK = 0.5 }, + require = cuns_req1, + requires_target = true, + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.4, 1) end, + getDist = function(self, t) return 1 + math.ceil(self:getTalentLevel(t) / 2) end, + action = function(self, t) + local tg = {type="hit", range=self:getTalentRange(t)} + local x, y, target = self:getTarget(tg) + if not x or not y or not target then return nil end + if math.floor(core.fov.distance(self.x, self.y, x, y)) > 1 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 = {"technique/mobility", 2}, + mode = "passive", + points = 5, + require = cuns_req2, + getDef = function(self, t) return self:getTalentLevel(t) * 0.08 end, + getHardiness = function(self, t) return self:getTalentLevel(t) * 0.06 end, + info = function(self, t) + return ([[Whilst wearing leather or lighter armour you gain %d%% defence and %d%% armour hardiness.]]): + format(t.getDef(self, t) * 100, t.getHardiness(self, t) * 100) + end, +} + +newTalent{ + name = "Light of Foot", + type = {"technique/mobility", 3}, + mode = "passive", + points = 5, + require = cuns_req3, + on_learn = function(self, t) + self.fatigue = (self.fatigue or 0) - 1.5 + end, + on_unlearn = function(self, t) + self.fatigue = (self.fatigue or 0) + 1.5 + end, + info = function(self, t) + return ([[You are light on foot, handling your armour better. Each step you take regenerates %0.2f stamina and your fatigue is permanently reduced by %d%%.]]): + format(self:getTalentLevelRaw(t) * 0.2, self:getTalentLevelRaw(t) * 1.5) + end, +} + +newTalent{ + name = "Strider", + type = {"technique/mobility", 4}, + points = 5, + random_ego = "attack", + cooldown = 25, + stamina = 30, + require = cuns_req4, + requires_target = true, + tactical = { DISABLE = 2, ATTACK = 2 }, + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.9, 1.4) end, + getDuration = function(self, t) return 3 + math.ceil(self:getTalentLevel(t)) end, + getAttackPenalty = function(self, t) return 10 + self:getTalentLevel(t) * 3 end, + getDamagePenalty = function(self, t) return 10 + self:getTalentLevel(t) * 4 end, + action = function(self, t) + local tg = {type="hit", range=self:getTalentRange(t)} + local x, y, target = self:getTarget(tg) + if not x or not y or not target then return nil end + if math.floor(core.fov.distance(self.x, self.y, x, y)) > 1 then return nil end + local hitted = self:attackTarget(target, nil, t.getDamage(self, t), true) + + if hitted then + if target:checkHit(self:combatAttackDex(), target:combatPhysicalResist(), 0, 95, 5 - self:getTalentLevel(t) / 2) then + local tw = target:getInven("MAINHAND") + if tw then + tw = tw[1] and tw[1].combat + end + tw = tw or target.combat + local atk = target:combatAttack(tw) * (t.getAttackPenalty(self, t)) / 100 + local dam = target:combatDamage(tw) * (t.getDamagePenalty(self, t)) / 100 + target:setEffect(target.EFF_CRIPPLE, t.getDuration(self, t), {atk=atk, dam=dam}) + else + game.logSeen(target, "%s is not crippled!", target.name:capitalize()) + end + end + + return true + end, + info = function(self, t) + local damage = t.getDamage(self, t) + local duration = t.getDuration(self, t) + local attackpen = t.getAttackPenalty(self, t) + local damagepen = t.getDamagePenalty(self, t) + return ([[You hit your target doing %d%% damage. If your attack hits, the target is crippled for %d turns, losing %d%% accuracy and %d%% damage. + Hit chance improves with talent level and your Dexterity stat.]]): + format(100 * damage, duration, attackpen, damagepen) + end, +} diff --git a/game/modules/tome/data/talents/techniques/thuggery.lua b/game/modules/tome/data/talents/techniques/thuggery.lua new file mode 100644 index 0000000000000000000000000000000000000000..6b0f73dd8dd12d59b90d96a5d354a5031b8765cc --- /dev/null +++ b/game/modules/tome/data/talents/techniques/thuggery.lua @@ -0,0 +1,161 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009, 2010, 2011 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 + +local Map = require "engine.Map" + +newTalent{ + name = "Skullcracker", + type = {"technique/thuggery", 1}, + points = 5, + random_ego = "attack", + cooldown = 12, + stamina = 10, + tactical = { DISABLE = 2, ATTACK = 0.5 }, + require = cuns_req1, + requires_target = true, + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.2, 0.7) end, + getDuration = function(self, t) return 3 + math.ceil(self:getTalentLevel(t)) end, + action = function(self, t) + local tg = {type="hit", range=self:getTalentRange(t)} + local x, y, target = self:getTarget(tg) + if not x or not y or not target then return nil end + if math.floor(core.fov.distance(self.x, self.y, x, y)) > 1 then return nil end + local hitted = self:attackTarget(target, nil, t.getDamage(self, t), true) + + if hitted then + if target:checkHit(self:combatAttackDex(), target:combatPhysicalResist(), 0, 95, 5 - self:getTalentLevel(t) / 2) and target:canBe("stun") then + target:setEffect(target.EFF_STUNNED, t.getDuration(self, t), {}) + else + game.logSeen(target, "%s resists the stun!", target.name:capitalize()) + end + end + + return true + end, + info = function(self, t) + local damage = t.getDamage(self, t) + local duration = t.getDuration(self, t) + return ([[You hit your target doing %d%% damage, trying to stun it instead of damaging it. If your attack hits, the target is stunned for %d turns. + Stun chance increase with talent level and your Dexterity stat.]]): + format(100 * damage, duration) + end, +} + +newTalent{ + name = "Riot-born", + type = {"technique/thuggery", 2}, + mode = "passive", + points = 5, + require = cuns_req2, + getCriticalChance = function(self, t) return self:getTalentLevel(t) * 10 end, + info = function(self, t) + local chance = t.getCriticalChance(self, t) + return ([[Your quick wit gives you a big advantage against stunned targets; all your hits will have a %d%% greater chance of being critical.]]): + format(chance) + end, +} +newTalent{ + name = "Vicious Strikes", + type = {"technique/thuggery", 3}, + points = 5, + random_ego = "defensive", + cooldown = 10, + stamina = 50, + require = cuns_req3, + requires_target = true, + tactical = { DISABLE = 2 }, + getDuration = function(self, t) return 1 + self:getTalentLevel(t) end, + action = function(self, t) + local tg = {type="hit", range=self:getTalentRange(t)} + local x, y, target = self:getTarget(tg) + if not x or not y or not target then return nil end + if math.floor(core.fov.distance(self.x, self.y, x, y)) > 1 then return nil end + local tx, ty, sx, sy = target.x, target.y, self.x, self.y + local hitted = self:attackTarget(target, nil, 0, true) + + if hitted then + self:setEffect(self.EFF_EVASION, t.getDuration(self, t), {chance=50}) + + -- Displace + self.x = nil self.y = nil + self:move(tx, ty, true) + if not target.dead then + target.x = nil target.y = nil + target:move(sx, sy, true) + end + end + + return true + end, + info = function(self, t) + local duration = t.getDuration(self, t) + return ([[Using a series of tricks and maneuvers, you switch places with your target. + Switching places will confuse your foes, granting you evasion(50%%) for %d turns.]]): + format(duration) + end, +} + +newTalent{ + name = "Total Thuggery", + type = {"technique/thuggery", 4}, + points = 5, + random_ego = "attack", + cooldown = 25, + stamina = 30, + require = cuns_req4, + requires_target = true, + tactical = { DISABLE = 2, ATTACK = 2 }, + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.9, 1.4) end, + getDuration = function(self, t) return 3 + math.ceil(self:getTalentLevel(t)) end, + getAttackPenalty = function(self, t) return 10 + self:getTalentLevel(t) * 3 end, + getDamagePenalty = function(self, t) return 10 + self:getTalentLevel(t) * 4 end, + action = function(self, t) + local tg = {type="hit", range=self:getTalentRange(t)} + local x, y, target = self:getTarget(tg) + if not x or not y or not target then return nil end + if math.floor(core.fov.distance(self.x, self.y, x, y)) > 1 then return nil end + local hitted = self:attackTarget(target, nil, t.getDamage(self, t), true) + + if hitted then + if target:checkHit(self:combatAttackDex(), target:combatPhysicalResist(), 0, 95, 5 - self:getTalentLevel(t) / 2) then + local tw = target:getInven("MAINHAND") + if tw then + tw = tw[1] and tw[1].combat + end + tw = tw or target.combat + local atk = target:combatAttack(tw) * (t.getAttackPenalty(self, t)) / 100 + local dam = target:combatDamage(tw) * (t.getDamagePenalty(self, t)) / 100 + target:setEffect(target.EFF_CRIPPLE, t.getDuration(self, t), {atk=atk, dam=dam}) + else + game.logSeen(target, "%s is not crippled!", target.name:capitalize()) + end + end + + return true + end, + info = function(self, t) + local damage = t.getDamage(self, t) + local duration = t.getDuration(self, t) + local attackpen = t.getAttackPenalty(self, t) + local damagepen = t.getDamagePenalty(self, t) + return ([[You hit your target doing %d%% damage. If your attack hits, the target is crippled for %d turns, losing %d%% accuracy and %d%% damage. + Hit chance improves with talent level and your Dexterity stat.]]): + format(100 * damage, duration, attackpen, damagepen) + end, +} diff --git a/game/modules/tome/data/texts/unlock-rogue_marauder.lua b/game/modules/tome/data/texts/unlock-rogue_marauder.lua new file mode 100644 index 0000000000000000000000000000000000000000..0a25f0545bf5e7d06fdb3a136cc1afb344903101 --- /dev/null +++ b/game/modules/tome/data/texts/unlock-rogue_marauder.lua @@ -0,0 +1,31 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009, 2010, 2011 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 + +return "New Class: #LIGHT_GREEN#Marauder (Rogue)", +[[Some rogues live by strength rather than cunning, relying on vicious attacks instead of stealth and subterfuge. These bandits maraud the land, lightly armoured and wielding dual weapons, taking what they can by force. + +You have learned the value in causing sheer damage in combat and can now create characters with the #LIGHT_GREEN#Marauder class#WHITE#. + +Marauders are highly mobile rogues with a range of dextrous techniques and tactics at their disposal. Class features:#YELLOW# +- Move with ease around the battlefield, dancing around your foes and avoiding their attacks +- Wield dual weapons and unleash devastating techniques on your opponents +- Rely on pure thuggery to cripple your enemies before taking them down#WHITE# + +Marauders use stamina to fuel their techniques, which replenishes slowly over time. +]]