function OnByakuren01SpellStartUp(keys)
	local caster = EntIndexToHScript(keys.caster_entindex)

	--解决浮点数精度问题
	local tick_step = math.floor(keys.tick_step * 100 + 0.5) / 100	
	local min_tick = math.floor(keys.min_tick * 100 + 0.5) / 100
	local max_tick = math.floor(keys.max_tick * 100 + 0.5) / 100
	local base_tick = math.floor(keys.base_tick * 100 + 0.5) / 100

	if caster.thtd_byakuren_01_attack_time == nil then
		caster.thtd_byakuren_01_attack_time = base_tick
	end

	if caster.thtd_byakuren_01_extra_damage == nil then
		caster.thtd_byakuren_01_extra_damage = 100
	end	

	if caster.thtd_byakuren_01_attack_time > min_tick then
		caster.thtd_byakuren_01_attack_time = caster.thtd_byakuren_01_attack_time - tick_step		
		caster.thtd_byakuren_01_extra_damage = caster.thtd_byakuren_01_extra_damage - keys.extra_damage		
		local modifier = caster:FindModifierByName("modifier_attack_time") or caster:AddNewModifier(caster, nil, "modifier_attack_time", {})
		if modifier ~= nil then
			if caster.thtd_byakuren_01_attack_time <= min_tick then 
				modifier:SetStackCount((caster.thtd_byakuren_01_attack_time+tick_step)*10)
			else
				modifier:SetStackCount(caster.thtd_byakuren_01_attack_time*10)
			end
		end
	end

	ByakurenUpdateBuff(caster)
end

function OnByakuren01SpellStartDown(keys)
	local caster = EntIndexToHScript(keys.caster_entindex)

	--解决浮点数精度问题
	local tick_step = math.floor(keys.tick_step * 100 + 0.5) / 100	
	local min_tick = math.floor(keys.min_tick * 100 + 0.5) / 100
	local max_tick = math.floor(keys.max_tick * 100 + 0.5) / 100	

	if caster.thtd_byakuren_01_attack_time == nil then
		caster.thtd_byakuren_01_attack_time = base_tick
	end

	if caster.thtd_byakuren_01_extra_damage == nil then
		caster.thtd_byakuren_01_extra_damage = 100
	end

	if caster.thtd_byakuren_01_attack_time < max_tick then
		caster.thtd_byakuren_01_attack_time = caster.thtd_byakuren_01_attack_time + tick_step
		caster.thtd_byakuren_01_extra_damage = caster.thtd_byakuren_01_extra_damage + keys.extra_damage
		local modifier = caster:FindModifierByName("modifier_attack_time") or caster:AddNewModifier(caster, nil, "modifier_attack_time", {})
		if modifier ~= nil then
			modifier:SetStackCount(caster.thtd_byakuren_01_attack_time*10)		
		end
	end

	ByakurenUpdateBuff(caster)
end

function ByakurenUpdateBuff(caster)
	local ability = caster:FindAbilityByName("thtd_byakuren_01")
	local base_tick = math.floor(ability:GetSpecialValueFor("base_tick") * 100 + 0.5) / 100

	if caster.thtd_byakuren_01_attack_time == nil then
		caster.thtd_byakuren_01_attack_time = base_tick
	end

	if caster.thtd_byakuren_01_extra_damage == nil then
		caster.thtd_byakuren_01_extra_damage = 100
	end

	if caster.thtd_byakuren_01_attack_time > base_tick then
		caster:RemoveModifierByName("modifier_byakuren_attack_down")
		caster:RemoveModifierByName("modifier_byakuren_attack_equal")
		ability:ApplyDataDrivenModifier(caster, caster, "modifier_byakuren_attack_up", {})			
	elseif caster.thtd_byakuren_01_attack_time == base_tick then
		caster:RemoveModifierByName("modifier_byakuren_attack_down")
		caster:RemoveModifierByName("modifier_byakuren_attack_up")
		ability:ApplyDataDrivenModifier(caster, caster, "modifier_byakuren_attack_equal", {})			
	elseif caster.thtd_byakuren_01_attack_time < base_tick then
		caster:RemoveModifierByName("modifier_byakuren_attack_up")
		caster:RemoveModifierByName("modifier_byakuren_attack_equal")
		ability:ApplyDataDrivenModifier(caster, caster, "modifier_byakuren_attack_down", {})			
	end
	local modifier = caster:FindModifierByName("modifier_byakuren_damage_percent") or ability:ApplyDataDrivenModifier(caster, caster, "modifier_byakuren_damage_percent", {})
	if modifier ~= nil then
		modifier:SetStackCount(caster.thtd_byakuren_01_extra_damage)
	end	

	local ability = caster:FindAbilityByName("thtd_byakuren_04")
	if ability:GetLevel() > 0 then
		if caster.thtd_byakuren_01_attack_time > base_tick then
			if caster:HasModifier("modifier_byakuren_04_magic_buff") == false then
				ability:ApplyDataDrivenModifier(caster,caster,"modifier_byakuren_04_magic_buff", nil)
			end
			if caster:HasModifier("modifier_byakuren_04_physical_buff") then
				caster:RemoveModifierByName("modifier_byakuren_04_physical_buff")
			end
			if caster:HasModifier("modifier_byakuren_04_pure_buff") then
				caster:RemoveModifierByName("modifier_byakuren_04_pure_buff")
			end
		elseif caster.thtd_byakuren_01_attack_time == base_tick then
			if caster:HasModifier("modifier_byakuren_04_pure_buff") == false then
				ability:ApplyDataDrivenModifier(caster,caster,"modifier_byakuren_04_pure_buff", nil)
			end
			if caster:HasModifier("modifier_byakuren_04_magic_buff") then
				caster:RemoveModifierByName("modifier_byakuren_04_magic_buff")
			end
			if caster:HasModifier("modifier_byakuren_04_physical_buff") then
				caster:RemoveModifierByName("modifier_byakuren_04_physical_buff")
			end
		elseif caster.thtd_byakuren_01_attack_time < base_tick then
			if caster:HasModifier("modifier_byakuren_04_magic_buff") then
				caster:RemoveModifierByName("modifier_byakuren_04_magic_buff")
			end
			if caster:HasModifier("modifier_byakuren_04_pure_buff") then
				caster:RemoveModifierByName("modifier_byakuren_04_pure_buff")
			end
		end
	else
		if caster:HasModifier("modifier_byakuren_04_physical_buff") then
			caster:RemoveModifierByName("modifier_byakuren_04_physical_buff")
		end
		if caster:HasModifier("modifier_byakuren_04_pure_buff") then
			caster:RemoveModifierByName("modifier_byakuren_04_pure_buff")
		end
		if caster:HasModifier("modifier_byakuren_04_magic_buff") then
			caster:RemoveModifierByName("modifier_byakuren_04_magic_buff")
		end
	end
end

function OnByakuren01AttackLanded(keys)
	local caster = EntIndexToHScript(keys.caster_entindex)
	local target = keys.target

	if caster.thtd_byakuren_01_extra_damage == nil then
		caster.thtd_byakuren_01_extra_damage = 100
	end

	local factor = 1 + THTD_GetStarLotusBuffedTowerCount(caster) * keys.damage_up / 100
	local targets = THTD_FindUnitsInRadius(caster,target:GetOrigin(),keys.range)
	local damage = caster:THTD_GetAbilityPowerDamage(keys.ability) * factor * caster.thtd_byakuren_01_extra_damage / 100

	for k,v in pairs(targets) do
		local damage_table = {
			victim = v,
			attacker = caster,
			damage = damage,
			ability = keys.ability,
			damage_type = keys.ability:GetAbilityDamageType(), 
			damage_flags = DOTA_DAMAGE_FLAG_NONE,
		}
		local base_tick = math.floor(keys.base_tick * 100 + 0.5) / 100
		if caster.thtd_byakuren_01_attack_time == base_tick then
			damage_table.damage_type = DAMAGE_TYPE_PURE
		elseif caster.thtd_byakuren_01_attack_time > base_tick then
			damage_table.damage_type = DAMAGE_TYPE_MAGICAL
		elseif caster.thtd_byakuren_01_attack_time < base_tick then
			damage_table.damage_type = DAMAGE_TYPE_PHYSICAL
		end
		UnitDamageTarget(damage_table)
	end

	local particle = ParticleManager:CreateParticle("particles/units/heroes/hero_abaddon/abaddon_aphotic_shield_explosion.vpcf",PATTACH_CUSTOMORIGIN,caster)
	ParticleManager:SetParticleControl(particle,0,target:GetOrigin()+Vector(0,0,64))
	ParticleManager:DestroyParticleSystem(particle,false)
end

function OnByakuren03SpellThink(keys)
	if GameRules:IsGamePaused() then return end
	if keys.ability == nil or keys.ability:GetLevel() < 1 then return end
	local caster = EntIndexToHScript(keys.caster_entindex)
	local targets = THTD_FindFriendlyUnitsInRadius(caster,caster:GetOrigin(),2500)

	for k,v in pairs(targets) do
		if v:HasModifier("modifier_byakuren_03_buff") == false then
			if THTD_IsStarLotusTower(v) then
				if v.thtd_byakuren_03_religious_count == nil then
					v.thtd_byakuren_03_religious_count = 0
				end
				v.thtd_byakuren_03_religious_count = v.thtd_byakuren_03_religious_count + 1
				SendOverheadEventMessage(v:GetPlayerOwner(), OVERHEAD_ALERT_BONUS_POISON_DAMAGE, v, v.thtd_byakuren_03_religious_count, v:GetPlayerOwner() )
				if v.thtd_byakuren_03_religious_count > 6000 then
					local unitName = v:GetUnitName()
					if unitName == "nazrin" then
						v.thtd_byakuren_buff_nazrin = keys.ability:GetSpecialValueFor("nazrin")	
					elseif unitName == "toramaru" then
						v.thtd_byakuren_buff_toramaru = keys.ability:GetSpecialValueFor("toramaru")	
					elseif unitName == "kogasa" then
						v.thtd_byakuren_buff_kogasa = keys.ability:GetSpecialValueFor("kogasa")	
					elseif unitName == "nue" then
						v.thtd_byakuren_buff_nue = keys.ability:GetSpecialValueFor("nue")	
					elseif unitName == "minamitsu" then
						v.thtd_byakuren_buff_minamitsu = keys.ability:GetSpecialValueFor("minamitsu")
					elseif unitName == "kyouko" then
						v.thtd_byakuren_buff_kyouko = keys.ability:GetSpecialValueFor("kyouko")
					end
					keys.ability:ApplyDataDrivenModifier(caster,v,"modifier_byakuren_03_buff", nil)					
				end
			end
		end 
	end
end

local thtd_byakuren_04_point = 
{
	[1] = Vector(-340,-145,32),
	[2] = Vector(340,-145,32),
	[3] = Vector(-185,220,32),
	[0] = Vector(185,220,32),	
}

