THTD_MAX_LEVEL = 10
THTD_MAX_ITEM_SLOT = 9
THTD_ITEM_TPSCROLL_SLOT = 15
THTD_ITEM_Neutral_SLOT = 16

thtd_exp_table={200,500,900,1400,2000,2700,3500,4400,5400}
thtd_exp_star_table={1,2/3,1/3,1/5,1/15}
-- 总和5400
-- 经验分配规则 保底 1X每只30点 2X每只20点，3X每只10点，4X每只6点，5X每只3点
-- 单吃一个兵经验 300点 200点 100点 60点 30点
-- 经验获取率1X 100% 2X 2/3 3X 1/3 4X 1/5 5X 1/10 
-- 素材培养 （1000+素材卡牌经验/5）* 星级

towerPlayerList = {[1] = {}, [2] = {}, [3] = {},[4] = {}}

towerNameList = table.loadkv("scripts/npc/tower.txt")

local thtd_power_table = table.loadkv("scripts/npc/power_table.txt")
local thtd_attack_factor = table.loadkv("scripts/npc/attack_factor.txt")
local thtd_ability_table = table.loadkv("scripts/npc/ability_table.txt") 
local thtd_combo_table = table.loadkv("scripts/npc/combo_table.txt") 



--------------------------------------------------

-- 初始化tower
function CDOTA_BaseNPC:THTD_InitExp()
	self.thtd_star = 1	
	self.thtd_level = 1
	self.thtd_exp = 0		
	self.thtd_is_ex = false
	self.thtd_is_tower = true
	self.thtd_close_ai = false
	self.thtd_tower_damage = 0	

	if self:GetUnitName() == "minoriko" or self:GetUnitName() == "sizuha" then
		if GameRules:GetCustomGameDifficulty() >= FUNNY_MODE and self:GetUnitName() == "minoriko" then 	
			self.thtd_star = 3	
		end
		self.thtd_level = THTD_MAX_LEVEL
		self.thtd_exp = thtd_exp_table[THTD_MAX_LEVEL - 1]	
		self.thtd_is_changed = false
		if GameRules:GetCustomGameDifficulty() < FUNNY_MODE and SpawnSystem.IsUnLimited ~= true then
			local time_count = 0
			local add = 0
			self:SetContextThink(DoUniqueString("thtd_minoriko_star_up_listen"), 
				function()
					if GameRules:IsGamePaused() then return 0.03 end				
					if self == nil or self:IsNull() or self:IsAlive() == false then return nil end
					if SpawnSystem.IsUnLimited then return nil end								
					
					if self.thtd_star < 5 and self:THTD_IsHidden() == false then
						if self.thtd_is_changed == true then
							time_count = 0
							self.thtd_is_changed = false
						end

						local totalTime = self:GetAbilityValue("thtd_"..self:GetUnitName().."_01", "grow_time")
			
						add = 1 + self:GetAbilityValue("ability_common_star_up_speed", "speed_tooltips", true)
						time_count = time_count + add
												
						-- OVERHEAD_ALERT_OUTGOING_DAMAGE
						SendOverheadEventMessage(self:GetPlayerOwner(), OVERHEAD_ALERT_BONUS_POISON_DAMAGE, self, math.max(0, totalTime - time_count), self:GetPlayerOwner() )
						
						if time_count >= totalTime then
							self.thtd_star = self.thtd_star + 1
							self:THTD_OpenAbility()
							self:THTD_DestroyLevelEffect()
							self:THTD_CreateLevelEffect()
							time_count = 0						
							if self.thtd_star == 5 then								
								EmitSoundOn(THTD_GetVoiceEvent(self:GetUnitName(),"spawn"),self)				
								CustomGameEventManager:Send_ServerToPlayer(self:GetPlayerOwner() , "show_message", {msg=self:GetUnitName().."_up_to_5_star", duration=30, params={}, color="#ff0"} )
							end
						end
					end
					return 1.0
				end, 
			1.0)	
		end	
	end	

	self.thtd_power = self:THTD_GetGrowPower()
	self.thtd_power_percentage = 0

	self.thtd_attack = self:THTD_GetGrowAttack()
	self.thtd_attack_percentage = 0	

	self.thtd_crit_chance = 0
	self.thtd_crit_damage = 0
	self:THTD_AddCritDamage(50)
	self:THTD_AddCritChance(5)
	
	self.thtd_mana_regen = self:GetManaRegen()
	self.thtd_mana_regen_percentage = 0	
	self.thtd_mana_cost_reduce_percentage = 0

	self.thtd_attack_speed_bonus = 0
	self.thtd_cooldown_percentage = 0	

	self.thtd_extra_star_damage = 0

	self.thtd_damage_magical_percentage = 0
	self.thtd_damage_physical_percentage = 0
	self.thtd_damage_pure_percentage = 0

	self:THTD_CreateLevelEffect()
	self:SetHasInventory(true)
	self:THTD_OpenAbility()
	
	self:THTD_RefreshPowerUI()
	self:THTD_RefreshAttack()		
end



--------------------------------------------------

function CDOTA_BaseNPC:THTD_IsTower()
	return self.thtd_is_tower or false
end

function CDOTA_BaseNPC:THTD_IsHidden()
	if self:HasModifier("modifier_touhoutd_release_hidden") then
		return true
	end
	return false
end

function CDOTA_BaseNPC:GetHero()
	if self:GetTeamNumber() == DOTA_TEAM_GOODGUYS then 
		-- local player = PlayerResource:GetPlayer(self:GetPlayerOwnerID())
		-- return player:GetAssignedHero()
		return GameRules.HeroList[self:GetPlayerOwnerID()]
	elseif self.thtd_player_index ~= nil then 
		return GameRules.HeroList[self.thtd_player_index]
	end
	return nil
end

function THTD_IsTowerInList(hero,towername)
	for k,v in pairs(hero.thtd_hero_tower_list) do
		if v~=nil and v:IsNull() == false then
			if v:GetUnitName() == towername then
				return true
			end
		end
	end
	return false
end

function THTD_GetCombo(tower)
	local comboTable = {}
	for index,value in pairs(thtd_combo_table) do
		local count = 0
		local isInCombo = false

		for k,v in pairs(value) do
			if THTD_IsTowerInList(tower:GetOwner(),v) == true then
				count = count + 1
			end
			if tower:GetUnitName() == v then
				isInCombo = true
			end
		end
		if count == #value and isInCombo == true then
			comboTable[index] = value
		end
	end

	if comboTable ~= nil then
		return comboTable
	end
	return nil
end

function CDOTA_BaseNPC:THTD_HeroComboRefresh()
	local hero = GameRules.HeroList[self:GetPlayerOwnerID()]
    if hero == nil then return end

	for index,tower in pairs(hero.thtd_hero_tower_list) do
		if THTD_IsValid(tower) then
			local combo = THTD_GetCombo(tower)			
			local func = tower["THTD_"..tower:GetUnitName().."_thtd_combo"]
			if func then
				local changeCombo = func(tower,combo)
				if changeCombo ~= nil and #changeCombo > 0 then
					for k,v in pairs(changeCombo) do	
						v["unit"] = tower
						local exist = false
						for k2,v2 in pairs(hero.thtd_combo_voice_array) do
							if v2["unit"] == v["unit"] then 
								exist = true
								break
							end
						end
						if exist == false then 
							table.insert(hero.thtd_combo_voice_array, v)
						end							
					end	
					changeCombo = {}									
				end		
			else				
				local changeCombo = tower:THTD_Set_Combo(combo)
				if changeCombo ~= nil and #changeCombo > 0 then
					for k,v in pairs(changeCombo) do	
						v["unit"] = tower
						local exist = false
						for k2,v2 in pairs(hero.thtd_combo_voice_array) do
							if v2["unit"] == v["unit"] then 
								exist = true
								break
							end
						end
						if exist == false then 
							table.insert(hero.thtd_combo_voice_array, v)
						end							
					end	
					changeCombo = {}									
				end
			end
		end
	end	

	hero:SetContextThink(DoUniqueString("thtd_combo_voice_array"), 
		function()
			if hero.is_game_over == true then return nil end	
			if hero.thtd_combo_voice_array == nil or #hero.thtd_combo_voice_array == 0 then
				hero.sound_lock = nil 
				return nil 
			end

			for k,v in pairs(hero.thtd_combo_voice_array) do
				if v~=nil and v["comboName"] == "lyrica_lunasa_merlin" then
					if v["unit"]~=nil and v["unit"]:IsNull()==false then
						EmitSoundOn(THTD_GetVoiceEvent(v["unit"]:GetUnitName(),"combo."..v["comboName"]),v["unit"])
						table.remove(hero.thtd_combo_voice_array,k)
					end
				elseif v~=nil and hero.sound_lock == nil then
					hero.sound_lock = true
					hero:SetContextThink(DoUniqueString("wait_voice_play_end"), 
						function()							
							hero.sound_lock = false
							return nil
						end,
					v["delay"]+0.5)
				elseif v~=nil and hero.sound_lock == false then
					hero.sound_lock = true
					if v["unit"]~=nil and v["unit"]:IsNull()==false then						
						EmitSoundOn(THTD_GetVoiceEvent(v["unit"]:GetUnitName(),"combo."..v["comboName"]),v["unit"])
					end
					hero:SetContextThink(DoUniqueString("wait_voice_play_end"), 
						function()							
							hero.sound_lock = false
							table.remove(hero.thtd_combo_voice_array,k)
							return nil
						end,
					v["duration"]+0.5)
				end
			end
			return 0.5
		end,
	0)
end



--------------------------------------------------

function CDOTA_BaseNPC:THTD_GetExp()
	return self.thtd_exp
end

function CDOTA_BaseNPC:THTD_AddExp(exp)		
	self.thtd_exp = self.thtd_exp + exp * thtd_exp_star_table[self.thtd_star]
	self:THTD_ExpToLevelUp()
end

function CDOTA_BaseNPC:THTD_ExpToLevelUp()
	if self:THTD_GetLevel() < THTD_MAX_LEVEL then
		if self.thtd_exp >= thtd_exp_table[self.thtd_level] then
			if self.thtd_exp >= thtd_exp_table[THTD_MAX_LEVEL-1] then
				self:THTD_SetLevel(THTD_MAX_LEVEL)				
				return
			end
			for i=self.thtd_level,(THTD_MAX_LEVEL-1) do
				if self.thtd_exp < thtd_exp_table[i] then
					self:THTD_SetLevel(i)
					return
				end
			end
		end
	end	
