-- 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 = "Grappling Stance",
	display_name = "抓取姿态",
	type = {"technique/unarmed-other", 1},
	mode = "sustained",
	hide = true,
	points = 1,
	cooldown = 12,
	tactical = { BUFF = 2 },
	type_no_req = true,
	no_npc_use = true, -- They dont need it since it auto switches anyway
	no_unlearn_last = true,
	getSave = function(self, t) return self:getStr(20, true) end,
	getDamage = function(self, t) return self:getStr(10, true) end,
	activate = function(self, t)
		cancelStances(self)
		local ret = {
			phys = self:addTemporaryValue("combat_physresist", t.getSave(self, t)),
			power = self:addTemporaryValue("combat_dam", t.getDamage(self, t)),
		}
		return ret
	end,
	deactivate = function(self, t, p)
		self:removeTemporaryValue("combat_physresist", p.phys)
		self:removeTemporaryValue("combat_dam", p.power)
		return true
	end,
	info = function(self, t)
		local save = t.getSave(self, t)
		local damage = t.getDamage(self, t)
		return ([[增加你的物理抗性 %d 和你的物理强度 %d。
		增益效果受你的力量加成。]])
		:format(save, damage)
	end,
}

newTalent{
	name = "Clinch",
	display_name = "关节技：锁钳",
	type = {"technique/grappling", 1},
	require = techs_req1,
	points = 5,
	random_ego = "attack",
	cooldown = 6,
	stamina = 5,
	tactical = { ATTACK = 2, DISABLE = 2 },
	requires_target = true,
	getDuration = function(self, t) return 4 + math.floor(self:getTalentLevel(t)) end,
	getPower = function(self, t) return self:combatTalentPhysicalDamage(t, 5, 25) end,
	getDrain = function(self, t) return 6 - math.max(1, self:getTalentLevelRaw(t) or 0) end,
	-- Learn the appropriate stance
	on_learn = function(self, t)
		if not self:knowTalent(self.T_GRAPPLING_STANCE) then
			self:learnTalent(self.T_GRAPPLING_STANCE, true, nil, {no_unlearn=true})
		end
	end,
	on_unlearn = function(self, t)
		if not self:knowTalent(t) then
			self:unlearnTalent(self.T_GRAPPLING_STANCE)
		end
	end,
	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 core.fov.distance(self.x, self.y, x, y) > 1 then return nil end

		local grappled = false

		-- force stance change
		if target and not self:isTalentActive(self.T_GRAPPLING_STANCE) then
			self:forceUseTalent(self.T_GRAPPLING_STANCE, {ignore_energy=true, ignore_cd = true})
		end

		-- breaks active grapples if the target is not grappled
		if target:isGrappled(self) then
			grappled = true
		else
			self:breakGrapples()
		end

		-- end the talent without effect if the target is to big
		if self:grappleSizeCheck(target) then
			return true
		end

		-- start the grapple; this will automatically hit and reapply the grapple if we're already grappling the target
		local hit = self:startGrapple(target)

		local duration = t.getDuration(self, t)

		-- do crushing hold or strangle if we're already grappling the target
		if hit and self:knowTalent(self.T_CRUSHING_HOLD) then
			local t = self:getTalentFromId(self.T_CRUSHING_HOLD)
			if grappled and not target.no_breath and not target.undead and target:canBe("silence") then
				target:setEffect(target.EFF_STRANGLE_HOLD, duration, {src=self, power=t.getDamage(self, t) * 1.5})
			else
				target:setEffect(target.EFF_CRUSHING_HOLD, duration, {src=self, power=t.getDamage(self, t)})
			end
		end

		return true
	end,
	info = function(self, t)
		local duration = t.getDuration(self, t)
		local power = t.getPower(self, t)
		local drain = t.getDrain(self, t)
		return ([[抓取目标(可抓取目标的身材最多比你大1倍)持续 %d 回合。1个被钳住的对手将无法移动并且他的攻击和闪避降低 %d 。任何目标或你的移动将会打破抓取。维持抓取每回合消耗 %d 体力。
		同时你只能抓取1个目标，并且对任意1个你没有抓取的目标使用徒手指向均会打破抓取。
		受物理强度影响，因抓取而造成的攻击、防御减值和成功率有额外加成。
		此技能成功后，你的姿态会自动切换为抓取姿态。]])
		:format(duration, power, drain)
	end,
}

newTalent{
	name = "Maim",
	display_name = "关节技：碎骨",
	type = {"technique/grappling", 2},
	require = techs_req2,
	points = 5,
	random_ego = "attack",
	cooldown = 12,
	stamina = 10,
	tactical = { ATTACK = { PHYSICAL = 2 }, DISABLE = 2 },
	requires_target = true,
	getDuration = function(self, t) return 2 + math.floor(self:getTalentLevel(t)) end,
	getDamage = function(self, t) return self:combatTalentPhysicalDamage(t, 10, 100) * getUnarmedTrainingBonus(self) end,
	getMaim = function(self, t) return self:combatTalentPhysicalDamage(t, 5, 30) end,
	-- Learn the appropriate stance
	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 core.fov.distance(self.x, self.y, x, y) > 1 then return nil end

		local grappled = false

		-- breaks active grapples if the target is not grappled
		if target:isGrappled(self) then
			grappled = true
		else
			self:breakGrapples()
		end

		-- end the talent without effect if the target is to big
		if self:grappleSizeCheck(target) then
			return true
		end

		-- start the grapple; this will automatically hit and reapply the grapple if we're already grappling the target
		local hit = self:startGrapple (target)
		-- deal damage and maim if appropriate
		if hit then
			if grappled then
				self:project(target, x, y, DamageType.PHYSICAL, self:physicalCrit(t.getDamage(self, t), nil, target, self:combatAttack(), target:combatDefense()))
				target:setEffect(target.EFF_MAIMED, t.getDuration(self, t), {power=t.getMaim(self, t)})
			else
				self:project(target, x, y, DamageType.PHYSICAL, self:physicalCrit(t.getDamage(self, t), nil, target, self:combatAttack(), target:combatDefense()))
			end
		end

		return true
	end,
	info = function(self, t)
		local duration = t.getDuration(self, t)
		local damage = t.getDamage(self, t)
		local maim = t.getMaim(self, t)
		return ([[抓取目标并给予 %0.2f 物理伤害。如果目标已被抓取，则目标会被致残，减少 %d 伤害和30%%整体速度持续 %d 回合。
		抓取效果受你已有的抓取技能影响。
		受物理强度影响，伤害有额外加成。]])
		:format(damDesc(self, DamageType.PHYSICAL, (damage)), maim, duration)
	end,
}

