function disable_entity(entity_id)

	if IsPlayer(entity_id) == true then
		-- disable player controls
		-- not using 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, "dress") then
				ComponentSetValue2(comp, "visible", false)
			end
		end

		for _, player_child_entity in ipairs(EntityGetAllChildren(entity_id)) do
			if EntityGetName(player_child_entity) == "arm_r" then
				ComponentSetValue2(EntityGetFirstComponent(player_child_entity, "SpriteComponent"), "visible", false)
			elseif EntityGetName(player_child_entity) == "cape" then
				ComponentSetValue2(EntityGetFirstComponent(player_child_entity, "InheritTransformComponent"), "Transform", 0, -500, 1, 1, 0)
			elseif EntityGetName(player_child_entity) == "inventory_quick" then
				if EntityGetAllChildren(player_child_entity) ~= nil then
					for _, inv_entity in ipairs(EntityGetAllChildren(player_child_entity)) do
						ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(inv_entity, "SpriteComponent"), "visible", false)
					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 smoothly, compared to switching "move_camera_with_aim" which snaps instantly
		EntitySetComponentIsEnabled(entity_id, EntityGetFirstComponent(entity_id, "PlatformShooterPlayerComponent"), false)
	else
		-- disable enemy controls
		EntitySetComponentIsEnabled(entity_id, EntityGetFirstComponent(entity_id, "ControlsComponent"), false)

		-- make enemy invisible
		-- not enabling all sprites for player like this because it would enable cursor sprite
		local sprite_comps = EntityGetComponent(entity_id, "SpriteComponent")
		for i, comp in ipairs(sprite_comps) do
			ComponentSetValue2(comp, "visible", false)
		end

		-- this is for enemy to fuck off after sex instead of standing in place
		ComponentSetValue2(EntityGetFirstComponent(entity_id, "AnimalAIComponent"), "preferred_job", "Escaping")
	end

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

	-- this is needed to keep entity at scene coordinates
	-- only_position to prevent entity sprite rotating along with scene entity
	EntityAddComponent2(entity_id, "InheritTransformComponent", {
		only_position=true
	})

	-- game repeats keys that were pressed when ControlsComponent is disabled until its enabled again
	-- to prevent this you need to manually set all pressed 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)

	-- move status icons above entity outside of screen
	-- thanks to invisible noita mod for reference
	local hitbox_original = EntityGetFirstComponent(entity_id, "HitboxComponent")
	EntityAddComponent2(entity_id, "HitboxComponent", {
		_tags="temp",
		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 this entity
	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_enable_polymorph.lua
	if entity_id == nil then
		entity_id = EntityGetWithTag("player_unit")[1]
	end

	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, "dress") then
				ComponentSetValue2(comp, "visible", true)
			end
		end

		for _, player_child_entity in ipairs(EntityGetAllChildren(entity_id)) do
			if EntityGetName(player_child_entity) == "arm_r" then
				ComponentSetValue2(EntityGetFirstComponent(player_child_entity, "SpriteComponent"), "visible", true)
			elseif EntityGetName(player_child_entity) == "cape" then
				ComponentSetValue2(EntityGetFirstComponent(player_child_entity, "InheritTransformComponent"), "Transform", 0, 0, 1, 1, 0)
			elseif EntityGetName(player_child_entity) == "inventory_quick" then
				if EntityGetAllChildren(player_child_entity) ~= nil then
					for _, inv_entity in ipairs(EntityGetAllChildren(player_child_entity)) do
						ComponentSetValue2(EntityGetFirstComponentIncludingDisabled(inv_entity, "SpriteComponent"), "visible", true)
					end
				end
			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 like for player controls 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 i, comp in ipairs(sprite_comps) do
			ComponentSetValue2(comp, "visible", true)
		end

		-- enemy aggression enabled with delay so it will not stand next to you and wait but wander off instead
		EntityAddComponent2(entity_id, "LuaComponent", {
			script_source_file="mods/lewd_noita/files/sex_logic/enemy_attack_enable.lua",
			execute_every_n_frame=600,
			remove_after_executed=true,
		})
	end

	-- timer for entity added earlier
	for i, ch in ipairs(EntityGetAllChildren(entity_id)) do
		if EntityGetName(ch) == "sex_cooldown" then
			EntityAddComponent2(ch, "LifetimeComponent", {
				lifetime=300
			})
		end
	end

	-- move status icons above player back on screen
	local hitbox_temp
	for i, comp in ipairs(EntityGetComponent(entity_id, "HitboxComponent")) do
		if ComponentHasTag(comp, "temp") 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