Skip to content
Snippets Groups Projects
necrosis.lua 13 KiB
Newer Older
dg's avatar
dg committed
-- ToME - Tales of Maj'Eyal
DarkGod's avatar
DarkGod committed
-- Copyright (C) 2009 - 2018 Nicolas Casalini
dg's avatar
dg committed
--
-- 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 = "Blurred Mortality",
	type = {"spell/necrosis",1},
	require = spells_req1,
dg's avatar
dg committed
	mode = "sustained",
dg's avatar
dg committed
	points = 5,
dg's avatar
dg committed
	sustain_mana = 30,
	cooldown = 30,
	tactical = { BUFF = 2 },
dg's avatar
dg committed
	lifeBonus = function(self, t) -- Add fraction of max life
		return 50 * self:getTalentLevelRaw(t) + self.max_life * self:combatTalentLimit(t, 1, .01, .05)
	end,
dg's avatar
dg committed
	activate = function(self, t)
DarkGod's avatar
DarkGod committed
		if self.player and not self:attr("no_lichform_quest") and not self:hasQuest("lichform") and not self:attr("undead") then
			self:grantQuest("lichform")
			if game.state.birth.campaign_name ~= "maj-eyal" then self:setQuestStatus("lichform", engine.Quest.DONE) end
			require("engine.ui.Dialog"):simplePopup("Lichform", "You have mastered the lesser arts of overcoming death, but your true goal is before you: the true immortality of Lichform!")
		end

dg's avatar
dg committed
		local ret = {
dg's avatar
dg committed
			die_at = self:addTemporaryValue("die_at", -t.lifeBonus(self, t)),
		} -- Add up to 100% max life
dg's avatar
dg committed
		return ret
dg's avatar
dg committed
	end,
dg's avatar
dg committed
	deactivate = function(self, t, p)
		self:removeTemporaryValue("die_at", p.die_at)
dg's avatar
dg committed
		return true
	end,
	info = function(self, t)
DarkGod's avatar
DarkGod committed
		return ([[The line between life and death blurs for you; you can only die when you reach -%d life.]]):
dg's avatar
dg committed
		format(t.lifeBonus(self, t))
dg's avatar
dg committed
	end,
}

newTalent{
	name = "Impending Doom",
	type = {"spell/necrosis",2},
	require = spells_req2,
	points = 5,
	tactical = { ATTACK = { ARCANE = 3 }, DISABLE = 2 },
	rnd_boss_restrict = function(self, t)
		return self.level < 15
	end,
dg's avatar
dg committed
	range = 7,
dg's avatar
dg committed
	requires_target = true,
dg's avatar
dg committed
	getMax = function(self, t) return 200 + self:combatTalentSpellDamage(t, 28, 850) end,
dg's avatar
dg committed
	getDamage = function(self, t) return self:combatLimit(self:combatTalentSpellDamage(t, 10, 100), 150, 50, 0, 117, 67) end, -- Limit damage factor to < 150%
dg's avatar
dg committed
	action = function(self, t)
dg's avatar
dg committed
		local tg = {type="hit", range=self:getTalentRange(t), talent=t}
dg's avatar
dg committed
		local x, y = self:getTarget(tg)
		if not x or not y then return nil end
dg's avatar
dg committed
		self:project(tg, x, y, function(px, py)
			local target = game.level.map(px, py, Map.ACTOR)
			if not target then return end
			local dam = target.life * t.getDamage(self, t) / 100
			dam = math.min(dam, t.getMax(self, t))
			target:setEffect(target.EFF_IMPENDING_DOOM, 10, {apply_power=self:combatSpellpower(), dam=dam/10, src=self})
dg's avatar
dg committed
		end, 1, {type="freeze"})
dg's avatar
dg committed
		return true
	end,
	info = function(self, t)
		return ([[Your target's doom draws near. Its healing factor is reduced by 80%%, and will take %d%% of its remaining life (or %0.2f, whichever is lower) over 10 turns as arcane damage.
dg's avatar
dg committed
		The damage will increase with your Spellpower.]]):
dg's avatar
dg committed
		format(t.getDamage(self, t), t.getMax(self, t))
dg's avatar
dg committed
	end,
}

