PK
gC data/UT A{RDQux d PK
Cbw3 3 data/timed_effects.luaUT Rΰ{Rux d -- ToME - Tales of Maj'Eyal:
-- Copyright (C) 2009, 2010, 2011, 2012, 2013 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 .
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
local Stats = require "engine.interface.ActorStats"
local Particles = require "engine.Particles"
local Entity = require "engine.Entity"
local Chat = require "engine.Chat"
local Map = require "engine.Map"
local Level = require "engine.Level"
newEffect{
name = "STONE_VINE",
desc = "Stone Vine",
long_desc = function(self, eff) return ("A living stone vine holds the target in place, inflicting %0.1f Physical%s damage per turn."):format(eff.dam, eff.arcanedam and (" and %0.1f Arcane"):format(eff.arcanedam) or "") end,
type = "physical",
subtype = { earth=true, pin=true },
status = "detrimental",
parameters = { dam=10 },
on_gain = function(self, err) return "#Target# is seized by a stone vine.", "+Stone Vine" end,
on_lose = function(self, err) return "#Target# is free from the stone vine.", "-Stone Vine" end,
activate = function(self, eff)
eff.last_x = eff.src.x
eff.last_y = eff.src.y
eff.tmpid = self:addTemporaryValue("never_move", 1)
eff.particle = self:addParticles(Particles.new("stonevine", 1, {tx=eff.src.x-self.x, ty=eff.src.y-self.y}))
end,
deactivate = function(self, eff)
self:removeTemporaryValue("never_move", eff.tmpid)
self:removeParticles(eff.particle)
end,
on_timeout = function(self, eff)
local severed = false
local src = eff.src or self
if core.fov.distance(self.x, self.y, src.x, src.y) >= eff.free or src.dead or not game.level:hasEntity(src) then severed = true end
if rng.percent(eff.free_chance) then severed = true end
self:removeParticles(eff.particle)
eff.particle = self:addParticles(Particles.new("stonevine", 1, {tx=eff.src.x-self.x, ty=eff.src.y-self.y}))
if severed then
return true
else
DamageType:get(DamageType.PHYSICAL).projector(src, self.x, self.y, DamageType.PHYSICAL, eff.dam)
if eff.arcanedam and src:knowTalent(src.T_ELDRITCH_VINES) then
src:incEquilibrium(-src:callTalent(src.T_ELDRITCH_VINES, "getEquilibrium"))
src:incMana(src:callTalent(src.T_ELDRITCH_VINES, "getMana"))
DamageType:get(DamageType.ARCANE).projector(src, self.x, self.y, DamageType.ARCANE, eff.arcanedam)
end
end
eff.last_x = src.x
eff.last_y = src.y
end,
}
newEffect{
name = "DWARVEN_RESILIENCE", image = "talents/dwarf_resilience.png",
desc = "Dwarven Resilience",
long_desc = function(self, eff)
if eff.mid_ac then
return ("The target's skin turns to stone, granting %d armour, %d physical save and %d spell save. Also applies %d armour to all non-physical damage."):format(eff.armor, eff.physical, eff.spell, eff.mid_ac)
else
return ("The target's skin turns to stone, granting %d armour, %d physical save and %d spell save."):format(eff.armor, eff.physical, eff.spell)
end
end,
type = "physical",
subtype = { earth=true },
status = "beneficial",
parameters = { armor=10, spell=10, physical=10 },
on_gain = function(self, err) return "#Target#'s skin turns to stone." end,
on_lose = function(self, err) return "#Target#'s skin returns to normal." end,
activate = function(self, eff)
eff.aid = self:addTemporaryValue("combat_armor", eff.armor)
eff.pid = self:addTemporaryValue("combat_physresist", eff.physical)
eff.sid = self:addTemporaryValue("combat_spellresist", eff.spell)
if self:knowTalent(self.T_STONE_FORTRESS) then
local ac = self:combatArmor() * self:callTalent(self.T_STONE_FORTRESS, "getPercent")/ 100
eff.mid_ac = ac
eff.mid = self:addTemporaryValue("flat_damage_armor", {all=ac, [DamageType.PHYSICAL]=-ac})
end
end,
deactivate = function(self, eff)
self:removeTemporaryValue("combat_armor", eff.aid)
self:removeTemporaryValue("combat_physresist", eff.pid)
self:removeTemporaryValue("combat_spellresist", eff.sid)
if eff.mid then self:removeTemporaryValue("flat_damage_armor", eff.mid) end
end,
}
newEffect{
name = "ELDRITCH_STONE", image = "talents/eldritch_stone.png",
desc = "Eldritch Stone Shield",
long_desc = function(self, eff)
return ("The target is surrounded by a stone shield absorbing %d/%d damage. When the shield is removed, it will explode for up to %d (currently %d) Arcane damage in a radius %d."):
format(eff.power, eff.max, eff.maxdam, math.min(eff.maxdam, self:getEquilibrium() - self:getMinEquilibrium()), eff.radius)
end,
type = "magical",
subtype = { earth=true, shield=true },
status = "beneficial",
parameters = { power=100, radius=3 , maxdam=500},
on_gain = function(self, err) return "#Target# is encased in a stone shield." end,
on_lose = function(self, err)
return ("The stone shield around #Target# %s"):format(self:getEquilibrium() - self:getMinEquilibrium() > 0 and "explodes!" or "crumbles.")
end,
on_aegis = function(self, eff, aegis)
eff.power = eff.power + eff.max * aegis / 100
if core.shader.active(4) then
self:removeParticles(eff.particle)
eff.particle = self:addParticles(Particles.new("shader_shield", 1, {size_factor=1.3, img="runicshield_stonewarden"}, {type="runicshield", shieldIntensity=0.2, oscillationSpeed=4, ellipsoidalFactor=1.3, time_factor=5000, auraColor={0x61/255, 0xff/255, 0x6a/255, 1}}))
end
end,
damage_feedback = function(self, eff, src, value)
if eff.particle and eff.particle._shader and eff.particle._shader.shad and src and src.x and src.y then
local r = -rng.float(0.2, 0.4)
local a = math.atan2(src.y - self.y, src.x - self.x)
eff.particle._shader:setUniform("impact", {math.cos(a) * r, math.sin(a) * r})
eff.particle._shader:setUniform("impact_tick", core.game.getTime())
end
end,
activate = function(self, eff)
if self:attr("shield_factor") then eff.power = eff.power * (100 + self:attr("shield_factor")) / 100 end
if self:attr("shield_dur") then eff.dur = eff.dur + self:attr("shield_dur") end
eff.max = eff.power
if core.shader.active(4) then
eff.particle = self:addParticles(Particles.new("shader_shield", 1, {size_factor=1.3, img="runicshield_stonewarden"}, {type="runicshield", shieldIntensity=0.2, oscillationSpeed=4, ellipsoidalFactor=1.3, time_factor=9000, auraColor={0x61/255, 0xff/255, 0x6a/255, 0}}))
else
eff.particle = self:addParticles(Particles.new("damage_shield", 1))
end
end,
deactivate = function(self, eff)
self:removeParticles(eff.particle)
local equi = self:getEquilibrium() - self:getMinEquilibrium()
if equi > 0 then
self:incMana(equi)
self:incEquilibrium(-equi)
self:project({type="ball", radius=eff.radius, friendlyfire=false}, self.x, self.y, DamageType.ARCANE, math.min(equi, eff.maxdam))
game.level.map:particleEmitter(self.x, self.y, eff.radius, "eldricth_stone_explo", {radius=eff.radius})
end
end,
}
newEffect{
name = "STONE_LINK_SOURCE", image = "talents/stone_link.png",
desc = "Stone Link",
long_desc = function(self, eff) return ("The target protects all those around it in radius %d by redirecting all damage against them to itself."):format(eff.rad) end,
type = "physical",
subtype = { earth=true, shield=true },
status = "beneficial",
parameters = { rad=3 },
on_gain = function(self, err) return ("#Target# begins protecting %s friends with a stone shield."):format(string.his_her(self)), "+Stone Link" end,
on_lose = function(self, err) return "#Target# is no longer protecting anyone.", "-Stone Link" end,
activate = function(self, eff)
if core.shader.active() then
eff.particle = self:addParticles(Particles.new("shader_shield", 1, {size_factor=eff.rad}, {type="shield", time_factor=4000, color={0.7, 0.4, 0.3}}))
else
eff.particle = self:addParticles(Particles.new("eldritch_stone", 1, {size_factor=eff.rad}))
end
end,
deactivate = function(self, eff)
self:removeParticles(eff.particle)
end,
on_timeout = function(self, eff)
self:project({type="ball", radius=eff.rad, selffire=false}, self.x, self.y, function(px, py)
local target = game.level.map(px, py, Map.ACTOR)
if not target or self:reactionToward(target) < 0 then return end
target:setEffect(target.EFF_STONE_LINK, 2, {src=self})
end)
end,
}
newEffect{
name = "STONE_LINK", image = "talents/stone_link.png",
desc = "Stone Link",
long_desc = function(self, eff) return ("The target is protected by %s, redirecting all damage to it."):format(eff.src.name) end,
type = "physical",
subtype = { earth=true, shield=true },
status = "beneficial",
parameters = { },
on_gain = function(self, err) return "#Target# is protected by a stone shield.", "+Stone Link" end,
on_lose = function(self, err) return "#Target# is less protected.", "-Stone Link" end,
activate = function(self, eff)
end,
deactivate = function(self, eff)
end,
}
newEffect{
name = "DEEPROCK_FORM", image = "talents/deeprock_form.png",
desc = "Deeprock Form",
long_desc = function(self, eff)
local xs = ""
if eff.arcaneDam and eff.arcanePen then
xs = xs..(", +%d%% Arcane damage and +%d%% Arcane damage penetration,"):format(eff.arcaneDam, eff.arcanePen)
end
if eff.natureDam and eff.naturePen then
xs = (", +%d%% Nature damage and +%d%% Nature damage penetration"):format(eff.natureDam, eff.naturePen)..xs
end
if eff.immune then
xs = (", %d%% bleeding, poison, disease, and stun immunity"):format(eff.immune*100)..xs
end
return ("The target has turned into a huge deeprock elemental. It gains 2 size categories%s and +%d%% Physical damage and +%d%% Physical damage penetration.%s"):format(xs, eff.dam, eff.pen, eff.useResist and " In addition, it uses its physical resistance against all damage." or "")
end,
type = "magical",
subtype = { earth=true, elemental=true },
status = "beneficial",
parameters = { dam = 10, pen = 5, armor = 5},
on_gain = function(self, err) return "#Target# is imbued by the power of the Stone.", "+Deeprock Form" end,
on_lose = function(self, err) return "#Target# is abandoned by the Stone's power.", "-Deeprock Form" end,
activate = function(self, eff)
if self:knowTalent(self.T_VOLCANIC_ROCK) then
self:learnTalent(self.T_VOLCANO, true, self:getTalentLevelRaw(self.T_VOLCANIC_ROCK) * 2, {no_unlearn=true})
self:effectTemporaryValue(eff, "talent_cd_reduction", {[self.T_VOLCANO] = 15})
local t = self:getTalentFromId(self.T_VOLCANIC_ROCK)
eff.arcaneDam, eff.arcanePen = t.getDam(self, t), t.getPen(self, t)
self:effectTemporaryValue(eff, "inc_damage", {[DamageType.ARCANE] = eff.arcaneDam})
self:effectTemporaryValue(eff, "resists_pen", {[DamageType.ARCANE] = eff.arcanePen})
end
if self:knowTalent(self.T_BOULDER_ROCK) then
self:learnTalent(self.T_THROW_BOULDER, true, self:getTalentLevelRaw(self.T_BOULDER_ROCK) * 2, {no_unlearn=true})
local t = self:getTalentFromId(self.T_BOULDER_ROCK)
eff.natureDam, eff.naturePen = t.getDam(self, t), t.getPen(self, t)
self:effectTemporaryValue(eff, "inc_damage", {[DamageType.NATURE] = eff.natureDam})
self:effectTemporaryValue(eff, "resists_pen", {[DamageType.NATURE] = eff.naturePen})
end
if self:knowTalent(self.T_MOUNTAINHEWN) then
local t = self:getTalentFromId(self.T_MOUNTAINHEWN)
if self:getTalentLevel(self.T_MOUNTAINHEWN) >= 5 then
eff.useResist = true
self:effectTemporaryValue(eff, "force_use_resist", DamageType.PHYSICAL)
end
eff.immune = t.getImmune(self, t)
self:effectTemporaryValue(eff, "cut_immune", eff.immune)
self:effectTemporaryValue(eff, "poison_immune", eff.immune)
self:effectTemporaryValue(eff, "disease_immune", eff.immune)
self:effectTemporaryValue(eff, "stun_immune", eff.immune)
end
self:effectTemporaryValue(eff, "inc_damage", {[DamageType.PHYSICAL] = eff.dam})
self:effectTemporaryValue(eff, "resists_pen", {[DamageType.PHYSICAL] = eff.pen})
self:effectTemporaryValue(eff, "combat_armor", eff.armor)
self:effectTemporaryValue(eff, "size_category", 2)
self.replace_display = mod.class.Actor.new{
image = "invis.png",
add_displays = {mod.class.Actor.new{
image = "npc/elemental_xorn_harkor_zun.png", display_y=-1, display_h=2,
shader = "shadow_simulacrum",
shader_args = { color = {0.6, 0.5, 0.2}, base = 0.95, time_factor = 1500 },
}},
}
self:removeAllMOs()
game.level.map:updateMap(self.x, self.y)
end,
deactivate = function(self, eff)
if self:knowTalent(self.T_VOLCANIC_ROCK) then self:unlearnTalent(self.T_VOLCANO, self:getTalentLevelRaw(self.T_VOLCANIC_ROCK) * 2) end
if self:knowTalent(self.T_BOULDER_ROCK) then self:unlearnTalent(self.T_THROW_BOULDER, self:getTalentLevelRaw(self.T_BOULDER_ROCK) * 2) end
self.replace_display = nil
self:removeAllMOs()
game.level.map:updateMap(self.x, self.y)
end,
}
PK
TB
data/talents/UT DQDQux d PK
gC data/talents/gifts/UT K{RDQux d PK
!gC̶ $ data/talents/gifts/earthen-power.luaUT ΰ{Rΰ{Rux d -- ToME - Tales of Maj'Eyal
-- Copyright (C) 2009, 2010, 2011, 2012, 2013 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 .
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
newTalent{
name = "Stoneshield",
type = {"wild-gift/earthen-power", 1},
mode = "passive",
require = gifts_req1,
points = 5,
no_unlearn_last = true,
on_learn = function(self, t)
self:attr("show_shield_combat", 1)
end,
on_unlearn = function(self, t)
self:attr("show_shield_combat", -1)
end,
getValues = function(self, t)
return
self:combatTalentLimit(t, 1, 0.07, 0.15),
self:combatTalentScale(t, 6, 10),
self:combatTalentLimit(t, 0.5, 0.067, 0.185),
self:combatTalentScale(t, 5, 9, "log")
end,
getDamage = function(self, t) return self:getTalentLevel(t) * 10 end,
getPercentInc = function(self, t) return math.sqrt(self:getTalentLevel(t) / 5) / 2 end,
info = function(self, t)
local m, mm, e, em = t.getValues(self, t)
local damage = t.getDamage(self, t)
local inc = t.getPercentInc(self, t)
return ([[The first time you take damage each turn, you regenerate %d%% of the damage dealt as mana (up to a maximum of %0.2f) and %d%% as equilibrium (up to %0.2f).
Increases Physical Power by %d, increases damage done with shields by %d%%, and allows you to dual-wield shields.
Also, all of your melee attacks will perform a shield bash in addition to their normal effects.]]):format(100 * m, mm, 100 * e, em, damage, inc*100)
end,
}
newTalent{
name = "Stone Fortress",
type = {"wild-gift/earthen-power", 2},
require = gifts_req2,
points = 5,
mode = "passive",
-- getPercent = function(self, t) return self:combatTalentLimit(t, 200, 60, 100) end, -- base damage version Limit < 200%
getPercent = function(self, t) return self:combatTalentScale(t, 60, 100, "log") end,
ReduceDamage = function(self, t, dam, src) -- unused: called by default projector in data.damage_types.lua
local effArmor = self:combatArmor()*t.getPercent(self, t)/100
-- Apply attacker base APR (but not for melee attacks which apply it separately)
if not (src.turn_procs and src.turn_procs.weapon_type) and src.combatAPR then effArmor = effArmor - src:combatAPR() end
return math.max(0, dam - effArmor)
end,
info = function(self, t)
return ([[When you use your Resilience of the Dwarves racial power your skin becomes so tough that it even absorbs damage from non physical attacks.
Non physical damage is reduced by %d%% of your total armour value (ignoring hardiness).]]):
format(t.getPercent(self, t))
end,
}
newTalent{
name = "Shards",
type = {"wild-gift/earthen-power", 3},
require = gifts_req3,
mode = "sustained",
points = 5,
sustain_equilibrium = 15,
cooldown = 30,
tactical = { BUFF = 2 },
activate = function(self, t)
return {}
end,
deactivate = function(self, t, p)
return true
end,
info = function(self, t)
return ([[Sharp shards of stone grow from your shields.
When you are hit in melee, you will get a free attack against the attacker with the shards doing %d%% shield damage (as Nature).
This effect can only happen once per turn.]]):
format(self:combatTalentWeaponDamage(t, 0.4, 1) * 100)
end,
}
newTalent{
name = "Eldritch Stone",
type = {"wild-gift/earthen-power", 4},
require = gifts_req4,
points = 5,
equilibrium = 10,
cooldown = 20,
tactical = { DEFEND = 2, EQUILIBRIUM=1, MANA=1 },
radius = function(self, t) return math.floor(self:combatTalentScale(t, 2.5, 4.5)) end,
getPower = function(self, t) return 70 + self:combatTalentStatDamage(t, "wil", 5, 400) end,
manaRegen = function(self, t) return self:combatTalentScale(t, 0.25, 1, 0.75) end,
maxDamage = function(self, t) return self:combatTalentScale(t, 150, 500) end,
passives = function(self, t, p)
self:talentTemporaryValue(p, "mana_regen_on_rest", t.manaRegen(self, t))
end,
action = function(self, t)
self:setEffect(self.EFF_ELDRITCH_STONE, 7, {power=t.getPower(self, t), radius=self:getTalentRadius(t), maxdam = t.maxDamage(self, t)})
game:playSoundNear(self, "talents/stone")
return true
end,
info = function(self, t)
local power = t.getPower(self, t)
local radius = self:getTalentRadius(t)
return ([[Creates a shield of impenetrable stone around you for 7 turns, absorbing up to %d damage.
Your equilibrium will increase by twice the damage absorbed.
When the effect ends, all equilibrium above minimum will be converted to mana in a storm of arcane energy.
The storm inflicts Arcane damage equal to the converted equilibrium (maximum %d) against everyone around you in a radius %d.
Also while resting you will passively regenerate %0.2f mana each turn.
The shield strength will increase with Willpower]]):format(power, t.maxDamage(self, t), radius, t.manaRegen(self, t))
end,
}
PK
gCgk $ data/talents/gifts/earthen-vines.luaUT {Rΰ{Rux d -- ToME - Tales of Maj'Eyal
-- Copyright (C) 2009, 2010, 2011, 2012, 2013 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 .
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
newTalent{
name = "Stone Vines",
type = {"wild-gift/earthen-vines", 1},
require = gifts_req1,
points = 5,
mode = "sustained",
sustain_equilibrium = 15,
cooldown = 10,
no_energy = true,
tactical = { ATTACK = { PHYSICAL = 2 }, BUFF = 2, DISABLE = { pin = 2 } },
radius = function(self, t) return math.floor(self:combatTalentScale(t, 4.5, 6.5)) end,
getValues = function(self, t) return math.floor(self:combatTalentScale(t, 5, 9)), self:combatTalentStatDamage(t, "wil", 3, 50), self:knowTalent(self.T_ELDRITCH_VINES) and self:callTalent(self.T_ELDRITCH_VINES, "getDamage") or nil end,
do_vines = function(self, t)
local p = self:isTalentActive(t.id)
local rad = self:getTalentRadius(t)
local tgts = {}
local grids = core.fov.circle_grids(self.x, self.y, rad, true)
for x, yy in pairs(grids) do for y, _ in pairs(grids[x]) do
local a = game.level.map(x, y, Map.ACTOR)
if a and self:reactionToward(a) < 0 and not a:hasEffect(a.EFF_STONE_VINE) then
tgts[#tgts+1] = a
end
end end
if #tgts <= 0 then return end
-- Randomly take targets
local tg = {type="hit", range=self:getTalentRange(t), talent=t}
local a, id = rng.table(tgts)
local hit, chance = a:checkHit(self:combatTalentStatDamage(t, "wil", 5, 110), a:combatPhysicalResist(), 0, 95, 5)
if a:canBe("pin") and hit then
local turns, dam, arcanedam = t.getValues(self, t)
a:setEffect(a.EFF_STONE_VINE, turns, {dam=dam, arcanedam = arcanedam, src=self, free=rad+4, free_chance=100-chance})
game:playSoundNear(self, "talents/stone")
end
end,
activate = function(self, t)
return {
movid = self:addTemporaryValue("movement_speed", -0.5),
particle = self:addParticles(Particles.new("stonevine_static", 1, {})),
}
end,
deactivate = function(self, t, p)
self:removeTemporaryValue("movement_speed", p.movid)
self:removeParticles(p.particle)
return true
end,
info = function(self, t)
local rad = self:getTalentRadius(t)
local turns, dam, arcanedam = t.getValues(self, t)
local xs = arcanedam and (" and %0.1f Arcane"):format(damDesc(self, DamageType.ARCANE, arcanedam)) or ""
return ([[From the ground around you, you form living stone vines extending from your feet.
Each turn, the vines will attempt to seize a random target within radius %d.
Affected creatures are pinned to the ground and take %0.1f Physical%s damage each turn for %d turns.
A creature entangled by the vines will have a chance to break free each turn, and will automatically succeed if it is more than %d grids away from you.
The chance to affect targets and damage increase with talent level and Willpower.
While earthen vines are active your movement speed is reduced by 50%%.]]):
format(rad, damDesc(self, DamageType.PHYSICAL, dam), xs, turns, rad+4)
end,
}
newTalent{
name = "Eldritch Vines",
type = {"wild-gift/earthen-vines", 2},
require = gifts_req2,
points = 5,
mode = "passive",
-- called by "STONE_VINE" effect
getDamage = function(self, t) return self:combatTalentStatDamage(t, "wil", 3, 50) end,
getEquilibrium = function(self, t) return self:combatTalentScale(t, 0.3, 1.25, "log", 0, 3) end,
getMana = function(self, t) return self:combatTalentScale(t, 0.4, 1.67) end,
info = function(self, t)
return ([[Each time one of your stone vines deals damage to a creature it will restore %0.1f equilibrium and %0.1f mana.
Your vines also become infused with eldritch energies, dealing an additional %0.1f arcane damage.]])
:format(t.getEquilibrium(self, t), t.getMana(self, t), damDesc(self, DamageType.ARCANE, t.getDamage(self, t)))
end,
}
newTalent{
name = "Rockwalk",
type = {"wild-gift/earthen-vines", 3},
require = gifts_req3,
points = 5,
equilibrium = 15,
cooldown = function(self, t) return math.ceil(self:combatTalentLimit(t, 0, 11, 7)) end,
requires_target = true,
range = 20,
tactical = { HEAL = 2, CLOSEIN = 2 },
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 not target:hasEffect(target.EFF_STONE_VINE) then return nil end
self:attr("allow_on_heal", 1)
self:heal(100 + self:combatTalentStatDamage(t, "wil", 40, 630), t)
self:attr("allow_on_heal", -1)
if core.shader.active(4) then
self:addParticles(Particles.new("shader_shield_temp", 1, {toback=true , size_factor=1.5, y=-0.3, img="healarcane", life=25}, {type="healing", time_factor=2000, beamsCount=20, noup=2.0, beamColor1={0x8e/255, 0x2f/255, 0xbb/255, 1}, beamColor2={0x90/255, 0xff/255, 0x95/255, 1}, circleDescendSpeed=4}))
self:addParticles(Particles.new("shader_shield_temp", 1, {toback=false, size_factor=1.5, y=-0.3, img="healarcane", life=25}, {type="healing", time_factor=2000, beamsCount=20, noup=1.0, beamColor1={0x8e/255, 0x2f/255, 0xbb/255, 1}, beamColor2={0x90/255, 0xff/255, 0x95/255, 1}, circleDescendSpeed=4}))
end
local tx, ty = util.findFreeGrid(x, y, 2, true, {[Map.ACTOR]=true})
if tx and ty then
local ox, oy = self.x, self.y
self:attr("preserve_body_of_stone", 1)
self:move(tx, ty, true)
self:attr("preserve_body_of_stone", -1)
if config.settings.tome.smooth_move > 0 then
self:resetMoveAnim()
self:setMoveAnim(ox, oy, 8, 5)
end
end
return true
end,
info = function(self, t)
return ([[Merge with one of your stone vines, traversing it to emerge near an entangled creature (maximum range %d).
Merging with the stone is beneficial for you, healing %0.2f life (increases with Willpower).
This will not break Body of Stone.]])
:format(self:getTalentRange(t) ,100 + self:combatTalentStatDamage(t, "wil", 40, 630))
end,
}
newTalent{
name = "Rockswallow",
type = {"wild-gift/earthen-vines", 4},
require = gifts_req4,
points = 5,
equilibrium = 15,
cooldown = function(self, t) return math.ceil(self:combatTalentLimit(t, 0, 11, 7)) end,
requires_target = true,
range = 20,
tactical = { ATTACK = { PHYSICAL = 2 }, CLOSEIN = 2 },
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 not target:hasEffect(target.EFF_STONE_VINE) then return nil end
DamageType:get(DamageType.PHYSICAL).projector(self, target.x, target.y, DamageType.PHYSICAL, 80 + self:combatTalentStatDamage(t, "wil", 40, 330))
if target.dead then return true end
local tx, ty = util.findFreeGrid(self.x, self.y, 2, true, {[Map.ACTOR]=true})
if tx and ty then
local ox, oy = target.x, target.y
target:move(tx, ty, true)
if config.settings.tome.smooth_move > 0 then
target:resetMoveAnim()
target:setMoveAnim(ox, oy, 8, 5)
end
end
return true
end,
info = function(self, t)
return ([[Merge your target (within range %d) with one of your stone vines that has seized it, forcing it to traverse the vine and reappear near you.
Merging with the stone is detrimental for the target, dealing %0.1f physical damage.
The damage will increases with your Willpower.]])
:format(self:getTalentRange(t), 80 + self:combatTalentStatDamage(t, "wil", 40, 330))
end,
}
PK
gCFu: : % data/talents/gifts/dwarven-nature.luaUT K{RK{Rux d -- ToME - Tales of Maj'Eyal
-- Copyright (C) 2009, 2010, 2011, 2012, 2013 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 .
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
newTalent{
name = "Earthen Missiles", short_name = "DWARVEN_HALF_EARTHEN_MISSILES",
type = {"spell/other",1},
points = 5,
mana = 10,
cooldown = 2,
tactical = { ATTACK = { PHYSICAL = 1, cut = 1} },
range = 10,
direct_hit = true,
reflectable = true,
proj_speed = 20,
requires_target = true,
getDamage = function(self, t) return self:combatTalentSpellDamage(t, 20, 200) end,
action = function(self, t)
local tg = {type="bolt", range=self:getTalentRange(t), talent=t, display={particle="stone_shards", trail="earthtrail"}, friendlyfire=false, friendlyblock=false}
local x, y = self:getTarget(tg)
if not x or not y then return nil end
local damage = t.getDamage(self, t)
self:projectile(tg, x, y, DamageType.SPLIT_BLEED, self:spellCrit(damage), nil)
game:playSoundNear(self, "talents/earth")
--missile #2
local tg2 = {type="bolt", range=self:getTalentRange(t), talent=t, display={particle="stone_shards", trail="earthtrail"}, friendlyfire=false, friendlyblock=false}
local x, y = self:getTarget(tg2)
if x and y then
self:projectile(tg2, x, y, DamageType.SPLIT_BLEED, self:spellCrit(damage), nil)
game:playSoundNear(self, "talents/earth")
end
--missile #3 (Talent Level 5 Bonus Missile)
if self:getTalentLevel(t) >= 5 then
local tg3 = {type="bolt", range=self:getTalentRange(t), talent=t, display={particle="stone_shards", trail="earthtrail"}, friendlyfire=false, friendlyblock=false}
local x, y = self:getTarget(tg3)
if x and y then
self:projectile(tg3, x, y, DamageType.SPLIT_BLEED, self:spellCrit(damage), nil)
game:playSoundNear(self, "talents/earth")
end
else end
return true
end,
info = function(self, t)
local count = 2
if self:getTalentLevel(t) >= 5 then
count = count + 1
end
local damage = t.getDamage(self, t)
return ([[Conjures %d missile shaped rocks that you target individually at any target or targets in range. Each missile deals %0.2f physical damage, and an additional %0.2f bleeding damage every turn for 5 turns.
At talent level 5, you can conjure one additional missile.
The damage will increase with your Spellpower.]]):format(count,damDesc(self, DamageType.PHYSICAL, damage/2), damDesc(self, DamageType.PHYSICAL, damage/12))
end,
}
newTalent{
name = "Elemental Split",
type = {"wild-gift/dwarven-nature", 1},
require = gifts_req1,
points = 5,
equilibrium = 20,
cooldown = 30,
getDuration = function(self, t) return math.floor(self:combatTalentScale(t, 6, 10)) end,
on_pre_use = function(self, t)
if self:hasEffect(self.EFF_DEEPROCK_FORM) then return false end
local cryst = game.party:findMember{type="dwarven nature crystaline half"}
local stone = game.party:findMember{type="dwarven nature stone half"}
if cryst or stone then return false end
return true
end,
action = function(self, t)
local nb_halves = 0
-- Find space
local x, y = util.findFreeGrid(self.x, self.y, 1, true, {[Map.ACTOR]=true})
if x then
local m = require("mod.class.NPC").new(self:clone{
shader = "shadow_simulacrum", shader_args = {time_factor=1000, base=0.5, color={0.6, 0.3, 0.6}},
no_drops = true,
faction = self.faction,
summoner = self, summoner_gain_exp=true,
summon_time = t.getDuration(self, t),
ai_target = {actor=nil},
ai = "summoned", ai_real = "tactical",
name = "Crystaline Half ("..self.name..")",
desc = [[A crystaline structure that has taken your exact form.]],
})
m:removeAllMOs()
m.make_escort = nil
m.on_added_to_level = nil
m.energy.value = 0
m.player = nil
-- m.max_life = m.max_life * t.getHealth(self, t)
-- m.life = util.bound(m.life, 0, m.max_life)
m.forceLevelup = function() end
m.die = nil
m.on_die = nil
m.on_acquire_target = nil
m.seen_by = nil
m.can_talk = nil
m.puuid = nil
m.on_takehit = nil
m.exp_worth = 0
m.no_inventory_access = true
m.clone_on_hit = nil
local tids = table.keys(m.talents)
for i, tid in ipairs(tids) do
if tid ~= m.T_STONESHIELD and tid ~= m.T_ARMOUR_TRAINING then
m:unlearnTalent(tid, m:getTalentLevelRaw(tid))
end
end
m:learnTalent(m.T_DWARVEN_HALF_EARTHEN_MISSILES, true, self:getTalentLevelRaw(t))
m.remove_from_party_on_death = true
if self:knowTalent(self.T_POWER_CORE) then
m:learnTalent(m.T_RAIN_OF_SPIKES, true, math.floor(self:getTalentLevel(self.T_POWER_CORE)))
end
game.zone:addEntity(game.level, m, "actor", x, y)
game.level.map:particleEmitter(x, y, 1, "shadow")
nb_halves = nb_halves + 1
if game.party:hasMember(self) then
game.party:addMember(m, {
control="no",
type="dwarven nature crystaline half",
title="Crystaline Half",
orders = {target=true},
})
end
end
-- Find space
local x, y = util.findFreeGrid(self.x, self.y, 1, true, {[Map.ACTOR]=true})
if x then
local m = require("mod.class.NPC").new(self:clone{
shader = "shadow_simulacrum", shader_args = {time_factor=-8000, base=0.5, color={0.6, 0.4, 0.3}},
no_drops = true,
faction = self.faction,
summoner = self, summoner_gain_exp=true,
summon_time = t.getDuration(self, t),
ai_target = {actor=nil},
ai = "summoned", ai_real = "tactical",
name = "Stone Half ("..self.name..")",
desc = [[A stone structure that has taken your exact form.]],
})
m:removeAllMOs()
m.make_escort = nil
m.on_added_to_level = nil
m.energy.value = 0
m.player = nil
-- m.max_life = m.max_life * t.getHealth(self, t)
-- m.life = util.bound(m.life, 0, m.max_life)
m.forceLevelup = function() end
m.die = nil
m.on_die = nil
m.on_acquire_target = nil
m.seen_by = nil
m.can_talk = nil
m.puuid = nil
m.on_takehit = nil
m.exp_worth = 0
m.no_inventory_access = true
m.clone_on_hit = nil
local tids = table.keys(m.talents)
for i, tid in ipairs(tids) do
if tid ~= m.T_STONESHIELD and tid ~= m.T_ARMOUR_TRAINING then
m:unlearnTalent(tid, m:getTalentLevelRaw(tid))
end
end
m.talent_cd_reduction={[m.T_TAUNT]=3},
m:learnTalent(m.T_TAUNT, true, self:getTalentLevelRaw(t))
m.remove_from_party_on_death = true
if self:knowTalent(self.T_POWER_CORE) then
m:learnTalent(m.T_STONE_LINK, true, math.floor(self:getTalentLevel(self.T_POWER_CORE)))
end
game.zone:addEntity(game.level, m, "actor", x, y)
game.level.map:particleEmitter(x, y, 1, "shadow")
nb_halves = nb_halves + 1
if game.party:hasMember(self) then
game.party:addMember(m, {
control="no",
type="dwarven nature stone half",
title="Stone Half",
orders = {target=true},
})
end
end
if nb_halves == 0 then return end
game:playSoundNear(self, "talents/spell_generic2")
return true
end,
info = function(self, t)
return ([[Reach inside your dwarven core and summon your stone and crystaline halves to fight alongside you for %d turns.
Your Crystaline Half will attack your foes with earthen missiles.
Your Stone Half will taunt your foes to protect you.
This power can not be called upon while under the effect of Deeprock Form.
]]):format(t.getDuration(self, t))
end,
}
newTalent{
name = "Power Core",
type = {"wild-gift/dwarven-nature", 2},
require = gifts_req2,
points = 5,
mode = "passive",
info = function(self, t)
return ([[Your halves learn new talents.
Crystaline Half: Rain of Spikes - A massive effect that makes all nearby foes bleed.
Stone Half: Stone Link - A protective shield that will redirect all damage against nearby allies to your Stone Half.
The level of those talents is %d.]]):
format(math.floor(self:getTalentLevel(t)))
end,
}
newTalent{
name = "Dwarven Unity",
type = {"wild-gift/dwarven-nature", 3},
require = gifts_req3,
points = 5,
equilibrium = 10,
cooldown = 6,
tactical = { ATTACK = 2, PROTECT = 2 },
radius = function(self, t) return math.floor(self:combatTalentScale(t, 4, 8)) end,
on_pre_use = function(self, t)
local cryst = game.party:findMember{type="dwarven nature crystaline half"}
local stone = game.party:findMember{type="dwarven nature stone half"}
if not cryst and not stone then return false end
return true
end,
action = function(self, t)
local cryst = game.party:findMember{type="dwarven nature crystaline half"}
local stone = game.party:findMember{type="dwarven nature stone half"}
if cryst then
self:project({type="ball", radius=self:getTalentRadius(t), friendlyfire=false}, self.x, self.y, function(px, py)
local target = game.level.map(px, py, Map.ACTOR)
if not target then return end
cryst:forceUseTalent(cryst.T_DWARVEN_HALF_EARTHEN_MISSILES, {ignore_cd=true, ignore_energy=true, force_target=target, force_level=self:getTalentLevelRaw(t), ignore_ressources=true})
end)
end
if stone then
game.level.map:remove(self.x, self.y, Map.ACTOR)
game.level.map:remove(stone.x, stone.y, Map.ACTOR)
game.level.map(self.x, self.y, Map.ACTOR, stone)
game.level.map(stone.x, stone.y, Map.ACTOR, self)
self.x, self.y, stone.x, stone.y = stone.x, stone.y, self.x, self.y
game.level.map:particleEmitter(stone.x, stone.y, 1, "teleport")
game.level.map:particleEmitter(self.x, self.y, 1, "teleport")
self:project({type="ball", radius=self:getTalentRadius(t), friendlyfire=false}, self.x, self.y, function(px, py)
local target = game.level.map(px, py, Map.ACTOR)
if not target then return end
target:setTarget(stone)
end)
end
return true
end,
info = function(self, t)
return ([[You call upon the immediate help of your Halves.
Your Stone Half will trade places with you and all creatures currently targetting you in a radius of %d will target it instead.
Your Crystaline Half will instantly fire a volley of level %d earthen missiles at all foes near the stone half (or you if the stone half is dead) in radius %d.]]):
format(self:getTalentRadius(t), self:getTalentLevelRaw(t), self:getTalentRadius(t))
end,
}
newTalent{
name = "Mergeback",
type = {"wild-gift/dwarven-nature", 4},
require = gifts_req4,
points = 5,
equilibrium = 10,
cooldown = 20,
no_npc_use = true,
radius = 3,
getRemoveCount = function(self, t) return math.floor(self:combatTalentScale(t, 5, 9, "log")) end,
getDamage = function(self, t) return self:combatTalentStatDamage(t, "wil", 60, 330) end,
getHeal = function(self, t) return self:combatTalentStatDamage(t, "wil", 60, 330) end,
on_pre_use = function(self, t)
local cryst = game.party:findMember{type="dwarven nature crystaline half"}
local stone = game.party:findMember{type="dwarven nature stone half"}
if not cryst and not stone then return false end
return true
end,
action = function(self, t)
local cryst = game.party:findMember{type="dwarven nature crystaline half"}
local stone = game.party:findMember{type="dwarven nature stone half"}
local nb = (cryst and 1 or 0) + (stone and 1 or 0)
if cryst then cryst:die() end
if stone then stone:die() end
local target = self
local effs = {}
for eff_id, p in pairs(target.tmp) do
local e = target.tempeffect_def[eff_id]
if (e.type == "magical" or e.type == "mental" or e.type == "physical") and e.status == "detrimental" then
effs[#effs+1] = {"effect", eff_id}
end
end
for i = 1, t.getRemoveCount(self, t) do
if #effs == 0 then break end
local eff = rng.tableRemove(effs)
if eff[1] == "effect" then
target:removeEffect(eff[2])
end
end
self:heal((self:mindCrit(t.getHeal(self, t) * nb)))
self:project({type="ball", radius=self:getTalentRadius(t), friendlyfire=false}, self.x, self.y, DamageType.NATURE, self:mindCrit(t.getDamage(self, t)) * nb)
game.level.map:particleEmitter(self.x, self.y, self:getTalentRadius(t), "generic_ball", {radius=self:getTalentRadius(t), rm=0, rM=0, gm=200, gM=250, bm=100, bM=170, am=200, aM=255})
game:playSoundNear(self, "talents/stone")
return true
end,
info = function(self, t)
local nb = t.getRemoveCount(self, t)
local dam = t.getDamage(self, t)
local heal = t.getHeal(self, t)
return ([[Merges your halves back into you, cleansing your body of %d detrimental magical, mental or physical effects.
Each half also heals you for %d and releases a shockwave dealing %0.2f Nature damage in a radius 3.]]):
format(nb, heal, damDesc(self, DamageType.NATURE, dam))
end,
}
-----------------------------------------------------------
-- Halves talents
-----------------------------------------------------------
newTalent{
name = "Stone Link",
type = {"wild-gift/other", 1},
points = 5,
equilibrium = 10,
cooldown = 10,
tactical = { BUFF = 2, },
radius = function(self, t) return math.floor(self:combatTalentScale(t, 2.5, 4.5)) end,
requires_target = false,
action = function(self, t)
self:setEffect(self.EFF_STONE_LINK_SOURCE, 5, {rad=self:getTalentRadius(t)})
game:playSoundNear(self, "talents/stone")
return true
end,
info = function(self, t)
local radius = self:getTalentRadius(t)
return ([[Creates a shield of radius %d that redirects all damage done to friends inside it to you for 5 turns.]]):format(radius)
end,
}
newTalent{
name = "Rain of Spikes",
type = {"wild-gift/other", 1},
points = 5,
equilibrium = 10,
cooldown = 6,
tactical = { ATTACKAREA = {PHYSICAL=2}, },
radius = function(self, t) return math.floor(self:combatTalentScale(t, 3, 7)) end,
getDamage = function(self, t) return self:combatTalentStatDamage(t, "wil", 60, 330) end,
action = function(self, t)
self:project({type="ball", radius=self:getTalentRadius(t), friendlyfire=false}, self.x, self.y, function(px, py)
local target = game.level.map(px, py, Map.ACTOR)
if not target then return end
if target:canBe("cut") then
target:setEffect(target.EFF_CUT, 6, {src = self, apply_power=self:combatMindpower(), power=self:mindCrit(t.getDamage(self, t))/6})
end
end, nil, {type="stone_spikes"})
game:playSoundNear(self, "talents/stone")
return true
end,
info = function(self, t)
local radius = self:getTalentRadius(t)
local dam = t.getDamage(self, t)
return ([[Fires spikes all around you, making your foes within radius %d bleed for %0.2f damage over 6 turns.
Damage and chance to apply the effect increase with Willpower.]]):format(radius, damDesc(self, DamageType.PHYSICAL, dam))
end,
}
PK
!gC data/talents/gifts/gifts.luaUT ΰ{Rΰ{Rux d -- ToME - Tales of Maj'Eyal
-- Copyright (C) 2009, 2010, 2011, 2012, 2013 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 .
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
newTalentType{ allow_random=true, is_nature=true, type="wild-gift/earthen-power", name = "earthen power", description = "Dwarves have learned to imbue their shields with the power of stone itself." }
newTalentType{ allow_random=true, is_nature=true, type="wild-gift/earthen-vines", name = "earthen vines", description = "Control the stone itself and bring it alive in the form of dreadful vines." }
newTalentType{ allow_random=true, is_nature=true, type="wild-gift/dwarven-nature", name = "dwarven nature", description = "Learn to harness the innate power of your race." }
damDesc = Talents.main_env.damDesc
gifts_req1 = Talents.main_env.gifts_req1
gifts_req2 = Talents.main_env.gifts_req2
gifts_req3 = Talents.main_env.gifts_req3
gifts_req4 = Talents.main_env.gifts_req4
gifts_req5 = Talents.main_env.gifts_req5
load("/data-stone-wardens/talents/gifts/earthen-power.lua")
load("/data-stone-wardens/talents/gifts/earthen-vines.lua")
load("/data-stone-wardens/talents/gifts/dwarven-nature.lua")
PK
ovC data/talents/spells/UT TRDQux d PK
!gCE-U data/talents/spells/spells.luaUT ΰ{Rΰ{Rux d -- ToME - Tales of Maj'Eyal
-- Copyright (C) 2009, 2010, 2011, 2012, 2013 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 .
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
newTalentType{ allow_random=true, no_silence=true, is_spell=true, type="spell/eldritch-shield", name = "eldritch shield", description = "Infuse arcane forces into your shield." }
newTalentType{ allow_random=true, no_silence=true, is_spell=true, type="spell/eldritch-stone", name = "eldritch stone", description = "Summon stony spikes imbued with various powers." }
newTalentType{ allow_random=true, no_silence=true, is_spell=true, type="spell/deeprock", name = "deeprock", description = "Harness the power of the world to turn into a Deeprock Form." }
damDesc = Talents.main_env.damDesc
spells_req1 = Talents.main_env.spells_req1
spells_req2 = Talents.main_env.spells_req2
spells_req3 = Talents.main_env.spells_req3
spells_req4 = Talents.main_env.spells_req4
spells_req5 = Talents.main_env.spells_req5
spells_req_high1 = Talents.main_env.spells_req_high1
spells_req_high2 = Talents.main_env.spells_req_high2
spells_req_high3 = Talents.main_env.spells_req_high3
spells_req_high4 = Talents.main_env.spells_req_high4
spells_req_high5 = Talents.main_env.spells_req_high5
load("/data-stone-wardens/talents/spells/eldritch-shield.lua")
load("/data-stone-wardens/talents/spells/eldritch-stone.lua")
load("/data-stone-wardens/talents/spells/deeprock.lua")
PK
mgCPs &