end

function CDOTA_BaseNPC:THTD_GetLevel()
	return self.thtd_level
end

function CDOTA_BaseNPC:THTD_SetLevel(level)
	if level > THTD_MAX_LEVEL then 
		level = THTD_MAX_LEVEL
	end
	if level == self.thtd_level then 
		return 
	end

	local lastPower = self:THTD_GetGrowPower()
	local lastAttack = self:THTD_GetGrowAttack()

	self.thtd_level = level
	if self.thtd_level == THTD_MAX_LEVEL then 
		self.thtd_exp = thtd_exp_table[THTD_MAX_LEVEL-1] + 1
	end

	self.thtd_power = self.thtd_power - lastPower + self:THTD_GetGrowPower()
	self.thtd_attack = self.thtd_attack - lastAttack + self:THTD_GetGrowAttack()

	local effectIndex = ParticleManager:CreateParticle("particles/econ/events/ti6/hero_levelup_ti6_godray.vpcf", PATTACH_CUSTOMORIGIN, self)
	ParticleManager:SetParticleControl(effectIndex, 0, self:GetOrigin())
	ParticleManager:DestroyParticleSystem(effectIndex,false)

	self:EmitSound("Sound_THTD.thtd_level_up")

	self:THTD_DestroyLevelEffect()
	self:THTD_CreateLevelEffect()

	self:THTD_RefreshPowerUI()
	self:THTD_RefreshAttack()
end

function CDOTA_BaseNPC:THTD_LevelUp(level)		
	if self.thtd_level == THTD_MAX_LEVEL then 
		return 
	end
	if level == nil then 
		level = 1
	end
	
	local lastPower = self:THTD_GetGrowPower()
	local lastAttack = self:THTD_GetGrowAttack()	

	self.thtd_level = math.min(THTD_MAX_LEVEL, self.thtd_level + level)
	self.thtd_exp = thtd_exp_table[self.thtd_level-1]

	self.thtd_power = self.thtd_power - lastPower + self:THTD_GetGrowPower()
	self.thtd_attack = self.thtd_attack - lastAttack + self:THTD_GetGrowAttack()

	local effectIndex = ParticleManager:CreateParticle("particles/econ/events/ti6/hero_levelup_ti6_godray.vpcf", PATTACH_CUSTOMORIGIN, self)
	ParticleManager:SetParticleControl(effectIndex, 0, self:GetOrigin())
	ParticleManager:DestroyParticleSystem(effectIndex,false)

	self:EmitSound("Sound_THTD.thtd_level_up")

	self:THTD_DestroyLevelEffect()
	self:THTD_CreateLevelEffect()

	self:THTD_RefreshPowerUI()
	self:THTD_RefreshAttack()
end



--------------------------------------------------

function CDOTA_BaseNPC:THTD_GetStar()
	return self.thtd_star
end

function CDOTA_BaseNPC:THTD_SetStar(star)
	if star > 5 then 
		star = 5
	end
	if star == self.thtd_star then 
		return 
	end

	local lastPower = self:THTD_GetGrowPower()
	local lastAttack = self:THTD_GetGrowAttack()		

	self.thtd_star = star
	self.thtd_level = 1
	self.thtd_exp = 0
	
	self.thtd_power = self.thtd_power - lastPower + self:THTD_GetGrowPower()
	self.thtd_attack = self.thtd_attack - lastAttack + self:THTD_GetGrowAttack()

	self:THTD_DestroyLevelEffect()
	self:THTD_CreateLevelEffect()
	self:SetMana(0)
	self:THTD_OpenAbility()

	self:EmitSound("Sound_THTD.thtd_star_up")

	local effectIndex = ParticleManager:CreateParticle("particles/heroes/byakuren/ability_byakuren_02.vpcf", PATTACH_CUSTOMORIGIN, self)
	ParticleManager:SetParticleControl(effectIndex, 0, self:GetOrigin())
	ParticleManager:SetParticleControl(effectIndex, 1, self:GetOrigin())
	ParticleManager:DestroyParticleSystem(effectIndex,false)

	self:THTD_RefreshPowerUI()
	self:THTD_RefreshAttack()
	self:THTD_HeroComboRefresh()
end

function CDOTA_BaseNPC:THTD_StarUp()
	if self.thtd_star == 5 then 
		return 
	end
	
	local lastPower = self:THTD_GetGrowPower()
	local lastAttack = self:THTD_GetGrowAttack()	

	self.thtd_star = self.thtd_star + 1
	self.thtd_level = 1
	self.thtd_exp = 0

	self.thtd_power = self.thtd_power - lastPower + self:THTD_GetGrowPower()
	self.thtd_attack = self.thtd_attack - lastAttack + self:THTD_GetGrowAttack()	

	self:THTD_DestroyLevelEffect()
	self:THTD_CreateLevelEffect()
	self:SetMana(0)
	self:THTD_OpenAbility()

	self:EmitSound("Sound_THTD.thtd_star_up")

	local effectIndex = ParticleManager:CreateParticle("particles/heroes/byakuren/ability_byakuren_02.vpcf", PATTACH_CUSTOMORIGIN, self)
	ParticleManager:SetParticleControl(effectIndex, 0, self:GetOrigin())
	ParticleManager:SetParticleControl(effectIndex, 1, self:GetOrigin())
	ParticleManager:DestroyParticleSystem(effectIndex,false)

	self:THTD_RefreshPowerUI()
	self:THTD_RefreshAttack()
	self:THTD_HeroComboRefresh()
end

function CDOTA_BaseNPC:THTD_CreateLevelEffect()
	if self.thtd_is_effect_open == true then return end
	self.thtd_level_effect = ParticleManager:CreateParticle("particles/thtd/msg/thtd_msg_level.vpcf", PATTACH_CUSTOMORIGIN, self)
	if self.thtd_level < 10 then
		ParticleManager:SetParticleControl(self.thtd_level_effect, 0, self:GetOrigin())
		ParticleManager:SetParticleControl(self.thtd_level_effect, 2, Vector(0,1,0))
		ParticleManager:SetParticleControl(self.thtd_level_effect, 3, Vector(0,self.thtd_level,0))
	else
		ParticleManager:SetParticleControl(self.thtd_level_effect, 0, self:GetOrigin())
		ParticleManager:SetParticleControl(self.thtd_level_effect, 2, Vector(0,2,0))
		ParticleManager:SetParticleControl(self.thtd_level_effect, 3, Vector(0,10,0))
	end

	self.thtd_star_effect = ParticleManager:CreateParticle("particles/thtd/msg/thtd_msg_star.vpcf", PATTACH_CUSTOMORIGIN, self)

	ParticleManager:SetParticleControl(self.thtd_star_effect, 0, self:GetOrigin())
	ParticleManager:SetParticleControl(self.thtd_star_effect, 2, Vector(0,self.thtd_star,0))
	ParticleManager:SetParticleControl(self.thtd_star_effect, 3, Vector(0,0,0))
	self.thtd_is_effect_open = true
end

function CDOTA_BaseNPC:THTD_DestroyLevelEffect()
	ParticleManager:DestroyParticleSystem(self.thtd_level_effect,true)
	ParticleManager:DestroyParticleSystem(self.thtd_star_effect,true)
	self.thtd_is_effect_open = false
end

local thtd_bonus_ability_table = 
{
	"ability_common_attack_speed_buff",
	"ability_common_power_buff",
	"ability_common_mana_regen_buff",
	"ability_common_decrease_armor_buff",
	"ability_common_decrease_magic_armor_buff",
	"ability_common_star_up_speed",
}

function CDOTA_BaseNPC:THTD_SetAbilityLevelUp()
	for k,v in pairs(thtd_bonus_ability_table) do
		local ability=self:FindAbilityByName(v)
		if ability ~= nil then
			if ability:GetLevel() < ability:GetMaxLevel() then
				ability:SetLevel(ability:GetLevel()+1)
			end
		end
	end
end

function CDOTA_BaseNPC:THTD_OpenAbility()
	local unitName = self:GetUnitName()
	if self:THTD_IsTowerEx() == true then
		unitName = unitName.."_ex"
	end
	-- 如果技能有光环，需要设置光环非被动，命名固定为 modifier_技能名_aura，且在 AbilitySpecial 中定义 open_aura_level 大于0，技能类型必须为 ability_datadriven
	for k,v in pairs(thtd_ability_table[unitName]) do
		for abilityName,level in pairs(v) do
			local ability = self:FindAbilityByName(abilityName)
			if ability ~= nil then 
				if self:THTD_GetStar() == k then
					if ability:GetLevel() ~= level then							
						local auraName = "modifier_"..abilityName.."_aura"
						if level < 1 then	
							local auraLevel = ability:GetSpecialValueFor("open_aura_level")						
							if auraLevel > 0 and self:HasModifier(auraName) then
								self:RemoveModifierByName(auraName)
							end
							ability:SetLevel(level)
							ability:SetActivated(false)	
							self[abilityName.."bonus_level"] = nil	
						else
							ability:SetActivated(true)
							ability:SetLevel(level)
							self[abilityName.."bonus_level"] = nil	
							local auraLevel = ability:GetSpecialValueFor("open_aura_level")
							if auraLevel > 0 then
								if level >= auraLevel then
									if self:HasModifier(auraName) == false then 
										ability:ApplyDataDrivenModifier(self, self, auraName, nil)
									end
								else
									if self:HasModifier(auraName) then
										self:RemoveModifierByName(auraName)
									end
								end
							end
						end						
					end
					
					-- local kv = ability:GetAbilityKeyValues()	
					-- if kv["Modifiers"] ~= nil then			
					-- 	for k2,v2 in pairs(kv["Modifiers"]) do
					-- 		print(k2)
					-- 		PrintTable(v2)							
					-- 		if v2["Passive"] == 1 and self:HasModifier(k2) == false then
					-- 			print("-----------add")
					-- 			ability:ApplyDataDrivenModifier(self, self, k2, nil)
					-- 		end 
					-- 	end
					-- end

				end
			end
		end
	end
end

