dofile_once("mods/lewd_noita/files/sex_logic/controls_toggle.lua")
dofile_once("mods/lewd_noita/files/sex_logic/scene_table.lua")

-- check global scene data table to avoid repeating all this every frame
-- table instead of individual variables to destroy all values at once
if sd == nil then
	sd = {}
end

local scene = GetUpdatedEntityID()

if sd[scene] == nil then
	sd[scene] = {}

	SetRandomSeed(GameGetFrameNum(), 0)

	sd[scene].scene_id = GetUpdatedEntityID()
	sd[scene].scene_name = EntityGetName(sd[scene].scene_id)

	-- chance for alternative scene to trigger
	if scene_table[sd[scene].scene_name .. "_alt"] ~= nil then
		if Random(0, 1) == 1 then
			sd[scene].scene_name = sd[scene].scene_name .. "_alt"
		end
	end

	local scene_children = EntityGetAllChildren(sd[scene].scene_id)

	for _, child in ipairs(scene_children) do
		if IsPlayer(child) == true or EntityGetName(child) == "$animal_kobold" then
			sd[scene].kobold_id = child
			disable_entity(sd[scene].kobold_id)
		elseif EntityHasTag(child, "enemy") == true then
			sd[scene].enemy_id = child
			disable_entity(sd[scene].enemy_id)

			-- store enemy name to show it in case enemy dies
			sd[scene].translated_enemy_name = GameTextGetTranslatedOrNot(EntityGetName(sd[scene].enemy_id))

			-- pregnancy effect is applied after enemy is already leaving you, we need to store this in case it manages to die before scene ends
			if scene_table[sd[scene].scene_name]["preg"] == true then
				sd[scene].enemy_id_filename = EntityGetFilename(sd[scene].enemy_id)
			end
		end
	end

	-- in case the scene falls down to unexplored area
	local fog_of_war_remover = EntityCreateNew("fow_remove")
	EntityAddComponent2(fog_of_war_remover, "InheritTransformComponent", {})
	EntityAddComponent2(fog_of_war_remover, "SpriteComponent", {
		image_file="data/particles/fog_of_war_hole_128.xml",
		fog_of_war_hole=true,
	})
	EntityAddChild(sd[scene].scene_id, fog_of_war_remover)

	EntityAddComponent2(sd[scene].scene_id, "AudioComponent", {
		file="data/audio/Desktop/animals.bank",
		event_root="animals/slime/damage",
	})

	EntityAddComponent2(sd[scene].scene_id, "AudioComponent", {
		file="mods/lewd_noita/files/audio/Desktop/lewd_noita.bank",
		event_root="plap",
	})

	EntityAddComponent2(sd[scene].scene_id, "AudioComponent", {
		file="mods/lewd_noita/files/audio/Desktop/lewd_noita.bank",
		event_root="cum",
	})

	EntityAddComponent2(sd[scene].scene_id, "AudioComponent", {
		file="mods/lewd_noita/files/audio/Desktop/lewd_noita.bank",
		event_root="moan",
	})

	-- scene should fall down if enemy can't fly or does not fly during sex
	if scene_table[sd[scene].scene_name]["fly"] == false then
		EntityAddComponent2(sd[scene].scene_id, "VelocityComponent", {})
		EntityAddComponent2(sd[scene].scene_id, "SimplePhysicsComponent", {})
	end

	-- prevent fungus exploding after scene already started
	-- fungus has two ParticleEmitterComponent, second is disabled until it starts exploding
	-- remove both to prevent situation when you remove wrong component and it creates explosion particles the entire animation
	if sd[scene].scene_name == "fungus" then
		EntitySetComponentIsEnabled(sd[scene].enemy_id, EntityGetFirstComponent(sd[scene].enemy_id, "CollisionTriggerComponent"), false)
		EntityRemoveComponent(sd[scene].enemy_id, EntityGetFirstComponentIncludingDisabled(sd[scene].enemy_id, "ParticleEmitterComponent"))
		EntityRemoveComponent(sd[scene].enemy_id, EntityGetFirstComponentIncludingDisabled(sd[scene].enemy_id, "ParticleEmitterComponent"))
	end

	sd[scene].total_stages = 1

	while ModTextFileGetContent("mods/lewd_noita/files/sex_gfx/" .. sd[scene].scene_name .. sd[scene].total_stages + 1 .. ".xml") ~= nil do
		sd[scene].total_stages = sd[scene].total_stages + 1
	end

	sd[scene].current_stage = 0
	sd[scene].current_loop = 0
	sd[scene].stage_start_frame = GameGetFrameNum()
	sd[scene].stage_xml_content = ModTextFileGetContent("mods/lewd_noita/files/sex_gfx/" .. sd[scene].scene_name .. sd[scene].current_stage + 1 .. ".xml")
	sd[scene].stage_frame_count = tonumber(sd[scene].stage_xml_content:match('frame_count%s*=%s*"(%-?%d+)"'))

	-- frame_wait is in seconds so you need to convert it to frames
	sd[scene].stage_frame_wait = tonumber(sd[scene].stage_xml_content:match('frame_wait%s*=%s*"(%-?%d*%.?%d+)"'))
	sd[scene].stage_loop_frames = math.floor(sd[scene].stage_frame_count * (60 * sd[scene].stage_frame_wait))

	-- nymphomania perk
	if GameHasFlagRun("PERK_PICKED_LN_NYMPHOMANIA") == true then
		local nymphomania_entity = EntityCreateNew("effect_nymphomania")
		EntityAddComponent2(nymphomania_entity, "InheritTransformComponent", {})
		EntityAddComponent2(nymphomania_entity, "GameEffectComponent", {
			effect="PROTECTION_ALL",
			frames=1800,
		})
		EntityAddComponent2(nymphomania_entity, "UIIconComponent", {
			icon_sprite_file="mods/lewd_noita/files/perks/nymphomania_icon.png",
			name="Invulnerability",
			description="Your love for sex protects you from damage.",
			is_perk=false,
		})
		EntityAddChild(sd[scene].kobold_id, nymphomania_entity)
	end
