-- 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

newTalent{
	name = "Phase Door",
	display_name = "次元之门",
	type = {"spell/conveyance",1},
	require = spells_req1,
	points = 5,
	random_ego = "utility",
	mana = function(self, t) return game.zone and game.zone.force_controlled_teleport and 1 or 10 end,
	cooldown = function(self, t) return game.zone and game.zone.force_controlled_teleport and 3 or 8 end,
	tactical = { ESCAPE = 2 },
	requires_target = function(self, t) return self:getTalentLevel(t) >= 4 end,
	getRange = function(self, t) return 4 + self:combatTalentSpellDamage(t, 10, 15) end,
	getRadius = function(self, t) return 7 - self:getTalentLevelRaw(t) end,
	is_teleport = true,
	action = function(self, t)
		local target = self
		if self:getTalentLevel(t) >= 4 then
			game.logPlayer(self, "Selects a target to teleport...")
			local tg = {default_target=self, type="hit", nowarning=true, range=10, first_target="friend"}
			local tx, ty = self:getTarget(tg)
			if tx then
				local _ _, tx, ty = self:canProject(tg, tx, ty)
				if tx then
					target = game.level.map(tx, ty, Map.ACTOR) or self
				end
			end
		end
		if target ~= self and target:canBe("teleport") then
			local hit = self:checkHit(self:combatSpellpower(), target:combatSpellResist() + (target:attr("continuum_destabilization") or 0))
			if not hit then
				game.logSeen(target, "The spell fizzles!")
				return true
			end
		end

		-- Annoy them!
		if target ~= self and target:reactionToward(self) < 0 then target:setTarget(self) end

		local x, y = self.x, self.y
		local rad = t.getRange(self, t)
		local radius = t.getRadius(self, t)
		if self:getTalentLevel(t) >= 5 or game.zone.force_controlled_teleport then
			game.logPlayer(self, "Selects a teleport location...")
			local tg = {type="ball", nolock=true, pass_terrain=true, nowarning=true, range=rad, radius=radius, requires_knowledge=false}
			x, y = self:getTarget(tg)
			if not x then return nil end
			-- Target code does not restrict the target coordinates to the range, it lets the project function do it
			-- but we cant ...
			local _ _, x, y = self:canProject(tg, x, y)
			rad = radius

			-- Check LOS
			if not self:hasLOS(x, y) and rng.percent(35 + (game.level.map.attrs(self.x, self.y, "control_teleport_fizzle") or 0)) then
				game.logPlayer(self, "The targetted phase door fizzles and works randomly!")
				x, y = self.x, self.y
				rad = t.getRange(self, t)
			end
		end

		game.level.map:particleEmitter(target.x, target.y, 1, "teleport")
		target:teleportRandom(x, y, rad)
		game.level.map:particleEmitter(target.x, target.y, 1, "teleport")

		if target ~= self then
			target:setEffect(target.EFF_CONTINUUM_DESTABILIZATION, 100, {power=self:combatSpellpower(0.3)})
		end

		game:playSoundNear(self, "talents/teleport")
		return true
	end,
	info = function(self, t)
		local radius = t.getRadius(self, t)
		local range = t.getRange(self, t)
		return ([[在 %d 格范围内随机传送你自己。
		在等级4时，你可以传送指定生物（怪物或被护送者）。
		在等级5时，你可以选择传送位置（半径 %d ）。如果目标位置不在你的视线里，则法术有可能失败。
		受法术强度影响，影响范围有额外加成。]]):format(range, radius)
	end,
}