function CDOTA_BaseNPC:THTD_UpgradeEx()
	local unitName = self:GetUnitName()
	local star = self:THTD_GetStar()
	local level = self:THTD_GetLevel()

	for k,v in pairs(thtd_ability_table[unitName]) do
		for abilityName,level in pairs(v) do
			if self:THTD_GetStar() == k then
				self:RemoveAbility(abilityName)
			end
		end
	end
	unitName = self:GetUnitName().."_ex"

	for k,v in pairs(thtd_ability_table[unitName]) do
		for abilityName,level in pairs(v) do
			if self:THTD_GetStar() == k then
				local ability=self:AddAbility(abilityName)
				ability:SetLevel(level)
			end
		end
	end

	self:THTD_SetStar(1)
	self:THTD_SetLevel(1)
	self.thtd_is_ex = true
	self:THTD_SetStar(star)
	self:THTD_SetLevel(level)
end

function CDOTA_BaseNPC:THTD_IsTowerEx()
	return self.thtd_is_ex or false
end


-- 获取每波塔的总伤害量，单位百
function CDOTA_BaseNPC:THTD_GetTowerDamage()
	if not self:THTD_IsTower() then 
		return 0
	end
	return self.thtd_tower_damage
end

-- 累计塔的伤害量，自动除以100
function CDOTA_BaseNPC:THTD_AddTowerDamage(damage)
	if not self:THTD_IsTower() then 
		return
	end
	self.thtd_tower_damage = self.thtd_tower_damage + damage/100
end

-- 重置塔的伤害量
function CDOTA_BaseNPC:THTD_ResetTowerDamage()
	if not self:THTD_IsTower() then 
		return
	end
	self.thtd_tower_damage = 0
end



--------------------------------------------------

local thtd_mana_regen_black_list = 
{
	"lily",
}

function CDOTA_BaseNPC:IsInManaRegenBlackList()
	for k,v in pairs(thtd_mana_regen_black_list) do
		if self:GetUnitName() == v then
			return true
		end
	end
	return false
end

-- 增加魔法恢复百分比并刷新，线性叠加
function CDOTA_BaseNPC:THTD_AddManaRegenPercentage(bonus, uniqueString)
	if self.thtd_mana_regen_percentage == nil then 
		return 
	end
	if self:IsInManaRegenBlackList() then
		return
	end
	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_mana_regen"
		if self[uniqueString] ~= nil then
			self.thtd_mana_regen_percentage = self.thtd_mana_regen_percentage - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		if uniqueString == nil then 
			self.thtd_mana_regen_percentage = self.thtd_mana_regen_percentage + bonus	
		else		
			uniqueString = uniqueString.."_mana_regen"
			self.thtd_mana_regen_percentage = self.thtd_mana_regen_percentage + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end
	
	-- print("----- THTD_AddManaRegenPercentage : ", bonus)
	-- print("thtd_mana_regen_percentage : ", self.thtd_mana_regen_percentage)
	self:THTD_RefreshManaRegen()
end

-- 获取魔法恢复百分比
function CDOTA_BaseNPC:THTD_GetManaRegenPercentage()
	if self.thtd_mana_regen_percentage == nil then 
		return 0
	end
	return math.max(-100, self.thtd_mana_regen_percentage)
end

function CDOTA_BaseNPC:THTD_RefreshManaRegen()
	if self.thtd_mana_regen == nil then 
		return 
	end
	local mana_regen = self.thtd_mana_regen * (1 + self:THTD_GetManaRegenPercentage()/100)
	if math.abs(self:GetManaRegen() - mana_regen) > 0.1 then 
		self:SetBaseManaRegen(mana_regen)		
	end	
end



--------------------------------------------------

-- 增加魔法消耗降低百分比，乘法叠加，0-99
function CDOTA_BaseNPC:AddManaCostReducePercent(bonus, uniqueString)
	if self.thtd_mana_cost_reduce_percentage == nil then 
		return
	end	

	if self.mana_cost_reduce_table == nil then 
		self.mana_cost_reduce_table = {}
	end

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_mana_cost_reduce"
		if self.mana_cost_reduce_table[uniqueString] ~= nil then
			local percent = 100
			for k,v in pairs(self.mana_cost_reduce_table) do 
				if k ~= uniqueString and v ~= nil then 
					percent = percent * (1-v/100)
				end				
			end
			self.thtd_mana_cost_reduce_percentage = math.floor(100 - percent)
			self.mana_cost_reduce_table[uniqueString] = nil
		end
	else
		if bonus == nil then 
			bonus = 0 
		end
		if uniqueString == nil then 
			uniqueString = "common"
		end
		uniqueString = uniqueString.."_mana_cost_reduce"		
		self.mana_cost_reduce_table[uniqueString] = bonus
		local percent = 100
		for k,v in pairs(self.mana_cost_reduce_table) do 
			if v ~= nil then 
				percent = percent * (1-v/100)
			end				
		end
		self.thtd_mana_cost_reduce_percentage = math.floor(100 - percent)
	end

	local modifierName = "modifier_manacost_reduce_percent"
	local count = self:GetManaCostReducePercent()
	if count == 0 then
		self:RemoveModifierByName(modifierName)
		return
	end
	local modifier = self:FindModifierByName(modifierName) or self:AddNewModifier(self, nil, modifierName, {})	
	modifier:SetStackCount(count)	
end

-- 获取魔法消耗降低百分比，0-99
function CDOTA_BaseNPC:GetManaCostReducePercent()
	return math.min(99, math.max(0, self.thtd_mana_cost_reduce_percentage or 0))
end

-- 获取技能真实魔法消耗，技能未激活测为0
function CDOTA_BaseNPC:GetRealManaCost(ability)		
	if ability:GetLevel() < 1 then 
		return 0
	end
	return ability:GetManaCost(-1) * (1 - self:GetManaCostReducePercent()/100)
	-- ability:GetManaCost(-1) 和 ability:GetManaCost(ability:GetLevel()-1)都是当前等级数值
end



--------------------------------------------------

-- 获取卡名对应的种类（大写SSR SR R N），无则返回字符NULL
function THTD_GetCardQualityText(unitName)
    local quality = 0
    for k,v in pairs(towerNameList) do
        if v["cardname"] == unitName then
            quality = v["quality"]
            break
        end
    end
    if quality == 1 then
        return "N"
    elseif quality == 2 then
        return "R"
    elseif quality == 3 then
        return "SR"
    elseif quality == 4 then
        return "SSR"
    else
        return "NULL"
    end
end

-- 获取成长属性能量
function CDOTA_BaseNPC:THTD_GetGrowPower()
	local unitName = self:GetUnitName()
	if self:THTD_IsTowerEx() == true then
		unitName = unitName.."_ex"
	end
	if thtd_power_table[unitName] == nil then
		thtd_power_table[unitName] = thtd_power_table[THTD_GetCardQualityText(unitName)]
	end
	return math.floor(thtd_power_table[unitName][self.thtd_star][1] + thtd_power_table[unitName][self.thtd_star][2] * (self:THTD_GetLevel()-1))
end

-- 增加基础能量值
function CDOTA_BaseNPC:THTD_AddBasePower(bonus, uniqueString)
	if self.thtd_power == nil then 
		return 
	end

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_power"
		if self[uniqueString] ~= nil then
			self.thtd_power = self.thtd_power - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_power = self.thtd_power + bonus	
		else		
			uniqueString = uniqueString.."_power"
			self.thtd_power = self.thtd_power + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end

	self:THTD_RefreshPowerUI()
end

-- 获取基础能量
function CDOTA_BaseNPC:THTD_GetBasePower()
	return math.max(0, self.thtd_power or 0)
end

-- 增加能量提升百分比，线性叠加
function CDOTA_BaseNPC:THTD_AddPowerPercentage(bonus, uniqueString)
	if self.thtd_power_percentage == nil then 
		return 
	end	

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_power_percent"
		if self[uniqueString] ~= nil then
			self.thtd_power_percentage = self.thtd_power_percentage - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_power_percentage = self.thtd_power_percentage + bonus	
		else		
			uniqueString = uniqueString.."_power_percent"
			self.thtd_power_percentage = self.thtd_power_percentage + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end

	self:THTD_RefreshPowerUI()
end

-- 获取能量提升百分比
function CDOTA_BaseNPC:THTD_GetPowerPercentage()
	return math.max(-100, self.thtd_power_percentage or 0)
end

-- 获取最终能量
function CDOTA_BaseNPC:THTD_GetPower()
	if self.thtd_power == nil then 
		return 0 
	end	
	local base = self:THTD_GetBasePower()
	return base + math.floor(base * self:THTD_GetPowerPercentage()/100)
end

-- 更新UI显示，单位视野必须设置为800
function CDOTA_BaseNPC:THTD_RefreshPowerUI()		
	self:SetDayTimeVisionRange(self:THTD_GetBasePower() + 800)
	self:SetNightTimeVisionRange(self:THTD_GetPowerPercentage() + 800)	
end



--------------------------------------------------

-- 获取成长属性攻击力
function CDOTA_BaseNPC:THTD_GetGrowAttack()
	local unitName = self:GetUnitName()
	if self:THTD_IsTowerEx() == true then
		unitName = unitName.."_ex"
	end
	local power = self:THTD_GetGrowPower()
	if thtd_attack_factor[unitName] == nil then
		thtd_attack_factor[unitName] = 1
	end
	return math.floor(power * thtd_attack_factor[unitName])
end

-- 增加基础攻击力
function CDOTA_BaseNPC:THTD_AddBaseAttack(bonus, uniqueString)
	if self.thtd_attack == nil then 
		return 
	end

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_attack"
		if self[uniqueString] ~= nil then
			self.thtd_attack = self.thtd_attack - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_attack = self.thtd_attack + bonus	
		else		
			uniqueString = uniqueString.."_attack"
			self.thtd_attack = self.thtd_attack + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end

	self:THTD_RefreshAttack()
end

-- 获取基础攻击力
function CDOTA_BaseNPC:THTD_GetBaseAttack()
	return math.max(0, self.thtd_attack or 0)
end