end

local scene_x, scene_y = EntityGetTransform(scene)

-- check kobold dead or polymorphed
if EntityGetIsAlive(sd[scene].kobold_id) == false then

	-- in case kobold is polymorphed we need to enable her after polymorph ends
	local poly_handler = EntityCreateNew("after_polymorph_enable")
	EntitySetTransform(poly_handler, scene_x, scene_y)
	EntityAddComponent2(poly_handler, "LuaComponent", {
		script_source_file="mods/lewd_noita/files/sex_logic/after_polymorph_enable.lua"
	})
	EntityAddComponent2(poly_handler, "LifetimeComponent", {
		lifetime=1800
	})

	-- if enemy was present and disabled we enable enemy
	if sd[scene].enemy_id ~= nil and sd[scene].current_stage ~= sd[scene].total_stages then
		if EntityGetIsAlive(sd[scene].enemy_id) == true then
			enable_entity(sd[scene].enemy_id)
		end

		if sd[scene].second_attacker ~= nil and EntityGetIsAlive(sd[scene].second_attacker) == true then
			enable_entity(sd[scene].second_attacker)
		end
	end

	EntityKill(sd[scene].scene_id)
	sd[scene] = nil
	return
end

-- check kobold ignited, not checking last stage when enemy already left/born. chance to not trigger immediately
-- enemies with ignition immunity will keep fucking
if ComponentGetValue2(EntityGetFirstComponent(sd[scene].kobold_id, "DamageModelComponent"), "is_on_fire") == true and sd[scene].current_stage ~= sd[scene].total_stages and Random(1, 50) == 1 then

	-- if enemy present and can ignite it will release us and scene ends
	if sd[scene].enemy_id ~= nil and ComponentGetValue2(EntityGetFirstComponent(sd[scene].enemy_id, "DamageModelComponent"), "fire_probability_of_ignition") > 0 then

		if EntityGetIsAlive(sd[scene].enemy_id) == true then
			enable_entity(sd[scene].enemy_id)
		end

		if sd[scene].second_attacker ~= nil and EntityGetIsAlive(sd[scene].second_attacker) == true then
			enable_entity(sd[scene].second_attacker)
		end

		if IsPlayer(sd[scene].kobold_id) == true then
			GamePrintImportant("you are on fire!", "Too hot for " .. sd[scene].translated_enemy_name .. " to continue", "mods/lewd_noita/files/sex_logic/ui_msg.png")
			GamePlaySound("data/audio/Desktop/event_cues.bank", "event_cues/rune/create", scene_x, scene_y)
		end

		enable_entity(sd[scene].kobold_id)
		EntityKill(sd[scene].scene_id)
		sd[scene] = nil
		return
	elseif sd[scene].enemy_id == nil then
		if IsPlayer(sd[scene].kobold_id) == true then
			if sd[scene].scene_name == "birth" then
				GamePrintImportant("you are on fire!", "Whatever was crawling out of you, it burned to death", "mods/lewd_noita/files/sex_logic/ui_msg.png")
			elseif sd[scene].scene_name == "wizard_futa_orb" then
				GamePrintImportant("you were stroking so hard you ignited!", "", "mods/lewd_noita/files/sex_logic/ui_msg.png")
			end

			GamePlaySound("data/audio/Desktop/event_cues.bank", "event_cues/rune/create", scene_x, scene_y)
		end

		enable_entity(sd[scene].kobold_id)
		EntityKill(sd[scene].scene_id)
		sd[scene] = nil
		return
	end
end

