-- 是否魔界
function IsMakaiCard(unit)
	local unitName = unit:GetUnitName()
	if unitName == "shinki" or unitName == "alice" or unitName == "koakuma" or unitName == "mima" then 
		return true
	else
		return false
	end
end

function OnShinki01Think(keys)	
	local caster = keys.caster	
	local targets = THTD_FindFriendlyUnitsInRadius(caster,caster:GetOrigin(),1200)
	for k,v in pairs(targets) do		
		if IsMakaiCard(v) then 
			local modifier = v:FindModifierByName(keys.modifier)
			if modifier ~= nil then 
				modifier:SetDuration(0.3, false)
			else
				if v.thtd_shinki_01_kill_count == nil then 
					v.thtd_shinki_01_kill_count = 0
				end
				modifier = keys.ability:ApplyDataDrivenModifier(caster, v, keys.modifier, {duration = 0.3})				
				if modifier ~= nil and v.thtd_shinki_01_kill_count > 0 then 
					modifier:SetStackCount(v.thtd_shinki_01_kill_count)
				end
			end
		end
	end
end

function OnCreatedShinki01Buff(keys)
	keys.target:THTD_AddBasePower(keys.kill_bonus * keys.target.thtd_shinki_01_kill_count, "thtd_shinki_01_kill")	
end

function OnDestroyShinki01Buff(keys)
	keys.target:THTD_AddBasePower("thtd_shinki_01_kill")
end

function OnSpellStartShinki02(keys)
	local caster = EntIndexToHScript(keys.caster_entindex)	
	local castPoint = caster:GetOrigin()
	-- local effect = "particles/econ/items/queen_of_pain/qop_arcana/qop_arcana_sonic_wave.vpcf"
	local effect = "particles/econ/items/queen_of_pain/qop_arcana/qop_arcana_sonic_wave_v2.vpcf"
	local range = keys.ability:GetCastRange()
	for i=1,6 do
		local forward = Vector(math.cos(i*math.pi/3),math.sin(i*math.pi/3),0)
		local effectIndex = ParticleManager:CreateParticle(effect, PATTACH_CUSTOMORIGIN, caster)
		ParticleManager:SetParticleControl(effectIndex, 0, castPoint)
		ParticleManager:SetParticleControl(effectIndex, 1, forward * (range/2))
		ParticleManager:ReleaseParticleIndex(effectIndex)			
		-- local info = 
		-- {
		-- 	Ability = keys.ability,
		-- 	EffectName = effect,
		-- 	vSpawnOrigin = castPoint,
		-- 	fDistance = range,
		-- 	fStartRadius = 100,
		-- 	fEndRadius = 500,
		-- 	Source = caster,
		-- 	iSourceAttachment = "mouth",
		-- 	bHasFrontalCone = false,
		-- 	bReplaceExisting = false,
		-- 	iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
		-- 	iUnitTargetFlags = DOTA_UNIT_TARGET_FLAG_NONE,
		-- 	iUnitTargetType = DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
		-- 	fExpireTime = GameRules:GetGameTime() + 10.0,
		-- 	bDeleteOnHit = false,
		-- 	vVelocity = forward * 1400,
		-- 	bProvidesVision = false,
		-- 	ExtraData = {}
		-- }
		-- ProjectileManager:CreateLinearProjectile(info)
	end

	local tick = math.floor(keys.tick * 100 + 0.5)/100
	local time = math.floor(keys.duration_time * 100 + 0.5)/100
	
	caster:SetContextThink(DoUniqueString("dota_timer"), 
		function() 
			if GameRules:IsGamePaused() then return 0.1 end
			time = time - tick
			if time < 0 then 
				return nil 
			end 

			local targets = THTD_FindUnitsInRadius(caster,castPoint,range)
			local damage = caster:THTD_GetAbilityPowerDamage(keys.ability)
			local type = keys.ability:GetAbilityDamageType()
			for k,v in pairs(targets) do
				local DamageTable = {
					ability = keys.ability,
					victim = v, 
					attacker = caster, 
					damage = damage, 
					damage_type = type, 
					damage_flags = DOTA_DAMAGE_FLAG_NONE
				}
				UnitDamageTarget(DamageTable)
			end

			return tick
		end, 
	tick)
end