-- 增加攻击力提升百分比，线性叠加
function CDOTA_BaseNPC:THTD_AddAttackPercentage(bonus, uniqueString)
	if self.thtd_attack_percentage == nil then 
		return 
	end	

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_attack_percent"
		if self[uniqueString] ~= nil then
			self.thtd_attack_percentage = self.thtd_attack_percentage - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_attack_percentage = self.thtd_attack_percentage + bonus	
		else		
			uniqueString = uniqueString.."_attack_percent"
			self.thtd_attack_percentage = self.thtd_attack_percentage + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end
	
	self:THTD_RefreshAttack()
end

-- 获取攻击力提升百分比
function CDOTA_BaseNPC:THTD_GetAttackPercentage()
	return math.max(-100, self.thtd_attack_percentage or 0)
end

-- 获取总攻击力
function CDOTA_BaseNPC:THTD_GetAttack()
	if self.thtd_attack == nil then 
		return 0 
	end		
	local base = self:THTD_GetBaseAttack()
	return base + math.floor(base * self:THTD_GetAttackPercentage()/100)
end

-- 更新攻击力
function CDOTA_BaseNPC:THTD_RefreshAttack()		
	self:SetBaseDamageMin(self:THTD_GetBaseAttack())
	self:SetBaseDamageMax(self:THTD_GetBaseAttack())

	local modifierName = "modifier_base_attack_bonus_percent"
	local count = self:THTD_GetAttackPercentage()
	if count == 0 then 
		self:RemoveModifierByName(modifierName)
		return
	end
	local modifier = self:FindModifierByName(modifierName) or self:AddNewModifier(self, nil, modifierName, {})		
	if count > 0 then 
		modifier:SetStackCount(count)
	else
		modifier:SetStackCount(5000-count)
	end	
end



--------------------------------------------------

-- 获取单位技能伤害：星级 * 能量
function CDOTA_BaseNPC:THTD_GetStarDamage()
	if self.thtd_power == nil then 
		return 0 
	end		
	return self:THTD_GetStar() * self:THTD_GetPower()
end

-- 获取技能伤害，能量点*星级*系数，系数在技能的 AbilitySpecial 中定义，固定名称 power_damage，如果有多个则为 power_damage1，power_damage2，...
function CDOTA_BaseNPC:THTD_GetAbilityPowerDamage(ability, index)
	if not self:THTD_IsTower() then
		print("---------- THTD_GetAbilityPowerDamage Error!")
		print(self:GetUnitName().." is not tower")			
		return 0
	end

	if ability == nil then 
		print("---------- THTD_GetAbilityPowerDamage Error!")
		print("ability is nil")			
		return 0
	end

	-- 如果没有定义则会返回0
	local itemName = "power_damage"
	if index ~= nil then
		itemName = itemName..tostring(index)
	end
	local v = ability:GetSpecialValueFor(itemName)	

	return self:THTD_GetStarDamage() * v	
end



--------------------------------------------------

local thtd_attack_speed_black_list = 
{
	"nazrin",
	"iku"
}

function CDOTA_BaseNPC:IsInAttackSpeedBlackList()
	if SpawnSystem.IsUnLimited then 
		return false
	end
	for k,v in pairs(thtd_attack_speed_black_list) do
		if self:GetUnitName() == v then
			return true
		end
	end
	return false
end

-- 增加攻速，可负值，并刷新
function CDOTA_BaseNPC:THTD_AddAttackSpeed(bonus, uniqueString, is_no_black)
	if self.thtd_attack_speed_bonus == nil then 
		return
	end
	if is_no_black ~= true and self:IsInAttackSpeedBlackList() then
		return
	end

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_attack_speed"
		if self[uniqueString] ~= nil then
			self.thtd_attack_speed_bonus = self.thtd_attack_speed_bonus - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_attack_speed_bonus = self.thtd_attack_speed_bonus + bonus	
		else		
			uniqueString = uniqueString.."_attack_speed"
			self.thtd_attack_speed_bonus = self.thtd_attack_speed_bonus + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end

	local modifierName = "modifier_attack_speed"
	local count = self.thtd_attack_speed_bonus
	if count == 0 then 
		self:RemoveModifierByName(modifierName)
		return
	end
	local modifier = self:FindModifierByName(modifierName) or self:AddNewModifier(self, nil, modifierName, {})		
	if count > 0 then 
		modifier:SetStackCount(count)
	else
		modifier:SetStackCount(800-count)
	end
end

-- 攻速及攻击力继承主人
local inherit_attack_modifiers = 
{
	"modifier_attack_speed", 
	"modifier_base_attack_bonus_percent",
	"modifier_touhoutd_crit_damage",
	"modifier_touhoutd_crit_chance",
}

function CDOTA_BaseNPC:InheritOwnerBuff(caster)
	for _,v in pairs(inherit_attack_modifiers) do 
		local modifier = caster:FindModifierByName(v)
		if modifier ~= nil then
			local modifier2 = self:FindModifierByName(v) or self:AddNewModifier(caster, nil, v, {})
			if modifier2 ~= nil then 
				modifier2:SetStackCount(modifier:GetStackCount())
			end
		elseif self:HasModifier(v) then 
			self:RemoveModifierByName(v)			
		end
	end
end



--------------------------------------------------

local thtd_cooldown_black_list = 
{
	"daiyousei",
	"toramaru",
}

function CDOTA_BaseNPC:IsInCooldownBlackList()
	for k,v in pairs(thtd_cooldown_black_list) do
		if self:GetUnitName() == v then
			return true
		end
	end
	return false
end

-- CD降低百分比，加法叠加，负值增加CD
function CDOTA_BaseNPC:THTD_AddCooldownPercentage(bonus, uniqueString)
	if self.thtd_cooldown_percentage == nil then 
		return
	end
	if self:IsInCooldownBlackList() then
		return
	end

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_cooldown"
		if self[uniqueString] ~= nil then
			self.thtd_cooldown_percentage = self.thtd_cooldown_percentage - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_cooldown_percentage = self.thtd_cooldown_percentage + bonus	
		else		
			uniqueString = uniqueString.."_cooldown"
			self.thtd_cooldown_percentage = self.thtd_cooldown_percentage + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end

	local modifierName = "modifier_cooldown_reduce"
	local count = self.thtd_cooldown_percentage
	if count == 0 then 
		self:RemoveModifierByName(modifierName)
		return
	end
	local modifier = self:FindModifierByName(modifierName) or self:AddNewModifier(self, nil, modifierName, {})		
	if count > 0 then 
		modifier:SetStackCount(count)
	else
		modifier:SetStackCount(800-count)
	end
end

-- ability:GetCooldownTime()获取技能各种加成后的实际总冷却时间，
-- ability:GetCooldown(ability:GetLevel()-1)或ability:GetCooldown(-1)获取当前技能等级原本总冷却时间

-- 技能重新进入冷却，todo删除
function CDOTA_BaseNPC:ReCooldown(ability, substractCd)	
	ability:EndCooldown()
	ability:StartCooldown(ability:GetCooldown(-1)-substractCd)
end



--------------------------------------------------

-- 增加爆击伤害
function CDOTA_BaseNPC:THTD_AddCritDamage(bonus, uniqueString)
	if self.thtd_crit_damage == nil then 
		return
	end	

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_crit"
		if self[uniqueString] ~= nil then
			self.thtd_crit_damage = self.thtd_crit_damage - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_crit_damage = self.thtd_crit_damage + bonus	
		else		
			uniqueString = uniqueString.."_crit"
			self.thtd_crit_damage = self.thtd_crit_damage + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end

	local modifierName = "modifier_touhoutd_crit_damage"
	local count = self:THTD_GetCritDamage()
	if count == 0 then
		self:RemoveModifierByName(modifierName)
		return
	end
	local modifier = self:FindModifierByName(modifierName) or self:AddNewModifier(self, nil, modifierName, {})	
	modifier:SetStackCount(count)	
end

-- 获取爆击伤害，最低值为0
function CDOTA_BaseNPC:THTD_GetCritDamage()
	return math.max(0, self.thtd_crit_damage or 0)
end

-- 增加爆击概率
function CDOTA_BaseNPC:THTD_AddCritChance(bonus, uniqueString)
	if self.thtd_crit_chance == nil then 
		return
	end	

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_chance"
		if self[uniqueString] ~= nil then
			self.thtd_crit_chance = self.thtd_crit_chance - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_crit_chance = self.thtd_crit_chance + bonus	
		else		
			uniqueString = uniqueString.."_chance"
			self.thtd_crit_chance = self.thtd_crit_chance + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end

	local modifierName = "modifier_touhoutd_crit_chance"
	local count = self:THTD_GetCritChance()
	if count == 0 then
		self:RemoveModifierByName(modifierName)
		return
	end
	local modifier = self:FindModifierByName(modifierName) or self:AddNewModifier(self, nil, modifierName, {})	
	modifier:SetStackCount(count)	
end

-- 获取爆击伤害，最低值为0
function CDOTA_BaseNPC:THTD_GetCritChance()
	return math.max(0, self.thtd_crit_chance or 0)
end



--------------------------------------------------

-- 卡牌附加星能伤害，百分比，正负值，如果值为7位数，则在指定条件时降低伤害，如4505000表示伤害超过4星能时则降低50%，后面的5000为固定部分
function CDOTA_BaseNPC:AddExtraStarDamagePercentage(bonus, uniqueString)
	if self.thtd_extra_star_damage == nil then 
		return
	end	

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_star_damage_percent"
		if self[uniqueString] ~= nil then
			self.thtd_extra_star_damage = self.thtd_extra_star_damage - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_extra_star_damage = self.thtd_extra_star_damage + bonus	
		else		
			uniqueString = uniqueString.."_star_damage_percent"
			self.thtd_extra_star_damage = self.thtd_extra_star_damage + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end
end

--获取卡牌附加星能伤害，百分比，正值为增加，负值为降低
function CDOTA_BaseNPC:GetExtraStarDamagePercentage()    
	return self.thtd_extra_star_damage or 0
end



--------------------------------------------------

