function disable_entity(entity_id)

	if IsPlayer(entity_id) == true then
		-- disable player controls
		-- not doing EntitySetComponentIsEnabled because it crashes the game if entity is player
		ComponentSetValue2(EntityGetFirstComponent(entity_id, "ControlsComponent"), "enabled", false)

		-- make player main sprite and dress invisible
		ComponentSetValue2(EntityGetFirstComponent(entity_id, "SpriteComponent"), "visible", false)

		for _, comp in ipairs(EntityGetComponent(entity_id, "SpriteComponent")) do
			if ComponentHasTag(comp, "ln_dress") then
				ComponentSetValue2(comp, "visible", false)
			end
		end

		-- make player child entities invisible
		for _, ch in ipairs(EntityGetAllChildren(entity_id)) do
			if EntityGetName(ch) == "arm_r" then
				ComponentSetValue2(EntityGetFirstComponent(ch, "SpriteComponent"), "visible", false)
			elseif EntityGetName(ch) == "cape" then
				ComponentSetValue2(EntityGetFirstComponent(ch, "InheritTransformComponent"), "Transform", 0, -500, 1, 1, 0)
			elseif EntityGetName(ch) == "inventory_quick" and EntityGetAllChildren(ch) ~= nil then
				for _, inv_ch in ipairs(EntityGetAllChildren(ch)) do
					ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(inv_ch, "SpriteComponent"), "visible", false)

					-- disable wand particle effect if it has spells with it (tentacle/firebolt/electric spells etc)
					if EntityHasTag(inv_ch, "wand") and EntityGetAllChildren(inv_ch) ~= nil then
						for _, card in ipairs(EntityGetAllChildren(inv_ch)) do
							if EntityGetFirstComponent(card, "ParticleEmitterComponent") ~= nil then
								EntitySetComponentIsEnabled(card, EntityGetFirstComponent(card, "ParticleEmitterComponent"), false)
							end
							if EntityGetFirstComponent(card, "SpriteParticleEmitterComponent") ~= nil then
								EntitySetComponentIsEnabled(card, EntityGetFirstComponent(card, "SpriteParticleEmitterComponent"), false)
							end
						end
					end
				end
			end
		end

		-- disable showing "press to pick" text if item is nearby
		EntitySetComponentIsEnabled(entity_id, EntityGetFirstComponent(entity_id, "ItemPickUpperComponent"), false)

		-- close inventory
		ComponentSetValue2(EntityGetFirstComponent(entity_id, "InventoryGuiComponent"), "mActive", false)

		-- center camera on player
		-- toggling "move_camera_with_aim" snaps camera instantly, disabling component instead does it smoothly
		EntitySetComponentIsEnabled(entity_id, EntityGetFirstComponent(entity_id, "PlatformShooterPlayerComponent"), false)
	else
		-- disable enemy controls
		EntitySetComponentIsEnabled(entity_id, EntityGetFirstComponent(entity_id, "ControlsComponent"), false)

		-- make enemy invisible
		local sprite_comps = EntityGetComponent(entity_id, "SpriteComponent")
		for _, comp in ipairs(sprite_comps) do
			ComponentSetValue2(comp, "visible", false)
		end

		-- enemy should fuck off after sex instead of standing next to you. not sure if this is working
		ComponentSetValue2(EntityGetFirstComponent(entity_id, "AnimalAIComponent"), "preferred_job", "Escaping")
	end

	-- add cooldown to prevent triggering another scene while current scene plays
	local sex_cooldown = EntityCreateNew("ln_sex_cooldown")
	EntityAddComponent2(sex_cooldown, "InheritTransformComponent", {})
	EntityAddChild(entity_id, sex_cooldown)

	-- keep entity at scene coordinates
	-- only_position to prevent rotating entity when scene rotates
	EntityAddComponent2(entity_id, "InheritTransformComponent", {
		only_position=true
	})

	-- game repeats keys that were pressed when ControlsComponent is disabled until its enabled again
	-- to prevent stuff like wand shooting, flying up and losing levitation etc you need to manually set all buttons to false
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownFire", false)
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownFire2", false)
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownThrow", false)
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownInteract", false)
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownLeft", false)
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownRight", false)
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownUp", false)
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownDown", false)
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownFly", false)
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownChangeItemR", false)
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownChangeItemL", false)
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownInventory", false)
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownKick", false)
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownLeftClick", false)
	ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "mButtonDownRightClick", false)

	-- stain icons are attached to first HitboxComponent so we create identical temporary component and move original far away
	-- thanks to invisible noita mod for reference
	local hitbox_original = EntityGetFirstComponent(entity_id, "HitboxComponent")
	EntityAddComponent2(entity_id, "HitboxComponent", {
		_tags="ln_temp_hitbox",
		is_player=ComponentGetValue2(hitbox_original, "is_player"),
		is_enemy=ComponentGetValue2(hitbox_original, "is_enemy"),
		is_item=ComponentGetValue2(hitbox_original, "is_item"),
		aabb_min_x=ComponentGetValue2(hitbox_original, "aabb_min_x"),
		aabb_max_x=ComponentGetValue2(hitbox_original, "aabb_max_x"),
		aabb_min_y=ComponentGetValue2(hitbox_original, "aabb_min_y"),
		aabb_max_y=ComponentGetValue2(hitbox_original, "aabb_max_y"),
		damage_multiplier=ComponentGetValue2(hitbox_original, "damage_multiplier"),
	})
	ComponentSetValue2(hitbox_original, "is_player", false)
	ComponentSetValue2(hitbox_original, "is_enemy", false)
	ComponentSetValue2(hitbox_original, "is_item", false)
	ComponentSetValue2(hitbox_original, "aabb_min_x", 0)
	ComponentSetValue2(hitbox_original, "aabb_max_x", 0)
	ComponentSetValue2(hitbox_original, "aabb_min_y", -9999)
	ComponentSetValue2(hitbox_original, "aabb_max_y", -9999)
	ComponentSetValue2(hitbox_original, "damage_multiplier", 0)
	ComponentSetValue2(hitbox_original, "offset", 0, 9999)

	-- disable enemies attacking entity while scene plays. enemies will still gather around if entity is player
	ComponentSetValue2(EntityGetFirstComponent(entity_id, "GenomeDataComponent"), "food_chain_rank", 0)
	ComponentSetValue2(EntityGetFirstComponent(entity_id, "GenomeDataComponent"), "is_predator", false)