function OnSpellStartShinki03(keys)
	local caster = EntIndexToHScript(keys.caster_entindex)
	if caster:HasModifier(keys.modifier) then 
		caster:RemoveModifierByName(keys.modifier)
	end
	local modifier = keys.ability:ApplyDataDrivenModifier(caster, caster, keys.modifier, nil)

	local pfx_caster = ParticleManager:CreateParticle("particles/units/heroes/heroes_underlord/abbysal_underlord_darkrift_ambient.vpcf", PATTACH_ABSORIGIN_FOLLOW, caster)
	ParticleManager:SetParticleControlEnt(pfx_caster, 2, caster, PATTACH_ABSORIGIN_FOLLOW, nil, caster:GetAbsOrigin(), true)
	ParticleManager:SetParticleControl(pfx_caster, 1, Vector(0, 0, 0))
	modifier:AddParticle(pfx_caster, false, false, 15, false, false)

	-- caster:EmitSound("Hero_Nevermore.ROS.Arcana.Cast")
	caster:EmitSound("Hero_Terrorblade.Metamorphosis")
	local effectIndex = ParticleManager:CreateParticle("particles/econ/items/terrorblade/terrorblade_back_ti8/terrorblade_sunder_ti8.vpcf", PATTACH_ROOTBONE_FOLLOW, caster)
	-- ParticleManager:SetParticleControlEnt(effectIndex, 0, caster, PATTACH_ROOTBONE_FOLLOW, "follow_rootbone", caster:GetAbsOrigin(), true)
	-- ParticleManager:SetParticleControlEnt(effectIndex, 1, caster, PATTACH_ROOTBONE_FOLLOW, "follow_rootbone", caster:GetAbsOrigin(), true)
	ParticleManager:SetParticleControlEnt(effectIndex, 0, caster, PATTACH_ROOTBONE_FOLLOW, "follow_origin", caster:GetAbsOrigin(), true)
	ParticleManager:SetParticleControlEnt(effectIndex, 1, caster, PATTACH_ROOTBONE_FOLLOW, "follow_origin", caster:GetAbsOrigin(), true)
	ParticleManager:DestroyParticleSystem(effectIndex,false)	
end

function OnCreatedShinki03Buff(keys)	
	local target = keys.target	
	target:SetModelScale(target:GetModelScale() * 2)	
	target:THTD_AddBasePower(keys.power_bonus, "thtd_shinki_03_bonus")
	target:THTD_DestroyLevelEffect()
end

function OnDestroyShinki03Buff(keys)		
	local target = keys.target
	target:SetModelScale(target:GetModelScale() / 2)
	target:THTD_AddBasePower("thtd_shinki_03_bonus")
	target:THTD_CreateLevelEffect()
end