-- 卡牌增加魔法输出提升百分比，0到999
function CDOTA_BaseNPC:AddDamageOutgoingMagical(bonus, uniqueString)
	if self.thtd_damage_magical_percentage == nil then 
		return
	end	

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_out_magical"
		if self[uniqueString] ~= nil then
			self.thtd_damage_magical_percentage = self.thtd_damage_magical_percentage - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_damage_magical_percentage = self.thtd_damage_magical_percentage + bonus	
		else		
			uniqueString = uniqueString.."_out_magical"
			self.thtd_damage_magical_percentage = self.thtd_damage_magical_percentage + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end

	self.thtd_damage_magical_percentage = math.min(999, math.max(0, self.thtd_damage_magical_percentage))

	local modifierName = "modifier_touhoutd_damage_outgoing_magical"
	local count = self.thtd_damage_magical_percentage

	if count == 0 then
		self:RemoveModifierByName(modifierName)
		return
	end
	local modifier = self:FindModifierByName(modifierName) or self:AddNewModifier(self, nil, modifierName, {})	
	modifier:SetStackCount(count)
end

--获取卡牌魔法输出提升，没有则返回0
function CDOTA_BaseNPC:GetDamageOutgoingMagical()    
    return self.thtd_damage_magical_percentage or 0
end

-- 卡牌增加物理输出提升百分比，0到999
function CDOTA_BaseNPC:AddDamageOutgoingPhysical(bonus, uniqueString)
	if self.thtd_damage_physical_percentage == nil then 
		return
	end	

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_out_physical"
		if self[uniqueString] ~= nil then
			self.thtd_damage_physical_percentage = self.thtd_damage_physical_percentage - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_damage_physical_percentage = self.thtd_damage_physical_percentage + bonus	
		else		
			uniqueString = uniqueString.."_out_physical"
			self.thtd_damage_physical_percentage = self.thtd_damage_physical_percentage + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end

	self.thtd_damage_physical_percentage = math.min(999, math.max(0, self.thtd_damage_physical_percentage))

	local modifierName = "modifier_touhoutd_damage_outgoing_physical"
	local count = self.thtd_damage_physical_percentage
	if count == 0 then
		self:RemoveModifierByName(modifierName)
		return
	end
	local modifier = self:FindModifierByName(modifierName) or self:AddNewModifier(self, nil, modifierName, {})	
	modifier:SetStackCount(count)
end

--获取卡牌物理输出提升，没有则返回0
function CDOTA_BaseNPC:GetDamageOutgoingPhysical()    
	return self.thtd_damage_physical_percentage or 0
end

-- 卡牌增加纯粹输出提升百分比，0到999
function CDOTA_BaseNPC:AddDamageOutgoingPure(bonus, uniqueString)
	if self.thtd_damage_pure_percentage == nil then 
		return
	end	

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_out_pure"
		if self[uniqueString] ~= nil then
			self.thtd_damage_pure_percentage = self.thtd_damage_pure_percentage - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_damage_pure_percentage = self.thtd_damage_pure_percentage + bonus	
		else		
			uniqueString = uniqueString.."_out_pure"
			self.thtd_damage_pure_percentage = self.thtd_damage_pure_percentage + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end

	self.thtd_damage_pure_percentage = math.min(999, math.max(0, self.thtd_damage_pure_percentage))

	local modifierName = "modifier_touhoutd_damage_outgoing_pure"
	local count = self.thtd_damage_pure_percentage
	if count == 0 then
		self:RemoveModifierByName(modifierName)
		return
	end
	local modifier = self:FindModifierByName(modifierName) or self:AddNewModifier(self, nil, modifierName, {})	
	modifier:SetStackCount(count)
end

--获取卡牌纯粹输出提升，没有则返回0，百分比已转换为小数
function CDOTA_BaseNPC:GetDamageOutgoingPure()    
    return self.thtd_damage_pure_percentage or 0
end

-- 卡牌增加所有类型输出提升百分比，0到999
function CDOTA_BaseNPC:AddDamageOutgoingAll(bonus, uniqueString)
	self:AddDamageOutgoingMagical(bonus, uniqueString)
	self:AddDamageOutgoingPhysical(bonus, uniqueString)
	self:AddDamageOutgoingPure(bonus, uniqueString)
end



--------------------------------------------------

-- 怪受到纯粹伤害加深百分比，0到999
function CDOTA_BaseNPC:AddDamageIncomingPure(bonus, uniqueString)
	if self.thtd_damage_incoming_pure_percentage == nil then 
		return
	end	

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_in_pure"
		if self[uniqueString] ~= nil then
			self.thtd_damage_incoming_pure_percentage = self.thtd_damage_incoming_pure_percentage - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_damage_incoming_pure_percentage = self.thtd_damage_incoming_pure_percentage + bonus	
		else		
			uniqueString = uniqueString.."_in_pure"
			self.thtd_damage_incoming_pure_percentage = self.thtd_damage_incoming_pure_percentage + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end

	self.thtd_damage_incoming_pure_percentage = math.min(999, math.max(0, self.thtd_damage_incoming_pure_percentage))

	local modifierName = "modifier_touhoutd_damage_incoming_pure"
	local count = self.thtd_damage_incoming_pure_percentage
	if count == 0 then
		self:RemoveModifierByName(modifierName)
		return
	end
	local modifier = self:FindModifierByName(modifierName) or self:AddNewModifier(self, nil, modifierName, {})	
	modifier:SetStackCount(count)
end

--获取怪受到纯粹伤害加深，没有则返回0
function CDOTA_BaseNPC:GetDamageIncomingPure()    
	return self.thtd_damage_incoming_pure_percentage or 0
end

-- 怪受到物理伤害加深百分比，0到999
function CDOTA_BaseNPC:AddDamageIncomingPhysical(bonus, uniqueString)
	if self.thtd_damage_incoming_physical_percentage == nil then 
		return
	end	

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_in_physical"
		if self[uniqueString] ~= nil then
			self.thtd_damage_incoming_physical_percentage = self.thtd_damage_incoming_physical_percentage - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_damage_incoming_physical_percentage = self.thtd_damage_incoming_physical_percentage + bonus	
		else		
			uniqueString = uniqueString.."_in_physical"
			self.thtd_damage_incoming_physical_percentage = self.thtd_damage_incoming_physical_percentage + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end

	self.thtd_damage_incoming_physical_percentage = math.min(999, math.max(0, self.thtd_damage_incoming_physical_percentage))

	local modifierName = "modifier_touhoutd_damage_incoming_physical"
	local count = self.thtd_damage_incoming_physical_percentage
	if count == 0 then
		self:RemoveModifierByName(modifierName)
		return
	end
	local modifier = self:FindModifierByName(modifierName) or self:AddNewModifier(self, nil, modifierName, {})	
	modifier:SetStackCount(count)
end

--获取怪受到物理伤害加深，没有则返回0
function CDOTA_BaseNPC:GetDamageIncomingPhysical()    
    return self.thtd_damage_incoming_physical_percentage or 0
end

-- 怪受到魔法伤害加深百分比，0到999
function CDOTA_BaseNPC:AddDamageIncomingMagical(bonus, uniqueString)
	if self.thtd_damage_incoming_magical_percentage == nil then 
		return
	end	

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_in_magical"
		if self[uniqueString] ~= nil then
			self.thtd_damage_incoming_magical_percentage = self.thtd_damage_incoming_magical_percentage - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_damage_incoming_magical_percentage = self.thtd_damage_incoming_magical_percentage + bonus	
		else		
			uniqueString = uniqueString.."_in_magical"
			self.thtd_damage_incoming_magical_percentage = self.thtd_damage_incoming_magical_percentage + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end

	self.thtd_damage_incoming_magical_percentage = math.min(999, math.max(0, self.thtd_damage_incoming_magical_percentage))

	local modifierName = "modifier_touhoutd_damage_incoming_magical"
	local count = self.thtd_damage_incoming_magical_percentage
	if count == 0 then
		self:RemoveModifierByName(modifierName)
		return
	end
	local modifier = self:FindModifierByName(modifierName) or self:AddNewModifier(self, nil, modifierName, {})	
	modifier:SetStackCount(count)
end

--获取怪受到魔法伤害加深，没有则返回0
function CDOTA_BaseNPC:GetDamageIncomingMagical()    
    return self.thtd_damage_incoming_magical_percentage or 0
end

-- 怪受到所有类型伤害加深百分比，0到999
function CDOTA_BaseNPC:AddDamageIncomingAll(bonus, uniqueString)
	self:AddDamageIncomingMagical(bonus, uniqueString)
	self:AddDamageIncomingPhysical(bonus, uniqueString)
	self:AddDamageIncomingPure(bonus, uniqueString)
end



--------------------------------------------------

-- 怪抵挡纯粹伤害数据，正值为抵挡，负值为附加
function CDOTA_BaseNPC:AddDamageBlockPure(bonus, uniqueString)
	if self.thtd_damage_block_pure == nil then 
		return
	end	

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_block_pure"
		if self[uniqueString] ~= nil then
			self.thtd_damage_block_pure = self.thtd_damage_block_pure - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_damage_block_pure = self.thtd_damage_block_pure + bonus	
		else		
			uniqueString = uniqueString.."_block_pure"
			self.thtd_damage_block_pure = self.thtd_damage_block_pure + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end
end

--获取怪抵挡纯粹伤害数据，正值为抵挡，负值为附加
function CDOTA_BaseNPC:GetDamageBlockPure()    
	return self.thtd_damage_block_pure or 0
end

-- 怪抵挡物理伤害数据，正值为抵挡，负值为附加
function CDOTA_BaseNPC:AddDamageBlockPhysical(bonus, uniqueString)
	if self.thtd_damage_block_physical == nil then 
		return
	end	

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_block_physical"
		if self[uniqueString] ~= nil then
			self.thtd_damage_block_physical = self.thtd_damage_block_physical - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_damage_block_physical = self.thtd_damage_block_physical + bonus	
		else		
			uniqueString = uniqueString.."_block_physical"
			self.thtd_damage_block_physical = self.thtd_damage_block_physical + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end
end

--获取怪抵挡物理伤害数据，正值为抵挡，负值为附加
function CDOTA_BaseNPC:GetDamageBlockPhysical()    
    return self.thtd_damage_block_physical or 0
end

-- 怪抵挡魔法伤害数据，正值为抵挡，负值为附加
function CDOTA_BaseNPC:AddDamageBlockMagical(bonus, uniqueString)
	if self.thtd_damage_block_magical == nil then 
		return
	end	

	if type(bonus) == "string" and uniqueString == nil then 
		uniqueString = bonus.."_block_magical"
		if self[uniqueString] ~= nil then
			self.thtd_damage_block_magical = self.thtd_damage_block_magical - self[uniqueString]
			self[uniqueString] = nil
		end
	else
		bonus = math.floor(bonus + 0.5)
		if uniqueString == nil then 
			self.thtd_damage_block_magical = self.thtd_damage_block_magical + bonus	
		else		
			uniqueString = uniqueString.."_block_magical"
			self.thtd_damage_block_magical = self.thtd_damage_block_magical + bonus - (self[uniqueString] or 0)
			self[uniqueString] = bonus
		end
	end