newTalent{
	name = "Crushing Hold",
	display_name = "关节技：折颈",
	type = {"technique/grappling", 3},
	require = techs_req3,
	mode = "passive",
	points = 5,
	tactical = { ATTACK = { PHYSICAL = 2 }, DISABLE = { silence = 2 } },
	requires_target = true,
	getDamage = function(self, t) return self:combatTalentPhysicalDamage(t, 5, 50) * getUnarmedTrainingBonus(self) end,
	info = function(self, t)
		local damage = t.getDamage(self, t)
		return ([[你的抓取天赋受到强化，可勒紧目标，每回合可造成 %0.2f 物理伤害。如果目标已被抓取那么技能会造成一次强力的勒颈效果，沉默目标并造成每回合 %0.2f 物理伤害。
		不死族对此技能的沉默效果免疫，此技能对不用呼吸的生物造成的窒息效果免疫，只会产生折颈所造成的物理伤害。
		受物理强度影响，伤害按比例加成。]])
		:format(damDesc(self, DamageType.PHYSICAL, (damage)), damDesc(self, DamageType.PHYSICAL, (damage * 1.5)))
	end,
}

newTalent{
	name = "Take Down",
	display_name = "关节技：抱摔",
	type = {"technique/grappling", 4},
	require = techs_req4,
	points = 5,
	random_ego = "attack",
	cooldown = 24,
	stamina = 12,
	tactical = { ATTACK = { PHYSICAL = 1, stun = 1}, DISABLE = { stun = 2 }, CLOSEIN = 2 },
	requires_target = true,
	range = function(self, t) return 2 + math.floor(self:getTalentLevel(t)/3) end,
	getDuration = function(self, t) return 2 + math.floor(self:getTalentLevel(t)) end,
	getTakeDown = function(self, t) return self:combatTalentPhysicalDamage(t, 10, 100) * getUnarmedTrainingBonus(self) end,
	getSlam = function(self, t) return self:combatTalentPhysicalDamage(t, 15, 150) * getUnarmedTrainingBonus(self) end,
	-- Learn the appropriate stance
	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 core.fov.distance(self.x, self.y, x, y) > self:getTalentRange(t) then return nil end

		local grappled = false

		-- do the rush
		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()
		local tx, ty = self.x, self.y
		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

		-- breaks active grapples if the target is not grappled
		if target:isGrappled(self) then
			grappled = true
		else
			self:breakGrapples()
		end

		if core.fov.distance(self.x, self.y, x, y) == 1 then
			-- end the talent without effect if the target is to big
			if self:grappleSizeCheck(target) then
				return true
			end

			-- start the grapple; this will automatically hit and reapply the grapple if we're already grappling the target
			local hit = self:startGrapple (target)
			-- takedown or slam as appropriate
			if hit then
				if grappled then
					self:project(target, x, y, DamageType.PHYSICAL, self:physicalCrit(t.getSlam(self, t), nil, target, self:combatAttack(), target:combatDefense()))
					if target:canBe("stun") then
						target:setEffect(target.EFF_STUNNED, t.getDuration(self, t), {apply_power=self:combatPhysicalpower()})
					else
						game.logSeen(target, "%s resists the stun!", target.name:capitalize())
					end
				else
					self:project(target, x, y, DamageType.PHYSICAL, self:physicalCrit(t.getTakeDown(self, t), nil, target, self:combatAttack(), target:combatDefense()))
					if target:canBe("stun") then
						target:setEffect(target.EFF_DAZED, t.getDuration(self, t), {apply_power=self:combatPhysicalpower()})
					else
						game.logSeen(target, "%s resists the daze!", target.name:capitalize())
					end
				end
			end
		end

		return true
	end,
	info = function(self, t)
		local duration = t.getDuration(self, t)
		local takedown = t.getTakeDown(self, t)
		local slam = t.getSlam(self, t)
		return ([[向目标冲锋并把目标压倒在地钳制住，造成 %0.2f 物理伤害，眩晕目标 %d 回合。如果你已经抓取此目标，则会将他们摔到地上造成 %0.2f 物理伤害，有可能眩晕目标 %d 回合。
		抓取效果受你已有的抓取技能影响，受物理强度影响，伤害有额外加成。]])
		:format(damDesc(self, DamageType.PHYSICAL, (takedown)), duration, damDesc(self, DamageType.PHYSICAL, (slam)), duration)
	end,
}