-- check kobold in water
if ComponentGetValue2(EntityGetFirstComponent(sd[scene].kobold_id, "DamageModelComponent"), "mAirAreWeInWater") == true then

	-- prevent drowning by keeping scene afloat
	ComponentSetValue2(EntityGetFirstComponent(sd[scene].scene_id, "VelocityComponent"), "mVelocity", Random(-10, 10), -20)

	-- chance for enemy to release. if no enemy scene will continue
	if sd[scene].enemy_id ~= nil and sd[scene].current_stage ~= sd[scene].total_stages and Random(1, 50) == 1 then
		if IsPlayer(sd[scene].kobold_id) == true then
			GamePrintImportant(sd[scene].translated_enemy_name .. " left", "Your frantic splashing killed the mood", "mods/lewd_noita/files/sex_logic/ui_msg.png")
			GamePlaySound("data/audio/Desktop/event_cues.bank", "event_cues/rune/create", scene_x, scene_y)
		end

		if EntityGetIsAlive(sd[scene].enemy_id) == true then
			enable_entity(sd[scene].enemy_id)
		end

		if sd[scene].second_attacker ~= nil and EntityGetIsAlive(sd[scene].second_attacker) == true then
			enable_entity(sd[scene].second_attacker)
		end

		enable_entity(sd[scene].kobold_id)
		EntityKill(sd[scene].scene_id)
		sd[scene] = nil
		return
	end
end

-- check enemy dead or ignited
if sd[scene].enemy_id ~= nil and sd[scene].current_stage ~= sd[scene].total_stages then
	if EntityGetIsAlive(sd[scene].enemy_id) == false or sd[scene].second_attacker ~= nil and EntityGetIsAlive(sd[scene].second_attacker) == false then

		-- in case enemy is polymorphed we need to enable it after polymorph ends
		local poly_handler = EntityCreateNew("after_polymorph_enable")
		EntitySetTransform(poly_handler, scene_x, scene_y)
		EntityAddComponent2(poly_handler, "LuaComponent", {
			script_source_file="mods/lewd_noita/files/sex_logic/after_polymorph_enable.lua"
		})
		EntityAddComponent2(poly_handler, "LifetimeComponent", {
			lifetime=1800
		})

		if IsPlayer(sd[scene].kobold_id) == true then
			GamePrintImportant(sd[scene].translated_enemy_name .. " is no more", "", "mods/lewd_noita/files/sex_logic/ui_msg.png")
			GamePlaySound("data/audio/Desktop/event_cues.bank", "event_cues/rune/create", scene_x, scene_y)
		end

		-- if we have two fuckers we need to enable remaining fucker so we check both
		if EntityGetIsAlive(sd[scene].enemy_id) == true then
			enable_entity(sd[scene].enemy_id)
		end

		if sd[scene].second_attacker ~= nil and EntityGetIsAlive(sd[scene].second_attacker) == true then
			enable_entity(sd[scene].second_attacker)
		end

		enable_entity(sd[scene].kobold_id)
		EntityKill(sd[scene].scene_id)
		sd[scene] = nil
		return
	end

	if ComponentGetValue2(EntityGetFirstComponent(sd[scene].enemy_id, "DamageModelComponent"), "is_on_fire") == true or
	sd[scene].second_attacker ~= nil and ComponentGetValue2(EntityGetFirstComponent(sd[scene].second_attacker, "DamageModelComponent"), "is_on_fire") == true and
	Random(1, 50) == 1 then
		if IsPlayer(sd[scene].kobold_id) == true then
			GamePrintImportant(sd[scene].translated_enemy_name .. " caught on fire!", "How fortunate", "mods/lewd_noita/files/sex_logic/ui_msg.png")
			GamePlaySound("data/audio/Desktop/event_cues.bank", "event_cues/rune/create", scene_x, scene_y)
		end

		if EntityGetIsAlive(sd[scene].enemy_id) == true then
			enable_entity(sd[scene].enemy_id)
		end

		if sd[scene].second_attacker ~= nil and EntityGetIsAlive(sd[scene].second_attacker) == true then
			enable_entity(sd[scene].second_attacker)
		end

		enable_entity(sd[scene].kobold_id)
		EntityKill(sd[scene].scene_id)
		sd[scene] = nil
		return
	end
end

-- exception for failed alchemist b
if sd[scene].scene_fixed == true then
	local x, y = EntityGetTransform(sd[scene].enemy_id)
	EntitySetTransform(sd[scene].scene_id, x, y, 0)
end

-- https://noita.wiki.gg/wiki/Modding:_Utilities#Rotate_entity_depending_on_topology_of_terrain
if EntityGetFirstComponent(sd[scene].scene_id, "VelocityComponent") ~= nil then
	local vel_x, vel_y = ComponentGetValue2(EntityGetFirstComponent(sd[scene].scene_id, "VelocityComponent"), "mVelocity")
	if vel_y == 0 then
		local found_normal, normal_x, normal_y, approximate_distance_from_surface = GetSurfaceNormal(scene_x, scene_y, 60, 16)

		if found_normal then
			EntitySetTransform(sd[scene].scene_id, scene_x, scene_y, math.rad(-90) + math.atan2(normal_y, normal_x))
		end
	end