end

--获取怪抵挡魔法伤害数据，正值为抵挡，负值为附加
function CDOTA_BaseNPC:GetDamageBlockMagical()    
    return self.thtd_damage_block_magical or 0
end

-- 怪受到所有类型伤害加深百分比，0到999
function CDOTA_BaseNPC:AddDamageBlockAll(bonus, uniqueString)
	self:AddDamageBlockMagical(bonus, uniqueString)
	self:AddDamageBlockPhysical(bonus, uniqueString)
	self:AddDamageBlockPure(bonus, uniqueString)
end



--------------------------------------------------

function CDOTA_BaseNPC:THTD_GetFaith()
	if not self:HasModifier("modifier_sanae_04_combo_buff") then 
		return 0 
	end

	local hero = GameRules.HeroList[self:GetPlayerOwnerID()]
	if hero == nil then return 0 end
	return hero.thtd_ss_faith or 0
end

function CDOTA_BaseNPC:THTD_AddFaith()
	if not self:HasModifier("modifier_sanae_04_combo_buff") then 
		return 
	end

	local hero = GameRules.HeroList[self:GetPlayerOwnerID()]
	if hero == nil then return end

	if hero.thtd_ss_faith == nil then 
		hero.thtd_ss_faith = 0 
	end	

	if hero.thtd_ss_faith == 999 then 
		return
	end

	hero.thtd_ss_faith = math.min(999, hero.thtd_ss_faith + 1)
	for k,v in pairs(hero.thtd_hero_tower_list) do
		if v:HasModifier("modifier_sanae_04_combo_buff") then			
			v:FindModifierByName("modifier_sanae_04_combo_buff"):SetStackCount(hero.thtd_ss_faith)
			v:THTD_AddBasePower(math.floor(hero.thtd_ss_faith/3), "thtd_sanae_04_combo_buff")
		end
	end
end



local thtd_Unique_Slow_Buff = 
{
	"modifier_cirno_01_slow_buff",	
	"modifier_merlin_01_debuff",
	"modifier_satori_01_debuff",
	"modifier_thdots_ran02_debuff",
	"modifier_sanae_debuff",
	"modifier_minamitsu_01_slow_buff",	
	"modifier_yoshika_01_slow",
	"modifier_medicine_01_slow",
	"modifier_star_01_slow",
	"modifier_suika_01_slow_debuff",
	"modifier_hina_01_slow_debuff",
	"modifier_earthshock_debuff_datadriven",
}

function THTD_IsUniqueSlowBuff(modifierName)
	for index,name in pairs(thtd_Unique_Slow_Buff) do
		if name == modifierName then
			return true
		end
	end
	return false
end

function CDOTA_BaseNPC:THTD_HasUniqueSlowBuff()
	local modifiers = self:FindAllModifiers()
	local count = 0

	for k,v in pairs(modifiers) do
		for index,name in pairs(thtd_Unique_Slow_Buff) do
			if v:GetName() == name then
				count = count + 1
			end
		end
	end
	if count > 1 then
		return true
	end
	
	return false
end



--------------------------------------------------

local thtd_equip_table = 
{
	["item_2005"] = 
	{
		["single"] = 
		{
			["attack_percentage"] = 10,
		},
		["suit"] = 
		{
			[2] = {
				["attack_percentage"] = 30,
			},
			[4] = {
				["modifier"] = "modifier_item_2005_attack_aura",
			},
		},
	},
	["item_2006"] = 
	{
		["single"] = 
		{
			["mana_regen_percentage"] = 4,
		},
		["suit"] = 
		{
			[2] = {
				["mana_regen_percentage"] = 10,
			},
			[4] = {
				["modifier"] = "modifier_item_2006_mana_regen_aura",
			},
		},
	},
	["item_2007"] = 
	{
		["single"] = 
		{
			["mana_regen_percentage"] = 4,
		},
		["suit"] = 
		{
			[2] = {
				["mana_regen_percentage"] = 10,
			},
			[4] = {
				["modifier"] = "modifier_item_2008_slow_aura",
			},
		},
	},
	["item_2008"] = 
	{
		["single"] = 
		{
			["crit_chance"] = 4,
		},
		["suit"] = 
		{
			[2] = {
				["crit_chance"] = 10,
			},
			[4] = {
				["crit_damage"] = 100,
			},
		},
	},
	["item_2009"] = 
	{
		["single"] = 
		{
			["magical_damage_percentage"] = 5,
			["power"] = 10,			
		},
		["suit"] = 
		{
			[2] = {
				["magical_damage_percentage"] = 15,
				["power"] = 25,				
			},
			[4] = {
				["modifier"] = "modifier_item_2009_damage",
			},
		},
	},
	["item_2010"] = 
	{
		["single"] = 
		{
			["physical_damage_percentage"] = 5,
			["power"] = 10,			
		},
		["suit"] = 
		{
			[2] = {
				["physical_damage_percentage"] = 15,
				["power"] = 25,				
			},
			[4] = {
				["modifier"] = "modifier_item_2010_damage",
			},
		},
	},
	["item_2011"] = 
	{
		["single"] = 
		{
			["attack"] = 20,
			["power"] = 10,
		},
		["suit"] = 
		{
			[2] = {
				["attack"] = 50,
				["power"] = 25,
			},
			[4] = {				
				["crit_damage"] = 150,
				["modifier"] = "modifier_item_2011_attack_stun",
			},
		},
	},
	["item_2012"] = 
	{
		["single"] = 
		{
			["magical_damage_percentage"] = 10,
		},
		["suit"] = 
		{
			[2] = {
				["magical_damage_percentage"] = 25,
			},
			[4] = {
				["modifier"] = "modifier_item_2012_magical_damage_aura",
			},
		},
	},
	["item_2013"] = 
	{
		["single"] = 
		{
			["physical_damage_percentage"] = 10,
		},
		["suit"] = 
		{
			[2] = {
				["physical_damage_percentage"] = 25,
			},
			[4] = {
				["modifier"] = "modifier_item_2013_physical_damage_aura",
			},
		},
	},
	["item_2014"] = 
	{
		["single"] = 
		{
			["damage_percentage"] = 10,
		},
		["suit"] = 
		{
			[2] = {
				["damage_percentage"] = 20,
			},
			[4] = {
				["modifier"] = "modifier_item_2014_damage_aura",
			},
		},
	},
	["item_2015"] = 
	{
		["single"] = 
		{
			["crit_chance"] = 5,
		},
		["suit"] = 
		{
			[2] = {
				["crit_chance"] = 20,
			},
			[4] = {
				["crit_chance"] = 45,
			},
		},
	},
	["item_2016"] = 
	{
		["single"] = 
		{
			["damage_percentage"] = 5,
			["mana_regen_percentage"] = 5,
		},
		["suit"] = 
		{
			[2] = {
				["damage_percentage"] = 6,
				["mana_regen_percentage"] = 10,
			},
			[4] = {
				["cooldown"] = 25,
			},
		},
	},
	["item_2017"] = 
	{
		["single"] = 
		{
			["attack_speed"] = 10,
		},
		["suit"] = 
		{
			[2] = {
				["attack_speed"] = 25,
			},
			[4] = {
				["attack_speed"] = 45,
			},
		},
	},
	["item_2018"] = 
	{
		["single"] = 
		{
			["attack"] = 15,
			["power"] = 5,
		},
		["suit"] = 
		{
			[2] = {
				["attack"] = 45,
				["power"] = 15,
			},
			[4] = {			
				["attack"] = 70,	
				["crit_chance"] = 30,
				-- ["modifier"] = "modifier_item_2018_bonus_attack_range",
			},
		},
	},
	["item_2019"] = 
	{
		["single"] = 
		{
			["power_percentage"] = 4,			
		},
		["suit"] = 
		{
			[2] = {
				["power_percentage"] = 12,				
			},
			[4] = {
				["power"] = 40,				
			},
		},
	},
	["item_2020"] = 
	{
		["single"] = 
		{
			["power"] = 20,
		},
		["suit"] = 
		{
			[2] = {
				["power"] = 60,
			},
			[4] = {
				["extra_star_percentage"] = 200,
			},
		},
	},		
}

local equip_bonus_table = 
{
	["mana_regen_percentage"] = "THTD_AddManaRegenPercentage",
	["cooldown"] = "THTD_AddCooldownPercentage",
	["attack"] = "THTD_AddBaseAttack",	
	["attack_percentage"] = "THTD_AddAttackPercentage",
	["attack_speed"] = "THTD_AddAttackSpeed",	
	["crit_chance"] = "THTD_AddCritChance",
	["crit_damage"] = "THTD_AddCritDamage",	
	["power"] = "THTD_AddBasePower",
	["power_percentage"] = "THTD_AddPowerPercentage",
	["magical_damage_percentage"] = "AddDamageOutgoingMagical",
	["physical_damage_percentage"] = "AddDamageOutgoingPhysical",
	["damage_percentage"] = "AddDamageOutgoingAll",
	["extra_star_percentage"] = "AddExtraStarDamagePercentage",
}

function CDOTA_BaseNPC:GetItemEquipCount(itemName, exclude_item)
	-- OnEquip和OnUnequip有bug，需要一个延时
	local count = 0
 	for i=0,5 do
		local targetItem = self:GetItemInSlot(i)
		if targetItem ~= nil and targetItem:IsNull() == false then
			if targetItem:GetAbilityName() == itemName and targetItem ~= exclude_item then
				count = count + 1
			end
		end
	end
	return count
end