end

function enable_entity(entity_id)

	-- in case this is called from controls_after_polymorph.lua
	entity_id = entity_id or EntityGetWithTag("player_unit")[1]

	EntityRemoveFromParent(entity_id)
	EntityRemoveComponent(entity_id, EntityGetFirstComponent(entity_id, "InheritTransformComponent"))

	if IsPlayer(entity_id) == true then

		-- enable player controls
		ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), "enabled", true)

		-- enable picking up items
		EntitySetComponentIsEnabled(entity_id, EntityGetFirstComponentIncludingDisabled(entity_id, "ItemPickUpperComponent"), true)

		-- after enabling PlatformShooterPlayerComponent camera briefly snaps to coordinates it had when you disabled it
		-- to prevent this you need to set those coordinates to player coordinates before enabling it
		local shooter_comp = EntityGetFirstComponentIncludingDisabled(entity_id, "PlatformShooterPlayerComponent")
		local player_x, player_y = EntityGetTransform(entity_id)
		ComponentSetValue2(shooter_comp, "mSmoothedCameraPosition", player_x, player_y)
		ComponentSetValue2(shooter_comp, "mDesiredCameraPos", player_x, player_y)
		ComponentSetValue2(shooter_comp, "mSmoothedAimingVector", 0, 0)
		EntitySetComponentIsEnabled(entity_id, shooter_comp, true)

		-- make player main sprite and dress visible
		ComponentSetValue2(EntityGetFirstComponent(entity_id, "SpriteComponent"), "visible", true)

		for _, comp in ipairs(EntityGetComponent(entity_id, "SpriteComponent")) do
			if ComponentHasTag(comp, "ln_dress") then
				ComponentSetValue2(comp, "visible", true)
			end
		end

		-- make player child entities visible
		for _, ch in ipairs(EntityGetAllChildren(entity_id)) do
			if EntityGetName(ch) == "arm_r" then
				ComponentSetValue2(EntityGetFirstComponent(ch, "SpriteComponent"), "visible", true)
			elseif EntityGetName(ch) == "cape" then
				ComponentSetValue2(EntityGetFirstComponent(ch, "InheritTransformComponent"), "Transform", 0, 0, 1, 1, 0)
			elseif EntityGetName(ch) == "inventory_quick" and EntityGetAllChildren(ch) ~= nil then
				for _, inv_ch in ipairs(EntityGetAllChildren(ch)) do
					ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(inv_ch, "SpriteComponent"), "visible", true)

					-- enable wand particle effect if it has spells with it (tentacle/firebolt/electric spells etc)
					-- SpriteComponent check to prevent enabling particles for not currently held wands, those have it disabled
					if EntityHasTag(inv_ch, "wand") and EntityGetAllChildren(inv_ch) ~= nil and EntityGetFirstComponent(inv_ch, "SpriteComponent") ~= nil then
						for _, card in ipairs(EntityGetAllChildren(inv_ch)) do
							if EntityGetFirstComponentIncludingDisabled(card, "ParticleEmitterComponent") ~= nil then
								EntitySetComponentIsEnabled(card, EntityGetFirstComponentIncludingDisabled(card, "ParticleEmitterComponent"), true)
							end
							if EntityGetFirstComponentIncludingDisabled(card, "SpriteParticleEmitterComponent") ~= nil then
								EntitySetComponentIsEnabled(card, EntityGetFirstComponentIncludingDisabled(card, "SpriteParticleEmitterComponent"), true)
							end
						end
					end
				end
			elseif EntityGetName(ch) == "ln_perk_effect_nymphomania" then
				EntityKill(ch)
			end
		end

		-- enable enemies attacking player
		ComponentSetValue2(EntityGetFirstComponent(entity_id, "GenomeDataComponent"), "food_chain_rank", 20)
		ComponentSetValue2(EntityGetFirstComponent(entity_id, "GenomeDataComponent"), "is_predator", true)
	else

		-- enable enemy controls
		-- not changing value of ControlsComponent like we do for player because otherwise player will control the enemy
		EntitySetComponentIsEnabled(entity_id, EntityGetFirstComponentIncludingDisabled(entity_id, "ControlsComponent"), true)

		-- make enemy visible
		local sprite_comps = EntityGetComponent(entity_id, "SpriteComponent")
		for _, comp in ipairs(sprite_comps) do
			ComponentSetValue2(comp, "visible", true)
		end

		-- enemy aggression enabled with delay so it will not attack you immediately after sex but fuck off instead
		-- enable sooner for kobold to make sure another scene is not triggered and its not enabled mid scene
		local delay_frames = 600

		if EntityGetName(entity_id) == "$animal_kobold" then
			delay_frames = 60
		end

		EntityAddComponent2(entity_id, "LuaComponent", {
			script_source_file="mods/lewd_noita/files/sex_logic/enemy_attack_enable.lua",
			execute_every_n_frame=delay_frames,
			remove_after_executed=true,
		})
	end

	-- timer for cooldown entity added when scene started
	for _, ch in ipairs(EntityGetAllChildren(entity_id)) do
		if EntityGetName(ch) == "ln_sex_cooldown" then
			EntityAddComponent2(ch, "LifetimeComponent", {
				lifetime=300
			})
		end
	end

	-- restore original HitboxComponent to move stain icons above entity back on screen and delete temporary component
	local hitbox_temp
	for _, comp in ipairs(EntityGetComponent(entity_id, "HitboxComponent")) do
		if ComponentHasTag(comp, "ln_temp_hitbox") then
			hitbox_temp = comp
		end
	end
	local hitbox_original = EntityGetFirstComponent(entity_id, "HitboxComponent")
	ComponentSetValue2(hitbox_original, "is_player", ComponentGetValue2(hitbox_temp, "is_player"))
	ComponentSetValue2(hitbox_original, "is_enemy", ComponentGetValue2(hitbox_temp, "is_enemy"))
	ComponentSetValue2(hitbox_original, "is_item", ComponentGetValue2(hitbox_temp, "is_item"))
	ComponentSetValue2(hitbox_original, "aabb_min_x", ComponentGetValue2(hitbox_temp, "aabb_min_x"))
	ComponentSetValue2(hitbox_original, "aabb_max_x", ComponentGetValue2(hitbox_temp, "aabb_max_x"))
	ComponentSetValue2(hitbox_original, "aabb_min_y", ComponentGetValue2(hitbox_temp, "aabb_min_y"))
	ComponentSetValue2(hitbox_original, "aabb_max_y", ComponentGetValue2(hitbox_temp, "aabb_max_y"))
	ComponentSetValue2(hitbox_original, "damage_multiplier", ComponentGetValue2(hitbox_temp, "damage_multiplier"))
	ComponentSetValue2(hitbox_original, "offset", 0, 0)
	EntityRemoveComponent(entity_id, hitbox_temp)
end