newTalent{
	name = "Teleport",
	display_name = "传送",
	type = {"spell/conveyance",2},
	require = spells_req2,
	points = 5,
	random_ego = "utility",
	mana = 20,
	cooldown = 30,
	tactical = { ESCAPE = 3 },
	requires_target = function(self, t) return self:getTalentLevel(t) >= 4 end,
	getRange = function(self, t) return 100 + self:combatSpellpower(1) end,
	getRadius = function(self, t) return 20 - self:getTalentLevel(t) end,
	is_teleport = true,
	action = function(self, t)
		local target = self

		if self:getTalentLevel(t) >= 4 then
			game.logPlayer(self, "Selects a target to teleport...")
			local tg = {default_target=self, type="hit", nowarning=true, range=10, first_target="friend"}
			local tx, ty = self:getTarget(tg)
			if tx then
				local _ _, tx, ty = self:canProject(tg, tx, ty)
				if tx then
					target = game.level.map(tx, ty, Map.ACTOR) or self
				end
			end
		end

		if target ~= self and target:canBe("teleport") then
			local hit = self:checkHit(self:combatSpellpower(), target:combatSpellResist() + (target:attr("continuum_destabilization") or 0))
			if not hit then
				game.logSeen(target, "The spell fizzles!")
				return true
			end
		end

		-- Annoy them!
		if target ~= self and target:reactionToward(self) < 0 then target:setTarget(self) end

		local x, y = self.x, self.y
		if self:getTalentLevel(t) >= 5 then
			game.logPlayer(self, "Selects a teleport location...")
			local tg = {type="ball", nolock=true, pass_terrain=true, nowarning=true, range=t.getRange(self, t), radius=t.getRadius(self, t), requires_knowledge=false}
			x, y = self:getTarget(tg)
			if not x then return nil end
			-- Target code does not restrict the target coordinates to the range, it lets the project function do it
			-- but we cant ...
			local _ _, x, y = self:canProject(tg, x, y)
			game.level.map:particleEmitter(target.x, target.y, 1, "teleport")
			target:teleportRandom(x, y, t.getRadius(self, t))
			game.level.map:particleEmitter(target.x, target.y, 1, "teleport")
		else
			game.level.map:particleEmitter(target.x, target.y, 1, "teleport")
			target:teleportRandom(x, y, t.getRange(self, t), 15)
			game.level.map:particleEmitter(target.x, target.y, 1, "teleport")
		end

		if target ~= self then
			target:setEffect(target.EFF_CONTINUUM_DESTABILIZATION, 100, {power=self:combatSpellpower(0.3)})
		end

		game:playSoundNear(self, "talents/teleport")
		return true
	end,
	info = function(self, t)
		local range = t.getRange(self, t)
		local radius = t.getRadius(self, t)
		return ([[在 %d 格范围内随机传送，最小距离15.
		在等级4时，你可以传送指定生物（怪物或被护送者）。
		在等级5时，你可以选择传送位置（半径 %d ）。
		受法术强度影响，影响范围有额外加成。]]):format(range, radius)
	end,
}

newTalent{
	name = "Displacement Shield",
	display_name = "相位护盾",
	type = {"spell/conveyance", 3},
	require = spells_req3,
	points = 5,
	mana = 70,
	cooldown = 35,
	tactical = { DEFEND = 2 },
	range = 8,
	requires_target = true,
	getTransferChange = function(self, t) return 40 + self:getTalentLevel(t) * 5 end,
	getMaxAbsorb = function(self, t) return 50 + self:combatTalentSpellDamage(t, 20, 400) end,
	getDuration = function(self, t) return util.bound(10 + math.floor(self:getTalentLevel(t) * 3), 10, 25) end,
	action = function(self, t)
		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)
		target = game.level.map(tx, ty, Map.ACTOR)
		if target == self then target = nil end
		if not target then return end

		self:setEffect(self.EFF_DISPLACEMENT_SHIELD, t.getDuration(self, t), {power=t.getMaxAbsorb(self, t), target=target, chance=t.getTransferChange(self, t)})
		game:playSoundNear(self, "talents/teleport")
		return true
	end,
	info = function(self, t)
		local chance = t.getTransferChange(self, t)
		local maxabsorb = t.getMaxAbsorb(self, t)
		local duration = t.getDuration(self, t)
		return ([[这个复杂的法术可以扭曲施法者周围的空间，此空间可连接至范围内的另外1个目标。
		任何时候，施法者所承受的伤害有 %d%% 的概率转移给指定连接的目标。
		一旦吸收伤害达到上限（ %d ），持续时间到了（ %d 回合）或目标死亡，护盾会破碎掉。
		受法术强度影响，护盾的伤害最大吸收值有额外加成。]]):
		format(chance, maxabsorb, duration)
	end,
}

newTalent{
	name = "Probability Travel",
	display_name = "次元移动",
	type = {"spell/conveyance",4},
	mode = "sustained",
	require = spells_req4,
	points = 5,
	cooldown = 40,
	sustain_mana = 200,
	tactical = { ESCAPE = 1, CLOSEIN = 1 },
	getRange = function(self, t) return math.floor(4 + self:combatSpellpower(0.06) * self:getTalentLevel(t)) end,
	activate = function(self, t)
		game:playSoundNear(self, "talents/teleport")
		return {
			prob_travel = self:addTemporaryValue("prob_travel", t.getRange(self, t)),
		}
	end,
	deactivate = function(self, t, p)
		self:removeTemporaryValue("prob_travel", p.prob_travel)
		return true
	end,
	info = function(self, t)
		local range = t.getRange(self, t)
		return ([[当你击中一个固体表面时，此法术会撕裂位面将你瞬间传送至另一面。
		传送最大距离为 %d 格。
		受法术强度影响，传送距离有额外加成。]]):
		format(range)
	end,
}