function CDOTA_BaseNPC:ItemEquipBonus(item)
	local itemName = item:GetAbilityName()
	local itemCount = self:GetItemEquipCount(itemName)
	print(itemName.." count : ", itemCount)

	local playerid = self:GetPlayerOwnerID()
	local countBonus = 0
	if GameRules.player_bb_buff[playerid]["item_3027"] > 0 and THTD_IsStarLotusTower(self) then
		countBonus = GameRules.player_bb_buff[playerid]["item_3027"]
	end

	if (itemCount + countBonus) >= 4 then 
		for bonusName,bonus in pairs(thtd_equip_table[itemName]["single"]) do
			self:ItemBonusAdd(itemName, bonusName, "single", bonus * itemCount)	
		end
		for bonusName,bonus in pairs(thtd_equip_table[itemName]["suit"][2]) do
			self:ItemBonusAdd(itemName, bonusName, "suit2", bonus)			
		end
		for bonusName,bonus in pairs(thtd_equip_table[itemName]["suit"][4]) do
			self:ItemBonusAdd(itemName, bonusName, "suit4", bonus)	
		end
	elseif itemCount >= 2 then 
		for bonusName,bonus in pairs(thtd_equip_table[itemName]["single"]) do
			self:ItemBonusAdd(itemName, bonusName, "single", bonus * itemCount)	
		end
		for bonusName,bonus in pairs(thtd_equip_table[itemName]["suit"][2]) do
			self:ItemBonusAdd(itemName, bonusName, "suit2", bonus)			
		end
		for bonusName,bonus in pairs(thtd_equip_table[itemName]["suit"][4]) do
			self:ItemBonusRemove(itemName, bonusName, "suit4", bonus)
		end
	elseif itemCount > 0 then 
		for bonusName,bonus in pairs(thtd_equip_table[itemName]["single"]) do
			self:ItemBonusAdd(itemName, bonusName, "single", bonus * itemCount)	
		end
		for bonusName,bonus in pairs(thtd_equip_table[itemName]["suit"][2]) do
			self:ItemBonusRemove(itemName, bonusName, "suit2", bonus)			
		end
		for bonusName,bonus in pairs(thtd_equip_table[itemName]["suit"][4]) do
			self:ItemBonusRemove(itemName, bonusName, "suit4", bonus)
		end	
	else
		for bonusName,bonus in pairs(thtd_equip_table[itemName]["single"]) do
			self:ItemBonusRemove(itemName, bonusName, "single", bonus)			
		end
		for bonusName,bonus in pairs(thtd_equip_table[itemName]["suit"][2]) do
			self:ItemBonusRemove(itemName, bonusName, "suit2", bonus)			
		end
		for bonusName,bonus in pairs(thtd_equip_table[itemName]["suit"][4]) do
			self:ItemBonusRemove(itemName, bonusName, "suit4", bonus)
		end	
	end
end

function CDOTA_BaseNPC:ItemBonusAdd(itemName, bonusName, type, bonus)
	local uniqueString = itemName.."_"..bonusName.."_"..type.."_bonus"
	if bonusName == "modifier" then
		if not self:HasModifier(bonus) then
			self:AddNewModifier(self, nil, bonus, {})								
		end	
	else
		local add = bonus - (self[uniqueString] or 0)	
		local func = self[equip_bonus_table[bonusName]]										
		if func then							
			func(self, add)
			self[uniqueString] = bonus
		end
	end
end

function CDOTA_BaseNPC:ItemBonusRemove(itemName, bonusName, type, bonus)
	local uniqueString = itemName.."_"..bonusName.."_"..type.."_bonus"	
	if bonusName == "modifier" then
		if self:HasModifier(bonus) then
			self:RemoveModifierByName(bonus)				
		end
	else
		if self[uniqueString] ~= nil then 
			local func = self[equip_bonus_table[bonusName]]
			if func then							
				func(self, -self[uniqueString])				
			end
			self[uniqueString] = nil
		end
	end
end



--------------------------------------------------

function CDOTA_BaseNPC:THTD_DropItemAll()
	local items = {}
	for i=0,THTD_MAX_ITEM_SLOT-1 do	
		local targetItem = self:GetItemInSlot(i)
		if targetItem~=nil and targetItem:IsNull()==false and targetItem:GetAbilityName() ~= "item_3121" and targetItem:GetAbilityName() ~= "item_3149" then	
			table.insert(items,targetItem)
		end
	end
	local targetItem = self:GetItemInSlot(THTD_ITEM_Neutral_SLOT)
	if targetItem~=nil and targetItem:IsNull()==false then	
		table.insert(items,targetItem)
	end

	for _,targetItem in pairs(items) do 
		if self:GetUnitName() == "chen" or self:GetUnitName() == "aya" then									
			self:DropItemAtPositionImmediate(targetItem, self:GetOwner():GetOrigin())				
		else
			self:DropItemAtPositionImmediate(targetItem, self:GetOrigin())
		end		
	end

	items = {}
end

function CDOTA_BaseNPC:THTD_AddCardPoolItem(itemName)
	if self:IsRealHero() == false or itemName==nil then return true end

	local item = CreateItem(itemName, nil, nil)
	if item == nil then return false end	
	item.card_poor_player_id = self.thtd_player_id
	item.owner_player_id = self.thtd_player_id
	self:AddItem(item)
	item:THTD_RemoveItemInList(self.thtd_player_id)				

	local cardName = item:THTD_GetCardName()
	if item:THTD_IsCardHasVoice() == true then
		EmitSoundOn(THTD_GetVoiceEvent(cardName,"spawn"), self)
		-- local player = self:GetPlayerOwner()
		-- if player then
		-- 	-- 这两个声音太小
		-- 	-- EmitSoundOnClient(THTD_GetVoiceEvent(cardName,"spawn"),player)
		-- 	-- EmitAnnouncerSoundForPlayer(THTD_GetVoiceEvent(cardName,"spawn"), self:GetPlayerOwnerID())
		-- end

		-- 不在视野也会听到这个音效
		-- EmitSoundOnLocationWithCaster(vLocation, soundName, hCaster)
	end

	if item:THTD_IsCardHasPortrait() == true then
		local portraits= item:THTD_GetPortraitPath(cardName)
		local quality = item:THTD_GetCardQuality()
		if quality == 1 then
			local effectIndex = ParticleManager:CreateParticleForPlayer(portraits, PATTACH_WORLDORIGIN, self, self:GetPlayerOwner())
			ParticleManager:SetParticleControl(effectIndex, 0, Vector(-58,-80,0))
			ParticleManager:SetParticleControl(effectIndex, 1, Vector(80,0,0))
			ParticleManager:DestroyParticleSystemTime(effectIndex,6.0)
			self:EmitSound("Sound_THTD.thtd_draw_n")
		elseif quality == 2 then
			local effectIndex = ParticleManager:CreateParticleForPlayer(portraits, PATTACH_WORLDORIGIN, self, self:GetPlayerOwner())
			ParticleManager:SetParticleControl(effectIndex, 0, Vector(-58,-80,0))
			ParticleManager:SetParticleControl(effectIndex, 1, Vector(80,0,0))
			ParticleManager:DestroyParticleSystemTime(effectIndex,6.0)
			self:EmitSound("Sound_THTD.thtd_draw_r")
		elseif quality == 3 then
			local effectIndex = ParticleManager:CreateParticleForPlayer(portraits, PATTACH_WORLDORIGIN, self, self:GetPlayerOwner())
			ParticleManager:SetParticleControl(effectIndex, 0, Vector(-58,-80,0))
			ParticleManager:SetParticleControl(effectIndex, 1, Vector(80,0,0))
			ParticleManager:DestroyParticleSystemTime(effectIndex,6.0)
			self:EmitSound("Sound_THTD.thtd_draw_sr")
		elseif quality == 4 then
			local effectIndex = ParticleManager:CreateParticle(portraits, PATTACH_WORLDORIGIN, nil)
			ParticleManager:SetParticleControl(effectIndex, 0, Vector(-58,-80,0))
			ParticleManager:SetParticleControl(effectIndex, 1, Vector(80,0,0))
			ParticleManager:DestroyParticleSystemTime(effectIndex,6.0)
			effectIndex = ParticleManager:CreateParticle("particles/portraits/portraits_ssr_get_screen_effect.vpcf", PATTACH_WORLDORIGIN, nil)
			ParticleManager:DestroyParticleSystemTime(effectIndex,4.0)
			self:EmitSound("Sound_THTD.thtd_draw_ssr")
		end		
	end

	return true
end

local thtd_remain_buff = 
{
	"modifier_miko_02_buff",	
	"modifier_miko_02_ready",
	"modifier_byakuren_03_buff",
	"modifier_sakuya_02_buff",
}

function THTD_IsRemainBuff(modifierName)
	for index,name in pairs(thtd_remain_buff) do
		if name == modifierName then
			return true
		end
	end
	return false
end


--------------------------------------------------

local thtd_spell_lock  = {
	[0] = {	},
	[1] = {	},
	[2] = {	},
	[3] = {	},
}

-- 控制链
local thtd_stun_group = {
	-- "thtd_patchouli_04_start_stun",  有延迟生效
	"thtd_patchouli_04_in_stun",
	"thtd_sakuya_03",
	"thtd_utsuho_03",	
	"thtd_medicine_02",
	"thtd_wriggle_02",	
	"thtd_hecatia_03",
	"thtd_komachi_02",
	"thtd_kokoro_02",
	"thtd_reimu_03",
	"thtd_kyouko_02",
	"thtd_shikieiki_04",	
}

function THTD_SetSpellLock(caster, abilityName, time)
	local id = caster:GetPlayerOwnerID()
	if thtd_spell_lock[id] == nil then thtd_spell_lock[id] = {} end
	thtd_spell_lock[id][abilityName] = GameRules:GetGameTime() + time  -- 有时实际时间要加一个AI运行间隔
	-- ability:GetCastPoint() --施法前摇
end

function THTD_IsSpellLock(caster, abilityName)	
	local id = caster:GetPlayerOwnerID()
	if thtd_spell_lock[id] == nil then 
		thtd_spell_lock[id] = {} 
	end

	local isInGroup = false
	local isGroupLock = false
	for k,v in pairs(thtd_stun_group) do
		if v == abilityName then 
			isInGroup = true
		end
		if thtd_spell_lock[id][v] ~= nil and thtd_spell_lock[id][v] > GameRules:GetGameTime() then 
			isGroupLock = true
		end
		if isInGroup and isGroupLock then 
			return true
		end
	end
	
	if thtd_spell_lock[id][abilityName] ~= nil and thtd_spell_lock[id][abilityName] > GameRules:GetGameTime() then			
		return true
	else		
		return false
	end	