local baseModel = 1.0

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

	local entities = Entities:FindAllByClassname("npc_dota_creature")						
	for k,v in pairs(entities) do
		local findNum = string.find(v:GetUnitName(), 'shinki_dragon')
		if findNum ~= nil and v~=nil and v:IsNull()==false and v:IsAlive() then
			local c = v.thtd_spawn_unit_owner
			if c:GetOwner() == caster:GetOwner() then 	
				CustomGameEventManager:Send_ServerToPlayer(caster:GetPlayerOwner(), "display_custom_error", {msg="shinki_dragon_casted"})
				keys.ability:EndCooldown()
				return 
			end			
		end		
	end

	if caster.ability_shinki04_devour_count == nil then
		caster.ability_shinki04_devour_count = 0
	end
	
	local unit = CreateUnitByName(
		"shinki_dragon"
		,caster:GetOrigin() + caster:GetForwardVector() * 500
		,false
		,caster:GetOwner()
		,caster:GetOwner()
		,caster:GetTeam()
	)	
	if unit == nil then 
		keys.ability:EndCooldown()
		return 
	end
	FindClearSpaceForUnit(unit, unit:GetOrigin(), false)

	unit:SetModelScale(baseModel * (1 + caster.ability_shinki04_devour_count * 0.02))
		
	unit:SetControllableByPlayer(caster:GetPlayerOwnerID(), false) 	
	unit:SetHasInventory(false)
	unit.thtd_spawn_unit_owner = caster	

	local powerStack = math.max(0, math.min(3, caster:GetTowerPowerLevel()))	
	local hero = caster:GetOwner()
	if GameRules.player_bb_buff[hero.thtd_player_id]["item_3016"] > 0 or powerStack > 0 then 		
		unit:AddNewModifier(unit, nil, "modifier_bb_buff_3016_effect", nil):SetStackCount(GameRules.player_bb_buff[hero.thtd_player_id]["item_3016"] + powerStack)
	end

	local ability = unit:GetAbilityByIndex(0)
	if ability ~= nil then 
		ability:SetActivated(true)
		ability:SetLevel(1)		
	end
	ability = unit:GetAbilityByIndex(1)
	if ability ~= nil then 
		ability:SetActivated(true)
		ability:SetLevel(1)
	end
	ability = unit:GetAbilityByIndex(2)
	if ability ~= nil then 
		ability:SetActivated(true)
		ability:SetLevel(1)
	end

	ability = unit:FindAbilityByName("shinki_dragon_01")
	if ability ~= nil then 
		if caster.ability_shinki04_devour_count > 0 then	
			ability:ApplyDataDrivenModifier(unit, unit, "modifier_shinki_dragon_01_buff", nil)
			unit:SetModifierStackCount("modifier_shinki_dragon_01_buff", unit, caster.ability_shinki04_devour_count)
		end	
		local modifier = caster:FindModifierByName("modifier_shinki_dragon_01_cooldown")
		if modifier ~= nil then			
			ability:StartCooldown(modifier:GetDuration())
		end
	end		

	keys.ability:ApplyDataDrivenModifier(caster, unit, "modifier_shinki_04_buff", nil)	

	local oldSwpanUnit = caster.thtd_summon_unit
	if oldSwpanUnit ~=nil and oldSwpanUnit:IsNull() == false then 
		oldSwpanUnit:AddNoDraw()
		oldSwpanUnit:ForceKill(false)
	end
	caster.thtd_summon_unit = unit

	local factor = unit:GetAbilityValue("shinki_dragon_01", "damage_up", true)
	local attackValue = math.floor(caster:THTD_GetStarDamage() * (1 + caster.ability_shinki04_devour_count * factor))
	unit:SetBaseDamageMax(attackValue)
	unit:SetBaseDamageMin(attackValue)		
	
	unit:SetContextThink(DoUniqueString("modifier_shinki_04"), 
		function()
			if GameRules:IsGamePaused() then return 0.03 end
			if caster==nil or caster:IsNull() or caster:IsAlive()==false or caster:THTD_IsHidden() then
				unit:AddNoDraw()
				unit:ForceKill(false)
				caster.thtd_summon_unit = nil
				return nil
			end
			
			attackValue = math.floor(caster:THTD_GetStarDamage() * (1 + caster.ability_shinki04_devour_count * factor))
			unit:SetBaseDamageMax(attackValue)
			unit:SetBaseDamageMin(attackValue)

			unit:InheritOwnerBuff(caster)

			if GetDistanceBetweenTwoVec2D(caster:GetOrigin(), unit:GetOrigin()) > 1000 then
				local forward = (unit:GetAbsOrigin() - caster:GetAbsOrigin()):Normalized() 
				unit:MoveToPosition(caster:GetOrigin() + forward*1000)
			end

			enemy = unit:GetAttackTarget()	

			ability = unit:FindAbilityByName("shinki_dragon_01")		
			if unit:IsReadyToCastAbility(ability) and enemy ~= nil and enemy.thtd_damage_lock ~= true then	
				if enemy~=nil and enemy:IsNull()==false and enemy:IsAlive() then 									
					unit:CastAbilityOnTarget(enemy, ability, caster:GetPlayerOwnerID())					
				end
			end
			
			ability = unit:FindAbilityByName("shinki_dragon_03")
			if unit:IsReadyToCastAbility(ability) then
				if enemy~=nil and enemy:IsNull()==false and enemy:IsAlive() then 									
					unit:CastAbilityNoTarget(ability, caster:GetPlayerOwnerID())
				end
			end

			return math.floor(100/unit:GetAttacksPerSecond()) / 100
		end,
	0)	
end