newTalent{
dg's avatar
dg committed
	name = "Undeath Link",
dg's avatar
dg committed
	type = {"spell/necrosis",3},
	require = spells_req3,
	points = 5,
	random_ego = "attack",
dg's avatar
dg committed
	tactical = { HEAL = 2 },
dg's avatar
dg committed
	getHeal = function(self, t) return self:combatLimit(self:combatTalentSpellDamage(t, 10, 70), 100, 20, 0,  66.7, 46.7) end, --Limit to <100%
dg's avatar
dg committed
	on_pre_use = function(self, t)
		if game.party and game.party:hasMember(self) then
			for act, def in pairs(game.party.members) do
				if act.summoner and act.summoner == self and act.necrotic_minion then
					return true
				end
			end
		else
			for uid, act in pairs(game.level.entities) do
				if act.summoner and act.summoner == self and act.necrotic_minion then
					return true
				end
			end
		end
		return false
dg's avatar
dg committed
	end,
	action = function(self, t)
dg's avatar
dg committed
		local heal = t.getHeal(self, t)
dg's avatar
dg committed
		local maxdrain = 0 --Use biggest drain for healing purposes
		local drain = 0
dg's avatar
dg committed
		if game.party and game.party:hasMember(self) then
			for act, def in pairs(game.party.members) do
				if act.summoner and act.summoner == self and act.necrotic_minion then
dg's avatar
dg committed
					drain = math.min(act.max_life * heal / 100, act.life-act.die_at)
					act:takeHit(drain, self)
					maxdrain = math.max(maxdrain, drain)
dg's avatar
dg committed
				end
			end
		else
			for uid, act in pairs(game.level.entities) do
				if act.summoner and act.summoner == self and act.necrotic_minion then
dg's avatar
dg committed
					drain = math.min(act.max_life * heal / 100, act.life-act.die_at)
					act:takeHit(drain, self)
					maxdrain = math.max(maxdrain, drain)
dg's avatar
dg committed
				end
dg's avatar
dg committed
			end
dg's avatar
dg committed
		end
		self:attr("allow_on_heal", 1)
dg's avatar
dg committed
		self:heal(maxdrain)
		local empower = necroEssenceDead(self)
		if empower then
			self:setEffect(self.EFF_DAMAGE_SHIELD, 4, {color={0xcb/255, 0xcb/255, 0xcb/255}, power=maxdrain * 0.3})
			empower()
		end
		self:attr("allow_on_heal", -1)
		if core.shader.active(4) then
			self:addParticles(Particles.new("shader_shield_temp", 1, {size_factor=1.5, y=-0.3, img="healdark", life=25}, {type="healing", time_factor=6000, beamsCount=15, noup=2.0, beamColor1={0xcb/255, 0xcb/255, 0xcb/255, 1}, beamColor2={0x35/255, 0x35/255, 0x35/255, 1}}))
			self:addParticles(Particles.new("shader_shield_temp", 1, {size_factor=1.5, y=-0.3, img="healdark", life=25}, {type="healing", time_factor=6000, beamsCount=15, noup=1.0, beamColor1={0xcb/255, 0xcb/255, 0xcb/255, 1}, beamColor2={0x35/255, 0x35/255, 0x35/255, 1}}))
		end
dg's avatar
dg committed
		game:playSoundNear(self, "talents/ice")
dg's avatar
dg committed
		return true
	end,
	info = function(self, t)
dg's avatar
dg committed
		local heal = t.getHeal(self, t)
dg's avatar
dg committed
		return ([[Absorb up to %d%% of the maximum life of each of your necrotic minions (even negative life, possibly destroying them). This will heal you for the greatest amount absorbed.
dg's avatar
dg committed
		The healing will increase with your Spellpower.]]):
dg's avatar
dg committed
		format(heal)
dg's avatar
dg committed
	end,
}