end



--------------------------------------------------

-- 潜能设置
local thtd_potency_table =
{    
	["cirno"] = {		
		["thtd_cirno_02"] = {  
			[1] = {3, 4},
			[2] = {6, 8},
			[3] = {9, 16},
		},	
		["thtd_cirno_04"] = {  
			[1] = {3},
			[2] = {6},
			[3] = {9},
		},		  
	},

	["clownpiece"] = {		
		["thtd_clownpiece_01"] = {  
			[1] = {100},
			[2] = {200},
			[3] = {400},
		},	
		["thtd_clownpiece_02"] = {  
			[1] = {0, 0, 0},
			[2] = {200, 2, 1},
			[3] = {400, 4, 2},
		},	
		["thtd_clownpiece_03"] = {  
			[1] = {5, 0},
			[2] = {10, 0},
			[3] = {20, 5},
		},			  
	},

	["hanadayousei"] = {		
		["thtd_hanadayousei_01"] = {  
			[1] = {3, 100},
			[2] = {6, 200},
			[3] = {99, 400},
		},	
	},

	["kogasa"] = {		
		["thtd_kogasa_01"] = {  
			[1] = {100, 2, 2},
			[2] = {200, 4, 4},
			[3] = {400, 8, 8},
		},	
	},

	["letty"] = {		
		["thtd_letty_01"] = {  
			[1] = {1, 1},
			[2] = {2, 2},
			[3] = {4, 4},
		},	
	},

	["mugiyousei"] = {		
		["thtd_mugiyousei_01"] = {  
			[1] = {3, 3},
			[2] = {6, 6},
			[3] = {9, 9},
		},	
	},
	
	["aya"] = {		
		["thtd_aya_01"] = {  
			[1] = {1, 0},
			[2] = {2, 1},
			[3] = {4, 2},
		},	
		["thtd_aya_02"] = {  
			[1] = {2},
			[2] = {4},
			[3] = {8},
		},		
	},
	
	["kisume"] = {		
		["thtd_kisume_01"] = {  
			[1] = {2},
			[2] = {4},
			[3] = {8},
		},	
		["thtd_kisume_02"] = {  
			[1] = {2, 0},
			[2] = {4, 0},
			[3] = {8, 1},
		},		
	},

	["minamitsu"] = {		
		["thtd_minamitsu_02"] = {  
			[1] = {25, 2},
			[2] = {50, 4},
			[3] = {75, 7},
		},	
		["thtd_minamitsu_04"] = {  
			[1] = {5, 0},
			[2] = {10, 2},
			[3] = {20, 4},
		},		
	},

	["kagerou"] = {	
		["thtd_kagerou_02"] = {  
			[1] = {2},
			[2] = {5},
			[3] = {10},
		},	
		["thtd_kagerou_03"] = {  
			[1] = {100, 2, 10},
			[2] = {200, 4, 20},
			[3] = {300, 8, 30},
		},		
	},

	["marisa"] = {	
		["thtd_marisa_02"] = {  
			[1] = {100},
			[2] = {200},
			[3] = {400},
		},	
		["thtd_marisa_03"] = {  
			[1] = {8, 40},
			[2] = {18, 80},
			[3] = {28, 160},
		},
	},

	["alice"] = {	
		["thtd_alice_02"] = {  
			[1] = {1},
			[2] = {2},
			[3] = {3},
		},	
		["thtd_alice_03"] = {  
			[1] = {100},
			[2] = {200},
			[3] = {400},
		},
	},

	["patchouli"] = {	
		["thtd_patchouli_01"] = {  
			[1] = {50},
			[2] = {100},
			[3] = {200},
		},	
		["thtd_patchouli_04"] = {  
			[1] = {15},
			[2] = {30},
			[3] = {60},
		},
	},

	["sakuya"] = {	
		["thtd_sakuya_01"] = {  
			[1] = {5},
			[2] = {10},
			[3] = {15},
		},	
		["thtd_sakuya_03"] = {  
			[1] = {5},
			[2] = {10},
			[3] = {15},
		},
	},

	["tenshi"] = {	
		["thtd_tenshi_02"] = {  
			[1] = {10},
			[2] = {20},
			[3] = {40},
		},	
		["thtd_tenshi_03"] = {  
			[1] = {10},
			[2] = {20},
			[3] = {40},
		},
	},

	["youmu"] = {	
		["thtd_youmu_02"] = {  
			[1] = {10},
			[2] = {20},
			[3] = {30},
		},	
		["thtd_youmu_03"] = {  
			[1] = {10},
			[2] = {20},
			[3] = {40},
		},
	},

	["yuyuko"] = {	
		["thtd_yuyuko_02"] = {  
			[1] = {5},
			[2] = {10},
			[3] = {15},
		},	
		["thtd_yuyuko_03"] = {  
			[1] = {10},
			[2] = {20},
			[3] = {30},
		},
	},

	["rumia"] = {	
		["thtd_rumia_02"] = {  
			[1] = {2},
			[2] = {4},
			[3] = {6},
		},	
		["thtd_rumia_04"] = {  
			[1] = {3},
			[2] = {8},
			[3] = {13},
		},
	},

	["satori"] = {	
		["thtd_satori_02"] = {  
			[1] = {50},
			[2] = {100},
			[3] = {150},
		},			
	},

	["kyouko"] = {	
		["thtd_kyouko_01"] = {  
			[1] = {5},
			[2] = {25},
			[3] = {50},
		},	
		["thtd_kyouko_02"] = {  
			[1] = {10},
			[2] = {20},
			[3] = {40},
		},		
	},

	["kokoro"] = {	
		["thtd_kokoro_04"] = {  
			[1] = {1},
			[2] = {5},
			[3] = {10},
		}	
	},

	["hina"] = {	
		["thtd_hina_02"] = {  
			[1] = {7},
			[2] = {15},
			[3] = {30},
		}	
	},

	["inaba"] = {	
		["thtd_inaba_02"] = {  
			[1] = {5},
			[2] = {10},
			[3] = {20},
		}	
	},
	
}

-- 获取觉醒后对应技能的潜能数值表，无则返回 nil
function CDOTA_BaseNPC:GetAbilityPowerValue(abilityName)	
	local powerLevel = self:GetTowerPowerLevel()
	if powerLevel < 1 then 
		return nil 
	end
	local level = math.min(3, powerLevel)	
	local unitName = self:GetUnitName()
	if thtd_potency_table[unitName] == nil then return nil end
	if thtd_potency_table[unitName][abilityName] == nil then return nil end
	return thtd_potency_table[unitName][abilityName][level]
end

-- 获取觉醒后的潜能等级，-1未开启，0小于10级，1为10级效果，2为50级效果，3为100级效果，4为666级，5为999级
function CDOTA_BaseNPC:GetTowerPowerLevel()
	if self.thtd_power_level == nil then 
		return -1
	elseif self.thtd_power_level >= 999 then 
		return 5
	elseif self.thtd_power_level >= 666 then 
		return 4
	elseif self.thtd_power_level >= 100 then 
		return 3
	elseif self.thtd_power_level >= 50 then 
		return 2
	elseif self.thtd_power_level >= 10 then 
		return 1
	else
		return 0
	end
end

-- 是否达到觉醒后潜能666等级
function CDOTA_BaseNPC:IsPower666()
	return self.thtd_power_level ~= nil and self.thtd_power_level >= 666
end

-- 是否达到觉醒后潜能999等级
function CDOTA_BaseNPC:IsPower999()
	return self.thtd_power_level ~= nil and self.thtd_power_level >= 999
end

-- 设置觉醒后潜能奖励
function CDOTA_BaseNPC:AddPowerBonus()
	local level = self:GetTowerPowerLevel()
	if level >= 0 then 
		self:THTD_AddBaseAttack(self.thtd_power_level * 3, "thtd_tower_power_bonus")
		self:THTD_AddBasePower(self.thtd_power_level * 3, "thtd_tower_power_bonus")		
	end

	local modifierName = "modifier_ability_power_"..self:GetUnitName()
	if level >= 1 then 		
		local modifier = self:FindModifierByName(modifierName) or self:AddNewModifier(self, nil, modifierName, nil)
		if modifier ~= nil then 
			modifier:SetStackCount(level)			
		end
	else
		self:RemoveModifierByName(modifierName)
	end
end

-- 移除觉醒后潜能奖励
function CDOTA_BaseNPC:RemovePowerBonus()
	self:THTD_AddBaseAttack("thtd_tower_power_bonus")
	self:THTD_AddBasePower("thtd_tower_power_bonus")
	self:RemoveModifierByName("modifier_ability_power_"..self:GetUnitName())
end

-- 获取最大潜能等级，秋姐妹、大妖精和N卡为100，其它999
function CDOTA_BaseNPC:GetMaxPowerLevel()
	local unitName = self:GetUnitName()
	if unitName == "minoriko" or unitName == "sizuha" or unitName == "nazrin" or unitName == "lily" or unitName == "daiyousei" or unitName == "mugiyousei" or unitName == "shanghainingyou" or unitName == "hourainingyou" or unitName == "hanadayousei" or unitName == "maidyousei"  then 
		return 100
	else 
		return 999
	end
end

function THTD_GetMaxPowerLevel(unitName)
	if unitName == "minoriko" or unitName == "sizuha" or unitName == "nazrin" or unitName == "lily" or unitName == "daiyousei" or unitName == "mugiyousei" or unitName == "shanghainingyou" or unitName == "hourainingyou" or unitName == "hanadayousei" or unitName == "maidyousei"  then 
		return 100
	else 
		return 999
	end
end



--------------------------------------------------

-- 设置幸运日
function CDOTA_BaseNPC:SetLuckDay()
	if self:THTD_IsTower() then	
		local crit = 0
		if self:GetUnitName() == GameRules.GameData.luck_card or GameRules.GameData.luck_card == "all" then
			crit = GameRules.GameData.luck_crit
		end		
		if crit > 0 then 
			if self:HasModifier("modifier_touhoutd_luck") == false then								
				self:AddNewModifier(self, nil, "modifier_touhoutd_luck", {})							
			end
		elseif self:HasModifier("modifier_touhoutd_luck") then 
			self:RemoveModifierByName("modifier_touhoutd_luck")			
		end	
	end
end