function OnShinkiDragon01SpellStart(keys)	
	local caster = EntIndexToHScript(keys.caster_entindex)
	local target = keys.target
	local owner = caster.thtd_spawn_unit_owner
	if owner==nil or owner:IsNull() or owner:IsAlive()==false or owner:THTD_IsHidden() then return end
	if target.thtd_damage_lock == true then return end	

	local cooldown = math.floor(target:GetHealth() / caster:GetAverageTrueAttackDamage(caster))
	cooldown = math.min(600, math.max(15, cooldown))
	keys.ability:ApplyDataDrivenModifier(owner, owner, "modifier_shinki_dragon_01_cooldown", {Duration = cooldown})
	keys.ability:StartCooldown(cooldown)
		
	caster:NpcKill(target)

	local max_count = keys.max_count
	if owner:IsPower999() then max_count = 999 end

	if owner.ability_shinki04_devour_count < max_count then 
		local skipedCount = 0
		if SpawnSystem.ReachToWave ~= nil then 
			if owner.skiped_wave == nil then
				owner.skiped_wave = SpawnSystem.ReachToWave + 50 - SpawnSystem.CurWave - 1
			end
		elseif owner.skiped_wave ~= nil then 
			skipedCount = owner.skiped_wave * 2
			owner.skiped_wave = nil
		end
		local addCount = math.min(max_count - owner.ability_shinki04_devour_count, 1 + skipedCount)

		owner.ability_shinki04_devour_count = owner.ability_shinki04_devour_count + addCount	
		caster:SetModelScale(baseModel * (1 + math.min(3, owner.ability_shinki04_devour_count * 0.02)))
		if not caster:HasModifier("modifier_shinki_dragon_01_buff") then 
			keys.ability:ApplyDataDrivenModifier(caster, caster, "modifier_shinki_dragon_01_buff", nil)
		end	
		caster:SetModifierStackCount("modifier_shinki_dragon_01_buff", caster, owner.ability_shinki04_devour_count)
	elseif owner.ability_shinki04_devour_count > max_count then 
		owner.ability_shinki04_devour_count = max_count
		caster:SetModelScale(baseModel * (1 + math.min(3, owner.ability_shinki04_devour_count * 0.02)))
		caster:SetModifierStackCount("modifier_shinki_dragon_01_buff", caster, owner.ability_shinki04_devour_count)
	end	
end


function OnShinki02AttackLanded(keys)
	local caster = EntIndexToHScript(keys.caster_entindex)
	local owner = caster.thtd_spawn_unit_owner
	if owner==nil or owner:IsNull() or owner:IsAlive()==false or owner:THTD_IsHidden() then return end
	local target = keys.target	

	if RollPercentage(keys.chance) then 
		local enemies = THTD_FindUnitsInRadius(owner, target:GetOrigin(), keys.range)
		local damage = caster:GetAverageTrueAttackDamage(caster)
		local isEnabledStun = false
		if caster.stun_locked ~= true then 
			isEnabledStun = true
			caster.stun_locked = true
			caster:SetContextThink(DoUniqueString("modifier_shinki_04"), 
				function()
					caster.stun_locked = false
					return nil
				end,
			1.0)
		end
		if #enemies > 0 then
			for k,v in pairs(enemies) do
				if isEnabledStun then 
					keys.ability:ApplyDataDrivenModifier(caster, v, "modifier_bash_stun_datadriven", {Duration = keys.stun_time})
				end
				local DamageTable = {
					ability = keys.ability,
					victim = v, 
					attacker = caster, 
					damage = damage, 
					damage_type = keys.ability:GetAbilityDamageType(),  
					damage_flags = DOTA_DAMAGE_FLAG_NONE
				}
				if v == target then
					DamageTable.damage = DamageTable.damage * keys.damage_crit 
				else
					DamageTable.damage = DamageTable.damage * keys.aoe_crit 
				end
				UnitDamageTarget(DamageTable)
			end			
		end	
		caster:EmitSound("Hero_Slardar.Bash")	
	end
end


function OnShinkiDragon03SpellStart(keys)	
	local caster = EntIndexToHScript(keys.caster_entindex)
	local owner = caster.thtd_spawn_unit_owner
	if owner==nil or owner:IsNull() or owner:IsAlive()==false or owner:THTD_IsHidden() then return end
	
	local crit = 1
	if owner:IsPower666() then 
		crit = 4 
		keys.ability:EndCooldown()
		keys.ability:StartCooldown(1.0)
	end

	local enemies = THTD_FindUnitsInRadius(owner, caster:GetOrigin(), keys.RangeRadius)
	local damage = caster:GetAverageTrueAttackDamage(caster) * keys.DamageTimes * crit
	local debuff = "modifier_earthshock_debuff_datadriven"
	if #enemies > 0 then
		for k,v in pairs(enemies) do
			keys.ability:ApplyDataDrivenModifier(caster, v, debuff, {})
			local DamageTable = {
				ability = keys.ability,
				victim = v, 
				attacker = caster, 
				damage = damage, 
				damage_type = keys.ability:GetAbilityDamageType(),  
				damage_flags = DOTA_DAMAGE_FLAG_NONE
			}
			UnitDamageTarget(DamageTable)
		end			
	end	
end