Skip to content
Snippets Groups Projects
Commit 0f193e62 authored by dg's avatar dg
Browse files

New rogue tree: cunning/scoundrel

Two new high level artifact daggers


git-svn-id: http://svn.net-core.org/repos/t-engine4@5422 51575b47-30f0-44d4-a5cc-537603b46e54
parent 3e0b6c0d
No related branches found
No related tags found
No related merge requests found
Showing
with 301 additions and 13 deletions
......@@ -43,7 +43,7 @@ function _M:init(t)
self.on_drag_end = t.on_drag_end
self.on_focus_change = t.on_focus_change
self.special_bg = t.special_bg
self._last_x, _last_y, self._last_ox, self._last_oy = 0, 0, 0, 0
if self.tabslist == nil and self.default_tabslist then
......@@ -62,11 +62,11 @@ function _M:generate()
self.uis = {}
if self.tabslist then
self.c_tabs = ImageList.new{width=self.w, height=36, tile_w=32, tile_h=32, padding=5, force_size=true, selection="ctrl-multiple", list=self.tabslist,
fct=function() self:generateList() end,
self.c_tabs = ImageList.new{width=self.w, height=36, tile_w=32, tile_h=32, padding=5, force_size=true, selection="ctrl-multiple", list=self.tabslist,
fct=function() self:generateList() end,
on_select=function(item, how) self:selectTab(item, how) end
}
self.c_tabs.no_keyboard_focus = true
if _M._last_tabs then
for _, l in ipairs(_M._last_tabs) do self.c_tabs.dlist[l[1]][l[2]].selected = true end
......@@ -74,36 +74,36 @@ function _M:generate()
self.c_tabs.dlist[1][1].selected = true
end
self.uis[#self.uis+1] = {x=0, y=0, ui=self.c_tabs}
self.c_tabs.on_focus_change = function(ui_self, status)
if status == true then
self.c_tabs.on_focus_change = function(ui_self, status)
if status == true then
local item = ui_self.dlist[ui_self.sel_j] and ui_self.dlist[ui_self.sel_j][ui_self.sel_i]
self.on_select(item, true)
end
end
end
local direct_draw= function(item, x, y, w, h, total_w, total_h, loffset_x, loffset_y, dest_area)
-- if there is object and is withing visible bounds
if item.object and total_h + h > loffset_y and total_h < loffset_y + dest_area.h then
if item.object and total_h + h > loffset_y and total_h < loffset_y + dest_area.h then
local clip_y_start, clip_y_end = 0, 0
-- if it started before visible area then compute its top clip
if total_h < loffset_y then
if total_h < loffset_y then
clip_y_start = loffset_y - total_h
end
-- if it ended after visible area then compute its bottom clip
if total_h + h > loffset_y + dest_area.h then
clip_y_end = total_h + h - loffset_y - dest_area.h
if total_h + h > loffset_y + dest_area.h then
clip_y_end = total_h + h - loffset_y - dest_area.h
end
-- get entity texture with everything it has i.e particles
local texture = item.object:getEntityFinalTexture(nil, h, h)
local one_by_tex_h = 1 / h
texture:toScreenPrecise(x, y, h, h - clip_y_start - clip_y_end, 0, 1, clip_y_start * one_by_tex_h, (h - clip_y_end) * one_by_tex_h)
return h, h, 0, 0, clip_y_start, clip_y_end
end
end
return 0, 0, 0, 0, 0, 0
end
self.c_inven = ListColumns.new{width=self.w, height=self.h - (self.c_tabs and self.c_tabs.h or 0), sortable=true, scrollbar=true, select_delay = 0.1, columns=self.columns or {
self.c_inven = ListColumns.new{width=self.w, height=self.h - (self.c_tabs and self.c_tabs.h or 0), sortable=true, scrollbar=true, columns=self.columns or {
{name="", width={33,"fixed"}, display_prop="char", sort="id"},
{name="", width={24,"fixed"}, display_prop="object", sort="sortname", direct_draw=direct_draw},
{name="Inventory", width=72, display_prop="name", sort="sortname"},
......
......@@ -628,6 +628,18 @@ function _M:attackTargetWith(target, weapon, damtype, mult, force_dam)
t.do_weakness(self, t, target)
end
-- Lacerating Strikes
if hitted and not target.dead and self:knowTalent(self.T_LACERATING_STRIKES) then
local t = self:getTalentFromId(self.T_LACERATING_STRIKES)
t.do_cut(self, t, target, dam)
end
-- Scoundrel's Strategies
if hitted and not target.dead and self:knowTalent(self.T_SCOUNDREL) and target:hasEffect(target.EFF_CUT) then
local t = self:getTalentFromId(self.T_SCOUNDREL)
t.do_scoundrel(self, t, target)
end
-- Special effect
if hitted and weapon and weapon.special_on_hit and weapon.special_on_hit.fct and (not target.dead or weapon.special_on_hit.on_kill) then
weapon.special_on_hit.fct(weapon, self, target)
......@@ -848,6 +860,10 @@ function _M:combatDefenseBase(fake)
d = d * (1 + self:getTalentLevel(self.T_MOBILE_DEFENCE) * 0.08)
end
if self:knowTalent(self.T_MISDIRECTION) then
d = d * (1 + self:getTalentLevel(self.T_MISDIRECTION) * (0.02 * (1 + self:getCun() / 85)))
end
return d
end
......@@ -1178,6 +1194,11 @@ function _M:physicalCrit(dam, weapon, target, atk, def, add_chance, crit_power_a
chance = 100
end
-- Scoundrel's Strategies
if self:attr("cut") and target:knowTalent(self.T_SCOUNDREL) then
chance = chance - (5 + (target:getTalentLevel(self.T_SCOUNDREL)*5))
end
if self:isTalentActive(self.T_STEALTH) and self:knowTalent(self.T_SHADOWSTRIKE) then
chance = 100
crit_power_add = crit_power_add + self:getTalentLevel(self.T_SHADOWSTRIKE) / 7
......
......@@ -64,6 +64,7 @@ newBirthDescriptor{
["cunning/dirty"]={true, 0.3},
["cunning/lethality"]={true, 0.3},
["cunning/survival"]={true, 0.3},
["cunning/scoundrel"]={true, 0.3},
},
unlockable_talents_types = {
["cunning/poisons"]={false, 0.3, "rogue_poisons"},
......
......@@ -384,3 +384,80 @@ newEntity{ base = "BASE_AMULET",
max_power = 60, power_regen = 1,
use_talent = { id = Talents.T_WORMHOLE, level = 2, power = 60 },
}
newEntity{ base = "BASE_KNIFE", define_as = "MANDIBLE_UNGOLMOR",
power_source = {nature=true},
unique = true,
name = "Mandible of Ungolmor", image = "object/artifact/dagger_life_drinker.png",
unided_name = "curved, serrated black dagger",
desc = [[This obsidian-crafted, curved blade is studded with the deadly fangs of the Ungolmor. It seems to drain light from the world around it.]],
level_range = {40, 50},
rarity = 270,
require = { stat = { cun=38 }, },
cost = 650,
material_level = 5,
combat = {
dam = 40,
apr = 12,
physcrit = 22,
dammod = {cun=0.30, str=0.35, dex=0.35},
convert_damage ={[DamageType.DARKNESS] = 30},
special_on_crit = {desc="inflicts pinning spydric poison upon the target", fct=function(combat, who, target)
if target:canBe("poison") then
local tg = {type="hit", range=1}
local x, y = who:getTarget(tg)
who:project(tg, target.x, target.y, engine.DamageType.SPYDRIC_POISON, {src=who, dam=30, dur=3})
end
end},
},
wielder = {
inc_damage={[DamageType.NATURE] = 30, [DamageType.DARKNESS] = 20,},
inc_stats = {[Stats.STAT_CUN] = 8, [Stats.STAT_DEX] = 4,},
combat_armor = 5,
combat_armor_hardiness = 5,
lite = -2,
},
max_power = 40, power_regen = 1,
use_talent = { id = Talents.T_CREEPING_DARKNESS, level = 3, power = 25 },
}
newEntity{ base = "BASE_KNIFE", define_as = "KINETIC_SPIKE",
power_source = {psionic=true},
unique = true,
name = "Kinetic Spike", image = "object/artifact/dagger_life_drinker.png",
unided_name = "bladeless hilt",
desc = [[A simple, rudely crafted stone hilt, this object manifests a blade of wavering, nearly invisible force, like a heat haze, as you grasp it. Despite its simple appearance, it is capable of shearing through solid granite, in the hands of those with the necessary mental fortitude to use it properly.]],
level_range = {42, 50},
rarity = 310,
require = { stat = { wil=42 }, },
cost = 450,
material_level = 5,
combat = {
dam = 38,
apr = 40, -- Hard to imagine much being harder to stop with armor.
physcrit = 10,
dammod = {wil=0.30, str=0.30, dex=0.40},
},
wielder = {
combat_atk = 8,
combat_dam = 15,
resists_pen = {[DamageType.PHYSICAL] = 30},
},
max_power = 10, power_regen = 1,
use_power = { name = "fires a bolt of kinetic force, doing 150%% weapon damage", power = 10,
use = function(self, who)
local tg = {type="bolt", range=8}
local x, y = who:getTarget(tg)
if not x or not y then return nil end
local _ _, x, y = who:canProject(tg, x, y)
local target = game.level.map(x, y, engine.Map.ACTOR)
if target then
who:attackTarget(target, engine.DamageType.PHYSICAL, 1.5, true)
game.logSeen(who, "The %s fires a bolt of kinetic force!", self:getName())
else
return
end
return {id=true, used=true}
end
},
}
game/modules/tome/data/gfx/talents/lacerating_strikes.png

2.38 KiB

game/modules/tome/data/gfx/talents/misdirection.png

3.05 KiB

game/modules/tome/data/gfx/talents/nimble_movements.png

2.11 KiB

game/modules/tome/data/gfx/talents/scoundrel.png

3.37 KiB

......@@ -30,6 +30,7 @@ newTalentType{ allow_random=true, type="cunning/shadow-magic", name = "shadow ma
newTalentType{ allow_random=true, type="cunning/ambush", name = "ambush", min_lev = 10, description = "Using darkness and a bit of magic you manipulate the shadows." }
newTalentType{ allow_random=true, type="cunning/survival", name = "survival", generic = true, description = "The knowledge of the dangers of the world, and how to best avoid them." }
newTalentType{ allow_random=true, type="cunning/tactical", name = "tactical", description = "Tactical combat abilities." }
newTalentType{ allow_random=true, type="cunning/scoundrel", name = "scoundrel", generic = true, description = "The use of ungentlemanly techniques." }
-- Generic requires for cunning based on talent level
cuns_req1 = {
......@@ -82,3 +83,4 @@ load("/data/talents/cunning/tactical.lua")
load("/data/talents/cunning/survival.lua")
load("/data/talents/cunning/shadow-magic.lua")
load("/data/talents/cunning/ambush.lua")
load("/data/talents/cunning/scoundrel.lua")
-- ToME - Tales of Maj'Eyal
-- Copyright (C) 2009, 2010, 2011, 2012 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 = "Lacerating Strikes",
type = {"cunning/scoundrel", 1},
mode = "passive",
points = 5,
require = cuns_req1,
mode = "passive",
do_cut = function(self, t, target, dam)
if target:canBe("cut") and rng.percent(10+(self:getTalentLevel(t)*10)) then
dam = dam * self:combatTalentWeaponDamage(t, 0.15, 0.35)
target:setEffect(target.EFF_CUT, 10, {src=self, power=(dam / 10)})
end
end,
info = function(self, t)
return ([[Rend your foe with every attack you do. All attacks now have a %d%% chance of inflicting an additional %d%% of your attack's damage in Bleeding damage, divided over ten turns.]]):
format(10+(self:getTalentLevel(t)*10),100 * self:combatTalentWeaponDamage(t, 0.15, 0.35))
end,
}
newTalent{
name = "Scoundrel's Strategies", short_name = "SCOUNDREL",
type = {"cunning/scoundrel", 2},
require = cuns_req2,
mode = "passive",
points = 5,
getDuration = function(self, t) return 3 + math.ceil(self:getTalentLevel(t)/2) end,
getMovePenalty = function(self, t) return (5 + self:combatTalentStatDamage(t, "cun", 10, 30)) / 100 end,
getAttackPenalty = function(self, t) return 5 + self:combatTalentStatDamage(t, "cun", 5, 20) end,
getWillPenalty = function(self, t) return 5 + self:combatTalentStatDamage(t, "cun", 5, 20) end,
getCunPenalty = function(self, t) return 5 + self:combatTalentStatDamage(t, "cun", 5, 20) end,
do_scoundrel = function(self, t, target)
if not rng.percent(5+(self:getTalentLevel(t)*3)) then return end
if rng.percent(50) then
if target:hasEffect(target.EFF_DISABLE) then return end
target:setEffect(target.EFF_DISABLE, t.getDuration(self, t), {speed=t.getMovePenalty(self, t), atk=t.getAttackPenalty(self, t), apply_power=self:combatAttack()})
else
if target:hasEffect(target.EFF_ANGUISH) then return end
target:setEffect(target.EFF_ANGUISH, t.getDuration(self, t), {will=t.getWillPenalty(self, t), cun=t.getCunPenalty(self, t), apply_power=self:combatAttack()})
end
end,
info = function(self, t)
local duration = t.getDuration(self, t)
local move = t.getMovePenalty(self, t)
local attack = t.getAttackPenalty(self, t)
local will = t.getWillPenalty(self, t)
local cun = t.getCunPenalty(self, t)
return ([[Learn to take advantage of your enemy's pain.
If your enemy is bleeding and attempts to attack you, their critical hit rate is reduced by %d%%, as their wounds make them more predictable.
If you attack a bleeding enemy, there is a %d%% chance that, for %d turns, they are disabled as you take advantage of openings (reducing their movement speed by %d%% and accuracy by %d) or anguished as you strike their painful wounds (reducing their willpower by %d and their cunning by %d).
The statistical reductions will increase with the Cunning stat.
]]):format(5+(self:getTalentLevel(t)*5),5+(self:getTalentLevel(t)*3),duration,move * 100,attack,will,cun)
end,
}
newTalent{
name = "Nimble Movements",
type = {"cunning/scoundrel",3},
message = "@Source@ dashes quickly!",
no_break_stealth = true,
require = cuns_req3,
points = 5,
random_ego = "attack",
cooldown = function(self, t) return math.floor(35 - self:getTalentLevel(t) * 3.5) end,
tactical = { CLOSEIN = 3 },
requires_target = true,
range = function(self, t) return math.floor(6 + self:getTalentLevel(t) * 0.6) end,
action = function(self, t)
if self:attr("never_move") then game.logPlayer(self, "You can not do that currently.") return end
local tg = {type="hit", range=self:getTalentRange(t)}
local x, y, target = self:getTarget(tg)
if not x or not y then return nil end
if core.fov.distance(self.x, self.y, x, y) > self:getTalentRange(t) then return nil end
local block_actor = function(_, bx, by) return game.level.map:checkEntity(bx, by, Map.TERRAIN, "block_move", self) end
local l = self:lineFOV(x, y, block_actor)
local lx, ly, is_corner_blocked = l:step()
if is_corner_blocked or game.level.map:checkAllEntities(lx, ly, "block_move", self) then
game.logPlayer(self, "You cannot dash through that!")
return
end
local tx, ty = lx, ly
lx, ly, is_corner_blocked = l:step()
while lx and ly do
if is_corner_blocked or game.level.map:checkAllEntities(lx, ly, "block_move", self) then break end
tx, ty = lx, ly
lx, ly, is_corner_blocked = l:step()
end
local ox, oy = self.x, self.y
self:move(tx, ty, true)
if config.settings.tome.smooth_move > 0 then
self:resetMoveAnim()
self:setMoveAnim(ox, oy, 8, 5)
end
return true
end,
info = function(self, t)
return ([[Quickly and quietly dash your way to the target square, if it is not blocked by enemies or obstacles. This talent will not break Stealth.]])
end,
}
newTalent{
name = "Misdirection",
type = {"cunning/scoundrel", 4},
mode = "passive",
points = 5,
require = cuns_req4,
mode = "passive",
on_learn = function(self, t)
self.projectile_evasion = (self.projectile_evasion or 0) + 3
self.projectile_evasion_spread = (self.projectile_evasion_spread or 0) + 1
end,
on_unlearn = function(self, t)
self.projectile_evasion = (self.projectile_evasion or 0) - 3
self.projectile_evasion_spread = (self.projectile_evasion_spread or 0) - 1
end,
info = function(self, t)
return ([[Your abilities sowing confusion and chaos have reached their peak. Now even your most simple moves confuse your enemies, rendering their offense less effective.
Your defense increases by %d%%.
Your bonus percent to defense will increase with Cunning.]]):
format(self:getTalentLevel(self.T_MISDIRECTION) * (0.02 * (1 + self:getCun() / 85) *100),self:getTalentLevelRaw(t) * 3 ,self:getTalentLevelRaw(t) * 1)
end,
}
......@@ -1841,3 +1841,43 @@ newEffect{
self:removeParticles(eff.particle)
end,
}
newEffect{
name = "DISABLE", image = "talents/cripple.png",
desc = "Disable",
long_desc = function(self, eff) return ("The target is disabled, reducing movement speed by %d%% and physical power by %d."):format(eff.speed * 100, eff.atk) end,
type = "physical",
subtype = { wound=true },
status = "detrimental",
parameters = { speed=0.15, atk=10 },
on_gain = function(self, err) return "#Target# is disabled.", "+Disabled" end,
on_lose = function(self, err) return "#Target# is not disabled anymore.", "-Disabled" end,
activate = function(self, eff)
eff.speedid = self:addTemporaryValue("movement_speed", -eff.speed)
eff.atkid = self:addTemporaryValue("combat_atk", -eff.atk)
end,
deactivate = function(self, eff)
self:removeTemporaryValue("movement_speed", eff.speedid)
self:removeTemporaryValue("combat_atk", eff.atk)
end,
}
newEffect{
name = "ANGUISH", image = "talents/agony.png",
desc = "Anguish",
long_desc = function(self, eff) return ("The target is in extreme anguish, preventing them from making tactical decisions, and reducing Willpower by %d and Cunning by %d."):format(eff.will, eff.cun) end,
type = "physical",
subtype = { wound=true },
status = "detrimental",
parameters = { will=5, cun=5 },
on_gain = function(self, err) return "#Target# is in anguish.", "+Anguish" end,
on_lose = function(self, err) return "#Target# is no longer in anguish.", "-Anguish" end,
activate = function(self, eff)
eff.sid = self:addTemporaryValue("inc_stats", {[Stats.STAT_WIL]=-eff.will, [Stats.STAT_CUN]=-eff.cun})
-- if self.ai_state then eff.ai = self:addTemporaryValue("ai_state", {forbid_tactical=1}) end
end,
deactivate = function(self, eff)
self:removeTemporaryValue("inc_stats", eff.sid)
-- if eff.ai then self:removeTemporaryValue("ai_state", eff.ai) end
end,
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment