function OnKokoro01SpellStart(keys)
	local caster = keys.caster
	local targets = THTD_FindUnitsInRadius(caster, caster:GetAbsOrigin(), keys.ability:GetCastRange())	
	if #targets == 0 then return end	
	for k,v in pairs(targets) do 
		local info = 
		{
			Target = v,
			Source = caster,
			Ability = keys.ability,	
			EffectName = "particles/units/heroes/hero_arc_warden/arc_warden_wraith_prj.vpcf",
	        iMoveSpeed = 660,
			vSourceLoc= caster:GetAbsOrigin(),                -- Optional (HOW)
			bDrawsOnMinimap = false,                          -- Optional
		    bDodgeable = true,                                -- Optional
		  	bIsAttack = false,                                -- Optional
		    bVisibleToEnemies = true,                         -- Optional
		    bReplaceExisting = false,                         -- Optional
		    flExpireTime = GameRules:GetGameTime() + 10,      -- Optional but recommended
			bProvidesVision = true,                           -- Optional
			iVisionRadius = 400,                              -- Optional
			iVisionTeamNumber = caster:GetTeamNumber(),       -- Optional
			ExtraData = { }
		}
		local projectile = ProjectileManager:CreateTrackingProjectile(info)
		ParticleManager:DestroyLinearProjectileSystem(projectile,false)
	end
	
	KokoroSetPvCrit(caster)
	KokoroSetMust(caster, 1)
end

function OnProjectileHitUnitKokoro01(keys)
	local caster = keys.caster
	local target = keys.target
	local damage = caster:THTD_GetAbilityPowerDamage(keys.ability)

	local crit1 = 1
	local hasBuff1 = false
	if caster:HasModifier("modifier_kokoro_04_buff_1") then 
		hasBuff1 = true
	end
	local damage_up_base = caster:GetAbilityValue("thtd_kokoro_04", "damage_up_base", true)
	local damage_up_per = caster:GetAbilityValue("thtd_kokoro_04", "damage_up_per", true)
	local damage_up_factor = 1	
	if caster:IsPower666() then 
		damage_up_factor = 4
	end
	local crit2 = KokoroGetPvCrit(caster)
	if hasBuff1 then 
		crit1 = 1 + (damage_up_base + damage_up_per * (100 - target:GetHealthPercent())) * damage_up_factor
	end	

	local DamageTable = {
			ability = keys.ability,
	        victim = target, 
	        attacker = caster, 
	        damage = damage * crit1 * crit2, 
	        damage_type = keys.ability:GetAbilityDamageType(), 
	        damage_flags = DOTA_DAMAGE_FLAG_NONE
   	}
	UnitDamageTarget(DamageTable)
end

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

	KokoroSetPvCrit(caster)

	local stun_time = keys.stun_time

	local crit1 = 1
	local hasBuff1 = false
	if caster:HasModifier("modifier_kokoro_04_buff_1") then 
		hasBuff1 = true
	end
	local damage_up_base = caster:GetAbilityValue("thtd_kokoro_04", "damage_up_base", true)
	local damage_up_per = caster:GetAbilityValue("thtd_kokoro_04", "damage_up_per", true)
	local damage_up_factor = 1	
	if caster:IsPower666() then 
		damage_up_factor = 4
	end
	local crit2 = KokoroGetPvCrit(caster)

	local enemies = THTD_FindUnitsInRadius(caster, caster:GetAbsOrigin(), keys.ability:GetCastRange())
	local damage = caster:THTD_GetAbilityPowerDamage(keys.ability)
	for k,v in pairs(enemies) do
		local unit = CreateUnitByName(
			"kokoro_jin_yin", 
			caster:GetAbsOrigin(), 
			false, 
			caster:GetOwner(), 
			caster:GetOwner(), 
			caster:GetTeam() 
		)
		if unit ~= nil then 			
			keys.ability:ApplyDataDrivenModifier(caster, unit, "modifier_kokoro_02_rooted", {})	
			-- unit:MoveToTargetToAttack(v)
			-- 设置朝向
			local vecForward = (v:GetOrigin() - caster:GetOrigin()):Normalized()
			unit:SetForwardVector(vecForward)
			-- local angles = VectorToAngles(vecForward)
			-- unit:SetAngles(angles.x,angles.y,angles.z)
			local scale = unit:GetModelScale()
			local count = 0
			unit:SetContextThink(
				DoUniqueString("kokoro02_move"),
				function ()
					if GameRules:IsGamePaused() then return 0.03 end						
					if v==nil or v:IsNull() or v:IsAlive()==false then	
						unit:AddNoDraw()
						unit:ForceKill(false)	
						return nil
					end
					if caster==nil or caster:IsNull() or caster:IsAlive()==false or caster:THTD_IsHidden() then							
						unit:AddNoDraw()
						unit:ForceKill(false)	
						return nil
					end					
					
					unit:SetModelScale(scale * (1 + 0.1 * count))
					unit:MoveToTargetToAttack(v)
					local vecMove=(unit:GetOrigin()-v:GetOrigin()):Normalized() * 100
					unit:SetAbsOrigin(GetGroundPosition(unit:GetOrigin()-vecMove, unit))
					if (unit:GetOrigin()-v:GetOrigin()):Length() < 50 then 
						if hasBuff1 then 
							crit1 = 1 + (damage_up_base + damage_up_per * (100 - v:GetHealthPercent())) * damage_up_factor
						end						
						local DamageTable = {
							ability = keys.ability,
							victim = v, 
							attacker = caster, 
							damage = damage * crit1 * crit2, 
							damage_type = keys.ability:GetAbilityDamageType(),  
							damage_flags = DOTA_DAMAGE_FLAG_NONE
						}
						UnitDamageTarget(DamageTable)							
						UnitStunTarget(caster,v,stun_time)
						unit:AddNoDraw()
						unit:ForceKill(false)								
						return nil
					end

					count = count + 1
					return 0.05
				end,
			0.1)			
		end	
	end

	KokoroSetMust(caster, 2)
end

function OnKokoro03SpellStart(keys)
	local caster = EntIndexToHScript(keys.caster_entindex)
	local range = keys.ability:GetCastRange()

	KokoroSetPvCrit(caster)

	-- local effect = "particles/econ/items/mars/mars_fall20_immortal_shield/mars_fall20_immortal_shield_bash.vpcf"
	local effect1 = "particles/econ/items/mars/mars_fall20_immortal_shield/mars_fall20_immortal_shield_bash_headmodel.vpcf"	
	local effect2 = "particles/units/heroes/hero_mars/mars_shield_bash_model.vpcf"		
	caster:EmitSound("Hero_Mars.Shield.Cast")	--"Hero_Mars.Shield.Cast.Small"	
	local casterPoint = caster:GetOrigin()
	local forward = caster:GetForwardVector()	

	local effectIndex = ParticleManager:CreateParticle(effect1, PATTACH_WORLDORIGIN, caster)
	ParticleManager:SetParticleControl(effectIndex, 0, casterPoint)	
	ParticleManager:SetParticleControlForward(effectIndex, 0, forward)
	ParticleManager:ReleaseParticleIndex(effectIndex)
	local effectIndex = ParticleManager:CreateParticle(effect2, PATTACH_WORLDORIGIN, caster)
	ParticleManager:SetParticleControl(effectIndex, 0, casterPoint)
	ParticleManager:SetParticleControl(effectIndex, 1, Vector(range, 0, 0))
	ParticleManager:SetParticleControlForward(effectIndex, 0, forward)
	ParticleManager:ReleaseParticleIndex(effectIndex)	

	local rotate_angle = QAngle(0,45,0)
	local rotate_forward = (RotatePosition(casterPoint + forward * 300, rotate_angle, casterPoint) - casterPoint):Normalized()
	local effectIndex = ParticleManager:CreateParticle(effect1, PATTACH_WORLDORIGIN, caster)
	ParticleManager:SetParticleControl(effectIndex, 0, casterPoint)	
	ParticleManager:SetParticleControlForward(effectIndex, 0, rotate_forward)
	ParticleManager:ReleaseParticleIndex(effectIndex)
	local effectIndex = ParticleManager:CreateParticle(effect2, PATTACH_WORLDORIGIN, caster)
	ParticleManager:SetParticleControl(effectIndex, 0, casterPoint)
	ParticleManager:SetParticleControl(effectIndex, 1, Vector(range, 0, 0))
	ParticleManager:SetParticleControlForward(effectIndex, 0, rotate_forward)
	ParticleManager:ReleaseParticleIndex(effectIndex)	

	local rotate_angle = QAngle(0,-45,0)
	local rotate_forward = (RotatePosition(casterPoint + forward * 300, rotate_angle, casterPoint) - casterPoint):Normalized()
	local effectIndex = ParticleManager:CreateParticle(effect1, PATTACH_WORLDORIGIN, caster)
	ParticleManager:SetParticleControl(effectIndex, 0, casterPoint)	
	ParticleManager:SetParticleControlForward(effectIndex, 0, rotate_forward)
	ParticleManager:ReleaseParticleIndex(effectIndex)
	local effectIndex = ParticleManager:CreateParticle(effect2, PATTACH_WORLDORIGIN, caster)
	ParticleManager:SetParticleControl(effectIndex, 0, casterPoint)
	ParticleManager:SetParticleControl(effectIndex, 1, Vector(range, 0, 0))
	ParticleManager:SetParticleControlForward(effectIndex, 0, rotate_forward)
	ParticleManager:ReleaseParticleIndex(effectIndex)	

	local crit1 = 1
	local hasBuff1 = false
	if caster:HasModifier("modifier_kokoro_04_buff_1") then 
		hasBuff1 = true
	end
	local damage_up_base = caster:GetAbilityValue("thtd_kokoro_04", "damage_up_base", true)
	local damage_up_per = caster:GetAbilityValue("thtd_kokoro_04", "damage_up_per", true)
	local damage_up_factor = 1	
	if caster:IsPower666() then 
		damage_up_factor = 4
	end
	local crit2 = KokoroGetPvCrit(caster)

	local targets = THTD_FindUnitsInRadius(caster, caster:GetAbsOrigin(), range)
	local damage = caster:THTD_GetAttack() * keys.crit_mult
	for k,v in pairs(targets) do 
		if hasBuff1 then 
			crit1 = 1 + (damage_up_base + damage_up_per * (100 - v:GetHealthPercent())) * damage_up_factor
		end	
		local DamageTable = {
			ability = keys.ability,
	        victim = v, 
	        attacker = caster, 
	        damage = damage * crit1 * crit2, 
	        damage_type = keys.ability:GetAbilityDamageType(), 
	        damage_flags = DOTA_DAMAGE_FLAG_NONE
   		}
		UnitDamageTarget(DamageTable)
	end

	KokoroSetMust(caster, 3)
end

function KokoroSetMust(caster, index)		
	local ability4 = caster:FindAbilityByName("thtd_kokoro_04")
	if ability4:GetLevel() > 0 then			
		caster:RemoveModifierByName("modifier_kokoro_04_buff_1")
		caster:RemoveModifierByName("modifier_kokoro_04_buff_2")
		caster:RemoveModifierByName("modifier_kokoro_04_buff_3")
		ability4:ApplyDataDrivenModifier(caster, caster, "modifier_kokoro_04_buff_"..index, nil)		
	end
end

function KokoroSetPvCrit(caster)	
	local powerDamageUp = 0
	local pv = caster:GetAbilityPowerValue("thtd_kokoro_04")
	if pv ~= nil then 	
		powerDamageUp = pv[1]	
	end
	caster.thtd_kokoro_pv_crit = 1 + powerDamageUp * 66/100
end

function KokoroGetPvCrit(caster)
	return caster.thtd_kokoro_pv_crit or 1
end

function OnCreatedKokoro04Buff2(keys)	
	local target = keys.target	

	local bonus = keys.bonus	
	if target:IsPower666() then 
		bonus = bonus * 4
	end	
	target:THTD_AddPowerPercentage(bonus, "thtd_kokoro_04_buff2_bonus")
	target:THTD_AddAttackPercentage(bonus, "thtd_kokoro_04_buff2_bonus")
end

function OnDestroyKokoro04Buff2(keys)		
	local target = keys.target
	target:THTD_AddPowerPercentage("thtd_kokoro_04_buff2_bonus")
	target:THTD_AddAttackPercentage("thtd_kokoro_04_buff2_bonus")	
end

function OnCreatedKokoro04Buff3(keys)
	local target = keys.target	
	
	local bonus = keys.crit_damage	
	if target:IsPower666() then 
		bonus = bonus * 4
	end
	target:THTD_AddCritDamage(bonus, "thtd_kokoro_04_bonus")
end

function OnDestroyKokoro04Buff3(keys)
	keys.target:THTD_AddCritDamage("thtd_kokoro_04_bonus")	
end

function OnKokoro04Think(keys)	
	if keys.ability:GetLevel() < 1 then return end	
	
	local caster = keys.caster		
	
	local bonus = 0
	if caster:IsPower999() then 	
		bonus = 999
	end
	local targets = THTD_FindUnitsInRadius(caster, caster:GetAbsOrigin(), keys.ability:GetCastRange())
	for k,v in pairs(targets) do 
		local hp = v:GetHealthPercent()		
		if hp > 70 then 
			bonus = bonus + hp - 70
		end
		if caster:IsPower999() then 	
			bonus = bonus + (100 - hp) * 1
		end
	end
	
	if caster.thtd_kokoro_04_power_bonus == bonus then return end

	if caster.thtd_kokoro_04_power_bonus ~= nil then 
		caster:THTD_AddBasePower(-caster.thtd_kokoro_04_power_bonus)
		caster:THTD_AddBaseAttack(-caster.thtd_kokoro_04_power_bonus)
	end
	caster:THTD_AddBasePower(bonus)
	caster:THTD_AddBaseAttack(bonus)
	caster.thtd_kokoro_04_power_bonus = bonus	
end