function OnByakuren04AttackLanded(keys)
	if keys.ability:GetLevel() < 1 then return end
	local caster = EntIndexToHScript(keys.caster_entindex)
	local target = keys.target

	if caster.thtd_byakuren_04_init ~= true then
		caster.thtd_byakuren_04_init = true
		ByakurenUpdateBuff(caster)
	end

	local base_tick = math.floor(caster:GetAbilityValue("thtd_byakuren_01", "base_tick") * 100 + 0.5) / 100

	if caster.thtd_byakuren_01_attack_time == nil then
		caster.thtd_byakuren_01_attack_time = base_tick
	end

	if caster.thtd_byakuren_01_extra_damage == nil then
		caster.thtd_byakuren_01_extra_damage = 100
	end

		
	local buffedCount = THTD_GetStarLotusBuffedTowerCount(caster)
	local buffedBonus = keys.power_bonus

	if caster.thtd_byakuren_01_attack_time > base_tick then
		local targets = THTD_FindUnitsInRadius(caster,caster:GetOrigin(),keys.range)
		if #targets > 0 then
			local count = 1
			local outCount = math.floor((keys.damage_count + buffedCount - 1)/#targets) + 1		
			local damageCount = {}
			for iOut=1,outCount do
				for i=1,#targets do
					local effectIndex = ParticleManager:CreateParticle("particles/heroes/thtd_byakuren/ability_byakuren_04_laser.vpcf", PATTACH_CUSTOMORIGIN, caster)
					ParticleManager:SetParticleControl(effectIndex, 0, caster:GetOrigin()+thtd_byakuren_04_point[count%4])
					ParticleManager:SetParticleControl(effectIndex, 1, targets[i]:GetOrigin())
					ParticleManager:SetParticleControl(effectIndex, 3, targets[i]:GetOrigin())
					ParticleManager:SetParticleControl(effectIndex, 9, caster:GetOrigin()+thtd_byakuren_04_point[count%4])
					ParticleManager:DestroyParticleSystemTime(effectIndex,2.0)

					local effectIndex = ParticleManager:CreateParticle("particles/heroes/thtd_byakuren/ability_byakuren_04_item.vpcf", PATTACH_CUSTOMORIGIN, caster)
					ParticleManager:SetParticleControl(effectIndex, 0, caster:GetOrigin()+thtd_byakuren_04_point[count%4])
					ParticleManager:DestroyParticleSystemTime(effectIndex,1.0)

					damageCount[i] = (damageCount[i] or 0) + 1
					count = count + 1
					if count > (keys.damage_count + buffedCount) then
						break
					end
				end
				if count > (keys.damage_count + buffedCount) then
					break
				end
			end
			-- PrintTable(damageCount)
			
			local damage = caster:THTD_GetAbilityPowerDamage(keys.ability) * (caster.thtd_byakuren_01_extra_damage/100) * (1 + buffedCount * buffedBonus/100)			
			for i=1,#targets do
				if damageCount[i] ~= nil then 
					local damage_table = {
						victim = targets[i],
						attacker = caster,
						damage = damage * damageCount[i],
						ability = keys.ability,
						damage_type = DAMAGE_TYPE_MAGICAL, 
						damage_flags = DOTA_DAMAGE_FLAG_NONE,
					}
					UnitDamageTarget(damage_table)
				end
			end
		end
		return
	end

	if caster.thtd_byakuren_01_attack_time == base_tick then
		if caster.thtd_byakuren_04_attack_count == nil then
			caster.thtd_byakuren_04_attack_count = 0
		end		
		caster.thtd_byakuren_04_attack_count = caster.thtd_byakuren_04_attack_count + 1
		if caster.thtd_byakuren_04_attack_count >= keys.max_count / (1 + buffedCount * buffedBonus/100) then
			caster.thtd_byakuren_04_attack_count = 0

			local targets = THTD_FindUnitsInRadius(caster,caster:GetOrigin(),keys.range)
			local damage = caster:THTD_GetAbilityPowerDamage(keys.ability) * (1 + buffedCount * buffedBonus/100)			
			for k,v in pairs(targets) do
				local damage_table = {
					victim = v,
					attacker = caster,
					damage = damage,
					ability = keys.ability,
					damage_type = DAMAGE_TYPE_PURE, 
					damage_flags = DOTA_DAMAGE_FLAG_NONE,
				}
				UnitDamageTarget(damage_table)
				local particle = ParticleManager:CreateParticle("particles/heroes/byakuren/ability_byakuren_02.vpcf",PATTACH_CUSTOMORIGIN,caster)
				ParticleManager:SetParticleControl(particle,0,v:GetOrigin())
				ParticleManager:SetParticleControl(particle,1,v:GetOrigin())
				ParticleManager:DestroyParticleSystem(particle,false)
			end
		end
		return
	end

	if caster.thtd_byakuren_01_attack_time < base_tick then
		if RollPercentage(keys.chance) and caster:HasModifier("modifier_byakuren_04_physical_buff") == false then	
			caster.byakuren_04_power_bonus = buffedCount * buffedBonus
			keys.ability:ApplyDataDrivenModifier(caster,caster,"modifier_byakuren_04_physical_buff", {Duration = keys.duration_time})
		end
	end
end

function OnCreatedByakuren04PhysicalBuff(keys)
	local target = keys.target	

	local effectIndex = ParticleManager:CreateParticle("particles/heroes/thtd_byakuren/ability_byakuren_04_phy.vpcf",PATTACH_CUSTOMORIGIN,target)
	ParticleManager:SetParticleControl(effectIndex,0,target:GetOrigin()+Vector(0,0,32))
	ParticleManager:DestroyParticleSystemTime(effectIndex, keys.duration_time)	
	target.thtd_byakuren_04_physical_buff_effect = effectIndex

	local bonus = target.byakuren_04_power_bonus		
	target:THTD_AddPowerPercentage(bonus, "thtd_byakuren_04_physical_buff")
	target:THTD_AddAttackPercentage(bonus, "thtd_byakuren_04_physical_buff")	
	target:THTD_AddAttackSpeed(keys.attack_speed, "thtd_byakuren_04_physical_buff")
	target:THTD_AddBaseAttack(keys.attack_bonus, "thtd_byakuren_04_physical_buff")
	target:THTD_AddBasePower(keys.attack_bonus, "thtd_byakuren_04_physical_buff")
end

function OnDestroyByakuren04PhysicalBuff(keys)
	local target = keys.target
	ParticleManager:DestroyParticleSystem(target.thtd_byakuren_04_physical_buff_effect, true)	
	target:THTD_AddPowerPercentage("thtd_byakuren_04_physical_buff")
	target:THTD_AddAttackPercentage("thtd_byakuren_04_physical_buff")	
	target:THTD_AddAttackSpeed("thtd_byakuren_04_physical_buff")	
	target:THTD_AddBaseAttack("thtd_byakuren_04_physical_buff")
	target:THTD_AddBasePower("thtd_byakuren_04_physical_buff")
end

function OnCreatedByakuren04PureBuff(keys)
	local target = keys.target
	target:THTD_AddCritDamage(keys.crit_damage, "thtd_byakuren_04_pure_buff")
	target:THTD_AddCritChance(keys.crit_change, "thtd_byakuren_04_pure_buff")	
end

function OnDestroyByakuren04PureBuff(keys)
	local target = keys.target
	target:THTD_AddCritDamage("thtd_byakuren_04_pure_buff")
	target:THTD_AddCritChance("thtd_byakuren_04_pure_buff")	
end


function OnCreatedByakuren04Buff(keys)	
	keys.target:AddDamageOutgoingMagical(keys.penetration, "thtd_byakuren_04_damage_up")
end

function OnDestroyByakuren04Buff(keys)		
	keys.target:AddDamageOutgoingMagical("thtd_byakuren_04_damage_up")
end