newTalent{
	name = "Lichform",
	type = {"spell/necrosis",4},
dg's avatar
dg committed
	require = {
		stat = { mag=function(level) return 40 + (level-1) * 2 end },
		level = function(level) return 20 + (level-1)  end,
DarkGod's avatar
DarkGod committed
		special = { desc="'From Death, Life' quest completed and not already undead", fct=function(self, t) return not self:attr("undead") and (self:isQuestStatus("lichform", engine.Quest.DONE) or game.state.birth.ignore_prodigies_special_reqs) end},
dg's avatar
dg committed
	},
dg's avatar
dg committed
	mode = "sustained",
dg's avatar
dg committed
	points = 5,
dg's avatar
dg committed
	sustain_mana = 150,
dg's avatar
dg committed
	cooldown = 30,
dg's avatar
dg committed
	no_unlearn_last = true,
dg's avatar
dg committed
	no_npc_use = true,
	becomeLich = function(self, t)
		self.has_used_lichform = true
dg's avatar
dg committed
		self.descriptor.race = "Undead"
		self.descriptor.subrace = "Lich"
		if not self.has_custom_tile then
			self.moddable_tile = "skeleton"
			self.moddable_tile_nude = 1
			self.moddable_tile_base = "base_lich_01.png"
			self.moddable_tile_ornament = nil
			self.moddable_tile_hair = nil
			self.moddable_tile_facial_features = nil
			self.moddable_tile_tatoo = nil
			self.moddable_tile_horn = nil
DarkGod's avatar
DarkGod committed
			self.attachement_spots = "race_skeleton"
dg's avatar
dg committed
		self.blood_color = colors.GREY
		self:attr("poison_immune", 1)
		self:attr("disease_immune", 1)
		self:attr("stun_immune", 1)
dg's avatar
dg committed
		self:attr("cut_immune", 1)
		self:attr("fear_immune", 1)
		self:attr("no_breath", 1)
		self:attr("undead", 1)
		self.resists[DamageType.COLD] = (self.resists[DamageType.COLD] or 0) + 20
		self.resists[DamageType.DARKNESS] = (self.resists[DamageType.DARKNESS] or 0) + 20
		self.inscription_forbids = self.inscription_forbids or {}
		self.inscription_forbids["inscriptions/infusions"] = true
dg's avatar
dg committed

dg's avatar
dg committed
		local level = self:getTalentLevel(t)
		if level < 2 then
			self:incIncStat("mag", -3) self:incIncStat("wil", -3)
			self.resists.all = (self.resists.all or 0) - 10
		elseif level < 3 then
			-- nothing
		elseif level < 4 then
			self:incIncStat("mag", 3) self:incIncStat("wil", 3)
			self.life_rating = self.life_rating + 1
		elseif level < 5 then
			self:incIncStat("mag", 3) self:incIncStat("wil", 3)
			self:attr("combat_spellresist", 10) self:attr("combat_mentalresist", 10)
			self.life_rating = self.life_rating + 2
			self:learnTalentType("celestial/star-fury", true)
			self:setTalentTypeMastery("celestial/star-fury", self:getTalentTypeMastery("celestial/star-fury") - 0.3)
			self.negative_regen = self.negative_regen + 0.2 + 0.1
dg's avatar
dg committed
		elseif level < 6 then
			self:incIncStat("mag", 5) self:incIncStat("wil", 5)
			self:attr("combat_spellresist", 10) self:attr("combat_mentalresist", 10)
			self.resists_cap.all = (self.resists_cap.all or 0) + 10
			self.life_rating = self.life_rating + 2
			self:learnTalentType("celestial/star-fury", true)
			self:setTalentTypeMastery("celestial/star-fury", self:getTalentTypeMastery("celestial/star-fury") - 0.1)
			self.negative_regen = self.negative_regen + 0.2 + 0.5
		elseif level < 7 then
dg's avatar
dg committed
			self:incIncStat("mag", 6) self:incIncStat("wil", 6) self:incIncStat("cun", 6)
			self:attr("combat_spellresist", 15) self:attr("combat_mentalresist", 15)
			self.resists_cap.all = (self.resists_cap.all or 0) + 15
			self.life_rating = self.life_rating + 3
			self:learnTalentType("celestial/star-fury", true)
			self:setTalentTypeMastery("celestial/star-fury", self:getTalentTypeMastery("celestial/star-fury") + 0.1)
			self.negative_regen = self.negative_regen + 0.2 + 1
		else -- level 7
			self:incIncStat("mag", 12) self:incIncStat("wil", 12) self:incIncStat("cun", 12)
			self:attr("combat_spellresist", 35) self:attr("combat_mentalresist", 35)
			self.resists_cap.all = (self.resists_cap.all or 0) + 15
			self.life_rating = self.life_rating + 4
			self:attr("ignore_direct_crits", 60)
			self:learnTalentType("celestial/star-fury", true)
			self:setTalentTypeMastery("celestial/star-fury", self:getTalentTypeMastery("celestial/star-fury") + 0.3)
			self.negative_regen = self.negative_regen + 0.2 + 1
dg's avatar
dg committed
		end

dg's avatar
dg committed
		if self:attr("blood_life") then
			self.blood_life = nil
			game.log("#GREY#As you turn into a powerful undead you feel your body violently rejecting the Blood of Life.")
		end

		if not self.has_custom_tile then
			self:removeAllMOs()
			self:updateModdableTile()
			require("engine.ui.Dialog"):yesnoLongPopup("Lichform", "#GREY#You feel your life slip away, only to be replaced by pure arcane forces! Your flesh starts to rot on your bones, and your eyes fall apart as you are reborn into a Lich!\n\n#{italic}#You may now choose to customize the appearance of your Lich, this can not be changed afterwards.", 600, function(ret) if ret then
				require("mod.dialogs.Birther"):showCosmeticCustomizer(self, "Lich Cosmetic Options")
			end end, "Customize Appearance", "Use Default", true)
		else
			require("engine.ui.Dialog"):simplePopup("Lichform", "#GREY#You feel your life slip away, only to be replaced by pure arcane forces! Your flesh starts to rot on your bones, and your eyes fall apart as you are reborn into a Lich!")
		end
dg's avatar
dg committed

		game.level.map:particleEmitter(self.x, self.y, 1, "demon_teleport")
dg's avatar
dg committed
	end,
	on_pre_use = function(self, t)
		if self:attr("undead") then return false else return true end
	end,
	activate = function(self, t)
		local ret = {
			mana = self:addTemporaryValue("mana_regen", -4),
		}
		return ret
	end,
	deactivate = function(self, t, p)
		self:removeTemporaryValue("mana_regen", p.mana)
dg's avatar
dg committed
		return true
	end,
	info = function(self, t)
dg's avatar
dg committed
		return ([[This is your true goal and the purpose of all necromancy - to become a powerful and everliving Lich!
		If you are killed while this spell is active, the arcane forces you unleash will be able to rebuild your body into the desired Lichform.
dg's avatar
dg committed
		All liches gain the following intrinsics:
dg's avatar
dg committed
		- Poison, cut, and fear immunity.
		- 100%% disease and stun resistance.
dg's avatar
dg committed
		- 20%% cold and darkness resistance.
		- No need to breathe.
		- Infusions do not work.
dg's avatar
dg committed
		Also:
		At level 1: -3 to all stats, -10%% to all resistances. Such meagre devotion!
dg's avatar
dg committed
		At level 2: Nothing.
		At level 3: +3 Magic and Willpower, +1 life rating (not retroactive).
		At level 4: +3 Magic and Willpower, +2 life rating (not retroactive), +10 spell and mental saves, Celestial/Star Fury category (0.7) and 0.1 negative energies regeneration.
		At level 5: +5 Magic and Willpower, +2 life rating (not retroactive), +10 spell and mental saves, all resistance caps raised by 10%%, Celestial/Star Fury category (0.9) and 0.5 negative energy regeneration.
		At level 6: +6 Magic, Willpower and Cunning, +3 life rating (not retroactive), +15 spell and mental saves, all resistance caps raised by 15%%, Celestial/Star Fury category (1.1) and 1.0 negative energy regeneration.
		At level 7: #CRIMSON##{bold}#Your power becomes overwhelming!#{normal}##LAST# +12 Magic, Willpower and Cunning, 60%% chance to ignore critical hits, +4 life rating (not retroactive), +35 spell and mental saves, all resistance caps raised by 15%%, Celestial/Star Fury category (1.3) and 1.0 negative energy regeneration.
dg's avatar
dg committed
		The undead cannot use this talent.
		While active, it will drain 4 mana per turn.
		Once you die and turn into a Lich you can not invest any more in this talent.]]):
dg's avatar
dg committed
		format()
dg's avatar
dg committed
	end,
}