Forked from
tome / Tales of MajEyal
9046 commits behind the upstream repository.
-
dg authored
git-svn-id: http://svn.net-core.org/repos/t-engine4@6058 51575b47-30f0-44d4-a5cc-537603b46e54
dg authoredgit-svn-id: http://svn.net-core.org/repos/t-engine4@6058 51575b47-30f0-44d4-a5cc-537603b46e54
slumber.lua 10.08 KiB
-- 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
newTalent{
name = "Slumber",
type = {"psionic/slumber", 1},
points = 5,
require = psi_wil_req1,
cooldown = 8,
psi = 10,
tactical = { DISABLE = {sleep = 2} },
direct_hit = true,
requires_target = true,
range = 7,
target = function(self, t) return {type="hit", range=self:getTalentRange(t), talent=t} end,
getDuration = function(self, t) return 2 + math.ceil(self:getTalentLevel(t)/2) end,
getInsomniaPower = function(self, t)
local t = self:getTalentFromId(self.T_SANDMAN)
local reduction = t.getInsomniaPower(self, t)
return 20 - reduction
end,
getSleepPower = function(self, t)
local power = self:combatTalentMindDamage(t, 10, 100)
if self:knowTalent(self.T_SANDMAN) then
local t = self:getTalentFromId(self.T_SANDMAN)
power = power * t.getSleepPowerBonus(self, t)
end
return math.ceil(power)
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 nil end
local _ _, x, y = self:canProject(tg, x, y)
target = game.level.map(x, y, Map.ACTOR)
if not target then return nil end
--Restless?
local is_waking =0
if self:knowTalent(self.T_RESTLESS_NIGHT) then
local t = self:getTalentFromId(self.T_RESTLESS_NIGHT)
is_waking = t.getDamage(self, t)
end
local power = self:mindCrit(t.getSleepPower(self, t))
if target:canBe("sleep") then
target:setEffect(target.EFF_SLUMBER, t.getDuration(self, t), {src=self, power=power, waking=is_waking, insomnia=t.getInsomniaPower(self, t), no_ct_effect=true, apply_power=self:combatMindpower()})
game.level.map:particleEmitter(target.x, target.y, 1, "generic_charge", {rm=180, rM=200, gm=100, gM=120, bm=30, bM=50, am=70, aM=180})
else
game.logSeen(self, "%s resists the sleep!", target.name:capitalize())
end
game:playSoundNear(self, "talents/dispel")
return true
end,
info = function(self, t)
local duration = t.getDuration(self, t)
local power = t.getSleepPower(self, t)
local insomnia = t.getInsomniaPower(self, t)
return([[Puts the target into a deep sleep for %d turns, rendering it unable to act. Every %d points of damage the target suffers will reduce the effect duration by one turn.
When Slumber ends the target will suffer from Insomnia for a number of turns equal to the amount of time it was asleep (up to ten turns max), granting it %d%% sleep immunity for each turn of the Insomnia effect.
The damage threshold will scale with your mindpower.]]):format(duration, power, insomnia)
end,
}
newTalent{
name = "Restless Night",
type = {"psionic/slumber", 2},
points = 5,
require = psi_wil_req2,
mode = "passive",
getDamage = function(self, t) return self:combatTalentMindDamage(t, 5, 40) end,
doRestlessNight = function (self, target, damage)
local dam = self:mindCrit(damage)
target:setEffect(target.EFF_RESTLESS_NIGHT, 5, {power=dam, src=self, no_ct_effect=true})
game.level.map:particleEmitter(target.x, target.y, 1, "generic_discharge", {rm=180, rM=200, gm=100, gM=120, bm=30, bM=50, am=70, aM=180})
end,
info = function(self, t)
local damage = t.getDamage(self, t)
return([[Targets you have slept now take %0.2f mind damage each turn for five turns upon waking.
The damage will scale with your mindpower.]]):format(damDesc(self, DamageType.MIND, (damage)))
end,
}
newTalent{
name = "Sandman",
type = {"psionic/slumber", 3},
points = 5,
require = psi_wil_req3,
mode = "passive",
getSleepPowerBonus = function(self, t) return 1 + math.min(1, self:getTalentLevel(t)/10) end,
getInsomniaPower = function(self, t) return math.min(10, self:getTalentLevelRaw(t) * 2) end,
info = function(self, t)
local power_bonus = t.getSleepPowerBonus(self, t) - 1
local insomnia = t.getInsomniaPower(self, t)
return([[Increases the amount of damage you can deal to sleeping targets before reducing the effect duration by %d%% and reduces the sleep immunity of your Insomnia effects by %d%%.
These effects will be directly reflected in the appropriate talent descriptions.
The damage threshold bonus will scale with your mindpower.]]):format(power_bonus * 100, insomnia)
end,
}
newTalent{
name = "Dreamscape",
type = {"psionic/slumber", 4},
points = 5,
require = psi_wil_req4,
cooldown = 24,
psi = 40,
random_boss_rarity = 10,
tactical = { DISABLE = function(self, t, target) if target and target.game_ender and target:attr("sleep") then return 4 else return 0 end end},
direct_hit = true,
requires_target = true,
range = 7,
target = function(self, t) return {type="hit", range=self:getTalentRange(t), talent=t} end,
getDuration = function(self, t) return 4 + math.ceil(self:getTalentLevel(t) * 2) end,
getPower = function(self, t) return self:combatTalentMindDamage(t, 10, 100) end,
on_pre_use = function(self, t, silent) if self:attr("is_psychic_projection") then if not silent then game.logPlayer(self, "You feel it unwise to travel to the dreamscape in such a fragile form.") end return false end return true end,
action = function(self, t)
if game.zone.is_dream_scape then
game.logPlayer(self, "This talent can not be used from within the Dreamscape.")
return
end
if game.zone.no_planechange then
game.logPlayer(self, "This talent can not be used here.")
return
end
if not self:canBe("planechange") or target.summon_time or target.summon then
game.logPlayer(self, "The spell fizzles...")
return
end
local tg = {type="hit", range=self:getTalentRange(t), talent=t}
local tx, ty, target = self:getTarget(tg)
if not tx or not ty or not target then return nil end
local _ _, tx, ty = self:canProject(tg, tx, ty)
if not tx or not ty or not target then return nil end
target = game.level.map(tx, ty, Map.ACTOR)
if not tx or not ty or not target then return nil end
if not (target.player and target.game_ender) and not (self.player and self.game_ender) then return nil end
if target == self then return end
if target:attr("negative_status_effect_immune") or target:attr("status_effect_immune") then return nil end
if not (target and target:attr("sleep")) then
game.logPlayer(self, "Your target must be sleeping in order to enter it's dreamscape.")
return nil
end
if self:reactionToward(target) >= 0 then
game.logPlayer(self, "You can't cast this on friendly targets.")
return nil
end
game:onTickEnd(function()
if self:attr("dead") then return end
local oldzone = game.zone
local oldlevel = game.level
-- Clean up thought-forms
cancelThoughtForms(self)
-- Remove them before making the new elvel, this way party memebrs are not removed from the old
if oldlevel:hasEntity(self) then oldlevel:removeEntity(self) end
if oldlevel:hasEntity(target) then oldlevel:removeEntity(target) end
oldlevel.no_remove_entities = true
local zone = mod.class.Zone.new("dreamscape-talent")
local level = zone:getLevel(game, 1, 0)
oldlevel.no_remove_entities = nil
level:addEntity(self)
level:addEntity(target)
level.source_zone = oldzone
level.source_level = oldlevel
game.zone = zone
game.level = level
game.zone_name_s = nil
local x1, y1 = util.findFreeGrid(4, 6, 20, true, {[Map.ACTOR]=true})
if x1 then
self:move(x1, y1, true)
game.level.map:particleEmitter(x1, y1, 1, "generic_teleport", {rm=0, rM=0, gm=180, gM=255, bm=180, bM=255, am=35, aM=90})
end
local x2, y2 = util.findFreeGrid(8, 6, 20, true, {[Map.ACTOR]=true})
if x2 then
target:move(x2, y2, true)
end
target:setTarget(self)
target.dream_plane_trapper = self
target.dream_plane_on_die = target.on_die
target.on_die = function(self, ...)
self.dream_plane_trapper:removeEffect(self.EFF_DREAMSCAPE)
local args = {...}
game:onTickEnd(function()
if self.dream_plane_on_die then self:dream_plane_on_die(unpack(args)) end
self.on_die, self.dream_plane_on_die = self.dream_plane_on_die, nil
end)
end
self.dream_plane_on_die = self.on_die
self.on_die = function(self, ...)
self:removeEffect(self.EFF_DREAMSCAPE)
local args = {...}
game:onTickEnd(function()
if self.dream_plane_on_die then self:dream_plane_on_die(unpack(args)) end
self.on_die, self.dream_plane_on_die = self.dream_plane_on_die, nil
-- if not game.party:hasMember(self) then world:gainAchievement("FEARSCAPE", game:getPlayer(true)) end
end)
end
game.logPlayer(game.player, "#LIGHT_BLUE#You are taken to the Dreamscape!")
if game.party:hasMember(target) then game.player:learnLore("dreamscape-entry") end
end)
local power = self:mindCrit(t.getPower(self, t))
self:setEffect(self.EFF_DREAMSCAPE, t.getDuration(self, t), {target=target, power=power, projections_killed=0, x=self.x, y=self.y, tx=target.x, ty=target.y})
game:playSoundNear(self, "talents/teleport")
return true
end,
info = function(self, t)
local duration = t.getDuration(self, t)
local power = t.getPower(self, t)
return([[Enter a sleeping target's dreams for %d turns. While in the dreamscape you'll encounter the target's invulnerable sleeping form as well as dream projections that it will spawn every other turn to defend it's mind.
Projections inflict 50%% less damage then the original, unless the target has Lucid Dreamer active.
When the dreamscape ends the target's life will be reduced by 10%% and it will to be brainlocked for one turn for each projection destroyed.
In the dreamscape your damage will be improved by %d%%.
The damage bonus will improve with your mindpower.]]):format(duration, power)
end,
}