end

-- this used to prevent falling sound if you are in the air when fucked by flying enemy
-- now it prevents you accumulating falling speed which is released all at once if flying enemy dies before scene end
-- with this fix you will start falling gracefully instead of fucking collapsing
-- https://noita.wiki.gg/wiki/Modding:_Utilities#Player_movement_checking
if EntityGetFirstComponent(sd[scene].scene_id, "VelocityComponent") == nil then
	local vel_x, vel_y = ComponentGetValue2(EntityGetFirstComponent(sd[scene].kobold_id, "CharacterDataComponent"), "mVelocity")
	if (vel_y > 0 and vel_y ~= 60) then
		ComponentSetValue2(EntityGetFirstComponent(sd[scene].kobold_id, "CharacterDataComponent"), "mVelocity", 0, 0)
	end
end

-- this runs every time animation loop repeats
-- for example if the loop takes 24 frames to play, this will run on frame 24, 48, 72 and so on
-- this ensures smooth transition to the next stage since it will only start after current animation is fully played
if (GameGetFrameNum() - sd[scene].stage_start_frame) % sd[scene].stage_loop_frames == 0 then
	sd[scene].current_loop = sd[scene].current_loop + 1
	if sd[scene].current_loop == 1 or sd[scene].current_loop > sd[scene].stage_loops then
		sd[scene].current_stage = sd[scene].current_stage + 1
		sd[scene].current_loop = 1
		sd[scene].stage_start_frame = GameGetFrameNum()

		if sd[scene].current_stage == 1 then
			sd[scene].stage_loops = 10 + Random(0, 10)
			sd[scene].stage_sound = "plap_medium"

			if sd[scene].scene_name ~= "birth" then
				GameEntityPlaySound(sd[scene].scene_id, "moan" .. Random(1, 9))
			end
		elseif sd[scene].total_stages - sd[scene].current_stage > 1 then
			sd[scene].stage_loops = 10 + Random(0, 10)
			sd[scene].stage_sound = "plap_hard"
		elseif sd[scene].total_stages - sd[scene].current_stage == 1 then
			sd[scene].stage_loops = 6 + Random(0, 5)
			sd[scene].stage_sound = "cum"
			GameEntityPlaySound(sd[scene].scene_id, "moan" .. Random(1, 9))
			sd[scene].cum_stage = true
			sd[scene].cum_type = scene_table[sd[scene].scene_name]["cum"]
			sd[scene].cum_amount = Random(400, 500)

			if sd[scene].cum_type == "ln_cum" and GameHasFlagRun("PERK_PICKED_LN_CONNOISSEUR") then
				if Random(1, 5) == 1 then
					sd[scene].cum_type = "ln_cum_potent"
					sd[scene].cum_amount = sd[scene].cum_amount * 3
				end
			end

			-- exception for failed alchemist b
			if sd[scene].scene_name == "failed_alchemist_b" then
				EntityRemoveFromParent(sd[scene].enemy_id)
				EntitySetComponentIsEnabled(sd[scene].enemy_id, EntityGetFirstComponentIncludingDisabled(sd[scene].enemy_id, "ControlsComponent"), true)
				EntityRemoveComponent(sd[scene].scene_id, EntityGetFirstComponent(sd[scene].scene_id, "VelocityComponent"))
				EntityRemoveComponent(sd[scene].scene_id, EntityGetFirstComponent(sd[scene].scene_id, "SimplePhysicsComponent"))
				sd[scene].scene_fixed = true
			end
		elseif sd[scene].current_stage == sd[scene].total_stages then
			sd[scene].stage_loops = 3 + Random(0, 3)
			sd[scene].stage_sound = ""

			-- exception for failed alchemist b
			sd[scene].scene_fixed = false

			-- if kobold was fucked by flying enemy, she will fall down on last stage when it releases her
			if EntityGetFirstComponent(sd[scene].scene_id, "VelocityComponent") == nil then
				EntityAddComponent2(sd[scene].scene_id, "VelocityComponent", {})
				EntityAddComponent2(sd[scene].scene_id, "SimplePhysicsComponent", {})
			end

			if sd[scene].enemy_id ~= nil then
				enable_entity(sd[scene].enemy_id)

				if sd[scene].second_attacker ~= nil then
					enable_entity(sd[scene].second_attacker)
				end

				-- chance to be glued by cum
				if Random(1, 5) == 1 then
					EntityLoad("data/entities/projectiles/glue.xml", scene_x, scene_y)
				end

				-- continue fungus explosion we prevented when scene started
				if sd[scene].scene_name == "fungus" then
					ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(sd[scene].enemy_id, "CollisionTriggerComponent"), "mTimer", Random(300, 600))
					EntitySetComponentIsEnabled(sd[scene].enemy_id, EntityGetFirstComponentIncludingDisabled(sd[scene].enemy_id, "CollisionTriggerComponent"), true)
					GameEntityPlaySound(sd[scene].enemy_id, "death_buildup")
					EntityAddComponent2(sd[scene].enemy_id, "ParticleEmitterComponent", {
						emitted_material_name="plasma_fading_pink",
						x_pos_offset_min=-4,
						y_pos_offset_min=-4,
						x_pos_offset_max=4,
						y_pos_offset_max=4,
						x_vel_min=-60,
						x_vel_max=60,
						y_vel_min=-120,
						y_vel_max=-40,
						count_min=9,
						count_max=15,
						lifetime_min=0.6,
						lifetime_max=3.8,
						create_real_particles=false,
						emit_cosmetic_particles=true,
						emission_interval_min_frames=1,
						emission_interval_max_frames=2,
						airflow_force=6,
						airflow_scale=1.0,
					})
				end

				-- restore hellhound back to normal
				if sd[scene].scene_name == "hellhound" or sd[scene].scene_name == "hellhound_alt" then
					ComponentSetValue2(EntityGetFirstComponent(sd[scene].enemy_id, "GenomeDataComponent"), "herd_id", StringToHerdId("player"))
					GetGameEffectLoadTo(sd[scene].enemy_id, "CHARM", false)
					ComponentSetValue2(EntityGetFirstComponent(sd[scene].enemy_id, "AnimalAIComponent"), "attack_melee_damage_min", 1)
					ComponentSetValue2(EntityGetFirstComponent(sd[scene].enemy_id, "AnimalAIComponent"), "attack_melee_damage_max", 2)
					GamePrintImportant("hellhound is satisfied", "For now...", "mods/lewd_noita/files/sex_logic/ui_msg.png")
					GamePlaySound("data/audio/Desktop/event_cues.bank", "event_cues/rune/create", scene_x, scene_y)
				end

				if GameHasFlagRun("PERK_PICKED_LN_CHARMER") == true then
					GetGameEffectLoadTo(sd[scene].enemy_id, "CHARM", false)
					local cloud = EntityCreateNew()
					EntitySetTransform(cloud, scene_x, scene_y)
					EntityAddComponent2(cloud, "ParticleEmitterComponent", {
						emitted_material_name="ln_gas_horny_short",
						create_real_particles=true,
						image_animation_file="data/particles/image_emitters/circle_256.png",
						image_animation_speed=4,
						emission_interval_min_frames=1,
						emission_interval_max_frames=1,
						image_animation_loop=false,
						set_magic_creation=true,
					})
					EntityAddComponent2(cloud, "LifetimeComponent", {
						lifetime=30
					})
					EntityAddComponent2(cloud, "AudioComponent", {
						file="data/audio/Desktop/projectiles.bank",
						event_root="player_projectiles/circle_of",
					})
				end

				if GameHasFlagRun("PERK_PICKED_LN_SUCCUBUS") then
					if sd[scene].scene_name == "hellhound" or sd[scene].scene_name == "hellhound_alt" then
						GamePrintImportant("hellhounds are immune to succubus magic!", "", "mods/lewd_noita/files/sex_logic/ui_msg.png")
						GamePlaySound("data/audio/Desktop/event_cues.bank", "event_cues/rune/create", scene_x, scene_y)
					else
						local damage_model_comp = EntityGetFirstComponent(sd[scene].kobold_id, "DamageModelComponent")
						local max_hp = tonumber(ComponentGetValue2(damage_model_comp, "max_hp"))
						local max_hp_old = max_hp
						local hp_increase = sd[scene].cum_amount / 100 / 5
						max_hp = max_hp + hp_increase

						ComponentSetValue2(damage_model_comp, "max_hp", max_hp)
						ComponentSetValue2(damage_model_comp, "max_hp_old", max_hp_old)
						ComponentSetValue2(damage_model_comp, "mLastMaxHpChangeFrame", GameGetFrameNum())

						EntityAddComponent2(sd[scene].enemy_id, "LuaComponent", {
							script_source_file="mods/lewd_noita/files/perks/succubus.lua",
							execute_every_n_frame=Random(180, 240),
							remove_after_executed=true,
						})

						GamePrintImportant("lifeforce is drained", "Maximum health is increased by " .. math.floor(hp_increase * 25), "mods/lewd_noita/files/sex_logic/ui_msg.png")
						GamePlaySound("data/audio/Desktop/event_cues.bank", "event_cues/rune/create", scene_x, scene_y)
					end

				end

				if GameHasFlagRun("PERK_PICKED_LN_WHORE") == true then
					if sd[scene].scene_name == "hellhound" or sd[scene].scene_name == "hellhound_alt" then
						GamePrintImportant("no gold for you","Your trusty hellhound companion isn't affected by your foul magic!", "mods/lewd_noita/files/sex_logic/ui_msg.png")
						GamePlaySound("data/audio/Desktop/event_cues.bank", "event_cues/rune/create", scene_x, scene_y)
					else
						EntityAddComponent2(sd[scene].enemy_id, "LuaComponent", {
							script_source_file="mods/lewd_noita/files/perks/whore.lua",
							execute_every_n_frame=Random(180, 240),
							remove_after_executed=true,
						})
					end
				end

				if sd[scene].scene_name == "miniblob" then
					EntityLoad("data/entities/animals/miniblob.xml", scene_x, scene_y)
					EntityLoad("data/entities/animals/miniblob.xml", scene_x, scene_y)
					EntityLoad("data/entities/animals/miniblob.xml", scene_x, scene_y)
					EntityLoad("data/entities/animals/miniblob.xml", scene_x, scene_y)
					GameEntityPlaySound(sd[scene].scene_id, "explosion")
					EntityLoad("data/entities/particles/particle_explosion/explosion_glue.xml", scene_x, scene_y)
				end
			elseif sd[scene].scene_name == "birth" then
				local entity_to_create = ComponentGetValue2(EntityGetFirstComponent(sd[scene].scene_id, "VariableStorageComponent"), "value_string")

				if entity_to_create == "mods/lewd_noita/files/enemies/hellhound.xml" then
					EntityLoad("mods/lewd_noita/files/enemies/hellhound_egg.xml", scene_x, scene_y)
					GameEntityPlaySound(sd[scene].scene_id, "explosion")
					EntityLoad("data/entities/particles/particle_explosion/explosion_glue.xml", scene_x, scene_y)
				else
					local child_enemy = EntityLoad(entity_to_create, scene_x, scene_y)

					GetGameEffectLoadTo(child_enemy, "CHARM", false)

					GameEntityPlaySound(sd[scene].scene_id, "explosion")
					EntityLoad("data/entities/particles/particle_explosion/explosion_glue.xml", scene_x, scene_y)
				end
			elseif sd[scene].scene_name == "worm_tiny_head" then
				EntityLoad("data/entities/animals/worm_tiny.xml", scene_x, scene_y + 5)
				EntityAddComponent2(sd[scene].scene_id, "WormAttractorComponent", {
					direction=-1,
					radius=500,
				})
			end

			-- set to nil to prevent cum creation on last stage when kobold is no longer fucked
			sd[scene].cum_stage = nil
		elseif sd[scene].current_stage > sd[scene].total_stages then
			if sd[scene].scene_name == "lurker" then
				EntityLoad("data/entities/animals/lurker.xml", scene_x + 10, scene_y)
				EntityLoad("data/entities/animals/lurker.xml", scene_x - 10, scene_y)
			elseif sd[scene].scene_name == "tentacle_vase_blue" then
				EntityLoad("mods/lewd_noita/files/enemies/tentacle_vase_blue_cum.xml", scene_x, scene_y - 20)
			elseif sd[scene].scene_name == "tentacle_vase_pink" then
				EntityLoad("mods/lewd_noita/files/enemies/tentacle_vase_pink_cum.xml", scene_x, scene_y - 20)
			end

			if sd[scene].scene_name ~= "wizard_futa_orb" and sd[scene].scene_name ~= "birth" then

				-- leaking cum effect
				if sd[scene].cum_type ~= nil then

					local leak_cum_entity = nil

					if EntityGetAllChildren(sd[scene].kobold_id) ~= nil then
						for i, ch in ipairs(EntityGetAllChildren(sd[scene].kobold_id)) do
							if EntityGetName(ch) == "effect_leak_cum" then
								leak_cum_entity = ch
							end
						end
					end

					if leak_cum_entity == nil then
						local leak_cum_entity = EntityCreateNew("effect_leak_cum")
						EntityAddComponent2(leak_cum_entity, "InheritTransformComponent", {})
						EntityAddComponent2(leak_cum_entity, "GameEffectComponent", {
							effect="CUSTOM",
							custom_effect_id="EFFECT_LEAK_CUM",
						})
						EntityAddComponent2(leak_cum_entity, "UIIconComponent", {
							icon_sprite_file="mods/lewd_noita/files/status_effects/leak_cum.png",
							name="Leaking cum",
							description="You're leaking cum.",
						})
						EntityAddComponent2(leak_cum_entity, "VariableStorageComponent", {
							name=sd[scene].cum_type,
							value_int=sd[scene].cum_amount,
						})
						EntityAddComponent2(leak_cum_entity, "LuaComponent", {
							script_source_file="mods/lewd_noita/files/status_effects/leak_cum.lua"
						})
						EntityAddChild(sd[scene].kobold_id, leak_cum_entity)
					else
						local var_comps = EntityGetComponent(leak_cum_entity, "VariableStorageComponent")
						local comp_exists = false

						for i, comp in ipairs(var_comps) do
							if ComponentGetValue2(comp, "name") == sd[scene].cum_type then
								ComponentSetValue2(comp, "value_int", ComponentGetValue2(comp, "value_int") + sd[scene].cum_amount)
								comp_exists = true
							end
						end

						if comp_exists == false then
							EntityAddComponent2(leak_cum_entity, "VariableStorageComponent", {
								name=sd[scene].cum_type,
								value_int=sd[scene].cum_amount,
							})
						end
					end
				end

				-- pregnancy effect
				local pregnancy_entity = nil

				for i, ch in ipairs(EntityGetAllChildren(sd[scene].kobold_id)) do
					if EntityGetName(ch) == "effect_pregnancy" then
						pregnancy_entity = ch
					end
				end

				if scene_table[sd[scene].scene_name]["preg"] == true and pregnancy_entity == nil then
					if Random(0, 1) == 1 then

						if sd[scene].scene_name == "worm_tiny_head" then
							sd[scene].enemy_id_filename = "data/entities/items/pickup/egg_worm.xml"
						end

						local pregnancy_entity = EntityCreateNew("effect_pregnancy")
						EntityAddComponent2(pregnancy_entity, "InheritTransformComponent", {})
						EntityAddComponent2(pregnancy_entity, "GameEffectComponent", {
							effect="CUSTOM",
							custom_effect_id="EFFECT_PREGNANCY",
						})
						EntityAddComponent2(pregnancy_entity, "UIIconComponent", {
							icon_sprite_file="mods/lewd_noita/files/status_effects/pregnant.png",
							name="Pregnant",
							description="You are about to give birth to something.",
						})
						EntityAddComponent2(pregnancy_entity, "VariableStorageComponent", {
							name=sd[scene].enemy_id_filename,
							value_string=tostring(GameGetFrameNum()),
						})
						EntityAddComponent2(pregnancy_entity, "LuaComponent", {
							script_source_file="mods/lewd_noita/files/sex_logic/start_birth.lua"
						})
						EntityAddChild(sd[scene].kobold_id, pregnancy_entity)
					end
				end

				if scene_table[sd[scene].scene_name]["effect"] ~= nil then
					local sex_effect_entity = EntityLoad("mods/lewd_noita/files/status_effects/" .. scene_table[sd[scene].scene_name]["effect"] .. ".xml")
					ComponentSetValue2(EntityGetFirstComponent(sex_effect_entity, "GameEffectComponent"), "frames", Random(5, 10) * 60)
					EntityAddChild(sd[scene].kobold_id, sex_effect_entity)
				end

				-- sex fury perk
				if GameHasFlagRun("PERK_PICKED_LN_SEXFURY") == true then
					local sexfury_entity = EntityCreateNew("effect_sexfury")
					EntityAddComponent2(sexfury_entity, "InheritTransformComponent", {})
					EntityAddComponent2(sexfury_entity, "GameEffectComponent", {
						effect="BERSERK",
						frames=3600,
					})
					EntityAddComponent2(sexfury_entity, "GameEffectComponent", {
						effect="MOVEMENT_FASTER_2X",
						frames=3600,
					})
					EntityAddComponent2(sexfury_entity, "GameEffectComponent", {
						effect="FASTER_LEVITATION",
						frames=3600,
					})
					EntityAddComponent2(sexfury_entity, "GameEffectComponent", {
						effect="MANA_REGENERATION",
						frames=3600,
					})
					EntityAddComponent2(sexfury_entity, "GameEffectComponent", {
						effect="KNOCKBACK_IMMUNITY",
						frames=3600,
					})
					EntityAddComponent2(sexfury_entity, "GameEffectComponent", {
						effect="STUN_PROTECTION_FREEZE",
						frames=3600,
					})
					EntityAddComponent2(sexfury_entity, "GameEffectComponent", {
						effect="STUN_PROTECTION_ELECTRICITY",
						frames=3600,
					})
					EntityAddComponent2(sexfury_entity, "UIIconComponent", {
						icon_sprite_file="mods/lewd_noita/files/perks/sexfury_icon.png",
						name="Butthurt",
						description="You are about to kick some ass.",
						is_perk=false,
					})
					EntityAddChild(sd[scene].kobold_id, sexfury_entity)
				end

			end

			enable_entity(sd[scene].kobold_id)
			EntityKill(sd[scene].scene_id)
			sd[scene] = nil
			return
		end

		-- changing image_file in SpriteComponent doesn't change it instantly for some reason and it ruins the entire animation
		-- removing SpriteComponent and creating it again with new sprite solves the problem
		local sprite_comp = EntityGetFirstComponent(sd[scene].scene_id, "SpriteComponent")

		if sprite_comp ~= nil then
			EntityRemoveComponent(sd[scene].scene_id, sprite_comp)
		end

		EntityAddComponent2(sd[scene].scene_id, "SpriteComponent", {
			z_index=-2,
			image_file="mods/lewd_noita/files/sex_gfx/" .. sd[scene].scene_name .. sd[scene].current_stage .. ".xml",
		})

		sd[scene].stage_xml_content = ModTextFileGetContent("mods/lewd_noita/files/sex_gfx/" .. sd[scene].scene_name .. sd[scene].current_stage .. ".xml")
		sd[scene].stage_frame_count = tonumber(sd[scene].stage_xml_content:match('frame_count%s*=%s*"(%-?%d+)"'))
		sd[scene].stage_frame_wait = tonumber(sd[scene].stage_xml_content:match('frame_wait%s*=%s*"(%-?%d*%.?%d+)"'))
		sd[scene].stage_loop_frames = math.floor(sd[scene].stage_frame_count * (60 * sd[scene].stage_frame_wait))

		if tonumber(sd[scene].stage_xml_content:match('loop%s*=%s*"(%-?%d+)"')) == 0 then
			sd[scene].stage_loops = 1
		end
	end

	-- double hook
	if sd[scene].current_stage ~= sd[scene].total_stages then
		-- string.sub check in case we have "_alt" scene name
		if scene_table[sd[scene].scene_name .. "_double"] ~= nil or scene_table[string.sub(sd[scene].scene_name, 1, -5) .. "_double"] ~= nil then
			local close_enemies = EntityGetInRadiusWithTag(scene_x, scene_y, 10, "enemy")

			if #close_enemies > 1 then

				-- get scene name without "_alt"
				local name_minus_alt = sd[scene].scene_name

				if string.find(sd[scene].scene_name, "_alt") ~= nil then
					name_minus_alt = string.sub(sd[scene].scene_name, 1, -5)
				end

				-- EntityGetParent check to exclude currently fucking enemy
				for _, enemy in ipairs(close_enemies) do
					local enemy_name = string.match(ComponentGetValue2(EntityGetFirstComponent(enemy, "SpriteComponent"), "image_file"), "([^/]+)%.(.+)$")

					if enemy_name == name_minus_alt and EntityGetParent(enemy) == 0 then
						sd[scene].second_attacker = enemy

						-- if current scene has "_alt" but no "_alt_double" for that scene exists, remove "_alt" to get default "_double" instead
						if ModTextFileGetContent("mods/lewd_noita/files/sex_gfx/" .. sd[scene].scene_name .. "_double" .. sd[scene].current_stage + 1 .. ".xml") == nil then
							sd[scene].scene_name = string.sub(sd[scene].scene_name, 1, -5)
						end

						sd[scene].scene_name = sd[scene].scene_name .. "_double"
						sd[scene].total_stages = 1

						while ModTextFileGetContent("mods/lewd_noita/files/sex_gfx/" .. sd[scene].scene_name .. sd[scene].total_stages + 1 .. ".xml") ~= nil do
							sd[scene].total_stages = sd[scene].total_stages + 1
						end

						sd[scene].current_stage = 0
						sd[scene].current_loop = 0
						EntityRemoveComponent(sd[scene].scene_id, EntityGetFirstComponent(sd[scene].scene_id, "SpriteComponent"))
						EntityAddComponent2(sd[scene].scene_id, "SpriteComponent", {
							z_index=-2,
							image_file="mods/lewd_noita/files/sex_gfx/" .. sd[scene].scene_name .. sd[scene].current_stage + 1 .. ".xml",
						})

						sd[scene].stage_xml_content = ModTextFileGetContent("mods/lewd_noita/files/sex_gfx/" .. sd[scene].scene_name .. sd[scene].current_stage + 1 .. ".xml")
						sd[scene].stage_frame_count = tonumber(sd[scene].stage_xml_content:match('frame_count%s*=%s*"(%-?%d+)"'))
						sd[scene].stage_frame_wait = tonumber(sd[scene].stage_xml_content:match('frame_wait%s*=%s*"(%-?%d*%.?%d+)"'))
						sd[scene].stage_loop_frames = math.floor(sd[scene].stage_frame_count * (60 * sd[scene].stage_frame_wait))

						EntityAddChild(sd[scene].scene_id, sd[scene].second_attacker)
						disable_entity(sd[scene].second_attacker)

						if IsPlayer(sd[scene].kobold_id) == true then
							GamePrintImportant("oh fuck!", "Another " .. sd[scene].translated_enemy_name .. " joined the party!", "mods/lewd_noita/files/sex_logic/ui_msg.png")
							GamePlaySound("data/audio/Desktop/event_cues.bank", "event_cues/rune/create", scene_x, scene_y)
						end

						break
					end
				end
			end
		end
	end

	if sd[scene].cum_stage == true and sd[scene].cum_type ~= nil then
		GameCreateParticle(sd[scene].cum_type, scene_x, scene_y, sd[scene].cum_amount / 20, 5, -10, false, false, true)
	end
-- play plap/cum sound in the middle of animation instead of very first frame
elseif (GameGetFrameNum() - (sd[scene].stage_start_frame + math.floor(sd[scene].stage_loop_frames / 2))) % sd[scene].stage_loop_frames == 0 then
	GameEntityPlaySound(sd[scene].scene_id, sd[scene].stage_sound .. Random(1, 9))
end